diff --git a/.github/update.log b/.github/update.log index 5d20007300..26ebf48c2e 100644 --- a/.github/update.log +++ b/.github/update.log @@ -737,3 +737,4 @@ Update On Wed Aug 14 20:33:18 CEST 2024 Update On Thu Aug 15 20:37:38 CEST 2024 Update On Fri Aug 16 20:32:54 CEST 2024 Update On Sat Aug 17 20:30:44 CEST 2024 +Update On Sun Aug 18 20:30:02 CEST 2024 diff --git a/clash-nyanpasu/frontend/ui/hooks/use-breakpoint.ts b/clash-nyanpasu/frontend/ui/hooks/use-breakpoint.ts index ee36bfc7b7..5b0777baa7 100644 --- a/clash-nyanpasu/frontend/ui/hooks/use-breakpoint.ts +++ b/clash-nyanpasu/frontend/ui/hooks/use-breakpoint.ts @@ -1,77 +1,62 @@ -import { useSetState, useThrottleFn } from "ahooks"; -import { useCallback, useEffect, useMemo } from "react"; -import { useTheme } from "@mui/material"; +import { useAsyncEffect } from "ahooks"; +import { useEffect, useState } from "react"; +import { createBreakpoint } from "react-use"; +import { MUI_BREAKPOINTS } from "@/materialYou"; import { appWindow } from "@tauri-apps/api/window"; -export const useBreakpoint = ( - columnMapping: { [key: string]: number } = { - sm: 1, - md: 1, - lg: 2, - xl: 3, - default: 4, - }, -) => { - const { breakpoints } = useTheme(); +export type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl"; - const [breakpoint, setBreakpoint] = useSetState({ - key: "sm", - column: 1, - }); +const breakpointsOrder: Breakpoint[] = ["xs", "sm", "md", "lg", "xl"]; - const breakpointsValues = useMemo(() => { - return Object.entries(breakpoints.values); - }, [breakpoints.values]); +export const useBreakpoint = createBreakpoint( + MUI_BREAKPOINTS.values, +) as () => Breakpoint; - const getBreakpoint = useCallback( - async (width: number) => { - const isMinimized = await appWindow.isMinimized(); +type BreakpointEffectCallback = (currentBreakpoint: Breakpoint) => void; - if (isMinimized) { - return; - } - - for (const [key, value] of breakpointsValues) { - if (value >= width) { - if (key !== breakpoint.key) { - setBreakpoint({ - key, - column: columnMapping[key], - }); - } - return; - } - } - - if (breakpoint.key !== "default") { - setBreakpoint({ - column: columnMapping["default"], - key: "default", - }); - } - }, - [breakpointsValues, columnMapping, breakpoint.key, setBreakpoint], - ); - - const { run: triggerBreakpoint } = useThrottleFn( - () => { - const width = document.body.clientWidth; - getBreakpoint(width); - }, - { - wait: 100, - }, - ); +export const useBreakpointEffect = (callback: BreakpointEffectCallback) => { + const currentBreakpoint = useBreakpoint(); useEffect(() => { - const observer = new ResizeObserver(triggerBreakpoint); - - observer.observe(document.body); - - return () => { - observer.disconnect(); - }; - }, [triggerBreakpoint]); - - return breakpoint; + callback(currentBreakpoint); + }, [currentBreakpoint, callback]); +}; + +type BreakpointValues = Partial>; + +export const useBreakpointValue = ( + values: BreakpointValues, + defaultValue?: T, +): T => { + const currentBreakpoint = useBreakpoint(); + + const calculateValue = (): T => { + const value = values[currentBreakpoint]; + + if (value !== undefined) { + return value as T; + } + + const currentIndex = breakpointsOrder.indexOf(currentBreakpoint); + + for (let i = currentIndex; i >= 0; i--) { + const fallbackValue = values[breakpointsOrder[i]]; + + if (fallbackValue !== undefined) { + return fallbackValue as T; + } + } + + return defaultValue ?? (values[breakpointsOrder[0]] as T); + }; + + const [result, setResult] = useState(calculateValue); + + useAsyncEffect(async () => { + if (!(await appWindow.isMinimized())) { + setResult(calculateValue); + } + }, [currentBreakpoint, values, defaultValue]); + + return result; }; diff --git a/clash-nyanpasu/frontend/ui/package.json b/clash-nyanpasu/frontend/ui/package.json index 7e048b498d..404bfbfb01 100644 --- a/clash-nyanpasu/frontend/ui/package.json +++ b/clash-nyanpasu/frontend/ui/package.json @@ -18,7 +18,8 @@ "framer-motion": "12.0.0-alpha.0", "react": "18.3.1", "react-error-boundary": "4.0.13", - "react-i18next": "15.0.1" + "react-i18next": "15.0.1", + "react-use": "^17.5.1" }, "devDependencies": { "@emotion/react": "11.13.0", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 402da6354e..cd66fee25d 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -390,6 +390,9 @@ importers: react-i18next: specifier: 15.0.1 version: 15.0.1(i18next@23.12.3)(react-dom@19.0.0-rc-e948a5ac-20240807(react@19.0.0-rc-e948a5ac-20240807))(react@19.0.0-rc-e948a5ac-20240807) + react-use: + specifier: ^17.5.1 + version: 17.5.1(react@19.0.0-rc-e948a5ac-20240807) devDependencies: '@emotion/react': specifier: 11.13.0 @@ -1927,55 +1930,46 @@ packages: resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.17.2': resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.17.2': resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.17.2': resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.17.2': resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-s390x-gnu@4.17.2': resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.17.2': resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.17.2': resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.17.2': resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} @@ -2095,28 +2089,24 @@ packages: engines: {node: '>=10'} cpu: [arm64] os: [linux] - libc: [glibc] '@swc/core-linux-arm64-musl@1.6.1': resolution: {integrity: sha512-dr6YbLBg/SsNxs1hDqJhxdcrS8dGMlOXJwXIrUvACiA8jAd6S5BxYCaqsCefLYXtaOmu0bbx1FB/evfodqB70Q==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - libc: [musl] '@swc/core-linux-x64-gnu@1.6.1': resolution: {integrity: sha512-A0b/3V+yFy4LXh3O9umIE7LXPC7NBWdjl6AQYqymSMcMu0EOb1/iygA6s6uWhz9y3e172Hpb9b/CGsuD8Px/bg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - libc: [glibc] '@swc/core-linux-x64-musl@1.6.1': resolution: {integrity: sha512-5dJjlzZXhC87nZZZWbpiDP8kBIO0ibis893F/rtPIQBI5poH+iJuA32EU3wN4/WFHeK4et8z6SGSVghPtWyk4g==} engines: {node: '>=10'} cpu: [x64] os: [linux] - libc: [musl] '@swc/core-win32-arm64-msvc@1.6.1': resolution: {integrity: sha512-HBi1ZlwvfcUibLtT3g/lP57FaDPC799AD6InolB2KSgkqyBbZJ9wAXM8/CcH67GLIP0tZ7FqblrJTzGXxetTJQ==} @@ -2212,28 +2202,24 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [glibc] '@tauri-apps/cli-linux-arm64-musl@1.6.0': resolution: {integrity: sha512-4U628tuf2U8pMr4tIBJhEkrFwt+46dwhXrDlpdyWSZtnop5RJAVKHODm0KbWns4xGKfTW1F3r6sSv+2ZxLcISA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - libc: [musl] '@tauri-apps/cli-linux-x64-gnu@1.6.0': resolution: {integrity: sha512-AKRzp76fVUaJyXj5KRJT9bJyhwZyUnRQU0RqIRqOtZCT5yr6qGP8rjtQ7YhCIzWrseBlOllc3Qvbgw3Yl0VQcA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [glibc] '@tauri-apps/cli-linux-x64-musl@1.6.0': resolution: {integrity: sha512-0edIdq6aMBTaRMIXddHfyAFL361JqulLLd2Wi2aoOie7DkQ2MYh6gv3hA7NB9gqFwNIGE+xtJ4BkXIP2tSGPlg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - libc: [musl] '@tauri-apps/cli-win32-arm64-msvc@1.6.0': resolution: {integrity: sha512-QwWpWk4ubcwJ1rljsRAmINgB2AwkyzZhpYbalA+MmzyYMREcdXWGkyixWbRZgqc6fEWEBmq5UG73qz5eBJiIKg==} @@ -2411,6 +2397,9 @@ packages: '@types/http-cache-semantics@4.0.4': resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + '@types/js-cookie@2.2.7': + resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} + '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} @@ -2539,6 +2528,9 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 + '@xobotyi/scrollbar-width@1.9.5': + resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} + JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true @@ -3000,6 +2992,9 @@ packages: copy-anything@2.0.6: resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + cosmiconfig-typescript-loader@5.0.0: resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} engines: {node: '>=v16'} @@ -3057,6 +3052,13 @@ packages: resolution: {integrity: sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==} engines: {node: '>=12 || >=16'} + css-in-js-utils@3.1.0: + resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + css-tree@2.3.1: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -3448,6 +3450,9 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + es-abstract@1.23.3: resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} engines: {node: '>= 0.4'} @@ -3730,10 +3735,16 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-shallow-equal@1.0.0: + resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==} + fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} + fastest-stable-stringify@2.0.2: + resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -4057,6 +4068,9 @@ packages: engines: {node: '>=18'} hasBin: true + hyphenate-style-name@1.1.0: + resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} + i18next@23.12.3: resolution: {integrity: sha512-DyigQmrR10V9U2N6pjhbfahW13GY7n8BQD9swN09JuRRropgsksWVi4vRLeex0Qf7zCPnBfIqQfhcBzdZBQBYw==} @@ -4125,6 +4139,9 @@ packages: inline-style-parser@0.2.3: resolution: {integrity: sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==} + inline-style-prefixer@7.0.1: + resolution: {integrity: sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==} + internal-ip@6.2.0: resolution: {integrity: sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg==} engines: {node: '>=10'} @@ -4392,6 +4409,9 @@ packages: react: optional: true + js-cookie@2.2.1: + resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} + js-cookie@3.0.5: resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} engines: {node: '>=14'} @@ -4656,6 +4676,9 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} @@ -4833,6 +4856,12 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nano-css@5.6.2: + resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==} + peerDependencies: + react: npm:react@rc + react-dom: npm:react-dom@rc + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -5505,6 +5534,18 @@ packages: react: npm:react@rc react-dom: npm:react-dom@rc + react-universal-interface@0.6.2: + resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} + peerDependencies: + react: npm:react@rc + tslib: '*' + + react-use@17.5.1: + resolution: {integrity: sha512-LG/uPEVRflLWMwi3j/sZqR00nF6JGqTTDblkXK2nzXsIvij06hXl1V/MZIlwj1OKIQUtlh1l9jK8gLsRyCQxMg==} + peerDependencies: + react: npm:react@rc + react-dom: npm:react-dom@rc + react@19.0.0-rc-e948a5ac-20240807: resolution: {integrity: sha512-HQz6Ien3YXDqFFsZcoEagiXk43VOtyvEQAk2ZR/+99dnhRxlFT7e2n0g6qgeD2B/S7UZimiYS+HQS410xhvMxg==} engines: {node: '>=0.10.0'} @@ -5625,6 +5666,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rtl-css-js@1.16.1: + resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -5695,6 +5739,10 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} + set-harmonic-interval@1.0.1: + resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} + engines: {node: '>=6.9'} + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -5769,6 +5817,10 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map@0.5.6: + resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} + engines: {node: '>=0.10.0'} + source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} @@ -5794,6 +5846,18 @@ packages: sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + stack-generator@2.0.10: + resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} + + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + + stacktrace-gps@3.1.2: + resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} + + stacktrace-js@2.0.2: + resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} + store2@2.14.3: resolution: {integrity: sha512-4QcZ+yx7nzEFiV4BMLnr/pRa5HYzNITX2ri0Zh6sT9EyQHbBHacC6YigllUPU9X3D0f/22QCgfokpKs52YRrUg==} @@ -5933,6 +5997,9 @@ packages: stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + stylis@4.3.2: + resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==} + stylus@0.62.0: resolution: {integrity: sha512-v3YCf31atbwJQIMtPNX8hcQ+okD4NQaTuKGUWfII8eaqn+3otrbttGL1zSMZAAtiPsBztQnujVBugg/cXFUpyg==} hasBin: true @@ -6033,6 +6100,10 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + throttle-debounce@3.0.1: + resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} + engines: {node: '>=10'} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -6048,6 +6119,9 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -6064,6 +6138,9 @@ packages: resolution: {integrity: sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A==} engines: {node: '>=14.0.0'} + ts-easing@0.2.0: + resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -8388,6 +8465,8 @@ snapshots: '@types/http-cache-semantics@4.0.4': {} + '@types/js-cookie@2.2.7': {} + '@types/json5@0.0.29': {} '@types/jsonfile@6.1.4': @@ -8550,6 +8629,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@xobotyi/scrollbar-width@1.9.5': {} + JSONStream@1.3.5: dependencies: jsonparse: 1.3.1 @@ -9042,6 +9123,10 @@ snapshots: dependencies: is-what: 3.14.1 + copy-to-clipboard@3.3.3: + dependencies: + toggle-selection: 1.0.6 + cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.15)(cosmiconfig@9.0.0(typescript@5.5.4))(typescript@5.5.4): dependencies: '@types/node': 20.14.15 @@ -9101,6 +9186,15 @@ snapshots: css-functions-list@3.2.2: {} + css-in-js-utils@3.1.0: + dependencies: + hyphenate-style-name: 1.1.0 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + css-tree@2.3.1: dependencies: mdn-data: 2.0.30 @@ -9499,6 +9593,10 @@ snapshots: dependencies: is-arrayish: 0.2.1 + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 @@ -9997,8 +10095,12 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-shallow-equal@1.0.0: {} + fastest-levenshtein@1.0.16: {} + fastest-stable-stringify@2.0.2: {} + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -10373,6 +10475,8 @@ snapshots: husky@9.1.4: {} + hyphenate-style-name@1.1.0: {} + i18next@23.12.3: dependencies: '@babel/runtime': 7.24.8 @@ -10422,6 +10526,10 @@ snapshots: inline-style-parser@0.2.3: {} + inline-style-prefixer@7.0.1: + dependencies: + css-in-js-utils: 3.1.0 + internal-ip@6.2.0: dependencies: default-gateway: 6.0.3 @@ -10646,6 +10754,8 @@ snapshots: '@types/react': types-react@19.0.0-rc.1 react: 19.0.0-rc-e948a5ac-20240807 + js-cookie@2.2.1: {} + js-cookie@3.0.5: {} js-tokens@4.0.0: {} @@ -10984,6 +11094,8 @@ snapshots: dependencies: '@types/mdast': 4.0.3 + mdn-data@2.0.14: {} + mdn-data@2.0.30: {} memorystream@0.3.1: {} @@ -11204,6 +11316,18 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 + nano-css@5.6.2(react@19.0.0-rc-e948a5ac-20240807): + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + css-tree: 1.1.3 + csstype: 3.1.3 + fastest-stable-stringify: 2.0.2 + inline-style-prefixer: 7.0.1 + react: 19.0.0-rc-e948a5ac-20240807 + rtl-css-js: 1.16.1 + stacktrace-js: 2.0.2 + stylis: 4.3.2 + nanoid@3.3.7: {} natural-compare@1.4.0: {} @@ -11812,6 +11936,29 @@ snapshots: react: 19.0.0-rc-e948a5ac-20240807 react-dom: 19.0.0-rc-e948a5ac-20240807(react@19.0.0-rc-e948a5ac-20240807) + react-universal-interface@0.6.2(react@19.0.0-rc-e948a5ac-20240807)(tslib@2.6.2): + dependencies: + react: 19.0.0-rc-e948a5ac-20240807 + tslib: 2.6.2 + + react-use@17.5.1(react@19.0.0-rc-e948a5ac-20240807): + dependencies: + '@types/js-cookie': 2.2.7 + '@xobotyi/scrollbar-width': 1.9.5 + copy-to-clipboard: 3.3.3 + fast-deep-equal: 3.1.3 + fast-shallow-equal: 1.0.0 + js-cookie: 2.2.1 + nano-css: 5.6.2(react@19.0.0-rc-e948a5ac-20240807) + react: 19.0.0-rc-e948a5ac-20240807 + react-universal-interface: 0.6.2(react@19.0.0-rc-e948a5ac-20240807)(tslib@2.6.2) + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + set-harmonic-interval: 1.0.1 + throttle-debounce: 3.0.1 + ts-easing: 0.2.0 + tslib: 2.6.2 + react@19.0.0-rc-e948a5ac-20240807: {} read-cache@1.0.0: @@ -11964,6 +12111,10 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.17.2 fsevents: 2.3.3 + rtl-css-js@1.16.1: + dependencies: + '@babel/runtime': 7.24.8 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -12035,6 +12186,8 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + set-harmonic-interval@1.0.1: {} + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -12105,6 +12258,8 @@ snapshots: source-map-js@1.2.0: {} + source-map@0.5.6: {} + source-map@0.5.7: {} source-map@0.6.1: {} @@ -12119,6 +12274,23 @@ snapshots: sprintf-js@1.1.3: {} + stack-generator@2.0.10: + dependencies: + stackframe: 1.3.4 + + stackframe@1.3.4: {} + + stacktrace-gps@3.1.2: + dependencies: + source-map: 0.5.6 + stackframe: 1.3.4 + + stacktrace-js@2.0.2: + dependencies: + error-stack-parser: 2.1.4 + stack-generator: 2.0.10 + stacktrace-gps: 3.1.2 + store2@2.14.3: {} string-argv@0.3.2: {} @@ -12311,6 +12483,8 @@ snapshots: stylis@4.2.0: {} + stylis@4.3.2: {} + stylus@0.62.0: dependencies: '@adobe/css-tools': 4.3.3 @@ -12488,6 +12662,8 @@ snapshots: dependencies: any-promise: 1.3.0 + throttle-debounce@3.0.1: {} + through@2.3.8: {} timed-out@4.0.1: {} @@ -12498,6 +12674,8 @@ snapshots: dependencies: is-number: 7.0.0 + toggle-selection@1.0.6: {} + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -12508,6 +12686,8 @@ snapshots: ts-custom-error@3.3.1: {} + ts-easing@0.2.0: {} + ts-interface-checker@0.1.13: {} tsconfck@3.0.3(typescript@5.5.4): diff --git a/filebrowser/frontend/package-lock.json b/filebrowser/frontend/package-lock.json index 84b5c1a781..bbdc993e05 100644 --- a/filebrowser/frontend/package-lock.json +++ b/filebrowser/frontend/package-lock.json @@ -3106,31 +3106,29 @@ } }, "node_modules/@volar/language-core": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.1.6.tgz", - "integrity": "sha512-pAlMCGX/HatBSiDFMdMyqUshkbwWbLxpN/RL7HCQDOo2gYBE+uS+nanosLc1qR6pTQ/U8q00xt8bdrrAFPSC0A==", + "version": "2.4.0-alpha.19", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.19.tgz", + "integrity": "sha512-8H6x3vC0/SbOqy1cU0s7/Hk9nNH61t8qOoghjX7XpguLagEyjF6zkMp6C5F/sBlpr0WpeByc1KDfyBHumB8ZfA==", "dev": true, "dependencies": { - "@volar/source-map": "2.1.6" + "@volar/source-map": "2.4.0-alpha.19" } }, "node_modules/@volar/source-map": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.1.6.tgz", - "integrity": "sha512-TeyH8pHHonRCHYI91J7fWUoxi0zWV8whZTVRlsWHSYfjm58Blalkf9LrZ+pj6OiverPTmrHRkBsG17ScQyWECw==", - "dev": true, - "dependencies": { - "muggle-string": "^0.4.0" - } + "version": "2.4.0-alpha.19", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.19.tgz", + "integrity": "sha512-f86wTDVVjWUtaBcmFYTTLtWpBfooNfZmwvn73f+KXIchYqKgQVzOuGbORuVPwSrAjYLPW0f8Aa5Gb9TbdI17Ug==", + "dev": true }, "node_modules/@volar/typescript": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.1.6.tgz", - "integrity": "sha512-JgPGhORHqXuyC3r6skPmPHIZj4LoMmGlYErFTuPNBq9Nhc9VTv7ctHY7A3jMN3ngKEfRrfnUcwXHztvdSQqNfw==", + "version": "2.4.0-alpha.19", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.0-alpha.19.tgz", + "integrity": "sha512-Q7tfVVL3HmvUlqjcoTEk/6LiwlDF13XP8avAARovK4Qc6Djsckc+COLovr+ZX6kIxxTdM+Ggv9C0nCNFjMeiSQ==", "dev": true, "dependencies": { - "@volar/language-core": "2.1.6", - "path-browserify": "^1.0.1" + "@volar/language-core": "2.4.0-alpha.19", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" } }, "node_modules/@vue/compiler-core": { @@ -3179,6 +3177,16 @@ "@vue/shared": "3.4.21" } }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, "node_modules/@vue/devtools-api": { "version": "6.6.1", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz", @@ -3223,18 +3231,19 @@ } }, "node_modules/@vue/language-core": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.7.tgz", - "integrity": "sha512-Vh1yZX3XmYjn9yYLkjU8DN6L0ceBtEcapqiyclHne8guG84IaTzqtvizZB1Yfxm3h6m7EIvjerLO5fvOZO6IIQ==", + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.29.tgz", + "integrity": "sha512-o2qz9JPjhdoVj8D2+9bDXbaI4q2uZTHQA/dbyZT4Bj1FR9viZxDJnLcKVHfxdn6wsOzRgpqIzJEEmSSvgMvDTQ==", "dev": true, "dependencies": { - "@volar/language-core": "~2.1.3", + "@volar/language-core": "~2.4.0-alpha.18", "@vue/compiler-dom": "^3.4.0", + "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.4.0", "computeds": "^0.0.1", "minimatch": "^9.0.3", - "path-browserify": "^1.0.1", - "vue-template-compiler": "^2.7.14" + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" @@ -7480,6 +7489,12 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, "node_modules/vue": { "version": "3.4.21", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz", @@ -7627,16 +7642,6 @@ "vue": "^3.2.0" } }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", - "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "dev": true, - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, "node_modules/vue-toastification": { "version": "2.0.0-rc.5", "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz", @@ -7646,20 +7651,20 @@ } }, "node_modules/vue-tsc": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.7.tgz", - "integrity": "sha512-LYa0nInkfcDBB7y8jQ9FQ4riJTRNTdh98zK/hzt4gEpBZQmf30dPhP+odzCa+cedGz6B/guvJEd0BavZaRptjg==", + "version": "2.0.29", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.29.tgz", + "integrity": "sha512-MHhsfyxO3mYShZCGYNziSbc63x7cQ5g9kvijV7dRe1TTXBRLxXyL0FnXWpUF1xII2mJ86mwYpYsUmMwkmerq7Q==", "dev": true, "dependencies": { - "@volar/typescript": "~2.1.3", - "@vue/language-core": "2.0.7", + "@volar/typescript": "~2.4.0-alpha.18", + "@vue/language-core": "2.0.29", "semver": "^7.5.4" }, "bin": { "vue-tsc": "bin/vue-tsc.js" }, "peerDependencies": { - "typescript": "*" + "typescript": ">=5.0.0" } }, "node_modules/w3c-xmlserializer": { diff --git a/filebrowser/frontend/src/api/tus.ts b/filebrowser/frontend/src/api/tus.ts index dd824357e9..5e4e116b18 100644 --- a/filebrowser/frontend/src/api/tus.ts +++ b/filebrowser/frontend/src/api/tus.ts @@ -61,7 +61,7 @@ export async function upload( fileData.hasStarted = true; fileData.lastProgressTimestamp = Date.now(); - fileData.interval = setInterval(() => { + fileData.interval = window.setInterval(() => { calcProgress(filePath); }, SPEED_UPDATE_INTERVAL); } diff --git a/filebrowser/frontend/src/css/_shell.css b/filebrowser/frontend/src/css/_shell.css index 1d2813a93a..3b4eec0eb5 100644 --- a/filebrowser/frontend/src/css/_shell.css +++ b/filebrowser/frontend/src/css/_shell.css @@ -14,7 +14,7 @@ width: 100%; } -.shell__divider{ +.shell__divider { background: rgba(127, 127, 127, 0.3); width: 100%; height: 8px; @@ -69,8 +69,6 @@ body.rtl .shell-content { font-size: inherit; } - - .shell__prompt { width: 1.2rem; } @@ -84,5 +82,5 @@ body.rtl .shell-content { font-family: inherit; white-space: pre-wrap; width: 100%; - color:var(--textSecondary); + color: var(--textSecondary); } diff --git a/filebrowser/frontend/src/css/_variables.css b/filebrowser/frontend/src/css/_variables.css index a56285ba3a..85ad96ec42 100644 --- a/filebrowser/frontend/src/css/_variables.css +++ b/filebrowser/frontend/src/css/_variables.css @@ -54,5 +54,5 @@ --borderPrimary: rgba(255, 255, 255, 0.05); --borderSecondary: rgba(255, 255, 255, 0.15); --dividerPrimary: rgba(30, 30, 30, 0.4); - --dividerSecondary:rgba(30, 30, 30, 0.6); + --dividerSecondary: rgba(30, 30, 30, 0.6); } diff --git a/filebrowser/frontend/src/i18n/ca.json b/filebrowser/frontend/src/i18n/ca.json index f8b5966c08..bc00fd2adf 100644 --- a/filebrowser/frontend/src/i18n/ca.json +++ b/filebrowser/frontend/src/i18n/ca.json @@ -261,4 +261,4 @@ "seconds": "Segons", "unit": "Unitat" } -} \ No newline at end of file +} diff --git a/filebrowser/frontend/src/i18n/zh-tw.json b/filebrowser/frontend/src/i18n/zh-tw.json index fdb2447c06..050666f8c4 100644 --- a/filebrowser/frontend/src/i18n/zh-tw.json +++ b/filebrowser/frontend/src/i18n/zh-tw.json @@ -6,7 +6,7 @@ "copy": "複製", "copyFile": "複製檔案", "copyToClipboard": "複製到剪貼簿", - "copyDownloadLinkToClipboard": "複製到剪貼簿", + "copyDownloadLinkToClipboard": "複製到剪貼簿", "create": "建立", "delete": "刪除", "download": "下載", @@ -228,7 +228,7 @@ "title": "主題" }, "user": "使用者", - "userCommands": "使用者命令(Shell 命令)", + "userCommands": "使用者命令(Shell 命令)", "userCommandsHelp": "指定該使用者可以執行的命令(Shell 命令),用空格分隔。例如:", "userCreated": "使用者已建立!", "userDefaults": "使用者預設選項", diff --git a/filebrowser/frontend/src/stores/upload.ts b/filebrowser/frontend/src/stores/upload.ts index 60dfdb8a80..6fef19a035 100644 --- a/filebrowser/frontend/src/stores/upload.ts +++ b/filebrowser/frontend/src/stores/upload.ts @@ -22,7 +22,7 @@ function formatSize(bytes: number): string { const i = Math.floor(Math.log(bytes) / Math.log(k)); // Return the rounded size with two decimal places - return (bytes / k ** i).toFixed(2) + " " + sizes[i]; + return (bytes / k ** i).toFixed(2) + " " + sizes[i]; } export const useUploadStore = defineStore("upload", { diff --git a/filebrowser/frontend/src/views/files/Preview.vue b/filebrowser/frontend/src/views/files/Preview.vue index b337252a97..17b3df6062 100644 --- a/filebrowser/frontend/src/views/files/Preview.vue +++ b/filebrowser/frontend/src/views/files/Preview.vue @@ -413,7 +413,7 @@ const toggleNavigation = throttle(function () { clearTimeout(navTimeout.value); } - navTimeout.value = setTimeout(() => { + navTimeout.value = window.setTimeout(() => { showNav.value = false || hoverNav.value; navTimeout.value = null; }, 1500); diff --git a/filebrowser/frontend/src/views/settings/Global.vue b/filebrowser/frontend/src/views/settings/Global.vue index 40a3ec043f..26db84eb85 100644 --- a/filebrowser/frontend/src/views/settings/Global.vue +++ b/filebrowser/frontend/src/views/settings/Global.vue @@ -273,7 +273,7 @@ const formattedChunkSize = computed({ } // Set a new timeout to apply the format after a short delay - debounceTimeout.value = setTimeout(() => { + debounceTimeout.value = window.setTimeout(() => { if (settings.value) settings.value.tus.chunkSize = parseBytes(value); }, 1500); }, diff --git a/naiveproxy/CHROMIUM_VERSION b/naiveproxy/CHROMIUM_VERSION index c67e7a510e..99ecb8a287 100644 --- a/naiveproxy/CHROMIUM_VERSION +++ b/naiveproxy/CHROMIUM_VERSION @@ -1 +1 @@ -127.0.6533.64 +128.0.6613.40 diff --git a/naiveproxy/src/AUTHORS b/naiveproxy/src/AUTHORS index 0d9f16b9a0..ad27653d70 100644 --- a/naiveproxy/src/AUTHORS +++ b/naiveproxy/src/AUTHORS @@ -61,7 +61,6 @@ Aldo Culquicondor Alec Petridis Aleksandar Stojiljkovic Aleksei Gurianov -Aleksey Khoroshilov Alesandro Ortiz Alessandro Astone Alex Chronopoulos @@ -209,7 +208,6 @@ Brendan Kirby Brendan Long Brendon Tiszka Brett Lewis -Brian Clifton Brian Dunn Brian G. Merrell Brian Konzman, SJ @@ -297,6 +295,7 @@ Daiwei Li Damien Marié Dan McCombs Daniel Adams +Daniel Bertalan Daniel Bevenius Daniel Bomar Daniel Carvalho Liedke @@ -311,6 +310,7 @@ Daniel Playfair Cal Daniel Shaulov Daniel Trebbien Daniel Waxweiler +Daniel Zhao Dániel Bátyai Dániel Vince Daniil Suvorov @@ -409,6 +409,7 @@ Erik Kurzinger Erik Sjölund Eriq Augustine Ernesto Mudu +Ethan Chen Ethan Wong Etienne Laurin Eugene Kim @@ -435,7 +436,6 @@ Finbar Crago François Beaufort François Devatine Francois Kritzinger -Francois Marier Francois Rauch Frankie Dintino Franklin Ta @@ -478,6 +478,7 @@ Greg Visser Gregory Davis Grzegorz Czajkowski Guangzhen Li +Guobin Wu Gurpreet Kaur Gustav Tiger Gyuyoung Kim @@ -631,6 +632,7 @@ Jesper Storm Bache Jesper van den Ende Jesse Miller Jesus Sanchez-Palencia +Jia Yu Jiadong Chen Jiadong Zhu Jiahao Lu @@ -686,6 +688,7 @@ John Kleinschmidt John Yani John Yoo Johnson Lin +Jojo R Jon Jensen Jonathan Frazer Jonathan Garbee @@ -734,6 +737,7 @@ Junmin Zhu Junsang Mo Junsong Li Jun Wang +Jun Xu Jun Zeng Justin Okamoto Justin Ribeiro @@ -933,7 +937,6 @@ Matthieu Rigolot Matthieu Vlad Hauglustaine Mattias Buelens Max Coplan -Max Karolinskiy Max Perepelitsyn Max Schmitt Max Vujovic @@ -969,7 +972,6 @@ Mihai Tica Mike Pennisi Mike Tilburg Mikhail Pozdnyakov -Mikhail Atuchin Milko Leporis Milton Chiang Milutin Smiljanic @@ -1110,7 +1112,6 @@ Po-Chun Chang Prakhar Shrivastav Pramod Begur Srinath Pranay Kumar -Pranjal Jumde Prashant Hiremath Prashant Nevase Prashant Patil @@ -1137,7 +1138,6 @@ Rahul Gupta Rahul Yadav Rajesh Mahindra Rajneesh Rana -Ralph Giles Raman Tenneti Ramkumar Gokarnesan Ramkumar Ramachandra @@ -1203,6 +1203,7 @@ Ryan Manuel Ryan Norton Ryan Sleevi Ryan Yoakum +Ryan Huen Rye Zhang Ryo Ogawa Ryuan Choi @@ -1386,6 +1387,7 @@ Takuya Kurimoto Tanay Chowdhury Tanvir Rizvi Tao Wang +Tao Xiong Tapu Kumar Ghose Taylor Price Ted Kim @@ -1611,6 +1613,7 @@ Akamai Inc. <*@akamai.com> ARM Holdings <*@arm.com> BlackBerry Limited <*@blackberry.com> Bocoup <*@bocoup.com> +Brave Software Inc. <*@brave.com> Canonical Limited <*@canonical.com> Cloudflare, Inc. <*@cloudflare.com> CloudMosa, Inc. <*@cloudmosa.com> diff --git a/naiveproxy/src/DEPS b/naiveproxy/src/DEPS index d2b8d544a5..3c1d822bba 100644 --- a/naiveproxy/src/DEPS +++ b/naiveproxy/src/DEPS @@ -253,7 +253,7 @@ vars = { # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:6fb4d5d26773ebddeac2c57506324493e4220007', + 'luci_go': 'git_revision:771ea9a614a104c71655f699ef82219a2a474817', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -272,19 +272,19 @@ vars = { # reclient CIPD package 'reclient_package': 'infra/rbe/client/', # reclient CIPD package version - 'reclient_version': 're_client_version:0.143.0.518e369-gomaip', + 'reclient_version': 're_client_version:0.150.1.d9707319-gomaip', # screen-ai CIPD packages # TODO(b/281483558): Use a tag to download the latest version of screen-ai # (e.g. 'version:121.3') and find a way to automate updating //DEPS with it. - 'screen_ai_linux': 'version:124.3', - 'screen_ai_macos_amd64': 'version:124.3', - 'screen_ai_macos_arm64': 'version:124.3', - 'screen_ai_windows_amd64': 'version:124.3', - 'screen_ai_windows_386': 'version:124.3', + 'screen_ai_linux': 'version:125.0', + 'screen_ai_macos_amd64': 'version:125.0', + 'screen_ai_macos_arm64': 'version:125.0', + 'screen_ai_windows_amd64': 'version:125.0', + 'screen_ai_windows_386': 'version:125.0', # siso CIPD package version. - 'siso_version': 'git_revision:188a286bc04cc0276ce8dfecd64f04785b6f038c', + 'siso_version': 'git_revision:b41f9eaf44dfdaec51ab2d7089aaa4cb6d9e7f5e', # download libaom test data 'download_libaom_testdata': False, @@ -307,38 +307,38 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': 'fb285de0da654c8099283ccd37f0b3394317b2c5', + 'src_internal_revision': 'e98873e610e950455dad3468926fb88a1303f69b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '1c8089adffdabe3790cc4ca4fb36e24c2f6ab792', + 'skia_revision': 'fb67954b7e76dc59567dd1f87734ada0cd1bc7f6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '5c5f3d841901cb78a4e130d38d081d03f82f1e36', + 'v8_revision': '57fb77ac624960f08296dbba8ef5b82ab5184287', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '43c6e22996278ff7be2506f0f7d9493cb2f14223', + 'angle_revision': '713102774487cf1a8b3f433529eb8181cbcec31a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '2ff3212615da62f591be15eef78721c29c5c0b31', + 'swiftshader_revision': 'c4dfa69de7deecf52c6b53badbc8bb7be1a05e8c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '6265082af5b2e931c01781befbd93abf39c3d4be', + 'pdfium_revision': '66c80ddf43e3c3181d404607dcdc0cf37fdf7675', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. # # Note this revision should be updated with # third_party/boringssl/roll_boringssl.py, not roll-dep. - 'boringssl_revision': '2db0eb3f96a5756298dcd7f9319e56a98585bd10', + 'boringssl_revision': 'f01108e4761e1d4189cb134322c3cb01dc71ef87', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:21.20240606.0.1', + 'fuchsia_version': 'version:22.20240717.4.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -346,7 +346,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling googletest # and whatever else without interference from each other. - 'googletest_revision': 'a7f443b80b105f940225332ed3c31f2790092f47', + 'googletest_revision': 'cee1ba1f24fb12b9ae8f31e70dca3f73dbb12cc2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -358,11 +358,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '416908382260d3ed2c78f91a780d73957f6a8dca', + 'nacl_revision': 'ad617ab7dd5f23a67fcff244b3c3263ffcc7e66d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'd41a855aab6d8ce131c465ce01f0f536e0fb2269', + 'freetype_revision': '37cefe33b284d0bad4ec52bcccc1a8c2d8704340', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -382,15 +382,15 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '0a2c28ef7c96c683a79869455a1b6814fce293c6', + 'catapult_revision': '523ebded2f72a446544e2d9271ef39857f4e6ae7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. - 'chromium_variations_revision': 'f67c79165e124a649525d797f0c4de51354b0146', + 'chromium_variations_revision': 'c134de595151ae72a112767e22da4448eb50e57f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. - 'crossbench_revision': '45d21f24294ba4e72c6f0e37101f996ec839e824', + 'crossbench_revision': 'b03a515f9e56280ecabfb254b188349d1a049827', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -402,7 +402,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'c563ccab2ed28501c07ef473ab9fc7a68d08f754', + 'devtools_frontend_revision': '47f04a536265028feb1254a3663853e0ce526455', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -410,7 +410,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version # and whatever else without interference from each other. - 'android_sdk_build-tools_version': 'YK9Rzw3fDzMHVzatNN6VlyoD_81amLZpN1AbmkdOd6AC', + 'android_sdk_build-tools_version': 'DxwAZ3hD551Neu6ycuW5CPnXFrdleRBd93oX1eB_m9YC', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_emulator_version # and whatever else without interference from each other. @@ -418,19 +418,19 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_platform-tools_version # and whatever else without interference from each other. - 'android_sdk_platform-tools_version': 'HWVsGs2HCKgSVv41FsOcsfJbNcB0UFiNrF6Tc4yRArYC', + 'android_sdk_platform-tools_version': 'WihaseZR6cojZbkzIqwGhpTp92ztaGfqq8njBU8eTXYC', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_platforms_version # and whatever else without interference from each other. - 'android_sdk_platforms_version': 'u-bhWbTME6u-DjypTgr3ZikCyeAeU6txkR9ET6Uudc8C', + 'android_sdk_platforms_version': 'kIXA-9XuCfOESodXEdOBkW5f1ytrGWdbp3HFp1I8A_0C', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '6c0b2ce19bac367099a07f102b5e33a4e56620a1', + 'dawn_revision': '9e12a15979615111af43befcd441762d23060001', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '76863f97e957032cb5ebcf893a1326d99b8bd68b', + 'quiche_revision': 'aecfea159d58ef53bd690688e4aca512fc4a3d35', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -446,11 +446,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavif # and whatever else without interference from each other. - 'libavif_revision': 'e19debf01d4c13003452c402fb0faffe8b59fcf7', + 'libavif_revision': '03acd65314fe29e6627cf4eab752819f6ee15d74', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling crabbyavif # and whatever else without interference from each other. - 'crabbyavif_revision': '4019784e240dfab5e341fe518f059fd936d7a1f7', + 'crabbyavif_revision': '716408df5cb6d43ebe31cb24194979b81a83b03c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavifinfo # and whatever else without interference from each other. @@ -462,7 +462,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': 'bc66c63a48e3595ff4e1d410c8f58c44854d532f', + 'nearby_revision': '76651429b8f96fc6c80949ba8f4e18c4b738e216', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -474,7 +474,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'cros_components_revision': '2f4bcf1e2e954ed149ab8c83bb31664f9c3c8625', + 'cros_components_revision': '39e57dd0d30ed019d6fb07c24b350f5fe78a1625', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -482,11 +482,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'libcxxabi_revision': '43dd5b4bf62e8593461dce9a95e3d43fdcd0b9f2', + 'libcxxabi_revision': 'a3c7d3e2f3e1e724b4651891b1a71257cbd88acc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'libunwind_revision': 'c8f1d81998280ae2ea0e76ddb60aae6e1b4b860e', + 'libunwind_revision': 'd09db732ff68f40fd3581306c650b17ea1955b4e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -498,29 +498,33 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ffmpeg # and whatever else without interference from each other. - 'ffmpeg_revision': 'bc1ee906cede137c061bea5a5e8d0743374392a5', + 'ffmpeg_revision': 'd941d9677bb4802f01750fd908ec284fb72c84df', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling beto-core # and whatever else without interference from each other. - 'betocore_revision': '8bd72cfb219344308ee857bcbe65a27fe91acfe8', + 'betocore_revision': '08537fdd2b0990270ea0214a61dfd318f293bc15', # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '852bc6746f45add53fec19f3a29280e69e358d44', + 'libcxx_revision': '6bb75caa139ee1e686d2205910454cf6ea212e58', # GN CIPD package version. - 'gn_version': 'git_revision:b3a0bff47dd81073bfe67a402971bad92e4f2423', + 'gn_version': 'git_revision:b2afae122eeb6ce09c52d63f67dc53fc517dbdc8', + + # ninja CIPD package. + 'ninja_package': 'infra/3pp/build_support/ninja-1_11_1/', # ninja CIPD package version. - # https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja - # This has to stay in sync with the version in src/third_party/ninja/README.chromium. - 'ninja_version': 'version:2@1.11.1.chromium.6', + 'ninja_version': 'version:2@1.11.1.chromium.2', # 'magic' variable to tell depot_tools that git submodules should be accepted # but parity with DEPS file is expected. 'SUBMODULE_MIGRATION': 'True', - # condition to allowlist deps for non-git-source processing. + # condition to allowlist deps to be synced in Cider. Allowlisting is needed + # because not all deps are compatible with Cider. Once we migrate everything + # to be compatible we can get rid of this allowlisting mecahnism and remove + # this condition. Tracking bug for removing this condition: b/349365433 'non_git_source': 'True', } @@ -704,6 +708,16 @@ deps = { }, ], }, + 'src/third_party/data_sharing_sdk': { + 'packages': [ + { + 'package': 'chrome_internal/third_party/google3/data_sharing_sdk', + 'version': '_gPXBMBdGeGG9VVbhUbqpHlF4albbDV9mP2cpa0KKqsC', + }, + ], + 'condition': 'checkout_src_internal', + 'dep_type': 'cipd', + }, # Pull down Node binaries for WebUI toolchain. # The Linux binary is always downloaded regardless of host os and architecture # since remote node actions run on Linux worker. @@ -768,6 +782,21 @@ deps = { }, ], }, + # Pull down NPM dependencies for WebUI toolchain. + 'src/third_party/node/node_modules': { + 'bucket': 'chromium-nodejs', + 'dep_type': 'gcs', + 'condition': 'non_git_source', + 'objects': [ + { + 'object_name': '754719bba9f4122301e4605959910e7e3508d88c', + 'sha256sum': '690da706abb3ecd793c24012b3c080e49faa306fac41823646eca333031e7f90', + 'size_bytes': 8311774, + 'generation': 1719949965421539, + 'output_file': 'node_modules.tar.gz', + }, + ], + }, # Download selected models from TFHub as testdata. 'src/third_party/tfhub_models/testdata': { 'bucket': 'chromium-tfhub-models', @@ -787,143 +816,143 @@ deps = { 'condition': 'not llvm_force_head_revision', 'objects': [ { - 'object_name': 'Linux_x64/clang-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '2c95e921b2a26b968e5f2160560ed1f35559f5cc8a64a4f87974d51eff8eea8b', - 'size_bytes': 50869256, - 'generation': 1717767135920224, + 'object_name': 'Linux_x64/clang-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '01286e19596f8297700fb82a186753504d660582d7dc36546b369fdd9ba01f33', + 'size_bytes': 51489372, + 'generation': 1721053058125162, 'condition': 'host_os == "linux" and non_git_source', }, { - 'object_name': 'Linux_x64/clang-tidy-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '0ca2bb8311f1abcb80ba0d8c9a97c1375a5e14ff1c7920633d10cf3137fa272b', - 'size_bytes': 12898000, - 'generation': 1717767136015811, + 'object_name': 'Linux_x64/clang-tidy-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': 'f4726521a6a23e981c33389ce90edb8c723f78ab547f32440608d4d0a9ff707b', + 'size_bytes': 13078048, + 'generation': 1721053058125104, 'condition': 'host_os == "linux" and checkout_clang_tidy and non_git_source', }, { - 'object_name': 'Linux_x64/clangd-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': 'fc8daa9f864fcfb9797eebc008807d833dfcfcecb063bbb8931f36683358d8b2', - 'size_bytes': 13303136, - 'generation': 1717767135963516, + 'object_name': 'Linux_x64/clangd-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '28237331f546aadd54c558dcd128ab25ee43cacf1e36733d7820e8381781c5dc', + 'size_bytes': 13541548, + 'generation': 1721053058172583, 'condition': 'host_os == "linux" and checkout_clangd and non_git_source', }, { - 'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '253cb7766958664635b1ec9e25c60a9a9f5c919bb644249fcbc0316e01a38357', - 'size_bytes': 2316576, - 'generation': 1717767136054513, + 'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '77241a292b67bc29caea0dcaa673ee00f7dc8f4aeefb7d546be36765d5b4c0ed', + 'size_bytes': 2357628, + 'generation': 1721053058239613, 'condition': 'host_os == "linux" and checkout_clang_coverage_tools and non_git_source', }, { - 'object_name': 'Linux_x64/llvmobjdump-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '8eb8aebc5b1bc237d552ef5e4dba701dbedfedd2e45f8cba4f4051c5727d34a5', - 'size_bytes': 5345684, - 'generation': 1717767135991162, + 'object_name': 'Linux_x64/llvmobjdump-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '891f7bda6ee5e1d4ecdef7c008e1ce0752b70bbaa044bd04e00643cf6a5ad2ea', + 'size_bytes': 5388988, + 'generation': 1721053058125359, 'condition': '(checkout_linux or checkout_mac or checkout_android and host_os != "mac") and non_git_source', }, { - 'object_name': 'Mac/clang-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '6e21ef43878368e499c009f6c383cebf318a109ed7c68a77017d1f898ac6ebd1', - 'size_bytes': 45828024, - 'generation': 1717767137856220, + 'object_name': 'Mac/clang-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': 'f5426bc6840290cc5de7fda207e9317e790f9c93e29140eeeba5907f01634291', + 'size_bytes': 46440028, + 'generation': 1721053060063486, 'condition': 'host_os == "mac" and host_cpu == "x64"', }, { - 'object_name': 'Mac/clang-mac-runtime-library-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '70d8f252b65542c474f7b909767f70a6ca7e39396f0d8b2f9d3a74f065e0c241', - 'size_bytes': 842840, - 'generation': 1717767144188942, + 'object_name': 'Mac/clang-mac-runtime-library-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '2cd2ef71cc207ae7221c657e8693e8571613f615c70927fb06a322c9a04d41d8', + 'size_bytes': 864720, + 'generation': 1721053067687284, 'condition': 'checkout_mac and not host_os == "mac"', }, { - 'object_name': 'Mac/clang-tidy-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': 'ac1d4ccb3ca15e91966a5f64c223224c32936066d3df2c512682df688734ad07', - 'size_bytes': 12493348, - 'generation': 1717767137928722, + 'object_name': 'Mac/clang-tidy-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': 'd2244bf0ba14ee407bbfc527b6026f882a0919898d2cebf6e281436775b7231e', + 'size_bytes': 12659584, + 'generation': 1721053060116531, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_tidy', }, { - 'object_name': 'Mac/clangd-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '03428ee82481659ea1b4f60393cb0b83b56cf91d6da992a9ed28d9797752f6ca', - 'size_bytes': 12784392, - 'generation': 1717767137943240, + 'object_name': 'Mac/clangd-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': 'd5f1d41d6273bc2bcd38bccd49d875f118304ed7f01db271bac6b88816cfc4f8', + 'size_bytes': 12971072, + 'generation': 1721053060068931, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clangd', }, { - 'object_name': 'Mac/llvm-code-coverage-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '307a36afe3aacba165a9dcfa362038029ac3f692bd18138062ad37f4ae482301', - 'size_bytes': 2172676, - 'generation': 1717767138031856, + 'object_name': 'Mac/llvm-code-coverage-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '7e09a5d5f0a7dc641ef776c7e23111fdc41d061366f790232978bef41a894637', + 'size_bytes': 2233488, + 'generation': 1721053060268344, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_coverage_tools', }, { - 'object_name': 'Mac_arm64/clang-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '81cf4c48c346e7332cd83917d3f82660634d1123ab53fc93740f80fabd37de2e', - 'size_bytes': 41487688, - 'generation': 1717767147110695, + 'object_name': 'Mac_arm64/clang-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '805f9429987b478ab226569aa8d8fce75ddbabf3da5607bc84557dd04be8159e', + 'size_bytes': 42068284, + 'generation': 1721053069454629, 'condition': 'host_os == "mac" and host_cpu == "arm64"', }, { - 'object_name': 'Mac_arm64/clang-tidy-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '568cf47b9ec277adc4232e7171b6fe0665fa879bb1789343fbe0e8f5dab30d3b', - 'size_bytes': 11456804, - 'generation': 1717767147142997, + 'object_name': 'Mac_arm64/clang-tidy-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '845dd7b83405807f017d62af1b0ad2158e38fe9d3c4e772f4ed77496ee7a0890', + 'size_bytes': 11612208, + 'generation': 1721053069520817, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_tidy', }, { - 'object_name': 'Mac_arm64/clangd-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': 'a53d7330161cb42aa8780a74615a888cacacb8ea9a6a449d8af74f2bff944f9b', - 'size_bytes': 11912916, - 'generation': 1717767147207329, + 'object_name': 'Mac_arm64/clangd-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '2ccbef1de415fc00e2a7f6a5f6ba52a493b2045205e744282267667cb4797a85', + 'size_bytes': 12087592, + 'generation': 1721053069479959, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clangd', }, { - 'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '9084ef3dd48711b2143369eca753e90fa5608fd66786ba3faae599a29a3b5a88', - 'size_bytes': 1951880, - 'generation': 1717767147282651, + 'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': 'f489666c2bd2cd2030367e539b823f282f92f1340ba3823043a44c8b74885cf4', + 'size_bytes': 2005912, + 'generation': 1721053069580934, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_coverage_tools', }, { - 'object_name': 'Win/clang-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '5b42a3e8f5847e9333263af5faa002ccd798893caf2ff47734a047e098bbb284', - 'size_bytes': 40135748, - 'generation': 1717767156694710, + 'object_name': 'Win/clang-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '209ef626a0700401843edf4b19ae16975b7abdfc5cf75a7ee5ed58f71a9ff034', + 'size_bytes': 41767584, + 'generation': 1721053079535176, 'condition': 'host_os == "win"', }, { - 'object_name': 'Win/clang-tidy-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': 'f8e08efb486f622b79129af2597caca9dba5033a8252f17fe2da64f021cc27cb', - 'size_bytes': 12521172, - 'generation': 1717767156756900, + 'object_name': 'Win/clang-tidy-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '9dbd209ca36da40eaa4163e41060cfb3ab2b441d5e191d57313340030d3d8939', + 'size_bytes': 12865940, + 'generation': 1721053079590816, 'condition': 'host_os == "win" and checkout_clang_tidy', }, { - 'object_name': 'Win/clang-win-runtime-library-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': 'f8609347334a99b0363dd14d43b84d4db139630b43a8eefc8f8d4ec5b4b0fa49', - 'size_bytes': 2804644, - 'generation': 1717767164441105, + 'object_name': 'Win/clang-win-runtime-library-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '32798e1486e21375f479b9822e92e1446624ea0474232052522b824843190095', + 'size_bytes': 2844696, + 'generation': 1721053087422798, 'condition': 'checkout_win and not host_os == "win"', }, { - 'object_name': 'Win/clangd-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': 'a52a5a9416b611bbc6248ce6a67d5f3d6937b4bfa55adc16e08cae3c69168f85', - 'size_bytes': 12968240, - 'generation': 1717767156753940, + 'object_name': 'Win/clangd-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '41cb8cb7f750e2ecb0e63df89bce4927e151449c741f8bd15a43ca97ada547b9', + 'size_bytes': 13323796, + 'generation': 1721053079631561, 'condition': 'host_os == "win" and checkout_clangd', }, { - 'object_name': 'Win/llvm-code-coverage-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '34403d7c53bbdfd0c8ff5c10ce635754e80098b0e94942045e76284d6712d03a', - 'size_bytes': 2291052, - 'generation': 1717767156872540, + 'object_name': 'Win/llvm-code-coverage-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '76944d9e4a873b22294e592bbdf749c9c74621268107a987cbfc97029a950d07', + 'size_bytes': 2355756, + 'generation': 1721053079754133, 'condition': 'host_os == "win" and checkout_clang_coverage_tools', }, { - 'object_name': 'Win/llvmobjdump-llvmorg-19-init-10646-g084e2b53-57.tar.xz', - 'sha256sum': '1f8a52fdc4d051b30c6617d31a4737853b8c149e86f4082c55957210f68204a2', - 'size_bytes': 5298192, - 'generation': 1717767156826531, + 'object_name': 'Win/llvmobjdump-llvmorg-19-init-14561-gecea8371-3000.tar.xz', + 'sha256sum': '2821d40f2d05669905a4b9e44db04c5d772e604a7f8da9981497686bd3494ce0', + 'size_bytes': 5361436, + 'generation': 1721053079615201, 'condition': 'checkout_linux or checkout_mac or checkout_android and host_os == "win"', }, ] @@ -934,31 +963,31 @@ deps = { 'bucket': 'chromium-browser-clang', 'objects': [ { - 'object_name': 'Linux_x64/rust-toolchain-32dd3795bce8b347fda786529cf5e42a813e0b7d-2-llvmorg-19-init-10646-g084e2b53.tar.xz', - 'sha256sum': 'e7e236fe6e61b7a41ba6b1e4bc64e91119359cdddce268597c6328b9fea8d76d', - 'size_bytes': 151082700, - 'generation': 1715715529295267, + 'object_name': 'Linux_x64/rust-toolchain-3cf924b934322fd7b514600a7dc84fc517515346-3-llvmorg-19-init-14561-gecea8371.tar.xz', + 'sha256sum': 'd3532ada45f1e47d5d7a197190842beebc20acbd1a9ec8fe442b67b9fd9c0074', + 'size_bytes': 148907072, + 'generation': 1721105673940838, 'condition': 'host_os == "linux" and non_git_source', }, { - 'object_name': 'Mac/rust-toolchain-32dd3795bce8b347fda786529cf5e42a813e0b7d-2-llvmorg-19-init-10646-g084e2b53.tar.xz', - 'sha256sum': '3860d592e7f6a853aa06a00642f4110132c7af7f2b91d7bdd399d00dbd5177f6', - 'size_bytes': 143827372, - 'generation': 1715715530889094, + 'object_name': 'Mac/rust-toolchain-3cf924b934322fd7b514600a7dc84fc517515346-3-llvmorg-19-init-14561-gecea8371.tar.xz', + 'sha256sum': 'a0fa4c395c7bcac8240793dc6c81eb067614210aab817dbf9b825ede1e5980ce', + 'size_bytes': 141660688, + 'generation': 1721105675261013, 'condition': 'host_os == "mac" and host_cpu == "x64"', }, { - 'object_name': 'Mac_arm64/rust-toolchain-32dd3795bce8b347fda786529cf5e42a813e0b7d-2-llvmorg-19-init-10646-g084e2b53.tar.xz', - 'sha256sum': '333dfb93cb0d944acb1ed9f0c44aba9dfdb4e7cd2c660758014338bea37ce8da', - 'size_bytes': 135183068, - 'generation': 1715715532458630, + 'object_name': 'Mac_arm64/rust-toolchain-3cf924b934322fd7b514600a7dc84fc517515346-3-llvmorg-19-init-14561-gecea8371.tar.xz', + 'sha256sum': '6ee658298d8c43a2cba6ccf99373cd861560845788b419446787d890ff9494ba', + 'size_bytes': 133032452, + 'generation': 1721105676505827, 'condition': 'host_os == "mac" and host_cpu == "arm64"', }, { - 'object_name': 'Win/rust-toolchain-32dd3795bce8b347fda786529cf5e42a813e0b7d-2-llvmorg-19-init-10646-g084e2b53.tar.xz', - 'sha256sum': 'f610825518d0f3b6f1e9d2772065165b5bcac3302448a53ac89b3684bae7dbd2', - 'size_bytes': 206423884, - 'generation': 1715715534082072, + 'object_name': 'Win/rust-toolchain-3cf924b934322fd7b514600a7dc84fc517515346-3-llvmorg-19-init-14561-gecea8371.tar.xz', + 'sha256sum': 'dc14ef350334c38fdca58ccf0e341ec357ded991e2e81e353a3f9311e979a199', + 'size_bytes': 204514276, + 'generation': 1721105677747562, 'condition': 'host_os == "win"', }, ], @@ -1054,14 +1083,14 @@ deps = { 'condition': 'checkout_win' }, - 'src/third_party/aosp_dalvik': { + 'src/third_party/aosp_dalvik/cipd': { 'packages': [ { 'package': 'chromium/third_party/aosp_dalvik/linux-amd64', 'version': 'version:2@13.0.0_r24.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, @@ -1069,20 +1098,24 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/cronet_android_mainline_clang/linux-amd64', - 'version': '2HCVOxZv-I1F2tuUgLjeEnC36bV4h35uxQuyDExYxVMC', + 'version': 'YBJ6tRxent4zFvyGNyAxWQ160dRHZ6vj7in9Al3VeGAC', }, ], 'condition': 'checkout_android and host_os == "linux"', 'dep_type': 'cipd', }, - 'src/android_webview/tools/cts_archive': { + 'src/android_webview/tools/cts_archive/cipd': { 'packages': [ { 'package': 'chromium/android_webview/tools/cts_archive', 'version': 'UYQZhJpB3MWpJIAcesI-M1bqRoTghiKCYr_SD9tPDewC', }, ], + # TODO(b/352185555): This path is ready for non_git_sources but some + # files in this package are too large for existing limits. Do not add + # `non_git_source` here until we evaluate how big android sources are + # and agree on some final limits. 'condition': 'checkout_android', 'dep_type': 'cipd', }, @@ -1110,7 +1143,7 @@ deps = { '/external/github.com/llvm/llvm-project/libunwind.git' + '@' + Var('libunwind_revision'), - 'src/third_party/updater/chrome_linux64': { + 'src/third_party/updater/chrome_linux64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_linux and non_git_source', 'packages': [ @@ -1121,7 +1154,7 @@ deps = { ], }, - 'src/third_party/updater/chrome_mac_universal': { + 'src/third_party/updater/chrome_mac_universal/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_mac', 'packages': [ @@ -1132,7 +1165,7 @@ deps = { ], }, - 'src/third_party/updater/chrome_mac_universal_prod': { + 'src/third_party/updater/chrome_mac_universal_prod/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_mac', 'packages': [ @@ -1143,7 +1176,7 @@ deps = { ], }, - 'src/third_party/updater/chrome_win_x86': { + 'src/third_party/updater/chrome_win_x86/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ @@ -1154,7 +1187,7 @@ deps = { ], }, - 'src/third_party/updater/chrome_win_x86_64': { + 'src/third_party/updater/chrome_win_x86_64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ @@ -1165,7 +1198,7 @@ deps = { ], }, - 'src/third_party/updater/chromium_linux64': { + 'src/third_party/updater/chromium_linux64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_linux and non_git_source', 'packages': [ @@ -1177,7 +1210,7 @@ deps = { }, # A somewhat recent Chromium-branded updater build. (x86_64) - 'src/third_party/updater/chromium_mac_amd64': { + 'src/third_party/updater/chromium_mac_amd64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_mac', 'packages': [ @@ -1189,7 +1222,7 @@ deps = { }, # A somewhat recent Chromium-branded updater build. (ARM64) - 'src/third_party/updater/chromium_mac_arm64': { + 'src/third_party/updater/chromium_mac_arm64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_mac', 'packages': [ @@ -1200,7 +1233,7 @@ deps = { ], }, - 'src/third_party/updater/chromium_win_x86': { + 'src/third_party/updater/chromium_win_x86/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ @@ -1211,7 +1244,7 @@ deps = { ], }, - 'src/third_party/updater/chromium_win_x86_64': { + 'src/third_party/updater/chromium_win_x86_64/cipd': { 'dep_type': 'cipd', 'condition': 'checkout_win', 'packages': [ @@ -1223,7 +1256,7 @@ deps = { }, 'src/chrome/test/data/autofill/captured_sites/artifacts': { - 'url': Var('chrome_git') + '/chrome/test/captured_sites/autofill.git' + '@' + 'baa382cb460fab7eeb6e9b0ce8ce4a8eaa604c13', + 'url': Var('chrome_git') + '/chrome/test/captured_sites/autofill.git' + '@' + 'f66e1db8c80c6fb794ffc1117b8587c3e452d193', 'condition': 'checkout_chromium_autofill_test_dependencies', }, @@ -1254,21 +1287,21 @@ deps = { 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '65599068d951070dbecb482c21a1c3eb01f9dfa8', + '61d79046538c2febc691f2fe6df7bc69d6b48b47', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'cbeef22a59f72b8b5b4ac426d2eaa547fd2888b8', + 'url': Var('chromium_git') + '/website.git' + '@' + '82c1d3e5b812b35df1cb6a031f59616dc594d4f7', }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'd220a473076f712d9eddb786840f4d7a210cffdd', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '1bbcd36b01da8262d1e5c4d8e7290a2164e98440', 'condition': 'checkout_ios', }, 'src/ios/third_party/edo/src': { - 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + 'a81474e8b932e1fca1f217a098ef02b313dcc05e', + 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + 'afdcbb02534ac7aeef1ecf793ebf84f699f8299f', 'condition': 'checkout_ios', }, @@ -1283,7 +1316,7 @@ deps = { }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '10161d455bd708e406e085834e1a6f85117719aa', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '86241a2598cea2056102f98d86fe9b30fc25e25d', 'condition': 'checkout_ios', }, @@ -1371,11 +1404,6 @@ deps = { 'url': Var('chromium_git') + '/external/github.com/google/Accessibility-Test-Framework-for-Android.git' + '@' + '4a764c690353ea136c82f1a696a70bf38d1ef5fe', }, - 'src/third_party/android_protobuf/src': { - 'url': Var('android_git') + '/platform/external/protobuf.git' + '@' + '7fca48d8ce97f7ba3ab8eea5c472f1ad3711762f', - 'condition': 'checkout_android', - }, - 'src/third_party/android_protoc': { 'packages': [ { @@ -1391,7 +1419,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_toolchain/android_toolchain', - 'version': 'wpJvg81kuXdMM66r_l9Doa-pLfR6S26Jd1x40LpwWEoC', + 'version': 'h9HeidXTeHQ-oskldbqCZx26-7VrVvXpLfqOI87uy4QC', }, ], 'condition': 'checkout_android_native_support', @@ -1409,14 +1437,14 @@ deps = { 'dep_type': 'cipd', }, - 'src/third_party/androidx': { + 'src/third_party/androidx/cipd': { 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'ng582aHt0njFtL0qiBwJXwQIJtUpSvOIas3HxMwb8n8C', + 'version': 'z6Znkgans_yNNgdQluwGGXbyICjvCR5oFnU-ZvMdjN4C', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, @@ -1429,7 +1457,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_system_sdk/public', - 'version': '4QeolYaSKWBtVTgzJU4tHUfzA9OJTDM8YUcD426IctwC', + 'version': 'XzzECzCzGLrccJS1U-HdmM5VMh9BotgQ_mWhFQ464PwC', }, ], 'condition': 'checkout_android', @@ -1440,7 +1468,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/aapt2', - 'version': 'G1S0vNnfv3f8FD-9mH5RFSUiK-mnSwri_IdiVQKwLP0C', + 'version': 'cfGQ9GV4juNnGZIPzTmaL3ehiZM1hs6UsB5HUA8fT6oC', }, ], 'condition': 'checkout_android', @@ -1462,7 +1490,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/bundletool', - 'version': 'CaAT7TJbLQC0LVo1i2TXtaMjK4SZBQ33n-s6DcBbZfgC', + 'version': 'X5yajoh75x5lwpY1-eO4tey50eTX4XkB5JE1WXVal_MC', }, ], 'condition': 'checkout_android', @@ -1473,7 +1501,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': '_oR7ebBg7HOz8losirWwVBzIiJ9AtS3Xv34pUNKrkNQC', + 'version': '6HiuLpbOXMHuhrrqdM98SceuO7Irim5oDe6SDOuSHSYC', }, ], 'condition': 'checkout_android', @@ -1484,7 +1512,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/manifest_merger', - 'version': 'NhxjXSeTx7oy0a_3ilG0QjFMO8YItXf67EW20A_stP8C', + 'version': 'PWl6vXHNVVT3uJRejbQuGcgQ8wekHWcExK0-Xw7aS7MC', }, ], 'condition': 'checkout_android', @@ -1494,7 +1522,7 @@ deps = { 'src/third_party/android_sdk/public': { 'packages': [ { - 'package': 'chromium/third_party/android_sdk/public/build-tools/34.0.0', + 'package': 'chromium/third_party/android_sdk/public/build-tools/35.0.0', 'version': Var('android_sdk_build-tools_version'), }, { @@ -1506,7 +1534,7 @@ deps = { 'version': Var('android_sdk_platform-tools_version'), }, { - 'package': 'chromium/third_party/android_sdk/public/platforms/android-34', + 'package': 'chromium/third_party/android_sdk/public/platforms/android-35', 'version': Var('android_sdk_platforms_version'), }, { @@ -1599,7 +1627,7 @@ deps = { Var('chromium_git') + '/external/github.com/chromium/content_analysis_sdk.git' + '@' + '9a408736204513e0e95dd2ab3c08de0d95963efc', 'src/third_party/dav1d/libdav1d': - Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + '92f592ed104ba92ad35c781ee93f354525eef503', + Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + '2355eeb8f254a1c34dbb0241be5c70cdf6ed46d1', 'src/third_party/dawn': Var('dawn_git') + '/dawn.git' + '@' + Var('dawn_revision'), @@ -1640,7 +1668,7 @@ deps = { Var('boringssl_git') + '/boringssl.git' + '@' + Var('boringssl_revision'), 'src/third_party/breakpad/breakpad': - Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '76788faa4ef163081f82273bfca7fae8a734b971', + Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '81819541a78c49e9109d2267462775e801f89ce6', 'src/third_party/cast_core/public/src': Var('chromium_git') + '/cast_core/public' + '@' + '71f51fd6fa45fac73848f65421081edd723297cd', @@ -1651,7 +1679,7 @@ deps = { 'src/third_party/ced/src': Var('chromium_git') + '/external/github.com/google/compact_enc_det.git' + '@' + 'ba412eaaacd3186085babcd901679a48863c7dd5', - 'src/third_party/checkstyle': { + 'src/third_party/checkstyle/cipd': { 'packages': [ { 'package': 'chromium/third_party/checkstyle', @@ -1659,7 +1687,7 @@ deps = { }, ], # Needed on Linux for use on chromium_presubmit. - 'condition': 'checkout_android or checkout_linux', + 'condition': '(checkout_android or checkout_linux) and non_git_source', 'dep_type': 'cipd', }, @@ -1675,7 +1703,7 @@ deps = { # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '1d2172955fb8aa08fcdcc559ecf5902a7156aa30', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '34fd166175969865b657e3ecdab165434fc76837', 'condition': 'checkout_chromeos', }, @@ -1689,14 +1717,14 @@ deps = { Var('chromium_git') + '/external/github.com/google/cpu_features.git' + '@' + '936b9ab5515dead115606559502e3864958f7f6e', 'src/third_party/cpuinfo/src': - Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + '05332fd802d9109a2a151ec32154b107c1e5caf9', + Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + 'ca678952a9a8eaa6de112d154e8e104b22f9ab3f', 'src/third_party/crc32c/src': Var('chromium_git') + '/external/github.com/google/crc32c.git' + '@' + 'fa5ade41ee480003d9c5af6f43567ba22e4e17e6', # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '9cf50172dadfcba2908d110b1da8c17e628ab03f', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '86bdf11581c80f776bfdf54db7f39f930fd6abaf', 'condition': 'checkout_linux or checkout_chromeos', }, @@ -1710,13 +1738,13 @@ deps = { }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e30d8fac34378beeb3d72cfca444e87f6fc28013', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '31e21628c3a558d4f2189712e25849d608b3ff8c', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '9cf32beffc4f735fbca98fde9e75088c3dd19fc8', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '1268fb3d10867afd06ed545e334775195eb46c51', 'condition': 'checkout_src_internal', }, @@ -1724,7 +1752,7 @@ deps = { Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '199de96b345ada7c6e7e6ba3d2fa7a6911b8767d', 'src/third_party/eigen3/src': - Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '38b9cc263bbaeb03ce408a4e26084543a6c0dedb', + Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '33d0937c6bdf5ec999939fb17f2a553183d14a74', 'src/third_party/emoji-metadata/src': { 'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '045f146fca682a836e01cd265171312bfb300e06', @@ -1752,7 +1780,7 @@ deps = { Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '689da3a7ed50af7448c3f1961d1791c7c1d9c85c', 'src/third_party/flatbuffers/src': - Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + '6ede1ccc9e24e00d5b19c19d6df0f09fdf1a64fe', + Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + 'fb9afbafc7dfe226b9db54d4923bfb8839635274', # Used for embedded builds. CrOS & Linux use the system version. 'src/third_party/fontconfig/src': { @@ -1820,7 +1848,7 @@ deps = { }, 'src/third_party/cardboard/src' : { - 'url': Var('chromium_git') + '/external/github.com/googlevr/cardboard/' + '@' + 'c8842698f4a9d63cce865e7d6cb75773a4673496', + 'url': Var('chromium_git') + '/external/github.com/googlevr/cardboard/' + '@' + '596352df971aacede278a50f55ff1fecc4e81afc', 'condition': 'checkout_android', }, @@ -1854,7 +1882,7 @@ deps = { 'dep_type': 'cipd', }, - 'src/third_party/google-java-format': { + 'src/third_party/google-java-format/cipd': { 'packages': [ { 'package': 'chromium/third_party/google-java-format', @@ -1910,11 +1938,11 @@ deps = { 'condition': 'checkout_android', }, - 'src/third_party/jdk': { + 'src/third_party/jdk/current': { 'packages': [ { 'package': 'chromium/third_party/jdk', - 'version': 'tUJrCBvDNDE9jFvgkuOwX8tU6oCWT8CtI2_JxpGlTJIC', + 'version': 'BXZwbslDFpYhPRuG8hBh2z7ApP36ZG-ZfkBWrkpnPl4C', }, ], # Needed on Linux for use on chromium_presubmit (for checkstyle). @@ -1948,7 +1976,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/kotlin_stdlib', - 'version': '_4e0lDaCjMgaNeq2v2olJs_15Ax3PxGfCU9fMt0FTKcC', + 'version': '8qx9sot30FtFtPSKIpcEu3KhfqtQHpExnueNhpwxd48C', }, ], 'condition': 'checkout_android', @@ -1959,7 +1987,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/kotlinc', - 'version': '0jpbSygC1gCOFyv-hsyNVfvxPLhDSXnTCSnxHY_mjKoC', + 'version': 'H2ku141hEdbVcUCziJceqiI6I8b9jvHfUxd7FiRSbiUC', }, ], 'condition': 'checkout_android', @@ -1979,7 +2007,7 @@ deps = { Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'e8712e415627f22d0b00ebee8db99547077f39bd', 'src/third_party/libaom/source/libaom': - Var('aomedia_git') + '/aom.git' + '@' + '2badbae61d6ee0996152d640f1e1896c0a0548ab', + Var('aomedia_git') + '/aom.git' + '@' + '93b8eee4f428675195c5c76e8da719ff50c2a01c', 'src/third_party/libavif/src': Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'), @@ -2052,7 +2080,7 @@ deps = { }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + 'a2508b5711b6eb7aee197c8de16a46bda6fdbe88', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '057e53d759ac05417bbc7880b1d2e2ac7f08fc67', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da', @@ -2106,7 +2134,7 @@ deps = { }, 'src/third_party/microsoft_dxheaders/src': { - 'url': Var('chromium_git') + '/external/github.com/microsoft/DirectX-Headers.git' + '@' + '83bb9ef2a6893a4214e5d6c45c6bbd9607d1c308', + 'url': Var('chromium_git') + '/external/github.com/microsoft/DirectX-Headers.git' + '@' + '9be295b3b81ce1d0ff2b44f18d0eb86ea54c5122', 'condition': 'checkout_win', }, @@ -2148,14 +2176,14 @@ deps = { 'src/third_party/ninja': { 'packages': [ { - 'package': 'infra/3pp/tools/ninja/${{platform}}', + 'package': Var('ninja_package') + '${{platform}}', 'version': Var('ninja_version'), } ], 'condition': 'non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/siso': { + 'src/third_party/siso/cipd': { 'packages': [ { 'package': 'infra/build/siso/${{platform}}', @@ -2180,7 +2208,7 @@ deps = { Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '09a4f3ec842a8932341b195c5b01e141c8a16eb7', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + 'a838dff3585383974de4887b51b8d6d91ebe3247', + Var('chromium_git') + '/openscreen' + '@' + '4f7c05781bc43e93706b0330eb830e2bc33fcb6c', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '95fe35ffb383710a6e0567e958ead9a3b66e930c', @@ -2206,7 +2234,7 @@ deps = { Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '636a83a4915afdff2e5758e09a5231ff04278ede', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '077d742d9f9738a0453e408560a283a7514c9e8e', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -2247,11 +2275,18 @@ deps = { 'output_file': 'chrome_page_load_all_categories_not_extended.pftrace.gz' }, { - 'object_name': 'test_data/speedometer.perfetto_trace.gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529', + 'object_name': 'test_data/speedometer_21.perfetto_trace.gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529', 'sha256sum': '8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529', 'size_bytes': 891088, - 'generation': 1684336047660953, - 'output_file': 'speedometer.perfetto_trace.gz' + 'generation': 1716566741068306, + 'output_file': 'speedometer_21.perfetto_trace.gz' + }, + { + 'object_name': 'test_data/speedometer_3.perfetto_trace.gz-b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02', + 'sha256sum': 'b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02', + 'size_bytes': 1301036, + 'generation': 1716566914245446, + 'output_file': 'speedometer_3.perfetto_trace.gz' }, { 'object_name': 'test_data/scroll_jank_with_pinch.pftrace-8587d2016fdb5d39b5f852704b6e3925e9e6527af01696396be767bed04d4a45', @@ -2287,7 +2322,14 @@ deps = { 'size_bytes': 769741, 'generation': 1693402148909129, 'output_file': 'scroll_offsets.pftrace' - } + }, + { + 'object_name': 'test_data/chrome_input_with_frame_view_new.pftrace-e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12', + 'sha256sum': 'e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12', + 'size_bytes': 1967821, + 'generation': 1719520814352733, + 'output_file': 'chrome_input_with_frame_view_new.pftrace' + }, ], 'dep_type': 'gcs' }, @@ -2322,18 +2364,19 @@ deps = { 'version': 'hOpuGIMj1FAtBWGDlXARkCm2srxY4enn8iI3AgrDna4C' }, ], - 'condition': 'host_os == "linux" and checkout_fuchsia and checkout_fuchsia_for_arm64_host and non_git_source', + # TODO(b/351926334): Do not add `non_git_source` to this condition until the bug is fixed. + 'condition': 'host_os == "linux" and checkout_fuchsia and checkout_fuchsia_for_arm64_host', 'dep_type': 'cipd', }, 'src/third_party/re2/src': - Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '33eba105f662c99c8f7d6a264c84ed350bd1dc39', + Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '6dcd83d60f7944926bfd308cc13979fc53dd69ca', 'src/third_party/r8': { 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': '4Bvfp_cCjeULmPkfvkxfFZbH9xB8l5ctPnHCcpH_U8gC', + 'version': '8UxK0Gx2bU0BT44gG8VlK1y8ISbMzcxs2r9ZaxiEPL4C', }, ], 'condition': 'checkout_android', @@ -2454,29 +2497,29 @@ deps = { Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f', 'src/third_party/tflite/src': - Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '0c51dc593181858f2570510befeedbd2d1f53853', + Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'f9122e774969459927e9d956674c0aac06eb3b68', 'src/third_party/turbine': { 'packages': [ { 'package': 'chromium/third_party/turbine', - 'version': 'elwEJQJc0yejdGqKWdrPxMt4P7dQ-cC4UB0UdGYRllsC', + 'version': 'EICM7eVhYRyG5-glA6v4B4llD23SycxxXp3bjd_pke8C', }, ], 'condition': 'checkout_android', 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@7ad3ff13fb10994a9fd7576186fa00b2a361ef81', - 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@73eccd4b67985d344578cade8958214cee0a3f6e', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@d8095b45a0b2dcc2a85327ff4cc306c618dfa39a', + 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@dc9f6f61adaec755a09e1943cf7014c688443bcb', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', - 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@eb49bb7b1136298b77945c52b4bbbc433f7885de', - 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@ce46482db7ab3ea9c52fce832d27ca40b14f8e87', - 'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@d192041a2fc9c9fd8ae67d8ae3f32c5511541f04', - 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@1bae807cd919890f7174fa14228b6e672e8d296e', - 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@a9a1bcd709e185700847268eb4310f6484b027bc', - 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@07759f04791dc3fbb390174f0d24d4a792e0d357', - 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@28c0a5d84f1a5a03655407f5cf52b98399d369af', + 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@db5a00f8cebe81146cafabf89019674a3c4bf03d', + 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@a0817526b8e391732632e6a887134be256a20a18', + 'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@fabe9e2672334fdb9a622d42a2e8f94578952082', + 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@5892ebe2d7505c2238a643288d9a5b2e68784a36', + 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@2cee0d5b1d8c34e26fd6d9992d3d428ac4c5139d', + 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@67522b34edde86dbb97e164280291f387ade55fc', + 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@919599474e6e6639527e7c3775ed1064665412d3', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21', @@ -2513,10 +2556,10 @@ deps = { Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '1b6371436a0a60e6b9a4ae2a40a8eba198e3af02', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '2101ec529d6bbc88bad909c8fbca8cfc91a2ff30', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '198d1770062c1a8aba86e7d6e001bb47bea028ee', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'e0b28a6a81a989c1f5c89e30fcd247870047390d', + Var('webrtc_git') + '/src.git' + '@' + 'e7686023a186ac233ed1284da45cc166c0df4e1a', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -2541,7 +2584,7 @@ deps = { }, 'src/third_party/xnnpack/src': - Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + 'c2aef747585d1453d682e82ee431317a1e35c7f3', + Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '8df2e765487685757ab5dabd12516cd0a24e3e25', 'src/tools/page_cycler/acid3': Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + 'a926d0a32e02c4c03ae95bb798e6c780e0e184ba', @@ -2560,13 +2603,13 @@ deps = { }, 'src/third_party/zstd/src': - Var('chromium_git') + '/external/github.com/facebook/zstd.git' + '@' + '0e2ceb2d5061f3a8357d124029ebaae16d915a3d', + Var('chromium_git') + '/external/github.com/facebook/zstd.git' + '@' + '0ff651dd876823b99fa5c5f53292be28381aee9b', 'src/tools/skia_goldctl/linux': { 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'FInOjoKFumG08L2ebBAsdfg4qwh1gYJZUc9pap-n6xsC', + 'version': 'Tmr9c1O-W7mu7zgVbAgDIpLiDFfiWA2nnWa7FYu0pjgC', }, ], 'dep_type': 'cipd', @@ -2576,7 +2619,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'u0dlrkRpMzR6yqRbcwNgFWbdJW1Dzu6oZ47ZJoYgCPoC', + 'version': 'VoFA8h7UVLHiMG1OJitx6oYOOdQYwTVztBFAMdPaqywC', }, ], 'dep_type': 'cipd', @@ -2587,7 +2630,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': '0l-LH3gvKogXZwC20bT0BBAQWhdfoL25JiEUL-6E_UUC', + 'version': '_7hIgAZisiST_h_sDMLpXETbV5CzGfmG4Oxm38v4rlEC', }, ], 'dep_type': 'cipd', @@ -2598,7 +2641,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': 'Cp4Qw2MXJonjzOYTjnnxkuYfzUaDJb7S2QaR3_-Ky6kC', + 'version': 'JFa9d9Q6qO_diHbU_E8cW9EMTEBkDXLlZz8-USH6YLAC', }, ], 'dep_type': 'cipd', @@ -2628,7 +2671,18 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/eche_app/app', - 'version': 'V7l2yr0da33J7Ty2l57gj9ddh_o1B1pLJmoEazmx-qwC', + 'version': 'zwwvkQYhDuxMzHv44Qmf2bsMV7dz7PGzJwY2TaBt2E0C', + }, + ], + 'condition': 'checkout_chromeos and checkout_src_internal', + 'dep_type': 'cipd', + }, + + 'src/ash/webui/boca_ui/resources/prod': { + 'packages': [ + { + 'package': 'chromeos_internal/apps/boca_app/app', + 'version': 'Be-tokanJu7FuIhv0GPbtsnQyRzVK_mh0aB_-oZbp8IC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2639,7 +2693,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'FXvB8bjsXPk_pk2Ox-lQ3OYg0eRbd0REhH0IdBuhqjMC', + 'version': 'EHrJf332vNaknaw2tf1JbkUL6xwMbAnLRhJcNcE-8ZAC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2650,7 +2704,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'uWzYNXKGqa6BplFWv9h12fqJK0SjAqSwJ6ayxbL4jX8C', + 'version': '3U0WcASbDx-H7TmXmK0LjVmxHlT4EISYU64Lufono_gC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2683,7 +2737,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'h03rVuq2LXiugVk4ZCdq6X5qot-5aUG_71IZdDlThLQC', + 'version': 'KHACchGt7kSgKJO2GXd1uU-0WBxMIVnoiY-ZekxPDY8C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2708,1719 +2762,1719 @@ deps = { # === ANDROID_DEPS Generated Code Start === # Generated by //third_party/android_deps/fetch_all.py - 'src/third_party/android_deps/libs/android_arch_core_common': { + 'src/third_party/android_deps/cipd/libs/android_arch_core_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/android_arch_core_common', 'version': 'version:2@1.1.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/android_arch_core_runtime': { + 'src/third_party/android_deps/cipd/libs/android_arch_core_runtime': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/android_arch_core_runtime', 'version': 'version:2@1.1.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/android_arch_lifecycle_common': { + 'src/third_party/android_deps/cipd/libs/android_arch_lifecycle_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/android_arch_lifecycle_common', 'version': 'version:2@1.1.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/android_arch_lifecycle_livedata': { + 'src/third_party/android_deps/cipd/libs/android_arch_lifecycle_livedata': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/android_arch_lifecycle_livedata', 'version': 'version:2@1.1.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/android_arch_lifecycle_livedata_core': { + 'src/third_party/android_deps/cipd/libs/android_arch_lifecycle_livedata_core': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/android_arch_lifecycle_livedata_core', 'version': 'version:2@1.1.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/android_arch_lifecycle_runtime': { + 'src/third_party/android_deps/cipd/libs/android_arch_lifecycle_runtime': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/android_arch_lifecycle_runtime', 'version': 'version:2@1.1.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/android_arch_lifecycle_viewmodel': { + 'src/third_party/android_deps/cipd/libs/android_arch_lifecycle_viewmodel': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/android_arch_lifecycle_viewmodel', 'version': 'version:2@1.1.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_asynclayoutinflater': { + 'src/third_party/android_deps/cipd/libs/com_android_support_asynclayoutinflater': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_asynclayoutinflater', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_collections': { + 'src/third_party/android_deps/cipd/libs/com_android_support_collections': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_collections', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_coordinatorlayout': { + 'src/third_party/android_deps/cipd/libs/com_android_support_coordinatorlayout': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_coordinatorlayout', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_cursoradapter': { + 'src/third_party/android_deps/cipd/libs/com_android_support_cursoradapter': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_cursoradapter', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_customview': { + 'src/third_party/android_deps/cipd/libs/com_android_support_customview': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_customview', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_documentfile': { + 'src/third_party/android_deps/cipd/libs/com_android_support_documentfile': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_documentfile', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_drawerlayout': { + 'src/third_party/android_deps/cipd/libs/com_android_support_drawerlayout': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_drawerlayout', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_interpolator': { + 'src/third_party/android_deps/cipd/libs/com_android_support_interpolator': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_interpolator', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_loader': { + 'src/third_party/android_deps/cipd/libs/com_android_support_loader': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_loader', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_localbroadcastmanager': { + 'src/third_party/android_deps/cipd/libs/com_android_support_localbroadcastmanager': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_localbroadcastmanager', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_print': { + 'src/third_party/android_deps/cipd/libs/com_android_support_print': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_print', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_slidingpanelayout': { + 'src/third_party/android_deps/cipd/libs/com_android_support_slidingpanelayout': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_slidingpanelayout', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_support_annotations': { + 'src/third_party/android_deps/cipd/libs/com_android_support_support_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_support_annotations', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_support_compat': { + 'src/third_party/android_deps/cipd/libs/com_android_support_support_compat': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_support_compat', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_support_core_ui': { + 'src/third_party/android_deps/cipd/libs/com_android_support_support_core_ui': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_support_core_ui', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_support_core_utils': { + 'src/third_party/android_deps/cipd/libs/com_android_support_support_core_utils': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_support_core_utils', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_swiperefreshlayout': { + 'src/third_party/android_deps/cipd/libs/com_android_support_swiperefreshlayout': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_swiperefreshlayout', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_versionedparcelable': { + 'src/third_party/android_deps/cipd/libs/com_android_support_versionedparcelable': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_versionedparcelable', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_support_viewpager': { + 'src/third_party/android_deps/cipd/libs/com_android_support_viewpager': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_support_viewpager', 'version': 'version:2@28.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_tools_common': { + 'src/third_party/android_deps/cipd/libs/com_android_tools_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_tools_common', 'version': 'version:2@30.2.0-beta01.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_tools_layoutlib_layoutlib_api': { + 'src/third_party/android_deps/cipd/libs/com_android_tools_layoutlib_layoutlib_api': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_tools_layoutlib_layoutlib_api', 'version': 'version:2@30.2.0-beta01.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_android_tools_sdk_common': { + 'src/third_party/android_deps/cipd/libs/com_android_tools_sdk_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_android_tools_sdk_common', 'version': 'version:2@30.2.0-beta01.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_github_ben_manes_caffeine_caffeine': { + 'src/third_party/android_deps/cipd/libs/com_github_ben_manes_caffeine_caffeine': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_github_ben_manes_caffeine_caffeine', 'version': 'version:2@2.8.8.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_github_kevinstern_software_and_algorithms': { + 'src/third_party/android_deps/cipd/libs/com_github_kevinstern_software_and_algorithms': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_github_kevinstern_software_and_algorithms', 'version': 'version:2@1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_annotations': { + 'src/third_party/android_deps/cipd/libs/com_google_android_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_annotations', 'version': 'version:2@4.1.1.4.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_apps_common_testing_accessibility_framework_accessibility_test_framework': { + 'src/third_party/android_deps/cipd/libs/com_google_android_apps_common_testing_accessibility_framework_accessibility_test_framework': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_apps_common_testing_accessibility_framework_accessibility_test_framework', 'version': 'version:2@4.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_datatransport_transport_api': { + 'src/third_party/android_deps/cipd/libs/com_google_android_datatransport_transport_api': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_datatransport_transport_api', 'version': 'version:2@2.2.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_auth': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_auth': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_auth', 'version': 'version:2@20.1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_auth_api_phone': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone', 'version': 'version:2@18.0.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_auth_base': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base', 'version': 'version:2@18.0.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_base': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_base': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_base', 'version': 'version:2@18.1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_basement': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_basement': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_basement', 'version': 'version:2@18.1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_cast': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_cast': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_cast', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_cast_framework': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_clearcut': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_cloud_messaging': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_cloud_messaging': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_cloud_messaging', 'version': 'version:2@16.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_flags': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_flags': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_flags', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_gcm': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_gcm': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_gcm', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_iid': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_iid': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_iid', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_instantapps': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps', 'version': 'version:2@18.0.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_location': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_location': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_location', 'version': 'version:2@21.0.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_phenotype': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_stats': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_stats': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_stats', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_tasks': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_tasks': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_tasks', 'version': 'version:2@18.0.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_vision': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_vision': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_vision', 'version': 'version:2@20.1.3.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common': { + 'src/third_party/android_deps/cipd/libs/com_google_android_gms_play_services_vision_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common', 'version': 'version:2@19.1.3.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_material_material': { + 'src/third_party/android_deps/cipd/libs/com_google_android_material_material': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_material_material', 'version': 'version:2@1.11.0-beta01.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_play_core_common': { + 'src/third_party/android_deps/cipd/libs/com_google_android_play_core_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_play_core_common', 'version': 'version:2@2.0.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_android_play_feature_delivery': { + 'src/third_party/android_deps/cipd/libs/com_google_android_play_feature_delivery': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_play_feature_delivery', 'version': 'version:2@2.0.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_auto_auto_common': { + 'src/third_party/android_deps/cipd/libs/com_google_auto_auto_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_auto_auto_common', 'version': 'version:2@1.2.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_auto_service_auto_service': { + 'src/third_party/android_deps/cipd/libs/com_google_auto_service_auto_service': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_auto_service_auto_service', 'version': 'version:2@1.0-rc6.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_auto_service_auto_service_annotations': { + 'src/third_party/android_deps/cipd/libs/com_google_auto_service_auto_service_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_auto_service_auto_service_annotations', 'version': 'version:2@1.0-rc6.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_auto_value_auto_value_annotations': { + 'src/third_party/android_deps/cipd/libs/com_google_auto_value_auto_value_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_auto_value_auto_value_annotations', 'version': 'version:2@1.10.4.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_code_findbugs_jsr305': { + 'src/third_party/android_deps/cipd/libs/com_google_code_findbugs_jsr305': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_code_findbugs_jsr305', 'version': 'version:2@3.0.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_code_gson_gson': { + 'src/third_party/android_deps/cipd/libs/com_google_code_gson_gson': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_code_gson_gson', 'version': 'version:2@2.9.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_dagger_dagger': { + 'src/third_party/android_deps/cipd/libs/com_google_dagger_dagger': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_dagger_dagger', 'version': 'version:2@2.30.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_dagger_dagger_compiler': { + 'src/third_party/android_deps/cipd/libs/com_google_dagger_dagger_compiler': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_dagger_dagger_compiler', 'version': 'version:2@2.30.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_dagger_dagger_producers': { + 'src/third_party/android_deps/cipd/libs/com_google_dagger_dagger_producers': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_dagger_dagger_producers', 'version': 'version:2@2.30.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_dagger_dagger_spi': { + 'src/third_party/android_deps/cipd/libs/com_google_dagger_dagger_spi': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_dagger_dagger_spi', 'version': 'version:2@2.30.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_errorprone_error_prone_annotation': { + 'src/third_party/android_deps/cipd/libs/com_google_errorprone_error_prone_annotation': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_errorprone_error_prone_annotation', 'version': 'version:2@2.19.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations': { + 'src/third_party/android_deps/cipd/libs/com_google_errorprone_error_prone_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations', 'version': 'version:2@2.23.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_errorprone_error_prone_check_api': { + 'src/third_party/android_deps/cipd/libs/com_google_errorprone_error_prone_check_api': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_errorprone_error_prone_check_api', 'version': 'version:2@2.11.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_errorprone_error_prone_core': { + 'src/third_party/android_deps/cipd/libs/com_google_errorprone_error_prone_core': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_errorprone_error_prone_core', 'version': 'version:2@2.11.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_errorprone_error_prone_type_annotations': { + 'src/third_party/android_deps/cipd/libs/com_google_errorprone_error_prone_type_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_errorprone_error_prone_type_annotations', 'version': 'version:2@2.11.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_errorprone_javac': { + 'src/third_party/android_deps/cipd/libs/com_google_errorprone_javac': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_errorprone_javac', 'version': 'version:2@9+181-r4173-1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_errorprone_javac_shaded': { + 'src/third_party/android_deps/cipd/libs/com_google_errorprone_javac_shaded': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_errorprone_javac_shaded', 'version': 'version:2@9-dev-r4023-3.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_annotations': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_annotations', 'version': 'version:2@16.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_common': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_common': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_common', 'version': 'version:2@19.5.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_components': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_components': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_components', 'version': 'version:2@16.1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_encoders': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_encoders': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_encoders', 'version': 'version:2@16.1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_encoders_json': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_encoders_json': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_encoders_json', 'version': 'version:2@17.1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_iid': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_iid': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_iid', 'version': 'version:2@21.0.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_iid_interop': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_iid_interop': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_iid_interop', 'version': 'version:2@17.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_installations': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_installations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_installations', 'version': 'version:2@16.3.5.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_installations_interop': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_installations_interop': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_installations_interop', 'version': 'version:2@16.0.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_measurement_connector': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_measurement_connector': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_measurement_connector', 'version': 'version:2@18.0.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_firebase_firebase_messaging': { + 'src/third_party/android_deps/cipd/libs/com_google_firebase_firebase_messaging': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_firebase_firebase_messaging', 'version': 'version:2@21.0.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_googlejavaformat_google_java_format': { + 'src/third_party/android_deps/cipd/libs/com_google_googlejavaformat_google_java_format': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_googlejavaformat_google_java_format', 'version': 'version:2@1.5.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_guava_failureaccess': { + 'src/third_party/android_deps/cipd/libs/com_google_guava_failureaccess': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_guava_failureaccess', 'version': 'version:2@1.0.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_guava_guava': { + 'src/third_party/android_deps/cipd/libs/com_google_guava_guava': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_guava_guava', 'version': 'version:2@32.1.3-jre.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_guava_guava_android': { + 'src/third_party/android_deps/cipd/libs/com_google_guava_guava_android': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_guava_guava_android', 'version': 'version:2@32.1.3-android.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_j2objc_j2objc_annotations': { + 'src/third_party/android_deps/cipd/libs/com_google_j2objc_j2objc_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_j2objc_j2objc_annotations', 'version': 'version:2@2.8.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_protobuf_protobuf_java': { + 'src/third_party/android_deps/cipd/libs/com_google_protobuf_protobuf_java': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_protobuf_protobuf_java', 'version': 'version:2@3.19.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_google_protobuf_protobuf_javalite': { + 'src/third_party/android_deps/cipd/libs/com_google_protobuf_protobuf_javalite': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_protobuf_protobuf_javalite', 'version': 'version:2@3.21.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_googlecode_java_diff_utils_diffutils': { + 'src/third_party/android_deps/cipd/libs/com_googlecode_java_diff_utils_diffutils': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_googlecode_java_diff_utils_diffutils', 'version': 'version:2@1.3.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_squareup_javapoet': { + 'src/third_party/android_deps/cipd/libs/com_squareup_javapoet': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_squareup_javapoet', 'version': 'version:2@1.13.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_squareup_javawriter': { + 'src/third_party/android_deps/cipd/libs/com_squareup_javawriter': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_squareup_javawriter', 'version': 'version:2@2.1.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_squareup_moshi_moshi': { + 'src/third_party/android_deps/cipd/libs/com_squareup_moshi_moshi': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_squareup_moshi_moshi', 'version': 'version:2@1.15.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_squareup_moshi_moshi_adapters': { + 'src/third_party/android_deps/cipd/libs/com_squareup_moshi_moshi_adapters': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_squareup_moshi_moshi_adapters', 'version': 'version:2@1.15.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_squareup_okio_okio_jvm': { + 'src/third_party/android_deps/cipd/libs/com_squareup_okio_okio_jvm': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_squareup_okio_okio_jvm', 'version': 'version:2@3.7.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/com_squareup_wire_wire_runtime_jvm': { + 'src/third_party/android_deps/cipd/libs/com_squareup_wire_wire_runtime_jvm': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_squareup_wire_wire_runtime_jvm', 'version': 'version:2@4.9.7.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/io_github_java_diff_utils_java_diff_utils': { + 'src/third_party/android_deps/cipd/libs/io_github_java_diff_utils_java_diff_utils': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/io_github_java_diff_utils_java_diff_utils', 'version': 'version:2@4.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/io_grpc_grpc_api': { + 'src/third_party/android_deps/cipd/libs/io_grpc_grpc_api': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/io_grpc_grpc_api', 'version': 'version:2@1.49.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/io_grpc_grpc_binder': { + 'src/third_party/android_deps/cipd/libs/io_grpc_grpc_binder': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/io_grpc_grpc_binder', 'version': 'version:2@1.49.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/io_grpc_grpc_context': { + 'src/third_party/android_deps/cipd/libs/io_grpc_grpc_context': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/io_grpc_grpc_context', 'version': 'version:2@1.49.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/io_grpc_grpc_core': { + 'src/third_party/android_deps/cipd/libs/io_grpc_grpc_core': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/io_grpc_grpc_core', 'version': 'version:2@1.49.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/io_grpc_grpc_protobuf_lite': { + 'src/third_party/android_deps/cipd/libs/io_grpc_grpc_protobuf_lite': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/io_grpc_grpc_protobuf_lite', 'version': 'version:2@1.49.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/io_grpc_grpc_stub': { + 'src/third_party/android_deps/cipd/libs/io_grpc_grpc_stub': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/io_grpc_grpc_stub', 'version': 'version:2@1.49.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/io_perfmark_perfmark_api': { + 'src/third_party/android_deps/cipd/libs/io_perfmark_perfmark_api': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/io_perfmark_perfmark_api', 'version': 'version:2@0.25.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/javax_annotation_javax_annotation_api': { + 'src/third_party/android_deps/cipd/libs/javax_annotation_javax_annotation_api': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/javax_annotation_javax_annotation_api', 'version': 'version:2@1.3.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/javax_annotation_jsr250_api': { + 'src/third_party/android_deps/cipd/libs/javax_annotation_jsr250_api': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/javax_annotation_jsr250_api', 'version': 'version:2@1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/javax_inject_javax_inject': { + 'src/third_party/android_deps/cipd/libs/javax_inject_javax_inject': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/javax_inject_javax_inject', 'version': 'version:2@1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/net_bytebuddy_byte_buddy': { + 'src/third_party/android_deps/cipd/libs/net_bytebuddy_byte_buddy': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy', 'version': 'version:2@1.14.12.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/net_bytebuddy_byte_buddy_agent': { + 'src/third_party/android_deps/cipd/libs/net_bytebuddy_byte_buddy_agent': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy_agent', 'version': 'version:2@1.14.12.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/net_ltgt_gradle_incap_incap': { + 'src/third_party/android_deps/cipd/libs/net_ltgt_gradle_incap_incap': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/net_ltgt_gradle_incap_incap', 'version': 'version:2@0.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_bouncycastle_bcprov_jdk18on': { + 'src/third_party/android_deps/cipd/libs/org_bouncycastle_bcprov_jdk18on': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_bouncycastle_bcprov_jdk18on', 'version': 'version:2@1.77.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_ccil_cowan_tagsoup_tagsoup': { + 'src/third_party/android_deps/cipd/libs/org_ccil_cowan_tagsoup_tagsoup': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ccil_cowan_tagsoup_tagsoup', 'version': 'version:2@1.2.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_checkerframework_checker_compat_qual': { + 'src/third_party/android_deps/cipd/libs/org_checkerframework_checker_compat_qual': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_checkerframework_checker_compat_qual', 'version': 'version:2@2.5.5.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_checkerframework_checker_qual': { + 'src/third_party/android_deps/cipd/libs/org_checkerframework_checker_qual': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_checkerframework_checker_qual', 'version': 'version:2@3.37.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_checkerframework_checker_util': { + 'src/third_party/android_deps/cipd/libs/org_checkerframework_checker_util': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_checkerframework_checker_util', 'version': 'version:2@3.25.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_checkerframework_dataflow_errorprone': { + 'src/third_party/android_deps/cipd/libs/org_checkerframework_dataflow_errorprone': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_checkerframework_dataflow_errorprone', 'version': 'version:2@3.15.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_codehaus_mojo_animal_sniffer_annotations': { + 'src/third_party/android_deps/cipd/libs/org_codehaus_mojo_animal_sniffer_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_codehaus_mojo_animal_sniffer_annotations', 'version': 'version:2@1.21.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_conscrypt_conscrypt_openjdk_uber': { + 'src/third_party/android_deps/cipd/libs/org_conscrypt_conscrypt_openjdk_uber': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_conscrypt_conscrypt_openjdk_uber', 'version': 'version:2@2.5.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_eclipse_jgit_org_eclipse_jgit': { + 'src/third_party/android_deps/cipd/libs/org_eclipse_jgit_org_eclipse_jgit': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_eclipse_jgit_org_eclipse_jgit', 'version': 'version:2@4.4.1.201607150455-r.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_hamcrest_hamcrest': { + 'src/third_party/android_deps/cipd/libs/org_hamcrest_hamcrest': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_hamcrest_hamcrest', 'version': 'version:2@2.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime', 'version': 'version:2@1.9.22.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime', 'version': 'version:2@1.9.22.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7', 'version': 'version:2@1.8.20.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk8': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk8': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk8', 'version': 'version:2@1.8.20.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_atomicfu_jvm': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm', 'version': 'version:2@0.23.2.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android', 'version': 'version:2@1.6.4.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_core_jvm', 'version': 'version:2@1.6.4.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_guava', 'version': 'version:2@1.6.4.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_metadata_jvm': { + 'src/third_party/android_deps/cipd/libs/org_jetbrains_kotlinx_kotlinx_metadata_jvm': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_metadata_jvm', 'version': 'version:2@0.1.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_jsoup_jsoup': { + 'src/third_party/android_deps/cipd/libs/org_jsoup_jsoup': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jsoup_jsoup', 'version': 'version:2@1.15.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_mockito_mockito_android': { + 'src/third_party/android_deps/cipd/libs/org_mockito_mockito_android': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_android', 'version': 'version:2@5.11.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_mockito_mockito_core': { + 'src/third_party/android_deps/cipd/libs/org_mockito_mockito_core': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_core', 'version': 'version:2@5.11.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_mockito_mockito_subclass': { + 'src/third_party/android_deps/cipd/libs/org_mockito_mockito_subclass': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_subclass', 'version': 'version:2@5.11.0.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_objenesis_objenesis': { + 'src/third_party/android_deps/cipd/libs/org_objenesis_objenesis': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_objenesis_objenesis', 'version': 'version:2@3.3.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_ow2_asm_asm': { + 'src/third_party/android_deps/cipd/libs/org_ow2_asm_asm': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm', 'version': 'version:2@9.7.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_ow2_asm_asm_analysis': { + 'src/third_party/android_deps/cipd/libs/org_ow2_asm_asm_analysis': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_analysis', 'version': 'version:2@9.7.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_ow2_asm_asm_commons': { + 'src/third_party/android_deps/cipd/libs/org_ow2_asm_asm_commons': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_commons', 'version': 'version:2@9.7.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_ow2_asm_asm_tree': { + 'src/third_party/android_deps/cipd/libs/org_ow2_asm_asm_tree': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_tree', 'version': 'version:2@9.7.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_ow2_asm_asm_util': { + 'src/third_party/android_deps/cipd/libs/org_ow2_asm_asm_util': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_util', 'version': 'version:2@9.7.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_pcollections_pcollections': { + 'src/third_party/android_deps/cipd/libs/org_pcollections_pcollections': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_pcollections_pcollections', 'version': 'version:2@3.1.4.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_annotations': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_annotations': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_annotations', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_junit': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_junit': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_junit', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_nativeruntime': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_nativeruntime': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_nativeruntime', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_nativeruntime_dist_compat': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_nativeruntime_dist_compat': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_nativeruntime_dist_compat', 'version': 'version:2@1.0.9.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_pluginapi': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_pluginapi': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_pluginapi', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_plugins_maven_dependency_resolver': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_plugins_maven_dependency_resolver': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_plugins_maven_dependency_resolver', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_resources': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_resources': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_resources', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_robolectric': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_robolectric': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_robolectric', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_sandbox': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_sandbox': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_sandbox', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_shadowapi': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_shadowapi': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_shadowapi', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_shadows_framework': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_shadows_framework': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_shadows_framework', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_shadows_versioning': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_shadows_versioning': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_shadows_versioning', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_utils': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_utils': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_utils', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/org_robolectric_utils_reflector': { + 'src/third_party/android_deps/cipd/libs/org_robolectric_utils_reflector': { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_utils_reflector', 'version': 'version:2@4.12.1.cr1', }, ], - 'condition': 'checkout_android', + 'condition': 'checkout_android and non_git_source', 'dep_type': 'cipd', }, @@ -4476,22 +4530,16 @@ deps = { # Dependencies from src_internal 'src/chromeos/ash/resources/internal': { 'url': Var('chrome_git') + '/chrome/chromeos/ash/resources/internal.git' + '@' + - '17bf44b4f03344c069d218dbb7b4bec9467d182d', + 'd3a9fae91a30293f1e28a9fc647972e7e2ac45f5', 'condition': 'checkout_src_internal and checkout_chromeos', }, 'src/chromeos/assistant/internal': { 'url': Var('chrome_git') + '/chrome/assistant.git' + '@' + - '5885da7fd3b1622325506bc2d4468cd95195366f', + '99deb76682f8bf5fb1d0b7229f18ef110dbba92d', 'condition': 'checkout_src_internal and checkout_chromeos', }, - 'src/ash/webui/conch': { - 'url': Var('chrome_git') + '/ash/webui/conch.git' + '@' + - 'a392942d0ed65999f48d5df9e66f1ccec5e03eb1', - 'condition': 'checkout_src_internal and checkout_chromeos', - }, - 'src/ui/gl/resources/angle-metal': { 'packages': [{ 'package': 'chromium/gpu/angle-metal-shader-libraries', @@ -4557,7 +4605,13 @@ deps = { 'src/chrome/browser/platform_experience/win': { 'url': Var('chrome_git') + '/chrome/browser/platform_experience/win.git' + '@' + - '50d041ad6372254b4a8f90b76ea58d0b2b5847b4', + 'c8ae639df9ebb018ac5793fc76c1a4e74787112e', + 'condition': 'checkout_src_internal', + }, + + 'src/chrome/browser/request_header_integrity/internal': { + 'url': Var('chrome_git') + '/chrome/browser/request_header_integrity/internal.git' + '@' + + 'd8c364e3d61da496b725fc8db66e9c079a12de9c', 'condition': 'checkout_src_internal', }, @@ -4569,7 +4623,7 @@ deps = { 'src/chrome/browser/resources/settings/internal': { 'url': Var('chrome_git') + '/chrome/browser/resources/settings_internal.git' + '@' + - '2735f17dcd23dba5f7564e54a8e82fee3368a7ad', # from svn revision 41419 + '55d878306e9b97e03f8abc9df6b17daafd42d2e0', # from svn revision 41419 'condition': 'checkout_src_internal', }, @@ -4583,7 +4637,7 @@ deps = { 'packages' : [ { 'package': 'chromeos_internal/inputs/orca', - 'version': 'BlK9M7Mo_MyZC1SNq90Xk6hFKnoOY5AiT3Sbrl9K4LAC' + 'version': '9lRnWbSgGutEjzY_mwrpqzhlMsl44e3hxDktHxiSByMC' } ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4611,7 +4665,7 @@ deps = { # grepping. 'src/chrome/installer/mac/internal': { 'url': Var('chrome_git') + '/chrome/installer/mac/internal.git' + '@' + - '504e608fba2b504f8dedbb66bf436b14dc62851d', + '074535931aa25dad3ad08811e2126521f38b10de', 'condition': 'checkout_src_internal', }, @@ -4664,13 +4718,25 @@ deps = { }, 'src/chrome/services/speech/internal': { - 'url': Var('chrome_git') + '/chromeos/speech.git' + '@' + '27f567e38ad88b28bde05ee2d7e3d788acb9191f', + 'url': Var('chrome_git') + '/chromeos/speech.git' + '@' + '917c83b7c79126906c5d19668256b9d9139a0e71', 'condition': 'checkout_chromeos and checkout_src_internal', }, + 'src/chrome/updater/internal': { + 'url': Var('chrome_git') + '/chrome/updater/internal.git' + '@' + + '84d54a3483d304c84d6e39d4b2c4e467dfd616ed', + 'condition': 'checkout_src_internal', + }, + + 'src/components/accessibility/internal': { + 'url': Var('chrome_git') + '/chrome-accessibility.git' + '@' + + '3c105c67495263fc5c4dc829892785976e8214ae', + 'condition': 'checkout_src_internal', + }, + 'src/components/autofill/core/browser/form_parsing/internal_resources': { 'url': Var('chrome_git') + '/chrome/components/autofill_regex_patterns.git' + '@' + - 'feb267b80dd9df83ce4949470d5b1cc6214cd775', + '6207ca1a2abd6d4cf18f7725e4554bb485632dad', 'condition': 'checkout_src_internal', }, @@ -4693,13 +4759,13 @@ deps = { 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - '7521f446d4f643c0d1fedef780584f4784d5b198', + '27c76a4fcf19141efb5a888625be60aa50a0399d', 'condition': 'checkout_src_internal', }, 'src/components/plus_addresses/resources/internal': { 'url': Var('chrome_git') + '/chrome/components/plus_addresses/resources.git' + '@' + - '4f595c87a18088bf7c43613ebae849f23559f725', + '5dd0c0e18dbef80c05ac8e2cdb9f91246936f235', 'condition': 'checkout_src_internal', }, @@ -4729,13 +4795,13 @@ deps = { 'src/components/test/data/autofill/heuristics-json/internal': { 'url': Var('chrome_git') + '/chrome/test/autofill/structured_forms.git' + '@' + - '9003254f2582c512a366eac433e7f5c321913a95', + 'fdc4a9d5020c357bbe990522c1ca1e646fe00379', 'condition': 'checkout_chromium_autofill_test_dependencies', }, 'src/components/vector_icons/google_chrome': { 'url': Var('chrome_git') + '/chrome/vector_icons/google_chrome.git' + '@' + - '9bb1e6ad61614f0cdea0a9176ce31ba1c381ef7e', + 'ecad7931572c1f673bf582b785838daadbaadfab', 'condition': 'checkout_src_internal', }, @@ -4753,7 +4819,7 @@ deps = { 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - 'b2d35187a718f91fe19f22741b15b7a5174a0af2', + 'f8c506ff321b7d47c057594af51699895725bbc3', 'condition': 'checkout_ios and checkout_src_internal', }, @@ -4805,25 +4871,11 @@ deps = { 'condition': 'checkout_android and checkout_src_internal', }, - # OpenGL ES 2.0 Conformance tests. - 'src/third_party/gles2_conform': { - 'url': Var('chrome_git') + '/chrome/deps/gles2_conform.git' + '@' + - '57738bb2cc672cb81ed2ee287fcd0defde968811', - 'condition': 'checkout_src_internal', - }, - - # OpenGL ES 3.X Conformance tests. - 'src/third_party/khronos_glcts': { - 'url': Var('chrome_git') + '/chrome/deps/khronos_glcts.git' + '@' + - 'eedb0baca9e88c53596874901ff5f6136102d20d', - 'condition': 'checkout_src_internal', - }, - 'src/third_party/libassistant/x64': { 'packages': [ { - 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_device/x64/internal', - 'version': 'sQlpA8YX9xqenXh1shzWPTjO-UbfG8RZBdjG4Bq6_JEC', + 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_device/x86_64/internal', + 'version': 'CmuG4T_84hgqYyVPLppHO_cYpXPoYIFpJNT5wC5iGZgC', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4834,7 +4886,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_device/arm64/internal', - 'version': 'jBi2aiKUgOIsm4EySOUEOYcZVx1_vGQKdX624Sn7--cC', + 'version': '0gwaQvw-4Jne1dvCdVsGRVHcADdvSLBy172ar-FFyIoC', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4845,7 +4897,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_device/arm/internal', - 'version': 'p4h4yK1oeCIH1yXn637uVBIZ82hFnGinKrdn4EZ9L8QC', + 'version': 'bLW45XE7O8kCndjxEYtqdupr0tV4mgB7xKkcETBOsskC', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4856,7 +4908,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_glinux/x64/internal', - 'version': 'vsmFJIFJr5245jA8Zz67H6mJFahlkhwf_AYa00ay5fkC', + 'version': '3Opw5sw239P8B6hdZCofFV_16gGsW5nJbuoA93doiAkC', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4867,7 +4919,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/fake_s3_server_cros_glinux/x64/internal', - 'version': '_9aXc-Ngn6ckUP5OFPt55-pAyP6Wgg0eiSKZaoN1LLAC', + 'version': '7BVkGvAvW0XDvbHj3P4-e6TAxssx6_PC2L0eQBLWyP8C', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4981,19 +5033,19 @@ deps = { 'src/third_party/widevine/cdm/linux': { 'url': Var('chrome_git') + '/chrome/deps/widevine/cdm/linux.git' + '@' + - 'a491291d608cdb117f2d1e449e8c9b44a0173548', + 'a7112e9c9e97711f5f8ec5d2ec2ad21fd5ab88e0', 'condition': 'checkout_linux and checkout_src_internal', }, 'src/third_party/widevine/cdm/mac': { 'url': Var('chrome_git') + '/chrome/deps/widevine/cdm/mac.git' + '@' + - '2796e8b7ae5cb53ffa9711fdca1cd4247a1f3968', + '2d33c009716adffeab29445a1d237bf54d0de6eb', 'condition': 'checkout_mac and checkout_src_internal', }, 'src/third_party/widevine/cdm/win': { 'url': Var('chrome_git') + '/chrome/deps/widevine/cdm/win.git' + '@' + - '4f0b47c1af51699e62344d055b1a6d61f87aec13', + '0d0174461e77947dc68bd96016cbccf41c9754c6', 'condition': 'checkout_win and checkout_src_internal', }, @@ -5174,6 +5226,7 @@ hooks = [ 'python3', 'src/tools/remove_stale_files.py', 'src/third_party/test_fonts/test_fonts.tar.gz', # Remove after 20240901 + 'src/third_party/node/node_modules.tar.gz', # TODO: Remove after 20241201, see https://crbug.com/351092787 ], }, { @@ -5364,20 +5417,6 @@ hooks = [ ], }, - # Pull down NPM dependencies for WebUI toolchain. - { - 'name': 'webui_node_modules', - 'pattern': '.', - 'action': [ 'python3', - 'src/third_party/depot_tools/download_from_google_storage.py', - '--no_resume', - '--extract', - '--no_auth', - '--bucket', 'chromium-nodejs', - '-s', 'src/third_party/node/node_modules.tar.gz.sha1', - ], - }, - # Download Telemetry's binary dependencies via conditionals { 'name': 'checkout_telemetry_binary_dependencies', @@ -5523,18 +5562,6 @@ hooks = [ '--gs_url_base=chromeos-prebuilt/afdo-job/vetted/release', ], }, - { - 'name': 'Fetch ChromeOS AFDO profiles (experimental Arm profile)', - 'pattern': '.', - 'condition': 'checkout_chromeos or checkout_simplechrome', - 'action': [ 'python3', - 'src/tools/download_optimization_profile.py', - '--newest_state=src/chromeos/profiles/arm-exp.afdo.newest.txt', - '--local_state=src/chromeos/profiles/arm-exp.afdo.local.txt', - '--output_name=src/chromeos/profiles/arm-exp.afdo.prof', - '--gs_url_base=chromeos-prebuilt/afdo-job/vetted/release', - ], - }, { # Pull doclava binaries if building for Android. 'name': 'doclava', diff --git a/naiveproxy/src/base/BUILD.gn b/naiveproxy/src/base/BUILD.gn index 66222309f3..4ebe349993 100644 --- a/naiveproxy/src/base/BUILD.gn +++ b/naiveproxy/src/base/BUILD.gn @@ -168,12 +168,6 @@ if (is_fuchsia) { } } -if (enable_pkeys && is_debug) { - config("no_stack_protector") { - cflags = [ "-fno-stack-protector" ] - } -} - buildflag_header("ios_cronet_buildflags") { header = "ios_cronet_buildflags.h" header_dir = "base/message_loop" @@ -276,6 +270,7 @@ component("base") { "containers/map_util.h", "containers/small_map.h", "containers/span.h", + "containers/span_or_size.h", "containers/span_reader.h", "containers/span_writer.h", "containers/stack.h", @@ -576,6 +571,8 @@ component("base") { "profiler/stack_sampler.h", "profiler/stack_sampling_profiler.cc", "profiler/stack_sampling_profiler.h", + "profiler/stack_unwind_data.cc", + "profiler/stack_unwind_data.h", "profiler/suspendable_thread_delegate.h", "profiler/thread_delegate.h", "profiler/unwinder.cc", @@ -583,6 +580,7 @@ component("base") { "rand_util.cc", "rand_util.h", "ranges/algorithm.h", + "ranges/from_range.h", "ranges/functional.h", "ranges/ranges.h", "run_loop.cc", @@ -629,7 +627,6 @@ component("base") { "strings/string_number_conversions.cc", "strings/string_number_conversions.h", "strings/string_number_conversions_internal.h", - "strings/string_piece.h", "strings/string_split.cc", "strings/string_split.h", "strings/string_split_internal.h", @@ -825,7 +822,6 @@ component("base") { "task/thread_pool/worker_thread_waitable_event.cc", "task/thread_pool/worker_thread_waitable_event.h", "task/updateable_sequenced_task_runner.h", - "template_util.h", "test/scoped_logging_settings.h", "test/spin_wait.h", "third_party/cityhash/city.cc", @@ -1063,6 +1059,10 @@ component("base") { "//build/config/compiler:compiler_buildflags", "//third_party/modp_b64", ] + if (!is_nacl) { + # Used by metrics/crc32, except on NaCl builds. + deps += [ "//third_party/zlib" ] + } # `raw_ptr` cannot be made a component due to CRT symbol issues. # Its gateway to being a component is through `//base`, so we have @@ -1110,7 +1110,7 @@ component("base") { ] # Base provides conversions between CXX types and base types (e.g. - # StringPiece). + # std::string_view). public_deps += [ "//build/rust:cxx_cppdeps" ] } @@ -1265,7 +1265,6 @@ component("base") { "android/jni_string.h", "android/jni_utils.cc", "android/jni_utils.h", - "android/jni_weak_ref.cc", "android/jni_weak_ref.h", "android/library_loader/library_loader_hooks.cc", "android/library_loader/library_loader_hooks.h", @@ -1282,6 +1281,17 @@ component("base") { public_deps += [ "//third_party/jni_zero:jni_zero" ] } # is_android || is_robolectric + if (is_android && !is_robolectric) { + # The robolectic toolchain doesn't provide the NDK headers required for data + # and function type definitions used by BinderApi et al. + sources += [ + "android/binder.cc", + "android/binder.h", + "android/binder_box.cc", + "android/binder_box.h", + ] + } + # Chromeos. if (is_chromeos) { sources += [ @@ -2517,7 +2527,7 @@ buildflag_header("protected_memory_buildflags") { header_dir = "base/memory" # Currently Protected Memory is only supported on Windows. - protected_memory_enabled = is_win + protected_memory_enabled = !is_component_build && is_win flags = [ "PROTECTED_MEMORY_ENABLED=$protected_memory_enabled" ] } @@ -2560,6 +2570,8 @@ buildflag_header("sanitizer_buildflags") { flags = [ "IS_HWASAN=$is_hwasan", + "IS_UBSAN=$is_ubsan", + "IS_UBSAN_SECURITY=$is_ubsan_security", "USING_SANITIZER=$using_sanitizer", ] } diff --git a/naiveproxy/src/base/DEPS b/naiveproxy/src/base/DEPS index 98a3e6b1ec..3294fba384 100644 --- a/naiveproxy/src/base/DEPS +++ b/naiveproxy/src/base/DEPS @@ -25,6 +25,7 @@ include_rules = [ "+third_party/test_fonts", # JSON Deserialization. "+third_party/rust/serde_json_lenient/v0_2/wrapper", + "+third_party/zlib", # These are implicitly brought in from the root, and we don't want them. "-ipc", diff --git a/naiveproxy/src/base/allocator/OWNERS b/naiveproxy/src/base/allocator/OWNERS index e27d563cac..d6c29b23c1 100644 --- a/naiveproxy/src/base/allocator/OWNERS +++ b/naiveproxy/src/base/allocator/OWNERS @@ -1,5 +1,4 @@ lizeb@chromium.org -primiano@chromium.org wfh@chromium.org per-file allocator.gni=file://base/allocator/partition_allocator/OWNERS diff --git a/naiveproxy/src/base/allocator/allocator_check.cc b/naiveproxy/src/base/allocator/allocator_check.cc index a993747fcc..59e41bda88 100644 --- a/naiveproxy/src/base/allocator/allocator_check.cc +++ b/naiveproxy/src/base/allocator/allocator_check.cc @@ -5,7 +5,7 @@ #include "base/allocator/allocator_check.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if BUILDFLAG(IS_WIN) #include "partition_alloc/shim/winheap_stubs_win.h" diff --git a/naiveproxy/src/base/allocator/dispatcher/dispatcher.cc b/naiveproxy/src/base/allocator/dispatcher/dispatcher.cc index 2c5dfc7870..3e47d1f5d3 100644 --- a/naiveproxy/src/base/allocator/dispatcher/dispatcher.cc +++ b/naiveproxy/src/base/allocator/dispatcher/dispatcher.cc @@ -8,7 +8,7 @@ #include "base/check.h" #include "base/dcheck_is_on.h" #include "base/no_destructor.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/shim/allocator_shim.h" #if DCHECK_IS_ON() diff --git a/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.cc b/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.cc index 6ea80eb089..c27ca912de 100644 --- a/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.cc +++ b/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.cc @@ -3,7 +3,8 @@ // found in the LICENSE file. #include "base/allocator/dispatcher/internal/dispatch_data.h" -#include "partition_alloc/partition_alloc_buildflags.h" + +#include "partition_alloc/buildflags.h" namespace base::allocator::dispatcher::internal { diff --git a/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.h b/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.h index 3c1b24c117..6619470022 100644 --- a/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.h +++ b/naiveproxy/src/base/allocator/dispatcher/internal/dispatch_data.h @@ -7,7 +7,7 @@ #include "base/base_export.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_PARTITION_ALLOC) #include "partition_alloc/partition_alloc_hooks.h" diff --git a/naiveproxy/src/base/allocator/dispatcher/internal/dispatcher_internal.h b/naiveproxy/src/base/allocator/dispatcher/internal/dispatcher_internal.h index 1db681a40f..aeed29ca73 100644 --- a/naiveproxy/src/base/allocator/dispatcher/internal/dispatcher_internal.h +++ b/naiveproxy/src/base/allocator/dispatcher/internal/dispatcher_internal.h @@ -13,7 +13,7 @@ #include "base/allocator/dispatcher/subsystem.h" #include "base/check.h" #include "base/compiler_specific.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_PARTITION_ALLOC) #include "partition_alloc/partition_alloc_allocation_data.h" @@ -184,6 +184,20 @@ struct DispatcherImpl { return reallocated_address; } + static void* ReallocUncheckedFn(const AllocatorDispatch* self, + void* address, + size_t size, + void* context) { + // Note: size == 0 actually performs free. + DoNotifyFreeForShim(address); + void* const reallocated_address = self->next->realloc_unchecked_function( + self->next, address, size, context); + + DoNotifyAllocationForShim(reallocated_address, size); + + return reallocated_address; + } + static void FreeFn(const AllocatorDispatch* self, void* address, void* context) { @@ -193,7 +207,7 @@ struct DispatcherImpl { // the address becomes available and can be allocated by another thread. // That would be racy otherwise. DoNotifyFreeForShim(address); - self->next->free_function(self->next, address, context); + MUSTTAIL return self->next->free_function(self->next, address, context); } static unsigned BatchMallocFn(const AllocatorDispatch* self, @@ -217,8 +231,8 @@ struct DispatcherImpl { DoNotifyFreeForShim(to_be_freed[i]); } - self->next->batch_free_function(self->next, to_be_freed, num_to_be_freed, - context); + MUSTTAIL return self->next->batch_free_function(self->next, to_be_freed, + num_to_be_freed, context); } static void FreeDefiniteSizeFn(const AllocatorDispatch* self, @@ -226,14 +240,16 @@ struct DispatcherImpl { size_t size, void* context) { DoNotifyFreeForShim(address); - self->next->free_definite_size_function(self->next, address, size, context); + MUSTTAIL return self->next->free_definite_size_function(self->next, address, + size, context); } static void TryFreeDefaultFn(const AllocatorDispatch* self, void* address, void* context) { DoNotifyFreeForShim(address); - self->next->try_free_default_function(self->next, address, context); + MUSTTAIL return self->next->try_free_default_function(self->next, address, + context); } static void* AlignedMallocFn(const AllocatorDispatch* self, @@ -248,6 +264,18 @@ struct DispatcherImpl { return address; } + static void* AlignedMallocUncheckedFn(const AllocatorDispatch* self, + size_t size, + size_t alignment, + void* context) { + void* const address = self->next->aligned_malloc_unchecked_function( + self->next, size, alignment, context); + + DoNotifyAllocationForShim(address, size); + + return address; + } + static void* AlignedReallocFn(const AllocatorDispatch* self, void* address, size_t size, @@ -263,11 +291,27 @@ struct DispatcherImpl { return address; } + static void* AlignedReallocUncheckedFn(const AllocatorDispatch* self, + void* address, + size_t size, + size_t alignment, + void* context) { + // Note: size == 0 actually performs free. + DoNotifyFreeForShim(address); + address = self->next->aligned_realloc_unchecked_function( + self->next, address, size, alignment, context); + + DoNotifyAllocationForShim(address, size); + + return address; + } + static void AlignedFreeFn(const AllocatorDispatch* self, void* address, void* context) { DoNotifyFreeForShim(address); - self->next->aligned_free_function(self->next, address, context); + MUSTTAIL return self->next->aligned_free_function(self->next, address, + context); } ALWAYS_INLINE static void DoNotifyAllocationForShim(void* address, @@ -308,23 +352,26 @@ std::tuple DispatcherImpl::s_observers; #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) template AllocatorDispatch DispatcherImpl::allocator_dispatch_ = { - AllocFn, // alloc_function - AllocUncheckedFn, // alloc_unchecked_function - AllocZeroInitializedFn, // alloc_zero_initialized_function - AllocAlignedFn, // alloc_aligned_function - ReallocFn, // realloc_function - FreeFn, // free_function - nullptr, // get_size_estimate_function - nullptr, // good_size_function - nullptr, // claimed_address_function - BatchMallocFn, // batch_malloc_function - BatchFreeFn, // batch_free_function - FreeDefiniteSizeFn, // free_definite_size_function - TryFreeDefaultFn, // try_free_default_function - AlignedMallocFn, // aligned_malloc_function - AlignedReallocFn, // aligned_realloc_function - AlignedFreeFn, // aligned_free_function - nullptr // next + AllocFn, // alloc_function + AllocUncheckedFn, // alloc_unchecked_function + AllocZeroInitializedFn, // alloc_zero_initialized_function + AllocAlignedFn, // alloc_aligned_function + ReallocFn, // realloc_function + ReallocUncheckedFn, // realloc_unchecked_function + FreeFn, // free_function + nullptr, // get_size_estimate_function + nullptr, // good_size_function + nullptr, // claimed_address_function + BatchMallocFn, // batch_malloc_function + BatchFreeFn, // batch_free_function + FreeDefiniteSizeFn, // free_definite_size_function + TryFreeDefaultFn, // try_free_default_function + AlignedMallocFn, // aligned_malloc_function + AlignedMallocUncheckedFn, // aligned_malloc_unchecked_function + AlignedReallocFn, // aligned_realloc_function + AlignedReallocUncheckedFn, // aligned_realloc_unchecked_function + AlignedFreeFn, // aligned_free_function + nullptr // next }; #endif // PA_BUILDFLAG(USE_ALLOCATOR_SHIM) diff --git a/naiveproxy/src/base/allocator/dispatcher/notification_data.h b/naiveproxy/src/base/allocator/dispatcher/notification_data.h index b9adabb5e7..8aa715ea91 100644 --- a/naiveproxy/src/base/allocator/dispatcher/notification_data.h +++ b/naiveproxy/src/base/allocator/dispatcher/notification_data.h @@ -10,7 +10,7 @@ #include "base/allocator/dispatcher/memory_tagging.h" #include "base/allocator/dispatcher/subsystem.h" #include "base/base_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" namespace base::allocator::dispatcher { diff --git a/naiveproxy/src/base/allocator/early_zone_registration_apple.cc b/naiveproxy/src/base/allocator/early_zone_registration_apple.cc index ac912b96fe..702f86f136 100644 --- a/naiveproxy/src/base/allocator/early_zone_registration_apple.cc +++ b/naiveproxy/src/base/allocator/early_zone_registration_apple.cc @@ -7,7 +7,7 @@ #include #include -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/shim/early_zone_registration_constants.h" // BASE_EXPORT tends to be defined as soon as anything from //base is included. diff --git a/naiveproxy/src/base/allocator/partition_alloc_features.cc b/naiveproxy/src/base/allocator/partition_alloc_features.cc index c73a297111..d940748b2c 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_features.cc +++ b/naiveproxy/src/base/allocator/partition_alloc_features.cc @@ -13,8 +13,8 @@ #include "build/build_config.h" #include "build/chromecast_buildflags.h" #include "build/chromeos_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_root.h" #include "partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h" @@ -71,25 +71,7 @@ const base::FeatureParam kDanglingPtrTypeParam{ &kDanglingPtrTypeOption, }; -#if PA_BUILDFLAG(USE_STARSCAN) -// If enabled, PCScan is turned on by default for all partitions that don't -// disable it explicitly. -BASE_FEATURE(kPartitionAllocPCScan, - "PartitionAllocPCScan", - FEATURE_DISABLED_BY_DEFAULT); -#endif // PA_BUILDFLAG(USE_STARSCAN) - #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -// If enabled, PCScan is turned on only for the browser's malloc partition. -BASE_FEATURE(kPartitionAllocPCScanBrowserOnly, - "PartitionAllocPCScanBrowserOnly", - FEATURE_DISABLED_BY_DEFAULT); - -// If enabled, PCScan is turned on only for the renderer's malloc partition. -BASE_FEATURE(kPartitionAllocPCScanRendererOnly, - "PartitionAllocPCScanRendererOnly", - FEATURE_DISABLED_BY_DEFAULT); - // Use a larger maximum thread cache cacheable bucket size. BASE_FEATURE(kPartitionAllocLargeThreadCacheSize, "PartitionAllocLargeThreadCacheSize", @@ -266,37 +248,6 @@ BASE_FEATURE(kLowerPAMemoryLimitForNonMainRenderers, "LowerPAMemoryLimitForNonMainRenderers", FEATURE_DISABLED_BY_DEFAULT); -// If enabled, switches PCScan scheduling to a mutator-aware scheduler. Does not -// affect whether PCScan is enabled itself. -BASE_FEATURE(kPartitionAllocPCScanMUAwareScheduler, - "PartitionAllocPCScanMUAwareScheduler", - FEATURE_ENABLED_BY_DEFAULT); - -// If enabled, PCScan frees unconditionally all quarantined objects. -// This is a performance testing feature. -BASE_FEATURE(kPartitionAllocPCScanImmediateFreeing, - "PartitionAllocPCScanImmediateFreeing", - FEATURE_DISABLED_BY_DEFAULT); - -// If enabled, PCScan clears eagerly (synchronously) on free(). -BASE_FEATURE(kPartitionAllocPCScanEagerClearing, - "PartitionAllocPCScanEagerClearing", - FEATURE_DISABLED_BY_DEFAULT); - -// In addition to heap, scan also the stack of the current mutator. -BASE_FEATURE(kPartitionAllocPCScanStackScanning, - "PartitionAllocPCScanStackScanning", -#if PA_BUILDFLAG(STACK_SCAN_SUPPORTED) - FEATURE_ENABLED_BY_DEFAULT -#else - FEATURE_DISABLED_BY_DEFAULT -#endif // PA_BUILDFLAG(STACK_SCAN_SUPPORTED) -); - -BASE_FEATURE(kPartitionAllocDCScan, - "PartitionAllocDCScan", - FEATURE_DISABLED_BY_DEFAULT); - // Whether to straighten free lists for larger slot spans in PurgeMemory() -> // ... -> PartitionPurgeSlotSpan(). BASE_FEATURE(kPartitionAllocStraightenLargerSlotSpanFreeLists, diff --git a/naiveproxy/src/base/allocator/partition_alloc_features.h b/naiveproxy/src/base/allocator/partition_alloc_features.h index cfe6815c6c..8fd6597eaf 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_features.h +++ b/naiveproxy/src/base/allocator/partition_alloc_features.h @@ -9,11 +9,10 @@ #include "base/compiler_specific.h" #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" -#include "base/strings/string_piece.h" #include "base/time/time.h" #include "build/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_root.h" namespace base { @@ -59,13 +58,7 @@ enum class DanglingPtrType { extern const BASE_EXPORT base::FeatureParam kDanglingPtrTypeParam; -#if PA_BUILDFLAG(USE_STARSCAN) -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScan); -#endif #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanBrowserOnly); -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanRendererOnly); - BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocLargeThreadCacheSize); BASE_EXPORT int GetPartitionAllocLargeThreadCacheSizeValue(); BASE_EXPORT int GetPartitionAllocLargeThreadCacheSizeValueForLowRAMAndroid(); @@ -162,11 +155,6 @@ extern const BASE_EXPORT base::FeatureParam kPartitionAllocBucketDistributionParam; BASE_EXPORT BASE_DECLARE_FEATURE(kLowerPAMemoryLimitForNonMainRenderers); -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanMUAwareScheduler); -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanStackScanning); -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocDCScan); -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanImmediateFreeing); -BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanEagerClearing); BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocUseDenserDistribution); BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocMemoryReclaimer); diff --git a/naiveproxy/src/base/allocator/partition_alloc_support.cc b/naiveproxy/src/base/allocator/partition_alloc_support.cc index f8d54ebe6f..2507f4901c 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_support.cc +++ b/naiveproxy/src/base/allocator/partition_alloc_support.cc @@ -42,12 +42,12 @@ #include "base/trace_event/base_tracing.h" #include "build/build_config.h" #include "partition_alloc/allocation_guard.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/dangling_raw_ptr_checks.h" #include "partition_alloc/memory_reclaimer.h" #include "partition_alloc/page_allocator.h" #include "partition_alloc/partition_alloc_base/debug/alias.h" #include "partition_alloc/partition_alloc_base/threading/platform_thread.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -60,14 +60,6 @@ #include "partition_alloc/stack/stack.h" #include "partition_alloc/thread_cache.h" -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/shim/nonscannable_allocator.h" -#include "partition_alloc/starscan/pcscan.h" -#include "partition_alloc/starscan/pcscan_scheduling.h" -#include "partition_alloc/starscan/stats_collector.h" -#include "partition_alloc/starscan/stats_reporter.h" -#endif // PA_BUILDFLAG(USE_STARSCAN) - #if BUILDFLAG(IS_ANDROID) #include "base/system/sys_info.h" #endif @@ -120,129 +112,10 @@ constexpr base::TimeDelta kFirstPAPurgeOrReclaimDelay = base::Minutes(1); namespace switches { [[maybe_unused]] constexpr char kRendererProcess[] = "renderer"; constexpr char kZygoteProcess[] = "zygote"; -#if PA_BUILDFLAG(USE_STARSCAN) -constexpr char kGpuProcess[] = "gpu-process"; -constexpr char kUtilityProcess[] = "utility"; -#endif } // namespace switches -#if PA_BUILDFLAG(USE_STARSCAN) - -#if BUILDFLAG(ENABLE_BASE_TRACING) -constexpr const char* ScannerIdToTracingString( - partition_alloc::internal::StatsCollector::ScannerId id) { - switch (id) { - case partition_alloc::internal::StatsCollector::ScannerId::kClear: - return "PCScan.Scanner.Clear"; - case partition_alloc::internal::StatsCollector::ScannerId::kScan: - return "PCScan.Scanner.Scan"; - case partition_alloc::internal::StatsCollector::ScannerId::kSweep: - return "PCScan.Scanner.Sweep"; - case partition_alloc::internal::StatsCollector::ScannerId::kOverall: - return "PCScan.Scanner"; - case partition_alloc::internal::StatsCollector::ScannerId::kNumIds: - __builtin_unreachable(); - } -} - -constexpr const char* MutatorIdToTracingString( - partition_alloc::internal::StatsCollector::MutatorId id) { - switch (id) { - case partition_alloc::internal::StatsCollector::MutatorId::kClear: - return "PCScan.Mutator.Clear"; - case partition_alloc::internal::StatsCollector::MutatorId::kScanStack: - return "PCScan.Mutator.ScanStack"; - case partition_alloc::internal::StatsCollector::MutatorId::kScan: - return "PCScan.Mutator.Scan"; - case partition_alloc::internal::StatsCollector::MutatorId::kOverall: - return "PCScan.Mutator"; - case partition_alloc::internal::StatsCollector::MutatorId::kNumIds: - __builtin_unreachable(); - } -} -#endif // BUILDFLAG(ENABLE_BASE_TRACING) - -// Inject TRACE_EVENT_BEGIN/END, TRACE_COUNTER1, and UmaHistogramTimes. -class StatsReporterImpl final : public partition_alloc::StatsReporter { - public: - void ReportTraceEvent( - partition_alloc::internal::StatsCollector::ScannerId id, - [[maybe_unused]] partition_alloc::internal::base::PlatformThreadId tid, - int64_t start_time_ticks_internal_value, - int64_t end_time_ticks_internal_value) override { -#if BUILDFLAG(ENABLE_BASE_TRACING) - // TRACE_EVENT_* macros below drop most parameters when tracing is - // disabled at compile time. - const char* tracing_id = ScannerIdToTracingString(id); - const TimeTicks start_time = - TimeTicks::FromInternalValue(start_time_ticks_internal_value); - const TimeTicks end_time = - TimeTicks::FromInternalValue(end_time_ticks_internal_value); - TRACE_EVENT_BEGIN(kTraceCategory, perfetto::StaticString(tracing_id), - perfetto::ThreadTrack::ForThread(tid), start_time); - TRACE_EVENT_END(kTraceCategory, perfetto::ThreadTrack::ForThread(tid), - end_time); -#endif // BUILDFLAG(ENABLE_BASE_TRACING) - } - - void ReportTraceEvent( - partition_alloc::internal::StatsCollector::MutatorId id, - [[maybe_unused]] partition_alloc::internal::base::PlatformThreadId tid, - int64_t start_time_ticks_internal_value, - int64_t end_time_ticks_internal_value) override { -#if BUILDFLAG(ENABLE_BASE_TRACING) - // TRACE_EVENT_* macros below drop most parameters when tracing is - // disabled at compile time. - const char* tracing_id = MutatorIdToTracingString(id); - const TimeTicks start_time = - TimeTicks::FromInternalValue(start_time_ticks_internal_value); - const TimeTicks end_time = - TimeTicks::FromInternalValue(end_time_ticks_internal_value); - TRACE_EVENT_BEGIN(kTraceCategory, perfetto::StaticString(tracing_id), - perfetto::ThreadTrack::ForThread(tid), start_time); - TRACE_EVENT_END(kTraceCategory, perfetto::ThreadTrack::ForThread(tid), - end_time); -#endif // BUILDFLAG(ENABLE_BASE_TRACING) - } - - void ReportSurvivedQuarantineSize(size_t survived_size) override { - TRACE_COUNTER1(kTraceCategory, "PCScan.SurvivedQuarantineSize", - survived_size); - } - - void ReportSurvivedQuarantinePercent(double survived_rate) override { - // Multiply by 1000 since TRACE_COUNTER1 expects integer. In catapult, - // divide back. - // TODO(bikineev): Remove after switching to perfetto. - TRACE_COUNTER1(kTraceCategory, "PCScan.SurvivedQuarantinePercent", - 1000 * survived_rate); - } - - void ReportStats(const char* stats_name, int64_t sample_in_usec) override { - TimeDelta sample = Microseconds(sample_in_usec); - UmaHistogramTimes(stats_name, sample); - } - - private: - static constexpr char kTraceCategory[] = "partition_alloc"; -}; - -#endif // PA_BUILDFLAG(USE_STARSCAN) - } // namespace -#if PA_BUILDFLAG(USE_STARSCAN) -void RegisterPCScanStatsReporter() { - static StatsReporterImpl s_reporter; - static bool registered = false; - - DCHECK(!registered); - - partition_alloc::internal::PCScan::RegisterStatsReporter(&s_reporter); - registered = true; -} -#endif // PA_BUILDFLAG(USE_STARSCAN) - namespace { void RunThreadCachePeriodicPurge() { @@ -551,7 +424,7 @@ std::string ExtractDanglingPtrSignature(std::string stacktrace) { for (size_t i = 0; i < lines.size(); ++i) { for (const auto& patterns : callee_patterns) { if (ranges::all_of(patterns, [&](std::string_view pattern) { - return lines[i].find(pattern) != StringPiece::npos; + return lines[i].find(pattern) != std::string_view::npos; })) { caller_index = i + 1; } @@ -855,96 +728,6 @@ void InstallUnretainedDanglingRawPtrChecks() { } } -namespace { - -#if PA_BUILDFLAG(USE_STARSCAN) -void SetProcessNameForPCScan(const std::string& process_type) { - const char* name = [&process_type] { - if (process_type.empty()) { - // Empty means browser process. - return "Browser"; - } - if (process_type == switches::kRendererProcess) { - return "Renderer"; - } - if (process_type == switches::kGpuProcess) { - return "Gpu"; - } - if (process_type == switches::kUtilityProcess) { - return "Utility"; - } - return static_cast(nullptr); - }(); - - if (name) { - partition_alloc::internal::PCScan::SetProcessName(name); - } -} - -bool EnablePCScanForMallocPartitionsIfNeeded() { -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - partition_alloc::internal::base::PlatformThread::SetThreadNameHook( - &base::PlatformThread::SetName); - - using Config = partition_alloc::internal::PCScan::InitConfig; - DCHECK(base::FeatureList::GetInstance()); - if (base::FeatureList::IsEnabled(base::features::kPartitionAllocPCScan)) { - allocator_shim::EnablePCScan({Config::WantedWriteProtectionMode::kEnabled, - Config::SafepointMode::kEnabled}); - base::allocator::RegisterPCScanStatsReporter(); - return true; - } -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - return false; -} - -bool EnablePCScanForMallocPartitionsInBrowserProcessIfNeeded() { -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - using Config = partition_alloc::internal::PCScan::InitConfig; - DCHECK(base::FeatureList::GetInstance()); - if (base::FeatureList::IsEnabled( - base::features::kPartitionAllocPCScanBrowserOnly)) { - const Config::WantedWriteProtectionMode wp_mode = - base::FeatureList::IsEnabled(base::features::kPartitionAllocDCScan) - ? Config::WantedWriteProtectionMode::kEnabled - : Config::WantedWriteProtectionMode::kDisabled; -#if !PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) - CHECK_EQ(Config::WantedWriteProtectionMode::kDisabled, wp_mode) - << "DCScan is currently only supported on Linux based systems"; -#endif - allocator_shim::EnablePCScan({wp_mode, Config::SafepointMode::kEnabled}); - base::allocator::RegisterPCScanStatsReporter(); - return true; - } -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - return false; -} - -bool EnablePCScanForMallocPartitionsInRendererProcessIfNeeded() { -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - using Config = partition_alloc::internal::PCScan::InitConfig; - DCHECK(base::FeatureList::GetInstance()); - if (base::FeatureList::IsEnabled( - base::features::kPartitionAllocPCScanRendererOnly)) { - const Config::WantedWriteProtectionMode wp_mode = - base::FeatureList::IsEnabled(base::features::kPartitionAllocDCScan) - ? Config::WantedWriteProtectionMode::kEnabled - : Config::WantedWriteProtectionMode::kDisabled; -#if !PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) - CHECK_EQ(Config::WantedWriteProtectionMode::kDisabled, wp_mode) - << "DCScan is currently only supported on Linux based systems"; -#endif - allocator_shim::EnablePCScan({wp_mode, Config::SafepointMode::kDisabled}); - base::allocator::RegisterPCScanStatsReporter(); - return true; - } -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - return false; -} -#endif // PA_BUILDFLAG(USE_STARSCAN) - -} // namespace - void ReconfigurePartitionForKnownProcess(const std::string& process_type) { DCHECK_NE(process_type, switches::kZygoteProcess); // TODO(keishi): Move the code to enable BRP back here after Finch @@ -1279,62 +1062,16 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit( // 100 is a reasonable cap for this value. UmaHistogramCounts100("Memory.PartitionAlloc.PartitionRoot.ExtrasSize", int(extras_size)); -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - // If BRP is not enabled, check if any of PCScan flags is enabled. - [[maybe_unused]] bool scan_enabled = false; -#if PA_BUILDFLAG(USE_STARSCAN) - if (!brp_config.enable_brp) { - scan_enabled = EnablePCScanForMallocPartitionsIfNeeded(); - // No specified process type means this is the Browser process. - if (process_type.empty()) { - scan_enabled = scan_enabled || - EnablePCScanForMallocPartitionsInBrowserProcessIfNeeded(); - } - if (process_type == switches::kRendererProcess) { - scan_enabled = scan_enabled || - EnablePCScanForMallocPartitionsInRendererProcessIfNeeded(); - } - if (scan_enabled) { - if (base::FeatureList::IsEnabled( - base::features::kPartitionAllocPCScanStackScanning)) { -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - partition_alloc::internal::PCScan::EnableStackScanning(); -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - } - if (base::FeatureList::IsEnabled( - base::features::kPartitionAllocPCScanImmediateFreeing)) { - partition_alloc::internal::PCScan::EnableImmediateFreeing(); - } - if (base::FeatureList::IsEnabled( - base::features::kPartitionAllocPCScanEagerClearing)) { - partition_alloc::internal::PCScan::SetClearType( - partition_alloc::internal::PCScan::ClearType::kEager); - } - SetProcessNameForPCScan(process_type); - } - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -#if PA_BUILDFLAG(USE_STARSCAN) +#if !defined(__MUSL__) + // This call causes hanging in pthread_getattr_np() under qemu-user, see + // https://www.openwall.com/lists/musl/2017/06/15/9. partition_alloc::internal::StackTopRegistry::Get().NotifyThreadCreated( partition_alloc::internal::GetStackTop()); +#endif - // Non-quarantinable partition is dealing with hot V8's zone allocations. - // In case PCScan is enabled in Renderer, enable thread cache on this - // partition. At the same time, thread cache on the main(malloc) partition - // must be disabled, because only one partition can have it on. - if (scan_enabled && process_type == switches::kRendererProcess) { - allocator_shim::NonQuarantinableAllocator::Instance() - .root() - ->EnableThreadCacheIfSupported(); - } else -#endif // PA_BUILDFLAG(USE_STARSCAN) - { - allocator_shim::internal::PartitionAllocMalloc::Allocator() - ->EnableThreadCacheIfSupported(); - } + allocator_shim::internal::PartitionAllocMalloc::Allocator() + ->EnableThreadCacheIfSupported(); if (base::FeatureList::IsEnabled( base::features::kPartitionAllocLargeEmptySlotSpanRing)) { @@ -1436,20 +1173,6 @@ void PartitionAllocSupport::ReconfigureAfterTaskRunnerInit( #endif // PA_CONFIG(THREAD_CACHE_SUPPORTED) && // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -#if PA_BUILDFLAG(USE_STARSCAN) - if (base::FeatureList::IsEnabled( - base::features::kPartitionAllocPCScanMUAwareScheduler)) { - // Assign PCScan a task-based scheduling backend. - static base::NoDestructor< - partition_alloc::internal::MUAwareTaskBasedBackend> - mu_aware_task_based_backend{ - partition_alloc::internal::PCScan::scheduler(), - &partition_alloc::internal::PCScan::PerformDelayedScan}; - partition_alloc::internal::PCScan::scheduler().SetNewSchedulingBackend( - *mu_aware_task_based_backend.get()); - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) base::allocator::StartMemoryReclaimer( base::SingleThreadTaskRunner::GetCurrentDefault()); diff --git a/naiveproxy/src/base/allocator/partition_alloc_support.h b/naiveproxy/src/base/allocator/partition_alloc_support.h index 1fbf5b9de9..c54c8d5363 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_support.h +++ b/naiveproxy/src/base/allocator/partition_alloc_support.h @@ -14,16 +14,12 @@ #include "base/synchronization/lock.h" #include "base/task/sequenced_task_runner.h" #include "base/thread_annotations.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/thread_cache.h" namespace base::allocator { -#if PA_BUILDFLAG(USE_STARSCAN) -BASE_EXPORT void RegisterPCScanStatsReporter(); -#endif - // Starts a periodic timer on the current thread to purge all thread caches. BASE_EXPORT void StartThreadCachePeriodicPurge(); diff --git a/naiveproxy/src/base/allocator/partition_allocator/DEPS b/naiveproxy/src/base/allocator/partition_allocator/DEPS index 92f98324ca..ac57f43824 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/DEPS +++ b/naiveproxy/src/base/allocator/partition_allocator/DEPS @@ -9,35 +9,48 @@ noparent = True # `partition_alloc` can depend only on itself, via its `include_dirs`. include_rules = [ "+partition_alloc" ] +# TODO(crbug.com/40158212): Depending on what is tested, split the tests in +# between chromium and partition_alloc. Remove those exceptions: specific_include_rules = { - ".*_(perf|unit)test\.cc$": [ - "+base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h", - "+base/allocator/dispatcher/dispatcher.h", - "+base/debug/allocation_trace.h", - "+base/debug/debugging_buildflags.h", - "+base/debug/proc_maps_linux.h", - "+base/system/sys_info.h", - "+base/test/gtest_util.h", - "+base/timer/lap_timer.h", - "+base/win/windows_version.h", + # Dependencies on //testing: + ".*_(perf|unit)?test.*\.(h|cc)": [ "+testing/gmock/include/gmock/gmock.h", "+testing/gtest/include/gtest/gtest.h", "+testing/perf/perf_result_reporter.h", ], - "extended_api\.cc$": [ + "gtest_util.h": [ + "+testing/gtest/include/gtest/gtest.h", + ], + + # Dependencies on //base: + "extended_api\.cc": [ "+base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h", ], - "raw_(ptr|ref)_unittest\.cc$": [ - "+base", - "+third_party/abseil-cpp/absl/types/optional.h", - "+third_party/abseil-cpp/absl/types/variant.h", + "partition_alloc_perftest\.cc": [ + "+base/allocator/dispatcher/dispatcher.h", + "+base/debug/allocation_trace.h", + "+base/debug/debugging_buildflags.h", + "+base/timer/lap_timer.h", ], - "raw_ptr_test_support\.h$": [ - "+testing/gmock/include/gmock/gmock.h", - "+third_party/abseil-cpp/absl/types/optional.h", + "partition_lock_perftest\.cc": [ + "+base/timer/lap_timer.h", ], - "use_death_tests\.h$": [ - "+testing/gtest/include/gtest/gtest.h", + "raw_ptr_unittest\.cc": [ + "+base/allocator/partition_alloc_features.h", + "+base/allocator/partition_alloc_support.h", + "+base/cpu.h", + "+base/debug/asan_service.h", + "+base/metrics/histogram_base.h", + "+base/test/bind.h", + "+base/test/gtest_util.h", + "+base/test/memory/dangling_ptr_instrumentation.h", + "+base/test/scoped_feature_list.h", + "+base/types/to_address.h", + ], + "raw_ref_unittest\.cc": [ + "+base/debug/asan_service.h", + "+base/memory/raw_ptr_asan_service.h", + "+base/test/gtest_util.h", ], } diff --git a/naiveproxy/src/base/allocator/partition_allocator/PRESUBMIT.py b/naiveproxy/src/base/allocator/partition_allocator/PRESUBMIT.py index 4151b3d3cc..5bbe613a2c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/PRESUBMIT.py +++ b/naiveproxy/src/base/allocator/partition_allocator/PRESUBMIT.py @@ -13,6 +13,16 @@ PRESUBMIT_VERSION = '2.0.0' # chromium repository. PRESUBMIT.py is executed from chromium. _PARTITION_ALLOC_BASE_PATH = 'base/allocator/partition_allocator/src/' + +# Filter for C/C++ files. +def c_cpp_files(file): + return file.LocalPath().endswith(('.h', '.hpp', '.c', '.cc', '.cpp')) + +# Filter for GN files. +def gn_files(file): + return file.LocalPath().endswith(('.gn', '.gni')) + + # This is adapted from Chromium's PRESUBMIT.py. The differences are: # - Base path: It is relative to the partition_alloc's source directory instead # of chromium. @@ -99,25 +109,104 @@ def CheckForIncludeGuards(input_api, output_api): # overrides the default build settings and forward the dependencies to # partition_alloc. def CheckNoExternalImportInGn(input_api, output_api): - def gn_files(file): - return file.LocalPath().endswith('.gn') or \ - file.LocalPath().endswith('.gni') - # Match and capture from import(""). import_re = input_api.re.compile(r'^ *import\("([^"]+)"\)') errors = [] for f in input_api.AffectedSourceFiles(gn_files): - for line_number, line in enumerate(input_api.ReadFile(f).splitlines()): + for line_number, line in f.ChangedContents(): match = import_re.search(line) if not match: continue import_path = match.group(1) if import_path.startswith('//build_overrides/'): - continue; + continue if not import_path.startswith('//'): continue; errors.append(output_api.PresubmitError( '%s:%d\nPartitionAlloc disallow external import: %s' % (f.LocalPath(), line_number + 1, import_path))) return errors; + +# partition_alloc still supports C++17, because Skia still uses C++17. +def CheckCpp17CompatibleHeaders(input_api, output_api): + CPP_20_HEADERS = [ + "barrier", + "bit", + "compare", + "format", + "numbers", + "ranges", + "semaphore", + "source_location", + "span", + "stop_token", + "syncstream", + "version", + ] + + CPP_23_HEADERS = [ + "expected", + "flat_map", + "flat_set", + "generator", + "mdspan", + "print", + "spanstream", + "stacktrace", + "stdatomic.h", + "stdfloat", + ] + + errors = [] + for f in input_api.AffectedSourceFiles(c_cpp_files): + # for line_number, line in f.ChangedContents(): + for line_number, line in enumerate(f.NewContents()): + for header in CPP_20_HEADERS: + if not "#include <%s>" % header in line: + continue + errors.append( + output_api.PresubmitError( + '%s:%d\nPartitionAlloc disallows C++20 headers: <%s>' + % (f.LocalPath(), line_number + 1, header))) + for header in CPP_23_HEADERS: + if not "#include <%s>" % header in line: + continue + errors.append( + output_api.PresubmitError( + '%s:%d\nPartitionAlloc disallows C++23 headers: <%s>' + % (f.LocalPath(), line_number + 1, header))) + return errors + +def CheckCpp17CompatibleKeywords(input_api, output_api): + CPP_20_KEYWORDS = [ + "concept", + "consteval", + "constinit", + "co_await", + "co_return", + "co_yield", + "requires", + ] + # Note: C++23 doesn't introduce new keywords. + + errors = [] + for f in input_api.AffectedSourceFiles(c_cpp_files): + for line_number, line in f.ChangedContents(): + for keyword in CPP_20_KEYWORDS: + if not keyword in line: + continue + # Skip if part of a comment + if '//' in line and line.index('//') < line.index(keyword): + continue + + # Make sure there are word separators around the keyword: + regex = r'\b%s\b' % keyword + if not input_api.re.search(regex, line): + continue + + errors.append( + output_api.PresubmitError( + '%s:%d\nPartitionAlloc disallows C++20 keywords: %s' + % (f.LocalPath(), line_number + 1, keyword))) + return errors diff --git a/naiveproxy/src/base/allocator/partition_allocator/PartitionAlloc.md b/naiveproxy/src/base/allocator/partition_allocator/PartitionAlloc.md index dd845961a1..c8e9a77d06 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/PartitionAlloc.md +++ b/naiveproxy/src/base/allocator/partition_allocator/PartitionAlloc.md @@ -119,7 +119,7 @@ partition page that holds metadata (32B struct per partition page). of each super page). * In some configurations, PartitionAlloc stores more metadata than can fit in the one system page at the front. These are the bitmaps for - StarScan and `MTECheckedPtr`, and they are relegated to the head of + `MTECheckedPtr`, and they are relegated to the head of what would otherwise be usable space for slot spans. One, both, or none of these bitmaps may be present, depending on build configuration, runtime configuration, and type of allocation. diff --git a/naiveproxy/src/base/allocator/partition_allocator/build_overrides/build.gni b/naiveproxy/src/base/allocator/partition_allocator/build_overrides/build.gni deleted file mode 100644 index 30c0b64901..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/build_overrides/build.gni +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2022 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# This file will be used to check out PartitionAlloc and to build it as -# standalone library. In this case, PartitionAlloc needs to define -# build_with_chromium. If building PartitionAlloc as a part of chromium, -# chromium will provide build_with_chromium=true. -build_with_chromium = false diff --git a/naiveproxy/src/base/allocator/partition_allocator/build_overrides/partition_alloc.gni b/naiveproxy/src/base/allocator/partition_allocator/build_overrides/partition_alloc.gni index 786e2e64ce..a7939c0060 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/build_overrides/partition_alloc.gni +++ b/naiveproxy/src/base/allocator/partition_allocator/build_overrides/partition_alloc.gni @@ -2,7 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build_overrides/build.gni") +# By definition, PartitionAlloc standalone builds outside of chromium. +build_with_chromium = false # This is the default build configuration when building PartitionAlloc # as a standalone library. @@ -14,9 +15,12 @@ use_allocator_shim_default = false enable_backup_ref_ptr_support_default = false enable_backup_ref_ptr_slow_checks_default = false enable_dangling_raw_ptr_checks_default = false -assert_cpp20_default = true # This is the default build configuration for pointers/raw_ptr*. raw_ptr_zero_on_construct_default = true raw_ptr_zero_on_move_default = true raw_ptr_zero_on_destruct_default = false + +# PartitionAlloc needs to support cpp17 for standalone builds, as long as Skia +# supports it. +assert_cpp20_default = false diff --git a/naiveproxy/src/base/allocator/partition_allocator/glossary.md b/naiveproxy/src/base/allocator/partition_allocator/glossary.md index 68ce6c1ca2..cd7192e67a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/glossary.md +++ b/naiveproxy/src/base/allocator/partition_allocator/glossary.md @@ -169,7 +169,7 @@ tracking a non-contiguous set of allocations using a bitmap. The usable area of a super page in which slot spans reside. While generally this means "everything between the first and last guard partition pages in a super page," the presence of -other metadata (e.g. StarScan bitmaps) can bump the starting offset +other metadata can bump the starting offset forward. While this term is entrenched in the code, the team considers it suboptimal and is actively looking for a replacement. diff --git a/naiveproxy/src/base/allocator/partition_allocator/gn/BUILDCONFIG.gn b/naiveproxy/src/base/allocator/partition_allocator/gn/BUILDCONFIG.gn index 28d9cfd929..abbb511df6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/gn/BUILDCONFIG.gn +++ b/naiveproxy/src/base/allocator/partition_allocator/gn/BUILDCONFIG.gn @@ -8,7 +8,6 @@ # - skia: //gn/BUILDCONFIG.gn # - chromium: //build/config/BUILDCONFIG.gn -is_partition_alloc_standalone = true build_with_chromium = false is_asan = false diff --git a/naiveproxy/src/base/allocator/partition_allocator/gn/partition_alloc/BUILD.gn b/naiveproxy/src/base/allocator/partition_allocator/gn/partition_alloc/BUILD.gn index 12b434d27e..bdbc21794b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/gn/partition_alloc/BUILD.gn +++ b/naiveproxy/src/base/allocator/partition_allocator/gn/partition_alloc/BUILD.gn @@ -13,7 +13,7 @@ config("default") { "-fvisibility=hidden", ] cflags_cc = [ - "-std=c++20", + "-std=c++17", "-fvisibility-inlines-hidden", ] cflags_objcc = cflags_cc diff --git a/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni b/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni index 719591ea17..24a38e6178 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni +++ b/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni @@ -101,7 +101,8 @@ declare_args() { # Puts the regular and BRP pools right next to each other, so that we can # check "belongs to one of the two pools" with a single bitmask operation. - glue_core_pools = false + # TODO(crbug.com/350104111): Fix ios-simulator failures to remove `!is_ios`. + glue_core_pools = use_partition_alloc_as_malloc && !is_ios # Introduces pointer compression support in PA. These are 4-byte # pointers that can point within the core pools (regular and BRP). @@ -245,9 +246,6 @@ declare_args() { use_full_mte = false } -# *Scan is currently only used by Chromium, and supports only 64-bit. -use_starscan = build_with_chromium && has_64_bit_pointers - stack_scan_supported = current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm" || current_cpu == "arm64" || current_cpu == "riscv64" @@ -260,8 +258,11 @@ stack_scan_supported = # Do not clear the following, as they can function outside of PartitionAlloc # - has_64_bit_pointers # - has_memory_tagging -if (!use_partition_alloc) { +if (!use_partition_alloc || + (defined(toolchain_allows_use_partition_alloc_as_malloc) && + !toolchain_allows_use_partition_alloc_as_malloc)) { use_partition_alloc_as_malloc = false + glue_core_pools = false enable_backup_ref_ptr_support = false use_raw_ptr_backup_ref_impl = false use_asan_backup_ref_ptr = false @@ -272,8 +273,8 @@ if (!use_partition_alloc) { enable_dangling_raw_ptr_feature_flag = false enable_pointer_subtraction_check = false backup_ref_ptr_poison_oob_ptr = false + backup_ref_ptr_extra_oob_checks = false enable_backup_ref_ptr_instance_tracer = false - use_starscan = false use_full_mte = false } @@ -409,17 +410,3 @@ declare_args() { # Embedders may opt-out of using C++ 20 build. assert_cpp20 = assert_cpp20_default } - -declare_args() { - # Enables compilation of the freelist dispatcher, which we'll use to - # carry out runtime evaluation of PartitionAlloc's two freelist - # implementations: the existing encoded-next freelist and the new - # pool offset freelist. When false, the latter is not built. - # - # This is being exposed as a GN arg because of an undiagnosed crashy - # interaction with Mac PGO builders: crbug.com/338094768#comment20 - use_freelist_dispatcher = has_64_bit_pointers && false -} - -assert(has_64_bit_pointers || !use_freelist_dispatcher, - "freelist dispatcher can't be used without 64-bit pointers") diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn index 9823fb0301..f3e9c4c00f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn @@ -15,7 +15,30 @@ if (!defined(partition_alloc_remove_configs)) { partition_alloc_remove_configs = [] } -# Add partition_alloc.gni and import it for partition_alloc configs. +# Enables compilation of the freelist dispatcher, which we'll use to +# carry out runtime evaluation of PartitionAlloc's two freelist +# implementations: the existing encoded-next freelist and the new +# pool offset freelist. When false, the latter is not built. +use_freelist_dispatcher = has_64_bit_pointers + +assert(has_64_bit_pointers || !use_freelist_dispatcher, + "freelist dispatcher can't be used without 64-bit pointers") + +record_alloc_info = false + +# GWP-ASan is tied to BRP's enablement. +enable_gwp_asan_support = enable_backup_ref_ptr_support + +# Pools are a logical concept when address space is 32-bit. +glue_core_pools = glue_core_pools && has_64_bit_pointers + +# Pointer compression requires 64-bit pointers. +enable_pointer_compression = + enable_pointer_compression_support && has_64_bit_pointers + +# Duplicates the setup Chromium uses to define `DCHECK_IS_ON()`, but avails it +# as a buildflag. +dchecks_are_on = is_debug || dcheck_always_on # TODO(crbug.com/40276913): Split PartitionAlloc into a public and # private parts. The public config would include add the "./include" dir and @@ -90,11 +113,81 @@ config("wexit_time_destructors") { } } +source_set("buildflag_macro") { + sources = [ "buildflag.h" ] + public_configs = [ ":public_includes" ] +} + +pa_buildflag_header("buildflags") { + header = "buildflags.h" + flags = [ + "ASSERT_CPP_20=$assert_cpp20", + "BACKUP_REF_PTR_EXTRA_OOB_CHECKS=$backup_ref_ptr_extra_oob_checks", + "BACKUP_REF_PTR_POISON_OOB_PTR=$backup_ref_ptr_poison_oob_ptr", + "ENABLE_BACKUP_REF_PTR_FEATURE_FLAG=$enable_backup_ref_ptr_feature_flag", + "ENABLE_BACKUP_REF_PTR_INSTANCE_TRACER=$enable_backup_ref_ptr_instance_tracer", + "ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=$enable_backup_ref_ptr_slow_checks", + "ENABLE_BACKUP_REF_PTR_SUPPORT=$enable_backup_ref_ptr_support", + "ENABLE_DANGLING_RAW_PTR_CHECKS=$enable_dangling_raw_ptr_checks", + "ENABLE_DANGLING_RAW_PTR_FEATURE_FLAG=$enable_dangling_raw_ptr_feature_flag", + "ENABLE_GWP_ASAN_SUPPORT=$enable_gwp_asan_support", + "ENABLE_PKEYS=$enable_pkeys", + "ENABLE_POINTER_ARITHMETIC_TRAIT_CHECK=$enable_pointer_arithmetic_trait_check", + "ENABLE_POINTER_COMPRESSION=$enable_pointer_compression", + "ENABLE_POINTER_SUBTRACTION_CHECK=$enable_pointer_subtraction_check", + "ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=$enable_shadow_metadata", + "ENABLE_THREAD_ISOLATION=$enable_pkeys", + "FORCE_ENABLE_RAW_PTR_EXCLUSION=$force_enable_raw_ptr_exclusion", + "FORWARD_THROUGH_MALLOC=$forward_through_malloc", + "GLUE_CORE_POOLS=$glue_core_pools", + "HAS_64_BIT_POINTERS=$has_64_bit_pointers", + "HAS_MEMORY_TAGGING=$has_memory_tagging", + "IS_CASTOS=$is_castos", + "IS_CAST_ANDROID=$is_cast_android", + "IS_CHROMEOS=$is_chromeos", + "IS_DEBUG=$is_debug", + "RAW_PTR_ZERO_ON_CONSTRUCT=$raw_ptr_zero_on_construct", + "RAW_PTR_ZERO_ON_DESTRUCT=$raw_ptr_zero_on_destruct", + "RAW_PTR_ZERO_ON_MOVE=$raw_ptr_zero_on_move", + "RECORD_ALLOC_INFO=$record_alloc_info", + "STACK_SCAN_SUPPORTED=$stack_scan_supported", + "USE_ALLOCATOR_SHIM=$use_allocator_shim", + "USE_ASAN_BACKUP_REF_PTR=$use_asan_backup_ref_ptr", + "USE_FREELIST_DISPATCHER=$use_freelist_dispatcher", + "USE_FREESLOT_BITMAP=$use_freeslot_bitmap", + "USE_FULL_MTE=$use_full_mte", + "USE_LARGE_EMPTY_SLOT_SPAN_RING=$use_large_empty_slot_span_ring", + "USE_PARTITION_ALLOC=$use_partition_alloc", + "USE_PARTITION_ALLOC_AS_MALLOC=$use_partition_alloc_as_malloc", + "USE_RAW_PTR_ASAN_UNOWNED_IMPL=$use_raw_ptr_asan_unowned_impl", + "USE_RAW_PTR_BACKUP_REF_IMPL=$use_raw_ptr_backup_ref_impl", + "USE_RAW_PTR_HOOKABLE_IMPL=$use_raw_ptr_hookable_impl", + "DCHECKS_ARE_ON=$dchecks_are_on", + "EXPENSIVE_DCHECKS_ARE_ON=$enable_expensive_dchecks", + "DCHECK_IS_CONFIGURABLE=$dcheck_is_configurable", + "CAN_UNWIND_WITH_FRAME_POINTERS=$can_unwind_with_frame_pointers", + ] +} + +# TODO(crbug.com/41481467): Remove this alias. +# Temporary alias, the time to update partition_alloc dependants. +# Currently needed by pdfium and dawn. +source_set("partition_alloc_buildflags") { + public = [ "partition_alloc_buildflags.h" ] + public_deps = [ ":buildflags" ] +} + +# Provides platform and architecture detections from the compiler defines. source_set("build_config") { sources = [ "build_config.h", "buildflag.h", ] + public_deps = [ + ":buildflag_macro", # Provides 'PA_BUILDFLAG()' macro. + ":buildflags", # Provides `IS_CHROMEOS` definition. + ] + public_configs = [ ":public_includes" ] } component("raw_ptr") { @@ -146,135 +239,6 @@ component("raw_ptr") { configs += [ ":dependants_extra_warnings" ] } -pa_buildflag_header("partition_alloc_buildflags") { - header = "partition_alloc_buildflags.h" - - _record_alloc_info = false - - # GWP-ASan is tied to BRP's enablement. - _enable_gwp_asan_support = enable_backup_ref_ptr_support - - # Pools are a logical concept when address space is 32-bit. - _glue_core_pools = glue_core_pools && has_64_bit_pointers - - # Pointer compression requires 64-bit pointers. - _enable_pointer_compression = - enable_pointer_compression_support && has_64_bit_pointers - - # TODO(crbug.com/40158212): Need to refactor the following buildflags. - # The buildflags (except RECORD_ALLOC_INFO) are used by both chrome and - # PartitionAlloc. For PartitionAlloc, - # gen/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h - # defines and PartitionAlloc includes the header file. For chrome, - # gen/base/allocator/buildflags.h defines and chrome includes. - flags = [ - "HAS_64_BIT_POINTERS=$has_64_bit_pointers", - "HAS_MEMORY_TAGGING=$has_memory_tagging", - - "USE_ALLOCATOR_SHIM=$use_allocator_shim", - "USE_LARGE_EMPTY_SLOT_SPAN_RING=$use_large_empty_slot_span_ring", - "USE_PARTITION_ALLOC=$use_partition_alloc", - "USE_PARTITION_ALLOC_AS_MALLOC=$use_partition_alloc_as_malloc", - - "ENABLE_BACKUP_REF_PTR_SUPPORT=$enable_backup_ref_ptr_support", - "ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=$enable_backup_ref_ptr_slow_checks", - "ENABLE_BACKUP_REF_PTR_FEATURE_FLAG=$enable_backup_ref_ptr_feature_flag", - "ENABLE_BACKUP_REF_PTR_INSTANCE_TRACER=$enable_backup_ref_ptr_instance_tracer", - "ENABLE_DANGLING_RAW_PTR_CHECKS=$enable_dangling_raw_ptr_checks", - "ENABLE_DANGLING_RAW_PTR_FEATURE_FLAG=$enable_dangling_raw_ptr_feature_flag", - "ENABLE_POINTER_SUBTRACTION_CHECK=$enable_pointer_subtraction_check", - "ENABLE_POINTER_ARITHMETIC_TRAIT_CHECK=$enable_pointer_arithmetic_trait_check", - "BACKUP_REF_PTR_EXTRA_OOB_CHECKS=$backup_ref_ptr_extra_oob_checks", - "BACKUP_REF_PTR_POISON_OOB_PTR=$backup_ref_ptr_poison_oob_ptr", - "USE_RAW_PTR_BACKUP_REF_IMPL=$use_raw_ptr_backup_ref_impl", - "USE_ASAN_BACKUP_REF_PTR=$use_asan_backup_ref_ptr", - "USE_RAW_PTR_ASAN_UNOWNED_IMPL=$use_raw_ptr_asan_unowned_impl", - "USE_RAW_PTR_HOOKABLE_IMPL=$use_raw_ptr_hookable_impl", - "ENABLE_GWP_ASAN_SUPPORT=$_enable_gwp_asan_support", - - # TODO(bartekn): Remove once PDFium switches to - # USE_RAW_PTR_ASAN_UNOWNED_IMPL. - "USE_ASAN_UNOWNED_PTR=$use_raw_ptr_asan_unowned_impl", - - "FORCE_ENABLE_RAW_PTR_EXCLUSION=$force_enable_raw_ptr_exclusion", - - "USE_FULL_MTE=$use_full_mte", - - "RECORD_ALLOC_INFO=$_record_alloc_info", - "USE_FREESLOT_BITMAP=$use_freeslot_bitmap", - "GLUE_CORE_POOLS=$_glue_core_pools", - "ENABLE_POINTER_COMPRESSION=$_enable_pointer_compression", - "ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=$enable_shadow_metadata", - "USE_FREELIST_DISPATCHER=$use_freelist_dispatcher", - - "USE_STARSCAN=$use_starscan", - - "STACK_SCAN_SUPPORTED=$stack_scan_supported", - - "ENABLE_PKEYS=$enable_pkeys", - "ENABLE_THREAD_ISOLATION=$enable_pkeys", - - "FORWARD_THROUGH_MALLOC=$forward_through_malloc", - "ASSERT_CPP_20=$assert_cpp20", - "IS_DEBUG=$is_debug", - ] -} - -pa_buildflag_header("raw_ptr_buildflags") { - header = "raw_ptr_buildflags.h" - - flags = [ - "RAW_PTR_ZERO_ON_CONSTRUCT=$raw_ptr_zero_on_construct", - "RAW_PTR_ZERO_ON_MOVE=$raw_ptr_zero_on_move", - "RAW_PTR_ZERO_ON_DESTRUCT=$raw_ptr_zero_on_destruct", - ] -} - -pa_buildflag_header("chromecast_buildflags") { - header = "chromecast_buildflags.h" - - # TODO(https://crbug.com/41481467): Remove the "PA_" prefix, because it - # will already be part of the define and the `PA_BUILDFLAG` macro. - flags = [ - "PA_IS_CAST_ANDROID=$is_cast_android", - "PA_IS_CASTOS=$is_castos", - ] -} - -pa_buildflag_header("chromeos_buildflags") { - header = "chromeos_buildflags.h" - flags = [ "IS_CHROMEOS=$is_chromeos" ] -} - -pa_buildflag_header("debugging_buildflags") { - header = "debugging_buildflags.h" - header_dir = rebase_path(".", "//") + "/partition_alloc_base/debug" - - # Duplicates the setup Chromium uses to define `DCHECK_IS_ON()`, - # but avails it as a buildflag. - _dcheck_is_on = is_debug || dcheck_always_on - - # TODO(https://crbug.com/41481467): Remove the "PA_" prefix, because it - # will already be part of the define and the `PA_BUILDFLAG` macro. - flags = [ - "PA_DCHECK_IS_ON=$_dcheck_is_on", - "PA_EXPENSIVE_DCHECKS_ARE_ON=$enable_expensive_dchecks", - "PA_DCHECK_IS_CONFIGURABLE=$dcheck_is_configurable", - "PA_CAN_UNWIND_WITH_FRAME_POINTERS=$can_unwind_with_frame_pointers", - ] -} - -group("buildflags") { - public_deps = [ - ":chromecast_buildflags", - ":chromeos_buildflags", - ":debugging_buildflags", - ":partition_alloc_buildflags", - ":raw_ptr_buildflags", - ] - public_configs = [ ":public_includes" ] -} - if (is_clang_or_gcc) { config("partition_alloc_implementation") { # See also: `partition_alloc_base/component_export.h` @@ -463,29 +427,6 @@ if (is_clang_or_gcc) { "yield_processor.h", ] - if (use_starscan) { - sources += [ - "starscan/logging.h", - "starscan/pcscan.cc", - "starscan/pcscan.h", - "starscan/pcscan_internal.cc", - "starscan/pcscan_internal.h", - "starscan/pcscan_scheduling.cc", - "starscan/pcscan_scheduling.h", - "starscan/raceful_worklist.h", - "starscan/scan_loop.h", - "starscan/snapshot.cc", - "starscan/snapshot.h", - "starscan/starscan_fwd.h", - "starscan/state_bitmap.h", - "starscan/stats_collector.cc", - "starscan/stats_collector.h", - "starscan/stats_reporter.h", - "starscan/write_protector.cc", - "starscan/write_protector.h", - ] - } - defines = [] if (is_win) { sources += [ @@ -534,10 +475,7 @@ if (is_clang_or_gcc) { public_deps = [ ":build_config", - ":chromecast_buildflags", - ":chromeos_buildflags", - ":debugging_buildflags", - ":partition_alloc_buildflags", + ":buildflags", ] configs += [ @@ -547,10 +485,6 @@ if (is_clang_or_gcc) { ] deps = [ ":allocator_base" ] public_configs = [] - if (is_android) { - # tagging.cc requires __arm_mte_set_* functions. - deps += [ "//third_party/cpu_features:ndk_compat" ] - } if (is_fuchsia) { deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.kernel:fuchsia.kernel_cpp", @@ -672,7 +606,9 @@ if (is_clang_or_gcc) { "partition_alloc_base/threading/platform_thread_win.cc", "partition_alloc_base/time/time_win.cc", ] - } else if (is_posix) { + } + + if (is_posix) { sources += [ "partition_alloc_base/debug/stack_trace_posix.cc", "partition_alloc_base/files/file_util.h", @@ -703,7 +639,9 @@ if (is_clang_or_gcc) { } else { sources += [ "partition_alloc_base/time/time_now_posix.cc" ] } - } else if (is_fuchsia) { + } + + if (is_fuchsia) { sources += [ "partition_alloc_base/fuchsia/fuchsia_logging.cc", "partition_alloc_base/fuchsia/fuchsia_logging.h", @@ -717,6 +655,7 @@ if (is_clang_or_gcc) { "partition_alloc_base/time/time_fuchsia.cc", ] } + if (is_android) { # Only android build requires native_library, and native_library depends # on file_path. So file_path is added if is_android = true. @@ -729,6 +668,7 @@ if (is_clang_or_gcc) { "partition_alloc_base/native_library_posix.cc", ] } + if (is_apple) { # Apple-specific utilities sources += [ @@ -757,10 +697,7 @@ if (is_clang_or_gcc) { public_deps = [ ":build_config", - ":chromecast_buildflags", - ":chromeos_buildflags", - ":debugging_buildflags", - ":partition_alloc_buildflags", + ":buildflags", ] public_configs = [ ":public_includes" ] configs += [ @@ -819,14 +756,10 @@ if (is_clang_or_gcc) { "shim/allocator_shim_dispatch_to_noop_on_free.h", ] if (use_partition_alloc) { - shim_sources += [ - "shim/allocator_shim_default_dispatch_to_partition_alloc.cc", - "shim/nonscannable_allocator.cc", - ] - shim_headers += [ - "shim/allocator_shim_default_dispatch_to_partition_alloc.h", - "shim/nonscannable_allocator.h", - ] + shim_sources += + [ "shim/allocator_shim_default_dispatch_to_partition_alloc.cc" ] + shim_headers += + [ "shim/allocator_shim_default_dispatch_to_partition_alloc.h" ] } if (is_android) { shim_headers += [ @@ -929,6 +862,199 @@ if (is_clang_or_gcc) { ] } } # if (is_clang_or_gcc) -# TODO(crbug.com/40158212): After making partition_alloc a standalone library, -# move test code here. i.e. test("partition_alloc_tests") { ... } and -# test("partition_alloc_perftests"). + +# TODO(crbug.com/40158212): Consider supporting building tests outside of +# chromium and having a dedicated 'partition_alloc_unittests' target. +if (build_with_chromium) { + source_set("unittests") { + testonly = true + + sources = [ "partition_alloc_base/test/gtest_util.h" ] + + if (is_linux || is_chromeos || is_android) { + sources += [ + "partition_alloc_base/debug/proc_maps_linux.cc", + "partition_alloc_base/debug/proc_maps_linux.h", + ] + } + + if (is_android) { + sources += [ + "partition_alloc_base/files/file_path_pa_unittest.cc", + "partition_alloc_base/native_library_pa_unittest.cc", + ] + } + + if (use_partition_alloc) { + sources += [ + "address_pool_manager_unittest.cc", + "address_space_randomization_unittest.cc", + "compressed_pointer_unittest.cc", + "freeslot_bitmap_unittest.cc", + "hardening_unittest.cc", + "lightweight_quarantine_unittest.cc", + "memory_reclaimer_unittest.cc", + "page_allocator_unittest.cc", + "partition_alloc_base/bits_pa_unittest.cc", + "partition_alloc_base/component_export_pa_unittest.cc", + "partition_alloc_base/cpu_pa_unittest.cc", + "partition_alloc_base/logging_pa_unittest.cc", + "partition_alloc_base/no_destructor_pa_unittest.cc", + "partition_alloc_base/rand_util_pa_unittest.cc", + "partition_alloc_base/scoped_clear_last_error_pa_unittest.cc", + "partition_alloc_base/strings/cstring_builder_pa_unittest.cc", + "partition_alloc_base/strings/safe_sprintf_pa_unittest.cc", + "partition_alloc_base/strings/string_util_pa_unittest.cc", + "partition_alloc_base/strings/stringprintf_pa_unittest.cc", + "partition_alloc_base/thread_annotations_pa_unittest.cc", + "partition_alloc_unittest.cc", + "partition_lock_unittest.cc", + "reverse_bytes_unittest.cc", + "slot_start_unittest.cc", + "thread_cache_unittest.cc", + "use_death_tests.h", + ] + } + + if (is_fuchsia) { + sources += + [ "partition_alloc_base/fuchsia/fuchsia_logging_pa_unittest.cc" ] + } + + if (use_allocator_shim) { + sources += [ + "shim/allocator_shim_default_dispatch_to_partition_alloc_unittest.cc", + ] + + if (is_win) { + sources += [ "shim/winheap_stubs_win_unittest.cc" ] + } + + if (is_ios) { + sources += [ + "shim/allocator_interception_apple_unittest.mm", + "shim/malloc_zone_functions_apple_unittest.cc", + ] + } + } + + if ((is_android || is_linux) && target_cpu == "arm64") { + cflags = [ + "-Xclang", + "-target-feature", + "-Xclang", + "+mte", + ] + } + + if (enable_pkeys && is_debug && !is_component_build) { + # This test requires RELRO, which is not enabled in component builds. + # Also, require a debug build, since we only disable stack protectors in + # debug builds in PartitionAlloc (see below why it's needed). + sources += [ "thread_isolation/pkey_unittest.cc" ] + + # We want to test the pkey code without access to memory that is not + # pkey-tagged. This will allow us to catch unintended memory accesses + # that could break our security assumptions. The stack protector reads a + # value from the TLS which won't be pkey-tagged, hence disabling it for + # the test. + configs += [ ":no_stack_protector" ] + } + + frameworks = [] + if (is_mac) { + frameworks += [ + "Foundation.framework", + "OpenCL.framework", + ] + } + + deps = [ + ":partition_alloc", + ":test_support", + "//testing/gmock", + "//testing/gtest", + ] + + configs -= partition_alloc_remove_configs + configs += partition_alloc_add_configs + } +} + +source_set("test_support") { + testonly = true + + sources = [ + "extended_api.cc", + "extended_api.h", + "partition_alloc_base/threading/platform_thread_for_testing.h", + "partition_alloc_for_testing.h", + "pointers/raw_ptr_counting_impl_for_test.h", + ] + if (is_posix) { + sources += [ + "partition_alloc_base/threading/platform_thread_posix_for_testing.cc", + ] + } + if (is_fuchsia) { + sources += [ + "partition_alloc_base/threading/platform_thread_fuchsia_for_testing.cc", + "partition_alloc_base/threading/platform_thread_posix_for_testing.cc", + ] + } + if (is_win) { + sources += + [ "partition_alloc_base/threading/platform_thread_win_for_testing.cc" ] + } + if (is_apple) { + sources += [ + "partition_alloc_base/threading/platform_thread_apple_for_testing.mm", + ] + } + if (is_linux || is_chromeos) { + sources += [ + "partition_alloc_base/threading/platform_thread_linux_for_testing.cc", + ] + } + if (is_android) { + sources += [ + "partition_alloc_base/threading/platform_thread_android_for_testing.cc", + ] + } + public_deps = [ + ":arm_bti_testfunctions", + ":buildflags", + ":partition_alloc", + ":raw_ptr", + ] + public_configs = [] + + if (is_fuchsia) { + public_deps += [ + "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.logger:fuchsia.logger_hlcpp", + "//third_party/fuchsia-sdk/sdk/pkg/fit", + "//third_party/fuchsia-sdk/sdk/pkg/sync", + "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp", + "//third_party/fuchsia-sdk/sdk/pkg/zx", + ] + + # Needed for users of spinning_mutex.h, which for performance reasons, + # contains inlined calls to `libsync` inside the header file. + # It appends an entry to the "libs" section of the dependent target. + public_configs += [ ":fuchsia_sync_lib" ] + } + + configs -= partition_alloc_remove_configs + configs += partition_alloc_add_configs +} + +source_set("arm_bti_testfunctions") { + testonly = true + sources = [] + if (target_cpu == "arm64" && (is_linux || is_android)) { + sources = [ + "arm_bti_test_functions.S", + "arm_bti_test_functions.h", + ] + } +} diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/aarch64_support.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/aarch64_support.h index 556cad562f..aa9eda75e2 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/aarch64_support.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/aarch64_support.h @@ -8,7 +8,7 @@ #include #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if defined(__MUSL__) // Musl does not support ifunc. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.cc index 86462a5f5c..97898f345f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.cc @@ -11,11 +11,10 @@ #include "partition_alloc/address_space_stats.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/page_allocator.h" #include "partition_alloc/page_allocator_constants.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/notreached.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/reservation_offset_table.h" @@ -125,7 +124,7 @@ void AddressPoolManager::Pool::Initialize(uintptr_t ptr, size_t length) { PA_CHECK(!(ptr & kSuperPageOffsetMask)); PA_CHECK(!(length & kSuperPageOffsetMask)); address_begin_ = ptr; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) address_end_ = ptr + length; PA_DCHECK(address_begin_ < address_end_); #endif @@ -204,7 +203,7 @@ uintptr_t AddressPoolManager::Pool::FindChunk(size_t requested_size) { bit_hint_ = end_bit; } uintptr_t address = address_begin_ + beg_bit * kSuperPageSize; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(address + requested_size <= address_end_); #endif return address; @@ -246,7 +245,7 @@ void AddressPoolManager::Pool::FreeChunk(uintptr_t address, size_t free_size) { PA_DCHECK(!(free_size & kSuperPageOffsetMask)); PA_DCHECK(address_begin_ <= address); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(address + free_size <= address_end_); #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.h index a185acbe82..b8694b5d17 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.h @@ -10,12 +10,11 @@ #include "partition_alloc/address_pool_manager_types.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_address_space.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_lock.h" @@ -162,7 +161,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) size_t total_bits_ = 0; uintptr_t address_begin_ = 0; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) uintptr_t address_end_ = 0; #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_bitmap.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_bitmap.cc index c9a83690a5..c0aedbcde9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_bitmap.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_bitmap.cc @@ -4,7 +4,7 @@ #include "partition_alloc/address_pool_manager_bitmap.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_constants.h" #if !PA_BUILDFLAG(HAS_64_BIT_POINTERS) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_bitmap.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_bitmap.h index 61de0b607a..8befb272e8 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_bitmap.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager_bitmap.h @@ -11,9 +11,9 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_lock.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.cc index 1c4e8ea0f4..a24b5523ee 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.cc @@ -5,7 +5,7 @@ #include "partition_alloc/address_space_randomization.h" #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/random.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.h index d0e54446e1..1484444314 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.h @@ -178,8 +178,18 @@ AslrMask(uintptr_t bits) { } #else // !PA_BUILDFLAG(IS_AIX) && !PA_BUILDFLAG(PA_ARCH_CPU_BIG_ENDIAN) + #if PA_BUILDFLAG(IS_LINUX) // Little-endian Linux PPC has 48 bits of virtual addressing. Use 46. + PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR uintptr_t ASLRMask() { + return AslrMask(46); + } + PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR uintptr_t ASLROffset() { + return AslrAddress(0); + } + + #else + PA_ALWAYS_INLINE constexpr uintptr_t ASLRMask() { return AslrMask(46); } @@ -187,6 +197,8 @@ AslrMask(uintptr_t bits) { return AslrAddress(0); } + #endif + #endif // !PA_BUILDFLAG(IS_AIX) && !PA_BUILDFLAG(PA_ARCH_CPU_BIG_ENDIAN) #elif PA_BUILDFLAG(PA_ARCH_CPU_S390X) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_stats.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_stats.h index f87549e946..4fa4f82e3e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_stats.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/address_space_stats.h @@ -7,8 +7,8 @@ #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" namespace partition_alloc { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/build_config.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/build_config.h index f1ffc5664f..410e7ec222 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/build_config.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/build_config.h @@ -48,7 +48,7 @@ #include "partition_alloc/buildflag.h" // IWYU pragma: export // Definition of PA_BUILDFLAG(IS_CHROMEOS). -#include "partition_alloc/chromeos_buildflags.h" // IWYU pragma: export +#include "partition_alloc/buildflags.h" // IWYU pragma: export // Clangd does not detect PA_BUILDFLAG_INTERNAL_* indirect usage, so mark the // header as "always_keep" to avoid "unused include" warning. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni index a1c752a2bc..979042758e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni @@ -116,6 +116,6 @@ template("pa_buildflag_header") { "visibility", ]) - public_deps = [ "${_current_dir}:build_config" ] + public_deps = [ "${_current_dir}:buildflag_macro" ] } } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/compressed_pointer.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/compressed_pointer.cc index 04b36461c6..6a62a27c9b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/compressed_pointer.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/compressed_pointer.cc @@ -3,7 +3,8 @@ // found in the LICENSE file. #include "partition_alloc/compressed_pointer.h" -#include "partition_alloc/partition_alloc_buildflags.h" + +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(ENABLE_POINTER_COMPRESSION) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/compressed_pointer.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/compressed_pointer.h index 0a8aa1c25d..1182b61ccf 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/compressed_pointer.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/compressed_pointer.h @@ -5,14 +5,14 @@ #ifndef PARTITION_ALLOC_COMPRESSED_POINTER_H_ #define PARTITION_ALLOC_COMPRESSED_POINTER_H_ -#include #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_address_space.h" +#include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" #if PA_BUILDFLAG(ENABLE_POINTER_COMPRESSION) @@ -78,7 +78,7 @@ constexpr bool IsDecayedSame = class CompressedPointerBaseGlobal final { public: static constexpr size_t kUsefulBits = - std::countr_zero(PartitionAddressSpace::CorePoolsSize()); + base::bits::CountrZero(PartitionAddressSpace::CorePoolsSize()); static_assert(kUsefulBits >= sizeof(uint32_t) * CHAR_BIT); static constexpr size_t kBitsToShift = kUsefulBits - sizeof(uint32_t) * CHAR_BIT; @@ -232,7 +232,7 @@ class PA_TRIVIAL_ABI CompressedPointer final { static constexpr size_t kMinimalRequiredAlignment = 8; static_assert((1 << kOverallBitsToShift) == kMinimalRequiredAlignment); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(reinterpret_cast(ptr) % kMinimalRequiredAlignment == 0); PA_DCHECK(internal::CompressedPointerBaseGlobal::IsSet()); @@ -243,7 +243,7 @@ class PA_TRIVIAL_ABI CompressedPointer final { PA_DCHECK(!ptr || (base & kCorePoolsBaseMask) == (reinterpret_cast(ptr) & kCorePoolsBaseMask)); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) const auto uptr = reinterpret_cast(ptr); // Shift the pointer and truncate. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/encoded_next_freelist.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/encoded_next_freelist.h index 047749257e..42ff1d828d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/encoded_next_freelist.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/encoded_next_freelist.h @@ -9,11 +9,10 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/freeslot_bitmap.h" #include "partition_alloc/partition_alloc-inl.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -177,7 +176,7 @@ class EncodedNextFreelistEntry { // SetNext() is either called on the freelist head, when provisioning new // slots, or when GetNext() has been called before, no need to pass the // size. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Regular freelists always point to an entry within the same super page. // // This is most likely a PartitionAlloc bug if this triggers. @@ -186,7 +185,7 @@ class EncodedNextFreelistEntry { (SlotStartPtr2Addr(entry) & kSuperPageBaseMask))) { FreelistCorruptionDetected(0); } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) encoded_next_ = EncodedFreelistPtr(entry); #if PA_CONFIG(HAS_FREELIST_SHADOW_ENTRY) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/extended_api.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/extended_api.cc index b8d4156a78..e2898d7cd4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/extended_api.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/extended_api.cc @@ -4,7 +4,7 @@ #include "partition_alloc/extended_api.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h" #include "partition_alloc/thread_cache.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/extended_api.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/extended_api.h index b3577c892d..0b4be9a029 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/extended_api.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/extended_api.h @@ -5,7 +5,7 @@ #ifndef PARTITION_ALLOC_EXTENDED_API_H_ #define PARTITION_ALLOC_EXTENDED_API_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_root.h" #include "partition_alloc/partition_stats.h" #include "partition_alloc/thread_cache.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/freeslot_bitmap.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/freeslot_bitmap.h index e9708013fd..f8fdfefaaa 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/freeslot_bitmap.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/freeslot_bitmap.h @@ -9,10 +9,10 @@ #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/freeslot_bitmap_constants.h" #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_constants.h" #if PA_BUILDFLAG(USE_FREESLOT_BITMAP) @@ -92,7 +92,7 @@ PA_ALWAYS_INLINE void FreeSlotBitmapReset(uintptr_t begin_addr, *cell &= ~CellWithAOne(bit_index); } -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Checks if the cells that are meant to contain only unset bits are really 0. auto [begin_cell, begin_bit_index] = GetFreeSlotBitmapCellPtrAndBitIndex(begin_addr); @@ -131,7 +131,7 @@ PA_ALWAYS_INLINE void FreeSlotBitmapReset(uintptr_t begin_addr, for (FreeSlotBitmapCellType* cell = begin_cell; cell < end_cell; ++cell) { PA_DCHECK(*cell == 0u); } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) } } // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/freeslot_bitmap_constants.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/freeslot_bitmap_constants.h index 8faf77a403..87df099190 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/freeslot_bitmap_constants.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/freeslot_bitmap_constants.h @@ -7,9 +7,9 @@ #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_alloc_forward.h" #include "partition_alloc/reservation_offset_table.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.cc index 5e9fc045c7..d9a41e53e5 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.cc @@ -19,17 +19,21 @@ namespace partition_alloc { +namespace { +PartitionOptions GwpAsanPartitionOptions() { + PartitionOptions options; + options.backup_ref_ptr = PartitionOptions::kEnabled; + return options; +} +} // namespace + // static void* GwpAsanSupport::MapRegion(size_t slot_count, std::vector& free_list) { PA_CHECK(slot_count > 0); - constexpr PartitionOptions kConfig = []() { - PartitionOptions opts; - opts.backup_ref_ptr = PartitionOptions::kEnabled; - return opts; - }(); - static internal::base::NoDestructor root(kConfig); + static internal::base::NoDestructor root( + GwpAsanPartitionOptions()); const size_t kSlotSize = 2 * internal::SystemPageSize(); uint16_t bucket_index = PartitionRoot::SizeToBucketIndex( diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.h index 6e8b28f36f..2c3e7be105 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.h @@ -5,8 +5,8 @@ #ifndef PARTITION_ALLOC_GWP_ASAN_SUPPORT_H_ #define PARTITION_ALLOC_GWP_ASAN_SUPPORT_H_ +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" #if PA_BUILDFLAG(ENABLE_GWP_ASAN_SUPPORT) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.h index 65c736adc5..61230503de 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/in_slot_metadata.h @@ -6,28 +6,23 @@ #define PARTITION_ALLOC_IN_SLOT_METADATA_H_ #include -#include #include #include #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/dangling_raw_ptr_checks.h" +#include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/immediate_crash.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_alloc_forward.h" #include "partition_alloc/tagging.h" -#if PA_BUILDFLAG(IS_APPLE) -#include "partition_alloc/partition_alloc_base/bits.h" -#endif // PA_BUILDFLAG(IS_APPLE) - namespace partition_alloc::internal { // Aligns up (on 8B boundary) `in_slot_metadata_size` on Mac as a workaround for @@ -40,10 +35,10 @@ namespace partition_alloc::internal { // Placed outside `PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)` // intentionally to accommodate usage in contexts also outside // this gating. -PA_ALWAYS_INLINE size_t -AlignUpInSlotMetadataSizeForApple(size_t in_slot_metadata_size) { +PA_ALWAYS_INLINE constexpr size_t AlignUpInSlotMetadataSizeForApple( + size_t in_slot_metadata_size) { #if PA_BUILDFLAG(IS_APPLE) - return internal::base::bits::AlignUp(in_slot_metadata_size, 8); + return base::bits::AlignUp(in_slot_metadata_size, 8); #else return in_slot_metadata_size; #endif // PA_BUILDFLAG(IS_APPLE) @@ -171,9 +166,9 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) InSlotMetadata { std::numeric_limits::max()); static constexpr auto kPtrInc = - SafeShift(1, std::countr_zero(kPtrCountMask)); + SafeShift(1, base::bits::CountrZero(kPtrCountMask)); static constexpr auto kUnprotectedPtrInc = - SafeShift(1, std::countr_zero(kUnprotectedPtrCountMask)); + SafeShift(1, base::bits::CountrZero(kUnprotectedPtrCountMask)); PA_ALWAYS_INLINE explicit InSlotMetadata(bool needs_mac11_malloc_size_hack); @@ -550,7 +545,7 @@ PA_ALWAYS_INLINE InSlotMetadata* InSlotMetadataPointer(uintptr_t slot_start, if (PA_LIKELY(slot_start & SystemPageOffsetMask())) { uintptr_t refcount_address = slot_start + slot_size - sizeof(InSlotMetadata); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_CHECK(refcount_address % alignof(InSlotMetadata) == 0); #endif @@ -563,7 +558,7 @@ PA_ALWAYS_INLINE InSlotMetadata* InSlotMetadataPointer(uintptr_t slot_start, (slot_start & kSuperPageBaseMask) + SystemPageSize() * 2); size_t index = ((slot_start & kSuperPageOffsetMask) >> SystemPageShift()) << GetInSlotMetadataIndexMultiplierShift(); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_CHECK(sizeof(InSlotMetadata) * index <= SystemPageSize()); #endif @@ -575,7 +570,7 @@ PA_ALWAYS_INLINE InSlotMetadata* InSlotMetadataPointer(uintptr_t slot_start, static inline constexpr size_t kInSlotMetadataSizeAdjustment = #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - sizeof(InSlotMetadata); + AlignUpInSlotMetadataSizeForApple(sizeof(InSlotMetadata)); #else 0ul; #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator.h index ec042f83fd..4e6ed30024 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator.h @@ -26,7 +26,7 @@ PartitionRoot& InternalAllocatorRoot(); // A class that meets C++ named requirements, Allocator. template -InternalAllocator::value_type* InternalAllocator::allocate( +typename InternalAllocator::value_type* InternalAllocator::allocate( std::size_t count) { PA_CHECK(count <= std::numeric_limits::max() / sizeof(value_type)); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc index 5b59466204..c40f6dfe46 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc @@ -64,8 +64,9 @@ LightweightQuarantineBranch::~LightweightQuarantineBranch() { bool LightweightQuarantineBranch::Quarantine(void* object, SlotSpanMetadata* slot_span, - uintptr_t slot_start) { - const auto usable_size = root_.allocator_root_.GetSlotUsableSize(slot_span); + uintptr_t slot_start, + size_t usable_size) { + PA_DCHECK(usable_size == root_.allocator_root_.GetSlotUsableSize(slot_span)); const size_t capacity_in_bytes = branch_capacity_in_bytes_.load(std::memory_order_relaxed); @@ -86,7 +87,7 @@ bool LightweightQuarantineBranch::Quarantine(void* object, // Put the entry onto the list. branch_size_in_bytes_ += usable_size; - slots_.emplace_back(slot_start, usable_size); + slots_.push_back({slot_start, usable_size}); // Swap randomly so that the quarantine list remain shuffled. // This is not uniformly random, but sufficiently random. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h index 82e1956986..0e5ea66ac9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h @@ -110,7 +110,8 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LightweightQuarantineBranch { // immediately). Otherwise, returns `true`. bool Quarantine(void* object, SlotSpanMetadata* slot_span, - uintptr_t slot_start); + uintptr_t slot_start, + size_t usable_size); // Dequarantine all entries **held by this branch**. // It is possible that another branch with entries and it remains untouched. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.cc index a388426e9c..a13f20b073 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer.cc @@ -4,16 +4,12 @@ #include "partition_alloc/memory_reclaimer.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc.h" #include "partition_alloc/partition_alloc_base/no_destructor.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/starscan/pcscan.h" -#endif - namespace partition_alloc { // static @@ -63,26 +59,6 @@ void MemoryReclaimer::Reclaim(int flags) { internal::ScopedGuard lock( lock_); // Has to protect from concurrent (Un)Register calls. - // PCScan quarantines freed slots. Trigger the scan first to let it call - // FreeNoHooksImmediate on slots that pass the quarantine. - // - // In turn, FreeNoHooksImmediate may add slots to thread cache. Purge it next - // so that the slots are actually freed. (This is done synchronously only for - // the current thread.) - // - // Lastly decommit empty slot spans and lastly try to discard unused pages at - // the end of the remaining active slots. -#if PA_CONFIG(STARSCAN_ENABLE_STARSCAN_ON_RECLAIM) && PA_BUILDFLAG(USE_STARSCAN) - { - using PCScan = internal::PCScan; - const auto invocation_mode = flags & PurgeFlags::kAggressiveReclaim - ? PCScan::InvocationMode::kForcedBlocking - : PCScan::InvocationMode::kBlocking; - PCScan::PerformScanIfNeeded(invocation_mode); - } -#endif // PA_CONFIG(STARSCAN_ENABLE_STARSCAN_ON_RECLAIM) && - // PA_BUILDFLAG(USE_STARSCAN) - #if PA_CONFIG(THREAD_CACHE_SUPPORTED) // Don't completely empty the thread cache outside of low memory situations, // as there is periodic purge which makes sure that it doesn't take too much diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator.cc index f0e653192b..7700900906 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator.cc @@ -5,12 +5,12 @@ #include "partition_alloc/page_allocator.h" #include -#include #include #include "partition_alloc/address_space_randomization.h" #include "partition_alloc/build_config.h" #include "partition_alloc/page_allocator_internal.h" +#include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_lock.h" @@ -79,7 +79,7 @@ uintptr_t TrimMapping(uintptr_t base_address, uintptr_t alignment_offset, PageAccessibilityConfiguration accessibility) { PA_DCHECK(base_length >= trim_length); - PA_DCHECK(std::has_single_bit(alignment)); + PA_DCHECK(internal::base::bits::HasSingleBit(alignment)); PA_DCHECK(alignment_offset < alignment); uintptr_t new_base = NextAlignedWithOffset(base_address, alignment, alignment_offset); @@ -108,7 +108,7 @@ uintptr_t TrimMapping(uintptr_t base_address, uintptr_t NextAlignedWithOffset(uintptr_t address, uintptr_t alignment, uintptr_t requested_offset) { - PA_DCHECK(std::has_single_bit(alignment)); + PA_DCHECK(internal::base::bits::HasSingleBit(alignment)); PA_DCHECK(requested_offset < alignment); uintptr_t actual_offset = address & (alignment - 1); @@ -183,7 +183,7 @@ uintptr_t AllocPagesWithAlignOffset( PA_DCHECK(!(length & internal::PageAllocationGranularityOffsetMask())); PA_DCHECK(align >= internal::PageAllocationGranularity()); // Alignment must be power of 2 for masking math to work. - PA_DCHECK(std::has_single_bit(align)); + PA_DCHECK(internal::base::bits::HasSingleBit(align)); PA_DCHECK(align_offset < align); PA_DCHECK(!(align_offset & internal::PageAllocationGranularityOffsetMask())); PA_DCHECK(!(address & internal::PageAllocationGranularityOffsetMask())); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator.h index 51f8eefe48..d3585b6051 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator.h @@ -9,10 +9,10 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/page_allocator_constants.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/thread_isolation/thread_isolation.h" namespace partition_alloc { @@ -173,6 +173,14 @@ void FreePages(void* address, size_t length); // // Returns true if the permission change succeeded. In most cases you must // |CHECK| the result. +// +// Note: On Windows, setting permissions to `PAGE_NOACCESS` will also decommit +// pages. This is desirable because clients assume that pages with no access +// rights should be "free" from a resource standpoint. In particular this allows +// clients to map a large amount of memory, set its access rights to +// `PAGE_NOACCESS` and not worry about commit limit exhaustion. +// On the flip side, this means that changing permissions can often fail on this +// platform. [[nodiscard]] PA_COMPONENT_EXPORT(PARTITION_ALLOC) bool TrySetSystemPagesAccess( uintptr_t address, size_t length, @@ -187,6 +195,8 @@ void FreePages(void* address, size_t length); // bytes. // // Performs a CHECK that the operation succeeds. +// +// See the note above for Windows-specific behavior. PA_COMPONENT_EXPORT(PARTITION_ALLOC) void SetSystemPagesAccess(uintptr_t address, size_t length, @@ -323,6 +333,13 @@ void RecommitSystemPages( // that the page is required again. Once written to, the content of the page is // guaranteed stable once more. After being written to, the page content may be // based on the original page content, or a page of zeroes. +// +// WARNING: Do not discard a large amount of pages, for a potentially long +// duration. Discarded pages are *not* decommitted on Windows, where total +// system-wide committed memory is limited. As most Chromium OOM crashes are +// commit limit related, this will both impact Private Memory Footprint (which +// reports committed memory) and stability (since we will bump into the limit +// more often). PA_COMPONENT_EXPORT(PARTITION_ALLOC) void DiscardSystemPages(uintptr_t address, size_t length); PA_COMPONENT_EXPORT(PARTITION_ALLOC) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h index 3c94e1ea9e..7265e5355e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_constants.h @@ -26,7 +26,8 @@ #define PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR __attribute__((const)) #elif (PA_BUILDFLAG(IS_ANDROID) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS)) || \ - (PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_ARM64)) + (PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_ARM64)) || \ + (PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_PPC64)) // This should work for all POSIX (if needed), but currently all other // supported OS/architecture combinations use either hard-coded values // (such as x86) or have means to determine these values without needing @@ -86,17 +87,7 @@ PageAllocationGranularity(); PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t PageAllocationGranularityShift() { -#if PA_BUILDFLAG(IS_WIN) || PA_BUILDFLAG(PA_ARCH_CPU_PPC64) - // Modern ppc64 systems support 4kB (shift = 12) and 64kB (shift = 16) page - // sizes. Since 64kB is the de facto standard on the platform and binaries - // compiled for 64kB are likely to work on 4kB systems, 64kB is a good choice - // here. - return 16; // 64kB -#elif defined(_MIPS_ARCH_LOONGSON) || PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64) - return 14; // 16kB -#elif PA_BUILDFLAG(IS_APPLE) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS) - return static_cast(vm_page_shift); -#elif defined(PARTITION_ALLOCATOR_CONSTANTS_POSIX_NONCONST_PAGE_SIZE) +#if defined(PARTITION_ALLOCATOR_CONSTANTS_POSIX_NONCONST_PAGE_SIZE) // arm64 supports 4kb (shift = 12), 16kb (shift = 14), and 64kb (shift = 16) // page sizes. Retrieve from or initialize cache. size_t shift = page_characteristics.shift.load(std::memory_order_relaxed); @@ -106,6 +97,26 @@ PageAllocationGranularityShift() { page_characteristics.shift.store(shift, std::memory_order_relaxed); } return shift; +#elif PA_BUILDFLAG(IS_WIN) || PA_BUILDFLAG(PA_ARCH_CPU_PPC64) + // Modern ppc64 systems support 4kB (shift = 12) and 64kB (shift = 16) page + // sizes. Since 64kB is the de facto standard on the platform and binaries + // compiled for 64kB are likely to work on 4kB systems, 64kB is a good choice + // here. + return 16; // 64kB +#elif defined(_MIPS_ARCH_LOONGSON) || PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64) + return 14; // 16kB +#elif PA_BUILDFLAG(IS_APPLE) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS) + return static_cast(vm_page_shift); +#elif PA_BUILDFLAG(IS_WIN) || PA_BUILDFLAG(PA_ARCH_CPU_PPC64) + // Modern ppc64 systems support 4kB (shift = 12) and 64kB (shift = 16) page + // sizes. Since 64kB is the de facto standard on the platform and binaries + // compiled for 64kB are likely to work on 4kB systems, 64kB is a good choice + // here. + return 16; // 64kB +#elif defined(_MIPS_ARCH_LOONGSON) || PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64) + return 14; // 16kB +#elif PA_BUILDFLAG(IS_APPLE) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS) + return static_cast(vm_page_shift); #else return 12; // 4kB #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc index d99ddd5531..26feb70e30 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc @@ -5,8 +5,8 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/page_allocator.h" -#include "partition_alloc/partition_alloc_buildflags.h" #if PA_BUILDFLAG(HAS_MEMORY_TAGGING) || \ (defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT == 1) && \ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.h index 3c4a17dc7e..7423413278 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.h @@ -14,10 +14,10 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/oom.h" #include "partition_alloc/page_allocator.h" #include "partition_alloc/page_allocator_constants.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/notreached.h" #include "partition_alloc/partition_alloc_base/posix/eintr_wrapper.h" #include "partition_alloc/partition_alloc_check.h" @@ -299,14 +299,14 @@ void DecommitSystemPagesInternal( bool change_permissions = accessibility_disposition == PageAccessibilityDisposition::kRequireUpdate; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // This is not guaranteed, show that we're serious. // // More specifically, several callers have had issues with assuming that // memory is zeroed, this would hopefully make these bugs more visible. We // don't memset() everything, because ranges can be very large, and doing it // over the entire range could make Chrome unusable with - // PA_BUILDFLAG(PA_DCHECK_IS_ON). + // PA_BUILDFLAG(DCHECKS_ARE_ON). // // Only do it when we are about to change the permissions, since we don't know // the previous permissions, and cannot restore them. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_win.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_win.h index 76d76fc467..eb117d5897 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_win.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_win.h @@ -7,11 +7,11 @@ #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/oom.h" #include "partition_alloc/page_allocator.h" #include "partition_alloc/page_allocator_internal.h" #include "partition_alloc/partition_alloc_base/notreached.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" namespace partition_alloc::internal { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.cc index b203261365..87b247ea53 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.cc @@ -5,7 +5,6 @@ #include "partition_alloc/partition_address_space.h" #include -#include #include #include #include @@ -13,11 +12,12 @@ #include "partition_alloc/address_pool_manager.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/compressed_pointer.h" #include "partition_alloc/page_allocator.h" +#include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/debug/alias.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -183,6 +183,19 @@ void PartitionAddressSpace::Init() { PageAccessibilityConfiguration( PageAccessibilityConfiguration::kInaccessible), PageTag::kPartitionAlloc, pools_fd); +#if PA_BUILDFLAG(IS_ANDROID) + // On Android, Adreno-GSL library fails to mmap if we snatch address + // 0x400000000. Find a different address instead. + if (setup_.regular_pool_base_address_ == 0x400000000) { + uintptr_t new_base_address = + AllocPages(glued_pool_sizes, glued_pool_sizes, + PageAccessibilityConfiguration( + PageAccessibilityConfiguration::kInaccessible), + PageTag::kPartitionAlloc, pools_fd); + FreePages(setup_.regular_pool_base_address_, glued_pool_sizes); + setup_.regular_pool_base_address_ = new_base_address; + } +#endif // PA_BUILDFLAG(IS_ANDROID) if (!setup_.regular_pool_base_address_) { HandlePoolAllocFailure(); } @@ -263,16 +276,6 @@ void PartitionAddressSpace::Init() { PA_DCHECK(!IsInCorePools(setup_.brp_pool_base_address_ + brp_pool_size)); #endif // PA_BUILDFLAG(GLUE_CORE_POOLS) -#if PA_CONFIG(STARSCAN_USE_CARD_TABLE) - // Reserve memory for PCScan quarantine card table. - uintptr_t requested_address = setup_.regular_pool_base_address_; - uintptr_t actual_address = AddressPoolManager::GetInstance().Reserve( - kRegularPoolHandle, requested_address, kSuperPageSize); - PA_CHECK(requested_address == actual_address) - << "QuarantineCardTable is required to be allocated at the beginning of " - "the regular pool"; -#endif // PA_CONFIG(STARSCAN_USE_CARD_TABLE) - #if PA_BUILDFLAG(ENABLE_POINTER_COMPRESSION) CompressedPointerBaseGlobal::SetBase(setup_.regular_pool_base_address_); #endif // PA_BUILDFLAG(ENABLE_POINTER_COMPRESSION) @@ -295,7 +298,7 @@ void PartitionAddressSpace::InitConfigurablePool(uintptr_t pool_base, PA_CHECK(pool_base); PA_CHECK(size <= kConfigurablePoolMaxSize); PA_CHECK(size >= kConfigurablePoolMinSize); - PA_CHECK(std::has_single_bit(size)); + PA_CHECK(base::bits::HasSingleBit(size)); PA_CHECK(pool_base % size == 0); setup_.configurable_pool_base_address_ = pool_base; @@ -401,7 +404,7 @@ void PartitionAddressSpace::UninitConfigurablePoolForTesting() { void PartitionAddressSpace::UninitThreadIsolatedPoolForTesting() { if (IsThreadIsolatedPoolInitialized()) { UnprotectThreadIsolatedGlobals(); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) ThreadIsolationSettings::settings.enabled = false; #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h index 4e69c22e65..8cd883f0b4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h @@ -5,17 +5,17 @@ #ifndef PARTITION_ALLOC_PARTITION_ADDRESS_SPACE_H_ #define PARTITION_ALLOC_PARTITION_ADDRESS_SPACE_H_ -#include #include #include #include "partition_alloc/address_pool_manager_types.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/page_allocator_constants.h" +#include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" #include "partition_alloc/partition_alloc_base/notreached.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -315,7 +315,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace { "because the test process cannot use an extended virtual address space. " "Temporarily disable ShadowMetadata feature on iOS"); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Check whether the given |ptr| points to an address inside the address space // reserved for the regular and brp shadow. However the result |true| doesn't // mean the given |ptr| is valid. Because we don't use the entire address @@ -328,7 +328,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace { ptr_as_uintptr < pool_shadow_address_ + BRPPoolSize() || ptr_as_uintptr < pool_shadow_address_ + kConfigurablePoolMaxSize)); } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) static void InitShadowMetadata(PoolHandleMask pool); static void MapMetadata(uintptr_t super_page, bool copy_metadata); @@ -382,17 +382,17 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace { // ArrayBuffers be located inside of it. static constexpr size_t kRegularPoolSize = kPoolMaxSize; static constexpr size_t kBRPPoolSize = kPoolMaxSize; - static_assert(std::has_single_bit(kRegularPoolSize)); - static_assert(std::has_single_bit(kBRPPoolSize)); + static_assert(base::bits::HasSingleBit(kRegularPoolSize)); + static_assert(base::bits::HasSingleBit(kBRPPoolSize)); #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) static constexpr size_t kThreadIsolatedPoolSize = kGiB / 4; - static_assert(std::has_single_bit(kThreadIsolatedPoolSize)); + static_assert(base::bits::HasSingleBit(kThreadIsolatedPoolSize)); #endif static constexpr size_t kConfigurablePoolMaxSize = kPoolMaxSize; static constexpr size_t kConfigurablePoolMinSize = 1 * kGiB; static_assert(kConfigurablePoolMinSize <= kConfigurablePoolMaxSize); - static_assert(std::has_single_bit(kConfigurablePoolMaxSize)); - static_assert(std::has_single_bit(kConfigurablePoolMinSize)); + static_assert(base::bits::HasSingleBit(kConfigurablePoolMaxSize)); + static_assert(base::bits::HasSingleBit(kConfigurablePoolMinSize)); #if PA_BUILDFLAG(IS_IOS) @@ -407,8 +407,8 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace { static constexpr size_t kBRPPoolSizeForIOSTestProcess = kGiB / 4; static_assert(kRegularPoolSizeForIOSTestProcess < kRegularPoolSize); static_assert(kBRPPoolSizeForIOSTestProcess < kBRPPoolSize); - static_assert(std::has_single_bit(kRegularPoolSizeForIOSTestProcess)); - static_assert(std::has_single_bit(kBRPPoolSizeForIOSTestProcess)); + static_assert(base::bits::HasSingleBit(kRegularPoolSizeForIOSTestProcess)); + static_assert(base::bits::HasSingleBit(kBRPPoolSizeForIOSTestProcess)); #endif // PA_BUILDFLAG(IOS_IOS) #if !PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc-inl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc-inl.h index 7d11185a94..78d81e3d8a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc-inl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc-inl.h @@ -9,9 +9,9 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/in_slot_metadata.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/random.h" #include "partition_alloc/tagging.h" @@ -57,7 +57,7 @@ PA_ALWAYS_INLINE void SecureMemset(void* ptr, uint8_t value, size_t size) { #pragma optimize("", on) #endif -#if PA_BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON) +#if PA_BUILDFLAG(EXPENSIVE_DCHECKS_ARE_ON) // Used to memset() memory for debugging purposes only. PA_ALWAYS_INLINE void DebugMemset(void* ptr, int value, size_t size) { // Only set the first 512kiB of the allocation. This is enough to detect uses @@ -71,12 +71,12 @@ PA_ALWAYS_INLINE void DebugMemset(void* ptr, int value, size_t size) { size_t size_to_memset = std::min(size, size_t{1} << 19); memset(ptr, value, size_to_memset); } -#endif // PA_BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON) +#endif // PA_BUILDFLAG(EXPENSIVE_DCHECKS_ARE_ON) // Returns true if we've hit the end of a random-length period. We don't want to // invoke `RandomValue` too often, because we call this function in a hot spot // (`Free`), and `RandomValue` incurs the cost of atomics. -#if !PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if !PA_BUILDFLAG(DCHECKS_ARE_ON) PA_ALWAYS_INLINE bool RandomPeriod() { static thread_local uint8_t counter = 0; if (PA_UNLIKELY(counter == 0)) { @@ -87,7 +87,7 @@ PA_ALWAYS_INLINE bool RandomPeriod() { counter--; return counter == 0; } -#endif // !PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // !PA_BUILDFLAG(DCHECKS_ARE_ON) PA_ALWAYS_INLINE uintptr_t ObjectInnerPtr2Addr(const void* ptr) { return UntagPtr(ptr); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.cc index 18d9997ca3..554033f9b3 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc.cc @@ -9,10 +9,9 @@ #include #include "partition_alloc/address_pool_manager.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/memory_reclaimer.h" #include "partition_alloc/partition_address_space.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_hooks.h" #include "partition_alloc/partition_direct_map_extent.h" #include "partition_alloc/partition_oom.h" @@ -20,10 +19,6 @@ #include "partition_alloc/partition_root.h" #include "partition_alloc/partition_stats.h" -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/starscan/pcscan.h" -#endif - namespace partition_alloc { void PartitionAllocGlobalInit(OomFunction on_out_of_memory) { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_allocation_data.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_allocation_data.h index afe38ae76e..e0fd180113 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_allocation_data.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_allocation_data.h @@ -7,8 +7,8 @@ #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/tagging.h" namespace partition_alloc { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.h index b3ff53ab14..719e4c0677 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.h @@ -8,8 +8,8 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/logging.h" // Use the PA_MACH_LOG family of macros along with a mach_error_t @@ -47,7 +47,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) MachLogMessage } // namespace partition_alloc::internal::logging -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_MACH_DVLOG_IS_ON(verbose_level) PA_VLOG_IS_ON(verbose_level) #else #define PA_MACH_DVLOG_IS_ON(verbose_level) 0 @@ -91,9 +91,9 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) MachLogMessage PA_LAZY_STREAM(PA_MACH_VLOG_STREAM(verbose_level, mach_err), \ PA_MACH_DVLOG_IS_ON(verbose_level) && (condition)) -#define PA_MACH_DCHECK(condition, mach_err) \ - PA_LAZY_STREAM(PA_MACH_LOG_STREAM(FATAL, mach_err), \ - PA_BUILDFLAG(PA_DCHECK_IS_ON) && !(condition)) \ +#define PA_MACH_DCHECK(condition, mach_err) \ + PA_LAZY_STREAM(PA_MACH_LOG_STREAM(FATAL, mach_err), \ + PA_BUILDFLAG(DCHECKS_ARE_ON) && !(condition)) \ << "Check failed: " #condition << ". " #endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_APPLE_MACH_LOGGING_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits.h index 23239726e1..5776352fd5 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits.h @@ -7,37 +7,42 @@ #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_BITS_H_ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_BITS_H_ -#include -#include #include #include +#include +#include "partition_alloc/build_config.h" +#include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/check.h" +#include "partition_alloc/partition_alloc_base/compiler_specific.h" namespace partition_alloc::internal::base::bits { -// Bit functions in are restricted to a specific set of types of unsigned -// integer; restrict functions in this file that are related to those in that -// header to match for consistency. -template -concept UnsignedInteger = - std::unsigned_integral && !std::same_as && - !std::same_as && !std::same_as && - !std::same_as && !std::same_as && - !std::same_as; +// Backport of C++20 std::has_single_bit in . +// +// Returns true iff |value| is a power of 2. +template >> +constexpr bool HasSingleBit(T value) { + // From "Hacker's Delight": Section 2.1 Manipulating Rightmost Bits. + // + // Only positive integers with a single bit set are powers of two. If only one + // bit is set in x (e.g. 0b00000100000000) then |x-1| will have that bit set + // to zero and all bits to its right set to 1 (e.g. 0b00000011111111). Hence + // |x & (x-1)| is 0 iff x is a power of two. + return value > 0 && (value & (value - 1)) == 0; +} // Round down |size| to a multiple of alignment, which must be a power of two. template - requires UnsignedInteger inline constexpr T AlignDown(T size, T alignment) { - PA_BASE_DCHECK(std::has_single_bit(alignment)); + static_assert(std::is_unsigned_v); + PA_BASE_DCHECK(HasSingleBit(alignment)); return size & ~(alignment - 1); } // Move |ptr| back to the previous multiple of alignment, which must be a power // of two. Defined for types where sizeof(T) is one byte. template - requires(sizeof(T) == 1) inline T* AlignDown(T* ptr, size_t alignment) { return reinterpret_cast( AlignDown(reinterpret_cast(ptr), alignment)); @@ -45,54 +50,105 @@ inline T* AlignDown(T* ptr, size_t alignment) { // Round up |size| to a multiple of alignment, which must be a power of two. template - requires UnsignedInteger inline constexpr T AlignUp(T size, T alignment) { - PA_BASE_DCHECK(std::has_single_bit(alignment)); + static_assert(std::is_unsigned_v); + PA_BASE_DCHECK(HasSingleBit(alignment)); return (size + alignment - 1) & ~(alignment - 1); } // Advance |ptr| to the next multiple of alignment, which must be a power of // two. Defined for types where sizeof(T) is one byte. template - requires(sizeof(T) == 1) inline T* AlignUp(T* ptr, size_t alignment) { return reinterpret_cast( AlignUp(reinterpret_cast(ptr), alignment)); } -// Returns the integer i such as 2^i <= n < 2^(i+1). +// Backport of C++20 std::countl_zero in . // -// A common use for this function is to measure the number of bits required to -// contain a value; for that case use std::bit_width(). +// CountlZero(value) returns the number of zero bits following the +// most significant 1 bit in |value| if |value| is non-zero, otherwise it +// returns {sizeof(T) * 8}. +// Example: 00100010 -> 2 // -// A common use for this function is to take its result and use it to left-shift -// a bit; instead of doing so, use std::bit_floor(). -constexpr int Log2Floor(uint32_t n) { - return 31 - std::countl_zero(n); +// CountrZero(value) returns the number of zero bits preceding the +// least significant 1 bit in |value| if |value| is non-zero, otherwise it +// returns {sizeof(T) * 8}. +// Example: 00100010 -> 1 +// +// C does not have an operator to do this, but fortunately the various +// compilers have built-ins that map to fast underlying processor instructions. +// __builtin_clz has undefined behaviour for an input of 0, even though there's +// clearly a return value that makes sense, and even though some processor clz +// instructions have defined behaviour for 0. We could drop to raw __asm__ to +// do better, but we'll avoid doing that unless we see proof that we need to. +template +PA_ALWAYS_INLINE constexpr + typename std::enable_if && sizeof(T) <= 8, int>::type + CountlZero(T value) { + static_assert(bits > 0, "invalid instantiation"); +#if PA_BUILDFLAG(PA_COMPILER_MSVC) && !defined(__clang__) + // We would prefer to use the _BitScanReverse(64) intrinsics, but they + // aren't constexpr and thus unusable here. + if (PA_LIKELY(value)) { + int leading_zeros = 0; + constexpr T kMostSignificantBitMask = 1ull << (bits - 1); + for (; !(value & kMostSignificantBitMask); value <<= 1, ++leading_zeros) { + } + return leading_zeros; + } + return bits; +#else + return PA_LIKELY(value) + ? bits == 64 + ? __builtin_clzll(static_cast(value)) + : __builtin_clz(static_cast(value)) - (32 - bits) + : bits; +#endif // PA_BUILDFLAG(PA_COMPILER_MSVC) && !defined(__clang__) +} + +// Backport of C++20 std::countr_zero in . +// +// Returns the number of consecutive 0 bits, starting from the least significant +// one. +template +PA_ALWAYS_INLINE constexpr + typename std::enable_if && sizeof(T) <= 8, int>::type + CountrZero(T value) { +#if PA_BUILDFLAG(PA_COMPILER_MSVC) && !defined(__clang__) + // We would prefer to use the _BitScanForward(64) intrinsics, but they + // aren't constexpr and thus unusable here. + if (PA_LIKELY(value)) { + int trailing_zeros = 0; + constexpr T kLeastSignificantBitMask = 1ull; + for (; !(value & kLeastSignificantBitMask); value >>= 1, ++trailing_zeros) { + } + return trailing_zeros; + } + return bits; + +#else + return PA_LIKELY(value) ? bits == 64 + ? __builtin_ctzll(static_cast(value)) + : __builtin_ctz(static_cast(value)) + : bits; +#endif // PA_BUILDFLAG(PA_COMPILER_MSVC) && !defined(__clang__) +} + +// Backport of C++20 std::bit_width in . +// +// Returns the smallest i such as n <= 2^i. +// This represent the number of bits needed to store values up to n. +constexpr int BitWidth(uint32_t n) { + return 32 - CountlZero(n); } // Returns the integer i such as 2^(i-1) < n <= 2^i. -// -// A common use for this function is to measure the number of bits required to -// contain a value; for that case use std::bit_width(). -// -// A common use for this function is to take its result and use it to left-shift -// a bit; instead of doing so, use std::bit_ceil(). constexpr int Log2Ceiling(uint32_t n) { // When n == 0, we want the function to return -1. // When n == 0, (n - 1) will underflow to 0xFFFFFFFF, which is // why the statement below starts with (n ? 32 : -1). - return (n ? 32 : -1) - std::countl_zero(n - 1); -} - -// Returns a value of type T with a single bit set in the left-most position. -// Can be used instead of manually shifting a 1 to the left. Unlike the other -// functions in this file, usable for any integral type. -template - requires std::integral -constexpr T LeftmostBit() { - T one(1u); - return one << (8 * sizeof(T) - 1); + return (n ? 32 : -1) - CountlZero(n - 1); } } // namespace partition_alloc::internal::base::bits diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.h index 5b39833387..a4f5e674c0 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.h @@ -7,9 +7,9 @@ #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/immediate_crash.h" #include "partition_alloc/partition_alloc_base/log_message.h" #include "partition_alloc/partition_alloc_base/strings/cstring_builder.h" @@ -145,7 +145,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) NotImplemented #error "Debug builds are not expected to be optimized as official builds." #endif // defined(OFFICIAL_BUILD) && !defined(NDEBUG) -#if defined(OFFICIAL_BUILD) && !PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if defined(OFFICIAL_BUILD) && !PA_BUILDFLAG(DCHECKS_ARE_ON) // Discard log strings to reduce code bloat. // @@ -185,7 +185,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) NotImplemented #endif -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_BASE_DCHECK(condition) \ PA_LAZY_CHECK_STREAM( \ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.cc new file mode 100644 index 0000000000..6b7832fae5 --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.cc @@ -0,0 +1,196 @@ +// Copyright 2013 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. +#pragma allow_unsafe_buffers +#endif + +#include "partition_alloc/partition_alloc_base/debug/proc_maps_linux.h" + +#include +#include + +#include "partition_alloc/build_config.h" +#include "partition_alloc/partition_alloc_base/files/file_util.h" +#include "partition_alloc/partition_alloc_base/logging.h" +#include "partition_alloc/partition_alloc_base/posix/eintr_wrapper.h" +#include "partition_alloc/partition_alloc_check.h" + +#if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) || \ + PA_BUILDFLAG(IS_ANDROID) +#include +#endif + +namespace partition_alloc::internal::base::debug { + +namespace { +// On Android the 'open' function may have two versions: +// int open(const char *pathname, int flags); +// int open(const char *pathname, int flags, mode_t mode); +// +// This doesn't play well with WrapEINTR template. This alias helps the compiler +// to make a decision. +int OpenFile(const char* pathname, int flags) { + return open(pathname, flags); +} +} // namespace + +// Scans |proc_maps| starting from |pos| returning true if the gate VMA was +// found, otherwise returns false. +static bool ContainsGateVMA(std::string* proc_maps, size_t pos) { +#if PA_BUILDFLAG(PA_ARCH_CPU_ARM_FAMILY) + // The gate VMA on ARM kernels is the interrupt vectors page. + return proc_maps->find(" [vectors]\n", pos) != std::string::npos; +#elif PA_BUILDFLAG(PA_ARCH_CPU_X86_64) + // The gate VMA on x86 64-bit kernels is the virtual system call page. + return proc_maps->find(" [vsyscall]\n", pos) != std::string::npos; +#else + // Otherwise assume there is no gate VMA in which case we shouldn't + // get duplicate entries. + return false; +#endif +} + +bool ReadProcMaps(std::string* proc_maps) { + // seq_file only writes out a page-sized amount on each call. Refer to header + // file for details. + const size_t read_size = static_cast(sysconf(_SC_PAGESIZE)); + + int fd = WrapEINTR(OpenFile)("/proc/self/maps", O_RDONLY); + if (fd == -1) { + PA_LOG(ERROR) << "Couldn't open /proc/self/maps"; + WrapEINTR(close)(fd); + return false; + } + proc_maps->clear(); + + while (true) { + // To avoid a copy, resize |proc_maps| so read() can write directly into it. + // Compute |buffer| afterwards since resize() may reallocate. + size_t pos = proc_maps->size(); + proc_maps->resize(pos + read_size); + void* buffer = &(*proc_maps)[pos]; + + ssize_t bytes_read = WrapEINTR(read)(fd, buffer, read_size); + if (bytes_read < 0) { + PA_DPLOG(ERROR) << "Couldn't read /proc/self/maps"; + proc_maps->clear(); + WrapEINTR(close)(fd); + return false; + } + + // ... and don't forget to trim off excess bytes. + proc_maps->resize(pos + static_cast(bytes_read)); + + if (bytes_read == 0) { + break; + } + + // The gate VMA is handled as a special case after seq_file has finished + // iterating through all entries in the virtual memory table. + // + // Unfortunately, if additional entries are added at this point in time + // seq_file gets confused and the next call to read() will return duplicate + // entries including the gate VMA again. + // + // Avoid this by searching for the gate VMA and breaking early. + if (ContainsGateVMA(proc_maps, pos)) { + break; + } + } + + WrapEINTR(close)(fd); + return true; +} + +bool ParseProcMaps(const std::string& input, + std::vector* regions_out) { + PA_CHECK(regions_out); + std::vector regions; + + // This isn't async safe nor terribly efficient, but it doesn't need to be at + // this point in time. + std::vector lines; + + // Split the input into lines. + int start = 0; + for (size_t i = 0; i < input.size(); ++i) { + if (input[i] == '\n') { + lines.push_back(input.substr(start, i - start)); + start = i + 1; + } + } + lines.push_back(input.substr(start)); + + for (size_t i = 0; i < lines.size(); ++i) { + // Due to splitting on '\n' the last line should be empty. + if (i == lines.size() - 1) { + if (!lines[i].empty()) { + PA_DLOG(WARNING) << "Last line not empty"; + return false; + } + break; + } + + MappedMemoryRegion region; + const char* line = lines[i].c_str(); + char permissions[5] = {'\0'}; // Ensure NUL-terminated string. + uint8_t dev_major = 0; + uint8_t dev_minor = 0; + long inode = 0; + int path_index = 0; + + // Sample format from man 5 proc: + // + // address perms offset dev inode pathname + // 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm + // + // The final %n term captures the offset in the input string, which is used + // to determine the path name. It *does not* increment the return value. + // Refer to man 3 sscanf for details. + if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4c %llx %hhx:%hhx %ld %n", + ®ion.start, ®ion.end, permissions, ®ion.offset, + &dev_major, &dev_minor, &inode, &path_index) < 7) { + PA_LOG(WARNING) << "sscanf failed for line: " << line; + return false; + } + + region.permissions = 0; + + if (permissions[0] == 'r') { + region.permissions |= MappedMemoryRegion::READ; + } else if (permissions[0] != '-') { + return false; + } + + if (permissions[1] == 'w') { + region.permissions |= MappedMemoryRegion::WRITE; + } else if (permissions[1] != '-') { + return false; + } + + if (permissions[2] == 'x') { + region.permissions |= MappedMemoryRegion::EXECUTE; + } else if (permissions[2] != '-') { + return false; + } + + if (permissions[3] == 'p') { + region.permissions |= MappedMemoryRegion::PRIVATE; + } else if (permissions[3] != 's' && + permissions[3] != 'S') { // Shared memory. + return false; + } + + // Pushing then assigning saves us a string copy. + regions.push_back(region); + regions.back().path.assign(line + path_index); + } + + regions_out->swap(regions); + return true; +} + +} // namespace partition_alloc::internal::base::debug diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.h new file mode 100644 index 0000000000..e8e6ccc2cd --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/proc_maps_linux.h @@ -0,0 +1,93 @@ +// Copyright 2013 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_ +#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_ + +#include + +#include +#include + +#include "partition_alloc/partition_alloc_base/component_export.h" + +namespace partition_alloc::internal::base::debug { + +// Describes a region of mapped memory and the path of the file mapped. +struct MappedMemoryRegion { + enum Permission { + READ = 1 << 0, + WRITE = 1 << 1, + EXECUTE = 1 << 2, + PRIVATE = 1 << 3, // If set, region is private, otherwise it is shared. + }; + + // The address range [start,end) of mapped memory. + uintptr_t start; + uintptr_t end; + + // Byte offset into |path| of the range mapped into memory. + unsigned long long offset; + + // Image base, if this mapping corresponds to an ELF image. + uintptr_t base; + + // Bitmask of read/write/execute/private/shared permissions. + uint8_t permissions; + + // Name of the file mapped into memory. + // + // NOTE: path names aren't guaranteed to point at valid files. For example, + // "[heap]" and "[stack]" are used to represent the location of the process' + // heap and stack, respectively. + std::string path; +}; + +// Reads the data from /proc/self/maps and stores the result in |proc_maps|. +// Returns true if successful, false otherwise. +// +// There is *NO* guarantee that the resulting contents will be free of +// duplicates or even contain valid entries by time the method returns. +// +// +// THE GORY DETAILS +// +// Did you know it's next-to-impossible to atomically read the whole contents +// of /proc//maps? You would think that if we passed in a large-enough +// buffer to read() that It Should Just Work(tm), but sadly that's not the case. +// +// Linux's procfs uses seq_file [1] for handling iteration, text formatting, +// and dealing with resulting data that is larger than the size of a page. That +// last bit is especially important because it means that seq_file will never +// return more than the size of a page in a single call to read(). +// +// Unfortunately for a program like Chrome the size of /proc/self/maps is +// larger than the size of page so we're forced to call read() multiple times. +// If the virtual memory table changed in any way between calls to read() (e.g., +// a different thread calling mprotect()), it can make seq_file generate +// duplicate entries or skip entries. +// +// Even if seq_file was changed to keep flushing the contents of its page-sized +// buffer to the usermode buffer inside a single call to read(), it has to +// release its lock on the virtual memory table to handle page faults while +// copying data to usermode. This puts us in the same situation where the table +// can change while we're copying data. +// +// Alternatives such as fork()-and-suspend-the-parent-while-child-reads were +// attempted, but they present more subtle problems than it's worth. Depending +// on your use case your best bet may be to read /proc//maps prior to +// starting other threads. +// +// [1] http://kernelnewbies.org/Documents/SeqFileHowTo +PA_COMPONENT_EXPORT(PARTITION_ALLOC) bool ReadProcMaps(std::string* proc_maps); + +// Parses /proc//maps input data and stores in |regions|. Returns true +// and updates |regions| if and only if all of |input| was successfully parsed. +PA_COMPONENT_EXPORT(PARTITION_ALLOC) +bool ParseProcMaps(const std::string& input, + std::vector* regions); + +} // namespace partition_alloc::internal::base::debug + +#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_PROC_MAPS_LINUX_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.cc index 90b06db275..fa6fcc900d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.cc @@ -19,7 +19,7 @@ extern "C" void* __libc_stack_end; namespace partition_alloc::internal::base::debug { namespace { -#if PA_BUILDFLAG(PA_CAN_UNWIND_WITH_FRAME_POINTERS) +#if PA_BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) #if defined(__arm__) && defined(__GNUC__) && !defined(__clang__) // GCC and LLVM generate slightly different frames on ARM, see @@ -141,11 +141,11 @@ uintptr_t ScanStackForNextFrame(uintptr_t fp, uintptr_t stack_end) { return 0; } -#endif // PA_BUILDFLAG(PA_CAN_UNWIND_WITH_FRAME_POINTERS) +#endif // PA_BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) } // namespace -#if PA_BUILDFLAG(PA_CAN_UNWIND_WITH_FRAME_POINTERS) +#if PA_BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) // We force this function to be inlined into its callers (e.g. // TraceStackFramePointers()) in all build modes so we don't have to worry about @@ -199,7 +199,7 @@ PA_NOINLINE size_t TraceStackFramePointers(const void** out_trace, #endif // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) -#if PA_BUILDFLAG(PA_CAN_UNWIND_WITH_FRAME_POINTERS) +#if PA_BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) uintptr_t GetStackEnd() { #if PA_BUILDFLAG(IS_ANDROID) // Bionic reads proc/maps on every call to pthread_getattr_np() when called diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.h index a5584cac3d..287765d494 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.h @@ -9,13 +9,13 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" namespace partition_alloc::internal::base::debug { // Returns end of the stack, or 0 if we couldn't get it. -#if PA_BUILDFLAG(PA_CAN_UNWIND_WITH_FRAME_POINTERS) +#if PA_BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) uintptr_t GetStackEnd(); #endif @@ -37,7 +37,7 @@ void OutputStackTrace(unsigned index, uintptr_t offset); #endif -#if PA_BUILDFLAG(PA_CAN_UNWIND_WITH_FRAME_POINTERS) +#if PA_BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) // For stack scanning to be efficient it's very important for the thread to // be started by Chrome. In that case we naturally terminate unwinding once @@ -67,7 +67,7 @@ size_t TraceStackFramePointers(const void** out_trace, size_t skip_initial, bool enable_scanning = kEnableScanningByDefault); -#endif // PA_BUILDFLAG(PA_CAN_UNWIND_WITH_FRAME_POINTERS) +#endif // PA_BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) } // namespace partition_alloc::internal::base::debug diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_linux.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_linux.cc index dbe5f684f2..f2bfb20711 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_linux.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_linux.cc @@ -5,7 +5,7 @@ #include "partition_alloc/partition_alloc_base/debug/stack_trace.h" #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" +#include "partition_alloc/buildflags.h" namespace partition_alloc::internal::base::debug { @@ -13,7 +13,7 @@ size_t CollectStackTrace(const void** trace, size_t count) { // NOTE: This code MUST be async-signal safe (it's used by in-process // stack dumping signal handler). NO malloc or stdio is allowed here. -#if PA_BUILDFLAG(PA_CAN_UNWIND_WITH_FRAME_POINTERS) +#if PA_BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) // Regarding Linux and Android, backtrace API internally invokes malloc(). // So the API is not available inside memory allocation. Instead try tracing // using frame pointers. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_mac.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_mac.cc index 3cd9d0c78b..74a17d2c5d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_mac.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_mac.cc @@ -5,7 +5,7 @@ #include "partition_alloc/partition_alloc_base/debug/stack_trace.h" #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/numerics/safe_conversions.h" // Surprisingly, uClibc defines __GLIBC__ in some build configs, but diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.h index 2108e69f7c..cbddde331d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/fuchsia/fuchsia_logging.h @@ -9,8 +9,8 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/logging.h" // Use the PA_ZX_LOG family of macros along with a zx_status_t containing a @@ -54,17 +54,17 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) ZxLogMessage #define PA_ZX_DLOG(severity, zx_err) \ PA_LAZY_STREAM(PA_ZX_LOG_STREAM(severity, zx_err), PA_DLOG_IS_ON(severity)) -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_ZX_DLOG_IF(severity, condition, zx_err) \ PA_LAZY_STREAM(PA_ZX_LOG_STREAM(severity, zx_err), \ PA_DLOG_IS_ON(severity) && (condition)) -#else // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#else // PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_ZX_DLOG_IF(severity, condition, zx_err) PA_EAT_STREAM_PARAMETERS -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) -#define PA_ZX_DCHECK(condition, zx_err) \ - PA_LAZY_STREAM(PA_ZX_LOG_STREAM(DCHECK, zx_err), \ - PA_BUILDFLAG(PA_DCHECK_IS_ON) && !(condition)) \ +#define PA_ZX_DCHECK(condition, zx_err) \ + PA_LAZY_STREAM(PA_ZX_LOG_STREAM(DCHECK, zx_err), \ + PA_BUILDFLAG(DCHECKS_ARE_ON) && !(condition)) \ << "Check failed: " #condition << ". " #endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_FUCHSIA_FUCHSIA_LOGGING_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.cc index d57d829eec..d61be9bed8 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.cc @@ -63,13 +63,13 @@ LogMessageHandlerFunction g_log_message_handler = nullptr; } // namespace -#if PA_BUILDFLAG(PA_DCHECK_IS_CONFIGURABLE) +#if PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) // In DCHECK-enabled Chrome builds, allow the meaning of LOGGING_DCHECK to be // determined at run-time. We default it to ERROR, to avoid it triggering // crashes before the run-time has explicitly chosen the behaviour. PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) logging::LogSeverity LOGGING_DCHECK = LOGGING_ERROR; -#endif // PA_BUILDFLAG(PA_DCHECK_IS_CONFIGURABLE) +#endif // PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) // This is never instantiated, it's just used for EAT_STREAM_PARAMETERS to have // an object of the correct type on the LHS of the unused part of the ternary diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.h index 38252d36f3..46b233d674 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.h @@ -8,8 +8,8 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/scoped_clear_last_error.h" #include "partition_alloc/partition_alloc_base/strings/cstring_builder.h" @@ -41,7 +41,7 @@ constexpr LogSeverity LOGGING_NUM_SEVERITIES = 4; // LOGGING_DFATAL is LOGGING_FATAL in DCHECK-enabled builds, ERROR in normal // mode. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) constexpr LogSeverity LOGGING_DFATAL = LOGGING_FATAL; #else constexpr LogSeverity LOGGING_DFATAL = LOGGING_ERROR; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.h index 6f113dcc70..3f4ed8b3f2 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.h @@ -10,9 +10,9 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/log_message.h" // TODO(crbug.com/40158212): Need to update the description, because logging for @@ -337,7 +337,7 @@ constexpr LogSeverity LOGGING_0 = LOGGING_ERROR; // Definitions for DLOG et al. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_DLOG_IS_ON(severity) PA_LOG_IS_ON(severity) #define PA_DLOG_IF(severity, condition) PA_LOG_IF(severity, condition) @@ -347,11 +347,11 @@ constexpr LogSeverity LOGGING_0 = LOGGING_ERROR; #define PA_DVPLOG_IF(verboselevel, condition) \ PA_VPLOG_IF(verboselevel, condition) -#else // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#else // PA_BUILDFLAG(DCHECKS_ARE_ON) -// If !PA_BUILDFLAG(PA_DCHECK_IS_ON), we want to avoid emitting any references +// If !PA_BUILDFLAG(DCHECKS_ARE_ON), we want to avoid emitting any references // to |condition| (which may reference a variable defined only if -// PA_BUILDFLAG(PA_DCHECK_IS_ON)). Contrast this with DCHECK et al., which has +// PA_BUILDFLAG(DCHECKS_ARE_ON)). Contrast this with DCHECK et al., which has // different behavior. #define PA_DLOG_IS_ON(severity) false @@ -361,7 +361,7 @@ constexpr LogSeverity LOGGING_0 = LOGGING_ERROR; #define PA_DVLOG_IF(verboselevel, condition) PA_EAT_STREAM_PARAMETERS #define PA_DVPLOG_IF(verboselevel, condition) PA_EAT_STREAM_PARAMETERS -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_DLOG(severity) \ PA_LAZY_STREAM(PA_LOG_STREAM(severity), PA_DLOG_IS_ON(severity)) @@ -375,11 +375,11 @@ constexpr LogSeverity LOGGING_0 = LOGGING_ERROR; // Definitions for DCHECK et al. -#if PA_BUILDFLAG(PA_DCHECK_IS_CONFIGURABLE) +#if PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) extern LogSeverity LOGGING_DCHECK; #else constexpr LogSeverity LOGGING_DCHECK = LOGGING_FATAL; -#endif // PA_BUILDFLAG(PA_DCHECK_IS_CONFIGURABLE) +#endif // PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) // Redefine the standard assert to use our nice log files #undef assert diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.cc index 4c7084ee41..f952f31893 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.cc @@ -9,7 +9,7 @@ #include #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" +#include "partition_alloc/buildflags.h" namespace partition_alloc::internal::base::subtle { @@ -21,7 +21,7 @@ bool RefCountedThreadSafeBase::HasAtLeastOneRef() const { return !ref_count_.IsZero(); } -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) RefCountedThreadSafeBase::~RefCountedThreadSafeBase() { PA_BASE_DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without " "calling Release()"; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.h index eac1069f51..2b8b87ba11 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.h @@ -6,11 +6,11 @@ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_MEMORY_REF_COUNTED_H_ #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/atomic_ref_count.h" #include "partition_alloc/partition_alloc_base/check.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/memory/scoped_refptr.h" namespace partition_alloc::internal::base { @@ -28,12 +28,12 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) RefCountedThreadSafeBase { explicit constexpr RefCountedThreadSafeBase(StartRefCountFromZeroTag) {} explicit constexpr RefCountedThreadSafeBase(StartRefCountFromOneTag) : ref_count_(1) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) needs_adopt_ref_ = true; #endif } -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) ~RefCountedThreadSafeBase(); #else ~RefCountedThreadSafeBase() = default; @@ -59,14 +59,14 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) RefCountedThreadSafeBase { friend scoped_refptr AdoptRef(U*); void Adopted() const { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_BASE_DCHECK(needs_adopt_ref_); needs_adopt_ref_ = false; #endif } PA_ALWAYS_INLINE void AddRefImpl() const { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_BASE_DCHECK(!in_dtor_); // This RefCounted object is created with non-zero reference count. // The first reference to such a object has to be made by AdoptRef or @@ -77,7 +77,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) RefCountedThreadSafeBase { } PA_ALWAYS_INLINE void AddRefWithCheckImpl() const { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_BASE_DCHECK(!in_dtor_); // This RefCounted object is created with non-zero reference count. // The first reference to such a object has to be made by AdoptRef or @@ -88,12 +88,12 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) RefCountedThreadSafeBase { } PA_ALWAYS_INLINE bool ReleaseImpl() const { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_BASE_DCHECK(!in_dtor_); PA_BASE_DCHECK(!ref_count_.IsZero()); #endif if (!ref_count_.Decrement()) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) in_dtor_ = true; #endif return true; @@ -102,7 +102,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) RefCountedThreadSafeBase { } mutable AtomicRefCount ref_count_{0}; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) mutable bool needs_adopt_ref_ = false; mutable bool in_dtor_ = false; #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.cc index bc66013143..e3d1060c6c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.cc @@ -5,7 +5,7 @@ #include "partition_alloc/partition_alloc_base/strings/cstring_builder.h" #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/strings/safe_sprintf.h" #if !PA_BUILDFLAG(IS_WIN) @@ -16,7 +16,7 @@ #include #include -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #include "partition_alloc/partition_alloc_base/check.h" #define PA_RAW_DCHECK PA_RAW_CHECK #else diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/gtest_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/gtest_util.h new file mode 100644 index 0000000000..4b39dd1650 --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/test/gtest_util.h @@ -0,0 +1,87 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_ +#define PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_ + +#include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" +#include "partition_alloc/partition_alloc_base/check.h" +#include "testing/gtest/include/gtest/gtest.h" + +// EXPECT/ASSERT_DCHECK_DEATH is intended to replace EXPECT/ASSERT_DEBUG_DEATH +// when the death is expected to be caused by a DCHECK. Contrary to +// EXPECT/ASSERT_DEBUG_DEATH however, it doesn't execute the statement in non- +// dcheck builds as DCHECKs are intended to catch things that should never +// happen and as such executing the statement results in undefined behavior +// (|statement| is compiled in unsupported configurations nonetheless). +// DCHECK_IS_CONFIGURABLE is excluded from DCHECK_DEATH because it's non-FATAL +// by default and there are no known tests that configure a FATAL level. If this +// gets used from FATAL contexts under DCHECK_IS_CONFIGURABLE this may need to +// be updated to look at LOGGING_DCHECK's current severity level. +// Death tests misbehave on Android. +#if PA_BUILDFLAG(DCHECKS_ARE_ON) && defined(GTEST_HAS_DEATH_TEST) && \ + !PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) && !PA_BUILDFLAG(IS_ANDROID) + +// EXPECT/ASSERT_DCHECK_DEATH tests verify that a DCHECK is hit ("Check failed" +// is part of the error message). Optionally you may specify part of the message +// to verify which DCHECK (or LOG(DFATAL)) is being hit. +#define PA_EXPECT_DCHECK_DEATH(statement) \ + EXPECT_DEATH(statement, "Check failed") +#define PA_EXPECT_DCHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, msg) +#define PA_ASSERT_DCHECK_DEATH(statement) \ + ASSERT_DEATH(statement, "Check failed") +#define PA_ASSERT_DCHECK_DEATH_WITH(statement, msg) ASSERT_DEATH(statement, msg) + +#else + +#define PA_EXPECT_DCHECK_DEATH(statement) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, "Check failed", ) +#define PA_EXPECT_DCHECK_DEATH_WITH(statement, msg) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, msg, ) +#define PA_ASSERT_DCHECK_DEATH(statement) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, "Check failed", return) +#define PA_ASSERT_DCHECK_DEATH_WITH(statement, msg) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, msg, return) + +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) && defined(GTEST_HAS_DEATH_TEST) && + // !PA_BUILDFLAG(DCHECK_IS_CONFIGURABLE) && !PA_BUILDFLAG(IS_ANDROID) + +// As above, but for CHECK(). +#if defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID) + +#if PA_BASE_CHECK_WILL_STREAM() +#define PA_EXPECT_CHECK_DEATH(statement) EXPECT_DEATH(statement, "Check failed") +#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, msg) +#define PA_ASSERT_CHECK_DEATH(statement) ASSERT_DEATH(statement, "Check failed") +#define PA_EXPECT_NOTREACHED_DEATH(statement) \ + EXPECT_DEATH(statement, "NOTREACHED hit") +#define PA_ASSERT_NOTREACHED_DEATH(statement) \ + ASSERT_DEATH(statement, "NOTREACHED hit") +#else +#define PA_EXPECT_CHECK_DEATH(statement) EXPECT_DEATH(statement, "") +#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) EXPECT_DEATH(statement, "") +#define PA_ASSERT_CHECK_DEATH(statement) ASSERT_DEATH(statement, "") +#define PA_EXPECT_NOTREACHED_DEATH(statement) EXPECT_DEATH(statement, "") +#define PA_ASSERT_NOTREACHED_DEATH(statement) ASSERT_DEATH(statement, "") +#endif // PA_BASE_CHECK_WILL_STREAM() + +#else // defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID) + +// Note GTEST_UNSUPPORTED_DEATH_TEST takes a |regex| only to see whether it is a +// valid regex. It is never evaluated. +#define PA_EXPECT_CHECK_DEATH(statement) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, "", ) +#define PA_EXPECT_CHECK_DEATH_WITH(statement, msg) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, "", ) +#define PA_ASSERT_CHECK_DEATH(statement) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, "", return) +#define PA_EXPECT_NOTREACHED_DEATH(statement) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, "", ) +#define PA_ASSERT_NOTREACHED_DEATH(statement) \ + GTEST_UNSUPPORTED_DEATH_TEST(statement, "", return) + +#endif // defined(GTEST_HAS_DEATH_TEST) && !PA_BUILDFLAG(IS_ANDROID) + +#endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_TEST_GTEST_UTIL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations.h index 525beb3e6c..feb1d13ee9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/thread_annotations.h @@ -38,7 +38,7 @@ #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_THREAD_ANNOTATIONS_H_ #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" +#include "partition_alloc/buildflags.h" #if defined(__clang__) #define PA_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) @@ -246,7 +246,7 @@ inline T& ts_unchecked_read(T& v) PA_NO_THREAD_SAFETY_ANALYSIS { // The above is imported as-is from abseil-cpp. The following Chromium-specific // synonyms are added for Chromium concepts (SequenceChecker/ThreadChecker). -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Equivalent to PA_GUARDED_BY for SequenceChecker/ThreadChecker. Currently, #define PA_GUARDED_BY_CONTEXT(name) PA_GUARDED_BY(name) @@ -254,11 +254,11 @@ inline T& ts_unchecked_read(T& v) PA_NO_THREAD_SAFETY_ANALYSIS { // Equivalent to PA_EXCLUSIVE_LOCKS_REQUIRED for SequenceChecker/ThreadChecker. #define PA_VALID_CONTEXT_REQUIRED(name) PA_EXCLUSIVE_LOCKS_REQUIRED(name) -#else // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#else // PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_GUARDED_BY_CONTEXT(name) #define PA_VALID_CONTEXT_REQUIRED(name) -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) #endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_THREAD_ANNOTATIONS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread.cc index 855deda9b2..27d2cff853 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread.cc @@ -6,25 +6,7 @@ namespace partition_alloc::internal::base { -namespace { - -// SetThreadNameHook is invoked by EnablePCScan(). EnablePCScan() will be -// invoked soon after running RunBrowser, RunZygote, and RunContentProcess. -// So g_set_thread_name_proc can be non-atomic. -SetThreadNameProc g_set_thread_name_proc = nullptr; - -} // namespace - -void PlatformThread::SetThreadNameHook(SetThreadNameProc hook) { - g_set_thread_name_proc = hook; -} - // static -void PlatformThread::SetName(const std::string& name) { - if (!g_set_thread_name_proc) { - return; - } - g_set_thread_name_proc(name); -} +void PlatformThread::SetName(const std::string& name) {} } // namespace partition_alloc::internal::base diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix.cc index 53219ed310..4f79382fb7 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix.cc @@ -14,7 +14,7 @@ #include #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/logging.h" #include "partition_alloc/partition_alloc_base/threading/platform_thread_internal_posix.h" @@ -95,7 +95,7 @@ PlatformThreadId PlatformThread::CurrentId() { g_is_main_thread = false; } } else { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) if (g_thread_id != syscall(__NR_gettid)) { PA_RAW_LOG( FATAL, diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix_for_testing.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix_for_testing.cc index 742309dd58..bcb20dc18a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix_for_testing.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_posix_for_testing.cc @@ -14,11 +14,11 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/check.h" #include "partition_alloc/partition_alloc_base/logging.h" #include "partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h" #include "partition_alloc/partition_alloc_base/threading/platform_thread_internal_posix.h" -#include "partition_alloc/partition_alloc_buildflags.h" #if PA_BUILDFLAG(IS_FUCHSIA) #include @@ -26,9 +26,8 @@ #include #endif -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_BUILDFLAG(USE_STARSCAN) +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #include "partition_alloc/stack/stack.h" -#include "partition_alloc/starscan/pcscan.h" #endif namespace partition_alloc::internal::base { @@ -52,14 +51,14 @@ void* ThreadFunc(void* params) { delegate = thread_params->delegate; -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_BUILDFLAG(USE_STARSCAN) +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) StackTopRegistry::Get().NotifyThreadCreated(); #endif } delegate->ThreadMain(); -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_BUILDFLAG(USE_STARSCAN) +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) StackTopRegistry::Get().NotifyThreadDestroyed(); #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win_for_testing.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win_for_testing.cc index ce1c83fc00..d2ff34fc62 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win_for_testing.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_win_for_testing.cc @@ -7,15 +7,14 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/oom.h" #include "partition_alloc/partition_alloc_base/check.h" #include "partition_alloc/partition_alloc_base/debug/alias.h" #include "partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h" -#include "partition_alloc/partition_alloc_buildflags.h" -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_BUILDFLAG(USE_STARSCAN) +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #include "partition_alloc/stack/stack.h" -#include "partition_alloc/starscan/pcscan.h" #endif namespace partition_alloc::internal::base { @@ -63,7 +62,7 @@ DWORD __stdcall ThreadFunc(void* params) { GetCurrentProcess(), &platform_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_BUILDFLAG(USE_STARSCAN) +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) StackTopRegistry::Get().NotifyThreadCreated(); #endif @@ -75,7 +74,7 @@ DWORD __stdcall ThreadFunc(void* params) { delete thread_params; delegate->ThreadMain(); -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_BUILDFLAG(USE_STARSCAN) +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) StackTopRegistry::Get().NotifyThreadDestroyed(); #endif return 0; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h index cce9d97a0e..61427e34a2 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h @@ -73,7 +73,7 @@ #include "partition_alloc/partition_alloc_base/numerics/clamped_math.h" #if PA_BUILDFLAG(IS_APPLE) -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #endif // PA_BUILDFLAG(IS_APPLE) #if PA_BUILDFLAG(IS_FUCHSIA) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h new file mode 100644 index 0000000000..4225e0f273 --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h @@ -0,0 +1,10 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef PARTITION_ALLOC_PARTITION_ALLOC_BUILDFLAGS_H_ +#define PARTITION_ALLOC_PARTITION_ALLOC_BUILDFLAGS_H_ + +// TODO(crbug.com/41481467): Remove this alias, the time to updates dependants. +#include "partition_alloc/buildflags.h" + +#endif // PARTITION_ALLOC_PARTITION_ALLOC_BUILDFLAGS_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h index 342b63960e..438e011079 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h @@ -8,13 +8,12 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/page_allocator_constants.h" #include "partition_alloc/partition_alloc_base/check.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/debug/alias.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/immediate_crash.h" -#include "partition_alloc/partition_alloc_buildflags.h" // When PartitionAlloc is used as the default allocator, we cannot use the // regular (D)CHECK() macros, as they allocate internally. When an assertion is @@ -33,11 +32,11 @@ PA_UNLIKELY(!(condition)) ? PA_IMMEDIATE_CRASH() \ : PA_EAT_CHECK_STREAM_PARAMS() -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_DCHECK(condition) PA_CHECK(condition) #else #define PA_DCHECK(condition) PA_EAT_CHECK_STREAM_PARAMS(!(condition)) -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_PCHECK(condition) \ if (!(condition)) { \ @@ -47,11 +46,11 @@ } \ static_assert(true) -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_DPCHECK(condition) PA_PCHECK(condition) #else #define PA_DPCHECK(condition) PA_EAT_CHECK_STREAM_PARAMS(!(condition)) -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) #else // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && // !PA_BASE_CHECK_WILL_STREAM() @@ -65,7 +64,7 @@ // Expensive dchecks that run within *Scan. These checks are only enabled in // debug builds with dchecks enabled. #if !defined(NDEBUG) -#define PA_SCAN_DCHECK_IS_ON() PA_BUILDFLAG(PA_DCHECK_IS_ON) +#define PA_SCAN_DCHECK_IS_ON() PA_BUILDFLAG(DCHECKS_ARE_ON) #else #define PA_SCAN_DCHECK_IS_ON() 0 #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_config.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_config.h index 675022df58..620bbd5e53 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_config.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_config.h @@ -6,8 +6,7 @@ #define PARTITION_ALLOC_PARTITION_ALLOC_CONFIG_H_ #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" // PA_CONFIG() uses a similar trick as BUILDFLAG() to allow the compiler catch // typos or a missing #include. @@ -36,13 +35,6 @@ static_assert(sizeof(void*) == 8, ""); static_assert(sizeof(void*) != 8, ""); #endif // PA_CONFIG(HAS_64_BITS_POINTERS) -#if PA_BUILDFLAG(HAS_64_BIT_POINTERS) && \ - (defined(__ARM_NEON) || defined(__ARM_NEON__)) && defined(__ARM_FP) -#define PA_CONFIG_STARSCAN_NEON_SUPPORTED() 1 -#else -#define PA_CONFIG_STARSCAN_NEON_SUPPORTED() 0 -#endif - #if PA_BUILDFLAG(HAS_64_BIT_POINTERS) && PA_BUILDFLAG(IS_IOS) // Allow PA to select an alternate pool size at run-time before initialization, // rather than using a single constexpr value. @@ -56,72 +48,12 @@ static_assert(sizeof(void*) != 8, ""); #define PA_CONFIG_DYNAMICALLY_SELECT_POOL_SIZE() 0 #endif // PA_BUILDFLAG(HAS_64_BIT_POINTERS) && PA_BUILDFLAG(IS_IOS) -#if PA_BUILDFLAG(HAS_64_BIT_POINTERS) && \ - (PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_ANDROID)) -#include -// TODO(bikineev): Enable for ChromeOS. -#define PA_CONFIG_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED() \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)) -#else -#define PA_CONFIG_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED() 0 -#endif // PA_BUILDFLAG(HAS_64_BIT_POINTERS) && - // (PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_ANDROID)) - -#if PA_BUILDFLAG(USE_STARSCAN) -// Use card table to avoid races for PCScan configuration without safepoints. -// The card table provides the guaranteee that for a marked card the underling -// super-page is fully initialized. -#define PA_CONFIG_STARSCAN_USE_CARD_TABLE() 1 -#else -// The card table is permanently disabled for 32-bit. -#define PA_CONFIG_STARSCAN_USE_CARD_TABLE() 0 -#endif // PA_BUILDFLAG(USE_STARSCAN) - -// Use batched freeing when sweeping pages. This builds up a freelist in the -// scanner thread and appends to the slot-span's freelist only once. -#define PA_CONFIG_STARSCAN_BATCHED_FREE() 1 - -// TODO(bikineev): Temporarily disable inlining in *Scan to get clearer -// stacktraces. -#define PA_CONFIG_STARSCAN_NOINLINE_SCAN_FUNCTIONS() 1 - -// TODO(bikineev): Temporarily disable *Scan in MemoryReclaimer as it seems to -// cause significant jank. -#define PA_CONFIG_STARSCAN_ENABLE_STARSCAN_ON_RECLAIM() 0 - -// Double free detection comes with expensive cmpxchg (with the loop around it). -// We currently disable it to improve the runtime. -#define PA_CONFIG_STARSCAN_EAGER_DOUBLE_FREE_DETECTION_ENABLED() 0 - // POSIX is not only UNIX, e.g. macOS and other OSes. We do use Linux-specific // features such as futex(2). #define PA_CONFIG_HAS_LINUX_KERNEL() \ (PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) || \ PA_BUILDFLAG(IS_ANDROID)) -// On some platforms, we implement locking by spinning in userspace, then going -// into the kernel only if there is contention. This requires platform support, -// namely: -// - On Linux, futex(2) -// - On Windows, a fast userspace "try" operation which is available with -// SRWLock -// - On macOS, pthread_mutex_trylock() is fast by default starting with macOS -// 10.14. Chromium targets an earlier version, so it cannot be known at -// compile-time. So we use something different. -// TODO(crbug.com/40274152): macOS 10.15 is now required; switch to -// better locking. -// - Otherwise, on POSIX we assume that a fast userspace pthread_mutex_trylock() -// is available. -// -// Otherwise, a userspace spinlock implementation is used. -#if PA_CONFIG(HAS_LINUX_KERNEL) || PA_BUILDFLAG(IS_WIN) || \ - PA_BUILDFLAG(IS_APPLE) || PA_BUILDFLAG(IS_POSIX) || \ - PA_BUILDFLAG(IS_FUCHSIA) -#define PA_CONFIG_HAS_FAST_MUTEX() 1 -#else -#define PA_CONFIG_HAS_FAST_MUTEX() 0 -#endif - // If defined, enables zeroing memory on Free() with roughly 1% probability. // This applies only to normal buckets, as direct-map allocations are always // decommitted. @@ -163,7 +95,7 @@ static_assert(sizeof(void*) == 8); #endif // Specifies whether allocation extras need to be added. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) #define PA_CONFIG_EXTRAS_REQUIRED() 1 #else #define PA_CONFIG_EXTRAS_REQUIRED() 0 @@ -204,10 +136,10 @@ static_assert(sizeof(void*) == 8); // calling malloc() again. // // Limitations: -// - PA_BUILDFLAG(PA_DCHECK_IS_ON) due to runtime cost +// - PA_BUILDFLAG(DCHECKS_ARE_ON) due to runtime cost // - thread_local TLS to simplify the implementation // - Not on Android due to bot failures -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) && \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) && \ PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ PA_CONFIG(THREAD_LOCAL_TLS) && !PA_BUILDFLAG(IS_ANDROID) #define PA_CONFIG_HAS_ALLOCATION_GUARD() 1 @@ -253,7 +185,7 @@ constexpr bool kUseLazyCommit = false; #define PA_CONFIG_IN_SLOT_METADATA_CHECK_COOKIE() \ (!(PA_BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS) && \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)) && \ - (PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ + (PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS))) // Use available space in the reference count to store the initially requested @@ -349,6 +281,6 @@ static_assert(__cplusplus >= 202002L, // Named pass-through that determines whether or not PA should generally // enforce that `SlotStart` instances are in fact slot starts. -#define PA_CONFIG_ENFORCE_SLOT_STARTS() PA_BUILDFLAG(PA_DCHECK_IS_ON) +#define PA_CONFIG_ENFORCE_SLOT_STARTS() PA_BUILDFLAG(DCHECKS_ARE_ON) #endif // PARTITION_ALLOC_PARTITION_ALLOC_CONFIG_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h index 16de15bc7d..9bcea60dbd 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h @@ -12,10 +12,10 @@ #include "partition_alloc/address_pool_manager_types.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/flags.h" #include "partition_alloc/page_allocator_constants.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_forward.h" @@ -100,7 +100,13 @@ constexpr size_t kPartitionCachelineSize = 64; // other constant values, we pack _all_ `PartitionRoot::Alloc` sizes perfectly // up against the end of a system page. -#if defined(_MIPS_ARCH_LOONGSON) || PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64) +#if (PA_BUILDFLAG(IS_APPLE) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS)) || \ + defined(PARTITION_ALLOCATOR_CONSTANTS_POSIX_NONCONST_PAGE_SIZE) +PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t +PartitionPageShift() { + return PageAllocationGranularityShift() + 2; +} +#elif defined(_MIPS_ARCH_LOONGSON) || PA_BUILDFLAG(PA_ARCH_CPU_LOONGARCH64) PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t PartitionPageShift() { return 16; // 64 KiB @@ -110,12 +116,6 @@ PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t PartitionPageShift() { return 18; // 256 KiB } -#elif (PA_BUILDFLAG(IS_APPLE) && PA_BUILDFLAG(PA_ARCH_CPU_64_BITS)) || \ - defined(PARTITION_ALLOCATOR_CONSTANTS_POSIX_NONCONST_PAGE_SIZE) -PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t -PartitionPageShift() { - return PageAllocationGranularityShift() + 2; -} #else PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t PartitionPageShift() { @@ -455,7 +455,14 @@ PA_ALWAYS_INLINE constexpr size_t MaxDirectMapped() { // Max alignment supported by AlignedAlloc(). // kSuperPageSize alignment can't be easily supported, because each super page // starts with guard pages & metadata. +// TODO(casey.smalley@arm.com): under 64k pages we can end up in a situation +// where a normal slot span will be large enough to contain multiple items, +// but the address will go over the final partition page after being aligned. +#if PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_ARM64) +constexpr size_t kMaxSupportedAlignment = kSuperPageSize / 4; +#else constexpr size_t kMaxSupportedAlignment = kSuperPageSize / 2; +#endif constexpr size_t kBitsPerSizeT = sizeof(void*) * CHAR_BIT; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_forward.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_forward.h index d932e80893..1778674ac4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_forward.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_forward.h @@ -10,9 +10,9 @@ #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" #include "partition_alloc/partition_alloc_config.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.cc index f0396c6b1f..5001a2a583 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.cc @@ -5,12 +5,12 @@ #include "partition_alloc/partition_bucket.h" #include -#include #include #include #include "partition_alloc/address_pool_manager.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/freeslot_bitmap.h" #include "partition_alloc/freeslot_bitmap_constants.h" #include "partition_alloc/oom.h" @@ -22,10 +22,8 @@ #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" #include "partition_alloc/partition_alloc_base/debug/alias.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/immediate_crash.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -38,10 +36,6 @@ #include "partition_alloc/reservation_offset_table.h" #include "partition_alloc/tagging.h" -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/starscan/pcscan.h" -#endif - namespace partition_alloc::internal { namespace { @@ -186,7 +180,7 @@ SlotSpanMetadata* PartitionDirectMap(PartitionRoot* root, size_t raw_size, size_t slot_span_alignment) { PA_DCHECK((slot_span_alignment >= PartitionPageSize()) && - std::has_single_bit(slot_span_alignment)); + base::bits::HasSingleBit(slot_span_alignment)); // No static EXCLUSIVE_LOCKS_REQUIRED(), as the checker doesn't understand // scoped unlocking. @@ -255,7 +249,7 @@ SlotSpanMetadata* PartitionDirectMap(PartitionRoot* root, const size_t reservation_size = PartitionRoot::GetDirectMapReservationSize( raw_size + padding_for_alignment); PA_DCHECK(reservation_size >= raw_size); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) const size_t available_reservation_size = reservation_size - padding_for_alignment - PartitionRoot::GetDirectMapMetadataAndGuardPagesSize(); @@ -791,19 +785,7 @@ PartitionBucket::InitializeSuperPage(PartitionRoot* root, uintptr_t state_bitmap = super_page + PartitionPageSize() + (is_direct_mapped() ? 0 : ReservedFreeSlotBitmapSize()); -#if PA_BUILDFLAG(USE_STARSCAN) - PA_DCHECK(SuperPageStateBitmapAddr(super_page) == state_bitmap); - const size_t state_bitmap_reservation_size = - root->IsQuarantineAllowed() ? ReservedStateBitmapSize() : 0; - const size_t state_bitmap_size_to_commit = - root->IsQuarantineAllowed() ? CommittedStateBitmapSize() : 0; - PA_DCHECK(state_bitmap_reservation_size % PartitionPageSize() == 0); - PA_DCHECK(state_bitmap_size_to_commit % SystemPageSize() == 0); - PA_DCHECK(state_bitmap_size_to_commit <= state_bitmap_reservation_size); - uintptr_t payload = state_bitmap + state_bitmap_reservation_size; -#else uintptr_t payload = state_bitmap; -#endif // PA_BUILDFLAG(USE_STARSCAN) root->next_partition_page = payload; root->next_partition_page_end = root->next_super_page - PartitionPageSize(); @@ -886,24 +868,6 @@ PartitionBucket::InitializeSuperPage(PartitionRoot* root, payload < SuperPagesEndFromExtent(current_extent)); } - // If PCScan is used, commit the state bitmap. Otherwise, leave it uncommitted - // and let PartitionRoot::RegisterScannableRoot() commit it when needed. Make - // sure to register the super-page after it has been fully initialized. - // Otherwise, the concurrent scanner may try to access |extent->root| which - // could be not initialized yet. -#if PA_BUILDFLAG(USE_STARSCAN) - if (root->IsQuarantineEnabled()) { - { - ScopedSyscallTimer timer{root}; - RecommitSystemPages(state_bitmap, state_bitmap_size_to_commit, - root->PageAccessibilityWithThreadIsolationIfEnabled( - PageAccessibilityConfiguration::kReadWrite), - PageAccessibilityDisposition::kRequireUpdate); - } - PCScan::RegisterNewSuperPage(root, super_page); - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - #if PA_BUILDFLAG(USE_FREESLOT_BITMAP) // Commit the pages for freeslot bitmap. if (!is_direct_mapped()) { @@ -1042,7 +1006,7 @@ PartitionBucket::ProvisionMoreSlotsAndAllocOne(PartitionRoot* root, next_slot = next_slot_end; next_slot_end = next_slot + slot_size; prev_entry = entry; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) free_list_entries_added++; #endif } @@ -1051,7 +1015,7 @@ PartitionBucket::ProvisionMoreSlotsAndAllocOne(PartitionRoot* root, FreeSlotBitmapMarkSlotAsFree(return_slot); #endif -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // The only provisioned slot not added to the free list is the one being // returned. PA_DCHECK(slots_to_provision == free_list_entries_added + 1); @@ -1339,7 +1303,7 @@ uintptr_t PartitionBucket::SlowPathAlloc(PartitionRoot* root, SlotSpanMetadata** slot_span, bool* is_already_zeroed) { PA_DCHECK((slot_span_alignment >= PartitionPageSize()) && - std::has_single_bit(slot_span_alignment)); + base::bits::HasSingleBit(slot_span_alignment)); // The slow path is called when the freelist is empty. The only exception is // when a higher-order alignment is requested, in which case the freelist diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.h index 0da7f199b3..e0ed3ac7fe 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.h @@ -135,7 +135,14 @@ struct PartitionBucket { // Returns a slot number starting from the beginning of the slot span. PA_ALWAYS_INLINE size_t GetSlotNumber(size_t offset_in_slot_span) const { // See the static assertion for `kReciprocalShift` above. - PA_DCHECK(offset_in_slot_span <= kMaxBucketed); + // TODO(casey.smalley@arm.com): triggers on Aarch64/Linux + // systems with 64k system pages. Constants need to be + // adjusted to prevent different parts of the allocator + // from overlapping. For now this will allow 64k pages + // to function on Aarch64/Linux systems, albeit not + // very efficiently. + PA_DCHECK(internal::SystemPageSize() == (size_t{1} << 16) || + offset_in_slot_span <= kMaxBucketed); PA_DCHECK(slot_size <= kMaxBucketed); const size_t offset_in_slot = diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket_lookup.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket_lookup.h index b2643784ad..bb2dba77a4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket_lookup.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_bucket_lookup.h @@ -6,13 +6,12 @@ #define PARTITION_ALLOC_PARTITION_BUCKET_LOOKUP_H_ #include -#include #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_constants.h" @@ -171,11 +170,17 @@ class BucketIndexLookup final { bucket_index_lookup_[((kBitsPerSizeT + 1) * kNumBucketsPerOrder) + 1]{}; }; +PA_ALWAYS_INLINE constexpr size_t RoundUpToPowerOfTwo(size_t size) { + const size_t n = 1 << base::bits::Log2Ceiling(static_cast(size)); + PA_CHECK(size <= n); + return n; +} + PA_ALWAYS_INLINE constexpr size_t RoundUpSize(size_t size) { - const size_t next_power = std::bit_ceil(size); + const size_t next_power = RoundUpToPowerOfTwo(size); const size_t prev_power = next_power >> 1; - PA_DCHECK(size <= next_power); - PA_DCHECK(prev_power < size); + PA_CHECK(size <= next_power); + PA_CHECK(prev_power < size); if (size <= prev_power * 5 / 4) { return prev_power * 5 / 4; } else { @@ -194,7 +199,7 @@ PA_ALWAYS_INLINE constexpr uint16_t BucketIndexLookup::GetIndexForDenserBuckets( // materialized in the binary. constexpr BucketIndexLookup lookup{}; const size_t order = - kBitsPerSizeT - static_cast(std::countl_zero(size)); + kBitsPerSizeT - static_cast(base::bits::CountlZero(size)); // The order index is simply the next few bits after the most significant // bit. const size_t order_index = diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_cookie.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_cookie.h index be2ba0282e..adda56c874 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_cookie.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_cookie.h @@ -5,8 +5,8 @@ #ifndef PARTITION_ALLOC_PARTITION_COOKIE_H_ #define PARTITION_ALLOC_PARTITION_COOKIE_H_ +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_check.h" namespace partition_alloc::internal { @@ -14,7 +14,7 @@ namespace partition_alloc::internal { static constexpr size_t kCookieSize = 16; // Cookie is enabled for debug builds. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) inline constexpr unsigned char kCookieValue[kCookieSize] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xD0, 0x0D, @@ -42,7 +42,7 @@ PA_ALWAYS_INLINE void PartitionCookieCheckValue(unsigned char* address) {} PA_ALWAYS_INLINE void PartitionCookieWriteValue(unsigned char* cookie_ptr) {} -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) } // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_dcheck_helper.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_dcheck_helper.cc index f1f5a3555a..a005d5156f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_dcheck_helper.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_dcheck_helper.cc @@ -12,7 +12,7 @@ namespace partition_alloc::internal { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) void DCheckIsValidSlotSpan(internal::SlotSpanMetadata* slot_span) { PartitionRoot* root = PartitionRoot::FromSlotSpanMetadata(slot_span); @@ -62,6 +62,6 @@ void DCheckRootLockOfSlotSpanIsAcquired(internal::SlotSpanMetadata* slot_span) { DCheckRootLockIsAcquired(PartitionRoot::FromSlotSpanMetadata(slot_span)); } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) } // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_dcheck_helper.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_dcheck_helper.h index dec2aa23c7..2f012276bd 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_dcheck_helper.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_dcheck_helper.h @@ -14,7 +14,7 @@ namespace partition_alloc::internal { struct PartitionSuperPageExtentEntry; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // To allow these asserts to have empty bodies in no-DCHECK() builds, while // avoiding issues with circular includes. @@ -22,7 +22,7 @@ struct PartitionSuperPageExtentEntry; // Export symbol if dcheck-is-on. Because the body is not empty. #define PA_EXPORT_IF_DCHECK_IS_ON() PA_COMPONENT_EXPORT(PARTITION_ALLOC) -#else // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#else // PA_BUILDFLAG(DCHECKS_ARE_ON) // The static_assert() eats follow-on semicolons. #define PA_EMPTY_BODY_IF_DCHECK_IS_OFF() \ @@ -31,7 +31,7 @@ struct PartitionSuperPageExtentEntry; // inline if dcheck-is-off so it's no overhead. #define PA_EXPORT_IF_DCHECK_IS_ON() PA_ALWAYS_INLINE -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) PA_EXPORT_IF_DCHECK_IS_ON() void DCheckIsValidSlotSpan(internal::SlotSpanMetadata* slot_span) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_freelist_entry.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_freelist_entry.h index b68cb71ad5..a5a4f6745f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_freelist_entry.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_freelist_entry.h @@ -7,10 +7,10 @@ #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_constants.h" namespace partition_alloc::internal { @@ -101,7 +101,7 @@ struct PartitionFreelistDispatcher { PartitionFreelistEntry* next) const = 0; PA_ALWAYS_INLINE virtual uintptr_t ClearForAllocation( PartitionFreelistEntry* entry) const = 0; - PA_ALWAYS_INLINE virtual constexpr bool IsEncodedNextPtrZero( + PA_ALWAYS_INLINE virtual bool IsEncodedNextPtrZero( PartitionFreelistEntry* entry) const = 0; #else static const PartitionFreelistDispatcher* Create( @@ -177,7 +177,7 @@ struct PartitionFreelistDispatcher { return entry->ClearForAllocation(); } - PA_ALWAYS_INLINE constexpr bool IsEncodedNextPtrZero( + PA_ALWAYS_INLINE bool IsEncodedNextPtrZero( PartitionFreelistEntry* entry) const { return entry->IsEncodedNextPtrZero(); } @@ -286,7 +286,7 @@ struct PartitionFreelistDispatcherImpl final : PartitionFreelistDispatcher { return GetEntryImpl(entry)->ClearForAllocation(); } - PA_ALWAYS_INLINE constexpr bool IsEncodedNextPtrZero( + PA_ALWAYS_INLINE bool IsEncodedNextPtrZero( PartitionFreelistEntry* entry) const override { return GetEntryImpl(entry)->IsEncodedNextPtrZero(); } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_lock.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_lock.h index d83fa6e1c7..0b29aa6fbb 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_lock.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_lock.h @@ -9,8 +9,8 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/immediate_crash.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" #include "partition_alloc/partition_alloc_base/threading/platform_thread.h" @@ -24,7 +24,7 @@ class PA_LOCKABLE Lock { public: inline constexpr Lock(); void Acquire() PA_EXCLUSIVE_LOCK_FUNCTION() { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) LiftThreadIsolationScope lift_thread_isolation_restrictions; #endif @@ -65,7 +65,7 @@ class PA_LOCKABLE Lock { } void Release() PA_UNLOCK_FUNCTION() { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) LiftThreadIsolationScope lift_thread_isolation_restrictions; #endif @@ -76,7 +76,7 @@ class PA_LOCKABLE Lock { } void AssertAcquired() const PA_ASSERT_EXCLUSIVE_LOCK() { lock_.AssertAcquired(); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) LiftThreadIsolationScope lift_thread_isolation_restrictions; #endif @@ -87,7 +87,7 @@ class PA_LOCKABLE Lock { void Reinit() PA_UNLOCK_FUNCTION() { lock_.AssertAcquired(); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) owning_thread_ref_.store(base::PlatformThreadRef(), std::memory_order_release); #endif @@ -97,7 +97,7 @@ class PA_LOCKABLE Lock { private: SpinningMutex lock_; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Should in theory be protected by |lock_|, but we need to read it to detect // recursive lock acquisition (and thus, the allocator becoming reentrant). std::atomic owning_thread_ref_ = diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page.cc index 7b6c04757b..a9e96a943c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page.cc @@ -8,14 +8,13 @@ #include #include "partition_alloc/address_pool_manager.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/freeslot_bitmap.h" #include "partition_alloc/page_allocator.h" #include "partition_alloc/page_allocator_constants.h" #include "partition_alloc/partition_address_space.h" #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_alloc_forward.h" @@ -193,11 +192,11 @@ void SlotSpanMetadata::FreeSlowPath(size_t number_of_freed) { return; } -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) const PartitionFreelistDispatcher* freelist_dispatcher = PartitionRoot::FromSlotSpanMetadata(this)->get_freelist_dispatcher(); freelist_dispatcher->CheckFreeList(freelist_head, bucket->slot_size); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) // If it's the current active slot span, change it. We bounce the slot span // to the empty list as a force towards defragmentation. @@ -317,7 +316,7 @@ void UnmapNow(uintptr_t reservation_start, size_t reservation_size, pool_handle pool) { PA_DCHECK(reservation_start && reservation_size > 0); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // When ENABLE_BACKUP_REF_PTR_SUPPORT is off, BRP pool isn't used. #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) if (pool == kBRPPoolHandle) { @@ -356,7 +355,7 @@ void UnmapNow(uintptr_t reservation_start, IsManagedByPartitionAllocConfigurablePool(reservation_start)); #endif } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK((reservation_start & kSuperPageOffsetMask) == 0); uintptr_t reservation_end = reservation_start + reservation_size; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page.h index 6f05c5dcd9..256c71a622 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page.h @@ -10,14 +10,13 @@ #include "partition_alloc/address_pool_manager.h" #include "partition_alloc/address_pool_manager_types.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/freeslot_bitmap_constants.h" #include "partition_alloc/partition_address_space.h" #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -29,21 +28,12 @@ #include "partition_alloc/partition_superpage_extent_entry.h" #include "partition_alloc/reservation_offset_table.h" -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/starscan/state_bitmap.h" -#endif - -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) #include "partition_alloc/tagging.h" #endif namespace partition_alloc::internal { -#if PA_BUILDFLAG(USE_STARSCAN) -using AllocationStateMap = - StateBitmap; -#endif - // Metadata of the slot span. // // Some notes on slot span states. It can be in one of four major states: @@ -87,27 +77,25 @@ struct SlotSpanMetadata { // CHECK()ed in AllocNewSlotSpan(). // The maximum number of bits needed to cover all currently supported OSes. - static constexpr size_t kMaxSlotsPerSlotSpanBits = 13; + static constexpr size_t kMaxSlotsPerSlotSpanBits = 15; static_assert(kMaxSlotsPerSlotSpan < (1 << kMaxSlotsPerSlotSpanBits), ""); - // |marked_full| isn't equivalent to being full. Slot span is marked as full - // iff it isn't on the active slot span list (or any other list). - uint32_t marked_full : 1; // |num_allocated_slots| is 0 for empty or decommitted slot spans, which can // be further differentiated by checking existence of the freelist. uint32_t num_allocated_slots : kMaxSlotsPerSlotSpanBits; uint32_t num_unprovisioned_slots : kMaxSlotsPerSlotSpanBits; + // |marked_full| isn't equivalent to being full. Slot span is marked as full + // iff it isn't on the active slot span list (or any other list). + uint32_t marked_full : 1; + private: const uint32_t can_store_raw_size_ : 1; - uint32_t freelist_is_sorted_ : 1; - uint32_t unused1_ : (32 - 1 - 2 * kMaxSlotsPerSlotSpanBits - 1 - 1); + uint16_t freelist_is_sorted_ : 1; // If |in_empty_cache_|==1, |empty_cache_index| is undefined and mustn't be // used. uint16_t in_empty_cache_ : 1; - uint16_t empty_cache_index_ - : kMaxEmptyCacheIndexBits; // < kMaxFreeableSpans. - uint16_t unused2_ : (16 - 1 - kMaxEmptyCacheIndexBits); + uint16_t empty_cache_index_ : kMaxEmptyCacheIndexBits; // < kMaxFreeableSpans. // Can use only 48 bits (6B) in this bitfield, as this structure is embedded // in PartitionPage which has 2B worth of fields and must fit in 32B. @@ -254,18 +242,13 @@ static_assert(sizeof(SlotSpanMetadata) <= kPageMetadataSize, "SlotSpanMetadata must fit into a Page Metadata slot."); inline constexpr SlotSpanMetadata::SlotSpanMetadata() noexcept - : marked_full(0), - num_allocated_slots(0), + : num_allocated_slots(0), num_unprovisioned_slots(0), + marked_full(0), can_store_raw_size_(false), freelist_is_sorted_(true), - unused1_(0), in_empty_cache_(0), - empty_cache_index_(0), - unused2_(0) { - (void)unused1_; - (void)unused2_; -} + empty_cache_index_(0) {} inline SlotSpanMetadata::SlotSpanMetadata(const SlotSpanMetadata&) = default; @@ -377,47 +360,11 @@ PA_ALWAYS_INLINE PartitionSuperPageExtentEntry* PartitionSuperPageToExtent( PartitionSuperPageToMetadataArea(super_page)); } -#if PA_BUILDFLAG(USE_STARSCAN) - -// Size that should be reserved for state bitmap (if present) inside a super -// page. Elements of a super page are partition-page-aligned, hence the returned -// size is a multiple of partition page size. -PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t -ReservedStateBitmapSize() { - return base::bits::AlignUp(sizeof(AllocationStateMap), PartitionPageSize()); -} - -// Size that should be committed for state bitmap (if present) inside a super -// page. It is a multiple of system page size. -PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t -CommittedStateBitmapSize() { - return base::bits::AlignUp(sizeof(AllocationStateMap), SystemPageSize()); -} - -// Returns the address/pointer to the state bitmap in the super page. It's the -// caller's responsibility to ensure that the bitmaps even exist. -PA_ALWAYS_INLINE uintptr_t SuperPageStateBitmapAddr(uintptr_t super_page) { - PA_DCHECK(!(super_page % kSuperPageAlignment)); - return super_page + PartitionPageSize() + - (IsManagedByNormalBuckets(super_page) ? ReservedFreeSlotBitmapSize() - : 0); -} - -PA_ALWAYS_INLINE AllocationStateMap* SuperPageStateBitmap( - uintptr_t super_page) { - return reinterpret_cast( - SuperPageStateBitmapAddr(super_page)); -} - -#else // PA_BUILDFLAG(USE_STARSCAN) - PA_ALWAYS_INLINE PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t ReservedStateBitmapSize() { return 0ull; } -#endif // PA_BUILDFLAG(USE_STARSCAN) - PA_ALWAYS_INLINE uintptr_t SuperPagePayloadStartOffset(bool is_managed_by_normal_buckets, bool with_quarantine) { @@ -482,7 +429,7 @@ PA_ALWAYS_INLINE PartitionPageMetadata* PartitionPageMetadata::FromAddr( uintptr_t address) { uintptr_t super_page = address & kSuperPageBaseMask; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(IsReservationStart(super_page)); DCheckIsWithInSuperPagePayload(address); #endif @@ -557,11 +504,11 @@ PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromAddr( PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromSlotStart( uintptr_t slot_start) { auto* slot_span = FromAddr(slot_start); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Checks that the pointer is a multiple of slot size. uintptr_t slot_span_start = ToSlotSpanStart(slot_span); PA_DCHECK(!((slot_start - slot_span_start) % slot_span->bucket->slot_size)); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) return slot_span; } @@ -584,13 +531,13 @@ PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromObject(void* object) { PA_ALWAYS_INLINE SlotSpanMetadata* SlotSpanMetadata::FromObjectInnerAddr( uintptr_t address) { auto* slot_span = FromAddr(address); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Checks that the address is within the expected object boundaries. uintptr_t slot_span_start = ToSlotSpanStart(slot_span); uintptr_t shift_from_slot_start = (address - slot_span_start) % slot_span->bucket->slot_size; DCheckIsValidShiftFromSlotStart(slot_span, shift_from_slot_start); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) return slot_span; } @@ -615,7 +562,7 @@ PA_ALWAYS_INLINE size_t SlotSpanMetadata::GetRawSize() const { PA_ALWAYS_INLINE void SlotSpanMetadata::SetFreelistHead( PartitionFreelistEntry* new_head) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // |this| is in the metadata region, hence isn't MTE-tagged. Untag |new_head| // as well. uintptr_t new_head_untagged = UntagPtr(new_head); @@ -683,7 +630,7 @@ PA_ALWAYS_INLINE void SlotSpanMetadata::AppendFreeList( PartitionRoot* root, const PartitionFreelistDispatcher* freelist_dispatcher) PA_EXCLUSIVE_LOCKS_REQUIRED(PartitionRootLock(root)) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) DCheckRootLockIsAcquired(root); PA_DCHECK(!(freelist_dispatcher->GetNext(tail, bucket->slot_size))); PA_DCHECK(number_of_freed); @@ -768,7 +715,7 @@ PA_ALWAYS_INLINE void SlotSpanMetadata::Reset() { size_t num_slots_per_span = bucket->get_slots_per_span(); PA_DCHECK(num_slots_per_span <= kMaxSlotsPerSlotSpan); - num_unprovisioned_slots = static_cast(num_slots_per_span); + num_unprovisioned_slots = static_cast(num_slots_per_span); PA_DCHECK(num_unprovisioned_slots); ToSuperPageExtent()->IncrementNumberOfNonemptySlotSpans(); @@ -776,23 +723,13 @@ PA_ALWAYS_INLINE void SlotSpanMetadata::Reset() { next_slot_span = nullptr; } -#if PA_BUILDFLAG(USE_STARSCAN) -// Returns the state bitmap from an address within a normal-bucket super page. -// It's the caller's responsibility to ensure that the bitmap exists. -PA_ALWAYS_INLINE AllocationStateMap* StateBitmapFromAddr(uintptr_t address) { - PA_DCHECK(IsManagedByNormalBuckets(address)); - uintptr_t super_page = address & kSuperPageBaseMask; - return SuperPageStateBitmap(super_page); -} -#endif // PA_BUILDFLAG(USE_STARSCAN) - // Iterates over all slot spans in a super-page. |Callback| must return true if // early return is needed. template void IterateSlotSpans(uintptr_t super_page, bool with_quarantine, Callback callback) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(!(super_page % kSuperPageAlignment)); auto* extent_entry = PartitionSuperPageToExtent(super_page); DCheckRootLockIsAcquired(extent_entry->root); @@ -837,6 +774,11 @@ void IterateSlotSpans(uintptr_t super_page, // Helper class derived from the implementation of `SlotSpanMetadata` // that can (but does not _have_ to) enforce that it is in fact a slot // start. +// +// Behavior is not well-defined if this class is used outside +// PartitionAlloc internals, e.g. if PA is deferring to sanitizers. +// In such cases, the return value from PA's `Alloc()` may not be +// a slot start - it might not be managed by PartitionAlloc at all. class PA_COMPONENT_EXPORT(PARTITION_ALLOC) SlotStart { public: template @@ -849,6 +791,18 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) SlotStart { return result; } + template + PA_ALWAYS_INLINE static SlotStart FromObject(void* tagged_object) { + uintptr_t untagged_slot_start = + internal::UntagAddr(reinterpret_cast(tagged_object)); + return SlotStart::FromUntaggedAddr(untagged_slot_start); + } + + // Tagging objects is not free. Avoid calling this repeatedly. + PA_ALWAYS_INLINE void* ToObject() { + return internal::TagAddr(untagged_slot_start); + } + PA_ALWAYS_INLINE void CheckIsSlotStart() { auto* slot_span_metadata = SlotSpanMetadata::FromAddr(untagged_slot_start); @@ -865,31 +819,6 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) SlotStart { : untagged_slot_start(untagged_slot_start) {} }; -// Helper class analogous to `SlotStart` and implemented in terms of -// the same. -// -// Notably, no untag-tag is incurred if `enforce` is false. -class PA_COMPONENT_EXPORT(PARTITION_ALLOC) TaggedSlotStart { - public: - template - PA_ALWAYS_INLINE static TaggedSlotStart FromTaggedAddr( - uintptr_t tagged_slot_start) { - TaggedSlotStart result = TaggedSlotStart(tagged_slot_start); - if constexpr (enforce) { - SlotStart::FromUntaggedAddr( - internal::UntagAddr(tagged_slot_start)); - } - return result; - } - - uintptr_t tagged_slot_start; - - private: - PA_ALWAYS_INLINE - explicit TaggedSlotStart(uintptr_t tagged_slot_start) - : tagged_slot_start(tagged_slot_start) {} -}; - } // namespace partition_alloc::internal #endif // PARTITION_ALLOC_PARTITION_PAGE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page_constants.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page_constants.h index a5d2ce8995..a5c96b6224 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page_constants.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_page_constants.h @@ -16,10 +16,14 @@ namespace partition_alloc::internal { // (1 << 12 or 1 << 14), as checked in PartitionRoot::Init(). And // PartitionPageSize() is 4 times the OS page size. static constexpr size_t kMaxSlotsPerSlotSpan = 4 * (1 << 14) / kSmallestBucket; +#elif defined(PARTITION_ALLOCATOR_CONSTANTS_POSIX_NONCONST_PAGE_SIZE) && \ + PA_BUILDFLAG(IS_LINUX) && \ + (PA_BUILDFLAG(PA_ARCH_CPU_ARM64) || PA_BUILDFLAG(PA_ARCH_CPU_PPC64)) +// System page size can be 4, 16, or 64 kiB on Linux on AArch64. +// System page size can be 4 or 64 kiB on Linux on ppc64. +// In both cases, use the 64 kiB maximum. +static constexpr size_t kMaxSlotsPerSlotSpan = 4 * (1 << 16) / kSmallestBucket; #elif defined(PARTITION_ALLOCATOR_CONSTANTS_POSIX_NONCONST_PAGE_SIZE) -// System page size can be 4, 16, or 64 kiB on Linux on arm64. 64 kiB is -// currently (kMaxSlotsPerSlotSpanBits == 13) not supported by the code, -// so we use the 16 kiB maximum (64 kiB will crash). static constexpr size_t kMaxSlotsPerSlotSpan = 4 * (1 << 14) / kSmallestBucket; #else // A slot span can "span" multiple PartitionPages, but then its slot size is diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc index 06db42602d..4f00b79c47 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc @@ -7,6 +7,7 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/freeslot_bitmap.h" #include "partition_alloc/in_slot_metadata.h" #include "partition_alloc/oom.h" @@ -16,9 +17,7 @@ #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -34,10 +33,6 @@ #include "partition_alloc/partition_alloc_base/mac/mac_util.h" #endif -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/starscan/pcscan.h" -#endif - #if !PA_BUILDFLAG(HAS_64_BIT_POINTERS) #include "partition_alloc/address_pool_manager_bitmap.h" #endif @@ -838,7 +833,7 @@ static void PartitionDumpBucketStats(PartitionBucketMemoryStats* stats_out, } } -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) void DCheckIfManagedByPartitionAllocBRPPool(uintptr_t address) { PA_DCHECK(IsManagedByPartitionAllocBRPPool(address)); } @@ -846,7 +841,7 @@ void DCheckIfManagedByPartitionAllocBRPPool(uintptr_t address) { #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) void PartitionAllocThreadIsolationInit(ThreadIsolationOption thread_isolation) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) ThreadIsolationSettings::settings.enabled = true; #endif PartitionAddressSpace::InitThreadIsolatedPool(thread_isolation); @@ -1086,12 +1081,11 @@ void PartitionRoot::Init(PartitionOptions opts) { (internal::SystemPageSize() == (size_t{1} << 14))); #elif PA_BUILDFLAG(IS_LINUX) && PA_BUILDFLAG(PA_ARCH_CPU_ARM64) // Check runtime pagesize. Though the code is currently the same, it is - // not merged with the IS_APPLE case above as a 1 << 16 case needs to be - // added here in the future, to allow 64 kiB pagesize. That is only - // supported on Linux on arm64, not on IS_APPLE, but not yet present here - // as the rest of the PartitionAlloc does not currently support it. + // not merged with the IS_APPLE case above as a 1 << 16 case is only + // supported on Linux on AArch64. PA_CHECK((internal::SystemPageSize() == (size_t{1} << 12)) || - (internal::SystemPageSize() == (size_t{1} << 14))); + (internal::SystemPageSize() == (size_t{1} << 14)) || + (internal::SystemPageSize() == (size_t{1} << 16))); #endif ::partition_alloc::internal::ScopedGuard guard{lock_}; @@ -1109,11 +1103,11 @@ void PartitionRoot::Init(PartitionOptions opts) { ReserveBackupRefPtrGuardRegionIfNeeded(); #endif -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) settings.use_cookie = true; #else static_assert(!Settings::use_cookie); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) settings.brp_enabled_ = opts.backup_ref_ptr == PartitionOptions::kEnabled; #else // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) @@ -1184,13 +1178,8 @@ void PartitionRoot::Init(PartitionOptions opts) { #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) if (brp_enabled()) { - size_t in_slot_metadata_size = - internal::AlignUpInSlotMetadataSizeForApple( - internal::kInSlotMetadataSizeAdjustment); - settings.in_slot_metadata_size = in_slot_metadata_size; - PA_CHECK(internal::kInSlotMetadataSizeAdjustment <= - in_slot_metadata_size); - settings.extras_size += in_slot_metadata_size; + settings.in_slot_metadata_size = internal::kInSlotMetadataSizeAdjustment; + settings.extras_size += internal::kInSlotMetadataSizeAdjustment; #if PA_CONFIG(MAYBE_ENABLE_MAC11_MALLOC_SIZE_HACK) EnableMac11MallocSizeHackIfNeeded(); #endif @@ -1198,14 +1187,7 @@ void PartitionRoot::Init(PartitionOptions opts) { #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) #endif // PA_CONFIG(EXTRAS_REQUIRED) - settings.quarantine_mode = -#if PA_BUILDFLAG(USE_STARSCAN) - (opts.star_scan_quarantine == PartitionOptions::kDisallowed - ? QuarantineMode::kAlwaysDisabled - : QuarantineMode::kDisabledByDefault); -#else - QuarantineMode::kAlwaysDisabled; -#endif // PA_BUILDFLAG(USE_STARSCAN) + settings.quarantine_mode = QuarantineMode::kAlwaysDisabled; // We mark the sentinel slot span as free to make sure it is skipped by our // logic to find a new active slot span. @@ -1390,14 +1372,14 @@ bool PartitionRoot::TryReallocInPlaceForDirectMap( size_t available_reservation_size = current_reservation_size - extent->padding_for_alignment - PartitionRoot::GetDirectMapMetadataAndGuardPagesSize(); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) uintptr_t reservation_start = slot_start & internal::kSuperPageBaseMask; PA_DCHECK(internal::IsReservationStart(reservation_start)); PA_DCHECK(slot_start + available_reservation_size == reservation_start + current_reservation_size - GetDirectMapMetadataAndGuardPagesSize() + internal::PartitionPageSize()); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(new_slot_size > internal::kMaxMemoryTaggingSize); if (new_slot_size == current_slot_size) { @@ -1422,7 +1404,7 @@ bool PartitionRoot::TryReallocInPlaceForDirectMap( // entries in the reservation offset table (for entire reservation_size // region) have been already initialized. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) memset(reinterpret_cast(slot_start + current_slot_size), internal::kUninitializedByte, recommit_slot_size_growth); #endif @@ -1478,17 +1460,17 @@ bool PartitionRoot::TryReallocInPlaceForNormalBuckets( // memory as we're already using, so re-use the allocation after updating // statistics (and cookie, if present). if (slot_span->CanStoreRawSize()) { -#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && PA_BUILDFLAG(DCHECKS_ARE_ON) internal::InSlotMetadata* old_ref_count = nullptr; if (PA_LIKELY(brp_enabled())) { old_ref_count = InSlotMetadataPointerFromSlotStartAndSize( slot_start, slot_span->bucket->slot_size); } #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && - // PA_BUILDFLAG(PA_DCHECK_IS_ON) + // PA_BUILDFLAG(DCHECKS_ARE_ON) size_t new_raw_size = AdjustSizeForExtrasAdd(new_size); slot_span->SetRawSize(new_raw_size); -#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && PA_BUILDFLAG(DCHECKS_ARE_ON) if (PA_LIKELY(brp_enabled())) { internal::InSlotMetadata* new_ref_count = InSlotMetadataPointerFromSlotStartAndSize( @@ -1496,7 +1478,7 @@ bool PartitionRoot::TryReallocInPlaceForNormalBuckets( PA_DCHECK(new_ref_count == old_ref_count); } #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && - // PA_BUILDFLAG(PA_DCHECK_IS_ON) + // PA_BUILDFLAG(DCHECKS_ARE_ON) // Write a new trailing cookie only when it is possible to keep track // raw size (otherwise we wouldn't know where to look for it later). if (settings.use_cookie) { @@ -1518,20 +1500,14 @@ bool PartitionRoot::TryReallocInPlaceForNormalBuckets( } void PartitionRoot::PurgeMemory(int flags) { + auto start = now_maybe_overridden_for_testing(); + unsigned int local_purge_generation, local_purge_next_bucket_index; + { ::partition_alloc::internal::ScopedGuard guard{ internal::PartitionRootLock(this)}; - auto start = now_maybe_overridden_for_testing(); - -#if PA_BUILDFLAG(USE_STARSCAN) - // Avoid purging if there is PCScan task currently scheduled. Since pcscan - // takes snapshot of all allocated pages, decommitting pages here (even - // under the lock) is racy. - // TODO(bikineev): Consider rescheduling the purging after PCScan. - if (PCScan::IsInProgress()) { - return; - } -#endif // PA_BUILDFLAG(USE_STARSCAN) + local_purge_next_bucket_index = purge_next_bucket_index; + local_purge_generation = purge_generation; if (flags & PurgeFlags::kDecommitEmptySlotSpans) { DecommitEmptySlotSpans(); @@ -1541,43 +1517,70 @@ void PartitionRoot::PurgeMemory(int flags) { return; } } - if (flags & PurgeFlags::kDiscardUnusedSystemPages) { - for (unsigned int bucket_index = purge_next_bucket_index; - bucket_index < internal::kNumBuckets; bucket_index++) { - Bucket& bucket = buckets[bucket_index]; - if (bucket.slot_size == internal::kInvalidBucketSize) { - continue; - } + } - // Don't do the most expensive operation except for the largest buckets, - // where the cost of doing so is lower, and gains are likely higher. - size_t min_bucket_size_to_purge = - (flags & PurgeFlags::kLimitDuration) - ? internal::MinConservativePurgeableSlotSize() - : internal::MinPurgeableSlotSize(); - if (bucket.slot_size >= min_bucket_size_to_purge) { - internal::PartitionPurgeBucket(this, &bucket); - } else { - if (sort_smaller_slot_span_free_lists_) { - bucket.SortSmallerSlotSpanFreeLists(); - } - } + if (flags & PurgeFlags::kDiscardUnusedSystemPages) { + // Don't do the most expensive operation except for the largest buckets, + // where the cost of doing so is lower, and gains are likely higher, + // except in two cases + // - We don't care about reclaim duration + // - It's been a long time (16 walks through the entire bucket list) + // + // Note that in the latter case, we still limit total reclaim duration. + size_t min_bucket_size_to_purge = + internal::MinConservativePurgeableSlotSize(); + if (!(flags & PurgeFlags::kLimitDuration) || !local_purge_generation) { + min_bucket_size_to_purge = internal::MinPurgeableSlotSize(); + } - // Do it at the end, as the actions above change the status of slot - // spans (e.g. empty -> decommitted). - bucket.MaintainActiveList(); + for (unsigned int bucket_index = local_purge_next_bucket_index; + bucket_index < internal::kNumBuckets; bucket_index++) { + // Only acquire the lock for a single iteration, so that if there is a + // waiter blocked on it, it can steal it from us before the next + // one. + ::partition_alloc::internal::ScopedGuard guard{ + internal::PartitionRootLock(this)}; - if (sort_active_slot_spans_) { - bucket.SortActiveSlotSpans(); - } - if (flags & PurgeFlags::kLimitDuration && - (now_maybe_overridden_for_testing() - start > kMaxPurgeDuration)) { - // Pick up where we stopped next time. - purge_next_bucket_index = (bucket_index + 1) % kNumBuckets; - return; + Bucket& bucket = buckets[bucket_index]; + if (bucket.slot_size == internal::kInvalidBucketSize) { + continue; + } + + if (bucket.slot_size >= min_bucket_size_to_purge) { + internal::PartitionPurgeBucket(this, &bucket); + } else { + if (sort_smaller_slot_span_free_lists_) { + bucket.SortSmallerSlotSpanFreeLists(); } } + + // Do it at the end, as the actions above change the status of slot + // spans (e.g. empty -> decommitted). + bucket.MaintainActiveList(); + + if (sort_active_slot_spans_) { + bucket.SortActiveSlotSpans(); + } + // Checking at the end to make sure we make progress by processing at + // least one bucket. + if (flags & PurgeFlags::kLimitDuration && + (now_maybe_overridden_for_testing() - start > kMaxPurgeDuration)) { + // Pick up where we stopped next time. + purge_next_bucket_index = (bucket_index + 1) % kNumBuckets; + return; + } + } + + { + ::partition_alloc::internal::ScopedGuard guard{ + internal::PartitionRootLock(this)}; + // In theory, these may have been modified since we last read them into + // the local variables at the beginning of the function. This should not + // happen (since Purge() runs on a single thread), and also does not + // matter since we just want to make sure to not do too much work and to + // make some progress. purge_next_bucket_index = 0; + purge_generation = (purge_generation + 1) % 16; } } } @@ -1768,7 +1771,7 @@ void PartitionRoot::ResetForTesting(bool allow_leaks) { ::partition_alloc::internal::ScopedGuard guard{ internal::PartitionRootLock(this)}; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) if (!allow_leaks) { unsigned num_allocated_slots = 0; for (Bucket& bucket : buckets) { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.h index 0a5a1bd7d5..7b4135258c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.h @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -42,7 +41,7 @@ #include "partition_alloc/address_pool_manager_types.h" #include "partition_alloc/allocation_guard.h" #include "partition_alloc/build_config.h" -#include "partition_alloc/chromecast_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/freeslot_bitmap.h" #include "partition_alloc/in_slot_metadata.h" #include "partition_alloc/lightweight_quarantine.h" @@ -53,13 +52,11 @@ #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/export_template.h" #include "partition_alloc/partition_alloc_base/no_destructor.h" #include "partition_alloc/partition_alloc_base/notreached.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" #include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -78,10 +75,6 @@ #include "partition_alloc/thread_cache.h" #include "partition_alloc/thread_isolation/thread_isolation.h" -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/starscan/pcscan.h" -#endif - namespace partition_alloc::internal { // We want this size to be big enough that we have time to start up other @@ -108,7 +101,7 @@ namespace partition_alloc { namespace internal { // Avoid including partition_address_space.h from this .h file, by moving the // call to IsManagedByPartitionAllocBRPPool into the .cc file. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_COMPONENT_EXPORT(PARTITION_ALLOC) void DCheckIfManagedByPartitionAllocBRPPool(uintptr_t address); #else @@ -152,7 +145,7 @@ struct PartitionOptions { // positive of the plugin, since constexpr implies inline. inline constexpr PartitionOptions(); inline constexpr PartitionOptions(const PartitionOptions& other); - inline constexpr ~PartitionOptions(); + inline PA_CONSTEXPR_DTOR ~PartitionOptions(); enum class AllowToggle : uint8_t { kDisallowed, @@ -196,7 +189,7 @@ struct PartitionOptions { constexpr PartitionOptions::PartitionOptions() = default; constexpr PartitionOptions::PartitionOptions(const PartitionOptions& other) = default; -constexpr PartitionOptions::~PartitionOptions() = default; +PA_CONSTEXPR_DTOR PartitionOptions::~PartitionOptions() = default; // When/if free lists should be "straightened" when calling // PartitionRoot::PurgeMemory(..., accounting_only=false). @@ -214,9 +207,6 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { using FreeListEntry = internal::PartitionFreelistEntry; using SuperPageExtentEntry = internal::PartitionSuperPageExtentEntry; using DirectMapExtent = internal::PartitionDirectMapExtent; -#if PA_BUILDFLAG(USE_STARSCAN) - using PCScan = internal::PCScan; -#endif enum class QuarantineMode : uint8_t { kAlwaysDisabled, @@ -254,11 +244,11 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { bool with_thread_cache = false; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) bool use_cookie = false; #else static constexpr bool use_cookie = false; -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) bool brp_enabled_ = false; #if PA_CONFIG(MAYBE_ENABLE_MAC11_MALLOC_SIZE_HACK) @@ -371,8 +361,11 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { int16_t global_empty_slot_span_ring_size PA_GUARDED_BY(internal::PartitionRootLock(this)) = internal::kDefaultEmptySlotSpanRingSize; - unsigned int purge_next_bucket_index + uint16_t purge_generation PA_GUARDED_BY(internal::PartitionRootLock(this)) = + 0; + uint16_t purge_next_bucket_index PA_GUARDED_BY(internal::PartitionRootLock(this)) = 0; + static_assert(kNumBuckets < std::numeric_limits::max()); // Integrity check = ~reinterpret_cast(this). uintptr_t inverted_self = 0; @@ -838,14 +831,6 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { return internal::TagAddr(SlotStartToObjectAddr(slot_start)); } - PA_ALWAYS_INLINE void* TaggedSlotStartToObject( - void* tagged_slot_start) const { - return reinterpret_cast( - internal::TaggedSlotStart::FromTaggedAddr( - reinterpret_cast(tagged_slot_start)) - .tagged_slot_start); - } - PA_ALWAYS_INLINE uintptr_t ObjectToSlotStart(void* object) const { uintptr_t untagged_slot_start = internal::UntagAddr(reinterpret_cast(object)); @@ -857,11 +842,6 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { return UntagPtr(object); } - PA_ALWAYS_INLINE uintptr_t ObjectToTaggedSlotStart(void* object) const { - return reinterpret_cast( - internal::TagAddr(ObjectToSlotStart(object))); - } - #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) bool brp_enabled() const { return settings.brp_enabled_; } #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) @@ -1158,7 +1138,7 @@ PartitionAllocGetDirectMapSlotStartAndSizeInBRPPool(uintptr_t address) { PA_DCHECK(!page_metadata->slot_span_metadata_offset); auto* slot_span = &page_metadata->slot_span_metadata; uintptr_t slot_start = SlotSpanMetadata::ToSlotSpanStart(slot_span); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) auto* direct_map_metadata = PartitionDirectMapMetadata::FromSlotSpanMetadata(slot_span); size_t padding_for_alignment = @@ -1168,7 +1148,7 @@ PartitionAllocGetDirectMapSlotStartAndSizeInBRPPool(uintptr_t address) { PartitionPageSize()); PA_DCHECK(slot_start == reservation_start + PartitionPageSize() + padding_for_alignment); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) return SlotAddressAndSize{.slot_start = slot_start, .size = slot_span->bucket->slot_size}; } @@ -1192,12 +1172,12 @@ PartitionAllocGetSlotStartAndSizeInBRPPool(uintptr_t address) { } auto* slot_span = SlotSpanMetadata::FromAddr(address); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) auto* root = PartitionRoot::FromSlotSpanMetadata(slot_span); // Double check that in-slot metadata is indeed present. Currently that's the // case only when BRP is used. PA_DCHECK(root->brp_enabled()); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) // Get the offset from the beginning of the slot span. uintptr_t slot_span_start = SlotSpanMetadata::ToSlotSpanStart(slot_span); @@ -1251,7 +1231,7 @@ PA_ALWAYS_INLINE void PartitionAllocFreeForRefCounting(uintptr_t slot_start) { ->IsAlive()); // Iterating over the entire slot can be really expensive. -#if PA_BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON) +#if PA_BUILDFLAG(EXPENSIVE_DCHECKS_ARE_ON) auto hook = PartitionAllocHooks::GetQuarantineOverrideHook(); // If we have a hook the object segment is not necessarily filled // with |kQuarantinedByte|. @@ -1264,7 +1244,7 @@ PA_ALWAYS_INLINE void PartitionAllocFreeForRefCounting(uintptr_t slot_start) { } DebugMemset(SlotStartAddr2Ptr(slot_start), kFreedByte, slot_span->GetUtilizedSlotSize()); -#endif // PA_BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON) +#endif // PA_BUILDFLAG(EXPENSIVE_DCHECKS_ARE_ON) root->total_size_of_brp_quarantined_bytes.fetch_sub( slot_span->GetSlotSizeForBookkeeping(), std::memory_order_relaxed); @@ -1286,7 +1266,7 @@ PartitionRoot::AllocFromBucket(Bucket* bucket, size_t* slot_size, bool* is_already_zeroed) { PA_DCHECK((slot_span_alignment >= internal::PartitionPageSize()) && - std::has_single_bit(slot_span_alignment)); + internal::base::bits::HasSingleBit(slot_span_alignment)); SlotSpanMetadata* slot_span = bucket->active_slot_spans_head; // There always must be a slot span on the active list (could be a sentinel). PA_DCHECK(slot_span); @@ -1481,9 +1461,7 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) { return; } - // Almost all calls to FreeNoNooks() will end up writing to |*object|, the - // only cases where we don't would be delayed free() in PCScan, but |*object| - // can be cold in cache. + // Almost all calls to FreeNoNooks() will end up writing to |*object|. PA_PREFETCH_FOR_WRITE(object); // On Android, malloc() interception is more fragile than on other @@ -1497,7 +1475,7 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) { // On Android Chromecast devices, this is already checked in PartitionFree() // in the shim. #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ - (PA_BUILDFLAG(IS_ANDROID) && !PA_BUILDFLAG(PA_IS_CAST_ANDROID)) + (PA_BUILDFLAG(IS_ANDROID) && !PA_BUILDFLAG(IS_CAST_ANDROID)) uintptr_t object_addr = internal::ObjectPtr2Addr(object); PA_CHECK(IsManagedByPartitionAlloc(object_addr)); #endif @@ -1505,17 +1483,18 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) { SlotSpanMetadata* slot_span = SlotSpanMetadata::FromObject(object); PA_DCHECK(PartitionRoot::FromSlotSpanMetadata(slot_span) == this); + internal::SlotStart slot_start = internal::SlotStart::FromObject(object); + PA_DCHECK(slot_span == + SlotSpanMetadata::FromSlotStart(slot_start.untagged_slot_start)); + #if PA_BUILDFLAG(HAS_MEMORY_TAGGING) if (PA_LIKELY(IsMemoryTaggingEnabled())) { const size_t slot_size = slot_span->bucket->slot_size; if (PA_LIKELY(slot_size <= internal::kMaxMemoryTaggingSize)) { - // slot_span is untagged at this point, so we have to recover its tag - // again to increment and provide use-after-free mitigations. - void* retagged_slot_start = internal::TagMemoryRangeIncrement( - ObjectToTaggedSlotStart(object), slot_size); - // Incrementing the MTE-tag in the memory range invalidates the |object|'s - // tag, so it must be retagged. - object = TaggedSlotStartToObject(retagged_slot_start); + // Retag the `object` to provide MTE UaF mitigation. Doing so + // invalidates the tag in the address of `object`, so it must + // be refreshed. + object = internal::TagMemoryRangeIncrement(object, slot_size); } } #else // PA_BUILDFLAG(HAS_MEMORY_TAGGING) @@ -1533,13 +1512,9 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) { PA_PREFETCH(slot_span); #endif // PA_BUILDFLAG(HAS_MEMORY_TAGGING) - uintptr_t slot_start = ObjectToSlotStart(object); - PA_DCHECK(slot_span == SlotSpanMetadata::FromSlotStart(slot_start)); - if constexpr (ContainsFlags(flags, FreeFlags::kZap)) { if (settings.zapping_by_free_flags) { - internal::SecureMemset(internal::SlotStartAddr2Ptr(slot_start), - internal::kFreedByte, + internal::SecureMemset(object, internal::kFreedByte, GetSlotUsableSize(slot_span)); } } @@ -1554,31 +1529,18 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) { // will be false only for the aligned partition. if (brp_enabled()) { auto* ref_count = InSlotMetadataPointerFromSlotStartAndSize( - slot_start, slot_span->bucket->slot_size); + slot_start.untagged_slot_start, slot_span->bucket->slot_size); ref_count->PreReleaseFromAllocator(); } #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - GetSchedulerLoopQuarantineBranch().Quarantine(object, slot_span, - slot_start); + GetSchedulerLoopQuarantineBranch().Quarantine( + object, slot_span, slot_start.untagged_slot_start, + GetSlotUsableSize(slot_span)); return; } } -#if PA_BUILDFLAG(USE_STARSCAN) - // TODO(bikineev): Change the condition to PA_LIKELY once PCScan is enabled by - // default. - if (PA_UNLIKELY(ShouldQuarantine(object))) { - // PCScan safepoint. Call before potentially scheduling scanning task. - PCScan::JoinScanIfNeeded(); - if (PA_LIKELY(internal::IsManagedByNormalBuckets(slot_start))) { - PCScan::MoveToQuarantine(object, GetSlotUsableSize(slot_span), slot_start, - slot_span->bucket->slot_size); - return; - } - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - - FreeNoHooksImmediate(object, slot_span, slot_start); + FreeNoHooksImmediate(object, slot_span, slot_start.untagged_slot_start); } PA_ALWAYS_INLINE void PartitionRoot::FreeNoHooksImmediate( @@ -1620,17 +1582,6 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeNoHooksImmediate( GetSlotUsableSize(slot_span)); } -#if PA_BUILDFLAG(USE_STARSCAN) - // TODO(bikineev): Change the condition to PA_LIKELY once PCScan is enabled by - // default. - if (PA_UNLIKELY(IsQuarantineEnabled())) { - if (PA_LIKELY(internal::IsManagedByNormalBuckets(slot_start))) { - // Mark the state in the state bitmap as freed. - internal::StateBitmapFromAddr(slot_start)->Free(slot_start); - } - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - #if PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) if (PA_LIKELY(brp_enabled())) { auto* ref_count = InSlotMetadataPointerFromSlotStartAndSize( @@ -1660,7 +1611,7 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeNoHooksImmediate( #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) // memset() can be really expensive. -#if PA_BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON) +#if PA_BUILDFLAG(EXPENSIVE_DCHECKS_ARE_ON) internal::DebugMemset(internal::SlotStartAddr2Ptr(slot_start), internal::kFreedByte, slot_span->GetUtilizedSlotSize()); #elif PA_CONFIG(ZERO_RANDOMLY_ON_FREE) @@ -2089,7 +2040,7 @@ PA_ALWAYS_INLINE void* PartitionRoot::AllocInternal(size_t requested_size, const char* type_name) { static_assert(AreValidFlags(flags)); PA_DCHECK((slot_span_alignment >= internal::PartitionPageSize()) && - std::has_single_bit(slot_span_alignment)); + internal::base::bits::HasSingleBit(slot_span_alignment)); static_assert(!ContainsFlags( flags, AllocFlags::kMemoryShouldBeTaggedForMte)); // Internal only. @@ -2182,16 +2133,6 @@ PA_ALWAYS_INLINE void* PartitionRoot::AllocInternalNoHooks( uintptr_t slot_start = 0; size_t slot_size = 0; -#if PA_BUILDFLAG(USE_STARSCAN) - const bool is_quarantine_enabled = IsQuarantineEnabled(); - // PCScan safepoint. Call before trying to allocate from cache. - // TODO(bikineev): Change the condition to PA_LIKELY once PCScan is enabled by - // default. - if (PA_UNLIKELY(is_quarantine_enabled)) { - PCScan::JoinScanIfNeeded(); - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - auto* thread_cache = GetOrCreateThreadCache(); // Don't use thread cache if higher order alignment is requested, because the @@ -2212,7 +2153,7 @@ PA_ALWAYS_INLINE void* PartitionRoot::AllocInternalNoHooks( // Keep it in sync! usable_size = AdjustSizeForExtrasSubtract(slot_size); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Make sure that the allocated pointer comes from the same place it would // for a non-thread cache allocation. SlotSpanMetadata* slot_span = SlotSpanMetadata::FromSlotStart(slot_start); @@ -2260,7 +2201,7 @@ PA_ALWAYS_INLINE void* PartitionRoot::AllocInternalNoHooks( // (f) slot_size // // Notes: - // - Cookie exists only in the PA_BUILDFLAG(PA_DCHECK_IS_ON) case. + // - Cookie exists only in the PA_BUILDFLAG(DCHECKS_ARE_ON) case. // - Think of raw_size as the minimum size required internally to satisfy // the allocation request (i.e. requested_size + extras) // - At most one "empty" or "unused" space can occur at a time. They occur @@ -2297,7 +2238,7 @@ PA_ALWAYS_INLINE void* PartitionRoot::AllocInternalNoHooks( // PA_LIKELY: operator new() calls malloc(), not calloc(). if constexpr (!zero_fill) { // memset() can be really expensive. -#if PA_BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON) +#if PA_BUILDFLAG(EXPENSIVE_DCHECKS_ARE_ON) internal::DebugMemset(object, internal::kUninitializedByte, usable_size); #endif } else if (!is_already_zeroed) { @@ -2327,17 +2268,6 @@ PA_ALWAYS_INLINE void* PartitionRoot::AllocInternalNoHooks( } #endif // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) -#if PA_BUILDFLAG(USE_STARSCAN) - // TODO(bikineev): Change the condition to PA_LIKELY once PCScan is enabled by - // default. - if (PA_UNLIKELY(is_quarantine_enabled)) { - if (PA_LIKELY(internal::IsManagedByNormalBuckets(slot_start))) { - // Mark the corresponding bits in the state bitmap as allocated. - internal::StateBitmapFromAddr(slot_start)->Allocate(slot_start); - } - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - return object; } @@ -2384,7 +2314,7 @@ PA_ALWAYS_INLINE void* PartitionRoot::AlignedAllocInline( // crbug.com/1185484. // This is mandated by |posix_memalign()|, so should never fire. - PA_CHECK(std::has_single_bit(alignment)); + PA_CHECK(internal::base::bits::HasSingleBit(alignment)); // Catch unsupported alignment requests early. PA_CHECK(alignment <= internal::kMaxSupportedAlignment); size_t raw_size = AdjustSizeForExtrasAdd(requested_size); @@ -2400,10 +2330,12 @@ PA_ALWAYS_INLINE void* PartitionRoot::AlignedAllocInline( // PartitionAlloc only guarantees alignment for power-of-two sized // allocations. To make sure this applies here, round up the allocation // size. - raw_size = static_cast(1) - << (int{sizeof(size_t) * 8} - std::countl_zero(raw_size - 1)); + raw_size = + static_cast(1) + << (int{sizeof(size_t) * 8} - + partition_alloc::internal::base::bits::CountlZero(raw_size - 1)); } - PA_DCHECK(std::has_single_bit(raw_size)); + PA_DCHECK(internal::base::bits::HasSingleBit(raw_size)); // Adjust back, because AllocInternalNoHooks/Alloc will adjust it again. adjusted_size = AdjustSizeForExtrasSubtract(raw_size); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_stats.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_stats.h index df967b29ba..1de104ed39 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_stats.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_stats.h @@ -8,8 +8,8 @@ #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h index 93d76bc8b2..87190a632a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h @@ -11,10 +11,10 @@ #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" #include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h" -#include "partition_alloc/partition_alloc_buildflags.h" namespace base::internal { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h index b512eb6fb0..480ed28c86 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h @@ -12,16 +12,14 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/flags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" #include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_forward.h" #include "partition_alloc/pointers/instance_tracer.h" -#include "partition_alloc/raw_ptr_buildflags.h" #if PA_BUILDFLAG(IS_WIN) #include "partition_alloc/partition_alloc_base/win/win_handle_types.h" @@ -415,7 +413,10 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr { } PA_ALWAYS_INLINE constexpr raw_ptr& operator=(const raw_ptr& p) noexcept { - // Duplicate before releasing, in case the pointer is assigned to itself. + // Increment the ref-count first before releasing, in case the pointer is + // assigned to itself. (This is different from the concern in the assign-T* + // version of this operator, where a different pointer to the same allocator + // slot could cause trouble, which isn't a concern here at all.) // // Unlike the move version of this operator, don't add |this != &p| branch, // for performance reasons. Self-assignment is rare, so unconditionally @@ -530,7 +531,12 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr { // `raw_ptr -> T* -> raw_ptr<>` route will be taken. static_assert(Traits == (raw_ptr::Traits | RawPtrTraits::kMayDangle)); + // If it was the same type, another overload would've been used. + static_assert(!std::is_same_v>); + // Unlike the regular varsion of operator=, we don't have an issue of + // `*this` and `ptr` being the same object (because it isn't even the same + // type, as asserted above), so no need to increment the ref-count first. Impl::ReleaseWrappedPtr(wrapped_ptr_); Impl::Untrace(tracer_.owner_id()); wrapped_ptr_ = Impl::WrapRawPtrForDuplication( @@ -587,9 +593,15 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr { return *this; } PA_ALWAYS_INLINE constexpr raw_ptr& operator=(T* p) noexcept { + // Duplicate before releasing, in case the pointers point to the same + // allocator slot. Releasing the pointer first could lead to dropping the + // ref-count to 0 for the slot, immediately unqurantining and releasing it, + // just to immediately reacquire the the ref-count on that slot, leading to + // correctness issues. + T* new_ptr = Impl::WrapRawPtr(p); Impl::ReleaseWrappedPtr(wrapped_ptr_); Impl::Untrace(tracer_.owner_id()); - wrapped_ptr_ = Impl::WrapRawPtr(p); + wrapped_ptr_ = new_ptr; Impl::Trace(tracer_.owner_id(), wrapped_ptr_); return *this; } @@ -601,15 +613,12 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr { !std::is_void_v::type>>> PA_ALWAYS_INLINE constexpr raw_ptr& operator=( const raw_ptr& ptr) noexcept { - // Make sure that pointer isn't assigned to itself (look at raw_ptr address, - // not its contained pointer value). The comparison is only needed when they - // are the same type, otherwise they can't be the same raw_ptr object. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ - PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - if constexpr (std::is_same_v>) { - PA_RAW_PTR_CHECK(this != &ptr); - } -#endif + // If it was the same type, another overload would've been used. + static_assert(!std::is_same_v>); + + // Unlike the regular varsion of operator=, we don't have an issue of + // `*this` and `ptr` being the same object (because it isn't even the same + // type, as asserted above), so no need to increment the ref-count first. Impl::ReleaseWrappedPtr(wrapped_ptr_); Impl::Untrace(tracer_.owner_id()); wrapped_ptr_ = @@ -623,15 +632,12 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr { !std::is_void_v::type>>> PA_ALWAYS_INLINE constexpr raw_ptr& operator=( raw_ptr&& ptr) noexcept { - // Make sure that pointer isn't assigned to itself (look at raw_ptr address, - // not its contained pointer value). The comparison is only needed when they - // are the same type, otherwise they can't be the same raw_ptr object. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ - PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - if constexpr (std::is_same_v>) { - PA_RAW_PTR_CHECK(this != &ptr); - } -#endif + // If it was the same type, another overload would've been used. + static_assert(!std::is_same_v>); + + // Unlike the regular varsion of operator=, we don't have an issue of + // `*this` and `ptr` being the same object (because it isn't even the same + // type, as asserted above), so no need to increment the ref-count first. Impl::ReleaseWrappedPtr(wrapped_ptr_); Impl::Untrace(tracer_.owner_id()); wrapped_ptr_ = Impl::template Upcast(ptr.wrapped_ptr_); @@ -1254,7 +1260,6 @@ struct iterator_traits> { // `std::to_address(pointer)` in C++20 [3]. // // [1] https://wg21.link/pointer.traits.optmem - template struct pointer_traits<::raw_ptr> { using pointer = ::raw_ptr; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_asan_unowned_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_asan_unowned_impl.h index 6a772b9d91..c2ba4a81d9 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_asan_unowned_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_asan_unowned_impl.h @@ -8,9 +8,9 @@ #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_forward.h" #if !PA_BUILDFLAG(USE_RAW_PTR_ASAN_UNOWNED_IMPL) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.cc index 98e047673b..67eb234103 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.cc @@ -6,11 +6,11 @@ #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/dangling_raw_ptr_checks.h" #include "partition_alloc/in_slot_metadata.h" #include "partition_alloc/partition_alloc.h" #include "partition_alloc/partition_alloc_base/check.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_root.h" #include "partition_alloc/reservation_offset_table.h" @@ -19,7 +19,7 @@ namespace base::internal { template void RawPtrBackupRefImpl::AcquireInternal( uintptr_t address) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_BASE_CHECK(UseBrp(address)); #endif @@ -39,7 +39,7 @@ void RawPtrBackupRefImpl::AcquireInternal( template void RawPtrBackupRefImpl::ReleaseInternal( uintptr_t address) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_BASE_CHECK(UseBrp(address)); #endif @@ -100,7 +100,7 @@ bool RawPtrBackupRefImpl:: template bool RawPtrBackupRefImpl::IsPointeeAlive( uintptr_t address) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_BASE_CHECK(UseBrp(address)); #endif @@ -122,7 +122,7 @@ template struct RawPtrBackupRefImpl; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address) { if (partition_alloc::internal::IsManagedByDirectMap(address)) { @@ -136,7 +136,7 @@ void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address) { partition_alloc::PartitionPageSize()); } } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) || +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) || // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) } // namespace base::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h index 54326319d1..f49a35b5c1 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h @@ -9,11 +9,11 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_address_space.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" #include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_alloc_forward.h" @@ -30,7 +30,7 @@ namespace base::internal { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_COMPONENT_EXPORT(RAW_PTR) void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address); @@ -71,11 +71,11 @@ struct RawPtrBackupRefImpl { // address is nullptr. #if PA_HAS_BUILTIN(__builtin_constant_p) if (__builtin_constant_p(address == 0) && (address == 0)) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_BASE_CHECK( !partition_alloc::IsManagedByPartitionAllocBRPPool(address)); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) || +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) || // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) return false; } @@ -102,7 +102,7 @@ struct RawPtrBackupRefImpl { // IsManagedByPartitionAllocBRPPool returns true for a valid pointer, // it must be at least partition page away from the beginning of a super // page. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) if (use_brp) { CheckThatAddressIsntWithinFirstPartitionPage(address); @@ -158,7 +158,7 @@ struct RawPtrBackupRefImpl { } uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(ptr)); if (IsSupportedAndNotNull(address)) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_BASE_CHECK(ptr != nullptr); #endif @@ -193,7 +193,7 @@ struct RawPtrBackupRefImpl { } uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(wrapped_ptr)); if (IsSupportedAndNotNull(address)) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_BASE_CHECK(wrapped_ptr != nullptr); #endif @@ -217,7 +217,7 @@ struct RawPtrBackupRefImpl { if (partition_alloc::internal::base::is_constant_evaluated()) { return wrapped_ptr; } -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) || \ +#if PA_BUILDFLAG(DCHECKS_ARE_ON) || \ PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) #if PA_BUILDFLAG(BACKUP_REF_PTR_POISON_OOB_PTR) PA_BASE_CHECK(!IsPtrOOB(wrapped_ptr)); @@ -227,7 +227,7 @@ struct RawPtrBackupRefImpl { PA_BASE_CHECK(wrapped_ptr != nullptr); PA_BASE_CHECK(IsPointeeAlive(address)); // Detects use-after-free. } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) || +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) || // PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) return wrapped_ptr; } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_exclusion.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_exclusion.h index 7734657c11..afe79ace2a 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_exclusion.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_exclusion.h @@ -8,8 +8,8 @@ // This header will be leakily included even when // `!use_partition_alloc`, which is okay because it's a leaf header. #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" // nogncheck -#include "partition_alloc/partition_alloc_buildflags.h" #if PA_HAS_ATTRIBUTE(annotate) #if defined(OFFICIAL_BUILD) && !PA_BUILDFLAG(FORCE_ENABLE_RAW_PTR_EXCLUSION) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_hookable_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_hookable_impl.h index e5dc2fc4ab..404c8ed4ac 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_hookable_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_hookable_impl.h @@ -8,10 +8,10 @@ #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" #include "partition_alloc/partition_alloc_base/cxx20_is_constant_evaluated.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_forward.h" #if !PA_BUILDFLAG(USE_RAW_PTR_HOOKABLE_IMPL) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc index d07f5813ba..f57d18ef7d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc @@ -11,7 +11,7 @@ #include "base/functional/bind.h" #include "base/functional/callback.h" #include "partition_alloc/pointers/raw_ptr.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" namespace { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h index b518596629..0ccb95acfb 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h @@ -9,9 +9,9 @@ #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/augmentations/compiler_specific.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/pointers/raw_ptr.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pool_offset_freelist.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pool_offset_freelist.h index e2f7cad55d..c680abab1c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pool_offset_freelist.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pool_offset_freelist.h @@ -9,11 +9,10 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_address_space.h" #include "partition_alloc/partition_alloc-inl.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/tagging.h" @@ -78,11 +77,11 @@ class EncodedPoolOffset { if (!ptr) { return kEncodeedNullptr; } - uintptr_t address = reinterpret_cast(ptr); + uintptr_t address = SlotStartPtr2Addr(ptr); PoolInfo pool_info = PartitionAddressSpace::GetPoolInfo(address); // Save a MTE tag as well as an offset. - uintptr_t tagged_offset = address & (kPtrTagMask | ~pool_info.base_mask); - PA_DCHECK(tagged_offset == (pool_info.offset | (address & kPtrTagMask))); + uintptr_t tagged_offset = + reinterpret_cast(ptr) & (kPtrTagMask | ~pool_info.base_mask); return Transform(tagged_offset); } @@ -210,7 +209,7 @@ class PoolOffsetFreelistEntry { // SetNext() is either called on the freelist head, when provisioning new // slots, or when GetNext() has been called before, no need to pass the // size. -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Regular freelists always point to an entry within the same super page. // // This is most likely a PartitionAlloc bug if this triggers. @@ -219,7 +218,7 @@ class PoolOffsetFreelistEntry { (SlotStartPtr2Addr(entry) & kSuperPageBaseMask))) { FreelistCorruptionDetected(0); } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) encoded_next_ = EncodedPoolOffset(entry); #if PA_CONFIG(HAS_FREELIST_SHADOW_ENTRY) @@ -253,7 +252,7 @@ class PoolOffsetFreelistEntry { return nullptr; } - PoolInfo pool_info = GetPoolInfo(reinterpret_cast(this)); + PoolInfo pool_info = GetPoolInfo(SlotStartPtr2Addr(this)); // We verify that `(next_ & pool_info.base_mask) == 0` in `IsWellFormed()`, // which is meant to prevent from breaking out of the pool in face of // a corruption (see PoolOffsetFreelistEntry class-level comment). diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reservation_offset_table.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reservation_offset_table.cc index 0ab06c05c2..949604573f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reservation_offset_table.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reservation_offset_table.cc @@ -4,7 +4,7 @@ #include "partition_alloc/reservation_offset_table.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" namespace partition_alloc::internal { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reservation_offset_table.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reservation_offset_table.h index 1e534ecffd..88fcaa9134 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reservation_offset_table.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/reservation_offset_table.h @@ -12,11 +12,10 @@ #include "partition_alloc/address_pool_manager.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_address_space.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/tagging.h" @@ -182,7 +181,7 @@ PA_ALWAYS_INLINE uintptr_t ComputeReservationStart(uintptr_t address, // If the given address doesn't point to direct-map allocated memory, // returns 0. PA_ALWAYS_INLINE uintptr_t GetDirectMapReservationStart(uintptr_t address) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) bool is_in_brp_pool = IsManagedByPartitionAllocBRPPool(address); bool is_in_regular_pool = IsManagedByPartitionAllocRegularPool(address); bool is_in_configurable_pool = @@ -196,14 +195,14 @@ PA_ALWAYS_INLINE uintptr_t GetDirectMapReservationStart(uintptr_t address) { #if !PA_BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) PA_DCHECK(!is_in_brp_pool); #endif -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) uint16_t* offset_ptr = ReservationOffsetPointer(address); PA_DCHECK(*offset_ptr != kOffsetTagNotAllocated); if (*offset_ptr == kOffsetTagNormalBuckets) { return 0; } uintptr_t reservation_start = ComputeReservationStart(address, offset_ptr); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // MSVC workaround: the preprocessor seems to choke on an `#if` embedded // inside another macro (PA_DCHECK). #if !PA_BUILDFLAG(HAS_64_BIT_POINTERS) @@ -228,7 +227,7 @@ PA_ALWAYS_INLINE uintptr_t GetDirectMapReservationStart(uintptr_t address) { IsManagedByPartitionAllocThreadIsolatedPool(reservation_start)); #endif PA_DCHECK(*ReservationOffsetPointer(reservation_start) == 0); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) return reservation_start; } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_dispatch.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_dispatch.h index bbd42211d1..33b227bea2 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_dispatch.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_dispatch.h @@ -30,6 +30,10 @@ struct AllocatorDispatch { void* address, size_t size, void* context); + using ReallocUncheckedFn = void*(const AllocatorDispatch* self, + void* ptr, + size_t size, + void* context); using FreeFn = void(const AllocatorDispatch* self, void* address, void* context); @@ -64,11 +68,20 @@ struct AllocatorDispatch { size_t size, size_t alignment, void* context); + using AlignedMallocUncheckedFn = void*(const AllocatorDispatch* self, + size_t size, + size_t alignment, + void* context); using AlignedReallocFn = void*(const AllocatorDispatch* self, void* address, size_t size, size_t alignment, void* context); + using AlignedReallocUncheckedFn = void*(const AllocatorDispatch* self, + void* address, + size_t size, + size_t alignment, + void* context); using AlignedFreeFn = void(const AllocatorDispatch* self, void* address, void* context); @@ -78,6 +91,7 @@ struct AllocatorDispatch { AllocZeroInitializedFn* alloc_zero_initialized_function; AllocAlignedFn* alloc_aligned_function; ReallocFn* realloc_function; + ReallocUncheckedFn* realloc_unchecked_function; FreeFn* free_function; GetSizeEstimateFn* get_size_estimate_function; GoodSizeFn* good_size_function; @@ -91,7 +105,9 @@ struct AllocatorDispatch { // _aligned_malloc, _aligned_realloc, and _aligned_free are specific to the // Windows allocator. AlignedMallocFn* aligned_malloc_function; + AlignedMallocUncheckedFn* aligned_malloc_unchecked_function; AlignedReallocFn* aligned_realloc_function; + AlignedReallocUncheckedFn* aligned_realloc_unchecked_function; AlignedFreeFn* aligned_free_function; const AllocatorDispatch* next; @@ -112,8 +128,9 @@ struct AllocatorDispatch { // which is more efficient than having {this_alloc, this_free} where // this_free is a function just calls next_free. // - // Note that it's hard for toolchains to apply TCO (tail-call optimization) - // because the allocator shim chain is built runtime. + // Given its performance sensitivity, it is recommended to use tail-call + // optimizations wherever possible. Use MUSTTAIL on return statements in + // AllocatorDispatch. // // Note that this optimization works well because there is no case to remove // a shim in the middle of the allocator shim chain nor to reorder the shims @@ -145,6 +162,7 @@ struct AllocatorDispatch { COPY_IF_NULLPTR(alloc_zero_initialized_function); COPY_IF_NULLPTR(alloc_aligned_function); COPY_IF_NULLPTR(realloc_function); + COPY_IF_NULLPTR(realloc_unchecked_function); COPY_IF_NULLPTR(free_function); COPY_IF_NULLPTR(get_size_estimate_function); COPY_IF_NULLPTR(good_size_function); @@ -154,7 +172,9 @@ struct AllocatorDispatch { COPY_IF_NULLPTR(free_definite_size_function); COPY_IF_NULLPTR(try_free_default_function); COPY_IF_NULLPTR(aligned_malloc_function); + COPY_IF_NULLPTR(aligned_malloc_unchecked_function); COPY_IF_NULLPTR(aligned_realloc_function); + COPY_IF_NULLPTR(aligned_realloc_unchecked_function); COPY_IF_NULLPTR(aligned_free_function); #undef COPY_IF_NULLPTR diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.h index e0d4876b43..0ffe987a55 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.h @@ -5,7 +5,7 @@ #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_INTERCEPTION_APPLE_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_INTERCEPTION_APPLE_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.mm index c82ef756b1..63345f8c49 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.mm @@ -17,7 +17,7 @@ #include "partition_alloc/shim/allocator_interception_apple.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include @@ -26,7 +26,6 @@ #import #include -#include #include #include #include @@ -34,6 +33,7 @@ #include "partition_alloc/build_config.h" #include "partition_alloc/oom.h" #include "partition_alloc/partition_alloc_base/apple/mach_logging.h" +#include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/logging.h" #include "partition_alloc/partition_alloc_check.h" @@ -183,7 +183,7 @@ void* oom_killer_memalign(struct _malloc_zone_t* zone, // other reasons why null might be returned. See posix_memalign() in 10.15's // https://opensource.apple.com/source/libmalloc/libmalloc-283/src/malloc.c . if (!result && size && alignment >= sizeof(void*) && - std::has_single_bit(alignment)) { + partition_alloc::internal::base::bits::HasSingleBit(alignment)) { partition_alloc::TerminateBecauseOutOfMemory(size); } return result; @@ -239,7 +239,7 @@ void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone, // other reasons why null might be returned. See posix_memalign() in 10.15's // https://opensource.apple.com/source/libmalloc/libmalloc-283/src/malloc.c . if (!result && size && alignment >= sizeof(void*) && - std::has_single_bit(alignment)) { + partition_alloc::internal::base::bits::HasSingleBit(alignment)) { partition_alloc::TerminateBecauseOutOfMemory(size); } return result; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc index 8c05d584a0..03528ffef3 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc @@ -7,7 +7,7 @@ #include #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h index fdfe96ccc8..c9d01a5638 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h @@ -8,7 +8,7 @@ #include #include -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include "partition_alloc/build_config.h" @@ -17,10 +17,6 @@ #include "partition_alloc/shim/allocator_dispatch.h" #include "partition_alloc/tagging.h" -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/starscan/pcscan.h" -#endif - namespace allocator_shim { // Allocator Shim API. Allows to: @@ -64,9 +60,37 @@ void SetCallNewHandlerOnMallocFailure(bool value); // regardless of SetCallNewHandlerOnMallocFailure(). PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) void* UncheckedAlloc(size_t size); +// Reallocates |ptr| to point at |size| bytes with the same alignment as |ptr|, +// or returns nullptr while leaving the |ptr| unchanged. It does NOT call the +// new_handler, regardless of SetCallNewHandlerOnMallocFailure(). +PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) +void* UncheckedRealloc(void* ptr, size_t size); + // Frees memory allocated with UncheckedAlloc(). PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) void UncheckedFree(void* ptr); +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + +// The aligned allocation functions are only available when PartitionAlloc is +// acting as malloc. Otherwise there may be nothing to forward them to for the +// platform allocator. + +// Allocates |size| bytes aligned to |align| or returns nullptr. It does NOT +// call the new_handler, regardless of SetCallNewHandlerOnMallocFailure(). +PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) +void* UncheckedAlignedAlloc(size_t align, size_t size); + +// Reallocates |ptr| to point at |size| bytes with an alignment of |align|, +// or returns nullptr while leaving the |ptr| unchanged. It does NOT call the +// new_handler, regardless of SetCallNewHandlerOnMallocFailure(). +PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) +void* UncheckedAlignedRealloc(void* ptr, size_t size, size_t align); + +// Frees memory allocated with UncheckedAlignedAlloc(). +PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) void UncheckedAlignedFree(void* ptr); + +#endif + // Inserts |dispatch| in front of the allocator chain. This method is // thread-safe w.r.t concurrent invocations of InsertAllocatorDispatch(). // The callers have responsibility for inserting a single dispatch no more @@ -141,10 +165,6 @@ PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) uint32_t GetMainPartitionRootExtrasSize(); PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) void AdjustDefaultAllocatorForForeground(); PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) void AdjustDefaultAllocatorForBackground(); -#if PA_BUILDFLAG(USE_STARSCAN) -PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) -void EnablePCScan(partition_alloc::internal::PCScan::InitConfig); -#endif #endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) } // namespace allocator_shim diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_android.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_android.cc index 7c8f014be6..a92a713606 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_android.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_android.cc @@ -7,7 +7,7 @@ #include #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_apple.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_apple.cc index bb7abe9d7f..6a89deeccc 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_apple.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_apple.cc @@ -8,8 +8,8 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/apple/mach_logging.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/shim/allocator_interception_apple.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_apple_zoned_malloc.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_apple_zoned_malloc.cc index 0373c66ca5..8bc19f7e8b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_apple_zoned_malloc.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_apple_zoned_malloc.cc @@ -123,6 +123,7 @@ const AllocatorDispatch AllocatorDispatch::default_dispatch = { &CallocImpl, /* alloc_zero_initialized_function */ &MemalignImpl, /* alloc_aligned_function */ &ReallocImpl, /* realloc_function */ + &ReallocImpl, /* realloc_unchecked_function */ &FreeImpl, /* free_function */ &GetSizeEstimateImpl, /* get_size_estimate_function */ &GoodSizeImpl, /* good_size_function */ @@ -132,7 +133,9 @@ const AllocatorDispatch AllocatorDispatch::default_dispatch = { &FreeDefiniteSizeImpl, /* free_definite_size_function */ &TryFreeDefaultImpl, /* try_free_default_function */ nullptr, /* aligned_malloc_function */ + nullptr, /* aligned_malloc_unchecked_function */ nullptr, /* aligned_realloc_function */ + nullptr, /* aligned_realloc_unchecked_function */ nullptr, /* aligned_free_function */ nullptr, /* next */ }; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc index ec23ed9798..41c532544b 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc @@ -76,6 +76,17 @@ void* GlibcRealloc(const AllocatorDispatch*, return __libc_realloc(address, size); } +void* GlibcUncheckedRealloc(const AllocatorDispatch*, + void* address, + size_t size, + void* context) { + if (PA_UNLIKELY(size >= kMaxAllowedSize)) { + return nullptr; + } + + return __libc_realloc(address, size); +} + void* GlibcMemalign(const AllocatorDispatch*, size_t alignment, size_t size, @@ -110,21 +121,24 @@ size_t GlibcGetSizeEstimate(const AllocatorDispatch*, } // namespace const AllocatorDispatch AllocatorDispatch::default_dispatch = { - &GlibcMalloc, /* alloc_function */ - &GlibcUncheckedMalloc, /* alloc_unchecked_function */ - &GlibcCalloc, /* alloc_zero_initialized_function */ - &GlibcMemalign, /* alloc_aligned_function */ - &GlibcRealloc, /* realloc_function */ - &GlibcFree, /* free_function */ - &GlibcGetSizeEstimate, /* get_size_estimate_function */ - nullptr, /* good_size_function */ - nullptr, /* claimed_address */ - nullptr, /* batch_malloc_function */ - nullptr, /* batch_free_function */ - nullptr, /* free_definite_size_function */ - nullptr, /* try_free_default_function */ - nullptr, /* aligned_malloc_function */ - nullptr, /* aligned_realloc_function */ - nullptr, /* aligned_free_function */ - nullptr, /* next */ + &GlibcMalloc, /* alloc_function */ + &GlibcUncheckedMalloc, /* alloc_unchecked_function */ + &GlibcCalloc, /* alloc_zero_initialized_function */ + &GlibcMemalign, /* alloc_aligned_function */ + &GlibcRealloc, /* realloc_function */ + &GlibcUncheckedRealloc, /* realloc_unchecked_function */ + &GlibcFree, /* free_function */ + &GlibcGetSizeEstimate, /* get_size_estimate_function */ + nullptr, /* good_size_function */ + nullptr, /* claimed_address */ + nullptr, /* batch_malloc_function */ + nullptr, /* batch_free_function */ + nullptr, /* free_definite_size_function */ + nullptr, /* try_free_default_function */ + nullptr, /* aligned_malloc_function */ + nullptr, /* aligned_malloc_unchecked_function */ + nullptr, /* aligned_realloc_function */ + nullptr, /* aligned_realloc_unchecked_function */ + nullptr, /* aligned_free_function */ + nullptr, /* next */ }; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc index 5b523a1dd3..6496070df8 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc @@ -72,6 +72,7 @@ const AllocatorDispatch AllocatorDispatch::default_dispatch = { &RealCalloc, /* alloc_zero_initialized_function */ &RealMemalign, /* alloc_aligned_function */ &RealRealloc, /* realloc_function */ + &RealRealloc, /* realloc_unchecked_function */ &RealFree, /* free_function */ &RealSizeEstimate, /* get_size_estimate_function */ nullptr, /* good_size_function */ @@ -81,7 +82,9 @@ const AllocatorDispatch AllocatorDispatch::default_dispatch = { nullptr, /* free_definite_size_function */ nullptr, /* try_free_default_function */ nullptr, /* aligned_malloc_function */ + nullptr, /* aligned_malloc_unchecked_function */ nullptr, /* aligned_realloc_function */ + nullptr, /* aligned_realloc_unchecked_function */ nullptr, /* aligned_free_function */ nullptr, /* next */ }; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc index f4a5bb9efd..93bc1d54e2 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc @@ -5,7 +5,6 @@ #include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h" #include -#include #include #include #include @@ -13,21 +12,20 @@ #include "partition_alloc/allocation_guard.h" #include "partition_alloc/build_config.h" -#include "partition_alloc/chromecast_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/memory_reclaimer.h" #include "partition_alloc/partition_alloc.h" +#include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/no_destructor.h" #include "partition_alloc/partition_alloc_base/numerics/checked_math.h" #include "partition_alloc/partition_alloc_base/numerics/safe_conversions.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_root.h" #include "partition_alloc/partition_stats.h" #include "partition_alloc/shim/allocator_dispatch.h" #include "partition_alloc/shim/allocator_shim_internals.h" -#include "partition_alloc/shim/nonscannable_allocator.h" #if PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) #include @@ -175,6 +173,7 @@ bool AllocatorConfigurationFinalized() { return g_roots_finalized.load(); } +template void* AllocateAlignedMemory(size_t alignment, size_t size) { // Memory returned by the regular allocator *always* respects |kAlignment|, // which is a power of two, and any valid alignment is also a power of two. So @@ -186,15 +185,13 @@ void* AllocateAlignedMemory(size_t alignment, size_t size) { // time. if (alignment <= partition_alloc::internal::kAlignment) { // This is mandated by |posix_memalign()| and friends, so should never fire. - PA_CHECK(std::has_single_bit(alignment)); + PA_CHECK(partition_alloc::internal::base::bits::HasSingleBit(alignment)); // TODO(bartekn): See if the compiler optimizes branches down the stack on // Mac, where PartitionPageSize() isn't constexpr. - return Allocator()->AllocInline( - size); + return Allocator()->AllocInline(size); } - return Allocator()->AlignedAllocInline( - alignment, size); + return Allocator()->AlignedAllocInline(alignment, size); } } // namespace @@ -232,7 +229,8 @@ void* PartitionMemalign(const AllocatorDispatch*, size_t size, void* context) { partition_alloc::ScopedDisallowAllocations guard{}; - return AllocateAlignedMemory(alignment, size); + return AllocateAlignedMemory(alignment, + size); } void* PartitionAlignedAlloc(const AllocatorDispatch* dispatch, @@ -240,7 +238,18 @@ void* PartitionAlignedAlloc(const AllocatorDispatch* dispatch, size_t alignment, void* context) { partition_alloc::ScopedDisallowAllocations guard{}; - return AllocateAlignedMemory(alignment, size); + return AllocateAlignedMemory(alignment, + size); +} + +void* PartitionAlignedAllocUnchecked(const AllocatorDispatch* dispatch, + size_t size, + size_t alignment, + void* context) { + partition_alloc::ScopedDisallowAllocations guard{}; + return AllocateAlignedMemory( + alignment, size); } // aligned_realloc documentation is @@ -257,7 +266,43 @@ void* PartitionAlignedRealloc(const AllocatorDispatch* dispatch, partition_alloc::ScopedDisallowAllocations guard{}; void* new_ptr = nullptr; if (size > 0) { - new_ptr = AllocateAlignedMemory(alignment, size); + new_ptr = AllocateAlignedMemory( + alignment, size); + } else { + // size == 0 and address != null means just "free(address)". + if (address) { + partition_alloc::PartitionRoot::FreeInlineInUnknownRoot< + partition_alloc::FreeFlags::kNoHooks>(address); + } + } + // The original memory block (specified by address) is unchanged if ENOMEM. + if (!new_ptr) { + return nullptr; + } + // TODO(tasak): Need to compare the new alignment with the address' alignment. + // If the two alignments are not the same, need to return nullptr with EINVAL. + if (address) { + size_t usage = partition_alloc::PartitionRoot::GetUsableSize(address); + size_t copy_size = usage > size ? size : usage; + memcpy(new_ptr, address, copy_size); + + partition_alloc::PartitionRoot::FreeInlineInUnknownRoot< + partition_alloc::FreeFlags::kNoHooks>(address); + } + return new_ptr; +} + +void* PartitionAlignedReallocUnchecked(const AllocatorDispatch* dispatch, + void* address, + size_t size, + size_t alignment, + void* context) { + partition_alloc::ScopedDisallowAllocations guard{}; + void* new_ptr = nullptr; + if (size > 0) { + new_ptr = AllocateAlignedMemory( + alignment, size); } else { // size == 0 and address != null means just "free(address)". if (address) { @@ -302,11 +347,32 @@ void* PartitionRealloc(const AllocatorDispatch*, size, ""); } -#if PA_BUILDFLAG(PA_IS_CAST_ANDROID) +void* PartitionReallocUnchecked(const AllocatorDispatch*, + void* address, + size_t size, + void* context) { + partition_alloc::ScopedDisallowAllocations guard{}; +#if PA_BUILDFLAG(IS_APPLE) + if (PA_UNLIKELY(!partition_alloc::IsManagedByPartitionAlloc( + reinterpret_cast(address)) && + address)) { + // A memory region allocated by the system allocator is passed in this + // function. Forward the request to `realloc` which supports zone- + // dispatching so that it appropriately selects the right zone. + return realloc(address, size); + } +#endif // PA_BUILDFLAG(IS_APPLE) + + return Allocator() + ->Realloc(address, size, ""); +} + +#if PA_BUILDFLAG(IS_CAST_ANDROID) extern "C" { void __real_free(void*); } // extern "C" -#endif // PA_BUILDFLAG(PA_IS_CAST_ANDROID) +#endif // PA_BUILDFLAG(IS_CAST_ANDROID) void PartitionFree(const AllocatorDispatch*, void* object, void* context) { partition_alloc::ScopedDisallowAllocations guard{}; @@ -326,7 +392,7 @@ void PartitionFree(const AllocatorDispatch*, void* object, void* context) { // malloc() pointer can be passed to PartitionAlloc's free(). If we don't own // the pointer, pass it along. This should not have a runtime cost vs regular // Android, since on Android we have a PA_CHECK() rather than the branch here. -#if PA_BUILDFLAG(PA_IS_CAST_ANDROID) +#if PA_BUILDFLAG(IS_CAST_ANDROID) if (PA_UNLIKELY(!partition_alloc::IsManagedByPartitionAlloc( reinterpret_cast(object)) && object)) { @@ -335,7 +401,7 @@ void PartitionFree(const AllocatorDispatch*, void* object, void* context) { // here. return __real_free(object); } -#endif // PA_BUILDFLAG(PA_IS_CAST_ANDROID) +#endif // PA_BUILDFLAG(IS_CAST_ANDROID) partition_alloc::PartitionRoot::FreeInlineInUnknownRoot< partition_alloc::FreeFlags::kNoHooks>(object); @@ -577,22 +643,6 @@ uint32_t GetMainPartitionRootExtrasSize() { #endif // PA_CONFIG(EXTRAS_REQUIRED) } -#if PA_BUILDFLAG(USE_STARSCAN) -void EnablePCScan(partition_alloc::internal::PCScan::InitConfig config) { - partition_alloc::internal::PCScan::Initialize(config); - - PA_CHECK(AllocatorConfigurationFinalized()); - partition_alloc::internal::PCScan::RegisterScannableRoot(Allocator()); - if (OriginalAllocator() != nullptr) { - partition_alloc::internal::PCScan::RegisterScannableRoot( - OriginalAllocator()); - } - - allocator_shim::NonScannableAllocator::Instance().NotifyPCScanEnabled(); - allocator_shim::NonQuarantinableAllocator::Instance().NotifyPCScanEnabled(); -} -#endif // PA_BUILDFLAG(USE_STARSCAN) - void AdjustDefaultAllocatorForForeground() { Allocator()->AdjustForForeground(); } @@ -611,7 +661,9 @@ const AllocatorDispatch AllocatorDispatch::default_dispatch = { PartitionCalloc, // alloc_zero_initialized_function &allocator_shim::internal::PartitionMemalign, // alloc_aligned_function &allocator_shim::internal::PartitionRealloc, // realloc_function - &allocator_shim::internal::PartitionFree, // free_function + &allocator_shim::internal:: + PartitionReallocUnchecked, // realloc_unchecked_function + &allocator_shim::internal::PartitionFree, // free_function &allocator_shim::internal:: PartitionGetSizeEstimate, // get_size_estimate_function #if PA_BUILDFLAG(IS_APPLE) @@ -638,7 +690,11 @@ const AllocatorDispatch AllocatorDispatch::default_dispatch = { &allocator_shim::internal:: PartitionAlignedAlloc, // aligned_malloc_function &allocator_shim::internal:: - PartitionAlignedRealloc, // aligned_realloc_function + PartitionAlignedAllocUnchecked, // aligned_malloc_unchecked_function + &allocator_shim::internal:: + PartitionAlignedRealloc, // aligned_realloc_function + &allocator_shim::internal:: + PartitionAlignedReallocUnchecked, // aligned_realloc_unchecked_function &allocator_shim::internal::PartitionFree, // aligned_free_function nullptr, // next }; @@ -666,22 +722,6 @@ SHIM_ALWAYS_EXPORT int mallopt(int cmd, int value) __THROW { SHIM_ALWAYS_EXPORT struct mallinfo mallinfo(void) __THROW { partition_alloc::SimplePartitionStatsDumper allocator_dumper; Allocator()->DumpStats("malloc", true, &allocator_dumper); - // TODO(bartekn): Dump OriginalAllocator() into "malloc" as well. - // Dump stats for nonscannable and nonquarantinable allocators. - auto& nonscannable_allocator = - allocator_shim::NonScannableAllocator::Instance(); - partition_alloc::SimplePartitionStatsDumper nonscannable_allocator_dumper; - if (auto* nonscannable_root = nonscannable_allocator.root()) { - nonscannable_root->DumpStats("malloc", true, - &nonscannable_allocator_dumper); - } - auto& nonquarantinable_allocator = - allocator_shim::NonQuarantinableAllocator::Instance(); - partition_alloc::SimplePartitionStatsDumper nonquarantinable_allocator_dumper; - if (auto* nonquarantinable_root = nonquarantinable_allocator.root()) { - nonquarantinable_root->DumpStats("malloc", true, - &nonquarantinable_allocator_dumper); - } struct mallinfo info = {}; info.arena = 0; // Memory *not* allocated with mmap(). @@ -689,21 +729,15 @@ SHIM_ALWAYS_EXPORT struct mallinfo mallinfo(void) __THROW { // Memory allocated with mmap(), aka virtual size. info.hblks = partition_alloc::internal::base::checked_cast( - allocator_dumper.stats().total_mmapped_bytes + - nonscannable_allocator_dumper.stats().total_mmapped_bytes + - nonquarantinable_allocator_dumper.stats().total_mmapped_bytes); + allocator_dumper.stats().total_mmapped_bytes); // Resident bytes. info.hblkhd = partition_alloc::internal::base::checked_cast( - allocator_dumper.stats().total_resident_bytes + - nonscannable_allocator_dumper.stats().total_resident_bytes + - nonquarantinable_allocator_dumper.stats().total_resident_bytes); + allocator_dumper.stats().total_resident_bytes); // Allocated bytes. info.uordblks = partition_alloc::internal::base::checked_cast( - allocator_dumper.stats().total_active_bytes + - nonscannable_allocator_dumper.stats().total_active_bytes + - nonquarantinable_allocator_dumper.stats().total_active_bytes); + allocator_dumper.stats().total_active_bytes); return info; } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h index 7d513db99c..b1370719c1 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h @@ -5,7 +5,7 @@ #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DEFAULT_DISPATCH_TO_PARTITION_ALLOC_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DEFAULT_DISPATCH_TO_PARTITION_ALLOC_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include "partition_alloc/partition_alloc.h" @@ -55,6 +55,12 @@ void* PartitionAlignedAlloc(const AllocatorDispatch* dispatch, size_t alignment, void* context); +PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) +void* PartitionAlignedAllocUnchecked(const AllocatorDispatch* dispatch, + size_t size, + size_t alignment, + void* context); + PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) void* PartitionAlignedRealloc(const AllocatorDispatch* dispatch, void* address, @@ -62,12 +68,25 @@ void* PartitionAlignedRealloc(const AllocatorDispatch* dispatch, size_t alignment, void* context); +PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) +void* PartitionAlignedReallocUnchecked(const AllocatorDispatch* dispatch, + void* address, + size_t size, + size_t alignment, + void* context); + PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) void* PartitionRealloc(const AllocatorDispatch*, void* address, size_t size, void* context); +PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) +void* PartitionReallocUnchecked(const AllocatorDispatch*, + void* address, + size_t size, + void* context); + PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) void PartitionFree(const AllocatorDispatch*, void* object, void* context); @@ -83,9 +102,17 @@ size_t PartitionGetSizeEstimate(const AllocatorDispatch*, // we're making it more resilient to ConfigurePartitions() interface changes, so // that we don't have to modify multiple callers. This is particularly important // when callers are in a different repo, like PDFium or Dawn. -PA_ALWAYS_INLINE void ConfigurePartitionsForTesting() { +PA_ALWAYS_INLINE void ConfigurePartitionsForTesting( + bool enable_memory_tagging_if_available = true) { auto enable_brp = allocator_shim::EnableBrp(true); + +#if PA_BUILDFLAG(HAS_MEMORY_TAGGING) + auto enable_memory_tagging = + allocator_shim::EnableMemoryTagging(enable_memory_tagging_if_available); +#else auto enable_memory_tagging = allocator_shim::EnableMemoryTagging(false); +#endif // PA_BUILDFLAG(HAS_MEMORY_TAGGING) + // Since the only user of this function is a test function, we use // synchronous reporting mode, if MTE is enabled. auto memory_tagging_reporting_mode = diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_winheap.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_winheap.cc index 2c2771c6d2..e31c17f0a2 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_winheap.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_winheap.cc @@ -95,6 +95,7 @@ constexpr AllocatorDispatch AllocatorDispatch::default_dispatch = { &DefaultWinHeapCallocImpl, &DefaultWinHeapMemalignImpl, &DefaultWinHeapReallocImpl, + &DefaultWinHeapReallocImpl, /* realloc_unchecked_function */ &DefaultWinHeapFreeImpl, &DefaultWinHeapGetSizeEstimateImpl, nullptr, /* good_size */ @@ -104,7 +105,9 @@ constexpr AllocatorDispatch AllocatorDispatch::default_dispatch = { nullptr, /* free_definite_size_function */ nullptr, /* try_free_default_function */ &DefaultWinHeapAlignedMallocImpl, + &DefaultWinHeapAlignedMallocImpl, /* aligned_malloc_unchecked_function */ &DefaultWinHeapAlignedReallocImpl, + &DefaultWinHeapAlignedReallocImpl, /* aligned_realloc_unchecked_function */ &DefaultWinHeapAlignedFreeImpl, nullptr, /* next */ }; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.cc index 3069ed9f35..5b33020e11 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.cc @@ -39,6 +39,7 @@ AllocatorDispatch allocator_dispatch = { nullptr, // alloc_zero_initialized_function nullptr, // alloc_aligned_function nullptr, // realloc_function + nullptr, // realloc_unchecked_function FreeFn, // free_function nullptr, // get_size_estimate_function nullptr, // good_size_function @@ -48,7 +49,9 @@ AllocatorDispatch allocator_dispatch = { FreeDefiniteSizeFn, // free_definite_size_function TryFreeDefaultFn, // try_free_default_function nullptr, // aligned_malloc_function + nullptr, // aligned_malloc_unchecked_function nullptr, // aligned_realloc_function + nullptr, // aligned_realloc_unchecked_function AlignedFreeFn, // aligned_free_function nullptr // next }; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_functions.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_functions.h index 5fe645ff71..806f25fdd6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_functions.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_functions.h @@ -66,11 +66,33 @@ void* UncheckedAlloc(size_t size) { return chain_head->alloc_unchecked_function(chain_head, size, nullptr); } +void* UncheckedRealloc(void* ptr, size_t size) { + const AllocatorDispatch* const chain_head = internal::GetChainHead(); + return chain_head->realloc_unchecked_function(chain_head, ptr, size, nullptr); +} + void UncheckedFree(void* ptr) { const AllocatorDispatch* const chain_head = internal::GetChainHead(); return chain_head->free_function(chain_head, ptr, nullptr); } +void* UncheckedAlignedAlloc(size_t size, size_t align) { + const AllocatorDispatch* const chain_head = internal::GetChainHead(); + return chain_head->aligned_malloc_unchecked_function(chain_head, size, align, + nullptr); +} + +void* UncheckedAlignedRealloc(void* ptr, size_t size, size_t align) { + const AllocatorDispatch* const chain_head = internal::GetChainHead(); + return chain_head->aligned_realloc_unchecked_function(chain_head, ptr, size, + align, nullptr); +} + +void UncheckedAlignedFree(void* ptr) { + const AllocatorDispatch* const chain_head = internal::GetChainHead(); + return chain_head->aligned_free_function(chain_head, ptr, nullptr); +} + void InsertAllocatorDispatch(AllocatorDispatch* dispatch) { // Loop in case of (an unlikely) race on setting the list head. constexpr size_t kMaxRetries = 7; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_default_zone.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_default_zone.h index 19de53cfa4..e4a7660ac1 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_default_zone.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_default_zone.h @@ -17,10 +17,10 @@ #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/apple/mach_logging.h" #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/logging.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_root.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_symbols.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_symbols.h index 0ee2bd5984..7e8ebc5e85 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_symbols.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_apple_symbols.h @@ -9,7 +9,7 @@ #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_APPLE_SYMBOLS_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_APPLE_SYMBOLS_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include "partition_alloc/shim/malloc_zone_functions_apple.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h index 4fb059ebea..24a6c2459e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h @@ -9,7 +9,7 @@ #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_CPP_SYMBOLS_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_CPP_SYMBOLS_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) // Preempt the default new/delete C++ symbols so they call the shim entry diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_glibc_weak_symbols.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_glibc_weak_symbols.h index a060117695..205149b417 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_glibc_weak_symbols.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_glibc_weak_symbols.h @@ -20,7 +20,7 @@ // allocating via malloc() and freeing using __libc_free(). // See tcmalloc's libc_override_glibc.h for more context. -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include // for __GLIBC__ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_libc_symbols.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_libc_symbols.h index 76925ebb11..a7206d73d7 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_libc_symbols.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_libc_symbols.h @@ -12,7 +12,7 @@ #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_LIBC_SYMBOLS_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_LIBC_SYMBOLS_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include "partition_alloc/build_config.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_linker_wrapped_symbols.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_linker_wrapped_symbols.h index 3157d53bfd..c596d874bc 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_linker_wrapped_symbols.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_linker_wrapped_symbols.h @@ -15,7 +15,7 @@ // -wrap linker flags (e.g., libchrome.so) will be rewritten to the // linker as references to __wrap_malloc, __wrap_free, which are defined here. -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_ucrt_symbols_win.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_ucrt_symbols_win.h index e46d9af1ab..1e44a76eba 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_ucrt_symbols_win.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_ucrt_symbols_win.h @@ -12,7 +12,7 @@ #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_UCRT_SYMBOLS_WIN_H_ #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_UCRT_SYMBOLS_WIN_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include "partition_alloc/partition_alloc_base/component_export.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_win_component.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_win_component.cc index 31ba4759ee..f60e2b7e36 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_win_component.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_win_component.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/shim/allocator_dispatch.h" #include "partition_alloc/shim/winheap_stubs_win.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_win_static.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_win_static.cc index 54019d768f..dc1061e4b4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_win_static.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_win_static.cc @@ -3,9 +3,9 @@ // found in the LICENSE file. #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/numerics/checked_math.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/shim/allocator_shim.h" #include "partition_alloc/shim/checked_multiply_win.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple.h index 6180662591..1eeb3b7d2c 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/malloc_zone_functions_apple.h @@ -5,7 +5,7 @@ #ifndef PARTITION_ALLOC_SHIM_MALLOC_ZONE_FUNCTIONS_APPLE_H_ #define PARTITION_ALLOC_SHIM_MALLOC_ZONE_FUNCTIONS_APPLE_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.cc deleted file mode 100644 index a2b96a4370..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "partition_alloc/shim/nonscannable_allocator.h" - -#include "partition_alloc/partition_root.h" - -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -#include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h" - -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/internal_allocator.h" -#include "partition_alloc/starscan/pcscan.h" -#endif -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - -namespace allocator_shim::internal { - -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -template -NonScannableAllocatorImpl::NonScannableAllocatorImpl() = default; -template -NonScannableAllocatorImpl::~NonScannableAllocatorImpl() = - default; - -template -NonScannableAllocatorImpl& -NonScannableAllocatorImpl::Instance() { - static partition_alloc::internal::base::NoDestructor< - NonScannableAllocatorImpl> - instance; - return *instance; -} - -template -void* NonScannableAllocatorImpl::Alloc(size_t size) { -#if PA_BUILDFLAG(USE_STARSCAN) - // TODO(bikineev): Change to LIKELY once PCScan is enabled by default. - if (PA_UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) { - PA_DCHECK(allocator_.get()); - return allocator_->root() - ->AllocInline(size); - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - // Otherwise, dispatch to default partition. - return allocator_shim::internal::PartitionAllocMalloc::Allocator() - ->AllocInline(size); -} - -template -void NonScannableAllocatorImpl::Free(void* ptr) { -#if PA_BUILDFLAG(USE_STARSCAN) - if (PA_UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) { - allocator_->root()->FreeInline(ptr); - return; - } -#endif // PA_BUILDFLAG(USE_STARSCAN) - partition_alloc::PartitionRoot::FreeInlineInUnknownRoot< - partition_alloc::FreeFlags::kNoHooks>(ptr); -} - -template -void NonScannableAllocatorImpl::NotifyPCScanEnabled() { -#if PA_BUILDFLAG(USE_STARSCAN) - partition_alloc::PartitionOptions opts; - opts.star_scan_quarantine = - quarantinable ? partition_alloc::PartitionOptions::kAllowed - : partition_alloc::PartitionOptions::kDisallowed; - opts.backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled; - allocator_.reset(partition_alloc::internal::ConstructAtInternalPartition< - partition_alloc::PartitionAllocator>(opts)); - if constexpr (quarantinable) { - partition_alloc::internal::PCScan::RegisterNonScannableRoot( - allocator_->root()); - } - pcscan_enabled_.store(true, std::memory_order_release); -#endif // PA_BUILDFLAG(USE_STARSCAN) -} - -template class PA_EXPORT_TEMPLATE_DEFINE(PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)) - NonScannableAllocatorImpl; -template class PA_EXPORT_TEMPLATE_DEFINE(PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)) - NonScannableAllocatorImpl; - -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - -} // namespace allocator_shim::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.h deleted file mode 100644 index b976a7f34e..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_SHIM_NONSCANNABLE_ALLOCATOR_H_ -#define PARTITION_ALLOC_SHIM_NONSCANNABLE_ALLOCATOR_H_ - -#include -#include -#include - -#include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/export_template.h" -#include "partition_alloc/partition_alloc_base/no_destructor.h" -#include "partition_alloc/partition_alloc_buildflags.h" - -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -#include "partition_alloc/partition_alloc.h" - -#if PA_BUILDFLAG(USE_STARSCAN) -#include "partition_alloc/internal_allocator_forward.h" -#endif -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - -namespace allocator_shim { - -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -namespace internal { - -// Represents allocator that contains memory for data-like objects (that don't -// contain pointers/references) and therefore doesn't require scanning by -// PCScan. An example would be strings or socket/IPC/file buffers. Use with -// caution. -template -class NonScannableAllocatorImpl final { - public: - static NonScannableAllocatorImpl& Instance(); - - NonScannableAllocatorImpl(const NonScannableAllocatorImpl&) = delete; - NonScannableAllocatorImpl& operator=(const NonScannableAllocatorImpl&) = - delete; - - void* Alloc(size_t size); - void Free(void*); - - // Returns PartitionRoot corresponding to the allocator, or nullptr if the - // allocator is not enabled. - partition_alloc::PartitionRoot* root() { -#if PA_BUILDFLAG(USE_STARSCAN) - if (!allocator_.get()) { - return nullptr; - } - return allocator_->root(); -#else - return nullptr; -#endif // PA_BUILDFLAG(USE_STARSCAN) - } - - void NotifyPCScanEnabled(); - - private: - template - friend class partition_alloc::internal::base::NoDestructor; - - NonScannableAllocatorImpl(); - ~NonScannableAllocatorImpl(); - -#if PA_BUILDFLAG(USE_STARSCAN) - std::unique_ptr - allocator_; - std::atomic_bool pcscan_enabled_{false}; -#endif // PA_BUILDFLAG(USE_STARSCAN) -}; - -extern template class PA_EXPORT_TEMPLATE_DECLARE( - PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)) NonScannableAllocatorImpl; -extern template class PA_EXPORT_TEMPLATE_DECLARE( - PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)) NonScannableAllocatorImpl; - -} // namespace internal - -using NonScannableAllocator = internal::NonScannableAllocatorImpl; -using NonQuarantinableAllocator = internal::NonScannableAllocatorImpl; - -#endif // PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - -} // namespace allocator_shim - -#endif // PARTITION_ALLOC_SHIM_NONSCANNABLE_ALLOCATOR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/shim_alloc_functions.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/shim_alloc_functions.h index 9e66c4df64..0fd970ed04 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/shim_alloc_functions.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/shim_alloc_functions.h @@ -9,14 +9,13 @@ #ifndef PARTITION_ALLOC_SHIM_SHIM_ALLOC_FUNCTIONS_H_ #define PARTITION_ALLOC_SHIM_SHIM_ALLOC_FUNCTIONS_H_ -#include #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/bits.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/memory/page_size.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" namespace { @@ -60,7 +59,7 @@ PA_ALWAYS_INLINE void* ShimCppNew(size_t size) { context = malloc_default_zone(); #endif ptr = chain_head->alloc_function(chain_head, size, context); - } while (!ptr && allocator_shim::internal::CallNewHandler(size)); + } while (PA_UNLIKELY(!ptr && allocator_shim::internal::CallNewHandler(size))); return ptr; } @@ -85,7 +84,7 @@ PA_ALWAYS_INLINE void* ShimCppAlignedNew(size_t size, size_t alignment) { #endif ptr = chain_head->alloc_aligned_function(chain_head, alignment, size, context); - } while (!ptr && allocator_shim::internal::CallNewHandler(size)); + } while (PA_UNLIKELY(!ptr && allocator_shim::internal::CallNewHandler(size))); return ptr; } @@ -105,9 +104,9 @@ PA_ALWAYS_INLINE void* ShimMalloc(size_t size, void* context) { void* ptr; do { ptr = chain_head->alloc_function(chain_head, size, context); - } while (!ptr && - allocator_shim::internal::g_call_new_handler_on_malloc_failure && - allocator_shim::internal::CallNewHandler(size)); + } while (PA_UNLIKELY( + !ptr && allocator_shim::internal::g_call_new_handler_on_malloc_failure && + allocator_shim::internal::CallNewHandler(size))); return ptr; } @@ -118,9 +117,9 @@ PA_ALWAYS_INLINE void* ShimCalloc(size_t n, size_t size, void* context) { do { ptr = chain_head->alloc_zero_initialized_function(chain_head, n, size, context); - } while (!ptr && - allocator_shim::internal::g_call_new_handler_on_malloc_failure && - allocator_shim::internal::CallNewHandler(size)); + } while (PA_UNLIKELY( + !ptr && allocator_shim::internal::g_call_new_handler_on_malloc_failure && + allocator_shim::internal::CallNewHandler(size))); return ptr; } @@ -132,9 +131,10 @@ PA_ALWAYS_INLINE void* ShimRealloc(void* address, size_t size, void* context) { void* ptr; do { ptr = chain_head->realloc_function(chain_head, address, size, context); - } while (!ptr && size && - allocator_shim::internal::g_call_new_handler_on_malloc_failure && - allocator_shim::internal::CallNewHandler(size)); + } while (PA_UNLIKELY( + !ptr && size && + allocator_shim::internal::g_call_new_handler_on_malloc_failure && + allocator_shim::internal::CallNewHandler(size))); return ptr; } @@ -147,9 +147,9 @@ PA_ALWAYS_INLINE void* ShimMemalign(size_t alignment, do { ptr = chain_head->alloc_aligned_function(chain_head, alignment, size, context); - } while (!ptr && - allocator_shim::internal::g_call_new_handler_on_malloc_failure && - allocator_shim::internal::CallNewHandler(size)); + } while (PA_UNLIKELY( + !ptr && allocator_shim::internal::g_call_new_handler_on_malloc_failure && + allocator_shim::internal::CallNewHandler(size))); return ptr; } @@ -158,7 +158,8 @@ PA_ALWAYS_INLINE int ShimPosixMemalign(void** res, size_t size) { // posix_memalign is supposed to check the arguments. See tc_posix_memalign() // in tc_malloc.cc. - if (((alignment % sizeof(void*)) != 0) || !std::has_single_bit(alignment)) { + if (((alignment % sizeof(void*)) != 0) || + !partition_alloc::internal::base::bits::HasSingleBit(alignment)) { return EINVAL; } void* ptr = ShimMemalign(alignment, size, nullptr); @@ -252,9 +253,9 @@ PA_ALWAYS_INLINE void* ShimAlignedMalloc(size_t size, do { ptr = chain_head->aligned_malloc_function(chain_head, size, alignment, context); - } while (!ptr && - allocator_shim::internal::g_call_new_handler_on_malloc_failure && - allocator_shim::internal::CallNewHandler(size)); + } while (PA_UNLIKELY( + !ptr && allocator_shim::internal::g_call_new_handler_on_malloc_failure && + allocator_shim::internal::CallNewHandler(size))); return ptr; } @@ -270,9 +271,10 @@ PA_ALWAYS_INLINE void* ShimAlignedRealloc(void* address, do { ptr = chain_head->aligned_realloc_function(chain_head, address, size, alignment, context); - } while (!ptr && size && - allocator_shim::internal::g_call_new_handler_on_malloc_failure && - allocator_shim::internal::CallNewHandler(size)); + } while (PA_UNLIKELY( + !ptr && size && + allocator_shim::internal::g_call_new_handler_on_malloc_failure && + allocator_shim::internal::CallNewHandler(size))); return ptr; } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win.cc index 931ec65f6d..de5116fb7f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win.cc @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -104,12 +103,12 @@ struct AlignedPrefix { static_assert( kMaxWindowsAllocation < std::numeric_limits::max(), "original_allocation_offset must be able to fit into an unsigned int"); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Magic value used to check that _aligned_free() and _aligned_realloc() are // only ever called on an aligned allocated chunk. static constexpr unsigned int kMagic = 0x12003400; unsigned int magic; -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) }; // Compute how large an allocation we need to fit an allocation with the given @@ -134,18 +133,18 @@ void* AlignAllocation(void* ptr, size_t alignment) { prefix->original_allocation_offset = partition_alloc::internal::base::checked_cast( address - reinterpret_cast(ptr)); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) prefix->magic = AlignedPrefix::kMagic; -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) return reinterpret_cast(address); } // Return the original allocation from an aligned allocation. void* UnalignAllocation(void* ptr) { AlignedPrefix* prefix = reinterpret_cast(ptr) - 1; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) PA_DCHECK(prefix->magic == AlignedPrefix::kMagic); -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) void* unaligned = static_cast(ptr) - prefix->original_allocation_offset; PA_CHECK(unaligned < ptr); @@ -158,7 +157,7 @@ void* UnalignAllocation(void* ptr) { } // namespace void* WinHeapAlignedMalloc(size_t size, size_t alignment) { - PA_CHECK(std::has_single_bit(alignment)); + PA_CHECK(partition_alloc::internal::base::bits::HasSingleBit(alignment)); size_t adjusted = AdjustedSize(size, alignment); if (adjusted >= kMaxWindowsAllocation) { @@ -174,7 +173,7 @@ void* WinHeapAlignedMalloc(size_t size, size_t alignment) { } void* WinHeapAlignedRealloc(void* ptr, size_t size, size_t alignment) { - PA_CHECK(std::has_single_bit(alignment)); + PA_CHECK(partition_alloc::internal::base::bits::HasSingleBit(alignment)); if (!ptr) { return WinHeapAlignedMalloc(size, alignment); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win.h index be8fd29c4f..61055584cf 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/winheap_stubs_win.h @@ -11,7 +11,7 @@ #include -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include "partition_alloc/partition_alloc_base/component_export.h" diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.cc index 723cf24333..4af4fdd2f0 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.cc @@ -24,21 +24,20 @@ #include #endif // PA_CONFIG(HAS_LINUX_KERNEL) -#if !PA_CONFIG(HAS_FAST_MUTEX) +#if !PA_CONFIG(HAS_LINUX_KERNEL) && !PA_BUILDFLAG(IS_WIN) && \ + !PA_BUILDFLAG(IS_APPLE) && !PA_BUILDFLAG(IS_POSIX) && \ + !PA_BUILDFLAG(IS_FUCHSIA) #include "partition_alloc/partition_alloc_base/threading/platform_thread.h" #if PA_BUILDFLAG(IS_POSIX) #include - #define PA_YIELD_THREAD sched_yield() - #else // Other OS - #warning "Thread yield not supported on this OS." #define PA_YIELD_THREAD ((void)0) #endif -#endif // !PA_CONFIG(HAS_FAST_MUTEX) +#endif namespace partition_alloc::internal { @@ -83,8 +82,6 @@ void SpinningMutex::AcquireSpinThenBlock() { LockSlow(); } -#if PA_CONFIG(HAS_FAST_MUTEX) - #if PA_CONFIG(HAS_LINUX_KERNEL) void SpinningMutex::FutexWait() { @@ -162,11 +159,9 @@ void SpinningMutex::LockSlow() { sync_mutex_lock(&lock_); } -#endif +#else -#else // PA_CONFIG(HAS_FAST_MUTEX) - -void SpinningMutex::LockSlowSpinLock() { +void SpinningMutex::LockSlow() { int yield_thread_count = 0; do { if (yield_thread_count < 10) { @@ -179,9 +174,9 @@ void SpinningMutex::LockSlowSpinLock() { // progress. base::PlatformThread::Sleep(base::Milliseconds(1)); } - } while (!TrySpinLock()); + } while (!Try()); } -#endif // PA_CONFIG(HAS_FAST_MUTEX) +#endif } // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.h index f7e0e0a23f..6453ce5803 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/spinning_mutex.h @@ -36,8 +36,8 @@ namespace partition_alloc::internal { -// The behavior of this class depends on whether PA_HAS_FAST_MUTEX is defined. -// 1. When it is defined: +// The behavior of this class depends on platform support: +// 1. When platform supports is available: // // Simple spinning lock. It will spin in user space a set number of times before // going into the kernel to sleep. @@ -51,18 +51,22 @@ namespace partition_alloc::internal { // // We don't rely on base::Lock which we could make spin (by calling Try() in a // loop), as performance is below a custom spinlock as seen on high-level -// benchmarks. Instead this implements a simple non-recursive mutex on top of -// the futex() syscall on Linux, SRWLock on Windows, os_unfair_lock on macOS, -// and pthread_mutex on POSIX. The main difference between this and a libc -// implementation is that it only supports the simplest path: private (to a -// process), non-recursive mutexes with no priority inheritance, no timed waits. +// benchmarks. Instead this implements a simple non-recursive mutex on top of: +// - Linux : futex() +// - Windows : SRWLock +// - MacOS : os_unfair_lock +// - POSIX : pthread_mutex_trylock() +// +// The main difference between this and a libc implementation is that it only +// supports the simplest path: private (to a process), non-recursive mutexes +// with no priority inheritance, no timed waits. // // As an interesting side-effect to be used in the allocator, this code does not // make any allocations, locks are small with a constexpr constructor and no // destructor. // // 2. Otherwise: This is a simple SpinLock, in the sense that it does not have -// any awareness of other threads' behavior. +// any awareness of other threads' behavior. class PA_LOCKABLE PA_COMPONENT_EXPORT(PARTITION_ALLOC) SpinningMutex { public: inline constexpr SpinningMutex(); @@ -74,11 +78,7 @@ class PA_LOCKABLE PA_COMPONENT_EXPORT(PARTITION_ALLOC) SpinningMutex { private: PA_NOINLINE void AcquireSpinThenBlock() PA_EXCLUSIVE_LOCK_FUNCTION(); -#if PA_CONFIG(HAS_FAST_MUTEX) void LockSlow() PA_EXCLUSIVE_LOCK_FUNCTION(); -#else - PA_ALWAYS_INLINE void LockSlow() PA_EXCLUSIVE_LOCK_FUNCTION(); -#endif // See below, the latency of PA_YIELD_PROCESSOR can be as high as ~150 // cycles. Meanwhile, sleeping costs a few us. Spinning 64 times at 3GHz would @@ -88,8 +88,6 @@ class PA_LOCKABLE PA_COMPONENT_EXPORT(PARTITION_ALLOC) SpinningMutex { // more. static constexpr int kSpinCount = 64; -#if PA_CONFIG(HAS_FAST_MUTEX) - #if PA_CONFIG(HAS_LINUX_KERNEL) void FutexWait(); void FutexWake(); @@ -107,16 +105,9 @@ class PA_LOCKABLE PA_COMPONENT_EXPORT(PARTITION_ALLOC) SpinningMutex { pthread_mutex_t lock_ = PTHREAD_MUTEX_INITIALIZER; #elif PA_BUILDFLAG(IS_FUCHSIA) sync_mutex lock_; -#endif - -#else // PA_CONFIG(HAS_FAST_MUTEX) +#else std::atomic lock_{false}; - - // Spinlock-like, fallback. - PA_ALWAYS_INLINE bool TrySpinLock(); - PA_ALWAYS_INLINE void ReleaseSpinLock(); - void LockSlowSpinLock(); -#endif // PA_CONFIG(HAS_FAST_MUTEX) +#endif }; PA_ALWAYS_INLINE void SpinningMutex::Acquire() { @@ -133,8 +124,6 @@ PA_ALWAYS_INLINE void SpinningMutex::Acquire() { inline constexpr SpinningMutex::SpinningMutex() = default; -#if PA_CONFIG(HAS_FAST_MUTEX) - #if PA_CONFIG(HAS_LINUX_KERNEL) PA_ALWAYS_INLINE bool SpinningMutex::Try() { @@ -215,9 +204,7 @@ PA_ALWAYS_INLINE void SpinningMutex::Release() { sync_mutex_unlock(&lock_); } -#endif - -#else // PA_CONFIG(HAS_FAST_MUTEX) +#else PA_ALWAYS_INLINE bool SpinningMutex::Try() { // Possibly faster than CAS. The theory is that if the cacheline is shared, @@ -230,11 +217,7 @@ PA_ALWAYS_INLINE void SpinningMutex::Release() { lock_.store(false, std::memory_order_release); } -PA_ALWAYS_INLINE void SpinningMutex::LockSlow() { - return LockSlowSpinLock(); -} - -#endif // PA_CONFIG(HAS_FAST_MUTEX) +#endif } // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/stack.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/stack.cc index 0422f33410..f85442c9cf 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/stack.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/stack/stack.cc @@ -8,8 +8,8 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #if PA_BUILDFLAG(IS_WIN) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/OWNERS b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/OWNERS deleted file mode 100644 index 228f0c3184..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -bikineev@chromium.org -mlippautz@chromium.org diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/README.md b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/README.md deleted file mode 100644 index 059b76007b..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# StarScan: Heap scanning use-after-free prevention - -C++ and other languages that rely on explicit memory management using `malloc()` -and `free()` are prone to memory corruptions and the resulting security issues. -The fundamental idea behind these heap scanning algorithms is to intercept an -underlying allocator and delay releasing of memory until the corresponding -memory block is provably unreachable from application code. - -The basic ingredients for such algorithms are: -1. *Quarantine*: When an object is deemed unused with a `free()` call, it is - put into quarantine instead of being returned to the allocator. The object - is not actually freed by the underlying allocator and cannot be used for - future allocation requests until it is found that no pointers are pointing - to the given memory block. -2. *Scan*: When the quarantine reaches a certain quarantine limit (e.g. based - on memory size of quarantine list entries), the quarantine scan is - triggered. The scan iterates over the application memory and checks if - references are pointing to quarantined memory. If objects in the quarantine - are still referenced then they are kept in quarantine, if not they are - flagged to be released. -3. *Sweep*: All objects that are flagged to be released are actually returned - to the underlying memory allocator. - -[Heap scanning algorithms](http://bit.ly/conservative-heap-scan) come in -different flavors that offer different performance and security characteristics. - -*Probabilistic conservative scan (PCScan)* (`pcscan.{h,cc}`) is one particular -kind of heap scanning algorithm implemented on top of -[PartitionAlloc](../PartitionAlloc.md) with the following properties: - -* Memory blocks are scanned conservatively for pointers. -* Scanning and sweeping are generally performed on a separate thread to - maximize application performance. -* Lazy safe points prohibit certain operations from modifying the memory graph - and provide convenient entry points for scanning the stack. - -PCScan is currently considered **experimental** - please do not use it in -production code just yet. It can be enabled in the following configurations via -`--enable-features` on builds that use PartitionAlloc as the -[main allocator](../../README.md): - -* `PartitionAllocPCScan`: All processes and all supporting partitions enable - PCScan. -* `PartitionAllocPCScanBrowserOnly`: Enables PCScan in the browser process - for the default malloc partition. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/logging.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/logging.h deleted file mode 100644 index c81eff9111..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/logging.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_LOGGING_H_ -#define PARTITION_ALLOC_STARSCAN_LOGGING_H_ - -#include "partition_alloc/allocation_guard.h" -#include "partition_alloc/partition_alloc_base/logging.h" - -namespace partition_alloc::internal { - -// Logging requires allocations. This logger allows reentrant allocations to -// happen within the allocator context. -struct LoggerWithAllowedAllocations : ScopedAllowAllocations, - logging::LogMessage { - using logging::LogMessage::LogMessage; -}; - -#define PA_PCSCAN_VLOG_STREAM(verbose_level) \ - ::partition_alloc::internal::LoggerWithAllowedAllocations( \ - __FILE__, __LINE__, -(verbose_level)) \ - .stream() - -// Logging macro that is meant to be used inside *Scan. Generally, reentrancy -// may be an issue if the macro is called from malloc()/free(). Currently, it's -// only called at the end of *Scan and when scheduling a new *Scan task. -// Allocating from these paths should not be an issue, since we make sure that -// no infinite recursion can occur (e.g. we can't schedule two *Scan tasks and -// the inner free() call must be non-reentrant). However, these sorts of things -// are tricky to enforce and easy to mess up with. Since verbose *Scan logging -// is essential for debugging, we choose to provide support for it inside *Scan. -#define PA_PCSCAN_VLOG(verbose_level) \ - PA_LAZY_STREAM(PA_PCSCAN_VLOG_STREAM(verbose_level), \ - PA_VLOG_IS_ON(verbose_level)) - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_LOGGING_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan.cc deleted file mode 100644 index db33463bfc..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "partition_alloc/starscan/pcscan.h" - -#include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/starscan/pcscan_internal.h" - -namespace partition_alloc::internal { - -void PCScan::Initialize(InitConfig config) { - PCScanInternal::Instance().Initialize(config); -} - -bool PCScan::IsInitialized() { - return PCScanInternal::Instance().is_initialized(); -} - -void PCScan::Disable() { - auto& instance = PCScan::Instance(); - instance.scheduler().scheduling_backend().DisableScheduling(); -} - -bool PCScan::IsEnabled() { - auto& instance = PCScan::Instance(); - return instance.scheduler().scheduling_backend().is_scheduling_enabled(); -} - -void PCScan::Reenable() { - auto& instance = PCScan::Instance(); - instance.scheduler().scheduling_backend().EnableScheduling(); -} - -void PCScan::RegisterScannableRoot(Root* root) { - PCScanInternal::Instance().RegisterScannableRoot(root); -} - -void PCScan::RegisterNonScannableRoot(Root* root) { - PCScanInternal::Instance().RegisterNonScannableRoot(root); -} - -void PCScan::RegisterNewSuperPage(Root* root, uintptr_t super_page_base) { - PCScanInternal::Instance().RegisterNewSuperPage(root, super_page_base); -} - -void PCScan::PerformScan(InvocationMode invocation_mode) { - PCScanInternal::Instance().PerformScan(invocation_mode); -} - -void PCScan::PerformScanIfNeeded(InvocationMode invocation_mode) { - PCScanInternal::Instance().PerformScanIfNeeded(invocation_mode); -} - -void PCScan::PerformDelayedScan(int64_t delay_in_microseconds) { - PCScanInternal::Instance().PerformDelayedScan( - base::Microseconds(delay_in_microseconds)); -} - -void PCScan::JoinScan() { - PCScanInternal::Instance().JoinScan(); -} - -void PCScan::SetProcessName(const char* process_name) { - PCScanInternal::Instance().SetProcessName(process_name); -} - -void PCScan::EnableStackScanning() { - PCScanInternal::Instance().EnableStackScanning(); -} -void PCScan::DisableStackScanning() { - PCScanInternal::Instance().DisableStackScanning(); -} -bool PCScan::IsStackScanningEnabled() { - return PCScanInternal::Instance().IsStackScanningEnabled(); -} - -void PCScan::EnableImmediateFreeing() { - PCScanInternal::Instance().EnableImmediateFreeing(); -} - -void PCScan::SetClearType(ClearType clear_type) { - PCScan& instance = Instance(); - instance.clear_type_ = clear_type; -} - -void PCScan::UninitForTesting() { - PCScanInternal::Instance().ClearRootsForTesting(); // IN-TEST -} - -void PCScan::ReinitForTesting(InitConfig config) { - PCScanInternal::Instance().ReinitForTesting(config); // IN-TEST -} - -void PCScan::FinishScanForTesting() { - PCScanInternal::Instance().FinishScanForTesting(); // IN-TEST -} - -void PCScan::RegisterStatsReporter(partition_alloc::StatsReporter* reporter) { - PCScanInternal::Instance().RegisterStatsReporter(reporter); -} - -PCScan PCScan::instance_ PA_CONSTINIT; - -} // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan.h deleted file mode 100644 index 471379b818..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan.h +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_PCSCAN_H_ -#define PARTITION_ALLOC_STARSCAN_PCSCAN_H_ - -#include - -#include "partition_alloc/page_allocator.h" -#include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/no_destructor.h" -#include "partition_alloc/partition_alloc_config.h" -#include "partition_alloc/partition_alloc_forward.h" -#include "partition_alloc/partition_direct_map_extent.h" -#include "partition_alloc/partition_page.h" -#include "partition_alloc/starscan/pcscan_scheduling.h" -#include "partition_alloc/tagging.h" - -namespace partition_alloc { - -class StatsReporter; - -namespace internal { - -[[noreturn]] PA_NOINLINE PA_NOT_TAIL_CALLED - PA_COMPONENT_EXPORT(PARTITION_ALLOC) void DoubleFreeAttempt(); - -// PCScan (Probabilistic Conservative Scanning) is the algorithm that eliminates -// use-after-free bugs by verifying that there are no pointers in memory which -// point to explicitly freed objects before actually releasing their memory. If -// PCScan is enabled for a partition, freed objects are not immediately returned -// to the allocator, but are stored in a quarantine. When the quarantine reaches -// a certain threshold, a concurrent PCScan task gets posted. The task scans the -// entire heap, looking for dangling pointers (those that point to the -// quarantine entries). After scanning, the unvisited quarantine entries are -// unreachable and therefore can be safely reclaimed. -// -// The driver class encapsulates the entire PCScan infrastructure. -class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PCScan final { - public: - using Root = PartitionRoot; - using SlotSpan = SlotSpanMetadata; - - enum class InvocationMode { - kBlocking, - kNonBlocking, - kForcedBlocking, - kScheduleOnlyForTesting, - }; - - enum class ClearType : uint8_t { - // Clear in the scanning task. - kLazy, - // Eagerly clear quarantined objects on MoveToQuarantine(). - kEager, - }; - - // Parameters used to initialize *Scan. - struct InitConfig { - // Based on the provided mode, PCScan will try to use a certain - // WriteProtector, if supported by the system. - enum class WantedWriteProtectionMode : uint8_t { - kDisabled, - kEnabled, - } write_protection = WantedWriteProtectionMode::kDisabled; - - // Flag that enables safepoints that stop mutator execution and help - // scanning. - enum class SafepointMode : uint8_t { - kDisabled, - kEnabled, - } safepoint = SafepointMode::kDisabled; - }; - - PCScan(const PCScan&) = delete; - PCScan& operator=(const PCScan&) = delete; - - // Initializes PCScan and prepares internal data structures. - static void Initialize(InitConfig); - static bool IsInitialized(); - - // Disable/reenable PCScan. Temporal disabling can be useful in CPU demanding - // contexts. - static void Disable(); - static void Reenable(); - // Query if PCScan is enabled. - static bool IsEnabled(); - - // Registers a root for scanning. - static void RegisterScannableRoot(Root* root); - // Registers a root that doesn't need to be scanned but still contains - // quarantined objects. - static void RegisterNonScannableRoot(Root* root); - - // Registers a newly allocated super page for |root|. - static void RegisterNewSuperPage(Root* root, uintptr_t super_page_base); - - PA_ALWAYS_INLINE static void MoveToQuarantine(void* object, - size_t usable_size, - uintptr_t slot_start, - size_t slot_size); - - // Performs scanning unconditionally. - static void PerformScan(InvocationMode invocation_mode); - // Performs scanning only if a certain quarantine threshold was reached. - static void PerformScanIfNeeded(InvocationMode invocation_mode); - // Performs scanning with specified delay. - static void PerformDelayedScan(int64_t delay_in_microseconds); - - // Enables safepoints in mutator threads. - PA_ALWAYS_INLINE static void EnableSafepoints(); - // Join scan from safepoint in mutator thread. As soon as PCScan is scheduled, - // mutators can join PCScan helping out with clearing and scanning. - PA_ALWAYS_INLINE static void JoinScanIfNeeded(); - - // Checks if there is a PCScan task currently in progress. - PA_ALWAYS_INLINE static bool IsInProgress(); - - // Sets process name (used for histograms). |name| must be a string literal. - static void SetProcessName(const char* name); - - static void EnableStackScanning(); - static void DisableStackScanning(); - static bool IsStackScanningEnabled(); - - static void EnableImmediateFreeing(); - - // Define when clearing should happen (on free() or in scanning task). - static void SetClearType(ClearType); - - static void UninitForTesting(); - - static inline PCScanScheduler& scheduler(); - - // Registers reporting class. - static void RegisterStatsReporter(partition_alloc::StatsReporter* reporter); - - private: - class PCScanThread; - friend class PCScanTask; - friend class PartitionAllocPCScanTestBase; - friend class PCScanInternal; - - enum class State : uint8_t { - // PCScan task is not scheduled. - kNotRunning, - // PCScan task is being started and about to be scheduled. - kScheduled, - // PCScan task is scheduled and can be scanning (or clearing). - kScanning, - // PCScan task is sweeping or finalizing. - kSweepingAndFinishing - }; - - PA_ALWAYS_INLINE static PCScan& Instance(); - - PA_ALWAYS_INLINE bool IsJoinable() const; - PA_ALWAYS_INLINE void SetJoinableIfSafepointEnabled(bool); - - inline constexpr PCScan(); - - // Joins scan unconditionally. - static void JoinScan(); - - // Finish scan as scanner thread. - static void FinishScanForTesting(); - - // Reinitialize internal structures (e.g. card table). - static void ReinitForTesting(InitConfig); - - size_t epoch() const { return scheduler_.epoch(); } - - // PA_CONSTINIT for fast access (avoiding static thread-safe initialization). - static PCScan instance_ PA_CONSTINIT; - - PCScanScheduler scheduler_{}; - std::atomic state_{State::kNotRunning}; - std::atomic is_joinable_{false}; - bool is_safepoint_enabled_{false}; - ClearType clear_type_{ClearType::kLazy}; -}; - -// To please Chromium's clang plugin. -constexpr PCScan::PCScan() = default; - -PA_ALWAYS_INLINE PCScan& PCScan::Instance() { - // The instance is declared as a static member, not static local. The reason - // is that we want to use the require_constant_initialization attribute to - // avoid double-checked-locking which would otherwise have been introduced - // by the compiler for thread-safe dynamic initialization (see constinit - // from C++20). - return instance_; -} - -PA_ALWAYS_INLINE bool PCScan::IsInProgress() { - const PCScan& instance = Instance(); - return instance.state_.load(std::memory_order_relaxed) != State::kNotRunning; -} - -PA_ALWAYS_INLINE bool PCScan::IsJoinable() const { - // This has acquire semantics since a mutator relies on the task being set up. - return is_joinable_.load(std::memory_order_acquire); -} - -PA_ALWAYS_INLINE void PCScan::SetJoinableIfSafepointEnabled(bool value) { - if (!is_safepoint_enabled_) { - PA_DCHECK(!is_joinable_.load(std::memory_order_relaxed)); - return; - } - // Release semantics is required to "publish" the change of the state so that - // the mutators can join scanning and expect the consistent state. - is_joinable_.store(value, std::memory_order_release); -} - -PA_ALWAYS_INLINE void PCScan::EnableSafepoints() { - PCScan& instance = Instance(); - instance.is_safepoint_enabled_ = true; -} - -PA_ALWAYS_INLINE void PCScan::JoinScanIfNeeded() { - PCScan& instance = Instance(); - if (PA_UNLIKELY(instance.IsJoinable())) { - instance.JoinScan(); - } -} - -PA_ALWAYS_INLINE void PCScan::MoveToQuarantine(void* object, - size_t usable_size, - uintptr_t slot_start, - size_t slot_size) { - PCScan& instance = Instance(); - if (instance.clear_type_ == ClearType::kEager) { - // We need to distinguish between usable_size and slot_size in this context: - // - for large buckets usable_size can be noticeably smaller than slot_size; - // - usable_size is safe as it doesn't cover extras as opposed to slot_size. - // TODO(bikineev): If we start protecting quarantine memory, we can lose - // double-free coverage (the check below). Consider performing the - // double-free check before protecting if eager clearing becomes default. - SecureMemset(object, 0, usable_size); - } - - auto* state_bitmap = StateBitmapFromAddr(slot_start); - - // Mark the state in the state bitmap as quarantined. Make sure to do it after - // the clearing to avoid racing with *Scan Sweeper. - [[maybe_unused]] const bool succeeded = - state_bitmap->Quarantine(slot_start, instance.epoch()); -#if PA_CONFIG(STARSCAN_EAGER_DOUBLE_FREE_DETECTION_ENABLED) - if (PA_UNLIKELY(!succeeded)) { - DoubleFreeAttempt(); - } -#else - // The compiler is able to optimize cmpxchg to a lock-prefixed and. -#endif // PA_CONFIG(STARSCAN_EAGER_DOUBLE_FREE_DETECTION_ENABLED) - - const bool is_limit_reached = instance.scheduler_.AccountFreed(slot_size); - if (PA_UNLIKELY(is_limit_reached)) { - // Perform a quick check if another scan is already in progress. - if (instance.IsInProgress()) { - return; - } - // Avoid blocking the current thread for regular scans. - instance.PerformScan(InvocationMode::kNonBlocking); - } -} - -inline PCScanScheduler& PCScan::scheduler() { - PCScan& instance = Instance(); - return instance.scheduler_; -} - -} // namespace internal -} // namespace partition_alloc - -#endif // PARTITION_ALLOC_STARSCAN_PCSCAN_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_internal.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_internal.cc deleted file mode 100644 index a7edebb06e..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_internal.cc +++ /dev/null @@ -1,1623 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "partition_alloc/starscan/pcscan_internal.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "partition_alloc/address_pool_manager.h" -#include "partition_alloc/allocation_guard.h" -#include "partition_alloc/build_config.h" -#include "partition_alloc/internal_allocator.h" -#include "partition_alloc/page_allocator.h" -#include "partition_alloc/page_allocator_constants.h" -#include "partition_alloc/partition_address_space.h" -#include "partition_alloc/partition_alloc.h" -#include "partition_alloc/partition_alloc_base/bits.h" -#include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/cpu.h" -#include "partition_alloc/partition_alloc_base/debug/alias.h" -#include "partition_alloc/partition_alloc_base/immediate_crash.h" -#include "partition_alloc/partition_alloc_base/memory/ref_counted.h" -#include "partition_alloc/partition_alloc_base/memory/scoped_refptr.h" -#include "partition_alloc/partition_alloc_base/no_destructor.h" -#include "partition_alloc/partition_alloc_base/threading/platform_thread.h" -#include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_alloc_buildflags.h" -#include "partition_alloc/partition_alloc_check.h" -#include "partition_alloc/partition_alloc_config.h" -#include "partition_alloc/partition_alloc_constants.h" -#include "partition_alloc/partition_freelist_entry.h" -#include "partition_alloc/partition_page.h" -#include "partition_alloc/reservation_offset_table.h" -#include "partition_alloc/stack/stack.h" -#include "partition_alloc/starscan/pcscan_scheduling.h" -#include "partition_alloc/starscan/raceful_worklist.h" -#include "partition_alloc/starscan/scan_loop.h" -#include "partition_alloc/starscan/snapshot.h" -#include "partition_alloc/starscan/stats_collector.h" -#include "partition_alloc/starscan/stats_reporter.h" -#include "partition_alloc/tagging.h" -#include "partition_alloc/thread_cache.h" - -#if !PA_BUILDFLAG(HAS_64_BIT_POINTERS) -#include "partition_alloc/address_pool_manager_bitmap.h" -#endif - -#if PA_CONFIG(STARSCAN_NOINLINE_SCAN_FUNCTIONS) -#define PA_SCAN_INLINE PA_NOINLINE -#else -#define PA_SCAN_INLINE PA_ALWAYS_INLINE -#endif - -namespace partition_alloc::internal { - -[[noreturn]] PA_NOINLINE PA_NOT_TAIL_CALLED void DoubleFreeAttempt() { - PA_NO_CODE_FOLDING(); - PA_IMMEDIATE_CRASH(); -} - -namespace { - -#if PA_CONFIG(HAS_ALLOCATION_GUARD) -// Currently, check reentracy only on Linux. On Android TLS is emulated by the -// runtime lib, which can allocate and therefore cause reentrancy. -struct ReentrantScannerGuard final { - public: - ReentrantScannerGuard() { - PA_CHECK(!guard_); - guard_ = true; - } - ~ReentrantScannerGuard() { guard_ = false; } - - private: - // Since this variable has hidden visibility (not referenced by other DSOs), - // assume that thread_local works on all supported architectures. - static thread_local size_t guard_; -}; -thread_local size_t ReentrantScannerGuard::guard_ = 0; -#else -struct [[maybe_unused]] ReentrantScannerGuard final {}; -#endif // PA_CONFIG(HAS_ALLOCATION_GUARD) - -// Scope that disables MTE checks. Only used inside scanning to avoid the race: -// a slot tag is changed by the mutator, while the scanner sees an old value. -struct DisableMTEScope final { - DisableMTEScope() { - ::partition_alloc::ChangeMemoryTaggingModeForCurrentThread( - ::partition_alloc::TagViolationReportingMode::kDisabled); - } - ~DisableMTEScope() { - ::partition_alloc::ChangeMemoryTaggingModeForCurrentThread( - parent_tagging_mode); - } - - private: - ::partition_alloc::TagViolationReportingMode parent_tagging_mode = - ::partition_alloc::internal::GetMemoryTaggingModeForCurrentThread(); -}; - -#if PA_CONFIG(STARSCAN_USE_CARD_TABLE) -// Bytemap that represent regions (cards) that contain quarantined slots. -// A single PCScan cycle consists of the following steps: -// 1) clearing (memset quarantine + marking cards that contain quarantine); -// 2) scanning; -// 3) sweeping (freeing + unmarking cards that contain freed slots). -// Marking cards on step 1) ensures that the card table stays in the consistent -// state while scanning. Unmarking on the step 3) ensures that unmarking -// actually happens (and we don't hit too many false positives). -// -// The code here relies on the fact that |address| is in the regular pool and -// that the card table (this object) is allocated at the very beginning of that -// pool. -class QuarantineCardTable final { - public: - // Avoid the load of the base of the regular pool. - PA_ALWAYS_INLINE static QuarantineCardTable& GetFrom(uintptr_t address) { - PA_SCAN_DCHECK(IsManagedByPartitionAllocRegularPool(address)); - return *reinterpret_cast( - address & PartitionAddressSpace::RegularPoolBaseMask()); - } - - PA_ALWAYS_INLINE void Quarantine(uintptr_t begin, size_t size) { - return SetImpl(begin, size, true); - } - - PA_ALWAYS_INLINE void Unquarantine(uintptr_t begin, size_t size) { - return SetImpl(begin, size, false); - } - - // Returns whether the card to which |address| points to contains quarantined - // slots. May return false positives for but should never return false - // negatives, as otherwise this breaks security. - PA_ALWAYS_INLINE bool IsQuarantined(uintptr_t address) const { - const size_t byte = Byte(address); - PA_SCAN_DCHECK(byte < bytes_.size()); - return bytes_[byte]; - } - - private: - static constexpr size_t kCardSize = kPoolMaxSize / kSuperPageSize; - static constexpr size_t kBytes = kPoolMaxSize / kCardSize; - - QuarantineCardTable() = default; - - PA_ALWAYS_INLINE static size_t Byte(uintptr_t address) { - return (address & ~PartitionAddressSpace::RegularPoolBaseMask()) / - kCardSize; - } - - PA_ALWAYS_INLINE void SetImpl(uintptr_t begin, size_t size, bool value) { - const size_t byte = Byte(begin); - const size_t need_bytes = (size + (kCardSize - 1)) / kCardSize; - PA_SCAN_DCHECK(bytes_.size() >= byte + need_bytes); - PA_SCAN_DCHECK(IsManagedByPartitionAllocRegularPool(begin)); - for (size_t i = byte; i < byte + need_bytes; ++i) { - bytes_[i] = value; - } - } - - std::array bytes_; -}; -static_assert(kSuperPageSize >= sizeof(QuarantineCardTable), - "Card table size must be less than kSuperPageSize, since this is " - "what is committed"); -#endif // PA_CONFIG(STARSCAN_USE_CARD_TABLE) - -template -using MetadataVector = std::vector>; -template -using MetadataSet = std::set, InternalAllocator>; -template -using MetadataHashMap = - std::unordered_map, - std::equal_to<>, - InternalAllocator>>; - -struct GetSlotStartResult final { - PA_ALWAYS_INLINE bool is_found() const { - PA_SCAN_DCHECK(!slot_start || slot_size); - return slot_start; - } - - uintptr_t slot_start = 0; - size_t slot_size = 0; -}; - -// Returns the start of a slot, or 0 if |maybe_inner_address| is not inside of -// an existing slot span. The function may return a non-0 address even inside a -// decommitted or free slot span, it's the caller responsibility to check if -// memory is actually allocated. -// -// |maybe_inner_address| must be within a normal-bucket super page and can also -// point to guard pages or slot-span metadata. -PA_SCAN_INLINE GetSlotStartResult -GetSlotStartInSuperPage(uintptr_t maybe_inner_address) { - PA_SCAN_DCHECK(IsManagedByNormalBuckets(maybe_inner_address)); - // Don't use SlotSpanMetadata/PartitionPage::FromAddr() and family, because - // they expect an address within a super page payload area, which we don't - // know yet if |maybe_inner_address| is. - const uintptr_t super_page = maybe_inner_address & kSuperPageBaseMask; - - const uintptr_t partition_page_index = - (maybe_inner_address & kSuperPageOffsetMask) >> PartitionPageShift(); - auto* page = - PartitionSuperPageToMetadataArea(super_page) + partition_page_index; - // Check if page is valid. The check also works for the guard pages and the - // metadata page. - if (!page->is_valid) { - return {}; - } - - page -= page->slot_span_metadata_offset; - PA_SCAN_DCHECK(page->is_valid); - PA_SCAN_DCHECK(!page->slot_span_metadata_offset); - auto* slot_span = &page->slot_span_metadata; - // Check if the slot span is actually used and valid. - if (!slot_span->bucket) { - return {}; - } -#if PA_SCAN_DCHECK_IS_ON() - DCheckIsValidSlotSpan(slot_span); -#endif - const uintptr_t slot_span_start = - SlotSpanMetadata::ToSlotSpanStart(slot_span); - const ptrdiff_t ptr_offset = maybe_inner_address - slot_span_start; - PA_SCAN_DCHECK(0 <= ptr_offset && - ptr_offset < static_cast( - slot_span->bucket->get_pages_per_slot_span() * - PartitionPageSize())); - // Slot span size in bytes is not necessarily multiple of partition page. - // Don't check if the pointer points outside of usable area, since checking - // the quarantine bit will anyway return false in this case. - const size_t slot_size = slot_span->bucket->slot_size; - const size_t slot_number = slot_span->bucket->GetSlotNumber(ptr_offset); - const uintptr_t slot_start = slot_span_start + (slot_number * slot_size); - PA_SCAN_DCHECK(slot_start <= maybe_inner_address && - maybe_inner_address < slot_start + slot_size); - return {.slot_start = slot_start, .slot_size = slot_size}; -} - -#if PA_SCAN_DCHECK_IS_ON() -bool IsQuarantineEmptyOnSuperPage(uintptr_t super_page) { - auto* bitmap = SuperPageStateBitmap(super_page); - size_t visited = 0; - bitmap->IterateQuarantined([&visited](auto) { ++visited; }); - return !visited; -} -#endif - -SimdSupport DetectSimdSupport() { -#if PA_CONFIG(STARSCAN_NEON_SUPPORTED) - return SimdSupport::kNEON; -#else - const base::CPU& cpu = base::CPU::GetInstanceNoAllocation(); - if (cpu.has_avx2()) { - return SimdSupport::kAVX2; - } - if (cpu.has_sse41()) { - return SimdSupport::kSSE41; - } - return SimdSupport::kUnvectorized; -#endif // PA_CONFIG(STARSCAN_NEON_SUPPORTED) -} - -void CommitCardTable() { -#if PA_CONFIG(STARSCAN_USE_CARD_TABLE) - RecommitSystemPages(PartitionAddressSpace::RegularPoolBase(), - sizeof(QuarantineCardTable), - PageAccessibilityConfiguration( - PageAccessibilityConfiguration::kReadWrite), - PageAccessibilityDisposition::kRequireUpdate); -#endif -} - -template -void IterateNonEmptySlotSpans(uintptr_t super_page, - size_t nonempty_slot_spans, - Function function) { - PA_SCAN_DCHECK(!(super_page % kSuperPageAlignment)); - PA_SCAN_DCHECK(nonempty_slot_spans); - - size_t slot_spans_to_visit = nonempty_slot_spans; -#if PA_SCAN_DCHECK_IS_ON() - size_t visited = 0; -#endif - - IterateSlotSpans(super_page, true /*with_quarantine*/, - [&function, &slot_spans_to_visit -#if PA_SCAN_DCHECK_IS_ON() - , - &visited -#endif - ](SlotSpanMetadata* slot_span) { - if (slot_span->is_empty() || slot_span->is_decommitted()) { - // Skip empty/decommitted slot spans. - return false; - } - function(slot_span); - --slot_spans_to_visit; -#if PA_SCAN_DCHECK_IS_ON() - // In debug builds, scan all the slot spans to check that - // number of visited slot spans is equal to the number of - // nonempty_slot_spans. - ++visited; - return false; -#else - return slot_spans_to_visit == 0; -#endif - }); -#if PA_SCAN_DCHECK_IS_ON() - // Check that exactly all non-empty slot spans have been visited. - PA_DCHECK(nonempty_slot_spans == visited); -#endif -} - -// SuperPageSnapshot is used to record all slot spans that contain live slots. -// The class avoids dynamic allocations and is designed to be instantiated on -// stack. To avoid stack overflow, internal data structures are kept packed. -class SuperPageSnapshot final { - // The following constants are used to define a conservative estimate for - // maximum number of slot spans in a super page. - // - // For systems with runtime-defined page size, assume partition page size is - // at least 16kiB. - static constexpr size_t kMinPartitionPageSize = - __builtin_constant_p(PartitionPageSize()) ? PartitionPageSize() : 1 << 14; - static constexpr size_t kStateBitmapMinReservedSize = - __builtin_constant_p(ReservedStateBitmapSize()) - ? ReservedStateBitmapSize() - : partition_alloc::internal::base::bits::AlignUp( - sizeof(AllocationStateMap), - kMinPartitionPageSize); - // Take into account guard partition page at the end of super-page. - static constexpr size_t kGuardPagesSize = 2 * kMinPartitionPageSize; - - static constexpr size_t kPayloadMaxSize = - kSuperPageSize - kStateBitmapMinReservedSize - kGuardPagesSize; - static_assert(kPayloadMaxSize % kMinPartitionPageSize == 0, - "kPayloadMaxSize must be multiple of kMinPartitionPageSize"); - - static constexpr size_t kMaxSlotSpansInSuperPage = - kPayloadMaxSize / kMinPartitionPageSize; - - public: - struct ScanArea { - // Use packed integer types to save stack space. In theory, kAlignment could - // be used instead of words, but it doesn't seem to bring savings. - uint32_t offset_within_page_in_words; - uint32_t size_in_words; - uint32_t slot_size_in_words; - }; - - class ScanAreas : private std::array { - using Base = std::array; - - public: - using iterator = Base::iterator; - using const_iterator = Base::const_iterator; - using Base::operator[]; - - iterator begin() { return Base::begin(); } - const_iterator begin() const { return Base::begin(); } - - iterator end() { return std::next(begin(), size_); } - const_iterator end() const { return std::next(begin(), size_); } - - void set_size(size_t new_size) { size_ = new_size; } - - private: - size_t size_; - }; - - static_assert(std::is_trivially_default_constructible_v, - "ScanAreas must be trivially default constructible to ensure " - "that no memsets are generated by the compiler as a " - "result of value-initialization (or zero-initialization)"); - - void* operator new(size_t) = delete; - void operator delete(void*) = delete; - - // Creates snapshot for a single super page. In theory, we could simply - // iterate over slot spans without taking a snapshot. However, we do this to - // minimize the mutex locking time. The mutex must be acquired to make sure - // that no mutator is concurrently changing any of the slot spans. - explicit SuperPageSnapshot(uintptr_t super_page_base); - - const ScanAreas& scan_areas() const { return scan_areas_; } - - private: - ScanAreas scan_areas_; -}; - -static_assert( - sizeof(SuperPageSnapshot) <= 2048, - "SuperPageSnapshot must stay relatively small to be allocated on stack"); - -SuperPageSnapshot::SuperPageSnapshot(uintptr_t super_page) { - auto* extent_entry = PartitionSuperPageToExtent(super_page); - - ::partition_alloc::internal::ScopedGuard lock( - ::partition_alloc::internal::PartitionRootLock(extent_entry->root)); - - const size_t nonempty_slot_spans = - extent_entry->number_of_nonempty_slot_spans; - if (!nonempty_slot_spans) { -#if PA_SCAN_DCHECK_IS_ON() - // Check that quarantine bitmap is empty for super-pages that contain - // only empty/decommitted slot-spans. - PA_CHECK(IsQuarantineEmptyOnSuperPage(super_page)); -#endif - scan_areas_.set_size(0); - return; - } - - size_t current = 0; - - IterateNonEmptySlotSpans( - super_page, nonempty_slot_spans, - [this, ¤t](SlotSpanMetadata* slot_span) { - const uintptr_t payload_begin = - SlotSpanMetadata::ToSlotSpanStart(slot_span); - // For single-slot slot-spans, scan only utilized slot part. - const size_t provisioned_size = - PA_UNLIKELY(slot_span->CanStoreRawSize()) - ? slot_span->GetRawSize() - : slot_span->GetProvisionedSize(); - // Free & decommitted slot spans are skipped. - PA_SCAN_DCHECK(provisioned_size > 0); - const uintptr_t payload_end = payload_begin + provisioned_size; - auto& area = scan_areas_[current]; - - const size_t offset_in_words = - (payload_begin & kSuperPageOffsetMask) / sizeof(uintptr_t); - const size_t size_in_words = - (payload_end - payload_begin) / sizeof(uintptr_t); - const size_t slot_size_in_words = - slot_span->bucket->slot_size / sizeof(uintptr_t); - -#if PA_SCAN_DCHECK_IS_ON() - PA_DCHECK(offset_in_words <= - std::numeric_limits< - decltype(area.offset_within_page_in_words)>::max()); - PA_DCHECK(size_in_words <= - std::numeric_limits::max()); - PA_DCHECK( - slot_size_in_words <= - std::numeric_limits::max()); -#endif - - area.offset_within_page_in_words = offset_in_words; - area.size_in_words = size_in_words; - area.slot_size_in_words = slot_size_in_words; - - ++current; - }); - - PA_SCAN_DCHECK(kMaxSlotSpansInSuperPage >= current); - scan_areas_.set_size(current); -} - -} // namespace - -class PCScanScanLoop; - -// This class is responsible for performing the entire PCScan task. -// TODO(bikineev): Move PCScan algorithm out of PCScanTask. -class PCScanTask final : public base::RefCountedThreadSafe, - public InternalPartitionAllocated { - public: - // Creates and initializes a PCScan state. - PCScanTask(PCScan& pcscan, size_t quarantine_last_size); - - PCScanTask(PCScanTask&&) noexcept = delete; - PCScanTask& operator=(PCScanTask&&) noexcept = delete; - - // Execute PCScan from mutator inside safepoint. - void RunFromMutator(); - - // Execute PCScan from the scanner thread. Must be called only once from the - // scanner thread. - void RunFromScanner(); - - PCScanScheduler& scheduler() const { return pcscan_.scheduler(); } - - private: - class StackVisitor; - friend class PCScanScanLoop; - - using Root = PCScan::Root; - using SlotSpan = SlotSpanMetadata; - - // This is used: - // - to synchronize all scanning threads (mutators and the scanner); - // - for the scanner, to transition through the state machine - // (kScheduled -> kScanning (ctor) -> kSweepingAndFinishing (dtor). - template - class SyncScope final { - public: - explicit SyncScope(PCScanTask& task) : task_(task) { - task_.number_of_scanning_threads_.fetch_add(1, std::memory_order_relaxed); - if (context == Context::kScanner) { - task_.pcscan_.state_.store(PCScan::State::kScanning, - std::memory_order_relaxed); - task_.pcscan_.SetJoinableIfSafepointEnabled(true); - } - } - ~SyncScope() { - // First, notify the scanning thread that this thread is done. - NotifyThreads(); - if (context == Context::kScanner) { - // The scanner thread must wait here until all safepoints leave. - // Otherwise, sweeping may free a page that can later be accessed by a - // descheduled mutator. - WaitForOtherThreads(); - task_.pcscan_.state_.store(PCScan::State::kSweepingAndFinishing, - std::memory_order_relaxed); - } - } - - private: - void NotifyThreads() { - { - // The lock is required as otherwise there is a race between - // fetch_sub/notify in the mutator and checking - // number_of_scanning_threads_/waiting in the scanner. - std::lock_guard lock(task_.mutex_); - task_.number_of_scanning_threads_.fetch_sub(1, - std::memory_order_relaxed); - { - // Notify that scan is done and there is no need to enter - // the safepoint. This also helps a mutator to avoid repeating - // entering. Since the scanner thread waits for all threads to finish, - // there is no ABA problem here. - task_.pcscan_.SetJoinableIfSafepointEnabled(false); - } - } - task_.condvar_.notify_all(); - } - - void WaitForOtherThreads() { - std::unique_lock lock(task_.mutex_); - task_.condvar_.wait(lock, [this] { - return !task_.number_of_scanning_threads_.load( - std::memory_order_relaxed); - }); - } - - PCScanTask& task_; - }; - - friend class base::RefCountedThreadSafe; - ~PCScanTask() = default; - - PA_SCAN_INLINE AllocationStateMap* TryFindScannerBitmapForPointer( - uintptr_t maybe_ptr) const; - - // Lookup and marking functions. Return size of the slot if marked, or zero - // otherwise. - PA_SCAN_INLINE size_t TryMarkSlotInNormalBuckets(uintptr_t maybe_ptr) const; - - // Scans stack, only called from safepoints. - void ScanStack(); - - // Scan individual areas. - void ScanNormalArea(PCScanInternal& pcscan, - PCScanScanLoop& scan_loop, - uintptr_t begin, - uintptr_t end); - void ScanLargeArea(PCScanInternal& pcscan, - PCScanScanLoop& scan_loop, - uintptr_t begin, - uintptr_t end, - size_t slot_size); - - // Scans all registered partitions and marks reachable quarantined slots. - void ScanPartitions(); - - // Clear quarantined slots and prepare card table for fast lookup - void ClearQuarantinedSlotsAndPrepareCardTable(); - - // Unprotect all slot spans from all partitions. - void UnprotectPartitions(); - - // Sweeps (frees) unreachable quarantined entries. - void SweepQuarantine(); - - // Finishes the scanner (updates limits, UMA, etc). - void FinishScanner(); - - // Cache the pcscan epoch to avoid the compiler loading the atomic - // QuarantineData::epoch_ on each access. - const size_t pcscan_epoch_; - std::unique_ptr snapshot_; - StatsCollector stats_; - // Mutex and codvar that are used to synchronize scanning threads. - std::mutex mutex_; - std::condition_variable condvar_; - std::atomic number_of_scanning_threads_{0u}; - // We can unprotect only once to reduce context-switches. - std::once_flag unprotect_once_flag_; - bool immediatelly_free_slots_{false}; - PCScan& pcscan_; -}; - -PA_SCAN_INLINE AllocationStateMap* PCScanTask::TryFindScannerBitmapForPointer( - uintptr_t maybe_ptr) const { - PA_SCAN_DCHECK(IsManagedByPartitionAllocRegularPool(maybe_ptr)); - // First, check if |maybe_ptr| points to a valid super page or a quarantined - // card. -#if PA_BUILDFLAG(HAS_64_BIT_POINTERS) -#if PA_CONFIG(STARSCAN_USE_CARD_TABLE) - // Check if |maybe_ptr| points to a quarantined card. - if (PA_LIKELY( - !QuarantineCardTable::GetFrom(maybe_ptr).IsQuarantined(maybe_ptr))) { - return nullptr; - } -#else // PA_CONFIG(STARSCAN_USE_CARD_TABLE) - // Without the card table, use the reservation offset table to check if - // |maybe_ptr| points to a valid super-page. It's not as precise (meaning that - // we may have hit the slow path more frequently), but reduces the memory - // overhead. Since we are certain here, that |maybe_ptr| refers to the - // regular pool, it's okay to use non-checking version of - // ReservationOffsetPointer(). - const uintptr_t offset = - maybe_ptr & ~PartitionAddressSpace::RegularPoolBaseMask(); - if (PA_LIKELY(*ReservationOffsetPointer(kRegularPoolHandle, offset) != - kOffsetTagNormalBuckets)) { - return nullptr; - } -#endif // PA_CONFIG(STARSCAN_USE_CARD_TABLE) -#else // PA_BUILDFLAG(HAS_64_BIT_POINTERS) - if (PA_LIKELY(!IsManagedByPartitionAllocRegularPool(maybe_ptr))) { - return nullptr; - } -#endif // PA_BUILDFLAG(HAS_64_BIT_POINTERS) - - // We are certain here that |maybe_ptr| points to an allocated super-page. - return StateBitmapFromAddr(maybe_ptr); -} - -// Looks up and marks a potential dangling pointer. Returns the size of the slot -// (which is then accounted as quarantined), or zero if no slot is found. -// For normal bucket super pages, PCScan uses two quarantine bitmaps, the -// mutator and the scanner one. The former is used by mutators when slots are -// freed, while the latter is used concurrently by the PCScan thread. The -// bitmaps are swapped as soon as PCScan is triggered. Once a dangling pointer -// (which points to a slot in the scanner bitmap) is found, -// TryMarkSlotInNormalBuckets() marks it again in the bitmap and clears -// from the scanner bitmap. This way, when scanning is done, all uncleared -// entries in the scanner bitmap correspond to unreachable slots. -PA_SCAN_INLINE size_t -PCScanTask::TryMarkSlotInNormalBuckets(uintptr_t maybe_ptr) const { - // Check if |maybe_ptr| points somewhere to the heap. - // The caller has to make sure that |maybe_ptr| isn't MTE-tagged. - auto* state_map = TryFindScannerBitmapForPointer(maybe_ptr); - if (!state_map) { - return 0; - } - - // Beyond this point, we know that |maybe_ptr| is a pointer within a - // normal-bucket super page. - PA_SCAN_DCHECK(IsManagedByNormalBuckets(maybe_ptr)); - -#if !PA_CONFIG(STARSCAN_USE_CARD_TABLE) - // Pointer from a normal bucket is always in the first superpage. - auto* root = Root::FromAddrInFirstSuperpage(maybe_ptr); - // Without the card table, we must make sure that |maybe_ptr| doesn't point to - // metadata partition. - // TODO(bikineev): To speed things up, consider removing the check and - // committing quarantine bitmaps for metadata partition. - // TODO(bikineev): Marking an entry in the reservation-table is not a - // publishing operation, meaning that the |root| pointer may not be assigned - // yet. This can happen as arbitrary pointers may point into a super-page - // during its set up. Make sure to check |root| is not null before - // dereferencing it. - if (PA_UNLIKELY(!root || !root->IsQuarantineEnabled())) { - return 0; - } -#endif // !PA_CONFIG(STARSCAN_USE_CARD_TABLE) - - // Check if pointer was in the quarantine bitmap. - const GetSlotStartResult slot_start_result = - GetSlotStartInSuperPage(maybe_ptr); - if (!slot_start_result.is_found()) { - return 0; - } - - const uintptr_t slot_start = slot_start_result.slot_start; - if (PA_LIKELY(!state_map->IsQuarantined(slot_start))) { - return 0; - } - - PA_SCAN_DCHECK((maybe_ptr & kSuperPageBaseMask) == - (slot_start & kSuperPageBaseMask)); - - if (PA_UNLIKELY(immediatelly_free_slots_)) { - return 0; - } - - // Now we are certain that |maybe_ptr| is a dangling pointer. Mark it again in - // the mutator bitmap and clear from the scanner bitmap. Note that since - // PCScan has exclusive access to the scanner bitmap, we can avoid atomic rmw - // operation for it. - if (PA_LIKELY( - state_map->MarkQuarantinedAsReachable(slot_start, pcscan_epoch_))) { - return slot_start_result.slot_size; - } - - return 0; -} - -void PCScanTask::ClearQuarantinedSlotsAndPrepareCardTable() { - const PCScan::ClearType clear_type = pcscan_.clear_type_; - -#if !PA_CONFIG(STARSCAN_USE_CARD_TABLE) - if (clear_type == PCScan::ClearType::kEager) { - return; - } -#endif - - StarScanSnapshot::ClearingView view(*snapshot_); - view.VisitConcurrently([clear_type](uintptr_t super_page) { - auto* bitmap = StateBitmapFromAddr(super_page); - auto* root = Root::FromFirstSuperPage(super_page); - bitmap->IterateQuarantined([root, clear_type](uintptr_t slot_start) { - auto* slot_span = SlotSpanMetadata::FromSlotStart(slot_start); - // Use zero as a zapping value to speed up the fast bailout check in - // ScanPartitions. - const size_t size = root->GetSlotUsableSize(slot_span); - if (clear_type == PCScan::ClearType::kLazy) { - void* object = root->SlotStartToObject(slot_start); - memset(object, 0, size); - } -#if PA_CONFIG(STARSCAN_USE_CARD_TABLE) - // Set card(s) for this quarantined slot. - QuarantineCardTable::GetFrom(slot_start).Quarantine(slot_start, size); -#endif - }); - }); -} - -void PCScanTask::UnprotectPartitions() { - auto& pcscan = PCScanInternal::Instance(); - if (!pcscan.WriteProtectionEnabled()) { - return; - } - - StarScanSnapshot::UnprotectingView unprotect_view(*snapshot_); - unprotect_view.VisitConcurrently([&pcscan](uintptr_t super_page) { - SuperPageSnapshot super_page_snapshot(super_page); - - for (const auto& scan_area : super_page_snapshot.scan_areas()) { - const uintptr_t begin = - super_page | - (scan_area.offset_within_page_in_words * sizeof(uintptr_t)); - const uintptr_t end = - begin + (scan_area.size_in_words * sizeof(uintptr_t)); - - pcscan.UnprotectPages(begin, end - begin); - } - }); -} - -class PCScanScanLoop final : public ScanLoop { - friend class ScanLoop; - - public: - explicit PCScanScanLoop(const PCScanTask& task) - : ScanLoop(PCScanInternal::Instance().simd_support()), task_(task) {} - - size_t quarantine_size() const { return quarantine_size_; } - - private: -#if PA_BUILDFLAG(HAS_64_BIT_POINTERS) - PA_ALWAYS_INLINE static uintptr_t RegularPoolBase() { - return PartitionAddressSpace::RegularPoolBase(); - } - PA_ALWAYS_INLINE static uintptr_t RegularPoolMask() { - return PartitionAddressSpace::RegularPoolBaseMask(); - } -#endif // PA_BUILDFLAG(HAS_64_BIT_POINTERS) - - PA_SCAN_INLINE void CheckPointer(uintptr_t maybe_ptr_maybe_tagged) { - // |maybe_ptr| may have an MTE tag, so remove it first. - quarantine_size_ += - task_.TryMarkSlotInNormalBuckets(UntagAddr(maybe_ptr_maybe_tagged)); - } - - const PCScanTask& task_; - DisableMTEScope disable_mte_; - size_t quarantine_size_ = 0; -}; - -class PCScanTask::StackVisitor final : public internal::StackVisitor { - public: - explicit StackVisitor(const PCScanTask& task) : task_(task) {} - - void VisitStack(uintptr_t* stack_ptr, uintptr_t* stack_top) override { - static constexpr size_t kMinimalAlignment = 32; - uintptr_t begin = - reinterpret_cast(stack_ptr) & ~(kMinimalAlignment - 1); - uintptr_t end = - (reinterpret_cast(stack_top) + kMinimalAlignment - 1) & - ~(kMinimalAlignment - 1); - PA_CHECK(begin < end); - PCScanScanLoop loop(task_); - loop.Run(begin, end); - quarantine_size_ += loop.quarantine_size(); - } - - // Returns size of quarantined slots that are reachable from the current - // stack. - size_t quarantine_size() const { return quarantine_size_; } - - private: - const PCScanTask& task_; - size_t quarantine_size_ = 0; -}; - -PCScanTask::PCScanTask(PCScan& pcscan, size_t quarantine_last_size) - : pcscan_epoch_(pcscan.epoch() - 1), - snapshot_(StarScanSnapshot::Create(PCScanInternal::Instance())), - stats_(PCScanInternal::Instance().process_name(), quarantine_last_size), - immediatelly_free_slots_( - PCScanInternal::Instance().IsImmediateFreeingEnabled()), - pcscan_(pcscan) {} - -void PCScanTask::ScanStack() { - const auto& pcscan = PCScanInternal::Instance(); - if (!pcscan.IsStackScanningEnabled()) { - return; - } - // Check if the stack top was registered. It may happen that it's not if the - // current allocation happens from pthread trampolines. - void* stack_top = StackTopRegistry::Get().GetCurrentThreadStackTop(); - if (PA_UNLIKELY(!stack_top)) { - return; - } - - Stack stack_scanner(stack_top); - StackVisitor visitor(*this); - stack_scanner.IteratePointers(&visitor); - stats_.IncreaseSurvivedQuarantineSize(visitor.quarantine_size()); -} - -void PCScanTask::ScanNormalArea(PCScanInternal& pcscan, - PCScanScanLoop& scan_loop, - uintptr_t begin, - uintptr_t end) { - // Protect slot span before scanning it. - pcscan.ProtectPages(begin, end - begin); - scan_loop.Run(begin, end); -} - -void PCScanTask::ScanLargeArea(PCScanInternal& pcscan, - PCScanScanLoop& scan_loop, - uintptr_t begin, - uintptr_t end, - size_t slot_size) { - // For scanning large areas, it's worthwhile checking whether the range that - // is scanned contains allocated slots. It also helps to skip discarded - // freed slots. - // Protect slot span before scanning it. - pcscan.ProtectPages(begin, end - begin); - - auto* bitmap = StateBitmapFromAddr(begin); - - for (uintptr_t current_slot = begin; current_slot < end; - current_slot += slot_size) { - // It is okay to skip slots as the object they hold has been zapped at this - // point, which means that the pointers no longer retain other slots. - if (!bitmap->IsAllocated(current_slot)) { - continue; - } - uintptr_t current_slot_end = current_slot + slot_size; - // |slot_size| may be larger than |raw_size| for single-slot slot spans. - scan_loop.Run(current_slot, std::min(current_slot_end, end)); - } -} - -void PCScanTask::ScanPartitions() { - // Threshold for which bucket size it is worthwhile in checking whether the - // slot is allocated and needs to be scanned. PartitionPurgeSlotSpan() - // purges only slots >= page-size, this helps us to avoid faulting in - // discarded pages. We actually lower it further to 1024, to take advantage of - // skipping unallocated slots, but don't want to go any lower, as this comes - // at a cost of expensive bitmap checking. - static constexpr size_t kLargeScanAreaThresholdInWords = - 1024 / sizeof(uintptr_t); - - PCScanScanLoop scan_loop(*this); - auto& pcscan = PCScanInternal::Instance(); - - StarScanSnapshot::ScanningView snapshot_view(*snapshot_); - snapshot_view.VisitConcurrently([this, &pcscan, - &scan_loop](uintptr_t super_page) { - SuperPageSnapshot super_page_snapshot(super_page); - - for (const auto& scan_area : super_page_snapshot.scan_areas()) { - const uintptr_t begin = - super_page | - (scan_area.offset_within_page_in_words * sizeof(uintptr_t)); - PA_SCAN_DCHECK(begin == - super_page + (scan_area.offset_within_page_in_words * - sizeof(uintptr_t))); - const uintptr_t end = begin + scan_area.size_in_words * sizeof(uintptr_t); - - if (PA_UNLIKELY(scan_area.slot_size_in_words >= - kLargeScanAreaThresholdInWords)) { - ScanLargeArea(pcscan, scan_loop, begin, end, - scan_area.slot_size_in_words * sizeof(uintptr_t)); - } else { - ScanNormalArea(pcscan, scan_loop, begin, end); - } - } - }); - - stats_.IncreaseSurvivedQuarantineSize(scan_loop.quarantine_size()); -} - -namespace { - -struct SweepStat { - // Bytes that were really swept (by calling free()). - size_t swept_bytes = 0; - // Bytes of marked quarantine memory that were discarded (by calling - // madvice(DONT_NEED)). - size_t discarded_bytes = 0; -}; - -void UnmarkInCardTable(uintptr_t slot_start, SlotSpanMetadata* slot_span) { -#if PA_CONFIG(STARSCAN_USE_CARD_TABLE) - // Reset card(s) for this quarantined slot. Please note that the cards may - // still contain quarantined slots (which were promoted in this scan cycle), - // but ClearQuarantinedSlotsAndPrepareCardTable() will set them again in the - // next PCScan cycle. - QuarantineCardTable::GetFrom(slot_start) - .Unquarantine(slot_start, slot_span->GetUtilizedSlotSize()); -#endif // PA_CONFIG(STARSCAN_USE_CARD_TABLE) -} - -[[maybe_unused]] size_t FreeAndUnmarkInCardTable(PartitionRoot* root, - SlotSpanMetadata* slot_span, - uintptr_t slot_start) { - void* object = root->SlotStartToObject(slot_start); - root->FreeNoHooksImmediate(object, slot_span, slot_start); - UnmarkInCardTable(slot_start, slot_span); - return slot_span->bucket->slot_size; -} - -[[maybe_unused]] void SweepSuperPage(PartitionRoot* root, - uintptr_t super_page, - size_t epoch, - SweepStat& stat) { - auto* bitmap = StateBitmapFromAddr(super_page); - PartitionRoot::FromFirstSuperPage(super_page); - bitmap->IterateUnmarkedQuarantined(epoch, [root, - &stat](uintptr_t slot_start) { - auto* slot_span = SlotSpanMetadata::FromSlotStart(slot_start); - stat.swept_bytes += FreeAndUnmarkInCardTable(root, slot_span, slot_start); - }); -} - -[[maybe_unused]] void SweepSuperPageAndDiscardMarkedQuarantine( - PartitionRoot* root, - uintptr_t super_page, - size_t epoch, - SweepStat& stat) { - auto* bitmap = StateBitmapFromAddr(super_page); - bitmap->IterateQuarantined(epoch, [root, &stat](uintptr_t slot_start, - bool is_marked) { - auto* slot_span = SlotSpanMetadata::FromSlotStart(slot_start); - if (PA_LIKELY(!is_marked)) { - stat.swept_bytes += FreeAndUnmarkInCardTable(root, slot_span, slot_start); - return; - } - // Otherwise, try to discard pages for marked quarantine. Since no data is - // stored in quarantined slots (e.g. the |next| pointer), this can be - // freely done. - const size_t slot_size = slot_span->bucket->slot_size; - if (slot_size >= SystemPageSize()) { - const uintptr_t discard_end = - base::bits::AlignDown(slot_start + slot_size, SystemPageSize()); - const uintptr_t discard_begin = - base::bits::AlignUp(slot_start, SystemPageSize()); - const intptr_t discard_size = discard_end - discard_begin; - if (discard_size > 0) { - DiscardSystemPages(discard_begin, discard_size); - stat.discarded_bytes += discard_size; - } - } - }); -} - -[[maybe_unused]] void SweepSuperPageWithBatchedFree(PartitionRoot* root, - uintptr_t super_page, - size_t epoch, - SweepStat& stat) { - auto* bitmap = StateBitmapFromAddr(super_page); - SlotSpanMetadata* previous_slot_span = nullptr; - internal::PartitionFreelistEntry* freelist_tail = nullptr; - internal::PartitionFreelistEntry* freelist_head = nullptr; - size_t freelist_entries = 0; - - const auto bitmap_iterator = [&](uintptr_t slot_start) { - SlotSpanMetadata* current_slot_span = - SlotSpanMetadata::FromSlotStart(slot_start); - const internal::PartitionFreelistDispatcher* freelist_dispatcher = - root->get_freelist_dispatcher(); - auto* entry = freelist_dispatcher->EmplaceAndInitNull(slot_start); - - if (current_slot_span != previous_slot_span) { - // We started scanning a new slot span. Flush the accumulated freelist to - // the slot-span's freelist. This is a single lock acquired per slot span. - if (previous_slot_span && freelist_entries) { - root->RawFreeBatch(freelist_head, freelist_tail, freelist_entries, - previous_slot_span); - } - freelist_head = entry; - freelist_tail = nullptr; - freelist_entries = 0; - previous_slot_span = current_slot_span; - } - - if (freelist_tail) { - freelist_dispatcher->SetNext(freelist_tail, entry); - } - freelist_tail = entry; - ++freelist_entries; - - UnmarkInCardTable(slot_start, current_slot_span); - - stat.swept_bytes += current_slot_span->bucket->slot_size; - }; - - bitmap->IterateUnmarkedQuarantinedAndFree(epoch, bitmap_iterator); - - if (previous_slot_span && freelist_entries) { - root->RawFreeBatch(freelist_head, freelist_tail, freelist_entries, - previous_slot_span); - } -} - -} // namespace - -void PCScanTask::SweepQuarantine() { - // Check that scan is unjoinable by this time. - PA_DCHECK(!pcscan_.IsJoinable()); - // Discard marked quarantine memory on every Nth scan. - // TODO(bikineev): Find a better signal (e.g. memory pressure, high - // survival rate, etc). - static constexpr size_t kDiscardMarkedQuarantineFrequency = 16; - const bool should_discard = - (pcscan_epoch_ % kDiscardMarkedQuarantineFrequency == 0) && - (pcscan_.clear_type_ == PCScan::ClearType::kEager); - - SweepStat stat; - StarScanSnapshot::SweepingView sweeping_view(*snapshot_); - sweeping_view.VisitNonConcurrently( - [this, &stat, should_discard](uintptr_t super_page) { - auto* root = PartitionRoot::FromFirstSuperPage(super_page); - -#if PA_CONFIG(STARSCAN_BATCHED_FREE) - SweepSuperPageWithBatchedFree(root, super_page, pcscan_epoch_, stat); - (void)should_discard; -#else - if (PA_UNLIKELY(should_discard && !root->settings.use_cookie)) { - SweepSuperPageAndDiscardMarkedQuarantine(root, super_page, - pcscan_epoch_, stat); - } else { - SweepSuperPage(root, super_page, pcscan_epoch_, stat); - } -#endif // PA_CONFIG(STARSCAN_BATCHED_FREE) - }); - - stats_.IncreaseSweptSize(stat.swept_bytes); - stats_.IncreaseDiscardedQuarantineSize(stat.discarded_bytes); - -#if PA_CONFIG(THREAD_CACHE_SUPPORTED) - // Sweeping potentially frees into the current thread's thread cache. Purge - // releases the cache back to the global allocator. - auto* current_thread_tcache = ThreadCache::Get(); - if (ThreadCache::IsValid(current_thread_tcache)) { - current_thread_tcache->Purge(); - } -#endif // PA_CONFIG(THREAD_CACHE_SUPPORTED) -} - -void PCScanTask::FinishScanner() { - stats_.ReportTracesAndHists(PCScanInternal::Instance().GetReporter()); - - pcscan_.scheduler_.scheduling_backend().UpdateScheduleAfterScan( - stats_.survived_quarantine_size(), stats_.GetOverallTime(), - PCScanInternal::Instance().CalculateTotalHeapSize()); - - PCScanInternal::Instance().ResetCurrentPCScanTask(); - // Change the state and check that concurrent task can't be scheduled twice. - PA_CHECK(pcscan_.state_.exchange(PCScan::State::kNotRunning, - std::memory_order_acq_rel) == - PCScan::State::kSweepingAndFinishing); -} - -void PCScanTask::RunFromMutator() { - ReentrantScannerGuard reentrancy_guard; - StatsCollector::MutatorScope overall_scope( - stats_, StatsCollector::MutatorId::kOverall); - { - SyncScope sync_scope(*this); - // Mutator might start entering the safepoint while scanning was already - // finished. - if (!pcscan_.IsJoinable()) { - return; - } - { - // Clear all quarantined slots and prepare card table. - StatsCollector::MutatorScope clear_scope( - stats_, StatsCollector::MutatorId::kClear); - ClearQuarantinedSlotsAndPrepareCardTable(); - } - { - // Scan the thread's stack to find dangling references. - StatsCollector::MutatorScope scan_scope( - stats_, StatsCollector::MutatorId::kScanStack); - ScanStack(); - } - { - // Unprotect all scanned pages, if needed. - UnprotectPartitions(); - } - { - // Scan heap for dangling references. - StatsCollector::MutatorScope scan_scope(stats_, - StatsCollector::MutatorId::kScan); - ScanPartitions(); - } - } -} - -void PCScanTask::RunFromScanner() { - ReentrantScannerGuard reentrancy_guard; - { - StatsCollector::ScannerScope overall_scope( - stats_, StatsCollector::ScannerId::kOverall); - { - SyncScope sync_scope(*this); - { - // Clear all quarantined slots and prepare the card table. - StatsCollector::ScannerScope clear_scope( - stats_, StatsCollector::ScannerId::kClear); - ClearQuarantinedSlotsAndPrepareCardTable(); - } - { - // Scan heap for dangling references. - StatsCollector::ScannerScope scan_scope( - stats_, StatsCollector::ScannerId::kScan); - ScanPartitions(); - } - { - // Unprotect all scanned pages, if needed. - UnprotectPartitions(); - } - } - { - // Sweep unreachable quarantined slots. - StatsCollector::ScannerScope sweep_scope( - stats_, StatsCollector::ScannerId::kSweep); - SweepQuarantine(); - } - } - FinishScanner(); -} - -class PCScan::PCScanThread final { - public: - using TaskHandle = PCScanInternal::TaskHandle; - - static PCScanThread& Instance() { - // Lazily instantiate the scanning thread. - static internal::base::NoDestructor instance; - return *instance; - } - - void PostTask(TaskHandle task) { - { - std::lock_guard lock(mutex_); - PA_DCHECK(!posted_task_.get()); - posted_task_ = std::move(task); - wanted_delay_ = base::TimeDelta(); - } - condvar_.notify_one(); - } - - void PostDelayedTask(base::TimeDelta delay) { - { - std::lock_guard lock(mutex_); - if (posted_task_.get()) { - return; - } - wanted_delay_ = delay; - } - condvar_.notify_one(); - } - - private: - friend class internal::base::NoDestructor; - - PCScanThread() { - ScopedAllowAllocations allow_allocations_within_std_thread; - std::thread{[](PCScanThread* instance) { - static constexpr const char* kThreadName = "PCScan"; - // Ideally we should avoid mixing base:: and std:: API for - // threading, but this is useful for visualizing the pcscan - // thread in chrome://tracing. - internal::base::PlatformThread::SetName(kThreadName); - instance->TaskLoop(); - }, - this} - .detach(); - } - - // Waits and returns whether the delay should be recomputed. - bool Wait(std::unique_lock& lock) { - PA_DCHECK(lock.owns_lock()); - if (wanted_delay_.is_zero()) { - condvar_.wait(lock, [this] { - // Re-evaluate if either delay changed, or a task was - // enqueued. - return !wanted_delay_.is_zero() || posted_task_.get(); - }); - // The delay has already been set up and should not be queried again. - return false; - } - condvar_.wait_for( - lock, std::chrono::microseconds(wanted_delay_.InMicroseconds())); - // If no task has been posted, the delay should be recomputed at this point. - return !posted_task_.get(); - } - - void TaskLoop() { - while (true) { - TaskHandle current_task; - { - std::unique_lock lock(mutex_); - // Scheduling. - while (!posted_task_.get()) { - if (Wait(lock)) { - wanted_delay_ = - scheduler().scheduling_backend().UpdateDelayedSchedule(); - if (wanted_delay_.is_zero()) { - break; - } - } - } - // Differentiate between a posted task and a delayed task schedule. - if (posted_task_.get()) { - std::swap(current_task, posted_task_); - wanted_delay_ = base::TimeDelta(); - } else { - PA_DCHECK(wanted_delay_.is_zero()); - } - } - // Differentiate between a posted task and a delayed task schedule. - if (current_task.get()) { - current_task->RunFromScanner(); - } else { - PCScan::Instance().PerformScan(PCScan::InvocationMode::kNonBlocking); - } - } - } - - PCScanScheduler& scheduler() const { return PCScan::Instance().scheduler(); } - - std::mutex mutex_; - std::condition_variable condvar_; - TaskHandle posted_task_; - base::TimeDelta wanted_delay_; -}; - -PCScanInternal::PCScanInternal() : simd_support_(DetectSimdSupport()) {} - -PCScanInternal::~PCScanInternal() = default; - -void PCScanInternal::Initialize(PCScan::InitConfig config) { - PA_DCHECK(!is_initialized_); -#if PA_BUILDFLAG(HAS_64_BIT_POINTERS) - // Make sure that pools are initialized. - PartitionAddressSpace::Init(); -#endif - CommitCardTable(); -#if PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) - if (config.write_protection == - PCScan::InitConfig::WantedWriteProtectionMode::kEnabled) { - write_protector_ = std::make_unique(); - } else { - write_protector_ = std::make_unique(); - } -#else - write_protector_ = std::make_unique(); -#endif // PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) - PCScan::SetClearType(write_protector_->SupportedClearType()); - - if (config.safepoint == PCScan::InitConfig::SafepointMode::kEnabled) { - PCScan::Instance().EnableSafepoints(); - } - scannable_roots_ = RootsMap(); - nonscannable_roots_ = RootsMap(); - - static partition_alloc::StatsReporter s_no_op_reporter; - PCScan::Instance().RegisterStatsReporter(&s_no_op_reporter); - - // Don't initialize PCScanThread::Instance() as otherwise sandbox complains - // about multiple threads running on sandbox initialization. - is_initialized_ = true; -} - -void PCScanInternal::PerformScan(PCScan::InvocationMode invocation_mode) { -#if PA_SCAN_DCHECK_IS_ON() - PA_DCHECK(is_initialized()); - PA_DCHECK(scannable_roots().size() > 0); - PA_DCHECK(std::all_of( - scannable_roots().begin(), scannable_roots().end(), - [](const auto& pair) { return pair.first->IsScanEnabled(); })); - PA_DCHECK(std::all_of( - nonscannable_roots().begin(), nonscannable_roots().end(), - [](const auto& pair) { return pair.first->IsQuarantineEnabled(); })); -#endif - - PCScan& frontend = PCScan::Instance(); - { - // If scanning is already in progress, bail out. - PCScan::State expected = PCScan::State::kNotRunning; - if (!frontend.state_.compare_exchange_strong( - expected, PCScan::State::kScheduled, std::memory_order_acq_rel, - std::memory_order_relaxed)) { - return; - } - } - - const size_t last_quarantine_size = - frontend.scheduler_.scheduling_backend().ScanStarted(); - - // Create PCScan task and set it as current. - auto task = base::MakeRefCounted(frontend, last_quarantine_size); - PCScanInternal::Instance().SetCurrentPCScanTask(task); - - if (PA_UNLIKELY(invocation_mode == - PCScan::InvocationMode::kScheduleOnlyForTesting)) { - // Immediately change the state to enable safepoint testing. - frontend.state_.store(PCScan::State::kScanning, std::memory_order_release); - frontend.SetJoinableIfSafepointEnabled(true); - return; - } - - // Post PCScan task. - if (PA_LIKELY(invocation_mode == PCScan::InvocationMode::kNonBlocking)) { - PCScan::PCScanThread::Instance().PostTask(std::move(task)); - } else { - PA_SCAN_DCHECK(PCScan::InvocationMode::kBlocking == invocation_mode || - PCScan::InvocationMode::kForcedBlocking == invocation_mode); - std::move(*task).RunFromScanner(); - } -} - -void PCScanInternal::PerformScanIfNeeded( - PCScan::InvocationMode invocation_mode) { - if (!scannable_roots().size()) { - return; - } - PCScan& frontend = PCScan::Instance(); - if (invocation_mode == PCScan::InvocationMode::kForcedBlocking || - frontend.scheduler_.scheduling_backend() - .GetQuarantineData() - .MinimumScanningThresholdReached()) { - PerformScan(invocation_mode); - } -} - -void PCScanInternal::PerformDelayedScan(base::TimeDelta delay) { - PCScan::PCScanThread::Instance().PostDelayedTask(delay); -} - -void PCScanInternal::JoinScan() { - // Current task can be destroyed by the scanner. Check that it's valid. - if (auto current_task = CurrentPCScanTask()) { - current_task->RunFromMutator(); - } -} - -PCScanInternal::TaskHandle PCScanInternal::CurrentPCScanTask() const { - std::lock_guard lock(current_task_mutex_); - return current_task_; -} - -void PCScanInternal::SetCurrentPCScanTask(TaskHandle task) { - std::lock_guard lock(current_task_mutex_); - current_task_ = std::move(task); -} - -void PCScanInternal::ResetCurrentPCScanTask() { - std::lock_guard lock(current_task_mutex_); - current_task_.reset(); -} - -namespace { -PCScanInternal::SuperPages GetSuperPagesAndCommitStateBitmaps( - PCScan::Root& root) { - const size_t state_bitmap_size_to_commit = CommittedStateBitmapSize(); - PCScanInternal::SuperPages super_pages; - for (auto* super_page_extent = root.first_extent; super_page_extent; - super_page_extent = super_page_extent->next) { - for (uintptr_t super_page = SuperPagesBeginFromExtent(super_page_extent), - super_page_end = SuperPagesEndFromExtent(super_page_extent); - super_page != super_page_end; super_page += kSuperPageSize) { - // Make sure the metadata is committed. - // TODO(bikineev): Remove once this is known to work. - const volatile char* metadata = - reinterpret_cast(PartitionSuperPageToMetadataArea(super_page)); - *metadata; - RecommitSystemPages(SuperPageStateBitmapAddr(super_page), - state_bitmap_size_to_commit, - PageAccessibilityConfiguration( - PageAccessibilityConfiguration::kReadWrite), - PageAccessibilityDisposition::kRequireUpdate); - super_pages.push_back(super_page); - } - } - return super_pages; -} -} // namespace - -void PCScanInternal::RegisterScannableRoot(Root* root) { - PA_DCHECK(is_initialized()); - PA_DCHECK(root); - // Avoid nesting locks and store super_pages in a temporary vector. - SuperPages super_pages; - { - ::partition_alloc::internal::ScopedGuard guard( - ::partition_alloc::internal::PartitionRootLock(root)); - PA_CHECK(root->IsQuarantineAllowed()); - if (root->IsScanEnabled()) { - return; - } - PA_CHECK(!root->IsQuarantineEnabled()); - super_pages = GetSuperPagesAndCommitStateBitmaps(*root); - root->settings.scan_mode = Root::ScanMode::kEnabled; - root->settings.quarantine_mode = Root::QuarantineMode::kEnabled; - } - std::lock_guard lock(roots_mutex_); - PA_DCHECK(!scannable_roots_.count(root)); - auto& root_super_pages = scannable_roots_[root]; - root_super_pages.insert(root_super_pages.end(), super_pages.begin(), - super_pages.end()); -} - -void PCScanInternal::RegisterNonScannableRoot(Root* root) { - PA_DCHECK(is_initialized()); - PA_DCHECK(root); - // Avoid nesting locks and store super_pages in a temporary vector. - SuperPages super_pages; - { - ::partition_alloc::internal::ScopedGuard guard( - ::partition_alloc::internal::PartitionRootLock(root)); - PA_CHECK(root->IsQuarantineAllowed()); - PA_CHECK(!root->IsScanEnabled()); - if (root->IsQuarantineEnabled()) { - return; - } - super_pages = GetSuperPagesAndCommitStateBitmaps(*root); - root->settings.quarantine_mode = Root::QuarantineMode::kEnabled; - } - std::lock_guard lock(roots_mutex_); - PA_DCHECK(!nonscannable_roots_.count(root)); - auto& root_super_pages = nonscannable_roots_[root]; - root_super_pages.insert(root_super_pages.end(), super_pages.begin(), - super_pages.end()); -} - -void PCScanInternal::RegisterNewSuperPage(Root* root, - uintptr_t super_page_base) { - PA_DCHECK(is_initialized()); - PA_DCHECK(root); - PA_CHECK(root->IsQuarantineAllowed()); - PA_DCHECK(!(super_page_base % kSuperPageAlignment)); - // Make sure the metadata is committed. - // TODO(bikineev): Remove once this is known to work. - const volatile char* metadata = reinterpret_cast( - PartitionSuperPageToMetadataArea(super_page_base)); - *metadata; - - std::lock_guard lock(roots_mutex_); - - // Dispatch based on whether root is scannable or not. - if (root->IsScanEnabled()) { - PA_DCHECK(scannable_roots_.count(root)); - auto& super_pages = scannable_roots_[root]; - PA_DCHECK(std::find(super_pages.begin(), super_pages.end(), - super_page_base) == super_pages.end()); - super_pages.push_back(super_page_base); - } else { - PA_DCHECK(root->IsQuarantineEnabled()); - PA_DCHECK(nonscannable_roots_.count(root)); - auto& super_pages = nonscannable_roots_[root]; - PA_DCHECK(std::find(super_pages.begin(), super_pages.end(), - super_page_base) == super_pages.end()); - super_pages.push_back(super_page_base); - } -} - -void PCScanInternal::SetProcessName(const char* process_name) { - PA_DCHECK(is_initialized()); - PA_DCHECK(process_name); - PA_DCHECK(!process_name_); - process_name_ = process_name; -} - -size_t PCScanInternal::CalculateTotalHeapSize() const { - PA_DCHECK(is_initialized()); - std::lock_guard lock(roots_mutex_); - const auto acc = [](size_t size, const auto& pair) { - return size + pair.first->get_total_size_of_committed_pages(); - }; - return std::accumulate(scannable_roots_.begin(), scannable_roots_.end(), 0u, - acc) + - std::accumulate(nonscannable_roots_.begin(), nonscannable_roots_.end(), - 0u, acc); -} - -void PCScanInternal::EnableStackScanning() { - PA_DCHECK(!stack_scanning_enabled_); - stack_scanning_enabled_ = true; -} -void PCScanInternal::DisableStackScanning() { - PA_DCHECK(stack_scanning_enabled_); - stack_scanning_enabled_ = false; -} -bool PCScanInternal::IsStackScanningEnabled() const { - return stack_scanning_enabled_; -} - -bool PCScanInternal::WriteProtectionEnabled() const { - return write_protector_->IsEnabled(); -} - -void PCScanInternal::ProtectPages(uintptr_t begin, size_t size) { - // Slot-span sizes are multiple of system page size. However, the ranges that - // are recorded are not, since in the snapshot we only record the used - // payload. Therefore we align up the incoming range by 4k. The unused part of - // slot-spans doesn't need to be protected (the allocator will enter the - // safepoint before trying to allocate from it). - PA_SCAN_DCHECK(write_protector_.get()); - write_protector_->ProtectPages( - begin, - partition_alloc::internal::base::bits::AlignUp(size, SystemPageSize())); -} - -void PCScanInternal::UnprotectPages(uintptr_t begin, size_t size) { - PA_SCAN_DCHECK(write_protector_.get()); - write_protector_->UnprotectPages( - begin, - partition_alloc::internal::base::bits::AlignUp(size, SystemPageSize())); -} - -void PCScanInternal::ClearRootsForTesting() { - std::lock_guard lock(roots_mutex_); - // Set all roots as non-scannable and non-quarantinable. - for (auto& pair : scannable_roots_) { - Root* root = pair.first; - root->settings.scan_mode = Root::ScanMode::kDisabled; - root->settings.quarantine_mode = Root::QuarantineMode::kDisabledByDefault; - } - for (auto& pair : nonscannable_roots_) { - Root* root = pair.first; - root->settings.quarantine_mode = Root::QuarantineMode::kDisabledByDefault; - } - // Make sure to destroy maps so that on the following ReinitForTesting() call - // the maps don't attempt to destroy the backing. - scannable_roots_.clear(); - scannable_roots_.~RootsMap(); - nonscannable_roots_.clear(); - nonscannable_roots_.~RootsMap(); - // Destroy write protector object, so that there is no double free on the next - // call to ReinitForTesting(); - write_protector_.reset(); -} - -void PCScanInternal::ReinitForTesting(PCScan::InitConfig config) { - is_initialized_ = false; - auto* new_this = new (this) PCScanInternal; - new_this->Initialize(config); -} - -void PCScanInternal::FinishScanForTesting() { - auto current_task = CurrentPCScanTask(); - PA_CHECK(current_task.get()); - current_task->RunFromScanner(); -} - -void PCScanInternal::RegisterStatsReporter( - partition_alloc::StatsReporter* reporter) { - PA_DCHECK(reporter); - stats_reporter_ = reporter; -} - -partition_alloc::StatsReporter& PCScanInternal::GetReporter() { - PA_DCHECK(stats_reporter_); - return *stats_reporter_; -} - -} // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_internal.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_internal.h deleted file mode 100644 index 2580f0411f..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_internal.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_PCSCAN_INTERNAL_H_ -#define PARTITION_ALLOC_STARSCAN_PCSCAN_INTERNAL_H_ - -#include -#include -#include -#include -#include -#include -#include - -#include "partition_alloc/internal_allocator_forward.h" -#include "partition_alloc/partition_alloc_base/memory/scoped_refptr.h" -#include "partition_alloc/partition_alloc_base/no_destructor.h" -#include "partition_alloc/starscan/pcscan.h" -#include "partition_alloc/starscan/starscan_fwd.h" -#include "partition_alloc/starscan/write_protector.h" - -namespace partition_alloc::internal { - -class PCScanTask; - -// Internal PCScan singleton. The separation between frontend and backend is -// needed to keep access to the hot data (quarantine) in the frontend fast, -// whereas the backend can hold cold data. -class PCScanInternal final { - public: - using Root = PCScan::Root; - using TaskHandle = scoped_refptr; - - using SuperPages = - std::vector>; - using RootsMap = std::unordered_map< - Root*, - SuperPages, - std::hash, - std::equal_to<>, - internal::InternalAllocator>>; - - static PCScanInternal& Instance() { - // Since the data that PCScanInternal holds is cold, it's fine to have the - // runtime check for thread-safe local static initialization. - static internal::base::NoDestructor instance; - return *instance; - } - - PCScanInternal(const PCScanInternal&) = delete; - PCScanInternal& operator=(const PCScanInternal&) = delete; - - ~PCScanInternal(); - - void Initialize(PCScan::InitConfig); - bool is_initialized() const { return is_initialized_; } - - void PerformScan(PCScan::InvocationMode); - void PerformScanIfNeeded(PCScan::InvocationMode); - void PerformDelayedScan(base::TimeDelta delay); - void JoinScan(); - - TaskHandle CurrentPCScanTask() const; - void SetCurrentPCScanTask(TaskHandle task); - void ResetCurrentPCScanTask(); - - void RegisterScannableRoot(Root*); - void RegisterNonScannableRoot(Root*); - - RootsMap& scannable_roots() { return scannable_roots_; } - const RootsMap& scannable_roots() const { return scannable_roots_; } - - RootsMap& nonscannable_roots() { return nonscannable_roots_; } - const RootsMap& nonscannable_roots() const { return nonscannable_roots_; } - - void RegisterNewSuperPage(Root* root, uintptr_t super_page_base); - - void SetProcessName(const char* name); - const char* process_name() const { return process_name_; } - - // Get size of all committed pages from scannable and nonscannable roots. - size_t CalculateTotalHeapSize() const; - - SimdSupport simd_support() const { return simd_support_; } - - void EnableStackScanning(); - void DisableStackScanning(); - bool IsStackScanningEnabled() const; - - void EnableImmediateFreeing() { immediate_freeing_enabled_ = true; } - bool IsImmediateFreeingEnabled() const { return immediate_freeing_enabled_; } - - bool WriteProtectionEnabled() const; - void ProtectPages(uintptr_t begin, size_t size); - void UnprotectPages(uintptr_t begin, size_t size); - - void ClearRootsForTesting(); // IN-TEST - void ReinitForTesting(PCScan::InitConfig); // IN-TEST - void FinishScanForTesting(); // IN-TEST - - void RegisterStatsReporter(partition_alloc::StatsReporter* reporter); - partition_alloc::StatsReporter& GetReporter(); - - private: - friend internal::base::NoDestructor; - friend class StarScanSnapshot; - - PCScanInternal(); - - TaskHandle current_task_; - mutable std::mutex current_task_mutex_; - - RootsMap scannable_roots_; - RootsMap nonscannable_roots_; - mutable std::mutex roots_mutex_; - - bool stack_scanning_enabled_{false}; - - bool immediate_freeing_enabled_{false}; - - const char* process_name_ = nullptr; - const SimdSupport simd_support_; - - std::unique_ptr write_protector_; - partition_alloc::StatsReporter* stats_reporter_ = nullptr; - - bool is_initialized_ = false; -}; - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_PCSCAN_INTERNAL_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_scheduling.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_scheduling.cc deleted file mode 100644 index 0ed3106735..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_scheduling.cc +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "partition_alloc/starscan/pcscan_scheduling.h" - -#include -#include - -#include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_alloc_check.h" -#include "partition_alloc/partition_alloc_hooks.h" -#include "partition_alloc/partition_lock.h" -#include "partition_alloc/starscan/logging.h" -#include "partition_alloc/starscan/pcscan.h" - -namespace partition_alloc::internal { - -// static -constexpr size_t QuarantineData::kQuarantineSizeMinLimit; - -void PCScanScheduler::SetNewSchedulingBackend( - PCScanSchedulingBackend& backend) { - backend_ = &backend; -} - -void PCScanSchedulingBackend::DisableScheduling() { - scheduling_enabled_.store(false, std::memory_order_relaxed); -} - -void PCScanSchedulingBackend::EnableScheduling() { - scheduling_enabled_.store(true, std::memory_order_relaxed); - // Check if *Scan needs to be run immediately. - if (NeedsToImmediatelyScan()) { - PCScan::PerformScan(PCScan::InvocationMode::kNonBlocking); - } -} - -size_t PCScanSchedulingBackend::ScanStarted() { - auto& data = GetQuarantineData(); - data.epoch.fetch_add(1, std::memory_order_relaxed); - return data.current_size.exchange(0, std::memory_order_relaxed); -} - -base::TimeDelta PCScanSchedulingBackend::UpdateDelayedSchedule() { - return base::TimeDelta(); -} - -// static -constexpr double LimitBackend::kQuarantineSizeFraction; - -bool LimitBackend::LimitReached() { - return is_scheduling_enabled(); -} - -void LimitBackend::UpdateScheduleAfterScan(size_t survived_bytes, - base::TimeDelta, - size_t heap_size) { - scheduler_.AccountFreed(survived_bytes); - // |heap_size| includes the current quarantine size, we intentionally leave - // some slack till hitting the limit. - auto& data = GetQuarantineData(); - data.size_limit.store( - std::max(QuarantineData::kQuarantineSizeMinLimit, - static_cast(kQuarantineSizeFraction * heap_size)), - std::memory_order_relaxed); -} - -bool LimitBackend::NeedsToImmediatelyScan() { - return false; -} - -// static -constexpr double MUAwareTaskBasedBackend::kSoftLimitQuarantineSizePercent; -// static -constexpr double MUAwareTaskBasedBackend::kHardLimitQuarantineSizePercent; -// static -constexpr double MUAwareTaskBasedBackend::kTargetMutatorUtilizationPercent; - -MUAwareTaskBasedBackend::MUAwareTaskBasedBackend( - PCScanScheduler& scheduler, - ScheduleDelayedScanFunc schedule_delayed_scan) - : PCScanSchedulingBackend(scheduler), - schedule_delayed_scan_(schedule_delayed_scan) { - PA_DCHECK(schedule_delayed_scan_); -} - -MUAwareTaskBasedBackend::~MUAwareTaskBasedBackend() = default; - -bool MUAwareTaskBasedBackend::LimitReached() { - bool should_reschedule = false; - base::TimeDelta reschedule_delay; - { - ScopedGuard guard(scheduler_lock_); - // At this point we reached a limit where the schedule generally wants to - // trigger a scan. - if (hard_limit_) { - // The hard limit is not reset, indicating that the scheduler only hit the - // soft limit. See inlined comments for the algorithm. - auto& data = GetQuarantineData(); - PA_DCHECK(hard_limit_ >= QuarantineData::kQuarantineSizeMinLimit); - // 1. Update the limit to the hard limit which will always immediately - // trigger a scan. - data.size_limit.store(hard_limit_, std::memory_order_relaxed); - hard_limit_ = 0; - - // 2. Unlikely case: If also above hard limit, start scan right away. This - // ignores explicit PCScan disabling. - if (PA_UNLIKELY(data.current_size.load(std::memory_order_relaxed) > - data.size_limit.load(std::memory_order_relaxed))) { - return true; - } - - // 3. Check if PCScan was explicitly disabled. - if (PA_UNLIKELY(!is_scheduling_enabled())) { - return false; - } - - // 4. Otherwise, the soft limit would trigger a scan immediately if the - // mutator utilization requirement is satisfied. - reschedule_delay = earliest_next_scan_time_ - base::TimeTicks::Now(); - if (reschedule_delay <= base::TimeDelta()) { - // May invoke scan immediately. - return true; - } - - PA_PCSCAN_VLOG(3) << "Rescheduling scan with delay: " - << reschedule_delay.InMillisecondsF() << " ms"; - // 5. If the MU requirement is not satisfied, schedule a delayed scan to - // the time instance when MU is satisfied. - should_reschedule = true; - } - } - // Don't reschedule under the lock as the callback can call free() and - // recursively enter the lock. - if (should_reschedule) { - schedule_delayed_scan_(reschedule_delay.InMicroseconds()); - return false; - } - return true; -} - -size_t MUAwareTaskBasedBackend::ScanStarted() { - ScopedGuard guard(scheduler_lock_); - - return PCScanSchedulingBackend::ScanStarted(); -} - -void MUAwareTaskBasedBackend::UpdateScheduleAfterScan( - size_t survived_bytes, - base::TimeDelta time_spent_in_scan, - size_t heap_size) { - scheduler_.AccountFreed(survived_bytes); - - ScopedGuard guard(scheduler_lock_); - - // |heap_size| includes the current quarantine size, we intentionally leave - // some slack till hitting the limit. - auto& data = GetQuarantineData(); - data.size_limit.store( - std::max( - QuarantineData::kQuarantineSizeMinLimit, - static_cast(kSoftLimitQuarantineSizePercent * heap_size)), - std::memory_order_relaxed); - hard_limit_ = std::max( - QuarantineData::kQuarantineSizeMinLimit, - static_cast(kHardLimitQuarantineSizePercent * heap_size)); - - // This computes the time window that the scheduler will reserve for the - // mutator. Scanning, unless reaching the hard limit, will generally be - // delayed until this time has passed. - const auto time_required_on_mutator = - time_spent_in_scan * kTargetMutatorUtilizationPercent / - (1.0 - kTargetMutatorUtilizationPercent); - earliest_next_scan_time_ = base::TimeTicks::Now() + time_required_on_mutator; -} - -bool MUAwareTaskBasedBackend::NeedsToImmediatelyScan() { - bool should_reschedule = false; - base::TimeDelta reschedule_delay; - { - ScopedGuard guard(scheduler_lock_); - // If |hard_limit_| was set to zero, the soft limit was reached. Bail out if - // it's not. - if (hard_limit_) { - return false; - } - - // Check if mutator utilization requiremet is satisfied. - reschedule_delay = earliest_next_scan_time_ - base::TimeTicks::Now(); - if (reschedule_delay <= base::TimeDelta()) { - // May invoke scan immediately. - return true; - } - - PA_PCSCAN_VLOG(3) << "Rescheduling scan with delay: " - << reschedule_delay.InMillisecondsF() << " ms"; - // Schedule a delayed scan to the time instance when MU is satisfied. - should_reschedule = true; - } - // Don't reschedule under the lock as the callback can call free() and - // recursively enter the lock. - if (should_reschedule) { - schedule_delayed_scan_(reschedule_delay.InMicroseconds()); - } - return false; -} - -base::TimeDelta MUAwareTaskBasedBackend::UpdateDelayedSchedule() { - ScopedGuard guard(scheduler_lock_); - // TODO(crbug.com/40176938): Adjust schedule to current heap sizing. - const auto delay = earliest_next_scan_time_ - base::TimeTicks::Now(); - PA_PCSCAN_VLOG(3) << "Schedule is off by " << delay.InMillisecondsF() << "ms"; - return delay >= base::TimeDelta() ? delay : base::TimeDelta(); -} - -} // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_scheduling.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_scheduling.h deleted file mode 100644 index 09950c9a84..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_scheduling.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_PCSCAN_SCHEDULING_H_ -#define PARTITION_ALLOC_STARSCAN_PCSCAN_SCHEDULING_H_ - -#include -#include - -#include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/thread_annotations.h" -#include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_lock.h" - -namespace partition_alloc::internal { - -class PCScanScheduler; - -struct QuarantineData final { - static constexpr size_t kQuarantineSizeMinLimit = 1 * 1024 * 1024; - - inline constexpr QuarantineData(); - - bool MinimumScanningThresholdReached() const { - return current_size.load(std::memory_order_relaxed) > - kQuarantineSizeMinLimit; - } - - std::atomic current_size{0u}; - std::atomic size_limit{kQuarantineSizeMinLimit}; - std::atomic epoch{0u}; -}; - -// No virtual destructor to allow constant initialization of PCScan as -// static global which directly embeds LimitBackend as default backend. -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnon-virtual-dtor" -#endif -class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PCScanSchedulingBackend { -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - - public: - inline constexpr explicit PCScanSchedulingBackend(PCScanScheduler&); - - PCScanSchedulingBackend(const PCScanSchedulingBackend&) = delete; - PCScanSchedulingBackend& operator=(const PCScanSchedulingBackend&) = delete; - - void DisableScheduling(); - void EnableScheduling(); - - bool is_scheduling_enabled() const { - return scheduling_enabled_.load(std::memory_order_relaxed); - } - - inline QuarantineData& GetQuarantineData(); - - // Invoked when the limit in PCScanScheduler is reached. Returning true - // signals the caller to invoke a scan. - virtual bool LimitReached() = 0; - - // Invoked on starting a scan. Returns current quarantine size. - virtual size_t ScanStarted(); - - // Invoked at the end of a scan to compute a new limit. - virtual void UpdateScheduleAfterScan(size_t survived_bytes, - base::TimeDelta time_spent_in_scan, - size_t heap_size) = 0; - - // Invoked by PCScan to ask for a new timeout for a scheduled PCScan task. - // Only invoked if scheduler requests a delayed scan at some point. - virtual base::TimeDelta UpdateDelayedSchedule(); - - protected: - inline bool SchedulingDisabled() const; - - virtual bool NeedsToImmediatelyScan() = 0; - - PCScanScheduler& scheduler_; - std::atomic scheduling_enabled_{true}; -}; - -// Scheduling backend that just considers a single hard limit. -class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LimitBackend final - : public PCScanSchedulingBackend { - public: - static constexpr double kQuarantineSizeFraction = 0.1; - - inline constexpr explicit LimitBackend(PCScanScheduler&); - - bool LimitReached() final; - void UpdateScheduleAfterScan(size_t, base::TimeDelta, size_t) final; - - private: - bool NeedsToImmediatelyScan() final; -}; - -// Task based backend that is aware of a target mutator utilization that -// specifies how much percent of the execution should be reserved for the -// mutator. I.e., the MU-aware scheduler ensures that scans are limit and -// there is enough time left for the mutator to execute the actual application -// workload. -// -// See constants below for trigger mechanisms. -class PA_COMPONENT_EXPORT(PARTITION_ALLOC) MUAwareTaskBasedBackend final - : public PCScanSchedulingBackend { - public: - using ScheduleDelayedScanFunc = void (*)(int64_t delay_in_microseconds); - - MUAwareTaskBasedBackend(PCScanScheduler&, ScheduleDelayedScanFunc); - ~MUAwareTaskBasedBackend(); - - bool LimitReached() final; - size_t ScanStarted() final; - void UpdateScheduleAfterScan(size_t, base::TimeDelta, size_t) final; - base::TimeDelta UpdateDelayedSchedule() final; - - private: - // Limit triggering the scheduler. If `kTargetMutatorUtilizationPercent` is - // satisfied at this point then a scan is triggered immediately. - static constexpr double kSoftLimitQuarantineSizePercent = 0.1; - // Hard limit at which a scan is triggered in any case. Avoids blowing up the - // heap completely. - static constexpr double kHardLimitQuarantineSizePercent = 0.5; - // Target mutator utilization that is respected when invoking a scan. - // Specifies how much percent of walltime should be spent in the mutator. - // Inversely, specifies how much walltime (indirectly CPU) is spent on - // memory management in scan. - static constexpr double kTargetMutatorUtilizationPercent = 0.90; - - bool NeedsToImmediatelyScan() final; - - // Callback to schedule a delayed scan. - const ScheduleDelayedScanFunc schedule_delayed_scan_; - - Lock scheduler_lock_; - size_t hard_limit_ PA_GUARDED_BY(scheduler_lock_){0}; - base::TimeTicks earliest_next_scan_time_ PA_GUARDED_BY(scheduler_lock_); - - friend class PartitionAllocPCScanMUAwareTaskBasedBackendTest; -}; - -// The scheduler that is embedded in the PCSCan frontend which requires a fast -// path for freeing objects. The scheduler holds data needed to invoke a -// `PCScanSchedulingBackend` upon hitting a limit. The backend implements -// the actual scheduling strategy and is in charge of maintaining limits. -class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PCScanScheduler final { - public: - inline constexpr PCScanScheduler(); - - PCScanScheduler(const PCScanScheduler&) = delete; - PCScanScheduler& operator=(const PCScanScheduler&) = delete; - - // Account freed `bytes`. Returns true if scan should be triggered - // immediately, and false otherwise. - PA_ALWAYS_INLINE bool AccountFreed(size_t bytes); - - size_t epoch() const { - return quarantine_data_.epoch.load(std::memory_order_relaxed); - } - - // Sets a new scheduling backend that should be used by the scanner. - void SetNewSchedulingBackend(PCScanSchedulingBackend&); - - PCScanSchedulingBackend& scheduling_backend() { return *backend_; } - const PCScanSchedulingBackend& scheduling_backend() const { - return *backend_; - } - - private: - QuarantineData quarantine_data_{}; - // The default backend used is a simple LimitBackend that just triggers scan - // on reaching a hard limit. - LimitBackend default_scheduling_backend_{*this}; - PCScanSchedulingBackend* backend_ = &default_scheduling_backend_; - - friend PCScanSchedulingBackend; -}; - -// To please Chromium's clang plugin. -constexpr PCScanScheduler::PCScanScheduler() = default; -constexpr QuarantineData::QuarantineData() = default; - -constexpr PCScanSchedulingBackend::PCScanSchedulingBackend( - PCScanScheduler& scheduler) - : scheduler_(scheduler) {} - -QuarantineData& PCScanSchedulingBackend::GetQuarantineData() { - return scheduler_.quarantine_data_; -} - -constexpr LimitBackend::LimitBackend(PCScanScheduler& scheduler) - : PCScanSchedulingBackend(scheduler) {} - -PA_ALWAYS_INLINE bool PCScanScheduler::AccountFreed(size_t size) { - const size_t size_before = - quarantine_data_.current_size.fetch_add(size, std::memory_order_relaxed); - return (size_before + size > - quarantine_data_.size_limit.load(std::memory_order_relaxed)) && - backend_->LimitReached(); -} - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_PCSCAN_SCHEDULING_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/raceful_worklist.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/raceful_worklist.h deleted file mode 100644 index 4f4c93704c..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/raceful_worklist.h +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_RACEFUL_WORKLIST_H_ -#define PARTITION_ALLOC_STARSCAN_RACEFUL_WORKLIST_H_ - -#include -#include -#include - -#include "partition_alloc/internal_allocator_forward.h" -#include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_base/rand_util.h" -#include "partition_alloc/partition_alloc_check.h" - -namespace partition_alloc::internal { - -template -class RacefulWorklist { - struct Node { - explicit Node(const T& value) : value(value) {} - Node(const Node& other) - : value(other.value), - is_being_visited( - other.is_being_visited.load(std::memory_order_relaxed)), - is_visited(other.is_visited.load(std::memory_order_relaxed)) {} - - T value; - std::atomic is_being_visited{false}; - std::atomic is_visited{false}; - }; - using Underlying = std::vector>; - - public: - class RandomizedView { - public: - explicit RandomizedView(RacefulWorklist& worklist) - : worklist_(worklist), offset_(0) { - if (worklist.data_.size() > 0) { - offset_ = static_cast( - internal::base::RandGenerator(worklist.data_.size())); - } - } - - RandomizedView(const RandomizedView&) = delete; - const RandomizedView& operator=(const RandomizedView&) = delete; - - template - void Visit(Function f); - - private: - RacefulWorklist& worklist_; - size_t offset_; - }; - - RacefulWorklist() = default; - - RacefulWorklist(const RacefulWorklist&) = delete; - RacefulWorklist& operator=(const RacefulWorklist&) = delete; - - void Push(const T& t) { data_.push_back(Node(t)); } - - template - void Push(It begin, It end) { - std::transform(begin, end, std::back_inserter(data_), - [](const T& t) { return Node(t); }); - } - - template - void VisitNonConcurrently(Function) const; - - private: - Underlying data_; - std::atomic fully_visited_{false}; -}; - -template -template -void RacefulWorklist::VisitNonConcurrently(Function f) const { - for (const auto& t : data_) { - f(t.value); - } -} - -template -template -void RacefulWorklist::RandomizedView::Visit(Function f) { - auto& data = worklist_.data_; - std::vector> - to_revisit; - - // To avoid worklist iteration, quick check if the worklist was already - // visited. - if (worklist_.fully_visited_.load(std::memory_order_acquire)) { - return; - } - - const auto offset_it = std::next(data.begin(), offset_); - - // First, visit items starting from the offset. - for (auto it = offset_it; it != data.end(); ++it) { - if (it->is_visited.load(std::memory_order_relaxed)) { - continue; - } - if (it->is_being_visited.load(std::memory_order_relaxed)) { - to_revisit.push_back(it); - continue; - } - it->is_being_visited.store(true, std::memory_order_relaxed); - f(it->value); - it->is_visited.store(true, std::memory_order_relaxed); - } - - // Then, visit items before the offset. - for (auto it = data.begin(); it != offset_it; ++it) { - if (it->is_visited.load(std::memory_order_relaxed)) { - continue; - } - if (it->is_being_visited.load(std::memory_order_relaxed)) { - to_revisit.push_back(it); - continue; - } - it->is_being_visited.store(true, std::memory_order_relaxed); - f(it->value); - it->is_visited.store(true, std::memory_order_relaxed); - } - - // Finally, racefully visit items that were scanned by some other thread. - for (auto it : to_revisit) { - if (PA_LIKELY(it->is_visited.load(std::memory_order_relaxed))) { - continue; - } - // Don't bail out here if the item is being visited by another thread. - // This is helpful to guarantee forward progress if the other thread - // is making slow progress. - it->is_being_visited.store(true, std::memory_order_relaxed); - f(it->value); - it->is_visited.store(true, std::memory_order_relaxed); - } - - worklist_.fully_visited_.store(true, std::memory_order_release); -} - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_RACEFUL_WORKLIST_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/scan_loop.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/scan_loop.h deleted file mode 100644 index c9036e59bb..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/scan_loop.h +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_SCAN_LOOP_H_ -#define PARTITION_ALLOC_STARSCAN_SCAN_LOOP_H_ - -#include -#include - -#include "partition_alloc/build_config.h" -#include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_buildflags.h" -#include "partition_alloc/partition_alloc_check.h" -#include "partition_alloc/partition_alloc_config.h" -#include "partition_alloc/starscan/starscan_fwd.h" -#include "partition_alloc/tagging.h" - -#if PA_BUILDFLAG(PA_ARCH_CPU_X86_64) -// Include order is important, so we disable formatting. -// clang-format off -// Including these headers directly should generally be avoided. For the -// scanning loop, we check at runtime which SIMD extension we can use. Since -// Chrome is compiled with -msse3 (the minimal requirement), we include the -// headers directly to make the intrinsics available. Another option could be to -// use inline assembly, but that would hinder compiler optimization for -// vectorized instructions. -#include -#include -#include -#include -// clang-format on -#endif - -#if PA_CONFIG(STARSCAN_NEON_SUPPORTED) -#include -#endif - -namespace partition_alloc::internal { - -// Iterates over range of memory using the best available SIMD extension. -// Assumes that 64bit platforms have pool support and the begin pointer of -// incoming ranges are properly aligned. The class is designed around the CRTP -// version of the "template method" (in GoF terms). CRTP is needed for fast -// static dispatch. -template -class ScanLoop { - public: - explicit ScanLoop(SimdSupport simd_type) : simd_type_(simd_type) {} - - ScanLoop(const ScanLoop&) = delete; - ScanLoop& operator=(const ScanLoop&) = delete; - - // Scan input range. Assumes the range is properly aligned. Please note that - // the function doesn't MTE-tag the input range as it assumes that MTE is - // disabled when function is called. See DisableMTEScope for details. - void Run(uintptr_t begin, uintptr_t end); - - private: - const Derived& derived() const { return static_cast(*this); } - Derived& derived() { return static_cast(*this); } - -#if PA_BUILDFLAG(PA_ARCH_CPU_X86_64) - __attribute__((target("avx2"))) void RunAVX2(uintptr_t, uintptr_t); - __attribute__((target("sse4.1"))) void RunSSE4(uintptr_t, uintptr_t); -#endif -#if PA_CONFIG(STARSCAN_NEON_SUPPORTED) - void RunNEON(uintptr_t, uintptr_t); -#endif - - void RunUnvectorized(uintptr_t, uintptr_t); - - SimdSupport simd_type_; -}; - -template -void ScanLoop::Run(uintptr_t begin, uintptr_t end) { -// We allow vectorization only for 64bit since they require support of the -// 64bit regular pool, and only for x86 because a special instruction set is -// required. -#if PA_BUILDFLAG(PA_ARCH_CPU_X86_64) - if (simd_type_ == SimdSupport::kAVX2) { - return RunAVX2(begin, end); - } - if (simd_type_ == SimdSupport::kSSE41) { - return RunSSE4(begin, end); - } -#elif PA_CONFIG(STARSCAN_NEON_SUPPORTED) - if (simd_type_ == SimdSupport::kNEON) { - return RunNEON(begin, end); - } -#endif // PA_CONFIG(STARSCAN_NEON_SUPPORTED) - return RunUnvectorized(begin, end); -} - -template -void ScanLoop::RunUnvectorized(uintptr_t begin, uintptr_t end) { - PA_SCAN_DCHECK(!(begin % sizeof(uintptr_t))); - PA_SCAN_DCHECK(!(end % sizeof(uintptr_t))); -#if PA_BUILDFLAG(HAS_64_BIT_POINTERS) - // If the read value is a pointer into the PA region, it's likely - // MTE-tagged. Piggyback on |mask| to untag, for efficiency. - const uintptr_t mask = Derived::RegularPoolMask() & kPtrUntagMask; - const uintptr_t base = Derived::RegularPoolBase(); -#endif // PA_BUILDFLAG(HAS_64_BIT_POINTERS) - for (; begin < end; begin += sizeof(uintptr_t)) { - // Read the region word-by-word. Everything that we read is a potential - // pointer to or inside an object on heap. Such an object should be - // quarantined, if attempted to free. - // - // Keep it MTE-untagged. See DisableMTEScope for details. - const uintptr_t maybe_ptr = *reinterpret_cast(begin); -#if PA_BUILDFLAG(HAS_64_BIT_POINTERS) - if (PA_LIKELY((maybe_ptr & mask) != base)) { - continue; - } -#else - if (!maybe_ptr) { - continue; - } -#endif // PA_BUILDFLAG(HAS_64_BIT_POINTERS) - derived().CheckPointer(maybe_ptr); - } -} - -#if PA_BUILDFLAG(PA_ARCH_CPU_X86_64) -template -__attribute__((target("avx2"))) void ScanLoop::RunAVX2(uintptr_t begin, - uintptr_t end) { - static constexpr size_t kAlignmentRequirement = 32; - static constexpr size_t kWordsInVector = 4; - static constexpr size_t kBytesInVector = kWordsInVector * sizeof(uintptr_t); - PA_SCAN_DCHECK(!(begin % kAlignmentRequirement)); - // Stick to integer instructions. This brings slightly better throughput. For - // example, according to the Intel docs, on Broadwell and Haswell the CPI of - // vmovdqa (_mm256_load_si256) is twice smaller (0.25) than that of vmovapd - // (_mm256_load_pd). - const __m256i vbase = _mm256_set1_epi64x(derived().RegularPoolBase()); - // If the read value is a pointer into the PA region, it's likely - // MTE-tagged. Piggyback on |regular_pool_mask| to untag, for efficiency. - const __m256i regular_pool_mask = - _mm256_set1_epi64x(derived().RegularPoolMask() & kPtrUntagMask); - - static_assert(sizeof(__m256i) == kBytesInVector); - for (; begin <= (end - kBytesInVector); begin += kBytesInVector) { - // Keep it MTE-untagged. See DisableMTEScope for details. - const __m256i maybe_ptrs = - _mm256_load_si256(reinterpret_cast<__m256i*>(begin)); - const __m256i vand = _mm256_and_si256(maybe_ptrs, regular_pool_mask); - const __m256i vcmp = _mm256_cmpeq_epi64(vand, vbase); - const int mask = _mm256_movemask_pd(_mm256_castsi256_pd(vcmp)); - if (PA_LIKELY(!mask)) { - continue; - } - // It's important to extract pointers from the already loaded vector. - // Otherwise, new loads can break in-pool assumption checked above. - if (mask & 0b0001) { - derived().CheckPointer(_mm256_extract_epi64(maybe_ptrs, 0)); - } - if (mask & 0b0010) { - derived().CheckPointer(_mm256_extract_epi64(maybe_ptrs, 1)); - } - if (mask & 0b0100) { - derived().CheckPointer(_mm256_extract_epi64(maybe_ptrs, 2)); - } - if (mask & 0b1000) { - derived().CheckPointer(_mm256_extract_epi64(maybe_ptrs, 3)); - } - } - // Run unvectorized on the remainder of the region. - RunUnvectorized(begin, end); -} - -template -__attribute__((target("sse4.1"))) void ScanLoop::RunSSE4( - uintptr_t begin, - uintptr_t end) { - static constexpr size_t kAlignmentRequirement = 16; - static constexpr size_t kWordsInVector = 2; - static constexpr size_t kBytesInVector = kWordsInVector * sizeof(uintptr_t); - PA_SCAN_DCHECK(!(begin % kAlignmentRequirement)); - const __m128i vbase = _mm_set1_epi64x(derived().RegularPoolBase()); - // If the read value is a pointer into the PA region, it's likely - // MTE-tagged. Piggyback on |regular_pool_mask| to untag, for efficiency. - const __m128i regular_pool_mask = - _mm_set1_epi64x(derived().RegularPoolMask() & kPtrUntagMask); - - static_assert(sizeof(__m128i) == kBytesInVector); - for (; begin <= (end - kBytesInVector); begin += kBytesInVector) { - // Keep it MTE-untagged. See DisableMTEScope for details. - const __m128i maybe_ptrs = - _mm_loadu_si128(reinterpret_cast<__m128i*>(begin)); - const __m128i vand = _mm_and_si128(maybe_ptrs, regular_pool_mask); - const __m128i vcmp = _mm_cmpeq_epi64(vand, vbase); - const int mask = _mm_movemask_pd(_mm_castsi128_pd(vcmp)); - if (PA_LIKELY(!mask)) { - continue; - } - // It's important to extract pointers from the already loaded vector. - // Otherwise, new loads can break in-pool assumption checked above. - if (mask & 0b01) { - derived().CheckPointer(_mm_cvtsi128_si64(maybe_ptrs)); - } - if (mask & 0b10) { - // The mask is used to move the 4th and 3rd dwords into the second and - // first position. - static constexpr int kSecondWordMask = (3 << 2) | (2 << 0); - const __m128i shuffled = _mm_shuffle_epi32(maybe_ptrs, kSecondWordMask); - derived().CheckPointer(_mm_cvtsi128_si64(shuffled)); - } - } - // Run unvectorized on the remainder of the region. - RunUnvectorized(begin, end); -} -#endif // PA_BUILDFLAG(PA_ARCH_CPU_X86_64) - -#if PA_CONFIG(STARSCAN_NEON_SUPPORTED) -template -void ScanLoop::RunNEON(uintptr_t begin, uintptr_t end) { - static constexpr size_t kAlignmentRequirement = 16; - static constexpr size_t kWordsInVector = 2; - static constexpr size_t kBytesInVector = kWordsInVector * sizeof(uintptr_t); - PA_SCAN_DCHECK(!(begin % kAlignmentRequirement)); - const uint64x2_t vbase = vdupq_n_u64(derived().RegularPoolBase()); - // If the read value is a pointer into the PA region, it's likely - // MTE-tagged. Piggyback on |regular_pool_mask| to untag, for efficiency. - const uint64x2_t regular_pool_mask = - vdupq_n_u64(derived().RegularPoolMask() & kPtrUntagMask); - - for (; begin <= (end - kBytesInVector); begin += kBytesInVector) { - // Keep it MTE-untagged. See DisableMTEScope for details. - const uint64x2_t maybe_ptrs = vld1q_u64(reinterpret_cast(begin)); - const uint64x2_t vand = vandq_u64(maybe_ptrs, regular_pool_mask); - const uint64x2_t vcmp = vceqq_u64(vand, vbase); - const uint32_t max = vmaxvq_u32(vreinterpretq_u32_u64(vcmp)); - if (PA_LIKELY(!max)) { - continue; - } - // It's important to extract pointers from the already loaded vector. - // Otherwise, new loads can break in-pool assumption checked above. - if (vgetq_lane_u64(vcmp, 0)) { - derived().CheckPointer(vgetq_lane_u64(maybe_ptrs, 0)); - } - if (vgetq_lane_u64(vcmp, 1)) { - derived().CheckPointer(vgetq_lane_u64(maybe_ptrs, 1)); - } - } - // Run unvectorized on the remainder of the region. - RunUnvectorized(begin, end); -} -#endif // PA_CONFIG(STARSCAN_NEON_SUPPORTED) - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_SCAN_LOOP_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/snapshot.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/snapshot.cc deleted file mode 100644 index 705538af7d..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/snapshot.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "partition_alloc/starscan/snapshot.h" - -#include -#include - -#include "partition_alloc/internal_allocator.h" -#include "partition_alloc/partition_alloc_check.h" -#include "partition_alloc/starscan/pcscan_internal.h" - -namespace partition_alloc::internal { - -std::unique_ptr StarScanSnapshot::Create( - const PCScanInternal& pcscan) { - // Create unique_ptr object to avoid presubmit error. - std::unique_ptr snapshot(new StarScanSnapshot(pcscan)); - return snapshot; -} - -StarScanSnapshot::StarScanSnapshot(const PCScanInternal& pcscan) { - PA_DCHECK(pcscan.is_initialized()); - std::lock_guard lock(pcscan.roots_mutex_); - - for (const auto& root : pcscan.scannable_roots()) { - const auto& super_pages = root.second; - clear_worklist_.Push(super_pages.begin(), super_pages.end()); - scan_worklist_.Push(super_pages.begin(), super_pages.end()); - sweep_worklist_.Push(super_pages.begin(), super_pages.end()); - if (pcscan.WriteProtectionEnabled()) { - unprotect_worklist_.Push(super_pages.begin(), super_pages.end()); - } - } - - for (const auto& root : pcscan.nonscannable_roots()) { - const auto& super_pages = root.second; - clear_worklist_.Push(super_pages.begin(), super_pages.end()); - sweep_worklist_.Push(super_pages.begin(), super_pages.end()); - if (pcscan.WriteProtectionEnabled()) { - unprotect_worklist_.Push(super_pages.begin(), super_pages.end()); - } - } -} - -StarScanSnapshot::~StarScanSnapshot() = default; - -} // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/snapshot.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/snapshot.h deleted file mode 100644 index 92a1a81d74..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/snapshot.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_SNAPSHOT_H_ -#define PARTITION_ALLOC_STARSCAN_SNAPSHOT_H_ - -#include -#include - -#include "partition_alloc/internal_allocator_forward.h" -#include "partition_alloc/starscan/pcscan_internal.h" -#include "partition_alloc/starscan/raceful_worklist.h" - -namespace partition_alloc::internal { - -class StarScanSnapshot final : public InternalPartitionAllocated { - public: - using SuperPageBase = uintptr_t; - using SuperPagesWorklist = RacefulWorklist; - - class ViewBase { - public: - template - void VisitConcurrently(Function); - - template - void VisitNonConcurrently(Function); - - protected: - explicit ViewBase(SuperPagesWorklist& worklist) : worklist_(worklist) {} - - private: - SuperPagesWorklist& worklist_; - }; - - class ClearingView : public ViewBase { - public: - inline explicit ClearingView(StarScanSnapshot& snapshot); - }; - class ScanningView : public ViewBase { - public: - inline explicit ScanningView(StarScanSnapshot& snapshot); - }; - class SweepingView : public ViewBase { - public: - inline explicit SweepingView(StarScanSnapshot& snapshot); - }; - class UnprotectingView : public ViewBase { - public: - inline explicit UnprotectingView(StarScanSnapshot& snapshot); - }; - - static std::unique_ptr Create(const PCScanInternal&); - - StarScanSnapshot(const StarScanSnapshot&) = delete; - StarScanSnapshot& operator=(const StarScanSnapshot&) = delete; - - ~StarScanSnapshot(); - - private: - explicit StarScanSnapshot(const PCScanInternal&); - - SuperPagesWorklist clear_worklist_; - SuperPagesWorklist scan_worklist_; - SuperPagesWorklist unprotect_worklist_; - SuperPagesWorklist sweep_worklist_; -}; - -template -void StarScanSnapshot::ViewBase::VisitConcurrently(Function f) { - SuperPagesWorklist::RandomizedView view(worklist_); - view.Visit(std::move(f)); -} - -template -void StarScanSnapshot::ViewBase::VisitNonConcurrently(Function f) { - worklist_.VisitNonConcurrently(std::move(f)); -} - -StarScanSnapshot::ClearingView::ClearingView(StarScanSnapshot& snapshot) - : StarScanSnapshot::ViewBase(snapshot.clear_worklist_) {} - -StarScanSnapshot::ScanningView::ScanningView(StarScanSnapshot& snapshot) - : StarScanSnapshot::ViewBase(snapshot.scan_worklist_) {} - -StarScanSnapshot::SweepingView::SweepingView(StarScanSnapshot& snapshot) - : StarScanSnapshot::ViewBase(snapshot.sweep_worklist_) {} - -StarScanSnapshot::UnprotectingView::UnprotectingView(StarScanSnapshot& snapshot) - : StarScanSnapshot::ViewBase(snapshot.unprotect_worklist_) {} - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_SNAPSHOT_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/starscan_fwd.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/starscan_fwd.h deleted file mode 100644 index 8c56982ec6..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/starscan_fwd.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_STARSCAN_FWD_H_ -#define PARTITION_ALLOC_STARSCAN_STARSCAN_FWD_H_ - -#include - -namespace partition_alloc::internal { - -// Defines what thread executes a StarScan task. -enum class Context { - // For tasks executed from mutator threads (safepoints). - kMutator, - // For concurrent scanner tasks. - kScanner -}; - -// Defines ISA extension for scanning. -enum class SimdSupport : uint8_t { - kUnvectorized, - kSSE41, - kAVX2, - kNEON, -}; - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_STARSCAN_FWD_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap.h deleted file mode 100644 index d90ef89176..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap.h +++ /dev/null @@ -1,491 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_STATE_BITMAP_H_ -#define PARTITION_ALLOC_STARSCAN_STATE_BITMAP_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "partition_alloc/partition_alloc_base/bits.h" -#include "partition_alloc/partition_alloc_base/compiler_specific.h" -#include "partition_alloc/partition_alloc_check.h" - -namespace partition_alloc::internal { - -// Bitmap which tracks allocation states. An allocation can be in one of 3 -// states: -// - freed (00), -// - allocated (11), -// - quarantined (01 or 10, depending on the *Scan epoch). -// -// The state machine of allocation states: -// +-------------+ +-------------+ -// | | malloc() | | -// | Freed +--------------->| Allocated | -// | (00) | (or 11) | (11) | -// | | | | -// +-------------+ +------+------+ -// ^ | -// | | -// real_free() | (and 00) free() | (and 01(10)) -// | | -// | +-------------+ | -// | | | | -// +-------+ Quarantined |<-------+ -// | (01,10) | -// | | -// +-------------+ -// ^ | -// | mark() | -// +-----------+ -// (xor 11) -// -// The bitmap can be safely accessed from multiple threads, but this doesn't -// imply visibility on the data (i.e. no ordering guaranties, since relaxed -// atomics are used underneath). The bitmap itself must be created inside a -// page, size and alignment of which are specified as template arguments -// |PageSize| and |PageAlignment|. |AllocationAlignment| specifies the minimal -// alignment of objects that are allocated inside a page (serves as the -// granularity in the bitmap). -template -class StateBitmap final { - enum class State : uint8_t { - kFreed = 0b00, - kQuarantined1 = 0b01, - kQuarantined2 = 0b10, - kAlloced = 0b11, - kMaxValue = kAlloced, - }; - - using CellType = uintptr_t; - static constexpr size_t kBitsPerCell = sizeof(CellType) * CHAR_BIT; - static constexpr size_t kBitsNeededForAllocation = - std::bit_width(static_cast(State::kMaxValue)); - static constexpr CellType kStateMask = (1 << kBitsNeededForAllocation) - 1; - - static constexpr size_t kBitmapSize = - (PageSize + ((kBitsPerCell * AllocationAlignment) - 1)) / - (kBitsPerCell * AllocationAlignment) * kBitsNeededForAllocation; - static constexpr size_t kPageOffsetMask = PageAlignment - 1; - static constexpr size_t kPageBaseMask = ~kPageOffsetMask; - - public: - using Epoch = size_t; - - static constexpr size_t kPageSize = PageSize; - static constexpr size_t kPageAlignment = PageAlignment; - static constexpr size_t kAllocationAlignment = AllocationAlignment; - static constexpr size_t kMaxEntries = - (kBitmapSize / kBitsNeededForAllocation) * kBitsPerCell; - - inline StateBitmap(); - - // Sets the bits corresponding to |address| as allocated. - PA_ALWAYS_INLINE void Allocate(uintptr_t address); - - // Sets the bits corresponding to |address| as quarantined. Must be called - // only once, in which case returns |true|. Otherwise, if the object was - // already quarantined or freed before, returns |false|. - PA_ALWAYS_INLINE bool Quarantine(uintptr_t address, Epoch epoch); - - // Marks ("promotes") quarantined object. Returns |true| on success, otherwise - // |false| if the object was marked before. - PA_ALWAYS_INLINE bool MarkQuarantinedAsReachable(uintptr_t address, - Epoch epoch); - - // Sets the bits corresponding to |address| as freed. - PA_ALWAYS_INLINE void Free(uintptr_t address); - - // Getters that check object state. - PA_ALWAYS_INLINE bool IsAllocated(uintptr_t address) const; - PA_ALWAYS_INLINE bool IsQuarantined(uintptr_t address) const; - PA_ALWAYS_INLINE bool IsFreed(uintptr_t address) const; - - // Iterate objects depending on their state. - // - // The callback is of type - // void(uintptr_t object_start) - template - inline void IterateAllocated(Callback) const; - // The callback is of type - // void(uintptr_t object_start) - template ()(0), 0) = 0> - inline void IterateQuarantined(Callback) const; - // The callback is of type - // void(uintptr_t object_start, bool is_marked) - template ()(0, true), 0) = 0> - inline void IterateQuarantined(size_t epoch, Callback) const; - // The callback is of type - // void(uintptr_t object_start) - template - inline void IterateUnmarkedQuarantined(size_t epoch, Callback) const; - // The callback is of type - // void(uintptr_t object_start) - // The function is similar as above, but it also frees (clears) the iterated - // bits. - template - inline void IterateUnmarkedQuarantinedAndFree(size_t epoch, Callback); - - inline void Clear(); - - private: - std::atomic& AsAtomicCell(size_t cell_index) { - return reinterpret_cast&>(bitmap_[cell_index]); - } - const std::atomic& AsAtomicCell(size_t cell_index) const { - return reinterpret_cast&>(bitmap_[cell_index]); - } - - PA_ALWAYS_INLINE unsigned GetBits(uintptr_t address) const; - - struct FilterQuarantine { - PA_ALWAYS_INLINE bool operator()(CellType cell) const; - const size_t epoch; - }; - - struct FilterUnmarkedQuarantine { - PA_ALWAYS_INLINE bool operator()(CellType cell) const; - const size_t epoch; - }; - - struct FilterAllocated { - PA_ALWAYS_INLINE bool operator()(CellType cell) const; - const size_t epoch; - }; - - // Simply calls the callback. - struct SimpleCallbackForwarder { - PA_ALWAYS_INLINE explicit SimpleCallbackForwarder(size_t epoch) {} - - template - PA_ALWAYS_INLINE void operator()(Callback, - uintptr_t pointer, - CellType bits) const; - }; - - // Calls the callback and passes a bool argument, indicating whether a - // quarantine object is marked or not. - struct QuarantineCallbackForwarder { - PA_ALWAYS_INLINE explicit QuarantineCallbackForwarder(size_t epoch) - : is_unmarked{epoch} {} - - template - PA_ALWAYS_INLINE void operator()(Callback, - uintptr_t pointer, - CellType bits) const; - FilterUnmarkedQuarantine is_unmarked; - }; - - template - inline void IterateImpl(size_t epoch, Callback); - - PA_ALWAYS_INLINE CellType LoadCell(size_t cell_index) const; - PA_ALWAYS_INLINE static constexpr std::pair - AllocationIndexAndBit(uintptr_t); - - std::array bitmap_; -}; - -// The constructor can be omitted, but the Chromium's clang plugin wrongly -// warns that the type is not trivially constructible. -template -inline StateBitmap:: - StateBitmap() = default; - -template -PA_ALWAYS_INLINE void -StateBitmap::Allocate( - uintptr_t address) { - PA_SCAN_DCHECK(IsFreed(address)); - auto [cell_index, object_bit] = AllocationIndexAndBit(address); - const CellType mask = static_cast(State::kAlloced) << object_bit; - auto& cell = AsAtomicCell(cell_index); - cell.fetch_or(mask, std::memory_order_relaxed); -} - -template -PA_ALWAYS_INLINE bool -StateBitmap::Quarantine( - uintptr_t address, - Epoch epoch) { - // *Scan is enabled at runtime, which means that we can quarantine allocation, - // that was previously not recorded in the bitmap. Hence, we can't reliably - // check transition from kAlloced to kQuarantined. - static_assert((~static_cast(State::kQuarantined1) & kStateMask) == - (static_cast(State::kQuarantined2) & kStateMask), - "kQuarantined1 must be inverted kQuarantined2"); - const State quarantine_state = - epoch & 0b1 ? State::kQuarantined1 : State::kQuarantined2; - auto [cell_index, object_bit] = AllocationIndexAndBit(address); - const CellType mask = - ~(static_cast(quarantine_state) << object_bit); - auto& cell = AsAtomicCell(cell_index); - const CellType cell_before = cell.fetch_and(mask, std::memory_order_relaxed); - // Check if the previous state was also quarantined. - return __builtin_popcount(static_cast((cell_before >> object_bit) & - kStateMask)) != 1; -} - -template -PA_ALWAYS_INLINE bool -StateBitmap:: - MarkQuarantinedAsReachable(uintptr_t address, Epoch epoch) { - static_assert((~static_cast(State::kQuarantined1) & kStateMask) == - (static_cast(State::kQuarantined2) & kStateMask), - "kQuarantined1 must be inverted kQuarantined2"); - const State quarantine_state_old = - epoch & 0b1 ? State::kQuarantined2 : State::kQuarantined1; - auto [cell_index, object_bit] = AllocationIndexAndBit(address); - const CellType clear_mask = - ~(static_cast(State::kAlloced) << object_bit); - const CellType set_mask_old = static_cast(quarantine_state_old) - << object_bit; - const CellType xor_mask = static_cast(0b11) << object_bit; - auto& cell = AsAtomicCell(cell_index); - CellType expected = - (cell.load(std::memory_order_relaxed) & clear_mask) | set_mask_old; - CellType desired = expected ^ xor_mask; - while (PA_UNLIKELY(!cell.compare_exchange_weak(expected, desired, - std::memory_order_relaxed, - std::memory_order_relaxed))) { - // First check if the object was already marked before or in parallel. - if ((expected & set_mask_old) == 0) { - // Check that the bits can't be in any state other than - // marked-quarantined. - PA_SCAN_DCHECK( - ((expected >> object_bit) & kStateMask) == - (~static_cast(quarantine_state_old) & kStateMask)); - return false; - } - // Otherwise, some other bits in the cell were concurrently changed. Update - // desired and retry. - desired = expected ^ xor_mask; - } - return true; -} - -template -PA_ALWAYS_INLINE void -StateBitmap::Free( - uintptr_t address) { - // *Scan is enabled at runtime, which means that we can free an allocation, - // that was previously not recorded as quarantined in the bitmap. Hence, we - // can't reliably check the transition from kQuarantined to kFreed. - static_assert((~static_cast(State::kAlloced) & kStateMask) == - (static_cast(State::kFreed) & kStateMask), - "kFreed must be inverted kAlloced"); - auto [cell_index, object_bit] = AllocationIndexAndBit(address); - const CellType mask = ~(static_cast(State::kAlloced) << object_bit); - auto& cell = AsAtomicCell(cell_index); - cell.fetch_and(mask, std::memory_order_relaxed); -} - -template -PA_ALWAYS_INLINE bool -StateBitmap::IsAllocated( - uintptr_t address) const { - return GetBits(address) == static_cast(State::kAlloced); -} - -template -PA_ALWAYS_INLINE bool -StateBitmap::IsQuarantined( - uintptr_t address) const { - // On x86 CPI of popcnt is the same as tzcnt, so we use it instead of tzcnt + - // inversion. - return __builtin_popcount(GetBits(address)) == 1; -} - -template -PA_ALWAYS_INLINE bool -StateBitmap::IsFreed( - uintptr_t address) const { - return GetBits(address) == static_cast(State::kFreed); -} - -template -PA_ALWAYS_INLINE - typename StateBitmap::CellType - StateBitmap::LoadCell( - size_t cell_index) const { - return AsAtomicCell(cell_index).load(std::memory_order_relaxed); -} - -template -PA_ALWAYS_INLINE constexpr std::pair -StateBitmap:: - AllocationIndexAndBit(uintptr_t address) { - const uintptr_t offset_in_page = address & kPageOffsetMask; - const size_t allocation_number = - (offset_in_page / kAllocationAlignment) * kBitsNeededForAllocation; - const size_t cell_index = allocation_number / kBitsPerCell; - PA_SCAN_DCHECK(kBitmapSize > cell_index); - const size_t bit = allocation_number % kBitsPerCell; - return {cell_index, bit}; -} - -template -unsigned StateBitmap::GetBits( - uintptr_t address) const { - auto [cell_index, object_bit] = AllocationIndexAndBit(address); - return (LoadCell(cell_index) >> object_bit) & kStateMask; -} - -template -bool StateBitmap:: - FilterQuarantine::operator()(CellType bits) const { - return __builtin_popcount(static_cast(bits)) == 1; -} - -template -bool StateBitmap:: - FilterUnmarkedQuarantine::operator()(CellType bits) const { - // Truth table: - // epoch & 1 | bits | result - // 0 | 01 | 1 - // 1 | 10 | 1 - // * | ** | 0 - return bits - (epoch & 0b01) == 0b01; -} - -template -bool StateBitmap:: - FilterAllocated::operator()(CellType bits) const { - return bits == 0b11; -} - -template -template -PA_ALWAYS_INLINE void -StateBitmap:: - SimpleCallbackForwarder::operator()(Callback callback, - uintptr_t pointer, - CellType bits) const { - callback(pointer); -} - -template -template -PA_ALWAYS_INLINE void -StateBitmap:: - QuarantineCallbackForwarder::operator()(Callback callback, - uintptr_t pointer, - CellType bits) const { - callback(pointer, !is_unmarked(bits)); -} - -template -template -inline void -StateBitmap::IterateImpl( - size_t epoch, - Callback callback) { - // The bitmap (|this|) is allocated inside the page with |kPageAlignment|. - Filter filter{epoch}; - CallbackForwarder callback_forwarder{epoch}; - const uintptr_t base = reinterpret_cast(this) & kPageBaseMask; - for (size_t cell_index = 0; cell_index < kBitmapSize; ++cell_index) { - CellType value = LoadCell(cell_index); - while (value) { - const size_t trailing_zeroes = - static_cast(std::countr_zero(value) & ~0b1); - const size_t clear_value_mask = - ~(static_cast(kStateMask) << trailing_zeroes); - const CellType bits = (value >> trailing_zeroes) & kStateMask; - if (!filter(bits)) { - // Clear current object bit in temporary value to advance iteration. - value &= clear_value_mask; - continue; - } - const size_t object_number = - (cell_index * kBitsPerCell) + trailing_zeroes; - const uintptr_t object_address = - base + - (object_number * kAllocationAlignment / kBitsNeededForAllocation); - - callback_forwarder(callback, object_address, bits); - - if (Clear) { - // Clear the current bits. - AsAtomicCell(cell_index) - .fetch_and(clear_value_mask, std::memory_order_relaxed); - } - - // Clear current object bit in temporary value to advance iteration. - value &= clear_value_mask; - } - } -} - -template -template -inline void -StateBitmap::IterateAllocated( - Callback callback) const { - const_cast(this) - ->IterateImpl( - 0, std::move(callback)); -} - -template -template ()(0), 0)> -inline void -StateBitmap::IterateQuarantined( - Callback callback) const { - const_cast(this) - ->IterateImpl( - 0, std::move(callback)); -} - -template -template ()(0, true), 0)> -inline void -StateBitmap::IterateQuarantined( - size_t epoch, - Callback callback) const { - const_cast(this) - ->IterateImpl(epoch, std::move(callback)); -} - -template -template -inline void StateBitmap:: - IterateUnmarkedQuarantined(size_t epoch, Callback callback) const { - const_cast(this) - ->IterateImpl(epoch, std::move(callback)); -} - -template -template -inline void StateBitmap:: - IterateUnmarkedQuarantinedAndFree(size_t epoch, Callback callback) { - IterateImpl(epoch, std::move(callback)); -} - -template -void StateBitmap::Clear() { - std::fill(bitmap_.begin(), bitmap_.end(), '\0'); -} - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_STATE_BITMAP_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_collector.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_collector.cc deleted file mode 100644 index e05f045f6b..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_collector.cc +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "partition_alloc/starscan/stats_collector.h" - -#include "partition_alloc/internal_allocator.h" -#include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/starscan/logging.h" -#include "partition_alloc/starscan/stats_reporter.h" - -namespace partition_alloc::internal { - -StatsCollector::StatsCollector(const char* process_name, - size_t quarantine_last_size) - : process_name_(process_name), - quarantine_last_size_(quarantine_last_size) {} - -StatsCollector::~StatsCollector() = default; - -base::TimeDelta StatsCollector::GetOverallTime() const { - return GetTimeImpl(mutator_trace_events_, - MutatorId::kOverall) + - GetTimeImpl(scanner_trace_events_, - ScannerId::kOverall); -} - -void StatsCollector::ReportTracesAndHists( - partition_alloc::StatsReporter& reporter) const { - ReportTracesAndHistsImpl(reporter, mutator_trace_events_); - ReportTracesAndHistsImpl(reporter, scanner_trace_events_); - ReportSurvivalRate(reporter); -} - -template -base::TimeDelta StatsCollector::GetTimeImpl( - const DeferredTraceEventMap& event_map, - IdType id) const { - base::TimeDelta overall; - for (const auto& tid_and_events : event_map.get_underlying_map_unsafe()) { - const auto& events = tid_and_events.second; - const auto& event = events[static_cast(id)]; - overall += (event.end_time - event.start_time); - } - return overall; -} - -template -void StatsCollector::ReportTracesAndHistsImpl( - partition_alloc::StatsReporter& reporter, - const DeferredTraceEventMap& event_map) const { - std::array(IdType::kNumIds)> - accumulated_events{}; - // First, report traces and accumulate each trace scope to report UMA hists. - for (const auto& tid_and_events : event_map.get_underlying_map_unsafe()) { - const internal::base::PlatformThreadId tid = tid_and_events.first; - const auto& events = tid_and_events.second; - PA_DCHECK(accumulated_events.size() == events.size()); - for (size_t id = 0; id < events.size(); ++id) { - const auto& event = events[id]; - if (event.start_time.is_null()) { - // If start_time is null, the event was never triggered, e.g. safepoint - // bailed out if started at the end of scanning. - PA_DCHECK(event.end_time.is_null()); - continue; - } - reporter.ReportTraceEvent(static_cast>(id), tid, - event.start_time.ToInternalValue(), - event.end_time.ToInternalValue()); - accumulated_events[id] += (event.end_time - event.start_time); - } - } - // Report UMA if process_name is set. - if (!process_name_) { - return; - } - for (size_t id = 0; id < accumulated_events.size(); ++id) { - if (accumulated_events[id].is_zero()) { - continue; - } - reporter.ReportStats(ToUMAString(static_cast>(id)).c_str(), - accumulated_events[id].InMicroseconds()); - } -} - -void StatsCollector::ReportSurvivalRate( - partition_alloc::StatsReporter& reporter) const { - const double survived_rate = - static_cast(survived_quarantine_size()) / quarantine_last_size_; - reporter.ReportSurvivedQuarantineSize(survived_quarantine_size()); - reporter.ReportSurvivedQuarantinePercent(survived_rate); - PA_PCSCAN_VLOG(2) << "quarantine size: " << quarantine_last_size_ << " -> " - << survived_quarantine_size() - << ", swept bytes: " << swept_size() - << ", survival rate: " << survived_rate; - if (discarded_quarantine_size_) { - PA_PCSCAN_VLOG(2) << "discarded quarantine size: " - << discarded_quarantine_size_; - } -} - -template base::TimeDelta StatsCollector::GetTimeImpl( - const DeferredTraceEventMap&, - IdType) const; -template base::TimeDelta StatsCollector::GetTimeImpl( - const DeferredTraceEventMap&, - IdType) const; - -template void StatsCollector::ReportTracesAndHistsImpl( - partition_alloc::StatsReporter& reporter, - const DeferredTraceEventMap&) const; -template void StatsCollector::ReportTracesAndHistsImpl( - partition_alloc::StatsReporter& reporter, - const DeferredTraceEventMap&) const; - -} // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_collector.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_collector.h deleted file mode 100644 index 055a6f8bbf..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_collector.h +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_STATS_COLLECTOR_H_ -#define PARTITION_ALLOC_STARSCAN_STATS_COLLECTOR_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "partition_alloc/internal_allocator_forward.h" -#include "partition_alloc/partition_alloc_base/threading/platform_thread.h" -#include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_alloc_check.h" -#include "partition_alloc/starscan/starscan_fwd.h" - -namespace partition_alloc { - -class StatsReporter; - -namespace internal { - -#define FOR_ALL_PCSCAN_SCANNER_SCOPES(V) \ - V(Clear) \ - V(Scan) \ - V(Sweep) \ - V(Overall) - -#define FOR_ALL_PCSCAN_MUTATOR_SCOPES(V) \ - V(Clear) \ - V(ScanStack) \ - V(Scan) \ - V(Overall) - -class StatsCollector final { - public: - enum class ScannerId { -#define DECLARE_ENUM(name) k##name, - FOR_ALL_PCSCAN_SCANNER_SCOPES(DECLARE_ENUM) -#undef DECLARE_ENUM - kNumIds, - }; - - enum class MutatorId { -#define DECLARE_ENUM(name) k##name, - FOR_ALL_PCSCAN_MUTATOR_SCOPES(DECLARE_ENUM) -#undef DECLARE_ENUM - kNumIds, - }; - - template - using IdType = - std::conditional_t; - - // We don't immediately trace events, but instead defer it until scanning is - // done. This is needed to avoid unpredictable work that can be done by traces - // (e.g. recursive mutex lock). - struct DeferredTraceEvent { - base::TimeTicks start_time; - base::TimeTicks end_time; - }; - - // Thread-safe hash-map that maps thread id to scanner events. Doesn't - // accumulate events, i.e. every event can only be registered once. - template - class DeferredTraceEventMap final { - public: - using IdType = StatsCollector::IdType; - using PerThreadEvents = - std::array(IdType::kNumIds)>; - using UnderlyingMap = - std::unordered_map, - std::equal_to<>, - internal::InternalAllocator< - std::pair>>; - - inline void RegisterBeginEventFromCurrentThread(IdType id); - inline void RegisterEndEventFromCurrentThread(IdType id); - - const UnderlyingMap& get_underlying_map_unsafe() const { return events_; } - - private: - std::mutex mutex_; - UnderlyingMap events_; - }; - - template - class Scope final { - public: - Scope(StatsCollector& stats, IdType type) - : stats_(stats), type_(type) { - stats_.RegisterBeginEventFromCurrentThread(type); - } - - Scope(const Scope&) = delete; - Scope& operator=(const Scope&) = delete; - - ~Scope() { stats_.RegisterEndEventFromCurrentThread(type_); } - - private: - StatsCollector& stats_; - IdType type_; - }; - - using ScannerScope = Scope; - using MutatorScope = Scope; - - StatsCollector(const char* process_name, size_t quarantine_last_size); - - StatsCollector(const StatsCollector&) = delete; - StatsCollector& operator=(const StatsCollector&) = delete; - - ~StatsCollector(); - - void IncreaseSurvivedQuarantineSize(size_t size) { - survived_quarantine_size_.fetch_add(size, std::memory_order_relaxed); - } - size_t survived_quarantine_size() const { - return survived_quarantine_size_.load(std::memory_order_relaxed); - } - - void IncreaseSweptSize(size_t size) { swept_size_ += size; } - size_t swept_size() const { return swept_size_; } - - void IncreaseDiscardedQuarantineSize(size_t size) { - discarded_quarantine_size_ += size; - } - - base::TimeDelta GetOverallTime() const; - void ReportTracesAndHists(partition_alloc::StatsReporter& reporter) const; - - private: - using MetadataString = std::basic_string, - internal::InternalAllocator>; - - MetadataString ToUMAString(ScannerId id) const; - MetadataString ToUMAString(MutatorId id) const; - - void RegisterBeginEventFromCurrentThread(MutatorId id) { - mutator_trace_events_.RegisterBeginEventFromCurrentThread(id); - } - void RegisterEndEventFromCurrentThread(MutatorId id) { - mutator_trace_events_.RegisterEndEventFromCurrentThread(id); - } - void RegisterBeginEventFromCurrentThread(ScannerId id) { - scanner_trace_events_.RegisterBeginEventFromCurrentThread(id); - } - void RegisterEndEventFromCurrentThread(ScannerId id) { - scanner_trace_events_.RegisterEndEventFromCurrentThread(id); - } - - template - base::TimeDelta GetTimeImpl(const DeferredTraceEventMap& event_map, - IdType id) const; - - template - void ReportTracesAndHistsImpl( - partition_alloc::StatsReporter& reporter, - const DeferredTraceEventMap& event_map) const; - - void ReportSurvivalRate(partition_alloc::StatsReporter& reporter) const; - - DeferredTraceEventMap mutator_trace_events_; - DeferredTraceEventMap scanner_trace_events_; - - std::atomic survived_quarantine_size_{0u}; - size_t swept_size_ = 0u; - size_t discarded_quarantine_size_ = 0u; - const char* process_name_ = nullptr; - const size_t quarantine_last_size_ = 0u; -}; - -template -inline void StatsCollector::DeferredTraceEventMap< - context>::RegisterBeginEventFromCurrentThread(IdType id) { - std::lock_guard lock(mutex_); - const auto tid = base::PlatformThread::CurrentId(); - const auto now = base::TimeTicks::Now(); - auto& event_array = events_[tid]; - auto& event = event_array[static_cast(id)]; - PA_DCHECK(event.start_time.is_null()); - PA_DCHECK(event.end_time.is_null()); - event.start_time = now; -} - -template -inline void StatsCollector::DeferredTraceEventMap< - context>::RegisterEndEventFromCurrentThread(IdType id) { - std::lock_guard lock(mutex_); - const auto tid = base::PlatformThread::CurrentId(); - const auto now = base::TimeTicks::Now(); - auto& event_array = events_[tid]; - auto& event = event_array[static_cast(id)]; - PA_DCHECK(!event.start_time.is_null()); - PA_DCHECK(event.end_time.is_null()); - event.end_time = now; -} - -inline StatsCollector::MetadataString StatsCollector::ToUMAString( - ScannerId id) const { - PA_DCHECK(process_name_); - const MetadataString process_name = process_name_; - switch (id) { - case ScannerId::kClear: - return "PA.PCScan." + process_name + ".Scanner.Clear"; - case ScannerId::kScan: - return "PA.PCScan." + process_name + ".Scanner.Scan"; - case ScannerId::kSweep: - return "PA.PCScan." + process_name + ".Scanner.Sweep"; - case ScannerId::kOverall: - return "PA.PCScan." + process_name + ".Scanner"; - case ScannerId::kNumIds: - __builtin_unreachable(); - } -} - -inline StatsCollector::MetadataString StatsCollector::ToUMAString( - MutatorId id) const { - PA_DCHECK(process_name_); - const MetadataString process_name = process_name_; - switch (id) { - case MutatorId::kClear: - return "PA.PCScan." + process_name + ".Mutator.Clear"; - case MutatorId::kScanStack: - return "PA.PCScan." + process_name + ".Mutator.ScanStack"; - case MutatorId::kScan: - return "PA.PCScan." + process_name + ".Mutator.Scan"; - case MutatorId::kOverall: - return "PA.PCScan." + process_name + ".Mutator"; - case MutatorId::kNumIds: - __builtin_unreachable(); - } -} - -#undef FOR_ALL_PCSCAN_MUTATOR_SCOPES -#undef FOR_ALL_PCSCAN_SCANNER_SCOPES - -} // namespace internal -} // namespace partition_alloc - -#endif // PARTITION_ALLOC_STARSCAN_STATS_COLLECTOR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_reporter.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_reporter.h deleted file mode 100644 index cf355105a4..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/stats_reporter.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_STATS_REPORTER_H_ -#define PARTITION_ALLOC_STARSCAN_STATS_REPORTER_H_ - -#include "partition_alloc/partition_alloc_base/threading/platform_thread.h" -#include "partition_alloc/starscan/stats_collector.h" - -namespace partition_alloc { - -// StatsReporter is a wrapper to invoke TRACE_EVENT_BEGIN/END, TRACE_COUNTER1, -// and UmaHistogramTimes. It is used to just remove trace_log and uma -// dependencies from PartitionAlloc. -class StatsReporter { - public: - virtual void ReportTraceEvent(internal::StatsCollector::ScannerId id, - internal::base::PlatformThreadId tid, - int64_t start_time_ticks_internal_value, - int64_t end_time_ticks_internal_value) {} - virtual void ReportTraceEvent(internal::StatsCollector::MutatorId id, - internal::base::PlatformThreadId tid, - int64_t start_time_ticks_internal_value, - int64_t end_time_ticks_internal_value) {} - - virtual void ReportSurvivedQuarantineSize(size_t survived_size) {} - - virtual void ReportSurvivedQuarantinePercent(double survivied_rate) {} - - virtual void ReportStats(const char* stats_name, int64_t sample_in_usec) {} -}; - -} // namespace partition_alloc - -#endif // PARTITION_ALLOC_STARSCAN_STATS_REPORTER_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.cc deleted file mode 100644 index 27391301fe..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "partition_alloc/starscan/write_protector.h" - -#include -#include - -#include "partition_alloc/address_pool_manager.h" -#include "partition_alloc/build_config.h" -#include "partition_alloc/partition_address_space.h" -#include "partition_alloc/partition_alloc_base/logging.h" -#include "partition_alloc/partition_alloc_base/posix/eintr_wrapper.h" -#include "partition_alloc/partition_alloc_base/threading/platform_thread.h" -#include "partition_alloc/partition_alloc_check.h" - -#if PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) -#include -#include -#include -#include -#include -#include -#include -#endif // PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) - -namespace partition_alloc::internal { - -PCScan::ClearType NoWriteProtector::SupportedClearType() const { - return PCScan::ClearType::kLazy; -} - -#if PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) - -namespace { -void UserFaultFDThread(int uffd) { - PA_DCHECK(-1 != uffd); - - static constexpr char kThreadName[] = "PCScanPFHandler"; - internal::base::PlatformThread::SetName(kThreadName); - - while (true) { - // Pool on the uffd descriptor for page fault events. - pollfd pollfd{ - .fd = uffd, - .events = POLLIN, - .revents = 0, // Unused output param of `pool` call. - }; - const int nready = WrapEINTR(poll)(&pollfd, 1, -1); - PA_CHECK(-1 != nready); - - // Get page fault info. - uffd_msg msg; - const int nread = WrapEINTR(read)(uffd, &msg, sizeof(msg)); - PA_CHECK(0 != nread); - - // We only expect page faults. - PA_DCHECK(UFFD_EVENT_PAGEFAULT == msg.event); - // We have subscribed only to wp-fault events. - PA_DCHECK(UFFD_PAGEFAULT_FLAG_WP & msg.arg.pagefault.flags); - - // Enter the safepoint. Concurrent faulted writes will wait until safepoint - // finishes. - PCScan::JoinScanIfNeeded(); - } -} -} // namespace - -UserFaultFDWriteProtector::UserFaultFDWriteProtector() - : uffd_(syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK)) { - if (uffd_ == -1) { - PA_LOG(WARNING) << "userfaultfd is not supported by the current kernel"; - return; - } - - PA_PCHECK(-1 != uffd_); - - uffdio_api uffdio_api; - uffdio_api.api = UFFD_API; - uffdio_api.features = 0; - PA_CHECK(-1 != ioctl(uffd_, UFFDIO_API, &uffdio_api)); - PA_CHECK(UFFD_API == uffdio_api.api); - - // Register the regular pool to listen uffd events. - struct uffdio_register uffdio_register; - uffdio_register.range.start = PartitionAddressSpace::RegularPoolBase(); - uffdio_register.range.len = kPoolMaxSize; - uffdio_register.mode = UFFDIO_REGISTER_MODE_WP; - PA_CHECK(-1 != ioctl(uffd_, UFFDIO_REGISTER, &uffdio_register)); - - // Start uffd thread. - std::thread(UserFaultFDThread, uffd_).detach(); -} - -namespace { -enum class UserFaultFDWPMode { - kProtect, - kUnprotect, -}; - -void UserFaultFDWPSet(int uffd, - uintptr_t begin, - size_t length, - UserFaultFDWPMode mode) { - PA_DCHECK(0 == (begin % SystemPageSize())); - PA_DCHECK(0 == (length % SystemPageSize())); - - uffdio_writeprotect wp; - wp.range.start = begin; - wp.range.len = length; - wp.mode = - (mode == UserFaultFDWPMode::kProtect) ? UFFDIO_WRITEPROTECT_MODE_WP : 0; - PA_PCHECK(-1 != ioctl(uffd, UFFDIO_WRITEPROTECT, &wp)); -} -} // namespace - -void UserFaultFDWriteProtector::ProtectPages(uintptr_t begin, size_t length) { - if (IsSupported()) { - UserFaultFDWPSet(uffd_, begin, length, UserFaultFDWPMode::kProtect); - } -} - -void UserFaultFDWriteProtector::UnprotectPages(uintptr_t begin, size_t length) { - if (IsSupported()) { - UserFaultFDWPSet(uffd_, begin, length, UserFaultFDWPMode::kUnprotect); - } -} - -PCScan::ClearType UserFaultFDWriteProtector::SupportedClearType() const { - return IsSupported() ? PCScan::ClearType::kEager : PCScan::ClearType::kLazy; -} - -bool UserFaultFDWriteProtector::IsSupported() const { - return uffd_ != -1; -} - -#endif // PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) - -} // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.h deleted file mode 100644 index 30fc61db3d..0000000000 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PARTITION_ALLOC_STARSCAN_WRITE_PROTECTOR_H_ -#define PARTITION_ALLOC_STARSCAN_WRITE_PROTECTOR_H_ - -#include -#include -#include - -#include "partition_alloc/build_config.h" -#include "partition_alloc/internal_allocator_forward.h" -#include "partition_alloc/starscan/pcscan.h" -#include "partition_alloc/starscan/raceful_worklist.h" - -namespace partition_alloc::internal { - -// Interface for page protection/unprotection. This is used in DCScan to catch -// concurrent mutator writes. Protection is done when the scanner starts -// scanning a range. Unprotection happens at the end of the scanning phase. -class WriteProtector : public internal::InternalPartitionAllocated { - public: - virtual ~WriteProtector() = default; - - virtual void ProtectPages(uintptr_t begin, size_t length) = 0; - virtual void UnprotectPages(uintptr_t begin, size_t length) = 0; - - virtual bool IsEnabled() const = 0; - - virtual PCScan::ClearType SupportedClearType() const = 0; -}; - -class NoWriteProtector final : public WriteProtector { - public: - void ProtectPages(uintptr_t, size_t) final {} - void UnprotectPages(uintptr_t, size_t) final {} - PCScan::ClearType SupportedClearType() const final; - inline bool IsEnabled() const override; -}; - -bool NoWriteProtector::IsEnabled() const { - return false; -} - -#if PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) -class UserFaultFDWriteProtector final : public WriteProtector { - public: - UserFaultFDWriteProtector(); - - UserFaultFDWriteProtector(const UserFaultFDWriteProtector&) = delete; - UserFaultFDWriteProtector& operator=(const UserFaultFDWriteProtector&) = - delete; - - void ProtectPages(uintptr_t, size_t) final; - void UnprotectPages(uintptr_t, size_t) final; - - PCScan::ClearType SupportedClearType() const final; - - inline bool IsEnabled() const override; - - private: - bool IsSupported() const; - - const int uffd_ = 0; -}; - -bool UserFaultFDWriteProtector::IsEnabled() const { - return IsSupported(); -} -#endif // PA_CONFIG(STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED) - -} // namespace partition_alloc::internal - -#endif // PARTITION_ALLOC_STARSCAN_WRITE_PROTECTOR_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/tagging.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/tagging.cc index 5ea3ae4cb5..b88f09bdc4 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/tagging.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/tagging.cc @@ -8,9 +8,9 @@ #include "partition_alloc/aarch64_support.h" #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/cpu.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" @@ -316,4 +316,33 @@ bool PermissiveMte::HandleCrash(int signo, } #endif // PA_BUILDFLAG(HAS_MEMORY_TAGGING) && PA_BUILDFLAG(IS_ANDROID) +SuspendTagCheckingScope::SuspendTagCheckingScope() noexcept { +#if PA_BUILDFLAG(HAS_MEMORY_TAGGING) + if (PA_UNLIKELY(internal::base::CPU::GetInstanceNoAllocation().has_mte())) { + asm volatile( + R"( + .arch_extension memtag + mrs %0, tco + msr tco, #1 + )" + : "=r"(previous_tco_)); + } +#endif // PA_BUILDFLAG(HAS_MEMORY_TAGGING) +} + +SuspendTagCheckingScope::~SuspendTagCheckingScope() { +#if PA_BUILDFLAG(HAS_MEMORY_TAGGING) + if (PA_UNLIKELY(internal::base::CPU::GetInstanceNoAllocation().has_mte())) { + // Restore previous tco value. + __asm__ __volatile__( + R"( + .arch_extension memtag + msr tco, %0 + )" + : + : "r"(previous_tco_)); + } +#endif // PA_BUILDFLAG(HAS_MEMORY_TAGGING) +} + } // namespace partition_alloc diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/tagging.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/tagging.h index 3f71dad20e..047983bf63 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/tagging.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/tagging.h @@ -12,9 +12,9 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #if PA_BUILDFLAG(HAS_MEMORY_TAGGING) && PA_BUILDFLAG(IS_ANDROID) @@ -149,6 +149,20 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PermissiveMte { }; #endif // PA_BUILDFLAG(HAS_MEMORY_TAGGING) +// Stops MTE tag checking for the current thread while this is alive. This does +// not affect the return value for GetMemoryTaggingModeForCurrentThread(). +class PA_COMPONENT_EXPORT(PARTITION_ALLOC) SuspendTagCheckingScope final { + public: + SuspendTagCheckingScope() noexcept; + ~SuspendTagCheckingScope(); + + private: +#if PA_BUILDFLAG(HAS_MEMORY_TAGGING) + // Stores the previous value of the Tag Check Override (TCO) register. + uint64_t previous_tco_; +#endif +}; + } // namespace partition_alloc #endif // PARTITION_ALLOC_TAGGING_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.cc index 47e59ce88a..f02fe775da 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.cc @@ -11,13 +11,12 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/internal_allocator.h" #include "partition_alloc/partition_alloc-inl.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/immediate_crash.h" #include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_check.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" @@ -179,7 +178,7 @@ void ThreadCacheRegistry::ForcePurgeAllThreadAfterForkUnsafe() { internal::ScopedGuard scoped_locker(GetLock()); ThreadCache* tcache = list_head_; while (tcache) { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) // Before fork(), locks are acquired in the parent process. This means that // a concurrent allocation in the parent which must be filled by the central // allocator (i.e. the thread cache bucket is empty) will block inside the diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.h index 9aa9aeb382..d65baaaea0 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.h @@ -12,14 +12,13 @@ #include #include "partition_alloc/build_config.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/lightweight_quarantine.h" #include "partition_alloc/partition_alloc-inl.h" #include "partition_alloc/partition_alloc_base/compiler_specific.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" #include "partition_alloc/partition_alloc_base/time/time.h" -#include "partition_alloc/partition_alloc_buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_alloc_constants.h" #include "partition_alloc/partition_alloc_forward.h" @@ -190,7 +189,7 @@ constexpr ThreadCacheRegistry::ThreadCacheRegistry() = default; } while (0) #endif // PA_CONFIG(THREAD_CACHE_ENABLE_STATISTICS) -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) namespace internal { @@ -214,13 +213,13 @@ class ReentrancyGuard { x \ } -#else // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#else // PA_BUILDFLAG(DCHECKS_ARE_ON) #define PA_REENTRANCY_GUARD(x) \ do { \ } while (0) -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) // Per-thread cache. *Not* threadsafe, must only be accessed from a single // thread. @@ -367,8 +366,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ThreadCache { kThreadCacheDefaultSizeThreshold; static constexpr size_t kLargeSizeThreshold = kThreadCacheLargeSizeThreshold; static constexpr uint16_t kBucketCount = - internal::BucketIndexLookup::GetIndex(ThreadCache::kLargeSizeThreshold) + - 1; + internal::BucketIndexLookup::GetIndex(kThreadCacheLargeSizeThreshold) + 1; static_assert( kBucketCount < internal::kNumBuckets, "Cannot have more cached buckets than what the allocator supports"); @@ -457,7 +455,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ThreadCache { PartitionRoot* const root_; const internal::base::PlatformThreadId thread_id_; -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) bool is_in_thread_cache_ = false; #endif @@ -616,11 +614,12 @@ PA_ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket, static const uint32_t poison_16_bytes[4] = {0xbadbad00, 0xbadbad00, 0xbadbad00, 0xbadbad00}; -#if !(PA_BUILDFLAG(IS_WIN) && defined(COMPONENT_BUILD)) - void* slot_start_tagged = std::assume_aligned( - internal::SlotStartAddr2Ptr(slot_start)); +#if !(PA_BUILDFLAG(IS_WIN) && defined(COMPONENT_BUILD)) && \ + PA_HAS_BUILTIN(__builtin_assume_aligned) + void* slot_start_tagged = __builtin_assume_aligned( + internal::SlotStartAddr2Ptr(slot_start), internal::kAlignment); #else - // TODO(crbug.com/40262684): std::assume_aligned introuces an additional + // TODO(crbug.com/40262684): std::assume_aligned introduce an additional // dependency: _libcpp_verbose_abort(const char*, ...). It will cause // "undefined symbol" error when linking allocator_shim.dll. void* slot_start_tagged = internal::SlotStartAddr2Ptr(slot_start); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/alignment.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/alignment.h index 947226161a..9b68a05fc6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/alignment.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/alignment.h @@ -5,7 +5,7 @@ #ifndef PARTITION_ALLOC_THREAD_ISOLATION_ALIGNMENT_H_ #define PARTITION_ALLOC_THREAD_ISOLATION_ALIGNMENT_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey.cc index 905bf60f3e..d5b7b38efc 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey.cc @@ -61,7 +61,7 @@ void Wrpkru(uint32_t pkru) { asm volatile(".byte 0x0f,0x01,0xef\n" : : "a"(pkru), "c"(0), "d"(0)); } -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) LiftPkeyRestrictionsScope::LiftPkeyRestrictionsScope() : saved_pkey_value_(kDefaultPkeyValue) { @@ -83,7 +83,7 @@ LiftPkeyRestrictionsScope::~LiftPkeyRestrictionsScope() { } } -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) } // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey.h index b4a759596d..382dbadd4f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey.h @@ -5,17 +5,17 @@ #ifndef PARTITION_ALLOC_THREAD_ISOLATION_PKEY_H_ #define PARTITION_ALLOC_THREAD_ISOLATION_PKEY_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(ENABLE_PKEYS) -#include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" -#include "partition_alloc/thread_isolation/alignment.h" - #include #include +#include "partition_alloc/buildflags.h" +#include "partition_alloc/partition_alloc_base/component_export.h" +#include "partition_alloc/thread_isolation/alignment.h" + namespace partition_alloc::internal { constexpr int kDefaultPkey = 0; @@ -39,7 +39,7 @@ uint32_t Rdpkru(); // Write the pkru register (the current pkey state). void Wrpkru(uint32_t pkru); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LiftPkeyRestrictionsScope { public: @@ -53,7 +53,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LiftPkeyRestrictionsScope { uint32_t saved_pkey_value_; }; -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) } // namespace partition_alloc::internal diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.cc index 09bb583020..77e968954f 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.cc @@ -18,7 +18,7 @@ namespace partition_alloc::internal { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) ThreadIsolationSettings ThreadIsolationSettings::settings; #endif @@ -80,7 +80,7 @@ void WriteProtectThreadIsolatedGlobals(ThreadIsolationOption thread_isolation) { thread_isolation, pkey_reservation_offset_table, ReservationOffsetTable::kReservationOffsetTableLength); -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) WriteProtectThreadIsolatedVariable(thread_isolation, ThreadIsolationSettings::settings); #endif diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.h index de2cb23d1e..523892b386 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.h @@ -5,15 +5,15 @@ #ifndef PARTITION_ALLOC_THREAD_ISOLATION_THREAD_ISOLATION_H_ #define PARTITION_ALLOC_THREAD_ISOLATION_THREAD_ISOLATION_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(ENABLE_THREAD_ISOLATION) #include #include +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_base/component_export.h" -#include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" #if PA_BUILDFLAG(ENABLE_PKEYS) #include "partition_alloc/thread_isolation/pkey.h" @@ -52,7 +52,7 @@ struct ThreadIsolationOption { namespace partition_alloc::internal { -#if PA_BUILDFLAG(PA_DCHECK_IS_ON) +#if PA_BUILDFLAG(DCHECKS_ARE_ON) struct PA_THREAD_ISOLATED_ALIGN ThreadIsolationSettings { bool enabled = false; @@ -64,7 +64,7 @@ struct PA_THREAD_ISOLATED_ALIGN ThreadIsolationSettings { using LiftThreadIsolationScope = LiftPkeyRestrictionsScope; #endif // PA_BUILDFLAG(ENABLE_PKEYS) -#endif // PA_BUILDFLAG(PA_DCHECK_IS_ON) +#endif // PA_BUILDFLAG(DCHECKS_ARE_ON) void WriteProtectThreadIsolatedGlobals(ThreadIsolationOption thread_isolation); void UnprotectThreadIsolatedGlobals(); diff --git a/naiveproxy/src/base/android/base_feature_map.cc b/naiveproxy/src/base/android/base_feature_map.cc new file mode 100644 index 0000000000..87636286f7 --- /dev/null +++ b/naiveproxy/src/base/android/base_feature_map.cc @@ -0,0 +1,35 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "base/android/feature_map.h" +#include "base/base_jni/BaseFeatureMap_jni.h" +#include "base/feature_list.h" +#include "base/features.h" +#include "base/no_destructor.h" + +namespace base::android { + +namespace { +// Array of features exposed through the Java BaseFeatureMap API. Entries in +// this array may either refer to features defined in //base features. +const base::Feature* const kFeaturesExposedToJava[] = { + &features::kPostPowerMonitorBroadcastReceiverInitToBackground, +}; + +// static +base::android::FeatureMap* GetFeatureMap() { + static base::NoDestructor kFeatureMap(std::vector( + std::begin(kFeaturesExposedToJava), std::end(kFeaturesExposedToJava))); + return kFeatureMap.get(); +} + +} // namespace + +static jlong JNI_BaseFeatureMap_GetNativeMap(JNIEnv* env) { + return reinterpret_cast(GetFeatureMap()); +} + +} // namespace base::android diff --git a/naiveproxy/src/base/android/binder.cc b/naiveproxy/src/base/android/binder.cc new file mode 100644 index 0000000000..0a3366576c --- /dev/null +++ b/naiveproxy/src/base/android/binder.cc @@ -0,0 +1,556 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/android/binder.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "base/android/requires_api.h" +#include "base/check.h" +#include "base/memory/raw_ptr_exclusion.h" +#include "base/no_destructor.h" +#include "base/notreached.h" +#include "base/numerics/safe_conversions.h" +#include "base/types/expected.h" + +// The Binder NDK library was introduced in Q. +#define BINDER_MIN_API 29 + +// Helper used extensively herein to guard blocks of code on the availability of +// Binder NDK functions. +#define WITH_BINDER_API(name) \ + if (__builtin_available(android BINDER_MIN_API, *)) \ + if (GetBinderApi()) \ + if (const BinderApi& name = *GetBinderApi(); true) + +namespace base::android { + +namespace { + +// Helper to expose useful functions from libbinder_ndk.so at runtime. Currently +// limited to functions supported in Q. +struct BASE_EXPORT BinderApi { + // Excluded from raw_ptr because this is trivially safe and it keeps BinderApi + // from having a destructor in any build configuration. + RAW_PTR_EXCLUSION void* const library = dlopen("libbinder_ndk.so", RTLD_LAZY); + +#define DEFINE_BINDER_API_ENTRY(name) \ + REQUIRES_ANDROID_API(BINDER_MIN_API) \ + decltype(::name)* const name = \ + library ? (decltype(::name)*)dlsym(library, "" #name) : nullptr + + DEFINE_BINDER_API_ENTRY(AIBinder_Class_define); + DEFINE_BINDER_API_ENTRY(AIBinder_Class_setOnDump); + DEFINE_BINDER_API_ENTRY(AIBinder_new); + DEFINE_BINDER_API_ENTRY(AIBinder_isRemote); + DEFINE_BINDER_API_ENTRY(AIBinder_isAlive); + DEFINE_BINDER_API_ENTRY(AIBinder_ping); + DEFINE_BINDER_API_ENTRY(AIBinder_dump); + DEFINE_BINDER_API_ENTRY(AIBinder_linkToDeath); + DEFINE_BINDER_API_ENTRY(AIBinder_unlinkToDeath); + DEFINE_BINDER_API_ENTRY(AIBinder_getCallingUid); + DEFINE_BINDER_API_ENTRY(AIBinder_getCallingPid); + DEFINE_BINDER_API_ENTRY(AIBinder_incStrong); + DEFINE_BINDER_API_ENTRY(AIBinder_decStrong); + DEFINE_BINDER_API_ENTRY(AIBinder_debugGetRefCount); + DEFINE_BINDER_API_ENTRY(AIBinder_associateClass); + DEFINE_BINDER_API_ENTRY(AIBinder_getClass); + DEFINE_BINDER_API_ENTRY(AIBinder_getUserData); + DEFINE_BINDER_API_ENTRY(AIBinder_prepareTransaction); + DEFINE_BINDER_API_ENTRY(AIBinder_transact); + DEFINE_BINDER_API_ENTRY(AIBinder_Weak_new); + DEFINE_BINDER_API_ENTRY(AIBinder_Weak_delete); + DEFINE_BINDER_API_ENTRY(AIBinder_Weak_promote); + DEFINE_BINDER_API_ENTRY(AIBinder_DeathRecipient_new); + DEFINE_BINDER_API_ENTRY(AIBinder_DeathRecipient_delete); + DEFINE_BINDER_API_ENTRY(AIBinder_fromJavaBinder); + DEFINE_BINDER_API_ENTRY(AIBinder_toJavaBinder); + DEFINE_BINDER_API_ENTRY(AParcel_delete); + DEFINE_BINDER_API_ENTRY(AParcel_setDataPosition); + DEFINE_BINDER_API_ENTRY(AParcel_getDataPosition); + DEFINE_BINDER_API_ENTRY(AParcel_writeStrongBinder); + DEFINE_BINDER_API_ENTRY(AParcel_readStrongBinder); + DEFINE_BINDER_API_ENTRY(AParcel_writeParcelFileDescriptor); + DEFINE_BINDER_API_ENTRY(AParcel_readParcelFileDescriptor); + DEFINE_BINDER_API_ENTRY(AParcel_writeStatusHeader); + DEFINE_BINDER_API_ENTRY(AParcel_readStatusHeader); + DEFINE_BINDER_API_ENTRY(AParcel_writeString); + DEFINE_BINDER_API_ENTRY(AParcel_readString); + DEFINE_BINDER_API_ENTRY(AParcel_writeStringArray); + DEFINE_BINDER_API_ENTRY(AParcel_readStringArray); + DEFINE_BINDER_API_ENTRY(AParcel_writeParcelableArray); + DEFINE_BINDER_API_ENTRY(AParcel_readParcelableArray); + DEFINE_BINDER_API_ENTRY(AParcel_writeInt32); + DEFINE_BINDER_API_ENTRY(AParcel_writeUint32); + DEFINE_BINDER_API_ENTRY(AParcel_writeInt64); + DEFINE_BINDER_API_ENTRY(AParcel_writeUint64); + DEFINE_BINDER_API_ENTRY(AParcel_writeFloat); + DEFINE_BINDER_API_ENTRY(AParcel_writeDouble); + DEFINE_BINDER_API_ENTRY(AParcel_writeBool); + DEFINE_BINDER_API_ENTRY(AParcel_writeChar); + DEFINE_BINDER_API_ENTRY(AParcel_writeByte); + DEFINE_BINDER_API_ENTRY(AParcel_readInt32); + DEFINE_BINDER_API_ENTRY(AParcel_readUint32); + DEFINE_BINDER_API_ENTRY(AParcel_readInt64); + DEFINE_BINDER_API_ENTRY(AParcel_readUint64); + DEFINE_BINDER_API_ENTRY(AParcel_readFloat); + DEFINE_BINDER_API_ENTRY(AParcel_readDouble); + DEFINE_BINDER_API_ENTRY(AParcel_readBool); + DEFINE_BINDER_API_ENTRY(AParcel_readChar); + DEFINE_BINDER_API_ENTRY(AParcel_readByte); + DEFINE_BINDER_API_ENTRY(AParcel_writeInt32Array); + DEFINE_BINDER_API_ENTRY(AParcel_writeUint32Array); + DEFINE_BINDER_API_ENTRY(AParcel_writeInt64Array); + DEFINE_BINDER_API_ENTRY(AParcel_writeUint64Array); + DEFINE_BINDER_API_ENTRY(AParcel_writeFloatArray); + DEFINE_BINDER_API_ENTRY(AParcel_writeDoubleArray); + DEFINE_BINDER_API_ENTRY(AParcel_writeBoolArray); + DEFINE_BINDER_API_ENTRY(AParcel_writeCharArray); + DEFINE_BINDER_API_ENTRY(AParcel_writeByteArray); + DEFINE_BINDER_API_ENTRY(AParcel_readInt32Array); + DEFINE_BINDER_API_ENTRY(AParcel_readUint32Array); + DEFINE_BINDER_API_ENTRY(AParcel_readInt64Array); + DEFINE_BINDER_API_ENTRY(AParcel_readUint64Array); + DEFINE_BINDER_API_ENTRY(AParcel_readFloatArray); + DEFINE_BINDER_API_ENTRY(AParcel_readDoubleArray); + DEFINE_BINDER_API_ENTRY(AParcel_readBoolArray); + DEFINE_BINDER_API_ENTRY(AParcel_readCharArray); + DEFINE_BINDER_API_ENTRY(AParcel_readByteArray); +#undef DEFINE_BINDER_API_ENTRY +}; + +static BinderApi* GetBinderApi() { + static BinderApi api; + if (!api.library) { + return nullptr; + } + return &api; +} + +std::unique_ptr>& BindersFromParent() { + static NoDestructor>> ptr; + return *ptr; +} + +} // namespace + +ParcelReader::ParcelReader(const AParcel* parcel) : parcel_(parcel) {} + +ParcelReader::ParcelReader(const Parcel& parcel) : parcel_(parcel.get()) {} + +ParcelReader::ParcelReader(const ParcelReader&) = default; + +ParcelReader& ParcelReader::operator=(const ParcelReader&) = default; + +ParcelReader::~ParcelReader() = default; + +BinderStatusOr ParcelReader::ReadBinder() const { + WITH_BINDER_API(api) { + AIBinder* binder; + const auto status = api.AParcel_readStrongBinder(parcel_.get(), &binder); + if (status != STATUS_OK) { + return unexpected(status); + } + return BinderRef(binder); + } + return unexpected(STATUS_UNEXPECTED_NULL); +} + +BinderStatusOr ParcelReader::ReadInt32() const { + WITH_BINDER_API(api) { + int32_t value; + const auto status = api.AParcel_readInt32(parcel_.get(), &value); + if (status != STATUS_OK) { + return unexpected(status); + } + return ok(value); + } + return unexpected(STATUS_UNEXPECTED_NULL); +} + +BinderStatusOr ParcelReader::ReadUint32() const { + WITH_BINDER_API(api) { + uint32_t value; + const auto status = api.AParcel_readUint32(parcel_.get(), &value); + if (status != STATUS_OK) { + return unexpected(status); + } + return ok(value); + } + return unexpected(STATUS_UNEXPECTED_NULL); +} + +BinderStatusOr ParcelReader::ReadUint64() const { + WITH_BINDER_API(api) { + uint64_t value; + const auto status = api.AParcel_readUint64(parcel_.get(), &value); + if (status != STATUS_OK) { + return unexpected(status); + } + return ok(value); + } + return unexpected(STATUS_UNEXPECTED_NULL); +} + +BinderStatusOr ParcelReader::ReadByteArrayImpl( + AParcel_byteArrayAllocator allocator, + void* context) const { + WITH_BINDER_API(api) { + const auto status = + api.AParcel_readByteArray(parcel_.get(), context, allocator); + if (status != STATUS_OK) { + return unexpected(status); + } + return ok(); + } + return unexpected(STATUS_UNEXPECTED_NULL); +} + +BinderStatusOr ParcelReader::ReadFileDescriptor() const { + WITH_BINDER_API(api) { + int fd; + const auto status = + api.AParcel_readParcelFileDescriptor(parcel_.get(), &fd); + if (status != STATUS_OK) { + return unexpected(status); + } + return ScopedFD(fd); + } + return unexpected(STATUS_UNEXPECTED_NULL); +} + +ParcelWriter::ParcelWriter(AParcel* parcel) : parcel_(parcel) {} + +ParcelWriter::ParcelWriter(Parcel& parcel) : parcel_(parcel.get()) {} + +ParcelWriter::ParcelWriter(const ParcelWriter&) = default; + +ParcelWriter& ParcelWriter::operator=(const ParcelWriter&) = default; + +ParcelWriter::~ParcelWriter() = default; + +BinderStatusOr ParcelWriter::WriteBinder(BinderRef binder) const { + binder_status_t status = STATUS_UNEXPECTED_NULL; + WITH_BINDER_API(api) { + status = api.AParcel_writeStrongBinder(parcel_.get(), binder.get()); + if (status == STATUS_OK) { + return ok(); + } + } + return unexpected(status); +} + +BinderStatusOr ParcelWriter::WriteInt32(int32_t value) const { + binder_status_t status = STATUS_UNEXPECTED_NULL; + WITH_BINDER_API(api) { + status = api.AParcel_writeInt32(parcel_.get(), value); + if (status == STATUS_OK) { + return ok(); + } + } + return unexpected(status); +} + +BinderStatusOr ParcelWriter::WriteUint32(uint32_t value) const { + binder_status_t status = STATUS_UNEXPECTED_NULL; + WITH_BINDER_API(api) { + status = api.AParcel_writeUint32(parcel_.get(), value); + if (status == STATUS_OK) { + return ok(); + } + } + return unexpected(status); +} + +BinderStatusOr ParcelWriter::WriteUint64(uint64_t value) const { + binder_status_t status = STATUS_UNEXPECTED_NULL; + WITH_BINDER_API(api) { + status = api.AParcel_writeUint64(parcel_.get(), value); + if (status == STATUS_OK) { + return ok(); + } + } + return unexpected(status); +} + +BinderStatusOr ParcelWriter::WriteByteArray( + span bytes) const { + binder_status_t status = STATUS_UNEXPECTED_NULL; + WITH_BINDER_API(api) { + status = api.AParcel_writeByteArray( + parcel_.get(), reinterpret_cast(bytes.data()), + checked_cast(bytes.size())); + if (status == STATUS_OK) { + return ok(); + } + } + return unexpected(status); +} + +BinderStatusOr ParcelWriter::WriteFileDescriptor(ScopedFD file) const { + binder_status_t status = STATUS_UNEXPECTED_NULL; + WITH_BINDER_API(api) { + status = api.AParcel_writeParcelFileDescriptor(parcel_.get(), file.get()); + if (status == STATUS_OK) { + return ok(); + } + } + return unexpected(status); +} + +Parcel::Parcel() = default; + +Parcel::Parcel(AParcel* parcel) : parcel_(parcel) {} + +Parcel::Parcel(Parcel&& other) : parcel_(other.release()) {} + +Parcel& Parcel::operator=(Parcel&& other) { + reset(); + parcel_ = other.release(); + return *this; +} + +Parcel::~Parcel() { + reset(); +} + +void Parcel::reset() { + WITH_BINDER_API(api) { + if (AParcel* parcel = release()) { + api.AParcel_delete(parcel); + } + } +} + +BinderRef::BinderRef() = default; + +BinderRef::BinderRef(AIBinder* binder) : binder_(binder) {} + +BinderRef::BinderRef(const BinderRef& other) : binder_(other.binder_) { + if (binder_) { + WITH_BINDER_API(api) { + api.AIBinder_incStrong(binder_); + } + } +} + +BinderRef& BinderRef::operator=(const BinderRef& other) { + reset(); + binder_ = other.binder_; + if (binder_) { + WITH_BINDER_API(api) { + api.AIBinder_incStrong(binder_); + } + } + return *this; +} + +BinderRef::BinderRef(BinderRef&& other) : binder_(other.release()) {} + +BinderRef& BinderRef::operator=(BinderRef&& other) { + reset(); + binder_ = other.release(); + return *this; +} + +BinderRef::~BinderRef() { + reset(); +} + +void BinderRef::reset() { + if (AIBinder* binder = release()) { + WITH_BINDER_API(api) { + api.AIBinder_decStrong(binder); + } + } +} + +ScopedJavaLocalRef BinderRef::ToJavaBinder(JNIEnv* env) const { + ScopedJavaLocalRef object; + if (binder_) { + WITH_BINDER_API(api) { + object = ScopedJavaLocalRef::Adopt( + env, api.AIBinder_toJavaBinder(env, binder_.get())); + } + } + return object; +} + +BinderRef BinderRef::FromJavaBinder(JNIEnv* env, jobject java_binder) { + WITH_BINDER_API(api) { + if (AIBinder* binder = api.AIBinder_fromJavaBinder(env, java_binder)) { + return BinderRef(binder); + } + } + return BinderRef(); +} + +bool BinderRef::AssociateWithClass(AIBinder_Class* binder_class) { + if (binder_) { + WITH_BINDER_API(api) { + return api.AIBinder_associateClass(binder_.get(), binder_class); + } + } + return false; +} + +BinderStatusOr BinderRef::PrepareTransaction() { + if (binder_) { + WITH_BINDER_API(api) { + AParcel* parcel; + const auto status = + api.AIBinder_prepareTransaction(binder_.get(), &parcel); + if (status != STATUS_OK) { + return unexpected(status); + } + return Parcel(parcel); + } + } + return unexpected(STATUS_UNEXPECTED_NULL); +} + +BinderStatusOr BinderRef::TransactImpl(transaction_code_t code, + Parcel parcel, + binder_flags_t flags) { + if (binder_) { + WITH_BINDER_API(api) { + // NOTE: AIBinder_transact always takes ownership of the input parcel even + // in failure modes. Hence it's safe to release here unconditionally. + AParcel* in = parcel.release(); + AParcel* out; + const auto status = + api.AIBinder_transact(binder_.get(), code, &in, &out, 0); + if (status != STATUS_OK) { + return unexpected(status); + } + return Parcel(out); + } + } + return unexpected(STATUS_UNEXPECTED_NULL); +} + +namespace internal { + +AIBinder_Class* BinderClassBase::RegisterBinderClass(const char* name) { + WITH_BINDER_API(api) { + return api.AIBinder_Class_define(name, &SupportsBinderBase::OnIBinderCreate, + &SupportsBinderBase::OnIBinderDestroy, + &SupportsBinderBase::OnIBinderTransact); + } + return nullptr; +} + +SupportsBinderBase::SupportsBinderBase(AIBinder_Class* binder_class) + : binder_class_(binder_class) {} + +SupportsBinderBase::~SupportsBinderBase() { +#if DCHECK_IS_ON() + // If we're being destroyed there must no longer be an IBinder for this + // object. And in that case, `weak_binder_` should have already been cleared + // by OnIBinderDestroy(). + AutoLock lock(lock_); + DCHECK(!weak_binder_); +#endif +} + +BinderRef SupportsBinderBase::GetBinder() { + WITH_BINDER_API(api) { + AutoLock lock(lock_); + if (weak_binder_) { + AIBinder* strong = api.AIBinder_Weak_promote(weak_binder_.get()); + if (strong) { + return BinderRef(strong); + } + + // Our weak IBinder is no longer valid. + api.AIBinder_Weak_delete(weak_binder_.get()); + weak_binder_ = nullptr; + } + + // We have no IBinder, so create a new one. + AIBinder* binder = api.AIBinder_new(binder_class_.get(), this); + CHECK(binder); + weak_binder_ = api.AIBinder_Weak_new(binder); + self_for_binder_ = this; + return BinderRef(binder); + } + + return BinderRef(); +} + +void SupportsBinderBase::OnBinderDestroyed() {} + +void SupportsBinderBase::OnBinderDestroyedBase() { + scoped_refptr self_ref; + WITH_BINDER_API(api) { + AutoLock lock(lock_); + if (weak_binder_) { + api.AIBinder_Weak_delete(weak_binder_.get()); + weak_binder_ = nullptr; + } + self_ref.swap(self_for_binder_); + } + OnBinderDestroyed(); + + // May delete `this`. + self_ref.reset(); +} + +void* SupportsBinderBase::OnIBinderCreate(void* self) { + return self; +} + +void SupportsBinderBase::OnIBinderDestroy(void* self) { + reinterpret_cast(self)->OnBinderDestroyedBase(); +} + +binder_status_t SupportsBinderBase::OnIBinderTransact(AIBinder* binder, + transaction_code_t code, + const AParcel* in, + AParcel* out) { + WITH_BINDER_API(api) { + void* const user_data = api.AIBinder_getUserData(binder); + auto* const target = reinterpret_cast(user_data); + + const auto result = + target->OnBinderTransaction(code, ParcelReader(in), ParcelWriter(out)); + return result.has_value() ? STATUS_OK : result.error(); + } + + // If binder NDK is unsupported, nobody will be calling this method. + NOTREACHED_NORETURN(); +} + +} // namespace internal + +bool IsNativeBinderAvailable() { + return GetBinderApi(); +} + +void SetBindersFromParent(std::vector binders) { + CHECK(!BindersFromParent()); + BindersFromParent() = + std::make_unique>(std::move(binders)); +} + +BinderRef TakeBinderFromParent(size_t index) { + auto& binders = BindersFromParent(); + CHECK(binders); + if (index >= binders->size()) { + return BinderRef(); + } + return std::move(binders->at(index)); +} + +} // namespace base::android diff --git a/naiveproxy/src/base/android/binder.h b/naiveproxy/src/base/android/binder.h new file mode 100644 index 0000000000..915fcaf6d4 --- /dev/null +++ b/naiveproxy/src/base/android/binder.h @@ -0,0 +1,408 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ANDROID_BINDER_H_ +#define BASE_ANDROID_BINDER_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "base/android/scoped_java_ref.h" +#include "base/base_export.h" +#include "base/check.h" +#include "base/containers/span.h" +#include "base/files/scoped_file.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/ref_counted.h" +#include "base/numerics/safe_conversions.h" +#include "base/synchronization/lock.h" +#include "base/types/expected.h" +#include "base/types/expected_macros.h" + +// DEFINE_BINDER_CLASS() generates a definition for a unique binder class. +// Binder classes are used by the binder implementation to enforce a kind of +// type safety, requiring client IBinders to be associated with the same class +// as the remote object's original IBinder. +// +// Objects implementing SupportsBinder must specify such a class as the T; +// and clients wishing to perform transactions against such objects must use a +// TypedBinderRef to do so. +// +// See usage comments on SupportsBinder below. +#define _BINDER_CLASS_LINE(line) _BINDER_CLASS_LINE2(line) +#define _BINDER_CLASS_LINE2(line) #line +#define DEFINE_BINDER_CLASS(name) \ + struct name : public base::android::internal::BinderClassBase { \ + using BinderRef = base::android::TypedBinderRef; \ + static inline AIBinder_Class* GetBinderClass() { \ + static AIBinder_Class* const clazz = RegisterBinderClass( \ + #name ":" __FILE__ ":" _BINDER_CLASS_LINE(__LINE__)); \ + return clazz; \ + } \ + static inline base::android::TypedBinderRef AdoptBinderRef( \ + base::android::BinderRef binder) { \ + return base::android::TypedBinderRef::Adopt(std::move(binder)); \ + } \ + } + +namespace base::android { + +class BinderRef; +class Parcel; + +template +using BinderStatusOr = expected; + +// Provides a read-only view into a AParcel. Does not retain ownership of the +// AParcel, which must outlive this object. +class BASE_EXPORT ParcelReader { + public: + explicit ParcelReader(const AParcel* parcel); + explicit ParcelReader(const Parcel& parcel); + ParcelReader(const ParcelReader&); + ParcelReader& operator=(const ParcelReader&); + ~ParcelReader(); + + // A subset of the NDK functions defined for reading from an AParcel. Others + // may be exposed here as needed. + BinderStatusOr ReadBinder() const; + BinderStatusOr ReadInt32() const; + BinderStatusOr ReadUint32() const; + BinderStatusOr ReadUint64() const; + BinderStatusOr ReadFileDescriptor() const; + + // Reads a byte array from the parcel. `allocator` is called with a single + // size_t argument for the number of bytes in the array and must return a + // pointer to at least that much memory, into which ReadByteArray() will copy + // the array data before returning. If the parcel contains an empty or null + // byte array, `allocator` is not invoked. If `allocator` is invoked and + // returns null, ReadByteArray() returns an error. + template + BinderStatusOr ReadByteArray(Allocator allocator) const { + auto c_allocator = [](void* context, int32_t length, int8_t** out) { + const auto& allocator = *static_cast(context); + const auto size = saturated_cast(length); + if (!size) { + *out = nullptr; + return true; + } + + // Binder API wants int8_t for bytes, but we generally use uint8_t. + uint8_t* const data = allocator(size); + *out = reinterpret_cast(data); + return !!data; + }; + return ReadByteArrayImpl(c_allocator, &allocator); + } + + private: + BinderStatusOr ReadByteArrayImpl(AParcel_byteArrayAllocator allocator, + void* context) const; + + raw_ptr parcel_; +}; + +// Provides a writable view into a AParcel. Does not retain ownership of the +// AParcel, which must outlive this object. +class BASE_EXPORT ParcelWriter { + public: + explicit ParcelWriter(AParcel* parcel); + explicit ParcelWriter(Parcel& parcel); + ParcelWriter(const ParcelWriter&); + ParcelWriter& operator=(const ParcelWriter&); + ~ParcelWriter(); + + // A subset of the NDK functions defined for writing to an AParcel. Others may + // be exposed here as needed. + BinderStatusOr WriteBinder(BinderRef binder) const; + BinderStatusOr WriteInt32(int32_t value) const; + BinderStatusOr WriteUint32(uint32_t value) const; + BinderStatusOr WriteUint64(uint64_t value) const; + BinderStatusOr WriteByteArray(span bytes) const; + BinderStatusOr WriteFileDescriptor(ScopedFD fd) const; + + private: + raw_ptr parcel_; +}; + +// Wraps unique ownership of an AParcel. This is similar to the NDK's +// ScopedAParcel, but it uses our internal BinderApi to invoke NDK functions. +class BASE_EXPORT Parcel { + public: + Parcel(); + explicit Parcel(AParcel* parcel); + Parcel(Parcel&& other); + Parcel& operator=(Parcel&& other); + ~Parcel(); + + explicit operator bool() const { return parcel_ != nullptr; } + + const AParcel* get() const { return parcel_; } + AParcel* get() { return parcel_; } + [[nodiscard]] AParcel* release() { return std::exchange(parcel_, nullptr); } + + void reset(); + + ParcelReader reader() const { return ParcelReader(*this); } + ParcelWriter writer() { return ParcelWriter(*this); } + + private: + raw_ptr parcel_ = nullptr; +}; + +// A BinderRef owns a strong ref-count on an AIBinder. This is like the NDK's +// SpAIBinder, but it uses our internal BinderApi to invoke NDK functions. +class BASE_EXPORT BinderRef { + public: + BinderRef(); + explicit BinderRef(AIBinder* binder); + BinderRef(const BinderRef& other); + BinderRef& operator=(const BinderRef& other); + BinderRef(BinderRef&& other); + BinderRef& operator=(BinderRef&& other); + ~BinderRef(); + + explicit operator bool() const { return binder_ != nullptr; } + + AIBinder* get() const { return binder_; } + [[nodiscard]] AIBinder* release() { return std::exchange(binder_, nullptr); } + + void reset(); + + // Returns a new strong reference to this binder as a local Java object + // reference. + ScopedJavaLocalRef ToJavaBinder(JNIEnv* env) const; + + // Returns a new strong reference to an existing Java binder as a BinderRef. + static BinderRef FromJavaBinder(JNIEnv* env, jobject java_binder); + + // Attempts to associate this binder with `binder_class`. Generally should be + // used via TypedBinderRef::Adopt() or the equivalent T::AdoptBinderRef() + // for some binder class T. + bool AssociateWithClass(AIBinder_Class* binder_class); + + protected: + // Protected to force usage through a strongly typed subclass, ensuring that + // transaction clients have an associated binder class. See documentation on + // TypedBinderRef below. + BinderStatusOr PrepareTransaction(); + BinderStatusOr TransactImpl(transaction_code_t code, + Parcel parcel, + binder_flags_t flags); + + protected: + raw_ptr binder_ = nullptr; +}; + +namespace internal { + +// Base class for classes generated by DEFINE_BINDER_CLASS(). +class BASE_EXPORT BinderClassBase { + public: + static AIBinder_Class* RegisterBinderClass(const char* descriptor); +}; + +// Common implementation for SupportsBinder below. Instances of this base +// class handle IBinder callbacks and forward events for destruction and +// incoming transactions to a templated subclass. +class BASE_EXPORT SupportsBinderBase + : public RefCountedThreadSafe { + public: + explicit SupportsBinderBase(AIBinder_Class* binder_class); + + // Called for every incoming transaction on the underlying IBinder. Note that + // this is called from the binder thread pool so implementations must be + // thread-safe. + virtual BinderStatusOr OnBinderTransaction(transaction_code_t code, + const ParcelReader& in, + const ParcelWriter& out) = 0; + + // Called any time the underlying IBinder is destroyed. Note that this may be + // invoked multiple times, as the underlying IBinder exists only as long as + // there are living BinderRefs referencing this object. If BinderRefs are + // created and then all destroyed, this will be invoked once. If subsequent + // BinderRefs are created and then all destroyed, this will be invoked again. + // + // Similar to OnBinderTransaction, this is invoked from the binder thread pool + // and implementations must be thread-safe. + virtual void OnBinderDestroyed(); + + protected: + friend class RefCountedThreadSafe; + friend class BinderClassBase; + + virtual ~SupportsBinderBase(); + + // Creates a strong reference to the underlying IBinder, allocating a new + // IBinder if one did not already exist for this object. + BinderRef GetBinder(); + + private: + void OnBinderDestroyedBase(); + + // Binder class callbacks. + static void* OnIBinderCreate(void* self); + static void OnIBinderDestroy(void* self); + static binder_status_t OnIBinderTransact(AIBinder* binder, + transaction_code_t code, + const AParcel* in, + AParcel* out); + + const raw_ptr binder_class_; + + Lock lock_; + + // A weak reference to the underlying IBinder, if one exists. + raw_ptr weak_binder_ GUARDED_BY(lock_) = nullptr; + + // As long as any IBinder is alive for this object, we retain an extra ref + // count on `this` to ensure that transactions can be handled safely. + scoped_refptr self_for_binder_ GUARDED_BY(lock_); +}; + +} // namespace internal + +// A BinderRef which has been associated with a specific binder class. +template +class TypedBinderRef : public BinderRef { + public: + static_assert(std::is_base_of_v, + "Invalid binder class type"); + TypedBinderRef() = default; + + // Asserts that the binder can be associated with class T. This is safe to + // call when it's known that the binder hasn't been associated with any other + // class in the calling process yet. + explicit TypedBinderRef(BinderRef binder) { + CHECK(!binder || binder.AssociateWithClass(T::GetBinderClass())); + binder_ = binder.release(); + } + + TypedBinderRef(const TypedBinderRef&) = default; + TypedBinderRef& operator=(const TypedBinderRef&) = default; + TypedBinderRef(TypedBinderRef&&) = default; + TypedBinderRef& operator=(TypedBinderRef&&) = default; + ~TypedBinderRef() = default; + + // Adopts a BinderRef that is not already associated with another binder + // class, associating it with T. If `binder` is already associated with T this + // is a no-op which only narrows the ref type. + // + // If `binder` was already associated with a binder class other than T, the + // reference is dropped and this returns null. + // + // For convenience clients may instead prefer to call this method via + // T::AdoptBinderRef() as defined by DEFINE_BINDER_CLASS(T). + static TypedBinderRef Adopt(BinderRef binder) { + TypedBinderRef typed_binder; + if (binder.AssociateWithClass(T::GetBinderClass())) { + typed_binder.binder_ = binder.release(); + } + return typed_binder; + } + + // Prepares a new transaction on this binder, returning a Parcel that can be + // populated and then sent via Transact() or TransactOneWay() below. + BinderStatusOr PrepareTransaction() { + return BinderRef::PrepareTransaction(); + } + + // Transact with a `parcel` created by a call to PrepareTransaction() on the + // same binder. Returns the output parcel from the transaction. `code` is + // an arbitrary value with interface-specific meaning. + BinderStatusOr Transact(transaction_code_t code, Parcel parcel) { + return TransactImpl(code, std::move(parcel), /*flags=*/0); + } + + // Like Transact(), but this internally prepares a transacation and passes the + // allocated Parcel into `fn`. After `fn` returns the Parcel is transacted. + template + BinderStatusOr Transact(transaction_code_t code, Fn fn) { + ASSIGN_OR_RETURN(auto parcel, PrepareTransaction()); + RETURN_IF_ERROR(fn(ParcelWriter(parcel.get()))); + return Transact(code, std::move(parcel)); + } + + // Like Transact() but asynchronous. Discards the empty response parcel. + BinderStatusOr TransactOneWay(transaction_code_t code, Parcel parcel) { + RETURN_IF_ERROR(TransactImpl(code, std::move(parcel), FLAG_ONEWAY)); + return ok(); + } + + // Like TransactOneWay(), but this internally prepares a transaction + // passes the allocated Parcel into `fn`. After `fn` returns the Parcel is + // transacted. + template + BinderStatusOr TransactOneWay(transaction_code_t code, Fn fn) { + ASSIGN_OR_RETURN(auto parcel, PrepareTransaction()); + RETURN_IF_ERROR(fn(ParcelWriter(parcel.get()))); + return TransactOneWay(code, std::move(parcel)); + } +}; + +// Base class for objects which support native binder transactions. Example +// usage: +// +// // In some common header. +// DEFINE_BINDER_CLASS(ThingyInterface); +// +// // The interface implementation. +// class Thingy : public base::android::SupportsBinder { +// public: +// ... (normal class stuff, plus overrides of SupportsBinder methods) +// }; +// +// // The client. `ref` generally comes from the parent process untyped, +// // specifically from some SupportsBinder subclass calling GetBinder(). +// void UseThingy(BinderRef ref) { +// auto thingy = ThingyInterface::AdoptBinderRef(std::move(ref)); +// ... (do transactions with `thingy`) +// } +template +class BASE_EXPORT SupportsBinder : public internal::SupportsBinderBase { + public: + static_assert(std::is_base_of_v, + "Invalid binder class type"); + + SupportsBinder() : SupportsBinderBase(T::GetBinderClass()) {} + + // Creates a strong reference to the underlying IBinder, allocating a new + // IBinder if one did not already exist for this object. + TypedBinderRef GetBinder() { + return TypedBinderRef(SupportsBinderBase::GetBinder()); + } + + protected: + ~SupportsBinder() override = default; +}; + +// Indicates whether Binder NDK functionality is generally available to the +// caller. If this returns false, BinderRefs will always be null and +// SupportsBinder implementations will never receive binder transactions; but +// definitions within this header are otherwise still safe to reference and use. +BASE_EXPORT bool IsNativeBinderAvailable(); + +// Stashes a global collection of BinderRefs for later retrieval by +// TakeBinderFromParent(). This is intended for use by generic multiprocess +// support code to retain interfaces from the parent process so application- +// specific logic in the child process can retrieve them later. It should be +// called at most once per process, and as early as possible. +BASE_EXPORT void SetBindersFromParent(std::vector binders); + +// Retrieves (by index) a BinderRef which was stashed earlier by +// SetBindersFromParent(). If there is no binder for the given index, the +// returned BinderRef is null. This consumes the binder for that index, so +// subsequent calls for the same index will always return null. +BASE_EXPORT BinderRef TakeBinderFromParent(size_t index); + +} // namespace base::android + +#endif // BASE_ANDROID_BINDER_H_ diff --git a/naiveproxy/src/base/android/binder_box.cc b/naiveproxy/src/base/android/binder_box.cc new file mode 100644 index 0000000000..fa0481feeb --- /dev/null +++ b/naiveproxy/src/base/android/binder_box.cc @@ -0,0 +1,93 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/android/binder_box.h" + +#include +#include + +#include +#include +#include + +#include "base/android/binder.h" +#include "base/android/scoped_java_ref.h" +#include "base/types/expected_macros.h" + +namespace base::android { + +namespace { + +DEFINE_BINDER_CLASS(BinderBoxInterface); + +// Binder transaction support for PackBinderBox() and UnpackBinderBox(). +class BinderBox : public SupportsBinder { + static constexpr transaction_code_t kUnpack = 1; + + public: + explicit BinderBox(std::vector binders) + : binders_(std::move(binders)) {} + + ScopedJavaLocalRef GetJavaBinder(JNIEnv* env) { + return GetBinder().ToJavaBinder(env); + } + + static BinderStatusOr> Unpack( + JNIEnv* env, + const JavaRef& box) { + auto proxy = TypedBinderRef::Adopt( + BinderRef::FromJavaBinder(env, box.obj())); + if (!proxy) { + return unexpected(STATUS_BAD_TYPE); + } + ASSIGN_OR_RETURN(auto parcel, proxy.PrepareTransaction()); + ASSIGN_OR_RETURN(const auto reply, + proxy.Transact(kUnpack, std::move(parcel))); + ASSIGN_OR_RETURN(const size_t num_binders, reply.reader().ReadUint32()); + std::vector binders(num_binders); + for (size_t i = 0; i < num_binders; ++i) { + ASSIGN_OR_RETURN(binders[i], reply.reader().ReadBinder()); + } + return binders; + } + + private: + ~BinderBox() override = default; + + // SupportsBinder: + BinderStatusOr OnBinderTransaction(transaction_code_t code, + const ParcelReader& in, + const ParcelWriter& out) override { + if (code != kUnpack) { + return unexpected(STATUS_UNKNOWN_TRANSACTION); + } + const uint32_t num_binders = checked_cast(binders_.size()); + RETURN_IF_ERROR(out.WriteUint32(num_binders)); + for (uint32_t i = 0; i < num_binders; ++i) { + RETURN_IF_ERROR(out.WriteBinder(binders_[i])); + } + binders_.clear(); + return ok(); + } + + std::vector binders_; +}; + +} // namespace + +ScopedJavaLocalRef PackBinderBox(JNIEnv* env, + std::vector binders) { + if (binders.empty()) { + return nullptr; + } + return MakeRefCounted(std::move(binders))->GetJavaBinder(env); +} + +BinderStatusOr> UnpackBinderBox( + JNIEnv* env, + const JavaRef& box) { + return BinderBox::Unpack(env, box); +} + +} // namespace base::android diff --git a/naiveproxy/src/base/android/binder_box.h b/naiveproxy/src/base/android/binder_box.h new file mode 100644 index 0000000000..ae5236442a --- /dev/null +++ b/naiveproxy/src/base/android/binder_box.h @@ -0,0 +1,39 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ANDROID_BINDER_BOX_H_ +#define BASE_ANDROID_BINDER_BOX_H_ + +#include + +#include + +#include "base/android/binder.h" +#include "base/android/scoped_java_ref.h" +#include "base/base_export.h" + +namespace base::android { + +// Creates a new binder box containing `binders` and returns a Java reference to +// it. The Java reference (which itself is an android.os.IBinder) may be passed +// to another process and unpacked there by UnpackBinderBox(). +// +// The point of this thing is to conveniently pass native binders through Java +// code (e.g. across Java AIDL) without actually taking Java references to them. +// This is desirable because by design AIBinder_toJavaBinder actually leaks +// IBinder references for an indeterminate period of time, which is unacceptable +// for native binder users who want deterministic control of their binder's +// refcounts. +BASE_EXPORT ScopedJavaLocalRef PackBinderBox( + JNIEnv* env, + std::vector binders); + +// Retrieves a collection of binders stashed in a binder box. +BASE_EXPORT BinderStatusOr> UnpackBinderBox( + JNIEnv* env, + const JavaRef& box); + +} // namespace base::android + +#endif // BASE_ANDROID_BINDER_BOX_H_ diff --git a/naiveproxy/src/base/android/build_info.h b/naiveproxy/src/base/android/build_info.h index 9e9948aae5..b69f455589 100644 --- a/naiveproxy/src/base/android/build_info.h +++ b/naiveproxy/src/base/android/build_info.h @@ -37,6 +37,7 @@ enum SdkVersion { SDK_VERSION_Sv2 = 32, SDK_VERSION_T = 33, SDK_VERSION_U = 34, + SDK_VERSION_V = 35, }; // BuildInfo is a singleton class that stores android build and device diff --git a/naiveproxy/src/base/android/bundle_utils.cc b/naiveproxy/src/base/android/bundle_utils.cc index 9b47e6f40f..f0e7af2192 100644 --- a/naiveproxy/src/base/android/bundle_utils.cc +++ b/naiveproxy/src/base/android/bundle_utils.cc @@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #include "base/android/bundle_utils.h" #include @@ -16,6 +11,8 @@ #include "base/android/jni_string.h" #include "base/base_jni/BundleUtils_jni.h" #include "base/check.h" +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/notreached.h" @@ -40,8 +37,16 @@ namespace android { namespace { -const void* ReadRelPtr(const int32_t* relptr) { - return reinterpret_cast(relptr) + *relptr; +// Takes as input a "rel pointer", which is a pointer to a 32-bit integer that +// contains the offset to add to the pointer, in order to find the actual +// desired pointer address. +// +// # Safety +// If the value in the pointer does not provide an offset from the pointer that +// stays inside the same allocation, Undefined Behaviour can result. +UNSAFE_BUFFER_USAGE void* ReadRelPtr(int32_t* relptr) { + // SAFETY: This relies on the caller to provide a valid pointer + value. + return UNSAFE_BUFFERS(reinterpret_cast(relptr) + *relptr); } } // namespace @@ -80,15 +85,29 @@ void* BundleUtils::DlOpenModuleLibraryPartition(const std::string& library_name, // modified to sort the partitions. DCHECK(__part_index_begin != nullptr); DCHECK(__part_index_end != nullptr); - for (const PartitionIndexEntry* part = __part_index_begin; - part != __part_index_end; ++part) { - std::string name( - reinterpret_cast(ReadRelPtr(&part->name_relptr))); + // SAFETY: `__part_index_begin` and `__part_index_end` are provided by the + // linker (https://lld.llvm.org/Partitions.html) and we rely on the linker to + // provide pointers that are part of the same allocation with + // `__part_index_begin <= __part_index_end`. + auto parts = UNSAFE_BUFFERS( + span(__part_index_begin, __part_index_end)); + for (PartitionIndexEntry& part : parts) { + std::string name(static_cast( + // SAFETY: `name_relptr` plus its value points to a nul-terminated + // string containing the soname of the partition. This pointer and + // offset is provided by the linker and thus assumed to always be + // correct. https://lld.llvm.org/Partitions.html + UNSAFE_BUFFERS(ReadRelPtr(&part.name_relptr)))); if (name == partition) { android_dlextinfo info = {}; info.flags = ANDROID_DLEXT_RESERVED_ADDRESS; - info.reserved_addr = const_cast(ReadRelPtr(&part->addr_relptr)); - info.reserved_size = part->size; + info.reserved_addr = + // SAFETY: `addr_offset` field is a relative pointer to the + // partition's load address. This pointer and offset is provided by + // the linker and thus assumed to always be correct. + // https://lld.llvm.org/Partitions.html + UNSAFE_BUFFERS(ReadRelPtr(&part.addr_relptr)); + info.reserved_size = part.size; #if __ANDROID_API__ >= 24 return android_dlopen_ext(library_path.c_str(), RTLD_LOCAL, &info); diff --git a/naiveproxy/src/base/android/callback_android.h b/naiveproxy/src/base/android/callback_android.h index 1165d0f5c5..23c0d689c7 100644 --- a/naiveproxy/src/base/android/callback_android.h +++ b/naiveproxy/src/base/android/callback_android.h @@ -6,11 +6,13 @@ #define BASE_ANDROID_CALLBACK_ANDROID_H_ #include + #include #include #include "base/android/scoped_java_ref.h" #include "base/base_export.h" +#include "base/functional/callback.h" #include "base/time/time.h" #include "base/types/optional_ref.h" @@ -49,4 +51,16 @@ void BASE_EXPORT RunRunnableAndroid(const JavaRef& runnable); } // namespace android } // namespace base +namespace jni_zero { + +template <> +inline base::RepeatingClosure FromJniType( + JNIEnv* env, + const JavaRef& obj) { + return base::BindRepeating(&base::android::RunRunnableAndroid, + base::android::ScopedJavaGlobalRef(obj)); +} + +} // namespace jni_zero + #endif // BASE_ANDROID_CALLBACK_ANDROID_H_ diff --git a/naiveproxy/src/base/android/content_uri_utils.cc b/naiveproxy/src/base/android/content_uri_utils.cc index 24bd39d2ab..1234415731 100644 --- a/naiveproxy/src/base/android/content_uri_utils.cc +++ b/naiveproxy/src/base/android/content_uri_utils.cc @@ -32,6 +32,13 @@ File OpenContentUriForRead(const FilePath& content_uri) { return File(fd); } +int64_t GetContentUriFileSize(const FilePath& content_uri) { + JNIEnv* env = base::android::AttachCurrentThread(); + ScopedJavaLocalRef j_uri = + ConvertUTF8ToJavaString(env, content_uri.value()); + return Java_ContentUriUtils_getContentUriFileSize(env, j_uri); +} + std::string GetContentUriMimeType(const FilePath& content_uri) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef j_uri = diff --git a/naiveproxy/src/base/android/content_uri_utils.h b/naiveproxy/src/base/android/content_uri_utils.h index 33665f6cf7..c14515d0f8 100644 --- a/naiveproxy/src/base/android/content_uri_utils.h +++ b/naiveproxy/src/base/android/content_uri_utils.h @@ -18,6 +18,9 @@ namespace base { // Returns -1 if the URI is invalid. BASE_EXPORT File OpenContentUriForRead(const FilePath& content_uri); +// Gets file size, or -1 if file is unknown length. +BASE_EXPORT int64_t GetContentUriFileSize(const FilePath& content_uri); + // Check whether a content URI exists. BASE_EXPORT bool ContentUriExists(const FilePath& content_uri); diff --git a/naiveproxy/src/base/android/input_hint_checker.cc b/naiveproxy/src/base/android/input_hint_checker.cc index 0b021627bf..d60bd79fba 100644 --- a/naiveproxy/src/base/android/input_hint_checker.cc +++ b/naiveproxy/src/base/android/input_hint_checker.cc @@ -4,8 +4,14 @@ #include "base/android/input_hint_checker.h" +#include +#include + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" +#include "base/metrics/histogram_functions.h" #include "base/no_destructor.h" #include "base/time/time.h" @@ -14,6 +20,13 @@ namespace base::android { +enum class InputHintChecker::InitState { + kNotStarted, + kInProgress, + kInitialized, + kFailedToInitialize +}; + namespace { bool g_input_hint_enabled; @@ -35,6 +48,22 @@ BASE_FEATURE(kYieldWithInputHint, const base::FeatureParam kPollIntervalMillisParam{&kYieldWithInputHint, "poll_interval_ms", 3}; +// Class calling a private method of InputHintChecker. +// This allows not to declare the method called by pthread_create in the public +// header. +class InputHintChecker::OffThreadInitInvoker { + public: + // Called by pthread_create(). + static void* Run(void* opaque) { + InputHintChecker::GetInstance().RunOffThreadInitialization(); + return nullptr; + } +}; + +InputHintChecker::InputHintChecker() : init_state_(InitState::kNotStarted) {} + +InputHintChecker::~InputHintChecker() = default; + // static void InputHintChecker::InitializeFeatures() { bool is_enabled = base::FeatureList::IsEnabled(kYieldWithInputHint); @@ -44,20 +73,32 @@ void InputHintChecker::InitializeFeatures() { } } -bool InputHintChecker::HasInputImplWithThrottling() { +void InputHintChecker::SetView( + JNIEnv* env, + const jni_zero::JavaParamRef& root_view) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - auto now = base::TimeTicks::Now(); - if (last_checked_.is_null() || (now - last_checked_) >= g_poll_interval) { - last_checked_ = now; - // TODO(pasko): Implement fetching the hint from the system. - return false; + InitState state = FetchState(); + if (state == InitState::kFailedToInitialize) { + return; } - return false; -} - -void InputHintChecker::SetView(JNIEnv* env, jobject root_view) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); view_ = JavaObjectWeakGlobalRef(env, root_view); + if (!root_view) { + return; + } + if (state == InitState::kNotStarted) { + // Store the View.class and continue initialization on another thread. A + // separate non-Java thread is required to obtain a reference to + // j.l.reflect.Method via double-reflection. + TransitionToState(InitState::kInProgress); + view_class_ = + ScopedJavaGlobalRef(env, env->GetObjectClass(root_view.obj())); + pthread_t new_thread; + if (pthread_create(&new_thread, nullptr, OffThreadInitInvoker::Run, + nullptr) != 0) { + PLOG(ERROR) << "pthread_create"; + TransitionToState(InitState::kFailedToInitialize); + } + } } // static @@ -68,6 +109,184 @@ bool InputHintChecker::HasInput() { return GetInstance().HasInputImplWithThrottling(); } +bool InputHintChecker::IsInitializedForTesting() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return FetchState() == InitState::kInitialized; +} + +bool InputHintChecker::FailedToInitializeForTesting() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return FetchState() == InitState::kFailedToInitialize; +} + +bool InputHintChecker::HasInputImplWithThrottling() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + // Early return if off-thread initialization has not succeeded yet. + InitState state = FetchState(); + if (state != InitState::kInitialized) { + return false; + } + + // Input processing is associated with the root view. Early return when the + // root view is not available. It can happen in cases like multi-window. + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef scoped_view = view_.get(env); + if (!scoped_view) { + return false; + } + + // Throttle. + auto now = base::TimeTicks::Now(); + if (last_checked_.is_null() || (now - last_checked_) >= g_poll_interval) { + last_checked_ = now; + } else { + return false; + } + + return HasInputImpl(env, scoped_view.obj()); +} + +bool InputHintChecker::HasInputImplNoThrottlingForTesting(_JNIEnv* env) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (FetchState() != InitState::kInitialized) { + return false; + } + ScopedJavaLocalRef scoped_view = view_.get(env); + CHECK(scoped_view.obj()); + return HasInputImpl(env, scoped_view.obj()); +} + +bool InputHintChecker::HasInputImplWithThrottlingForTesting(_JNIEnv* env) { + if (FetchState() != InitState::kInitialized) { + return false; + } + return HasInputImplWithThrottling(); +} + +bool InputHintChecker::HasInputImpl(JNIEnv* env, jobject o) { + auto has_input_result = ScopedJavaLocalRef::Adopt( + env, env->CallObjectMethod(reflect_method_for_has_input_.obj(), + invoke_id_, o, nullptr)); + if (ClearException(env)) { + LOG(ERROR) << "Exception when calling reflect_method_for_has_input_"; + TransitionToState(InitState::kFailedToInitialize); + return false; + } + if (!has_input_result) { + LOG(ERROR) << "Returned null from reflection call"; + TransitionToState(InitState::kFailedToInitialize); + return false; + } + + // Convert result to bool and return. + bool value = static_cast( + env->CallBooleanMethod(has_input_result.obj(), boolean_value_id_)); + if (ClearException(env)) { + LOG(ERROR) << "Exception when converting to boolean"; + TransitionToState(InitState::kFailedToInitialize); + return false; + } + return value; +} + +InputHintChecker::InitState InputHintChecker::FetchState() const { + return init_state_.load(std::memory_order_acquire); +} + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class InitializationResult { + kSuccess = 0, + kFailure = 1, + kMaxValue = kFailure, +}; + +void InputHintChecker::TransitionToState(InitState new_state) { + DCHECK_NE(new_state, FetchState()); + if (new_state == InitState::kInitialized || + new_state == InitState::kFailedToInitialize) { + InitializationResult r = (new_state == InitState::kInitialized) + ? InitializationResult::kSuccess + : InitializationResult::kFailure; + UmaHistogramEnumeration("Android.InputHintChecker.InitializationResult", r); + } + init_state_.store(new_state, std::memory_order_release); +} + +void InputHintChecker::RunOffThreadInitialization() { + JNIEnv* env = AttachCurrentThread(); + InitGlobalRefsAndMethodIds(env); + DetachFromVM(); +} + +void InputHintChecker::InitGlobalRefsAndMethodIds(JNIEnv* env) { + // Obtain j.l.reflect.Method using View.class.getMethod("probablyHasInput", + // "..."). + jclass view_class = env->GetObjectClass(view_class_.obj()); + if (ClearException(env)) { + LOG(ERROR) << "exception on GetObjectClass(view)"; + TransitionToState(InitState::kFailedToInitialize); + return; + } + jmethodID get_method_id = env->GetMethodID( + view_class, "getMethod", + "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"); + if (ClearException(env)) { + LOG(ERROR) << "exception when looking for method getMethod()"; + TransitionToState(InitState::kFailedToInitialize); + return; + } + ScopedJavaLocalRef has_input_string = + ConvertUTF8ToJavaString(env, "probablyHasInput"); + auto method = ScopedJavaLocalRef::Adopt( + env, env->CallObjectMethod(view_class_.obj(), get_method_id, + has_input_string.obj(), nullptr)); + if (ClearException(env)) { + LOG(ERROR) << "exception when calling getMethod(probablyHasInput)"; + TransitionToState(InitState::kFailedToInitialize); + return; + } + if (!method) { + LOG(ERROR) << "got null from getMethod(probablyHasInput)"; + TransitionToState(InitState::kFailedToInitialize); + return; + } + + // Cache useful members for further calling Method.invoke(view). + reflect_method_for_has_input_ = ScopedJavaGlobalRef(method); + jclass method_class = + env->GetObjectClass(reflect_method_for_has_input_.obj()); + if (ClearException(env) || !method_class) { + LOG(ERROR) << "exception on GetObjectClass(getMethod) or null returned"; + TransitionToState(InitState::kFailedToInitialize); + return; + } + invoke_id_ = env->GetMethodID( + method_class, "invoke", + "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); + if (ClearException(env)) { + LOG(ERROR) << "exception when looking for invoke() of getMethod()"; + TransitionToState(InitState::kFailedToInitialize); + return; + } + jclass boolean_class = env->FindClass("java/lang/Boolean"); + if (ClearException(env) || !boolean_class) { + LOG(ERROR) << "exception when looking for class Boolean or null returned"; + TransitionToState(InitState::kFailedToInitialize); + return; + } + boolean_value_id_ = env->GetMethodID(boolean_class, "booleanValue", "()Z"); + if (ClearException(env)) { + LOG(ERROR) << "exception when looking for method booleanValue"; + TransitionToState(InitState::kFailedToInitialize); + return; + } + + // Publish the obtained members to the thread observing kInitialized. + TransitionToState(InitState::kInitialized); +} + InputHintChecker& InputHintChecker::GetInstance() { static NoDestructor checker; if (g_test_instance) { @@ -86,8 +305,27 @@ InputHintChecker::ScopedOverrideInstance::~ScopedOverrideInstance() { } void JNI_InputHintChecker_SetView(_JNIEnv* env, - const JavaParamRef& v) { - InputHintChecker::GetInstance().SetView(env, v.obj()); + const jni_zero::JavaParamRef& v) { + InputHintChecker::GetInstance().SetView(env, v); +} + +jboolean JNI_InputHintChecker_IsInitializedForTesting(_JNIEnv* env) { + return InputHintChecker::GetInstance().IsInitializedForTesting(); // IN-TEST +} + +jboolean JNI_InputHintChecker_FailedToInitializeForTesting(_JNIEnv* env) { + return InputHintChecker::GetInstance() + .FailedToInitializeForTesting(); // IN-TEST +} + +jboolean JNI_InputHintChecker_HasInputForTesting(_JNIEnv* env) { + InputHintChecker& checker = InputHintChecker::GetInstance(); + return checker.HasInputImplNoThrottlingForTesting(env); // IN-TEST +} + +jboolean JNI_InputHintChecker_HasInputWithThrottlingForTesting(_JNIEnv* env) { + InputHintChecker& checker = InputHintChecker::GetInstance(); + return checker.HasInputImplWithThrottlingForTesting(env); // IN-TEST } } // namespace base::android diff --git a/naiveproxy/src/base/android/input_hint_checker.h b/naiveproxy/src/base/android/input_hint_checker.h index f466644e74..5bc7bc7bd7 100644 --- a/naiveproxy/src/base/android/input_hint_checker.h +++ b/naiveproxy/src/base/android/input_hint_checker.h @@ -5,6 +5,8 @@ #ifndef BASE_ANDROID_INPUT_HINT_CHECKER_H_ #define BASE_ANDROID_INPUT_HINT_CHECKER_H_ +#include + #include "base/android/jni_weak_ref.h" #include "base/base_export.h" #include "base/feature_list.h" @@ -27,8 +29,8 @@ BASE_DECLARE_FEATURE(kYieldWithInputHint); // thread. class BASE_EXPORT InputHintChecker { public: - InputHintChecker() = default; - virtual ~InputHintChecker() = default; + InputHintChecker(); + virtual ~InputHintChecker(); // Returns the singleton. static InputHintChecker& GetInstance(); @@ -39,11 +41,19 @@ class BASE_EXPORT InputHintChecker { // Obtains a weak reference to |root_view| so that the following calls to // HasInput() take the input hint for this View. Requirements for the View // object are described in InputHintChecker.java. - void SetView(JNIEnv* env, jobject root_view); + void SetView(JNIEnv* env, const jni_zero::JavaParamRef& root_view); - // Fetches and returns the input hint from the Android Framework. Throttles - // the calls to one every few milliseconds. When a call is made before the - // minimal time interval passed since the previous call, returns false. + // Fetches and returns the input hint from the Android Framework. + // + // Works as a hint: when unhandled input events are detected, this method + // returns |true| with high probability. However, the returned value neither + // guarantees presence nor absence of input events in the queue. For example, + // this method returns |false| while the singleton is going through + // initialization. + // + // Throttles the calls to one every few milliseconds. When a call is made + // before the minimal time interval passed since the previous call, returns + // false. static bool HasInput() { return false; } // RAII override of GetInstance() for testing. @@ -52,15 +62,49 @@ class BASE_EXPORT InputHintChecker { ~ScopedOverrideInstance(); }; + bool IsInitializedForTesting(); + bool FailedToInitializeForTesting(); + bool HasInputImplNoThrottlingForTesting(_JNIEnv* env); + bool HasInputImplWithThrottlingForTesting(_JNIEnv* env); + protected: virtual bool HasInputImplWithThrottling(); private: friend class base::NoDestructor; + class OffThreadInitInvoker; + enum class InitState; + InitState FetchState() const; + void TransitionToState(InitState new_state); + void RunOffThreadInitialization(); + void InitGlobalRefsAndMethodIds(JNIEnv* env); + bool HasInputImpl(JNIEnv* env, jobject o); - JavaObjectWeakGlobalRef view_; - THREAD_CHECKER(thread_checker_); base::TimeTicks last_checked_; + + // Initialization state. It is made atomic because part of the initialization + // happens on another thread while public methods of this class can be called + // on the UI thread. + std::atomic init_state_; + + // The android.view.View object reference used to fetch the hint in + // HasInput(). + JavaObjectWeakGlobalRef view_; + + // Represents a reference to android.view.View.class. Used during + // initialization. + ScopedJavaGlobalRef view_class_; + + // Represents a reference to object of type j.l.reflect.Method for + // View#probablyHasInput(). + ScopedJavaGlobalRef reflect_method_for_has_input_; + + // The ID corresponding to j.l.reflect.Method#invoke(Object, Object...). + jmethodID invoke_id_; + + // The ID corresponding to j.l.Boolean#booleanValue(). + jmethodID boolean_value_id_; + THREAD_CHECKER(thread_checker_); }; } // namespace base::android diff --git a/naiveproxy/src/base/android/jni_android.cc b/naiveproxy/src/base/android/jni_android.cc index 47d0167c09..c4d651b0ad 100644 --- a/naiveproxy/src/base/android/jni_android.cc +++ b/naiveproxy/src/base/android/jni_android.cc @@ -14,6 +14,7 @@ #include "base/debug/debugging_buildflags.h" #include "base/feature_list.h" #include "base/logging.h" +#include "base/strings/string_util.h" #include "build/build_config.h" #include "build/robolectric_buildflags.h" #include "third_party/abseil-cpp/absl/base/attributes.h" @@ -50,9 +51,11 @@ jmethodID g_class_loader_load_class_method_id = nullptr; jclass GetClassFromSplit(JNIEnv* env, const char* class_name, const char* split_name) { + DCHECK(IsStringASCII(class_name)); + ScopedJavaLocalRef j_class_name(env, env->NewStringUTF(class_name)); return static_cast(env->CallObjectMethod( GetSplitClassLoader(env, split_name), g_class_loader_load_class_method_id, - ConvertUTF8ToJavaString(env, class_name).obj())); + j_class_name.obj())); } // Must be called before using GetClassFromSplit - we need to set the global, diff --git a/naiveproxy/src/base/android/jni_string.cc b/naiveproxy/src/base/android/jni_string.cc index 008cef4b1e..2df1b05949 100644 --- a/naiveproxy/src/base/android/jni_string.cc +++ b/naiveproxy/src/base/android/jni_string.cc @@ -84,6 +84,10 @@ std::string ConvertJavaStringToUTF8(JNIEnv* env, const JavaRef& str) { ScopedJavaLocalRef ConvertUTF8ToJavaString(JNIEnv* env, std::string_view str) { + // ART allocates new empty strings, so use a singleton when applicable. + if (str.empty()) { + return jni_zero::g_empty_string.AsLocalRef(env); + } // JNI's NewStringUTF expects "modified" UTF8 so instead create the string // via our own UTF16 conversion utility. // Further, Dalvik requires the string passed into NewStringUTF() to come from @@ -150,6 +154,10 @@ std::u16string ConvertJavaStringToUTF16(JNIEnv* env, ScopedJavaLocalRef ConvertUTF16ToJavaString(JNIEnv* env, std::u16string_view str) { + // ART allocates new empty strings, so use a singleton when applicable. + if (str.empty()) { + return jni_zero::g_empty_string.AsLocalRef(env); + } return ScopedJavaLocalRef(env, ConvertUTF16ToJavaStringImpl(env, str)); } diff --git a/naiveproxy/src/base/android/jni_weak_ref.cc b/naiveproxy/src/base/android/jni_weak_ref.cc deleted file mode 100644 index 4244fcfcba..0000000000 --- a/naiveproxy/src/base/android/jni_weak_ref.cc +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/android/jni_weak_ref.h" - -#include - -#include "base/android/jni_android.h" - -using base::android::AttachCurrentThread; - -JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef() : obj_(nullptr) {} - -JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef( - const JavaObjectWeakGlobalRef& orig) - : obj_(nullptr) { - Assign(orig); -} - -JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef( - JavaObjectWeakGlobalRef&& orig) noexcept - : obj_(orig.obj_) { - orig.obj_ = nullptr; -} - -JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef(JNIEnv* env, jobject obj) - : obj_(env->NewWeakGlobalRef(obj)) { -} - -JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef( - JNIEnv* env, - const base::android::JavaRef& obj) - : obj_(env->NewWeakGlobalRef(obj.obj())) { -} - -JavaObjectWeakGlobalRef::~JavaObjectWeakGlobalRef() { - reset(); -} - -void JavaObjectWeakGlobalRef::operator=(const JavaObjectWeakGlobalRef& rhs) { - Assign(rhs); -} - -void JavaObjectWeakGlobalRef::operator=(JavaObjectWeakGlobalRef&& rhs) { - std::swap(obj_, rhs.obj_); -} - -void JavaObjectWeakGlobalRef::reset() { - if (obj_) { - AttachCurrentThread()->DeleteWeakGlobalRef(obj_); - obj_ = nullptr; - } -} - -base::android::ScopedJavaLocalRef - JavaObjectWeakGlobalRef::get(JNIEnv* env) const { - return GetRealObject(env, obj_); -} - -base::android::ScopedJavaLocalRef GetRealObject( - JNIEnv* env, jweak obj) { - jobject real = nullptr; - if (obj) - real = env->NewLocalRef(obj); - return base::android::ScopedJavaLocalRef(env, real); -} - -void JavaObjectWeakGlobalRef::Assign(const JavaObjectWeakGlobalRef& other) { - if (&other == this) - return; - - JNIEnv* env = AttachCurrentThread(); - if (obj_) - env->DeleteWeakGlobalRef(obj_); - - obj_ = other.obj_ ? env->NewWeakGlobalRef(other.obj_) : nullptr; -} diff --git a/naiveproxy/src/base/android/jni_weak_ref.h b/naiveproxy/src/base/android/jni_weak_ref.h index d97952929d..6ed916e747 100644 --- a/naiveproxy/src/base/android/jni_weak_ref.h +++ b/naiveproxy/src/base/android/jni_weak_ref.h @@ -5,47 +5,9 @@ #ifndef BASE_ANDROID_JNI_WEAK_REF_H_ #define BASE_ANDROID_JNI_WEAK_REF_H_ -#include - #include "base/android/scoped_java_ref.h" -#include "base/base_export.h" +#include "third_party/jni_zero/jni_zero.h" -// Manages WeakGlobalRef lifecycle. -// This class is not thread-safe w.r.t. get() and reset(). Multiple threads may -// safely use get() concurrently, but if the user calls reset() (or of course, -// calls the destructor) they'll need to provide their own synchronization. -class BASE_EXPORT JavaObjectWeakGlobalRef { - public: - JavaObjectWeakGlobalRef(); - JavaObjectWeakGlobalRef(const JavaObjectWeakGlobalRef& orig); - JavaObjectWeakGlobalRef(JavaObjectWeakGlobalRef&& orig) noexcept; - JavaObjectWeakGlobalRef(JNIEnv* env, jobject obj); - JavaObjectWeakGlobalRef(JNIEnv* env, - const base::android::JavaRef& obj); - virtual ~JavaObjectWeakGlobalRef(); - - void operator=(const JavaObjectWeakGlobalRef& rhs); - void operator=(JavaObjectWeakGlobalRef&& rhs); - - base::android::ScopedJavaLocalRef get(JNIEnv* env) const; - - // Returns true if the weak reference has not been initialized to point at - // an object (or ḣas had reset() called). - // Do not call this to test if the object referred to still exists! The weak - // reference remains initialized even if the target object has been collected. - bool is_uninitialized() const { return obj_ == nullptr; } - - void reset(); - - private: - void Assign(const JavaObjectWeakGlobalRef& rhs); - - jweak obj_; -}; - -// Get the real object stored in the weak reference returned as a -// ScopedJavaLocalRef. -BASE_EXPORT base::android::ScopedJavaLocalRef GetRealObject( - JNIEnv* env, jweak obj); +using JavaObjectWeakGlobalRef = jni_zero::ScopedJavaGlobalWeakRef; #endif // BASE_ANDROID_JNI_WEAK_REF_H_ diff --git a/naiveproxy/src/base/android/library_loader/anchor_functions.lds b/naiveproxy/src/base/android/library_loader/anchor_functions.lds index 8bd7876b29..4b47f1f1fc 100644 --- a/naiveproxy/src/base/android/library_loader/anchor_functions.lds +++ b/naiveproxy/src/base/android/library_loader/anchor_functions.lds @@ -4,4 +4,8 @@ # Define symbols that point to the start and end of the .text section. PROVIDE_HIDDEN(linker_script_start_of_text = ADDR(.text)); -PROVIDE_HIDDEN(linker_script_end_of_text = ADDR(.text) + SIZEOF(.text)); + +# The `malloc_hook` section comes from function attributes set in +# third_party/abseil-cpp. See http://crbug.com/352317042. +PROVIDE_HIDDEN(linker_script_end_of_text = + ADDR(.text) + SIZEOF(.text) + SIZEOF(malloc_hook)); diff --git a/naiveproxy/src/base/android/orderfile/orderfile_instrumentation.cc b/naiveproxy/src/base/android/orderfile/orderfile_instrumentation.cc index d5cf80f808..ebefbd18ff 100644 --- a/naiveproxy/src/base/android/orderfile/orderfile_instrumentation.cc +++ b/naiveproxy/src/base/android/orderfile/orderfile_instrumentation.cc @@ -44,9 +44,7 @@ // Must be applied to all functions within this file. #define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function)) -namespace base { -namespace android { -namespace orderfile { +namespace base::android::orderfile { namespace { // Constants used for StartDelayedDump(). @@ -145,14 +143,13 @@ __attribute__((always_inline, no_instrument_function)) void RecordAddress( ImmediateCrash(); } - // We should really crash at the first instance, but it does happen on bots, - // for a mysterious reason. Give it some leeway. Note that since we don't - // remember the caller address, if a single function is misplaced but we get - // many calls to it, then we still crash. If this is the case, add - // deduplication. - // - // Bumped to 100 temporarily as part of crbug.com/1265928 investigation. - if (g_unexpected_addresses.fetch_add(1, std::memory_order_relaxed) < 100) { + // Observing return addresses outside of the intended range indicates a + // potentially serious problem in the way the build is set up. However, a + // small number of unexpected addresses is tolerable for production builds. + // It seems useful to allow a limited number of out-of-range addresses to + // let the orderfile_generator guess the root causes. See + // crbug.com/330761384, crbug.com/352317042. + if (g_unexpected_addresses.fetch_add(1, std::memory_order_relaxed) < 10) { return; } @@ -352,9 +349,7 @@ NO_INSTRUMENT_FUNCTION std::vector GetOrderedOffsetsForTesting() { return result; } -} // namespace orderfile -} // namespace android -} // namespace base +} // namespace base::android::orderfile extern "C" { diff --git a/naiveproxy/src/base/android/proguard/chromium_apk.flags b/naiveproxy/src/base/android/proguard/chromium_apk.flags index fb46265a47..bbb5a1c4ff 100644 --- a/naiveproxy/src/base/android/proguard/chromium_apk.flags +++ b/naiveproxy/src/base/android/proguard/chromium_apk.flags @@ -24,7 +24,7 @@ # If we annotated all Parcelables that get put into Bundles other than # for saveInstanceState (e.g. PendingIntents), then we could actually keep the # names of just those ones. For now, we'll just keep them all. --keepnames class !cr_allowunused,** implements android.os.Parcelable {} +-keepnames,allowaccessmodification class !cr_allowunused,** implements android.os.Parcelable {} # Keep all default constructors for used Fragments. Required since they are # called reflectively when fragments are reinflated after the app is killed. @@ -67,7 +67,7 @@ # Keep the names of exception types, to make it easier to understand stack # traces in contexts where it's not trivial to deobfuscate them - for example # when reported to app developers who are using WebView. --keepnames class ** extends java.lang.Throwable {} +-keepnames,allowaccessmodification class ** extends java.lang.Throwable {} # Should be removed once we use Android V SDK. b/336753747 -keep class !cr_allowunused,androidx.privacysandbox.ads.adservices.internal.ContinuationOutcomeReceiver { diff --git a/naiveproxy/src/base/check_deref.h b/naiveproxy/src/base/check_deref.h index 8be25de078..e719406819 100644 --- a/naiveproxy/src/base/check_deref.h +++ b/naiveproxy/src/base/check_deref.h @@ -32,7 +32,10 @@ namespace logging { ::logging::CheckDeref(ptr, #ptr " != nullptr", __FILE__, __LINE__) template -T& CheckDeref(T* ptr, const char* message, const char* file, int line) { +[[nodiscard]] T& CheckDeref(T* ptr, + const char* message, + const char* file, + int line) { // Note: we can't just call `CHECK_NE(ptr, nullptr)` here, as that would // cause the error to be reported from this header, and we want the error // to be reported at the file and line of the caller. diff --git a/naiveproxy/src/base/check_op.cc b/naiveproxy/src/base/check_op.cc index 108339261f..bc0e1c4f65 100644 --- a/naiveproxy/src/base/check_op.cc +++ b/naiveproxy/src/base/check_op.cc @@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #include "base/check_op.h" #include @@ -15,7 +10,9 @@ #include #include +#include "base/containers/span.h" #include "base/logging.h" +#include "base/strings/cstring_view.h" namespace logging { @@ -70,15 +67,23 @@ char* CheckOpValueStr(const std::string& v) { } char* CheckOpValueStr(std::string_view v) { - // Ideally this would be `strndup`, but `strndup` is not portable. - char* ret = static_cast(malloc(v.size() + 1)); - if (ret) { - std::copy(v.begin(), v.end(), ret); - ret[v.size()] = 0; - } + // Ideally this would be `strndup`, but `strndup` is not portable. We have to + // use malloc() instead of HeapArray in order to match strdup() in the other + // overloads. The API contract is that the caller uses free() to release the + // pointer returned here. + char* ret = static_cast(malloc(v.size() + 1u)); + auto [val, nul] = + // SAFETY: We allocated `ret` as `v.size() + 1` bytes above. + UNSAFE_BUFFERS(base::span(ret, v.size() + 1u)).split_at(v.size()); + val.copy_from(v); + nul.copy_from({{'\0'}}); return ret; } +char* CheckOpValueStr(base::cstring_view v) { + return strdup(v.c_str()); +} + char* CheckOpValueStr(double v) { char buf[50]; snprintf(buf, sizeof(buf), "%.6lf", v); diff --git a/naiveproxy/src/base/check_op.h b/naiveproxy/src/base/check_op.h index 080d822faa..8673532e4f 100644 --- a/naiveproxy/src/base/check_op.h +++ b/naiveproxy/src/base/check_op.h @@ -38,6 +38,11 @@ // you use e.g. both CHECK_EQ and CHECK, including this header is enough. If you // only use CHECK however, please include the smaller check.h instead. +namespace base { +template +class basic_cstring_view; +} + namespace logging { // Functions for turning check operand values into NUL-terminated C strings. @@ -59,6 +64,7 @@ BASE_EXPORT char* CheckOpValueStr(double v); // versions here too. BASE_EXPORT char* CheckOpValueStr(const std::string& v); BASE_EXPORT char* CheckOpValueStr(std::string_view v); +BASE_EXPORT char* CheckOpValueStr(base::basic_cstring_view v); // Convert a streamable value to string out-of-line to avoid . BASE_EXPORT char* StreamValToStr(const void* v, diff --git a/naiveproxy/src/base/compiler_specific.h b/naiveproxy/src/base/compiler_specific.h index 52f00a951d..55e0278c6d 100644 --- a/naiveproxy/src/base/compiler_specific.h +++ b/naiveproxy/src/base/compiler_specific.h @@ -84,6 +84,16 @@ #define NOT_TAIL_CALLED #endif +// Annotate a function indicating it must be tail called. +// Can be used only on return statements, even for functions returning void. +// Caller and callee must have the same number of arguments and its types must +// be "similar". +#if defined(__clang__) && HAS_ATTRIBUTE(musttail) +#define MUSTTAIL [[clang::musttail]] +#else +#define MUSTTAIL +#endif + // Specify memory alignment for structs, classes, etc. // Use like: // class ALIGNAS(16) MyClass { ... } diff --git a/naiveproxy/src/base/containers/buffer_iterator.h b/naiveproxy/src/base/containers/buffer_iterator.h index 0fa382d427..9f4dada9d8 100644 --- a/naiveproxy/src/base/containers/buffer_iterator.h +++ b/naiveproxy/src/base/containers/buffer_iterator.h @@ -12,6 +12,7 @@ #include "base/compiler_specific.h" #include "base/containers/span.h" +#include "base/memory/raw_span.h" #include "base/numerics/checked_math.h" namespace base { @@ -231,9 +232,9 @@ class BufferIterator { private: // The original buffer that the iterator was constructed with. - const span buffer_; + const raw_span buffer_; // A subspan of `buffer_` containing the remaining bytes to iterate over. - span remaining_; + raw_span remaining_; // Copy and assign allowed. }; diff --git a/naiveproxy/src/base/containers/checked_iterators.h b/naiveproxy/src/base/containers/checked_iterators.h index ee9859b4c5..312a8ddaeb 100644 --- a/naiveproxy/src/base/containers/checked_iterators.h +++ b/naiveproxy/src/base/containers/checked_iterators.h @@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #ifndef BASE_CONTAINERS_CHECKED_ITERATORS_H_ #define BASE_CONTAINERS_CHECKED_ITERATORS_H_ @@ -44,10 +39,27 @@ class CheckedContiguousIterator { constexpr CheckedContiguousIterator() = default; + // Constructs an iterator from `start` to `end`, starting at `start`. + // + // # Safety + // `start` and `end` must point to a single allocation. + // + // # Checks + // This function CHECKs that `start <= end` and will terminate otherwise. UNSAFE_BUFFER_USAGE constexpr CheckedContiguousIterator(T* start, const T* end) - : CheckedContiguousIterator(start, start, end) {} + : start_(start), current_(start), end_(end) { + CHECK_LE(start, end); + } + // Constructs an iterator from `start` to `end`, starting at `current`. + // + // # Safety + // `start`, `current` and `end` must point to a single allocation. + // + // # Checks + // This function CHECKs that `start <= current <= end` and will terminate + // otherwise. UNSAFE_BUFFER_USAGE constexpr CheckedContiguousIterator(const T* start, T* current, const T* end) @@ -94,7 +106,10 @@ class CheckedContiguousIterator { constexpr CheckedContiguousIterator& operator++() { CHECK_NE(current_, end_); - ++current_; + // SAFETY: `current_ <= end_` is an invariant maintained internally, and the + // CHECK above ensures that we are not at the end yet, so incrementing stays + // in bounds of the allocation. + UNSAFE_BUFFERS(++current_); return *this; } @@ -106,7 +121,10 @@ class CheckedContiguousIterator { constexpr CheckedContiguousIterator& operator--() { CHECK_NE(current_, start_); - --current_; + // SAFETY: `current_ >= start_` is an invariant maintained internally, and + // the CHECK above ensures that we are not at the start yet, so decrementing + // stays in bounds of the allocation. + UNSAFE_BUFFERS(--current_); return *this; } @@ -117,12 +135,17 @@ class CheckedContiguousIterator { } constexpr CheckedContiguousIterator& operator+=(difference_type rhs) { - if (rhs > 0) { - CHECK_LE(rhs, end_ - current_); - } else { - CHECK_LE(-rhs, current_ - start_); - } - current_ += rhs; + // NOTE: Since the max allocation size is PTRDIFF_MAX (in our compilers), + // subtracting two pointers from the same allocation can not underflow. + CHECK_LE(rhs, end_ - current_); + CHECK_GE(rhs, start_ - current_); + // SAFETY: `current_ <= end_` is an invariant maintained internally. The + // checks above ensure: + // `start_ - current_ <= rhs <= end_ - current_`. + // Which means: + // `start_ <= rhs + current <= end_`, so `current_` will remain in bounds of + // the allocation after adding `rhs`. + UNSAFE_BUFFERS(current_ += rhs); return *this; } @@ -139,12 +162,17 @@ class CheckedContiguousIterator { } constexpr CheckedContiguousIterator& operator-=(difference_type rhs) { - if (rhs < 0) { - CHECK_LE(-rhs, end_ - current_); - } else { - CHECK_LE(rhs, current_ - start_); - } - current_ -= rhs; + // NOTE: Since the max allocation size is PTRDIFF_MAX (in our compilers), + // subtracting two pointers from the same allocation can not underflow. + CHECK_GE(rhs, current_ - end_); + CHECK_LE(rhs, current_ - start_); + // SAFETY: `start_ <= current_` is an invariant maintained internally. The + // checks above ensure: + // `current_ - end_ <= rhs <= current_ - start_`. + // Which means: + // `end_ >= current - rhs >= start_`, so `current_` will remain in bounds + // of the allocation after subtracting `rhs`. + UNSAFE_BUFFERS(current_ -= rhs); return *this; } @@ -172,17 +200,27 @@ class CheckedContiguousIterator { } constexpr reference operator[](difference_type rhs) const { - CHECK_GE(rhs, 0); + // NOTE: Since the max allocation size is PTRDIFF_MAX (in our compilers), + // subtracting two pointers from the same allocation can not underflow. + CHECK_GE(rhs, start_ - current_); CHECK_LT(rhs, end_ - current_); - return current_[rhs]; + // SAFETY: `start_ <= current_ <= end_` is an invariant maintained + // internally. The checks above ensure: + // `start_ - current_ <= rhs < end_ - current_`. + // Which means: + // `start_ <= current_ + rhs < end_`. + // So `current_[rhs]` will be a valid dereference of a pointer in the + // allocation (it is not the pointer toone-past-the-end). + return UNSAFE_BUFFERS(current_[rhs]); } [[nodiscard]] static bool IsRangeMoveSafe( const CheckedContiguousIterator& from_begin, const CheckedContiguousIterator& from_end, const CheckedContiguousIterator& to) { - if (from_end < from_begin) + if (from_end < from_begin) { return false; + } const auto from_begin_uintptr = get_uintptr(from_begin.current_); const auto from_end_uintptr = get_uintptr(from_end.current_); const auto to_begin_uintptr = get_uintptr(to.current_); diff --git a/naiveproxy/src/base/containers/circular_deque.h b/naiveproxy/src/base/containers/circular_deque.h index d960715958..4b0cafe4f3 100644 --- a/naiveproxy/src/base/containers/circular_deque.h +++ b/naiveproxy/src/base/containers/circular_deque.h @@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #ifndef BASE_CONTAINERS_CIRCULAR_DEQUE_H_ #define BASE_CONTAINERS_CIRCULAR_DEQUE_H_ @@ -17,11 +12,14 @@ #include #include "base/check.h" +#include "base/containers/span.h" #include "base/containers/vector_buffer.h" #include "base/dcheck_is_on.h" #include "base/memory/raw_ptr_exclusion.h" +#include "base/numerics/checked_math.h" +#include "base/numerics/safe_conversions.h" #include "base/ranges/algorithm.h" -#include "base/template_util.h" +#include "base/ranges/from_range.h" #if DCHECK_IS_ON() #include @@ -52,6 +50,7 @@ // circular_deque(size_t count); // circular_deque(size_t count, const T& value); // circular_deque(InputIterator first, InputIterator last); +// circular_deque(base::from_range_t, Range range); // circular_deque(const circular_deque&); // circular_deque(circular_deque&&); // circular_deque(std::initializer_list); @@ -63,6 +62,7 @@ // void assign(size_t count, const T& value); // void assign(InputIterator first, InputIterator last); // void assign(std::initializer_list value); +// void assign_range(Range range); // // Random accessors: // T& at(size_t); @@ -141,28 +141,36 @@ constexpr size_t kCircularBufferInitialCapacity = 3; template class circular_deque_const_iterator { public: - using difference_type = std::ptrdiff_t; + using difference_type = ptrdiff_t; using value_type = T; using pointer = const T*; using reference = const T&; using iterator_category = std::random_access_iterator_tag; - circular_deque_const_iterator() : parent_deque_(nullptr), index_(0) { -#if DCHECK_IS_ON() - created_generation_ = 0; -#endif // DCHECK_IS_ON() - } + circular_deque_const_iterator() = default; // Dereferencing. const T& operator*() const { + CHECK_NE(index_, end_); CheckUnstableUsage(); - parent_deque_->CheckValidIndex(index_); - return parent_deque_->buffer_[index_]; + CheckValidIndex(index_); + // SAFETY: Increment() and Decrement() and Add() operations ensure that + // `index_` stays inside [begin_, end_] (while supporting wrap around for + // the structure. This maintains that `index_` always points at a + // valid position for the `buffer_`. We also CHECK above that `index_` is + // not `end_` making it a valid pointer to dereference. + return UNSAFE_BUFFERS(buffer_[index_]); } const T* operator->() const { + CHECK_NE(index_, end_); CheckUnstableUsage(); - parent_deque_->CheckValidIndex(index_); - return &parent_deque_->buffer_[index_]; + CheckValidIndex(index_); + // SAFETY: Increment() and Decrement() and Add() operations ensure that + // `index_` stays inside [begin_, end_] while supporting wrap around for + // the structure. This maintains that `index_` always points at a + // valid position for the `buffer_`. We also CHECK above that `index_` is + // not `end_` making it a valid pointer to dereference. + return &UNSAFE_BUFFERS(buffer_[index_]); } const value_type& operator[](difference_type i) const { return *(*this + i); } @@ -236,8 +244,21 @@ class circular_deque_const_iterator { friend class circular_deque; circular_deque_const_iterator(const circular_deque* parent, size_t index) - : parent_deque_(parent), index_(index) { + : buffer_(parent->buffer_.data()), + cap_(parent->buffer_.capacity()), + begin_(parent->begin_), + end_(parent->end_), + index_(index) { + if (begin_ <= end_) { + CHECK_GE(index_, begin_); + CHECK_LE(index_, end_); + } else if (index_ >= begin_) { + CHECK(index_ < cap_); + } else { + CHECK(index_ <= end_); + } #if DCHECK_IS_ON() + parent_deque_ = parent; created_generation_ = parent->generation_; #endif // DCHECK_IS_ON() } @@ -245,84 +266,129 @@ class circular_deque_const_iterator { // Returns the offset from the beginning index of the buffer to the current // item. size_t OffsetFromBegin() const { - if (index_ >= parent_deque_->begin_) - return index_ - parent_deque_->begin_; // On the same side as begin. - return parent_deque_->buffer_.capacity() - parent_deque_->begin_ + index_; + if (index_ >= begin_) { + return index_ - begin_; // On the same side as begin. + } + return cap_ - begin_ + index_; + } + + // The size of the deque, ie. the number of elements in it. + size_t Size() const { + if (begin_ <= end_) { + return end_ - begin_; + } + return cap_ - begin_ + end_; } // Most uses will be ++ and -- so use a simplified implementation. void Increment() { CheckUnstableUsage(); - parent_deque_->CheckValidIndex(index_); + CheckValidIndex(index_); + CHECK_NE(index_, end_); index_++; - if (index_ == parent_deque_->buffer_.capacity()) - index_ = 0; + if (index_ == cap_) { + index_ = 0u; + } } void Decrement() { CheckUnstableUsage(); - parent_deque_->CheckValidIndexOrEnd(index_); - if (index_ == 0) - index_ = parent_deque_->buffer_.capacity() - 1; - else + CheckValidIndexOrEnd(index_); + CHECK_NE(index_, begin_); + if (index_ == 0u) { + index_ = cap_ - 1u; + } else { index_--; + } } void Add(difference_type delta) { CheckUnstableUsage(); #if DCHECK_IS_ON() - if (delta <= 0) - parent_deque_->CheckValidIndexOrEnd(index_); - else - parent_deque_->CheckValidIndex(index_); + if (delta <= 0) { + CheckValidIndexOrEnd(index_); + } else { + CheckValidIndex(index_); + } #endif // It should be valid to add 0 to any iterator, even if the container is // empty and the iterator points to end(). The modulo below will divide // by 0 if the buffer capacity is empty, so it's important to check for // this case explicitly. - if (delta == 0) + if (delta == 0) { return; + } - difference_type new_offset = OffsetFromBegin() + delta; - DCHECK(new_offset >= 0 && - new_offset <= static_cast(parent_deque_->size())); - index_ = (new_offset + parent_deque_->begin_) % - parent_deque_->buffer_.capacity(); + const auto offset_from_begin = + // The max allocation size is PTRDIFF_MAX, so this value can't be larger + // than fits in ptrdiff_t. + static_cast(OffsetFromBegin()); + const auto deque_size = + // The max allocation size is PTRDIFF_MAX, so this value can't be larger + // than fits in ptrdiff_t. + static_cast(Size()); + if (delta >= 0) { + // Check `offset_from_begin + delta <= deque_size` without overflowing. + CHECK_LE(delta, deque_size - offset_from_begin); + } else { + // Check `offset_from_begin + delta >= 0` without overflowing. We avoid + // negating a negative `delta` which can overflow. Instead negate the + // positive number which can not. + CHECK_GE(delta, -offset_from_begin) << offset_from_begin; + } + const auto new_offset = + // The above checks verify that `offset_from_begin + delta` is in the + // range [0, deque_size] and does not overflow, so it also fits in + // `size_t`. + static_cast(offset_from_begin + delta); + index_ = (new_offset + begin_) % cap_; } #if DCHECK_IS_ON() + void CheckValidIndexOrEnd(size_t index) const { + parent_deque_->CheckValidIndexOrEnd(index_); + } + void CheckValidIndex(size_t index) const { + parent_deque_->CheckValidIndex(index_); + } void CheckUnstableUsage() const { DCHECK(parent_deque_); // Since circular_deque doesn't guarantee stability, any attempt to // dereference this iterator after a mutation (i.e. the generation doesn't // match the original) in the container is illegal. - DCHECK(created_generation_ == parent_deque_->generation_) + DCHECK_EQ(created_generation_, parent_deque_->generation_) << "circular_deque iterator dereferenced after mutation."; } void CheckComparable(const circular_deque_const_iterator& other) const { - DCHECK(parent_deque_ == other.parent_deque_); + DCHECK_EQ(parent_deque_, other.parent_deque_); // Since circular_deque doesn't guarantee stability, two iterators that // are compared must have been generated without mutating the container. // If this fires, the container was mutated between generating the two // iterators being compared. - DCHECK(created_generation_ == other.created_generation_); + DCHECK_EQ(created_generation_, other.created_generation_); } #else inline void CheckUnstableUsage() const {} inline void CheckComparable(const circular_deque_const_iterator&) const {} + void CheckValidIndexOrEnd(size_t index) const {} + void CheckValidIndex(size_t index) const {} #endif // DCHECK_IS_ON() - // `parent_deque_` is not a raw_ptr<...> for performance reasons: Usually + // `buffer_` is not a raw_ptr<...> for performance reasons: Usually // on-stack pointer, pointing back to the collection being iterated, owned by // object that iterates over it. Additionally this is supported by the // analysis of sampling profiler data and tab_search:top100:2020. - RAW_PTR_EXCLUSION const circular_deque* parent_deque_; + RAW_PTR_EXCLUSION const T* buffer_ = nullptr; - size_t index_; + size_t cap_ = 0u; + size_t begin_ = 0u; + size_t end_ = 0u; + size_t index_ = 0u; #if DCHECK_IS_ON() + RAW_PTR_EXCLUSION const circular_deque* parent_deque_ = nullptr; // The generation of the parent deque when this iterator was created. The // container will update the generation for every modification so we can // test if the container was modified by comparing them. - uint64_t created_generation_; + uint64_t created_generation_ = 0u; #endif // DCHECK_IS_ON() }; @@ -405,7 +471,7 @@ class circular_deque { public: using value_type = T; - using size_type = std::size_t; + using size_type = size_t; using difference_type = std::ptrdiff_t; using reference = value_type&; using const_reference = const value_type&; @@ -420,29 +486,56 @@ class circular_deque { // --------------------------------------------------------------------------- // Constructor + // Constructs an empty deque. constexpr circular_deque() = default; - // Constructs with |count| copies of |value| or default constructed version. + // Constructs with `count` copies of a default-constructed T. explicit circular_deque(size_type count) { resize(count); } + + // Constructs with `count` copies of `value`. circular_deque(size_type count, const T& value) { resize(count, value); } - // Range constructor. + // Construct a deque by constructing its elements from each element in + // `[first, last)`. + // + // Prefer using the `from_range_t` constructor, which builds a deque from a + // range, instead of from problematic iterator pairs. + // + // # Safety + // The `first` and `last` iterators must be from the same container, with + // `first <= last`. template - circular_deque(InputIterator first, InputIterator last) { - assign(first, last); + requires(std::input_iterator) + UNSAFE_BUFFER_USAGE circular_deque(InputIterator first, InputIterator last) + : circular_deque() { + // SAFETY: The caller is responsible for giving iterator from the same + // container. + UNSAFE_BUFFERS(assign(first, last)); + } + + // Constructs a deque from the elements in a range (a container or span), + // typically by copy-constructing if the range also holds objects of type + // `T`. + // + // Example: + // ``` + // int values[] = {1, 3}; + // circular_deque deq(base::from_range, values); + // ``` + template + requires(std::ranges::input_range) + circular_deque(base::from_range_t, Range&& value) : circular_deque() { + assign_range(std::forward(value)); } // Copy/move. circular_deque(const circular_deque& other) : buffer_(other.size() + 1) { - assign(other.begin(), other.end()); + assign_range(other); } circular_deque(circular_deque&& other) noexcept : buffer_(std::move(other.buffer_)), - begin_(other.begin_), - end_(other.end_) { - other.begin_ = 0; - other.end_ = 0; - } + begin_(std::exchange(other.begin_, 0u)), + end_(std::exchange(other.end_, 0u)) {} circular_deque(std::initializer_list init) { assign(init); } @@ -454,60 +547,83 @@ class circular_deque { // All of these may invalidate iterators and references. circular_deque& operator=(const circular_deque& other) { - if (&other == this) + if (&other == this) { return *this; + } reserve(other.size()); - assign(other.begin(), other.end()); + assign_range(other); return *this; } circular_deque& operator=(circular_deque&& other) noexcept { - if (&other == this) + if (&other == this) { return *this; + } // We're about to overwrite the buffer, so don't free it in clear to // avoid doing it twice. ClearRetainCapacity(); buffer_ = std::move(other.buffer_); - begin_ = other.begin_; - end_ = other.end_; - - other.begin_ = 0; - other.end_ = 0; - + begin_ = std::exchange(other.begin_, 0u); + end_ = std::exchange(other.end_, 0u); IncrementGeneration(); return *this; } circular_deque& operator=(std::initializer_list ilist) { reserve(ilist.size()); - assign(std::begin(ilist), std::end(ilist)); + assign_range(ilist); return *this; } void assign(size_type count, const value_type& value) { ClearRetainCapacity(); reserve(count); - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { emplace_back(value); + } IncrementGeneration(); } - // This variant should be enabled only when InputIterator is an iterator. + // Constructs and appends new elements into the container from each element in + // `[first, last)`, typically by copy-constructing if the iterators are also + // over objects of type `T`. + // + // # Safety + // Requires that `first` and `last` are valid iterators into a container, with + // `first <= last`. template - std::enable_if_t<::base::internal::is_iterator::value, void> - assign(InputIterator first, InputIterator last) { + requires(std::input_iterator) + UNSAFE_BUFFER_USAGE void assign(InputIterator first, InputIterator last) { // Possible future enhancement, dispatch on iterator tag type. For forward // iterators we can use std::difference to preallocate the space required // and only do one copy. ClearRetainCapacity(); - for (; first != last; ++first) + while (first != last) { emplace_back(*first); + // SAFETY: Pointers are iterators, so `first` may be a pointer. We require + // the caller to provide valid pointers such that `last` is for the same + // allocation and `first <= last`, and we've checked in the loop condition + // that `first != last` so incrementing will stay a valid pointer for the + // allocation. + UNSAFE_BUFFERS(++first); + } IncrementGeneration(); } - void assign(std::initializer_list value) { - reserve(std::distance(value.begin(), value.end())); - assign(value.begin(), value.end()); + // Copies and appends new elements into the container from each element in + // the initializer list. + void assign(std::initializer_list value) { assign_range(value); } + + // Constructs and appends new elements into the container from each element in + // a range (a container or span), typically by copy-constructing if + // the range also holds objects of type `T`. + template + requires(std::ranges::input_range) + void assign_range(Range&& range) { + reserve(std::ranges::distance(range)); + // SAFETY: begin() and end() produce iterators from the same container with + // begin <= end. + UNSAFE_BUFFERS(assign(std::ranges::begin(range), std::ranges::end(range))); } // --------------------------------------------------------------------------- @@ -516,38 +632,36 @@ class circular_deque { // Since this class assumes no exceptions, at() and operator[] are equivalent. const value_type& at(size_type i) const { - DCHECK(i < size()); + CHECK_LT(i, size()); size_t right_size = buffer_.capacity() - begin_; - if (begin_ <= end_ || i < right_size) + if (begin_ <= end_ || i < right_size) { return buffer_[begin_ + i]; + } return buffer_[i - right_size]; } value_type& at(size_type i) { return const_cast(std::as_const(*this).at(i)); } - value_type& operator[](size_type i) { - return const_cast(std::as_const(*this)[i]); - } - const value_type& operator[](size_type i) const { return at(i); } + value_type& operator[](size_type i) { return at(i); } value_type& front() { - DCHECK(!empty()); + CHECK(!empty()); return buffer_[begin_]; } const value_type& front() const { - DCHECK(!empty()); + CHECK(!empty()); return buffer_[begin_]; } value_type& back() { - DCHECK(!empty()); - return *(--end()); + CHECK(!empty()); + return *(end() - 1); } const value_type& back() const { - DCHECK(!empty()); - return *(--end()); + CHECK(!empty()); + return *(end() - 1); } // --------------------------------------------------------------------------- @@ -585,8 +699,9 @@ class circular_deque { // As a result, it's only worthwhile to call reserve() when you're adding // many things at once with no intermediate operations. void reserve(size_type new_capacity) { - if (new_capacity > capacity()) + if (new_capacity > capacity()) { SetCapacityTo(new_capacity); + } } size_type capacity() const { @@ -598,8 +713,9 @@ class circular_deque { if (empty()) { // Optimize empty case to really delete everything if there was // something. - if (buffer_.capacity()) + if (buffer_.capacity()) { buffer_ = VectorBuffer(); + } } else { SetCapacityTo(size()); } @@ -619,8 +735,9 @@ class circular_deque { bool empty() const { return begin_ == end_; } size_type size() const { - if (begin_ <= end_) + if (begin_ <= end_) { return end_ - begin_; + } return buffer_.capacity() - begin_ + end_; } @@ -643,8 +760,9 @@ class circular_deque { // one-by-one will typically be small relative to calling the constructor // for every item. ExpandCapacityIfNecessary(count - size()); - while (size() < count) + while (size() < count) { emplace_back(); + } } else if (count < size()) { size_t new_end = (begin_ + count) % buffer_.capacity(); DestructRange(new_end, end_); @@ -658,8 +776,9 @@ class circular_deque { // SEE ABOVE VERSION if you change this. The code is mostly the same. if (count > size()) { ExpandCapacityIfNecessary(count - size()); - while (size() < count) + while (size() < count) { emplace_back(value); + } } else if (count < size()) { size_t new_end = (begin_ + count) % buffer_.capacity(); DestructRange(new_end, end_); @@ -690,35 +809,38 @@ class circular_deque { // Optimize insert at the beginning. if (pos == begin()) { ExpandCapacityIfNecessary(count); - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { push_front(value); + } return; } + CHECK_LT(pos.index_, buffer_.capacity()); iterator insert_cur(this, pos.index_); iterator insert_end; MakeRoomFor(count, &insert_cur, &insert_end); while (insert_cur < insert_end) { - new (&buffer_[insert_cur.index_]) T(value); + std::construct_at( + // SAFETY: insert_cur is a valid iterator into the container, which + // means its index is less than capacity_. This is checked for above + // explicitly, and MakeRoomFor maintains it. + UNSAFE_BUFFERS(buffer_.begin() + insert_cur.index_), value); ++insert_cur; } IncrementGeneration(); } - // This enable_if keeps this call from getting confused with the (pos, count, - // value) version when value is an integer. template - std::enable_if_t<::base::internal::is_iterator::value, void> - insert(const_iterator pos, InputIterator first, InputIterator last) { + requires(std::input_iterator) + void insert(const_iterator pos, InputIterator first, InputIterator last) { ValidateIterator(pos); - const difference_type inserted_items_signed = std::distance(first, last); - if (inserted_items_signed == 0) + const size_t inserted_items = + checked_cast(std::distance(first, last)); + if (inserted_items == 0u) { return; // Can divide by 0 when doing modulo below, so return early. - CHECK(inserted_items_signed > 0); - const size_type inserted_items = - static_cast(inserted_items_signed); + } // Make a hole to copy the items into. iterator insert_cur; @@ -727,20 +849,38 @@ class circular_deque { // Optimize insert at the beginning, nothing needs to be shifted and the // hole is the |inserted_items| block immediately before |begin_|. ExpandCapacityIfNecessary(inserted_items); - insert_end = begin(); - begin_ = - (begin_ + buffer_.capacity() - inserted_items) % buffer_.capacity(); + const size_t old_begin = begin_; + begin_ = (old_begin + buffer_.capacity() - inserted_items) % + buffer_.capacity(); insert_cur = begin(); + insert_end = iterator(this, old_begin); } else { + CHECK_LT(pos.index_, buffer_.capacity()); insert_cur = iterator(this, pos.index_); MakeRoomFor(inserted_items, &insert_cur, &insert_end); } // Copy the items. while (insert_cur < insert_end) { - new (&buffer_[insert_cur.index_]) T(*first); + std::construct_at( + // SAFETY: insert_cur.index_ is either `begin_` or `pos.index`. This + // class maintains the invariant that `begin_ < capacity_`. In the + // latter case, we check above that `pos.index_ < capacity_`. + UNSAFE_BUFFERS(buffer_.begin() + insert_cur.index_), *first); ++insert_cur; - ++first; + // SAFETY: The input iterator may be a pointer, in which case we will + // produce UB if `first` is incremented past `last`. We use checked_cast + // of std::distance to an unsigned value above, which ensures that `last + // >= first`. Then we need that `insert_end - insert_cur <= last - first`: + // - If inserting at the start, pos == begin() and `insert_cur` is + // positioned at `begin_ - (last - first)`, and `insert_end` is + // positioned at `begin_` so we have + // `insert_end - insert_cur == last - first`. + // - If inserting elsewhere, `MakeRoomFor(last - first, ...)` returns an + // iterator + // pair with distance of `last - first`, so we have + // `insert_end - insert_cur == last - first`. + UNSAFE_BUFFERS(++first); } IncrementGeneration(); @@ -767,10 +907,16 @@ class circular_deque { // Do this before we make the new iterators we return. IncrementGeneration(); + CHECK_LT(pos.index_, buffer_.capacity()); iterator insert_begin(this, pos.index_); iterator insert_end; MakeRoomFor(1, &insert_begin, &insert_end); - new (&buffer_[insert_begin.index_]) T(std::forward(args)...); + std::construct_at( + // SAFETY: insert_cur is a valid iterator into the container, which + // means its index is less than capacity_. This is checked for above + // explicitly, and MakeRoomFor maintains it. + UNSAFE_BUFFERS(buffer_.begin() + insert_begin.index_), + std::forward(args)...); return insert_begin; } @@ -782,51 +928,53 @@ class circular_deque { // worth having the extra code for every template instantiation of erase() // to resize capacity downward to a new buffer. iterator erase(const_iterator pos) { return erase(pos, pos + 1); } - iterator erase(const_iterator first, const_iterator last) { - ValidateIterator(first); - ValidateIterator(last); + iterator erase(const_iterator pos_begin, const_iterator pos_end) { + ValidateIterator(pos_begin); + ValidateIterator(pos_end); IncrementGeneration(); - // First, call the destructor on the deleted items. - if (first.index_ == last.index_) { + if (pos_begin.index_ == pos_end.index_) { // Nothing deleted. Need to return early to avoid falling through to // moving items on top of themselves. - return iterator(this, first.index_); - } else if (first.index_ < last.index_) { - // Contiguous range. - buffer_.DestructRange(&buffer_[first.index_], &buffer_[last.index_]); - } else { - // Deleted range wraps around. - buffer_.DestructRange(&buffer_[first.index_], - &buffer_[buffer_.capacity()]); - buffer_.DestructRange(&buffer_[0], &buffer_[last.index_]); + return iterator(this, pos_begin.index_); } - if (first.index_ == begin_) { + // First, call the destructor on the deleted items. + DestructRange(pos_begin.index_, pos_end.index_); + + if (pos_begin.index_ == begin_) { // This deletion is from the beginning. Nothing needs to be copied, only // begin_ needs to be updated. - begin_ = last.index_; - return iterator(this, last.index_); + begin_ = pos_end.index_; + return iterator(this, pos_end.index_); } // In an erase operation, the shifted items all move logically to the left, // so move them from left-to-right. - iterator move_src(this, last.index_); - iterator move_src_end = end(); - iterator move_dest(this, first.index_); - for (; move_src < move_src_end; move_src++, move_dest++) { - buffer_.MoveRange(&buffer_[move_src.index_], - &buffer_[move_src.index_ + 1], - &buffer_[move_dest.index_]); + // + // The elements are being moved to memory where the T objects were + // previously destroyed. + // + // TODO(danakj): We could skip destruction and do MoveAssignRange here, for + // the elements that are being replaced. + size_t move_src = pos_end.index_; + const size_t move_src_end = end_; + size_t move_dest = pos_begin.index_; + const size_t cap = buffer_.capacity(); + while (move_src != move_src_end) { + VectorBuffer::MoveConstructRange(buffer_.subspan(move_src, 1u), + buffer_.subspan(move_dest, 1u)); + move_src = (move_src + 1u) % cap; + move_dest = (move_dest + 1u) % cap; } - end_ = move_dest.index_; + end_ = move_dest; // Since we did not reallocate and only changed things after the erase // element(s), the input iterator's index points to the thing following the // deletion. - return iterator(this, first.index_); + return iterator(this, pos_begin.index_); } // --------------------------------------------------------------------------- @@ -841,33 +989,42 @@ class circular_deque { template reference emplace_front(Args&&... args) { ExpandCapacityIfNecessary(1); - if (begin_ == 0) + if (begin_ == 0) { begin_ = buffer_.capacity() - 1; - else + } else { begin_--; + } IncrementGeneration(); - new (&buffer_[begin_]) T(std::forward(args)...); + std::construct_at( + // SAFETY: This class maintains an invariant that `begin_` is less than + // `buffer_`'s capacity. + UNSAFE_BUFFERS(buffer_.begin() + begin_), std::forward(args)...); return front(); } template reference emplace_back(Args&&... args) { ExpandCapacityIfNecessary(1); - new (&buffer_[end_]) T(std::forward(args)...); - if (end_ == buffer_.capacity() - 1) + std::construct_at( + // SAFETY: This class maintains an invariant that `end_` is less than + // `buffer_`'s capacity. + UNSAFE_BUFFERS(buffer_.begin() + end_), std::forward(args)...); + if (end_ == buffer_.capacity() - 1) { end_ = 0; - else + } else { end_++; + } IncrementGeneration(); return back(); } void pop_front() { - DCHECK(size()); - buffer_.DestructRange(&buffer_[begin_], &buffer_[begin_ + 1]); + CHECK(!empty()); + DestructRange(begin_, begin_ + 1u); begin_++; - if (begin_ == buffer_.capacity()) + if (begin_ == buffer_.capacity()) { begin_ = 0; + } ShrinkCapacityIfNecessary(); @@ -878,12 +1035,13 @@ class circular_deque { IncrementGeneration(); } void pop_back() { - DCHECK(size()); - if (end_ == 0) + CHECK(!empty()); + if (end_ == 0) { end_ = buffer_.capacity() - 1; - else + } else { end_--; - buffer_.DestructRange(&buffer_[end_], &buffer_[end_ + 1]); + } + DestructRange(end_, end_ + 1u); ShrinkCapacityIfNecessary(); @@ -907,32 +1065,37 @@ class circular_deque { friend internal::circular_deque_iterator; friend internal::circular_deque_const_iterator; - // Moves the items in the given circular buffer to the current one. The - // source is moved from so will become invalid. The destination buffer must - // have already been allocated with enough size. - static void MoveBuffer(VectorBuffer& from_buf, - size_t from_begin, - size_t from_end, - VectorBuffer* to_buf, - size_t* to_begin, - size_t* to_end) { - size_t from_capacity = from_buf.capacity(); - + // Moves the items in the given circular buffer to the current one. The source + // is moved from so will become invalid. The destination buffer must have + // already been allocated with enough size. + // + // # Safety + // `from_begin` and `from_end` must be less-than and less-than-or-equal-to the + // capacity of `from_buf` respectively, with `from_begin <= from_end`, or + // Undefined Behaviour may result. + UNSAFE_BUFFER_USAGE static void MoveBuffer(VectorBuffer& from_buf, + size_t from_begin, + size_t from_end, + VectorBuffer& to_buf, + size_t* to_begin, + size_t* to_end) { *to_begin = 0; if (from_begin < from_end) { // Contiguous. - from_buf.MoveRange(&from_buf[from_begin], &from_buf[from_end], - to_buf->begin()); + VectorBuffer::MoveConstructRange( + from_buf.subspan(from_begin, from_end - from_begin), + to_buf.subspan(0u, from_end - from_begin)); *to_end = from_end - from_begin; } else if (from_begin > from_end) { // Discontiguous, copy the right side to the beginning of the new buffer. - from_buf.MoveRange(&from_buf[from_begin], &from_buf[from_capacity], - to_buf->begin()); - size_t right_size = from_capacity - from_begin; + span right_side = from_buf.subspan(from_begin); + VectorBuffer::MoveConstructRange(right_side, + to_buf.subspan(0u, right_side.size())); // Append the left side. - from_buf.MoveRange(&from_buf[0], &from_buf[from_end], - &(*to_buf)[right_size]); - *to_end = right_size + from_end; + span left_side = from_buf.subspan(0u, from_end); + VectorBuffer::MoveConstructRange( + left_side, to_buf.subspan(right_side.size(), left_side.size())); + *to_end = left_side.size() + right_side.size(); } else { // No items. *to_end = 0; @@ -944,14 +1107,25 @@ class circular_deque { void SetCapacityTo(size_t new_capacity) { // Use the capacity + 1 as the internal buffer size to differentiate // empty and full (see definition of buffer_ below). - VectorBuffer new_buffer(new_capacity + 1); - MoveBuffer(buffer_, begin_, end_, &new_buffer, &begin_, &end_); + VectorBuffer new_buffer(new_capacity + 1u); + // SAFETY: This class maintains an invariant that `begin_` and `end_` are + // less than `buffer_`'s capacity. + UNSAFE_BUFFERS( + MoveBuffer(buffer_, begin_, end_, new_buffer, &begin_, &end_)); buffer_ = std::move(new_buffer); } void ExpandCapacityIfNecessary(size_t additional_elts) { - size_t min_new_capacity = size() + additional_elts; - if (capacity() >= min_new_capacity) + const size_t cur_size = size(); + const size_t cur_capacity = capacity(); + + // Protect against overflow when adding `additional_elts`, and exceeding the + // max allocation size. + CHECK_LE(additional_elts, PTRDIFF_MAX - cur_size); + + size_t min_new_capacity = cur_size + additional_elts; + if (cur_capacity >= min_new_capacity) { return; // Already enough room. + } min_new_capacity = std::max(min_new_capacity, internal::kCircularBufferInitialCapacity); @@ -959,21 +1133,21 @@ class circular_deque { // std::vector always grows by at least 50%. WTF::Deque grows by at least // 25%. We expect queue workloads to generally stay at a similar size and // grow less than a vector might, so use 25%. - size_t new_capacity = - std::max(min_new_capacity, capacity() + capacity() / 4); - SetCapacityTo(new_capacity); + SetCapacityTo(std::max(min_new_capacity, cur_capacity + cur_capacity / 4u)); } void ShrinkCapacityIfNecessary() { // Don't auto-shrink below this size. - if (capacity() <= internal::kCircularBufferInitialCapacity) + if (capacity() <= internal::kCircularBufferInitialCapacity) { return; + } // Shrink when 100% of the size() is wasted. size_t sz = size(); size_t empty_spaces = capacity() - sz; - if (empty_spaces < sz) + if (empty_spaces < sz) { return; + } // Leave 1/4 the size as free capacity, not going below the initial // capacity. @@ -989,6 +1163,10 @@ class circular_deque { void ClearRetainCapacity() { // This can't resize(0) because that requires a default constructor to // compile, which not all contained classes may implement. + + // SAFETY: This class maintains an invariant that `begin_` and `end_` are + // less than `buffer_`'s capacity. `new_end` is computed modulo the capacity + // so it is in range. DestructRange(begin_, end_); begin_ = 0; end_ = 0; @@ -1002,10 +1180,10 @@ class circular_deque { if (end == begin) { return; } else if (end > begin) { - buffer_.DestructRange(&buffer_[begin], &buffer_[end]); + VectorBuffer::DestructRange(buffer_.subspan(begin, end - begin)); } else { - buffer_.DestructRange(&buffer_[begin], &buffer_[buffer_.capacity()]); - buffer_.DestructRange(&buffer_[0], &buffer_[end]); + VectorBuffer::DestructRange(buffer_.subspan(begin)); + VectorBuffer::DestructRange(buffer_.subspan(0u, end)); } } @@ -1023,24 +1201,26 @@ class circular_deque { size_t begin_offset = insert_begin->OffsetFromBegin(); ExpandCapacityIfNecessary(count); - insert_begin->index_ = (begin_ + begin_offset) % buffer_.capacity(); - *insert_end = - iterator(this, (insert_begin->index_ + count) % buffer_.capacity()); + // Update the new end and prepare the iterators for copying. The newly + // used space contains uninitialized memory. + const size_t cap = buffer_.capacity(); + size_t src = end_; + end_ = (end_ + count) % cap; + size_t dest = end_; - // Update the new end and prepare the iterators for copying. - iterator src = end(); - end_ = (end_ + count) % buffer_.capacity(); - iterator dest = end(); + *insert_begin = iterator(this, (begin_ + begin_offset) % cap); + *insert_end = iterator(this, (insert_begin->index_ + count) % cap); // Move the elements. This will always involve shifting logically to the // right, so move in a right-to-left order. while (true) { - if (src == *insert_begin) + if (src == insert_begin->index_) { break; - --src; - --dest; - buffer_.MoveRange(&buffer_[src.index_], &buffer_[src.index_ + 1], - &buffer_[dest.index_]); + } + src = (src + cap - 1u) % cap; + dest = (dest + cap - 1u) % cap; + VectorBuffer::MoveConstructRange(buffer_.subspan(src, 1u), + buffer_.subspan(dest, 1u)); } } @@ -1049,16 +1229,18 @@ class circular_deque { // buffer, not an index used by operator[] or at() which will be offsets from // begin. void CheckValidIndex(size_t i) const { - if (begin_ <= end_) + if (begin_ <= end_) { DCHECK(i >= begin_ && i < end_); - else + } else { DCHECK((i >= begin_ && i < buffer_.capacity()) || i < end_); + } } // Asserts the given index is either dereferencable or points to end(). void CheckValidIndexOrEnd(size_t i) const { - if (i != end_) + if (i != end_) { CheckValidIndex(i); + } } void ValidateIterator(const const_iterator& i) const { diff --git a/naiveproxy/src/base/containers/contains.h b/naiveproxy/src/base/containers/contains.h index e3223888e6..d263b30c7b 100644 --- a/naiveproxy/src/base/containers/contains.h +++ b/naiveproxy/src/base/containers/contains.h @@ -5,10 +5,12 @@ #ifndef BASE_CONTAINERS_CONTAINS_H_ #define BASE_CONTAINERS_CONTAINS_H_ +#include #include #include #include "base/ranges/algorithm.h" +// TODO(dcheng): Remove this after fixing any IWYU errors. #include "base/ranges/ranges.h" namespace base { @@ -41,7 +43,7 @@ constexpr bool Contains(const Container& container, const Value& value) { "Error: About to perform linear search on an associative container. " "Either use a more generic comparator (e.g. std::less<>) or, if a " "linear search is desired, provide an explicit projection parameter."); - return ranges::find(container, value) != ranges::end(container); + return ranges::find(container, value) != std::ranges::end(container); } } @@ -53,7 +55,7 @@ constexpr bool Contains(const Container& container, const Value& value, Proj proj) { return ranges::find(container, value, std::move(proj)) != - ranges::end(container); + std::ranges::end(container); } } // namespace base diff --git a/naiveproxy/src/base/containers/enum_set.h b/naiveproxy/src/base/containers/enum_set.h index 6f7026b6f5..71830f3d0b 100644 --- a/naiveproxy/src/base/containers/enum_set.h +++ b/naiveproxy/src/base/containers/enum_set.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/naiveproxy/src/base/containers/flat_tree.h b/naiveproxy/src/base/containers/flat_tree.h index 30e9881912..f8a531c57f 100644 --- a/naiveproxy/src/base/containers/flat_tree.h +++ b/naiveproxy/src/base/containers/flat_tree.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -43,7 +44,8 @@ constexpr bool is_sorted_and_unique(const Range& range, Comp comp) { // Being unique implies that there are no adjacent elements that // compare equal. So this checks that each element is strictly less // than the element after it. - return ranges::adjacent_find(range, std::not_fn(comp)) == ranges::end(range); + return ranges::adjacent_find(range, std::not_fn(comp)) == + std::ranges::end(range); } // Helper inspired by C++20's std::to_array to convert a C-style array to a @@ -539,7 +541,7 @@ template flat_tree::flat_tree( std::initializer_list ilist, const KeyCompare& comp) - : flat_tree(std::begin(ilist), std::end(ilist), comp) {} + : flat_tree(std::ranges::begin(ilist), std::ranges::end(ilist), comp) {} template template @@ -575,7 +577,10 @@ flat_tree::flat_tree( sorted_unique_t, std::initializer_list ilist, const KeyCompare& comp) - : flat_tree(sorted_unique, std::begin(ilist), std::end(ilist), comp) {} + : flat_tree(sorted_unique, + std::ranges::begin(ilist), + std::ranges::end(ilist), + comp) {} // ---------------------------------------------------------------------------- // Assignments. @@ -647,7 +652,7 @@ auto flat_tree::begin() template constexpr auto flat_tree::begin() const -> const_iterator { - return ranges::begin(body_); + return std::ranges::begin(body_); } template @@ -664,7 +669,7 @@ auto flat_tree::end() -> iterator { template constexpr auto flat_tree::end() const -> const_iterator { - return ranges::end(body_); + return std::ranges::end(body_); } template diff --git a/naiveproxy/src/base/containers/heap_array.h b/naiveproxy/src/base/containers/heap_array.h index 9869f838ab..8f532796ca 100644 --- a/naiveproxy/src/base/containers/heap_array.h +++ b/naiveproxy/src/base/containers/heap_array.h @@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #ifndef BASE_CONTAINERS_HEAP_ARRAY_H_ #define BASE_CONTAINERS_HEAP_ARRAY_H_ @@ -147,10 +142,14 @@ class TRIVIAL_ABI GSL_OWNER HeapArray { // most useful, say, when the compiler can't deduce a template // argument type. base::span as_span() ABSL_ATTRIBUTE_LIFETIME_BOUND { - return base::span(data_.get(), size_); + // SAFETY: `size_` is the number of elements in the `data_` allocation` at + // all times. + return UNSAFE_BUFFERS(base::span(data_.get(), size_)); } base::span as_span() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return base::span(data_.get(), size_); + // SAFETY: `size_` is the number of elements in the `data_` allocation` at + // all times. + return UNSAFE_BUFFERS(base::span(data_.get(), size_)); } // Convenience method to copy the contents of the entire array from a @@ -197,7 +196,21 @@ class TRIVIAL_ABI GSL_OWNER HeapArray { base::span leak() && { HeapArray dropped = std::move(*this); T* leaked = dropped.data_.release(); - return make_span(leaked, dropped.size_); + // SAFETY: The `size_` is the number of elements in the allocation in + // `data_` at all times, which is renamed as `leaked` here. + return UNSAFE_BUFFERS(span(leaked, dropped.size_)); + } + + // Allows construction of a smaller HeapArray from an existing HeapArray w/o + // reallocations or copies. Note: The original allocation is preserved, so + // CopiedFrom() should be preferred for significant size reductions. + base::HeapArray take_first(size_t reduced_size) && { + CHECK_LE(reduced_size, size_); + size_ = 0u; + if (!reduced_size) { + data_.reset(); + } + return base::HeapArray(std::move(data_), reduced_size); } // Delete the memory previously obtained from leak(). Argument is a pointer diff --git a/naiveproxy/src/base/containers/small_map.h b/naiveproxy/src/base/containers/small_map.h index 3aa67ffc63..f17d509a5d 100644 --- a/naiveproxy/src/base/containers/small_map.h +++ b/naiveproxy/src/base/containers/small_map.h @@ -2,24 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #ifndef BASE_CONTAINERS_SMALL_MAP_H_ #define BASE_CONTAINERS_SMALL_MAP_H_ #include +#include #include #include +#include #include +#include #include #include "base/check.h" #include "base/check_op.h" +#include "base/containers/adapters.h" +#include "base/containers/span.h" #include "base/memory/stack_allocated.h" +#include "base/numerics/safe_conversions.h" +#include "base/types/to_address.h" inline constexpr size_t kUsingFullMapSentinel = std::numeric_limits::max(); @@ -97,7 +99,7 @@ namespace internal { template class small_map_default_init { public: - void operator()(NormalMap* map) const { new (map) NormalMap(); } + void operator()(NormalMap* map) const { std::construct_at(map); } }; // has_key_equal::value is true iff there exists a type M::key_equal. This is @@ -157,23 +159,25 @@ class small_map { "Initial size out of range"); public: - typedef typename NormalMap::key_type key_type; - typedef typename NormalMap::mapped_type data_type; - typedef typename NormalMap::mapped_type mapped_type; - typedef typename NormalMap::value_type value_type; - typedef EqualKey key_equal; + using key_type = NormalMap::key_type; + using data_type = NormalMap::mapped_type; + using mapped_type = NormalMap::mapped_type; + using value_type = NormalMap::value_type; + using key_equal = EqualKey; - small_map() : size_(0), functor_(MapInit()) {} + constexpr small_map() : functor_(MapInit()) { InitEmpty(); } - explicit small_map(const MapInit& functor) : size_(0), functor_(functor) {} + constexpr explicit small_map(const MapInit& functor) : functor_(functor) { + InitEmpty(); + } // Allow copy-constructor and assignment, since STL allows them too. - small_map(const small_map& src) { + constexpr small_map(const small_map& src) { // size_ and functor_ are initted in InitFrom() InitFrom(src); } - void operator=(const small_map& src) { + constexpr void operator=(const small_map& src) { if (&src == this) return; // This is not optimal. If src and dest are both using the small array, we @@ -186,22 +190,35 @@ class small_map { ~small_map() { Destroy(); } + // The elements in the inline array storage. They are held in a union so that + // they can be constructed lazily as they are inserted, and can be destroyed + // when they are erased. + union ArrayElement { + ArrayElement() {} + ~ArrayElement() {} + + value_type value; + }; + class const_iterator; class iterator { STACK_ALLOCATED(); + using map_iterator = NormalMap::iterator; + using array_iterator = span::iterator; + public: - typedef typename NormalMap::iterator::iterator_category iterator_category; - typedef typename NormalMap::iterator::value_type value_type; - typedef typename NormalMap::iterator::difference_type difference_type; - typedef typename NormalMap::iterator::pointer pointer; - typedef typename NormalMap::iterator::reference reference; + using iterator_category = map_iterator::iterator_category; + using value_type = map_iterator::value_type; + using difference_type = map_iterator::difference_type; + using pointer = map_iterator::pointer; + using reference = map_iterator::reference; - inline iterator() : array_iter_(nullptr) {} + iterator() = default; - inline iterator& operator++() { - if (array_iter_ != nullptr) { + constexpr iterator& operator++() { + if (has_array_iter()) { ++array_iter_; } else { ++map_iter_; @@ -209,78 +226,66 @@ class small_map { return *this; } - inline iterator operator++(int /*unused*/) { + constexpr iterator operator++(int /*unused*/) { iterator result(*this); ++(*this); return result; } - inline iterator& operator--() { - if (array_iter_ != nullptr) { - --array_iter_; - } else { - --map_iter_; - } - return *this; + constexpr value_type* operator->() const { + return has_array_iter() ? std::addressof(array_iter_->value) + : std::addressof(*map_iter_); } - inline iterator operator--(int /*unused*/) { - iterator result(*this); - --(*this); - return result; + constexpr value_type& operator*() const { + return has_array_iter() ? array_iter_->value : *map_iter_; } - inline value_type* operator->() const { - return array_iter_ ? array_iter_ : map_iter_.operator->(); - } - - inline value_type& operator*() const { - return array_iter_ ? *array_iter_ : *map_iter_; - } - - inline bool operator==(const iterator& other) const { - if (array_iter_ != nullptr) { + constexpr bool operator==(const iterator& other) const { + if (has_array_iter()) { return array_iter_ == other.array_iter_; } else { - return other.array_iter_ == nullptr && map_iter_ == other.map_iter_; + return !other.has_array_iter() && map_iter_ == other.map_iter_; } } - inline bool operator!=(const iterator& other) const { - return !(*this == other); - } - private: friend class small_map; friend class const_iterator; - inline explicit iterator(value_type* init) : array_iter_(init) {} - inline explicit iterator(const typename NormalMap::iterator& init) - : array_iter_(nullptr), map_iter_(init) {} + constexpr explicit iterator(const array_iterator& init) + : array_iter_(init) {} + constexpr explicit iterator(const map_iterator& init) : map_iter_(init) {} - value_type* array_iter_ = nullptr; - typename NormalMap::iterator map_iter_; + constexpr bool has_array_iter() const { + return base::to_address(array_iter_) != nullptr; + } + + array_iterator array_iter_; + map_iterator map_iter_; }; class const_iterator { STACK_ALLOCATED(); - public: - typedef typename NormalMap::const_iterator::iterator_category - iterator_category; - typedef typename NormalMap::const_iterator::value_type value_type; - typedef typename NormalMap::const_iterator::difference_type difference_type; - typedef typename NormalMap::const_iterator::pointer pointer; - typedef typename NormalMap::const_iterator::reference reference; + using map_iterator = NormalMap::const_iterator; + using array_iterator = span::iterator; - inline const_iterator() : array_iter_(nullptr) {} + public: + using iterator_category = map_iterator::iterator_category; + using value_type = map_iterator::value_type; + using difference_type = map_iterator::difference_type; + using pointer = map_iterator::pointer; + using reference = map_iterator::reference; + + const_iterator() = default; // Non-explicit constructor lets us convert regular iterators to const // iterators. - inline const_iterator(const iterator& other) + constexpr const_iterator(const iterator& other) : array_iter_(other.array_iter_), map_iter_(other.map_iter_) {} - inline const_iterator& operator++() { - if (array_iter_ != nullptr) { + constexpr const_iterator& operator++() { + if (has_array_iter()) { ++array_iter_; } else { ++map_iter_; @@ -288,90 +293,81 @@ class small_map { return *this; } - inline const_iterator operator++(int /*unused*/) { + constexpr const_iterator operator++(int /*unused*/) { const_iterator result(*this); ++(*this); return result; } - inline const_iterator& operator--() { - if (array_iter_ != nullptr) { - --array_iter_; - } else { - --map_iter_; - } - return *this; + constexpr const value_type* operator->() const { + return has_array_iter() ? std::addressof(array_iter_->value) + : std::addressof(*map_iter_); } - inline const_iterator operator--(int /*unused*/) { - const_iterator result(*this); - --(*this); - return result; + constexpr const value_type& operator*() const { + return has_array_iter() ? array_iter_->value : *map_iter_; } - inline const value_type* operator->() const { - return array_iter_ ? array_iter_ : map_iter_.operator->(); - } - - inline const value_type& operator*() const { - return array_iter_ ? *array_iter_ : *map_iter_; - } - - inline bool operator==(const const_iterator& other) const { - if (array_iter_ != nullptr) { + constexpr bool operator==(const const_iterator& other) const { + if (has_array_iter()) { return array_iter_ == other.array_iter_; } - return other.array_iter_ == nullptr && map_iter_ == other.map_iter_; - } - - inline bool operator!=(const const_iterator& other) const { - return !(*this == other); + return !other.has_array_iter() && map_iter_ == other.map_iter_; } private: friend class small_map; - inline explicit const_iterator(const value_type* init) + constexpr explicit const_iterator(const array_iterator& init) : array_iter_(init) {} - inline explicit const_iterator( - const typename NormalMap::const_iterator& init) - : array_iter_(nullptr), map_iter_(init) {} + constexpr explicit const_iterator(const map_iterator& init) + : map_iter_(init) {} - const value_type* array_iter_ = nullptr; - typename NormalMap::const_iterator map_iter_; + constexpr bool has_array_iter() const { + return base::to_address(array_iter_) != nullptr; + } + + array_iterator array_iter_; + map_iterator map_iter_; }; - iterator find(const key_type& key) { + constexpr iterator find(const key_type& key) { key_equal compare; if (UsingFullMap()) { return iterator(map()->find(key)); } - for (size_t i = 0; i < size_; ++i) { - if (compare(array_[i].first, key)) { - return iterator(array_ + i); + span r = sized_array_span(); + auto it = r.begin(); + for (; it != r.end(); ++it) { + if (compare(it->value.first, key)) { + return iterator(it); } } - return iterator(array_ + size_); + return iterator(it); } - const_iterator find(const key_type& key) const { + constexpr const_iterator find(const key_type& key) const { key_equal compare; if (UsingFullMap()) { return const_iterator(map()->find(key)); } - for (size_t i = 0; i < size_; ++i) { - if (compare(array_[i].first, key)) { - return const_iterator(array_ + i); + span r = sized_array_span(); + auto it = r.begin(); + for (; it != r.end(); ++it) { + if (compare(it->value.first, key)) { + return const_iterator(it); } } - return const_iterator(array_ + size_); + return const_iterator(it); } // Invalidates iterators. - data_type& operator[](const key_type& key) { + constexpr data_type& operator[](const key_type& key) + requires(std::is_default_constructible_v) + { key_equal compare; if (UsingFullMap()) { @@ -379,10 +375,10 @@ class small_map { } // Search backwards to favor recently-added elements. - for (size_t i = size_; i > 0; --i) { - const size_t index = i - 1; - if (compare(array_[index].first, key)) { - return array_[index].second; + span r = sized_array_span(); + for (ArrayElement& e : Reversed(r)) { + if (compare(e.value.first, key)) { + return e.value.second; } } @@ -391,40 +387,41 @@ class small_map { return map_[key]; } - DCHECK(size_ < kArraySize); - new (&array_[size_]) value_type(key, data_type()); - return array_[size_++].second; + ArrayElement& e = array_[size_++]; + std::construct_at(std::addressof(e.value), key, data_type()); + return e.value.second; } // Invalidates iterators. - std::pair insert(const value_type& x) { + constexpr std::pair insert(const value_type& x) { key_equal compare; if (UsingFullMap()) { - std::pair ret = map_.insert(x); - return std::make_pair(iterator(ret.first), ret.second); + auto [map_iter, inserted] = map_.insert(x); + return std::make_pair(iterator(map_iter), inserted); } - for (size_t i = 0; i < size_; ++i) { - if (compare(array_[i].first, x.first)) { - return std::make_pair(iterator(array_ + i), false); + span r = sized_array_span(); + for (auto it = r.begin(); it != r.end(); ++it) { + if (compare(it->value.first, x.first)) { + return std::make_pair(iterator(it), false); } } if (size_ == kArraySize) { ConvertToRealMap(); // Invalidates all iterators! - std::pair ret = map_.insert(x); - return std::make_pair(iterator(ret.first), ret.second); + auto [map_iter, inserted] = map_.insert(x); + return std::make_pair(iterator(map_iter), inserted); } - DCHECK(size_ < kArraySize); - new (&array_[size_]) value_type(x); - return std::make_pair(iterator(array_ + size_++), true); + ArrayElement& e = array_[size_++]; + std::construct_at(std::addressof(e.value), x); + return std::make_pair(iterator(sized_array_span().end() - 1u), true); } // Invalidates iterators. template - void insert(InputIterator f, InputIterator l) { + constexpr void insert(InputIterator f, InputIterator l) { while (f != l) { insert(*f); ++f; @@ -433,110 +430,119 @@ class small_map { // Invalidates iterators. template - std::pair emplace(Args&&... args) { + constexpr std::pair emplace(Args&&... args) { key_equal compare; if (UsingFullMap()) { - std::pair ret = - map_.emplace(std::forward(args)...); - return std::make_pair(iterator(ret.first), ret.second); + auto [map_iter, inserted] = map_.emplace(std::forward(args)...); + return std::make_pair(iterator(map_iter), inserted); } value_type x(std::forward(args)...); - for (size_t i = 0; i < size_; ++i) { - if (compare(array_[i].first, x.first)) { - return std::make_pair(iterator(array_ + i), false); + span r = sized_array_span(); + for (auto it = r.begin(); it != r.end(); ++it) { + if (compare(it->value.first, x.first)) { + return std::make_pair(iterator(it), false); } } if (size_ == kArraySize) { ConvertToRealMap(); // Invalidates all iterators! - std::pair ret = - map_.emplace(std::move(x)); - return std::make_pair(iterator(ret.first), ret.second); + auto [map_iter, inserted] = map_.emplace(std::move(x)); + return std::make_pair(iterator(map_iter), inserted); } - DCHECK(size_ < kArraySize); - new (&array_[size_]) value_type(std::move(x)); - return std::make_pair(iterator(array_ + size_++), true); + ArrayElement& p = array_[size_++]; + std::construct_at(std::addressof(p.value), std::move(x)); + return std::make_pair(iterator(sized_array_span().end() - 1u), true); } - iterator begin() { - return UsingFullMap() ? iterator(map_.begin()) : iterator(array_); + constexpr iterator begin() { + return UsingFullMap() ? iterator(map_.begin()) + : iterator(sized_array_span().begin()); } - const_iterator begin() const { + constexpr const_iterator begin() const { return UsingFullMap() ? const_iterator(map_.begin()) - : const_iterator(array_); + : const_iterator(sized_array_span().begin()); } - iterator end() { - return UsingFullMap() ? iterator(map_.end()) : iterator(array_ + size_); + constexpr iterator end() { + return UsingFullMap() ? iterator(map_.end()) + : iterator(sized_array_span().end()); } - const_iterator end() const { + constexpr const_iterator end() const { return UsingFullMap() ? const_iterator(map_.end()) - : const_iterator(array_ + size_); + : const_iterator(sized_array_span().end()); } - void clear() { + constexpr void clear() { if (UsingFullMap()) { + // Make the array active in the union. map_.~NormalMap(); + std::construct_at(&array_); } else { - for (size_t i = 0; i < size_; ++i) { - array_[i].~value_type(); + for (ArrayElement& e : sized_array_span()) { + e.value.~value_type(); } } - size_ = 0; + size_ = 0u; } // Invalidates iterators. Returns iterator following the last removed element. - iterator erase(const iterator& position) { + constexpr iterator erase(const iterator& position) { if (UsingFullMap()) { return iterator(map_.erase(position.map_iter_)); } - size_t i = static_cast(position.array_iter_ - array_); - // TODO(crbug.com/40565371): When we have a checked iterator, this CHECK - // might not be necessary. - CHECK_LE(i, size_); - array_[i].~value_type(); - --size_; - if (i != size_) { - new (&array_[i]) value_type(std::move(array_[size_])); - array_[size_].~value_type(); - return iterator(array_ + i); + auto erase_pos = position.array_iter_; + auto last_pos = sized_array_span().end() - 1u; + + if (erase_pos == last_pos) { + erase_pos->value.~value_type(); + --size_; + return end(); + } else { + ptrdiff_t index = std::ranges::distance(begin().array_iter_, erase_pos); + erase_pos->value.~value_type(); + std::construct_at(std::addressof(erase_pos->value), + std::move(last_pos->value)); + last_pos->value.~value_type(); + --size_; + return iterator(sized_array_span().begin() + index); } - return end(); } - size_t erase(const key_type& key) { + constexpr size_t erase(const key_type& key) { iterator iter = find(key); if (iter == end()) { - return 0; + return 0u; } erase(iter); - return 1; + return 1u; } - size_t count(const key_type& key) const { - return (find(key) == end()) ? 0 : 1; + constexpr size_t count(const key_type& key) const { + return (find(key) == end()) ? 0u : 1u; } - size_t size() const { return UsingFullMap() ? map_.size() : size_; } + constexpr size_t size() const { return UsingFullMap() ? map_.size() : size_; } - bool empty() const { return UsingFullMap() ? map_.empty() : size_ == 0; } + constexpr bool empty() const { + return UsingFullMap() ? map_.empty() : size_ == 0u; + } // Returns true if we have fallen back to using the underlying map // representation. - bool UsingFullMap() const { return size_ == kUsingFullMapSentinel; } + constexpr bool UsingFullMap() const { return size_ == kUsingFullMapSentinel; } - inline NormalMap* map() { + constexpr NormalMap* map() { CHECK(UsingFullMap()); return &map_; } - inline const NormalMap* map() const { + constexpr const NormalMap* map() const { CHECK(UsingFullMap()); return &map_; } @@ -545,66 +551,82 @@ class small_map { // When `size_ == kUsingFullMapSentinel`, we have switched storage strategies // from `array_[kArraySize] to `NormalMap map_`. See ConvertToRealMap and // UsingFullMap. - size_t size_; + size_t size_ = 0u; MapInit functor_; // We want to call constructors and destructors manually, but we don't want // to allocate and deallocate the memory used for them separately. Since // array_ and map_ are mutually exclusive, we'll put them in a union. + using ArrayMap = std::array; union { - value_type array_[kArraySize]; + ArrayMap array_; NormalMap map_; }; - void ConvertToRealMap() { - // Storage for the elements in the temporary array. This is intentionally - // declared as a union to avoid having to default-construct |kArraySize| - // elements, only to move construct over them in the initial loop. - union Storage { - Storage() {} - ~Storage() {} - value_type array[kArraySize]; - } temp; + constexpr span sized_array_span() { + CHECK(!UsingFullMap()); + return span(array_).first(size_); + } + constexpr span sized_array_span() const { + CHECK(!UsingFullMap()); + return span(array_).first(size_); + } + + constexpr void ConvertToRealMap() { + CHECK_EQ(size_, kArraySize); + + std::array temp_array; // Move the current elements into a temporary array. - for (size_t i = 0; i < kArraySize; ++i) { - new (&temp.array[i]) value_type(std::move(array_[i])); - array_[i].~value_type(); + for (size_t i = 0u; i < kArraySize; ++i) { + ArrayElement& e = temp_array[i]; + std::construct_at(std::addressof(e.value), std::move(array_[i].value)); + array_[i].value.~value_type(); } - // Initialize the map. + // Make the map active in the union. size_ = kUsingFullMapSentinel; + array_.~ArrayMap(); functor_(&map_); // Insert elements into it. - for (size_t i = 0; i < kArraySize; ++i) { - map_.insert(std::move(temp.array[i])); - temp.array[i].~value_type(); + for (ArrayElement& e : temp_array) { + map_.insert(std::move(e.value)); + e.value.~value_type(); } } // Helpers for constructors and destructors. - void InitFrom(const small_map& src) { + constexpr void InitEmpty() { + // Make the array active in the union. + std::construct_at(&array_); + } + constexpr void InitFrom(const small_map& src) { functor_ = src.functor_; size_ = src.size_; if (src.UsingFullMap()) { + // Make the map active in the union. functor_(&map_); map_ = src.map_; } else { - for (size_t i = 0; i < size_; ++i) { - new (&array_[i]) value_type(src.array_[i]); + // Make the array active in the union. + std::construct_at(&array_); + for (size_t i = 0u; i < size_; ++i) { + ArrayElement& e = array_[i]; + std::construct_at(std::addressof(e.value), src.array_[i].value); } } } - void Destroy() { + constexpr void Destroy() { if (UsingFullMap()) { map_.~NormalMap(); } else { - for (size_t i = 0; i < size_; ++i) { - array_[i].~value_type(); + for (size_t i = 0u; i < size_; ++i) { + array_[i].value.~value_type(); } + array_.~ArrayMap(); } } }; diff --git a/naiveproxy/src/base/containers/span.h b/naiveproxy/src/base/containers/span.h index 1b30ff8ac8..6fc6e8a641 100644 --- a/naiveproxy/src/base/containers/span.h +++ b/naiveproxy/src/base/containers/span.h @@ -237,6 +237,7 @@ constexpr std::ostream& span_stream(std::ostream& l, span r); // - as_byte_span() function. // - as_writable_byte_span() function. // - copy_from() method. +// - copy_from_nonoverlapping() method. // - span_from_ref() function. // - byte_span_from_ref() function. // - span_from_cstring() function. @@ -313,6 +314,11 @@ class GSL_POINTER span { data_(base::to_address(first)) { // Guarantees that the N in the type signature is correct. CHECK(N == count); + + // `count != 0` implies non-null `data_`. Consider using + // `base::SpanOrSize` to represent a size that may or may not be + // accompanied by the actual data. + DCHECK(count == 0 || !!data_); } // Constructs a span from a contiguous iterator and a size. @@ -556,26 +562,89 @@ class GSL_POINTER span { return reverse_iterator(begin()); } - // Bounds-checked copy from a non-overlapping span. The spans must be the - // exact same size or a hard CHECK() occurs. If the two spans overlap, - // Undefined Behaviour occurs. + // Bounds-checked copy from a span. The spans must be the exact same size for + // the method to be callable. // // This is a non-std extension that is inspired by the Rust // slice::copy_from_slice() method. // - // # Checks - // The function CHECKs that the `other` span has the same size as itself and - // will terminate otherwise. + // If it's known the spans can not overlap, `copy_from_nonoverlapping()` + // provides an unsafe alternative that avoids intermediate copies. constexpr void copy_from(span other) requires(!std::is_const_v) { - CHECK_EQ(size_bytes(), other.size_bytes()); - // Verify non-overlapping in developer builds. - // - // SAFETY: span provides that data() points to at least size() many - // elements, so adding size() to the data() pointer is well-defined. - DCHECK(UNSAFE_BUFFERS(data() + size()) <= other.data() || - data() >= UNSAFE_BUFFERS(other.data() + other.size())); + if constexpr (std::is_trivially_copyable_v) { + if constexpr (N > 0) { + // Avoid having to look for overlap and pick a direction, memmove allows + // arbitrary overlap. + memmove(data(), other.data(), size_bytes()); + } + } else { + // Use intptrs as pointers from different allocations are not comparable. + const auto data_intptr = reinterpret_cast(data()); + const auto other_data_intptr = reinterpret_cast(other.data()); + if (data_intptr < other_data_intptr) { + // SAFETY: The std::copy() here does not check bounds, but the compiler + // has verified that `this` and `other` have `N` elements (and are + // pointers of the same type) through the parameter's type, so `data()` + // and `other.data()` both point to at least `N` elements. + UNSAFE_BUFFERS(std::copy(other.data(), other.data() + N, data())); + } else if (data_intptr != other_data_intptr) { + // SAFETY: The std::copy() here does not check bounds, but the compiler + // has verified that `this` and `other` have `N` elements (and are + // pointers of the same type) through the parameter's type, so `data()` + // and `other.data()` both point to at least `N` elements. + UNSAFE_BUFFERS( + std::copy_backward(other.data(), other.data() + N, data() + N)); + } + } + } + + // Bounds-checked copy from a span. The spans must be the exact same size or a + // hard CHECK() occurs. The spans are allowed to overlap. + // + // This is a non-std extension that is inspired by the Rust + // slice::copy_from_slice() method. + // + // If it's known the spans can not overlap, `copy_from_nonoverlapping()` + // provides an unsafe alternative that avoids intermediate copies. + // + // # Checks + // The function CHECKs that the `other` span has the same size as itself and + // will terminate otherwise. + // + // # Implementation note + // The parameter is taken as a template to avoid implicit conversion where + // span can also be constructed from it. If the input is a fixed-length + // span then we want to use the other overload and reject sizes that don't + // match at compile time. + template > + requires(X == dynamic_extent && std::convertible_to>) + constexpr void copy_from(const R& other) + requires(!std::is_const_v) + { + return copy_from(span(other)); + } + + // Bounds-checked copy from a non-overlapping span. The spans must be the + // exact same size for the method to be callable. + // + // This is a non-std extension that is inspired by the Rust + // slice::copy_from_slice() method. + // + // # Safety + // The `other` span must not overlap with `this` or Undefined Behaviour may + // occur. + UNSAFE_BUFFER_USAGE constexpr void copy_from_nonoverlapping( + span other) + requires(!std::is_const_v) + { + // Verify non-overlapping in developer builds. Use intptrs as pointers from + // different allocations are not comparable. + const auto data_intptr = reinterpret_cast(data()); + const auto other_data_intptr = reinterpret_cast(other.data()); + DCHECK(data_intptr + size_bytes() <= other_data_intptr || + data_intptr >= other_data_intptr + size_bytes()); // When compiling with -Oz, std::ranges::copy() does not get inlined, which // makes copy_from() very expensive compared to memcpy for small sizes (up // to around 4x slower). We observe that this is because ranges::copy() uses @@ -590,12 +659,70 @@ class GSL_POINTER span { // size_bytes(), which while computable at compile time when `other` has a // fixed size, the optimizer stumbles on with -Oz. // - // SAFETY: The copy() here does not check bounds, but we have verified that - // `this` and `other` have the same bounds above (and are pointers of the - // same type), so `data()` and `other.data()` both have at least - // `other.size()` elements. - UNSAFE_BUFFERS( - std::copy(other.data(), other.data() + other.size(), data())); + // SAFETY: The std::copy() here does not check bounds, but we have verified + // that `this` and `other` have the same bounds above (and are pointers of + // the same type), so `data()` and `other.data()` both have at least + // `N` elements. + UNSAFE_BUFFERS(std::copy(other.data(), other.data() + N, data())); + } + + // Bounds-checked copy from a non-overlapping span. The spans must be the + // exact same size or a hard CHECK() occurs. If the two spans overlap, + // Undefined Behaviour may occur. + // + // This is a non-std extension that is inspired by the Rust + // slice::copy_from_slice() method. + // + // # Checks + // The function CHECKs that the `other` span has the same size as itself and + // will terminate otherwise. + // + // # Safety + // The `other` span must not overlap with `this` or Undefined Behaviour may + // occur. + // + // # Implementation note + // The parameter is taken as a template to avoid implicit conversion where + // span can also be constructed from it. If the input is a fixed-length + // span then we want to use the other overload and reject sizes that don't + // match at compile time. + template > + requires(X == dynamic_extent && std::convertible_to>) + UNSAFE_BUFFER_USAGE constexpr void copy_from_nonoverlapping(const R& other) + requires(!std::is_const_v) + { + // SAFETY: The caller must ensure the spans do not overlap. + UNSAFE_BUFFERS(copy_from_nonoverlapping(span(other))); + } + + // Bounds-checked copy from a span into the front of this span. The `other` + // span must not be larger than this span. + // + // Prefer copy_from() when you expect the entire span to be written to. This + // method does not make that guarantee and may leave some bytes uninitialized + // in the destination span, while `copy_from()` ensures the entire span is + // written which helps prevent bugs. + // + // This is sugar for `span.first(other.size()).copy_from(other)` to avoid the + // need for writing the size twice, while also preserving compile-time size + // information. + // + // # Checks + // If `other` is dynamic-sized, then this function CHECKs if `other` is larger + // than this span. If `other` is fixed-size, then the same verification is + // done at compile time. + template > + requires((X <= N || X == dynamic_extent) && + std::convertible_to>) + constexpr void copy_prefix_from(const R& other) + requires(!std::is_const_v) + { + auto from = span(other); + if constexpr (X == dynamic_extent) { + return first(from.size()).copy_from(from); + } else { + return first().copy_from(from); + } } // Implicit conversion from std::span to base::span. @@ -743,7 +870,12 @@ class GSL_POINTER span { // We can not protect here generally against an invalid iterator/count // being passed in, since we have no context to determine if the // iterator or count are valid. - : data_(base::to_address(first)), size_(count) {} + : data_(base::to_address(first)), size_(count) { + // `count != 0` implies non-null `data_`. Consider using + // `base::SpanOrSize` to represent a size that may or may not be + // accompanied by the actual data. + DCHECK(count == 0 || !!data_); + } // Constructs a span from a contiguous iterator and a size. // @@ -999,26 +1131,74 @@ class GSL_POINTER span { return reverse_iterator(begin()); } - // Bounds-checked copy from a non-overlapping span. The spans must be the - // exact same size or a hard CHECK() occurs. If the two spans overlap, - // Undefined Behaviour occurs. + // Bounds-checked copy from a span. The spans must be the exact same size or a + // hard CHECK() occurs. The spans are allowed to overlap. // // This is a non-std extension that is inspired by the Rust // slice::copy_from_slice() method. // + // If it's known the spans can not overlap, `copy_from_nonoverlapping()` + // provides an unsafe alternative that avoids intermediate copies. + // // # Checks // The function CHECKs that the `other` span has the same size as itself and // will terminate otherwise. constexpr void copy_from(span other) requires(!std::is_const_v) { - CHECK_EQ(size_bytes(), other.size_bytes()); - // Verify non-overlapping in developer builds. - // - // SAFETY: span provides that data() points to at least size() many - // elements, so adding size() to the data() pointer is well-defined. - DCHECK(UNSAFE_BUFFERS(data() + size()) <= other.data() || - data() >= UNSAFE_BUFFERS(other.data() + other.size())); + CHECK_EQ(size(), other.size()); + + if constexpr (std::is_trivially_copyable_v) { + if (!empty()) { + // Avoid having to look for overlap and pick a direction, memmove allows + // arbitrary overlap. + memmove(data(), other.data(), size_bytes()); + } + } else { + // Use intptrs as pointers from different allocations are not comparable. + const auto data_intptr = reinterpret_cast(data()); + const auto other_data_intptr = reinterpret_cast(other.data()); + if (data_intptr < other_data_intptr) { + // SAFETY: The std::copy() here does not check bounds, but we have + // verified that `this` and `other` have the same bounds above (and are + // pointers of the same type), so `data()` and `other.data()` both have + // at least `size()` elements. + UNSAFE_BUFFERS(std::copy(other.data(), other.data() + size(), data())); + } else if (data_intptr != other_data_intptr) { + // SAFETY: The std::copy() here does not check bounds, but we have + // verified that `this` and `other` have the same bounds above (and are + // pointers of the same type), so `data()` and `other.data()` both have + // at least `size()` elements. + UNSAFE_BUFFERS(std::copy_backward(other.data(), other.data() + size(), + data() + size())); + } + } + } + + // Bounds-checked copy from a non-overlapping span. The spans must be the + // exact same size or a hard CHECK() occurs. + // + // This is a non-std extension that is inspired by the Rust + // slice::copy_from_slice() method. + // + // # Checks + // The function CHECKs that the `other` span has the same size as itself and + // will terminate otherwise. + // + // # Safety + // The `other` span must not overlap with `this` or Undefined Behaviour may + // occur. + UNSAFE_BUFFER_USAGE constexpr void copy_from_nonoverlapping( + span other) + requires(!std::is_const_v) + { + CHECK_EQ(size(), other.size()); + // Verify non-overlapping in developer builds. Use intptrs as pointers from + // different allocations are not comparable. + const auto data_intptr = reinterpret_cast(data()); + const auto other_data_intptr = reinterpret_cast(other.data()); + DCHECK(data_intptr + size_bytes() <= other_data_intptr || + data_intptr >= other_data_intptr + size_bytes()); // When compiling with -Oz, std::ranges::copy() does not get inlined, which // makes copy_from() very expensive compared to memcpy for small sizes (up // to around 4x slower). We observe that this is because ranges::copy() uses @@ -1033,12 +1213,32 @@ class GSL_POINTER span { // size_bytes(), which while computable at compile time when `other` has a // fixed size, the optimizer stumbles on with -Oz. // - // SAFETY: The copy() here does not check bounds, but we have verified that - // `this` and `other` have the same bounds above (and are pointers of the - // same type), so `data()` and `other.data()` both have at least - // `other.size()` elements. - UNSAFE_BUFFERS( - std::copy(other.data(), other.data() + other.size(), data())); + // SAFETY: The std::copy() here does not check bounds, but we have verified + // that `this` and `other` have the same bounds above (and are pointers of + // the same type), so `data()` and `other.data()` both have at least + // `size()` elements. + UNSAFE_BUFFERS(std::copy(other.data(), other.data() + size(), data())); + } + + // Bounds-checked copy from a span into the front of this span. The `other` + // span must not be larger than this span. + // + // Prefer copy_from() when you expect the entire span to be written to. This + // method does not make that guarantee and may leave some bytes uninitialized + // in the destination span, while `copy_from()` ensures the entire span is + // written which helps prevent bugs. + // + // This is sugar for `span.first(other.size()).copy_from(other)` to avoid the + // need for writing the size twice, while also preserving compile-time size + // information. + // + // # Checks + // If `other` is dynamic-sized, then this function CHECKs if `other` is larger + // than this span. + constexpr void copy_prefix_from(span other) + requires(!std::is_const_v) + { + return first(other.size()).copy_from(other); } // Compares two spans for equality by comparing the objects pointed to by the @@ -1145,8 +1345,8 @@ constexpr std::ostream& operator<<(std::ostream& l, span r) { } // [span.objectrep], views of object representation -template -constexpr auto as_bytes(span s) noexcept { +template +constexpr auto as_bytes(span s) noexcept { constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X; // SAFETY: span provides that data() points to at least size_bytes() many // bytes. So since `uint8_t` has a size of 1 byte, the size_bytes() value is @@ -1158,9 +1358,9 @@ constexpr auto as_bytes(span s) noexcept { reinterpret_cast(s.data()), s.size_bytes())); } -template +template requires(!std::is_const_v) -constexpr auto as_writable_bytes(span s) noexcept { +constexpr auto as_writable_bytes(span s) noexcept { constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X; // SAFETY: span provides that data() points to at least size_bytes() many // bytes. So since `uint8_t` has a size of 1 byte, the size_bytes() value is a @@ -1176,8 +1376,8 @@ constexpr auto as_writable_bytes(span s) noexcept { // span of const char rather than const uint8_t. This non-std function is // added since chrome still represents many things as char arrays which // rightfully should be uint8_t. -template -constexpr auto as_chars(span s) noexcept { +template +constexpr auto as_chars(span s) noexcept { constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X; // SAFETY: span provides that data() points to at least size_bytes() many // bytes. So since `char` has a size of 1 byte, the size_bytes() value is a @@ -1214,9 +1414,9 @@ constexpr std::string_view as_string_view( // it returns a span of char rather than uint8_t. This non-std function is // added since chrome still represents many things as char arrays which // rightfully should be uint8_t. -template +template requires(!std::is_const_v) -auto as_writable_chars(span s) noexcept { +auto as_writable_chars(span s) noexcept { constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X; // SAFETY: span provides that data() points to at least size_bytes() many // bytes. So since `char` has a size of 1 byte, the size_bytes() value is @@ -1378,7 +1578,7 @@ constexpr span byte_span_from_ref( return as_writable_bytes(span_from_ref(single_object)); } -// Converts a string literal (such as `"hello"`) to a span of `char` while +// Converts a string literal (such as `"hello"`) to a span of `CharT` while // omitting the terminating NUL character. These two are equivalent: // ``` // base::span s1 = base::span_from_cstring("hello"); @@ -1390,14 +1590,15 @@ constexpr span byte_span_from_ref( // // Internal NUL characters (ie. that are not at the end of the string) are // always preserved. -template -constexpr span span_from_cstring( - const char (&lit ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) - ENABLE_IF_ATTR(lit[N - 1u] == '\0', "requires string literal as input") { +template +constexpr span span_from_cstring( + const CharT (&lit ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) + ENABLE_IF_ATTR(lit[N - 1u] == CharT{0}, + "requires string literal as input") { return span(lit).template first(); } -// Converts a string literal (such as `"hello"`) to a span of `char` that +// Converts a string literal (such as `"hello"`) to a span of `CharT` that // includes the terminating NUL character. These two are equivalent: // ``` // base::span s1 = base::span_with_nul_from_cstring("hello"); @@ -1407,15 +1608,16 @@ constexpr span span_from_cstring( // ``` // // If you do not want to include the NUL terminator, then use -// `span_from_cstring()` or use a view type (`base::cstring_view` or +// `span_from_cstring()` or use a view type (e.g. `base::cstring_view` or // `std::string_view`) in place of a string literal. // // Internal NUL characters (ie. that are not at the end of the string) are // always preserved. -template -constexpr span span_with_nul_from_cstring( - const char (&lit ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) - ENABLE_IF_ATTR(lit[N - 1u] == '\0', "requires string literal as input") { +template +constexpr span span_with_nul_from_cstring( + const CharT (&lit ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) + ENABLE_IF_ATTR(lit[N - 1u] == CharT{0}, + "requires string literal as input") { return span(lit); } diff --git a/naiveproxy/src/base/containers/span_nocompile.nc b/naiveproxy/src/base/containers/span_nocompile.nc index 1878d7ba0d..5feb62d701 100644 --- a/naiveproxy/src/base/containers/span_nocompile.nc +++ b/naiveproxy/src/base/containers/span_nocompile.nc @@ -188,9 +188,17 @@ void FromVolatileArrayDisallowed() { void FixedSizeCopyTooSmall() { const int src[] = {1, 2, 3}; int dst[2]; - base::span(dst).copy_from(base::make_span(src)); // expected-error@*:* {{no viable conversion}} + base::span(dst).copy_from(base::span(src)); // expected-error@*:* {{no matching member function}} - base::span(dst).copy_from(src); // expected-error@*:* {{no viable conversion}} + base::span(dst).copy_from(src); // expected-error@*:* {{no matching member function}} + + base::span(dst).copy_prefix_from(src); // expected-error@*:* {{no matching member function}} +} + +void FixedSizeCopyFromNonSpan() { + int dst[2]; + // The copy_from() template overload is not selected. + base::span(dst).copy_from(5); // expected-error@*:* {{no matching member function for call to 'copy_from'}} } void FixedSizeSplitAtOutOfBounds() { diff --git a/naiveproxy/src/base/containers/span_or_size.h b/naiveproxy/src/base/containers/span_or_size.h new file mode 100644 index 0000000000..fdf12df394 --- /dev/null +++ b/naiveproxy/src/base/containers/span_or_size.h @@ -0,0 +1,68 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_CONTAINERS_SPAN_OR_SIZE_H_ +#define BASE_CONTAINERS_SPAN_OR_SIZE_H_ + +#include + +#include + +#include "base/containers/span.h" +#include "base/functional/overloaded.h" +#include "base/types/optional_ref.h" + +namespace base { + +// `SpanOrSize` contains either a `span` or just the size of data. This +// is useful if the data is not retained in some scenarios, but size needs to be +// available in all the scenarios. +template +class SpanOrSize { + public: + explicit constexpr SpanOrSize(base::span span) : span_or_size_(span) {} + explicit constexpr SpanOrSize(size_t size) : span_or_size_(size) {} + + ~SpanOrSize() = default; + + // `SpanOrSize` is copyable and movable (just like `span` and `size_t`). + SpanOrSize(const SpanOrSize&) = default; + SpanOrSize& operator=(const SpanOrSize&) = default; + SpanOrSize(SpanOrSize&&) = default; + SpanOrSize& operator=(SpanOrSize&&) = default; + + constexpr T* ptr_or_null_if_no_data() const { + return std::visit(base::Overloaded{ + [](const base::span& span) { return span.data(); }, + [](size_t size) -> T* { return nullptr; }, + }, + span_or_size_); + } + + constexpr size_t size() const { + return std::visit(base::Overloaded{ + [](const base::span& span) { return span.size(); }, + [](size_t size) { return size; }, + }, + span_or_size_); + } + + constexpr optional_ref> span() const { + return std::visit( + base::Overloaded{ + [](const base::span& span) { + return optional_ref>(span); + }, + [](size_t size) { return optional_ref>(); }, + }, + span_or_size_); + } + + private: + std::variant, size_t> span_or_size_; +}; + +} // namespace base + +#endif // BASE_CONTAINERS_SPAN_OR_SIZE_H_ diff --git a/naiveproxy/src/base/containers/span_reader.h b/naiveproxy/src/base/containers/span_reader.h index 58ed336098..aacb2de004 100644 --- a/naiveproxy/src/base/containers/span_reader.h +++ b/naiveproxy/src/base/containers/span_reader.h @@ -9,6 +9,7 @@ #include #include "base/containers/span.h" +#include "base/memory/stack_allocated.h" #include "base/numerics/byte_conversions.h" #include "base/numerics/safe_conversions.h" @@ -21,6 +22,8 @@ namespace base { // with span directly). template class SpanReader { + STACK_ALLOCATED(); + public: // Construct SpanReader from a span. explicit SpanReader(span buf) : buf_(buf), original_size_(buf_.size()) {} diff --git a/naiveproxy/src/base/containers/vector_buffer.h b/naiveproxy/src/base/containers/vector_buffer.h index 60d905f4f3..a0ff29cabb 100644 --- a/naiveproxy/src/base/containers/vector_buffer.h +++ b/naiveproxy/src/base/containers/vector_buffer.h @@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #ifndef BASE_CONTAINERS_VECTOR_BUFFER_H_ #define BASE_CONTAINERS_VECTOR_BUFFER_H_ @@ -19,6 +14,7 @@ #include "base/check.h" #include "base/check_op.h" #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/containers/util.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/numerics/checked_math.h" @@ -86,82 +82,92 @@ class VectorBuffer { // we have to allow this for now (`i <= capacity_`), until we fix those call // sites to use real iterators. This comment applies here and to `const T& // operator[]`, below. - CHECK_LE(i, capacity_); - return buffer_[i]; + CHECK_LT(i, capacity_); + // SAFETY: `capacity_` is the size of the array pointed to by `buffer_`, + // which `i` is less than, so the dereference is inside the allocation. + return UNSAFE_BUFFERS(buffer_[i]); } const T& operator[](size_t i) const { - CHECK_LE(i, capacity_); - return buffer_[i]; + CHECK_LT(i, capacity_); + // SAFETY: `capacity_` is the size of the array pointed to by `buffer_`, + // which `i` is less than, so the dereference is inside the allocation. + return UNSAFE_BUFFERS(buffer_[i]); } + const T* data() const { return buffer_; } + T* data() { return buffer_; } + T* begin() { return buffer_; } - T* end() { return &buffer_[capacity_]; } + T* end() { + // SAFETY: `capacity_` is the size of the array pointed to by `buffer_`. + return UNSAFE_BUFFERS(buffer_ + capacity_); + } + + span as_span() { + // SAFETY: The `buffer_` array's size is `capacity_` so this gives the + // pointer to the start and one-past-the-end of the `buffer_`. + return UNSAFE_BUFFERS(span(buffer_, buffer_ + capacity_)); + } + + span subspan(size_t index) { return as_span().subspan(index); } + + span subspan(size_t index, size_t size) { + return as_span().subspan(index, size); + } // DestructRange ------------------------------------------------------------ - void DestructRange(T* begin, T* end) { + static void DestructRange(span range) { // Trivially destructible objects need not have their destructors called. if constexpr (!std::is_trivially_destructible_v) { - CHECK_LE(begin, end); - while (begin != end) { - begin->~T(); - begin++; + for (T& t : range) { + t.~T(); } } } // MoveRange ---------------------------------------------------------------- - // - // The destructor will be called (as necessary) for all moved types. The - // ranges must not overlap. - // - // The parameters and begin and end (one past the last) of the input buffer, - // and the address of the first element to copy to. There must be sufficient - // room in the destination for all items in the range [begin, end). - - // Trivially copyable types can use memcpy. Trivially copyable implies - // that there is a trivial destructor as we don't have to call it. - - // Trivially relocatable types can also use memcpy. Trivially relocatable - // imples that memcpy is equivalent to move + destroy. template static inline constexpr bool is_trivially_copyable_or_relocatable = std::is_trivially_copyable_v || IS_TRIVIALLY_RELOCATABLE(T2); - static void MoveRange(T* from_begin, T* from_end, T* to) { - CHECK(!RangesOverlap(from_begin, from_end, to)); + // Moves or copies elements from the `from` span to the `to` span. Uses memcpy + // when possible. The memory in `to` must be uninitialized and the ranges must + // not overlap. + // + // The objects in `from` are destroyed afterward. + static void MoveConstructRange(span from, span to) { + CHECK(!RangesOverlap(from, to)); + CHECK_EQ(from.size(), to.size()); if constexpr (is_trivially_copyable_or_relocatable) { - memcpy(to, from_begin, - CheckSub(get_uintptr(from_end), get_uintptr(from_begin)) - .ValueOrDie()); + // We can't use span::copy_from() as it tries to call copy constructors, + // and fails to compile on move-only trivially-relocatable types. + memcpy(to.data(), from.data(), to.size_bytes()); + // Destructors are skipped because they are trivial or should be elided in + // trivial relocation (https://reviews.llvm.org/D114732). } else { - while (from_begin != from_end) { + for (size_t i = 0; i < from.size(); ++i) { + T* to_pointer = to.subspan(i).data(); if constexpr (std::move_constructible) { - new (to) T(std::move(*from_begin)); + new (to_pointer) T(std::move(from[i])); } else { - new (to) T(*from_begin); + new (to_pointer) T(from[i]); } - from_begin->~T(); - from_begin++; - to++; + from[i].~T(); } } } private: - static bool RangesOverlap(const T* from_begin, - const T* from_end, - const T* to) { - const auto from_begin_uintptr = get_uintptr(from_begin); - const auto from_end_uintptr = get_uintptr(from_end); - const auto to_uintptr = get_uintptr(to); - return !( - to >= from_end || - CheckAdd(to_uintptr, CheckSub(from_end_uintptr, from_begin_uintptr)) - .ValueOrDie() <= from_begin_uintptr); + static bool RangesOverlap(span a, span b) { + const auto a_start = reinterpret_cast(a.data()); + const auto a_end = reinterpret_cast(a.data()) + a.size(); + const auto b_start = reinterpret_cast(b.data()); + const auto b_end = reinterpret_cast(b.data()) + b.size(); + return a_end > b_start && a_start < b_end; } // `buffer_` is not a raw_ptr<...> for performance reasons (based on analysis diff --git a/naiveproxy/src/base/cpu.cc b/naiveproxy/src/base/cpu.cc index 29a32e5be5..c50ebb8582 100644 --- a/naiveproxy/src/base/cpu.cc +++ b/naiveproxy/src/base/cpu.cc @@ -221,7 +221,7 @@ const ProcCpuInfo& ParseProcCpu() { #endif // defined(ARCH_CPU_ARM_FAMILY) && (BUILDFLAG(IS_ANDROID) || // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) -DEFINE_PROTECTED_DATA base::ProtectedMemory g_cpu_instance; +DEFINE_PROTECTED_DATA base::ProtectedMemory g_cpu_instance; } // namespace diff --git a/naiveproxy/src/base/debug/debug.gni b/naiveproxy/src/base/debug/debug.gni index b17202ef61..1d236d210a 100644 --- a/naiveproxy/src/base/debug/debug.gni +++ b/naiveproxy/src/base/debug/debug.gni @@ -15,12 +15,7 @@ declare_args() { # # Although it should work on other platforms as well, for the above reasons, # we currently enable it only for Android when compiling for Arm64. - # - # To prepare for usage in official builds, ensure profiling data for the - # recorder is present during the optimization. - build_allocation_stack_trace_recorder = - (!is_official_build || chrome_pgo_phase == 1) && current_cpu == "arm64" && - is_android + build_allocation_stack_trace_recorder = current_cpu == "arm64" && is_android } declare_args() { diff --git a/naiveproxy/src/base/debug/debugger_posix.cc b/naiveproxy/src/base/debug/debugger_posix.cc index 489b86e5ec..f5bf9ca2ee 100644 --- a/naiveproxy/src/base/debug/debugger_posix.cc +++ b/naiveproxy/src/base/debug/debugger_posix.cc @@ -178,13 +178,15 @@ Process GetDebuggerProcess() { std::string_view status(buf, static_cast(num_read)); std::string_view tracer("TracerPid:\t"); - StringPiece::size_type pid_index = status.find(tracer); - if (pid_index == StringPiece::npos) + std::string_view::size_type pid_index = status.find(tracer); + if (pid_index == std::string_view::npos) { return Process(); + } pid_index += tracer.size(); - StringPiece::size_type pid_end_index = status.find('\n', pid_index); - if (pid_end_index == StringPiece::npos) + std::string_view::size_type pid_end_index = status.find('\n', pid_index); + if (pid_end_index == std::string_view::npos) { return Process(); + } std::string_view pid_str(buf + pid_index, pid_end_index - pid_index); int pid = 0; diff --git a/naiveproxy/src/base/debug/stack_trace_fuchsia.cc b/naiveproxy/src/base/debug/stack_trace_fuchsia.cc index c51dc0a756..649f3544df 100644 --- a/naiveproxy/src/base/debug/stack_trace_fuchsia.cc +++ b/naiveproxy/src/base/debug/stack_trace_fuchsia.cc @@ -188,7 +188,7 @@ void SymbolMap::Populate() { // The "module" stack trace annotation doesn't allow for strings which // resemble paths, so extract the filename portion from |link_map_name|. size_t directory_prefix_idx = link_map_name.find_last_of("/"); - if (directory_prefix_idx != StringPiece::npos) { + if (directory_prefix_idx != std::string_view::npos) { link_map_name = link_map_name.substr( directory_prefix_idx + 1, link_map_name.size() - directory_prefix_idx - 1); diff --git a/naiveproxy/src/base/feature_list.h b/naiveproxy/src/base/feature_list.h index da311dd0e6..125a50d28f 100644 --- a/naiveproxy/src/base/feature_list.h +++ b/naiveproxy/src/base/feature_list.h @@ -646,8 +646,8 @@ class BASE_EXPORT FeatureList { // enabled. This is mutable as it's not externally visible and needs to be // usable from const getters. mutable Lock feature_identity_tracker_lock_; - mutable std::map feature_identity_tracker_ - GUARDED_BY(feature_identity_tracker_lock_); + mutable std::map> + feature_identity_tracker_ GUARDED_BY(feature_identity_tracker_lock_); // Tracks the associated FieldTrialList for DCHECKs. This is used to catch // the scenario where multiple FieldTrialList are used with the same diff --git a/naiveproxy/src/base/features.cc b/naiveproxy/src/base/features.cc index 9c9e3cdde7..6ab819ba14 100644 --- a/naiveproxy/src/base/features.cc +++ b/naiveproxy/src/base/features.cc @@ -40,6 +40,22 @@ BASE_FEATURE(kEnforceNoExecutableFileHandles, "EnforceNoExecutableFileHandles", FEATURE_ENABLED_BY_DEFAULT); +// Use non default low memory device threshold. +// Value should be given via |LowMemoryDeviceThresholdMB|. +#if BUILDFLAG(IS_IOS) +// For M99, 45% of devices have 2GB of RAM, and 55% have more. +#define LOW_MEMORY_DEVICE_THRESHOLD_MB 1024 +#else +// Updated Desktop default threshold to match the Android 2021 definition. +#define LOW_MEMORY_DEVICE_THRESHOLD_MB 2048 +#endif +BASE_FEATURE(kLowEndMemoryExperiment, + "LowEndMemoryExperiment", + FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam kLowMemoryDeviceThresholdMB{ + &kLowEndMemoryExperiment, "LowMemoryDeviceThresholdMB", + LOW_MEMORY_DEVICE_THRESHOLD_MB}; + // TODO(crbug.com/40580068): Roll out this to 100% before replacing existing // NOTREACHED_IN_MIGRATION()s with NOTREACHED() as part of [[noreturn]] // migration. Note that a prerequisite for rolling out this experiment is that @@ -50,9 +66,6 @@ BASE_FEATURE(kNotReachedIsFatal, "NotReachedIsFatal", FEATURE_ENABLED_BY_DEFAULT); -// Optimizes parsing and loading of data: URLs. -BASE_FEATURE(kOptimizeDataUrls, "OptimizeDataUrls", FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kUseRustJsonParser, "UseRustJsonParser", FEATURE_DISABLED_BY_DEFAULT); @@ -88,6 +101,12 @@ BASE_FEATURE(kPartialLowEndModeOnMidRangeDevices, BASE_FEATURE(kCollectAndroidFrameTimelineMetrics, "CollectAndroidFrameTimelineMetrics", FEATURE_DISABLED_BY_DEFAULT); + +// If enabled, post registering PowerMonitor broadcast receiver to a background +// thread, +BASE_FEATURE(kPostPowerMonitorBroadcastReceiverInitToBackground, + "PostPowerMonitorBroadcastReceiverInitToBackground", + FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_ANDROID) void Init(EmitThreadControllerProfilerMetadata diff --git a/naiveproxy/src/base/features.h b/naiveproxy/src/base/features.h index 935881f187..e478770251 100644 --- a/naiveproxy/src/base/features.h +++ b/naiveproxy/src/base/features.h @@ -17,12 +17,14 @@ namespace base::features { // Alphabetical: BASE_EXPORT BASE_DECLARE_FEATURE(kEnforceNoExecutableFileHandles); +BASE_EXPORT BASE_DECLARE_FEATURE(kLowEndMemoryExperiment); + BASE_EXPORT BASE_DECLARE_FEATURE(kNotReachedIsFatal); -BASE_EXPORT BASE_DECLARE_FEATURE(kOptimizeDataUrls); - BASE_EXPORT BASE_DECLARE_FEATURE(kUseRustJsonParser); +BASE_EXPORT extern const base::FeatureParam kLowMemoryDeviceThresholdMB; + #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) BASE_EXPORT BASE_DECLARE_FEATURE(kPartialLowEndModeOn3GbDevices); BASE_EXPORT BASE_DECLARE_FEATURE(kPartialLowEndModeOnMidRangeDevices); @@ -30,6 +32,8 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kPartialLowEndModeOnMidRangeDevices); #if BUILDFLAG(IS_ANDROID) BASE_EXPORT BASE_DECLARE_FEATURE(kCollectAndroidFrameTimelineMetrics); +BASE_EXPORT BASE_DECLARE_FEATURE( + kPostPowerMonitorBroadcastReceiverInitToBackground); #endif // Policy for emitting profiler metadata from `ThreadController`. diff --git a/naiveproxy/src/base/files/file_path.cc b/naiveproxy/src/base/files/file_path.cc index 0910514a2d..7c8936ee80 100644 --- a/naiveproxy/src/base/files/file_path.cc +++ b/naiveproxy/src/base/files/file_path.cc @@ -13,6 +13,7 @@ #include #include +#include #include "base/check_op.h" #include "base/files/safe_base_name.h" @@ -20,7 +21,6 @@ #include "base/pickle.h" #include "base/ranges/algorithm.h" #include "base/strings/strcat.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_ostream_operators.h" @@ -445,8 +445,7 @@ FilePath FilePath::InsertBeforeExtension(StringPieceType suffix) const { base::StrCat({RemoveExtension().value(), suffix, Extension()})); } -FilePath FilePath::InsertBeforeExtensionASCII(StringPiece suffix) - const { +FilePath FilePath::InsertBeforeExtensionASCII(std::string_view suffix) const { DCHECK(IsStringASCII(suffix)); #if BUILDFLAG(IS_WIN) return InsertBeforeExtension(UTF8ToWide(suffix)); @@ -473,7 +472,7 @@ FilePath FilePath::AddExtension(StringPieceType extension) const { return FilePath(str); } -FilePath FilePath::AddExtensionASCII(StringPiece extension) const { +FilePath FilePath::AddExtensionASCII(std::string_view extension) const { DCHECK(IsStringASCII(extension)); #if BUILDFLAG(IS_WIN) return AddExtension(UTF8ToWide(extension)); @@ -573,7 +572,7 @@ FilePath FilePath::Append(const SafeBaseName& component) const { return Append(component.path().value()); } -FilePath FilePath::AppendASCII(StringPiece component) const { +FilePath FilePath::AppendASCII(std::string_view component) const { DCHECK(base::IsStringASCII(component)); #if BUILDFLAG(IS_WIN) return Append(UTF8ToWide(component)); @@ -659,18 +658,18 @@ std::u16string FilePath::AsUTF16Unsafe() const { } // static -FilePath FilePath::FromASCII(StringPiece ascii) { +FilePath FilePath::FromASCII(std::string_view ascii) { DCHECK(base::IsStringASCII(ascii)); return FilePath(ASCIIToWide(ascii)); } // static -FilePath FilePath::FromUTF8Unsafe(StringPiece utf8) { +FilePath FilePath::FromUTF8Unsafe(std::string_view utf8) { return FilePath(UTF8ToWide(utf8)); } // static -FilePath FilePath::FromUTF16Unsafe(StringPiece16 utf16) { +FilePath FilePath::FromUTF16Unsafe(std::u16string_view utf16) { return FilePath(AsWStringView(utf16)); } @@ -706,13 +705,13 @@ std::u16string FilePath::AsUTF16Unsafe() const { } // static -FilePath FilePath::FromASCII(StringPiece ascii) { +FilePath FilePath::FromASCII(std::string_view ascii) { DCHECK(base::IsStringASCII(ascii)); return FilePath(ascii); } // static -FilePath FilePath::FromUTF8Unsafe(StringPiece utf8) { +FilePath FilePath::FromUTF8Unsafe(std::string_view utf8) { #if defined(SYSTEM_NATIVE_UTF8) return FilePath(utf8); #else @@ -721,7 +720,7 @@ FilePath FilePath::FromUTF8Unsafe(StringPiece utf8) { } // static -FilePath FilePath::FromUTF16Unsafe(StringPiece16 utf16) { +FilePath FilePath::FromUTF16Unsafe(std::u16string_view utf16) { #if defined(SYSTEM_NATIVE_UTF8) return FilePath(UTF16ToUTF8(utf16)); #else diff --git a/naiveproxy/src/base/files/file_path.h b/naiveproxy/src/base/files/file_path.h index 2a7fdfd35b..34f93e0f39 100644 --- a/naiveproxy/src/base/files/file_path.h +++ b/naiveproxy/src/base/files/file_path.h @@ -109,7 +109,6 @@ #include #include "base/base_export.h" -#include "base/strings/string_piece.h" #include "base/trace_event/base_tracing_forward.h" #include "build/build_config.h" @@ -324,7 +323,8 @@ class BASE_EXPORT FilePath { // path == "C:\pics\jojo" suffix == " (1)", returns "C:\pics\jojo (1)" // path == "C:\pics.old\jojo" suffix == " (1)", returns "C:\pics.old\jojo (1)" [[nodiscard]] FilePath InsertBeforeExtension(StringPieceType suffix) const; - [[nodiscard]] FilePath InsertBeforeExtensionASCII(StringPiece suffix) const; + [[nodiscard]] FilePath InsertBeforeExtensionASCII( + std::string_view suffix) const; // Adds |extension| to |file_name|. Returns the current FilePath if // |extension| is empty. Returns "" if BaseName() == "." or "..". @@ -332,7 +332,7 @@ class BASE_EXPORT FilePath { // Like above, but takes the extension as an ASCII string. See AppendASCII for // details on how this is handled. - [[nodiscard]] FilePath AddExtensionASCII(StringPiece extension) const; + [[nodiscard]] FilePath AddExtensionASCII(std::string_view extension) const; // Replaces the extension of |file_name| with |extension|. If |file_name| // does not have an extension, then |extension| is added. If |extension| is @@ -364,7 +364,7 @@ class BASE_EXPORT FilePath { // On Linux, although it can use any 8-bit encoding for paths, we assume that // ASCII is a valid subset, regardless of the encoding, since many operating // system paths will always be ASCII. - [[nodiscard]] FilePath AppendASCII(StringPiece component) const; + [[nodiscard]] FilePath AppendASCII(std::string_view component) const; // Returns true if this FilePath contains an absolute path. On Windows, an // absolute path begins with either a drive letter specification followed by @@ -421,7 +421,7 @@ class BASE_EXPORT FilePath { std::u16string AsUTF16Unsafe() const; // Returns a FilePath object from a path name in ASCII. - static FilePath FromASCII(StringPiece ascii); + static FilePath FromASCII(std::string_view ascii); // Returns a FilePath object from a path name in UTF-8. This function // should only be used for cases where you are sure that the input @@ -431,10 +431,10 @@ class BASE_EXPORT FilePath { // internally calls SysWideToNativeMB() on POSIX systems other than Mac // and Chrome OS, to mitigate the encoding issue. See the comment at // AsUTF8Unsafe() for details. - static FilePath FromUTF8Unsafe(StringPiece utf8); + static FilePath FromUTF8Unsafe(std::string_view utf8); // Similar to FromUTF8Unsafe, but accepts UTF-16 instead. - static FilePath FromUTF16Unsafe(StringPiece16 utf16); + static FilePath FromUTF16Unsafe(std::u16string_view utf16); void WriteToPickle(Pickle* pickle) const; bool ReadFromPickle(PickleIterator* iter); diff --git a/naiveproxy/src/base/files/file_util.cc b/naiveproxy/src/base/files/file_util.cc index 9d5143bfcc..7fc1a395ae 100644 --- a/naiveproxy/src/base/files/file_util.cc +++ b/naiveproxy/src/base/files/file_util.cc @@ -9,6 +9,8 @@ #include "base/files/file_util.h" +#include + #include "base/task/sequenced_task_runner.h" #include "build/build_config.h" @@ -33,7 +35,6 @@ #include "base/notreached.h" #include "base/posix/eintr_wrapper.h" #include "base/ranges/algorithm.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -494,7 +495,7 @@ bool WriteFile(const FilePath& filename, span data) { size) == size; } -bool WriteFile(const FilePath& filename, StringPiece data) { +bool WriteFile(const FilePath& filename, std::string_view data) { int size = checked_cast(data.size()); return WriteFile(filename, data.data(), size) == size; } diff --git a/naiveproxy/src/base/files/file_util.h b/naiveproxy/src/base/files/file_util.h index e471ea344a..8fc8d1d6d1 100644 --- a/naiveproxy/src/base/files/file_util.h +++ b/naiveproxy/src/base/files/file_util.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "base/base_export.h" #include "base/containers/span.h" @@ -590,18 +591,18 @@ UNSAFE_BUFFER_USAGE BASE_EXPORT int WriteFile(const FilePath& filename, // exist, it gets created with read/write permissions for all. BASE_EXPORT bool WriteFile(const FilePath& filename, span data); -// Another WriteFile() variant that takes a StringPiece so callers don't have to -// do manual conversions from a char span to a uint8_t span. -BASE_EXPORT bool WriteFile(const FilePath& filename, StringPiece data); +// Another WriteFile() variant that takes a std::string_view so callers don't +// have to do manual conversions from a char span to a uint8_t span. +BASE_EXPORT bool WriteFile(const FilePath& filename, std::string_view data); #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) // Appends |data| to |fd|. Does not close |fd| when done. Returns true iff all // of |data| were written to |fd|. BASE_EXPORT bool WriteFileDescriptor(int fd, span data); -// WriteFileDescriptor() variant that takes a StringPiece so callers don't have -// to do manual conversions from a char span to a uint8_t span. -BASE_EXPORT bool WriteFileDescriptor(int fd, StringPiece data); +// WriteFileDescriptor() variant that takes a std::string_view so callers don't +// have to do manual conversions from a char span to a uint8_t span. +BASE_EXPORT bool WriteFileDescriptor(int fd, std::string_view data); // Allocates disk space for the file referred to by |fd| for the byte range // starting at |offset| and continuing for |size| bytes. The file size will be @@ -617,9 +618,9 @@ BASE_EXPORT bool AllocateFileRegion(File* file, int64_t offset, size_t size); BASE_EXPORT bool AppendToFile(const FilePath& filename, span data); -// AppendToFile() variant that takes a StringPiece so callers don't have to do -// manual conversions from a char span to a uint8_t span. -BASE_EXPORT bool AppendToFile(const FilePath& filename, StringPiece data); +// AppendToFile() variant that takes a std::string_view so callers don't have to +// do manual conversions from a char span to a uint8_t span. +BASE_EXPORT bool AppendToFile(const FilePath& filename, std::string_view data); // Gets the current working directory for the process. BASE_EXPORT bool GetCurrentDirectory(FilePath* path); diff --git a/naiveproxy/src/base/files/file_util_posix.cc b/naiveproxy/src/base/files/file_util_posix.cc index 6f93a711fe..39a4e7f1aa 100644 --- a/naiveproxy/src/base/files/file_util_posix.cc +++ b/naiveproxy/src/base/files/file_util_posix.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include "base/base_export.h" #include "base/base_switches.h" @@ -45,7 +46,6 @@ #include "base/posix/eintr_wrapper.h" #include "base/strings/cstring_view.h" #include "base/strings/strcat.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" @@ -387,7 +387,7 @@ bool DoDeleteFile(const FilePath& path, bool recursive) { // Appends |mode_char| to |mode| before the optional character set encoding; see // https://www.gnu.org/software/libc/manual/html_node/Opening-Streams.html for // details. -std::string AppendModeCharacter(StringPiece mode, char mode_char) { +std::string AppendModeCharacter(std::string_view mode, char mode_char) { std::string result(mode); size_t comma_pos = result.find(','); result.insert(comma_pos == std::string::npos ? result.length() : comma_pos, 1, @@ -744,7 +744,7 @@ bool ExecutableExistsInPath(Environment* env, return false; } - for (const StringPiece& cur_path : + for (std::string_view cur_path : SplitStringPiece(path, ":", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY)) { FilePath file(cur_path); int permissions; @@ -821,11 +821,11 @@ bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) { FilePath FormatTemporaryFileName(FilePath::StringPieceType identifier) { #if BUILDFLAG(IS_APPLE) - StringPiece prefix = base::apple::BaseBundleID(); + std::string_view prefix = base::apple::BaseBundleID(); #elif BUILDFLAG(GOOGLE_CHROME_BRANDING) - StringPiece prefix = "com.google.Chrome"; + std::string_view prefix = "com.google.Chrome"; #else - StringPiece prefix = "org.chromium.Chromium"; + std::string_view prefix = "org.chromium.Chromium"; #endif return FilePath(StrCat({".", prefix, ".", identifier})); } @@ -986,7 +986,17 @@ bool GetFileInfo(const FilePath& file_path, File::Info* results) { if (!file.IsValid()) { return false; } - return file.GetInfo(results); + bool success = file.GetInfo(results); + // Fstat on a virtual content-uri will get size=0 and last_modified=now. + // Fix size, and set last_modified=0 to at least make it stable. + if (success && results->size == 0) { + int64_t size = 0; + if (size >= 0) { + results->size = size; + results->last_modified = Time(); + } + } + return success; } else { #endif // BUILDFLAG(IS_ANDROID) if (File::Stat(file_path, &file_info) != 0) { @@ -1088,7 +1098,7 @@ int WriteFile(const FilePath& filename, const char* data, int size) { } int bytes_written = - WriteFileDescriptor(fd, StringPiece(data, static_cast(size))) + WriteFileDescriptor(fd, std::string_view(data, static_cast(size))) ? size : -1; if (IGNORE_EINTR(close(fd)) < 0) { @@ -1110,7 +1120,7 @@ bool WriteFileDescriptor(int fd, span data) { return true; } -bool WriteFileDescriptor(int fd, StringPiece data) { +bool WriteFileDescriptor(int fd, std::string_view data) { return WriteFileDescriptor(fd, as_bytes(make_span(data))); } @@ -1219,7 +1229,7 @@ bool AppendToFile(const FilePath& filename, span data) { return ret; } -bool AppendToFile(const FilePath& filename, StringPiece data) { +bool AppendToFile(const FilePath& filename, std::string_view data) { return AppendToFile(filename, as_bytes(make_span(data))); } diff --git a/naiveproxy/src/base/files/file_util_win.cc b/naiveproxy/src/base/files/file_util_win.cc index e63c95f42b..6ec5b46db3 100644 --- a/naiveproxy/src/base/files/file_util_win.cc +++ b/naiveproxy/src/base/files/file_util_win.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -40,7 +41,7 @@ #include "base/rand_util.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" +#include "base/strings/string_split_win.h" #include "base/strings/string_util.h" #include "base/strings/string_util_win.h" #include "base/strings/utf_string_conversions.h" @@ -851,28 +852,34 @@ bool DevicePathToDriveLetterPath(const FilePath& nt_device_path, ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); // Get the mapping of drive letters to device paths. - std::array drive_mapping_buffer = {L'\0'}; - if (!::GetLogicalDriveStrings(drive_mapping_buffer.size() - 1u, - drive_mapping_buffer.data())) { - DLOG(ERROR) << "Failed to get drive mapping."; + // Note: There are 26 letters possible, and each entry takes 4 characters of + // space (e.g. ['C', ':', '\\', '\0'] plus an additional NUL character at the + // end, meaning 128 is safely above the maximum possible size needed). + std::array drive_strings_buffer = {}; + DWORD count = ::GetLogicalDriveStrings(drive_strings_buffer.size() - 1u, + drive_strings_buffer.data()); + CHECK_LT(count, drive_strings_buffer.size()); + if (!count) { + DLOG(ERROR) << "Failed to get drive mapping"; return false; } - - // The drive mapping is a sequence of null terminated strings. - // The last string is empty. - std::wstring_view drive_mapping(drive_mapping_buffer.data(), - drive_mapping_buffer.size()); - wchar_t device_path_as_string[MAX_PATH]; - wchar_t drive[] = FILE_PATH_LITERAL(" :"); + // Truncate the buffer to the bytes actually copied by GetLogicalDriveStrings. + // Note: This gets rid of the superfluous NUL character at the end. Thus, + // `drive_strings` is now a sequence of null terminated strings. + std::wstring_view drive_strings(drive_strings_buffer.data(), count); // For each string in the drive mapping, get the junction that links // to it. If that junction is a prefix of |device_path|, then we // know that |drive| is the real path prefix. - while (drive_mapping[0u]) { - drive[0u] = drive_mapping[0u]; // Copy the drive letter. + for (std::wstring_view drive_string : base::SplitStringPiece( + drive_strings, base::MakeStringViewWithNulChars(L"\0"), + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + wchar_t drive[] = L" :"; + drive[0u] = drive_string[0u]; // Copy the drive letter. - if (QueryDosDevice(drive, device_path_as_string, - sizeof(device_path_as_string))) { + wchar_t device_path_as_string[MAX_PATH]; + if (::QueryDosDevice(drive, device_path_as_string, + std::size(device_path_as_string))) { FilePath device_path(device_path_as_string); if (device_path == nt_device_path || device_path.IsParent(nt_device_path)) { @@ -882,11 +889,6 @@ bool DevicePathToDriveLetterPath(const FilePath& nt_device_path, return true; } } - // Move to the next drive letter string, which starts one - // increment after the '\0' that terminates the current string. - size_t idx = drive_mapping.find(L'\0'); - CHECK(idx != std::wstring_view::npos); - drive_mapping = drive_mapping.substr(idx + 1u); } // No drive matched. The path does not start with a device junction @@ -1074,7 +1076,7 @@ bool AppendToFile(const FilePath& filename, span data) { return false; } -bool AppendToFile(const FilePath& filename, StringPiece data) { +bool AppendToFile(const FilePath& filename, std::string_view data) { return AppendToFile(filename, as_bytes(make_span(data))); } diff --git a/naiveproxy/src/base/files/important_file_writer.cc b/naiveproxy/src/base/files/important_file_writer.cc index 49a4500fdd..e5c357d315 100644 --- a/naiveproxy/src/base/files/important_file_writer.cc +++ b/naiveproxy/src/base/files/important_file_writer.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include "base/check.h" @@ -57,7 +58,7 @@ constexpr auto kReplacePauseInterval = Milliseconds(100); #endif void UmaHistogramTimesWithSuffix(const char* histogram_name, - StringPiece histogram_suffix, + std::string_view histogram_suffix, base::TimeDelta sample) { DCHECK(histogram_name); std::string histogram_full_name(histogram_name); @@ -109,9 +110,10 @@ void DeleteTmpFileWithRetry(File tmp_file, } // namespace // static -bool ImportantFileWriter::WriteFileAtomically(const FilePath& path, - StringPiece data, - StringPiece histogram_suffix) { +bool ImportantFileWriter::WriteFileAtomically( + const FilePath& path, + std::string_view data, + std::string_view histogram_suffix) { // Calling the impl by way of the public WriteFileAtomically, so // |from_instance| is false. return WriteFileAtomicallyImpl(path, data, histogram_suffix, @@ -147,10 +149,11 @@ void ImportantFileWriter::ProduceAndWriteStringToFileAtomically( } // static -bool ImportantFileWriter::WriteFileAtomicallyImpl(const FilePath& path, - StringPiece data, - StringPiece histogram_suffix, - bool from_instance) { +bool ImportantFileWriter::WriteFileAtomicallyImpl( + const FilePath& path, + std::string_view data, + std::string_view histogram_suffix, + bool from_instance) { const TimeTicks write_start = TimeTicks::Now(); if (!from_instance) ImportantFileWriterCleaner::AddDirectory(path.DirName()); @@ -275,7 +278,7 @@ bool ImportantFileWriter::WriteFileAtomicallyImpl(const FilePath& path, ImportantFileWriter::ImportantFileWriter( const FilePath& path, scoped_refptr task_runner, - StringPiece histogram_suffix) + std::string_view histogram_suffix) : ImportantFileWriter(path, std::move(task_runner), kDefaultCommitInterval, @@ -285,7 +288,7 @@ ImportantFileWriter::ImportantFileWriter( const FilePath& path, scoped_refptr task_runner, TimeDelta interval, - StringPiece histogram_suffix) + std::string_view histogram_suffix) : path_(path), task_runner_(std::move(task_runner)), commit_interval_(interval), diff --git a/naiveproxy/src/base/files/important_file_writer.h b/naiveproxy/src/base/files/important_file_writer.h index 1ec3aba248..8839d733b5 100644 --- a/naiveproxy/src/base/files/important_file_writer.h +++ b/naiveproxy/src/base/files/important_file_writer.h @@ -8,13 +8,13 @@ #include #include #include +#include #include "base/base_export.h" #include "base/files/file_path.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/sequence_checker.h" -#include "base/strings/string_piece.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "third_party/abseil-cpp/absl/types/variant.h" @@ -76,9 +76,10 @@ class BASE_EXPORT ImportantFileWriter { // Save |data| to |path| in an atomic manner. Blocks and writes data on the // current thread. Does not guarantee file integrity across system crash (see // the class comment above). - static bool WriteFileAtomically(const FilePath& path, - StringPiece data, - StringPiece histogram_suffix = StringPiece()); + static bool WriteFileAtomically( + const FilePath& path, + std::string_view data, + std::string_view histogram_suffix = std::string_view()); // Initialize the writer. // |path| is the name of file to write. @@ -87,13 +88,13 @@ class BASE_EXPORT ImportantFileWriter { // All non-const methods, ctor and dtor must be called on the same thread. ImportantFileWriter(const FilePath& path, scoped_refptr task_runner, - StringPiece histogram_suffix = StringPiece()); + std::string_view histogram_suffix = std::string_view()); // Same as above, but with a custom commit interval. ImportantFileWriter(const FilePath& path, scoped_refptr task_runner, TimeDelta interval, - StringPiece histogram_suffix = StringPiece()); + std::string_view histogram_suffix = std::string_view()); ImportantFileWriter(const ImportantFileWriter&) = delete; ImportantFileWriter& operator=(const ImportantFileWriter&) = delete; @@ -179,8 +180,8 @@ class BASE_EXPORT ImportantFileWriter { // WriteFileAtomically. When false, the directory containing |path| is added // to the set cleaned by the ImportantFileWriterCleaner (Windows only). static bool WriteFileAtomicallyImpl(const FilePath& path, - StringPiece data, - StringPiece histogram_suffix, + std::string_view data, + std::string_view histogram_suffix, bool from_instance); void ClearPendingWrite(); diff --git a/naiveproxy/src/base/files/scoped_file.h b/naiveproxy/src/base/files/scoped_file.h index 181d821001..815e93c855 100644 --- a/naiveproxy/src/base/files/scoped_file.h +++ b/naiveproxy/src/base/files/scoped_file.h @@ -56,11 +56,18 @@ struct ScopedFILECloser { #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) namespace subtle { +#if !defined(COMPONENT_BUILD) // Enables or disables enforcement of FD ownership as tracked by ScopedFD // objects. Enforcement is disabled by default since it proves unwieldy in some // test environments, but tracking is always done. It's best to enable this as // early as possible in a process's lifetime. +// +// This function is not available in component builds, as the close() +// interceptor used by the implementation is unreliable when compiled into +// a shared library (b/342530259). If FD ownership needs to be tested or +// enforced, it should be done on a non-component build instead. void BASE_EXPORT EnableFDOwnershipEnforcement(bool enabled); +#endif // !defined(COMPONENT_BUILD) // Resets ownership state of all FDs. The only permissible use of this API is // in a forked child process between the fork() and a subsequent exec() call. @@ -81,7 +88,7 @@ void BASE_EXPORT EnableFDOwnershipEnforcement(bool enabled); void BASE_EXPORT ResetFDOwnership(); } // namespace subtle -#endif +#endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) // ----------------------------------------------------------------------------- diff --git a/naiveproxy/src/base/files/scoped_file_linux.cc b/naiveproxy/src/base/files/scoped_file_linux.cc index 338550107f..9c00f893ae 100644 --- a/naiveproxy/src/base/files/scoped_file_linux.cc +++ b/naiveproxy/src/base/files/scoped_file_linux.cc @@ -14,7 +14,6 @@ #include "base/debug/stack_trace.h" #include "base/immediate_crash.h" #include "base/logging.h" -#include "base/strings/string_piece.h" namespace { @@ -65,9 +64,11 @@ void ScopedFDCloseTraits::Release(const ScopedFD& owner, int fd) { namespace subtle { +#if !defined(COMPONENT_BUILD) void EnableFDOwnershipEnforcement(bool enabled) { g_is_ownership_enforced = enabled; } +#endif // !defined(COMPONENT_BUILD) void ResetFDOwnership() { std::fill(g_is_fd_owned.begin(), g_is_fd_owned.end(), false); @@ -82,7 +83,7 @@ bool IsFDOwned(int fd) { } // namespace base #ifndef OPENWRT_BUILD_STATIC - +#if !defined(COMPONENT_BUILD) using LibcCloseFuncPtr = int (*)(int); // Load the libc close symbol to forward to from the close wrapper. @@ -112,5 +113,5 @@ __attribute__((visibility("default"), noinline)) int close(int fd) { } } // extern "C" - +#endif // !defined(COMPONENT_BUILD) #endif // OPENWRT_BUILD_STATIC diff --git a/naiveproxy/src/base/fuchsia/fidl_event_handler.h b/naiveproxy/src/base/fuchsia/fidl_event_handler.h index b069c0791b..54729203e2 100644 --- a/naiveproxy/src/base/fuchsia/fidl_event_handler.h +++ b/naiveproxy/src/base/fuchsia/fidl_event_handler.h @@ -14,7 +14,6 @@ #include "base/fuchsia/fuchsia_logging.h" #include "base/functional/callback.h" #include "base/location.h" -#include "base/strings/string_piece.h" namespace fidl { template diff --git a/naiveproxy/src/base/fuchsia/intl_profile_watcher.cc b/naiveproxy/src/base/fuchsia/intl_profile_watcher.cc index e70c3254bf..3a82dda673 100644 --- a/naiveproxy/src/base/fuchsia/intl_profile_watcher.cc +++ b/naiveproxy/src/base/fuchsia/intl_profile_watcher.cc @@ -11,7 +11,6 @@ #include "base/fuchsia/fuchsia_logging.h" #include "base/fuchsia/process_context.h" -#include "base/strings/string_piece.h" using ::fuchsia::intl::Profile; diff --git a/naiveproxy/src/base/fuchsia/intl_profile_watcher.h b/naiveproxy/src/base/fuchsia/intl_profile_watcher.h index 787368cb86..ce9f7fdea8 100644 --- a/naiveproxy/src/base/fuchsia/intl_profile_watcher.h +++ b/naiveproxy/src/base/fuchsia/intl_profile_watcher.h @@ -10,7 +10,6 @@ #include "base/base_export.h" #include "base/functional/callback.h" -#include "base/strings/string_piece.h" namespace base { diff --git a/naiveproxy/src/base/fuchsia/mem_buffer_util.cc b/naiveproxy/src/base/fuchsia/mem_buffer_util.cc index c1afc4a5db..e0b5d7075a 100644 --- a/naiveproxy/src/base/fuchsia/mem_buffer_util.cc +++ b/naiveproxy/src/base/fuchsia/mem_buffer_util.cc @@ -24,7 +24,7 @@ std::optional ReadUTF8FromVMOAsUTF16( if (!output_utf8) return std::nullopt; std::u16string output; - return UTF8ToUTF16(&output_utf8->front(), output_utf8->size(), &output) + return UTF8ToUTF16(output_utf8->data(), output_utf8->size(), &output) ? std::optional(std::move(output)) : std::nullopt; } diff --git a/naiveproxy/src/base/fuchsia/scheduler.h b/naiveproxy/src/base/fuchsia/scheduler.h index 203c31b638..0f409d0b9e 100644 --- a/naiveproxy/src/base/fuchsia/scheduler.h +++ b/naiveproxy/src/base/fuchsia/scheduler.h @@ -5,7 +5,6 @@ #ifndef BASE_FUCHSIA_SCHEDULER_H_ #define BASE_FUCHSIA_SCHEDULER_H_ -#include "base/strings/string_piece.h" #include "base/time/time.h" namespace base { diff --git a/naiveproxy/src/base/functional/bind_internal.h b/naiveproxy/src/base/functional/bind_internal.h index bf64a8d29a..32de38664d 100644 --- a/naiveproxy/src/base/functional/bind_internal.h +++ b/naiveproxy/src/base/functional/bind_internal.h @@ -29,7 +29,7 @@ #include "base/types/is_instantiation.h" #include "base/types/to_address.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "third_party/abseil-cpp/absl/functional/function_ref.h" diff --git a/naiveproxy/src/base/functional/callback_helpers.h b/naiveproxy/src/base/functional/callback_helpers.h index d744442758..a491f22076 100644 --- a/naiveproxy/src/base/functional/callback_helpers.h +++ b/naiveproxy/src/base/functional/callback_helpers.h @@ -166,7 +166,7 @@ OnceCallback IgnoreArgs( class BASE_EXPORT ScopedClosureRunner { public: ScopedClosureRunner(); - explicit ScopedClosureRunner(OnceClosure closure); + [[nodiscard]] explicit ScopedClosureRunner(OnceClosure closure); ScopedClosureRunner(ScopedClosureRunner&& other); // Runs the current closure if it's set, then replaces it with the closure // from |other|. This is akin to how unique_ptr frees the contained pointer in diff --git a/naiveproxy/src/base/functional/function_ref.h b/naiveproxy/src/base/functional/function_ref.h index edee844a90..1039db8c66 100644 --- a/naiveproxy/src/base/functional/function_ref.h +++ b/naiveproxy/src/base/functional/function_ref.h @@ -6,6 +6,7 @@ #define BASE_FUNCTIONAL_FUNCTION_REF_H_ #include +#include #include #include @@ -33,7 +34,7 @@ class FunctionRef; // valid to invoke. // // The usual lifetime precautions for other non-owning references types (e.g. -// `base::StringPiece`, `base::span`) also apply to `base::FunctionRef`. +// `std::string_view`, `base::span`) also apply to `base::FunctionRef`. // `base::FunctionRef` should typically be used as an argument; returning a // `base::FunctionRef` or storing a `base::FunctionRef` as a field is dangerous // and likely to result in lifetime bugs. diff --git a/naiveproxy/src/base/hash/sha1_boringssl.cc b/naiveproxy/src/base/hash/sha1_boringssl.cc index 2b7a1d0aea..957ee47e1a 100644 --- a/naiveproxy/src/base/hash/sha1_boringssl.cc +++ b/naiveproxy/src/base/hash/sha1_boringssl.cc @@ -12,7 +12,6 @@ #include "base/containers/span.h" #include "base/hash/sha1.h" -#include "third_party/boringssl/src/include/openssl/crypto.h" #include "third_party/boringssl/src/include/openssl/sha.h" namespace base { @@ -20,14 +19,12 @@ static_assert(kSHA1Length == SHA_DIGEST_LENGTH, "SHA-1 digest length mismatch."); SHA1Digest SHA1Hash(span data) { - CRYPTO_library_init(); SHA1Digest digest; SHA1(data.data(), data.size(), digest.data()); return digest; } std::string SHA1HashString(std::string_view str) { - CRYPTO_library_init(); std::string digest(kSHA1Length, '\0'); SHA1(reinterpret_cast(str.data()), str.size(), reinterpret_cast(digest.data())); diff --git a/naiveproxy/src/base/i18n/icu_string_conversions.cc b/naiveproxy/src/base/i18n/icu_string_conversions.cc index 95af6cd82c..5d13773f94 100644 --- a/naiveproxy/src/base/i18n/icu_string_conversions.cc +++ b/naiveproxy/src/base/i18n/icu_string_conversions.cc @@ -11,7 +11,7 @@ #include #include "base/check.h" -#include "base/containers/heap_array.h" +#include "base/types/fixed_array.h" #include "base/notreached.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -176,10 +176,10 @@ bool CodepageToUTF16(std::string_view encoded, size_t uchar_max_length = encoded.length() + 1; SetUpErrorHandlerForToUChars(on_error, converter, &status); - auto buffer = base::HeapArray::Uninit(uchar_max_length); - int actual_size = - ucnv_toUChars(converter, buffer.data(), buffer.size(), encoded.data(), - static_cast(encoded.length()), &status); + base::FixedArray buffer(uchar_max_length); + int actual_size = ucnv_toUChars( + converter, buffer.data(), static_cast(uchar_max_length), + encoded.data(), static_cast(encoded.length()), &status); ucnv_close(converter); if (!U_SUCCESS(status)) { utf16->clear(); // Make sure the output is empty on error. diff --git a/naiveproxy/src/base/json/json_reader.h b/naiveproxy/src/base/json/json_reader.h index 12701ffedb..b0b6f19494 100644 --- a/naiveproxy/src/base/json/json_reader.h +++ b/naiveproxy/src/base/json/json_reader.h @@ -110,14 +110,14 @@ class BASE_EXPORT JSONReader { JSONReader& operator=(const JSONReader&) = delete; // Reads and parses |json|, returning a Value. - // If |json| is not a properly formed JSON string, returns absl::nullopt. + // If |json| is not a properly formed JSON string, returns std::nullopt. static std::optional Read( std::string_view json, int options = JSON_PARSE_CHROMIUM_EXTENSIONS, size_t max_depth = internal::kAbsoluteMaxDepth); // Reads and parses |json|, returning a Value::Dict. - // If |json| is not a properly formed JSON dict string, returns absl::nullopt. + // If |json| is not a properly formed JSON dict string, returns std::nullopt. static std::optional ReadDict( std::string_view json, int options = JSON_PARSE_CHROMIUM_EXTENSIONS, diff --git a/naiveproxy/src/base/logging.cc b/naiveproxy/src/base/logging.cc index 6ab92bf1d1..ea255c2cd5 100644 --- a/naiveproxy/src/base/logging.cc +++ b/naiveproxy/src/base/logging.cc @@ -60,6 +60,7 @@ #include "base/vlog.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "third_party/abseil-cpp/absl/base/internal/raw_logging.h" #include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #if !BUILDFLAG(IS_NACL) @@ -644,6 +645,30 @@ void SetShowErrorDialogs(bool enable_dialogs) { show_error_dialogs = enable_dialogs; } +namespace { + +[[noreturn]] void AbslAbortHook(const char* file, + int line, + const char* buf_start, + const char* prefix_end, + const char* buf_end) { + // This simulates a CHECK(false) at file:line instead of here. This is used + // instead of base::ImmediateCrash() to give better error messages locally + // (printed stack for one). + LogMessageFatal(file, line, LOGGING_FATAL).stream() + << "Check failed: false. " << prefix_end; +} + +} // namespace + +void RegisterAbslAbortHook() { + // TODO(pbos): Update this to not rely on a _internal namespace once there's + // a public API in absl::. + // Note: If this fails to compile because of an absl roll, this is fair to + // remove if you file a crbug.com/new and assign it to pbos@. + ::absl::raw_log_internal::RegisterAbortHook(&AbslAbortHook); +} + ScopedLogAssertHandler::ScopedLogAssertHandler( LogAssertHandlerFunction handler) { GetLogAssertHandlerStack().push(std::move(handler)); diff --git a/naiveproxy/src/base/logging.h b/naiveproxy/src/base/logging.h index 54493741ef..fe2ce670da 100644 --- a/naiveproxy/src/base/logging.h +++ b/naiveproxy/src/base/logging.h @@ -334,6 +334,11 @@ BASE_EXPORT void SetLogPrefix(const char* prefix); // Dialogs are not shown by default. BASE_EXPORT void SetShowErrorDialogs(bool enable_dialogs); +// Registers an abort hook with absl that will crash the process similarly to a +// `CHECK` failure in case of a FATAL error in absl (e.g., any operation that +// would throw an exception). +BASE_EXPORT void RegisterAbslAbortHook(); + // Sets the Log Assert Handler that will be used to notify of check failures. // Resets Log Assert Handler on object destruction. // The default handler shows a dialog box and then terminate the process, diff --git a/naiveproxy/src/base/memory/README.md b/naiveproxy/src/base/memory/README.md index d156182795..68e826e9ee 100644 --- a/naiveproxy/src/base/memory/README.md +++ b/naiveproxy/src/base/memory/README.md @@ -6,7 +6,7 @@ This is a brief overview of what they are and how they should be used. Refer to individual header files for details. C++ is not memory safe, so use these types to help guard against potential memory bugs. There are other pointer-like object types implemented elsewhere that may be -right for a given use case, such as `absl::optional` and +right for a given use case, such as `std::optional` and `std::unique_ptr`. More on all types in video form [here](https://youtu.be/MpwbWSEDfjM?t=582s) and in a doc [here](https://docs.google.com/document/d/1VRevv8JhlP4I8fIlvf87IrW2IRjE0PbkSfIcI6-UbJo/edit?usp=sharing). diff --git a/naiveproxy/src/base/memory/nonscannable_memory.cc b/naiveproxy/src/base/memory/nonscannable_memory.cc index 5fc81e6d76..928d3a815d 100644 --- a/naiveproxy/src/base/memory/nonscannable_memory.cc +++ b/naiveproxy/src/base/memory/nonscannable_memory.cc @@ -4,46 +4,26 @@ #include "base/memory/nonscannable_memory.h" -#include "partition_alloc/partition_alloc_buildflags.h" - -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) -#include "partition_alloc/shim/nonscannable_allocator.h" -#else #include -#endif + +#include "partition_alloc/buildflags.h" namespace base { void* AllocNonScannable(size_t size) { -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - return allocator_shim::NonScannableAllocator::Instance().Alloc(size); -#else return ::malloc(size); -#endif } void FreeNonScannable(void* ptr) { -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - allocator_shim::NonScannableAllocator::Instance().Free(ptr); -#else return ::free(ptr); -#endif } void* AllocNonQuarantinable(size_t size) { -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - return allocator_shim::NonQuarantinableAllocator::Instance().Alloc(size); -#else return ::malloc(size); -#endif } void FreeNonQuarantinable(void* ptr) { -#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) - allocator_shim::NonQuarantinableAllocator::Instance().Free(ptr); -#else return ::free(ptr); -#endif } } // namespace base diff --git a/naiveproxy/src/base/memory/nonscannable_memory.h b/naiveproxy/src/base/memory/nonscannable_memory.h index b01bbfd54a..96b484eb75 100644 --- a/naiveproxy/src/base/memory/nonscannable_memory.h +++ b/naiveproxy/src/base/memory/nonscannable_memory.h @@ -9,21 +9,16 @@ #include "base/base_export.h" -// This file contains allocation/deallocation functions for memory that doesn't -// need to be scanned by PCScan. Such memory should only contain "data" objects, -// i.e. objects that don't have pointers/references to other objects. An example -// would be strings or socket/IPC/file buffers. Use with caution. +// TODO(https://crbug.com/351126352): Remove this header. +// This file contains utility functions for PCScan algorithm. +// As PCScan being removed from the repository, all functions here +// just forward requests to the default allocator. +// Do not introduce new use of these functions. + namespace base { -// Allocate/free non-scannable, but still quarantinable memory. BASE_EXPORT void* AllocNonScannable(size_t size); BASE_EXPORT void FreeNonScannable(void* ptr); - -// Allocate/free non-scannable and non-quarantinable memory. These functions -// behave as normal, *Scan-unaware allocation functions. This can be useful for -// allocations that are guaranteed to be safe by the user, i.e. allocations that -// cannot be referenced from outside and cannot contain dangling references -// themselves. BASE_EXPORT void* AllocNonQuarantinable(size_t size); BASE_EXPORT void FreeNonQuarantinable(void* ptr); diff --git a/naiveproxy/src/base/memory/protected_memory.h b/naiveproxy/src/base/memory/protected_memory.h index 710f6c8179..c48fd52731 100644 --- a/naiveproxy/src/base/memory/protected_memory.h +++ b/naiveproxy/src/base/memory/protected_memory.h @@ -33,11 +33,15 @@ // Instances of `base::ProtectedMemory` use constant initialization. To allow // protection of objects which do not provide constant initialization or would // require a global constructor, `base::ProtectedMemory` provides lazy -// initialization. With template parameter `ConstructLazily` set to `true`, the -// value is constructed lazily when initialized through -// `ProtectedMemoryInitializer`. In this case, explicit initialization through -// `ProtectedMemoryInitializer` is mandatory to prevent accessing uninitialized -// memory. If data is accessed without initialization a CHECK triggers. +// initialization through `ProtectedMemoryInitializer`. Explicit initialization +// through `ProtectedMemoryInitializer` is mandatory, even for objects that +// provide constant initialization. This is because on some platforms, the +// memory section doesn't start as readonly and needs to be initialized that way +// at runtime. The requirement for explicit initialization gives an opportunity +// to perform this initialization and ensures that in the unlikely event that +// the value is modified before the memory is initialized to read-only, it will +// be forced back to a known, safe, initial state before it ever used. If data +// is accessed without initialization a CHECK triggers. // // `base::ProtectedMemory` requires T to be trivially destructible. T having // a non-trivial constructor indicates that is holds data which can not be @@ -112,7 +116,7 @@ __declspec(selectany) char __stop_protected_memory; #define DEFINE_PROTECTED_DATA constinit __declspec(allocate("prot$mem")) #else #error "Protected Memory is currently only supported on Windows." -#endif // BUILDFLAG(IS_WIN) +#endif #else #define DECLARE_PROTECTED_DATA constinit @@ -121,43 +125,17 @@ __declspec(selectany) char __stop_protected_memory; namespace base { -template +template class AutoWritableMemory; FORWARD_DECLARE_TEST(ProtectedMemoryDeathTest, VerifyTerminationOnAccess); namespace internal { -// Helper classes which store the data and implement and initialization -// according to `ConstructLazily`. With `ConstructLazily` set to false, the -// instance of T is created upon construction time, whereas with -// `ConstructLazily` set to true, the instance of T is only constructed when -// emplace is called. -template -class ProtectedDataHolder { - public: - consteval ProtectedDataHolder() = default; - - template - consteval explicit ProtectedDataHolder(U&&... args) - : data_(std::forward(args)...) {} - - T& GetReference() { return data_; } - const T& GetReference() const { return data_; } - - T* GetPointer() { return &data_; } - const T* GetPointer() const { return &data_; } - - template - void emplace(U&&... data) { - data_ = T(std::forward(data)...); - } - - private: - T data_ = T(); -}; - +// Helper class which store the data and implement and initialization for +// constructing the underlying protected data lazily. The instance of T is only +// constructed when emplace is called. template -class ProtectedDataHolder { +class ProtectedDataHolder { public: consteval ProtectedDataHolder() = default; @@ -202,7 +180,7 @@ class ProtectedDataHolder { // parameter `ConstructLazily` enables a lazy initialization. In this case, an // initialization before first access is mandatory (see // `ProtectedMemoryInitializer`). -template +template class ProtectedMemory { public: // T must be trivially destructible. Otherwise it indicates that T holds data @@ -216,12 +194,7 @@ class ProtectedMemory { // no arguments. For lazily constructed data no arguments are accepted as T is // not initialized when `ProtectedMemory` is created but through // `ProtectedMemoryInitializer` instead. - template < - typename... U, - bool ConstructLazilyP = ConstructLazily, - std::enable_if_t = true> - consteval explicit ProtectedMemory(U&&... args) - : data_(std::forward(args)...) { + consteval explicit ProtectedMemory() : data_() { static_assert(std::is_trivially_destructible_v); } @@ -233,10 +206,10 @@ class ProtectedMemory { const T* operator->() const { return data_.GetPointer(); } private: - friend class AutoWritableMemory; + friend class AutoWritableMemory; FRIEND_TEST_ALL_PREFIXES(ProtectedMemoryDeathTest, VerifyTerminationOnAccess); - internal::ProtectedDataHolder data_; + internal::ProtectedDataHolder data_; }; #if BUILDFLAG(PROTECTED_MEMORY_ENABLED) @@ -262,7 +235,7 @@ class BASE_EXPORT AutoWritableMemoryBase { static bool IsObjectInProtectedSection(const T& object) { const T* const ptr = std::addressof(object); const T* const ptr_end = ptr + 1; - return (ptr > internal::kProtectedMemoryStart) && + return (ptr >= internal::kProtectedMemoryStart) && (ptr_end <= internal::kProtectedMemoryEnd); } @@ -337,11 +310,10 @@ class BASE_EXPORT AutoWritableMemoryBase { // support enforcing write protection can only be changed at page level. To // allow a more fine grained control a dedicated page per instance of protected // data would be required. -template +template class AutoWritableMemory : public AutoWritableMemoryBase { public: - explicit AutoWritableMemory( - ProtectedMemory& protected_memory) + explicit AutoWritableMemory(ProtectedMemory& protected_memory) #if BUILDFLAG(PROTECTED_MEMORY_ENABLED) LOCKS_EXCLUDED(WriterData::writers_lock()) #endif @@ -404,16 +376,15 @@ class AutoWritableMemory : public AutoWritableMemoryBase { } private: - const raw_ref> protected_memory_; + const raw_ref> protected_memory_; }; // Helper class for creating simple ProtectedMemory static initializers. class ProtectedMemoryInitializer { public: - template - explicit ProtectedMemoryInitializer( - ProtectedMemory& protected_memory, - U&&... args) { + template + explicit ProtectedMemoryInitializer(ProtectedMemory& protected_memory, + U&&... args) { AutoWritableMemory writer(protected_memory); writer.emplace(std::forward(args)...); } diff --git a/naiveproxy/src/base/memory/protected_memory_nocompile.nc b/naiveproxy/src/base/memory/protected_memory_nocompile.nc index 5be08ac41a..2a93c0a644 100644 --- a/naiveproxy/src/base/memory/protected_memory_nocompile.nc +++ b/naiveproxy/src/base/memory/protected_memory_nocompile.nc @@ -28,22 +28,15 @@ static_assert(!std::is_trivially_destructible_v); } // namespace void DoNotAcceptDataWhichIsNotTriviallyDestructibleData() { - base::ProtectedMemory - data_1_eager; // expected-error@base/memory/protected_memory.h:* {{static assertion failed due to requirement 'std::is_trivially_destructible_v'}} - base::ProtectedMemory - data_2_eager; // expected-error@base/memory/protected_memory.h:* {{static assertion failed due to requirement 'std::is_trivially_destructible_v'}} - - base::ProtectedMemory - data_1_lazy; // expected-error@base/memory/protected_memory.h:* {{static assertion failed due to requirement 'std::is_trivially_destructible_v'}} - base::ProtectedMemory - data_2_lazy; // expected-error@base/memory/protected_memory.h:* {{static assertion failed due to requirement 'std::is_trivially_destructible_v'}} + base::ProtectedMemory + data_1; // expected-error@base/memory/protected_memory.h:* {{static assertion failed due to requirement 'std::is_trivially_destructible_v'}} + base::ProtectedMemory + data_2; // expected-error@base/memory/protected_memory.h:* {{static assertion failed due to requirement 'std::is_trivially_destructible_v'}} } -void DoNotAcceptParametersForDataWhichIsLazilyConstructible() { - base::ProtectedMemory data( - 2); // expected-error@base/memory/protected_memory_nocompile.nc:* {{no matching constructor for initialization of 'base::ProtectedMemory'}} +void DoNotAcceptParametersForData() { + base::ProtectedMemory + data(2); // expected-error@base/memory/protected_memory_nocompile.nc:* {{no matching constructor for initialization of 'base::ProtectedMemory'}} } } // namespace base diff --git a/naiveproxy/src/base/memory/protected_memory_win.cc b/naiveproxy/src/base/memory/protected_memory_win.cc index a08976760c..7febdad807 100644 --- a/naiveproxy/src/base/memory/protected_memory_win.cc +++ b/naiveproxy/src/base/memory/protected_memory_win.cc @@ -15,6 +15,7 @@ namespace base { +#if BUILDFLAG(PROTECTED_MEMORY_ENABLED) namespace { bool SetMemory(void* start, void* end, DWORD prot) { @@ -49,5 +50,6 @@ bool AutoWritableMemoryBase::SetMemoryReadWrite(void* start, void* end) { bool AutoWritableMemoryBase::SetMemoryReadOnly(void* start, void* end) { return SetMemory(start, end, PAGE_READONLY); } +#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED) } // namespace base diff --git a/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.cc b/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.cc index 6dceff4b17..117c49cbbb 100644 --- a/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.cc +++ b/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.cc @@ -4,7 +4,7 @@ #include "base/memory/raw_ptr_asan_bound_arg_tracker.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) diff --git a/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.h b/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.h index 17c8aaf207..e698398585 100644 --- a/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.h +++ b/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.h @@ -5,7 +5,7 @@ #ifndef BASE_MEMORY_RAW_PTR_ASAN_BOUND_ARG_TRACKER_H_ #define BASE_MEMORY_RAW_PTR_ASAN_BOUND_ARG_TRACKER_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) #include diff --git a/naiveproxy/src/base/memory/raw_ptr_asan_hooks.h b/naiveproxy/src/base/memory/raw_ptr_asan_hooks.h index 052c1f7374..ce73085df4 100644 --- a/naiveproxy/src/base/memory/raw_ptr_asan_hooks.h +++ b/naiveproxy/src/base/memory/raw_ptr_asan_hooks.h @@ -5,7 +5,7 @@ #ifndef BASE_MEMORY_RAW_PTR_ASAN_HOOKS_H_ #define BASE_MEMORY_RAW_PTR_ASAN_HOOKS_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) diff --git a/naiveproxy/src/base/memory/raw_ptr_asan_service.h b/naiveproxy/src/base/memory/raw_ptr_asan_service.h index 224c877eca..1e03545830 100644 --- a/naiveproxy/src/base/memory/raw_ptr_asan_service.h +++ b/naiveproxy/src/base/memory/raw_ptr_asan_service.h @@ -5,7 +5,7 @@ #ifndef BASE_MEMORY_RAW_PTR_ASAN_SERVICE_H_ #define BASE_MEMORY_RAW_PTR_ASAN_SERVICE_H_ -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) #include diff --git a/naiveproxy/src/base/memory/raw_span.h b/naiveproxy/src/base/memory/raw_span.h index 9dd043d3e1..b0767e9113 100644 --- a/naiveproxy/src/base/memory/raw_span.h +++ b/naiveproxy/src/base/memory/raw_span.h @@ -23,8 +23,9 @@ using raw_span = span>; template -span ExtractAsDanglingSpan(raw_span& arg) { - span result = std::exchange(arg, raw_span()); +auto ExtractAsDanglingSpan(raw_span& arg) { + raw_span result = + std::exchange(arg, raw_span()); return result; } diff --git a/naiveproxy/src/base/memory/safety_checks.h b/naiveproxy/src/base/memory/safety_checks.h index 136acdd411..d4304d3dbe 100644 --- a/naiveproxy/src/base/memory/safety_checks.h +++ b/naiveproxy/src/base/memory/safety_checks.h @@ -10,7 +10,7 @@ #include "base/compiler_specific.h" #include "base/dcheck_is_on.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_constants.h" #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) diff --git a/naiveproxy/src/base/memory/weak_ptr.h b/naiveproxy/src/base/memory/weak_ptr.h index 17f9ca6258..e449bf2c8a 100644 --- a/naiveproxy/src/base/memory/weak_ptr.h +++ b/naiveproxy/src/base/memory/weak_ptr.h @@ -92,6 +92,23 @@ class ProcessNodeImpl; class WorkerNodeImpl; } // namespace performance_manager +// TODO(crbug.com/40485134): This is a hack to prevent new uses of +// SupportsWeakPtr. The remaining uses are troublesome to fix, so we declare +// these classes as friends so they have access to the constructor. +namespace gl { +class GLContext; +class GLSurface; +} // namespace gl + +namespace ui { +class MenuModel; +class TextInputClient; +} // namespace ui + +namespace views { +class WidgetDelegate; +} // namespace views + namespace base { namespace sequence_manager::internal { @@ -466,16 +483,23 @@ class WeakPtrFactory : public internal::WeakPtrFactoryBase { } }; +// TODO(crbug.com/40485134): This is a hack to prevent new uses of +// SupportsWeakPtr. The remaining uses are troublesome to fix, so we declare +// these classes as friends so they have access to the constructor. This +// class is used in the unit tests. +namespace weak_ptr_unittest { +struct Target; +} + // A class may extend from SupportsWeakPtr to let others take weak pointers to // it. This avoids the class itself implementing boilerplate to dispense weak // pointers. However, since SupportsWeakPtr's destructor won't invalidate -// weak pointers to the class until after the derived class' members have been +// weak pointers to the class until after the derived class's members have been // destroyed, its use can lead to subtle use-after-destroy issues. +// This class cannot be used in new code. See crbug.com/40485134. template class SupportsWeakPtr : public internal::SupportsWeakPtrBase { public: - SupportsWeakPtr() = default; - SupportsWeakPtr(const SupportsWeakPtr&) = delete; SupportsWeakPtr& operator=(const SupportsWeakPtr&) = delete; @@ -487,6 +511,19 @@ class SupportsWeakPtr : public internal::SupportsWeakPtrBase { ~SupportsWeakPtr() = default; private: + friend struct MultiplyDerivedProducer; + friend struct Producer; + friend struct weak_ptr_unittest::Target; + friend class gl::GLContext; + friend class gl::GLSurface; + friend class ui::MenuModel; + friend class ui::TextInputClient; + friend class views::WidgetDelegate; + + // The constructor is private so only the declared friends can construct + // instances. + SupportsWeakPtr() = default; + internal::WeakReferenceOwner weak_reference_owner_; }; diff --git a/naiveproxy/src/base/message_loop/message_pump_android.cc b/naiveproxy/src/base/message_loop/message_pump_android.cc index bdbbd841f2..b3df4a333a 100644 --- a/naiveproxy/src/base/message_loop/message_pump_android.cc +++ b/naiveproxy/src/base/message_loop/message_pump_android.cc @@ -221,7 +221,8 @@ void MessagePumpAndroid::DoNonDelayedLooperWork(bool do_idle_work) { // hint false negatives" happen, for example, during initialization, in // multi-window cases, or when a previous value is cached to throttle // polling the input channel. - if (is_type_ui_ && android::InputHintChecker::HasInput()) { + if (is_type_ui_ && next_work_info.is_immediate() && + android::InputHintChecker::HasInput()) { ScheduleWork(); return; } diff --git a/naiveproxy/src/base/message_loop/message_pump_apple.mm b/naiveproxy/src/base/message_loop/message_pump_apple.mm index e7fe3f71d8..987a3ed711 100644 --- a/naiveproxy/src/base/message_loop/message_pump_apple.mm +++ b/naiveproxy/src/base/message_loop/message_pump_apple.mm @@ -187,7 +187,8 @@ void MessagePumpCFRunLoopBase::ScheduleDelayedWork( DCHECK(!next_work_info.is_immediate()); // The tolerance needs to be set before the fire date or it may be ignored. - if (g_timer_slack.load(std::memory_order_relaxed) && + if (GetAlignWakeUpsEnabled() && + g_timer_slack.load(std::memory_order_relaxed) && !next_work_info.delayed_run_time.is_max() && delayed_work_leeway_ != next_work_info.leeway) { if (!next_work_info.leeway.is_zero()) { diff --git a/naiveproxy/src/base/message_loop/message_pump_epoll.cc b/naiveproxy/src/base/message_loop/message_pump_epoll.cc index d95a7cd68f..79d707e2b3 100644 --- a/naiveproxy/src/base/message_loop/message_pump_epoll.cc +++ b/naiveproxy/src/base/message_loop/message_pump_epoll.cc @@ -200,8 +200,20 @@ void MessagePumpEpoll::AddEpollEvent(EpollEventEntry& entry) { void MessagePumpEpoll::UpdateEpollEvent(EpollEventEntry& entry) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + const uint32_t events = entry.ComputeActiveEvents(); if (!entry.stopped) { - const uint32_t events = entry.ComputeActiveEvents(); + if (events == 0) { + // There is no active interest now. + // We don't have to call epoll_ctl() if the last event was registered as + // one-shot since the fd has already been disabled. + if (!(entry.registered_events & EPOLLONESHOT)) { + // The fd is still enabled. We need to disable it but don't remove the + // entry from `entries_` to keep the reference alive because handling + // the entry isn't finished yet. + StopEpollEvent(entry); + } + return; + } if (events == entry.registered_events && !(events & EPOLLONESHOT)) { // Persistent events don't need to be modified if no bits are changing. return; @@ -210,6 +222,10 @@ void MessagePumpEpoll::UpdateEpollEvent(EpollEventEntry& entry) { int rv = epoll_ctl(epoll_.get(), EPOLL_CTL_MOD, entry.fd, &event); DPCHECK(rv == 0); entry.registered_events = events; + } else if (events != 0) { + // An interest for the fd has been reactivated. Re-enable the fd. + entry.stopped = false; + AddEpollEvent(entry); } } @@ -219,6 +235,7 @@ void MessagePumpEpoll::StopEpollEvent(EpollEventEntry& entry) { int rv = epoll_ctl(epoll_.get(), EPOLL_CTL_DEL, entry.fd, nullptr); DPCHECK(rv == 0); entry.stopped = true; + entry.registered_events = 0; } } diff --git a/naiveproxy/src/base/message_loop/message_pump_kqueue.cc b/naiveproxy/src/base/message_loop/message_pump_kqueue.cc index 04df618161..36664eb867 100644 --- a/naiveproxy/src/base/message_loop/message_pump_kqueue.cc +++ b/naiveproxy/src/base/message_loop/message_pump_kqueue.cc @@ -294,7 +294,8 @@ bool MessagePumpKqueue::WatchMachReceivePort( TimeTicks MessagePumpKqueue::AdjustDelayedRunTime(TimeTicks earliest_time, TimeTicks run_time, TimeTicks latest_time) { - if (g_timer_slack.load(std::memory_order_relaxed)) { + if (GetAlignWakeUpsEnabled() && + g_timer_slack.load(std::memory_order_relaxed)) { return earliest_time; } return MessagePump::AdjustDelayedRunTime(earliest_time, run_time, diff --git a/naiveproxy/src/base/message_loop/message_pump_win.cc b/naiveproxy/src/base/message_loop/message_pump_win.cc index e55f8f0d40..b5cda6323f 100644 --- a/naiveproxy/src/base/message_loop/message_pump_win.cc +++ b/naiveproxy/src/base/message_loop/message_pump_win.cc @@ -25,7 +25,7 @@ #include "base/tracing_buildflags.h" #if BUILDFLAG(ENABLE_BASE_TRACING) -#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_message_pump.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_message_pump.pbzero.h" // nogncheck #endif // BUILDFLAG(ENABLE_BASE_TRACING) namespace base { diff --git a/naiveproxy/src/base/metrics/crc32.cc b/naiveproxy/src/base/metrics/crc32.cc index 5117f7ea3d..83e3cee257 100644 --- a/naiveproxy/src/base/metrics/crc32.cc +++ b/naiveproxy/src/base/metrics/crc32.cc @@ -4,10 +4,33 @@ #include "base/metrics/crc32.h" +#if !BUILDFLAG(IS_NACL) +#include "third_party/zlib/zlib.h" +#endif // !BUILDFLAG(IS_NACL) + namespace base { +#if !BUILDFLAG(IS_NACL) +uint32_t Crc32(uint32_t sum, span data) { + if (data.empty()) { + return sum; + } + + // Make sure zlib checks CPU features before further calls to crc32_z. + // zlib's crc32_z implementation says it's a convention to call + // crc32(0, NULL, 0); before making calls to crc32(), so it uses it as + // a place to cache CPU features if needed. + // There's no need to cache the results, since there's an internal zlib + // caching mechanism, so this function will just return if called multiple + // times. + (void)crc32_z(0L, Z_NULL, 0); + + return static_cast( + (~crc32_z((~sum) & 0xffffffff, data.data(), data.size())) & 0xffffffff); +} +#else // Static table of checksums for all possible 8 bit bytes. -const std::array kCrcTable = { +static constexpr std::array kCrcTable = { 0x0, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x76dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0xedb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x9b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, @@ -76,5 +99,6 @@ uint32_t Crc32(uint32_t sum, span data) { } return sum; } +#endif // !BUILDFLAG(IS_NACL) } // namespace base diff --git a/naiveproxy/src/base/metrics/crc32.h b/naiveproxy/src/base/metrics/crc32.h index 9e4e9134ef..579a2cf9ae 100644 --- a/naiveproxy/src/base/metrics/crc32.h +++ b/naiveproxy/src/base/metrics/crc32.h @@ -15,8 +15,6 @@ namespace base { -BASE_EXPORT extern const std::array kCrcTable; - // This provides a simple, fast CRC-32 calculation that can be used for checking // the integrity of data. It is not a "secure" calculation! |sum| can start // with any seed or be used to continue an operation began with previous data. diff --git a/naiveproxy/src/base/metrics/field_trial_params.h b/naiveproxy/src/base/metrics/field_trial_params.h index 47916fd093..f9e4b5be70 100644 --- a/naiveproxy/src/base/metrics/field_trial_params.h +++ b/naiveproxy/src/base/metrics/field_trial_params.h @@ -164,8 +164,7 @@ struct FeatureParam { // GetFieldTrialParamValueByFeature() for more details. BASE_EXPORT std::string Get() const; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #global-scope, #constexpr-ctor-field-initializer + // RAW_PTR_EXCLUSION: #global-scope, RAW_PTR_EXCLUSION const Feature* const feature; const char* const name; const char* const default_value; @@ -189,8 +188,7 @@ struct FeatureParam { // GetFieldTrialParamValueByFeature() for more details. BASE_EXPORT double Get() const; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #global-scope, #constexpr-ctor-field-initializer + // RAW_PTR_EXCLUSION: #global-scope RAW_PTR_EXCLUSION const Feature* const feature; const char* const name; const double default_value; @@ -214,8 +212,7 @@ struct FeatureParam { // GetFieldTrialParamValueByFeature() for more details. BASE_EXPORT int Get() const; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #global-scope, #constexpr-ctor-field-initializer + // RAW_PTR_EXCLUSION: #global-scope RAW_PTR_EXCLUSION const Feature* const feature; const char* const name; const int default_value; @@ -239,8 +236,7 @@ struct FeatureParam { // GetFieldTrialParamValueByFeature() for more details. BASE_EXPORT bool Get() const; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #global-scope, #constexpr-ctor-field-initializer + // RAW_PTR_EXCLUSION: #global-scope RAW_PTR_EXCLUSION const Feature* const feature; const char* const name; const bool default_value; @@ -265,8 +261,7 @@ struct FeatureParam { // GetFieldTrialParamValueByFeature() for more details. BASE_EXPORT base::TimeDelta Get() const; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #global-scope, #constexpr-ctor-field-initializer + // RAW_PTR_EXCLUSION: #global-scope RAW_PTR_EXCLUSION const Feature* const feature; const char* const name; const base::TimeDelta default_value; @@ -336,13 +331,11 @@ struct FeatureParam { return ""; } - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #global-scope, #constexpr-ctor-field-initializer + // RAW_PTR_EXCLUSION: #global-scope RAW_PTR_EXCLUSION const base::Feature* const feature; const char* const name; const Enum default_value; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #global-scope, #constexpr-ctor-field-initializer + // RAW_PTR_EXCLUSION: #global-scope RAW_PTR_EXCLUSION const Option* const options; const size_t option_count; }; diff --git a/naiveproxy/src/base/metrics/histogram_functions.h b/naiveproxy/src/base/metrics/histogram_functions.h index 18f460cc99..0036558c99 100644 --- a/naiveproxy/src/base/metrics/histogram_functions.h +++ b/naiveproxy/src/base/metrics/histogram_functions.h @@ -191,6 +191,14 @@ BASE_EXPORT void UmaHistogramCustomTimes(const char* name, // For short timings from 1 ms up to 10 seconds (50 buckets). BASE_EXPORT void UmaHistogramTimes(const std::string& name, TimeDelta sample); BASE_EXPORT void UmaHistogramTimes(const char* name, TimeDelta sample); +// TODO(crbug.com/353712922): rename and reintroduce this function/macro +// Warning: There is another UMA logging function with a very similar name +// which buckets data differently than this one. +// https://source.chromium.org/chromium/chromium/src/+/main:base/metrics/histogram_macros.h?q=UMA_HISTOGRAM_MEDIUM_TIMES +// If you modify your logging to use that other function, you will be making a +// meaningful semantic change to your data, and should change your histogram's +// name, as per the guidelines at +// https://chromium.googlesource.com/chromium/src/tools/+/HEAD/metrics/histograms/README.md#revising-histograms. // For medium timings up to 3 minutes (50 buckets). BASE_EXPORT void UmaHistogramMediumTimes(const std::string& name, TimeDelta sample); diff --git a/naiveproxy/src/base/metrics/histogram_macros.h b/naiveproxy/src/base/metrics/histogram_macros.h index 149c9e351c..b364da1298 100644 --- a/naiveproxy/src/base/metrics/histogram_macros.h +++ b/naiveproxy/src/base/metrics/histogram_macros.h @@ -229,6 +229,14 @@ UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, base::Milliseconds(1), \ base::Seconds(10), 50) +// TODO(crbug.com/353712922): rename and reintroduce this function/macro +// Warning: There is another UMA logging function with a very similar name +// which buckets data differently than this one. +// https://source.chromium.org/chromium/chromium/src/+/main:base/metrics/histogram_functions.h?q=UmaHistogramMediumTimes +// If you modify your logging to use that other function, you will be making a +// meaningful semantic change to your data, and should change your histogram's +// name, as per the guidelines at +// https://chromium.googlesource.com/chromium/src/tools/+/HEAD/metrics/histograms/README.md#revising-histograms. // Medium timings - up to 3 minutes. Note this starts at 10ms (no good reason, // but not worth changing). #define UMA_HISTOGRAM_MEDIUM_TIMES(name, sample) \ diff --git a/naiveproxy/src/base/metrics/histogram_macros_internal.h b/naiveproxy/src/base/metrics/histogram_macros_internal.h index 91b0ff9edd..9cdddf1a10 100644 --- a/naiveproxy/src/base/metrics/histogram_macros_internal.h +++ b/naiveproxy/src/base/metrics/histogram_macros_internal.h @@ -16,43 +16,33 @@ #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" #include "base/time/time.h" +#include "base/types/cxx23_to_underlying.h" // This is for macros and helpers internal to base/metrics. They should not be // used outside of this directory. For writing to UMA histograms, see // histogram_macros.h. -namespace base { -namespace internal { +namespace base::internal { -// Helper traits for deducing the boundary value for enums. -template +// Helper trait for deducing the boundary value for enums. +template + requires(std::is_enum_v) struct EnumSizeTraits { static constexpr Enum Count() { - static_assert( - sizeof(Enum) == 0, - "enumerator must define kMaxValue enumerator to use this macro!"); - return Enum(); + if constexpr (requires { Enum::kMaxValue; }) { + // Since the UMA histogram macros expect a value one larger than the max + // defined enumerator value, add one. + return static_cast(base::to_underlying(Enum::kMaxValue) + 1); + } else { + static_assert( + sizeof(Enum) == 0, + "enumerator must define kMaxValue enumerator to use this macro!"); + return Enum(); + } } }; -// Since the UMA histogram macros expect a value one larger than the max defined -// enumerator value, add one. -template -struct EnumSizeTraits< - Enum, - std::enable_if_t>> { - static constexpr Enum Count() { - // If you're getting - // note: integer value X is outside the valid range of values [0, X] for - // this enumeration type - // Then you need to give your enum a fixed underlying type. - return static_cast( - static_cast>(Enum::kMaxValue) + 1); - } -}; - -} // namespace internal -} // namespace base +} // namespace base::internal // TODO(rkaplow): Improve commenting of these methods. //------------------------------------------------------------------------------ diff --git a/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc b/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc index d3d1f9b335..785d24a7e0 100644 --- a/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc +++ b/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc @@ -1055,8 +1055,8 @@ bool GlobalHistogramAllocator::WriteToPersistentLocation() { } std::string_view contents(static_cast(data()), used()); - if (!ImportantFileWriter::WriteFileAtomically(persistent_location_, - contents)) { + if (!ImportantFileWriter::WriteFileAtomically( + persistent_location_, contents, "PersistentHistogramAllocator")) { LOG(ERROR) << "Could not write \"" << Name() << "\" persistent histograms" << " to file: " << persistent_location_.value(); return false; diff --git a/naiveproxy/src/base/native_library.h b/naiveproxy/src/base/native_library.h index 6e8f90ba25..bca1eb9577 100644 --- a/naiveproxy/src/base/native_library.h +++ b/naiveproxy/src/base/native_library.h @@ -9,11 +9,11 @@ // a loadable module. #include +#include #include "base/base_export.h" #include "base/files/file_path.h" #include "base/memory/raw_ptr_exclusion.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" #if BUILDFLAG(IS_WIN) @@ -122,13 +122,13 @@ BASE_EXPORT void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, // - "mylib.dll" on Windows // - "libmylib.so" on Linux // - "libmylib.dylib" on Mac -BASE_EXPORT std::string GetNativeLibraryName(StringPiece name); +BASE_EXPORT std::string GetNativeLibraryName(std::string_view name); // Returns the full platform-specific name for a gn |loadable_module| target. // See tools/gn/docs/reference.md#loadable_module // The returned name is the same as GetNativeLibraryName() on all platforms // except for Mac where for "mylib" it returns "mylib.so". -BASE_EXPORT std::string GetLoadableModuleName(StringPiece name); +BASE_EXPORT std::string GetLoadableModuleName(std::string_view name); } // namespace base diff --git a/naiveproxy/src/base/native_library_fuchsia.cc b/naiveproxy/src/base/native_library_fuchsia.cc index 52c7d19bb2..c8c75f0d21 100644 --- a/naiveproxy/src/base/native_library_fuchsia.cc +++ b/naiveproxy/src/base/native_library_fuchsia.cc @@ -14,6 +14,8 @@ #include #include +#include + #include "base/base_paths.h" #include "base/files/file.h" #include "base/files/file_path.h" @@ -22,7 +24,6 @@ #include "base/path_service.h" #include "base/posix/safe_strerror.h" #include "base/strings/strcat.h" -#include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" @@ -98,11 +99,11 @@ void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, return dlsym(library, name); } -std::string GetNativeLibraryName(StringPiece name) { +std::string GetNativeLibraryName(std::string_view name) { return StrCat({"lib", name, ".so"}); } -std::string GetLoadableModuleName(StringPiece name) { +std::string GetLoadableModuleName(std::string_view name) { return GetNativeLibraryName(name); } diff --git a/naiveproxy/src/base/native_library_ios.mm b/naiveproxy/src/base/native_library_ios.mm index 34350f2d8f..22c0e13b78 100644 --- a/naiveproxy/src/base/native_library_ios.mm +++ b/naiveproxy/src/base/native_library_ios.mm @@ -4,9 +4,10 @@ #include "base/native_library.h" +#include + #include "base/check.h" #include "base/notimplemented.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" namespace base { @@ -35,12 +36,12 @@ void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, return nullptr; } -std::string GetNativeLibraryName(StringPiece name) { +std::string GetNativeLibraryName(std::string_view name) { DCHECK(IsStringASCII(name)); return std::string(name); } -std::string GetLoadableModuleName(StringPiece name) { +std::string GetLoadableModuleName(std::string_view name) { return GetNativeLibraryName(name); } diff --git a/naiveproxy/src/base/native_library_mac.mm b/naiveproxy/src/base/native_library_mac.mm index 4d9bdfc09a..d2e142a5ee 100644 --- a/naiveproxy/src/base/native_library_mac.mm +++ b/naiveproxy/src/base/native_library_mac.mm @@ -7,12 +7,13 @@ #include #include +#include + #include "base/apple/scoped_cftyperef.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" #include "base/strings/strcat.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -120,12 +121,12 @@ void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, return function_pointer; } -std::string GetNativeLibraryName(StringPiece name) { +std::string GetNativeLibraryName(std::string_view name) { DCHECK(IsStringASCII(name)); return StrCat({"lib", name, ".dylib"}); } -std::string GetLoadableModuleName(StringPiece name) { +std::string GetLoadableModuleName(std::string_view name) { DCHECK(IsStringASCII(name)); return StrCat({name, ".so"}); } diff --git a/naiveproxy/src/base/native_library_posix.cc b/naiveproxy/src/base/native_library_posix.cc index ab8587de9e..45a9147565 100644 --- a/naiveproxy/src/base/native_library_posix.cc +++ b/naiveproxy/src/base/native_library_posix.cc @@ -6,11 +6,12 @@ #include +#include + #include "base/files/file_path.h" #include "base/logging.h" #include "base/notreached.h" #include "base/strings/strcat.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/scoped_blocking_call.h" @@ -62,12 +63,12 @@ void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, return dlsym(library, name); } -std::string GetNativeLibraryName(StringPiece name) { +std::string GetNativeLibraryName(std::string_view name) { DCHECK(IsStringASCII(name)); return StrCat({"lib", name, ".so"}); } -std::string GetLoadableModuleName(StringPiece name) { +std::string GetLoadableModuleName(std::string_view name) { return GetNativeLibraryName(name); } diff --git a/naiveproxy/src/base/native_library_win.cc b/naiveproxy/src/base/native_library_win.cc index b9ac4772c8..ab6b7f35a9 100644 --- a/naiveproxy/src/base/native_library_win.cc +++ b/naiveproxy/src/base/native_library_win.cc @@ -6,12 +6,13 @@ #include +#include + #include "base/files/file_util.h" #include "base/metrics/histogram_macros.h" #include "base/path_service.h" #include "base/scoped_native_library.h" #include "base/strings/strcat.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -127,12 +128,12 @@ void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, return reinterpret_cast(GetProcAddress(library, name)); } -std::string GetNativeLibraryName(StringPiece name) { +std::string GetNativeLibraryName(std::string_view name) { DCHECK(IsStringASCII(name)); return StrCat({name, ".dll"}); } -std::string GetLoadableModuleName(StringPiece name) { +std::string GetLoadableModuleName(std::string_view name) { return GetNativeLibraryName(name); } diff --git a/naiveproxy/src/base/observer_list.h b/naiveproxy/src/base/observer_list.h index 98bfcca8f9..fd97b9fd8a 100644 --- a/naiveproxy/src/base/observer_list.h +++ b/naiveproxy/src/base/observer_list.h @@ -127,6 +127,16 @@ class ObserverList { allow_reentrancy, internal::UncheckedObserverAdapter>; + // Allow declaring an ObserverList<...>::UncheckedAndRawPtrExcluded that + // holds raw pointers without raw_ptr<>. This is used to avoid performance + // regressions caused by ObserverList::Unchecked's raw_ptr<> operations. + // Use of this alias is managed by chrome-memory-safety@google.com. + using UncheckedAndRawPtrExcluded = ObserverList< + ObserverType, + check_empty, + allow_reentrancy, + internal::UncheckedObserverAdapter>; + // An iterator class that can be used to access the list of observers. class Iter { public: diff --git a/naiveproxy/src/base/observer_list_internal.h b/naiveproxy/src/base/observer_list_internal.h index ef12d3d61a..ea60e13ff9 100644 --- a/naiveproxy/src/base/observer_list_internal.h +++ b/naiveproxy/src/base/observer_list_internal.h @@ -24,7 +24,8 @@ namespace base { namespace internal { // Adapter for putting raw pointers into an ObserverList::Unchecked. -template +template class BASE_EXPORT UncheckedObserverAdapter { public: explicit UncheckedObserverAdapter(const void* observer) @@ -55,7 +56,9 @@ class BASE_EXPORT UncheckedObserverAdapter { #endif // DCHECK_IS_ON() private: - raw_ptr ptr_; + using StorageType = + std::conditional_t>; + StorageType ptr_; #if DCHECK_IS_ON() base::debug::StackTrace stack_; #endif // DCHECK_IS_ON() diff --git a/naiveproxy/src/base/one_shot_event.cc b/naiveproxy/src/base/one_shot_event.cc index 051d63ad2d..25c7d8cad8 100644 --- a/naiveproxy/src/base/one_shot_event.cc +++ b/naiveproxy/src/base/one_shot_event.cc @@ -5,100 +5,88 @@ #include "base/one_shot_event.h" #include + +#include #include #include "base/functional/callback.h" #include "base/location.h" -#include "base/task/single_thread_task_runner.h" +#include "base/sequence_checker.h" #include "base/task/task_runner.h" #include "base/time/time.h" namespace base { struct OneShotEvent::TaskInfo { - TaskInfo() {} + TaskInfo() = default; TaskInfo(const Location& from_here, - scoped_refptr runner, + scoped_refptr runner, OnceClosure task, const TimeDelta& delay) : from_here(from_here), runner(std::move(runner)), task(std::move(task)), delay(delay) { - CHECK(this->runner.get()); // Detect mistakes with a decent stack frame. + CHECK(this->runner); // Detect mistakes with a decent stack frame. } TaskInfo(TaskInfo&&) = default; TaskInfo& operator=(TaskInfo&&) = default; Location from_here; - scoped_refptr runner; + scoped_refptr runner; OnceClosure task; TimeDelta delay; }; -OneShotEvent::OneShotEvent() : signaled_(false) { - // It's acceptable to construct the OneShotEvent on one thread, but - // immediately move it to another thread. - thread_checker_.DetachFromThread(); +OneShotEvent::OneShotEvent() { + // It's acceptable to construct the `OneShotEvent` on one sequence, but + // immediately move it to another sequence. + DETACH_FROM_SEQUENCE(sequence_checker_); } OneShotEvent::OneShotEvent(bool signaled) : signaled_(signaled) { - thread_checker_.DetachFromThread(); + DETACH_FROM_SEQUENCE(sequence_checker_); } -OneShotEvent::~OneShotEvent() {} +OneShotEvent::~OneShotEvent() = default; void OneShotEvent::Post(const Location& from_here, OnceClosure task, - scoped_refptr runner) const { - PostImpl(from_here, std::move(task), std::move(runner), TimeDelta()); + scoped_refptr runner) const { + PostDelayed(from_here, std::move(task), TimeDelta(), std::move(runner)); } void OneShotEvent::PostDelayed(const Location& from_here, OnceClosure task, - const TimeDelta& delay) const { - PostImpl(from_here, std::move(task), - SingleThreadTaskRunner::GetCurrentDefault(), delay); -} - -void OneShotEvent::Signal() { - DCHECK(thread_checker_.CalledOnValidThread()); - - CHECK(!signaled_) << "Only call Signal once."; - - signaled_ = true; - // After this point, a call to Post() from one of the queued tasks - // could proceed immediately, but the fact that this object is - // single-threaded prevents that from being relevant. - - // Move tasks to a temporary to ensure no new ones are added. - std::vector moved_tasks; - std::swap(moved_tasks, tasks_); - - // We could randomize tasks in debug mode in order to check that - // the order doesn't matter... - for (TaskInfo& task : moved_tasks) { - if (task.delay.is_zero()) - task.runner->PostTask(task.from_here, std::move(task.task)); - else - task.runner->PostDelayedTask(task.from_here, std::move(task.task), - task.delay); - } - DCHECK(tasks_.empty()) << "No new tasks should be added during task running!"; -} - -void OneShotEvent::PostImpl(const Location& from_here, - OnceClosure task, - scoped_refptr runner, - const TimeDelta& delay) const { - DCHECK(thread_checker_.CalledOnValidThread()); + const TimeDelta& delay, + scoped_refptr runner) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (is_signaled()) { - if (delay.is_zero()) - runner->PostTask(from_here, std::move(task)); - else - runner->PostDelayedTask(from_here, std::move(task), delay); + runner->PostDelayedTask(from_here, std::move(task), delay); } else { tasks_.emplace_back(from_here, std::move(runner), std::move(task), delay); } } +void OneShotEvent::Signal() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + CHECK(!signaled_) << "Only call Signal once."; + + signaled_ = true; + // After this point, a call to `Post` from one of the queued tasks could + // proceed immediately, but the fact that this object is sequence-bound + // prevents that from being relevant. + + // Move tasks to a temporary to ensure no new ones are added. + std::vector moved_tasks = std::exchange(tasks_, {}); + + // We could randomize tasks in debug mode in order to check that + // the order doesn't matter... + for (TaskInfo& task : moved_tasks) { + task.runner->PostDelayedTask(task.from_here, std::move(task.task), + task.delay); + } + DCHECK(tasks_.empty()) << "No new tasks should be added during task running!"; +} + } // namespace base diff --git a/naiveproxy/src/base/one_shot_event.h b/naiveproxy/src/base/one_shot_event.h index 2c5753ac81..7008182b52 100644 --- a/naiveproxy/src/base/one_shot_event.h +++ b/naiveproxy/src/base/one_shot_event.h @@ -11,93 +11,92 @@ #include "base/check.h" #include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" namespace base { class Location; -class SingleThreadTaskRunner; class TimeDelta; -// This class represents an event that's expected to happen once. It -// allows clients to guarantee that code is run after the OneShotEvent -// is signaled. If the OneShotEvent is destroyed before it's -// signaled, the closures are destroyed without being run. +// This class represents an event that's expected to happen once. It allows +// clients to guarantee that code is run after the `OneShotEvent` is signaled. +// If the `OneShotEvent` is destroyed before it's signaled, the closures are +// destroyed without being run. // -// This class is similar to a WaitableEvent combined with several -// WaitableEventWatchers, but using it is simpler. +// This class is similar to a `WaitableEvent` combined with several +// `WaitableEventWatcher`s, but using it is simpler. // -// This class is not thread-safe, and must be used from a single thread. +// This class' methods must be used from a single sequence (although not +// necessarily the one in which it has been constructed). +// However, there are no restrictions on the `TaskRunner`s used - and hence, the +// sequence/thread on which the posted tasks will run. By default they will +// be posted to the current sequence's default task runner. class BASE_EXPORT OneShotEvent { public: OneShotEvent(); // Use the following constructor to create an already signaled event. This is // useful if you construct the event on a different thread from where it is - // used, in which case it is not possible to call Signal() just after + // used, in which case it is not possible to call `Signal` just after // construction. explicit OneShotEvent(bool signaled); ~OneShotEvent(); - // True if Signal has been called. This function is mostly for - // migrating old code; usually calling Post() unconditionally will - // result in more readable code. + // True if `Signal` has been called. This function is mostly for migrating old + // code; usually calling `Post` unconditionally will result in more readable + // code. bool is_signaled() const { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return signaled_; } - // Causes is_signaled() to return true and all tasks to be posted to their + // Causes `is_signaled` to return true and all tasks to be posted to their // corresponding task runners in the FIFO order. Note that tasks posted to - // different SingleThreadTaskRunners may still execute in arbitrary order. - // This method must only be called once. + // different `TaskRunner`s may still execute in arbitrary order. This + // method must only be called once. void Signal(); - // Scheduled |task| to be called on |runner| after is_signaled() - // becomes true. If called with |delay|, then the task will happen - // (roughly) |delay| after is_signaled(), *not* |delay| after the - // post. Inside |task|, if this OneShotEvent is still alive, - // CHECK(is_signaled()) will never fail (which implies that - // OneShotEvent::Reset() doesn't exist). + // Schedules `task` to be called on `runner` after `is_signaled` becomes + // `true`. If called with `delay`, then the task will happen (roughly) `delay` + // after `is_signaled`, *not* `delay` after the post. Inside `task`, if this + // `OneShotEvent` is still alive, `CHECK(is_signaled())` will never fail + // (which implies that `OneShotEvent::Reset` doesn't exist). // - // If |*this| is destroyed before being released, none of these - // tasks will be executed. + // If `*this` is destroyed before being released, none of these tasks will be + // executed. // - // Tasks are posted in FIFO order, however, tasks posted to different - // SingleThreadTaskRunners may still execute in an arbitrary order. Tasks will - // never be called on the current thread before this function returns. Beware - // that there's no simple way to wait for all tasks on a OneShotEvent to - // complete, so it's almost never safe to use base::Unretained() when creating - // one. + // Tasks are posted in FIFO order, however, tasks may still execute in an + // arbitrary order (specified by the combination and type of `TaskRunner`s + // used). Tasks will never be called on the current sequence before this + // function returns. + // Beware that there's no simple way to wait for all tasks on a `OneShotEvent` + // to complete, so it's almost never safe to use `base::Unretained` when + // creating one. void Post(const Location& from_here, OnceClosure task, - scoped_refptr runner = - SingleThreadTaskRunner::GetCurrentDefault()) const; + scoped_refptr runner = + SequencedTaskRunner::GetCurrentDefault()) const; void PostDelayed(const Location& from_here, OnceClosure task, - const TimeDelta& delay) const; + const TimeDelta& delay, + scoped_refptr runner = + SequencedTaskRunner::GetCurrentDefault()) const; private: struct TaskInfo; + SEQUENCE_CHECKER(sequence_checker_); - void PostImpl(const Location& from_here, - OnceClosure task, - scoped_refptr runner, - const TimeDelta& delay) const; + bool signaled_ = false; - ThreadChecker thread_checker_; - - bool signaled_; - - // The task list is mutable because it's not part of the logical - // state of the object. This lets us return const references to the - // OneShotEvent to clients that just want to run tasks through it - // without worrying that they'll signal the event. + // The task list is mutable because it's not part of the logical state of the + // object. This lets us return const references to the `OneShotEvent` to + // clients that just want to run tasks through it without worrying that + // they'll signal the event. // - // Optimization note: We could reduce the size of this class to a - // single pointer by storing |signaled_| in the low bit of a - // pointer, and storing the size and capacity of the array (if any) - // on the far end of the pointer. + // Optimization note: We could reduce the size of this class to a single + // pointer by storing `signaled_` in the low bit of a pointer, and storing the + // size and capacity of the array (if any) on the far end of the pointer. mutable std::vector tasks_; }; diff --git a/naiveproxy/src/base/pickle.cc b/naiveproxy/src/base/pickle.cc index e67971e565..c2755cbabc 100644 --- a/naiveproxy/src/base/pickle.cc +++ b/naiveproxy/src/base/pickle.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "base/bits.h" @@ -165,7 +166,7 @@ bool PickleIterator::ReadString(std::string* result) { return true; } -bool PickleIterator::ReadStringPiece(StringPiece* result) { +bool PickleIterator::ReadStringPiece(std::string_view* result) { size_t len; if (!ReadLength(&len)) return false; @@ -173,7 +174,7 @@ bool PickleIterator::ReadStringPiece(StringPiece* result) { if (!read_from) return false; - *result = StringPiece(read_from, len); + *result = std::string_view(read_from, len); return true; } @@ -189,7 +190,7 @@ bool PickleIterator::ReadString16(std::u16string* result) { return true; } -bool PickleIterator::ReadStringPiece16(StringPiece16* result) { +bool PickleIterator::ReadStringPiece16(std::u16string_view* result) { size_t len; if (!ReadLength(&len)) return false; @@ -197,7 +198,8 @@ bool PickleIterator::ReadStringPiece16(StringPiece16* result) { if (!read_from) return false; - *result = StringPiece16(reinterpret_cast(read_from), len); + *result = + std::u16string_view(reinterpret_cast(read_from), len); return true; } @@ -332,11 +334,11 @@ Pickle& Pickle::operator=(const Pickle& other) { return *this; } -void Pickle::WriteString(const StringPiece& value) { +void Pickle::WriteString(std::string_view value) { WriteData(value.data(), value.size()); } -void Pickle::WriteString16(const StringPiece16& value) { +void Pickle::WriteString16(std::u16string_view value) { WriteInt(checked_cast(value.size())); WriteBytes(value.data(), value.size() * sizeof(char16_t)); } diff --git a/naiveproxy/src/base/pickle.h b/naiveproxy/src/base/pickle.h index ec297d38b9..d81fd5db10 100644 --- a/naiveproxy/src/base/pickle.h +++ b/naiveproxy/src/base/pickle.h @@ -23,7 +23,6 @@ #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/memory/ref_counted.h" -#include "base/strings/string_piece.h" namespace base { @@ -51,11 +50,13 @@ class BASE_EXPORT PickleIterator { [[nodiscard]] bool ReadFloat(float* result); [[nodiscard]] bool ReadDouble(double* result); [[nodiscard]] bool ReadString(std::string* result); - // The StringPiece data will only be valid for the lifetime of the message. - [[nodiscard]] bool ReadStringPiece(StringPiece* result); + // The std::string_view data will only be valid for the lifetime of the + // message. + [[nodiscard]] bool ReadStringPiece(std::string_view* result); [[nodiscard]] bool ReadString16(std::u16string* result); - // The StringPiece16 data will only be valid for the lifetime of the message. - [[nodiscard]] bool ReadStringPiece16(StringPiece16* result); + // The std::u16string_view data will only be valid for the lifetime of the + // message. + [[nodiscard]] bool ReadStringPiece16(std::u16string_view* result); // A pointer to the data will be placed in |*data|, and the length will be // placed in |*length|. The pointer placed into |*data| points into the @@ -229,8 +230,8 @@ class BASE_EXPORT Pickle { void WriteUInt64(uint64_t value) { WritePOD(value); } void WriteFloat(float value) { WritePOD(value); } void WriteDouble(double value) { WritePOD(value); } - void WriteString(const StringPiece& value); - void WriteString16(const StringPiece16& value); + void WriteString(std::string_view value); + void WriteString16(std::u16string_view value); // "Data" is a blob with a length. When you read it out you will be given the // length. See also WriteBytes. // TODO(https://crbug.com/40284755): Migrate callers to the span versions. diff --git a/naiveproxy/src/base/process/launch.h b/naiveproxy/src/base/process/launch.h index 56990778cb..c6a92bd4de 100644 --- a/naiveproxy/src/base/process/launch.h +++ b/naiveproxy/src/base/process/launch.h @@ -36,6 +36,10 @@ #include "base/posix/file_descriptor_shuffle.h" #endif +#if BUILDFLAG(IS_ANDROID) +#include "base/android/binder.h" +#endif + namespace base { #if BUILDFLAG(IS_APPLE) @@ -189,6 +193,13 @@ struct BASE_EXPORT LaunchOptions { FileHandleMappingVector fds_to_remap; #endif // BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_ANDROID) + // Set of strong IBinder references to be passed to the child process. These + // make their way to ChildProcessServiceDelegate.onConnectionSetup (Java) + // within the new child process. + std::vector binders; +#endif + #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) // Set/unset environment variables. These are applied on top of the parent // process environment. Empty (the default) means to inherit the same diff --git a/naiveproxy/src/base/process/memory.cc b/naiveproxy/src/base/process/memory.cc index e0c256137b..2aa660ab15 100644 --- a/naiveproxy/src/base/process/memory.cc +++ b/naiveproxy/src/base/process/memory.cc @@ -11,7 +11,7 @@ #include "base/immediate_crash.h" #include "base/logging.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_PARTITION_ALLOC) #include "partition_alloc/page_allocator.h" diff --git a/naiveproxy/src/base/process/memory_fuchsia.cc b/naiveproxy/src/base/process/memory_fuchsia.cc index 121c7f24d0..6c3175618a 100644 --- a/naiveproxy/src/base/process/memory_fuchsia.cc +++ b/naiveproxy/src/base/process/memory_fuchsia.cc @@ -4,7 +4,7 @@ #include "base/process/memory.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include "partition_alloc/shim/allocator_shim.h" diff --git a/naiveproxy/src/base/process/memory_linux.cc b/naiveproxy/src/base/process/memory_linux.cc index bbbbf4f699..6d802c2839 100644 --- a/naiveproxy/src/base/process/memory_linux.cc +++ b/naiveproxy/src/base/process/memory_linux.cc @@ -15,7 +15,7 @@ #include "base/strings/string_number_conversions.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/shim/allocator_shim.h" #if !PA_BUILDFLAG(USE_ALLOCATOR_SHIM) && \ diff --git a/naiveproxy/src/base/process/memory_mac.mm b/naiveproxy/src/base/process/memory_mac.mm index bb14d92ffc..9d3a5d6054 100644 --- a/naiveproxy/src/base/process/memory_mac.mm +++ b/naiveproxy/src/base/process/memory_mac.mm @@ -5,10 +5,11 @@ #include "base/process/memory.h" #include + #include #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/shim/allocator_interception_apple.h" #include "partition_alloc/shim/allocator_shim.h" diff --git a/naiveproxy/src/base/process/memory_win.cc b/naiveproxy/src/base/process/memory_win.cc index b032bbf1b5..7f26781b83 100644 --- a/naiveproxy/src/base/process/memory_win.cc +++ b/naiveproxy/src/base/process/memory_win.cc @@ -4,7 +4,7 @@ #include "base/process/memory.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_ALLOCATOR_SHIM) #include "partition_alloc/shim/allocator_shim.h" diff --git a/naiveproxy/src/base/profiler/OWNERS b/naiveproxy/src/base/profiler/OWNERS index bc48135f84..f088ce881e 100644 --- a/naiveproxy/src/base/profiler/OWNERS +++ b/naiveproxy/src/base/profiler/OWNERS @@ -1,3 +1,2 @@ agarwaltushar@google.com -dproy@chromium.org wittman@chromium.org diff --git a/naiveproxy/src/base/profiler/chrome_unwind_info_android.h b/naiveproxy/src/base/profiler/chrome_unwind_info_android.h index db08ef84ee..8483b31b5b 100644 --- a/naiveproxy/src/base/profiler/chrome_unwind_info_android.h +++ b/naiveproxy/src/base/profiler/chrome_unwind_info_android.h @@ -9,6 +9,7 @@ #include "base/base_export.h" #include "base/containers/span.h" +#include "base/memory/raw_span.h" namespace base { @@ -127,7 +128,7 @@ struct BASE_EXPORT ChromeUnwindInfoAndroid { // - 10101nnn // - 10110000 // - 10110010 uleb128 - span unwind_instruction_table; + raw_span unwind_instruction_table; // Function offset table is expected to have following memory layout: // +---------------------+---------------------+ @@ -158,7 +159,7 @@ struct BASE_EXPORT ChromeUnwindInfoAndroid { // - Within each function section, offset strictly decreases. By doing so, // each function's own terminal instruction will serve as termination // condition when searching in the table. - span function_offset_table; + raw_span function_offset_table; // The function table represents the individual functions within a 128kb page. // The relevant entry for an instruction offset from the start of the text @@ -188,7 +189,7 @@ struct BASE_EXPORT ChromeUnwindInfoAndroid { // - Within each page, `Page Offset` strictly increases. // - Each `FunctionTableEntry` represents a function where the start // address falls into the page memory address range. - span function_table; + raw_span function_table; // The page table represents discrete 128kb 'pages' of memory in the text // section, each of which contains functions. The page table is indexed by @@ -212,7 +213,7 @@ struct BASE_EXPORT ChromeUnwindInfoAndroid { // Note: // - The page start instructions in page table non-strictly increases, i.e // empty page is allowed. - span page_table; + raw_span page_table; }; // Creates `ChromeUnwindInfoAndroid` struct based on binary `data` assuming diff --git a/naiveproxy/src/base/profiler/frame.h b/naiveproxy/src/base/profiler/frame.h index 4d5ca01445..3b12289b38 100644 --- a/naiveproxy/src/base/profiler/frame.h +++ b/naiveproxy/src/base/profiler/frame.h @@ -6,7 +6,7 @@ #define BASE_PROFILER_FRAME_H_ #include "base/base_export.h" -#include "base/memory/raw_ptr_exclusion.h" +#include "base/memory/raw_ptr.h" #include "base/profiler/module_cache.h" namespace base { @@ -28,9 +28,7 @@ struct BASE_EXPORT Frame { uintptr_t instruction_pointer; // The module information. - // `module` is not a raw_ptr<...> because it is used with gmock Field() that - // expects a raw pointer in V8UnwinderTest.UnwindThroughV8Frames. - RAW_PTR_EXCLUSION const ModuleCache::Module* module; + raw_ptr module; // This serves as a temporary way to pass function names from libunwindstack // unwinder to tracing profiler. Not used by any other unwinder. diff --git a/naiveproxy/src/base/profiler/stack_copier.cc b/naiveproxy/src/base/profiler/stack_copier.cc index 16144dcaba..6cc3a6acef 100644 --- a/naiveproxy/src/base/profiler/stack_copier.cc +++ b/naiveproxy/src/base/profiler/stack_copier.cc @@ -9,13 +9,47 @@ #include "base/profiler/stack_copier.h" +#include + #include "base/bits.h" #include "base/compiler_specific.h" +#include "base/profiler/stack_buffer.h" +#include "partition_alloc/tagging.h" namespace base { StackCopier::~StackCopier() = default; +std::unique_ptr StackCopier::CloneStack( + const StackBuffer& stack_buffer, + uintptr_t* stack_top, + RegisterContext* thread_context) { + const uintptr_t original_top = *stack_top; + const uintptr_t original_bottom = + reinterpret_cast(stack_buffer.buffer()); + size_t stack_size = original_top - original_bottom; + auto cloned_stack_buffer = std::make_unique(stack_size); + const uint8_t* stack_copy_bottom = CopyStackContentsAndRewritePointers( + reinterpret_cast(stack_buffer.buffer()), + reinterpret_cast(original_top), + StackBuffer::kPlatformStackAlignment, cloned_stack_buffer->buffer()); + + // `stack_buffer` is double pointer aligned by default so we should always + // get the same result. + CHECK(stack_copy_bottom == + reinterpret_cast(cloned_stack_buffer->buffer())); + *stack_top = + reinterpret_cast(stack_copy_bottom) + stack_size; + + for (uintptr_t* reg : GetRegistersToRewrite(thread_context)) { + *reg = RewritePointerIfInOriginalStack( + reinterpret_cast(original_bottom), + reinterpret_cast(original_top), stack_copy_bottom, + *reg); + } + return cloned_stack_buffer; +} + // static uintptr_t StackCopier::RewritePointerIfInOriginalStack( const uint8_t* original_stack_bottom, @@ -42,6 +76,12 @@ const uint8_t* StackCopier::CopyStackContentsAndRewritePointers( const uintptr_t* original_stack_top, size_t platform_stack_alignment, uintptr_t* stack_buffer_bottom) { + // Disable MTE during this function because this function indiscriminately + // reads stack frames, some of which belong to system libraries, not Chrome + // itself. With stack tagging, some bytes on the stack have MTE tags different + // from the stack pointer tag. + partition_alloc::SuspendTagCheckingScope suspend_tag_checking_scope; + const uint8_t* byte_src = original_stack_bottom; // The first address in the stack with pointer alignment. Pointer-aligned // values from this point to the end of the stack are possibly rewritten using diff --git a/naiveproxy/src/base/profiler/stack_copier.h b/naiveproxy/src/base/profiler/stack_copier.h index 44945fd0b1..1c026ffde1 100644 --- a/naiveproxy/src/base/profiler/stack_copier.h +++ b/naiveproxy/src/base/profiler/stack_copier.h @@ -7,6 +7,8 @@ #include +#include + #include "base/base_export.h" #include "base/profiler/register_context.h" #include "base/time/time.h" @@ -49,7 +51,19 @@ class BASE_EXPORT StackCopier { RegisterContext* thread_context, Delegate* delegate) = 0; + // Creates a copy of StackBuffer so that it can be passed to another thread. + // `stack_top` as passed in will match stack_top in `stack_buffer` but + // will be modified to match the returned StackBuffer. Similarly any + // registers in `thread_context` will be manipulated so they are relative to + // the result of this function. + std::unique_ptr CloneStack(const StackBuffer& stack_buffer, + uintptr_t* stack_top, + RegisterContext* thread_context); + protected: + virtual std::vector GetRegistersToRewrite( + RegisterContext* thread_context) = 0; + // If the value at |pointer| points to the original stack, rewrite it to point // to the corresponding location in the copied stack. // diff --git a/naiveproxy/src/base/profiler/stack_copier_signal.cc b/naiveproxy/src/base/profiler/stack_copier_signal.cc index 4fb174d57c..6e0d2eda7c 100644 --- a/naiveproxy/src/base/profiler/stack_copier_signal.cc +++ b/naiveproxy/src/base/profiler/stack_copier_signal.cc @@ -295,4 +295,9 @@ bool StackCopierSignal::CopyStack(StackBuffer* stack_buffer, return copied; } +std::vector StackCopierSignal::GetRegistersToRewrite( + RegisterContext* thread_context) { + return thread_delegate_->GetRegistersToRewrite(thread_context); +} + } // namespace base diff --git a/naiveproxy/src/base/profiler/stack_copier_signal.h b/naiveproxy/src/base/profiler/stack_copier_signal.h index 5b3e77818d..f8fde8d270 100644 --- a/naiveproxy/src/base/profiler/stack_copier_signal.h +++ b/naiveproxy/src/base/profiler/stack_copier_signal.h @@ -30,6 +30,10 @@ class BASE_EXPORT StackCopierSignal : public StackCopier { using StackCopier::CopyStackContentsAndRewritePointers; + protected: + std::vector GetRegistersToRewrite( + RegisterContext* thread_context) override; + private: std::unique_ptr thread_delegate_; }; diff --git a/naiveproxy/src/base/profiler/stack_copier_suspend.cc b/naiveproxy/src/base/profiler/stack_copier_suspend.cc index 64da4b4bb7..3e5022a2a8 100644 --- a/naiveproxy/src/base/profiler/stack_copier_suspend.cc +++ b/naiveproxy/src/base/profiler/stack_copier_suspend.cc @@ -76,4 +76,9 @@ bool StackCopierSuspend::CopyStack(StackBuffer* stack_buffer, return true; } +std::vector StackCopierSuspend::GetRegistersToRewrite( + RegisterContext* thread_context) { + return thread_delegate_->GetRegistersToRewrite(thread_context); +} + } // namespace base diff --git a/naiveproxy/src/base/profiler/stack_copier_suspend.h b/naiveproxy/src/base/profiler/stack_copier_suspend.h index a8d1f2adaf..540fc0832b 100644 --- a/naiveproxy/src/base/profiler/stack_copier_suspend.h +++ b/naiveproxy/src/base/profiler/stack_copier_suspend.h @@ -30,6 +30,10 @@ class BASE_EXPORT StackCopierSuspend : public StackCopier { RegisterContext* thread_context, Delegate* delegate) override; + protected: + std::vector GetRegistersToRewrite( + RegisterContext* thread_context) override; + private: std::unique_ptr thread_delegate_; }; diff --git a/naiveproxy/src/base/profiler/stack_sampler.cc b/naiveproxy/src/base/profiler/stack_sampler.cc index aa495ef32f..461c24faba 100644 --- a/naiveproxy/src/base/profiler/stack_sampler.cc +++ b/naiveproxy/src/base/profiler/stack_sampler.cc @@ -21,6 +21,7 @@ #include "base/profiler/suspendable_thread_delegate.h" #include "base/profiler/unwinder.h" #include "base/ranges/algorithm.h" +#include "base/task/thread_pool.h" // IMPORTANT NOTE: Some functions within this implementation are invoked while // the target thread is suspended so it must not do any allocation from the @@ -33,6 +34,8 @@ namespace base { namespace { +using CallbackRunner = base::RefCountedData; + Unwinder* GetUnwinder(const UnwinderCapture& state) { return std::get<0>(state); } @@ -77,10 +80,17 @@ class StackCopierDelegate : public StackCopier::Delegate { const MetadataRecorder::MetadataProvider* const metadata_provider_; }; +bool g_use_thread_pool = true; + } // namespace StackSampler::~StackSampler() = default; +// static +void StackSampler::SetUseThreadPool(bool use_thread_pool) { + g_use_thread_pool = use_thread_pool; +} + std::unique_ptr StackSampler::CreateStackBuffer() { size_t size = GetStackBufferSize(); if (size == 0) { @@ -90,36 +100,82 @@ std::unique_ptr StackSampler::CreateStackBuffer() { } void StackSampler::Initialize() { - std::vector> unwinders = - std::move(unwinders_factory_).Run(); - - // |unwinders| is iterated backward since |unwinders_factory_| generates - // unwinders in increasing priority order. |unwinders_| is stored in - // decreasing priority order for ease of use within the class. - unwinders_.insert(unwinders_.end(), - std::make_move_iterator(unwinders.rbegin()), - std::make_move_iterator(unwinders.rend())); - - for (const auto& unwinder : unwinders_) { - unwinder->Initialize(module_cache_); - } - was_initialized_ = true; + unwind_data_->Initialize(std::move(unwinders_factory_).Run()); + if (g_use_thread_pool) { + thread_pool_runner_ = base::ThreadPool::CreateSequencedTaskRunner({}); + + // The thread pool might not start right away (or it may never start), so we + // schedule a job and wait for it to become running before we schedule other + // work. + thread_pool_runner_->PostTaskAndReply( + FROM_HERE, base::DoNothing(), + base::BindOnce(&StackSampler::ThreadPoolRunning, + weak_ptr_factory_.GetWeakPtr())); + } +} + +void StackSampler::ThreadPoolRunning() { + thread_pool_ready_ = true; + unwind_data_->OnThreadPoolRunning(); +} + +void StackSampler::Stop(OnceClosure done_callback) { + if (thread_pool_ready_) { + // Post a task to the sequenced task runner to ensure we've completed any + // remaining work. We need to ensure we use a CallbackRunner here + // because we want to ensure `done_callback` is called even if + // PostTaskAndReply returns false. + auto callback_runner = base::MakeRefCounted( + ScopedClosureRunner(std::move(done_callback))); + bool res = thread_pool_runner_->PostTaskAndReply( + FROM_HERE, base::DoNothing(), + base::BindOnce([](scoped_refptr runner) {}, + callback_runner)); + if (!res) { + callback_runner->data.RunAndReset(); + } + + } else { + std::move(done_callback).Run(); + } } void StackSampler::AddAuxUnwinder(std::unique_ptr unwinder) { - // Initialize() invokes Initialize() on the unwinders that are present - // at the time. If it hasn't occurred yet, we allow it to add the initial - // modules, otherwise we do it here. - if (was_initialized_) { - unwinder->Initialize(module_cache_); + if (thread_pool_ready_) { + // If we have initialized a thread pool, then we need the Initialize to + // be called on the thread pool since it will manipulate the ModuleCache, + // but AddAuxUnwinder needs to happen on the SamplingThread. + thread_pool_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce( + [](StackUnwindData* unwind_data, + std::unique_ptr unwinder) { + unwinder->Initialize(unwind_data->module_cache()); + return unwinder; + }, + base::Unretained(unwind_data_.get()), std::move(unwinder)), + base::BindOnce(&StackSampler::AddAuxUnwinderWithoutInit, + weak_ptr_factory_.GetWeakPtr())); + } else { + // Initialize() invokes Initialize() on the unwinders that are present + // at the time. If it hasn't occurred yet, we allow it to add the initial + // modules, otherwise we do it here. + if (was_initialized_) { + unwinder->Initialize(unwind_data_->module_cache()); + } + unwind_data_->AddAuxUnwinder(std::move(unwinder)); } - unwinders_.push_front(std::move(unwinder)); +} + +void StackSampler::AddAuxUnwinderWithoutInit( + std::unique_ptr unwinder) { + unwind_data_->AddAuxUnwinder(std::move(unwinder)); } void StackSampler::RecordStackFrames(StackBuffer* stack_buffer, - ProfileBuilder* profile_builder, - PlatformThreadId thread_id) { + PlatformThreadId thread_id, + base::OnceClosure done_callback) { DCHECK(stack_buffer); if (record_sample_callback_) { @@ -130,11 +186,8 @@ void StackSampler::RecordStackFrames(StackBuffer* stack_buffer, uintptr_t stack_top; TimeTicks timestamp; - std::vector unwinders; - for (const auto& unwinder : unwinders_) { - unwinders.emplace_back(unwinder.get(), - unwinder->CreateUnwinderStateCapture()); - } + std::vector unwinders = unwind_data_->GetUnwinderSnapshot(); + ProfileBuilder* profile_builder = unwind_data_->profile_builder(); bool copy_stack_succeeded; { @@ -150,6 +203,7 @@ void StackSampler::RecordStackFrames(StackBuffer* stack_buffer, if (!copy_stack_succeeded) { profile_builder->OnSampleCompleted( {}, timestamp.is_null() ? TimeTicks::Now() : timestamp); + std::move(done_callback).Run(); return; } @@ -161,10 +215,6 @@ void StackSampler::RecordStackFrames(StackBuffer* stack_buffer, test_delegate_->OnPreStackWalk(); } - profile_builder->OnSampleCompleted( - WalkStack(module_cache_, &thread_context, stack_top, unwinders), - timestamp); - #if BUILDFLAG(IS_CHROMEOS) ptrdiff_t stack_size = reinterpret_cast(stack_top) - reinterpret_cast(stack_buffer->buffer()); @@ -197,6 +247,46 @@ void StackSampler::RecordStackFrames(StackBuffer* stack_buffer, stack_buffer->MarkUpperBufferContentsAsUnneeded(kLargeStackSize); } #endif // #if BUILDFLAG(IS_CHROMEOS) + + if (thread_pool_ready_) { + // Since `stack_buffer` needs to be the maximum stack size and be + // preallocated it tends to be much larger than the actual stack size. So we + // copy the stack here that is a smaller size before passing it over to the + // worker. To allocate a `StackBuffer` for every sample not be good. + std::unique_ptr cloned_stack = + stack_copier_->CloneStack(*stack_buffer, &stack_top, &thread_context); + thread_pool_runner_->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce( + [](StackUnwindData* unwind_data, + std::vector unwinders, + RegisterContext thread_context, + std::unique_ptr stack, uintptr_t stack_top) { + return WalkStack(unwind_data->module_cache(), &thread_context, + stack_top, std::move(unwinders)); + }, + base::Unretained(unwind_data_.get()), std::move(unwinders), + OwnedRef(thread_context), std::move(cloned_stack), stack_top), + base::BindOnce(&StackSampler::UnwindComplete, + weak_ptr_factory_.GetWeakPtr(), timestamp, + std::move(done_callback))); + } else { + auto frames = WalkStack(unwind_data_->module_cache(), &thread_context, + stack_top, std::move(unwinders)); + UnwindComplete(timestamp, std::move(done_callback), std::move(frames)); + } +} + +void StackSampler::UnwindComplete(TimeTicks timestamp, + OnceClosure done_callback, + std::vector frames) { + unwind_data_->profile_builder()->OnSampleCompleted(std::move(frames), + timestamp); + std::move(done_callback).Run(); +} + +StackUnwindData* StackSampler::GetStackUnwindData() { + return unwind_data_.get(); } // static @@ -204,32 +294,34 @@ std::vector StackSampler::WalkStackForTesting( ModuleCache* module_cache, RegisterContext* thread_context, uintptr_t stack_top, - const std::vector& unwinders) { - return WalkStack(module_cache, thread_context, stack_top, unwinders); + std::vector unwinders) { + return WalkStack(module_cache, thread_context, stack_top, + std::move(unwinders)); } // static std::unique_ptr StackSampler::CreateForTesting( std::unique_ptr stack_copier, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, - ModuleCache* module_cache, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate) { - return base::WrapUnique(new StackSampler( - std::move(stack_copier), std::move(core_unwinders_factory), module_cache, - record_sample_callback, test_delegate)); + return base::WrapUnique( + new StackSampler(std::move(stack_copier), std::move(stack_unwind_data), + std::move(core_unwinders_factory), + record_sample_callback, test_delegate)); } StackSampler::StackSampler(std::unique_ptr stack_copier, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, - ModuleCache* module_cache, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate) : stack_copier_(std::move(stack_copier)), unwinders_factory_(std::move(core_unwinders_factory)), - module_cache_(module_cache), record_sample_callback_(std::move(record_sample_callback)), - test_delegate_(test_delegate) { + test_delegate_(test_delegate), + unwind_data_(std::move(stack_unwind_data)) { CHECK(unwinders_factory_); } @@ -238,7 +330,7 @@ std::vector StackSampler::WalkStack( ModuleCache* module_cache, RegisterContext* thread_context, uintptr_t stack_top, - const std::vector& unwinders) { + std::vector unwinders) { std::vector stack; // Reserve enough memory for most stacks, to avoid repeated // allocations. Approximately 99.9% of recorded stacks are 128 frames or @@ -269,8 +361,7 @@ std::vector StackSampler::WalkStack( // The unwinder with the lowest priority should be the only one that returns // COMPLETED since the stack starts in native code. - DCHECK(result != UnwindResult::kCompleted || - GetUnwinder(*unwinder) == GetUnwinder(unwinders.back())); + DCHECK(result != UnwindResult::kCompleted || *unwinder == unwinders.back()); } while (result != UnwindResult::kAborted && result != UnwindResult::kCompleted && // Give up if the authoritative unwinder for the module was unable to diff --git a/naiveproxy/src/base/profiler/stack_sampler.h b/naiveproxy/src/base/profiler/stack_sampler.h index 2d69ab7877..a5f12a57e4 100644 --- a/naiveproxy/src/base/profiler/stack_sampler.h +++ b/naiveproxy/src/base/profiler/stack_sampler.h @@ -6,37 +6,37 @@ #define BASE_PROFILER_STACK_SAMPLER_H_ #include -#include #include #include "base/base_export.h" #include "base/containers/circular_deque.h" #include "base/functional/callback.h" +#include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/profiler/frame.h" #include "base/profiler/register_context.h" #include "base/profiler/sampling_profiler_thread_token.h" #include "base/profiler/stack_copier.h" -#include "base/profiler/stack_sampler.h" +#include "base/profiler/stack_unwind_data.h" #include "base/threading/platform_thread.h" #include "build/build_config.h" namespace base { class ModuleCache; -class ProfileBuilder; class StackBuffer; class StackSamplerTestDelegate; class Unwinder; -class UnwinderStateCapture; - -using UnwinderCapture = - std::tuple, std::unique_ptr>; // StackSampler is an implementation detail of StackSamplingProfiler. It // abstracts the native implementation required to record a set of stack frames // for a given thread. It delegates to StackCopier for the // platform-specific stack copying implementation. +// This class is used on both the SamplingThread and a worker thread of the +// thread pool. Recording stack frames always occurs on the +// SamplingThread but unwinding the stack can occur on either the SamplingThread +// or a worker thread. Sampling can start before the thread pool is running so +// unwinding will occur on the SamplingThread until the thread pool is ready. class BASE_EXPORT StackSampler { public: // Factory for generating a set of Unwinders for use by the profiler. @@ -50,7 +50,7 @@ class BASE_EXPORT StackSampler { // if this platform does not support stack sampling. static std::unique_ptr Create( SamplingProfilerThreadToken thread_token, - ModuleCache* module_cache, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate); @@ -67,12 +67,18 @@ class BASE_EXPORT StackSampler { // any StackSampler object. static std::unique_ptr CreateStackBuffer(); + // Set whether a thread pool should be used or not. + static void SetUseThreadPool(bool use_thread_pool); + // The following functions are all called on the SamplingThread (not the // thread being sampled). // Performs post-construction initialization on the SamplingThread. void Initialize(); + // Stops the sampler. + void Stop(OnceClosure done_callback); + // Adds an auxiliary unwinder to handle additional, non-native-code unwind // scenarios. Unwinders must be inserted in increasing priority, following // |unwinders| provided in Create(), to guide unwind attempts. @@ -80,21 +86,23 @@ class BASE_EXPORT StackSampler { // Records a set of frames and returns them. void RecordStackFrames(StackBuffer* stack_buffer, - ProfileBuilder* profile_builder, - PlatformThreadId thread_id); + PlatformThreadId thread_id, + OnceClosure done_callback); + + StackUnwindData* GetStackUnwindData(); // Exposes the internal function for unit testing. static std::vector WalkStackForTesting( ModuleCache* module_cache, RegisterContext* thread_context, uintptr_t stack_top, - const std::vector& unwinders); + std::vector unwinders); // Create a StackSampler, overriding the platform-specific components. static std::unique_ptr CreateForTesting( std::unique_ptr stack_copier, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, - ModuleCache* module_cache, RepeatingClosure record_sample_callback = RepeatingClosure(), StackSamplerTestDelegate* test_delegate = nullptr); @@ -112,25 +120,29 @@ class BASE_EXPORT StackSampler { #endif private: + FRIEND_TEST_ALL_PREFIXES(StackSamplerTest, + AuxUnwinderInvokedWhileRecordingStackFrames); + StackSampler(std::unique_ptr stack_copier, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, - ModuleCache* module_cache, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate); - static std::vector WalkStack( - ModuleCache* module_cache, - RegisterContext* thread_context, - uintptr_t stack_top, - const std::vector& unwinders); + static std::vector WalkStack(ModuleCache* module_cache, + RegisterContext* thread_context, + uintptr_t stack_top, + std::vector unwinders); + + void UnwindComplete(TimeTicks timestamp, + OnceClosure done_callback, + std::vector frames); + void AddAuxUnwinderWithoutInit(std::unique_ptr unwinder); + void ThreadPoolRunning(); const std::unique_ptr stack_copier_; UnwindersFactory unwinders_factory_; - // Unwinders are stored in decreasing priority order. - base::circular_deque> unwinders_; - - const raw_ptr module_cache_; const RepeatingClosure record_sample_callback_; const raw_ptr test_delegate_; @@ -141,10 +153,16 @@ class BASE_EXPORT StackSampler { uint32_t stack_size_histogram_sampling_counter_ = 0; #endif - // True if ownership of the object has been passed to the profiling thread and - // initialization has occurred there. If that's the case then any further aux - // unwinder that's provided needs to be set up within AddAuxUnwinder(). + scoped_refptr thread_pool_runner_; + + // The StackUnwindData will be in released on the `thread_pool_runner_` if it + // is non-null. + std::unique_ptr unwind_data_; + bool was_initialized_ = false; + bool thread_pool_ready_ = false; + + base::WeakPtrFactory weak_ptr_factory_{this}; }; // StackSamplerTestDelegate provides seams for test code to execute during stack diff --git a/naiveproxy/src/base/profiler/stack_sampler_android.cc b/naiveproxy/src/base/profiler/stack_sampler_android.cc index 9a6c609375..7ac08cc417 100644 --- a/naiveproxy/src/base/profiler/stack_sampler_android.cc +++ b/naiveproxy/src/base/profiler/stack_sampler_android.cc @@ -17,7 +17,7 @@ namespace base { std::unique_ptr StackSampler::Create( SamplingProfilerThreadToken thread_token, - ModuleCache* module_cache, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate) { @@ -26,7 +26,7 @@ std::unique_ptr StackSampler::Create( return nullptr; return base::WrapUnique(new StackSampler( std::make_unique(std::move(thread_delegate)), - std::move(core_unwinders_factory), module_cache, + std::move(stack_unwind_data), std::move(core_unwinders_factory), std::move(record_sample_callback), test_delegate)); } diff --git a/naiveproxy/src/base/profiler/stack_sampler_ios.cc b/naiveproxy/src/base/profiler/stack_sampler_ios.cc index caacf56f21..209b4f458d 100644 --- a/naiveproxy/src/base/profiler/stack_sampler_ios.cc +++ b/naiveproxy/src/base/profiler/stack_sampler_ios.cc @@ -35,7 +35,7 @@ std::vector> CreateUnwinders() { // static std::unique_ptr StackSampler::Create( SamplingProfilerThreadToken thread_token, - ModuleCache* module_cache, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate) { @@ -44,7 +44,7 @@ std::unique_ptr StackSampler::Create( return base::WrapUnique(new StackSampler( std::make_unique( std::make_unique(thread_token)), - BindOnce(&CreateUnwinders), module_cache, + std::move(stack_unwind_data), BindOnce(&CreateUnwinders), std::move(record_sample_callback), test_delegate)); #else return nullptr; diff --git a/naiveproxy/src/base/profiler/stack_sampler_mac.cc b/naiveproxy/src/base/profiler/stack_sampler_mac.cc index a8620bac16..e8bdf6bd4d 100644 --- a/naiveproxy/src/base/profiler/stack_sampler_mac.cc +++ b/naiveproxy/src/base/profiler/stack_sampler_mac.cc @@ -29,7 +29,7 @@ std::vector> CreateUnwinders() { // static std::unique_ptr StackSampler::Create( SamplingProfilerThreadToken thread_token, - ModuleCache* module_cache, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate) { @@ -37,7 +37,7 @@ std::unique_ptr StackSampler::Create( return base::WrapUnique(new StackSampler( std::make_unique( std::make_unique(thread_token)), - BindOnce(&CreateUnwinders), module_cache, + std::move(stack_unwind_data), BindOnce(&CreateUnwinders), std::move(record_sample_callback), test_delegate)); } diff --git a/naiveproxy/src/base/profiler/stack_sampler_posix.cc b/naiveproxy/src/base/profiler/stack_sampler_posix.cc index a29bc57d85..84d15fd6c8 100644 --- a/naiveproxy/src/base/profiler/stack_sampler_posix.cc +++ b/naiveproxy/src/base/profiler/stack_sampler_posix.cc @@ -39,7 +39,7 @@ std::vector> CreateUnwinders() { std::unique_ptr StackSampler::Create( SamplingProfilerThreadToken thread_token, - ModuleCache* module_cache, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate) { @@ -49,7 +49,7 @@ std::unique_ptr StackSampler::Create( return base::WrapUnique( new StackSampler(std::make_unique( ThreadDelegatePosix::Create(thread_token)), - BindOnce(&CreateUnwinders), module_cache, + std::move(stack_unwind_data), BindOnce(&CreateUnwinders), std::move(record_sample_callback), test_delegate)); #else return nullptr; diff --git a/naiveproxy/src/base/profiler/stack_sampler_win.cc b/naiveproxy/src/base/profiler/stack_sampler_win.cc index 0519b6ef78..da156defb0 100644 --- a/naiveproxy/src/base/profiler/stack_sampler_win.cc +++ b/naiveproxy/src/base/profiler/stack_sampler_win.cc @@ -17,7 +17,7 @@ namespace base { // static std::unique_ptr StackSampler::Create( SamplingProfilerThreadToken thread_token, - ModuleCache* module_cache, + std::unique_ptr stack_unwind_data, UnwindersFactory core_unwinders_factory, RepeatingClosure record_sample_callback, StackSamplerTestDelegate* test_delegate) { @@ -31,7 +31,7 @@ std::unique_ptr StackSampler::Create( return base::WrapUnique(new StackSampler( std::make_unique( std::make_unique(thread_token)), - BindOnce(create_unwinders), module_cache, + std::move(stack_unwind_data), BindOnce(create_unwinders), std::move(record_sample_callback), test_delegate)); #else return nullptr; diff --git a/naiveproxy/src/base/profiler/stack_sampling_profiler.cc b/naiveproxy/src/base/profiler/stack_sampling_profiler.cc index 24d7dc8419..243094bb48 100644 --- a/naiveproxy/src/base/profiler/stack_sampling_profiler.cc +++ b/naiveproxy/src/base/profiler/stack_sampling_profiler.cc @@ -22,6 +22,7 @@ #include "base/profiler/profiler_buildflags.h" #include "base/profiler/stack_buffer.h" #include "base/profiler/stack_sampler.h" +#include "base/profiler/stack_unwind_data.h" #include "base/profiler/unwinder.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" @@ -123,13 +124,11 @@ class StackSamplingProfiler::SamplingThread : public Thread { CollectionContext(PlatformThreadId thread_id, const SamplingParams& params, WaitableEvent* finished, - std::unique_ptr sampler, - std::unique_ptr profile_builder) + std::unique_ptr sampler) : collection_id(next_collection_id.GetNext()), thread_id(thread_id), params(params), finished(finished), - profile_builder(std::move(profile_builder)), sampler(std::move(sampler)) {} ~CollectionContext() = default; @@ -142,9 +141,6 @@ class StackSamplingProfiler::SamplingThread : public Thread { const raw_ptr finished; // Signaled when all sampling complete. - // Receives the sampling data and builds a CallStackProfile. - std::unique_ptr profile_builder; - // Platform-specific module that does the actual sampling. std::unique_ptr sampler; @@ -157,6 +153,9 @@ class StackSamplingProfiler::SamplingThread : public Thread { // Counter that indicates the current sample position along the acquisition. int sample_count = 0; + // Whether stop has been requested. + bool stopping = false; + // Sequence number for generating new collection ids. static AtomicSequenceNumber next_collection_id; }; @@ -254,6 +253,7 @@ class StackSamplingProfiler::SamplingThread : public Thread { int64_t value, std::optional thread_id); void RemoveCollectionTask(int collection_id); + void ScheduleCollectionStop(int collection_id); void RecordSampleTask(int collection_id); void ShutdownTask(int add_events); @@ -461,7 +461,7 @@ void StackSamplingProfiler::SamplingThread::Remove(int collection_id) { // runner above and the call below. In that case, however, everything has // stopped so there's no need to try to stop it. task_runner->PostTask(FROM_HERE, - BindOnce(&SamplingThread::RemoveCollectionTask, + BindOnce(&SamplingThread::ScheduleCollectionStop, Unretained(this), collection_id)); } @@ -551,8 +551,10 @@ void StackSamplingProfiler::SamplingThread::FinishCollection( collection->profile_start_time + collection->params.sampling_interval; - collection->profile_builder->OnProfileCompleted( - profile_duration, collection->params.sampling_interval); + collection->sampler->GetStackUnwindData() + ->profile_builder() + ->OnProfileCompleted(profile_duration, + collection->params.sampling_interval); // Signal that this collection is finished. WaitableEvent* collection_finished = collection->finished; @@ -611,8 +613,9 @@ void StackSamplingProfiler::SamplingThread::ApplyMetadataToPastSamplesTask( for (auto& id_collection_pair : active_collections_) { if (thread_id && id_collection_pair.second->thread_id != thread_id) continue; - id_collection_pair.second->profile_builder->ApplyMetadataRetrospectively( - period_start, period_end, item); + id_collection_pair.second->sampler->GetStackUnwindData() + ->profile_builder() + ->ApplyMetadataRetrospectively(period_start, period_end, item); } } @@ -627,7 +630,9 @@ void StackSamplingProfiler::SamplingThread::AddProfileMetadataTask( if (thread_id && id_collection_pair.second->thread_id != thread_id) { continue; } - id_collection_pair.second->profile_builder->AddProfileMetadata(item); + id_collection_pair.second->sampler->GetStackUnwindData() + ->profile_builder() + ->AddProfileMetadata(item); } } @@ -674,6 +679,21 @@ void StackSamplingProfiler::SamplingThread::RemoveCollectionTask( FinishCollection(std::move(collection)); } +void StackSamplingProfiler::SamplingThread::ScheduleCollectionStop( + int collection_id) { + DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); + + auto found = active_collections_.find(collection_id); + if (found == active_collections_.end()) { + return; + } + + CollectionContext* collection = found->second.get(); + collection->stopping = true; + collection->sampler->Stop(BindOnce(&SamplingThread::RemoveCollectionTask, + Unretained(this), collection_id)); +} + void StackSamplingProfiler::SamplingThread::RecordSampleTask( int collection_id) { DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId()); @@ -681,24 +701,35 @@ void StackSamplingProfiler::SamplingThread::RecordSampleTask( auto found = active_collections_.find(collection_id); // The task won't be found if it has been stopped. - if (found == active_collections_.end()) + if (found == active_collections_.end()) { return; + } CollectionContext* collection = found->second.get(); + // If we are in the process of stopping just don't collect a stack + // trace as that would cause further jobs to be scheduled. + if (collection->stopping) { + return; + } + // If this is the first sample, the collection params need to be filled. if (collection->sample_count == 0) { collection->profile_start_time = TimeTicks::Now(); collection->next_sample_time = TimeTicks::Now(); } + bool more_collections_remaining = + ++collection->sample_count < collection->params.samples_per_profile; // Record a single sample. - collection->sampler->RecordStackFrames(stack_buffer_.get(), - collection->profile_builder.get(), - collection->thread_id); - + collection->sampler->RecordStackFrames( + stack_buffer_.get(), collection->thread_id, + more_collections_remaining + ? DoNothing() + : BindOnce(&SamplingThread::RemoveCollectionTask, Unretained(this), + collection_id)); // Schedule the next sample recording if there is one. - if (++collection->sample_count < collection->params.samples_per_profile) { + if (more_collections_remaining) { collection->next_sample_time = GetNextSampleTimeImpl( collection->next_sample_time, collection->params.sampling_interval, TimeTicks::Now()); @@ -710,15 +741,6 @@ void StackSamplingProfiler::SamplingThread::RecordSampleTask( DCHECK(success); return; } - - // Take ownership of |collection| and remove it from the map. - std::unique_ptr owned_collection = - std::move(found->second); - size_t count = active_collections_.erase(collection_id); - DCHECK_EQ(1U, count); - - // All capturing has completed so finish the collection. - FinishCollection(std::move(owned_collection)); } void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) { @@ -837,19 +859,18 @@ StackSamplingProfiler::StackSamplingProfiler( StackSamplerTestDelegate* test_delegate) : thread_token_(thread_token), params_(params), - profile_builder_(std::move(profile_builder)), - sampler_(StackSampler::Create(thread_token, - profile_builder_->GetModuleCache(), - std::move(core_unwinders_factory), - std::move(record_sample_callback), - test_delegate)), + sampler_(StackSampler::Create( + thread_token, + std::make_unique(std::move(profile_builder)), + std::move(core_unwinders_factory), + std::move(record_sample_callback), + test_delegate)), // The event starts "signaled" so code knows it's safe to start thread // and "manual" so that it can be waited in multiple places. profiling_inactive_(kResetPolicy, WaitableEvent::InitialState::SIGNALED), profiler_id_(kNullProfilerId) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), "StackSamplingProfiler::StackSamplingProfiler"); - DCHECK(profile_builder_); } StackSamplingProfiler::~StackSamplingProfiler() { @@ -879,14 +900,11 @@ void StackSamplingProfiler::Start() { "StackSamplingProfiler::Start"); // Multiple calls to Start() for a single StackSamplingProfiler object is not - // allowed. If profile_builder_ is nullptr, then Start() has been called - // already. - DCHECK(profile_builder_); - - // |sampler_| will be null if sampling isn't supported on the current - // platform. - if (!sampler_) + // allowed. If `sampler_` is nullptr, then Start() has been called already or + // sampling isn't supported on the current platform. + if (!sampler_) { return; + } // The IsSignaled() check below requires that the WaitableEvent be manually // reset, to avoid signaling the event in IsSignaled() itself. @@ -903,8 +921,8 @@ void StackSamplingProfiler::Start() { DCHECK_EQ(kNullProfilerId, profiler_id_); profiler_id_ = SamplingThread::GetInstance()->Add( std::make_unique( - thread_token_.id, params_, &profiling_inactive_, std::move(sampler_), - std::move(profile_builder_))); + thread_token_.id, params_, &profiling_inactive_, + std::move(sampler_))); DCHECK_NE(kNullProfilerId, profiler_id_); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), diff --git a/naiveproxy/src/base/profiler/stack_sampling_profiler.h b/naiveproxy/src/base/profiler/stack_sampling_profiler.h index 7f895361c5..c8cae2e7f9 100644 --- a/naiveproxy/src/base/profiler/stack_sampling_profiler.h +++ b/naiveproxy/src/base/profiler/stack_sampling_profiler.h @@ -209,18 +209,13 @@ class BASE_EXPORT StackSamplingProfiler { const SamplingParams params_; - // Receives the sampling data and builds a profile. The ownership of this - // object will be transferred to the sampling thread when thread sampling - // starts. - std::unique_ptr profile_builder_; - // Stack sampler which stops the thread and collects stack frames. The // ownership of this object will be transferred to the sampling thread when // thread sampling starts. std::unique_ptr sampler_; // This starts "signaled", is reset when sampling begins, and is signaled - // when that sampling is complete and the profile_builder_'s + // when that sampling is complete and the profile builder's // OnProfileCompleted function has executed. WaitableEvent profiling_inactive_; diff --git a/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.h b/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.h index 9f8ac60fa0..9fd3de3e9d 100644 --- a/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.h +++ b/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.h @@ -15,6 +15,7 @@ #include "base/memory/raw_ptr.h" #include "base/native_library.h" #include "base/profiler/frame.h" +#include "base/profiler/module_cache.h" #include "base/profiler/sampling_profiler_thread_token.h" #include "base/profiler/stack_sampling_profiler.h" #include "base/synchronization/waitable_event.h" @@ -23,7 +24,6 @@ namespace base { class Unwinder; -class ModuleCache; // A thread to target for profiling that will run the supplied closure. class TargetThread : public PlatformThread::Delegate { diff --git a/naiveproxy/src/base/profiler/stack_unwind_data.cc b/naiveproxy/src/base/profiler/stack_unwind_data.cc new file mode 100644 index 0000000000..a05f982404 --- /dev/null +++ b/naiveproxy/src/base/profiler/stack_unwind_data.cc @@ -0,0 +1,72 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/profiler/stack_unwind_data.h" + +#include +#include + +#include "base/check.h" +#include "base/compiler_specific.h" +#include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" +#include "base/metrics/histogram_functions.h" +#include "base/numerics/safe_conversions.h" +#include "base/profiler/metadata_recorder.h" +#include "base/profiler/profile_builder.h" +#include "base/profiler/sample_metadata.h" +#include "base/profiler/stack_buffer.h" +#include "base/profiler/stack_copier.h" +#include "base/profiler/suspendable_thread_delegate.h" +#include "base/profiler/unwinder.h" +#include "base/ranges/algorithm.h" + +namespace base { + +StackUnwindData::StackUnwindData( + std::unique_ptr profile_builder) + : profile_builder_(std::move(profile_builder)), + module_cache_(profile_builder_->GetModuleCache()) {} + +StackUnwindData::~StackUnwindData() = default; + +std::vector StackUnwindData::GetUnwinderSnapshot() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sampling_thread_sequence_checker_); + std::vector unwinders; + for (const auto& unwinder : unwinders_) { + unwinders.emplace_back(unwinder.get(), + unwinder->CreateUnwinderStateCapture()); + } + return unwinders; +} + +void StackUnwindData::Initialize( + std::vector> unwinders) { + DETACH_FROM_SEQUENCE(sampling_thread_sequence_checker_); + DETACH_FROM_SEQUENCE(worker_sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sampling_thread_sequence_checker_); + // |unwinders| is iterated backward since |unwinders_factory_| generates + // unwinders in increasing priority order. |unwinders_| is stored in + // decreasing priority order for ease of use within the class. + unwinders_.insert(unwinders_.end(), + std::make_move_iterator(unwinders.rbegin()), + std::make_move_iterator(unwinders.rend())); + + for (const auto& unwinder : unwinders_) { + unwinder->Initialize(module_cache_); + } +} + +void StackUnwindData::OnThreadPoolRunning() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sampling_thread_sequence_checker_); + DETACH_FROM_SEQUENCE(worker_sequence_checker_); +} + +void StackUnwindData::AddAuxUnwinder(std::unique_ptr unwinder) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sampling_thread_sequence_checker_); + // Unwinder would already be initialized on the SamplingThread. + unwinders_.push_front(std::move(unwinder)); +} + +} // namespace base diff --git a/naiveproxy/src/base/profiler/stack_unwind_data.h b/naiveproxy/src/base/profiler/stack_unwind_data.h new file mode 100644 index 0000000000..2b7b984b42 --- /dev/null +++ b/naiveproxy/src/base/profiler/stack_unwind_data.h @@ -0,0 +1,71 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_PROFILER_STACK_UNWIND_DATA_H_ +#define BASE_PROFILER_STACK_UNWIND_DATA_H_ + +#include +#include +#include + +#include "base/base_export.h" +#include "base/containers/circular_deque.h" +#include "base/memory/raw_ptr.h" +#include "base/profiler/frame.h" +#include "base/profiler/register_context.h" +#include "base/sequence_checker.h" +#include "base/synchronization/lock.h" +#include "base/task/sequenced_task_runner.h" +#include "base/thread_annotations.h" + +namespace base { + +class ProfileBuilder; +class Unwinder; +class ModuleCache; +class UnwinderStateCapture; + +using UnwinderCapture = + std::tuple, std::unique_ptr>; + +// StackUnwindData is an implementation detail of StackSamplingProfiler. It +// contains data so that we can unwind stacks off the sampling thread. +class BASE_EXPORT StackUnwindData { + public: + explicit StackUnwindData(std::unique_ptr profile_builder); + ~StackUnwindData(); + + ProfileBuilder* profile_builder() { return profile_builder_.get(); } + + ModuleCache* module_cache() { + DCHECK_CALLED_ON_VALID_SEQUENCE(worker_sequence_checker_); + return module_cache_; + } + + // These are called by the SamplingThread. + void Initialize(std::vector> unwinders); + std::vector GetUnwinderSnapshot(); + void OnThreadPoolRunning(); + + // This may be called by either: + // 1) the thread to sample if we haven't started sampling + // 2) the SamplingThread + void AddAuxUnwinder(std::unique_ptr unwinder); + + private: + SEQUENCE_CHECKER(sampling_thread_sequence_checker_); + SEQUENCE_CHECKER(worker_sequence_checker_); + + // Receives the sampling data and builds a CallStackProfile. + std::unique_ptr profile_builder_; + + // Unwinders are stored in decreasing priority order. + base::circular_deque> unwinders_ + GUARDED_BY_CONTEXT(sampling_thread_sequence_checker_); + const raw_ptr module_cache_; +}; + +} // namespace base + +#endif // BASE_PROFILER_STACK_UNWIND_DATA_H_ diff --git a/naiveproxy/src/base/rand_util_fuchsia.cc b/naiveproxy/src/base/rand_util_fuchsia.cc index cea0a17cdc..4026dd8cda 100644 --- a/naiveproxy/src/base/rand_util_fuchsia.cc +++ b/naiveproxy/src/base/rand_util_fuchsia.cc @@ -15,7 +15,6 @@ #include "base/containers/span.h" #include "base/feature_list.h" -#include "third_party/boringssl/src/include/openssl/crypto.h" #include "third_party/boringssl/src/include/openssl/rand.h" namespace base { @@ -47,8 +46,6 @@ bool UseBoringSSLForRandBytes() { void RandBytes(span output) { if (internal::UseBoringSSLForRandBytes()) { - // Ensure BoringSSL is initialized so it can use things like RDRAND. - CRYPTO_library_init(); // BoringSSL's RAND_bytes always returns 1. Any error aborts the program. (void)RAND_bytes(output.data(), output.size()); return; diff --git a/naiveproxy/src/base/rand_util_posix.cc b/naiveproxy/src/base/rand_util_posix.cc index d7dc274bfd..00fcb8547e 100644 --- a/naiveproxy/src/base/rand_util_posix.cc +++ b/naiveproxy/src/base/rand_util_posix.cc @@ -37,7 +37,6 @@ #endif #if !BUILDFLAG(IS_NACL) -#include "third_party/boringssl/src/include/openssl/crypto.h" #include "third_party/boringssl/src/include/openssl/rand.h" #endif @@ -185,8 +184,6 @@ void RandBytesInternal(span output, bool avoid_allocation) { #if !BUILDFLAG(IS_NACL) // The BoringSSL experiment takes priority over everything else. if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) { - // Ensure BoringSSL is initialized so it can use things like RDRAND. - CRYPTO_library_init(); // BoringSSL's RAND_bytes always returns 1. Any error aborts the program. (void)RAND_bytes(output.data(), output.size()); return; diff --git a/naiveproxy/src/base/rand_util_win.cc b/naiveproxy/src/base/rand_util_win.cc index 6961e0ef81..9c2ae8389b 100644 --- a/naiveproxy/src/base/rand_util_win.cc +++ b/naiveproxy/src/base/rand_util_win.cc @@ -20,7 +20,6 @@ #include "base/check.h" #include "base/feature_list.h" -#include "third_party/boringssl/src/include/openssl/crypto.h" #include "third_party/boringssl/src/include/openssl/rand.h" // Prototype for ProcessPrng. @@ -72,8 +71,6 @@ decltype(&ProcessPrng) GetProcessPrng() { void RandBytesInternal(span output, bool avoid_allocation) { if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) { - // Ensure BoringSSL is initialized so it can use things like RDRAND. - CRYPTO_library_init(); // BoringSSL's RAND_bytes always returns 1. Any error aborts the program. (void)RAND_bytes(output.data(), output.size()); return; diff --git a/naiveproxy/src/base/ranges/algorithm.h b/naiveproxy/src/base/ranges/algorithm.h index 0c3515f8f2..5e69ca9cb5 100644 --- a/naiveproxy/src/base/ranges/algorithm.h +++ b/naiveproxy/src/base/ranges/algorithm.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -233,7 +234,7 @@ template > constexpr bool all_of(Range&& range, Pred pred, Proj proj = {}) { - return ranges::all_of(ranges::begin(range), ranges::end(range), + return ranges::all_of(std::ranges::begin(range), std::ranges::end(range), std::move(pred), std::move(proj)); } @@ -280,7 +281,7 @@ template > constexpr bool any_of(Range&& range, Pred pred, Proj proj = {}) { - return ranges::any_of(ranges::begin(range), ranges::end(range), + return ranges::any_of(std::ranges::begin(range), std::ranges::end(range), std::move(pred), std::move(proj)); } @@ -327,7 +328,7 @@ template > constexpr bool none_of(Range&& range, Pred pred, Proj proj = {}) { - return ranges::none_of(ranges::begin(range), ranges::end(range), + return ranges::none_of(std::ranges::begin(range), std::ranges::end(range), std::move(pred), std::move(proj)); } @@ -377,7 +378,7 @@ template > constexpr auto for_each(Range&& range, Fun f, Proj proj = {}) { - return ranges::for_each(ranges::begin(range), ranges::end(range), + return ranges::for_each(std::ranges::begin(range), std::ranges::end(range), std::move(f), std::move(proj)); } @@ -453,7 +454,7 @@ template > constexpr auto find(Range&& range, const T& value, Proj proj = {}) { - return ranges::find(ranges::begin(range), ranges::end(range), value, + return ranges::find(std::ranges::begin(range), std::ranges::end(range), value, std::move(proj)); } @@ -492,7 +493,7 @@ template > constexpr auto find_if(Range&& range, Pred pred, Proj proj = {}) { - return ranges::find_if(ranges::begin(range), ranges::end(range), + return ranges::find_if(std::ranges::begin(range), std::ranges::end(range), std::move(pred), std::move(proj)); } @@ -531,7 +532,7 @@ template > constexpr auto find_if_not(Range&& range, Pred pred, Proj proj = {}) { - return ranges::find_if_not(ranges::begin(range), ranges::end(range), + return ranges::find_if_not(std::ranges::begin(range), std::ranges::end(range), std::move(pred), std::move(proj)); } @@ -613,8 +614,8 @@ constexpr auto find_end(Range1&& range1, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::find_end(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), + return ranges::find_end(std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2)); } @@ -687,8 +688,9 @@ constexpr auto find_first_of(Range1&& range1, Proj1 proj1 = {}, Proj2 proj2 = {}) { return ranges::find_first_of( - ranges::begin(range1), ranges::end(range1), ranges::begin(range2), - ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2)); + std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), std::move(pred), + std::move(proj1), std::move(proj2)); } // [alg.adjacent.find] Adjacent find @@ -749,8 +751,9 @@ template > constexpr auto adjacent_find(Range&& range, Pred pred = {}, Proj proj = {}) { - return ranges::adjacent_find(ranges::begin(range), ranges::end(range), - std::move(pred), std::move(proj)); + return ranges::adjacent_find(std::ranges::begin(range), + std::ranges::end(range), std::move(pred), + std::move(proj)); } // [alg.count] Count @@ -794,8 +797,8 @@ template > constexpr auto count(Range&& range, const T& value, Proj proj = {}) { - return ranges::count(ranges::begin(range), ranges::end(range), value, - std::move(proj)); + return ranges::count(std::ranges::begin(range), std::ranges::end(range), + value, std::move(proj)); } // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`. @@ -833,7 +836,7 @@ template > constexpr auto count_if(Range&& range, Pred pred, Proj proj = {}) { - return ranges::count_if(ranges::begin(range), ranges::end(range), + return ranges::count_if(std::ranges::begin(range), std::ranges::end(range), std::move(pred), std::move(proj)); } @@ -903,8 +906,8 @@ constexpr auto mismatch(Range1&& range1, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::mismatch(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), + return ranges::mismatch(std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2)); } @@ -990,8 +993,8 @@ constexpr bool equal(Range1&& range1, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::equal(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), + return ranges::equal(std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2)); } @@ -1071,8 +1074,9 @@ constexpr bool is_permutation(Range1&& range1, Proj1 proj1 = {}, Proj2 proj2 = {}) { return ranges::is_permutation( - ranges::begin(range1), ranges::end(range1), ranges::begin(range2), - ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2)); + std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), std::move(pred), + std::move(proj1), std::move(proj2)); } // [alg.search] Search @@ -1142,8 +1146,8 @@ constexpr auto search(Range1&& range1, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::search(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), + return ranges::search(std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2)); } @@ -1206,8 +1210,8 @@ constexpr auto search_n(Range&& range, const T& value, Pred pred = {}, Proj proj = {}) { - return ranges::search_n(ranges::begin(range), ranges::end(range), count, - value, std::move(pred), std::move(proj)); + return ranges::search_n(std::ranges::begin(range), std::ranges::end(range), + count, value, std::move(pred), std::move(proj)); } // [alg.modifying.operations] Mutating sequence operations @@ -1258,7 +1262,8 @@ template , typename = internal::iterator_category_t> constexpr auto copy(Range&& range, OutputIterator result) { - return ranges::copy(ranges::begin(range), ranges::end(range), result); + return ranges::copy(std::ranges::begin(range), std::ranges::end(range), + result); } // Let `N` be `max(0, n)`. @@ -1341,8 +1346,8 @@ constexpr auto copy_if(Range&& range, OutputIterator result, Pred pred, Proj proj = {}) { - return ranges::copy_if(ranges::begin(range), ranges::end(range), result, - std::move(pred), std::move(proj)); + return ranges::copy_if(std::ranges::begin(range), std::ranges::end(range), + result, std::move(pred), std::move(proj)); } // Let `N` be `last - first`. @@ -1386,8 +1391,8 @@ template , typename = internal::iterator_category_t> constexpr auto copy_backward(Range&& range, BidirectionalIterator result) { - return ranges::copy_backward(ranges::begin(range), ranges::end(range), - result); + return ranges::copy_backward(std::ranges::begin(range), + std::ranges::end(range), result); } // [alg.move] Move @@ -1438,7 +1443,8 @@ template , typename = internal::iterator_category_t> constexpr auto move(Range&& range, OutputIterator result) { - return ranges::move(ranges::begin(range), ranges::end(range), result); + return ranges::move(std::ranges::begin(range), std::ranges::end(range), + result); } // Let `E(n)` be `std::move(*(last - n))`. @@ -1486,8 +1492,8 @@ template , typename = internal::iterator_category_t> constexpr auto move_backward(Range&& range, BidirectionalIterator result) { - return ranges::move_backward(ranges::begin(range), ranges::end(range), - result); + return ranges::move_backward(std::ranges::begin(range), + std::ranges::end(range), result); } // [alg.swap] Swap @@ -1539,8 +1545,9 @@ template , typename = internal::range_category_t> constexpr auto swap_ranges(Range1&& range1, Range2&& range2) { - return ranges::swap_ranges(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2)); + return ranges::swap_ranges( + std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2)); } // [alg.transform] Transform @@ -1611,8 +1618,8 @@ constexpr auto transform(Range&& range, OutputIterator result, UnaryOperation op, Proj proj = {}) { - return ranges::transform(ranges::begin(range), ranges::end(range), result, - std::move(op), std::move(proj)); + return ranges::transform(std::ranges::begin(range), std::ranges::end(range), + result, std::move(op), std::move(proj)); } // Let: @@ -1706,9 +1713,9 @@ constexpr auto transform(Range1&& range1, BinaryOperation binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::transform(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), result, - std::move(binary_op), std::move(proj1), + return ranges::transform(std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), + result, std::move(binary_op), std::move(proj1), std::move(proj2)); } @@ -1769,8 +1776,8 @@ constexpr auto replace(Range&& range, const T& old_value, const T& new_value, Proj proj = {}) { - return ranges::replace(ranges::begin(range), ranges::end(range), old_value, - new_value, std::move(proj)); + return ranges::replace(std::ranges::begin(range), std::ranges::end(range), + old_value, new_value, std::move(proj)); } // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`. @@ -1823,7 +1830,7 @@ constexpr auto replace_if(Range&& range, Predicate pred, const T& new_value, Proj proj = {}) { - return ranges::replace_if(ranges::begin(range), ranges::end(range), + return ranges::replace_if(std::ranges::begin(range), std::ranges::end(range), std::move(pred), new_value, std::move(proj)); } @@ -1898,8 +1905,9 @@ constexpr auto replace_copy(Range&& range, const T& old_value, const T& new_value, Proj proj = {}) { - return ranges::replace_copy(ranges::begin(range), ranges::end(range), result, - old_value, new_value, std::move(proj)); + return ranges::replace_copy(std::ranges::begin(range), + std::ranges::end(range), result, old_value, + new_value, std::move(proj)); } // Let `E(i)` be `bool(invoke(pred, invoke(proj, *(first + (i - result)))))`. @@ -1969,8 +1977,9 @@ constexpr auto replace_copy_if(Range&& range, Predicate pred, const T& new_value, Proj proj = {}) { - return ranges::replace_copy_if(ranges::begin(range), ranges::end(range), - result, pred, new_value, std::move(proj)); + return ranges::replace_copy_if(std::ranges::begin(range), + std::ranges::end(range), result, pred, + new_value, std::move(proj)); } // [alg.fill] Fill @@ -2011,7 +2020,8 @@ template > constexpr auto fill(Range&& range, const T& value) { - return ranges::fill(ranges::begin(range), ranges::end(range), value); + return ranges::fill(std::ranges::begin(range), std::ranges::end(range), + value); } // Let `N` be `max(0, n)`. @@ -2071,7 +2081,7 @@ template > constexpr auto generate(Range&& range, Generator gen) { - return ranges::generate(ranges::begin(range), ranges::end(range), + return ranges::generate(std::ranges::begin(range), std::ranges::end(range), std::move(gen)); } @@ -2144,8 +2154,8 @@ template > constexpr auto remove(Range&& range, const T& value, Proj proj = {}) { - return ranges::remove(ranges::begin(range), ranges::end(range), value, - std::move(proj)); + return ranges::remove(std::ranges::begin(range), std::ranges::end(range), + value, std::move(proj)); } // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`. @@ -2190,7 +2200,7 @@ template > constexpr auto remove_if(Range&& range, Predicate pred, Proj proj = {}) { - return ranges::remove_if(ranges::begin(range), ranges::end(range), + return ranges::remove_if(std::ranges::begin(range), std::ranges::end(range), std::move(pred), std::move(proj)); } @@ -2263,8 +2273,8 @@ constexpr auto remove_copy(Range&& range, OutputIterator result, const T& value, Proj proj = {}) { - return ranges::remove_copy(ranges::begin(range), ranges::end(range), result, - value, std::move(proj)); + return ranges::remove_copy(std::ranges::begin(range), std::ranges::end(range), + result, value, std::move(proj)); } // Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`. @@ -2333,8 +2343,9 @@ constexpr auto remove_copy_if(Range&& range, OutputIterator result, Pred pred, Proj proj = {}) { - return ranges::remove_copy_if(ranges::begin(range), ranges::end(range), - result, std::move(pred), std::move(proj)); + return ranges::remove_copy_if(std::ranges::begin(range), + std::ranges::end(range), result, + std::move(pred), std::move(proj)); } // [alg.unique] Unique @@ -2391,7 +2402,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto unique(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::unique(ranges::begin(range), ranges::end(range), + return ranges::unique(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -2453,8 +2464,8 @@ constexpr auto unique_copy(Range&& range, OutputIterator result, Comp comp = {}, Proj proj = {}) { - return ranges::unique_copy(ranges::begin(range), ranges::end(range), result, - std::move(comp), std::move(proj)); + return ranges::unique_copy(std::ranges::begin(range), std::ranges::end(range), + result, std::move(comp), std::move(proj)); } // [alg.reverse] Reverse @@ -2487,7 +2498,7 @@ constexpr auto reverse(BidirectionalIterator first, // Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse(R template > constexpr auto reverse(Range&& range) { - return ranges::reverse(ranges::begin(range), ranges::end(range)); + return ranges::reverse(std::ranges::begin(range), std::ranges::end(range)); } // Let `N` be `last - first`. @@ -2533,7 +2544,8 @@ template , typename = internal::iterator_category_t> constexpr auto reverse_copy(Range&& range, OutputIterator result) { - return ranges::reverse_copy(ranges::begin(range), ranges::end(range), result); + return ranges::reverse_copy(std::ranges::begin(range), + std::ranges::end(range), result); } // [alg.rotate] Rotate @@ -2572,7 +2584,8 @@ constexpr auto rotate(ForwardIterator first, // Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate(R template > constexpr auto rotate(Range&& range, iterator_t middle) { - return ranges::rotate(ranges::begin(range), middle, ranges::end(range)); + return ranges::rotate(std::ranges::begin(range), middle, + std::ranges::end(range)); } // Let `N` be `last - first`. @@ -2621,8 +2634,8 @@ template middle, OutputIterator result) { - return ranges::rotate_copy(ranges::begin(range), middle, ranges::end(range), - result); + return ranges::rotate_copy(std::ranges::begin(range), middle, + std::ranges::end(range), result); } // [alg.random.sample] Sample @@ -2678,7 +2691,7 @@ template > constexpr auto shuffle(Range&& range, UniformRandomBitGenerator&& g) { - return ranges::shuffle(ranges::begin(range), ranges::end(range), + return ranges::shuffle(std::ranges::begin(range), std::ranges::end(range), std::forward(g)); } @@ -2733,8 +2746,8 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto sort(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::sort(ranges::begin(range), ranges::end(range), std::move(comp), - std::move(proj)); + return ranges::sort(std::ranges::begin(range), std::ranges::end(range), + std::move(comp), std::move(proj)); } // [stable.sort] stable_sort @@ -2789,7 +2802,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto stable_sort(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::stable_sort(ranges::begin(range), ranges::end(range), + return ranges::stable_sort(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -2853,8 +2866,9 @@ constexpr auto partial_sort(Range&& range, iterator_t middle, Comp comp = {}, Proj proj = {}) { - return ranges::partial_sort(ranges::begin(range), middle, ranges::end(range), - std::move(comp), std::move(proj)); + return ranges::partial_sort(std::ranges::begin(range), middle, + std::ranges::end(range), std::move(comp), + std::move(proj)); } // [partial.sort.copy] partial_sort_copy @@ -2948,10 +2962,10 @@ constexpr auto partial_sort_copy(Range1&& range, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::partial_sort_copy(ranges::begin(range), ranges::end(range), - ranges::begin(result_range), - ranges::end(result_range), std::move(comp), - std::move(proj1), std::move(proj2)); + return ranges::partial_sort_copy( + std::ranges::begin(range), std::ranges::end(range), + std::ranges::begin(result_range), std::ranges::end(result_range), + std::move(comp), std::move(proj1), std::move(proj2)); } // [is.sorted] is_sorted @@ -3009,8 +3023,9 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto is_sorted_until(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::is_sorted_until(ranges::begin(range), ranges::end(range), - std::move(comp), std::move(proj)); + return ranges::is_sorted_until(std::ranges::begin(range), + std::ranges::end(range), std::move(comp), + std::move(proj)); } // Returns: Whether the range `[first, last)` is sorted with respect to `comp` @@ -3049,7 +3064,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto is_sorted(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::is_sorted(ranges::begin(range), ranges::end(range), + return ranges::is_sorted(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -3115,8 +3130,9 @@ constexpr auto nth_element(Range&& range, iterator_t nth, Comp comp = {}, Proj proj = {}) { - return ranges::nth_element(ranges::begin(range), nth, ranges::end(range), - std::move(comp), std::move(proj)); + return ranges::nth_element(std::ranges::begin(range), nth, + std::ranges::end(range), std::move(comp), + std::move(proj)); } // [alg.binary.search] Binary search @@ -3172,8 +3188,8 @@ constexpr auto lower_bound(Range&& range, const T& value, Comp comp = {}, Proj proj = {}) { - return ranges::lower_bound(ranges::begin(range), ranges::end(range), value, - std::move(comp), std::move(proj)); + return ranges::lower_bound(std::ranges::begin(range), std::ranges::end(range), + value, std::move(comp), std::move(proj)); } // [upper.bound] upper_bound @@ -3226,8 +3242,8 @@ constexpr auto upper_bound(Range&& range, const T& value, Comp comp = {}, Proj proj = {}) { - return ranges::upper_bound(ranges::begin(range), ranges::end(range), value, - std::move(comp), std::move(proj)); + return ranges::upper_bound(std::ranges::begin(range), std::ranges::end(range), + value, std::move(comp), std::move(proj)); } // [equal.range] equal_range @@ -3281,8 +3297,8 @@ constexpr auto equal_range(Range&& range, const T& value, Comp comp = {}, Proj proj = {}) { - return ranges::equal_range(ranges::begin(range), ranges::end(range), value, - std::move(comp), std::move(proj)); + return ranges::equal_range(std::ranges::begin(range), std::ranges::end(range), + value, std::move(comp), std::move(proj)); } // [binary.search] binary_search @@ -3333,8 +3349,9 @@ constexpr auto binary_search(Range&& range, const T& value, Comp comp = {}, Proj proj = {}) { - return ranges::binary_search(ranges::begin(range), ranges::end(range), value, - std::move(comp), std::move(proj)); + return ranges::binary_search(std::ranges::begin(range), + std::ranges::end(range), value, std::move(comp), + std::move(proj)); } // [alg.partitions] Partitions @@ -3370,8 +3387,9 @@ template > constexpr auto is_partitioned(Range&& range, Pred pred, Proj proj = {}) { - return ranges::is_partitioned(ranges::begin(range), ranges::end(range), - std::move(pred), std::move(proj)); + return ranges::is_partitioned(std::ranges::begin(range), + std::ranges::end(range), std::move(pred), + std::move(proj)); } // Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`. @@ -3421,7 +3439,7 @@ template > constexpr auto partition(Range&& range, Pred pred, Proj proj = {}) { - return ranges::partition(ranges::begin(range), ranges::end(range), + return ranges::partition(std::ranges::begin(range), std::ranges::end(range), std::move(pred), std::move(proj)); } @@ -3474,8 +3492,9 @@ template > constexpr auto stable_partition(Range&& range, Pred pred, Proj proj = {}) { - return ranges::stable_partition(ranges::begin(range), ranges::end(range), - std::move(pred), std::move(proj)); + return ranges::stable_partition(std::ranges::begin(range), + std::ranges::end(range), std::move(pred), + std::move(proj)); } // Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`. @@ -3544,9 +3563,9 @@ constexpr auto partition_copy(Range&& range, OutputIterator2 out_false, Pred pred, Proj proj = {}) { - return ranges::partition_copy(ranges::begin(range), ranges::end(range), - out_true, out_false, std::move(pred), - std::move(proj)); + return ranges::partition_copy(std::ranges::begin(range), + std::ranges::end(range), out_true, out_false, + std::move(pred), std::move(proj)); } // let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`. @@ -3589,8 +3608,9 @@ template > constexpr auto partition_point(Range&& range, Pred pred, Proj proj = {}) { - return ranges::partition_point(ranges::begin(range), ranges::end(range), - std::move(pred), std::move(proj)); + return ranges::partition_point(std::ranges::begin(range), + std::ranges::end(range), std::move(pred), + std::move(proj)); } // [alg.merge] Merge @@ -3691,9 +3711,10 @@ constexpr auto merge(Range1&& range1, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::merge(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), result, - std::move(comp), std::move(proj1), std::move(proj2)); + return ranges::merge(std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), + result, std::move(comp), std::move(proj1), + std::move(proj2)); } // Preconditions: `[first, middle)` and `[middle, last)` are valid ranges sorted @@ -3751,8 +3772,9 @@ constexpr auto inplace_merge(Range&& range, iterator_t middle, Comp comp = {}, Proj proj = {}) { - return ranges::inplace_merge(ranges::begin(range), middle, ranges::end(range), - std::move(comp), std::move(proj)); + return ranges::inplace_merge(std::ranges::begin(range), middle, + std::ranges::end(range), std::move(comp), + std::move(proj)); } // [alg.set.operations] Set operations on sorted structures @@ -3830,8 +3852,8 @@ constexpr auto includes(Range1&& range1, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::includes(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), + return ranges::includes(std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), std::move(comp), std::move(proj1), std::move(proj2)); } @@ -3930,9 +3952,10 @@ constexpr auto set_union(Range1&& range1, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::set_union(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), result, - std::move(comp), std::move(proj1), std::move(proj2)); + return ranges::set_union(std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), + result, std::move(comp), std::move(proj1), + std::move(proj2)); } // [set.intersection] set_intersection @@ -4030,10 +4053,10 @@ constexpr auto set_intersection(Range1&& range1, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::set_intersection(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), - result, std::move(comp), std::move(proj1), - std::move(proj2)); + return ranges::set_intersection( + std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), result, + std::move(comp), std::move(proj1), std::move(proj2)); } // [set.difference] set_difference @@ -4133,10 +4156,10 @@ constexpr auto set_difference(Range1&& range1, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) { - return ranges::set_difference(ranges::begin(range1), ranges::end(range1), - ranges::begin(range2), ranges::end(range2), - result, std::move(comp), std::move(proj1), - std::move(proj2)); + return ranges::set_difference( + std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), result, + std::move(comp), std::move(proj1), std::move(proj2)); } // [set.symmetric.difference] set_symmetric_difference @@ -4244,9 +4267,9 @@ constexpr auto set_symmetric_difference(Range1&& range1, Proj1 proj1 = {}, Proj2 proj2 = {}) { return ranges::set_symmetric_difference( - ranges::begin(range1), ranges::end(range1), ranges::begin(range2), - ranges::end(range2), result, std::move(comp), std::move(proj1), - std::move(proj2)); + std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), result, + std::move(comp), std::move(proj1), std::move(proj2)); } // [alg.heap.operations] Heap operations @@ -4305,7 +4328,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto push_heap(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::push_heap(ranges::begin(range), ranges::end(range), + return ranges::push_heap(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -4364,7 +4387,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto pop_heap(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::pop_heap(ranges::begin(range), ranges::end(range), + return ranges::pop_heap(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -4414,7 +4437,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto make_heap(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::make_heap(ranges::begin(range), ranges::end(range), + return ranges::make_heap(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -4470,7 +4493,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto sort_heap(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::sort_heap(ranges::begin(range), ranges::end(range), + return ranges::sort_heap(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -4513,7 +4536,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto is_heap(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::is_heap(ranges::begin(range), ranges::end(range), + return ranges::is_heap(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -4554,8 +4577,9 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto is_heap_until(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::is_heap_until(ranges::begin(range), ranges::end(range), - std::move(comp), std::move(proj)); + return ranges::is_heap_until(std::ranges::begin(range), + std::ranges::end(range), std::move(comp), + std::move(proj)); } // [alg.min.max] Minimum and maximum @@ -4610,7 +4634,7 @@ template > constexpr auto min(Range&& range, Comp comp = {}, Proj proj = {}) { return *std::min_element( - ranges::begin(range), ranges::end(range), + std::ranges::begin(range), std::ranges::end(range), internal::ProjectedBinaryPredicate(comp, proj, proj)); } @@ -4663,7 +4687,7 @@ template > constexpr auto max(Range&& range, Comp comp = {}, Proj proj = {}) { return *std::max_element( - ranges::begin(range), ranges::end(range), + std::ranges::begin(range), std::ranges::end(range), internal::ProjectedBinaryPredicate(comp, proj, proj)); } @@ -4699,7 +4723,7 @@ constexpr auto minmax(std::initializer_list ilist, Comp comp = {}, Proj proj = {}) { auto it = - std::minmax_element(ranges::begin(ilist), ranges::end(ilist), + std::minmax_element(std::ranges::begin(ilist), std::ranges::end(ilist), internal::ProjectedBinaryPredicate(comp, proj, proj)); return std::pair{*it.first, *it.second}; } @@ -4721,7 +4745,7 @@ template ; auto it = - std::minmax_element(ranges::begin(range), ranges::end(range), + std::minmax_element(std::ranges::begin(range), std::ranges::end(range), internal::ProjectedBinaryPredicate(comp, proj, proj)); return std::pair{*it.first, *it.second}; } @@ -4768,7 +4792,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto min_element(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::min_element(ranges::begin(range), ranges::end(range), + return ranges::min_element(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -4814,7 +4838,7 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto max_element(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::max_element(ranges::begin(range), ranges::end(range), + return ranges::max_element(std::ranges::begin(range), std::ranges::end(range), std::move(comp), std::move(proj)); } @@ -4864,8 +4888,9 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto minmax_element(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::minmax_element(ranges::begin(range), ranges::end(range), - std::move(comp), std::move(proj)); + return ranges::minmax_element(std::ranges::begin(range), + std::ranges::end(range), std::move(comp), + std::move(proj)); } // [alg.clamp] Bounded value @@ -4992,8 +5017,9 @@ constexpr bool lexicographical_compare(Range1&& range1, Proj1 proj1 = {}, Proj2 proj2 = {}) { return ranges::lexicographical_compare( - ranges::begin(range1), ranges::end(range1), ranges::begin(range2), - ranges::end(range2), std::move(comp), std::move(proj1), std::move(proj2)); + std::ranges::begin(range1), std::ranges::end(range1), + std::ranges::begin(range2), std::ranges::end(range2), std::move(comp), + std::move(proj1), std::move(proj2)); } // [alg.permutation.generators] Permutation generators @@ -5048,8 +5074,9 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto next_permutation(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::next_permutation(ranges::begin(range), ranges::end(range), - std::move(comp), std::move(proj)); + return ranges::next_permutation(std::ranges::begin(range), + std::ranges::end(range), std::move(comp), + std::move(proj)); } // Effects: Takes a sequence defined by the range `[first, last)` and transforms @@ -5101,8 +5128,9 @@ template < std::projected, Proj>, std::projected, Proj>>> constexpr auto prev_permutation(Range&& range, Comp comp = {}, Proj proj = {}) { - return ranges::prev_permutation(ranges::begin(range), ranges::end(range), - std::move(comp), std::move(proj)); + return ranges::prev_permutation(std::ranges::begin(range), + std::ranges::end(range), std::move(comp), + std::move(proj)); } } // namespace ranges diff --git a/naiveproxy/src/base/ranges/from_range.h b/naiveproxy/src/base/ranges/from_range.h new file mode 100644 index 0000000000..a0fca0a340 --- /dev/null +++ b/naiveproxy/src/base/ranges/from_range.h @@ -0,0 +1,25 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_RANGES_FROM_RANGE_H_ +#define BASE_RANGES_FROM_RANGE_H_ + +namespace base { + +// A marker type for constructors from a range. This is a backport of +// `std::from_range_t` in C++23, and will be relaced with the std version one +// day. +// +// https://en.cppreference.com/w/cpp/ranges/from_range +struct from_range_t { + explicit from_range_t() = default; +}; + +// The instantiation of `from_range_t`, to be passed to constructors taking the +// marker type `from_range_t`. +constexpr inline from_range_t from_range; + +} // namespace base + +#endif // BASE_RANGES_FROM_RANGE_H_ diff --git a/naiveproxy/src/base/ranges/ranges.h b/naiveproxy/src/base/ranges/ranges.h index 8835ac3fa4..b8ba4e6b74 100644 --- a/naiveproxy/src/base/ranges/ranges.h +++ b/naiveproxy/src/base/ranges/ranges.h @@ -15,92 +15,13 @@ #include #include -#include "base/template_util.h" - -namespace base { - -namespace internal { - -// Overload for C array. -template -constexpr T* begin(T (&array)[N], priority_tag<2>) { - return array; -} - -// Generic container overload. -template -constexpr auto begin(Range&& range, priority_tag<1>) - -> decltype(std::forward(range).begin()) { - return std::forward(range).begin(); -} - -// Overload for free begin() function. -template -constexpr auto begin(Range&& range, priority_tag<0>) - -> decltype(begin(std::forward(range))) { - return begin(std::forward(range)); -} - -// Overload for C array. -template -constexpr T* end(T (&array)[N], priority_tag<2>) { - return array + N; -} - -// Generic container overload. -template -constexpr auto end(Range&& range, priority_tag<1>) - -> decltype(std::forward(range).end()) { - return std::forward(range).end(); -} - -// Overload for free end() function. -template -constexpr auto end(Range&& range, priority_tag<0>) - -> decltype(end(std::forward(range))) { - return end(std::forward(range)); -} - -} // namespace internal - -namespace ranges { - -// Simplified implementation of C++20's std::ranges::begin. -// As opposed to std::ranges::begin, this implementation does does not check -// whether begin() returns an iterator and does not inhibit ADL. -// -// The trailing return type and dispatch to the internal implementation is -// necessary to be SFINAE friendly. -// -// Reference: https://wg21.link/range.access.begin -template -constexpr auto begin(Range&& range) noexcept - -> decltype(internal::begin(std::forward(range), - internal::priority_tag<2>())) { - return internal::begin(std::forward(range), - internal::priority_tag<2>()); -} - -// Simplified implementation of C++20's std::ranges::end. -// As opposed to std::ranges::end, this implementation does does not check -// whether end() returns an iterator and does not inhibit ADL. -// -// The trailing return type and dispatch to the internal implementation is -// necessary to be SFINAE friendly. -// -// Reference: - https://wg21.link/range.access.end -template -constexpr auto end(Range&& range) noexcept - -> decltype(internal::end(std::forward(range), - internal::priority_tag<2>())) { - return internal::end(std::forward(range), internal::priority_tag<2>()); -} +namespace base::ranges { // Implementation of C++20's std::ranges::iterator_t. // // Reference: https://wg21.link/ranges.syn#:~:text=iterator_t template -using iterator_t = decltype(ranges::begin(std::declval())); +using iterator_t = decltype(std::begin(std::declval())); // Implementation of C++20's std::ranges::range_value_t. // @@ -108,8 +29,6 @@ using iterator_t = decltype(ranges::begin(std::declval())); template using range_value_t = std::iter_value_t>; -} // namespace ranges - -} // namespace base +} // namespace base::ranges #endif // BASE_RANGES_RANGES_H_ diff --git a/naiveproxy/src/base/sampling_heap_profiler/sampling_heap_profiler.cc b/naiveproxy/src/base/sampling_heap_profiler/sampling_heap_profiler.cc index 3acae10034..4136d33af1 100644 --- a/naiveproxy/src/base/sampling_heap_profiler/sampling_heap_profiler.cc +++ b/naiveproxy/src/base/sampling_heap_profiler/sampling_heap_profiler.cc @@ -166,18 +166,9 @@ uint32_t SamplingHeapProfiler::Start() { } unwinder_.store(unwinder); - auto* poisson_allocation_sampler = PoissonAllocationSampler::Get(); - - // Sampling interval is in bytes. Record it in KB since the extra precision - // isn't needed for metrics and HeapProfilerController can set the interval to - // center around 10M bytes, which would overflow the buckets. - base::UmaHistogramCounts10M( - "HeapProfiling.SamplingIntervalKB", - static_cast(poisson_allocation_sampler->SamplingInterval() / 1024)); - AutoLock lock(start_stop_mutex_); if (!running_sessions_++) - poisson_allocation_sampler->AddSamplesObserver(this); + PoissonAllocationSampler::Get()->AddSamplesObserver(this); return last_sample_ordinal_; } diff --git a/naiveproxy/src/base/scoped_add_feature_flags.cc b/naiveproxy/src/base/scoped_add_feature_flags.cc index ee4900adb5..5d83d51ebf 100644 --- a/naiveproxy/src/base/scoped_add_feature_flags.cc +++ b/naiveproxy/src/base/scoped_add_feature_flags.cc @@ -4,6 +4,8 @@ #include "base/scoped_add_feature_flags.h" +#include + #include "base/base_switches.h" #include "base/command_line.h" #include "base/containers/contains.h" @@ -18,11 +20,11 @@ ScopedAddFeatureFlags::ScopedAddFeatureFlags(CommandLine* command_line) command_line->GetSwitchValueASCII(switches::kEnableFeatures); std::string disabled_features = command_line->GetSwitchValueASCII(switches::kDisableFeatures); - for (const StringPiece& feature : + for (std::string_view feature : FeatureList::SplitFeatureListString(enabled_features)) { enabled_features_.emplace_back(feature); } - for (const StringPiece& feature : + for (std::string_view feature : FeatureList::SplitFeatureListString(disabled_features)) { disabled_features_.emplace_back(feature); } @@ -41,9 +43,10 @@ void ScopedAddFeatureFlags::EnableIfNotSet(const Feature& feature) { AddFeatureIfNotSet(feature, /*suffix=*/"", /*enable=*/true); } -void ScopedAddFeatureFlags::EnableIfNotSetWithParameter(const Feature& feature, - StringPiece name, - StringPiece value) { +void ScopedAddFeatureFlags::EnableIfNotSetWithParameter( + const Feature& feature, + std::string_view name, + std::string_view value) { std::string suffix = StrCat({":", name, "/", value}); AddFeatureIfNotSet(feature, suffix, true /* enable */); } @@ -59,8 +62,8 @@ bool ScopedAddFeatureFlags::IsEnabled(const Feature& feature) { bool ScopedAddFeatureFlags::IsEnabledWithParameter( const Feature& feature, - StringPiece parameter_name, - StringPiece parameter_value) { + std::string_view parameter_name, + std::string_view parameter_value) { std::string feature_name = feature.name; if (!parameter_name.empty()) { StrAppend(&feature_name, {":", parameter_name, "/", parameter_value}); @@ -73,7 +76,7 @@ bool ScopedAddFeatureFlags::IsEnabledWithParameter( } void ScopedAddFeatureFlags::AddFeatureIfNotSet(const Feature& feature, - StringPiece suffix, + std::string_view suffix, bool enable) { std::string feature_name = StrCat({feature.name, suffix}); if (Contains(enabled_features_, feature_name) || diff --git a/naiveproxy/src/base/scoped_add_feature_flags.h b/naiveproxy/src/base/scoped_add_feature_flags.h index fea3d21139..9bb19e8d33 100644 --- a/naiveproxy/src/base/scoped_add_feature_flags.h +++ b/naiveproxy/src/base/scoped_add_feature_flags.h @@ -6,6 +6,7 @@ #define BASE_SCOPED_ADD_FEATURE_FLAGS_H_ #include +#include #include #include "base/base_export.h" @@ -34,8 +35,8 @@ class BASE_EXPORT ScopedAddFeatureFlags { void EnableIfNotSet(const Feature& feature); void DisableIfNotSet(const Feature& feature); void EnableIfNotSetWithParameter(const Feature& feature, - StringPiece name, - StringPiece value); + std::string_view name, + std::string_view value); // Check if the feature is enabled from command line or functions above bool IsEnabled(const Feature& feature); @@ -44,12 +45,12 @@ class BASE_EXPORT ScopedAddFeatureFlags { // from command line or functions above. An empty parameter name means that we // are checking if the feature is enabled without any parameter. bool IsEnabledWithParameter(const Feature& feature, - StringPiece parameter_name, - StringPiece parameter_value); + std::string_view parameter_name, + std::string_view parameter_value); private: void AddFeatureIfNotSet(const Feature& feature, - StringPiece suffix, + std::string_view suffix, bool enable); const raw_ptr command_line_; diff --git a/naiveproxy/src/base/sequence_checker.h b/naiveproxy/src/base/sequence_checker.h index 70f1017ec6..406854e12f 100644 --- a/naiveproxy/src/base/sequence_checker.h +++ b/naiveproxy/src/base/sequence_checker.h @@ -13,8 +13,9 @@ // SequenceChecker verifies mutual exclusion between calls to its // `CalledOnValidSequence()` method. Mutual exclusion is guaranteed if all calls // are made from the same thread, from the same sequence (see -// `SequencedTaskRunner`) or under the same lock. SequenceChecker supports -// thread safety annotations (see base/thread_annotations.h). +// `SequencedTaskRunner`) or under the same lock acquired with +// `base::subtle::LockTracking::kEnabled`. SequenceChecker supports thread +// safety annotations (see base/thread_annotations.h). // // Use the macros below instead of the SequenceChecker directly so that the // unused member doesn't result in an extra byte (four when padded) per instance diff --git a/naiveproxy/src/base/sequence_checker_impl.cc b/naiveproxy/src/base/sequence_checker_impl.cc index e2a4c6f097..bd2530a9e2 100644 --- a/naiveproxy/src/base/sequence_checker_impl.cc +++ b/naiveproxy/src/base/sequence_checker_impl.cc @@ -97,7 +97,7 @@ bool SequenceCheckerImpl::CalledOnValidSequence( // Valid if holding a bound lock. if (!is_valid) { #if DCHECK_IS_ON() - for (uintptr_t lock : subtle::GetLocksHeldByCurrentThread()) { + for (uintptr_t lock : subtle::GetTrackedLocksHeldByCurrentThread()) { if (Contains(locks_, lock)) { is_valid = true; break; @@ -150,7 +150,7 @@ bool SequenceCheckerImpl::CalledOnValidSequence( // `locks_` must contain locks held at binding time and for all calls to // `CalledOnValidSequence` that returned true afterwards. std::erase_if(locks_, [](uintptr_t lock_ptr) { - return !Contains(subtle::GetLocksHeldByCurrentThread(), lock_ptr); + return !Contains(subtle::GetTrackedLocksHeldByCurrentThread(), lock_ptr); }); #endif // DCHECK_IS_ON() @@ -191,7 +191,7 @@ void SequenceCheckerImpl::EnsureAssigned() const { // detail of `SequenceCheckerImpl` and doesn't provide mutual exclusion // guarantees to the caller). DCHECK(locks_.empty()); - ranges::remove_copy(subtle::GetLocksHeldByCurrentThread(), + ranges::remove_copy(subtle::GetTrackedLocksHeldByCurrentThread(), std::back_inserter(locks_), reinterpret_cast(&lock_)); #endif // DCHECK_IS_ON() diff --git a/naiveproxy/src/base/strings/abseil_string_number_conversions.cc b/naiveproxy/src/base/strings/abseil_string_number_conversions.cc index 2ad938a6c6..e23a6d5a0d 100644 --- a/naiveproxy/src/base/strings/abseil_string_number_conversions.cc +++ b/naiveproxy/src/base/strings/abseil_string_number_conversions.cc @@ -4,17 +4,18 @@ #include "base/strings/abseil_string_number_conversions.h" +#include + #include "base/strings/string_number_conversions_internal.h" -#include "base/strings/string_piece.h" #include "third_party/abseil-cpp/absl/numeric/int128.h" namespace base { -bool StringToUint128(StringPiece input, absl::uint128* output) { +bool StringToUint128(std::string_view input, absl::uint128* output) { return internal::StringToIntImpl(input, *output); } -bool HexStringToUInt128(StringPiece input, absl::uint128* output) { +bool HexStringToUInt128(std::string_view input, absl::uint128* output) { return internal::HexStringToIntImpl(input, *output); } diff --git a/naiveproxy/src/base/strings/abseil_string_number_conversions.h b/naiveproxy/src/base/strings/abseil_string_number_conversions.h index 00b0f4e10a..5a4301fe3c 100644 --- a/naiveproxy/src/base/strings/abseil_string_number_conversions.h +++ b/naiveproxy/src/base/strings/abseil_string_number_conversions.h @@ -5,20 +5,22 @@ #ifndef BASE_STRINGS_ABSEIL_STRING_NUMBER_CONVERSIONS_H_ #define BASE_STRINGS_ABSEIL_STRING_NUMBER_CONVERSIONS_H_ +#include + #include "base/base_export.h" -#include "base/strings/string_piece.h" #include "third_party/abseil-cpp/absl/numeric/int128.h" namespace base { // Best effort conversion, see `base::StringToInt()` for restrictions. // Will only successfully parse values that will fit into `output`. -BASE_EXPORT bool StringToUint128(StringPiece input, absl::uint128* output); +BASE_EXPORT bool StringToUint128(std::string_view input, absl::uint128* output); // Best effort conversion, see `base::StringToInt()` for restrictions. // Will only successfully parse hex values that will fit into `output`. // The string is not required to start with 0x. -BASE_EXPORT bool HexStringToUInt128(StringPiece input, absl::uint128* output); +BASE_EXPORT bool HexStringToUInt128(std::string_view input, + absl::uint128* output); } // namespace base diff --git a/naiveproxy/src/base/strings/cstring_view.h b/naiveproxy/src/base/strings/cstring_view.h index 21962af040..6fffd7bcf8 100644 --- a/naiveproxy/src/base/strings/cstring_view.h +++ b/naiveproxy/src/base/strings/cstring_view.h @@ -69,11 +69,19 @@ class basic_cstring_view final { // auto s2 = base::cstring_view("this works too"); // CHECK(s == "this works too"); // ``` + // + // The string will end at the first NUL character in the given array. + // + // Example: + // ``` + // auto s = base::cstring_view("hello\0world"); + // CHECK(s == "hello"); + // ``` template // NOLINTNEXTLINE(google-explicit-constructor) constexpr basic_cstring_view(const Char (&lit LIFETIME_BOUND)[M]) noexcept ENABLE_IF_ATTR(lit[M - 1u] == Char{0}, "requires string literal as input") - : ptr_(lit), len_(M - 1u) { + : ptr_(lit), len_(std::char_traits::length(lit)) { // For non-clang compilers. On clang, the function is not even callable // without this being known to pass at compile time. // diff --git a/naiveproxy/src/base/strings/escape.cc b/naiveproxy/src/base/strings/escape.cc index c131d5762a..6f3af5df8f 100644 --- a/naiveproxy/src/base/strings/escape.cc +++ b/naiveproxy/src/base/strings/escape.cc @@ -10,12 +10,10 @@ #include "base/strings/escape.h" #include +#include #include "base/check_op.h" -#include "base/feature_list.h" -#include "base/features.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversion_utils.h" #include "base/strings/utf_string_conversions.h" @@ -42,7 +40,7 @@ struct Charmap { // to +, otherwise, if spaces are in the charmap, they are converted to // %20. And if keep_escaped is true, %XX will be kept as it is, otherwise, if // '%' is in the charmap, it is converted to %25. -std::string Escape(StringPiece text, +std::string Escape(std::string_view text, const Charmap& charmap, bool use_plus, bool keep_escaped = false) { @@ -70,7 +68,7 @@ template void AppendEscapedCharForHTMLImpl(typename str::value_type c, str* output) { static constexpr struct { char key; - StringPiece replacement; + std::string_view replacement; } kCharsToEscape[] = { {'<', "<"}, {'>', ">"}, {'&', "&"}, {'"', """}, {'\'', "'"}, @@ -186,7 +184,7 @@ const char kUrlUnescape[128] = { // Attempts to unescape the sequence at |index| within |escaped_text|. If // successful, sets |value| to the unescaped value. Returns whether // unescaping succeeded. -bool UnescapeUnsignedByteAtIndex(StringPiece escaped_text, +bool UnescapeUnsignedByteAtIndex(std::string_view escaped_text, size_t index, unsigned char* value) { if ((index + 2) >= escaped_text.size()) @@ -208,7 +206,7 @@ bool UnescapeUnsignedByteAtIndex(StringPiece escaped_text, // the character's code point and |unescaped_out| to be the unescaped UTF-8 // string. |unescaped_out| will always be 1/3rd the length of the substring of // |escaped_text| that corresponds to the unescaped character. -bool UnescapeUTF8CharacterAtIndex(StringPiece escaped_text, +bool UnescapeUTF8CharacterAtIndex(std::string_view escaped_text, size_t index, base_icu::UChar32* code_point_out, std::string* unescaped_out) { @@ -387,7 +385,7 @@ bool ShouldUnescapeCodePoint(UnescapeRule::Type rules, // character. The resulting |adjustments| will always be sorted by increasing // offset. std::string UnescapeURLWithAdjustmentsImpl( - StringPiece escaped_text, + std::string_view escaped_text, UnescapeRule::Type rules, OffsetAdjuster::Adjustments* adjustments) { if (adjustments) @@ -461,37 +459,37 @@ std::string UnescapeURLWithAdjustmentsImpl( } // namespace -std::string EscapeAllExceptUnreserved(StringPiece text) { +std::string EscapeAllExceptUnreserved(std::string_view text) { return Escape(text, kUnreservedCharmap, false); } -std::string EscapeQueryParamValue(StringPiece text, bool use_plus) { +std::string EscapeQueryParamValue(std::string_view text, bool use_plus) { return Escape(text, kQueryCharmap, use_plus); } -std::string EscapePath(StringPiece path) { +std::string EscapePath(std::string_view path) { return Escape(path, kPathCharmap, false); } #if BUILDFLAG(IS_APPLE) -std::string EscapeNSURLPrecursor(StringPiece precursor) { +std::string EscapeNSURLPrecursor(std::string_view precursor) { return Escape(precursor, kNSURLCharmap, false, true); } #endif // BUILDFLAG(IS_APPLE) -std::string EscapeUrlEncodedData(StringPiece path, bool use_plus) { +std::string EscapeUrlEncodedData(std::string_view path, bool use_plus) { return Escape(path, kUrlEscape, use_plus); } -std::string EscapeNonASCIIAndPercent(StringPiece input) { +std::string EscapeNonASCIIAndPercent(std::string_view input) { return Escape(input, kNonASCIICharmapAndPercent, false); } -std::string EscapeNonASCII(StringPiece input) { +std::string EscapeNonASCII(std::string_view input) { return Escape(input, kNonASCIICharmap, false); } -std::string EscapeExternalHandlerValue(StringPiece text) { +std::string EscapeExternalHandlerValue(std::string_view text) { return Escape(text, kExternalHandlerCharmap, false, true); } @@ -499,21 +497,21 @@ void AppendEscapedCharForHTML(char c, std::string* output) { AppendEscapedCharForHTMLImpl(c, output); } -std::string EscapeForHTML(StringPiece input) { +std::string EscapeForHTML(std::string_view input) { return EscapeForHTMLImpl(input); } -std::u16string EscapeForHTML(StringPiece16 input) { +std::u16string EscapeForHTML(std::u16string_view input) { return EscapeForHTMLImpl(input); } -std::string UnescapeURLComponent(StringPiece escaped_text, +std::string UnescapeURLComponent(std::string_view escaped_text, UnescapeRule::Type rules) { return UnescapeURLWithAdjustmentsImpl(escaped_text, rules, nullptr); } std::u16string UnescapeAndDecodeUTF8URLComponentWithAdjustments( - StringPiece text, + std::string_view text, UnescapeRule::Type rules, OffsetAdjuster::Adjustments* adjustments) { std::u16string result; @@ -533,28 +531,16 @@ std::u16string UnescapeAndDecodeUTF8URLComponentWithAdjustments( return UTF8ToUTF16WithAdjustments(text, adjustments); } -std::string UnescapeBinaryURLComponent(StringPiece escaped_text, +std::string UnescapeBinaryURLComponent(std::string_view escaped_text, UnescapeRule::Type rules) { // Only NORMAL and REPLACE_PLUS_WITH_SPACE are supported. DCHECK(rules != UnescapeRule::NONE); DCHECK(!(rules & ~(UnescapeRule::NORMAL | UnescapeRule::REPLACE_PLUS_WITH_SPACE))); - // It is not possible to read the feature state when this function is invoked - // before FeatureList initialization. In that case, fallback to the feature's - // default state. - // - // TODO(crbug.com/40224104): Cleanup this feature. - const bool optimize_data_urls_feature_is_enabled = - base::FeatureList::GetInstance() - ? base::FeatureList::IsEnabled(features::kOptimizeDataUrls) - : features::kOptimizeDataUrls.default_state == - base::FEATURE_ENABLED_BY_DEFAULT; - // If there are no '%' characters in the string, there will be nothing to // unescape, so we can take the fast path. - if (optimize_data_urls_feature_is_enabled && - escaped_text.find('%') == StringPiece::npos) { + if (escaped_text.find('%') == std::string_view::npos) { std::string unescaped_text(escaped_text); if (rules & UnescapeRule::REPLACE_PLUS_WITH_SPACE) std::replace(unescaped_text.begin(), unescaped_text.end(), '+', ' '); @@ -598,7 +584,7 @@ std::string UnescapeBinaryURLComponent(StringPiece escaped_text, return unescaped_text; } -bool UnescapeBinaryURLComponentSafe(StringPiece escaped_text, +bool UnescapeBinaryURLComponentSafe(std::string_view escaped_text, bool fail_on_path_separators, std::string* unescaped_text) { unescaped_text->clear(); @@ -618,7 +604,7 @@ bool UnescapeBinaryURLComponentSafe(StringPiece escaped_text, return true; } -bool ContainsEncodedBytes(StringPiece escaped_text, +bool ContainsEncodedBytes(std::string_view escaped_text, const std::set& bytes) { for (size_t i = 0, max = escaped_text.size(); i < max;) { unsigned char byte; @@ -638,7 +624,7 @@ bool ContainsEncodedBytes(StringPiece escaped_text, return false; } -std::u16string UnescapeForHTML(StringPiece16 input) { +std::u16string UnescapeForHTML(std::u16string_view input) { static const struct { const char* ampersand_code; const char16_t replacement; diff --git a/naiveproxy/src/base/strings/escape.h b/naiveproxy/src/base/strings/escape.h index fd0479aed0..8ce6229cac 100644 --- a/naiveproxy/src/base/strings/escape.h +++ b/naiveproxy/src/base/strings/escape.h @@ -9,9 +9,9 @@ #include #include +#include #include "base/base_export.h" -#include "base/strings/string_piece.h" #include "base/strings/utf_offset_string_conversions.h" #include "build/build_config.h" @@ -21,51 +21,53 @@ namespace base { // Escapes all characters except unreserved characters. Unreserved characters, // as defined in RFC 3986, include alphanumerics and -._~ -BASE_EXPORT std::string EscapeAllExceptUnreserved(StringPiece text); +BASE_EXPORT std::string EscapeAllExceptUnreserved(std::string_view text); // Escapes characters in text suitable for use as a query parameter value. // We %XX everything except alphanumerics and -_.!~*'() // Spaces change to "+" unless you pass usePlus=false. // This is basically the same as encodeURIComponent in javascript. -BASE_EXPORT std::string EscapeQueryParamValue(StringPiece text, bool use_plus); +BASE_EXPORT std::string EscapeQueryParamValue(std::string_view text, + bool use_plus); // Escapes a partial or complete file/pathname. This includes: // non-printable, non-7bit, and (including space) "#%:<>?[\]^`{|} -BASE_EXPORT std::string EscapePath(StringPiece path); +BASE_EXPORT std::string EscapePath(std::string_view path); #if BUILDFLAG(IS_APPLE) // Escapes characters as per expectations of NSURL. This includes: // non-printable, non-7bit, and (including space) "#%<>[\]^`{|} -BASE_EXPORT std::string EscapeNSURLPrecursor(StringPiece precursor); +BASE_EXPORT std::string EscapeNSURLPrecursor(std::string_view precursor); #endif // BUILDFLAG(IS_APPLE) // Escapes application/x-www-form-urlencoded content. This includes: // non-printable, non-7bit, and (including space) ?>=<;+'&%$#"![\]^`{|} // Space is escaped as + (if use_plus is true) and other special characters // as %XX (hex). -BASE_EXPORT std::string EscapeUrlEncodedData(StringPiece path, bool use_plus); +BASE_EXPORT std::string EscapeUrlEncodedData(std::string_view path, + bool use_plus); // Escapes all non-ASCII input, as well as escaping % to %25. -BASE_EXPORT std::string EscapeNonASCIIAndPercent(StringPiece input); +BASE_EXPORT std::string EscapeNonASCIIAndPercent(std::string_view input); // Escapes all non-ASCII input. Note this function leaves % unescaped, which // means the unescaping the resulting string will not give back the original // input. -BASE_EXPORT std::string EscapeNonASCII(StringPiece input); +BASE_EXPORT std::string EscapeNonASCII(std::string_view input); // Escapes characters in text suitable for use as an external protocol handler // command. // We %XX everything except alphanumerics and -_.!~*'() and the restricted // characters (;/?:@&=+$,#[]) and a valid percent escape sequence (%XX). -BASE_EXPORT std::string EscapeExternalHandlerValue(StringPiece text); +BASE_EXPORT std::string EscapeExternalHandlerValue(std::string_view text); // Appends the given character to the output string, escaping the character if // the character would be interpreted as an HTML delimiter. BASE_EXPORT void AppendEscapedCharForHTML(char c, std::string* output); // Escapes chars that might cause this text to be interpreted as HTML tags. -BASE_EXPORT std::string EscapeForHTML(StringPiece text); -BASE_EXPORT std::u16string EscapeForHTML(StringPiece16 text); +BASE_EXPORT std::string EscapeForHTML(std::string_view text); +BASE_EXPORT std::u16string EscapeForHTML(std::u16string_view text); // Unescaping ------------------------------------------------------------------ @@ -122,7 +124,7 @@ class UnescapeRule { // UTF-8, they could be used to mislead the user. Callers that want to // unconditionally unescape everything for uses other than displaying data to // the user should use UnescapeBinaryURLComponent(). -BASE_EXPORT std::string UnescapeURLComponent(StringPiece escaped_text, +BASE_EXPORT std::string UnescapeURLComponent(std::string_view escaped_text, UnescapeRule::Type rules); // Unescapes the given substring as a URL, and then tries to interpret the @@ -132,7 +134,7 @@ BASE_EXPORT std::string UnescapeURLComponent(StringPiece escaped_text, // information on how the original string was adjusted to get the string // returned. BASE_EXPORT std::u16string UnescapeAndDecodeUTF8URLComponentWithAdjustments( - StringPiece text, + std::string_view text, UnescapeRule::Type rules, OffsetAdjuster::Adjustments* adjustments); @@ -143,7 +145,7 @@ BASE_EXPORT std::u16string UnescapeAndDecodeUTF8URLComponentWithAdjustments( // // Only the NORMAL and REPLACE_PLUS_WITH_SPACE rules are allowed. BASE_EXPORT std::string UnescapeBinaryURLComponent( - StringPiece escaped_text, + std::string_view escaped_text, UnescapeRule::Type rules = UnescapeRule::NORMAL); // Variant of UnescapeBinaryURLComponent(). Writes output to |unescaped_text|. @@ -153,7 +155,7 @@ BASE_EXPORT std::string UnescapeBinaryURLComponent( // CRLF but not space), and optionally path separators. Path separators include // both forward and backward slashes on all platforms. Does not fail if any of // those characters appear unescaped in the input string. -BASE_EXPORT bool UnescapeBinaryURLComponentSafe(StringPiece escaped_text, +BASE_EXPORT bool UnescapeBinaryURLComponentSafe(std::string_view escaped_text, bool fail_on_path_separators, std::string* unescaped_text); @@ -163,12 +165,12 @@ BASE_EXPORT bool UnescapeBinaryURLComponentSafe(StringPiece escaped_text, // For example, if |bytes| is {'%', '/'}, returns true if |escaped_text| // contains "%25" or "%2F", but not if it just contains bare '%' or '/' // characters. -BASE_EXPORT bool ContainsEncodedBytes(StringPiece escaped_text, +BASE_EXPORT bool ContainsEncodedBytes(std::string_view escaped_text, const std::set& bytes); // Unescapes the following ampersand character codes from |text|: // < > & " ' -BASE_EXPORT std::u16string UnescapeForHTML(StringPiece16 text); +BASE_EXPORT std::u16string UnescapeForHTML(std::u16string_view text); } // namespace base diff --git a/naiveproxy/src/base/strings/pattern.cc b/naiveproxy/src/base/strings/pattern.cc index ffa9e01b62..78ec382826 100644 --- a/naiveproxy/src/base/strings/pattern.cc +++ b/naiveproxy/src/base/strings/pattern.cc @@ -9,6 +9,8 @@ #include "base/strings/pattern.h" +#include + #include "base/third_party/icu/icu_utf.h" namespace base { @@ -147,12 +149,12 @@ struct NextCharUTF16 { } // namespace -bool MatchPattern(StringPiece eval, StringPiece pattern) { +bool MatchPattern(std::string_view eval, std::string_view pattern) { return MatchPatternT(eval.data(), eval.data() + eval.size(), pattern.data(), pattern.data() + pattern.size(), NextCharUTF8()); } -bool MatchPattern(StringPiece16 eval, StringPiece16 pattern) { +bool MatchPattern(std::u16string_view eval, std::u16string_view pattern) { return MatchPatternT(eval.data(), eval.data() + eval.size(), pattern.data(), pattern.data() + pattern.size(), NextCharUTF16()); } diff --git a/naiveproxy/src/base/strings/pattern.h b/naiveproxy/src/base/strings/pattern.h index 472f5f6e12..87aa430d2a 100644 --- a/naiveproxy/src/base/strings/pattern.h +++ b/naiveproxy/src/base/strings/pattern.h @@ -5,8 +5,9 @@ #ifndef BASE_STRINGS_PATTERN_H_ #define BASE_STRINGS_PATTERN_H_ +#include + #include "base/base_export.h" -#include "base/strings/string_piece.h" namespace base { @@ -15,8 +16,10 @@ namespace base { // // The backslash character (\) is an escape character for * and ?. // ? matches 0 or 1 character, while * matches 0 or more characters. -BASE_EXPORT bool MatchPattern(StringPiece string, StringPiece pattern); -BASE_EXPORT bool MatchPattern(StringPiece16 string, StringPiece16 pattern); +BASE_EXPORT bool MatchPattern(std::string_view string, + std::string_view pattern); +BASE_EXPORT bool MatchPattern(std::u16string_view string, + std::u16string_view pattern); } // namespace base diff --git a/naiveproxy/src/base/strings/strcat.cc b/naiveproxy/src/base/strings/strcat.cc index f5e90ea206..354ef23cc4 100644 --- a/naiveproxy/src/base/strings/strcat.cc +++ b/naiveproxy/src/base/strings/strcat.cc @@ -5,16 +5,17 @@ #include "base/strings/strcat.h" #include +#include #include "base/strings/strcat_internal.h" namespace base { -std::string StrCat(span pieces) { +std::string StrCat(span pieces) { return internal::StrCatT(pieces); } -std::u16string StrCat(span pieces) { +std::u16string StrCat(span pieces) { return internal::StrCatT(pieces); } @@ -26,11 +27,11 @@ std::u16string StrCat(span pieces) { return internal::StrCatT(pieces); } -void StrAppend(std::string* dest, span pieces) { +void StrAppend(std::string* dest, span pieces) { internal::StrAppendT(*dest, pieces); } -void StrAppend(std::u16string* dest, span pieces) { +void StrAppend(std::u16string* dest, span pieces) { internal::StrAppendT(*dest, pieces); } diff --git a/naiveproxy/src/base/strings/strcat.h b/naiveproxy/src/base/strings/strcat.h index 5d150c0fc7..b2a765687e 100644 --- a/naiveproxy/src/base/strings/strcat.h +++ b/naiveproxy/src/base/strings/strcat.h @@ -6,10 +6,10 @@ #define BASE_STRINGS_STRCAT_H_ #include +#include #include "base/base_export.h" #include "base/containers/span.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" #if BUILDFLAG(IS_WIN) @@ -36,7 +36,7 @@ namespace base { // StrCat can see all arguments at once, so it can allocate one return buffer // of exactly the right size and copy once, as opposed to a sequence of // operator+ which generates a series of temporary strings, copying as it goes. -// And by using StringPiece arguments, StrCat can avoid creating temporary +// And by using std::string_view arguments, StrCat can avoid creating temporary // string objects for char* constants. // // ALTERNATIVES @@ -53,24 +53,26 @@ namespace base { // and the call sites look nice. // // As-written Abseil's helper class for numbers generates slightly more code -// than the raw StringPiece version. We can de-inline the helper class' -// constructors which will cause the StringPiece constructors to be de-inlined -// for this call and generate slightly less code. This is something we can -// explore more in the future. +// than the raw std::string_view version. We can de-inline the helper class' +// constructors which will cause the std::string_view constructors to be +// de-inlined for this call and generate slightly less code. This is something +// we can explore more in the future. -[[nodiscard]] BASE_EXPORT std::string StrCat(span pieces); +[[nodiscard]] BASE_EXPORT std::string StrCat( + span pieces); [[nodiscard]] BASE_EXPORT std::u16string StrCat( - span pieces); + span pieces); [[nodiscard]] BASE_EXPORT std::string StrCat(span pieces); [[nodiscard]] BASE_EXPORT std::u16string StrCat( span pieces); // Initializer list forwards to the array version. -inline std::string StrCat(std::initializer_list pieces) { +inline std::string StrCat(std::initializer_list pieces) { return StrCat(make_span(pieces)); } -inline std::u16string StrCat(std::initializer_list pieces) { +inline std::u16string StrCat( + std::initializer_list pieces) { return StrCat(make_span(pieces)); } @@ -82,21 +84,22 @@ inline std::u16string StrCat(std::initializer_list pieces) { // foo += StrCat(...); // because it avoids a temporary string allocation and copy. -BASE_EXPORT void StrAppend(std::string* dest, span pieces); +BASE_EXPORT void StrAppend(std::string* dest, + span pieces); BASE_EXPORT void StrAppend(std::u16string* dest, - span pieces); + span pieces); BASE_EXPORT void StrAppend(std::string* dest, span pieces); BASE_EXPORT void StrAppend(std::u16string* dest, span pieces); // Initializer list forwards to the array version. inline void StrAppend(std::string* dest, - std::initializer_list pieces) { + std::initializer_list pieces) { StrAppend(dest, make_span(pieces)); } inline void StrAppend(std::u16string* dest, - std::initializer_list pieces) { + std::initializer_list pieces) { StrAppend(dest, make_span(pieces)); } diff --git a/naiveproxy/src/base/strings/strcat_internal.h b/naiveproxy/src/base/strings/strcat_internal.h index 0cd3b12ef9..d8c141403c 100644 --- a/naiveproxy/src/base/strings/strcat_internal.h +++ b/naiveproxy/src/base/strings/strcat_internal.h @@ -10,10 +10,10 @@ #ifndef BASE_STRINGS_STRCAT_INTERNAL_H_ #define BASE_STRINGS_STRCAT_INTERNAL_H_ +#include #include #include "base/containers/span.h" -#include "base/template_util.h" namespace base { @@ -25,15 +25,17 @@ namespace internal { // initialized afterwards. Currently proposed for standardization as // std::basic_string::resize_and_overwrite: https://wg21.link/P1072R6 template -auto Resize(std::basic_string& str, size_t total_size, priority_tag<1>) - -> decltype(str.__resize_default_init(total_size)) { + requires requires(std::basic_string& str, size_t total_size) { + { str.__resize_default_init(total_size) } -> std::same_as; + } +auto Resize(std::basic_string& str, size_t total_size) { str.__resize_default_init(total_size); } // Fallback to regular std::basic_string::resize() if invoking // __resize_default_init is ill-formed. template -void Resize(std::basic_string& str, size_t total_size, priority_tag<0>) { +void Resize(std::basic_string& str, size_t total_size) { str.resize(total_size); } @@ -59,7 +61,7 @@ void StrAppendT(std::basic_string& dest, span pieces) { // added characters. Since this codepath is also triggered by `resize()`, we // don't have to manage the std::string's capacity ourselves here to avoid // performance hits in case `StrAppend()` gets called in a loop. - Resize(dest, total_size, priority_tag<1>()); + Resize(dest, total_size); CharT* dest_char = &dest[initial_size]; for (const auto& cur : pieces) { std::char_traits::copy(dest_char, cur.data(), cur.size()); diff --git a/naiveproxy/src/base/strings/string_number_conversions.cc b/naiveproxy/src/base/strings/string_number_conversions.cc index 225b01bea7..9abca17ec9 100644 --- a/naiveproxy/src/base/strings/string_number_conversions.cc +++ b/naiveproxy/src/base/strings/string_number_conversions.cc @@ -6,11 +6,11 @@ #include #include +#include #include "base/containers/span.h" #include "base/logging.h" #include "base/strings/string_number_conversions_internal.h" -#include "base/strings/string_piece.h" namespace base { @@ -70,51 +70,51 @@ std::u16string NumberToString16(double value) { return internal::DoubleToStringT(value); } -bool StringToInt(StringPiece input, int* output) { +bool StringToInt(std::string_view input, int* output) { return internal::StringToIntImpl(input, *output); } -bool StringToInt(StringPiece16 input, int* output) { +bool StringToInt(std::u16string_view input, int* output) { return internal::StringToIntImpl(input, *output); } -bool StringToUint(StringPiece input, unsigned* output) { +bool StringToUint(std::string_view input, unsigned* output) { return internal::StringToIntImpl(input, *output); } -bool StringToUint(StringPiece16 input, unsigned* output) { +bool StringToUint(std::u16string_view input, unsigned* output) { return internal::StringToIntImpl(input, *output); } -bool StringToInt64(StringPiece input, int64_t* output) { +bool StringToInt64(std::string_view input, int64_t* output) { return internal::StringToIntImpl(input, *output); } -bool StringToInt64(StringPiece16 input, int64_t* output) { +bool StringToInt64(std::u16string_view input, int64_t* output) { return internal::StringToIntImpl(input, *output); } -bool StringToUint64(StringPiece input, uint64_t* output) { +bool StringToUint64(std::string_view input, uint64_t* output) { return internal::StringToIntImpl(input, *output); } -bool StringToUint64(StringPiece16 input, uint64_t* output) { +bool StringToUint64(std::u16string_view input, uint64_t* output) { return internal::StringToIntImpl(input, *output); } -bool StringToSizeT(StringPiece input, size_t* output) { +bool StringToSizeT(std::string_view input, size_t* output) { return internal::StringToIntImpl(input, *output); } -bool StringToSizeT(StringPiece16 input, size_t* output) { +bool StringToSizeT(std::u16string_view input, size_t* output) { return internal::StringToIntImpl(input, *output); } -bool StringToDouble(StringPiece input, double* output) { +bool StringToDouble(std::string_view input, double* output) { return internal::StringToDoubleImpl(input, input.data(), *output); } -bool StringToDouble(StringPiece16 input, double* output) { +bool StringToDouble(std::u16string_view input, double* output) { return internal::StringToDoubleImpl( input, reinterpret_cast(input.data()), *output); } @@ -137,39 +137,39 @@ std::string HexEncode(span bytes) { return ret; } -std::string HexEncode(StringPiece chars) { +std::string HexEncode(std::string_view chars) { return HexEncode(base::as_byte_span(chars)); } -bool HexStringToInt(StringPiece input, int* output) { +bool HexStringToInt(std::string_view input, int* output) { return internal::HexStringToIntImpl(input, *output); } -bool HexStringToUInt(StringPiece input, uint32_t* output) { +bool HexStringToUInt(std::string_view input, uint32_t* output) { return internal::HexStringToIntImpl(input, *output); } -bool HexStringToInt64(StringPiece input, int64_t* output) { +bool HexStringToInt64(std::string_view input, int64_t* output) { return internal::HexStringToIntImpl(input, *output); } -bool HexStringToUInt64(StringPiece input, uint64_t* output) { +bool HexStringToUInt64(std::string_view input, uint64_t* output) { return internal::HexStringToIntImpl(input, *output); } -bool HexStringToBytes(StringPiece input, std::vector* output) { +bool HexStringToBytes(std::string_view input, std::vector* output) { DCHECK(output->empty()); return internal::HexStringToByteContainer( input, std::back_inserter(*output)); } -bool HexStringToString(StringPiece input, std::string* output) { +bool HexStringToString(std::string_view input, std::string* output) { DCHECK(output->empty()); return internal::HexStringToByteContainer(input, std::back_inserter(*output)); } -bool HexStringToSpan(StringPiece input, span output) { +bool HexStringToSpan(std::string_view input, span output) { if (input.size() / 2 != output.size()) return false; diff --git a/naiveproxy/src/base/strings/string_number_conversions.h b/naiveproxy/src/base/strings/string_number_conversions.h index 20854c8c5c..9da1dc856a 100644 --- a/naiveproxy/src/base/strings/string_number_conversions.h +++ b/naiveproxy/src/base/strings/string_number_conversions.h @@ -14,11 +14,11 @@ #include #include +#include #include #include "base/base_export.h" #include "base/containers/span.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" // ---------------------------------------------------------------------------- @@ -75,20 +75,20 @@ BASE_EXPORT std::u16string NumberToString16(double value); // - Empty string. |*output| will be set to 0. // WARNING: Will write to |output| even when returning false. // Read the comments above carefully. -BASE_EXPORT bool StringToInt(StringPiece input, int* output); -BASE_EXPORT bool StringToInt(StringPiece16 input, int* output); +BASE_EXPORT bool StringToInt(std::string_view input, int* output); +BASE_EXPORT bool StringToInt(std::u16string_view input, int* output); -BASE_EXPORT bool StringToUint(StringPiece input, unsigned* output); -BASE_EXPORT bool StringToUint(StringPiece16 input, unsigned* output); +BASE_EXPORT bool StringToUint(std::string_view input, unsigned* output); +BASE_EXPORT bool StringToUint(std::u16string_view input, unsigned* output); -BASE_EXPORT bool StringToInt64(StringPiece input, int64_t* output); -BASE_EXPORT bool StringToInt64(StringPiece16 input, int64_t* output); +BASE_EXPORT bool StringToInt64(std::string_view input, int64_t* output); +BASE_EXPORT bool StringToInt64(std::u16string_view input, int64_t* output); -BASE_EXPORT bool StringToUint64(StringPiece input, uint64_t* output); -BASE_EXPORT bool StringToUint64(StringPiece16 input, uint64_t* output); +BASE_EXPORT bool StringToUint64(std::string_view input, uint64_t* output); +BASE_EXPORT bool StringToUint64(std::u16string_view input, uint64_t* output); -BASE_EXPORT bool StringToSizeT(StringPiece input, size_t* output); -BASE_EXPORT bool StringToSizeT(StringPiece16 input, size_t* output); +BASE_EXPORT bool StringToSizeT(std::string_view input, size_t* output); +BASE_EXPORT bool StringToSizeT(std::u16string_view input, size_t* output); // For floating-point conversions, only conversions of input strings in decimal // form are defined to work. Behavior with strings representing floating-point @@ -98,8 +98,8 @@ BASE_EXPORT bool StringToSizeT(StringPiece16 input, size_t* output); // If your input is locale specific, use ICU to read the number. // WARNING: Will write to |output| even when returning false. // Read the comments here and above StringToInt() carefully. -BASE_EXPORT bool StringToDouble(StringPiece input, double* output); -BASE_EXPORT bool StringToDouble(StringPiece16 input, double* output); +BASE_EXPORT bool StringToDouble(std::string_view input, double* output); +BASE_EXPORT bool StringToDouble(std::u16string_view input, double* output); // Hex encoding ---------------------------------------------------------------- @@ -110,7 +110,7 @@ BASE_EXPORT bool StringToDouble(StringPiece16 input, double* output); // max size for |size| should be is // std::numeric_limits::max() / 2 BASE_EXPORT std::string HexEncode(base::span bytes); -BASE_EXPORT std::string HexEncode(StringPiece chars); +BASE_EXPORT std::string HexEncode(std::string_view chars); // TODO(crbug.com/40284755): The pointer-based overload should be removed. BASE_EXPORT std::string HexEncode(const void* bytes, size_t size); @@ -133,34 +133,34 @@ inline void AppendHexEncodedByte(uint8_t byte, // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. // -0x80000000 < |input| < 0x7FFFFFFF. -BASE_EXPORT bool HexStringToInt(StringPiece input, int* output); +BASE_EXPORT bool HexStringToInt(std::string_view input, int* output); // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. // 0x00000000 < |input| < 0xFFFFFFFF. // The string is not required to start with 0x. -BASE_EXPORT bool HexStringToUInt(StringPiece input, uint32_t* output); +BASE_EXPORT bool HexStringToUInt(std::string_view input, uint32_t* output); // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. // -0x8000000000000000 < |input| < 0x7FFFFFFFFFFFFFFF. -BASE_EXPORT bool HexStringToInt64(StringPiece input, int64_t* output); +BASE_EXPORT bool HexStringToInt64(std::string_view input, int64_t* output); // Best effort conversion, see StringToInt above for restrictions. // Will only successful parse hex values that will fit into |output|, i.e. // 0x0000000000000000 < |input| < 0xFFFFFFFFFFFFFFFF. // The string is not required to start with 0x. -BASE_EXPORT bool HexStringToUInt64(StringPiece input, uint64_t* output); +BASE_EXPORT bool HexStringToUInt64(std::string_view input, uint64_t* output); // Similar to the previous functions, except that output is a vector of bytes. // |*output| will contain as many bytes as were successfully parsed prior to the // error. There is no overflow, but input.size() must be evenly divisible by 2. // Leading 0x or +/- are not allowed. -BASE_EXPORT bool HexStringToBytes(StringPiece input, +BASE_EXPORT bool HexStringToBytes(std::string_view input, std::vector* output); // Same as HexStringToBytes, but for an std::string. -BASE_EXPORT bool HexStringToString(StringPiece input, std::string* output); +BASE_EXPORT bool HexStringToString(std::string_view input, std::string* output); // Decodes the hex string |input| into a presized |output|. The output buffer // must be sized exactly to |input.size() / 2| or decoding will fail and no @@ -168,7 +168,8 @@ BASE_EXPORT bool HexStringToString(StringPiece input, std::string* output); // considered a failure. When decoding fails due to encountering invalid input // characters, |output| will have been filled with the decoded bytes up until // the failure. -BASE_EXPORT bool HexStringToSpan(StringPiece input, base::span output); +BASE_EXPORT bool HexStringToSpan(std::string_view input, + base::span output); } // namespace base diff --git a/naiveproxy/src/base/strings/string_number_conversions_internal.h b/naiveproxy/src/base/strings/string_number_conversions_internal.h index edf71f05ba..bdf17327a4 100644 --- a/naiveproxy/src/base/strings/string_number_conversions_internal.h +++ b/naiveproxy/src/base/strings/string_number_conversions_internal.h @@ -261,7 +261,7 @@ bool StringToDoubleImpl(STRING input, const CHAR* data, double& output) { } template -static bool HexStringToByteContainer(StringPiece input, OutIter output) { +static bool HexStringToByteContainer(std::string_view input, OutIter output) { size_t count = input.size(); if (count == 0 || (count % 2) != 0) return false; diff --git a/naiveproxy/src/base/strings/string_piece.h b/naiveproxy/src/base/strings/string_piece.h index dca7b39ddc..89e5e04ba7 100644 --- a/naiveproxy/src/base/strings/string_piece.h +++ b/naiveproxy/src/base/strings/string_piece.h @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// This header is deprecated. `base::StringPiece` is now `std::string_view`. -// Use it and instead. +// This header is deprecated. Use `std::string_view` and instead. // // TODO(crbug.com/40506050): Remove uses of this header. diff --git a/naiveproxy/src/base/strings/string_piece_nocompile.nc b/naiveproxy/src/base/strings/string_piece_nocompile.nc deleted file mode 100644 index 9c940f1810..0000000000 --- a/naiveproxy/src/base/strings/string_piece_nocompile.nc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a "No Compile Test" suite. -// http://dev.chromium.org/developers/testing/no-compile-tests - -#include "base/strings/string_piece.h" - -#include - -namespace base { - -// Returns a std::string xvalue (temporary object). -std::string f(); - - -void HoldsDanglingReferenceToString() { - [[maybe_unused]] StringPiece piece = f(); // expected-error {{object backing the pointer will be destroyed at the end of the full-expression}} -} - -} // namespace base diff --git a/naiveproxy/src/base/strings/string_piece_rust.h b/naiveproxy/src/base/strings/string_piece_rust.h index d2c1641be1..c0842595d3 100644 --- a/naiveproxy/src/base/strings/string_piece_rust.h +++ b/naiveproxy/src/base/strings/string_piece_rust.h @@ -7,8 +7,9 @@ #include +#include + #include "base/rust_buildflags.h" -#include "base/strings/string_piece.h" #include "third_party/rust/cxx/v1/cxx.h" #if !BUILDFLAG(BUILD_RUST_BASE_CONVERSIONS) @@ -21,21 +22,21 @@ namespace base { // if there is any invalid UTF8. If you're concerned about this, then // instead use StringPieceToRustSlice and convert the data to a string on // the Rust side (or pass in a std::string). -inline rust::Str StringPieceToRustStrUTF8(StringPiece string_piece) { +inline rust::Str StringPieceToRustStrUTF8(std::string_view string_piece) { return rust::Str(string_piece.data(), string_piece.size()); } -// Create a Rust slice from a StringPiece. No UTF8 check is performed. +// Create a Rust slice from a std::string_view. No UTF8 check is performed. inline rust::Slice StringPieceToRustSlice( - StringPiece string_piece) { + std::string_view string_piece) { return rust::Slice( reinterpret_cast(string_piece.data()), - string_piece.length() * sizeof(StringPiece::value_type)); + string_piece.length() * sizeof(std::string_view::value_type)); } -// Create a StringPiece from a Rust str. -inline StringPiece RustStrToStringPiece(rust::Str str) { - return StringPiece(str.data(), str.size()); +// Create a std::string_view from a Rust str. +inline std::string_view RustStrToStringPiece(rust::Str str) { + return std::string_view(str.data(), str.size()); } } // namespace base diff --git a/naiveproxy/src/base/strings/string_split.cc b/naiveproxy/src/base/strings/string_split.cc index 3f5125ea76..36238e57b7 100644 --- a/naiveproxy/src/base/strings/string_split.cc +++ b/naiveproxy/src/base/strings/string_split.cc @@ -6,6 +6,8 @@ #include +#include + #include "base/logging.h" #include "base/strings/string_split_internal.h" #include "base/strings/string_util.h" @@ -15,7 +17,7 @@ namespace base { namespace { -bool AppendStringKeyValue(StringPiece input, +bool AppendStringKeyValue(std::string_view input, char delimiter, StringPairs* result) { // Always append a new item regardless of success (it might be empty). The @@ -32,9 +34,10 @@ bool AppendStringKeyValue(StringPiece input, result_pair.first = std::string(input.substr(0, end_key_pos)); // Find the value string. - StringPiece remains = input.substr(end_key_pos, input.size() - end_key_pos); + std::string_view remains = + input.substr(end_key_pos, input.size() - end_key_pos); size_t begin_value_pos = remains.find_first_not_of(delimiter); - if (begin_value_pos == StringPiece::npos) { + if (begin_value_pos == std::string_view::npos) { DVLOG(1) << "cannot parse value from input: " << input; return false; // No value. } @@ -47,60 +50,61 @@ bool AppendStringKeyValue(StringPiece input, } // namespace -std::vector SplitString(StringPiece input, - StringPiece separators, +std::vector SplitString(std::string_view input, + std::string_view separators, WhitespaceHandling whitespace, SplitResult result_type) { return internal::SplitStringT(input, separators, whitespace, result_type); } -std::vector SplitString(StringPiece16 input, - StringPiece16 separators, +std::vector SplitString(std::u16string_view input, + std::u16string_view separators, WhitespaceHandling whitespace, SplitResult result_type) { return internal::SplitStringT(input, separators, whitespace, result_type); } -std::vector SplitStringPiece(StringPiece input, - StringPiece separators, - WhitespaceHandling whitespace, - SplitResult result_type) { - return internal::SplitStringT(input, separators, whitespace, - result_type); +std::vector SplitStringPiece(std::string_view input, + std::string_view separators, + WhitespaceHandling whitespace, + SplitResult result_type) { + return internal::SplitStringT(input, separators, whitespace, + result_type); } -std::vector SplitStringPiece(StringPiece16 input, - StringPiece16 separators, - WhitespaceHandling whitespace, - SplitResult result_type) { - return internal::SplitStringT(input, separators, whitespace, - result_type); +std::vector SplitStringPiece( + std::u16string_view input, + std::u16string_view separators, + WhitespaceHandling whitespace, + SplitResult result_type) { + return internal::SplitStringT(input, separators, + whitespace, result_type); } -bool SplitStringIntoKeyValuePairs(StringPiece input, +bool SplitStringIntoKeyValuePairs(std::string_view input, char key_value_delimiter, char key_value_pair_delimiter, StringPairs* key_value_pairs) { return SplitStringIntoKeyValuePairsUsingSubstr( - input, key_value_delimiter, StringPiece(&key_value_pair_delimiter, 1), - key_value_pairs); + input, key_value_delimiter, + std::string_view(&key_value_pair_delimiter, 1), key_value_pairs); } bool SplitStringIntoKeyValuePairsUsingSubstr( - StringPiece input, + std::string_view input, char key_value_delimiter, - StringPiece key_value_pair_delimiter, + std::string_view key_value_pair_delimiter, StringPairs* key_value_pairs) { key_value_pairs->clear(); - std::vector pairs = SplitStringPieceUsingSubstr( + std::vector pairs = SplitStringPieceUsingSubstr( input, key_value_pair_delimiter, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); key_value_pairs->reserve(pairs.size()); bool success = true; - for (const StringPiece& pair : pairs) { + for (std::string_view pair : pairs) { if (!AppendStringKeyValue(pair, key_value_delimiter, key_value_pairs)) { // Don't return here, to allow for pairs without associated // value or key; just record that the split failed. @@ -111,38 +115,38 @@ bool SplitStringIntoKeyValuePairsUsingSubstr( } std::vector SplitStringUsingSubstr( - StringPiece16 input, - StringPiece16 delimiter, + std::u16string_view input, + std::u16string_view delimiter, WhitespaceHandling whitespace, SplitResult result_type) { return internal::SplitStringUsingSubstrT( input, delimiter, whitespace, result_type); } -std::vector SplitStringUsingSubstr(StringPiece input, - StringPiece delimiter, +std::vector SplitStringUsingSubstr(std::string_view input, + std::string_view delimiter, WhitespaceHandling whitespace, SplitResult result_type) { return internal::SplitStringUsingSubstrT( input, delimiter, whitespace, result_type); } -std::vector SplitStringPieceUsingSubstr( - StringPiece16 input, - StringPiece16 delimiter, +std::vector SplitStringPieceUsingSubstr( + std::u16string_view input, + std::u16string_view delimiter, WhitespaceHandling whitespace, SplitResult result_type) { - std::vector result; - return internal::SplitStringUsingSubstrT( + std::vector result; + return internal::SplitStringUsingSubstrT( input, delimiter, whitespace, result_type); } -std::vector SplitStringPieceUsingSubstr( - StringPiece input, - StringPiece delimiter, +std::vector SplitStringPieceUsingSubstr( + std::string_view input, + std::string_view delimiter, WhitespaceHandling whitespace, SplitResult result_type) { - return internal::SplitStringUsingSubstrT( + return internal::SplitStringUsingSubstrT( input, delimiter, whitespace, result_type); } diff --git a/naiveproxy/src/base/strings/string_split.h b/naiveproxy/src/base/strings/string_split.h index e8c677be6e..9bd5910a84 100644 --- a/naiveproxy/src/base/strings/string_split.h +++ b/naiveproxy/src/base/strings/string_split.h @@ -6,11 +6,11 @@ #define BASE_STRINGS_STRING_SPLIT_H_ #include +#include #include #include #include "base/base_export.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" namespace base { @@ -46,13 +46,13 @@ enum SplitResult { // std::vector tokens = base::SplitString( // input, ",;", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); [[nodiscard]] BASE_EXPORT std::vector SplitString( - StringPiece input, - StringPiece separators, + std::string_view input, + std::string_view separators, WhitespaceHandling whitespace, SplitResult result_type); [[nodiscard]] BASE_EXPORT std::vector SplitString( - StringPiece16 input, - StringPiece16 separators, + std::u16string_view input, + std::u16string_view separators, WhitespaceHandling whitespace, SplitResult result_type); @@ -70,14 +70,14 @@ enum SplitResult { // base::KEEP_WHITESPACE, // base::SPLIT_WANT_NONEMPTY)) { // ... -[[nodiscard]] BASE_EXPORT std::vector SplitStringPiece( - StringPiece input, - StringPiece separators, +[[nodiscard]] BASE_EXPORT std::vector SplitStringPiece( + std::string_view input, + std::string_view separators, WhitespaceHandling whitespace, SplitResult result_type); -[[nodiscard]] BASE_EXPORT std::vector SplitStringPiece( - StringPiece16 input, - StringPiece16 separators, +[[nodiscard]] BASE_EXPORT std::vector SplitStringPiece( + std::u16string_view input, + std::u16string_view separators, WhitespaceHandling whitespace, SplitResult result_type); @@ -87,7 +87,7 @@ using StringPairs = std::vector>; // removes whitespace leading each key and trailing each value. Returns true // only if each pair has a non-empty key and value. |key_value_pairs| will // include ("","") pairs for entries without |key_value_delimiter|. -BASE_EXPORT bool SplitStringIntoKeyValuePairs(StringPiece input, +BASE_EXPORT bool SplitStringIntoKeyValuePairs(std::string_view input, char key_value_delimiter, char key_value_pair_delimiter, StringPairs* key_value_pairs); @@ -95,21 +95,21 @@ BASE_EXPORT bool SplitStringIntoKeyValuePairs(StringPiece input, // Similar to SplitStringIntoKeyValuePairs, but use a substring // |key_value_pair_delimiter| instead of a single char. BASE_EXPORT bool SplitStringIntoKeyValuePairsUsingSubstr( - StringPiece input, + std::string_view input, char key_value_delimiter, - StringPiece key_value_pair_delimiter, + std::string_view key_value_pair_delimiter, StringPairs* key_value_pairs); // Similar to SplitString, but use a substring delimiter instead of a list of // characters that are all possible delimiters. [[nodiscard]] BASE_EXPORT std::vector SplitStringUsingSubstr( - StringPiece16 input, - StringPiece16 delimiter, + std::u16string_view input, + std::u16string_view delimiter, WhitespaceHandling whitespace, SplitResult result_type); [[nodiscard]] BASE_EXPORT std::vector SplitStringUsingSubstr( - StringPiece input, - StringPiece delimiter, + std::string_view input, + std::string_view delimiter, WhitespaceHandling whitespace, SplitResult result_type); @@ -125,16 +125,16 @@ BASE_EXPORT bool SplitStringIntoKeyValuePairsUsingSubstr( // base::KEEP_WHITESPACE, // base::SPLIT_WANT_NONEMPTY)) { // ... -[[nodiscard]] BASE_EXPORT std::vector -SplitStringPieceUsingSubstr(StringPiece16 input, - StringPiece16 delimiter, +[[nodiscard]] BASE_EXPORT std::vector +SplitStringPieceUsingSubstr(std::u16string_view input, + std::u16string_view delimiter, + WhitespaceHandling whitespace, + SplitResult result_type); +[[nodiscard]] BASE_EXPORT std::vector +SplitStringPieceUsingSubstr(std::string_view input, + std::string_view delimiter, WhitespaceHandling whitespace, SplitResult result_type); -[[nodiscard]] BASE_EXPORT std::vector SplitStringPieceUsingSubstr( - StringPiece input, - StringPiece delimiter, - WhitespaceHandling whitespace, - SplitResult result_type); } // namespace base diff --git a/naiveproxy/src/base/strings/string_split_internal.h b/naiveproxy/src/base/strings/string_split_internal.h index dc07da353d..87464fb26a 100644 --- a/naiveproxy/src/base/strings/string_split_internal.h +++ b/naiveproxy/src/base/strings/string_split_internal.h @@ -5,9 +5,9 @@ #ifndef BASE_STRINGS_STRING_SPLIT_INTERNAL_H_ #define BASE_STRINGS_STRING_SPLIT_INTERNAL_H_ +#include #include -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" namespace base { @@ -19,16 +19,16 @@ template std::basic_string_view WhitespaceForType(); template <> -inline StringPiece16 WhitespaceForType() { +inline std::u16string_view WhitespaceForType() { return kWhitespaceUTF16; } template <> -inline StringPiece WhitespaceForType() { +inline std::string_view WhitespaceForType() { return kWhitespaceASCII; } // General string splitter template. Can take 8- or 16-bit input, can produce -// the corresponding string or StringPiece output. +// the corresponding string or std::string_view output. template diff --git a/naiveproxy/src/base/strings/string_split_win.cc b/naiveproxy/src/base/strings/string_split_win.cc index 3e0f30a20b..807e64680e 100644 --- a/naiveproxy/src/base/strings/string_split_win.cc +++ b/naiveproxy/src/base/strings/string_split_win.cc @@ -8,7 +8,6 @@ #include #include -#include "base/strings/string_piece.h" #include "base/strings/string_split_internal.h" namespace base { diff --git a/naiveproxy/src/base/strings/string_split_win.h b/naiveproxy/src/base/strings/string_split_win.h index de29758edc..d71a2873a3 100644 --- a/naiveproxy/src/base/strings/string_split_win.h +++ b/naiveproxy/src/base/strings/string_split_win.h @@ -10,7 +10,6 @@ #include #include "base/base_export.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" namespace base { diff --git a/naiveproxy/src/base/strings/string_tokenizer.h b/naiveproxy/src/base/strings/string_tokenizer.h index 89b20b050a..13a213fb3a 100644 --- a/naiveproxy/src/base/strings/string_tokenizer.h +++ b/naiveproxy/src/base/strings/string_tokenizer.h @@ -15,7 +15,6 @@ #include #include "base/check.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" namespace base { diff --git a/naiveproxy/src/base/strings/string_util.cc b/naiveproxy/src/base/strings/string_util.cc index 3221c679cd..e89ca0444f 100644 --- a/naiveproxy/src/base/strings/string_util.cc +++ b/naiveproxy/src/base/strings/string_util.cc @@ -72,19 +72,19 @@ bool IsWprintfFormatPortable(const wchar_t* format) { return true; } -std::string ToLowerASCII(StringPiece str) { +std::string ToLowerASCII(std::string_view str) { return internal::ToLowerASCIIImpl(str); } -std::u16string ToLowerASCII(StringPiece16 str) { +std::u16string ToLowerASCII(std::u16string_view str) { return internal::ToLowerASCIIImpl(str); } -std::string ToUpperASCII(StringPiece str) { +std::string ToUpperASCII(std::string_view str) { return internal::ToUpperASCIIImpl(str); } -std::u16string ToUpperASCII(StringPiece16 str) { +std::u16string ToUpperASCII(std::u16string_view str) { return internal::ToUpperASCIIImpl(str); } @@ -98,55 +98,57 @@ const std::u16string& EmptyString16() { return *s16; } -bool ReplaceChars(StringPiece16 input, - StringPiece16 replace_chars, - StringPiece16 replace_with, +bool ReplaceChars(std::u16string_view input, + std::u16string_view replace_chars, + std::u16string_view replace_with, std::u16string* output) { return internal::ReplaceCharsT(input, replace_chars, replace_with, output); } -bool ReplaceChars(StringPiece input, - StringPiece replace_chars, - StringPiece replace_with, +bool ReplaceChars(std::string_view input, + std::string_view replace_chars, + std::string_view replace_with, std::string* output) { return internal::ReplaceCharsT(input, replace_chars, replace_with, output); } -bool RemoveChars(StringPiece16 input, - StringPiece16 remove_chars, +bool RemoveChars(std::u16string_view input, + std::u16string_view remove_chars, std::u16string* output) { - return internal::ReplaceCharsT(input, remove_chars, StringPiece16(), output); + return internal::ReplaceCharsT(input, remove_chars, std::u16string_view(), + output); } -bool RemoveChars(StringPiece input, - StringPiece remove_chars, +bool RemoveChars(std::string_view input, + std::string_view remove_chars, std::string* output) { - return internal::ReplaceCharsT(input, remove_chars, StringPiece(), output); + return internal::ReplaceCharsT(input, remove_chars, std::string_view(), + output); } -bool TrimString(StringPiece16 input, - StringPiece16 trim_chars, +bool TrimString(std::u16string_view input, + std::u16string_view trim_chars, std::u16string* output) { return internal::TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; } -bool TrimString(StringPiece input, - StringPiece trim_chars, +bool TrimString(std::string_view input, + std::string_view trim_chars, std::string* output) { return internal::TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; } -StringPiece16 TrimString(StringPiece16 input, - StringPiece16 trim_chars, - TrimPositions positions) { +std::u16string_view TrimString(std::u16string_view input, + std::u16string_view trim_chars, + TrimPositions positions) { return internal::TrimStringPieceT(input, trim_chars, positions); } -StringPiece TrimString(StringPiece input, - StringPiece trim_chars, - TrimPositions positions) { +std::string_view TrimString(std::string_view input, + std::string_view trim_chars, + TrimPositions positions) { return internal::TrimStringPieceT(input, trim_chars, positions); } @@ -187,55 +189,56 @@ void TruncateUTF8ToByteSize(const std::string& input, output->clear(); } -TrimPositions TrimWhitespace(StringPiece16 input, +TrimPositions TrimWhitespace(std::u16string_view input, TrimPositions positions, std::u16string* output) { - return internal::TrimStringT(input, StringPiece16(kWhitespaceUTF16), + return internal::TrimStringT(input, std::u16string_view(kWhitespaceUTF16), positions, output); } -StringPiece16 TrimWhitespace(StringPiece16 input, - TrimPositions positions) { - return internal::TrimStringPieceT(input, StringPiece16(kWhitespaceUTF16), - positions); +std::u16string_view TrimWhitespace(std::u16string_view input, + TrimPositions positions) { + return internal::TrimStringPieceT( + input, std::u16string_view(kWhitespaceUTF16), positions); } -TrimPositions TrimWhitespaceASCII(StringPiece input, +TrimPositions TrimWhitespaceASCII(std::string_view input, TrimPositions positions, std::string* output) { - return internal::TrimStringT(input, StringPiece(kWhitespaceASCII), positions, - output); + return internal::TrimStringT(input, std::string_view(kWhitespaceASCII), + positions, output); } -StringPiece TrimWhitespaceASCII(StringPiece input, TrimPositions positions) { - return internal::TrimStringPieceT(input, StringPiece(kWhitespaceASCII), +std::string_view TrimWhitespaceASCII(std::string_view input, + TrimPositions positions) { + return internal::TrimStringPieceT(input, std::string_view(kWhitespaceASCII), positions); } -std::u16string CollapseWhitespace(StringPiece16 text, +std::u16string CollapseWhitespace(std::u16string_view text, bool trim_sequences_with_line_breaks) { return internal::CollapseWhitespaceT(text, trim_sequences_with_line_breaks); } -std::string CollapseWhitespaceASCII(StringPiece text, +std::string CollapseWhitespaceASCII(std::string_view text, bool trim_sequences_with_line_breaks) { return internal::CollapseWhitespaceT(text, trim_sequences_with_line_breaks); } -bool ContainsOnlyChars(StringPiece input, StringPiece characters) { - return input.find_first_not_of(characters) == StringPiece::npos; +bool ContainsOnlyChars(std::string_view input, std::string_view characters) { + return input.find_first_not_of(characters) == std::string_view::npos; } -bool ContainsOnlyChars(StringPiece16 input, StringPiece16 characters) { - return input.find_first_not_of(characters) == StringPiece16::npos; +bool ContainsOnlyChars(std::u16string_view input, + std::u16string_view characters) { + return input.find_first_not_of(characters) == std::u16string_view::npos; } - -bool IsStringASCII(StringPiece str) { +bool IsStringASCII(std::string_view str) { return internal::DoIsStringASCII(str.data(), str.length()); } -bool IsStringASCII(StringPiece16 str) { +bool IsStringASCII(std::u16string_view str) { return internal::DoIsStringASCII(str.data(), str.length()); } @@ -245,38 +248,38 @@ bool IsStringASCII(std::wstring_view str) { } #endif -bool IsStringUTF8(StringPiece str) { +bool IsStringUTF8(std::string_view str) { return internal::DoIsStringUTF8(str); } -bool IsStringUTF8AllowingNoncharacters(StringPiece str) { +bool IsStringUTF8AllowingNoncharacters(std::string_view str) { return internal::DoIsStringUTF8(str); } -bool EqualsASCII(StringPiece16 str, StringPiece ascii) { +bool EqualsASCII(std::u16string_view str, std::string_view ascii) { return ranges::equal(ascii, str); } -bool StartsWith(StringPiece str, - StringPiece search_for, +bool StartsWith(std::string_view str, + std::string_view search_for, CompareCase case_sensitivity) { return internal::StartsWithT(str, search_for, case_sensitivity); } -bool StartsWith(StringPiece16 str, - StringPiece16 search_for, +bool StartsWith(std::u16string_view str, + std::u16string_view search_for, CompareCase case_sensitivity) { return internal::StartsWithT(str, search_for, case_sensitivity); } -bool EndsWith(StringPiece str, - StringPiece search_for, +bool EndsWith(std::string_view str, + std::string_view search_for, CompareCase case_sensitivity) { return internal::EndsWithT(str, search_for, case_sensitivity); } -bool EndsWith(StringPiece16 str, - StringPiece16 search_for, +bool EndsWith(std::u16string_view str, + std::u16string_view search_for, CompareCase case_sensitivity) { return internal::EndsWithT(str, search_for, case_sensitivity); } @@ -322,8 +325,8 @@ std::u16string FormatBytesUnlocalized(int64_t bytes) { void ReplaceFirstSubstringAfterOffset(std::u16string* str, size_t start_offset, - StringPiece16 find_this, - StringPiece16 replace_with) { + std::u16string_view find_this, + std::u16string_view replace_with) { internal::DoReplaceMatchesAfterOffset( str, start_offset, internal::MakeSubstringMatcher(find_this), replace_with, internal::ReplaceType::REPLACE_FIRST); @@ -331,8 +334,8 @@ void ReplaceFirstSubstringAfterOffset(std::u16string* str, void ReplaceFirstSubstringAfterOffset(std::string* str, size_t start_offset, - StringPiece find_this, - StringPiece replace_with) { + std::string_view find_this, + std::string_view replace_with) { internal::DoReplaceMatchesAfterOffset( str, start_offset, internal::MakeSubstringMatcher(find_this), replace_with, internal::ReplaceType::REPLACE_FIRST); @@ -340,8 +343,8 @@ void ReplaceFirstSubstringAfterOffset(std::string* str, void ReplaceSubstringsAfterOffset(std::u16string* str, size_t start_offset, - StringPiece16 find_this, - StringPiece16 replace_with) { + std::u16string_view find_this, + std::u16string_view replace_with) { internal::DoReplaceMatchesAfterOffset( str, start_offset, internal::MakeSubstringMatcher(find_this), replace_with, internal::ReplaceType::REPLACE_ALL); @@ -349,8 +352,8 @@ void ReplaceSubstringsAfterOffset(std::u16string* str, void ReplaceSubstringsAfterOffset(std::string* str, size_t start_offset, - StringPiece find_this, - StringPiece replace_with) { + std::string_view find_this, + std::string_view replace_with) { internal::DoReplaceMatchesAfterOffset( str, start_offset, internal::MakeSubstringMatcher(find_this), replace_with, internal::ReplaceType::REPLACE_ALL); @@ -364,36 +367,38 @@ char16_t* WriteInto(std::u16string* str, size_t length_with_null) { return internal::WriteIntoT(str, length_with_null); } -std::string JoinString(span parts, StringPiece separator) { +std::string JoinString(span parts, + std::string_view separator) { return internal::JoinStringT(parts, separator); } std::u16string JoinString(span parts, - StringPiece16 separator) { + std::u16string_view separator) { return internal::JoinStringT(parts, separator); } -std::string JoinString(span parts, StringPiece separator) { +std::string JoinString(span parts, + std::string_view separator) { return internal::JoinStringT(parts, separator); } -std::u16string JoinString(span parts, - StringPiece16 separator) { +std::u16string JoinString(span parts, + std::u16string_view separator) { return internal::JoinStringT(parts, separator); } -std::string JoinString(std::initializer_list parts, - StringPiece separator) { +std::string JoinString(std::initializer_list parts, + std::string_view separator) { return internal::JoinStringT(parts, separator); } -std::u16string JoinString(std::initializer_list parts, - StringPiece16 separator) { +std::u16string JoinString(std::initializer_list parts, + std::u16string_view separator) { return internal::JoinStringT(parts, separator); } std::u16string ReplaceStringPlaceholders( - StringPiece16 format_string, + std::u16string_view format_string, const std::vector& subst, std::vector* offsets) { std::optional replacement = @@ -407,7 +412,7 @@ std::u16string ReplaceStringPlaceholders( return replacement.value(); } -std::string ReplaceStringPlaceholders(StringPiece format_string, +std::string ReplaceStringPlaceholders(std::string_view format_string, const std::vector& subst, std::vector* offsets) { std::optional replacement = diff --git a/naiveproxy/src/base/strings/string_util.h b/naiveproxy/src/base/strings/string_util.h index 07b31fa58e..80a2737976 100644 --- a/naiveproxy/src/base/strings/string_util.h +++ b/naiveproxy/src/base/strings/string_util.h @@ -27,7 +27,7 @@ #include "base/check_op.h" #include "base/compiler_specific.h" #include "base/containers/span.h" -#include "base/strings/string_piece.h" // For implicit conversions. +// For implicit conversions. #include "base/strings/string_util_internal.h" #include "base/types/to_address.h" #include "build/build_config.h" @@ -103,15 +103,14 @@ constexpr std::basic_string_view MakeBasicStringPiece(Iter begin, return {base::to_address(begin), static_cast(end - begin)}; } -// Explicit instantiations of MakeBasicStringPiece for the BasicStringPiece -// aliases defined in base/strings/string_piece.h +// Explicit instantiations of MakeBasicStringPiece. template -constexpr StringPiece MakeStringPiece(Iter begin, Iter end) { +constexpr std::string_view MakeStringPiece(Iter begin, Iter end) { return MakeBasicStringPiece(begin, end); } template -constexpr StringPiece16 MakeStringPiece16(Iter begin, Iter end) { +constexpr std::u16string_view MakeStringPiece16(Iter begin, Iter end) { return MakeBasicStringPiece(begin, end); } @@ -137,20 +136,20 @@ CharT ToUpperASCII(CharT c) { } // Converts the given string to its ASCII-lowercase equivalent. Non-ASCII -// bytes (or UTF-16 code units in `StringPiece16`) are permitted but will be -// unmodified. -BASE_EXPORT std::string ToLowerASCII(StringPiece str); -BASE_EXPORT std::u16string ToLowerASCII(StringPiece16 str); +// bytes (or UTF-16 code units in `std::u16string_view`) are permitted but will +// be unmodified. +BASE_EXPORT std::string ToLowerASCII(std::string_view str); +BASE_EXPORT std::u16string ToLowerASCII(std::u16string_view str); // Converts the given string to its ASCII-uppercase equivalent. Non-ASCII -// bytes (or UTF-16 code units in `StringPiece16`) are permitted but will be -// unmodified. -BASE_EXPORT std::string ToUpperASCII(StringPiece str); -BASE_EXPORT std::u16string ToUpperASCII(StringPiece16 str); +// bytes (or UTF-16 code units in `std::u16string_view`) are permitted but will +// be unmodified. +BASE_EXPORT std::string ToUpperASCII(std::string_view str); +BASE_EXPORT std::u16string ToUpperASCII(std::u16string_view str); // Functor for ASCII case-insensitive comparisons for STL algorithms like -// std::search. Non-ASCII bytes (or UTF-16 code units in `StringPiece16`) are -// permitted but will be compared as-is. +// std::search. Non-ASCII bytes (or UTF-16 code units in `std::u16string_view`) +// are permitted but will be compared as-is. // // Note that a full Unicode version of this functor is not possible to write // because case mappings might change the number of characters, depend on @@ -173,32 +172,35 @@ template struct CaseInsensitiveCompareASCII { // or base::i18n::FoldCase and then just call the normal string operators on the // result. // -// Non-ASCII bytes (or UTF-16 code units in `StringPiece16`) are permitted but -// will be compared unmodified. -BASE_EXPORT constexpr int CompareCaseInsensitiveASCII(StringPiece a, - StringPiece b) { +// Non-ASCII bytes (or UTF-16 code units in `std::u16string_view`) are permitted +// but will be compared unmodified. +BASE_EXPORT constexpr int CompareCaseInsensitiveASCII(std::string_view a, + std::string_view b) { return internal::CompareCaseInsensitiveASCIIT(a, b); } -BASE_EXPORT constexpr int CompareCaseInsensitiveASCII(StringPiece16 a, - StringPiece16 b) { +BASE_EXPORT constexpr int CompareCaseInsensitiveASCII(std::u16string_view a, + std::u16string_view b) { return internal::CompareCaseInsensitiveASCIIT(a, b); } // Equality for ASCII case-insensitive comparisons. Non-ASCII bytes (or UTF-16 -// code units in `StringPiece16`) are permitted but will be compared unmodified. -// To compare all Unicode code points case-insensitively, use +// code units in `std::u16string_view`) are permitted but will be compared +// unmodified. To compare all Unicode code points case-insensitively, use // base::i18n::ToLower or base::i18n::FoldCase and then compare with either == // or !=. -inline bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b) { +inline bool EqualsCaseInsensitiveASCII(std::string_view a, std::string_view b) { return internal::EqualsCaseInsensitiveASCIIT(a, b); } -inline bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) { +inline bool EqualsCaseInsensitiveASCII(std::u16string_view a, + std::u16string_view b) { return internal::EqualsCaseInsensitiveASCIIT(a, b); } -inline bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece b) { +inline bool EqualsCaseInsensitiveASCII(std::u16string_view a, + std::string_view b) { return internal::EqualsCaseInsensitiveASCIIT(a, b); } -inline bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece16 b) { +inline bool EqualsCaseInsensitiveASCII(std::string_view a, + std::u16string_view b) { return internal::EqualsCaseInsensitiveASCIIT(a, b); } @@ -237,11 +239,11 @@ BASE_EXPORT extern const char kUtf8ByteOrderMark[]; // Removes characters in |remove_chars| from anywhere in |input|. Returns true // if any characters were removed. |remove_chars| must be null-terminated. // NOTE: Safe to use the same variable for both |input| and |output|. -BASE_EXPORT bool RemoveChars(StringPiece16 input, - StringPiece16 remove_chars, +BASE_EXPORT bool RemoveChars(std::u16string_view input, + std::u16string_view remove_chars, std::u16string* output); -BASE_EXPORT bool RemoveChars(StringPiece input, - StringPiece remove_chars, +BASE_EXPORT bool RemoveChars(std::string_view input, + std::string_view remove_chars, std::string* output); // Replaces characters in |replace_chars| from anywhere in |input| with @@ -249,13 +251,13 @@ BASE_EXPORT bool RemoveChars(StringPiece input, // the |replace_with| string. Returns true if any characters were replaced. // |replace_chars| must be null-terminated. // NOTE: Safe to use the same variable for both |input| and |output|. -BASE_EXPORT bool ReplaceChars(StringPiece16 input, - StringPiece16 replace_chars, - StringPiece16 replace_with, +BASE_EXPORT bool ReplaceChars(std::u16string_view input, + std::u16string_view replace_chars, + std::u16string_view replace_with, std::u16string* output); -BASE_EXPORT bool ReplaceChars(StringPiece input, - StringPiece replace_chars, - StringPiece replace_with, +BASE_EXPORT bool ReplaceChars(std::string_view input, + std::string_view replace_chars, + std::string_view replace_with, std::string* output); enum TrimPositions { @@ -271,21 +273,21 @@ enum TrimPositions { // // It is safe to use the same variable for both |input| and |output| (this is // the normal usage to trim in-place). -BASE_EXPORT bool TrimString(StringPiece16 input, - StringPiece16 trim_chars, +BASE_EXPORT bool TrimString(std::u16string_view input, + std::u16string_view trim_chars, std::u16string* output); -BASE_EXPORT bool TrimString(StringPiece input, - StringPiece trim_chars, +BASE_EXPORT bool TrimString(std::string_view input, + std::string_view trim_chars, std::string* output); -// StringPiece versions of the above. The returned pieces refer to the original -// buffer. -BASE_EXPORT StringPiece16 TrimString(StringPiece16 input, - StringPiece16 trim_chars, - TrimPositions positions); -BASE_EXPORT StringPiece TrimString(StringPiece input, - StringPiece trim_chars, - TrimPositions positions); +// std::string_view versions of the above. The returned pieces refer to the +// original buffer. +BASE_EXPORT std::u16string_view TrimString(std::u16string_view input, + std::u16string_view trim_chars, + TrimPositions positions); +BASE_EXPORT std::string_view TrimString(std::string_view input, + std::string_view trim_chars, + TrimPositions positions); // Truncates a string to the nearest UTF-8 character that will leave // the string less than or equal to the specified byte size. @@ -295,21 +297,21 @@ BASE_EXPORT void TruncateUTF8ToByteSize(const std::string& input, // Trims any whitespace from either end of the input string. // -// The StringPiece versions return a substring referencing the input buffer. -// The ASCII versions look only for ASCII whitespace. +// The std::string_view versions return a substring referencing the input +// buffer. The ASCII versions look only for ASCII whitespace. // // The std::string versions return where whitespace was found. // NOTE: Safe to use the same variable for both input and output. -BASE_EXPORT TrimPositions TrimWhitespace(StringPiece16 input, +BASE_EXPORT TrimPositions TrimWhitespace(std::u16string_view input, TrimPositions positions, std::u16string* output); -BASE_EXPORT StringPiece16 TrimWhitespace(StringPiece16 input, - TrimPositions positions); -BASE_EXPORT TrimPositions TrimWhitespaceASCII(StringPiece input, +BASE_EXPORT std::u16string_view TrimWhitespace(std::u16string_view input, + TrimPositions positions); +BASE_EXPORT TrimPositions TrimWhitespaceASCII(std::string_view input, TrimPositions positions, std::string* output); -BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input, - TrimPositions positions); +BASE_EXPORT std::string_view TrimWhitespaceASCII(std::string_view input, + TrimPositions positions); // Searches for CR or LF characters. Removes all contiguous whitespace // strings that contain them. This is useful when trying to deal with text @@ -320,28 +322,29 @@ BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input, // sequences containing a CR or LF are trimmed. // (3) All other whitespace sequences are converted to single spaces. BASE_EXPORT std::u16string CollapseWhitespace( - StringPiece16 text, + std::u16string_view text, bool trim_sequences_with_line_breaks); BASE_EXPORT std::string CollapseWhitespaceASCII( - StringPiece text, + std::string_view text, bool trim_sequences_with_line_breaks); // Returns true if |input| is empty or contains only characters found in // |characters|. -BASE_EXPORT bool ContainsOnlyChars(StringPiece input, StringPiece characters); -BASE_EXPORT bool ContainsOnlyChars(StringPiece16 input, - StringPiece16 characters); +BASE_EXPORT bool ContainsOnlyChars(std::string_view input, + std::string_view characters); +BASE_EXPORT bool ContainsOnlyChars(std::u16string_view input, + std::u16string_view characters); // Returns true if |str| is structurally valid UTF-8 and also doesn't // contain any non-character code point (e.g. U+10FFFE). Prohibiting // non-characters increases the likelihood of detecting non-UTF-8 in // real-world text, for callers which do not need to accept // non-characters in strings. -BASE_EXPORT bool IsStringUTF8(StringPiece str); +BASE_EXPORT bool IsStringUTF8(std::string_view str); // Returns true if |str| contains valid UTF-8, allowing non-character // code points. -BASE_EXPORT bool IsStringUTF8AllowingNoncharacters(StringPiece str); +BASE_EXPORT bool IsStringUTF8AllowingNoncharacters(std::string_view str); // Returns true if |str| contains only valid ASCII character values. // Note 1: IsStringASCII executes in time determined solely by the @@ -349,8 +352,8 @@ BASE_EXPORT bool IsStringUTF8AllowingNoncharacters(StringPiece str); // timing attacks for all strings of equal length. // Note 2: IsStringASCII assumes the input is likely all ASCII, and // does not leave early if it is not the case. -BASE_EXPORT bool IsStringASCII(StringPiece str); -BASE_EXPORT bool IsStringASCII(StringPiece16 str); +BASE_EXPORT bool IsStringASCII(std::string_view str); +BASE_EXPORT bool IsStringASCII(std::u16string_view str); #if defined(WCHAR_T_IS_32_BIT) BASE_EXPORT bool IsStringASCII(std::wstring_view str); @@ -359,7 +362,7 @@ BASE_EXPORT bool IsStringASCII(std::wstring_view str); // Performs a case-sensitive string compare of the given 16-bit string against // the given 8-bit ASCII string (typically a constant). The behavior is // undefined if the |ascii| string is not ASCII. -BASE_EXPORT bool EqualsASCII(StringPiece16 str, StringPiece ascii); +BASE_EXPORT bool EqualsASCII(std::u16string_view str, std::string_view ascii); // Indicates case sensitivity of comparisons. Only ASCII case insensitivity // is supported. Full Unicode case-insensitive conversions would need to go in @@ -375,20 +378,20 @@ enum class CompareCase { }; BASE_EXPORT bool StartsWith( - StringPiece str, - StringPiece search_for, + std::string_view str, + std::string_view search_for, CompareCase case_sensitivity = CompareCase::SENSITIVE); BASE_EXPORT bool StartsWith( - StringPiece16 str, - StringPiece16 search_for, + std::u16string_view str, + std::u16string_view search_for, CompareCase case_sensitivity = CompareCase::SENSITIVE); BASE_EXPORT bool EndsWith( - StringPiece str, - StringPiece search_for, + std::string_view str, + std::string_view search_for, CompareCase case_sensitivity = CompareCase::SENSITIVE); BASE_EXPORT bool EndsWith( - StringPiece16 str, - StringPiece16 search_for, + std::u16string_view str, + std::u16string_view search_for, CompareCase case_sensitivity = CompareCase::SENSITIVE); // Determines the type of ASCII character, independent of locale (the C @@ -504,15 +507,16 @@ BASE_EXPORT std::u16string FormatBytesUnlocalized(int64_t bytes); // Starting at |start_offset| (usually 0), replace the first instance of // |find_this| with |replace_with|. -BASE_EXPORT void ReplaceFirstSubstringAfterOffset(std::u16string* str, - size_t start_offset, - StringPiece16 find_this, - StringPiece16 replace_with); +BASE_EXPORT void ReplaceFirstSubstringAfterOffset( + std::u16string* str, + size_t start_offset, + std::u16string_view find_this, + std::u16string_view replace_with); BASE_EXPORT void ReplaceFirstSubstringAfterOffset( std::string* str, size_t start_offset, - StringPiece find_this, - StringPiece replace_with); + std::string_view find_this, + std::string_view replace_with); // Starting at |start_offset| (usually 0), look through |str| and replace all // instances of |find_this| with |replace_with|. @@ -522,13 +526,12 @@ BASE_EXPORT void ReplaceFirstSubstringAfterOffset( // std::replace(str.begin(), str.end(), 'a', 'b'); BASE_EXPORT void ReplaceSubstringsAfterOffset(std::u16string* str, size_t start_offset, - StringPiece16 find_this, - StringPiece16 replace_with); -BASE_EXPORT void ReplaceSubstringsAfterOffset( - std::string* str, - size_t start_offset, - StringPiece find_this, - StringPiece replace_with); + std::u16string_view find_this, + std::u16string_view replace_with); +BASE_EXPORT void ReplaceSubstringsAfterOffset(std::string* str, + size_t start_offset, + std::string_view find_this, + std::string_view replace_with); // Reserves enough memory in |str| to accommodate |length_with_null| characters, // sets the size of |str| to |length_with_null - 1| characters, and returns a @@ -556,40 +559,41 @@ BASE_EXPORT char16_t* WriteInto(std::u16string* str, size_t length_with_null); // string_split.h. // // If possible, callers should build a vector of StringPieces and use the -// StringPiece variant, so that they do not create unnecessary copies of +// std::string_view variant, so that they do not create unnecessary copies of // strings. For example, instead of using SplitString, modifying the vector, // then using JoinString, use SplitStringPiece followed by JoinString so that no // copies of those strings are created until the final join operation. // // Use StrCat (in base/strings/strcat.h) if you don't need a separator. BASE_EXPORT std::string JoinString(span parts, - StringPiece separator); + std::string_view separator); BASE_EXPORT std::u16string JoinString(span parts, - StringPiece16 separator); -BASE_EXPORT std::string JoinString(span parts, - StringPiece separator); -BASE_EXPORT std::u16string JoinString(span parts, - StringPiece16 separator); + std::u16string_view separator); +BASE_EXPORT std::string JoinString(span parts, + std::string_view separator); +BASE_EXPORT std::u16string JoinString(span parts, + std::u16string_view separator); // Explicit initializer_list overloads are required to break ambiguity when used // with a literal initializer list (otherwise the compiler would not be able to -// decide between the string and StringPiece overloads). -BASE_EXPORT std::string JoinString(std::initializer_list parts, - StringPiece separator); +// decide between the string and std::string_view overloads). +BASE_EXPORT std::string JoinString( + std::initializer_list parts, + std::string_view separator); BASE_EXPORT std::u16string JoinString( - std::initializer_list parts, - StringPiece16 separator); + std::initializer_list parts, + std::u16string_view separator); // Replace $1-$2-$3..$9 in the format string with values from |subst|. // Additionally, any number of consecutive '$' characters is replaced by that // number less one. Eg $$->$, $$$->$$, etc. The offsets parameter here can be // NULL. This only allows you to use up to nine replacements. BASE_EXPORT std::u16string ReplaceStringPlaceholders( - StringPiece16 format_string, + std::u16string_view format_string, const std::vector& subst, std::vector* offsets); BASE_EXPORT std::string ReplaceStringPlaceholders( - StringPiece format_string, + std::string_view format_string, const std::vector& subst, std::vector* offsets); @@ -599,6 +603,16 @@ BASE_EXPORT std::u16string ReplaceStringPlaceholders( const std::u16string& a, size_t* offset); +// Helper function for creating a std::string_view from a string literal that +// preserves internal NUL characters. +template +std::basic_string_view MakeStringViewWithNulChars( + const CharT (&lit LIFETIME_BOUND)[N]) + ENABLE_IF_ATTR(lit[N - 1u] == CharT{0}, + "requires string literal as input") { + return std::basic_string_view(lit, N - 1u); +} + } // namespace base #if BUILDFLAG(IS_WIN) diff --git a/naiveproxy/src/base/strings/string_util_impl_helpers.h b/naiveproxy/src/base/strings/string_util_impl_helpers.h index 530e6e5de7..2bb47c65a1 100644 --- a/naiveproxy/src/base/strings/string_util_impl_helpers.h +++ b/naiveproxy/src/base/strings/string_util_impl_helpers.h @@ -19,7 +19,6 @@ #include "base/logging.h" #include "base/notreached.h" #include "base/ranges/algorithm.h" -#include "base/strings/string_piece.h" #include "base/third_party/icu/icu_utf.h" namespace base::internal { @@ -74,8 +73,8 @@ TrimPositions TrimStringT(T input, TrimPositions positions, std::basic_string* output) { // Find the edges of leading/trailing whitespace as desired. Need to use - // a StringPiece version of input to be able to call find* on it with the - // StringPiece version of trim_chars (normally the trim_chars will be a + // a std::string_view version of input to be able to call find* on it with the + // std::string_view version of trim_chars (normally the trim_chars will be a // constant so avoid making a copy). const size_t last_char = input.length() - 1; const size_t first_good_char = @@ -207,7 +206,7 @@ bool DoIsStringASCII(const Char* characters, size_t length) { } template -inline bool DoIsStringUTF8(StringPiece str) { +inline bool DoIsStringUTF8(std::string_view str) { const uint8_t* src = reinterpret_cast(str.data()); size_t src_len = str.length(); size_t char_index = 0; @@ -468,8 +467,8 @@ inline typename string_type::value_type* WriteIntoT(string_type* str, // Generic version for all JoinString overloads. |list_type| must be a sequence // (base::span or std::initializer_list) of strings/StringPieces (std::string, -// std::u16string, StringPiece or StringPiece16). |CharT| is either char or -// char16_t. +// std::u16string, std::string_view or std::u16string_view). |CharT| is either +// char or char16_t. template diff --git a/naiveproxy/src/base/strings/string_util_internal.h b/naiveproxy/src/base/strings/string_util_internal.h index 7a98e84572..65800b6eb1 100644 --- a/naiveproxy/src/base/strings/string_util_internal.h +++ b/naiveproxy/src/base/strings/string_util_internal.h @@ -10,7 +10,6 @@ #include #include "base/ranges/algorithm.h" -#include "base/strings/string_piece.h" namespace base::internal { diff --git a/naiveproxy/src/base/strings/string_util_posix.h b/naiveproxy/src/base/strings/string_util_posix.h index 6496c30c07..908b6d9ae4 100644 --- a/naiveproxy/src/base/strings/string_util_posix.h +++ b/naiveproxy/src/base/strings/string_util_posix.h @@ -12,7 +12,6 @@ #include #include "base/check.h" -#include "base/strings/string_piece.h" namespace base { diff --git a/naiveproxy/src/base/strings/string_util_win.cc b/naiveproxy/src/base/strings/string_util_win.cc index 7723fa87fe..87a22f77e6 100644 --- a/naiveproxy/src/base/strings/string_util_win.cc +++ b/naiveproxy/src/base/strings/string_util_win.cc @@ -74,10 +74,10 @@ std::wstring CollapseWhitespace(std::wstring_view text, } bool ContainsOnlyChars(std::wstring_view input, std::wstring_view characters) { - return input.find_first_not_of(characters) == StringPiece::npos; + return input.find_first_not_of(characters) == std::string_view::npos; } -bool EqualsASCII(std::wstring_view str, StringPiece ascii) { +bool EqualsASCII(std::wstring_view str, std::string_view ascii) { return ranges::equal(ascii, str); } diff --git a/naiveproxy/src/base/strings/string_util_win.h b/naiveproxy/src/base/strings/string_util_win.h index e3e2be8f21..9223baa6c4 100644 --- a/naiveproxy/src/base/strings/string_util_win.h +++ b/naiveproxy/src/base/strings/string_util_win.h @@ -17,7 +17,6 @@ #include "base/check.h" #include "base/containers/span.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" namespace base { @@ -68,7 +67,7 @@ inline const wchar_t* as_wcstr(const char16_t* str) { return reinterpret_cast(str); } -inline const wchar_t* as_wcstr(StringPiece16 str) { +inline const wchar_t* as_wcstr(std::u16string_view str) { return reinterpret_cast(str.data()); } @@ -91,16 +90,16 @@ inline const char16_t* as_u16cstr(std::wstring_view str) { } // Utility functions to convert between std::wstring_view and -// base::StringPiece16. -inline std::wstring_view AsWStringView(StringPiece16 str) { +// std::u16string_view. +inline std::wstring_view AsWStringView(std::u16string_view str) { return std::wstring_view(as_wcstr(str.data()), str.size()); } -inline StringPiece16 AsStringPiece16(std::wstring_view str) { - return StringPiece16(as_u16cstr(str.data()), str.size()); +inline std::u16string_view AsStringPiece16(std::wstring_view str) { + return std::u16string_view(as_u16cstr(str.data()), str.size()); } -inline std::wstring AsWString(StringPiece16 str) { +inline std::wstring AsWString(std::u16string_view str) { return std::wstring(as_wcstr(str.data()), str.size()); } @@ -123,10 +122,12 @@ inline bool EqualsCaseInsensitiveASCII(std::wstring_view a, std::wstring_view b) { return internal::EqualsCaseInsensitiveASCIIT(a, b); } -inline bool EqualsCaseInsensitiveASCII(std::wstring_view a, StringPiece b) { +inline bool EqualsCaseInsensitiveASCII(std::wstring_view a, + std::string_view b) { return internal::EqualsCaseInsensitiveASCIIT(a, b); } -inline bool EqualsCaseInsensitiveASCII(StringPiece a, std::wstring_view b) { +inline bool EqualsCaseInsensitiveASCII(std::string_view a, + std::wstring_view b) { return internal::EqualsCaseInsensitiveASCIIT(a, b); } @@ -161,7 +162,7 @@ BASE_EXPORT std::wstring CollapseWhitespace( BASE_EXPORT bool ContainsOnlyChars(std::wstring_view input, std::wstring_view characters); -BASE_EXPORT bool EqualsASCII(StringPiece16 str, StringPiece ascii); +BASE_EXPORT bool EqualsASCII(std::u16string_view str, std::string_view ascii); BASE_EXPORT bool StartsWith( std::wstring_view str, diff --git a/naiveproxy/src/base/strings/sys_string_conversions.h b/naiveproxy/src/base/strings/sys_string_conversions.h index 006f2e3f55..4499cb30bd 100644 --- a/naiveproxy/src/base/strings/sys_string_conversions.h +++ b/naiveproxy/src/base/strings/sys_string_conversions.h @@ -12,9 +12,9 @@ #include #include +#include #include "base/base_export.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" #if BUILDFLAG(IS_APPLE) @@ -32,14 +32,15 @@ namespace base { // Converts between wide and UTF-8 representations of a string. On error, the // result is system-dependent. [[nodiscard]] BASE_EXPORT std::string SysWideToUTF8(const std::wstring& wide); -[[nodiscard]] BASE_EXPORT std::wstring SysUTF8ToWide(StringPiece utf8); +[[nodiscard]] BASE_EXPORT std::wstring SysUTF8ToWide(std::string_view utf8); // Converts between wide and the system multi-byte representations of a string. // DANGER: This will lose information and can change (on Windows, this can // change between reboots). [[nodiscard]] BASE_EXPORT std::string SysWideToNativeMB( const std::wstring& wide); -[[nodiscard]] BASE_EXPORT std::wstring SysNativeMBToWide(StringPiece native_mb); +[[nodiscard]] BASE_EXPORT std::wstring SysNativeMBToWide( + std::string_view native_mb); // Windows-specific ------------------------------------------------------------ @@ -48,7 +49,7 @@ namespace base { // Converts between 8-bit and wide strings, using the given code page. The // code page identifier is one accepted by the Windows function // MultiByteToWideChar(). -[[nodiscard]] BASE_EXPORT std::wstring SysMultiByteToWide(StringPiece mb, +[[nodiscard]] BASE_EXPORT std::wstring SysMultiByteToWide(std::string_view mb, uint32_t code_page); [[nodiscard]] BASE_EXPORT std::string SysWideToMultiByte( const std::wstring& wide, @@ -64,9 +65,9 @@ namespace base { // Converts a string to a CFStringRef. Returns null on failure. [[nodiscard]] BASE_EXPORT apple::ScopedCFTypeRef -SysUTF8ToCFStringRef(StringPiece utf8); +SysUTF8ToCFStringRef(std::string_view utf8); [[nodiscard]] BASE_EXPORT apple::ScopedCFTypeRef -SysUTF16ToCFStringRef(StringPiece16 utf16); +SysUTF16ToCFStringRef(std::u16string_view utf16); // Converts a CFStringRef to a string. Returns an empty string on failure. It is // not valid to call these with a null `ref`. @@ -76,8 +77,9 @@ SysUTF16ToCFStringRef(StringPiece16 utf16); #ifdef __OBJC__ // Converts a string to an autoreleased NSString. Returns nil on failure. -[[nodiscard]] BASE_EXPORT NSString* SysUTF8ToNSString(StringPiece utf8); -[[nodiscard]] BASE_EXPORT NSString* SysUTF16ToNSString(StringPiece16 utf16); +[[nodiscard]] BASE_EXPORT NSString* SysUTF8ToNSString(std::string_view utf8); +[[nodiscard]] BASE_EXPORT NSString* SysUTF16ToNSString( + std::u16string_view utf16); // Converts an NSString to a string. Returns an empty string on failure or if // `ref` is nil. diff --git a/naiveproxy/src/base/strings/sys_string_conversions_apple.mm b/naiveproxy/src/base/strings/sys_string_conversions_apple.mm index 710490c2aa..a6aee409ee 100644 --- a/naiveproxy/src/base/strings/sys_string_conversions_apple.mm +++ b/naiveproxy/src/base/strings/sys_string_conversions_apple.mm @@ -14,7 +14,6 @@ #include "base/apple/foundation_util.h" #include "base/apple/scoped_cftyperef.h" #include "base/numerics/safe_conversions.h" -#include "base/strings/string_piece.h" namespace base { @@ -96,8 +95,8 @@ OutStringType StringToStringWithEncodingsT(const InStringType& in, out_encoding); } -// Given a StringPiece `in` with an encoding specified by `in_encoding`, returns -// it as a CFStringRef. Returns null on failure. +// Given a std::string_view `in` with an encoding specified by `in_encoding`, +// returns it as a CFStringRef. Returns null on failure. template apple::ScopedCFTypeRef StringPieceToCFStringWithEncodingsT( std::basic_string_view in, @@ -126,8 +125,8 @@ std::string SysWideToUTF8(const std::wstring& wide) { } // Do not assert in this function since it is used by the assertion code! -std::wstring SysUTF8ToWide(StringPiece utf8) { - return StringToStringWithEncodingsT( +std::wstring SysUTF8ToWide(std::string_view utf8) { + return StringToStringWithEncodingsT( utf8, kCFStringEncodingUTF8, kCFStringEncodingUTF32LE); } @@ -135,23 +134,25 @@ std::string SysWideToNativeMB(const std::wstring& wide) { return SysWideToUTF8(wide); } -std::wstring SysNativeMBToWide(StringPiece native_mb) { +std::wstring SysNativeMBToWide(std::string_view native_mb) { return SysUTF8ToWide(native_mb); } -apple::ScopedCFTypeRef SysUTF8ToCFStringRef(StringPiece utf8) { +apple::ScopedCFTypeRef SysUTF8ToCFStringRef( + std::string_view utf8) { return StringPieceToCFStringWithEncodingsT(utf8, kCFStringEncodingUTF8); } -apple::ScopedCFTypeRef SysUTF16ToCFStringRef(StringPiece16 utf16) { +apple::ScopedCFTypeRef SysUTF16ToCFStringRef( + std::u16string_view utf16) { return StringPieceToCFStringWithEncodingsT(utf16, kCFStringEncodingUTF16LE); } -NSString* SysUTF8ToNSString(StringPiece utf8) { +NSString* SysUTF8ToNSString(std::string_view utf8) { return base::apple::CFToNSOwnershipCast(SysUTF8ToCFStringRef(utf8).release()); } -NSString* SysUTF16ToNSString(StringPiece16 utf16) { +NSString* SysUTF16ToNSString(std::u16string_view utf16) { return base::apple::CFToNSOwnershipCast( SysUTF16ToCFStringRef(utf16).release()); } diff --git a/naiveproxy/src/base/strings/sys_string_conversions_posix.cc b/naiveproxy/src/base/strings/sys_string_conversions_posix.cc index 8772b5b08b..baf1fd68bf 100644 --- a/naiveproxy/src/base/strings/sys_string_conversions_posix.cc +++ b/naiveproxy/src/base/strings/sys_string_conversions_posix.cc @@ -13,7 +13,8 @@ #include #include -#include "base/strings/string_piece.h" +#include + #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -24,7 +25,7 @@ std::string SysWideToUTF8(const std::wstring& wide) { // than our ICU, but this will do for now. return WideToUTF8(wide); } -std::wstring SysUTF8ToWide(StringPiece utf8) { +std::wstring SysUTF8ToWide(std::string_view utf8) { // In theory this should be using the system-provided conversion rather // than our ICU, but this will do for now. std::wstring out; @@ -40,7 +41,7 @@ std::string SysWideToNativeMB(const std::wstring& wide) { return WideToUTF8(wide); } -std::wstring SysNativeMBToWide(StringPiece native_mb) { +std::wstring SysNativeMBToWide(std::string_view native_mb) { return SysUTF8ToWide(native_mb); } @@ -103,7 +104,7 @@ std::string SysWideToNativeMB(const std::wstring& wide) { return out; } -std::wstring SysNativeMBToWide(StringPiece native_mb) { +std::wstring SysNativeMBToWide(std::string_view native_mb) { mbstate_t ps; // Calculate the number of wide characters. We walk through the string diff --git a/naiveproxy/src/base/strings/sys_string_conversions_win.cc b/naiveproxy/src/base/strings/sys_string_conversions_win.cc index e84c79d1e7..34fa82b2f9 100644 --- a/naiveproxy/src/base/strings/sys_string_conversions_win.cc +++ b/naiveproxy/src/base/strings/sys_string_conversions_win.cc @@ -8,7 +8,7 @@ #include -#include "base/strings/string_piece.h" +#include namespace base { @@ -18,7 +18,7 @@ std::string SysWideToUTF8(const std::wstring& wide) { } // Do not assert in this function since it is used by the asssertion code! -std::wstring SysUTF8ToWide(StringPiece utf8) { +std::wstring SysUTF8ToWide(std::string_view utf8) { return SysMultiByteToWide(utf8, CP_UTF8); } @@ -26,12 +26,12 @@ std::string SysWideToNativeMB(const std::wstring& wide) { return SysWideToMultiByte(wide, CP_ACP); } -std::wstring SysNativeMBToWide(StringPiece native_mb) { +std::wstring SysNativeMBToWide(std::string_view native_mb) { return SysMultiByteToWide(native_mb, CP_ACP); } // Do not assert in this function since it is used by the asssertion code! -std::wstring SysMultiByteToWide(StringPiece mb, uint32_t code_page) { +std::wstring SysMultiByteToWide(std::string_view mb, uint32_t code_page) { if (mb.empty()) return std::wstring(); diff --git a/naiveproxy/src/base/strings/utf_offset_string_conversions.cc b/naiveproxy/src/base/strings/utf_offset_string_conversions.cc index e7335c6f10..4848372a8b 100644 --- a/naiveproxy/src/base/strings/utf_offset_string_conversions.cc +++ b/naiveproxy/src/base/strings/utf_offset_string_conversions.cc @@ -8,9 +8,9 @@ #include #include +#include #include "base/check_op.h" -#include "base/strings/string_piece.h" #include "base/strings/utf_string_conversion_utils.h" namespace base { @@ -229,7 +229,7 @@ bool UTF8ToUTF16WithAdjustments( } std::u16string UTF8ToUTF16WithAdjustments( - const base::StringPiece& utf8, + std::string_view utf8, base::OffsetAdjuster::Adjustments* adjustments) { std::u16string result; UTF8ToUTF16WithAdjustments(utf8.data(), utf8.length(), &result, adjustments); @@ -237,7 +237,7 @@ std::u16string UTF8ToUTF16WithAdjustments( } std::u16string UTF8ToUTF16AndAdjustOffsets( - const base::StringPiece& utf8, + std::string_view utf8, std::vector* offsets_for_adjustment) { for (size_t& offset : *offsets_for_adjustment) { if (offset > utf8.length()) @@ -250,7 +250,7 @@ std::u16string UTF8ToUTF16AndAdjustOffsets( } std::string UTF16ToUTF8AndAdjustOffsets( - const base::StringPiece16& utf16, + std::u16string_view utf16, std::vector* offsets_for_adjustment) { for (size_t& offset : *offsets_for_adjustment) { if (offset > utf16.length()) diff --git a/naiveproxy/src/base/strings/utf_offset_string_conversions.h b/naiveproxy/src/base/strings/utf_offset_string_conversions.h index c535b96121..0c52fc078b 100644 --- a/naiveproxy/src/base/strings/utf_offset_string_conversions.h +++ b/naiveproxy/src/base/strings/utf_offset_string_conversions.h @@ -8,10 +8,10 @@ #include #include +#include #include #include "base/base_export.h" -#include "base/strings/string_piece.h" namespace base { @@ -97,17 +97,17 @@ BASE_EXPORT bool UTF8ToUTF16WithAdjustments( std::u16string* output, base::OffsetAdjuster::Adjustments* adjustments); [[nodiscard]] BASE_EXPORT std::u16string UTF8ToUTF16WithAdjustments( - const base::StringPiece& utf8, + std::string_view utf8, base::OffsetAdjuster::Adjustments* adjustments); // As above, but instead internally examines the adjustments and applies them // to |offsets_for_adjustment|. Input offsets greater than the length of the // input string will be set to std::u16string::npos. See comments by // AdjustOffsets(). BASE_EXPORT std::u16string UTF8ToUTF16AndAdjustOffsets( - const base::StringPiece& utf8, + std::string_view utf8, std::vector* offsets_for_adjustment); BASE_EXPORT std::string UTF16ToUTF8AndAdjustOffsets( - const base::StringPiece16& utf16, + std::u16string_view utf16, std::vector* offsets_for_adjustment); } // namespace base diff --git a/naiveproxy/src/base/strings/utf_string_conversions.cc b/naiveproxy/src/base/strings/utf_string_conversions.cc index eb9365c2a7..e5fe23d1c1 100644 --- a/naiveproxy/src/base/strings/utf_string_conversions.cc +++ b/naiveproxy/src/base/strings/utf_string_conversions.cc @@ -17,7 +17,6 @@ #include #include -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_ostream_operators.h" #include "base/strings/utf_string_conversion_utils.h" @@ -229,10 +228,10 @@ bool UTFConversion(const InputString& src_str, DestString* dest_str) { // UTF16 <-> UTF8 -------------------------------------------------------------- bool UTF8ToUTF16(const char* src, size_t src_len, std::u16string* output) { - return UTFConversion(StringPiece(src, src_len), output); + return UTFConversion(std::string_view(src, src_len), output); } -std::u16string UTF8ToUTF16(StringPiece utf8) { +std::u16string UTF8ToUTF16(std::string_view utf8) { std::u16string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. @@ -241,10 +240,10 @@ std::u16string UTF8ToUTF16(StringPiece utf8) { } bool UTF16ToUTF8(const char16_t* src, size_t src_len, std::string* output) { - return UTFConversion(StringPiece16(src, src_len), output); + return UTFConversion(std::u16string_view(src, src_len), output); } -std::string UTF16ToUTF8(StringPiece16 utf16) { +std::string UTF16ToUTF8(std::u16string_view utf16) { std::string ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. @@ -271,7 +270,7 @@ bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output) { return true; } -std::wstring UTF16ToWide(StringPiece16 utf16) { +std::wstring UTF16ToWide(std::u16string_view utf16) { return std::wstring(utf16.begin(), utf16.end()); } @@ -290,10 +289,10 @@ std::u16string WideToUTF16(std::wstring_view wide) { } bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output) { - return UTFConversion(StringPiece16(src, src_len), output); + return UTFConversion(std::u16string_view(src, src_len), output); } -std::wstring UTF16ToWide(StringPiece16 utf16) { +std::wstring UTF16ToWide(std::u16string_view utf16) { std::wstring ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. @@ -308,10 +307,10 @@ std::wstring UTF16ToWide(StringPiece16 utf16) { // UTF8ToWide is the same code, regardless of whether wide is 16 or 32 bits bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output) { - return UTFConversion(StringPiece(src, src_len), output); + return UTFConversion(std::string_view(src, src_len), output); } -std::wstring UTF8ToWide(StringPiece utf8) { +std::wstring UTF8ToWide(std::string_view utf8) { std::wstring ret; // Ignore the success flag of this call, it will do the best it can for // invalid input, which is what we want here. @@ -327,7 +326,7 @@ bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) { } std::string WideToUTF8(std::wstring_view wide) { - return UTF16ToUTF8(StringPiece16(as_u16cstr(wide), wide.size())); + return UTF16ToUTF8(std::u16string_view(as_u16cstr(wide), wide.size())); } #elif defined(WCHAR_T_IS_32_BIT) @@ -346,18 +345,18 @@ std::string WideToUTF8(std::wstring_view wide) { #endif // defined(WCHAR_T_IS_32_BIT) -std::u16string ASCIIToUTF16(StringPiece ascii) { +std::u16string ASCIIToUTF16(std::string_view ascii) { DCHECK(IsStringASCII(ascii)) << ascii; return std::u16string(ascii.begin(), ascii.end()); } -std::string UTF16ToASCII(StringPiece16 utf16) { +std::string UTF16ToASCII(std::u16string_view utf16) { DCHECK(IsStringASCII(utf16)) << UTF16ToUTF8(utf16); return std::string(utf16.begin(), utf16.end()); } #if defined(WCHAR_T_IS_16_BIT) -std::wstring ASCIIToWide(StringPiece ascii) { +std::wstring ASCIIToWide(std::string_view ascii) { DCHECK(IsStringASCII(ascii)) << ascii; return std::wstring(ascii.begin(), ascii.end()); } diff --git a/naiveproxy/src/base/strings/utf_string_conversions.h b/naiveproxy/src/base/strings/utf_string_conversions.h index c7417d6ad5..c446b33980 100644 --- a/naiveproxy/src/base/strings/utf_string_conversions.h +++ b/naiveproxy/src/base/strings/utf_string_conversions.h @@ -11,7 +11,6 @@ #include #include "base/base_export.h" -#include "base/strings/string_piece.h" #include "base/types/always_false.h" #include "build/build_config.h" @@ -28,7 +27,7 @@ BASE_EXPORT bool WideToUTF8(const wchar_t* src, size_t src_len, [[nodiscard]] BASE_EXPORT std::string WideToUTF8(std::wstring_view wide); BASE_EXPORT bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output); -[[nodiscard]] BASE_EXPORT std::wstring UTF8ToWide(StringPiece utf8); +[[nodiscard]] BASE_EXPORT std::wstring UTF8ToWide(std::string_view utf8); BASE_EXPORT bool WideToUTF16(const wchar_t* src, size_t src_len, @@ -37,29 +36,29 @@ BASE_EXPORT bool WideToUTF16(const wchar_t* src, BASE_EXPORT bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output); -[[nodiscard]] BASE_EXPORT std::wstring UTF16ToWide(StringPiece16 utf16); +[[nodiscard]] BASE_EXPORT std::wstring UTF16ToWide(std::u16string_view utf16); BASE_EXPORT bool UTF8ToUTF16(const char* src, size_t src_len, std::u16string* output); -[[nodiscard]] BASE_EXPORT std::u16string UTF8ToUTF16(StringPiece utf8); +[[nodiscard]] BASE_EXPORT std::u16string UTF8ToUTF16(std::string_view utf8); BASE_EXPORT bool UTF16ToUTF8(const char16_t* src, size_t src_len, std::string* output); -[[nodiscard]] BASE_EXPORT std::string UTF16ToUTF8(StringPiece16 utf16); +[[nodiscard]] BASE_EXPORT std::string UTF16ToUTF8(std::u16string_view utf16); // This converts an ASCII string, typically a hardcoded constant, to a UTF16 // string. -[[nodiscard]] BASE_EXPORT std::u16string ASCIIToUTF16(StringPiece ascii); +[[nodiscard]] BASE_EXPORT std::u16string ASCIIToUTF16(std::string_view ascii); // Converts to 7-bit ASCII by truncating. The result must be known to be ASCII // beforehand. -[[nodiscard]] BASE_EXPORT std::string UTF16ToASCII(StringPiece16 utf16); +[[nodiscard]] BASE_EXPORT std::string UTF16ToASCII(std::u16string_view utf16); #if defined(WCHAR_T_IS_16_BIT) // This converts an ASCII string, typically a hardcoded constant, to a wide // string. -[[nodiscard]] BASE_EXPORT std::wstring ASCIIToWide(StringPiece ascii); +[[nodiscard]] BASE_EXPORT std::wstring ASCIIToWide(std::string_view ascii); // Converts to 7-bit ASCII by truncating. The result must be known to be ASCII // beforehand. @@ -92,7 +91,7 @@ template // to allow this conversion. template std::u16string ASCIIToUTF16(char (&str)[N]) { - return ASCIIToUTF16(StringPiece(str)); + return ASCIIToUTF16(std::string_view(str)); } } // namespace base diff --git a/naiveproxy/src/base/synchronization/lock.cc b/naiveproxy/src/base/synchronization/lock.cc index 8c3a891f21..4ebb7316b9 100644 --- a/naiveproxy/src/base/synchronization/lock.cc +++ b/naiveproxy/src/base/synchronization/lock.cc @@ -35,13 +35,11 @@ namespace { // dynamic-size array (e.g. owned by a `ThreadLocalOwnedPointer`) would require // handling reentrancy issues with allocator shims that use `base::Lock`. constexpr int kHeldLocksCapacity = 10; -thread_local std::array g_locks_held_by_thread; +thread_local std::array + g_tracked_locks_held_by_thread; -// Number of non-nullptr elements in `g_locks_held_by_thread`. -thread_local size_t g_num_locks_held_by_thread = 0; - -// Whether a lock is added to `g_locks_held_by_thread` when acquired. -thread_local bool g_track_locks = true; +// Number of non-nullptr elements in `g_tracked_locks_held_by_thread`. +thread_local size_t g_num_tracked_locks_held_by_thread = 0; } // namespace @@ -49,6 +47,33 @@ Lock::~Lock() { DCHECK(owning_thread_ref_.is_null()); } +void Lock::Acquire(subtle::LockTracking tracking) { + lock_.Lock(); + if (tracking == subtle::LockTracking::kEnabled) { + AddToLocksHeldOnCurrentThread(); + } + CheckUnheldAndMark(); +} + +void Lock::Release() { + CheckHeldAndUnmark(); + if (in_tracked_locks_held_by_current_thread_) { + RemoveFromLocksHeldOnCurrentThread(); + } + lock_.Unlock(); +} + +bool Lock::Try(subtle::LockTracking tracking) { + const bool rv = lock_.Try(); + if (rv) { + if (tracking == subtle::LockTracking::kEnabled) { + AddToLocksHeldOnCurrentThread(); + } + CheckUnheldAndMark(); + } + return rv; +} + void Lock::AssertAcquired() const { DCHECK_EQ(owning_thread_ref_, PlatformThread::CurrentRef()); } @@ -60,57 +85,58 @@ void Lock::AssertNotHeld() const { void Lock::CheckHeldAndUnmark() { DCHECK_EQ(owning_thread_ref_, PlatformThread::CurrentRef()); owning_thread_ref_ = PlatformThreadRef(); - - // Remove from the list of held locks. - for (size_t i = 0; i < g_num_locks_held_by_thread; ++i) { - // Traverse from the end since locks are typically acquired and released in - // opposite order. - const size_t index = g_num_locks_held_by_thread - i - 1; - if (g_locks_held_by_thread[index] == reinterpret_cast(this)) { - g_locks_held_by_thread[index] = - g_locks_held_by_thread[g_num_locks_held_by_thread - 1]; - g_locks_held_by_thread[g_num_locks_held_by_thread - 1] = - reinterpret_cast(nullptr); - --g_num_locks_held_by_thread; - break; - } - } } void Lock::CheckUnheldAndMark() { DCHECK(owning_thread_ref_.is_null()); owning_thread_ref_ = PlatformThread::CurrentRef(); +} - if (g_track_locks) { - // Check if capacity is exceeded. - if (g_num_locks_held_by_thread >= kHeldLocksCapacity) { - // Disable tracking of locks since logging may acquire a lock. - subtle::DoNotTrackLocks do_not_track_locks; - CHECK(false) - << "This thread holds more than " << kHeldLocksCapacity - << " locks simultaneously. Reach out to //base OWNERS to determine " - "whether it's preferable to increase `kHeldLocksCapacity` or to " - "use `DoNotTrackLocks` in this scope."; - } +void Lock::AddToLocksHeldOnCurrentThread() { + CHECK(!in_tracked_locks_held_by_current_thread_); - // Add to the list of held locks. - g_locks_held_by_thread[g_num_locks_held_by_thread] = - reinterpret_cast(this); - ++g_num_locks_held_by_thread; + // Check if capacity is exceeded. + if (g_num_tracked_locks_held_by_thread >= kHeldLocksCapacity) { + CHECK(false) + << "This thread holds more than " << kHeldLocksCapacity + << " tracked locks simultaneously. Reach out to //base OWNERS to " + "determine whether `kHeldLocksCapacity` should be increased."; } + + // Add to the list of held locks. + g_tracked_locks_held_by_thread[g_num_tracked_locks_held_by_thread] = + reinterpret_cast(this); + ++g_num_tracked_locks_held_by_thread; + in_tracked_locks_held_by_current_thread_ = true; +} + +void Lock::RemoveFromLocksHeldOnCurrentThread() { + CHECK(in_tracked_locks_held_by_current_thread_); + for (size_t i = 0; i < g_num_tracked_locks_held_by_thread; ++i) { + // Traverse from the end since locks are typically acquired and released in + // opposite order. + const size_t index = g_num_tracked_locks_held_by_thread - i - 1; + if (g_tracked_locks_held_by_thread[index] == + reinterpret_cast(this)) { + g_tracked_locks_held_by_thread[index] = + g_tracked_locks_held_by_thread[g_num_tracked_locks_held_by_thread - + 1]; + g_tracked_locks_held_by_thread[g_num_tracked_locks_held_by_thread - 1] = + reinterpret_cast(nullptr); + --g_num_tracked_locks_held_by_thread; + break; + } + } + in_tracked_locks_held_by_current_thread_ = false; } namespace subtle { -span GetLocksHeldByCurrentThread() { - return span(g_locks_held_by_thread.begin(), - g_num_locks_held_by_thread); +span GetTrackedLocksHeldByCurrentThread() { + return span(g_tracked_locks_held_by_thread.begin(), + g_num_tracked_locks_held_by_thread); } -DoNotTrackLocks::DoNotTrackLocks() : auto_reset_(&g_track_locks, false) {} - -DoNotTrackLocks::~DoNotTrackLocks() = default; - } // namespace subtle } // namespace base diff --git a/naiveproxy/src/base/synchronization/lock.h b/naiveproxy/src/base/synchronization/lock.h index 0e66574e46..b486121558 100644 --- a/naiveproxy/src/base/synchronization/lock.h +++ b/naiveproxy/src/base/synchronization/lock.h @@ -8,6 +8,7 @@ #include "base/base_export.h" #include "base/dcheck_is_on.h" #include "base/synchronization/lock_impl.h" +#include "base/synchronization/lock_subtle.h" #include "base/thread_annotations.h" #include "build/build_config.h" @@ -30,14 +31,20 @@ class LOCKABLE BASE_EXPORT Lock { #if !DCHECK_IS_ON() ~Lock() = default; - void Acquire() EXCLUSIVE_LOCK_FUNCTION() { lock_.Lock(); } + void Acquire(subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_LOCK_FUNCTION() { + lock_.Lock(); + } void Release() UNLOCK_FUNCTION() { lock_.Unlock(); } // If the lock is not held, take it and return true. If the lock is already // held by another thread, immediately return false. This must not be called // by a thread already holding the lock (what happens is undefined and an // assertion may fail). - bool Try() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return lock_.Try(); } + bool Try(subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_TRYLOCK_FUNCTION(true) { + return lock_.Try(); + } // Null implementation if not debug. void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK() {} @@ -45,25 +52,13 @@ class LOCKABLE BASE_EXPORT Lock { #else ~Lock(); - // NOTE: We do not permit recursive locks and will commonly fire a DCHECK() if - // a thread attempts to acquire the lock a second time (while already holding - // it). - void Acquire() EXCLUSIVE_LOCK_FUNCTION() { - lock_.Lock(); - CheckUnheldAndMark(); - } - void Release() UNLOCK_FUNCTION() { - CheckHeldAndUnmark(); - lock_.Unlock(); - } - - bool Try() EXCLUSIVE_TRYLOCK_FUNCTION(true) { - bool rv = lock_.Try(); - if (rv) { - CheckUnheldAndMark(); - } - return rv; - } + // Note: Acquiring a lock that is already held by the calling thread is not + // supported and results in a CHECK() failure. + void Acquire(subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_LOCK_FUNCTION(); + void Release() UNLOCK_FUNCTION(); + bool Try(subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_TRYLOCK_FUNCTION(true); void AssertAcquired() const ASSERT_EXCLUSIVE_LOCK(); void AssertNotHeld() const; @@ -93,17 +88,22 @@ class LOCKABLE BASE_EXPORT Lock { private: #if DCHECK_IS_ON() - // Members and routines taking care of locks assertions. - // Note that this checks for recursive locks and allows them - // if the variable is set. This is allowed by the underlying implementation - // on windows but not on Posix, so we're doing unneeded checks on Posix. - // It's worth it to share the code. + // Check that `owning_thread_ref_` refers to the current thread and unset it. void CheckHeldAndUnmark(); + // Check that `owning_thread_ref_` is null and set it to the current thread. void CheckUnheldAndMark(); - // All private data is implicitly protected by lock_. - // Be VERY careful to only access members under that lock. + // Adds/removes this lock to/from the thread-local list returned by + // `subtle::GetLocksHeldByCurrentThread()`, unless tracking is disabled. + void AddToLocksHeldOnCurrentThread(); + void RemoveFromLocksHeldOnCurrentThread(); + + // Reference to the thread holding the lock. Protected by `lock_`. base::PlatformThreadRef owning_thread_ref_; + + // Whether the lock is currently in the list of locks held by a thread. When + // true, the lock is removed from the list upon `Release()`. + bool in_tracked_locks_held_by_current_thread_ = false; #endif // DCHECK_IS_ON() // Platform specific underlying lock implementation. diff --git a/naiveproxy/src/base/synchronization/lock_impl.h b/naiveproxy/src/base/synchronization/lock_impl.h index 6289b0a9a8..d098516399 100644 --- a/naiveproxy/src/base/synchronization/lock_impl.h +++ b/naiveproxy/src/base/synchronization/lock_impl.h @@ -5,11 +5,14 @@ #ifndef BASE_SYNCHRONIZATION_LOCK_IMPL_H_ #define BASE_SYNCHRONIZATION_LOCK_IMPL_H_ +#include + #include "base/base_export.h" #include "base/check.h" #include "base/dcheck_is_on.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/memory/stack_allocated.h" +#include "base/synchronization/lock_subtle.h" #include "base/thread_annotations.h" #include "build/build_config.h" @@ -136,9 +139,12 @@ class SCOPED_LOCKABLE BasicAutoLock { public: struct AlreadyAcquired {}; - explicit BasicAutoLock(LockType& lock) EXCLUSIVE_LOCK_FUNCTION(lock) + explicit BasicAutoLock( + LockType& lock, + subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_LOCK_FUNCTION(lock) : lock_(lock) { - lock_.Acquire(); + lock_.Acquire(tracking); } BasicAutoLock(LockType& lock, const AlreadyAcquired&) @@ -164,9 +170,12 @@ class SCOPED_LOCKABLE BasicAutoLock { template class SCOPED_LOCKABLE BasicMovableAutoLock { public: - explicit BasicMovableAutoLock(LockType& lock) EXCLUSIVE_LOCK_FUNCTION(lock) + explicit BasicMovableAutoLock( + LockType& lock, + subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_LOCK_FUNCTION(lock) : lock_(&lock) { - lock_->Acquire(); + lock_->Acquire(tracking); } BasicMovableAutoLock(const BasicMovableAutoLock&) = delete; @@ -200,8 +209,11 @@ class SCOPED_LOCKABLE BasicAutoTryLock { // caller that checks `is_acquired()` before writing to guarded data would be // flagged with "writing variable 'foo' requires holding 'lock' exclusively." // See . - explicit BasicAutoTryLock(LockType& lock) LOCKS_EXCLUDED(lock) - : lock_(lock), is_acquired_(lock_.Try()) {} + explicit BasicAutoTryLock( + LockType& lock, + subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + LOCKS_EXCLUDED(lock) + : lock_(lock), is_acquired_(lock_.Try(tracking)) {} BasicAutoTryLock(const BasicAutoTryLock&) = delete; BasicAutoTryLock& operator=(const BasicAutoTryLock&) = delete; @@ -249,10 +261,13 @@ class SCOPED_LOCKABLE BasicAutoLockMaybe { STACK_ALLOCATED(); public: - explicit BasicAutoLockMaybe(LockType* lock) EXCLUSIVE_LOCK_FUNCTION(lock) + explicit BasicAutoLockMaybe( + LockType* lock, + subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_LOCK_FUNCTION(lock) : lock_(lock) { if (lock_) - lock_->Acquire(); + lock_->Acquire(tracking); } BasicAutoLockMaybe(const BasicAutoLockMaybe&) = delete; @@ -276,10 +291,13 @@ class SCOPED_LOCKABLE BasicReleasableAutoLock { STACK_ALLOCATED(); public: - explicit BasicReleasableAutoLock(LockType* lock) EXCLUSIVE_LOCK_FUNCTION(lock) + explicit BasicReleasableAutoLock( + LockType* lock, + subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_LOCK_FUNCTION(lock) : lock_(lock) { DCHECK(lock_); - lock_->Acquire(); + lock_->Acquire(tracking); } BasicReleasableAutoLock(const BasicReleasableAutoLock&) = delete; diff --git a/naiveproxy/src/base/synchronization/lock_subtle.h b/naiveproxy/src/base/synchronization/lock_subtle.h index b2968d457a..cc99dcfa96 100644 --- a/naiveproxy/src/base/synchronization/lock_subtle.h +++ b/naiveproxy/src/base/synchronization/lock_subtle.h @@ -13,31 +13,30 @@ namespace base::subtle { #if DCHECK_IS_ON() -// Returns addresses of locks held by the current thread. `uintptr_t` is used -// because addresses are meant to be used as unique identifiers but not to be -// dereferenced. -BASE_EXPORT span GetLocksHeldByCurrentThread(); +// Returns addresses of locks acquired by the current thread with +// `subtle::LockTracking::kEnabled`. `uintptr_t` is used because addresses are +// meant to be used as unique identifiers but not to be dereferenced. +BASE_EXPORT span GetTrackedLocksHeldByCurrentThread(); #endif -// Creates a scope in which acquired locks aren't tracked by -// `GetLocksHeldByCurrentThread()`. This is required in rare circumstances where -// the number of locks held simultaneously by a thread may exceed the -// fixed-sized thread-local storage. A lock which isn't tracked by -// `GetLocksHeldByCurrentThread()` cannot be used to satisfy a -// `SequenceChecker`. -class BASE_EXPORT [[maybe_unused]] DoNotTrackLocks { -#if DCHECK_IS_ON() - public: - DoNotTrackLocks(); - ~DoNotTrackLocks(); - - private: - AutoReset auto_reset_; -#else - public: - DoNotTrackLocks() = default; - ~DoNotTrackLocks() = default; -#endif // DCHECK_IS_ON() +// Whether to add a lock to the list returned by +// `subtle::GetLocksHeldByCurrentThread()` upon acquisition. This has no effect +// in non-DCHECK builds because tracking is always disabled. This is disabled by +// default to avoid exceeding the fixed-size storage backing +// `GetTrackedLocksHeldByCurrentThread()` and to avoid reentrancy, e.g.: +// +// thread_local implementation +// Add lock to the thread_local array of locks held by current thread +// base::Lock::Acquire from allocator shim +// ... Allocator shim ... +// thread_local implementation +// Access to a thread_local variable +// +// A lock acquired with `subtle::LockTracking::kEnabled` can be used to provide +// a mutual exclusion guarantee for SEQUENCE_CHECKER. +enum class LockTracking { + kDisabled, + kEnabled, }; } // namespace base::subtle diff --git a/naiveproxy/src/base/synchronization/waitable_event.h b/naiveproxy/src/base/synchronization/waitable_event.h index abdd2cc768..e067e22d28 100644 --- a/naiveproxy/src/base/synchronization/waitable_event.h +++ b/naiveproxy/src/base/synchronization/waitable_event.h @@ -87,7 +87,7 @@ class BASE_EXPORT WaitableEvent { // Returns true if the event is in the signaled state, else false. If this // is not a manual reset event, then this test will cause a reset. - bool IsSignaled(); + bool IsSignaled() const; // Wait indefinitely for the event to be signaled. Wait's return "happens // after" |Signal| has completed. This means that it's safe for a diff --git a/naiveproxy/src/base/synchronization/waitable_event_apple.cc b/naiveproxy/src/base/synchronization/waitable_event_apple.cc index 668d52c023..59d295fbfd 100644 --- a/naiveproxy/src/base/synchronization/waitable_event_apple.cc +++ b/naiveproxy/src/base/synchronization/waitable_event_apple.cc @@ -64,7 +64,7 @@ void WaitableEvent::SignalImpl() { MACH_CHECK(kr == KERN_SUCCESS || kr == MACH_SEND_TIMED_OUT, kr) << "mach_msg"; } -bool WaitableEvent::IsSignaled() { +bool WaitableEvent::IsSignaled() const { return PeekPort(receive_right_->Name(), policy_ == ResetPolicy::AUTOMATIC); } diff --git a/naiveproxy/src/base/synchronization/waitable_event_posix.cc b/naiveproxy/src/base/synchronization/waitable_event_posix.cc index 2dadd7310f..8c07f52d31 100644 --- a/naiveproxy/src/base/synchronization/waitable_event_posix.cc +++ b/naiveproxy/src/base/synchronization/waitable_event_posix.cc @@ -20,7 +20,6 @@ #include "base/ranges/algorithm.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" -#include "base/synchronization/lock_subtle.h" #include "base/threading/scoped_blocking_call.h" #include "base/threading/thread_restrictions.h" #include "base/time/time.h" @@ -78,7 +77,7 @@ void WaitableEvent::SignalImpl() { } } -bool WaitableEvent::IsSignaled() { +bool WaitableEvent::IsSignaled() const { base::AutoLock locked(kernel_->lock_); const bool result = kernel_->signaled_; @@ -325,13 +324,6 @@ size_t WaitableEvent::WaitManyImpl(WaitableEvent** raw_waitables, size_t WaitableEvent::EnqueueMany(std::pair* waitables, size_t count, Waiter* waiter) NO_THREAD_SAFETY_ANALYSIS { - // This scope may bring the number of locks held on the thread above the - // fixed-sized thread local storage used by `GetLocksHeldByCurrentThread()` - // (this was observed with the "WaitSetTest.NoStarvation" test but not in - // production). Disable tracking, at the cost of not being able to use these - // locks to guarantee mutual exclusion in `SequenceChecker`. - subtle::DoNotTrackLocks do_not_track_locks; - size_t winner = count; size_t winner_index = count; for (size_t i = 0; i < count; ++i) { diff --git a/naiveproxy/src/base/synchronization/waitable_event_win.cc b/naiveproxy/src/base/synchronization/waitable_event_win.cc index c6a64719ed..67a5806178 100644 --- a/naiveproxy/src/base/synchronization/waitable_event_win.cc +++ b/naiveproxy/src/base/synchronization/waitable_event_win.cc @@ -62,7 +62,7 @@ void WaitableEvent::SignalImpl() { SetEvent(handle_.get()); } -bool WaitableEvent::IsSignaled() { +bool WaitableEvent::IsSignaled() const { DWORD result = WaitForSingleObject(handle_.get(), 0); if (result != WAIT_OBJECT_0 && result != WAIT_TIMEOUT) { ReportInvalidWaitableEventResult(result); diff --git a/naiveproxy/src/base/system/sys_info.cc b/naiveproxy/src/base/system/sys_info.cc index 38bde5a139..b74d655071 100644 --- a/naiveproxy/src/base/system/sys_info.cc +++ b/naiveproxy/src/base/system/sys_info.cc @@ -21,13 +21,11 @@ namespace base { namespace { -#if BUILDFLAG(IS_IOS) -// For M99, 45% of devices have 2GB of RAM, and 55% have more. -constexpr uint64_t kLowMemoryDeviceThresholdMB = 1024; -#else -// Updated Desktop default threshold to match the Android 2021 definition. -constexpr uint64_t kLowMemoryDeviceThresholdMB = 2048; -#endif +uint64_t GetLowMemoryDeviceThresholdMB() { + static const uint64_t threshold = base::saturated_cast( + features::kLowMemoryDeviceThresholdMB.Get()); + return threshold; +} std::optional g_amount_of_physical_memory_mb_for_testing; } // namespace @@ -67,7 +65,7 @@ uint64_t SysInfo::AmountOfAvailablePhysicalMemory() { // from the fake |kLowMemoryDeviceThresholdMB| limit. uint64_t memory_used = AmountOfPhysicalMemoryImpl() - AmountOfAvailablePhysicalMemoryImpl(); - uint64_t memory_limit = kLowMemoryDeviceThresholdMB * 1024 * 1024; + uint64_t memory_limit = GetLowMemoryDeviceThresholdMB() * 1024 * 1024; // std::min ensures no underflow, as |memory_used| can be > |memory_limit|. return memory_limit - std::min(memory_used, memory_limit); } @@ -207,7 +205,7 @@ bool DetectLowEndDevice() { int ram_size_mb = SysInfo::AmountOfPhysicalMemoryMB(); return ram_size_mb > 0 && - static_cast(ram_size_mb) <= kLowMemoryDeviceThresholdMB; + static_cast(ram_size_mb) <= GetLowMemoryDeviceThresholdMB(); } // static diff --git a/naiveproxy/src/base/system/sys_info_android.cc b/naiveproxy/src/base/system/sys_info_android.cc index d4b3059270..bc726fd5fc 100644 --- a/naiveproxy/src/base/system/sys_info_android.cc +++ b/naiveproxy/src/base/system/sys_info_android.cc @@ -12,7 +12,6 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/system/sys_info_internal.h" diff --git a/naiveproxy/src/base/system/sys_info_chromeos.cc b/naiveproxy/src/base/system/sys_info_chromeos.cc index 11206415ec..c0def643ec 100644 --- a/naiveproxy/src/base/system/sys_info_chromeos.cc +++ b/naiveproxy/src/base/system/sys_info_chromeos.cc @@ -20,7 +20,6 @@ #include "base/no_destructor.h" #include "base/notreached.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" diff --git a/naiveproxy/src/base/system/sys_info_fuchsia.cc b/naiveproxy/src/base/system/sys_info_fuchsia.cc index 12e075ac1f..0f9efc8065 100644 --- a/naiveproxy/src/base/system/sys_info_fuchsia.cc +++ b/naiveproxy/src/base/system/sys_info_fuchsia.cc @@ -19,7 +19,6 @@ #include "base/no_destructor.h" #include "base/notimplemented.h" #include "base/numerics/clamped_math.h" -#include "base/strings/string_piece.h" #include "base/synchronization/lock.h" #include "base/threading/scoped_blocking_call.h" #include "build/build_config.h" diff --git a/naiveproxy/src/base/task/common/checked_lock_impl.cc b/naiveproxy/src/base/task/common/checked_lock_impl.cc index b6285db464..36951b8351 100644 --- a/naiveproxy/src/base/task/common/checked_lock_impl.cc +++ b/naiveproxy/src/base/task/common/checked_lock_impl.cc @@ -142,8 +142,7 @@ LazyInstance::Leaky g_safe_acquisition_tracker = CheckedLockImpl::CheckedLockImpl() : CheckedLockImpl(nullptr) {} -CheckedLockImpl::CheckedLockImpl(const CheckedLockImpl* predecessor) - : is_universal_predecessor_(false) { +CheckedLockImpl::CheckedLockImpl(const CheckedLockImpl* predecessor) { DCHECK(predecessor == nullptr || !predecessor->is_universal_successor_); g_safe_acquisition_tracker.Get().RegisterLock(this, predecessor); } @@ -164,8 +163,8 @@ void CheckedLockImpl::AssertNoLockHeldOnCurrentThread() { g_safe_acquisition_tracker.Get().AssertNoLockHeldOnCurrentThread(); } -void CheckedLockImpl::Acquire() { - lock_.Acquire(); +void CheckedLockImpl::Acquire(subtle::LockTracking tracking) { + lock_.Acquire(tracking); g_safe_acquisition_tracker.Get().RecordAcquisition(this); } diff --git a/naiveproxy/src/base/task/common/checked_lock_impl.h b/naiveproxy/src/base/task/common/checked_lock_impl.h index 84ea56ed47..b49e15eafa 100644 --- a/naiveproxy/src/base/task/common/checked_lock_impl.h +++ b/naiveproxy/src/base/task/common/checked_lock_impl.h @@ -37,7 +37,8 @@ class BASE_EXPORT CheckedLockImpl { static void AssertNoLockHeldOnCurrentThread(); - void Acquire() EXCLUSIVE_LOCK_FUNCTION(lock_); + void Acquire(subtle::LockTracking tracking = subtle::LockTracking::kDisabled) + EXCLUSIVE_LOCK_FUNCTION(lock_); void Release() UNLOCK_FUNCTION(lock_); void AssertAcquired() const; diff --git a/naiveproxy/src/base/task/common/operations_controller.h b/naiveproxy/src/base/task/common/operations_controller.h index f1949e31fb..e2f6cd1d8c 100644 --- a/naiveproxy/src/base/task/common/operations_controller.h +++ b/naiveproxy/src/base/task/common/operations_controller.h @@ -9,7 +9,7 @@ #include #include "base/base_export.h" -#include "base/memory/raw_ptr_exclusion.h" +#include "base/memory/stack_allocated.h" #include "base/synchronization/waitable_event.h" namespace base { @@ -62,6 +62,8 @@ class BASE_EXPORT OperationsController { // // This class is thread-safe class OperationToken { + STACK_ALLOCATED(); + public: ~OperationToken() { if (outer_) @@ -79,9 +81,7 @@ class BASE_EXPORT OperationsController { friend class OperationsController; explicit OperationToken(OperationsController* outer) : outer_(outer) {} - // `outer_` is not a raw_ptr<...> for performance reasons (based on analysis - // of sampling profiler data and tab_search:top100:2020). - RAW_PTR_EXCLUSION OperationsController* outer_; + OperationsController* outer_; }; OperationsController(); diff --git a/naiveproxy/src/base/task/current_thread.h b/naiveproxy/src/base/task/current_thread.h index 6e21e7299a..66382e91c7 100644 --- a/naiveproxy/src/base/task/current_thread.h +++ b/naiveproxy/src/base/task/current_thread.h @@ -24,7 +24,7 @@ #include "build/build_config.h" namespace autofill { -class NextIdleTimeTicks; +class NextIdleBarrier; } namespace content { @@ -149,9 +149,9 @@ class BASE_EXPORT CurrentThread { // to run. class RegisterOnNextIdleCallbackPasskey { private: - RegisterOnNextIdleCallbackPasskey() {} + RegisterOnNextIdleCallbackPasskey() = default; - friend autofill::NextIdleTimeTicks; + friend autofill::NextIdleBarrier; friend content::BrowserMainLoop; friend bool test::RunUntil(FunctionRef); friend void test::TestPredicateOrRegisterOnNextIdleCallback( diff --git a/naiveproxy/src/base/task/sequence_manager/lazily_deallocated_deque.h b/naiveproxy/src/base/task/sequence_manager/lazily_deallocated_deque.h index 7781074491..73edc796af 100644 --- a/naiveproxy/src/base/task/sequence_manager/lazily_deallocated_deque.h +++ b/naiveproxy/src/base/task/sequence_manager/lazily_deallocated_deque.h @@ -19,6 +19,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr_exclusion.h" +#include "base/memory/raw_span.h" #include "base/time/time.h" namespace base { @@ -315,7 +316,7 @@ class LazilyDeallocatedDeque { size_t front_index_ = 0; size_t back_index_ = 0; std::unique_ptr backing_store_; - base::span data_; + base::raw_span data_; std::unique_ptr next_ = nullptr; }; diff --git a/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.h b/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.h index 90855b0be0..4817792019 100644 --- a/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.h +++ b/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.h @@ -309,7 +309,9 @@ class BASE_EXPORT SequenceManagerImpl std::optional metrics_subsampler; internal::TaskQueueSelector selector; - ObserverList::UncheckedAndDanglingUntriaged task_observers; + // RAW_PTR_EXCLUSION: Performance reasons(based on analysis of + // speedometer3). + ObserverList::UncheckedAndRawPtrExcluded task_observers; ObserverList task_time_observers; const raw_ptr default_clock; raw_ptr time_domain = nullptr; diff --git a/naiveproxy/src/base/task/sequence_manager/tasks.cc b/naiveproxy/src/base/task/sequence_manager/tasks.cc index 5bf10c72f5..44010aa7d5 100644 --- a/naiveproxy/src/base/task/sequence_manager/tasks.cc +++ b/naiveproxy/src/base/task/sequence_manager/tasks.cc @@ -79,7 +79,6 @@ HeapHandle Task::GetHeapHandle() const { bool Task::IsCanceled() const { CHECK(task); if (task.IsCancelled()) { - DCHECK(!delayed_task_handle_delegate_); return true; } diff --git a/naiveproxy/src/base/task/sequenced_task_runner.h b/naiveproxy/src/base/task/sequenced_task_runner.h index d5a6d286b0..cfae0eb214 100644 --- a/naiveproxy/src/base/task/sequenced_task_runner.h +++ b/naiveproxy/src/base/task/sequenced_task_runner.h @@ -20,6 +20,7 @@ namespace blink { class LowPrecisionTimer; +class ScriptedIdleTaskController; class TimerBase; class TimerBasedTickProvider; class WebRtcTaskQueue; @@ -67,6 +68,7 @@ class PostDelayedTaskPassKey { friend class base::DeadlineTimer; friend class base::MetronomeTimer; friend class blink::LowPrecisionTimer; + friend class blink::ScriptedIdleTaskController; friend class blink::TimerBase; friend class blink::TimerBasedTickProvider; friend class blink::WebRtcTaskQueue; diff --git a/naiveproxy/src/base/task/thread_pool/service_thread.cc b/naiveproxy/src/base/task/thread_pool/service_thread.cc index d20511266c..9aaf0932e4 100644 --- a/naiveproxy/src/base/task/thread_pool/service_thread.cc +++ b/naiveproxy/src/base/task/thread_pool/service_thread.cc @@ -13,9 +13,7 @@ ServiceThread::ServiceThread() : Thread("ThreadPoolServiceThread") {} NOINLINE void ServiceThread::Run(RunLoop* run_loop) { Thread::Run(run_loop); - // Inhibit tail calls of Run and inhibit code folding. - const int line_number = __LINE__; - base::debug::Alias(&line_number); + NO_CODE_FOLDING(); } } // namespace internal diff --git a/naiveproxy/src/base/task/thread_pool/task_tracker.cc b/naiveproxy/src/base/task/thread_pool/task_tracker.cc index 684d0d68fe..1a60e671d4 100644 --- a/naiveproxy/src/base/task/thread_pool/task_tracker.cc +++ b/naiveproxy/src/base/task/thread_pool/task_tracker.cc @@ -243,7 +243,7 @@ void TaskTracker::StartShutdown() { DCHECK(!shutdown_event_); DCHECK(!state_->HasShutdownStarted()); - shutdown_event_ = std::make_unique(); + shutdown_event_.emplace(); const bool tasks_are_blocking_shutdown = state_->StartShutdown(); diff --git a/naiveproxy/src/base/task/thread_pool/task_tracker.h b/naiveproxy/src/base/task/thread_pool/task_tracker.h index b010bb8775..b030fc5aa3 100644 --- a/naiveproxy/src/base/task/thread_pool/task_tracker.h +++ b/naiveproxy/src/base/task/thread_pool/task_tracker.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -18,7 +19,6 @@ #include "base/containers/circular_deque.h" #include "base/functional/callback_forward.h" #include "base/sequence_checker.h" -#include "base/strings/string_piece.h" #include "base/synchronization/waitable_event.h" #include "base/task/common/checked_lock.h" #include "base/task/common/task_annotator.h" @@ -272,7 +272,7 @@ class BASE_EXPORT TaskTracker { // Event instantiated when shutdown starts and signaled when shutdown // completes. - std::unique_ptr shutdown_event_ GUARDED_BY(shutdown_lock_); + std::optional shutdown_event_ GUARDED_BY(shutdown_lock_); // Used to generate unique |PendingTask::sequence_num| when posting tasks. AtomicSequenceNumber sequence_nums_; diff --git a/naiveproxy/src/base/task/thread_pool/worker_thread.cc b/naiveproxy/src/base/task/thread_pool/worker_thread.cc index 03b3b2946e..bf23bfdd85 100644 --- a/naiveproxy/src/base/task/thread_pool/worker_thread.cc +++ b/naiveproxy/src/base/task/thread_pool/worker_thread.cc @@ -25,7 +25,7 @@ #include "base/time/time_override.h" #include "base/trace_event/base_tracing.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_config.h" #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA) diff --git a/naiveproxy/src/base/template_util.h b/naiveproxy/src/base/template_util.h deleted file mode 100644 index c14bacffd2..0000000000 --- a/naiveproxy/src/base/template_util.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2011 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TEMPLATE_UTIL_H_ -#define BASE_TEMPLATE_UTIL_H_ - -#include - -#include -#include - -namespace base { - -namespace internal { - -// Used to detect whether the given type is an iterator. This is normally used -// with std::enable_if to provide disambiguation for functions that take -// templatzed iterators as input. -template -struct is_iterator : std::false_type {}; - -template -struct is_iterator< - T, - std::void_t::iterator_category>> - : std::true_type {}; - -// Helper to express preferences in an overload set. If more than one overload -// are available for a given set of parameters the overload with the higher -// priority will be chosen. -template -struct priority_tag : priority_tag {}; - -template <> -struct priority_tag<0> {}; - -} // namespace internal - -} // namespace base - -#endif // BASE_TEMPLATE_UTIL_H_ diff --git a/naiveproxy/src/base/test/BUILD.gn b/naiveproxy/src/base/test/BUILD.gn index a60a2c1de0..f7afbfba3f 100644 --- a/naiveproxy/src/base/test/BUILD.gn +++ b/naiveproxy/src/base/test/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") import("//build/compiled_action.gni") import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") @@ -57,6 +58,8 @@ static_library("test_support") { "bind.h", "copy_only_int.cc", "copy_only_int.h", + "fuzztest_init_helper.cc", + "fuzztest_init_helper.h", "gmock_callback_support.h", "gmock_expected_support.h", "gmock_move_support.h", @@ -76,6 +79,8 @@ static_library("test_support") { "launcher/test_result.h", "launcher/test_results_tracker.h", "launcher/unit_test_launcher.h", + "metrics/action_suffix_reader.cc", + "metrics/action_suffix_reader.h", "metrics/histogram_enum_reader.cc", "metrics/histogram_enum_reader.h", "metrics/histogram_tester.cc", @@ -91,6 +96,7 @@ static_library("test_support") { "mock_entropy_provider.h", "mock_log.cc", "mock_log.h", + "move_only_int.cc", "move_only_int.h", "multiprocess_test.h", "null_task_runner.cc", @@ -183,7 +189,6 @@ static_library("test_support") { deps = [ ":proto_test_support", "//build:chromeos_buildflags", - "//third_party/fuzztest:init_helper", "//third_party/google_benchmark", "//third_party/icu:icuuc", "//third_party/libxml:libxml_utils", @@ -648,11 +653,15 @@ if (is_android) { "android/javatests/src/org/chromium/base/test/transit/ActivityElement.java", "android/javatests/src/org/chromium/base/test/transit/BatchedPublicTransitRule.java", "android/javatests/src/org/chromium/base/test/transit/CallbackCondition.java", + "android/javatests/src/org/chromium/base/test/transit/CarryOn.java", "android/javatests/src/org/chromium/base/test/transit/Condition.java", "android/javatests/src/org/chromium/base/test/transit/ConditionChecker.java", "android/javatests/src/org/chromium/base/test/transit/ConditionStatus.java", + "android/javatests/src/org/chromium/base/test/transit/ConditionStatusWithResult.java", "android/javatests/src/org/chromium/base/test/transit/ConditionWaiter.java", + "android/javatests/src/org/chromium/base/test/transit/ConditionWithResult.java", "android/javatests/src/org/chromium/base/test/transit/ConditionalState.java", + "android/javatests/src/org/chromium/base/test/transit/ElementFactory.java", "android/javatests/src/org/chromium/base/test/transit/ElementInState.java", "android/javatests/src/org/chromium/base/test/transit/Elements.java", "android/javatests/src/org/chromium/base/test/transit/EntryPointSentinelStation.java", @@ -662,6 +671,7 @@ if (is_android) { "android/javatests/src/org/chromium/base/test/transit/FacilitySwap.java", "android/javatests/src/org/chromium/base/test/transit/InstrumentationThreadCondition.java", "android/javatests/src/org/chromium/base/test/transit/LogicalElement.java", + "android/javatests/src/org/chromium/base/test/transit/MoreViewConditions.java", "android/javatests/src/org/chromium/base/test/transit/PublicTransitConfig.java", "android/javatests/src/org/chromium/base/test/transit/ScrollableFacility.java", "android/javatests/src/org/chromium/base/test/transit/Station.java", @@ -677,6 +687,20 @@ if (is_android) { "android/javatests/src/org/chromium/base/test/transit/ViewElementInState.java", ] } + + robolectric_library("public_transit_robolectric_tests_java") { + deps = [ + ":public_transit_java", + "//base:base_java_test_support", + "//base:base_junit_test_support", + "//base:callback_java", + "//third_party/junit", + ] + + sources = [ + "android/javatests/src/org/chromium/base/test/transit/TripUnitTest.java", + ] + } } source_set("fuzztest_support") { @@ -687,3 +711,21 @@ source_set("fuzztest_support") { "//third_party/fuzztest:fuzztest_internal", ] } + +buildflag_header("confirm_fuzztest_init_buildflags") { + header = "confirm_fuzztest_init_buildflags.h" + flags = + [ "REGISTER_FUZZTESTS_IN_TEST_SUITES=$register_fuzztests_in_test_suites" ] +} + +# Contains a static initializer which will arrange for fuzztests to be +# registered. Usually invoked from testing/test.gni +source_set("confirm_fuzztest_init") { + sources = [ "confirm_fuzztest_init.cc" ] + testonly = true + deps = [ + ":confirm_fuzztest_init_buildflags", + ":test_support", + "//third_party/fuzztest:init_fuzztest", + ] +} diff --git a/naiveproxy/src/base/test/copy_only_int.cc b/naiveproxy/src/base/test/copy_only_int.cc index bda48854db..a2c23d6c10 100644 --- a/naiveproxy/src/base/test/copy_only_int.cc +++ b/naiveproxy/src/base/test/copy_only_int.cc @@ -4,9 +4,26 @@ #include "base/test/copy_only_int.h" +#include + +#include "base/functional/callback.h" +#include "base/no_destructor.h" + namespace base { // static int CopyOnlyInt::num_copies_ = 0; +CopyOnlyInt::~CopyOnlyInt() { + int old_data = std::exchange(data_, 0); + if (GetDestructionCallbackStorage()) { + GetDestructionCallbackStorage().Run(old_data); + } +} + +RepeatingCallback& CopyOnlyInt::GetDestructionCallbackStorage() { + static NoDestructor> callback; + return *callback; +} + } // namespace base diff --git a/naiveproxy/src/base/test/copy_only_int.h b/naiveproxy/src/base/test/copy_only_int.h index 4580977010..a81c72f475 100644 --- a/naiveproxy/src/base/test/copy_only_int.h +++ b/naiveproxy/src/base/test/copy_only_int.h @@ -5,6 +5,10 @@ #ifndef BASE_TEST_COPY_ONLY_INT_H_ #define BASE_TEST_COPY_ONLY_INT_H_ +#include + +#include "base/functional/callback.h" +#include "third_party/abseil-cpp/absl/cleanup/cleanup.h" namespace base { @@ -14,31 +18,12 @@ class CopyOnlyInt { public: explicit CopyOnlyInt(int data = 1) : data_(data) {} CopyOnlyInt(const CopyOnlyInt& other) : data_(other.data_) { ++num_copies_; } - ~CopyOnlyInt() { data_ = 0; } + ~CopyOnlyInt(); - friend bool operator==(const CopyOnlyInt& lhs, const CopyOnlyInt& rhs) { - return lhs.data_ == rhs.data_; - } - - friend bool operator!=(const CopyOnlyInt& lhs, const CopyOnlyInt& rhs) { - return !operator==(lhs, rhs); - } - - friend bool operator<(const CopyOnlyInt& lhs, const CopyOnlyInt& rhs) { - return lhs.data_ < rhs.data_; - } - - friend bool operator>(const CopyOnlyInt& lhs, const CopyOnlyInt& rhs) { - return rhs < lhs; - } - - friend bool operator<=(const CopyOnlyInt& lhs, const CopyOnlyInt& rhs) { - return !(rhs < lhs); - } - - friend bool operator>=(const CopyOnlyInt& lhs, const CopyOnlyInt& rhs) { - return !(lhs < rhs); - } + friend bool operator==(const CopyOnlyInt& lhs, + const CopyOnlyInt& rhs) = default; + friend auto operator<=>(const CopyOnlyInt& lhs, + const CopyOnlyInt& rhs) = default; int data() const { return data_; } @@ -46,7 +31,18 @@ class CopyOnlyInt { static int num_copies() { return num_copies_; } + // Called with the value of `data()` when an instance of `CopyOnlyInt` is + // destroyed. Returns an `absl::Cleanup` scoper that automatically + // unregisters the callback when the scoper is destroyed. + static auto SetScopedDestructionCallback( + RepeatingCallback callback) { + GetDestructionCallbackStorage() = std::move(callback); + return absl::Cleanup([] { GetDestructionCallbackStorage().Reset(); }); + } + private: + static RepeatingCallback& GetDestructionCallbackStorage(); + volatile int data_; static int num_copies_; diff --git a/naiveproxy/src/base/test/launcher/unit_test_launcher.cc b/naiveproxy/src/base/test/launcher/unit_test_launcher.cc index 86409bca4d..2e39e2fb4d 100644 --- a/naiveproxy/src/base/test/launcher/unit_test_launcher.cc +++ b/naiveproxy/src/base/test/launcher/unit_test_launcher.cc @@ -30,6 +30,7 @@ #include "base/task/single_thread_task_executor.h" #include "base/task/single_thread_task_runner.h" #include "base/test/allow_check_is_test_for_testing.h" +#include "base/test/fuzztest_init_helper.h" #include "base/test/launcher/test_launcher.h" #include "base/test/scoped_block_tests_writing_to_special_dirs.h" #include "base/test/test_switches.h" @@ -271,11 +272,28 @@ int LaunchUnitTestsInternal(RunTestSuiteCallback run_test_suite, void InitGoogleTestChar(int* argc, char** argv) { testing::InitGoogleTest(argc, argv); + MaybeInitFuzztest(*argc, argv); } #if BUILDFLAG(IS_WIN) -void InitGoogleTestWChar(int* argc, wchar_t** argv) { + +// Safety: as is normal in command lines, argc and argv must correspond +// to one another. Otherwise there will be out-of-bounds accesses. +UNSAFE_BUFFER_USAGE void InitGoogleTestWChar(int* argc, wchar_t** argv) { testing::InitGoogleTest(argc, argv); + // Fuzztest requires a narrow command-line. + CHECK(*argc >= 0); + base::span wide_command_line = + UNSAFE_BUFFERS(base::make_span(argv, static_cast(*argc))); + std::vector narrow_command_line; + std::vector narrow_command_line_pointers; + narrow_command_line.reserve(*argc); + narrow_command_line_pointers.reserve(*argc); + for (int i = 0; i < *argc; i++) { + narrow_command_line.push_back(WideToUTF8(wide_command_line[i])); + narrow_command_line_pointers.push_back(narrow_command_line[i].data()); + } + MaybeInitFuzztest(*argc, narrow_command_line_pointers.data()); } #endif // BUILDFLAG(IS_WIN) diff --git a/naiveproxy/src/base/test/metrics/action_suffix_reader.cc b/naiveproxy/src/base/test/metrics/action_suffix_reader.cc new file mode 100644 index 0000000000..a34123be56 --- /dev/null +++ b/naiveproxy/src/base/test/metrics/action_suffix_reader.cc @@ -0,0 +1,189 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/metrics/action_suffix_reader.h" + +#include +#include +#include +#include +#include + +#include "base/base_paths.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/strings/stringprintf.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libxml/chromium/xml_reader.h" + +namespace base { + +namespace { + +// Extracts suffixes from a histograms.xml if the suffixes apply to +// `affected_action`, otherwise null. +// +// Expects |reader| to point at the starting node of the suffixes block. +// +// Returns map { name => label } on success, and nullopt on failure. +std::optional ParseActionSuffixesFromActionsXml( + const std::string& affected_action, + XmlReader& reader) { + ActionSuffixEntryMap result; + std::vector failures; + bool action_found = false; + + while (true) { + // Because reader initially points to the start of the + // element, and because and elements are not + // nested, when the closing tag is reached, parsing is complete. + const std::string node_name = reader.NodeName(); + if (node_name == "action-suffix" && reader.IsClosingElement()) { + break; + } + + std::string name; + + // Affected actions can be anywhere in the XML block, so just check if the + // one the caller cares about is present. + if (node_name == "affected-action" && reader.NodeAttribute("name", &name) && + name == affected_action) { + action_found = true; + } + + // The other thing found in this block is the list of suffixes. Capture them + // all, recording failures, and then later the list will be returned if the + // action was found. + if (node_name == "suffix") { + std::string label; + const bool has_name = reader.NodeAttribute("name", &name); + const bool has_label = reader.NodeAttribute("label", &label); + + if (!has_name) { + failures.emplace_back(StringPrintf( + "Bad suffix entry with label \"%s\"; no 'name' attribute.", + label.c_str())); + } + + if (!has_label) { + failures.emplace_back(StringPrintf( + "Bad suffix entry with name \"%s\"; no 'label' attribute.", + name.c_str())); + } + + // Don't check label here because we want to check for duplicate names, + // and if there was a missing label the function has already failed. + if (has_name) { + const auto insert_result = result.emplace(name, label); + if (!insert_result.second) { + failures.emplace_back( + StringPrintf("Duplicate suffix name \"%s\"", name.c_str())); + } + } + } + + // All variant entries are on the same level, so advance to the next + // sibling. + reader.Next(); + } + + if (!action_found) { + return std::nullopt; + } + + if (!failures.empty()) { + for (const auto& failure : failures) { + ADD_FAILURE() << failure; + } + return std::nullopt; + } + + return result; +} + +std::vector ReadActionSuffixesForActionImpl( + XmlReader& reader, + const std::string& affected_action) { + std::vector result; + + // Implement simple depth first search. + while (true) { + const std::string node_name = reader.NodeName(); + if (node_name == "action-suffix") { + // Try to step into the node. + if (reader.Read()) { + const auto suffixes = + ParseActionSuffixesFromActionsXml(affected_action, reader); + if (suffixes) { + result.emplace_back(std::move(*suffixes)); + } + } + } + + // Go deeper if possible (stops at the closing tag of the deepest node). + if (reader.Read()) { + continue; + } + + // Try next node on the same level (skips closing tag). + if (reader.Next()) { + continue; + } + + // Go up until next node on the same level exists. + while (reader.Depth() && !reader.SkipToElement()) { + } + + // Reached top. actions.xml consists of the single top level node 'actions', + // so this is the end. + if (!reader.Depth()) { + break; + } + } + + return result; +} + +} // namespace + +// Hidden function that reads from `xml_string` instead of actions.xml. +// Used to unit test the internal logic. +std::vector ReadActionSuffixesForActionForTesting( + const std::string& xml_string, + const std::string& affected_action) { + XmlReader reader; + CHECK(reader.Load(xml_string)); + return ReadActionSuffixesForActionImpl(reader, affected_action); +} + +std::vector ReadActionSuffixesForAction( + const std::string& affected_action) { + FilePath src_root; + if (!PathService::Get(DIR_SRC_TEST_DATA_ROOT, &src_root)) { + ADD_FAILURE() << "Failed to get src root."; + return {}; + } + + const FilePath path = src_root.AppendASCII("tools") + .AppendASCII("metrics") + .AppendASCII("actions") + .AppendASCII("actions.xml"); + + if (!PathExists(path)) { + ADD_FAILURE() << "File does not exist: " << path; + return {}; + } + + XmlReader reader; + if (!reader.LoadFile(path.MaybeAsASCII())) { + ADD_FAILURE() << "Failed to load " << path; + return {}; + } + + return ReadActionSuffixesForActionImpl(reader, affected_action); +} + +} // namespace base diff --git a/naiveproxy/src/base/test/metrics/action_suffix_reader.h b/naiveproxy/src/base/test/metrics/action_suffix_reader.h new file mode 100644 index 0000000000..db362cc0f4 --- /dev/null +++ b/naiveproxy/src/base/test/metrics/action_suffix_reader.h @@ -0,0 +1,39 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TEST_METRICS_ACTION_SUFFIX_READER_H_ +#define BASE_TEST_METRICS_ACTION_SUFFIX_READER_H_ + +#include +#include +#include +#include + +namespace base { + +using ActionSuffixEntryMap = std::map; + +// Find and read the suffixes list(s) which apply to the given `affected_action` +// in actions.xml. +// +// Useful for when you want to verify that the set of suffixes associated with +// a particular action contains expected values. For example, +// BrowserUserEducationServiceTest.CheckFeaturePromoActions verifies that for +// every registered Chrome Desktop in-product-help experience, there is a +// corresponding suffix for recording UserEducation.MessageAction* actions. This +// prevents someone from adding an IPH experience without adding the +// corresponding action entry. +// +// Returns a list of maps, each of which corresponds to one list of suffixes +// associated with the action (an `` could theoretically show +// up in more than one `` block.) +// +// If no suffix list is found, returns an empty list. May generate test errors +// on malformed/duplicate entries even if valid suffixes are found. +extern std::vector ReadActionSuffixesForAction( + const std::string& affected_action); + +} // namespace base + +#endif // BASE_TEST_METRICS_ACTION_SUFFIX_READER_H_ diff --git a/naiveproxy/src/base/test/metrics/histogram_tester.cc b/naiveproxy/src/base/test/metrics/histogram_tester.cc index c92812ef4b..735ec63976 100644 --- a/naiveproxy/src/base/test/metrics/histogram_tester.cc +++ b/naiveproxy/src/base/test/metrics/histogram_tester.cc @@ -185,7 +185,7 @@ void HistogramTester::GetBucketCountForSamples( HistogramTester::CountsMap HistogramTester::GetTotalCountsForPrefix( std::string_view prefix) const { - EXPECT_TRUE(prefix.find('.') != StringPiece::npos) + EXPECT_TRUE(prefix.find('.') != std::string_view::npos) << "|prefix| ought to contain at least one period, to avoid matching too" << " many histograms."; diff --git a/naiveproxy/src/base/test/move_only_int.cc b/naiveproxy/src/base/test/move_only_int.cc new file mode 100644 index 0000000000..309a3a2dbe --- /dev/null +++ b/naiveproxy/src/base/test/move_only_int.cc @@ -0,0 +1,26 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/move_only_int.h" + +#include + +#include "base/functional/callback.h" +#include "base/no_destructor.h" + +namespace base { + +MoveOnlyInt::~MoveOnlyInt() { + int old_data = std::exchange(data_, 0); + if (GetDestructionCallbackStorage()) { + GetDestructionCallbackStorage().Run(old_data); + } +} + +RepeatingCallback& MoveOnlyInt::GetDestructionCallbackStorage() { + static NoDestructor> callback; + return *callback; +} + +} // namespace base diff --git a/naiveproxy/src/base/test/move_only_int.h b/naiveproxy/src/base/test/move_only_int.h index 1a2ac66258..5ee0d2168f 100644 --- a/naiveproxy/src/base/test/move_only_int.h +++ b/naiveproxy/src/base/test/move_only_int.h @@ -5,6 +5,11 @@ #ifndef BASE_TEST_MOVE_ONLY_INT_H_ #define BASE_TEST_MOVE_ONLY_INT_H_ +#include + +#include "base/functional/callback.h" +#include "third_party/abseil-cpp/absl/cleanup/cleanup.h" + namespace base { // A move-only class that holds an integer. This is designed for testing @@ -17,7 +22,7 @@ class MoveOnlyInt { MoveOnlyInt(const MoveOnlyInt&) = delete; MoveOnlyInt& operator=(const MoveOnlyInt&) = delete; - ~MoveOnlyInt() { data_ = 0; } + ~MoveOnlyInt(); MoveOnlyInt& operator=(MoveOnlyInt&& other) { data_ = other.data_; @@ -25,41 +30,38 @@ class MoveOnlyInt { return *this; } - friend bool operator==(const MoveOnlyInt& lhs, const MoveOnlyInt& rhs) { - return lhs.data_ == rhs.data_; - } + friend bool operator==(const MoveOnlyInt& lhs, + const MoveOnlyInt& rhs) = default; + friend auto operator<=>(const MoveOnlyInt& lhs, + const MoveOnlyInt& rhs) = default; - friend bool operator!=(const MoveOnlyInt& lhs, const MoveOnlyInt& rhs) { - return !operator==(lhs, rhs); + friend bool operator==(const MoveOnlyInt& lhs, int rhs) { + return lhs.data_ == rhs; } - - friend bool operator<(const MoveOnlyInt& lhs, int rhs) { - return lhs.data_ < rhs; + friend bool operator==(int lhs, const MoveOnlyInt& rhs) { + return lhs == rhs.data_; } - - friend bool operator<(int lhs, const MoveOnlyInt& rhs) { - return lhs < rhs.data_; + friend auto operator<=>(const MoveOnlyInt& lhs, int rhs) { + return lhs.data_ <=> rhs; } - - friend bool operator<(const MoveOnlyInt& lhs, const MoveOnlyInt& rhs) { - return lhs.data_ < rhs.data_; - } - - friend bool operator>(const MoveOnlyInt& lhs, const MoveOnlyInt& rhs) { - return rhs < lhs; - } - - friend bool operator<=(const MoveOnlyInt& lhs, const MoveOnlyInt& rhs) { - return !(rhs < lhs); - } - - friend bool operator>=(const MoveOnlyInt& lhs, const MoveOnlyInt& rhs) { - return !(lhs < rhs); + friend auto operator<=>(int lhs, const MoveOnlyInt& rhs) { + return lhs <=> rhs.data_; } int data() const { return data_; } + // Called with the value of `data()` when an instance of `MoveOnlyInt` is + // destroyed. Returns an `absl::Cleanup` scoper that automatically + // unregisters the callback when the scoper is destroyed. + static auto SetScopedDestructionCallback( + RepeatingCallback callback) { + GetDestructionCallbackStorage() = std::move(callback); + return absl::Cleanup([] { GetDestructionCallbackStorage().Reset(); }); + } + private: + static RepeatingCallback& GetDestructionCallbackStorage(); + volatile int data_; }; diff --git a/naiveproxy/src/base/test/multiprocess_test_android.cc b/naiveproxy/src/base/test/multiprocess_test_android.cc index ea3204a3f5..62a12af7cd 100644 --- a/naiveproxy/src/base/test/multiprocess_test_android.cc +++ b/naiveproxy/src/base/test/multiprocess_test_android.cc @@ -5,8 +5,10 @@ #include "base/test/multiprocess_test.h" #include + #include +#include "base/android/binder_box.h" #include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/scoped_java_ref.h" @@ -51,8 +53,9 @@ Process SpawnMultiProcessTestChild(const std::string& procname, android::ScopedJavaLocalRef j_argv = android::ToJavaArrayOfStrings(env, command_line.argv()); + jint pid = android::Java_MultiprocessTestClientLauncher_launchClient( - env, j_argv, fds); + env, j_argv, fds, base::android::PackBinderBox(env, options.binders)); return Process(pid); } diff --git a/naiveproxy/src/base/test/test_future.h b/naiveproxy/src/base/test/test_future.h index 5e1d87a0f1..49be3eb210 100644 --- a/naiveproxy/src/base/test/test_future.h +++ b/naiveproxy/src/base/test/test_future.h @@ -547,6 +547,77 @@ class TestFuture { TestFuture implementation_; }; +// A gmock action that when invoked will store the argument values and +// unblock any waiters. The action must be invoked on the sequence the +// TestFuture was created on. +// +// Usually the action will be used with `WillOnce()` and only invoked once, +// but if you consume the value with `Take()` or `Clear()` it is safe to +// invoke it again. +// +// Example usage: +// TestFuture future; +// +// EXPECT_CALL(delegate, OnReadComplete) +// .WillOnce(InvokeFuture(future)); +// +// object_under_test.Read(buffer, 16); +// +// EXPECT_EQ(future.Take(), 16); +// +// +// +// Implementation note: this is not implemented using the MATCHER_P macro as the +// C++03-compatible way it implements varargs would make this too verbose. +// Instead, it takes advantage of the ability to pass a functor to .WillOnce() +// and .WillRepeatedly(). +template +class InvokeFuture { + public: + // The TestFuture must be an lvalue. Passing an rvalue would make no sense as + // you wouldn't be able to call Take() on it afterwards. + explicit InvokeFuture(TestFuture& future) + : callback_(future.GetRepeatingCallback()) {} + + // GMock actions must be copyable. + InvokeFuture(const InvokeFuture&) = default; + InvokeFuture& operator=(const InvokeFuture&) = default; + + // WillOnce() can take advantage of move constructors. + InvokeFuture(InvokeFuture&&) = default; + InvokeFuture& operator=(InvokeFuture&&) = default; + + void operator()(Types... values) { + callback_.Run(std::forward(values)...); + } + + private: + RepeatingCallback callback_; +}; + +// Specialization for TestFuture. +template <> +class InvokeFuture { + public: + explicit InvokeFuture(TestFuture& future) + : closure_(future.GetRepeatingCallback()) {} + + InvokeFuture(const InvokeFuture&) = default; + InvokeFuture& operator=(const InvokeFuture&) = default; + InvokeFuture(InvokeFuture&&) = default; + InvokeFuture& operator=(InvokeFuture&&) = default; + + void operator()() { closure_.Run(); } + + private: + RepeatingClosure closure_; +}; + +// Deduction guide so the compiler can choose the correct specialisation of +// InvokeFuture. +template +InvokeFuture(TestFuture&) -> InvokeFuture; + } // namespace base::test #endif // BASE_TEST_TEST_FUTURE_H_ diff --git a/naiveproxy/src/base/test/test_suite.cc b/naiveproxy/src/base/test/test_suite.cc index 692ce3d0de..fb40e14e62 100644 --- a/naiveproxy/src/base/test/test_suite.cc +++ b/naiveproxy/src/base/test/test_suite.cc @@ -44,6 +44,7 @@ #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool/thread_pool_instance.h" +#include "base/test/fuzztest_init_helper.h" #include "base/test/gtest_xml_unittest_result_printer.h" #include "base/test/gtest_xml_util.h" #include "base/test/icu_test_util.h" @@ -58,12 +59,11 @@ #include "base/time/time.h" #include "base/tracing_buildflags.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/tagging.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" -#include "third_party/fuzztest/init_helper.h" #if BUILDFLAG(IS_APPLE) #include "base/apple/scoped_nsautorelease_pool.h" @@ -664,16 +664,7 @@ void TestSuite::InitializeFromCommandLine(int* argc, char** argv) { // CommandLine::Init() is called earlier from PreInitialize(). testing::InitGoogleTest(argc, argv); testing::InitGoogleMock(argc, argv); - - // Make a copy of argc/argv for the sake of InitFuzzTest, which will store - // it and attempt to use it later after other Chromium code might have - // changed it. - for (int i = 0; i < *argc; i++) { - fuzztest_argv_raw_.push_back(argv[i]); - } - fuzztest_argc_ = fuzztest_argv_raw_.size(); - fuzztest_argv_ptr_ = fuzztest_argv_raw_.data(); - MaybeInitFuzztest(&fuzztest_argc_, &fuzztest_argv_ptr_); + MaybeInitFuzztest(*argc, argv); #if BUILDFLAG(IS_IOS) InitIOSArgs(*argc, argv); diff --git a/naiveproxy/src/base/test/test_suite.h b/naiveproxy/src/base/test/test_suite.h index 209115aed8..15c5b8f971 100644 --- a/naiveproxy/src/base/test/test_suite.h +++ b/naiveproxy/src/base/test/test_suite.h @@ -115,15 +115,6 @@ class TestSuite { std::vector argv_as_strings_; #endif raw_ptr argv_; - // An extra copy of the command line for FuzzTest, since it stores - // it and relies on using it later, after other Chromium code might - // have modified the real argv/argc. - // We need fuzztest_argv_raw_.data() to have type char**, so we can't use - // raw_ptr here. - RAW_PTR_EXCLUSION std::vector fuzztest_argv_raw_; - int fuzztest_argc_; - // We need fuzztest_argv_ptr_ to have type char**, - RAW_PTR_EXCLUSION char** fuzztest_argv_ptr_; }; } // namespace base diff --git a/naiveproxy/src/base/third_party/nspr/README.chromium b/naiveproxy/src/base/third_party/nspr/README.chromium index fb44f50dae..e794cbb6ac 100644 --- a/naiveproxy/src/base/third_party/nspr/README.chromium +++ b/naiveproxy/src/base/third_party/nspr/README.chromium @@ -1,5 +1,7 @@ Name: Netscape Portable Runtime (NSPR) -URL: http://www.mozilla.org/projects/nspr/ +URL: https://hg.mozilla.org/projects/nspr +Revision: dd5b9aa4631b350ba58e2e83106724808fd9a97f License: MPL 1.1/GPL 2.0/LGPL 2.1 License File: LICENSE +Security Critical: yes Shipped: yes diff --git a/naiveproxy/src/base/third_party/superfasthash/OWNERS b/naiveproxy/src/base/third_party/superfasthash/OWNERS deleted file mode 100644 index 633cc350a8..0000000000 --- a/naiveproxy/src/base/third_party/superfasthash/OWNERS +++ /dev/null @@ -1 +0,0 @@ -mgiuca@chromium.org diff --git a/naiveproxy/src/base/third_party/superfasthash/README.chromium b/naiveproxy/src/base/third_party/superfasthash/README.chromium index 35ac47cf01..9a3fa0bee1 100644 --- a/naiveproxy/src/base/third_party/superfasthash/README.chromium +++ b/naiveproxy/src/base/third_party/superfasthash/README.chromium @@ -17,6 +17,7 @@ Local Modifications: - #include instead of "pstdint.h". - #include . - Added casts. +- Fix some undefined behavior (signed left-shift overflow, bad pointer cast) The license is a standard 3-clause BSD license with the following minor changes: diff --git a/naiveproxy/src/base/third_party/superfasthash/superfasthash.c b/naiveproxy/src/base/third_party/superfasthash/superfasthash.c index 5401f510bc..d740d4c4f2 100644 --- a/naiveproxy/src/base/third_party/superfasthash/superfasthash.c +++ b/naiveproxy/src/base/third_party/superfasthash/superfasthash.c @@ -27,16 +27,9 @@ #include #include -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif -#if !defined (get16bits) #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif uint32_t SuperFastHash (const char * data, int len) { uint32_t hash = (uint32_t)len, tmp; @@ -60,8 +53,7 @@ int rem; switch (rem) { case 3: hash += get16bits (data); hash ^= hash << 16; - hash ^= - (uint32_t)(((signed char)data[sizeof (uint16_t)]) << 18); + hash ^= (uint32_t)(signed char)data[sizeof (uint16_t)] << 18; hash += hash >> 11; break; case 2: hash += get16bits (data); diff --git a/naiveproxy/src/base/third_party/xdg_user_dirs/README.chromium b/naiveproxy/src/base/third_party/xdg_user_dirs/README.chromium index baca9fb599..6edfaa4508 100644 --- a/naiveproxy/src/base/third_party/xdg_user_dirs/README.chromium +++ b/naiveproxy/src/base/third_party/xdg_user_dirs/README.chromium @@ -1,5 +1,7 @@ Name: xdg-user-dirs URL: http://www.freedesktop.org/wiki/Software/xdg-user-dirs +Revision: 2f28f353ec3cf9288da70bab3ca963f2144808f0 +Date: 2009-02-26 License: MIT License File: LICENSE Shipped: yes diff --git a/naiveproxy/src/base/threading/platform_thread_apple.mm b/naiveproxy/src/base/threading/platform_thread_apple.mm index 86f4c428d5..b7cf09e999 100644 --- a/naiveproxy/src/base/threading/platform_thread_apple.mm +++ b/naiveproxy/src/base/threading/platform_thread_apple.mm @@ -93,10 +93,6 @@ BASE_FEATURE(kOptimizedRealtimeThreadingMac, #endif ); -BASE_FEATURE(kUserInteractiveCompositingMac, - "UserInteractiveCompositingMac", - FEATURE_ENABLED_BY_DEFAULT); - namespace { bool IsOptimizedRealtimeThreadingMacEnabled() { @@ -116,8 +112,6 @@ const FeatureParam kOptimizedRealtimeThreadingMacBusy{ // (kOptimizedRealtimeThreadingMacBusy, 1]. const FeatureParam kOptimizedRealtimeThreadingMacBusyLimit{ &kOptimizedRealtimeThreadingMac, "busy_limit", 1.0}; -std::atomic g_user_interactive_compositing( - kUserInteractiveCompositingMac.default_state == FEATURE_ENABLED_BY_DEFAULT); namespace { @@ -149,8 +143,6 @@ void PlatformThreadApple::InitializeFeatures() { g_time_constraints.store(TimeConstraints::ReadFromFeatureParams()); g_use_optimized_realtime_threading.store( IsOptimizedRealtimeThreadingMacEnabled()); - g_user_interactive_compositing.store( - FeatureList::IsEnabled(kUserInteractiveCompositingMac)); } // static @@ -295,18 +287,6 @@ namespace internal { void SetCurrentThreadTypeImpl(ThreadType thread_type, MessagePumpType pump_type_hint) { - // Changing the priority of the main thread causes performance - // regressions. https://crbug.com/601270 - // TODO(crbug.com/40209052): Remove this check. kCompositing is the - // default on Mac, so this check is counter intuitive. - if ([[NSThread currentThread] isMainThread] && - thread_type >= ThreadType::kCompositing && - !g_user_interactive_compositing.load(std::memory_order_relaxed)) { - DCHECK(thread_type == ThreadType::kDefault || - thread_type == ThreadType::kCompositing); - return; - } - switch (thread_type) { case ThreadType::kBackground: pthread_set_qos_class_self_np(QOS_CLASS_BACKGROUND, 0); @@ -321,12 +301,6 @@ void SetCurrentThreadTypeImpl(ThreadType thread_type, pthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0); break; case ThreadType::kCompositing: - if (g_user_interactive_compositing.load(std::memory_order_relaxed)) { - pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0); - } else { - pthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0); - } - break; case ThreadType::kDisplayCritical: { pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0); break; diff --git a/naiveproxy/src/base/threading/platform_thread_posix.cc b/naiveproxy/src/base/threading/platform_thread_posix.cc index c3091909a3..6f26203506 100644 --- a/naiveproxy/src/base/threading/platform_thread_posix.cc +++ b/naiveproxy/src/base/threading/platform_thread_posix.cc @@ -26,7 +26,7 @@ #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_NACL) #include "base/posix/can_lower_nice_to.h" diff --git a/naiveproxy/src/base/threading/platform_thread_win.cc b/naiveproxy/src/base/threading/platform_thread_win.cc index 7dfc06977f..91967355b6 100644 --- a/naiveproxy/src/base/threading/platform_thread_win.cc +++ b/naiveproxy/src/base/threading/platform_thread_win.cc @@ -29,7 +29,7 @@ #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #include "partition_alloc/stack/stack.h" diff --git a/naiveproxy/src/base/threading/scoped_blocking_call.h b/naiveproxy/src/base/threading/scoped_blocking_call.h index 1f37ca2159..95d140132f 100644 --- a/naiveproxy/src/base/threading/scoped_blocking_call.h +++ b/naiveproxy/src/base/threading/scoped_blocking_call.h @@ -8,7 +8,6 @@ #include "base/base_export.h" #include "base/functional/callback_forward.h" #include "base/location.h" -#include "base/strings/string_piece.h" #include "base/threading/scoped_blocking_call_internal.h" #include "base/types/strong_alias.h" diff --git a/naiveproxy/src/base/threading/thread.h b/naiveproxy/src/base/threading/thread.h index 4707ec3a66..073a3d87b7 100644 --- a/naiveproxy/src/base/threading/thread.h +++ b/naiveproxy/src/base/threading/thread.h @@ -12,6 +12,7 @@ #include "base/base_export.h" #include "base/check.h" +#include "base/compiler_specific.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/message_loop/message_pump_type.h" @@ -259,8 +260,9 @@ class BASE_EXPORT Thread : PlatformThread::Delegate { // Called just prior to starting the message loop virtual void Init() {} - // Called to start the run loop - virtual void Run(RunLoop* run_loop); + // Called to start the run loop. Inhibit tail calls to this function so that + // the caller will be on the stack for profiling and crash analysis. + NOT_TAIL_CALLED virtual void Run(RunLoop* run_loop); // Called just after the message loop ends virtual void CleanUp() {} diff --git a/naiveproxy/src/base/threading/thread_restrictions.h b/naiveproxy/src/base/threading/thread_restrictions.h index fca9f03283..1bc39182f8 100644 --- a/naiveproxy/src/base/threading/thread_restrictions.h +++ b/naiveproxy/src/base/threading/thread_restrictions.h @@ -158,9 +158,10 @@ StartupProfilePathInfo GetStartupProfilePath( const base::CommandLine& command_line, bool ignore_profile_picker); -bool EnsureBrowserStateDirectoriesCreated(const base::FilePath&, - const base::FilePath&, - const base::FilePath&); +int EnsureBrowserStateDirectoriesCreated(const base::FilePath&, + const base::FilePath&, + const base::FilePath&); + Profile* GetLastProfileMac(); bool HasWaylandDisplay(base::Environment* env); @@ -675,9 +676,9 @@ class BASE_EXPORT [[maybe_unused, nodiscard]] ScopedAllowBlocking { #endif // Sorted by function name (with namespace), ignoring the return type. - friend bool ::EnsureBrowserStateDirectoriesCreated(const base::FilePath&, - const base::FilePath&, - const base::FilePath&); + friend int ::EnsureBrowserStateDirectoriesCreated(const base::FilePath&, + const base::FilePath&, + const base::FilePath&); friend Profile* ::GetLastProfileMac(); // http://crbug.com/1176734 // Note: This function return syntax is required so the "::" doesn't get // mis-parsed. See https://godbolt.org/z/KGhnPxfc8 for the issue. diff --git a/naiveproxy/src/base/time/time.cc b/naiveproxy/src/base/time/time.cc index 60d1cb7fc4..216a0336c8 100644 --- a/naiveproxy/src/base/time/time.cc +++ b/naiveproxy/src/base/time/time.cc @@ -280,6 +280,11 @@ LiveTicks LiveTicksNowIgnoringOverride() { #endif +std::ostream& operator<<(std::ostream& os, LiveTicks live_ticks) { + const TimeDelta as_time_delta = live_ticks - LiveTicks(); + return os << as_time_delta.InMicroseconds() << " bogo-live-microseconds"; +} + // ThreadTicks ---------------------------------------------------------------- // static diff --git a/naiveproxy/src/base/time/time.h b/naiveproxy/src/base/time/time.h index 2868c2da36..67062cf05e 100644 --- a/naiveproxy/src/base/time/time.h +++ b/naiveproxy/src/base/time/time.h @@ -1318,10 +1318,26 @@ class BASE_EXPORT LiveTicks : public time_internal::TimeBase { constexpr explicit LiveTicks(int64_t us) : TimeBase(us) {} }; +// For logging use only. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, LiveTicks live_ticks); + // ThreadTicks ---------------------------------------------------------------- -// Represents a clock, specific to a particular thread, than runs only while the -// thread is running. +// Represents a thread-specific clock that runs only while the thread is +// scheduled. This has the effect of counting time spent actually executing +// code, but not time spent blocked (e.g. on I/O), or ready and waiting to be +// run. +// +// Note: This is typically significantly more expensive than TimeTicks. For +// instance, on Linux-based systems, it requires a true system call, whereas +// TimeTicks::Now() calls are usually handled through the vDSO. This does not +// matter if a couple us of overhead is not important to you, but do not call +// this in a tight loop, or for sub-microsecond intervals. +// +// For instance, in 2024 on a Linux system, in a simple loop: +// - TimeTicks::Now() takes 27ns per loop iteration +// - ThreadTicks::Now() takes 875ns per loop iteration. Actual cost is likely +// higher in Chromium due to the sandbox (seccomp-BPF). class BASE_EXPORT ThreadTicks : public time_internal::TimeBase { public: constexpr ThreadTicks() : TimeBase(0) {} diff --git a/naiveproxy/src/base/time/time_delta_from_string.cc b/naiveproxy/src/base/time/time_delta_from_string.cc index a70e801167..8d3120b055 100644 --- a/naiveproxy/src/base/time/time_delta_from_string.cc +++ b/naiveproxy/src/base/time/time_delta_from_string.cc @@ -57,7 +57,7 @@ struct ParsedDecimal { constexpr std::optional ConsumeDurationNumber( std::string_view& number_string) { ParsedDecimal res; - StringPiece::const_iterator orig_start = number_string.begin(); + std::string_view::const_iterator orig_start = number_string.begin(); // Parse contiguous digits. for (; !number_string.empty(); number_string.remove_prefix(1)) { const int d = number_string.front() - '0'; diff --git a/naiveproxy/src/base/timer/timer.cc b/naiveproxy/src/base/timer/timer.cc index c7d1bf3fc7..9c5aabde26 100644 --- a/naiveproxy/src/base/timer/timer.cc +++ b/naiveproxy/src/base/timer/timer.cc @@ -180,7 +180,7 @@ void OneShotTimer::RunUserTask() { } void OneShotTimer::EnsureNonNullUserTask() { - DCHECK(user_task_); + CHECK(user_task_); } RepeatingTimer::RepeatingTimer() = default; diff --git a/naiveproxy/src/base/token.cc b/naiveproxy/src/base/token.cc index 9cd562f176..01d692f111 100644 --- a/naiveproxy/src/base/token.cc +++ b/naiveproxy/src/base/token.cc @@ -12,12 +12,12 @@ #include #include +#include #include "base/check.h" #include "base/hash/hash.h" #include "base/pickle.h" #include "base/rand_util.h" -#include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" namespace base { @@ -40,7 +40,7 @@ std::string Token::ToString() const { } // static -std::optional Token::FromString(StringPiece string_representation) { +std::optional Token::FromString(std::string_view string_representation) { if (string_representation.size() != 32) { return std::nullopt; } diff --git a/naiveproxy/src/base/token.h b/naiveproxy/src/base/token.h index 2d9d039f79..1f432418fe 100644 --- a/naiveproxy/src/base/token.h +++ b/naiveproxy/src/base/token.h @@ -15,10 +15,10 @@ #include #include #include +#include #include "base/base_export.h" #include "base/containers/span.h" -#include "base/strings/string_piece.h" namespace base { @@ -66,7 +66,8 @@ class BASE_EXPORT Token { // FromString is the opposite of ToString. It returns std::nullopt if the // |string_representation| is invalid. - static std::optional FromString(StringPiece string_representation); + static std::optional FromString( + std::string_view string_representation); private: // Note: Two uint64_t are used instead of uint8_t[16] in order to have a diff --git a/naiveproxy/src/base/trace_event/address_space_dump_provider.cc b/naiveproxy/src/base/trace_event/address_space_dump_provider.cc index d90d4f8e46..67d394c865 100644 --- a/naiveproxy/src/base/trace_event/address_space_dump_provider.cc +++ b/naiveproxy/src/base/trace_event/address_space_dump_provider.cc @@ -8,7 +8,7 @@ #include "base/trace_event/memory_allocator_dump.h" #include "base/trace_event/process_memory_dump.h" #include "partition_alloc/address_pool_manager.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_constants.h" namespace base::trace_event { diff --git a/naiveproxy/src/base/trace_event/builtin_categories.h b/naiveproxy/src/base/trace_event/builtin_categories.h index a3da4353d4..560313ed41 100644 --- a/naiveproxy/src/base/trace_event/builtin_categories.h +++ b/naiveproxy/src/base/trace_event/builtin_categories.h @@ -365,6 +365,7 @@ X("input,rail") \ X("input,input.scrolling") \ X("input,views") \ + X("interactions,input.scrolling") \ X("interactions,startup") \ X("ipc,security") \ X("ipc,toplevel") \ diff --git a/naiveproxy/src/base/trace_event/etw_interceptor_win.cc b/naiveproxy/src/base/trace_event/etw_interceptor_win.cc index 2d75fdebcc..3db233f64f 100644 --- a/naiveproxy/src/base/trace_event/etw_interceptor_win.cc +++ b/naiveproxy/src/base/trace_event/etw_interceptor_win.cc @@ -4,20 +4,215 @@ #include "base/trace_event/etw_interceptor_win.h" +#include +#include + #include "base/containers/flat_map.h" #include "base/time/time.h" #include "base/trace_event/trace_event_etw_export_win.h" +#include "third_party/abseil-cpp/absl/container/inlined_vector.h" +#include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/perfetto/protos/perfetto/common/interceptor_descriptor.gen.h" #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h" namespace base::trace_event { +namespace { +template +concept EtwFieldWithDataDescType = EtwFieldBaseType && requires(T t) { + { t.GetDataDescCount() } -> std::same_as; +}; + +template +struct EventDataDescTraits; + +template +struct EventDataDescTraits>> { + static const T* GetAddress(const T& value) noexcept { + return const_cast(&value); + } + static ULONG GetSize(const T& value) noexcept { return sizeof(value); } +}; + +template <> +struct EventDataDescTraits { + static const char* GetAddress(const std::string& value) noexcept { + return value.c_str(); + } + static ULONG GetSize(const std::string& value) noexcept { + return static_cast(value.size() + 1); + } +}; + +class TlmFieldDebugAnnotation final : public TlmFieldBase { + public: + TlmFieldDebugAnnotation( + std::string_view name, + perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation); + ~TlmFieldDebugAnnotation(); + + void FillEventDescriptor(EVENT_DATA_DESCRIPTOR* descriptors) const noexcept; + + uint8_t GetDataDescCount() const noexcept; + uint8_t GetInType() const noexcept; + uint8_t GetOutType() const noexcept; + + // Copy operations are suppressed. Only declare move operations. + TlmFieldDebugAnnotation(TlmFieldDebugAnnotation&&) noexcept; + TlmFieldDebugAnnotation& operator=(TlmFieldDebugAnnotation&&) noexcept; + + private: + uint8_t data_desc_count_ = 1; + uint8_t in_type_ = 2 /* TlgInANSISTRING */; + uint8_t out_type_ = 0; + absl::variant value_; +}; + +TlmFieldDebugAnnotation::TlmFieldDebugAnnotation( + std::string_view name, + perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation) + : TlmFieldBase(name) { + CHECK_NE(Name(), nullptr); + + if (annotation.has_bool_value()) { + in_type_ = 4 /* TlgInUINT8 */; + out_type_ = 3 /* TlgOutBOOLEAN */; + value_ = annotation.bool_value(); + } else if (annotation.has_int_value()) { + in_type_ = 9; + value_ = annotation.int_value(); + } else if (annotation.has_uint_value()) { + in_type_ = 10; + value_ = annotation.uint_value(); + } else if (annotation.has_string_value()) { + in_type_ = 2 /* TlgInANSISTRING */; + value_.emplace(annotation.string_value().data, + annotation.string_value().size); + } else if (annotation.has_legacy_json_value()) { + in_type_ = 2 /* TlgInANSISTRING */; + value_.emplace(annotation.legacy_json_value().data, + annotation.legacy_json_value().size); + } else if (annotation.has_pointer_value()) { + in_type_ = 21 /* TlgInINTPTR */; + value_ = annotation.pointer_value(); + } else if (annotation.has_double_value()) { + in_type_ = 12 /* TlgInDOUBLE */; + value_ = annotation.double_value(); + } +} + +TlmFieldDebugAnnotation::~TlmFieldDebugAnnotation() {} + +TlmFieldDebugAnnotation::TlmFieldDebugAnnotation( + TlmFieldDebugAnnotation&&) noexcept = default; +TlmFieldDebugAnnotation& TlmFieldDebugAnnotation::operator=( + TlmFieldDebugAnnotation&&) noexcept = default; + +void TlmFieldDebugAnnotation::FillEventDescriptor( + EVENT_DATA_DESCRIPTOR* descriptors) const noexcept { + absl::visit( + [&](const T& arg) { + using Traits = EventDataDescTraits; + EventDataDescCreate(&descriptors[0], Traits::GetAddress(arg), + Traits::GetSize(arg)); + }, + value_); +} + +uint8_t TlmFieldDebugAnnotation::GetDataDescCount() const noexcept { + return data_desc_count_; +} + +uint8_t TlmFieldDebugAnnotation::GetInType() const noexcept { + return in_type_; +} + +uint8_t TlmFieldDebugAnnotation::GetOutType() const noexcept { + return out_type_; +} + +std::string_view GetDebugAnnotationName( + perfetto::TrackEventStateTracker::SequenceState& sequence_state, + const perfetto::protos::pbzero::DebugAnnotation_Decoder& annotation) { + protozero::ConstChars name{}; + if (const auto id = annotation.name_iid()) { + const auto& value = sequence_state.debug_annotation_names[id]; + name.data = value.data(); + name.size = value.size(); + } else if (annotation.has_name()) { + name.data = annotation.name().data; + name.size = annotation.name().size; + } + return std::string_view(name.data, name.size); +} +} // namespace + +class MultiEtwPayloadHandler final { + public: + MultiEtwPayloadHandler(TlmProvider* provider, + std::string_view event_name, + const EVENT_DESCRIPTOR& event_descriptor) + : provider_(provider), event_descriptor_(event_descriptor) { + is_enabled_ = provider_->IsEnabled(event_descriptor); + if (!is_enabled_) { + return; + } + metadata_index_ = provider_->EventBegin(metadata_, event_name); + } + + // Ensures that this function cannot be called with temporary objects. + template + void WriteField(const T&& value) = delete; + + // Caller needs to ensure that the `value` being passed is not destroyed, till + // `EventEnd` is called. + template + void WriteField(const T& value) { + if (!is_enabled_) { + return; + } + const int data_desc_count = value.GetDataDescCount(); + provider_->EventAddField(metadata_, &metadata_index_, value.GetInType(), + value.GetOutType(), value.Name()); + descriptors_.resize(descriptors_.size() + + static_cast(data_desc_count)); + + value.FillEventDescriptor(&descriptors_[descriptors_index_]); + descriptors_index_ += data_desc_count; + } + + ~MultiEtwPayloadHandler() { std::ignore = EventEnd(); } + + private: + ULONG EventEnd() { + if (!is_enabled_) { + return 0; + } + ULONG ret = + provider_->EventEnd(metadata_, metadata_index_, &descriptors_[0], + descriptors_index_, event_descriptor_); + return ret; + } + + raw_ptr provider_; + bool is_enabled_ = false; + char metadata_[TlmProvider::kMaxEventMetadataSize]{}; + uint16_t metadata_index_ = 0; + static constexpr int kMaxPossibleDescriptors = 6; + static constexpr int kMinPossibleDescriptors = 2; + uint8_t descriptors_index_ = kMinPossibleDescriptors; + absl::InlinedVector + descriptors_{kMinPossibleDescriptors}; + EVENT_DESCRIPTOR event_descriptor_; +}; + class ETWInterceptor::Delegate : public perfetto::TrackEventStateTracker::Delegate { public: - explicit Delegate(perfetto::LockedHandle locked_self) - : locked_self_(std::move(locked_self)) { + Delegate(perfetto::LockedHandle locked_self, + perfetto::TrackEventStateTracker::SequenceState& sequence_state) + : sequence_state_(sequence_state), locked_self_(std::move(locked_self)) { DCHECK(locked_self_); } ~Delegate() override; @@ -29,6 +224,7 @@ class ETWInterceptor::Delegate const perfetto::TrackEventStateTracker::ParsedTrackEvent&) override; private: + raw_ref sequence_state_; perfetto::LockedHandle locked_self_; }; @@ -62,26 +258,69 @@ void ETWInterceptor::Delegate::OnTrackEvent( DCHECK_NE(nullptr, phase_string); // TODO(crbug.com/40276149): Consider exporting thread time once // TrackEventStateTracker supports it. - if (event.track_event.type() == - perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END) { - locked_self_->provider_->WriteEvent( - std::string_view(event.name.data, event.name.size), - TlmEventDescriptor(0, keyword), - TlmMbcsStringField("Phase", phase_string), - TlmUInt64Field( - "Timestamp", - event.timestamp_ns / base::TimeTicks::kNanosecondsPerMicrosecond), - TlmUInt64Field( - "Duration", - event.duration_ns / base::TimeTicks::kNanosecondsPerMicrosecond)); + if (!event.track_event.has_debug_annotations()) { + if (event.track_event.type() == + perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END) { + locked_self_->provider_->WriteEvent( + std::string_view(event.name.data, event.name.size), + TlmEventDescriptor(0, keyword), + TlmMbcsStringField("Phase", phase_string), + TlmUInt64Field("Id", track.uuid), + TlmUInt64Field( + "Timestamp", + event.timestamp_ns / base::TimeTicks::kNanosecondsPerMicrosecond), + TlmUInt64Field( + "Duration", + event.duration_ns / base::TimeTicks::kNanosecondsPerMicrosecond)); + } else { + locked_self_->provider_->WriteEvent( + std::string_view(event.name.data, event.name.size), + TlmEventDescriptor(0, keyword), + TlmMbcsStringField("Phase", phase_string), + TlmUInt64Field("Id", track.uuid), + TlmUInt64Field("Timestamp", + event.timestamp_ns / + base::TimeTicks::kNanosecondsPerMicrosecond)); + } } else { - locked_self_->provider_->WriteEvent( - std::string_view(event.name.data, event.name.size), - TlmEventDescriptor(0, keyword), - TlmMbcsStringField("Phase", phase_string), - TlmUInt64Field( - "Timestamp", - event.timestamp_ns / base::TimeTicks::kNanosecondsPerMicrosecond)); + const auto event_descriptor = TlmEventDescriptor(0, keyword); + const std::string_view event_name(event.name.data, event.name.size); + + MultiEtwPayloadHandler etw_payload_handler(locked_self_->provider_, + event_name, event_descriptor); + const TlmMbcsStringField phase_event("Phase", phase_string); + etw_payload_handler.WriteField(phase_event); + + const TlmUInt64Field timestamp_field( + "Timestamp", + event.timestamp_ns / base::TimeTicks::kNanosecondsPerMicrosecond); + etw_payload_handler.WriteField(timestamp_field); + + const TlmUInt64Field id_field("Id", track.uuid); + etw_payload_handler.WriteField(id_field); + + std::optional duration_field; + if (event.track_event.type() == + perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END) { + duration_field.emplace( + "Duration", + event.duration_ns / base::TimeTicks::kNanosecondsPerMicrosecond); + etw_payload_handler.WriteField(*duration_field); + } + + // Add debug annotations. + static constexpr int kMaxDebugAnnotations = 2; + absl::InlinedVector + debug_fields; + for (auto it = event.track_event.debug_annotations(); it; ++it) { + perfetto::protos::pbzero::DebugAnnotation_Decoder annotation(*it); + debug_fields.emplace_back( + GetDebugAnnotationName(sequence_state_.get(), annotation), + annotation); + } + for (const auto& debug_field : debug_fields) { + etw_payload_handler.WriteField(debug_field); + } } } @@ -101,7 +340,7 @@ void ETWInterceptor::OnTracePacket(InterceptorContext context) { if (!locked_self) { return; } - Delegate delegate(std::move(locked_self)); + Delegate delegate(std::move(locked_self), tls.sequence_state); perfetto::protos::pbzero::TracePacket::Decoder packet( context.packet_data.data, context.packet_data.size); perfetto::TrackEventStateTracker::ProcessTracePacket( diff --git a/naiveproxy/src/base/trace_event/malloc_dump_provider.cc b/naiveproxy/src/base/trace_event/malloc_dump_provider.cc index be35a70639..e5140a9789 100644 --- a/naiveproxy/src/base/trace_event/malloc_dump_provider.cc +++ b/naiveproxy/src/base/trace_event/malloc_dump_provider.cc @@ -22,10 +22,9 @@ #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/traced_value.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_alloc_config.h" #include "partition_alloc/partition_bucket_lookup.h" -#include "partition_alloc/shim/nonscannable_allocator.h" #if BUILDFLAG(IS_APPLE) #include @@ -138,14 +137,6 @@ void ReportPartitionAllocStats(ProcessMemoryDump* pmd, original_allocator->DumpStats("original", is_light_dump, &partition_stats_dumper); } - auto& nonscannable_allocator = - allocator_shim::NonScannableAllocator::Instance(); - if (auto* root = nonscannable_allocator.root()) - root->DumpStats("nonscannable", is_light_dump, &partition_stats_dumper); - auto& nonquarantinable_allocator = - allocator_shim::NonQuarantinableAllocator::Instance(); - if (auto* root = nonquarantinable_allocator.root()) - root->DumpStats("nonquarantinable", is_light_dump, &partition_stats_dumper); *total_virtual_size += partition_stats_dumper.total_resident_bytes(); *resident_size += partition_stats_dumper.total_resident_bytes(); @@ -257,38 +248,24 @@ void ReportPartitionAllocThreadCacheStats( dump->AddScalar("metadata_overhead", MemoryAllocatorDump::kUnitsBytes, stats.metadata_overhead); - if (stats.alloc_count) { - int hit_rate_percent = - static_cast((100 * stats.alloc_hits) / stats.alloc_count); - base::UmaHistogramPercentage( - "Memory.PartitionAlloc.ThreadCache.HitRate" + metrics_suffix, - hit_rate_percent); - int batch_fill_rate_percent = - static_cast((100 * stats.batch_fill_count) / stats.alloc_count); - base::UmaHistogramPercentage( - "Memory.PartitionAlloc.ThreadCache.BatchFillRate" + metrics_suffix, - batch_fill_rate_percent); - #if PA_CONFIG(THREAD_CACHE_ALLOC_STATS) - if (detailed) { - partition_alloc::internal::BucketIndexLookup lookup{}; - std::string name = dump->absolute_name(); - for (size_t i = 0; i < partition_alloc::kNumBuckets; i++) { - size_t bucket_size = lookup.bucket_sizes()[i]; - if (bucket_size == partition_alloc::kInvalidBucketSize) - continue; - // Covers all normal buckets, that is up to ~1MiB, so 7 digits. - std::string dump_name = - base::StringPrintf("%s/buckets_alloc/%07d", name.c_str(), - static_cast(bucket_size)); - auto* buckets_alloc_dump = pmd->CreateAllocatorDump(dump_name); - buckets_alloc_dump->AddScalar("count", - MemoryAllocatorDump::kUnitsObjects, - stats.allocs_per_bucket_[i]); + if (stats.alloc_count && detailed) { + partition_alloc::internal::BucketIndexLookup lookup{}; + std::string name = dump->absolute_name(); + for (size_t i = 0; i < partition_alloc::kNumBuckets; i++) { + size_t bucket_size = lookup.bucket_sizes()[i]; + if (bucket_size == partition_alloc::kInvalidBucketSize) { + continue; } + // Covers all normal buckets, that is up to ~1MiB, so 7 digits. + std::string dump_name = base::StringPrintf( + "%s/buckets_alloc/%07d", name.c_str(), static_cast(bucket_size)); + auto* buckets_alloc_dump = pmd->CreateAllocatorDump(dump_name); + buckets_alloc_dump->AddScalar("count", MemoryAllocatorDump::kUnitsObjects, + stats.allocs_per_bucket_[i]); } -#endif // PA_CONFIG(THREAD_CACHE_ALLOC_STATS) } +#endif // PA_CONFIG(THREAD_CACHE_ALLOC_STATS) } void ReportPartitionAllocLightweightQuarantineStats( diff --git a/naiveproxy/src/base/trace_event/malloc_dump_provider.h b/naiveproxy/src/base/trace_event/malloc_dump_provider.h index bad2d4f9ef..ae3f02a048 100644 --- a/naiveproxy/src/base/trace_event/malloc_dump_provider.h +++ b/naiveproxy/src/base/trace_event/malloc_dump_provider.h @@ -14,7 +14,7 @@ #include "base/time/time.h" #include "base/trace_event/memory_dump_provider.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "partition_alloc/partition_stats.h" #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \ diff --git a/naiveproxy/src/base/trace_event/memory_dump_manager.cc b/naiveproxy/src/base/trace_event/memory_dump_manager.cc index 28813cd257..e8f073545c 100644 --- a/naiveproxy/src/base/trace_event/memory_dump_manager.cc +++ b/naiveproxy/src/base/trace_event/memory_dump_manager.cc @@ -37,7 +37,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "third_party/abseil-cpp/absl/base/dynamic_annotations.h" #if BUILDFLAG(IS_ANDROID) diff --git a/naiveproxy/src/base/trace_event/memory_infra_background_allowlist.cc b/naiveproxy/src/base/trace_event/memory_infra_background_allowlist.cc index 524bc705ff..c46c7e441f 100644 --- a/naiveproxy/src/base/trace_event/memory_infra_background_allowlist.cc +++ b/naiveproxy/src/base/trace_event/memory_infra_background_allowlist.cc @@ -17,7 +17,7 @@ #include "base/containers/fixed_flat_set.h" #include "base/strings/string_util.h" #include "build/build_config.h" -#include "partition_alloc/partition_alloc_buildflags.h" +#include "partition_alloc/buildflags.h" #include "third_party/abseil-cpp/absl/strings/ascii.h" #if BUILDFLAG(IS_ANDROID) @@ -247,6 +247,11 @@ constexpr auto kAllocatorDumpNameAllowlist = #endif "partition_alloc/partitions/layout", "skia/gpu_resources/context_0x?", + "skia/gpu_resources/graphite_context_0x?", + "skia/gpu_resources/gpu_main_graphite_image_provider_0x?", + "skia/gpu_resources/gpu_main_graphite_recorder_0x?", + "skia/gpu_resources/viz_compositor_graphite_image_provider_0x?", + "skia/gpu_resources/viz_compositor_graphite_recorder_0x?", "skia/sk_glyph_cache", "skia/sk_resource_cache", "sqlite", diff --git a/naiveproxy/src/base/trace_event/process_memory_dump.cc b/naiveproxy/src/base/trace_event/process_memory_dump.cc index cd7165a629..bf95e8b77a 100644 --- a/naiveproxy/src/base/trace_event/process_memory_dump.cc +++ b/naiveproxy/src/base/trace_event/process_memory_dump.cc @@ -16,6 +16,7 @@ #include #include "base/bits.h" +#include "base/containers/heap_array.h" #include "base/logging.h" #include "base/memory/page_size.h" #include "base/memory/ptr_util.h" @@ -115,13 +116,14 @@ std::optional ProcessMemoryDump::CountResidentBytes( const size_t kMaxChunkSize = 8 * 1024 * 1024; size_t max_vec_size = GetSystemPageCount(std::min(mapped_size, kMaxChunkSize), page_size); + #if BUILDFLAG(IS_WIN) - std::unique_ptr vec( - new PSAPI_WORKING_SET_EX_INFORMATION[max_vec_size]); + auto vec = + base::HeapArray::WithSize(max_vec_size); #elif BUILDFLAG(IS_APPLE) - std::unique_ptr vec(new char[max_vec_size]); + auto vec = base::HeapArray::WithSize(max_vec_size); #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) - std::unique_ptr vec(new unsigned char[max_vec_size]); + auto vec = base::HeapArray::WithSize(max_vec_size); #endif while (offset < mapped_size) { @@ -134,9 +136,10 @@ std::optional ProcessMemoryDump::CountResidentBytes( vec[i].VirtualAddress = reinterpret_cast(chunk_start + i * page_size); } - DWORD vec_size = static_cast( - page_count * sizeof(PSAPI_WORKING_SET_EX_INFORMATION)); - failure = !QueryWorkingSetEx(GetCurrentProcess(), vec.get(), vec_size); + + auto span = vec.first(page_count); + failure = !QueryWorkingSetEx(GetCurrentProcess(), span.data(), + static_cast(span.size_bytes())); for (size_t i = 0; i < page_count; i++) resident_page_count += vec[i].VirtualAttributes.Valid; @@ -149,7 +152,7 @@ std::optional ProcessMemoryDump::CountResidentBytes( #elif BUILDFLAG(IS_APPLE) // mincore in MAC does not fail with EAGAIN. failure = - !!mincore(reinterpret_cast(chunk_start), chunk_size, vec.get()); + !!mincore(reinterpret_cast(chunk_start), chunk_size, vec.data()); for (size_t i = 0; i < page_count; i++) resident_page_count += vec[i] & MINCORE_INCORE ? 1 : 0; #elif BUILDFLAG(IS_POSIX) @@ -160,9 +163,9 @@ std::optional ProcessMemoryDump::CountResidentBytes( result = #if BUILDFLAG(IS_AIX) mincore(reinterpret_cast(chunk_start), chunk_size, - reinterpret_cast(vec.get())); + reinterpret_cast(vec.data())); #else - mincore(reinterpret_cast(chunk_start), chunk_size, vec.get()); + mincore(reinterpret_cast(chunk_start), chunk_size, vec.data()); #endif } while (result == -1 && errno == EAGAIN && error_counter++ < 100); failure = !!result; diff --git a/naiveproxy/src/base/trace_event/trace_log.cc b/naiveproxy/src/base/trace_event/trace_log.cc index 1bf54ef985..e18cdb9de4 100644 --- a/naiveproxy/src/base/trace_event/trace_log.cc +++ b/naiveproxy/src/base/trace_event/trace_log.cc @@ -27,13 +27,15 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" -#include "base/memory/raw_ptr_exclusion.h" #include "base/memory/ref_counted_memory.h" +#include "base/memory/stack_allocated.h" #include "base/no_destructor.h" #include "base/notreached.h" +#include "base/numerics/safe_conversions.h" #include "base/process/process.h" #include "base/process/process_metrics.h" #include "base/ranges/algorithm.h" +#include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" @@ -43,6 +45,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/task/thread_pool.h" +#include "base/task/thread_pool/thread_pool_instance.h" #include "base/threading/platform_thread.h" #include "base/threading/thread_id_name_manager.h" #include "base/time/time.h" @@ -53,12 +56,8 @@ #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_buffer.h" #include "base/trace_event/trace_event.h" -#include "build/build_config.h" - -#include "base/numerics/safe_conversions.h" -#include "base/run_loop.h" -#include "base/task/thread_pool/thread_pool_instance.h" #include "base/tracing/perfetto_platform.h" +#include "build/build_config.h" #include "third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h" // nogncheck #include "third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h" // nogncheck #include "third_party/perfetto/include/perfetto/tracing/console_interceptor.h" @@ -429,6 +428,8 @@ class JsonStringOutputWriter // A helper class that allows the lock to be acquired in the middle of the scope // and unlocks at the end of scope if locked. class TraceLog::OptionalAutoLock { + STACK_ALLOCATED(); + public: explicit OptionalAutoLock(Lock* lock) : lock_(lock) {} @@ -450,8 +451,7 @@ class TraceLog::OptionalAutoLock { } private: - // This field is not a raw_ptr<> because it is needed for lock annotations. - RAW_PTR_EXCLUSION Lock* lock_; + Lock* lock_; bool locked_ = false; }; @@ -833,6 +833,12 @@ void TraceLog::SetEnabled(const TraceConfig& trace_config, SetEnabledImpl(trace_config, perfetto_config); } +std::vector TraceLog::GetTrackEventSessions() + const { + AutoLock lock(track_event_lock_); + return track_event_sessions_; +} + perfetto::DataSourceConfig TraceLog::GetCurrentTrackEventDataSourceConfig() const { AutoLock lock(track_event_lock_); diff --git a/naiveproxy/src/base/trace_event/trace_logging_minimal_win.cc b/naiveproxy/src/base/trace_event/trace_logging_minimal_win.cc index 64cdb54dba..fd102e481d 100644 --- a/naiveproxy/src/base/trace_event/trace_logging_minimal_win.cc +++ b/naiveproxy/src/base/trace_event/trace_logging_minimal_win.cc @@ -237,7 +237,7 @@ bool TlmProvider::KeywordEnabled(uint64_t keyword) const noexcept { } TlmInt64Field::TlmInt64Field(const char* name, const int64_t value) noexcept - : TlmFieldBase(name), value_(value) { + : TlmFieldWithConstants(name), value_(value) { DCHECK_NE(Name(), nullptr); } int64_t TlmInt64Field::Value() const noexcept { @@ -249,7 +249,7 @@ void TlmInt64Field::FillEventDescriptor( } TlmUInt64Field::TlmUInt64Field(const char* name, const uint64_t value) noexcept - : TlmFieldBase(name), value_(value) { + : TlmFieldWithConstants(name), value_(value) { DCHECK_NE(Name(), nullptr); } uint64_t TlmUInt64Field::Value() const noexcept { @@ -262,7 +262,7 @@ void TlmUInt64Field::FillEventDescriptor( TlmMbcsStringField::TlmMbcsStringField(const char* name, const char* value) noexcept - : TlmFieldBase(name), value_(value) { + : TlmFieldWithConstants(name), value_(value) { DCHECK_NE(Name(), nullptr); DCHECK_NE(value_, nullptr); } @@ -279,7 +279,7 @@ void TlmMbcsStringField::FillEventDescriptor( TlmUtf8StringField::TlmUtf8StringField(const char* name, const char* value) noexcept - : TlmFieldBase(name), value_(value) { + : TlmFieldWithConstants(name), value_(value) { DCHECK_NE(Name(), nullptr); DCHECK_NE(value_, nullptr); } @@ -293,3 +293,11 @@ void TlmUtf8StringField::FillEventDescriptor( EventDataDescCreate(&descriptors[0], value_, base::checked_cast(strlen(value_) + 1)); } + +TlmFieldBase::TlmFieldBase(const char* name) noexcept : name_(name) {} +TlmFieldBase::TlmFieldBase(std::string_view name) noexcept : name_(name) {} + +TlmFieldBase::~TlmFieldBase() = default; + +TlmFieldBase::TlmFieldBase(TlmFieldBase&&) noexcept = default; +TlmFieldBase& TlmFieldBase::operator=(TlmFieldBase&&) noexcept = default; diff --git a/naiveproxy/src/base/trace_event/trace_logging_minimal_win.h b/naiveproxy/src/base/trace_event/trace_logging_minimal_win.h index 175ffa8071..23381c82eb 100644 --- a/naiveproxy/src/base/trace_event/trace_logging_minimal_win.h +++ b/naiveproxy/src/base/trace_event/trace_logging_minimal_win.h @@ -33,6 +33,7 @@ #include #include +#include #include // TODO(joel@microsoft.com) Update headers and use defined constants instead // of magic numbers after crbug.com/1089996 is resolved. @@ -119,6 +120,21 @@ #include "base/base_export.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" +#include "third_party/abseil-cpp/absl/types/variant.h" + +namespace base::trace_event { +class MultiEtwPayloadHandler; + +template +concept EtwFieldBaseType = requires(T t) { + { t.Name() } -> std::same_as; + { + t.FillEventDescriptor(std::declval()) + } -> std::same_as; + { t.GetInType() } -> std::same_as; + { t.GetOutType() } -> std::same_as; +}; +} // namespace base::trace_event class BASE_EXPORT TlmProvider { public: @@ -192,7 +208,7 @@ class BASE_EXPORT TlmProvider { // If any active trace listeners are interested in events from this provider // with the specified level and keyword, packs the data into an event and // sends it to ETW. Returns Win32 error code or 0 for success. - template + template ULONG WriteEvent(std::string_view event_name, const EVENT_DESCRIPTOR& event_descriptor, const FieldTys&... event_fields) const noexcept { @@ -206,8 +222,8 @@ class BASE_EXPORT TlmProvider { metadata_index = EventBegin(metadata, event_name); { // scope for dummy array (simulates a C++17 comma-fold expression) char dummy[sizeof...(FieldTys) == 0 ? 1 : sizeof...(FieldTys)] = { - EventAddField(metadata, &metadata_index, event_fields.in_type_, - event_fields.out_type_, event_fields.Name())...}; + EventAddField(metadata, &metadata_index, event_fields.GetInType(), + event_fields.GetOutType(), event_fields.Name())...}; DCHECK(dummy); } @@ -229,6 +245,8 @@ class BASE_EXPORT TlmProvider { } private: + friend class base::trace_event::MultiEtwPayloadHandler; + // Size of the buffer used for provider metadata (field within the // TlmProvider object). Provider metadata consists of the nul-terminated // provider name plus a few sizes and flags, so this buffer needs to be @@ -308,15 +326,36 @@ class BASE_EXPORT TlmProvider { }; // Base class for field types. +// It's expected that data (name, value) will outlive the TlmFieldBase object. +class BASE_EXPORT TlmFieldBase { + public: + constexpr const char* Name() const noexcept { return name_.data(); } + + protected: + explicit TlmFieldBase(const char* name) noexcept; + explicit TlmFieldBase(std::string_view name) noexcept; + + // Copy operations are suppressed. Only declare move operations. + TlmFieldBase(TlmFieldBase&&) noexcept; + TlmFieldBase& operator=(TlmFieldBase&&) noexcept; + ~TlmFieldBase(); + + private: + std::string_view name_; +}; + template // Default out_type is TlgOutNULL -class TlmFieldBase { +class TlmFieldWithConstants : public TlmFieldBase { public: - constexpr const char* Name() const noexcept { return name_; } + uint8_t GetDataDescCount() const noexcept { return data_desc_count_; } + uint8_t GetInType() const noexcept { return in_type_; } + uint8_t GetOutType() const noexcept { return out_type_; } protected: - explicit constexpr TlmFieldBase(const char* name) noexcept : name_(name) {} + explicit constexpr TlmFieldWithConstants(const char* name) noexcept + : TlmFieldBase(name) {} private: friend class TlmProvider; @@ -324,13 +363,12 @@ class TlmFieldBase { static constexpr uint8_t data_desc_count_ = data_desc_count; static constexpr uint8_t in_type_ = in_type; static constexpr uint8_t out_type_ = out_type; - - const char* name_; }; -// Class that represents an event field containing nul-terminated MBCS data. -class TlmMbcsStringField - : public TlmFieldBase<1, 2> // 1 data descriptor, Type = TlgInANSISTRING +// Class that represents an event field containing nul-terminated MBCS data +class BASE_EXPORT TlmMbcsStringField + : public TlmFieldWithConstants<1, 2> // 1 data descriptor, Type = + // TlgInANSISTRING { public: // name is a utf-8 nul-terminated string. @@ -347,9 +385,9 @@ class TlmMbcsStringField }; // Class that represents an event field containing nul-terminated UTF-8 data. -class TlmUtf8StringField - : public TlmFieldBase<1, 2, 35> // 1 data descriptor, Type = - // TlgInANSISTRING + TlgOutUTF8 +class BASE_EXPORT TlmUtf8StringField + : public TlmFieldWithConstants<1, 2, 35> // 1 data descriptor, Type = + // TlgInANSISTRING + TlgOutUTF8 { public: // name and value are utf-8 nul-terminated strings. @@ -364,8 +402,9 @@ class TlmUtf8StringField }; // Class that represents an event field containing a 64 bit signed integer. -class TlmInt64Field - : public TlmFieldBase<1, 9> // 1 data descriptor, Type = _TlgInINT64 +class BASE_EXPORT TlmInt64Field + : public TlmFieldWithConstants<1, + 9> // 1 data descriptor, Type = _TlgInINT64 { public: // name is a utf-8 nul-terminated string. @@ -378,8 +417,9 @@ class TlmInt64Field const int64_t value_; }; -class TlmUInt64Field - : public TlmFieldBase<1, 10> // 1 data descriptor, Type = _TlgInUINT64 +class BASE_EXPORT TlmUInt64Field + : public TlmFieldWithConstants<1, 10> // 1 data descriptor, Type = + // _TlgInUINT64 { public: // name is a utf-8 nul-terminated string. diff --git a/naiveproxy/src/base/tracing/protos/chrome_track_event.proto b/naiveproxy/src/base/tracing/protos/chrome_track_event.proto index beb61a560d..e56bca1539 100644 --- a/naiveproxy/src/base/tracing/protos/chrome_track_event.proto +++ b/naiveproxy/src/base/tracing/protos/chrome_track_event.proto @@ -127,7 +127,9 @@ message RenderFrameImplDeletion { optional uint64 frame_tree_node_id = 4; } -// Matches content::ShouldSwapBrowsingInstance. +// Corresponds to `content::ShouldSwapBrowsingInstance`. +// Note that the enum values here are not equivalent to the content enum and +// must be converted explicitly. See `ShouldSwapBrowsingInstanceToProto`. enum ShouldSwapBrowsingInstance { // Was used for all "no BrowsingInstance swap" scenarios, now broken down in // separate reasons. @@ -163,6 +165,7 @@ enum ShouldSwapBrowsingInstance { SHOULD_SWAP_BROWSING_INSTANCE_NO_UNLOAD_HANDLER_EXISTS_ON_SAME_SITE_NAVIGATION = 21; SHOULD_SWAP_BROWSING_INSTANCE_NO_NOT_PRIMARY_MAIN_FRAME = 22; + SHOULD_SWAP_BROWSING_INSTANCE_NO_INITIATOR_REQUESTED_NO_PROACTIVE_SWAP = 23; } message ShouldSwapBrowsingInstancesResult { @@ -1556,6 +1559,15 @@ message WebContentInteraction { optional int64 total_duration_ms = 2; } +message ScrollMetrics { + optional int64 frame_count = 1; + optional int64 vsync_count = 2; + optional int64 missed_vsync_max = 3; + optional int64 missed_vsync_sum = 4; + optional int64 delayed_frame_count = 5; + optional int64 predictor_janky_frame_count = 6; +} + // The EventForwarder is a subsystem in android that forwards events from Java // code to Chromium's native implementation. In this case we register how many // events there was, what time this event occurred and the current x & y on the @@ -1903,7 +1915,7 @@ message AnimationFrameScriptTimingInfo { message ChromeTrackEvent { // Extension range for Chrome: 1000-1999 - // Next ID: 1066 + // Next ID: 1067 extend TrackEvent { optional ChromeAppState chrome_app_state = 1000; @@ -2043,5 +2055,7 @@ message ChromeTrackEvent { optional AnimationFrameScriptTimingInfo animation_frame_script_timing_info = 1065; + + optional ScrollMetrics scroll_metrics = 1066; } } diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/chrome_scrolls.sql b/naiveproxy/src/base/tracing/stdlib/chrome/chrome_scrolls.sql index fcc893306f..cf8ec56981 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/chrome_scrolls.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/chrome_scrolls.sql @@ -31,20 +31,18 @@ CREATE PERFETTO TABLE chrome_scrolls( ) AS WITH all_scrolls AS ( SELECT - args.string_value AS name, - S.ts AS ts, - S.dur AS dur, - chrome_get_most_recent_scroll_begin_id(S.ts) AS scroll_id - FROM slice AS S JOIN args USING(arg_set_id) - WHERE name="EventLatency" - AND args.string_value GLOB "*GESTURE_SCROLL*" + event_type AS name, + ts, + dur, + scroll_id + FROM chrome_gesture_scroll_events ), scroll_starts AS ( SELECT scroll_id, MIN(ts) AS gesture_scroll_begin_ts FROM all_scrolls - WHERE name = "GESTURE_SCROLL_BEGIN" + WHERE name = 'GESTURE_SCROLL_BEGIN' GROUP BY scroll_id ), scroll_ends AS ( @@ -52,8 +50,12 @@ scroll_ends AS ( scroll_id, MAX(ts) AS gesture_scroll_end_ts FROM all_scrolls - WHERE name GLOB "*GESTURE_SCROLL_UPDATE" - OR name = "GESTURE_SCROLL_END" + WHERE name IN ( + 'GESTURE_SCROLL_UPDATE', + 'FIRST_GESTURE_SCROLL_UPDATE', + 'INERTIAL_GESTURE_SCROLL_UPDATE', + 'GESTURE_SCROLL_END' + ) GROUP BY scroll_id ) SELECT @@ -68,49 +70,3 @@ FROM all_scrolls sa LEFT JOIN scroll_ends se ON sa.scroll_id = se.scroll_id GROUP BY sa.scroll_id; - --- Defines slices for all of scrolls intervals in a trace based on the scroll --- definition in chrome_scrolls. Note that scrolls may overlap (particularly in --- cases of jank/broken traces, etc); so scrolling intervals are not exactly the --- same as individual scrolls. -CREATE PERFETTO VIEW chrome_scrolling_intervals( - -- The unique identifier of the scroll interval. This may span multiple scrolls if they overlap. - id INT, - -- Comma-separated list of scroll ids that are included in this interval. - scroll_ids STRING, - -- The start timestamp of the scroll interval. - ts INT, - -- The duration of the scroll interval. - dur INT -) AS -WITH all_scrolls AS ( - SELECT - id AS scroll_id, - s.ts AS start_ts, - s.ts + s.dur AS end_ts - FROM chrome_scrolls s), -ordered_end_ts AS ( - SELECT - *, - MAX(end_ts) OVER (ORDER BY start_ts) AS max_end_ts_so_far - FROM all_scrolls), -range_starts AS ( - SELECT - *, - CASE - WHEN start_ts <= 1 + LAG(max_end_ts_so_far) OVER (ORDER BY start_ts) THEN 0 - ELSE 1 - END AS range_start - FROM ordered_end_ts), -range_groups AS ( - SELECT - *, - SUM(range_start) OVER (ORDER BY start_ts) AS range_group - FROM range_starts) -SELECT - range_group AS id, - GROUP_CONCAT(scroll_id) AS scroll_ids, - MIN(start_ts) AS ts, - MAX(end_ts) - MIN(start_ts) AS dur -FROM range_groups -GROUP BY range_group; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/event_latency.sql b/naiveproxy/src/base/tracing/stdlib/chrome/event_latency.sql new file mode 100644 index 0000000000..8e58912205 --- /dev/null +++ b/naiveproxy/src/base/tracing/stdlib/chrome/event_latency.sql @@ -0,0 +1,159 @@ +-- Copyright 2024 The Chromium Authors +-- Use of this source code is governed by a BSD-style license that can be +-- found in the LICENSE file. + +INCLUDE PERFETTO MODULE deprecated.v42.common.slices; + +-- Finds the end timestamp for a given slice's descendant with a given name. +-- If there are multiple descendants with a given name, the function will return +-- the first one, so it's most useful when working with a timeline broken down +-- into phases, where each subphase can happen only once. +CREATE PERFETTO FUNCTION _descendant_slice_end( + -- Id of the parent slice. + parent_id INT, + -- Name of the child with the desired end TS. + child_name STRING +) +-- End timestamp of the child or NULL if it doesn't exist. +RETURNS INT AS +SELECT + CASE WHEN s.dur + IS NOT -1 THEN s.ts + s.dur + ELSE NULL + END +FROM descendant_slice($parent_id) s +WHERE s.name GLOB $child_name +LIMIT 1; + +-- Returns the presentation timestamp for a given EventLatency slice. +-- This is either the end of +-- SwapEndToPresentationCompositorFrame (if it exists), +-- the end of LatchToPresentation (if it exists), +-- the end of SwapStartToPresentation (if it exists), +-- or the end of LatchToSwapEnd (workaround in older Chrome versions). +CREATE PERFETTO FUNCTION _get_presentation_timestamp( + -- The slice id which we need the presentation timestamp for. + id LONG +) +RETURNS INT AS +SELECT + COALESCE(_descendant_slice_end(id, 'SwapEndToPresentationCompositorFrame'), + _descendant_slice_end(id, '*ToPresentation'), + _descendant_slice_end(id, 'LatchToSwapEnd')) +FROM slice WHERE $id = id; + +-- All EventLatency slices. +CREATE PERFETTO TABLE chrome_event_latencies( + -- Slice Id for the EventLatency scroll event. + id INT, + -- Slice name. + name STRING, + -- The start timestamp of the scroll. + ts INT, + -- The duration of the scroll. + dur INT, + -- The id of the scroll update event. + scroll_update_id INT, + -- Whether this input event was presented. + is_presented BOOL, + -- EventLatency event type. + event_type STRING, + -- Perfetto track this slice is found on. + track_id INT +) AS +SELECT + slice.id, + slice.name, + slice.ts, + slice.dur, + EXTRACT_arg(arg_set_id, 'event_latency.event_latency_id') AS scroll_update_id, + has_descendant_slice_with_name( + slice.id, + 'SubmitCompositorFrameToPresentationCompositorFrame') + AS is_presented, + EXTRACT_ARG(arg_set_id, 'event_latency.event_type') AS event_type, + slice.track_id +FROM slice +WHERE name = 'EventLatency'; + +-- All EventLatency slices that are relevant to scrolling, including presented +-- pinches. Materialized to reduce how many times we query slice. +CREATE PERFETTO TABLE _gesture_scroll_events_no_scroll_id +AS +SELECT + name, + ts, + dur, + id, + scroll_update_id, + is_presented, + _get_presentation_timestamp(chrome_event_latencies.id) + AS presentation_timestamp, + event_type, + track_id +FROM chrome_event_latencies +WHERE ( + event_type GLOB '*GESTURE_SCROLL*' + -- Pinches are only relevant if the frame was presented. + OR (event_type GLOB '*GESTURE_PINCH_UPDATE' + AND has_descendant_slice_with_name( + id, + 'SubmitCompositorFrameToPresentationCompositorFrame') + ) +); + +-- Extracts scroll id for the EventLatency slice at `ts`. +CREATE PERFETTO FUNCTION chrome_get_most_recent_scroll_begin_id( + -- Timestamp of the EventLatency slice to get the scroll id for. + ts INT) +-- The event_latency_id of the EventLatency slice with the type +-- GESTURE_SCROLL_BEGIN that is the closest to `ts`. +RETURNS INT AS +SELECT scroll_update_id +FROM _gesture_scroll_events_no_scroll_id +WHERE event_type = 'GESTURE_SCROLL_BEGIN' +AND ts<=$ts +ORDER BY ts DESC +LIMIT 1; + +-- All scroll-related events (frames) including gesture scroll updates, begins +-- and ends with respective scroll ids and start/end timestamps, regardless of +-- being presented. This includes pinches that were presented. See b/315761896 +-- for context on pinches. +CREATE PERFETTO TABLE chrome_gesture_scroll_events( + -- Slice Id for the EventLatency scroll event. + id INT, + -- Slice name. + name STRING, + -- The start timestamp of the scroll. + ts INT, + -- The duration of the scroll. + dur INT, + -- The id of the scroll update event. + scroll_update_id INT, + -- The id of the scroll. + scroll_id INT, + -- Whether this input event was presented. + is_presented BOOL, + -- Frame presentation timestamp aka the timestamp of the + -- SwapEndToPresentationCompositorFrame substage. + -- TODO(b/341047059): temporarily use LatchToSwapEnd as a workaround if + -- SwapEndToPresentationCompositorFrame is missing due to b/247542163. + presentation_timestamp INT, + -- EventLatency event type. + event_type STRING, + -- Perfetto track this slice is found on. + track_id INT +) AS +SELECT + id, + name, + ts, + dur, + scroll_update_id, + chrome_get_most_recent_scroll_begin_id(ts) AS scroll_id, + is_presented, + presentation_timestamp, + event_type, + track_id +FROM _gesture_scroll_events_no_scroll_id; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/interactions.sql b/naiveproxy/src/base/tracing/stdlib/chrome/interactions.sql index 78600dc1cd..a3211cabaf 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/interactions.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/interactions.sql @@ -7,6 +7,7 @@ -- Currently we only track Chrome page loads and their associated metrics. INCLUDE PERFETTO MODULE chrome.page_loads; +INCLUDE PERFETTO MODULE chrome.scroll_interactions; INCLUDE PERFETTO MODULE chrome.startups; INCLUDE PERFETTO MODULE chrome.web_content_interactions; @@ -55,4 +56,12 @@ SELECT 'InteractionToFirstPaint' AS name, ts, dur -FROM chrome_web_content_interactions; +FROM chrome_web_content_interactions +UNION ALL +SELECT + id AS scoped_id, + 'chrome_scroll_interactions' AS type, + 'Scroll' AS name, + ts, + dur +FROM chrome_scroll_interactions; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/perfetto_sql_files.gni b/naiveproxy/src/base/tracing/stdlib/chrome/perfetto_sql_files.gni index 9a84d4a65d..77eeb14ba1 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/perfetto_sql_files.gni +++ b/naiveproxy/src/base/tracing/stdlib/chrome/perfetto_sql_files.gni @@ -6,16 +6,21 @@ chrome_stdlib_sql_files = [ "chrome_scrolls.sql", "cpu_powerups.sql", + "event_latency.sql", "event_latency_description.sql", "histograms.sql", "interactions.sql", "metadata.sql", "page_loads.sql", + "scroll_interactions.sql", "speedometer.sql", + "speedometer_2_1.sql", + "speedometer_3.sql", "startups.sql", "tasks.sql", "vsync_intervals.sql", "web_content_interactions.sql", + "scroll_jank/predictor_error.sql", "scroll_jank/scroll_jank_cause_map.sql", "scroll_jank/scroll_jank_cause_utils.sql", "scroll_jank/scroll_jank_intervals.sql", diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_interactions.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_interactions.sql new file mode 100644 index 0000000000..9319849e76 --- /dev/null +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_interactions.sql @@ -0,0 +1,66 @@ +-- Copyright 2024 The Chromium Authors +-- Use of this source code is governed by a BSD-style license that can be +-- found in the LICENSE file. + +INCLUDE PERFETTO MODULE slices.with_context; + +-- Top level scroll events, with metrics. +CREATE PERFETTO TABLE chrome_scroll_interactions( + -- Unique id for an individual scroll. + id INT, + -- Name of the scroll event. + name STRING, + -- Start timestamp of the scroll. + ts INT, + -- Duration of the scroll. + dur INT, + -- The total number of frames in the scroll. + frame_count INT, + -- The total number of vsyncs in the scroll. + vsync_count INT, + -- The maximum number of vsyncs missed during any and all janks. + missed_vsync_max INT, + -- The total number of vsyncs missed during any and all janks. + missed_vsync_sum INT, + -- The number of delayed frames. + delayed_frame_count INT, + -- The number of frames that are deemed janky to the human eye after Chrome + -- has applied its scroll prediction algorithm. + predictor_janky_frame_count INT, + -- The process id this event occurred on. + renderer_upid INT +) AS +WITH scroll_metrics AS ( + SELECT + id, + ts, + dur, + EXTRACT_ARG(arg_set_id, 'scroll_metrics.frame_count') + AS frame_count, + EXTRACT_ARG(arg_set_id, 'scroll_metrics.vsync_count') + AS vsync_count, + EXTRACT_ARG(arg_set_id, 'scroll_metrics.missed_vsync_max') + AS missed_vsync_max, + EXTRACT_ARG(arg_set_id, 'scroll_metrics.missed_vsync_sum') + AS missed_vsync_sum, + EXTRACT_ARG(arg_set_id, 'scroll_metrics.delayed_frame_count') + AS delayed_frame_count, + EXTRACT_ARG(arg_set_id, 'scroll_metrics.predictor_janky_frame_count') + AS predictor_janky_frame_count, + upid AS renderer_upid + FROM process_slice + WHERE name = 'Scroll' +) +SELECT + id, + 'Scroll' AS name, + ts, + dur, + frame_count, + vsync_count, + missed_vsync_max, + missed_vsync_sum, + delayed_frame_count, + predictor_janky_frame_count, + renderer_upid +FROM scroll_metrics; \ No newline at end of file diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/predictor_error.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/predictor_error.sql new file mode 100644 index 0000000000..fc8415a3d9 --- /dev/null +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/predictor_error.sql @@ -0,0 +1,147 @@ +-- Copyright 2024 The Chromium Authors +-- Use of this source code is governed by a BSD-style license that can be +-- found in the LICENSE file. + +-- This file implements the scrolling predictor jank metric, as is +-- implemented in cc/metrics/predictor_jank_tracker.cc. See comments in that +-- file to get additional context on how the metric is implemented. +-- +-- "Delta" here refers to how much (in pixels) the page offset changed for a +-- given frame due to a scroll. +-- +-- For more details please check the following document: +-- http://doc/1Y0u0Tq5eUZff75nYUzQVw6JxmbZAW9m64pJidmnGWsY. + +INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_offsets; + +-- The maximum delta value between three consecutive frames, used to determine +-- whether the sequence in the scroll is fast or slow; the sequence speed is +-- used to determine whether the sequence includes any predictor jank. +CREATE PERFETTO FUNCTION _get_slow_scroll_delta_threshold() +RETURNS DOUBLE AS +SELECT 7.0; + +-- The threshold for the ratio of the delta of middle frame to tbe deltas of its +-- neighbors in a sequence of three frames, if the sequence is considered +-- "slow". +CREATE PERFETTO FUNCTION _get_slow_scroll_janky_threshold() +RETURNS DOUBLE AS +SELECT 1.4; + +-- The threshold for the ratio of the delta of middle frame to tbe deltas of its +-- neighbors in a sequence of three frames, if the sequence is considered +-- "fast". +CREATE PERFETTO FUNCTION _get_fast_scroll_janky_threshold() +RETURNS DOUBLE AS +SELECT 1.2; + +-- Determine the acceptable threshold (see _get_slow_scroll_janky_threshold() +-- and _get_fast_scroll_janky_threshold()) based on the maximum delta value +-- between three consecutive frames. +CREATE PERFETTO FUNCTION _get_scroll_jank_threshold( + d1 DOUBLE, + d2 DOUBLE, + d3 DOUBLE +) +RETURNS DOUBLE AS +SELECT + CASE + WHEN MAX(MAX($d1, $d2), $d3) <= _get_slow_scroll_delta_threshold() + THEN _get_slow_scroll_janky_threshold() + ELSE _get_fast_scroll_janky_threshold() + END; + +-- Calculate the predictor jank of three consecutive frames, if it is above the +-- threshold. Anything below the threshold is not considered jank. +CREATE PERFETTO FUNCTION _get_predictor_jank( + d1 DOUBLE, + d2 DOUBLE, + d3 DOUBLE, + threshold DOUBLE +) +RETURNS DOUBLE AS +SELECT + CASE + WHEN $d2/MAX($d1, $d3) >= $threshold + THEN $d2/MAX($d1, $d3) - $threshold + WHEN MIN($d1, $d3)/$d2 >= $threshold + THEN MIN($d1, $d3)/$d2 - $threshold + ELSE 0 + END; + +CREATE PERFETTO TABLE _deltas_and_neighbors AS +SELECT + scroll_id, + event_latency_slice_id, + scroll_update_id, + ts, + delta_y, + relative_offset_y, + LAG(IFNULL(delta_y, 0.0)) + OVER (PARTITION BY scroll_id ORDER BY ts ASC) AS prev_delta, + LEAD(IFNULL(delta_y, 0.0)) + OVER (PARTITION BY scroll_id ORDER BY ts ASC) AS next_delta +FROM chrome_presented_scroll_offsets; + +CREATE PERFETTO TABLE _deltas_and_neighbors_with_threshold AS +SELECT + scroll_id, + event_latency_slice_id, + scroll_update_id, + ts, + delta_y, + relative_offset_y, + prev_delta, + next_delta, + _get_scroll_jank_threshold(ABS(prev_delta), ABS(delta_y), ABS(next_delta)) + AS delta_threshold +FROM _deltas_and_neighbors +WHERE delta_y IS NOT NULL + AND prev_delta IS NOT NULL + AND next_delta IS NOT NULL; + +-- The scrolling offsets and predictor jank values for the actual (applied) +-- scroll events. +CREATE PERFETTO TABLE chrome_predictor_error( + -- An ID that ties all EventLatencies in a particular scroll. (implementation + -- note: This is the EventLatency TraceId of the GestureScrollbegin). + scroll_id INT, + -- An ID for this particular EventLatency regardless of it being presented or + -- not. + event_latency_slice_id INT, + -- An ID that ties this |event_latency_id| with the Trace Id (another + -- event_latency_id) that it was presented with. + scroll_update_id INT, + -- Presentation timestamp. + present_ts INT, + -- The delta in raw coordinates between this presented EventLatency and the + -- previous presented frame. + delta_y DOUBLE, + -- The pixel offset of this presented EventLatency compared to the initial + -- one. + relative_offset_y DOUBLE, + -- The delta in raw coordinates of the previous scroll update event. + prev_delta DOUBLE, + -- The delta in raw coordinates of the subsequent scroll update event. + next_delta DOUBLE, + -- The jank value based on the discrepancy between scroll predictor + -- coordinates and the actual deltas between scroll update events. + predictor_jank DOUBLE, + -- The threshold used to determine if jank occurred. + delta_threshold DOUBLE +) +AS +SELECT + scroll_id, + event_latency_slice_id, + scroll_update_id, + ts AS present_ts, + delta_y, + relative_offset_y, + prev_delta, + next_delta, + _get_predictor_jank( + ABS(prev_delta), ABS(delta_y), ABS(next_delta), delta_threshold) + AS predictor_jank, + delta_threshold +FROM _deltas_and_neighbors_with_threshold; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_intervals.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_intervals.sql index 5fb66d6141..ab15041aa5 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_intervals.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_intervals.sql @@ -37,10 +37,13 @@ SELECT s.name, e.cause_of_jank, e.sub_cause_of_jank, - CAST((e.delay_since_last_frame/e.vsync_interval) - 1 AS INT) AS delayed_frame_count, - CAST(s.ts + s.dur - ((e.delay_since_last_frame - e.vsync_interval) * 1e6) AS INT) AS frame_jank_ts, - CAST((e.delay_since_last_frame - e.vsync_interval) * 1e6 AS INT) AS frame_jank_dur -FROM slice s + CAST((e.delay_since_last_frame/e.vsync_interval) - 1 AS INT) + AS delayed_frame_count, + CAST(s.ts + s.dur - ((e.delay_since_last_frame - e.vsync_interval) * 1e6) + AS INT) AS frame_jank_ts, + CAST((e.delay_since_last_frame - e.vsync_interval) * 1e6 AS INT) + AS frame_jank_dur +FROM chrome_gesture_scroll_events s JOIN chrome_janky_frames e ON s.id = e. event_latency_id; @@ -56,9 +59,9 @@ CREATE PERFETTO VIEW chrome_janky_frame_presentation_intervals( -- How many vsyncs this frame missed its deadline by. delayed_frame_count INT, -- The stage of EventLatency that the caused the jank. - cause_of_jank INT, + cause_of_jank STRING, -- The stage of cause_of_jank that caused the jank. - sub_cause_of_jank INT, + sub_cause_of_jank STRING, -- The id of the associated event latency in the slice table. event_latency_id INT ) AS @@ -73,7 +76,7 @@ SELECT FROM chrome_janky_event_latencies_v3; -- Scroll jank frame presentation stats for individual scrolls. -CREATE PERFETTO VIEW chrome_scroll_stats( +CREATE PERFETTO TABLE chrome_scroll_stats( -- Id of the individual scroll. scroll_id INT, -- The number of frames in the scroll. @@ -98,7 +101,8 @@ WITH vsyncs AS ( GROUP BY scroll_id), missed_vsyncs AS ( SELECT - CAST(SUM((delay_since_last_frame / vsync_interval) - 1) AS INT) AS total_missed_vsyncs, + CAST(SUM((delay_since_last_frame / vsync_interval) - 1) AS INT) + AS total_missed_vsyncs, scroll_id FROM chrome_janky_frames GROUP BY scroll_id), @@ -157,7 +161,8 @@ range_starts AS ( -- This is a two-pass calculation to calculate the first event in the -- group. An event is considered the first event in a group if all events -- which started before it also finished the current one started. - WHEN start_ts <= 1 + LAG(max_end_ts_so_far) OVER (ORDER BY start_ts) THEN 0 + WHEN start_ts <= 1 + LAG(max_end_ts_so_far) OVER (ORDER BY start_ts) + THEN 0 ELSE 1 END AS range_start FROM ordered_jank_end_ts), diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql index b1d07a1d30..7da57d356f 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql @@ -2,35 +2,12 @@ -- Use of this source code is governed by a BSD-style license that can be -- found in the LICENSE file. -INCLUDE PERFETTO MODULE deprecated.v42.common.slices; - -- Hardware info is useful when using sql metrics for analysis -- in BTP. INCLUDE PERFETTO MODULE chrome.metadata; INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3_cause; INCLUDE PERFETTO MODULE chrome.scroll_jank.utils; --- Finds the end timestamp for a given slice's descendant with a given name. --- If there are multiple descendants with a given name, the function will return the --- first one, so it's most useful when working with a timeline broken down into phases, --- where each subphase can happen only once. -CREATE PERFETTO FUNCTION _descendant_slice_end( - -- Id of the parent slice. - parent_id INT, - -- Name of the child with the desired end TS. - child_name STRING -) --- End timestamp of the child or NULL if it doesn't exist. -RETURNS INT AS -SELECT - CASE WHEN s.dur - IS NOT -1 THEN s.ts + s.dur - ELSE NULL - END -FROM descendant_slice($parent_id) s -WHERE s.name = $child_name -LIMIT 1; - -- Given a slice id, returns the name of the slice. CREATE PERFETTO FUNCTION _slice_name_from_id( -- The slice id which we need the name for. @@ -60,36 +37,25 @@ CREATE PERFETTO TABLE chrome_gesture_scroll_updates( is_presented BOOL, -- Frame presentation timestamp aka the timestamp of the -- SwapEndToPresentationCompositorFrame substage. - -- TODO(b/341047059): temporarily use LatchToSwapEnd as a workaround if - -- SwapEndToPresentationCompositorFrame is missing due to b/247542163. presentation_timestamp INT, -- EventLatency event type. - event_type INT + event_type STRING ) AS SELECT - slice.ts, - slice.dur, - slice.id, - EXTRACT_arg(arg_set_id, 'event_latency.event_latency_id') AS scroll_update_id, - chrome_get_most_recent_scroll_begin_id(slice.ts) AS scroll_id, - has_descendant_slice_with_name(slice.id, 'SubmitCompositorFrameToPresentationCompositorFrame') - AS is_presented, - CASE WHEN has_descendant_slice_with_name(slice.id, "SwapEndToPresentationCompositorFrame") - THEN _descendant_slice_end(slice.id, "SwapEndToPresentationCompositorFrame") - ELSE _descendant_slice_end(slice.id, "LatchToSwapEnd") - END - AS presentation_timestamp, - EXTRACT_ARG(arg_set_id, 'event_latency.event_type') AS event_type -FROM slice JOIN args USING(arg_set_id) -WHERE name = "EventLatency" -AND ( - args.string_value GLOB '*GESTURE_SCROLL_UPDATE' - -- Pinches are only relevant if the frame was presented. - OR (args.string_value GLOB '*GESTURE_PINCH_UPDATE' - AND has_descendant_slice_with_name( - slice.id, - 'SubmitCompositorFrameToPresentationCompositorFrame') - ) + ts, + dur, + id, + scroll_update_id, + scroll_id, + is_presented, + presentation_timestamp, + event_type +FROM chrome_gesture_scroll_events +WHERE event_type IN ( + 'GESTURE_SCROLL_UPDATE', + 'FIRST_GESTURE_SCROLL_UPDATE', + 'INERTIAL_GESTURE_SCROLL_UPDATE', + 'GESTURE_PINCH_UPDATE' ); CREATE PERFETTO TABLE _presented_gesture_scrolls AS @@ -123,7 +89,7 @@ CREATE PERFETTO TABLE chrome_presented_gesture_scrolls( -- Frame presentation timestamp. presentation_timestamp INT, -- EventLatency event type. - event_type INT + event_type STRING ) AS WITH scroll_updates_with_presentation_info as MATERIALIZED ( @@ -168,7 +134,7 @@ CREATE PERFETTO TABLE chrome_scroll_updates_with_deltas( -- The id of the scroll update event. scroll_update_id INT, -- The perceived delta_y on the screen post prediction. - delta_y INT + delta_y DOUBLE ) AS SELECT EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id, @@ -225,7 +191,7 @@ CREATE PERFETTO TABLE chrome_full_frame_delta_view( -- The timestamp of the last presented input. last_presented_input_ts INT, -- The perceived delta_y on the screen post prediction. - delta_y INT, + delta_y DOUBLE, -- ID of the associated EventLatency. event_latency_id INT, -- Duration of the associated EventLatency. @@ -249,7 +215,7 @@ LEFT JOIN chrome_scroll_updates_with_deltas deltas -- Group all gestures presented at the same timestamp together in -- a single row. -CREATE PERFETTO VIEW chrome_merged_frame_view( +CREATE PERFETTO TABLE chrome_merged_frame_view( -- ID of the frame. id INT, -- The timestamp of the last presented input. @@ -261,11 +227,11 @@ CREATE PERFETTO VIEW chrome_merged_frame_view( -- ID of the associated scroll update. scroll_update_id INT, -- All scroll updates associated with the frame presentation timestamp. - encapsulated_scroll_ids INT, + encapsulated_scroll_ids STRING, -- Sum of all perceived delta_y values at the frame presentation timestamp. - total_delta INT, + total_delta DOUBLE, -- Lists all of the perceived delta_y values at the frame presentation timestamp. - segregated_delta_y INT, + segregated_delta_y STRING, -- ID of the associated EventLatency. event_latency_id INT, -- Maximum duration of the associated EventLatency. @@ -292,7 +258,7 @@ ORDER BY presentation_timestamp; -- View contains all chrome presented frames during gesture updates -- while calculating delay since last presented which usually should -- equal to |VSYNC_INTERVAL| if no jank is present. -CREATE PERFETTO VIEW chrome_frame_info_with_delay( +CREATE PERFETTO TABLE chrome_frame_info_with_delay( -- gesture scroll slice id. id INT, -- OS timestamp of the last touch move arrival within a frame. @@ -304,11 +270,11 @@ CREATE PERFETTO VIEW chrome_frame_info_with_delay( -- ID of the associated scroll update. scroll_update_id INT, -- Trace ids of all frames presented in at this vsync. - encapsulated_scroll_ids INT, + encapsulated_scroll_ids STRING, -- Summation of all delta_y of all gesture scrolls in this frame. - total_delta INT, + total_delta DOUBLE, -- All delta y of all gesture scrolls comma separated, summing those gives |total_delta|. - segregated_delta_y INT, + segregated_delta_y STRING, -- Event latency id of the presented frame. event_latency_id INT, -- Duration of the EventLatency. @@ -317,9 +283,9 @@ CREATE PERFETTO VIEW chrome_frame_info_with_delay( presentation_timestamp INT, -- Time elapsed since the previous frame was presented, usually equals |VSYNC| -- if no frame drops happened. - delay_since_last_frame INT, + delay_since_last_frame DOUBLE, -- Difference in OS timestamps of inputs in the current and the previous frame. - delay_since_last_input INT, + delay_since_last_input DOUBLE, -- The event latency id that will be used as a reference to determine the -- jank cause. prev_event_latency_id INT @@ -339,9 +305,9 @@ FROM chrome_merged_frame_view; -- minimum delay between frames larger than zero. -- -- TODO(~M130): Remove the lowest vsync since we should always have vsync_interval_ms. -CREATE PERFETTO VIEW chrome_vsyncs( +CREATE PERFETTO TABLE chrome_vsyncs( -- The lowest delay between frames larger than zero. - vsync_interval INT + vsync_interval DOUBLE ) AS WITH trace_vsyncs AS ( @@ -359,13 +325,13 @@ FROM chrome_frame_info_with_delay WHERE delay_since_last_frame > 0; -- Filter the frame view only to frames that had missed vsyncs. -CREATE PERFETTO VIEW chrome_janky_frames_no_cause( +CREATE PERFETTO TABLE chrome_janky_frames_no_cause( -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view. - delay_since_last_frame INT, + delay_since_last_frame DOUBLE, -- Event latency id of the presented frame. event_latency_id INT, -- Vsync interval at the time of recording the trace. - vsync_interval INT, + vsync_interval DOUBLE, -- Device brand and model. hardware_class STRING, -- The scroll corresponding to this frame. @@ -385,13 +351,13 @@ WHERE delay_since_last_frame > (select vsync_interval + vsync_interval / 2 from AND delay_since_last_input < (select vsync_interval + vsync_interval / 2 from chrome_vsyncs); -- Janky frame information including the jank cause. -CREATE PERFETTO VIEW chrome_janky_frames_no_subcause( +CREATE PERFETTO TABLE chrome_janky_frames_no_subcause( -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view. - delay_since_last_frame INT, + delay_since_last_frame DOUBLE, -- Event latency id of the presented frame. event_latency_id INT, -- Vsync interval at the time of recording the trace. - vsync_interval INT, + vsync_interval DOUBLE, -- Device brand and model. hardware_class STRING, -- The scroll corresponding to this frame. @@ -408,17 +374,17 @@ FROM chrome_janky_frames_no_cause; -- Finds all causes of jank for all janky frames, and a cause of sub jank -- if the cause of jank was GPU related. -CREATE PERFETTO VIEW chrome_janky_frames( +CREATE PERFETTO TABLE chrome_janky_frames( -- The reason the Vsync was missed. - cause_of_jank INT, + cause_of_jank STRING, -- Further breakdown if the root cause was GPU related. - sub_cause_of_jank INT, + sub_cause_of_jank STRING, -- Time elapsed since the previous frame was presented, will be more than |VSYNC| in this view. - delay_since_last_frame INT, + delay_since_last_frame DOUBLE, -- Event latency id of the presented frame. event_latency_id INT, -- Vsync interval at the time of recording the trace. - vsync_interval INT, + vsync_interval DOUBLE, -- Device brand and model. hardware_class STRING, -- The scroll corresponding to this frame. @@ -446,7 +412,7 @@ SELECT FROM chrome_janky_frames_no_subcause; -- Counting all unique frame presentation timestamps. -CREATE PERFETTO VIEW chrome_unique_frame_presentation_ts( +CREATE PERFETTO TABLE chrome_unique_frame_presentation_ts( -- The unique frame presentation timestamp. presentation_timestamp INT ) AS @@ -457,7 +423,7 @@ FROM chrome_presented_gesture_scrolls; -- Dividing missed frames over total frames to get janky frame percentage. -- This represents the v3 scroll jank metrics. -- Reflects Event.Jank.DelayedFramesPercentage UMA metric. -CREATE PERFETTO VIEW chrome_janky_frames_percentage( +CREATE PERFETTO TABLE chrome_janky_frames_percentage( -- The percent of missed frames relative to total frames - aka the percent of janky frames. delayed_frame_percentage FLOAT ) AS @@ -470,7 +436,7 @@ SELECT FROM chrome_unique_frame_presentation_ts) * 100 AS delayed_frame_percentage; -- Number of frames and janky frames per scroll. -CREATE PERFETTO VIEW chrome_frames_per_scroll( +CREATE PERFETTO TABLE chrome_frames_per_scroll( -- The ID of the scroll. scroll_id INT, -- The number of frames in the scroll. @@ -478,7 +444,7 @@ CREATE PERFETTO VIEW chrome_frames_per_scroll( -- The number of delayed/janky frames. num_janky_frames INT, -- The percentage of janky frames relative to total frames. - scroll_jank_percentage INT + scroll_jank_percentage DOUBLE ) AS WITH frames AS ( @@ -509,9 +475,9 @@ CREATE PERFETTO VIEW chrome_causes_per_scroll( scroll_id INT, -- The maximum time a frame was delayed after the presentation of the previous -- frame. - max_delay_since_last_frame INT, + max_delay_since_last_frame DOUBLE, -- The expected vsync interval. - vsync_interval INT, + vsync_interval DOUBLE, -- A proto amalgamation of each scroll jank cause including cause name, sub -- cause and the duration of the delay since the previous frame was presented. scroll_jank_causes BYTES @@ -534,4 +500,4 @@ SELECT AS scroll_jank_causes FROM chrome_janky_frames -GROUP BY scroll_id; \ No newline at end of file +GROUP BY scroll_id; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql index f1bfd37234..5904a54ebe 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql @@ -48,6 +48,7 @@ WHERE slice.name = 'TranslateAndScaleWebInputEvent'; -- Associate the gesture scroll update OS timestamp with the delta. CREATE PERFETTO TABLE _scroll_deltas_with_timestamp AS SELECT + slice.id AS event_latency_slice_id, slice.ts AS input_ts, data.scroll_update_id, data.delta_y @@ -60,6 +61,7 @@ FROM _translate_and_scale_scroll_deltas data CREATE PERFETTO TABLE _scroll_deltas_with_scroll_id AS SELECT scrolls.id AS scroll_id, + deltas.event_latency_slice_id, deltas.input_ts, deltas.scroll_update_id, deltas.delta_y @@ -73,7 +75,8 @@ CREATE PERFETTO TABLE _scroll_deltas_with_delays AS SELECT deltas.scroll_id, delay.total_delta, - delay.scroll_update_id, + deltas.scroll_update_id, + deltas.event_latency_slice_id, delay.presentation_timestamp AS presentation_timestamp, deltas.input_ts, deltas.delta_y @@ -83,20 +86,26 @@ FROM _scroll_deltas_with_scroll_id AS deltas -- The raw coordinates and pixel offsets for all input events which were part of -- a scroll. CREATE PERFETTO TABLE chrome_scroll_input_offsets( - -- Trace id associated with the scroll. + -- An ID that ties all EventLatencies in a particular scroll. (implementation + -- note: This is the EventLatency TraceId of the GestureScrollbegin). scroll_id INT, - -- Trace id associated with the scroll. + -- An ID for this particular EventLatency regardless of it being presented or + -- not. + event_latency_slice_id INT, + -- An ID that ties this |event_latency_id| with the Trace Id (another + -- event_latency_id) that it was presented with. scroll_update_id INT, -- Timestamp the of the scroll input event. ts INT, -- The delta in raw coordinates between this scroll update event and the -- previous. - delta_y INT, + delta_y DOUBLE, -- The pixel offset of this scroll update event compared to the initial one. - relative_offset_y INT + relative_offset_y DOUBLE ) AS SELECT scroll_id, + event_latency_slice_id, scroll_update_id, input_ts AS ts, delta_y, @@ -109,24 +118,32 @@ FROM _scroll_deltas_with_delays; -- necessarily inclusive of all user scroll events, rather those scroll events -- that are actually processed. CREATE PERFETTO TABLE chrome_presented_scroll_offsets( - -- Trace id associated with the scroll. + -- An ID that ties all EventLatencies in a particular scroll. (implementation + -- note: This is the EventLatency TraceId of the GestureScrollbegin). scroll_id INT, - -- Trace id associated with the scroll update event. + -- An ID for this particular EventLatency regardless of it being presented or + -- not. + event_latency_slice_id INT, + -- An ID that ties this |event_latency_id| with the Trace Id (another + -- event_latency_id) that it was presented with. scroll_update_id INT, -- Presentation timestamp. ts INT, -- The delta in raw coordinates between this scroll update event and the -- previous. - delta_y INT, + delta_y DOUBLE, -- The pixel offset of this scroll update event compared to the initial one. - relative_offset_y INT + relative_offset_y DOUBLE ) AS SELECT scroll_id, + event_latency_slice_id, scroll_update_id, presentation_timestamp AS ts, total_delta AS delta_y, SUM(IFNULL(total_delta, 0)) OVER ( PARTITION BY scroll_id ORDER BY scroll_update_id, presentation_timestamp ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS relative_offset_y -FROM _scroll_deltas_with_delays; \ No newline at end of file +FROM _scroll_deltas_with_delays +WHERE presentation_timestamp IS NOT NULL +; \ No newline at end of file diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/utils.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/utils.sql index b7b6badd1d..559638bcb7 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/utils.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/utils.sql @@ -2,7 +2,9 @@ -- Use of this source code is governed by a BSD-style license that can be -- found in the LICENSE file. -- --- Those are helper functions used in computing jank metrics +-- These are helper functions/tables used in computing jank metrics + +INCLUDE PERFETTO MODULE chrome.event_latency; -- This function takes timestamps of two consecutive frames and determines if -- its janky by a delay of more than 0.5 of a frame in order to make sure that @@ -103,18 +105,3 @@ FROM slice s WHERE category GLOB "*scheduler.long_tasks*" AND name = $name; - --- Extracts scroll id for the EventLatency slice at `ts`. -CREATE PERFETTO FUNCTION chrome_get_most_recent_scroll_begin_id( - -- Timestamp of the EventLatency slice to get the scroll id for. - ts INT) --- The event_latency_id of the EventLatency slice with the type --- GESTURE_SCROLL_BEGIN that is the closest to `ts`. -RETURNS INT AS -SELECT EXTRACT_ARG(arg_set_id, "event_latency.event_latency_id") -FROM slice -WHERE name="EventLatency" -AND EXTRACT_ARG(arg_set_id, "event_latency.event_type") = "GESTURE_SCROLL_BEGIN" -AND ts<=$ts -ORDER BY ts DESC -LIMIT 1; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/speedometer.sql b/naiveproxy/src/base/tracing/stdlib/chrome/speedometer.sql index 79b820f88f..9cfcaa8aec 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/speedometer.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/speedometer.sql @@ -2,202 +2,92 @@ -- Use of this source code is governed by a BSD-style license that can be -- found in the LICENSE file. --- Annotates a trace with Speedometer 2.1 related information. --- --- The scripts below analyse traces with the following tracing options --- enabled: --- --- - Chromium: --- "blink.user_timing". --- --- NOTE: A regular speedometer run (e.g. from the website) will generate the --- required events. No need to add any extra JS or anything. --- --- Noteworthy tables: --- speedometer_mark: List of marks (event slices) emitted by Speedometer. --- These are the points in time Speedometer makes a clock reading to --- compute intervals of time for the final score. --- speedometer_measure_slice: Augmented slices for Speedometer measurements. --- These are the intervals of time Speedometer uses to compute the final --- score. --- speedometer_iteration_slice: Slice that covers one Speedometer iteration --- and has the total_time and score for it. If you average all the scores --- over all iterations you get the final Speedometer score for the run. +INCLUDE PERFETTO MODULE chrome.speedometer_2_1; +INCLUDE PERFETTO MODULE chrome.speedometer_3; --- List of marks (event slices) emitted by Speedometer. --- These are the points in time Speedometer makes a clock reading to compute --- intervals of time for the final score. --- --- @column slice_id Slice this data refers to. --- @column iteration Speedometer iteration the mark belongs to. --- @column suite_name Suite name --- @column test_name Test name --- @column mark_type Type of mark (start, sync-end, async-end) -CREATE PERFETTO VIEW _chrome_speedometer_mark +CREATE PERFETTO FUNCTION _chrome_speedometer_version() +RETURNS STRING AS WITH - speedometer_21_suite_name(suite_name) AS ( - VALUES - ('VanillaJS-TodoMVC'), - ('Vanilla-ES2015-TodoMVC'), - ('Vanilla-ES2015-Babel-Webpack-TodoMVC'), - ('React-TodoMVC'), - ('React-Redux-TodoMVC'), - ('EmberJS-TodoMVC'), - ('EmberJS-Debug-TodoMVC'), - ('BackboneJS-TodoMVC'), - ('AngularJS-TodoMVC'), - ('Angular2-TypeScript-TodoMVC'), - ('VueJS-TodoMVC'), - ('jQuery-TodoMVC'), - ('Preact-TodoMVC'), - ('Inferno-TodoMVC'), - ('Elm-TodoMVC'), - ('Flight-TodoMVC') - ), - speedometer_21_test_name(test_name) AS ( - VALUES - ('Adding100Items'), - ('CompletingAllItems'), - -- This seems to be an issue with Speedometer 2.1. All tests delete all items, - -- but for some reason the test names do not match for all suites. - ('DeletingAllItems'), - ('DeletingItems') - ), - speedometer_21_test_mark_type(mark_type) AS ( - VALUES - ('start'), - ('sync-end'), - ('async-end') - ), - -- Make sure we only look at slices with names we expect. - speedometer_mark_name AS ( - SELECT - s.suite_name || '.' || t.test_name || '-' || m.mark_type AS name, - s.suite_name, - t.test_name, - m.mark_type - FROM - speedometer_21_suite_name AS s, - speedometer_21_test_name AS t, - speedometer_21_test_mark_type AS m + num_measures AS ( + SELECT '2.1' AS version, COUNT(*) AS num_measures + FROM chrome_speedometer_2_1_measure + UNION ALL + SELECT '3' AS version, COUNT(*) AS num_measures + FROM chrome_speedometer_3_measure ) -SELECT - s.id AS slice_id, - RANK() OVER (PARTITION BY name ORDER BY ts ASC) AS iteration, - m.suite_name, - m.test_name, - m.mark_type -FROM slice AS s -JOIN speedometer_mark_name AS m - USING (name) -WHERE category = 'blink.user_timing'; +SELECT version +FROM num_measures +ORDER BY num_measures DESC +LIMIT 1; -- Augmented slices for Speedometer measurements. -- These are the intervals of time Speedometer uses to compute the final score. -- There are two intervals that are measured for every test: sync and async --- sync is the time between the start and sync-end marks, async is the time --- between the sync-end and async-end marks. CREATE PERFETTO TABLE chrome_speedometer_measure( - -- Speedometer iteration the mark belongs to. + -- Start timestamp of the measure slice + ts INT, + -- Duration of the measure slice + dur INT, + -- Full measure name + name STRING, + -- Speedometer iteration the slice belongs to. iteration INT, -- Suite name suite_name STRING, -- Test name test_name STRING, -- Type of the measure (sync or async) - measure_type STRING, - -- Start timestamp of the measure - ts INT, - -- Duration of the measure - dur INT -) + measure_type STRING) AS WITH - -- Get the 3 test timestamps (start, sync-end, async-end) in one row. Using a - -- the LAG window function and partitioning by test. 2 out of the 3 rows - -- generated per test will have some NULL ts values. - augmented AS ( - SELECT - iteration, - suite_name, - test_name, - ts AS async_end_ts, - LAG(ts, 1) - OVER (PARTITION BY iteration, suite_name, test_name ORDER BY ts ASC) - AS sync_end_ts, - LAG(ts, 2) - OVER (PARTITION BY iteration, suite_name, test_name ORDER BY ts ASC) - AS start_ts, - COUNT() - OVER (PARTITION BY iteration, suite_name, test_name ORDER BY ts ASC) - AS mark_count - FROM _chrome_speedometer_mark - JOIN slice - USING (slice_id) - ), - filtered AS ( - SELECT * - FROM augmented - -- This server 2 purposes: make sure we have all the marks (think truncated - -- trace), and remove the NULL ts values due to the LAG window function. - WHERE mark_count = 3 + all_versions AS ( + SELECT '2.1' AS version, * FROM chrome_speedometer_2_1_measure + UNION ALL + SELECT '3' AS version, * FROM chrome_speedometer_3_measure ) -SELECT - iteration, - suite_name, - test_name, - 'async' AS measure_type, - sync_end_ts AS ts, - async_end_ts - sync_end_ts AS dur -FROM filtered -UNION ALL -SELECT - iteration, - suite_name, - test_name, - 'sync' AS measure_type, - start_ts AS ts, - sync_end_ts - start_ts AS dur -FROM filtered; +SELECT ts, dur, name, iteration, suite_name, test_name, measure_type +FROM all_versions +WHERE version = _chrome_speedometer_version(); -- Slice that covers one Speedometer iteration. --- This slice is actually estimated as a default Speedometer run will not emit --- marks to cover this interval. The metrics associated are the same ones --- Speedometer would output, but note we use ns precision (Speedometer uses --- ~100us) so the actual values might differ a bit. Also note Speedometer --- returns the values in ms these here and in ns. +-- Depending on the Speedometer version these slices might need to be estimated +-- as older versions of Speedometer to not emit marks for this interval. The +-- metrics associated are the same ones Speedometer would output, but note we +-- use ns precision (Speedometer uses ~100us) so the actual values might differ +-- a bit. CREATE PERFETTO TABLE chrome_speedometer_iteration( - -- Speedometer iteration. - iteration INT, -- Start timestamp of the iteration ts INT, -- Duration of the iteration dur INT, - -- Total duration of the measures in this iteration - total INT, - -- Average suite duration for this iteration. - mean INT, + -- Iteration name + name STRING, + -- Iteration number + iteration INT, -- Geometric mean of the suite durations for this iteration. - geomean INT, - -- Speedometer score for this iteration (The total score for a run in the average of all iteration scores). - score INT -) AS -SELECT - iteration, - MIN(start) AS ts, - MAX(end) - MIN(start) AS dur, - SUM(suite_total) AS total, - AVG(suite_total)AS mean, - -- Compute geometric mean using LN instead of multiplication to prevent - -- overflows - EXP(AVG(LN(suite_total))) AS geomean, - 1e9 / EXP(AVG(LN(suite_total))) * 60 / 3 AS score -FROM - ( - SELECT - iteration, SUM(dur) AS suite_total, MIN(ts) AS start, MAX(ts + dur) AS end - FROM chrome_speedometer_measure - GROUP BY suite_name, iteration + geomean DOUBLE, + -- Speedometer score for this iteration (The total score for a run in the + -- average of all iteration scores). + score DOUBLE) +AS +WITH + all_versions AS ( + SELECT '2.1' AS version, * FROM chrome_speedometer_2_1_iteration + UNION ALL + SELECT '3' AS version, * FROM chrome_speedometer_3_iteration ) -GROUP BY iteration; +SELECT ts, dur, name, iteration, geomean, score +FROM all_versions +WHERE version = _chrome_speedometer_version(); + +-- Returns the Speedometer score for all iterations in the trace +CREATE PERFETTO FUNCTION chrome_speedometer_score() +-- Speedometer score +RETURNS DOUBLE +AS +SELECT + IIF( + _chrome_speedometer_version() = '3', + chrome_speedometer_3_score(), + chrome_speedometer_2_1_score()); diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/speedometer_2_1.sql b/naiveproxy/src/base/tracing/stdlib/chrome/speedometer_2_1.sql new file mode 100644 index 0000000000..bf89628921 --- /dev/null +++ b/naiveproxy/src/base/tracing/stdlib/chrome/speedometer_2_1.sql @@ -0,0 +1,220 @@ +-- Copyright 2024 The Chromium Authors +-- Use of this source code is governed by a BSD-style license that can be +-- found in the LICENSE file. + +-- List Speedometer 2.1 tests. +CREATE PERFETTO VIEW _chrome_speedometer_2_1_test_name( + -- Suite name + suite_name STRING, + -- Test name + test_name STRING) +AS +WITH + data(suite_name, test_name) AS ( + VALUES('Angular2-TypeScript-TodoMVC', 'Adding100Items'), + ('Angular2-TypeScript-TodoMVC', 'CompletingAllItems'), + ('Angular2-TypeScript-TodoMVC', 'DeletingItems'), + ('AngularJS-TodoMVC', 'Adding100Items'), + ('AngularJS-TodoMVC', 'CompletingAllItems'), + ('AngularJS-TodoMVC', 'DeletingAllItems'), + ('BackboneJS-TodoMVC', 'Adding100Items'), + ('BackboneJS-TodoMVC', 'CompletingAllItems'), + ('BackboneJS-TodoMVC', 'DeletingAllItems'), + ('Elm-TodoMVC', 'Adding100Items'), + ('Elm-TodoMVC', 'CompletingAllItems'), + ('Elm-TodoMVC', 'DeletingItems'), + ('EmberJS-Debug-TodoMVC', 'Adding100Items'), + ('EmberJS-Debug-TodoMVC', 'CompletingAllItems'), + ('EmberJS-Debug-TodoMVC', 'DeletingItems'), + ('EmberJS-TodoMVC', 'Adding100Items'), + ('EmberJS-TodoMVC', 'CompletingAllItems'), + ('EmberJS-TodoMVC', 'DeletingItems'), + ('Flight-TodoMVC', 'Adding100Items'), + ('Flight-TodoMVC', 'CompletingAllItems'), + ('Flight-TodoMVC', 'DeletingItems'), + ('Inferno-TodoMVC', 'Adding100Items'), + ('Inferno-TodoMVC', 'CompletingAllItems'), + ('Inferno-TodoMVC', 'DeletingItems'), + ('Preact-TodoMVC', 'Adding100Items'), + ('Preact-TodoMVC', 'CompletingAllItems'), + ('Preact-TodoMVC', 'DeletingItems'), + ('React-Redux-TodoMVC', 'Adding100Items'), + ('React-Redux-TodoMVC', 'CompletingAllItems'), + ('React-Redux-TodoMVC', 'DeletingItems'), + ('React-TodoMVC', 'Adding100Items'), + ('React-TodoMVC', 'CompletingAllItems'), + ('React-TodoMVC', 'DeletingAllItems'), + ('Vanilla-ES2015-Babel-Webpack-TodoMVC', 'Adding100Items'), + ('Vanilla-ES2015-Babel-Webpack-TodoMVC', 'CompletingAllItems'), + ('Vanilla-ES2015-Babel-Webpack-TodoMVC', 'DeletingItems'), + ('Vanilla-ES2015-TodoMVC', 'Adding100Items'), + ('Vanilla-ES2015-TodoMVC', 'CompletingAllItems'), + ('Vanilla-ES2015-TodoMVC', 'DeletingItems'), + ('VanillaJS-TodoMVC', 'Adding100Items'), + ('VanillaJS-TodoMVC', 'CompletingAllItems'), + ('VanillaJS-TodoMVC', 'DeletingAllItems'), + ('VueJS-TodoMVC', 'Adding100Items'), + ('VueJS-TodoMVC', 'CompletingAllItems'), + ('VueJS-TodoMVC', 'DeletingAllItems'), + ('jQuery-TodoMVC', 'Adding100Items'), + ('jQuery-TodoMVC', 'CompletingAllItems'), + ('jQuery-TodoMVC', 'DeletingAllItems') + ) +SELECT suite_name, test_name FROM data; + +-- Augmented slices for Speedometer measurements. +-- These are the intervals of time Speedometer uses to compute the final score. +-- There are two intervals that are measured for every test: sync and async +-- sync is the time between the start and sync-end marks, async is the time +-- between the sync-end and async-end marks. +CREATE PERFETTO TABLE chrome_speedometer_2_1_measure( + -- Start timestamp of the measure slice + ts INT, + -- Duration of the measure slice + dur INT, + -- Full measure name + name STRING, + -- Speedometer iteration the slice belongs to. + iteration INT, + -- Suite name + suite_name STRING, + -- Test name + test_name STRING, + -- Type of the measure (sync or async) + measure_type STRING) +AS +WITH + mark_type(mark_type) AS ( + VALUES('start'), + ('sync-end'), + ('async-end') + ), + -- Make sure we only look at slices with names we expect. + mark_name AS ( + SELECT + suite_name || '.' || test_name || '-' || mark_type AS name, + suite_name, + test_name, + mark_type + FROM + _chrome_speedometer_2_1_test_name, + mark_type + ), + mark AS ( + SELECT + s.id AS slice_id, + RANK() OVER (PARTITION BY name ORDER BY ts ASC) AS iteration, + m.suite_name, + m.test_name, + m.mark_type + FROM slice AS s + JOIN mark_name AS m + USING (name) + WHERE category = 'blink.user_timing' + ), + -- Get the 3 test timestamps (start, sync-end, async-end) in one row. Using a + -- the LAG window function and partitioning by test. 2 out of the 3 rows + -- generated per test will have some NULL ts values. + augmented AS ( + SELECT + iteration, + suite_name, + test_name, + ts AS async_end_ts, + LAG(ts, 1) + OVER (PARTITION BY iteration, suite_name, test_name ORDER BY ts ASC) + AS sync_end_ts, + LAG(ts, 2) + OVER (PARTITION BY iteration, suite_name, test_name ORDER BY ts ASC) + AS start_ts, + COUNT() + OVER (PARTITION BY iteration, suite_name, test_name ORDER BY ts ASC) + AS mark_count + FROM mark + JOIN slice + USING (slice_id) + ), + filtered AS ( + SELECT * + FROM augmented + -- This server 2 purposes: make sure we have all the marks (think truncated + -- trace), and remove the NULL ts values due to the LAG window function. + WHERE mark_count = 3 + ), + base AS ( + SELECT + sync_end_ts AS ts, + async_end_ts - sync_end_ts AS dur, + iteration, + suite_name, + test_name, + 'async' AS measure_type + FROM filtered + UNION ALL + SELECT + start_ts AS ts, + sync_end_ts - start_ts AS dur, + iteration, + suite_name, + test_name, + 'sync' AS measure_type + FROM filtered + ) +SELECT + ts, + dur, + suite_name || '.' || test_name || '-' || measure_type AS name, + iteration, + suite_name, + test_name, + measure_type +FROM base; + +-- Slice that covers one Speedometer iteration. +-- This slice is actually estimated as a default Speedometer run will not emit +-- marks to cover this interval. The metrics associated are the same ones +-- Speedometer would output, but note we use ns precision (Speedometer uses +-- ~100us) so the actual values might differ a bit. Also note Speedometer +-- returns the values in ms these here and in ns. +CREATE PERFETTO TABLE chrome_speedometer_2_1_iteration( + -- Start timestamp of the iteration + ts INT, + -- Duration of the iteration + dur INT, + -- Iteration name + name STRING, + -- Iteration number + iteration INT, + -- Geometric mean of the suite durations for this iteration. + geomean DOUBLE, + -- Speedometer score for this iteration (The total score for a run in the + -- average of all iteration scores). + score DOUBLE) +AS +SELECT + MIN(start) AS ts, + MAX(END) - MIN(start) AS dur, + 'iteration-' || iteration AS name, + iteration, + -- Compute geometric mean using LN instead of multiplication to prevent + -- overflows + EXP(AVG(LN(suite_total))) AS geomean, + 1000 / EXP(AVG(LN(suite_total))) * 60 / 3 AS score +FROM + ( + SELECT + iteration, + SUM(dur / (1000.0 * 1000.0)) AS suite_total, + MIN(ts) AS start, + MAX(ts + dur) AS END + FROM chrome_speedometer_2_1_measure + GROUP BY suite_name, iteration + ) +GROUP BY iteration; + +-- Returns the Speedometer 2.1 score for all iterations in the trace +CREATE PERFETTO FUNCTION chrome_speedometer_2_1_score() +-- Speedometer 2.1 score +RETURNS DOUBLE +AS +SELECT AVG(score) FROM chrome_speedometer_2_1_iteration; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/speedometer_3.sql b/naiveproxy/src/base/tracing/stdlib/chrome/speedometer_3.sql new file mode 100644 index 0000000000..cc855d8032 --- /dev/null +++ b/naiveproxy/src/base/tracing/stdlib/chrome/speedometer_3.sql @@ -0,0 +1,206 @@ +-- Copyright 2024 The Chromium Authors +-- Use of this source code is governed by a BSD-style license that can be +-- found in the LICENSE file. + +-- List Speedometer 3 tests. +CREATE PERFETTO VIEW _chrome_speedometer_3_test_name( + -- Suite name + suite_name STRING, + -- Test name + test_name STRING) +AS +WITH + data(suite_name, test_name) AS ( + VALUES('TodoMVC-JavaScript-ES5', 'Adding100Items'), + ('TodoMVC-JavaScript-ES5', 'CompletingAllItems'), + ('TodoMVC-JavaScript-ES5', 'DeletingAllItems'), + ('TodoMVC-JavaScript-ES6-Webpack-Complex-DOM', 'Adding100Items'), + ('TodoMVC-JavaScript-ES6-Webpack-Complex-DOM', 'CompletingAllItems'), + ('TodoMVC-JavaScript-ES6-Webpack-Complex-DOM', 'DeletingAllItems'), + ('TodoMVC-WebComponents', 'Adding100Items'), + ('TodoMVC-WebComponents', 'CompletingAllItems'), + ('TodoMVC-WebComponents', 'DeletingAllItems'), + ('TodoMVC-React-Complex-DOM', 'Adding100Items'), + ('TodoMVC-React-Complex-DOM', 'CompletingAllItems'), + ('TodoMVC-React-Complex-DOM', 'DeletingAllItems'), + ('TodoMVC-React-Redux', 'Adding100Items'), + ('TodoMVC-React-Redux', 'CompletingAllItems'), + ('TodoMVC-React-Redux', 'DeletingAllItems'), + ('TodoMVC-Backbone', 'Adding100Items'), + ('TodoMVC-Backbone', 'CompletingAllItems'), + ('TodoMVC-Backbone', 'DeletingAllItems'), + ('TodoMVC-Angular-Complex-DOM', 'Adding100Items'), + ('TodoMVC-Angular-Complex-DOM', 'CompletingAllItems'), + ('TodoMVC-Angular-Complex-DOM', 'DeletingAllItems'), + ('TodoMVC-Vue', 'Adding100Items'), + ('TodoMVC-Vue', 'CompletingAllItems'), + ('TodoMVC-Vue', 'DeletingAllItems'), + ('TodoMVC-jQuery', 'Adding100Items'), + ('TodoMVC-jQuery', 'CompletingAllItems'), + ('TodoMVC-jQuery', 'DeletingAllItems'), + ('TodoMVC-Preact-Complex-DOM', 'Adding100Items'), + ('TodoMVC-Preact-Complex-DOM', 'CompletingAllItems'), + ('TodoMVC-Preact-Complex-DOM', 'DeletingAllItems'), + ('TodoMVC-Svelte-Complex-DOM', 'Adding100Items'), + ('TodoMVC-Svelte-Complex-DOM', 'CompletingAllItems'), + ('TodoMVC-Svelte-Complex-DOM', 'DeletingAllItems'), + ('TodoMVC-Lit-Complex-DOM', 'Adding100Items'), + ('TodoMVC-Lit-Complex-DOM', 'CompletingAllItems'), + ('TodoMVC-Lit-Complex-DOM', 'DeletingAllItems'), + ('NewsSite-Next', 'NavigateToUS'), + ('NewsSite-Next', 'NavigateToWorld'), + ('NewsSite-Next', 'NavigateToPolitics'), + ('NewsSite-Nuxt', 'NavigateToUS'), + ('NewsSite-Nuxt', 'NavigateToWorld'), + ('NewsSite-Nuxt', 'NavigateToPolitics'), + ('Editor-CodeMirror', 'Long'), + ('Editor-CodeMirror', 'Highlight'), + ('Editor-TipTap', 'Long'), + ('Editor-TipTap', 'Highlight'), + ('Charts-observable-plot', 'Stacked by 6'), + ('Charts-observable-plot', 'Stacked by 20'), + ('Charts-observable-plot', 'Dotted'), + ('Charts-chartjs', 'Draw scatter'), + ('Charts-chartjs', 'Show tooltip'), + ('Charts-chartjs', 'Draw opaque scatter'), + ('React-Stockcharts-SVG', 'Render'), + ('React-Stockcharts-SVG', 'PanTheChart'), + ('React-Stockcharts-SVG', 'ZoomTheChart'), + ('Perf-Dashboard', 'Render'), + ('Perf-Dashboard', 'SelectingPoints'), + ('Perf-Dashboard', 'SelectingRange') + ) +SELECT suite_name, test_name FROM data; + +CREATE PERFETTO VIEW _chrome_speedometer_iteration_slice +AS +WITH data AS ( + SELECT + *, + substr(name, 1 + length('iteration-')) AS iteration_str + FROM + slice + WHERE + category = 'blink.user_timing' + AND name GLOB 'iteration-*' +) +SELECT + *, + CAST(iteration_str AS INT) as iteration +FROM data +WHERE iteration_str = iteration; + +-- Augmented slices for Speedometer measurements. +-- These are the intervals of time Speedometer uses to compute the final score. +-- There are two intervals that are measured for every test: sync and async. +CREATE PERFETTO TABLE chrome_speedometer_3_measure( + -- Start timestamp of the measure slice + ts INT, + -- Duration of the measure slice + dur INT, + -- Full measure name + name STRING, + -- Speedometer iteration the slice belongs to. + iteration INT, + -- Suite name + suite_name STRING, + -- Test name + test_name STRING, + -- Type of the measure (sync or async) + measure_type STRING) +AS +WITH + measure_type(measure_type) AS ( + VALUES('sync'), + ('async') + ), + measure_name AS ( + SELECT + suite_name || '.' || test_name || '-' || measure_type AS name, + suite_name, + test_name, + measure_type + FROM + _chrome_speedometer_3_test_name, + measure_type + ), + measure_slice AS ( + SELECT + s.ts, + s.dur, + s.name, + m.suite_name, + m.test_name, + m.measure_type + FROM + slice s, + measure_name AS m + USING (name) + WHERE + s.category = 'blink.user_timing' + ) +SELECT + s.ts, + s.dur, + s.name, + i.iteration, + s.suite_name, + s.test_name, + s.measure_type +FROM + measure_slice AS s, + _chrome_speedometer_iteration_slice i +ON (s.ts >= i.ts AND s.ts < i.ts + i.dur) +ORDER BY s.ts ASC; + +-- Slice that covers one Speedometer iteration. +-- The metrics associated are the same ones +-- Speedometer would output, but note we use ns precision (Speedometer uses +-- ~100us) so the actual values might differ a bit. +CREATE PERFETTO TABLE chrome_speedometer_3_iteration( + -- Start timestamp of the iteration + ts INT, + -- Duration of the iteration + dur INT, + -- Iteration name + name STRING, + -- Iteration number + iteration INT, + -- Geometric mean of the suite durations for this iteration. + geomean DOUBLE, + -- Speedometer score for this iteration (The total score for a run in the + -- average of all iteration scores). + score DOUBLE) +AS +WITH + suite AS ( + SELECT + iteration, suite_name, SUM(dur / (1000.0 * 1000.0)) AS suite_total + FROM chrome_speedometer_3_measure + GROUP BY iteration, suite_name + ), + iteration AS ( + SELECT + iteration, + -- Compute geometric mean using LN instead of multiplication to prevent + -- overflows + EXP(AVG(LN(suite_total))) AS geomean + FROM suite + GROUP BY iteration + ) +SELECT + s.ts, + s.dur, + s.name, + i.iteration, + i.geomean, + 1000.0 / i.geomean AS score +FROM iteration AS i, _chrome_speedometer_iteration_slice AS s +USING (iteration); + +-- Returns the Speedometer 3 score for all iterations in the trace +CREATE PERFETTO FUNCTION chrome_speedometer_3_score() +-- Speedometer 3 score +RETURNS DOUBLE +AS +SELECT AVG(score) FROM chrome_speedometer_3_iteration; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/tasks.sql b/naiveproxy/src/base/tracing/stdlib/chrome/tasks.sql index a177cbaa66..7c09a643f9 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/tasks.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/tasks.sql @@ -105,7 +105,7 @@ SELECT -- -- Note: this might include messages received within a sync mojo call. -- TODO(altimin): This should use EXTEND_TABLE when it becomes available. -CREATE TABLE _chrome_mojo_slices AS +CREATE PERFETTO TABLE _chrome_mojo_slices AS WITH -- Select all new-style (post crrev.com/c/3270337) mojo slices and -- generate |task_name| for them. @@ -153,17 +153,16 @@ old_non_associated_mojo_slices AS ( FROM slice WHERE category GLOB "*toplevel*" AND name = "Connector::DispatchMessage" -) +), +merged AS ( -- Merge all mojo slices. SELECT * FROM new_mojo_slices UNION ALL SELECT * FROM old_associated_mojo_slices UNION ALL -SELECT * FROM old_non_associated_mojo_slices; - --- As we lookup by ID on |_chrome_mojo_slices| table, add an index on --- id to make lookups fast. -CREATE INDEX _chrome_mojo_slices_idx ON _chrome_mojo_slices(id); +SELECT * FROM old_non_associated_mojo_slices +) +SELECT * FROM merged ORDER BY id; -- This table contains a list of slices corresponding to the _representative_ -- Chrome Java view operations. @@ -178,7 +177,7 @@ CREATE INDEX _chrome_mojo_slices_idx ON _chrome_mojo_slices(id); -- capture toolbar screenshot. -- @column is_hardware_screenshot BOOL Whether this slice is a part of accelerated -- capture toolbar screenshot. -CREATE TABLE _chrome_java_views AS +CREATE PERFETTO TABLE _chrome_java_views AS WITH -- .draw, .onLayout and .onMeasure parts of the java view names don't add much, strip them. java_slices_with_trimmed_names AS ( @@ -363,7 +362,7 @@ LEFT JOIN root_slice_and_java_view_not_grouped java_view USING (id) GROUP BY root.id; -- A list of tasks executed by Chrome scheduler. -CREATE TABLE _chrome_scheduler_tasks AS +CREATE PERFETTO TABLE _chrome_scheduler_tasks AS SELECT id FROM slice @@ -476,7 +475,7 @@ WHERE task.id = $slice_id; -- @column task_name STRING Name for the given task. -- @column task_type STRING Type of the task (e.g. "scheduler"). -- @column scheduling_delay INT -CREATE TABLE _chrome_tasks AS +CREATE PERFETTO TABLE _chrome_tasks AS WITH -- Select slices from "toplevel" category which do not have another -- "toplevel" slice as ancestor. The possible cases include sync mojo messages @@ -614,7 +613,7 @@ CREATE PERFETTO VIEW chrome_tasks( -- Alias of |slice.track_id|. track_id INT, -- Alias of |slice.category|. - category INT, + category STRING, -- Alias of |slice.arg_set_id|. arg_set_id INT, -- Alias of |slice.thread_ts|. diff --git a/naiveproxy/src/base/tracing/test/README b/naiveproxy/src/base/tracing/test/README.md similarity index 82% rename from naiveproxy/src/base/tracing/test/README rename to naiveproxy/src/base/tracing/test/README.md index 065bef0143..f6449cbab1 100644 --- a/naiveproxy/src/base/tracing/test/README +++ b/naiveproxy/src/base/tracing/test/README.md @@ -25,13 +25,13 @@ If you are adding a **new TestSuite**, be sure to add it to `include_index.py` s ### Adding New Test Data -If your test requires modifying or adding new test data i.e. a new trace in `base/tracing/test/data`, you will need to upload this to the GCS bucket. +If your test requires modifying or adding new test data i.e. a new trace in `base/tracing/test/data`, you will need to perform the following steps: +**1**. Upload the file to the GCS bucket: ``` -$ base/tracing/test/test_data.py upload + $ base/tracing/test/test_data.py upload ``` - -This script will output a deps entry which you will need to add to the [DEPS file](../../../DEPS) (see examples in the `src/base/tracing/test/data` entry). +**2**. Add the deps entry produced by the above script to the [DEPS file](../../../DEPS) (see examples in the `src/base/tracing/test/data` entry). ``` { "path": { @@ -50,7 +50,9 @@ This script will output a deps entry which you will need to add to the [DEPS fil ``` You will need to **manually** add this to the deps entry. After adding this entry, running `gclient sync` will download the test files in your local repo. See these [docs](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/gcs_dependencies.md) for the GCS dependency workflow. -Perfetto has it's own way to download GCS objects with the [test_data](../../../third_party/perfetto/tools/test_data) script. This script uses .sha256 files to download. The `test_data.py upload` command will also generate the `file_name-a1b2c3f4.sha256` in `base/tracing/test/data`. You will need to check-in these files in the codebase so they can by rolled to Perfetto, so the tests can work there too. +**Note:** you can get the DEPS entry separately from the upload step by calling `base/tracing/test/test_data.py get_deps ` or `base/tracing/test/test_data.py get_all_deps`. + +**3**. Check in the .sha256 files produced by the `test_data.py upload` command (`file_name-a1b2c3f4.sha256` in `base/tracing/test/data`). These files will be rolled to Perfetto and used to download the GCS objects by Perfetto's own [test_data](../../../third_party/perfetto/tools/test_data) script. ## Writing TestTraceProcessor Tests diff --git a/naiveproxy/src/base/tracing/test/data/.test_data_chrome_input_with_frame_view_new_pftrace-e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12_hash b/naiveproxy/src/base/tracing/test/data/.test_data_chrome_input_with_frame_view_new_pftrace-e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12_hash new file mode 100644 index 0000000000..b924d64c4a --- /dev/null +++ b/naiveproxy/src/base/tracing/test/data/.test_data_chrome_input_with_frame_view_new_pftrace-e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12_hash @@ -0,0 +1 @@ +e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12 diff --git a/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_is_first_class_gcs b/naiveproxy/src/base/tracing/test/data/.test_data_chrome_input_with_frame_view_new_pftrace-e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12_is_first_class_gcs similarity index 100% rename from naiveproxy/src/base/tracing/test/data/.test_data_speedometer_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_is_first_class_gcs rename to naiveproxy/src/base/tracing/test/data/.test_data_chrome_input_with_frame_view_new_pftrace-e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12_is_first_class_gcs diff --git a/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_hash b/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_21_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_hash similarity index 100% rename from naiveproxy/src/base/tracing/test/data/.test_data_speedometer_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_hash rename to naiveproxy/src/base/tracing/test/data/.test_data_speedometer_21_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_hash diff --git a/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_21_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_is_first_class_gcs b/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_21_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_is_first_class_gcs new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_21_perfetto_trace_gz-8a159b354d74a3ca0d38ce9cd071ef47de322db4261ee266bfafe04d70310529_is_first_class_gcs @@ -0,0 +1 @@ +1 diff --git a/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_3_perfetto_trace_gz-b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02_hash b/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_3_perfetto_trace_gz-b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02_hash new file mode 100644 index 0000000000..fbe9485cd1 --- /dev/null +++ b/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_3_perfetto_trace_gz-b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02_hash @@ -0,0 +1 @@ +b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02 diff --git a/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_3_perfetto_trace_gz-b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02_is_first_class_gcs b/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_3_perfetto_trace_gz-b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02_is_first_class_gcs new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/naiveproxy/src/base/tracing/test/data/.test_data_speedometer_3_perfetto_trace_gz-b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02_is_first_class_gcs @@ -0,0 +1 @@ +1 diff --git a/naiveproxy/src/base/tracing/test/data/chrome_input_with_frame_view_new.pftrace b/naiveproxy/src/base/tracing/test/data/chrome_input_with_frame_view_new.pftrace new file mode 100644 index 0000000000..6cb4a638b7 Binary files /dev/null and b/naiveproxy/src/base/tracing/test/data/chrome_input_with_frame_view_new.pftrace differ diff --git a/naiveproxy/src/base/tracing/test/data/speedometer.perfetto_trace.gz b/naiveproxy/src/base/tracing/test/data/speedometer_21.perfetto_trace.gz similarity index 100% rename from naiveproxy/src/base/tracing/test/data/speedometer.perfetto_trace.gz rename to naiveproxy/src/base/tracing/test/data/speedometer_21.perfetto_trace.gz diff --git a/naiveproxy/src/base/tracing/test/data/speedometer_3.perfetto_trace.gz b/naiveproxy/src/base/tracing/test/data/speedometer_3.perfetto_trace.gz new file mode 100644 index 0000000000..4ad62ae101 Binary files /dev/null and b/naiveproxy/src/base/tracing/test/data/speedometer_3.perfetto_trace.gz differ diff --git a/naiveproxy/src/base/tracing/test/data_sha256/chrome_input_with_frame_view_new.pftrace.sha256 b/naiveproxy/src/base/tracing/test/data_sha256/chrome_input_with_frame_view_new.pftrace.sha256 new file mode 100644 index 0000000000..3f18a44361 --- /dev/null +++ b/naiveproxy/src/base/tracing/test/data_sha256/chrome_input_with_frame_view_new.pftrace.sha256 @@ -0,0 +1 @@ +e901ad9577088e62c921dd8bfcb43d652ecf49fa69b5b57f81bb3d27dbe94e12 \ No newline at end of file diff --git a/naiveproxy/src/base/tracing/test/data_sha256/speedometer.perfetto_trace.gz.sha256 b/naiveproxy/src/base/tracing/test/data_sha256/speedometer_21.perfetto_trace.gz.sha256 similarity index 100% rename from naiveproxy/src/base/tracing/test/data_sha256/speedometer.perfetto_trace.gz.sha256 rename to naiveproxy/src/base/tracing/test/data_sha256/speedometer_21.perfetto_trace.gz.sha256 diff --git a/naiveproxy/src/base/tracing/test/data_sha256/speedometer_3.perfetto_trace.gz.sha256 b/naiveproxy/src/base/tracing/test/data_sha256/speedometer_3.perfetto_trace.gz.sha256 new file mode 100644 index 0000000000..481be39039 --- /dev/null +++ b/naiveproxy/src/base/tracing/test/data_sha256/speedometer_3.perfetto_trace.gz.sha256 @@ -0,0 +1 @@ +b2c77fbe2c17363432a1ad0c05c1c1c20d3ebc62bda92c041d39918011af6f02 \ No newline at end of file diff --git a/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/chrome_speedometer.out b/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/chrome_speedometer.out deleted file mode 100644 index 2a524853ad..0000000000 --- a/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/chrome_speedometer.out +++ /dev/null @@ -1,11 +0,0 @@ -"iteration","ts","dur","total","mean","geomean","score","num_measurements" -1,693997310311984,7020297000,5191976000,"324498500.0","254177934.4","78.7",96 -2,694004414619984,6308034000,4600497000,"287531062.5","224382472.1","89.1",96 -3,694010770005984,5878289000,4209484000,"263092750.0","200261720.2","99.9",96 -4,694016699502984,5934578000,4213632000,"263352000.0","201163561.9","99.4",96 -5,694022683560984,5952163000,4259111000,"266194437.5","203014932.4","98.5",96 -6,694028690570984,5966530000,4269728000,"266858000.0","204306068.2","97.9",96 -7,694034719276984,5853043000,4219351000,"263709437.5","200358118.8","99.8",96 -8,694040637173984,6087435000,4261576000,"266348500.0","202962356.2","98.5",96 -9,694046772284984,6040820000,4245060000,"265316250.0","199331263.1","100.3",96 -10,694052857814984,6063770000,4388487000,"274280437.5","208004176.2","96.2",96 diff --git a/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_v3_new.out b/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_v3_new.out new file mode 100644 index 0000000000..7203356b2b --- /dev/null +++ b/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/scroll_jank_v3_new.out @@ -0,0 +1,9 @@ +"cause_of_jank","sub_cause_of_jank","delay_since_last_frame","vsync_interval" +"BrowserMainToRendererCompositor","[NULL]",22.219000,11.111000 +"SubmitCompositorFrameToPresentationCompositorFrame","StartDrawToSwapStart",22.242000,11.111000 +"SubmitCompositorFrameToPresentationCompositorFrame","StartDrawToSwapStart",22.194000,11.111000 +"SubmitCompositorFrameToPresentationCompositorFrame","StartDrawToSwapStart",22.223000,11.111000 +"SubmitCompositorFrameToPresentationCompositorFrame","SwapEndToPresentationCompositorFrame",22.222000,11.111000 +"SubmitCompositorFrameToPresentationCompositorFrame","StartDrawToSwapStart",33.326000,11.111000 +"SubmitCompositorFrameToPresentationCompositorFrame","StartDrawToSwapStart",22.220000,11.111000 +"SubmitCompositorFrameToPresentationCompositorFrame","StartDrawToSwapStart",33.324000,11.111000 diff --git a/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/tests.py b/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/tests.py index ddc088e526..d2afd6a05f 100755 --- a/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/tests.py +++ b/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/tests.py @@ -109,32 +109,85 @@ class ChromeStdlib(TestSuite): "Net.HttpResponseCode",541 """)) - def test_speedometer(self): + def test_speedometer_2_1_score(self): return DiffTestBlueprint( - trace=DataPath('speedometer.perfetto_trace.gz'), + trace=DataPath('speedometer_21.perfetto_trace.gz'), + query=""" + INCLUDE PERFETTO MODULE chrome.speedometer; + + SELECT format("%.1f", chrome_speedometer_score()) AS score + """, + out=Csv(""" + "score" + "95.8" + """)) + + def test_speedometer_2_1_iteration(self): + return DiffTestBlueprint( + trace=DataPath('speedometer_21.perfetto_trace.gz'), query=""" INCLUDE PERFETTO MODULE chrome.speedometer; SELECT - iteration, - ts, - dur, - total, - format('%.1f', mean) AS mean, - format('%.1f', geomean) AS geomean, - format('%.1f', score) AS score, - num_measurements - FROM - chrome_speedometer_iteration, - ( - SELECT iteration, COUNT(*) AS num_measurements - FROM chrome_speedometer_measure - GROUP BY iteration - ) - USING (iteration) - ORDER BY iteration; + ts,dur,name,iteration, + format("%.1f", geomean) AS geomean, + format("%.1f", score) AS score + FROM chrome_speedometer_iteration + ORDER BY iteration ASC """, - out=Path('chrome_speedometer.out')) + out=Csv(""" + "ts","dur","name","iteration","geomean","score" + 693997310311984,7020297000,"iteration-1",1,"254.2","78.7" + 694004414619984,6308034000,"iteration-2",2,"224.4","89.1" + 694010770005984,5878289000,"iteration-3",3,"200.3","99.9" + 694016699502984,5934578000,"iteration-4",4,"201.2","99.4" + 694022683560984,5952163000,"iteration-5",5,"203.0","98.5" + 694028690570984,5966530000,"iteration-6",6,"204.3","97.9" + 694034719276984,5853043000,"iteration-7",7,"200.4","99.8" + 694040637173984,6087435000,"iteration-8",8,"203.0","98.5" + 694046772284984,6040820000,"iteration-9",9,"199.3","100.3" + 694052857814984,6063770000,"iteration-10",10,"208.0","96.2" + """)) + + def test_speedometer_3_score(self): + return DiffTestBlueprint( + trace=DataPath('speedometer_3.perfetto_trace.gz'), + query=""" + INCLUDE PERFETTO MODULE chrome.speedometer; + + SELECT format("%.2f", chrome_speedometer_score()) AS score + """, + out=Csv(""" + "score" + "9.32" + """)) + + def test_speedometer_3_iteration(self): + return DiffTestBlueprint( + trace=DataPath('speedometer_3.perfetto_trace.gz'), + query=""" + INCLUDE PERFETTO MODULE chrome.speedometer; + + SELECT + ts,dur,name,iteration, + format("%.1f", geomean) AS geomean, + format("%.1f", score) AS score + FROM chrome_speedometer_iteration + ORDER BY iteration ASC + """, + out=Csv(""" + "ts","dur","name","iteration","geomean","score" + 303831755756,29237440000,"iteration-0",0,"149.6","6.7" + 333069212756,5852045000,"iteration-1",1,"110.7","9.0" + 338921282756,5128440000,"iteration-2",2,"113.5","8.8" + 344049763756,4640412000,"iteration-3",3,"105.0","9.5" + 348690198756,4790109000,"iteration-4",4,"106.9","9.4" + 353480329756,5150878000,"iteration-5",5,"106.0","9.4" + 358631265756,4825246000,"iteration-6",6,"103.1","9.7" + 363456560756,4447621000,"iteration-7",7,"95.5","10.5" + 367904208756,4566333000,"iteration-8",8,"100.8","9.9" + 372470568756,4301553000,"iteration-9",9,"96.9","10.3" + """)) # CPU power ups def test_cpu_powerups(self): @@ -149,4 +202,4 @@ class ChromeStdlib(TestSuite): 424,2 703,2 708,2 - """)) \ No newline at end of file + """)) diff --git a/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py b/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py index 5a70b29e5f..fcb98a79dc 100755 --- a/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py +++ b/naiveproxy/src/base/tracing/test/trace_processor/diff_tests/chrome/tests_scroll_jank.py @@ -26,6 +26,25 @@ class ChromeScrollJankStdlib(TestSuite): """, out=Path('scroll_jank_v3.out')) + # https://crrev.com/c/5634125 introduces new *ToPresentation slices, + # and a new test trace file was added that contains them. + # TODO(b/341047059): after M128 is rolled out to stable, + # the test using the old trace can be removed. + def test_chrome_frames_with_missed_vsyncs_m128(self): + return DiffTestBlueprint( + trace=DataPath('chrome_input_with_frame_view_new.pftrace'), + query=""" + INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3; + + SELECT + cause_of_jank, + sub_cause_of_jank, + delay_since_last_frame, + vsync_interval + FROM chrome_janky_frames; + """, + out=Path('scroll_jank_v3_new.out')) + def test_chrome_frames_with_missed_vsyncs_percentage(self): return DiffTestBlueprint( trace=DataPath('chrome_input_with_frame_view.pftrace'), @@ -61,26 +80,6 @@ class ChromeScrollJankStdlib(TestSuite): 4652,1035868607429926,1517121000,1035868607429926,1035870086449926 """)) - def test_chrome_scroll_intervals(self): - return DiffTestBlueprint( - trace=DataPath('chrome_input_with_frame_view.pftrace'), - query=""" - INCLUDE PERFETTO MODULE chrome.chrome_scrolls; - - SELECT - id, - ts, - dur - FROM chrome_scrolling_intervals - ORDER by id; - """, - out=Csv(""" - "id","ts","dur" - 1,1035865535981926,1255745000 - 2,1035866799527926,1458525000 - 3,1035868607429926,1517121000 - """)) - def test_chrome_scroll_input_offsets(self): return DiffTestBlueprint( trace=DataPath('scroll_offsets_trace_2.pftrace'), @@ -99,11 +98,11 @@ class ChromeScrollJankStdlib(TestSuite): """, out=Csv(""" "scroll_update_id","ts","delta_y","relative_offset_y" - 130,1349914859791,-6.932281,-220.834854 - 132,1349923327791,-32.999954,-253.834808 - 134,1349931893791,-39.999954,-293.834762 - 140,1349956886791,-51.000046,-344.834808 - 147,1349982489791,-89.808540,-434.643348 + 130,1349914859791,-6.932281,-6.932281 + 132,1349923327791,-32.999954,-39.932235 + 134,1349931893791,-39.999954,-79.932189 + 136,1349940237791,-50.000076,-129.932266 + 138,1349948670791,-57.999939,-187.932205 """)) def test_chrome_janky_event_latencies_v3(self): @@ -231,6 +230,34 @@ class ChromeScrollJankStdlib(TestSuite): 147,1350018935791,-89.808540,-379.559608 """)) + def test_chrome_predictor_metrics(self): + return DiffTestBlueprint( + trace=DataPath('scroll_offsets_trace_2.pftrace'), + query=""" + INCLUDE PERFETTO MODULE chrome.scroll_jank.predictor_error; + + SELECT + scroll_update_id, + present_ts, + delta_y, + prev_delta, + next_delta, + predictor_jank, + delta_threshold + FROM chrome_predictor_error + WHERE scroll_update_id IS NOT NULL + ORDER by present_ts + LIMIT 5; + """, + out=Csv(""" + "scroll_update_id","present_ts","delta_y","prev_delta","next_delta","predictor_jank","delta_threshold" + 132,1349985554791,-16.573090,-6.932281,-107.517273,0.000000,1.200000 + 134,1349996680791,-107.517273,-16.573090,-158.728424,0.000000,1.200000 + 140,1350007850791,-158.728424,-107.517273,-89.808540,0.276306,1.200000 + 147,1350018935791,-89.808540,-158.728424,-47.583618,0.000000,1.200000 + 148,1350030066791,-47.583618,-89.808540,-98.283493,0.687384,1.200000 + """)) + def test_scroll_jank_cause_map(self): return DiffTestBlueprint( trace=TextProto(''), diff --git a/naiveproxy/src/base/types/optional_ref.h b/naiveproxy/src/base/types/optional_ref.h index 76bcced5e1..3dcdf6cc42 100644 --- a/naiveproxy/src/base/types/optional_ref.h +++ b/naiveproxy/src/base/types/optional_ref.h @@ -84,6 +84,8 @@ class optional_ref { std::is_convertible_v; public: + using value_type = T; + // Constructs an empty `optional_ref`. constexpr optional_ref() = default; // NOLINTNEXTLINE(google-explicit-constructor) @@ -168,6 +170,7 @@ class optional_ref { // Returns `true` iff the `optional_ref` is non-empty. constexpr bool has_value() const { return ptr_; } + constexpr explicit operator bool() const { return has_value(); } // CHECKs if the `optional_ref` is empty. constexpr T& value() const { diff --git a/naiveproxy/src/base/unguessable_token.cc b/naiveproxy/src/base/unguessable_token.cc index 1f91a938ca..ea33ca66f3 100644 --- a/naiveproxy/src/base/unguessable_token.cc +++ b/naiveproxy/src/base/unguessable_token.cc @@ -5,6 +5,7 @@ #include "base/unguessable_token.h" #include +#include #include "base/check.h" #include "base/format_macros.h" @@ -47,7 +48,7 @@ std::optional UnguessableToken::Deserialize(uint64_t high, // static std::optional UnguessableToken::DeserializeFromString( - StringPiece string_representation) { + std::string_view string_representation) { auto token = Token::FromString(string_representation); // A zeroed out token means that it's not initialized via Create(). if (!token.has_value() || token.value().is_zero()) { diff --git a/naiveproxy/src/base/unguessable_token.h b/naiveproxy/src/base/unguessable_token.h index 2ec3340af0..2021d4b35e 100644 --- a/naiveproxy/src/base/unguessable_token.h +++ b/naiveproxy/src/base/unguessable_token.h @@ -7,14 +7,15 @@ #include #include + #include #include +#include #include #include "base/base_export.h" #include "base/check.h" #include "base/containers/span.h" -#include "base/strings/string_piece.h" #include "base/token.h" namespace base { @@ -74,7 +75,7 @@ class BASE_EXPORT UnguessableToken { // the given string does not represent a valid serialized `UnguessableToken`. // This should be handled as a security issue. static std::optional DeserializeFromString( - StringPiece string_representation); + std::string_view string_representation); // Creates an empty UnguessableToken. // Assign to it with Create() before using it. diff --git a/naiveproxy/src/base/values.cc b/naiveproxy/src/base/values.cc index 92cbce9418..10daa37a5f 100644 --- a/naiveproxy/src/base/values.cc +++ b/naiveproxy/src/base/values.cc @@ -48,24 +48,24 @@ static_assert(std::size(kTypeNames) == static_cast(Value::Type::LIST) + 1, "kTypeNames Has Wrong Size"); -// Helper class to enumerate the path components from a StringPiece +// Helper class to enumerate the path components from a std::string_view // without performing heap allocations. Components are simply separated // by single dots (e.g. "foo.bar.baz" -> ["foo", "bar", "baz"]). // // Usage example: // PathSplitter splitter(some_path); // while (splitter.HasNext()) { -// StringPiece component = splitter.Next(); +// std::string_view component = splitter.Next(); // ... // } // class PathSplitter { public: - explicit PathSplitter(StringPiece path) : path_(path) {} + explicit PathSplitter(std::string_view path) : path_(path) {} bool HasNext() const { return pos_ < path_.size(); } - StringPiece Next() { + std::string_view Next() { DCHECK(HasNext()); size_t start = pos_; size_t pos = path_.find('.', start); @@ -81,7 +81,7 @@ class PathSplitter { } private: - StringPiece path_; + std::string_view path_; size_t pos_ = 0; }; @@ -184,9 +184,9 @@ Value::Value(int value) : data_(value) {} Value::Value(double value) : data_(absl::in_place_type_t(), value) {} -Value::Value(StringPiece value) : Value(std::string(value)) {} +Value::Value(std::string_view value) : Value(std::string(value)) {} -Value::Value(StringPiece16 value) : Value(UTF16ToUTF8(value)) {} +Value::Value(std::u16string_view value) : Value(UTF16ToUTF8(value)) {} Value::Value(const char* value) : Value(std::string(value)) {} @@ -426,66 +426,66 @@ void Value::Dict::Merge(Dict dict) { } } -const Value* Value::Dict::Find(StringPiece key) const { +const Value* Value::Dict::Find(std::string_view key) const { DCHECK(IsStringUTF8AllowingNoncharacters(key)); return FindPtrOrNull(storage_, key); } -Value* Value::Dict::Find(StringPiece key) { +Value* Value::Dict::Find(std::string_view key) { return FindPtrOrNull(storage_, key); } -std::optional Value::Dict::FindBool(StringPiece key) const { +std::optional Value::Dict::FindBool(std::string_view key) const { const Value* v = Find(key); return v ? v->GetIfBool() : std::nullopt; } -std::optional Value::Dict::FindInt(StringPiece key) const { +std::optional Value::Dict::FindInt(std::string_view key) const { const Value* v = Find(key); return v ? v->GetIfInt() : std::nullopt; } -std::optional Value::Dict::FindDouble(StringPiece key) const { +std::optional Value::Dict::FindDouble(std::string_view key) const { const Value* v = Find(key); return v ? v->GetIfDouble() : std::nullopt; } -const std::string* Value::Dict::FindString(StringPiece key) const { +const std::string* Value::Dict::FindString(std::string_view key) const { const Value* v = Find(key); return v ? v->GetIfString() : nullptr; } -std::string* Value::Dict::FindString(StringPiece key) { +std::string* Value::Dict::FindString(std::string_view key) { Value* v = Find(key); return v ? v->GetIfString() : nullptr; } -const Value::BlobStorage* Value::Dict::FindBlob(StringPiece key) const { +const Value::BlobStorage* Value::Dict::FindBlob(std::string_view key) const { const Value* v = Find(key); return v ? v->GetIfBlob() : nullptr; } -const Value::Dict* Value::Dict::FindDict(StringPiece key) const { +const Value::Dict* Value::Dict::FindDict(std::string_view key) const { const Value* v = Find(key); return v ? v->GetIfDict() : nullptr; } -Value::Dict* Value::Dict::FindDict(StringPiece key) { +Value::Dict* Value::Dict::FindDict(std::string_view key) { Value* v = Find(key); return v ? v->GetIfDict() : nullptr; } -const Value::List* Value::Dict::FindList(StringPiece key) const { +const Value::List* Value::Dict::FindList(std::string_view key) const { const Value* v = Find(key); return v ? v->GetIfList() : nullptr; } -Value::List* Value::Dict::FindList(StringPiece key) { +Value::List* Value::Dict::FindList(std::string_view key) { Value* v = Find(key); return v ? v->GetIfList() : nullptr; } -Value::Dict* Value::Dict::EnsureDict(StringPiece key) { +Value::Dict* Value::Dict::EnsureDict(std::string_view key) { Value::Dict* dict = FindDict(key); if (dict) { return dict; @@ -493,7 +493,7 @@ Value::Dict* Value::Dict::EnsureDict(StringPiece key) { return &Set(key, base::Value::Dict())->GetDict(); } -Value::List* Value::Dict::EnsureList(StringPiece key) { +Value::List* Value::Dict::EnsureList(std::string_view key) { Value::List* list = FindList(key); if (list) { return list; @@ -501,7 +501,7 @@ Value::List* Value::Dict::EnsureList(StringPiece key) { return &Set(key, base::Value::List())->GetList(); } -Value* Value::Dict::Set(StringPiece key, Value&& value) & { +Value* Value::Dict::Set(std::string_view key, Value&& value) & { DCHECK(IsStringUTF8AllowingNoncharacters(key)); auto wrapped_value = std::make_unique(std::move(value)); @@ -510,107 +510,109 @@ Value* Value::Dict::Set(StringPiece key, Value&& value) & { return raw_value; } -Value* Value::Dict::Set(StringPiece key, bool value) & { +Value* Value::Dict::Set(std::string_view key, bool value) & { return Set(key, Value(value)); } -Value* Value::Dict::Set(StringPiece key, int value) & { +Value* Value::Dict::Set(std::string_view key, int value) & { return Set(key, Value(value)); } -Value* Value::Dict::Set(StringPiece key, double value) & { +Value* Value::Dict::Set(std::string_view key, double value) & { return Set(key, Value(value)); } -Value* Value::Dict::Set(StringPiece key, StringPiece value) & { +Value* Value::Dict::Set(std::string_view key, std::string_view value) & { return Set(key, Value(value)); } -Value* Value::Dict::Set(StringPiece key, StringPiece16 value) & { +Value* Value::Dict::Set(std::string_view key, std::u16string_view value) & { return Set(key, Value(value)); } -Value* Value::Dict::Set(StringPiece key, const char* value) & { +Value* Value::Dict::Set(std::string_view key, const char* value) & { return Set(key, Value(value)); } -Value* Value::Dict::Set(StringPiece key, const char16_t* value) & { +Value* Value::Dict::Set(std::string_view key, const char16_t* value) & { return Set(key, Value(value)); } -Value* Value::Dict::Set(StringPiece key, std::string&& value) & { +Value* Value::Dict::Set(std::string_view key, std::string&& value) & { return Set(key, Value(std::move(value))); } -Value* Value::Dict::Set(StringPiece key, BlobStorage&& value) & { +Value* Value::Dict::Set(std::string_view key, BlobStorage&& value) & { return Set(key, Value(std::move(value))); } -Value* Value::Dict::Set(StringPiece key, Dict&& value) & { +Value* Value::Dict::Set(std::string_view key, Dict&& value) & { return Set(key, Value(std::move(value))); } -Value* Value::Dict::Set(StringPiece key, List&& value) & { +Value* Value::Dict::Set(std::string_view key, List&& value) & { return Set(key, Value(std::move(value))); } -Value::Dict&& Value::Dict::Set(StringPiece key, Value&& value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, Value&& value) && { DCHECK(IsStringUTF8AllowingNoncharacters(key)); storage_.insert_or_assign(key, std::make_unique(std::move(value))); return std::move(*this); } -Value::Dict&& Value::Dict::Set(StringPiece key, bool value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, bool value) && { return std::move(*this).Set(key, Value(value)); } -Value::Dict&& Value::Dict::Set(StringPiece key, int value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, int value) && { return std::move(*this).Set(key, Value(value)); } -Value::Dict&& Value::Dict::Set(StringPiece key, double value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, double value) && { return std::move(*this).Set(key, Value(value)); } -Value::Dict&& Value::Dict::Set(StringPiece key, StringPiece value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, + std::string_view value) && { return std::move(*this).Set(key, Value(value)); } -Value::Dict&& Value::Dict::Set(StringPiece key, StringPiece16 value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, + std::u16string_view value) && { return std::move(*this).Set(key, Value(value)); } -Value::Dict&& Value::Dict::Set(StringPiece key, const char* value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, const char* value) && { return std::move(*this).Set(key, Value(value)); } -Value::Dict&& Value::Dict::Set(StringPiece key, const char16_t* value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, const char16_t* value) && { return std::move(*this).Set(key, Value(value)); } -Value::Dict&& Value::Dict::Set(StringPiece key, std::string&& value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, std::string&& value) && { return std::move(*this).Set(key, Value(std::move(value))); } -Value::Dict&& Value::Dict::Set(StringPiece key, BlobStorage&& value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, BlobStorage&& value) && { return std::move(*this).Set(key, Value(std::move(value))); } -Value::Dict&& Value::Dict::Set(StringPiece key, Dict&& value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, Dict&& value) && { return std::move(*this).Set(key, Value(std::move(value))); } -Value::Dict&& Value::Dict::Set(StringPiece key, List&& value) && { +Value::Dict&& Value::Dict::Set(std::string_view key, List&& value) && { return std::move(*this).Set(key, Value(std::move(value))); } -bool Value::Dict::Remove(StringPiece key) { +bool Value::Dict::Remove(std::string_view key) { DCHECK(IsStringUTF8AllowingNoncharacters(key)); return storage_.erase(key) > 0; } -std::optional Value::Dict::Extract(StringPiece key) { +std::optional Value::Dict::Extract(std::string_view key) { DCHECK(IsStringUTF8AllowingNoncharacters(key)); auto it = storage_.find(key); @@ -622,7 +624,7 @@ std::optional Value::Dict::Extract(StringPiece key) { return v; } -const Value* Value::Dict::FindByDottedPath(StringPiece path) const { +const Value* Value::Dict::FindByDottedPath(std::string_view path) const { DCHECK(!path.empty()); DCHECK(IsStringUTF8AllowingNoncharacters(path)); @@ -644,63 +646,68 @@ const Value* Value::Dict::FindByDottedPath(StringPiece path) const { } } -Value* Value::Dict::FindByDottedPath(StringPiece path) { +Value* Value::Dict::FindByDottedPath(std::string_view path) { return const_cast(std::as_const(*this).FindByDottedPath(path)); } -std::optional Value::Dict::FindBoolByDottedPath(StringPiece path) const { +std::optional Value::Dict::FindBoolByDottedPath( + std::string_view path) const { const Value* v = FindByDottedPath(path); return v ? v->GetIfBool() : std::nullopt; } -std::optional Value::Dict::FindIntByDottedPath(StringPiece path) const { +std::optional Value::Dict::FindIntByDottedPath( + std::string_view path) const { const Value* v = FindByDottedPath(path); return v ? v->GetIfInt() : std::nullopt; } std::optional Value::Dict::FindDoubleByDottedPath( - StringPiece path) const { + std::string_view path) const { const Value* v = FindByDottedPath(path); return v ? v->GetIfDouble() : std::nullopt; } -const std::string* Value::Dict::FindStringByDottedPath(StringPiece path) const { +const std::string* Value::Dict::FindStringByDottedPath( + std::string_view path) const { const Value* v = FindByDottedPath(path); return v ? v->GetIfString() : nullptr; } -std::string* Value::Dict::FindStringByDottedPath(StringPiece path) { +std::string* Value::Dict::FindStringByDottedPath(std::string_view path) { Value* v = FindByDottedPath(path); return v ? v->GetIfString() : nullptr; } const Value::BlobStorage* Value::Dict::FindBlobByDottedPath( - StringPiece path) const { + std::string_view path) const { const Value* v = FindByDottedPath(path); return v ? v->GetIfBlob() : nullptr; } -const Value::Dict* Value::Dict::FindDictByDottedPath(StringPiece path) const { +const Value::Dict* Value::Dict::FindDictByDottedPath( + std::string_view path) const { const Value* v = FindByDottedPath(path); return v ? v->GetIfDict() : nullptr; } -Value::Dict* Value::Dict::FindDictByDottedPath(StringPiece path) { +Value::Dict* Value::Dict::FindDictByDottedPath(std::string_view path) { Value* v = FindByDottedPath(path); return v ? v->GetIfDict() : nullptr; } -const Value::List* Value::Dict::FindListByDottedPath(StringPiece path) const { +const Value::List* Value::Dict::FindListByDottedPath( + std::string_view path) const { const Value* v = FindByDottedPath(path); return v ? v->GetIfList() : nullptr; } -Value::List* Value::Dict::FindListByDottedPath(StringPiece path) { +Value::List* Value::Dict::FindListByDottedPath(std::string_view path) { Value* v = FindByDottedPath(path); return v ? v->GetIfList() : nullptr; } -Value* Value::Dict::SetByDottedPath(StringPiece path, Value&& value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, Value&& value) & { DCHECK(!path.empty()); DCHECK(IsStringUTF8AllowingNoncharacters(path)); @@ -708,7 +715,7 @@ Value* Value::Dict::SetByDottedPath(StringPiece path, Value&& value) & { Value* current_value = nullptr; PathSplitter splitter(path); while (true) { - StringPiece next_key = splitter.Next(); + std::string_view next_key = splitter.Next(); if (!splitter.HasNext()) { return current_dict->Set(next_key, std::move(value)); } @@ -728,121 +735,133 @@ Value* Value::Dict::SetByDottedPath(StringPiece path, Value&& value) & { } } -Value* Value::Dict::SetByDottedPath(StringPiece path, bool value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, bool value) & { return SetByDottedPath(path, Value(value)); } -Value* Value::Dict::SetByDottedPath(StringPiece path, int value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, int value) & { return SetByDottedPath(path, Value(value)); } -Value* Value::Dict::SetByDottedPath(StringPiece path, double value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, double value) & { return SetByDottedPath(path, Value(value)); } -Value* Value::Dict::SetByDottedPath(StringPiece path, StringPiece value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, + std::string_view value) & { return SetByDottedPath(path, Value(value)); } -Value* Value::Dict::SetByDottedPath(StringPiece path, StringPiece16 value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, + std::u16string_view value) & { return SetByDottedPath(path, Value(value)); } -Value* Value::Dict::SetByDottedPath(StringPiece path, const char* value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, + const char* value) & { return SetByDottedPath(path, Value(value)); } -Value* Value::Dict::SetByDottedPath(StringPiece path, const char16_t* value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, + const char16_t* value) & { return SetByDottedPath(path, Value(value)); } -Value* Value::Dict::SetByDottedPath(StringPiece path, std::string&& value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, + std::string&& value) & { return SetByDottedPath(path, Value(std::move(value))); } -Value* Value::Dict::SetByDottedPath(StringPiece path, BlobStorage&& value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, + BlobStorage&& value) & { return SetByDottedPath(path, Value(std::move(value))); } -Value* Value::Dict::SetByDottedPath(StringPiece path, Dict&& value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, Dict&& value) & { return SetByDottedPath(path, Value(std::move(value))); } -Value* Value::Dict::SetByDottedPath(StringPiece path, List&& value) & { +Value* Value::Dict::SetByDottedPath(std::string_view path, List&& value) & { return SetByDottedPath(path, Value(std::move(value))); } -bool Value::Dict::RemoveByDottedPath(StringPiece path) { +bool Value::Dict::RemoveByDottedPath(std::string_view path) { return ExtractByDottedPath(path).has_value(); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, Value&& value) && { +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, + Value&& value) && { SetByDottedPath(path, std::move(value)); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, bool value) && { +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, + bool value) && { SetByDottedPath(path, Value(value)); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, int value) && { +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, + int value) && { SetByDottedPath(path, Value(value)); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, double value) && { +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, + double value) && { SetByDottedPath(path, Value(value)); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, - StringPiece value) && { +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, + std::string_view value) && { SetByDottedPath(path, Value(value)); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, - StringPiece16 value) && { +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, + std::u16string_view value) && { SetByDottedPath(path, Value(value)); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, const char* value) && { SetByDottedPath(path, Value(value)); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, const char16_t* value) && { SetByDottedPath(path, Value(value)); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, std::string&& value) && { SetByDottedPath(path, Value(std::move(value))); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, BlobStorage&& value) && { SetByDottedPath(path, Value(std::move(value))); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, Dict&& value) && { +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, + Dict&& value) && { SetByDottedPath(path, Value(std::move(value))); return std::move(*this); } -Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, List&& value) && { +Value::Dict&& Value::Dict::SetByDottedPath(std::string_view path, + List&& value) && { SetByDottedPath(path, Value(std::move(value))); return std::move(*this); } -std::optional Value::Dict::ExtractByDottedPath(StringPiece path) { +std::optional Value::Dict::ExtractByDottedPath(std::string_view path) { DCHECK(!path.empty()); DCHECK(IsStringUTF8AllowingNoncharacters(path)); @@ -850,12 +869,12 @@ std::optional Value::Dict::ExtractByDottedPath(StringPiece path) { // removing dictionaries that become empty if a value matching `path` is // extracted. size_t dot_index = path.find('.'); - if (dot_index == StringPiece::npos) { + if (dot_index == std::string_view::npos) { return Extract(path); } // This could be clever to avoid a double-lookup by using storage_ directly, // but for now, just implement it in the most straightforward way. - StringPiece next_key = path.substr(0, dot_index); + std::string_view next_key = path.substr(0, dot_index); auto* next_dict = FindDict(next_key); if (!next_dict) { return std::nullopt; @@ -1087,11 +1106,11 @@ void Value::List::Append(double value) & { storage_.emplace_back(value); } -void Value::List::Append(StringPiece value) & { +void Value::List::Append(std::string_view value) & { Append(Value(value)); } -void Value::List::Append(StringPiece16 value) & { +void Value::List::Append(std::u16string_view value) & { storage_.emplace_back(value); } @@ -1139,12 +1158,12 @@ Value::List&& Value::List::Append(double value) && { return std::move(*this); } -Value::List&& Value::List::Append(StringPiece value) && { +Value::List&& Value::List::Append(std::string_view value) && { Append(Value(value)); return std::move(*this); } -Value::List&& Value::List::Append(StringPiece16 value) && { +Value::List&& Value::List::Append(std::u16string_view value) && { storage_.emplace_back(value); return std::move(*this); } @@ -1279,7 +1298,7 @@ bool operator==(const Value& lhs, double rhs) { return lhs.is_double() && lhs.GetDouble() == rhs; } -bool operator==(const Value& lhs, StringPiece rhs) { +bool operator==(const Value& lhs, std::string_view rhs) { return lhs.is_string() && lhs.GetString() == rhs; } diff --git a/naiveproxy/src/base/values.h b/naiveproxy/src/base/values.h index d8e9e323c6..67147157a0 100644 --- a/naiveproxy/src/base/values.h +++ b/naiveproxy/src/base/values.h @@ -26,7 +26,6 @@ #include "base/containers/flat_map.h" #include "base/containers/span.h" #include "base/memory/raw_ref.h" -#include "base/strings/string_piece.h" #include "base/trace_event/base_tracing_forward.h" #include "base/value_iterators.h" #include "third_party/abseil-cpp/absl/types/variant.h" @@ -837,11 +836,11 @@ class BASE_EXPORT GSL_OWNER Value { friend bool operator==(double lhs, const Value& rhs) { return rhs == lhs; } friend bool operator!=(const Value& lhs, double rhs) { return !(lhs == rhs); } friend bool operator!=(double lhs, const Value& rhs) { return !(lhs == rhs); } - // Note: StringPiece16 overload intentionally omitted: Value internally stores - // strings as UTF-8. While it is possible to implement a comparison operator - // that would not require first creating a new UTF-8 string from the UTF-16 - // string argument, it is simpler to just not implement it at all for a rare - // use case. + // Note: std::u16string_view overload intentionally omitted: Value internally + // stores strings as UTF-8. While it is possible to implement a comparison + // operator that would not require first creating a new UTF-8 string from the + // UTF-16 string argument, it is simpler to just not implement it at all for a + // rare use case. BASE_EXPORT friend bool operator==(const Value& lhs, std::string_view rhs); friend bool operator==(std::string_view lhs, const Value& rhs) { return rhs == lhs; @@ -999,10 +998,10 @@ class BASE_EXPORT GSL_OWNER Value { // serialization methods without having to clone the contents and transfer // ownership of the clone to a `Value` wrapper object. // -// Like `StringPiece` and `span`, this adapter does NOT retain ownership. Any -// underlying object that is passed by reference (i.e. `std::string`, -// `Value::BlobStorage`, `Value::Dict`, `Value::List`, or `Value`) MUST remain -// live as long as there is a `ValueView` referencing it. +// Like `std::string_view` and `span`, this adapter does NOT retain +// ownership. Any underlying object that is passed by reference (i.e. +// `std::string`, `Value::BlobStorage`, `Value::Dict`, `Value::List`, or +// `Value`) MUST remain live as long as there is a `ValueView` referencing it. // // While it might be nice to just use the `absl::variant` type directly, the // need to use `std::reference_wrapper` makes it clunky. `absl::variant` and diff --git a/naiveproxy/src/base/version.cc b/naiveproxy/src/base/version.cc index 87d627954f..e40a3e9bd3 100644 --- a/naiveproxy/src/base/version.cc +++ b/naiveproxy/src/base/version.cc @@ -83,6 +83,8 @@ Version::Version() = default; Version::Version(const Version& other) = default; +Version::Version(Version&& other) = default; + Version::~Version() = default; Version::Version(std::string_view version_str) { diff --git a/naiveproxy/src/base/version.h b/naiveproxy/src/base/version.h index ea9ab54e3b..cb1c092f60 100644 --- a/naiveproxy/src/base/version.h +++ b/naiveproxy/src/base/version.h @@ -25,6 +25,10 @@ class BASE_EXPORT Version { Version(); Version(const Version& other); + Version(Version&& other); + + Version& operator=(const Version& other) = default; + Version& operator=(Version&& other) = default; // Initializes from a decimal dotted version number, like "0.1.1". // Each component is limited to a uint32_t. Call IsValid() to learn diff --git a/naiveproxy/src/base/win/sid.cc b/naiveproxy/src/base/win/sid.cc index dd063382d9..2f250ba9bf 100644 --- a/naiveproxy/src/base/win/sid.cc +++ b/naiveproxy/src/base/win/sid.cc @@ -29,7 +29,6 @@ #include "base/win/scoped_handle.h" #include "base/win/scoped_localalloc.h" #include "base/win/windows_version.h" -#include "third_party/boringssl/src/include/openssl/crypto.h" #include "third_party/boringssl/src/include/openssl/sha.h" namespace base::win { @@ -131,7 +130,6 @@ Sid Sid::FromNamedCapability(const std::wstring& capability_name) { if (known_cap != known_capabilities->end()) { return FromKnownCapability(known_cap->second); } - CRYPTO_library_init(); static_assert((SHA256_DIGEST_LENGTH / sizeof(DWORD)) == SECURITY_APP_PACKAGE_RID_COUNT); DWORD rids[(SHA256_DIGEST_LENGTH / sizeof(DWORD)) + 2]; diff --git a/naiveproxy/src/base/win/win_util.cc b/naiveproxy/src/base/win/win_util.cc index 754936d535..b8ae7d9470 100644 --- a/naiveproxy/src/base/win/win_util.cc +++ b/naiveproxy/src/base/win/win_util.cc @@ -822,6 +822,25 @@ bool IsAppVerifierLoaded() { return GetModuleHandleA(kApplicationVerifierDllName); } +std::optional ExpandEnvironmentVariables(wcstring_view str) { + std::wstring path_expanded; + DWORD path_len = MAX_PATH; + for (int iterations = 0; iterations < 5; iterations++) { + DWORD result = ::ExpandEnvironmentStringsW( + str.c_str(), base::WriteInto(&path_expanded, path_len), path_len); + if (!result) { + // Failed to expand variables. + break; + } + if (result <= path_len) { + return path_expanded.substr(0, result - 1); + } + path_len = result; + } + + return std::nullopt; +} + ScopedDomainStateForTesting::ScopedDomainStateForTesting(bool state) : initial_state_(IsEnrolledToDomain()) { *GetDomainEnrollmentStateStorage() = state; diff --git a/naiveproxy/src/base/win/win_util.h b/naiveproxy/src/base/win/win_util.h index 816dab95c7..a7f6848f5d 100644 --- a/naiveproxy/src/base/win/win_util.h +++ b/naiveproxy/src/base/win/win_util.h @@ -30,6 +30,7 @@ #include #include "base/base_export.h" +#include "base/strings/cstring_view.h" #include "base/win/windows_types.h" struct IPropertyStore; @@ -252,6 +253,20 @@ BASE_EXPORT bool IsCurrentSessionRemote(); // loaded into the current process. BASE_EXPORT bool IsAppVerifierLoaded(); +// Replaces the name of each environment variable embedded in the specified +// string with the string equivalent of the value of the variable, then returns +// the resulting string. +// +// The implementation calls the `ExpandEnvironmentStrings` WinAPI, meaning: +// * Each %variableName% portion is replaced with the current value of that +// environment variable. +// * Case is ignored when looking up the environment-variable name. +// * If the name is not found, the %variableName% portion is left unexpanded. +// +// If `ExpandEnvironmentStrings` fails, `std::nullopt` is returned. +BASE_EXPORT std::optional ExpandEnvironmentVariables( + wcstring_view str); + // Allows changing the domain enrolled state for the life time of the object. // The original state is restored upon destruction. class BASE_EXPORT ScopedDomainStateForTesting { diff --git a/naiveproxy/src/build/3pp_common/fetch_github_release.py b/naiveproxy/src/build/3pp_common/fetch_github_release.py index 148968adde..4c3b1d9509 100644 --- a/naiveproxy/src/build/3pp_common/fetch_github_release.py +++ b/naiveproxy/src/build/3pp_common/fetch_github_release.py @@ -12,6 +12,8 @@ import sys from typing import Dict, List import urllib.request +import scripthash + def _fetch_json(url): return json.load(urllib.request.urlopen(url)) @@ -26,15 +28,7 @@ def _find_valid_urls(release, artifact_regex): def _latest(api_url, install_scripts=None, artifact_regex=None): # Make the version change every time this file changes. - md5 = hashlib.md5() - md5.update(pathlib.Path(__file__).read_bytes()) - import __main__ - md5.update(pathlib.Path(__main__.__file__).read_bytes()) - - if install_scripts: - for path in install_scripts: - md5.update(pathlib.Path(path).read_bytes()) - file_hash = md5.hexdigest()[:10] + file_hash = scripthash.compute(extra_paths=install_scripts) releases: List[Dict] = _fetch_json(f'{api_url}/releases') for release in releases: diff --git a/naiveproxy/src/build/3pp_common/maven.py b/naiveproxy/src/build/3pp_common/maven.py new file mode 100644 index 0000000000..a3f913ddb8 --- /dev/null +++ b/naiveproxy/src/build/3pp_common/maven.py @@ -0,0 +1,184 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""The fetch.py and install.py helpers for a 3pp Maven module.""" + +import argparse +import hashlib +import os +import pathlib +import re +import shutil +import subprocess +import sys +import urllib.request + +import scripthash + +APACHE_MAVEN_URL = 'https://repo.maven.apache.org/maven2' + +_THIS_DIR = pathlib.Path(__file__).resolve().parent +_SRC_ROOT = _THIS_DIR.parents[1] + +_POM_TEMPLATE = """\ + + 4.0.0 + group + artifact + 1 + + + {group_id} + {artifact_id} + {version} + runtime + + + + + + maven-assembly-plugin + 3.3.0 + + + jar-with-dependencies + + + + + package + + single + + + + + + + + + placeholder_id + placeholder_name + {maven_url} + + + +""" + + +def _detect_latest(maven_url, package): + metadata_url = '{}/{}/maven-metadata.xml'.format( + maven_url, + package.replace('.', '/').replace(':', '/')) + metadata = urllib.request.urlopen(metadata_url).read().decode('utf-8') + # Do not parse xml with the Python included parser since it is susceptible + # to maliciously crafted xmls. Only use regular expression parsing to be + # safe. RE should be enough to handle what we need to extract. + # TODO(agrieve): Use 'if m := ..." once docker image updates from Python 3.6. + m = re.search('([^<]+)', metadata) + if m: + latest = m.group(1) + else: + # If no latest info was found just hope the versions are sorted and the + # last one is the latest (as is commonly the case). + latest = re.findall('([^<]+)', metadata)[-1] + return latest + + +def _latest(maven_url, package, version_override=None): + # Make the version change every time any Python file changes. + file_hash = scripthash.compute() + version = version_override or _detect_latest(maven_url, package) + print('{}.{}'.format(version, file_hash)) + + +def _checkout(checkout_path): + # Make 3pp_common scripts available in the docker container install.py + # will run in. + dest_dir = os.path.join(checkout_path, '.3pp', 'chromium', + os.path.relpath(_THIS_DIR, _SRC_ROOT)) + os.makedirs(os.path.dirname(dest_dir)) + shutil.copytree(_THIS_DIR, + dest_dir, + ignore=shutil.ignore_patterns('.*', '__pycache__')) + print('Copied', _THIS_DIR, 'to', dest_dir) + + +def _install(output_prefix, + deps_prefix, + maven_url, + package, + version, + jar_name=None): + # Runs in a docker container. + group_id, artifact_id = package.split(':') + if not jar_name: + jar_name = f'{artifact_id}.jar' + + pathlib.Path('pom.xml').write_text( + _POM_TEMPLATE.format(version=version, + group_id=group_id, + artifact_id=artifact_id, + maven_url=maven_url)) + + # Set up JAVA_HOME for the mvn command to find the JDK. + env = os.environ.copy() + env['JAVA_HOME'] = os.path.join(deps_prefix) + + # Ensure that mvn works and the environment is set up correctly. + subprocess.run(['mvn', '-v'], check=True, env=env) + + # Build the jar file, explicitly specify -f to reduce sources of error. + subprocess.run(['mvn', 'clean', 'assembly:single', '-f', 'pom.xml'], + check=True, + env=env) + + # Move and rename output to the upload directory. Moving only the jar avoids + # polluting the output directory with maven intermediate outputs. + os.makedirs(output_prefix, exist_ok=True) + shutil.move('target/artifact-1-jar-with-dependencies.jar', + os.path.join(output_prefix, jar_name)) + + +def main(*, + package, + jar_name=None, + maven_url='https://dl.google.com/android/maven2', + version_override=None): + """3pp entry point for fetch.py. + + Args: + package: E.g.: some.package:some-thing + jar_name: Name of .jar. Defaults to |some-thing|.jar + maven_url: URL of Maven repository. + version_override: Use this version instead of the latest one. + """ + parser = argparse.ArgumentParser() + # TODO(agrieve): Add required=True once 3pp builds with > python3.6. + subparsers = parser.add_subparsers() + + subparser = subparsers.add_parser('latest') + subparser.set_defaults(action='latest') + + subparser = subparsers.add_parser('checkout') + subparser.add_argument('checkout_path') + subparser.set_defaults(action='checkout') + + subparser = subparsers.add_parser('install') + subparser.add_argument('output_prefix', + help='The path to install the compiled package to.') + subparser.add_argument('deps_prefix', + help='The path to a directory containing all deps.') + subparser.set_defaults(action='install') + args = parser.parse_args() + + if args.action == 'latest': + _latest(maven_url, package, version_override=version_override) + elif args.action == 'checkout': + _checkout(args.checkout_path) + elif args.action == 'install': + # Remove the hash at the end: 30.4.0-alpha05.HASH => 30.4.0-alpha05 + version = os.environ['_3PP_VERSION'].rsplit('.', 1)[0] + assert version, '_3PP_VERSION not set' + _install(args.output_prefix, args.deps_prefix, maven_url, package, + version, jar_name) diff --git a/naiveproxy/src/build/3pp_common/scripthash.py b/naiveproxy/src/build/3pp_common/scripthash.py new file mode 100644 index 0000000000..90951f31f8 --- /dev/null +++ b/naiveproxy/src/build/3pp_common/scripthash.py @@ -0,0 +1,34 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import hashlib +import os +import pathlib +import sys + +_SRC_ROOT = str(pathlib.Path(__file__).resolve().parents[2]) + + +def _find_deps(): + module_paths = (os.path.abspath(m.__file__) for m in sys.modules.values() + if m and getattr(m, '__file__', None)) + ret = set() + for path in module_paths: + if path.startswith(_SRC_ROOT): + if (path.endswith('.pyc') + or (path.endswith('c') and not os.path.splitext(path)[1])): + path = path[:-1] + ret.add(path) + return sorted(ret) + + +def compute(extra_paths=None): + """Compute a hash of loaded Python modules and given |extra_paths|.""" + md5 = hashlib.md5() + for path in _find_deps(): + md5.update(pathlib.Path(path).read_bytes()) + if extra_paths: + for path in extra_paths: + md5.update(pathlib.Path(path).read_bytes()) + return md5.hexdigest()[:10] diff --git a/naiveproxy/src/build/BUILD.gn b/naiveproxy/src/build/BUILD.gn index 00bf4d8571..ebb68e2113 100644 --- a/naiveproxy/src/build/BUILD.gn +++ b/naiveproxy/src/build/BUILD.gn @@ -94,6 +94,11 @@ buildflag_header("ios_buildflags") { flags = [ "IS_IOS_APP_EXTENSION=$_is_ios_app_extension" ] } +buildflag_header("android_buildflags") { + header = "android_buildflags.h" + flags = [ "IS_DESKTOP_ANDROID=$is_desktop_android" ] +} + if (build_with_chromium) { group("gold_common_pytype") { testonly = true diff --git a/naiveproxy/src/build/OWNERS.setnoparent b/naiveproxy/src/build/OWNERS.setnoparent index 35c5454143..b7867d2b50 100644 --- a/naiveproxy/src/build/OWNERS.setnoparent +++ b/naiveproxy/src/build/OWNERS.setnoparent @@ -23,6 +23,7 @@ file://third_party/blink/SECURITY_OWNERS file://tools/traffic_annotation/summary/TRAFFIC_ANNOTATION_OWNERS file://tools/metrics/ukm/PRIVACY_OWNERS file://base/metrics/METRICS_OWNERS +file://chrome/browser/ui/hats/HATS_PRIVACY_OWNERS # Blink API owners are responsible for decisions about what APIs Blink should # expose to the open web. @@ -80,3 +81,7 @@ file://ash/system/OWNERS # New WebUI additions should be reviewed by WebUI PLATFORM_OWNERS to ensure # they follow the guidance at https://www.chromium.org/developers/webui file://ui/webui/PLATFORM_OWNERS + +# Core Views framework needs reviews from direct owners. Limits leakage of +1 +# from higher folder owners. +file://ui/views/VIEWS_OWNERS diff --git a/naiveproxy/src/build/android/PRESUBMIT.py b/naiveproxy/src/build/android/PRESUBMIT.py index de7c71f209..5e98127671 100644 --- a/naiveproxy/src/build/android/PRESUBMIT.py +++ b/naiveproxy/src/build/android/PRESUBMIT.py @@ -42,7 +42,7 @@ def CommonChecks(input_api, output_api): J(), J('gyp'), J('buildbot'), - J('..', 'util', 'lib', 'common'), + J('..', 'util'), J('..', '..', 'third_party', 'catapult', 'common', 'py_trace_event'), J('..', '..', 'third_party', 'catapult', 'common', 'py_utils'), diff --git a/naiveproxy/src/build/android/apk_operations.py b/naiveproxy/src/build/android/apk_operations.py index d34e24d69d..afe821964a 100755 --- a/naiveproxy/src/build/android/apk_operations.py +++ b/naiveproxy/src/build/android/apk_operations.py @@ -1024,10 +1024,7 @@ def _RunCompileDex(devices, package_name, compilation_filter): cmd = ['cmd', 'package', 'compile', '-f', '-m', compilation_filter, package_name] parallel_devices = device_utils.DeviceUtils.parallel(devices) - outputs = parallel_devices.RunShellCommand(cmd, timeout=120).pGet(None) - for output in _PrintPerDeviceOutput(devices, outputs): - for line in output: - print(line) + return parallel_devices.RunShellCommand(cmd, timeout=120).pGet(None) def _RunProfile(device, package_name, host_build_directory, pprof_out_path, @@ -1200,6 +1197,7 @@ class _Command: self._parser = None self._from_wrapper_script = from_wrapper_script self.args = None + self.incremental_apk_path = None self.apk_helper = None self.additional_apk_helpers = None self.install_dict = None @@ -1258,12 +1256,21 @@ class _Command: # # - Called directly, then --package-name is required on the command-line. # + # Similarly is_official_build is set directly by the bundle wrapper + # script, so it also needs to be added for non-bundle builds. if not self.is_bundle: group.add_argument( '--package-name', help=argparse.SUPPRESS if self._from_wrapper_script else ( "App's package name.")) + group.add_argument( + '--is-official-build', + action='store_true', + default=False, + help=argparse.SUPPRESS if self._from_wrapper_script else + ('Whether this is an official build or not (affects perf).')) + if self.needs_apk_helper or self.needs_package_name: # Adding this argument to the subparser would override the set_defaults() # value set by on the parent parser (even if None). @@ -1379,16 +1386,16 @@ class _Command: args.__dict__.setdefault('apk_path', None) args.__dict__.setdefault('incremental_json', None) - incremental_apk_path = None + self.incremental_apk_path = None install_dict = None if args.incremental_json and not (self.supports_incremental and args.non_incremental): with open(args.incremental_json) as f: install_dict = json.load(f) - incremental_apk_path = os.path.join(args.output_directory, - install_dict['apk_path']) - if not os.path.exists(incremental_apk_path): - incremental_apk_path = None + self.incremental_apk_path = os.path.join(args.output_directory, + install_dict['apk_path']) + if not os.path.exists(self.incremental_apk_path): + self.incremental_apk_path = None if self.supports_incremental: if args.incremental and args.non_incremental: @@ -1398,11 +1405,11 @@ class _Command: if not args.apk_path: self._parser.error('Apk has not been built.') elif args.incremental: - if not incremental_apk_path: + if not self.incremental_apk_path: self._parser.error('Incremental apk has not been built.') args.apk_path = None - if args.apk_path and incremental_apk_path: + if args.apk_path and self.incremental_apk_path: self._parser.error('Both incremental and non-incremental apks exist. ' 'Select using --incremental or --non-incremental') @@ -1411,11 +1418,12 @@ class _Command: # a while to unpack the apks file from the aab file, so avoid this slowdown # for simple commands that don't need apk_helper. if self.needs_apk_helper: - if not self._CreateApkHelpers(args, incremental_apk_path, install_dict): + if not self._CreateApkHelpers(args, self.incremental_apk_path, + install_dict): self._parser.error('App is not built.') if self.needs_package_name and not args.package_name: - if self._CreateApkHelpers(args, incremental_apk_path, install_dict): + if self._CreateApkHelpers(args, self.incremental_apk_path, install_dict): args.package_name = self.apk_helper.GetPackageName() elif self._from_wrapper_script: self._parser.error('App is not built.') @@ -1435,7 +1443,8 @@ class _Command: if not available_devices: raise Exception('Cannot find any available devices.') - if not self._CreateApkHelpers(args, incremental_apk_path, install_dict): + if not self._CreateApkHelpers(args, self.incremental_apk_path, + install_dict): self.devices = available_devices else: fully_supported, not_supported_reasons = self._FindSupportedDevices( @@ -1501,6 +1510,7 @@ class _PackageInfoCommand(_Command): class _InstallCommand(_Command): name = 'install' description = 'Installs the APK or bundle to one or more devices.' + needs_package_name = True needs_apk_helper = True supports_incremental = True default_modules = [] @@ -1539,6 +1549,8 @@ class _InstallCommand(_Command): _InstallBundle(self.devices, self.apk_helper, modules, self.args.fake) else: _InstallApk(self.devices, self.apk_helper, self.install_dict) + if self.args.is_official_build: + _RunCompileDex(self.devices, self.args.package_name, 'speed') class _UninstallCommand(_Command): @@ -1747,10 +1759,10 @@ To disable filtering, (but keep coloring), use --verbose. deobfuscate = None if self.args.proguard_mapping_path and not self.args.no_deobfuscate: deobfuscate = deobfuscator.Deobfuscator(self.args.proguard_mapping_path) - - if self.args.apk_path or self.bundle_generation_info: + apk_path = self.args.apk_path or self.incremental_apk_path + if apk_path or self.bundle_generation_info: stack_script_context = _StackScriptContext(self.args.output_directory, - self.args.apk_path, + apk_path, self.bundle_generation_info, quiet=True) else: @@ -1866,8 +1878,11 @@ class _CompileDexCommand(_Command): '"speed-profile".') def Run(self): - _RunCompileDex(self.devices, self.args.package_name, - self.args.compilation_filter) + outputs = _RunCompileDex(self.devices, self.args.package_name, + self.args.compilation_filter) + for output in _PrintPerDeviceOutput(self.devices, outputs): + for line in output: + print(line) class _PrintCertsCommand(_Command): @@ -2123,8 +2138,8 @@ class _StackCommand(_Command): help='File to decode. If not specified, stdin is processed.') def Run(self): - context = _StackScriptContext(self.args.output_directory, - self.args.apk_path, + apk_path = self.args.apk_path or self.incremental_apk_path + context = _StackScriptContext(self.args.output_directory, apk_path, self.bundle_generation_info) try: proc = context.Popen(input_file=self.args.file) @@ -2204,7 +2219,12 @@ def _RunInternal(parser, if bundle_generation_info: args.command.RegisterBundleGenerationInfo(bundle_generation_info) if args.additional_apk_paths: - for path in additional_apk_paths: + for i, path in enumerate(args.additional_apk_paths): + if path and not os.path.exists(path): + inc_path = path.replace('.apk', '_incremental.apk') + if os.path.exists(inc_path): + args.additional_apk_paths[i] = inc_path + path = inc_path if not path or not os.path.exists(path): raise Exception('Invalid additional APK path "{}"'.format(path)) args.command.ProcessArgs(args) @@ -2238,7 +2258,7 @@ def RunForBundle(output_directory, bundle_path, bundle_apks_path, additional_apk_paths, aapt2_path, keystore_path, keystore_password, keystore_alias, package_name, command_line_flags_file, proguard_mapping_path, target_cpu, - system_image_locales, default_modules): + system_image_locales, default_modules, is_official_build): """Entry point for generated app bundle wrapper scripts. Args: @@ -2274,16 +2294,15 @@ def RunForBundle(output_directory, bundle_path, bundle_apks_path, _InstallCommand.default_modules = default_modules parser = argparse.ArgumentParser() - parser.set_defaults( - package_name=package_name, - command_line_flags_file=command_line_flags_file, - proguard_mapping_path=proguard_mapping_path, - target_cpu=target_cpu) - _RunInternal( - parser, - output_directory=output_directory, - additional_apk_paths=additional_apk_paths, - bundle_generation_info=bundle_generation_info) + parser.set_defaults(package_name=package_name, + command_line_flags_file=command_line_flags_file, + proguard_mapping_path=proguard_mapping_path, + target_cpu=target_cpu, + is_official_build=is_official_build) + _RunInternal(parser, + output_directory=output_directory, + additional_apk_paths=additional_apk_paths, + bundle_generation_info=bundle_generation_info) def RunForTestApk(*, output_directory, package_name, test_apk_path, diff --git a/naiveproxy/src/build/android/diff_resource_sizes.py b/naiveproxy/src/build/android/diff_resource_sizes.py index e3fd90bb41..3258d5365c 100755 --- a/naiveproxy/src/build/android/diff_resource_sizes.py +++ b/naiveproxy/src/build/android/diff_resource_sizes.py @@ -15,8 +15,8 @@ import sys from pylib.constants import host_paths -with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): - import perf_tests_results_helper # pylint: disable=import-error +with host_paths.SysPath(host_paths.BUILD_UTIL_PATH): + from lib.common import perf_tests_results_helper with host_paths.SysPath(host_paths.TRACING_PATH): from tracing.value import convert_chart_json # pylint: disable=import-error diff --git a/naiveproxy/src/build/android/generate_vscode_classpath.py b/naiveproxy/src/build/android/generate_vscode_project.py similarity index 74% rename from naiveproxy/src/build/android/generate_vscode_classpath.py rename to naiveproxy/src/build/android/generate_vscode_project.py index 3b7540d8f1..e9dbd35e5d 100755 --- a/naiveproxy/src/build/android/generate_vscode_classpath.py +++ b/naiveproxy/src/build/android/generate_vscode_project.py @@ -2,8 +2,8 @@ # Copyright 2023 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Given a .build_config.json file, generates a .classpath file that can be -used with the "Language Support for Java™ by Red Hat" Visual Studio Code +"""Given a .build_config.json file, generates an Eclipse JDT project that can +be used with the "Language Support for Java™ by Red Hat" Visual Studio Code extension. See //docs/vscode.md for details. """ @@ -82,10 +82,11 @@ def _ProcessBuildConfigFile(output_dir, build_config_path, source_dirs, libs, logging.debug('Found lib `%s', lib_path) libs.add(lib_path) - source_dirs.add( - os.path.join(output_dir, - _WithoutSuffix(build_config_path, '.build_config.json'), - 'generated_java', 'input_srcjars')) + input_srcjars = os.path.join(output_dir, + _WithoutSuffix(build_config_path, '.build_config.json'), + 'generated_java', 'input_srcjars') + if os.path.exists(input_srcjars): + source_dirs.add(input_srcjars) android = build_config.get('android') if android is not None: @@ -115,27 +116,54 @@ def _ProcessBuildConfigFile(output_dir, build_config_path, source_dirs, libs, def _GenerateClasspathEntry(kind, path): classpathentry = xml.etree.ElementTree.Element('classpathentry') classpathentry.set('kind', kind) - classpathentry.set('path', f'_/{path}') + classpathentry.set('path', path) return classpathentry -def _GenerateClasspathFile(source_dirs, libs): +def _GenerateProject(source_dirs, libs, output_dir): classpath = xml.etree.ElementTree.Element('classpath') - for source_dir in source_dirs: + for source_dir in sorted(source_dirs): classpath.append(_GenerateClasspathEntry('src', source_dir)) - for lib in libs: + for lib in sorted(libs): classpath.append(_GenerateClasspathEntry('lib', lib)) + classpath.append( + _GenerateClasspathEntry('output', os.path.join(output_dir, 'jdt_output'))) - xml.etree.ElementTree.ElementTree(classpath).write(sys.stdout, - encoding='unicode') + xml.etree.ElementTree.ElementTree(classpath).write( + '.classpath', encoding='unicode') + print('Generated .classpath', file=sys.stderr) + + with open('.project', 'w') as f: + f.write(""" + + chromium + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + +""") + print('Generated .project', file=sys.stderr) + + # Tell the Eclipse compiler not to use java.lang.invoke.StringConcatFactory + # in the generated bytecodes as the class is unavailable in Android. + os.makedirs('.settings', exist_ok=True) + with open('.settings/org.eclipse.jdt.core.prefs', 'w') as f: + f.write("""eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.useStringConcatFactory=disabled +""") + print('Generated .settings', file=sys.stderr) def _ParseArguments(argv): parser = argparse.ArgumentParser( description= - 'Given Chromium Java build config files, dumps an Eclipse JDT classpath ' - 'file to standard output that can be used with the "Language Support for ' - 'Java™ by Red Hat" Visual Studio Code extension. See //docs/vscode.md ' + 'Given Chromium Java build config files, generates an Eclipse JDT ' + 'project that can be used with the "Language Support for Java™ by ' + 'Red Hat" Visual Studio Code extension. See //docs/vscode.md ' 'for details.') parser.add_argument( '--output-dir', @@ -152,6 +180,9 @@ def _ParseArguments(argv): def main(argv): build_utils.InitLogging('GENERATE_VSCODE_CLASSPATH_DEBUG') + + assert os.path.exists('.gn'), 'This script must be run from the src directory' + args = _ParseArguments(argv) output_dir = args.output_dir @@ -168,7 +199,7 @@ def main(argv): logging.info('Done processing %d build config files', len(already_processed_build_config_files)) - _GenerateClasspathFile(source_dirs, libs) + _GenerateProject(source_dirs, libs, output_dir) if __name__ == '__main__': diff --git a/naiveproxy/src/build/android/gyp/compile_java.py b/naiveproxy/src/build/android/gyp/compile_java.py index 40a8329dd2..312869610f 100755 --- a/naiveproxy/src/build/android/gyp/compile_java.py +++ b/naiveproxy/src/build/android/gyp/compile_java.py @@ -406,6 +406,15 @@ class _InfoFileContext: def _OnStaleMd5(changes, options, javac_cmd, javac_args, java_files, kt_files): logging.info('Starting _OnStaleMd5') + + # Use the build server for errorprone runs. + if (options.enable_errorprone and not options.skip_build_server + and server_utils.MaybeRunCommand(name=options.target_name, + argv=sys.argv, + stamp_file=options.jar_path, + force=options.use_build_server)): + return + if options.enable_kythe_annotations: # Kythe requires those env variables to be set and compile_java.py does the # same @@ -443,10 +452,12 @@ def _OnStaleMd5(changes, options, javac_cmd, javac_args, java_files, kt_files): jar_info_path = None if not options.enable_errorprone: # Delete any stale files in the generated directory. The purpose of - # options.generated_dir is for codesearch. + # options.generated_dir is for codesearch and Android Studio. shutil.rmtree(options.generated_dir, True) intermediates_out_dir = options.generated_dir + # Write .info file only for the main javac invocation (no need to do it + # when running Error Prone. jar_info_path = options.jar_path + '.info' # Compiles with Error Prone take twice as long to run as pure javac. Thus GN @@ -607,6 +618,15 @@ def _RunCompiler(changes, CreateJarFile(jar_path, classes_dir, service_provider_configuration, options.additional_jar_files, options.kotlin_jar_path) + # Remove input srcjars that confuse Android Studio: + # https://crbug.com/353326240 + for root, _, files in os.walk(intermediates_out_dir): + for subpath in files: + p = os.path.join(root, subpath) + # JNI Zero placeholders + if '_jni_java/' in p and not p.endswith('Jni.java'): + os.unlink(p) + if save_info_file: info_file_context.Commit(jar_info_path) @@ -732,14 +752,6 @@ def main(argv): argv = build_utils.ExpandFileArgs(argv) options, java_files, kt_files = _ParseOptions(argv) - # Only use the build server for errorprone runs. - if (options.enable_errorprone and not options.skip_build_server - and server_utils.MaybeRunCommand(name=options.target_name, - argv=sys.argv, - stamp_file=options.jar_path, - force=options.use_build_server)): - return - javac_cmd = [build_utils.JAVAC_PATH] javac_args = [ diff --git a/naiveproxy/src/build/android/gyp/compile_kt.py b/naiveproxy/src/build/android/gyp/compile_kt.py index d7b1ccf081..cbb3fc3302 100755 --- a/naiveproxy/src/build/android/gyp/compile_kt.py +++ b/naiveproxy/src/build/android/gyp/compile_kt.py @@ -154,6 +154,9 @@ def main(argv): '-no-stdlib', # Avoid depending on the bundled Kotlin reflect libs. '-no-reflect', + # We typically set a default of 1G for java commands, see + # build_utils.JavaCmd. This may help prevent OOMs. + '-J-Xmx1G', ] if args.generated_dir: diff --git a/naiveproxy/src/build/android/gyp/compile_resources.py b/naiveproxy/src/build/android/gyp/compile_resources.py index be0db0fbcb..cb227e9d1b 100755 --- a/naiveproxy/src/build/android/gyp/compile_resources.py +++ b/naiveproxy/src/build/android/gyp/compile_resources.py @@ -39,8 +39,6 @@ import zip_helpers # Pngs that we shouldn't convert to webp. Please add rationale when updating. _PNG_WEBP_EXCLUSION_PATTERN = re.compile('|'.join([ - # Crashes on Galaxy S5 running L (https://crbug.com/807059). - r'.*star_gray\.png', # Android requires pngs for 9-patch images. r'.*\.9\.png', # Daydream requires pngs for icon files. diff --git a/naiveproxy/src/build/android/gyp/create_bundle_wrapper_script.py b/naiveproxy/src/build/android/gyp/create_bundle_wrapper_script.py index a3870bf895..f8357fe154 100755 --- a/naiveproxy/src/build/android/gyp/create_bundle_wrapper_script.py +++ b/naiveproxy/src/build/android/gyp/create_bundle_wrapper_script.py @@ -42,7 +42,8 @@ def main(): proguard_mapping_path=resolve(${MAPPING_PATH}), target_cpu=${TARGET_CPU}, system_image_locales=${SYSTEM_IMAGE_LOCALES}, - default_modules=${DEFAULT_MODULES}) + default_modules=${DEFAULT_MODULES}, + is_official_build=${IS_OFFICIAL_BUILD}) if __name__ == '__main__': sys.exit(main()) @@ -71,6 +72,7 @@ def main(args): parser.add_argument('--target-cpu') parser.add_argument('--system-image-locales') parser.add_argument('--default-modules', nargs='*', default=[]) + parser.add_argument('--is-official-build', action='store_true') args = parser.parse_args(args) def relativize(path): @@ -113,6 +115,8 @@ def main(args): repr(action_helpers.parse_gn_list(args.system_image_locales)), 'DEFAULT_MODULES': repr(args.default_modules), + 'IS_OFFICIAL_BUILD': + repr(args.is_official_build), } script.write(SCRIPT_TEMPLATE.substitute(script_dict)) os.chmod(args.script_output_path, 0o750) diff --git a/naiveproxy/src/build/android/gyp/lint.py b/naiveproxy/src/build/android/gyp/lint.py index 0ac068ae48..ed8368cda1 100755 --- a/naiveproxy/src/build/android/gyp/lint.py +++ b/naiveproxy/src/build/android/gyp/lint.py @@ -467,17 +467,6 @@ def main(): build_utils.InitLogging('LINT_DEBUG') args = _ParseArgs(sys.argv[1:]) - # TODO(wnwen): Consider removing lint cache now that there are only two lint - # invocations. - # Avoid parallelizing cache creation since lint runs without the cache defeat - # the purpose of creating the cache in the first place. - if (not args.create_cache and not args.skip_build_server - and server_utils.MaybeRunCommand(name=args.target_name, - argv=sys.argv, - stamp_file=args.stamp, - force=args.use_build_server)): - return - sources = [] for sources_file in args.sources: sources.extend(build_utils.ReadSourcesList(sources_file)) @@ -492,6 +481,21 @@ def main(): ]) depfile_deps = [p for p in possible_depfile_deps if p] + if args.depfile: + action_helpers.write_depfile(args.depfile, args.stamp, depfile_deps) + + # TODO(wnwen): Consider removing lint cache now that there are only two lint + # invocations. + # Avoid parallelizing cache creation since lint runs without the cache defeat + # the purpose of creating the cache in the first place. Forward the command + # after the depfile has been written as siso requires it. + if (not args.create_cache and not args.skip_build_server + and server_utils.MaybeRunCommand(name=args.target_name, + argv=sys.argv, + stamp_file=args.stamp, + force=args.use_build_server)): + return + _RunLint(args.custom_lint_jar_path, args.lint_jar_path, args.backported_methods, @@ -514,9 +518,6 @@ def main(): logging.info('Creating stamp file') build_utils.Touch(args.stamp) - if args.depfile: - action_helpers.write_depfile(args.depfile, args.stamp, depfile_deps) - if __name__ == '__main__': sys.exit(main()) diff --git a/naiveproxy/src/build/android/gyp/util/jar_utils.py b/naiveproxy/src/build/android/gyp/util/jar_utils.py index 05ecdbfb8c..a2823feda3 100644 --- a/naiveproxy/src/build/android/gyp/util/jar_utils.py +++ b/naiveproxy/src/build/android/gyp/util/jar_utils.py @@ -5,35 +5,19 @@ import logging import pathlib +import subprocess import zipfile from typing import List, Optional, Union -from util import build_utils - _SRC_PATH = pathlib.Path(__file__).resolve().parents[4] _JDEPS_PATH = _SRC_PATH / 'third_party/jdk/current/bin/jdeps' _IGNORED_JAR_PATHS = [ # This matches org_ow2_asm_asm_commons and org_ow2_asm_asm_analysis, both of - # which fail jdeps (not sure why). - 'third_party/android_deps/libs/org_ow2_asm_asm', + # which fail jdeps (not sure why), see: https://crbug.com/348423879 + 'third_party/android_deps/cipd/libs/org_ow2_asm_asm', ] - -def _is_relative_to(path: pathlib.Path, other_path: pathlib.Path): - """This replicates pathlib.Path.is_relative_to. - - Since bots still run python3.8, they do not have access to is_relative_to, - which was introduced in python3.9. - """ - try: - path.relative_to(other_path) - return True - except ValueError: - # This error is expected when path is not a subpath of other_path. - return False - - def _should_ignore(jar_path: pathlib.Path) -> bool: for ignored_jar_path in _IGNORED_JAR_PATHS: if ignored_jar_path in str(jar_path): @@ -43,20 +27,39 @@ def _should_ignore(jar_path: pathlib.Path) -> bool: def run_jdeps(filepath: pathlib.Path, *, - jdeps_path: pathlib.Path = _JDEPS_PATH) -> Optional[str]: + jdeps_path: pathlib.Path = _JDEPS_PATH, + verbose: bool = False) -> Optional[str]: """Runs jdeps on the given filepath and returns the output.""" if not filepath.exists() or _should_ignore(filepath): # Some __compile_java targets do not generate a .jar file, skipping these # does not affect correctness. return None - return build_utils.CheckOutput([ + cmd = [ str(jdeps_path), '-verbose:class', '--multi-release', # Some jars support multiple JDK releases. 'base', str(filepath), - ]) + ] + + if verbose: + logging.debug('Starting %s', filepath) + try: + return subprocess.run( + cmd, + check=True, + text=True, + capture_output=True, + ).stdout + except subprocess.CalledProcessError as e: + # Pack all the information into the error message since that is the last + # thing visible in the output. + raise RuntimeError(f'\nFilepath:\n{filepath}\ncmd:\n{" ".join(cmd)}\n' + f'stdout:\n{e.stdout}\nstderr:{e.stderr}\n') from e + finally: + if verbose: + logging.debug('Finished %s', filepath) def extract_full_class_names_from_jar( diff --git a/naiveproxy/src/build/android/incremental_install/third_party/AndroidHiddenApiBypass/README.chromium b/naiveproxy/src/build/android/incremental_install/third_party/AndroidHiddenApiBypass/README.chromium index 72fd2659d6..06d50802e1 100644 --- a/naiveproxy/src/build/android/incremental_install/third_party/AndroidHiddenApiBypass/README.chromium +++ b/naiveproxy/src/build/android/incremental_install/third_party/AndroidHiddenApiBypass/README.chromium @@ -1,6 +1,7 @@ Name: AndroidHiddenApiBypass URL: https://github.com/LSPosed/AndroidHiddenApiBypass Version: b16cc3934a27e55e51f00f5504c7f49e7c8cfab7 +Revision: b16cc3934a27e55e51f00f5504c7f49e7c8cfab7 License: Apache 2.0 License File: LICENSE Security Critical: no diff --git a/naiveproxy/src/build/android/pylib/base/base_test_result.py b/naiveproxy/src/build/android/pylib/base/base_test_result.py index 584ca84f69..70de88a748 100644 --- a/naiveproxy/src/build/android/pylib/base/base_test_result.py +++ b/naiveproxy/src/build/android/pylib/base/base_test_result.py @@ -10,7 +10,7 @@ import re import sys import threading -from lib.results import result_types # pylint: disable=import-error +from lib.results import result_types # This must match the source adding the suffix: bit.ly/3Zmwwyx MULTIPROCESS_SUFFIX = '__multiprocess_mode' diff --git a/naiveproxy/src/build/android/pylib/constants/__init__.py b/naiveproxy/src/build/android/pylib/constants/__init__.py index 86ef4192eb..481f78a92c 100644 --- a/naiveproxy/src/build/android/pylib/constants/__init__.py +++ b/naiveproxy/src/build/android/pylib/constants/__init__.py @@ -114,7 +114,7 @@ DEVICE_PERF_OUTPUT_DIR = ( SCREENSHOTS_DIR = os.path.join(DIR_SOURCE_ROOT, 'out_screenshots') -ANDROID_SDK_BUILD_TOOLS_VERSION = '34.0.0' +ANDROID_SDK_BUILD_TOOLS_VERSION = '35.0.0' ANDROID_SDK_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'android_sdk', 'public') ANDROID_SDK_TOOLS = os.path.join(ANDROID_SDK_ROOT, diff --git a/naiveproxy/src/build/android/pylib/constants/host_paths.py b/naiveproxy/src/build/android/pylib/constants/host_paths.py index 4b712649e7..6af2f7a406 100644 --- a/naiveproxy/src/build/android/pylib/constants/host_paths.py +++ b/naiveproxy/src/build/android/pylib/constants/host_paths.py @@ -14,16 +14,14 @@ DIR_SOURCE_ROOT = os.environ.get( os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, os.pardir))) -BUILD_COMMON_PATH = os.path.join( - DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common') - # third-party libraries ANDROID_PLATFORM_DEVELOPMENT_SCRIPTS_PATH = os.path.join( DIR_SOURCE_ROOT, 'third_party', 'android_platform', 'development', 'scripts') BUILD_PATH = os.path.join(DIR_SOURCE_ROOT, 'build') -DEVIL_PATH = os.path.join( - DIR_SOURCE_ROOT, 'third_party', 'catapult', 'devil') +BUILD_UTIL_PATH = os.path.join(DIR_SOURCE_ROOT, 'build', 'util') + +DEVIL_PATH = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'catapult', 'devil') JAVA_PATH = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'jdk', 'current', 'bin') TRACING_PATH = os.path.join( diff --git a/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py b/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py index dbed400181..2b331a0392 100644 --- a/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py +++ b/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py @@ -21,10 +21,8 @@ from pylib.base import test_instance from pylib.symbols import stack_symbolizer from pylib.utils import test_filter - -with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): - import unittest_util # pylint: disable=import-error - +with host_paths.SysPath(host_paths.BUILD_UTIL_PATH): + from lib.common import unittest_util BROWSER_TEST_SUITES = [ 'android_browsertests', diff --git a/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance.py b/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance.py index 2b86a4d730..4ffeda08da 100644 --- a/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance.py +++ b/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance.py @@ -22,9 +22,8 @@ from pylib.utils import dexdump from pylib.utils import gold_utils from pylib.utils import test_filter - -with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): - import unittest_util # pylint: disable=import-error +with host_paths.SysPath(host_paths.BUILD_UTIL_PATH): + from lib.common import unittest_util # Ref: http://developer.android.com/reference/android/app/Activity.html _ACTIVITY_RESULT_CANCELED = 0 @@ -63,6 +62,16 @@ _BUNDLE_STACK_ID = 'stack' # The ID of the bundle value Chrome uses to report the test duration. _BUNDLE_DURATION_ID = 'duration_ms' +# The following error messages are too general to be useful in failure +# clustering. The runner doesn't report failure reason when such failure +# reason is parsed from test logs. +_BANNED_FAILURE_REASONS = [ + # Default error message from org.chromium.base.test.util.CallbackHelper + # when timeout at expecting call back. + 'java.util.concurrent.TimeoutException: waitForCallback timed out!', +] + + class MissingSizeAnnotationError(test_exception.TestException): def __init__(self, class_name): super().__init__( @@ -195,7 +204,9 @@ def _MaybeSetLog(bundle, current_result, symbolizer, device_abi): else: current_result.SetLog(stack) - current_result.SetFailureReason(_ParseExceptionMessage(stack)) + parsed_failure_reason = _ParseExceptionMessage(stack) + if parsed_failure_reason not in _BANNED_FAILURE_REASONS: + current_result.SetFailureReason(parsed_failure_reason) def _ParseExceptionMessage(stack): @@ -604,6 +615,8 @@ class InstrumentationTestInstance(test_instance.TestInstance): self._approve_app_links_package = None self._initializeApproveAppLinksAttributes(args) + self._webview_process_mode = args.webview_process_mode + self._wpr_enable_record = args.wpr_enable_record self._external_shard_index = args.test_launcher_shard_index @@ -1029,6 +1042,10 @@ class InstrumentationTestInstance(test_instance.TestInstance): def wpr_record_mode(self): return self._wpr_enable_record + @property + def webview_process_mode(self): + return self._webview_process_mode + @property def wpr_replay_mode(self): return not self._wpr_enable_record diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run.py index f423a7c7d5..b734dd5455 100644 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run.py @@ -110,6 +110,8 @@ _EXTRA_TEST_IS_UNIT = 'BaseChromiumAndroidJUnitRunner.IsUnitTest' _EXTRA_PACKAGE_UNDER_TEST = ('org.chromium.chrome.test.pagecontroller.rules.' 'ChromeUiApplicationTestRule.PackageUnderTest') +_EXTRA_WEBVIEW_PROCESS_MODE = 'AwJUnit4ClassRunner.ProcessMode' + FEATURE_ANNOTATION = 'Feature' RENDER_TEST_FEATURE_ANNOTATION = 'RenderTest' WPR_ARCHIVE_FILE_PATH_ANNOTATION = 'WPRArchiveDirectory' @@ -539,6 +541,14 @@ class LocalDeviceInstrumentationTestRun( def approve_app_links(dev): self._ToggleAppLinks(dev, 'STATE_APPROVED') + @trace_event.traced + def disable_system_modals(dev): + # Disable "Swipe down to exit fullscreen" modal. + # Disable notification permission dialog in Android T+. + cmd = ('settings put secure immersive_mode_confirmations confirmed && ' + 'settings put secure notification_permission_enabled 0') + dev.RunShellCommand(cmd, shell=True, check_return=True) + @trace_event.traced def set_vega_permissions(dev): # Normally, installation of VrCore automatically grants storage @@ -615,8 +625,8 @@ class LocalDeviceInstrumentationTestRun( install_steps += [push_test_data, create_flag_changer] post_install_steps += [ - set_debug_app, approve_app_links, set_vega_permissions, - DismissCrashDialogs + set_debug_app, approve_app_links, disable_system_modals, + set_vega_permissions, DismissCrashDialogs ] def bind_crash_handler(step, dev): @@ -1393,6 +1403,9 @@ class LocalDeviceInstrumentationTestRun( # Workaround for https://github.com/mockito/mockito/issues/922 'notPackage': 'net.bytebuddy', } + if self._test_instance.webview_process_mode: + extras[_EXTRA_WEBVIEW_PROCESS_MODE] = ( + self._test_instance.webview_process_mode) if self._test_instance.timeout_scale != 1: extras[EXTRA_TIMEOUT_SCALE] = str(self._test_instance.timeout_scale) diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_test_run.py b/naiveproxy/src/build/android/pylib/local/device/local_device_test_run.py index 099c88a3f5..0c038976e8 100644 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_test_run.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_test_run.py @@ -25,6 +25,8 @@ from pylib.base import test_exception from pylib.base import test_run from pylib.local.device import local_device_environment +from lib.proto import exception_recorder + _SIGTERM_TEST_LOG = ( ' Suite execution terminated, probably due to swarming timeout.\n' @@ -86,7 +88,8 @@ class LocalDeviceTestRun(test_run.TestRun): else: raise Exception( 'Unexpected result type: %s' % type(result).__name__) - except device_errors.CommandTimeoutError: + except device_errors.CommandTimeoutError as e: + exception_recorder.register(e) # Test timeouts don't count as device errors for the purpose # of bad device detection. consecutive_device_errors = 0 @@ -113,11 +116,13 @@ class LocalDeviceTestRun(test_run.TestRun): base_test_result.BaseTestResult( self._GetUniqueTestName(test), base_test_result.ResultType.TIMEOUT)) - except device_errors.DeviceUnreachableError: + except device_errors.DeviceUnreachableError as e: + exception_recorder.register(e) # If the device is no longer reachable then terminate this # run_tests_on_device call. raise - except base_error.BaseError: + except base_error.BaseError as e: + exception_recorder.register(e) # If we get a device error but believe the device is still # reachable, attempt to continue using it. if isinstance(tests, test_collection.TestCollection): diff --git a/naiveproxy/src/build/android/pylib/local/emulator/avd.py b/naiveproxy/src/build/android/pylib/local/emulator/avd.py index b156d2128c..6eb7ca8cb1 100644 --- a/naiveproxy/src/build/android/pylib/local/emulator/avd.py +++ b/naiveproxy/src/build/android/pylib/local/emulator/avd.py @@ -28,6 +28,8 @@ from pylib import constants from pylib.local.emulator import ini from pylib.local.emulator.proto import avd_pb2 +from lib.proto import exception_recorder + # A common root directory to store the CIPD packages for creating or starting # the emulator instance, e.g. emulator binary, system images, AVDs. COMMON_CIPD_ROOT = os.path.join(constants.DIR_SOURCE_ROOT, '.android_emulator') @@ -842,7 +844,7 @@ class AvdConfig: for line in cmd_helper.IterCmdOutputLines(ensure_cmd): logging.info(' %s', line) except subprocess.CalledProcessError as e: - # avd.py is executed with python2. + exception_recorder.register(e) # pylint: disable=W0707 raise AvdException('Failed to install CIPD packages: %s' % str(e), command=ensure_cmd) @@ -970,7 +972,8 @@ class _AvdInstance: debug_tags=None, disk_size=None, enable_network=False, - require_fast_start=False): + require_fast_start=False, + retries=0): """Starts the emulator running an instance of the given AVD. Note when ensure_system_settings is True, the program will wait until the @@ -1014,8 +1017,8 @@ class _AvdInstance: avd_type = self._avd_name.split('_')[1] logging.info('Emulator Type: %s', avd_type) - if avd_type == 'car': - logging.info('Auto emulator will start slow') + if avd_type in ('car', '32'): + logging.info('Auto, Tablet emulator will start slow') is_slow_start = True if wipe_data: @@ -1051,8 +1054,8 @@ class _AvdInstance: emulator_cmd.append('-show-kernel') emulator_env = { - # kill immediately when emulator hang. - 'ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL': '0', + # kill as early as possible when emulator hang. + 'ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL': '1', # Sets the emulator configuration directory 'ANDROID_EMULATOR_HOME': self._emulator_home, } @@ -1104,7 +1107,7 @@ class _AvdInstance: self._emulator_serial = timeout_retry.Run( listen_for_serial, timeout=120 if is_slow_start else 30, - retries=0, + retries=retries, args=[sock]) logging.info('%s started', self._emulator_serial) except Exception: @@ -1118,7 +1121,7 @@ class _AvdInstance: assert self.device is not None, '`instance.device` not initialized.' logging.info('Waiting for device to be fully booted.') self.device.WaitUntilFullyBooted(timeout=360 if is_slow_start else 90, - retries=0) + retries=retries) logging.info('Device fully booted, verifying system settings.') _EnsureSystemSettings(self.device) diff --git a/naiveproxy/src/build/android/pylib/local/emulator/local_emulator_environment.py b/naiveproxy/src/build/android/pylib/local/emulator/local_emulator_environment.py index 322cb01666..c133450b95 100644 --- a/naiveproxy/src/build/android/pylib/local/emulator/local_emulator_environment.py +++ b/naiveproxy/src/build/android/pylib/local/emulator/local_emulator_environment.py @@ -6,13 +6,12 @@ import logging from devil import base_error -from devil.android import device_errors from devil.utils import parallelizer -from devil.utils import reraiser_thread -from devil.utils import timeout_retry from pylib.local.device import local_device_environment from pylib.local.emulator import avd +from lib.proto import exception_recorder + # Mirroring https://bit.ly/2OjuxcS#23 _MAX_ANDROID_EMULATORS = 16 @@ -43,7 +42,6 @@ class LocalEmulatorEnvironment(local_device_environment.LocalDeviceEnvironment): self._emulator_instances = [] self._device_serials = [] - self._emulator_start_timeout = 60 #override def SetUp(self): @@ -54,39 +52,26 @@ class LocalEmulatorEnvironment(local_device_environment.LocalDeviceEnvironment): for _ in range(self._emulator_count) ] - if 'car' in self._avd_config.avd_name or self._writable_system: - logging.info("Use longer timeout for AVD") - self._emulator_start_timeout = 120 - def start_emulator_instance(inst): - def is_timeout_error(exc): - return isinstance( - exc, - (device_errors.CommandTimeoutError, reraiser_thread.TimeoutError)) - - def impl(inst): - try: - inst.Start(window=self._emulator_window, - writable_system=self._writable_system, - debug_tags=self._emulator_debug_tags, - enable_network=self._emulator_enable_network, - require_fast_start=True) - except avd.AvdException: - logging.exception('Failed to start emulator instance.') - return None - except base_error.BaseError as e: - # Timeout error usually indicates the emulator is not responding. - # In this case, we should stop it forcely. - logging.info("Force stop the emulator") - inst.Stop(force=is_timeout_error(e)) - raise - return inst - - return timeout_retry.Run(impl, - timeout=self._emulator_start_timeout, - retries=2, - args=[inst], - retry_if_func=is_timeout_error) + try: + inst.Start(window=self._emulator_window, + writable_system=self._writable_system, + debug_tags=self._emulator_debug_tags, + enable_network=self._emulator_enable_network, + require_fast_start=True, + retries=2) + except avd.AvdException as e: + exception_recorder.register(e) + logging.exception('Failed to start emulator instance.') + return None + except base_error.BaseError as e: + exception_recorder.register(e) + # Timeout error usually indicates the emulator is not responding. + # In this case, we should stop it forcely. + logging.info("Force stop the emulator %s", inst) + inst.Stop(force=True) + raise + return inst parallel_emulators = parallelizer.SyncParallelizer(emulator_instances) self._emulator_instances = [ diff --git a/naiveproxy/src/build/android/pylib/local/local_test_server_spawner.py b/naiveproxy/src/build/android/pylib/local/local_test_server_spawner.py index a4e10ac5e8..5c277b3ec3 100644 --- a/naiveproxy/src/build/android/pylib/local/local_test_server_spawner.py +++ b/naiveproxy/src/build/android/pylib/local/local_test_server_spawner.py @@ -11,9 +11,8 @@ from devil.android import ports from pylib.base import test_server from pylib.constants import host_paths -with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): - import chrome_test_server_spawner - +with host_paths.SysPath(host_paths.BUILD_UTIL_PATH): + from lib.common import chrome_test_server_spawner # The tests should not need more than one test server instance. MAX_TEST_SERVER_INSTANCES = 1 diff --git a/naiveproxy/src/build/android/resource_sizes.py b/naiveproxy/src/build/android/resource_sizes.py index 3285511163..99a502c224 100755 --- a/naiveproxy/src/build/android/resource_sizes.py +++ b/naiveproxy/src/build/android/resource_sizes.py @@ -34,13 +34,14 @@ from pylib.constants import host_paths _AAPT_PATH = lazy.WeakConstant(lambda: build_tools.GetPath('aapt')) _ANDROID_UTILS_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'gyp') -_BUILD_UTILS_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'build', 'util') _READOBJ_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'llvm-build', 'Release+Asserts', 'bin', 'llvm-readobj') -with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): - import perf_tests_results_helper # pylint: disable=import-error +with host_paths.SysPath(host_paths.BUILD_UTIL_PATH): + from lib.common import perf_tests_results_helper + from lib.results import result_sink + from lib.results import result_types with host_paths.SysPath(host_paths.TRACING_PATH): from tracing.value import convert_chart_json # pylint: disable=import-error @@ -48,10 +49,6 @@ with host_paths.SysPath(host_paths.TRACING_PATH): with host_paths.SysPath(_ANDROID_UTILS_PATH, 0): from util import build_utils # pylint: disable=import-error -with host_paths.SysPath(_BUILD_UTILS_PATH, 0): - from lib.results import result_sink # pylint: disable=import-error - from lib.results import result_types # pylint: disable=import-error - # Captures an entire config from aapt output. _AAPT_CONFIG_PATTERN = r'config %s:(.*?)config [a-zA-Z-]+:' # Matches string resource entries from aapt output. @@ -865,7 +862,10 @@ def main(): '--isolated-script-test-perf-output', type=os.path.realpath, help=argparse.SUPPRESS) - + argparser.add_argument('--isolated-script-test-repeat', + help=argparse.SUPPRESS) + argparser.add_argument('--isolated-script-test-launcher-retry-limit', + help=argparse.SUPPRESS) output_group = argparser.add_mutually_exclusive_group() output_group.add_argument( diff --git a/naiveproxy/src/build/android/resource_sizes.pydeps b/naiveproxy/src/build/android/resource_sizes.pydeps index 86db3ff825..b649dc07d6 100644 --- a/naiveproxy/src/build/android/resource_sizes.pydeps +++ b/naiveproxy/src/build/android/resource_sizes.pydeps @@ -44,6 +44,7 @@ ../../third_party/catapult/tracing/tracing_project.py ../gn_helpers.py ../util/lib/__init__.py +../util/lib/common/__init__.py ../util/lib/common/perf_result_data_type.py ../util/lib/common/perf_tests_results_helper.py ../util/lib/results/__init__.py diff --git a/naiveproxy/src/build/android/test_runner.py b/naiveproxy/src/build/android/test_runner.py index de130fa240..47292b22bd 100755 --- a/naiveproxy/src/build/android/test_runner.py +++ b/naiveproxy/src/build/android/test_runner.py @@ -56,7 +56,8 @@ from pylib.utils import test_filter from py_utils import contextlib_ext -from lib.results import result_sink # pylint: disable=import-error +from lib.proto import exception_recorder +from lib.results import result_sink _DEVIL_STATIC_CONFIG_FILE = os.path.abspath(os.path.join( host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'devil_config.json')) @@ -600,6 +601,11 @@ def AddInstrumentationTestOptions(parser): default=[], action='append', help="Specifies command line arguments to add to WebView's flag file") + parser.add_argument( + '--webview-process-mode', + choices=['single', 'multiple'], + help='Run WebView instrumentation tests only in the specified process ' + 'mode. If not set, both single and multiple process modes will execute.') parser.add_argument( '--run-setup-command', default=[], @@ -969,7 +975,7 @@ def RunTestsCommand(args, result_sink_client=None): command = args.command ProcessCommonOptions(args) - logging.info('command: %s', ' '.join(sys.argv)) + logging.info('command: %s', shlex.join(sys.argv)) if args.enable_platform_mode or command in _DEFAULT_PLATFORM_MODE_TESTS: return RunTestsInPlatformMode(args, result_sink_client) @@ -1153,6 +1159,42 @@ def RunTestsInPlatformMode(args, result_sink_client=None): save_detailed_results = (args.local_output or not local_utils.IsOnSwarming() ) and not args.isolated_script_test_output + @contextlib.contextmanager + def exceptions_uploader(): + + def _upload_exceptions(): + if not result_sink_client or not exception_recorder.size(): + return + + try_count = 0 + try_count_max = 2 + while try_count < try_count_max: + try_count += 1 + logging.info('Uploading exception records to RDB. (TRY %d/%d)', + try_count, try_count_max) + try: + record_dict = exception_recorder.to_dict() + exception_recorder.clear() + result_sink_client.UpdateInvocationExtendedProperties( + {exception_recorder.EXCEPTION_OCCURRENCES_KEY: record_dict}) + break + except Exception as e: # pylint: disable=W0703 + logging.error("Got error %s when uploading exception records:\n%r", e, + record_dict) + if try_count < try_count_max: + # Upload can fail due to record size being too big. In this case, + # report just the upload failure. + exception_recorder.register(e) + else: + # Swallow the exception if the upload fails again and hit the max + # try so that it won't fail the test task (and it shouldn't). + logging.error("Hit max retry. Skip uploading exception records.") + + try: + yield + finally: + _upload_exceptions() + ### Set up test objects. out_manager = output_manager_factory.CreateOutputManager(args) @@ -1182,7 +1224,8 @@ def RunTestsInPlatformMode(args, result_sink_client=None): # |raw_logs_fh| is only used by Robolectric tests. raw_logs_fh = io.StringIO() if save_detailed_results else None - with json_writer(), logcats_uploader, env, test_instance, test_run: + with json_writer(), exceptions_uploader(), logcats_uploader, \ + env, test_instance, test_run: repetitions = (range(args.repeat + 1) if args.repeat >= 0 else itertools.count()) diff --git a/naiveproxy/src/build/android/test_runner.pydeps b/naiveproxy/src/build/android/test_runner.pydeps index b58e857c61..d69679364d 100644 --- a/naiveproxy/src/build/android/test_runner.pydeps +++ b/naiveproxy/src/build/android/test_runner.pydeps @@ -137,8 +137,12 @@ ../skia_gold_common/skia_gold_session.py ../skia_gold_common/skia_gold_session_manager.py ../util/lib/__init__.py +../util/lib/common/__init__.py ../util/lib/common/chrome_test_server_spawner.py ../util/lib/common/unittest_util.py +../util/lib/proto/__init__.py +../util/lib/proto/exception_occurrences_pb2.py +../util/lib/proto/exception_recorder.py ../util/lib/results/__init__.py ../util/lib/results/result_sink.py ../util/lib/results/result_types.py diff --git a/naiveproxy/src/build/config/BUILDCONFIG.gn b/naiveproxy/src/build/config/BUILDCONFIG.gn index 4f74aac12a..8b50c42527 100644 --- a/naiveproxy/src/build/config/BUILDCONFIG.gn +++ b/naiveproxy/src/build/config/BUILDCONFIG.gn @@ -350,6 +350,7 @@ default_compiler_configs = [ "//build/config/compiler:default_optimization", "//build/config/compiler:default_stack_frames", "//build/config/compiler:default_symbols", + "//build/config/compiler:libcxx_module", "//build/config/compiler:no_exceptions", "//build/config/compiler:no_rtti", "//build/config/compiler:no_unresolved_symbols", diff --git a/naiveproxy/src/build/config/android/config.gni b/naiveproxy/src/build/config/android/config.gni index 502736c4cd..2975eb28a6 100644 --- a/naiveproxy/src/build/config/android/config.gni +++ b/naiveproxy/src/build/config/android/config.gni @@ -18,6 +18,13 @@ declare_args() { is_java_debug = is_debug || incremental_install } +# These two combinations could theoretically be made to work, but they are +# not useful and so not worth the effort. +assert(!(is_java_debug && is_official_build), + "Cannot have is_official_build && is_java_debug") +assert(!(incremental_install && !is_java_debug), + "Cannot have incremental_install without is_java_debug") + # Toolchain used to create native libraries for robolectric_binary() targets. robolectric_toolchain = "//build/toolchain/android:robolectric_$host_cpu" @@ -134,12 +141,12 @@ if (is_android || is_chromeos) { public_android_sdk_root = "//third_party/android_sdk/public" public_android_sdk_build_tools = - "${public_android_sdk_root}/build-tools/34.0.0" - public_android_sdk_version = "34" - if (android_sdk_release == "u") { + "${public_android_sdk_root}/build-tools/35.0.0" + public_android_sdk_version = "35" + if (android_sdk_release == "v") { default_android_sdk_root = public_android_sdk_root default_android_sdk_version = public_android_sdk_version - default_android_sdk_build_tools_version = "34.0.0" + default_android_sdk_build_tools_version = "35.0.0" public_android_sdk = true } @@ -152,7 +159,7 @@ if (is_android || is_chromeos) { # Purposefully repeated so that downstream can change # default_android_sdk_root without changing lint version. default_lint_android_sdk_root = public_android_sdk_root - default_lint_android_sdk_version = 34 + default_lint_android_sdk_version = 35 } if (!defined(default_extras_android_sdk_root)) { diff --git a/naiveproxy/src/build/config/android/create_unwind_table.gni b/naiveproxy/src/build/config/android/create_unwind_table.gni index 92b7427c47..59cb024a84 100644 --- a/naiveproxy/src/build/config/android/create_unwind_table.gni +++ b/naiveproxy/src/build/config/android/create_unwind_table.gni @@ -6,7 +6,8 @@ import("//build/config/android/rules.gni") unwind_table_asset_v2_filename = "unwind_cfi_32_v2" -_dump_syms_target = "//third_party/breakpad:dump_syms($host_toolchain)" +_dump_syms_target = + "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)" _dump_syms = get_label_info(_dump_syms_target, "root_out_dir") + "/dump_syms" _readobj_path = "$clang_base_path/bin/llvm-readobj" diff --git a/naiveproxy/src/build/config/android/extract_unwind_tables.gni b/naiveproxy/src/build/config/android/extract_unwind_tables.gni index d4daa6a2aa..6518a2d3a0 100644 --- a/naiveproxy/src/build/config/android/extract_unwind_tables.gni +++ b/naiveproxy/src/build/config/android/extract_unwind_tables.gni @@ -6,7 +6,8 @@ import("//build/config/android/rules.gni") unwind_table_asset_v1_filename = "unwind_cfi_32" -_dump_syms_target = "//third_party/breakpad:dump_syms($host_toolchain)" +_dump_syms_target = + "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)" _dump_syms = get_label_info(_dump_syms_target, "root_out_dir") + "/dump_syms" template("unwind_table_v1") { diff --git a/naiveproxy/src/build/config/android/linker_version_script.gni b/naiveproxy/src/build/config/android/linker_version_script.gni index 3e99868c3c..facf3a3cfd 100644 --- a/naiveproxy/src/build/config/android/linker_version_script.gni +++ b/naiveproxy/src/build/config/android/linker_version_script.gni @@ -29,7 +29,7 @@ template("generate_linker_version_script") { if (defined(invoker.testonly) && invoker.testonly) { args += [ "--export-fortesting-java-symbols" ] } - if (allow_jni_multiplexing) { + if (enable_jni_multiplexing) { args += [ "--jni-multiplexing" ] } diff --git a/naiveproxy/src/build/config/android/rules.gni b/naiveproxy/src/build/config/android/rules.gni index 2ed5851e0d..80f918a818 100644 --- a/naiveproxy/src/build/config/android/rules.gni +++ b/naiveproxy/src/build/config/android/rules.gni @@ -3265,7 +3265,6 @@ if (!is_robolectric && enable_java_templates) { "data_deps", "deps", "enable_lint", - "enable_jni_multiplexing", "enable_proguard_checks", "enforce_resource_overlays_in_tests", "expected_android_manifest", @@ -3414,7 +3413,6 @@ if (!is_robolectric && enable_java_templates) { "data", "data_deps", "deps", - "enable_jni_multiplexing", "expected_android_manifest", "expected_android_manifest_base", "expected_android_manifest_library_version_offset", @@ -3657,9 +3655,7 @@ if (!is_robolectric && enable_java_templates) { data += invoker.data } - deps = [ - "//testing/android/instrumentation:instrumentation_test_runner_java", - ] + deps = [ "//testing/android/instrumentation:test_runner_java" ] if (defined(invoker.deps)) { deps += invoker.deps } @@ -5093,6 +5089,9 @@ if (!is_robolectric && enable_java_templates) { data_deps += [ "//build/android/stacktrace:java_deobfuscate" ] data += [ _proguard_mapping_path ] } + if (is_official_build) { + args += [ "--is-official-build" ] + } } _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && diff --git a/naiveproxy/src/build/config/android/sdk.gni b/naiveproxy/src/build/config/android/sdk.gni index af8496c47b..d666ebea62 100644 --- a/naiveproxy/src/build/config/android/sdk.gni +++ b/naiveproxy/src/build/config/android/sdk.gni @@ -4,7 +4,7 @@ # The default SDK release used by public builds. Value may differ in # internal builds. -default_android_sdk_release = "u" +default_android_sdk_release = "v" # SDK releases against which public builds are supported. -public_sdk_releases = [ "u" ] +public_sdk_releases = [ "v" ] diff --git a/naiveproxy/src/build/config/c++/BUILD.gn b/naiveproxy/src/build/config/c++/BUILD.gn index fa74fd90d4..f920982b3d 100644 --- a/naiveproxy/src/build/config/c++/BUILD.gn +++ b/naiveproxy/src/build/config/c++/BUILD.gn @@ -42,23 +42,15 @@ config("runtime_library") { defines += [ "_LIBCPP_ENABLE_DEBUG_MODE" ] } - defines += [ "CR_LIBCXX_REVISION=$libcxx_revision" ] - - # Temporarily add a define to force a rebuild when changing - # buildtools/third_party/libc++/__config_site which isn't picked up by - # dependency tracking (because it's an #include of headers included via - # -isysroot). - # TODO(thakis): Remove this after a few days. - if (is_fuchsia) { - defines += [ "TEMP_REBUILD_HACK" ] + # Fuzzers build parts of the code with asan enabled and some with it + # disabled. That's incompatible with _LIBCPP_INSTRUMENTED_WITH_ASAN, see + # https://crbug.com/347026228#comment25 + # TODO(thakis): Enable on apple if https://llvm.org/PR96099 gets fixed. + if (is_asan && !use_fuzzing_engine && !is_apple) { + defines += [ "_LIBCPP_INSTRUMENTED_WITH_ASAN" ] } - # Temporarily add a define to force a rebuild when changing - # buildtools/third_party/libc++/__assertion_handler which isn't picked up by - # dependency tracking (because it's an #include of headers included via - # -isysroot). - # TODO(crbug.com/40255003): remove after a few days. - defines += [ "TEMP_REBUILD_HACK_ASSERTION_HANDLER" ] + defines += [ "CR_LIBCXX_REVISION=$libcxx_revision" ] if (is_win) { # Intentionally not using libc++abi on Windows because libc++abi only diff --git a/naiveproxy/src/build/config/c++/c++.gni b/naiveproxy/src/build/config/c++/c++.gni index e7bf4cd86f..385c1d3c13 100644 --- a/naiveproxy/src/build/config/c++/c++.gni +++ b/naiveproxy/src/build/config/c++/c++.gni @@ -38,8 +38,17 @@ declare_args() { # generation of snapshot_blob.bin take ~40-60 s longer. Therefore this # defaults to off. enable_iterator_debugging = false + + # Use Clang header modules for libc++. + # This is experimental only (see crbug.com/543704). + # For details on the current state of modules in Chromium see + # https://chromium.googlesource.com/chromium/src/+/main/docs/modules.md + use_libcxx_modules = false } +assert(!use_libcxx_modules || !use_remoteexec, + "Implicit Clang header modules don't work with remote execution.") + use_custom_libcxx = use_custom_libcxx || (use_custom_libcxx_for_host && !is_a_target_toolchain) use_custom_libcxx = use_custom_libcxx && !is_nacl @@ -88,6 +97,7 @@ if (is_android && export_libcxxabi_from_executables) { libcxx_prefix = "//third_party/libc++/src" libcxxabi_prefix = "//third_party/libc++abi/src" +libcxx_module_prefix = "$root_gen_dir/libcxx" assert(!(is_ios && libcxx_is_shared), "Can't build libc++ as a shared library on iOS.") diff --git a/naiveproxy/src/build/config/chrome_build.gni b/naiveproxy/src/build/config/chrome_build.gni index cd12d2f976..ddb1d392ef 100644 --- a/naiveproxy/src/build/config/chrome_build.gni +++ b/naiveproxy/src/build/config/chrome_build.gni @@ -22,9 +22,11 @@ declare_args() { # Set to true to enable settings for high end Android devices, typically # enhancing speed at the expense of resources such as binary sizes and memory. - # Non-official builds should ignore this argument so that arm64 builders - # remain fast and independent from PGO without having to set the value to false. - is_high_end_android = target_cpu == "arm64" + is_high_end_android = target_cpu == "arm64" || target_cpu == "x64" + + # Set to true to set defaults that enable features on Android that are more + # typically available on desktop. + is_desktop_android = false if (is_android) { # By default, Trichrome channels are compiled using separate package names. @@ -38,6 +40,14 @@ declare_args() { # Ensure !is_android implies !is_high_end_android. is_high_end_android = is_high_end_android && is_android +if (is_desktop_android) { + assert(target_os == "android", + "Target must be Android to use is_desktop_android.") + + # Disable for non-android secondary toolchains. + is_desktop_android = is_android +} + declare_args() { # Whether to apply size->speed trade-offs to the secondary toolchain. # Relevant only for 64-bit target_cpu. diff --git a/naiveproxy/src/build/config/chromeos/rules.gni b/naiveproxy/src/build/config/chromeos/rules.gni index 68de9c69df..17f27bf4a4 100644 --- a/naiveproxy/src/build/config/chromeos/rules.gni +++ b/naiveproxy/src/build/config/chromeos/rules.gni @@ -508,6 +508,32 @@ template("generate_runner_script") { } } +# Handy template to define a generated_script test prepended with the +# cros_test_wrapper, which will automatically handle spinning up a CrOS VM +# and/or deploying the browser to the DUT prior to test execution. +template("cros_test_wrapper_script_test") { + forward_variables_from(invoker, + [ + "data_deps", + "args", + ]) + generate_wrapper("${target_name}") { + executable = "$root_out_dir/bin/cros_test_wrapper" + wrapper_script = "$root_out_dir/bin/run_${target_name}" + testonly = true + + if (!defined(args)) { + args = [] + } + executable_args = args + + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ "//chromeos:cros_test_wrapper" ] + } +} + template("tast_test") { forward_variables_from(invoker, "*") diff --git a/naiveproxy/src/build/config/clang/BUILD.gn b/naiveproxy/src/build/config/clang/BUILD.gn index 75f12546f9..e6d80a8d48 100644 --- a/naiveproxy/src/build/config/clang/BUILD.gn +++ b/naiveproxy/src/build/config/clang/BUILD.gn @@ -10,8 +10,60 @@ if (is_ios) { import("//build/config/ios/config.gni") # For `target_environment` } +config("raw_ptr_check") { + if (clang_use_chrome_plugins || clang_use_raw_ptr_plugin) { + cflags = [] + + # The plugin is built directly into clang, so there's no need to load it + # dynamically. + cflags += [ + "-Xclang", + "-add-plugin", + "-Xclang", + "raw-ptr-plugin", + + "-Xclang", + "-plugin-arg-raw-ptr-plugin", + "-Xclang", + "check-raw-ptr-to-stack-allocated", + + "-Xclang", + "-plugin-arg-raw-ptr-plugin", + "-Xclang", + "disable-check-raw-ptr-to-stack-allocated-error", + + # TODO(crbug.com/40944547): Remove when raw_ptr check has been + # enabled for the dawn repo. + "-Xclang", + "-plugin-arg-raw-ptr-plugin", + "-Xclang", + "raw-ptr-exclude-path=" + + rebase_path("//third_party/dawn/", root_build_dir), + ] + + if (enable_check_raw_ptr_fields) { + cflags += [ + "-Xclang", + "-plugin-arg-raw-ptr-plugin", + "-Xclang", + "check-raw-ptr-fields", + ] + } + + if (enable_check_raw_ref_fields) { + cflags += [ + "-Xclang", + "-plugin-arg-raw-ptr-plugin", + "-Xclang", + "check-raw-ref-fields", + ] + } + } +} + config("find_bad_constructs") { if (clang_use_chrome_plugins) { + configs = [] cflags = [] # The plugin is built directly into clang, so there's no need to load it @@ -42,35 +94,6 @@ config("find_bad_constructs") { "-plugin-arg-find-bad-constructs", "-Xclang", "check-allow-auto-typedefs-better-nested", - - "-Xclang", - "-plugin-arg-find-bad-constructs", - "-Xclang", - "check-raw-ptr-to-stack-allocated", - - "-Xclang", - "-plugin-arg-find-bad-constructs", - "-Xclang", - "disable-check-raw-ptr-to-stack-allocated-error", - - # TODO(https://crbug.com/40064499): Remove when clang plugin rolls with - # updated RawPtrManualPathsToIgnore.h and we confirm that these - # directories are fully rewritten. - "-Xclang", - "-plugin-arg-find-bad-constructs", - "-Xclang", - "raw-ptr-exclude-path=/renderer/", - "-Xclang", - "-plugin-arg-find-bad-constructs", - "-Xclang", - "raw-ptr-exclude-path=third_party/blink/public/web/", - - # TODO(crbug.com/40944547): Remove when raw_ptr check has been - # enabled for the dawn repo. - "-Xclang", - "-plugin-arg-find-bad-constructs", - "-Xclang", - "raw-ptr-exclude-path=/third_party/dawn/", ] if (is_linux || is_chromeos || is_android || is_fuchsia) { @@ -82,23 +105,7 @@ config("find_bad_constructs") { ] } - if (enable_check_raw_ptr_fields) { - cflags += [ - "-Xclang", - "-plugin-arg-find-bad-constructs", - "-Xclang", - "check-raw-ptr-fields", - ] - } - - if (enable_check_raw_ref_fields) { - cflags += [ - "-Xclang", - "-plugin-arg-find-bad-constructs", - "-Xclang", - "check-raw-ref-fields", - ] - } + configs += [ ":raw_ptr_check" ] } } diff --git a/naiveproxy/src/build/config/clang/clang.gni b/naiveproxy/src/build/config/clang/clang.gni index 11d3551ebc..9928fc37b8 100644 --- a/naiveproxy/src/build/config/clang/clang.gni +++ b/naiveproxy/src/build/config/clang/clang.gni @@ -15,6 +15,9 @@ declare_args() { is_clang && !is_nacl && current_os != "zos" && default_toolchain != "//build/toolchain/cros:target" + # Use this instead of clang_use_chrome_plugins to enable just the raw-ptr-plugin. + clang_use_raw_ptr_plugin = false + enable_check_raw_ptr_fields = build_with_chromium && !is_official_build && ((is_linux && !is_castos) || (is_android && !is_cast_android) || is_mac || diff --git a/naiveproxy/src/build/config/compiler/BUILD.gn b/naiveproxy/src/build/config/compiler/BUILD.gn index dee027e9e1..eca58cadbd 100644 --- a/naiveproxy/src/build/config/compiler/BUILD.gn +++ b/naiveproxy/src/build/config/compiler/BUILD.gn @@ -427,7 +427,11 @@ config("compiler") { # links. ldflags += [ "-Wl,--build-id=sha1" ] } else if (current_os != "aix" && current_os != "zos") { - ldflags += [ "-Wl,--build-id" ] + if (use_lld && !is_nacl) { + ldflags += [ "-Wl,--build-id=fast" ] + } else { + ldflags += [ "-Wl,--build-id" ] + } } if (!is_android) { @@ -555,7 +559,7 @@ config("compiler") { ldflags += [ "-Wl,-z,keep-text-section-prefix" ] } - if (is_clang && !is_nacl && current_os != "zos") { + if (is_clang && !is_nacl) { cflags += [ "-fcrash-diagnostics-dir=" + clang_diagnostic_dir ] if (save_reproducers_on_lld_crash && use_lld) { ldflags += [ @@ -678,7 +682,7 @@ config("compiler") { } } - if (is_clang && current_os != "zos") { + if (is_clang) { # C++17 removes trigraph support, but clang still warns that it ignores # them when seeing them. Don't. cflags_cc += [ "-Wno-trigraphs" ] @@ -780,9 +784,7 @@ config("compiler") { # FIXME(inglorion): maybe tune these? # TODO(b/271459198): Revert limit on amd64 to 30 when fixed. import_instr_limit = 20 - } else if (is_android && (optimize_for_size || use_order_profiling)) { - # Reduce inlining for the orderfile instrumented build to mitigate - # crbug.com/330761384. + } else if (is_android && optimize_for_size) { # TODO(crbug.com/40219076): Investigate if we can get the > 6% perf win # of import_instr_limit 30 with a binary size hit smaller than ~2 MiB. import_instr_limit = 5 @@ -1590,7 +1592,13 @@ config("compiler_deterministic") { # -ffile-compilation-dir is an alias for both -fdebug-compilation-dir= # and -fcoverage-compilation-dir=. cflags += [ "-ffile-compilation-dir=." ] - swiftflags += [ "-file-compilation-dir=." ] + + # Convert absolute paths to relative paths. Expands to, for example: + # -file-prefix-map /path/to/chromium/src=../.. + swiftflags += [ + "-file-prefix-map", + rebase_path("//.", "") + "=" + rebase_path("//.", root_build_dir), + ] } if (!is_win) { # We don't use clang -cc1as on Windows (yet? https://crbug.com/762167) @@ -1630,7 +1638,8 @@ config("compiler_deterministic") { } config("clang_revision") { - if (is_clang && clang_base_path == default_clang_base_path) { + if (is_clang && clang_base_path == default_clang_base_path && + current_os != "zos") { update_args = [ "--print-revision", "--verify-version=$clang_version", @@ -1687,6 +1696,34 @@ config("compiler_arm") { } } +config("libcxx_module") { + if (use_libcxx_modules) { + modulemap = rebase_path("//third_party/libc++/src/include/module.modulemap", + root_build_dir) + cflags_cc = [ + "-fmodules", + "-fmodule-map-file=" + modulemap, + "-fno-implicit-module-maps", + "-fbuiltin-module-map", + "-fmodules-cache-path=" + + rebase_path("$libcxx_module_prefix/module_cache", root_build_dir), + + "-Xclang", + "-fmodules-local-submodule-visibility", # required for builtins + + # TODO(crbug.com/1456385): Figure out if this can be removed. + "-Wno-modules-ambiguous-internal-linkage", + + # TODO(crbug.com/40440396): Clean up. + "-Wno-modules-import-nested-redundant", + + # Needed to allow using builtin modules when the headers are + # unnecessarily using extern "C". + "-Wno-module-import-in-extern-c", + ] + } +} + # runtime_library ------------------------------------------------------------- # # Sets the runtime library and associated options. @@ -1923,16 +1960,9 @@ config("default_warnings") { # TODO(crbug.com/330524456): -Wcast-function-type is under -Wextra now. "-Wno-cast-function-type", - # Ignore warnings about MSVC optimization pragmas. - # TODO(thakis): Only for no_chromium_code? http://crbug.com/912662 - "-Wno-ignored-pragma-optimize", - # TODO(crbug.com/40231599) Evaluate and possibly enable. "-Wno-deprecated-builtins", - # TODO(crbug.com/40234766) Evaluate and possibly enable. - "-Wno-bitfield-constant-conversion", - # TODO(crbug.com/40255410) Evaluate and possibly enable. "-Wno-deprecated-this-capture", @@ -1957,10 +1987,8 @@ config("default_warnings") { "-Wno-c++11-narrowing-const-reference", ] - if (llvm_force_head_revision) { - # TODO(crbug.com/344680447): Fix and re-enable. - cflags_cc += [ "-Wno-missing-template-arg-list-after-template-kw" ] - } + # TODO(crbug.com/344680447): Fix and re-enable. + cflags_cc += [ "-Wno-missing-template-arg-list-after-template-kw" ] } } @@ -1976,6 +2004,11 @@ config("default_warnings") { } } + # TODO(crbug.com/354162568): Clean up and enable. + if (llvm_force_head_revision && is_apple && use_lld) { + ldflags += [ "-Wl,--no-warn-duplicate-rpath" ] + } + # Rust warnings # Require `unsafe` blocks even in `unsafe` fns. This is intended to become @@ -2464,7 +2497,12 @@ config("default_stack_frames") { # [2]: https://crrev.com/c/5447532 config("optimize") { if (is_win) { - cflags = [ "/O2" ] + common_optimize_on_cflags + # clang-cl's /O2 corresponds to clang's -O3, and really want -O2 for + # consistency with the other platforms. + cflags = [ + "/O2", + "/clang:-O2", + ] + common_optimize_on_cflags # The `-O3` for clang turns on extra optimizations compared to the standard # `-O2`. But for rust, `-Copt-level=3` is the default and is thus reliable @@ -2647,12 +2685,10 @@ if (is_clang && is_a_target_toolchain) { if (is_android || is_castos) { _clang_sample_profile = "//chrome/android/profiles/afdo.prof" } else { - assert( - chromeos_afdo_platform == "atom" || - chromeos_afdo_platform == "bigcore" || - chromeos_afdo_platform == "arm" || - chromeos_afdo_platform == "arm-exp", - "Only 'atom', 'bigcore', 'arm' and 'arm-exp' are valid ChromeOS profiles.") + assert(chromeos_afdo_platform == "atom" || + chromeos_afdo_platform == "bigcore" || + chromeos_afdo_platform == "arm", + "Only 'atom', 'bigcore', and 'arm' are valid ChromeOS profiles.") _clang_sample_profile = "//chromeos/profiles/${chromeos_afdo_platform}.afdo.prof" } @@ -2775,7 +2811,8 @@ config("symbols") { } # On aix -gdwarf causes linker failures due to thread_local variables. - if (!is_nacl && current_os != "aix") { + # On zos -gdwarf causes INSUFFICIENT ABOVE THE LINE STORAGE WAS AVAILABLE. + if (!is_nacl && current_os != "aix" && current_os != "zos") { if (use_dwarf5) { cflags += [ "-gdwarf-5" ] rustflags += [ "-Zdwarf-version=5" ] @@ -2859,13 +2896,12 @@ config("symbols") { # Compress debug on 32-bit ARM to stay under 4GB file size limit. # https://b/243982712, https://crbug.com/1354616, https://crbug.com/334073642 - if (symbol_level == 2 && !use_debug_fission && !is_nacl && - (is_chromeos_device || is_android) && + if (symbol_level == 2 && !use_debug_fission && !is_nacl && !is_win && (current_cpu == "arm" || current_cpu == "x86")) { configs += [ "//build/config:compress_debug_sections" ] } - if (is_clang && (!is_nacl || is_nacl_saigo) && current_os != "zos") { + if (is_clang && (!is_nacl || is_nacl_saigo)) { if (is_apple) { # TODO(crbug.com/40117949): Investigate missing debug info on mac. # Make sure we don't use constructor homing on mac. @@ -2949,7 +2985,7 @@ config("minimal_symbols") { cflags += [ "-g1" ] } - if (!is_nacl && is_clang && !is_tsan && !is_asan) { + if (!is_nacl && is_clang && !is_tsan && !is_asan && current_os != "zos") { # See comment for -gdwarf-aranges in config("symbols"). cflags += [ "-gdwarf-aranges" ] } diff --git a/naiveproxy/src/build/config/compiler/compiler.gni b/naiveproxy/src/build/config/compiler/compiler.gni index e9acde43a5..8310207e93 100644 --- a/naiveproxy/src/build/config/compiler/compiler.gni +++ b/naiveproxy/src/build/config/compiler/compiler.gni @@ -263,6 +263,17 @@ if (clang_need_input_root_absolute_path) { compiler_logs = [ "clang_need_input_root_absolute_path=false" ] } +# TODO: https://issues.chromium.org/40120210 - remove this +# once we can use relative path in hmap. +clang_need_input_root_absolute_path_for_objc = + clang_need_input_root_absolute_path +if (target_os == "ios") { + # objc/objcxx uses hmap, which contains absolute path + # see also b/256536089 + clang_need_input_root_absolute_path_for_objc = true +} +compiler_logs += [ "clang_need_input_root_absolute_path_for_objc=$clang_need_input_root_absolute_path_for_objc" ] + # If it wasn't manually set, set to an appropriate default. assert(symbol_level >= -1 && symbol_level <= 2, "Invalid symbol_level") if (symbol_level == -1) { diff --git a/naiveproxy/src/build/config/fuchsia/gn_configs.gni b/naiveproxy/src/build/config/fuchsia/gn_configs.gni index b43f1396fe..c233a30235 100644 --- a/naiveproxy/src/build/config/fuchsia/gn_configs.gni +++ b/naiveproxy/src/build/config/fuchsia/gn_configs.gni @@ -9,7 +9,7 @@ declare_args() { # value to specify the API level the packages produced from this repository # should be targeting, e.g. in their top-level //.gn file. A value of -1 # means that no API level will be passed to the tools that consumes it. - fuchsia_target_api_level = 18 + fuchsia_target_api_level = 20 # Path to the fuchsia SDK. This is intended for use in other templates & # rules to reference the contents of the fuchsia SDK. diff --git a/naiveproxy/src/build/config/ios/ios_sdk.gni b/naiveproxy/src/build/config/ios/ios_sdk.gni index ff3e26fc6a..3593dc787c 100644 --- a/naiveproxy/src/build/config/ios/ios_sdk.gni +++ b/naiveproxy/src/build/config/ios/ios_sdk.gni @@ -153,3 +153,6 @@ if (target_environment == "device" && ios_enable_code_signing) { # This variable corresponds to the test bundle identifier. shared_bundle_id_for_test_apps = "$ios_app_bundle_id_prefix.chrome.unittests.dev" + +_sdk_root = rebase_path(ios_sdk_path, root_build_dir) +ios_sdk_logs = [ "ios_sdk_path=${_sdk_root}" ] diff --git a/naiveproxy/src/build/config/mac/mac_sdk.gni b/naiveproxy/src/build/config/mac/mac_sdk.gni index 09902c6335..2be0168abe 100644 --- a/naiveproxy/src/build/config/mac/mac_sdk.gni +++ b/naiveproxy/src/build/config/mac/mac_sdk.gni @@ -141,3 +141,6 @@ if (use_system_xcode) { # TODO(thakis): Do this at the uses of this variable instead. mac_bin_path = rebase_path(mac_bin_path, root_build_dir) } + +_sdk_root = rebase_path(mac_sdk_path, root_build_dir) +mac_sdk_logs = [ "mac_sdk_path=${_sdk_root}" ] diff --git a/naiveproxy/src/build/config/riscv.gni b/naiveproxy/src/build/config/riscv.gni index 595b4611fc..3e8e425339 100644 --- a/naiveproxy/src/build/config/riscv.gni +++ b/naiveproxy/src/build/config/riscv.gni @@ -27,5 +27,9 @@ if (current_cpu == "riscv64" || v8_current_cpu == "riscv64" || riscv_use_zba = false riscv_use_zbb = false riscv_use_zbs = false + + # RISCV Svpbmt Standard Extension for Page-Based Memory Types + # RISCV SV39 compilation flag. + riscv_use_sv39 = false } } diff --git a/naiveproxy/src/build/config/rust.gni b/naiveproxy/src/build/config/rust.gni index 97e788a227..fd4c683442 100644 --- a/naiveproxy/src/build/config/rust.gni +++ b/naiveproxy/src/build/config/rust.gni @@ -29,7 +29,7 @@ declare_args() { # The CXX tool is in //third_party/rust which is not shared with downstream # projects yet. So they need to copy the required dependencies and GN files # into their project to enable CXX there. - enable_cxx = build_with_chromium + enable_rust_cxx = build_with_chromium # The chromium prelude crate provides the `chromium::import!` macro which # is needed to depend on first-party rust libraries. Third-party libraries diff --git a/naiveproxy/src/build/config/sanitizers/BUILD.gn b/naiveproxy/src/build/config/sanitizers/BUILD.gn index 837bfbc6f2..7b9c17af08 100644 --- a/naiveproxy/src/build/config/sanitizers/BUILD.gn +++ b/naiveproxy/src/build/config/sanitizers/BUILD.gn @@ -16,15 +16,20 @@ if (is_ios) { # libfuzzer can't cope with shared objects being unloaded, which sometimes # occurs for large fuzzers that involve our graphics stack. Shim out dlclose -# so that this doesn't occur. At the moment we've only implemented this on Linux -# since that's the only platform we use these large fuzzers - in the future -# we could choose to do the same on Windows. -use_dlcloseshim = use_libfuzzer && is_linux +# so that this doesn't occur. +# +# dlclose() is defined by POSIX, making `is_posix` a tempting condition to use. +# However the linker does not necessarily support `-wrap` on all POSIX +# platforms, hence the restriction to Linux and ChromeOS. We might eventually +# want to disable shared library unloading on all platforms, but we have not +# noticed a need for it as the known-affected large fuzzers only run on Linux. +use_dlcloseshim = use_libfuzzer && (is_linux || is_chromeos) # Contains the dependencies needed for sanitizers to link into executables and # shared_libraries. group("deps") { deps = [] + data = [] if (using_sanitizer) { public_configs = [ # Even when a target removes default_sanitizer_flags, it may be depending @@ -38,7 +43,7 @@ group("deps") { } else { exe = "" } - data = [ + data += [ "//tools/valgrind/asan/", "$clang_base_path/bin/llvm-symbolizer${exe}", ] diff --git a/naiveproxy/src/build/config/sanitizers/sanitizers.gni b/naiveproxy/src/build/config/sanitizers/sanitizers.gni index 0d1c9c5fda..ef2f230fd7 100644 --- a/naiveproxy/src/build/config/sanitizers/sanitizers.gni +++ b/naiveproxy/src/build/config/sanitizers/sanitizers.gni @@ -45,9 +45,6 @@ declare_args() { # TODO(crbug.com/40240570): Default this to true and remove. msan_eager_checks = true - # TODO(crbug.com/40222690): evaluate and possibly enable - msan_check_use_after_dtor = false - # Use dynamic libraries instrumented by one of the sanitizers instead of the # standard system libraries. Set this flag to build the libraries from source. use_locally_built_instrumented_libraries = false @@ -84,6 +81,9 @@ declare_args() { # Compile for fuzzing with AFL. use_afl = false + # Compile for fuzzing with Fuzzilli. + use_fuzzilli = false + # Compile for fuzzing with an external engine (e.g., Grammarinator). use_external_fuzzing_engine = false @@ -117,9 +117,6 @@ declare_args() { # When true, seed corpora archives are built. archive_seed_corpus = true - # When true, sanitizer warnings will cause test case failures. - fail_on_san_warnings = false - # When true, only builds fuzzer targets that require high end machines to run. # Otherwise, builds all the targets. # TODO(paulsemel): once we have everything implemented on the recipe side, we @@ -139,6 +136,12 @@ declare_args() { is_ubsan_vptr = is_ubsan_security } +# Whether we are doing a fuzzer build. Normally this should be checked instead +# of checking "use_libfuzzer || use_afl" because often developers forget to +# check for "use_afl", and "use_centipede" is new. +use_fuzzing_engine = use_libfuzzer || use_afl || use_centipede || + use_external_fuzzing_engine || use_fuzzilli + declare_args() { # Builds fuzztest test executables such that they support the # --fuzz= argument, which requires some sanitizer coverage. @@ -152,7 +155,7 @@ declare_args() { # TODO(crbug.com/40286621): enable on component builds enable_fuzztest_fuzz = !(use_libfuzzer || use_afl || use_centipede || - use_external_fuzzing_engine) && + use_external_fuzzing_engine || use_fuzzilli) && (is_asan || is_hwasan || is_lsan || is_tsan || is_msan || is_ubsan || is_ubsan_vptr || is_ubsan_security) && !is_component_build && is_linux && build_with_chromium @@ -168,6 +171,15 @@ declare_args() { register_fuzztests_in_test_suites = is_linux || is_mac || is_win || use_libfuzzer || use_afl || use_centipede || use_external_fuzzing_engine + + # TODO(crbug.com/40222690): Enable everywhere. + msan_check_use_after_dtor = is_linux && !use_fuzzing_engine +} + +declare_args() { + use_sanitizer_coverage = + !use_clang_coverage && (use_fuzzing_engine || enable_fuzztest_fuzz || + sanitizer_coverage_flags != "") } assert(!is_hwasan || (target_os == "android" && target_cpu == "arm64"), @@ -198,7 +210,6 @@ if (!is_a_target_toolchain || toolchain_for_rust_host_build_tools) { is_ubsan_no_recover = false is_ubsan_security = false is_ubsan_vptr = false - fail_on_san_warnings = false msan_track_origins = 0 sanitizer_coverage_flags = "" use_afl = false @@ -213,37 +224,38 @@ if (!is_a_target_toolchain || toolchain_for_rust_host_build_tools) { is_hwasan = false } +# Whether we are linking against a sanitizer runtime library. Among other +# things, this changes the default symbol level and other settings in order to +# prepare to create stack traces "live" using the sanitizer runtime. +using_sanitizer = + is_asan || is_hwasan || is_lsan || is_tsan || is_msan || is_ubsan || + is_ubsan_vptr || is_ubsan_security || use_sanitizer_coverage || use_cfi_diag + # Use dynamic libraries instrumented by one of the sanitizers instead of the # standard system libraries. We have instrumented system libraries for msan, # which requires them to prevent false positives. # TODO(thakis): Maybe remove this variable. use_prebuilt_instrumented_libraries = is_msan -# Whether we are doing a fuzzer build. Normally this should be checked instead -# of checking "use_libfuzzer || use_afl" because often developers forget to -# check for "use_afl", and "use_centipede" is new. -use_fuzzing_engine = - use_libfuzzer || use_afl || use_centipede || use_external_fuzzing_engine - # Whether the current fuzzing engine supports libprotobuf_mutator. use_fuzzing_engine_with_lpm = use_libfuzzer || use_centipede # Whether the fuzzing engine supports fuzzers which supply their own # "main" function. -fuzzing_engine_supports_custom_main = use_libfuzzer || use_centipede +fuzzing_engine_supports_custom_main = + use_libfuzzer || use_centipede || use_fuzzilli # Args that are in turn dependent on other args must be in a separate # declare_args block. User overrides are only applied at the end of a # declare_args block. declare_args() { + # When true, sanitizer warnings will cause test case failures. + fail_on_san_warnings = using_sanitizer + # Generates an owners file for each fuzzer test. # TODO(crbug.com/40175535): Remove this arg when finding OWNERS is faster. generate_fuzzer_owners = use_fuzzing_engine - use_sanitizer_coverage = - !use_clang_coverage && (use_fuzzing_engine || enable_fuzztest_fuzz || - sanitizer_coverage_flags != "") - # https://crbug.com/1002058: Code coverage works inside the sandbox via the # help of several helper IPCs. Unfortunately, the sandbox-only path does not # work well for fuzzing builds. Since fuzzing builds already disable the @@ -277,13 +289,6 @@ if (sanitizer_coverage_flags == "") { } } -# Whether we are linking against a sanitizer runtime library. Among other -# things, this changes the default symbol level and other settings in order to -# prepare to create stack traces "live" using the sanitizer runtime. -using_sanitizer = - is_asan || is_hwasan || is_lsan || is_tsan || is_msan || is_ubsan || - is_ubsan_vptr || is_ubsan_security || use_sanitizer_coverage || use_cfi_diag - assert(!using_sanitizer || is_clang, "Sanitizers (is_*san) require setting is_clang = true in 'gn args'") diff --git a/naiveproxy/src/build/config/siso/PRESUBMIT.py b/naiveproxy/src/build/config/siso/PRESUBMIT.py index 7a48f084ff..327541be4a 100644 --- a/naiveproxy/src/build/config/siso/PRESUBMIT.py +++ b/naiveproxy/src/build/config/siso/PRESUBMIT.py @@ -14,6 +14,8 @@ def CheckSisoConfigFormat(input_api, output_api): filepath = f.AbsoluteLocalPath() if not filepath.endswith('.star'): continue + if not input_api.os_path.isfile(filepath): + continue name = 'Validate ' + filepath cmd = ['lucicfg', 'fmt', '-dry-run', '-log-level', log_level, filepath] commands.append(input_api.Command(name, cmd, {}, output_api.PresubmitError)) diff --git a/naiveproxy/src/build/config/siso/clang_code_coverage_wrapper.star b/naiveproxy/src/build/config/siso/clang_code_coverage_wrapper.star index a354d354a5..9a8516b586 100644 --- a/naiveproxy/src/build/config/siso/clang_code_coverage_wrapper.star +++ b/naiveproxy/src/build/config/siso/clang_code_coverage_wrapper.star @@ -41,7 +41,6 @@ _COVERAGE_EXCLUSION_LIST_MAP = { "fuchsia": [ # TODO(crbug.com/40167659): These files caused clang to crash while # compiling them. - "../../base/allocator/partition_allocator/src/partition_alloc/pcscan.cc", "../../third_party/skia/src/core/SkOpts.cpp", "../../third_party/skia/src/opts/SkOpts_hsw.cpp", "../../third_party/skia/third_party/skcms/skcms.cc", diff --git a/naiveproxy/src/build/config/siso/clang_linux.star b/naiveproxy/src/build/config/siso/clang_linux.star index 2b3b29065b..e2ef8d788d 100644 --- a/naiveproxy/src/build/config/siso/clang_linux.star +++ b/naiveproxy/src/build/config/siso/clang_linux.star @@ -11,6 +11,7 @@ load("./clang_all.star", "clang_all") load("./clang_code_coverage_wrapper.star", "clang_code_coverage_wrapper") load("./config.star", "config") load("./cros.star", "cros") +load("./gn_logs.star", "gn_logs") # TODO: b/323091468 - Propagate target android ABI and android SDK version # from GN, and remove the hardcoded filegroups. @@ -125,6 +126,9 @@ def __step_config(ctx, step_config): }) step_config["input_deps"].update(clang_all.input_deps) + input_root_absolute_path = gn_logs.read(ctx).get("clang_need_input_root_absolute_path") == "true" + canonicalize_dir = not input_root_absolute_path + step_config["rules"].extend([ { "name": "clang/cxx", @@ -135,7 +139,8 @@ def __step_config(ctx, step_config): ], "exclude_input_patterns": ["*.stamp"], "remote": True, - "canonicalize_dir": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "timeout": "2m", }, { @@ -147,7 +152,8 @@ def __step_config(ctx, step_config): ], "exclude_input_patterns": ["*.stamp"], "remote": True, - "canonicalize_dir": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "timeout": "2m", }, { @@ -158,7 +164,8 @@ def __step_config(ctx, step_config): "third_party/llvm-build/Release+Asserts/bin/clang", ], "remote": config.get(ctx, "cog"), - "canonicalize_dir": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "timeout": "2m", }, { @@ -171,7 +178,8 @@ def __step_config(ctx, step_config): "exclude_input_patterns": ["*.stamp"], "handler": "clang_compile_coverage", "remote": True, - "canonicalize_dir": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "timeout": "2m", }, { @@ -184,7 +192,8 @@ def __step_config(ctx, step_config): "exclude_input_patterns": ["*.stamp"], "handler": "clang_compile_coverage", "remote": True, - "canonicalize_dir": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "timeout": "2m", }, ]) diff --git a/naiveproxy/src/build/config/siso/clang_mac.star b/naiveproxy/src/build/config/siso/clang_mac.star index 59afe8006e..4df4959af0 100644 --- a/naiveproxy/src/build/config/siso/clang_mac.star +++ b/naiveproxy/src/build/config/siso/clang_mac.star @@ -10,6 +10,7 @@ load("@builtin//struct.star", "module") load("./clang_all.star", "clang_all") load("./clang_code_coverage_wrapper.star", "clang_code_coverage_wrapper") load("./config.star", "config") +load("./gn_logs.star", "gn_logs") load("./rewrapper_cfg.star", "rewrapper_cfg") def __filegroups(ctx): @@ -33,39 +34,25 @@ def __filegroups(ctx): }, } - # precompute subtree for sysroot/frameworks for siso scandeps, - # which is not complex enough to handle C preprocessor tricks - # and need system include dirs when using deps log of -MMD. - # need to add new entries when new version is used. - # TODO: b/323091468 - get sysroot, ios_sdk_path from gn - fg[ctx.fs.canonpath("./sdk/xcode_links/MacOSX14.2.sdk") + ":headers"] = { - "type": "glob", - "includes": sdk_includes, - } - fg[ctx.fs.canonpath("./sdk/xcode_links/iPhoneSimulator17.2.sdk") + ":headers"] = { - "type": "glob", - "includes": sdk_includes, - } - - # https://b.corp.google.com/issues/332652041#comment2 - fg[ctx.fs.canonpath("./sdk/xcode_links/MacOSX14.4.sdk") + ":headers"] = { - "type": "glob", - "includes": sdk_includes, - } - fg[ctx.fs.canonpath("./sdk/xcode_links/iPhoneSimulator17.4.sdk") + ":headers"] = { - "type": "glob", - "includes": sdk_includes, - } - - # https://chromium-review.googlesource.com/c/chromium/src/+/5568662 - fg[ctx.fs.canonpath("./sdk/xcode_links/MacOSX14.5.sdk") + ":headers"] = { - "type": "glob", - "includes": sdk_includes, - } - fg[ctx.fs.canonpath("./sdk/xcode_links/iPhoneSimulator17.5.sdk") + ":headers"] = { - "type": "glob", - "includes": sdk_includes, - } + if gn.args(ctx).get("use_remoteexec") == "true": + # precompute subtree for sysroot/frameworks for siso scandeps, + # which is not complex enough to handle C preprocessor tricks + # and need system include dirs when using deps log of -MMD. + # need to add new entries when new version is used. + # + # if use_remoteexec is not true, these dirs are not under exec root + # and failed to create filegroup for such dirs. crbug.com/352216756 + gn_logs_data = gn_logs.read(ctx) + if gn_logs_data.get("mac_sdk_path"): + fg[ctx.fs.canonpath("./" + gn_logs_data.get("mac_sdk_path")) + ":headers"] = { + "type": "glob", + "includes": sdk_includes, + } + if gn_logs_data.get("ios_sdk_path"): + fg[ctx.fs.canonpath("./" + gn_logs_data.get("ios_sdk_path")) + ":headers"] = { + "type": "glob", + "includes": sdk_includes, + } fg[ctx.fs.canonpath("./sdk/xcode_links/iPhoneSimulator.platform/Developer/Library/Frameworks") + ":headers"] = { "type": "glob", @@ -98,14 +85,12 @@ def __step_config(ctx, step_config): }) step_config["input_deps"].update(clang_all.input_deps) - # TODO: https://issues.chromium.org/40120210 - remove this - # once we can use relative path in hmap. - need_input_root_absolute_path_for_objc = False - gn_args = gn.args(ctx) - if gn_args.get("target_os") == "\"ios\"": - # objc/objcxx uses hmap, which contains absolute path - # see also b/256536089 - need_input_root_absolute_path_for_objc = True + gn_logs_data = gn_logs.read(ctx) + input_root_absolute_path = gn_logs_data.get("clang_need_input_root_absolute_path") == "true" + input_root_absolute_path_for_objc = gn_logs_data.get("clang_need_input_root_absolute_path_for_objc") == "true" + + canonicalize_dir = not input_root_absolute_path + canonicalize_dir_for_objc = not input_root_absolute_path_for_objc step_config["rules"].extend([ { @@ -118,6 +103,8 @@ def __step_config(ctx, step_config): "exclude_input_patterns": ["*.stamp"], "platform_ref": "clang", "remote": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "remote_wrapper": reproxy_config["remote_wrapper"], "timeout": "2m", }, @@ -131,6 +118,8 @@ def __step_config(ctx, step_config): "exclude_input_patterns": ["*.stamp"], "platform_ref": "clang", "remote": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "remote_wrapper": reproxy_config["remote_wrapper"], "timeout": "2m", }, @@ -146,7 +135,8 @@ def __step_config(ctx, step_config): "remote": True, "remote_wrapper": reproxy_config["remote_wrapper"], "timeout": "2m", - "input_root_absolute_path": need_input_root_absolute_path_for_objc, + "input_root_absolute_path": input_root_absolute_path_for_objc, + "canonicalize_dir": canonicalize_dir_for_objc, }, { "name": "clang/objc", @@ -160,7 +150,8 @@ def __step_config(ctx, step_config): "remote": True, "remote_wrapper": reproxy_config["remote_wrapper"], "timeout": "2m", - "input_root_absolute_path": need_input_root_absolute_path_for_objc, + "input_root_absolute_path": input_root_absolute_path_for_objc, + "canonicalize_dir": canonicalize_dir_for_objc, }, { "name": "clang-coverage/cxx", @@ -173,6 +164,8 @@ def __step_config(ctx, step_config): "handler": "clang_compile_coverage", "platform_ref": "clang", "remote": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "remote_wrapper": reproxy_config["remote_wrapper"], "timeout": "2m", }, @@ -187,6 +180,8 @@ def __step_config(ctx, step_config): "handler": "clang_compile_coverage", "platform_ref": "clang", "remote": True, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "remote_wrapper": reproxy_config["remote_wrapper"], "timeout": "2m", }, @@ -203,7 +198,8 @@ def __step_config(ctx, step_config): "remote": True, "remote_wrapper": reproxy_config["remote_wrapper"], "timeout": "2m", - "input_root_absolute_path": need_input_root_absolute_path_for_objc, + "input_root_absolute_path": input_root_absolute_path_for_objc, + "canonicalize_dir": canonicalize_dir_for_objc, }, { "name": "clang-coverage/objc", @@ -218,7 +214,8 @@ def __step_config(ctx, step_config): "remote": True, "remote_wrapper": reproxy_config["remote_wrapper"], "timeout": "2m", - "input_root_absolute_path": need_input_root_absolute_path_for_objc, + "input_root_absolute_path": input_root_absolute_path_for_objc, + "canonicalize_dir": canonicalize_dir_for_objc, }, ]) return step_config diff --git a/naiveproxy/src/build/config/siso/clang_windows.star b/naiveproxy/src/build/config/siso/clang_windows.star index 49c561ceb2..c2eab193bb 100644 --- a/naiveproxy/src/build/config/siso/clang_windows.star +++ b/naiveproxy/src/build/config/siso/clang_windows.star @@ -10,6 +10,7 @@ load("@builtin//struct.star", "module") load("./clang_all.star", "clang_all") load("./clang_code_coverage_wrapper.star", "clang_code_coverage_wrapper") load("./config.star", "config") +load("./gn_logs.star", "gn_logs") load("./rewrapper_cfg.star", "rewrapper_cfg") def __win_toolchain_dir(ctx): @@ -242,6 +243,9 @@ def __step_config(ctx, step_config): ], }) remote_wrapper = reproxy_config.get("remote_wrapper") + input_root_absolute_path = gn_logs.read(ctx).get("clang_need_input_root_absolute_path") == "true" + canonicalize_dir = not input_root_absolute_path + step_config["rules"].extend([ { "name": "clang-cl/cxx", @@ -253,6 +257,8 @@ def __step_config(ctx, step_config): "exclude_input_patterns": ["*.stamp"], "platform_ref": "clang-cl", "remote": remote, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "remote_wrapper": remote_wrapper, "timeout": "2m", }, @@ -266,6 +272,8 @@ def __step_config(ctx, step_config): "exclude_input_patterns": ["*.stamp"], "platform_ref": "clang-cl", "remote": remote, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "remote_wrapper": remote_wrapper, "timeout": "2m", }, @@ -280,6 +288,8 @@ def __step_config(ctx, step_config): "handler": "clang_compile_coverage", "platform_ref": "clang-cl", "remote": remote, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "remote_wrapper": remote_wrapper, "timeout": "2m", }, @@ -294,6 +304,8 @@ def __step_config(ctx, step_config): "handler": "clang_compile_coverage", "platform_ref": "clang-cl", "remote": remote, + "input_root_absolute_path": input_root_absolute_path, + "canonicalize_dir": canonicalize_dir, "remote_wrapper": remote_wrapper, "timeout": "2m", }, diff --git a/naiveproxy/src/build/config/siso/gn_logs.star b/naiveproxy/src/build/config/siso/gn_logs.star new file mode 100644 index 0000000000..c1dd10f405 --- /dev/null +++ b/naiveproxy/src/build/config/siso/gn_logs.star @@ -0,0 +1,27 @@ +# -*- bazel-starlark -*- +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""gn_logs module to access gn_logs data.""" + +load("@builtin//struct.star", "module") + +def __read(ctx): + fname = ctx.fs.canonpath("./gn_logs.txt") + if not ctx.fs.exists(fname): + return {} + gn_logs = ctx.fs.read(fname) + vars = {} + for line in str(gn_logs).splitlines(): + if line.startswith("#"): + continue + if not "=" in line: + continue + kv = line.split("=", 1) + vars[kv[0].strip()] = kv[1].strip() + return vars + +gn_logs = module( + "gn_logs", + read = __read, +) diff --git a/naiveproxy/src/build/config/siso/mac.star b/naiveproxy/src/build/config/siso/mac.star index e50b3acf86..86b31c6387 100644 --- a/naiveproxy/src/build/config/siso/mac.star +++ b/naiveproxy/src/build/config/siso/mac.star @@ -15,29 +15,12 @@ def __filegroups(ctx): fg.update(typescript.filegroups(ctx)) return fg -# to reduce unnecessary local process and -# unnecessary digest calculation of output file. -def __copy_bundle_data(ctx, cmd): - input = cmd.inputs[0] - out = cmd.outputs[0] - ctx.actions.copy(input, out, recursive = ctx.fs.is_dir(input)) - ctx.actions.exit(exit_status = 0) - -__handlers = { - "copy_bundle_data": __copy_bundle_data, -} +__handlers = {} __handlers.update(clang.handlers) __handlers.update(typescript.handlers) def __step_config(ctx, step_config): config.check(ctx) - step_config["rules"].extend([ - { - "name": "mac/copy_bundle_data", - "action": "(.*)?copy_bundle_data", - "handler": "copy_bundle_data", - }, - ]) step_config = clang.step_config(ctx, step_config) step_config = typescript.step_config(ctx, step_config) return step_config diff --git a/naiveproxy/src/build/config/siso/main.star b/naiveproxy/src/build/config/siso/main.star index 1f35441051..d628586ef1 100644 --- a/naiveproxy/src/build/config/siso/main.star +++ b/naiveproxy/src/build/config/siso/main.star @@ -9,6 +9,7 @@ load("@builtin//lib/gn.star", "gn") load("@builtin//runtime.star", "runtime") load("@builtin//struct.star", "module") load("./blink_all.star", "blink_all") +load("./gn_logs.star", "gn_logs") load("./linux.star", chromium_linux = "chromium") load("./mac.star", chromium_mac = "chromium") load("./mojo.star", "mojo") @@ -17,304 +18,6 @@ load("./reproxy.star", "reproxy") load("./simple.star", "simple") load("./windows.star", chromium_windows = "chromium") -def __use_large_b289968566(ctx, step_config): - # TODO(b/289968566): they often faile with exit=137 (OOM?). - # They need to run on a machine has more memory than the default machine type n2-custom-2-3840 - exit137_list = [ - # Fallback happens with follwoing args.gn (try/linux-chromeos-rel-compilator). - # Fallback may happen in other build config too. - # also_build_lacros_chrome = true - # dcheck_always_on = true - # enable_backup_ref_ptr_feature_flag = true - # enable_dangling_raw_ptr_checks = true - # enable_dangling_raw_ptr_feature_flag = true - # ffmpeg_branding = "ChromeOS" - # is_component_build = false - # is_debug = false - # proprietary_codecs = true - # symbol_level = 0 - # target_os = "chromeos" - # use_cups = true - # use_remoteexec = true - "./lacros_clang_x64/obj/chrome/browser/browser/chrome_browser_interface_binders.o", - "./lacros_clang_x64/obj/chrome/browser/browser/chrome_content_browser_client.o", - "./lacros_clang_x64/obj/content/browser/browser/browser_interface_binders.o", - "./lacros_clang_x64/obj/content/browser/browser/render_frame_host_impl.o", - "./lacros_clang_x64/obj/content/browser/browser/web_contents_impl.o", - "./lacros_clang_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", - "./lacros_clang_x64/obj/third_party/blink/public/mojom/mojom_platform/speech_recognition_grammar.mojom.o", - "./obj/chrome/browser/ash/ash/autotest_private_api.o", - "./obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o", - "./obj/chrome/browser/ash/ash/user_session_manager.o", - "./obj/chrome/browser/ash/ash/webui_login_view.o", - "./obj/chrome/browser/ash/system_web_apps/apps/browser_tests/media_app_integration_browsertest.o", - "./obj/chrome/browser/ash/system_web_apps/browser_tests/system_web_app_manager_browsertest.o", - "./obj/chrome/browser/ash/unit_tests/wizard_controller_unittest.o", - "./obj/chrome/browser/browser/browser_prefs.o", - "./obj/chrome/browser/browser/chrome_browser_interface_binders.o", - "./obj/chrome/browser/browser/chrome_browser_main_extra_parts_profiles.o", - "./obj/chrome/browser/browser/chrome_content_browser_client.o", - "./obj/chrome/browser/browser/render_view_context_menu.o", - "./obj/chrome/browser/ui/ash/holding_space/browser_tests/holding_space_ui_browsertest.o", - "./obj/chrome/test/browser_tests/browser_non_client_frame_view_chromeos_browsertest.o", - "./obj/chrome/test/browser_tests/chrome_shelf_controller_browsertest.o", - "./obj/chrome/test/browser_tests/device_local_account_browsertest.o", - "./obj/chrome/test/browser_tests/file_manager_browsertest_base.o", - "./obj/chrome/test/browser_tests/file_tasks_browsertest.o", - "./obj/chrome/test/browser_tests/full_restore_app_launch_handler_browsertest.o", - "./obj/chrome/test/browser_tests/safe_browsing_blocking_page_test.o", - "./obj/chrome/test/browser_tests/scalable_iph_browsertest.o", - "./obj/chrome/test/interactive_ui_tests/local_card_migration_uitest.o", - "./obj/chrome/test/interactive_ui_tests/system_web_app_interactive_uitest.o", - "./obj/chrome/test/interactive_ui_tests/tab_drag_controller_interactive_uitest.o", - "./obj/chrome/test/test_support_ui/web_app_integration_test_driver.o", - "./obj/chrome/test/unit_tests/chrome_browsing_data_remover_delegate_unittest.o", - "./obj/chrome/test/unit_tests/chrome_compose_client_unittest.o", - "./obj/chrome/test/unit_tests/chrome_shelf_controller_unittest.o", - "./obj/chrome/test/unit_tests/render_view_context_menu_unittest.o", - "./obj/content/browser/browser/browser_interface_binders.o", - - # Fallback happens with follwoing args.gn (try/linux-lacros-rel-compilator). - # Fallback may happen in other build config too. - # also_build_ash_chrome = true - # chromeos_is_browser_only = true - # dcheck_always_on = true - # is_clang = true - # is_component_build = false - # is_debug = false - # symbol_level = 0 - # target_os = "chromeos" - # use_cups = true - # use_remoteexec = true - "./ash_clang_x64/obj/chrome/browser/ash/ash/autotest_private_api.o", - "./ash_clang_x64/obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o", - "./ash_clang_x64/obj/chrome/browser/browser/browser_prefs.o", - "./ash_clang_x64/obj/chrome/browser/browser/chrome_browser_interface_binders.o", - "./ash_clang_x64/obj/chrome/browser/browser/chrome_content_browser_client.o", - "./ash_clang_x64/obj/content/browser/browser/browser_interface_binders.o", - - # Fallback happens with follwoing args.gn (try/android_compile_dbg). - # Fallback may happen in other build config too. - # debuggable_apks = false - # ffmpeg_branding = "Chrome" - # is_component_build = true - # is_debug = true - # proprietary_codecs = true - # symbol_level = 0 - # target_cpu = "arm64" - # target_os = "android" - # use_remoteexec = true - "./android_clang_arm/obj/content/browser/browser/browser_interface_binders.o", - "./obj/chrome/test/unit_tests__library/chrome_browsing_data_remover_delegate_unittest.o", - "./obj/content/test/content_browsertests__library/fenced_frame_browsertest.o", - "./obj/content/test/content_unittests__library/ad_auction_service_impl_unittest.o", - "./obj/content/test/content_unittests__library/auction_runner_unittest.o", - # Fallback happens with follwoing args.gn (try/fuchsia-x64-cast-receiver-rel). - # Fallback may happen in other build config too. - # cast_streaming_enable_remoting = true - # chrome_pgo_phase = 0 - # dcheck_always_on = true - # enable_cast_receiver = true - # enable_dav1d_decoder = false - # enable_hidpi = false - # enable_libaom = false - # enable_library_cdms = false - # enable_logging_override = true - # enable_pdf = false - # enable_plugins = false - # enable_printing = false - # fuchsia_code_coverage = true - # is_component_build = false - # is_debug = false - # optimize_for_size = true - # optional_trace_events_enabled = false - # produce_v8_compile_hints = false - # symbol_level = 0 - # target_os = "fuchsia" - # use_remoteexec = true - # use_thin_lto = false - "./obj/fuchsia_web/runners/cast_runner_integration_tests__exec/cast_runner_integration_test.o", - "./obj/fuchsia_web/webengine/web_engine_core/frame_impl.o", - - # Fallback happens with follwoing args.gn (try/linux_chromium_asan_rel_ng). - # dcheck_always_on = true - # fail_on_san_warnings = true - # is_asan = true - # is_component_build = false - # is_debug = false - # is_lsan = true - # symbol_level = 1 - # use_remoteexec = true - "./obj/components/autofill/core/browser/unit_tests/browser_autofill_manager_unittest.o", - "./obj/content/browser/browser/render_frame_host_impl.o", - "./obj/content/browser/browser/web_contents_impl.o", - "./obj/content/test/content_browsertests/back_forward_cache_features_browsertest.o", - "./obj/content/test/content_browsertests/back_forward_cache_internal_browsertest.o", - "./obj/content/test/content_browsertests/fenced_frame_browsertest.o", - "./obj/content/test/content_browsertests/interest_group_browsertest.o", - "./obj/content/test/content_browsertests/navigation_controller_impl_browsertest.o", - "./obj/content/test/content_browsertests/navigation_request_browsertest.o", - "./obj/content/test/content_browsertests/prerender_browsertest.o", - "./obj/content/test/content_browsertests/render_frame_host_impl_browsertest.o", - "./obj/content/test/content_browsertests/shared_storage_browsertest.o", - "./obj/content/test/content_browsertests/site_per_process_browsertest.o", - "./obj/content/test/content_browsertests/web_contents_impl_browsertest.o", - "./obj/content/test/content_unittests/ad_auction_service_impl_unittest.o", - "./obj/content/test/content_unittests/auction_runner_unittest.o", - "./obj/content/test/content_unittests/authenticator_impl_unittest.o", - "./obj/content/test/content_unittests/web_usb_service_impl_unittest.o", - "./obj/net/third_party/quiche/quiche_tests/quic_connection_test.o", - "./obj/third_party/abseil-cpp/absl/functional/any_invocable_test/any_invocable_test.o", - "./obj/third_party/blink/renderer/core/unit_tests/web_frame_test.o", - "./obj/third_party/blink/renderer/core/unit_tests/web_media_player_impl_unittest.o", - "./obj/third_party/perfetto/protos/perfetto/trace/merged_trace_lite/perfetto_trace.pb.o", - "./obj/ui/gl/gl_unittest_utils/gl_bindings_autogen_mock.o", - - # Fallback happens with follwoing args.gn (ci/Linux MSan Builder). - # dcheck_always_on = false - # is_component_build = false - # is_debug = false - # is_msan = true - # msan_track_origins = 2 - # use_remoteexec = true - "./obj/chrome/test/unit_tests/site_settings_handler_unittest.o", - "./obj/components/policy/chrome_settings_proto_generated_compile_proto/chrome_settings.pb.o", - "./obj/content/test/content_browsertests/cross_origin_opener_policy_browsertest.o", - "./obj/content/test/content_browsertests/navigation_controller_impl_browsertest.o", - "./obj/content/test/content_unittests/auction_runner_unittest.o", - "./obj/content/test/test_support/service_worker_test_utils.o", - "./obj/net/dns/tests/host_resolver_manager_unittest.o", - "./obj/net/third_party/quiche/quiche_tests/oghttp2_adapter_test.o", - "./obj/net/third_party/quiche/quiche_tests/quic_connection_test.o", - "./obj/net/third_party/quiche/quiche_tests/structured_headers_generated_test.o", - "./obj/ui/accessibility/accessibility_unittests/ax_node_position_unittest.o", - "./obj/ui/gl/gl_unittest_utils/gl_bindings_autogen_mock.o", - "./obj/ui/gl/gl_unittest_utils/gl_mock.o", - "./obj/v8/v8_turboshaft/csa-optimize-phase.o", - # Fallback happens with following args.gn (try/android-arm64-rel) - # android_static_analysis = "off" - # coverage_instrumentation_input_file = "//.code-coverage/files_to_instrument.txt" - # dcheck_always_on = true - # debuggable_apks = false - # fail_on_android_expectations = true - # ffmpeg_branding = "Chrome" - # is_component_build = false - # is_debug = false - # proprietary_codecs = true - # skip_secondary_abi_for_cq = true - # strip_debug_info = true - # symbol_level = 0 - # system_webview_package_name = "com.google.android.apps.chrome" - # target_cpu = "arm64" - # target_os = "android" - # use_clang_coverage = true - # use_remoteexec = false - # use_siso = true - "./obj/content/test/content_browsertests__library/interest_group_browsertest.o", - "./obj/content/test/content_browsertests__library/prerender_browsertest.o", - "./robolectric_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", - # Fallback happens with the following args.gn - # (linux-build-perf-developer, win-build-perf-developer) - # is_component_build = true - # is_debug = true - # symbol_level = 2 - # use_siso = true - "./clang_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", - "./obj/content/browser/browser/render_process_host_impl.o", - "./obj/net/http/transport_security_state_generated_files/transport_security_state.o", - # Fallback happens with the following args.gn - # (try/mac-rel) - # coverage_instrumentation_input_file = "//.code-coverage/files_to_instrument.txt" - # dcheck_always_on = true - # enable_backup_ref_ptr_feature_flag = true - # enable_dangling_raw_ptr_checks = true - # enable_dangling_raw_ptr_feature_flag = true - # ffmpeg_branding = "Chrome" - # is_component_build = false - # is_debug = false - # proprietary_codecs = true - # symbol_level = 0 - # target_cpu = "x64" - # use_clang_coverage = true - # use_remoteexec = false - # use_siso = true - "./arm64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", - "./arm64_v8_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", - "./clang_arm64_v8_x64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", - # Fallback happens with the following args.gn - # (try/ios-simulator) - # coverage_instrumentation_input_file = "//.code-coverage/files_to_instrument.txt" - # enable_run_ios_unittests_with_xctest = true - # is_component_build = false - # is_debug = true - # symbol_level = 1 - # target_cpu = "x64" - # target_environment = "simulator" - # target_os = "ios" - # use_clang_coverage = true - # use_remoteexec = false - # use_siso = true - "./clang_arm64/obj/net/http/transport_security_state_generated_files/transport_security_state.o", - # Fallback happens with the following args.gn - # (mac-build-perf-developer, win-build-perf-developer) - # is_component_build = true - # is_debug = true - # symbol_level = 2 - # use_siso = true - "./obj/content/browser/browser/storage_partition_impl.o", - "./obj/third_party/blink/renderer/core/core/local_frame_view.o", - "./obj/third_party/blink/renderer/core/core_hot/document.o", - # Fallback happens with the following args.gn - # (android-build-perf-developer) - # is_component_build = true - # is_debug = true - # symbol_level = 2 - # target_cpu = "arm64" - # target_os = "android" - # use_siso = true - "./obj/third_party/sentencepiece/sentencepiece/unicode_script.o", - ] - if runtime.os == "windows": - exit137_list = [obj.removesuffix(".o") + ".obj" for obj in exit137_list if obj.startswith("./obj/")] - - # Fallback happens with the following args.gn - # (win-build-perf-developer) - # is_component_build = true - # is_debug = true - # symbol_level = 2 - # use_siso = true - exit137_list.extend([ - "./obj/third_party/blink/renderer/core/core/local_frame.obj", - ]) - - new_rules = [] - for rule in step_config["rules"]: - if not rule["name"].endswith("/cxx"): - new_rules.append(rule) - continue - if "action_outs" in rule: - fail("unexpeced \"action_outs\" in cxx rule %s" % rule["name"]) - r = {} - r.update(rule) - r["name"] += "/b289968566/exit-137" - r["action_outs"] = exit137_list - - # Some large compile take longer than the default timeout 2m. - r["timeout"] = "4m" - - # use `_large` variant of platform if it doesn't use default platform, - # i.e. mac/win case. - if "platform_ref" in r: - r["platform_ref"] = r["platform_ref"] + "_large" - else: - r["platform_ref"] = "large" - if r.get("handler") == "rewrite_rewrapper": - r["handler"] = "rewrite_rewrapper_large" - new_rules.append(r) - new_rules.append(rule) - step_config["rules"] = new_rules - return step_config - def __disable_remote(ctx, step_config): if gn.args(ctx).get("use_remoteexec") == "true": return step_config @@ -333,7 +36,13 @@ def init(ctx): "darwin": chromium_mac, "windows": chromium_windows, }[runtime.os] + properties = {} + for k, v in gn.args(ctx).items(): + properties["gn_args:" + k] = v + for k, v in gn_logs.read(ctx).items(): + properties["gn_logs:" + k] = v step_config = { + "properties": properties, "platforms": { "default": { "OSFamily": "Linux", @@ -382,7 +91,6 @@ def init(ctx): arg0 = arg0.removesuffix(".exe") rule["remote_command"] = arg0 - step_config = __use_large_b289968566(ctx, step_config) step_config = __disable_remote(ctx, step_config) filegroups = {} diff --git a/naiveproxy/src/build/config/siso/mojo.star b/naiveproxy/src/build/config/siso/mojo.star index f42b5dcb4f..cda3b86249 100644 --- a/naiveproxy/src/build/config/siso/mojo.star +++ b/naiveproxy/src/build/config/siso/mojo.star @@ -88,6 +88,7 @@ def __step_config(ctx, step_config): "command_prefix": platform.python_bin + " ../../mojo/public/tools/bindings/validate_typemap_config.py", "remote": True, "canonicalize_dir": True, + "timeout": "2m", "output_local": True, "platform_ref": platform_ref, }, diff --git a/naiveproxy/src/build/config/siso/simple.star b/naiveproxy/src/build/config/siso/simple.star index 5cf4177ea5..3e280af24e 100644 --- a/naiveproxy/src/build/config/siso/simple.star +++ b/naiveproxy/src/build/config/siso/simple.star @@ -15,6 +15,14 @@ def __copy(ctx, cmd): ctx.actions.copy(input, out, recursive = ctx.fs.is_dir(input)) ctx.actions.exit(exit_status = 0) +# to reduce unnecessary local process and +# unnecessary digest calculation of output file. +def __copy_bundle_data(ctx, cmd): + input = cmd.inputs[0] + out = cmd.outputs[0] + ctx.actions.copy(input, out, recursive = ctx.fs.is_dir(input)) + ctx.actions.exit(exit_status = 0) + def __stamp(ctx, cmd): if len(cmd.outputs) > 1: # run touch command as is? @@ -33,6 +41,7 @@ def __stamp(ctx, cmd): __handlers = { "copy": __copy, + "copy_bundle_data": __copy_bundle_data, "stamp": __stamp, } @@ -43,6 +52,11 @@ def __step_config(ctx, step_config): "action": "(.*_)?copy", "handler": "copy", }, + { + "name": "simple/copy_bundle_data", + "action": "(.*)?copy_bundle_data", + "handler": "copy_bundle_data", + }, { "name": "simple/stamp", "action": "(.*_)?stamp", diff --git a/naiveproxy/src/build/config/siso/typescript_unix.star b/naiveproxy/src/build/config/siso/typescript_unix.star index 2fc61fccc4..f093fe929d 100644 --- a/naiveproxy/src/build/config/siso/typescript_unix.star +++ b/naiveproxy/src/build/config/siso/typescript_unix.star @@ -11,11 +11,9 @@ def __step_config(ctx, step_config): remote_run = True step_config["input_deps"].update(typescript_all.input_deps) - use_input_root_absolute_path = False - if gn.args(ctx).get("use_javascript_coverage") == "true": - # crbug.com/345528247: The mismatch of checkout paths between the bot - # and remote workers breaks js coverage builds. - use_input_root_absolute_path = True + # crbug.com/345528247 - use_javascript_coverage + # b/348104171: absolute path used in //ash/webui/recorder_app_ui/resources:build_ts? + use_input_root_absolute_path = True # TODO: crbug.com/1478909 - Specify typescript inputs in GN config. step_config["input_deps"].update({ diff --git a/naiveproxy/src/build/config/unsafe_buffers_paths.txt b/naiveproxy/src/build/config/unsafe_buffers_paths.txt index 01599dcb61..253512ab88 100644 --- a/naiveproxy/src/build/config/unsafe_buffers_paths.txt +++ b/naiveproxy/src/build/config/unsafe_buffers_paths.txt @@ -60,19 +60,59 @@ -buildtools/ -cc/ -chrome/ ++chrome/browser/apps/guest_view/ ++chrome/browser/autofill/ ++chrome/browser/extensions/api/web_view/ ++chrome/browser/guest_view/ ++chrome/browser/history_clusters/ ++chrome/browser/history_embeddings/ ++chrome/browser/manta/ ++chrome/browser/model_execution/ ++chrome/browser/navigation_predictor/ ++chrome/browser/page_image_service/ ++chrome/browser/performance_manager/ ++chrome/browser/preloading/ ++chrome/browser/ui/autofill/ ++chrome/browser/ui/views/autofill/ ++chrome/browser/ui/webui/history_clusters/ ++chrome/browser/win/ -chromecast/ -chromeos/ -clank/ -codelabs/ -components/ -+components/discardable_memory ++components/autofill/ ++components/compose/ ++components/discardable_memory/ ++components/guest_view/ ++components/history_clusters/ ++components/history_embeddings/ ++components/manta/ ++components/optimization_guide/content/ ++components/optimization_guide/core/ ++components/optimization_guide/internal/testdata/ ++components/optimization_guide/internal/testing/ ++components/optimization_guide/internal/tools/ ++components/optimization_guide/optimization_guide_internals/ ++components/optimization_guide/proto/ ++components/optimization_guide/tools/ ++components/page_image_service/ ++components/password_manager/ ++components/performance_manager/ ++components/plus_addresses/ ++components/prefs/ ++components/sync/ ++components/sync_bookmarks/ ++components/sync_device_info/ ++components/sync_preferences/ ++components/sync_sessions/ ++components/sync_user_events/ ++components/variations/ -courgette/ -crypto/ -data/ --dbus/ -device/ -docs/ --extensions/ -fuchsia_web/ -gin/ -google_apis/ @@ -85,28 +125,29 @@ -ios_internal/ -ipc/ -media/ --mojo/ -native_client/ -native_client_sdk/ -net/third_party/ -ppapi/ -printing/ -remoting/ --rlz/ -sandbox/ --services/ +-services/accessibility +-services/data_decoder +-services/shape_detection +-services/tracing/public/cpp/perfetto/ -signing_keys/ -skia/ -sql/ -storage/ -testing/ -third_party/ ++third_party/blink/ -tools/ -ui/ +ui/views/ --url/ +-url/third_party -v8/ --webkit/ # TODO(crbug.com/41497066#comment22) The Win SDK headers don't get categorized # as system headers when building with DEPOT_TOOLS_WIN_TOOLCHAIN=0 ? diff --git a/naiveproxy/src/build/config/zos/BUILD.gn b/naiveproxy/src/build/config/zos/BUILD.gn index 082ac1d389..6d41055b4b 100644 --- a/naiveproxy/src/build/config/zos/BUILD.gn +++ b/naiveproxy/src/build/config/zos/BUILD.gn @@ -6,14 +6,14 @@ import("//build/config/sanitizers/sanitizers.gni") import("//build/toolchain/toolchain.gni") # This is included by reference in the //build/config/compiler config that -# is applied to all targets. It is here to separate out the logic. +# is applied to all targets. It is here to specify defines and flags that +# are z/OS-specific. config("compiler") { defines = [ "_AE_BIMODAL=1", "_ALL_SOURCE", "_ENHANCED_ASCII_EXT=0xFFFFFFFF", - "_Export=extern", "_LARGE_TIME_API", "_OPEN_MSGQ_EXT", "_OPEN_SYS_FILE_EXT=1", @@ -23,35 +23,26 @@ config("compiler") { "_UNIX03_WITHDRAWN", "_XOPEN_SOURCE=600", "_XOPEN_SOURCE_EXTENDED", - "__static_assert=static_assert", "PATH_MAX=1024", + "ZOSLIB_OVERRIDE_CLIB", ] cflags = [ - "-q64", - "-qASCII", - "-Wc,DLL", - "-Wa,GOFF", - "-qENUM=INT", - "-qEXPORTALL", - "-qASM", - "-qmakedep", - "-qARCH=10", - "-qTUNE=10", - "-qasmlib=sys1.maclib:sys1.modgen", - "-qfloat=IEEE", - "-qlibansi", - "-qgonumber", - "-qlongname", + "-fno-short-enums", + "-fno-xl-pragma-pack", + "-fzos-le-char-mode=ascii", + "-m64", + "-march=arch14", + "-mzos-target=zosv2r4", + "-Wno-unknown-pragmas", ] - cflags_cc = [ - ] + cflags_cc = [] asmflags = [ - "-Wa,GOFF", + "-Wa,-mGOFF", + "-fno-integrated-as", ] - ldflags = [ - ] + ldflags = [] } diff --git a/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 b/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 index a13ff8eb17..b48b6ecad9 100644 --- a/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 +++ b/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 @@ -1 +1 @@ -21.20240605.3.1 +22.20240718.101.1 diff --git a/naiveproxy/src/build/fuchsia/test/coveragetest.py b/naiveproxy/src/build/fuchsia/test/coveragetest.py index 7bd2d70329..f48c044fbd 100755 --- a/naiveproxy/src/build/fuchsia/test/coveragetest.py +++ b/naiveproxy/src/build/fuchsia/test/coveragetest.py @@ -20,7 +20,7 @@ COVERED_FILES = [ # The files will be tested without coverage requirements. TESTED_FILES = [ - 'common.py', 'ffx_emulator.py', 'modification_waiter.py', + 'common.py', 'ffx_emulator.py', 'modification_waiter.py', 'monitors.py', 'serial_boot_device.py' ] diff --git a/naiveproxy/src/build/fuchsia/test/ffx_emulator.py b/naiveproxy/src/build/fuchsia/test/ffx_emulator.py index 100fcd9d0e..1fc2710e9b 100644 --- a/naiveproxy/src/build/fuchsia/test/ffx_emulator.py +++ b/naiveproxy/src/build/fuchsia/test/ffx_emulator.py @@ -10,6 +10,8 @@ import random from contextlib import AbstractContextManager +import monitors + from common import run_ffx_command, IMAGES_ROOT, INTERNAL_IMAGES_ROOT, \ DIR_SRC_ROOT from compatible_utils import get_host_arch @@ -89,7 +91,8 @@ class FfxEmulator(AbstractContextManager): if self._product.endswith('arm64'): emu_command.extend(['--engine', 'qemu']) - run_ffx_command(cmd=emu_command, timeout=310, configs=configs) + with monitors.time_consumption('emulator', 'startup_time'): + run_ffx_command(cmd=emu_command, timeout=310, configs=configs) return self._node_name diff --git a/naiveproxy/src/build/fuchsia/test/monitors.py b/naiveproxy/src/build/fuchsia/test/monitors.py new file mode 100644 index 0000000000..80b375b188 --- /dev/null +++ b/naiveproxy/src/build/fuchsia/test/monitors.py @@ -0,0 +1,57 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +""" The module to provide measurements when it's supported. """ + +import os +import sys + +from contextlib import AbstractContextManager + +PROTO_DIR = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', 'util/lib/proto/')) +if os.path.isdir(PROTO_DIR): + sys.path.append(PROTO_DIR) + # pylint: disable=import-error, unused-import + from measures import average, count, data_points, dump, time_consumption +else: + + class Dummy(AbstractContextManager): + """Dummy implementation when measures components do not exist.""" + + # pylint: disable=no-self-use + def record(self, *_) -> None: + """Dummy implementation of Measure.record.""" + + # pylint: disable=no-self-use + def dump(self) -> None: + """Dummy implementation of Measure.dump.""" + # Shouldn't be called. + assert False + + # pylint: disable=no-self-use + def __enter__(self) -> None: + pass + + # pylint: disable=no-self-use + def __exit__(self, *_) -> bool: + return False + + def average(*_) -> Dummy: + """Dummy implementation of measures.average.""" + return Dummy() + + def count(*_) -> Dummy: + """Dummy implementation of measures.count.""" + return Dummy() + + def data_points(*_) -> Dummy: + """Dummy implementation of measures.data_points.""" + return Dummy() + + def time_consumption(*_) -> Dummy: + """Dummy implementation of measures.time_consumption.""" + return Dummy() + + def dump(*_) -> None: + """Dummy implementation of measures.dump.""" diff --git a/naiveproxy/src/build/fuchsia/test/monitors_unittests.py b/naiveproxy/src/build/fuchsia/test/monitors_unittests.py new file mode 100755 index 0000000000..6b70a1e3af --- /dev/null +++ b/naiveproxy/src/build/fuchsia/test/monitors_unittests.py @@ -0,0 +1,59 @@ +#!/usr/bin/env vpython3 + +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""File for testing monitors.py.""" + +import importlib +import os +import tempfile +import unittest +import unittest.mock as mock + +import monitors + + +def dump() -> bool: + """Tries to dump the metrics into a temporary file and returns if the + file exits.""" + with tempfile.TemporaryDirectory() as tmpdir: + monitors.dump(tmpdir) + return os.path.isfile( + os.path.join(tmpdir, 'test_script_metrics.jsonpb')) + + +class MonitorsRealTest(unittest.TestCase): + """Test real implementation of monitors.py.""" + + def test_run_real_implementation(self) -> None: + """Ensures the real version of the monitors is loaded.""" + importlib.reload(monitors) + ave = monitors.average('test', 'run', 'real', 'implementation') + ave.record(1) + ave.record(2) + self.assertTrue(dump()) + + @mock.patch('os.path.isdir', side_effect=[False, True]) + def test_run_dummy_implementation(self, *_) -> None: + """Ensures the dummy version of the monitors is loaded.""" + importlib.reload(monitors) + ave = monitors.average('test', 'run', 'dummy', 'implementation') + ave.record(1) + ave.record(2) + self.assertFalse(dump()) + + @mock.patch('os.path.isdir', side_effect=[False, True]) + def test_with_dummy_implementation(self, *_) -> None: + """Ensures the dummy version of the monitors can be used by 'with' + statement.""" + importlib.reload(monitors) + executed = False + with monitors.time_consumption('test', 'with', 'dummy'): + executed = True + self.assertTrue(executed) + self.assertFalse(dump()) + + +if __name__ == '__main__': + unittest.main() diff --git a/naiveproxy/src/build/fuchsia/test/run_test.py b/naiveproxy/src/build/fuchsia/test/run_test.py index 6149fbeb36..7db26bee21 100755 --- a/naiveproxy/src/build/fuchsia/test/run_test.py +++ b/naiveproxy/src/build/fuchsia/test/run_test.py @@ -13,6 +13,8 @@ import tempfile from contextlib import ExitStack from typing import List +import monitors + from common import register_common_args, register_device_args, \ register_log_args, resolve_packages from compatible_utils import running_unattended @@ -89,14 +91,19 @@ def main(): runner_args.device = True with ExitStack() as stack: - # See http://crbug.com/343611361#comment5, the ffx daemon may still - # write logs after being shut down and causes the unnecessary test - # failures. So this AbstractContextManager would check the modification - # time of the output folder to ensure no writes happening before - # exiting. - # This may belong to IsolateDaemon, but let's keep it here to test its - # functionality and reliability. - stack.enter_context(ModificationWaiter(runner_args.out_dir)) + if runner_args.logs_dir: + # See http://crbug.com/343611361#comment5, the ffx daemon may still + # write logs after being shut down and causes the unnecessary test + # failures. So this AbstractContextManager would check the + # modification time of the output folder to ensure no writes + # happening before exiting. + # This may belong to IsolateDaemon, but let's keep it here to test + # its functionality and reliability. + stack.enter_context(ModificationWaiter(runner_args.logs_dir)) + # TODO(crbug.com/343242386): Find a way to upload metric output when + # logs_dir is not defined. + stack.push(lambda *_: monitors.dump( + os.path.join(runner_args.logs_dir, 'invocations'))) log_manager = LogManager(runner_args.logs_dir) if running_unattended(): if runner_args.extra_path: diff --git a/naiveproxy/src/build/gn_helpers.py b/naiveproxy/src/build/gn_helpers.py index 34dfb134dd..4e98200541 100644 --- a/naiveproxy/src/build/gn_helpers.py +++ b/naiveproxy/src/build/gn_helpers.py @@ -23,7 +23,6 @@ file to the build directory. import json import os import re -import shlex import shutil import sys @@ -556,7 +555,7 @@ def CreateBuildCommand(output_directory): if not shutil.which(f'autoninja{suffix}'): third_party_prefix = os.path.join(_CHROMIUM_ROOT, 'third_party') ninja_prefix = os.path.join(third_party_prefix, 'ninja', '') - siso_prefix = os.path.join(third_party_prefix, 'siso', '') + siso_prefix = os.path.join(third_party_prefix, 'siso', 'cipd', '') # Also - bots configure reclient manually, and so do not use the "auto" # wrappers. ninja_cmd = [f'{ninja_prefix}ninja{suffix}'] @@ -565,7 +564,8 @@ def CreateBuildCommand(output_directory): ninja_cmd = [f'autoninja{suffix}'] siso_cmd = list(ninja_cmd) - if output_directory and os.path.relpath(output_directory) != '.': + if output_directory and os.path.abspath(output_directory) != os.path.abspath( + os.curdir): ninja_cmd += ['-C', output_directory] siso_cmd += ['-C', output_directory] siso_deps = os.path.exists(os.path.join(output_directory, '.siso_deps')) diff --git a/naiveproxy/src/build/gn_logs.gni b/naiveproxy/src/build/gn_logs.gni index 213b093a0a..76e2da4130 100644 --- a/naiveproxy/src/build/gn_logs.gni +++ b/naiveproxy/src/build/gn_logs.gni @@ -9,4 +9,13 @@ import("//build/toolchain/concurrent_links.gni") build_gn_logs = [ "### compiler.gni ###" ] + compiler_logs build_gn_logs += [ "" ] +if (target_os == "ios") { + import("//build/config/ios/ios_sdk.gni") + import("//build/config/mac/mac_sdk.gni") + build_gn_logs += [ "### ios_sdk.gni ###" ] + ios_sdk_logs + build_gn_logs += [ "" ] + build_gn_logs += [ "### mac_sdk.gni ###" ] + mac_sdk_logs + build_gn_logs += [ "" ] +} + build_gn_logs += [ "#### get_concurrent_links.py ####" ] + concurrent_links_logs diff --git a/naiveproxy/src/build/install-build-deps.py b/naiveproxy/src/build/install-build-deps.py index cfbf9e8f1a..58264ec626 100755 --- a/naiveproxy/src/build/install-build-deps.py +++ b/naiveproxy/src/build/install-build-deps.py @@ -162,7 +162,7 @@ def check_distro(options): "\tUbuntu 20.04 LTS (focal with EoS April 2025)", "\tUbuntu 22.04 LTS (jammy with EoS June 2027)", "\tUbuntu 24.04 LTS (noble with EoS June 2029)", - "\tDebian 10 (buster) or later", + "\tDebian 11 (bullseye) or later", sep="\n", file=sys.stderr, ) @@ -234,6 +234,7 @@ def dev_list(): "libsctp-dev", "libspeechd-dev", "libsqlite3-dev", + "libssl-dev", "libsystemd-dev", "libudev-dev", "libva-dev", @@ -249,7 +250,7 @@ def dev_list(): "p7zip", "patch", "perl", - "pkg-config", + "pkgconf", "rpm", "ruby", "subversion", @@ -326,17 +327,6 @@ def dev_list(): elif package_exists("lib32gcc1"): packages.append("lib32gcc1") - # TODO(b/339091434): Remove this workaround once this bug is fixed. This - # workaround ensures the newer libssl-dev is used to prevent package conficts. - apt_cache_cmd = ["apt-cache", "show", "libssl-dev"] - output = subprocess.check_output(apt_cache_cmd).decode() - pattern = re.compile(r'^Version: (.+?)$', re.M) - versions = re.findall(pattern, output) - if set(versions) == {"3.2.1-3", "3.0.10-1"}: - packages.append("libssl-dev=3.2.1-3") - else: - packages.append("libssl-dev") - return packages @@ -638,6 +628,20 @@ def arm_list(options): "linux-libc-dev-armhf-cross", ] + # Work around an Ubuntu dependency issue. + # TODO(https://crbug.com/40549424): Remove this when support for Focal + # and Jammy are dropped. + if distro_codename() == "focal": + packages.extend([ + "g++-10-multilib-arm-linux-gnueabihf", + "gcc-10-multilib-arm-linux-gnueabihf", + ]) + elif distro_codename() == "jammy": + packages.extend([ + "g++-11-arm-linux-gnueabihf", + "gcc-11-arm-linux-gnueabihf", + ]) + return packages @@ -714,11 +718,20 @@ def nacl_list(options): return packages +# Packages suffixed with t64 are "transition packages" and should be preferred. +def maybe_append_t64(package): + name = package.split(":") + name[0] += "t64" + renamed = ":".join(name) + return renamed if package_exists(renamed) else package + + # Debian is in the process of transitioning to automatic debug packages, which # have the -dbgsym suffix (https://wiki.debian.org/AutomaticDebugPackages). # Untransitioned packages have the -dbg suffix. And on some systems, neither # will be available, so exclude the ones that are missing. def dbg_package_name(package): + package = maybe_append_t64(package) if package_exists(package + "-dbgsym"): return [package + "-dbgsym"] if package_exists(package + "-dbg"): @@ -757,10 +770,11 @@ def package_list(options): packages = (dev_list() + lib_list() + dbg_list(options) + lib32_list(options) + arm_list(options) + nacl_list(options) + backwards_compatible_list(options)) + packages = [maybe_append_t64(package) for package in set(packages)] # Sort all the :i386 packages to the front, to avoid confusing dpkg-query # (https://crbug.com/446172). - return sorted(set(packages), key=lambda x: (not x.endswith(":i386"), x)) + return sorted(packages, key=lambda x: (not x.endswith(":i386"), x)) def missing_packages(packages): diff --git a/naiveproxy/src/build/lacros/lacros_resource_sizes.py b/naiveproxy/src/build/lacros/lacros_resource_sizes.py index 23ce0d09ca..965361c03f 100755 --- a/naiveproxy/src/build/lacros/lacros_resource_sizes.py +++ b/naiveproxy/src/build/lacros/lacros_resource_sizes.py @@ -41,8 +41,7 @@ DIR_SOURCE_ROOT = os.environ.get( os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))) -BUILD_COMMON_PATH = os.path.join(DIR_SOURCE_ROOT, 'build', 'util', 'lib', - 'common') +BUILD_UTIL_PATH = os.path.join(DIR_SOURCE_ROOT, 'build', 'util') TRACING_PATH = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'catapult', 'tracing') @@ -50,8 +49,8 @@ TRACING_PATH = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'catapult', EU_STRIP_PATH = os.path.join(DIR_SOURCE_ROOT, 'buildtools', 'third_party', 'eu-strip', 'bin', 'eu-strip') -with _SysPath(BUILD_COMMON_PATH): - import perf_tests_results_helper # pylint: disable=import-error +with _SysPath(BUILD_UTIL_PATH): + from lib.common import perf_tests_results_helper with _SysPath(TRACING_PATH): from tracing.value import convert_chart_json # pylint: disable=import-error @@ -124,6 +123,8 @@ _TRACKED_GROUPS = [ title='Group: Other PAKs'), _Group(paths=['snapshot_blob.bin'], title='Group: Misc'), _Group(paths=['locales/'], title='Dir: locales'), + _Group(paths=['PrivacySandboxAttestationsPreloaded/'], + title='Dir: PrivacySandboxAttestationsPreloaded'), _Group(paths=['resources/accessibility/'], title='Dir: resources/accessibility'), _Group(paths=['WidevineCdm/'], title='Dir: WidevineCdm'), diff --git a/naiveproxy/src/build/lacros/lacros_resource_sizes.pydeps b/naiveproxy/src/build/lacros/lacros_resource_sizes.pydeps index dc6a116996..8797053b22 100644 --- a/naiveproxy/src/build/lacros/lacros_resource_sizes.pydeps +++ b/naiveproxy/src/build/lacros/lacros_resource_sizes.pydeps @@ -8,6 +8,7 @@ ../../third_party/catapult/tracing/tracing/value/convert_chart_json.py ../../third_party/catapult/tracing/tracing_project.py ../util/lib/__init__.py +../util/lib/common/__init__.py ../util/lib/common/perf_result_data_type.py ../util/lib/common/perf_tests_results_helper.py ../util/lib/results/__init__.py diff --git a/naiveproxy/src/build/linux/extract_symbols.gni b/naiveproxy/src/build/linux/extract_symbols.gni index 8fef1312d8..26426c8aad 100644 --- a/naiveproxy/src/build/linux/extract_symbols.gni +++ b/naiveproxy/src/build/linux/extract_symbols.gni @@ -18,7 +18,8 @@ template("extract_symbols") { "testonly", ]) action("${target_name}") { - dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)" + dump_syms_label = + "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)" dump_syms_binary = get_label_info(dump_syms_label, "root_out_dir") + "/" + "dump_syms" diff --git a/naiveproxy/src/build/linux/sysroot_scripts/install-sysroot.py b/naiveproxy/src/build/linux/sysroot_scripts/install-sysroot.py index 9113d85f19..834a47eb0e 100755 --- a/naiveproxy/src/build/linux/sysroot_scripts/install-sysroot.py +++ b/naiveproxy/src/build/linux/sysroot_scripts/install-sysroot.py @@ -36,7 +36,7 @@ from urllib.request import urlopen SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(SCRIPT_DIR))) -VALID_ARCHS = ('amd64', 'i386', 'armhf', 'arm64', 'mipsel', 'mips64el', 'riscv64') +VALID_ARCHS = ("amd64", "i386", "armhf", "arm64", "mipsel", "mips64el", "riscv64") ARCH_TRANSLATIONS = { "x64": "amd64", diff --git a/naiveproxy/src/build/linux/sysroot_scripts/sysroot_creator.py b/naiveproxy/src/build/linux/sysroot_scripts/sysroot_creator.py index be7cab9f31..deb79a3319 100755 --- a/naiveproxy/src/build/linux/sysroot_scripts/sysroot_creator.py +++ b/naiveproxy/src/build/linux/sysroot_scripts/sysroot_creator.py @@ -306,7 +306,7 @@ def hacks_and_patches(install_root: str, script_dir: str, arch: str) -> None: # earliest supported version of glibc (2.26). features_h = os.path.join(install_root, "usr", "include", "features.h") replace_in_file(features_h, r"(#define\s+__GLIBC_MINOR__)", r"\1 26 //") - + # fcntl64() was introduced in glibc 2.28. Make sure to use fcntl() instead. fcntl_h = os.path.join(install_root, "usr", "include", "fcntl.h") replace_in_file( diff --git a/naiveproxy/src/build/linux/unbundle/absl_base.gn b/naiveproxy/src/build/linux/unbundle/absl_base.gn index 7da86e4614..b5ce0863e6 100644 --- a/naiveproxy/src/build/linux/unbundle/absl_base.gn +++ b/naiveproxy/src/build/linux/unbundle/absl_base.gn @@ -27,6 +27,7 @@ shim_headers("base_shim") { headers = [ "call_once.h", "casts.h", + "dynamic_annotations.h", ] } diff --git a/naiveproxy/src/build/linux/unbundle/absl_container.gn b/naiveproxy/src/build/linux/unbundle/absl_container.gn index 9d1a0dea8e..e211c911c2 100644 --- a/naiveproxy/src/build/linux/unbundle/absl_container.gn +++ b/naiveproxy/src/build/linux/unbundle/absl_container.gn @@ -117,6 +117,8 @@ source_set("flat_hash_map_test") { } source_set("flat_hash_set_test") { } +source_set("hash_function_defaults_test") { +} source_set("inlined_vector_test") { } source_set("node_slot_policy_test") { diff --git a/naiveproxy/src/build/linux/unbundle/absl_debugging.gn b/naiveproxy/src/build/linux/unbundle/absl_debugging.gn index 5fbd34abbc..b59a45b091 100644 --- a/naiveproxy/src/build/linux/unbundle/absl_debugging.gn +++ b/naiveproxy/src/build/linux/unbundle/absl_debugging.gn @@ -46,5 +46,7 @@ source_set("symbolize") { public_configs = [ ":system_absl_symbolize" ] } +source_set("demangle_rust_test") { +} source_set("stacktrace_test") { } diff --git a/naiveproxy/src/build/linux/unbundle/absl_flags.gn b/naiveproxy/src/build/linux/unbundle/absl_flags.gn index 56b65c61a1..cb0358399e 100644 --- a/naiveproxy/src/build/linux/unbundle/absl_flags.gn +++ b/naiveproxy/src/build/linux/unbundle/absl_flags.gn @@ -1,6 +1,12 @@ import("//build/config/linux/pkg_config.gni") import("//build/shim_headers.gni") +pkg_config("absl_flags_config") { + # This target is referenced by //third_party/abseil-cpp:absl_full_deps + # and as such must be named like this and not like system_ + packages = [ "absl_flags_config" ] +} + pkg_config("system_absl_flags") { packages = [ "absl_flags" ] } @@ -9,10 +15,28 @@ pkg_config("system_absl_flags_parse") { packages = [ "absl_flags_parse" ] } +pkg_config("system_absl_flags_reflection") { + packages = [ "absl_flags_reflection" ] +} + pkg_config("system_absl_flags_usage") { packages = [ "absl_flags_usage" ] } +shim_headers("flags_config_shim") { + root_path = "." + prefix = "absl/flags/" + headers = [ + "config.h", + "usage_config.h", + ] +} + +source_set("config") { + deps = [ ":flags_config_shim" ] + public_configs = [ ":absl_flags_config" ] +} + shim_headers("flag_shim") { root_path = "." prefix = "absl/flags/" @@ -38,6 +62,20 @@ source_set("parse") { public_configs = [ ":system_absl_flags_parse" ] } +shim_headers("flags_reflection_shim") { + root_path = "." + prefix = "absl/flags/" + headers = [ + "internal/registry.h", + "reflection.h", + ] +} + +source_set("reflection") { + deps = [ ":flags_reflection_shim" ] + public_configs = [ ":system_absl_flags_reflection" ] +} + shim_headers("usage_shim") { root_path = "." prefix = "absl/flags/" diff --git a/naiveproxy/src/build/linux/unbundle/absl_log.gn b/naiveproxy/src/build/linux/unbundle/absl_log.gn index b78d5e495d..d5c06506d6 100644 --- a/naiveproxy/src/build/linux/unbundle/absl_log.gn +++ b/naiveproxy/src/build/linux/unbundle/absl_log.gn @@ -9,6 +9,10 @@ pkg_config("system_absl_absl_log") { packages = [ "absl_absl_log" ] } +pkg_config("system_absl_check") { + packages = [ "absl_check" ] +} + pkg_config("system_absl_die_if_null") { packages = [ "absl_die_if_null" ] } @@ -16,6 +20,15 @@ pkg_config("system_absl_die_if_null") { pkg_config("system_absl_log") { packages = [ "absl_log" ] } + +pkg_config("system_absl_log_globals") { + packages = [ "absl_log_globals" ] +} + +pkg_config("system_absl_log_initialize") { + packages = [ "absl_log_initialize" ] +} + shim_headers("absl_check_shim") { root_path = "." prefix = "absl/log/" @@ -38,6 +51,17 @@ source_set("absl_log") { public_configs = [ ":system_absl_absl_log" ] } +shim_headers("check_shim") { + root_path = "." + prefix = "absl/log/" + headers = [ "check.h" ] +} + +source_set("check") { + deps = [ ":check_shim" ] + public_configs = [ ":system_absl_check" ] +} + shim_headers("die_if_null_shim") { root_path = "." prefix = "absl/log/" @@ -49,6 +73,28 @@ source_set("die_if_null") { public_configs = [ ":system_absl_die_if_null" ] } +shim_headers("globals_shim") { + root_path = "." + prefix = "absl/log/" + headers = [ "globals.h" ] +} + +source_set("globals") { + deps = [ ":globals_shim" ] + public_configs = [ ":system_absl_log_globals" ] +} + +shim_headers("initialize_shim") { + root_path = "." + prefix = "absl/log/" + headers = [ "initialize.h" ] +} + +source_set("initialize") { + deps = [ ":initialize_shim" ] + public_configs = [ ":system_absl_log_initialize" ] +} + shim_headers("log_shim") { root_path = "." prefix = "absl/log/" diff --git a/naiveproxy/src/build/linux/unbundle/absl_random.gn b/naiveproxy/src/build/linux/unbundle/absl_random.gn index 7bb70241ad..eae95345e4 100644 --- a/naiveproxy/src/build/linux/unbundle/absl_random.gn +++ b/naiveproxy/src/build/linux/unbundle/absl_random.gn @@ -57,3 +57,8 @@ source_set("random") { deps = [ ":random_shim" ] public_configs = [ ":system_absl_random_random" ] } + +group("distributions_test") { +} +group("mock_distributions_test") { +} diff --git a/naiveproxy/src/build/linux/unbundle/absl_status.gn b/naiveproxy/src/build/linux/unbundle/absl_status.gn index 5f1e73a6d4..1905485814 100644 --- a/naiveproxy/src/build/linux/unbundle/absl_status.gn +++ b/naiveproxy/src/build/linux/unbundle/absl_status.gn @@ -38,3 +38,5 @@ source_set("status_test") { } source_set("statusor_test") { } +source_set("status_matchers_test") { +} diff --git a/naiveproxy/src/build/linux/unbundle/absl_types.gn b/naiveproxy/src/build/linux/unbundle/absl_types.gn index 4bb77f1b63..8d2b131455 100644 --- a/naiveproxy/src/build/linux/unbundle/absl_types.gn +++ b/naiveproxy/src/build/linux/unbundle/absl_types.gn @@ -93,5 +93,7 @@ source_set("variant") { source_set("optional_test") { } +source_set("span_test") { +} source_set("variant_test") { } diff --git a/naiveproxy/src/build/linux/unbundle/dav1d.gn b/naiveproxy/src/build/linux/unbundle/dav1d.gn index 3d65158bc6..a6d005a662 100644 --- a/naiveproxy/src/build/linux/unbundle/dav1d.gn +++ b/naiveproxy/src/build/linux/unbundle/dav1d.gn @@ -21,3 +21,14 @@ source_set("dav1d") { deps = [ ":dav1d_shim" ] public_configs = [ ":system_dav1d" ] } + +group("dav1d_headers") { + public_deps = [ ":dav1d_shim" ] +} + +config("dav1d_config") { + configs = [ + ":system_dav1d", + ":dav1d_shim_config", + ] +} diff --git a/naiveproxy/src/build/linux/unbundle/highway.gn b/naiveproxy/src/build/linux/unbundle/highway.gn index d997c7c2ce..ac7e743f70 100644 --- a/naiveproxy/src/build/linux/unbundle/highway.gn +++ b/naiveproxy/src/build/linux/unbundle/highway.gn @@ -1,9 +1,20 @@ import("//build/config/linux/pkg_config.gni") +import("//build/shim_headers.gni") +import("src/hwy.gni") pkg_config("libhwy_external_config") { packages = [ "libhwy" ] } +shim_headers("libhwy_shim") { + root_path = "src" + headers = [] + foreach(header, hwy_public) { + headers += [ rebase_path(header, "./src") ] + } +} + source_set("libhwy") { public_configs = [ ":libhwy_external_config" ] + public_deps = [ ":libhwy_shim" ] } diff --git a/naiveproxy/src/build/linux/unbundle/icu.gn b/naiveproxy/src/build/linux/unbundle/icu.gn index 366ffd5a35..bad83cda02 100644 --- a/naiveproxy/src/build/linux/unbundle/icu.gn +++ b/naiveproxy/src/build/linux/unbundle/icu.gn @@ -61,6 +61,10 @@ source_set("icuuc") { ] } +group("icuuc_public") { + public_deps = [ ":icuuc" ] +} + shim_headers("icui18n_shim") { root_path = "source/i18n" headers = [ diff --git a/naiveproxy/src/build/linux/unbundle/re2.gn b/naiveproxy/src/build/linux/unbundle/re2.gn index d8e4d79b18..d587619d04 100644 --- a/naiveproxy/src/build/linux/unbundle/re2.gn +++ b/naiveproxy/src/build/linux/unbundle/re2.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/c++/c++.gni") +import("//build/config/linux/pkg_config.gni") import("//build/shim_headers.gni") assert(!use_custom_libcxx, @@ -10,6 +11,10 @@ assert(!use_custom_libcxx, "use_custom_libcxx=true because the library's interface relies on " + "libstdc++'s std::string and std::vector.") +pkg_config("re2_config") { + packages = [ "re2" ] +} + shim_headers("re2_shim") { root_path = "src" headers = [ @@ -23,5 +28,5 @@ shim_headers("re2_shim") { source_set("re2") { deps = [ ":re2_shim" ] - libs = [ "re2" ] + public_configs = [ ":re2_config" ] } diff --git a/naiveproxy/src/build/rust/BUILD.gn b/naiveproxy/src/build/rust/BUILD.gn index ec82053808..6473dfbab2 100644 --- a/naiveproxy/src/build/rust/BUILD.gn +++ b/naiveproxy/src/build/rust/BUILD.gn @@ -17,11 +17,11 @@ if (toolchain_has_rust) { rustflags = [ "--edition=2015" ] } - if (enable_cxx) { + if (enable_rust_cxx) { # The version of cxx under //third_party/rust/chromium_crates_io/vendor. # Update this whenever cxx is rolled. Also update the version number in the # //third_party/rust/cxx/v1/cxx.h header. - cxx_version = "1.0.122" + cxx_version = "1.0.124" # The required dependencies for cxx-generated bindings, that must be included # on the C++ side. diff --git a/naiveproxy/src/build/rust/run_build_script.py b/naiveproxy/src/build/rust/run_build_script.py index b0a0ae3cab..60cfee9bb5 100755 --- a/naiveproxy/src/build/rust/run_build_script.py +++ b/naiveproxy/src/build/rust/run_build_script.py @@ -62,7 +62,9 @@ def host_triple(rustc_path): return known_vars["host"] -RUSTC_CFG_LINE = re.compile("cargo:rustc-cfg=(.*)") +# Before 1.77, the format was `cargo:rustc-cfg=`. As of 1.77 the format is now +# `cargo::rustc-cfg=`. +RUSTC_CFG_LINE = re.compile("cargo::?rustc-cfg=(.*)") def main(): diff --git a/naiveproxy/src/build/rust/rust_target.gni b/naiveproxy/src/build/rust/rust_target.gni index 1ca1af2d91..10371f12c0 100644 --- a/naiveproxy/src/build/rust/rust_target.gni +++ b/naiveproxy/src/build/rust/rust_target.gni @@ -5,9 +5,11 @@ import("//build/config/rust.gni") import("//build/rust/rust_unit_test.gni") -# The //build directory is re-used for non-Chromium products. We do not support -# cxx bindings in such contexts, because //third_party may be missing. -if (build_with_chromium) { +# The //build directory is re-used for non-Chromium projects. Do not support +# cxx bindings in such contexts by default, because //third_party may be +# missing. Projects that wish to use cxx bindings must explicitly set the +# enable_rust_cxx GN arg to true. +if (enable_rust_cxx) { import("//third_party/rust/cxx/chromium_integration/rust_cxx.gni") } @@ -183,7 +185,7 @@ template("rust_target") { # generate Rust code internally, depending on what bindings are declared. If # set, it's a set of rust files that include Cxx bindings declarations. _cxx_bindings = [] - assert(!defined(invoker.cxx_bindings) || enable_cxx, + assert(!defined(invoker.cxx_bindings) || enable_rust_cxx, "cxx bindings are not supported when building rust targets " + "outside the Chromium build.") if (defined(invoker.cxx_bindings)) { diff --git a/naiveproxy/src/build/rust/rust_unit_test.gni b/naiveproxy/src/build/rust/rust_unit_test.gni index b6cf3b2181..be2bbeb4a0 100644 --- a/naiveproxy/src/build/rust/rust_unit_test.gni +++ b/naiveproxy/src/build/rust/rust_unit_test.gni @@ -86,11 +86,6 @@ template("rust_unit_test") { _env_out_dir = target_gen_dir } - # TODO(crbug.com/40778298): Arrange to run test executables on try bots. - # TODO(crbug.com/gn/146): Allow Rust executables to depend on C/C++ source - # sets. - # This is important in cases where Rust tests may depend upon C/C++ - # dependencies. executable(_exe_target_name) { testonly = true forward_variables_from(invoker, diff --git a/naiveproxy/src/build/rust/std/BUILD.gn b/naiveproxy/src/build/rust/std/BUILD.gn index 86fb3da8d4..b9500eeabb 100644 --- a/naiveproxy/src/build/rust/std/BUILD.gn +++ b/naiveproxy/src/build/rust/std/BUILD.gn @@ -12,17 +12,27 @@ # Clang drives the linking it is required. # # Part of the standard library provided here is "remap_alloc" which maps -# allocator functions into the shim provided by PartitionAlloc so that Rust and -# C++ use the same allocator backend. +# allocator functions to PartitionAlloc when `use_partition_alloc_as_malloc` is +# true, so that Rust and C++ use the same allocator backend. +import("//base/allocator/partition_allocator/partition_alloc.gni") import("//build/config/compiler/compiler.gni") import("//build/config/coverage/coverage.gni") import("//build/config/rust.gni") import("//build/config/sanitizers/sanitizers.gni") if (toolchain_has_rust) { - # Equivalent of allocator symbols injected by rustc. + # If clang performs the link step, we need to provide the allocator symbols + # that are normally injected by rustc during linking. + # + # We also "happen to" use this to redirect allocations to PartitionAlloc, + # though that would be better done through a #[global_allocator] crate (see + # above). source_set("remap_alloc") { + public_deps = [ "//base/allocator/partition_allocator:buildflags" ] + if (use_partition_alloc_as_malloc) { + public_deps += [ "//base/allocator/partition_allocator:partition_alloc" ] + } sources = [ # `alias.*`, `compiler_specific.h`, and `immediate_crash.*` have been # copied from `//base`. @@ -51,7 +61,6 @@ if (toolchain_has_rust) { "core", "getopts", "hashbrown", - "libc", "panic_abort", "panic_unwind", "rustc_demangle", @@ -67,6 +76,7 @@ if (toolchain_has_rust) { "addr2line", "adler", "gimli", + "libc", "memchr", "miniz_oxide", "object", @@ -268,32 +278,27 @@ if (toolchain_has_rust) { rustc_sanitizer_runtimes += [ ":sanitizer_rt_hwasan" ] } - group("local_stdlib_libs") { + # Builds and links against the Rust stdlib. Both Rust and C++ targets should + # depend on this, as it provides the path to the library and includes the + # allocator hooks. + group("std") { assert(toolchain_has_rust, "Some C++ target is depending on Rust code even though " + "toolchain_has_rust=false. Usually this would mean" + "a NaCl target is depending on Rust, as there's no Rust " + "toolchain targetting NaCl.") - all_dependent_configs = [ ":stdlib_dependent_libs" ] + all_dependent_configs = [ + ":stdlib_public_dependent_libs", + ":local_stdlib_sysroot", + ":stdlib_dependent_libs", + ] deps = [] foreach(libname, stdlib_files + skip_stdlib_files) { deps += [ "rules:$libname" ] } deps += rustc_sanitizer_runtimes - visibility = [ ":*" ] - } - # Builds and links against the Rust stdlib. Used by targets for which - # linking is driven by C++. - group("std") { - all_dependent_configs = [ - ":stdlib_public_dependent_libs", - ":local_stdlib_sysroot", - ] - public_deps = [ - ":local_stdlib_libs", - ":remap_alloc", - ] + public_deps = [ ":remap_alloc" ] } } else { action("find_stdlib") { diff --git a/naiveproxy/src/build/rust/std/DEPS b/naiveproxy/src/build/rust/std/DEPS new file mode 100644 index 0000000000..eb524c0a06 --- /dev/null +++ b/naiveproxy/src/build/rust/std/DEPS @@ -0,0 +1,9 @@ +include_rules = [ + "-base", +] + +specific_include_rules = { + "remap_alloc.cc" : [ + "+partition_alloc" + ] +} diff --git a/naiveproxy/src/build/rust/std/remap_alloc.cc b/naiveproxy/src/build/rust/std/remap_alloc.cc index 7604b2049f..0a87be2479 100644 --- a/naiveproxy/src/build/rust/std/remap_alloc.cc +++ b/naiveproxy/src/build/rust/std/remap_alloc.cc @@ -2,19 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include - -#include #include -#include -#include #include "build/build_config.h" #include "build/rust/std/alias.h" #include "build/rust/std/immediate_crash.h" +#include "partition_alloc/buildflags.h" -#if BUILDFLAG(IS_ANDROID) -#include +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) +#include "partition_alloc/partition_alloc_constants.h" // nogncheck +#include "partition_alloc/shim/allocator_shim.h" // nogncheck #endif // When linking a final binary, rustc has to pick between either: @@ -45,20 +42,21 @@ // few other symbols. // // We're not (always) using rustc for final linking. For cases where we're not -// Rustc as the final linker, we'll define those symbols here instead. +// Rustc as the final linker, we'll define those symbols here instead. This +// allows us to redirect allocation to PartitionAlloc if clang is doing the +// link. // -// The Rust stdlib on Windows uses GetProcessHeap() which will bypass -// PartitionAlloc, so we do not forward these functions back to the stdlib. -// Instead, we pass them to PartitionAlloc, while replicating functionality from -// the unix stdlib to allow them to provide their increased functionality on top -// of the system functions. +// We use unchecked allocation paths in PartitionAlloc rather than going through +// its shims in `malloc()` etc so that we can support fallible allocation paths +// such as Vec::try_reserve without crashing on allocation failure. // -// In future, we may build a crate with a #[global_allocator] and +// In future, we should build a crate with a #[global_allocator] and // redirect these symbols back to Rust in order to use to that crate instead. -// -// Instead of going through system functions like malloc() we may want to call -// into PA directly if we wished for Rust allocations to be in a different -// partition, or similar, in the future. +// This would allow Rust-linked executables to: +// 1. Use PartitionAlloc on Windows. The stdlib uses Windows heap functions +// directly that PartitionAlloc can not intercept. +// 2. Have `Vec::try_reserve` to fail at runtime on Linux instead of crashing in +// malloc() where PartitionAlloc replaces that function. // // They're weak symbols, because this file will sometimes end up in targets // which are linked by rustc, and thus we would otherwise get duplicate @@ -85,59 +83,37 @@ extern "C" { // Marked as weak as when Rust drives linking it includes this symbol itself, // and we don't want a collision due to C++ being in the same link target, where // C++ causes us to explicitly link in the stdlib and this symbol here. -[[maybe_unused]] __attribute__(( - weak)) unsigned char __rust_no_alloc_shim_is_unstable; +[[maybe_unused]] +__attribute__((weak)) unsigned char __rust_no_alloc_shim_is_unstable; REMAP_ALLOC_ATTRIBUTES void* __rust_alloc(size_t size, size_t align) { - // This mirrors kMaxSupportedAlignment from - // base/allocator/partition_allocator/src/partition_alloc/partition_alloc_constants.h. - // ParitionAlloc will crash if given an alignment larger than this. - constexpr size_t max_align = (1 << 21) / 2; - if (align > max_align) { +#if !PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + extern void* __rdl_alloc(size_t size, size_t align); + return __rdl_alloc(size, align); +#else + // PartitionAlloc will crash if given an alignment larger than this. + if (align > partition_alloc::internal::kMaxSupportedAlignment) { return nullptr; } if (align <= alignof(std::max_align_t)) { - return malloc(size); + return allocator_shim::UncheckedAlloc(size); } else { - // Note: PartitionAlloc by default will route aligned allocations back to - // malloc() (the fast path) if they are for a small enough alignment. So we - // just unconditionally use aligned allocation functions here. - // https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc;l=219-226;drc=31d99ff4aa0cc0b75063325ff243e911516a5a6a - -#if defined(COMPILER_MSVC) - return _aligned_malloc(size, align); -#elif BUILDFLAG(IS_ANDROID) - // Android has no posix_memalign() exposed: - // https://source.chromium.org/chromium/chromium/src/+/main:base/memory/aligned_memory.cc;l=24-30;drc=e4622aaeccea84652488d1822c28c78b7115684f - return memalign(align, size); -#else - // The `align` from Rust is always a power of 2: - // https://doc.rust-lang.org/std/alloc/struct.Layout.html#method.from_size_align. - // - // We get here only if align > alignof(max_align_t), which guarantees that - // the alignment is both a power of 2 and even, which is required by - // posix_memalign(). - // - // The PartitionAlloc impl requires that the alignment is at least the same - // as pointer-alignment. std::max_align_t is at least pointer-aligned as - // well, so we satisfy that. - void* p; - auto ret = posix_memalign(&p, align, size); - return ret == 0 ? p : nullptr; -#endif + return allocator_shim::UncheckedAlignedAlloc(size, align); } +#endif } REMAP_ALLOC_ATTRIBUTES void __rust_dealloc(void* p, size_t size, size_t align) { -#if defined(COMPILER_MSVC) - if (align <= alignof(std::max_align_t)) { - free(p); - } else { - _aligned_free(p); - } +#if !PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + extern void __rdl_dealloc(void* p, size_t size, size_t align); + __rdl_dealloc(p, size, align); #else - free(p); + if (align <= alignof(std::max_align_t)) { + allocator_shim::UncheckedFree(p); + } else { + allocator_shim::UncheckedAlignedFree(p); + } #endif } @@ -145,23 +121,33 @@ REMAP_ALLOC_ATTRIBUTES void* __rust_realloc(void* p, size_t old_size, size_t align, size_t new_size) { +#if !PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + extern void* __rdl_realloc(void* p, size_t old_size, size_t align, + size_t new_size); + return __rdl_realloc(p, old_size, align, new_size); +#else if (align <= alignof(std::max_align_t)) { - return realloc(p, new_size); + return allocator_shim::UncheckedRealloc(p, new_size); } else { - void* out = __rust_alloc(align, new_size); - memcpy(out, p, std::min(old_size, new_size)); - return out; + return allocator_shim::UncheckedAlignedRealloc(p, new_size, align); } +#endif } REMAP_ALLOC_ATTRIBUTES void* __rust_alloc_zeroed(size_t size, size_t align) { - if (align <= alignof(std::max_align_t)) { - return calloc(size, 1); - } else { - void* p = __rust_alloc(size, align); +#if !PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + extern void* __rdl_alloc_zeroed(size_t size, size_t align); + return __rdl_alloc_zeroed(size, align); +#else + // TODO(danakj): It's possible that a partition_alloc::UncheckedAllocZeroed() + // call would perform better than partition_alloc::UncheckedAlloc() + memset. + // But there is no such API today. See b/342251590. + void* p = __rust_alloc(size, align); + if (p) { memset(p, 0, size); - return p; } + return p; +#endif } REMAP_ALLOC_ATTRIBUTES void __rust_alloc_error_handler(size_t size, diff --git a/naiveproxy/src/build/rust/std/rules/BUILD.gn b/naiveproxy/src/build/rust/std/rules/BUILD.gn index d5710ccd8d..0a61bfe6aa 100644 --- a/naiveproxy/src/build/rust/std/rules/BUILD.gn +++ b/naiveproxy/src/build/rust/std/rules/BUILD.gn @@ -8,12 +8,12 @@ import("//build/rust/cargo_crate.gni") cargo_crate("addr2line") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.21.0/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.22.0/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.21.0/src/builtin_split_dwarf_loader.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.21.0/src/function.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.21.0/src/lazy.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.21.0/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.22.0/src/builtin_split_dwarf_loader.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.22.0/src/function.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.22.0/src/lazy.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/addr2line-0.22.0/src/lib.rs", ] inputs = [] no_std = true @@ -21,7 +21,7 @@ cargo_crate("addr2line") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "0.21.0" + cargo_pkg_version = "0.22.0" cargo_pkg_name = "addr2line" cargo_pkg_description = "A cross-platform symbolication library written in Rust, using `gimli`" @@ -786,6 +786,7 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/README.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/avx512bw.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/avx512f.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/build.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/src/aarch64/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/src/aarch64/neon/generated.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../stdarch/crates/core_arch/src/aarch64/neon/mod.rs", @@ -928,6 +929,7 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ffi/c_ulonglong.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ffi/c_ushort.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ffi/c_void.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/fmt/fmt_trait_method_doc.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/macros/panic.md", ] no_std = true @@ -1010,50 +1012,52 @@ cargo_crate("getopts") { } cargo_crate("gimli") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/arch.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/constants.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/endianity.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/leb128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/abbrev.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/addr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/aranges.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/cfi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/dwarf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/endian_reader.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/endian_slice.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/index.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/line.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/lists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/loclists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/lookup.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/op.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/pubnames.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/pubtypes.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/reader.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/rnglists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/str.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/unit.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/value.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/test_util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/abbrev.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/cfi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/dwarf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/endian_vec.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/line.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/loc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/op.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/range.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/str.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/unit.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/arch.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/constants.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/endianity.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/leb128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/abbrev.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/addr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/aranges.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/cfi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/dwarf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/endian_reader.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/endian_slice.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/index.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/line.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/lists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/loclists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/lookup.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/op.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/pubnames.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/pubtypes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/reader.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/relocate.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/rnglists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/str.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/unit.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/read/value.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/test_util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/abbrev.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/cfi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/dwarf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/endian_vec.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/line.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/loc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/op.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/range.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/relocate.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/str.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/unit.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.29.0/src/write/writer.rs", ] inputs = [] no_std = true @@ -1061,7 +1065,7 @@ cargo_crate("gimli") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "0.28.1" + cargo_pkg_version = "0.29.0" cargo_pkg_name = "gimli" cargo_pkg_description = "A library for reading and writing the DWARF debugging format." @@ -1098,32 +1102,32 @@ cargo_crate("gimli") { } cargo_crate("hashbrown") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/helpers.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/raw.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/table.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rkyv/hash_map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rkyv/hash_set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rkyv/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/serde.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/bitmask.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/generic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/neon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/sse2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/rustc_entry.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/scopeguard.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rayon/helpers.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rayon/map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rayon/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rayon/raw.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rayon/set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rayon/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rkyv/hash_map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rkyv/hash_set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/rkyv/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/external_trait_impls/serde.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/raw/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/raw/bitmask.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/raw/generic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/raw/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/raw/neon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/raw/sse2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/rustc_entry.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/scopeguard.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.5/src/table.rs", ] inputs = [] no_std = true @@ -1131,7 +1135,7 @@ cargo_crate("hashbrown") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.14.3" + cargo_pkg_version = "0.14.5" cargo_pkg_authors = "Amanieu d'Antras " cargo_pkg_name = "hashbrown" cargo_pkg_description = "A Rust port of Google's SwissTable hash map" @@ -1171,242 +1175,244 @@ cargo_crate("hashbrown") { } cargo_crate("libc") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fixed_width_ints.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/hermit/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/hermit/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/hermit/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/psp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/sgx.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/solid/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/solid/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/solid/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/switch.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/teeos/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/aix/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/aix/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b32/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/aarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/long_array.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/dragonfly/errno.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/dragonfly/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/mips.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/sparc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/mips64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/sparc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/b32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/native.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/b32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b32/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b32/x86/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/aarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/aarch64/int128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/riscv64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/emscripten/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/emscripten/lfs64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/emscripten/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/emscripten/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/generic/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/powerpc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/sparc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/arm/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/csky/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/csky/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/m68k/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/m68k/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/mips/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/riscv32/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/sparc/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/x86/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/mips64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/riscv64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/s390x.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/sparc64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/arm/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/hexagon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/mips/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/riscv32/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/x86/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/aarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/aarch64/int128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/mips64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/riscv64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/s390x.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/lfs64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/non_exhaustive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/arm/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/arm/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips32/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/x86_64/l4re.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/x86_64/other.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/espidf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/generic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/horizon/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/powerpc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/vita/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/nto/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/nto/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/nto/neutrino.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/nto/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/redox/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/compat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/illumos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/solaris.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/x86_common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/wasi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/windows/gnu/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/windows/gnu/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/windows/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/windows/msvc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/xous.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/fixed_width_ints.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/fuchsia/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/fuchsia/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/fuchsia/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/fuchsia/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/fuchsia/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/fuchsia/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/hermit/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/hermit/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/hermit/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/psp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/sgx.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/solid/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/solid/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/solid/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/switch.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/teeos/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/aix/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/aix/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/b32/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/b64/aarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/b64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/b64/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/long_array.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/apple/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/dragonfly/errno.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/dragonfly/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/freebsdlike/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/mips.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/sparc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/netbsd/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/mips64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/sparc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/bsd/netbsdlike/openbsd/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/haiku/b32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/haiku/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/haiku/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/haiku/native.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/haiku/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/hurd/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/hurd/b32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/hurd/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/hurd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/hurd/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b32/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b32/x86/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b64/aarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b64/aarch64/int128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b64/riscv64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b64/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/android/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/emscripten/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/emscripten/lfs64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/emscripten/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/emscripten/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/arch/generic/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/arch/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/arch/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/arch/powerpc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/arch/sparc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/arm/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/csky/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/csky/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/m68k/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/m68k/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/mips/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/riscv32/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/sparc/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/x86/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/aarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/mips64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/riscv64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/s390x.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/sparc64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/gnu/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/arm/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/hexagon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/mips/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/riscv32/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/x86/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/aarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/aarch64/int128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/loongarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/mips64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/riscv64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/s390x.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/lfs64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/musl/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/non_exhaustive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/arm/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/arm/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/mips/mips32/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/mips/mips64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/x86_64/l4re.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/linux/uclibc/x86_64/other.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/linux_like/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/espidf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/generic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/horizon/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/powerpc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/newlib/vita/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/nto/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/nto/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/nto/neutrino.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/nto/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/redox/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/solarish/compat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/solarish/illumos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/solarish/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/solarish/solaris.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/solarish/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/solarish/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/unix/solarish/x86_common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/vxworks/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/vxworks/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/vxworks/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/vxworks/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/vxworks/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/vxworks/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/vxworks/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/wasi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/windows/gnu/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/windows/gnu/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/windows/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/windows/msvc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/src/xous.rs", ] inputs = [] no_std = true @@ -1414,7 +1420,7 @@ cargo_crate("libc") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2015" - cargo_pkg_version = "0.2.153" + cargo_pkg_version = "0.2.155" cargo_pkg_authors = "The Rust Project Developers" cargo_pkg_name = "libc" cargo_pkg_description = "Raw FFI bindings to platform libraries like libc." @@ -1434,8 +1440,8 @@ cargo_crate("libc") { "rustc-dep-of-std", "rustc-std-workspace-core", ] - build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/build.rs" - build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/build.rs" ] + build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/build.rs" + build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.155/build.rs" ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", "STD_ENV_ARCH=$rust_target_arch", @@ -1531,18 +1537,18 @@ cargo_crate("memchr") { } cargo_crate("miniz_oxide") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/deflate/buffer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/deflate/core.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/deflate/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/deflate/stream.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/inflate/core.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/inflate/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/inflate/output_buffer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/inflate/stream.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/shared.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/deflate/buffer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/deflate/core.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/deflate/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/deflate/stream.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/inflate/core.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/inflate/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/inflate/output_buffer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/inflate/stream.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.3/src/shared.rs", ] inputs = [] no_std = true @@ -1550,7 +1556,7 @@ cargo_crate("miniz_oxide") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "0.7.2" + cargo_pkg_version = "0.7.3" cargo_pkg_authors = "Frommi , oyvindln " cargo_pkg_name = "miniz_oxide" cargo_pkg_description = "DEFLATE compression and decompression library rewritten in Rust based on miniz" @@ -1589,82 +1595,87 @@ cargo_crate("miniz_oxide") { } cargo_crate("object") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/archive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/elf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/endian.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/macho.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/pe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/pod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/any.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/archive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/import.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/attributes.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/compression.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/dynamic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/hash.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/note.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/version.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/dyld_cache.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/fat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/load_command.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/data_directory.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/export.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/import.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/resource.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/rich.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/read_cache.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/read_ref.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/wasm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/coff/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/coff/object.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/coff/writer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/elf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/elf/object.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/elf/writer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/macho.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/pe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/string.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/xcoff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/xcoff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/archive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/build/bytes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/build/elf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/build/error.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/build/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/build/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/elf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/endian.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/macho.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/pe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/pod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/any.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/archive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/coff/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/coff/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/coff/import.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/coff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/coff/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/coff/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/coff/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/attributes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/compression.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/dynamic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/hash.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/note.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/elf/version.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/dyld_cache.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/fat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/load_command.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/macho/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/data_directory.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/export.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/import.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/resource.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/rich.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/pe/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/read_cache.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/read_ref.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/wasm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/xcoff/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/xcoff/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/xcoff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/xcoff/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/xcoff/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/xcoff/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/read/xcoff/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/coff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/coff/object.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/coff/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/elf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/elf/object.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/elf/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/macho.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/pe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/string.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/write/xcoff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.36.0/src/xcoff.rs", ] inputs = [] no_std = true @@ -1672,7 +1683,7 @@ cargo_crate("object") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "0.32.2" + cargo_pkg_version = "0.36.0" cargo_pkg_name = "object" cargo_pkg_description = "A unified interface for reading and writing object file formats." @@ -1824,6 +1835,7 @@ cargo_crate("proc_macro") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/proc_macro/src/bridge/server.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/proc_macro/src/bridge/symbol.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/proc_macro/src/diagnostic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/proc_macro/src/escape.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/proc_macro/src/lib.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/proc_macro/src/quote.rs", ] @@ -1893,11 +1905,11 @@ cargo_crate("profiler_builtins") { } cargo_crate("rustc_demangle") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/rustc-demangle-0.1.23/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/rustc-demangle-0.1.24/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/rustc-demangle-0.1.23/src/legacy.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/rustc-demangle-0.1.23/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/rustc-demangle-0.1.23/src/v0.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/rustc-demangle-0.1.24/src/legacy.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/rustc-demangle-0.1.24/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/rustc-demangle-0.1.24/src/v0.rs", ] inputs = [] no_std = true @@ -1905,7 +1917,7 @@ cargo_crate("rustc_demangle") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2015" - cargo_pkg_version = "0.1.23" + cargo_pkg_version = "0.1.24" cargo_pkg_authors = "Alex Crichton " cargo_pkg_name = "rustc-demangle" cargo_pkg_description = "Rust compiler symbol demangling." @@ -2327,6 +2339,7 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/fd.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/fs.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/futex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/io.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/net.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/os.rs", @@ -2581,7 +2594,9 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sync/thread_parking/unsupported.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sync/thread_parking/windows.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sync/thread_parking/xous.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/fast_local.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/fast_local/eager.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/fast_local/lazy.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/fast_local/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/os_local.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/thread_local/static_local.rs", @@ -2659,6 +2674,7 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/ffi/c_ulonglong.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/ffi/c_ushort.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/ffi/c_void.md", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/fmt/fmt_trait_method_doc.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/macros/panic.md", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../core/src/primitive_docs.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/../../portable-simd/crates/core_simd/src/core_simd_docs.md", @@ -2703,9 +2719,6 @@ cargo_crate("std") { ":object", ] } - if (is_win) { - deps += [ ":libc" ] - } features = [ "addr2line", "backtrace", @@ -2873,8 +2886,6 @@ cargo_crate("test") { deps = [ ":core", ":getopts", - ":panic_abort", - ":panic_unwind", ":std", "//build/rust/std:profiler_builtins_group", "//build/rust/std:std_build_deps", @@ -2895,19 +2906,18 @@ cargo_crate("test") { } cargo_crate("unicode_width") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.11/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.13/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.11/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.11/src/tables.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.11/src/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.13/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.13/src/tables.rs", ] inputs = [] no_std = true # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false - edition = "2015" - cargo_pkg_version = "0.1.11" + edition = "2021" + cargo_pkg_version = "0.1.13" cargo_pkg_authors = "kwantam , Manish Goregaokar " cargo_pkg_name = "unicode-width" diff --git a/naiveproxy/src/build/rust/tests/BUILD.gn b/naiveproxy/src/build/rust/tests/BUILD.gn index 5dc10465f8..4d2d3b0ab4 100644 --- a/naiveproxy/src/build/rust/tests/BUILD.gn +++ b/naiveproxy/src/build/rust/tests/BUILD.gn @@ -47,7 +47,7 @@ group("deps") { if (enable_chromium_prelude) { deps += [ "//build/rust/chromium_prelude:import_test" ] } - if (enable_cxx) { + if (enable_rust_cxx) { deps += [ "//build/rust/tests/test_cpp_including_rust", "//build/rust/tests/test_rust_calling_cpp", @@ -80,7 +80,7 @@ group("deps") { #"test_rs_bindings_from_cc:test_rs_bindings_from_cc_unittests", ] - if (enable_cxx) { + if (enable_rust_cxx) { deps += [ "//build/rust/tests/test_cpp_including_rust:test_cpp_including_rust_unittests", "//build/rust/tests/test_rust_exe:test_rust_exe_unittests", @@ -93,7 +93,7 @@ group("deps") { # Dylibs should only be built in component builds. We turn on flags which # are incompatible with shared library compilation in non-component builds # (such as code coverage https://crbug.com/1457533). - if (is_component_build && enable_cxx) { + if (is_component_build && enable_rust_cxx) { deps += [ "//build/rust/tests/test_rust_shared_library" ] if (can_build_rust_unit_tests) { deps += [ "//build/rust/tests/test_cpp_including_rust:test_cpp_including_rust_dylib_unittests" ] diff --git a/naiveproxy/src/build/rust/tests/test_cpp_including_rust/shared_unittests.cc b/naiveproxy/src/build/rust/tests/test_cpp_including_rust/shared_unittests.cc index afa0938e6f..8a6f266c88 100644 --- a/naiveproxy/src/build/rust/tests/test_cpp_including_rust/shared_unittests.cc +++ b/naiveproxy/src/build/rust/tests/test_cpp_including_rust/shared_unittests.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include #include -#include "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h" -#include "build/buildflag.h" +#include "base/allocator/partition_allocator/src/partition_alloc/buildflags.h" #include "build/rust/tests/test_rust_shared_library/src/lib.rs.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,3 +35,38 @@ TEST(RustSharedTest, RustComponentUsesPartitionAlloc) { TEST(RustSharedTest, AllocAligned) { alloc_aligned(); } + +// TODO(crbug.com/343218479): A rust_shared_library target does not use our +// allocation shim so it is not properly redirected to PartitionAlloc (though is +// happens to use PA on Linux since the std allocator calls malloc). To enable +// this, we need to insert the allocation shim into `rust_shared_library`, +// probably by having the template produce a Rust static library and having +// clang do the linking step. +TEST(RustSharedTest, DISABLED_RustLargeAllocationFailure) { + // If allocation succeeds, we get true back. + EXPECT_TRUE(allocate_huge_via_rust(100u, 1u)); + +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + // We only do these tests when using PA, as the system allocator will not fail + // on large allocations (unless it is really OOM). + + // PartitionAlloc currently limits all allocations to no more than i32::MAX + // elements, so the allocation will fail. If done through normal malloc(), + // PA will crash when an allocation fails rather than return null, but Rust + // can be trusted to handle failure without introducing null derefs so this + // should fail gracefully. + size_t max_size = partition_alloc::internal::MaxDirectMapped(); + EXPECT_FALSE(allocate_huge_via_rust(max_size + 1u, 4u)); + + // Same as above but with an alignment larger than PartitionAlloc's default + // alignment, which goes down a different path. + size_t big_alignment = alignof(std::max_align_t) * 2u; + EXPECT_FALSE(allocate_huge_via_rust(max_size + 1u, big_alignment)); + + // PartitionAlloc will crash if given an alignment larger than this. The + // allocation hooks handle it gracefully. + size_t max_alignment = partition_alloc::internal::kMaxSupportedAlignment; + EXPECT_FALSE(allocate_huge_via_rust(100u, max_alignment * 2u)); + +#endif +} diff --git a/naiveproxy/src/build/rust/tests/test_cpp_including_rust/static_unittests.cc b/naiveproxy/src/build/rust/tests/test_cpp_including_rust/static_unittests.cc index 759241b4f8..51ca114e78 100644 --- a/naiveproxy/src/build/rust/tests/test_cpp_including_rust/static_unittests.cc +++ b/naiveproxy/src/build/rust/tests/test_cpp_including_rust/static_unittests.cc @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include +#include #include -#include "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h" -#include "build/buildflag.h" +#include "base/allocator/partition_allocator/src/partition_alloc/buildflags.h" #include "build/rust/tests/test_rust_static_library/src/lib.rs.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,3 +36,46 @@ TEST(RustStaticTest, RustComponentUsesPartitionAlloc) { TEST(RustStaticTest, AllocAligned) { alloc_aligned(); } + +TEST(RustStaticTest, RustLargeAllocationFailure) { + // A small allocation that should always succeed. If allocation succeeds, we + // get true back. + EXPECT_TRUE(allocate_huge_via_rust(100u, 1u)); + +#if PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + // We only do these tests when using PA, as the system allocator will not fail + // on large allocations (unless it is really OOM). + + // PartitionAlloc currently limits all allocations to no more than i32::MAX + // elements, so the allocation will fail. If done through normal malloc(), + // PA will crash when an allocation fails rather than return null, but Rust + // can be trusted to handle failure without introducing null derefs so this + // should fail gracefully. + size_t max_size = partition_alloc::internal::MaxDirectMapped(); + EXPECT_FALSE(allocate_huge_via_rust(max_size + 1u, 4u)); + + // Same as above but with an alignment larger than PartitionAlloc's default + // alignment, which goes down a different path. + size_t big_alignment = alignof(std::max_align_t) * 2u; + EXPECT_FALSE(allocate_huge_via_rust(max_size + 1u, big_alignment)); + + // PartitionAlloc will crash if given an alignment larger than this. The + // allocation hooks handle it gracefully. + size_t max_alignment = partition_alloc::internal::kMaxSupportedAlignment; + EXPECT_FALSE(allocate_huge_via_rust(100u, max_alignment * 2u)); + + // Repeat the test but with alloc_zeroed(). + EXPECT_TRUE(allocate_zeroed_huge_via_rust(100u, 1u)); + EXPECT_FALSE(allocate_zeroed_huge_via_rust(max_size + 1u, 4u)); + EXPECT_FALSE(allocate_zeroed_huge_via_rust(max_size + 1u, big_alignment)); + EXPECT_FALSE(allocate_zeroed_huge_via_rust(100u, max_alignment * 2u)); + + // Repeat the test but with realloc(). + EXPECT_TRUE(reallocate_huge_via_rust(100u, 1u)); + EXPECT_FALSE(reallocate_huge_via_rust(max_size + 1u, 4u)); + EXPECT_FALSE(reallocate_huge_via_rust(max_size + 1u, big_alignment)); + // Note: We don't test with `max_alignment * 2` since the initial allocation + // will always fail, the realloc can't happen anyway. + +#endif +} diff --git a/naiveproxy/src/build/rust/tests/test_rlib_crate/BUILD.gn b/naiveproxy/src/build/rust/tests/test_rlib_crate/BUILD.gn index 9410316a2d..953cebb24d 100644 --- a/naiveproxy/src/build/rust/tests/test_rlib_crate/BUILD.gn +++ b/naiveproxy/src/build/rust/tests/test_rlib_crate/BUILD.gn @@ -10,6 +10,7 @@ cargo_crate("target1") { sources = [ "crate/src/lib.rs" ] build_sources = [ "crate/build.rs" ] build_root = "crate/build.rs" + build_script_inputs = [ "crate/build.rs" ] build_script_outputs = [ "generated/generated.rs" ] epoch = "0.2" features = [ @@ -31,6 +32,7 @@ cargo_crate("target2") { sources = [ "crate/src/lib.rs" ] build_sources = [ "crate/build.rs" ] build_root = "crate/build.rs" + build_script_inputs = [ "crate/build.rs" ] build_script_outputs = [ "generated/generated.rs" ] epoch = "0.2" features = [ "my-feature_a" ] @@ -46,6 +48,7 @@ cargo_crate("test_rlib_crate_associated_bin") { sources = [ "crate/src/main.rs" ] build_sources = [ "crate/build.rs" ] build_root = "crate/build.rs" + build_script_inputs = [ "crate/build.rs" ] features = [ "my-feature_a", "my-feature_b", diff --git a/naiveproxy/src/build/rust/tests/test_rust_shared_library/src/lib.rs b/naiveproxy/src/build/rust/tests/test_rust_shared_library/src/lib.rs index c2440b9686..29492540ad 100644 --- a/naiveproxy/src/build/rust/tests/test_rust_shared_library/src/lib.rs +++ b/naiveproxy/src/build/rust/tests/test_rust_shared_library/src/lib.rs @@ -12,8 +12,9 @@ mod ffi { extern "Rust" { fn say_hello(); fn alloc_aligned(); - fn allocate_via_rust() -> Box; fn add_two_ints_via_rust(x: i32, y: i32) -> i32; + fn allocate_via_rust() -> Box; + fn allocate_huge_via_rust(size: usize, align: usize) -> bool; } } @@ -40,8 +41,20 @@ pub fn add_two_ints_via_rust(x: i32, y: i32) -> i32 { x + y } -// The next function is used from the RustComponentUsesPartitionAlloc unit -// tests. +// Used from the RustComponentUsesPartitionAlloc unit tests. pub fn allocate_via_rust() -> Box { Box::new(ffi::SomeStruct { a: 43 }) } + +// Used from the RustLargeAllocationFailure unit tests. +pub fn allocate_huge_via_rust(size: usize, align: usize) -> bool { + let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); + let p = unsafe { std::alloc::alloc(layout) }; + // Rust can optimize out allocations. By printing the pointer value we ensure + // the allocation actually happens (and can thus fail). + dbg!(p); + if !p.is_null() { + unsafe { std::alloc::dealloc(p, layout) }; + } + !p.is_null() +} diff --git a/naiveproxy/src/build/rust/tests/test_rust_static_library/src/lib.rs b/naiveproxy/src/build/rust/tests/test_rust_static_library/src/lib.rs index a5a1e904c4..73460a7821 100644 --- a/naiveproxy/src/build/rust/tests/test_rust_static_library/src/lib.rs +++ b/naiveproxy/src/build/rust/tests/test_rust_static_library/src/lib.rs @@ -12,8 +12,11 @@ mod ffi { extern "Rust" { fn say_hello(); fn alloc_aligned(); - fn allocate_via_rust() -> Box; fn add_two_ints_via_rust(x: i32, y: i32) -> i32; + fn allocate_via_rust() -> Box; + fn allocate_huge_via_rust(size: usize, align: usize) -> bool; + fn allocate_zeroed_huge_via_rust(size: usize, align: usize) -> bool; + fn reallocate_huge_via_rust(size: usize, align: usize) -> bool; } } @@ -52,3 +55,45 @@ mod tests { // Always passes; just to see if tests in modules are handled correctly. } } + +// Used from the RustLargeAllocationFailure unit tests. +pub fn allocate_huge_via_rust(size: usize, align: usize) -> bool { + let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); + let p = unsafe { std::alloc::alloc(layout) }; + // Rust can optimize out allocations. By printing the pointer value we ensure + // the allocation actually happens (and can thus fail). + dbg!(p); + if !p.is_null() { + unsafe { std::alloc::dealloc(p, layout) }; + } + !p.is_null() +} + +// Used from the RustLargeAllocationFailure unit tests. +pub fn allocate_zeroed_huge_via_rust(size: usize, align: usize) -> bool { + let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); + let p = unsafe { std::alloc::alloc_zeroed(layout) }; + // Rust can optimize out allocations. By printing the pointer value we ensure + // the allocation actually happens (and can thus fail). + dbg!(p); + if !p.is_null() { + unsafe { std::alloc::dealloc(p, layout) }; + } + !p.is_null() +} + +// Used from the RustLargeAllocationFailure unit tests. +pub fn reallocate_huge_via_rust(size: usize, align: usize) -> bool { + let layout = std::alloc::Layout::from_size_align(align, align).unwrap(); + let p = unsafe { std::alloc::alloc(layout) }; + assert!(!p.is_null()); + let p = unsafe { std::alloc::realloc(p, layout, size) }; + let layout = std::alloc::Layout::from_size_align(size, align).unwrap(); + // Rust can optimize out allocations. By printing the pointer value we ensure + // the allocation actually happens (and can thus fail). + dbg!(p); + if !p.is_null() { + unsafe { std::alloc::dealloc(p, layout) }; + } + !p.is_null() +} diff --git a/naiveproxy/src/build/sanitizers/OWNERS b/naiveproxy/src/build/sanitizers/OWNERS index 09f2efa99a..7d6af61b6b 100644 --- a/naiveproxy/src/build/sanitizers/OWNERS +++ b/naiveproxy/src/build/sanitizers/OWNERS @@ -1,6 +1,5 @@ eugenis@chromium.org glider@chromium.org -metzman@chromium.org rnk@chromium.org per-file tsan_suppressions.cc=* per-file lsan_suppressions.cc=* diff --git a/naiveproxy/src/build/sanitizers/asan_suppressions.cc b/naiveproxy/src/build/sanitizers/asan_suppressions.cc index 601b79e034..24fcf8c6ed 100644 --- a/naiveproxy/src/build/sanitizers/asan_suppressions.cc +++ b/naiveproxy/src/build/sanitizers/asan_suppressions.cc @@ -25,6 +25,7 @@ char kASanDefaultSuppressions[] = "odr_violation:^std::thread::Builder::\n" "odr_violation:^read_fonts::tables::\n" "odr_violation:^std_detect::detect::cache::\n" + "odr_violation:^alloc::sync::\n" // End of suppressions. // PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS. diff --git a/naiveproxy/src/build/toolchain/android/BUILD.gn b/naiveproxy/src/build/toolchain/android/BUILD.gn index d857317d0e..6597b54222 100644 --- a/naiveproxy/src/build/toolchain/android/BUILD.gn +++ b/naiveproxy/src/build/toolchain/android/BUILD.gn @@ -143,7 +143,7 @@ clang_toolchain("robolectric_$host_cpu") { # Forwarding this value from the primary toolchain to the secondary # robolectric toolchain, since the default depends on is_component_build # which can be different between primary and robolectric. - allow_jni_multiplexing = allow_jni_multiplexing + enable_jni_multiplexing = enable_jni_multiplexing } } diff --git a/naiveproxy/src/build/toolchain/apple/toolchain.gni b/naiveproxy/src/build/toolchain/apple/toolchain.gni index 9e138aacd8..acd5a59f5e 100644 --- a/naiveproxy/src/build/toolchain/apple/toolchain.gni +++ b/naiveproxy/src/build/toolchain/apple/toolchain.gni @@ -792,6 +792,68 @@ template("single_apple_toolchain") { } } +# Make an additional toolchain which is used for making tools that are run +# on the host machine as part of the build process (such as proc macros +# and Cargo build scripts). This toolchain uses the prebuilt stdlib that +# comes with the compiler, so it doesn't have to wait for the stdlib to be +# built before building other stuff. And this ensures its proc macro +# outputs have the right ABI to be loaded by the compiler, and it can be +# used to compile build scripts that are part of the stdlib that is built +# for the default toolchain. +template("apple_rust_host_build_tools_toolchain") { + single_apple_toolchain(target_name) { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + TESTONLY_AND_VISIBILITY + [ "toolchain_args" ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_for_rust_host_build_tools = true + + # The host build tools are static release builds to make the Chromium + # build faster. They do not need PGO etc, so no official builds. + is_debug = false + is_component_build = false + is_official_build = false + use_clang_coverage = false + use_sanitizer_coverage = false + generate_linker_map = false + use_thin_lto = false + } + } +} + +# If PartitionAlloc is part of the build (even as a transitive dependency), then +# it replaces the system allocator. If this toolchain is used, that will be +# overridden and the system allocator will be used regardless. This is important +# in some third-party binaries outside of Chrome. +template("apple_system_allocator_toolchain") { + single_apple_toolchain(target_name) { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + TESTONLY_AND_VISIBILITY + [ "toolchain_args" ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_allows_use_partition_alloc_as_malloc = false + + # Disable component build so that we can copy the exes to the + # root_build_dir and support the default_toolchain redirection on Windows. + # See also the comment in //build/symlink.gni. + is_component_build = false + + # Only one toolchain can be configured with MSAN support with our current + # GN setup, or they all try to make the instrumented libraries and + # collide. + is_msan = false + } + } +} + # Makes an Apple toolchain for the target, and an equivalent toolchain with the # prebuilt Rust stdlib for building proc macros (and other for-build-use # artifacts). @@ -799,51 +861,28 @@ template("apple_toolchain") { single_apple_toolchain(target_name) { assert(defined(invoker.toolchain_args), "Toolchains must declare toolchain_args") - forward_variables_from(invoker, - "*", - [ - "visibility", - "test_only", - ]) + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) # No need to forward visibility and test_only as they apply to targets not # toolchains, but presubmit checks require that we explicitly exclude them } - if (enable_rust && current_toolchain == default_toolchain) { - # Make an additional toolchain which is used for making tools that are run - # on the host machine as part of the build process (such as proc macros - # and Cargo build scripts). This toolchain uses the prebuilt stdlib that - # comes with the compiler, so it doesn't have to wait for the stdlib to be - # built before building other stuff. And this ensures its proc macro - # outputs have the right ABI to be loaded by the compiler, and it can be - # used to compile build scripts that are part of the stdlib that is built - # for the default toolchain. - single_apple_toolchain("${target_name}_for_rust_host_build_tools") { - assert(defined(invoker.toolchain_args), - "Toolchains must declare toolchain_args") - forward_variables_from(invoker, - "*", - [ - "toolchain_args", - "visibility", - "test_only", - ]) - toolchain_args = { - # Populate toolchain args from the invoker. - forward_variables_from(invoker.toolchain_args, "*") - toolchain_for_rust_host_build_tools = true + apple_rust_host_build_tools_toolchain( + "${target_name}_for_rust_host_build_tools") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + } - # The host build tools are static release builds to make the Chromium - # build faster. They do not need PGO etc, so no official builds. - is_debug = false - is_component_build = false - is_official_build = false - use_clang_coverage = false - use_sanitizer_coverage = false - generate_linker_map = false - use_thin_lto = false - } - } + apple_system_allocator_toolchain( + "${target_name}_host_with_system_allocator") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + } + apple_system_allocator_toolchain("${target_name}_with_system_allocator") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) } } diff --git a/naiveproxy/src/build/toolchain/clang_code_coverage_wrapper.py b/naiveproxy/src/build/toolchain/clang_code_coverage_wrapper.py index 51653f5a2c..9c38d71228 100755 --- a/naiveproxy/src/build/toolchain/clang_code_coverage_wrapper.py +++ b/naiveproxy/src/build/toolchain/clang_code_coverage_wrapper.py @@ -87,7 +87,6 @@ _COVERAGE_EXCLUSION_LIST_MAP = { 'fuchsia': [ # TODO(crbug.com/40167659): These files caused clang to crash while # compiling them. - '../../base/allocator/partition_allocator/src/partition_alloc/pcscan.cc', '../../third_party/skia/src/core/SkOpts.cpp', '../../third_party/skia/src/opts/SkOpts_hsw.cpp', '../../third_party/skia/third_party/skcms/skcms.cc', diff --git a/naiveproxy/src/build/toolchain/concurrent_links.gni b/naiveproxy/src/build/toolchain/concurrent_links.gni index 95043e69f8..07aebd8c9f 100644 --- a/naiveproxy/src/build/toolchain/concurrent_links.gni +++ b/naiveproxy/src/build/toolchain/concurrent_links.gni @@ -35,7 +35,7 @@ if (concurrent_links == -1) { _args += [ "--mem_per_link_gb=45" ] } else if (is_android) { # Large solink of Android official builds take 30-60GB. - _args += [ "--mem_per_link_gb=30" ] + _args += [ "--mem_per_link_gb=50" ] } else if (is_linux) { # OOM quite frequently for linux. _args += [ "--mem_per_link_gb=30" ] diff --git a/naiveproxy/src/build/toolchain/gcc_toolchain.gni b/naiveproxy/src/build/toolchain/gcc_toolchain.gni index 09f1f39208..1dc27be222 100644 --- a/naiveproxy/src/build/toolchain/gcc_toolchain.gni +++ b/naiveproxy/src/build/toolchain/gcc_toolchain.gni @@ -141,8 +141,10 @@ template("single_gcc_toolchain") { "toolchain_args must specify a current_os") # use_reclient is default to use_remoteexec - if (!defined(invoker_toolchain_args.use_reclient) && defined(invoker_toolchain_args.use_remoteexec)) { - invoker_toolchain_args.use_reclient = invoker_toolchain_args.use_remoteexec + if (!defined(invoker_toolchain_args.use_reclient) && + defined(invoker_toolchain_args.use_remoteexec)) { + invoker_toolchain_args.use_reclient = + invoker_toolchain_args.use_remoteexec } # When invoking this toolchain not as the default one, these args will be @@ -796,6 +798,72 @@ template("single_gcc_toolchain") { } } +# Make an additional toolchain which is used for making tools that are run +# on the host machine as part of the build process (such as proc macros +# and Cargo build scripts). This toolchain uses the prebuilt stdlib that +# comes with the compiler, so it doesn't have to wait for the stdlib to be +# built before building other stuff. And this ensures its proc macro +# outputs have the right ABI to be loaded by the compiler, and it can be +# used to compile build scripts that are part of the stdlib that is built +# for the default toolchain. +template("gcc_rust_host_build_tools_toolchain") { + single_gcc_toolchain(target_name) { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + TESTONLY_AND_VISIBILITY + [ "toolchain_args" ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_for_rust_host_build_tools = true + + # The host build tools are static release builds to make the Chromium + # build faster. + is_debug = false + is_component_build = false + is_official_build = false + use_clang_coverage = false + use_sanitizer_coverage = false + generate_linker_map = false + use_thin_lto = false + } + + # When cross-compiling we don't want to use the target platform's file + # extensions. + shlib_extension = host_shlib_extension + } +} + +# If PartitionAlloc is part of the build (even as a transitive dependency), then +# it replaces the system allocator. If this toolchain is used, that will be +# overridden and the system allocator will be used regardless. This is important +# in some third-party binaries outside of Chrome. +template("gcc_system_allocator_toolchain") { + single_gcc_toolchain(target_name) { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + TESTONLY_AND_VISIBILITY + [ "toolchain_args" ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_allows_use_partition_alloc_as_malloc = false + + # Disable component build so that we can copy the exes to the + # root_build_dir and support the default_toolchain redirection on Windows. + # See also the comment in //build/symlink.gni. + is_component_build = false + + # Only one toolchain can be configured with MSAN support with our current + # GN setup, or they all try to make the instrumented libraries and + # collide. + is_msan = false + } + } +} + # Makes a GCC toolchain for the target, and an equivalent toolchain with the # prebuilt Rust stdlib for building proc macros (and other for-build-use # artifacts). @@ -803,56 +871,28 @@ template("gcc_toolchain") { single_gcc_toolchain(target_name) { assert(defined(invoker.toolchain_args), "Toolchains must declare toolchain_args") - forward_variables_from(invoker, - "*", - [ - "visibility", - "test_only", - ]) + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) # No need to forward visibility and test_only as they apply to targets not # toolchains, but presubmit checks require that we explicitly exclude them } - if (enable_rust && current_toolchain == default_toolchain) { - # Make an additional toolchain which is used for making tools that are run - # on the host machine as part of the build process (such as proc macros - # and Cargo build scripts). This toolchain uses the prebuilt stdlib that - # comes with the compiler, so it doesn't have to wait for the stdlib to be - # built before building other stuff. And this ensures its proc macro - # outputs have the right ABI to be loaded by the compiler, and it can be - # used to compile build scripts that are part of the stdlib that is built - # for the default toolchain. - single_gcc_toolchain("${target_name}_for_rust_host_build_tools") { - assert(defined(invoker.toolchain_args), - "Toolchains must declare toolchain_args") - forward_variables_from(invoker, - "*", - [ - "toolchain_args", - "visibility", - "test_only", - ]) - toolchain_args = { - # Populate toolchain args from the invoker. - forward_variables_from(invoker.toolchain_args, "*") - toolchain_for_rust_host_build_tools = true + gcc_rust_host_build_tools_toolchain( + "${target_name}_for_rust_host_build_tools") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + } - # The host build tools are static release builds to make the Chromium - # build faster. - is_debug = false - is_component_build = false - is_official_build = false - use_clang_coverage = false - use_sanitizer_coverage = false - generate_linker_map = false - use_thin_lto = false - } - - # When cross-compiling we don't want to use the target platform's file - # extensions. - shlib_extension = host_shlib_extension - } + gcc_system_allocator_toolchain("${target_name}_host_with_system_allocator") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + } + gcc_system_allocator_toolchain("${target_name}_with_system_allocator") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) } } diff --git a/naiveproxy/src/build/toolchain/ios/compile_xcassets.py b/naiveproxy/src/build/toolchain/ios/compile_xcassets.py index 09ee2c154e..0171cb764d 100644 --- a/naiveproxy/src/build/toolchain/ios/compile_xcassets.py +++ b/naiveproxy/src/build/toolchain/ios/compile_xcassets.py @@ -79,6 +79,11 @@ def FilterCompilerOutput(compiler_output, relative_paths): current_section = None data_in_section = False for line in compiler_output.splitlines(): + # TODO:(crbug.com/348008793): Ignore Dark and Tintable App Icon unassigned + # children warning when building with Xcode 15 + if 'The app icon set "AppIcon" has 2 unassigned children' in line: + continue + match = SECTION_HEADER.search(line) if match is not None: data_in_section = False diff --git a/naiveproxy/src/build/toolchain/ios/swiftc.py b/naiveproxy/src/build/toolchain/ios/swiftc.py index 6f82245489..c4c0a07dbc 100644 --- a/naiveproxy/src/build/toolchain/ios/swiftc.py +++ b/naiveproxy/src/build/toolchain/ios/swiftc.py @@ -436,6 +436,13 @@ def invoke_swift_compiler(args, extras_args, build_cache_dir, output_file_map): f'-j{num_threads}', ]) + # Handle -file-prefix-map flag. + if args.file_prefix_map: + swiftc_args.extend([ + '-file-prefix-map', + args.file_prefix_map, + ]) + swift_toolchain_path = args.swift_toolchain_path if not swift_toolchain_path: swift_toolchain_path = os.path.join(os.path.dirname(args.sdk_path), @@ -624,8 +631,9 @@ def main(args): default='5', help='version of the Swift language') - parser.add_argument('-file-compilation-dir', - help='compilation directory to embed in debug info') + parser.add_argument( + '-file-prefix-map', + help='remap source paths in debug, coverage, and index info') # Positional arguments. parser.add_argument('sources', diff --git a/naiveproxy/src/build/toolchain/toolchain.gni b/naiveproxy/src/build/toolchain/toolchain.gni index 14aa5f76d3..6794edc819 100644 --- a/naiveproxy/src/build/toolchain/toolchain.gni +++ b/naiveproxy/src/build/toolchain/toolchain.gni @@ -30,6 +30,10 @@ declare_args() { # consumed during the build process. That includes proc macros and Cargo build # scripts. toolchain_for_rust_host_build_tools = false + + # If false, the toolchain overrides `use_partition_alloc_as_malloc` in + # PartitionAlloc, to allow use of the system allocator. + toolchain_allows_use_partition_alloc_as_malloc = true } if (generate_linker_map) { @@ -68,7 +72,7 @@ if (host_os == "mac") { host_shlib_extension = ".dylib" } else if (host_os == "win") { host_shlib_extension = ".dll" -} else if (host_os == "linux" || host_os == "aix") { +} else if (host_os == "linux" || host_os == "aix" || host_os == "zos") { host_shlib_extension = ".so" } else { assert(false, "Host platform not supported") @@ -116,3 +120,15 @@ if (host_os == "win") { is_a_target_toolchain = (current_toolchain != host_toolchain || default_toolchain == host_toolchain) && current_os == target_os + +# A toolchain for building tools that run on the host machine and need to use +# the system allocator. This toolchain does not use PartitionAlloc-Everywhere by +# design. We use a name with `_host` injected into it to avoid colliding with +# toolchains of the same name (but different path) between different OSes. +host_system_allocator_toolchain = "${host_toolchain}_host_with_system_allocator" + +# A toolchain for building tools that run on the default target machine and need +# to use the system allocator. This toolchain does not use +# PartitionAlloc-Everywhere by design. +default_system_allocator_toolchain = + "${default_toolchain}_with_system_allocator" diff --git a/naiveproxy/src/build/toolchain/win/toolchain.gni b/naiveproxy/src/build/toolchain/win/toolchain.gni index c2d8d3aab1..3d7ab8877d 100644 --- a/naiveproxy/src/build/toolchain/win/toolchain.gni +++ b/naiveproxy/src/build/toolchain/win/toolchain.gni @@ -589,36 +589,71 @@ template("msvc_toolchain") { } } +# Make an additional toolchain which is used for making tools that are run +# on the host machine as part of the build process (such as proc macros +# and Cargo build scripts). This toolchain uses the prebuilt stdlib that +# comes with the compiler, so it doesn't have to wait for the stdlib to be +# built before building other stuff. And this ensures its proc macro +# outputs have the right ABI to be loaded by the compiler, and it can be +# used to compile build scripts that are part of the stdlib that is built +# for the default toolchain. template("msvc_rust_host_build_tools_toolchain") { - assert(defined(invoker.toolchain_args)) - if (enable_rust) { - msvc_toolchain("${target_name}_for_rust_host_build_tools") { - forward_variables_from(invoker, - "*", - [ - "toolchain_args", - "visibility", - "testonly", - ]) - toolchain_args = { - # Populate toolchain args from the invoker. - forward_variables_from(invoker.toolchain_args, "*") - toolchain_for_rust_host_build_tools = true + msvc_toolchain(target_name) { + assert(defined(invoker.toolchain_args)) + forward_variables_from(invoker, + "*", + [ + "toolchain_args", + "visibility", + "testonly", + ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_for_rust_host_build_tools = true - # The host build tools are static release builds to make the Chromium - # build faster. They do not need PGO etc, so no official builds. - is_debug = false - is_component_build = false - is_official_build = false - use_clang_coverage = false - use_sanitizer_coverage = false - generate_linker_map = false - use_thin_lto = false - } + # The host build tools are static release builds to make the Chromium + # build faster. They do not need PGO etc, so no official builds. + is_debug = false + is_component_build = false + is_official_build = false + use_clang_coverage = false + use_sanitizer_coverage = false + generate_linker_map = false + use_thin_lto = false + } + } +} + +# If PartitionAlloc is part of the build (even as a transitive dependency), then +# it replaces the system allocator. If this toolchain is used, that will be +# overridden and the system allocator will be used regardless. This is important +# in some third-party binaries outside of Chrome. +template("msvc_system_allocator_toolchain") { + msvc_toolchain(target_name) { + assert(defined(invoker.toolchain_args)) + forward_variables_from(invoker, + "*", + [ + "toolchain_args", + "visibility", + "testonly", + ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_allows_use_partition_alloc_as_malloc = false + + # Disable component build so that we can copy the exes to the + # root_build_dir and support the default_toolchain redirection on Windows. + # See also the comment in //build/symlink.gni. + is_component_build = false + + # Only one toolchain can be configured with MSAN support with our current + # GN setup, or they all try to make the instrumented libraries and + # collide. + is_msan = false } - } else { - not_needed(invoker, "*") - not_needed([ "target_name" ]) } } @@ -628,12 +663,12 @@ template("win_toolchains") { # //build/config/BUILDCONFIG.gn). But the prebuilt stdlib does not # exist for Windows x86 and it's exceedingly difficult to get it # built from a single build_rust.py invocation. So we just don't follow - # along in the `msvc_rust_host_build_tools_toolchain` toolchains, and - # always use the host cpu type (which will be x64 in that case). Things - # built with these toolchains are never built for the target_cpu anyhow, - # so the optimization there does not benefit them. + # along in the `build_tools_toolchain` toolchains, and always use the host + # cpu type (which will be x64 in that case). Things built with these + # toolchains are never built for the target_cpu anyhow, so the optimization + # there does not benefit them. # - # Thus, in msvc_rust_host_build_tools_toolchain: + # Thus, in build_tools_toolchain, for the host machine: # * Use `rust_host_toolchain_arch` instead of `toolchain_arch`. # * Use `rust_host_win_toolchain_data` instead of `win_toolchain_data`. @@ -652,7 +687,7 @@ template("win_toolchains") { error("Unsupported toolchain_arch, add it to win_toolchain_data.gni") } - # The toolchain data for `msvc_rust_host_build_tools_toolchain()`. + # The toolchain data for `build_tools_toolchain` for the host machine. if (rust_host_toolchain_arch == "x86") { rust_host_win_toolchain_data = win_toolchain_data_x86 } else if (rust_host_toolchain_arch == "x64") { @@ -687,7 +722,38 @@ template("win_toolchains") { current_cpu = toolchain_arch } } - msvc_rust_host_build_tools_toolchain(cl_toolchain_prefix + target_name) { + msvc_system_allocator_toolchain( + cl_toolchain_prefix + target_name + "_host_with_system_allocator") { + environment = "environment." + rust_host_toolchain_arch + cl = "\"${rust_host_win_toolchain_data.vc_bin_dir}/cl.exe\"" + + toolchain_args = { + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + is_clang = false + use_clang_coverage = false + current_os = "win" + current_cpu = rust_host_toolchain_arch + } + } + msvc_system_allocator_toolchain( + cl_toolchain_prefix + target_name + "_with_system_allocator") { + environment = "environment." + toolchain_arch + cl = "\"${win_toolchain_data.vc_bin_dir}/cl.exe\"" + + toolchain_args = { + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + is_clang = false + use_clang_coverage = false + current_os = "win" + current_cpu = toolchain_arch + } + } + msvc_rust_host_build_tools_toolchain( + cl_toolchain_prefix + target_name + "_for_rust_host_build_tools") { environment = "environment." + rust_host_toolchain_arch cl = "\"${rust_host_win_toolchain_data.vc_bin_dir}/cl.exe\"" @@ -736,7 +802,48 @@ template("win_toolchains") { current_cpu = toolchain_arch } } - msvc_rust_host_build_tools_toolchain(clang_toolchain_prefix + target_name) { + msvc_system_allocator_toolchain( + clang_toolchain_prefix + target_name + "_host_with_system_allocator") { + environment = "environment." + rust_host_toolchain_arch + cl = "${_clang_bin_path}/clang-cl${_exe}" + + sys_include_flags = "${rust_host_win_toolchain_data.include_flags_imsvc}" + if (use_lld) { + sys_lib_flags = "-libpath:$_clang_lib_dir " + + "${rust_host_win_toolchain_data.libpath_lldlink_flags}" + } + + toolchain_args = { + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + is_clang = true + current_os = "win" + current_cpu = rust_host_toolchain_arch + } + } + msvc_system_allocator_toolchain( + clang_toolchain_prefix + target_name + "_with_system_allocator") { + environment = "environment." + toolchain_arch + cl = "${_clang_bin_path}/clang-cl${_exe}" + + sys_include_flags = "${win_toolchain_data.include_flags_imsvc}" + if (use_lld) { + sys_lib_flags = "-libpath:$_clang_lib_dir " + + "${win_toolchain_data.libpath_lldlink_flags}" + } + + toolchain_args = { + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + is_clang = true + current_os = "win" + current_cpu = toolchain_arch + } + } + msvc_rust_host_build_tools_toolchain( + clang_toolchain_prefix + target_name + "_for_rust_host_build_tools") { environment = "environment." + rust_host_toolchain_arch cl = "${_clang_bin_path}/clang-cl${_exe}" diff --git a/naiveproxy/src/build/toolchain/zos/BUILD.gn b/naiveproxy/src/build/toolchain/zos/BUILD.gn index 3af5f8033d..94f8caf1a1 100644 --- a/naiveproxy/src/build/toolchain/zos/BUILD.gn +++ b/naiveproxy/src/build/toolchain/zos/BUILD.gn @@ -7,9 +7,9 @@ import("//build/toolchain/gcc_toolchain.gni") toolchain("s390x") { - cc = "xlclang" - cxx = "xlclang++" - asm = "xlclang" + cc = "ibm-clang" + cxx = "ibm-clang++" + asm = "ibm-clang" ar = "ar" ld = cxx @@ -36,7 +36,7 @@ toolchain("s390x") { tool("cc") { depfile = "{{output}}.d" - command = "$cc -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}${extra_cflags} -c {{source}} -o {{output}}" + command = "$cc -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}${extra_cflags} -c {{source}} -o {{output}}" depsformat = "gcc" description = "CC {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -44,7 +44,7 @@ toolchain("s390x") { tool("cxx") { depfile = "{{output}}.d" - command = "$cxx -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}${extra_cppflags}${extra_cxxflags} -c {{source}} -o {{output}}" + command = "$cxx -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}${extra_cppflags}${extra_cxxflags} -c {{source}} -o {{output}}" depsformat = "gcc" description = "CXX {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -53,7 +53,7 @@ toolchain("s390x") { tool("asm") { # Just use the C compiler to compile assembly. depfile = "{{output}}.d" - command = "$asm -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{asmflags}}${extra_asmflags} -c {{source}} -o {{output}}" + command = "$asm ${rebuild_string} {{asmflags}}${extra_asmflags} -c {{source}} -o {{output}}" depsformat = "gcc" description = "ASM {{output}}" outputs = [ "$object_subdir/{{source_name_part}}.o" ] @@ -88,11 +88,12 @@ toolchain("s390x") { # implement (1) linking to produce a .so, (2) extracting the symbols # from that file (3) if the extracted list differs from the existing # .TOC file, overwrite it, otherwise, don't change it. - link_command = "$ld -Wl,DLL {{ldflags}}${extra_ldflags} -o \"$sofile\" `cat $rspfile`" + link_command = "$ld -Wl,-x${xfile} {{ldflags}}${extra_ldflags} -o \"$sofile\" `cat $rspfile`" solink_wrapper = - rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir) - command = "$python_path \"$solink_wrapper\" --output=\"$sofile\" -- $link_command" + rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir) + command = + "$python_path \"$solink_wrapper\" --output=\"$sofile\" -- $link_command" rspfile_content = "{{inputs}} {{solibs}} {{libs}}" @@ -153,7 +154,8 @@ toolchain("s390x") { link_wrapper = rebase_path("//build/toolchain/gcc_link_wrapper.py", root_build_dir) - command = "$python_path \"$link_wrapper\" --output=\"$outfile\" -- $link_command" + command = + "$python_path \"$link_wrapper\" --output=\"$outfile\" -- $link_command" description = "LINK $outfile" rspfile_content = "{{inputs}}" diff --git a/naiveproxy/src/build/util/BUILD.gn b/naiveproxy/src/build/util/BUILD.gn index a96d326776..ea9abdc3b5 100644 --- a/naiveproxy/src/build/util/BUILD.gn +++ b/naiveproxy/src/build/util/BUILD.gn @@ -35,3 +35,11 @@ group("test_results") { "//build/util/lib/results/", ] } + +group("proto") { + data = [ + "//.vpython3", + "//build/util/lib/__init__.py", + "//build/util/lib/proto/", + ] +} diff --git a/naiveproxy/src/build/util/LASTCHANGE b/naiveproxy/src/build/util/LASTCHANGE index 07a43fb244..b024e6ee4e 100644 --- a/naiveproxy/src/build/util/LASTCHANGE +++ b/naiveproxy/src/build/util/LASTCHANGE @@ -1,2 +1,2 @@ -LASTCHANGE=3d41cad040c1f6a4e365c4746cc2c40e8dc4b9db-refs/branch-heads/6533@{#1744} +LASTCHANGE=ce7f05019fe091c912aa09c989eb3d7d406d0f3c-refs/branch-heads/6613@{#1037} LASTCHANGE_YEAR=2024 diff --git a/naiveproxy/src/build/util/LASTCHANGE.committime b/naiveproxy/src/build/util/LASTCHANGE.committime index 04f39043c1..6fea024923 100644 --- a/naiveproxy/src/build/util/LASTCHANGE.committime +++ b/naiveproxy/src/build/util/LASTCHANGE.committime @@ -1 +1 @@ -1721667576 \ No newline at end of file +1723595729 \ No newline at end of file diff --git a/naiveproxy/src/build/util/android_chrome_version.py b/naiveproxy/src/build/util/android_chrome_version.py index 767e4eeb4d..957bfa0306 100755 --- a/naiveproxy/src/build/util/android_chrome_version.py +++ b/naiveproxy/src/build/util/android_chrome_version.py @@ -56,6 +56,7 @@ _PACKAGE_NAMES = { 'TRICHROME': 30, 'TRICHROME_BETA': 40, 'TRICHROME_AUTO': 50, + 'TRICHROME_DESKTOP': 60, 'WEBVIEW_STABLE': 0, 'WEBVIEW_BETA': 10, 'WEBVIEW_DEV': 20, @@ -98,6 +99,7 @@ _APKS = { ('TRICHROME', 'TRICHROME', '64'), ('TRICHROME_AUTO', 'TRICHROME_AUTO', '64'), ('TRICHROME_BETA', 'TRICHROME_BETA', '64'), + ('TRICHROME_DESKTOP', 'TRICHROME_DESKTOP', '64'), ('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '64'), ('WEBVIEW_BETA', 'WEBVIEW_BETA', '64'), ('WEBVIEW_DEV', 'WEBVIEW_DEV', '64'), @@ -128,6 +130,7 @@ _APKS = { ('TRICHROME_32_64_BETA', 'TRICHROME_BETA', '32_64'), ('TRICHROME_64_32_BETA', 'TRICHROME_BETA', '64_32'), ('TRICHROME_64_32_HIGH_BETA', 'TRICHROME_BETA', '64_32_high'), + ('TRICHROME_DESKTOP_64', 'TRICHROME_DESKTOP', '64'), ('TRICHROME_64_BETA', 'TRICHROME_BETA', '64'), ('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '32_64'), ('WEBVIEW_BETA', 'WEBVIEW_BETA', '32_64'), diff --git a/naiveproxy/src/build/util/android_chrome_version_test.py b/naiveproxy/src/build/util/android_chrome_version_test.py index ca7ae93ccb..8c85dab322 100644 --- a/naiveproxy/src/build/util/android_chrome_version_test.py +++ b/naiveproxy/src/build/util/android_chrome_version_test.py @@ -174,6 +174,8 @@ class _VersionTest(unittest.TestCase): 'TRICHROME_AUTO_64_VERSION_CODE'] arch_trichrome_auto_64_32_version_code = output[ 'TRICHROME_AUTO_64_32_VERSION_CODE'] + arch_trichrome_desktop_64_version_code = output[ + 'TRICHROME_DESKTOP_64_VERSION_CODE'] self.assertEqual(arch_monochrome_32_version_code, '484400020') self.assertEqual(arch_monochrome_32_64_version_code, '484400023') @@ -191,6 +193,7 @@ class _VersionTest(unittest.TestCase): self.assertEqual(arch_trichrome_auto_32_64_version_code, '484400053') self.assertEqual(arch_trichrome_auto_64_version_code, '484400055') self.assertEqual(arch_trichrome_auto_64_32_version_code, '484400054') + self.assertEqual(arch_trichrome_desktop_64_version_code, '484400065') def testGenerateVersionCodesAndroidArchX64(self): """Assert it handles different architectures correctly. @@ -233,6 +236,8 @@ class _VersionTest(unittest.TestCase): 'TRICHROME_AUTO_64_VERSION_CODE'] arch_trichrome_auto_64_32_version_code = output[ 'TRICHROME_AUTO_64_32_VERSION_CODE'] + arch_trichrome_desktop_64_version_code = output[ + 'TRICHROME_DESKTOP_64_VERSION_CODE'] self.assertEqual(arch_monochrome_32_version_code, '484400021') self.assertEqual(arch_monochrome_32_64_version_code, '484400026') @@ -249,6 +254,7 @@ class _VersionTest(unittest.TestCase): self.assertEqual(arch_trichrome_auto_32_64_version_code, '484400056') self.assertEqual(arch_trichrome_auto_64_version_code, '484400058') self.assertEqual(arch_trichrome_auto_64_32_version_code, '484400057') + self.assertEqual(arch_trichrome_desktop_64_version_code, '484400068') def testGenerateVersionCodesAndroidArchOrderArm(self): """Assert it handles different architectures correctly. @@ -518,6 +524,8 @@ class _VersionGroupedTest(unittest.TestCase): 'TRICHROME_AUTO_64_32_VERSION_CODE'] arch_trichrome_auto_64_32_high_version_code = output[ 'TRICHROME_AUTO_64_32_HIGH_VERSION_CODE'] + arch_trichrome_desktop_64_version_code = output[ + 'TRICHROME_DESKTOP_64_VERSION_CODE'] self.assertEqual(arch_monochrome_32_version_code, '575000020') self.assertEqual(arch_monochrome_32_64_version_code, '575000021') @@ -536,6 +544,7 @@ class _VersionGroupedTest(unittest.TestCase): self.assertEqual(arch_trichrome_auto_version_code, '575000051') self.assertEqual(arch_trichrome_auto_32_version_code, '575000050') self.assertEqual(arch_trichrome_auto_32_64_version_code, '575000051') + self.assertEqual(arch_trichrome_desktop_64_version_code, '575000064') def testGenerateVersionCodesAndroidArchX64(self): """Assert it handles different architectures correctly. @@ -581,6 +590,8 @@ class _VersionGroupedTest(unittest.TestCase): 'TRICHROME_AUTO_64_32_VERSION_CODE'] arch_trichrome_auto_64_version_code = output[ 'TRICHROME_AUTO_64_VERSION_CODE'] + arch_trichrome_desktop_64_version_code = output[ + 'TRICHROME_DESKTOP_64_VERSION_CODE'] self.assertEqual(arch_monochrome_32_version_code, '575000026') self.assertEqual(arch_monochrome_32_64_version_code, '575000027') @@ -597,6 +608,7 @@ class _VersionGroupedTest(unittest.TestCase): self.assertEqual(arch_trichrome_auto_32_64_version_code, '575000057') self.assertEqual(arch_trichrome_auto_64_version_code, '575000059') self.assertEqual(arch_trichrome_auto_64_32_version_code, '575000058') + self.assertEqual(arch_trichrome_desktop_64_version_code, '575000069') def testGenerateVersionCodesAndroidArchRiscv64(self): """Assert it handles different architectures correctly. @@ -660,6 +672,7 @@ class _VersionGroupedTest(unittest.TestCase): self.assertFalse('WEBVIEW_32_STABLE_VERSION_CODE' in output) self.assertFalse('WEBVIEW_32_BETA_VERSION_CODE' in output) self.assertFalse('WEBVIEW_32_DEV_VERSION_CODE' in output) + self.assertFalse('TRICHROME_DESKTOP_64_VERSION_CODE' in output) def testGenerateVersionCodesAndroidArchOrderArm(self): """Assert it handles different architectures correctly. @@ -972,6 +985,16 @@ class _VersionCodeTest(unittest.TestCase): self.assertEqual(abi, 'x86_64') self.assertEqual(is_next_build, False) + def testX86_Desktop_64Translate(self): + """Test for a desktop build with x86_64.""" + build, patch, package, abi, is_next_build = TranslateVersionCode( + '499900068') + self.assertEqual(build, 4999) + self.assertEqual(patch, 0) + self.assertEqual(package, 'TRICHROME_DESKTOP') + self.assertEqual(abi, 'x86_64') + self.assertEqual(is_next_build, False) + def testWebviewTranslate(self): """Test for a build with Webview.""" build, patch, package, abi, is_next_build = TranslateVersionCode( @@ -1060,6 +1083,7 @@ class _VersionCodeGroupedTest(unittest.TestCase): self.assertEqual(abi, 'arm_64_32_high') self.assertEqual(is_next_build, False) + def testX86_64Translate(self): """Test for a build with x86_64.""" build, patch, package, abi, is_next_build = TranslateVersionCode( @@ -1100,6 +1124,16 @@ class _VersionCodeGroupedTest(unittest.TestCase): self.assertEqual(abi, 'x86_64_32') self.assertEqual(is_next_build, False) + def testX86_Auto_64_32Translate(self): + """Test for a desktop build with x86_64_32.""" + build, patch, package, abi, is_next_build = TranslateVersionCode( + '575000068') + self.assertEqual(build, 5750) + self.assertEqual(patch, 0) + self.assertEqual(package, 'TRICHROME_DESKTOP') + self.assertEqual(abi, 'x86_64_32') + self.assertEqual(is_next_build, False) + def testWebviewTranslate(self): """Test for a build with Webview.""" build, patch, package, abi, is_next_build = TranslateVersionCode( diff --git a/naiveproxy/src/build/util/lib/common/perf_tests_results_helper.py b/naiveproxy/src/build/util/lib/common/perf_tests_results_helper.py index 8246e206c0..86b41b7dd8 100644 --- a/naiveproxy/src/build/util/lib/common/perf_tests_results_helper.py +++ b/naiveproxy/src/build/util/lib/common/perf_tests_results_helper.py @@ -10,7 +10,7 @@ import json import logging import math -import perf_result_data_type +from lib.common import perf_result_data_type # Mapping from result type to test output diff --git a/naiveproxy/src/build/util/lib/proto/exception_recorder.py b/naiveproxy/src/build/util/lib/proto/exception_recorder.py new file mode 100644 index 0000000000..e86fff544f --- /dev/null +++ b/naiveproxy/src/build/util/lib/proto/exception_recorder.py @@ -0,0 +1,102 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +""" The module to create and manage ExceptionOccurrence records. """ + +import os +import json +import traceback + +from abc import ABC, abstractmethod +from typing import List + +from google.protobuf import any_pb2 +from google.protobuf.json_format import MessageToDict + +from lib.proto.exception_occurrences_pb2 import ExceptionOccurrence +from lib.proto.exception_occurrences_pb2 import ExceptionOccurrences + +# This is used as the key when being uploaded to ResultDB via result_sink +# and shouldn't be changed +EXCEPTION_OCCURRENCES_KEY = 'exception_occurrences' + +# This is used as the key when being uploaded to ResultDB via rdb +# and shouldn't be changed +EXCEPTION_OCCURRENCES_FILENAME = f'{EXCEPTION_OCCURRENCES_KEY}.jsonpb' + +_records: List[ExceptionOccurrence] = [] + + +class Formatter(ABC): + + @abstractmethod + def format_name(self, exc: Exception) -> str: + """Format the exception name.""" + + @abstractmethod + def format_stacktrace(self, exc: Exception) -> List[str]: + """Format the exception stacktrace.""" + + +class _Formatter(Formatter): + + def format_name(self, exc: Exception) -> str: + exc_name = type(exc).__qualname__ + exc_module = type(exc).__module__ + if exc_module not in ('__main__', 'builtins'): + exc_name = '%s.%s' % (exc_module, exc_name) + return exc_name + + def format_stacktrace(self, exc: Exception) -> List[str]: + return traceback.format_exception(type(exc), exc, exc.__traceback__) + + +# Default formatter +_default_formatter = _Formatter() + + +def register(exc: Exception, + formatter: Formatter = _default_formatter) -> ExceptionOccurrence: + """Create and register an ExceptionOccurrence record.""" + ret = ExceptionOccurrence(name=formatter.format_name(exc), + stacktrace=formatter.format_stacktrace(exc)) + ret.occurred_time.GetCurrentTime() + _records.append(ret) + return ret + + +def size() -> int: + """Get the current size of registered ExceptionOccurrence records.""" + return len(_records) + + +def clear() -> None: + """Clear all the registered ExceptionOccurrence records.""" + _records.clear() + + +def to_dict() -> dict: + """Convert all the registered ExceptionOccurrence records to an dict. + + The records are wrapped in protobuf Any message before exported as dict + so that an additional key "@type" is included. + """ + occurrences = ExceptionOccurrences() + occurrences.datapoints.extend(_records) + any_msg = any_pb2.Any() + any_msg.Pack(occurrences) + return MessageToDict(any_msg, preserving_proto_field_name=True) + + +def to_json() -> str: + """Convert all the registered ExceptionOccurrence records to a json str.""" + return json.dumps(to_dict(), sort_keys=True, indent=2) + + +def dump(dir_path: str) -> None: + """Dumps the records into |EXCEPTION_OCCURRENCES_FILENAME| in the |path|.""" + os.makedirs(dir_path, exist_ok=True) + with open(os.path.join(dir_path, EXCEPTION_OCCURRENCES_FILENAME), + 'w', + encoding='utf-8') as wf: + wf.write(to_json()) diff --git a/naiveproxy/src/build/util/lib/proto/exception_recorder_unittests.py b/naiveproxy/src/build/util/lib/proto/exception_recorder_unittests.py new file mode 100755 index 0000000000..414d0d6043 --- /dev/null +++ b/naiveproxy/src/build/util/lib/proto/exception_recorder_unittests.py @@ -0,0 +1,69 @@ +#!/usr/bin/env vpython3 + +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""File for testing exception_recorder.py.""" + +import os +import sys +import tempfile +import unittest +import unittest.mock + +_BUILD_UTIL_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..')) +if _BUILD_UTIL_PATH not in sys.path: + sys.path.insert(0, _BUILD_UTIL_PATH) + +from lib.proto import exception_recorder +from lib.proto.exception_occurrences_pb2 import ExceptionOccurrences + + +class MyClass: + + class MyException(Exception): + pass + + +class ExceptionRecorderTest(unittest.TestCase): + + def myException(self): + raise MyClass.MyException('Hello') + + def test_register(self) -> None: + exception_recorder.clear() + with self.assertRaises(MyClass.MyException) as cm: + self.myException() + record = exception_recorder.register(cm.exception) + self.assertEqual(record.name, 'MyClass.MyException') + self.assertTrue(len(record.stacktrace) > 0) + self.assertTrue(record.occurred_time.ToSeconds() > 0) + self.assertEqual(len(exception_recorder._records), 1) + + def test_to_dict(self) -> None: + exception_recorder.clear() + with self.assertRaises(MyClass.MyException) as cm: + self.myException() + record = exception_recorder.register(cm.exception) + actual = exception_recorder.to_dict() + self.assertIn('@type', actual) + self.assertIn(ExceptionOccurrences.DESCRIPTOR.full_name, actual['@type']) + actual_record = actual['datapoints'][0] + self.assertEqual(actual_record['name'], record.name) + self.assertEqual(actual_record['stacktrace'], record.stacktrace) + + def test_dump(self) -> None: + exception_recorder.clear() + with self.assertRaises(MyClass.MyException) as cm: + self.myException() + record = exception_recorder.register(cm.exception) + with tempfile.TemporaryDirectory() as tmpdir: + exception_recorder.dump(tmpdir) + file_path = os.path.join( + tmpdir, exception_recorder.EXCEPTION_OCCURRENCES_FILENAME) + self.assertTrue(os.path.exists(file_path)) + + +if __name__ == '__main__': + unittest.main() diff --git a/naiveproxy/src/build/util/lib/proto/measures.py b/naiveproxy/src/build/util/lib/proto/measures.py new file mode 100755 index 0000000000..33fcfeeda0 --- /dev/null +++ b/naiveproxy/src/build/util/lib/proto/measures.py @@ -0,0 +1,68 @@ +#!/usr/bin/env vpython3 + +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +""" The module to create and manage measures using in the process. """ + +import json +import os + +from google.protobuf import any_pb2 +from google.protobuf.json_format import MessageToJson + +from average import Average +from count import Count +from data_points import DataPoints +from measure import Measure +from metric import Metric +from time_consumption import TimeConsumption + +# The file name is used as the key when being loaded into the ResultDB and +# shouldn't be changed. +TEST_SCRIPT_METRICS_JSONPB_FILENAME = 'test_script_metrics.jsonpb' + +_metric = Metric() + + +def _create_name(*name_pieces: str) -> str: + if len(name_pieces) == 0: + raise ValueError('Need at least one name piece.') + return '/'.join(list(name_pieces)) + + +def _register(m: Measure) -> Measure: + _metric.register(m) + return m + + +def average(*name_pieces: str) -> Average: + return _register(Average(_create_name(*name_pieces))) + + +def count(*name_pieces: str) -> Count: + return _register(Count(_create_name(*name_pieces))) + + +def data_points(*name_pieces: str) -> DataPoints: + return _register(DataPoints(_create_name(*name_pieces))) + + +def time_consumption(*name_pieces: str) -> TimeConsumption: + return _register(TimeConsumption(_create_name(*name_pieces))) + + +# TODO(crbug.com/343242386): May need to implement a lock and reset logic to +# clear in-memory data and lock the instance to block further operations and +# avoid accidentally accumulating data which won't be published at all. +def dump(dir_path: str) -> None: + """Dumps the metric data into test_script_metrics.jsonpb in the |path|.""" + os.makedirs(dir_path, exist_ok=True) + any_msg = any_pb2.Any() + any_msg.Pack(_metric.dump()) + with open(os.path.join(dir_path, TEST_SCRIPT_METRICS_JSONPB_FILENAME), + 'w', + encoding='utf-8') as wf: + wf.write( + MessageToJson(any_msg, preserving_proto_field_name=True, + sort_keys=True)) diff --git a/naiveproxy/src/build/util/lib/proto/measures_unittests.py b/naiveproxy/src/build/util/lib/proto/measures_unittests.py new file mode 100755 index 0000000000..e90acf3b77 --- /dev/null +++ b/naiveproxy/src/build/util/lib/proto/measures_unittests.py @@ -0,0 +1,95 @@ +#!/usr/bin/env vpython3 + +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""File for testing measures.py.""" + +import os +import tempfile +import unittest + +import google.protobuf.json_format as json_format + +from google.protobuf import any_pb2 + +import measures + +from measure import Measure +from test_script_metrics_pb2 import TestScriptMetric, TestScriptMetrics + + +class MeasuresTest(unittest.TestCase): + """Test measure.py.""" + + def test_create_average(self) -> None: + ave = measures.average('a', 'b', 'c') + ave.record(1) + ave.record(2) + exp = TestScriptMetric() + exp.name = 'a/b/c' + exp.value = 1.5 + self.assertEqual(ave.dump(), exp) + + def test_create_single_name_piece(self) -> None: + self.assertEqual(measures.average('a')._name, 'a') + + def test_create_no_name_piece(self) -> None: + self.assertRaises(ValueError, lambda: measures.average()) + + def test_create_none_in_name_pieces(self) -> None: + self.assertRaises(TypeError, lambda: measures.average('a', None)) + + def test_create_count(self) -> None: + self.assertIsInstance(measures.count('a'), Measure) + + def test_create_data_points(self) -> None: + self.assertIsInstance(measures.data_points('a'), Measure) + + def test_register(self) -> None: + before = len(measures._metric._metrics) + for x in range(3): + measures.average('a') + self.assertEqual(len(measures._metric._metrics), before + 3) + + def test_dump(self) -> None: + before = len(measures._metric._metrics) + count = measures.count('test', 'dump') + for _ in range(101): + count.record() + with tempfile.TemporaryDirectory() as tmpdir: + measures.dump(tmpdir) + with open(os.path.join(tmpdir, + measures.TEST_SCRIPT_METRICS_JSONPB_FILENAME), + 'r', + encoding='utf-8') as rf: + any_msg = json_format.Parse(rf.read(), any_pb2.Any()) + message = TestScriptMetrics() + self.assertTrue(any_msg.Unpack(message)) + self.assertEqual(len(message.metrics), before + 1) + exp = TestScriptMetric() + exp.name = 'test/dump' + exp.value = 101 + self.assertEqual(message.metrics[-1], exp) + + def test_dump_with_type(self) -> None: + with tempfile.TemporaryDirectory() as tmpdir: + measures.dump(tmpdir) + with open(os.path.join(tmpdir, + measures.TEST_SCRIPT_METRICS_JSONPB_FILENAME), + 'r', + encoding='utf-8') as rf: + txt = rf.read() + self.assertTrue('"@type":' in txt) + self.assertTrue(TestScriptMetrics().DESCRIPTOR.full_name in txt) + + def test_dump_create_dir(self) -> None: + with tempfile.TemporaryDirectory() as tmpdir: + dir_path = os.path.join(tmpdir, 'hello', 'this', 'dir', 'should', 'not', + 'exist') + measures.dump(dir_path) + self.assertTrue(os.path.isdir(dir_path)) + + +if __name__ == '__main__': + unittest.main() diff --git a/naiveproxy/src/build/util/lib/proto/metric.py b/naiveproxy/src/build/util/lib/proto/metric.py index 544e7847a7..9751cf1915 100755 --- a/naiveproxy/src/build/util/lib/proto/metric.py +++ b/naiveproxy/src/build/util/lib/proto/metric.py @@ -17,9 +17,6 @@ class Metric: def register(self, metric: Measure) -> None: self._metrics.append(metric) - # Dumping to the protobuf is mostly for testing purpose only. The real use - # case would dump everything into a json file for the further upload. - # TODO(crbug.com/343242386): May dump to a file once the file name is defined. def dump(self) -> TestScriptMetrics: result = TestScriptMetrics() result.metrics.extend([m.dump() for m in self._metrics]) diff --git a/naiveproxy/src/build/util/lib/proto/time_consumption.py b/naiveproxy/src/build/util/lib/proto/time_consumption.py new file mode 100755 index 0000000000..a8d1fc459d --- /dev/null +++ b/naiveproxy/src/build/util/lib/proto/time_consumption.py @@ -0,0 +1,40 @@ +#!/usr/bin/env vpython3 + +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +""" A metric implementation to calculate the time consumption. + +Example: + with TimeConsumption('foo'): + do_something() +""" + +import time + +from contextlib import AbstractContextManager + +from measure import Measure +from test_script_metrics_pb2 import TestScriptMetric + + +class TimeConsumption(AbstractContextManager, Measure): + + def __init__(self, name: str) -> None: + self._name = name + ' (seconds)' + self._start = 0 + self._end = 0 + + def __enter__(self) -> None: + self._start = time.time() + + def __exit__(self, exc_type, exc_value, traceback) -> bool: + self._end = time.time() + # Do not suppress exceptions. + return False + + def dump(self) -> TestScriptMetric: + result = TestScriptMetric() + result.name = self._name + result.value = (self._end - self._start) + return result diff --git a/naiveproxy/src/build/util/lib/proto/time_consumption_unittests.py b/naiveproxy/src/build/util/lib/proto/time_consumption_unittests.py new file mode 100755 index 0000000000..c51f48d3e6 --- /dev/null +++ b/naiveproxy/src/build/util/lib/proto/time_consumption_unittests.py @@ -0,0 +1,73 @@ +#!/usr/bin/env vpython3 + +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""File for testing time_consumption.py.""" + +import os +import tempfile +import unittest +import unittest.mock as mock + +import google.protobuf.json_format as json_format + +from google.protobuf import any_pb2 + +import measures + +from test_script_metrics_pb2 import TestScriptMetric, TestScriptMetrics + + +class TimeConsumptionTest(unittest.TestCase): + """Test time_consumption.py.""" + + @mock.patch('time_consumption.time.time', side_effect=[100, 110]) + def test_by_dumping(self, time_patch) -> None: + before = len(measures._metric._metrics) + with measures.time_consumption('test', 'time', 'consumption'): + pass + with tempfile.TemporaryDirectory() as tmpdir: + measures.dump(tmpdir) + with open(os.path.join(tmpdir, + measures.TEST_SCRIPT_METRICS_JSONPB_FILENAME), + 'r', + encoding='utf-8') as rf: + any_msg = json_format.Parse(rf.read(), any_pb2.Any()) + message = TestScriptMetrics() + self.assertTrue(any_msg.Unpack(message)) + self.assertEqual(len(message.metrics), before + 1) + exp = TestScriptMetric() + exp.name = 'test/time/consumption (seconds)' + exp.value = 10 + self.assertEqual(message.metrics[-1], exp) + self.assertEqual(time_patch.call_count, 2) + + @mock.patch('time_consumption.time.time', side_effect=[100, 101, 102, 110]) + def test_exit_twice(self, time_patch) -> None: + # This is not a common use scenario, but it shouldn't crash. + before = len(measures._metric._metrics) + consumption = measures.time_consumption('test', 'time', 'consumption2') + with consumption: + pass + with consumption: + pass + with tempfile.TemporaryDirectory() as tmpdir: + measures.dump(tmpdir) + with open(os.path.join(tmpdir, + measures.TEST_SCRIPT_METRICS_JSONPB_FILENAME), + 'r', + encoding='utf-8') as rf: + any_msg = json_format.Parse(rf.read(), any_pb2.Any()) + message = TestScriptMetrics() + self.assertTrue(any_msg.Unpack(message)) + self.assertEqual(len(message.metrics), before + 1) + exp = TestScriptMetric() + exp.name = 'test/time/consumption2 (seconds)' + exp.value = 8 + self.assertEqual(message.metrics[-1], exp) + self.assertEqual(time_patch.call_count, 4) + + +if __name__ == '__main__': + unittest.main() diff --git a/naiveproxy/src/build/whitespace_file.txt b/naiveproxy/src/build/whitespace_file.txt index 1dc8a00b7e..9a34ff289d 100644 --- a/naiveproxy/src/build/whitespace_file.txt +++ b/naiveproxy/src/build/whitespace_file.txt @@ -215,3 +215,14 @@ There was a test Interesting first commit. If debugging is the process of removing bugs, then programming must be the process of putting them in. + +--- + +TOKI PONA: + +Toki Pona is an isolating language with only 14 phonemes and an underlying feature of minimalism. +It focuses on simple, near-universal concepts to maximize expression from very few words. +In Toki Pona: The Language of Good (referred to as pu), Lang presents around 120 words, +while the later Toki Pona Dictionary (referred to as ku) lists 137 "essential" words and a +number of less-used ones. Its words are easy to pronounce across language backgrounds, +which allows it to serve as a bridge of sorts for people of different cultures. diff --git a/naiveproxy/src/build_overrides/partition_alloc.gni b/naiveproxy/src/build_overrides/partition_alloc.gni index 285b9a9448..00e42d8f03 100644 --- a/naiveproxy/src/build_overrides/partition_alloc.gni +++ b/naiveproxy/src/build_overrides/partition_alloc.gni @@ -65,6 +65,12 @@ if (!is_debug || partition_alloc_optimized_debug) { partition_alloc_add_configs = [ "//build/config/compiler:no_optimize" ] } +# llvm_profile_set_target() generated by -fgenerate-profile invokes malloc() +# internally. Since allocator_shim and PartitionAlloc are not reenterant, +# the code will cause crashes. See crbug.com/338094768. +partition_alloc_remove_configs += + [ "//build/config/compiler/pgo:default_pgo_flags" ] + # Sanitizers replace the allocator, don't use our own. _is_using_sanitizers = is_asan || is_hwasan || is_lsan || is_tsan || is_msan @@ -107,8 +113,9 @@ if (_default_use_allocator_shim && _is_partition_alloc_everywhere_platform && use_partition_alloc_as_malloc_default = _default_allocator == "partition" use_allocator_shim_default = _default_use_allocator_shim -_is_brp_supported = (is_win || is_android || is_linux || is_mac || is_ios || - is_chromeos) && use_partition_alloc_as_malloc_default +_is_brp_supported = + (is_win || is_android || is_linux || is_mac || is_ios || is_chromeos || + is_fuchsia) && use_partition_alloc_as_malloc_default enable_backup_ref_ptr_support_default = _is_brp_supported diff --git a/naiveproxy/src/buildtools/deps_revisions.gni b/naiveproxy/src/buildtools/deps_revisions.gni index f7df5d5473..d20fe70ae8 100644 --- a/naiveproxy/src/buildtools/deps_revisions.gni +++ b/naiveproxy/src/buildtools/deps_revisions.gni @@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision vars in //DEPS. - libcxx_revision = "852bc6746f45add53fec19f3a29280e69e358d44" + libcxx_revision = "6bb75caa139ee1e686d2205910454cf6ea212e58" } diff --git a/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn b/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn index b29b678d6a..edcae7b322 100644 --- a/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn +++ b/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn @@ -166,6 +166,9 @@ target(_libcxx_target_type, "libc++") { "//build/config/compiler:chromium_code", "//build/config/coverage:default_coverage", ] + if (use_libcxx_modules) { + configs -= [ "//build/config/compiler:libcxx_module" ] + } if ((is_android || is_apple) && libcxx_is_shared) { # Use libc++_chrome to avoid conflicting with system libc++ output_name = "libc++_chrome" diff --git a/naiveproxy/src/buildtools/third_party/libc++/__config_site b/naiveproxy/src/buildtools/third_party/libc++/__config_site index d3249c5c30..1793075756 100644 --- a/naiveproxy/src/buildtools/third_party/libc++/__config_site +++ b/naiveproxy/src/buildtools/third_party/libc++/__config_site @@ -1,6 +1,11 @@ #ifndef _LIBCPP_CONFIG_SITE #define _LIBCPP_CONFIG_SITE +// Dynamic libc++ configuration macros are in +// build/config/libc++:runtime_library. This file only has defines +// that are constant across platforms, or easily set via preprocessor checks. +// Things that are set depending on GN args are not here. + // We set a custom _LIBCPP_ABI_NAMESPACE for the following reasons: // // 1. When libcxx_is_shared is true, symbols from libc++.so are exported for all @@ -40,8 +45,6 @@ // TODO(thakis): Is this right? /* #undef _LIBCPP_HAS_NO_TIME_ZONE_DATABASE */ -#define _LIBCPP_INSTRUMENTED_WITH_ASAN - // PSTL backends /* #undef _LIBCPP_PSTL_BACKEND_SERIAL */ #if defined(__APPLE__) @@ -50,15 +53,6 @@ #define _LIBCPP_PSTL_BACKEND_STD_THREAD #endif -// PSTL backends, old spelling -// TODO(thakis): Remove these after the next libc++ roll is in. -/* #undef _LIBCPP_PSTL_CPU_BACKEND_SERIAL */ -#if defined(__APPLE__) -#define _LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH -#else -#define _LIBCPP_PSTL_CPU_BACKEND_THREAD -#endif - // Settings below aren't part of __config_site upstream. // We set them here since we want them to take effect everywhere, // unconditionally. diff --git a/naiveproxy/src/buildtools/third_party/libc++abi/BUILD.gn b/naiveproxy/src/buildtools/third_party/libc++abi/BUILD.gn index 0321740443..ab3218ccd3 100644 --- a/naiveproxy/src/buildtools/third_party/libc++abi/BUILD.gn +++ b/naiveproxy/src/buildtools/third_party/libc++abi/BUILD.gn @@ -98,6 +98,10 @@ source_set("libc++abi") { # libc++abi depends on libc++ internals. include_dirs = [ "//third_party/libc++/src/src" ] + + if (use_libcxx_modules) { + configs -= [ "//build/config/compiler:libcxx_module" ] + } if (!is_apple) { sources -= [ "//third_party/libc++abi/src/src/cxa_exception.cpp", diff --git a/naiveproxy/src/chrome/VERSION b/naiveproxy/src/chrome/VERSION index 3522450d49..04fefa2240 100644 --- a/naiveproxy/src/chrome/VERSION +++ b/naiveproxy/src/chrome/VERSION @@ -1,4 +1,4 @@ -MAJOR=127 +MAJOR=128 MINOR=0 -BUILD=6533 -PATCH=64 +BUILD=6613 +PATCH=40 diff --git a/naiveproxy/src/chrome/android/profiles/newest.txt b/naiveproxy/src/chrome/android/profiles/newest.txt index efc1128c2c..5236cda111 100644 --- a/naiveproxy/src/chrome/android/profiles/newest.txt +++ b/naiveproxy/src/chrome/android/profiles/newest.txt @@ -1 +1 @@ -chromeos-chrome-amd64-127.0.6533.17_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-128.0.6613.32_rc-r1-merged.afdo.bz2 diff --git a/naiveproxy/src/chrome/build/android-arm32.pgo.txt b/naiveproxy/src/chrome/build/android-arm32.pgo.txt index 5567915505..6177f4a45e 100644 --- a/naiveproxy/src/chrome/build/android-arm32.pgo.txt +++ b/naiveproxy/src/chrome/build/android-arm32.pgo.txt @@ -1 +1 @@ -chrome-android32-main-1718042165-0017430c0366f5da532bb988c4ba1662f6b0b28a-194d1c4d5cd8deb5c36519f821e2a38976130551.profdata +chrome-android32-main-1721692744-44d1aa29423beb497bfdbe4ea144a3b53506761b-b4c470c65b0b73144417d44ce36bb63d9334527e.profdata diff --git a/naiveproxy/src/chrome/build/android-arm64.pgo.txt b/naiveproxy/src/chrome/build/android-arm64.pgo.txt index b1c49a76f6..55aa7a1b68 100644 --- a/naiveproxy/src/chrome/build/android-arm64.pgo.txt +++ b/naiveproxy/src/chrome/build/android-arm64.pgo.txt @@ -1 +1 @@ -chrome-android64-main-1718027784-29282e25cbba8cae6781f2f3d4f57df3133edca4-21923f9629f23105bfe8e4417bc295d236b10068.profdata +chrome-android64-main-1721685490-c8957b0b165632608350cf0651337e162c430dd8-c607102c91854425b42b57789e63222caac64b85.profdata diff --git a/naiveproxy/src/chrome/build/lacros64.pgo.txt b/naiveproxy/src/chrome/build/lacros64.pgo.txt index 431496aa2a..3e3b1120fd 100644 --- a/naiveproxy/src/chrome/build/lacros64.pgo.txt +++ b/naiveproxy/src/chrome/build/lacros64.pgo.txt @@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1718020694-f5b5e2b4245f11aa40685ca8f56a48f94f3b15f2-8003dfad08b6aefbd8447edfc2704e442f0c3bee.profdata +chrome-chromeos-amd64-generic-main-1720094353-160886ed3176b04b754aa3eab646963e9ebefc16-d42818bee373ccac275b7a0989053908da65ddb4.profdata diff --git a/naiveproxy/src/chrome/build/linux.pgo.txt b/naiveproxy/src/chrome/build/linux.pgo.txt index 7b08645534..8696302576 100644 --- a/naiveproxy/src/chrome/build/linux.pgo.txt +++ b/naiveproxy/src/chrome/build/linux.pgo.txt @@ -1 +1 @@ -chrome-linux-6533-1721647559-b59d3252e50dcc0e34a9d5ca3790d80421583ca4-419f07950174cbcea67e9a8035fcc0a2ced2ff1e.profdata +chrome-linux-6613-1723571743-978bf352c6598979c1835e8a17c4382c57186e27-bfa8880547ba8b84e6f5efee6db486daf237d00d.profdata diff --git a/naiveproxy/src/chrome/build/mac-arm.pgo.txt b/naiveproxy/src/chrome/build/mac-arm.pgo.txt index 208edff5fc..e4ad9cc392 100644 --- a/naiveproxy/src/chrome/build/mac-arm.pgo.txt +++ b/naiveproxy/src/chrome/build/mac-arm.pgo.txt @@ -1 +1 @@ -chrome-mac-arm-6533-1721662630-24fdb837d1e1eb2a91b5a7a0d3af9ce2acf2fcfb-294725c2c1c80fe644889477f8f6bfe21f86a47b.profdata +chrome-mac-arm-6613-1723586010-d223af322d141d53ed5eb10ba4c0896914abbd69-9490dad7c92f2b14aea1bbc208be9661fb9c37c4.profdata diff --git a/naiveproxy/src/chrome/build/win-arm64.pgo.txt b/naiveproxy/src/chrome/build/win-arm64.pgo.txt index 84fcc0e6ef..dfd435d96e 100644 --- a/naiveproxy/src/chrome/build/win-arm64.pgo.txt +++ b/naiveproxy/src/chrome/build/win-arm64.pgo.txt @@ -1 +1 @@ -chrome-win-arm64-main-1717674968-a5d4c690088e552a3ea3b574f0da14a717c64541-c8edf3a785636bd4423281908dd830b2c685b53d.profdata +chrome-win-arm64-main-1721671192-1e7479dc923adf839844affd8765f1a8d3a8fe45-26f1f04be9c7bf43f621aed8ac4b9628777eb406.profdata diff --git a/naiveproxy/src/chrome/build/win32.pgo.txt b/naiveproxy/src/chrome/build/win32.pgo.txt index d2a6c83667..62889f9f7c 100644 --- a/naiveproxy/src/chrome/build/win32.pgo.txt +++ b/naiveproxy/src/chrome/build/win32.pgo.txt @@ -1 +1 @@ -chrome-win32-6533-1721626729-d40f1918ed7b71775e44f73fd84a5bc32a9e4abb-d0876f469f5634eb93b60930336a0b7709532ac0.profdata +chrome-win32-6613-1723571743-d23faa9d6be57d92ddea94a35099b8bec82a90ab-bfa8880547ba8b84e6f5efee6db486daf237d00d.profdata diff --git a/naiveproxy/src/chrome/build/win64.pgo.txt b/naiveproxy/src/chrome/build/win64.pgo.txt index a6a665be7a..a62ff5fe13 100644 --- a/naiveproxy/src/chrome/build/win64.pgo.txt +++ b/naiveproxy/src/chrome/build/win64.pgo.txt @@ -1 +1 @@ -chrome-win64-6533-1721647559-5f948c17acc66561f5035462c27089de5245c9ff-419f07950174cbcea67e9a8035fcc0a2ced2ff1e.profdata +chrome-win64-6613-1723571743-8479c7658dbe708c6d468c654aac241d0a9be9e4-bfa8880547ba8b84e6f5efee6db486daf237d00d.profdata diff --git a/naiveproxy/src/chrome/version.gni b/naiveproxy/src/chrome/version.gni index 3677614b40..10ae6eddf5 100644 --- a/naiveproxy/src/chrome/version.gni +++ b/naiveproxy/src/chrome/version.gni @@ -76,6 +76,8 @@ if (is_mac) { "trichrome_64_version_code = \"@TRICHROME_64_VERSION_CODE@\" " _version_dictionary_template += "trichrome_auto_64_version_code = \"@TRICHROME_AUTO_64_VERSION_CODE@\" " + _version_dictionary_template += + "trichrome_desktop_64_version_code = \"@TRICHROME_DESKTOP_64_VERSION_CODE@\" " if (target_cpu == "arm64") { _version_dictionary_template += "trichrome_64_32_high_version_code = \"@TRICHROME_64_32_HIGH_VERSION_CODE@\" " _version_dictionary_template += "trichrome_auto_64_32_high_version_code = \"@TRICHROME_AUTO_64_32_HIGH_VERSION_CODE@\" " @@ -166,6 +168,7 @@ if (is_mac) { "trichrome_auto_64_version_code", "trichrome_auto_64_32_version_code", "trichrome_auto_64_32_high_version_code", + "trichrome_desktop_64_version_code", "trichrome_64_version_code", "trichrome_beta_version_code", "trichrome_32_beta_version_code", @@ -185,6 +188,13 @@ if (is_mac) { ]) chrome_version_name = chrome_version_full + + # There is a different version code only for arm64. + if (is_high_end_android && target_cpu != "arm64") { + trichrome_64_32_high_beta_version_code = trichrome_64_32_beta_version_code + trichrome_64_32_high_version_code = trichrome_64_32_version_code + trichrome_auto_64_32_high_version_code = trichrome_auto_64_32_version_code + } } if (is_android && current_toolchain == default_toolchain) { @@ -214,6 +224,7 @@ if (is_android && current_toolchain == default_toolchain) { "TrichromeChromeAuto3264: $trichrome_auto_32_64_version_code", "TrichromeChromeAuto64: $trichrome_auto_64_version_code", "TrichromeChromeAuto6432: $trichrome_auto_64_32_version_code", + "TrichromeChromeDesktop64: $trichrome_desktop_64_version_code", ] if (target_cpu == "arm64") { lines_to_write += [ @@ -279,7 +290,11 @@ if (is_android) { } else { true_true_true_true = trichrome_64_32_version_code } - true_true_true_false = trichrome_64_version_code + if (is_desktop_android) { + true_true_true_false = trichrome_desktop_64_version_code + } else { + true_true_true_false = trichrome_64_version_code + } true_false_false_true = trichrome_32_version_code true_false_true_true = trichrome_32_64_version_code } diff --git a/naiveproxy/src/crypto/aead.cc b/naiveproxy/src/crypto/aead.cc index dfadecfb1d..933d94b302 100644 --- a/naiveproxy/src/crypto/aead.cc +++ b/naiveproxy/src/crypto/aead.cc @@ -10,14 +10,12 @@ #include "base/containers/span.h" #include "base/numerics/checked_math.h" -#include "crypto/openssl_util.h" #include "third_party/boringssl/src/include/openssl/aes.h" #include "third_party/boringssl/src/include/openssl/evp.h" namespace crypto { Aead::Aead(AeadAlgorithm algorithm) { - EnsureOpenSSLInit(); switch (algorithm) { case AES_128_CTR_HMAC_SHA256: aead_ = EVP_aead_aes_128_ctr_hmac_sha256(); diff --git a/naiveproxy/src/crypto/aead.h b/naiveproxy/src/crypto/aead.h index faa890846d..6a4bb24c9b 100644 --- a/naiveproxy/src/crypto/aead.h +++ b/naiveproxy/src/crypto/aead.h @@ -15,6 +15,7 @@ #include "base/containers/span.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_span.h" #include "crypto/crypto_export.h" struct evp_aead_st; @@ -81,7 +82,7 @@ class CRYPTO_EXPORT Aead { base::span additional_data, base::span out) const; - std::optional> key_; + std::optional> key_; raw_ptr aead_; }; diff --git a/naiveproxy/src/crypto/ec_private_key.cc b/naiveproxy/src/crypto/ec_private_key.cc index 2b56908a28..679242ccad 100644 --- a/naiveproxy/src/crypto/ec_private_key.cc +++ b/naiveproxy/src/crypto/ec_private_key.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/ec_private_key.h" #include diff --git a/naiveproxy/src/crypto/ec_signature_creator_impl.cc b/naiveproxy/src/crypto/ec_signature_creator_impl.cc index 3129ef4872..6eab8f49b1 100644 --- a/naiveproxy/src/crypto/ec_signature_creator_impl.cc +++ b/naiveproxy/src/crypto/ec_signature_creator_impl.cc @@ -17,10 +17,7 @@ namespace crypto { -ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) - : key_(key) { - EnsureOpenSSLInit(); -} +ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) : key_(key) {} ECSignatureCreatorImpl::~ECSignatureCreatorImpl() = default; diff --git a/naiveproxy/src/crypto/encryptor.cc b/naiveproxy/src/crypto/encryptor.cc index ade03b28ff..dd88aee8f0 100644 --- a/naiveproxy/src/crypto/encryptor.cc +++ b/naiveproxy/src/crypto/encryptor.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/encryptor.h" #include @@ -46,7 +51,6 @@ bool Encryptor::Init(const SymmetricKey* key, DCHECK(key); DCHECK(mode == CBC || mode == CTR); - EnsureOpenSSLInit(); if (mode == CBC && iv.size() != AES_BLOCK_SIZE) return false; // CTR mode passes the starting counter separately, via SetCounter(). diff --git a/naiveproxy/src/crypto/hmac.cc b/naiveproxy/src/crypto/hmac.cc index 662ae6d617..28d13d424f 100644 --- a/naiveproxy/src/crypto/hmac.cc +++ b/naiveproxy/src/crypto/hmac.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/hmac.h" #include diff --git a/naiveproxy/src/crypto/nss_key_util.cc b/naiveproxy/src/crypto/nss_key_util.cc index a3e7c0ff65..3ca325bd62 100644 --- a/naiveproxy/src/crypto/nss_key_util.cc +++ b/naiveproxy/src/crypto/nss_key_util.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/nss_key_util.h" #include diff --git a/naiveproxy/src/crypto/nss_util_chromeos.cc b/naiveproxy/src/crypto/nss_util_chromeos.cc index a4c22a564e..c5bfa8e394 100644 --- a/naiveproxy/src/crypto/nss_util_chromeos.cc +++ b/naiveproxy/src/crypto/nss_util_chromeos.cc @@ -28,6 +28,7 @@ #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/no_destructor.h" +#include "base/not_fatal_until.h" #include "base/path_service.h" #include "base/strings/stringprintf.h" #include "base/task/sequenced_task_runner.h" @@ -419,7 +420,7 @@ class ChromeOSTokenManager { void CloseChromeOSUserForTesting(const std::string& username_hash) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); auto i = chromeos_user_map_.find(username_hash); - DCHECK(i != chromeos_user_map_.end()); + CHECK(i != chromeos_user_map_.end(), base::NotFatalUntil::M130); chromeos_user_map_.erase(i); } diff --git a/naiveproxy/src/crypto/openssl_util.cc b/naiveproxy/src/crypto/openssl_util.cc index 55ddb856b4..18a77a33df 100644 --- a/naiveproxy/src/crypto/openssl_util.cc +++ b/naiveproxy/src/crypto/openssl_util.cc @@ -10,7 +10,6 @@ #include #include "base/logging.h" -#include "third_party/boringssl/src/include/openssl/crypto.h" #include "third_party/boringssl/src/include/openssl/err.h" namespace crypto { @@ -33,11 +32,6 @@ int OpenSSLErrorCallback(const char* str, size_t len, void* context) { } // namespace -void EnsureOpenSSLInit() { - // CRYPTO_library_init may be safely called concurrently. - CRYPTO_library_init(); -} - void ClearOpenSSLERRStack(const base::Location& location) { if (DCHECK_IS_ON() && VLOG_IS_ON(1)) { uint32_t error_num = ERR_peek_error(); diff --git a/naiveproxy/src/crypto/openssl_util.h b/naiveproxy/src/crypto/openssl_util.h index cfcd811db8..4b76ae36ad 100644 --- a/naiveproxy/src/crypto/openssl_util.h +++ b/naiveproxy/src/crypto/openssl_util.h @@ -56,13 +56,6 @@ class ScopedOpenSSLSafeSizeBuffer { unsigned char min_sized_buffer_[MIN_SIZE]; }; -// Initialize OpenSSL if it isn't already initialized. This must be called -// before any other OpenSSL functions though it is safe and cheap to call this -// multiple times. -// This function is thread-safe, and OpenSSL will only ever be initialized once. -// OpenSSL will be properly shut down on program exit. -CRYPTO_EXPORT void EnsureOpenSSLInit(); - // Drains the OpenSSL ERR_get_error stack. On a debug build the error codes // are send to VLOG(1), on a release build they are disregarded. In most // cases you should pass FROM_HERE as the |location|. @@ -78,9 +71,7 @@ class OpenSSLErrStackTracer { // messages. Note any diagnostic emitted will be tagged with the location of // the constructor call as it's not possible to trace a destructor's callsite. explicit OpenSSLErrStackTracer(const base::Location& location) - : location_(location) { - EnsureOpenSSLInit(); - } + : location_(location) {} OpenSSLErrStackTracer(const OpenSSLErrStackTracer&) = delete; OpenSSLErrStackTracer& operator=(const OpenSSLErrStackTracer&) = delete; diff --git a/naiveproxy/src/crypto/rsa_private_key.cc b/naiveproxy/src/crypto/rsa_private_key.cc index d601aa8e42..bd53bab174 100644 --- a/naiveproxy/src/crypto/rsa_private_key.cc +++ b/naiveproxy/src/crypto/rsa_private_key.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/rsa_private_key.h" #include diff --git a/naiveproxy/src/crypto/scoped_fake_user_verifying_key_provider.cc b/naiveproxy/src/crypto/scoped_fake_user_verifying_key_provider.cc index fe558070eb..3efac24ed1 100644 --- a/naiveproxy/src/crypto/scoped_fake_user_verifying_key_provider.cc +++ b/naiveproxy/src/crypto/scoped_fake_user_verifying_key_provider.cc @@ -36,9 +36,14 @@ class FakeUserVerifyingSigningKey : public UserVerifyingSigningKey { ~FakeUserVerifyingSigningKey() override = default; void Sign(base::span data, - base::OnceCallback>)> - callback) override { - std::move(callback).Run(software_key_->SignSlowly(data)); + UserVerifyingKeySignatureCallback callback) override { + auto opt_signature = software_key_->SignSlowly(data); + if (!opt_signature.has_value()) { + std::move(callback).Run( + base::unexpected(UserVerifyingKeySigningError::kUnknownError)); + return; + } + std::move(callback).Run(base::ok(*opt_signature)); } std::vector GetPublicKey() const override { @@ -59,8 +64,7 @@ class FakeUserVerifyingKeyProvider : public UserVerifyingKeyProvider { void GenerateUserVerifyingSigningKey( base::span acceptable_algorithms, - base::OnceCallback)> - callback) override { + UserVerifyingKeyCreationCallback callback) override { auto software_unexportable_key = GetSoftwareUnsecureUnexportableKeyProvider()->GenerateSigningKeySlowly( acceptable_algorithms); @@ -72,11 +76,11 @@ class FakeUserVerifyingKeyProvider : public UserVerifyingKeyProvider { void GetUserVerifyingSigningKey( UserVerifyingKeyLabel key_label, - base::OnceCallback)> - callback) override { + UserVerifyingKeyCreationCallback callback) override { for (auto deleted_key : g_deleted_keys_) { if (deleted_key == key_label) { - std::move(callback).Run(nullptr); + std::move(callback).Run( + base::unexpected(UserVerifyingKeyCreationError::kUnknownError)); return; } } @@ -89,8 +93,9 @@ class FakeUserVerifyingKeyProvider : public UserVerifyingKeyProvider { GetSoftwareUnsecureUnexportableKeyProvider() ->FromWrappedSigningKeySlowly(*wrapped_key); CHECK(software_unexportable_key); - std::move(callback).Run(std::make_unique( - std::move(key_label), std::move(software_unexportable_key))); + std::move(callback).Run( + base::ok(std::make_unique( + std::move(key_label), std::move(software_unexportable_key)))); } void DeleteUserVerifyingKey( @@ -107,9 +112,9 @@ class FailingUserVerifyingSigningKey : public UserVerifyingSigningKey { ~FailingUserVerifyingSigningKey() override = default; void Sign(base::span data, - base::OnceCallback>)> - callback) override { - std::move(callback).Run(std::nullopt); + UserVerifyingKeySignatureCallback callback) override { + std::move(callback).Run( + base::unexpected(UserVerifyingKeySigningError::kUnknownError)); } std::vector GetPublicKey() const override { return {1, 2, 3, 4}; } @@ -127,16 +132,16 @@ class FailingUserVerifyingKeyProvider : public UserVerifyingKeyProvider { void GenerateUserVerifyingSigningKey( base::span acceptable_algorithms, - base::OnceCallback)> - callback) override { - std::move(callback).Run(std::make_unique()); + UserVerifyingKeyCreationCallback callback) override { + std::move(callback).Run( + base::ok(std::make_unique())); } void GetUserVerifyingSigningKey( UserVerifyingKeyLabel key_label, - base::OnceCallback)> - callback) override { - std::move(callback).Run(std::make_unique()); + UserVerifyingKeyCreationCallback callback) override { + std::move(callback).Run( + base::ok(std::make_unique())); } void DeleteUserVerifyingKey( diff --git a/naiveproxy/src/crypto/secure_hash.cc b/naiveproxy/src/crypto/secure_hash.cc index b1f26e1f45..6f81ebe8ac 100644 --- a/naiveproxy/src/crypto/secure_hash.cc +++ b/naiveproxy/src/crypto/secure_hash.cc @@ -19,12 +19,7 @@ namespace { class SecureHashSHA256 : public SecureHash { public: - SecureHashSHA256() { - // Ensure that CPU features detection is performed before using - // BoringSSL. This will enable hw accelerated implementations. - EnsureOpenSSLInit(); - SHA256_Init(&ctx_); - } + SecureHashSHA256() { SHA256_Init(&ctx_); } SecureHashSHA256(const SecureHashSHA256& other) { memcpy(&ctx_, &other.ctx_, sizeof(ctx_)); @@ -56,12 +51,7 @@ class SecureHashSHA256 : public SecureHash { class SecureHashSHA512 : public SecureHash { public: - SecureHashSHA512() { - // Ensure that CPU features detection is performed before using - // BoringSSL. This will enable hw accelerated implementations. - EnsureOpenSSLInit(); - SHA512_Init(&ctx_); - } + SecureHashSHA512() { SHA512_Init(&ctx_); } SecureHashSHA512(const SecureHashSHA512& other) { memcpy(&ctx_, &other.ctx_, sizeof(ctx_)); diff --git a/naiveproxy/src/crypto/signature_verifier.cc b/naiveproxy/src/crypto/signature_verifier.cc index f510546c58..833a3dfb25 100644 --- a/naiveproxy/src/crypto/signature_verifier.cc +++ b/naiveproxy/src/crypto/signature_verifier.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/signature_verifier.h" #include diff --git a/naiveproxy/src/crypto/unexportable_key.cc b/naiveproxy/src/crypto/unexportable_key.cc index f5f999c2bc..a199d5e9de 100644 --- a/naiveproxy/src/crypto/unexportable_key.cc +++ b/naiveproxy/src/crypto/unexportable_key.cc @@ -15,10 +15,13 @@ std::unique_ptr (*g_mock_provider)() = nullptr; UnexportableSigningKey::~UnexportableSigningKey() = default; UnexportableKeyProvider::~UnexportableKeyProvider() = default; - VirtualUnexportableSigningKey::~VirtualUnexportableSigningKey() = default; VirtualUnexportableKeyProvider::~VirtualUnexportableKeyProvider() = default; +bool UnexportableSigningKey::IsHardwareBacked() const { + return false; +} + #if BUILDFLAG(IS_WIN) std::unique_ptr GetUnexportableKeyProviderWin(); std::unique_ptr @@ -58,6 +61,10 @@ GetVirtualUnexportableKeyProvider_DO_NOT_USE_METRICS_ONLY() { namespace internal { +bool HasScopedUnexportableKeyProvider() { + return g_mock_provider != nullptr; +} + void SetUnexportableKeyProviderForTesting( std::unique_ptr (*func)()) { if (g_mock_provider) { diff --git a/naiveproxy/src/crypto/unexportable_key.h b/naiveproxy/src/crypto/unexportable_key.h index 73c061d1dd..468df428ca 100644 --- a/naiveproxy/src/crypto/unexportable_key.h +++ b/naiveproxy/src/crypto/unexportable_key.h @@ -61,6 +61,13 @@ class CRYPTO_EXPORT UnexportableSigningKey { virtual std::optional> SignSlowly( base::span data) = 0; + // Returns true if the underlying key is stored in "hardware". Something like + // ARM TrustZone would count as hardware for these purposes. Ideally all + // implementations of this class would return true here, because software + // implementations aren't really "unexportable", but a software implementation + // does exist. + virtual bool IsHardwareBacked() const; + #if BUILDFLAG(IS_MAC) // Returns the underlying reference to a Keychain key owned by the current // instance. @@ -261,6 +268,8 @@ GetSoftwareUnsecureUnexportableKeyProvider(); namespace internal { +CRYPTO_EXPORT bool HasScopedUnexportableKeyProvider(); + CRYPTO_EXPORT void SetUnexportableKeyProviderForTesting( std::unique_ptr (*func)()); diff --git a/naiveproxy/src/crypto/unexportable_key_mac.mm b/naiveproxy/src/crypto/unexportable_key_mac.mm index d4137feb3b..fef1b873cc 100644 --- a/naiveproxy/src/crypto/unexportable_key_mac.mm +++ b/naiveproxy/src/crypto/unexportable_key_mac.mm @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/unexportable_key.h" #import @@ -156,6 +161,8 @@ class UnexportableSigningKeyMac : public UnexportableSigningKey { return CFDataToVec(signature.get()); } + bool IsHardwareBacked() const override { return true; } + SecKeyRef GetSecKeyRef() const override { return key_.get(); } private: diff --git a/naiveproxy/src/crypto/unexportable_key_software_unsecure.cc b/naiveproxy/src/crypto/unexportable_key_software_unsecure.cc index 979198ec87..a89f00a7dc 100644 --- a/naiveproxy/src/crypto/unexportable_key_software_unsecure.cc +++ b/naiveproxy/src/crypto/unexportable_key_software_unsecure.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "base/check.h" #include "build/build_config.h" #include "crypto/sha2.h" diff --git a/naiveproxy/src/crypto/unexportable_key_win.cc b/naiveproxy/src/crypto/unexportable_key_win.cc index 363722c81a..e415bdecd5 100644 --- a/naiveproxy/src/crypto/unexportable_key_win.cc +++ b/naiveproxy/src/crypto/unexportable_key_win.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/unexportable_key_win.h" #include @@ -315,6 +320,8 @@ class ECDSAKey : public UnexportableSigningKey { return SignECDSA(key_.get(), data); } + bool IsHardwareBacked() const override { return true; } + private: ScopedNCryptKey key_; const std::vector wrapped_; @@ -346,6 +353,8 @@ class RSAKey : public UnexportableSigningKey { return SignRSA(key_.get(), data); } + bool IsHardwareBacked() const override { return true; } + private: ScopedNCryptKey key_; const std::vector wrapped_; diff --git a/naiveproxy/src/crypto/user_verifying_key.h b/naiveproxy/src/crypto/user_verifying_key.h index 7352f66631..92daade44c 100644 --- a/naiveproxy/src/crypto/user_verifying_key.h +++ b/naiveproxy/src/crypto/user_verifying_key.h @@ -14,6 +14,7 @@ #include "base/containers/span.h" #include "base/functional/callback.h" #include "base/memory/ref_counted.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "crypto/crypto_export.h" #include "crypto/scoped_lacontext.h" @@ -24,6 +25,25 @@ namespace crypto { typedef std::string UserVerifyingKeyLabel; +// Error values supplied to the callbacks for creating and retrieving +// user-verifying keys, upon failure. +enum class UserVerifyingKeyCreationError { + kPlatformApiError = 0, + kDuplicateCredential = 1, + kNotFound = 2, + kUserCancellation = 3, + kNoMatchingAlgorithm = 4, + kUnknownError = 5, +}; + +// Error values supplied to the callback for signing with a user-verifying key, +// upon failure. +enum class UserVerifyingKeySigningError { + kPlatformApiError = 0, + kUserCancellation = 1, + kUnknownError = 2, +}; + // UserVerifyingSigningKey is a hardware-backed key that triggers a user // verification by the platform before a signature will be provided. // @@ -36,13 +56,13 @@ typedef std::string UserVerifyingKeyLabel; class CRYPTO_EXPORT UserVerifyingSigningKey { public: virtual ~UserVerifyingSigningKey(); + using UserVerifyingKeySignatureCallback = base::OnceCallback, UserVerifyingKeySigningError>)>; // Sign invokes |callback| to provide a signature of |data|, or |nullopt| if // an error occurs during signing. - virtual void Sign( - base::span data, - base::OnceCallback>)> - callback) = 0; + virtual void Sign(base::span data, + UserVerifyingKeySignatureCallback callback) = 0; // Provides the SPKI public key. virtual std::vector GetPublicKey() const = 0; @@ -98,6 +118,10 @@ class CRYPTO_EXPORT UserVerifyingKeyProvider { #endif // BUILDFLAG(IS_MAC) }; + using UserVerifyingKeyCreationCallback = base::OnceCallback, + UserVerifyingKeyCreationError>)>; + virtual ~UserVerifyingKeyProvider(); // Similar to |GenerateSigningKeySlowly| but the resulting signing key can @@ -108,8 +132,7 @@ class CRYPTO_EXPORT UserVerifyingKeyProvider { virtual void GenerateUserVerifyingSigningKey( base::span acceptable_algorithms, - base::OnceCallback)> - callback) = 0; + UserVerifyingKeyCreationCallback callback) = 0; // Similar to |FromWrappedSigningKey| but uses a wrapped key that was // generated from |GenerateUserVerifyingSigningKey|. This can be called from @@ -118,8 +141,7 @@ class CRYPTO_EXPORT UserVerifyingKeyProvider { // Invokes |callback| with the resulting key, or nullptr on error. virtual void GetUserVerifyingSigningKey( UserVerifyingKeyLabel key_label, - base::OnceCallback)> - callback) = 0; + UserVerifyingKeyCreationCallback callback) = 0; // Deletes a user verifying signing key. Work is be done asynchronously on a // low-priority thread when the underlying platform is slow. diff --git a/naiveproxy/src/crypto/user_verifying_key_mac.mm b/naiveproxy/src/crypto/user_verifying_key_mac.mm index f68d7b1fa4..4435380fdc 100644 --- a/naiveproxy/src/crypto/user_verifying_key_mac.mm +++ b/naiveproxy/src/crypto/user_verifying_key_mac.mm @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "crypto/user_verifying_key.h" + +#import + #include #include #include #include -#import - #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/location.h" @@ -18,11 +20,11 @@ #include "base/task/single_thread_task_runner.h" #include "base/task/thread_pool.h" #include "base/threading/scoped_thread_priority.h" +#include "base/types/expected.h" #include "crypto/apple_keychain_v2.h" #include "crypto/scoped_lacontext.h" #include "crypto/unexportable_key.h" #include "crypto/unexportable_key_mac.h" -#include "crypto/user_verifying_key.h" namespace crypto { @@ -46,10 +48,14 @@ class RefCountedUnexportableSigningKey }; // Wraps signing |data| with |key|. -std::optional> DoSign( +base::expected, UserVerifyingKeySigningError> DoSign( std::vector data, scoped_refptr key) { - return key->key()->SignSlowly(data); + auto opt_signature = key->key()->SignSlowly(data); + if (!opt_signature.has_value()) { + return base::unexpected(UserVerifyingKeySigningError::kUnknownError); + } + return base::ok(*opt_signature); } std::string ToString(const std::vector& vec) { @@ -68,8 +74,7 @@ class UserVerifyingSigningKeyMac : public UserVerifyingSigningKey { ~UserVerifyingSigningKeyMac() override = default; void Sign(base::span data, - base::OnceCallback>)> - callback) override { + UserVerifyingKeySignatureCallback callback) override { // Signing will result in the system TouchID prompt being shown if the // caller does not pass an authenticated LAContext, so we run the signing // code in a separate thread. @@ -100,40 +105,42 @@ class UserVerifyingSigningKeyMac : public UserVerifyingSigningKey { const scoped_refptr key_; }; -std::unique_ptr DoGenerateKey( - base::span - acceptable_algorithms, - UnexportableKeyProvider::Config config, - LAContext* lacontext) { +base::expected, + UserVerifyingKeyCreationError> +DoGenerateKey(base::span + acceptable_algorithms, + UnexportableKeyProvider::Config config, + LAContext* lacontext) { std::unique_ptr key_provider = GetUnexportableKeyProviderMac(std::move(config)); if (!key_provider) { - return nullptr; + return base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError); } std::unique_ptr key = key_provider->GenerateSigningKeySlowly(acceptable_algorithms, lacontext); if (!key) { - return nullptr; + return base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError); } - return std::make_unique(std::move(key)); + return base::ok(std::make_unique(std::move(key))); } -std::unique_ptr DoGetKey( - std::vector wrapped_key, - UnexportableKeyProvider::Config config, - LAContext* lacontext) { +base::expected, + UserVerifyingKeyCreationError> +DoGetKey(std::vector wrapped_key, + UnexportableKeyProvider::Config config, + LAContext* lacontext) { std::unique_ptr key_provider = GetUnexportableKeyProviderMac(std::move(config)); if (!key_provider) { - return nullptr; + return base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError); } std::unique_ptr key = key_provider->FromWrappedSigningKeySlowly(wrapped_key, lacontext); if (!key) { - return nullptr; + return base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError); } - return std::make_unique(std::move(key)); + return base::ok(std::make_unique(std::move(key))); } bool DoDeleteKey(std::vector wrapped_key, @@ -156,8 +163,7 @@ class UserVerifyingKeyProviderMac : public UserVerifyingKeyProvider { void GenerateUserVerifyingSigningKey( base::span acceptable_algorithms, - base::OnceCallback)> - callback) override { + UserVerifyingKeyCreationCallback callback) override { // Creating a key may result in disk access, so do it in a separate thread // to avoid blocking the UI. scoped_refptr worker_task_runner = @@ -174,8 +180,7 @@ class UserVerifyingKeyProviderMac : public UserVerifyingKeyProvider { void GetUserVerifyingSigningKey( UserVerifyingKeyLabel key_label, - base::OnceCallback)> - callback) override { + UserVerifyingKeyCreationCallback callback) override { // Retrieving a key may result in disk access, so do it in a separate thread // to avoid blocking the UI. scoped_refptr worker_task_runner = diff --git a/naiveproxy/src/crypto/user_verifying_key_win.cc b/naiveproxy/src/crypto/user_verifying_key_win.cc index 1906b5a5a8..a5f822975b 100644 --- a/naiveproxy/src/crypto/user_verifying_key_win.cc +++ b/naiveproxy/src/crypto/user_verifying_key_win.cc @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifdef UNSAFE_BUFFERS_BUILD +// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. +#pragma allow_unsafe_buffers +#endif + #include "crypto/user_verifying_key.h" #include @@ -44,7 +49,13 @@ using ABI::Windows::Security::Credentials::KeyCredentialCreationOption; using ABI::Windows::Security::Credentials::KeyCredentialOperationResult; using ABI::Windows::Security::Credentials::KeyCredentialRetrievalResult; using ABI::Windows::Security::Credentials::KeyCredentialStatus; +using ABI::Windows::Security::Credentials:: + KeyCredentialStatus_CredentialAlreadyExists; +using ABI::Windows::Security::Credentials::KeyCredentialStatus_NotFound; using ABI::Windows::Security::Credentials::KeyCredentialStatus_Success; +using ABI::Windows::Security::Credentials::KeyCredentialStatus_UserCanceled; +using ABI::Windows::Security::Credentials:: + KeyCredentialStatus_UserPrefersPassword; using ABI::Windows::Security::Cryptography::Core:: CryptographicPublicKeyBlobType_X509SubjectPublicKeyInfo; using ABI::Windows::Storage::Streams::IBuffer; @@ -221,7 +232,7 @@ SplitOnceCallbackIntoThree(base::OnceCallback callback) { } void OnSigningSuccess( - base::OnceCallback>)> callback, + UserVerifyingSigningKey::UserVerifyingKeySignatureCallback callback, scoped_refptr foregrounder, ComPtr sign_result) { foregrounder->Stop(); @@ -232,7 +243,16 @@ void OnSigningSuccess( LOG(ERROR) << FormatError( "Failed to obtain Status from IKeyCredentialOperationResult", hr); RecordSignAsyncResult(KeyCredentialSignResult::kInvalidStatusReturned); - std::move(callback).Run(std::nullopt); + UserVerifyingKeySigningError sign_error; + switch (status) { + case KeyCredentialStatus_UserCanceled: + case KeyCredentialStatus_UserPrefersPassword: + sign_error = UserVerifyingKeySigningError::kUserCancellation; + break; + default: + sign_error = UserVerifyingKeySigningError::kUnknownError; + } + std::move(callback).Run(base::unexpected(sign_error)); return; } @@ -242,7 +262,8 @@ void OnSigningSuccess( LOG(ERROR) << FormatError( "Failed to obtain Result from IKeyCredentialOperationResult", hr); RecordSignAsyncResult(KeyCredentialSignResult::kInvalidResultReturned); - std::move(callback).Run(std::nullopt); + std::move(callback).Run( + base::unexpected(UserVerifyingKeySigningError::kPlatformApiError)); return; } @@ -255,36 +276,39 @@ void OnSigningSuccess( hr); RecordSignAsyncResult( KeyCredentialSignResult::kInvalidSignatureBufferReturned); - std::move(callback).Run(std::nullopt); + std::move(callback).Run( + base::unexpected(UserVerifyingKeySigningError::kPlatformApiError)); return; } RecordSignAsyncResult(KeyCredentialSignResult::kSucceeded); - std::move(callback).Run( - std::vector(signature_data, signature_data + signature_length)); + std::move(callback).Run(base::ok( + std::vector(signature_data, signature_data + signature_length))); } void OnSigningError( - base::OnceCallback>)> callback, + UserVerifyingSigningKey::UserVerifyingKeySignatureCallback callback, scoped_refptr foregrounder, HRESULT hr) { foregrounder->Stop(); LOG(ERROR) << FormatError("Failed to sign with user-verifying signature", hr); RecordSignAsyncResult(KeyCredentialSignResult::kAPIReturnedError); - std::move(callback).Run(std::nullopt); + std::move(callback).Run( + base::unexpected(UserVerifyingKeySigningError::kPlatformApiError)); } void SignInternal( std::vector data, ComPtr credential, - base::OnceCallback>)> callback) { + UserVerifyingSigningKey::UserVerifyingKeySignatureCallback callback) { Microsoft::WRL::ComPtr signing_buf; HRESULT hr = base::win::CreateIBufferFromData(data.data(), data.size(), &signing_buf); if (FAILED(hr)) { LOG(ERROR) << FormatError("SignInternal: IBuffer creation failed", hr); RecordSignAsyncResult(KeyCredentialSignResult::kIBufferCreationFailed); - std::move(callback).Run(std::nullopt); + std::move(callback).Run( + base::unexpected(UserVerifyingKeySigningError::kPlatformApiError)); return; } @@ -294,7 +318,8 @@ void SignInternal( LOG(ERROR) << FormatError("SignInternal: Call to RequestSignAsync failed", hr); RecordSignAsyncResult(KeyCredentialSignResult::kRequestSignAsyncFailed); - std::move(callback).Run(std::nullopt); + std::move(callback).Run( + base::unexpected(UserVerifyingKeySigningError::kPlatformApiError)); return; } @@ -310,7 +335,8 @@ void SignInternal( LOG(ERROR) << FormatError("SignInternal: Call to PostAsyncHandlers failed", hr); RecordSignAsyncResult(KeyCredentialSignResult::kPostAsyncHandlersFailed); - std::move(std::get<2>(callback_splits)).Run(std::nullopt); + std::move(std::get<2>(callback_splits)) + .Run(base::unexpected(UserVerifyingKeySigningError::kPlatformApiError)); return; } @@ -325,8 +351,7 @@ class UserVerifyingSigningKeyWin : public UserVerifyingSigningKey { ~UserVerifyingSigningKeyWin() override = default; void Sign(base::span data, - base::OnceCallback>)> - callback) override { + UserVerifyingKeySignatureCallback callback) override { scoped_refptr task_runner = base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::USER_BLOCKING}); @@ -364,7 +389,7 @@ class UserVerifyingSigningKeyWin : public UserVerifyingSigningKey { }; void OnKeyCreationCompletionSuccess( - base::OnceCallback)> callback, + UserVerifyingKeyProvider::UserVerifyingKeyCreationCallback callback, std::string key_name, scoped_refptr foregrounder, ComPtr key_result) { @@ -378,13 +403,29 @@ void OnKeyCreationCompletionSuccess( LOG(ERROR) << FormatError( "Failed to obtain Status from IKeyCredentialRetrievalResult", hr); RecordCreateAsyncResult(KeyCredentialCreateResult::kInvalidStatusReturned); - std::move(callback).Run(nullptr); + std::move(callback).Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); return; } else if (status != KeyCredentialStatus_Success) { LOG(ERROR) << "IKeyCredentialRetrievalResult failed with status " << static_cast(status); RecordCreateAsyncResult(KeyCredentialCreateResult::kInvalidResultReturned); - std::move(callback).Run(nullptr); + UserVerifyingKeyCreationError uv_key_error; + switch (status) { + case KeyCredentialStatus_CredentialAlreadyExists: + uv_key_error = UserVerifyingKeyCreationError::kDuplicateCredential; + break; + case KeyCredentialStatus_NotFound: + uv_key_error = UserVerifyingKeyCreationError::kNotFound; + break; + case KeyCredentialStatus_UserCanceled: + case KeyCredentialStatus_UserPrefersPassword: + uv_key_error = UserVerifyingKeyCreationError::kUserCancellation; + break; + default: + uv_key_error = UserVerifyingKeyCreationError::kUnknownError; + } + std::move(callback).Run(base::unexpected(uv_key_error)); return; } @@ -395,18 +436,19 @@ void OnKeyCreationCompletionSuccess( "Failed to obtain KeyCredential from KeyCredentialRetrievalResult", hr); RecordCreateAsyncResult( KeyCredentialCreateResult::kInvalidCredentialReturned); - std::move(callback).Run(nullptr); + std::move(callback).Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); return; } RecordCreateAsyncResult(KeyCredentialCreateResult::kSucceeded); auto key = std::make_unique( std::move(key_name), std::move(credential)); - std::move(callback).Run(std::move(key)); + std::move(callback).Run(base::ok(std::move(key))); } void OnKeyCreationCompletionError( - base::OnceCallback)> callback, + UserVerifyingKeyProvider::UserVerifyingKeyCreationCallback callback, scoped_refptr foregrounder, HRESULT hr) { if (foregrounder) { @@ -415,13 +457,13 @@ void OnKeyCreationCompletionError( LOG(ERROR) << FormatError("Failed to obtain user-verifying key from system", hr); RecordCreateAsyncResult(KeyCredentialCreateResult::kAPIReturnedError); - std::move(callback).Run(nullptr); + std::move(callback).Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); } void GenerateUserVerifyingSigningKeyInternal( std::string key_label, - base::OnceCallback)> - callback) { + UserVerifyingKeyProvider::UserVerifyingKeyCreationCallback callback) { SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); auto key_name = base::win::ScopedHString::Create(key_label); @@ -435,7 +477,8 @@ void GenerateUserVerifyingSigningKeyInternal( "factory for KeyCredentialManager", hr); RecordCreateAsyncResult(KeyCredentialCreateResult::kNoActivationFactory); - std::move(callback).Run(nullptr); + std::move(callback).Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); return; } ComPtr> create_result; @@ -450,7 +493,8 @@ void GenerateUserVerifyingSigningKeyInternal( hr); RecordCreateAsyncResult( KeyCredentialCreateResult::kRequestCreateAsyncFailed); - std::move(callback).Run(nullptr); + std::move(callback).Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); return; } @@ -470,7 +514,9 @@ void GenerateUserVerifyingSigningKeyInternal( hr); RecordCreateAsyncResult( KeyCredentialCreateResult::kPostAsyncHandlersFailed); - std::move(std::get<2>(callback_splits)).Run(nullptr); + std::move(std::get<2>(callback_splits)) + .Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); return; } @@ -479,8 +525,7 @@ void GenerateUserVerifyingSigningKeyInternal( void GetUserVerifyingSigningKeyInternal( std::string key_label, - base::OnceCallback)> - callback) { + UserVerifyingKeyProvider::UserVerifyingKeyCreationCallback callback) { SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); auto key_name = base::win::ScopedHString::Create(key_label); @@ -493,7 +538,8 @@ void GetUserVerifyingSigningKeyInternal( "GetUserVerifyingSigningKeyInternal: Failed to obtain activation " "factory for KeyCredentialManager", hr); - std::move(callback).Run(nullptr); + std::move(callback).Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); return; } @@ -502,7 +548,8 @@ void GetUserVerifyingSigningKeyInternal( if (FAILED(hr)) { LOG(ERROR) << FormatError( "GetUserVerifyingSigningKeyInternal: Call to OpenAsync failed", hr); - std::move(callback).Run(nullptr); + std::move(callback).Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); return; } @@ -520,7 +567,9 @@ void GetUserVerifyingSigningKeyInternal( LOG(ERROR) << FormatError( "GetUserVerifyingSigningKeyInternal: Call to PostAsyncHandlers failed", hr); - std::move(std::get<2>(callback_splits)).Run(nullptr); + std::move(std::get<2>(callback_splits)) + .Run( + base::unexpected(UserVerifyingKeyCreationError::kPlatformApiError)); return; } } @@ -576,13 +625,13 @@ class UserVerifyingKeyProviderWin : public UserVerifyingKeyProvider { void GenerateUserVerifyingSigningKey( base::span acceptable_algorithms, - base::OnceCallback)> - callback) override { + UserVerifyingKeyCreationCallback callback) override { // Ignore the non-empty return value of `SelectAlgorithm` unless in the // future Windows supports more algorithms. if (!SelectAlgorithm(acceptable_algorithms)) { LOG(ERROR) << "Key generation does not include a supported algorithm."; - std::move(callback).Run(nullptr); + std::move(callback).Run(base::unexpected( + UserVerifyingKeyCreationError::kNoMatchingAlgorithm)); return; } @@ -603,8 +652,7 @@ class UserVerifyingKeyProviderWin : public UserVerifyingKeyProvider { void GetUserVerifyingSigningKey( UserVerifyingKeyLabel key_label, - base::OnceCallback)> - callback) override { + UserVerifyingKeyCreationCallback callback) override { scoped_refptr task_runner = base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::USER_BLOCKING}); diff --git a/naiveproxy/src/get-clang.sh b/naiveproxy/src/get-clang.sh index ddf7365d5a..791ad0c8f4 100755 --- a/naiveproxy/src/get-clang.sh +++ b/naiveproxy/src/get-clang.sh @@ -28,9 +28,9 @@ cd - echo $CLANG_REVISION >third_party/llvm-build/Release+Asserts/cr_build_revision if [ ! -d third_party/llvm-build/Release+Asserts/bin ]; then mkdir -p third_party/llvm-build/Release+Asserts - clang_path="clang-$CLANG_REVISION.tgz" + clang_path="clang-$CLANG_REVISION.tar.xz" clang_url="https://commondatastorage.googleapis.com/chromium-browser-clang/$WITH_CLANG/$clang_path" - curl "$clang_url" | tar xzf - -C third_party/llvm-build/Release+Asserts + curl "$clang_url" | tar xJf - -C third_party/llvm-build/Release+Asserts fi # sccache diff --git a/naiveproxy/src/net/BUILD.gn b/naiveproxy/src/net/BUILD.gn index 8af1173761..bc5ff093b3 100644 --- a/naiveproxy/src/net/BUILD.gn +++ b/naiveproxy/src/net/BUILD.gn @@ -330,12 +330,12 @@ component("net") { "cert/ev_root_ca_metadata.h", "cert/internal/cert_issuer_source_aia.cc", "cert/internal/cert_issuer_source_aia.h", + "cert/internal/platform_trust_store.cc", + "cert/internal/platform_trust_store.h", "cert/internal/revocation_checker.cc", "cert/internal/revocation_checker.h", "cert/internal/system_trust_store.cc", "cert/internal/system_trust_store.h", - "cert/internal/trust_store_features.cc", - "cert/internal/trust_store_features.h", "cert/known_roots.cc", "cert/known_roots.h", "cert/merkle_audit_proof.cc", @@ -515,6 +515,8 @@ component("net") { "first_party_sets/first_party_sets_cache_filter.h", "first_party_sets/first_party_sets_context_config.cc", "first_party_sets/first_party_sets_context_config.h", + "first_party_sets/first_party_sets_validator.cc", + "first_party_sets/first_party_sets_validator.h", "first_party_sets/global_first_party_sets.cc", "first_party_sets/global_first_party_sets.h", "first_party_sets/local_set_declaration.cc", @@ -623,10 +625,20 @@ component("net") { "http/http_stream_factory_job.h", "http/http_stream_factory_job_controller.cc", "http/http_stream_factory_job_controller.h", + "http/http_stream_key.cc", + "http/http_stream_key.h", "http/http_stream_parser.cc", "http/http_stream_parser.h", + "http/http_stream_pool.cc", + "http/http_stream_pool.h", + "http/http_stream_pool_group.cc", + "http/http_stream_pool_group.h", + "http/http_stream_pool_job.cc", + "http/http_stream_pool_job.h", "http/http_stream_request.cc", "http/http_stream_request.h", + "http/http_text_based_stream_handle.cc", + "http/http_text_based_stream_handle.h", "http/http_transaction.h", "http/http_transaction_factory.h", "http/http_util.cc", @@ -821,6 +833,17 @@ component("net") { "quic/web_transport_client.h", "quic/web_transport_error.cc", "quic/web_transport_error.h", + "shared_dictionary/shared_dictionary.h", + "shared_dictionary/shared_dictionary_constants.h", + "shared_dictionary/shared_dictionary_getter.h", + "shared_dictionary/shared_dictionary_header_checker_source_stream.cc", + "shared_dictionary/shared_dictionary_header_checker_source_stream.h", + "shared_dictionary/shared_dictionary_isolation_key.cc", + "shared_dictionary/shared_dictionary_isolation_key.h", + "shared_dictionary/shared_dictionary_network_transaction.cc", + "shared_dictionary/shared_dictionary_network_transaction.h", + "shared_dictionary/shared_dictionary_network_transaction_factory.cc", + "shared_dictionary/shared_dictionary_network_transaction_factory.h", "socket/client_socket_factory.cc", "socket/client_socket_factory.h", "socket/client_socket_handle.cc", @@ -880,13 +903,21 @@ component("net") { "socket/ssl_server_socket_impl.cc", "socket/ssl_server_socket_impl.h", "socket/ssl_socket.h", + "socket/stream_attempt.cc", + "socket/stream_attempt.h", "socket/stream_socket.cc", "socket/stream_socket.h", + "socket/stream_socket_handle.cc", + "socket/stream_socket_handle.h", "socket/tcp_client_socket.cc", "socket/tcp_client_socket.h", "socket/tcp_server_socket.cc", "socket/tcp_server_socket.h", "socket/tcp_socket.h", + "socket/tcp_stream_attempt.cc", + "socket/tcp_stream_attempt.h", + "socket/tls_stream_attempt.cc", + "socket/tls_stream_attempt.h", "socket/transport_client_socket.cc", "socket/transport_client_socket.h", "socket/transport_client_socket_pool.cc", @@ -985,6 +1016,7 @@ component("net") { "ssl/ssl_server_config.h", "ssl/threaded_ssl_private_key.cc", "ssl/threaded_ssl_private_key.h", + "storage_access_api/status.h", "url_request/clear_site_data.cc", "url_request/clear_site_data.h", "url_request/redirect_info.cc", @@ -1005,8 +1037,6 @@ component("net") { "url_request/url_request_context_getter_observer.h", "url_request/url_request_error_job.cc", "url_request/url_request_error_job.h", - "url_request/url_request_filter.cc", - "url_request/url_request_filter.h", "url_request/url_request_http_job.cc", "url_request/url_request_http_job.h", "url_request/url_request_interceptor.cc", @@ -1103,6 +1133,7 @@ component("net") { "reporting/reporting_report.h", "reporting/reporting_service.cc", "reporting/reporting_service.h", + "reporting/reporting_target_type.h", "reporting/reporting_uploader.cc", "reporting/reporting_uploader.h", ] @@ -1112,17 +1143,20 @@ component("net") { sources += [ "device_bound_sessions/cookie_craving.cc", "device_bound_sessions/cookie_craving.h", - "device_bound_sessions/device_bound_session_params.h", - "device_bound_sessions/device_bound_session_registration_fetcher_param.cc", - "device_bound_sessions/device_bound_session_registration_fetcher_param.h", - "device_bound_sessions/device_bound_session_service.cc", - "device_bound_sessions/device_bound_session_service.h", "device_bound_sessions/registration_fetcher.cc", "device_bound_sessions/registration_fetcher.h", + "device_bound_sessions/registration_fetcher_param.cc", + "device_bound_sessions/registration_fetcher_param.h", "device_bound_sessions/session_binding_utils.cc", "device_bound_sessions/session_binding_utils.h", "device_bound_sessions/session_inclusion_rules.cc", "device_bound_sessions/session_inclusion_rules.h", + "device_bound_sessions/session_json_utils.cc", + "device_bound_sessions/session_json_utils.h", + "device_bound_sessions/session_params.cc", + "device_bound_sessions/session_params.h", + "device_bound_sessions/session_service.cc", + "device_bound_sessions/session_service.h", "device_bound_sessions/unexportable_key_service_factory.cc", "device_bound_sessions/unexportable_key_service_factory.h", ] @@ -1242,6 +1276,8 @@ component("net") { "base/net_errors_win.cc", "base/network_change_notifier_win.cc", "base/network_change_notifier_win.h", + "base/network_cost_change_notifier_win.cc", + "base/network_cost_change_notifier_win.h", "base/network_interfaces_win.cc", "base/network_interfaces_win.h", "base/platform_mime_util_win.cc", @@ -1730,9 +1766,6 @@ source_set("net_public_deps") { } } -if (is_android) { -} - component("uri_template") { sources = [ "third_party/uri_template/uri_template.cc", diff --git a/naiveproxy/src/net/android/network_library_stub.cc b/naiveproxy/src/net/android/network_library_stub.cc index 5a391da45c..8632eba439 100644 --- a/naiveproxy/src/net/android/network_library_stub.cc +++ b/naiveproxy/src/net/android/network_library_stub.cc @@ -10,8 +10,8 @@ namespace net { namespace android { void VerifyX509CertChain(const std::vector& cert_chain, - base::StringPiece auth_type, - base::StringPiece host, + std::string_view auth_type, + std::string_view host, CertVerifyStatusAndroid* status, bool* is_issued_by_known_root, std::vector* verified_chain) { @@ -23,7 +23,7 @@ void AddTestRootCertificate(const uint8_t* cert, size_t len) { void ClearTestRootCertificates() { } -bool IsCleartextPermitted(base::StringPiece host) { +bool IsCleartextPermitted(std::string_view host) { return true; } @@ -31,7 +31,7 @@ bool HaveOnlyLoopbackAddresses() { return false; } -bool GetMimeTypeFromExtension(base::StringPiece extension, +bool GetMimeTypeFromExtension(std::string_view extension, std::string* result) { return false; } diff --git a/naiveproxy/src/net/base/data_url.cc b/naiveproxy/src/net/base/data_url.cc index d36b9249dc..71b70db4cc 100644 --- a/naiveproxy/src/net/base/data_url.cc +++ b/naiveproxy/src/net/base/data_url.cc @@ -10,12 +10,11 @@ #include #include "base/base64.h" -#include "base/feature_list.h" -#include "base/features.h" #include "base/ranges/algorithm.h" #include "base/strings/escape.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "net/base/features.h" #include "net/base/mime_util.h" #include "net/http/http_response_headers.h" #include "net/http/http_util.h" @@ -54,15 +53,8 @@ bool DataURL::Parse(const GURL& url, DCHECK(charset->empty()); DCHECK(!data || data->empty()); - std::string_view content; - std::string content_string; - if (base::FeatureList::IsEnabled(base::features::kOptimizeDataUrls)) { - // Avoid copying the URL content which can be expensive for large URLs. - content = url.GetContentPiece(); - } else { - content_string = url.GetContent(); - content = content_string; - } + // Avoid copying the URL content which can be expensive for large URLs. + std::string_view content = url.GetContentPiece(); std::string_view::const_iterator comma = base::ranges::find(content, ','); if (comma == content.end()) @@ -136,16 +128,33 @@ bool DataURL::Parse(const GURL& url, // of the data, and should be stripped. Otherwise, the escaped whitespace // could be part of the payload, so don't strip it. if (base64_encoded) { - // If the data URL is well formed, we can decode it immediately. - if (base::FeatureList::IsEnabled(base::features::kOptimizeDataUrls) && - IsDataURLReadyForDecode(raw_body)) { - if (!base::Base64Decode(raw_body, data)) - return false; + if (base::FeatureList::IsEnabled(features::kOptimizeParsingDataUrls)) { + // Since whitespace and invalid characters in input will always cause + // `Base64Decode` to fail, just handle unescaping the URL on failure. + // This is not much slower than scanning the URL for being well formed + // first, even for input with whitespace. + if (!base::Base64Decode(raw_body, data)) { + std::string unescaped_body = + base::UnescapeBinaryURLComponent(raw_body); + if (!base::Base64Decode(unescaped_body, data, + base::Base64DecodePolicy::kForgiving)) { + return false; + } + } } else { - std::string unescaped_body = base::UnescapeBinaryURLComponent(raw_body); - if (!base::Base64Decode(unescaped_body, data, - base::Base64DecodePolicy::kForgiving)) - return false; + // If the data URL is well formed, we can decode it immediately. + if (IsDataURLReadyForDecode(raw_body)) { + if (!base::Base64Decode(raw_body, data)) { + return false; + } + } else { + std::string unescaped_body = + base::UnescapeBinaryURLComponent(raw_body); + if (!base::Base64Decode(unescaped_body, data, + base::Base64DecodePolicy::kForgiving)) { + return false; + } + } } } else { // Strip whitespace for non-text MIME types. @@ -191,10 +200,14 @@ Error DataURL::BuildResponse(const GURL& url, if (!charset->empty()) content_type.append(";charset=" + *charset); // The terminal double CRLF isn't needed by TryToCreate(). - *headers = HttpResponseHeaders::TryToCreate( - "HTTP/1.1 200 OK\r\n" - "Content-Type:" + - content_type); + if (base::FeatureList::IsEnabled(features::kOptimizeParsingDataUrls)) { + *headers = HttpResponseHeaders::TryToCreateForDataURL(content_type); + } else { + *headers = HttpResponseHeaders::TryToCreate( + "HTTP/1.1 200 OK\r\n" + "Content-Type:" + + content_type); + } // Above line should always succeed - TryToCreate() only fails when there are // nulls in the string, and DataURL::Parse() can't return nulls in anything // but the |data| argument. diff --git a/naiveproxy/src/net/base/elements_upload_data_stream.cc b/naiveproxy/src/net/base/elements_upload_data_stream.cc index b6fcbf7dde..18f9bc3d40 100644 --- a/naiveproxy/src/net/base/elements_upload_data_stream.cc +++ b/naiveproxy/src/net/base/elements_upload_data_stream.cc @@ -131,8 +131,12 @@ void ElementsUploadDataStream::OnReadElementCompleted( ProcessReadResult(buf, result); result = ReadElements(buf); - if (result != ERR_IO_PENDING) + if (result != ERR_IO_PENDING) { + if (result < ERR_IO_PENDING) { + LOG(ERROR) << "OnReadElementCompleted failed with Error: " << result; + } OnReadCompleted(result); + } } void ElementsUploadDataStream::ProcessReadResult( diff --git a/naiveproxy/src/net/base/features.cc b/naiveproxy/src/net/base/features.cc index 85361b5394..067bc25deb 100644 --- a/naiveproxy/src/net/base/features.cc +++ b/naiveproxy/src/net/base/features.cc @@ -105,6 +105,21 @@ BASE_FEATURE(kNetworkQualityEstimator, "NetworkQualityEstimator", base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam kRecentHTTPThresholdInSeconds{ + &kNetworkQualityEstimator, "RecentHTTPThresholdInSeconds", -1}; +const base::FeatureParam kRecentTransportThresholdInSeconds{ + &kNetworkQualityEstimator, "RecentTransportThresholdInSeconds", -1}; +const base::FeatureParam kRecentEndToEndThresholdInSeconds{ + &kNetworkQualityEstimator, "RecentEndToEndThresholdInSeconds", -1}; +const base::FeatureParam kCountNewObservationsReceivedComputeEct{ + &kNetworkQualityEstimator, "CountNewObservationsReceivedComputeEct", 50}; +const base::FeatureParam kObservationBufferSize{ + &kNetworkQualityEstimator, "ObservationBufferSize", 300}; +const base::FeatureParam + kEffectiveConnectionTypeRecomputationInterval{ + &kNetworkQualityEstimator, + "EffectiveConnectionTypeRecomputationInterval", base::Seconds(10)}; + BASE_FEATURE(kSplitCacheByIncludeCredentials, "SplitCacheByIncludeCredentials", base::FEATURE_DISABLED_BY_DEFAULT); @@ -121,16 +136,6 @@ BASE_FEATURE(kPartitionConnectionsByNetworkIsolationKey, "PartitionConnectionsByNetworkIsolationKey", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kEnableCrossSiteFlagNetworkIsolationKey, - "EnableCrossSiteFlagNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kEnableFrameSiteSharedOpaqueNetworkIsolationKey, - "EnableFrameSiteSharedOpaqueNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kHttpCacheKeyingExperimentControlGroup, - "HttpCacheKeyingExperimentControlGroup", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kTLS13KeyUpdate, "TLS13KeyUpdate", base::FEATURE_DISABLED_BY_DEFAULT); @@ -219,7 +224,7 @@ extern const base::FeatureParam BASE_FEATURE(kAncestorChainBitEnabledInPartitionedCookies, "AncestorChainBitEnabledInPartitionedCookies", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kStaticKeyPinningEnforcement, "StaticKeyPinningEnforcement", @@ -238,13 +243,9 @@ BASE_FEATURE(kThirdPartyStoragePartitioning, // Whether to use the new code paths needed to support partitioning Blob URLs. // This exists as a kill-switch in case an issue is identified with the Blob // URL implementation that causes breakage. -BASE_FEATURE(kSupportPartitionedBlobUrl, - "SupportPartitionedBlobUrl", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kTopLevelTpcdOriginTrial, "TopLevelTpcdOriginTrial", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kTpcdTrialSettings, "TpcdSupportSettings", @@ -549,4 +550,24 @@ BASE_FEATURE(kSpdySessionForProxyAdditionalChecks, "SpdySessionForProxyAdditionalChecks", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kCompressionDictionaryTransportOverHttp1, + "CompressionDictionaryTransportOverHttp1", + base::FEATURE_ENABLED_BY_DEFAULT); + +BASE_FEATURE(kCompressionDictionaryTransportOverHttp2, + "CompressionDictionaryTransportOverHttp2", + base::FEATURE_ENABLED_BY_DEFAULT); + +BASE_FEATURE(kCompressionDictionaryTransportRequireKnownRootCert, + "CompressionDictionaryTransportRequireKnownRootCert", + base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kReportingApiEnableEnterpriseCookieIssues, + "ReportingApiEnableEnterpriseCookieIssues", + base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kOptimizeParsingDataUrls, + "OptimizeParsingDataUrls", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace net::features diff --git a/naiveproxy/src/net/base/features.h b/naiveproxy/src/net/base/features.h index ffa3f6ced7..8d4fb2164e 100644 --- a/naiveproxy/src/net/base/features.h +++ b/naiveproxy/src/net/base/features.h @@ -121,6 +121,37 @@ NET_EXPORT BASE_DECLARE_FEATURE(kEnableTLS13EarlyData); // quality estimator (NQE). NET_EXPORT BASE_DECLARE_FEATURE(kNetworkQualityEstimator); +// The maximum age in seconds of observations to be used for calculating the +// HTTP RTT from the historical data. +// Negative value means infinite. i.e. all data are used. +NET_EXPORT extern const base::FeatureParam kRecentHTTPThresholdInSeconds; + +// The maximum age in seconds of observations to be used for calculating the +// transport RTT from the historical data. +// Negative value means infinite. i.e. all data are used. +NET_EXPORT extern const base::FeatureParam + kRecentTransportThresholdInSeconds; + +// The maximum age in seconds of observations to be used for calculating the +// end to end RTT from the historical data. +// Negative value means infinite. i.e. all data are used. +NET_EXPORT extern const base::FeatureParam + kRecentEndToEndThresholdInSeconds; + +// Number of observations received after which the effective connection type +// should be recomputed. +NET_EXPORT extern const base::FeatureParam + kCountNewObservationsReceivedComputeEct; + +// Maximum number of observations that can be held in a single +// ObservationBuffer. +NET_EXPORT extern const base::FeatureParam kObservationBufferSize; + +// Minimum duration between two consecutive computations of effective +// connection type. Set to non-zero value as a performance optimization. +NET_EXPORT extern const base::FeatureParam + kEffectiveConnectionTypeRecomputationInterval; + // Splits cache entries by the request's includeCredentials. NET_EXPORT BASE_DECLARE_FEATURE(kSplitCacheByIncludeCredentials); @@ -138,17 +169,6 @@ NET_EXPORT BASE_DECLARE_FEATURE(kSplitCodeCacheByNetworkIsolationKey); // See https://github.com/MattMenke2/Explainer---Partition-Network-State. NET_EXPORT BASE_DECLARE_FEATURE(kPartitionConnectionsByNetworkIsolationKey); -// Creates a NetworkIsolationKey which is used -// to partition the HTTP cache. This key will have the following properties: -// `top_frame_site_` -> the schemeful site of the top level page. -// `frame_site_` -> std::nullopt. -// `is_cross_site_` -> a boolean indicating whether the frame site is -// schemefully cross-site from the top-level site. -NET_EXPORT BASE_DECLARE_FEATURE(kEnableCrossSiteFlagNetworkIsolationKey); -NET_EXPORT BASE_DECLARE_FEATURE( - kEnableFrameSiteSharedOpaqueNetworkIsolationKey); -NET_EXPORT BASE_DECLARE_FEATURE(kHttpCacheKeyingExperimentControlGroup); - // Enables sending TLS 1.3 Key Update messages on TLS 1.3 connections in order // to ensure that this corner of the spec is exercised. This is currently // disabled by default because we discovered incompatibilities with some @@ -255,7 +275,6 @@ NET_EXPORT BASE_DECLARE_FEATURE(kStaticKeyPinningEnforcement); NET_EXPORT BASE_DECLARE_FEATURE(kCookieDomainRejectNonASCII); NET_EXPORT BASE_DECLARE_FEATURE(kThirdPartyStoragePartitioning); -NET_EXPORT BASE_DECLARE_FEATURE(kSupportPartitionedBlobUrl); // Controls consideration of top-level 3PCD origin trial settings. NET_EXPORT BASE_DECLARE_FEATURE(kTopLevelTpcdOriginTrial); @@ -414,9 +433,9 @@ NET_EXPORT extern const base::FeatureParam kIpPrivacyAlwaysProxy; // defaults to true and is intended for development of the QUIC functionality. NET_EXPORT extern const base::FeatureParam kIpPrivacyFallbackToDirect; -// Identifier for an experiment arm, to be sent to IP Protection proxies in the -// `Ip-Protection-Debug-Experiment-Arm` header. The default value, 0, is not -// sent. +// Identifier for an experiment arm, to be sent to IP Protection proxies and the +// token server in the `Ip-Protection-Debug-Experiment-Arm` header. The default +// value, 0, is not sent. NET_EXPORT extern const base::FeatureParam kIpPrivacyDebugExperimentArm; // Whether QuicParams::migrate_sessions_on_network_change_v2 defaults to true or @@ -522,6 +541,27 @@ NET_EXPORT BASE_DECLARE_FEATURE(kStorageAccessHeaders); // not causing any problems. NET_EXPORT BASE_DECLARE_FEATURE(kSpdySessionForProxyAdditionalChecks); +// When this feature is enabled, Chromium can use stored shared dictionaries +// even when the connection is using HTTP/1 for non-localhost requests. +NET_EXPORT BASE_DECLARE_FEATURE(kCompressionDictionaryTransportOverHttp1); + +// When this feature is enabled, Chromium can use stored shared dictionaries +// even when the connection is using HTTP/2 for non-localhost requests. +NET_EXPORT BASE_DECLARE_FEATURE(kCompressionDictionaryTransportOverHttp2); + +// When this feature is enabled, Chromium will use stored shared dictionaries +// only if the request URL is a localhost URL or the transport layer is using a +// certificate rooted at a standard CA root. +NET_EXPORT BASE_DECLARE_FEATURE( + kCompressionDictionaryTransportRequireKnownRootCert); + +// Enables enterprises to use the Reporting API to collect 3PCD-related +// issues from sites used in their organization. +NET_EXPORT BASE_DECLARE_FEATURE(kReportingApiEnableEnterpriseCookieIssues); + +// Optimize parsing data: URLs. +NET_EXPORT BASE_DECLARE_FEATURE(kOptimizeParsingDataUrls); + } // namespace net::features #endif // NET_BASE_FEATURES_H_ diff --git a/naiveproxy/src/net/base/file_stream.cc b/naiveproxy/src/net/base/file_stream.cc index c554ecb25d..2e3988d6d9 100644 --- a/naiveproxy/src/net/base/file_stream.cc +++ b/naiveproxy/src/net/base/file_stream.cc @@ -6,6 +6,7 @@ #include +#include "build/build_config.h" #include "net/base/file_stream_context.h" #include "net/base/net_errors.h" @@ -91,4 +92,11 @@ int FileStream::Flush(CompletionOnceCallback callback) { return ERR_IO_PENDING; } +#if BUILDFLAG(IS_WIN) +int FileStream::ConnectNamedPipe(CompletionOnceCallback callback) { + return IsOpen() ? context_->ConnectNamedPipe(std::move(callback)) + : ERR_UNEXPECTED; +} +#endif // BUILDFLAG(IS_WIN) + } // namespace net diff --git a/naiveproxy/src/net/base/file_stream.h b/naiveproxy/src/net/base/file_stream.h index 407f5e1fa1..6beb745852 100644 --- a/naiveproxy/src/net/base/file_stream.h +++ b/naiveproxy/src/net/base/file_stream.h @@ -15,6 +15,7 @@ #include #include "base/files/file.h" +#include "build/build_config.h" #include "net/base/completion_once_callback.h" #include "net/base/net_export.h" @@ -33,7 +34,9 @@ class NET_EXPORT FileStream { explicit FileStream(const scoped_refptr& task_runner); // Construct a FileStream with an already opened file. |file| must be opened - // for async reading on Windows, and sync reading everywehere else. + // for async reading on Windows, and sync reading everywehere else. To use + // ConnectNamedPipe(), `file` must wrap a handle from CreateNamedPipe() with + // `FILE_FLAG_OVERLAPPED`. // // Uses |task_runner| for asynchronous operations. FileStream(base::File file, @@ -157,6 +160,15 @@ class NET_EXPORT FileStream { // This method should not be called if the stream was opened READ_ONLY. virtual int Flush(CompletionOnceCallback callback); +#if BUILDFLAG(IS_WIN) + // Waits for a client to connect to the named pipe provided to the two-arg + // constructor. Returns `OK` if the client has already connected, + // `ERR_IO_PENDING` if `callback` will be run later with the result of the + // operation once the client connects, or another `Error` value in case of + // failure. + int ConnectNamedPipe(CompletionOnceCallback callback); +#endif // BUILDFLAG(IS_WIN) + private: class Context; diff --git a/naiveproxy/src/net/base/file_stream_context.h b/naiveproxy/src/net/base/file_stream_context.h index 493a9e5a68..27d52246e4 100644 --- a/naiveproxy/src/net/base/file_stream_context.h +++ b/naiveproxy/src/net/base/file_stream_context.h @@ -51,6 +51,7 @@ namespace net { class IOBuffer; +// Implementation for a FileStream. See file_stream.h for documentation. #if BUILDFLAG(IS_WIN) class FileStream::Context : public base::MessagePumpForIO::IOHandler { #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) @@ -77,6 +78,10 @@ class FileStream::Context { int Write(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); +#if BUILDFLAG(IS_WIN) + int ConnectNamedPipe(CompletionOnceCallback callback); +#endif + bool async_in_progress() const { return async_in_progress_; } //////////////////////////////////////////////////////////////////////////// diff --git a/naiveproxy/src/net/base/file_stream_context_win.cc b/naiveproxy/src/net/base/file_stream_context_win.cc index 67c46ce182..b5ba60a8c8 100644 --- a/naiveproxy/src/net/base/file_stream_context_win.cc +++ b/naiveproxy/src/net/base/file_stream_context_win.cc @@ -100,6 +100,26 @@ int FileStream::Context::Write(IOBuffer* buf, return ERR_IO_PENDING; } +int FileStream::Context::ConnectNamedPipe(CompletionOnceCallback callback) { + DCHECK(!async_in_progress_); + + result_ = 0; + // Always returns zero when making an asynchronous call. + ::ConnectNamedPipe(file_.GetPlatformFile(), &io_context_.overlapped); + const auto error = ::GetLastError(); + if (error == ERROR_PIPE_CONNECTED) { + return OK; // The client has already connected; operation complete. + } + if (error == ERROR_IO_PENDING) { + IOCompletionIsPending(std::move(callback), /*buf=*/nullptr); + return ERR_IO_PENDING; // Wait for an I/O completion packet. + } + // ERROR_INVALID_FUNCTION means that `file_` isn't a handle to a named pipe, + // but to an actual file. This is a programming error. + CHECK_NE(error, static_cast(ERROR_INVALID_FUNCTION)); + return static_cast(MapSystemError(error)); +} + FileStream::Context::IOResult FileStream::Context::SeekFileImpl( int64_t offset) { LARGE_INTEGER result; diff --git a/naiveproxy/src/net/base/io_buffer.cc b/naiveproxy/src/net/base/io_buffer.cc index 5035b26442..9b5eca4e7e 100644 --- a/naiveproxy/src/net/base/io_buffer.cc +++ b/naiveproxy/src/net/base/io_buffer.cc @@ -145,6 +145,14 @@ base::span GrowableIOBuffer::everything() const { base::span(real_data_.get(), base::checked_cast(capacity_)))); } +base::span GrowableIOBuffer::span_before_offset() { + return everything().first(base::checked_cast(offset_)); +} + +base::span GrowableIOBuffer::span_before_offset() const { + return everything().first(base::checked_cast(offset_)); +} + GrowableIOBuffer::~GrowableIOBuffer() { data_ = nullptr; } diff --git a/naiveproxy/src/net/base/io_buffer.h b/naiveproxy/src/net/base/io_buffer.h index f72c06b1f5..1afc458246 100644 --- a/naiveproxy/src/net/base/io_buffer.h +++ b/naiveproxy/src/net/base/io_buffer.h @@ -114,8 +114,7 @@ class NET_EXPORT IOBuffer : public base::RefCountedThreadSafe { virtual ~IOBuffer(); - raw_ptr data_ = - nullptr; + raw_ptr data_ = nullptr; int size_ = 0; }; @@ -228,6 +227,10 @@ class NET_EXPORT GrowableIOBuffer : public IOBuffer { base::span everything(); base::span everything() const; + // Return a span before the `offset()`. + base::span span_before_offset(); + base::span span_before_offset() const; + private: ~GrowableIOBuffer() override; diff --git a/naiveproxy/src/net/base/isolation_info.cc b/naiveproxy/src/net/base/isolation_info.cc index 9361e41cc3..f24182324f 100644 --- a/naiveproxy/src/net/base/isolation_info.cc +++ b/naiveproxy/src/net/base/isolation_info.cc @@ -218,11 +218,6 @@ const std::optional& IsolationInfo::frame_origin() const { return frame_origin_; } -const std::optional& IsolationInfo::frame_origin_for_testing() - const { - return frame_origin_; -} - bool IsolationInfo::IsEqualForTesting(const IsolationInfo& other) const { return (request_type_ == other.request_type_ && top_frame_origin_ == other.top_frame_origin_ && @@ -300,21 +295,6 @@ std::string IsolationInfo::DebugString() const { return s; } -NetworkAnonymizationKey -IsolationInfo::CreateNetworkAnonymizationKeyForIsolationInfo( - const std::optional& top_frame_origin, - const std::optional& frame_origin, - const std::optional& nonce) const { - if (!top_frame_origin) { - return NetworkAnonymizationKey(); - } - SchemefulSite top_frame_site(*top_frame_origin); - SchemefulSite frame_site(*frame_origin); - - return NetworkAnonymizationKey::CreateFromFrameSite(top_frame_site, - frame_site, nonce); -} - IsolationInfo::IsolationInfo(RequestType request_type, const std::optional& top_frame_origin, const std::optional& frame_origin, @@ -330,9 +310,11 @@ IsolationInfo::IsolationInfo(RequestType request_type, SchemefulSite(*frame_origin), nonce)), network_anonymization_key_( - CreateNetworkAnonymizationKeyForIsolationInfo(top_frame_origin, - frame_origin, - nonce)), + !top_frame_origin ? NetworkAnonymizationKey() + : NetworkAnonymizationKey::CreateFromFrameSite( + SchemefulSite(*top_frame_origin), + SchemefulSite(*frame_origin), + nonce)), site_for_cookies_(site_for_cookies), nonce_(nonce) { DCHECK(IsConsistent(request_type_, top_frame_origin_, frame_origin_, diff --git a/naiveproxy/src/net/base/isolation_info.h b/naiveproxy/src/net/base/isolation_info.h index fb50541f27..569c3a48a5 100644 --- a/naiveproxy/src/net/base/isolation_info.h +++ b/naiveproxy/src/net/base/isolation_info.h @@ -28,17 +28,18 @@ struct StructTraits; namespace net { // Class to store information about network stack requests based on the context -// in which they are made. It provides NetworkIsolationKeys, used to shard -// storage, and SiteForCookies, used determine when to send same site cookies. -// The IsolationInfo is typically the same for all subresource requests made in -// the context of the same frame, but may be different for different frames -// within a page. The IsolationInfo associated with requests for frames may -// change as redirects are followed, and this class also contains the logic on -// how to do that. +// in which they are made. It provides NetworkIsolationKeys, used to shard the +// HTTP cache, NetworkAnonymizationKeys, used to shard other network state, and +// SiteForCookies, used determine when to send same site cookies. The +// IsolationInfo is typically the same for all subresource requests made in the +// context of the same frame, but may be different for different frames within a +// page. The IsolationInfo associated with requests for frames may change as +// redirects are followed, and this class also contains the logic on how to do +// that. // -// The SiteForCookies logic in this class is currently unused, but will -// eventually replace the logic in URLRequest/RedirectInfo for tracking and -// updating that value. +// TODO(crbug.com/40093296): The SiteForCookies logic in this class is currently +// unused, but will eventually replace the logic in URLRequest/RedirectInfo for +// tracking and updating that value. class NET_EXPORT IsolationInfo { public: // The update-on-redirect patterns. @@ -123,8 +124,8 @@ class NET_EXPORT IsolationInfo { const SiteForCookies& site_for_cookies, const std::optional& nonce = std::nullopt); - // TODO(crbug.com/40871266): Remove this and create a safer way to ensure NIKs - // created from NAKs aren't used by accident. + // TODO(crbug.com/344943210): Remove this and create a safer way to ensure + // NIKs created from NAKs aren't used by accident. static IsolationInfo DoNotUseCreatePartialFromNak( const net::NetworkAnonymizationKey& network_anonymization_key); @@ -182,16 +183,8 @@ class NET_EXPORT IsolationInfo { // policy. It MUST NEVER be used for any kind of SECURITY check. const SiteForCookies& site_for_cookies() const { return site_for_cookies_; } - // Do not use outside of testing. Returns the `frame_origin_`. - const std::optional& frame_origin_for_testing() const; - bool IsEqualForTesting(const IsolationInfo& other) const; - NetworkAnonymizationKey CreateNetworkAnonymizationKeyForIsolationInfo( - const std::optional& top_frame_origin, - const std::optional& frame_origin, - const std::optional& nonce) const; - // Serialize the `IsolationInfo` into a string. Fails if transient, returning // an empty string. std::string Serialize() const; diff --git a/naiveproxy/src/net/base/lookup_string_in_fixed_set.cc b/naiveproxy/src/net/base/lookup_string_in_fixed_set.cc index 1842b12331..e987831a24 100644 --- a/naiveproxy/src/net/base/lookup_string_in_fixed_set.cc +++ b/naiveproxy/src/net/base/lookup_string_in_fixed_set.cc @@ -9,64 +9,70 @@ #include "net/base/lookup_string_in_fixed_set.h" +#include + #include "base/check.h" +#include "base/containers/span.h" namespace net { namespace { -// Read next offset from |pos|, increment |offset| by that amount, and increment -// |pos| either to point to the start of the next encoded offset in its node, or -// nullptr, if there are no remaining offsets. +// Read next offset from `bytes`, increment `offset_bytes` by that amount, and +// increment `bytes` either to point to the start of the next encoded offset in +// its node, or set it to an empty span, if there are no remaining offsets. // // Returns true if an offset could be read; false otherwise. -inline bool GetNextOffset(const unsigned char** pos, - const unsigned char** offset) { - if (*pos == nullptr) +inline bool GetNextOffset(base::span* bytes, + base::span* offset_bytes) { + if (!bytes->size()) { return false; + } size_t bytes_consumed; - switch (**pos & 0x60) { + switch (bytes->front() & 0x60) { case 0x60: // Read three byte offset - *offset += (((*pos)[0] & 0x1F) << 16) | ((*pos)[1] << 8) | (*pos)[2]; + *offset_bytes = offset_bytes->subspan(((bytes->front() & 0x1F) << 16) | + ((*bytes)[1] << 8) | (*bytes)[2]); bytes_consumed = 3; break; case 0x40: // Read two byte offset - *offset += (((*pos)[0] & 0x1F) << 8) | (*pos)[1]; + *offset_bytes = + offset_bytes->subspan(((bytes->front() & 0x1F) << 8) | (*bytes)[1]); bytes_consumed = 2; break; default: - *offset += (*pos)[0] & 0x3F; + *offset_bytes = offset_bytes->subspan(bytes->front() & 0x3F); bytes_consumed = 1; } - if ((**pos & 0x80) != 0) { - *pos = nullptr; + if ((bytes->front() & 0x80) != 0) { + *bytes = base::span(); } else { - *pos += bytes_consumed; + *bytes = bytes->subspan(bytes_consumed); } return true; } -// Check if byte at |offset| is last in label. -bool IsEOL(const unsigned char* offset) { - return (*offset & 0x80) != 0; +// Check if byte at `byte` is last in label. +bool IsEOL(uint8_t byte) { + return (byte & 0x80) != 0; } -// Check if byte at |offset| matches key. This version matches both end-of-label +// Check if byte at `byte` matches key. This version matches both end-of-label // chars and not-end-of-label chars. -bool IsMatch(const unsigned char* offset, char key) { - return (*offset & 0x7F) == key; +bool IsMatch(uint8_t byte, char key) { + return (byte & 0x7F) == key; } -// Read return value at |offset|, if it is a return value. Returns true if a +// Read return value at `byte`, if it is a return value. Returns true if a // return value could be read, false otherwise. -bool GetReturnValue(const unsigned char* offset, int* return_value) { +bool GetReturnValue(uint8_t byte, int* return_value) { // Return values are always encoded as end-of-label chars (so the high bit is // set). So byte values in the inclusive range [0x80, 0x9F] encode the return // values 0 through 31 (though make_dafsa.py doesn't currently encode values // higher than 7). The following code does that translation. - if ((*offset & 0xE0) == 0x80) { - *return_value = *offset & 0x1F; + if ((byte & 0xE0) == 0x80) { + *return_value = byte & 0x1F; return true; } return false; @@ -74,9 +80,9 @@ bool GetReturnValue(const unsigned char* offset, int* return_value) { } // namespace -FixedSetIncrementalLookup::FixedSetIncrementalLookup(const unsigned char* graph, - size_t length) - : pos_(graph), end_(graph + length) {} +FixedSetIncrementalLookup::FixedSetIncrementalLookup( + base::span graph) + : bytes_(graph), original_bytes_(graph) {} FixedSetIncrementalLookup::FixedSetIncrementalLookup( const FixedSetIncrementalLookup& other) = default; @@ -87,7 +93,7 @@ FixedSetIncrementalLookup& FixedSetIncrementalLookup::operator=( FixedSetIncrementalLookup::~FixedSetIncrementalLookup() = default; bool FixedSetIncrementalLookup::Advance(char input) { - if (!pos_) { + if (bytes_.empty()) { // A previous input exhausted the graph, so there are no possible matches. return false; } @@ -97,49 +103,49 @@ bool FixedSetIncrementalLookup::Advance(char input) { // low values (values 0x00-0x1F) are reserved to encode the return values. So // values outside this range will never be in the dictionary. if (input >= 0x20) { - if (pos_is_label_character_) { + if (bytes_starts_with_label_character_) { // Currently processing a label, so it is only necessary to check the byte - // at |pos_| to see if it encodes a character matching |input|. - bool is_last_char_in_label = IsEOL(pos_); - bool is_match = IsMatch(pos_, input); + // pointed by `bytes_` to see if it encodes a character matching `input`. + bool is_last_char_in_label = IsEOL(bytes_.front()); + bool is_match = IsMatch(bytes_.front(), input); if (is_match) { // If this is not the last character in the label, the next byte should // be interpreted as a character or return value. Otherwise, the next // byte should be interpreted as a list of child node offsets. - ++pos_; - DCHECK(pos_ < end_); - pos_is_label_character_ = !is_last_char_in_label; + bytes_ = bytes_.subspan(1); + DCHECK(!bytes_.empty()); + bytes_starts_with_label_character_ = !is_last_char_in_label; return true; } } else { - const unsigned char* offset = pos_; - // Read offsets from |pos_| until the label of the child node at |offset| - // matches |input|, or until there are no more offsets. - while (GetNextOffset(&pos_, &offset)) { - DCHECK(offset < end_); - DCHECK((pos_ == nullptr) || (pos_ < end_)); + base::span offset_bytes = bytes_; + // Read offsets from `bytes_` until the label of the child node at + // `offset_bytes` matches `input`, or until there are no more offsets. + while (GetNextOffset(&bytes_, &offset_bytes)) { + DCHECK(!offset_bytes.empty()); - // |offset| points to a DAFSA node that is a child of the original node. + // `offset_bytes` points to a DAFSA node that is a child of the original + // node. // // The low 7 bits of a node encodes a character value; the high bit // indicates whether it's the last character in the label. // - // Note that |*offset| could also be a result code value, but these are - // really just out-of-range ASCII values, encoded the same way as - // characters. Since |input| was already validated as a printable ASCII - // value ASCII value, IsMatch will never return true if |offset| is a + // Note that `*offset_bytes` could also be a result code value, but + // these are really just out-of-range ASCII values, encoded the same way + // as characters. Since `input` was already validated as a printable + // ASCII value, IsMatch will never return true if `offset_bytes` is a // result code. - bool is_last_char_in_label = IsEOL(offset); - bool is_match = IsMatch(offset, input); + bool is_last_char_in_label = IsEOL(offset_bytes.front()); + bool is_match = IsMatch(offset_bytes.front(), input); if (is_match) { // If this is not the last character in the label, the next byte // should be interpreted as a character or return value. Otherwise, // the next byte should be interpreted as a list of child node // offsets. - pos_ = offset + 1; - DCHECK(pos_ < end_); - pos_is_label_character_ = !is_last_char_in_label; + bytes_ = offset_bytes.subspan(1); + DCHECK(!bytes_.empty()); + bytes_starts_with_label_character_ = !is_last_char_in_label; return true; } } @@ -147,48 +153,47 @@ bool FixedSetIncrementalLookup::Advance(char input) { } // If no match was found, then end of the DAFSA has been reached. - pos_ = nullptr; - pos_is_label_character_ = false; + bytes_ = base::span(); + bytes_starts_with_label_character_ = false; return false; } int FixedSetIncrementalLookup::GetResultForCurrentSequence() const { int value = kDafsaNotFound; // Look to see if there is a next character that's a return value. - if (pos_is_label_character_) { + if (bytes_starts_with_label_character_) { // Currently processing a label, so it is only necessary to check the byte - // at |pos_| to see if encodes a return value. - GetReturnValue(pos_, &value); + // at `bytes_` to see if encodes a return value. + GetReturnValue(bytes_.front(), &value); } else { - // Otherwise, |pos_| is an offset list (or nullptr). Explore the list of - // child nodes (given by their offsets) to find one whose label is a result - // code. + // Otherwise, `bytes_` is an offset list. Explore the list of child nodes + // (given by their offsets) to find one whose label is a result code. // - // This search uses a temporary copy of |pos_|, since mutating |pos_| could - // skip over a node that would be important to a subsequent Advance() call. - const unsigned char* temp_pos = pos_; + // This search uses a temporary copy of `bytes_`, since mutating `bytes_` + // could skip over a node that would be important to a subsequent Advance() + // call. + base::span temp_bytes = bytes_; - // Read offsets from |temp_pos| until either |temp_pos| is nullptr or until - // the byte at |offset| contains a result code (encoded as an ASCII - // character below 0x20). - const unsigned char* offset = pos_; - while (GetNextOffset(&temp_pos, &offset)) { - DCHECK(offset < end_); - DCHECK((temp_pos == nullptr) || temp_pos < end_); - if (GetReturnValue(offset, &value)) + // Read offsets from `temp_bytes` until either `temp_bytes` is exhausted or + // until the byte at `offset_bytes` contains a result code (encoded as an + // ASCII character below 0x20). + base::span offset_bytes = bytes_; + while (GetNextOffset(&temp_bytes, &offset_bytes)) { + DCHECK(!offset_bytes.empty()); + if (GetReturnValue(offset_bytes.front(), &value)) { break; + } } } return value; } -int LookupStringInFixedSet(const unsigned char* graph, - size_t length, +int LookupStringInFixedSet(base::span graph, const char* key, size_t key_length) { // Do an incremental lookup until either the end of the graph is reached, or // until every character in |key| is consumed. - FixedSetIncrementalLookup lookup(graph, length); + FixedSetIncrementalLookup lookup(graph); const char* key_end = key + key_length; while (key != key_end) { if (!lookup.Advance(*key)) @@ -206,12 +211,11 @@ int LookupStringInFixedSet(const unsigned char* graph, // LookupStringInFixedSet::Advance() at compile time. Tests on x86_64 linux // indicated about 10% increased runtime cost for GetRegistryLength() in average // if the implementation of this function was separated from the lookup methods. -int LookupSuffixInReversedSet(const unsigned char* graph, - size_t length, +int LookupSuffixInReversedSet(base::span graph, bool include_private, std::string_view host, size_t* suffix_length) { - FixedSetIncrementalLookup lookup(graph, length); + FixedSetIncrementalLookup lookup(graph); *suffix_length = 0; int result = kDafsaNotFound; std::string_view::const_iterator pos = host.end(); diff --git a/naiveproxy/src/net/base/lookup_string_in_fixed_set.h b/naiveproxy/src/net/base/lookup_string_in_fixed_set.h index 47bdc11316..d8a435782e 100644 --- a/naiveproxy/src/net/base/lookup_string_in_fixed_set.h +++ b/naiveproxy/src/net/base/lookup_string_in_fixed_set.h @@ -7,8 +7,12 @@ #include +#include #include +#include "base/containers/span.h" +#include "base/memory/raw_ptr_exclusion.h" +#include "base/memory/raw_span.h" #include "net/base/net_export.h" namespace net { @@ -29,13 +33,12 @@ enum { // Automaton) by the script make_dafsa.py during compilation. This permits // efficient (in time and space) lookup. The graph generated by make_dafsa.py // takes the form of a constant byte array which should be supplied via the -// |graph| and |length| parameters. The return value is kDafsaNotFound, -// kDafsaFound, or a bitmap consisting of one or more of kDafsaExceptionRule, -// kDafsaWildcardRule and kDafsaPrivateRule ORed together. +// |graph| parameter. The return value is kDafsaNotFound, kDafsaFound, or a +// bitmap consisting of one or more of kDafsaExceptionRule, kDafsaWildcardRule +// and kDafsaPrivateRule ORed together. // // TODO(nick): Replace this with FixedSetIncrementalLookup everywhere. -NET_EXPORT int LookupStringInFixedSet(const unsigned char* graph, - size_t length, +NET_EXPORT int LookupStringInFixedSet(base::span graph, const char* key, size_t key_length); @@ -45,8 +48,7 @@ NET_EXPORT int LookupStringInFixedSet(const unsigned char* graph, // If no match was found a value of 0 is written to |suffix_length| and the // value kDafsaNotFound is returned, otherwise the length of the longest match // is written to |suffix_length| and the type of the longest match is returned. -int LookupSuffixInReversedSet(const unsigned char* graph, - size_t length, +int LookupSuffixInReversedSet(base::span graph, bool include_private, std::string_view host, size_t* suffix_length); @@ -92,9 +94,9 @@ int LookupSuffixInReversedSet(const unsigned char* graph, // class NET_EXPORT FixedSetIncrementalLookup { public: - // Begin a lookup against the provided fixed set. |graph| and |length| - // describe a byte buffer generated by the make_dafsa.py script, as described - // in the class comment. + // Begin a lookup against the provided fixed set. `graph` describes a byte + // buffer generated by the make_dafsa.py script, as described in the class + // comment. // // FixedSetIncrementalLookup is initialized to a state corresponding to the // empty input sequence. Calling GetResultForCurrentSequence() in the initial @@ -102,7 +104,7 @@ class NET_EXPORT FixedSetIncrementalLookup { // Characters can be added to the sequence by calling Advance(), and the // lookup result can be checked after each addition by calling // GetResultForCurrentSequence(). - FixedSetIncrementalLookup(const unsigned char* graph, size_t length); + explicit FixedSetIncrementalLookup(base::span graph); // FixedSetIncrementalLookup is copyable so that callers can save/restore // their position in the search. This is for cases where branching or @@ -142,18 +144,22 @@ class NET_EXPORT FixedSetIncrementalLookup { int GetResultForCurrentSequence() const; private: - // Pointer to the current position in the graph indicating the current state - // of the automaton, or nullptr if the graph is exhausted. - const unsigned char* pos_; + // Span start points to the current position in the graph indicating the + // current state of the automaton. Is as empty span if the graph is exhausted. + // RAW_PTR_EXCLUSION: Already protected by `original_bytes_` (see below). + RAW_PTR_EXCLUSION base::span bytes_; - // Pointer just past the end of the graph. |pos_| should never get here. This - // is used only in DCHECKs. - const unsigned char* end_; + // `original_bytes_` bytes isn't used per se, as we care only about the + // current state in `bytes_` (which is a subspan), but is kept here as + // raw_span<> because of its anti-UaF properties. `bytes_`, due to being + // constantly modified, isn't a good candidate for raw_span<> for performance + // reasons: `bytes_ = bytes_.subspan(N)` would be costly. + base::raw_span original_bytes_; - // Contains the current decoder state. If true, |pos_| points to a label - // character or a return code. If false, |pos_| points to a sequence of + // Contains the current decoder state. If true, `bytes_` points to a label + // character or a return code. If false, `bytes_` points to a sequence of // offsets that indicate the child nodes of the current state. - bool pos_is_label_character_ = false; + bool bytes_starts_with_label_character_ = false; }; } // namespace net diff --git a/naiveproxy/src/net/base/net_error_details.h b/naiveproxy/src/net/base/net_error_details.h index 6a45f3bc88..295f1def19 100644 --- a/naiveproxy/src/net/base/net_error_details.h +++ b/naiveproxy/src/net/base/net_error_details.h @@ -8,6 +8,7 @@ #include "net/base/net_export.h" #include "net/http/http_connection_info.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_error_codes.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" namespace net { @@ -25,6 +26,8 @@ struct NET_EXPORT NetErrorDetails { bool quic_broken; // QUIC granular error info. quic::QuicErrorCode quic_connection_error; + // Source of the connection close. + quic::ConnectionCloseSource source = quic::ConnectionCloseSource::FROM_SELF; // Early prediction of the connection type that this request attempts to use. // Will be discarded by upper layers if the connection type can be fetched // from response header from the server. diff --git a/naiveproxy/src/net/base/network_change_notifier.cc b/naiveproxy/src/net/base/network_change_notifier.cc index a76412a919..4bdf50d9f3 100644 --- a/naiveproxy/src/net/base/network_change_notifier.cc +++ b/naiveproxy/src/net/base/network_change_notifier.cc @@ -254,11 +254,6 @@ class NetworkChangeNotifier::ObserverList { const scoped_refptr< base::ObserverListThreadSafe> default_network_active_observer_list_; - - // Indicates if connection cost observer was added before - // network_change_notifier was initialized, if so ConnectionCostObserverAdded - // is invoked from constructor. - std::atomic_bool connection_cost_observers_added_ = false; }; class NetworkChangeNotifier::SystemDnsConfigObserver @@ -704,13 +699,8 @@ void NetworkChangeNotifier::AddNetworkObserver(NetworkObserver* observer) { void NetworkChangeNotifier::AddConnectionCostObserver( ConnectionCostObserver* observer) { DCHECK(!observer->observer_list_); - GetObserverList().connection_cost_observers_added_ = true; observer->observer_list_ = GetObserverList().connection_cost_observer_list_; observer->observer_list_->AddObserver(observer); - base::AutoLock auto_lock(NetworkChangeNotifierCreationLock()); - if (g_network_change_notifier) { - g_network_change_notifier->ConnectionCostObserverAdded(); - } } void NetworkChangeNotifier::AddDefaultNetworkActiveObserver( @@ -869,9 +859,6 @@ NetworkChangeNotifier::NetworkChangeNotifier( g_network_change_notifier = this; system_dns_config_notifier_->AddObserver(system_dns_config_observer_.get()); - if (GetObserverList().connection_cost_observers_added_) { - g_network_change_notifier->ConnectionCostObserverAdded(); - } } if (!omit_observers_in_constructor_for_testing) { network_change_calculator_ = diff --git a/naiveproxy/src/net/base/network_change_notifier.h b/naiveproxy/src/net/base/network_change_notifier.h index 928f584fb6..6afabd71b9 100644 --- a/naiveproxy/src/net/base/network_change_notifier.h +++ b/naiveproxy/src/net/base/network_change_notifier.h @@ -685,13 +685,6 @@ class NET_EXPORT NetworkChangeNotifier { // as early as possible in the destructor to prevent races. void ClearGlobalPointer(); - // Called whenever a new ConnectionCostObserver is added. This method is - // needed so that the implementation class can be notified and - // potentially take action when an observer gets added. Since the act of - // adding an observer and the observer list itself are both static, the - // implementation class has no direct capability to watch for changes. - virtual void ConnectionCostObserverAdded() {} - // Listening for notifications of this type is expensive as they happen // frequently. For this reason, we report {de}registration to the // implementation class, so that it can decide to only listen to this type of diff --git a/naiveproxy/src/net/base/network_change_notifier_apple.h b/naiveproxy/src/net/base/network_change_notifier_apple.h index d2304eb1c8..6f68837c25 100644 --- a/naiveproxy/src/net/base/network_change_notifier_apple.h +++ b/naiveproxy/src/net/base/network_change_notifier_apple.h @@ -22,6 +22,7 @@ #include "net/base/network_change_notifier.h" #include "net/base/network_config_watcher_apple.h" #include "net/base/network_interfaces.h" +#include "net/log/net_log_with_source.h" namespace net { @@ -116,6 +117,7 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierApple base::RepeatingCallback get_ipv6_primary_interface_name_callback_; #endif // BUILDFLAG(IS_MAC) + NetLogWithSource net_log_; }; } // namespace net diff --git a/naiveproxy/src/net/base/network_change_notifier_apple.mm b/naiveproxy/src/net/base/network_change_notifier_apple.mm index 3beb387a45..249838b009 100644 --- a/naiveproxy/src/net/base/network_change_notifier_apple.mm +++ b/naiveproxy/src/net/base/network_change_notifier_apple.mm @@ -24,11 +24,13 @@ #include "net/base/features.h" #include "net/base/network_interfaces_getifaddrs.h" #include "net/dns/dns_config_service.h" +#include "net/log/net_log.h" #if BUILDFLAG(IS_IOS) #import #endif +namespace net { namespace { // The maximum number of seconds to wait for the connection type to be // determined. @@ -82,12 +84,67 @@ GetNetworkInterfaceListForNetworkChangeCheck( }); return interfaces; } + +base::Value::Dict GetNetworkInterfaceValueDict( + const NetworkInterface& interface) { + base::Value::Dict dict; + dict.Set("name", interface.name); + dict.Set("friendly_name", interface.friendly_name); + dict.Set("interface_index", static_cast(interface.interface_index)); + dict.Set("type", static_cast(interface.type)); + dict.Set("address", interface.address.ToString()); + dict.Set("prefix_length", static_cast(interface.prefix_length)); + dict.Set("ip_address_attributes", interface.ip_address_attributes); + if (interface.mac_address) { + dict.Set("mac_address", base::HexEncode(*interface.mac_address)); + } + return dict; +} + +base::Value::List GetNetworkInterfacesValueList( + const NetworkInterfaceList& interfaces) { + base::Value::List list; + for (const NetworkInterface& interface : interfaces) { + list.Append(GetNetworkInterfaceValueDict(interface)); + } + return list; +} + +base::Value::Dict NetLogOsConfigChangedParams( + const std::string& result, + bool net_ipv4_key_found, + bool net_ipv6_key_found, + bool net_interface_key_found, + bool reduce_ip_address_change_notification, + const std::string& old_ipv4_primary_interface_name, + const std::string& old_ipv6_primary_interface_name, + const std::string& new_ipv4_primary_interface_name, + const std::string& new_ipv6_primary_interface_name, + const std::optional& old_interfaces, + const std::optional& new_interfaces) { + base::Value::Dict dict; + dict.Set("result", result); + dict.Set("net_ipv4_key", net_ipv4_key_found); + dict.Set("net_ipv6_key", net_ipv6_key_found); + dict.Set("net_interface_key", net_interface_key_found); + dict.Set("reduce_notification", reduce_ip_address_change_notification); + dict.Set("old_ipv4_interface", old_ipv4_primary_interface_name); + dict.Set("old_ipv6_interface", old_ipv6_primary_interface_name); + dict.Set("new_ipv4_interface", new_ipv4_primary_interface_name); + dict.Set("new_ipv6_interface", new_ipv6_primary_interface_name); + if (old_interfaces) { + dict.Set("old_interfaces", GetNetworkInterfacesValueList(*old_interfaces)); + } + if (new_interfaces) { + dict.Set("new_interfaces", GetNetworkInterfacesValueList(*new_interfaces)); + } + return dict; +} + #endif // BUILDFLAG(IS_MAC) } // namespace -namespace net { - static bool CalculateReachability(SCNetworkConnectionFlags flags) { bool reachable = flags & kSCNetworkFlagsReachable; bool connection_required = flags & kSCNetworkFlagsConnectionRequired; @@ -97,18 +154,19 @@ static bool CalculateReachability(SCNetworkConnectionFlags flags) { NetworkChangeNotifierApple::NetworkChangeNotifierApple() : NetworkChangeNotifier(NetworkChangeCalculatorParamsMac()), initial_connection_type_cv_(&connection_type_lock_), - forwarder_(this) + forwarder_(this), #if BUILDFLAG(IS_MAC) - , reduce_ip_address_change_notification_(base::FeatureList::IsEnabled( features::kReduceIPAddressChangeNotification)), get_network_list_callback_(base::BindRepeating(&GetNetworkList)), get_ipv4_primary_interface_name_callback_( base::BindRepeating(&GetIPv4PrimaryInterfaceName)), get_ipv6_primary_interface_name_callback_( - base::BindRepeating(&GetIPv6PrimaryInterfaceName)) + base::BindRepeating(&GetIPv6PrimaryInterfaceName)), #endif // BUILDFLAG(IS_MAC) -{ + net_log_(net::NetLogWithSource::Make( + net::NetLog::Get(), + net::NetLogSourceType::NETWORK_CHANGE_NOTIFIER)) { // Must be initialized after the rest of this object, as it may call back into // SetInitialConnectionType(). config_watcher_ = std::make_unique(&forwarder_); @@ -377,26 +435,48 @@ void NetworkChangeNotifierApple::OnNetworkConfigChange(CFArrayRef changed_keys) #elif BUILDFLAG(IS_MAC) DCHECK_EQ(run_loop_.get(), CFRunLoopGetCurrent()); - bool maybe_notify = false; + bool net_ipv4_key_found = false; + bool net_ipv6_key_found = false; + bool net_interface_key_found = false; for (CFIndex i = 0; i < CFArrayGetCount(changed_keys); ++i) { CFStringRef key = static_cast(CFArrayGetValueAtIndex(changed_keys, i)); - if (CFStringHasSuffix(key, kSCEntNetIPv4) || - CFStringHasSuffix(key, kSCEntNetIPv6)) { - maybe_notify = true; + if (CFStringHasSuffix(key, kSCEntNetIPv4)) { + net_ipv4_key_found = true; + } + if (CFStringHasSuffix(key, kSCEntNetIPv6)) { + net_ipv6_key_found = true; + } + if (net_ipv4_key_found || net_ipv6_key_found) { break; } if (CFStringHasSuffix(key, kSCEntNetInterface)) { + net_interface_key_found = true; // TODO(willchan): Does not appear to be working. Look into this. // Perhaps this isn't needed anyway. } else { NOTREACHED_IN_MIGRATION(); } } - if (!maybe_notify) { + if (!(net_ipv4_key_found || net_ipv6_key_found)) { + net_log_.AddEvent(net::NetLogEventType::NETWORK_MAC_OS_CONFIG_CHANGED, [&] { + return NetLogOsConfigChangedParams( + "DoNotNotify_NoIPAddressChange", net_ipv4_key_found, + net_ipv6_key_found, net_interface_key_found, + reduce_ip_address_change_notification_, ipv4_primary_interface_name_, + ipv6_primary_interface_name_, "", "", + interfaces_for_network_change_check_, std::nullopt); + }); return; } if (!reduce_ip_address_change_notification_) { + net_log_.AddEvent(net::NetLogEventType::NETWORK_MAC_OS_CONFIG_CHANGED, [&] { + return NetLogOsConfigChangedParams( + "Notify_NoReduce", net_ipv4_key_found, net_ipv6_key_found, + net_interface_key_found, reduce_ip_address_change_notification_, + ipv4_primary_interface_name_, ipv6_primary_interface_name_, "", "", + interfaces_for_network_change_check_, std::nullopt); + }); NotifyObserversOfIPAddressChange(); return; } @@ -416,8 +496,24 @@ void NetworkChangeNotifierApple::OnNetworkConfigChange(CFArrayRef changed_keys) interfaces_for_network_change_check_.value() == interfaces.value() && ipv4_primary_interface_name_ == ipv4_primary_interface_name && ipv6_primary_interface_name_ == ipv6_primary_interface_name) { + net_log_.AddEvent(net::NetLogEventType::NETWORK_MAC_OS_CONFIG_CHANGED, [&] { + return NetLogOsConfigChangedParams( + "DoNotNotify_NoChange", net_ipv4_key_found, net_ipv6_key_found, + net_interface_key_found, reduce_ip_address_change_notification_, + ipv4_primary_interface_name_, ipv6_primary_interface_name_, + ipv4_primary_interface_name, ipv6_primary_interface_name, + interfaces_for_network_change_check_, interfaces); + }); return; } + net_log_.AddEvent(net::NetLogEventType::NETWORK_MAC_OS_CONFIG_CHANGED, [&] { + return NetLogOsConfigChangedParams( + "Notify_Changed", net_ipv4_key_found, net_ipv6_key_found, + net_interface_key_found, reduce_ip_address_change_notification_, + ipv4_primary_interface_name_, ipv6_primary_interface_name_, + ipv4_primary_interface_name, ipv6_primary_interface_name, + interfaces_for_network_change_check_, interfaces); + }); ipv4_primary_interface_name_ = std::move(ipv4_primary_interface_name); ipv6_primary_interface_name_ = std::move(ipv6_primary_interface_name); interfaces_for_network_change_check_ = std::move(interfaces); diff --git a/naiveproxy/src/net/base/network_change_notifier_win.cc b/naiveproxy/src/net/base/network_change_notifier_win.cc index a4cfc9c6ce..7f23824ad3 100644 --- a/naiveproxy/src/net/base/network_change_notifier_win.cc +++ b/naiveproxy/src/net/base/network_change_notifier_win.cc @@ -23,6 +23,7 @@ #include "base/time/time.h" #include "base/win/windows_version.h" #include "net/base/features.h" +#include "net/base/network_cost_change_notifier_win.h" #include "net/base/winsock_init.h" #include "net/base/winsock_util.h" @@ -33,88 +34,8 @@ namespace { // Time between NotifyAddrChange retries, on failure. const int kWatchForAddressChangeRetryIntervalMs = 500; -HRESULT GetConnectionPoints(IUnknown* manager, - REFIID IIDSyncInterface, - IConnectionPoint** connection_point_raw) { - *connection_point_raw = nullptr; - Microsoft::WRL::ComPtr connection_point_container; - HRESULT hr = - manager->QueryInterface(IID_PPV_ARGS(&connection_point_container)); - if (FAILED(hr)) - return hr; - - // Find the interface - Microsoft::WRL::ComPtr connection_point; - hr = connection_point_container->FindConnectionPoint(IIDSyncInterface, - &connection_point); - if (FAILED(hr)) - return hr; - - *connection_point_raw = connection_point.Get(); - (*connection_point_raw)->AddRef(); - - return hr; -} - } // namespace -// This class is used as an event sink to register for notifications from the -// INetworkCostManagerEvents interface. In particular, we are focused on getting -// notified when the Connection Cost changes. This is only supported on Win10+. -class NetworkCostManagerEventSink - : public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - INetworkCostManagerEvents> { - public: - using CostChangedCallback = base::RepeatingCallback; - - NetworkCostManagerEventSink(INetworkCostManager* cost_manager, - const CostChangedCallback& callback) - : network_cost_manager_(cost_manager), cost_changed_callback_(callback) {} - ~NetworkCostManagerEventSink() override = default; - - // INetworkCostManagerEvents members - IFACEMETHODIMP CostChanged(_In_ DWORD cost, - _In_opt_ NLM_SOCKADDR* /*pSockAddr*/) override { - cost_changed_callback_.Run(); - return S_OK; - } - - IFACEMETHODIMP DataPlanStatusChanged( - _In_opt_ NLM_SOCKADDR* /*pSockAddr*/) override { - return S_OK; - } - - HRESULT RegisterForNotifications() { - Microsoft::WRL::ComPtr unknown; - HRESULT hr = QueryInterface(IID_PPV_ARGS(&unknown)); - if (hr != S_OK) - return hr; - - hr = GetConnectionPoints(network_cost_manager_.Get(), - IID_INetworkCostManagerEvents, &connection_point_); - if (hr != S_OK) - return hr; - - hr = connection_point_->Advise(unknown.Get(), &cookie_); - return hr; - } - - void UnRegisterForNotifications() { - if (connection_point_) { - connection_point_->Unadvise(cookie_); - connection_point_ = nullptr; - cookie_ = 0; - } - } - - private: - Microsoft::WRL::ComPtr network_cost_manager_; - Microsoft::WRL::ComPtr connection_point_; - DWORD cookie_ = 0; - CostChangedCallback cost_changed_callback_; -}; - NetworkChangeNotifierWin::NetworkChangeNotifierWin() : NetworkChangeNotifier(NetworkChangeCalculatorParamsWin()), blocking_task_runner_( @@ -126,6 +47,10 @@ NetworkChangeNotifierWin::NetworkChangeNotifierWin() base::SequencedTaskRunner::GetCurrentDefault()) { memset(&addr_overlapped_, 0, sizeof addr_overlapped_); addr_overlapped_.hEvent = WSACreateEvent(); + + cost_change_notifier_ = NetworkCostChangeNotifierWin::CreateInstance( + base::BindRepeating(&NetworkChangeNotifierWin::OnCostChanged, + weak_factory_.GetWeakPtr())); } NetworkChangeNotifierWin::~NetworkChangeNotifierWin() { @@ -136,11 +61,6 @@ NetworkChangeNotifierWin::~NetworkChangeNotifierWin() { addr_watcher_.StopWatching(); } WSACloseEvent(addr_overlapped_.hEvent); - - if (network_cost_manager_event_sink_) { - network_cost_manager_event_sink_->UnRegisterForNotifications(); - network_cost_manager_event_sink_ = nullptr; - } } // static @@ -325,105 +245,23 @@ void NetworkChangeNotifierWin::RecomputeCurrentConnectionTypeOnBlockingSequence( NetworkChangeNotifier::ConnectionCost NetworkChangeNotifierWin::GetCurrentConnectionCost() { - InitializeConnectionCost(); - - // If we don't have the event sink we aren't registered for automatic updates. - // In that case, we need to update the value at the time it is requested. - if (!network_cost_manager_event_sink_) - UpdateConnectionCostFromCostManager(); - + if (last_computed_connection_cost_ == + ConnectionCost::CONNECTION_COST_UNKNOWN) { + // Use the default logic when the Windows OS APIs do not have a cost for the + // current connection. + return NetworkChangeNotifier::GetCurrentConnectionCost(); + } return last_computed_connection_cost_; } -bool NetworkChangeNotifierWin::InitializeConnectionCostOnce() { - HRESULT hr = - ::CoCreateInstance(CLSID_NetworkListManager, nullptr, CLSCTX_ALL, - IID_INetworkCostManager, &network_cost_manager_); - if (FAILED(hr)) { - SetCurrentConnectionCost(CONNECTION_COST_UNKNOWN); - return true; - } +void NetworkChangeNotifierWin::OnCostChanged( + NetworkChangeNotifier::ConnectionCost new_cost) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - UpdateConnectionCostFromCostManager(); - - return true; -} - -void NetworkChangeNotifierWin::InitializeConnectionCost() { - static bool g_connection_cost_initialized = InitializeConnectionCostOnce(); - DCHECK(g_connection_cost_initialized); -} - -HRESULT NetworkChangeNotifierWin::UpdateConnectionCostFromCostManager() { - if (!network_cost_manager_) - return E_ABORT; - - DWORD cost = NLM_CONNECTION_COST_UNKNOWN; - HRESULT hr = network_cost_manager_->GetCost(&cost, nullptr); - if (FAILED(hr)) { - SetCurrentConnectionCost(CONNECTION_COST_UNKNOWN); - } else { - SetCurrentConnectionCost( - ConnectionCostFromNlmCost((NLM_CONNECTION_COST)cost)); - } - return hr; -} - -// static -NetworkChangeNotifier::ConnectionCost -NetworkChangeNotifierWin::ConnectionCostFromNlmCost(NLM_CONNECTION_COST cost) { - if (cost == NLM_CONNECTION_COST_UNKNOWN) - return CONNECTION_COST_UNKNOWN; - else if ((cost & NLM_CONNECTION_COST_UNRESTRICTED) != 0) - return CONNECTION_COST_UNMETERED; - else - return CONNECTION_COST_METERED; -} - -void NetworkChangeNotifierWin::SetCurrentConnectionCost( - ConnectionCost connection_cost) { - last_computed_connection_cost_ = connection_cost; -} - -void NetworkChangeNotifierWin::OnCostChanged() { - ConnectionCost old_cost = last_computed_connection_cost_; - // It is possible to get multiple notifications in a short period of time. - // Rather than worrying about whether this notification represents the latest, - // just get the current value from the CostManager so we know that we're - // actually getting the correct value. - UpdateConnectionCostFromCostManager(); // Only notify if there's actually a change. - if (old_cost != GetCurrentConnectionCost()) + if (last_computed_connection_cost_ != new_cost) { + last_computed_connection_cost_ = new_cost; NotifyObserversOfConnectionCostChange(); -} - -void NetworkChangeNotifierWin::ConnectionCostObserverAdded() { - sequence_runner_for_registration_->PostTask( - FROM_HERE, - base::BindOnce(&NetworkChangeNotifierWin::OnConnectionCostObserverAdded, - weak_factory_.GetWeakPtr())); -} - -void NetworkChangeNotifierWin::OnConnectionCostObserverAdded() { - DCHECK(sequence_runner_for_registration_->RunsTasksInCurrentSequence()); - InitializeConnectionCost(); - - // No need to register if we don't have a cost manager or if we're already - // registered. - if (!network_cost_manager_ || network_cost_manager_event_sink_) - return; - - network_cost_manager_event_sink_ = - Microsoft::WRL::Make( - network_cost_manager_.Get(), - base::BindRepeating(&NetworkChangeNotifierWin::OnCostChanged, - weak_factory_.GetWeakPtr())); - HRESULT hr = network_cost_manager_event_sink_->RegisterForNotifications(); - if (hr != S_OK) { - // If registration failed for any reason, just destroy the event sink. The - // observer will remain connected but will not receive any updates. If - // another observer gets added later, we can re-attempt registration. - network_cost_manager_event_sink_ = nullptr; } } diff --git a/naiveproxy/src/net/base/network_change_notifier_win.h b/naiveproxy/src/net/base/network_change_notifier_win.h index 4e74edbfcf..f7815e469e 100644 --- a/naiveproxy/src/net/base/network_change_notifier_win.h +++ b/naiveproxy/src/net/base/network_change_notifier_win.h @@ -7,12 +7,7 @@ #include -#include -#include -#include -#include - -#include +#include #include "base/compiler_specific.h" #include "base/functional/callback.h" @@ -20,6 +15,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/thread_annotations.h" +#include "base/threading/sequence_bound.h" #include "base/timer/timer.h" #include "base/win/object_watcher.h" #include "net/base/net_export.h" @@ -31,7 +27,7 @@ class SequencedTaskRunner; namespace net { -class NetworkCostManagerEventSink; +class NetworkCostChangeNotifierWin; // NetworkChangeNotifierWin uses a SequenceChecker, as all its internal // notification code must be called on the sequence it is created and destroyed @@ -106,25 +102,7 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsWin(); - // Gets the current network connection cost (if possible) and caches it. - void InitializeConnectionCost(); - // Does the work of initializing for thread safety. - bool InitializeConnectionCostOnce(); - // Retrieves the current network connection cost from the OS's Cost Manager. - HRESULT UpdateConnectionCostFromCostManager(); - // Converts the OS enum values to the enum values used in our code. - static ConnectionCost ConnectionCostFromNlmCost(NLM_CONNECTION_COST cost); - // Sets the cached network connection cost value. - void SetCurrentConnectionCost(ConnectionCost connection_cost); - // Callback method for the notification event sink. - void OnCostChanged(); - // Tells this class that an observer was added and therefore this class needs - // to register for notifications. - void ConnectionCostObserverAdded() override; - // Since ConnectionCostObserverAdded() can be called on any thread and we - // don't want to do a bunch of work on an arbitrary thread, this method used - // to post task to do the work. - void OnConnectionCostObserverAdded(); + void OnCostChanged(NetworkChangeNotifier::ConnectionCost new_cost); // All member variables may only be accessed on the sequence |this| was // created on. @@ -147,8 +125,13 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin mutable base::Lock last_computed_connection_type_lock_; ConnectionType last_computed_connection_type_; - std::atomic last_computed_connection_cost_ = - ConnectionCost::CONNECTION_COST_UNKNOWN; + std::atomic + last_computed_connection_cost_ = + NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_UNKNOWN; + + // Provides the cost of the current connection. Uses the Windows OS APIs to + // monitor and determine cost. + base::SequenceBound cost_change_notifier_; // Result of IsOffline() when NotifyObserversOfConnectionTypeChange() // was last called. @@ -156,10 +139,6 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin // Number of times polled to check if still offline. int offline_polls_; - Microsoft::WRL::ComPtr network_cost_manager_; - Microsoft::WRL::ComPtr - network_cost_manager_event_sink_; - // Used to ensure that all registration actions are properly sequenced on the // same thread regardless of which thread was used to call into the // NetworkChangeNotifier API. diff --git a/naiveproxy/src/net/base/network_cost_change_notifier_win.cc b/naiveproxy/src/net/base/network_cost_change_notifier_win.cc new file mode 100644 index 0000000000..79aaacf6c7 --- /dev/null +++ b/naiveproxy/src/net/base/network_cost_change_notifier_win.cc @@ -0,0 +1,257 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/network_cost_change_notifier_win.h" + +#include +#include + +#include "base/check.h" +#include "base/no_destructor.h" +#include "base/task/bind_post_task.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/thread_pool.h" +#include "base/threading/scoped_thread_priority.h" +#include "base/win/com_init_util.h" + +using Microsoft::WRL::ComPtr; + +namespace net { + +namespace { + +NetworkChangeNotifier::ConnectionCost ConnectionCostFromNlmConnectionCost( + DWORD connection_cost_flags) { + if (connection_cost_flags == NLM_CONNECTION_COST_UNKNOWN) { + return NetworkChangeNotifier::CONNECTION_COST_UNKNOWN; + } else if ((connection_cost_flags & NLM_CONNECTION_COST_UNRESTRICTED) != 0) { + return NetworkChangeNotifier::CONNECTION_COST_UNMETERED; + } else { + return NetworkChangeNotifier::CONNECTION_COST_METERED; + } +} + +NetworkCostChangeNotifierWin::CoCreateInstanceCallback& +GetCoCreateInstanceCallback() { + static base::NoDestructor< + NetworkCostChangeNotifierWin::CoCreateInstanceCallback> + co_create_instance_callback{base::BindRepeating(&CoCreateInstance)}; + return *co_create_instance_callback; +} + +} // namespace + +// This class is used as an event sink to register for notifications from the +// `INetworkCostManagerEvents` interface. In particular, we are focused on +// getting notified when the connection cost changes. +class NetworkCostManagerEventSinkWin final + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags, + INetworkCostManagerEvents> { + public: + static HRESULT CreateInstance( + INetworkCostManager* network_cost_manager, + base::RepeatingClosure cost_changed_callback, + ComPtr* result) { + ComPtr instance = + Microsoft::WRL::Make( + cost_changed_callback); + HRESULT hr = instance->RegisterForNotifications(network_cost_manager); + if (hr != S_OK) { + return hr; + } + + *result = instance; + return S_OK; + } + + void UnRegisterForNotifications() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (event_sink_connection_point_) { + event_sink_connection_point_->Unadvise(event_sink_connection_cookie_); + event_sink_connection_point_.Reset(); + } + } + + // Implement the INetworkCostManagerEvents interface. + HRESULT __stdcall CostChanged(DWORD /*cost*/, + NLM_SOCKADDR* /*socket_address*/) final { + // It is possible to get multiple notifications in a short period of time. + // Rather than worrying about whether this notification represents the + // latest, just notify the owner who can get the current value from the + // INetworkCostManager so we know that we're actually getting the correct + // value. + cost_changed_callback_.Run(); + return S_OK; + } + + HRESULT __stdcall DataPlanStatusChanged( + NLM_SOCKADDR* /*socket_address*/) final { + return S_OK; + } + + NetworkCostManagerEventSinkWin(base::RepeatingClosure cost_changed_callback) + : cost_changed_callback_(cost_changed_callback) {} + + NetworkCostManagerEventSinkWin(const NetworkCostManagerEventSinkWin&) = + delete; + NetworkCostManagerEventSinkWin& operator=( + const NetworkCostManagerEventSinkWin&) = delete; + + private: + ~NetworkCostManagerEventSinkWin() final = default; + + HRESULT RegisterForNotifications(INetworkCostManager* cost_manager) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + base::win::AssertComInitialized(); + base::win::AssertComApartmentType(base::win::ComApartmentType::STA); + + ComPtr this_event_sink_unknown; + HRESULT hr = QueryInterface(IID_PPV_ARGS(&this_event_sink_unknown)); + + // `NetworkCostManagerEventSinkWin::QueryInterface` for `IUnknown` must + // succeed since it is implemented by this class. + CHECK_EQ(hr, S_OK); + + ComPtr connection_point_container; + hr = + cost_manager->QueryInterface(IID_PPV_ARGS(&connection_point_container)); + if (hr != S_OK) { + return hr; + } + + Microsoft::WRL::ComPtr event_sink_connection_point; + hr = connection_point_container->FindConnectionPoint( + IID_INetworkCostManagerEvents, &event_sink_connection_point); + if (hr != S_OK) { + return hr; + } + + hr = event_sink_connection_point->Advise(this_event_sink_unknown.Get(), + &event_sink_connection_cookie_); + if (hr != S_OK) { + return hr; + } + + CHECK_EQ(event_sink_connection_point_, nullptr); + event_sink_connection_point_ = event_sink_connection_point; + return S_OK; + } + + base::RepeatingClosure cost_changed_callback_; + + // The following members must be accessed on the sequence from + // `sequence_checker_` + SEQUENCE_CHECKER(sequence_checker_); + DWORD event_sink_connection_cookie_ = 0; + Microsoft::WRL::ComPtr event_sink_connection_point_; +}; + +// static +base::SequenceBound +NetworkCostChangeNotifierWin::CreateInstance( + CostChangedCallback cost_changed_callback) { + scoped_refptr com_best_effort_task_runner = + base::ThreadPool::CreateCOMSTATaskRunner( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}); + + return base::SequenceBound( + com_best_effort_task_runner, + // Ensure `cost_changed_callback` runs on the sequence of the creator and + // owner of `NetworkCostChangeNotifierWin`. + base::BindPostTask(base::SequencedTaskRunner::GetCurrentDefault(), + cost_changed_callback)); +} + +NetworkCostChangeNotifierWin::NetworkCostChangeNotifierWin( + CostChangedCallback cost_changed_callback) + : cost_changed_callback_(cost_changed_callback) { + StartWatching(); +} + +NetworkCostChangeNotifierWin::~NetworkCostChangeNotifierWin() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + StopWatching(); +} + +void NetworkCostChangeNotifierWin::StartWatching() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (base::win::GetVersion() < kSupportedOsVersion) { + return; + } + + base::win::AssertComInitialized(); + base::win::AssertComApartmentType(base::win::ComApartmentType::STA); + + SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); + + // Create `INetworkListManager` using `CoCreateInstance()`. Tests may provide + // a fake implementation of `INetworkListManager` through an + // `OverrideCoCreateInstanceForTesting()`. + ComPtr cost_manager; + HRESULT hr = GetCoCreateInstanceCallback().Run( + CLSID_NetworkListManager, /*unknown_outer=*/nullptr, CLSCTX_ALL, + IID_INetworkCostManager, &cost_manager); + if (hr != S_OK) { + return; + } + + // Subscribe to cost changed events. + hr = NetworkCostManagerEventSinkWin::CreateInstance( + cost_manager.Get(), + // Cost changed callbacks must run on this sequence to get the new cost + // from `INetworkCostManager`. + base::BindPostTask( + base::SequencedTaskRunner::GetCurrentDefault(), + base::BindRepeating(&NetworkCostChangeNotifierWin::HandleCostChanged, + weak_ptr_factory_.GetWeakPtr())), + &cost_manager_event_sink_); + + if (hr != S_OK) { + return; + } + + // Set the initial cost and inform observers of the initial value. + cost_manager_ = cost_manager; + HandleCostChanged(); +} + +void NetworkCostChangeNotifierWin::StopWatching() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (cost_manager_event_sink_) { + cost_manager_event_sink_->UnRegisterForNotifications(); + cost_manager_event_sink_.Reset(); + } + + cost_manager_.Reset(); +} + +void NetworkCostChangeNotifierWin::HandleCostChanged() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + DWORD connection_cost_flags; + HRESULT hr = cost_manager_->GetCost(&connection_cost_flags, + /*destination_ip_address=*/nullptr); + if (hr != S_OK) { + connection_cost_flags = NLM_CONNECTION_COST_UNKNOWN; + } + + NetworkChangeNotifier::ConnectionCost changed_cost = + ConnectionCostFromNlmConnectionCost(connection_cost_flags); + + cost_changed_callback_.Run(changed_cost); +} + +// static +void NetworkCostChangeNotifierWin::OverrideCoCreateInstanceForTesting( + CoCreateInstanceCallback callback_for_testing) { + GetCoCreateInstanceCallback() = callback_for_testing; +} + +} // namespace net diff --git a/naiveproxy/src/net/base/network_cost_change_notifier_win.h b/naiveproxy/src/net/base/network_cost_change_notifier_win.h new file mode 100644 index 0000000000..d72601f026 --- /dev/null +++ b/naiveproxy/src/net/base/network_cost_change_notifier_win.h @@ -0,0 +1,88 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_ +#define NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_ + +#include +#include + +#include "base/functional/callback_forward.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "base/threading/sequence_bound.h" +#include "base/win/windows_version.h" +#include "net/base/net_export.h" +#include "net/base/network_change_notifier.h" + +namespace net { +class NetworkCostManagerEventSinkWin; + +// Uses the `INetworkCostManager` Windows OS API to monitor the cost of the +// current connection. `INetworkCostManager` performs blocking IO and +// synchronous RPC, which must be accessed through a thread pool worker thread. +// `NetworkCostChangeNotifierWin` uses `base::SequenceBound` to prevent these +// expensive operations from happening on the UI thread. +class NET_EXPORT_PRIVATE NetworkCostChangeNotifierWin final { + public: + // `INetworkCostManager` requires Windows Build 19041 or higher. On prior + // builds, calls to the Windows OS API `IConnectionPoint::Advise()` may hang. + static constexpr base::win::Version kSupportedOsVersion = + base::win::Version::WIN10_20H1; + + using CostChangedCallback = + base::RepeatingCallback; + + // Constructs a new instance using a COM STA single threaded task runner. + // Posts the task that subscribes to cost change events using Windows OS APIs. + static base::SequenceBound CreateInstance( + CostChangedCallback cost_changed_callback); + + // Use `CreateInstance()` above. This constructor is public for use by + // `base::SequenceBound` only. + explicit NetworkCostChangeNotifierWin( + CostChangedCallback cost_changed_callback); + ~NetworkCostChangeNotifierWin(); + + // Tests use this hook to provide a fake implementation of the OS APIs. + // The fake implementation enables tests to simulate different network + // conditions. + using CoCreateInstanceCallback = base::RepeatingCallback< + HRESULT(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*)>; + static void OverrideCoCreateInstanceForTesting( + CoCreateInstanceCallback callback_for_testing); + + NetworkCostChangeNotifierWin(const NetworkCostChangeNotifierWin&) = delete; + NetworkCostChangeNotifierWin& operator=(const NetworkCostChangeNotifierWin&) = + delete; + + private: + // Creates `INetworkCostManager` for `cost_manager_` and subscribe to cost + // change events. + void StartWatching(); + + // Stops monitoring the cost of the current connection by unsubscribing to + // `INetworkCostManager` events and releasing all members. + void StopWatching(); + + // Gets the current cost from `cost_manager_` and then runs + // `cost_changed_callback_`. + void HandleCostChanged(); + + // All members must be accessed on the sequence from `sequence_checker_` + SEQUENCE_CHECKER(sequence_checker_); + + CostChangedCallback cost_changed_callback_; + + Microsoft::WRL::ComPtr cost_manager_; + + Microsoft::WRL::ComPtr + cost_manager_event_sink_; + + base::WeakPtrFactory weak_ptr_factory_{this}; +}; + +} // namespace net + +#endif // NET_BASE_NETWORK_COST_CHANGE_NOTIFIER_WIN_H_ diff --git a/naiveproxy/src/net/base/network_delegate.cc b/naiveproxy/src/net/base/network_delegate.cc index 20b33dae1e..e5d86c47e5 100644 --- a/naiveproxy/src/net/base/network_delegate.cc +++ b/naiveproxy/src/net/base/network_delegate.cc @@ -135,6 +135,12 @@ bool NetworkDelegate::CanSetCookie( inclusion_status); } +std::optional +NetworkDelegate::GetStorageAccessStatus(const URLRequest& request) const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return OnGetStorageAccessStatus(request); +} + NetworkDelegate::PrivacySetting NetworkDelegate::ForcePrivacyMode( const URLRequest& request) const { TRACE_EVENT0(NetTracingCategory(), "NetworkDelegate::ForcePrivacyMode"); diff --git a/naiveproxy/src/net/base/network_delegate.h b/naiveproxy/src/net/base/network_delegate.h index b42d7dfe35..50343c1b90 100644 --- a/naiveproxy/src/net/base/network_delegate.h +++ b/naiveproxy/src/net/base/network_delegate.h @@ -20,6 +20,7 @@ #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_setting_override.h" +#include "net/cookies/cookie_util.h" #include "net/cookies/site_for_cookies.h" #include "net/first_party_sets/first_party_set_metadata.h" #include "net/first_party_sets/first_party_sets_cache_filter.h" @@ -91,6 +92,9 @@ class NET_EXPORT NetworkDelegate { const net::FirstPartySetMetadata& first_party_set_metadata, CookieInclusionStatus* inclusion_status); + std::optional GetStorageAccessStatus( + const URLRequest& request) const; + // PrivacySetting is kStateDisallowed iff the given |url| has to be // requested over connection that is not tracked by the server. // @@ -302,6 +306,9 @@ class NET_EXPORT NetworkDelegate { virtual bool OnCanUseReportingClient(const url::Origin& origin, const GURL& endpoint) const = 0; + + virtual std::optional + OnGetStorageAccessStatus(const URLRequest& request) const = 0; }; } // namespace net diff --git a/naiveproxy/src/net/base/network_delegate_impl.cc b/naiveproxy/src/net/base/network_delegate_impl.cc index c84ba45c5f..be38a6ced2 100644 --- a/naiveproxy/src/net/base/network_delegate_impl.cc +++ b/naiveproxy/src/net/base/network_delegate_impl.cc @@ -4,8 +4,11 @@ #include "net/base/network_delegate_impl.h" +#include + #include "net/base/net_errors.h" #include "net/cookies/cookie_setting_override.h" +#include "net/cookies/cookie_util.h" namespace net { @@ -67,6 +70,11 @@ bool NetworkDelegateImpl::OnCanSetCookie( return true; } +std::optional +NetworkDelegateImpl::OnGetStorageAccessStatus(const URLRequest& request) const { + return std::nullopt; +} + NetworkDelegate::PrivacySetting NetworkDelegateImpl::OnForcePrivacyMode( const URLRequest& request) const { return NetworkDelegate::PrivacySetting::kStateAllowed; diff --git a/naiveproxy/src/net/base/network_delegate_impl.h b/naiveproxy/src/net/base/network_delegate_impl.h index 34ee432578..4923732da6 100644 --- a/naiveproxy/src/net/base/network_delegate_impl.h +++ b/naiveproxy/src/net/base/network_delegate_impl.h @@ -84,6 +84,9 @@ class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate { const net::FirstPartySetMetadata& first_party_set_metadata, CookieInclusionStatus* inclusion_status) override; + std::optional OnGetStorageAccessStatus( + const URLRequest& request) const override; + NetworkDelegate::PrivacySetting OnForcePrivacyMode( const URLRequest& request) const override; diff --git a/naiveproxy/src/net/base/network_isolation_key.cc b/naiveproxy/src/net/base/network_isolation_key.cc index 1d768baee9..7e55a50d53 100644 --- a/naiveproxy/src/net/base/network_isolation_key.cc +++ b/naiveproxy/src/net/base/network_isolation_key.cc @@ -40,9 +40,6 @@ NetworkIsolationKey::NetworkIsolationKey( std::optional&& nonce) : top_frame_site_(std::move(top_frame_site)), frame_site_(std::make_optional(std::move(frame_site))), - is_cross_site_((GetMode() == Mode::kCrossSiteFlagEnabled) - ? std::make_optional(*top_frame_site_ != *frame_site_) - : std::nullopt), nonce_(std::move(nonce)) { DCHECK(!nonce_ || !nonce_->is_empty()); } @@ -84,46 +81,14 @@ std::optional NetworkIsolationKey::ToCacheKeyString() const { if (IsTransient()) return std::nullopt; - std::string variable_key_piece; - switch (GetMode()) { - case Mode::kFrameSiteEnabled: - variable_key_piece = frame_site_->Serialize(); - break; - case Mode::kFrameSiteWithSharedOpaqueEnabled: - if (frame_site_->opaque()) { - variable_key_piece = "_opaque"; - break; - } - variable_key_piece = frame_site_->Serialize(); - break; - case Mode::kCrossSiteFlagEnabled: - variable_key_piece = (*is_cross_site_ ? "_1" : "_0"); - break; - } - return top_frame_site_->Serialize() + " " + variable_key_piece; + return top_frame_site_->Serialize() + " " + frame_site_->Serialize(); } std::string NetworkIsolationKey::ToDebugString() const { // The space-separated serialization of |top_frame_site_| and // |frame_site_|. std::string return_string = GetSiteDebugString(top_frame_site_); - switch (GetMode()) { - case Mode::kFrameSiteEnabled: - return_string += " " + GetSiteDebugString(frame_site_); - break; - case Mode::kFrameSiteWithSharedOpaqueEnabled: - if (frame_site_ && frame_site_->opaque()) { - return_string += " opaque-origin"; - break; - } - return_string += " " + GetSiteDebugString(frame_site_); - break; - case Mode::kCrossSiteFlagEnabled: - if (is_cross_site_.has_value()) { - return_string += (*is_cross_site_ ? " cross-site" : " same-site"); - } - break; - } + return_string += " " + GetSiteDebugString(frame_site_); if (nonce_.has_value()) { return_string += " (with nonce " + nonce_->ToString() + ")"; @@ -136,7 +101,7 @@ bool NetworkIsolationKey::IsFullyPopulated() const { if (!top_frame_site_.has_value()) { return false; } - if (GetMode() == Mode::kFrameSiteEnabled && !frame_site_.has_value()) { + if (!frame_site_.has_value()) { return false; } return true; @@ -148,22 +113,6 @@ bool NetworkIsolationKey::IsTransient() const { return IsOpaque(); } -// static -NetworkIsolationKey::Mode NetworkIsolationKey::GetMode() { - if (base::FeatureList::IsEnabled( - net::features::kEnableCrossSiteFlagNetworkIsolationKey)) { - DCHECK(!base::FeatureList::IsEnabled( - net::features::kEnableFrameSiteSharedOpaqueNetworkIsolationKey)); - return Mode::kCrossSiteFlagEnabled; - } else if (base::FeatureList::IsEnabled( - net::features:: - kEnableFrameSiteSharedOpaqueNetworkIsolationKey)) { - return Mode::kFrameSiteWithSharedOpaqueEnabled; - } else { - return Mode::kFrameSiteEnabled; - } -} - bool NetworkIsolationKey::IsEmpty() const { return !top_frame_site_.has_value() && !frame_site_.has_value(); } @@ -172,9 +121,7 @@ bool NetworkIsolationKey::IsOpaque() const { if (top_frame_site_->opaque()) { return true; } - // For Mode::kCrossSiteFlagEnabled and Mode::kFrameSiteWithSharedOpaqueEnabled - // we don't want to treat NIKs for opaque origin frames as opaque. - if (GetMode() == Mode::kFrameSiteEnabled && frame_site_->opaque()) { + if (frame_site_->opaque()) { return true; } if (nonce_.has_value()) { diff --git a/naiveproxy/src/net/base/network_isolation_key.h b/naiveproxy/src/net/base/network_isolation_key.h index c73302f1d8..e590668e92 100644 --- a/naiveproxy/src/net/base/network_isolation_key.h +++ b/naiveproxy/src/net/base/network_isolation_key.h @@ -28,13 +28,15 @@ class NetworkAnonymizationKey; namespace net { -// NetworkIsolationKey (NIK) is used to partition shared netork state based on +// NetworkIsolationKey (NIK) is used to partition shared network state based on // the context in which the requests were made. It is used to divide the HTTP // cache, while the NetworkAnonymizationKey is used for most other network // state. // -// The precise form of the NIK is still subject to experimentation. See -// `network_anonymization_key.h` for details on keying terminology. +// The NetworkIsolationKey uses the "triple-key" scheme to partition the HTTP +// cache. The key has the following properties: +// `top_frame_site` -> the schemeful site of the top level page. +// `frame_site ` -> the schemeful site of the frame. class NET_EXPORT NetworkIsolationKey { public: // Full constructor. When a request is initiated by the top frame, it must @@ -80,22 +82,8 @@ class NET_EXPORT NetworkIsolationKey { // Compare keys for equality, true if all enabled fields are equal. bool operator==(const NetworkIsolationKey& other) const { - switch (GetMode()) { - case Mode::kFrameSiteWithSharedOpaqueEnabled: - if ((frame_site_ && frame_site_->opaque()) && - (other.frame_site_ && other.frame_site_->opaque())) { - return std::tie(top_frame_site_, nonce_) == - std::tie(other.top_frame_site_, other.nonce_); - } - [[fallthrough]]; - case Mode::kFrameSiteEnabled: - return std::tie(top_frame_site_, frame_site_, nonce_) == - std::tie(other.top_frame_site_, other.frame_site_, other.nonce_); - case Mode::kCrossSiteFlagEnabled: - return std::tie(top_frame_site_, is_cross_site_, nonce_) == - std::tie(other.top_frame_site_, other.is_cross_site_, - other.nonce_); - } + return std::tie(top_frame_site_, frame_site_, nonce_) == + std::tie(other.top_frame_site_, other.frame_site_, other.nonce_); } // Compare keys for inequality, true if any enabled field varies. @@ -105,22 +93,8 @@ class NET_EXPORT NetworkIsolationKey { // Provide an ordering for keys based on all enabled fields. bool operator<(const NetworkIsolationKey& other) const { - switch (GetMode()) { - case Mode::kFrameSiteWithSharedOpaqueEnabled: - if ((frame_site_ && frame_site_->opaque()) && - (other.frame_site_ && other.frame_site_->opaque())) { - return std::tie(top_frame_site_, nonce_) < - std::tie(other.top_frame_site_, other.nonce_); - } - [[fallthrough]]; - case Mode::kFrameSiteEnabled: - return std::tie(top_frame_site_, frame_site_, nonce_) < - std::tie(other.top_frame_site_, other.frame_site_, other.nonce_); - case Mode::kCrossSiteFlagEnabled: - return std::tie(top_frame_site_, is_cross_site_, nonce_) < - std::tie(other.top_frame_site_, other.is_cross_site_, - other.nonce_); - } + return std::tie(top_frame_site_, frame_site_, nonce_) < + std::tie(other.top_frame_site_, other.frame_site_, other.nonce_); } // Returns the string representation of the key for use in string-keyed disk @@ -148,47 +122,9 @@ class NET_EXPORT NetworkIsolationKey { return top_frame_site_; } - enum class Mode { - // This scheme indicates that "triple-key" NetworkIsolationKeys are used to - // partition the HTTP cache. This key will have the following properties: - // `top_frame_site` -> the schemeful site of the top level page. - // `frame_site ` -> the schemeful site of the frame. - // `is_cross_site` -> std::nullopt. - kFrameSiteEnabled, - // This scheme indicates that "2.5-key" NetworkIsolationKeys are used to - // partition the HTTP cache. This key will have the following properties: - // `top_frame_site_` -> the schemeful site of the top level page. - // `frame_site_` -> should only be accessed for serialization or building - // nonced CookiePartitionKeys. - // `is_cross_site_` -> a boolean indicating whether the frame site is - // schemefully cross-site from the top-level site. - kCrossSiteFlagEnabled, - // This scheme indicates that "triple-key" NetworkIsolationKeys are used to - // partition the HTTP cache except when the frame site has an opaque origin. - // In that case, a fixed value will be used instead of the frame site such - // that all opaque origin frames under a given top-level site share a cache - // partition (unless the NIK is explicitly provided a nonce). - kFrameSiteWithSharedOpaqueEnabled, - }; - - // Returns the cache key scheme currently in use. - static Mode GetMode(); - // Do not use outside of testing. Returns the `frame_site_`. const std::optional GetFrameSiteForTesting() const { - if (GetMode() == Mode::kFrameSiteEnabled || - GetMode() == Mode::kFrameSiteWithSharedOpaqueEnabled) { - return frame_site_; - } - return std::nullopt; - } - - // Do not use outside of testing. Returns `is_cross_site_`. - const std::optional GetIsCrossSiteForTesting() const { - if (GetMode() == Mode::kCrossSiteFlagEnabled) { - return is_cross_site_; - } - return std::nullopt; + return frame_site_; } // When serializing a NIK for sending via mojo we want to access the frame @@ -238,17 +174,6 @@ class NET_EXPORT NetworkIsolationKey { // The origin/etld+1 of the frame that initiates the request. std::optional frame_site_; - // A boolean indicating whether the frame origin is cross-site from the - // top-level origin. This will be used for experiments to determine the - // the difference in performance between partitioning the HTTP cache using the - // top-level origin and frame origin ("triple-keying") vs. the top-level - // origin and an is-cross-site bit ("2.5-keying") like the - // `NetworkAnonymizationKey` uses for network state partitioning. This will be - // std::nullopt when `GetMode()` returns `Mode::kFrameSiteEnabled` or - // `Mode::kFrameSiteWithSharedOpaqueEnabled`, or for an empty - // `NetworkIsolationKey`. - std::optional is_cross_site_; - // Having a nonce is a way to force a transient opaque `NetworkIsolationKey` // for non-opaque origins. std::optional nonce_; diff --git a/naiveproxy/src/net/base/priority_queue.h b/naiveproxy/src/net/base/priority_queue.h index 62544345b0..cd25449b2d 100644 --- a/naiveproxy/src/net/base/priority_queue.h +++ b/naiveproxy/src/net/base/priority_queue.h @@ -15,6 +15,7 @@ #include "base/check_op.h" #include "base/functional/bind.h" #include "base/functional/callback.h" +#include "base/not_fatal_until.h" #include "base/threading/thread_checker.h" #if !defined(NDEBUG) @@ -264,7 +265,7 @@ class PriorityQueue { typename Pointer::ListIterator it = pointer.iterator_; Priority priority = pointer.priority_; - DCHECK(it != lists_[priority].end()); + CHECK(it != lists_[priority].end(), base::NotFatalUntil::M130); ++it; while (it == lists_[priority].end()) { if (priority == 0u) { @@ -289,7 +290,7 @@ class PriorityQueue { typename Pointer::ListIterator it = pointer.iterator_; Priority priority = pointer.priority_; - DCHECK(it != lists_[priority].end()); + CHECK(it != lists_[priority].end(), base::NotFatalUntil::M130); while (it == lists_[priority].begin()) { if (priority == num_priorities() - 1) { DCHECK(pointer.Equals(FirstMax())); diff --git a/naiveproxy/src/net/base/proxy_chain.cc b/naiveproxy/src/net/base/proxy_chain.cc index 5ae183287c..687e524a3a 100644 --- a/naiveproxy/src/net/base/proxy_chain.cc +++ b/naiveproxy/src/net/base/proxy_chain.cc @@ -9,6 +9,7 @@ #include "base/check.h" #include "base/no_destructor.h" +#include "base/pickle.h" #include "base/ranges/algorithm.h" #include "base/strings/stringprintf.h" #include "net/base/proxy_server.h" @@ -41,6 +42,36 @@ ProxyChain::ProxyChain(std::vector proxy_server_list) } } +bool ProxyChain::InitFromPickle(base::PickleIterator* pickle_iter) { + if (!pickle_iter->ReadInt(&ip_protection_chain_id_)) { + return false; + } + size_t chain_length = 0; + if (!pickle_iter->ReadLength(&chain_length)) { + return false; + } + + std::vector proxy_server_list; + for (size_t i = 0; i < chain_length; ++i) { + proxy_server_list.push_back(ProxyServer::CreateFromPickle(pickle_iter)); + } + proxy_server_list_ = std::move(proxy_server_list); + return true; +} + +void ProxyChain::Persist(base::Pickle* pickle) const { + DCHECK(IsValid()); + pickle->WriteInt(ip_protection_chain_id_); + if (length() > static_cast(INT_MAX) - 1) { + pickle->WriteInt(0); + return; + } + pickle->WriteInt(static_cast(length())); + for (const auto& proxy_server : proxy_server_list_.value()) { + proxy_server.Persist(pickle); + } +} + const ProxyServer& ProxyChain::GetProxyServer(size_t chain_index) const { DCHECK(IsValid()); CHECK_LT(chain_index, proxy_server_list_.value().size()); diff --git a/naiveproxy/src/net/base/proxy_chain.h b/naiveproxy/src/net/base/proxy_chain.h index a922a1ec1a..2473a8f00e 100644 --- a/naiveproxy/src/net/base/proxy_chain.h +++ b/naiveproxy/src/net/base/proxy_chain.h @@ -18,6 +18,11 @@ #include "net/base/net_export.h" #include "net/base/proxy_server.h" +namespace base { +class Pickle; +class PickleIterator; +} // namespace base + namespace net { // ProxyChain represents a chain of ProxyServers. A chain with multiple proxy @@ -74,6 +79,16 @@ class NET_EXPORT ProxyChain { return ProxyChain(std::move(proxy_server_list), chain_id); } + // Initialize from a pickle that contains data generated by a call to the + // `Persist` method. + // + // Returns true upon success, otherwise returns false. + bool InitFromPickle(base::PickleIterator* pickle_iter); + + // Call this method to persist `ProxyChain`. Illegal to call this on an + // invalid object. + void Persist(base::Pickle* pickle) const; + // Get ProxyServer at index in chain. This is not valid for direct or invalid // proxy chains. const ProxyServer& GetProxyServer(size_t chain_index) const; diff --git a/naiveproxy/src/net/base/proxy_server.cc b/naiveproxy/src/net/base/proxy_server.cc index 7c2f64aab8..5ee9bfef6a 100644 --- a/naiveproxy/src/net/base/proxy_server.cc +++ b/naiveproxy/src/net/base/proxy_server.cc @@ -13,6 +13,7 @@ #include "base/check_op.h" #include "base/numerics/safe_conversions.h" +#include "base/pickle.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -23,6 +24,24 @@ namespace net { +namespace { + +bool IsValidSchemeInt(int scheme_int) { + switch (scheme_int) { + case ProxyServer::SCHEME_INVALID: + case ProxyServer::SCHEME_HTTP: + case ProxyServer::SCHEME_SOCKS4: + case ProxyServer::SCHEME_SOCKS5: + case ProxyServer::SCHEME_HTTPS: + case ProxyServer::SCHEME_QUIC: + return true; + default: + return false; + } +} + +} // namespace + ProxyServer::ProxyServer(Scheme scheme, const HostPortPair& host_port_pair) : scheme_(scheme), host_port_pair_(host_port_pair) { if (scheme_ == SCHEME_INVALID) { @@ -99,6 +118,28 @@ ProxyServer ProxyServer::FromSchemeHostAndPort(Scheme scheme, return ProxyServer(scheme, HostPortPair(unbracketed_host, fixed_port)); } +// static +ProxyServer ProxyServer::CreateFromPickle(base::PickleIterator* pickle_iter) { + Scheme scheme = SCHEME_INVALID; + int scheme_int; + if (pickle_iter->ReadInt(&scheme_int) && IsValidSchemeInt(scheme_int)) { + scheme = static_cast(scheme_int); + } + + HostPortPair host_port_pair; + std::string host_port_pair_string; + if (pickle_iter->ReadString(&host_port_pair_string)) { + host_port_pair = HostPortPair::FromString(host_port_pair_string); + } + + return ProxyServer(scheme, host_port_pair); +} + +void ProxyServer::Persist(base::Pickle* pickle) const { + pickle->WriteInt(static_cast(scheme_)); + pickle->WriteString(host_port_pair_.ToString()); +} + std::string ProxyServer::GetHost() const { return host_port_pair().HostForURL(); } diff --git a/naiveproxy/src/net/base/proxy_server.h b/naiveproxy/src/net/base/proxy_server.h index 9f0f551bc0..3f6269cb19 100644 --- a/naiveproxy/src/net/base/proxy_server.h +++ b/naiveproxy/src/net/base/proxy_server.h @@ -16,6 +16,11 @@ #include "net/base/host_port_pair.h" #include "net/base/net_export.h" +namespace base { +class Pickle; +class PickleIterator; +} // namespace base + namespace net { // ProxyServer encodes the {type, host, port} of a proxy server. @@ -59,6 +64,10 @@ class NET_EXPORT ProxyServer { std::string_view host, std::optional port); + static ProxyServer CreateFromPickle(base::PickleIterator* pickle_iter); + + void Persist(base::Pickle* pickle) const; + // In URL format (with brackets around IPv6 literals). Must not call for // invalid ProxyServers. std::string GetHost() const; diff --git a/naiveproxy/src/net/base/registry_controlled_domains/registry_controlled_domain.cc b/naiveproxy/src/net/base/registry_controlled_domains/registry_controlled_domain.cc index bb94350f69..3dd65497da 100644 --- a/naiveproxy/src/net/base/registry_controlled_domains/registry_controlled_domain.cc +++ b/naiveproxy/src/net/base/registry_controlled_domains/registry_controlled_domain.cc @@ -45,10 +45,12 @@ #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include #include #include #include "base/check_op.h" +#include "base/containers/span.h" #include "base/notreached.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -67,8 +69,8 @@ namespace { // See make_dafsa.py for documentation of the generated dafsa byte array. -const unsigned char* g_graph = kDafsa; -size_t g_graph_length = sizeof(kDafsa); +// This is mutable so that it can be overridden for testing. +base::span g_graph = kDafsa; struct MappedHostComponent { size_t original_begin; @@ -98,8 +100,7 @@ RegistryLengthOutput GetRegistryLengthInTrimmedHost( PrivateRegistryFilter private_filter) { size_t length; int type = LookupSuffixInReversedSet( - g_graph, g_graph_length, private_filter == INCLUDE_PRIVATE_REGISTRIES, - host, &length); + g_graph, private_filter == INCLUDE_PRIVATE_REGISTRIES, host, &length); CHECK_LE(length, host.size()); @@ -499,14 +500,11 @@ size_t PermissiveGetHostRegistryLength(std::u16string_view host, void ResetFindDomainGraphForTesting() { g_graph = kDafsa; - g_graph_length = sizeof(kDafsa); } -void SetFindDomainGraphForTesting(const unsigned char* domains, size_t length) { - CHECK(domains); - CHECK_NE(length, 0u); +void SetFindDomainGraphForTesting(base::span domains) { + CHECK(!domains.empty()); g_graph = domains; - g_graph_length = length; } } // namespace net::registry_controlled_domains diff --git a/naiveproxy/src/net/base/registry_controlled_domains/registry_controlled_domain.h b/naiveproxy/src/net/base/registry_controlled_domains/registry_controlled_domain.h index a952980bca..6138569b9e 100644 --- a/naiveproxy/src/net/base/registry_controlled_domains/registry_controlled_domain.h +++ b/naiveproxy/src/net/base/registry_controlled_domains/registry_controlled_domain.h @@ -115,10 +115,12 @@ #include +#include #include #include #include +#include "base/containers/span.h" #include "net/base/net_export.h" class GURL; @@ -308,8 +310,7 @@ NET_EXPORT_PRIVATE void ResetFindDomainGraphForTesting(); // Used for unit tests, so that a frozen list of domains is used. NET_EXPORT_PRIVATE void SetFindDomainGraphForTesting( - const unsigned char* domains, - size_t length); + base::span domains); } // namespace net::registry_controlled_domains diff --git a/naiveproxy/src/net/base/upload_data_stream.cc b/naiveproxy/src/net/base/upload_data_stream.cc index e4951c468e..69c840bb9f 100644 --- a/naiveproxy/src/net/base/upload_data_stream.cc +++ b/naiveproxy/src/net/base/upload_data_stream.cc @@ -83,6 +83,9 @@ int UploadDataStream::Read(IOBuffer* buf, DCHECK(!IsInMemory()); callback_ = std::move(callback); } else { + if (result < ERR_IO_PENDING) { + LOG(ERROR) << "ReadInternal failed with Error: " << result; + } OnReadCompleted(result); } diff --git a/naiveproxy/src/net/cert/coalescing_cert_verifier.cc b/naiveproxy/src/net/cert/coalescing_cert_verifier.cc index c1babbe3ff..f4e48e0e5f 100644 --- a/naiveproxy/src/net/cert/coalescing_cert_verifier.cc +++ b/naiveproxy/src/net/cert/coalescing_cert_verifier.cc @@ -10,6 +10,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_macros.h" +#include "base/not_fatal_until.h" #include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" @@ -471,7 +472,7 @@ void CoalescingCertVerifier::RemoveJob(Job* job) { // Otherwise, it MUST have been a job from a previous generation. auto inflight_it = base::ranges::find_if(inflight_jobs_, base::MatchesUniquePtr(job)); - DCHECK(inflight_it != inflight_jobs_.end()); + CHECK(inflight_it != inflight_jobs_.end(), base::NotFatalUntil::M130); inflight_jobs_.erase(inflight_it); return; } diff --git a/naiveproxy/src/net/cert/internal/platform_trust_store.cc b/naiveproxy/src/net/cert/internal/platform_trust_store.cc new file mode 100644 index 0000000000..cf5ab15e17 --- /dev/null +++ b/naiveproxy/src/net/cert/internal/platform_trust_store.cc @@ -0,0 +1,23 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert/internal/platform_trust_store.h" + +namespace net { + +PlatformTrustStore::CertWithTrust::CertWithTrust( + std::vector cert_bytes, + bssl::CertificateTrust trust) + : cert_bytes(std::move(cert_bytes)), trust(trust) {} +PlatformTrustStore::CertWithTrust::~CertWithTrust() = default; + +PlatformTrustStore::CertWithTrust::CertWithTrust(const CertWithTrust&) = + default; +PlatformTrustStore::CertWithTrust& PlatformTrustStore::CertWithTrust::operator=( + const CertWithTrust& other) = default; +PlatformTrustStore::CertWithTrust::CertWithTrust(CertWithTrust&&) = default; +PlatformTrustStore::CertWithTrust& PlatformTrustStore::CertWithTrust::operator=( + CertWithTrust&& other) = default; + +} // namespace net diff --git a/naiveproxy/src/net/cert/internal/platform_trust_store.h b/naiveproxy/src/net/cert/internal/platform_trust_store.h new file mode 100644 index 0000000000..8a03d2c442 --- /dev/null +++ b/naiveproxy/src/net/cert/internal/platform_trust_store.h @@ -0,0 +1,43 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_CERT_INTERNAL_PLATFORM_TRUST_STORE_H_ +#define NET_CERT_INTERNAL_PLATFORM_TRUST_STORE_H_ + +#include + +#include "net/base/net_export.h" +#include "third_party/boringssl/src/pki/parsed_certificate.h" +#include "third_party/boringssl/src/pki/trust_store.h" + +namespace net { + +// Extension of bssl::TrustStore that supports enumerating all +// user added certs. +class NET_EXPORT PlatformTrustStore : public bssl::TrustStore { + public: + PlatformTrustStore() = default; + + PlatformTrustStore(const PlatformTrustStore&) = delete; + PlatformTrustStore& operator=(const PlatformTrustStore&) = delete; + + struct NET_EXPORT CertWithTrust { + CertWithTrust(std::vector cert_bytes, + bssl::CertificateTrust trust); + ~CertWithTrust(); + CertWithTrust(const CertWithTrust&); + CertWithTrust& operator=(const CertWithTrust& other); + CertWithTrust(CertWithTrust&&); + CertWithTrust& operator=(CertWithTrust&& other); + + std::vector cert_bytes; + bssl::CertificateTrust trust; + }; + + virtual std::vector GetAllUserAddedCerts() = 0; +}; + +} // namespace net + +#endif // NET_CERT_INTERNAL_PLATFORM_TRUST_STORE_H_ diff --git a/naiveproxy/src/net/cert/internal/system_trust_store.cc b/naiveproxy/src/net/cert/internal/system_trust_store.cc index 11e39936a8..629c38ea78 100644 --- a/naiveproxy/src/net/cert/internal/system_trust_store.cc +++ b/naiveproxy/src/net/cert/internal/system_trust_store.cc @@ -46,10 +46,15 @@ #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) #include "base/lazy_instance.h" #endif + #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) #include "net/cert/internal/trust_store_chrome.h" #endif // CHROME_ROOT_STORE_SUPPORTED +#if BUILDFLAG(IS_CHROMEOS) +#include "base/system/sys_info.h" +#endif + namespace net { #if BUILDFLAG(IS_CHROMEOS) @@ -118,10 +123,15 @@ class SystemTrustStoreChromeWithUnOwnedSystemStore : public SystemTrustStore { // outlive this object. explicit SystemTrustStoreChromeWithUnOwnedSystemStore( std::unique_ptr trust_store_chrome, - bssl::TrustStore* trust_store_system) - : trust_store_chrome_(std::move(trust_store_chrome)) { + net::PlatformTrustStore* trust_store_system) + : trust_store_chrome_(std::move(trust_store_chrome)), + platform_trust_store_(trust_store_system) { #if BUILDFLAG(IS_CHROMEOS) if (GetChromeOSTestTrustStore()) { + // The fake_root_ca_certs.pem file is only intended for testing purposes, + // crash if it is present on a ChromeOS device in a non-test image. + base::SysInfo::CrashIfChromeOSNonTestImage(); + trust_store_collection_.AddTrustStore(GetChromeOSTestTrustStore()); non_crs_trust_store_collection_.AddTrustStore( GetChromeOSTestTrustStore()); @@ -160,10 +170,15 @@ class SystemTrustStoreChromeWithUnOwnedSystemStore : public SystemTrustStore { return trust_store_chrome_->GetConstraintsForCert(cert); } + net::PlatformTrustStore* GetPlatformTrustStore() override { + return platform_trust_store_; + } + private: std::unique_ptr trust_store_chrome_; bssl::TrustStoreCollection trust_store_collection_; bssl::TrustStoreCollection non_crs_trust_store_collection_; + net::PlatformTrustStore* platform_trust_store_; }; std::unique_ptr CreateChromeOnlySystemTrustStore( @@ -179,19 +194,19 @@ class SystemTrustStoreChrome // |trust_store_chrome| and local trust settings from |trust_store_system|. explicit SystemTrustStoreChrome( std::unique_ptr trust_store_chrome, - std::unique_ptr trust_store_system) + std::unique_ptr trust_store_system) : SystemTrustStoreChromeWithUnOwnedSystemStore( std::move(trust_store_chrome), trust_store_system.get()), trust_store_system_(std::move(trust_store_system)) {} private: - std::unique_ptr trust_store_system_; + std::unique_ptr trust_store_system_; }; std::unique_ptr CreateSystemTrustStoreChromeForTesting( std::unique_ptr trust_store_chrome, - std::unique_ptr trust_store_system) { + std::unique_ptr trust_store_system) { return std::make_unique( std::move(trust_store_chrome), std::move(trust_store_system)); } @@ -339,16 +354,9 @@ constexpr char kStaticCertFileEnv[] = "SSL_CERT_FILE"; // See https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html. constexpr char kStaticCertDirsEnv[] = "SSL_CERT_DIR"; -class StaticUnixSystemCerts { +class TrustStoreUnix : public PlatformTrustStore { public: - StaticUnixSystemCerts() : system_trust_store_(Create()) {} - - bssl::TrustStoreInMemory* system_trust_store() { - return system_trust_store_.get(); - } - - static std::unique_ptr Create() { - auto ptr = std::make_unique(); + TrustStoreUnix() { auto env = base::Environment::Create(); std::string env_value; @@ -363,7 +371,7 @@ class StaticUnixSystemCerts { std::string file; if (!base::ReadFileToString(base::FilePath(filename), &file)) continue; - if (AddCertificatesFromBytes(file.data(), file.size(), ptr.get())) { + if (AddCertificatesFromBytes(file, trust_store_)) { cert_file_ok = true; break; } @@ -385,7 +393,7 @@ class StaticUnixSystemCerts { if (!base::ReadFileToString(filename, &file)) { continue; } - if (AddCertificatesFromBytes(file.data(), file.size(), ptr.get())) { + if (AddCertificatesFromBytes(file, trust_store_)) { cert_dir_ok = true; } } @@ -397,17 +405,34 @@ class StaticUnixSystemCerts { LOG(ERROR) << "No CA certificates were found. Try using environment " "variable SSL_CERT_FILE or SSL_CERT_DIR"; } + } - return ptr; + TrustStoreUnix(const TrustStoreUnix&) = delete; + TrustStoreUnix& operator=(const TrustStoreUnix&) = delete; + + // bssl::CertIssuerSource implementation: + void SyncGetIssuersOf(const bssl::ParsedCertificate* cert, + bssl::ParsedCertificateList* issuers) override { + trust_store_.SyncGetIssuersOf(cert, issuers); + } + + // bssl::TrustStore implementation: + bssl::CertificateTrust GetTrust( + const bssl::ParsedCertificate* cert) override { + return trust_store_.GetTrust(cert); + } + + // net::PlatformTrustStore implementation: + std::vector GetAllUserAddedCerts() + override { + return {}; } private: - static bool AddCertificatesFromBytes(const char* data, - size_t length, - bssl::TrustStoreInMemory* store) { + static bool AddCertificatesFromBytes(std::string_view data, + bssl::TrustStoreInMemory& store) { auto certs = X509Certificate::CreateCertificateListFromBytes( - {reinterpret_cast(data), length}, - X509Certificate::FORMAT_AUTO); + base::as_bytes(base::make_span(data)), X509Certificate::FORMAT_AUTO); bool certs_ok = false; for (const auto& cert : certs) { bssl::CertErrors errors; @@ -415,8 +440,8 @@ class StaticUnixSystemCerts { bssl::UpRef(cert->cert_buffer()), x509_util::DefaultParseCertificateOptions(), &errors); if (parsed) { - if (!store->Contains(parsed.get())) { - store->AddTrustAnchor(parsed); + if (!store.Contains(parsed.get())) { + store.AddTrustAnchor(parsed); } certs_ok = true; } else { @@ -426,67 +451,17 @@ class StaticUnixSystemCerts { return certs_ok; } - std::unique_ptr system_trust_store_; + bssl::TrustStoreInMemory trust_store_; }; -base::LazyInstance::Leaky g_root_certs_static_unix = - LAZY_INSTANCE_INITIALIZER; - } // namespace -class SystemTrustStoreStaticUnix : public SystemTrustStore { - public: - SystemTrustStoreStaticUnix() = default; - - bssl::TrustStore* GetTrustStore() override { - return g_root_certs_static_unix.Get().system_trust_store(); - } - - bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const override { - return g_root_certs_static_unix.Get().system_trust_store()->Contains( - trust_anchor); - } - -#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) - bool IsLocallyTrustedRoot( - const bssl::ParsedCertificate* trust_anchor) override { - return g_root_certs_static_unix.Get() - .system_trust_store() - ->GetTrust(trust_anchor) - .IsTrustAnchor(); - } - - int64_t chrome_root_store_version() const override { - return 0; - } - - base::span GetChromeRootConstraints( - const bssl::ParsedCertificate* /*cert*/) const override { - return {}; - } -#endif -}; - -std::unique_ptr CreateSslSystemTrustStore() { - return std::make_unique(); -} - -#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) - std::unique_ptr CreateSslSystemTrustStoreChromeRoot( std::unique_ptr chrome_root) { return std::make_unique( - std::move(chrome_root), StaticUnixSystemCerts::Create()); + std::move(chrome_root), std::make_unique()); } -#else - -std::unique_ptr CreateSslSystemTrustStoreChromeRoot() { - return std::make_unique(); -} - -#endif // CHROME_ROOT_STORE_SUPPORTED - #elif BUILDFLAG(IS_WIN) namespace { diff --git a/naiveproxy/src/net/cert/internal/system_trust_store.h b/naiveproxy/src/net/cert/internal/system_trust_store.h index 7502f6344c..b05819cd5f 100644 --- a/naiveproxy/src/net/cert/internal/system_trust_store.h +++ b/naiveproxy/src/net/cert/internal/system_trust_store.h @@ -8,6 +8,7 @@ #include "base/containers/span.h" #include "build/build_config.h" #include "net/base/net_export.h" +#include "net/cert/internal/platform_trust_store.h" #include "net/net_buildflags.h" #include "third_party/boringssl/src/pki/parsed_certificate.h" #include "third_party/boringssl/src/pki/trust_store.h" @@ -40,6 +41,14 @@ class SystemTrustStore { virtual bool IsKnownRoot(const bssl::ParsedCertificate* cert) const = 0; #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) + // Returns the PlatformTrustStore that can be used to look for + // platform-specific user-added trust settings. This pointer is non-owned, + // and valid only for the lifetime of |this|. Any net::PlatformTrustStore + // objects returned from this method must be thread-safe. + // + // May return null if there is no PlatformTrustStore. + virtual net::PlatformTrustStore* GetPlatformTrustStore() = 0; + // IsLocallyTrustedRoot returns true if the given certificate is trusted in // the user-installed root store. (It may *also* be trusted in the Chrome // Root Store.) @@ -82,7 +91,7 @@ NET_EXPORT std::unique_ptr CreateChromeOnlySystemTrustStore( NET_EXPORT_PRIVATE std::unique_ptr CreateSystemTrustStoreChromeForTesting( std::unique_ptr trust_store_chrome, - std::unique_ptr trust_store_system); + std::unique_ptr trust_store_system); #endif // BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) #if BUILDFLAG(IS_MAC) diff --git a/naiveproxy/src/net/cert/internal/trust_store_android.cc b/naiveproxy/src/net/cert/internal/trust_store_android.cc index 4347baf0f0..6ac438e6ab 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_android.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_android.cc @@ -10,6 +10,7 @@ #include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" #include "net/android/network_library.h" +#include "net/cert/internal/platform_trust_store.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #include "third_party/boringssl/src/pki/cert_errors.h" @@ -62,9 +63,14 @@ class TrustStoreAndroid::Impl bssl::TrustStoreInMemory trust_store_; }; -TrustStoreAndroid::TrustStoreAndroid() = default; +TrustStoreAndroid::TrustStoreAndroid() { + // It's okay for ObserveCertDBChanges to be called on a different sequence + // than the object was constructed on. + DETACH_FROM_SEQUENCE(certdb_observer_sequence_checker_); +} TrustStoreAndroid::~TrustStoreAndroid() { + DCHECK_CALLED_ON_VALID_SEQUENCE(certdb_observer_sequence_checker_); if (is_observing_certdb_changes_) { CertDatabase::GetInstance()->RemoveObserver(this); } @@ -78,6 +84,7 @@ void TrustStoreAndroid::Initialize() { // rather than in the constructor to avoid having to add a TaskEnvironment to // every unit test that uses TrustStoreAndroid. void TrustStoreAndroid::ObserveCertDBChanges() { + DCHECK_CALLED_ON_VALID_SEQUENCE(certdb_observer_sequence_checker_); if (!is_observing_certdb_changes_) { is_observing_certdb_changes_ = true; CertDatabase::GetInstance()->AddObserver(this); @@ -119,4 +126,10 @@ bssl::CertificateTrust TrustStoreAndroid::GetTrust( return MaybeInitializeAndGetImpl()->GetTrust(cert); } +std::vector +TrustStoreAndroid::GetAllUserAddedCerts() { + // TODO(crbug.com/40928765): implement this. + return {}; +} + } // namespace net diff --git a/naiveproxy/src/net/cert/internal/trust_store_android.h b/naiveproxy/src/net/cert/internal/trust_store_android.h index 23728e843a..23f7cd4901 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_android.h +++ b/naiveproxy/src/net/cert/internal/trust_store_android.h @@ -12,6 +12,7 @@ #include "base/synchronization/lock.h" #include "net/base/net_export.h" #include "net/cert/cert_database.h" +#include "net/cert/internal/platform_trust_store.h" #include "third_party/boringssl/src/pki/trust_store.h" #include "third_party/boringssl/src/pki/trust_store_in_memory.h" @@ -20,7 +21,7 @@ namespace net { // TrustStoreAndroid is an implementation of bssl::TrustStore which uses the // Android cert systems to find user-added trust anchors for path building. It // ignores the Android builtin trust anchors. -class NET_EXPORT TrustStoreAndroid : public bssl::TrustStore, +class NET_EXPORT TrustStoreAndroid : public PlatformTrustStore, public CertDatabase::Observer { public: TrustStoreAndroid(); @@ -36,6 +37,10 @@ class NET_EXPORT TrustStoreAndroid : public bssl::TrustStore, bssl::ParsedCertificateList* issuers) override; bssl::CertificateTrust GetTrust(const bssl::ParsedCertificate* cert) override; + // net::PlatformTrustStore implementation: + std::vector GetAllUserAddedCerts() + override; + // CertDatabase::Observer: void OnTrustStoreChanged() override; @@ -51,7 +56,9 @@ class NET_EXPORT TrustStoreAndroid : public bssl::TrustStore, // returns scoped_refptr. scoped_refptr MaybeInitializeAndGetImpl(); - bool is_observing_certdb_changes_ = false; + bool is_observing_certdb_changes_ + GUARDED_BY_CONTEXT(certdb_observer_sequence_checker_) = false; + SEQUENCE_CHECKER(certdb_observer_sequence_checker_); base::Lock init_lock_; scoped_refptr impl_ GUARDED_BY(init_lock_); diff --git a/naiveproxy/src/net/cert/internal/trust_store_chrome.cc b/naiveproxy/src/net/cert/internal/trust_store_chrome.cc index 6df5b03ae6..bea0157d66 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_chrome.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_chrome.cc @@ -6,9 +6,14 @@ #include +#include "base/command_line.h" #include "base/containers/span.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "crypto/sha2.h" #include "net/cert/root_store_proto_lite/root_store.pb.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" @@ -22,6 +27,7 @@ namespace { #include "net/data/ssl/chrome_root_store/chrome-root-store-inc.cc" } // namespace +ChromeRootCertConstraints::ChromeRootCertConstraints() = default; ChromeRootCertConstraints::ChromeRootCertConstraints( std::optional sct_not_after, std::optional sct_all_after, @@ -140,13 +146,17 @@ ChromeRootStoreData::CreateChromeRootStoreData( } TrustStoreChrome::TrustStoreChrome() - : TrustStoreChrome(kChromeRootCertList, - /*certs_are_static=*/true, - /*version=*/CompiledChromeRootStoreVersion()) {} + : TrustStoreChrome( + kChromeRootCertList, + /*certs_are_static=*/true, + /*version=*/CompiledChromeRootStoreVersion(), + /*override_constraints=*/InitializeConstraintsOverrides()) {} TrustStoreChrome::TrustStoreChrome(base::span certs, bool certs_are_static, - int64_t version) { + int64_t version, + ConstraintOverrideMap override_constraints) + : override_constraints_(std::move(override_constraints)) { std::vector< std::pair>> constraints; @@ -190,7 +200,8 @@ TrustStoreChrome::TrustStoreChrome(base::span certs, version_ = version; } -TrustStoreChrome::TrustStoreChrome(const ChromeRootStoreData& root_store_data) { +TrustStoreChrome::TrustStoreChrome(const ChromeRootStoreData& root_store_data) + : override_constraints_(InitializeConstraintsOverrides()) { std::vector< std::pair>> constraints; @@ -209,6 +220,98 @@ TrustStoreChrome::TrustStoreChrome(const ChromeRootStoreData& root_store_data) { TrustStoreChrome::~TrustStoreChrome() = default; +TrustStoreChrome::ConstraintOverrideMap +TrustStoreChrome::InitializeConstraintsOverrides() { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(kTestCrsConstraintsSwitch)) { + return ParseCrsConstraintsSwitch( + command_line->GetSwitchValueASCII(kTestCrsConstraintsSwitch)); + } + + return {}; +} + +TrustStoreChrome::ConstraintOverrideMap +TrustStoreChrome::ParseCrsConstraintsSwitch(std::string_view switch_value) { + // This function constructs a flat_map on the fly rather than the more + // efficient approach of creating a vector first and then constructing the + // flat_map from that. It is expected that there will only be a small number + // of elements in the map, and that this is only used for testing, therefore + // simplicity of the implementation is weighted higher than theoretical + // efficiency. + ConstraintOverrideMap constraints; + + base::StringPairs roots_and_constraints_pairs; + base::SplitStringIntoKeyValuePairs(switch_value, ':', '+', + &roots_and_constraints_pairs); + for (const auto& [root_hashes_hex, root_constraints] : + roots_and_constraints_pairs) { + std::vector> root_hashes; + for (std::string_view root_hash_hex : + base::SplitStringPiece(root_hashes_hex, ",", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY)) { + std::array root_hash; + if (!base::HexStringToSpan(root_hash_hex, root_hash)) { + LOG(ERROR) << "invalid root hash: " << root_hash_hex; + continue; + } + root_hashes.push_back(std::move(root_hash)); + } + if (root_hashes.empty()) { + LOG(ERROR) << "skipped constraintset with no valid root hashes"; + continue; + } + ChromeRootCertConstraints constraint; + base::StringPairs constraint_value_pairs; + base::SplitStringIntoKeyValuePairs(root_constraints, '=', ',', + &constraint_value_pairs); + for (const auto& [constraint_name, constraint_value] : + constraint_value_pairs) { + std::string constraint_name_lower = base::ToLowerASCII(constraint_name); + if (constraint_name_lower == "sctnotafter") { + int64_t value; + if (!base::StringToInt64(constraint_value, &value)) { + LOG(ERROR) << "invalid sctnotafter: " << constraint_value; + continue; + } + constraint.sct_not_after = + base::Time::UnixEpoch() + base::Seconds(value); + } else if (constraint_name_lower == "sctallafter") { + int64_t value; + if (!base::StringToInt64(constraint_value, &value)) { + LOG(ERROR) << "invalid sctallafter: " << constraint_value; + continue; + } + constraint.sct_all_after = + base::Time::UnixEpoch() + base::Seconds(value); + } else if (constraint_name_lower == "minversion") { + base::Version version(constraint_value); + if (!version.IsValid()) { + LOG(ERROR) << "invalid minversion: " << constraint_value; + continue; + } + constraint.min_version = version; + } else if (constraint_name_lower == "maxversionexclusive") { + base::Version version(constraint_value); + if (!version.IsValid()) { + LOG(ERROR) << "invalid maxversionexclusive: " << constraint_value; + continue; + } + constraint.max_version_exclusive = version; + } else { + LOG(ERROR) << "unrecognized constraint " << constraint_name_lower; + } + // TODO(crbug.com/40941039): add other constraint types here when they + // are implemented + } + for (const auto& root_hash : root_hashes) { + constraints[root_hash].push_back(constraint); + } + } + + return constraints; +} + void TrustStoreChrome::SyncGetIssuersOf(const bssl::ParsedCertificate* cert, bssl::ParsedCertificateList* issuers) { trust_store_.SyncGetIssuersOf(cert, issuers); @@ -226,6 +329,15 @@ bool TrustStoreChrome::Contains(const bssl::ParsedCertificate* cert) const { base::span TrustStoreChrome::GetConstraintsForCert( const bssl::ParsedCertificate* cert) const { + if (!override_constraints_.empty()) { + const std::array cert_hash = + crypto::SHA256Hash(cert->der_cert()); + auto it = override_constraints_.find(cert_hash); + if (it != override_constraints_.end()) { + return it->second; + } + } + auto it = constraints_.find(cert->der_cert().AsStringView()); if (it != constraints_.end()) { return it->second; @@ -236,10 +348,13 @@ TrustStoreChrome::GetConstraintsForCert( // static std::unique_ptr TrustStoreChrome::CreateTrustStoreForTesting( base::span certs, - int64_t version) { + int64_t version, + ConstraintOverrideMap override_constraints) { // Note: wrap_unique is used because the constructor is private. return base::WrapUnique(new TrustStoreChrome( - certs, /*certs_are_static=*/false, /*version=*/version)); + certs, + /*certs_are_static=*/false, + /*version=*/version, std::move(override_constraints))); } int64_t CompiledChromeRootStoreVersion() { diff --git a/naiveproxy/src/net/cert/internal/trust_store_chrome.h b/naiveproxy/src/net/cert/internal/trust_store_chrome.h index 1ecc8b7390..30c589aa7b 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_chrome.h +++ b/naiveproxy/src/net/cert/internal/trust_store_chrome.h @@ -12,6 +12,7 @@ #include "base/containers/span.h" #include "base/time/time.h" #include "base/version.h" +#include "crypto/sha2.h" #include "net/base/net_export.h" #include "third_party/boringssl/src/pki/trust_store.h" #include "third_party/boringssl/src/pki/trust_store_in_memory.h" @@ -42,6 +43,7 @@ struct ChromeRootCertInfo { }; struct NET_EXPORT ChromeRootCertConstraints { + ChromeRootCertConstraints(); ChromeRootCertConstraints(std::optional sct_not_after, std::optional sct_all_after, std::optional min_version, @@ -104,18 +106,43 @@ class NET_EXPORT ChromeRootStoreData { // https://g.co/chrome/root-policy class NET_EXPORT TrustStoreChrome : public bssl::TrustStore { public: + using ConstraintOverrideMap = + base::flat_map, + std::vector>; + + // Commandline switch that can be used to specify constraints for testing + // purposes. + // + // The base unit of the switch is a root constraint specification: + // `${comma_separated_root_sha256_hashes}:${comma_separated_constraints}` + // Multiple such specifications can be separated by `+` characters: + // `${hashes}:${constraints}+${morehashes}:${moreconstraints}` + // + // Recognized constraints: + // `sctnotafter=${seconds_since_epoch}` + // `sctallafter=${seconds_since_epoch}` + // `minversion=${dotted_version_string}` + // `maxversionexclusive=${dotted_version_string}` + // + // If the same root hash is specified multiple times in separate constraint + // specifications, each time will create a new constraintset for that root, + // which can be used to test the handling of multiple constraintsets on one + // root. + static constexpr char kTestCrsConstraintsSwitch[] = "test-crs-constraints"; + // Creates a TrustStoreChrome that uses a copy of `certs`, instead of the // default Chrome Root Store. static std::unique_ptr CreateTrustStoreForTesting( base::span certs, - int64_t version); + int64_t version, + ConstraintOverrideMap override_constraints = {}); // Creates a TrustStoreChrome that uses the compiled in Chrome Root Store. TrustStoreChrome(); // Creates a TrustStoreChrome that uses the passed in anchors as // the contents of the Chrome Root Store. - TrustStoreChrome(const ChromeRootStoreData& anchors); + explicit TrustStoreChrome(const ChromeRootStoreData& anchors); ~TrustStoreChrome() override; TrustStoreChrome(const TrustStoreChrome& other) = delete; @@ -137,17 +164,32 @@ class NET_EXPORT TrustStoreChrome : public bssl::TrustStore { int64_t version() const { return version_; } + // Parses a string specifying constraint overrides, in the format expected by + // the `kTestCrsConstraintsSwitch` command line switch. + static ConstraintOverrideMap ParseCrsConstraintsSwitch( + std::string_view switch_value); + private: TrustStoreChrome(base::span certs, bool certs_are_static, - int64_t version); + int64_t version, + ConstraintOverrideMap override_constraints); + + static ConstraintOverrideMap InitializeConstraintsOverrides(); + bssl::TrustStoreInMemory trust_store_; + // Map from certificate DER bytes to additional constraints (if any) for that // certificate. The DER bytes of the key are owned by the ParsedCertificate // stored in `trust_store_`, so this must be below `trust_store_` in the // member list. base::flat_map> constraints_; + + // Map from certificate SHA256 hash to constraints. If a certificate has an + // entry in this map, it will override the entry in `constraints_` (if any). + const ConstraintOverrideMap override_constraints_; + int64_t version_; }; diff --git a/naiveproxy/src/net/cert/internal/trust_store_features.cc b/naiveproxy/src/net/cert/internal/trust_store_features.cc deleted file mode 100644 index a86231f05e..0000000000 --- a/naiveproxy/src/net/cert/internal/trust_store_features.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/cert/internal/trust_store_features.h" - -#include - -#include "base/no_destructor.h" - -namespace net { - -namespace { -std::atomic_bool* GetLocalAnchorConstraintsEnforcementFlag() { - static std::atomic_bool flag = base::FeatureList::IsEnabled( - net::features::kEnforceLocalAnchorConstraints); - return &flag; -} - -} // namespace - -bool IsLocalAnchorConstraintsEnforcementEnabled() { - return GetLocalAnchorConstraintsEnforcementFlag()->load(); -} - -void SetLocalAnchorConstraintsEnforcementEnabled(bool enabled) { - GetLocalAnchorConstraintsEnforcementFlag()->store(enabled); -} - -namespace features { - -BASE_FEATURE(kEnforceLocalAnchorConstraints, - "EnforceLocalAnchorConstraints", - base::FEATURE_ENABLED_BY_DEFAULT); - -} // namespace features - -} // namespace net diff --git a/naiveproxy/src/net/cert/internal/trust_store_features.h b/naiveproxy/src/net/cert/internal/trust_store_features.h deleted file mode 100644 index 2807d6a1c5..0000000000 --- a/naiveproxy/src/net/cert/internal/trust_store_features.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_CERT_INTERNAL_TRUST_STORE_FEATURES_H_ -#define NET_CERT_INTERNAL_TRUST_STORE_FEATURES_H_ - -#include "base/feature_list.h" -#include "net/base/net_export.h" - -namespace net { - -// Returns true when platform bssl::TrustStore implementations should enforce -// constraints encoded into X.509 certificate trust anchors. -// When disabled, platform bssl::TrustStore implementations will not enforce -// anchor constraints (other than expiry). Has no effect if using a platform -// CertVerifyProc implementation. -// TODO(crbug.com/40887079): remove this a few milestones after the -// trust anchor constraints enforcement has been launched on all relevant -// platforms. -// Should only be called after base::Features have been resolved. Note that -// using ScopedFeatureList to override this won't work properly in unittests, -// use ScopedLocalAnchorConstraintsEnforcementForTesting instead. Using -// ScopedFeatureList in browser_tests is fine. -// It is safe to call this function on any thread. -NET_EXPORT bool IsLocalAnchorConstraintsEnforcementEnabled(); - -// Override the feature flag. Don't call this without consulting -// net/cert/OWNERS. -// It is safe to call this function on any thread. -NET_EXPORT void SetLocalAnchorConstraintsEnforcementEnabled(bool enabled); - -// Temporarily change the SetLocalAnchorConstraintsEnforcementEnabled value, -// resetting to the original value when destructed. -class NET_EXPORT ScopedLocalAnchorConstraintsEnforcementForTesting { - public: - explicit ScopedLocalAnchorConstraintsEnforcementForTesting(bool enabled) - : previous_value_(IsLocalAnchorConstraintsEnforcementEnabled()) { - SetLocalAnchorConstraintsEnforcementEnabled(enabled); - } - - ~ScopedLocalAnchorConstraintsEnforcementForTesting() { - SetLocalAnchorConstraintsEnforcementEnabled(previous_value_); - } - - private: - const bool previous_value_; -}; - -namespace features { - -// Most code should not check this feature flag directly, instead use -// IsLocalAnchorConstraintsEnforcementEnabled(). -NET_EXPORT BASE_DECLARE_FEATURE(kEnforceLocalAnchorConstraints); - -} // namespace features - -} // namespace net - -#endif // NET_CERT_INTERNAL_TRUST_STORE_FEATURES_H_ diff --git a/naiveproxy/src/net/cert/internal/trust_store_mac.cc b/naiveproxy/src/net/cert/internal/trust_store_mac.cc index 4465b3e66c..bd0809e41b 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_mac.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_mac.cc @@ -31,7 +31,7 @@ #include "net/base/features.h" #include "net/base/hash_value.h" #include "net/base/network_notification_thread_mac.h" -#include "net/cert/internal/trust_store_features.h" +#include "net/cert/internal/platform_trust_store.h" #include "net/cert/test_keychain_search_list_mac.h" #include "net/cert/x509_util.h" #include "net/cert/x509_util_apple.h" @@ -1070,11 +1070,9 @@ bssl::CertificateTrust TrustStoreMac::GetTrust( // depend on the context the certificate is encountered in. bssl::CertificateTrust trust = bssl::CertificateTrust::ForTrustAnchorOrLeaf() - .WithEnforceAnchorExpiry(); - if (IsLocalAnchorConstraintsEnforcementEnabled()) { - trust = trust.WithEnforceAnchorConstraints() - .WithRequireAnchorBasicConstraints(); - } + .WithEnforceAnchorExpiry() + .WithEnforceAnchorConstraints() + .WithRequireAnchorBasicConstraints(); return trust; } case TrustStatus::DISTRUSTED: @@ -1091,6 +1089,12 @@ bssl::CertificateTrust TrustStoreMac::GetTrust( return bssl::CertificateTrust::ForUnspecified(); } +std::vector +TrustStoreMac::GetAllUserAddedCerts() { + // TODO(crbug.com/40928765): implement this. + return {}; +} + // static std::vector> TrustStoreMac::FindMatchingCertificatesForMacNormalizedSubject( diff --git a/naiveproxy/src/net/cert/internal/trust_store_mac.h b/naiveproxy/src/net/cert/internal/trust_store_mac.h index 6f13044618..576017cf20 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_mac.h +++ b/naiveproxy/src/net/cert/internal/trust_store_mac.h @@ -10,6 +10,7 @@ #include "base/apple/scoped_cftyperef.h" #include "base/gtest_prod_util.h" #include "net/base/net_export.h" +#include "net/cert/internal/platform_trust_store.h" #include "third_party/boringssl/src/pki/trust_store.h" namespace net { @@ -21,7 +22,7 @@ namespace net { // methods may be called from multiple threads simultaneously. It is the owner's // responsibility to ensure the TrustStoreMac object outlives any threads // accessing it. -class NET_EXPORT TrustStoreMac : public bssl::TrustStore { +class NET_EXPORT TrustStoreMac : public PlatformTrustStore { public: // NOTE: When updating this enum, also update ParamToTrustImplType in // system_trust_store.cc @@ -54,6 +55,10 @@ class NET_EXPORT TrustStoreMac : public bssl::TrustStore { bssl::ParsedCertificateList* issuers) override; bssl::CertificateTrust GetTrust(const bssl::ParsedCertificate* cert) override; + // net::PlatformTrustStore implementation: + std::vector GetAllUserAddedCerts() + override; + private: class TrustImpl; class TrustImplDomainCacheFullCerts; diff --git a/naiveproxy/src/net/cert/internal/trust_store_nss.cc b/naiveproxy/src/net/cert/internal/trust_store_nss.cc index c2a078d9a0..198a09c6a3 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_nss.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_nss.cc @@ -29,7 +29,7 @@ #include "crypto/nss_util_internal.h" #include "crypto/scoped_nss_types.h" #include "net/base/features.h" -#include "net/cert/internal/trust_store_features.h" +#include "net/cert/internal/platform_trust_store.h" #include "net/cert/scoped_nss_types.h" #include "net/cert/x509_util.h" #include "net/cert/x509_util_nss.h" @@ -454,11 +454,9 @@ bssl::CertificateTrust TrustStoreNSS::GetTrustIgnoringSystemTrust( return bssl::CertificateTrust::ForTrustedLeaf(); case CKT_NSS_TRUSTED_DELEGATOR: { DVLOG(1) << "CKT_NSS_TRUSTED_DELEGATOR -> trust anchor"; - const bool enforce_anchor_constraints = - IsLocalAnchorConstraintsEnforcementEnabled(); return bssl::CertificateTrust::ForTrustAnchor() - .WithEnforceAnchorConstraints(enforce_anchor_constraints) - .WithEnforceAnchorExpiry(enforce_anchor_constraints); + .WithEnforceAnchorConstraints() + .WithEnforceAnchorExpiry(); } case CKT_NSS_MUST_VERIFY_TRUST: case CKT_NSS_VALID_DELEGATOR: @@ -492,30 +490,21 @@ bssl::CertificateTrust TrustStoreNSS::GetTrustForNSSTrust( return bssl::CertificateTrust::ForDistrusted(); } - bool is_trusted_ca = false; - bool is_trusted_leaf = false; - const bool enforce_anchor_constraints = - IsLocalAnchorConstraintsEnforcementEnabled(); - // Determine if the certificate is a trust anchor. - if ((trust_flags & CERTDB_TRUSTED_CA) == CERTDB_TRUSTED_CA) { - is_trusted_ca = true; - } + bool is_trusted_ca = (trust_flags & CERTDB_TRUSTED_CA) == CERTDB_TRUSTED_CA; constexpr unsigned int kTrustedPeerBits = CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED; - if ((trust_flags & kTrustedPeerBits) == kTrustedPeerBits) { - is_trusted_leaf = true; - } + bool is_trusted_leaf = (trust_flags & kTrustedPeerBits) == kTrustedPeerBits; if (is_trusted_ca && is_trusted_leaf) { return bssl::CertificateTrust::ForTrustAnchorOrLeaf() - .WithEnforceAnchorConstraints(enforce_anchor_constraints) - .WithEnforceAnchorExpiry(enforce_anchor_constraints); + .WithEnforceAnchorConstraints() + .WithEnforceAnchorExpiry(); } else if (is_trusted_ca) { return bssl::CertificateTrust::ForTrustAnchor() - .WithEnforceAnchorConstraints(enforce_anchor_constraints) - .WithEnforceAnchorExpiry(enforce_anchor_constraints); + .WithEnforceAnchorConstraints() + .WithEnforceAnchorExpiry(); } else if (is_trusted_leaf) { return bssl::CertificateTrust::ForTrustedLeaf(); } @@ -523,4 +512,10 @@ bssl::CertificateTrust TrustStoreNSS::GetTrustForNSSTrust( return bssl::CertificateTrust::ForUnspecified(); } +std::vector +TrustStoreNSS::GetAllUserAddedCerts() { + // TODO(crbug.com/40928765): implement this. + return {}; +} + } // namespace net diff --git a/naiveproxy/src/net/cert/internal/trust_store_nss.h b/naiveproxy/src/net/cert/internal/trust_store_nss.h index 51c801b7fe..94aed3b8d9 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_nss.h +++ b/naiveproxy/src/net/cert/internal/trust_store_nss.h @@ -8,8 +8,11 @@ #include #include +#include + #include "crypto/scoped_nss_types.h" #include "net/base/net_export.h" +#include "net/cert/internal/platform_trust_store.h" #include "net/cert/scoped_nss_types.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/boringssl/src/pki/trust_store.h" @@ -18,7 +21,7 @@ namespace net { // TrustStoreNSS is an implementation of bssl::TrustStore which uses NSS to find // trust anchors for path building. This bssl::TrustStore is thread-safe. -class NET_EXPORT TrustStoreNSS : public bssl::TrustStore { +class NET_EXPORT TrustStoreNSS : public PlatformTrustStore { public: struct UseTrustFromAllUserSlots : absl::monostate {}; using UserSlotTrustSetting = @@ -46,6 +49,10 @@ class NET_EXPORT TrustStoreNSS : public bssl::TrustStore { // bssl::TrustStore implementation: bssl::CertificateTrust GetTrust(const bssl::ParsedCertificate* cert) override; + // net::PlatformTrustStore implementation: + std::vector GetAllUserAddedCerts() + override; + struct ListCertsResult { ListCertsResult(ScopedCERTCertificate cert, bssl::CertificateTrust trust); ~ListCertsResult(); diff --git a/naiveproxy/src/net/cert/internal/trust_store_win.cc b/naiveproxy/src/net/cert/internal/trust_store_win.cc index b43394922f..08383b87bd 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_win.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_win.cc @@ -11,6 +11,7 @@ #include +#include "base/containers/to_vector.h" #include "base/hash/sha1.h" #include "base/location.h" #include "base/logging.h" @@ -19,7 +20,6 @@ #include "base/strings/string_number_conversions.h" #include "base/threading/scoped_blocking_call.h" #include "net/base/features.h" -#include "net/cert/internal/trust_store_features.h" #include "net/cert/x509_util.h" #include "net/third_party/mozilla_win/cert/win_util.h" #include "third_party/boringssl/src/pki/cert_errors.h" @@ -29,6 +29,19 @@ namespace net { namespace { +// Certificates in the Windows roots store may be used as either trust +// anchors or trusted leafs (if self-signed). +constexpr bssl::CertificateTrust kRootCertTrust = + bssl::CertificateTrust::ForTrustAnchorOrLeaf() + .WithEnforceAnchorExpiry() + .WithEnforceAnchorConstraints() + .WithRequireLeafSelfSigned(); + +// Certificates in the Trusted People store may be trusted leafs (if +// self-signed). +constexpr bssl::CertificateTrust kTrustedPeopleTrust = + bssl::CertificateTrust::ForTrustedLeaf().WithRequireLeafSelfSigned(); + // Returns true if the cert can be used for server authentication, based on // certificate properties. // @@ -88,6 +101,15 @@ bool IsCertTrustedForServerAuth(PCCERT_CONTEXT cert) { return false; } +void AddCertWithTrust( + PCCERT_CONTEXT cert, + const bssl::CertificateTrust trust, + std::vector* certs) { + certs->push_back(net::PlatformTrustStore::CertWithTrust( + base::ToVector(base::make_span(cert->pbCertEncoded, cert->cbCertEncoded)), + trust)); +} + } // namespace TrustStoreWin::CertStores::CertStores() = default; @@ -326,13 +348,7 @@ class TrustStoreWin::Impl { // If we find at least one version of the cert that is trusted for TLS // Server Auth, we will trust the cert. if (IsCertTrustedForServerAuth(cert_from_store)) { - // Certificates in the Roots store may be used as either trust - // anchors or trusted leafs (if self-signed). - return bssl::CertificateTrust::ForTrustAnchorOrLeaf() - .WithEnforceAnchorExpiry() - .WithEnforceAnchorConstraints( - IsLocalAnchorConstraintsEnforcementEnabled()) - .WithRequireLeafSelfSigned(); + return kRootCertTrust; } } } @@ -346,10 +362,7 @@ class TrustStoreWin::Impl { // If we find at least one version of the cert that is trusted for TLS // Server Auth, we will trust the cert. if (IsCertTrustedForServerAuth(cert_from_store)) { - // Certificates in the Trusted People store may be trusted leafs (if - // self-signed). - return bssl::CertificateTrust::ForTrustedLeaf() - .WithRequireLeafSelfSigned(); + return kTrustedPeopleTrust; } } } @@ -368,6 +381,44 @@ class TrustStoreWin::Impl { return bssl::CertificateTrust::ForUnspecified(); } + std::vector GetAllUserAddedCerts() { + std::vector certs; + if (!root_cert_store_.get() || !intermediate_cert_store_.get() || + !trusted_people_cert_store_.get() || !all_certs_store_.get() || + !disallowed_cert_store_.get()) { + return certs; + } + + PCCERT_CONTEXT cert_from_store = nullptr; + while ((cert_from_store = CertEnumCertificatesInStore( + disallowed_cert_store_.get(), cert_from_store))) { + AddCertWithTrust(cert_from_store, bssl::CertificateTrust::ForDistrusted(), + &certs); + } + + while ((cert_from_store = CertEnumCertificatesInStore( + trusted_people_cert_store_.get(), cert_from_store))) { + if (IsCertTrustedForServerAuth(cert_from_store)) { + AddCertWithTrust(cert_from_store, kTrustedPeopleTrust, &certs); + } + } + + while ((cert_from_store = CertEnumCertificatesInStore( + root_cert_store_.get(), cert_from_store))) { + if (IsCertTrustedForServerAuth(cert_from_store)) { + AddCertWithTrust(cert_from_store, kRootCertTrust, &certs); + } + } + + while ((cert_from_store = CertEnumCertificatesInStore( + intermediate_cert_store_.get(), cert_from_store))) { + AddCertWithTrust(cert_from_store, + bssl::CertificateTrust::ForUnspecified(), &certs); + } + + return certs; + } + private: // Cert Collection containing all user-added trust anchors. crypto::ScopedHCERTSTORE root_cert_store_; @@ -452,4 +503,9 @@ bssl::CertificateTrust TrustStoreWin::GetTrust( return MaybeInitializeAndGetImpl()->GetTrust(cert); } +std::vector +TrustStoreWin::GetAllUserAddedCerts() { + return MaybeInitializeAndGetImpl()->GetAllUserAddedCerts(); +} + } // namespace net diff --git a/naiveproxy/src/net/cert/internal/trust_store_win.h b/naiveproxy/src/net/cert/internal/trust_store_win.h index e0b33d13c9..ceaa56787b 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_win.h +++ b/naiveproxy/src/net/cert/internal/trust_store_win.h @@ -5,11 +5,14 @@ #ifndef NET_CERT_INTERNAL_TRUST_STORE_WIN_H_ #define NET_CERT_INTERNAL_TRUST_STORE_WIN_H_ +#include + #include "base/memory/ptr_util.h" #include "base/synchronization/lock.h" #include "base/win/wincrypt_shim.h" #include "crypto/scoped_capi_types.h" #include "net/base/net_export.h" +#include "net/cert/internal/platform_trust_store.h" #include "third_party/boringssl/src/pki/trust_store.h" namespace net { @@ -19,7 +22,7 @@ namespace net { // the Windows builtin trust anchors. This bssl::TrustStore is thread-safe (we // think). // TODO(crbug.com/40784682): confirm this is thread safe. -class NET_EXPORT TrustStoreWin : public bssl::TrustStore { +class NET_EXPORT TrustStoreWin : public PlatformTrustStore { public: struct NET_EXPORT_PRIVATE CertStores { ~CertStores(); @@ -79,6 +82,10 @@ class NET_EXPORT TrustStoreWin : public bssl::TrustStore { bssl::CertificateTrust GetTrust(const bssl::ParsedCertificate* cert) override; + // net::PlatformTrustStore implementation: + std::vector GetAllUserAddedCerts() + override; + private: // Inner Impl class for use in initializing stores. class Impl; diff --git a/naiveproxy/src/net/cert/known_roots.cc b/naiveproxy/src/net/cert/known_roots.cc index bab8dfa963..947dcec279 100644 --- a/naiveproxy/src/net/cert/known_roots.cc +++ b/naiveproxy/src/net/cert/known_roots.cc @@ -52,9 +52,4 @@ int32_t GetNetTrustAnchorHistogramIdForSPKI(const HashValue& spki_hash) { return root_data->histogram_id; } -bool IsLegacyPubliclyTrustedCA(const HashValue& spki_hash) { - const RootCertData* root_data = GetRootCertData(spki_hash); - return root_data && root_data->legacy_ca; -} - } // namespace net diff --git a/naiveproxy/src/net/cert/known_roots.h b/naiveproxy/src/net/cert/known_roots.h index 02a0264f98..44ecb76d3a 100644 --- a/naiveproxy/src/net/cert/known_roots.h +++ b/naiveproxy/src/net/cert/known_roots.h @@ -20,13 +20,6 @@ class HashValue; NET_EXPORT int32_t GetNetTrustAnchorHistogramIdForSPKI(const HashValue& spki_hash); -// Returns true if the CA identified by |spki_hash| is known as a Legacy CA, -// which means that they are known as a well-known root, but are not trusted -// on the ChromiumOS or Android platforms. This indicates a CA that either has -// been removed from public trust (generally, voluntarily) or has not (or not -// yet) undergone a public review and discussion for broad public trust. -NET_EXPORT bool IsLegacyPubliclyTrustedCA(const HashValue& spki_hash); - } // namespace net #endif // NET_CERT_KNOWN_ROOTS_H_ diff --git a/naiveproxy/src/net/cert/root_cert_list_generated.h b/naiveproxy/src/net/cert/root_cert_list_generated.h index cf13fcf103..22ccc631f6 100644 --- a/naiveproxy/src/net/cert/root_cert_list_generated.h +++ b/naiveproxy/src/net/cert/root_cert_list_generated.h @@ -25,3805 +25,3259 @@ const struct RootCertData { // A value suitable for histograms using the NetTrustAnchors enum. int16_t histogram_id : 15; - - // If true, indicates the CA is considered a "Legacy" CA, formerly trusted - // or not yet trusted. - bool legacy_ca : 1; } kRootCerts[] = { {{ 0x00, 0x41, 0x24, 0xAD, 0x60, 0x37, 0xFD, 0x5F, 0x33, 0x19, 0xE7, 0xA2, 0x3D, 0x4D, 0x9C, 0x81, 0x1F, 0x55, 0x98, 0xD6, 0x6C, 0x47, 0x54, 0x15, 0x5B, 0x0A, 0xAA, 0x9E, 0x8F, 0x00, 0x62, 0x1F, }, - 357, - true}, + 357}, {{ 0x00, 0x6C, 0xB2, 0x26, 0xA7, 0x72, 0xC7, 0x18, 0x2D, 0x77, 0x72, 0x38, 0x3E, 0x37, 0x3F, 0x0F, 0x22, 0x9E, 0x7D, 0xFE, 0x34, 0x44, 0x81, 0x0A, 0x8D, 0x6E, 0x50, 0x90, 0x5D, 0x20, 0xD6, 0x61, }, - 251, - true}, + 251}, {{ 0x00, 0x6D, 0x7B, 0xE7, 0x55, 0x5D, 0xD8, 0x20, 0x26, 0x44, 0x2C, 0x4F, 0x1A, 0x27, 0xA8, 0x0E, 0x89, 0xA1, 0x98, 0x9C, 0xB8, 0x7B, 0x34, 0x44, 0x8E, 0xD2, 0x19, 0x4C, 0x18, 0x19, 0x6D, 0x5E, }, - 55, - false}, + 55}, {{ 0x01, 0xD0, 0xD8, 0xE0, 0x7B, 0xC5, 0xA9, 0x2D, 0xA7, 0xE7, 0xB8, 0x1E, 0x9A, 0x56, 0x9F, 0xE3, 0xA2, 0xD6, 0x3A, 0x99, 0x7D, 0xAC, 0x59, 0x60, 0x02, 0xC5, 0xDC, 0x81, 0x0C, 0xAD, 0x17, 0xBD, }, - 283, - true}, + 283}, {{ 0x02, 0x06, 0xEA, 0xD1, 0x63, 0xB1, 0x0E, 0xA2, 0xF8, 0x62, 0x08, 0x68, 0xEB, 0xD7, 0xA1, 0x5F, 0x64, 0xA2, 0x02, 0x50, 0xD1, 0x6C, 0xD5, 0x7D, 0x6E, 0x87, 0xC4, 0xFF, 0xF1, 0xA2, 0x19, 0x7C, }, - 456, - true}, + 456}, {{ 0x02, 0x37, 0x6D, 0x09, 0x08, 0xAC, 0x23, 0x04, 0x1C, 0xC7, 0xD6, 0x66, 0xD9, 0xDA, 0xF1, 0x92, 0x55, 0x4F, 0x7F, 0xC3, 0x63, 0x17, 0xAA, 0x9C, 0xB8, 0x00, 0x90, 0x86, 0x16, 0xB2, 0x8A, 0xF8, }, - 411, - true}, + 411}, {{ 0x02, 0x3C, 0x81, 0xCC, 0xE8, 0xE7, 0xC6, 0x4F, 0xA9, 0x42, 0xD3, 0xC1, 0x50, 0x48, 0x70, 0x7D, 0x35, 0xD9, 0xBB, 0x5B, 0x87, 0xF4, 0xF5, 0x44, 0xC5, 0xBF, 0x1B, 0xC5, 0x64, 0x3A, 0xF2, 0xFA, }, - 69, - true}, + 69}, {{ 0x04, 0xA6, 0xEA, 0x65, 0x4B, 0x23, 0x65, 0x89, 0x73, 0xC9, 0x81, 0x98, 0xC6, 0x4A, 0x3A, 0x69, 0x1C, 0x0D, 0xA7, 0x2E, 0xBE, 0xBD, 0x9A, 0xEB, 0xF7, 0x53, 0x24, 0xCD, 0xE6, 0x96, 0x0E, 0xAA, }, - 157, - true}, + 157}, {{ 0x05, 0x1C, 0xF9, 0xFA, 0x95, 0xE4, 0x0E, 0x9B, 0x83, 0xED, 0xAE, 0xDA, 0x69, 0x61, 0xF6, 0x16, 0x8C, 0x78, 0x79, 0xC4, 0x66, 0x01, 0x72, 0x47, 0x9C, 0xDD, 0x51, 0xAB, 0x03, 0xCE, 0xA6, 0x2B, }, - 73, - false}, + 73}, {{ 0x05, 0x2B, 0x68, 0x71, 0x07, 0xEC, 0x84, 0xE8, 0x73, 0x03, 0x82, 0x45, 0x2E, 0xC2, 0xA2, 0x74, 0x51, 0x74, 0x5D, 0x74, 0x85, 0xA5, 0x7D, 0x6F, 0x46, 0x4E, 0x0D, 0xA7, 0xA1, 0xB6, 0xAF, 0x2A, }, - 136, - true}, + 136}, {{ 0x05, 0x57, 0x0A, 0xE6, 0xEB, 0x0F, 0xCE, 0xB4, 0x21, 0x0E, 0x6D, 0xB7, 0x94, 0x86, 0xB7, 0x09, 0x4C, 0xAF, 0x20, 0x04, 0x01, 0xE1, 0x49, 0xB6, 0x67, 0x74, 0x41, 0xB5, 0xF2, 0x5E, 0x44, 0x9B, }, - 36, - false}, + 36}, {{ 0x05, 0xE7, 0x7E, 0xF1, 0xFD, 0xFE, 0x05, 0xE2, 0xDC, 0xA5, 0x22, 0xCA, 0xE6, 0x4D, 0x83, 0x79, 0xA0, 0x41, 0xB7, 0xB4, 0xF1, 0x6C, 0x7C, 0xAE, 0x36, 0x06, 0x7A, 0x7F, 0x72, 0xA1, 0x48, 0x72, }, - 37, - false}, + 37}, {{ 0x05, 0xEC, 0x08, 0x97, 0xB2, 0x19, 0x95, 0xA4, 0xA9, 0x89, 0x9F, 0x8F, 0xCB, 0x06, 0x60, 0x1A, 0xDE, 0x61, 0xC0, 0x43, 0x89, 0x96, 0x9D, 0x13, 0x8F, 0xE3, 0x2C, 0xD6, 0xCF, 0xC7, 0x46, 0xAB, }, - 309, - true}, + 309}, {{ 0x06, 0x56, 0xF5, 0x95, 0x52, 0x04, 0xC8, 0xD2, 0xBC, 0x8B, 0x1C, 0xA4, 0x75, 0xE2, 0xA4, 0xFA, 0x6E, 0x12, 0x4D, 0x12, 0x45, 0x12, 0x78, 0x41, 0x57, 0xC8, 0x58, 0xB5, 0x54, 0x71, 0x14, 0x1A, }, - 78, - true}, + 78}, {{ 0x06, 0xC7, 0xBD, 0x95, 0x53, 0xF7, 0x10, 0xE0, 0x58, 0xEB, 0x27, 0xB1, 0x5D, 0x47, 0xDD, 0x62, 0xD7, 0xFD, 0x43, 0x52, 0xD9, 0x1D, 0xA9, 0x6E, 0x1E, 0xFC, 0x50, 0xE1, 0x53, 0x54, 0xB8, 0xD7, }, - 302, - true}, + 302}, {{ 0x07, 0xE8, 0x54, 0xF2, 0x6A, 0x7C, 0xBD, 0x38, 0x99, 0x27, 0xAA, 0x04, 0x1B, 0xFE, 0xF1, 0xB6, 0xCD, 0x21, 0xDD, 0x14, 0x38, 0x18, 0xAD, 0x94, 0x7D, 0xC6, 0x55, 0xA9, 0xE5, 0x87, 0xFE, 0x88, }, - 190, - false}, + 190}, {{ 0x08, 0x6D, 0xCD, 0x7B, 0xCF, 0x86, 0x4A, 0xAA, 0xD5, 0xEF, 0x8C, 0x1C, 0x57, 0x7B, 0xB6, 0x8A, 0x13, 0x1E, 0x05, 0x5C, 0x93, 0xF6, 0x3B, 0x9C, 0x47, 0xEE, 0x26, 0xEE, 0xF1, 0x5B, 0xE7, 0xAB, }, - 338, - true}, + 338}, {{ 0x08, 0xB3, 0xA6, 0x33, 0x5F, 0xCE, 0x5E, 0xF4, 0x8F, 0x8F, 0x0E, 0x54, 0x39, 0x86, 0xC0, 0x7F, 0xD1, 0x8A, 0x3B, 0x12, 0x26, 0x12, 0x9F, 0x61, 0x86, 0x4B, 0xBD, 0x5B, 0xDD, 0x1F, 0x1C, 0xC9, }, - 180, - false}, + 180}, {{ 0x09, 0x3D, 0xB7, 0x67, 0x88, 0x8F, 0x6B, 0x13, 0x27, 0x55, 0x5D, 0xBD, 0x42, 0xBB, 0x5C, 0x93, 0xFE, 0xDE, 0xC5, 0x04, 0x4C, 0x7A, 0x84, 0xBC, 0x6E, 0xA3, 0x2A, 0x57, 0x8C, 0x22, 0x35, 0xC0, }, - 114, - true}, + 114}, {{ 0x09, 0x99, 0xBF, 0x90, 0x0B, 0xD5, 0xC2, 0x97, 0x86, 0x5E, 0x21, 0xE1, 0xAA, 0xDE, 0x6C, 0xF6, 0xBB, 0x3A, 0x94, 0xD1, 0x1A, 0xE5, 0xEA, 0x79, 0x84, 0x42, 0xA4, 0xE2, 0xF8, 0x13, 0x24, 0x1F, }, - 329, - true}, + 329}, {{ 0x0B, 0x9F, 0xA5, 0xA5, 0x9E, 0xED, 0x71, 0x5C, 0x26, 0xC1, 0x02, 0x0C, 0x71, 0x1B, 0x4F, 0x6E, 0xC4, 0x2D, 0x58, 0xB0, 0x01, 0x5E, 0x14, 0x33, 0x7A, 0x39, 0xDA, 0xD3, 0x01, 0xC5, 0xAF, 0xC3, }, - 200, - false}, + 200}, {{ 0x0B, 0xDD, 0x5A, 0xBE, 0x94, 0x0C, 0xAA, 0xAB, 0xE8, 0xB2, 0xBB, 0xA8, 0x83, 0x48, 0xFB, 0x6F, 0x4A, 0xA4, 0xCC, 0x84, 0x43, 0x6F, 0x88, 0x0B, 0xEC, 0xE6, 0x6B, 0x48, 0xBD, 0xA9, 0x13, 0xD8, }, - 250, - true}, + 250}, {{ 0x0C, 0x7A, 0xCA, 0xA7, 0x10, 0x22, 0x67, 0x20, 0xBB, 0xC9, 0x40, 0x34, 0x9E, 0xE2, 0xE6, 0x14, 0x86, 0x52, 0xA8, 0x9D, 0xBF, 0x40, 0x6A, 0x23, 0x2C, 0x89, 0x5F, 0x6D, 0xC7, 0x8E, 0xBB, 0x9A, }, - 91, - false}, + 91}, {{ 0x0D, 0x47, 0xE9, 0x85, 0x88, 0x45, 0x2C, 0xF0, 0x77, 0x8A, 0xF6, 0xAF, 0x03, 0xD4, 0x42, 0x72, 0x1D, 0xC0, 0x83, 0x66, 0x0A, 0x4B, 0xB2, 0x3C, 0x69, 0x74, 0x41, 0xFE, 0x2B, 0xB8, 0x4F, 0x9B, }, - 314, - true}, + 314}, {{ 0x0F, 0x9C, 0x12, 0x99, 0x55, 0x75, 0x98, 0xCF, 0x75, 0x21, 0xBC, 0xC8, 0x79, 0x84, 0x20, 0xA1, 0x55, 0xCE, 0xC1, 0xBB, 0x23, 0xA5, 0x7A, 0xC3, 0x7F, 0x51, 0x20, 0xFC, 0x9A, 0x20, 0x57, 0xF8, }, - 433, - true}, + 433}, {{ 0x0F, 0xE1, 0x4C, 0x26, 0x4B, 0x17, 0xBB, 0x6F, 0x0D, 0x65, 0x3E, 0x7A, 0x70, 0xEB, 0x36, 0x3D, 0xBF, 0x54, 0xBE, 0x15, 0x80, 0x39, 0xED, 0xDA, 0xE5, 0xC2, 0x57, 0x11, 0xDF, 0x48, 0xC1, 0x03, }, - 270, - true}, + 270}, {{ 0x10, 0x69, 0xFA, 0x47, 0xA0, 0xAA, 0x4F, 0x8C, 0xF7, 0x11, 0x1B, 0x1C, 0xAE, 0xA3, 0x65, 0xEE, 0xAE, 0xD1, 0x0B, 0xFF, 0xF3, 0x26, 0x60, 0xDE, 0xF6, 0xE0, 0x61, 0x4B, 0xFA, 0xE7, 0x08, 0x75, }, - 45, - true}, + 45}, {{ 0x10, 0xBA, 0x34, 0x85, 0xCA, 0x8B, 0xB6, 0x88, 0x0A, 0xB9, 0x53, 0x1A, 0x40, 0x63, 0xE4, 0x00, 0x15, 0x55, 0x56, 0x1C, 0x7F, 0x2E, 0x05, 0x51, 0x65, 0xF4, 0x9B, 0x2D, 0x74, 0xFC, 0x5F, 0x6B, }, - 62, - false}, + 62}, {{ 0x11, 0x1C, 0x24, 0xA2, 0x43, 0x06, 0x1D, 0xA7, 0x6E, 0x57, 0xE3, 0xB1, 0x24, 0x3E, 0xDA, 0x90, 0x87, 0x9F, 0xFB, 0x75, 0x05, 0x52, 0x39, 0x54, 0x43, 0xFA, 0x8C, 0x34, 0xDC, 0x0E, 0xD7, 0x37, }, - 442, - true}, + 442}, {{ 0x11, 0x24, 0x32, 0xE4, 0xBB, 0x84, 0x8C, 0x45, 0x54, 0x9F, 0xCB, 0xF0, 0xC7, 0x10, 0xC5, 0x66, 0xD0, 0x08, 0x2B, 0xBB, 0xC4, 0xE9, 0xB3, 0x8E, 0x6C, 0x76, 0xAD, 0x46, 0x44, 0x81, 0x28, 0xFC, }, - 388, - true}, + 388}, {{ 0x11, 0x34, 0xFD, 0x81, 0x56, 0x1A, 0x28, 0x18, 0xEC, 0xCF, 0xFF, 0xC2, 0xE4, 0x40, 0xA0, 0xCE, 0xF9, 0xA4, 0x0E, 0x29, 0x26, 0xC0, 0x82, 0x99, 0x80, 0x4D, 0x73, 0x8B, 0x0A, 0x97, 0xF6, 0x3D, }, - 515, - true}, + 515}, {{ 0x12, 0x23, 0x12, 0xC0, 0x81, 0x94, 0x91, 0x06, 0xB7, 0x04, 0x9F, 0x3F, 0xEB, 0xF1, 0x99, 0xC0, 0x10, 0xAD, 0xA1, 0x3E, 0x32, 0x81, 0xCD, 0x35, 0x8A, 0x41, 0xE7, 0xBD, 0x09, 0xC8, 0x29, 0xD7, }, - 514, - true}, + 514}, {{ 0x12, 0x55, 0xCA, 0xBE, 0x81, 0x52, 0xFA, 0x64, 0xDF, 0x94, 0x2F, 0x7A, 0x47, 0x41, 0x7E, 0x29, 0xF9, 0x6C, 0x1C, 0xE1, 0x1B, 0xF8, 0xC8, 0x4E, 0xCB, 0xE2, 0x81, 0x5C, 0xC1, 0x28, 0x08, 0x10, }, - 469, - false}, + 469}, {{ 0x14, 0x62, 0x00, 0x9B, 0x2D, 0xE6, 0x5D, 0x6D, 0x4D, 0x39, 0xBE, 0x89, 0x2B, 0xD2, 0xC1, 0x86, 0x49, 0x05, 0x31, 0xCE, 0x65, 0x90, 0xE4, 0x8F, 0xE1, 0x96, 0x07, 0x0D, 0x31, 0x7B, 0x60, 0xB0, }, - 330, - true}, + 330}, {{ 0x14, 0x9F, 0x2E, 0xE6, 0x3B, 0x9A, 0x5E, 0x58, 0x03, 0x24, 0x0A, 0x77, 0x0D, 0xC9, 0x91, 0xFC, 0x2E, 0x34, 0x45, 0xE6, 0x28, 0x31, 0xC2, 0x45, 0xA4, 0x9B, 0xC4, 0xF1, 0xF7, 0x38, 0xFF, 0x9C, }, - 196, - false}, + 196}, {{ 0x15, 0x28, 0x39, 0x7D, 0xA2, 0x12, 0x89, 0x0A, 0x83, 0x0B, 0x0B, 0x95, 0xA5, 0x99, 0x68, 0xCE, 0xF2, 0x34, 0x77, 0x37, 0x79, 0xDF, 0x51, 0x81, 0xCF, 0x10, 0xFA, 0x64, 0x75, 0x34, 0xBB, 0x65, }, - 146, - true}, + 146}, {{ 0x15, 0xBB, 0x28, 0xD9, 0x20, 0x7E, 0x13, 0xF8, 0xBC, 0x95, 0x57, 0xDD, 0x78, 0x5E, 0xBA, 0x77, 0x3B, 0xEA, 0x94, 0x4E, 0x04, 0xD7, 0xE0, 0x8F, 0xF8, 0xAA, 0x55, 0xEF, 0x31, 0x94, 0xAA, 0x20, }, - 400, - true}, + 400}, {{ 0x15, 0xE7, 0xE7, 0x17, 0xB4, 0x28, 0xFE, 0xEE, 0x3A, 0xF3, 0xAF, 0xD9, 0x15, 0x0D, 0xBA, 0xD4, 0x97, 0x00, 0x8D, 0x3A, 0x3F, 0xF0, 0x16, 0x96, 0x47, 0x19, 0x90, 0x7B, 0xDB, 0x01, 0xA6, 0x45, }, - 40, - true}, + 40}, {{ 0x15, 0xEE, 0xD3, 0x39, 0x59, 0x4B, 0x30, 0x4F, 0x8C, 0xF8, 0x47, 0xB4, 0x77, 0x37, 0x1D, 0x8D, 0x6F, 0xEC, 0x61, 0xF4, 0xDB, 0x2B, 0x01, 0xAF, 0x58, 0x9E, 0x7C, 0x53, 0xB3, 0x5C, 0xAE, 0x4C, }, - 174, - false}, + 174}, {{ 0x15, 0xF1, 0x4A, 0xC4, 0x5C, 0x9C, 0x7D, 0xA2, 0x33, 0xD3, 0x47, 0x91, 0x64, 0xE8, 0x13, 0x7F, 0xE3, 0x5E, 0xE0, 0xF3, 0x8A, 0xE8, 0x58, 0x18, 0x3F, 0x08, 0x41, 0x0E, 0xA8, 0x2A, 0xC4, 0xB4, }, - 22, - false}, + 22}, {{ 0x16, 0x1E, 0x83, 0xEA, 0x32, 0xD4, 0x76, 0x41, 0xE2, 0x3C, 0xBE, 0x0E, 0xB4, 0x13, 0xA3, 0xE0, 0xB0, 0x68, 0x59, 0x92, 0x2A, 0x49, 0xD1, 0xA2, 0x0C, 0xFA, 0x05, 0xA4, 0x1E, 0x28, 0x0C, 0xFC, }, - 300, - true}, + 300}, {{ 0x16, 0xA9, 0xE0, 0x12, 0xD3, 0x23, 0x29, 0xF2, 0x82, 0xB1, 0x0B, 0xBF, 0x57, 0xC7, 0xC0, 0xB4, 0x2A, 0xE8, 0x0F, 0x6A, 0xC9, 0x54, 0x2E, 0xB4, 0x09, 0xBC, 0x1C, 0x2C, 0xDE, 0x50, 0xD3, 0x22, }, - 229, - true}, + 229}, {{ 0x16, 0xD8, 0x2D, 0x67, 0xA1, 0xED, 0x8E, 0x89, 0xF9, 0xAB, 0x58, 0xF7, 0xD0, 0xFD, 0x3E, 0xB0, 0xD0, 0x01, 0x76, 0x87, 0xFC, 0xAE, 0xEC, 0xD4, 0x04, 0x75, 0xF1, 0x00, 0x83, 0xA5, 0xB5, 0x93, }, - 165, - true}, + 165}, {{ 0x17, 0x75, 0x5A, 0x5C, 0x29, 0x5F, 0x3D, 0x2D, 0x72, 0xE6, 0xF0, 0x31, 0xA1, 0xF0, 0x7F, 0x40, 0x0C, 0x58, 0x8B, 0x9E, 0x58, 0x2B, 0x22, 0xF1, 0x7E, 0xAE, 0x31, 0xA1, 0x59, 0x0D, 0x11, 0x85, }, - 52, - true}, + 52}, {{ 0x18, 0xCF, 0xA6, 0x45, 0x18, 0xE9, 0x16, 0xCA, 0xFE, 0x98, 0x55, 0x61, 0x51, 0x3C, 0xAB, 0x7A, 0x89, 0x7A, 0x54, 0xBD, 0x23, 0xB8, 0xE2, 0x68, 0x74, 0xC5, 0xC7, 0xCB, 0xD1, 0x24, 0x9C, 0xFC, }, - 317, - true}, + 317}, {{ 0x19, 0x06, 0xC6, 0x12, 0x4D, 0xBB, 0x43, 0x85, 0x78, 0xD0, 0x0E, 0x06, 0x6D, 0x50, 0x54, 0xC6, 0xC3, 0x7F, 0x0F, 0xA6, 0x02, 0x8C, 0x05, 0x54, 0x5E, 0x09, 0x94, 0xED, 0xDA, 0xEC, 0x86, 0x29, }, - 63, - false}, + 63}, {{ 0x19, 0x16, 0xF3, 0x50, 0x8E, 0xC3, 0xFA, 0xD7, 0x95, 0xF8, 0xDC, 0x4B, 0xD3, 0x16, 0xF9, 0xC6, 0x08, 0x5A, 0x64, 0xDE, 0x3C, 0x41, 0x53, 0xAC, 0x6D, 0x62, 0xD5, 0xEA, 0x19, 0x51, 0x5D, 0x39, }, - 162, - true}, + 162}, {{ 0x19, 0xAD, 0x98, 0xDE, 0x02, 0x15, 0x5D, 0x7E, 0x33, 0xE9, 0xDD, 0x21, 0xF0, 0xE4, 0x56, 0x10, 0xFD, 0x11, 0xD2, 0x80, 0x44, 0xB8, 0x31, 0x8B, 0xBE, 0xBF, 0x9F, 0x63, 0x37, 0x88, 0x8D, 0xF0, }, - 417, - true}, + 417}, {{ 0x1A, 0x42, 0x12, 0x23, 0xE8, 0x9B, 0xD8, 0x7C, 0x40, 0x3B, 0x48, 0xFA, 0x61, 0x69, 0x48, 0x47, 0x0D, 0x0F, 0x2C, 0x21, 0xCE, 0x2A, 0xC7, 0xBD, 0xD2, 0x27, 0x55, 0x06, 0x1C, 0x62, 0xBA, 0x92, }, - 304, - true}, + 304}, {{ 0x1A, 0x7A, 0x3A, 0x1A, 0x68, 0xDD, 0x23, 0x61, 0xE3, 0xF3, 0xBB, 0x85, 0x5F, 0x3B, 0x26, 0xFC, 0xD8, 0x8B, 0x19, 0x7D, 0x8D, 0xD4, 0xDE, 0x06, 0xCF, 0x1B, 0x36, 0x2A, 0xC8, 0x9E, 0xC1, 0x3B, }, - 39, - false}, + 39}, {{ 0x1B, 0x8A, 0x89, 0x53, 0x17, 0x01, 0x60, 0x8C, 0x9E, 0xF3, 0xC6, 0x5F, 0x5D, 0x60, 0xA9, 0x48, 0xB1, 0xBA, 0xDB, 0x97, 0x53, 0x62, 0x2A, 0x2E, 0x81, 0xC0, 0xA4, 0xA2, 0x84, 0xBE, 0x63, 0xCC, }, - 419, - true}, + 419}, {{ 0x1C, 0x29, 0x4B, 0xC2, 0x52, 0x43, 0x76, 0x89, 0x13, 0xED, 0x4A, 0xD5, 0xED, 0x61, 0xCB, 0x02, 0xBF, 0xBA, 0xE0, 0xBC, 0xE6, 0xE6, 0xE7, 0x2E, 0x5F, 0x96, 0x58, 0xF3, 0x46, 0xB4, 0x24, 0x96, }, - 244, - true}, + 244}, {{ 0x1D, 0x75, 0xD0, 0x83, 0x1B, 0x9E, 0x08, 0x85, 0x39, 0x4D, 0x32, 0xC7, 0xA1, 0xBF, 0xDB, 0x3D, 0xBC, 0x1C, 0x28, 0xE2, 0xB0, 0xE8, 0x39, 0x1F, 0xB1, 0x35, 0x98, 0x1D, 0xBC, 0x5B, 0xA9, 0x36, }, - 1, - false}, + 1}, {{ 0x1E, 0xA3, 0xC5, 0xE4, 0x3E, 0xD6, 0x6C, 0x2D, 0xA2, 0x98, 0x3A, 0x42, 0xA4, 0xA7, 0x9B, 0x1E, 0x90, 0x67, 0x86, 0xCE, 0x9F, 0x1B, 0x58, 0x62, 0x14, 0x19, 0xA0, 0x04, 0x63, 0xA8, 0x7D, 0x38, }, - 38, - false}, + 38}, {{ 0x1E, 0xB9, 0xCF, 0x90, 0x1F, 0x08, 0x58, 0xAA, 0x17, 0xC3, 0x99, 0xBA, 0xBE, 0xBB, 0xDD, 0x8C, 0xB3, 0x03, 0xA4, 0xEF, 0x4E, 0x12, 0x20, 0xC4, 0x93, 0xCC, 0xA2, 0xF7, 0x5A, 0x3F, 0x91, 0x4E, }, - 416, - true}, + 416}, {{ 0x1F, 0x3C, 0x9F, 0xD4, 0xFD, 0xBB, 0x50, 0xA0, 0x55, 0xBC, 0xCA, 0x7F, 0xE5, 0xA5, 0x81, 0xA9, 0x20, 0x99, 0xCE, 0xF1, 0xE9, 0xE4, 0x76, 0xD6, 0xBA, 0xEF, 0x0C, 0x91, 0x08, 0x31, 0xC7, 0xB3, }, - 519, - true}, + 519}, {{ 0x1F, 0x42, 0x24, 0xCE, 0xC8, 0x4F, 0xC9, 0x9C, 0xED, 0x88, 0x1F, 0xF6, 0xFC, 0xFD, 0x3E, 0x21, 0xF8, 0xC5, 0x19, 0xC5, 0x47, 0xAA, 0x6A, 0x5D, 0xD3, 0xDE, 0x24, 0x73, 0x02, 0xCE, 0x50, 0xD1, }, - 88, - true}, + 88}, {{ 0x20, 0x21, 0x91, 0x7E, 0x98, 0x26, 0x39, 0x45, 0xC8, 0x59, 0xC4, 0x3F, 0x1D, 0x73, 0xCB, 0x41, 0x39, 0x05, 0x3C, 0x41, 0x4F, 0xA0, 0x3C, 0xA3, 0xBC, 0x7E, 0xE8, 0x86, 0x14, 0x29, 0x8F, 0x3B, }, - 179, - false}, + 179}, {{ 0x20, 0x26, 0x65, 0xE4, 0xC5, 0xC3, 0x80, 0xB4, 0x49, 0x0A, 0x81, 0x77, 0x3D, 0xB5, 0xDB, 0xA6, 0x2A, 0x90, 0xDB, 0x6F, 0x5B, 0xE6, 0xE0, 0xE5, 0x4D, 0x11, 0x99, 0x2F, 0xB1, 0xE6, 0x55, 0xFD, }, - 398, - true}, + 398}, {{ 0x20, 0xE2, 0x4A, 0x5A, 0x33, 0x93, 0xD6, 0xC3, 0xAD, 0xC3, 0x84, 0xFA, 0xF9, 0x51, 0x52, 0xE1, 0xF9, 0xAA, 0x72, 0x22, 0x77, 0x40, 0x28, 0xB5, 0x3C, 0x5A, 0x34, 0xED, 0x0C, 0x6C, 0xB3, 0x99, }, - 351, - true}, + 351}, {{ 0x21, 0xAE, 0x41, 0x25, 0x66, 0x32, 0x47, 0x25, 0xFF, 0xEF, 0xC1, 0xDC, 0xCF, 0x88, 0xF1, 0x6F, 0x8D, 0x6B, 0xF4, 0xDB, 0xBB, 0x37, 0xFE, 0x8C, 0xAB, 0xA4, 0x7E, 0x8D, 0x66, 0xC2, 0xCD, 0xF9, }, - 477, - true}, + 477}, {{ 0x22, 0x05, 0x0A, 0x92, 0x83, 0x64, 0x81, 0xC2, 0xF3, 0xC1, 0xF8, 0x41, 0x7D, 0x37, 0x44, 0x7A, 0x16, 0x70, 0x07, 0xAC, 0x9B, 0xA6, 0x4E, 0xA2, 0x28, 0xCB, 0x6A, 0x1E, 0x14, 0xC6, 0x4B, 0x8B, }, - 379, - true}, + 379}, {{ 0x22, 0x07, 0x6E, 0x5A, 0xEF, 0x44, 0xBB, 0x9A, 0x41, 0x6A, 0x28, 0xB7, 0xD1, 0xC4, 0x43, 0x22, 0xD7, 0x05, 0x9F, 0x60, 0xFE, 0xFF, 0xA5, 0xCA, 0xF6, 0xC5, 0xBE, 0x84, 0x47, 0x89, 0x13, 0x03, }, - 226, - true}, + 226}, {{ 0x22, 0xA3, 0x69, 0x94, 0xF2, 0x8F, 0x2F, 0xA3, 0xB1, 0x6A, 0xE8, 0x72, 0xA7, 0x9D, 0xBB, 0x12, 0xA9, 0x82, 0xDA, 0x5B, 0x82, 0x4D, 0x7A, 0xE4, 0x34, 0xF9, 0x61, 0x78, 0xAC, 0x54, 0x03, 0x51, }, - 503, - true}, + 503}, {{ 0x23, 0x2C, 0xBE, 0x2D, 0x9E, 0x69, 0x94, 0xC1, 0xCE, 0xB7, 0xFB, 0xEE, 0x23, 0xAB, 0x16, 0x57, 0xDE, 0xFB, 0x6B, 0x35, 0x64, 0x72, 0x6F, 0x1E, 0x78, 0x95, 0x1C, 0xEF, 0x3A, 0x2B, 0x09, 0x5D, }, - 339, - true}, + 339}, {{ 0x23, 0x64, 0xD6, 0x92, 0xDC, 0xCA, 0xE1, 0x3D, 0xA5, 0x6A, 0xD4, 0xA0, 0x7C, 0x13, 0x25, 0xDC, 0x57, 0x52, 0x15, 0xFF, 0x1A, 0x07, 0x16, 0x81, 0xDF, 0xCA, 0x5D, 0xD6, 0xED, 0x7C, 0x84, 0x52, }, - 422, - true}, + 422}, {{ 0x23, 0x84, 0x9D, 0x09, 0x49, 0x23, 0xD4, 0x4A, 0x48, 0x81, 0xB6, 0x3A, 0xB1, 0x85, 0xE9, 0xBE, 0x15, 0xAA, 0xC8, 0xEF, 0x2C, 0x30, 0x44, 0xD9, 0x34, 0xBC, 0x7F, 0x26, 0xE2, 0xD2, 0xCD, 0x69, }, - 115, - true}, + 115}, {{ 0x23, 0xF2, 0xED, 0xFF, 0x3E, 0xDE, 0x90, 0x25, 0x9A, 0x9E, 0x30, 0xF4, 0x0A, 0xF8, 0xF9, 0x12, 0xA5, 0xE5, 0xB3, 0x69, 0x4E, 0x69, 0x38, 0x44, 0x03, 0x41, 0xF6, 0x06, 0x0E, 0x01, 0x4F, 0xFA, }, - 64, - false}, + 64}, {{ 0x24, 0x48, 0x03, 0xCF, 0xA3, 0x59, 0x53, 0x38, 0x5D, 0x06, 0x65, 0x7A, 0xC4, 0xE5, 0xAB, 0x4F, 0x2B, 0xC0, 0x40, 0x52, 0x77, 0xBE, 0x66, 0x2A, 0xDB, 0x90, 0x5E, 0x14, 0x98, 0xB1, 0xDE, 0xFD, }, - 460, - true}, + 460}, {{ 0x25, 0x41, 0xE5, 0x3B, 0xA5, 0xB3, 0xB0, 0x7A, 0xCB, 0xE7, 0x09, 0x7A, 0xC4, 0xA0, 0x3E, 0x04, 0x0C, 0x11, 0xCF, 0x7A, 0x6D, 0x4A, 0x67, 0xCB, 0x21, 0x3D, 0x55, 0x8B, 0x50, 0x16, 0x7A, 0x06, }, - 498, - false}, + 498}, {{ 0x25, 0x96, 0x90, 0x4D, 0xC4, 0xD6, 0x99, 0xAE, 0x20, 0xC2, 0xCE, 0xF4, 0xDC, 0xE4, 0x7F, 0x28, 0x59, 0x37, 0xD7, 0x74, 0x64, 0xAC, 0x37, 0x07, 0x46, 0xF5, 0x2D, 0xEA, 0x76, 0xBA, 0x0C, 0x28, }, - 116, - false}, + 116}, {{ 0x25, 0xAE, 0xEC, 0x63, 0xF3, 0xCC, 0xD7, 0x3D, 0xD6, 0x1C, 0xB4, 0xFB, 0xBD, 0x13, 0x60, 0x37, 0x22, 0xE0, 0x2C, 0xB5, 0x4E, 0x03, 0x04, 0x77, 0x37, 0x08, 0x42, 0x11, 0x07, 0x1D, 0x78, 0x50, }, - 61, - true}, + 61}, {{ 0x25, 0xB4, 0x1B, 0x50, 0x6E, 0x49, 0x30, 0x95, 0x28, 0x23, 0xA6, 0xEB, 0x9F, 0x1D, 0x31, 0xDE, 0xF6, 0x45, 0xEA, 0x38, 0xA5, 0xC6, 0xC6, 0xA9, 0x6D, 0x71, 0x95, 0x7E, 0x38, 0x4D, 0xF0, 0x58, }, - 152, - false}, + 152}, {{ 0x25, 0xD4, 0x91, 0x3C, 0xF5, 0x87, 0x09, 0x74, 0x14, 0xD2, 0x9D, 0x26, 0xF6, 0xC1, 0xB1, 0x94, 0x2C, 0xD6, 0xD6, 0x4E, 0xAF, 0x45, 0xD0, 0xFC, 0xF8, 0x15, 0x26, 0xAD, 0xBA, 0x96, 0xD3, 0x24, }, - 59, - false}, + 59}, {{ 0x26, 0xC1, 0x8D, 0xC6, 0xEE, 0xA6, 0xF6, 0x32, 0xF6, 0x76, 0xBC, 0xEB, 0xA1, 0xD8, 0xC2, 0xB4, 0x83, 0x52, 0xF2, 0x9C, 0x2D, 0x5F, 0xCD, 0xA8, 0x78, 0xE0, 0x9D, 0xCB, 0x83, 0x2D, 0xD6, 0xE5, }, - 140, - true}, + 140}, {{ 0x27, 0x8A, 0x63, 0x91, 0xD3, 0xD3, 0x6B, 0x49, 0xAA, 0x40, 0x80, 0xF5, 0x6A, 0x36, 0xB3, 0xC1, 0x0F, 0xBA, 0x4E, 0x28, 0xAA, 0x6A, 0x95, 0x92, 0xA8, 0x2E, 0x75, 0x35, 0x11, 0x3A, 0x12, 0xD3, }, - 163, - true}, + 163}, {{ 0x28, 0x2F, 0xB5, 0xCF, 0xBA, 0xF0, 0x15, 0x18, 0xD9, 0x70, 0x4D, 0xE7, 0x88, 0x4D, 0x7A, 0x25, 0xFF, 0x01, 0xCF, 0x88, 0x2E, 0x99, 0x42, 0x90, 0xD5, 0x99, 0x5D, 0x5E, 0xB6, 0xC4, 0x49, 0x88, }, - 489, - true}, + 489}, {{ 0x28, 0x33, 0x10, 0x81, 0x9F, 0x5E, 0x09, 0x20, 0x49, 0x95, 0xD8, 0xAD, 0x9F, 0xF6, 0xFC, 0x10, 0x74, 0x62, 0x97, 0xB5, 0xC0, 0xAE, 0x06, 0xBD, 0xD1, 0xE1, 0x12, 0x4B, 0x10, 0xA0, 0xD7, 0xAD, }, - 343, - true}, + 343}, {{ 0x28, 0x96, 0xB4, 0xDD, 0xBE, 0x61, 0x45, 0x71, 0x83, 0xCC, 0x7E, 0xD2, 0x7B, 0xD7, 0x8A, 0xC5, 0x0A, 0x20, 0x7F, 0x69, 0x01, 0xC5, 0xC5, 0x2E, 0x53, 0xDC, 0x16, 0x76, 0xF9, 0xBB, 0x1E, 0x06, }, - 241, - true}, + 241}, {{ 0x29, 0xE7, 0xFD, 0xDA, 0x48, 0x9E, 0x46, 0xEE, 0x48, 0x6E, 0xFD, 0x75, 0xAC, 0xC4, 0x8F, 0x25, 0x19, 0x32, 0xDC, 0x9D, 0xA1, 0x87, 0x2B, 0x31, 0x75, 0x3C, 0xD6, 0x47, 0x19, 0x56, 0x7A, 0xA5, }, - 441, - true}, + 441}, {{ 0x2A, 0x29, 0x33, 0x7C, 0x3D, 0x62, 0x24, 0xCC, 0x53, 0xF0, 0xBB, 0x5E, 0x5D, 0x58, 0x20, 0xC0, 0xD8, 0x84, 0x8B, 0x04, 0x87, 0x13, 0x28, 0xF0, 0x90, 0xFE, 0xE3, 0xCD, 0x6B, 0xF8, 0x21, 0xB4, }, - 83, - true}, + 83}, {{ 0x2A, 0x42, 0x12, 0x60, 0x5A, 0xA3, 0xE8, 0xAE, 0xCB, 0x0F, 0xC1, 0x98, 0x06, 0xCF, 0x3B, 0x40, 0xB5, 0x3B, 0x95, 0xF1, 0xA3, 0x4D, 0xBB, 0xD6, 0xE3, 0xED, 0x27, 0x23, 0x03, 0x24, 0xAB, 0xB3, }, - 102, - false}, + 102}, {{ 0x2A, 0x4F, 0x49, 0xEE, 0x77, 0x01, 0xA3, 0x95, 0xAC, 0x93, 0x2E, 0x44, 0x42, 0x92, 0x67, 0x15, 0x88, 0xAD, 0xE2, 0x12, 0x59, 0xCE, 0x29, 0x6E, 0x19, 0x49, 0x40, 0x36, 0x87, 0x02, 0xEA, 0x7F, }, - 359, - true}, + 359}, {{ 0x2A, 0x8B, 0xED, 0x32, 0xAE, 0x68, 0x0D, 0x2D, 0x18, 0x7B, 0x9A, 0x7A, 0xFD, 0x17, 0x1D, 0x83, 0xFD, 0x0B, 0x93, 0x5E, 0xAF, 0x9E, 0x2C, 0x1B, 0x43, 0xE8, 0x02, 0x78, 0xD2, 0x06, 0x3E, 0x39, }, - 161, - true}, + 161}, {{ 0x2A, 0x8F, 0x2D, 0x8A, 0xF0, 0xEB, 0x12, 0x38, 0x98, 0xF7, 0x4C, 0x86, 0x6A, 0xC3, 0xFA, 0x66, 0x90, 0x54, 0xE2, 0x3C, 0x17, 0xBC, 0x7A, 0x95, 0xBD, 0x02, 0x34, 0x19, 0x2D, 0xC6, 0x35, 0xD0, }, - 113, - false}, + 113}, {{ 0x2B, 0x07, 0x1C, 0x59, 0xA0, 0xA0, 0xAE, 0x76, 0xB0, 0xEA, 0xDB, 0x2B, 0xAD, 0x23, 0xBA, 0xD4, 0x58, 0x0B, 0x69, 0xC3, 0x60, 0x1B, 0x63, 0x0C, 0x2E, 0xAF, 0x06, 0x13, 0xAF, 0xA8, 0x3F, 0x92, }, - 6, - false}, + 6}, {{ 0x2B, 0xB5, 0xC2, 0x8A, 0x34, 0xC9, 0xA3, 0x7D, 0xD9, 0x60, 0x45, 0x00, 0xCA, 0x9B, 0x30, 0x38, 0xD0, 0x05, 0x28, 0xB4, 0x74, 0x77, 0x3A, 0x27, 0x32, 0xAE, 0xA7, 0x9E, 0x49, 0x05, 0xC2, 0x34, }, - 311, - true}, + 311}, {{ 0x2B, 0xCE, 0xE8, 0x58, 0x15, 0x8C, 0xF5, 0x46, 0x5F, 0xC9, 0xD7, 0x6F, 0x0D, 0xFA, 0x31, 0x2F, 0xEF, 0x25, 0xA4, 0xDC, 0xA8, 0x50, 0x1D, 0xA9, 0xB4, 0x6B, 0x67, 0xD1, 0xFB, 0xFA, 0x1B, 0x64, }, - 109, - false}, + 109}, {{ 0x2D, 0x6D, 0x69, 0x0C, 0x16, 0xB1, 0x18, 0x53, 0x88, 0x4B, 0xBE, 0xA2, 0x72, 0x37, 0x25, 0x26, 0x7E, 0x3F, 0x9B, 0x54, 0xA6, 0xCF, 0x07, 0xAD, 0x46, 0x90, 0xAB, 0x1E, 0x7C, 0xFB, 0x75, 0xE8, }, - 438, - true}, + 438}, {{ 0x2D, 0xA8, 0xF9, 0xEA, 0x34, 0x54, 0xD2, 0x11, 0x46, 0x46, 0x4A, 0x3F, 0x9D, 0x02, 0x8D, 0xC4, 0xC7, 0xFB, 0xB5, 0x7B, 0x1C, 0x52, 0xC7, 0x3C, 0x2B, 0x05, 0x72, 0xA2, 0xF5, 0x99, 0xA2, 0xD3, }, - 269, - true}, + 269}, {{ 0x2D, 0xC9, 0x47, 0x0B, 0xE6, 0x3E, 0xF4, 0xAC, 0xF1, 0xBD, 0x82, 0x86, 0x09, 0x40, 0x2B, 0xB7, 0xB8, 0x7B, 0xD9, 0x96, 0x38, 0xA6, 0x43, 0x93, 0x4E, 0x88, 0x68, 0x2D, 0x1B, 0xE8, 0xC3, 0x08, }, - 248, - true}, + 248}, {{ 0x2D, 0xEE, 0x51, 0x71, 0x59, 0x6A, 0xB8, 0xF3, 0xCD, 0x3C, 0x76, 0x35, 0xFE, 0xA8, 0xE6, 0xC3, 0x00, 0x6A, 0xA9, 0xE3, 0x1D, 0xB3, 0x9D, 0x03, 0xA7, 0x48, 0x0D, 0xDB, 0x24, 0x28, 0xA3, 0x3E, }, - 264, - true}, + 264}, {{ 0x2E, 0x00, 0x91, 0x5A, 0x9F, 0x7B, 0xE0, 0x6A, 0xB2, 0x37, 0x0C, 0x7B, 0x7C, 0x20, 0x0C, 0x0A, 0x96, 0xD5, 0xAC, 0x6A, 0x50, 0xCE, 0x18, 0x74, 0xDB, 0xEF, 0xDE, 0x40, 0x22, 0xD4, 0xDE, 0x8E, }, - 272, - true}, + 272}, {{ 0x2E, 0x06, 0xCA, 0xE1, 0xFC, 0x20, 0xB2, 0x00, 0xE6, 0xFB, 0x74, 0x85, 0x57, 0xA4, 0x44, 0x4B, 0xEC, 0x93, 0x17, 0xDF, 0xFF, 0x2E, 0x41, 0x51, 0x66, 0x9E, 0x0F, 0x79, 0x44, 0xF0, 0xA9, 0xE0, }, - 513, - true}, + 513}, {{ 0x2F, 0xC5, 0x66, 0x7A, 0x4B, 0x9A, 0x26, 0x78, 0xED, 0x6A, 0xC6, 0xAD, 0x25, 0x46, 0x5F, 0xCB, 0xF6, 0x09, 0x4B, 0xFC, 0xD9, 0x50, 0x40, 0x97, 0xC7, 0xA8, 0xFA, 0x47, 0xAD, 0xE5, 0xE8, 0x88, }, - 206, - false}, + 206}, {{ 0x2F, 0xCC, 0x99, 0xF5, 0xC9, 0xD0, 0x0F, 0x9A, 0x20, 0xDA, 0x61, 0x31, 0xDE, 0xA5, 0xC0, 0x27, 0xD9, 0x26, 0x36, 0xD6, 0x8C, 0xD9, 0xCD, 0xBE, 0x95, 0x29, 0x0A, 0x3C, 0x40, 0x89, 0x19, 0xE0, }, - 427, - true}, + 427}, {{ 0x30, 0x27, 0xA2, 0x98, 0xFA, 0x57, 0x31, 0x4D, 0xC0, 0xE3, 0xDD, 0x10, 0x19, 0x41, 0x1B, 0x8F, 0x40, 0x4C, 0x43, 0xC3, 0xF9, 0x34, 0xCE, 0x3B, 0xDF, 0x85, 0x65, 0x12, 0xC8, 0x0A, 0xA1, 0x5C, }, - 256, - true}, + 256}, {{ 0x30, 0x9F, 0x13, 0xD4, 0x9E, 0xA6, 0x6F, 0x52, 0x32, 0x41, 0xB5, 0x55, 0x24, 0x74, 0x44, 0x64, 0xE2, 0x8C, 0xC1, 0xB8, 0x2E, 0xF7, 0x9B, 0x64, 0xE4, 0xD5, 0x81, 0x88, 0x0D, 0xCD, 0x77, 0x1F, }, - 237, - true}, + 237}, {{ 0x30, 0xAB, 0x1B, 0xCD, 0x7B, 0xED, 0x1F, 0xF2, 0x67, 0x9F, 0x71, 0x22, 0x88, 0x20, 0x42, 0x0A, 0x70, 0x63, 0xC6, 0xCE, 0xAD, 0x7E, 0xC3, 0x0D, 0x4A, 0x01, 0x61, 0x54, 0x87, 0x6D, 0xDD, 0xB5, }, - 280, - true}, + 280}, {{ 0x30, 0xB7, 0x1C, 0x4F, 0x91, 0x22, 0x47, 0x6E, 0x76, 0x1E, 0x62, 0x0E, 0xEC, 0x42, 0xBF, 0xA5, 0xF8, 0x4C, 0x49, 0x3C, 0xD4, 0x9B, 0xBB, 0x18, 0x34, 0xB2, 0x6E, 0x55, 0x5F, 0x60, 0xDE, 0x40, }, - 360, - true}, + 360}, {{ 0x31, 0x51, 0x26, 0x80, 0x23, 0x3F, 0x5F, 0x2A, 0x1F, 0x29, 0x43, 0x7F, 0x56, 0xD4, 0x98, 0x8C, 0xF0, 0xAF, 0xC4, 0x1C, 0xC6, 0xC5, 0xDA, 0x62, 0x75, 0x92, 0x8E, 0x9C, 0x0B, 0xEA, 0xDE, 0x27, }, - 254, - true}, + 254}, {{ 0x31, 0xDE, 0x0C, 0xB1, 0x9F, 0x2A, 0xDB, 0xB0, 0xD1, 0xCD, 0x7B, 0x1B, 0x31, 0xEF, 0x8E, 0xE3, 0xEB, 0x59, 0xB7, 0x44, 0x59, 0xAE, 0xF9, 0x4B, 0x48, 0x0B, 0xEE, 0xEE, 0xB8, 0x5C, 0x64, 0xC9, }, - 147, - true}, + 147}, {{ 0x32, 0x19, 0xB0, 0x91, 0x14, 0xFF, 0x49, 0x5A, 0x3E, 0xB6, 0xEB, 0x00, 0xC2, 0xEF, 0xEA, 0xB3, 0x40, 0x02, 0xAE, 0x5F, 0x0A, 0x56, 0xC7, 0x67, 0x9E, 0xA0, 0x87, 0xA3, 0xFA, 0x03, 0x7E, 0x4F, }, - 125, - false}, + 125}, {{ 0x32, 0xD1, 0x80, 0xED, 0x31, 0xC9, 0x35, 0x58, 0x9E, 0xC9, 0xDB, 0xBB, 0x72, 0x21, 0x23, 0xB8, 0x83, 0xB5, 0xFC, 0x2D, 0xC1, 0x0F, 0x9F, 0xCA, 0x3A, 0x95, 0xD7, 0x7E, 0x1B, 0xFC, 0xB5, 0x34, }, - 27, - false}, + 27}, {{ 0x33, 0x29, 0xBF, 0xA1, 0x3B, 0x60, 0x07, 0xAB, 0x5F, 0xC3, 0x71, 0x3F, 0x0A, 0xCB, 0x28, 0x94, 0x26, 0xE2, 0xFB, 0xC9, 0x9C, 0xC5, 0xC1, 0x10, 0xA9, 0x14, 0xB1, 0x39, 0x57, 0x16, 0x00, 0xB6, }, - 471, - true}, + 471}, {{ 0x33, 0x80, 0x70, 0x9A, 0xF3, 0xB0, 0x96, 0xBE, 0x3C, 0xC2, 0xA4, 0x05, 0x48, 0x14, 0x2C, 0x0A, 0x52, 0x00, 0x28, 0xDB, 0x09, 0xE2, 0xCB, 0x77, 0xAE, 0x22, 0x06, 0x61, 0x6A, 0xB6, 0xCB, 0xB4, }, - 130, - false}, + 130}, {{ 0x33, 0xAF, 0x58, 0xB5, 0x58, 0x9E, 0xCE, 0xA7, 0x92, 0x62, 0x52, 0x47, 0x78, 0x38, 0xBA, 0x40, 0x24, 0x7A, 0xB3, 0x7B, 0x6F, 0xB3, 0x9E, 0x34, 0xFC, 0xBD, 0x55, 0x2C, 0xD5, 0xA8, 0xC6, 0x6D, }, - 233, - true}, + 233}, {{ 0x33, 0xFA, 0x5A, 0x53, 0x00, 0x61, 0x3D, 0x46, 0x6E, 0x6F, 0x85, 0xC8, 0x05, 0x16, 0x95, 0xBE, 0xD5, 0xD1, 0xFA, 0xD5, 0x9F, 0x25, 0xE0, 0x40, 0xAC, 0xDA, 0x04, 0x72, 0xA7, 0x4F, 0x3C, 0x20, }, - 458, - true}, + 458}, {{ 0x34, 0x87, 0x67, 0xCD, 0xAD, 0x3B, 0xDD, 0x28, 0xB2, 0xB8, 0xDD, 0x53, 0x51, 0xAE, 0xC3, 0x0C, 0x68, 0xCE, 0xC5, 0xCD, 0x69, 0xD2, 0x76, 0xDF, 0x38, 0x27, 0xDB, 0xC4, 0xF5, 0x80, 0x64, 0x64, }, - 295, - false}, + 295}, {{ 0x34, 0x99, 0xF9, 0x3F, 0xD3, 0x94, 0x52, 0x3B, 0xFB, 0x1E, 0xC4, 0xC3, 0xAD, 0x4D, 0xFB, 0x31, 0x01, 0x31, 0xFB, 0xE9, 0xEE, 0x54, 0x76, 0xBD, 0xE6, 0x29, 0x5D, 0xE8, 0x08, 0xD5, 0xDD, 0x8F, }, - 138, - true}, + 138}, {{ 0x35, 0x51, 0xDE, 0x58, 0xA7, 0xD7, 0x9C, 0xD9, 0x80, 0x28, 0x3D, 0xF8, 0x17, 0x90, 0xD6, 0x3A, 0x98, 0x2C, 0x1A, 0x63, 0xB3, 0x04, 0x82, 0xEC, 0x58, 0x21, 0xDB, 0x76, 0x61, 0x55, 0x4E, 0xF9, }, - 150, - true}, + 150}, {{ 0x35, 0xF5, 0x3C, 0xE1, 0x26, 0x46, 0x11, 0xE0, 0x33, 0x40, 0xFE, 0x37, 0xE1, 0xEC, 0x7D, 0x4C, 0xC9, 0x86, 0xC5, 0x61, 0x3D, 0xCA, 0x70, 0xFD, 0x04, 0xAA, 0x44, 0x54, 0x5F, 0x2D, 0xAF, 0x28, }, - 508, - true}, + 508}, {{ 0x36, 0xAB, 0xC3, 0x26, 0x56, 0xAC, 0xFC, 0x64, 0x5C, 0x61, 0xB7, 0x16, 0x13, 0xC4, 0xBF, 0x21, 0xC7, 0x87, 0xF5, 0xCA, 0xBB, 0xEE, 0x48, 0x34, 0x8D, 0x58, 0x59, 0x78, 0x03, 0xD7, 0xAB, 0xC9, }, - 205, - false}, + 205}, {{ 0x36, 0xC2, 0x23, 0x14, 0x13, 0x1A, 0x5F, 0xBF, 0x1B, 0x70, 0xEA, 0x4C, 0xCF, 0x4B, 0xC1, 0x3A, 0x77, 0x7D, 0x93, 0x8E, 0xC6, 0x5E, 0x1D, 0xA2, 0x4E, 0x3C, 0x2C, 0xFD, 0x01, 0xD3, 0xD1, 0x63, }, - 94, - false}, + 94}, {{ 0x36, 0xD7, 0xC7, 0x9F, 0x3D, 0x08, 0x9A, 0x0F, 0xF7, 0x99, 0x72, 0xD9, 0x09, 0x23, 0xDE, 0xA5, 0xCA, 0x76, 0xB4, 0xCC, 0xBA, 0xF7, 0xC2, 0x75, 0x1C, 0xB1, 0x52, 0xE9, 0x49, 0x4F, 0x52, 0xD0, }, - 500, - true}, + 500}, {{ 0x36, 0xEC, 0xC6, 0x1F, 0xC7, 0xE5, 0xF1, 0x92, 0x3D, 0x16, 0x7E, 0x67, 0xDF, 0xDE, 0x34, 0x60, 0x85, 0x49, 0xB3, 0x4A, 0x63, 0xC7, 0xC6, 0xE6, 0x0F, 0xFD, 0x5C, 0x18, 0x40, 0x38, 0x1F, 0x5C, }, - 74, - true}, + 74}, {{ 0x37, 0x6A, 0x1A, 0x70, 0x82, 0xA5, 0x93, 0xDC, 0xCC, 0x20, 0xD5, 0x61, 0xD1, 0x19, 0xE9, 0xAB, 0x8D, 0x30, 0xF1, 0x1C, 0xC3, 0x21, 0xD0, 0xA3, 0x7F, 0xA4, 0x1F, 0x0D, 0xF2, 0x84, 0xE0, 0x1C, }, - 494, - false}, + 494}, {{ 0x38, 0x07, 0x39, 0x62, 0x0E, 0x13, 0x33, 0x58, 0x05, 0xEA, 0xDA, 0x8F, 0x9F, 0x8B, 0x81, 0x55, 0x4D, 0x3B, 0xD3, 0xC0, 0x01, 0x7F, 0x36, 0x32, 0xC2, 0x67, 0x76, 0x69, 0xCA, 0xC7, 0xA2, 0xBF, }, - 459, - true}, + 459}, {{ 0x38, 0x1A, 0x3F, 0xC7, 0xA8, 0xB0, 0x82, 0xFA, 0x28, 0x61, 0x3A, 0x4D, 0x07, 0xF2, 0xC7, 0x55, 0x3F, 0x4E, 0x19, 0x18, 0xEE, 0x07, 0xCA, 0xA9, 0xE8, 0xB7, 0xCE, 0xDE, 0x5A, 0x9C, 0xA0, 0x6A, }, - 192, - true}, + 192}, {{ 0x38, 0x61, 0xD7, 0xB6, 0x96, 0x1F, 0xCD, 0xB2, 0x12, 0x04, 0x56, 0xFF, 0x6F, 0xC2, 0xEB, 0x77, 0x04, 0xB1, 0xA7, 0x41, 0xB4, 0xBD, 0x93, 0x3A, 0x83, 0x76, 0xF5, 0xE1, 0x91, 0x5C, 0xA6, 0x98, }, - 101, - true}, + 101}, {{ 0x3A, 0x0D, 0x88, 0x5C, 0xB3, 0x46, 0xD8, 0xF0, 0x1F, 0xD3, 0x00, 0xAF, 0x15, 0x46, 0xF6, 0x35, 0x5C, 0x00, 0x69, 0x0E, 0x34, 0x0E, 0xD9, 0x8F, 0x34, 0x6E, 0x77, 0xB5, 0x74, 0xBE, 0x3F, 0xD8, }, - 303, - true}, + 303}, {{ 0x3A, 0x6C, 0x24, 0xE8, 0x0F, 0x68, 0x1D, 0x8B, 0x10, 0x47, 0xCE, 0xC0, 0x51, 0xC2, 0x75, 0x94, 0xF8, 0x85, 0xBA, 0x08, 0x87, 0xA2, 0x63, 0x79, 0x09, 0x2D, 0xFE, 0xF5, 0x06, 0x16, 0x0E, 0x9B, }, - 279, - true}, + 279}, {{ 0x3A, 0x80, 0x3E, 0x7C, 0x0A, 0x43, 0xA2, 0x9F, 0xD7, 0x36, 0x72, 0xE3, 0xD0, 0xBB, 0x2C, 0x36, 0x53, 0xD9, 0x48, 0xED, 0xE0, 0xB3, 0xCB, 0x1D, 0xB4, 0xCE, 0x75, 0xA8, 0x57, 0xE8, 0x9A, 0xF1, }, - 143, - true}, + 143}, {{ 0x3B, 0x0D, 0x73, 0xB4, 0xBE, 0x4A, 0x85, 0x4A, 0xDC, 0x3E, 0x51, 0xD7, 0xEF, 0x9F, 0xA4, 0x8A, 0xEF, 0xBB, 0x2C, 0xDD, 0x82, 0x4D, 0x67, 0xBD, 0xC7, 0xD7, 0xD0, 0x9A, 0x2A, 0xBC, 0x2D, 0x43, }, - 128, - false}, + 128}, {{ 0x3B, 0x45, 0x91, 0x82, 0x05, 0xC5, 0x91, 0x29, 0x8A, 0x19, 0x22, 0xA5, 0x8B, 0x49, 0x21, 0xD0, 0x1F, 0x64, 0x8F, 0xA9, 0xD2, 0x8B, 0xDD, 0xDF, 0xAD, 0x24, 0xAE, 0xEC, 0x59, 0x42, 0xCF, 0xBF, }, - 14, - true}, + 14}, {{ 0x3B, 0xDE, 0x97, 0x68, 0x6E, 0x3A, 0xF5, 0x1D, 0x3F, 0x57, 0x2C, 0x48, 0x88, 0xC1, 0x2B, 0xD1, 0xD1, 0xE0, 0x97, 0xF1, 0x2F, 0x49, 0xEC, 0x3C, 0x92, 0x89, 0x65, 0x51, 0xE3, 0x6F, 0x00, 0x85, }, - 245, - true}, + 245}, {{ 0x3C, 0x19, 0x6F, 0x84, 0xE2, 0xA0, 0xC6, 0x1F, 0xEC, 0x18, 0xBA, 0xCA, 0xBD, 0x31, 0x78, 0x3B, 0x57, 0x45, 0x17, 0xAA, 0xD8, 0xEB, 0xC6, 0xCE, 0x6D, 0x1D, 0x7D, 0xC8, 0x2B, 0x3C, 0x50, 0xDF, }, - 318, - true}, + 318}, {{ 0x3C, 0x35, 0xE1, 0x64, 0xBE, 0xDD, 0x2C, 0xF1, 0x2B, 0xEB, 0x83, 0xEC, 0xFF, 0x78, 0xB5, 0xE8, 0x0D, 0xA8, 0x15, 0x8D, 0x28, 0x30, 0x21, 0x7E, 0x4E, 0xBF, 0xFC, 0xE8, 0x92, 0x88, 0x99, 0xA6, }, - 13, - true}, + 13}, {{ 0x3C, 0x84, 0xD9, 0x96, 0x72, 0x2B, 0x3C, 0x18, 0x72, 0xF5, 0x3D, 0xDD, 0x77, 0x17, 0xBB, 0x2F, 0xA5, 0x0E, 0xBF, 0xA0, 0x7B, 0x3F, 0x3B, 0x4A, 0x39, 0x53, 0x35, 0xC5, 0x67, 0x12, 0xFD, 0x69, }, - 315, - true}, + 315}, {{ 0x3D, 0x8D, 0x06, 0x1E, 0xDC, 0xF7, 0xB3, 0xD4, 0x59, 0x95, 0xBA, 0x43, 0x41, 0x32, 0x8D, 0x1B, 0xE7, 0xB7, 0xEB, 0x4E, 0x9D, 0x14, 0xFE, 0xE7, 0x0D, 0x2F, 0x18, 0xAD, 0x68, 0xBE, 0xA7, 0xC5, }, - 436, - true}, + 436}, {{ 0x3E, 0xA7, 0xB5, 0xC0, 0x45, 0xA9, 0x9A, 0x97, 0x71, 0xE2, 0xDE, 0xA8, 0xE8, 0x09, 0x8B, 0xA2, 0x73, 0x2D, 0x17, 0xCE, 0xEE, 0x82, 0x27, 0x95, 0x52, 0xFE, 0xEE, 0x90, 0x55, 0x30, 0xF3, 0x5F, }, - 420, - true}, + 420}, {{ 0x3E, 0xC1, 0x8D, 0xFE, 0xB8, 0x94, 0xA9, 0xEA, 0x20, 0xEB, 0x2C, 0xD4, 0x0C, 0x69, 0x3E, 0x2A, 0x29, 0x14, 0x4F, 0xE2, 0xEC, 0x60, 0xB4, 0xF7, 0xB8, 0x90, 0x26, 0x04, 0x0B, 0x39, 0xAE, 0xBE, }, - 461, - true}, + 461}, {{ 0x3E, 0xE6, 0xB3, 0x41, 0x40, 0x28, 0x51, 0xB2, 0x7E, 0x64, 0x02, 0x1A, 0x30, 0x23, 0xAA, 0xC7, 0xC1, 0xA0, 0xD2, 0xDE, 0xF2, 0x7D, 0x5B, 0xCE, 0x5C, 0x2D, 0xBE, 0xB0, 0xB2, 0x2D, 0xCC, 0x71, }, - 481, - true}, + 481}, {{ 0x3F, 0xAB, 0x78, 0x4F, 0xC3, 0xC9, 0xAB, 0x9E, 0xED, 0xC1, 0x2E, 0xCD, 0xC0, 0xDB, 0x55, 0x0F, 0x4C, 0x3D, 0xBF, 0xD3, 0xE8, 0x6D, 0x78, 0x81, 0x53, 0x33, 0xC5, 0xEB, 0xA5, 0x18, 0xCB, 0x9D, }, - 225, - true}, + 225}, {{ 0x3F, 0xB6, 0x3C, 0x29, 0xF4, 0x7B, 0xCC, 0x4E, 0x6A, 0xAD, 0xB3, 0x57, 0x7C, 0xE7, 0xCA, 0x85, 0x43, 0xE0, 0xBB, 0xAB, 0xA5, 0x53, 0x67, 0x6B, 0x8F, 0xD1, 0x61, 0x29, 0x5B, 0xDB, 0x90, 0x11, }, - 368, - true}, + 368}, {{ 0x40, 0x02, 0xFC, 0xD3, 0x11, 0xD0, 0x73, 0x31, 0x56, 0x7E, 0x71, 0xBC, 0xD9, 0x71, 0xE4, 0x60, 0x48, 0xC8, 0xDC, 0xE8, 0xD1, 0x65, 0x97, 0x11, 0x75, 0x3B, 0x3D, 0xAA, 0x2A, 0x26, 0x9A, 0xFA, }, - 47, - true}, + 47}, {{ 0x40, 0xFC, 0xFC, 0x28, 0x87, 0x5D, 0xCC, 0xBF, 0xEB, 0xCB, 0xDF, 0x6C, 0xD7, 0x43, 0x33, 0x12, 0xDA, 0x63, 0xC4, 0xEF, 0xCF, 0x3B, 0xD7, 0xB1, 0xB5, 0x05, 0xC2, 0x20, 0x20, 0xAE, 0x02, 0x74, }, - 35, - false}, + 35}, {{ 0x41, 0x79, 0xED, 0xD9, 0x81, 0xEF, 0x74, 0x74, 0x77, 0xB4, 0x96, 0x26, 0x40, 0x8A, 0xF4, 0x3D, 0xAA, 0x2C, 0xA7, 0xAB, 0x7F, 0x9E, 0x08, 0x2C, 0x10, 0x60, 0xF8, 0x40, 0x96, 0x77, 0x43, 0x48, }, - 485, - false}, + 485}, {{ 0x42, 0x23, 0x89, 0x40, 0x03, 0xA8, 0x81, 0xC5, 0xDF, 0x6B, 0xAB, 0x16, 0x3D, 0xB2, 0x35, 0xC2, 0x21, 0xA1, 0x8D, 0x54, 0xBF, 0x75, 0x99, 0x45, 0x82, 0x0E, 0x67, 0x0D, 0xA8, 0x2E, 0x3F, 0x39, }, - 187, - false}, + 187}, {{ 0x42, 0x43, 0x16, 0x27, 0xEA, 0x76, 0xCC, 0x78, 0x69, 0x7F, 0x91, 0x5E, 0x34, 0x55, 0xB1, 0xB2, 0xEC, 0x82, 0xFF, 0x2F, 0x63, 0x80, 0xEE, 0x64, 0x23, 0xEF, 0x3C, 0x08, 0x40, 0xB7, 0xE6, 0x31, }, - 521, - false}, + 521}, {{ 0x42, 0xA7, 0x09, 0x84, 0xFF, 0xD3, 0x99, 0xC4, 0xEA, 0xF0, 0xE7, 0x02, 0xA4, 0x4B, 0xEF, 0x2A, 0xD8, 0xA7, 0x9B, 0x8B, 0xF4, 0x64, 0x8F, 0x6B, 0xB2, 0x10, 0xE1, 0x23, 0xFD, 0x07, 0x57, 0x93, }, - 409, - true}, + 409}, {{ 0x42, 0xA8, 0x07, 0xCE, 0xC5, 0xAE, 0x9C, 0x0F, 0x03, 0xB4, 0x0C, 0xA0, 0x43, 0xAC, 0x70, 0x46, 0x8B, 0x52, 0x19, 0xBD, 0x75, 0xCC, 0x5B, 0xBE, 0xA5, 0x1D, 0x92, 0x1D, 0xD1, 0x00, 0x15, 0x6F, }, - 466, - true}, + 466}, {{ 0x43, 0x1B, 0x79, 0xFD, 0x93, 0x55, 0xD1, 0x0D, 0xC1, 0xB5, 0x0D, 0xBF, 0x6A, 0x6B, 0x62, 0xD7, 0xA5, 0xB6, 0xD3, 0x56, 0x54, 0x1C, 0x27, 0x60, 0x52, 0x55, 0xCA, 0x4C, 0xA7, 0x94, 0x20, 0xC1, }, - 340, - true}, + 340}, {{ 0x43, 0x76, 0xA9, 0x93, 0x96, 0x76, 0x9F, 0xD4, 0x87, 0x24, 0x0E, 0xE8, 0xB5, 0x73, 0xAD, 0x49, 0x70, 0x6A, 0x5B, 0x94, 0x73, 0x61, 0x6A, 0xCE, 0xF3, 0x84, 0x09, 0xE9, 0x15, 0x86, 0xDC, 0x1E, }, - 444, - true}, + 444}, {{ 0x43, 0x9C, 0x19, 0xFF, 0x3E, 0xDB, 0x26, 0x5E, 0xF1, 0xA9, 0x20, 0xF7, 0x4A, 0x48, 0x02, 0xD3, 0xDD, 0x95, 0xAC, 0xE0, 0x24, 0xE2, 0x1E, 0x5A, 0x6C, 0xE8, 0xE0, 0x64, 0xDC, 0x15, 0x66, 0xCD, }, - 447, - true}, + 447}, {{ 0x43, 0xC7, 0x42, 0x62, 0xF7, 0x49, 0x26, 0x62, 0xD2, 0x45, 0x9B, 0xCC, 0x98, 0x99, 0xBA, 0xC5, 0x4A, 0x4E, 0xCC, 0x01, 0xE1, 0xA3, 0xF5, 0xE7, 0x65, 0x58, 0x99, 0x2B, 0x40, 0x15, 0x24, 0x18, }, - 414, - true}, + 414}, {{ 0x43, 0xCF, 0xFC, 0x35, 0x9F, 0x2E, 0x8C, 0xAA, 0x57, 0x38, 0x8E, 0xE9, 0xF6, 0xF1, 0xDB, 0xE9, 0x3B, 0xF0, 0x93, 0x68, 0x2A, 0x69, 0x9A, 0xC3, 0x85, 0x2E, 0x6D, 0x1F, 0x85, 0x79, 0xE7, 0xF9, }, - 56, - true}, + 56}, {{ 0x44, 0x62, 0xC1, 0x07, 0xC4, 0x85, 0xDD, 0x6A, 0x54, 0x43, 0xF5, 0xE7, 0xA1, 0x60, 0x44, 0x16, 0x03, 0x4A, 0x37, 0x4C, 0x3F, 0x4D, 0x10, 0x87, 0x5F, 0x1C, 0x37, 0x15, 0x02, 0x75, 0x63, 0xAF, }, - 156, - true}, + 156}, {{ 0x44, 0xA3, 0xD8, 0x0D, 0x3F, 0x53, 0x48, 0x59, 0x6D, 0x80, 0xA0, 0x98, 0x42, 0xC2, 0x3A, 0x39, 0x77, 0x44, 0x39, 0xF8, 0xB0, 0xB9, 0x19, 0x23, 0x9D, 0x2A, 0x03, 0xDA, 0xC5, 0xCE, 0x52, 0x13, }, - 403, - true}, + 403}, {{ 0x44, 0xAF, 0x8A, 0xFC, 0xF1, 0x39, 0x5D, 0x2A, 0x8E, 0x30, 0xEF, 0x81, 0x2C, 0xE1, 0x9C, 0xEB, 0x2E, 0x89, 0x48, 0xDF, 0xD2, 0x1E, 0x00, 0xFB, 0xAA, 0x34, 0x68, 0x9F, 0x9A, 0x24, 0x72, 0x1F, }, - 51, - true}, + 51}, {{ 0x45, 0x3B, 0x74, 0x80, 0x9B, 0x69, 0x01, 0x96, 0x27, 0xF2, 0xF8, 0x43, 0x00, 0x1D, 0xB5, 0x95, 0x0C, 0xDD, 0x1D, 0x45, 0x37, 0x10, 0x53, 0xE7, 0xF3, 0xDF, 0xDB, 0xC3, 0x71, 0x41, 0x13, 0xC6, }, - 518, - true}, + 518}, {{ 0x46, 0x3D, 0xBB, 0x9B, 0x0A, 0x26, 0xED, 0x26, 0x16, 0x39, 0x7B, 0x64, 0x31, 0x25, 0xFB, 0xD2, 0x9B, 0x66, 0xCF, 0x3A, 0x46, 0xFD, 0xB4, 0x38, 0x4B, 0x20, 0x9E, 0x78, 0x23, 0x7A, 0x1A, 0xFF, }, - 353, - true}, + 353}, {{ 0x46, 0x91, 0xCB, 0xFD, 0xE8, 0x4A, 0x6B, 0x60, 0x52, 0xDD, 0xBE, 0x15, 0x2B, 0xB0, 0xC2, 0x16, 0xAE, 0x25, 0xA8, 0x6E, 0x57, 0x47, 0x81, 0x3D, 0xBC, 0x0F, 0x14, 0x7F, 0x33, 0x85, 0x70, 0xBE, }, - 2, - true}, + 2}, {{ 0x46, 0x97, 0xA5, 0xAB, 0xEA, 0x00, 0x70, 0xA3, 0x95, 0x45, 0x6F, 0xD3, 0x58, 0xE9, 0x1F, 0x72, 0xF2, 0x27, 0xD5, 0x85, 0x09, 0x33, 0x22, 0x7F, 0x1E, 0x0B, 0xC7, 0x9F, 0xF8, 0x47, 0xBF, 0xAC, }, - 352, - true}, + 352}, {{ 0x47, 0x9D, 0x13, 0x0B, 0xF3, 0xFC, 0x61, 0xDC, 0x2F, 0x1D, 0x50, 0x8D, 0x23, 0x9A, 0x13, 0x27, 0x6A, 0xE7, 0xB3, 0xC9, 0x84, 0x10, 0x11, 0xA0, 0x2C, 0x14, 0x02, 0xC7, 0xE6, 0x77, 0xBD, 0x5F, }, - 263, - true}, + 263}, {{ 0x47, 0xC7, 0xA1, 0x49, 0xCA, 0x82, 0xFA, 0x7B, 0xA9, 0x40, 0xA4, 0xD7, 0x11, 0xD0, 0x10, 0x62, 0x5C, 0x6C, 0xB0, 0xB7, 0x48, 0xB1, 0x70, 0x16, 0xC4, 0x6E, 0x25, 0xCE, 0x7A, 0xCD, 0x2B, 0x0C, }, - 266, - true}, + 266}, {{ 0x48, 0x2F, 0x76, 0xA2, 0xA9, 0x34, 0x6D, 0xBB, 0x07, 0x76, 0x19, 0xBB, 0xE1, 0xEF, 0xEC, 0xD5, 0x41, 0x07, 0xE9, 0x92, 0xFF, 0x4E, 0x8F, 0x4D, 0x70, 0xA3, 0x9E, 0x24, 0x05, 0xD9, 0x39, 0xD4, }, - 278, - true}, + 278}, {{ 0x48, 0xA8, 0xA7, 0xEC, 0xD0, 0x3A, 0x83, 0xB2, 0x6A, 0xEC, 0x75, 0x74, 0xD0, 0x9D, 0x64, 0x53, 0xE9, 0x5F, 0x90, 0x36, 0x06, 0x34, 0xCE, 0x20, 0x4B, 0xCB, 0xD4, 0x73, 0x99, 0x7D, 0x4C, 0x05, }, - 532, - false}, + 532}, {{ 0x49, 0x05, 0x46, 0x66, 0x23, 0xAB, 0x41, 0x78, 0xBE, 0x92, 0xAC, 0x5C, 0xBD, 0x65, 0x84, 0xF7, 0xA1, 0xE1, 0x7F, 0x27, 0x65, 0x2D, 0x5A, 0x85, 0xAF, 0x89, 0x50, 0x4E, 0xA2, 0x39, 0xAA, 0xAA, }, - 95, - false}, + 95}, {{ 0x49, 0x5A, 0x96, 0xBA, 0x6B, 0xAD, 0x78, 0x24, 0x07, 0xBD, 0x52, 0x1A, 0x00, 0xBA, 0xCE, 0x65, 0x7B, 0xB3, 0x55, 0x55, 0x5E, 0x4B, 0xB7, 0xF8, 0x14, 0x6C, 0x71, 0xBB, 0xA5, 0x7E, 0x7A, 0xCE, }, - 79, - false}, + 79}, {{ 0x49, 0x71, 0x28, 0xFC, 0x90, 0x65, 0x6B, 0x87, 0x29, 0x04, 0x82, 0xB2, 0x23, 0xEF, 0xB7, 0x22, 0x40, 0xFE, 0x9C, 0x42, 0x1E, 0x79, 0x93, 0x8D, 0xE5, 0xF8, 0x11, 0x0C, 0xB0, 0xBE, 0x90, 0x56, }, - 512, - true}, + 512}, {{ 0x49, 0x8B, 0xC0, 0xCD, 0x5A, 0x49, 0xB7, 0x14, 0x07, 0x1E, 0xC7, 0x6A, 0x41, 0x66, 0x1C, 0xE2, 0xF2, 0x7F, 0xC3, 0x9F, 0xE4, 0x16, 0x8B, 0xC7, 0xB7, 0x79, 0x9A, 0x0A, 0xE2, 0x5F, 0x65, 0x28, }, - 332, - true}, + 332}, {{ 0x49, 0xB8, 0x06, 0x85, 0xD3, 0x32, 0xE0, 0x72, 0xC0, 0xE7, 0xB7, 0x20, 0x03, 0x26, 0x47, 0xE8, 0x42, 0x10, 0x61, 0x04, 0xE0, 0xB1, 0x13, 0x9A, 0xB9, 0xE8, 0x11, 0xBF, 0xB1, 0x1E, 0xC0, 0x34, }, - 285, - true}, + 285}, {{ 0x49, 0xCB, 0xD8, 0x3C, 0x03, 0xCA, 0xBF, 0xA0, 0x71, 0x3B, 0x97, 0xBC, 0x96, 0x48, 0x1D, 0x03, 0x5F, 0xD4, 0xEB, 0xE0, 0x6F, 0x07, 0xFA, 0xB5, 0x64, 0x0E, 0xD9, 0x23, 0x2D, 0x81, 0x10, 0xB2, }, - 457, - true}, + 457}, {{ 0x4A, 0x26, 0x59, 0x66, 0x6D, 0xC0, 0x20, 0x3B, 0x91, 0x6F, 0x53, 0xD8, 0x0A, 0xD8, 0xF6, 0x1A, 0xC3, 0x0B, 0xEA, 0x16, 0x1F, 0x48, 0x5C, 0xC7, 0x52, 0x7E, 0x6A, 0x59, 0x37, 0xE4, 0x92, 0x16, }, - 188, - true}, + 188}, {{ 0x4A, 0x49, 0xED, 0xBD, 0x2F, 0x8F, 0x82, 0x30, 0xBD, 0x55, 0x92, 0xB3, 0x13, 0x57, 0x3F, 0xE1, 0xC1, 0x72, 0xA4, 0x5F, 0xA9, 0x80, 0x11, 0xCC, 0x1E, 0xDD, 0xBB, 0x36, 0xAD, 0xE3, 0xFC, 0xE5, }, - 169, - false}, + 169}, {{ 0x4B, 0x72, 0xDF, 0xED, 0x3E, 0xDC, 0xCB, 0x5F, 0x49, 0x45, 0x68, 0x2E, 0x29, 0x57, 0x31, 0xA0, 0x86, 0x4A, 0xC6, 0xB5, 0xB8, 0x5B, 0x19, 0x3E, 0xCD, 0x2F, 0x06, 0xB4, 0x90, 0x0C, 0x1C, 0xFD, }, - 184, - true}, + 184}, {{ 0x4B, 0xA2, 0x49, 0x96, 0xDD, 0xEE, 0x6F, 0x8E, 0x1F, 0xCE, 0xC0, 0xAA, 0x9E, 0xCC, 0xFD, 0x3A, 0xA5, 0x47, 0x7B, 0x3E, 0xF8, 0xF5, 0xF8, 0x5F, 0x0A, 0x06, 0x07, 0x3F, 0x97, 0x52, 0x28, 0x57, }, - 381, - true}, + 381}, {{ 0x4B, 0xA6, 0x03, 0x1C, 0xA3, 0x05, 0xB0, 0x9E, 0x53, 0xBD, 0xE3, 0x70, 0x51, 0x45, 0x48, 0x1D, 0x03, 0x32, 0xB6, 0x51, 0xFE, 0x30, 0x37, 0x0D, 0xD5, 0x25, 0x4C, 0xC4, 0xD2, 0xCB, 0x32, 0xF3, }, - 328, - true}, + 328}, {{ 0x4B, 0xDC, 0x63, 0x6F, 0x48, 0xD2, 0x1F, 0xB6, 0x8C, 0x5A, 0x3C, 0xD4, 0xA2, 0x06, 0x85, 0x78, 0x80, 0x43, 0xBD, 0xB5, 0x24, 0xE7, 0xE8, 0x4D, 0x41, 0x92, 0xC4, 0x51, 0xEE, 0x34, 0x29, 0xB5, }, - 131, - true}, + 131}, {{ 0x4C, 0xC2, 0x97, 0x58, 0xA2, 0xCB, 0x9B, 0x50, 0x10, 0x99, 0x87, 0xF3, 0x75, 0x37, 0xCF, 0x0C, 0x55, 0xBA, 0x2E, 0x67, 0x98, 0x93, 0x73, 0x07, 0xA0, 0x02, 0x96, 0xB0, 0x1D, 0xFF, 0xE4, 0x4A, }, - 284, - true}, + 284}, {{ 0x4D, 0x40, 0xE7, 0xAF, 0x43, 0x04, 0xA0, 0x9D, 0xE8, 0x7F, 0xBF, 0x98, 0x96, 0x20, 0x4C, 0x05, 0x51, 0x41, 0xE3, 0xF8, 0x09, 0xB2, 0xFE, 0x73, 0x3B, 0xB2, 0x31, 0x0F, 0xDF, 0x98, 0xA1, 0x62, }, - 155, - true}, + 155}, {{ 0x4E, 0x6C, 0x16, 0x16, 0x63, 0x71, 0x99, 0xB5, 0x07, 0x7A, 0x80, 0xAD, 0x0C, 0x22, 0x48, 0xC7, 0x25, 0xE5, 0x76, 0xFC, 0x8A, 0x71, 0x99, 0x89, 0x45, 0x6B, 0xC9, 0xCA, 0xFD, 0xDB, 0x75, 0x24, }, - 454, - true}, + 454}, {{ 0x4E, 0xAD, 0xA9, 0xB5, 0x31, 0x1E, 0x71, 0x81, 0x99, 0xD9, 0x8E, 0xA8, 0x2B, 0x95, 0x00, 0x5C, 0xBA, 0x93, 0x19, 0x8A, 0xB1, 0xF9, 0x7E, 0xFC, 0xBE, 0x8D, 0xC6, 0x20, 0x16, 0x28, 0xF8, 0xAF, }, - 100, - true}, + 100}, {{ 0x4E, 0xF7, 0xDA, 0xCF, 0x77, 0xED, 0xB7, 0x51, 0xF7, 0x04, 0x03, 0x5F, 0xB5, 0xC6, 0xC4, 0x42, 0x35, 0x1E, 0xC7, 0x22, 0x0A, 0xF9, 0x0B, 0xDF, 0x82, 0xFD, 0x04, 0x7B, 0xD3, 0xC2, 0x41, 0x87, }, - 470, - true}, + 470}, {{ 0x4F, 0x71, 0x62, 0xB9, 0x74, 0x49, 0x1C, 0x98, 0x58, 0x5E, 0xC2, 0x8F, 0xE7, 0x59, 0xAA, 0x00, 0xC3, 0x30, 0xD0, 0xB4, 0x65, 0x19, 0x0A, 0x89, 0x6C, 0xC4, 0xB6, 0x16, 0x23, 0x18, 0x31, 0xFC, }, - 476, - true}, + 476}, {{ 0x50, 0x8F, 0x8C, 0x61, 0x78, 0xAF, 0x32, 0x9B, 0xB6, 0xBB, 0x75, 0x3A, 0xB9, 0x43, 0xD9, 0x02, 0x3B, 0xE7, 0x96, 0xC3, 0xAD, 0xBB, 0x6C, 0x5C, 0xD4, 0x66, 0x4B, 0x66, 0xFE, 0xEC, 0xCA, 0xE5, }, - 413, - true}, + 413}, {{ 0x50, 0x94, 0xB7, 0x3B, 0x73, 0x6A, 0xDF, 0x73, 0xA0, 0xCB, 0xF4, 0x3E, 0x27, 0xBF, 0x14, 0x40, 0x7B, 0x4A, 0x36, 0xAA, 0x36, 0x3A, 0x45, 0x7F, 0xCE, 0x33, 0x94, 0x9C, 0xEB, 0xA8, 0xE6, 0x49, }, - 385, - true}, + 385}, {{ 0x50, 0xCC, 0x86, 0xBA, 0x96, 0xDB, 0x32, 0x63, 0xC7, 0x9A, 0x43, 0xEA, 0xD0, 0x75, 0x53, 0xD9, 0xF5, 0x66, 0x59, 0xE6, 0x90, 0x7E, 0x72, 0xD8, 0xC0, 0x26, 0x63, 0x7A, 0x1C, 0xDC, 0x85, 0xDC, }, - 204, - false}, + 204}, {{ 0x51, 0x0D, 0x20, 0xE5, 0xC4, 0x7F, 0x63, 0xCF, 0x66, 0x6B, 0x20, 0xF6, 0x1A, 0xF6, 0x2B, 0xC0, 0x99, 0xA4, 0x2A, 0xC8, 0x24, 0xFF, 0xA4, 0x43, 0xA2, 0xDA, 0x7C, 0x90, 0xB1, 0x80, 0x8A, 0x91, }, - 154, - false}, + 154}, {{ 0x51, 0x43, 0xE4, 0x75, 0x69, 0xA1, 0xD5, 0xFC, 0x86, 0x78, 0x93, 0xE0, 0xCC, 0x41, 0x2C, 0x41, 0xF5, 0x57, 0x15, 0xDA, 0x78, 0xE5, 0x9E, 0x9F, 0x8E, 0x43, 0x77, 0x00, 0x08, 0xCA, 0x42, 0xD2, }, - 406, - true}, + 406}, {{ 0x51, 0x92, 0x43, 0x8E, 0xC3, 0x69, 0xD7, 0xEE, 0x0C, 0xE7, 0x1F, 0x5C, 0x6D, 0xB7, 0x5F, 0x94, 0x1E, 0xFB, 0xF7, 0x2E, 0x58, 0x44, 0x17, 0x15, 0xE9, 0x9E, 0xAB, 0x04, 0xC2, 0xC8, 0xAC, 0xEE, }, - 58, - false}, + 58}, {{ 0x51, 0xB6, 0xEA, 0x64, 0x78, 0x68, 0x7B, 0x47, 0xD9, 0x63, 0xB6, 0x14, 0x90, 0x59, 0x78, 0x0C, 0xF0, 0x8A, 0x4F, 0x02, 0xF0, 0x42, 0xD6, 0x1B, 0x5B, 0xD5, 0x26, 0x39, 0x09, 0x5E, 0xE9, 0x10, }, - 324, - true}, + 324}, {{ 0x52, 0x2C, 0x39, 0x60, 0x32, 0x80, 0x26, 0xA1, 0xE3, 0x22, 0x38, 0x9A, 0x8A, 0x08, 0xFE, 0xDC, 0x1B, 0x86, 0xD9, 0xC2, 0xB5, 0x9B, 0x33, 0x48, 0x4B, 0x77, 0xF7, 0xCE, 0x79, 0x06, 0x35, 0xD7, }, - 320, - true}, + 320}, {{ 0x53, 0x75, 0x66, 0x26, 0x28, 0xFA, 0x0A, 0x68, 0x40, 0xAE, 0xC8, 0xC5, 0x92, 0xBF, 0x5D, 0x8D, 0xE5, 0x64, 0xED, 0x3E, 0xFB, 0x62, 0xC7, 0xC9, 0x32, 0xFC, 0xA8, 0xD7, 0x54, 0xD9, 0xBB, 0xD6, }, - 203, - false}, + 203}, {{ 0x55, 0xE0, 0x0B, 0xE2, 0x77, 0xCE, 0xB0, 0x54, 0x52, 0x99, 0xF2, 0x4F, 0xD9, 0xF8, 0x77, 0xE2, 0xAC, 0xF3, 0x28, 0x52, 0xDB, 0x43, 0xFF, 0xCD, 0x29, 0xBC, 0xA7, 0x4B, 0x39, 0xB4, 0xC9, 0xFA, }, - 287, - false}, + 287}, {{ 0x55, 0xF7, 0x7D, 0xE4, 0x1C, 0x03, 0x79, 0x24, 0x28, 0xF8, 0xD5, 0x18, 0xC5, 0x51, 0x04, 0x22, 0x5B, 0xE4, 0x3A, 0x55, 0x98, 0xD9, 0x26, 0xA5, 0x28, 0xAD, 0x65, 0x3E, 0x1C, 0xCE, 0xC7, 0xBF, }, - 484, - false}, + 484}, {{ 0x56, 0x17, 0x4D, 0x3A, 0xD9, 0x71, 0xA8, 0x94, 0x49, 0x64, 0xB1, 0x89, 0x81, 0x1F, 0x30, 0x08, 0x49, 0x3A, 0x6A, 0x90, 0x42, 0x2E, 0x3C, 0x58, 0x04, 0xEC, 0x83, 0x8D, 0x4F, 0x94, 0xF6, 0x22, }, - 90, - false}, + 90}, {{ 0x56, 0x32, 0xD9, 0x7B, 0xFA, 0x77, 0x5B, 0xF3, 0xC9, 0x9D, 0xDE, 0xA5, 0x2F, 0xC2, 0x55, 0x34, 0x10, 0x86, 0x40, 0x16, 0x72, 0x9C, 0x52, 0xDD, 0x65, 0x24, 0xC8, 0xA9, 0xC3, 0xB4, 0x48, 0x9F, }, - 21, - false}, + 21}, {{ 0x56, 0x3B, 0x3C, 0xAF, 0x8C, 0xFE, 0xF3, 0x4C, 0x23, 0x35, 0xCA, 0xF5, 0x60, 0xA7, 0xA9, 0x59, 0x06, 0xE8, 0x48, 0x84, 0x62, 0xEB, 0x75, 0xAC, 0x59, 0x78, 0x48, 0x30, 0xDF, 0x9E, 0x5B, 0x2B, }, - 10, - false}, + 10}, {{ 0x56, 0x7B, 0x82, 0x11, 0xFD, 0x20, 0xD3, 0xD2, 0x83, 0xEE, 0x0C, 0xD7, 0xCE, 0x06, 0x72, 0xCB, 0x9D, 0x99, 0xBC, 0x5B, 0x48, 0x7A, 0x58, 0xC9, 0xD5, 0x4E, 0xC6, 0x7F, 0x77, 0xD4, 0xA8, 0xF5, }, - 121, - true}, + 121}, {{ 0x57, 0xA7, 0x42, 0xA8, 0x8D, 0x3E, 0x18, 0xFC, 0x0B, 0xC6, 0x11, 0xBC, 0x79, 0x76, 0xC2, 0x2E, 0xDC, 0x50, 0x01, 0x17, 0x57, 0x51, 0x2B, 0x1A, 0x7E, 0x2E, 0x1D, 0x06, 0x9B, 0x3E, 0xCB, 0xA0, }, - 464, - true}, + 464}, {{ 0x58, 0x04, 0x46, 0x26, 0xC3, 0x4C, 0x1A, 0x7B, 0x15, 0x8D, 0xDB, 0x67, 0x6D, 0x9E, 0x2E, 0x65, 0x44, 0x3D, 0x81, 0x8D, 0xAB, 0x31, 0x16, 0x23, 0x1E, 0x2D, 0x62, 0xAB, 0x64, 0x26, 0xA0, 0xB7, }, - 440, - true}, + 440}, {{ 0x58, 0x1C, 0xC1, 0x58, 0x21, 0x16, 0x96, 0x94, 0xC3, 0x9C, 0x29, 0x91, 0xB5, 0x3E, 0x93, 0xAB, 0x94, 0x5A, 0x42, 0xB0, 0x76, 0x66, 0x17, 0x74, 0xC2, 0xEC, 0xF3, 0x8A, 0x33, 0x23, 0xAC, 0xEA, }, - 540, - false}, + 540}, {{ 0x58, 0x99, 0xD9, 0x13, 0xEA, 0xD1, 0x19, 0xB9, 0xCD, 0xB7, 0xBA, 0x2F, 0x30, 0xEF, 0xE0, 0xDF, 0x68, 0xAD, 0x2C, 0xD2, 0x25, 0xBD, 0xF4, 0x93, 0xE8, 0x32, 0x3A, 0x25, 0xAA, 0x4D, 0xBE, 0x23, }, - 482, - true}, + 482}, {{ 0x58, 0xA2, 0xA6, 0x98, 0xD8, 0x6F, 0xD8, 0x49, 0x7D, 0x41, 0xF6, 0x8E, 0x4C, 0xAE, 0xB4, 0xA9, 0x88, 0x74, 0xF4, 0x33, 0xDA, 0x91, 0x3D, 0xD2, 0x6C, 0x5C, 0xA4, 0x4D, 0x08, 0xFF, 0x72, 0xFE, }, - 401, - true}, + 401}, {{ 0x58, 0xDD, 0x61, 0xFE, 0xB3, 0x6E, 0xA7, 0xD2, 0x58, 0x72, 0x43, 0x71, 0x70, 0x91, 0x49, 0xCB, 0x12, 0x13, 0x37, 0x86, 0x4C, 0xAC, 0xB2, 0xD0, 0x99, 0x9A, 0xD2, 0x07, 0x39, 0xD0, 0x64, 0x77, }, - 186, - false}, + 186}, {{ 0x59, 0x55, 0xAE, 0x29, 0x15, 0x74, 0xA9, 0x31, 0x34, 0x2C, 0xF7, 0x45, 0x0E, 0x16, 0x65, 0x2E, 0xDE, 0x1E, 0x0F, 0xB3, 0x09, 0x7E, 0x15, 0x71, 0xDF, 0xAC, 0x11, 0xC9, 0x15, 0x60, 0x15, 0x64, }, - 81, - false}, + 81}, {{ 0x59, 0xDF, 0x31, 0x7B, 0xFA, 0x9F, 0x4F, 0x0A, 0xB7, 0xCA, 0x51, 0x4D, 0x77, 0x72, 0x29, 0x6A, 0xA2, 0xC7, 0x65, 0xB8, 0x76, 0x64, 0xD0, 0x8B, 0x96, 0xE5, 0x73, 0x99, 0xE3, 0x64, 0x72, 0x9C, }, - 173, - false}, + 173}, {{ 0x5A, 0x88, 0x96, 0x47, 0x22, 0x0E, 0x54, 0xD6, 0xBD, 0x8A, 0x16, 0x81, 0x72, 0x24, 0x52, 0x0B, 0xB5, 0xC7, 0x8E, 0x58, 0x98, 0x4B, 0xD5, 0x70, 0x50, 0x63, 0x88, 0xB9, 0xDE, 0x0F, 0x07, 0x5F, }, - 80, - false}, + 80}, {{ 0x5A, 0xAC, 0xF1, 0xB9, 0x65, 0xE8, 0x53, 0x01, 0x0F, 0xCB, 0x2A, 0x11, 0x03, 0x17, 0xD5, 0xFC, 0xE3, 0xEE, 0x35, 0x1E, 0x9C, 0xC9, 0x5B, 0xF4, 0x44, 0xA5, 0x71, 0xD7, 0xB8, 0xEF, 0x91, 0x62, }, - 346, - true}, + 346}, {{ 0x5C, 0x41, 0xA7, 0x3A, 0xB2, 0xC3, 0x5D, 0xFC, 0xD7, 0x71, 0xF6, 0xFD, 0x6E, 0x3E, 0x8F, 0xAC, 0x9B, 0x46, 0x9D, 0x38, 0x6C, 0xAD, 0xDA, 0x56, 0xA9, 0x5B, 0x64, 0x6E, 0xB4, 0x8C, 0xCA, 0x34, }, - 468, - false}, + 468}, {{ 0x5D, 0xEE, 0x74, 0xCC, 0x34, 0x3D, 0xB9, 0x3F, 0x8D, 0xEA, 0xF9, 0xE4, 0x1F, 0xBC, 0x65, 0xB3, 0x34, 0x25, 0x4B, 0x5B, 0x23, 0xB5, 0x68, 0xFA, 0x28, 0x14, 0xDB, 0x8B, 0x73, 0x21, 0xAC, 0x85, }, - 296, - true}, + 296}, {{ 0x5E, 0x76, 0x73, 0xA1, 0x7A, 0x08, 0xD6, 0x14, 0x13, 0xCD, 0x51, 0xB5, 0x7D, 0xBA, 0xAC, 0xBE, 0xBF, 0xE5, 0xAC, 0xB9, 0x15, 0xE3, 0x96, 0x6E, 0x53, 0x21, 0xB1, 0x3E, 0xB9, 0xEF, 0xAA, 0xEB, }, - 159, - true}, + 159}, {{ 0x5E, 0xFA, 0x07, 0x3F, 0x49, 0x42, 0x63, 0x44, 0x48, 0x3A, 0xB0, 0xDD, 0xBB, 0xDD, 0xA5, 0xE3, 0x59, 0x72, 0xF9, 0xC4, 0x7C, 0x74, 0xDD, 0xF9, 0x8E, 0xC4, 0x22, 0x90, 0xB2, 0x51, 0xCA, 0x97, }, - 271, - true}, + 271}, {{ 0x5F, 0x66, 0x5B, 0x40, 0x60, 0xBE, 0x9E, 0xFA, 0xF6, 0xAD, 0x73, 0x9F, 0x6B, 0x39, 0xA1, 0xDB, 0x98, 0x47, 0x27, 0x7E, 0xB8, 0xDC, 0x14, 0x40, 0x45, 0x37, 0x6D, 0xE1, 0x00, 0x9E, 0x31, 0x27, }, - 164, - true}, + 164}, {{ 0x60, 0x46, 0x13, 0x68, 0x79, 0xE5, 0x64, 0x50, 0x40, 0x0F, 0x7D, 0xB2, 0xEC, 0xD0, 0xDF, 0x1B, 0x88, 0xF6, 0x67, 0xC1, 0xE3, 0xFF, 0xFC, 0x52, 0x96, 0x4F, 0xF9, 0xE2, 0xE4, 0x8E, 0x85, 0xF5, }, - 344, - true}, + 344}, {{ 0x61, 0x06, 0xC0, 0xE3, 0xA0, 0xA2, 0x99, 0x83, 0x18, 0x75, 0x12, 0x7B, 0xD7, 0xD3, 0xCC, 0x18, 0x59, 0x80, 0x3D, 0x51, 0x1C, 0xAC, 0x11, 0xEB, 0x6E, 0x08, 0x40, 0xDD, 0x16, 0x6F, 0xC1, 0x0E, }, - 176, - false}, + 176}, {{ 0x61, 0x61, 0x67, 0x20, 0x14, 0x33, 0xAE, 0xA6, 0xC8, 0xE5, 0xE3, 0x07, 0x0A, 0xFC, 0xAF, 0x67, 0x49, 0x18, 0x8F, 0x81, 0x4B, 0xD1, 0xAB, 0xB1, 0x79, 0xAE, 0x8D, 0xAD, 0x3A, 0xBF, 0x26, 0xEC, }, - 141, - false}, + 141}, {{ 0x62, 0x55, 0x4C, 0x17, 0x00, 0x55, 0x43, 0xB2, 0x37, 0x21, 0x5F, 0x04, 0x26, 0x8D, 0xCD, 0x2F, 0xD1, 0xC4, 0x70, 0x24, 0x0A, 0xD3, 0xC8, 0x66, 0x0E, 0x25, 0xAE, 0x2C, 0x59, 0x63, 0x0F, 0x55, }, - 97, - false}, + 97}, {{ 0x62, 0x8E, 0x3A, 0x11, 0x56, 0xF6, 0xFA, 0xA9, 0x2F, 0x94, 0xB4, 0x09, 0x25, 0x8D, 0x4C, 0xBA, 0x3F, 0x20, 0x47, 0x48, 0x0D, 0x30, 0x19, 0x4F, 0xAF, 0x3F, 0xBE, 0xD0, 0x5E, 0xAE, 0xB5, 0xB2, }, - 5, - true}, + 5}, {{ 0x62, 0xA3, 0x1A, 0x5C, 0x73, 0x0D, 0xBA, 0x67, 0x4D, 0xDB, 0x25, 0xDE, 0x33, 0xDF, 0x14, 0x36, 0x44, 0x37, 0x5B, 0x49, 0xAF, 0x07, 0x87, 0x8A, 0x66, 0x7B, 0x81, 0x34, 0x91, 0xC7, 0x39, 0x71, }, - 323, - true}, + 323}, {{ 0x63, 0xD9, 0xAF, 0x9B, 0x47, 0xB1, 0x06, 0x4D, 0x49, 0xA1, 0x0E, 0x7B, 0x7F, 0xD5, 0x66, 0xDB, 0xC8, 0xCA, 0xA3, 0x99, 0x45, 0x9B, 0xFC, 0x28, 0x29, 0xC5, 0x71, 0xAD, 0x8C, 0x6E, 0xF3, 0x4A, }, - 33, - false}, + 33}, {{ 0x63, 0xF1, 0xA6, 0xF7, 0x9D, 0x6E, 0x73, 0x0D, 0x10, 0x43, 0x2E, 0x63, 0x08, 0x19, 0x4F, 0xF7, 0xBC, 0x28, 0x85, 0x0A, 0xDF, 0x2B, 0xAD, 0xF7, 0x89, 0xD9, 0x71, 0x38, 0x5D, 0x85, 0x12, 0xEE, }, - 448, - true}, + 448}, {{ 0x65, 0x1B, 0xD6, 0x6F, 0x5C, 0x3D, 0xC6, 0x37, 0x95, 0x7E, 0xF5, 0x18, 0x5E, 0x4F, 0xA6, 0x71, 0xC2, 0x16, 0x54, 0xB1, 0xC0, 0xEA, 0x49, 0x38, 0x4F, 0x44, 0xBC, 0xB2, 0x56, 0xA5, 0x08, 0x4C, }, - 362, - true}, + 362}, {{ 0x65, 0x44, 0xFF, 0x9A, 0xDB, 0x64, 0x2C, 0x4C, 0x36, 0x98, 0xA6, 0x0D, 0x81, 0x43, 0xB6, 0xB9, 0x3B, 0xCE, 0xF0, 0x13, 0x65, 0xB5, 0x40, 0xF6, 0x14, 0xDC, 0xC2, 0xA4, 0x5A, 0xB9, 0x4D, 0x31, }, - 98, - true}, + 98}, {{ 0x65, 0x9C, 0xB3, 0x68, 0xAC, 0x56, 0x99, 0x8B, 0xD0, 0x7A, 0xF2, 0xCA, 0xFC, 0x5F, 0xB9, 0x3F, 0x8E, 0x79, 0x47, 0x4A, 0xCC, 0xC2, 0xA6, 0xCF, 0x1A, 0xC9, 0xF2, 0x19, 0x2D, 0x13, 0x63, 0x60, }, - 221, - true}, + 221}, {{ 0x66, 0xB0, 0x05, 0x39, 0x82, 0x6A, 0x37, 0x48, 0x49, 0x30, 0x19, 0x1E, 0x02, 0x8F, 0x62, 0xDA, 0xB1, 0xCB, 0xC8, 0x9B, 0x3A, 0xCD, 0x47, 0x2D, 0xC4, 0xE5, 0x90, 0x5E, 0x47, 0xBF, 0x73, 0x64, }, - 428, - true}, + 428}, {{ 0x67, 0x40, 0x39, 0xE4, 0x72, 0x56, 0x19, 0x63, 0xC8, 0xCB, 0x00, 0xD2, 0x1A, 0x97, 0xA9, 0x0A, 0x18, 0xBB, 0x8A, 0x1C, 0x4C, 0x31, 0x7A, 0xC6, 0x7E, 0x38, 0x2A, 0x65, 0x2B, 0xB5, 0x73, 0xC0, }, - 216, - true}, + 216}, {{ 0x67, 0x56, 0x05, 0xF1, 0x56, 0x7E, 0x25, 0xFB, 0xD2, 0x52, 0x6B, 0xEF, 0xEA, 0x2A, 0xEF, 0xBD, 0xB2, 0x27, 0x9F, 0x3E, 0x1B, 0xAA, 0x3A, 0x30, 0x3A, 0xE7, 0x55, 0x5D, 0x1B, 0xDA, 0x3E, 0xE4, }, - 198, - true}, + 198}, {{ 0x67, 0x6B, 0x9F, 0xF3, 0x03, 0xED, 0xE1, 0x80, 0xFB, 0x95, 0xA4, 0x73, 0x6F, 0xB4, 0xD3, 0x15, 0x30, 0x32, 0xC0, 0x14, 0x44, 0x4F, 0x63, 0xA2, 0x07, 0x4C, 0x41, 0xB9, 0x8B, 0x51, 0xE0, 0xBD, }, - 452, - true}, + 452}, {{ 0x67, 0xA8, 0x42, 0x64, 0xD4, 0x2E, 0x20, 0x4A, 0x9A, 0x5B, 0x0A, 0x36, 0x67, 0xB9, 0x51, 0xDB, 0x22, 0xC5, 0x05, 0xDF, 0x95, 0xED, 0x98, 0x3B, 0x5E, 0x8C, 0x4D, 0x1F, 0xCE, 0x77, 0xAF, 0x43, }, - 480, - true}, + 480}, {{ 0x67, 0xDC, 0x4F, 0x32, 0xFA, 0x10, 0xE7, 0xD0, 0x1A, 0x79, 0xA0, 0x73, 0xAA, 0x0C, 0x9E, 0x02, 0x12, 0xEC, 0x2F, 0xFC, 0x3D, 0x77, 0x9E, 0x0A, 0xA7, 0xF9, 0xC0, 0xF0, 0xE1, 0xC2, 0xC8, 0x93, }, - 104, - false}, + 104}, {{ 0x67, 0xEA, 0x19, 0x32, 0x43, 0xAE, 0x38, 0x39, 0x39, 0xB5, 0xAD, 0x9E, 0x35, 0x6A, 0x6B, 0x2B, 0xF9, 0x3A, 0x93, 0xBC, 0xDC, 0xF8, 0x28, 0xA4, 0x70, 0x82, 0x49, 0x78, 0x83, 0x08, 0x3F, 0x86, }, - 126, - true}, + 126}, {{ 0x68, 0x1D, 0xC4, 0x82, 0xC2, 0x96, 0xC8, 0x40, 0x2C, 0x6E, 0xBB, 0x20, 0xE6, 0x83, 0x09, 0xA3, 0xBC, 0x84, 0x65, 0x23, 0xAE, 0x34, 0xB9, 0x84, 0xA8, 0x4E, 0xE6, 0x97, 0xA3, 0x31, 0x2D, 0xB7, }, - 536, - false}, + 536}, {{ 0x68, 0x27, 0x47, 0xF8, 0xBA, 0x62, 0x1B, 0x87, 0xCD, 0xD3, 0xBC, 0x29, 0x5E, 0xD5, 0xCA, 0xBC, 0xE7, 0x22, 0xA1, 0xC0, 0xC0, 0x36, 0x3D, 0x1D, 0x68, 0xB3, 0x89, 0x28, 0xD2, 0x78, 0x7F, 0x1E, }, - 487, - false}, + 487}, {{ 0x68, 0x9B, 0xF4, 0x5B, 0x30, 0x83, 0xFD, 0xEA, 0xD5, 0x5F, 0x14, 0x7F, 0xD1, 0x05, 0xE3, 0xCF, 0x21, 0x8A, 0xD5, 0x8E, 0xDF, 0x3E, 0x4B, 0x30, 0x1C, 0x0C, 0x5E, 0xEE, 0xA6, 0xCF, 0x21, 0x0D, }, - 429, - true}, + 429}, {{ 0x68, 0xAA, 0x63, 0x54, 0x51, 0xD8, 0x39, 0x62, 0x16, 0x7E, 0x88, 0xFB, 0x08, 0xF8, 0x67, 0x8D, 0x73, 0xAE, 0xC6, 0x6F, 0xC5, 0x59, 0x46, 0x21, 0x37, 0xCF, 0xF9, 0xD1, 0xBC, 0x3D, 0x38, 0x71, }, - 506, - true}, + 506}, {{ 0x68, 0xC3, 0x69, 0x22, 0x14, 0x72, 0x4D, 0x4B, 0x55, 0xA7, 0x60, 0xF4, 0x70, 0xB4, 0xFC, 0xA8, 0xB5, 0xE0, 0xFE, 0x1D, 0x72, 0x9C, 0xFF, 0x22, 0xFE, 0xB4, 0xCA, 0x88, 0xAC, 0xD3, 0x98, 0x09, }, - 231, - true}, + 231}, {{ 0x68, 0xDE, 0xD9, 0xA2, 0x03, 0xFF, 0x6E, 0x36, 0x7E, 0x12, 0xAA, 0x49, 0x97, 0x7C, 0xD2, 0x00, 0xF7, 0x12, 0x7A, 0x80, 0x0F, 0xAA, 0x6F, 0x85, 0x9F, 0x0B, 0xAF, 0xED, 0x82, 0x86, 0xA4, 0xFB, }, - 499, - true}, + 499}, {{ 0x69, 0x3C, 0x9A, 0xA6, 0xB2, 0x45, 0xB3, 0xB0, 0x26, 0x16, 0x37, 0x75, 0x08, 0x63, 0xEA, 0xDB, 0x6C, 0x24, 0x8A, 0x16, 0xE5, 0x2D, 0x6F, 0x4B, 0xC9, 0x0C, 0x86, 0xBB, 0xF3, 0x2D, 0x70, 0x42, }, - 522, - false}, + 522}, {{ 0x6A, 0x43, 0x6B, 0x58, 0xD9, 0xD8, 0x30, 0xE8, 0xD5, 0xB8, 0xA6, 0x42, 0x50, 0x5A, 0xD6, 0xB4, 0x14, 0x06, 0xAD, 0xCD, 0x68, 0x94, 0xD9, 0x41, 0x4F, 0x7B, 0xE0, 0xA1, 0x46, 0x7B, 0xAD, 0xB7, }, - 426, - true}, + 426}, {{ 0x6A, 0x7B, 0x14, 0x82, 0x12, 0x70, 0x02, 0xF9, 0x00, 0x5A, 0x87, 0x35, 0x6E, 0x1D, 0xC3, 0xE0, 0x0B, 0x70, 0xBB, 0xBF, 0xA7, 0x95, 0x02, 0x4F, 0xF8, 0xBE, 0xFF, 0x74, 0xC4, 0x25, 0x9B, 0x75, }, - 421, - true}, + 421}, {{ 0x6A, 0x97, 0xB5, 0x1C, 0x82, 0x19, 0xE9, 0x3E, 0x5D, 0xEC, 0x64, 0xBA, 0xD5, 0x80, 0x6C, 0xDE, 0xB0, 0xF8, 0x35, 0x5B, 0xE4, 0x7E, 0x75, 0x70, 0x10, 0xB7, 0x02, 0x45, 0x6E, 0x01, 0xAA, 0xFD, }, - 531, - false}, + 531}, {{ 0x6B, 0x1A, 0x50, 0x5E, 0x02, 0x46, 0xF2, 0xF6, 0x0C, 0x49, 0x0F, 0xF0, 0xC0, 0x97, 0xA7, 0xBE, 0x27, 0x21, 0x0C, 0xBB, 0x75, 0x00, 0x23, 0x7F, 0x88, 0xB0, 0xCD, 0x48, 0x29, 0x8B, 0xC9, 0xB8, }, - 191, - false}, + 191}, {{ 0x6B, 0x3B, 0x57, 0xE9, 0xEC, 0x88, 0xD1, 0xBB, 0x3D, 0x01, 0x63, 0x7F, 0xF3, 0x3C, 0x76, 0x98, 0xB3, 0xC9, 0x75, 0x82, 0x55, 0xE9, 0xF0, 0x1E, 0xA9, 0x17, 0x8F, 0x3E, 0x7F, 0x3B, 0x2B, 0x52, }, - 194, - false}, + 194}, {{ 0x6B, 0x86, 0xDE, 0x96, 0xA6, 0x58, 0xA5, 0x68, 0x20, 0xA4, 0xF3, 0x5D, 0x90, 0xDB, 0x6C, 0x3E, 0xFD, 0xD5, 0x74, 0xCE, 0x94, 0xB9, 0x09, 0xCB, 0x0D, 0x7F, 0xF1, 0x7C, 0x3C, 0x18, 0x9D, 0x83, }, - 261, - true}, + 261}, {{ 0x6B, 0xCF, 0xC8, 0x6C, 0x8D, 0xDC, 0x2A, 0xF2, 0xE6, 0xA1, 0x18, 0x0A, 0x2D, 0xDA, 0xBB, 0x37, 0xB7, 0xEA, 0x37, 0x55, 0x31, 0x6B, 0x64, 0xB9, 0xB8, 0x95, 0x1B, 0xF0, 0xCA, 0x35, 0x1F, 0x06, }, - 20, - false}, + 20}, {{ 0x6C, 0x46, 0x4B, 0x9A, 0x5B, 0x23, 0x3A, 0x5E, 0x87, 0x4D, 0xA7, 0x65, 0xC2, 0x6F, 0x04, 0x50, 0x10, 0xD2, 0xDD, 0xCF, 0xF4, 0x57, 0x94, 0xF0, 0xB4, 0xC7, 0xE4, 0xAA, 0xFA, 0x50, 0x14, 0x95, }, - 137, - false}, + 137}, {{ 0x6C, 0x5C, 0xBF, 0x02, 0xC1, 0x84, 0x91, 0x66, 0x27, 0x8F, 0x1C, 0xD1, 0xC8, 0x35, 0x83, 0xA1, 0x47, 0xFB, 0x7B, 0xC9, 0x5E, 0x28, 0x9B, 0x27, 0x63, 0x66, 0x93, 0x5E, 0x31, 0x53, 0xF3, 0x02, }, - 277, - true}, + 277}, {{ 0x6C, 0xAE, 0x87, 0xC5, 0x58, 0xD2, 0x44, 0x15, 0x68, 0xE3, 0x82, 0x70, 0xA8, 0xDD, 0x8F, 0xF4, 0x84, 0xA2, 0x59, 0xDC, 0x4F, 0x3C, 0xE9, 0x4C, 0xCF, 0x43, 0x4C, 0x1F, 0xA9, 0x98, 0x11, 0xF6, }, - 325, - true}, + 325}, {{ 0x6D, 0x28, 0xF9, 0xE4, 0x05, 0x14, 0x8B, 0x69, 0x02, 0x7D, 0xA9, 0x90, 0x81, 0x52, 0x11, 0xC8, 0x58, 0x84, 0x1C, 0x54, 0x3F, 0xEC, 0xED, 0x00, 0x8C, 0x23, 0x80, 0x21, 0x98, 0x3C, 0x09, 0x5A, }, - 376, - true}, + 376}, {{ 0x6D, 0x6F, 0x0C, 0x34, 0x09, 0x71, 0xA2, 0x18, 0xA3, 0x1D, 0x10, 0x33, 0x0E, 0xA9, 0xAE, 0x7C, 0x7A, 0x65, 0x50, 0x53, 0x4C, 0x6E, 0xEF, 0xED, 0xDD, 0x21, 0x18, 0xE1, 0x14, 0xDB, 0x47, 0x3E, }, - 202, - true}, + 202}, {{ 0x6D, 0xBF, 0xAE, 0x00, 0xD3, 0x7B, 0x9C, 0xD7, 0x3F, 0x8F, 0xB4, 0x7D, 0xE6, 0x59, 0x17, 0xAF, 0x00, 0xE0, 0xDD, 0xDF, 0x42, 0xDB, 0xCE, 0xAC, 0x20, 0xC1, 0x7C, 0x02, 0x75, 0xEE, 0x20, 0x95, }, - 117, - false}, + 117}, {{ 0x6E, 0x36, 0x4B, 0x61, 0x33, 0xDE, 0xEF, 0xDC, 0xBB, 0x21, 0x27, 0x3C, 0x5F, 0x44, 0x5A, 0x20, 0xAF, 0xBC, 0x05, 0x03, 0x8D, 0x5B, 0x02, 0x1C, 0x0C, 0x21, 0x53, 0x03, 0x90, 0x16, 0x34, 0x5B, }, - 193, - false}, + 193}, {{ 0x6F, 0x3E, 0x07, 0x7F, 0xE5, 0x50, 0x46, 0x46, 0xC0, 0x19, 0x1A, 0xFC, 0xE4, 0x94, 0xE4, 0xEB, 0x68, 0x18, 0x3E, 0x39, 0x8F, 0x5A, 0x4D, 0xC0, 0x56, 0x69, 0xF8, 0xB6, 0xE6, 0xE6, 0x82, 0xFE, }, - 151, - true}, + 151}, {{ 0x70, 0x06, 0xA3, 0x83, 0x11, 0xE5, 0x8F, 0xB1, 0x93, 0x48, 0x42, 0x33, 0x21, 0x82, 0x10, 0xC6, 0x61, 0x25, 0xA0, 0xE4, 0xA8, 0x26, 0xAE, 0xD5, 0x39, 0xAC, 0x56, 0x1D, 0xFB, 0xFB, 0xD9, 0x03, }, - 227, - true}, + 227}, {{ 0x70, 0x16, 0x27, 0x0B, 0x60, 0xB2, 0x8C, 0x6E, 0x17, 0x7E, 0xDE, 0xBD, 0x71, 0x80, 0x07, 0xDF, 0xD3, 0x31, 0x0C, 0x64, 0xA7, 0x37, 0xB7, 0xDB, 0x01, 0xA0, 0x76, 0x90, 0xC3, 0x43, 0xBC, 0x27, }, - 389, - true}, + 389}, {{ 0x70, 0x21, 0x16, 0xCC, 0xD8, 0xBF, 0x23, 0xE1, 0x64, 0x66, 0xF0, 0xE0, 0xDB, 0xA0, 0xED, 0x6A, 0x23, 0x9A, 0x9C, 0x1C, 0xD6, 0xA8, 0xF5, 0xA6, 0x6B, 0x39, 0xAF, 0x35, 0x95, 0x02, 0x03, 0x85, }, - 92, - false}, + 92}, {{ 0x70, 0x6B, 0xB1, 0x01, 0x7C, 0x85, 0x5C, 0x59, 0x16, 0x9B, 0xAD, 0x5C, 0x17, 0x81, 0xCF, 0x59, 0x7F, 0x12, 0xD2, 0xCA, 0xD2, 0xF6, 0x3D, 0x1A, 0x4A, 0xA3, 0x74, 0x93, 0x80, 0x0F, 0xFB, 0x80, }, - 18, - false}, + 18}, {{ 0x71, 0x9C, 0xF5, 0xB3, 0x61, 0x92, 0xE7, 0xBD, 0xE6, 0x50, 0xCC, 0x91, 0x34, 0x1E, 0x6F, 0x64, 0x9D, 0xBB, 0x8C, 0x3E, 0xE4, 0x8B, 0xAC, 0xAA, 0x97, 0xFA, 0x0E, 0x05, 0xB6, 0x37, 0x4B, 0x41, }, - 242, - true}, + 242}, {{ 0x71, 0xED, 0x91, 0x8A, 0x7A, 0xC6, 0xD1, 0x7B, 0x38, 0x49, 0xC2, 0x01, 0x80, 0xB3, 0xE7, 0x33, 0x46, 0x91, 0xBC, 0x5F, 0xB7, 0x33, 0x77, 0xF0, 0x07, 0x0A, 0xFA, 0x0B, 0xE7, 0x89, 0xB2, 0xD1, }, - 446, - true}, + 446}, {{ 0x76, 0x21, 0x95, 0xC2, 0x25, 0x58, 0x6E, 0xE6, 0xC0, 0x23, 0x74, 0x56, 0xE2, 0x10, 0x7D, 0xC5, 0x4F, 0x1E, 0xFC, 0x21, 0xF6, 0x1A, 0x79, 0x2E, 0xBD, 0x51, 0x59, 0x13, 0xCC, 0xE6, 0x83, 0x32, }, - 535, - false}, + 535}, {{ 0x76, 0xEE, 0x85, 0x90, 0x37, 0x4C, 0x71, 0x54, 0x37, 0xBB, 0xCA, 0x6B, 0xBA, 0x60, 0x28, 0xEA, 0xDD, 0xE2, 0xDC, 0x6D, 0xBB, 0xB8, 0xC3, 0xF6, 0x10, 0xE8, 0x51, 0xF1, 0x1D, 0x1A, 0xB7, 0xF5, }, - 42, - false}, + 42}, {{ 0x77, 0x29, 0x07, 0x17, 0x61, 0x4B, 0x25, 0xF1, 0x29, 0x64, 0xEB, 0xDB, 0x38, 0xB5, 0xF8, 0x3C, 0xAA, 0xDC, 0x0F, 0x6C, 0x36, 0xB0, 0x77, 0x7F, 0x88, 0x0F, 0xC6, 0xDE, 0xE1, 0xD3, 0x39, 0xCC, }, - 127, - false}, + 127}, {{ 0x77, 0x2F, 0xCC, 0xCA, 0x7D, 0x16, 0x46, 0xD6, 0x06, 0x28, 0x13, 0x4F, 0xF2, 0xE6, 0xE7, 0xF5, 0xBA, 0x09, 0x58, 0x98, 0xBE, 0x59, 0x69, 0x8B, 0xCE, 0x9D, 0x15, 0xF9, 0x6F, 0x69, 0xA9, 0xF3, }, - 12, - false}, + 12}, {{ 0x78, 0x2D, 0x7E, 0x61, 0xE1, 0x32, 0x3D, 0x2A, 0xAF, 0xB8, 0x77, 0xBE, 0x34, 0xEE, 0x1D, 0xE0, 0xC1, 0x34, 0x51, 0x36, 0xD4, 0xFC, 0xB3, 0xC9, 0x45, 0x93, 0x7F, 0x6A, 0x67, 0xB4, 0x12, 0xFE, }, - 435, - true}, + 435}, {{ 0x78, 0x6F, 0xFA, 0x57, 0x86, 0x18, 0xC3, 0xB9, 0xA3, 0x11, 0x17, 0x5E, 0x50, 0x81, 0x6F, 0x4D, 0xDA, 0x06, 0x05, 0xC3, 0x86, 0x9F, 0x29, 0x6E, 0xBC, 0x59, 0x43, 0xBF, 0x09, 0xF4, 0xE9, 0x04, }, - 510, - true}, + 510}, {{ 0x78, 0xCF, 0x3D, 0x3C, 0x72, 0xDA, 0xF9, 0x1C, 0xC5, 0x1B, 0x87, 0x13, 0x57, 0xA5, 0x51, 0xCF, 0x95, 0xB8, 0x37, 0xD0, 0x74, 0xC2, 0x70, 0xB0, 0x8F, 0xAC, 0xD4, 0x63, 0xA8, 0xD3, 0x9B, 0xB3, }, - 437, - true}, + 437}, {{ 0x79, 0xCA, 0xAF, 0x53, 0x47, 0xE6, 0xE4, 0xA9, 0x4C, 0x8E, 0x78, 0xA9, 0x84, 0x96, 0xFC, 0x74, 0x02, 0x0F, 0x80, 0x9E, 0xDE, 0x13, 0xF2, 0x20, 0xFA, 0xB6, 0x10, 0x4C, 0x8D, 0xED, 0x32, 0x9F, }, - 516, - true}, + 516}, {{ 0x7A, 0xED, 0xDD, 0xF3, 0x6B, 0x18, 0xF8, 0xAC, 0xB7, 0x37, 0x9F, 0xE1, 0xCE, 0x18, 0x32, 0x12, 0xB2, 0x35, 0x0D, 0x07, 0x88, 0xAB, 0xE0, 0xE8, 0x24, 0x57, 0xBE, 0x9B, 0xAD, 0xAD, 0x6D, 0x54, }, - 195, - true}, + 195}, {{ 0x7A, 0xFE, 0x4B, 0x07, 0x1A, 0x2F, 0x1F, 0x46, 0xF8, 0xBA, 0x94, 0x4A, 0x26, 0xD5, 0x84, 0xD5, 0x96, 0x0B, 0x92, 0xFB, 0x48, 0xC3, 0xBA, 0x1B, 0x7C, 0xAB, 0x84, 0x90, 0x5F, 0x32, 0xAA, 0xCD, }, - 291, - false}, + 291}, {{ 0x7C, 0x3B, 0x46, 0xD9, 0xBE, 0x8F, 0x27, 0x41, 0xF9, 0x80, 0x03, 0x95, 0x21, 0x85, 0x8E, 0x4C, 0xDD, 0x30, 0x77, 0x4F, 0xB3, 0x2B, 0x3B, 0x21, 0xCE, 0xEA, 0x06, 0xAA, 0x79, 0xC6, 0xAA, 0xC6, }, - 341, - true}, + 341}, {{ 0x7C, 0xAA, 0x03, 0x46, 0x51, 0x24, 0x59, 0x0C, 0x60, 0x1E, 0x56, 0x7E, 0x52, 0x14, 0x8E, 0x95, 0x2C, 0x0C, 0xFF, 0xE8, 0x90, 0x00, 0x53, 0x0F, 0xE0, 0xD9, 0x5B, 0x6D, 0x50, 0xEA, 0xAE, 0x41, }, - 86, - false}, + 86}, {{ 0x7C, 0xD6, 0x7C, 0x24, 0x8F, 0x69, 0xD8, 0x3F, 0xC2, 0xF9, 0xBB, 0x01, 0xDC, 0xB1, 0xF7, 0xAD, 0x67, 0xA3, 0x63, 0xD0, 0x46, 0x04, 0x37, 0x96, 0xD0, 0x98, 0x4C, 0x3A, 0x23, 0x1F, 0x6B, 0xB0, }, - 294, - false}, + 294}, {{ 0x7D, 0x43, 0x4D, 0x1D, 0xAD, 0xA2, 0xA1, 0x54, 0xD4, 0x9F, 0x47, 0x3E, 0x38, 0x13, 0x10, 0xB8, 0x3E, 0xE5, 0x8D, 0x29, 0x0A, 0x13, 0x45, 0x51, 0x82, 0xD7, 0x7F, 0x19, 0x62, 0xDF, 0x55, 0xEE, }, - 306, - true}, + 306}, {{ 0x7D, 0x6C, 0x3E, 0xBF, 0x9E, 0xA7, 0x35, 0xD1, 0x85, 0x4B, 0xEE, 0xA7, 0xCB, 0x94, 0x1A, 0xB1, 0xE3, 0x50, 0x35, 0x15, 0xE0, 0x87, 0xBB, 0xB5, 0xBE, 0x69, 0x5D, 0x05, 0xF2, 0xF5, 0x56, 0xE4, }, - 473, - true}, + 473}, {{ 0x7E, 0x0E, 0xAD, 0x76, 0xBB, 0x68, 0x19, 0xDC, 0x2F, 0x54, 0x51, 0x1A, 0x84, 0x35, 0x4F, 0x6E, 0x8B, 0x30, 0x7B, 0x9D, 0xD8, 0x20, 0x58, 0xEA, 0x6C, 0x00, 0x4F, 0x01, 0xD9, 0xDD, 0xA5, 0xDF, }, - 181, - false}, + 181}, {{ 0x7E, 0x6A, 0xCD, 0x85, 0x3C, 0xAC, 0xC6, 0x93, 0x2E, 0x9B, 0x51, 0x9F, 0xDA, 0xD1, 0xBE, 0xB5, 0x15, 0xED, 0x2A, 0x2D, 0x00, 0x25, 0xCF, 0xD3, 0x98, 0xC3, 0xAC, 0x1F, 0x0D, 0xBB, 0x75, 0x4B, }, - 395, - true}, + 395}, {{ 0x7E, 0x87, 0x82, 0xC1, 0x50, 0xCE, 0x39, 0x52, 0xF8, 0x02, 0xE6, 0x36, 0x02, 0x3A, 0x5D, 0x3E, 0x95, 0xBB, 0x5D, 0x68, 0xE3, 0x3E, 0x85, 0xAD, 0xB2, 0xBA, 0x17, 0x81, 0x25, 0xCE, 0xBF, 0x15, }, - 30, - false}, + 30}, {{ 0x7F, 0x1D, 0xEC, 0x8B, 0x03, 0x19, 0x54, 0x8A, 0x05, 0x6D, 0xE5, 0xBB, 0x52, 0x1B, 0xD9, 0x3E, 0xB7, 0x4E, 0x6A, 0x76, 0xF2, 0x8D, 0xFF, 0xB7, 0x5B, 0x45, 0xA5, 0x3B, 0x77, 0x5A, 0xF7, 0xAB, }, - 274, - true}, + 274}, {{ 0x7F, 0x42, 0x96, 0xFC, 0x5B, 0x6A, 0x4E, 0x3B, 0x35, 0xD3, 0xC3, 0x69, 0x62, 0x3E, 0x36, 0x4A, 0xB1, 0xAF, 0x38, 0x1D, 0x8F, 0xA7, 0x12, 0x15, 0x33, 0xC9, 0xD6, 0xC6, 0x33, 0xEA, 0x24, 0x61, }, - 209, - false}, + 209}, {{ 0x7F, 0x7C, 0x88, 0xA7, 0x7D, 0x4D, 0x3B, 0x44, 0xC3, 0x3B, 0x3C, 0x03, 0x0B, 0xC8, 0x3F, 0x1A, 0x26, 0xC2, 0x0D, 0x49, 0x17, 0x7C, 0xA7, 0x74, 0x5D, 0x91, 0xD9, 0xDE, 0x17, 0xE0, 0x8F, 0x14, }, - 349, - true}, + 349}, {{ 0x80, 0x5C, 0x66, 0x96, 0x26, 0x6B, 0x96, 0xB1, 0x47, 0x46, 0x8A, 0x32, 0x1E, 0xBA, 0x9E, 0xB8, 0xB5, 0x96, 0x8F, 0x2C, 0x47, 0x7C, 0xDD, 0x95, 0xFD, 0xAD, 0xD1, 0xFC, 0x63, 0xDD, 0x61, 0x4B, }, - 298, - true}, + 298}, {{ 0x80, 0x8D, 0x68, 0xB3, 0xFA, 0xB4, 0x88, 0x4A, 0x5F, 0x97, 0x1A, 0xCE, 0x7D, 0x10, 0x55, 0x0D, 0x7A, 0x95, 0xA1, 0x63, 0x77, 0x4F, 0x3E, 0xC3, 0x6A, 0xFF, 0xFB, 0x21, 0x3F, 0xBE, 0x4C, 0x74, }, - 84, - false}, + 84}, {{ 0x80, 0x9F, 0x2B, 0xAA, 0xE3, 0x5A, 0xFB, 0x4F, 0x36, 0xBD, 0x64, 0x76, 0xCE, 0x75, 0xC2, 0x00, 0x10, 0x77, 0x90, 0x1B, 0x6A, 0xF5, 0xC4, 0xDA, 0xB8, 0x2E, 0x18, 0x8C, 0x6B, 0x95, 0xC1, 0xA1, }, - 258, - true}, + 258}, {{ 0x80, 0xDB, 0xFB, 0x97, 0xBD, 0xD3, 0x92, 0x6B, 0xAE, 0xE4, 0x1F, 0x73, 0xC5, 0x58, 0x8F, 0xAA, 0x17, 0xD7, 0x07, 0xB0, 0x3A, 0xDF, 0x49, 0x07, 0xA2, 0xBC, 0x67, 0x7F, 0x3E, 0xF1, 0x71, 0x7C, }, - 214, - true}, + 214}, {{ 0x81, 0x6B, 0xA0, 0xBF, 0xDF, 0x5F, 0xD6, 0x4D, 0x56, 0x8E, 0xC0, 0xD0, 0x52, 0xF7, 0x11, 0x64, 0xD9, 0xE2, 0xCC, 0xAE, 0x12, 0xE0, 0x21, 0x9E, 0xD6, 0xCD, 0x81, 0xE7, 0xE8, 0x45, 0xFB, 0x84, }, - 423, - true}, + 423}, {{ 0x81, 0xA9, 0x8F, 0xC7, 0x88, 0xC3, 0x5F, 0x55, 0x76, 0x45, 0xA9, 0x52, 0x24, 0xE5, 0x0C, 0xD1, 0xDA, 0xC8, 0xFF, 0xB2, 0x09, 0xDC, 0x1E, 0x56, 0x88, 0xAA, 0x29, 0x20, 0x5F, 0x13, 0x22, 0x18, }, - 166, - true}, + 166}, {{ 0x82, 0x8B, 0x0E, 0xEF, 0xF2, 0x46, 0x54, 0xE8, 0xFF, 0x58, 0x41, 0xA2, 0x9D, 0xD5, 0xD4, 0xE3, 0xED, 0x30, 0x95, 0x2C, 0xA4, 0x34, 0x25, 0xA7, 0x92, 0x83, 0x40, 0x72, 0x08, 0xD3, 0x9D, 0x16, }, - 511, - true}, + 511}, {{ 0x82, 0xB5, 0xF8, 0x4D, 0xAF, 0x47, 0xA5, 0x9C, 0x7A, 0xB5, 0x21, 0xE4, 0x98, 0x2A, 0xEF, 0xA4, 0x0A, 0x53, 0x40, 0x6A, 0x3A, 0xEC, 0x26, 0x03, 0x9E, 0xFA, 0x6B, 0x2E, 0x0E, 0x72, 0x44, 0xC1, }, - 183, - false}, + 183}, {{ 0x84, 0xAA, 0xC0, 0x93, 0xE0, 0x8C, 0x49, 0xDB, 0xFF, 0xF8, 0xE5, 0x60, 0x75, 0x92, 0x48, 0xDB, 0xE6, 0x71, 0x35, 0xB3, 0x72, 0xB2, 0x3D, 0x2A, 0x88, 0x1D, 0x5F, 0x99, 0xCB, 0xB1, 0x91, 0xE8, }, - 276, - true}, + 276}, {{ 0x85, 0xA3, 0xD8, 0x1D, 0x2A, 0xD0, 0xC7, 0x9D, 0xF0, 0xA7, 0x96, 0x84, 0xE0, 0xE2, 0x66, 0x60, 0x09, 0xA0, 0x9D, 0xE1, 0x57, 0x60, 0xEA, 0x1D, 0x76, 0xCF, 0x0E, 0xE7, 0xB2, 0x82, 0x5D, 0xBD, }, - 410, - true}, + 410}, {{ 0x85, 0xD2, 0x6B, 0xE9, 0x0D, 0x93, 0x4F, 0xCC, 0xDB, 0x4F, 0xF7, 0xB3, 0x8D, 0x8C, 0x79, 0xCA, 0x76, 0x52, 0xB8, 0x16, 0xD6, 0xA5, 0x24, 0x46, 0xCA, 0x84, 0x28, 0xA6, 0xB8, 0x5D, 0xC5, 0x7C, }, - 273, - true}, + 273}, {{ 0x86, 0x0A, 0x7F, 0x19, 0x21, 0x0D, 0x5E, 0xAD, 0x05, 0x7A, 0x78, 0x53, 0x2B, 0x80, 0x95, 0x14, 0x53, 0xCB, 0x29, 0x07, 0x31, 0x5F, 0x3B, 0xA7, 0xAA, 0x47, 0xB6, 0x98, 0x97, 0xD7, 0x0F, 0x3F, }, - 249, - true}, + 249}, {{ 0x86, 0xA6, 0x8F, 0x05, 0x00, 0x34, 0x12, 0x6A, 0x54, 0x0D, 0x39, 0xDB, 0x2C, 0x5F, 0x91, 0x7E, 0xF6, 0x6A, 0x94, 0xFB, 0x96, 0x19, 0xFA, 0x1E, 0xCD, 0x82, 0x7C, 0xEA, 0x46, 0xBA, 0x0C, 0xB0, }, - 170, - false}, + 170}, {{ 0x86, 0xC1, 0x3A, 0x34, 0x08, 0xDD, 0x1A, 0xA7, 0x7E, 0xE8, 0xB6, 0x94, 0x7C, 0x03, 0x95, 0x87, 0x72, 0xF5, 0x31, 0x24, 0x8C, 0x16, 0x27, 0xBE, 0xFB, 0x2C, 0x4F, 0x4B, 0x04, 0xD0, 0x44, 0x96, }, - 53, - true}, + 53}, {{ 0x86, 0xC8, 0x4B, 0x1C, 0x3A, 0x66, 0xF4, 0x28, 0x5A, 0xF7, 0x97, 0x05, 0x24, 0x67, 0xE3, 0xED, 0x23, 0x6F, 0xD2, 0x98, 0x6F, 0x03, 0x3C, 0x02, 0xC4, 0x77, 0x1B, 0xE0, 0xB9, 0x70, 0x48, 0x2A, }, - 366, - true}, + 366}, {{ 0x87, 0x15, 0x7A, 0x75, 0x85, 0xF4, 0xD0, 0x3B, 0x00, 0xA3, 0x98, 0x46, 0x1E, 0x16, 0x4E, 0x48, 0x06, 0xE1, 0xB3, 0xF4, 0x6D, 0x03, 0xAF, 0xBD, 0xC9, 0xDE, 0xF4, 0xE4, 0x77, 0x8B, 0xE2, 0xE9, }, - 378, - true}, + 378}, {{ 0x87, 0x1A, 0x91, 0x94, 0xF4, 0xEE, 0xD5, 0xB3, 0x12, 0xFF, 0x40, 0xC8, 0x4C, 0x1D, 0x52, 0x4A, 0xED, 0x2F, 0x77, 0x8B, 0xBF, 0xF2, 0x5F, 0x13, 0x8C, 0xF8, 0x1F, 0x68, 0x0A, 0x7A, 0xDC, 0x67, }, - 483, - false}, + 483}, {{ 0x87, 0xAF, 0x34, 0xD6, 0x6F, 0xB3, 0xF2, 0xFD, 0xF3, 0x6E, 0x09, 0x11, 0x1E, 0x9A, 0xBA, 0x2F, 0x6F, 0x44, 0xB2, 0x07, 0xF3, 0x86, 0x3F, 0x3D, 0x0B, 0x54, 0xB2, 0x50, 0x23, 0x90, 0x9A, 0xA5, }, - 75, - false}, + 75}, {{ 0x88, 0x1A, 0x1B, 0x9E, 0xDF, 0x69, 0xAD, 0xE1, 0x41, 0x83, 0x9A, 0xE8, 0x67, 0x3D, 0x31, 0xB4, 0xF4, 0xD4, 0x7F, 0x12, 0x6C, 0xA0, 0x8A, 0x79, 0xFF, 0x06, 0x5D, 0xC9, 0xA6, 0x90, 0xF4, 0xA3, }, - 322, - true}, + 322}, {{ 0x89, 0x1F, 0xF8, 0x98, 0xE4, 0xA8, 0xD5, 0x55, 0x14, 0x00, 0x56, 0xE3, 0x17, 0x6E, 0xEA, 0x91, 0xF4, 0xD8, 0x08, 0xEE, 0x7F, 0x6D, 0x1B, 0xFB, 0xCC, 0xE6, 0xF8, 0x48, 0x07, 0x63, 0x9F, 0x91, }, - 199, - false}, + 199}, {{ 0x89, 0x91, 0xE2, 0x19, 0xCE, 0x9F, 0x74, 0x47, 0x9E, 0xAF, 0xED, 0xB3, 0x53, 0x58, 0x36, 0x12, 0x1D, 0xD2, 0x33, 0xEA, 0x76, 0x8A, 0xFB, 0x9D, 0x9A, 0xC8, 0xB4, 0xA2, 0x23, 0x81, 0xA8, 0xD5, }, - 321, - true}, + 321}, {{ 0x8A, 0x27, 0xB5, 0x55, 0x7B, 0x4B, 0xEC, 0x7C, 0xC0, 0x30, 0x5F, 0xBF, 0x3D, 0x53, 0xD1, 0xF7, 0x1C, 0xD3, 0xF3, 0x49, 0x10, 0xC5, 0xD6, 0x5E, 0x27, 0xEC, 0xDD, 0xB8, 0x20, 0x77, 0xBA, 0x3D, }, - 7, - false}, + 7}, {{ 0x8A, 0x2A, 0xFF, 0xBD, 0x1A, 0x1C, 0x5D, 0x1B, 0xDC, 0xCB, 0xB7, 0xF5, 0x48, 0xBA, 0x99, 0x5F, 0x96, 0x68, 0x06, 0xB3, 0xFD, 0x0C, 0x3A, 0x00, 0xFA, 0xE2, 0xE5, 0x2F, 0x3C, 0x85, 0x39, 0x89, }, - 145, - true}, + 145}, {{ 0x8A, 0x42, 0xEE, 0xAD, 0xBC, 0x8B, 0x21, 0xA3, 0x5C, 0x4B, 0x3A, 0xAD, 0xD7, 0xDF, 0xBC, 0xBD, 0x2E, 0xD1, 0xB1, 0xDA, 0x12, 0xE8, 0xC4, 0x5A, 0x53, 0x4D, 0xA9, 0x06, 0x07, 0xE5, 0x64, 0xFD, }, - 392, - true}, + 392}, {{ 0x8A, 0x90, 0x3B, 0x60, 0x0A, 0x08, 0x0B, 0x38, 0xDF, 0xE2, 0x0D, 0xFB, 0x6A, 0xCD, 0x23, 0x12, 0x2F, 0x64, 0x62, 0x0E, 0x58, 0x08, 0xB9, 0xFC, 0x86, 0x88, 0x95, 0x2F, 0xC1, 0xA3, 0x55, 0x9C, }, - 275, - true}, + 275}, {{ 0x8A, 0xB4, 0xE8, 0x85, 0x56, 0xCB, 0xF8, 0x64, 0xA5, 0xE9, 0xFD, 0x50, 0x17, 0x1C, 0xD4, 0xED, 0x84, 0x24, 0xE8, 0xF0, 0x80, 0x1B, 0x99, 0xE2, 0x36, 0xC8, 0x10, 0x91, 0x59, 0x50, 0xAE, 0x4B, }, - 370, - true}, + 370}, {{ 0x8A, 0xDB, 0x23, 0x85, 0x54, 0xA0, 0xCB, 0xFC, 0x3A, 0x11, 0xFE, 0xCC, 0x18, 0x3E, 0x3C, 0xD2, 0xC2, 0x3D, 0x25, 0xE7, 0x89, 0x4C, 0xF2, 0xBB, 0xAE, 0x58, 0xEB, 0x70, 0xA4, 0x4E, 0x7C, 0xF3, }, - 234, - true}, + 234}, {{ 0x8B, 0x49, 0x50, 0x6A, 0x34, 0x61, 0x06, 0x3E, 0xA8, 0xCC, 0x13, 0xFF, 0xCE, 0x2B, 0x58, 0x1D, 0xE1, 0x5A, 0x94, 0xB9, 0x57, 0x09, 0x2A, 0x93, 0x12, 0x34, 0x67, 0xB8, 0x9E, 0xD8, 0x02, 0xE2, }, - 375, - true}, + 375}, {{ 0x8B, 0xB5, 0x93, 0xA9, 0x3B, 0xE1, 0xD0, 0xE8, 0xA8, 0x22, 0xBB, 0x88, 0x7C, 0x54, 0x78, 0x90, 0xC3, 0xE7, 0x06, 0xAA, 0xD2, 0xDA, 0xB7, 0x62, 0x54, 0xF9, 0x7F, 0xB3, 0x6B, 0x82, 0xFC, 0x26, }, - 175, - false}, + 175}, {{ 0x8B, 0xEA, 0x76, 0xEB, 0xD6, 0x13, 0x7A, 0xFF, 0x9F, 0x1E, 0xCC, 0x3C, 0x08, 0xCA, 0xF1, 0xDE, 0xC4, 0x7D, 0xB9, 0x16, 0x90, 0xD5, 0x75, 0x4C, 0x4E, 0x9F, 0x15, 0x23, 0x2C, 0x0A, 0x2E, 0x78, }, - 418, - true}, + 418}, {{ 0x8D, 0x41, 0x7D, 0xB2, 0xDD, 0x8B, 0xF5, 0xE3, 0x08, 0x4D, 0x1E, 0x3F, 0x19, 0x6D, 0x58, 0x38, 0x49, 0xD8, 0x1B, 0xDD, 0x4C, 0x00, 0xC7, 0x0B, 0x9D, 0x39, 0x36, 0x9E, 0x96, 0xB8, 0xC7, 0x82, }, - 495, - false}, + 495}, {{ 0x8D, 0x76, 0x77, 0x64, 0xB3, 0xCB, 0xDA, 0x08, 0x92, 0x9D, 0x07, 0x2A, 0x22, 0xA5, 0x61, 0xF4, 0xDC, 0xDD, 0x1B, 0xC5, 0x7D, 0x3C, 0xBD, 0xDC, 0x94, 0x8C, 0x47, 0xD2, 0xB4, 0x7F, 0x91, 0x22, }, - 17, - false}, + 17}, {{ 0x8D, 0x77, 0x5A, 0x4F, 0x93, 0xCD, 0x20, 0xC1, 0x83, 0x06, 0x14, 0x4F, 0x42, 0xB5, 0x69, 0xFC, 0x2A, 0x89, 0x7E, 0xAE, 0xAE, 0xC3, 0xD3, 0xEA, 0x3C, 0xB0, 0x25, 0xD1, 0xAD, 0x4D, 0x28, 0xE7, }, - 384, - true}, + 384}, {{ 0x8E, 0x15, 0xD4, 0x26, 0xCD, 0x04, 0x89, 0x8F, 0x21, 0x8B, 0xE2, 0xE5, 0xFE, 0x37, 0x84, 0xF3, 0x75, 0x09, 0x4C, 0xC4, 0x35, 0xDC, 0x61, 0xAD, 0x86, 0xC4, 0xA3, 0xC0, 0x15, 0x11, 0xDB, 0xE1, }, - 439, - true}, + 439}, {{ 0x8E, 0x80, 0x46, 0xEC, 0x4C, 0xAC, 0x01, 0x5A, 0x50, 0x7C, 0xE0, 0xD2, 0xD0, 0x15, 0x4A, 0x4B, 0x40, 0xE8, 0xE4, 0x2B, 0x31, 0x65, 0xCF, 0xA5, 0x46, 0x57, 0x14, 0x35, 0x11, 0x2D, 0x17, 0xE5, }, - 463, - false}, + 463}, {{ 0x8E, 0x8B, 0x56, 0xF5, 0x91, 0x8A, 0x25, 0xBD, 0x85, 0xDC, 0xE7, 0x66, 0x63, 0xFD, 0x94, 0xCC, 0x23, 0x69, 0x0F, 0x10, 0xEA, 0x95, 0x86, 0x61, 0x31, 0x71, 0xC6, 0xF8, 0x37, 0x88, 0x90, 0xD5, }, - 239, - true}, + 239}, {{ 0x8E, 0xD5, 0xB4, 0xC0, 0x41, 0xB6, 0xB2, 0x93, 0xC0, 0xE6, 0x41, 0x30, 0x15, 0x06, 0x6D, 0x31, 0x84, 0x83, 0xC9, 0x01, 0xFF, 0x69, 0xE8, 0x6A, 0x52, 0x1D, 0x0C, 0xB2, 0x55, 0x69, 0xF3, 0xE8, }, - 228, - true}, + 228}, {{ 0x8F, 0xD1, 0x12, 0xC3, 0xC8, 0x37, 0x0F, 0x14, 0x7D, 0x5C, 0xCD, 0x3A, 0x7D, 0x86, 0x5E, 0xB8, 0xDD, 0x54, 0x07, 0x83, 0xBA, 0xC6, 0x9F, 0xC6, 0x00, 0x88, 0xE3, 0x74, 0x3F, 0xF3, 0x33, 0x78, }, - 77, - false}, + 77}, {{ 0x90, 0x91, 0xE3, 0x1F, 0xE9, 0x25, 0x46, 0xA5, 0xF5, 0xE1, 0xB3, 0xED, 0x40, 0x71, 0xF4, 0x44, 0x0B, 0x84, 0x0C, 0x1E, 0x80, 0xDB, 0xFC, 0xBA, 0x7A, 0x7E, 0xC6, 0xD5, 0x82, 0x5F, 0x0B, 0x24, }, - 509, - true}, + 509}, {{ 0x91, 0x19, 0xE2, 0xF4, 0x13, 0x57, 0x97, 0x77, 0x95, 0x49, 0x91, 0x70, 0x3E, 0xEE, 0x23, 0xA0, 0x45, 0x23, 0xA3, 0x12, 0xB5, 0xC6, 0x5F, 0x7F, 0x93, 0x74, 0xAA, 0x31, 0x00, 0xEB, 0xD8, 0xE7, }, - 336, - true}, + 336}, {{ 0x91, 0x31, 0x19, 0xF2, 0xCD, 0x3F, 0x48, 0xAC, 0xA7, 0x4E, 0xA6, 0x44, 0x3E, 0xE5, 0x0E, 0x0D, 0xE1, 0x20, 0x2D, 0x9C, 0x54, 0xF3, 0x36, 0xDC, 0x93, 0x00, 0xAF, 0xFE, 0x97, 0xD4, 0x57, 0x7C, }, - 394, - true}, + 394}, {{ 0x91, 0x50, 0x86, 0xCC, 0xD4, 0xED, 0x1E, 0xA7, 0x49, 0xB4, 0x27, 0xF6, 0xB0, 0xCE, 0xB4, 0xA0, 0xEF, 0x5B, 0x4A, 0x1C, 0xF1, 0x80, 0x70, 0x53, 0x9C, 0x0F, 0x2A, 0x75, 0x81, 0x85, 0xA3, 0x82, }, - 224, - true}, + 224}, {{ 0x92, 0x7A, 0x1B, 0x85, 0x62, 0x28, 0x05, 0x76, 0xD0, 0x48, 0xC5, 0x03, 0x21, 0xAD, 0xA4, 0x3D, 0x87, 0x03, 0xD2, 0xD9, 0x52, 0x1A, 0x18, 0xC2, 0x8B, 0x8C, 0x46, 0xCC, 0x6A, 0xAE, 0x4E, 0xFD, }, - 99, - false}, + 99}, {{ 0x92, 0xC4, 0x68, 0x79, 0x62, 0x6E, 0xF2, 0xCC, 0x1E, 0xCE, 0xA5, 0x0C, 0x72, 0xFB, 0x5E, 0x38, 0x58, 0x44, 0x09, 0x5F, 0x21, 0xCB, 0xF3, 0xB2, 0x83, 0xCB, 0x82, 0xE6, 0xB9, 0xFC, 0x6A, 0x58, }, - 111, - false}, + 111}, {{ 0x93, 0x18, 0x22, 0x6F, 0x8C, 0x83, 0xAF, 0xE4, 0x7F, 0x5F, 0x47, 0xC2, 0x4F, 0x59, 0xCE, 0x12, 0xDB, 0xA8, 0xC7, 0x3B, 0x18, 0x1B, 0xEE, 0x6B, 0x2E, 0xA1, 0xF4, 0x0A, 0x06, 0xBC, 0x18, 0x69, }, - 49, - false}, + 49}, {{ 0x93, 0x1F, 0x1C, 0xF0, 0x3A, 0x6F, 0x84, 0xC3, 0x0F, 0xF3, 0xAD, 0x86, 0x9B, 0xE3, 0xC2, 0x1A, 0x41, 0x01, 0x91, 0xCC, 0x98, 0xAC, 0x0A, 0xFC, 0x9D, 0x4E, 0x8B, 0x89, 0xBD, 0x86, 0x9D, 0xDC, }, - 319, - true}, + 319}, {{ 0x93, 0x65, 0x7F, 0x85, 0x30, 0xC5, 0x96, 0xBF, 0x90, 0x9E, 0x50, 0xDA, 0x7D, 0x8D, 0x9C, 0xBB, 0x36, 0xB8, 0x24, 0xCC, 0x16, 0xAB, 0x58, 0x91, 0x37, 0xE1, 0x43, 0x80, 0x11, 0xBC, 0x99, 0x01, }, - 282, - true}, + 282}, {{ 0x93, 0x92, 0xAE, 0x21, 0x49, 0x92, 0x4A, 0xDE, 0x37, 0xE6, 0x45, 0xDB, 0xA1, 0xFF, 0x4B, 0xDD, 0xDC, 0xDA, 0x2B, 0x29, 0x1B, 0x60, 0x97, 0x66, 0x9D, 0x2A, 0xFA, 0x5C, 0x7A, 0x37, 0x26, 0x19, }, - 76, - true}, + 76}, {{ 0x93, 0xA9, 0xB3, 0xC9, 0x6A, 0xAE, 0x1C, 0xD6, 0x61, 0x21, 0x5D, 0x0C, 0x2A, 0x06, 0x5D, 0xA9, 0x63, 0xD7, 0x16, 0x0D, 0x1C, 0x69, 0x46, 0x21, 0xBC, 0xB2, 0x8C, 0x40, 0x6D, 0xF6, 0x4D, 0xB2, }, - 246, - true}, + 246}, {{ 0x94, 0x07, 0x2A, 0xD3, 0xF5, 0x8F, 0x70, 0xF9, 0x30, 0x98, 0xE5, 0xA5, 0xF6, 0xC0, 0x4C, 0x96, 0xC7, 0x10, 0xBD, 0x84, 0x9D, 0x83, 0x18, 0x49, 0x19, 0xAE, 0x90, 0xEB, 0x89, 0x0A, 0xE4, 0x00, }, - 85, - false}, + 85}, {{ 0x94, 0x15, 0xB2, 0x5D, 0xBA, 0x3B, 0xBD, 0x71, 0x14, 0x39, 0xE2, 0xA9, 0x96, 0x4B, 0x7A, 0x52, 0x56, 0xAF, 0xF3, 0xB0, 0x5C, 0x77, 0x2C, 0x8A, 0x34, 0xE6, 0xC9, 0x35, 0x66, 0xAB, 0xA6, 0x3A, }, - 478, - true}, + 478}, {{ 0x94, 0x2A, 0x69, 0x16, 0xA6, 0xE4, 0xAE, 0x52, 0x77, 0x11, 0xC5, 0x45, 0x02, 0x47, 0xA2, 0xA7, 0x4F, 0xB8, 0xE1, 0x56, 0xA8, 0x25, 0x4C, 0xA6, 0x6E, 0x73, 0x9A, 0x11, 0x49, 0x3B, 0xB4, 0x45, }, - 34, - false}, + 34}, {{ 0x94, 0xB9, 0x4B, 0xBF, 0x9A, 0x07, 0x26, 0xF1, 0x7B, 0x09, 0x73, 0xAF, 0x6D, 0x41, 0xE9, 0xFB, 0x2E, 0x70, 0x99, 0x65, 0x1B, 0xCB, 0xEF, 0xDD, 0xD9, 0x7B, 0x0A, 0x5F, 0x2A, 0xAB, 0xB0, 0xDD, }, - 391, - true}, + 391}, {{ 0x95, 0x1E, 0xE0, 0x46, 0xFA, 0x83, 0x31, 0x6E, 0x67, 0x86, 0xC0, 0x8C, 0x44, 0xF1, 0x3B, 0x4C, 0xA2, 0xEA, 0xD2, 0xD2, 0x64, 0x4D, 0x63, 0x31, 0x43, 0x91, 0xC0, 0xCC, 0x70, 0x88, 0x7D, 0x0D, }, - 185, - false}, + 185}, {{ 0x95, 0x2C, 0x20, 0x39, 0xC0, 0x24, 0x3E, 0xB5, 0x15, 0xDD, 0x73, 0xD8, 0x3F, 0xC3, 0x64, 0x31, 0x84, 0x87, 0x4F, 0xEB, 0x08, 0x62, 0xA9, 0x83, 0x77, 0x31, 0xED, 0x9B, 0x47, 0x42, 0xE1, 0x7A, }, - 44, - false}, + 44}, {{ 0x95, 0x46, 0xCE, 0x00, 0xE0, 0x3D, 0xD6, 0x1A, 0xCA, 0x58, 0xC5, 0xC8, 0xDB, 0xF3, 0x8A, 0x11, 0x1B, 0xAD, 0x64, 0x06, 0xC9, 0x1D, 0x74, 0x22, 0xE7, 0xF4, 0xC4, 0x0A, 0x0C, 0xB5, 0x8F, 0x18, }, - 347, - true}, + 347}, {{ 0x95, 0x73, 0x54, 0x73, 0xBD, 0x67, 0xA3, 0xB9, 0x5A, 0x8D, 0x5F, 0x90, 0xC5, 0xA2, 0x1A, 0xCE, 0x1E, 0x0D, 0x79, 0x47, 0x32, 0x06, 0x74, 0xD4, 0xAB, 0x84, 0x79, 0x72, 0xB9, 0x15, 0x44, 0xD2, }, - 259, - true}, + 259}, {{ 0x96, 0x35, 0x2D, 0x0A, 0xD8, 0x75, 0xC0, 0x27, 0xDB, 0x82, 0xD5, 0x99, 0xBA, 0xA8, 0xD4, 0x2E, 0x5C, 0x47, 0x26, 0x49, 0x98, 0x1E, 0xCE, 0xED, 0x3B, 0xFC, 0x65, 0xF4, 0xC8, 0x1F, 0xD5, 0xC1, }, - 526, - false}, + 526}, {{ 0x96, 0x47, 0x5B, 0x35, 0xAC, 0xB1, 0xC9, 0x30, 0x3A, 0x90, 0xBD, 0x1D, 0xBF, 0x57, 0x41, 0x8F, 0x78, 0xE2, 0x9A, 0xF1, 0x1C, 0x4D, 0xE8, 0xC8, 0xCB, 0xA2, 0xE5, 0xF9, 0x30, 0x9E, 0x38, 0xD4, }, - 316, - true}, + 316}, {{ 0x96, 0x7B, 0x0C, 0xD9, 0x3F, 0xCE, 0xF7, 0xF2, 0x7C, 0xE2, 0xC2, 0x45, 0x76, 0x7A, 0xE9, 0xB0, 0x5A, 0x77, 0x6B, 0x06, 0x49, 0xF9, 0x96, 0x5B, 0x62, 0x90, 0x96, 0x84, 0x69, 0x68, 0x68, 0x72, }, - 50, - false}, + 50}, {{ 0x96, 0x99, 0x22, 0x5C, 0x5D, 0xE5, 0x2E, 0x56, 0xCD, 0xD3, 0x2D, 0xF2, 0xE9, 0x6D, 0x1C, 0xFE, 0xA5, 0xAA, 0x3C, 0xA0, 0xBB, 0x52, 0xCD, 0x89, 0x33, 0xC2, 0x3B, 0x5C, 0x27, 0x44, 0x38, 0x20, }, - 139, - false}, + 139}, {{ 0x97, 0x2F, 0xBC, 0x6D, 0x55, 0xBF, 0xEF, 0xB1, 0xAB, 0xE3, 0x75, 0x8A, 0xD7, 0xD6, 0x7A, 0x34, 0x9B, 0xBE, 0xF8, 0x0C, 0x06, 0xF1, 0xD8, 0x50, 0x01, 0xDF, 0xB9, 0x10, 0x1B, 0x9A, 0xBC, 0x1B, }, - 425, - true}, + 425}, {{ 0x97, 0x36, 0xAC, 0x3B, 0x25, 0xD1, 0x6C, 0x45, 0xA4, 0x54, 0x18, 0xA9, 0x64, 0x57, 0x81, 0x56, 0x48, 0x0A, 0x8C, 0xC4, 0x34, 0x54, 0x1D, 0xDC, 0x5D, 0xD5, 0x92, 0x33, 0x22, 0x98, 0x68, 0xDE, }, - 66, - true}, + 66}, {{ 0x97, 0x9F, 0x6F, 0x6A, 0x8A, 0x41, 0xC4, 0x21, 0xCC, 0x67, 0x34, 0x73, 0xD5, 0x8A, 0x63, 0x79, 0x81, 0x7B, 0xE7, 0x3D, 0x2E, 0x52, 0x46, 0x98, 0xC8, 0x0F, 0xFB, 0x66, 0xA1, 0x49, 0xD0, 0x89, }, - 396, - true}, + 396}, {{ 0x98, 0x00, 0x8E, 0x2E, 0xDB, 0xB7, 0x2B, 0xAD, 0x42, 0xDA, 0x2F, 0xCB, 0x06, 0xAC, 0x1A, 0xAA, 0x0B, 0x2E, 0x6E, 0x0C, 0x72, 0xE8, 0xCA, 0x20, 0x4F, 0xBA, 0xFD, 0x1B, 0xB4, 0x87, 0x94, 0x41, }, - 238, - true}, + 238}, {{ 0x98, 0x09, 0x22, 0xEE, 0xE0, 0x7F, 0x86, 0xBC, 0x7F, 0x5E, 0x5E, 0x95, 0xD5, 0x7D, 0xB8, 0xBD, 0xAE, 0x68, 0xE1, 0x7A, 0x42, 0x1C, 0x4E, 0x72, 0xA9, 0x6A, 0x70, 0x8A, 0x87, 0x92, 0x01, 0x24, }, - 149, - true}, + 149}, {{ 0x98, 0x47, 0xE5, 0x65, 0x3E, 0x5E, 0x9E, 0x84, 0x75, 0x16, 0xE5, 0xCB, 0x81, 0x86, 0x06, 0xAA, 0x75, 0x44, 0xA1, 0x9B, 0xE6, 0x7F, 0xD7, 0x36, 0x6D, 0x50, 0x69, 0x88, 0xE8, 0xD8, 0x43, 0x47, }, - 486, - false}, + 486}, {{ 0x98, 0xB3, 0xF1, 0x0A, 0x02, 0x50, 0x41, 0x91, 0x0F, 0x19, 0x7C, 0xF1, 0x7C, 0xA0, 0xFC, 0xDF, 0xED, 0x75, 0xFB, 0x2C, 0x8C, 0x14, 0xA8, 0x43, 0xE0, 0x4D, 0x56, 0x56, 0xC9, 0xEB, 0xAC, 0x1A, }, - 235, - true}, + 235}, {{ 0x98, 0xCA, 0x29, 0xF3, 0x13, 0x38, 0x67, 0x21, 0xAF, 0xBF, 0x5D, 0x14, 0xF1, 0xAB, 0xCA, 0xA1, 0xDC, 0x63, 0xCC, 0x8D, 0x1F, 0xD7, 0xDC, 0x36, 0x1F, 0x6B, 0x01, 0x36, 0x89, 0x38, 0xF2, 0x4B, }, - 223, - true}, + 223}, {{ 0x99, 0x1B, 0x5E, 0xD1, 0xB2, 0xFD, 0x36, 0x4B, 0x9F, 0x63, 0x4B, 0x62, 0x4B, 0x30, 0x52, 0x03, 0xF2, 0x99, 0x08, 0xBE, 0x31, 0x8E, 0xF6, 0x39, 0x92, 0x22, 0xD8, 0xA3, 0xEF, 0x79, 0x90, 0xE5, }, - 299, - true}, + 299}, {{ 0x99, 0x33, 0x3C, 0x3A, 0x66, 0x5C, 0xF0, 0xEF, 0xBB, 0x74, 0x88, 0xB3, 0x80, 0x7B, 0x8B, 0x65, 0xF8, 0x7B, 0x5B, 0x29, 0xD6, 0x88, 0x0F, 0x02, 0x8E, 0xDC, 0x28, 0x44, 0x2E, 0xEA, 0xE6, 0x69, }, - 434, - true}, + 434}, {{ 0x99, 0x62, 0xAB, 0x16, 0x99, 0xB0, 0xEB, 0x7C, 0x7E, 0x8A, 0x57, 0x8B, 0xC7, 0x98, 0x93, 0x04, 0x20, 0x31, 0xC1, 0x15, 0x8C, 0x63, 0x36, 0x13, 0x19, 0x9A, 0x90, 0xB9, 0x65, 0x2A, 0x2A, 0x75, }, - 462, - true}, + 462}, {{ 0x9A, 0xDB, 0x99, 0xC9, 0x3A, 0xB2, 0x56, 0xEC, 0xCA, 0x2B, 0x53, 0x50, 0xC7, 0x50, 0x48, 0xA8, 0x58, 0x4C, 0x12, 0xDF, 0xC2, 0x48, 0xE3, 0xF6, 0x0E, 0xA9, 0x35, 0x4C, 0x34, 0xEB, 0xFC, 0xCE, }, - 65, - true}, + 65}, {{ 0x9B, 0x21, 0x9D, 0x0F, 0xBF, 0xF3, 0x6A, 0x5F, 0xB3, 0x20, 0x90, 0x57, 0x19, 0x06, 0xBC, 0xEE, 0xA6, 0x86, 0x17, 0xC8, 0x33, 0xA3, 0xF6, 0x1B, 0x81, 0xE9, 0x62, 0xA8, 0xE6, 0x4D, 0xB8, 0xAF, }, - 217, - true}, + 217}, {{ 0x9C, 0x6F, 0x6A, 0x12, 0x3C, 0xBA, 0xA4, 0xEE, 0x34, 0xDB, 0xEC, 0xEE, 0xE2, 0x4C, 0x97, 0xD7, 0x38, 0x87, 0x8C, 0xB4, 0x23, 0xF3, 0xC2, 0x27, 0x39, 0x03, 0x42, 0x4F, 0x5D, 0x1F, 0x6D, 0xD5, }, - 135, - true}, + 135}, {{ 0x9D, 0x98, 0xA1, 0xFB, 0x60, 0x53, 0x8C, 0x4C, 0xC4, 0x85, 0x7F, 0xF1, 0xA8, 0xC8, 0x03, 0x4F, 0xAF, 0x6F, 0xC5, 0x92, 0x09, 0x3F, 0x61, 0x99, 0x94, 0xB2, 0xC8, 0x13, 0xD2, 0x50, 0xB8, 0x64, }, - 333, - true}, + 333}, {{ 0x9D, 0xC3, 0x8A, 0x9E, 0xDC, 0xF8, 0x28, 0x42, 0xB6, 0x74, 0xDA, 0x18, 0x6B, 0x6D, 0x62, 0x15, 0xAB, 0x9E, 0x2E, 0xC6, 0xD7, 0x2F, 0x57, 0xB0, 0x8A, 0x89, 0x27, 0x28, 0xC3, 0x14, 0x31, 0xF3, }, - 342, - true}, + 342}, {{ 0x9D, 0xD5, 0x5F, 0xC5, 0x73, 0xF5, 0x46, 0xCB, 0x6A, 0x38, 0x31, 0xD1, 0x11, 0x2D, 0x87, 0x10, 0xA6, 0xF4, 0xF8, 0x2D, 0xC8, 0x7F, 0x5F, 0xAE, 0x9D, 0x3A, 0x1A, 0x02, 0x8D, 0xD3, 0x6E, 0x4B, }, - 11, - true}, + 11}, {{ 0x9E, 0x5A, 0x34, 0xB0, 0x89, 0x29, 0xBC, 0x0A, 0x58, 0x1C, 0x89, 0x36, 0xAA, 0xFD, 0x6A, 0xB7, 0x51, 0x7B, 0xB1, 0x51, 0x88, 0xB4, 0xF6, 0xFC, 0x02, 0xC4, 0x59, 0x06, 0xF7, 0x15, 0x95, 0xB0, }, - 354, - true}, + 354}, {{ 0x9E, 0xA9, 0xFE, 0x27, 0x45, 0x37, 0xF4, 0xF9, 0x35, 0x64, 0x2C, 0xDE, 0x82, 0x4F, 0xD7, 0x7E, 0xB0, 0xE1, 0x25, 0xCF, 0x11, 0x8A, 0xB9, 0xB4, 0xC2, 0x19, 0xF6, 0xCB, 0xF9, 0x59, 0xB1, 0x8D, }, - 431, - true}, + 431}, {{ 0x9E, 0xCC, 0x51, 0x36, 0x8E, 0x86, 0xE3, 0x46, 0x0F, 0x66, 0xC2, 0x95, 0xE4, 0x94, 0x2D, 0xD5, 0x30, 0x80, 0xF2, 0x7B, 0x1E, 0x41, 0x0A, 0xFF, 0x2D, 0x1A, 0xA9, 0xD4, 0xE6, 0xBC, 0x7E, 0x7C, }, - 144, - true}, + 144}, {{ 0x9E, 0xFD, 0x91, 0x1D, 0x6F, 0xF4, 0x6F, 0x18, 0x31, 0x11, 0x1D, 0xF3, 0xC5, 0x4C, 0xD2, 0x61, 0x1C, 0xAE, 0x23, 0x98, 0xFF, 0x73, 0x86, 0xD1, 0xCB, 0x6B, 0x4F, 0x32, 0xE3, 0x33, 0x7E, 0xD6, }, - 407, - true}, + 407}, {{ 0xA0, 0x2F, 0xAF, 0xA1, 0x92, 0xC8, 0xCB, 0x81, 0xCB, 0x13, 0x41, 0x55, 0x4F, 0x9C, 0x05, 0xB7, 0x1C, 0xCA, 0x2A, 0x89, 0x0B, 0x0D, 0x12, 0x98, 0xD6, 0x83, 0x64, 0x7C, 0x96, 0x1E, 0xFB, 0xDF, }, - 523, - false}, + 523}, {{ 0xA1, 0x25, 0x74, 0xF4, 0xEB, 0x73, 0x95, 0xCC, 0x63, 0x0A, 0x15, 0xFE, 0xC8, 0xDB, 0x1C, 0x7C, 0x82, 0x8F, 0x66, 0x69, 0x9D, 0x98, 0x4C, 0x8C, 0x89, 0x7E, 0xCA, 0x44, 0xC8, 0x08, 0xF5, 0x5D, }, - 310, - true}, + 310}, {{ 0xA1, 0xD4, 0x5D, 0x06, 0x29, 0x73, 0x41, 0xB1, 0xF3, 0xA7, 0x35, 0xCF, 0xA3, 0x8F, 0x28, 0x3E, 0x68, 0x79, 0xFE, 0xC0, 0x62, 0x81, 0xA3, 0x61, 0xE5, 0xF4, 0x17, 0xCC, 0x70, 0xD2, 0x9D, 0xC9, }, - 424, - true}, + 424}, {{ 0xA2, 0x5A, 0x72, 0x14, 0xC2, 0xB6, 0xC8, 0x61, 0x42, 0xAD, 0xA3, 0x9D, 0xFF, 0x2D, 0x73, 0xD8, 0x65, 0xAA, 0x57, 0x84, 0x3F, 0xDD, 0x2D, 0xB7, 0x7B, 0x3F, 0xEB, 0xF8, 0x26, 0x83, 0xDE, 0x2D, }, - 240, - true}, + 240}, {{ 0xA2, 0xDC, 0x98, 0xCA, 0x7C, 0xBB, 0xEE, 0x18, 0x22, 0xB2, 0x5B, 0x26, 0x7B, 0xD5, 0xCA, 0x50, 0x2F, 0xA7, 0xB0, 0xCF, 0x4F, 0xFF, 0x07, 0x03, 0xEE, 0x6A, 0x41, 0x67, 0x03, 0xF3, 0xC7, 0xEA, }, - 334, - true}, + 334}, {{ 0xA3, 0x20, 0xF4, 0xD5, 0x34, 0xD7, 0xBE, 0x97, 0xC1, 0xAE, 0x8D, 0xD0, 0x49, 0x97, 0x35, 0xBC, 0x89, 0x5C, 0x32, 0x3A, 0xDD, 0x2D, 0x38, 0x8B, 0xFC, 0xCF, 0x66, 0x2C, 0x23, 0xD7, 0xF9, 0x9A, }, - 293, - false}, + 293}, {{ 0xA3, 0x78, 0x41, 0x9D, 0x1A, 0xE9, 0xEB, 0xD2, 0x7B, 0x22, 0x94, 0x80, 0x44, 0xC6, 0x84, 0xBA, 0x29, 0xBC, 0x08, 0x4B, 0x98, 0xF9, 0x65, 0xBE, 0x73, 0x26, 0x2F, 0x0F, 0x6A, 0xAA, 0x1C, 0x6F, }, - 307, - true}, + 307}, {{ 0xA4, 0x00, 0x3B, 0xD5, 0xBD, 0xD8, 0x94, 0xE0, 0x1A, 0x8E, 0x01, 0xE0, 0x6B, 0x62, 0xC7, 0xAA, 0x82, 0xF0, 0x3D, 0xE5, 0x25, 0x31, 0x33, 0x57, 0x0A, 0xAD, 0x4F, 0xD0, 0xE7, 0xD8, 0x1D, 0x3C, }, - 106, - true}, + 106}, {{ 0xA4, 0x95, 0xC8, 0xD1, 0x10, 0xE8, 0xB9, 0xE2, 0x00, 0xF3, 0x70, 0xAE, 0xDA, 0x3F, 0xF9, 0x2E, 0xE4, 0x3F, 0x8E, 0x3D, 0x4E, 0xC0, 0xDB, 0x1C, 0x0D, 0xC5, 0x8B, 0xD7, 0x62, 0x88, 0x0B, 0xA5, }, - 529, - false}, + 529}, {{ 0xA4, 0xB8, 0x9B, 0xB7, 0x06, 0x56, 0xEA, 0x49, 0x8F, 0x2D, 0x9E, 0x00, 0xA4, 0x97, 0xFD, 0xB9, 0xDC, 0xD2, 0x0B, 0x81, 0xB8, 0x93, 0x8E, 0x95, 0x2B, 0xBA, 0x2D, 0xF9, 0xF6, 0x57, 0x29, 0xC3, }, - 371, - true}, + 371}, {{ 0xA4, 0xCB, 0xF4, 0x85, 0x16, 0xAF, 0x31, 0x60, 0xEB, 0xC6, 0x2A, 0xCA, 0xC6, 0xE7, 0xF2, 0x58, 0x60, 0x9E, 0xD0, 0x89, 0x15, 0x35, 0x01, 0x0C, 0x16, 0x69, 0x24, 0x93, 0xA9, 0xFE, 0x1F, 0xBF, }, - 449, - true}, + 449}, {{ 0xA5, 0x1A, 0x2F, 0x3A, 0x05, 0x0E, 0x83, 0x8A, 0x50, 0x50, 0x69, 0x65, 0x78, 0xDB, 0xBE, 0xDA, 0xAC, 0x1A, 0x10, 0x7E, 0xE2, 0xD9, 0xD4, 0x8F, 0xAE, 0x50, 0x5D, 0x18, 0xD0, 0xDA, 0x5C, 0xF8, }, - 260, - true}, + 260}, {{ 0xA5, 0x20, 0x4D, 0xBB, 0x27, 0x54, 0xB9, 0x7E, 0x3C, 0x8A, 0x10, 0x4E, 0xAC, 0xB3, 0x74, 0xA6, 0x49, 0x8A, 0x43, 0x87, 0x73, 0xC7, 0x50, 0x77, 0xF0, 0x06, 0x3C, 0x2C, 0xEB, 0x25, 0xD2, 0xA2, }, - 305, - true}, + 305}, {{ 0xA5, 0x9D, 0x2F, 0x09, 0xC8, 0xB1, 0x68, 0xCD, 0x9A, 0xFA, 0x3B, 0xC3, 0xEB, 0x4D, 0xB0, 0xD7, 0xA4, 0x35, 0x88, 0xD5, 0x23, 0x28, 0x7F, 0x2B, 0x83, 0xA8, 0x22, 0xEB, 0x33, 0x70, 0x91, 0x70, }, - 453, - true}, + 453}, {{ 0xA6, 0xE1, 0x1F, 0xF1, 0x5E, 0xC3, 0x26, 0xA5, 0xE3, 0xF1, 0x8A, 0xD3, 0x3A, 0x05, 0x66, 0x94, 0xDC, 0x84, 0xC6, 0x99, 0x76, 0x6D, 0x02, 0x8A, 0x5A, 0xD0, 0xEF, 0xE1, 0xA8, 0xE5, 0x3A, 0xC7, }, - 67, - true}, + 67}, {{ 0xA6, 0xF1, 0xF9, 0xBF, 0x8A, 0x0A, 0x9D, 0xDC, 0x08, 0x0F, 0xB4, 0x9B, 0x1E, 0xFC, 0x3D, 0x1A, 0x1C, 0x2C, 0x32, 0xDC, 0x0E, 0x13, 0x6A, 0x5B, 0x00, 0xC9, 0x73, 0x16, 0xF2, 0xA3, 0xDC, 0x11, }, - 70, - true}, + 70}, {{ 0xA7, 0x4B, 0x4B, 0x6A, 0x2E, 0xB5, 0x5B, 0x98, 0x64, 0xC0, 0x4E, 0xCB, 0x16, 0x00, 0x3F, 0xF5, 0xDB, 0x5B, 0x51, 0xE4, 0x2C, 0xF8, 0x59, 0xF9, 0x5E, 0x9D, 0x0A, 0x1D, 0xD4, 0x64, 0x40, 0x96, }, - 364, - true}, + 364}, {{ 0xA7, 0x6E, 0x29, 0x49, 0xCB, 0x87, 0xF6, 0x23, 0x6B, 0x5F, 0x68, 0xC6, 0x90, 0x74, 0x75, 0x87, 0xD6, 0x44, 0x8E, 0xA2, 0x1C, 0xFE, 0xAD, 0x79, 0x50, 0x08, 0x4A, 0xC0, 0x15, 0x19, 0x0B, 0x25, }, - 455, - true}, + 455}, {{ 0xA7, 0x98, 0xD9, 0x2F, 0x76, 0xC9, 0xC6, 0x75, 0x5E, 0x5F, 0x55, 0xF8, 0x6C, 0xD1, 0x4A, 0xED, 0xCC, 0x06, 0x55, 0x37, 0x1E, 0x27, 0xCC, 0xDE, 0x03, 0x77, 0x74, 0x5C, 0xE3, 0xC5, 0x00, 0x13, }, - 356, - true}, + 356}, {{ 0xA7, 0xA8, 0xF0, 0x39, 0x89, 0x4F, 0x5F, 0x67, 0x5E, 0x92, 0xA7, 0x78, 0xE0, 0x08, 0xE4, 0x24, 0xC9, 0x41, 0x7D, 0xBA, 0x06, 0xA1, 0x73, 0x8B, 0x45, 0xB4, 0xE0, 0x8D, 0x36, 0xFC, 0x2D, 0x7C, }, - 220, - true}, + 220}, {{ 0xA7, 0xE3, 0x9B, 0xD7, 0xDF, 0x60, 0x9B, 0xEF, 0x32, 0x62, 0xBF, 0x3D, 0xB4, 0xDC, 0x8F, 0x38, 0x14, 0xE0, 0xDB, 0x5A, 0x7A, 0x52, 0x15, 0x6A, 0x6D, 0x0C, 0x35, 0xB4, 0xDA, 0xE8, 0xA6, 0xAD, }, - 301, - true}, + 301}, {{ 0xA8, 0x12, 0x93, 0x44, 0x5D, 0xB1, 0x96, 0xA2, 0x03, 0x0F, 0x9E, 0x45, 0x5F, 0xE3, 0xC7, 0x4A, 0x9A, 0x4F, 0x83, 0x17, 0xB0, 0x2B, 0x01, 0x40, 0x60, 0x27, 0xA8, 0x70, 0x81, 0x74, 0x43, 0x4C, }, - 15, - false}, + 15}, {{ 0xA8, 0x6B, 0xDA, 0xB8, 0xF4, 0x80, 0xB6, 0xEB, 0x89, 0x42, 0xAB, 0x91, 0x70, 0xBD, 0xD0, 0x99, 0x19, 0x71, 0xA7, 0xAD, 0x13, 0x5D, 0xFB, 0xBC, 0xB7, 0x28, 0x5F, 0x07, 0xA7, 0xD1, 0xE3, 0x8A, }, - 268, - true}, + 268}, {{ 0xA8, 0x74, 0x43, 0xB3, 0xD8, 0x96, 0xEB, 0x25, 0x7C, 0xCC, 0xE9, 0x9B, 0x95, 0xAD, 0xA9, 0xBC, 0x81, 0xB9, 0xDB, 0x4E, 0x31, 0x42, 0xAA, 0x9A, 0x99, 0xAF, 0x09, 0x42, 0xCB, 0x0A, 0x4A, 0x3A, }, - 120, - false}, + 120}, {{ 0xA9, 0x99, 0x72, 0xCE, 0x1F, 0x6C, 0x58, 0x1D, 0x00, 0x97, 0xF6, 0x26, 0x18, 0x06, 0x2E, 0x53, 0x15, 0x7B, 0x52, 0x76, 0xE1, 0xEC, 0x66, 0x51, 0xA3, 0x15, 0x70, 0x57, 0xF0, 0x57, 0xB3, 0x39, }, - 4, - true}, + 4}, {{ 0xAA, 0x1C, 0x2B, 0xED, 0xB1, 0xA5, 0x08, 0xBA, 0xAD, 0x7F, 0xB3, 0xF5, 0xE0, 0x28, 0x97, 0xB9, 0x07, 0xC7, 0x48, 0xDE, 0xA9, 0xB7, 0x90, 0x89, 0x04, 0xAA, 0xDB, 0xD0, 0x49, 0x7A, 0xAB, 0x6A, }, - 252, - true}, + 252}, {{ 0xAA, 0x26, 0x30, 0xA7, 0xB6, 0x17, 0xB0, 0x4D, 0x0A, 0x29, 0x4B, 0xAB, 0x7A, 0x8C, 0xAA, 0xA5, 0x01, 0x6E, 0x6D, 0xBE, 0x60, 0x48, 0x37, 0xA8, 0x3A, 0x85, 0x71, 0x9F, 0xAB, 0x66, 0x7E, 0xB5, }, - 93, - false}, + 93}, {{ 0xAB, 0x38, 0x76, 0xC3, 0xDA, 0x5D, 0xE0, 0xC9, 0xCF, 0x67, 0x36, 0x86, 0x8E, 0xE5, 0xB8, 0x8B, 0xF9, 0xBA, 0x1D, 0xFF, 0x9C, 0x9D, 0x72, 0xD2, 0xFE, 0x5A, 0x8D, 0x2F, 0x78, 0x30, 0x21, 0x66, }, - 265, - true}, + 265}, {{ 0xAB, 0x39, 0xA4, 0xB0, 0x25, 0x95, 0x56, 0x91, 0xA4, 0x02, 0x69, 0xF3, 0x53, 0xFA, 0x1D, 0x5C, 0xB9, 0x4E, 0xAF, 0x6C, 0x7E, 0xA9, 0x80, 0x84, 0x84, 0xBB, 0xBB, 0x62, 0xFD, 0x9F, 0x68, 0xF3, }, - 262, - true}, + 262}, {{ 0xAB, 0x5C, 0xDB, 0x33, 0x56, 0x39, 0x73, 0x56, 0xD6, 0xE6, 0x91, 0x97, 0x3C, 0x25, 0xB8, 0x61, 0x8B, 0x65, 0xD7, 0x6A, 0x90, 0x48, 0x6E, 0xA7, 0xA8, 0xA5, 0xC1, 0x77, 0x67, 0xF4, 0x67, 0x3A, }, - 160, - true}, + 160}, {{ 0xAB, 0x98, 0x49, 0x52, 0x76, 0xAD, 0xF1, 0xEC, 0xAF, 0xF2, 0x8F, 0x35, 0xC5, 0x30, 0x48, 0x78, 0x1E, 0x5C, 0x17, 0x18, 0xDA, 0xB9, 0xC8, 0xE6, 0x7A, 0x50, 0x4F, 0x4F, 0x6A, 0x51, 0x32, 0x8F, }, - 122, - false}, + 122}, {{ 0xAB, 0xCA, 0xDF, 0xA3, 0x5F, 0xF8, 0x35, 0xCB, 0x3A, 0x0A, 0x0B, 0x86, 0x40, 0x06, 0x22, 0xB8, 0x0D, 0x5E, 0x80, 0xC7, 0x65, 0xBC, 0x02, 0x7F, 0x1B, 0x1C, 0x4E, 0x0A, 0x62, 0x0F, 0x5E, 0x1C, }, - 451, - true}, + 451}, {{ 0xAC, 0x44, 0x7D, 0xED, 0xD0, 0x43, 0x2A, 0xAB, 0x9C, 0x07, 0x0F, 0x2C, 0xCA, 0x01, 0xB6, 0xDA, 0xB0, 0x9B, 0xEF, 0x07, 0xCF, 0x4C, 0xA6, 0xAA, 0xA7, 0x55, 0x63, 0x4F, 0x85, 0x7B, 0x31, 0x5A, }, - 479, - true}, + 479}, {{ 0xAC, 0xF6, 0x5E, 0x1D, 0x62, 0xCB, 0x58, 0xA2, 0xBA, 0xFD, 0x6F, 0xFA, 0xB4, 0x0F, 0xB8, 0x86, 0x99, 0xC4, 0x73, 0x97, 0xCF, 0x5C, 0xB4, 0x83, 0xD4, 0x2D, 0x69, 0xCA, 0xD3, 0x4C, 0xD4, 0x8B, }, - 24, - true}, + 24}, {{ 0xAC, 0xF7, 0xAD, 0x98, 0xE6, 0xF0, 0x65, 0x86, 0x6E, 0x6F, 0x8C, 0xDF, 0x0C, 0xEB, 0x6F, 0x74, 0x81, 0xF6, 0x95, 0x7B, 0x6D, 0xFF, 0x82, 0x3F, 0x6B, 0x94, 0xD7, 0x9F, 0x01, 0xA6, 0x1C, 0x39, }, - 382, - true}, + 382}, {{ 0xAD, 0x30, 0x4C, 0x88, 0x4A, 0x5D, 0x37, 0x6B, 0xD1, 0x95, 0x20, 0x9A, 0x14, 0xC3, 0x9E, 0x07, 0xF0, 0xD3, 0xF5, 0xCF, 0x89, 0x3D, 0x80, 0x2B, 0x05, 0x3E, 0x1B, 0x92, 0x6E, 0x55, 0xD7, 0x74, }, - 390, - true}, + 390}, {{ 0xAE, 0x20, 0x33, 0xB3, 0x08, 0x28, 0x25, 0xA7, 0x03, 0xE5, 0xA6, 0xAD, 0xC3, 0x22, 0x1A, 0x86, 0x85, 0x4A, 0xA4, 0x11, 0xDB, 0x04, 0x7D, 0xD5, 0xF5, 0x3E, 0xB8, 0x4A, 0xA1, 0x4B, 0xDC, 0x01, }, - 383, - true}, + 383}, {{ 0xAE, 0x56, 0xD8, 0x47, 0x97, 0x3D, 0x19, 0x93, 0x90, 0xE6, 0x6E, 0x40, 0x24, 0xC9, 0xF8, 0x7D, 0x87, 0x37, 0x1E, 0x8B, 0xA8, 0x87, 0x6A, 0xF8, 0x3D, 0x1E, 0x64, 0x4F, 0x54, 0x66, 0x47, 0x38, }, - 281, - true}, + 281}, {{ 0xAE, 0x7F, 0x96, 0x2C, 0xB9, 0xE6, 0xA7, 0xDB, 0xF7, 0xB8, 0x33, 0xFB, 0x18, 0xFA, 0x9B, 0x71, 0xA8, 0x91, 0x75, 0xDF, 0x94, 0x9C, 0x23, 0x2B, 0x6A, 0x9E, 0xF7, 0xCB, 0x3D, 0xF2, 0xBB, 0xFC, }, - 525, - false}, + 525}, {{ 0xAF, 0x11, 0x0F, 0x6B, 0x5A, 0xE8, 0xB7, 0x67, 0xEA, 0xC6, 0xE0, 0xAA, 0x27, 0x3F, 0x38, 0x16, 0xE7, 0xA4, 0x0A, 0x64, 0x4E, 0xDA, 0xCB, 0x43, 0x98, 0x14, 0x63, 0x56, 0xE7, 0x75, 0x09, 0xD6, }, - 386, - true}, + 386}, {{ 0xAF, 0x20, 0x7C, 0x61, 0xFD, 0x9C, 0x7C, 0xF9, 0x2C, 0x2A, 0xFE, 0x81, 0x54, 0x28, 0x2D, 0xC3, 0xF2, 0xCB, 0xF3, 0x2F, 0x75, 0xCD, 0x17, 0x28, 0x14, 0xC5, 0x2B, 0x03, 0xB7, 0xEB, 0xC2, 0x58, }, - 257, - true}, + 257}, {{ 0xAF, 0x6A, 0xB5, 0x1B, 0x7B, 0xAD, 0x1D, 0xED, 0xD5, 0x33, 0xEB, 0x59, 0x33, 0x2B, 0x62, 0x27, 0xD6, 0x55, 0x7F, 0x20, 0xB4, 0x44, 0x32, 0x16, 0xDB, 0x73, 0x5B, 0x92, 0x28, 0x0C, 0x7A, 0x44, }, - 337, - true}, + 337}, {{ 0xAF, 0xF9, 0x88, 0x90, 0x6D, 0xDE, 0x12, 0x95, 0x5D, 0x9B, 0xEB, 0xBF, 0x92, 0x8F, 0xDC, 0xC3, 0x1C, 0xCE, 0x32, 0x8D, 0x5B, 0x93, 0x84, 0xF2, 0x1C, 0x89, 0x41, 0xCA, 0x26, 0xE2, 0x03, 0x91, }, - 31, - false}, + 31}, {{ 0xB0, 0x3D, 0x87, 0xB0, 0x56, 0xD0, 0x8C, 0xC9, 0xD4, 0xE6, 0x75, 0xEF, 0x19, 0xCA, 0x83, 0xAB, 0x53, 0x53, 0x21, 0x68, 0xA8, 0x25, 0x85, 0x98, 0xBE, 0x72, 0xE6, 0xD8, 0x5C, 0x7D, 0xD7, 0xC1, }, - 25, - false}, + 25}, {{ 0xB0, 0x83, 0xFF, 0x53, 0x6F, 0x7F, 0x48, 0xA9, 0x08, 0x1E, 0x29, 0x4A, 0x01, 0x87, 0xB5, 0x3E, 0x81, 0x97, 0x71, 0x40, 0x2D, 0x9D, 0x48, 0x10, 0x30, 0x6D, 0xE0, 0x31, 0x02, 0x4E, 0x5F, 0x46, }, - 412, - true}, + 412}, {{ 0xB0, 0xF6, 0xF1, 0x5B, 0x48, 0x17, 0xEB, 0xE6, 0xFE, 0x0B, 0x4B, 0xFC, 0xD7, 0xD3, 0xAC, 0xE4, 0xC7, 0x58, 0xB0, 0xAB, 0x6F, 0x8A, 0x9D, 0xA2, 0xED, 0x92, 0xE6, 0x18, 0x23, 0x9D, 0x9C, 0x98, }, - 142, - true}, + 142}, {{ 0xB1, 0x12, 0x41, 0x42, 0xA5, 0xA1, 0xA5, 0xA2, 0x88, 0x19, 0xC7, 0x35, 0x34, 0x0E, 0xFF, 0x8C, 0x9E, 0x2F, 0x81, 0x68, 0xFE, 0xE3, 0xBA, 0x18, 0x7F, 0x25, 0x3B, 0xC1, 0xA3, 0x92, 0xD7, 0xE2, }, - 72, - true}, + 72}, {{ 0xB1, 0x5A, 0xC9, 0x56, 0x12, 0x04, 0x75, 0x61, 0x24, 0xB9, 0xC4, 0xD3, 0xFE, 0x40, 0x6D, 0x93, 0x83, 0x3F, 0xF6, 0x66, 0x52, 0xF6, 0x7F, 0xBF, 0x13, 0x9F, 0x5B, 0xBF, 0x03, 0x0A, 0x0E, 0x64, }, - 528, - false}, + 528}, {{ 0xB1, 0x6C, 0xB1, 0xBA, 0x52, 0x9A, 0x39, 0xE2, 0xDF, 0xD5, 0x3B, 0x3F, 0xF5, 0xA7, 0x9F, 0x19, 0x04, 0x61, 0x4D, 0x83, 0xE3, 0x13, 0x04, 0xF0, 0x27, 0x8B, 0xB4, 0x0B, 0x38, 0xCF, 0x78, 0x24, }, - 432, - true}, + 432}, {{ 0xB1, 0xBE, 0x0F, 0x7A, 0x5E, 0x63, 0x8B, 0x55, 0x9D, 0x8B, 0x52, 0x1F, 0xEF, 0x60, 0x17, 0xAD, 0x8F, 0xA1, 0x6E, 0xB0, 0x54, 0x8E, 0x84, 0x6B, 0x2A, 0xC4, 0xB4, 0x1D, 0x89, 0xB4, 0x1F, 0x14, }, - 211, - true}, + 211}, {{ 0xB2, 0x13, 0xA9, 0xCB, 0xAA, 0x9A, 0x88, 0x31, 0xAC, 0x0B, 0x3A, 0xA8, 0x0E, 0x9D, 0x15, 0x85, 0x6C, 0xD4, 0x3A, 0x7C, 0xC2, 0xE0, 0xBA, 0xC5, 0xFC, 0xB8, 0x4A, 0x24, 0x75, 0x1A, 0x8A, 0x78, }, - 450, - true}, + 450}, {{ 0xB2, 0x1D, 0x2A, 0x74, 0x33, 0x18, 0x71, 0x2B, 0xA1, 0x6F, 0x39, 0x91, 0x9D, 0x96, 0x1A, 0x4B, 0xAF, 0xBA, 0x3B, 0xCA, 0x9A, 0x43, 0xA7, 0x5B, 0x1F, 0xCF, 0xE2, 0x2C, 0x5D, 0x70, 0xCA, 0xBA, }, - 107, - false}, + 107}, {{ 0xB2, 0xDE, 0xF5, 0x36, 0x2A, 0xD3, 0xFA, 0xCD, 0x04, 0xBD, 0x29, 0x04, 0x7A, 0x43, 0x84, 0x4F, 0x76, 0x70, 0x34, 0xEA, 0x48, 0x92, 0xF8, 0x0E, 0x56, 0xBE, 0xE6, 0x90, 0x24, 0x3E, 0x25, 0x02, }, - 48, - true}, + 48}, {{ 0xB2, 0xF7, 0x29, 0x8B, 0x52, 0xBF, 0x2C, 0x3C, 0xAC, 0x4D, 0xDF, 0xE7, 0x2D, 0xE4, 0xD6, 0x82, 0xAC, 0x58, 0x95, 0x75, 0x95, 0x98, 0x2F, 0x2B, 0x62, 0x30, 0x1A, 0xF5, 0x97, 0xC6, 0x99, 0xC5, }, - 507, - true}, + 507}, {{ 0xB3, 0x18, 0x2E, 0x28, 0x9A, 0xE3, 0x4D, 0xDF, 0x2B, 0xE6, 0x43, 0xAB, 0x79, 0xC2, 0x44, 0x30, 0x16, 0x05, 0xFA, 0x0F, 0x1E, 0xAA, 0xE6, 0xD1, 0x0F, 0xB9, 0x29, 0x60, 0x0A, 0xF8, 0x4D, 0xF0, }, - 355, - true}, + 355}, {{ 0xB4, 0x29, 0x6D, 0x5F, 0xE6, 0x0E, 0x52, 0xF3, 0xF0, 0xFF, 0x99, 0xDA, 0x75, 0xAF, 0x5E, 0x7E, 0x62, 0x59, 0x9F, 0x99, 0xEB, 0xE0, 0xFA, 0x41, 0x3F, 0x66, 0xE6, 0xB4, 0x25, 0xC3, 0xD0, 0x9F, }, - 348, - true}, + 348}, {{ 0xB4, 0x89, 0xCC, 0xB2, 0x24, 0xB9, 0xA6, 0xB8, 0x1D, 0xD2, 0x74, 0xCE, 0xAF, 0x52, 0x09, 0xC2, 0x52, 0x99, 0x8C, 0x9A, 0x76, 0xAF, 0x48, 0xE4, 0xF4, 0xC5, 0x0A, 0x07, 0x28, 0x46, 0x18, 0x25, }, - 465, - true}, + 465}, {{ 0xB4, 0xA0, 0x39, 0xEA, 0xFC, 0x43, 0x10, 0xBA, 0x9B, 0xDE, 0x09, 0x3E, 0xDB, 0x8F, 0x9D, 0x9D, 0x0B, 0x3D, 0x4C, 0x7C, 0x00, 0x4D, 0x48, 0x28, 0x8C, 0x35, 0xDB, 0xCC, 0x19, 0x46, 0x7D, 0x18, }, - 82, - true}, + 82}, {{ 0xB5, 0xEC, 0x35, 0xBA, 0xAB, 0x53, 0x88, 0x84, 0xCF, 0xA8, 0xDD, 0x97, 0x37, 0x6B, 0x10, 0x2F, 0x03, 0xE5, 0x3B, 0x48, 0x2C, 0x64, 0x10, 0x0C, 0x25, 0x07, 0x22, 0xAE, 0x9B, 0x04, 0x2C, 0xBC, }, - 430, - true}, + 430}, {{ 0xB6, 0x38, 0xCF, 0xF0, 0x5C, 0x8A, 0x83, 0x27, 0x58, 0xED, 0xC3, 0x02, 0x8A, 0xF9, 0xE2, 0xD5, 0x55, 0x14, 0x56, 0x8B, 0xC6, 0xBB, 0x34, 0xAB, 0x36, 0xD1, 0x40, 0xB9, 0x7A, 0xC6, 0xB1, 0x2D, }, - 68, - true}, + 68}, {{ 0xB6, 0x56, 0xA4, 0x34, 0x38, 0x31, 0xA2, 0xAC, 0xF1, 0x1E, 0xEA, 0xBC, 0x3A, 0x44, 0xB9, 0x70, 0x25, 0xFF, 0xFB, 0xA2, 0xB9, 0x10, 0xDA, 0x87, 0x14, 0xCF, 0x82, 0x7D, 0x81, 0xBE, 0x10, 0xC9, }, - 408, - true}, + 408}, {{ 0xB7, 0x38, 0x29, 0x0C, 0xC0, 0x85, 0x47, 0xE7, 0x9A, 0xC6, 0x7F, 0x83, 0x1E, 0xBB, 0x33, 0x54, 0x7C, 0x4E, 0x7D, 0xB4, 0x51, 0x4E, 0x2D, 0x29, 0x88, 0xC2, 0x3C, 0x44, 0x13, 0x40, 0xEB, 0x41, }, - 207, - false}, + 207}, {{ 0xB7, 0x40, 0x8B, 0x4D, 0x2B, 0xE0, 0x23, 0x8B, 0xA3, 0x70, 0x04, 0xDD, 0x34, 0xE2, 0x76, 0xC6, 0x01, 0x9B, 0xD2, 0xF2, 0x4C, 0x9D, 0xB7, 0xD4, 0x98, 0x0F, 0x5F, 0x6C, 0x35, 0x9A, 0x4B, 0xCC, }, - 496, - false}, + 496}, {{ 0xB8, 0x9B, 0xCB, 0xB8, 0xAC, 0xD4, 0x74, 0xC1, 0xBE, 0xA7, 0xDA, 0xD6, 0x50, 0x37, 0xF4, 0x8D, 0xCE, 0xCC, 0x9D, 0xFA, 0xA0, 0x61, 0x2C, 0x3C, 0x24, 0x45, 0x95, 0x64, 0x19, 0xDF, 0x32, 0xFE, }, - 475, - true}, + 475}, {{ 0xB9, 0x18, 0x2F, 0x52, 0xAF, 0x0D, 0xD1, 0x8E, 0x3A, 0x99, 0xEB, 0xBA, 0xE7, 0x88, 0x3D, 0x4E, 0x4C, 0xC7, 0xFE, 0x2F, 0x81, 0xFA, 0xD0, 0xD3, 0x6C, 0xA6, 0x61, 0xEF, 0xC3, 0x2D, 0x0A, 0x92, }, - 312, - true}, + 312}, {{ 0xB9, 0x4C, 0x19, 0x83, 0x00, 0xCE, 0xC5, 0xC0, 0x57, 0xAD, 0x07, 0x27, 0xB7, 0x0B, 0xBE, 0x91, 0x81, 0x69, 0x92, 0x25, 0x64, 0x39, 0xA7, 0xB3, 0x2F, 0x45, 0x98, 0x11, 0x9D, 0xDA, 0x9C, 0x97, }, - 178, - false}, + 178}, {{ 0xBB, 0x0C, 0xE7, 0x04, 0x03, 0x14, 0xA1, 0x43, 0xDC, 0xD1, 0x0E, 0x65, 0xCC, 0xAE, 0xEF, 0x70, 0x10, 0xE1, 0xB7, 0x84, 0xD1, 0x5D, 0x19, 0x5D, 0x77, 0xB5, 0x60, 0x19, 0x56, 0xBF, 0x9E, 0x3F, }, - 541, - false}, + 541}, {{ 0xBB, 0x41, 0x28, 0xEC, 0x96, 0x20, 0xF2, 0xD2, 0xA4, 0x9C, 0xE8, 0xE2, 0xC4, 0xE2, 0x57, 0xAE, 0xBA, 0xD9, 0x3A, 0x0F, 0x11, 0xC5, 0x6B, 0x5F, 0xA4, 0xB0, 0x0E, 0x23, 0x75, 0x9F, 0xA3, 0x9D, }, - 105, - false}, + 105}, {{ 0xBB, 0x52, 0x08, 0x6D, 0x06, 0x39, 0xE8, 0xDB, 0x33, 0x27, 0x75, 0xAC, 0x8F, 0x4E, 0x84, 0x35, 0xD9, 0x2C, 0xEB, 0x00, 0xF4, 0xE2, 0x4F, 0x28, 0xFC, 0x0E, 0xAB, 0xE2, 0x40, 0x77, 0x2E, 0x80, }, - 201, - false}, + 201}, {{ 0xBC, 0xCE, 0x8E, 0x2B, 0xBA, 0xEE, 0x71, 0xB6, 0x35, 0x8D, 0xDD, 0x64, 0x1C, 0xBB, 0xFC, 0x25, 0xDE, 0x45, 0x40, 0x03, 0x00, 0x62, 0x71, 0xF7, 0x5B, 0x50, 0xB7, 0x26, 0xD6, 0x7C, 0x3B, 0xC9, }, - 243, - true}, + 243}, {{ 0xBC, 0xFB, 0x44, 0xAA, 0xB9, 0xAD, 0x02, 0x10, 0x15, 0x70, 0x6B, 0x41, 0x21, 0xEA, 0x76, 0x1C, 0x81, 0xC9, 0xE8, 0x89, 0x67, 0x59, 0x0F, 0x6F, 0x94, 0xAE, 0x74, 0x4D, 0xC8, 0x8B, 0x78, 0xFB, }, - 23, - false}, + 23}, {{ 0xBD, 0x15, 0x3E, 0xD7, 0xB0, 0x43, 0x4F, 0x68, 0x86, 0xB1, 0x7B, 0xCE, 0x8B, 0xBE, 0x84, 0xED, 0x34, 0x0C, 0x71, 0x32, 0xD7, 0x02, 0xA8, 0xF4, 0xFA, 0x31, 0x8F, 0x75, 0x6E, 0xCB, 0xD6, 0xF3, }, - 71, - false}, + 71}, {{ 0xBD, 0xAC, 0xCB, 0xF2, 0xE8, 0xB2, 0x7C, 0x0C, 0x02, 0xA6, 0x89, 0xEE, 0x86, 0x6C, 0x9B, 0x86, 0xEC, 0x04, 0x44, 0x2A, 0xFC, 0xDD, 0xDD, 0x5D, 0x4E, 0xC3, 0x6D, 0xEF, 0x21, 0xE7, 0x61, 0xDD, }, - 539, - false}, + 539}, {{ 0xBE, 0x32, 0x80, 0xC6, 0x86, 0x3C, 0x77, 0x0A, 0x33, 0xC9, 0x04, 0x0B, 0xD9, 0x7D, 0x55, 0x40, 0xB2, 0x16, 0xD1, 0xD9, 0x1D, 0xB8, 0xB0, 0x88, 0xCE, 0xAC, 0x11, 0x97, 0xDA, 0xE1, 0xD6, 0x60, }, - 501, - true}, + 501}, {{ 0xBE, 0x3D, 0xB7, 0xB7, 0x9B, 0xFE, 0x57, 0x9D, 0xCF, 0x9B, 0x07, 0xCA, 0x4C, 0xAD, 0x75, 0xAF, 0xF1, 0x69, 0x75, 0x56, 0x8E, 0x5B, 0x45, 0xCF, 0xCA, 0xE4, 0xD6, 0x1F, 0xB6, 0x31, 0x75, 0xA8, }, - 57, - false}, + 57}, {{ 0xBE, 0xDD, 0x8B, 0xC9, 0x7E, 0xA8, 0x64, 0x97, 0x19, 0x5A, 0x07, 0x8A, 0x99, 0x9A, 0x23, 0x7A, 0x06, 0x0A, 0xEB, 0xAE, 0x07, 0xBC, 0x0A, 0x0B, 0x9B, 0x77, 0x89, 0x82, 0xBA, 0x5F, 0x62, 0xF4, }, - 372, - true}, + 372}, {{ 0xBF, 0x01, 0xC3, 0x5F, 0x33, 0x71, 0x13, 0xF1, 0x67, 0xB4, 0xA5, 0x01, 0x86, 0x76, 0x5E, 0x7B, 0x1E, 0x38, 0x90, 0xAF, 0x58, 0x63, 0x28, 0xF1, 0x85, 0xCD, 0x0D, 0x6B, 0xAE, 0x81, 0x35, 0x21, }, - 415, - true}, + 415}, {{ 0xBF, 0xE8, 0x29, 0x09, 0x87, 0x2E, 0x44, 0x34, 0xF1, 0x15, 0xC5, 0x1A, 0x56, 0x16, 0x80, 0x19, 0x59, 0x4D, 0x0E, 0x03, 0xDC, 0xA3, 0x63, 0xD9, 0xF3, 0xB4, 0x83, 0x9D, 0x0B, 0xAB, 0xCD, 0xE5, }, - 404, - true}, + 404}, {{ 0xC0, 0x6C, 0x87, 0x2F, 0xC2, 0xD0, 0xAC, 0x08, 0xD7, 0x8D, 0x42, 0x19, 0x81, 0xFB, 0xDA, 0x4E, 0x35, 0x50, 0x0D, 0x09, 0x46, 0xF7, 0x98, 0x94, 0xED, 0xD2, 0x1A, 0xC2, 0x9D, 0xEC, 0x07, 0x19, }, - 232, - true}, + 232}, {{ 0xC0, 0x71, 0x35, 0xF6, 0xB4, 0x52, 0x39, 0x82, 0x64, 0xA4, 0x77, 0x6D, 0xBD, 0x0A, 0x6A, 0x30, 0x7C, 0x60, 0xA3, 0x6F, 0x96, 0x7B, 0xD2, 0x63, 0x21, 0xDC, 0xB8, 0x17, 0xB5, 0xC0, 0xC4, 0x81, }, - 167, - true}, + 167}, {{ 0xC1, 0xAD, 0x1B, 0x18, 0x98, 0xEC, 0x39, 0x50, 0x48, 0xDF, 0x07, 0x0B, 0xFA, 0x21, 0x7E, 0x25, 0xC9, 0x13, 0xBE, 0xD8, 0xCA, 0x6B, 0x73, 0xDE, 0x08, 0x55, 0x28, 0x84, 0x6A, 0x01, 0x03, 0xC1, }, - 124, - false}, + 124}, {{ 0xC2, 0xB3, 0xC3, 0x1A, 0x4A, 0x29, 0x85, 0x0A, 0xA8, 0xF3, 0xCF, 0x47, 0x2A, 0x11, 0x69, 0xFF, 0x71, 0xB4, 0x16, 0x57, 0x9F, 0x6A, 0x44, 0x82, 0xEC, 0x77, 0x44, 0xB8, 0x3D, 0xF9, 0x88, 0xAC, }, - 533, - false}, + 533}, {{ 0xC3, 0x72, 0xF6, 0xD1, 0x8E, 0xBE, 0xE5, 0xAA, 0x23, 0xD9, 0xE9, 0x19, 0xF3, 0xE6, 0xBE, 0x98, 0x48, 0x8E, 0xC0, 0x16, 0x07, 0xDF, 0x31, 0x62, 0xFC, 0x19, 0x2E, 0x4B, 0x13, 0x46, 0xAF, 0xB3, }, - 505, - true}, + 505}, {{ 0xC3, 0xBC, 0x61, 0x00, 0xF5, 0x7E, 0x32, 0x0D, 0x86, 0x59, 0xF2, 0x25, 0x84, 0x67, 0x7E, 0x56, 0x86, 0x0A, 0xAB, 0x10, 0x14, 0xE0, 0x08, 0x4A, 0x49, 0x6F, 0xFF, 0x8C, 0x88, 0x0B, 0x6B, 0xA3, }, - 26, - true}, + 26}, {{ 0xC4, 0x25, 0x33, 0xD3, 0xAF, 0x49, 0x98, 0xF5, 0xAD, 0x9F, 0x07, 0x25, 0x21, 0xD8, 0x5D, 0x47, 0x2F, 0xA7, 0xFF, 0xDC, 0xFC, 0x58, 0x8C, 0x82, 0x47, 0xB3, 0x37, 0xDC, 0x77, 0x10, 0x93, 0x89, }, - 373, - true}, + 373}, {{ 0xC4, 0x44, 0xB5, 0xB6, 0x6C, 0xE5, 0xD7, 0x1E, 0x1B, 0x5E, 0x40, 0xF2, 0x73, 0x85, 0xC9, 0x5C, 0xBF, 0xD2, 0x4A, 0x05, 0xB5, 0x6F, 0x70, 0xCA, 0xC0, 0x99, 0x2F, 0x0F, 0x50, 0xC3, 0x37, 0x9C, }, - 108, - false}, + 108}, {{ 0xC5, 0x3D, 0xAD, 0x9E, 0x53, 0xAE, 0x27, 0xED, 0x95, 0xF0, 0xEA, 0x7A, 0x92, 0x03, 0xF7, 0xBF, 0x56, 0xEF, 0xF0, 0xF8, 0xE1, 0xCE, 0x96, 0x0C, 0xB4, 0x76, 0x1B, 0x96, 0x83, 0x42, 0xE3, 0x4E, }, - 443, - true}, + 443}, {{ 0xC5, 0x69, 0x7B, 0xE9, 0x1C, 0xD6, 0x55, 0x53, 0x9B, 0x56, 0x07, 0x58, 0xE9, 0x1B, 0x6E, 0x08, 0x54, 0x61, 0x62, 0x37, 0x41, 0x03, 0x4C, 0x48, 0x5E, 0x47, 0xD7, 0xE9, 0xD2, 0x5A, 0x03, 0xC0, }, - 213, - true}, + 213}, {{ 0xC5, 0x75, 0x0B, 0xF8, 0x5F, 0x45, 0x9F, 0xB7, 0x0E, 0x2B, 0x6C, 0xD1, 0x89, 0x8D, 0x37, 0x5E, 0x92, 0xD7, 0x93, 0x8E, 0x47, 0xA6, 0xE0, 0x34, 0xCC, 0xE0, 0xC1, 0x2D, 0x30, 0x37, 0x2C, 0xCD, }, - 502, - true}, + 502}, {{ 0xC5, 0xEA, 0x25, 0x9C, 0x62, 0x98, 0x03, 0x50, 0x86, 0x49, 0xF0, 0x21, 0x77, 0xF6, 0x3C, 0x32, 0xFA, 0x85, 0xCC, 0x4A, 0xD5, 0xC3, 0x5F, 0x0D, 0x54, 0x1C, 0x45, 0xDF, 0x10, 0xA4, 0x9F, 0xD7, }, - 286, - true}, + 286}, {{ 0xC6, 0x3D, 0x68, 0xC6, 0x48, 0xA1, 0x8B, 0x77, 0x64, 0x1C, 0x42, 0x7A, 0x66, 0x9D, 0x61, 0xC9, 0x76, 0x8A, 0x55, 0xF4, 0xFC, 0xD0, 0x32, 0x2E, 0xAC, 0x96, 0xC5, 0x77, 0x00, 0x29, 0x9C, 0xF1, }, - 290, - false}, + 290}, {{ 0xC7, 0x3A, 0xFC, 0x2E, 0xBA, 0x77, 0x0D, 0x0C, 0xBC, 0x1E, 0xE4, 0x1F, 0x25, 0x2B, 0x52, 0xE8, 0xA9, 0x3D, 0x12, 0xB7, 0x2D, 0xCC, 0xEC, 0x03, 0x1D, 0x8D, 0x83, 0x9C, 0xBF, 0x81, 0x8A, 0x79, }, - 3, - true}, + 3}, {{ 0xC7, 0x46, 0x12, 0x7C, 0x5F, 0x6B, 0x52, 0x9C, 0xE9, 0xE2, 0x94, 0x8E, 0xFD, 0x94, 0x65, 0x44, 0x40, 0x89, 0x31, 0x9A, 0xCF, 0x03, 0xF3, 0x4D, 0x0B, 0xF3, 0x7E, 0xAD, 0xC7, 0x7D, 0xB2, 0x2F, }, - 43, - true}, + 43}, {{ 0xC7, 0x84, 0x33, 0x3D, 0x20, 0xBC, 0xD7, 0x42, 0xB9, 0xFD, 0xC3, 0x23, 0x6F, 0x4E, 0x50, 0x9B, 0x89, 0x37, 0x07, 0x0E, 0x73, 0x06, 0x7E, 0x25, 0x4D, 0xD3, 0xBF, 0x9C, 0x45, 0xBF, 0x4D, 0xDE, }, - 182, - false}, + 182}, {{ 0xC7, 0xF4, 0x3B, 0x4C, 0xF5, 0xB7, 0x15, 0x68, 0x29, 0x4F, 0x82, 0x2B, 0x53, 0x76, 0x26, 0x05, 0xF6, 0xDD, 0xD1, 0x5C, 0xAD, 0xEC, 0xE7, 0x39, 0xE9, 0xE2, 0xC3, 0xCB, 0xA6, 0x1E, 0x9D, 0x67, }, - 134, - false}, + 134}, {{ 0xC7, 0xF5, 0x84, 0x23, 0x6D, 0x86, 0x39, 0x5E, 0x8F, 0x6F, 0x82, 0xC0, 0x10, 0x88, 0x6A, 0x2C, 0x56, 0xE0, 0x71, 0xA6, 0xA1, 0xC3, 0xED, 0x28, 0x76, 0xB8, 0xA3, 0xA7, 0x2C, 0x5E, 0xFB, 0xB5, }, - 397, - true}, + 397}, {{ 0xC9, 0x0D, 0x00, 0x9C, 0x47, 0xEE, 0xB9, 0xF2, 0xA2, 0x9A, 0xE8, 0x48, 0xF5, 0xD9, 0x30, 0xF2, 0xB4, 0x1E, 0xF5, 0xED, 0xBC, 0x5C, 0x56, 0x95, 0xC1, 0x41, 0x43, 0x45, 0xC1, 0xDD, 0x67, 0xB4, }, - 358, - true}, + 358}, {{ 0xC9, 0x42, 0x26, 0x2C, 0x0C, 0x7C, 0x0A, 0x95, 0xBB, 0x15, 0x2B, 0x71, 0xC4, 0x25, 0x56, 0xDD, 0xBE, 0x9A, 0x04, 0xFA, 0x83, 0x78, 0x37, 0x35, 0x50, 0xD2, 0xB7, 0xCE, 0x27, 0xD9, 0x52, 0xA3, }, - 520, - true}, + 520}, {{ 0xC9, 0x54, 0xC2, 0xC0, 0xB1, 0x89, 0x82, 0x5B, 0xB6, 0x5D, 0xDB, 0x3D, 0xDC, 0xA0, 0x80, 0xB7, 0xDB, 0xCF, 0xE6, 0xB1, 0x7C, 0xAD, 0xE1, 0x02, 0x2B, 0xAD, 0xA8, 0x18, 0x33, 0x66, 0x77, 0xD0, }, - 308, - true}, + 308}, {{ 0xC9, 0x90, 0x5B, 0x0E, 0xE0, 0x12, 0x02, 0x29, 0x3C, 0xA0, 0x26, 0xE6, 0x4F, 0x08, 0x41, 0x24, 0x42, 0xC5, 0x50, 0x4C, 0x06, 0xE4, 0x4C, 0xA7, 0xE9, 0x72, 0x6D, 0x61, 0xF2, 0x0E, 0x40, 0x89, }, - 402, - true}, + 402}, {{ 0xCB, 0x6E, 0x91, 0x71, 0x1A, 0xD6, 0xD5, 0x5C, 0x89, 0x06, 0xF3, 0x79, 0xCB, 0x07, 0x1F, 0xB5, 0xC4, 0x79, 0x33, 0x65, 0x4A, 0x74, 0x15, 0x61, 0x2E, 0xEE, 0x66, 0x29, 0xF2, 0x6F, 0xBC, 0xD7, }, - 41, - true}, + 41}, {{ 0xCB, 0xAD, 0x7B, 0x1D, 0x38, 0x48, 0x49, 0xDF, 0x09, 0x46, 0xB7, 0xEE, 0x8E, 0x7F, 0x5F, 0x7C, 0xE3, 0xAE, 0xD8, 0x76, 0xFD, 0xA7, 0xBC, 0x9D, 0x30, 0xD8, 0xB1, 0x6F, 0x29, 0xFF, 0x2C, 0x53, }, - 492, - true}, + 492}, {{ 0xCB, 0xE5, 0xAC, 0x15, 0xD8, 0x8B, 0x5C, 0xAC, 0x3F, 0x81, 0xE6, 0xDF, 0x3B, 0xFB, 0x57, 0xBE, 0xA6, 0x09, 0x58, 0x81, 0x3A, 0x47, 0xB7, 0x7F, 0x3C, 0x5C, 0xB6, 0xB9, 0x81, 0x91, 0xBD, 0xB5, }, - 8, - true}, + 8}, {{ 0xCC, 0x49, 0x97, 0x86, 0x3C, 0x8C, 0x48, 0xA4, 0xCB, 0x5C, 0x3E, 0x65, 0x37, 0xDC, 0x06, 0x02, 0x8D, 0x86, 0x38, 0xBE, 0x49, 0xF5, 0xF8, 0xA2, 0xBA, 0x56, 0xF2, 0xF2, 0xC8, 0xA8, 0xC7, 0x79, }, - 267, - true}, + 267}, {{ 0xCE, 0x24, 0xEB, 0x06, 0x26, 0xDE, 0xFD, 0x81, 0x68, 0xC9, 0x6A, 0x77, 0x01, 0xF0, 0x93, 0x01, 0x60, 0x0F, 0xE5, 0xDD, 0x0D, 0xBC, 0xE5, 0x8E, 0x9C, 0x97, 0xB8, 0x30, 0xAF, 0x02, 0xEF, 0x28, }, - 32, - false}, + 32}, {{ 0xCE, 0xB1, 0x94, 0x11, 0xC6, 0x50, 0x52, 0xC7, 0x57, 0xF9, 0x41, 0xEB, 0x82, 0x6C, 0x96, 0x94, 0x1E, 0x4D, 0x08, 0xD0, 0x96, 0xC7, 0xDB, 0x7E, 0x7E, 0xA3, 0xC4, 0xF8, 0xC1, 0x3F, 0x1A, 0x13, }, - 288, - false}, + 288}, {{ 0xCE, 0xD4, 0x39, 0x02, 0xAB, 0x5F, 0xB5, 0x7B, 0x44, 0x23, 0x22, 0xDC, 0x0E, 0x17, 0x2A, 0x4F, 0xB5, 0x5F, 0x71, 0x78, 0xB8, 0x08, 0xF9, 0x4E, 0x78, 0x0A, 0x6F, 0xD6, 0xCC, 0x6B, 0xD8, 0x18, }, - 19, - false}, + 19}, {{ 0xCF, 0x0B, 0x47, 0x4A, 0xCE, 0x84, 0x69, 0xFA, 0xBA, 0x40, 0x2F, 0x02, 0xEE, 0xBD, 0xF9, 0xE1, 0x70, 0x0D, 0x9C, 0xBE, 0x8B, 0xE4, 0xE4, 0x34, 0x84, 0x07, 0xB6, 0x9D, 0xD3, 0x19, 0x6E, 0x94, }, - 148, - true}, + 148}, {{ 0xD0, 0x77, 0x3A, 0xDB, 0x60, 0x04, 0x3E, 0x95, 0x43, 0x09, 0xD9, 0x71, 0x4F, 0xE0, 0x53, 0xEA, 0xAD, 0x8A, 0xA5, 0xB9, 0x58, 0x6E, 0xDB, 0xA4, 0x68, 0xE2, 0x76, 0xDF, 0x82, 0x06, 0x5A, 0xDF, }, - 132, - true}, + 132}, {{ 0xD1, 0xC4, 0x53, 0x77, 0xEB, 0xDC, 0xD6, 0x18, 0xCD, 0x16, 0x51, 0xDC, 0x2E, 0x02, 0xC2, 0x1D, 0x75, 0x1E, 0x5A, 0xA9, 0xFC, 0xD1, 0xB3, 0x43, 0x1F, 0xF6, 0xEC, 0xF6, 0xA3, 0x13, 0x48, 0xFA, }, - 292, - false}, + 292}, {{ 0xD1, 0xDE, 0x2A, 0xE6, 0x1C, 0x8D, 0xF2, 0xFA, 0x62, 0x39, 0x66, 0x16, 0x3D, 0x4C, 0x73, 0xD4, 0x60, 0xBF, 0xC4, 0x28, 0xE5, 0x75, 0x85, 0xBE, 0x6B, 0xFE, 0xB9, 0xA5, 0x63, 0x23, 0xD1, 0xB6, }, - 46, - false}, + 46}, {{ 0xD1, 0xEC, 0xAC, 0xCA, 0x44, 0x01, 0x2C, 0x3E, 0x1E, 0x6D, 0x1B, 0x39, 0xDD, 0x29, 0x68, 0xFC, 0x7F, 0xD3, 0x12, 0x7A, 0xAA, 0x57, 0xAB, 0x51, 0x82, 0xA3, 0xBE, 0xAB, 0xCC, 0xD7, 0xA3, 0xA9, }, - 367, - true}, + 367}, {{ 0xD2, 0xA5, 0xF3, 0x2F, 0x0E, 0x01, 0xB9, 0x10, 0xEF, 0x4E, 0x3B, 0x46, 0xBF, 0x84, 0xE5, 0xAF, 0x5F, 0xB5, 0x68, 0x9E, 0x7D, 0x15, 0x07, 0xE9, 0x29, 0xE3, 0x68, 0xAC, 0x88, 0xC6, 0xCC, 0x76, }, - 103, - false}, + 103}, {{ 0xD2, 0xF9, 0x1A, 0x04, 0xE3, 0xA6, 0x1D, 0x4E, 0xAD, 0x78, 0x48, 0xC8, 0xD4, 0x3B, 0x5E, 0x11, 0x52, 0xD8, 0x85, 0x72, 0x74, 0x89, 0xBC, 0x65, 0x73, 0x8B, 0x67, 0xC0, 0xA2, 0x27, 0x85, 0xA7, }, - 255, - true}, + 255}, {{ 0xD3, 0x98, 0x0A, 0xAD, 0xD2, 0x16, 0x38, 0xC7, 0x0D, 0x74, 0xA4, 0xBB, 0x1F, 0x8A, 0xB5, 0xE1, 0x17, 0x24, 0xE6, 0x2E, 0xD4, 0x08, 0xF9, 0xFA, 0x8D, 0x3D, 0x4D, 0x91, 0x69, 0x00, 0x28, 0x6B, }, - 472, - true}, + 472}, {{ 0xD4, 0x9C, 0x6F, 0x28, 0x9C, 0xD0, 0x56, 0x51, 0x94, 0x92, 0x48, 0x0F, 0x19, 0x2F, 0x00, 0xA6, 0xFC, 0x7C, 0x18, 0x62, 0xDA, 0xB2, 0xE7, 0xB5, 0xD8, 0xE0, 0x5F, 0x66, 0x78, 0xFA, 0xE1, 0x41, }, - 491, - true}, + 491}, {{ 0xD4, 0xAF, 0x6C, 0x0A, 0x48, 0x23, 0x10, 0xBD, 0x7C, 0x54, 0xBB, 0x7A, 0xB1, 0x21, 0x91, 0x6F, 0x86, 0xC0, 0xC0, 0x7C, 0xD5, 0x2F, 0xCA, 0xC3, 0x2D, 0x38, 0x44, 0xC2, 0x60, 0x05, 0x11, 0x5F, }, - 326, - true}, + 326}, {{ 0xD5, 0x59, 0x7E, 0xA3, 0x45, 0x3A, 0x62, 0x61, 0xF5, 0xD4, 0x2E, 0xB9, 0xCA, 0xF5, 0xBD, 0xB4, 0xE3, 0x8A, 0x1E, 0xDE, 0xBD, 0xB5, 0xBE, 0xA6, 0xD7, 0xC0, 0xBC, 0x1A, 0x8A, 0xBE, 0xCA, 0xB2, }, - 405, - true}, + 405}, {{ 0xD6, 0x46, 0xF3, 0xEA, 0x2D, 0x70, 0x03, 0xFC, 0xAA, 0x77, 0xAD, 0x21, 0x91, 0x36, 0xC7, 0x8E, 0x02, 0x4A, 0x6F, 0x2E, 0x23, 0x07, 0xDF, 0xB8, 0xCF, 0xA9, 0x7A, 0x17, 0x13, 0x73, 0xEC, 0xDF, }, - 374, - true}, + 374}, {{ 0xD6, 0xA1, 0x84, 0x43, 0xD3, 0x48, 0xDB, 0x99, 0x4F, 0x93, 0x4C, 0xCD, 0x8E, 0x63, 0x5D, 0x83, 0x3A, 0x27, 0xAC, 0x1E, 0x56, 0xF8, 0xAF, 0xAF, 0x7C, 0x97, 0xCB, 0x4F, 0x43, 0xEA, 0xB6, 0x8B, }, - 172, - true}, + 172}, {{ 0xD6, 0xEC, 0x63, 0x48, 0xA7, 0xC4, 0xD4, 0x2A, 0xC4, 0x8D, 0x9C, 0x43, 0x14, 0x5A, 0x8C, 0xD7, 0x19, 0x71, 0x36, 0x23, 0x63, 0x26, 0x7C, 0x66, 0x73, 0xA7, 0x7B, 0x8A, 0x85, 0x73, 0xA6, 0x6B, }, - 530, - false}, + 530}, {{ 0xD8, 0xFB, 0x33, 0xE3, 0x85, 0xC9, 0xC2, 0xDA, 0x72, 0x9A, 0x84, 0x70, 0x6B, 0xA9, 0x27, 0xDC, 0xBB, 0x79, 0x27, 0x3E, 0x12, 0x2F, 0xFD, 0x96, 0x73, 0x36, 0x3B, 0x70, 0xB7, 0xF3, 0x6C, 0xBB, }, - 153, - true}, + 153}, {{ 0xD9, 0x24, 0x05, 0xC4, 0x6D, 0x91, 0x2A, 0x56, 0x3E, 0x43, 0x28, 0x7F, 0x56, 0xCD, 0x41, 0x0A, 0x1C, 0xDF, 0x63, 0x67, 0xC5, 0x7C, 0x9E, 0xA7, 0xC5, 0xCA, 0xE0, 0x39, 0xDC, 0xBC, 0xCE, 0x50, }, - 365, - true}, + 365}, {{ 0xD9, 0xC4, 0x73, 0xCE, 0xE2, 0x5F, 0x94, 0xD1, 0xBC, 0x60, 0x62, 0xBD, 0x62, 0x91, 0x14, 0x77, 0x27, 0x6F, 0x06, 0x4B, 0x82, 0x7A, 0x94, 0x4E, 0x06, 0x4F, 0x85, 0xD0, 0x91, 0x2D, 0x2C, 0x5E, }, - 253, - true}, + 253}, {{ 0xDA, 0x80, 0x0B, 0x80, 0xB2, 0xA8, 0x7D, 0x39, 0x9E, 0x66, 0xFA, 0x19, 0xD7, 0x2F, 0xDF, 0x49, 0x98, 0x3B, 0x47, 0xD8, 0xCF, 0x32, 0x2C, 0x7C, 0x79, 0x50, 0x3A, 0x0C, 0x7E, 0x28, 0xFE, 0xAF, }, - 230, - true}, + 230}, {{ 0xDA, 0x87, 0x96, 0xBE, 0x34, 0xCC, 0x81, 0xAB, 0xEE, 0x73, 0x04, 0xC4, 0xD2, 0xBC, 0xA0, 0xAC, 0x98, 0x4C, 0x5B, 0x24, 0xB6, 0x1B, 0x13, 0xE2, 0x28, 0x5E, 0x1D, 0x27, 0xAD, 0x8C, 0xEB, 0xF0, }, - 218, - true}, + 218}, {{ 0xDB, 0x15, 0xC0, 0x06, 0x2B, 0x52, 0x0F, 0x31, 0x8A, 0x19, 0xDA, 0xCF, 0xEC, 0xD6, 0x4F, 0x9E, 0x7A, 0x3F, 0xBE, 0x60, 0x9F, 0xD5, 0x86, 0x79, 0x6F, 0x20, 0xAE, 0x02, 0x8E, 0x8E, 0x30, 0x58, }, - 168, - true}, + 168}, {{ 0xDB, 0xC1, 0xE3, 0xA1, 0x52, 0x38, 0xA0, 0x48, 0x3B, 0xCD, 0xB8, 0xFD, 0xEC, 0x61, 0x6E, 0x03, 0xE7, 0x05, 0xA4, 0x8E, 0x2A, 0x50, 0x11, 0x57, 0xCA, 0xDF, 0x3B, 0x9C, 0x73, 0x11, 0xC5, 0xE5, }, - 87, - false}, + 87}, {{ 0xDC, 0x05, 0x3D, 0x02, 0x7F, 0xC1, 0x86, 0xE7, 0xC4, 0x1C, 0xD1, 0x93, 0xAF, 0x30, 0xFC, 0x09, 0x79, 0x4E, 0xB9, 0xF3, 0xD9, 0xE6, 0x73, 0x6D, 0xCE, 0x04, 0x14, 0x40, 0xD8, 0x76, 0xA8, 0x01, }, - 399, - true}, + 399}, {{ 0xDD, 0x5E, 0xD1, 0xC0, 0x90, 0xF9, 0xF4, 0x48, 0x06, 0x1B, 0xAA, 0x94, 0xA6, 0xBB, 0x11, 0x01, 0x75, 0x44, 0xE9, 0xEE, 0xFA, 0xA2, 0x0C, 0xC7, 0x14, 0xCE, 0x6C, 0x63, 0x3F, 0x5D, 0xC6, 0x29, }, - 189, - false}, + 189}, {{ 0xDD, 0x9A, 0x6B, 0xFB, 0xF4, 0x4E, 0x17, 0xA2, 0x7F, 0x36, 0x8A, 0xC8, 0xE0, 0x67, 0xB3, 0x07, 0x39, 0x62, 0x69, 0xA7, 0x47, 0xF9, 0x2E, 0x8F, 0x2A, 0xCF, 0x2B, 0x45, 0x1E, 0x3F, 0xFC, 0x72, }, - 236, - true}, + 236}, {{ 0xDE, 0x7B, 0x69, 0x32, 0xE9, 0xC4, 0x45, 0x82, 0xCE, 0x0D, 0xE0, 0x7A, 0xBD, 0xAB, 0x7E, 0xEA, 0x90, 0xC7, 0x5D, 0x6D, 0x2A, 0x07, 0x33, 0x1D, 0xF5, 0x7B, 0xD5, 0xCB, 0x88, 0x55, 0x3D, 0x13, }, - 542, - false}, + 542}, {{ 0xDF, 0x53, 0x0B, 0xAC, 0x9F, 0xCD, 0x91, 0x4C, 0x25, 0x2C, 0x2F, 0xBD, 0xCE, 0xDD, 0xC6, 0x18, 0x3D, 0x4A, 0xE8, 0xC6, 0x80, 0xAD, 0x65, 0xF0, 0x3E, 0x20, 0x48, 0x61, 0xDD, 0x7B, 0x1C, 0x73, }, - 313, - true}, + 313}, {{ 0xE0, 0x4A, 0x02, 0x2C, 0xE3, 0x2F, 0x4C, 0xCF, 0x2C, 0x7F, 0x60, 0x46, 0x28, 0x7B, 0x82, 0x8A, 0x32, 0xA9, 0x09, 0xF5, 0xE7, 0x51, 0x44, 0x7F, 0x83, 0xFD, 0x2C, 0x71, 0xF6, 0xFD, 0x81, 0x73, }, - 524, - false}, + 524}, {{ 0xE0, 0xC7, 0x80, 0xC6, 0x29, 0x90, 0x3E, 0x12, 0x6F, 0x1D, 0x91, 0x95, 0x70, 0xDC, 0xE7, 0xC4, 0x96, 0xF8, 0x5F, 0x33, 0xAA, 0xE6, 0x6B, 0x9A, 0x31, 0x47, 0xEE, 0x75, 0xF8, 0xD1, 0x62, 0x0A, }, - 493, - true}, + 493}, {{ 0xE0, 0xEF, 0x88, 0x2D, 0xA4, 0x8A, 0xB0, 0xB7, 0xEF, 0xB0, 0xD9, 0xBA, 0x15, 0xB2, 0x71, 0x7D, 0xD0, 0x8F, 0x04, 0x3C, 0x25, 0xAC, 0x09, 0xB5, 0x6B, 0x8B, 0x57, 0xFC, 0xEE, 0xB5, 0xA3, 0x5D, }, - 369, - true}, + 369}, {{ 0xE1, 0x4E, 0x51, 0x89, 0x1F, 0x34, 0x92, 0x24, 0x3E, 0xEA, 0x61, 0x3B, 0xC2, 0xC8, 0x14, 0xD4, 0x72, 0x24, 0xB2, 0x24, 0xC5, 0x7D, 0x38, 0x16, 0x9E, 0x95, 0x8E, 0x30, 0xB3, 0xDE, 0xDE, 0xE4, }, - 527, - false}, + 527}, {{ 0xE1, 0x56, 0x44, 0x5F, 0xA2, 0x0C, 0x32, 0xAD, 0x00, 0x93, 0x7B, 0x27, 0xD0, 0x96, 0xB8, 0x96, 0x3B, 0xCC, 0x86, 0x39, 0x50, 0x33, 0x3A, 0x87, 0x7E, 0x68, 0xFA, 0x69, 0x70, 0x7A, 0x03, 0xAF, }, - 445, - true}, + 445}, {{ 0xE2, 0x66, 0x13, 0xA5, 0x78, 0xE1, 0x58, 0xC2, 0xA4, 0x4E, 0x4F, 0xEC, 0x41, 0xE6, 0xF3, 0x7A, 0x0A, 0x99, 0x1F, 0xE1, 0xA5, 0xFE, 0x73, 0x6C, 0x30, 0x3F, 0x44, 0x20, 0xA9, 0x0F, 0xB5, 0x0A, }, - 331, - true}, + 331}, {{ 0xE2, 0xD8, 0x91, 0xEF, 0xB7, 0x38, 0x66, 0x91, 0x05, 0xD5, 0x30, 0xDE, 0x5E, 0xD7, 0x2E, 0x2B, 0x2A, 0xC3, 0xF4, 0xA6, 0x70, 0x78, 0xB5, 0x34, 0x9B, 0x3F, 0xDA, 0xCA, 0x49, 0x6F, 0x5E, 0xB8, }, - 9, - true}, + 9}, {{ 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55, }, - 488, - true}, + 488}, {{ 0xE4, 0x2F, 0x24, 0xBD, 0x4D, 0x37, 0xF4, 0xAA, 0x2E, 0x56, 0xB9, 0x79, 0xD8, 0x3D, 0x1E, 0x65, 0x21, 0x9F, 0xE0, 0xE9, 0xE3, 0xA3, 0x82, 0xA1, 0xB3, 0xCB, 0x66, 0xC9, 0x39, 0x55, 0xDE, 0x75, }, - 29, - true}, + 29}, {{ 0xE4, 0x3D, 0xEA, 0x89, 0x4F, 0x42, 0xCE, 0xCF, 0x4A, 0x1D, 0xD6, 0x0E, 0xD1, 0xDA, 0xB8, 0x2F, 0x7C, 0x0A, 0x30, 0x8A, 0xE3, 0x2A, 0x3D, 0x49, 0xA7, 0xAA, 0x1A, 0x3E, 0x95, 0x70, 0x15, 0xF7, }, - 212, - true}, + 212}, {{ 0xE5, 0xCA, 0x37, 0xBC, 0x7B, 0x6C, 0x36, 0x19, 0x79, 0xBC, 0x6B, 0x12, 0x3C, 0xA9, 0xA1, 0xDB, 0x01, 0x90, 0x46, 0xD7, 0xFF, 0x5F, 0x57, 0xDF, 0xB8, 0x54, 0xB1, 0x9D, 0x10, 0xB0, 0x68, 0x2F, }, - 112, - false}, + 112}, {{ 0xE7, 0xCA, 0x91, 0xBB, 0xFB, 0xB1, 0x87, 0x88, 0x05, 0x7B, 0x3A, 0x80, 0x70, 0x44, 0x6E, 0xA5, 0x29, 0x11, 0x60, 0x19, 0x41, 0x02, 0xF7, 0xDC, 0xC3, 0xB9, 0x84, 0x8C, 0x63, 0xCB, 0x9C, 0xD5, }, - 89, - false}, + 89}, {{ 0xE8, 0x5F, 0xBF, 0x8B, 0x9A, 0x2E, 0xA4, 0x90, 0x9D, 0xCE, 0x0F, 0xB5, 0xB2, 0xFE, 0x5F, 0x58, 0x77, 0x34, 0x3D, 0x27, 0xD5, 0x8A, 0x41, 0x0A, 0x8B, 0x23, 0x7A, 0xB6, 0x75, 0xA2, 0xDD, 0xAF, }, - 345, - true}, + 345}, {{ 0xEA, 0x2F, 0x9E, 0x08, 0x7E, 0xAE, 0xBB, 0xDF, 0xC0, 0x56, 0x9E, 0xCA, 0x18, 0x36, 0x4E, 0x52, 0x36, 0x25, 0x46, 0x24, 0x85, 0x4F, 0x92, 0xE3, 0x78, 0x71, 0xB5, 0xEE, 0x36, 0x74, 0x48, 0x83, }, - 297, - true}, + 297}, {{ 0xEA, 0x87, 0xF4, 0x62, 0xDE, 0xEF, 0xFF, 0xBD, 0x77, 0x75, 0xAA, 0x2A, 0x4B, 0x7E, 0x0F, 0xCB, 0x91, 0xC2, 0x2E, 0xEE, 0x6D, 0xF6, 0x9E, 0xD9, 0x01, 0x00, 0xCC, 0xC7, 0x3B, 0x31, 0x14, 0x76, }, - 289, - false}, + 289}, {{ 0xEA, 0xBC, 0x18, 0x5C, 0x4E, 0x82, 0xD9, 0x42, 0xB1, 0xA5, 0x97, 0x8B, 0xA3, 0xC0, 0x18, 0x14, 0x87, 0xD6, 0xB3, 0xB9, 0x97, 0x4E, 0x5C, 0x49, 0xF7, 0x2F, 0x6D, 0x0B, 0xD9, 0x63, 0x71, 0x50, }, - 497, - false}, + 497}, {{ 0xEB, 0x49, 0x93, 0xEF, 0xA9, 0xB0, 0x89, 0xE5, 0x93, 0x41, 0x8A, 0xA8, 0x93, 0xF8, 0xE9, 0x3A, 0x73, 0x74, 0xD8, 0x10, 0xE5, 0x2F, 0xCB, 0xE0, 0x1E, 0x7F, 0x1D, 0x7E, 0x92, 0xA6, 0xD0, 0x24, }, - 215, - true}, + 215}, {{ 0xEC, 0x90, 0x56, 0xFE, 0x95, 0x09, 0x41, 0x16, 0x09, 0x76, 0x3A, 0xEE, 0x83, 0x1E, 0xF3, 0x7C, 0x83, 0x2B, 0x75, 0xB3, 0xD7, 0x27, 0x52, 0x8F, 0xC7, 0xC7, 0x52, 0x01, 0xC1, 0xFF, 0x28, 0xE6, }, - 197, - true}, + 197}, {{ 0xEC, 0xA0, 0xF1, 0x81, 0x40, 0x2C, 0xE7, 0xA8, 0x65, 0x2B, 0x31, 0xB4, 0xD0, 0x36, 0xDF, 0x24, 0x7E, 0x3A, 0x30, 0xB7, 0xF4, 0x1A, 0x50, 0xD9, 0x1E, 0xC4, 0xF9, 0x0B, 0x00, 0x6B, 0x43, 0xA1, }, - 16, - false}, + 16}, {{ 0xED, 0x1B, 0x22, 0x9E, 0x0E, 0x08, 0x75, 0x02, 0x1C, 0x1F, 0x17, 0x60, 0xC3, 0x40, 0x7F, 0xB1, 0xD6, 0x60, 0x8E, 0xDA, 0x7A, 0xDD, 0x71, 0xA3, 0xE3, 0x27, 0x5C, 0xED, 0x09, 0x69, 0x0F, 0x7C, }, - 377, - true}, + 377}, {{ 0xED, 0xE4, 0xB1, 0x53, 0x5A, 0x52, 0x9B, 0xF1, 0x60, 0x6B, 0xC6, 0xFF, 0x75, 0x7B, 0x91, 0x47, 0x0A, 0xA3, 0x0A, 0xEA, 0xFF, 0xD2, 0xD6, 0xDF, 0x2E, 0xBA, 0x34, 0x0D, 0xAE, 0x30, 0x2F, 0xCA, }, - 219, - true}, + 219}, {{ 0xEF, 0x4F, 0xA1, 0xC6, 0x30, 0xF0, 0x49, 0x50, 0xE0, 0xE2, 0xD1, 0x0D, 0xC1, 0x9F, 0x14, 0x9D, 0x08, 0xAB, 0x46, 0xDE, 0xC9, 0x5D, 0xA3, 0x13, 0x1C, 0xBA, 0xEA, 0x8A, 0xF8, 0xEA, 0x30, 0x27, }, - 393, - true}, + 393}, {{ 0xEF, 0x53, 0xFF, 0xAF, 0x0C, 0xEB, 0x04, 0x0D, 0x07, 0x7F, 0x5B, 0xD8, 0x0A, 0x9D, 0xEE, 0xF6, 0xD4, 0x50, 0x7F, 0xDB, 0x6F, 0x9B, 0xCF, 0x8C, 0x35, 0x94, 0xBE, 0xCE, 0x7E, 0xBD, 0xB0, 0x25, }, - 361, - true}, + 361}, {{ 0xEF, 0xFE, 0xE1, 0xF1, 0xE5, 0xF3, 0x9F, 0x42, 0xFF, 0x80, 0xD4, 0x71, 0xC9, 0xC5, 0xA7, 0x99, 0xA8, 0xC8, 0x43, 0xF9, 0xB6, 0x76, 0x31, 0x5F, 0x9E, 0xAB, 0x3F, 0x4C, 0x7A, 0x2F, 0x7F, 0xC8, }, - 129, - true}, + 129}, {{ 0xF0, 0x01, 0x1F, 0x92, 0xFC, 0xF9, 0xBE, 0x36, 0xC7, 0xA5, 0xB3, 0x6E, 0x7B, 0xC8, 0x62, 0xAB, 0x20, 0xE9, 0x4E, 0xF3, 0x6F, 0xEA, 0x8A, 0x56, 0x1D, 0xB0, 0xA8, 0xD7, 0x75, 0x0C, 0x1F, 0x51, }, - 537, - false}, + 537}, {{ 0xF1, 0xC6, 0xBA, 0x67, 0x0C, 0xFC, 0x88, 0xE4, 0xDF, 0x52, 0x97, 0x3C, 0xAE, 0x42, 0x0F, 0x0A, 0x08, 0x9D, 0xD4, 0x74, 0x14, 0x4F, 0xE5, 0x80, 0x6C, 0x42, 0x00, 0x64, 0xE1, 0x59, 0x12, 0x29, }, - 171, - false}, + 171}, {{ 0xF2, 0x6C, 0xDA, 0xA1, 0xC4, 0x8E, 0x2D, 0x36, 0x9E, 0xAF, 0x24, 0x99, 0x3A, 0x42, 0x4F, 0x82, 0x90, 0x98, 0x3A, 0xF7, 0x09, 0x4A, 0x5B, 0xDE, 0x9C, 0x7D, 0x44, 0x34, 0x1F, 0x2E, 0x24, 0x28, }, - 504, - true}, + 504}, {{ 0xF2, 0xA4, 0xE6, 0xB2, 0x63, 0xD0, 0xA5, 0x52, 0xAD, 0xFF, 0x5D, 0x85, 0xDC, 0x96, 0xB5, 0x82, 0x0F, 0xD6, 0x6A, 0xA0, 0xB1, 0x82, 0x28, 0xF4, 0x8F, 0xDB, 0x08, 0x7C, 0x8D, 0xB3, 0x41, 0x33, }, - 474, - true}, + 474}, {{ 0xF3, 0x43, 0x8E, 0x23, 0xB3, 0xCE, 0x53, 0x25, 0x22, 0xFA, 0xCF, 0x30, 0x79, 0x23, 0xF5, 0x8F, 0xD1, 0x86, 0x08, 0xE9, 0xBA, 0x7A, 0xDD, 0xC3, 0x0E, 0x95, 0x2B, 0x43, 0xC4, 0x96, 0x16, 0xC3, }, - 177, - false}, + 177}, {{ 0xF4, 0x23, 0x52, 0xC3, 0xCC, 0x3D, 0x84, 0xB8, 0x51, 0x89, 0x89, 0xD6, 0x47, 0xC8, 0x8C, 0xA3, 0x01, 0xC8, 0x8F, 0xB9, 0x91, 0x93, 0x8B, 0xBC, 0xEC, 0xC9, 0xEE, 0x60, 0xE5, 0x65, 0xD3, 0x77, }, - 467, - true}, + 467}, {{ 0xF4, 0x63, 0xC5, 0x4D, 0x9F, 0x1A, 0x04, 0x7A, 0xED, 0x52, 0x65, 0x6A, 0xC7, 0x85, 0xE0, 0x7E, 0xBE, 0xC5, 0x28, 0xE0, 0x20, 0x7B, 0xFD, 0x3F, 0x55, 0xD8, 0x93, 0x23, 0x76, 0x68, 0xF6, 0xAE, }, - 96, - true}, + 96}, {{ 0xF4, 0x8B, 0xAD, 0xD7, 0xDF, 0x6A, 0x06, 0x69, 0x0D, 0x0A, 0xE3, 0x13, 0x73, 0xB1, 0x28, 0x55, 0xF8, 0xDE, 0xDB, 0x14, 0x51, 0x7F, 0x36, 0x2A, 0x31, 0x31, 0x01, 0xCC, 0x98, 0xCC, 0x6B, 0x35, }, - 60, - false}, + 60}, {{ 0xF5, 0x3C, 0x22, 0x05, 0x98, 0x17, 0xDD, 0x96, 0xF4, 0x00, 0x65, 0x16, 0x39, 0xD2, 0xF8, 0x57, 0xE2, 0x10, 0x70, 0xA5, 0x9A, 0xBE, 0xD9, 0x07, 0x94, 0x00, 0xD9, 0xF6, 0x95, 0x50, 0x69, 0x00, }, - 118, - true}, + 118}, {{ 0xF5, 0x85, 0x7D, 0x88, 0x62, 0xBC, 0x2B, 0xA3, 0xC9, 0xDD, 0xCA, 0x3F, 0x84, 0x14, 0x6D, 0xC8, 0xD8, 0x1F, 0x4D, 0x57, 0x9D, 0x2B, 0x38, 0x7B, 0xF6, 0x00, 0x65, 0x38, 0x1E, 0xE6, 0x41, 0xDD, }, - 335, - true}, + 335}, {{ 0xF5, 0xE1, 0x9C, 0x8E, 0x14, 0xFE, 0x75, 0x5F, 0x55, 0x1C, 0xEC, 0x2B, 0x71, 0x13, 0xE7, 0xC9, 0x80, 0x23, 0xB1, 0x76, 0xEB, 0xE6, 0xC1, 0xAB, 0xCF, 0x87, 0x2B, 0x2A, 0x7B, 0x93, 0x23, 0x04, }, - 363, - true}, + 363}, {{ 0xF6, 0x14, 0x6B, 0xC2, 0x38, 0xE8, 0xFC, 0xE0, 0xD4, 0x7B, 0x70, 0x74, 0xC9, 0xA2, 0x6B, 0x1A, 0xA0, 0xF8, 0x83, 0x52, 0x85, 0x10, 0xF0, 0x6D, 0x9C, 0xFE, 0xC4, 0x1F, 0xF6, 0xCA, 0x19, 0x68, }, - 247, - true}, + 247}, {{ 0xF6, 0xB5, 0x9C, 0x8E, 0x27, 0x89, 0xA1, 0xFD, 0x5D, 0x5B, 0x25, 0x37, 0x42, 0xFE, 0xAD, 0xC6, 0x92, 0x5C, 0xB9, 0x3E, 0xDC, 0x34, 0x5E, 0x53, 0x16, 0x6E, 0x12, 0xC5, 0x2B, 0xA2, 0xA6, 0x01, }, - 327, - true}, + 327}, {{ 0xF7, 0x3B, 0xE5, 0xEB, 0xA5, 0x36, 0x91, 0x2C, 0x55, 0x7F, 0xB8, 0x55, 0x51, 0x7A, 0xD1, 0xEE, 0x04, 0x87, 0xBD, 0x8F, 0x63, 0x49, 0x8C, 0x39, 0x49, 0x16, 0x41, 0x77, 0xBA, 0x06, 0xC5, 0xDE, }, - 380, - true}, + 380}, {{ 0xF7, 0xAF, 0xF4, 0x1B, 0x27, 0x09, 0xF1, 0x75, 0xF8, 0xAB, 0xA1, 0x7E, 0x56, 0x7B, 0x27, 0x04, 0x6B, 0x2D, 0xD5, 0x4B, 0xF6, 0xE7, 0xE2, 0x63, 0xD3, 0x29, 0x58, 0x73, 0x43, 0x7B, 0x9C, 0xFF, }, - 387, - true}, + 387}, {{ 0xF7, 0xEC, 0xDE, 0xD5, 0xC6, 0x60, 0x47, 0xD2, 0x8E, 0xD6, 0x46, 0x6B, 0x54, 0x3C, 0x40, 0xE0, 0x74, 0x3A, 0xBE, 0x81, 0xD1, 0x09, 0x25, 0x4D, 0xCF, 0x84, 0x5D, 0x4C, 0x2C, 0x78, 0x53, 0xC5, }, - 208, - false}, + 208}, {{ 0xF8, 0xE5, 0xF9, 0x05, 0xBC, 0x93, 0x99, 0x11, 0x26, 0x7B, 0x83, 0xD5, 0x08, 0x14, 0xA9, 0x03, 0x23, 0xB5, 0x1E, 0x18, 0x36, 0x29, 0xDB, 0x52, 0xD4, 0xFC, 0x2D, 0x54, 0x68, 0xA5, 0xA5, 0x78, }, - 222, - true}, + 222}, {{ 0xFA, 0xC9, 0x5D, 0xE3, 0xC2, 0x4A, 0x17, 0x41, 0x94, 0x80, 0x0C, 0xFF, 0xAA, 0x3C, 0xA5, 0x1D, 0x71, 0x16, 0x63, 0x06, 0x64, 0xA9, 0xB6, 0x0C, 0x87, 0x58, 0xB4, 0xEF, 0x0D, 0xC5, 0x8F, 0x88, }, - 119, - true}, + 119}, {{ 0xFA, 0xDD, 0xDE, 0x04, 0xBC, 0xF0, 0x8C, 0xA8, 0xF4, 0xE2, 0x2E, 0xFD, 0x2A, 0xFE, 0xAD, 0xE6, 0xBF, 0x3D, 0x85, 0x0A, 0xE4, 0x7B, 0xE9, 0x6A, 0x82, 0xD5, 0x39, 0x49, 0x4F, 0x12, 0x0C, 0xBD, }, - 350, - true}, + 350}, {{ 0xFB, 0xE3, 0x01, 0x80, 0x31, 0xF9, 0x58, 0x6B, 0xCB, 0xF4, 0x17, 0x27, 0xE4, 0x17, 0xB7, 0xD1, 0xC4, 0x5C, 0x2F, 0x47, 0xF9, 0x3B, 0xE3, 0x72, 0xA1, 0x7B, 0x96, 0xB5, 0x07, 0x57, 0xD5, 0xA2, }, - 210, - false}, + 210}, {{ 0xFC, 0x3B, 0x82, 0x79, 0x6B, 0x57, 0x2C, 0xA9, 0x73, 0x19, 0x93, 0x63, 0x5D, 0xB8, 0xCF, 0x07, 0xC2, 0xBF, 0x01, 0xE1, 0x99, 0xB2, 0xF2, 0x73, 0xA3, 0xF9, 0x53, 0xBD, 0x18, 0x5D, 0xE3, 0xC0, }, - 158, - true}, + 158}, {{ 0xFC, 0x78, 0x43, 0x00, 0xEC, 0x8D, 0xF4, 0xD3, 0xD1, 0xBA, 0xD7, 0x63, 0x83, 0x51, 0x82, 0x91, 0x8D, 0x52, 0xA9, 0xFF, 0x02, 0x38, 0xBD, 0xF6, 0x95, 0xA1, 0xCD, 0x9B, 0xDB, 0x98, 0x32, 0x1C, }, - 534, - false}, + 534}, {{ 0xFC, 0xF7, 0xDA, 0x98, 0x36, 0x03, 0xE8, 0x88, 0x62, 0x03, 0x0D, 0x96, 0x13, 0x7D, 0x8E, 0x13, 0x03, 0x1B, 0xAD, 0xFB, 0x4D, 0x56, 0xC1, 0xFD, 0x4C, 0xAC, 0xC3, 0x39, 0xF6, 0xBD, 0xBB, 0x2A, }, - 28, - true}, + 28}, {{ 0xFD, 0x37, 0x1B, 0xEA, 0x97, 0x55, 0xFF, 0x60, 0xC8, 0x82, 0x8C, 0x84, 0x9B, 0x8E, 0x52, 0x15, 0xDE, 0x53, 0x2D, 0x61, 0xB0, 0x09, 0x85, 0x5F, 0xA0, 0xAD, 0x63, 0x0D, 0x90, 0xEE, 0xF8, 0x2E, }, - 490, - false}, + 490}, {{ 0xFD, 0x87, 0x2D, 0x17, 0x66, 0x17, 0xE5, 0x0C, 0x26, 0x61, 0x19, 0xD0, 0xFD, 0xB0, 0x47, 0xB0, 0x73, 0x2D, 0xA2, 0x04, 0x8B, 0x12, 0x1A, 0xF7, 0xB9, 0x86, 0x0C, 0xA3, 0xE2, 0xF2, 0xF2, 0xBE, }, - 123, - true}, + 123}, {{ 0xFD, 0xE8, 0x99, 0x9A, 0x5E, 0x42, 0x73, 0x19, 0x83, 0x5C, 0x89, 0xA1, 0x7D, 0x64, 0xA2, 0xDC, 0xD1, 0x3A, 0x85, 0x1C, 0x09, 0x16, 0xC4, 0xC5, 0x47, 0xB6, 0xD8, 0xF7, 0xA6, 0x43, 0x7D, 0x94, }, - 517, - true}, + 517}, {{ 0xFE, 0xA2, 0xB7, 0xD6, 0x45, 0xFB, 0xA7, 0x3D, 0x75, 0x3C, 0x1E, 0xC9, 0xA7, 0x87, 0x0C, 0x40, 0xE1, 0xF7, 0xB0, 0xC5, 0x61, 0xE9, 0x27, 0xB9, 0x85, 0xBF, 0x71, 0x18, 0x66, 0xE3, 0x6F, 0x22, }, - 110, - false}, + 110}, {{ 0xFE, 0xE8, 0xAF, 0x92, 0x91, 0x75, 0x68, 0x7F, 0x46, 0x38, 0xA3, 0xFC, 0x98, 0x3D, 0xB8, 0xEC, 0xD0, 0xE5, 0xE2, 0xA8, 0x3E, 0x73, 0x7F, 0x3F, 0xB7, 0x7B, 0x4C, 0x22, 0xFC, 0xBA, 0xC0, 0xA6, }, - 538, - false}, + 538}, {{ 0xFF, 0x34, 0x2F, 0xB6, 0xC4, 0xC8, 0xBD, 0x30, 0xA4, 0x70, 0x6F, 0x73, 0x48, 0x95, 0x39, 0xF1, 0x9E, 0x6E, 0x48, 0xCC, 0x05, 0xF4, 0x62, 0x54, 0x65, 0x4F, 0x66, 0x10, 0xDB, 0xC5, 0x40, 0xE9, }, - 133, - false}, + 133}, {{ 0xFF, 0x56, 0x80, 0xCD, 0x73, 0xA5, 0x70, 0x3D, 0xA0, 0x48, 0x17, 0xA0, 0x75, 0xFD, 0x46, 0x25, 0x06, 0xA7, 0x35, 0x06, 0xC4, 0xB8, 0x1A, 0x15, 0x83, 0xEF, 0x54, 0x94, 0x78, 0xD2, 0x64, 0x76, }, - 54, - true}, + 54}, }; } // namespace diff --git a/naiveproxy/src/net/cert/x509_util.cc b/naiveproxy/src/net/cert/x509_util.cc index f08050986b..521f0eeb36 100644 --- a/naiveproxy/src/net/cert/x509_util.cc +++ b/naiveproxy/src/net/cert/x509_util.cc @@ -15,7 +15,6 @@ #include #include -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/notreached.h" @@ -98,24 +97,6 @@ const EVP_MD* ToEVP(DigestAlgorithm alg) { return nullptr; } -class BufferPoolSingleton { - public: - BufferPoolSingleton() { - crypto::EnsureOpenSSLInit(); - - pool_ = CRYPTO_BUFFER_POOL_new(); - } - - CRYPTO_BUFFER_POOL* pool() { return pool_; } - - private: - // The singleton is leaky, so there is no need to use a smart pointer. - raw_ptr pool_; -}; - -base::LazyInstance::Leaky g_buffer_pool_singleton = - LAZY_INSTANCE_INITIALIZER; - } // namespace // Adds an X.509 Name with the specified distinguished name to |cbb|. @@ -347,7 +328,6 @@ bool CreateCert(EVP_PKEY* subject_key, std::string_view issuer, EVP_PKEY* issuer_key, std::string* der_encoded) { - crypto::EnsureOpenSSLInit(); crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); // See RFC 5280, section 4.1. First, construct the TBSCertificate. @@ -449,7 +429,8 @@ bool CreateSelfSignedCert(EVP_PKEY* key, } CRYPTO_BUFFER_POOL* GetBufferPool() { - return g_buffer_pool_singleton.Get().pool(); + static CRYPTO_BUFFER_POOL* const kSharedPool = CRYPTO_BUFFER_POOL_new(); + return kSharedPool; } bssl::UniquePtr CreateCryptoBuffer( @@ -510,7 +491,6 @@ scoped_refptr CreateX509CertificateFromBuffers( bool CreateCertBuffersFromPKCS7Bytes( base::span data, std::vector>* handles) { - crypto::EnsureOpenSSLInit(); crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE); CBS der_data; diff --git a/naiveproxy/src/net/cert/x509_util.h b/naiveproxy/src/net/cert/x509_util.h index 30d18af0f5..25be9fe32c 100644 --- a/naiveproxy/src/net/cert/x509_util.h +++ b/naiveproxy/src/net/cert/x509_util.h @@ -13,6 +13,7 @@ #include #include "base/containers/span.h" +#include "base/memory/raw_span.h" #include "base/memory/scoped_refptr.h" #include "base/time/time.h" #include "crypto/signature_verifier.h" @@ -96,9 +97,9 @@ struct NET_EXPORT Extension { ~Extension(); Extension(const Extension&); - base::span oid; + base::raw_span oid; bool critical; - base::span contents; + base::raw_span contents; }; // Create a certificate signed by |issuer_key| and write it to |der_encoded|. diff --git a/naiveproxy/src/net/cert_net/cert_net_fetcher_url_request.cc b/naiveproxy/src/net/cert_net/cert_net_fetcher_url_request.cc index a99c57f333..812755b74c 100644 --- a/naiveproxy/src/net/cert_net/cert_net_fetcher_url_request.cc +++ b/naiveproxy/src/net/cert_net/cert_net_fetcher_url_request.cc @@ -72,6 +72,7 @@ #include "base/functional/callback_helpers.h" #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" +#include "base/not_fatal_until.h" #include "base/numerics/safe_math.h" #include "base/ranges/algorithm.h" #include "base/synchronization/waitable_event.h" @@ -467,7 +468,7 @@ void Job::DetachRequest(CertNetFetcherURLRequest::RequestCore* request) { std::unique_ptr delete_this; auto it = base::ranges::find(requests_, request); - DCHECK(it != requests_.end()); + CHECK(it != requests_.end(), base::NotFatalUntil::M130); requests_.erase(it); // If there are no longer any requests attached to the job then diff --git a/naiveproxy/src/net/cookies/cookie_access_result.h b/naiveproxy/src/net/cookies/cookie_access_result.h index b720005554..0953da51ca 100644 --- a/naiveproxy/src/net/cookies/cookie_access_result.h +++ b/naiveproxy/src/net/cookies/cookie_access_result.h @@ -63,8 +63,9 @@ struct NET_EXPORT CookieAccessResult { inline void PrintTo(const CookieAccessResult& car, std::ostream* os) { *os << "{ { "; PrintTo(car.status, os); - *os << " }, " << static_cast(car.effective_same_site) << ", " - << static_cast(car.access_semantics) << ", " + *os << " }, effective_same_site=" << static_cast(car.effective_same_site) + << ", access_semantics=" << static_cast(car.access_semantics) + << ", is_allowed_to_access_secure_cookies=" << car.is_allowed_to_access_secure_cookies << " }"; } diff --git a/naiveproxy/src/net/cookies/cookie_monster.cc b/naiveproxy/src/net/cookies/cookie_monster.cc index 8e1134654e..98b23597fb 100644 --- a/naiveproxy/src/net/cookies/cookie_monster.cc +++ b/naiveproxy/src/net/cookies/cookie_monster.cc @@ -737,9 +737,17 @@ void CookieMonster::GetCookieListWithOptions( if (!cookie_partition_key_collection.IsEmpty()) { if (cookie_partition_key_collection.ContainsAllKeys()) { - for (const auto& it : partitioned_cookies_) { + for (PartitionedCookieMap::iterator partition_it = + partitioned_cookies_.begin(); + partition_it != partitioned_cookies_.end();) { + // InternalDeletePartitionedCookie may invalidate |partition_it| if + // that cookie partition only has one cookie and it expires. + auto cur_partition_it = partition_it; + ++partition_it; + std::vector partitioned_cookie_ptrs = - FindPartitionedCookiesForRegistryControlledHost(it.first, url); + FindPartitionedCookiesForRegistryControlledHost( + cur_partition_it->first, url); cookie_ptrs.insert(cookie_ptrs.end(), partitioned_cookie_ptrs.begin(), partitioned_cookie_ptrs.end()); } diff --git a/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.cc b/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.cc index 7005514d7d..d9a9646206 100644 --- a/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.cc +++ b/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.cc @@ -8,6 +8,7 @@ #include #include "base/functional/bind.h" +#include "base/not_fatal_until.h" #include "base/task/single_thread_task_runner.h" #include "base/task/task_runner.h" #include "net/base/features.h" @@ -251,12 +252,14 @@ void CookieMonsterChangeDispatcher::UnlinkSubscription( auto cookie_domain_map_iterator = cookie_domain_map_.find(subscription->domain_key()); - DCHECK(cookie_domain_map_iterator != cookie_domain_map_.end()); + CHECK(cookie_domain_map_iterator != cookie_domain_map_.end(), + base::NotFatalUntil::M130); CookieNameMap& cookie_name_map = cookie_domain_map_iterator->second; auto cookie_name_map_iterator = cookie_name_map.find(subscription->name_key()); - DCHECK(cookie_name_map_iterator != cookie_name_map.end()); + CHECK(cookie_name_map_iterator != cookie_name_map.end(), + base::NotFatalUntil::M130); SubscriptionList& subscription_list = cookie_name_map_iterator->second; subscription->RemoveFromList(); diff --git a/naiveproxy/src/net/cookies/cookie_partition_key.cc b/naiveproxy/src/net/cookies/cookie_partition_key.cc index deb7cafdde..cf87c1c34d 100644 --- a/naiveproxy/src/net/cookies/cookie_partition_key.cc +++ b/naiveproxy/src/net/cookies/cookie_partition_key.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/types/optional_util.h" #include "net/base/cronet_buildflags.h" +#include "net/base/features.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_util.h" #include "net/cookies/site_for_cookies.h" @@ -37,6 +38,7 @@ std::string SerializeSchemefulSite(const SchemefulSite& site) { } // namespace CookiePartitionKey::SerializedCookiePartitionKey::SerializedCookiePartitionKey( + base::PassKey key, const std::string& site, bool has_cross_site_ancestor) : top_level_site_(site), @@ -47,6 +49,17 @@ CookiePartitionKey::SerializedCookiePartitionKey::TopLevelSite() const { return top_level_site_; } +std::string CookiePartitionKey::SerializedCookiePartitionKey::GetDebugString() + const { + std::string out = TopLevelSite(); + if (base::FeatureList::IsEnabled( + features::kAncestorChainBitEnabledInPartitionedCookies)) { + base::StrAppend( + &out, {", ", has_cross_site_ancestor() ? "cross-site" : "same-site"}); + } + return out; +} + #if 0 CookiePartitionKey::CookiePartitionKey(mojo::DefaultConstruct::Tag) {} #endif @@ -108,8 +121,8 @@ bool CookiePartitionKey::operator<(const CookiePartitionKey& other) const { base::expected CookiePartitionKey::Serialize(const std::optional& in) { if (!in) { - return base::ok( - SerializedCookiePartitionKey(kEmptyCookiePartitionKey, true)); + return base::ok(SerializedCookiePartitionKey( + base::PassKey(), kEmptyCookiePartitionKey, true)); } if (!in->IsSerializeable()) { @@ -117,7 +130,8 @@ CookiePartitionKey::Serialize(const std::optional& in) { } return base::ok(SerializedCookiePartitionKey( - SerializeSchemefulSite(in->site_), in->IsThirdParty())); + base::PassKey(), SerializeSchemefulSite(in->site_), + in->IsThirdParty())); } std::optional CookiePartitionKey::FromNetworkIsolationKey( diff --git a/naiveproxy/src/net/cookies/cookie_partition_key.h b/naiveproxy/src/net/cookies/cookie_partition_key.h index 97e403d03e..4ef149ff8d 100644 --- a/naiveproxy/src/net/cookies/cookie_partition_key.h +++ b/naiveproxy/src/net/cookies/cookie_partition_key.h @@ -31,14 +31,16 @@ class NET_EXPORT CookiePartitionKey { const std::string& TopLevelSite() const; bool has_cross_site_ancestor() const; - private: - friend class CookiePartitionKey; + std::string GetDebugString() const; + // This constructor does not check if the values being serialized are valid. // The caller of this function must ensure that only valid values are passed // to this method. - explicit SerializedCookiePartitionKey(const std::string& site, - bool has_cross_site_ancestor); + SerializedCookiePartitionKey(base::PassKey key, + const std::string& site, + bool has_cross_site_ancestor); + private: std::string top_level_site_; bool has_cross_site_ancestor_; }; diff --git a/naiveproxy/src/net/cookies/cookie_util.h b/naiveproxy/src/net/cookies/cookie_util.h index a962e55200..419c8ebb05 100644 --- a/naiveproxy/src/net/cookies/cookie_util.h +++ b/naiveproxy/src/net/cookies/cookie_util.h @@ -56,6 +56,20 @@ enum class StorageAccessResult { kMaxValue = ACCESS_ALLOWED_SCHEME, }; +// This enum's values correspond to the values of the HTTP request header +// `Sec-Fetch-Storage-Access`, which is applied to cross-site requests. +enum class StorageAccessStatus { + // Applies to context that does not have unpartitioned cookie access, and does + // not have the `storage-access` permission. + kNone = 0, + // Applies to context that has `storage-access` permission, but has not opted + // into using it; the context also does not have unpartitioned cookie access + // through some other means. + kInactive = 1, + // Applies to context that has unpartitioned cookie access. + kActive = 2 +}; + // Helper to fire telemetry indicating if a given request for storage was // allowed or not by the provided |result|. NET_EXPORT void FireStorageAccessHistogram(StorageAccessResult result); diff --git a/naiveproxy/src/net/device_bound_sessions/cookie_craving.cc b/naiveproxy/src/net/device_bound_sessions/cookie_craving.cc index 49eb51cfb3..657bead13b 100644 --- a/naiveproxy/src/net/device_bound_sessions/cookie_craving.cc +++ b/naiveproxy/src/net/device_bound_sessions/cookie_craving.cc @@ -13,7 +13,7 @@ #include "net/cookies/parsed_cookie.h" #include "url/url_canon.h" -namespace net { +namespace net::device_bound_sessions { namespace { @@ -266,4 +266,4 @@ std::ostream& operator<<(std::ostream& os, const CookieCraving& cc) { return os; } -} // namespace net +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/cookie_craving.h b/naiveproxy/src/net/device_bound_sessions/cookie_craving.h index 43c1bb5178..d38dc33e7d 100644 --- a/naiveproxy/src/net/device_bound_sessions/cookie_craving.h +++ b/naiveproxy/src/net/device_bound_sessions/cookie_craving.h @@ -15,8 +15,10 @@ #include "net/cookies/cookie_partition_key.h" namespace net { - class CanonicalCookie; +} + +namespace net::device_bound_sessions { // This class represents the need for a certain cookie to be present. It is not // a cookie itself, but rather represents a requirement which can be satisfied @@ -149,6 +151,6 @@ class NET_EXPORT CookieCraving : public CookieBase { // Outputs a debug string, e.g. for more helpful test failure messages. NET_EXPORT std::ostream& operator<<(std::ostream& os, const CookieCraving& cc); -} // namespace net +} // namespace net::device_bound_sessions #endif // NET_DEVICE_BOUND_SESSIONS_COOKIE_CRAVING_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/device_bound_session_params.h b/naiveproxy/src/net/device_bound_sessions/device_bound_session_params.h deleted file mode 100644 index f691949348..0000000000 --- a/naiveproxy/src/net/device_bound_sessions/device_bound_session_params.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_PARAMS_H_ -#define NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_PARAMS_H_ - -namespace net { - -struct DeviceBoundSessionParams {}; - -} // namespace net - -#endif // NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_PARAMS_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/device_bound_session_service.cc b/naiveproxy/src/net/device_bound_sessions/device_bound_session_service.cc deleted file mode 100644 index be49281b8f..0000000000 --- a/naiveproxy/src/net/device_bound_sessions/device_bound_session_service.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/device_bound_sessions/device_bound_session_service.h" - -#include - -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "net/base/features.h" -#include "net/device_bound_sessions/registration_fetcher.h" -#include "net/device_bound_sessions/unexportable_key_service_factory.h" - -namespace net { - -namespace { -class DeviceBoundSessionServiceImpl : public DeviceBoundSessionService { - public: - DeviceBoundSessionServiceImpl( - unexportable_keys::UnexportableKeyService& key_service, - const URLRequestContext* request_context) - : key_service_(key_service), context_(request_context) { - CHECK(context_); - } - - void RegisterBoundSession( - DeviceBoundSessionRegistrationFetcherParam registration_params, - const IsolationInfo& isolation_info) override { - RegistrationFetcher::StartCreateTokenAndFetch( - std::move(registration_params), key_service_.get(), context_.get(), - isolation_info, - base::BindOnce(&DeviceBoundSessionServiceImpl::OnRegistrationComplete, - weak_factory_.GetWeakPtr())); - } - - // TODO(kristianm): Parse the registration params and create a session - // in the service. - void OnRegistrationComplete(std::optional params) {} - - private: - const raw_ref key_service_; - raw_ptr context_; - base::WeakPtrFactory weak_factory_{this}; -}; -} // namespace - -std::unique_ptr DeviceBoundSessionService::Create( - const URLRequestContext* request_context) { - unexportable_keys::UnexportableKeyService* service = - UnexportableKeyServiceFactory::GetInstance()->GetShared(); - if (!service) { - return nullptr; - } - - return std::make_unique(*service, - request_context); -} - -} // namespace net diff --git a/naiveproxy/src/net/device_bound_sessions/device_bound_session_service.h b/naiveproxy/src/net/device_bound_sessions/device_bound_session_service.h deleted file mode 100644 index 4ec330d1c0..0000000000 --- a/naiveproxy/src/net/device_bound_sessions/device_bound_session_service.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_SERVICE_H_ -#define NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_SERVICE_H_ - -#include - -#include "net/base/net_export.h" -#include "net/device_bound_sessions/device_bound_session_params.h" -#include "net/device_bound_sessions/device_bound_session_registration_fetcher_param.h" - -namespace net { - -class IsolationInfo; -class URLRequestContext; - -// Main class for Device Bound Session Credentials (DBSC). -// Full information can be found at https://github.com/WICG/dbsc -class NET_EXPORT DeviceBoundSessionService { - public: - // Returns nullptr if unexportable key provider is not supported by the - // platform or the device. - static std::unique_ptr Create( - const URLRequestContext* request_context); - - DeviceBoundSessionService(const DeviceBoundSessionService&) = delete; - DeviceBoundSessionService& operator=(const DeviceBoundSessionService&) = - delete; - - virtual ~DeviceBoundSessionService() = default; - - // Called to register a new session after getting a Sec-Session-Registration - // header. - // Registration parameters to be used for creating the registration - // request. - // Isolation info to be used for registration request, this should be the - // same as was used for the response with the Sec-Session-Registration - // header. - virtual void RegisterBoundSession( - DeviceBoundSessionRegistrationFetcherParam registration_params, - const IsolationInfo& isolation_info) = 0; - - protected: - DeviceBoundSessionService() = default; -}; - -} // namespace net - -#endif // NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_SERVICE_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/registration_fetcher.cc b/naiveproxy/src/net/device_bound_sessions/registration_fetcher.cc index 0e47e50931..827dfa661c 100644 --- a/naiveproxy/src/net/device_bound_sessions/registration_fetcher.cc +++ b/naiveproxy/src/net/device_bound_sessions/registration_fetcher.cc @@ -4,14 +4,17 @@ #include "net/device_bound_sessions/registration_fetcher.h" +#include + #include "components/unexportable_keys/background_task_priority.h" #include "components/unexportable_keys/unexportable_key_service.h" #include "net/base/io_buffer.h" #include "net/device_bound_sessions/session_binding_utils.h" +#include "net/device_bound_sessions/session_json_utils.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context.h" -namespace net { +namespace net::device_bound_sessions { namespace { @@ -82,8 +85,8 @@ void OnDataSigned( return; } - std::move(callback).Run( - RegistrationFetcher::RegistrationTokenResult(registration_token.value())); + std::move(callback).Run(RegistrationFetcher::RegistrationTokenResult( + registration_token.value(), key_id)); } void OnKeyGenerated( @@ -150,6 +153,7 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { if (!redirect_info.new_url.SchemeIsCryptographic()) { request->Cancel(); OnResponseCompleted(); + // *this is deleted here } } @@ -166,6 +170,7 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { void OnResponseStarted(URLRequest* request, int net_error) override { if (net_error != OK) { OnResponseCompleted(); + // *this is deleted here return; } @@ -173,6 +178,7 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { int response_code = headers ? headers->response_code() : 0; if (response_code < 200 || response_code >= 300) { OnResponseCompleted(); + // *this is deleted here return; } @@ -182,6 +188,7 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { OnReadCompleted(request, bytes_read); } else if (bytes_read != ERR_IO_PENDING) { OnResponseCompleted(); + // *this is deleted here } } @@ -196,11 +203,12 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { if (bytes_read != ERR_IO_PENDING) { OnResponseCompleted(); + // *this is deleted here } } RegistrationFetcherImpl( - DeviceBoundSessionRegistrationFetcherParam registration_params, + RegistrationFetcherParam registration_params, unexportable_keys::UnexportableKeyService& key_service, const URLRequestContext* context, const IsolationInfo& isolation_info, @@ -216,12 +224,13 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { void OnRegistrationTokenCreated( std::optional result) { - if (!result.has_value()) { + if (!result) { RunCallbackAndDeleteSelf(std::nullopt); return; } - StartFetchingRegistration(result.value().registration_token); + key_id_ = result->key_id; + StartFetchingRegistration(result->registration_token); } private: @@ -244,31 +253,42 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { } void OnResponseCompleted() { - // TODO(kristianm): Parse response in data_received_ - // For now just mark it as correct if *any* content was received. if (!data_received_.empty()) { - DeviceBoundSessionParams params; - RunCallbackAndDeleteSelf(params); + std::optional params = + ParseSessionInstructionJson(data_received_); + if (params) { + RunCallbackAndDeleteSelf( + RegistrationFetcher::RegistrationCompleteParams(std::move(*params), + *key_id_)); + } else { + RunCallbackAndDeleteSelf(std::nullopt); + } } else { RunCallbackAndDeleteSelf(std::nullopt); } + // *this is deleted here } // Running callback when fetching is complete or on error. // Deletes `this` afterwards. void RunCallbackAndDeleteSelf( - std::optional params) { + std::optional params) { std::move(callback_).Run(std::move(params)); delete this; } // State passed in to constructor - DeviceBoundSessionRegistrationFetcherParam registration_params_; + RegistrationFetcherParam registration_params_; const raw_ref key_service_; raw_ptr context_; IsolationInfo isolation_info_; RegistrationFetcher::RegistrationCompleteCallback callback_; + // Set during key creation, before sending request to fetch data. + // Should always be nullopt before that, and always a valid key after key + // creation. + std::optional key_id_ = std::nullopt; + // Created to fetch data std::unique_ptr request_; scoped_refptr buf_; @@ -278,7 +298,7 @@ class RegistrationFetcherImpl : public URLRequest::Delegate { } // namespace void RegistrationFetcher::StartCreateTokenAndFetch( - DeviceBoundSessionRegistrationFetcherParam registration_params, + RegistrationFetcherParam registration_params, unexportable_keys::UnexportableKeyService& key_service, // TODO(kristianm): Check the lifetime of context and make sure this use // is safe. @@ -311,4 +331,4 @@ void RegistrationFetcher::CreateTokenAsyncForTesting( std::move(callback)); } -} // namespace net +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/registration_fetcher.h b/naiveproxy/src/net/device_bound_sessions/registration_fetcher.h index c2a124c7ea..feac96952a 100644 --- a/naiveproxy/src/net/device_bound_sessions/registration_fetcher.h +++ b/naiveproxy/src/net/device_bound_sessions/registration_fetcher.h @@ -6,11 +6,12 @@ #define NET_DEVICE_BOUND_SESSIONS_REGISTRATION_FETCHER_H_ #include "base/functional/callback_forward.h" +#include "components/unexportable_keys/unexportable_key_service.h" #include "net/base/isolation_info.h" #include "net/base/net_errors.h" #include "net/base/net_export.h" -#include "net/device_bound_sessions/device_bound_session_params.h" -#include "net/device_bound_sessions/device_bound_session_registration_fetcher_param.h" +#include "net/device_bound_sessions/registration_fetcher_param.h" +#include "net/device_bound_sessions/session_params.h" #include "net/http/http_response_headers.h" #include "url/gurl.h" @@ -22,7 +23,7 @@ namespace unexportable_keys { class UnexportableKeyService; } -namespace net { +namespace net::device_bound_sessions { // This class creates a new unexportable key, creates a registration JWT and // signs it with the new key, and makes the network request to the DBSC @@ -30,15 +31,18 @@ namespace net { // instructions. class NET_EXPORT RegistrationFetcher { public: + struct RegistrationCompleteParams { + SessionParams params; + unexportable_keys::UnexportableKeyId key_id; + }; + using RegistrationCompleteCallback = - base::OnceCallback)>; + base::OnceCallback)>; // TODO(kristianm): Add more parameters when the returned JSON is parsed. struct NET_EXPORT RegistrationTokenResult { - explicit RegistrationTokenResult(std::string registration_token) - : registration_token(std::move(registration_token)) {} - std::string registration_token; + unexportable_keys::UnexportableKeyId key_id; }; // Creates an unexportable key from the key service, creates a registration @@ -48,7 +52,7 @@ class NET_EXPORT RegistrationFetcher { // This can fail during key creation, signing and during the network request, // and if so it the callback with be called with a std::nullopt. static void StartCreateTokenAndFetch( - DeviceBoundSessionRegistrationFetcherParam registration_params, + RegistrationFetcherParam registration_params, unexportable_keys::UnexportableKeyService& key_service, const URLRequestContext* context, const IsolationInfo& isolation_info, @@ -66,6 +70,6 @@ class NET_EXPORT RegistrationFetcher { callback); }; -} // namespace net +} // namespace net::device_bound_sessions #endif // NET_DEVICE_BOUND_SESSIONS_REGISTRATION_FETCHER_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/device_bound_session_registration_fetcher_param.cc b/naiveproxy/src/net/device_bound_sessions/registration_fetcher_param.cc similarity index 68% rename from naiveproxy/src/net/device_bound_sessions/device_bound_session_registration_fetcher_param.cc rename to naiveproxy/src/net/device_bound_sessions/registration_fetcher_param.cc index 6cb30dc902..4aa603dfcb 100644 --- a/naiveproxy/src/net/device_bound_sessions/device_bound_session_registration_fetcher_param.cc +++ b/naiveproxy/src/net/device_bound_sessions/registration_fetcher_param.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/device_bound_sessions/device_bound_session_registration_fetcher_param.h" +#include "net/device_bound_sessions/registration_fetcher_param.h" #include @@ -38,33 +38,25 @@ std::optional AlgoFromString( } } // namespace -namespace net { +namespace net::device_bound_sessions { -DeviceBoundSessionRegistrationFetcherParam:: - DeviceBoundSessionRegistrationFetcherParam( - DeviceBoundSessionRegistrationFetcherParam&& other) = default; +RegistrationFetcherParam::RegistrationFetcherParam( + RegistrationFetcherParam&& other) = default; -DeviceBoundSessionRegistrationFetcherParam& -DeviceBoundSessionRegistrationFetcherParam:: - operator=( - DeviceBoundSessionRegistrationFetcherParam&& other) noexcept = default; +RegistrationFetcherParam& RegistrationFetcherParam::operator=( + RegistrationFetcherParam&& other) noexcept = default; -DeviceBoundSessionRegistrationFetcherParam:: - ~DeviceBoundSessionRegistrationFetcherParam() = - default; +RegistrationFetcherParam::~RegistrationFetcherParam() = default; -DeviceBoundSessionRegistrationFetcherParam:: - DeviceBoundSessionRegistrationFetcherParam( - GURL registration_endpoint, - std::vector - supported_algos, - std::string challenge) - : registration_endpoint_(std::move(registration_endpoint)), - supported_algos_(std::move(supported_algos)), - challenge_(std::move(challenge)) {} +RegistrationFetcherParam::RegistrationFetcherParam( + GURL registration_endpoint, + std::vector supported_algos, + std::string challenge) + : registration_endpoint_(std::move(registration_endpoint)), + supported_algos_(std::move(supported_algos)), + challenge_(std::move(challenge)) {} -std::optional -DeviceBoundSessionRegistrationFetcherParam::ParseItem( +std::optional RegistrationFetcherParam::ParseItem( const GURL& request_url, const structured_headers::ParameterizedMember& session_registration) { std::vector supported_algos; @@ -120,16 +112,15 @@ DeviceBoundSessionRegistrationFetcherParam::ParseItem( return std::nullopt; } - return DeviceBoundSessionRegistrationFetcherParam( - std::move(registration_endpoint), std::move(supported_algos), - std::move(challenge)); + return RegistrationFetcherParam(std::move(registration_endpoint), + std::move(supported_algos), + std::move(challenge)); } -std::vector -DeviceBoundSessionRegistrationFetcherParam::CreateIfValid( +std::vector RegistrationFetcherParam::CreateIfValid( const GURL& request_url, const net::HttpResponseHeaders* headers) { - std::vector params; + std::vector params; if (!request_url.is_valid()) { return params; } @@ -148,7 +139,7 @@ DeviceBoundSessionRegistrationFetcherParam::CreateIfValid( for (const auto& item : *list) { if (item.member_is_inner_list) { - std::optional fetcher_param = + std::optional fetcher_param = ParseItem(request_url, item); if (fetcher_param) { params.push_back(std::move(*fetcher_param)); @@ -160,14 +151,13 @@ DeviceBoundSessionRegistrationFetcherParam::CreateIfValid( } // static -DeviceBoundSessionRegistrationFetcherParam -DeviceBoundSessionRegistrationFetcherParam::CreateInstanceForTesting( +RegistrationFetcherParam RegistrationFetcherParam::CreateInstanceForTesting( GURL registration_endpoint, std::vector supported_algos, std::string challenge) { - return DeviceBoundSessionRegistrationFetcherParam( - std::move(registration_endpoint), std::move(supported_algos), - std::move(challenge)); + return RegistrationFetcherParam(std::move(registration_endpoint), + std::move(supported_algos), + std::move(challenge)); } -} // namespace net +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/device_bound_session_registration_fetcher_param.h b/naiveproxy/src/net/device_bound_sessions/registration_fetcher_param.h similarity index 63% rename from naiveproxy/src/net/device_bound_sessions/device_bound_session_registration_fetcher_param.h rename to naiveproxy/src/net/device_bound_sessions/registration_fetcher_param.h index a82327cb19..d8e9ccf383 100644 --- a/naiveproxy/src/net/device_bound_sessions/device_bound_session_registration_fetcher_param.h +++ b/naiveproxy/src/net/device_bound_sessions/registration_fetcher_param.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_REGISTRATION_FETCHER_PARAM_H_ -#define NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_REGISTRATION_FETCHER_PARAM_H_ +#ifndef NET_DEVICE_BOUND_SESSIONS_REGISTRATION_FETCHER_PARAM_H_ +#define NET_DEVICE_BOUND_SESSIONS_REGISTRATION_FETCHER_PARAM_H_ #include #include @@ -15,7 +15,7 @@ #include "net/http/structured_headers.h" #include "url/gurl.h" -namespace net { +namespace net::device_bound_sessions { // Class to parse Sec-Session-Registration header. // See explainer for details: @@ -25,28 +25,25 @@ namespace net { // representing the challenge, the other is a string representing // the path. Example: // (RS256 ES256);path="start";challenge="code" -class NET_EXPORT DeviceBoundSessionRegistrationFetcherParam { +class NET_EXPORT RegistrationFetcherParam { public: - DeviceBoundSessionRegistrationFetcherParam( - DeviceBoundSessionRegistrationFetcherParam&& other); - DeviceBoundSessionRegistrationFetcherParam& operator=( - DeviceBoundSessionRegistrationFetcherParam&& other) noexcept; + RegistrationFetcherParam(RegistrationFetcherParam&& other); + RegistrationFetcherParam& operator=( + RegistrationFetcherParam&& other) noexcept; // Disabled to make accidental copies compile errors. - DeviceBoundSessionRegistrationFetcherParam( - const DeviceBoundSessionRegistrationFetcherParam& other) = delete; - DeviceBoundSessionRegistrationFetcherParam& operator=( - const DeviceBoundSessionRegistrationFetcherParam&) = delete; - ~DeviceBoundSessionRegistrationFetcherParam(); + RegistrationFetcherParam(const RegistrationFetcherParam& other) = delete; + RegistrationFetcherParam& operator=(const RegistrationFetcherParam&) = delete; + ~RegistrationFetcherParam(); // Returns a vector of valid instances. // TODO(chlily): Get IsolationInfo from the request as well - static std::vector CreateIfValid( + static std::vector CreateIfValid( const GURL& request_url, const HttpResponseHeaders* headers); // Convenience constructor for testing. - static DeviceBoundSessionRegistrationFetcherParam CreateInstanceForTesting( + static RegistrationFetcherParam CreateInstanceForTesting( GURL registration_endpoint, std::vector supported_algos, @@ -62,13 +59,13 @@ class NET_EXPORT DeviceBoundSessionRegistrationFetcherParam { const std::string& challenge() const { return challenge_; } private: - DeviceBoundSessionRegistrationFetcherParam( + RegistrationFetcherParam( GURL registration_endpoint, std::vector supported_algos, std::string challenge); - static std::optional ParseItem( + static std::optional ParseItem( const GURL& request_url, const structured_headers::ParameterizedMember& session_registration); @@ -79,6 +76,6 @@ class NET_EXPORT DeviceBoundSessionRegistrationFetcherParam { std::string challenge_; }; -} // namespace net +} // namespace net::device_bound_sessions -#endif // NET_DEVICE_BOUND_SESSIONS_DEVICE_BOUND_SESSION_REGISTRATION_FETCHER_PARAM_H_ +#endif // NET_DEVICE_BOUND_SESSIONS_REGISTRATION_FETCHER_PARAM_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/session_binding_utils.cc b/naiveproxy/src/net/device_bound_sessions/session_binding_utils.cc index 4bed15a153..5af4d13b31 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_binding_utils.cc +++ b/naiveproxy/src/net/device_bound_sessions/session_binding_utils.cc @@ -12,7 +12,6 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/strings/strcat.h" -#include "base/strings/string_piece.h" #include "base/time/time.h" #include "base/values.h" #include "crypto/sha2.h" @@ -21,7 +20,7 @@ #include "third_party/boringssl/src/include/openssl/ecdsa.h" #include "url/gurl.h" -namespace net { +namespace net::device_bound_sessions { namespace { @@ -55,7 +54,7 @@ base::Value::Dict CreatePublicKeyInfo(base::span pubkey) { std::optional CreateHeaderAndPayloadWithCustomPayload( crypto::SignatureVerifier::SignatureAlgorithm algorithm, - base::StringPiece schema, + std::string_view schema, const base::Value::Dict& payload) { auto header = base::Value::Dict() .Set("alg", SignatureAlgorithmToString(algorithm)) @@ -109,7 +108,7 @@ std::optional> ConvertDERSignatureToRaw( } // namespace std::optional CreateKeyRegistrationHeaderAndPayload( - base::StringPiece challenge, + std::string_view challenge, const GURL& registration_url, crypto::SignatureVerifier::SignatureAlgorithm algorithm, base::span pubkey, @@ -131,10 +130,10 @@ std::optional CreateKeyRegistrationHeaderAndPayload( std::optional CreateKeyAssertionHeaderAndPayload( crypto::SignatureVerifier::SignatureAlgorithm algorithm, base::span pubkey, - base::StringPiece client_id, - base::StringPiece challenge, + std::string_view client_id, + std::string_view challenge, const GURL& destination_url, - base::StringPiece name_space) { + std::string_view name_space) { auto payload = base::Value::Dict() .Set("sub", client_id) .Set("aud", destination_url.spec()) @@ -147,7 +146,7 @@ std::optional CreateKeyAssertionHeaderAndPayload( } std::optional AppendSignatureToHeaderAndPayload( - base::StringPiece header_and_payload, + std::string_view header_and_payload, crypto::SignatureVerifier::SignatureAlgorithm algorithm, base::span signature) { std::optional> signature_holder; @@ -163,4 +162,4 @@ std::optional AppendSignatureToHeaderAndPayload( {header_and_payload, ".", Base64UrlEncode(as_string_view(signature))}); } -} // namespace net +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/session_binding_utils.h b/naiveproxy/src/net/device_bound_sessions/session_binding_utils.h index 3db928ef7b..8ebff264f0 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_binding_utils.h +++ b/naiveproxy/src/net/device_bound_sessions/session_binding_utils.h @@ -7,9 +7,9 @@ #include #include +#include #include "base/containers/span.h" -#include "base/strings/string_piece.h" #include "crypto/signature_verifier.h" #include "net/base/net_export.h" @@ -19,11 +19,11 @@ namespace base { class Time; } -namespace net { +namespace net::device_bound_sessions { // Creates header and payload parts of a registration JWT. std::optional NET_EXPORT CreateKeyRegistrationHeaderAndPayload( - base::StringPiece challenge, + std::string_view challenge, const GURL& registration_url, crypto::SignatureVerifier::SignatureAlgorithm algorithm, base::span pubkey, @@ -32,10 +32,10 @@ std::optional NET_EXPORT CreateKeyRegistrationHeaderAndPayload( // Appends `signature` generated by `algorithm` to provided `header_and_payload` // to form a complete JWT. std::optional NET_EXPORT AppendSignatureToHeaderAndPayload( - base::StringPiece header_and_payload, + std::string_view header_and_payload, crypto::SignatureVerifier::SignatureAlgorithm algorithm, base::span signature); -} // namespace net +} // namespace net::device_bound_sessions #endif // NET_DEVICE_BOUND_SESSIONS_SESSION_BINDING_UTILS_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.cc b/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.cc index 208ee3c17d..abf0c71e3d 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.cc +++ b/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.cc @@ -15,7 +15,8 @@ #include "net/base/scheme_host_port_matcher_rule.h" #include "net/base/url_util.h" -namespace net { +namespace net::device_bound_sessions { + namespace { bool IsIncludeSiteAllowed(const url::Origin& origin) { @@ -251,4 +252,4 @@ size_t SessionInclusionRules::num_url_rules_for_testing() const { return url_rules_.size(); } -} // namespace net +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.h b/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.h index 543677fed4..89d68aba77 100644 --- a/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.h +++ b/naiveproxy/src/net/device_bound_sessions/session_inclusion_rules.h @@ -14,7 +14,7 @@ #include "net/base/schemeful_site.h" #include "url/origin.h" -namespace net { +namespace net::device_bound_sessions { // This class represents a set of rules that define which network requests may // potentially be deferred on account of an active DBSC session. It is derived @@ -122,6 +122,6 @@ class NET_EXPORT SessionInclusionRules final { std::vector url_rules_; }; -} // namespace net +} // namespace net::device_bound_sessions #endif // NET_DEVICE_BOUND_SESSIONS_SESSION_INCLUSION_RULES_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/session_json_utils.cc b/naiveproxy/src/net/device_bound_sessions/session_json_utils.cc new file mode 100644 index 0000000000..60471070b2 --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/session_json_utils.cc @@ -0,0 +1,117 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/device_bound_sessions/session_json_utils.h" + +#include "base/json/json_reader.h" + +namespace net::device_bound_sessions { + +namespace { + +SessionParams::Scope ParseScope(const base::Value::Dict& scope_dict) { + SessionParams::Scope scope; + + std::optional include_site = scope_dict.FindBool("include_site"); + scope.include_site = include_site.value_or(false); + const base::Value::List* specifications_list = + scope_dict.FindList("scope_specification"); + if (!specifications_list) { + return scope; + } + + for (const auto& specification : *specifications_list) { + const base::Value::Dict* specification_dict = specification.GetIfDict(); + if (!specification_dict) { + continue; + } + + const std::string* type = specification_dict->FindString("type"); + const std::string* domain = specification_dict->FindString("domain"); + const std::string* path = specification_dict->FindString("path"); + if (type && !type->empty() && domain && !domain->empty() && path && + !path->empty()) { + if (*type == "include") { + scope.specifications.push_back(SessionParams::Scope::Specification{ + SessionParams::Scope::Specification::Type::kInclude, *domain, + *path}); + } else if (*type == "exclude") { + scope.specifications.push_back(SessionParams::Scope::Specification{ + SessionParams::Scope::Specification::Type::kExclude, *domain, + *path}); + } + } + } + + return scope; +} + +std::vector ParseCredentials( + const base::Value::List& credentials_list) { + std::vector cookie_credentials; + for (const auto& json_credential : credentials_list) { + SessionParams::Credential credential; + const base::Value::Dict* credential_dict = json_credential.GetIfDict(); + if (!credential_dict) { + continue; + } + const std::string* type = credential_dict->FindString("type"); + if (!type || *type != "cookie") { + continue; + } + const std::string* name = credential_dict->FindString("name"); + const std::string* attributes = credential_dict->FindString("attributes"); + if (name && attributes) { + cookie_credentials.push_back( + SessionParams::Credential{*name, *attributes}); + } + } + + return cookie_credentials; +} + +} // namespace + +std::optional ParseSessionInstructionJson( + std::string_view response_json) { + // TODO(kristianm): Skip XSSI-escapes, see for example: + // https://hg.mozilla.org/mozilla-central/rev/4cee9ec9155e + // Discuss with others if XSSI should be part of the standard. + + // TODO(kristianm): Decide if the standard should require parsing + // to fail fully if any item is wrong, or if that item should be + // ignored. + + std::optional maybe_root = base::JSONReader::ReadDict( + response_json, base::JSON_PARSE_RFC, /*max_depth=*/5u); + if (!maybe_root) { + return std::nullopt; + } + + base::Value::Dict* scope_dict = maybe_root->FindDict("scope"); + + std::string* session_id = maybe_root->FindString("session_identifier"); + if (!session_id || session_id->empty()) { + return std::nullopt; + } + + std::string* refresh_url = maybe_root->FindString("refresh_url"); + + std::vector credentials; + base::Value::List* credentials_list = maybe_root->FindList("credentials"); + if (credentials_list) { + credentials = ParseCredentials(*credentials_list); + } + + if (credentials.empty()) { + return std::nullopt; + } + + return SessionParams( + *session_id, refresh_url ? *refresh_url : "", + scope_dict ? ParseScope(*scope_dict) : SessionParams::Scope{}, + std::move(credentials)); +} + +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/session_json_utils.h b/naiveproxy/src/net/device_bound_sessions/session_json_utils.h new file mode 100644 index 0000000000..5a024db3cd --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/session_json_utils.h @@ -0,0 +1,24 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_DEVICE_BOUND_SESSIONS_SESSION_JSON_UTILS_H_ +#define NET_DEVICE_BOUND_SESSIONS_SESSION_JSON_UTILS_H_ + +#include +#include + +#include "net/device_bound_sessions/session_params.h" + +namespace net::device_bound_sessions { + +// Utilities for parsing the JSON session specification +// https://github.com/WICG/dbsc/blob/main/README.md#session-registration-instructions-json + +// Parse the full JSON as a string +std::optional ParseSessionInstructionJson( + std::string_view response_json); + +} // namespace net::device_bound_sessions + +#endif // NET_DEVICE_BOUND_SESSIONS_SESSION_JSON_UTILS_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/session_params.cc b/naiveproxy/src/net/device_bound_sessions/session_params.cc new file mode 100644 index 0000000000..1ee5b16f98 --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/session_params.cc @@ -0,0 +1,33 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/device_bound_sessions/session_params.h" + +namespace net::device_bound_sessions { + +SessionParams::SessionParams(std::string id, + std::string refresh, + Scope incoming_scope, + std::vector creds) + : session_id(std::move(id)), + refresh_url(std::move(refresh)), + scope(std::move(incoming_scope)), + credentials(std::move(creds)) {} + +SessionParams::SessionParams(SessionParams&& other) = default; + +SessionParams& SessionParams::operator=(SessionParams&& other) = default; + +SessionParams::~SessionParams() = default; + +SessionParams::Scope::Scope() = default; + +SessionParams::Scope::Scope(Scope&& other) = default; + +SessionParams::Scope& SessionParams::Scope::operator=( + SessionParams::Scope&& other) = default; + +SessionParams::Scope::~Scope() = default; + +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/session_params.h b/naiveproxy/src/net/device_bound_sessions/session_params.h new file mode 100644 index 0000000000..0dd2dfe4f2 --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/session_params.h @@ -0,0 +1,64 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_DEVICE_BOUND_SESSIONS_SESSION_PARAMS_H_ +#define NET_DEVICE_BOUND_SESSIONS_SESSION_PARAMS_H_ + +#include +#include + +#include "net/base/net_export.h" + +namespace net::device_bound_sessions { + +// Struct to contain the parameters from the session instruction JSON. +// https://github.com/WICG/dbsc/blob/main/README.md#session-registration-instructions-json +// This is sent on session creation and session refresh +struct NET_EXPORT SessionParams final { + // Scope section of session instructions. + struct Scope { + // Specification section of the session scope instructions. + struct Specification { + enum class Type { kExclude, kInclude }; + bool operator==(const Specification&) const = default; + Type type; + std::string domain; + std::string path; + }; + + // Defaults to false if not in the params + bool include_site = false; + std::vector specifications; + + Scope(); + Scope(Scope&& other); + Scope& operator=(Scope&& other); + ~Scope(); + }; + + // Credential section of the session instruction. + struct Credential { + bool operator==(const Credential&) const = default; + std::string name; + std::string attributes; + }; + + SessionParams(std::string id, + std::string refresh_url, + Scope scope, + std::vector creds); + SessionParams(SessionParams&& other); + SessionParams& operator=(SessionParams&& other); + + ~SessionParams(); + + std::string session_id; + std::string refresh_url; + Scope scope; + std::vector credentials; +}; + +} // namespace net::device_bound_sessions + +#endif // NET_DEVICE_BOUND_SESSIONS_SESSION_PARAMS_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/session_service.cc b/naiveproxy/src/net/device_bound_sessions/session_service.cc new file mode 100644 index 0000000000..baefc5f6bc --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/session_service.cc @@ -0,0 +1,75 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/device_bound_sessions/session_service.h" + +#include + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "net/base/features.h" +#include "net/device_bound_sessions/session_params.h" +#include "net/device_bound_sessions/registration_fetcher.h" +#include "net/device_bound_sessions/unexportable_key_service_factory.h" + +namespace net::device_bound_sessions { + +namespace { +class SessionServiceImpl : public SessionService { + public: + SessionServiceImpl(unexportable_keys::UnexportableKeyService& key_service, + const URLRequestContext* request_context) + : key_service_(key_service), context_(request_context) { + CHECK(context_); + } + + void RegisterBoundSession(RegistrationFetcherParam registration_params, + const IsolationInfo& isolation_info) override { + RegistrationFetcher::StartCreateTokenAndFetch( + std::move(registration_params), key_service_.get(), context_.get(), + isolation_info, + base::BindOnce(&SessionServiceImpl::OnRegistrationComplete, + weak_factory_.GetWeakPtr())); + } + + // TODO(kristianm): Parse the registration params and create a session + // in the service. + void OnRegistrationComplete( + std::optional params) {} + + std::optional GetAnySessionRequiringDeferral( + URLRequest* request) override { + return std::nullopt; + } + + // TODO(kristianm): Actually send the refresh request, for now continue + // with sending the request right away. + void DeferRequestForRefresh( + std::string session_id, + RefreshCompleteCallback restart_callback, + RefreshCompleteCallback continue_callback) override { + CHECK(restart_callback); + CHECK(continue_callback); + std::move(continue_callback).Run(); + } + + private: + const raw_ref key_service_; + raw_ptr context_; + base::WeakPtrFactory weak_factory_{this}; +}; +} // namespace + +std::unique_ptr SessionService::Create( + const URLRequestContext* request_context) { + unexportable_keys::UnexportableKeyService* service = + UnexportableKeyServiceFactory::GetInstance()->GetShared(); + if (!service) { + return nullptr; + } + + return std::make_unique(*service, request_context); +} + +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/session_service.h b/naiveproxy/src/net/device_bound_sessions/session_service.h new file mode 100644 index 0000000000..05f97cbb6a --- /dev/null +++ b/naiveproxy/src/net/device_bound_sessions/session_service.h @@ -0,0 +1,75 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_DEVICE_BOUND_SESSIONS_SESSION_SERVICE_H_ +#define NET_DEVICE_BOUND_SESSIONS_SESSION_SERVICE_H_ + +#include + +#include "net/base/net_export.h" +#include "net/device_bound_sessions/registration_fetcher_param.h" + +namespace net { +class IsolationInfo; +class URLRequest; +class URLRequestContext; +} + +namespace net::device_bound_sessions { + +// Main class for Device Bound Session Credentials (DBSC). +// Full information can be found at https://github.com/WICG/dbsc +class NET_EXPORT SessionService { + public: + using RefreshCompleteCallback = base::OnceClosure; + + // Returns nullptr if unexportable key provider is not supported by the + // platform or the device. + static std::unique_ptr Create( + const URLRequestContext* request_context); + + SessionService(const SessionService&) = delete; + SessionService& operator=(const SessionService&) = delete; + + virtual ~SessionService() = default; + + // Called to register a new session after getting a Sec-Session-Registration + // header. + // Registration parameters to be used for creating the registration + // request. + // Isolation info to be used for registration request, this should be the + // same as was used for the response with the Sec-Session-Registration + // header. + virtual void RegisterBoundSession( + RegistrationFetcherParam registration_params, + const IsolationInfo& isolation_info) = 0; + + // Check if a request should be deferred due to the session cookie being + // missing. This should only be called once the request has the correct + // cookies added to the request. + // If multiple sessions needs to be refreshed for this request, + // any of them can be returned. + // Returns the session id if the request should be deferred, returns + // std::nullopt if the request does not need to be deferred. + virtual std::optional GetAnySessionRequiringDeferral( + URLRequest* request) = 0; + + // Defer a request while refreshing the session. + // session_id is the identifier of the session that is required to be + // refreshed. + // Provides two callbacks, will always call one of them: + // - The first will query for cookies for the requests again. + // - The second to send the request without query for cookies again. + virtual void DeferRequestForRefresh( + std::string session_id, + RefreshCompleteCallback restart_callback, + RefreshCompleteCallback continue_callback) = 0; + + protected: + SessionService() = default; +}; + +} // namespace net::device_bound_sessions + +#endif // NET_DEVICE_BOUND_SESSIONS_SESSION_SERVICE_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/test_util.cc b/naiveproxy/src/net/device_bound_sessions/test_util.cc index b6a9c1ed05..1cc08a2784 100644 --- a/naiveproxy/src/net/device_bound_sessions/test_util.cc +++ b/naiveproxy/src/net/device_bound_sessions/test_util.cc @@ -4,9 +4,9 @@ #include "net/device_bound_sessions/test_util.h" -namespace net { +namespace net::device_bound_sessions { -DeviceBoundSessionServiceMock::DeviceBoundSessionServiceMock() = default; -DeviceBoundSessionServiceMock::~DeviceBoundSessionServiceMock() = default; +SessionServiceMock::SessionServiceMock() = default; +SessionServiceMock::~SessionServiceMock() = default; -} // namespace net +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/test_util.h b/naiveproxy/src/net/device_bound_sessions/test_util.h index f60a24c422..4a50948222 100644 --- a/naiveproxy/src/net/device_bound_sessions/test_util.h +++ b/naiveproxy/src/net/device_bound_sessions/test_util.h @@ -5,24 +5,34 @@ #ifndef NET_DEVICE_BOUND_SESSIONS_TEST_UTIL_H_ #define NET_DEVICE_BOUND_SESSIONS_TEST_UTIL_H_ -#include "net/device_bound_sessions/device_bound_session_registration_fetcher_param.h" -#include "net/device_bound_sessions/device_bound_session_service.h" +#include "net/device_bound_sessions/registration_fetcher_param.h" +#include "net/device_bound_sessions/session_service.h" #include "testing/gmock/include/gmock/gmock.h" -namespace net { +namespace net::device_bound_sessions { -class DeviceBoundSessionServiceMock : public DeviceBoundSessionService { +class SessionServiceMock : public SessionService { public: - DeviceBoundSessionServiceMock(); - ~DeviceBoundSessionServiceMock() override; + SessionServiceMock(); + ~SessionServiceMock() override; MOCK_METHOD(void, RegisterBoundSession, - (DeviceBoundSessionRegistrationFetcherParam registration_params, + (RegistrationFetcherParam registration_params, const IsolationInfo& isolation_info), (override)); + MOCK_METHOD(std::optional, + GetAnySessionRequiringDeferral, + (URLRequest * request), + (override)); + MOCK_METHOD(void, + DeferRequestForRefresh, + (std::string session_id, + RefreshCompleteCallback restart_callback, + RefreshCompleteCallback continue_callback), + (override)); }; -} // namespace net +} // namespace net::device_bound_sessions #endif // NET_DEVICE_BOUND_SESSIONS_TEST_UTIL_H_ diff --git a/naiveproxy/src/net/device_bound_sessions/unexportable_key_service_factory.cc b/naiveproxy/src/net/device_bound_sessions/unexportable_key_service_factory.cc index 44c14e4cd7..9ee0b61a36 100644 --- a/naiveproxy/src/net/device_bound_sessions/unexportable_key_service_factory.cc +++ b/naiveproxy/src/net/device_bound_sessions/unexportable_key_service_factory.cc @@ -53,7 +53,7 @@ unexportable_keys::UnexportableKeyTaskManager* GetSharedTaskManagerInstance() { } // namespace -namespace net { +namespace net::device_bound_sessions { // Currently there is another UnexportableKeyServiceFactory in the // chrome/browser/signin code in the browser process. They do not share code, @@ -84,4 +84,4 @@ UnexportableKeyServiceFactory::GetShared() { UnexportableKeyServiceFactory::UnexportableKeyServiceFactory() = default; UnexportableKeyServiceFactory::~UnexportableKeyServiceFactory() = default; -} // namespace net +} // namespace net::device_bound_sessions diff --git a/naiveproxy/src/net/device_bound_sessions/unexportable_key_service_factory.h b/naiveproxy/src/net/device_bound_sessions/unexportable_key_service_factory.h index b2de3886a0..08731645fe 100644 --- a/naiveproxy/src/net/device_bound_sessions/unexportable_key_service_factory.h +++ b/naiveproxy/src/net/device_bound_sessions/unexportable_key_service_factory.h @@ -13,7 +13,7 @@ namespace unexportable_keys { class UnexportableKeyService; } -namespace net { +namespace net::device_bound_sessions { class UnexportableKeyServiceFactory { public: @@ -39,6 +39,6 @@ class UnexportableKeyServiceFactory { ~UnexportableKeyServiceFactory(); }; -} // namespace net +} // namespace net::device_bound_sessions #endif // NET_DEVICE_BOUND_SESSIONS_UNEXPORTABLE_KEY_SERVICE_FACTORY_H_ diff --git a/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc b/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc index 2640b62e21..9ebac916f9 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc @@ -191,13 +191,15 @@ class SimpleBackendImpl::ActiveEntryProxy static std::unique_ptr Create( int64_t entry_hash, - SimpleBackendImpl* backend) { - return base::WrapUnique(new ActiveEntryProxy(entry_hash, backend)); + base::WeakPtr backend) { + return base::WrapUnique( + new ActiveEntryProxy(entry_hash, std::move(backend))); } private: - ActiveEntryProxy(uint64_t entry_hash, SimpleBackendImpl* backend) - : entry_hash_(entry_hash), backend_(backend->AsWeakPtr()) {} + ActiveEntryProxy(uint64_t entry_hash, + base::WeakPtr backend) + : entry_hash_(entry_hash), backend_(std::move(backend)) {} uint64_t entry_hash_; base::WeakPtr backend_; @@ -271,7 +273,8 @@ void SimpleBackendImpl::Init(CompletionOnceCallback completion_callback) { base::BindOnce(&SimpleBackendImpl::InitCacheStructureOnDisk, std::move(file_operations), path_, orig_max_size_, GetCacheType()), - base::BindOnce(&SimpleBackendImpl::InitializeIndex, AsWeakPtr(), + base::BindOnce(&SimpleBackendImpl::InitializeIndex, + weak_ptr_factory_.GetWeakPtr(), std::move(completion_callback))); } @@ -359,7 +362,8 @@ void SimpleBackendImpl::DoomEntries(std::vector* entry_hashes, base::BindOnce(&SimpleSynchronousEntry::DeleteEntrySetFiles, mass_doom_entry_hashes_ptr, path_, file_operations_factory_->CreateUnbound()), - base::BindOnce(&SimpleBackendImpl::DoomEntriesComplete, AsWeakPtr(), + base::BindOnce(&SimpleBackendImpl::DoomEntriesComplete, + weak_ptr_factory_.GetWeakPtr(), std::move(mass_doom_entry_hashes), barrier_callback)); } @@ -395,9 +399,9 @@ EntryResult SimpleBackendImpl::OpenEntry(const std::string& key, base::OnceCallback operation = base::BindOnce(&SimpleBackendImpl::OpenEntry, base::Unretained(this), key, request_priority); - post_operation->emplace_back( - base::BindOnce(&RunEntryResultOperationAndCallback, AsWeakPtr(), - std::move(operation), std::move(callback))); + post_operation->emplace_back(base::BindOnce( + &RunEntryResultOperationAndCallback, weak_ptr_factory_.GetWeakPtr(), + std::move(operation), std::move(callback))); return EntryResult::MakeError(net::ERR_IO_PENDING); } return simple_entry->OpenEntry(std::move(callback)); @@ -427,9 +431,9 @@ EntryResult SimpleBackendImpl::CreateEntry( base::OnceCallback operation = base::BindOnce(&SimpleBackendImpl::CreateEntry, base::Unretained(this), key, request_priority); - post_operation->emplace_back( - base::BindOnce(&RunEntryResultOperationAndCallback, AsWeakPtr(), - std::move(operation), std::move(callback))); + post_operation->emplace_back(base::BindOnce( + &RunEntryResultOperationAndCallback, weak_ptr_factory_.GetWeakPtr(), + std::move(operation), std::move(callback))); return EntryResult::MakeError(net::ERR_IO_PENDING); } @@ -463,9 +467,9 @@ EntryResult SimpleBackendImpl::OpenOrCreateEntry( base::OnceCallback operation = base::BindOnce(&SimpleBackendImpl::OpenOrCreateEntry, base::Unretained(this), key, request_priority); - post_operation->emplace_back( - base::BindOnce(&RunEntryResultOperationAndCallback, AsWeakPtr(), - std::move(operation), std::move(callback))); + post_operation->emplace_back(base::BindOnce( + &RunEntryResultOperationAndCallback, weak_ptr_factory_.GetWeakPtr(), + std::move(operation), std::move(callback))); return EntryResult::MakeError(net::ERR_IO_PENDING); } } @@ -491,7 +495,7 @@ SimpleBackendImpl::MaybeOptimisticCreateForPostDoom( net_log_, GetNewEntryPriority(request_priority)); simple_entry->SetKey(key); simple_entry->SetActiveEntryProxy( - ActiveEntryProxy::Create(entry_hash, this)); + ActiveEntryProxy::Create(entry_hash, weak_ptr_factory_.GetWeakPtr())); simple_entry->SetCreatePendingDoom(); std::pair insert_result = active_entries_.insert( EntryMap::value_type(entry_hash, simple_entry.get())); @@ -522,7 +526,7 @@ net::Error SimpleBackendImpl::DoomEntry(const std::string& key, base::BindOnce(&SimpleBackendImpl::DoomEntry, base::Unretained(this), key, priority); post_operation->emplace_back( - base::BindOnce(&RunOperationAndCallback, AsWeakPtr(), + base::BindOnce(&RunOperationAndCallback, weak_ptr_factory_.GetWeakPtr(), std::move(operation), std::move(callback))); return net::ERR_IO_PENDING; } @@ -538,9 +542,9 @@ net::Error SimpleBackendImpl::DoomEntriesBetween( const Time initial_time, const Time end_time, CompletionOnceCallback callback) { - index_->ExecuteWhenReady(base::BindOnce(&SimpleBackendImpl::IndexReadyForDoom, - AsWeakPtr(), initial_time, end_time, - std::move(callback))); + index_->ExecuteWhenReady(base::BindOnce( + &SimpleBackendImpl::IndexReadyForDoom, weak_ptr_factory_.GetWeakPtr(), + initial_time, end_time, std::move(callback))); return net::ERR_IO_PENDING; } @@ -554,7 +558,7 @@ int64_t SimpleBackendImpl::CalculateSizeOfAllEntries( Int64CompletionOnceCallback callback) { index_->ExecuteWhenReady( base::BindOnce(&SimpleBackendImpl::IndexReadyForSizeCalculation, - AsWeakPtr(), std::move(callback))); + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); return net::ERR_IO_PENDING; } @@ -564,7 +568,8 @@ int64_t SimpleBackendImpl::CalculateSizeOfEntriesBetween( Int64CompletionOnceCallback callback) { index_->ExecuteWhenReady( base::BindOnce(&SimpleBackendImpl::IndexReadyForSizeBetweenCalculation, - AsWeakPtr(), initial_time, end_time, std::move(callback))); + weak_ptr_factory_.GetWeakPtr(), initial_time, end_time, + std::move(callback))); return net::ERR_IO_PENDING; } @@ -636,7 +641,7 @@ class SimpleBackendImpl::SimpleIterator final : public Iterator { }; std::unique_ptr SimpleBackendImpl::CreateIterator() { - return std::make_unique(AsWeakPtr()); + return std::make_unique(weak_ptr_factory_.GetWeakPtr()); } void SimpleBackendImpl::GetStats(base::StringPairs* stats) { @@ -803,7 +808,8 @@ SimpleBackendImpl::CreateOrFindActiveOrDoomedEntry( entry_operations_mode_, this, file_tracker_, file_operations_factory_, net_log_, GetNewEntryPriority(request_priority)); entry->SetKey(key); - entry->SetActiveEntryProxy(ActiveEntryProxy::Create(entry_hash, this)); + entry->SetActiveEntryProxy( + ActiveEntryProxy::Create(entry_hash, weak_ptr_factory_.GetWeakPtr())); } // TODO(jkarlin): In case of recycling a half-closed entry, we might want to // update its priority. @@ -842,9 +848,9 @@ EntryResult SimpleBackendImpl::OpenEntryFromHash(uint64_t entry_hash, base::BindOnce(&SimpleBackendImpl::OpenEntryFromHash, base::Unretained(this), entry_hash); // TODO(crbug.com/40105434) The cancellation behavior looks wrong. - post_doom->emplace_back(base::BindOnce(&RunEntryResultOperationAndCallback, - AsWeakPtr(), std::move(operation), - std::move(callback))); + post_doom->emplace_back(base::BindOnce( + &RunEntryResultOperationAndCallback, weak_ptr_factory_.GetWeakPtr(), + std::move(operation), std::move(callback))); return EntryResult::MakeError(net::ERR_IO_PENDING); } @@ -862,10 +868,11 @@ EntryResult SimpleBackendImpl::OpenEntryFromHash(uint64_t entry_hash, net_log_, GetNewEntryPriority(net::HIGHEST)); it->second = simple_entry.get(); simple_entry->SetActiveEntryProxy( - ActiveEntryProxy::Create(entry_hash, this)); + ActiveEntryProxy::Create(entry_hash, weak_ptr_factory_.GetWeakPtr())); post_open_by_hash_waiting_->OnOperationStart(entry_hash); callback = base::BindOnce(&SimpleBackendImpl::OnEntryOpenedFromHash, - AsWeakPtr(), entry_hash, std::move(callback)); + weak_ptr_factory_.GetWeakPtr(), entry_hash, + std::move(callback)); } // Note: the !did_insert case includes when another OpenEntryFromHash is @@ -883,9 +890,9 @@ net::Error SimpleBackendImpl::DoomEntryFromHash( base::OnceCallback operation = base::BindOnce(&SimpleBackendImpl::DoomEntryFromHash, base::Unretained(this), entry_hash); - post_doom->emplace_back(base::BindOnce(&RunOperationAndCallback, - AsWeakPtr(), std::move(operation), - std::move(callback))); + post_doom->emplace_back( + base::BindOnce(&RunOperationAndCallback, weak_ptr_factory_.GetWeakPtr(), + std::move(operation), std::move(callback))); return net::ERR_IO_PENDING; } diff --git a/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.h b/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.h index 7032253abf..a93dced5bd 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.h @@ -56,9 +56,8 @@ class SimpleEntryImpl; class SimpleFileTracker; class SimpleIndex; -class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend, - public SimpleIndexDelegate, - public base::SupportsWeakPtr { +class NET_EXPORT_PRIVATE SimpleBackendImpl final : public Backend, + public SimpleIndexDelegate { public: // Note: only pass non-nullptr for |file_tracker| if you don't want the global // one (which things other than tests would want). |file_tracker| must outlive @@ -151,6 +150,10 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend, } #endif + base::WeakPtr AsWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + private: class SimpleIterator; friend class SimpleIterator; @@ -293,6 +296,8 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend, #if BUILDFLAG(IS_ANDROID) ApplicationStatusListenerGetter app_status_listener_getter_; #endif + + base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/simple/simple_file_tracker.cc b/naiveproxy/src/net/disk_cache/simple/simple_file_tracker.cc index a600d5b4bb..52aee3af05 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_file_tracker.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_file_tracker.cc @@ -17,6 +17,7 @@ #include "base/files/file.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/not_fatal_until.h" #include "base/synchronization/lock.h" #include "net/disk_cache/disk_cache.h" #include "net/disk_cache/simple/simple_histogram_enums.h" @@ -189,7 +190,7 @@ void SimpleFileTracker::Doom(const SimpleSynchronousEntry* owner, EntryFileKey* key) { base::AutoLock hold_lock(lock_); auto iter = tracked_files_.find(key->entry_hash); - DCHECK(iter != tracked_files_.end()); + CHECK(iter != tracked_files_.end(), base::NotFatalUntil::M130); uint64_t max_doom_gen = 0; for (const std::unique_ptr& file_with_same_hash : @@ -223,7 +224,7 @@ bool SimpleFileTracker::IsEmptyForTesting() { SimpleFileTracker::TrackedFiles* SimpleFileTracker::Find( const SimpleSynchronousEntry* owner) { auto candidates = tracked_files_.find(owner->entry_file_key().entry_hash); - DCHECK(candidates != tracked_files_.end()); + CHECK(candidates != tracked_files_.end(), base::NotFatalUntil::M130); for (const auto& candidate : candidates->second) { if (candidate->owner == owner) { return candidate.get(); diff --git a/naiveproxy/src/net/disk_cache/simple/simple_index.cc b/naiveproxy/src/net/disk_cache/simple/simple_index.cc index 1adb727a1f..2deba5b98c 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_index.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_index.cc @@ -12,6 +12,7 @@ #include "base/check_op.h" #include "base/files/file_util.h" #include "base/functional/bind.h" +#include "base/not_fatal_until.h" #include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/strings/string_number_conversions.h" @@ -183,12 +184,13 @@ SimpleIndex::SimpleIndex( delegate_(delegate), cache_type_(cache_type), index_file_(std::move(index_file)), - task_runner_(task_runner), - // Creating the callback once so it is reused every time - // write_to_disk_timer_.Start() is called. - write_to_disk_cb_(base::BindRepeating(&SimpleIndex::WriteToDisk, - AsWeakPtr(), - INDEX_WRITE_REASON_IDLE)) {} + task_runner_(task_runner) { + // Creating the callback once so it is reused every time + // write_to_disk_timer_.Start() is called. + write_to_disk_cb_ = base::BindRepeating(&SimpleIndex::WriteToDisk, + weak_ptr_factory_.GetWeakPtr(), + INDEX_WRITE_REASON_IDLE); +} SimpleIndex::~SimpleIndex() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -207,17 +209,18 @@ void SimpleIndex::Initialize(base::Time cache_mtime) { base::android::ApplicationStatusListener* listener = app_status_listener_getter_.Run(); if (listener) { - listener->SetCallback(base::BindRepeating( - &SimpleIndex::OnApplicationStateChange, AsWeakPtr())); + listener->SetCallback( + base::BindRepeating(&SimpleIndex::OnApplicationStateChange, + weak_ptr_factory_.GetWeakPtr())); } // Not using the fallback on purpose here --- if the getter is set, we may // be in a process where the base::android::ApplicationStatusListener::New // impl is unavailable. // (See https://crbug.com/881572) } else if (base::android::IsVMInitialized()) { - owned_app_status_listener_ = - base::android::ApplicationStatusListener::New(base::BindRepeating( - &SimpleIndex::OnApplicationStateChange, AsWeakPtr())); + owned_app_status_listener_ = base::android::ApplicationStatusListener::New( + base::BindRepeating(&SimpleIndex::OnApplicationStateChange, + weak_ptr_factory_.GetWeakPtr())); } #endif @@ -225,8 +228,8 @@ void SimpleIndex::Initialize(base::Time cache_mtime) { auto* load_result_ptr = load_result.get(); index_file_->LoadIndexEntries( cache_mtime, - base::BindOnce(&SimpleIndex::MergeInitializingSet, AsWeakPtr(), - std::move(load_result)), + base::BindOnce(&SimpleIndex::MergeInitializingSet, + weak_ptr_factory_.GetWeakPtr(), std::move(load_result)), load_result_ptr); } @@ -323,7 +326,7 @@ base::Time SimpleIndex::GetLastUsedTime(uint64_t entry_hash) { void SimpleIndex::SetLastUsedTimeForTest(uint64_t entry_hash, const base::Time last_used) { auto it = entries_set_.find(entry_hash); - DCHECK(it != entries_set_.end()); + CHECK(it != entries_set_.end(), base::NotFatalUntil::M130); it->second.SetLastUsedTime(last_used); } @@ -452,8 +455,9 @@ void SimpleIndex::StartEvictionIfNeeded() { "Eviction.TimeToSelectEntries", cache_type_, base::TimeTicks::Now() - eviction_start_time_); - delegate_->DoomEntries( - &entry_hashes, base::BindOnce(&SimpleIndex::EvictionDone, AsWeakPtr())); + delegate_->DoomEntries(&entry_hashes, + base::BindOnce(&SimpleIndex::EvictionDone, + weak_ptr_factory_.GetWeakPtr())); } int32_t SimpleIndex::GetTrailerPrefetchSize(uint64_t entry_hash) const { diff --git a/naiveproxy/src/net/disk_cache/simple/simple_index.h b/naiveproxy/src/net/disk_cache/simple/simple_index.h index 3664557569..3e05d78192 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_index.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_index.h @@ -111,8 +111,7 @@ class NET_EXPORT_PRIVATE EntryMetadata { static_assert(sizeof(EntryMetadata) == 8, "incorrect metadata size"); // This class is not Thread-safe. -class NET_EXPORT_PRIVATE SimpleIndex - : public base::SupportsWeakPtr { +class NET_EXPORT_PRIVATE SimpleIndex final { public: // Used in histograms. Please only add entries at the end. enum IndexInitMethod { @@ -304,6 +303,8 @@ class NET_EXPORT_PRIVATE SimpleIndex // background we can write the index much more frequently, to insure fresh // index on next startup. bool app_on_background_ = false; + + base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace disk_cache diff --git a/naiveproxy/src/net/dns/dns_response.cc b/naiveproxy/src/net/dns/dns_response.cc index de2221cd05..7a4f3b5cf9 100644 --- a/naiveproxy/src/net/dns/dns_response.cc +++ b/naiveproxy/src/net/dns/dns_response.cc @@ -125,6 +125,16 @@ size_t DnsResourceRecord::CalculateRecordSize() const { DnsRecordParser::DnsRecordParser() = default; +DnsRecordParser::~DnsRecordParser() = default; + +DnsRecordParser::DnsRecordParser(const DnsRecordParser&) = default; + +DnsRecordParser::DnsRecordParser(DnsRecordParser&&) = default; + +DnsRecordParser& DnsRecordParser::operator=(const DnsRecordParser&) = default; + +DnsRecordParser& DnsRecordParser::operator=(DnsRecordParser&&) = default; + DnsRecordParser::DnsRecordParser(base::span packet, size_t offset, size_t num_records) diff --git a/naiveproxy/src/net/dns/dns_response.h b/naiveproxy/src/net/dns/dns_response.h index 501546ce84..b6ce4de387 100644 --- a/naiveproxy/src/net/dns/dns_response.h +++ b/naiveproxy/src/net/dns/dns_response.h @@ -16,6 +16,7 @@ #include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/containers/span_writer.h" +#include "base/memory/raw_span.h" #include "base/memory/scoped_refptr.h" #include "net/base/net_export.h" #include "net/dns/dns_response_result_extractor.h" @@ -83,6 +84,13 @@ class NET_EXPORT_PRIVATE DnsRecordParser { size_t offset, size_t num_records); + DnsRecordParser(const DnsRecordParser&); + DnsRecordParser(DnsRecordParser&&); + DnsRecordParser& operator=(const DnsRecordParser&); + DnsRecordParser& operator=(DnsRecordParser&&); + + ~DnsRecordParser(); + // Returns |true| if initialized. bool IsValid() const { return !packet_.empty(); } @@ -110,7 +118,7 @@ class NET_EXPORT_PRIVATE DnsRecordParser { bool ReadQuestion(std::string& out_dotted_qname, uint16_t& out_qtype); private: - base::span packet_; + base::raw_span packet_; size_t num_records_ = 0u; size_t num_records_parsed_ = 0u; // Current offset within the packet. diff --git a/naiveproxy/src/net/dns/host_resolver_dns_task.cc b/naiveproxy/src/net/dns/host_resolver_dns_task.cc index 77b56a0444..b35132f8d0 100644 --- a/naiveproxy/src/net/dns/host_resolver_dns_task.cc +++ b/naiveproxy/src/net/dns/host_resolver_dns_task.cc @@ -8,6 +8,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/not_fatal_until.h" #include "base/ranges/algorithm.h" #include "base/time/tick_clock.h" #include "net/base/features.h" @@ -381,7 +382,8 @@ void HostResolverDnsTask::OnDnsTransactionComplete( uint16_t request_port, int net_error, const DnsResponse* response) { - DCHECK(transaction_info_it != transactions_in_progress_.end()); + CHECK(transaction_info_it != transactions_in_progress_.end(), + base::NotFatalUntil::M130); DCHECK(base::Contains(transactions_in_progress_, *transaction_info_it)); // Pull the TransactionInfo out of `transactions_in_progress_` now, so it @@ -631,8 +633,9 @@ void HostResolverDnsTask::SortTransactionAndHandleResults( // Sort() potentially calls OnTransactionSorted() synchronously. client_->GetAddressSorter()->Sort( endpoints_to_sort, - base::BindOnce(&HostResolverDnsTask::OnTransactionSorted, AsWeakPtr(), - insertion_result.first, std::move(transaction_results))); + base::BindOnce(&HostResolverDnsTask::OnTransactionSorted, + weak_ptr_factory_.GetWeakPtr(), insertion_result.first, + std::move(transaction_results))); } else { HandleTransactionResults(std::move(transaction_info), std::move(transaction_results)); @@ -831,7 +834,8 @@ void HostResolverDnsTask::OnTransactionsFinished( // Sort addresses if needed. Sort could complete synchronously. client_->GetAddressSorter()->Sort( ip_endpoints, - base::BindOnce(&HostResolverDnsTask::OnSortComplete, AsWeakPtr(), + base::BindOnce(&HostResolverDnsTask::OnSortComplete, + weak_ptr_factory_.GetWeakPtr(), tick_clock_->NowTicks(), std::move(results), secure_)); return; } diff --git a/naiveproxy/src/net/dns/host_resolver_dns_task.h b/naiveproxy/src/net/dns/host_resolver_dns_task.h index 48c1a2f814..388546abfa 100644 --- a/naiveproxy/src/net/dns/host_resolver_dns_task.h +++ b/naiveproxy/src/net/dns/host_resolver_dns_task.h @@ -40,8 +40,7 @@ class DnsResponse; // a DNS stub resolver. One DnsTransaction is created for each resolution // needed, which for AF_UNSPEC resolutions includes both A and AAAA. The // transactions are scheduled separately and started separately. -class NET_EXPORT_PRIVATE HostResolverDnsTask - : public base::SupportsWeakPtr { +class NET_EXPORT_PRIVATE HostResolverDnsTask final { public: using Results = std::set>; @@ -114,6 +113,10 @@ class NET_EXPORT_PRIVATE HostResolverDnsTask void StartNextTransaction(); + base::WeakPtr AsWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + private: enum class TransactionErrorBehavior { // Errors lead to task fallback (immediately unless another pending/started @@ -258,6 +261,8 @@ class NET_EXPORT_PRIVATE HostResolverDnsTask bool fallback_available_; const HostResolver::HttpsSvcbOptions https_svcb_options_; + + base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace net diff --git a/naiveproxy/src/net/dns/host_resolver_manager.cc b/naiveproxy/src/net/dns/host_resolver_manager.cc index cb4d5fe59e..904b2daf93 100644 --- a/naiveproxy/src/net/dns/host_resolver_manager.cc +++ b/naiveproxy/src/net/dns/host_resolver_manager.cc @@ -41,6 +41,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" +#include "base/not_fatal_until.h" #include "base/numerics/safe_conversions.h" #include "base/observer_list.h" #include "base/ranges/algorithm.h" @@ -1161,7 +1162,7 @@ void HostResolverManager::CacheResult(HostCache* cache, std::unique_ptr HostResolverManager::RemoveJob( JobMap::iterator job_it) { - DCHECK(job_it != jobs_.end()); + CHECK(job_it != jobs_.end(), base::NotFatalUntil::M130); DCHECK(job_it->second); DCHECK_EQ(1u, jobs_.count(job_it->first)); diff --git a/naiveproxy/src/net/dns/host_resolver_manager_job.cc b/naiveproxy/src/net/dns/host_resolver_manager_job.cc index 75087f4bf8..a885312180 100644 --- a/naiveproxy/src/net/dns/host_resolver_manager_job.cc +++ b/naiveproxy/src/net/dns/host_resolver_manager_job.cc @@ -15,6 +15,7 @@ #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/not_fatal_until.h" #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "net/base/address_family.h" @@ -33,6 +34,7 @@ #include "net/dns/host_resolver_manager_service_endpoint_request_impl.h" #include "net/dns/host_resolver_mdns_task.h" #include "net/dns/host_resolver_nat64_task.h" +#include "net/dns/host_resolver_system_task.h" #include "net/dns/public/dns_query_type.h" #include "net/dns/public/secure_dns_mode.h" #include "net/log/net_log_with_source.h" @@ -379,7 +381,7 @@ bool HostResolverManager::Job::ServeFromHosts() { void HostResolverManager::Job::OnAddedToJobMap(JobMap::iterator iterator) { DCHECK(!self_iterator_); - DCHECK(iterator != resolver_->jobs_.end()); + CHECK(iterator != resolver_->jobs_.end(), base::NotFatalUntil::M130); self_iterator_ = iterator; } @@ -609,11 +611,17 @@ void HostResolverManager::Job::StartSystemTask() { DCHECK_EQ(1, num_occupied_job_slots_); DCHECK(HasAddressType(key_.query_types)); + std::optional cache_params; + if (key_.resolve_context->host_resolver_cache()) { + cache_params.emplace(*key_.resolve_context->host_resolver_cache(), + key_.network_anonymization_key); + } + system_task_ = HostResolverSystemTask::Create( std::string(key_.host.GetHostnameWithoutBrackets()), HostResolver::DnsQueryTypeSetToAddressFamily(key_.query_types), key_.flags, resolver_->host_resolver_system_params_, net_log_, - key_.GetTargetNetwork()); + key_.GetTargetNetwork(), std::move(cache_params)); // Start() could be called from within Resolve(), hence it must NOT directly // call OnSystemTaskComplete, for example, on synchronous failure. diff --git a/naiveproxy/src/net/dns/host_resolver_system_task.cc b/naiveproxy/src/net/dns/host_resolver_system_task.cc index 70955b19cb..9ebae04715 100644 --- a/naiveproxy/src/net/dns/host_resolver_system_task.cc +++ b/naiveproxy/src/net/dns/host_resolver_system_task.cc @@ -6,27 +6,42 @@ #include #include +#include +#include +#include "base/check.h" #include "base/dcheck_is_on.h" +#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/functional/callback.h" +#include "base/memory/raw_ref.h" #include "base/metrics/field_trial_params.h" #include "base/no_destructor.h" +#include "base/notreached.h" #include "base/sequence_checker.h" #include "base/sequence_checker_impl.h" #include "base/task/sequenced_task_runner.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" +#include "base/time/time.h" #include "base/types/pass_key.h" #include "dns_reloader.h" +#include "net/base/address_family.h" +#include "net/base/address_list.h" +#include "net/base/features.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" +#include "net/base/network_anonymization_key.h" #include "net/base/network_interfaces.h" #include "net/base/sys_addrinfo.h" #include "net/base/trace_constants.h" #include "net/base/tracing.h" #include "net/dns/address_info.h" #include "net/dns/dns_names_util.h" +#include "net/dns/host_resolver_cache.h" +#include "net/dns/host_resolver_internal_result.h" +#include "net/dns/public/host_resolver_source.h" #if BUILDFLAG(IS_WIN) #include "base/strings/utf_string_conversions.h" @@ -37,6 +52,13 @@ namespace net { namespace { +// System resolver results give no TTL, so a default caching time is needed. +// Pick 1 minute to match the minimum cache time for built-in resolver results +// because this is only serving as a secondary cache to the caching done by the +// system. Additionally, this matches the long-standing historical behavior from +// previous implementations of HostResolver caching. +constexpr base::TimeDelta kTtl = base::Minutes(1); + // Returns nullptr in the common case, or a task runner if the default has // been overridden. scoped_refptr& GetSystemDnsResolutionTaskRunnerOverride() { @@ -185,6 +207,18 @@ HostResolverSystemTask::Params::Params(const Params& other) = default; HostResolverSystemTask::Params::~Params() = default; +HostResolverSystemTask::CacheParams::CacheParams( + HostResolverCache& cache, + NetworkAnonymizationKey network_anonymization_key) + : cache(base::raw_ref(cache)), + network_anonymization_key(std::move(network_anonymization_key)) {} + +HostResolverSystemTask::CacheParams::CacheParams(const CacheParams&) = default; + +HostResolverSystemTask::CacheParams::CacheParams(CacheParams&&) = default; + +HostResolverSystemTask::CacheParams::~CacheParams() = default; + // static std::unique_ptr HostResolverSystemTask::Create( std::string hostname, @@ -192,9 +226,11 @@ std::unique_ptr HostResolverSystemTask::Create( HostResolverFlags flags, const Params& params, const NetLogWithSource& job_net_log, - handles::NetworkHandle network) { + handles::NetworkHandle network, + std::optional cache_params) { return std::make_unique( - hostname, address_family, flags, params, job_net_log, network); + hostname, address_family, flags, params, job_net_log, network, + std::move(cache_params)); } // static @@ -206,7 +242,8 @@ HostResolverSystemTask::CreateForOwnHostname( const NetLogWithSource& job_net_log, handles::NetworkHandle network) { return std::make_unique( - std::nullopt, address_family, flags, params, job_net_log, network); + std::nullopt, address_family, flags, params, job_net_log, network, + /*cache_params=*/std::nullopt); } HostResolverSystemTask::HostResolverSystemTask( @@ -215,16 +252,21 @@ HostResolverSystemTask::HostResolverSystemTask( HostResolverFlags flags, const Params& params, const NetLogWithSource& job_net_log, - handles::NetworkHandle network) + handles::NetworkHandle network, + std::optional cache_params) : hostname_(std::move(hostname)), address_family_(address_family), flags_(flags), params_(params), net_log_(job_net_log), - network_(network) { + network_(network), + cache_params_(std::move(cache_params)) { + // Must have hostname if results are to be cached. + CHECK(!cache_params_.has_value() || hostname_.has_value()); + if (hostname_) { - // |host| should be a valid domain name. HostResolverManager has checks to - // fail early if this is not the case. + // `hostname` should be a valid domain name. HostResolverManager has checks + // to fail early if this is not the case. DCHECK(dns_names_util::IsValidDnsName(*hostname_)) << "Invalid hostname: " << *hostname_; } @@ -338,10 +380,92 @@ void HostResolverSystemTask::OnLookupComplete(const uint32_t attempt_number, "attempt_number", attempt_number); } + MaybeCacheResults(results); + std::move(results_cb_).Run(results, os_error, error); // Running |results_cb_| can delete |this|. } +void HostResolverSystemTask::MaybeCacheResults( + const AddressList& address_list) { + if (address_list.empty() || !cache_params_.has_value() || + !base::FeatureList::IsEnabled(features::kUseHostResolverCache)) { + return; + } + CHECK(hostname_.has_value()); + + // Split out IPv4 and IPv6 endpoints while keeping them in the received order. + std::vector ipv4; + std::vector ipv6; + for (const IPEndPoint& endpoint : address_list) { + switch (endpoint.GetFamily()) { + case ADDRESS_FAMILY_IPV4: + ipv4.push_back(endpoint); + break; + case ADDRESS_FAMILY_IPV6: + ipv6.push_back(endpoint); + break; + default: + // Expect only IPv4 and IPv6 endpoints from system resolver. + NOTREACHED(); + } + } + CHECK(!ipv4.empty() || !ipv6.empty()); + + std::string_view domain_name = hostname_.value(); + if (!address_list.dns_aliases().empty()) { + // Expect at most one alias from system resolver. + CHECK_EQ(address_list.dns_aliases().size(), 1u); + + // Save one alias cache entry for each query type. + CacheAlias(std::string(domain_name), DnsQueryType::A, + address_list.dns_aliases().front()); + CacheAlias(std::string(domain_name), DnsQueryType::AAAA, + address_list.dns_aliases().front()); + + domain_name = address_list.dns_aliases().front(); + } + + CacheEndpoints(std::string(domain_name), std::move(ipv4), DnsQueryType::A); + CacheEndpoints(std::string(domain_name), std::move(ipv6), DnsQueryType::AAAA); +} + +void HostResolverSystemTask::CacheEndpoints(std::string domain_name, + std::vector endpoints, + DnsQueryType query_type) { + if (endpoints.empty()) { + cache_params_.value().cache->Set( + std::make_unique( + std::move(domain_name), query_type, base::TimeTicks::Now() + kTtl, + base::Time::Now() + kTtl, + HostResolverInternalResult::Source::kUnknown, + ERR_NAME_NOT_RESOLVED), + cache_params_.value().network_anonymization_key, + HostResolverSource::SYSTEM, /*secure=*/false); + } else { + cache_params_.value().cache->Set( + std::make_unique( + std::move(domain_name), query_type, base::TimeTicks::Now() + kTtl, + base::Time::Now() + kTtl, + HostResolverInternalResult::Source::kUnknown, std::move(endpoints), + std::vector{}, std::vector{}), + cache_params_.value().network_anonymization_key, + HostResolverSource::SYSTEM, /*secure=*/false); + } +} + +void HostResolverSystemTask::CacheAlias(std::string domain_name, + DnsQueryType query_type, + std::string target_name) { + cache_params_.value().cache->Set( + std::make_unique( + std::move(domain_name), query_type, base::TimeTicks::Now() + kTtl, + base::Time::Now() + kTtl, + HostResolverInternalResult::Source::kUnknown, std::move(target_name)), + cache_params_.value().network_anonymization_key, + HostResolverSource::SYSTEM, /*secure=*/false); +} + void EnsureSystemHostResolverCallReady() { EnsureDnsReloaderInit(); #if BUILDFLAG(IS_WIN) diff --git a/naiveproxy/src/net/dns/host_resolver_system_task.h b/naiveproxy/src/net/dns/host_resolver_system_task.h index ef1e9f5186..d0851558b8 100644 --- a/naiveproxy/src/net/dns/host_resolver_system_task.h +++ b/naiveproxy/src/net/dns/host_resolver_system_task.h @@ -7,18 +7,25 @@ #include #include +#include #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" +#include "base/memory/raw_ref.h" #include "base/task/task_runner.h" #include "net/base/address_list.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_export.h" +#include "net/base/network_anonymization_key.h" #include "net/base/network_handle.h" #include "net/dns/host_resolver_proc.h" +#include "net/dns/public/dns_query_type.h" #include "net/log/net_log_with_source.h" namespace net { +class HostResolverCache; + using SystemDnsResultsCallback = base::OnceCallback< void(const AddressList& addr_list, int os_error, int net_error)>; @@ -88,13 +95,27 @@ class NET_EXPORT HostResolverSystemTask { uint32_t retry_factor = 2; }; + struct CacheParams { + CacheParams(HostResolverCache& cache, + NetworkAnonymizationKey network_anonymization_key); + CacheParams(const CacheParams&); + CacheParams& operator=(const CacheParams&) = default; + CacheParams(CacheParams&&); + CacheParams& operator=(CacheParams&&) = default; + ~CacheParams(); + + base::raw_ref cache; + NetworkAnonymizationKey network_anonymization_key; + }; + static std::unique_ptr Create( std::string hostname, AddressFamily address_family, HostResolverFlags flags, const Params& params = Params(nullptr, 0), const NetLogWithSource& job_net_log = NetLogWithSource(), - handles::NetworkHandle network = handles::kInvalidNetworkHandle); + handles::NetworkHandle network = handles::kInvalidNetworkHandle, + std::optional cache_params = std::nullopt); // Same as above but resolves the result of GetHostName() (the machine's own // hostname). @@ -114,7 +135,8 @@ class NET_EXPORT HostResolverSystemTask { HostResolverFlags flags, const Params& params = Params(nullptr, 0), const NetLogWithSource& job_net_log = NetLogWithSource(), - handles::NetworkHandle network = handles::kInvalidNetworkHandle); + handles::NetworkHandle network = handles::kInvalidNetworkHandle, + std::optional cache_params = std::nullopt); HostResolverSystemTask(const HostResolverSystemTask&) = delete; HostResolverSystemTask& operator=(const HostResolverSystemTask&) = delete; @@ -143,6 +165,14 @@ class NET_EXPORT HostResolverSystemTask { const int os_error, int error); + void MaybeCacheResults(const AddressList& address_list); + void CacheEndpoints(std::string domain_name, + std::vector endpoints, + DnsQueryType query_type); + void CacheAlias(std::string domain_name, + DnsQueryType query_type, + std::string target_name); + // If `hostname_` is std::nullopt, this class should resolve the result of // net::GetHostName() (the machine's own hostname). const std::optional hostname_; @@ -168,6 +198,8 @@ class NET_EXPORT HostResolverSystemTask { // Network to perform DNS lookups for. const handles::NetworkHandle network_; + std::optional cache_params_; + SEQUENCE_CHECKER(sequence_checker_); // Used to loop back from the blocking lookup attempt tasks as well as from diff --git a/naiveproxy/src/net/dns/httpssvc_metrics.cc b/naiveproxy/src/net/dns/httpssvc_metrics.cc index 008d8b5fcf..9babb3d860 100644 --- a/naiveproxy/src/net/dns/httpssvc_metrics.cc +++ b/naiveproxy/src/net/dns/httpssvc_metrics.cc @@ -11,6 +11,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_base.h" #include "base/metrics/histogram_functions.h" +#include "base/not_fatal_until.h" #include "base/notreached.h" #include "base/numerics/clamped_math.h" #include "base/strings/string_split.h" @@ -122,7 +123,8 @@ void HttpssvcMetrics::RecordMetrics() { std::vector::iterator slowest_address_resolve = std::max_element(address_resolve_times_.begin(), address_resolve_times_.end()); - DCHECK(slowest_address_resolve != address_resolve_times_.end()); + CHECK(slowest_address_resolve != address_resolve_times_.end(), + base::NotFatalUntil::M130); // It's possible to get here with a zero resolve time in tests. Avoid // divide-by-zero below by returning early; this data point is invalid anyway. diff --git a/naiveproxy/src/net/dns/mdns_client_impl.cc b/naiveproxy/src/net/dns/mdns_client_impl.cc index 9d6d8b9006..fd04d04c9b 100644 --- a/naiveproxy/src/net/dns/mdns_client_impl.cc +++ b/naiveproxy/src/net/dns/mdns_client_impl.cc @@ -15,6 +15,7 @@ #include "base/functional/bind.h" #include "base/location.h" #include "base/metrics/histogram_functions.h" +#include "base/not_fatal_until.h" #include "base/observer_list.h" #include "base/ranges/algorithm.h" #include "base/strings/string_util.h" @@ -412,7 +413,7 @@ void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) { ListenerKey key(listener->GetName(), listener->GetType()); auto observer_list_iterator = listeners_.find(key); - DCHECK(observer_list_iterator != listeners_.end()); + CHECK(observer_list_iterator != listeners_.end(), base::NotFatalUntil::M130); DCHECK(observer_list_iterator->second->HasObserver(listener)); observer_list_iterator->second->RemoveObserver(listener); @@ -423,7 +424,7 @@ void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) { // happens while iterating over the observer list. base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(&MDnsClientImpl::Core::CleanupObserverList, - AsWeakPtr(), key)); + weak_ptr_factory_.GetWeakPtr(), key)); } } @@ -628,8 +629,8 @@ void MDnsListenerImpl::ScheduleNextRefresh() { return; } - next_refresh_.Reset( - base::BindRepeating(&MDnsListenerImpl::DoRefresh, AsWeakPtr())); + next_refresh_.Reset(base::BindRepeating(&MDnsListenerImpl::DoRefresh, + weak_ptr_factory_.GetWeakPtr())); // Schedule refreshes at both 85% and 95% of the original TTL. These will both // be canceled and rescheduled if the record's TTL is updated due to a @@ -680,7 +681,7 @@ bool MDnsTransactionImpl::Start() { DCHECK(!started_); started_ = true; - base::WeakPtr weak_this = AsWeakPtr(); + base::WeakPtr weak_this = weak_ptr_factory_.GetWeakPtr(); if (flags_ & MDnsTransaction::QUERY_CACHE) { ServeRecordsFromCache(); @@ -754,7 +755,7 @@ void MDnsTransactionImpl::SignalTransactionOver() { void MDnsTransactionImpl::ServeRecordsFromCache() { std::vector records; - base::WeakPtr weak_this = AsWeakPtr(); + base::WeakPtr weak_this = weak_ptr_factory_.GetWeakPtr(); if (client_->core()) { client_->core()->QueryCache(rrtype_, name_, &records); @@ -788,8 +789,8 @@ bool MDnsTransactionImpl::QueryAndListen() { if (!client_->core()->SendQuery(rrtype_, name_)) return false; - timeout_.Reset( - base::BindOnce(&MDnsTransactionImpl::SignalTransactionOver, AsWeakPtr())); + timeout_.Reset(base::BindOnce(&MDnsTransactionImpl::SignalTransactionOver, + weak_ptr_factory_.GetWeakPtr())); base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, timeout_.callback(), kTransactionTimeout); diff --git a/naiveproxy/src/net/dns/mdns_client_impl.h b/naiveproxy/src/net/dns/mdns_client_impl.h index bc98f70c03..1b0b0a5abf 100644 --- a/naiveproxy/src/net/dns/mdns_client_impl.h +++ b/naiveproxy/src/net/dns/mdns_client_impl.h @@ -17,6 +17,7 @@ #include "base/containers/queue.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/time/time.h" #include "net/base/io_buffer.h" @@ -131,7 +132,7 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient { // whenever the number of listeners reaches zero. The deletion happens // asychronously, so destroying the last listener does not immediately // invalidate the core. - class Core : public base::SupportsWeakPtr, MDnsConnection::Delegate { + class Core final : public MDnsConnection::Delegate { public: Core(base::Clock* clock, base::OneShotTimer* timer); @@ -210,6 +211,7 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient { base::Time scheduled_cleanup_; std::unique_ptr connection_; + base::WeakPtrFactory weak_ptr_factory_{this}; }; MDnsClientImpl(); @@ -248,8 +250,7 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient { std::unique_ptr core_; }; -class MDnsListenerImpl : public MDnsListener, - public base::SupportsWeakPtr { +class MDnsListenerImpl final : public MDnsListener { public: MDnsListenerImpl(uint16_t rrtype, const std::string& name, @@ -297,11 +298,11 @@ class MDnsListenerImpl : public MDnsListener, bool active_refresh_ = false; base::CancelableRepeatingClosure next_refresh_; + base::WeakPtrFactory weak_ptr_factory_{this}; }; -class MDnsTransactionImpl : public base::SupportsWeakPtr, - public MDnsTransaction, - public MDnsListener::Delegate { +class MDnsTransactionImpl final : public MDnsTransaction, + public MDnsListener::Delegate { public: MDnsTransactionImpl(uint16_t rrtype, const std::string& name, @@ -362,6 +363,7 @@ class MDnsTransactionImpl : public base::SupportsWeakPtr, bool started_ = false; int flags_; + base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace net diff --git a/naiveproxy/src/net/dns/system_dns_config_change_notifier.cc b/naiveproxy/src/net/dns/system_dns_config_change_notifier.cc index b9ab0dcfbd..93c5e1ae0b 100644 --- a/naiveproxy/src/net/dns/system_dns_config_change_notifier.cc +++ b/naiveproxy/src/net/dns/system_dns_config_change_notifier.cc @@ -13,6 +13,7 @@ #include "base/location.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/not_fatal_until.h" #include "base/sequence_checker.h" #include "base/synchronization/lock.h" #include "base/task/sequenced_task_runner.h" @@ -115,7 +116,7 @@ class SystemDnsConfigChangeNotifier::Core { { base::AutoLock lock(lock_); auto it = wrapped_observers_.find(observer); - DCHECK(it != wrapped_observers_.end()); + CHECK(it != wrapped_observers_.end(), base::NotFatalUntil::M130); removed_wrapped_observer = std::move(it->second); wrapped_observers_.erase(it); } diff --git a/naiveproxy/src/net/extras/shared_dictionary/OWNERS b/naiveproxy/src/net/extras/shared_dictionary/OWNERS index 96c689437f..f3dba24f2c 100644 --- a/naiveproxy/src/net/extras/shared_dictionary/OWNERS +++ b/naiveproxy/src/net/extras/shared_dictionary/OWNERS @@ -1,5 +1 @@ -# Primary -horo@chromium.org - -# Secondary -pmeenan@chromium.org +file://net/shared_dictionary/OWNERS diff --git a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_usage_info.h b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_usage_info.h index 22321e9b7d..50bfde3435 100644 --- a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_usage_info.h +++ b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_usage_info.h @@ -6,7 +6,7 @@ #define NET_EXTRAS_SHARED_DICTIONARY_SHARED_DICTIONARY_USAGE_INFO_H_ #include "base/component_export.h" -#include "net/extras/shared_dictionary/shared_dictionary_isolation_key.h" +#include "net/shared_dictionary/shared_dictionary_isolation_key.h" namespace net { diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc index d192a93e62..c305824368 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc @@ -26,6 +26,7 @@ #include "net/base/network_anonymization_key.h" #include "net/extras/sqlite/sqlite_persistent_store_backend_base.h" #include "net/reporting/reporting_endpoint.h" +#include "net/reporting/reporting_target_type.h" #include "sql/database.h" #include "sql/meta_table.h" #include "sql/statement.h" @@ -1386,6 +1387,8 @@ void SQLitePersistentReportingAndNelStore::Backend:: if (!NetworkAnonymizationKeyFromString(endpoints_statement.ColumnString(0), &network_anonymization_key)) continue; + // The target_type is set to kDeveloper because this function is used for + // V0 reporting, which only includes web developer entities. ReportingEndpointGroupKey group_key( network_anonymization_key, /* origin = */ @@ -1393,7 +1396,8 @@ void SQLitePersistentReportingAndNelStore::Backend:: /* origin_scheme = */ endpoints_statement.ColumnString(1), /* origin_host = */ endpoints_statement.ColumnString(2), /* origin_port = */ endpoints_statement.ColumnInt(3)), - /* group_name = */ endpoints_statement.ColumnString(4)); + /* group_name = */ endpoints_statement.ColumnString(4), + ReportingTargetType::kDeveloper); ReportingEndpoint::EndpointInfo endpoint_info; endpoint_info.url = GURL(endpoints_statement.ColumnString(5)); endpoint_info.priority = endpoints_statement.ColumnInt(6); @@ -1411,6 +1415,8 @@ void SQLitePersistentReportingAndNelStore::Backend:: endpoint_groups_statement.ColumnString(0), &network_anonymization_key)) continue; + // The target_type is set to kDeveloper because this function is used for + // V0 reporting, which only includes web developer entities. ReportingEndpointGroupKey group_key( network_anonymization_key, /* origin = */ @@ -1418,7 +1424,8 @@ void SQLitePersistentReportingAndNelStore::Backend:: /* origin_scheme = */ endpoint_groups_statement.ColumnString(1), /* origin_host = */ endpoint_groups_statement.ColumnString(2), /* origin_port = */ endpoint_groups_statement.ColumnInt(3)), - /* group_name = */ endpoint_groups_statement.ColumnString(4)); + /* group_name = */ endpoint_groups_statement.ColumnString(4), + ReportingTargetType::kDeveloper); OriginSubdomains include_subdomains = endpoint_groups_statement.ColumnBool(5) ? OriginSubdomains::INCLUDE : OriginSubdomains::EXCLUDE; diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc index 27c9ba4090..2a8ebf7abd 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc @@ -18,8 +18,8 @@ #include "base/task/sequenced_task_runner.h" #include "base/types/expected_macros.h" #include "net/base/network_isolation_key.h" -#include "net/extras/shared_dictionary/shared_dictionary_isolation_key.h" #include "net/extras/sqlite/sqlite_persistent_store_backend_base.h" +#include "net/shared_dictionary/shared_dictionary_isolation_key.h" #include "sql/database.h" #include "sql/statement.h" #include "sql/transaction.h" diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.cc b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.cc index 88d86765b2..6d85cb4e24 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.cc +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.cc @@ -25,14 +25,14 @@ namespace net { SQLitePersistentStoreBackendBase::SQLitePersistentStoreBackendBase( const base::FilePath& path, - std::string histogram_tag, + const std::string& histogram_tag, const int current_version_number, const int compatible_version_number, scoped_refptr background_task_runner, scoped_refptr client_task_runner, bool enable_exclusive_access) : path_(path), - histogram_tag_(std::move(histogram_tag)), + histogram_tag_(histogram_tag), current_version_number_(current_version_number), compatible_version_number_(compatible_version_number), background_task_runner_(std::move(background_task_runner)), diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.h b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.h index 0ace27e306..15eac6a3a7 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.h +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.h @@ -74,7 +74,7 @@ class SQLitePersistentStoreBackendBase // will be opened with exclusive flag. SQLitePersistentStoreBackendBase( const base::FilePath& path, - std::string histogram_tag, + const std::string& histogram_tag, const int current_version_number, const int compatible_version_number, scoped_refptr background_task_runner, diff --git a/naiveproxy/src/net/first_party_sets/first_party_sets_validator.cc b/naiveproxy/src/net/first_party_sets/first_party_sets_validator.cc new file mode 100644 index 0000000000..64c013ddcb --- /dev/null +++ b/naiveproxy/src/net/first_party_sets/first_party_sets_validator.cc @@ -0,0 +1,56 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/first_party_sets/first_party_sets_validator.h" + +#include "base/ranges/algorithm.h" +#include "net/base/schemeful_site.h" + +namespace net { + +FirstPartySetsValidator::FirstPartySetsValidator() = default; +FirstPartySetsValidator::~FirstPartySetsValidator() = default; + +FirstPartySetsValidator::FirstPartySetsValidator(FirstPartySetsValidator&&) = + default; +FirstPartySetsValidator& FirstPartySetsValidator::operator=( + FirstPartySetsValidator&&) = default; + +void FirstPartySetsValidator::Update(const SchemefulSite& site, + const SchemefulSite& primary) { + PrimarySiteState& primary_state = primary_states_[primary]; + if (site == primary) { + primary_state.has_self_entry = true; + } else { + primary_state.has_nonself_entry = true; + } + + const auto [it, inserted] = site_metadatas_.emplace(site, SiteState{primary}); + if (!inserted) { + // `site` appears in more than one set (or is listed in the same set more + // than once). + primary_state.is_disjoint = false; + primary_states_[it->second.first_seen_primary].is_disjoint = false; + } +} + +bool FirstPartySetsValidator::IsValid() const { + return base::ranges::all_of(primary_states_, [](const auto& pair) -> bool { + return pair.second.IsValid(); + }); +} + +bool FirstPartySetsValidator::IsSitePrimaryValid( + const SchemefulSite& primary) const { + const auto it = primary_states_.find(primary); + return it != primary_states_.end() && it->second.IsValid(); +} + +bool FirstPartySetsValidator::PrimarySiteState::IsValid() const { + // A set is valid iff its primary site has a self-entry, has at least one + // non-self entry, and the set is disjoint from all other sets. + return has_nonself_entry && has_self_entry && is_disjoint; +} + +} // namespace net diff --git a/naiveproxy/src/net/first_party_sets/first_party_sets_validator.h b/naiveproxy/src/net/first_party_sets/first_party_sets_validator.h new file mode 100644 index 0000000000..1cd28a0205 --- /dev/null +++ b/naiveproxy/src/net/first_party_sets/first_party_sets_validator.h @@ -0,0 +1,69 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_FIRST_PARTY_SETS_FIRST_PARTY_SETS_VALIDATOR_H_ +#define NET_FIRST_PARTY_SETS_FIRST_PARTY_SETS_VALIDATOR_H_ + +#include + +#include "net/base/net_export.h" +#include "net/base/schemeful_site.h" + +namespace net { + +// The helper class to check the validity of the Related Website Sets +// (First-Party Sets). E.g. Check whether the sets contain any singleton or +// orphan site. +// +// A singleton: some primary site that names a set with no non-primary sites. +// +// An orphan: some non-primary site whose primary has no entry in any set. +class NET_EXPORT FirstPartySetsValidator { + public: + FirstPartySetsValidator(); + ~FirstPartySetsValidator(); + + FirstPartySetsValidator(FirstPartySetsValidator&&); + FirstPartySetsValidator& operator=(FirstPartySetsValidator&&); + FirstPartySetsValidator(const FirstPartySetsValidator&) = delete; + FirstPartySetsValidator& operator=(const FirstPartySetsValidator&) = delete; + + // Updates the internal state of the validator with `site` and its `primary`. + // This method should be called once for each site in each set. + void Update(const SchemefulSite& site, const SchemefulSite& primary); + + // Returns true iff all the calls to `Update` thus far describe a valid set. + [[nodiscard]] bool IsValid() const; + + // Returns true iff `primary` has valid primary state for the RWSs. + [[nodiscard]] bool IsSitePrimaryValid(const SchemefulSite& primary) const; + + private: + struct PrimarySiteState { + bool IsValid() const; + + // A primary site is a singleton iff it is never used as the primary in some + // other site's entry. + bool has_nonself_entry = false; + // A primary site induces orphaned non-primary sites iff it is used as the + // primary site in some other site's entry, but it has no entry itself. + bool has_self_entry = false; + // True iff none of the sites in this primary's set appear in any other set. + bool is_disjoint = true; + }; + + struct SiteState { + SchemefulSite first_seen_primary; + }; + + // Tracks validity states for each primary site. + std::map primary_states_; + + // Tracks metadata for each site. + std::map site_metadatas_; +}; + +} // namespace net + +#endif // NET_FIRST_PARTY_SETS_FIRST_PARTY_SETS_VALIDATOR_H_ diff --git a/naiveproxy/src/net/first_party_sets/global_first_party_sets.cc b/naiveproxy/src/net/first_party_sets/global_first_party_sets.cc index 573ac50800..490ca230dd 100644 --- a/naiveproxy/src/net/first_party_sets/global_first_party_sets.cc +++ b/naiveproxy/src/net/first_party_sets/global_first_party_sets.cc @@ -4,14 +4,18 @@ #include "net/first_party_sets/global_first_party_sets.h" +#include +#include #include #include #include +#include #include "base/containers/contains.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/functional/function_ref.h" +#include "base/not_fatal_until.h" #include "base/ranges/algorithm.h" #include "base/types/optional_util.h" #include "net/base/schemeful_site.h" @@ -20,6 +24,7 @@ #include "net/first_party_sets/first_party_set_entry_override.h" #include "net/first_party_sets/first_party_set_metadata.h" #include "net/first_party_sets/first_party_sets_context_config.h" +#include "net/first_party_sets/first_party_sets_validator.h" #include "net/first_party_sets/local_set_declaration.h" namespace net { @@ -31,7 +36,7 @@ using SingleSet = base::flat_map; // Converts a list of First-Party Sets from a SingleSet to a FlattenedSet // representation. -FlattenedSets SetListToFlattenedSets(const std::vector& set_list) { +FlattenedSets Flatten(const std::vector& set_list) { FlattenedSets sets; for (const auto& set : set_list) { for (const auto& site_and_entry : set) { @@ -42,22 +47,10 @@ FlattenedSets SetListToFlattenedSets(const std::vector& set_list) { return sets; } -// Adds all sets in a list of First-Party Sets into `site_to_entry` which maps -// from a site to its entry. -void UpdateCustomizations( - const std::vector& set_list, - std::vector>& - site_to_entry) { - for (const auto& set : set_list) { - for (const auto& site_and_entry : set) { - site_to_entry.emplace_back(site_and_entry); - } - } -} - -const SchemefulSite& ProjectKey( - const std::pair& p) { - return p.first; +std::pair +SiteAndEntryToSiteAndOverride( + const std::pair& pair) { + return std::make_pair(pair.first, FirstPartySetEntryOverride(pair.second)); } } // namespace @@ -98,7 +91,7 @@ GlobalFirstPartySets::GlobalFirstPartySets( CHECK(base::ranges::all_of(aliases_, [&](const auto& pair) { return entries_.contains(pair.second); })); - CHECK(!ContainsSingleton()); + CHECK(IsValid(), base::NotFatalUntil::M130) << "Sets must be valid"; } GlobalFirstPartySets::GlobalFirstPartySets(GlobalFirstPartySets&&) = default; @@ -208,7 +201,7 @@ void GlobalFirstPartySets::ApplyManuallySpecifiedSet( /*addition_sets=*/{})); manual_aliases_ = std::move(manual_aliases); - CHECK(!ContainsSingleton()); + CHECK(IsValid(), base::NotFatalUntil::M130) << "Sets must be valid"; } void GlobalFirstPartySets::UnsafeSetManualConfig( @@ -217,74 +210,125 @@ void GlobalFirstPartySets::UnsafeSetManualConfig( manual_config_ = std::move(manual_config); } -FirstPartySetsContextConfig GlobalFirstPartySets::ComputeConfig( - const SetsMutation& mutation) const { - const std::vector& replacement_sets = mutation.replacements(); - const std::vector& addition_sets = mutation.additions(); - if (base::ranges::all_of(replacement_sets, - [](const SingleSet& set) { return set.empty(); }) && - base::ranges::all_of(addition_sets, - [](const SingleSet& set) { return set.empty(); })) { - // Nothing to do. - return FirstPartySetsContextConfig(); - } - - // Maps a site to its override. - std::vector> - site_to_entry; - - std::vector> - normalized_additions = NormalizeAdditionSets(addition_sets); - - // Create flattened versions of the sets for easier lookup. - FlattenedSets flattened_replacements = - SetListToFlattenedSets(replacement_sets); - FlattenedSets flattened_additions = - SetListToFlattenedSets(normalized_additions); - - // All of the custom sets are automatically inserted into site_to_entry. - UpdateCustomizations(replacement_sets, site_to_entry); - UpdateCustomizations(normalized_additions, site_to_entry); - - // Maps old primary site to new entry. - base::flat_map +base::flat_map +GlobalFirstPartySets::FindPrimariesAffectedByAdditions( + const FlattenedSets& additions) const { + std::vector> addition_intersected_primaries; - for (const auto& [new_member, new_entry] : flattened_additions) { + for (const auto& [new_member, new_entry] : additions) { if (const auto entry = FindEntry(new_member, /*config=*/nullptr); entry.has_value()) { // Found an overlap with the existing list of sets. - addition_intersected_primaries.emplace(entry->primary(), new_entry); + addition_intersected_primaries.emplace_back(entry->primary(), new_entry); } } + return addition_intersected_primaries; +} + +std::pair>, + base::flat_set> +GlobalFirstPartySets::FindPrimariesAffectedByReplacements( + const FlattenedSets& replacements, + const FlattenedSets& additions, + const base::flat_map& + addition_intersected_primaries) const { + if (replacements.empty()) { + return {{}, {}}; + } + + const auto canonicalize = [&](const SchemefulSite& site) { + const auto it = aliases_.find(site); + return it != aliases_.end() ? it->second : site; + }; + std::map> canonical_to_aliases; + ForEachAlias([&](const SchemefulSite& alias, const SchemefulSite& canonical) { + canonical_to_aliases[canonical].insert(alias); + }); + // Runs the given FunctionRef for all (existing) variants of the given site, + // i.e. all the aliases and the "canonical" variant. + const auto for_all_variants = + [canonical_to_aliases = std::move(canonical_to_aliases), + canonicalize = std::move(canonicalize)]( + const SchemefulSite& site, + const base::FunctionRef f) { + const SchemefulSite canonical = canonicalize(site); + f(canonical); + if (const auto it = canonical_to_aliases.find(canonical); + it != canonical_to_aliases.end()) { + for (const auto& alias : it->second) { + f(alias); + } + } + }; // Maps an existing primary site to the members it lost due to replacement. base::flat_map> potential_singletons; - for (const auto& [member, set_entry] : flattened_replacements) { - if (member == set_entry.primary()) - continue; - if (const auto existing_entry = FindEntry(member, /*config=*/nullptr); - existing_entry.has_value() && existing_entry->primary() != member && - !addition_intersected_primaries.contains(existing_entry->primary()) && - !flattened_additions.contains(existing_entry->primary()) && - !flattened_replacements.contains(existing_entry->primary())) { - potential_singletons[existing_entry->primary()].insert(member); - } - } - - // Find the existing primary sites that have left their existing sets, and - // whose existing members should be removed from their set (excluding any - // custom sets that those members are involved in). + // Stores existing primary sites which have left their sets (via + // replacement), and whose existing members should be removed from the set + // (excluding any custom sets that those members are involved in). base::flat_set replaced_existing_primaries; - for (const auto& [site, unused_primary] : flattened_replacements) { - if (const auto entry = FindEntry(site, /*config=*/nullptr); - entry.has_value() && entry->primary() == site) { - // Site was an primary in the existing sets. - bool inserted = replaced_existing_primaries.emplace(site).second; + for (const auto& [new_site, unused_entry] : replacements) { + const auto existing_entry = FindEntry(new_site, /*config=*/nullptr); + if (!existing_entry.has_value()) { + continue; + } + if (!addition_intersected_primaries.contains(existing_entry->primary()) && + !additions.contains(existing_entry->primary()) && + !replacements.contains(existing_entry->primary())) { + // The existing site's primary isn't involved in any of the customized + // sets, so it might become a singleton (if all of its variants and + // non-primaries [and their variants] are replaced by the + // customizations). + for_all_variants(new_site, [&](const SchemefulSite& variant) { + if (existing_entry->primary() != variant) { + potential_singletons[existing_entry->primary()].insert(variant); + } + }); + } + + if (existing_entry->primary() == new_site) { + // `new_site` was a primary in the existing sets, but is in the + // replacement sets, so its non-primaries (and aliases) might need to be + // deleted/hidden. + bool inserted = + replaced_existing_primaries.emplace(existing_entry->primary()).second; CHECK(inserted); } } + return std::make_pair(potential_singletons, replaced_existing_primaries); +} + +FirstPartySetsContextConfig GlobalFirstPartySets::ComputeConfig( + const SetsMutation& mutation) const { + if (base::ranges::all_of(mutation.replacements(), &SingleSet::empty) && + base::ranges::all_of(mutation.additions(), &SingleSet::empty)) { + // Nothing to do. + return FirstPartySetsContextConfig(); + } + + const FlattenedSets replacements = Flatten(mutation.replacements()); + const FlattenedSets additions = + Flatten(NormalizeAdditionSets(mutation.additions())); + + // Maps a site to its override. + std::vector> + site_to_override; + base::ranges::transform(replacements, std::back_inserter(site_to_override), + SiteAndEntryToSiteAndOverride); + base::ranges::transform(additions, std::back_inserter(site_to_override), + SiteAndEntryToSiteAndOverride); + + // Maps old primary site to new entry. + const base::flat_map + addition_intersected_primaries = + FindPrimariesAffectedByAdditions(additions); + + auto [potential_singletons, replaced_existing_primaries] = + FindPrimariesAffectedByReplacements(replacements, additions, + addition_intersected_primaries); + if (!addition_intersected_primaries.empty() || !potential_singletons.empty() || !replaced_existing_primaries.empty()) { // Find out which potential singletons are actually singletons; delete @@ -299,8 +343,8 @@ FirstPartySetsContextConfig GlobalFirstPartySets::ComputeConfig( if (const auto entry = addition_intersected_primaries.find(set_entry.primary()); entry != addition_intersected_primaries.end() && - !flattened_replacements.contains(member)) { - site_to_entry.emplace_back( + !replacements.contains(member)) { + site_to_override.emplace_back( member, FirstPartySetEntry(entry->second.primary(), member == entry->second.primary() ? SiteType::kPrimary @@ -319,9 +363,9 @@ FirstPartySetsContextConfig GlobalFirstPartySets::ComputeConfig( } // Remove members from sets whose primary left. if (replaced_existing_primaries.contains(set_entry.primary()) && - !flattened_replacements.contains(member) && + !replacements.contains(member) && !addition_intersected_primaries.contains(set_entry.primary())) { - site_to_entry.emplace_back(member, FirstPartySetEntryOverride()); + site_to_override.emplace_back(member, FirstPartySetEntryOverride()); } return true; @@ -330,7 +374,7 @@ FirstPartySetsContextConfig GlobalFirstPartySets::ComputeConfig( // Any primary remaining in `potential_singleton` is a real singleton, so // delete it: for (const auto& [primary, members] : potential_singletons) { - site_to_entry.emplace_back(primary, FirstPartySetEntryOverride()); + site_to_override.emplace_back(primary, FirstPartySetEntryOverride()); } } @@ -338,21 +382,27 @@ FirstPartySetsContextConfig GlobalFirstPartySets::ComputeConfig( // which is not already contained in the overlay, we explicitly ignore that // alias. ForEachAlias([&](const SchemefulSite& alias, const SchemefulSite& canonical) { - if (base::Contains(site_to_entry, canonical, ProjectKey) && - !base::Contains(site_to_entry, alias, ProjectKey)) { - site_to_entry.emplace_back(alias, FirstPartySetEntryOverride()); + if (base::Contains( + site_to_override, canonical, + &std::pair::first) && + !base::Contains( + site_to_override, alias, + &std::pair::first)) { + site_to_override.emplace_back(alias, FirstPartySetEntryOverride()); } }); - return FirstPartySetsContextConfig(std::move(site_to_entry)); + FirstPartySetsContextConfig config(std::move(site_to_override)); + CHECK(IsValid(&config), base::NotFatalUntil::M130) + << "Sets must not contain singleton or orphan"; + return config; } std::vector> GlobalFirstPartySets::NormalizeAdditionSets( const std::vector>& addition_sets) const { - if (base::ranges::all_of(addition_sets, - [](const SingleSet& set) { return set.empty(); })) { + if (base::ranges::all_of(addition_sets, &SingleSet::empty)) { // Nothing to do. return {}; } @@ -480,26 +530,17 @@ void GlobalFirstPartySets::ForEachAlias( } } -bool GlobalFirstPartySets::ContainsSingleton() const { - std::set possible_singletons; - std::set not_singletons; - +bool GlobalFirstPartySets::IsValid( + const FirstPartySetsContextConfig* config) const { + FirstPartySetsValidator validator; ForEachEffectiveSetEntry( - nullptr, + config, [&](const SchemefulSite& site, const FirstPartySetEntry& entry) -> bool { - if (!not_singletons.contains(entry.primary())) { - if (site == entry.primary()) { - possible_singletons.insert(entry.primary()); - } else { - not_singletons.insert(entry.primary()); - possible_singletons.erase(entry.primary()); - } - } - + validator.Update(site, entry.primary()); return true; }); - return !possible_singletons.empty(); + return validator.IsValid(); } std::ostream& operator<<(std::ostream& os, const GlobalFirstPartySets& sets) { diff --git a/naiveproxy/src/net/first_party_sets/global_first_party_sets.h b/naiveproxy/src/net/first_party_sets/global_first_party_sets.h index 0ee3c16b6e..4d1bb25a95 100644 --- a/naiveproxy/src/net/first_party_sets/global_first_party_sets.h +++ b/naiveproxy/src/net/first_party_sets/global_first_party_sets.h @@ -151,6 +151,27 @@ class NET_EXPORT GlobalFirstPartySets { const SchemefulSite& site, const FirstPartySetsContextConfig* config) const; + using FlattenedSets = base::flat_map; + + // Finds the existing primary sites whose sets are affected by a set of custom + // additions. + base::flat_map + FindPrimariesAffectedByAdditions(const FlattenedSets& additions) const; + + // Finds the existing primary sites whose sets are affected by a set of custom + // replacements. + // + // Returns the set of existing primaries that may become a singleton (along + // with the sites in their set that have left due to the replacements); and + // the set of existing primaries that themselves were in a replacement set. + std::pair>, + base::flat_set> + FindPrimariesAffectedByReplacements( + const FlattenedSets& replacements, + const FlattenedSets& additions, + const base::flat_map& + addition_intersected_primaries) const; + // Preprocesses a collection of "addition" sets, such that any sets that // transitively overlap (when taking the current `entries_` of this map, plus // the manual config, into account) are unioned together. I.e., this ensures @@ -173,9 +194,9 @@ class NET_EXPORT GlobalFirstPartySets { void ForEachAlias(base::FunctionRef f) const; - // Returns true iff this instance contains a singleton set (a set with only - // one site). - bool ContainsSingleton() const; + // Synchronously iterate over all the effective entries. Returns true iff all + // the entries are valid. + bool IsValid(const FirstPartySetsContextConfig* config = nullptr) const; // The version associated with the component_updater-provided public sets. // This may be invalid if the "First-Party Sets" component has not been diff --git a/naiveproxy/src/net/http/bidirectional_stream.cc b/naiveproxy/src/net/http/bidirectional_stream.cc index bb2a76bfef..a85ee99394 100644 --- a/naiveproxy/src/net/http/bidirectional_stream.cc +++ b/naiveproxy/src/net/http/bidirectional_stream.cc @@ -29,7 +29,6 @@ #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_log_util.h" #include "net/ssl/ssl_cert_request_info.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/gurl.h" @@ -37,10 +36,10 @@ namespace net { namespace { -base::Value::Dict NetLogHeadersParams(const spdy::Http2HeaderBlock* headers, +base::Value::Dict NetLogHeadersParams(const quiche::HttpHeaderBlock* headers, NetLogCaptureMode capture_mode) { base::Value::Dict dict; - dict.Set("headers", ElideHttp2HeaderBlockForNetLog(*headers, capture_mode)); + dict.Set("headers", ElideHttpHeaderBlockForNetLog(*headers, capture_mode)); return dict; } @@ -232,7 +231,7 @@ void BidirectionalStream::OnStreamReady(bool request_headers_sent) { } void BidirectionalStream::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { HttpResponseInfo response_info; if (SpdyHeadersToHttpResponse(response_headers, &response_info) != OK) { DLOG(WARNING) << "Invalid headers"; @@ -305,7 +304,7 @@ void BidirectionalStream::OnDataSent() { } void BidirectionalStream::OnTrailersReceived( - const spdy::Http2HeaderBlock& trailers) { + const quiche::HttpHeaderBlock& trailers) { if (net_log_.IsCapturing()) { net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_RECV_TRAILERS, [&](NetLogCaptureMode capture_mode) { diff --git a/naiveproxy/src/net/http/bidirectional_stream.h b/naiveproxy/src/net/http/bidirectional_stream.h index 33e2fe1141..68466371e0 100644 --- a/naiveproxy/src/net/http/bidirectional_stream.h +++ b/naiveproxy/src/net/http/bidirectional_stream.h @@ -21,7 +21,7 @@ #include "net/http/http_stream_factory.h" #include "net/http/http_stream_request.h" #include "net/log/net_log_with_source.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" namespace base { class OneShotTimer; @@ -69,7 +69,7 @@ class NET_EXPORT BidirectionalStream : public BidirectionalStreamImpl::Delegate, // call BidirectionalStream::SendData to send data, // or call BidirectionalStream::Cancel to cancel the stream. virtual void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) = 0; + const quiche::HttpHeaderBlock& response_headers) = 0; // Called when a pending read is completed asynchronously. // |bytes_read| specifies how much data is read. @@ -89,7 +89,8 @@ class NET_EXPORT BidirectionalStream : public BidirectionalStreamImpl::Delegate, // are received, which can happen before a read completes. // The delegate is able to continue reading if there is no pending read and // EOF has not been received, or to send data if there is no pending send. - virtual void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) = 0; + virtual void OnTrailersReceived( + const quiche::HttpHeaderBlock& trailers) = 0; // Called when an error occurred. Do not call into the stream after this // point. No other delegate functions will be called after this. @@ -187,10 +188,10 @@ class NET_EXPORT BidirectionalStream : public BidirectionalStreamImpl::Delegate, // BidirectionalStreamImpl::Delegate implementation: void OnStreamReady(bool request_headers_sent) override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnDataRead(int bytes_read) override; void OnDataSent() override; - void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) override; + void OnTrailersReceived(const quiche::HttpHeaderBlock& trailers) override; void OnFailed(int error) override; // HttpStreamRequest::Delegate implementation: diff --git a/naiveproxy/src/net/http/bidirectional_stream_impl.h b/naiveproxy/src/net/http/bidirectional_stream_impl.h index 99349641b6..09857747ec 100644 --- a/naiveproxy/src/net/http/bidirectional_stream_impl.h +++ b/naiveproxy/src/net/http/bidirectional_stream_impl.h @@ -14,7 +14,7 @@ #include "net/base/load_timing_info.h" #include "net/base/net_export.h" #include "net/socket/next_proto.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace base { @@ -59,7 +59,7 @@ class NET_EXPORT_PRIVATE BidirectionalStreamImpl { // reading, call BidirectionalStreamImpl::SendData to send data, // or call BidirectionalStreamImpl::Cancel to cancel the stream. virtual void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) = 0; + const quiche::HttpHeaderBlock& response_headers) = 0; // Called when read is completed asynchronously. |bytes_read| specifies how // much data is available. @@ -79,7 +79,8 @@ class NET_EXPORT_PRIVATE BidirectionalStreamImpl { // are received, which can happen before a read completes. // The delegate is able to continue reading if there is no pending read and // EOF has not been received, or to send data if there is no pending send. - virtual void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) = 0; + virtual void OnTrailersReceived( + const quiche::HttpHeaderBlock& trailers) = 0; // Called when an error occurred. Do not call into the stream after this // point. No other delegate functions will be called after this. diff --git a/naiveproxy/src/net/http/http_auth_cache.cc b/naiveproxy/src/net/http/http_auth_cache.cc index 70b870c0d0..cdd77cc1af 100644 --- a/naiveproxy/src/net/http/http_auth_cache.cc +++ b/naiveproxy/src/net/http/http_auth_cache.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/memory/raw_ref.h" #include "base/metrics/histogram_macros.h" +#include "base/not_fatal_until.h" #include "base/strings/string_util.h" #include "url/gurl.h" #include "url/scheme_host_port.h" @@ -434,7 +435,7 @@ void HttpAuthCache::EvictLeastRecentlyUsedEntry() { oldest_last_use_time_ticks = entry.last_use_time_ticks_; } } - DCHECK(oldest_entry_it != entries_.end()); + CHECK(oldest_entry_it != entries_.end(), base::NotFatalUntil::M130); entries_.erase(oldest_entry_it); } diff --git a/naiveproxy/src/net/http/http_basic_state.cc b/naiveproxy/src/net/http/http_basic_state.cc index 8ff9b25342..9150df7bbe 100644 --- a/naiveproxy/src/net/http/http_basic_state.cc +++ b/naiveproxy/src/net/http/http_basic_state.cc @@ -10,21 +10,26 @@ #include "base/check_op.h" #include "base/no_destructor.h" #include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" +#include "net/base/load_timing_info.h" +#include "net/base/net_errors.h" #include "net/http/http_request_info.h" #include "net/http/http_response_body_drainer.h" #include "net/http/http_stream_parser.h" #include "net/http/http_util.h" -#include "net/socket/client_socket_handle.h" +#include "net/socket/stream_socket.h" +#include "net/socket/stream_socket_handle.h" +#include "net/ssl/ssl_info.h" #include "url/gurl.h" namespace net { -HttpBasicState::HttpBasicState(std::unique_ptr connection, +HttpBasicState::HttpBasicState(std::unique_ptr connection, bool is_for_get_to_http_proxy) : read_buf_(base::MakeRefCounted()), connection_(std::move(connection)), is_for_get_to_http_proxy_(is_for_get_to_http_proxy) { - CHECK(connection_) << "ClientSocketHandle passed to HttpBasicState must " + CHECK(connection_) << "StreamSocketHandle passed to HttpBasicState must " "not be NULL. See crbug.com/790776"; } @@ -36,12 +41,36 @@ void HttpBasicState::Initialize(const HttpRequestInfo* request_info, DCHECK(!parser_.get()); traffic_annotation_ = request_info->traffic_annotation; parser_ = std::make_unique( - connection_->socket(), connection_->is_reused(), request_info->url, - request_info->method, request_info->upload_data_stream, read_buf_.get(), - net_log); + connection_->socket(), + connection_->reuse_type() == + StreamSocketHandle::SocketReuseType::kReusedIdle, + request_info->url, request_info->method, request_info->upload_data_stream, + read_buf_.get(), net_log); } -std::unique_ptr HttpBasicState::ReleaseConnection() { +void HttpBasicState::Close(bool not_reusable) { + // `parser_` is null if the owner of `this` is created by an orphaned + // HttpStreamFactory::Job in which case InitializeStream() will not have been + // called. This also protects against null dereference in the case where + // ReleaseConnection() has been called. + // + // TODO(mmenke): Can these cases be handled a bit more cleanly? + if (!parser_) { + return; + } + StreamSocket* socket = connection_->socket(); + if (not_reusable && socket) { + socket->Disconnect(); + } + parser()->OnConnectionClose(); + connection_->Reset(); +} + +std::unique_ptr HttpBasicState::ReleaseConnection() { + // The HttpStreamParser object still has a pointer to the connection. Just to + // be extra-sure it doesn't touch the connection again, delete it here rather + // than leaving it until the destructor is called. + parser_.reset(); return std::move(connection_); } @@ -49,30 +78,42 @@ scoped_refptr HttpBasicState::read_buf() const { return read_buf_; } -void HttpBasicState::DeleteParser() { parser_.reset(); } - std::string HttpBasicState::GenerateRequestLine() const { - static const char kSuffix[] = " HTTP/1.1\r\n"; - const size_t kSuffixLen = std::size(kSuffix) - 1; - const std::string path = is_for_get_to_http_proxy_ - ? HttpUtil::SpecForRequest(parser_->url()) - : parser_->url().PathForRequest(); - // Don't use StringPrintf for concatenation because it is very inefficient. - std::string request_line; - const size_t expected_size = - parser_->method().size() + 1 + path.size() + kSuffixLen; - request_line.reserve(expected_size); - request_line.append(parser_->method()); - request_line.append(1, ' '); - request_line.append(path); - request_line.append(kSuffix, kSuffixLen); - DCHECK_EQ(expected_size, request_line.size()); - return request_line; + return HttpUtil::GenerateRequestLine(parser_->method(), parser_->url(), + is_for_get_to_http_proxy_); } bool HttpBasicState::IsConnectionReused() const { - return connection_->is_reused() || - connection_->reuse_type() == ClientSocketHandle::UNUSED_IDLE; + return connection_->reuse_type() == + StreamSocketHandle::SocketReuseType::kReusedIdle || + connection_->reuse_type() == + StreamSocketHandle::SocketReuseType::kUnusedIdle; +} + +void HttpBasicState::SetConnectionReused() { + connection_->set_reuse_type(StreamSocketHandle::SocketReuseType::kReusedIdle); +} + +bool HttpBasicState::CanReuseConnection() const { + return parser_ && connection_->socket() && parser_->CanReuseConnection(); +} + +bool HttpBasicState::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { + return connection_->GetLoadTimingInfo(IsConnectionReused(), load_timing_info); +} + +void HttpBasicState::GetSSLInfo(SSLInfo* ssl_info) { + CHECK(connection_); + if (!connection_->socket() || !connection_->socket()->GetSSLInfo(ssl_info)) { + ssl_info->Reset(); + } +} + +int HttpBasicState::GetRemoteEndpoint(IPEndPoint* endpoint) { + if (!connection_ || !connection_->socket()) { + return ERR_SOCKET_NOT_CONNECTED; + } + return connection_->socket()->GetPeerAddress(endpoint); } const std::set& HttpBasicState::GetDnsAliases() const { diff --git a/naiveproxy/src/net/http/http_basic_state.h b/naiveproxy/src/net/http/http_basic_state.h index 93b3989fb0..7c995c1eb6 100644 --- a/naiveproxy/src/net/http/http_basic_state.h +++ b/naiveproxy/src/net/http/http_basic_state.h @@ -20,15 +20,18 @@ namespace net { -class ClientSocketHandle; +class StreamSocketHandle; class GrowableIOBuffer; +class IPEndPoint; class HttpStreamParser; struct HttpRequestInfo; +struct LoadTimingInfo; class NetLogWithSource; +class SSLInfo; class NET_EXPORT_PRIVATE HttpBasicState { public: - HttpBasicState(std::unique_ptr connection, + HttpBasicState(std::unique_ptr connection, bool is_for_get_to_http_proxy); HttpBasicState(const HttpBasicState&) = delete; @@ -41,17 +44,17 @@ class NET_EXPORT_PRIVATE HttpBasicState { RequestPriority priority, const NetLogWithSource& net_log); + // Called when the owner of `this` is closed. + void Close(bool not_reusable); + HttpStreamParser* parser() const { return parser_.get(); } // Returns true if this request is a non-tunneled HTTP request via a proxy. bool is_for_get_to_http_proxy() const { return is_for_get_to_http_proxy_; } - // Deletes |parser_| and sets it to NULL. - void DeleteParser(); + StreamSocketHandle* connection() const { return connection_.get(); } - ClientSocketHandle* connection() const { return connection_.get(); } - - std::unique_ptr ReleaseConnection(); + std::unique_ptr ReleaseConnection(); scoped_refptr read_buf() const; @@ -70,6 +73,20 @@ class NET_EXPORT_PRIVATE HttpBasicState { // TODO(mmenke): Consider renaming this concept, to avoid confusion with // ClientSocketHandle::is_reused(). bool IsConnectionReused() const; + void SetConnectionReused(); + + // Returns true if the connection can be "reused" as defined by + // HttpStreamParser. + // + // TODO(crbug.com/346835898): Consider renaming this concept, to avoid + // confusion with above IsConnectionReused() and ClientSocketHandle. + bool CanReuseConnection() const; + + bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const; + + void GetSSLInfo(SSLInfo* ssl_info); + + int GetRemoteEndpoint(IPEndPoint* endpoint); // Retrieves any DNS aliases for the remote endpoint. Includes all known // aliases, e.g. from A, AAAA, or HTTPS, not just from the address used for @@ -79,7 +96,7 @@ class NET_EXPORT_PRIVATE HttpBasicState { private: scoped_refptr read_buf_; - std::unique_ptr connection_; + std::unique_ptr connection_; std::unique_ptr parser_; diff --git a/naiveproxy/src/net/http/http_basic_stream.cc b/naiveproxy/src/net/http/http_basic_stream.cc index 23c9ee35d0..e401fc7254 100644 --- a/naiveproxy/src/net/http/http_basic_stream.cc +++ b/naiveproxy/src/net/http/http_basic_stream.cc @@ -14,13 +14,13 @@ #include "net/http/http_request_info.h" #include "net/http/http_response_body_drainer.h" #include "net/http/http_stream_parser.h" -#include "net/socket/client_socket_handle.h" +#include "net/socket/stream_socket_handle.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_info.h" namespace net { -HttpBasicStream::HttpBasicStream(std::unique_ptr connection, +HttpBasicStream::HttpBasicStream(std::unique_ptr connection, bool is_for_get_to_http_proxy) : state_(std::move(connection), is_for_get_to_http_proxy) {} @@ -80,29 +80,12 @@ int HttpBasicStream::ReadResponseBody(IOBuffer* buf, } void HttpBasicStream::Close(bool not_reusable) { - // parser() is null if |this| is created by an orphaned HttpStreamFactory::Job - // in which case InitializeStream() will not have been called. This also - // protects against null dereference in the case where - // state_.ReleaseConnection() has been called. - // - // TODO(mmenke): Can these cases be handled a bit more cleanly? - // WebSocketHandshakeStream will need to be updated as well. - if (!parser()) - return; - StreamSocket* socket = state_.connection()->socket(); - if (not_reusable && socket) - socket->Disconnect(); - parser()->OnConnectionClose(); - state_.connection()->Reset(); + state_.Close(not_reusable); } std::unique_ptr HttpBasicStream::RenewStreamForAuth() { DCHECK(IsResponseBodyComplete()); DCHECK(!parser()->IsMoreDataBuffered()); - // The HttpStreamParser object still has a pointer to the connection. Just to - // be extra-sure it doesn't touch the connection again, delete it here rather - // than leaving it until the destructor is called. - state_.DeleteParser(); return std::make_unique(state_.ReleaseConnection(), state_.is_for_get_to_http_proxy()); } @@ -116,12 +99,11 @@ bool HttpBasicStream::IsConnectionReused() const { } void HttpBasicStream::SetConnectionReused() { - state_.connection()->set_reuse_type(ClientSocketHandle::REUSED_IDLE); + state_.SetConnectionReused(); } bool HttpBasicStream::CanReuseConnection() const { - return parser() && state_.connection()->socket() && - parser()->CanReuseConnection(); + return state_.CanReuseConnection(); } int64_t HttpBasicStream::GetTotalReceivedBytes() const { @@ -138,9 +120,7 @@ int64_t HttpBasicStream::GetTotalSentBytes() const { bool HttpBasicStream::GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const { - if (!state_.connection()->GetLoadTimingInfo(IsConnectionReused(), - load_timing_info) || - !parser()) { + if (!state_.GetLoadTimingInfo(load_timing_info) || !parser()) { return false; } @@ -166,17 +146,11 @@ bool HttpBasicStream::GetAlternativeService( } void HttpBasicStream::GetSSLInfo(SSLInfo* ssl_info) { - if (!state_.connection()->socket() || - !state_.connection()->socket()->GetSSLInfo(ssl_info)) { - ssl_info->Reset(); - } + state_.GetSSLInfo(ssl_info); } int HttpBasicStream::GetRemoteEndpoint(IPEndPoint* endpoint) { - if (!state_.connection() || !state_.connection()->socket()) - return ERR_SOCKET_NOT_CONNECTED; - - return state_.connection()->socket()->GetPeerAddress(endpoint); + return state_.GetRemoteEndpoint(endpoint); } void HttpBasicStream::Drain(HttpNetworkSession* session) { diff --git a/naiveproxy/src/net/http/http_basic_stream.h b/naiveproxy/src/net/http/http_basic_stream.h index 46475928ad..59b57e3d04 100644 --- a/naiveproxy/src/net/http/http_basic_stream.h +++ b/naiveproxy/src/net/http/http_basic_stream.h @@ -24,7 +24,7 @@ namespace net { -class ClientSocketHandle; +class StreamSocketHandle; class HttpResponseInfo; struct HttpRequestInfo; class HttpRequestHeaders; @@ -36,7 +36,7 @@ class NET_EXPORT_PRIVATE HttpBasicStream : public HttpStream { public: // Constructs a new HttpBasicStream. InitializeStream must be called to // initialize it correctly. - HttpBasicStream(std::unique_ptr connection, + HttpBasicStream(std::unique_ptr connection, bool is_for_get_to_http_proxy); HttpBasicStream(const HttpBasicStream&) = delete; diff --git a/naiveproxy/src/net/http/http_cache.cc b/naiveproxy/src/net/http/http_cache.cc index 68f7479d0c..c5d6aea4bd 100644 --- a/naiveproxy/src/net/http/http_cache.cc +++ b/naiveproxy/src/net/http/http_cache.cc @@ -28,6 +28,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros_local.h" +#include "base/not_fatal_until.h" #include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/ranges/algorithm.h" @@ -449,29 +450,24 @@ HttpCache::~HttpCache() { } } -int HttpCache::GetBackend(disk_cache::Backend** backend, - CompletionOnceCallback callback) { +HttpCache::GetBackendResult HttpCache::GetBackend(GetBackendCallback callback) { DCHECK(!callback.is_null()); if (disk_cache_.get()) { - *backend = disk_cache_.get(); - return OK; + return {OK, disk_cache_.get()}; } - int rv = - CreateBackend(base::BindOnce(&HttpCache::ReportGetBackendResult, - GetWeakPtr(), backend, std::move(callback))); + int rv = CreateBackend(base::BindOnce(&HttpCache::ReportGetBackendResult, + GetWeakPtr(), std::move(callback))); if (rv != ERR_IO_PENDING) { - *backend = disk_cache_.get(); + return {rv, disk_cache_.get()}; } - return rv; + return {ERR_IO_PENDING, nullptr}; } -void HttpCache::ReportGetBackendResult(disk_cache::Backend** backend, - CompletionOnceCallback callback, +void HttpCache::ReportGetBackendResult(GetBackendCallback callback, int net_error) { - *backend = disk_cache_.get(); - std::move(callback).Run(net_error); + std::move(callback).Run(std::pair(net_error, disk_cache_.get())); } disk_cache::Backend* HttpCache::GetCurrentBackend() const { @@ -479,12 +475,10 @@ disk_cache::Backend* HttpCache::GetCurrentBackend() const { } // static -bool HttpCache::ParseResponseInfo(const char* data, - int len, +bool HttpCache::ParseResponseInfo(base::span data, HttpResponseInfo* response_info, bool* response_truncated) { - base::Pickle pickle = base::Pickle::WithUnownedBuffer( - base::as_bytes(base::span(data, base::checked_cast(len)))); + base::Pickle pickle = base::Pickle::WithUnownedBuffer(data); return response_info->InitFromPickle(pickle, response_truncated); } @@ -507,7 +501,6 @@ void HttpCache::OnExternalCacheHit( const GURL& url, const std::string& http_method, const NetworkIsolationKey& network_isolation_key, - bool is_subframe_document_resource, bool used_credentials) { if (!disk_cache_.get() || mode_ == DISABLE) { return; @@ -524,8 +517,9 @@ void HttpCache::OnExternalCacheHit( request_info.network_anonymization_key = NetworkAnonymizationKey::CreateFromNetworkIsolationKey( network_isolation_key); - - request_info.is_subframe_document_resource = is_subframe_document_resource; + // This method is only called for cache hits on resources, so mark this + // request as not being a subframe navigation. + request_info.is_subframe_document_resource = false; if (base::FeatureList::IsEnabled(features::kSplitCacheByIncludeCredentials)) { if (!used_credentials) { request_info.load_flags &= LOAD_DO_NOT_SAVE_COOKIES; @@ -900,7 +894,7 @@ void HttpCache::DeletePendingOp(PendingOp* pending_op) { if (!key.empty()) { auto it = pending_ops_.find(key); - DCHECK(it != pending_ops_.end()); + CHECK(it != pending_ops_.end(), base::NotFatalUntil::M130); pending_ops_.erase(it); } else { for (auto it = pending_ops_.begin(); it != pending_ops_.end(); ++it) { @@ -1092,7 +1086,7 @@ void HttpCache::DoneWithEntry(scoped_refptr& entry, // Transaction is reading from the entry. DCHECK(!entry->HasWriters()); auto readers_it = entry->readers().find(transaction); - DCHECK(readers_it != entry->readers().end()); + CHECK(readers_it != entry->readers().end(), base::NotFatalUntil::M130); entry->readers().erase(readers_it); ProcessQueuedTransactions(entry); } diff --git a/naiveproxy/src/net/http/http_cache.h b/naiveproxy/src/net/http/http_cache.h index 96a760147f..5ae8888718 100644 --- a/naiveproxy/src/net/http/http_cache.h +++ b/naiveproxy/src/net/http/http_cache.h @@ -24,6 +24,7 @@ #include #include "base/containers/lru_cache.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/functional/callback.h" #include "base/gtest_prod_util.h" @@ -175,21 +176,21 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory { HttpTransactionFactory* network_layer() { return network_layer_.get(); } + using GetBackendResult = std::pair>; + using GetBackendCallback = base::OnceCallback; // Retrieves the cache backend for this HttpCache instance. If the backend - // is not initialized yet, this method will initialize it. The return value is - // a network error code, and it could be ERR_IO_PENDING, in which case the - // `callback` will be notified when the operation completes. The pointer that - // receives the `backend` must remain valid until the operation completes. + // is not initialized yet, this method will initialize it. The integer portion + // of the return value is a network error code, and it could be + // ERR_IO_PENDING, in which case the `callback` will be notified when the + // operation completes. // `callback` will get cancelled if the HttpCache is destroyed. - int GetBackend(disk_cache::Backend** backend, - CompletionOnceCallback callback); + GetBackendResult GetBackend(GetBackendCallback callback); // Returns the current backend (can be NULL). disk_cache::Backend* GetCurrentBackend() const; // Given a header data blob, convert it to a response info object. - static bool ParseResponseInfo(const char* data, - int len, + static bool ParseResponseInfo(base::span data, HttpResponseInfo* response_info, bool* response_truncated); @@ -210,11 +211,11 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory { void CloseIdleConnections(const char* net_log_reason_utf8); // Called whenever an external cache in the system reuses the resource - // referred to by |url| and |http_method| and |network_isolation_key|. + // referred to by `url`, `http_method`, `network_isolation_key`, and + // `include_credentials`. void OnExternalCacheHit(const GURL& url, const std::string& http_method, const NetworkIsolationKey& network_isolation_key, - bool is_subframe_document_resource, bool include_credentials); // Causes all transactions created after this point to simulate lock timeout @@ -505,9 +506,7 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory { // operation completes. Returns an error code. int CreateBackend(CompletionOnceCallback callback); - void ReportGetBackendResult(disk_cache::Backend** backend, - CompletionOnceCallback callback, - int net_error); + void ReportGetBackendResult(GetBackendCallback callback, int net_error); // Makes sure that the backend creation is complete before allowing the // provided transaction to use the object. Returns an error code. diff --git a/naiveproxy/src/net/http/http_cache_transaction.cc b/naiveproxy/src/net/http/http_cache_transaction.cc index fd5cd3ab16..fc0bb4663d 100644 --- a/naiveproxy/src/net/http/http_cache_transaction.cc +++ b/naiveproxy/src/net/http/http_cache_transaction.cc @@ -25,12 +25,14 @@ #include "base/auto_reset.h" #include "base/compiler_specific.h" #include "base/containers/fixed_flat_set.h" +#include "base/containers/span.h" #include "base/feature_list.h" #include "base/format_macros.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/location.h" #include "base/memory/raw_ptr_exclusion.h" +#include "base/memory/stack_allocated.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/power_monitor/power_monitor.h" @@ -479,6 +481,15 @@ int64_t HttpCache::Transaction::GetTotalSentBytes() const { return total_sent_bytes; } +int64_t HttpCache::Transaction::GetReceivedBodyBytes() const { + int64_t received_body_bytes = network_transaction_info_.received_body_bytes; + const HttpTransaction* transaction = GetOwnedOrMovedNetworkTransaction(); + if (transaction) { + received_body_bytes = transaction->GetReceivedBodyBytes(); + } + return received_body_bytes; +} + void HttpCache::Transaction::DoneReading() { if (cache_.get() && entry_) { DCHECK_NE(mode_, UPDATE); @@ -1613,9 +1624,10 @@ int HttpCache::Transaction::DoCacheReadResponse() { } int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { - TRACE_EVENT_INSTANT( - "net", "HttpCacheTransaction::DoCacheReadResponseComplete", - perfetto::Track(trace_id_), "result", result, "io_buf_len", io_buf_len_); + TRACE_EVENT_INSTANT("net", + "HttpCacheTransaction::DoCacheReadResponseComplete", + perfetto::Track(trace_id_), "result", result, + "io_buf_len", read_buf_->size()); net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO, result); EndDiskCacheAccessTimeCount(DiskCacheAccessType::kRead); @@ -1623,9 +1635,9 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { // Record the time immediately before the cached response is parsed. read_headers_since_ = TimeTicks::Now(); - if (result != io_buf_len_ || - !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, &response_, - &truncated_)) { + if (result != read_buf_->size() || + !HttpCache::ParseResponseInfo(base::as_bytes(read_buf_->span()), + &response_, &truncated_)) { return OnCacheReadError(result, true); } @@ -1917,7 +1929,6 @@ int HttpCache::Transaction::DoSendRequestComplete(int result) { const HttpResponseInfo* response = network_trans_->GetResponseInfo(); response_.network_accessed = response->network_accessed; - response_.was_fetched_via_proxy = response->was_fetched_via_proxy; response_.proxy_chain = response->proxy_chain; response_.restricted_prefetch = response->restricted_prefetch; response_.resolve_error_info = response->resolve_error_info; @@ -2565,10 +2576,9 @@ void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log) { // // The former modes trump latter modes, so if we find a matching header we // can stop iterating kSpecialHeaders. - // static const struct { - // This field is not a raw_ptr<> because it was filtered by the rewriter - // for: #global-scope + // RAW_PTR_EXCLUSION: Never allocated by PartitionAlloc (always points to + // constexpr tables), so there is no benefit to using a raw_ptr, only cost. RAW_PTR_EXCLUSION const HeaderNameAndValue* search; int load_flag; } kSpecialHeaders[] = { @@ -3304,8 +3314,8 @@ int HttpCache::Transaction::DoConnectedCallback() { return OK; } - auto type = response_.was_fetched_via_proxy ? TransportType::kCachedFromProxy - : TransportType::kCached; + auto type = response_.WasFetchedViaProxy() ? TransportType::kCachedFromProxy + : TransportType::kCached; return connected_callback_.Run( TransportInfo(type, response_.remote_endpoint, /*accept_ch_frame_arg=*/"", /*cert_is_issued_by_known_root=*/false, kProtoUnknown), @@ -3932,6 +3942,8 @@ void HttpCache::Transaction::SaveNetworkTransactionInfo( network_transaction_info_.total_received_bytes += transaction.GetTotalReceivedBytes(); network_transaction_info_.total_sent_bytes += transaction.GetTotalSentBytes(); + network_transaction_info_.received_body_bytes = + transaction.GetReceivedBodyBytes(); ConnectionAttempts attempts = transaction.GetConnectionAttempts(); for (const auto& attempt : attempts) { diff --git a/naiveproxy/src/net/http/http_cache_transaction.h b/naiveproxy/src/net/http/http_cache_transaction.h index 93c6091b5b..1974b6be7c 100644 --- a/naiveproxy/src/net/http/http_cache_transaction.h +++ b/naiveproxy/src/net/http/http_cache_transaction.h @@ -144,6 +144,7 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { void StopCaching() override; int64_t GetTotalReceivedBytes() const override; int64_t GetTotalSentBytes() const override; + int64_t GetReceivedBodyBytes() const override; void DoneReading() override; const HttpResponseInfo* GetResponseInfo() const override; LoadState GetLoadState() const override; @@ -224,6 +225,7 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { std::unique_ptr old_network_trans_load_timing; int64_t total_received_bytes = 0; int64_t total_sent_bytes = 0; + int64_t received_body_bytes = 0; ConnectionAttempts old_connection_attempts; IPEndPoint old_remote_endpoint; // For metrics. Can be removed when associated histograms are removed. diff --git a/naiveproxy/src/net/http/http_cache_writers.cc b/naiveproxy/src/net/http/http_cache_writers.cc index 043b599d82..0f82652d71 100644 --- a/naiveproxy/src/net/http/http_cache_writers.cc +++ b/naiveproxy/src/net/http/http_cache_writers.cc @@ -10,6 +10,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/logging.h" +#include "base/not_fatal_until.h" #include "base/task/single_thread_task_runner.h" #include "net/base/net_errors.h" #include "net/disk_cache/disk_cache.h" @@ -191,7 +192,7 @@ void HttpCache::Writers::EraseTransaction(Transaction* transaction, int result) { // The transaction should be part of all_writers. auto it = all_writers_.find(transaction); - DCHECK(it != all_writers_.end()); + CHECK(it != all_writers_.end(), base::NotFatalUntil::M130); EraseTransaction(it, result); } diff --git a/naiveproxy/src/net/http/http_network_transaction.cc b/naiveproxy/src/net/http/http_network_transaction.cc index 1c7222e947..e4b9ba4c0d 100644 --- a/naiveproxy/src/net/http/http_network_transaction.cc +++ b/naiveproxy/src/net/http/http_network_transaction.cc @@ -480,6 +480,10 @@ int64_t HttpNetworkTransaction::GetTotalSentBytes() const { return total_sent_bytes; } +int64_t HttpNetworkTransaction::GetReceivedBodyBytes() const { + return received_body_bytes_; +} + void HttpNetworkTransaction::DoneReading() {} const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { @@ -515,6 +519,21 @@ bool HttpNetworkTransaction::GetLoadTimingInfo( if (!stream_ || !stream_->GetLoadTimingInfo(load_timing_info)) return false; + // If `dns_resolution_{start/end}_time_override_` are set, and they are older + // than `domain_lookup_{start/end}` of the `stream_`, use the overrides. + // TODO(crbug.com/40812426): Remove this when we launch Happy Eyeballs v3. + if (!dns_resolution_start_time_override_.is_null() && + !dns_resolution_end_time_override_.is_null() && + (dns_resolution_start_time_override_ < + load_timing_info->connect_timing.domain_lookup_start) && + (dns_resolution_end_time_override_ < + load_timing_info->connect_timing.domain_lookup_end)) { + load_timing_info->connect_timing.domain_lookup_start = + dns_resolution_start_time_override_; + load_timing_info->connect_timing.domain_lookup_end = + dns_resolution_end_time_override_; + } + load_timing_info->proxy_resolve_start = proxy_info_.proxy_resolve_start_time(); load_timing_info->proxy_resolve_end = proxy_info_.proxy_resolve_end_time(); @@ -635,6 +654,12 @@ void HttpNetworkTransaction::OnStreamReady(const ProxyInfo& used_proxy_info, response_.was_fetched_via_spdy = stream_request_->negotiated_protocol() == kProtoHTTP2; response_.dns_aliases = stream_->GetDnsAliases(); + + dns_resolution_start_time_override_ = + stream_request_->dns_resolution_start_time_override(); + dns_resolution_end_time_override_ = + stream_request_->dns_resolution_end_time_override(); + SetProxyInfoInResponse(used_proxy_info, &response_); OnIOComplete(OK); } @@ -1412,6 +1437,8 @@ int HttpNetworkTransaction::DoReadBodyComplete(int result) { if (result <= 0) { DCHECK_NE(ERR_IO_PENDING, result); done = true; + } else { + received_body_bytes_ += result; } // Clean up connection if we are done. @@ -1529,8 +1556,9 @@ void HttpNetworkTransaction::ProcessNetworkErrorLoggingHeader() { // Don't accept NEL headers received via a proxy, because the IP address of // the destination server is not known. - if (response_.was_fetched_via_proxy) + if (response_.WasFetchedViaProxy()) { return; + } // Only accept NEL headers on HTTPS connections that have no certificate // errors. @@ -1574,8 +1602,9 @@ void HttpNetworkTransaction::GenerateNetworkErrorLoggingReport(int rv) { // Don't generate NEL reports if we are behind a proxy, to avoid leaking // internal network details. - if (response_.was_fetched_via_proxy) + if (response_.WasFetchedViaProxy()) { return; + } // Ignore errors from non-HTTPS origins. if (!url_.SchemeIsCryptographic()) @@ -2072,11 +2101,8 @@ void HttpNetworkTransaction::SetProxyInfoInResponse( response_info->was_mdl_match = proxy_info.is_mdl_match(); if (proxy_info.is_empty()) { response_info->proxy_chain = ProxyChain(); - response_info->was_fetched_via_proxy = false; } else { response_info->proxy_chain = proxy_info.proxy_chain(); - response_info->was_fetched_via_proxy = - !response_info->proxy_chain.is_direct(); } } diff --git a/naiveproxy/src/net/http/http_network_transaction.h b/naiveproxy/src/net/http/http_network_transaction.h index 6d4cd70704..45295e2057 100644 --- a/naiveproxy/src/net/http/http_network_transaction.h +++ b/naiveproxy/src/net/http/http_network_transaction.h @@ -77,6 +77,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction void StopCaching() override; int64_t GetTotalReceivedBytes() const override; int64_t GetTotalSentBytes() const override; + int64_t GetReceivedBodyBytes() const override; void DoneReading() override; const HttpResponseInfo* GetResponseInfo() const override; LoadState GetLoadState() const override; @@ -498,6 +499,14 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction // Set to true when the server required HTTP/1.1 fallback. bool http_1_1_was_required_ = false; + + // If set, these values are used as DNS resolution times, rather than + // using DNS times coming from the established stream. + base::TimeTicks dns_resolution_start_time_override_; + base::TimeTicks dns_resolution_end_time_override_; + + // The number of bytes of the body received from network. + int64_t received_body_bytes_ = 0; }; } // namespace net diff --git a/naiveproxy/src/net/http/http_request_headers.cc b/naiveproxy/src/net/http/http_request_headers.cc index 716e37f39b..202f078693 100644 --- a/naiveproxy/src/net/http/http_request_headers.cc +++ b/naiveproxy/src/net/http/http_request_headers.cc @@ -70,6 +70,8 @@ const char HttpRequestHeaders::kProxyAuthorization[] = "Proxy-Authorization"; const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection"; const char HttpRequestHeaders::kRange[] = "Range"; const char HttpRequestHeaders::kReferer[] = "Referer"; +const char HttpRequestHeaders::kSecFetchStorageAccess[] = + "Sec-Fetch-Storage-Access"; const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding"; const char HttpRequestHeaders::kUserAgent[] = "User-Agent"; diff --git a/naiveproxy/src/net/http/http_request_headers.h b/naiveproxy/src/net/http/http_request_headers.h index cab12dc6ce..097eb2e13f 100644 --- a/naiveproxy/src/net/http/http_request_headers.h +++ b/naiveproxy/src/net/http/http_request_headers.h @@ -100,6 +100,7 @@ class NET_EXPORT HttpRequestHeaders { static const char kProxyConnection[]; static const char kRange[]; static const char kReferer[]; + static const char kSecFetchStorageAccess[]; static const char kTransferEncoding[]; static const char kUserAgent[]; diff --git a/naiveproxy/src/net/http/http_request_info.h b/naiveproxy/src/net/http/http_request_info.h index 8951f4fa64..d79c9eb8ab 100644 --- a/naiveproxy/src/net/http/http_request_info.h +++ b/naiveproxy/src/net/http/http_request_info.h @@ -8,6 +8,7 @@ #include #include +#include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "net/base/idempotency.h" #include "net/base/net_export.h" @@ -17,6 +18,8 @@ #include "net/base/request_priority.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_request_headers.h" +#include "net/shared_dictionary/shared_dictionary.h" +#include "net/shared_dictionary/shared_dictionary_getter.h" #include "net/socket/socket_tag.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/gurl.h" @@ -119,6 +122,10 @@ struct NET_EXPORT HttpRequestInfo { // Use as ID to mark the cache entry when persisting. Should be a positive // number once set. std::optional browser_run_id; + + // Used to get a shared dictionary for the request. This may be null if the + // request does not use a shared dictionary. + SharedDictionaryGetter dictionary_getter; }; } // namespace net diff --git a/naiveproxy/src/net/http/http_response_headers.cc b/naiveproxy/src/net/http/http_response_headers.cc index 6cbfa6f008..6d8ee86e52 100644 --- a/naiveproxy/src/net/http/http_response_headers.cc +++ b/naiveproxy/src/net/http/http_response_headers.cc @@ -233,23 +233,30 @@ HttpResponseHeaders::HttpResponseHeaders(const std::string& raw_input) : response_code_(-1) { Parse(raw_input); - // The most important thing to do with this histogram is find out - // the existence of unusual HTTP status codes. As it happens - // right now, there aren't double-constructions of response headers - // using this constructor, so our counts should also be accurate, + // As it happens right now, there aren't double-constructions of response + // headers using this constructor, so our counts should also be accurate, // without instantiating the histogram in two places. It is also // important that this histogram not collect data in the other // constructor, which rebuilds an histogram from a pickle, since // that would actually create a double call between the original // HttpResponseHeader that was serialized, and initialization of the // new object from that pickle. - UMA_HISTOGRAM_CUSTOM_ENUMERATION( - "Net.HttpResponseCode", - HttpUtil::MapStatusCodeForHistogram(response_code_), - // Note the third argument is only - // evaluated once, see macro - // definition for details. - HttpUtil::GetStatusCodesForHistogram()); + if (base::FeatureList::IsEnabled(features::kOptimizeParsingDataUrls)) { + std::optional status_code = + TryToGetHttpStatusCode(response_code_); + if (status_code.has_value()) { + UMA_HISTOGRAM_ENUMERATION("Net.HttpResponseCode2", status_code.value(), + net::HttpStatusCode::HTTP_STATUS_CODE_MAX); + } + } else { + UMA_HISTOGRAM_CUSTOM_ENUMERATION( + "Net.HttpResponseCode", + HttpUtil::MapStatusCodeForHistogram(response_code_), + // Note the third argument is only + // evaluated once, see macro + // definition for details. + HttpUtil::GetStatusCodesForHistogram()); + } } HttpResponseHeaders::HttpResponseHeaders(base::PickleIterator* iter) @@ -358,6 +365,23 @@ scoped_refptr HttpResponseHeaders::TryToCreate( HttpUtil::AssembleRawHeaders(headers)); } +scoped_refptr HttpResponseHeaders::TryToCreateForDataURL( + std::string_view content_type) { + // Reject strings with nulls. + if (HasEmbeddedNulls(content_type) || + content_type.size() > std::numeric_limits::max()) { + return nullptr; + } + + constexpr char kStatusLineAndHeaderName[] = "HTTP/1.1 200 OK\0Content-Type:"; + std::string raw_headers = + base::StrCat({std::string_view(kStatusLineAndHeaderName, + sizeof(kStatusLineAndHeaderName) - 1), + content_type, std::string_view("\0\0", 2)}); + + return base::MakeRefCounted(raw_headers); +} + void HttpResponseHeaders::Persist(base::Pickle* pickle, PersistOptions options) { if (options == PERSIST_RAW) { diff --git a/naiveproxy/src/net/http/http_response_headers.h b/naiveproxy/src/net/http/http_response_headers.h index 8364f7a402..d10a1cf56a 100644 --- a/naiveproxy/src/net/http/http_response_headers.h +++ b/naiveproxy/src/net/http/http_response_headers.h @@ -150,6 +150,13 @@ class NET_EXPORT HttpResponseHeaders static scoped_refptr TryToCreate( std::string_view headers); + // Takes content_type as an ASCII string and tries to combine it with the HTTP + // status line for data: URLs. Returns nullptr on failure. Unlike TryToCreate, + // HttpUtil::AssembleRawHeaders does not need to be called as the raw headers + // are already known. + static scoped_refptr TryToCreateForDataURL( + std::string_view content_type); + HttpResponseHeaders(const HttpResponseHeaders&) = delete; HttpResponseHeaders& operator=(const HttpResponseHeaders&) = delete; diff --git a/naiveproxy/src/net/http/http_response_info.cc b/naiveproxy/src/net/http/http_response_info.cc index fdbf5f0ca4..0a686620da 100644 --- a/naiveproxy/src/net/http/http_response_info.cc +++ b/naiveproxy/src/net/http/http_response_info.cc @@ -78,6 +78,7 @@ enum { RESPONSE_INFO_WAS_ALPN = 1 << 14, // This bit is set if the request was fetched via an explicit proxy. + // This bit is deprecated. RESPONSE_INFO_WAS_PROXY = 1 << 15, // This bit is set if the response info has an SSL connection status field. @@ -140,6 +141,9 @@ enum { // This bit is set if the request usd a shared dictionary for decoding its // body. RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY = 1, + + // This bit is set if the response has valid `proxy_chain`. + RESPONSE_EXTRA_INFO_HAS_PROXY_CHAIN = 1 << 1, }; HttpResponseInfo::HttpResponseInfo() = default; @@ -301,8 +305,6 @@ bool HttpResponseInfo::InitFromPickle(const base::Pickle& pickle, was_alpn_negotiated = (flags & RESPONSE_INFO_WAS_ALPN) != 0; - was_fetched_via_proxy = (flags & RESPONSE_INFO_WAS_PROXY) != 0; - *response_truncated = (flags & RESPONSE_INFO_TRUNCATED) != 0; did_use_http_auth = (flags & RESPONSE_INFO_USE_HTTP_AUTHENTICATION) != 0; @@ -354,6 +356,13 @@ bool HttpResponseInfo::InitFromPickle(const base::Pickle& pickle, did_use_shared_dictionary = (extra_flags & RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY) != 0; + + if (extra_flags & RESPONSE_EXTRA_INFO_HAS_PROXY_CHAIN) { + if (!proxy_chain.InitFromPickle(&iter)) { + return false; + } + } + return true; } @@ -382,8 +391,6 @@ void HttpResponseInfo::Persist(base::Pickle* pickle, flags |= RESPONSE_INFO_WAS_ALPN; flags |= RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL; } - if (was_fetched_via_proxy) - flags |= RESPONSE_INFO_WAS_PROXY; if (connection_info != HttpConnectionInfo::kUNKNOWN) { flags |= RESPONSE_INFO_HAS_CONNECTION_INFO; } @@ -409,6 +416,10 @@ void HttpResponseInfo::Persist(base::Pickle* pickle, extra_flags |= RESPONSE_EXTRA_INFO_DID_USE_SHARED_DICTIONARY; } + if (proxy_chain.IsValid()) { + extra_flags |= RESPONSE_EXTRA_INFO_HAS_PROXY_CHAIN; + } + if (extra_flags) { flags |= RESPONSE_INFO_HAS_EXTRA_FLAGS; } @@ -474,6 +485,10 @@ void HttpResponseInfo::Persist(base::Pickle* pickle, if (browser_run_id.has_value()) { pickle->WriteInt64(browser_run_id.value()); } + + if (proxy_chain.IsValid()) { + proxy_chain.Persist(pickle); + } } bool HttpResponseInfo::DidUseQuic() const { @@ -526,4 +541,8 @@ bool HttpResponseInfo::DidUseQuic() const { } } +bool HttpResponseInfo::WasFetchedViaProxy() const { + return proxy_chain.IsValid() && !proxy_chain.is_direct(); +} + } // namespace net diff --git a/naiveproxy/src/net/http/http_response_info.h b/naiveproxy/src/net/http/http_response_info.h index ec439b0828..f711f01979 100644 --- a/naiveproxy/src/net/http/http_response_info.h +++ b/naiveproxy/src/net/http/http_response_info.h @@ -104,20 +104,9 @@ class NET_EXPORT HttpResponseInfo { // True if the response was fetched via explicit proxying. Any type of // proxying may have taken place, HTTP or SOCKS. Note, we do not know if a // transparent proxy may have been involved. - // - // If true and this struct was not restored from pickled data, `proxy_chain` - // contains the proxy chain that was used. - // - // TODO(crbug.com/40487912): Remove this in favor of `proxy_chain`. - bool was_fetched_via_proxy = false; + bool WasFetchedViaProxy() const; // Information about the proxy chain used to fetch this response, if any. - // - // This field is not persisted by `Persist()` and not restored by - // `InitFromPickle()`. - // - // TODO(crbug.com/40487912): Support this field in `Persist()` and - // `InitFromPickle()` then use it to replace `was_fetched_via_proxy`. ProxyChain proxy_chain; // Whether this request was eligible for IP Protection based on the request diff --git a/naiveproxy/src/net/http/http_status_code.cc b/naiveproxy/src/net/http/http_status_code.cc index df035a5750..f42a999f9a 100644 --- a/naiveproxy/src/net/http/http_status_code.cc +++ b/naiveproxy/src/net/http/http_status_code.cc @@ -31,4 +31,17 @@ const char* TryToGetHttpReasonPhrase(HttpStatusCode code) { } } +const std::optional TryToGetHttpStatusCode(int response_code) { + switch (response_code) { +#define HTTP_STATUS_ENUM_VALUE(label, code, reason) \ + case code: \ + return HTTP_##label; +#include "net/http/http_status_code_list.h" +#undef HTTP_STATUS_ENUM_VALUE + + default: + return std::nullopt; + } +} + } // namespace net diff --git a/naiveproxy/src/net/http/http_status_code.h b/naiveproxy/src/net/http/http_status_code.h index 78950d268c..898cc4f0a0 100644 --- a/naiveproxy/src/net/http/http_status_code.h +++ b/naiveproxy/src/net/http/http_status_code.h @@ -5,10 +5,15 @@ #ifndef NET_HTTP_HTTP_STATUS_CODE_H_ #define NET_HTTP_HTTP_STATUS_CODE_H_ +#include + #include "net/base/net_export.h" namespace net { +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// // HTTP status codes. enum HttpStatusCode { @@ -33,6 +38,12 @@ NET_EXPORT const char* GetHttpReasonPhrase(HttpStatusCode code); // was obtained from a non-trusted party. NET_EXPORT const char* TryToGetHttpReasonPhrase(HttpStatusCode code); +// Returns the corresponding HTTP status code enum value for a given +// |response_code|. Returns std::nullopt if the status code is not in the IANA +// HTTP Status Code Registry. +NET_EXPORT const std::optional TryToGetHttpStatusCode( + int response_code); + } // namespace net #endif // NET_HTTP_HTTP_STATUS_CODE_H_ diff --git a/naiveproxy/src/net/http/http_status_code_list.h b/naiveproxy/src/net/http/http_status_code_list.h index b954fbe04e..9bc12c1810 100644 --- a/naiveproxy/src/net/http/http_status_code_list.h +++ b/naiveproxy/src/net/http/http_status_code_list.h @@ -19,6 +19,7 @@ // Informational 1xx HTTP_STATUS_ENUM_VALUE(CONTINUE, 100, "Continue") HTTP_STATUS_ENUM_VALUE(SWITCHING_PROTOCOLS, 101, "Switching Protocols") +HTTP_STATUS_ENUM_VALUE(PROCESSING, 102, "Processing") HTTP_STATUS_ENUM_VALUE(EARLY_HINTS, 103, "Early Hints") // Successful 2xx @@ -31,6 +32,9 @@ HTTP_STATUS_ENUM_VALUE(NON_AUTHORITATIVE_INFORMATION, HTTP_STATUS_ENUM_VALUE(NO_CONTENT, 204, "No Content") HTTP_STATUS_ENUM_VALUE(RESET_CONTENT, 205, "Reset Content") HTTP_STATUS_ENUM_VALUE(PARTIAL_CONTENT, 206, "Partial Content") +HTTP_STATUS_ENUM_VALUE(MULTI_STATUS, 207, "Multi-Status") +HTTP_STATUS_ENUM_VALUE(ALREADY_REPORTED, 208, "Already Reported") +HTTP_STATUS_ENUM_VALUE(IM_USED, 226, "IM Used") // Redirection 3xx HTTP_STATUS_ENUM_VALUE(MULTIPLE_CHOICES, 300, "Multiple Choices") @@ -70,9 +74,20 @@ HTTP_STATUS_ENUM_VALUE(REQUESTED_RANGE_NOT_SATISFIABLE, HTTP_STATUS_ENUM_VALUE(EXPECTATION_FAILED, 417, "Expectation Failed") // 418 returned by Cloud Print. HTTP_STATUS_ENUM_VALUE(INVALID_XPRIVET_TOKEN, 418, "Invalid XPrivet Token") +HTTP_STATUS_ENUM_VALUE(MISDIRECTED_REQUEST, 421, "Misdirected Request") HTTP_STATUS_ENUM_VALUE(UNPROCESSABLE_CONTENT, 422, "Unprocessable Content") +HTTP_STATUS_ENUM_VALUE(LOCKED, 423, "Locked") +HTTP_STATUS_ENUM_VALUE(FAILED_DEPENDENCY, 424, "Failed Dependency") HTTP_STATUS_ENUM_VALUE(TOO_EARLY, 425, "Too Early") +HTTP_STATUS_ENUM_VALUE(UPGRADE_REQUIRED, 426, "Upgrade Required") +HTTP_STATUS_ENUM_VALUE(PRECONDITION_REQUIRED, 428, "Precondition Required") HTTP_STATUS_ENUM_VALUE(TOO_MANY_REQUESTS, 429, "Too Many Requests") +HTTP_STATUS_ENUM_VALUE(REQUEST_HEADER_FIELDS_TOO_LARGE, + 431, + "Request Header Fields Too Large") +HTTP_STATUS_ENUM_VALUE(UNAVAILABLE_FOR_LEGAL_REASONS, + 451, + "Unavailable For Legal Reasons") // Server error 5xx HTTP_STATUS_ENUM_VALUE(INTERNAL_SERVER_ERROR, 500, "Internal Server Error") @@ -81,3 +96,13 @@ HTTP_STATUS_ENUM_VALUE(BAD_GATEWAY, 502, "Bad Gateway") HTTP_STATUS_ENUM_VALUE(SERVICE_UNAVAILABLE, 503, "Service Unavailable") HTTP_STATUS_ENUM_VALUE(GATEWAY_TIMEOUT, 504, "Gateway Timeout") HTTP_STATUS_ENUM_VALUE(VERSION_NOT_SUPPORTED, 505, "HTTP Version Not Supported") +HTTP_STATUS_ENUM_VALUE(VARIANT_ALSO_NEGOTIATES, 506, "Variant Also Negotiates") +HTTP_STATUS_ENUM_VALUE(INSUFFICIENT_STORAGE, 507, "Insufficient Storage") +HTTP_STATUS_ENUM_VALUE(LOOP_DETECTED, 508, "Loop Detected") +HTTP_STATUS_ENUM_VALUE(NOT_EXTENDED_OBSOLETED, 510, "Not Extended (Obsoleted)") +HTTP_STATUS_ENUM_VALUE(NETWORK_AUTHENTICATION_REQUIRED, + 511, + "Network Authentication Required") + +// Max value for histograms. Should not be recorded. +HTTP_STATUS_ENUM_VALUE(STATUS_CODE_MAX, 600, "HTTP Status Code Max") diff --git a/naiveproxy/src/net/http/http_stream_factory_job.cc b/naiveproxy/src/net/http/http_stream_factory_job.cc index 47329850df..ca38eb9752 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job.cc +++ b/naiveproxy/src/net/http/http_stream_factory_job.cc @@ -900,6 +900,11 @@ int HttpStreamFactory::Job::DoInitConnectionImplQuic( void HttpStreamFactory::Job::OnQuicHostResolution(int result) { DCHECK(expect_on_quic_host_resolution_); expect_on_quic_host_resolution_ = false; + + delegate_->OnQuicHostResolution(destination_, + quic_request_.dns_resolution_start_time(), + quic_request_.dns_resolution_end_time()); + // If no `OnQuicSessionCreated` call is expected, then consider the // connection "initialized" and inform the delegate. Note that // `OnQuicHostResolution` is actually called somewhat _after_ host resolution @@ -1039,7 +1044,7 @@ int HttpStreamFactory::Job::DoInitConnectionComplete(int result) { stream_ = std::make_unique(std::move(session), std::move(dns_aliases)); } - next_state_ = STATE_NONE; + next_state_ = STATE_CREATE_STREAM_COMPLETE; return OK; } diff --git a/naiveproxy/src/net/http/http_stream_factory_job.h b/naiveproxy/src/net/http/http_stream_factory_job.h index 620893b403..c6c7d84c09 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job.h +++ b/naiveproxy/src/net/http/http_stream_factory_job.h @@ -83,6 +83,12 @@ class HttpStreamFactory::Job const ProxyInfo& used_proxy_info, std::unique_ptr stream) = 0; + // Invoked when a QUIC job finished a DNS resolution. + virtual void OnQuicHostResolution( + const url::SchemeHostPort& destination, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time) = 0; + // Invoked when |job| fails to create a stream. virtual void OnStreamFailed(Job* job, int status) = 0; diff --git a/naiveproxy/src/net/http/http_stream_factory_job_controller.cc b/naiveproxy/src/net/http/http_stream_factory_job_controller.cc index f8dd063d2c..7886a25bec 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job_controller.cc +++ b/naiveproxy/src/net/http/http_stream_factory_job_controller.cc @@ -151,7 +151,9 @@ HttpStreamFactory::JobController::JobController( net_log_(NetLogWithSource::Make( session->net_log(), NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)) { - DCHECK(factory); + DCHECK(factory_); + DCHECK(session_); + DCHECK(job_factory_); DCHECK(base::EqualsCaseInsensitiveASCII(origin_url_.scheme_piece(), url::kHttpScheme) || base::EqualsCaseInsensitiveASCII(origin_url_.scheme_piece(), @@ -170,6 +172,12 @@ HttpStreamFactory::JobController::JobController( dict.Set("is_preconnect", is_preconnect_); dict.Set("privacy_mode", PrivacyModeToDebugString(request_info_.privacy_mode)); + base::Value::List allowed_bad_certs_list; + for (const auto& cert_and_status : allowed_bad_certs_) { + allowed_bad_certs_list.Append( + cert_and_status.cert->subject().GetDisplayName()); + } + dict.Set("allowed_bad_certs", std::move(allowed_bad_certs_list)); return dict; }); } @@ -193,7 +201,6 @@ std::unique_ptr HttpStreamFactory::JobController::Start( const NetLogWithSource& source_net_log, HttpStreamRequest::StreamType stream_type, RequestPriority priority) { - DCHECK(factory_); DCHECK(!request_); stream_type_ = stream_type; @@ -375,6 +382,24 @@ void HttpStreamFactory::JobController::OnWebSocketHandshakeStreamReady( std::move(stream)); } +void HttpStreamFactory::JobController::OnQuicHostResolution( + const url::SchemeHostPort& destination, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time) { + if (!request_) { + return; + } + if (destination != url::SchemeHostPort(origin_url_)) { + // Ignores different destination alternative job's DNS resolution time. + return; + } + // QUIC jobs (ALTERNATIVE, DNS_ALPN_H3) are started before the non-QUIC (MAIN) + // job. So we set the DNS resolution overrides to use the DNS timing of the + // QUIC jobs. + request_->SetDnsResolutionTimeOverrides(dns_resolution_start_time, + dns_resolution_end_time); +} + void HttpStreamFactory::JobController::OnStreamFailed(Job* job, int status) { DCHECK_NE(OK, status); if (job->job_type() == MAIN) { @@ -753,7 +778,6 @@ int HttpStreamFactory::JobController::DoLoop(int rv) { int HttpStreamFactory::JobController::DoResolveProxy() { DCHECK(!proxy_resolve_request_); - DCHECK(session_); next_state_ = STATE_RESOLVE_PROXY_COMPLETE; @@ -1398,7 +1422,6 @@ int HttpStreamFactory::JobController::ReconsiderProxyAfterError(Job* job, // ReconsiderProxyAfterError() should only be called when the last job fails. DCHECK_EQ(1, GetJobCount()); DCHECK(!proxy_resolve_request_); - DCHECK(session_); if (!job->should_reconsider_proxy()) { return error; diff --git a/naiveproxy/src/net/http/http_stream_factory_job_controller.h b/naiveproxy/src/net/http/http_stream_factory_job_controller.h index c700dc69ff..b9912e72c8 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job_controller.h +++ b/naiveproxy/src/net/http/http_stream_factory_job_controller.h @@ -105,6 +105,11 @@ class HttpStreamFactory::JobController const ProxyInfo& used_proxy_info, std::unique_ptr stream) override; + // Invoked when a QUIC job finished a DNS resolution. + void OnQuicHostResolution(const url::SchemeHostPort& destination, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time) override; + // Invoked when |job| fails to create a stream. void OnStreamFailed(Job* job, int status) override; @@ -175,7 +180,7 @@ class HttpStreamFactory::JobController }; void OnIOComplete(int result); - void OnResolveProxyError(int error); + void RunLoop(int result); int DoLoop(int result); int DoResolveProxy(); @@ -288,9 +293,9 @@ class HttpStreamFactory::JobController (dns_alpn_h3_job_ ? 1 : 0); } - raw_ptr factory_; - raw_ptr session_; - raw_ptr job_factory_; + const raw_ptr factory_; + const raw_ptr session_; + const raw_ptr job_factory_; // Request will be handed out to factory once created. This just keeps an // reference and is safe as |request_| will notify |this| JobController diff --git a/naiveproxy/src/net/http/http_stream_key.cc b/naiveproxy/src/net/http/http_stream_key.cc new file mode 100644 index 0000000000..7cc595db81 --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_key.cc @@ -0,0 +1,49 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_stream_key.h" + +#include "net/base/network_anonymization_key.h" +#include "net/base/privacy_mode.h" +#include "net/dns/public/secure_dns_policy.h" +#include "net/socket/socket_tag.h" +#include "url/scheme_host_port.h" + +namespace net { + +HttpStreamKey::HttpStreamKey() = default; + +HttpStreamKey::HttpStreamKey(url::SchemeHostPort destination, + PrivacyMode privacy_mode, + SocketTag socket_tag, + NetworkAnonymizationKey network_anonymization_key, + SecureDnsPolicy secure_dns_policy, + bool disable_cert_network_fetches) + : destination_(std::move(destination)), + privacy_mode_(privacy_mode), + socket_tag_(std::move(socket_tag)), + network_anonymization_key_(std::move(network_anonymization_key)), + secure_dns_policy_(secure_dns_policy), + disable_cert_network_fetches_(disable_cert_network_fetches) { + CHECK(socket_tag_ == SocketTag()) << "Socket tag is not supported yet"; +} + +HttpStreamKey::~HttpStreamKey() = default; + +HttpStreamKey::HttpStreamKey(const HttpStreamKey& other) = default; + +HttpStreamKey& HttpStreamKey::operator=(const HttpStreamKey& other) = default; + +bool HttpStreamKey::operator==(const HttpStreamKey& other) const = default; + +bool HttpStreamKey::operator<(const HttpStreamKey& other) const { + return std::tie(destination_, privacy_mode_, socket_tag_, + network_anonymization_key_, secure_dns_policy_, + disable_cert_network_fetches_) < + std::tie(other.destination_, other.privacy_mode_, other.socket_tag_, + other.network_anonymization_key_, other.secure_dns_policy_, + other.disable_cert_network_fetches_); +} + +} // namespace net diff --git a/naiveproxy/src/net/http/http_stream_key.h b/naiveproxy/src/net/http/http_stream_key.h new file mode 100644 index 0000000000..6061644ca8 --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_key.h @@ -0,0 +1,65 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_HTTP_STREAM_KEY_H_ +#define NET_HTTP_HTTP_STREAM_KEY_H_ + +#include "net/base/net_export.h" +#include "net/base/network_anonymization_key.h" +#include "net/base/privacy_mode.h" +#include "net/dns/public/secure_dns_policy.h" +#include "net/socket/socket_tag.h" +#include "url/scheme_host_port.h" + +namespace net { + +// The key used to group HttpStreams that don't require proxies. +// Currently SocketTag is not supported. +// TODO(crbug.com/346835898): Support SocketTag. +class NET_EXPORT_PRIVATE HttpStreamKey { + public: + HttpStreamKey(); + HttpStreamKey(url::SchemeHostPort destination, + PrivacyMode privacy_mode, + SocketTag socket_tag, + NetworkAnonymizationKey network_anonymization_key, + SecureDnsPolicy secure_dns_policy, + bool disable_cert_network_fetches); + + ~HttpStreamKey(); + + HttpStreamKey(const HttpStreamKey& other); + HttpStreamKey& operator=(const HttpStreamKey& other); + + bool operator==(const HttpStreamKey& other) const; + bool operator<(const HttpStreamKey& other) const; + + const url::SchemeHostPort& destination() const { return destination_; } + + PrivacyMode privacy_mode() const { return privacy_mode_; } + + const SocketTag& socket_tag() const { return socket_tag_; } + + const NetworkAnonymizationKey& network_anonymization_key() const { + return network_anonymization_key_; + } + + SecureDnsPolicy secure_dns_policy() const { return secure_dns_policy_; } + + bool disable_cert_network_fetches() const { + return disable_cert_network_fetches_; + } + + private: + url::SchemeHostPort destination_; + PrivacyMode privacy_mode_ = PrivacyMode::PRIVACY_MODE_DISABLED; + SocketTag socket_tag_; + NetworkAnonymizationKey network_anonymization_key_; + SecureDnsPolicy secure_dns_policy_ = SecureDnsPolicy::kAllow; + bool disable_cert_network_fetches_ = false; +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_STREAM_KEY_H_ diff --git a/naiveproxy/src/net/http/http_stream_parser.cc b/naiveproxy/src/net/http/http_stream_parser.cc index 915d2e612b..e00e141b08 100644 --- a/naiveproxy/src/net/http/http_stream_parser.cc +++ b/naiveproxy/src/net/http/http_stream_parser.cc @@ -16,11 +16,13 @@ #include "base/check.h" #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/clamped_math.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" #include "base/values.h" #include "net/base/features.h" @@ -175,8 +177,7 @@ class HttpStreamParser::SeekableIOBuffer : public IOBufferWithSize { data_ = real_data_; } - // DanglingUntriaged because it is assigned a DanglingUntriaged pointer. - raw_ptr real_data_; + raw_ptr real_data_; const int capacity_; int size_ = 0; int used_ = 0; @@ -686,9 +687,9 @@ int HttpStreamParser::DoReadBody() { if (available) { CHECK_GT(available, 0); int64_t bytes_from_buffer = std::min(available, remaining_read_len); - memcpy(user_read_buf_->data(), - read_buf_->StartOfBuffer() + read_buf_unused_offset_, - bytes_from_buffer); + base::as_writable_bytes(user_read_buf_->span()) + .copy_prefix_from(read_buf_->everything().subspan( + read_buf_unused_offset_, bytes_from_buffer)); read_buf_unused_offset_ += bytes_from_buffer; // Clear out the remaining data if we've reached the end of the body. if (truncate_to_content_length_enabled_ && @@ -817,14 +818,14 @@ int HttpStreamParser::DoReadBodyComplete(int result) { if (save_amount) { received_bytes_ -= save_amount; - memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, - save_amount); + read_buf_->everything().copy_prefix_from( + base::as_bytes(user_read_buf_->span().subspan(result, save_amount))); } read_buf_->set_offset(save_amount); if (additional_save_amount) { - memmove(read_buf_->data(), - read_buf_->StartOfBuffer() + read_buf_unused_offset_, - additional_save_amount); + base::as_writable_bytes(read_buf_->span()) + .copy_prefix_from(read_buf_->everything().subspan( + read_buf_unused_offset_, additional_save_amount)); read_buf_->set_offset(save_amount + additional_save_amount); } read_buf_unused_offset_ = 0; @@ -958,14 +959,12 @@ int HttpStreamParser::HandleReadHeaderResult(int result) { // which is where any extra data is copied to read_buf_, so we move the // data here. if (response_body_length_ == 0) { - int extra_bytes = read_buf_->offset() - end_of_header_offset; - if (extra_bytes) { - CHECK_GT(extra_bytes, 0); - memmove(read_buf_->StartOfBuffer(), - read_buf_->StartOfBuffer() + end_of_header_offset, - extra_bytes); + base::span extra_bytes = + read_buf_->span_before_offset().subspan(end_of_header_offset); + if (!extra_bytes.empty()) { + read_buf_->everything().copy_prefix_from(extra_bytes); } - read_buf_->SetCapacity(extra_bytes); + read_buf_->SetCapacity(extra_bytes.size()); if (response_->headers->response_code() / 100 == 1) { // After processing a 1xx response, the caller will ask for the next // header, so reset state to support that. We don't completely ignore a @@ -1012,8 +1011,9 @@ int HttpStreamParser::FindAndParseResponseHeaders(int new_bytes) { // Look for the start of the status line, if it hasn't been found yet. if (response_header_start_offset_ == std::string::npos) { - response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( - read_buf_->StartOfBuffer(), read_buf_->offset()); + auto buffer = base::as_chars(read_buf_->span_before_offset()); + response_header_start_offset_ = + HttpUtil::LocateStartOfStatusLine(buffer.data(), buffer.size()); } if (response_header_start_offset_ != std::string::npos) { @@ -1027,8 +1027,9 @@ int HttpStreamParser::FindAndParseResponseHeaders(int new_bytes) { (base::ClampedNumeric(read_buf_->offset()) - new_bytes - 3) .RawValue(); size_t search_start = std::max(response_header_start_offset_, lower_bound); - end_offset = HttpUtil::LocateEndOfHeaders( - read_buf_->StartOfBuffer(), read_buf_->offset(), search_start); + auto buffer = base::as_chars(read_buf_->span_before_offset()); + end_offset = HttpUtil::LocateEndOfHeaders(buffer.data(), buffer.size(), + search_start); } else if (read_buf_->offset() >= 8) { // Enough data to decide that this is an HTTP/0.9 response. // 8 bytes = (4 bytes of junk) + "http".length() @@ -1044,14 +1045,14 @@ int HttpStreamParser::FindAndParseResponseHeaders(int new_bytes) { return end_offset; } -int HttpStreamParser::ParseResponseHeaders(int end_offset) { +int HttpStreamParser::ParseResponseHeaders(size_t end_offset) { scoped_refptr headers; DCHECK_EQ(0, read_buf_unused_offset_); if (response_header_start_offset_ != std::string::npos) { received_bytes_ += end_offset; headers = HttpResponseHeaders::TryToCreate( - std::string_view(read_buf_->StartOfBuffer(), end_offset)); + base::as_string_view(read_buf_->everything().first(end_offset))); if (!headers) return ERR_INVALID_HTTP_RESPONSE; has_seen_status_line_ = true; @@ -1077,7 +1078,7 @@ int HttpStreamParser::ParseResponseHeaders(int end_offset) { // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/qS63pYso4P0 if (read_buf_->offset() < 3 || scheme != "http" || !base::EqualsCaseInsensitiveASCII( - std::string_view(read_buf_->StartOfBuffer(), 3), "icy")) { + base::as_string_view(read_buf_->everything().first(3u)), "icy")) { return ERR_INVALID_HTTP_RESPONSE; } } diff --git a/naiveproxy/src/net/http/http_stream_parser.h b/naiveproxy/src/net/http/http_stream_parser.h index 6f5be9ed52..0e05a9dd9a 100644 --- a/naiveproxy/src/net/http/http_stream_parser.h +++ b/naiveproxy/src/net/http/http_stream_parser.h @@ -208,7 +208,7 @@ class NET_EXPORT_PRIVATE HttpStreamParser { // Parse the headers into response_. Returns OK on success or a net::Error on // failure. - int ParseResponseHeaders(int end_of_header_offset); + int ParseResponseHeaders(size_t end_of_header_offset); // Examine the parsed headers to try to determine the response body size. void CalculateResponseBodySize(); diff --git a/naiveproxy/src/net/http/http_stream_pool.cc b/naiveproxy/src/net/http/http_stream_pool.cc new file mode 100644 index 0000000000..e247f9424b --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_pool.cc @@ -0,0 +1,164 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_stream_pool.h" + +#include +#include + +#include "base/containers/flat_set.h" +#include "base/notreached.h" +#include "net/base/network_change_notifier.h" +#include "net/http/http_network_session.h" +#include "net/http/http_stream_key.h" +#include "net/http/http_stream_pool_group.h" +#include "net/socket/ssl_client_socket.h" +#include "url/gurl.h" + +namespace net { + +HttpStreamPool::HttpStreamPool(HttpNetworkSession* http_network_session, + bool cleanup_on_ip_address_change) + : http_network_session_(http_network_session), + cleanup_on_ip_address_change_(cleanup_on_ip_address_change) { + CHECK(http_network_session_); + if (cleanup_on_ip_address_change) { + NetworkChangeNotifier::AddIPAddressObserver(this); + } + + http_network_session_->ssl_client_context()->AddObserver(this); +} + +HttpStreamPool::~HttpStreamPool() { + http_network_session_->ssl_client_context()->RemoveObserver(this); + + if (cleanup_on_ip_address_change_) { + NetworkChangeNotifier::RemoveIPAddressObserver(this); + } +} + +void HttpStreamPool::IncrementTotalIdleStreamCount() { + CHECK_LT(TotalActiveStreamCount(), kMaxStreamSocketsPerPool); + ++total_idle_stream_count_; +} + +void HttpStreamPool::DecrementTotalIdleStreamCount() { + CHECK_GT(total_idle_stream_count_, 0u); + --total_idle_stream_count_; +} + +void HttpStreamPool::IncrementTotalHandedOutStreamCount() { + CHECK_LT(TotalActiveStreamCount(), kMaxStreamSocketsPerPool); + ++total_handed_out_stream_count_; +} + +void HttpStreamPool::DecrementTotalHandedOutStreamCount() { + CHECK_GT(total_handed_out_stream_count_, 0u); + --total_handed_out_stream_count_; +} + +void HttpStreamPool::IncrementTotalConnectingStreamCount() { + CHECK_LT(TotalActiveStreamCount(), kMaxStreamSocketsPerPool); + ++total_connecting_stream_count_; +} + +void HttpStreamPool::DecrementTotalConnectingStreamCount() { + CHECK_GT(total_connecting_stream_count_, 0u); + --total_connecting_stream_count_; +} + +void HttpStreamPool::OnIPAddressChanged() { + CHECK(cleanup_on_ip_address_change_); + for (const auto& group : groups_) { + group.second->Refresh(); + group.second->CancelRequests(ERR_NETWORK_CHANGED); + } +} + +void HttpStreamPool::OnSSLConfigChanged( + SSLClientContext::SSLConfigChangeType change_type) { + for (const auto& group : groups_) { + group.second->Refresh(); + } + ProcessPendingRequestsInGroups(); +} + +void HttpStreamPool::OnSSLConfigForServersChanged( + const base::flat_set& servers) { + for (const auto& group : groups_) { + if (GURL::SchemeIsCryptographic(group.first.destination().scheme()) && + servers.contains( + HostPortPair::FromSchemeHostPort(group.first.destination()))) { + group.second->Refresh(); + } + } + ProcessPendingRequestsInGroups(); +} + +void HttpStreamPool::ProcessPendingRequestsInGroups() { + // Loop until there is nothing more to do. + while (true) { + Group* group = FindHighestStalledGroup(); + if (!group) { + return; + } + + if (ReachedMaxStreamLimit()) { + if (!CloseOneIdleStreamSocket()) { + return; + } + } + + group->ProcessPendingRequest(); + } +} + +HttpStreamPool::Group& HttpStreamPool::GetOrCreateGroupForTesting( + const HttpStreamKey& stream_key) { + return GetOrCreateGroup(stream_key); +} + +HttpStreamPool::Group& HttpStreamPool::GetOrCreateGroup( + const HttpStreamKey& stream_key) { + auto it = groups_.find(stream_key); + if (it == groups_.end()) { + it = groups_.try_emplace(it, stream_key, + std::make_unique(this, stream_key)); + } + return *it->second; +} + +HttpStreamPool::Group* HttpStreamPool::FindHighestStalledGroup() { + Group* highest_stalled_group = nullptr; + std::optional highest_priority; + + for (const auto& group : groups_) { + std::optional priority = + group.second->GetPriorityIfStalledByPoolLimit(); + if (!priority) { + continue; + } + if (!highest_priority || *priority > *highest_priority) { + highest_priority = priority; + highest_stalled_group = group.second.get(); + } + } + + return highest_stalled_group; +} + +bool HttpStreamPool::CloseOneIdleStreamSocket() { + if (total_idle_stream_count_ == 0) { + return false; + } + + for (auto& group : groups_) { + if (group.second->CloseOneIdleStreamSocket()) { + return true; + } + } + NOTREACHED_NORETURN(); +} + +} // namespace net diff --git a/naiveproxy/src/net/http/http_stream_pool.h b/naiveproxy/src/net/http/http_stream_pool.h new file mode 100644 index 0000000000..7dd4beffa5 --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_pool.h @@ -0,0 +1,148 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_HTTP_STREAM_POOL_H_ +#define NET_HTTP_HTTP_STREAM_POOL_H_ + +#include +#include + +#include "base/containers/flat_set.h" +#include "base/memory/raw_ptr.h" +#include "base/time/time.h" +#include "net/base/net_export.h" +#include "net/base/network_change_notifier.h" +#include "net/socket/ssl_client_socket.h" + +namespace net { + +class HttpStreamKey; +class HttpNetworkSession; + +// Manages in-flight HTTP stream requests and maintains idle stream sockets. +// Restricts the number of streams open at a time. HttpStreams are grouped by +// HttpStreamKey. +// +// Currently only supports non-proxy streams. +class NET_EXPORT_PRIVATE HttpStreamPool + : public NetworkChangeNotifier::IPAddressObserver, + public SSLClientContext::Observer { + public: + // The maximum number of sockets per pool. The same as + // ClientSocketPoolManager::max_sockets_per_pool(). + static constexpr size_t kMaxStreamSocketsPerPool = 256; + + // The maximum number of socket per group. The same as + // ClientSocketPoolManager::max_sockets_per_group(). + static constexpr size_t kMaxStreamSocketsPerGroup = 6; + + // The time to wait between connection attempts. + static constexpr base::TimeDelta kConnectionAttemptDelay = + base::Milliseconds(250); + + class NET_EXPORT_PRIVATE Group; + class NET_EXPORT_PRIVATE Job; + + explicit HttpStreamPool(HttpNetworkSession* http_network_session, + bool cleanup_on_ip_address_change = true); + + HttpStreamPool(const HttpStreamPool&) = delete; + HttpStreamPool& operator=(const HttpStreamPool&) = delete; + + ~HttpStreamPool() override; + + // Increments/Decrements the total number of idle streams in this pool. + void IncrementTotalIdleStreamCount(); + void DecrementTotalIdleStreamCount(); + + // Increments/Decrements the total number of active streams this pool handed + // out. + void IncrementTotalHandedOutStreamCount(); + void DecrementTotalHandedOutStreamCount(); + + // Increments/Decrements the total number of connecting streams this pool. + void IncrementTotalConnectingStreamCount(); + void DecrementTotalConnectingStreamCount(); + + size_t TotalActiveStreamCount() const { + return total_handed_out_stream_count_ + total_idle_stream_count_ + + total_connecting_stream_count_; + } + + bool ReachedMaxStreamLimit() const { + return TotalActiveStreamCount() >= max_stream_sockets_per_pool(); + } + + // NetworkChangeNotifier::IPAddressObserver methods: + void OnIPAddressChanged() override; + + // SSLClientContext::Observer methods. + void OnSSLConfigChanged( + SSLClientContext::SSLConfigChangeType change_type) override; + void OnSSLConfigForServersChanged( + const base::flat_set& servers) override; + + // Checks if there are any pending requests in groups and processes them. If + // `this` reached the maximum number of streams, it will try to close idle + // streams before processing pending requests. + void ProcessPendingRequestsInGroups(); + + Group& GetOrCreateGroupForTesting(const HttpStreamKey& stream_key); + + HttpNetworkSession* http_network_session() const { + return http_network_session_; + } + + size_t max_stream_sockets_per_pool() const { + return max_stream_sockets_per_pool_; + } + + size_t max_stream_sockets_per_group() const { + return max_stream_sockets_per_group_; + } + + void set_max_stream_sockets_per_pool_for_testing( + size_t max_stream_sockets_per_pool) { + max_stream_sockets_per_pool_ = max_stream_sockets_per_pool; + } + + void set_max_stream_sockets_per_group_for_testing( + size_t max_stream_sockets_per_group) { + max_stream_sockets_per_group_ = max_stream_sockets_per_group; + } + + private: + Group& GetOrCreateGroup(const HttpStreamKey& stream_key); + + // Searches for a group that has the highest priority pending request and + // hasn't reached reach the `max_stream_socket_per_group()` limit. Returns + // nullptr if no such group is found. + Group* FindHighestStalledGroup(); + + // Closes one idle stream from an arbitrary group. Returns true if it closed a + // stream. + bool CloseOneIdleStreamSocket(); + + const raw_ptr http_network_session_; + + const bool cleanup_on_ip_address_change_; + + size_t max_stream_sockets_per_pool_ = kMaxStreamSocketsPerPool; + size_t max_stream_sockets_per_group_ = kMaxStreamSocketsPerGroup; + + // The total number of active streams this pool handed out across all groups. + size_t total_handed_out_stream_count_ = 0; + + // The total number of idle streams in this pool. + size_t total_idle_stream_count_ = 0; + + // The total number of connecting streams in this pool. + size_t total_connecting_stream_count_ = 0; + + std::map> groups_; +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_STREAM_POOL_H_ diff --git a/naiveproxy/src/net/http/http_stream_pool_group.cc b/naiveproxy/src/net/http/http_stream_pool_group.cc new file mode 100644 index 0000000000..8f46f8ecce --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_pool_group.cc @@ -0,0 +1,239 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_stream_pool_group.h" + +#include "net/http/http_basic_stream.h" +#include "net/http/http_stream.h" +#include "net/http/http_stream_key.h" +#include "net/http/http_stream_pool_job.h" +#include "net/http/http_text_based_stream_handle.h" +#include "net/socket/next_proto.h" +#include "net/socket/stream_socket.h" + +namespace net { + +namespace { + +bool IsNegotiatedProtocolTextBased(NextProto next_proto) { + return next_proto == kProtoUnknown || next_proto == kProtoHTTP11; +} + +enum class StreamSocketUsableState { + kUsable, + kRemoteSideClosed, + kDataReceivedUnexpectedly, +}; + +StreamSocketUsableState CalculateStreamSocketUsableState( + const StreamSocket& socket) { + if (socket.WasEverUsed()) { + if (socket.IsConnectedAndIdle()) { + return StreamSocketUsableState::kUsable; + } + return socket.IsConnected() + ? StreamSocketUsableState::kDataReceivedUnexpectedly + : StreamSocketUsableState::kRemoteSideClosed; + } + + return socket.IsConnected() ? StreamSocketUsableState::kUsable + : StreamSocketUsableState::kRemoteSideClosed; +} + +} // namespace + +HttpStreamPool::Group::IdleStreamSocket::IdleStreamSocket( + std::unique_ptr stream_socket, + base::TimeTicks time_became_idle) + : stream_socket(std::move(stream_socket)), + time_became_idle(time_became_idle) {} + +HttpStreamPool::Group::IdleStreamSocket::~IdleStreamSocket() = default; + +HttpStreamPool::Group::Group(HttpStreamPool* pool, HttpStreamKey stream_key) + : pool_(pool), stream_key_(std::move(stream_key)) {} + +HttpStreamPool::Group::~Group() { + // TODO(crbug.com/346835898): Ensure `pool_`'s total active stream counts + // are consistent. +} + +std::unique_ptr HttpStreamPool::Group::RequestStream( + HttpStreamRequest::Delegate* delegate, + RequestPriority priority, + const std::vector& allowed_bad_certs, + const NetLogWithSource& net_log) { + if (!in_flight_job_) { + in_flight_job_ = std::make_unique(this, net_log.net_log()); + } + + return in_flight_job_->RequestStream(delegate, priority, allowed_bad_certs, + net_log); +} + +std::unique_ptr HttpStreamPool::Group::CreateTextBasedStream( + std::unique_ptr socket) { + CHECK(IsNegotiatedProtocolTextBased(socket->GetNegotiatedProtocol())); + CHECK_LE(ActiveStreamSocketCount(), pool_->max_stream_sockets_per_group()); + + ++handed_out_stream_count_; + pool_->IncrementTotalHandedOutStreamCount(); + + auto stream_handle = std::make_unique( + this, std::move(socket), generation_); + return std::make_unique(std::move(stream_handle), + /*is_for_get_to_http_proxy=*/false); +} + +void HttpStreamPool::Group::ReleaseStreamSocket( + std::unique_ptr socket, + int64_t generation) { + CHECK(IsNegotiatedProtocolTextBased(socket->GetNegotiatedProtocol())); + CHECK_GT(handed_out_stream_count_, 0u); + --handed_out_stream_count_; + pool_->DecrementTotalHandedOutStreamCount(); + + bool can_reuse = generation == generation_ && socket->IsConnectedAndIdle(); + if (can_reuse) { + AddIdleStreamSocket(std::move(socket)); + ProcessPendingRequest(); + } else { + socket.reset(); + } + + pool_->ProcessPendingRequestsInGroups(); +} + +void HttpStreamPool::Group::AddIdleStreamSocket( + std::unique_ptr socket) { + CHECK(socket->IsConnectedAndIdle()); + CHECK(IsNegotiatedProtocolTextBased(socket->GetNegotiatedProtocol())); + CHECK_LE(ActiveStreamSocketCount(), pool_->max_stream_sockets_per_group()); + + idle_stream_sockets_.emplace_back(std::move(socket), base::TimeTicks::Now()); + pool_->IncrementTotalIdleStreamCount(); + CleanupIdleStreamSockets(CleanupMode::kTimeoutOnly); +} + +std::unique_ptr HttpStreamPool::Group::GetIdleStreamSocket() { + CleanupIdleStreamSockets(CleanupMode::kTimeoutOnly); + + if (idle_stream_sockets_.empty()) { + return nullptr; + } + + // Iterate through the idle streams from oldtest to newest and try to find a + // used idle stream. Prefer the newest used idle stream. + auto idle_it = idle_stream_sockets_.end(); + for (auto it = idle_stream_sockets_.begin(); + it != idle_stream_sockets_.end();) { + CHECK_EQ(CalculateStreamSocketUsableState(*it->stream_socket), + StreamSocketUsableState::kUsable); + if (it->stream_socket->WasEverUsed()) { + idle_it = it; + } + ++it; + } + + if (idle_it == idle_stream_sockets_.end()) { + // There are no used idle streams. Pick the oldest (first) idle streams + // (FIFO). + idle_it = idle_stream_sockets_.begin(); + } + + CHECK(idle_it != idle_stream_sockets_.end()); + + std::unique_ptr stream_socket = + std::move(idle_it->stream_socket); + idle_stream_sockets_.erase(idle_it); + pool_->DecrementTotalIdleStreamCount(); + + return stream_socket; +} + +void HttpStreamPool::Group::ProcessPendingRequest() { + if (!in_flight_job_) { + return; + } + in_flight_job_->ProcessPendingRequest(); +} + +bool HttpStreamPool::Group::CloseOneIdleStreamSocket() { + if (idle_stream_sockets_.empty()) { + return false; + } + + idle_stream_sockets_.pop_front(); + pool_->DecrementTotalIdleStreamCount(); + return true; +} + +size_t HttpStreamPool::Group::ActiveStreamSocketCount() const { + return handed_out_stream_count_ + idle_stream_sockets_.size() + + (in_flight_job_ ? in_flight_job_->InFlightAttemptCount() : 0); +} + +bool HttpStreamPool::Group::ReachedMaxStreamLimit() const { + return ActiveStreamSocketCount() >= pool_->max_stream_sockets_per_group(); +} + +std::optional +HttpStreamPool::Group::GetPriorityIfStalledByPoolLimit() const { + if (ReachedMaxStreamLimit()) { + return std::nullopt; + } + + if (!in_flight_job_ || in_flight_job_->PendingRequestCount() == 0) { + return std::nullopt; + } + + return in_flight_job_->GetPriority(); +} + +void HttpStreamPool::Group::Refresh() { + ++generation_; + CleanupIdleStreamSockets(CleanupMode::kForce); + if (in_flight_job_) { + in_flight_job_->CancelInFlightAttempts(); + } +} + +void HttpStreamPool::Group::CancelRequests(int error) { + if (in_flight_job_) { + in_flight_job_->CancelRequests(error); + } +} + +void HttpStreamPool::Group::CleanupTimedoutIdleStreamSocketsForTesting() { + CleanupIdleStreamSockets(CleanupMode::kTimeoutOnly); +} + +void HttpStreamPool::Group::CleanupIdleStreamSockets(CleanupMode mode) { + const base::TimeTicks now = base::TimeTicks::Now(); + + // Iterate though the idle sockets to delete any disconnected ones. + for (auto it = idle_stream_sockets_.begin(); + it != idle_stream_sockets_.end();) { + bool should_delete = mode == CleanupMode::kForce; + base::TimeDelta timeout = it->stream_socket->WasEverUsed() + ? kUsedIdleStreamSocketTimeout + : kUnusedIdleStreamSocketTimeout; + StreamSocketUsableState state = + CalculateStreamSocketUsableState(*it->stream_socket); + if (state != StreamSocketUsableState::kUsable) { + should_delete = true; + } else if (now - it->time_became_idle >= timeout) { + should_delete = true; + } + + if (should_delete) { + it = idle_stream_sockets_.erase(it); + pool_->DecrementTotalIdleStreamCount(); + } else { + ++it; + } + } +} + +} // namespace net diff --git a/naiveproxy/src/net/http/http_stream_pool_group.h b/naiveproxy/src/net/http/http_stream_pool_group.h new file mode 100644 index 0000000000..4e1d7b1630 --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_pool_group.h @@ -0,0 +1,144 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_HTTP_STREAM_POOL_GROUP_H_ +#define NET_HTTP_HTTP_STREAM_POOL_GROUP_H_ + +#include +#include +#include + +#include "base/memory/raw_ptr.h" +#include "base/time/time.h" +#include "net/base/net_export.h" +#include "net/http/http_stream_key.h" +#include "net/http/http_stream_pool.h" +#include "net/http/http_stream_request.h" + +namespace net { + +class HttpStream; +class StreamSocket; + +// Maintains active/idle text-based HTTP streams. +class HttpStreamPool::Group { + public: + // The same timeout as ClientSocketPool::used_idle_socket_timeout(). + static constexpr base::TimeDelta kUsedIdleStreamSocketTimeout = + base::Seconds(300); + + // The same timeout as + // ClientSocketPoolManager::unused_idle_socket_timeout(). + static constexpr base::TimeDelta kUnusedIdleStreamSocketTimeout = + base::Seconds(60); + + Group(HttpStreamPool* pool, HttpStreamKey stream_key); + + Group(const Group&) = delete; + Group& operator=(const Group&) = delete; + + ~Group(); + + const HttpStreamKey& stream_key() const { return stream_key_; } + + HttpStreamPool* pool() { return pool_; } + const HttpStreamPool* pool() const { return pool_; } + + HttpNetworkSession* http_network_session() const { + return pool_->http_network_session(); + } + + // Creates an HttpStreamRequest. Will call delegate's methods. See the + // comments of HttpStreamRequest::Delegate methods for details. + // TODO(crbug.com/346835898): Support TLS, HTTP/2 and QUIC. + std::unique_ptr RequestStream( + HttpStreamRequest::Delegate* delegate, + RequestPriority priority, + const std::vector& allowed_bad_certs, + const NetLogWithSource& net_log); + + // Creates a text-based HttpStream from `socket`. Call sites must ensure that + // the number of active streams do not exceed the global/per-group limits. + // `socket` must not be negotiated to use HTTP/2. + std::unique_ptr CreateTextBasedStream( + std::unique_ptr socket); + + // Releases a StreamSocket that was used to create a text-based HttpStream. + void ReleaseStreamSocket(std::unique_ptr socket, + int64_t generation); + + // Adds `socket` as an idle StreamSocket for text-based HttpStream. Call sites + // must ensure that the number of idle streams do not exceed the global/per- + // group limits. + // `socket` must not be negotiated to use HTTP/2. + void AddIdleStreamSocket(std::unique_ptr socket); + + // Retrieves an existing idle StreamSocket. Returns nullptr when there is no + // idle stream. + std::unique_ptr GetIdleStreamSocket(); + + // Tries to process a pending request. + void ProcessPendingRequest(); + + // Closes one idle stream socket. Returns true if it closed a stream. + bool CloseOneIdleStreamSocket(); + + // Returns the number of idle streams. + size_t IdleStreamSocketCount() const { return idle_stream_sockets_.size(); } + + // Returns the number of active streams. + size_t ActiveStreamSocketCount() const; + + bool ReachedMaxStreamLimit() const; + + // Returns the highest pending request priority if the group is stalled due to + // the per-pool limit, not the per-group limit. + std::optional GetPriorityIfStalledByPoolLimit() const; + + // Increments the generation of this group. Closes idle streams. Streams + // handed out before this increment won't be reused. Cancels in-flight + // connection attempts. + void Refresh(); + + // Cancels all on-going requests. + void CancelRequests(int error); + + void CleanupTimedoutIdleStreamSocketsForTesting(); + + Job* GetJobForTesting() const { return in_flight_job_.get(); } + + private: + struct IdleStreamSocket { + IdleStreamSocket(std::unique_ptr stream_socket, + base::TimeTicks start_time); + ~IdleStreamSocket(); + + IdleStreamSocket(const IdleStreamSocket&) = delete; + IdleStreamSocket& operator=(const IdleStreamSocket&) = delete; + + std::unique_ptr stream_socket; + base::TimeTicks time_became_idle; + }; + + enum class CleanupMode { + // Clean up only timed out idle streams. + kTimeoutOnly, + // Clean up all idle streams. + kForce, + }; + void CleanupIdleStreamSockets(CleanupMode mode); + + const raw_ptr pool_; + const HttpStreamKey stream_key_; + + size_t handed_out_stream_count_ = 0; + int64_t generation_ = 0; + std::list idle_stream_sockets_; + + std::unique_ptr in_flight_job_; +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_STREAM_POOL_GROUP_H_ diff --git a/naiveproxy/src/net/http/http_stream_pool_job.cc b/naiveproxy/src/net/http/http_stream_pool_job.cc new file mode 100644 index 0000000000..b1099f8957 --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_pool_job.cc @@ -0,0 +1,633 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_stream_pool_job.h" + +#include +#include + +#include "base/containers/contains.h" +#include "base/functional/bind.h" +#include "base/task/sequenced_task_runner.h" +#include "base/timer/timer.h" +#include "net/base/completion_once_callback.h" +#include "net/base/host_port_pair.h" +#include "net/base/load_states.h" +#include "net/base/net_errors.h" +#include "net/dns/host_resolver.h" +#include "net/http/http_network_session.h" +#include "net/http/http_stream_key.h" +#include "net/http/http_stream_pool_group.h" +#include "net/log/net_log_with_source.h" +#include "net/socket/stream_attempt.h" +#include "net/socket/tcp_stream_attempt.h" +#include "net/socket/tls_stream_attempt.h" +#include "net/ssl/ssl_cert_request_info.h" + +namespace net { + +HttpStreamPool::Job::RequestEntry::RequestEntry(Job* job) : job_(job) { + CHECK(job_); +} + +std::unique_ptr +HttpStreamPool::Job::RequestEntry::CreateRequest( + HttpStreamRequest::Delegate* delegate, + const NetLogWithSource& net_log) { + CHECK(!delegate_); + CHECK(delegate); + + delegate_ = delegate; + + auto request = std::make_unique( + this, /*websocket_handshake_stream_create_helper=*/nullptr, net_log, + HttpStreamRequest::HTTP_STREAM); + + request_ = request.get(); + return request; +} + +LoadState HttpStreamPool::Job::RequestEntry::GetLoadState() const { + return job_->GetLoadState(); +} + +void HttpStreamPool::Job::RequestEntry::OnRequestComplete() { + CHECK(request_); + CHECK(delegate_); + request_ = nullptr; + delegate_ = nullptr; + job_->OnRequestComplete(this); + // `this` is deleted. +} + +int HttpStreamPool::Job::RequestEntry::RestartTunnelWithProxyAuth() { + NOTREACHED_NORETURN(); +} + +void HttpStreamPool::Job::RequestEntry::SetPriority(RequestPriority priority) { + CHECK(request_); + job_->SetRequestPriority(request_, priority); +} + +HttpStreamPool::Job::RequestEntry::~RequestEntry() = default; + +// Represents an in-flight stream attempt. +struct HttpStreamPool::Job::InFlightAttempt { + explicit InFlightAttempt(std::unique_ptr attempt) + : attempt(std::move(attempt)) {} + + InFlightAttempt(const InFlightAttempt&) = delete; + InFlightAttempt& operator=(const InFlightAttempt&) = delete; + + ~InFlightAttempt() = default; + + std::unique_ptr attempt; + // Timer to start a next attempt. When fired, `this` is treated as a slow + // attempt but `this` is not timed out yet. + base::OneShotTimer slow_timer; + bool is_slow = false; +}; + +HttpStreamPool::Job::Job(Group* group, NetLog* net_log) + : group_(group), + net_log_(NetLogWithSource::Make(net_log, + NetLogSourceType::HTTP_STREAM_POOL_JOB)), + requests_(NUM_PRIORITIES), + attempt_params_( + StreamAttemptParams::FromHttpNetworkSession(http_network_session())) { + proxy_info_.UseDirect(); + CHECK(group_); +} + +HttpStreamPool::Job::~Job() = default; + +std::unique_ptr HttpStreamPool::Job::RequestStream( + HttpStreamRequest::Delegate* delegate, + RequestPriority priority, + const std::vector& allowed_bad_certs, + const NetLogWithSource& net_log) { + // TODO(crbug.com/346835898): Handle requests that are coming while `this` is + // failing. + CHECK(!is_failing_); + + auto entry = std::make_unique(this); + std::unique_ptr request = + entry->CreateRequest(delegate, net_log); + requests_.Insert(std::move(entry), priority); + MaybeChangeServiceEndpointRequestPriority(); + + // Check idle streams first. If found, notify the request that an HttpStream + // is ready. Use PostTask() since `delegate` doesn't expect the request + // finishes synchronously. + std::unique_ptr stream_socket = group_->GetIdleStreamSocket(); + if (stream_socket) { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(&Job::CreateTextBasedStreamAndNotify, + base::Unretained(this), std::move(stream_socket))); + return request; + } + + allowed_bad_certs_ = allowed_bad_certs; + + if (service_endpoint_request_ || service_endpoint_request_finished_) { + MaybeAttemptConnection(); + } else { + ResolveServiceEndpoint(priority); + } + + return request; +} + +void HttpStreamPool::Job::OnServiceEndpointsUpdated() { + ProcessServiceEndpoindChanges(); +} + +void HttpStreamPool::Job::OnServiceEndpointRequestFinished(int rv) { + CHECK(!service_endpoint_request_finished_); + CHECK(service_endpoint_request_); + service_endpoint_request_finished_ = true; + resolve_error_info_ = service_endpoint_request_->GetResolveErrorInfo(); + + if (rv != OK) { + error_to_notify_ = rv; + NotifyFailure(); + return; + } + + CHECK(!service_endpoint_request_->GetEndpointResults().empty()); + ProcessServiceEndpoindChanges(); +} + +int HttpStreamPool::Job::WaitForSSLConfigReady( + CompletionOnceCallback callback) { + if (ssl_config_.has_value()) { + return OK; + } + + ssl_config_waiting_callbacks_.emplace_back(std::move(callback)); + return ERR_IO_PENDING; +} + +SSLConfig HttpStreamPool::Job::GetSSLConfig() { + CHECK(ssl_config_.has_value()); + return *ssl_config_; +} + +void HttpStreamPool::Job::ProcessPendingRequest() { + if (PendingRequestCount() == 0) { + return; + } + + std::unique_ptr stream_socket = group_->GetIdleStreamSocket(); + if (stream_socket) { + CreateTextBasedStreamAndNotify(std::move(stream_socket)); + return; + } + + MaybeAttemptConnection(/*max_attempts=*/1); +} + +void HttpStreamPool::Job::CancelInFlightAttempts() { + in_flight_attempts_.clear(); + slow_attempt_count_ = 0; +} + +void HttpStreamPool::Job::CancelRequests(int error) { + error_to_notify_ = error; + is_canceling_requests_ = true; + NotifyFailure(); +} + +size_t HttpStreamPool::Job::PendingRequestCount() const { + CHECK_GE(in_flight_attempts_.size(), slow_attempt_count_); + size_t non_slow_attempts = in_flight_attempts_.size() - slow_attempt_count_; + // The number of in-flight, non-slow attempts could be larger than the number + // of requests (e.g. a request was cancelled in the middle of an attempt). + if (requests_.size() <= non_slow_attempts) { + return 0; + } + + return requests_.size() - non_slow_attempts; +} + +const HttpStreamKey& HttpStreamPool::Job::stream_key() const { + return group_->stream_key(); +} + +HttpNetworkSession* HttpStreamPool::Job::http_network_session() { + return group_->http_network_session(); +} + +HttpStreamPool* HttpStreamPool::Job::pool() { + return group_->pool(); +} + +const HttpStreamPool* HttpStreamPool::Job::pool() const { + return group_->pool(); +} + +bool HttpStreamPool::Job::UsingTls() const { + return GURL::SchemeIsCryptographic(stream_key().destination().scheme()); +} + +LoadState HttpStreamPool::Job::GetLoadState() const { + if (service_endpoint_request_ && !service_endpoint_request_finished_) { + return LOAD_STATE_RESOLVING_HOST; + } + + // TODO(crbug.com/346835898): Add more load state as we implement this class. + return LOAD_STATE_IDLE; +} + +RequestPriority HttpStreamPool::Job::GetPriority() const { + CHECK(!requests_.empty()); + return static_cast(requests_.FirstMax().priority()); +} + +void HttpStreamPool::Job::ResolveServiceEndpoint( + RequestPriority initial_priority) { + HostResolver::ResolveHostParameters parameters; + parameters.initial_priority = initial_priority; + parameters.secure_dns_policy = stream_key().secure_dns_policy(); + service_endpoint_request_ = + http_network_session()->host_resolver()->CreateServiceEndpointRequest( + HostResolver::Host(stream_key().destination()), + stream_key().network_anonymization_key(), net_log_, + std::move(parameters)); + int rv = service_endpoint_request_->Start(this); + if (rv != ERR_IO_PENDING) { + OnServiceEndpointRequestFinished(rv); + } +} + +void HttpStreamPool::Job::MaybeChangeServiceEndpointRequestPriority() { + if (service_endpoint_request_ && !service_endpoint_request_finished_) { + service_endpoint_request_->ChangeRequestPriority(GetPriority()); + } +} + +void HttpStreamPool::Job::ProcessServiceEndpoindChanges() { + MaybeCalculateSSLConfig(); + MaybeAttemptConnection(); +} + +void HttpStreamPool::Job::MaybeCalculateSSLConfig() { + if (!UsingTls() || ssl_config_.has_value()) { + return; + } + + CHECK(service_endpoint_request_); + if (!service_endpoint_request_->EndpointsCryptoReady()) { + return; + } + + SSLConfig ssl_config; + + ssl_config.allowed_bad_certs = allowed_bad_certs_; + ssl_config.privacy_mode = stream_key().privacy_mode(); + ssl_config.disable_cert_verification_network_fetches = + stream_key().disable_cert_network_fetches(); + ssl_config.early_data_enabled = + http_network_session()->params().enable_early_data; + + ssl_config.alpn_protos = http_network_session()->GetAlpnProtos(); + ssl_config.application_settings = + http_network_session()->GetApplicationSettings(); + http_network_session()->http_server_properties()->MaybeForceHTTP11( + stream_key().destination(), stream_key().network_anonymization_key(), + &ssl_config); + + ssl_config.ignore_certificate_errors = + http_network_session()->params().ignore_certificate_errors; + ssl_config.network_anonymization_key = + stream_key().network_anonymization_key(); + + // TODO(crbug.com/346835898): Support ECH. + + ssl_config_.emplace(std::move(ssl_config)); + + for (auto& callback : ssl_config_waiting_callbacks_) { + std::move(callback).Run(OK); + } + ssl_config_waiting_callbacks_.clear(); +} + +void HttpStreamPool::Job::MaybeAttemptConnection( + std::optional max_attempts) { + CHECK_EQ(group_->IdleStreamSocketCount(), 0u); + + if (PendingRequestCount() == 0) { + // There are no requests waiting for streams. + return; + } + + // TODO(crbug.com/346835898): Ensure that we don't attempt connections when + // failing. + CHECK(!is_failing_); + + std::optional ip_endpoint = GetIPEndPointToAttempt(); + if (!ip_endpoint.has_value()) { + if (service_endpoint_request_finished_ && in_flight_attempts_.empty()) { + // Tried all endpoints. + NotifyFailure(); + } + return; + } + + // There might be multiple pending requests. Make attempts as much as needed + // and allowed. + size_t num_attempts = 0; + while (PendingRequestCount() > 0 && !group_->ReachedMaxStreamLimit()) { + // If we can't attempt connection due to the pool's limit, try to close an + // idle stream in the pool. + if (pool()->ReachedMaxStreamLimit()) { + if (!pool()->CloseOneIdleStreamSocket()) { + break; + } + } + + std::unique_ptr attempt; + if (UsingTls()) { + attempt = std::make_unique( + &attempt_params_, *ip_endpoint, + HostPortPair::FromSchemeHostPort(stream_key().destination()), + /*ssl_config_provider=*/this); + } else { + attempt = std::make_unique(&attempt_params_, + *ip_endpoint, &net_log_); + } + + auto in_flight_attempt = + std::make_unique(std::move(attempt)); + InFlightAttempt* raw_attempt = in_flight_attempt.get(); + in_flight_attempts_.emplace(std::move(in_flight_attempt)); + pool()->IncrementTotalConnectingStreamCount(); + + int rv = raw_attempt->attempt->Start(base::BindOnce( + &Job::OnInFlightAttemptComplete, base::Unretained(this), raw_attempt)); + if (rv != ERR_IO_PENDING) { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&Job::OnInFlightAttemptComplete, + base::Unretained(this), raw_attempt, rv)); + } else { + raw_attempt->slow_timer.Start( + FROM_HERE, kConnectionAttemptDelay, + base::BindOnce(&Job::OnInFlightAttemptSlow, base::Unretained(this), + raw_attempt)); + } + + ++num_attempts; + if (max_attempts.has_value() && num_attempts >= *max_attempts) { + break; + } + } +} + +std::optional HttpStreamPool::Job::GetIPEndPointToAttempt() { + CHECK(service_endpoint_request_); + if (service_endpoint_request_->GetEndpointResults().empty()) { + return std::nullopt; + } + + // Look for an IPEndPoint from the preferred address family first. + for (auto& endpoint : service_endpoint_request_->GetEndpointResults()) { + std::optional ip_endpoint = + prefer_ipv6_ ? FindUnattemptedIPEndPoint(endpoint.ipv6_endpoints) + : FindUnattemptedIPEndPoint(endpoint.ipv4_endpoints); + if (ip_endpoint.has_value()) { + return ip_endpoint; + } + } + + // If there is no IPEndPoint from the preferred address family, check the + // another address family. + for (auto& endpoint : service_endpoint_request_->GetEndpointResults()) { + std::optional ip_endpoint = + prefer_ipv6_ ? FindUnattemptedIPEndPoint(endpoint.ipv4_endpoints) + : FindUnattemptedIPEndPoint(endpoint.ipv6_endpoints); + if (ip_endpoint.has_value()) { + return ip_endpoint; + } + } + + return std::nullopt; +} + +std::optional HttpStreamPool::Job::FindUnattemptedIPEndPoint( + const std::vector& ip_endpoints) { + for (const auto& ip_endpoint : ip_endpoints) { + if (base::Contains(failed_ip_endpoints_, ip_endpoint)) { + continue; + } + if (base::Contains(slow_ip_endpoints_, ip_endpoint)) { + continue; + } + return ip_endpoint; + } + return std::nullopt; +} + +HttpStreamPool::Job::FailureKind HttpStreamPool::Job::DetermineFailureKind() { + if (is_canceling_requests_) { + return FailureKind::kStreamFailed; + } + + if (IsCertificateError(error_to_notify_)) { + return FailureKind::kCertifcateError; + } + + if (error_to_notify_ == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { + return FailureKind::kNeedsClientAuth; + } + + return FailureKind::kStreamFailed; +} + +void HttpStreamPool::Job::NotifyFailure() { + is_failing_ = true; + + RequestEntry* entry = ExtractFirstRequestToNotify(); + if (!entry) { + // TODO(crbug.com/346835898): Ensure that MaybeComplete() is called + // eventually. + return; + } + + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(&Job::NotifyFailure, weak_ptr_factory_.GetWeakPtr())); + + FailureKind kind = DetermineFailureKind(); + switch (kind) { + case FailureKind::kStreamFailed: + entry->delegate()->OnStreamFailed(error_to_notify_, net_error_details_, + proxy_info_, resolve_error_info_); + break; + case FailureKind::kCertifcateError: + CHECK(cert_error_ssl_info_.has_value()); + entry->delegate()->OnCertificateError(error_to_notify_, + *cert_error_ssl_info_); + break; + case FailureKind::kNeedsClientAuth: + CHECK(client_auth_cert_info_.get()); + entry->delegate()->OnNeedsClientAuth(client_auth_cert_info_.get()); + break; + } + // `this` may be deleted. +} + +void HttpStreamPool::Job::CreateTextBasedStreamAndNotify( + std::unique_ptr stream_socket) { + NextProto negotiated_protocol = stream_socket->GetNegotiatedProtocol(); + CHECK_NE(negotiated_protocol, NextProto::kProtoHTTP2); + + std::unique_ptr http_stream = + group_->CreateTextBasedStream(std::move(stream_socket)); + + RequestEntry* entry = ExtractFirstRequestToNotify(); + if (!entry) { + // The ownership of the stream will be moved to the group as `http_stream` + // is going to be destructed. + return; + } + + entry->request()->Complete(negotiated_protocol, + ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON); + entry->delegate()->OnStreamReady(proxy_info_, std::move(http_stream)); +} + +HttpStreamPool::Job::RequestEntry* +HttpStreamPool::Job::ExtractFirstRequestToNotify() { + if (requests_.empty()) { + return nullptr; + } + + std::unique_ptr entry = requests_.Erase(requests_.FirstMax()); + RequestEntry* raw_entry = entry.get(); + notified_requests_.emplace(std::move(entry)); + return raw_entry; +} + +void HttpStreamPool::Job::SetRequestPriority(HttpStreamRequest* request, + RequestPriority priority) { + for (RequestQueue::Pointer pointer = requests_.FirstMax(); !pointer.is_null(); + pointer = requests_.GetNextTowardsLastMin(pointer)) { + if (pointer.value()->request() == request) { + if (pointer.priority() == priority) { + break; + } + + std::unique_ptr entry = requests_.Erase(pointer); + requests_.Insert(std::move(entry), priority); + break; + } + } + + MaybeChangeServiceEndpointRequestPriority(); +} + +void HttpStreamPool::Job::OnRequestComplete(RequestEntry* entry) { + auto notified_it = notified_requests_.find(entry); + if (notified_it != notified_requests_.end()) { + notified_requests_.erase(notified_it); + } else { + for (RequestQueue::Pointer pointer = requests_.FirstMax(); + !pointer.is_null(); + pointer = requests_.GetNextTowardsLastMin(pointer)) { + if (pointer.value()->request() == entry->request()) { + requests_.Erase(pointer); + break; + } + } + } + MaybeComplete(); +} + +void HttpStreamPool::Job::OnInFlightAttemptComplete( + InFlightAttempt* raw_attempt, + int rv) { + raw_attempt->slow_timer.Stop(); + if (raw_attempt->is_slow) { + CHECK_GT(slow_attempt_count_, 0u); + --slow_attempt_count_; + } + + auto it = in_flight_attempts_.find(raw_attempt); + CHECK(it != in_flight_attempts_.end()); + std::unique_ptr in_flight_attempt = + std::move(in_flight_attempts_.extract(it).value()); + pool()->DecrementTotalConnectingStreamCount(); + + if (rv != OK) { + HandleAttemptFailure(std::move(in_flight_attempt), rv); + return; + } + + // TODO(crbug.com/346835898): Support preconnect. + + // TODO(crbug.com/346835898): Support HTTP/2. + std::unique_ptr stream_socket = + in_flight_attempt->attempt->ReleaseStreamSocket(); + CHECK(stream_socket); + CHECK_NE(stream_socket->GetNegotiatedProtocol(), NextProto::kProtoHTTP2); + CreateTextBasedStreamAndNotify(std::move(stream_socket)); +} + +void HttpStreamPool::Job::OnInFlightAttemptSlow(InFlightAttempt* raw_attempt) { + auto it = in_flight_attempts_.find(raw_attempt); + CHECK(it != in_flight_attempts_.end()); + + raw_attempt->is_slow = true; + ++slow_attempt_count_; + slow_ip_endpoints_.emplace(raw_attempt->attempt->ip_endpoint()); + prefer_ipv6_ = !raw_attempt->attempt->ip_endpoint().address().IsIPv6(); + + MaybeAttemptConnection(); +} + +void HttpStreamPool::Job::HandleAttemptFailure( + std::unique_ptr in_flight_attempt, + int rv) { + CHECK_NE(rv, ERR_IO_PENDING); + failed_ip_endpoints_.emplace(in_flight_attempt->attempt->ip_endpoint()); + + if (is_failing_) { + // `this` has already failed and is notifying requests to the failure. + return; + } + + error_to_notify_ = rv; + + if (rv == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { + CHECK(UsingTls()); + client_auth_cert_info_ = in_flight_attempt->attempt->GetCertRequestInfo(); + in_flight_attempt.reset(); + NotifyFailure(); + return; + } + + if (IsCertificateError(rv)) { + // When a certificate error happened for an attempt, notifies all requests + // of the error. + CHECK(UsingTls()); + CHECK(in_flight_attempt->attempt->stream_socket()); + SSLInfo ssl_info; + bool has_ssl_info = + in_flight_attempt->attempt->stream_socket()->GetSSLInfo(&ssl_info); + CHECK(has_ssl_info); + cert_error_ssl_info_ = ssl_info; + in_flight_attempt.reset(); + NotifyFailure(); + } else { + in_flight_attempt.reset(); + MaybeAttemptConnection(); + } +} + +void HttpStreamPool::Job::MaybeComplete() { + // TODO(crbug.com/346835898): Complete `this` when there is no request. +} + +} // namespace net diff --git a/naiveproxy/src/net/http/http_stream_pool_job.h b/naiveproxy/src/net/http/http_stream_pool_job.h new file mode 100644 index 0000000000..76da8efe42 --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_pool_job.h @@ -0,0 +1,267 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_HTTP_STREAM_POOL_JOB_H_ +#define NET_HTTP_HTTP_STREAM_POOL_JOB_H_ + +#include +#include +#include +#include + +#include "base/containers/unique_ptr_adapters.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "net/base/load_states.h" +#include "net/base/net_error_details.h" +#include "net/base/priority_queue.h" +#include "net/base/request_priority.h" +#include "net/dns/host_resolver.h" +#include "net/dns/public/resolve_error_info.h" +#include "net/http/http_stream_pool.h" +#include "net/http/http_stream_request.h" +#include "net/log/net_log_with_source.h" +#include "net/socket/stream_attempt.h" +#include "net/socket/tls_stream_attempt.h" +#include "net/ssl/ssl_cert_request_info.h" +#include "url/gurl.h" + +namespace net { + +class HttpNetworkSession; +class NetLog; +class HttpStreamKey; + +// Maintains in-flight HTTP stream requests. Peforms DNS resolution. +class HttpStreamPool::Job + : public HostResolver::ServiceEndpointRequest::Delegate, + public TlsStreamAttempt::SSLConfigProvider { + public: + // `group` must outlive `this`. + Job(Group* group, NetLog* net_log); + + Job(const Job&) = delete; + Job& operator=(const Job&) = delete; + + ~Job() override; + + // Creates an HttpStreamRequest. Will call delegate's methods. See the + // comments of HttpStreamRequest::Delegate methods for details. + // TODO(crbug.com/346835898): Support TLS, HTTP/2 and QUIC. + std::unique_ptr RequestStream( + HttpStreamRequest::Delegate* delegate, + RequestPriority priority, + const std::vector& allowed_bad_certs, + const NetLogWithSource& net_log); + + // HostResolver::ServiceEndpointRequest::Delegate implementation: + void OnServiceEndpointsUpdated() override; + void OnServiceEndpointRequestFinished(int rv) override; + + // TlsStreamAttempt::SSLConfigProvider implementation: + int WaitForSSLConfigReady(CompletionOnceCallback callback) override; + SSLConfig GetSSLConfig() override; + + // Tries to process a pending request. + void ProcessPendingRequest(); + + // Returns the number of total requests in this job. + size_t RequestCount() const { return requests_.size(); } + + // Returns the number of in-flight attempts. + size_t InFlightAttemptCount() const { return in_flight_attempts_.size(); } + + // Cancels all in-flight attempts. + void CancelInFlightAttempts(); + + // Cancels all requests. + void CancelRequests(int error); + + // Returns the number of pending requests. The number is calculated by + // subtracting the number of in-flight attempts (excluding slow attempts) from + // the number of total requests. + size_t PendingRequestCount() const; + + // Returns the highest priority in `requests_`. + RequestPriority GetPriority() const; + + private: + // Represents failure of connection attempts. Used to call request's delegate + // methods. + enum class FailureKind { + kStreamFailed, + kCertifcateError, + kNeedsClientAuth, + }; + + // A peer of an HttpStreamRequest. Holds the HttpStreamRequest's delegate + // pointer and implements HttpStreamRequest::Helper. + class RequestEntry : public HttpStreamRequest::Helper { + public: + explicit RequestEntry(Job* job); + + RequestEntry(RequestEntry&) = delete; + RequestEntry& operator=(const RequestEntry&) = delete; + + ~RequestEntry() override; + + std::unique_ptr CreateRequest( + HttpStreamRequest::Delegate* delegate, + const NetLogWithSource& net_log); + + HttpStreamRequest* request() const { return request_; } + + HttpStreamRequest::Delegate* delegate() const { return delegate_; } + + // HttpStreamRequest::Helper methods: + LoadState GetLoadState() const override; + void OnRequestComplete() override; + int RestartTunnelWithProxyAuth() override; + void SetPriority(RequestPriority priority) override; + + private: + const raw_ptr job_; + raw_ptr request_; + raw_ptr delegate_; + }; + + using RequestQueue = PriorityQueue>; + + struct InFlightAttempt; + + const HttpStreamKey& stream_key() const; + + HttpNetworkSession* http_network_session(); + + HttpStreamPool* pool(); + const HttpStreamPool* pool() const; + + bool UsingTls() const; + + // Returns the current load state. + LoadState GetLoadState() const; + + void ResolveServiceEndpoint(RequestPriority initial_priority); + + void MaybeChangeServiceEndpointRequestPriority(); + + // Called when service endpoint results have changed or finished. + void ProcessServiceEndpoindChanges(); + + // Calculate SSLConfig if it's not calculated yet and `this` has received + // enough information to calculate it. + void MaybeCalculateSSLConfig(); + + // Attempts connections if there are pending requests and IPEndPoints that + // haven't failed. If `max_attempts` is given, attempts connections up to + // `max_attempts`. + void MaybeAttemptConnection( + std::optional max_attempts = std::nullopt); + + std::optional GetIPEndPointToAttempt(); + std::optional FindUnattemptedIPEndPoint( + const std::vector& ip_endpoints); + + // Calculate the failure kind to notify requests of failure. Used to call + // one of the delegate's methods. + FailureKind DetermineFailureKind(); + + // Notifies a failure to all requests. + void NotifyFailure(); + + // Creates a text based stream and notifies the highest priority request. + void CreateTextBasedStreamAndNotify( + std::unique_ptr stream_socket); + + // Extracts an entry from `requests_` of which priority is highest. The + // ownership of the entry is moved to `notified_requests_`. + RequestEntry* ExtractFirstRequestToNotify(); + + // Called when the priority of `request` is set. + void SetRequestPriority(HttpStreamRequest* request, RequestPriority priority); + + // Called when an HttpStreamRequest associated with `entry` is going to + // be destroyed. + void OnRequestComplete(RequestEntry* entry); + + void OnInFlightAttemptComplete(InFlightAttempt* raw_attempt, int rv); + void OnInFlightAttemptSlow(InFlightAttempt* raw_attempt); + + void HandleAttemptFailure(std::unique_ptr in_flight_attempt, + int rv); + + void MaybeComplete(); + + const raw_ptr group_; + const NetLogWithSource net_log_; + + ProxyInfo proxy_info_; + + // Holds requests that are waiting for notifications (a delegate method call + // to indicate success or failure). + RequestQueue requests_; + // Holds requests that are already notified results. We need to keep them + // to avoid dangling pointers. + std::set, base::UniquePtrComparator> + notified_requests_; + + std::unique_ptr + service_endpoint_request_; + bool service_endpoint_request_finished_ = false; + + // Set to true when `this` cannot handle further requests. Used to ensure that + // `this` doesn't accept further requests while notifying the failure to the + // existing requests. + bool is_failing_ = false; + + // Set to true when `CancelRequests()` is called. + bool is_canceling_requests_ = false; + + NetErrorDetails net_error_details_; + ResolveErrorInfo resolve_error_info_; + + // Set to an error from the latest stream attempt failure or network change + // events. Used to notify delegates when all attempts failed. + int error_to_notify_ = ERR_FAILED; + + // Set to a SSLInfo when an attempt has failed with a certificate error. Used + // to notify requests. + std::optional cert_error_ssl_info_; + + // Set to a SSLCertRequestInfo when an attempt has requested a client cert. + // Used to notify requests. + scoped_refptr client_auth_cert_info_; + + // Allowed bad certificates from the newest request. + std::vector allowed_bad_certs_; + // SSLConfig for all TLS connection attempts. Calculated after the service + // endpoint request is ready to proceed cryptographic handshakes. + // TODO(crbug.com/40812426): We need to have separate SSLConfigs when we + // support multiple HTTPS RR that have different service endpoints. + std::optional ssl_config_; + std::vector ssl_config_waiting_callbacks_; + + StreamAttemptParams attempt_params_; + std::set, base::UniquePtrComparator> + in_flight_attempts_; + // The number of in-flight attempts that are treated as slow. + size_t slow_attempt_count_ = 0; + + // When true, try to use IPv6 for the next attempt first. + bool prefer_ipv6_ = true; + // Updated when a stream attempt failed. Used to calculate next IPEndPoint to + // attempt. + std::set failed_ip_endpoints_; + // Updated when a stream attempt is considered slow. Used to calculate next + // IPEndPoint to attempt. + std::set slow_ip_endpoints_; + + base::WeakPtrFactory weak_ptr_factory_{this}; +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_STREAM_POOL_JOB_H_ diff --git a/naiveproxy/src/net/http/http_stream_pool_test_util.cc b/naiveproxy/src/net/http/http_stream_pool_test_util.cc new file mode 100644 index 0000000000..6de47f8676 --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_pool_test_util.cc @@ -0,0 +1,55 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_stream_pool_test_util.h" + +#include "net/base/completion_once_callback.h" +#include "net/log/net_log_with_source.h" +#include "net/socket/socket_test_util.h" +#include "net/socket/stream_socket.h" +#include "net/traffic_annotation/network_traffic_annotation.h" + +namespace net { + +FakeStreamSocket::FakeStreamSocket() : MockClientSocket(NetLogWithSource()) { + connected_ = true; +} + +FakeStreamSocket::~FakeStreamSocket() = default; + +int FakeStreamSocket::Read(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + return 0; +} + +int FakeStreamSocket::Write( + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + const NetworkTrafficAnnotationTag& traffic_annotation) { + return 0; +} + +int FakeStreamSocket::Connect(CompletionOnceCallback callback) { + return OK; +} + +bool FakeStreamSocket::IsConnected() const { + return connected_; +} + +bool FakeStreamSocket::IsConnectedAndIdle() const { + return connected_ && is_idle_; +} + +bool FakeStreamSocket::WasEverUsed() const { + return was_ever_used_; +} + +bool FakeStreamSocket::GetSSLInfo(SSLInfo* ssl_info) { + return false; +} + +} // namespace net diff --git a/naiveproxy/src/net/http/http_stream_pool_test_util.h b/naiveproxy/src/net/http/http_stream_pool_test_util.h new file mode 100644 index 0000000000..940f645bbc --- /dev/null +++ b/naiveproxy/src/net/http/http_stream_pool_test_util.h @@ -0,0 +1,56 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_HTTP_STREAM_POOL_TEST_UTIL_H_ +#define NET_HTTP_HTTP_STREAM_POOL_TEST_UTIL_H_ + +#include "net/base/completion_once_callback.h" +#include "net/socket/socket_test_util.h" +#include "net/socket/stream_socket.h" +#include "net/traffic_annotation/network_traffic_annotation.h" + +namespace net { + +class IOBuffer; +class SSLInfo; + +class FakeStreamSocket : public MockClientSocket { + public: + FakeStreamSocket(); + + FakeStreamSocket(const FakeStreamSocket&) = delete; + FakeStreamSocket& operator=(const FakeStreamSocket&) = delete; + + ~FakeStreamSocket() override; + + void set_is_connected(bool connected) { connected_ = connected; } + + void set_is_idle(bool is_idle) { is_idle_ = is_idle; } + + void set_was_ever_used(bool was_ever_used) { was_ever_used_ = was_ever_used; } + + void set_peer_addr(IPEndPoint peer_addr) { peer_addr_ = peer_addr; } + + // StreamSocket implementation: + int Read(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) override; + int Write(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + const NetworkTrafficAnnotationTag& traffic_annotation) override; + int Connect(CompletionOnceCallback callback) override; + bool IsConnected() const override; + bool IsConnectedAndIdle() const override; + bool WasEverUsed() const override; + bool GetSSLInfo(SSLInfo* ssl_info) override; + + private: + bool is_idle_ = true; + bool was_ever_used_ = false; +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_STREAM_POOL_TEST_UTIL_H_ diff --git a/naiveproxy/src/net/http/http_stream_request.cc b/naiveproxy/src/net/http/http_stream_request.cc index 3f39da5aef..3060b3308a 100644 --- a/naiveproxy/src/net/http/http_stream_request.cc +++ b/naiveproxy/src/net/http/http_stream_request.cc @@ -81,4 +81,20 @@ HttpStreamRequest::websocket_handshake_stream_create_helper() const { return websocket_handshake_stream_create_helper_; } +void HttpStreamRequest::SetDnsResolutionTimeOverrides( + base::TimeTicks dns_resolution_start_time_override, + base::TimeTicks dns_resolution_end_time_override) { + CHECK(!dns_resolution_start_time_override.is_null()); + CHECK(!dns_resolution_end_time_override.is_null()); + if (dns_resolution_start_time_override_.is_null() || + (dns_resolution_start_time_override < + dns_resolution_start_time_override_)) { + dns_resolution_start_time_override_ = dns_resolution_start_time_override; + } + if (dns_resolution_end_time_override_.is_null() || + (dns_resolution_end_time_override < dns_resolution_end_time_override_)) { + dns_resolution_end_time_override_ = dns_resolution_end_time_override; + } +} + } // namespace net diff --git a/naiveproxy/src/net/http/http_stream_request.h b/naiveproxy/src/net/http/http_stream_request.h index 36db46f9d4..39b7a0202b 100644 --- a/naiveproxy/src/net/http/http_stream_request.h +++ b/naiveproxy/src/net/http/http_stream_request.h @@ -184,6 +184,17 @@ class NET_EXPORT_PRIVATE HttpStreamRequest { bool completed() const { return completed_; } + void SetDnsResolutionTimeOverrides( + base::TimeTicks dns_resolution_start_time_override, + base::TimeTicks dns_resolution_end_time_override); + + base::TimeTicks dns_resolution_start_time_override() const { + return dns_resolution_start_time_override_; + } + base::TimeTicks dns_resolution_end_time_override() const { + return dns_resolution_end_time_override_; + } + private: // Unowned. The helper must not be destroyed before this object is. raw_ptr helper_; @@ -201,6 +212,9 @@ class NET_EXPORT_PRIVATE HttpStreamRequest { AlternateProtocolUsage::ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON; ConnectionAttempts connection_attempts_; const StreamType stream_type_; + + base::TimeTicks dns_resolution_start_time_override_; + base::TimeTicks dns_resolution_end_time_override_; }; } // namespace net diff --git a/naiveproxy/src/net/http/http_text_based_stream_handle.cc b/naiveproxy/src/net/http/http_text_based_stream_handle.cc new file mode 100644 index 0000000000..6229c9a7dd --- /dev/null +++ b/naiveproxy/src/net/http/http_text_based_stream_handle.cc @@ -0,0 +1,37 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_text_based_stream_handle.h" + +#include + +#include "net/http/http_stream_pool_group.h" +#include "net/socket/stream_socket.h" + +namespace net { + +HttpTextBasedStreamHandle::HttpTextBasedStreamHandle( + HttpStreamPool::Group* group, + std::unique_ptr socket, + int64_t generation) + : group_(group), generation_(generation) { + CHECK(group); + CHECK(socket); + + // Always considered initialized. + SetSocket(std::move(socket)); + set_is_initialized(true); +} + +HttpTextBasedStreamHandle::~HttpTextBasedStreamHandle() { + Reset(); +} + +void HttpTextBasedStreamHandle::Reset() { + if (socket()) { + group_->ReleaseStreamSocket(PassSocket(), generation_); + } +} + +} // namespace net diff --git a/naiveproxy/src/net/http/http_text_based_stream_handle.h b/naiveproxy/src/net/http/http_text_based_stream_handle.h new file mode 100644 index 0000000000..08374b7e81 --- /dev/null +++ b/naiveproxy/src/net/http/http_text_based_stream_handle.h @@ -0,0 +1,42 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_HTTP_TEXT_BASED_STREAM_HANDLE_H_ +#define NET_HTTP_HTTP_TEXT_BASED_STREAM_HANDLE_H_ + +#include + +#include "base/memory/raw_ptr.h" +#include "net/base/net_export.h" +#include "net/http/http_stream_pool.h" +#include "net/socket/stream_socket_handle.h" + +namespace net { + +class StreamSocket; + +// A StreamSocketHandle that is associated with an HttpStreamPool::Group. +class NET_EXPORT_PRIVATE HttpTextBasedStreamHandle : public StreamSocketHandle { + public: + HttpTextBasedStreamHandle(HttpStreamPool::Group* group, + std::unique_ptr socket, + int64_t generation); + + HttpTextBasedStreamHandle(const HttpTextBasedStreamHandle&) = delete; + HttpTextBasedStreamHandle& operator=(const HttpTextBasedStreamHandle&) = + delete; + + ~HttpTextBasedStreamHandle() override; + + // StreamSocketHandle implementation: + void Reset() override; + + private: + const raw_ptr group_; + const int64_t generation_; +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_TEXT_BASED_STREAM_HANDLE_H_ diff --git a/naiveproxy/src/net/http/http_transaction.h b/naiveproxy/src/net/http/http_transaction.h index 925d9bac9a..bedbeb09ff 100644 --- a/naiveproxy/src/net/http/http_transaction.h +++ b/naiveproxy/src/net/http/http_transaction.h @@ -145,6 +145,9 @@ class NET_EXPORT_PRIVATE HttpTransaction { // Get the number of bytes sent over the network. virtual int64_t GetTotalSentBytes() const = 0; + // Get the number of bytes of the body received from network. + virtual int64_t GetReceivedBodyBytes() const = 0; + // Called to tell the transaction that we have successfully reached the end // of the stream. This is equivalent to performing an extra Read() at the end // that should return 0 bytes. This method should not be called if the diff --git a/naiveproxy/src/net/http/http_transaction_test_util.cc b/naiveproxy/src/net/http/http_transaction_test_util.cc index 4079dcfe47..76a23c1358 100644 --- a/naiveproxy/src/net/http/http_transaction_test_util.cc +++ b/naiveproxy/src/net/http/http_transaction_test_util.cc @@ -27,6 +27,7 @@ #include "net/base/load_timing_info.h" #include "net/base/net_errors.h" #include "net/base/network_isolation_key.h" +#include "net/base/proxy_chain.h" #include "net/base/schemeful_site.h" #include "net/cert/x509_certificate.h" #include "net/disk_cache/disk_cache.h" @@ -439,6 +440,10 @@ int64_t MockNetworkTransaction::GetTotalSentBytes() const { return sent_bytes_; } +int64_t MockNetworkTransaction::GetReceivedBodyBytes() const { + return received_body_bytes_; +} + void MockNetworkTransaction::DoneReading() { CHECK(!done_reading_called_); done_reading_called_ = true; @@ -502,6 +507,9 @@ const int64_t MockNetworkTransaction::kTotalReceivedBytes = 1000; // static const int64_t MockNetworkTransaction::kTotalSentBytes = 100; +// static +const int64_t MockNetworkTransaction::kReceivedBodyBytes = 500; + int MockNetworkTransaction::StartInternal(HttpRequestInfo request, CompletionOnceCallback callback) { current_request_ = std::move(request); @@ -598,6 +606,7 @@ int MockNetworkTransaction::DoSendRequest() { sent_bytes_ = kTotalSentBytes; received_bytes_ = kTotalReceivedBytes; + received_body_bytes_ = kReceivedBodyBytes; const MockTransaction* t = FindMockTransaction(current_request_.url); CHECK(t); @@ -620,8 +629,14 @@ int MockNetworkTransaction::DoSendRequest() { response_.was_cached = false; response_.network_accessed = true; response_.remote_endpoint = t->transport_info.endpoint; - response_.was_fetched_via_proxy = - t->transport_info.type == TransportType::kProxied; + if (t->transport_info.type == TransportType::kDirect) { + response_.proxy_chain = ProxyChain::Direct(); + } else if (t->transport_info.type == TransportType::kProxied) { + response_.proxy_chain = ProxyChain::FromSchemeHostAndPort( + ProxyServer::SCHEME_HTTP, + t->transport_info.endpoint.ToStringWithoutPort(), + t->transport_info.endpoint.port()); + } response_.response_time = transaction_factory_->Now(); if (!t->response_time.is_null()) diff --git a/naiveproxy/src/net/http/http_transaction_test_util.h b/naiveproxy/src/net/http/http_transaction_test_util.h index fad8cbfb0f..55a0b03a7c 100644 --- a/naiveproxy/src/net/http/http_transaction_test_util.h +++ b/naiveproxy/src/net/http/http_transaction_test_util.h @@ -215,6 +215,8 @@ class MockNetworkTransaction final : public HttpTransaction { int64_t GetTotalSentBytes() const override; + int64_t GetReceivedBodyBytes() const override; + void DoneReading() override; const HttpResponseInfo* GetResponseInfo() const override; @@ -270,6 +272,9 @@ class MockNetworkTransaction final : public HttpTransaction { // Bogus value that will be returned by GetTotalSentBytes() if the // MockNetworkTransaction was started. static const int64_t kTotalSentBytes; + // Bogus value that will be returned by GetReceivedBodyBytes() if the + // MockNetworkTransaction was started. + static const int64_t kReceivedBodyBytes; private: enum class State { @@ -327,6 +332,7 @@ class MockNetworkTransaction final : public HttpTransaction { base::WeakPtr transaction_factory_; int64_t received_bytes_ = 0; int64_t sent_bytes_ = 0; + int64_t received_body_bytes_ = 0; // NetLog ID of the fake / non-existent underlying socket used by the // connection. Requires Start() be passed a NetLogWithSource with a real diff --git a/naiveproxy/src/net/http/http_util.cc b/naiveproxy/src/net/http/http_util.cc index 43a89dd552..80dfe37653 100644 --- a/naiveproxy/src/net/http/http_util.cc +++ b/naiveproxy/src/net/http/http_util.cc @@ -89,6 +89,16 @@ std::string GetBaseLanguageCode(const std::string& language_code) { // HttpUtil ------------------------------------------------------------------- +std::string HttpUtil::GenerateRequestLine(std::string_view method, + GURL url, + bool is_for_get_to_http_proxy) { + static constexpr char kSuffix[] = " HTTP/1.1\r\n"; + const std::string path = is_for_get_to_http_proxy + ? HttpUtil::SpecForRequest(url) + : url.PathForRequest(); + return base::StrCat({method, " ", path, kSuffix}); +} + // static std::string HttpUtil::SpecForRequest(const GURL& url) { DCHECK(url.is_valid() && diff --git a/naiveproxy/src/net/http/http_util.h b/naiveproxy/src/net/http/http_util.h index 9a584b4682..4d09494491 100644 --- a/naiveproxy/src/net/http/http_util.h +++ b/naiveproxy/src/net/http/http_util.h @@ -33,6 +33,11 @@ class HttpResponseHeaders; class NET_EXPORT HttpUtil { public: + // Generates a request line that is used for text-based HTTP messaging. + static std::string GenerateRequestLine(std::string_view method, + GURL url, + bool is_for_get_to_http_proxy); + // Returns the absolute URL, to be used for the http request. This url is // made up of the protocol, host, [port], path, [query]. Everything else // is stripped (username, password, reference). diff --git a/naiveproxy/src/net/http/mock_http_cache.cc b/naiveproxy/src/net/http/mock_http_cache.cc index 4a089baa19..87e866f0ba 100644 --- a/naiveproxy/src/net/http/mock_http_cache.cc +++ b/naiveproxy/src/net/http/mock_http_cache.cc @@ -19,6 +19,7 @@ #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" #include "base/location.h" +#include "base/memory/raw_ptr.h" #include "base/task/single_thread_task_runner.h" #include "net/base/features.h" #include "net/base/net_errors.h" @@ -719,11 +720,10 @@ MockHttpCache::MockHttpCache( std::move(disk_cache_factory)) {} disk_cache::Backend* MockHttpCache::backend() { - TestCompletionCallback cb; - disk_cache::Backend* backend; - int rv = http_cache_.GetBackend(&backend, cb.callback()); - rv = cb.GetResult(rv); - return (rv == OK) ? backend : nullptr; + TestGetBackendCompletionCallback cb; + HttpCache::GetBackendResult result = http_cache_.GetBackend(cb.callback()); + result = cb.GetResult(result); + return (result.first == OK) ? result.second : nullptr; } MockDiskCache* MockHttpCache::disk_cache() { @@ -757,8 +757,8 @@ bool MockHttpCache::ReadResponseInfo(disk_cache::Entry* disk_entry, rv = cb.GetResult(rv); EXPECT_EQ(size, rv); - return HttpCache::ParseResponseInfo(buffer->data(), size, response_info, - response_truncated); + return HttpCache::ParseResponseInfo(base::as_bytes(buffer->span()), + response_info, response_truncated); } bool MockHttpCache::WriteResponseInfo(disk_cache::Entry* disk_entry, diff --git a/naiveproxy/src/net/http/mock_http_cache.h b/naiveproxy/src/net/http/mock_http_cache.h index 5bfb56ce07..6b3d2059f5 100644 --- a/naiveproxy/src/net/http/mock_http_cache.h +++ b/naiveproxy/src/net/http/mock_http_cache.h @@ -392,6 +392,27 @@ class MockBlockingBackendFactory : public HttpCache::BackendFactory { bool fail_ = false; }; +struct GetBackendResultIsPendingHelper { + bool operator()(const HttpCache::GetBackendResult& result) const { + return result.first == net::ERR_IO_PENDING; + } +}; +using TestGetBackendCompletionCallbackBase = + net::internal::TestCompletionCallbackTemplate< + HttpCache::GetBackendResult, + GetBackendResultIsPendingHelper>; + +class TestGetBackendCompletionCallback + : public TestGetBackendCompletionCallbackBase { + public: + TestGetBackendCompletionCallback() = default; + + HttpCache::GetBackendCallback callback() { + return base::BindOnce(&TestGetBackendCompletionCallback::SetResult, + base::Unretained(this)); + } +}; + } // namespace net #endif // NET_HTTP_MOCK_HTTP_CACHE_H_ diff --git a/naiveproxy/src/net/http/transport_security_persister.cc b/naiveproxy/src/net/http/transport_security_persister.cc index 7705d87e22..223eb29f45 100644 --- a/naiveproxy/src/net/http/transport_security_persister.cc +++ b/naiveproxy/src/net/http/transport_security_persister.cc @@ -20,8 +20,10 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/location.h" +#include "base/metrics/field_trial_params.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" +#include "base/time/time.h" #include "base/values.h" #include "net/base/features.h" #include "net/base/network_anonymization_key.h" @@ -30,8 +32,26 @@ namespace net { +BASE_FEATURE(kTransportSecurityFileWriterSchedule, + "TransportSecurityFileWriterSchedule", + base::FEATURE_ENABLED_BY_DEFAULT); + namespace { +// From kDefaultCommitInterval in base/files/important_file_writer.cc. +// kTransportSecurityFileWriterScheduleCommitInterval won't set the commit +// interval to less than this, for performance. +constexpr base::TimeDelta kMinCommitInterval = base::Seconds(10); + +// Max safe commit interval for the ImportantFileWriter. +constexpr base::TimeDelta kMaxCommitInterval = base::Minutes(10); + +// Overrides the default commit interval for the ImportantFileWriter. +const base::FeatureParam kCommitIntervalParam( + &kTransportSecurityFileWriterSchedule, + "commit_interval", + kMinCommitInterval); + constexpr const char* kHistogramSuffix = "TransportSecurityPersister"; // This function converts the binary hashes to a base64 string which we can @@ -188,7 +208,10 @@ TransportSecurityPersister::TransportSecurityPersister( const scoped_refptr& background_runner, const base::FilePath& data_path) : transport_security_state_(state), - writer_(data_path, background_runner, kHistogramSuffix), + writer_(data_path, + background_runner, + GetCommitInterval(), + kHistogramSuffix), foreground_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()), background_runner_(background_runner) { transport_security_state_->SetDelegate(this); @@ -265,6 +288,12 @@ void TransportSecurityPersister::LoadEntries(const std::string& serialized) { } } +// static +base::TimeDelta TransportSecurityPersister::GetCommitInterval() { + return std::clamp(kCommitIntervalParam.Get(), kMinCommitInterval, + kMaxCommitInterval); +} + void TransportSecurityPersister::Deserialize( const std::string& serialized, TransportSecurityState* state, diff --git a/naiveproxy/src/net/http/transport_security_persister.h b/naiveproxy/src/net/http/transport_security_persister.h index 96033d971c..de81471e78 100644 --- a/naiveproxy/src/net/http/transport_security_persister.h +++ b/naiveproxy/src/net/http/transport_security_persister.h @@ -36,11 +36,13 @@ #include #include +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/files/important_file_writer.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "net/base/net_export.h" #include "net/http/transport_security_state.h" @@ -50,6 +52,10 @@ class SequencedTaskRunner; namespace net { +// Exists only to hold a "commit-interval" param. If disabled, the default +// ImportantFileWriter commit interval is used. +NET_EXPORT BASE_DECLARE_FEATURE(kTransportSecurityFileWriterSchedule); + // Reads and updates on-disk TransportSecurity state. Clients of this class // should create, destroy, and call into it from one thread. // @@ -119,6 +125,9 @@ class NET_EXPORT TransportSecurityPersister // |transport_security_state_|. void LoadEntries(const std::string& serialized); + // Returns the commit interval used by the ImportantFileWriter. + static base::TimeDelta GetCommitInterval(); + private: // Populates |state| from the JSON string |serialized|. static void Deserialize(const std::string& serialized, diff --git a/naiveproxy/src/net/http/transport_security_state_static.pins b/naiveproxy/src/net/http/transport_security_state_static.pins index 2623bc67d4..f734842e7b 100644 --- a/naiveproxy/src/net/http/transport_security_state_static.pins +++ b/naiveproxy/src/net/http/transport_security_state_static.pins @@ -43,9 +43,9 @@ # hash function for preloaded entries again (we have already done so once). # -# Last updated: 2024-07-09 12:56 UTC +# Last updated: 2024-08-12 12:54 UTC PinsListTimestamp -1720529769 +1723467293 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= @@ -171,31 +171,6 @@ HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm -----END CERTIFICATE----- -RapidSSL ------BEGIN CERTIFICATE----- -MIID1TCCAr2gAwIBAgIDAjbRMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMTAwMjE5MjI0NTA1WhcNMjAwMjE4MjI0NTA1WjA8MQswCQYDVQQG -EwJVUzEXMBUGA1UEChMOR2VvVHJ1c3QsIEluYy4xFDASBgNVBAMTC1JhcGlkU1NM -IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3H4Vsce2cy1rfa0 -l6P7oeYLUF9QqjraD/w9KSRDxhApwfxVQHLuverfn7ZB9EhLyG7+T1cSi1v6kt1e -6K3z8Buxe037z/3R5fjj3Of1c3/fAUnPjFbBvTfjW761T4uL8NpPx+PdVUdp3/Jb -ewdPPeWsIcHIHXro5/YPoar1b96oZU8QiZwD84l6pV4BcjPtqelaHnnzh8jfyMX8 -N8iamte4dsywPuf95lTq319SQXhZV63xEtZ/vNWfcNMFbPqjfWdY3SZiHTGSDHl5 -HI7PynvBZq+odEj7joLCniyZXHstXZu8W1eefDp6E63yoxhbK1kPzVw662gzxigd -gtFQiwIDAQABo4HZMIHWMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUa2k9ahhC -St2PAmU5/TUkhniRFjAwHwYDVR0jBBgwFoAUwHqYaI2J+6sFZAwRfap9ZbjKzE4w -EgYDVR0TAQH/BAgwBgEB/wIBADA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3Js -Lmdlb3RydXN0LmNvbS9jcmxzL2d0Z2xvYmFsLmNybDA0BggrBgEFBQcBAQQoMCYw -JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdlb3RydXN0LmNvbTANBgkqhkiG9w0B -AQUFAAOCAQEAq7y8Cl0YlOPBscOoTFXWvrSY8e48HM3P8yQkXJYDJ1j8Nq6iL4/x -/torAsMzvcjdSCIrYA+lAxD9d/jQ7ZZnT/3qRyBwVNypDFV+4ZYlitm12ldKvo2O -SUNjpWxOJ4cl61tt/qJ/OCjgNqutOaWlYsS3XFgsql0BYKZiZ6PAx2Ij9OdsRu61 -04BqIhPSLT90T+qvjF+0OJzbrs6vhB6m9jRRWXnT43XcvNfzc9+S7NIgWW+c+5X4 -knYYCnwPLKbK3opie9jzzl9ovY8+wXS7FXI6FoOpC+ZNmZzYV+yoAVHHb1c0XqtK -LEL2TxyJeN4mTvVvk0wVaydWTQBUbHq3tw== ------END CERTIFICATE----- - DigiCertEVRoot -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs @@ -245,39 +220,6 @@ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- -Tor1 ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlOpp8zfF+jEbI6R7nxnm -phFPqBCCHMpahBMjQOjHD/860wrH1ZoIeevW9ZJ6MIuBV0jwwtAQokNsx8FVAmMH -Tjg6b4blbum1meahODgafcGjHrRGzEvuN6r577SgHcOQXkAIVsbZ6Bjk+8kh1t/v -cEaLa9DmzBQpMTYWCDY4kN0tFMSNS8CJekgA6vDVFHFRp4NiJ1eFmd38furKsZUZ -rqvY4jzyaIls/UQB8q/6bHbEeF5lTUaWPZob1XBv0Ib7nVX2gGzan+qYQim8Wdjc -LrGhnUBwil5lh9qQ/8VIMVbjtcAjeZpVWuTZA3stbOiaDCqJBGTe9glFOH1xz9hS -7QIDAQAB ------END PUBLIC KEY----- - -Tor2 ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1b2qGT7y4sjNG18lZKuC -tLwDfE57KseaNY6VM61DySaobdDt9VOiFS+3QaPcrT60qOH9aQ1DGhNv3jcAJvtT -i5nKSgVDu7Emb70j2xrRaJ+lnITYs2Je9JYUQmb6IQAplYTz60s0Ng1MrROqNswl -UhhXTCZLB1Bo+uN8OM7LoZ+Sr+sP0YhMsNAyxf3ZJVvzhWHQYGHvNBqIrXpq6YLc -zHSdd5QirZ3lSdhv2uGYxDBLslfk47xObxSvqblLD2ISlMRPL85FnetHL/dRMUEo -2c9MJ49nxItUbeizxxIeCbfWdbucd4il5bBlN9t3duFqwCu80ZOuHMvxavpP05D5 -RwIDAQAB ------END PUBLIC KEY----- - -Tor3 ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtNfM24/03NeOb3R1sRN5 -7zwYThdBJPSOXehVN3JvShTZ86kg+f0HYwbZZ0Xx0jujghabKgHkhiLMChl+Fg97 -Pi0t4mQm/3sdltfUypprdcE6CbCzKkWNTaD9+iMA4m8peSq0Pd5hCKvRidb1+OCL -rJKOqx24r9VwsIa69zdiE5DpFBqvi1YczoaknF09jNR/hjqMyEwENR7t/AKZ1VpK -6L6loJt2mCl3FWjM+Wt50ktrSyAI4aPfSAILAmSRhb5TY1xWRBuHDOzdf+DvegXu -/aHn0j5UscN2XqQiNJcUrdJYsekfpHDtYKP/pesHCp2lCSbYdAaS8mnqDJwV8xC4 -1wIDAQAB ------END PUBLIC KEY----- - GlobalSignRootCA -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG @@ -547,134 +489,6 @@ uy8blcsjtFoq5lG5Ba1982Qzkmot+08ZZQi/QxZ+QARS16YL3KQgJRCb7y+UXmGa PQIDAQAB -----END PUBLIC KEY----- -# From https://letsencrypt.org/certificates/ -# The key is shared by Let's Encrypt Authority X1 and X3. -LetsEncryptAuthorityPrimary_X1_X3 ------BEGIN CERTIFICATE----- -MIIEqDCCA5CgAwIBAgIRAJgT9HUT5XULQ+dDHpceRL0wDQYJKoZIhvcNAQELBQAw -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzAeFw0xNTEwMTkyMjMzMzZaFw0yMDEwMTkyMjMzMzZa -MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD -ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAJzTDPBa5S5Ht3JdN4OzaGMw6tc1Jhkl4b2+NfFwki+3uEtB -BaupnjUIWOyxKsRohwuj43Xk5vOnYnG6eYFgH9eRmp/z0HhncchpDpWRz/7mmelg -PEjMfspNdxIknUcbWuu57B43ABycrHunBerOSuu9QeU2mLnL/W08lmjfIypCkAyG -dGfIf6WauFJhFBM/ZemCh8vb+g5W9oaJ84U/l4avsNwa72sNlRZ9xCugZbKZBDZ1 -gGusSvMbkEl4L6KWTyogJSkExnTA0DHNjzE4lRa6qDO4Q/GxH8Mwf6J5MRM9LTb4 -4/zyM2q5OTHFr8SNDR1kFjOq+oQpttQLwNh9w5MCAwEAAaOCAZIwggGOMBIGA1Ud -EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMH8GCCsGAQUFBwEBBHMwcTAy -BggrBgEFBQcwAYYmaHR0cDovL2lzcmcudHJ1c3RpZC5vY3NwLmlkZW50cnVzdC5j -b20wOwYIKwYBBQUHMAKGL2h0dHA6Ly9hcHBzLmlkZW50cnVzdC5jb20vcm9vdHMv -ZHN0cm9vdGNheDMucDdjMB8GA1UdIwQYMBaAFMSnsaR7LHH62+FLkHX/xBVghYkQ -MFQGA1UdIARNMEswCAYGZ4EMAQIBMD8GCysGAQQBgt8TAQEBMDAwLgYIKwYBBQUH -AgEWImh0dHA6Ly9jcHMucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcwPAYDVR0fBDUw -MzAxoC+gLYYraHR0cDovL2NybC5pZGVudHJ1c3QuY29tL0RTVFJPT1RDQVgzQ1JM -LmNybDATBgNVHR4EDDAKoQgwBoIELm1pbDAdBgNVHQ4EFgQUqEpqYwR93brm0Tm3 -pkVl7/Oo7KEwDQYJKoZIhvcNAQELBQADggEBANHIIkus7+MJiZZQsY14cCoBG1hd -v0J20/FyWo5ppnfjL78S2k4s2GLRJ7iD9ZDKErndvbNFGcsW+9kKK/TnY21hp4Dd -ITv8S9ZYQ7oaoqs7HwhEMY9sibED4aXw09xrJZTC9zK1uIfW6t5dHQjuOWv+HHoW -ZnupyxpsEUlEaFb+/SCI4KCSBdAsYxAcsHYI5xxEI4LutHp6s3OT2FuO90WfdsIk -6q78OMSdn875bNjdBYAqxUp2/LEIHfDBkLoQz0hFJmwAbYahqKaLn73PAAm1X2kj -f1w8DdnkabOLGeOVcj9LQ+s67vBykx4anTjURkbqZslUEUsn2k5xeua2zUk= ------END CERTIFICATE----- - -# From https://letsencrypt.org/certificates/ -# The key is shared by Let's Encrypt Authority X2 and X4. -LetsEncryptAuthorityBackup_X2_X4 ------BEGIN CERTIFICATE----- -MIIEqDCCA5CgAwIBAgIRAMODTJjAvWslLKN5tm+lKw4wDQYJKoZIhvcNAQELBQAw -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzAeFw0xNTEwMTkyMjM1MDFaFw0yMDEwMTkyMjM1MDFa -MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD -ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMjCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAOEkdEJ7t5Ex2XP/OKrYzkRctzkK3ESuDb1FuZc3Z6+9UE9f -0xBUa/dB2o5j5m1bwOhAqYxB/NEDif9iYQlg1gcFeJqQvRpkPk/cz3cviWvLZ69B -TcWNAMBr/o2E3LXylTGo6PaQoENKk3Rcsz5DaUuJIkd0UT6ZZMPNJAH5hC8odxci -p93DbAhMZi83dMVvk46wRjcWYdFQmMiwD09YU3ys9totlmFQrUPcCqZPnrVSuZyO -707fRrMx3CD8acKjIHU+7DgbNk5mZtLf9Wakky97pg6UPmA9Skscb7q0TRw8kVhu -L03E2nDb7QE5dsBJ5+k1tRQGkMHlkuIQ/Wu5tIUCAwEAAaOCAZIwggGOMBIGA1Ud -EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMH8GCCsGAQUFBwEBBHMwcTAy -BggrBgEFBQcwAYYmaHR0cDovL2lzcmcudHJ1c3RpZC5vY3NwLmlkZW50cnVzdC5j -b20wOwYIKwYBBQUHMAKGL2h0dHA6Ly9hcHBzLmlkZW50cnVzdC5jb20vcm9vdHMv -ZHN0cm9vdGNheDMucDdjMB8GA1UdIwQYMBaAFMSnsaR7LHH62+FLkHX/xBVghYkQ -MFQGA1UdIARNMEswCAYGZ4EMAQIBMD8GCysGAQQBgt8TAQEBMDAwLgYIKwYBBQUH -AgEWImh0dHA6Ly9jcHMucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcwPAYDVR0fBDUw -MzAxoC+gLYYraHR0cDovL2NybC5pZGVudHJ1c3QuY29tL0RTVFJPT1RDQVgzQ1JM -LmNybDATBgNVHR4EDDAKoQgwBoIELm1pbDAdBgNVHQ4EFgQUxbGrTkyxzWQwk37B -hJkFq+YD4iUwDQYJKoZIhvcNAQELBQADggEBAAcSAhaE7rvHxyUnhgkEpMR56o2I -IH+mlw5kknjhAuvaBIAM59MZkFbFg5CrNWt8K+G3UoxJgFwv7HvJJxqwgPpNgXC/ -uT3prkvwt+2lvzKJKbqdH+lo40P8EuSyyJOz2hjrRzNMHbJHYDS9OhF5WC5LOQQa -ydgLZ/JHxXgJypEZqcmVgQ+yYBs0XPwXjE7OE8vbx5REwu7gToMIqAoWRoWW2MxS -g28RGPVnHzHk2XV1nZGy9T+NYQ91vWWJr1pzNEFZ0cnA2xGwTeJ+zZ3URCfw3Z1U -+YAL3YUmrvdoRBlASOTmNJmXSo9qvMYPa3DEomAPoFQFZqsSN6kuqDEIqMA= ------END CERTIFICATE----- - -# From https://letsencrypt.org/certificates/ -R3LetsEncrypt ------BEGIN CERTIFICATE----- -MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw -WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg -RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP -R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx -sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm -NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg -Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG -/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB -Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA -FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw -AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw -Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB -gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W -PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl -ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz -CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm -lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 -avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 -yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O -yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids -hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ -HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv -MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX -nLRbwHOoq7hHwg== ------END CERTIFICATE----- - -# From https://letsencrypt.org/certificates/ -R4LetsEncrypt ------BEGIN CERTIFICATE----- -MIIFFjCCAv6gAwIBAgIRAIp5IlCr5SxSbO7Pf8lC3WIwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw -WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg -RW5jcnlwdDELMAkGA1UEAxMCUjQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQCzKNx3KdPnkb7ztwoAx/vyVQslImNTNq/pCCDfDa8oPs3Gq1e2naQlGaXS -Mm1Jpgi5xy+hm5PFIEBrhDEgoo4wYCVg79kaiT8faXGy2uo/c0HEkG9m/X2eWNh3 -z81ZdUTJoQp7nz8bDjpmb7Z1z4vLr53AcMX/0oIKr13N4uichZSk5gA16H5OOYHH -IYlgd+odlvKLg3tHxG0ywFJ+Ix5FtXHuo+8XwgOpk4nd9Z/buvHa4H6Xh3GBHhqC -VuQ+fBiiCOUWX6j6qOBIUU0YFKAMo+W2yrO1VRJrcsdafzuM+efZ0Y4STTMzAyrx -E+FCPMIuWWAubeAHRzNl39Jnyk2FAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB -Af8CAQAwHQYDVR0OBBYEFDadPuCxQPYnLHy/jZ0xivZUpkYmMB8GA1UdIwQYMBaA -FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw -AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw -Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB -gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCJbu5CalWO+H+Az0lmIG14DXmlYHQE -k26umjuCyioWs2icOlZznPTcZvbfq02YPHGTCu3ctggVDULJ+fwOxKekzIqeyLNk -p8dyFwSAr23DYBIVeXDpxHhShvv0MLJzqqDFBTHYe1X5X2Y7oogy+UDJxV2N24/g -Z8lxG4Vr2/VEfUOrw4Tosl5Z+1uzOdvTyBcxD/E5rGgTLczmulctHy3IMTmdTFr0 -FnU0/HMQoquWQuODhFqzMqNcsdbjANUBwOEQrKI8Sy6+b84kHP7PtO+S4Ik8R2k7 -ZeMlE1JmxBi/PZU860YlwT8/qOYToCHVyDjhv8qutbf2QnUl3SV86th2I1QQE14s -0y7CdAHcHkw3sAEeYGkwCA74MO+VFtnYbf9B2JBOhyyWb5087rGzitu5MTAW41X9 -DwTeXEg+a24tAeht+Y1MionHUwa4j7FB/trN3Fnb/r90+4P66ZETVIEcjseUSMHO -w6yqv10/H/dw/8r2EDUincBBX3o9DL3SadqragkKy96HtMiLcqMMGAPm0gti1b6f -bnvOdr0mrIVIKX5nzOeGZORaYLoSD4C8qvFT7U+Um6DMo36cVDNsPmkF575/s3C2 -CxGiCPQqVxPgfNSh+2CPd2Xv04lNeuw6gG89DlOhHuoFKRlmPnom+gwqhz3ZXMfz -TfmvjrBokzCICA== ------END CERTIFICATE----- - ISRGRootX1 -----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw diff --git a/naiveproxy/src/net/http/transport_security_state_static_pins.json b/naiveproxy/src/net/http/transport_security_state_static_pins.json index 6059f1949c..e45480a46e 100644 --- a/naiveproxy/src/net/http/transport_security_state_static_pins.json +++ b/naiveproxy/src/net/http/transport_security_state_static_pins.json @@ -31,7 +31,7 @@ // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets' // refer to, and the timestamp at which the pins list was last updated. // -// Last updated: 2024-07-09 12:56 UTC +// Last updated: 2024-08-12 12:54 UTC // { "pinsets": [ @@ -59,20 +59,6 @@ ], "report_uri": "http://clients3.google.com/cert_upload_json" }, - { - "name": "tor", - "static_spki_hashes": [ - "RapidSSL", - "DigiCertEVRoot", - "Tor1", - "Tor2", - "Tor3", - "LetsEncryptAuthorityPrimary_X1_X3", - "LetsEncryptAuthorityBackup_X2_X4", - "R3LetsEncrypt", - "R4LetsEncrypt" - ] - }, { "name": "facebook", "static_spki_hashes": [ @@ -1959,31 +1945,6 @@ "name": "www.messenger.com", "include_subdomains": true, "pins": "facebook" - }, - { - "name": "torproject.org", - "include_subdomains": false, - "pins": "tor" - }, - { - "name": "blog.torproject.org", - "include_subdomains": true, - "pins": "tor" - }, - { - "name": "check.torproject.org", - "include_subdomains": true, - "pins": "tor" - }, - { - "name": "www.torproject.org", - "include_subdomains": true, - "pins": "tor" - }, - { - "name": "dist.torproject.org", - "include_subdomains": true, - "pins": "tor" } ] } \ No newline at end of file diff --git a/naiveproxy/src/net/log/file_net_log_observer.cc b/naiveproxy/src/net/log/file_net_log_observer.cc index f63ffc69e5..a3374f31f1 100644 --- a/naiveproxy/src/net/log/file_net_log_observer.cc +++ b/naiveproxy/src/net/log/file_net_log_observer.cc @@ -241,6 +241,10 @@ class FileNetLogObserver::FileWriter { bool IsUnbounded() const; bool IsBounded() const; + // Returns true if there is a file size bound to enforce and we want to stitch + // the files together. + bool IsBoundedAndStitchable() const; + // Increments |current_event_file_number_|, and updates all state relating to // the current event file (open file handle, num bytes written, current file // number). @@ -375,6 +379,16 @@ FileNetLogObserver::CreateUnboundedPreExisting( std::move(constants)); } +std::unique_ptr FileNetLogObserver::CreateBoundedFile( + base::File output_file, + uint64_t max_total_size, + NetLogCaptureMode capture_mode, + std::unique_ptr constants) { + return CreateInternal(base::FilePath(), base::FilePath(), + std::make_optional(std::move(output_file)), + max_total_size, 1, capture_mode, std::move(constants)); +} + FileNetLogObserver::~FileNetLogObserver() { if (net_log()) { // StopObserving was not called. @@ -558,11 +572,16 @@ FileNetLogObserver::FileWriter::FileWriter( max_event_file_size_(max_event_file_size), task_runner_(std::move(task_runner)) { DCHECK_EQ(pre_existing_log_file.has_value(), log_path.empty()); - DCHECK_EQ(IsBounded(), !inprogress_dir_path.empty()); if (pre_existing_log_file.has_value()) { // pre_existing_log_file.IsValid() being false is fine. final_log_file_ = std::move(pre_existing_log_file.value()); + if (inprogress_dir_path.empty()) { + // If we are not stitching the files together, then we aren't using + // bounded, but we still need to to keep track of the size of the current + // event file starting from 0 bytes written. + current_event_file_size_ = 0; + } } } @@ -572,14 +591,14 @@ void FileNetLogObserver::FileWriter::Initialize( std::unique_ptr constants_value) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); - // Open the final log file, and keep it open for the duration of logging (even - // in bounded mode). + // Open the final log file, and keep it open for the duration of logging + // (even in bounded mode). if (!final_log_path_.empty()) final_log_file_ = OpenFileForWrite(final_log_path_); else TruncateFile(&final_log_file_); - if (IsBounded()) { + if (IsBoundedAndStitchable()) { CreateInprogressDirectory(); base::File constants_file = OpenFileForWrite(GetConstantsFilePath()); WriteConstantsToFile(std::move(constants_value), &constants_file); @@ -593,7 +612,7 @@ void FileNetLogObserver::FileWriter::Stop( DCHECK(task_runner_->RunsTasksInCurrentSequence()); // Write out the polled data. - if (IsBounded()) { + if (IsBoundedAndStitchable()) { base::File closing_file = OpenFileForWrite(GetClosingFilePath()); WritePolledDataToFile(std::move(polled_data), &closing_file); } else { @@ -604,8 +623,9 @@ void FileNetLogObserver::FileWriter::Stop( // If operating in bounded mode, the events were written to separate files // within |inprogress_dir_path_|. Assemble them into the final destination // file. - if (IsBounded()) + if (IsBoundedAndStitchable()) { StitchFinalLogFile(); + } // Ensure the final log file has been flushed. final_log_file_.Close(); @@ -621,9 +641,14 @@ void FileNetLogObserver::FileWriter::Flush( while (!local_file_queue.empty()) { base::File* output_file; + if (inprogress_dir_path_.empty() && IsBounded() && + current_event_file_size_ > max_event_file_size_) { + return; + } + // If in bounded mode, output events to the current event file. Otherwise // output events to the final log path. - if (IsBounded()) { + if (IsBoundedAndStitchable()) { if (current_event_file_number_ == 0 || current_event_file_size_ >= max_event_file_size_) { IncrementCurrentEventFile(); @@ -639,9 +664,9 @@ void FileNetLogObserver::FileWriter::Flush( wrote_event_bytes_ |= bytes_written > 0; // Keep track of the filesize for current event file when in bounded mode. - if (IsBounded()) + if (IsBounded()) { current_event_file_size_ += bytes_written; - + } local_file_queue.pop(); } } @@ -651,7 +676,7 @@ void FileNetLogObserver::FileWriter::DeleteAllFiles() { final_log_file_.Close(); - if (IsBounded()) { + if (IsBoundedAndStitchable()) { current_event_file_.Close(); base::DeletePathRecursively(inprogress_dir_path_); } @@ -677,9 +702,13 @@ bool FileNetLogObserver::FileWriter::IsBounded() const { return !IsUnbounded(); } +bool FileNetLogObserver::FileWriter::IsBoundedAndStitchable() const { + return IsBounded() && !inprogress_dir_path_.empty(); +} + void FileNetLogObserver::FileWriter::IncrementCurrentEventFile() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); - DCHECK(IsBounded()); + DCHECK(IsBoundedAndStitchable()); current_event_file_number_++; current_event_file_ = OpenFileForWrite( @@ -690,7 +719,7 @@ void FileNetLogObserver::FileWriter::IncrementCurrentEventFile() { base::FilePath FileNetLogObserver::FileWriter::GetEventFilePath( size_t index) const { DCHECK_LT(index, total_num_event_files_); - DCHECK(IsBounded()); + DCHECK(IsBoundedAndStitchable()); return inprogress_dir_path_.AppendASCII( "event_file_" + base::NumberToString(index) + ".json"); } @@ -792,7 +821,7 @@ void FileNetLogObserver::FileWriter::StitchFinalLogFile() { } void FileNetLogObserver::FileWriter::CreateInprogressDirectory() { - DCHECK(IsBounded()); + DCHECK(IsBoundedAndStitchable()); // If an output file couldn't be created, either creation of intermediate // files will also fail (if they're in a sibling directory), or are they are diff --git a/naiveproxy/src/net/log/file_net_log_observer.h b/naiveproxy/src/net/log/file_net_log_observer.h index 3bf4ffa978..e851b34c78 100644 --- a/naiveproxy/src/net/log/file_net_log_observer.h +++ b/naiveproxy/src/net/log/file_net_log_observer.h @@ -86,6 +86,15 @@ class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver { NetLogCaptureMode capture_mode, std::unique_ptr constants); + // Creates a bounded log that writes to a pre-existing. Instead of stitching + // multiple log files together, once the maximum capacity has been reached the + // logging stops. + static std::unique_ptr CreateBoundedFile( + base::File output_file, + uint64_t max_total_size, + NetLogCaptureMode capture_mode, + std::unique_ptr constants); + FileNetLogObserver(const FileNetLogObserver&) = delete; FileNetLogObserver& operator=(const FileNetLogObserver&) = delete; diff --git a/naiveproxy/src/net/log/net_log.cc b/naiveproxy/src/net/log/net_log.cc index b43cf73c03..90e937e1ec 100644 --- a/naiveproxy/src/net/log/net_log.cc +++ b/naiveproxy/src/net/log/net_log.cc @@ -7,6 +7,7 @@ #include "base/check_op.h" #include "base/containers/contains.h" #include "base/no_destructor.h" +#include "base/not_fatal_until.h" #include "base/notreached.h" #include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" @@ -106,7 +107,7 @@ void NetLog::RemoveObserver(NetLog::ThreadSafeObserver* observer) { DCHECK_EQ(this, observer->net_log_); auto it = base::ranges::find(observers_, observer); - DCHECK(it != observers_.end()); + CHECK(it != observers_.end(), base::NotFatalUntil::M130); observers_.erase(it); observer->net_log_ = nullptr; @@ -134,7 +135,7 @@ void NetLog::RemoveCaptureModeObserver( DCHECK(HasCaptureModeObserver(observer)); auto it = base::ranges::find(capture_mode_observers_, observer); - DCHECK(it != capture_mode_observers_.end()); + CHECK(it != capture_mode_observers_.end(), base::NotFatalUntil::M130); capture_mode_observers_.erase(it); observer->net_log_ = nullptr; diff --git a/naiveproxy/src/net/log/net_log_event_type_list.h b/naiveproxy/src/net/log/net_log_event_type_list.h index 9207401e3f..fd5e42a930 100644 --- a/naiveproxy/src/net/log/net_log_event_type_list.h +++ b/naiveproxy/src/net/log/net_log_event_type_list.h @@ -958,6 +958,26 @@ EVENT_TYPE(SOCKET_POOL_CONNECTING_N_SOCKETS) // } EVENT_TYPE(SOCKET_POOL_CLOSING_SOCKET) +// ------------------------------------------------------------------------ +// StreamAttempt and subclasses +// ------------------------------------------------------------------------ + +// Marks the creation/destruction of a TcpStreamAttempt. +// For the END phase, if there was an error, the following parameters are +// attached: +// { +// "net_error": , +// } +EVENT_TYPE(TCP_STREAM_ATTEMPT_ALIVE) + +// Marks the creation/destruction of a TlsStreamAttempt. +// For the END phase, if there was an error, the following parameters are +// attached: +// { +// "net_error": , +// } +EVENT_TYPE(TLS_STREAM_ATTEMPT_ALIVE) + // ------------------------------------------------------------------------ // URLRequest // ------------------------------------------------------------------------ @@ -1844,8 +1864,22 @@ EVENT_TYPE(QUIC_SESSION_POOL_PLATFORM_NOTIFICATION) // These events track QuicSessionPool's handling of OnIPAddressChanged and // whether QuicSessions are closed or marked as going away. + EVENT_TYPE(QUIC_SESSION_POOL_ON_IP_ADDRESS_CHANGED) + +// { +// "net_error": , +// "quic_error": , +// "before_active_sessions_size": , +// "before_all_sessions_size": , +// "after_active_sessions_size": , +// "after_all_sessions_size": , +// } EVENT_TYPE(QUIC_SESSION_POOL_CLOSE_ALL_SESSIONS) + EVENT_TYPE(QUIC_SESSION_POOL_MARK_ALL_ACTIVE_SESSIONS_GOING_AWAY) // ------------------------------------------------------------------------ @@ -3064,6 +3098,35 @@ EVENT_TYPE(NETWORK_CONNECTIVITY_CHANGED) // } EVENT_TYPE(NETWORK_CHANGED) +// This event is emitted whenever the macOS's dynamic store entries of network +// interface related keys (SCEntNetInterface, SCEntNetIPv4, and SCEntNetIPv6) +// has been changed. +// { +// "result": , +// "net_ipv4_key": , +// "net_ipv6_key": , +// "net_interface_key": , +// "reduce_notification": , +// "old_ipv4_interface": , +// "old_ipv6_interface": , +// "new_ipv4_interface": , +// "new_ipv6_interface": , +// "old_interfaces": , +// "new_interfaces": +// } +EVENT_TYPE(NETWORK_MAC_OS_CONFIG_CHANGED) + // This event is emitted whenever DnsClient receives a new DnsConfig or // DnsConfigOverrides. // { @@ -4041,6 +4104,7 @@ EVENT_TYPE(COOKIE_SET_BLOCKED_BY_NETWORK_DELEGATE) // "name": , // "domain": , // "path": , +// "partition_key": // "operation": // } EVENT_TYPE(COOKIE_INCLUSION_STATUS) diff --git a/naiveproxy/src/net/log/net_log_source_type_list.h b/naiveproxy/src/net/log/net_log_source_type_list.h index cedd37ce35..24ac12dc7b 100644 --- a/naiveproxy/src/net/log/net_log_source_type_list.h +++ b/naiveproxy/src/net/log/net_log_source_type_list.h @@ -18,6 +18,8 @@ SOURCE_TYPE(HTTP_PROXY_CONNECT_JOB) SOURCE_TYPE(SOCKS_CONNECT_JOB) SOURCE_TYPE(SSL_CONNECT_JOB) SOURCE_TYPE(TRANSPORT_CONNECT_JOB) +SOURCE_TYPE(TCP_STREAM_ATTEMPT) +SOURCE_TYPE(TLS_STREAM_ATTEMPT) SOURCE_TYPE(SOCKET) SOURCE_TYPE(HTTP2_SESSION) SOURCE_TYPE(QUIC_CONNECTION_MIGRATION) @@ -26,6 +28,7 @@ SOURCE_TYPE(HOST_RESOLVER_IMPL_JOB) SOURCE_TYPE(DISK_CACHE_ENTRY) SOURCE_TYPE(MEMORY_CACHE_ENTRY) SOURCE_TYPE(HTTP_STREAM_JOB) +SOURCE_TYPE(HTTP_STREAM_POOL_JOB) SOURCE_TYPE(EXPONENTIAL_BACKOFF_THROTTLING) SOURCE_TYPE(UDP_SOCKET) SOURCE_TYPE(CERT_VERIFY_PROC_CREATED) diff --git a/naiveproxy/src/net/network_error_logging/network_error_logging_service.cc b/naiveproxy/src/net/network_error_logging/network_error_logging_service.cc index 5686ce1e73..4bcc417213 100644 --- a/naiveproxy/src/net/network_error_logging/network_error_logging_service.cc +++ b/naiveproxy/src/net/network_error_logging/network_error_logging_service.cc @@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" +#include "base/not_fatal_until.h" #include "base/rand_util.h" #include "base/time/clock.h" #include "base/time/default_clock.h" @@ -29,6 +30,7 @@ #include "net/base/url_util.h" #include "net/log/net_log.h" #include "net/reporting/reporting_service.h" +#include "net/reporting/reporting_target_type.h" #include "url/gurl.h" #include "url/origin.h" @@ -493,7 +495,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { details.user_agent, policy->report_to, kReportType, CreateReportBody(phase_string, type_string, sampling_fraction.value(), details), - details.reporting_upload_depth); + details.reporting_upload_depth, ReportingTargetType::kDeveloper); } void DoQueueSignedExchangeReport(SignedExchangeReportDetails details, @@ -542,7 +544,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { details.outer_url, std::nullopt, details.network_anonymization_key, details.user_agent, policy->report_to, kReportType, CreateSignedExchangeReportBody(details, sampling_fraction.value()), - 0 /* depth */); + 0 /* depth */, ReportingTargetType::kDeveloper); RecordSignedExchangeRequestOutcome(RequestOutcome::kQueued); } @@ -712,7 +714,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { // Removes the policy pointed to by |policy_it|. Invalidates |policy_it|. // Returns the iterator to the next element. PolicyMap::iterator RemovePolicy(PolicyMap::iterator policy_it) { - DCHECK(policy_it != policies_.end()); + CHECK(policy_it != policies_.end(), base::NotFatalUntil::M130); NelPolicy* policy = &policy_it->second; MaybeRemoveWildcardPolicy(policy); @@ -733,7 +735,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { auto wildcard_it = wildcard_policies_.find(WildcardNelPolicyKey(origin_key)); - DCHECK(wildcard_it != wildcard_policies_.end()); + CHECK(wildcard_it != wildcard_policies_.end(), base::NotFatalUntil::M130); size_t erased = wildcard_it->second.erase(policy); DCHECK_EQ(1u, erased); @@ -766,7 +768,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { // This should only be called if we have hit the max policy limit, so there // should be at least one policy. - DCHECK(stalest_it != policies_.end()); + CHECK(stalest_it != policies_.end(), base::NotFatalUntil::M130); RemovePolicy(stalest_it); } diff --git a/naiveproxy/src/net/nqe/network_quality_estimator.cc b/naiveproxy/src/net/nqe/network_quality_estimator.cc index 6d03fb24a0..f5e65f7795 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator.cc +++ b/naiveproxy/src/net/nqe/network_quality_estimator.cc @@ -84,11 +84,54 @@ bool RequestSchemeIsHTTPOrHTTPS(const URLRequest& request) { nqe::internal::NetworkID DoGetCurrentNetworkID( NetworkQualityEstimatorParams* params) { - nqe::internal::NetworkID network_id( - NetworkChangeNotifier::GetConnectionType(), std::string(), INT32_MIN); + nqe::internal::NetworkID network_id( + NetworkChangeNotifier::GetConnectionType(), std::string(), INT32_MIN); - return network_id; + return network_id; +} + +const char* CategoryToString(nqe::internal::ObservationCategory category) { + switch (category) { + case nqe::internal::OBSERVATION_CATEGORY_HTTP: + return "HTTP"; + case nqe::internal::OBSERVATION_CATEGORY_TRANSPORT: + return "Transport"; + case nqe::internal::OBSERVATION_CATEGORY_END_TO_END: + return "EndToEnd"; + case nqe::internal::OBSERVATION_CATEGORY_COUNT: + NOTREACHED_NORETURN(); } +} + +base::TimeTicks GetStartTimeFromThreshold(int threshold) { + if (threshold < 0) { + return base::TimeTicks(); + } + return base::TimeTicks::Now() - base::Seconds(threshold); +} + +base::TimeTicks GetHTTPStartTime() { + static const int threshold = features::kRecentHTTPThresholdInSeconds.Get(); + return GetStartTimeFromThreshold(threshold); +} + +base::TimeTicks GetTransportStartTime() { + static const int threshold = + features::kRecentTransportThresholdInSeconds.Get(); + return GetStartTimeFromThreshold(threshold); +} + +base::TimeTicks GetEndToEndStartTime() { + static const int threshold = + features::kRecentEndToEndThresholdInSeconds.Get(); + return GetStartTimeFromThreshold(threshold); +} + +void RecordFallbackSuccess(std::string_view category, bool fallback_success) { + base::UmaHistogramBoolean( + base::StrCat({"NQE.RTT.HittingThreshold.", category, ".FallbackSuccess"}), + fallback_success); +} } // namespace @@ -123,6 +166,8 @@ NetworkQualityEstimator::NetworkQualityEstimator( tick_clock_, params_->weight_multiplier_per_second(), 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/)}, + effective_connection_type_recomputation_interval_( + features::kEffectiveConnectionTypeRecomputationInterval.Get()), net_log_(NetLogWithSource::Make( net_log, net::NetLogSourceType::NETWORK_QUALITY_ESTIMATOR)), @@ -314,6 +359,25 @@ void NetworkQualityEstimator::NotifyHeadersReceived( if (IsHangingRequest(observed_http_rtt)) return; + // Metrics on estimation errors. + const auto& estimated_rtt = GetHttpRTT(); + if (estimated_rtt) { + const base::TimeDelta estimation_error = observed_http_rtt - *estimated_rtt; + if (estimation_error.is_zero()) { + base::UmaHistogramBoolean("NQE.RTT.Error.IsZero", true); + base::UmaHistogramTimes("NQE.RTT.Error.Absolute", estimation_error); + } else { + base::UmaHistogramBoolean("NQE.RTT.Error.IsZero", false); + if (estimation_error.is_positive()) { + base::UmaHistogramTimes("NQE.RTT.Error.Positive", estimation_error); + base::UmaHistogramTimes("NQE.RTT.Error.Absolute", estimation_error); + } else { // Negative. + base::UmaHistogramTimes("NQE.RTT.Error.Negative", -estimation_error); + base::UmaHistogramTimes("NQE.RTT.Error.Absolute", -estimation_error); + } + } + } + Observation http_rtt_observation(observed_http_rtt.InMilliseconds(), tick_clock_->NowTicks(), current_network_id_.signal_strength, @@ -554,6 +618,10 @@ void NetworkQualityEstimator::ComputeEffectiveConnectionType() { UMA_HISTOGRAM_TIMES("NQE.RTT.OnECTComputation", network_quality_.http_rtt()); } + if (network_quality_.transport_rtt() != nqe::internal::InvalidRTT()) { + base::UmaHistogramTimes("NQE.TransportRTT.OnECTComputation", + network_quality_.transport_rtt()); + } end_to_end_rtt_ = std::nullopt; if (end_to_end_rtt != nqe::internal::InvalidRTT()) { @@ -756,21 +824,41 @@ NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics( return EFFECTIVE_CONNECTION_TYPE_SLOW_2G; } - if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP, base::TimeTicks(), - http_rtt, nullptr)) { - *http_rtt = nqe::internal::InvalidRTT(); + if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP, + GetHTTPStartTime(), http_rtt, nullptr)) { + bool fallback_success = true; + if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP, + base::TimeTicks(), http_rtt, nullptr)) { + *http_rtt = nqe::internal::InvalidRTT(); + fallback_success = false; + } + RecordFallbackSuccess("HTTP", fallback_success); } if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT, - base::TimeTicks(), transport_rtt, + GetTransportStartTime(), transport_rtt, transport_rtt_observation_count)) { - *transport_rtt = nqe::internal::InvalidRTT(); + bool fallback_success = true; + if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT, + base::TimeTicks(), transport_rtt, + transport_rtt_observation_count)) { + *transport_rtt = nqe::internal::InvalidRTT(); + fallback_success = false; + } + RecordFallbackSuccess("Transport", fallback_success); } if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_END_TO_END, - base::TimeTicks(), end_to_end_rtt, + GetEndToEndStartTime(), end_to_end_rtt, end_to_end_rtt_observation_count)) { - *end_to_end_rtt = nqe::internal::InvalidRTT(); + bool fallback_success = true; + if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_END_TO_END, + base::TimeTicks(), end_to_end_rtt, + end_to_end_rtt_observation_count)) { + *end_to_end_rtt = nqe::internal::InvalidRTT(); + fallback_success = false; + } + RecordFallbackSuccess("EndToEnd", fallback_success); } UpdateHttpRttUsingAllRttValues(http_rtt, *transport_rtt, *end_to_end_rtt); @@ -1075,7 +1163,17 @@ void NetworkQualityEstimator::AddAndNotifyObserversOfRTT( observation.GetObservationCategories(); for (nqe::internal::ObservationCategory observation_category : observation_categories) { - rtt_ms_observations_[observation_category].AddObservation(observation); + auto evicted = + rtt_ms_observations_[observation_category].AddObservation(observation); + if (evicted) { + auto delta = base::TimeTicks::Now() - evicted->timestamp(); + base::UmaHistogramLongTimes100( + base::StrCat({"NQE.RTT.ObservationBufferLifeTime2.", + CategoryToString(observation_category)}), + delta); + base::UmaHistogramLongTimes100("NQE.RTT.ObservationBufferLifeTime2.All", + delta); + } } if (observation.source() == NETWORK_QUALITY_OBSERVATION_SOURCE_TCP || diff --git a/naiveproxy/src/net/nqe/network_quality_estimator.h b/naiveproxy/src/net/nqe/network_quality_estimator.h index 7a2fea609d..acb9b4379c 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator.h +++ b/naiveproxy/src/net/nqe/network_quality_estimator.h @@ -570,8 +570,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator // Minimum duration between two consecutive computations of effective // connection type. Set to non-zero value as a performance optimization. - const base::TimeDelta effective_connection_type_recomputation_interval_ = - base::Seconds(10); + const base::TimeDelta effective_connection_type_recomputation_interval_; // Time when the effective connection type was last computed. base::TimeTicks last_effective_connection_type_computation_; diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_params.cc b/naiveproxy/src/net/nqe/network_quality_estimator_params.cc index 027435aa54..5a3a250710 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_params.cc +++ b/naiveproxy/src/net/nqe/network_quality_estimator_params.cc @@ -13,6 +13,7 @@ #include "base/strings/string_number_conversions.h" #include "base/time/time.h" +#include "net/base/features.h" namespace net { @@ -479,6 +480,9 @@ NetworkQualityEstimatorParams::NetworkQualityEstimatorParams( params_, "add_default_platform_observations", "true") == "true"), + count_new_observations_received_compute_ect_( + features::kCountNewObservationsReceivedComputeEct.Get()), + observation_buffer_size_(features::kObservationBufferSize.Get()), socket_watchers_min_notification_interval_( base::Milliseconds(GetValueForVariationParam( params_, diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_params.h b/naiveproxy/src/net/nqe/network_quality_estimator_params.h index 44fa588d2d..d3735962bd 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_params.h +++ b/naiveproxy/src/net/nqe/network_quality_estimator_params.h @@ -221,11 +221,13 @@ class NET_EXPORT NetworkQualityEstimatorParams { // Number of observations received after which the effective connection type // should be recomputed. - size_t count_new_observations_received_compute_ect() const { return 50; } + size_t count_new_observations_received_compute_ect() const { + return count_new_observations_received_compute_ect_; + } // Maximum number of observations that can be held in a single // ObservationBuffer. - size_t observation_buffer_size() const { return 300; } + size_t observation_buffer_size() const { return observation_buffer_size_; } // Minimun interval between consecutive notifications from socket // watchers who live on the same thread as the network quality estimator. @@ -286,6 +288,8 @@ class NET_EXPORT NetworkQualityEstimatorParams { const base::TimeDelta hanging_request_min_duration_ = base::Milliseconds(3000); const bool add_default_platform_observations_; + const size_t count_new_observations_received_compute_ect_; + const size_t observation_buffer_size_; const base::TimeDelta socket_watchers_min_notification_interval_; const bool use_end_to_end_rtt_ = true; const double upper_bound_typical_kbps_multiplier_; diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_test_util.cc b/naiveproxy/src/net/nqe/network_quality_estimator_test_util.cc index ad00523a8c..edd44a2772 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_test_util.cc +++ b/naiveproxy/src/net/nqe/network_quality_estimator_test_util.cc @@ -51,8 +51,8 @@ TestNetworkQualityEstimator::TestNetworkQualityEstimator( : NetworkQualityEstimator( std::make_unique(variation_params), NetLog::Get()), - embedded_test_server_(base::FilePath(kTestFilePath)), - suppress_notifications_for_testing_(suppress_notifications_for_testing) { + suppress_notifications_for_testing_(suppress_notifications_for_testing), + embedded_test_server_(base::FilePath(kTestFilePath)) { SetUseLocalHostRequestsForTesting(allow_local_host_requests_for_tests); SetUseSmallResponsesForTesting(allow_smaller_responses_for_tests); } @@ -60,8 +60,8 @@ TestNetworkQualityEstimator::TestNetworkQualityEstimator( TestNetworkQualityEstimator::TestNetworkQualityEstimator( std::unique_ptr params) : NetworkQualityEstimator(std::move(params), NetLog::Get()), - embedded_test_server_(base::FilePath(kTestFilePath)), - suppress_notifications_for_testing_(false) {} + suppress_notifications_for_testing_(false), + embedded_test_server_(base::FilePath(kTestFilePath)) {} TestNetworkQualityEstimator::~TestNetworkQualityEstimator() = default; diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_test_util.h b/naiveproxy/src/net/nqe/network_quality_estimator_test_util.h index e2b3d8d139..351fbc32e9 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_test_util.h +++ b/naiveproxy/src/net/nqe/network_quality_estimator_test_util.h @@ -276,14 +276,18 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { // If set, GetRTTEstimateInternal() would return the set value. std::optional start_time_null_end_to_end_rtt_; - LocalHttpTestServer embedded_test_server_; - // If true, notifications are not sent to any of the observers. const bool suppress_notifications_for_testing_; size_t ping_rtt_received_count_ = 0; std::optional transport_rtt_observation_count_last_ect_computation_; + + // Destroy this first, since destroying the test server will wait (and run an + // event loop while waiting for the test server to stop on its task runner). + // While this loop is running, the estimator may receive posted tasks with new + // observations, which may potentially read and write other fields of `this`. + LocalHttpTestServer embedded_test_server_; }; } // namespace net diff --git a/naiveproxy/src/net/nqe/observation_buffer.cc b/naiveproxy/src/net/nqe/observation_buffer.cc index 1e14892132..11028fad8f 100644 --- a/naiveproxy/src/net/nqe/observation_buffer.cc +++ b/naiveproxy/src/net/nqe/observation_buffer.cc @@ -50,7 +50,8 @@ ObservationBuffer::ObservationBuffer(const ObservationBuffer& other) ObservationBuffer::~ObservationBuffer() = default; -void ObservationBuffer::AddObservation(const Observation& observation) { +std::optional ObservationBuffer::AddObservation( + const Observation& observation) { DCHECK_LE(observations_.size(), params_->observation_buffer_size()); // Observations must be in the non-decreasing order of the timestamps. @@ -61,12 +62,16 @@ void ObservationBuffer::AddObservation(const Observation& observation) { (observation.signal_strength() >= 0 && observation.signal_strength() <= 4)); + std::optional evicted_observation; // Evict the oldest element if the buffer is already full. - if (observations_.size() == params_->observation_buffer_size()) + if (observations_.size() == params_->observation_buffer_size()) { + evicted_observation = observations_.front(); observations_.pop_front(); + } observations_.push_back(observation); DCHECK_LE(observations_.size(), params_->observation_buffer_size()); + return evicted_observation; } std::optional ObservationBuffer::GetPercentile( diff --git a/naiveproxy/src/net/nqe/observation_buffer.h b/naiveproxy/src/net/nqe/observation_buffer.h index 5692c581e5..bd32b91223 100644 --- a/naiveproxy/src/net/nqe/observation_buffer.h +++ b/naiveproxy/src/net/nqe/observation_buffer.h @@ -55,7 +55,8 @@ class NET_EXPORT_PRIVATE ObservationBuffer { // Adds |observation| to the buffer. The oldest observation in the buffer // will be evicted to make room if the buffer is already full. - void AddObservation(const Observation& observation); + // In that case, an evicted observation will be returned. + std::optional AddObservation(const Observation& observation); // Returns the number of observations in this buffer. size_t Size() const { return static_cast(observations_.size()); } diff --git a/naiveproxy/src/net/ntlm/ntlm_buffer_reader.h b/naiveproxy/src/net/ntlm/ntlm_buffer_reader.h index 5c8dbb2b40..3c9f965d36 100644 --- a/naiveproxy/src/net/ntlm/ntlm_buffer_reader.h +++ b/naiveproxy/src/net/ntlm/ntlm_buffer_reader.h @@ -17,6 +17,7 @@ #include "base/check.h" #include "base/containers/span.h" +#include "base/memory/raw_span.h" #include "net/base/net_export.h" #include "net/ntlm/ntlm_constants.h" @@ -218,7 +219,7 @@ class NET_EXPORT_PRIVATE NtlmBufferReader { return *(GetBufferAtCursor()); } - base::span buffer_; + base::raw_span buffer_; size_t cursor_ = 0; }; diff --git a/naiveproxy/src/net/proxy_resolution/mock_proxy_resolver.cc b/naiveproxy/src/net/proxy_resolution/mock_proxy_resolver.cc index 5d4465108c..9134c8521d 100644 --- a/naiveproxy/src/net/proxy_resolution/mock_proxy_resolver.cc +++ b/naiveproxy/src/net/proxy_resolution/mock_proxy_resolver.cc @@ -8,6 +8,7 @@ #include #include "base/check.h" +#include "base/not_fatal_until.h" #include "base/ranges/algorithm.h" namespace net { @@ -77,7 +78,7 @@ void MockAsyncProxyResolver::AddCancelledJob(std::unique_ptr job) { void MockAsyncProxyResolver::RemovePendingJob(Job* job) { DCHECK(job); auto it = base::ranges::find(pending_jobs_, job); - DCHECK(it != pending_jobs_.end()); + CHECK(it != pending_jobs_.end(), base::NotFatalUntil::M130); pending_jobs_.erase(it); } @@ -157,7 +158,7 @@ int MockAsyncProxyResolverFactory::CreateProxyResolver( void MockAsyncProxyResolverFactory::RemovePendingRequest(Request* request) { auto it = base::ranges::find(pending_requests_, request); - DCHECK(it != pending_requests_.end()); + CHECK(it != pending_requests_.end(), base::NotFatalUntil::M130); pending_requests_.erase(it); } diff --git a/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.cc b/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.cc index 879e203eef..c48d161c94 100644 --- a/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.cc +++ b/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.cc @@ -62,8 +62,9 @@ void DhcpPacFileAdapterFetcher::Fetch( FROM_HERE, base::BindOnce(&DhcpPacFileAdapterFetcher::DhcpQuery::GetPacURLForAdapter, dhcp_query.get(), adapter_name), - base::BindOnce(&DhcpPacFileAdapterFetcher::OnDhcpQueryDone, AsWeakPtr(), - dhcp_query, traffic_annotation)); + base::BindOnce(&DhcpPacFileAdapterFetcher::OnDhcpQueryDone, + weak_ptr_factory_.GetWeakPtr(), dhcp_query, + traffic_annotation)); } void DhcpPacFileAdapterFetcher::Cancel() { diff --git a/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.h b/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.h index 43c34b2c91..a027eb9e4d 100644 --- a/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.h +++ b/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_adapter_fetcher_win.h @@ -32,8 +32,7 @@ class URLRequestContext; // For a given adapter, this class takes care of first doing a DHCP lookup // to get the PAC URL, then if there is one, trying to fetch it. -class NET_EXPORT_PRIVATE DhcpPacFileAdapterFetcher - : public base::SupportsWeakPtr { +class NET_EXPORT_PRIVATE DhcpPacFileAdapterFetcher { public: DhcpPacFileAdapterFetcher() = delete; @@ -196,6 +195,8 @@ class NET_EXPORT_PRIVATE DhcpPacFileAdapterFetcher const raw_ptr url_request_context_; THREAD_CHECKER(thread_checker_); + + base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace net diff --git a/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.cc b/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.cc index 5334077623..f66d09c4ae 100644 --- a/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.cc +++ b/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.cc @@ -304,7 +304,8 @@ int DhcpPacFileFetcherWin::Fetch( &DhcpPacFileFetcherWin::AdapterQuery::GetCandidateAdapterNames, last_query_.get()), base::BindOnce(&DhcpPacFileFetcherWin::OnGetCandidateAdapterNamesDone, - AsWeakPtr(), last_query_, traffic_annotation)); + weak_ptr_factory_.GetWeakPtr(), last_query_, + traffic_annotation)); return ERR_IO_PENDING; } diff --git a/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h b/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h index 0ae123076b..73a953f4a5 100644 --- a/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h +++ b/naiveproxy/src/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h @@ -32,9 +32,7 @@ class DhcpPacFileAdapterFetcher; class URLRequestContext; // Windows-specific implementation. -class NET_EXPORT_PRIVATE DhcpPacFileFetcherWin - : public DhcpPacFileFetcher, - public base::SupportsWeakPtr { +class NET_EXPORT_PRIVATE DhcpPacFileFetcherWin : public DhcpPacFileFetcher { public: DhcpPacFileFetcherWin() = delete; @@ -199,6 +197,8 @@ class NET_EXPORT_PRIVATE DhcpPacFileFetcherWin const scoped_refptr task_runner_; THREAD_CHECKER(thread_checker_); + + base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace net diff --git a/naiveproxy/src/net/proxy_resolution/win/proxy_config_service_win.cc b/naiveproxy/src/net/proxy_resolution/win/proxy_config_service_win.cc index ac85d298ff..8700badf6c 100644 --- a/naiveproxy/src/net/proxy_resolution/win/proxy_config_service_win.cc +++ b/naiveproxy/src/net/proxy_resolution/win/proxy_config_service_win.cc @@ -12,6 +12,7 @@ #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" #include "base/logging.h" +#include "base/not_fatal_until.h" #include "base/ranges/algorithm.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" @@ -130,7 +131,7 @@ void ProxyConfigServiceWin::OnObjectSignaled(base::win::RegKey* key) { // Figure out which registry key signalled this change. auto it = base::ranges::find(keys_to_watch_, key, &std::unique_ptr::get); - DCHECK(it != keys_to_watch_.end()); + CHECK(it != keys_to_watch_.end(), base::NotFatalUntil::M130); // Keep watching the registry key. if (!key->StartWatching( diff --git a/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.cc b/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.cc index b4cc447f1e..a93fdde411 100644 --- a/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.cc +++ b/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.cc @@ -17,7 +17,6 @@ #include "net/socket/next_proto.h" #include "net/spdy/spdy_http_utils.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "quic_http_stream.h" namespace net { @@ -110,7 +109,7 @@ void BidirectionalStreamQuicImpl::SendRequestHeaders() { int BidirectionalStreamQuicImpl::WriteHeaders() { DCHECK(!has_sent_headers_); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; HttpRequestInfo http_request_info; http_request_info.url = request_info_->url; http_request_info.method = request_info_->method; diff --git a/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.h b/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.h index f866bf7e33..8ca2b58cf2 100644 --- a/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.h +++ b/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.h @@ -17,7 +17,7 @@ #include "net/http/bidirectional_stream_impl.h" #include "net/quic/quic_chromium_client_session.h" #include "net/quic/quic_chromium_client_stream.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" namespace base { class OneShotTimer; @@ -99,8 +99,8 @@ class NET_EXPORT_PRIVATE BidirectionalStreamQuicImpl // received. LoadTimingInfo::ConnectTiming connect_timing_; - spdy::Http2HeaderBlock initial_headers_; - spdy::Http2HeaderBlock trailing_headers_; + quiche::HttpHeaderBlock initial_headers_; + quiche::HttpHeaderBlock trailing_headers_; // User provided read buffer for ReadData() response. scoped_refptr read_buffer_; diff --git a/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc b/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc index 0cdfb9eda2..3cd58707ad 100644 --- a/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc +++ b/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc @@ -28,8 +28,6 @@ ProofSourceChromium::~ProofSourceChromium() = default; bool ProofSourceChromium::Initialize(const base::FilePath& cert_path, const base::FilePath& key_path, const base::FilePath& sct_path) { - crypto::EnsureOpenSSLInit(); - std::string cert_data; if (!base::ReadFileToString(cert_path, &cert_data)) { DLOG(FATAL) << "Unable to read certificates."; diff --git a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc index d6b054b800..80c9151188 100644 --- a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc +++ b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc @@ -684,7 +684,7 @@ void DedicatedWebTransportHttp3Client::OnSettingsReceived() { } void DedicatedWebTransportHttp3Client::OnHeadersComplete( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { http_response_info_ = std::make_unique(); const int rv = SpdyHeadersToHttpResponse(headers, http_response_info_.get()); if (rv != OK) { @@ -735,7 +735,7 @@ int DedicatedWebTransportHttp3Client::DoSendRequest() { return ERR_QUIC_PROTOCOL_ERROR; } - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; DCHECK_EQ(url_.scheme(), url::kHttpsScheme); headers[":scheme"] = url_.scheme(); headers[":method"] = "CONNECT"; diff --git a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.h b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.h index 120f2bb3b3..23d07c2cfc 100644 --- a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.h +++ b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.h @@ -22,6 +22,7 @@ #include "net/quic/web_transport_client.h" #include "net/quic/web_transport_error.h" #include "net/socket/client_socket_factory.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_client_config.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/web_transport_fingerprint_proof_verifier.h" #include "net/third_party/quiche/src/quiche/quic/core/deterministic_connection_id_generator.h" @@ -66,7 +67,7 @@ class NET_EXPORT DedicatedWebTransportHttp3Client quic::WebTransportSession* session() override; void OnSettingsReceived(); - void OnHeadersComplete(const spdy::Http2HeaderBlock& headers); + void OnHeadersComplete(const quiche::HttpHeaderBlock& headers); void OnConnectStreamWriteSideInDataRecvdState(); void OnConnectStreamAborted(); void OnConnectStreamDeleted(); diff --git a/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.cc b/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.cc index b3dec9a6c0..a03acb2ec2 100644 --- a/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.cc +++ b/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.cc @@ -12,31 +12,33 @@ #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h" QuicFlagSaverImpl::QuicFlagSaverImpl() { -#define QUIC_FLAG(flag, value) saved_##flag##_ = FLAGS_##flag; -#include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + saved_##flag##_ = FLAGS_##flag; +#include "net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG(type, flag, ...) saved_##flag##_ = FLAGS_##flag; #include "net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h" #undef QUICHE_PROTOCOL_FLAG } QuicFlagSaverImpl::~QuicFlagSaverImpl() { -#define QUIC_FLAG(flag, value) FLAGS_##flag = saved_##flag##_; -#include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + FLAGS_##flag = saved_##flag##_; +#include "net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG(type, flag, ...) FLAGS_##flag = saved_##flag##_; #include "net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h" #undef QUICHE_PROTOCOL_FLAG } QuicFlagChecker::QuicFlagChecker() { -#define QUIC_FLAG(flag, value) \ - CHECK_EQ(value, FLAGS_##flag) \ +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + CHECK_EQ(external_value, FLAGS_##flag) \ << "Flag set to an unexpected value. A prior test is likely " \ << "setting a flag without using a QuicFlagSaver. Use QuicTest to " \ "avoid this issue."; -#include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#include "net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG_CHECK(type, flag, value) \ CHECK_EQ((type)value, FLAGS_##flag) \ diff --git a/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.h b/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.h index 55e403f4bc..2c3f388ad2 100644 --- a/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.h +++ b/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.h @@ -13,9 +13,10 @@ class QuicFlagSaverImpl { ~QuicFlagSaverImpl(); private: -#define QUIC_FLAG(flag, value) bool saved_##flag##_; -#include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + type saved_##flag##_; +#include "net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG(type, flag, ...) type saved_##flag##_; #include "net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h" #undef QUICHE_PROTOCOL_FLAG diff --git a/naiveproxy/src/net/quic/quic_chromium_client_session.cc b/naiveproxy/src/net/quic/quic_chromium_client_session.cc index 0f26aeb3b6..4387fa35be 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_session.cc +++ b/naiveproxy/src/net/quic/quic_chromium_client_session.cc @@ -62,6 +62,7 @@ #include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_info.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_stream_priority.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -414,6 +415,7 @@ void QuicChromiumClientSession::Handle::OnSessionClosed( quic::ParsedQuicVersion quic_version, int net_error, quic::QuicErrorCode quic_error, + quic::ConnectionCloseSource source, bool port_migration_detected, bool quic_connection_migration_attempted, bool quic_connection_migration_successful, @@ -425,6 +427,7 @@ void QuicChromiumClientSession::Handle::OnSessionClosed( quic_connection_migration_successful_ = quic_connection_migration_successful; net_error_ = net_error; quic_error_ = quic_error; + source_ = source; quic_version_ = quic_version; connect_timing_ = connect_timing; was_ever_used_ = was_ever_used; @@ -454,6 +457,7 @@ void QuicChromiumClientSession::Handle::PopulateNetErrorDetails( } else { details->quic_port_migration_detected = port_migration_detected_; details->quic_connection_error = quic_error_; + details->source = source_; details->quic_connection_migration_attempted = quic_connection_migration_attempted_; details->quic_connection_migration_successful = @@ -491,7 +495,6 @@ int QuicChromiumClientSession::Handle::RequestStream( const NetworkTrafficAnnotationTag& traffic_annotation) { DCHECK(!stream_request_); - // TODO(crbug.com/41491379): Add a regression test. if (!session_ || session_->going_away_) { return ERR_CONNECTION_CLOSED; } @@ -1128,7 +1131,7 @@ void QuicChromiumClientSession::Initialize() { size_t QuicChromiumClientSession::WriteHeadersOnHeadersStream( quic::QuicStreamId id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, bool fin, const spdy::SpdyStreamPrecedence& precedence, quiche::QuicheReferenceCountedPointer @@ -1179,7 +1182,7 @@ void QuicChromiumClientSession::OnAcceptChFrameReceivedViaAlps( void QuicChromiumClientSession::AddHandle(Handle* handle) { if (going_away_) { handle->OnSessionClosed(connection()->version(), ERR_UNEXPECTED, error(), - port_migration_detected_, + source_, port_migration_detected_, quic_connection_migration_attempted_, quic_connection_migration_successful_, GetConnectTiming(), WasConnectionEverUsed()); @@ -1329,8 +1332,8 @@ QuicChromiumClientSession::CreateOutgoingReliableStreamImpl( const NetworkTrafficAnnotationTag& traffic_annotation) { DCHECK(connection()->connected()); QuicChromiumClientStream* stream = new QuicChromiumClientStream( - GetNextOutgoingBidirectionalStreamId(), this, quic::BIDIRECTIONAL, - net_log_, traffic_annotation); + GetNextOutgoingBidirectionalStreamId(), this, server_id(), + quic::BIDIRECTIONAL, net_log_, traffic_annotation); ActivateStream(base::WrapUnique(stream)); ++num_total_streams_; UMA_HISTOGRAM_COUNTS_1M("Net.QuicSession.NumOpenStreams", @@ -1545,7 +1548,8 @@ QuicChromiumClientSession::CreateIncomingReliableStreamImpl( DCHECK(connection()->connected()); QuicChromiumClientStream* stream = new QuicChromiumClientStream( - id, this, quic::READ_UNIDIRECTIONAL, net_log_, traffic_annotation); + id, this, server_id(), quic::READ_UNIDIRECTIONAL, net_log_, + traffic_annotation); ActivateStream(base::WrapUnique(stream)); ++num_total_streams_; return stream; @@ -1557,8 +1561,8 @@ QuicChromiumClientSession::CreateIncomingReliableStreamImpl( const NetworkTrafficAnnotationTag& traffic_annotation) { DCHECK(connection()->connected()); - QuicChromiumClientStream* stream = - new QuicChromiumClientStream(pending, this, net_log_, traffic_annotation); + QuicChromiumClientStream* stream = new QuicChromiumClientStream( + pending, this, server_id(), net_log_, traffic_annotation); ActivateStream(base::WrapUnique(stream)); ++num_total_streams_; return stream; @@ -1770,6 +1774,7 @@ void QuicChromiumClientSession::OnConnectionClosed( quic::ConnectionCloseSource source) { DCHECK(!connection()->connected()); logger_->OnConnectionClosed(frame, source); + source_ = source; UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumDefaultPathDegrading", connection()->GetStats().num_path_degrading); @@ -2315,6 +2320,11 @@ void QuicChromiumClientSession::OnPortMigrationProbeSucceeded( DCHECK(writer); DCHECK(reader); + // Writer must be destroyed before reader, since it points to the socket owned + // by reader. C++ doesn't have any guarantees about destruction order of + // arguments. + std::unique_ptr writer_moved = std::move(writer); + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CONNECTIVITY_PROBING_FINISHED, [&] { return NetLogProbingResultParams(network, &peer_address, @@ -2329,7 +2339,7 @@ void QuicChromiumClientSession::OnPortMigrationProbeSucceeded( // that was used for probing. static_cast(connection()->writer()) ->set_delegate(nullptr); - writer->set_delegate(this); + writer_moved->set_delegate(this); if (!migrate_idle_session_ && !HasActiveRequestStreams()) { // If idle sessions won't be migrated, close the connection. @@ -2347,7 +2357,7 @@ void QuicChromiumClientSession::OnPortMigrationProbeSucceeded( // Migrate to the probed socket immediately: socket, writer and reader will // be acquired by connection and used as default on success. if (!MigrateToSocket(self_address, peer_address, std::move(reader), - std::move(writer))) { + std::move(writer_moved))) { LogMigrateToSocketStatus(false); net_log_.AddEvent( NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE_AFTER_PROBING); @@ -2451,6 +2461,11 @@ void QuicChromiumClientSession::OnServerPreferredAddressProbeSucceeded( const quic::QuicSocketAddress& self_address, std::unique_ptr writer, std::unique_ptr reader) { + // Writer must be destroyed before reader, since it points to the socket owned + // by reader. C++ doesn't have any guarantees about destruction order of + // arguments. + std::unique_ptr writer_moved = std::move(writer); + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CONNECTIVITY_PROBING_FINISHED, [&] { return NetLogProbingResultParams(network, &peer_address, @@ -2466,12 +2481,12 @@ void QuicChromiumClientSession::OnServerPreferredAddressProbeSucceeded( // that was used for probing. static_cast(connection()->writer()) ->set_delegate(nullptr); - writer->set_delegate(this); + writer_moved->set_delegate(this); // Migrate to the probed socket immediately: socket, writer and reader will // be acquired by connection and used as default on success. if (!MigrateToSocket(self_address, peer_address, std::move(reader), - std::move(writer))) { + std::move(writer_moved))) { LogMigrateToSocketStatus(false); net_log_.AddEvent( NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE_AFTER_PROBING); @@ -2927,7 +2942,7 @@ void QuicChromiumClientSession::CloseAllHandles(int net_error) { Handle* handle = *handles_.begin(); handles_.erase(handle); handle->OnSessionClosed(connection()->version(), net_error, error(), - port_migration_detected_, + source_, port_migration_detected_, quic_connection_migration_attempted_, quic_connection_migration_successful_, GetConnectTiming(), WasConnectionEverUsed()); @@ -3855,9 +3870,14 @@ bool QuicChromiumClientSession::MigrateToSocket( const quic::QuicSocketAddress& peer_address, std::unique_ptr reader, std::unique_ptr writer) { + // Writer must be destroyed before reader, since it points to the socket owned + // by reader. C++ doesn't have any guarantees about destruction order of + // arguments. + std::unique_ptr writer_moved = std::move(writer); + // Sessions carried via a proxy should never migrate, and that is ensured // elsewhere (for each possible migration trigger). - DCHECK(session_key_.proxy_chain().is_direct()); + DUMP_WILL_BE_CHECK(session_key_.proxy_chain().is_direct()); // TODO(zhongyi): figure out whether we want to limit the number of // connection migrations for v2, which includes migration on platform signals, @@ -3866,11 +3886,6 @@ bool QuicChromiumClientSession::MigrateToSocket( packet_readers_.size() >= kMaxReadersPerQuicSession) { HistogramAndLogMigrationFailure(MIGRATION_STATUS_TOO_MANY_CHANGES, connection_id(), "Too many changes"); - // Must destroy `writer` before `reader`, as `writer` references the socket - // owned by `reader`. Destruction order of parameters is apparently not - // specified by the C++ standard, but Clang looks to destroy arguments from - // first to last. - writer.reset(); return false; } @@ -3878,8 +3893,8 @@ bool QuicChromiumClientSession::MigrateToSocket( // Force the writer to be blocked to prevent it being used until // WriteToNewSocket completes. DVLOG(1) << "Force blocking the packet writer"; - writer->set_force_write_blocked(true); - if (!MigratePath(self_address, peer_address, writer.release(), + writer_moved->set_force_write_blocked(true); + if (!MigratePath(self_address, peer_address, writer_moved.release(), /*owns_writer=*/true)) { HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_UNUSED_CONNECTION_ID, connection_id(), @@ -3900,6 +3915,7 @@ void QuicChromiumClientSession::PopulateNetErrorDetails( NetErrorDetails* details) const { details->quic_port_migration_detected = port_migration_detected_; details->quic_connection_error = error(); + details->source = source_; details->quic_connection_migration_attempted = quic_connection_migration_attempted_; details->quic_connection_migration_successful = diff --git a/naiveproxy/src/net/quic/quic_chromium_client_session.h b/naiveproxy/src/net/quic/quic_chromium_client_session.h index 68efc8a87f..5d9b31fe8c 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_session.h +++ b/naiveproxy/src/net/quic/quic_chromium_client_session.h @@ -46,6 +46,7 @@ #include "net/socket/socket_performance_watcher.h" #include "net/spdy/http2_priority_dependencies.h" #include "net/spdy/multiplexed_session.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_packet_writer.h" @@ -53,6 +54,7 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_path_validator.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_time.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/origin.h" #include "url/scheme_host_port.h" @@ -333,6 +335,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession void OnSessionClosed(quic::ParsedQuicVersion quic_version, int net_error, quic::QuicErrorCode quic_error, + quic::ConnectionCloseSource source, bool port_migration_detected, bool quic_connection_migration_attempted, bool quic_connection_migration_successful, @@ -359,6 +362,8 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession bool was_handshake_confirmed_; int net_error_ = OK; quic::QuicErrorCode quic_error_ = quic::QUIC_NO_ERROR; + quic::ConnectionCloseSource source_ = + quic::ConnectionCloseSource::FROM_SELF; bool port_migration_detected_ = false; bool quic_connection_migration_attempted_ = false; bool quic_connection_migration_successful_ = false; @@ -701,7 +706,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession // quic::QuicSpdySession methods: size_t WriteHeadersOnHeadersStream( quic::QuicStreamId id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, bool fin, const spdy::SpdyStreamPrecedence& precedence, quiche::QuicheReferenceCountedPointer @@ -799,8 +804,8 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession // Returns true if the stream factory disables gQUIC 0-RTT. bool gquic_zero_rtt_disabled() const; - // Returns a Handle to this session. - std::unique_ptr CreateHandle( + // Returns a Handle to this session. Virtual for testing. + virtual std::unique_ptr CreateHandle( url::SchemeHostPort destination); // Returns the number of client hello messages that have been sent on the @@ -919,6 +924,8 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession const std::set& GetDnsAliasesForSessionKey( const QuicSessionKey& key) const; + void SetGoingAwayForTesting(bool going_away) { going_away_ = going_away; } + protected: // quic::QuicSession methods: bool ShouldCreateIncomingStream(quic::QuicStreamId id) override; @@ -1113,6 +1120,8 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession // True when the session is going away, and streams may no longer be created // on this session. Existing stream will continue to be processed. bool going_away_ = false; + // Connection close source + quic::ConnectionCloseSource source_ = quic::ConnectionCloseSource::FROM_SELF; // True when the session receives a go away from server due to port migration. bool port_migration_detected_ = false; bool quic_connection_migration_attempted_ = false; diff --git a/naiveproxy/src/net/quic/quic_chromium_client_stream.cc b/naiveproxy/src/net/quic/quic_chromium_client_stream.cc index f1f4fb695d..0b9bb4abe9 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_stream.cc +++ b/naiveproxy/src/net/quic/quic_chromium_client_stream.cc @@ -14,9 +14,11 @@ #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" +#include "base/not_fatal_until.h" #include "base/task/single_thread_task_runner.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" +#include "net/base/url_util.h" #include "net/http/http_status_code.h" #include "net/log/net_log_event_type.h" #include "net/quic/quic_chromium_client_session.h" @@ -178,7 +180,7 @@ void QuicChromiumClientStream::Handle::InvokeCallbacksOnClose(int error) { } int QuicChromiumClientStream::Handle::ReadInitialHeaders( - spdy::Http2HeaderBlock* header_block, + quiche::HttpHeaderBlock* header_block, CompletionOnceCallback callback) { ScopedBoolSaver saver(&may_invoke_callbacks_, false); if (!stream_) @@ -230,7 +232,7 @@ int QuicChromiumClientStream::Handle::ReadBody( } int QuicChromiumClientStream::Handle::ReadTrailingHeaders( - spdy::Http2HeaderBlock* header_block, + quiche::HttpHeaderBlock* header_block, CompletionOnceCallback callback) { ScopedBoolSaver saver(&may_invoke_callbacks_, false); if (!stream_) @@ -246,7 +248,7 @@ int QuicChromiumClientStream::Handle::ReadTrailingHeaders( } int QuicChromiumClientStream::Handle::WriteHeaders( - spdy::Http2HeaderBlock header_block, + quiche::HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_notifier_delegate) { @@ -544,22 +546,26 @@ QuicChromiumClientStream::Handle::GetGuaranteedLargestMessagePayload() const { QuicChromiumClientStream::QuicChromiumClientStream( quic::QuicStreamId id, quic::QuicSpdyClientSessionBase* session, + quic::QuicServerId server_id, quic::StreamType type, const NetLogWithSource& net_log, const NetworkTrafficAnnotationTag& traffic_annotation) : quic::QuicSpdyStream(id, session, type), net_log_(net_log), session_(session), + server_id_(std::move(server_id)), quic_version_(session->connection()->transport_version()) {} QuicChromiumClientStream::QuicChromiumClientStream( quic::PendingStream* pending, quic::QuicSpdyClientSessionBase* session, + quic::QuicServerId server_id, const NetLogWithSource& net_log, const NetworkTrafficAnnotationTag& traffic_annotation) : quic::QuicSpdyStream(pending, session), net_log_(net_log), session_(session), + server_id_(std::move(server_id)), quic_version_(session->connection()->transport_version()) {} QuicChromiumClientStream::~QuicChromiumClientStream() { @@ -574,7 +580,19 @@ void QuicChromiumClientStream::OnInitialHeadersComplete( DCHECK(!initial_headers_arrived_); quic::QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list); - spdy::Http2HeaderBlock header_block; + if (header_decoding_delay().has_value()) { + const int64_t delay_in_milliseconds = + header_decoding_delay()->ToMilliseconds(); + base::UmaHistogramTimes("Net.QuicChromiumClientStream.HeaderDecodingDelay", + base::Milliseconds(delay_in_milliseconds)); + if (IsGoogleHost(server_id_.host())) { + base::UmaHistogramTimes( + "Net.QuicChromiumClientStream.HeaderDecodingDelayGoogle", + base::Milliseconds(delay_in_milliseconds)); + } + } + + quiche::HttpHeaderBlock header_block; int64_t length = -1; if (!quic::SpdyUtils::CopyAndValidateHeaders(header_list, &length, &header_block)) { @@ -675,13 +693,13 @@ void QuicChromiumClientStream::OnCanWrite() { } size_t QuicChromiumClientStream::WriteHeaders( - spdy::Http2HeaderBlock header_block, + quiche::HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_listener) { if (!session()->OneRttKeysAvailable()) { auto entry = header_block.find(":method"); - DCHECK(entry != header_block.end()); + CHECK(entry != header_block.end(), base::NotFatalUntil::M130); DCHECK( entry->second != "POST" || (handle_ != nullptr && handle_->GetRequestIdempotency() == IDEMPOTENT)); @@ -814,7 +832,7 @@ void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable() { } int QuicChromiumClientStream::DeliverEarlyHints( - spdy::Http2HeaderBlock* headers) { + quiche::HttpHeaderBlock* headers) { if (early_hints_.empty()) { return ERR_IO_PENDING; } @@ -838,7 +856,7 @@ int QuicChromiumClientStream::DeliverEarlyHints( } int QuicChromiumClientStream::DeliverInitialHeaders( - spdy::Http2HeaderBlock* headers) { + quiche::HttpHeaderBlock* headers) { if (!initial_headers_arrived_) { return ERR_IO_PENDING; } @@ -861,7 +879,7 @@ int QuicChromiumClientStream::DeliverInitialHeaders( } bool QuicChromiumClientStream::DeliverTrailingHeaders( - spdy::Http2HeaderBlock* headers, + quiche::HttpHeaderBlock* headers, int* frame_len) { if (trailing_headers_frame_len_ == 0) { return false; diff --git a/naiveproxy/src/net/quic/quic_chromium_client_stream.h b/naiveproxy/src/net/quic/quic_chromium_client_stream.h index e88b85bd13..4720afee6c 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_stream.h +++ b/naiveproxy/src/net/quic/quic_chromium_client_stream.h @@ -27,8 +27,9 @@ #include "net/http/http_response_info.h" #include "net/http/http_stream.h" #include "net/log/net_log_with_source.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace quic { @@ -58,7 +59,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream // asynchronously when the headers arrive. // TODO(rch): Invoke |callback| when there is a stream or connection error // instead of calling OnClose() or OnError(). - int ReadInitialHeaders(spdy::Http2HeaderBlock* header_block, + int ReadInitialHeaders(quiche::HttpHeaderBlock* header_block, CompletionOnceCallback callback); // Reads at most |buffer_len| bytes of body into |buffer| and returns the @@ -76,7 +77,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream // the headers arrive. // TODO(rch): Invoke |callback| when there is a stream or connection error // instead of calling OnClose() or OnError(). - int ReadTrailingHeaders(spdy::Http2HeaderBlock* header_block, + int ReadTrailingHeaders(quiche::HttpHeaderBlock* header_block, CompletionOnceCallback callback); // Writes |header_block| to the peer. Closes the write side if |fin| is @@ -85,7 +86,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream // an error writing the headers, or the number of bytes written on // success. Will not return ERR_IO_PENDING. int WriteHeaders( - spdy::Http2HeaderBlock header_block, + quiche::HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_notifier_delegate); @@ -204,7 +205,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream // Callback to be invoked when ReadInitialHeaders completes asynchronously. CompletionOnceCallback read_headers_callback_; // Provided by the owner of this handle when ReadInitialHeaders is called. - raw_ptr read_headers_buffer_ = nullptr; + raw_ptr read_headers_buffer_ = nullptr; // Callback to be invoked when ReadBody completes asynchronously. CompletionOnceCallback read_body_callback_; @@ -244,12 +245,14 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream QuicChromiumClientStream( quic::QuicStreamId id, quic::QuicSpdyClientSessionBase* session, + quic::QuicServerId server_id, quic::StreamType type, const NetLogWithSource& net_log, const NetworkTrafficAnnotationTag& traffic_annotation); QuicChromiumClientStream( quic::PendingStream* pending, quic::QuicSpdyClientSessionBase* session, + quic::QuicServerId server_id, const NetLogWithSource& net_log, const NetworkTrafficAnnotationTag& traffic_annotation); @@ -271,7 +274,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream void OnClose() override; void OnCanWrite() override; size_t WriteHeaders( - spdy::Http2HeaderBlock header_block, + quiche::HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_listener) override; @@ -324,11 +327,11 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream // True if this stream is the first data stream created on this session. bool IsFirstStream(); - int DeliverEarlyHints(spdy::Http2HeaderBlock* header_block); + int DeliverEarlyHints(quiche::HttpHeaderBlock* header_block); - int DeliverInitialHeaders(spdy::Http2HeaderBlock* header_block); + int DeliverInitialHeaders(quiche::HttpHeaderBlock* header_block); - bool DeliverTrailingHeaders(spdy::Http2HeaderBlock* header_block, + bool DeliverTrailingHeaders(quiche::HttpHeaderBlock* header_block, int* frame_len); static constexpr char kHttp3DatagramDroppedHistogram[] = @@ -353,6 +356,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream bool initial_headers_sent_ = false; raw_ptr session_; + const quic::QuicServerId server_id_; quic::QuicTransportVersion quic_version_; // Set to false if this stream should not be migrated to a cellular network @@ -365,7 +369,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream // the handle. bool headers_delivered_ = false; // Stores the initial header until they are delivered to the handle. - spdy::Http2HeaderBlock initial_headers_; + quiche::HttpHeaderBlock initial_headers_; // Length of the HEADERS frame containing initial headers. size_t initial_headers_frame_len_ = 0; @@ -373,14 +377,14 @@ class NET_EXPORT_PRIVATE QuicChromiumClientStream size_t trailing_headers_frame_len_ = 0; struct EarlyHints { - EarlyHints(spdy::Http2HeaderBlock headers, size_t frame_len) + EarlyHints(quiche::HttpHeaderBlock headers, size_t frame_len) : headers(std::move(headers)), frame_len(frame_len) {} EarlyHints(EarlyHints&& other) = default; EarlyHints& operator=(EarlyHints&& other) = default; EarlyHints(const EarlyHints& other) = delete; EarlyHints& operator=(const EarlyHints& other) = delete; - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; size_t frame_len = 0; }; base::circular_deque early_hints_; diff --git a/naiveproxy/src/net/quic/quic_http3_logger.cc b/naiveproxy/src/net/quic/quic_http3_logger.cc index a72376b51a..b127311f6b 100644 --- a/naiveproxy/src/net/quic/quic_http3_logger.cc +++ b/naiveproxy/src/net/quic/quic_http3_logger.cc @@ -297,7 +297,7 @@ void QuicHttp3Logger::OnDataFrameSent(quic::QuicStreamId stream_id, void QuicHttp3Logger::OnHeadersFrameSent( quic::QuicStreamId stream_id, - const spdy::Http2HeaderBlock& header_block) { + const quiche::HttpHeaderBlock& header_block) { if (!net_log_.IsCapturing()) { return; } @@ -308,7 +308,7 @@ void QuicHttp3Logger::OnHeadersFrameSent( .Set("stream_id", NetLogNumberValue(static_cast(stream_id))) .Set("headers", - ElideHttp2HeaderBlockForNetLog(header_block, capture_mode)); + ElideHttpHeaderBlockForNetLog(header_block, capture_mode)); }); } diff --git a/naiveproxy/src/net/quic/quic_http3_logger.h b/naiveproxy/src/net/quic/quic_http3_logger.h index 3c54639f11..889fa783e8 100644 --- a/naiveproxy/src/net/quic/quic_http3_logger.h +++ b/naiveproxy/src/net/quic/quic_http3_logger.h @@ -9,6 +9,7 @@ #include "base/timer/timer.h" #include "net/log/net_log_with_source.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h" namespace net { @@ -58,7 +59,7 @@ class NET_EXPORT_PRIVATE QuicHttp3Logger : public quic::Http3DebugVisitor { void OnDataFrameSent(quic::QuicStreamId stream_id, quic::QuicByteCount payload_length) override; void OnHeadersFrameSent(quic::QuicStreamId stream_id, - const spdy::Http2HeaderBlock& header_block) override; + const quiche::HttpHeaderBlock& header_block) override; private: NetLogWithSource net_log_; diff --git a/naiveproxy/src/net/quic/quic_http_stream.cc b/naiveproxy/src/net/quic/quic_http_stream.cc index 9ff89e632a..dba25acb40 100644 --- a/naiveproxy/src/net/quic/quic_http_stream.cc +++ b/naiveproxy/src/net/quic/quic_http_stream.cc @@ -532,7 +532,7 @@ int QuicHttpStream::DoSendHeaders() { headers_bytes_sent_ += rv; } - request_headers_ = spdy::Http2HeaderBlock(); + request_headers_ = quiche::HttpHeaderBlock(); return rv; } @@ -608,7 +608,7 @@ int QuicHttpStream::DoSendBodyComplete(int rv) { } int QuicHttpStream::ProcessResponseHeaders( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { const int rv = SpdyHeadersToHttpResponse(headers, response_info_); base::UmaHistogramBoolean("Net.QuicHttpStream.ProcessResponseHeaderSuccess", rv == OK); diff --git a/naiveproxy/src/net/quic/quic_http_stream.h b/naiveproxy/src/net/quic/quic_http_stream.h index d5cc13e355..04f9b5ab42 100644 --- a/naiveproxy/src/net/quic/quic_http_stream.h +++ b/naiveproxy/src/net/quic/quic_http_stream.h @@ -26,6 +26,7 @@ #include "net/quic/quic_chromium_client_session.h" #include "net/quic/quic_chromium_client_stream.h" #include "net/spdy/multiplexed_http_stream.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h" namespace net { @@ -112,7 +113,7 @@ class NET_EXPORT_PRIVATE QuicHttpStream : public MultiplexedHttpStream { int DoSendBodyComplete(int rv); void OnReadResponseHeadersComplete(int rv); - int ProcessResponseHeaders(const spdy::Http2HeaderBlock& headers); + int ProcessResponseHeaders(const quiche::HttpHeaderBlock& headers); void ReadTrailingHeaders(); void OnReadTrailingHeadersComplete(int rv); @@ -178,12 +179,12 @@ class NET_EXPORT_PRIVATE QuicHttpStream : public MultiplexedHttpStream { int response_status_ = ERR_UNEXPECTED; // Serialized request headers. - spdy::Http2HeaderBlock request_headers_; + quiche::HttpHeaderBlock request_headers_; - spdy::Http2HeaderBlock response_header_block_; + quiche::HttpHeaderBlock response_header_block_; bool response_headers_received_ = false; - spdy::Http2HeaderBlock trailing_header_block_; + quiche::HttpHeaderBlock trailing_header_block_; bool trailing_headers_received_ = false; // Number of bytes received by the headers stream on behalf of this stream. diff --git a/naiveproxy/src/net/quic/quic_http_utils.cc b/naiveproxy/src/net/quic/quic_http_utils.cc index 740028cdbe..62fb89f312 100644 --- a/naiveproxy/src/net/quic/quic_http_utils.cc +++ b/naiveproxy/src/net/quic/quic_http_utils.cc @@ -26,11 +26,12 @@ RequestPriority ConvertQuicPriorityToRequestPriority( : static_cast(HIGHEST - priority); } -base::Value::Dict QuicRequestNetLogParams(quic::QuicStreamId stream_id, - const spdy::Http2HeaderBlock* headers, - quic::QuicStreamPriority priority, - NetLogCaptureMode capture_mode) { - base::Value::Dict dict = Http2HeaderBlockNetLogParams(headers, capture_mode); +base::Value::Dict QuicRequestNetLogParams( + quic::QuicStreamId stream_id, + const quiche::HttpHeaderBlock* headers, + quic::QuicStreamPriority priority, + NetLogCaptureMode capture_mode) { + base::Value::Dict dict = HttpHeaderBlockNetLogParams(headers, capture_mode); switch (priority.type()) { case quic::QuicPriorityType::kHttp: { auto http_priority = priority.http(); @@ -63,9 +64,9 @@ base::Value::Dict QuicRequestNetLogParams(quic::QuicStreamId stream_id, base::Value::Dict QuicResponseNetLogParams( quic::QuicStreamId stream_id, bool fin_received, - const spdy::Http2HeaderBlock* headers, + const quiche::HttpHeaderBlock* headers, NetLogCaptureMode capture_mode) { - base::Value::Dict dict = Http2HeaderBlockNetLogParams(headers, capture_mode); + base::Value::Dict dict = HttpHeaderBlockNetLogParams(headers, capture_mode); dict.Set("quic_stream_id", static_cast(stream_id)); dict.Set("fin", fin_received); return dict; diff --git a/naiveproxy/src/net/quic/quic_http_utils.h b/naiveproxy/src/net/quic/quic_http_utils.h index 5075098bf8..96984e139e 100644 --- a/naiveproxy/src/net/quic/quic_http_utils.h +++ b/naiveproxy/src/net/quic/quic_http_utils.h @@ -9,9 +9,9 @@ #include "net/base/net_export.h" #include "net/base/request_priority.h" #include "net/log/net_log_capture_mode.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_stream_priority.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" namespace net { @@ -24,19 +24,19 @@ NET_EXPORT_PRIVATE spdy::SpdyPriority ConvertRequestPriorityToQuicPriority( NET_EXPORT_PRIVATE RequestPriority ConvertQuicPriorityToRequestPriority(spdy::SpdyPriority priority); -// Converts a spdy::Http2HeaderBlock, stream_id and priority into NetLog event +// Converts a quiche::HttpHeaderBlock, stream_id and priority into NetLog event // parameters. NET_EXPORT base::Value::Dict QuicRequestNetLogParams( quic::QuicStreamId stream_id, - const spdy::Http2HeaderBlock* headers, + const quiche::HttpHeaderBlock* headers, quic::QuicStreamPriority priority, NetLogCaptureMode capture_mode); -// Converts a spdy::Http2HeaderBlock and stream into NetLog event parameters. +// Converts a quiche::HttpHeaderBlock and stream into NetLog event parameters. NET_EXPORT base::Value::Dict QuicResponseNetLogParams( quic::QuicStreamId stream_id, bool fin_received, - const spdy::Http2HeaderBlock* headers, + const quiche::HttpHeaderBlock* headers, NetLogCaptureMode capture_mode); } // namespace net diff --git a/naiveproxy/src/net/quic/quic_proxy_client_socket.cc b/naiveproxy/src/net/quic/quic_proxy_client_socket.cc index 1c7c9a1057..4a0f3cac45 100644 --- a/naiveproxy/src/net/quic/quic_proxy_client_socket.cc +++ b/naiveproxy/src/net/quic/quic_proxy_client_socket.cc @@ -375,7 +375,7 @@ int QuicProxyClientSocket::DoSendRequest() { NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, request_line, &request_.extra_headers); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; CreateSpdyHeadersFromHttpRequest(request_, std::nullopt, request_.extra_headers, &headers); @@ -456,7 +456,7 @@ int QuicProxyClientSocket::DoReadReplyComplete(int result) { } void QuicProxyClientSocket::OnReadResponseHeadersComplete(int result) { - // Convert the now-populated spdy::Http2HeaderBlock to HttpResponseInfo + // Convert the now-populated quiche::HttpHeaderBlock to HttpResponseInfo if (use_fastopen_ && read_headers_pending_) { if (next_state_ == STATE_DISCONNECTED) return; @@ -472,7 +472,7 @@ void QuicProxyClientSocket::OnReadResponseHeadersComplete(int result) { } int QuicProxyClientSocket::ProcessResponseHeaders( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { if (SpdyHeadersToHttpResponse(headers, &response_) != OK) { DLOG(WARNING) << "Invalid headers"; return ERR_QUIC_PROTOCOL_ERROR; diff --git a/naiveproxy/src/net/quic/quic_proxy_client_socket.h b/naiveproxy/src/net/quic/quic_proxy_client_socket.h index 029015a7b1..8b4fd198f6 100644 --- a/naiveproxy/src/net/quic/quic_proxy_client_socket.h +++ b/naiveproxy/src/net/quic/quic_proxy_client_socket.h @@ -16,6 +16,7 @@ #include "net/quic/quic_chromium_client_session.h" #include "net/quic/quic_chromium_client_stream.h" #include "net/spdy/spdy_read_queue.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace net { @@ -97,7 +98,7 @@ class NET_EXPORT_PRIVATE QuicProxyClientSocket : public ProxyClientSocket { // Callback for stream_->ReadInitialHeaders() void OnReadResponseHeadersComplete(int result); - int ProcessResponseHeaders(const spdy::Http2HeaderBlock& headers); + int ProcessResponseHeaders(const quiche::HttpHeaderBlock& headers); int DoLoop(int last_io_result); int DoGenerateAuthToken(); @@ -130,7 +131,7 @@ class NET_EXPORT_PRIVATE QuicProxyClientSocket : public ProxyClientSocket { HttpRequestInfo request_; HttpResponseInfo response_; - spdy::Http2HeaderBlock response_header_block_; + quiche::HttpHeaderBlock response_header_block_; // The hostname and port of the endpoint. This is not necessarily the one // specified by the URL, due to Alternate-Protocol or fixed testing ports. diff --git a/naiveproxy/src/net/quic/quic_proxy_client_socket_test_base.cc b/naiveproxy/src/net/quic/quic_proxy_client_socket_test_base.cc index 1e85dde30f..0c2cd202ea 100644 --- a/naiveproxy/src/net/quic/quic_proxy_client_socket_test_base.cc +++ b/naiveproxy/src/net/quic/quic_proxy_client_socket_test_base.cc @@ -230,10 +230,10 @@ QuicProxyClientSocketTestBase::ConstructAckAndRstOnlyPacket( quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received) { - return client_maker_.MakeAckAndRstPacket( - packet_number, client_data_stream_id1_, error_code, largest_received, - smallest_received, - /*include_stop_sending_if_v99=*/false); + return client_maker_.Packet(packet_number++) + .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) + .AddRstStreamFrame(client_data_stream_id1_, error_code) + .Build(); } std::unique_ptr @@ -242,19 +242,21 @@ QuicProxyClientSocketTestBase::ConstructAckAndRstPacket( quic::QuicRstStreamErrorCode error_code, uint64_t largest_received, uint64_t smallest_received) { - return client_maker_.MakeAckAndRstPacket( - packet_number, client_data_stream_id1_, error_code, largest_received, - smallest_received, - /*include_stop_sending_if_v99=*/true); + return client_maker_.Packet(packet_number++) + .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) + .AddStopSendingFrame(client_data_stream_id1_, error_code) + .AddRstStreamFrame(client_data_stream_id1_, error_code) + .Build(); } std::unique_ptr QuicProxyClientSocketTestBase::ConstructRstPacket( uint64_t packet_number, quic::QuicRstStreamErrorCode error_code) { - return client_maker_.MakeRstPacket(packet_number, client_data_stream_id1_, - error_code, - /*include_stop_sending_if_v99=*/true); + return client_maker_.Packet(packet_number) + .AddStopSendingFrame(client_data_stream_id1_, error_code) + .AddRstStreamFrame(client_data_stream_id1_, error_code) + .Build(); } std::unique_ptr @@ -262,7 +264,7 @@ QuicProxyClientSocketTestBase::ConstructConnectRequestPacket( uint64_t packet_number, std::optional extra_headers, RequestPriority request_priority) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; PopulateConnectRequestIR(&block, extra_headers); return client_maker_.MakeRequestHeadersPacket( packet_number, client_data_stream_id1_, !kFin, @@ -275,7 +277,7 @@ QuicProxyClientSocketTestBase::ConstructConnectRequestPacketWithExtraHeaders( uint64_t packet_number, std::vector> extra_headers, RequestPriority request_priority) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[":method"] = "CONNECT"; block[":authority"] = HostPortPair::FromSchemeHostPort(destination_endpoint_).ToString(); @@ -292,7 +294,7 @@ std::unique_ptr QuicProxyClientSocketTestBase::ConstructConnectAuthRequestPacket( uint64_t packet_number) { RequestPriority request_priority = LOWEST; - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; PopulateConnectRequestIR(&block, /*extra_headers=*/std::nullopt); block["proxy-authorization"] = "Basic Zm9vOmJhcg=="; return client_maker_.MakeRequestHeadersPacket( @@ -304,14 +306,15 @@ QuicProxyClientSocketTestBase::ConstructConnectAuthRequestPacket( std::unique_ptr QuicProxyClientSocketTestBase::ConstructDataPacket(uint64_t packet_number, std::string_view data) { - return client_maker_.MakeDataPacket(packet_number, client_data_stream_id1_, - !kFin, data); + return client_maker_.Packet(packet_number) + .AddStreamFrame(client_data_stream_id1_, !kFin, data) + .Build(); } std::unique_ptr QuicProxyClientSocketTestBase::ConstructDatagramPacket(uint64_t packet_number, std::string_view data) { - return client_maker_.MakeDatagramPacket(packet_number, data); + return client_maker_.Packet(packet_number).AddMessageFrame(data).Build(); } std::unique_ptr @@ -339,8 +342,9 @@ std::unique_ptr QuicProxyClientSocketTestBase::ConstructAckPacket(uint64_t packet_number, uint64_t largest_received, uint64_t smallest_received) { - return client_maker_.MakeAckPacket(packet_number, largest_received, - smallest_received); + return client_maker_.Packet(packet_number) + .AddAckFrame(1, largest_received, smallest_received) + .Build(); } // Helper functions for constructing packets sent by the server @@ -349,32 +353,35 @@ std::unique_ptr QuicProxyClientSocketTestBase::ConstructServerRstPacket( uint64_t packet_number, quic::QuicRstStreamErrorCode error_code) { - return server_maker_.MakeRstPacket(packet_number, client_data_stream_id1_, - error_code, - /*include_stop_sending_if_v99=*/true); + return server_maker_.Packet(packet_number) + .AddStopSendingFrame(client_data_stream_id1_, error_code) + .AddRstStreamFrame(client_data_stream_id1_, error_code) + .Build(); } std::unique_ptr QuicProxyClientSocketTestBase::ConstructServerDataPacket( uint64_t packet_number, std::string_view data) { - return server_maker_.MakeDataPacket(packet_number, client_data_stream_id1_, - !kFin, data); + return server_maker_.Packet(packet_number) + .AddStreamFrame(client_data_stream_id1_, !kFin, data) + .Build(); } std::unique_ptr QuicProxyClientSocketTestBase::ConstructServerDatagramPacket( uint64_t packet_number, std::string_view data) { - return server_maker_.MakeDatagramPacket(packet_number, data); + return server_maker_.Packet(packet_number).AddMessageFrame(data).Build(); } std::unique_ptr QuicProxyClientSocketTestBase::ConstructServerDataFinPacket( uint64_t packet_number, std::string_view data) { - return server_maker_.MakeDataPacket(packet_number, client_data_stream_id1_, - kFin, data); + return server_maker_.Packet(packet_number) + .AddStreamFrame(client_data_stream_id1_, kFin, data) + .Build(); } std::unique_ptr @@ -383,7 +390,7 @@ QuicProxyClientSocketTestBase::ConstructServerConnectReplyPacket( bool fin, size_t* header_length, std::optional extra_headers) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[":status"] = "200"; if (extra_headers) { @@ -404,7 +411,7 @@ std::unique_ptr QuicProxyClientSocketTestBase:: uint64_t packet_number, bool fin, std::vector> extra_headers) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[":status"] = "200"; for (const auto& header : extra_headers) { block[header.first] = header.second; @@ -418,7 +425,7 @@ std::unique_ptr QuicProxyClientSocketTestBase::ConstructServerConnectAuthReplyPacket( uint64_t packet_number, bool fin) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[":status"] = "407"; block["proxy-authenticate"] = "Basic realm=\"MyRealm1\""; return server_maker_.MakeResponseHeadersPacket( @@ -429,7 +436,7 @@ std::unique_ptr QuicProxyClientSocketTestBase::ConstructServerConnectRedirectReplyPacket( uint64_t packet_number, bool fin) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[":status"] = "302"; block["location"] = kRedirectUrl; block["set-cookie"] = "foo=bar"; @@ -441,7 +448,7 @@ std::unique_ptr QuicProxyClientSocketTestBase::ConstructServerConnectErrorReplyPacket( uint64_t packet_number, bool fin) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[":status"] = "500"; return server_maker_.MakeResponseHeadersPacket( diff --git a/naiveproxy/src/net/quic/quic_proxy_client_socket_test_base.h b/naiveproxy/src/net/quic/quic_proxy_client_socket_test_base.h index d308a830c6..af37657980 100644 --- a/naiveproxy/src/net/quic/quic_proxy_client_socket_test_base.h +++ b/naiveproxy/src/net/quic/quic_proxy_client_socket_test_base.h @@ -43,6 +43,7 @@ #include "net/ssl/ssl_config_service_defaults.h" #include "net/test/test_data_directory.h" #include "net/test/test_with_task_environment.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/mock_clock.h" @@ -121,7 +122,7 @@ class QuicProxyClientSocketTestBase virtual void InitializeClientSocket() = 0; virtual void PopulateConnectRequestIR( - spdy::Http2HeaderBlock* block, + quiche::HttpHeaderBlock* block, std::optional extra_headers) = 0; std::unique_ptr ConstructSettingsPacket( diff --git a/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc index 730ed09da0..29547e679c 100644 --- a/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc +++ b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc @@ -412,7 +412,7 @@ int QuicProxyDatagramClientSocket::DoSendRequest() { NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, request_line, &request_.extra_headers); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; CreateSpdyHeadersFromHttpRequestForExtendedConnect( request_, /*priority=*/std::nullopt, "connect-udp", request_.extra_headers, &headers); @@ -485,7 +485,7 @@ int QuicProxyDatagramClientSocket::DoReadReplyComplete(int result) { } void QuicProxyDatagramClientSocket::OnReadResponseHeadersComplete(int result) { - // Convert the now-populated spdy::Http2HeaderBlock to HttpResponseInfo + // Convert the now-populated quiche::HttpHeaderBlock to HttpResponseInfo if (result > 0) { result = ProcessResponseHeaders(response_header_block_); } @@ -496,7 +496,7 @@ void QuicProxyDatagramClientSocket::OnReadResponseHeadersComplete(int result) { } int QuicProxyDatagramClientSocket::ProcessResponseHeaders( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { if (SpdyHeadersToHttpResponse(headers, &response_) != OK) { DLOG(WARNING) << "Invalid headers"; return ERR_QUIC_PROTOCOL_ERROR; diff --git a/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.h b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.h index 1fab270ba6..fe9714dba8 100644 --- a/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.h +++ b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.h @@ -19,6 +19,7 @@ #include "net/socket/datagram_client_socket.h" #include "net/socket/udp_socket.h" #include "net/spdy/spdy_http_utils.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/scheme_host_port.h" @@ -141,7 +142,7 @@ class NET_EXPORT_PRIVATE QuicProxyDatagramClientSocket // Callback for stream_->ReadInitialHeaders() void OnReadResponseHeadersComplete(int result); - int ProcessResponseHeaders(const spdy::Http2HeaderBlock& headers); + int ProcessResponseHeaders(const quiche::HttpHeaderBlock& headers); int DoLoop(int last_io_result); int DoSendRequest(); @@ -181,7 +182,7 @@ class NET_EXPORT_PRIVATE QuicProxyDatagramClientSocket HttpRequestInfo request_; HttpResponseInfo response_; - spdy::Http2HeaderBlock response_header_block_; + quiche::HttpHeaderBlock response_header_block_; // Local address of socket. IPEndPoint local_address_; diff --git a/naiveproxy/src/net/quic/quic_session_pool.cc b/naiveproxy/src/net/quic/quic_session_pool.cc index 4403c4859c..23aa9c90f2 100644 --- a/naiveproxy/src/net/quic/quic_session_pool.cc +++ b/naiveproxy/src/net/quic/quic_session_pool.cc @@ -19,6 +19,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" +#include "base/not_fatal_until.h" #include "base/numerics/safe_conversions.h" #include "base/ranges/algorithm.h" #include "base/strings/escape.h" @@ -41,6 +42,7 @@ #include "net/base/session_usage.h" #include "net/base/trace_constants.h" #include "net/base/tracing.h" +#include "net/base/url_util.h" #include "net/cert/cert_verifier.h" #include "net/dns/host_resolver.h" #include "net/dns/public/secure_dns_policy.h" @@ -94,6 +96,13 @@ enum InitialRttEstimateSource { INITIAL_RTT_SOURCE_MAX, }; +enum FindMatchingIpSessionResult { + MATCHING_IP_SESSION_FOUND, + CAN_POOL_BUT_DIFFERENT_IP, + CANNOT_POOL_WITH_EXISTING_SESSIONS, + FIND_MATCHING_IP_SESSION_RESULT_MAX +}; + std::string QuicPlatformNotificationToString( QuicPlatformNotification notification) { switch (notification) { @@ -133,6 +142,17 @@ void HistogramCreateSessionFailure(enum CreateSessionFailure error) { CREATION_ERROR_MAX); } +void HistogramFindMatchingIpSessionResult(FindMatchingIpSessionResult result, + std::string_view host) { + UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.FindMatchingIpSessionResult", + result, FIND_MATCHING_IP_SESSION_RESULT_MAX); + if (IsGoogleHost(host) && !host.ends_with(".googlevideo.com")) { + UMA_HISTOGRAM_ENUMERATION( + "Net.QuicSession.FindMatchingIpSessionResultGoogle", result, + FIND_MATCHING_IP_SESSION_RESULT_MAX); + } +} + void SetInitialRttEstimate(base::TimeDelta estimate, enum InitialRttEstimateSource source, quic::QuicConfig* config) { @@ -269,9 +289,14 @@ void QuicSessionRequest::ExpectOnHostResolution() { expect_on_host_resolution_ = true; } -void QuicSessionRequest::OnHostResolutionComplete(int rv) { +void QuicSessionRequest::OnHostResolutionComplete( + int rv, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time) { DCHECK(expect_on_host_resolution_); expect_on_host_resolution_ = false; + dns_resolution_start_time_ = dns_resolution_start_time; + dns_resolution_end_time_ = dns_resolution_end_time; if (!host_resolution_callback_.is_null()) { std::move(host_resolution_callback_).Run(rv); } @@ -591,7 +616,7 @@ int QuicSessionPool::RequestSession( } if (rv == OK) { auto it = active_sessions_.find(session_key); - DCHECK(it != active_sessions_.end()); + CHECK(it != active_sessions_.end(), base::NotFatalUntil::M130); if (it == active_sessions_.end()) { return ERR_QUIC_PROTOCOL_ERROR; } @@ -661,8 +686,9 @@ void QuicSessionPool::SetRequestPriority(QuicSessionRequest* request, void QuicSessionPool::CloseAllSessions(int error, quic::QuicErrorCode quic_error) { - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_POOL_CLOSE_ALL_SESSIONS); base::UmaHistogramSparse("Net.QuicSession.CloseAllSessionsError", -error); + size_t before_active_sessions_size = active_sessions_.size(); + size_t before_all_sessions_size = active_sessions_.size(); while (!active_sessions_.empty()) { size_t initial_size = active_sessions_.size(); active_sessions_.begin()->second->CloseSessionOnError( @@ -678,6 +704,21 @@ void QuicSessionPool::CloseAllSessions(int error, DCHECK_NE(initial_size, all_sessions_.size()); } DCHECK(all_sessions_.empty()); + // TODO(crbug.com/347984574): Remove before/after counts once we identified + // the cause. + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_POOL_CLOSE_ALL_SESSIONS, [&] { + base::Value::Dict dict; + dict.Set("net_error", error); + dict.Set("quic_error", quic::QuicErrorCodeToString(quic_error)); + dict.Set("before_active_sessions_size", + static_cast(before_active_sessions_size)); + dict.Set("before_all_sessions_size", + static_cast(before_all_sessions_size)); + dict.Set("after_active_sessions_size", + static_cast(active_sessions_.size())); + dict.Set("after_all_sessions_size", static_cast(all_sessions_.size())); + return dict; + }); } base::Value QuicSessionPool::QuicSessionPoolInfoToValue() const { @@ -1116,6 +1157,20 @@ const std::set& QuicSessionPool::GetDnsAliasesForSessionKey( return it->second; } +void QuicSessionPool::ActivateSessionForTesting( + const url::SchemeHostPort& destination, + QuicChromiumClientSession* session) { + all_sessions_.emplace(session, QuicSessionPool::QuicSessionAliasKey( + destination, session->quic_session_key())); + ActivateSession(all_sessions_[session], session, std::set()); +} + +void QuicSessionPool::DeactivateSessionForTesting( + QuicChromiumClientSession* session) { + OnSessionGoingAway(session); + all_sessions_.erase(session); +} + quic::ParsedQuicVersion QuicSessionPool::SelectQuicVersion( const quic::ParsedQuicVersion& known_quic_version, const ConnectionEndpointMetadata& metadata, @@ -1204,16 +1259,38 @@ bool QuicSessionPool::HasMatchingIpSession( } MapSessionToAliasKey(session, key, std::move(dns_aliases)); - + HistogramFindMatchingIpSessionResult(MATCHING_IP_SESSION_FOUND, + server_id.host()); return true; } } + + bool can_pool = false; + static constexpr uint32_t kMaxLoopCount = 200; + uint32_t loop_count = 0; + for (const auto& entry : active_sessions_) { + ++loop_count; + if (loop_count >= kMaxLoopCount) { + break; + } + if (entry.second->CanPool(server_id.host(), key.session_key())) { + can_pool = true; + break; + } + } + if (can_pool) { + HistogramFindMatchingIpSessionResult(CAN_POOL_BUT_DIFFERENT_IP, + server_id.host()); + } else { + HistogramFindMatchingIpSessionResult(CANNOT_POOL_WITH_EXISTING_SESSIONS, + server_id.host()); + } return false; } void QuicSessionPool::OnJobComplete(Job* job, int rv) { auto iter = active_jobs_.find(job->key().session_key()); - DCHECK(iter != active_jobs_.end()); + CHECK(iter != active_jobs_.end(), base::NotFatalUntil::M130); if (rv == OK) { if (!is_quic_known_to_work_on_current_network_) { set_is_quic_known_to_work_on_current_network(true); diff --git a/naiveproxy/src/net/quic/quic_session_pool.h b/naiveproxy/src/net/quic/quic_session_pool.h index f07a1469e0..dec332c7fb 100644 --- a/naiveproxy/src/net/quic/quic_session_pool.h +++ b/naiveproxy/src/net/quic/quic_session_pool.h @@ -203,7 +203,9 @@ class NET_EXPORT_PRIVATE QuicSessionRequest { // `ExpectOnHostResolution()` was called. This is called after the Job can // make no further progress, and includes the result of that progress, perhaps // `ERR_IO_PENDING`. - void OnHostResolutionComplete(int rv); + void OnHostResolutionComplete(int rv, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time); // Tells QuicSessionRequest that `QuicSessionPool::Job` will call // `OnQuicSessionCreationComplete()` in the future. Must be called before @@ -242,6 +244,13 @@ class NET_EXPORT_PRIVATE QuicSessionRequest { const NetLogWithSource& net_log() const { return net_log_; } + base::TimeTicks dns_resolution_start_time() const { + return dns_resolution_start_time_; + } + base::TimeTicks dns_resolution_end_time() const { + return dns_resolution_end_time_; + } + private: raw_ptr pool_; QuicSessionKey session_key_; @@ -251,6 +260,9 @@ class NET_EXPORT_PRIVATE QuicSessionRequest { raw_ptr net_error_details_; // Unowned. std::unique_ptr session_; + base::TimeTicks dns_resolution_start_time_; + base::TimeTicks dns_resolution_end_time_; + // Set in Request(). If true, then OnHostResolutionComplete() is expected to // be called in the future. bool expect_on_host_resolution_ = false; @@ -484,6 +496,14 @@ class NET_EXPORT_PRIVATE QuicSessionPool const std::set& GetDnsAliasesForSessionKey( const QuicSessionKey& key) const; + int CountActiveSessions() { return active_sessions_.size(); } + + // Inject a QUIC session for testing various edge cases. + void ActivateSessionForTesting(const url::SchemeHostPort& destination, + QuicChromiumClientSession* session); + + void DeactivateSessionForTesting(QuicChromiumClientSession* session); + // Returns the QUIC version that would be used with an endpoint associated // with `metadata`, or `quic::ParsedQuicVersion::Unsupported()` if the // endpoint cannot be used with QUIC. diff --git a/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc b/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc index bc2c4d842e..41a1f8bb98 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc +++ b/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc @@ -220,7 +220,8 @@ void QuicSessionPool::DirectJob::OnResolveHostComplete(int rv) { rv = DoLoop(rv); for (QuicSessionRequest* request : requests()) { - request->OnHostResolutionComplete(rv); + request->OnHostResolutionComplete(rv, dns_resolution_start_time_, + dns_resolution_end_time_); } if (rv != ERR_IO_PENDING && !callback_.is_null()) { diff --git a/naiveproxy/src/net/quic/quic_session_pool_job.cc b/naiveproxy/src/net/quic/quic_session_pool_job.cc index 2f7aa3d4c0..285e3415e1 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_job.cc +++ b/naiveproxy/src/net/quic/quic_session_pool_job.cc @@ -5,6 +5,7 @@ #include "net/quic/quic_session_pool_job.h" #include "base/memory/weak_ptr.h" +#include "base/not_fatal_until.h" #include "net/base/completion_once_callback.h" #include "net/base/network_change_notifier.h" #include "net/base/network_handle.h" @@ -66,7 +67,7 @@ void QuicSessionPool::Job::AddRequest(QuicSessionRequest* request) { void QuicSessionPool::Job::RemoveRequest(QuicSessionRequest* request) { auto request_iter = requests_.find(request); - DCHECK(request_iter != requests_.end()); + CHECK(request_iter != requests_.end(), base::NotFatalUntil::M130); requests_.erase(request_iter); } diff --git a/naiveproxy/src/net/quic/quic_session_pool_test_base.cc b/naiveproxy/src/net/quic/quic_session_pool_test_base.cc index 243712ee25..76f7750237 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_test_base.cc +++ b/naiveproxy/src/net/quic/quic_session_pool_test_base.cc @@ -74,7 +74,9 @@ #include "net/test/gtest_util.h" #include "net/test/test_data_directory.h" #include "net/test/test_with_task_environment.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/common/quiche_data_writer.h" +#include "net/third_party/quiche/src/quiche/http2/test_tools/spdy_test_utils.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_handshake.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_client_config.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.h" @@ -90,7 +92,6 @@ #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_session_peer.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h" -#include "net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/static_http_user_agent_settings.h" #include "testing/gmock/include/gmock/gmock.h" @@ -159,7 +160,6 @@ QuicSessionPoolTestBase::QuicSessionPoolTestBase( &QuicSessionPoolTestBase::OnFailedOnDefaultNetwork, base::Unretained(this))), quic_params_(context_.params()) { - SetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5, true); enabled_features.push_back(features::kAsyncQuicSession); scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); FLAGS_quic_enable_http3_grease_randomness = false; @@ -322,8 +322,10 @@ void QuicSessionPoolTestBase::NotifyIPAddressChanged() { std::unique_ptr QuicSessionPoolTestBase::ConstructServerConnectionClosePacket(uint64_t num) { - return server_maker_.MakeConnectionClosePacket( - num, quic::QUIC_CRYPTO_VERSION_NOT_SUPPORTED, "Time to panic!"); + return server_maker_.Packet(num) + .AddConnectionCloseFrame(quic::QUIC_CRYPTO_VERSION_NOT_SUPPORTED, + "Time to panic!") + .Build(); } std::unique_ptr @@ -331,14 +333,17 @@ QuicSessionPoolTestBase::ConstructClientRstPacket( uint64_t packet_number, quic::QuicRstStreamErrorCode error_code) { quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(0); - return client_maker_.MakeRstPacket(packet_number, stream_id, error_code); + return client_maker_.Packet(packet_number) + .AddStopSendingFrame(stream_id, error_code) + .AddRstStreamFrame(stream_id, error_code) + .Build(); } std::unique_ptr QuicSessionPoolTestBase::ConstructGetRequestPacket(uint64_t packet_number, quic::QuicStreamId stream_id, bool fin) { - spdy::Http2HeaderBlock headers = + quiche::HttpHeaderBlock headers = client_maker_.GetRequestHeaders("GET", "https", "/"); spdy::SpdyPriority priority = ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY); @@ -367,7 +372,7 @@ QuicSessionPoolTestBase::ConstructConnectUdpRequestPacket( std::string authority, std::string path, bool fin) { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":scheme"] = "https"; headers[":path"] = path; headers[":protocol"] = "connect-udp"; @@ -407,7 +412,7 @@ QuicSessionPoolTestBase::ConstructClientH3DatagramPacket( std::unique_ptr inner) { std::string data = ConstructClientH3DatagramFrame( quarter_stream_id, context_id, std::move(inner)); - return client_maker_.MakeDatagramPacket(packet_number, data); + return client_maker_.Packet(packet_number).AddMessageFrame(data).Build(); } std::unique_ptr @@ -424,7 +429,7 @@ QuicSessionPoolTestBase::ConstructOkResponsePacket( uint64_t packet_number, quic::QuicStreamId stream_id, bool fin) { - spdy::Http2HeaderBlock headers = packet_maker.GetResponseHeaders("200"); + quiche::HttpHeaderBlock headers = packet_maker.GetResponseHeaders("200"); size_t spdy_headers_frame_len; return packet_maker.MakeResponseHeadersPacket(packet_number, stream_id, fin, std::move(headers), @@ -461,8 +466,9 @@ QuicSessionPoolTestBase::ConstructAckPacket( uint64_t packet_num_received, uint64_t smallest_received, uint64_t largest_received) { - return packet_maker.MakeAckPacket(packet_number, packet_num_received, - smallest_received, largest_received); + return packet_maker.Packet(packet_number) + .AddAckFrame(packet_num_received, smallest_received, largest_received) + .Build(); } std::string QuicSessionPoolTestBase::ConstructDataHeader(size_t body_len) { @@ -476,7 +482,9 @@ QuicSessionPoolTestBase::ConstructServerDataPacket(uint64_t packet_number, quic::QuicStreamId stream_id, bool fin, std::string_view data) { - return server_maker_.MakeDataPacket(packet_number, stream_id, fin, data); + return server_maker_.Packet(packet_number) + .AddStreamFrame(stream_id, fin, data) + .Build(); } std::string QuicSessionPoolTestBase::ConstructH3Datagram( diff --git a/naiveproxy/src/net/quic/quic_test_packet_maker.cc b/naiveproxy/src/net/quic/quic_test_packet_maker.cc index b3294f151f..efc6e62dd3 100644 --- a/naiveproxy/src/net/quic/quic_test_packet_maker.cc +++ b/naiveproxy/src/net/quic/quic_test_packet_maker.cc @@ -167,43 +167,6 @@ QuicTestPacketBuilder& QuicTestPacketMaker::Packet(uint64_t packet_number) { return *builder_.get(); } -std::unique_ptr -QuicTestPacketMaker::MakeConnectivityProbingPacket(uint64_t packet_number) { - auto& builder = Packet(packet_number); - if (perspective_ == quic::Perspective::IS_CLIENT) { - builder.AddPathChallengeFrame(); - } else { - builder.AddPathResponseFrame(); - } - return builder.AddPaddingFrame().Build(); -} - -std::unique_ptr QuicTestPacketMaker::MakePingPacket( - uint64_t packet_number) { - return Packet(packet_number).AddPingFrame().Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeRetireConnectionIdPacket(uint64_t packet_number, - uint64_t sequence_number) { - return Packet(packet_number) - .AddRetireConnectionIdFrame(sequence_number) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeNewConnectionIdPacket( - uint64_t packet_number, - const quic::QuicConnectionId& cid, - uint64_t sequence_number, - uint64_t retire_prior_to) { - return Packet(packet_number) - .AddNewConnectionIdFrame( - cid, sequence_number, retire_prior_to, - quic::QuicUtils::GenerateStatelessResetToken(cid)) - .Build(); -} - std::unique_ptr QuicTestPacketMaker::MakeDummyCHLOPacket(uint64_t packet_number) { SetEncryptionLevel(quic::ENCRYPTION_INITIAL); @@ -220,188 +183,6 @@ QuicTestPacketMaker::MakeDummyCHLOPacket(uint64_t packet_number) { return builder.Build(); } -std::unique_ptr -QuicTestPacketMaker::MakeRetransmissionAndRetireConnectionIdPacket( - uint64_t packet_number, - const std::vector& original_packet_numbers, - uint64_t sequence_number) { - auto& builder = Packet(packet_number); - for (auto it : original_packet_numbers) { - builder.AddPacketRetransmission(it); - } - - builder.AddRetireConnectionIdFrame(sequence_number); - return builder.Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeStreamsBlockedPacket( - uint64_t packet_number, - quic::QuicStreamCount stream_count, - bool unidirectional) { - return Packet(packet_number) - .AddStreamsBlockedFrame(1, stream_count, unidirectional) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeMaxStreamsPacket(uint64_t packet_number, - quic::QuicStreamCount stream_count, - bool unidirectional) { - return Packet(packet_number) - .AddMaxStreamsFrame(1, stream_count, unidirectional) - .Build(); -} - -std::unique_ptr QuicTestPacketMaker::MakeRstPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - bool include_stop_sending_if_v99) { - auto& builder = Packet(packet_number); - if (include_stop_sending_if_v99) { - builder.AddStopSendingFrame(stream_id, error_code); - } - if (quic::QuicUtils::IsBidirectionalStreamId(stream_id, version_)) { - builder.AddRstStreamFrame(stream_id, error_code); - } - return builder.Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeRstAndDataPacket( - uint64_t packet_number, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode rst_error_code, - quic::QuicStreamId data_stream_id, - std::string_view data) { - return Packet(packet_number) - .AddStopSendingFrame(rst_stream_id, rst_error_code) - .AddRstStreamFrame(rst_stream_id, rst_error_code) - .AddStreamFrame(data_stream_id, /* fin = */ false, data) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeDataAndRstPacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode rst_error_code) { - return Packet(packet_number) - .AddStreamFrame(data_stream_id, /* fin = */ false, data) - .AddStopSendingFrame(rst_stream_id, rst_error_code) - .AddRstStreamFrame(rst_stream_id, rst_error_code) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeDataRstAndAckPacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode rst_error_code, - uint64_t largest_received, - uint64_t smallest_received) { - return Packet(packet_number) - .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) - .AddStreamFrame(data_stream_id, /* fin = */ false, data) - .AddStopSendingFrame(rst_stream_id, rst_error_code) - .AddRstStreamFrame(rst_stream_id, rst_error_code) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeAckAndRstPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - bool include_stop_sending_if_v99) { - auto& builder = Packet(packet_number); - builder.AddAckFrame(/*first_received=*/1, largest_received, - smallest_received); - - if (include_stop_sending_if_v99) { - builder.AddStopSendingFrame(stream_id, error_code); - } - if (quic::QuicUtils::IsBidirectionalStreamId(stream_id, version_)) { - builder.AddRstStreamFrame(stream_id, error_code); - } - return builder.Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeRstAckAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details) { - return Packet(packet_number) - .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) - .AddStopSendingFrame(stream_id, error_code) - .AddRstStreamFrame(stream_id, error_code) - .AddConnectionCloseFrame(quic_error, quic_error_details) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeRstAckAndDataPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId data_id, - bool fin, - std::string_view data) { - return Packet(packet_number) - .AddRstStreamFrame(stream_id, error_code) - .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) - .AddStreamFrame(data_id, fin, data) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeAckDataAndRst(uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId data_id, - bool fin, - std::string_view data) { - return Packet(packet_number) - .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) - .AddStreamFrame(data_id, fin, data) - .AddStopSendingFrame(stream_id, error_code) - .AddRstStreamFrame(stream_id, error_code) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeAckRstAndDataPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId data_id, - bool fin, - std::string_view data) { - return Packet(packet_number) - .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) - .AddRstStreamFrame(stream_id, error_code) - .AddStreamFrame(data_id, fin, data) - .Build(); -} - std::unique_ptr QuicTestPacketMaker::MakeAckAndRetransmissionPacket( uint64_t packet_number, @@ -441,163 +222,6 @@ QuicTestPacketMaker::MakeCombinedRetransmissionPacket( return builder.Build(); } -std::unique_ptr -QuicTestPacketMaker::MakeRstAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details) { - return Packet(packet_number) - .AddStopSendingFrame(stream_id, error_code) - .AddRstStreamFrame(stream_id, error_code) - .AddConnectionCloseFrame(quic_error, quic_error_details) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeDataRstAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode error_code, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details) { - return Packet(packet_number) - .AddStreamFrame(data_stream_id, /* fin = */ false, data) - .AddStopSendingFrame(rst_stream_id, error_code) - .AddRstStreamFrame(rst_stream_id, error_code) - .AddConnectionCloseFrame(quic_error, quic_error_details) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeDataRstAckAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details) { - return Packet(packet_number) - .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) - .AddStreamFrame(data_stream_id, /* fin = */ false, data) - .AddStopSendingFrame(rst_stream_id, error_code) - .AddRstStreamFrame(rst_stream_id, error_code) - .AddConnectionCloseFrame(quic_error, quic_error_details) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeDataRstAckAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details, - uint64_t frame_type) { - return Packet(packet_number) - .AddStreamFrame(data_stream_id, /* fin = */ false, data) - .AddStopSendingFrame(rst_stream_id, error_code) - .AddRstStreamFrame(rst_stream_id, error_code) - .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) - .AddConnectionCloseFrame(quic_error, quic_error_details, frame_type) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeStopSendingPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code) { - return Packet(packet_number) - .AddStopSendingFrame(stream_id, error_code) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeAckAndConnectionClosePacket( - uint64_t packet_number, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details, - uint64_t frame_type) { - return Packet(packet_number) - .AddAckFrame(/*first_received=*/1, largest_received, smallest_received) - .AddConnectionCloseFrame(quic_error, quic_error_details, frame_type) - .Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeConnectionClosePacket( - uint64_t packet_number, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details) { - return Packet(packet_number) - .AddConnectionCloseFrame(quic_error, quic_error_details) - .Build(); -} - -std::unique_ptr QuicTestPacketMaker::MakeGoAwayPacket( - uint64_t packet_number, - quic::QuicErrorCode error_code, - std::string reason_phrase) { - return Packet(packet_number) - .AddGoAwayFrame(error_code, reason_phrase) - .Build(); -} - -std::unique_ptr QuicTestPacketMaker::MakeAckPacket( - uint64_t packet_number, - uint64_t largest_received, - uint64_t smallest_received) { - return MakeAckPacket(packet_number, 1, largest_received, smallest_received); -} - -std::unique_ptr QuicTestPacketMaker::MakeAckPacket( - uint64_t packet_number, - uint64_t first_received, - uint64_t largest_received, - uint64_t smallest_received, - std::optional ecn) { - return Packet(packet_number) - .AddAckFrame(first_received, largest_received, smallest_received, ecn) - .Build(); -} - -std::unique_ptr QuicTestPacketMaker::MakeDataPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - bool fin, - std::string_view data) { - return Packet(packet_number).AddStreamFrame(stream_id, fin, data).Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeDatagramPacket(uint64_t packet_number, - std::string_view datagram) { - return Packet(packet_number).AddMessageFrame(datagram).Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeDatagramPacket(uint64_t packet_number, - std::vector datagrams) { - auto& builder = Packet(packet_number); - for (auto& datagram : datagrams) { - builder.AddMessageFrame(datagram); - } - return builder.Build(); -} - std::unique_ptr QuicTestPacketMaker::MakeAckAndDataPacket(uint64_t packet_number, quic::QuicStreamId stream_id, @@ -622,32 +246,13 @@ QuicTestPacketMaker::MakeAckAndDatagramPacket(uint64_t packet_number, .Build(); } -std::unique_ptr -QuicTestPacketMaker::MakeAckRetransmissionAndDataPacket( - uint64_t packet_number, - const std::vector& original_packet_numbers, - quic::QuicStreamId stream_id, - uint64_t largest_received, - uint64_t smallest_received, - bool fin, - std::string_view data) { - auto& builder = Packet(packet_number); - builder.AddAckFrame(/*first_received=*/1, largest_received, - smallest_received); - for (auto it : original_packet_numbers) { - builder.AddPacketRetransmission(it); - } - builder.AddStreamFrame(stream_id, fin, data); - return builder.Build(); -} - std::unique_ptr QuicTestPacketMaker::MakeRequestHeadersAndMultipleDataFramesPacket( uint64_t packet_number, quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length, const std::vector& data_writes) { auto& builder = Packet(packet_number); @@ -675,7 +280,7 @@ QuicTestPacketMaker::MakeRequestHeadersPacket( quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length, bool should_include_priority_frame) { auto& builder = Packet(packet_number); @@ -703,7 +308,7 @@ QuicTestPacketMaker::MakeRetransmissionAndRequestHeadersPacket( quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length) { DCHECK(connection_state_.save_packet_frames); auto& builder = Packet(packet_number); @@ -732,7 +337,7 @@ QuicTestPacketMaker::MakeRequestHeadersAndRstPacket( quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length, quic::QuicRstStreamErrorCode error_code) { auto& builder = Packet(packet_number); @@ -758,7 +363,7 @@ QuicTestPacketMaker::MakeResponseHeadersPacket( uint64_t packet_number, quic::QuicStreamId stream_id, bool fin, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length) { std::string data = QpackEncodeHeaders(stream_id, std::move(headers), spdy_headers_frame_length); @@ -782,41 +387,6 @@ QuicTestPacketMaker::MakePriorityPacket(uint64_t packet_number, return builder.Build(); } -std::unique_ptr -QuicTestPacketMaker::MakeAckAndPriorityPacket( - uint64_t packet_number, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId id, - spdy::SpdyPriority spdy_priority) { - auto& builder = Packet(packet_number); - builder.AddAckFrame(/*first_received=*/1, largest_received, - smallest_received); - std::string priority_data = GenerateHttp3PriorityData(spdy_priority, id); - if (!priority_data.empty()) { - builder.AddStreamFrame(2, false, priority_data); - } - return builder.Build(); -} - -std::unique_ptr -QuicTestPacketMaker::MakeAckAndPriorityUpdatePacket( - uint64_t packet_number, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId id, - spdy::SpdyPriority spdy_priority) { - auto& builder = Packet(packet_number); - builder.AddAckFrame(/*first_received=*/1, largest_received, - smallest_received); - - std::string priority_data = GenerateHttp3PriorityData(spdy_priority, id); - if (!priority_data.empty()) { - builder.AddStreamFrame(2, false, priority_data); - } - return builder.Build(); -} - std::unique_ptr QuicTestPacketMaker::MakeRetransmissionPacket(uint64_t original_packet_number, uint64_t new_packet_number) { @@ -867,11 +437,11 @@ void QuicTestPacketMaker::SetEncryptionLevel(quic::EncryptionLevel level) { } } -spdy::Http2HeaderBlock QuicTestPacketMaker::GetRequestHeaders( +quiche::HttpHeaderBlock QuicTestPacketMaker::GetRequestHeaders( const std::string& method, const std::string& scheme, const std::string& path) const { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":method"] = method; headers[":authority"] = host_; headers[":scheme"] = scheme; @@ -879,26 +449,26 @@ spdy::Http2HeaderBlock QuicTestPacketMaker::GetRequestHeaders( return headers; } -spdy::Http2HeaderBlock QuicTestPacketMaker::ConnectRequestHeaders( +quiche::HttpHeaderBlock QuicTestPacketMaker::ConnectRequestHeaders( const std::string& host_port) const { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":method"] = "CONNECT"; headers[":authority"] = host_port; return headers; } -spdy::Http2HeaderBlock QuicTestPacketMaker::GetResponseHeaders( +quiche::HttpHeaderBlock QuicTestPacketMaker::GetResponseHeaders( const std::string& status) const { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":status"] = status; headers["content-type"] = "text/plain"; return headers; } -spdy::Http2HeaderBlock QuicTestPacketMaker::GetResponseHeaders( +quiche::HttpHeaderBlock QuicTestPacketMaker::GetResponseHeaders( const std::string& status, const std::string& alt_svc) const { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":status"] = status; headers["alt-svc"] = alt_svc; headers["content-type"] = "text/plain"; @@ -911,7 +481,7 @@ void QuicTestPacketMaker::Reset() { std::string QuicTestPacketMaker::QpackEncodeHeaders( quic::QuicStreamId stream_id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* encoded_data_length) { std::string data; @@ -1033,7 +603,7 @@ std::string QuicTestPacketMaker::GenerateHttp3PriorityData( } void QuicTestPacketMaker::AddPriorityHeader(spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock* headers) { + quiche::HttpHeaderBlock* headers) { if (use_priority_header_ && base::FeatureList::IsEnabled(net::features::kPriorityHeader)) { quic::HttpStreamPriority priority{ @@ -1087,13 +657,13 @@ QuicTestPacketBuilder& QuicTestPacketBuilder::AddRetireConnectionIdFrame( QuicTestPacketBuilder& QuicTestPacketBuilder::AddNewConnectionIdFrame( const quic::QuicConnectionId& cid, uint64_t sequence_number, - uint64_t retire_prior_to, - quic::StatelessResetToken reset_token) { + uint64_t retire_prior_to) { auto* new_cid_frame = new quic::QuicNewConnectionIdFrame(); new_cid_frame->connection_id = cid; new_cid_frame->sequence_number = sequence_number; new_cid_frame->retire_prior_to = retire_prior_to; - new_cid_frame->stateless_reset_token = reset_token; + new_cid_frame->stateless_reset_token = + quic::QuicUtils::GenerateStatelessResetToken(cid); AddFrame(quic::QuicFrame(new_cid_frame)); return *this; } diff --git a/naiveproxy/src/net/quic/quic_test_packet_maker.h b/naiveproxy/src/net/quic/quic_test_packet_maker.h index 34cd036466..e58d1e733b 100644 --- a/naiveproxy/src/net/quic/quic_test_packet_maker.h +++ b/naiveproxy/src/net/quic/quic_test_packet_maker.h @@ -19,6 +19,7 @@ #include "base/memory/raw_ptr.h" #include "net/base/request_priority.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/quic/core/http/http_encoder.h" #include "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_clock.h" @@ -93,207 +94,9 @@ class QuicTestPacketMaker { // Clone all frames from |packet_number|. quic::QuicFrames CloneSavedFrames(uint64_t packet_number); - std::unique_ptr MakeConnectivityProbingPacket( - uint64_t packet_number); - - std::unique_ptr MakePingPacket( - uint64_t packet_number); - - std::unique_ptr MakeRetireConnectionIdPacket( - uint64_t packet_number, - uint64_t sequence_number); - - std::unique_ptr MakeNewConnectionIdPacket( - uint64_t packet_number, - const quic::QuicConnectionId& cid, - uint64_t sequence_number, - uint64_t retire_prior_to); - std::unique_ptr MakeDummyCHLOPacket( uint64_t packet_number); - std::unique_ptr - MakeRetransmissionAndRetireConnectionIdPacket( - uint64_t packet_number, - const std::vector& original_packet_numbers, - uint64_t sequence_number); - - std::unique_ptr MakeStreamsBlockedPacket( - uint64_t packet_number, - quic::QuicStreamCount stream_count, - bool unidirectional); - - std::unique_ptr MakeMaxStreamsPacket( - uint64_t packet_number, - quic::QuicStreamCount stream_count, - bool unidirectional); - - std::unique_ptr MakeRstPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - bool include_stop_sending_if_v99 = true); - - std::unique_ptr MakeRstAndDataPacket( - uint64_t packet_number, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode rst_error_code, - quic::QuicStreamId data_stream_id, - std::string_view data); - - std::unique_ptr MakeDataAndRstPacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode rst_error_code); - - std::unique_ptr MakeDataRstAndAckPacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode rst_error_code, - uint64_t largest_received, - uint64_t smallest_received); - - std::unique_ptr MakeAckAndRstPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - bool include_stop_sending_if_v99 = true); - - std::unique_ptr MakeRstAckAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details); - - std::unique_ptr MakeRstAckAndDataPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId data_id, - bool fin, - std::string_view data); - - std::unique_ptr MakeAckDataAndRst( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId data_id, - bool fin, - std::string_view data); - - std::unique_ptr MakeAckRstAndDataPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId data_id, - bool fin, - std::string_view data); - - std::unique_ptr MakeRstAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details); - - std::unique_ptr MakeDataRstAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode error_code, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details); - - std::unique_ptr - MakeDataRstAckAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details); - - std::unique_ptr - MakeDataRstAckAndConnectionClosePacket( - uint64_t packet_number, - quic::QuicStreamId data_stream_id, - std::string_view data, - quic::QuicStreamId rst_stream_id, - quic::QuicRstStreamErrorCode error_code, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details, - uint64_t frame_type); - - std::unique_ptr MakeStopSendingPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - quic::QuicRstStreamErrorCode error_code); - - std::unique_ptr MakeAckAndConnectionClosePacket( - uint64_t packet_number, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details, - uint64_t frame_type); - - std::unique_ptr MakeConnectionClosePacket( - uint64_t packet_number, - quic::QuicErrorCode quic_error, - const std::string& quic_error_details); - - std::unique_ptr MakeGoAwayPacket( - uint64_t packet_number, - quic::QuicErrorCode error_code, - std::string reason_phrase); - - std::unique_ptr MakeAckPacket( - uint64_t packet_number, - uint64_t largest_received, - uint64_t smallest_received); - - std::unique_ptr MakeAckPacket( - uint64_t packet_number, - uint64_t first_received, - uint64_t largest_received, - uint64_t smallest_received, - std::optional ecn = std::nullopt); - - std::unique_ptr MakeDataPacket( - uint64_t packet_number, - quic::QuicStreamId stream_id, - bool fin, - std::string_view data); - - std::unique_ptr MakeDatagramPacket( - uint64_t packet_number, - std::string_view datagram); - - std::unique_ptr MakeDatagramPacket( - uint64_t packet_number, - std::vector datagrams); - std::unique_ptr MakeAckAndDataPacket( uint64_t packet_number, quic::QuicStreamId stream_id, @@ -308,15 +111,6 @@ class QuicTestPacketMaker { uint64_t smallest_received, std::string_view data); - std::unique_ptr MakeAckRetransmissionAndDataPacket( - uint64_t packet_number, - const std::vector& original_packet_numbers, - quic::QuicStreamId stream_id, - uint64_t largest_received, - uint64_t smallest_received, - bool fin, - std::string_view data); - std::unique_ptr MakeAckAndRetransmissionPacket( uint64_t packet_number, uint64_t first_received, @@ -330,7 +124,7 @@ class QuicTestPacketMaker { quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length, const std::vector& data_writes); @@ -341,7 +135,7 @@ class QuicTestPacketMaker { quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length, bool should_include_priority_frame = true); @@ -352,7 +146,7 @@ class QuicTestPacketMaker { quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length); std::unique_ptr MakeRequestHeadersAndRstPacket( @@ -360,7 +154,7 @@ class QuicTestPacketMaker { quic::QuicStreamId stream_id, bool fin, spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length, quic::QuicRstStreamErrorCode error_code); @@ -370,7 +164,7 @@ class QuicTestPacketMaker { uint64_t packet_number, quic::QuicStreamId stream_id, bool fin, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* spdy_headers_frame_length); // Creates a packet containing the initial SETTINGS frame, and saves the @@ -383,13 +177,6 @@ class QuicTestPacketMaker { quic::QuicStreamId id, spdy::SpdyPriority spdy_priority); - std::unique_ptr MakeAckAndPriorityPacket( - uint64_t packet_number, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId id, - spdy::SpdyPriority spdy_priority); - std::unique_ptr MakeRetransmissionPacket( uint64_t original_packet_number, uint64_t new_packet_number); @@ -398,13 +185,6 @@ class QuicTestPacketMaker { const std::vector& original_packet_numbers, uint64_t new_packet_number); - std::unique_ptr MakeAckAndPriorityUpdatePacket( - uint64_t packet_number, - uint64_t largest_received, - uint64_t smallest_received, - quic::QuicStreamId id, - spdy::SpdyPriority spdy_priority); - std::unique_ptr MakeStatelessResetPacket(); // Removes all stream frames associated with |stream_id|. @@ -412,17 +192,17 @@ class QuicTestPacketMaker { void SetEncryptionLevel(quic::EncryptionLevel level); - spdy::Http2HeaderBlock GetRequestHeaders(const std::string& method, - const std::string& scheme, - const std::string& path) const; + quiche::HttpHeaderBlock GetRequestHeaders(const std::string& method, + const std::string& scheme, + const std::string& path) const; - spdy::Http2HeaderBlock ConnectRequestHeaders( + quiche::HttpHeaderBlock ConnectRequestHeaders( const std::string& host_port) const; - spdy::Http2HeaderBlock GetResponseHeaders(const std::string& status) const; + quiche::HttpHeaderBlock GetResponseHeaders(const std::string& status) const; - spdy::Http2HeaderBlock GetResponseHeaders(const std::string& status, - const std::string& alt_svc) const; + quiche::HttpHeaderBlock GetResponseHeaders(const std::string& status, + const std::string& alt_svc) const; // Reset some of the state in the packet maker. // TODO(https://issues.chromium.org/u/1/issues/335279177): reset all state. @@ -443,7 +223,7 @@ class QuicTestPacketMaker { } std::string QpackEncodeHeaders(quic::QuicStreamId stream_id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, size_t* encoded_data_length); void set_ecn_codepoint(quic::QuicEcnCodepoint ecn) { ecn_codepoint_ = ecn; } @@ -457,7 +237,7 @@ class QuicTestPacketMaker { private: void AddPriorityHeader(spdy::SpdyPriority spdy_priority, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); quic::QuicStreamId GetFirstBidirectionalStreamId() const; @@ -524,8 +304,7 @@ class QuicTestPacketBuilder { QuicTestPacketBuilder& AddNewConnectionIdFrame( const quic::QuicConnectionId& cid, uint64_t sequence_number, - uint64_t retire_prior_to, - quic::StatelessResetToken reset_token); + uint64_t retire_prior_to); QuicTestPacketBuilder& AddMaxStreamsFrame( quic::QuicControlFrameId control_frame_id, quic::QuicStreamCount stream_count, diff --git a/naiveproxy/src/net/quic/set_quic_flag.cc b/naiveproxy/src/net/quic/set_quic_flag.cc index e7990fe27c..5b3cc86bf4 100644 --- a/naiveproxy/src/net/quic/set_quic_flag.cc +++ b/naiveproxy/src/net/quic/set_quic_flag.cc @@ -61,13 +61,13 @@ void SetQuicFlagByName_int64_t(int64_t* flag, const std::string& value) { } // namespace void SetQuicFlagByName(const std::string& flag_name, const std::string& value) { -#define QUIC_FLAG(flag, default_value) \ - if (flag_name == "FLAGS_" #flag) { \ - SetQuicFlagByName_bool(&FLAGS_##flag, value); \ - return; \ +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + if (flag_name == "FLAGS_" #flag) { \ + SetQuicFlagByName_##type(&FLAGS_##flag, value); \ + return; \ } -#include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#include "net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG(type, flag, ...) \ if (flag_name == "FLAGS_" #flag) { \ diff --git a/naiveproxy/src/net/quic/test_task_runner.cc b/naiveproxy/src/net/quic/test_task_runner.cc index 42486b0d4a..40b2115950 100644 --- a/naiveproxy/src/net/quic/test_task_runner.cc +++ b/naiveproxy/src/net/quic/test_task_runner.cc @@ -61,7 +61,7 @@ quic::QuicTime::Delta TestTaskRunner::NextPendingTaskDelay() { void TestTaskRunner::RunNextTask() { auto next = FindNextTask(); - DCHECK(next != tasks_.end()); + CHECK(next != tasks_.end()); clock_->AdvanceTime(quic::QuicTime::Delta::FromMicroseconds( (next->GetTimeToRun() - NowInTicks(*clock_)).InMicroseconds())); PostedTask task = std::move(*next); diff --git a/naiveproxy/src/net/reporting/reporting_cache.h b/naiveproxy/src/net/reporting/reporting_cache.h index 83236f4438..466c8f06c2 100644 --- a/naiveproxy/src/net/reporting/reporting_cache.h +++ b/naiveproxy/src/net/reporting/reporting_cache.h @@ -22,6 +22,7 @@ #include "net/reporting/reporting_endpoint.h" #include "net/reporting/reporting_header_parser.h" #include "net/reporting/reporting_report.h" +#include "net/reporting/reporting_target_type.h" #include "url/gurl.h" #include "url/origin.h" @@ -77,7 +78,8 @@ class NET_EXPORT ReportingCache { base::Value::Dict body, int depth, base::TimeTicks queued, - int attempts) = 0; + int attempts, + ReportingTargetType target_type) = 0; // Gets all reports in the cache. The returned pointers are valid as long as // either no calls to |RemoveReports| have happened or the reports' |pending| @@ -329,6 +331,11 @@ class NET_EXPORT ReportingCache { const IsolationInfo& isolation_info, const GURL& url) = 0; + // Sets an enterprise endpoint. + virtual void SetEnterpriseEndpointForTesting( + const ReportingEndpointGroupKey& group_key, + const GURL& url) = 0; + // Gets the isolation info associated with `reporting_source`, used when // determining which credentials to send for a given report. If // `reporting_source` is nullopt, as when a report is being delivered to a V0 diff --git a/naiveproxy/src/net/reporting/reporting_cache_impl.cc b/naiveproxy/src/net/reporting/reporting_cache_impl.cc index 18964dd784..f5b7803604 100644 --- a/naiveproxy/src/net/reporting/reporting_cache_impl.cc +++ b/naiveproxy/src/net/reporting/reporting_cache_impl.cc @@ -12,6 +12,7 @@ #include "base/containers/contains.h" #include "base/memory/raw_ptr.h" +#include "base/not_fatal_until.h" #include "base/ranges/algorithm.h" #include "base/stl_util.h" #include "base/time/clock.h" @@ -19,6 +20,7 @@ #include "net/base/network_anonymization_key.h" #include "net/base/url_util.h" #include "net/log/net_log.h" +#include "net/reporting/reporting_target_type.h" namespace net { @@ -39,7 +41,8 @@ void ReportingCacheImpl::AddReport( base::Value::Dict body, int depth, base::TimeTicks queued, - int attempts) { + int attempts, + ReportingTargetType target_type) { // If |reporting_source| is present, it must not be empty. DCHECK(!(reporting_source.has_value() && reporting_source->is_empty())); // Drop the report if its reporting source is already marked as expired. @@ -53,7 +56,7 @@ void ReportingCacheImpl::AddReport( auto report = std::make_unique( reporting_source, network_anonymization_key, url, user_agent, group_name, - type, std::move(body), depth, queued, attempts); + type, std::move(body), depth, queued, attempts, target_type); auto inserted = reports_.insert(std::move(report)); DCHECK(inserted.second); @@ -62,7 +65,7 @@ void ReportingCacheImpl::AddReport( // There should be at most one extra report (the one added above). DCHECK_EQ(context_->policy().max_report_count + 1, reports_.size()); ReportSet::const_iterator to_evict = FindReportToEvict(); - DCHECK(to_evict != reports_.end()); + CHECK(to_evict != reports_.end(), base::NotFatalUntil::M130); // The newly-added report isn't pending, so even if all other reports are // pending, the cache should have a report to evict. DCHECK(!to_evict->get()->IsUploadPending()); @@ -168,7 +171,7 @@ void ReportingCacheImpl::ClearReportsPending( reports) { for (const ReportingReport* report : reports) { auto it = reports_.find(report); - DCHECK(it != reports_.end()); + CHECK(it != reports_.end(), base::NotFatalUntil::M130); if (it->get()->status == ReportingReport::Status::DOOMED || it->get()->status == ReportingReport::Status::SUCCESS) { reports_.erase(it); @@ -185,7 +188,7 @@ void ReportingCacheImpl::IncrementReportsAttempts( reports) { for (const ReportingReport* report : reports) { auto it = reports_.find(report); - DCHECK(it != reports_.end()); + CHECK(it != reports_.end(), base::NotFatalUntil::M130); it->get()->attempts++; context_->NotifyReportUpdated(it->get()); } @@ -309,7 +312,7 @@ void ReportingCacheImpl::RemoveReports( bool delivery_success) { for (const ReportingReport* report : reports) { auto it = reports_.find(report); - DCHECK(it != reports_.end()); + CHECK(it != reports_.end(), base::NotFatalUntil::M130); switch (it->get()->status) { case ReportingReport::Status::DOOMED: @@ -537,7 +540,7 @@ void ReportingCacheImpl::RemoveEndpointGroup( if (group_it == endpoint_groups_.end()) return; ClientMap::iterator client_it = FindClientIt(group_key); - DCHECK(client_it != clients_.end()); + CHECK(client_it != clients_.end(), base::NotFatalUntil::M130); RemoveEndpointGroupInternal(client_it, group_it); ConsistencyCheckClients(); @@ -569,9 +572,9 @@ void ReportingCacheImpl::RemoveEndpointsForUrl(const GURL& url) { DCHECK(endpoint_it->second.info.url == url); const ReportingEndpointGroupKey& group_key = endpoint_it->first; ClientMap::iterator client_it = FindClientIt(group_key); - DCHECK(client_it != clients_.end()); + CHECK(client_it != clients_.end(), base::NotFatalUntil::M130); EndpointGroupMap::iterator group_it = FindEndpointGroupIt(group_key); - DCHECK(group_it != endpoint_groups_.end()); + CHECK(group_it != endpoint_groups_.end(), base::NotFatalUntil::M130); RemoveEndpointInternal(client_it, group_it, endpoint_it); } @@ -702,6 +705,16 @@ ReportingCacheImpl::GetCandidateEndpointsForDelivery( base::Time now = clock().Now(); ConsistencyCheckClients(); + if (group_key.IsEnterpriseEndpoint()) { + std::vector endpoints_out; + for (const ReportingEndpoint& endpoint : enterprise_endpoints_) { + if (endpoint.group_key == group_key) { + endpoints_out.push_back(endpoint); + } + } + return endpoints_out; + } + // If |group_key| has a defined |reporting_source| field, then this method is // being called for reports with an associated source. We need to first look // for a matching V1 endpoint, based on |reporting_source| and |group_name|. @@ -726,7 +739,7 @@ ReportingCacheImpl::GetCandidateEndpointsForDelivery( // can be compared to any V0 endpoint groups. ReportingEndpointGroupKey v0_lookup_group_key( group_key.network_anonymization_key, group_key.origin, - group_key.group_name); + group_key.group_name, group_key.target_type); // Look for an exact origin match for |origin| and |group|. EndpointGroupMap::iterator group_it = @@ -755,7 +768,7 @@ ReportingCacheImpl::GetCandidateEndpointsForDelivery( } ReportingEndpointGroupKey superdomain_lookup_group_key( v0_lookup_group_key.network_anonymization_key, client.origin, - v0_lookup_group_key.group_name); + v0_lookup_group_key.group_name, v0_lookup_group_key.target_type); group_it = FindEndpointGroupIt(superdomain_lookup_group_key); if (group_it == endpoint_groups_.end()) @@ -902,6 +915,17 @@ void ReportingCacheImpl::SetV1EndpointForTesting( FilterEndpointsByOrigin(document_endpoints_, group_key.origin)); } +void ReportingCacheImpl::SetEnterpriseEndpointForTesting( + const ReportingEndpointGroupKey& group_key, + const GURL& url) { + DCHECK(group_key.IsEnterpriseEndpoint()); + + ReportingEndpoint::EndpointInfo info; + info.url = url; + ReportingEndpoint new_endpoint(group_key, info); + enterprise_endpoints_.push_back(std::move(new_endpoint)); +} + void ReportingCacheImpl::SetEndpointForTesting( const ReportingEndpointGroupKey& group_key, const GURL& url, @@ -961,14 +985,14 @@ IsolationInfo ReportingCacheImpl::GetIsolationInfoForEndpoint( const ReportingEndpoint& endpoint) const { // V0 endpoint groups do not support credentials. if (!endpoint.group_key.reporting_source.has_value()) { - // TODO(crbug.com/40871266): Remove this and have a better way to get an + // TODO(crbug.com/344943210): Remove this and have a better way to get a // correct IsolationInfo here. return IsolationInfo::DoNotUseCreatePartialFromNak( endpoint.group_key.network_anonymization_key); } const auto it = isolation_info_.find(endpoint.group_key.reporting_source.value()); - DCHECK(it != isolation_info_.end()); + CHECK(it != isolation_info_.end(), base::NotFatalUntil::M130); return it->second; } @@ -1310,9 +1334,11 @@ void ReportingCacheImpl::RemoveEndpointGroupsForClientOtherThan( groups_to_keep_names); for (const std::string& group_name : groups_to_remove_names) { - EndpointGroupMap::iterator group_it = - FindEndpointGroupIt(ReportingEndpointGroupKey(network_anonymization_key, - origin, group_name)); + // The target_type is set to kDeveloper because this function is used for + // V0 reporting, which only includes web developer entities. + EndpointGroupMap::iterator group_it = FindEndpointGroupIt( + ReportingEndpointGroupKey(network_anonymization_key, origin, group_name, + ReportingTargetType::kDeveloper)); RemoveEndpointGroupInternal(client_it, group_it); } } @@ -1346,9 +1372,9 @@ std::optional ReportingCacheImpl::RemoveEndpointInternal(ClientMap::iterator client_it, EndpointGroupMap::iterator group_it, EndpointMap::iterator endpoint_it) { - DCHECK(client_it != clients_.end()); - DCHECK(group_it != endpoint_groups_.end()); - DCHECK(endpoint_it != endpoints_.end()); + CHECK(client_it != clients_.end(), base::NotFatalUntil::M130); + CHECK(group_it != endpoint_groups_.end(), base::NotFatalUntil::M130); + CHECK(endpoint_it != endpoints_.end(), base::NotFatalUntil::M130); const ReportingEndpointGroupKey& group_key = endpoint_it->first; // If this is the only endpoint in the group, then removing it will cause the @@ -1374,8 +1400,8 @@ ReportingCacheImpl::RemoveEndpointGroupInternal( ClientMap::iterator client_it, EndpointGroupMap::iterator group_it, size_t* num_endpoints_removed) { - DCHECK(client_it != clients_.end()); - DCHECK(group_it != endpoint_groups_.end()); + CHECK(client_it != clients_.end(), base::NotFatalUntil::M130); + CHECK(group_it != endpoint_groups_.end(), base::NotFatalUntil::M130); const ReportingEndpointGroupKey& group_key = group_it->first; // Remove the endpoints for this group. @@ -1418,13 +1444,16 @@ ReportingCacheImpl::RemoveEndpointGroupInternal( ReportingCacheImpl::ClientMap::iterator ReportingCacheImpl::RemoveClientInternal(ClientMap::iterator client_it) { - DCHECK(client_it != clients_.end()); + CHECK(client_it != clients_.end(), base::NotFatalUntil::M130); const Client& client = client_it->second; // Erase all groups in this client, and all endpoints in those groups. for (const std::string& group_name : client.endpoint_group_names) { + // The target_type is set to kDeveloper because this function is used for + // V0 reporting, which only includes web developer entities. ReportingEndpointGroupKey group_key(client.network_anonymization_key, - client.origin, group_name); + client.origin, group_name, + ReportingTargetType::kDeveloper); EndpointGroupMap::iterator group_it = FindEndpointGroupIt(group_key); if (context_->IsClientDataPersisted()) store()->DeleteReportingEndpointGroup(group_it->second); @@ -1445,7 +1474,7 @@ ReportingCacheImpl::RemoveClientInternal(ClientMap::iterator client_it) { void ReportingCacheImpl::EnforcePerClientAndGlobalEndpointLimits( ClientMap::iterator client_it) { - DCHECK(client_it != clients_.end()); + CHECK(client_it != clients_.end(), base::NotFatalUntil::M130); size_t client_endpoint_count = client_it->second.endpoint_count; // TODO(chlily): This is actually a limit on the endpoints for a given client // (for a NAK, origin pair). Rename this. @@ -1468,7 +1497,7 @@ void ReportingCacheImpl::EnforcePerClientAndGlobalEndpointLimits( } } - DCHECK(to_evict != clients_.end()); + CHECK(to_evict != clients_.end(), base::NotFatalUntil::M130); // Evict endpoints from the chosen client. size_t num_to_evict = GetEndpointCount() - max_endpoint_count; @@ -1480,7 +1509,7 @@ void ReportingCacheImpl::EnforcePerClientAndGlobalEndpointLimits( void ReportingCacheImpl::EvictEndpointsFromClient(ClientMap::iterator client_it, size_t endpoints_to_evict) { DCHECK_GT(endpoints_to_evict, 0u); - DCHECK(client_it != clients_.end()); + CHECK(client_it != clients_.end(), base::NotFatalUntil::M130); const Client& client = client_it->second; // Cache this value as |client| may be deleted. size_t client_endpoint_count = client.endpoint_count; @@ -1511,8 +1540,11 @@ void ReportingCacheImpl::EvictEndpointsFromClient(ClientMap::iterator client_it, EndpointGroupMap::iterator stalest_group_it = endpoint_groups_.end(); size_t stalest_group_endpoint_count = 0; for (const std::string& group_name : client.endpoint_group_names) { + // The target_type is set to kDeveloper because enterprise endpoints + // follow a different path. ReportingEndpointGroupKey group_key(network_anonymization_key, origin, - group_name); + group_name, + ReportingTargetType::kDeveloper); EndpointGroupMap::iterator group_it = FindEndpointGroupIt(group_key); size_t group_endpoint_count = GetEndpointCountInGroup(group_key); @@ -1525,7 +1557,8 @@ void ReportingCacheImpl::EvictEndpointsFromClient(ClientMap::iterator client_it, stalest_group_endpoint_count = group_endpoint_count; } } - DCHECK(stalest_group_it != endpoint_groups_.end()); + CHECK(stalest_group_it != endpoint_groups_.end(), + base::NotFatalUntil::M130); // Evict the least important (lowest priority, lowest weight) endpoint. EvictEndpointFromGroup(client_it, stalest_group_it); @@ -1549,7 +1582,7 @@ void ReportingCacheImpl::EvictEndpointFromGroup( endpoint_to_evict_it = it; } } - DCHECK(endpoint_to_evict_it != endpoints_.end()); + CHECK(endpoint_to_evict_it != endpoints_.end(), base::NotFatalUntil::M130); RemoveEndpointInternal(client_it, group_it, endpoint_to_evict_it); } @@ -1563,10 +1596,13 @@ bool ReportingCacheImpl::RemoveExpiredOrStaleGroups( client_it->second.endpoint_group_names); for (const std::string& group_name : groups_in_client_names) { + // The target_type is set to kDeveloper because enterprise endpoints + // follow a different path. EndpointGroupMap::iterator group_it = FindEndpointGroupIt( ReportingEndpointGroupKey(client_it->second.network_anonymization_key, - client_it->second.origin, group_name)); - DCHECK(group_it != endpoint_groups_.end()); + client_it->second.origin, group_name, + ReportingTargetType::kDeveloper)); + CHECK(group_it != endpoint_groups_.end(), base::NotFatalUntil::M130); const CachedReportingEndpointGroup& group = group_it->second; if (group.expires < now || now - group.last_used > context_->policy().max_group_staleness) { @@ -1609,8 +1645,11 @@ base::Value ReportingCacheImpl::GetClientAsValue(const Client& client) const { base::Value::List group_list; for (const std::string& group_name : client.endpoint_group_names) { + // The target_type is set to kDeveloper because enterprise endpoints + // follow a different path. ReportingEndpointGroupKey group_key(client.network_anonymization_key, - client.origin, group_name); + client.origin, group_name, + ReportingTargetType::kDeveloper); const CachedReportingEndpointGroup& group = endpoint_groups_.at(group_key); group_list.Append(GetEndpointGroupAsValue(group)); } diff --git a/naiveproxy/src/net/reporting/reporting_cache_impl.h b/naiveproxy/src/net/reporting/reporting_cache_impl.h index 6e71ba9231..c7b862f0cc 100644 --- a/naiveproxy/src/net/reporting/reporting_cache_impl.h +++ b/naiveproxy/src/net/reporting/reporting_cache_impl.h @@ -29,6 +29,7 @@ #include "net/reporting/reporting_endpoint.h" #include "net/reporting/reporting_header_parser.h" #include "net/reporting/reporting_report.h" +#include "net/reporting/reporting_target_type.h" #include "url/gurl.h" #include "url/origin.h" @@ -53,7 +54,8 @@ class ReportingCacheImpl : public ReportingCache { base::Value::Dict body, int depth, base::TimeTicks queued, - int attempts) override; + int attempts, + ReportingTargetType target_type) override; void GetReports( std::vector>* reports_out) const override; @@ -143,6 +145,9 @@ class ReportingCacheImpl : public ReportingCache { const base::UnguessableToken& reporting_source, const IsolationInfo& isolation_info, const GURL& url) override; + void SetEnterpriseEndpointForTesting( + const ReportingEndpointGroupKey& group_key, + const GURL& url) override; IsolationInfo GetIsolationInfoForEndpoint( const ReportingEndpoint& endpoint) const override; @@ -394,6 +399,10 @@ class ReportingCacheImpl : public ReportingCache { std::map> document_endpoints_; + // Endpoints set by the enterprise policy. + // TODO(crbug.com/353957526): Implement functions to add enterprise endpoints. + std::vector enterprise_endpoints_; + // Isolation info for each reporting source. Used for determining credentials // to send when delivering reports. This contains only V1 document endpoints. std::map isolation_info_; diff --git a/naiveproxy/src/net/reporting/reporting_delivery_agent.cc b/naiveproxy/src/net/reporting/reporting_delivery_agent.cc index f9fd48b65f..2ff4daf75f 100644 --- a/naiveproxy/src/net/reporting/reporting_delivery_agent.cc +++ b/naiveproxy/src/net/reporting/reporting_delivery_agent.cc @@ -30,6 +30,7 @@ #include "net/reporting/reporting_delegate.h" #include "net/reporting/reporting_endpoint_manager.h" #include "net/reporting/reporting_report.h" +#include "net/reporting/reporting_target_type.h" #include "net/reporting/reporting_uploader.h" #include "url/gurl.h" #include "url/origin.h" @@ -96,12 +97,14 @@ class Delivery { const NetworkAnonymizationKey& network_anonymization_key, const url::Origin& origin, const GURL& endpoint_url, - const std::optional reporting_source) + const std::optional reporting_source, + ReportingTargetType target_type) : isolation_info(isolation_info), network_anonymization_key(network_anonymization_key), origin(origin), endpoint_url(endpoint_url), - reporting_source(reporting_source) { + reporting_source(reporting_source), + target_type(target_type) { DCHECK(network_anonymization_key.IsEmpty() || network_anonymization_key == isolation_info.network_anonymization_key()); @@ -114,9 +117,10 @@ class Delivery { // should not need this (but it doesn't hurt). We can remove that as a // comparison key when V0 reporting endpoints are removed. return std::tie(network_anonymization_key, origin, endpoint_url, - reporting_source) < + reporting_source, target_type) < std::tie(other.network_anonymization_key, other.origin, - other.endpoint_url, other.reporting_source); + other.endpoint_url, other.reporting_source, + other.target_type); } IsolationInfo isolation_info; @@ -124,6 +128,7 @@ class Delivery { url::Origin origin; GURL endpoint_url; std::optional reporting_source; + ReportingTargetType target_type; }; explicit Delivery(const Target& target) : target_(target) {} @@ -141,6 +146,7 @@ class Delivery { network_anonymization_key()); DCHECK(IsSubdomainOf(target_.origin.host() /* subdomain */, endpoint.group_key.origin.host() /* superdomain */)); + DCHECK_EQ(endpoint.group_key.target_type, target_.target_type); for (auto it = reports_begin; it != reports_end; ++it) { DCHECK_EQ((*reports_begin)->GetGroupKey(), (*it)->GetGroupKey()); DCHECK((*it)->network_anonymization_key == network_anonymization_key()); @@ -150,6 +156,7 @@ class Delivery { // configuration's origin. DCHECK(IsSubdomainOf((*it)->url.host_piece() /* subdomain */, endpoint.group_key.origin.host() /* superdomain */)); + DCHECK_EQ((*it)->target_type, target_.target_type); } reports_per_group_[endpoint.group_key] += @@ -323,10 +330,10 @@ class ReportingDeliveryAgentImpl : public ReportingDeliveryAgent, cache()->GetIsolationInfoForEndpoint(endpoint); // Add the reports to the appropriate delivery. - Delivery::Target target(isolation_info, - report_group_key.network_anonymization_key, - report_group_key.origin, endpoint.info.url, - endpoint.group_key.reporting_source); + Delivery::Target target( + isolation_info, report_group_key.network_anonymization_key, + report_group_key.origin, endpoint.info.url, + endpoint.group_key.reporting_source, endpoint.group_key.target_type); auto delivery_it = deliveries.find(target); if (delivery_it == deliveries.end()) { bool inserted; diff --git a/naiveproxy/src/net/reporting/reporting_endpoint.cc b/naiveproxy/src/net/reporting/reporting_endpoint.cc index 2fe25db3dc..90f24a2c50 100644 --- a/naiveproxy/src/net/reporting/reporting_endpoint.cc +++ b/naiveproxy/src/net/reporting/reporting_endpoint.cc @@ -9,6 +9,7 @@ #include "base/time/time.h" #include "net/base/network_anonymization_key.h" +#include "net/reporting/reporting_target_type.h" #include "url/gurl.h" #include "url/origin.h" @@ -19,21 +20,25 @@ ReportingEndpointGroupKey::ReportingEndpointGroupKey() = default; ReportingEndpointGroupKey::ReportingEndpointGroupKey( const NetworkAnonymizationKey& network_anonymization_key, const url::Origin& origin, - const std::string& group_name) + const std::string& group_name, + ReportingTargetType target_type) : ReportingEndpointGroupKey(network_anonymization_key, std::nullopt, origin, - group_name) {} + group_name, + target_type) {} ReportingEndpointGroupKey::ReportingEndpointGroupKey( const NetworkAnonymizationKey& network_anonymization_key, std::optional reporting_source, const url::Origin& origin, - const std::string& group_name) + const std::string& group_name, + ReportingTargetType target_type) : network_anonymization_key(network_anonymization_key), reporting_source(std::move(reporting_source)), origin(origin), - group_name(group_name) { + group_name(group_name), + target_type(target_type) { // If |reporting_source| is present, it must not be empty. DCHECK(!(this->reporting_source.has_value() && this->reporting_source->is_empty())); @@ -45,7 +50,8 @@ ReportingEndpointGroupKey::ReportingEndpointGroupKey( : ReportingEndpointGroupKey(other.network_anonymization_key, reporting_source, other.origin, - other.group_name) {} + other.group_name, + other.target_type) {} ReportingEndpointGroupKey::ReportingEndpointGroupKey( const ReportingEndpointGroupKey& other) = default; @@ -59,14 +65,6 @@ ReportingEndpointGroupKey& ReportingEndpointGroupKey::operator=( ReportingEndpointGroupKey::~ReportingEndpointGroupKey() = default; -bool operator==(const ReportingEndpointGroupKey& lhs, - const ReportingEndpointGroupKey& rhs) { - return std::tie(lhs.reporting_source, lhs.network_anonymization_key, - lhs.origin, lhs.group_name) == - std::tie(rhs.reporting_source, rhs.network_anonymization_key, - rhs.origin, rhs.group_name); -} - bool operator!=(const ReportingEndpointGroupKey& lhs, const ReportingEndpointGroupKey& rhs) { return !(lhs == rhs); @@ -75,24 +73,27 @@ bool operator!=(const ReportingEndpointGroupKey& lhs, bool operator<(const ReportingEndpointGroupKey& lhs, const ReportingEndpointGroupKey& rhs) { return std::tie(lhs.reporting_source, lhs.network_anonymization_key, - lhs.origin, lhs.group_name) < + lhs.origin, lhs.group_name, lhs.target_type) < std::tie(rhs.reporting_source, rhs.network_anonymization_key, - rhs.origin, rhs.group_name); + rhs.origin, rhs.group_name, rhs.target_type); } bool operator>(const ReportingEndpointGroupKey& lhs, const ReportingEndpointGroupKey& rhs) { return std::tie(lhs.reporting_source, lhs.network_anonymization_key, - lhs.origin, lhs.group_name) > + lhs.origin, lhs.group_name, lhs.target_type) > std::tie(rhs.reporting_source, rhs.network_anonymization_key, - rhs.origin, rhs.group_name); + rhs.origin, rhs.group_name, rhs.target_type); } std::string ReportingEndpointGroupKey::ToString() const { return "Source: " + (reporting_source ? reporting_source->ToString() : "null") + "; NAK: " + network_anonymization_key.ToDebugString() + - "; Origin: " + origin.Serialize() + "; Group name: " + group_name; + "; Origin: " + origin.Serialize() + "; Group name: " + group_name + + "; Target type: " + + (target_type == ReportingTargetType::kDeveloper ? "developer" + : "enterprise"); } const int ReportingEndpoint::EndpointInfo::kDefaultPriority = 1; diff --git a/naiveproxy/src/net/reporting/reporting_endpoint.h b/naiveproxy/src/net/reporting/reporting_endpoint.h index 45ec034171..503063b64a 100644 --- a/naiveproxy/src/net/reporting/reporting_endpoint.h +++ b/naiveproxy/src/net/reporting/reporting_endpoint.h @@ -13,6 +13,7 @@ #include "base/unguessable_token.h" #include "net/base/net_export.h" #include "net/base/network_anonymization_key.h" +#include "net/reporting/reporting_target_type.h" #include "url/gurl.h" #include "url/origin.h" @@ -25,13 +26,15 @@ struct NET_EXPORT ReportingEndpointGroupKey { ReportingEndpointGroupKey( const NetworkAnonymizationKey& network_anonymization_key, const url::Origin& origin, - const std::string& group_name); + const std::string& group_name, + ReportingTargetType target_type); ReportingEndpointGroupKey( const NetworkAnonymizationKey& network_anonymization_key, std::optional reporting_source, const url::Origin& origin, - const std::string& group_name); + const std::string& group_name, + ReportingTargetType target_type); ReportingEndpointGroupKey( const ReportingEndpointGroupKey& other, @@ -51,13 +54,20 @@ struct NET_EXPORT ReportingEndpointGroupKey { // V1 document endpoint. bool IsDocumentEndpoint() const { return reporting_source.has_value(); } + // True if this endpoint "group" is set by the enterprise policy. + bool IsEnterpriseEndpoint() const { + return target_type == ReportingTargetType::kEnterprise; + } + // The NetworkAnonymizationKey the group is scoped to. Needed to prevent - // leaking third party contexts across sites. + // leaking third party contexts across sites. This is empty for + // enterprise groups. NetworkAnonymizationKey network_anonymization_key; // Source token for the document or worker which configured this endpoint, if // this was configured with the Reporting-Endpoints header. For endpoint - // groups configured with the Report-To header, this will be nullopt. + // groups configured with the Report-To header and enterprise endpoint groups, + // this will be nullopt. std::optional reporting_source; // Origin that configured this endpoint group. @@ -65,10 +75,17 @@ struct NET_EXPORT ReportingEndpointGroupKey { // Name of the endpoint group (defaults to "default" during header parsing). std::string group_name; + + // Used to distinguish web developer and enterprise entities so that + // enterprise reports aren’t sent to web developer endpoints and web developer + // reports aren’t sent to enterprise endpoints. + ReportingTargetType target_type = ReportingTargetType::kDeveloper; + + NET_EXPORT friend bool operator==(const ReportingEndpointGroupKey& lhs, + const ReportingEndpointGroupKey& rhs) = + default; }; -NET_EXPORT bool operator==(const ReportingEndpointGroupKey& lhs, - const ReportingEndpointGroupKey& rhs); NET_EXPORT bool operator!=(const ReportingEndpointGroupKey& lhs, const ReportingEndpointGroupKey& rhs); NET_EXPORT bool operator<(const ReportingEndpointGroupKey& lhs, diff --git a/naiveproxy/src/net/reporting/reporting_header_parser.cc b/naiveproxy/src/net/reporting/reporting_header_parser.cc index 36ecc12973..4dd58a017e 100644 --- a/naiveproxy/src/net/reporting/reporting_header_parser.cc +++ b/naiveproxy/src/net/reporting/reporting_header_parser.cc @@ -24,6 +24,7 @@ #include "net/reporting/reporting_context.h" #include "net/reporting/reporting_delegate.h" #include "net/reporting/reporting_endpoint.h" +#include "net/reporting/reporting_target_type.h" namespace net { @@ -135,8 +136,11 @@ bool ProcessEndpointGroup( return false; group_name = maybe_group_name->GetString(); } + // The target_type is set to kDeveloper because enterprise endpoints are + // created on a different path. ReportingEndpointGroupKey group_key(network_anonymization_key, origin, - group_name); + group_name, + ReportingTargetType::kDeveloper); parsed_endpoint_group_out->group_key = group_key; int ttl_sec = dict->FindInt(kMaxAgeKey).value_or(-1); @@ -223,8 +227,11 @@ bool ProcessV1Endpoint(ReportingDelegate* delegate, const std::string& endpoint_url_string, ReportingEndpoint& parsed_endpoint_out) { DCHECK(!reporting_source.is_empty()); + // The target_type is set to kDeveloper because enterprise endpoints are + // created on a different path. ReportingEndpointGroupKey group_key(network_anonymization_key, - reporting_source, origin, endpoint_name); + reporting_source, origin, endpoint_name, + ReportingTargetType::kDeveloper); parsed_endpoint_out.group_key = group_key; ReportingEndpoint::EndpointInfo parsed_endpoint; diff --git a/naiveproxy/src/net/reporting/reporting_report.cc b/naiveproxy/src/net/reporting/reporting_report.cc index cecee74746..508c276237 100644 --- a/naiveproxy/src/net/reporting/reporting_report.cc +++ b/naiveproxy/src/net/reporting/reporting_report.cc @@ -25,7 +25,8 @@ ReportingReport::ReportingReport( base::Value::Dict body, int depth, base::TimeTicks queued, - int attempts) + int attempts, + ReportingTargetType target_type) : reporting_source(reporting_source), network_anonymization_key(network_anonymization_key), id(base::UnguessableToken::Create()), @@ -36,7 +37,8 @@ ReportingReport::ReportingReport( body(std::move(body)), depth(depth), queued(queued), - attempts(attempts) { + attempts(attempts), + target_type(target_type) { // If |reporting_source| is present, it must not be empty. DCHECK(!(reporting_source.has_value() && reporting_source->is_empty())); } @@ -48,7 +50,8 @@ ReportingReport::~ReportingReport() = default; ReportingEndpointGroupKey ReportingReport::GetGroupKey() const { return ReportingEndpointGroupKey(network_anonymization_key, reporting_source, - url::Origin::Create(url), group); + url::Origin::Create(url), group, + target_type); } bool ReportingReport::IsUploadPending() const { diff --git a/naiveproxy/src/net/reporting/reporting_report.h b/naiveproxy/src/net/reporting/reporting_report.h index bece78c7fb..da96e56654 100644 --- a/naiveproxy/src/net/reporting/reporting_report.h +++ b/naiveproxy/src/net/reporting/reporting_report.h @@ -15,6 +15,7 @@ #include "net/base/net_export.h" #include "net/base/network_anonymization_key.h" #include "net/reporting/reporting_endpoint.h" +#include "net/reporting/reporting_target_type.h" #include "url/gurl.h" namespace net { @@ -49,7 +50,8 @@ struct NET_EXPORT ReportingReport { base::Value::Dict body, int depth, base::TimeTicks queued, - int attempts); + int attempts, + ReportingTargetType target_type); // Do NOT use this constructor outside of mojo deserialization context. ReportingReport(); @@ -59,11 +61,11 @@ struct NET_EXPORT ReportingReport { ReportingReport& operator=(ReportingReport&& other); ~ReportingReport(); - // Bundles together the NAK, origin of the report URL, and group name. - // This is not exactly the same as the group key of the endpoint that the - // report will be delivered to. The origin may differ if the endpoint is - // configured for a superdomain of the report's origin. The NAK and group name - // will be the same. + // Bundles together the NAK, reporting source, origin of the report URL, group + // name, and target type. This is not exactly the same as the group key of the + // endpoint that the report will be delivered to. The origin may differ if the + // endpoint is configured for a superdomain of the report's origin. The NAK, + // group name, and target type will be the same. ReportingEndpointGroupKey GetGroupKey() const; static void RecordReportDiscardedForNoURLRequestContext(); @@ -122,6 +124,11 @@ struct NET_EXPORT ReportingReport { int attempts = 0; Status status = Status::QUEUED; + + // Used to distinguish web developer and enterprise entities so that + // enterprise reports aren’t sent to web developer endpoints and web developer + // reports aren’t sent to enterprise endpoints + ReportingTargetType target_type = ReportingTargetType::kDeveloper; }; } // namespace net diff --git a/naiveproxy/src/net/reporting/reporting_service.cc b/naiveproxy/src/net/reporting/reporting_service.cc index e575851232..b552cb5e19 100644 --- a/naiveproxy/src/net/reporting/reporting_service.cc +++ b/naiveproxy/src/net/reporting/reporting_service.cc @@ -87,7 +87,8 @@ class ReportingServiceImpl : public ReportingService { const std::string& group, const std::string& type, base::Value::Dict body, - int depth) override { + int depth, + ReportingTargetType target_type) override { DCHECK(context_); DCHECK(context_->delegate()); // If |reporting_source| is provided, it must not be empty. @@ -110,7 +111,7 @@ class ReportingServiceImpl : public ReportingService { base::Unretained(this), reporting_source, FixupNetworkAnonymizationKey(network_anonymization_key), std::move(sanitized_url), user_agent, group, type, - std::move(body), depth, queued_ticks)); + std::move(body), depth, queued_ticks, target_type)); } void ProcessReportToHeader( @@ -213,11 +214,13 @@ class ReportingServiceImpl : public ReportingService { const std::string& type, base::Value::Dict body, int depth, - base::TimeTicks queued_ticks) { + base::TimeTicks queued_ticks, + ReportingTargetType target_type) { DCHECK(initialized_); - context_->cache()->AddReport( - reporting_source, network_anonymization_key, sanitized_url, user_agent, - group, type, std::move(body), depth, queued_ticks, 0 /* attempts */); + context_->cache()->AddReport(reporting_source, network_anonymization_key, + sanitized_url, user_agent, group, type, + std::move(body), depth, queued_ticks, + 0 /* attempts */, target_type); } void DoProcessReportToHeader( diff --git a/naiveproxy/src/net/reporting/reporting_service.h b/naiveproxy/src/net/reporting/reporting_service.h index 91f2d7fdc5..9a53ee54e4 100644 --- a/naiveproxy/src/net/reporting/reporting_service.h +++ b/naiveproxy/src/net/reporting/reporting_service.h @@ -16,6 +16,7 @@ #include "net/base/net_export.h" #include "net/reporting/reporting_cache.h" #include "net/reporting/reporting_cache_observer.h" +#include "net/reporting/reporting_target_type.h" class GURL; @@ -68,6 +69,8 @@ class NET_EXPORT ReportingService { // |user_agent| is the User-Agent header that was used for the request. // |group| is the endpoint group to which the report should be delivered. // |type| is the type of the report. |body| is the body of the report. + // |target_type| is used to tag the report as either a web developer report + // or an enterprise report. // // The Reporting system will take ownership of |body|; all other parameters // will be copied. @@ -79,7 +82,8 @@ class NET_EXPORT ReportingService { const std::string& group, const std::string& type, base::Value::Dict body, - int depth) = 0; + int depth, + ReportingTargetType target_type) = 0; // Processes a Report-To header. |origin| is the Origin of the URL that the // header came from; |header_value| is the normalized value of the Report-To diff --git a/naiveproxy/src/net/reporting/reporting_target_type.h b/naiveproxy/src/net/reporting/reporting_target_type.h new file mode 100644 index 0000000000..cc5ac2c6ea --- /dev/null +++ b/naiveproxy/src/net/reporting/reporting_target_type.h @@ -0,0 +1,17 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_REPORTING_REPORTING_TARGET_TYPE_H_ +#define NET_REPORTING_REPORTING_TARGET_TYPE_H_ + +namespace net { + +// Used to distinguish web developer and enterprise entities so that enterprise +// reports aren’t sent to web developer endpoints and web developer reports +// aren’t sent to enterprise endpoints +enum class ReportingTargetType { kDeveloper, kEnterprise }; + +} // namespace net + +#endif // NET_REPORTING_REPORTING_TARGET_TYPE_H_ diff --git a/naiveproxy/src/net/reporting/reporting_test_util.cc b/naiveproxy/src/net/reporting/reporting_test_util.cc index 4d2679348e..258090aa63 100644 --- a/naiveproxy/src/net/reporting/reporting_test_util.cc +++ b/naiveproxy/src/net/reporting/reporting_test_util.cc @@ -245,6 +245,12 @@ void ReportingTestBase::SetV1EndpointInCache( url); } +void ReportingTestBase::SetEnterpriseEndpointInCache( + const ReportingEndpointGroupKey& group_key, + const GURL& url) { + cache()->SetEnterpriseEndpointForTesting(group_key, url); +} + bool ReportingTestBase::EndpointExistsInCache( const ReportingEndpointGroupKey& group_key, const GURL& url) { @@ -346,7 +352,8 @@ void TestReportingService::QueueReport( const std::string& group, const std::string& type, base::Value::Dict body, - int depth) { + int depth, + ReportingTargetType target_type) { reports_.emplace_back( Report(url, network_anonymization_key, user_agent, group, type, std::make_unique(std::move(body)), depth)); diff --git a/naiveproxy/src/net/reporting/reporting_test_util.h b/naiveproxy/src/net/reporting/reporting_test_util.h index f0c4e1f34c..c315507bf1 100644 --- a/naiveproxy/src/net/reporting/reporting_test_util.h +++ b/naiveproxy/src/net/reporting/reporting_test_util.h @@ -21,6 +21,7 @@ #include "net/reporting/reporting_context.h" #include "net/reporting/reporting_delegate.h" #include "net/reporting/reporting_service.h" +#include "net/reporting/reporting_target_type.h" #include "net/reporting/reporting_uploader.h" #include "net/test/test_with_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" @@ -223,6 +224,11 @@ class ReportingTestBase : public TestWithTaskEnvironment { const IsolationInfo& isolation_info, const GURL& url); + // Sets an enterprise endpoint with the given group_key and url as origin in + // the enterprise endpoints vector. + void SetEnterpriseEndpointInCache(const ReportingEndpointGroupKey& group_key, + const GURL& url); + // Returns whether an endpoint with the given properties exists in the cache. bool EndpointExistsInCache(const ReportingEndpointGroupKey& group_key, const GURL& url); @@ -350,7 +356,8 @@ class TestReportingService : public ReportingService { const std::string& group, const std::string& type, base::Value::Dict body, - int depth) override; + int depth, + ReportingTargetType target_type) override; void ProcessReportToHeader( const url::Origin& url, diff --git a/naiveproxy/src/net/reporting/reporting_uploader.cc b/naiveproxy/src/net/reporting/reporting_uploader.cc index 99781b162a..deb3f72060 100644 --- a/naiveproxy/src/net/reporting/reporting_uploader.cc +++ b/naiveproxy/src/net/reporting/reporting_uploader.cc @@ -10,6 +10,7 @@ #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" +#include "base/not_fatal_until.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "net/base/elements_upload_data_stream.h" @@ -258,7 +259,7 @@ class ReportingUploaderImpl : public ReportingUploader, URLRequest::Delegate { // Grab Upload from map, and hold on to it in a local unique_ptr so it's // removed at the end of the method. auto it = uploads_.find(request); - DCHECK(it != uploads_.end()); + CHECK(it != uploads_.end(), base::NotFatalUntil::M130); std::unique_ptr upload = std::move(it->second); uploads_.erase(it); diff --git a/naiveproxy/src/net/server/http_connection.cc b/naiveproxy/src/net/server/http_connection.cc index 5b25790392..518552f3f7 100644 --- a/naiveproxy/src/net/server/http_connection.cc +++ b/naiveproxy/src/net/server/http_connection.cc @@ -53,7 +53,7 @@ bool HttpConnection::ReadIOBuffer::IncreaseCapacity() { } char* HttpConnection::ReadIOBuffer::StartOfBuffer() const { - return base_->StartOfBuffer(); + return base::as_writable_chars(base_->everything()).data(); } int HttpConnection::ReadIOBuffer::GetSize() const { diff --git a/naiveproxy/src/net/shared_dictionary/OWNERS b/naiveproxy/src/net/shared_dictionary/OWNERS new file mode 100644 index 0000000000..96c689437f --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/OWNERS @@ -0,0 +1,5 @@ +# Primary +horo@chromium.org + +# Secondary +pmeenan@chromium.org diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary.h b/naiveproxy/src/net/shared_dictionary/shared_dictionary.h new file mode 100644 index 0000000000..b374c95975 --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary.h @@ -0,0 +1,52 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SHARED_DICTIONARY_SHARED_DICTIONARY_H_ +#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_H_ + +#include + +#include "base/functional/callback.h" +#include "base/memory/ref_counted.h" +#include "net/base/net_export.h" + +namespace net { +class IOBuffer; +struct SHA256HashValue; + +// This class is used to read the binary of the shared dictionary. +class NET_EXPORT SharedDictionary : public base::RefCounted { + public: + // Reads the whole binary of the dictionary. If an error has occurred, returns + // ERR_FAILED. If the binary of the dictionary is already in the memory + // returns OK. Otherwise returns ERR_IO_PENDING and `callback` will be called + // asynchronously with OK or ERR_FAILED depending on the success status. + virtual int ReadAll(base::OnceCallback callback) = 0; + + // Returns the buffer which contains the binary of the dictionary. + // ReadAll() must have succeeded before calling this method. + virtual scoped_refptr data() const = 0; + + // Returns the binary size of the dictionary. It is safe to call this method + // before calling ReadAll(). + virtual size_t size() const = 0; + + // Returns the hash of the binary of the dictionary. It is safe to call this + // method before calling ReadAll(). + virtual const SHA256HashValue& hash() const = 0; + + // Returns the server-provided id of the dictionary. When this id is not + // empty, it will be serialized [RFC8941] and sent in "Dictionary-ID" request + // when Chrome can use the dictionary. + // https://www.rfc-editor.org/rfc/rfc8941#name-serializing-a-string + virtual const std::string& id() const = 0; + + protected: + friend class base::RefCounted; + virtual ~SharedDictionary() = default; +}; + +} // namespace net + +#endif // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_H_ diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary_constants.h b/naiveproxy/src/net/shared_dictionary/shared_dictionary_constants.h new file mode 100644 index 0000000000..7a719452b7 --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_constants.h @@ -0,0 +1,21 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SHARED_DICTIONARY_SHARED_DICTIONARY_CONSTANTS_H_ +#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_CONSTANTS_H_ + +namespace net::shared_dictionary { + +// The content encoding name of Dictionary-Compressed Brotli. +static constexpr char kSharedBrotliContentEncodingName[] = "dcb"; + +// The content encoding name of Dictionary-Compressed Zstandard. +static constexpr char kSharedZstdContentEncodingName[] = "dcz"; + +// The header name of "available-dictionary". +static constexpr char kAvailableDictionaryHeaderName[] = "available-dictionary"; + +} // namespace net::shared_dictionary + +#endif // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_CONSTANTS_H_ diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary_getter.h b/naiveproxy/src/net/shared_dictionary/shared_dictionary_getter.h new file mode 100644 index 0000000000..e44f1356b1 --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_getter.h @@ -0,0 +1,28 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SHARED_DICTIONARY_SHARED_DICTIONARY_GETTER_H_ +#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_GETTER_H_ + +#include +#include + +#include "base/functional/callback_forward.h" +#include "base/memory/scoped_refptr.h" +#include "net/shared_dictionary/shared_dictionary_isolation_key.h" + +class GURL; + +namespace net { + +class SharedDictionary; + +using SharedDictionaryGetter = + base::RepeatingCallback( + const std::optional& isolation_key, + const GURL& request_url)>; + +} // namespace net + +#endif // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_GETTER_H_ diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary_header_checker_source_stream.cc b/naiveproxy/src/net/shared_dictionary/shared_dictionary_header_checker_source_stream.cc new file mode 100644 index 0000000000..bac94680a0 --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_header_checker_source_stream.cc @@ -0,0 +1,183 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/shared_dictionary/shared_dictionary_header_checker_source_stream.h" + +#include "base/check_op.h" +#include "base/containers/span.h" +#include "base/functional/callback_helpers.h" +#include "base/strings/string_number_conversions.h" +#include "net/base/hash_value.h" +#include "net/base/io_buffer.h" + +namespace net { +namespace { + +static constexpr unsigned char kCompressionTypeBrotliSignature[] = {0xff, 0x44, + 0x43, 0x42}; +static constexpr unsigned char kCompressionTypeZstdSignature[] = { + 0x5e, 0x2a, 0x4d, 0x18, 0x20, 0x00, 0x00, 0x00}; +static constexpr size_t kCompressionTypeBrotliSignatureSize = + sizeof(kCompressionTypeBrotliSignature); +static constexpr size_t kCompressionTypeZstdSignatureSize = + sizeof(kCompressionTypeZstdSignature); +static constexpr int kCompressionDictionaryHashSize = 32; +static_assert(sizeof(SHA256HashValue) == kCompressionDictionaryHashSize, + "kCompressionDictionaryHashSize mismatch"); +static constexpr int kCompressionTypeBrotliHeaderSize = + kCompressionTypeBrotliSignatureSize + kCompressionDictionaryHashSize; +static constexpr int kCompressionTypeZstdHeaderSize = + kCompressionTypeZstdSignatureSize + kCompressionDictionaryHashSize; + +size_t GetSignatureSize(SharedDictionaryHeaderCheckerSourceStream::Type type) { + switch (type) { + case SharedDictionaryHeaderCheckerSourceStream::Type:: + kDictionaryCompressedBrotli: + return kCompressionTypeBrotliSignatureSize; + case SharedDictionaryHeaderCheckerSourceStream::Type:: + kDictionaryCompressedZstd: + return kCompressionTypeZstdSignatureSize; + } +} + +size_t GetHeaderSize(SharedDictionaryHeaderCheckerSourceStream::Type type) { + switch (type) { + case SharedDictionaryHeaderCheckerSourceStream::Type:: + kDictionaryCompressedBrotli: + return kCompressionTypeBrotliHeaderSize; + case SharedDictionaryHeaderCheckerSourceStream::Type:: + kDictionaryCompressedZstd: + return kCompressionTypeZstdHeaderSize; + } +} + +base::span GetExpectedSignature( + SharedDictionaryHeaderCheckerSourceStream::Type type) { + switch (type) { + case SharedDictionaryHeaderCheckerSourceStream::Type:: + kDictionaryCompressedBrotli: + return kCompressionTypeBrotliSignature; + case SharedDictionaryHeaderCheckerSourceStream::Type:: + kDictionaryCompressedZstd: + return kCompressionTypeZstdSignature; + } +} + +} // namespace + +SharedDictionaryHeaderCheckerSourceStream:: + SharedDictionaryHeaderCheckerSourceStream( + std::unique_ptr upstream, + Type type, + const SHA256HashValue& dictionary_hash) + : SourceStream(SourceStream::TYPE_NONE), + upstream_(std::move(upstream)), + type_(type), + dictionary_hash_(dictionary_hash), + head_read_buffer_(base::MakeRefCounted()) { + head_read_buffer_->SetCapacity(GetHeaderSize(type_)); + ReadHeader(); +} + +SharedDictionaryHeaderCheckerSourceStream:: + ~SharedDictionaryHeaderCheckerSourceStream() = default; + +int SharedDictionaryHeaderCheckerSourceStream::Read( + IOBuffer* dest_buffer, + int buffer_size, + CompletionOnceCallback callback) { + if (header_check_result_ == OK) { + return upstream_->Read(dest_buffer, buffer_size, std::move(callback)); + } + if (header_check_result_ == ERR_IO_PENDING) { + CHECK(head_read_buffer_); + // Still reading header. + pending_read_buf_ = dest_buffer; + pending_read_buf_len_ = buffer_size; + pending_callback_ = std::move(callback); + } + return header_check_result_; +} + +std::string SharedDictionaryHeaderCheckerSourceStream::Description() const { + return "SharedDictionaryHeaderCheckerSourceStream"; +} + +bool SharedDictionaryHeaderCheckerSourceStream::MayHaveMoreBytes() const { + return upstream_->MayHaveMoreBytes(); +} + +void SharedDictionaryHeaderCheckerSourceStream::ReadHeader() { + int result = upstream_->Read( + head_read_buffer_.get(), head_read_buffer_->RemainingCapacity(), + base::BindOnce( + &SharedDictionaryHeaderCheckerSourceStream::OnReadCompleted, + base::Unretained(this))); + if (result != ERR_IO_PENDING) { + OnReadCompleted(result); + } +} + +void SharedDictionaryHeaderCheckerSourceStream::OnReadCompleted(int result) { + CHECK_NE(result, ERR_IO_PENDING); + if (result <= 0) { + // OK means the stream is closed before reading header. + if (result == OK) { + result = ERR_UNEXPECTED_CONTENT_DICTIONARY_HEADER; + } + HeaderCheckCompleted(result); + return; + } + head_read_buffer_->set_offset(head_read_buffer_->offset() + result); + if (head_read_buffer_->RemainingCapacity() != 0) { + ReadHeader(); + return; + } + HeaderCheckCompleted( + CheckHeaderBuffer() ? OK : ERR_UNEXPECTED_CONTENT_DICTIONARY_HEADER); +} + +bool SharedDictionaryHeaderCheckerSourceStream::CheckHeaderBuffer() const { + CHECK(head_read_buffer_->RemainingCapacity() == 0); + if (GetSignatureInBuffer() != GetExpectedSignature(type_)) { + return false; + } + if (GetHashInBuffer() != base::span(dictionary_hash_.data)) { + return false; + } + return true; +} + +void SharedDictionaryHeaderCheckerSourceStream::HeaderCheckCompleted( + int header_check_result) { + CHECK_NE(header_check_result, ERR_IO_PENDING); + CHECK_EQ(header_check_result_, ERR_IO_PENDING); + + header_check_result_ = header_check_result; + head_read_buffer_.reset(); + + if (!pending_callback_) { + return; + } + + auto callback_split = base::SplitOnceCallback(std::move(pending_callback_)); + int read_result = Read(pending_read_buf_.get(), pending_read_buf_len_, + std::move(callback_split.first)); + if (read_result != ERR_IO_PENDING) { + std::move(callback_split.second).Run(read_result); + } +} + +base::span +SharedDictionaryHeaderCheckerSourceStream::GetSignatureInBuffer() const { + return head_read_buffer_->everything().subspan(0, GetSignatureSize(type_)); +} + +base::span +SharedDictionaryHeaderCheckerSourceStream::GetHashInBuffer() const { + return head_read_buffer_->everything().subspan( + GetSignatureSize(type_), kCompressionDictionaryHashSize); +} + +} // namespace net diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary_header_checker_source_stream.h b/naiveproxy/src/net/shared_dictionary/shared_dictionary_header_checker_source_stream.h new file mode 100644 index 0000000000..ce6f85b12e --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_header_checker_source_stream.h @@ -0,0 +1,84 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SHARED_DICTIONARY_SHARED_DICTIONARY_HEADER_CHECKER_SOURCE_STREAM_H_ +#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_HEADER_CHECKER_SOURCE_STREAM_H_ + +#include +#include + +#include "net/base/completion_once_callback.h" +#include "net/base/hash_value.h" +#include "net/base/net_export.h" +#include "net/filter/source_stream.h" + +namespace net { +class IOBuffer; +class GrowableIOBuffer; + +// This class is used to check the header bytes of "Dictionary-Compressed +// Brotli" stream and "Dictionary-Compressed Zstandard" stream. +// +// The "Dictionary-Compressed Brotli" stream's header is 36 bytes containing: +// - 4 bytes magic number: 0xff, 0x44, 0x43, 0x42 +// - 32 bytes SHA-256 hash digest of the dictionary. +// The "Dictionary-Compressed Zstandard" stream's header is 40 bytes containing: +// - 8 bytes magic number: 0x5e, 0x2a, 0x4d, 0x18, 0x20, 0x00, 0x00, 0x00 +// - 32 bytes SHA-256 hash digest of the dictionary. +// +// When an error occurred while reading the upstream, this class passes the +// error to the reader of this class. When the header bytes from the upstream +// was different from the expected header, this class passes +// ERR_UNEXPECTED_CONTENT_DICTIONARY_HEADER to the reader. +// +// This class consumes the header bytes from the upstream. So the reader of +// this class can read the bytes after the header bytes. +class NET_EXPORT SharedDictionaryHeaderCheckerSourceStream + : public SourceStream { + public: + enum class Type { + kDictionaryCompressedBrotli, + kDictionaryCompressedZstd, + }; + SharedDictionaryHeaderCheckerSourceStream( + std::unique_ptr upstream, + Type type, + const SHA256HashValue& dictionary_hash); + SharedDictionaryHeaderCheckerSourceStream( + const SharedDictionaryHeaderCheckerSourceStream&) = delete; + SharedDictionaryHeaderCheckerSourceStream& operator=( + const SharedDictionaryHeaderCheckerSourceStream&) = delete; + ~SharedDictionaryHeaderCheckerSourceStream() override; + + // SourceStream implementation: + int Read(IOBuffer* dest_buffer, + int buffer_size, + CompletionOnceCallback callback) override; + std::string Description() const override; + bool MayHaveMoreBytes() const override; + + private: + void ReadHeader(); + void OnReadCompleted(int result); + bool CheckHeaderBuffer() const; + void HeaderCheckCompleted(int header_check_result); + + base::span GetSignatureInBuffer() const; + base::span GetHashInBuffer() const; + + std::unique_ptr upstream_; + const Type type_; + const SHA256HashValue dictionary_hash_; + + scoped_refptr head_read_buffer_; + int header_check_result_ = ERR_IO_PENDING; + + scoped_refptr pending_read_buf_; + int pending_read_buf_len_ = 0; + CompletionOnceCallback pending_callback_; +}; + +} // namespace net + +#endif // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_HEADER_CHECKER_SOURCE_STREAM_H_ diff --git a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.cc b/naiveproxy/src/net/shared_dictionary/shared_dictionary_isolation_key.cc similarity index 88% rename from naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.cc rename to naiveproxy/src/net/shared_dictionary/shared_dictionary_isolation_key.cc index a53e04a4d2..654de69afa 100644 --- a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.cc +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_isolation_key.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/extras/shared_dictionary/shared_dictionary_isolation_key.h" +#include "net/shared_dictionary/shared_dictionary_isolation_key.h" #include "net/base/isolation_info.h" #include "net/base/network_isolation_key.h" @@ -11,8 +11,7 @@ namespace net { // static std::optional -SharedDictionaryIsolationKey::MaybeCreate( - const net::IsolationInfo& isolation_info) { +SharedDictionaryIsolationKey::MaybeCreate(const IsolationInfo& isolation_info) { if (!isolation_info.frame_origin() || isolation_info.frame_origin()->opaque() || !isolation_info.top_frame_origin() || @@ -22,7 +21,7 @@ SharedDictionaryIsolationKey::MaybeCreate( } return SharedDictionaryIsolationKey( *isolation_info.frame_origin(), - net::SchemefulSite(*isolation_info.top_frame_origin())); + SchemefulSite(*isolation_info.top_frame_origin())); } // static @@ -42,7 +41,7 @@ SharedDictionaryIsolationKey::MaybeCreate( SharedDictionaryIsolationKey::SharedDictionaryIsolationKey( const url::Origin& frame_origin, - const net::SchemefulSite& top_frame_site) + const SchemefulSite& top_frame_site) : frame_origin_(frame_origin), top_frame_site_(top_frame_site) { CHECK(!frame_origin.opaque()); CHECK(!top_frame_site.opaque()); diff --git a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.h b/naiveproxy/src/net/shared_dictionary/shared_dictionary_isolation_key.h similarity index 78% rename from naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.h rename to naiveproxy/src/net/shared_dictionary/shared_dictionary_isolation_key.h index 52421b6c66..3035c611cb 100644 --- a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.h +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_isolation_key.h @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_EXTRAS_SHARED_DICTIONARY_SHARED_DICTIONARY_ISOLATION_KEY_H_ -#define NET_EXTRAS_SHARED_DICTIONARY_SHARED_DICTIONARY_ISOLATION_KEY_H_ +#ifndef NET_SHARED_DICTIONARY_SHARED_DICTIONARY_ISOLATION_KEY_H_ +#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_ISOLATION_KEY_H_ #include -#include "base/component_export.h" +#include "net/base/net_export.h" #include "net/base/schemeful_site.h" #include "url/origin.h" @@ -16,13 +16,13 @@ class IsolationInfo; class NetworkIsolationKey; // Key used to isolate shared dictionary storages. -class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryIsolationKey { +class NET_EXPORT SharedDictionaryIsolationKey { public: // Creates a SharedDictionaryIsolationKey. Returns nullopt when // `frame_origin` or `top_frame_origin` of `isolation_info` is not set or // opaque, or `nonce` is set. static std::optional MaybeCreate( - const net::IsolationInfo& isolation_info); + const IsolationInfo& isolation_info); // Creates a SharedDictionaryIsolationKey. Returns nullopt when // `frame_origin` or `top_frame_origin` of `network_isolation_key` is not set @@ -33,10 +33,10 @@ class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryIsolationKey { SharedDictionaryIsolationKey() = default; SharedDictionaryIsolationKey(const url::Origin& frame_origin, - const net::SchemefulSite& top_frame_site); + const SchemefulSite& top_frame_site); const url::Origin& frame_origin() const { return frame_origin_; } - const net::SchemefulSite& top_frame_site() const { return top_frame_site_; } + const SchemefulSite& top_frame_site() const { return top_frame_site_; } ~SharedDictionaryIsolationKey(); @@ -60,9 +60,9 @@ class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryIsolationKey { private: url::Origin frame_origin_; - net::SchemefulSite top_frame_site_; + SchemefulSite top_frame_site_; }; } // namespace net -#endif // NET_EXTRAS_SHARED_DICTIONARY_SHARED_DICTIONARY_ISOLATION_KEY_H_ +#endif // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_ISOLATION_KEY_H_ diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction.cc b/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction.cc new file mode 100644 index 0000000000..23828890d9 --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction.cc @@ -0,0 +1,521 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/shared_dictionary/shared_dictionary_network_transaction.h" + +#include +#include +#include + +#include "base/base64.h" +#include "base/feature_list.h" +#include "base/functional/bind.h" +#include "base/functional/callback_helpers.h" +#include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" +#include "base/notreached.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/types/expected.h" +#include "net/base/completion_once_callback.h" +#include "net/base/features.h" +#include "net/base/hash_value.h" +#include "net/base/io_buffer.h" +#include "net/base/load_flags.h" +#include "net/base/net_errors.h" +#include "net/base/transport_info.h" +#include "net/base/url_util.h" +#include "net/cert/x509_certificate.h" +#include "net/filter/brotli_source_stream.h" +#include "net/filter/filter_source_stream.h" +#include "net/filter/source_stream.h" +#include "net/filter/zstd_source_stream.h" +#include "net/http/http_request_info.h" +#include "net/http/structured_headers.h" +#include "net/shared_dictionary/shared_dictionary_constants.h" +#include "net/shared_dictionary/shared_dictionary_header_checker_source_stream.h" +#include "net/shared_dictionary/shared_dictionary_isolation_key.h" +#include "net/ssl/ssl_private_key.h" + +namespace net { + +namespace { + +// Convert the interface from HttpTransaction to SourceStream. +class ProxyingSourceStream : public SourceStream { + public: + explicit ProxyingSourceStream(HttpTransaction* transaction) + : SourceStream(SourceStream::TYPE_NONE), transaction_(transaction) {} + + ProxyingSourceStream(const ProxyingSourceStream&) = delete; + ProxyingSourceStream& operator=(const ProxyingSourceStream&) = delete; + + ~ProxyingSourceStream() override = default; + + // SourceStream implementation: + int Read(IOBuffer* dest_buffer, + int buffer_size, + CompletionOnceCallback callback) override { + DCHECK(transaction_); + return transaction_->Read(dest_buffer, buffer_size, std::move(callback)); + } + + std::string Description() const override { return std::string(); } + + bool MayHaveMoreBytes() const override { return true; } + + private: + const raw_ptr transaction_; +}; + +void AddAcceptEncoding(HttpRequestHeaders* request_headers, + std::string_view encoding_header) { + std::string accept_encoding; + request_headers->SetHeader( + HttpRequestHeaders::kAcceptEncoding, + request_headers->GetHeader(HttpRequestHeaders::kAcceptEncoding, + &accept_encoding) + ? base::StrCat({accept_encoding, ", ", encoding_header}) + : std::string(encoding_header)); +} + +} // namespace + +SharedDictionaryNetworkTransaction::PendingReadTask::PendingReadTask( + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) + : buf(buf), buf_len(buf_len), callback(std::move(callback)) {} + +SharedDictionaryNetworkTransaction::PendingReadTask::~PendingReadTask() = + default; + +SharedDictionaryNetworkTransaction::SharedDictionaryNetworkTransaction( + std::unique_ptr network_transaction, + bool enable_shared_zstd) + : enable_shared_zstd_(enable_shared_zstd), + network_transaction_(std::move(network_transaction)) { + network_transaction_->SetConnectedCallback( + base::BindRepeating(&SharedDictionaryNetworkTransaction::OnConnected, + base::Unretained(this))); +} + +SharedDictionaryNetworkTransaction::~SharedDictionaryNetworkTransaction() = + default; + +int SharedDictionaryNetworkTransaction::Start(const HttpRequestInfo* request, + CompletionOnceCallback callback, + const NetLogWithSource& net_log) { + if (!(request->load_flags & LOAD_CAN_USE_SHARED_DICTIONARY) || + !request->dictionary_getter) { + return network_transaction_->Start(request, std::move(callback), net_log); + } + std::optional isolation_key = + SharedDictionaryIsolationKey::MaybeCreate(request->network_isolation_key, + request->frame_origin); + shared_dictionary_getter_ = base::BindRepeating(request->dictionary_getter, + isolation_key, request->url); + + // Safe to bind unretained `this` because the callback is owned by + // `network_transaction_` which is owned by `this`. + network_transaction_->SetModifyRequestHeadersCallback(base::BindRepeating( + &SharedDictionaryNetworkTransaction::ModifyRequestHeaders, + base::Unretained(this), request->url)); + return network_transaction_->Start( + request, + base::BindOnce(&SharedDictionaryNetworkTransaction::OnStartCompleted, + base::Unretained(this), std::move(callback)), + net_log); +} + +SharedDictionaryNetworkTransaction::SharedDictionaryEncodingType +SharedDictionaryNetworkTransaction::ParseSharedDictionaryEncodingType( + const HttpResponseHeaders& headers) { + std::string content_encoding; + if (!headers.GetNormalizedHeader("Content-Encoding", &content_encoding)) { + return SharedDictionaryEncodingType::kNotUsed; + } else if (content_encoding == + shared_dictionary::kSharedBrotliContentEncodingName) { + return SharedDictionaryEncodingType::kSharedBrotli; + } else if (enable_shared_zstd_ && + content_encoding == + shared_dictionary::kSharedZstdContentEncodingName) { + return SharedDictionaryEncodingType::kSharedZstd; + } + return SharedDictionaryEncodingType::kNotUsed; +} + +void SharedDictionaryNetworkTransaction::OnStartCompleted( + CompletionOnceCallback callback, + int result) { + if (shared_dictionary_) { + base::UmaHistogramSparse( + base::StrCat({"Net.SharedDictionaryTransaction.NetResultWithDict.", + cert_is_issued_by_known_root_ + ? "KnownRootCert" + : "UnknownRootCertOrNoCert"}), + -result); + } + + if (result != OK || !shared_dictionary_) { + std::move(callback).Run(result); + return; + } + + shared_dictionary_encoding_type_ = ParseSharedDictionaryEncodingType( + *network_transaction_->GetResponseInfo()->headers); + if (shared_dictionary_encoding_type_ == + SharedDictionaryEncodingType::kNotUsed) { + std::move(callback).Run(result); + return; + } + + shared_dictionary_used_response_info_ = std::make_unique( + *network_transaction_->GetResponseInfo()); + shared_dictionary_used_response_info_->did_use_shared_dictionary = true; + std::move(callback).Run(result); +} + +void SharedDictionaryNetworkTransaction::ModifyRequestHeaders( + const GURL& request_url, + HttpRequestHeaders* request_headers) { + // `shared_dictionary_` may have been already set if this transaction was + // restarted + if (!shared_dictionary_) { + shared_dictionary_ = shared_dictionary_getter_.Run(); + } + if (!shared_dictionary_) { + return; + } + + if (!IsLocalhost(request_url)) { + if (!base::FeatureList::IsEnabled( + features::kCompressionDictionaryTransportOverHttp1) && + negotiated_protocol_ != kProtoHTTP2 && + negotiated_protocol_ != kProtoQUIC) { + shared_dictionary_.reset(); + return; + } + if (!base::FeatureList::IsEnabled( + features::kCompressionDictionaryTransportOverHttp2) && + negotiated_protocol_ == kProtoHTTP2) { + shared_dictionary_.reset(); + return; + } + } + if (base::FeatureList::IsEnabled( + features::kCompressionDictionaryTransportRequireKnownRootCert) && + !cert_is_issued_by_known_root_ && !IsLocalhost(request_url)) { + shared_dictionary_.reset(); + return; + } + + // `is_shared_dictionary_read_allowed_callback_` triggers a notification of + // the shared dictionary usage to the browser process. So we need to call + // `is_shared_dictionary_read_allowed_callback_` after checking the result + // of `GetDictionarySync()`. + CHECK(is_shared_dictionary_read_allowed_callback_); + if (!is_shared_dictionary_read_allowed_callback_.Run()) { + shared_dictionary_.reset(); + return; + } + dictionary_hash_base64_ = base::StrCat( + {":", base::Base64Encode(shared_dictionary_->hash().data), ":"}); + request_headers->SetHeader(shared_dictionary::kAvailableDictionaryHeaderName, + dictionary_hash_base64_); + if (enable_shared_zstd_) { + AddAcceptEncoding( + request_headers, + base::StrCat({shared_dictionary::kSharedBrotliContentEncodingName, ", ", + shared_dictionary::kSharedZstdContentEncodingName})); + } else { + AddAcceptEncoding(request_headers, + shared_dictionary::kSharedBrotliContentEncodingName); + } + + if (!shared_dictionary_->id().empty()) { + std::optional serialized_id = + structured_headers::SerializeItem(shared_dictionary_->id()); + if (serialized_id) { + request_headers->SetHeader("Dictionary-ID", *serialized_id); + } + } + + if (dictionary_status_ == DictionaryStatus::kNoDictionary) { + dictionary_status_ = DictionaryStatus::kReading; + auto split_callback = base::SplitOnceCallback(base::BindOnce( + [](base::WeakPtr self, + base::Time read_start_time, int result) { + if (!self) { + bool succeeded = result == OK; + base::UmaHistogramTimes( + base::StrCat({"Net.SharedDictionaryTransaction." + "AbortedWhileReadingDictionary.", + succeeded ? "Success" : "Failure"}), + base::Time::Now() - read_start_time); + return; + } + self->OnReadSharedDictionary(read_start_time, result); + }, + weak_factory_.GetWeakPtr(), /*read_start_time=*/base::Time::Now())); + + int read_result = + shared_dictionary_->ReadAll(std::move(split_callback.first)); + if (read_result != ERR_IO_PENDING) { + std::move(split_callback.second).Run(read_result); + } + } +} + +void SharedDictionaryNetworkTransaction::OnReadSharedDictionary( + base::Time read_start_time, + int result) { + bool succeeded = result == OK; + base::UmaHistogramTimes( + base::StrCat({"Net.SharedDictionaryTransaction.DictionaryReadLatency.", + succeeded ? "Success" : "Failure"}), + base::Time::Now() - read_start_time); + if (!succeeded) { + dictionary_status_ = DictionaryStatus::kFailed; + } else { + dictionary_status_ = DictionaryStatus::kFinished; + CHECK(shared_dictionary_->data()); + } + if (pending_read_task_) { + auto task = std::move(pending_read_task_); + auto split_callback = base::SplitOnceCallback(std::move(task->callback)); + int ret = + Read(task->buf.get(), task->buf_len, std::move(split_callback.first)); + if (ret != ERR_IO_PENDING) { + std::move(split_callback.second).Run(ret); + } + } +} + +int SharedDictionaryNetworkTransaction::RestartIgnoringLastError( + CompletionOnceCallback callback) { + shared_dictionary_used_response_info_.reset(); + return network_transaction_->RestartIgnoringLastError( + base::BindOnce(&SharedDictionaryNetworkTransaction::OnStartCompleted, + base::Unretained(this), std::move(callback))); +} + +int SharedDictionaryNetworkTransaction::RestartWithCertificate( + scoped_refptr client_cert, + scoped_refptr client_private_key, + CompletionOnceCallback callback) { + shared_dictionary_used_response_info_.reset(); + return network_transaction_->RestartWithCertificate( + std::move(client_cert), std::move(client_private_key), + base::BindOnce(&SharedDictionaryNetworkTransaction::OnStartCompleted, + base::Unretained(this), std::move(callback))); +} + +int SharedDictionaryNetworkTransaction::RestartWithAuth( + const AuthCredentials& credentials, + CompletionOnceCallback callback) { + shared_dictionary_used_response_info_.reset(); + return network_transaction_->RestartWithAuth( + credentials, + base::BindOnce(&SharedDictionaryNetworkTransaction::OnStartCompleted, + base::Unretained(this), std::move(callback))); +} + +bool SharedDictionaryNetworkTransaction::IsReadyToRestartForAuth() { + return network_transaction_->IsReadyToRestartForAuth(); +} + +int SharedDictionaryNetworkTransaction::Read(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + if (!shared_dictionary_used_response_info_) { + return network_transaction_->Read(buf, buf_len, std::move(callback)); + } + + switch (dictionary_status_) { + case DictionaryStatus::kNoDictionary: + NOTREACHED_NORETURN(); + case DictionaryStatus::kReading: + CHECK(!pending_read_task_); + pending_read_task_ = + std::make_unique(buf, buf_len, std::move(callback)); + return ERR_IO_PENDING; + case DictionaryStatus::kFinished: + if (!shared_compression_stream_) { + // Wrap the source `network_transaction_` with a + // SharedDictionaryHeaderCheckerSourceStream to check the header + // of Dictionary-Compressed stream. + std::unique_ptr header_checker_source_stream = + std::make_unique( + std::make_unique( + network_transaction_.get()), + shared_dictionary_encoding_type_ == + SharedDictionaryEncodingType::kSharedBrotli + ? SharedDictionaryHeaderCheckerSourceStream::Type:: + kDictionaryCompressedBrotli + : SharedDictionaryHeaderCheckerSourceStream::Type:: + kDictionaryCompressedZstd, + shared_dictionary_->hash()); + if (shared_dictionary_encoding_type_ == + SharedDictionaryEncodingType::kSharedBrotli) { + SCOPED_UMA_HISTOGRAM_TIMER_MICROS( + "Network.SharedDictionary." + "CreateBrotliSourceStreamWithDictionary"); + shared_compression_stream_ = CreateBrotliSourceStreamWithDictionary( + std::move(header_checker_source_stream), + shared_dictionary_->data(), shared_dictionary_->size()); + } else if (shared_dictionary_encoding_type_ == + SharedDictionaryEncodingType::kSharedZstd) { + SCOPED_UMA_HISTOGRAM_TIMER_MICROS( + "Network.SharedDictionary.CreateZstdSourceStreamWithDictionary"); + shared_compression_stream_ = CreateZstdSourceStreamWithDictionary( + std::move(header_checker_source_stream), + shared_dictionary_->data(), shared_dictionary_->size()); + } + + UMA_HISTOGRAM_ENUMERATION("Network.SharedDictionary.EncodingType", + shared_dictionary_encoding_type_); + } + // When NET_DISABLE_ZSTD or NET_DISABLE_ZSTD is set, + // `shared_compression_stream_` can be null. + if (!shared_compression_stream_) { + return ERR_CONTENT_DECODING_FAILED; + } + return shared_compression_stream_->Read(buf, buf_len, + std::move(callback)); + case DictionaryStatus::kFailed: + return ERR_DICTIONARY_LOAD_FAILED; + } +} + +void SharedDictionaryNetworkTransaction::StopCaching() { + network_transaction_->StopCaching(); +} + +int64_t SharedDictionaryNetworkTransaction::GetTotalReceivedBytes() const { + return network_transaction_->GetTotalReceivedBytes(); +} + +int64_t SharedDictionaryNetworkTransaction::GetTotalSentBytes() const { + return network_transaction_->GetTotalSentBytes(); +} + +int64_t SharedDictionaryNetworkTransaction::GetReceivedBodyBytes() const { + return network_transaction_->GetReceivedBodyBytes(); +} + +void SharedDictionaryNetworkTransaction::DoneReading() { + network_transaction_->DoneReading(); +} + +const HttpResponseInfo* SharedDictionaryNetworkTransaction::GetResponseInfo() + const { + if (shared_dictionary_used_response_info_) { + return shared_dictionary_used_response_info_.get(); + } + return network_transaction_->GetResponseInfo(); +} + +LoadState SharedDictionaryNetworkTransaction::GetLoadState() const { + return network_transaction_->GetLoadState(); +} + +void SharedDictionaryNetworkTransaction::SetQuicServerInfo( + QuicServerInfo* quic_server_info) { + network_transaction_->SetQuicServerInfo(quic_server_info); +} + +bool SharedDictionaryNetworkTransaction::GetLoadTimingInfo( + LoadTimingInfo* load_timing_info) const { + return network_transaction_->GetLoadTimingInfo(load_timing_info); +} + +bool SharedDictionaryNetworkTransaction::GetRemoteEndpoint( + IPEndPoint* endpoint) const { + return network_transaction_->GetRemoteEndpoint(endpoint); +} + +void SharedDictionaryNetworkTransaction::PopulateNetErrorDetails( + NetErrorDetails* details) const { + return network_transaction_->PopulateNetErrorDetails(details); +} + +void SharedDictionaryNetworkTransaction::SetPriority(RequestPriority priority) { + network_transaction_->SetPriority(priority); +} + +void SharedDictionaryNetworkTransaction:: + SetWebSocketHandshakeStreamCreateHelper( + WebSocketHandshakeStreamBase::CreateHelper* create_helper) { + network_transaction_->SetWebSocketHandshakeStreamCreateHelper(create_helper); +} + +void SharedDictionaryNetworkTransaction::SetBeforeNetworkStartCallback( + BeforeNetworkStartCallback callback) { + network_transaction_->SetBeforeNetworkStartCallback(std::move(callback)); +} + +void SharedDictionaryNetworkTransaction::SetRequestHeadersCallback( + RequestHeadersCallback callback) { + network_transaction_->SetRequestHeadersCallback(std::move(callback)); +} + +void SharedDictionaryNetworkTransaction::SetResponseHeadersCallback( + ResponseHeadersCallback callback) { + network_transaction_->SetResponseHeadersCallback(std::move(callback)); +} + +void SharedDictionaryNetworkTransaction::SetEarlyResponseHeadersCallback( + ResponseHeadersCallback callback) { + network_transaction_->SetEarlyResponseHeadersCallback(std::move(callback)); +} + +void SharedDictionaryNetworkTransaction::SetConnectedCallback( + const ConnectedCallback& callback) { + connected_callback_ = callback; +} + +int SharedDictionaryNetworkTransaction::ResumeNetworkStart() { + return network_transaction_->ResumeNetworkStart(); +} + +void SharedDictionaryNetworkTransaction::SetModifyRequestHeadersCallback( + base::RepeatingCallback callback) { + // This method should not be called for this class. + NOTREACHED_IN_MIGRATION(); +} + +void SharedDictionaryNetworkTransaction:: + SetIsSharedDictionaryReadAllowedCallback( + base::RepeatingCallback callback) { + is_shared_dictionary_read_allowed_callback_ = std::move(callback); +} + +ConnectionAttempts SharedDictionaryNetworkTransaction::GetConnectionAttempts() + const { + return network_transaction_->GetConnectionAttempts(); +} + +void SharedDictionaryNetworkTransaction::CloseConnectionOnDestruction() { + network_transaction_->CloseConnectionOnDestruction(); +} + +bool SharedDictionaryNetworkTransaction::IsMdlMatchForMetrics() const { + return network_transaction_->IsMdlMatchForMetrics(); +} + +int SharedDictionaryNetworkTransaction::OnConnected( + const TransportInfo& info, + CompletionOnceCallback callback) { + cert_is_issued_by_known_root_ = info.cert_is_issued_by_known_root; + negotiated_protocol_ = info.negotiated_protocol; + + if (connected_callback_) { + return connected_callback_.Run(info, std::move(callback)); + } + return OK; +} + +} // namespace net diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction.h b/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction.h new file mode 100644 index 0000000000..c849998b0c --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction.h @@ -0,0 +1,181 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_H_ +#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_H_ + +#include + +#include "base/functional/callback.h" +#include "base/memory/raw_ref.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "base/types/expected.h" +#include "net/base/completion_once_callback.h" +#include "net/base/net_errors.h" +#include "net/base/net_export.h" +#include "net/http/http_transaction.h" +#include "net/shared_dictionary/shared_dictionary_getter.h" +#include "net/socket/next_proto.h" + +class GURL; + +namespace net { +class SharedDictionary; +class SourceStream; +struct TransportInfo; + +// A `HttpTransaction` that decodes shared dictionary compression. +// If the `LOAD_CAN_USE_SHARED_DICTIONARY` flag is not set in the `request`'s +// `load_flags`, this class delegates all function calls to the underlying +// transaction. +// Otherwise, this class registers a callback with the underlying transaction +// that will be called just before the request is sent to the network. When this +// callback is called, this class tries to get a registered dictionary from the +// `shared_dictionary_manager`. If a matching dictionary is found, and the +// "content-encoding" header of the response from the server is "dcb" or "dcz", +// this class will decode the response body using a `BrotliSourceStream` or +// `ZstdSourceStream` with the dictionary. +class NET_EXPORT SharedDictionaryNetworkTransaction : public HttpTransaction { + public: + SharedDictionaryNetworkTransaction( + std::unique_ptr network_transaction, + bool enable_shared_zstd); + + SharedDictionaryNetworkTransaction( + const SharedDictionaryNetworkTransaction&) = delete; + SharedDictionaryNetworkTransaction& operator=( + const SharedDictionaryNetworkTransaction&) = delete; + + ~SharedDictionaryNetworkTransaction() override; + + // HttpTransaction methods: + int Start(const HttpRequestInfo* request, + CompletionOnceCallback callback, + const NetLogWithSource& net_log) override; + int RestartIgnoringLastError(CompletionOnceCallback callback) override; + int RestartWithCertificate(scoped_refptr client_cert, + scoped_refptr client_private_key, + CompletionOnceCallback callback) override; + int RestartWithAuth(const AuthCredentials& credentials, + CompletionOnceCallback callback) override; + bool IsReadyToRestartForAuth() override; + + int Read(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) override; + void StopCaching() override; + int64_t GetTotalReceivedBytes() const override; + int64_t GetTotalSentBytes() const override; + int64_t GetReceivedBodyBytes() const override; + void DoneReading() override; + const HttpResponseInfo* GetResponseInfo() const override; + LoadState GetLoadState() const override; + void SetQuicServerInfo(QuicServerInfo* quic_server_info) override; + bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; + bool GetRemoteEndpoint(IPEndPoint* endpoint) const override; + void PopulateNetErrorDetails(NetErrorDetails* details) const override; + void SetPriority(RequestPriority priority) override; + void SetWebSocketHandshakeStreamCreateHelper( + WebSocketHandshakeStreamBase::CreateHelper* create_helper) override; + void SetBeforeNetworkStartCallback( + BeforeNetworkStartCallback callback) override; + void SetConnectedCallback(const ConnectedCallback& callback) override; + void SetRequestHeadersCallback(RequestHeadersCallback callback) override; + void SetResponseHeadersCallback(ResponseHeadersCallback callback) override; + void SetEarlyResponseHeadersCallback( + ResponseHeadersCallback callback) override; + void SetModifyRequestHeadersCallback( + base::RepeatingCallback callback) override; + void SetIsSharedDictionaryReadAllowedCallback( + base::RepeatingCallback callback) override; + int ResumeNetworkStart() override; + ConnectionAttempts GetConnectionAttempts() const override; + void CloseConnectionOnDestruction() override; + bool IsMdlMatchForMetrics() const override; + + private: + enum class DictionaryStatus { + kNoDictionary, + kReading, + kFinished, + kFailed, + }; + + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class SharedDictionaryEncodingType { + kNotUsed = 0, + kSharedBrotli = 1, + kSharedZstd = 2, + kMaxValue = kSharedZstd, + }; + + class PendingReadTask { + public: + PendingReadTask(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback); + + PendingReadTask(const PendingReadTask&) = delete; + PendingReadTask& operator=(const PendingReadTask&) = delete; + + ~PendingReadTask(); + + scoped_refptr buf; + int buf_len; + CompletionOnceCallback callback; + }; + + SharedDictionaryEncodingType ParseSharedDictionaryEncodingType( + const HttpResponseHeaders& headers); + + void OnStartCompleted(CompletionOnceCallback callback, int result); + + void ModifyRequestHeaders(const GURL& request_url, + HttpRequestHeaders* request_headers); + + void OnReadSharedDictionary(base::Time read_start_time, int result); + + int OnConnected(const TransportInfo& info, CompletionOnceCallback callback); + + const bool enable_shared_zstd_; + + scoped_refptr shared_dictionary_; + // The Structured Field sf-binary hash of sha256 of dictionary calculated when + // sending a HTTP request. + std::string dictionary_hash_base64_; + + DictionaryStatus dictionary_status_ = DictionaryStatus::kNoDictionary; + + SharedDictionaryEncodingType shared_dictionary_encoding_type_ = + SharedDictionaryEncodingType::kNotUsed; + + std::unique_ptr pending_read_task_; + + base::RepeatingCallback is_shared_dictionary_read_allowed_callback_; + + // The network side transaction. + std::unique_ptr network_transaction_; + + std::unique_ptr shared_compression_stream_; + + // This is set only when a shared dictionary is used for decoding the body. + std::unique_ptr shared_dictionary_used_response_info_; + + ConnectedCallback connected_callback_; + + bool cert_is_issued_by_known_root_ = false; + NextProto negotiated_protocol_ = kProtoUnknown; + + base::RepeatingCallback()> + shared_dictionary_getter_; + + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace net + +#endif // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_H_ diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction_factory.cc b/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction_factory.cc new file mode 100644 index 0000000000..b092215a3d --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction_factory.cc @@ -0,0 +1,43 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/shared_dictionary/shared_dictionary_network_transaction_factory.h" + +#include "net/base/net_errors.h" +#include "net/shared_dictionary/shared_dictionary_network_transaction.h" + +namespace net { + +SharedDictionaryNetworkTransactionFactory:: + SharedDictionaryNetworkTransactionFactory( + std::unique_ptr network_layer, + bool enable_shared_zstd) + : network_layer_(std::move(network_layer)), + enable_shared_zstd_(enable_shared_zstd) {} + +SharedDictionaryNetworkTransactionFactory:: + ~SharedDictionaryNetworkTransactionFactory() = default; + +int SharedDictionaryNetworkTransactionFactory::CreateTransaction( + RequestPriority priority, + std::unique_ptr* trans) { + std::unique_ptr network_transaction; + int rv = network_layer_->CreateTransaction(priority, &network_transaction); + if (rv != OK) { + return rv; + } + *trans = std::make_unique( + std::move(network_transaction), enable_shared_zstd_); + return OK; +} + +HttpCache* SharedDictionaryNetworkTransactionFactory::GetCache() { + return network_layer_->GetCache(); +} + +HttpNetworkSession* SharedDictionaryNetworkTransactionFactory::GetSession() { + return network_layer_->GetSession(); +} + +} // namespace net diff --git a/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction_factory.h b/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction_factory.h new file mode 100644 index 0000000000..718066189e --- /dev/null +++ b/naiveproxy/src/net/shared_dictionary/shared_dictionary_network_transaction_factory.h @@ -0,0 +1,42 @@ + +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_FACTORY_H_ +#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_FACTORY_H_ + +#include "net/base/net_export.h" +#include "net/http/http_transaction_factory.h" + +namespace net { + +// A HttpTransactionFactory to create SharedDictionaryNetworkTransactions. +class NET_EXPORT SharedDictionaryNetworkTransactionFactory + : public HttpTransactionFactory { + public: + SharedDictionaryNetworkTransactionFactory( + std::unique_ptr network_layer, + bool enable_shared_zstd); + + SharedDictionaryNetworkTransactionFactory( + const SharedDictionaryNetworkTransactionFactory&) = delete; + SharedDictionaryNetworkTransactionFactory& operator=( + const SharedDictionaryNetworkTransactionFactory&) = delete; + + ~SharedDictionaryNetworkTransactionFactory() override; + + // HttpTransactionFactory methods: + int CreateTransaction(RequestPriority priority, + std::unique_ptr* trans) override; + HttpCache* GetCache() override; + HttpNetworkSession* GetSession() override; + + private: + std::unique_ptr network_layer_; + const bool enable_shared_zstd_; +}; + +} // namespace net + +#endif // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_NETWORK_TRANSACTION_FACTORY_H_ diff --git a/naiveproxy/src/net/socket/client_socket_handle.cc b/naiveproxy/src/net/socket/client_socket_handle.cc index 542bb5c669..5fc8db377c 100644 --- a/naiveproxy/src/net/socket/client_socket_handle.cc +++ b/naiveproxy/src/net/socket/client_socket_handle.cc @@ -61,7 +61,7 @@ int ClientSocketHandle::Init( } void ClientSocketHandle::SetPriority(RequestPriority priority) { - if (socket_) { + if (socket()) { // The priority of the handle is no longer relevant to the socket pool; // just return. return; @@ -77,8 +77,9 @@ void ClientSocketHandle::Reset() { } void ClientSocketHandle::ResetAndCloseSocket() { - if (is_initialized() && socket_) - socket_->Disconnect(); + if (is_initialized() && socket()) { + socket()->Disconnect(); + } ResetInternal(true /* cancel */, true /* cancel_connect_job */); ResetErrorState(); } @@ -127,30 +128,6 @@ void ClientSocketHandle::CloseIdleSocketsInGroup( pool_->CloseIdleSocketsInGroup(group_id_, net_log_reason_utf8); } -bool ClientSocketHandle::GetLoadTimingInfo( - bool is_reused, - LoadTimingInfo* load_timing_info) const { - if (socket_) { - load_timing_info->socket_log_id = socket_->NetLog().source().id; - } else { - // Only return load timing information when there's a socket. - return false; - } - - load_timing_info->socket_reused = is_reused; - - // No times if the socket is reused. - if (is_reused) - return true; - - load_timing_info->connect_timing = connect_timing_; - return true; -} - -void ClientSocketHandle::SetSocket(std::unique_ptr s) { - socket_ = std::move(s); -} - void ClientSocketHandle::SetAdditionalErrorState(ConnectJob* connect_job) { connection_attempts_ = connect_job->GetConnectionAttempts(); @@ -159,10 +136,6 @@ void ClientSocketHandle::SetAdditionalErrorState(ConnectJob* connect_job) { ssl_cert_request_info_ = connect_job->GetCertRequestInfo(); } -std::unique_ptr ClientSocketHandle::PassSocket() { - return std::move(socket_); -} - void ClientSocketHandle::OnIOComplete(int result) { TRACE_EVENT0(NetTracingCategory(), "ClientSocketHandle::OnIOComplete"); CompletionOnceCallback callback = std::move(callback_); @@ -174,15 +147,16 @@ void ClientSocketHandle::OnIOComplete(int result) { void ClientSocketHandle::HandleInitCompletion(int result) { CHECK_NE(ERR_IO_PENDING, result); if (result != OK) { - if (!socket_.get()) + if (!socket()) { ResetInternal(false /* cancel */, false /* cancel_connect_job */); // Nothing to cancel since // the request failed. - else - is_initialized_ = true; + } else { + set_is_initialized(true); + } return; } - is_initialized_ = true; + set_is_initialized(true); CHECK_NE(-1, group_generation_) << "Pool should have set |group_generation_| to a valid value."; @@ -190,9 +164,9 @@ void ClientSocketHandle::HandleInitCompletion(int result) { // TODO(eroman): This logging is not complete, in particular set_socket() and // release() socket. It ends up working though, since those methods are being // used to layer sockets (and the destination sources are the same). - DCHECK(socket_.get()); - socket_->NetLog().BeginEventReferencingSource(NetLogEventType::SOCKET_IN_USE, - requesting_source_); + DCHECK(socket()); + socket()->NetLog().BeginEventReferencingSource(NetLogEventType::SOCKET_IN_USE, + requesting_source_); } void ClientSocketHandle::ResetInternal(bool cancel, bool cancel_connect_job) { @@ -203,11 +177,11 @@ void ClientSocketHandle::ResetInternal(bool cancel, bool cancel_connect_job) { // If so, we must have a pool. CHECK(pool_); if (is_initialized()) { - if (socket_) { - socket_->NetLog().EndEvent(NetLogEventType::SOCKET_IN_USE); + if (socket()) { + socket()->NetLog().EndEvent(NetLogEventType::SOCKET_IN_USE); // Release the socket back to the ClientSocketPool so it can be // deleted or reused. - pool_->ReleaseSocket(group_id_, std::move(socket_), group_generation_); + pool_->ReleaseSocket(group_id_, PassSocket(), group_generation_); } else { // If the handle has been initialized, we should still have a // socket. @@ -219,16 +193,16 @@ void ClientSocketHandle::ResetInternal(bool cancel, bool cancel_connect_job) { pool_->CancelRequest(group_id_, this, cancel_connect_job); } } - is_initialized_ = false; - socket_.reset(); + set_is_initialized(false); + PassSocket(); group_id_ = ClientSocketPool::GroupId(); - reuse_type_ = ClientSocketHandle::UNUSED; + set_reuse_type(SocketReuseType::kUnused); callback_.Reset(); if (higher_pool_) RemoveHigherLayeredPool(higher_pool_); pool_ = nullptr; idle_time_ = base::TimeDelta(); - connect_timing_ = LoadTimingInfo::ConnectTiming(); + set_connect_timing(LoadTimingInfo::ConnectTiming()); group_generation_ = -1; } diff --git a/naiveproxy/src/net/socket/client_socket_handle.h b/naiveproxy/src/net/socket/client_socket_handle.h index a14430bc23..175bd2b63f 100644 --- a/naiveproxy/src/net/socket/client_socket_handle.h +++ b/naiveproxy/src/net/socket/client_socket_handle.h @@ -27,6 +27,7 @@ #include "net/socket/client_socket_pool.h" #include "net/socket/connection_attempts.h" #include "net/socket/stream_socket.h" +#include "net/socket/stream_socket_handle.h" #include "net/ssl/ssl_cert_request_info.h" namespace net { @@ -41,21 +42,14 @@ class SocketTag; // connection. It is used by the ClientSocketPool to group similar connected // client socket objects. // -class NET_EXPORT ClientSocketHandle { +class NET_EXPORT ClientSocketHandle : public StreamSocketHandle { public: - enum SocketReuseType { - UNUSED = 0, // unused socket that just finished connecting - UNUSED_IDLE, // unused socket that has been idle for awhile - REUSED_IDLE, // previously used socket - NUM_TYPES, - }; - ClientSocketHandle(); ClientSocketHandle(const ClientSocketHandle&) = delete; ClientSocketHandle& operator=(const ClientSocketHandle&) = delete; - ~ClientSocketHandle(); + ~ClientSocketHandle() override; // Initializes a ClientSocketHandle object, which involves talking to the // ClientSocketPool to obtain a connected socket, possibly reusing one. This @@ -112,7 +106,7 @@ class NET_EXPORT ClientSocketHandle { // NOTE: To prevent the socket from being kept alive, be sure to call its // Disconnect method. This will result in the ClientSocketPool deleting the // StreamSocket. - void Reset(); + void Reset() override; // Like Reset(), but also closes the socket (if there is one) and cancels any // pending attempt to establish a connection, if the connection attempt is @@ -138,28 +132,10 @@ class NET_EXPORT ClientSocketHandle { // Closes idle sockets that are in the same group with |this|. void CloseIdleSocketsInGroup(const char* net_log_reason_utf8); - // Returns true when Init() has completed successfully. - bool is_initialized() const { return is_initialized_; } - - // Sets the portion of LoadTimingInfo related to connection establishment, and - // the socket id. |is_reused| is needed because the handle may not have full - // reuse information. |load_timing_info| must have all default values when - // called. Returns false and makes no changes to |load_timing_info| when - // |socket_| is NULL. - bool GetLoadTimingInfo(bool is_reused, - LoadTimingInfo* load_timing_info) const; - - // Used by ClientSocketPool to initialize the ClientSocketHandle. - // - // SetSocket() may also be used if this handle is used as simply for - // socket storage (e.g., http://crbug.com/37810). - void SetSocket(std::unique_ptr s); - // Populates several fields of |this| with error-related information from the // provided completed ConnectJob. Should only be called on ConnectJob failure. void SetAdditionalErrorState(ConnectJob* connect_job); - void set_reuse_type(SocketReuseType reuse_type) { reuse_type_ = reuse_type; } void set_idle_time(base::TimeDelta idle_time) { idle_time_ = idle_time; } void set_group_generation(int64_t group_generation) { group_generation_ = group_generation; @@ -176,7 +152,7 @@ class NET_EXPORT ClientSocketHandle { // Only valid if there is no |socket_|. bool is_ssl_error() const { - DCHECK(!socket_); + DCHECK(!socket()); return is_ssl_error_; } @@ -191,24 +167,13 @@ class NET_EXPORT ClientSocketHandle { return connection_attempts_; } - StreamSocket* socket() { return socket_.get(); } - - // SetSocket() must be called with a new socket before this handle - // is destroyed if is_initialized() is true. - std::unique_ptr PassSocket(); - // These may only be used if is_initialized() is true. const ClientSocketPool::GroupId& group_id() const { return group_id_; } int64_t group_generation() const { return group_generation_; } - bool is_reused() const { return reuse_type_ == REUSED_IDLE; } + bool is_reused() const { + return reuse_type() == SocketReuseType::kReusedIdle; + } base::TimeDelta idle_time() const { return idle_time_; } - SocketReuseType reuse_type() const { return reuse_type_; } - const LoadTimingInfo::ConnectTiming& connect_timing() const { - return connect_timing_; - } - void set_connect_timing(const LoadTimingInfo::ConnectTiming& connect_timing) { - connect_timing_ = connect_timing; - } base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); @@ -233,12 +198,9 @@ class NET_EXPORT ClientSocketHandle { // Resets the supplemental error state. void ResetErrorState(); - bool is_initialized_ = false; raw_ptr pool_ = nullptr; raw_ptr higher_pool_ = nullptr; - std::unique_ptr socket_; ClientSocketPool::GroupId group_id_; - SocketReuseType reuse_type_ = ClientSocketHandle::UNUSED; CompletionOnceCallback callback_; base::TimeDelta idle_time_; // See ClientSocketPool::ReleaseSocket() for an explanation. @@ -250,9 +212,6 @@ class NET_EXPORT ClientSocketHandle { NetLogSource requesting_source_; - // Timing information is set when a connection is successfully established. - LoadTimingInfo::ConnectTiming connect_timing_; - base::WeakPtrFactory weak_factory_{this}; }; diff --git a/naiveproxy/src/net/socket/socket_bio_adapter.cc b/naiveproxy/src/net/socket/socket_bio_adapter.cc index 16f0126397..d4224539fc 100644 --- a/naiveproxy/src/net/socket/socket_bio_adapter.cc +++ b/naiveproxy/src/net/socket/socket_bio_adapter.cc @@ -259,7 +259,8 @@ int SocketBIOAdapter::BIOWrite(const char* in, int len) { CHECK_LE(write_buffer_->RemainingCapacity(), write_buffer_used_); int write_offset = write_buffer_used_ - write_buffer_->RemainingCapacity(); int chunk = std::min(len, write_buffer_->capacity() - write_buffer_used_); - memcpy(write_buffer_->StartOfBuffer() + write_offset, in, chunk); + memcpy(write_buffer_->everything().subspan(write_offset, chunk).data(), in, + chunk); in += chunk; len -= chunk; bytes_copied += chunk; diff --git a/naiveproxy/src/net/socket/socket_test_util.h b/naiveproxy/src/net/socket/socket_test_util.h index db52f31d7b..11d2c2169f 100644 --- a/naiveproxy/src/net/socket/socket_test_util.h +++ b/naiveproxy/src/net/socket/socket_test_util.h @@ -22,6 +22,7 @@ #include "base/functional/callback.h" #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_span.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "build/build_config.h" @@ -436,9 +437,9 @@ class StaticSocketDataHelper { // fails if no data is available. const MockWrite& PeekRealWrite() const; - const base::span reads_; + const base::raw_span reads_; size_t read_index_ = 0; - const base::span writes_; + const base::raw_span writes_; size_t write_index_ = 0; }; diff --git a/naiveproxy/src/net/socket/ssl_client_socket_impl.cc b/naiveproxy/src/net/socket/ssl_client_socket_impl.cc index 623c7b5ef2..961dca5f44 100644 --- a/naiveproxy/src/net/socket/ssl_client_socket_impl.cc +++ b/naiveproxy/src/net/socket/ssl_client_socket_impl.cc @@ -193,7 +193,6 @@ class SSLClientSocketImpl::SSLContext { friend struct base::DefaultSingletonTraits; SSLContext() { - crypto::EnsureOpenSSLInit(); ssl_socket_data_index_ = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr); DCHECK_NE(ssl_socket_data_index_, -1); diff --git a/naiveproxy/src/net/socket/ssl_server_socket_impl.cc b/naiveproxy/src/net/socket/ssl_server_socket_impl.cc index d47f345570..6e86606456 100644 --- a/naiveproxy/src/net/socket/ssl_server_socket_impl.cc +++ b/naiveproxy/src/net/socket/ssl_server_socket_impl.cc @@ -943,7 +943,6 @@ SSLServerContextImpl::SSLServerContextImpl( } void SSLServerContextImpl::Init() { - crypto::EnsureOpenSSLInit(); ssl_ctx_.reset(SSL_CTX_new(TLS_with_buffers_method())); SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_SERVER); uint8_t session_ctx_id = 0; diff --git a/naiveproxy/src/net/socket/stream_attempt.cc b/naiveproxy/src/net/socket/stream_attempt.cc new file mode 100644 index 0000000000..564255a342 --- /dev/null +++ b/naiveproxy/src/net/socket/stream_attempt.cc @@ -0,0 +1,96 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/socket/stream_attempt.h" + +#include + +#include "net/base/completion_once_callback.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_errors.h" +#include "net/http/http_network_session.h" +#include "net/log/net_log.h" +#include "net/log/net_log_with_source.h" +#include "net/socket/stream_socket.h" + +namespace net { + +// static +StreamAttemptParams StreamAttemptParams::FromHttpNetworkSession( + HttpNetworkSession* session) { + return StreamAttemptParams( + session->context().client_socket_factory, session->ssl_client_context(), + session->context().socket_performance_watcher_factory, + session->context().network_quality_estimator, session->net_log()); +} + +StreamAttemptParams::StreamAttemptParams( + ClientSocketFactory* client_socket_factory, + SSLClientContext* ssl_client_context, + SocketPerformanceWatcherFactory* socket_performance_watcher_factory, + NetworkQualityEstimator* network_quality_estimator, + NetLog* net_log) + : client_socket_factory(client_socket_factory), + ssl_client_context(ssl_client_context), + socket_performance_watcher_factory(socket_performance_watcher_factory), + network_quality_estimator(network_quality_estimator), + net_log(net_log) {} + +StreamAttempt::StreamAttempt(const StreamAttemptParams* params, + IPEndPoint ip_endpoint, + NetLogSourceType net_log_source_type, + NetLogEventType net_log_attempt_event_type, + const NetLogWithSource* net_log) + : params_(params), + ip_endpoint_(ip_endpoint), + net_log_(net_log ? *net_log + : NetLogWithSource::Make(params->net_log, + net_log_source_type)), + net_log_attempt_event_type_(net_log_attempt_event_type) {} + +StreamAttempt::~StreamAttempt() { + // Log this attempt as aborted if the attempt was still in-progress when + // destroyed. + if (callback_) { + LogCompletion(ERR_ABORTED); + } +} + +int StreamAttempt::Start(CompletionOnceCallback callback) { + net_log().BeginEvent(net_log_attempt_event_type_); + + int rv = StartInternal(); + if (rv != ERR_IO_PENDING) { + LogCompletion(rv); + } else { + callback_ = std::move(callback); + } + return rv; +} + +std::unique_ptr StreamAttempt::ReleaseStreamSocket() { + return std::move(stream_socket_); +} + +scoped_refptr StreamAttempt::GetCertRequestInfo() { + return nullptr; +} + +void StreamAttempt::SetStreamSocket(std::unique_ptr socket) { + stream_socket_ = std::move(socket); +} + +void StreamAttempt::NotifyOfCompletion(int rv) { + CHECK(callback_); + + LogCompletion(rv); + std::move(callback_).Run(rv); + // `this` may be deleted. +} + +void StreamAttempt::LogCompletion(int rv) { + net_log().EndEventWithNetErrorCode(net_log_attempt_event_type_, rv); +} + +} // namespace net diff --git a/naiveproxy/src/net/socket/stream_attempt.h b/naiveproxy/src/net/socket/stream_attempt.h new file mode 100644 index 0000000000..f0d125c4dd --- /dev/null +++ b/naiveproxy/src/net/socket/stream_attempt.h @@ -0,0 +1,125 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SOCKET_STREAM_ATTEMPT_H_ +#define NET_SOCKET_STREAM_ATTEMPT_H_ + +#include + +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "net/base/completion_once_callback.h" +#include "net/base/ip_endpoint.h" +#include "net/base/load_states.h" +#include "net/base/load_timing_info.h" +#include "net/base/net_export.h" +#include "net/log/net_log_event_type.h" +#include "net/log/net_log_with_source.h" + +namespace net { + +class ClientSocketFactory; +class HttpNetworkSession; +class SocketPerformanceWatcherFactory; +class SSLClientContext; +class SSLCertRequestInfo; +class StreamSocket; +class NetworkQualityEstimator; +class NetLog; + +// Common parameters for StreamAttempt classes. +struct NET_EXPORT_PRIVATE StreamAttemptParams { + static StreamAttemptParams FromHttpNetworkSession( + HttpNetworkSession* session); + + StreamAttemptParams( + ClientSocketFactory* client_socket_factory, + SSLClientContext* ssl_client_context, + SocketPerformanceWatcherFactory* socket_performance_watcher_factory, + NetworkQualityEstimator* network_quality_estimator, + NetLog* net_log); + + raw_ptr client_socket_factory; + raw_ptr ssl_client_context; + raw_ptr socket_performance_watcher_factory; + raw_ptr network_quality_estimator; + raw_ptr net_log; +}; + +// Represents a TCP or TLS connection attempt to a single IP endpoint. +class NET_EXPORT_PRIVATE StreamAttempt { + public: + // `params` must outlive `this`. + StreamAttempt(const StreamAttemptParams* params, + IPEndPoint ip_endpoint, + NetLogSourceType net_log_source_type, + NetLogEventType net_log_attempt_event_type, + const NetLogWithSource* net_log = nullptr); + + StreamAttempt(const StreamAttempt&) = delete; + StreamAttempt& operator=(const StreamAttempt&) = delete; + + virtual ~StreamAttempt(); + + // Starts this connection attempt. When ERR_IO_PENDING is returned, the + // attempt completed synchronously and `callback` is never invoked. Otherwise, + // `callback` is invoked when the attempt completes. + int Start(CompletionOnceCallback callback); + + // Returns the load state of this attempt. + virtual LoadState GetLoadState() const = 0; + + // If the attempt failed with ERR_SSL_CLIENT_AUTH_CERT_NEEDED, returns the + // SSLCertRequestInfo received. Otherwise, returns nullptr. + virtual scoped_refptr GetCertRequestInfo(); + + StreamSocket* stream_socket() const { return stream_socket_.get(); } + + std::unique_ptr ReleaseStreamSocket(); + + const IPEndPoint& ip_endpoint() const { return ip_endpoint_; } + + const NetLogWithSource& net_log() const { return net_log_; } + + // Returns the connect timing information of this attempt. Should only be + // accessed after the attempt completed. DNS related fields are never set. + const LoadTimingInfo::ConnectTiming& connect_timing() const { + return connect_timing_; + } + + protected: + virtual int StartInternal() = 0; + + const StreamAttemptParams& params() { return *params_; } + + void SetStreamSocket(std::unique_ptr stream_socket); + + // Called by subclasses to notify the completion of this attempt. `this` may + // be deleted after calling this method. + void NotifyOfCompletion(int rv); + + LoadTimingInfo::ConnectTiming& mutable_connect_timing() { + return connect_timing_; + } + + private: + void LogCompletion(int rv); + + const raw_ptr params_; + const IPEndPoint ip_endpoint_; + + NetLogWithSource net_log_; + NetLogEventType net_log_attempt_event_type_; + + // `callback_` is consumed when the attempt completes. + CompletionOnceCallback callback_; + + std::unique_ptr stream_socket_; + + LoadTimingInfo::ConnectTiming connect_timing_; +}; + +} // namespace net + +#endif // NET_SOCKET_STREAM_ATTEMPT_H_ diff --git a/naiveproxy/src/net/socket/stream_socket_handle.cc b/naiveproxy/src/net/socket/stream_socket_handle.cc new file mode 100644 index 0000000000..3fe715a29e --- /dev/null +++ b/naiveproxy/src/net/socket/stream_socket_handle.cc @@ -0,0 +1,48 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "stream_socket_handle.h" + +#include + +#include "net/base/load_timing_info.h" +#include "net/log/net_log_with_source.h" +#include "net/socket/stream_socket.h" + +namespace net { + +StreamSocketHandle::StreamSocketHandle() = default; + +StreamSocketHandle::~StreamSocketHandle() = default; + +void StreamSocketHandle::SetSocket(std::unique_ptr socket) { + socket_ = std::move(socket); +} + +std::unique_ptr StreamSocketHandle::PassSocket() { + return std::move(socket_); +} + +bool StreamSocketHandle::GetLoadTimingInfo( + bool is_reused, + LoadTimingInfo* load_timing_info) const { + if (socket_) { + load_timing_info->socket_log_id = socket_->NetLog().source().id; + } else { + // Only return load timing information when there's a socket. + return false; + } + + load_timing_info->socket_reused = is_reused; + + // No times if the socket is reused. + if (is_reused) { + return true; + } + + load_timing_info->connect_timing = connect_timing_; + return true; +} + +} // namespace net diff --git a/naiveproxy/src/net/socket/stream_socket_handle.h b/naiveproxy/src/net/socket/stream_socket_handle.h new file mode 100644 index 0000000000..733fd637eb --- /dev/null +++ b/naiveproxy/src/net/socket/stream_socket_handle.h @@ -0,0 +1,87 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SOCKET_STREAM_SOCKET_HANDLE_H_ +#define NET_SOCKET_STREAM_SOCKET_HANDLE_H_ + +#include + +#include + +#include "net/base/load_timing_info.h" +#include "net/base/net_export.h" + +namespace net { + +class StreamSocket; + +// A base class for handles that contain a StreamSocket. A subclass may have a +// concept of initialization, where a handle needs to be initialized before it +// can be used. A handle can be deinitialized by calling Reset(). +class NET_EXPORT_PRIVATE StreamSocketHandle { + public: + enum class SocketReuseType { + kUnused = 0, // unused socket that just finished connecting + kUnusedIdle, // unused socket that has been idle for awhile + kReusedIdle, // previously used socket + kNumTypes, + }; + + StreamSocketHandle(); + + StreamSocketHandle(const StreamSocketHandle&) = delete; + StreamSocketHandle& operator=(const StreamSocketHandle&) = delete; + + virtual ~StreamSocketHandle(); + + // Returns true when `this` is initialized successfully. + bool is_initialized() const { return is_initialized_; } + + StreamSocket* socket() { return socket_.get(); } + StreamSocket* socket() const { return socket_.get(); } + + // Sets `socket` to `this`. + void SetSocket(std::unique_ptr socket); + + // Releases the ownership of `socket`. + std::unique_ptr PassSocket(); + + // Sets the portion of LoadTimingInfo related to connection establishment, and + // the socket id. `is_reused` is needed because the handle may not have full + // reuse information. `load_timing_info` must have all default values when + // called. Returns false and makes no changes to `load_timing_info` when + // `socket_` is nullptr. + bool GetLoadTimingInfo(bool is_reused, + LoadTimingInfo* load_timing_info) const; + + SocketReuseType reuse_type() const { return reuse_type_; } + void set_reuse_type(SocketReuseType reuse_type) { reuse_type_ = reuse_type; } + + const LoadTimingInfo::ConnectTiming& connect_timing() const { + return connect_timing_; + } + void set_connect_timing(const LoadTimingInfo::ConnectTiming& connect_timing) { + connect_timing_ = connect_timing; + } + + // Releases the underlying socket and uninitializes `this`. + virtual void Reset() = 0; + + protected: + void set_is_initialized(bool is_initialized) { + is_initialized_ = is_initialized; + } + + private: + bool is_initialized_ = false; + std::unique_ptr socket_; + SocketReuseType reuse_type_ = SocketReuseType::kUnused; + + // Timing information is set when a connection is successfully established. + LoadTimingInfo::ConnectTiming connect_timing_; +}; + +} // namespace net + +#endif // NET_SOCKET_STREAM_SOCKET_HANDLE_H_ diff --git a/naiveproxy/src/net/socket/tcp_stream_attempt.cc b/naiveproxy/src/net/socket/tcp_stream_attempt.cc new file mode 100644 index 0000000000..0e8ab98926 --- /dev/null +++ b/naiveproxy/src/net/socket/tcp_stream_attempt.cc @@ -0,0 +1,94 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/socket/tcp_stream_attempt.h" + +#include + +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "net/base/address_list.h" +#include "net/base/net_errors.h" +#include "net/socket/client_socket_factory.h" +#include "net/socket/socket_performance_watcher.h" +#include "net/socket/socket_performance_watcher_factory.h" +#include "net/socket/transport_client_socket.h" + +namespace net { + +TcpStreamAttempt::TcpStreamAttempt(const StreamAttemptParams* params, + IPEndPoint ip_endpoint, + const NetLogWithSource* net_log) + : StreamAttempt(params, + ip_endpoint, + NetLogSourceType::TCP_STREAM_ATTEMPT, + NetLogEventType::TCP_STREAM_ATTEMPT_ALIVE, + net_log) {} + +TcpStreamAttempt::~TcpStreamAttempt() = default; + +LoadState TcpStreamAttempt::GetLoadState() const { + switch (next_state_) { + case State::kNone: + return LOAD_STATE_IDLE; + case State::kConnecting: + return LOAD_STATE_CONNECTING; + } +} + +int TcpStreamAttempt::StartInternal() { + next_state_ = State::kConnecting; + + std::unique_ptr socket_performance_watcher; + if (params().socket_performance_watcher_factory) { + socket_performance_watcher = + params() + .socket_performance_watcher_factory->CreateSocketPerformanceWatcher( + SocketPerformanceWatcherFactory::PROTOCOL_TCP, + ip_endpoint().address()); + } + + std::unique_ptr stream_socket = + params().client_socket_factory->CreateTransportClientSocket( + AddressList(ip_endpoint()), std::move(socket_performance_watcher), + params().network_quality_estimator, net_log().net_log(), + net_log().source()); + + TransportClientSocket* socket_ptr = stream_socket.get(); + SetStreamSocket(std::move(stream_socket)); + + mutable_connect_timing().connect_start = base::TimeTicks::Now(); + CHECK(!timeout_timer_.IsRunning()); + timeout_timer_.Start( + FROM_HERE, kTcpHandshakeTimeout, + base::BindOnce(&TcpStreamAttempt::OnTimeout, base::Unretained(this))); + + int rv = socket_ptr->Connect( + base::BindOnce(&TcpStreamAttempt::OnIOComplete, base::Unretained(this))); + if (rv != ERR_IO_PENDING) { + HandleCompletion(); + } + return rv; +} + +void TcpStreamAttempt::HandleCompletion() { + next_state_ = State::kNone; + timeout_timer_.Stop(); + mutable_connect_timing().connect_end = base::TimeTicks::Now(); +} + +void TcpStreamAttempt::OnIOComplete(int rv) { + CHECK_NE(rv, ERR_IO_PENDING); + HandleCompletion(); + NotifyOfCompletion(rv); +} + +void TcpStreamAttempt::OnTimeout() { + SetStreamSocket(nullptr); + // TODO(bashi): The error code should be ERR_CONNECTION_TIMED_OUT but use + // ERR_TIMED_OUT for consistency with ConnectJobs. + OnIOComplete(ERR_TIMED_OUT); +} + +} // namespace net diff --git a/naiveproxy/src/net/socket/tcp_stream_attempt.h b/naiveproxy/src/net/socket/tcp_stream_attempt.h new file mode 100644 index 0000000000..e17622b457 --- /dev/null +++ b/naiveproxy/src/net/socket/tcp_stream_attempt.h @@ -0,0 +1,56 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SOCKET_TCP_STREAM_ATTEMPT_H_ +#define NET_SOCKET_TCP_STREAM_ATTEMPT_H_ + +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_export.h" +#include "net/socket/stream_attempt.h" + +namespace net { + +class NetLogWithSource; + +// Represents a single TCP connection attempt. +class NET_EXPORT_PRIVATE TcpStreamAttempt final : public StreamAttempt { + public: + // This timeout is shorter than TransportConnectJob::ConnectionTimeout() + // because a TcpStreamAttempt only attempts a single TCP connection. + static constexpr base::TimeDelta kTcpHandshakeTimeout = base::Seconds(60); + + TcpStreamAttempt(const StreamAttemptParams* params, + IPEndPoint ip_endpoint, + const NetLogWithSource* = nullptr); + + TcpStreamAttempt(const TcpStreamAttempt&) = delete; + TcpStreamAttempt& operator=(const TcpStreamAttempt&) = delete; + + ~TcpStreamAttempt() override; + + LoadState GetLoadState() const override; + + private: + enum class State { + kNone, + kConnecting, + }; + + int StartInternal() override; + + void HandleCompletion(); + + void OnIOComplete(int rv); + + void OnTimeout(); + + State next_state_ = State::kNone; + base::OneShotTimer timeout_timer_; +}; + +} // namespace net + +#endif // NET_SOCKET_TCP_STREAM_ATTEMPT_H_ diff --git a/naiveproxy/src/net/socket/tls_stream_attempt.cc b/naiveproxy/src/net/socket/tls_stream_attempt.cc new file mode 100644 index 0000000000..46e254f174 --- /dev/null +++ b/naiveproxy/src/net/socket/tls_stream_attempt.cc @@ -0,0 +1,167 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/socket/tls_stream_attempt.h" + +#include + +#include "base/memory/scoped_refptr.h" +#include "net/base/host_port_pair.h" +#include "net/base/net_errors.h" +#include "net/socket/client_socket_factory.h" +#include "net/socket/tcp_stream_attempt.h" +#include "net/ssl/ssl_cert_request_info.h" + +namespace net { + +TlsStreamAttempt::TlsStreamAttempt(const StreamAttemptParams* params, + IPEndPoint ip_endpoint, + HostPortPair host_port_pair, + SSLConfigProvider* ssl_config_provider) + : StreamAttempt(params, + ip_endpoint, + NetLogSourceType::TLS_STREAM_ATTEMPT, + NetLogEventType::TLS_STREAM_ATTEMPT_ALIVE), + host_port_pair_(std::move(host_port_pair)), + ssl_config_provider_(ssl_config_provider) {} + +TlsStreamAttempt::~TlsStreamAttempt() = default; + +LoadState TlsStreamAttempt::GetLoadState() const { + switch (next_state_) { + case State::kNone: + return LOAD_STATE_IDLE; + case State::kTcpAttempt: + case State::kTcpAttemptComplete: + CHECK(nested_attempt_); + return nested_attempt_->GetLoadState(); + case State::kTlsAttempt: + case State::kTlsAttemptComplete: + return LOAD_STATE_SSL_HANDSHAKE; + } +} + +scoped_refptr TlsStreamAttempt::GetCertRequestInfo() { + return ssl_cert_request_info_; +} + +int TlsStreamAttempt::StartInternal() { + CHECK_EQ(next_state_, State::kNone); + next_state_ = State::kTcpAttempt; + return DoLoop(OK); +} + +void TlsStreamAttempt::OnIOComplete(int rv) { + CHECK_NE(rv, ERR_IO_PENDING); + rv = DoLoop(rv); + if (rv != ERR_IO_PENDING) { + NotifyOfCompletion(rv); + } +} + +int TlsStreamAttempt::DoLoop(int rv) { + CHECK_NE(next_state_, State::kNone); + + do { + State state = next_state_; + next_state_ = State::kNone; + switch (state) { + case State::kNone: + NOTREACHED_NORETURN() << "Invalid state"; + case State::kTcpAttempt: + rv = DoTcpAttempt(); + break; + case State::kTcpAttemptComplete: + rv = DoTcpAttemptComplete(rv); + break; + case State::kTlsAttempt: + rv = DoTlsAttempt(rv); + break; + case State::kTlsAttemptComplete: + rv = DoTlsAttemptComplete(rv); + break; + } + } while (next_state_ != State::kNone && rv != ERR_IO_PENDING); + + return rv; +} + +int TlsStreamAttempt::DoTcpAttempt() { + next_state_ = State::kTcpAttemptComplete; + nested_attempt_ = + std::make_unique(¶ms(), ip_endpoint(), &net_log()); + return nested_attempt_->Start( + base::BindOnce(&TlsStreamAttempt::OnIOComplete, base::Unretained(this))); +} + +int TlsStreamAttempt::DoTcpAttemptComplete(int rv) { + const LoadTimingInfo::ConnectTiming& nested_timing = + nested_attempt_->connect_timing(); + mutable_connect_timing().connect_start = nested_timing.connect_start; + mutable_connect_timing().connect_end = nested_timing.connect_end; + + if (rv != OK) { + return rv; + } + + next_state_ = State::kTlsAttempt; + return ssl_config_provider_->WaitForSSLConfigReady( + base::BindOnce(&TlsStreamAttempt::OnIOComplete, base::Unretained(this))); +} + +int TlsStreamAttempt::DoTlsAttempt(int rv) { + CHECK_EQ(rv, OK); + + next_state_ = State::kTlsAttemptComplete; + + std::unique_ptr nested_socket = + nested_attempt_->ReleaseStreamSocket(); + SSLConfig ssl_config = ssl_config_provider_->GetSSLConfig(); + + nested_attempt_.reset(); + + tls_handshake_started_ = true; + mutable_connect_timing().ssl_start = base::TimeTicks::Now(); + tls_handshake_timeout_timer_.Start( + FROM_HERE, kTlsHandshakeTimeout, + base::BindOnce(&TlsStreamAttempt::OnTlsHandshakeTimeout, + base::Unretained(this))); + + ssl_socket_ = params().client_socket_factory->CreateSSLClientSocket( + params().ssl_client_context, std::move(nested_socket), host_port_pair_, + ssl_config); + + return ssl_socket_->Connect( + base::BindOnce(&TlsStreamAttempt::OnIOComplete, base::Unretained(this))); +} + +int TlsStreamAttempt::DoTlsAttemptComplete(int rv) { + CHECK(ssl_socket_); + + mutable_connect_timing().ssl_end = base::TimeTicks::Now(); + tls_handshake_timeout_timer_.Stop(); + + // TODO(crbug.com/346835898): Record some histograms as SSLConnectJob does. + + // TODO(crbug.com/346835898): Handle the following error as SSLConnectJob + // does. + CHECK_NE(rv, ERR_ECH_NOT_NEGOTIATED) << "Not implemented yet"; + + if (rv == OK || IsCertificateError(rv)) { + SetStreamSocket(std::move(ssl_socket_)); + } else if (rv == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { + ssl_cert_request_info_ = base::MakeRefCounted(); + ssl_socket_->GetSSLCertRequestInfo(ssl_cert_request_info_.get()); + } + + return rv; +} + +void TlsStreamAttempt::OnTlsHandshakeTimeout() { + // TODO(bashi): The error code should be ERR_CONNECTION_TIMED_OUT but use + // ERR_TIMED_OUT for consistency with ConnectJobs. + OnIOComplete(ERR_TIMED_OUT); +} + +} // namespace net diff --git a/naiveproxy/src/net/socket/tls_stream_attempt.h b/naiveproxy/src/net/socket/tls_stream_attempt.h new file mode 100644 index 0000000000..8a1f1152ef --- /dev/null +++ b/naiveproxy/src/net/socket/tls_stream_attempt.h @@ -0,0 +1,102 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SOCKET_TLS_STREAM_ATTEMPT_H_ +#define NET_SOCKET_TLS_STREAM_ATTEMPT_H_ + +#include + +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "base/timer/timer.h" +#include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_export.h" +#include "net/socket/stream_attempt.h" +#include "net/ssl/ssl_cert_request_info.h" +#include "net/ssl/ssl_config.h" + +namespace net { + +class TcpStreamAttempt; +class SSLClientSocket; + +// Represents a single TLS connection attempt. +class NET_EXPORT_PRIVATE TlsStreamAttempt final : public StreamAttempt { + public: + // Timeout for the TLS handshake. The timeout is the same as SSLConnectJob. + static constexpr base::TimeDelta kTlsHandshakeTimeout = base::Seconds(30); + + // An interface that provides a SSLConfig to TlsStreamAttempt lazily. + class NET_EXPORT_PRIVATE SSLConfigProvider { + public: + SSLConfigProvider() = default; + virtual ~SSLConfigProvider() = default; + + SSLConfigProvider(const SSLConfigProvider&) = delete; + SSLConfigProvider& operator=(const SSLConfigProvider&) = delete; + + // Returns OK when a SSLConfig is immediately available. `callback` is never + // invoked. Otherwise, returns ERR_IO_PENDING when `this` can't provide a + // SSLConfig immediately. `callback` is invoked when a SSLConfig is ready. + virtual int WaitForSSLConfigReady(CompletionOnceCallback callback) = 0; + + // Returns a SSLConfig. Should be called only after WaitForSSLConfigReady() + // returns OK or the callback is invoked. + virtual SSLConfig GetSSLConfig() = 0; + }; + + // `params` and `ssl_config_provider` must outlive `this`. + TlsStreamAttempt(const StreamAttemptParams* params, + IPEndPoint ip_endpoint, + HostPortPair host_port_pair, + SSLConfigProvider* ssl_config_provider); + + TlsStreamAttempt(const TlsStreamAttempt&) = delete; + TlsStreamAttempt& operator=(const TlsStreamAttempt&) = delete; + + ~TlsStreamAttempt() override; + + // StreamAttempt implementations: + LoadState GetLoadState() const override; + scoped_refptr GetCertRequestInfo() override; + + bool IsTlsHandshakeStarted() { return tls_handshake_started_; } + + private: + enum class State { + kNone, + kTcpAttempt, + kTcpAttemptComplete, + kTlsAttempt, + kTlsAttemptComplete, + }; + + int StartInternal() override; + + void OnIOComplete(int rv); + + int DoLoop(int rv); + int DoTcpAttempt(); + int DoTcpAttemptComplete(int rv); + int DoTlsAttempt(int rv); + int DoTlsAttemptComplete(int rv); + + void OnTlsHandshakeTimeout(); + + State next_state_ = State::kNone; + const HostPortPair host_port_pair_; + const raw_ptr ssl_config_provider_; + + std::unique_ptr nested_attempt_; + + bool tls_handshake_started_ = false; + base::OneShotTimer tls_handshake_timeout_timer_; + std::unique_ptr ssl_socket_; + scoped_refptr ssl_cert_request_info_; +}; + +} // namespace net + +#endif // NET_SOCKET_TLS_STREAM_ATTEMPT_H_ diff --git a/naiveproxy/src/net/socket/transport_client_socket_pool.cc b/naiveproxy/src/net/socket/transport_client_socket_pool.cc index 1037fe450f..2da71eab5a 100644 --- a/naiveproxy/src/net/socket/transport_client_socket_pool.cc +++ b/naiveproxy/src/net/socket/transport_client_socket_pool.cc @@ -18,6 +18,7 @@ #include "base/location.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" +#include "base/not_fatal_until.h" #include "base/notreached.h" #include "base/ranges/algorithm.h" #include "base/strings/string_util.h" @@ -484,10 +485,10 @@ int TransportClientSocketPool::RequestSocketInternal( handle->SetAdditionalErrorState(connect_job.get()); std::unique_ptr socket = connect_job->PassSocket(); if (socket) { - HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, + HandOutSocket(std::move(socket), + StreamSocketHandle::SocketReuseType::kUnused, connect_job->connect_timing(), handle, - base::TimeDelta() /* idle_time */, group, - request.net_log()); + /*time_idle=*/base::TimeDelta(), group, request.net_log()); } } if (group->IsEmpty()) @@ -544,8 +545,9 @@ bool TransportClientSocketPool::AssignIdleSocketToRequest( // treating as UNUSED rather than UNUSED_IDLE. This will avoid // HttpNetworkTransaction retrying on some errors. ClientSocketHandle::SocketReuseType reuse_type = - socket->WasEverUsed() ? ClientSocketHandle::REUSED_IDLE - : ClientSocketHandle::UNUSED_IDLE; + socket->WasEverUsed() + ? StreamSocketHandle::SocketReuseType::kReusedIdle + : StreamSocketHandle::SocketReuseType::kUnusedIdle; HandOutSocket(std::move(socket), reuse_type, LoadTimingInfo::ConnectTiming(), request.handle(), idle_time, @@ -1057,8 +1059,8 @@ void TransportClientSocketPool::CheckForStalledSocketGroups() { // Loop until there's nothing more to do. while (true) { // If we have idle sockets, see if we can give one to the top-stalled group. - GroupId top_group_id; Group* top_group = nullptr; + GroupId top_group_id; if (!FindTopStalledGroup(&top_group, &top_group_id)) return; @@ -1083,7 +1085,8 @@ void TransportClientSocketPool::CheckForStalledSocketGroups() { // insertion order). bool TransportClientSocketPool::FindTopStalledGroup(Group** group, GroupId* group_id) const { - CHECK((group && group_id) || (!group && !group_id)); + CHECK(group); + CHECK(group_id); Group* top_group = nullptr; const GroupId* top_group_id = nullptr; bool has_stalled_group = false; @@ -1092,8 +1095,6 @@ bool TransportClientSocketPool::FindTopStalledGroup(Group** group, if (!curr_group->has_unbound_requests()) continue; if (curr_group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { - if (!group) - return true; has_stalled_group = true; bool has_higher_priority = !top_group || @@ -1106,7 +1107,6 @@ bool TransportClientSocketPool::FindTopStalledGroup(Group** group, } if (top_group) { - CHECK(group); *group = top_group; *group_id = *top_group_id; } else { @@ -1194,7 +1194,7 @@ void TransportClientSocketPool::HandOutSocket( handle->set_group_generation(group->generation()); handle->set_connect_timing(connect_timing); - if (reuse_type == ClientSocketHandle::REUSED_IDLE) { + if (reuse_type == StreamSocketHandle::SocketReuseType::kReusedIdle) { net_log.AddEventWithIntParams( NetLogEventType::SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, "idle_ms", static_cast(idle_time.InMilliseconds())); @@ -1365,7 +1365,8 @@ void TransportClientSocketPool::OnConnectJobComplete(Group* group, if (result != OK) request->handle()->SetAdditionalErrorState(job); if (job->socket()) { - HandOutSocket(job->PassSocket(), ClientSocketHandle::UNUSED, + HandOutSocket(job->PassSocket(), + StreamSocketHandle::SocketReuseType::kUnused, job->connect_timing(), request->handle(), base::TimeDelta(), group, request->net_log()); } @@ -1544,7 +1545,7 @@ std::unique_ptr TransportClientSocketPool::Group::RemoveUnboundJob( // Check that |job| is in the list. auto it = base::ranges::find(jobs_, job, &std::unique_ptr::get); - DCHECK(it != jobs_.end()); + CHECK(it != jobs_.end(), base::NotFatalUntil::M130); // Check if |job| is in the unassigned jobs list. If so, remove it. auto it2 = base::ranges::find(unassigned_jobs_, job); diff --git a/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.h b/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.h index 58295d3274..643ab81b8b 100644 --- a/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.h +++ b/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.h @@ -18,6 +18,7 @@ #include "base/containers/span.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_span.h" #include "base/time/time.h" #include "net/base/address_list.h" #include "net/socket/client_socket_factory.h" @@ -147,7 +148,7 @@ class MockTransportClientSocketFactory : public ClientSocketFactory { raw_ptr net_log_; int allocation_count_ = 0; Type client_socket_type_ = Type::kSynchronous; - base::span rules_; + base::raw_span rules_; base::TimeDelta delay_; base::queue triggerable_sockets_; base::OnceClosure run_loop_quit_closure_; diff --git a/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.cc b/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.cc index f749271d52..bb8a2ca9dc 100644 --- a/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.cc +++ b/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.cc @@ -23,6 +23,7 @@ #include "net/socket/client_socket_handle.h" #include "net/socket/connect_job.h" #include "net/socket/connect_job_factory.h" +#include "net/socket/stream_socket_handle.h" #include "net/socket/websocket_endpoint_lock_manager.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -52,7 +53,7 @@ WebSocketTransportClientSocketPool::~WebSocketTransportClientSocketPool() { // static void WebSocketTransportClientSocketPool::UnlockEndpoint( - ClientSocketHandle* handle, + StreamSocketHandle* handle, WebSocketEndpointLockManager* websocket_endpoint_lock_manager) { DCHECK(handle->is_initialized()); DCHECK(handle->socket()); @@ -382,7 +383,7 @@ void WebSocketTransportClientSocketPool::HandOutSocket( ClientSocketHandle* handle, const NetLogWithSource& net_log) { DCHECK(socket); - DCHECK_EQ(ClientSocketHandle::UNUSED, handle->reuse_type()); + DCHECK_EQ(StreamSocketHandle::SocketReuseType::kUnused, handle->reuse_type()); DCHECK_EQ(0, handle->idle_time().InMicroseconds()); handle->SetSocket(std::move(socket)); diff --git a/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.h b/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.h index 8c8bb17aac..d6898fd6f7 100644 --- a/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.h +++ b/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.h @@ -28,6 +28,7 @@ namespace net { struct CommonConnectJobParams; struct NetworkTrafficAnnotationTag; +class StreamSocketHandle; // Identifier for a ClientSocketHandle to scope the lifetime of references. // ClientSocketHandleID are derived from ClientSocketHandle*, used in @@ -58,7 +59,7 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool // need to explicitly check for this. Instead, ensure that dead sockets are // returned to ReleaseSocket() in a timely fashion. static void UnlockEndpoint( - ClientSocketHandle* handle, + StreamSocketHandle* handle, WebSocketEndpointLockManager* websocket_endpoint_lock_manager); // ClientSocketPool implementation. diff --git a/naiveproxy/src/net/spdy/alps_decoder.h b/naiveproxy/src/net/spdy/alps_decoder.h index f890b3ee9c..230f1bf5a2 100644 --- a/naiveproxy/src/net/spdy/alps_decoder.h +++ b/naiveproxy/src/net/spdy/alps_decoder.h @@ -10,8 +10,8 @@ #include "base/containers/span.h" #include "base/strings/string_number_conversions.h" #include "net/base/net_export.h" +#include "net/third_party/quiche/src/quiche/http2/core/spdy_no_op_visitor.h" #include "net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.h" -#include "net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" namespace net { diff --git a/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc b/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc index 85fc774595..fe4fea81bb 100644 --- a/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc +++ b/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc @@ -21,7 +21,6 @@ #include "net/spdy/spdy_buffer.h" #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_stream.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" namespace net { @@ -201,13 +200,13 @@ void BidirectionalStreamSpdyImpl::OnHeadersSent() { } void BidirectionalStreamSpdyImpl::OnEarlyHintsReceived( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { DCHECK(stream_); // TODO(crbug.com/40496584): Plumb Early Hints to `delegate_` if needed. } void BidirectionalStreamSpdyImpl::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { DCHECK(stream_); if (delegate_) @@ -245,7 +244,7 @@ void BidirectionalStreamSpdyImpl::OnDataSent() { } void BidirectionalStreamSpdyImpl::OnTrailers( - const spdy::Http2HeaderBlock& trailers) { + const quiche::HttpHeaderBlock& trailers) { DCHECK(stream_); DCHECK(!stream_closed_); @@ -290,7 +289,7 @@ NetLogSource BidirectionalStreamSpdyImpl::source_dependency() const { } int BidirectionalStreamSpdyImpl::SendRequestHeadersHelper() { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; HttpRequestInfo http_request_info; http_request_info.url = request_info_->url; http_request_info.method = request_info_->method; diff --git a/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.h b/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.h index d797f13c27..5e6bcbd18e 100644 --- a/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.h +++ b/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.h @@ -22,7 +22,7 @@ #include "net/spdy/spdy_read_queue.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_stream.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" namespace base { class OneShotTimer; @@ -66,12 +66,12 @@ class NET_EXPORT_PRIVATE BidirectionalStreamSpdyImpl // SpdyStream::Delegate implementation: void OnHeadersSent() override; - void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override; + void OnEarlyHintsReceived(const quiche::HttpHeaderBlock& headers) override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnDataReceived(std::unique_ptr buffer) override; void OnDataSent() override; - void OnTrailers(const spdy::Http2HeaderBlock& trailers) override; + void OnTrailers(const quiche::HttpHeaderBlock& trailers) override; void OnClose(int status) override; bool CanGreaseFrameType() const override; NetLogSource source_dependency() const override; diff --git a/naiveproxy/src/net/spdy/buffered_spdy_framer.h b/naiveproxy/src/net/spdy/buffered_spdy_framer.h index 0796792701..d06c99d22e 100644 --- a/naiveproxy/src/net/spdy/buffered_spdy_framer.h +++ b/naiveproxy/src/net/spdy/buffered_spdy_framer.h @@ -17,8 +17,8 @@ #include "net/base/net_export.h" #include "net/log/net_log_source.h" #include "net/spdy/header_coalescer.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" @@ -49,7 +49,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface { spdy::SpdyStreamId parent_stream_id, bool exclusive, bool fin, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, base::TimeTicks recv_first_byte_time) = 0; // Called when a data frame header is received. @@ -106,7 +106,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface { // Called when a PUSH_PROMISE frame has been parsed. virtual void OnPushPromise(spdy::SpdyStreamId stream_id, spdy::SpdyStreamId promised_stream_id, - spdy::Http2HeaderBlock headers) = 0; + quiche::HttpHeaderBlock headers) = 0; // Called when an ALTSVC frame has been parsed. virtual void OnAltSvc( diff --git a/naiveproxy/src/net/spdy/header_coalescer.cc b/naiveproxy/src/net/spdy/header_coalescer.cc index 036dbf23e6..7c29d4c579 100644 --- a/naiveproxy/src/net/spdy/header_coalescer.cc +++ b/naiveproxy/src/net/spdy/header_coalescer.cc @@ -55,7 +55,7 @@ void HeaderCoalescer::OnHeader(std::string_view key, std::string_view value) { } } -spdy::Http2HeaderBlock HeaderCoalescer::release_headers() { +quiche::HttpHeaderBlock HeaderCoalescer::release_headers() { DCHECK(headers_valid_); headers_valid_ = false; return std::move(headers_); diff --git a/naiveproxy/src/net/spdy/header_coalescer.h b/naiveproxy/src/net/spdy/header_coalescer.h index a28389c155..af07cabd15 100644 --- a/naiveproxy/src/net/spdy/header_coalescer.h +++ b/naiveproxy/src/net/spdy/header_coalescer.h @@ -9,7 +9,7 @@ #include "net/base/net_export.h" #include "net/log/net_log_with_source.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_headers_handler_interface.h" namespace net { @@ -27,14 +27,14 @@ class NET_EXPORT_PRIVATE HeaderCoalescer void OnHeaderBlockEnd(size_t uncompressed_header_bytes, size_t compressed_header_bytes) override {} - spdy::Http2HeaderBlock release_headers(); + quiche::HttpHeaderBlock release_headers(); bool error_seen() const { return error_seen_; } private: // Helper to add a header. Return true on success. bool AddHeader(std::string_view key, std::string_view value); - spdy::Http2HeaderBlock headers_; + quiche::HttpHeaderBlock headers_; bool headers_valid_ = true; size_t header_list_size_ = 0; bool error_seen_ = false; diff --git a/naiveproxy/src/net/spdy/multiplexed_http_stream.cc b/naiveproxy/src/net/spdy/multiplexed_http_stream.cc index 77504214b1..bd98256747 100644 --- a/naiveproxy/src/net/spdy/multiplexed_http_stream.cc +++ b/naiveproxy/src/net/spdy/multiplexed_http_stream.cc @@ -8,7 +8,6 @@ #include "base/notreached.h" #include "net/http/http_raw_request_headers.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" namespace net { @@ -53,7 +52,7 @@ void MultiplexedHttpStream::SetRequestHeadersCallback( } void MultiplexedHttpStream::DispatchRequestHeadersCallback( - const spdy::Http2HeaderBlock& spdy_headers) { + const quiche::HttpHeaderBlock& spdy_headers) { if (!request_headers_callback_) return; HttpRawRequestHeaders raw_headers; diff --git a/naiveproxy/src/net/spdy/multiplexed_http_stream.h b/naiveproxy/src/net/spdy/multiplexed_http_stream.h index 13cc056e70..01a183c8d2 100644 --- a/naiveproxy/src/net/spdy/multiplexed_http_stream.h +++ b/naiveproxy/src/net/spdy/multiplexed_http_stream.h @@ -10,7 +10,7 @@ #include "net/http/http_stream.h" #include "net/spdy/multiplexed_session.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" namespace net { @@ -34,7 +34,7 @@ class NET_EXPORT_PRIVATE MultiplexedHttpStream : public HttpStream { protected: void DispatchRequestHeadersCallback( - const spdy::Http2HeaderBlock& spdy_headers); + const quiche::HttpHeaderBlock& spdy_headers); MultiplexedSessionHandle* session() { return session_.get(); } const MultiplexedSessionHandle* session() const { return session_.get(); } diff --git a/naiveproxy/src/net/spdy/spdy_http_stream.cc b/naiveproxy/src/net/spdy/spdy_http_stream.cc index 277c562816..e36e4dd8d2 100644 --- a/naiveproxy/src/net/spdy/spdy_http_stream.cc +++ b/naiveproxy/src/net/spdy/spdy_http_stream.cc @@ -27,7 +27,6 @@ #include "net/socket/next_proto.h" #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_session.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" #include "url/scheme_host_port.h" @@ -240,7 +239,7 @@ int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, return result; response_info_->remote_endpoint = address; - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; CreateSpdyHeadersFromHttpRequest(*request_info_, priority_, request_headers, &headers); DispatchRequestHeadersCallback(headers); @@ -278,7 +277,7 @@ void SpdyHttpStream::OnHeadersSent() { } void SpdyHttpStream::OnEarlyHintsReceived( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { DCHECK(!response_headers_complete_); DCHECK(response_info_); DCHECK_EQ(stream_->type(), SPDY_REQUEST_RESPONSE_STREAM); @@ -292,7 +291,7 @@ void SpdyHttpStream::OnEarlyHintsReceived( } void SpdyHttpStream::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { DCHECK(!response_headers_complete_); DCHECK(response_info_); response_headers_complete_ = true; @@ -353,7 +352,7 @@ void SpdyHttpStream::OnDataSent() { } // TODO(xunjieli): Maybe do something with the trailers. crbug.com/422958. -void SpdyHttpStream::OnTrailers(const spdy::Http2HeaderBlock& trailers) {} +void SpdyHttpStream::OnTrailers(const quiche::HttpHeaderBlock& trailers) {} void SpdyHttpStream::OnClose(int status) { DCHECK(stream_); diff --git a/naiveproxy/src/net/spdy/spdy_http_stream.h b/naiveproxy/src/net/spdy/spdy_http_stream.h index 3fff06a54a..c17da0052f 100644 --- a/naiveproxy/src/net/spdy/spdy_http_stream.h +++ b/naiveproxy/src/net/spdy/spdy_http_stream.h @@ -24,6 +24,7 @@ #include "net/spdy/spdy_read_queue.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_stream.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" namespace net { @@ -94,12 +95,12 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate, // SpdyStream::Delegate implementation. void OnHeadersSent() override; - void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override; + void OnEarlyHintsReceived(const quiche::HttpHeaderBlock& headers) override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnDataReceived(std::unique_ptr buffer) override; void OnDataSent() override; - void OnTrailers(const spdy::Http2HeaderBlock& trailers) override; + void OnTrailers(const quiche::HttpHeaderBlock& trailers) override; void OnClose(int status) override; bool CanGreaseFrameType() const override; NetLogSource source_dependency() const override; diff --git a/naiveproxy/src/net/spdy/spdy_http_utils.cc b/naiveproxy/src/net/spdy/spdy_http_utils.cc index 2b0fdcfa98..4ef3fb6ae9 100644 --- a/naiveproxy/src/net/spdy/spdy_http_utils.cc +++ b/naiveproxy/src/net/spdy/spdy_http_utils.cc @@ -29,7 +29,6 @@ #include "net/http/http_util.h" #include "net/quic/quic_http_utils.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_stream_priority.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" namespace net { @@ -46,16 +45,16 @@ constexpr size_t kExpectedRawHeaderSize = 4035; // `headers`. void AddUniqueSpdyHeader(std::string_view name, std::string_view value, - spdy::Http2HeaderBlock* headers) { + quiche::HttpHeaderBlock* headers) { auto insert_result = headers->insert({name, value}); - CHECK_EQ(insert_result, spdy::Http2HeaderBlock::InsertResult::kInserted); + CHECK_EQ(insert_result, quiche::HttpHeaderBlock::InsertResult::kInserted); } // Convert `headers` to an HttpResponseHeaders object based on the features // enabled at runtime. base::expected, int> SpdyHeadersToHttpResponseHeadersUsingFeatures( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { if (base::FeatureList::IsEnabled( features::kSpdyHeadersToHttpResponseUseBuilder)) { return SpdyHeadersToHttpResponseHeadersUsingBuilder(headers); @@ -66,7 +65,7 @@ SpdyHeadersToHttpResponseHeadersUsingFeatures( } // namespace -int SpdyHeadersToHttpResponse(const spdy::Http2HeaderBlock& headers, +int SpdyHeadersToHttpResponse(const quiche::HttpHeaderBlock& headers, HttpResponseInfo* response) { ASSIGN_OR_RETURN(response->headers, SpdyHeadersToHttpResponseHeadersUsingFeatures(headers)); @@ -76,9 +75,9 @@ int SpdyHeadersToHttpResponse(const spdy::Http2HeaderBlock& headers, NET_EXPORT_PRIVATE base::expected, int> SpdyHeadersToHttpResponseHeadersUsingRawString( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { // The ":status" header is required. - spdy::Http2HeaderBlock::const_iterator it = + quiche::HttpHeaderBlock::const_iterator it = headers.find(spdy::kHttp2StatusHeader); if (it == headers.end()) { return base::unexpected(ERR_INCOMPLETE_HTTP2_HEADERS); @@ -135,12 +134,12 @@ SpdyHeadersToHttpResponseHeadersUsingRawString( NET_EXPORT_PRIVATE base::expected, int> SpdyHeadersToHttpResponseHeadersUsingBuilder( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { // The ":status" header is required. // TODO(ricea): The ":status" header should always come first. Skip this hash // lookup after we no longer need to be compatible with the old // implementation. - spdy::Http2HeaderBlock::const_iterator it = + quiche::HttpHeaderBlock::const_iterator it = headers.find(spdy::kHttp2StatusHeader); if (it == headers.end()) { return base::unexpected(ERR_INCOMPLETE_HTTP2_HEADERS); @@ -202,7 +201,7 @@ SpdyHeadersToHttpResponseHeadersUsingBuilder( void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, std::optional priority, const HttpRequestHeaders& request_headers, - spdy::Http2HeaderBlock* headers) { + quiche::HttpHeaderBlock* headers) { headers->insert({spdy::kHttp2MethodHeader, info.method}); if (info.method == "CONNECT") { headers->insert({spdy::kHttp2AuthorityHeader, GetHostAndPort(info.url)}); @@ -246,7 +245,7 @@ void CreateSpdyHeadersFromHttpRequestForExtendedConnect( std::optional priority, const std::string& ext_connect_protocol, const HttpRequestHeaders& request_headers, - spdy::Http2HeaderBlock* headers) { + quiche::HttpHeaderBlock* headers) { CHECK_EQ(info.method, "CONNECT"); // Extended CONNECT, unlike CONNECT, requires scheme and path, and uses the @@ -266,7 +265,7 @@ void CreateSpdyHeadersFromHttpRequestForExtendedConnect( void CreateSpdyHeadersFromHttpRequestForWebSocket( const GURL& url, const HttpRequestHeaders& request_headers, - spdy::Http2HeaderBlock* headers) { + quiche::HttpHeaderBlock* headers) { headers->insert({spdy::kHttp2MethodHeader, "CONNECT"}); headers->insert({spdy::kHttp2AuthorityHeader, GetHostAndOptionalPort(url)}); headers->insert({spdy::kHttp2SchemeHeader, "https"}); @@ -307,7 +306,7 @@ ConvertSpdyPriorityToRequestPriority(spdy::SpdyPriority priority) { } NET_EXPORT_PRIVATE void ConvertHeaderBlockToHttpRequestHeaders( - const spdy::Http2HeaderBlock& spdy_headers, + const quiche::HttpHeaderBlock& spdy_headers, HttpRequestHeaders* http_headers) { for (const auto& it : spdy_headers) { std::string_view key = it.first; diff --git a/naiveproxy/src/net/spdy/spdy_http_utils.h b/naiveproxy/src/net/spdy/spdy_http_utils.h index eb15b5c00d..f94cf1a3f5 100644 --- a/naiveproxy/src/net/spdy/spdy_http_utils.h +++ b/naiveproxy/src/net/spdy/spdy_http_utils.h @@ -11,7 +11,7 @@ #include "base/types/expected.h" #include "net/base/net_export.h" #include "net/base/request_priority.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" #include "url/gurl.h" @@ -27,42 +27,42 @@ class HttpResponseHeaders; // RFC 9218. NET_EXPORT extern const char* const kHttp2PriorityHeader; -// Convert a spdy::Http2HeaderBlock into an HttpResponseInfo with some checks. -// `headers` input parameter with the spdy::Http2HeaderBlock. +// Convert a quiche::HttpHeaderBlock into an HttpResponseInfo with some checks. +// `headers` input parameter with the quiche::HttpHeaderBlock. // `response` output parameter for the HttpResponseInfo. // Returns OK if successfully converted. An error is returned if the -// spdy::Http2HeaderBlock is incomplete (e.g. missing 'status' or 'version') or +// quiche::HttpHeaderBlock is incomplete (e.g. missing 'status' or 'version') or // checks fail. -NET_EXPORT int SpdyHeadersToHttpResponse(const spdy::Http2HeaderBlock& headers, +NET_EXPORT int SpdyHeadersToHttpResponse(const quiche::HttpHeaderBlock& headers, HttpResponseInfo* response); -// Converts a spdy::Http2HeaderBlock object into an HttpResponseHeaders object +// Converts a quiche::HttpHeaderBlock object into an HttpResponseHeaders object // by creating a string with embedded nul bytes instead of newlines and then // parsing it to the HttpResponseHeaders constructor to be parsed. Exposed for // testing. // TODO(crbug.com/40282642): Remove this once it is no longer needed. NET_EXPORT_PRIVATE base::expected, int> SpdyHeadersToHttpResponseHeadersUsingRawString( - const spdy::Http2HeaderBlock& headers); + const quiche::HttpHeaderBlock& headers); -// Converts a spdy::Http2HeaderBlock object into an HttpResponseHeaders object +// Converts a quiche::HttpHeaderBlock object into an HttpResponseHeaders object // by using the HttpResponseHeaders::Builder API. Exposed for testing. // TODO(crbug.com/40282642): Merge this back into // SpdyHeadersToHttpResponse() when // SpdyHeadersToHttpResponseHeadersUsingRawString() is removed. NET_EXPORT_PRIVATE base::expected, int> SpdyHeadersToHttpResponseHeadersUsingBuilder( - const spdy::Http2HeaderBlock& headers); + const quiche::HttpHeaderBlock& headers); -// Create a spdy::Http2HeaderBlock from HttpRequestInfo and +// Create a quiche::HttpHeaderBlock from HttpRequestInfo and // HttpRequestHeaders. NET_EXPORT void CreateSpdyHeadersFromHttpRequest( const HttpRequestInfo& info, std::optional priority, const HttpRequestHeaders& request_headers, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); -// Create a spdy::Http2HeaderBlock from HttpRequestInfo and +// Create a quiche::HttpHeaderBlock from HttpRequestInfo and // HttpRequestHeaders, with the given protocol for extended CONNECT. // The request's method must be `CONNECT`. NET_EXPORT void CreateSpdyHeadersFromHttpRequestForExtendedConnect( @@ -70,18 +70,18 @@ NET_EXPORT void CreateSpdyHeadersFromHttpRequestForExtendedConnect( std::optional priority, const std::string& ext_connect_protocol, const HttpRequestHeaders& request_headers, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); -// Create a spdy::Http2HeaderBlock from HttpRequestInfo and HttpRequestHeaders +// Create a quiche::HttpHeaderBlock from HttpRequestInfo and HttpRequestHeaders // for a WebSockets over HTTP/2 request. NET_EXPORT void CreateSpdyHeadersFromHttpRequestForWebSocket( const GURL& url, const HttpRequestHeaders& request_headers, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); -// Create HttpRequestHeaders from spdy::Http2HeaderBlock. +// Create HttpRequestHeaders from quiche::HttpHeaderBlock. NET_EXPORT void ConvertHeaderBlockToHttpRequestHeaders( - const spdy::Http2HeaderBlock& spdy_headers, + const quiche::HttpHeaderBlock& spdy_headers, HttpRequestHeaders* http_headers); NET_EXPORT spdy::SpdyPriority ConvertRequestPriorityToSpdyPriority( diff --git a/naiveproxy/src/net/spdy/spdy_log_util.cc b/naiveproxy/src/net/spdy/spdy_log_util.cc index d70ea94647..2381d7eaff 100644 --- a/naiveproxy/src/net/spdy/spdy_log_util.cc +++ b/naiveproxy/src/net/spdy/spdy_log_util.cc @@ -24,8 +24,8 @@ base::Value ElideGoAwayDebugDataForNetLog(NetLogCaptureMode capture_mode, {"[", base::NumberToString(debug_data.size()), " bytes were stripped]"})); } -base::Value::List ElideHttp2HeaderBlockForNetLog( - const spdy::Http2HeaderBlock& headers, +base::Value::List ElideHttpHeaderBlockForNetLog( + const quiche::HttpHeaderBlock& headers, NetLogCaptureMode capture_mode) { base::Value::List headers_list; for (const auto& [key, value] : headers) { @@ -37,11 +37,11 @@ base::Value::List ElideHttp2HeaderBlockForNetLog( return headers_list; } -base::Value::Dict Http2HeaderBlockNetLogParams( - const spdy::Http2HeaderBlock* headers, +base::Value::Dict HttpHeaderBlockNetLogParams( + const quiche::HttpHeaderBlock* headers, NetLogCaptureMode capture_mode) { return base::Value::Dict().Set( - "headers", ElideHttp2HeaderBlockForNetLog(*headers, capture_mode)); + "headers", ElideHttpHeaderBlockForNetLog(*headers, capture_mode)); } } // namespace net diff --git a/naiveproxy/src/net/spdy/spdy_log_util.h b/naiveproxy/src/net/spdy/spdy_log_util.h index 4a84cb75e3..6540132693 100644 --- a/naiveproxy/src/net/spdy/spdy_log_util.h +++ b/naiveproxy/src/net/spdy/spdy_log_util.h @@ -12,7 +12,7 @@ #include "net/http/http_log_util.h" #include "net/log/net_log.h" #include "net/log/net_log_capture_mode.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" namespace net { @@ -22,14 +22,14 @@ NET_EXPORT_PRIVATE base::Value ElideGoAwayDebugDataForNetLog( NetLogCaptureMode capture_mode, std::string_view debug_data); -// Given a spdy::Http2HeaderBlock, return its base::Value::List representation. -NET_EXPORT_PRIVATE base::Value::List ElideHttp2HeaderBlockForNetLog( - const spdy::Http2HeaderBlock& headers, +// Given a quiche::HttpHeaderBlock, return its base::Value::List representation. +NET_EXPORT_PRIVATE base::Value::List ElideHttpHeaderBlockForNetLog( + const quiche::HttpHeaderBlock& headers, NetLogCaptureMode capture_mode); -// Converts a spdy::Http2HeaderBlock into NetLog event parameters. -NET_EXPORT_PRIVATE base::Value::Dict Http2HeaderBlockNetLogParams( - const spdy::Http2HeaderBlock* headers, +// Converts a quiche::HttpHeaderBlock into NetLog event parameters. +NET_EXPORT_PRIVATE base::Value::Dict HttpHeaderBlockNetLogParams( + const quiche::HttpHeaderBlock* headers, NetLogCaptureMode capture_mode); } // namespace net diff --git a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc index f1dc76d69a..4c92611207 100644 --- a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc +++ b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc @@ -406,7 +406,7 @@ int SpdyProxyClientSocket::DoSendRequest() { NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, request_line, &request_.extra_headers); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; CreateSpdyHeadersFromHttpRequest(request_, std::nullopt, request_.extra_headers, &headers); @@ -480,10 +480,10 @@ void SpdyProxyClientSocket::OnHeadersSent() { } void SpdyProxyClientSocket::OnEarlyHintsReceived( - const spdy::Http2HeaderBlock& headers) {} + const quiche::HttpHeaderBlock& headers) {} void SpdyProxyClientSocket::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { if (use_fastopen_ && read_headers_pending_ && next_state_ == STATE_OPEN) { next_state_ = STATE_READ_REPLY_COMPLETE; } @@ -553,7 +553,8 @@ void SpdyProxyClientSocket::OnDataSent() { weak_factory_.GetWeakPtr(), rv)); } -void SpdyProxyClientSocket::OnTrailers(const spdy::Http2HeaderBlock& trailers) { +void SpdyProxyClientSocket::OnTrailers( + const quiche::HttpHeaderBlock& trailers) { // |spdy_stream_| is of type SPDY_BIDIRECTIONAL_STREAM, so trailers are // combined with response headers and this method will not be calld. NOTREACHED_IN_MIGRATION(); diff --git a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.h b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.h index f617f6dfcc..8c77b06057 100644 --- a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.h +++ b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.h @@ -29,6 +29,7 @@ #include "net/spdy/spdy_read_queue.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_stream.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -98,12 +99,12 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket, // SpdyStream::Delegate implementation. void OnHeadersSent() override; - void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override; + void OnEarlyHintsReceived(const quiche::HttpHeaderBlock& headers) override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnDataReceived(std::unique_ptr buffer) override; void OnDataSent() override; - void OnTrailers(const spdy::Http2HeaderBlock& trailers) override; + void OnTrailers(const quiche::HttpHeaderBlock& trailers) override; void OnClose(int status) override; bool CanGreaseFrameType() const override; NetLogSource source_dependency() const override; diff --git a/naiveproxy/src/net/spdy/spdy_session.cc b/naiveproxy/src/net/spdy/spdy_session.cc index 9f47708443..b94e441b28 100644 --- a/naiveproxy/src/net/spdy/spdy_session.cc +++ b/naiveproxy/src/net/spdy/spdy_session.cc @@ -179,7 +179,7 @@ void LogSpdyAcceptChForOriginHistogram(bool value) { } base::Value::Dict NetLogSpdyHeadersSentParams( - const spdy::Http2HeaderBlock* headers, + const quiche::HttpHeaderBlock* headers, bool fin, spdy::SpdyStreamId stream_id, bool has_priority, @@ -188,12 +188,12 @@ base::Value::Dict NetLogSpdyHeadersSentParams( bool exclusive, NetLogSource source_dependency, NetLogCaptureMode capture_mode) { - auto dict = base::Value::Dict() - .Set("headers", - ElideHttp2HeaderBlockForNetLog(*headers, capture_mode)) - .Set("fin", fin) - .Set("stream_id", static_cast(stream_id)) - .Set("has_priority", has_priority); + auto dict = + base::Value::Dict() + .Set("headers", ElideHttpHeaderBlockForNetLog(*headers, capture_mode)) + .Set("fin", fin) + .Set("stream_id", static_cast(stream_id)) + .Set("has_priority", has_priority); if (has_priority) { dict.Set("parent_stream_id", static_cast(parent_stream_id)); dict.Set("weight", weight); @@ -206,12 +206,12 @@ base::Value::Dict NetLogSpdyHeadersSentParams( } base::Value::Dict NetLogSpdyHeadersReceivedParams( - const spdy::Http2HeaderBlock* headers, + const quiche::HttpHeaderBlock* headers, bool fin, spdy::SpdyStreamId stream_id, NetLogCaptureMode capture_mode) { return base::Value::Dict() - .Set("headers", ElideHttp2HeaderBlockForNetLog(*headers, capture_mode)) + .Set("headers", ElideHttpHeaderBlockForNetLog(*headers, capture_mode)) .Set("fin", fin) .Set("stream_id", static_cast(stream_id)); } @@ -1050,7 +1050,7 @@ std::unique_ptr SpdySession::CreateHeaders( spdy::SpdyStreamId stream_id, RequestPriority priority, spdy::SpdyControlFlags flags, - spdy::Http2HeaderBlock block, + quiche::HttpHeaderBlock block, NetLogSource source_dependency) { ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); CHECK(it != active_streams_.end()); @@ -1420,7 +1420,8 @@ bool SpdySession::IsReused() const { // connected socket, since canceling the H2 session request would have // destroyed the socket. return owned_stream_socket_ || - client_socket_handle_->reuse_type() == ClientSocketHandle::UNUSED_IDLE; + client_socket_handle_->reuse_type() == + StreamSocketHandle::SocketReuseType::kUnusedIdle; } bool SpdySession::GetLoadTimingInfo(spdy::SpdyStreamId stream_id, @@ -2976,7 +2977,7 @@ void SpdySession::OnWindowUpdate(spdy::SpdyStreamId stream_id, void SpdySession::OnPushPromise(spdy::SpdyStreamId /*stream_id*/, spdy::SpdyStreamId /*promised_stream_id*/, - spdy::Http2HeaderBlock /*headers*/) { + quiche::HttpHeaderBlock /*headers*/) { CHECK(in_io_loop_); DoDrainSession(ERR_HTTP2_PROTOCOL_ERROR, "PUSH_PROMISE received"); } @@ -2987,7 +2988,7 @@ void SpdySession::OnHeaders(spdy::SpdyStreamId stream_id, spdy::SpdyStreamId parent_stream_id, bool exclusive, bool fin, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, base::TimeTicks recv_first_byte_time) { CHECK(in_io_loop_); diff --git a/naiveproxy/src/net/spdy/spdy_session.h b/naiveproxy/src/net/spdy/spdy_session.h index 3a72f8bf37..7cd1ceb436 100644 --- a/naiveproxy/src/net/spdy/spdy_session.h +++ b/naiveproxy/src/net/spdy/spdy_session.h @@ -49,7 +49,7 @@ #include "net/spdy/spdy_stream.h" #include "net/spdy/spdy_write_queue.h" #include "net/ssl/ssl_config_service.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" @@ -441,7 +441,7 @@ class NET_EXPORT SpdySession spdy::SpdyStreamId stream_id, RequestPriority priority, spdy::SpdyControlFlags flags, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, NetLogSource source_dependency); // Creates and returns a SpdyBuffer holding a data frame with the given data. @@ -626,7 +626,7 @@ class NET_EXPORT SpdySession using PendingStreamRequestQueue = base::circular_deque>; using ActiveStreamMap = std::map; - using CreatedStreamSet = std::set>; + using CreatedStreamSet = std::set>; enum AvailabilityState { // The session is available in its socket pool and can be used @@ -889,14 +889,14 @@ class NET_EXPORT SpdySession int delta_window_size) override; void OnPushPromise(spdy::SpdyStreamId stream_id, spdy::SpdyStreamId promised_stream_id, - spdy::Http2HeaderBlock headers) override; + quiche::HttpHeaderBlock headers) override; void OnHeaders(spdy::SpdyStreamId stream_id, bool has_priority, int weight, spdy::SpdyStreamId parent_stream_id, bool exclusive, bool fin, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, base::TimeTicks recv_first_byte_time) override; void OnAltSvc(spdy::SpdyStreamId stream_id, std::string_view origin, diff --git a/naiveproxy/src/net/spdy/spdy_session_pool.cc b/naiveproxy/src/net/spdy/spdy_session_pool.cc index 3f714e8395..16cc84b86a 100644 --- a/naiveproxy/src/net/spdy/spdy_session_pool.cc +++ b/naiveproxy/src/net/spdy/spdy_session_pool.cc @@ -30,8 +30,8 @@ #include "net/log/net_log_with_source.h" #include "net/socket/client_socket_handle.h" #include "net/spdy/spdy_session.h" -#include "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.h" -#include "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.h" +#include "net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.h" +#include "net/third_party/quiche/src/quiche/http2/hpack/hpack_static_table.h" namespace net { diff --git a/naiveproxy/src/net/spdy/spdy_session_pool.h b/naiveproxy/src/net/spdy/spdy_session_pool.h index 6970a22fd2..08c9cc512b 100644 --- a/naiveproxy/src/net/spdy/spdy_session_pool.h +++ b/naiveproxy/src/net/spdy/spdy_session_pool.h @@ -322,14 +322,14 @@ class NET_EXPORT SpdySessionPool private: friend class SpdySessionPoolPeer; // For testing. - using SessionSet = std::set>; + using SessionSet = std::set>; using WeakSessionList = std::vector>; using AvailableSessionMap = std::map>; using AliasMap = std::multimap; using DnsAliasesBySessionKeyMap = std::map>; - using RequestSet = std::set>; + using RequestSet = std::set>; struct RequestInfoForKey { RequestInfoForKey(); diff --git a/naiveproxy/src/net/spdy/spdy_stream.cc b/naiveproxy/src/net/spdy/spdy_stream.cc index 1841a0f0f2..ac43a10175 100644 --- a/naiveproxy/src/net/spdy/spdy_stream.cc +++ b/naiveproxy/src/net/spdy/spdy_stream.cc @@ -328,7 +328,7 @@ void SpdyStream::SetRequestTime(base::Time t) { } void SpdyStream::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers, + const quiche::HttpHeaderBlock& response_headers, base::Time response_time, base::TimeTicks recv_first_byte_time) { switch (response_state_) { @@ -336,7 +336,7 @@ void SpdyStream::OnHeadersReceived( // No header block has been received yet. DCHECK(response_headers_.empty()); - spdy::Http2HeaderBlock::const_iterator it = + quiche::HttpHeaderBlock::const_iterator it = response_headers.find(spdy::kHttp2StatusHeader); if (it == response_headers.end()) { const std::string error("Response headers do not include :status."); @@ -617,12 +617,12 @@ base::WeakPtr SpdyStream::GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } -int SpdyStream::SendRequestHeaders(spdy::Http2HeaderBlock request_headers, +int SpdyStream::SendRequestHeaders(quiche::HttpHeaderBlock request_headers, SpdySendStatus send_status) { net_log_.AddEvent( NetLogEventType::HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS, [&](NetLogCaptureMode capture_mode) { - return Http2HeaderBlockNetLogParams(&request_headers, capture_mode); + return HttpHeaderBlockNetLogParams(&request_headers, capture_mode); }); CHECK_EQ(pending_send_status_, MORE_DATA_TO_SEND); CHECK(!request_headers_valid_); @@ -772,7 +772,7 @@ void SpdyStream::QueueNextDataFrame() { } void SpdyStream::OnEarlyHintsReceived( - const spdy::Http2HeaderBlock& response_headers, + const quiche::HttpHeaderBlock& response_headers, base::TimeTicks recv_first_byte_time) { // Record the timing of the 103 Early Hints response for the experiment // (https://crbug.com/1093693). @@ -801,7 +801,7 @@ void SpdyStream::OnEarlyHintsReceived( } void SpdyStream::SaveResponseHeaders( - const spdy::Http2HeaderBlock& response_headers, + const quiche::HttpHeaderBlock& response_headers, int status) { if (response_headers.contains("transfer-encoding")) { session_->ResetStream(stream_id_, ERR_HTTP2_PROTOCOL_ERROR, diff --git a/naiveproxy/src/net/spdy/spdy_stream.h b/naiveproxy/src/net/spdy/spdy_stream.h index 8f4ab54451..8908842c7c 100644 --- a/naiveproxy/src/net/spdy/spdy_stream.h +++ b/naiveproxy/src/net/spdy/spdy_stream.h @@ -25,7 +25,7 @@ #include "net/socket/next_proto.h" #include "net/socket/ssl_client_socket.h" #include "net/spdy/spdy_buffer.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -90,11 +90,11 @@ class NET_EXPORT_PRIVATE SpdyStream { // Called when a 103 Early Hints response is received. virtual void OnEarlyHintsReceived( - const spdy::Http2HeaderBlock& headers) = 0; + const quiche::HttpHeaderBlock& headers) = 0; // Called when response headers have been received. virtual void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) = 0; + const quiche::HttpHeaderBlock& response_headers) = 0; // Called when data is received. |buffer| may be NULL, which signals EOF. // May cause the stream to be closed. @@ -104,7 +104,7 @@ class NET_EXPORT_PRIVATE SpdyStream { virtual void OnDataSent() = 0; // Called when trailers are received. - virtual void OnTrailers(const spdy::Http2HeaderBlock& trailers) = 0; + virtual void OnTrailers(const quiche::HttpHeaderBlock& trailers) = 0; // Called when SpdyStream is closed. No other delegate functions // will be called after this is called, and the delegate must not @@ -262,7 +262,7 @@ class NET_EXPORT_PRIVATE SpdyStream { // Called by SpdySession when headers are received for this stream. May close // the stream. - void OnHeadersReceived(const spdy::Http2HeaderBlock& response_headers, + void OnHeadersReceived(const quiche::HttpHeaderBlock& response_headers, base::Time response_time, base::TimeTicks recv_first_byte_time); @@ -329,7 +329,7 @@ class NET_EXPORT_PRIVATE SpdyStream { // MORE_DATA_TO_SEND for bidirectional streams; for request/response streams, // it must be MORE_DATA_TO_SEND if the request has data to upload, or // NO_MORE_DATA_TO_SEND if not. - int SendRequestHeaders(spdy::Http2HeaderBlock request_headers, + int SendRequestHeaders(quiche::HttpHeaderBlock request_headers, SpdySendStatus send_status); // Sends a DATA frame. The delegate will be notified via @@ -385,10 +385,10 @@ class NET_EXPORT_PRIVATE SpdyStream { bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const; - const spdy::Http2HeaderBlock& request_headers() const { + const quiche::HttpHeaderBlock& request_headers() const { return request_headers_; } - const spdy::Http2HeaderBlock& response_headers() const { + const quiche::HttpHeaderBlock& response_headers() const { return response_headers_; } @@ -439,12 +439,12 @@ class NET_EXPORT_PRIVATE SpdyStream { // |pending_send_data_| is set. void QueueNextDataFrame(); - void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& response_headers, + void OnEarlyHintsReceived(const quiche::HttpHeaderBlock& response_headers, base::TimeTicks recv_first_byte_time); // Saves the given headers into |response_headers_| and calls // OnHeadersReceived() on the delegate if attached. - void SaveResponseHeaders(const spdy::Http2HeaderBlock& response_headers, + void SaveResponseHeaders(const quiche::HttpHeaderBlock& response_headers, int status); static std::string DescribeState(State state); @@ -485,7 +485,7 @@ class NET_EXPORT_PRIVATE SpdyStream { // The headers for the request to send. bool request_headers_valid_ = false; - spdy::Http2HeaderBlock request_headers_; + quiche::HttpHeaderBlock request_headers_; // Data waiting to be sent, and the close state of the local endpoint // after the data is fully written. @@ -502,7 +502,7 @@ class NET_EXPORT_PRIVATE SpdyStream { // For cached responses, this time could be "far" in the past. base::Time request_time_; - spdy::Http2HeaderBlock response_headers_; + quiche::HttpHeaderBlock response_headers_; ResponseState response_state_ = READY_FOR_HEADERS; base::Time response_time_; diff --git a/naiveproxy/src/net/spdy/spdy_stream_test_util.cc b/naiveproxy/src/net/spdy/spdy_stream_test_util.cc index 247bf16bd8..0cc983baf1 100644 --- a/naiveproxy/src/net/spdy/spdy_stream_test_util.cc +++ b/naiveproxy/src/net/spdy/spdy_stream_test_util.cc @@ -23,16 +23,16 @@ ClosingDelegate::~ClosingDelegate() = default; void ClosingDelegate::OnHeadersSent() {} void ClosingDelegate::OnEarlyHintsReceived( - const spdy::Http2HeaderBlock& headers) {} + const quiche::HttpHeaderBlock& headers) {} void ClosingDelegate::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) {} + const quiche::HttpHeaderBlock& response_headers) {} void ClosingDelegate::OnDataReceived(std::unique_ptr buffer) {} void ClosingDelegate::OnDataSent() {} -void ClosingDelegate::OnTrailers(const spdy::Http2HeaderBlock& trailers) {} +void ClosingDelegate::OnTrailers(const quiche::HttpHeaderBlock& trailers) {} void ClosingDelegate::OnClose(int status) { DCHECK(stream_); @@ -60,13 +60,13 @@ void StreamDelegateBase::OnHeadersSent() { } void StreamDelegateBase::OnEarlyHintsReceived( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { EXPECT_TRUE(send_headers_completed_); early_hints_.push_back(headers.Clone()); } void StreamDelegateBase::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { EXPECT_TRUE(send_headers_completed_); response_headers_ = response_headers.Clone(); } @@ -78,7 +78,7 @@ void StreamDelegateBase::OnDataReceived(std::unique_ptr buffer) { void StreamDelegateBase::OnDataSent() {} -void StreamDelegateBase::OnTrailers(const spdy::Http2HeaderBlock& trailers) {} +void StreamDelegateBase::OnTrailers(const quiche::HttpHeaderBlock& trailers) {} void StreamDelegateBase::OnClose(int status) { if (!stream_.get()) @@ -114,7 +114,7 @@ std::string StreamDelegateBase::TakeReceivedData() { std::string StreamDelegateBase::GetResponseHeaderValue( const std::string& name) const { - spdy::Http2HeaderBlock::const_iterator it = response_headers_.find(name); + quiche::HttpHeaderBlock::const_iterator it = response_headers_.find(name); return (it == response_headers_.end()) ? std::string() : std::string(it->second); } @@ -149,7 +149,7 @@ StreamDelegateSendImmediate::StreamDelegateSendImmediate( StreamDelegateSendImmediate::~StreamDelegateSendImmediate() = default; void StreamDelegateSendImmediate::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { StreamDelegateBase::OnHeadersReceived(response_headers); if (data_.data()) { scoped_refptr buf = @@ -179,7 +179,7 @@ StreamDelegateCloseOnHeaders::StreamDelegateCloseOnHeaders( StreamDelegateCloseOnHeaders::~StreamDelegateCloseOnHeaders() = default; void StreamDelegateCloseOnHeaders::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { stream()->Cancel(ERR_ABORTED); } diff --git a/naiveproxy/src/net/spdy/spdy_stream_test_util.h b/naiveproxy/src/net/spdy/spdy_stream_test_util.h index b6f4b49440..faeb5fb477 100644 --- a/naiveproxy/src/net/spdy/spdy_stream_test_util.h +++ b/naiveproxy/src/net/spdy/spdy_stream_test_util.h @@ -17,6 +17,7 @@ #include "net/log/net_log_source.h" #include "net/spdy/spdy_read_queue.h" #include "net/spdy/spdy_stream.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" namespace net::test { @@ -28,13 +29,13 @@ class ClosingDelegate : public SpdyStream::Delegate { ~ClosingDelegate() override; // SpdyStream::Delegate implementation. - void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override; + void OnEarlyHintsReceived(const quiche::HttpHeaderBlock& headers) override; void OnHeadersSent() override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnDataReceived(std::unique_ptr buffer) override; void OnDataSent() override; - void OnTrailers(const spdy::Http2HeaderBlock& trailers) override; + void OnTrailers(const quiche::HttpHeaderBlock& trailers) override; void OnClose(int status) override; bool CanGreaseFrameType() const override; NetLogSource source_dependency() const override; @@ -54,12 +55,12 @@ class StreamDelegateBase : public SpdyStream::Delegate { ~StreamDelegateBase() override; void OnHeadersSent() override; - void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override; + void OnEarlyHintsReceived(const quiche::HttpHeaderBlock& headers) override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnDataReceived(std::unique_ptr buffer) override; void OnDataSent() override; - void OnTrailers(const spdy::Http2HeaderBlock& trailers) override; + void OnTrailers(const quiche::HttpHeaderBlock& trailers) override; void OnClose(int status) override; bool CanGreaseFrameType() const override; NetLogSource source_dependency() const override; @@ -80,7 +81,7 @@ class StreamDelegateBase : public SpdyStream::Delegate { spdy::SpdyStreamId stream_id() const { return stream_id_; } // Returns 103 Early Hints response headers. - const std::vector& early_hints() const { + const std::vector& early_hints() const { return early_hints_; } @@ -99,8 +100,8 @@ class StreamDelegateBase : public SpdyStream::Delegate { spdy::SpdyStreamId stream_id_ = 0; TestCompletionCallback callback_; bool send_headers_completed_ = false; - std::vector early_hints_; - spdy::Http2HeaderBlock response_headers_; + std::vector early_hints_; + quiche::HttpHeaderBlock response_headers_; SpdyReadQueue received_data_queue_; LoadTimingInfo load_timing_info_; }; @@ -131,7 +132,7 @@ class StreamDelegateSendImmediate : public StreamDelegateBase { ~StreamDelegateSendImmediate() override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; private: std::string_view data_; @@ -158,7 +159,7 @@ class StreamDelegateCloseOnHeaders : public StreamDelegateBase { ~StreamDelegateCloseOnHeaders() override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; }; // Test delegate that sets a flag when EOF is detected. diff --git a/naiveproxy/src/net/spdy/spdy_test_util_common.cc b/naiveproxy/src/net/spdy/spdy_test_util_common.cc index c081373e8d..631b0f0614 100644 --- a/naiveproxy/src/net/spdy/spdy_test_util_common.cc +++ b/naiveproxy/src/net/spdy/spdy_test_util_common.cc @@ -112,7 +112,7 @@ std::unique_ptr ChopWriteFrame( // |headers| gets filled in from |extra_headers|. void AppendToHeaderBlock(const char* const extra_headers[], int extra_header_count, - spdy::Http2HeaderBlock* headers) { + quiche::HttpHeaderBlock* headers) { if (!extra_header_count) return; @@ -203,7 +203,7 @@ class PriorityGetter : public BufferedSpdyFramerVisitorInterface { spdy::SpdyStreamId parent_stream_id, bool exclusive, bool fin, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, base::TimeTicks recv_first_byte_time) override { if (has_priority) { priority_ = spdy::Http2WeightToSpdy3Priority(weight); @@ -231,7 +231,7 @@ class PriorityGetter : public BufferedSpdyFramerVisitorInterface { int delta_window_size) override {} void OnPushPromise(spdy::SpdyStreamId stream_id, spdy::SpdyStreamId promised_stream_id, - spdy::Http2HeaderBlock headers) override {} + quiche::HttpHeaderBlock headers) override {} void OnAltSvc(spdy::SpdyStreamId stream_id, std::string_view origin, const spdy::SpdyAltSvcWireFormat::AlternativeServiceVector& @@ -308,6 +308,8 @@ SpdySessionDependencies::SpdySessionDependencies( cert_verifier(std::make_unique()), transport_security_state(std::make_unique()), proxy_resolution_service(std::move(proxy_resolution_service)), + http_user_agent_settings( + std::make_unique("*", "test-ua")), ssl_config_service(std::make_unique()), socket_factory(std::make_unique()), http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()), @@ -594,7 +596,7 @@ SpdyTestUtil::SpdyTestUtil(bool use_priority_header) SpdyTestUtil::~SpdyTestUtil() = default; void SpdyTestUtil::AddUrlToHeaderBlock(std::string_view url, - spdy::Http2HeaderBlock* headers) const { + quiche::HttpHeaderBlock* headers) const { std::string scheme, host, path; ParseUrl(url, &scheme, &host, &path); (*headers)[spdy::kHttp2AuthorityHeader] = host; @@ -605,7 +607,7 @@ void SpdyTestUtil::AddUrlToHeaderBlock(std::string_view url, void SpdyTestUtil::AddPriorityToHeaderBlock( RequestPriority request_priority, bool priority_incremental, - spdy::Http2HeaderBlock* headers) const { + quiche::HttpHeaderBlock* headers) const { if (use_priority_header_ && base::FeatureList::IsEnabled(net::features::kPriorityHeader)) { uint8_t urgency = ConvertRequestPriorityToQuicPriority(request_priority); @@ -620,42 +622,42 @@ void SpdyTestUtil::AddPriorityToHeaderBlock( } // static -spdy::Http2HeaderBlock SpdyTestUtil::ConstructGetHeaderBlock( +quiche::HttpHeaderBlock SpdyTestUtil::ConstructGetHeaderBlock( std::string_view url) { return ConstructHeaderBlock("GET", url, nullptr); } // static -spdy::Http2HeaderBlock SpdyTestUtil::ConstructGetHeaderBlockForProxy( +quiche::HttpHeaderBlock SpdyTestUtil::ConstructGetHeaderBlockForProxy( std::string_view url) { return ConstructGetHeaderBlock(url); } // static -spdy::Http2HeaderBlock SpdyTestUtil::ConstructHeadHeaderBlock( +quiche::HttpHeaderBlock SpdyTestUtil::ConstructHeadHeaderBlock( std::string_view url, int64_t content_length) { return ConstructHeaderBlock("HEAD", url, nullptr); } // static -spdy::Http2HeaderBlock SpdyTestUtil::ConstructPostHeaderBlock( +quiche::HttpHeaderBlock SpdyTestUtil::ConstructPostHeaderBlock( std::string_view url, int64_t content_length) { return ConstructHeaderBlock("POST", url, &content_length); } // static -spdy::Http2HeaderBlock SpdyTestUtil::ConstructPutHeaderBlock( +quiche::HttpHeaderBlock SpdyTestUtil::ConstructPutHeaderBlock( std::string_view url, int64_t content_length) { return ConstructHeaderBlock("PUT", url, &content_length); } std::string SpdyTestUtil::ConstructSpdyReplyString( - const spdy::Http2HeaderBlock& headers) const { + const quiche::HttpHeaderBlock& headers) const { std::string reply_string; - for (spdy::Http2HeaderBlock::const_iterator it = headers.begin(); + for (quiche::HttpHeaderBlock::const_iterator it = headers.begin(); it != headers.end(); ++it) { auto key = std::string(it->first); // Remove leading colon from pseudo headers. @@ -752,7 +754,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyGet( RequestPriority request_priority, bool priority_incremental, std::optional header_request_priority) { - spdy::Http2HeaderBlock block(ConstructGetHeaderBlock(url)); + quiche::HttpHeaderBlock block(ConstructGetHeaderBlock(url)); return ConstructSpdyHeaders(stream_id, std::move(block), request_priority, true, priority_incremental, header_request_priority); @@ -765,7 +767,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyGet( RequestPriority request_priority, bool priority_incremental, std::optional header_request_priority) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[spdy::kHttp2MethodHeader] = "GET"; AddUrlToHeaderBlock(default_url_.spec(), &block); AppendToHeaderBlock(extra_headers, extra_header_count, &block); @@ -780,17 +782,21 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyConnect( int stream_id, RequestPriority priority, const HostPortPair& host_port_pair) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[spdy::kHttp2MethodHeader] = "CONNECT"; block[spdy::kHttp2AuthorityHeader] = host_port_pair.ToString(); - AppendToHeaderBlock(extra_headers, extra_header_count, &block); + if (extra_headers) { + AppendToHeaderBlock(extra_headers, extra_header_count, &block); + } else { + block["user-agent"] = "test-ua"; + } return ConstructSpdyHeaders(stream_id, std::move(block), priority, false); } spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyPushPromise( spdy::SpdyStreamId associated_stream_id, spdy::SpdyStreamId stream_id, - spdy::Http2HeaderBlock headers) { + quiche::HttpHeaderBlock headers) { spdy::SpdyPushPromiseIR push_promise(associated_stream_id, stream_id, std::move(headers)); return spdy::SpdySerializedFrame( @@ -799,7 +805,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyPushPromise( spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyResponseHeaders( int stream_id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, bool fin) { spdy::SpdyHeadersIR spdy_headers(stream_id, std::move(headers)); spdy_headers.set_fin(fin); @@ -809,7 +815,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyResponseHeaders( spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyHeaders( int stream_id, - spdy::Http2HeaderBlock block, + quiche::HttpHeaderBlock block, RequestPriority priority, bool fin, bool priority_incremental, @@ -851,7 +857,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyHeaders( spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyReply( int stream_id, - spdy::Http2HeaderBlock headers) { + quiche::HttpHeaderBlock headers) { spdy::SpdyHeadersIR reply(stream_id, std::move(headers)); return spdy::SpdySerializedFrame(response_spdy_framer_.SerializeFrame(reply)); } @@ -861,7 +867,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyReplyError( const char* const* const extra_headers, int extra_header_count, int stream_id) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[spdy::kHttp2StatusHeader] = status; block["hello"] = "bye"; AppendToHeaderBlock(extra_headers, extra_header_count, &block); @@ -878,7 +884,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyGetReply( const char* const extra_headers[], int extra_header_count, int stream_id) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[spdy::kHttp2StatusHeader] = "200"; block["hello"] = "bye"; AppendToHeaderBlock(extra_headers, extra_header_count, &block); @@ -894,7 +900,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyPost( const char* const extra_headers[], int extra_header_count, bool priority_incremental) { - spdy::Http2HeaderBlock block(ConstructPostHeaderBlock(url, content_length)); + quiche::HttpHeaderBlock block(ConstructPostHeaderBlock(url, content_length)); AppendToHeaderBlock(extra_headers, extra_header_count, &block); return ConstructSpdyHeaders(stream_id, std::move(block), request_priority, false, priority_incremental); @@ -905,7 +911,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructChunkedSpdyPost( int extra_header_count, RequestPriority request_priority, bool priority_incremental) { - spdy::Http2HeaderBlock block; + quiche::HttpHeaderBlock block; block[spdy::kHttp2MethodHeader] = "POST"; AddUrlToHeaderBlock(default_url_.spec(), &block); AppendToHeaderBlock(extra_headers, extra_header_count, &block); @@ -973,13 +979,13 @@ void SpdyTestUtil::UpdateWithStreamDestruction(int stream_id) { } // static -spdy::Http2HeaderBlock SpdyTestUtil::ConstructHeaderBlock( +quiche::HttpHeaderBlock SpdyTestUtil::ConstructHeaderBlock( std::string_view method, std::string_view url, int64_t* content_length) { std::string scheme, host, path; ParseUrl(url, &scheme, &host, &path); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[spdy::kHttp2MethodHeader] = std::string(method); headers[spdy::kHttp2AuthorityHeader] = host.c_str(); headers[spdy::kHttp2SchemeHeader] = scheme.c_str(); diff --git a/naiveproxy/src/net/spdy/spdy_test_util_common.h b/naiveproxy/src/net/spdy/spdy_test_util_common.h index e7d63ab52f..0a77338fb7 100644 --- a/naiveproxy/src/net/spdy/spdy_test_util_common.h +++ b/naiveproxy/src/net/spdy/spdy_test_util_common.h @@ -35,6 +35,7 @@ #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_session_pool.h" #include "net/ssl/ssl_config_service_defaults.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" #include "testing/gtest/include/gtest/gtest.h" @@ -85,7 +86,7 @@ std::unique_ptr ChopWriteFrame( // |headers| gets filled in from |extra_headers|. void AppendToHeaderBlock(const char* const extra_headers[], int extra_header_count, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); // Create an async MockWrite from the given spdy::SpdySerializedFrame. MockWrite CreateMockWrite(const spdy::SpdySerializedFrame& req); @@ -275,28 +276,29 @@ class SpdyTestUtil { // Add the appropriate headers to put |url| into |block|. void AddUrlToHeaderBlock(std::string_view url, - spdy::Http2HeaderBlock* headers) const; + quiche::HttpHeaderBlock* headers) const; // Add the appropriate priority header if PriorityHeaders is enabled. void AddPriorityToHeaderBlock(RequestPriority request_priority, bool priority_incremental, - spdy::Http2HeaderBlock* headers) const; + quiche::HttpHeaderBlock* headers) const; - static spdy::Http2HeaderBlock ConstructGetHeaderBlock(std::string_view url); - static spdy::Http2HeaderBlock ConstructGetHeaderBlockForProxy( + static quiche::HttpHeaderBlock ConstructGetHeaderBlock(std::string_view url); + static quiche::HttpHeaderBlock ConstructGetHeaderBlockForProxy( std::string_view url); - static spdy::Http2HeaderBlock ConstructHeadHeaderBlock( + static quiche::HttpHeaderBlock ConstructHeadHeaderBlock( std::string_view url, int64_t content_length); - static spdy::Http2HeaderBlock ConstructPostHeaderBlock( + static quiche::HttpHeaderBlock ConstructPostHeaderBlock( + std::string_view url, + int64_t content_length); + static quiche::HttpHeaderBlock ConstructPutHeaderBlock( std::string_view url, int64_t content_length); - static spdy::Http2HeaderBlock ConstructPutHeaderBlock(std::string_view url, - int64_t content_length); // Construct an expected SPDY reply string from the given headers. std::string ConstructSpdyReplyString( - const spdy::Http2HeaderBlock& headers) const; + const quiche::HttpHeaderBlock& headers) const; // Construct an expected SPDY SETTINGS frame. // |settings| are the settings to set. @@ -363,7 +365,9 @@ class SpdyTestUtil { bool priority_incremental = kDefaultPriorityIncremental, std::optional header_request_priority = std::nullopt); - // Constructs a SPDY HEADERS frame for a CONNECT request. + // Constructs a SPDY HEADERS frame for a CONNECT request. If `extra_headers` + // is nullptr, it includes just "user-agent" "test-ua" as that is commonly + // required. spdy::SpdySerializedFrame ConstructSpdyConnect( const char* const extra_headers[], int extra_header_count, @@ -375,19 +379,19 @@ class SpdyTestUtil { spdy::SpdySerializedFrame ConstructSpdyPushPromise( spdy::SpdyStreamId associated_stream_id, spdy::SpdyStreamId stream_id, - spdy::Http2HeaderBlock headers); + quiche::HttpHeaderBlock headers); // Constructs a HEADERS frame with the request header compression context with // END_STREAM flag set to |fin|. spdy::SpdySerializedFrame ConstructSpdyResponseHeaders( int stream_id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, bool fin); // Construct a HEADERS frame carrying exactly the given headers and priority. spdy::SpdySerializedFrame ConstructSpdyHeaders( int stream_id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, RequestPriority priority, bool fin, bool priority_incremental = kDefaultPriorityIncremental, @@ -396,7 +400,7 @@ class SpdyTestUtil { // Construct a reply HEADERS frame carrying exactly the given headers and the // default priority. spdy::SpdySerializedFrame ConstructSpdyReply(int stream_id, - spdy::Http2HeaderBlock headers); + quiche::HttpHeaderBlock headers); // Constructs a standard SPDY HEADERS frame to match the SPDY GET. // |extra_headers| are the extra header-value pairs, which typically @@ -477,9 +481,9 @@ class SpdyTestUtil { private: // |content_length| may be NULL, in which case the content-length // header will be omitted. - static spdy::Http2HeaderBlock ConstructHeaderBlock(std::string_view method, - std::string_view url, - int64_t* content_length); + static quiche::HttpHeaderBlock ConstructHeaderBlock(std::string_view method, + std::string_view url, + int64_t* content_length); // Multiple SpdyFramers are required to keep track of header compression // state. diff --git a/naiveproxy/src/net/ssl/openssl_ssl_util.cc b/naiveproxy/src/net/ssl/openssl_ssl_util.cc index 76639ed95f..aa9e79409a 100644 --- a/naiveproxy/src/net/ssl/openssl_ssl_util.cc +++ b/naiveproxy/src/net/ssl/openssl_ssl_util.cc @@ -37,8 +37,6 @@ namespace { class OpenSSLNetErrorLibSingleton { public: OpenSSLNetErrorLibSingleton() { - crypto::EnsureOpenSSLInit(); - // Allocate a new error library value for inserting net errors into // OpenSSL. This does not register any ERR_STRING_DATA for the errors, so // stringifying error codes through OpenSSL will return NULL. diff --git a/naiveproxy/src/net/storage_access_api/status.h b/naiveproxy/src/net/storage_access_api/status.h new file mode 100644 index 0000000000..91cdfac791 --- /dev/null +++ b/naiveproxy/src/net/storage_access_api/status.h @@ -0,0 +1,23 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_STORAGE_ACCESS_API_STATUS_H_ +#define NET_STORAGE_ACCESS_API_STATUS_H_ + +namespace net { + +// Status related to the Storage Access API. +// Spec: https://privacycg.github.io/storage-access/ +enum class StorageAccessApiStatus { + // This context has not opted into unpartitioned cookie access via the Storage + // Access API. + kNone, + // This context has opted into unpartitioned cookie access via the Storage + // Access API. + kAccessViaAPI, +}; + +} // namespace net + +#endif // NET_STORAGE_ACCESS_API_STATUS_H_ diff --git a/naiveproxy/src/net/test/cert_builder.cc b/naiveproxy/src/net/test/cert_builder.cc index 0b0aa7055d..b19ffe6b01 100644 --- a/naiveproxy/src/net/test/cert_builder.cc +++ b/naiveproxy/src/net/test/cert_builder.cc @@ -26,7 +26,6 @@ #include "base/strings/string_util.h" #include "base/time/time.h" #include "crypto/ec_private_key.h" -#include "crypto/openssl_util.h" #include "crypto/rsa_private_key.h" #include "crypto/sha2.h" #include "net/cert/asn1_util.h" @@ -1089,7 +1088,6 @@ CertBuilder::CertBuilder(CRYPTO_BUFFER* orig_cert, if (!issuer_) issuer_ = this; - crypto::EnsureOpenSSLInit(); if (orig_cert) InitFromCert( bssl::der::Input(x509_util::CryptoBufferAsStringPiece(orig_cert))); diff --git a/naiveproxy/src/net/test/quic_simple_test_server.cc b/naiveproxy/src/net/test/quic_simple_test_server.cc index 5c6171e14b..1932253b26 100644 --- a/naiveproxy/src/net/test/quic_simple_test_server.cc +++ b/naiveproxy/src/net/test/quic_simple_test_server.cc @@ -142,11 +142,11 @@ std::string const QuicSimpleTestServer::GetSimpleHeaderValue() { } void SetupQuicMemoryCacheBackend() { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[kHelloHeaderName] = kHelloHeaderValue; headers[kStatusHeader] = kHelloStatus; headers[kCombinedHeaderName] = kCombinedHelloHeaderValue; - spdy::Http2HeaderBlock trailers; + quiche::HttpHeaderBlock trailers; trailers[kHelloTrailerName] = kHelloTrailerValue; g_quic_cache_backend = new quic::QuicMemoryCacheBackend(); g_quic_cache_backend->AddResponse(base::StringPrintf("%s", kTestServerHost), @@ -240,7 +240,7 @@ bool QuicSimpleTestServer::Start() { } void QuicSimpleTestServer::AddResponse(const std::string& path, - spdy::Http2HeaderBlock response_headers, + quiche::HttpHeaderBlock response_headers, const std::string& response_body) { g_quic_cache_backend->AddResponse( base::StringPrintf("%s:%d", kTestServerHost, GetPort()), path, @@ -249,9 +249,9 @@ void QuicSimpleTestServer::AddResponse(const std::string& path, void QuicSimpleTestServer::AddResponseWithEarlyHints( const std::string& path, - const spdy::Http2HeaderBlock& response_headers, + const quiche::HttpHeaderBlock& response_headers, const std::string& response_body, - const std::vector& early_hints) { + const std::vector& early_hints) { g_quic_cache_backend->AddResponseWithEarlyHints(kTestServerHost, path, response_headers.Clone(), response_body, early_hints); diff --git a/naiveproxy/src/net/test/quic_simple_test_server.h b/naiveproxy/src/net/test/quic_simple_test_server.h index 1c684d964a..a565866ba1 100644 --- a/naiveproxy/src/net/test/quic_simple_test_server.h +++ b/naiveproxy/src/net/test/quic_simple_test_server.h @@ -10,7 +10,7 @@ #include "base/time/time.h" #include "net/base/host_port_pair.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "url/gurl.h" namespace net { @@ -26,15 +26,15 @@ class QuicSimpleTestServer { // Add a response to `path`. static void AddResponse(const std::string& path, - spdy::Http2HeaderBlock response_headers, + quiche::HttpHeaderBlock response_headers, const std::string& response_body); // Add a response to `path` with Early Hints. static void AddResponseWithEarlyHints( const std::string& path, - const spdy::Http2HeaderBlock& response_headers, + const quiche::HttpHeaderBlock& response_headers, const std::string& response_body, - const std::vector& early_hints); + const std::vector& early_hints); // Set a delay to `path`. static void SetResponseDelay(const std::string& path, base::TimeDelta delay); diff --git a/naiveproxy/src/net/test/test_connection_cost_observer.cc b/naiveproxy/src/net/test/test_connection_cost_observer.cc new file mode 100644 index 0000000000..1acb3eb18e --- /dev/null +++ b/naiveproxy/src/net/test/test_connection_cost_observer.cc @@ -0,0 +1,51 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/test/test_connection_cost_observer.h" + +namespace net { + +TestConnectionCostObserver::TestConnectionCostObserver() = default; + +TestConnectionCostObserver::~TestConnectionCostObserver() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void TestConnectionCostObserver::OnConnectionCostChanged( + NetworkChangeNotifier::ConnectionCost cost) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + cost_changed_inputs_.push_back(cost); + + if (run_loop_) { + run_loop_->Quit(); + } +} + +void TestConnectionCostObserver::WaitForConnectionCostChanged() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + run_loop_ = std::make_unique(); + run_loop_->Run(); + run_loop_.reset(); +} + +size_t TestConnectionCostObserver::cost_changed_calls() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return cost_changed_inputs_.size(); +} + +std::vector +TestConnectionCostObserver::cost_changed_inputs() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return cost_changed_inputs_; +} + +NetworkChangeNotifier::ConnectionCost +TestConnectionCostObserver::last_cost_changed_input() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK_GT(cost_changed_inputs_.size(), 0u); + return cost_changed_inputs_.back(); +} + +} // namespace net diff --git a/naiveproxy/src/net/test/test_connection_cost_observer.h b/naiveproxy/src/net/test/test_connection_cost_observer.h new file mode 100644 index 0000000000..fdbd05f878 --- /dev/null +++ b/naiveproxy/src/net/test/test_connection_cost_observer.h @@ -0,0 +1,50 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_TEST_TEST_CONNECTION_COST_OBSERVER_H_ +#define NET_TEST_TEST_CONNECTION_COST_OBSERVER_H_ + +#include +#include + +#include "base/run_loop.h" +#include "base/sequence_checker.h" +#include "net/base/network_change_notifier.h" + +namespace net { + +class TestConnectionCostObserver final + : public NetworkChangeNotifier::ConnectionCostObserver { + public: + TestConnectionCostObserver(); + ~TestConnectionCostObserver() final; + + void OnConnectionCostChanged( + NetworkChangeNotifier::ConnectionCost cost) final; + + void WaitForConnectionCostChanged(); + + size_t cost_changed_calls() const; + std::vector cost_changed_inputs() + const; + NetworkChangeNotifier::ConnectionCost last_cost_changed_input() const; + + TestConnectionCostObserver(const TestConnectionCostObserver&) = delete; + TestConnectionCostObserver& operator=(const TestConnectionCostObserver&) = + delete; + + private: + SEQUENCE_CHECKER(sequence_checker_); + + // Set and used to block in `WaitForConnectionCostChanged()` until the next + // cost changed event occurs. + std::unique_ptr run_loop_; + + // Record each `OnConnectionCostChanged()` call. + std::vector cost_changed_inputs_; +}; + +} // namespace net + +#endif // NET_TEST_TEST_CONNECTION_COST_OBSERVER_H_ diff --git a/naiveproxy/src/net/test/test_with_task_environment.h b/naiveproxy/src/net/test/test_with_task_environment.h index 4fc24a8b9f..1cda7fae14 100644 --- a/naiveproxy/src/net/test/test_with_task_environment.h +++ b/naiveproxy/src/net/test/test_with_task_environment.h @@ -41,6 +41,12 @@ class WithTaskEnvironment { return task_environment_.MainThreadIsIdle(); } + [[nodiscard]] base::RepeatingClosure QuitClosure() { + return task_environment_.QuitClosure(); + } + + void RunUntilQuit() { task_environment_.RunUntilQuit(); } + void RunUntilIdle() { task_environment_.RunUntilIdle(); } void FastForwardBy(base::TimeDelta delta) { diff --git a/naiveproxy/src/net/test/win/fake_network_cost_manager.cc b/naiveproxy/src/net/test/win/fake_network_cost_manager.cc new file mode 100644 index 0000000000..b0d81d14cb --- /dev/null +++ b/naiveproxy/src/net/test/win/fake_network_cost_manager.cc @@ -0,0 +1,311 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/test/win/fake_network_cost_manager.h" + +#include +#include + +#include + +#include "base/task/sequenced_task_runner.h" +#include "net/base/network_cost_change_notifier_win.h" + +using Microsoft::WRL::ClassicCom; +using Microsoft::WRL::ComPtr; +using Microsoft::WRL::RuntimeClass; +using Microsoft::WRL::RuntimeClassFlags; + +namespace net { + +namespace { + +DWORD NlmConnectionCostFlagsFromConnectionCost( + NetworkChangeNotifier::ConnectionCost source_cost) { + switch (source_cost) { + case NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_UNMETERED: + return (NLM_CONNECTION_COST_UNRESTRICTED | NLM_CONNECTION_COST_CONGESTED); + case NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_METERED: + return (NLM_CONNECTION_COST_VARIABLE | NLM_CONNECTION_COST_ROAMING | + NLM_CONNECTION_COST_APPROACHINGDATALIMIT); + case NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_UNKNOWN: + default: + return NLM_CONNECTION_COST_UNKNOWN; + } +} + +void DispatchCostChangedEvent(ComPtr event_target, + DWORD cost) { + std::ignore = + event_target->CostChanged(cost, /*destination_address=*/nullptr); +} + +} // namespace + +// A fake implementation of `INetworkCostManager` that can simulate costs, +// changed costs and errors. +class FakeNetworkCostManager final + : public RuntimeClass, + INetworkCostManager, + IConnectionPointContainer, + IConnectionPoint> { + public: + FakeNetworkCostManager(NetworkChangeNotifier::ConnectionCost connection_cost, + NetworkCostManagerStatus error_status) + : error_status_(error_status), connection_cost_(connection_cost) {} + + // For each event sink in `event_sinks_`, call + // `INetworkCostManagerEvents::CostChanged()` with `changed_cost` on the event + // sink's task runner. + void PostCostChangedEvents( + NetworkChangeNotifier::ConnectionCost changed_cost) { + DWORD cost_for_changed_event; + std::map + event_sinks_for_changed_event; + { + base::AutoLock auto_lock(member_lock_); + connection_cost_ = changed_cost; + cost_for_changed_event = + NlmConnectionCostFlagsFromConnectionCost(changed_cost); + + // Get the snapshot of event sinks to notify. The snapshot collection + // creates a new `ComPtr` for each event sink, which increments each the + // event sink's reference count, ensuring that each event sink + // remains alive to receive the cost changed event notification. + event_sinks_for_changed_event = event_sinks_; + } + + for (const auto& pair : event_sinks_for_changed_event) { + const auto& registration = pair.second; + registration.event_sink_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&DispatchCostChangedEvent, registration.event_sink_, + cost_for_changed_event)); + } + } + + // Implement the `INetworkCostManager` interface. + HRESULT + __stdcall GetCost(DWORD* cost, + NLM_SOCKADDR* destination_ip_address) override { + if (error_status_ == NetworkCostManagerStatus::kErrorGetCostFailed) { + return E_FAIL; + } + + if (destination_ip_address != nullptr) { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + { + base::AutoLock auto_lock(member_lock_); + *cost = NlmConnectionCostFlagsFromConnectionCost(connection_cost_); + } + return S_OK; + } + + HRESULT __stdcall GetDataPlanStatus( + NLM_DATAPLAN_STATUS* data_plan_status, + NLM_SOCKADDR* destination_ip_address) override { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + HRESULT __stdcall SetDestinationAddresses( + UINT32 length, + NLM_SOCKADDR* destination_ip_address_list, + VARIANT_BOOL append) override { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + // Implement the `IConnectionPointContainer` interface. + HRESULT __stdcall FindConnectionPoint(REFIID connection_point_id, + IConnectionPoint** result) override { + if (error_status_ == + NetworkCostManagerStatus::kErrorFindConnectionPointFailed) { + return E_ABORT; + } + + if (connection_point_id != IID_INetworkCostManagerEvents) { + return E_NOINTERFACE; + } + + *result = static_cast(this); + AddRef(); + return S_OK; + } + + HRESULT __stdcall EnumConnectionPoints( + IEnumConnectionPoints** results) override { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + // Implement the `IConnectionPoint` interface. + HRESULT __stdcall Advise(IUnknown* event_sink, + DWORD* event_sink_cookie) override { + if (error_status_ == NetworkCostManagerStatus::kErrorAdviseFailed) { + return E_NOT_VALID_STATE; + } + + ComPtr cost_manager_event_sink; + HRESULT hr = + event_sink->QueryInterface(IID_PPV_ARGS(&cost_manager_event_sink)); + if (hr != S_OK) { + return hr; + } + + base::AutoLock auto_lock(member_lock_); + + event_sinks_[next_event_sink_cookie_] = { + cost_manager_event_sink, + base::SequencedTaskRunner::GetCurrentDefault()}; + + *event_sink_cookie = next_event_sink_cookie_; + ++next_event_sink_cookie_; + + return S_OK; + } + + HRESULT __stdcall Unadvise(DWORD event_sink_cookie) override { + base::AutoLock auto_lock(member_lock_); + + auto it = event_sinks_.find(event_sink_cookie); + if (it == event_sinks_.end()) { + return ERROR_NOT_FOUND; + } + + event_sinks_.erase(it); + return S_OK; + } + + HRESULT __stdcall GetConnectionInterface(IID* result) override { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + HRESULT __stdcall GetConnectionPointContainer( + IConnectionPointContainer** result) override { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + HRESULT __stdcall EnumConnections(IEnumConnections** result) override { + NOTIMPLEMENTED(); + return E_NOTIMPL; + } + + // Implement the `IUnknown` interface. + HRESULT __stdcall QueryInterface(REFIID interface_id, + void** result) override { + if (error_status_ == NetworkCostManagerStatus::kErrorQueryInterfaceFailed) { + return E_NOINTERFACE; + } + return RuntimeClass, INetworkCostManager, + IConnectionPointContainer, + IConnectionPoint>::QueryInterface(interface_id, result); + } + + FakeNetworkCostManager(const FakeNetworkCostManager&) = delete; + FakeNetworkCostManager& operator=(const FakeNetworkCostManager&) = delete; + + private: + // The error state for this `FakeNetworkCostManager` to simulate. Cannot be + // changed. + const NetworkCostManagerStatus error_status_; + + // Synchronizes access to all members below. + base::Lock member_lock_; + + NetworkChangeNotifier::ConnectionCost connection_cost_ + GUARDED_BY(member_lock_); + + DWORD next_event_sink_cookie_ GUARDED_BY(member_lock_) = 0; + + struct EventSinkRegistration { + ComPtr event_sink_; + scoped_refptr event_sink_task_runner_; + }; + std::map event_sinks_ + GUARDED_BY(member_lock_); +}; + +FakeNetworkCostManagerEnvironment::FakeNetworkCostManagerEnvironment() { + // Set up `NetworkCostChangeNotifierWin` to use the fake OS APIs. + NetworkCostChangeNotifierWin::OverrideCoCreateInstanceForTesting( + base::BindRepeating( + &FakeNetworkCostManagerEnvironment::FakeCoCreateInstance, + base::Unretained(this))); +} + +FakeNetworkCostManagerEnvironment::~FakeNetworkCostManagerEnvironment() { + // Restore `NetworkCostChangeNotifierWin` to use the real OS APIs. + NetworkCostChangeNotifierWin::OverrideCoCreateInstanceForTesting( + base::BindRepeating(&CoCreateInstance)); +} + +HRESULT FakeNetworkCostManagerEnvironment::FakeCoCreateInstance( + REFCLSID class_id, + LPUNKNOWN outer_aggregate, + DWORD context_flags, + REFIID interface_id, + LPVOID* result) { + NetworkChangeNotifier::ConnectionCost connection_cost_for_new_instance; + NetworkCostManagerStatus error_status_for_new_instance; + { + base::AutoLock auto_lock(member_lock_); + connection_cost_for_new_instance = connection_cost_; + error_status_for_new_instance = error_status_; + } + + if (error_status_for_new_instance == + NetworkCostManagerStatus::kErrorCoCreateInstanceFailed) { + return E_ACCESSDENIED; + } + + if (class_id != CLSID_NetworkListManager) { + return E_NOINTERFACE; + } + + if (interface_id != IID_INetworkCostManager) { + return E_NOINTERFACE; + } + + ComPtr instance = + Microsoft::WRL::Make( + connection_cost_for_new_instance, error_status_for_new_instance); + { + base::AutoLock auto_lock(member_lock_); + fake_network_cost_managers_.push_back(instance); + } + *result = instance.Detach(); + return S_OK; +} + +void FakeNetworkCostManagerEnvironment::SetCost( + NetworkChangeNotifier::ConnectionCost value) { + // Update the cost for each `INetworkCostManager` instance in + // `fake_network_cost_managers_`. + std::vector> + fake_network_cost_managers_for_change_event; + { + base::AutoLock auto_lock(member_lock_); + connection_cost_ = value; + fake_network_cost_managers_for_change_event = fake_network_cost_managers_; + } + + for (const auto& network_cost_manager : + fake_network_cost_managers_for_change_event) { + network_cost_manager->PostCostChangedEvents(/*connection_cost=*/value); + } +} + +void FakeNetworkCostManagerEnvironment::SimulateError( + NetworkCostManagerStatus error_status) { + base::AutoLock auto_lock(member_lock_); + error_status_ = error_status; +} + +} // namespace net diff --git a/naiveproxy/src/net/test/win/fake_network_cost_manager.h b/naiveproxy/src/net/test/win/fake_network_cost_manager.h new file mode 100644 index 0000000000..91a9a6cc7c --- /dev/null +++ b/naiveproxy/src/net/test/win/fake_network_cost_manager.h @@ -0,0 +1,85 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_TEST_WIN_FAKE_NETWORK_COST_MANAGER_H_ +#define NET_TEST_WIN_FAKE_NETWORK_COST_MANAGER_H_ + +#include + +#include + +#include + +#include "base/synchronization/lock.h" +#include "base/thread_annotations.h" +#include "net/base/network_change_notifier.h" + +namespace net { +class FakeNetworkCostManager; + +// Each value represents a different Windows OS API that can fail when +// monitoring the cost of network connections. Use with +// `FakeNetworkCostManagerEnvironment::SimulateError()` to simulate Windows OS +// API failures that return error `HRESULT` codes. +enum class NetworkCostManagerStatus { + kOk, + kErrorCoCreateInstanceFailed, + kErrorQueryInterfaceFailed, + kErrorFindConnectionPointFailed, + kErrorAdviseFailed, + kErrorGetCostFailed, +}; + +// Provides a fake implementation of the `INetworkCostManager` Windows OS API +// for `NetworkCostChangeNotifierWin`. Must be constructed before any +// `NetworkCostChangeNotifierWin` instances exist. Sets up the fake OS API in +// the constructor and restores the real OS API in the destructor. Tests should +// use this class to simulate different network costs, cost changed events and +// errors without depending on the actual OS APIs or current network +// environment. +class FakeNetworkCostManagerEnvironment { + public: + FakeNetworkCostManagerEnvironment(); + ~FakeNetworkCostManagerEnvironment(); + + void SetCost(NetworkChangeNotifier::ConnectionCost value); + void SimulateError(NetworkCostManagerStatus error_status); + + FakeNetworkCostManagerEnvironment(const FakeNetworkCostManagerEnvironment&) = + delete; + FakeNetworkCostManagerEnvironment& operator=( + const FakeNetworkCostManagerEnvironment&) = delete; + + private: + // Creates a fake implementation of `INetworkCostManager`. + HRESULT FakeCoCreateInstance(REFCLSID class_id, + LPUNKNOWN outer_aggregate, + DWORD context_flags, + REFIID interface_id, + LPVOID* result); + + // Members must be accessed while holding this lock to support the creation + // and use of `FakeNetworkCostManager` instances on any thread. + base::Lock member_lock_; + + // The connection cost to simulate. + NetworkChangeNotifier::ConnectionCost connection_cost_ + GUARDED_BY(member_lock_) = + NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_UNKNOWN; + + // When `FakeNetworkCostManagerEnvironment` creates a new + // `FakeNetworkCostManager`, the new `FakeNetworkCostManager` will simulate + // this error. + NetworkCostManagerStatus error_status_ GUARDED_BY(member_lock_) = + NetworkCostManagerStatus::kOk; + + // Holds the fake implementations of `INetworkCostManager` constructed through + // `FakeCoCreateInstance()`. + std::vector> + fake_network_cost_managers_ GUARDED_BY(member_lock_); +}; + +} // namespace net + +#endif // NET_TEST_WIN_FAKE_NETWORK_COST_MANAGER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/build/source_list.bzl b/naiveproxy/src/net/third_party/quiche/src/build/source_list.bzl index f8f6e7e67d..386d90776d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/build/source_list.bzl +++ b/naiveproxy/src/net/third_party/quiche/src/build/source_list.bzl @@ -47,6 +47,7 @@ quiche_core_hdrs = [ "common/quiche_data_writer.h", "common/quiche_endian.h", "common/quiche_feature_flags_list.h", + "common/quiche_intrusive_list.h", "common/quiche_ip_address.h", "common/quiche_ip_address_family.h", "common/quiche_linked_hash_map.h", @@ -75,8 +76,22 @@ quiche_core_hdrs = [ "http2/adapter/oghttp2_session.h", "http2/adapter/oghttp2_util.h", "http2/adapter/window_manager.h", + "http2/core/array_output_buffer.h", + "http2/core/header_byte_listener_interface.h", + "http2/core/http2_frame_decoder_adapter.h", + "http2/core/http2_header_block_hpack_listener.h", "http2/core/http2_trace_logging.h", + "http2/core/no_op_headers_handler.h", "http2/core/priority_write_scheduler.h", + "http2/core/recording_headers_handler.h", + "http2/core/spdy_alt_svc_wire_format.h", + "http2/core/spdy_bitmasks.h", + "http2/core/spdy_frame_builder.h", + "http2/core/spdy_framer.h", + "http2/core/spdy_headers_handler_interface.h", + "http2/core/spdy_no_op_visitor.h", + "http2/core/spdy_protocol.h", + "http2/core/zero_copy_output_buffer.h", "http2/decoder/decode_buffer.h", "http2/decoder/decode_http2_structures.h", "http2/decoder/decode_status.h", @@ -111,6 +126,12 @@ quiche_core_hdrs = [ "http2/hpack/decoder/hpack_string_decoder_listener.h", "http2/hpack/decoder/hpack_whole_entry_buffer.h", "http2/hpack/decoder/hpack_whole_entry_listener.h", + "http2/hpack/hpack_constants.h", + "http2/hpack/hpack_encoder.h", + "http2/hpack/hpack_entry.h", + "http2/hpack/hpack_header_table.h", + "http2/hpack/hpack_output_stream.h", + "http2/hpack/hpack_static_table.h", "http2/hpack/http2_hpack_constants.h", "http2/hpack/huffman/hpack_huffman_decoder.h", "http2/hpack/huffman/hpack_huffman_encoder.h", @@ -302,7 +323,6 @@ quiche_core_hdrs = [ "quic/core/quic_default_connection_helper.h", "quic/core/quic_dispatcher.h", "quic/core/quic_error_codes.h", - "quic/core/quic_flags_list.h", "quic/core/quic_flow_controller.h", "quic/core/quic_framer.h", "quic/core/quic_generic_session.h", @@ -374,28 +394,16 @@ quiche_core_hdrs = [ "quic/platform/api/quic_stack_trace.h", "quic/platform/api/quic_testvalue.h", "quic/platform/api/quic_thread.h", - "spdy/core/array_output_buffer.h", - "spdy/core/header_byte_listener_interface.h", - "spdy/core/hpack/hpack_constants.h", "spdy/core/hpack/hpack_decoder_adapter.h", "spdy/core/hpack/hpack_encoder.h", - "spdy/core/hpack/hpack_entry.h", - "spdy/core/hpack/hpack_header_table.h", - "spdy/core/hpack/hpack_output_stream.h", - "spdy/core/hpack/hpack_static_table.h", "spdy/core/http2_frame_decoder_adapter.h", "spdy/core/http2_header_block.h", - "spdy/core/http2_header_block_hpack_listener.h", - "spdy/core/no_op_headers_handler.h", - "spdy/core/recording_headers_handler.h", "spdy/core/spdy_alt_svc_wire_format.h", "spdy/core/spdy_bitmasks.h", "spdy/core/spdy_frame_builder.h", "spdy/core/spdy_framer.h", "spdy/core/spdy_headers_handler_interface.h", - "spdy/core/spdy_no_op_visitor.h", "spdy/core/spdy_protocol.h", - "spdy/core/zero_copy_output_buffer.h", "web_transport/complete_buffer_visitor.h", "web_transport/encapsulated/encapsulated_web_transport.h", "web_transport/web_transport.h", @@ -432,7 +440,15 @@ quiche_core_srcs = [ "http2/adapter/oghttp2_session.cc", "http2/adapter/oghttp2_util.cc", "http2/adapter/window_manager.cc", + "http2/core/array_output_buffer.cc", + "http2/core/http2_frame_decoder_adapter.cc", "http2/core/http2_trace_logging.cc", + "http2/core/recording_headers_handler.cc", + "http2/core/spdy_alt_svc_wire_format.cc", + "http2/core/spdy_frame_builder.cc", + "http2/core/spdy_framer.cc", + "http2/core/spdy_no_op_visitor.cc", + "http2/core/spdy_protocol.cc", "http2/decoder/decode_buffer.cc", "http2/decoder/decode_http2_structures.cc", "http2/decoder/decode_status.cc", @@ -467,6 +483,12 @@ quiche_core_srcs = [ "http2/hpack/decoder/hpack_string_decoder_listener.cc", "http2/hpack/decoder/hpack_whole_entry_buffer.cc", "http2/hpack/decoder/hpack_whole_entry_listener.cc", + "http2/hpack/hpack_constants.cc", + "http2/hpack/hpack_encoder.cc", + "http2/hpack/hpack_entry.cc", + "http2/hpack/hpack_header_table.cc", + "http2/hpack/hpack_output_stream.cc", + "http2/hpack/hpack_static_table.cc", "http2/hpack/http2_hpack_constants.cc", "http2/hpack/huffman/hpack_huffman_decoder.cc", "http2/hpack/huffman/hpack_huffman_encoder.cc", @@ -677,21 +699,7 @@ quiche_core_srcs = [ "quic/core/web_transport_stats.cc", "quic/core/web_transport_write_blocked_list.cc", "quic/platform/api/quic_socket_address.cc", - "spdy/core/array_output_buffer.cc", - "spdy/core/hpack/hpack_constants.cc", "spdy/core/hpack/hpack_decoder_adapter.cc", - "spdy/core/hpack/hpack_encoder.cc", - "spdy/core/hpack/hpack_entry.cc", - "spdy/core/hpack/hpack_header_table.cc", - "spdy/core/hpack/hpack_output_stream.cc", - "spdy/core/hpack/hpack_static_table.cc", - "spdy/core/http2_frame_decoder_adapter.cc", - "spdy/core/recording_headers_handler.cc", - "spdy/core/spdy_alt_svc_wire_format.cc", - "spdy/core/spdy_frame_builder.cc", - "spdy/core/spdy_framer.cc", - "spdy/core/spdy_no_op_visitor.cc", - "spdy/core/spdy_protocol.cc", "web_transport/complete_buffer_visitor.cc", "web_transport/encapsulated/encapsulated_web_transport.cc", "web_transport/web_transport_headers.cc", @@ -779,9 +787,11 @@ quiche_test_support_hdrs = [ "http2/test_tools/http2_structure_decoder_test_util.h", "http2/test_tools/http2_structures_test_util.h", "http2/test_tools/http2_trace_printer.h", + "http2/test_tools/mock_spdy_framer_visitor.h", "http2/test_tools/payload_decoder_base_test_util.h", "http2/test_tools/random_decoder_test_base.h", "http2/test_tools/random_util.h", + "http2/test_tools/spdy_test_utils.h", "http2/test_tools/verify_macros.h", "quic/platform/api/quic_expect_bug.h", "quic/platform/api/quic_test.h", @@ -860,9 +870,6 @@ quiche_test_support_hdrs = [ "quic/test_tools/test_ticket_crypter.h", "quic/test_tools/web_transport_resets_backend.h", "quic/test_tools/web_transport_test_tools.h", - "spdy/test_tools/mock_spdy_framer_visitor.h", - "spdy/test_tools/mock_spdy_headers_handler.h", - "spdy/test_tools/spdy_test_utils.h", "web_transport/test_tools/mock_web_transport.h", ] quiche_test_support_srcs = [ @@ -887,9 +894,11 @@ quiche_test_support_srcs = [ "http2/test_tools/http2_structure_decoder_test_util.cc", "http2/test_tools/http2_structures_test_util.cc", "http2/test_tools/http2_trace_printer.cc", + "http2/test_tools/mock_spdy_framer_visitor.cc", "http2/test_tools/payload_decoder_base_test_util.cc", "http2/test_tools/random_decoder_test_base.cc", "http2/test_tools/random_util.cc", + "http2/test_tools/spdy_test_utils.cc", "quic/test_tools/bad_packet_writer.cc", "quic/test_tools/crypto_test_utils.cc", "quic/test_tools/failing_proof_source.cc", @@ -955,9 +964,6 @@ quiche_test_support_srcs = [ "quic/test_tools/test_ip_packets.cc", "quic/test_tools/test_ticket_crypter.cc", "quic/test_tools/web_transport_resets_backend.cc", - "spdy/test_tools/mock_spdy_framer_visitor.cc", - "spdy/test_tools/mock_spdy_headers_handler.cc", - "spdy/test_tools/spdy_test_utils.cc", ] balsa_hdrs = [ "balsa/balsa_enums.h", @@ -1089,6 +1095,7 @@ quiche_tests_srcs = [ "common/quiche_data_reader_test.cc", "common/quiche_data_writer_test.cc", "common/quiche_endian_test.cc", + "common/quiche_intrusive_list_test.cc", "common/quiche_ip_address_test.cc", "common/quiche_linked_hash_map_test.cc", "common/quiche_mem_slice_storage_test.cc", @@ -1112,7 +1119,12 @@ quiche_tests_srcs = [ "http2/adapter/recording_http2_visitor_test.cc", "http2/adapter/test_utils_test.cc", "http2/adapter/window_manager_test.cc", + "http2/core/array_output_buffer_test.cc", "http2/core/priority_write_scheduler_test.cc", + "http2/core/spdy_alt_svc_wire_format_test.cc", + "http2/core/spdy_frame_builder_test.cc", + "http2/core/spdy_framer_test.cc", + "http2/core/spdy_protocol_test.cc", "http2/decoder/decode_buffer_test.cc", "http2/decoder/decode_http2_structures_test.cc", "http2/decoder/http2_frame_decoder_test.cc", @@ -1141,6 +1153,11 @@ quiche_tests_srcs = [ "http2/hpack/decoder/hpack_entry_type_decoder_test.cc", "http2/hpack/decoder/hpack_string_decoder_test.cc", "http2/hpack/decoder/hpack_whole_entry_buffer_test.cc", + "http2/hpack/hpack_encoder_test.cc", + "http2/hpack/hpack_entry_test.cc", + "http2/hpack/hpack_header_table_test.cc", + "http2/hpack/hpack_output_stream_test.cc", + "http2/hpack/hpack_static_table_test.cc", "http2/hpack/http2_hpack_constants_test.cc", "http2/hpack/huffman/hpack_huffman_decoder_test.cc", "http2/hpack/huffman/hpack_huffman_encoder_test.cc", @@ -1319,18 +1336,8 @@ quiche_tests_srcs = [ "quic/tools/quic_memory_cache_backend_test.cc", "quic/tools/quic_tcp_like_trace_converter_test.cc", "quic/tools/simple_ticket_crypter_test.cc", - "spdy/core/array_output_buffer_test.cc", "spdy/core/hpack/hpack_decoder_adapter_test.cc", - "spdy/core/hpack/hpack_encoder_test.cc", - "spdy/core/hpack/hpack_entry_test.cc", - "spdy/core/hpack/hpack_header_table_test.cc", - "spdy/core/hpack/hpack_output_stream_test.cc", "spdy/core/hpack/hpack_round_trip_test.cc", - "spdy/core/hpack/hpack_static_table_test.cc", - "spdy/core/spdy_alt_svc_wire_format_test.cc", - "spdy/core/spdy_frame_builder_test.cc", - "spdy/core/spdy_framer_test.cc", - "spdy/core/spdy_protocol_test.cc", "web_transport/encapsulated/encapsulated_web_transport_test.cc", "web_transport/web_transport_headers_test.cc", "web_transport/web_transport_priority_scheduler_test.cc", @@ -1501,37 +1508,49 @@ load_balancer_srcs = [ "quic/load_balancer/load_balancer_server_id_test.cc", ] moqt_hdrs = [ + "quic/moqt/moqt_cached_object.h", "quic/moqt/moqt_framer.h", + "quic/moqt/moqt_known_track_publisher.h", "quic/moqt/moqt_messages.h", "quic/moqt/moqt_outgoing_queue.h", "quic/moqt/moqt_parser.h", + "quic/moqt/moqt_priority.h", + "quic/moqt/moqt_publisher.h", "quic/moqt/moqt_session.h", "quic/moqt/moqt_subscribe_windows.h", "quic/moqt/moqt_track.h", + "quic/moqt/test_tools/moqt_simulator_harness.h", "quic/moqt/test_tools/moqt_test_message.h", "quic/moqt/tools/moqt_client.h", "quic/moqt/tools/moqt_mock_visitor.h", "quic/moqt/tools/moqt_server.h", ] moqt_srcs = [ + "quic/moqt/moqt_cached_object.cc", "quic/moqt/moqt_framer.cc", "quic/moqt/moqt_framer_test.cc", "quic/moqt/moqt_integration_test.cc", + "quic/moqt/moqt_known_track_publisher.cc", "quic/moqt/moqt_messages.cc", "quic/moqt/moqt_outgoing_queue.cc", "quic/moqt/moqt_outgoing_queue_test.cc", "quic/moqt/moqt_parser.cc", "quic/moqt/moqt_parser_test.cc", + "quic/moqt/moqt_priority.cc", + "quic/moqt/moqt_priority_test.cc", "quic/moqt/moqt_session.cc", "quic/moqt/moqt_session_test.cc", "quic/moqt/moqt_subscribe_windows.cc", "quic/moqt/moqt_subscribe_windows_test.cc", + "quic/moqt/moqt_track.cc", "quic/moqt/moqt_track_test.cc", + "quic/moqt/test_tools/moqt_simulator_harness.cc", "quic/moqt/tools/chat_client_bin.cc", "quic/moqt/tools/moqt_client.cc", "quic/moqt/tools/moqt_end_to_end_test.cc", "quic/moqt/tools/moqt_ingestion_server_bin.cc", "quic/moqt/tools/moqt_server.cc", + "quic/moqt/tools/moqt_simulator_bin.cc", ] binary_http_hdrs = [ "binary_http/binary_http_message.h", diff --git a/naiveproxy/src/net/third_party/quiche/src/build/source_list.gni b/naiveproxy/src/net/third_party/quiche/src/build/source_list.gni index f203a7a9d5..20042695a7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/build/source_list.gni +++ b/naiveproxy/src/net/third_party/quiche/src/build/source_list.gni @@ -47,6 +47,7 @@ quiche_core_hdrs = [ "src/quiche/common/quiche_data_writer.h", "src/quiche/common/quiche_endian.h", "src/quiche/common/quiche_feature_flags_list.h", + "src/quiche/common/quiche_intrusive_list.h", "src/quiche/common/quiche_ip_address.h", "src/quiche/common/quiche_ip_address_family.h", "src/quiche/common/quiche_linked_hash_map.h", @@ -75,8 +76,22 @@ quiche_core_hdrs = [ "src/quiche/http2/adapter/oghttp2_session.h", "src/quiche/http2/adapter/oghttp2_util.h", "src/quiche/http2/adapter/window_manager.h", + "src/quiche/http2/core/array_output_buffer.h", + "src/quiche/http2/core/header_byte_listener_interface.h", + "src/quiche/http2/core/http2_frame_decoder_adapter.h", + "src/quiche/http2/core/http2_header_block_hpack_listener.h", "src/quiche/http2/core/http2_trace_logging.h", + "src/quiche/http2/core/no_op_headers_handler.h", "src/quiche/http2/core/priority_write_scheduler.h", + "src/quiche/http2/core/recording_headers_handler.h", + "src/quiche/http2/core/spdy_alt_svc_wire_format.h", + "src/quiche/http2/core/spdy_bitmasks.h", + "src/quiche/http2/core/spdy_frame_builder.h", + "src/quiche/http2/core/spdy_framer.h", + "src/quiche/http2/core/spdy_headers_handler_interface.h", + "src/quiche/http2/core/spdy_no_op_visitor.h", + "src/quiche/http2/core/spdy_protocol.h", + "src/quiche/http2/core/zero_copy_output_buffer.h", "src/quiche/http2/decoder/decode_buffer.h", "src/quiche/http2/decoder/decode_http2_structures.h", "src/quiche/http2/decoder/decode_status.h", @@ -111,6 +126,12 @@ quiche_core_hdrs = [ "src/quiche/http2/hpack/decoder/hpack_string_decoder_listener.h", "src/quiche/http2/hpack/decoder/hpack_whole_entry_buffer.h", "src/quiche/http2/hpack/decoder/hpack_whole_entry_listener.h", + "src/quiche/http2/hpack/hpack_constants.h", + "src/quiche/http2/hpack/hpack_encoder.h", + "src/quiche/http2/hpack/hpack_entry.h", + "src/quiche/http2/hpack/hpack_header_table.h", + "src/quiche/http2/hpack/hpack_output_stream.h", + "src/quiche/http2/hpack/hpack_static_table.h", "src/quiche/http2/hpack/http2_hpack_constants.h", "src/quiche/http2/hpack/huffman/hpack_huffman_decoder.h", "src/quiche/http2/hpack/huffman/hpack_huffman_encoder.h", @@ -302,7 +323,6 @@ quiche_core_hdrs = [ "src/quiche/quic/core/quic_default_connection_helper.h", "src/quiche/quic/core/quic_dispatcher.h", "src/quiche/quic/core/quic_error_codes.h", - "src/quiche/quic/core/quic_flags_list.h", "src/quiche/quic/core/quic_flow_controller.h", "src/quiche/quic/core/quic_framer.h", "src/quiche/quic/core/quic_generic_session.h", @@ -374,28 +394,16 @@ quiche_core_hdrs = [ "src/quiche/quic/platform/api/quic_stack_trace.h", "src/quiche/quic/platform/api/quic_testvalue.h", "src/quiche/quic/platform/api/quic_thread.h", - "src/quiche/spdy/core/array_output_buffer.h", - "src/quiche/spdy/core/header_byte_listener_interface.h", - "src/quiche/spdy/core/hpack/hpack_constants.h", "src/quiche/spdy/core/hpack/hpack_decoder_adapter.h", "src/quiche/spdy/core/hpack/hpack_encoder.h", - "src/quiche/spdy/core/hpack/hpack_entry.h", - "src/quiche/spdy/core/hpack/hpack_header_table.h", - "src/quiche/spdy/core/hpack/hpack_output_stream.h", - "src/quiche/spdy/core/hpack/hpack_static_table.h", "src/quiche/spdy/core/http2_frame_decoder_adapter.h", "src/quiche/spdy/core/http2_header_block.h", - "src/quiche/spdy/core/http2_header_block_hpack_listener.h", - "src/quiche/spdy/core/no_op_headers_handler.h", - "src/quiche/spdy/core/recording_headers_handler.h", "src/quiche/spdy/core/spdy_alt_svc_wire_format.h", "src/quiche/spdy/core/spdy_bitmasks.h", "src/quiche/spdy/core/spdy_frame_builder.h", "src/quiche/spdy/core/spdy_framer.h", "src/quiche/spdy/core/spdy_headers_handler_interface.h", - "src/quiche/spdy/core/spdy_no_op_visitor.h", "src/quiche/spdy/core/spdy_protocol.h", - "src/quiche/spdy/core/zero_copy_output_buffer.h", "src/quiche/web_transport/complete_buffer_visitor.h", "src/quiche/web_transport/encapsulated/encapsulated_web_transport.h", "src/quiche/web_transport/web_transport.h", @@ -432,7 +440,15 @@ quiche_core_srcs = [ "src/quiche/http2/adapter/oghttp2_session.cc", "src/quiche/http2/adapter/oghttp2_util.cc", "src/quiche/http2/adapter/window_manager.cc", + "src/quiche/http2/core/array_output_buffer.cc", + "src/quiche/http2/core/http2_frame_decoder_adapter.cc", "src/quiche/http2/core/http2_trace_logging.cc", + "src/quiche/http2/core/recording_headers_handler.cc", + "src/quiche/http2/core/spdy_alt_svc_wire_format.cc", + "src/quiche/http2/core/spdy_frame_builder.cc", + "src/quiche/http2/core/spdy_framer.cc", + "src/quiche/http2/core/spdy_no_op_visitor.cc", + "src/quiche/http2/core/spdy_protocol.cc", "src/quiche/http2/decoder/decode_buffer.cc", "src/quiche/http2/decoder/decode_http2_structures.cc", "src/quiche/http2/decoder/decode_status.cc", @@ -467,6 +483,12 @@ quiche_core_srcs = [ "src/quiche/http2/hpack/decoder/hpack_string_decoder_listener.cc", "src/quiche/http2/hpack/decoder/hpack_whole_entry_buffer.cc", "src/quiche/http2/hpack/decoder/hpack_whole_entry_listener.cc", + "src/quiche/http2/hpack/hpack_constants.cc", + "src/quiche/http2/hpack/hpack_encoder.cc", + "src/quiche/http2/hpack/hpack_entry.cc", + "src/quiche/http2/hpack/hpack_header_table.cc", + "src/quiche/http2/hpack/hpack_output_stream.cc", + "src/quiche/http2/hpack/hpack_static_table.cc", "src/quiche/http2/hpack/http2_hpack_constants.cc", "src/quiche/http2/hpack/huffman/hpack_huffman_decoder.cc", "src/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc", @@ -677,21 +699,7 @@ quiche_core_srcs = [ "src/quiche/quic/core/web_transport_stats.cc", "src/quiche/quic/core/web_transport_write_blocked_list.cc", "src/quiche/quic/platform/api/quic_socket_address.cc", - "src/quiche/spdy/core/array_output_buffer.cc", - "src/quiche/spdy/core/hpack/hpack_constants.cc", "src/quiche/spdy/core/hpack/hpack_decoder_adapter.cc", - "src/quiche/spdy/core/hpack/hpack_encoder.cc", - "src/quiche/spdy/core/hpack/hpack_entry.cc", - "src/quiche/spdy/core/hpack/hpack_header_table.cc", - "src/quiche/spdy/core/hpack/hpack_output_stream.cc", - "src/quiche/spdy/core/hpack/hpack_static_table.cc", - "src/quiche/spdy/core/http2_frame_decoder_adapter.cc", - "src/quiche/spdy/core/recording_headers_handler.cc", - "src/quiche/spdy/core/spdy_alt_svc_wire_format.cc", - "src/quiche/spdy/core/spdy_frame_builder.cc", - "src/quiche/spdy/core/spdy_framer.cc", - "src/quiche/spdy/core/spdy_no_op_visitor.cc", - "src/quiche/spdy/core/spdy_protocol.cc", "src/quiche/web_transport/complete_buffer_visitor.cc", "src/quiche/web_transport/encapsulated/encapsulated_web_transport.cc", "src/quiche/web_transport/web_transport_headers.cc", @@ -779,9 +787,11 @@ quiche_test_support_hdrs = [ "src/quiche/http2/test_tools/http2_structure_decoder_test_util.h", "src/quiche/http2/test_tools/http2_structures_test_util.h", "src/quiche/http2/test_tools/http2_trace_printer.h", + "src/quiche/http2/test_tools/mock_spdy_framer_visitor.h", "src/quiche/http2/test_tools/payload_decoder_base_test_util.h", "src/quiche/http2/test_tools/random_decoder_test_base.h", "src/quiche/http2/test_tools/random_util.h", + "src/quiche/http2/test_tools/spdy_test_utils.h", "src/quiche/http2/test_tools/verify_macros.h", "src/quiche/quic/platform/api/quic_expect_bug.h", "src/quiche/quic/platform/api/quic_test.h", @@ -860,9 +870,6 @@ quiche_test_support_hdrs = [ "src/quiche/quic/test_tools/test_ticket_crypter.h", "src/quiche/quic/test_tools/web_transport_resets_backend.h", "src/quiche/quic/test_tools/web_transport_test_tools.h", - "src/quiche/spdy/test_tools/mock_spdy_framer_visitor.h", - "src/quiche/spdy/test_tools/mock_spdy_headers_handler.h", - "src/quiche/spdy/test_tools/spdy_test_utils.h", "src/quiche/web_transport/test_tools/mock_web_transport.h", ] quiche_test_support_srcs = [ @@ -887,9 +894,11 @@ quiche_test_support_srcs = [ "src/quiche/http2/test_tools/http2_structure_decoder_test_util.cc", "src/quiche/http2/test_tools/http2_structures_test_util.cc", "src/quiche/http2/test_tools/http2_trace_printer.cc", + "src/quiche/http2/test_tools/mock_spdy_framer_visitor.cc", "src/quiche/http2/test_tools/payload_decoder_base_test_util.cc", "src/quiche/http2/test_tools/random_decoder_test_base.cc", "src/quiche/http2/test_tools/random_util.cc", + "src/quiche/http2/test_tools/spdy_test_utils.cc", "src/quiche/quic/test_tools/bad_packet_writer.cc", "src/quiche/quic/test_tools/crypto_test_utils.cc", "src/quiche/quic/test_tools/failing_proof_source.cc", @@ -955,9 +964,6 @@ quiche_test_support_srcs = [ "src/quiche/quic/test_tools/test_ip_packets.cc", "src/quiche/quic/test_tools/test_ticket_crypter.cc", "src/quiche/quic/test_tools/web_transport_resets_backend.cc", - "src/quiche/spdy/test_tools/mock_spdy_framer_visitor.cc", - "src/quiche/spdy/test_tools/mock_spdy_headers_handler.cc", - "src/quiche/spdy/test_tools/spdy_test_utils.cc", ] balsa_hdrs = [ "src/quiche/balsa/balsa_enums.h", @@ -1090,6 +1096,7 @@ quiche_tests_srcs = [ "src/quiche/common/quiche_data_reader_test.cc", "src/quiche/common/quiche_data_writer_test.cc", "src/quiche/common/quiche_endian_test.cc", + "src/quiche/common/quiche_intrusive_list_test.cc", "src/quiche/common/quiche_ip_address_test.cc", "src/quiche/common/quiche_linked_hash_map_test.cc", "src/quiche/common/quiche_mem_slice_storage_test.cc", @@ -1113,7 +1120,12 @@ quiche_tests_srcs = [ "src/quiche/http2/adapter/recording_http2_visitor_test.cc", "src/quiche/http2/adapter/test_utils_test.cc", "src/quiche/http2/adapter/window_manager_test.cc", + "src/quiche/http2/core/array_output_buffer_test.cc", "src/quiche/http2/core/priority_write_scheduler_test.cc", + "src/quiche/http2/core/spdy_alt_svc_wire_format_test.cc", + "src/quiche/http2/core/spdy_frame_builder_test.cc", + "src/quiche/http2/core/spdy_framer_test.cc", + "src/quiche/http2/core/spdy_protocol_test.cc", "src/quiche/http2/decoder/decode_buffer_test.cc", "src/quiche/http2/decoder/decode_http2_structures_test.cc", "src/quiche/http2/decoder/http2_frame_decoder_test.cc", @@ -1142,6 +1154,11 @@ quiche_tests_srcs = [ "src/quiche/http2/hpack/decoder/hpack_entry_type_decoder_test.cc", "src/quiche/http2/hpack/decoder/hpack_string_decoder_test.cc", "src/quiche/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc", + "src/quiche/http2/hpack/hpack_encoder_test.cc", + "src/quiche/http2/hpack/hpack_entry_test.cc", + "src/quiche/http2/hpack/hpack_header_table_test.cc", + "src/quiche/http2/hpack/hpack_output_stream_test.cc", + "src/quiche/http2/hpack/hpack_static_table_test.cc", "src/quiche/http2/hpack/http2_hpack_constants_test.cc", "src/quiche/http2/hpack/huffman/hpack_huffman_decoder_test.cc", "src/quiche/http2/hpack/huffman/hpack_huffman_encoder_test.cc", @@ -1320,18 +1337,8 @@ quiche_tests_srcs = [ "src/quiche/quic/tools/quic_memory_cache_backend_test.cc", "src/quiche/quic/tools/quic_tcp_like_trace_converter_test.cc", "src/quiche/quic/tools/simple_ticket_crypter_test.cc", - "src/quiche/spdy/core/array_output_buffer_test.cc", "src/quiche/spdy/core/hpack/hpack_decoder_adapter_test.cc", - "src/quiche/spdy/core/hpack/hpack_encoder_test.cc", - "src/quiche/spdy/core/hpack/hpack_entry_test.cc", - "src/quiche/spdy/core/hpack/hpack_header_table_test.cc", - "src/quiche/spdy/core/hpack/hpack_output_stream_test.cc", "src/quiche/spdy/core/hpack/hpack_round_trip_test.cc", - "src/quiche/spdy/core/hpack/hpack_static_table_test.cc", - "src/quiche/spdy/core/spdy_alt_svc_wire_format_test.cc", - "src/quiche/spdy/core/spdy_frame_builder_test.cc", - "src/quiche/spdy/core/spdy_framer_test.cc", - "src/quiche/spdy/core/spdy_protocol_test.cc", "src/quiche/web_transport/encapsulated/encapsulated_web_transport_test.cc", "src/quiche/web_transport/web_transport_headers_test.cc", "src/quiche/web_transport/web_transport_priority_scheduler_test.cc", @@ -1505,37 +1512,49 @@ load_balancer_srcs = [ "src/quiche/quic/load_balancer/load_balancer_server_id_test.cc", ] moqt_hdrs = [ + "src/quiche/quic/moqt/moqt_cached_object.h", "src/quiche/quic/moqt/moqt_framer.h", + "src/quiche/quic/moqt/moqt_known_track_publisher.h", "src/quiche/quic/moqt/moqt_messages.h", "src/quiche/quic/moqt/moqt_outgoing_queue.h", "src/quiche/quic/moqt/moqt_parser.h", + "src/quiche/quic/moqt/moqt_priority.h", + "src/quiche/quic/moqt/moqt_publisher.h", "src/quiche/quic/moqt/moqt_session.h", "src/quiche/quic/moqt/moqt_subscribe_windows.h", "src/quiche/quic/moqt/moqt_track.h", + "src/quiche/quic/moqt/test_tools/moqt_simulator_harness.h", "src/quiche/quic/moqt/test_tools/moqt_test_message.h", "src/quiche/quic/moqt/tools/moqt_client.h", "src/quiche/quic/moqt/tools/moqt_mock_visitor.h", "src/quiche/quic/moqt/tools/moqt_server.h", ] moqt_srcs = [ + "src/quiche/quic/moqt/moqt_cached_object.cc", "src/quiche/quic/moqt/moqt_framer.cc", "src/quiche/quic/moqt/moqt_framer_test.cc", "src/quiche/quic/moqt/moqt_integration_test.cc", + "src/quiche/quic/moqt/moqt_known_track_publisher.cc", "src/quiche/quic/moqt/moqt_messages.cc", "src/quiche/quic/moqt/moqt_outgoing_queue.cc", "src/quiche/quic/moqt/moqt_outgoing_queue_test.cc", "src/quiche/quic/moqt/moqt_parser.cc", "src/quiche/quic/moqt/moqt_parser_test.cc", + "src/quiche/quic/moqt/moqt_priority.cc", + "src/quiche/quic/moqt/moqt_priority_test.cc", "src/quiche/quic/moqt/moqt_session.cc", "src/quiche/quic/moqt/moqt_session_test.cc", "src/quiche/quic/moqt/moqt_subscribe_windows.cc", "src/quiche/quic/moqt/moqt_subscribe_windows_test.cc", + "src/quiche/quic/moqt/moqt_track.cc", "src/quiche/quic/moqt/moqt_track_test.cc", + "src/quiche/quic/moqt/test_tools/moqt_simulator_harness.cc", "src/quiche/quic/moqt/tools/chat_client_bin.cc", "src/quiche/quic/moqt/tools/moqt_client.cc", "src/quiche/quic/moqt/tools/moqt_end_to_end_test.cc", "src/quiche/quic/moqt/tools/moqt_ingestion_server_bin.cc", "src/quiche/quic/moqt/tools/moqt_server.cc", + "src/quiche/quic/moqt/tools/moqt_simulator_bin.cc", ] binary_http_hdrs = [ "src/quiche/binary_http/binary_http_message.h", diff --git a/naiveproxy/src/net/third_party/quiche/src/build/source_list.json b/naiveproxy/src/net/third_party/quiche/src/build/source_list.json index c5edd4dd6e..7e6cd21a66 100644 --- a/naiveproxy/src/net/third_party/quiche/src/build/source_list.json +++ b/naiveproxy/src/net/third_party/quiche/src/build/source_list.json @@ -46,6 +46,7 @@ "quiche/common/quiche_data_writer.h", "quiche/common/quiche_endian.h", "quiche/common/quiche_feature_flags_list.h", + "quiche/common/quiche_intrusive_list.h", "quiche/common/quiche_ip_address.h", "quiche/common/quiche_ip_address_family.h", "quiche/common/quiche_linked_hash_map.h", @@ -74,8 +75,22 @@ "quiche/http2/adapter/oghttp2_session.h", "quiche/http2/adapter/oghttp2_util.h", "quiche/http2/adapter/window_manager.h", + "quiche/http2/core/array_output_buffer.h", + "quiche/http2/core/header_byte_listener_interface.h", + "quiche/http2/core/http2_frame_decoder_adapter.h", + "quiche/http2/core/http2_header_block_hpack_listener.h", "quiche/http2/core/http2_trace_logging.h", + "quiche/http2/core/no_op_headers_handler.h", "quiche/http2/core/priority_write_scheduler.h", + "quiche/http2/core/recording_headers_handler.h", + "quiche/http2/core/spdy_alt_svc_wire_format.h", + "quiche/http2/core/spdy_bitmasks.h", + "quiche/http2/core/spdy_frame_builder.h", + "quiche/http2/core/spdy_framer.h", + "quiche/http2/core/spdy_headers_handler_interface.h", + "quiche/http2/core/spdy_no_op_visitor.h", + "quiche/http2/core/spdy_protocol.h", + "quiche/http2/core/zero_copy_output_buffer.h", "quiche/http2/decoder/decode_buffer.h", "quiche/http2/decoder/decode_http2_structures.h", "quiche/http2/decoder/decode_status.h", @@ -110,6 +125,12 @@ "quiche/http2/hpack/decoder/hpack_string_decoder_listener.h", "quiche/http2/hpack/decoder/hpack_whole_entry_buffer.h", "quiche/http2/hpack/decoder/hpack_whole_entry_listener.h", + "quiche/http2/hpack/hpack_constants.h", + "quiche/http2/hpack/hpack_encoder.h", + "quiche/http2/hpack/hpack_entry.h", + "quiche/http2/hpack/hpack_header_table.h", + "quiche/http2/hpack/hpack_output_stream.h", + "quiche/http2/hpack/hpack_static_table.h", "quiche/http2/hpack/http2_hpack_constants.h", "quiche/http2/hpack/huffman/hpack_huffman_decoder.h", "quiche/http2/hpack/huffman/hpack_huffman_encoder.h", @@ -301,7 +322,6 @@ "quiche/quic/core/quic_default_connection_helper.h", "quiche/quic/core/quic_dispatcher.h", "quiche/quic/core/quic_error_codes.h", - "quiche/quic/core/quic_flags_list.h", "quiche/quic/core/quic_flow_controller.h", "quiche/quic/core/quic_framer.h", "quiche/quic/core/quic_generic_session.h", @@ -373,28 +393,16 @@ "quiche/quic/platform/api/quic_stack_trace.h", "quiche/quic/platform/api/quic_testvalue.h", "quiche/quic/platform/api/quic_thread.h", - "quiche/spdy/core/array_output_buffer.h", - "quiche/spdy/core/header_byte_listener_interface.h", - "quiche/spdy/core/hpack/hpack_constants.h", "quiche/spdy/core/hpack/hpack_decoder_adapter.h", "quiche/spdy/core/hpack/hpack_encoder.h", - "quiche/spdy/core/hpack/hpack_entry.h", - "quiche/spdy/core/hpack/hpack_header_table.h", - "quiche/spdy/core/hpack/hpack_output_stream.h", - "quiche/spdy/core/hpack/hpack_static_table.h", "quiche/spdy/core/http2_frame_decoder_adapter.h", "quiche/spdy/core/http2_header_block.h", - "quiche/spdy/core/http2_header_block_hpack_listener.h", - "quiche/spdy/core/no_op_headers_handler.h", - "quiche/spdy/core/recording_headers_handler.h", "quiche/spdy/core/spdy_alt_svc_wire_format.h", "quiche/spdy/core/spdy_bitmasks.h", "quiche/spdy/core/spdy_frame_builder.h", "quiche/spdy/core/spdy_framer.h", "quiche/spdy/core/spdy_headers_handler_interface.h", - "quiche/spdy/core/spdy_no_op_visitor.h", "quiche/spdy/core/spdy_protocol.h", - "quiche/spdy/core/zero_copy_output_buffer.h", "quiche/web_transport/complete_buffer_visitor.h", "quiche/web_transport/encapsulated/encapsulated_web_transport.h", "quiche/web_transport/web_transport.h", @@ -431,7 +439,15 @@ "quiche/http2/adapter/oghttp2_session.cc", "quiche/http2/adapter/oghttp2_util.cc", "quiche/http2/adapter/window_manager.cc", + "quiche/http2/core/array_output_buffer.cc", + "quiche/http2/core/http2_frame_decoder_adapter.cc", "quiche/http2/core/http2_trace_logging.cc", + "quiche/http2/core/recording_headers_handler.cc", + "quiche/http2/core/spdy_alt_svc_wire_format.cc", + "quiche/http2/core/spdy_frame_builder.cc", + "quiche/http2/core/spdy_framer.cc", + "quiche/http2/core/spdy_no_op_visitor.cc", + "quiche/http2/core/spdy_protocol.cc", "quiche/http2/decoder/decode_buffer.cc", "quiche/http2/decoder/decode_http2_structures.cc", "quiche/http2/decoder/decode_status.cc", @@ -466,6 +482,12 @@ "quiche/http2/hpack/decoder/hpack_string_decoder_listener.cc", "quiche/http2/hpack/decoder/hpack_whole_entry_buffer.cc", "quiche/http2/hpack/decoder/hpack_whole_entry_listener.cc", + "quiche/http2/hpack/hpack_constants.cc", + "quiche/http2/hpack/hpack_encoder.cc", + "quiche/http2/hpack/hpack_entry.cc", + "quiche/http2/hpack/hpack_header_table.cc", + "quiche/http2/hpack/hpack_output_stream.cc", + "quiche/http2/hpack/hpack_static_table.cc", "quiche/http2/hpack/http2_hpack_constants.cc", "quiche/http2/hpack/huffman/hpack_huffman_decoder.cc", "quiche/http2/hpack/huffman/hpack_huffman_encoder.cc", @@ -676,21 +698,7 @@ "quiche/quic/core/web_transport_stats.cc", "quiche/quic/core/web_transport_write_blocked_list.cc", "quiche/quic/platform/api/quic_socket_address.cc", - "quiche/spdy/core/array_output_buffer.cc", - "quiche/spdy/core/hpack/hpack_constants.cc", "quiche/spdy/core/hpack/hpack_decoder_adapter.cc", - "quiche/spdy/core/hpack/hpack_encoder.cc", - "quiche/spdy/core/hpack/hpack_entry.cc", - "quiche/spdy/core/hpack/hpack_header_table.cc", - "quiche/spdy/core/hpack/hpack_output_stream.cc", - "quiche/spdy/core/hpack/hpack_static_table.cc", - "quiche/spdy/core/http2_frame_decoder_adapter.cc", - "quiche/spdy/core/recording_headers_handler.cc", - "quiche/spdy/core/spdy_alt_svc_wire_format.cc", - "quiche/spdy/core/spdy_frame_builder.cc", - "quiche/spdy/core/spdy_framer.cc", - "quiche/spdy/core/spdy_no_op_visitor.cc", - "quiche/spdy/core/spdy_protocol.cc", "quiche/web_transport/complete_buffer_visitor.cc", "quiche/web_transport/encapsulated/encapsulated_web_transport.cc", "quiche/web_transport/web_transport_headers.cc", @@ -778,9 +786,11 @@ "quiche/http2/test_tools/http2_structure_decoder_test_util.h", "quiche/http2/test_tools/http2_structures_test_util.h", "quiche/http2/test_tools/http2_trace_printer.h", + "quiche/http2/test_tools/mock_spdy_framer_visitor.h", "quiche/http2/test_tools/payload_decoder_base_test_util.h", "quiche/http2/test_tools/random_decoder_test_base.h", "quiche/http2/test_tools/random_util.h", + "quiche/http2/test_tools/spdy_test_utils.h", "quiche/http2/test_tools/verify_macros.h", "quiche/quic/platform/api/quic_expect_bug.h", "quiche/quic/platform/api/quic_test.h", @@ -859,9 +869,6 @@ "quiche/quic/test_tools/test_ticket_crypter.h", "quiche/quic/test_tools/web_transport_resets_backend.h", "quiche/quic/test_tools/web_transport_test_tools.h", - "quiche/spdy/test_tools/mock_spdy_framer_visitor.h", - "quiche/spdy/test_tools/mock_spdy_headers_handler.h", - "quiche/spdy/test_tools/spdy_test_utils.h", "quiche/web_transport/test_tools/mock_web_transport.h" ], "quiche_test_support_srcs": [ @@ -886,9 +893,11 @@ "quiche/http2/test_tools/http2_structure_decoder_test_util.cc", "quiche/http2/test_tools/http2_structures_test_util.cc", "quiche/http2/test_tools/http2_trace_printer.cc", + "quiche/http2/test_tools/mock_spdy_framer_visitor.cc", "quiche/http2/test_tools/payload_decoder_base_test_util.cc", "quiche/http2/test_tools/random_decoder_test_base.cc", "quiche/http2/test_tools/random_util.cc", + "quiche/http2/test_tools/spdy_test_utils.cc", "quiche/quic/test_tools/bad_packet_writer.cc", "quiche/quic/test_tools/crypto_test_utils.cc", "quiche/quic/test_tools/failing_proof_source.cc", @@ -953,10 +962,7 @@ "quiche/quic/test_tools/test_certificates.cc", "quiche/quic/test_tools/test_ip_packets.cc", "quiche/quic/test_tools/test_ticket_crypter.cc", - "quiche/quic/test_tools/web_transport_resets_backend.cc", - "quiche/spdy/test_tools/mock_spdy_framer_visitor.cc", - "quiche/spdy/test_tools/mock_spdy_headers_handler.cc", - "quiche/spdy/test_tools/spdy_test_utils.cc" + "quiche/quic/test_tools/web_transport_resets_backend.cc" ], "balsa_hdrs": [ "quiche/balsa/balsa_enums.h", @@ -1089,6 +1095,7 @@ "quiche/common/quiche_data_reader_test.cc", "quiche/common/quiche_data_writer_test.cc", "quiche/common/quiche_endian_test.cc", + "quiche/common/quiche_intrusive_list_test.cc", "quiche/common/quiche_ip_address_test.cc", "quiche/common/quiche_linked_hash_map_test.cc", "quiche/common/quiche_mem_slice_storage_test.cc", @@ -1112,7 +1119,12 @@ "quiche/http2/adapter/recording_http2_visitor_test.cc", "quiche/http2/adapter/test_utils_test.cc", "quiche/http2/adapter/window_manager_test.cc", + "quiche/http2/core/array_output_buffer_test.cc", "quiche/http2/core/priority_write_scheduler_test.cc", + "quiche/http2/core/spdy_alt_svc_wire_format_test.cc", + "quiche/http2/core/spdy_frame_builder_test.cc", + "quiche/http2/core/spdy_framer_test.cc", + "quiche/http2/core/spdy_protocol_test.cc", "quiche/http2/decoder/decode_buffer_test.cc", "quiche/http2/decoder/decode_http2_structures_test.cc", "quiche/http2/decoder/http2_frame_decoder_test.cc", @@ -1141,6 +1153,11 @@ "quiche/http2/hpack/decoder/hpack_entry_type_decoder_test.cc", "quiche/http2/hpack/decoder/hpack_string_decoder_test.cc", "quiche/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc", + "quiche/http2/hpack/hpack_encoder_test.cc", + "quiche/http2/hpack/hpack_entry_test.cc", + "quiche/http2/hpack/hpack_header_table_test.cc", + "quiche/http2/hpack/hpack_output_stream_test.cc", + "quiche/http2/hpack/hpack_static_table_test.cc", "quiche/http2/hpack/http2_hpack_constants_test.cc", "quiche/http2/hpack/huffman/hpack_huffman_decoder_test.cc", "quiche/http2/hpack/huffman/hpack_huffman_encoder_test.cc", @@ -1319,18 +1336,8 @@ "quiche/quic/tools/quic_memory_cache_backend_test.cc", "quiche/quic/tools/quic_tcp_like_trace_converter_test.cc", "quiche/quic/tools/simple_ticket_crypter_test.cc", - "quiche/spdy/core/array_output_buffer_test.cc", "quiche/spdy/core/hpack/hpack_decoder_adapter_test.cc", - "quiche/spdy/core/hpack/hpack_encoder_test.cc", - "quiche/spdy/core/hpack/hpack_entry_test.cc", - "quiche/spdy/core/hpack/hpack_header_table_test.cc", - "quiche/spdy/core/hpack/hpack_output_stream_test.cc", "quiche/spdy/core/hpack/hpack_round_trip_test.cc", - "quiche/spdy/core/hpack/hpack_static_table_test.cc", - "quiche/spdy/core/spdy_alt_svc_wire_format_test.cc", - "quiche/spdy/core/spdy_frame_builder_test.cc", - "quiche/spdy/core/spdy_framer_test.cc", - "quiche/spdy/core/spdy_protocol_test.cc", "quiche/web_transport/encapsulated/encapsulated_web_transport_test.cc", "quiche/web_transport/web_transport_headers_test.cc", "quiche/web_transport/web_transport_priority_scheduler_test.cc" @@ -1504,37 +1511,49 @@ "quiche/quic/load_balancer/load_balancer_server_id_test.cc" ], "moqt_hdrs": [ + "quiche/quic/moqt/moqt_cached_object.h", "quiche/quic/moqt/moqt_framer.h", + "quiche/quic/moqt/moqt_known_track_publisher.h", "quiche/quic/moqt/moqt_messages.h", "quiche/quic/moqt/moqt_outgoing_queue.h", "quiche/quic/moqt/moqt_parser.h", + "quiche/quic/moqt/moqt_priority.h", + "quiche/quic/moqt/moqt_publisher.h", "quiche/quic/moqt/moqt_session.h", "quiche/quic/moqt/moqt_subscribe_windows.h", "quiche/quic/moqt/moqt_track.h", + "quiche/quic/moqt/test_tools/moqt_simulator_harness.h", "quiche/quic/moqt/test_tools/moqt_test_message.h", "quiche/quic/moqt/tools/moqt_client.h", "quiche/quic/moqt/tools/moqt_mock_visitor.h", "quiche/quic/moqt/tools/moqt_server.h" ], "moqt_srcs": [ + "quiche/quic/moqt/moqt_cached_object.cc", "quiche/quic/moqt/moqt_framer.cc", "quiche/quic/moqt/moqt_framer_test.cc", "quiche/quic/moqt/moqt_integration_test.cc", + "quiche/quic/moqt/moqt_known_track_publisher.cc", "quiche/quic/moqt/moqt_messages.cc", "quiche/quic/moqt/moqt_outgoing_queue.cc", "quiche/quic/moqt/moqt_outgoing_queue_test.cc", "quiche/quic/moqt/moqt_parser.cc", "quiche/quic/moqt/moqt_parser_test.cc", + "quiche/quic/moqt/moqt_priority.cc", + "quiche/quic/moqt/moqt_priority_test.cc", "quiche/quic/moqt/moqt_session.cc", "quiche/quic/moqt/moqt_session_test.cc", "quiche/quic/moqt/moqt_subscribe_windows.cc", "quiche/quic/moqt/moqt_subscribe_windows_test.cc", + "quiche/quic/moqt/moqt_track.cc", "quiche/quic/moqt/moqt_track_test.cc", + "quiche/quic/moqt/test_tools/moqt_simulator_harness.cc", "quiche/quic/moqt/tools/chat_client_bin.cc", "quiche/quic/moqt/tools/moqt_client.cc", "quiche/quic/moqt/tools/moqt_end_to_end_test.cc", "quiche/quic/moqt/tools/moqt_ingestion_server_bin.cc", - "quiche/quic/moqt/tools/moqt_server.cc" + "quiche/quic/moqt/tools/moqt_server.cc", + "quiche/quic/moqt/tools/moqt_simulator_bin.cc" ], "binary_http_hdrs": [ "quiche/binary_http/binary_http_message.h" diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel b/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel index 39d0de208c..a982be6eed 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel @@ -45,14 +45,10 @@ cc_library( name = "quiche_flags_list", textual_hdrs = [ "common/quiche_protocol_flags_list.h", + "common/quiche_feature_flags_list.h", ], ) -cc_library( - name = "quic_flags_list", - textual_hdrs = ["quic/core/quic_flags_list.h"], -) - cc_library( name = "binary_http", srcs = binary_http_srcs, @@ -109,7 +105,6 @@ cc_library( hdrs = default_platform_impl_hdrs, strip_include_prefix = "common/platform/default", deps = [ - ":quic_flags_list", ":quiche_flags_list", ":quiche_platform_quiche_export", "@boringssl//:crypto", diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_enums.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_enums.cc index fa072fcea4..6b055fc67d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_enums.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_enums.cc @@ -58,8 +58,14 @@ const char* BalsaFrameEnums::ErrorCodeToString( return "FAILED_TO_FIND_NL_AFTER_RESPONSE_REASON_PHRASE"; case FAILED_TO_FIND_NL_AFTER_REQUEST_HTTP_VERSION: return "FAILED_TO_FIND_NL_AFTER_REQUEST_HTTP_VERSION"; + case INVALID_WS_IN_STATUS_LINE: + return "INVALID_WS_IN_STATUS_LINE"; + case INVALID_WS_IN_REQUEST_LINE: + return "INVALID_WS_IN_REQUEST_LINE"; case FAILED_CONVERTING_STATUS_CODE_TO_INT: return "FAILED_CONVERTING_STATUS_CODE_TO_INT"; + case INVALID_TARGET_URI: + return "INVALID_TARGET_URI"; case HEADERS_TOO_LONG: return "HEADERS_TOO_LONG"; case UNPARSABLE_CONTENT_LENGTH: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_enums.h b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_enums.h index 61c487ee9f..8dc270196d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_enums.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_enums.h @@ -64,8 +64,11 @@ struct QUICHE_EXPORT BalsaFrameEnums { FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI, // | firstline_b FAILED_TO_FIND_NL_AFTER_RESPONSE_REASON_PHRASE, // | firstline_c FAILED_TO_FIND_NL_AFTER_REQUEST_HTTP_VERSION, // | firstline_c + INVALID_WS_IN_STATUS_LINE, + INVALID_WS_IN_REQUEST_LINE, FAILED_CONVERTING_STATUS_CODE_TO_INT, + INVALID_TARGET_URI, HEADERS_TOO_LONG, UNPARSABLE_CONTENT_LENGTH, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_frame.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_frame.cc index 1e6080f462..d88e0e999b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_frame.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_frame.cc @@ -41,6 +41,9 @@ namespace quiche { namespace { +using FirstLineValidationOption = + HttpValidationPolicy::FirstLineValidationOption; + constexpr size_t kContinueStatusCode = 100; constexpr size_t kSwitchingProtocolsStatusCode = 101; @@ -71,7 +74,6 @@ void BalsaFrame::Reset() { term_chars_ = 0; parse_state_ = BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE; last_error_ = BalsaFrameEnums::BALSA_NO_ERROR; - invalid_chars_.clear(); lines_.clear(); if (continue_headers_ != nullptr) { continue_headers_->Clear(); @@ -85,6 +87,7 @@ void BalsaFrame::Reset() { if (trailers_ != nullptr) { trailers_->Clear(); } + is_valid_target_uri_ = true; } namespace { @@ -101,9 +104,8 @@ namespace { // whose indices fall in [*first_whitespace, *first_nonwhite), while the // non-whitespace span are the characters whose indices fall in // [*first_nonwhite, returnvalue - begin). -inline const char* ParseOneIsland(const char* current, const char* begin, - const char* end, size_t* first_whitespace, - size_t* first_nonwhite) { +inline char* ParseOneIsland(char* current, char* begin, char* end, + size_t* first_whitespace, size_t* first_nonwhite) { *first_whitespace = current - begin; while (current < end && CHAR_LE(*current, ' ')) { ++current; @@ -151,16 +153,32 @@ inline const char* ParseOneIsland(const char* current, const char* begin, // ProcessFirstLine(begin, end, is_request, &headers, &error_code); // -bool ParseHTTPFirstLine(const char* begin, const char* end, bool is_request, +bool ParseHTTPFirstLine(char* begin, char* end, bool is_request, BalsaHeaders* headers, - BalsaFrameEnums::ErrorCode* error_code) { + BalsaFrameEnums::ErrorCode* error_code, + FirstLineValidationOption whitespace_option) { while (begin < end && (end[-1] == '\n' || end[-1] == '\r')) { --end; } - const char* current = - ParseOneIsland(begin, begin, end, &headers->whitespace_1_idx_, - &headers->non_whitespace_1_idx_); + if (whitespace_option != FirstLineValidationOption::NONE) { + constexpr absl::string_view kBadWhitespace = "\r\t"; + char* pos = std::find_first_of(begin, end, kBadWhitespace.begin(), + kBadWhitespace.end()); + if (pos != end) { + if (whitespace_option == FirstLineValidationOption::REJECT) { + *error_code = static_cast( + BalsaFrameEnums::INVALID_WS_IN_STATUS_LINE + + static_cast(is_request)); + return false; + } + QUICHE_DCHECK(whitespace_option == FirstLineValidationOption::SANITIZE); + std::replace_if( + pos, end, [](char c) { return c == '\r' || c == '\t'; }, ' '); + } + } + char* current = ParseOneIsland(begin, begin, end, &headers->whitespace_1_idx_, + &headers->non_whitespace_1_idx_); current = ParseOneIsland(current, begin, end, &headers->whitespace_2_idx_, &headers->non_whitespace_2_idx_); current = ParseOneIsland(current, begin, end, &headers->whitespace_3_idx_, @@ -228,6 +246,94 @@ bool ParseHTTPFirstLine(const char* begin, const char* end, bool is_request, return true; } +namespace { +bool IsValidTargetUri(absl::string_view method, absl::string_view target_uri) { + if (target_uri.empty()) { + QUICHE_CODE_COUNT(invalid_target_uri_empty); + return false; + } + // HTTP/1.1 allows for a path of "*" for OPTIONS requests, based on RFC + // 9112, https://www.rfc-editor.org/rfc/rfc9112.html#section-3.2.4: + // + // The asterisk-form of request-target is only used for a server-wide OPTIONS + // request + // ... + // asterisk-form = "*" + if (target_uri == "*") { + if (method == "OPTIONS") { + return true; + } + QUICHE_CODE_COUNT(invalid_target_uri_asterisk_not_options); + return false; + } + if (method == "CONNECT") { + // The :authority must be authority-form for CONNECT method requests. From + // RFC 9112: https://www.rfc-editor.org/rfc/rfc9112.html#section-3.2.3: + // + // The "authority-form" of request-target is only used for CONNECT requests + // (Section 9.3.6 of [HTTP]). It consists of only the uri-host and port + // number of the tunnel destination, separated by a colon (":"). + // + // authority-form = uri-host ":" port + // + // When making a CONNECT request to establish a tunnel through one or more + // proxies, a client MUST send only the host and port of the tunnel + // destination as the request-target. The client obtains the host and port + // from the target URI's authority component, except that it sends the + // scheme's default port if the target URI elides the port. For example, a + // CONNECT request to "http://www.example.com" looks like the following: + // + // CONNECT www.example.com:80 HTTP/1.1 + // Host: www.example.com + // + // Also from RFC 9110, the CONNECT request-target must have a valid port + // number, https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.6: + // + // A server MUST reject a CONNECT request that targets an empty or invalid + // port number, typically by responding with a 400 (Bad Request) status code + size_t index = target_uri.find_last_of(':'); + if (index == absl::string_view::npos || index == 0) { + QUICHE_CODE_COUNT(invalid_target_uri_connect_missing_port); + return false; + } + // This is an IPv6 address and must have the closing "]" bracket just prior + // to the port delimiter. + if (target_uri[0] == '[' && target_uri[index - 1] != ']') { + QUICHE_CODE_COUNT(invalid_target_uri_connect_bad_v6_literal); + return false; + } + int port; + if (!absl::SimpleAtoi(target_uri.substr(index + 1), &port) || port < 0 || + port > 65535) { + QUICHE_CODE_COUNT(invalid_target_uri_connect_bad_port); + return false; + } + return true; + } + + // From RFC 9112: https://www.rfc-editor.org/rfc/rfc9112.html#name-origin-form + // + // When making a request directly to an origin server, other than a CONNECT + // or server-wide OPTIONS request (as detailed below), a client MUST send + // only the absolute path and query components of the target URI as the + // request-target. If the target URI's path component is empty, the client + // MUST send "/" as the path within the origin-form of request-target. + // + // https://www.rfc-editor.org/rfc/rfc9112.html#name-absolute-form + // When making a request to a proxy, other than a CONNECT or server-wide + // OPTIONS request (as detailed below), a client MUST send the target URI + // in "absolute-form" as the request-target. + // + // https://www.rfc-editor.org/rfc/rfc3986.html#section-4.2 + // https://www.rfc-editor.org/rfc/rfc3986.html#section-4.3 + if (target_uri[0] == '/' || absl::StrContains(target_uri, "://")) { + return true; + } + QUICHE_CODE_COUNT(invalid_target_uri_bad_path); + return false; +} +} // namespace + // begin - beginning of the firstline // end - end of the firstline // @@ -238,9 +344,11 @@ bool ParseHTTPFirstLine(const char* begin, const char* end, bool is_request, // // Another precondition for this function is that [begin, end) includes // at most one newline, which must be at the end of the line. -void BalsaFrame::ProcessFirstLine(const char* begin, const char* end) { +void BalsaFrame::ProcessFirstLine(char* begin, char* end) { BalsaFrameEnums::ErrorCode previous_error = last_error_; - if (!ParseHTTPFirstLine(begin, end, is_request_, headers_, &last_error_)) { + if (!ParseHTTPFirstLine( + begin, end, is_request_, headers_, &last_error_, + http_validation_policy().sanitize_cr_tab_in_first_line)) { parse_state_ = BalsaFrameEnums::ERROR; HandleError(last_error_); return; @@ -263,6 +371,14 @@ void BalsaFrame::ProcessFirstLine(const char* begin, const char* end) { headers_->whitespace_4_idx_ - headers_->non_whitespace_3_idx_); if (is_request_) { + is_valid_target_uri_ = IsValidTargetUri(part1, part2); + if (http_validation_policy().disallow_invalid_target_uris && + !is_valid_target_uri_) { + parse_state_ = BalsaFrameEnums::ERROR; + last_error_ = BalsaFrameEnums::INVALID_TARGET_URI; + HandleError(last_error_); + return; + } visitor_->OnRequestFirstLineInput(line_input, part1, part2, part3); if (part3.empty()) { parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ; @@ -543,13 +659,11 @@ bool BalsaFrame::CheckHeaderLinesForInvalidChars(const Lines& lines, for (const char* c = stream_begin; c < stream_end; c++) { if (header_properties::IsInvalidHeaderChar(*c)) { found_invalid = true; - invalid_chars_[*c]++; } if (*c == '\r' && http_validation_policy().disallow_lone_cr_in_request_headers && c + 1 < stream_end && *(c + 1) != '\n') { found_invalid = true; - invalid_chars_[*c]++; } } @@ -561,16 +675,12 @@ void BalsaFrame::ProcessHeaderLines(const Lines& lines, bool is_trailer, QUICHE_DCHECK(!lines.empty()); QUICHE_DVLOG(1) << "******@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**********\n"; - if ((is_request() || http_validation_policy() - .disallow_invalid_header_characters_in_response) && - track_invalid_chars()) { - if (CheckHeaderLinesForInvalidChars(lines, headers)) { - if (invalid_chars_error_enabled()) { - HandleError(BalsaFrameEnums::INVALID_HEADER_CHARACTER); - return; - } - - HandleWarning(BalsaFrameEnums::INVALID_HEADER_CHARACTER); + if (is_request() || + http_validation_policy().disallow_invalid_header_characters_in_response) { + if (invalid_chars_error_enabled() && + CheckHeaderLinesForInvalidChars(lines, headers)) { + HandleError(BalsaFrameEnums::INVALID_HEADER_CHARACTER); + return; } } @@ -793,7 +903,7 @@ size_t BalsaFrame::ProcessHeaders(const char* message_start, if (lines_.size() == 1) { headers_->WriteFromFramer(checkpoint, 1 + message_current - checkpoint); checkpoint = message_current + 1; - const char* begin = headers_->OriginalHeaderStreamBegin(); + char* begin = headers_->OriginalHeaderStreamBegin(); QUICHE_DVLOG(1) << "First line " << std::string(begin, lines_[0].second); @@ -1111,6 +1221,7 @@ size_t BalsaFrame::ProcessInput(const char* input, size_t size) { --current; parse_state_ = BalsaFrameEnums::READING_CHUNK_EXTENSION; + last_char_was_slash_r_ = false; visitor_->OnChunkLength(chunk_length_remaining_); continue; @@ -1129,11 +1240,22 @@ size_t BalsaFrame::ProcessInput(const char* input, size_t size) { return current - input; } const char c = *current; - if (http_validation_policy_.disallow_lone_cr_in_chunk_extension && - c == '\r' && (current + 1 == end || *(current + 1) != '\n')) { - // We have a lone carriage return. - HandleError(BalsaFrameEnums::INVALID_CHUNK_EXTENSION); - return current - input; + if (http_validation_policy_.disallow_lone_cr_in_chunk_extension) { + // This is a CR character and the next one is not LF. + const bool cr_followed_by_non_lf = + c == '\r' && current + 1 < end && *(current + 1) != '\n'; + // The last character processed by the last ProcessInput() call was + // CR, this is the first character of the current ProcessInput() + // call, and it is not LF. + const bool previous_cr_followed_by_non_lf = + last_char_was_slash_r_ && current == input && c != '\n'; + if (cr_followed_by_non_lf || previous_cr_followed_by_non_lf) { + HandleError(BalsaFrameEnums::INVALID_CHUNK_EXTENSION); + return current - input; + } + if (current + 1 == end) { + last_char_was_slash_r_ = c == '\r'; + } } if (c == '\r' || c == '\n') { extensions_length = (extensions_start == current) diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_frame.h b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_frame.h index d50fd65884..21d30bce19 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_frame.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_frame.h @@ -11,7 +11,6 @@ #include #include -#include "absl/container/flat_hash_map.h" #include "quiche/balsa/balsa_enums.h" #include "quiche/balsa/balsa_headers.h" #include "quiche/balsa/balsa_visitor_interface.h" @@ -37,7 +36,7 @@ class QUICHE_EXPORT BalsaFrame : public FramerInterface { typedef BalsaHeaders::HeaderLines HeaderLines; typedef BalsaHeaders::HeaderTokenList HeaderTokenList; - enum class InvalidCharsLevel { kOff, kWarning, kError }; + enum class InvalidCharsLevel { kOff, kError }; static constexpr int32_t kValidTerm1 = '\n' << 16 | '\r' << 8 | '\n'; static constexpr int32_t kValidTerm1Mask = 0xFF << 16 | 0xFF << 8 | 0xFF; @@ -59,6 +58,7 @@ class QUICHE_EXPORT BalsaFrame : public FramerInterface { term_chars_(0), parse_state_(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE), last_error_(BalsaFrameEnums::BALSA_NO_ERROR), + is_valid_target_uri_(true), continue_headers_(nullptr), headers_(nullptr), start_of_trailer_line_(0), @@ -125,10 +125,6 @@ class QUICHE_EXPORT BalsaFrame : public FramerInterface { invalid_chars_level_ = v; } - bool track_invalid_chars() { - return invalid_chars_level_ != InvalidCharsLevel::kOff; - } - bool invalid_chars_error_enabled() { return invalid_chars_level_ == InvalidCharsLevel::kError; } @@ -164,10 +160,6 @@ class QUICHE_EXPORT BalsaFrame : public FramerInterface { BalsaFrameEnums::ErrorCode ErrorCode() const { return last_error_; } - const absl::flat_hash_map& get_invalid_chars() const { - return invalid_chars_; - } - const BalsaHeaders* headers() const { return headers_; } BalsaHeaders* mutable_headers() { return headers_; } @@ -200,13 +192,15 @@ class QUICHE_EXPORT BalsaFrame : public FramerInterface { parse_truncated_headers_even_when_headers_too_long_ = set; } + bool is_valid_target_uri() const { return is_valid_target_uri_; } + protected: inline BalsaHeadersEnums::ContentLengthStatus ProcessContentLengthLine( size_t line_idx, size_t* length); inline void ProcessTransferEncodingLine(size_t line_idx); - void ProcessFirstLine(const char* begin, const char* end); + void ProcessFirstLine(char* begin, char* end); void CleanUpKeyValueWhitespace(const char* stream_begin, const char* line_begin, const char* current, @@ -217,7 +211,6 @@ class QUICHE_EXPORT BalsaFrame : public FramerInterface { BalsaHeaders* headers); // Returns true if there are invalid characters, false otherwise. - // Will also update counts per invalid character in invalid_chars_. bool CheckHeaderLinesForInvalidChars(const Lines& lines, const BalsaHeaders* headers); @@ -290,7 +283,7 @@ class QUICHE_EXPORT BalsaFrame : public FramerInterface { uint32_t term_chars_; BalsaFrameEnums::ParseState parse_state_; BalsaFrameEnums::ErrorCode last_error_; - absl::flat_hash_map invalid_chars_; + bool is_valid_target_uri_; // False if the target URI was invalid. Lines lines_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_headers.h b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_headers.h index 4e6e613f47..51599c026e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_headers.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/balsa_headers.h @@ -26,6 +26,7 @@ #include "absl/strings/string_view.h" #include "quiche/balsa/balsa_enums.h" #include "quiche/balsa/header_api.h" +#include "quiche/balsa/http_validation_policy.h" #include "quiche/balsa/standard_header_map.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_export.h" @@ -283,13 +284,13 @@ class QUICHE_EXPORT BalsaBuffer { can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_; } - const char* StartOfFirstBlock() const { + char* StartOfFirstBlock() const { QUICHE_BUG_IF(bug_if_1182_1, blocks_.empty()) << "First block not allocated yet!"; return blocks_.empty() ? nullptr : blocks_[0].buffer.get(); } - const char* EndOfFirstBlock() const { + char* EndOfFirstBlock() const { QUICHE_BUG_IF(bug_if_1182_2, blocks_.empty()) << "First block not allocated yet!"; return blocks_.empty() ? nullptr : blocks_[0].start_of_unused_bytes(); @@ -1044,9 +1045,10 @@ class QUICHE_EXPORT BalsaHeaders : public HeaderApi { friend class HTTPMessage; friend class test::BalsaHeadersTestPeer; - friend bool ParseHTTPFirstLine(const char* begin, const char* end, - bool is_request, BalsaHeaders* headers, - BalsaFrameEnums::ErrorCode* error_code); + friend bool ParseHTTPFirstLine( + char* begin, char* end, bool is_request, BalsaHeaders* headers, + BalsaFrameEnums::ErrorCode* error_code, + HttpValidationPolicy::FirstLineValidationOption whitespace_option); // Reverse iterators have been removed for lack of use, refer to // cl/30618773 in case they are needed. @@ -1073,11 +1075,11 @@ class QUICHE_EXPORT BalsaHeaders : public HeaderApi { balsa_buffer_.NoMoreWriteToContiguousBuffer(); } - const char* OriginalHeaderStreamBegin() const { + char* OriginalHeaderStreamBegin() const { return balsa_buffer_.StartOfFirstBlock(); } - const char* OriginalHeaderStreamEnd() const { + char* OriginalHeaderStreamEnd() const { return balsa_buffer_.EndOfFirstBlock(); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/http_validation_policy.h b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/http_validation_policy.h index b35799a6a8..e26f2f2b64 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/http_validation_policy.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/balsa/http_validation_policy.h @@ -63,6 +63,20 @@ struct QUICHE_EXPORT HttpValidationPolicy { // The RFC is quite specific about chunk extensions formatting, but we only // verify that there are no CR without a subsequent LF. bool disallow_lone_cr_in_chunk_extension = false; + + // If true, then requests with a target URI that is invalid will be rejected. + bool disallow_invalid_target_uris = false; + + // If SANITIZE, a request-line containing tab or carriage return will have + // those characters replaced with space. If REJECT, a request-line containing + // tab or carriage return will be rejected. + enum class FirstLineValidationOption { + NONE, + SANITIZE, + REJECT, + }; + FirstLineValidationOption sanitize_cr_tab_in_first_line = + FirstLineValidationOption::NONE; }; } // namespace quiche diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.cc index b52367ee82..2f6c4e11ca 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.cc @@ -13,6 +13,7 @@ #include #include +#include "absl/algorithm/container.h" #include "absl/functional/bind_front.h" #include "absl/status/status.h" #include "absl/status/statusor.h" @@ -148,6 +149,9 @@ void BlindSignAuth::GeneratePrivacyPassTokens( std::vector kExpectedExtensionTypes = { /*ExpirationTimestamp=*/0x0001, /*GeoHint=*/0x0002, /*ServiceType=*/0xF001, /*DebugMode=*/0xF002, /*ProxyLayer=*/0xF003}; + // TODO(b/345801768): Improve the API of + // `anonymous_tokens::ValidateExtensionsOrderAndValues` to + // avoid any possible TOCTOU problems. absl::Status result = anonymous_tokens::ValidateExtensionsOrderAndValues( *extensions, absl::MakeSpan(kExpectedExtensionTypes), absl::Now()); @@ -168,6 +172,11 @@ void BlindSignAuth::GeneratePrivacyPassTokens( absl::Time public_metadata_expiry_time = absl::FromUnixSeconds(expiration_timestamp->timestamp); + absl::StatusOr geo_hint = + anonymous_tokens::GeoHint::FromExtension( + extensions->extensions.at(1)); + QUICHE_CHECK(geo_hint.ok()); + // Create token challenge. anonymous_tokens::TokenChallenge challenge; challenge.issuer_name = kIssuerHostname; @@ -248,7 +257,7 @@ void BlindSignAuth::GeneratePrivacyPassTokens( absl::bind_front(&BlindSignAuth::PrivacyPassAuthAndSignCallback, this, std::move(initial_data_response.privacy_pass_data() .public_metadata_extensions()), - public_metadata_expiry_time, *use_case, + public_metadata_expiry_time, *geo_hint, *use_case, std::move(privacy_pass_clients), std::move(callback)); // TODO(b/304811277): remove other usages of string.data() fetcher_->DoRequest(BlindSignMessageRequestType::kAuthAndSign, oauth_token, @@ -258,6 +267,7 @@ void BlindSignAuth::GeneratePrivacyPassTokens( void BlindSignAuth::PrivacyPassAuthAndSignCallback( std::string encoded_extensions, absl::Time public_key_expiry_time, + anonymous_tokens::GeoHint geo_hint, anonymous_tokens::AnonymousTokensUseCase use_case, std::vector> @@ -327,12 +337,13 @@ void BlindSignAuth::PrivacyPassAuthAndSignCallback( privacy::ppn::PrivacyPassTokenData privacy_pass_token_data; privacy_pass_token_data.mutable_token()->assign( - absl::WebSafeBase64Escape(*marshaled_token)); + ConvertBase64ToWebSafeBase64(absl::Base64Escape(*marshaled_token))); privacy_pass_token_data.mutable_encoded_extensions()->assign( - absl::WebSafeBase64Escape(encoded_extensions)); + ConvertBase64ToWebSafeBase64(absl::Base64Escape(encoded_extensions))); privacy_pass_token_data.set_use_case_override(use_case); - tokens_vec.push_back(BlindSignToken{ - privacy_pass_token_data.SerializeAsString(), public_key_expiry_time}); + tokens_vec.push_back( + BlindSignToken{privacy_pass_token_data.SerializeAsString(), + public_key_expiry_time, geo_hint}); } std::move(callback)(absl::Span(tokens_vec)); @@ -350,6 +361,13 @@ privacy::ppn::ProxyLayer BlindSignAuth::QuicheProxyLayerToPpnProxyLayer( } } +std::string BlindSignAuth::ConvertBase64ToWebSafeBase64( + std::string base64_string) { + absl::c_replace(base64_string, /*old_value=*/'+', /*new_value=*/'-'); + absl::c_replace(base64_string, /*old_value=*/'/', /*new_value=*/'_'); + return base64_string; +} + std::string BlindSignAuthServiceTypeToString( quiche::BlindSignAuthServiceType service_type) { switch (service_type) { @@ -360,7 +378,10 @@ std::string BlindSignAuthServiceTypeToString( return "cronetipblinding"; } case BlindSignAuthServiceType::kWebviewIpBlinding: { - return "webviewipblinding"; + // Currently WebView uses the same service type as Chrome. + // TODO(b/280621504): Change this once we have a more specific service + // type. + return "chromeipblinding"; } } } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.h b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.h index 552f2c1916..37acf278a6 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.h @@ -12,6 +12,7 @@ #include "absl/status/statusor.h" #include "absl/time/time.h" #include "anonymous_tokens/cpp/privacy_pass/rsa_bssa_public_metadata_client.h" +#include "anonymous_tokens/cpp/privacy_pass/token_encodings.h" #include "quiche/blind_sign_auth/blind_sign_auth_interface.h" #include "quiche/blind_sign_auth/blind_sign_auth_protos.h" #include "quiche/blind_sign_auth/blind_sign_message_interface.h" @@ -27,7 +28,8 @@ class QUICHE_EXPORT BlindSignAuth : public BlindSignAuthInterface { privacy::ppn::BlindSignAuthOptions auth_options) : fetcher_(fetcher), auth_options_(std::move(auth_options)) {} - // Returns signed unblinded tokens and their expiration time in a callback. + // Returns signed unblinded tokens, their expiration time, and their geo in a + // callback. // Tokens are single-use. // The GetTokens callback will run on the same thread as the // BlindSignMessageInterface callbacks. @@ -49,6 +51,7 @@ class QUICHE_EXPORT BlindSignAuth : public BlindSignAuthInterface { SignedTokenCallback callback); void PrivacyPassAuthAndSignCallback( std::string encoded_extensions, absl::Time public_key_expiry_time, + anonymous_tokens::GeoHint geo_hint, anonymous_tokens::AnonymousTokensUseCase use_case, std::vector> @@ -57,6 +60,8 @@ class QUICHE_EXPORT BlindSignAuth : public BlindSignAuthInterface { absl::StatusOr response); privacy::ppn::ProxyLayer QuicheProxyLayerToPpnProxyLayer( quiche::ProxyLayer proxy_layer); + // Replaces '+' and '/' with '-' and '_' in a Base64 string. + std::string ConvertBase64ToWebSafeBase64(std::string base64_string); BlindSignMessageInterface* fetcher_ = nullptr; privacy::ppn::BlindSignAuthOptions auth_options_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_interface.h index c46df3ead8..12b6204262 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_interface.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth_interface.h @@ -11,11 +11,14 @@ #include "absl/status/statusor.h" #include "absl/time/time.h" #include "absl/types/span.h" +#include "anonymous_tokens/cpp/privacy_pass/token_encodings.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/quiche_callbacks.h" namespace quiche { +using ::anonymous_tokens::GeoHint; + // ProxyLayer indicates which proxy layer that tokens will be used with. enum class ProxyLayer : int { kProxyA, @@ -36,6 +39,7 @@ enum class BlindSignAuthServiceType { struct QUICHE_EXPORT BlindSignToken { std::string token; absl::Time expiration; + GeoHint geo_hint; }; using SignedTokenCallback = diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h index 4cd7c2eb13..b0504319b8 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h @@ -9,7 +9,7 @@ // Flags accessed via GetQuicheReloadableFlag/GetQuicheRestartFlag are temporary // boolean flags that are used to enable or disable code behavior changes. The -// current list is available in the quiche/quic/core/quic_flags_list.h file. +// current list is available at quiche/common/quiche_feature_flags_list.h. #define GetQuicheReloadableFlag(flag) GetQuicheReloadableFlagImpl(flag) #define SetQuicheReloadableFlag(flag, value) \ SetQuicheReloadableFlagImpl(flag, value) @@ -17,8 +17,8 @@ #define SetQuicheRestartFlag(flag, value) SetQuicheRestartFlagImpl(flag, value) // Flags accessed via GetQuicheFlag are permanent flags used to control QUICHE -// library behavior. The current list is available in the -// quiche/common/quiche_protocol_flags_list.h file. +// library behavior. The current list is available at +// quiche/common/quiche_protocol_flags_list.h. #define GetQuicheFlag(flag) GetQuicheFlagImpl(flag) #define SetQuicheFlag(flag, value) SetQuicheFlagImpl(flag, value) diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc index d753bd7638..d216dc10dc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc @@ -4,9 +4,10 @@ #include "quiche_platform_impl/quiche_flags_impl.h" -#define QUIC_FLAG(flag, value) bool FLAGS_##flag = value; -#include "quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + type FLAGS_##flag = external_value; +#include "quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG(type, flag, value, doc) type FLAGS_##flag = value; #include "quiche/common/quiche_protocol_flags_list.h" diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.h index 309c2705b3..8212beed14 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.h @@ -13,9 +13,10 @@ #include "quiche/common/platform/api/quiche_export.h" -#define QUIC_FLAG(flag, value) QUICHE_EXPORT extern bool FLAGS_##flag; -#include "quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + QUICHE_EXPORT extern type FLAGS_##flag; +#include "quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG // Protocol flags. #define QUICHE_PROTOCOL_FLAG(type, flag, ...) \ @@ -38,8 +39,8 @@ inline std::string GetQuicheFlagImplImpl(const std::string& flag) { // ------------------------------------------------------------------------ // QUICHE feature flags implementation. // ------------------------------------------------------------------------ -#define QUICHE_RELOADABLE_FLAG(flag) quic_reloadable_flag_##flag -#define QUICHE_RESTART_FLAG(flag) quic_restart_flag_##flag +#define QUICHE_RELOADABLE_FLAG(flag) quiche_reloadable_flag_##flag +#define QUICHE_RESTART_FLAG(flag) quiche_restart_flag_##flag #define GetQuicheReloadableFlagImpl(flag) \ GetQuicheFlag(QUICHE_RELOADABLE_FLAG(flag)) #define SetQuicheReloadableFlagImpl(flag, value) \ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.cc index ccdbff3ff6..0e7a7eae49 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.cc @@ -7,18 +7,20 @@ #include "quiche/common/platform/api/quiche_flags.h" QuicheFlagSaverImpl::QuicheFlagSaverImpl() { -#define QUIC_FLAG(flag, value) saved_##flag##_ = FLAGS_##flag; -#include "quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + saved_##flag##_ = FLAGS_##flag; +#include "quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG(type, flag, ...) saved_##flag##_ = FLAGS_##flag; #include "quiche/common/quiche_protocol_flags_list.h" #undef QUICHE_PROTOCOL_FLAG } QuicheFlagSaverImpl::~QuicheFlagSaverImpl() { -#define QUIC_FLAG(flag, value) FLAGS_##flag = saved_##flag##_; -#include "quiche/quic/core/quic_flags_list.h" // NOLINT -#undef QUIC_FLAG +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + FLAGS_##flag = saved_##flag##_; +#include "quiche/common/quiche_feature_flags_list.h" // NOLINT +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG(type, flag, ...) FLAGS_##flag = saved_##flag##_; #include "quiche/common/quiche_protocol_flags_list.h" // NOLINT #undef QUICHE_PROTOCOL_FLAG diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.h index 43d245bfcb..27489dffd0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.h @@ -24,9 +24,10 @@ class QuicheFlagSaverImpl { ~QuicheFlagSaverImpl(); private: -#define QUIC_FLAG(flag, value) bool saved_##flag##_; -#include "quiche/quic/core/quic_flags_list.h" -#undef QUIC_FLAG +#define QUICHE_FLAG(type, flag, internal_value, external_value, doc) \ + type saved_##flag##_; +#include "quiche/common/quiche_feature_flags_list.h" +#undef QUICHE_FLAG #define QUICHE_PROTOCOL_FLAG(type, flag, ...) type saved_##flag##_; #include "quiche/common/quiche_protocol_flags_list.h" diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h index b6784b136c..831d27dcaa 100755 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_feature_flags_list.h @@ -8,53 +8,52 @@ #if defined(QUICHE_FLAG) -QUICHE_FLAG(bool, quiche_reloadable_flag_http2_add_hpack_overhead_bytes2, false, "If true, HTTP/2 HEADERS frames will use two additional bytes of HPACK overhead per header in their SpdyHeadersIR::size() estimate. This flag is latched in SpdyHeadersIR to ensure a consistent size() value for a const SpdyHeadersIR regardless of flag state.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_act_upon_invalid_header, true, "If true, reject or send error response code upon receiving invalid request or response headers.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_add_stream_info_to_idle_close_detail, false, "If true, include stream information in idle timeout connection close detail.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_allow_client_enabled_bbr_v2, true, "If true, allow client to enable BBRv2 on server via connection option 'B2ON'.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_enable_bbpd_by_default, false, "If true, QUIC BBR2 will use a 0.91 PROBE_DOWN gain by default.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_extra_acked_window, false, "When true, the BBR4 copt sets the extra_acked window to 20 RTTs and BBR5 sets it to 40 RTTs.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_probe_two_rounds, true, "When true, the BB2U copt causes BBR2 to wait two rounds with out draining the queue before exiting PROBE_UP and BB2S has the same effect in STARTUP.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_simplify_inflight_hi, true, "When true, the BBHI copt causes QUIC BBRv2 to use a simpler algorithm for raising inflight_hi in PROBE_UP.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_better_qpack_compression, false, "If true, use improved QPACK compression algorithm.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_block_until_settings_received_copt, true, "If enabled and a BSUS connection is received, blocks server connections until SETTINGS frame is received.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_can_send_ack_frequency, true, "If true, ack frequency frame can be sent from server to client.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_conservative_bursts, false, "If true, set burst token to 2 in cwnd bootstrapping experiment.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false, "If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true, "If true, default-enable 5RTO blachole detection.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_default_to_bbr, true, "When true, defaults to BBR congestion control instead of Cubic.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_default_to_bbr_v2, false, "If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_batch_write, false, "If true, round-robin stream writes instead of batching in QuicWriteBlockedList.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_server_blackhole_detection, false, "If true, disable blackhole detection on server side.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_version_draft_29, false, "If true, disable QUIC version h3-29.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_version_q046, false, "If true, disable QUIC version Q046.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_version_rfcv1, false, "If true, disable QUIC version h3 (RFCv1).") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_discard_initial_packet_with_key_dropped, false, "If true, discard INITIAL packet if the key has been dropped.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_disable_resumption, true, "If true, disable resumption when receiving NRES connection option.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_mtu_discovery_at_server, false, "If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_server_on_wire_ping, true, "If true, enable server retransmittable on wire PING.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_version_rfcv2, false, "When true, support RFC9369.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_gfe_allow_alps_new_codepoint, true, "If true, allow quic to use new ALPS codepoint to negotiate during handshake for H3 if client sends new ALPS codepoint.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_ignore_gquic_probing, true, "If true, QUIC server will not respond to gQUIC probing packet(PING + PADDING) but treat it as a regular packet.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_limit_new_streams_per_loop_2, true, "If true, when the peer sends connection options \\\'SLP1\\\', \\\'SLP2\\\' and \\\'SLPF\\\', internet facing GFEs will only allow a limited number of new requests to be processed per event loop, and postpone the rest to the following event loops. Also guard QuicConnection to iterate through all decrypters at each encryption level to get cipher id for a request.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_new_error_code_when_packets_buffered_too_long, true, "If true, dispatcher sends error code QUIC_HANDSHAKE_FAILED_PACKETS_BUFFERED_TOO_LONG when handshake fails due to packets buffered for too long.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_no_path_degrading_before_handshake_confirmed, true, "If true, an endpoint does not detect path degrading or blackholing until handshake gets confirmed.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_no_write_control_frame_upon_connection_close, false, "If trrue, early return before write control frame in OnCanWrite() if the connection is already closed.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_no_write_control_frame_upon_connection_close2, false, "If true, QuicSession will block outgoing control frames when the connection is closed.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_pacing_remove_non_initial_burst, false, "If true, remove the non-initial burst in QUIC PacingSender.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_priority_respect_incremental, false, "If true, respect the incremental parameter of each stream in QuicWriteBlockedList.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_require_handshake_confirmation, true, "If true, require handshake confirmation for QUIC connections, functionally disabling 0-rtt handshakes.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_send_placeholder_ticket_when_encrypt_ticket_fails, false, "If true, when TicketCrypter fails to encrypt a session ticket, quic::TlsServerHandshaker will send a placeholder ticket, instead of an empty one, to the client.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_stop_reading_also_stops_header_decompression, false, "") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_test_peer_addr_change_after_normalize, false, "If true, QuicConnection::ProcessValidatedPacket will use normalized address to test peer address changes.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_testonly_default_false, false, "A testonly reloadable flag that will always default to false.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_testonly_default_true, true, "A testonly reloadable flag that will always default to true.") -QUICHE_FLAG(bool, quiche_reloadable_flag_quic_use_received_client_addresses_cache, true, "If true, use a LRU cache to record client addresses of packets received on server's original address.") -QUICHE_FLAG(bool, quiche_restart_flag_quic_opport_bundle_qpack_decoder_data5, true, "If true, bundle qpack decoder data with other frames opportunistically.") -QUICHE_FLAG(bool, quiche_restart_flag_quic_support_ect1, false, "When true, allows sending of QUIC packets marked ECT(1). A different flag (TBD) will actually utilize this capability to send ECT(1).") -QUICHE_FLAG(bool, quiche_restart_flag_quic_support_release_time_for_gso, false, "If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so.") -QUICHE_FLAG(bool, quiche_restart_flag_quic_testonly_default_false, false, "A testonly restart flag that will always default to false.") -QUICHE_FLAG(bool, quiche_restart_flag_quic_testonly_default_true, true, "A testonly restart flag that will always default to true.") +QUICHE_FLAG(bool, quiche_reloadable_flag_http2_add_hpack_overhead_bytes2, false, true, "If true, HTTP/2 HEADERS frames will use two additional bytes of HPACK overhead per header in their SpdyHeadersIR::size() estimate. This flag is latched in SpdyHeadersIR to ensure a consistent size() value for a const SpdyHeadersIR regardless of flag state.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_act_upon_invalid_header, true, true, "If true, reject or send error response code upon receiving invalid request or response headers.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_add_stream_info_to_idle_close_detail, false, true, "If true, include stream information in idle timeout connection close detail.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_allow_client_enabled_bbr_v2, true, true, "If true, allow client to enable BBRv2 on server via connection option 'B2ON'.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_enable_bbpd_by_default, false, true, "If true, QUIC BBR2 will use a 0.91 PROBE_DOWN gain by default.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_extra_acked_window, false, true, "When true, the BBR4 copt sets the extra_acked window to 20 RTTs and BBR5 sets it to 40 RTTs.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_probe_two_rounds, true, true, "When true, the BB2U copt causes BBR2 to wait two rounds with out draining the queue before exiting PROBE_UP and BB2S has the same effect in STARTUP.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_simplify_inflight_hi, true, true, "When true, the BBHI copt causes QUIC BBRv2 to use a simpler algorithm for raising inflight_hi in PROBE_UP.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_block_until_settings_received_copt, true, true, "If enabled and a BSUS connection is received, blocks server connections until SETTINGS frame is received.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_can_send_ack_frequency, true, true, "If true, ack frequency frame can be sent from server to client.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_conservative_bursts, false, false, "If true, set burst token to 2 in cwnd bootstrapping experiment.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false, false, "If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true, true, "If true, default-enable 5RTO blachole detection.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_default_to_bbr, true, false, "When true, defaults to BBR congestion control instead of Cubic.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_default_to_bbr_v2, false, false, "If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_batch_write, false, false, "If true, round-robin stream writes instead of batching in QuicWriteBlockedList.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_server_blackhole_detection, false, false, "If true, disable blackhole detection on server side.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_version_draft_29, false, false, "If true, disable QUIC version h3-29.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_version_q046, false, true, "If true, disable QUIC version Q046.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_disable_version_rfcv1, false, false, "If true, disable QUIC version h3 (RFCv1).") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_discard_initial_packet_with_key_dropped, false, true, "If true, discard INITIAL packet if the key has been dropped.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_disable_resumption, true, true, "If true, disable resumption when receiving NRES connection option.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_mtu_discovery_at_server, false, false, "If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_server_on_wire_ping, true, true, "If true, enable server retransmittable on wire PING.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_enable_version_rfcv2, false, false, "When true, support RFC9369.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_gfe_allow_alps_new_codepoint, true, true, "If true, allow quic to use new ALPS codepoint to negotiate during handshake for H3 if client sends new ALPS codepoint.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_ignore_gquic_probing, true, true, "If true, QUIC server will not respond to gQUIC probing packet(PING + PADDING) but treat it as a regular packet.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_limit_new_streams_per_loop_2, true, true, "If true, when the peer sends connection options \\\'SLP1\\\', \\\'SLP2\\\' and \\\'SLPF\\\', internet facing GFEs will only allow a limited number of new requests to be processed per event loop, and postpone the rest to the following event loops. Also guard QuicConnection to iterate through all decrypters at each encryption level to get cipher id for a request.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_new_error_code_when_packets_buffered_too_long, true, true, "If true, dispatcher sends error code QUIC_HANDSHAKE_FAILED_PACKETS_BUFFERED_TOO_LONG when handshake fails due to packets buffered for too long.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_no_path_degrading_before_handshake_confirmed, true, true, "If true, an endpoint does not detect path degrading or blackholing until handshake gets confirmed.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_no_write_control_frame_upon_connection_close, false, true, "If trrue, early return before write control frame in OnCanWrite() if the connection is already closed.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_no_write_control_frame_upon_connection_close2, false, false, "If true, QuicSession will block outgoing control frames when the connection is closed.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_pacing_remove_non_initial_burst, false, false, "If true, remove the non-initial burst in QUIC PacingSender.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_parse_cert_compression_algos_from_chlo, false, false, "If true, parse offered cert compression algorithms from received CHLOs.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_priority_respect_incremental, false, false, "If true, respect the incremental parameter of each stream in QuicWriteBlockedList.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_require_handshake_confirmation, true, true, "If true, require handshake confirmation for QUIC connections, functionally disabling 0-rtt handshakes.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_send_placeholder_ticket_when_encrypt_ticket_fails, false, true, "If true, when TicketCrypter fails to encrypt a session ticket, quic::TlsServerHandshaker will send a placeholder ticket, instead of an empty one, to the client.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_stop_reading_also_stops_header_decompression, false, true, "If true, QUIC stream will not continue decompressing buffer headers after StopReading() called.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_test_peer_addr_change_after_normalize, false, false, "If true, QuicConnection::ProcessValidatedPacket will use normalized address to test peer address changes.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_testonly_default_false, false, false, "A testonly reloadable flag that will always default to false.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_testonly_default_true, true, true, "A testonly reloadable flag that will always default to true.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_use_received_client_addresses_cache, true, true, "If true, use a LRU cache to record client addresses of packets received on server's original address.") +QUICHE_FLAG(bool, quiche_restart_flag_quic_support_ect1, false, false, "When true, allows sending of QUIC packets marked ECT(1). A different flag (TBD) will actually utilize this capability to send ECT(1).") +QUICHE_FLAG(bool, quiche_restart_flag_quic_support_release_time_for_gso, false, false, "If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so.") +QUICHE_FLAG(bool, quiche_restart_flag_quic_testonly_default_false, false, false, "A testonly restart flag that will always default to false.") +QUICHE_FLAG(bool, quiche_restart_flag_quic_testonly_default_true, true, true, "A testonly restart flag that will always default to true.") #endif // clang-format on diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_intrusive_list.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_intrusive_list.h new file mode 100644 index 0000000000..a00bc76cff --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_intrusive_list.h @@ -0,0 +1,343 @@ +// Copyright (c) 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_COMMON_QUICHE_INTRUSIVE_LIST_H_ +#define QUICHE_COMMON_QUICHE_INTRUSIVE_LIST_H_ + +// A QuicheIntrusiveList<> is a doubly-linked list where the link pointers are +// embedded in the elements. They are circularly linked making insertion and +// removal into a known position constant time and branch-free operations. +// +// Usage is similar to an STL list<> where feasible, but there are important +// differences. First and foremost, the elements must derive from the +// QuicheIntrusiveLink<> base class: +// +// struct Foo : public QuicheIntrusiveLink { +// // ... +// } +// +// QuicheIntrusiveList l; +// l.push_back(new Foo); +// l.push_front(new Foo); +// l.erase(&l.front()); +// l.erase(&l.back()); +// +// Intrusive lists are primarily useful when you would have considered embedding +// link pointers in your class directly for space or performance reasons. An +// QuicheIntrusiveLink<> is the size of 2 pointers, usually 16 bytes on 64-bit +// systems. Intrusive lists do not perform memory allocation (unlike the STL +// list<> class) and thus may use less memory than list<>. In particular, if the +// list elements are pointers to objects, using a list<> would perform an extra +// memory allocation for each list node structure, while an +// QuicheIntrusiveList<> would not. +// +// Note that QuicheIntrusiveLink is exempt from the C++ style guide's +// limitations on multiple inheritance, so it's fine to inherit from both +// QuicheIntrusiveLink and a base class, even if the base class is not a pure +// interface. +// +// Because the list pointers are embedded in the objects stored in an +// QuicheIntrusiveList<>, erasing an item from a list is constant time. Consider +// the following: +// +// map foo_map; +// list foo_list; +// +// foo_list.push_back(&foo_map["bar"]); +// foo_list.erase(&foo_map["bar"]); // Compile error! +// +// The problem here is that a Foo* doesn't know where on foo_list it resides, +// so removal requires iteration over the list. Various tricks can be performed +// to overcome this. For example, a foo_list::iterator can be stored inside of +// the Foo object. But at that point you'd be better off using an +// QuicheIntrusiveList<>: +// +// map foo_map; +// QuicheIntrusiveList foo_list; +// +// foo_list.push_back(&foo_map["bar"]); +// foo_list.erase(&foo_map["bar"]); // Yeah! +// +// Note that QuicheIntrusiveLists come with a few limitations. The primary +// limitation is that the QuicheIntrusiveLink<> base class is not copyable or +// assignable. The result is that STL algorithms which mutate the order of +// iterators, such as reverse() and unique(), will not work by default with +// QuicheIntrusiveLists. In order to allow these algorithms to work you'll need +// to define swap() and/or operator= for your class. +// +// Another limitation is that the QuicheIntrusiveList<> structure itself is not +// copyable or assignable since an item/link combination can only exist on one +// QuicheIntrusiveList<> at a time. This limitation is a result of the link +// pointers for an item being intrusive in the item itself. For example, the +// following will not compile: +// +// FooList a; +// FooList b(a); // no copy constructor +// b = a; // no assignment operator +// +// The similar STL code does work since the link pointers are external to the +// item: +// +// list a; +// a.push_back(new int); +// list b(a); +// QUICHE_CHECK(a.front() == b.front()); +// +// Note that QuicheIntrusiveList::size() runs in O(N) time. + +#include + +#include +#include + +#include "quiche/common/platform/api/quiche_export.h" + +namespace quiche { + +template +class QuicheIntrusiveList; + +template +class QUICHE_EXPORT QuicheIntrusiveLink { + protected: + // We declare the constructor protected so that only derived types and the + // befriended list can construct this. + QuicheIntrusiveLink() : next_(nullptr), prev_(nullptr) {} + +#ifndef SWIG + QuicheIntrusiveLink(const QuicheIntrusiveLink&) = delete; + QuicheIntrusiveLink& operator=(const QuicheIntrusiveLink&) = delete; +#endif // SWIG + + private: + // We befriend the matching list type so that it can manipulate the links + // while they are kept private from others. + friend class QuicheIntrusiveList; + + // Encapsulates the logic to convert from a link to its derived type. + T* cast_to_derived() { return static_cast(this); } + const T* cast_to_derived() const { return static_cast(this); } + + QuicheIntrusiveLink* next_; + QuicheIntrusiveLink* prev_; +}; + +template +class QUICHE_EXPORT QuicheIntrusiveList { + template + class iterator_impl; + + public: + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + typedef QuicheIntrusiveLink link_type; + typedef iterator_impl iterator; + typedef iterator_impl const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + QuicheIntrusiveList() { clear(); } + // After the move constructor the moved-from list will be empty. + // + // NOTE: There is no move assign operator (for now). + // The reason is that at the moment 'clear()' does not unlink the nodes. + // It makes is_linked() return true when it should return false. + // If such node is removed from the list (e.g. from its destructor), or is + // added to another list - a memory corruption will occur. + // Admitedly the destructor does not unlink the nodes either, but move-assign + // will likely make the problem more prominent. +#ifndef SWIG + QuicheIntrusiveList(QuicheIntrusiveList&& src) noexcept { + clear(); + if (src.empty()) return; + sentinel_link_.next_ = src.sentinel_link_.next_; + sentinel_link_.prev_ = src.sentinel_link_.prev_; + // Fix head and tail nodes of the list. + sentinel_link_.prev_->next_ = &sentinel_link_; + sentinel_link_.next_->prev_ = &sentinel_link_; + src.clear(); + } +#endif // SWIG + + iterator begin() { return iterator(sentinel_link_.next_); } + const_iterator begin() const { return const_iterator(sentinel_link_.next_); } + iterator end() { return iterator(&sentinel_link_); } + const_iterator end() const { return const_iterator(&sentinel_link_); } + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + bool empty() const { return (sentinel_link_.next_ == &sentinel_link_); } + // This runs in O(N) time. + size_type size() const { return std::distance(begin(), end()); } + size_type max_size() const { return size_type(-1); } + + reference front() { return *begin(); } + const_reference front() const { return *begin(); } + reference back() { return *(--end()); } + const_reference back() const { return *(--end()); } + + static iterator insert(iterator position, T* obj) { + return insert_link(position.link(), obj); + } + void push_front(T* obj) { insert(begin(), obj); } + void push_back(T* obj) { insert(end(), obj); } + + static iterator erase(T* obj) { + link_type* obj_link = obj; + // Fix up the next and previous links for the previous and next objects. + obj_link->next_->prev_ = obj_link->prev_; + obj_link->prev_->next_ = obj_link->next_; + // Zero out the next and previous links for the removed item. This will + // cause any future attempt to remove the item from the list to cause a + // crash instead of possibly corrupting the list structure. + link_type* next_link = obj_link->next_; + obj_link->next_ = nullptr; + obj_link->prev_ = nullptr; + return iterator(next_link); + } + + static iterator erase(iterator position) { + return erase(position.operator->()); + } + void pop_front() { erase(begin()); } + void pop_back() { erase(--end()); } + + // Check whether the given element is linked into some list. Note that this + // does *not* check whether it is linked into a particular list. + // Also, if clear() is used to clear the containing list, is_linked() will + // still return true even though obj is no longer in any list. + static bool is_linked(const T* obj) { + return obj->link_type::next_ != nullptr; + } + + void clear() { + sentinel_link_.next_ = sentinel_link_.prev_ = &sentinel_link_; + } + void swap(QuicheIntrusiveList& x) { + QuicheIntrusiveList tmp; + tmp.splice(tmp.begin(), *this); + this->splice(this->begin(), x); + x.splice(x.begin(), tmp); + } + + void splice(iterator pos, QuicheIntrusiveList& src) { + splice(pos, src.begin(), src.end()); + } + + void splice(iterator pos, iterator i) { splice(pos, i, std::next(i)); } + + void splice(iterator pos, iterator first, iterator last) { + if (first == last) return; + + link_type* const last_prev = last.link()->prev_; + + // Remove from the source. + first.link()->prev_->next_ = last.operator->(); + last.link()->prev_ = first.link()->prev_; + + // Attach to the destination. + first.link()->prev_ = pos.link()->prev_; + pos.link()->prev_->next_ = first.operator->(); + last_prev->next_ = pos.operator->(); + pos.link()->prev_ = last_prev; + } + + private: + static iterator insert_link(link_type* next_link, T* obj) { + link_type* obj_link = obj; + obj_link->next_ = next_link; + link_type* const initial_next_prev = next_link->prev_; + obj_link->prev_ = initial_next_prev; + initial_next_prev->next_ = obj_link; + next_link->prev_ = obj_link; + return iterator(obj_link); + } + + // The iterator implementation is parameterized on a potentially qualified + // variant of T and the matching qualified link type. Essentially, QualifiedT + // will either be 'T' or 'const T', the latter for a const_iterator. + template + class QUICHE_EXPORT iterator_impl { + public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = QualifiedT; + using difference_type = std::ptrdiff_t; + using pointer = QualifiedT*; + using reference = QualifiedT&; + + iterator_impl() = default; + iterator_impl(QualifiedLinkT* link) : link_(link) {} + iterator_impl(const iterator_impl& x) = default; + iterator_impl& operator=(const iterator_impl& x) = default; + + // Allow converting and comparing across iterators where the pointer + // assignment and comparisons (respectively) are allowed. + template + iterator_impl(const iterator_impl& x) : link_(x.link_) {} + template + bool operator==(const iterator_impl& x) const { + return link_ == x.link_; + } + template + bool operator!=(const iterator_impl& x) const { + return link_ != x.link_; + } + + reference operator*() const { return *operator->(); } + pointer operator->() const { return link_->cast_to_derived(); } + + QualifiedLinkT* link() const { return link_; } + +#ifndef SWIG // SWIG can't wrap these operator overloads. + iterator_impl& operator++() { + link_ = link_->next_; + return *this; + } + iterator_impl operator++(int /*unused*/) { + iterator_impl tmp = *this; + ++*this; + return tmp; + } + iterator_impl& operator--() { + link_ = link_->prev_; + return *this; + } + iterator_impl operator--(int /*unused*/) { + iterator_impl tmp = *this; + --*this; + return tmp; + } +#endif // SWIG + + private: + // Ensure iterators can access other iterators node directly. + template + friend class iterator_impl; + + QualifiedLinkT* link_ = nullptr; + }; + + // This bare link acts as the sentinel node. + link_type sentinel_link_; + + // These are private and undefined to prevent copying and assigning. + QuicheIntrusiveList(const QuicheIntrusiveList&); + void operator=(const QuicheIntrusiveList&); +}; + +} // namespace quiche + +#endif // QUICHE_COMMON_QUICHE_INTRUSIVE_LIST_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor.cc index eda177345c..89b02b58a2 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor.cc @@ -558,6 +558,12 @@ bool CallbackVisitor::OnMetadataEndForStream(Http2StreamId stream_id) { return true; } +std::pair CallbackVisitor::PackMetadataForStream( + Http2StreamId /*stream_id*/, uint8_t* /*dest*/, size_t /*dest_len*/) { + QUICHE_LOG(DFATAL) << "Unimplemented."; + return {-1, false}; +} + void CallbackVisitor::OnErrorDebug(absl::string_view message) { QUICHE_VLOG(1) << "OnErrorDebug(message=[" << absl::CEscape(message) << "])"; if (callbacks_->error_callback2) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor.h index f1d7a3ac66..c87e210618 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor.h @@ -76,6 +76,10 @@ class QUICHE_EXPORT CallbackVisitor : public Http2VisitorInterface { bool OnMetadataForStream(Http2StreamId stream_id, absl::string_view metadata) override; bool OnMetadataEndForStream(Http2StreamId stream_id) override; + std::pair PackMetadataForStream(Http2StreamId stream_id, + uint8_t* dest, + size_t dest_len) override; + void OnErrorDebug(absl::string_view message) override; size_t stream_map_size() const { return stream_map_.size(); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/http2_adapter.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/http2_adapter.h index 35c9829564..ef0700ee84 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/http2_adapter.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/http2_adapter.h @@ -72,6 +72,12 @@ class QUICHE_EXPORT Http2Adapter { virtual void SubmitMetadata(Http2StreamId stream_id, size_t max_frame_size, std::unique_ptr source) = 0; + // Submits a sequence of METADATA frames for the given stream. A |stream_id| + // of 0 indicates connection-level METADATA. The adapter will query the + // visitor for the payload by calling + // Http2VisitorInterface::PackMetadataForStream(). + virtual void SubmitMetadata(Http2StreamId stream_id, size_t num_frames) = 0; + // Invokes the visitor's OnReadyToSend() method for serialized frame data. // Returns 0 on success. virtual int Send() = 0; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/http2_visitor_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/http2_visitor_interface.h index 531c0afcd3..3bf489f5ca 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/http2_visitor_interface.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/http2_visitor_interface.h @@ -280,6 +280,16 @@ class QUICHE_EXPORT Http2VisitorInterface { // Returns false if there was an error unpacking the metadata payload. virtual bool OnMetadataEndForStream(Http2StreamId stream_id) = 0; + // Called when the connection is ready to send a metadata payload for a + // stream. Should return the number of payload bytes copied to |dest|, or a + // negative integer to indicate an error, as well as a boolean indicating + // whether the metadata payload has been completely copied. + virtual std::pair PackMetadataForStream( + Http2StreamId /*stream_id*/, uint8_t* /*dest*/, size_t /*dest_len*/) { + QUICHE_LOG(DFATAL) << "Not implemented"; + return {-1, false}; + } + // Invoked with an error message from the application. virtual void OnErrorDebug(absl::string_view message) = 0; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/mock_http2_visitor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/mock_http2_visitor.h index 40d3c807ff..a99c944b9c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/mock_http2_visitor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/mock_http2_visitor.h @@ -1,6 +1,7 @@ #ifndef QUICHE_HTTP2_ADAPTER_MOCK_HTTP2_VISITOR_H_ #define QUICHE_HTTP2_ADAPTER_MOCK_HTTP2_VISITOR_H_ +#include #include #include "quiche/http2/adapter/http2_visitor_interface.h" @@ -118,6 +119,10 @@ class QUICHE_NO_EXPORT MockHttp2Visitor : public Http2VisitorInterface { MOCK_METHOD(bool, OnMetadataEndForStream, (Http2StreamId stream_id), (override)); + MOCK_METHOD((std::pair), PackMetadataForStream, + (Http2StreamId stream_id, uint8_t* dest, size_t dest_len), + (override)); + MOCK_METHOD(void, OnErrorDebug, (absl::string_view message), (override)); }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter.cc index d03ab8b95f..6e653f5de1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter.cc @@ -76,6 +76,37 @@ class NgHttp2Adapter::NotifyingMetadataSource : public MetadataSource { std::unique_ptr source_; }; +// A metadata source that notifies the owning NgHttp2Adapter upon completion or +// failure. +class NgHttp2Adapter::NotifyingVisitorMetadataSource : public MetadataSource { + public: + explicit NotifyingVisitorMetadataSource(NgHttp2Adapter* adapter, + Http2StreamId stream_id, + Http2VisitorInterface& visitor) + : adapter_(adapter), stream_id_(stream_id), visitor_(visitor) {} + + size_t NumFrames(size_t /*max_frame_size*/) const override { + QUICHE_LOG(DFATAL) << "Should not be invoked."; + return 0; + } + + std::pair Pack(uint8_t* dest, size_t dest_len) override { + const auto [packed, end_metadata] = + visitor_.PackMetadataForStream(stream_id_, dest, dest_len); + if (packed < 0 || end_metadata) { + adapter_->RemovePendingMetadata(stream_id_); + } + return {packed, end_metadata}; + } + + void OnFailure() override { adapter_->RemovePendingMetadata(stream_id_); } + + private: + NgHttp2Adapter* const adapter_; + const Http2StreamId stream_id_; + Http2VisitorInterface& visitor_; +}; + /* static */ std::unique_ptr NgHttp2Adapter::CreateClientAdapter( Http2VisitorInterface& visitor, const nghttp2_option* options) { @@ -180,6 +211,31 @@ void NgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id, } } +void NgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id, + size_t num_frames) { + auto wrapped_source = std::make_unique( + this, stream_id, visitor_); + size_t num_successes = 0; + for (size_t i = 1; i <= num_frames; ++i) { + const int result = + nghttp2_submit_extension(session_->raw_ptr(), kMetadataFrameType, + i == num_frames ? kMetadataEndFlag : 0, + stream_id, wrapped_source.get()); + if (result != 0) { + QUICHE_LOG(DFATAL) << "Failed to submit extension frame " << i << " of " + << num_frames; + break; + } + ++num_successes; + } + if (num_successes > 0) { + // Finds the MetadataSourceVec for `stream_id` or inserts a new one if not + // present. + auto [it, _] = stream_metadata_.insert({stream_id, MetadataSourceVec{}}); + it->second.push_back(std::move(wrapped_source)); + } +} + int NgHttp2Adapter::Send() { const int result = nghttp2_session_send(session_->raw_ptr()); if (result != 0) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter.h index 8fa54e4420..c2e18be08c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_adapter.h @@ -56,6 +56,8 @@ class QUICHE_EXPORT NgHttp2Adapter : public Http2Adapter { void SubmitMetadata(Http2StreamId stream_id, size_t max_frame_size, std::unique_ptr source) override; + void SubmitMetadata(Http2StreamId stream_id, size_t num_frames) override; + int Send() override; int GetSendWindowSize() const override; @@ -117,6 +119,7 @@ class QUICHE_EXPORT NgHttp2Adapter : public Http2Adapter { private: class NotifyingMetadataSource; + class NotifyingVisitorMetadataSource; NgHttp2Adapter(Http2VisitorInterface& visitor, Perspective perspective, const nghttp2_option* options); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_util.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_util.cc index a59f69da8d..615ad89b36 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_util.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_util.cc @@ -91,7 +91,7 @@ std::vector GetNghttp2Nvs(absl::Span headers) { } std::vector GetResponseNghttp2Nvs( - const spdy::Http2HeaderBlock& headers, absl::string_view response_code) { + const quiche::HttpHeaderBlock& headers, absl::string_view response_code) { // Allocate enough for all headers and also the :status pseudoheader. const int num_headers = headers.size(); std::vector nghttp2_nvs; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_util.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_util.h index 423ad1bb7c..5e08e8c0f7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_util.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/nghttp2_util.h @@ -12,7 +12,7 @@ #include "quiche/http2/adapter/http2_protocol.h" #include "quiche/http2/adapter/http2_visitor_interface.h" #include "quiche/http2/adapter/nghttp2.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace http2 { namespace adapter { @@ -49,7 +49,7 @@ std::vector GetNghttp2Nvs(absl::Span headers); // the :status pseudoheader first based on the given |response_code|. The // |response_code| is passed in separately from |headers| for lifetime reasons. std::vector GetResponseNghttp2Nvs( - const spdy::Http2HeaderBlock& headers, absl::string_view response_code); + const quiche::HttpHeaderBlock& headers, absl::string_view response_code); // Returns the HTTP/2 error code corresponding to the raw wire value, as defined // in RFC 7540 Section 7. Unrecognized error codes are treated as INTERNAL_ERROR diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.cc index 998e309864..cb45f17e4d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.cc @@ -79,6 +79,15 @@ void OgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id, session_->SubmitMetadata(stream_id, std::move(source)); } +void OgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id, + size_t /* num_frames */) { + // Not necessary to pass max_frame_size along, since OgHttp2Session tracks the + // peer's advertised max frame size. Not necessary to pass the number of + // frames along, since OgHttp2Session will invoke the visitor method until it + // is done packing the payload. + session_->SubmitMetadata(stream_id); +} + int OgHttp2Adapter::Send() { return session_->Send(); } int OgHttp2Adapter::GetSendWindowSize() const { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.h index 3d002357c6..400aa87063 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.h @@ -38,6 +38,7 @@ class QUICHE_EXPORT OgHttp2Adapter : public Http2Adapter { int window_increment) override; void SubmitMetadata(Http2StreamId stream_id, size_t max_frame_size, std::unique_ptr source) override; + void SubmitMetadata(Http2StreamId stream_id, size_t num_frames) override; int Send() override; int GetSendWindowSize() const override; int GetStreamSendWindowSize(Http2StreamId stream_id) const override; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.cc index 770e6791b2..cc80bafa6f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.cc @@ -531,8 +531,8 @@ OgHttp2Session::ProcessBytesImpl(absl::string_view bytes) { int OgHttp2Session::Consume(Http2StreamId stream_id, size_t num_bytes) { auto it = stream_map_.find(stream_id); if (it == stream_map_.end()) { - QUICHE_LOG(ERROR) << "Stream " << stream_id << " not found when consuming " - << num_bytes << " bytes"; + QUICHE_VLOG(1) << "Stream " << stream_id << " not found when consuming " + << num_bytes << " bytes"; } else { it->second.window_manager.MarkDataFlushed(num_bytes); } @@ -994,6 +994,30 @@ void OgHttp2Session::SerializeMetadata(Http2StreamId stream_id, } } +void OgHttp2Session::SerializeMetadata(Http2StreamId stream_id) { + const uint32_t max_payload_size = + std::min(kMaxAllowedMetadataFrameSize, max_frame_payload_); + auto payload_buffer = std::make_unique(max_payload_size); + + while (true) { + auto [written, end_metadata] = visitor_.PackMetadataForStream( + stream_id, payload_buffer.get(), max_payload_size); + if (written < 0) { + // Unable to pack any metadata. + return; + } + QUICHE_DCHECK_LE(static_cast(written), max_payload_size); + auto payload = absl::string_view( + reinterpret_cast(payload_buffer.get()), written); + EnqueueFrame(std::make_unique( + stream_id, kMetadataFrameType, end_metadata ? kMetadataEndFlag : 0u, + std::string(payload))); + if (end_metadata) { + return; + } + } +} + int32_t OgHttp2Session::SubmitRequest( absl::Span headers, std::unique_ptr data_source, bool end_stream, @@ -1034,7 +1058,7 @@ int OgHttp2Session::SubmitTrailer(Http2StreamId stream_id, } else { // Save trailers so they can be written once data is done. state.trailers = - std::make_unique(ToHeaderBlock(trailers)); + std::make_unique(ToHeaderBlock(trailers)); trailers_ready_.insert(stream_id); } return 0; @@ -1045,6 +1069,10 @@ void OgHttp2Session::SubmitMetadata(Http2StreamId stream_id, SerializeMetadata(stream_id, std::move(source)); } +void OgHttp2Session::SubmitMetadata(Http2StreamId stream_id) { + SerializeMetadata(stream_id); +} + void OgHttp2Session::SubmitSettings(absl::Span settings) { auto frame = PrepareSettingsFrame(settings); EnqueueFrame(std::move(frame)); @@ -1116,16 +1144,6 @@ void OgHttp2Session::OnDataFrameHeader(spdy::SpdyStreamId stream_id, stream_id, spdy::ERROR_CODE_PROTOCOL_ERROR)); return; } - - // Validate against the content-length if it exists. - if (iter->second.remaining_content_length.has_value()) { - if (length > *iter->second.remaining_content_length) { - HandleContentLengthError(stream_id); - iter->second.remaining_content_length.reset(); - } else { - *iter->second.remaining_content_length -= length; - } - } } void OgHttp2Session::OnStreamFrameData(spdy::SpdyStreamId stream_id, @@ -1133,7 +1151,20 @@ void OgHttp2Session::OnStreamFrameData(spdy::SpdyStreamId stream_id, // Count the data against flow control, even if the stream is unknown. MarkDataBuffered(stream_id, len); - if (!stream_map_.contains(stream_id) || streams_reset_.contains(stream_id)) { + auto iter = stream_map_.find(stream_id); + if (iter == stream_map_.end()) { + return; + } + // Validate against the content-length if it exists. + if (iter->second.remaining_content_length.has_value()) { + if (len > *iter->second.remaining_content_length) { + HandleContentLengthError(stream_id); + iter->second.remaining_content_length.reset(); + } else { + *iter->second.remaining_content_length -= len; + } + } + if (streams_reset_.contains(stream_id)) { // If the stream was unknown due to a protocol error, the visitor was // informed in OnDataFrameHeader(). return; @@ -1763,7 +1794,7 @@ void OgHttp2Session::SendWindowUpdate(Http2StreamId stream_id, } void OgHttp2Session::SendHeaders(Http2StreamId stream_id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, bool end_stream) { auto frame = std::make_unique(stream_id, std::move(headers)); @@ -1772,7 +1803,7 @@ void OgHttp2Session::SendHeaders(Http2StreamId stream_id, } void OgHttp2Session::SendTrailers(Http2StreamId stream_id, - spdy::Http2HeaderBlock trailers) { + quiche::HttpHeaderBlock trailers) { auto frame = std::make_unique(stream_id, std::move(trailers)); frame->set_fin(true); @@ -1822,7 +1853,7 @@ OgHttp2Session::StreamStateMap::iterator OgHttp2Session::CreateStream( } void OgHttp2Session::StartRequest(Http2StreamId stream_id, - spdy::Http2HeaderBlock headers, + quiche::HttpHeaderBlock headers, std::unique_ptr data_source, void* user_data, bool end_stream) { if (received_goaway_) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.h index ab1373741a..2bd4c5f44b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.h @@ -21,7 +21,9 @@ #include "quiche/http2/adapter/http2_visitor_interface.h" #include "quiche/http2/adapter/window_manager.h" #include "quiche/http2/core/http2_trace_logging.h" +#include "quiche/http2/core/no_op_headers_handler.h" #include "quiche/http2/core/priority_write_scheduler.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_flags.h" @@ -29,8 +31,6 @@ #include "quiche/common/quiche_circular_deque.h" #include "quiche/common/quiche_linked_hash_map.h" #include "quiche/spdy/core/http2_frame_decoder_adapter.h" -#include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/no_op_headers_handler.h" #include "quiche/spdy/core/spdy_framer.h" #include "quiche/spdy/core/spdy_protocol.h" @@ -114,6 +114,7 @@ class QUICHE_EXPORT OgHttp2Session : public Http2Session, int SubmitTrailer(Http2StreamId stream_id, absl::Span trailers); void SubmitMetadata(Http2StreamId stream_id, std::unique_ptr source); + void SubmitMetadata(Http2StreamId stream_id); void SubmitSettings(absl::Span settings); bool IsServerSession() const { @@ -244,7 +245,7 @@ class QUICHE_EXPORT OgHttp2Session : public Http2Session, WindowManager window_manager; std::unique_ptr outbound_body; - std::unique_ptr trailers; + std::unique_ptr trailers; void* user_data = nullptr; int32_t send_window; std::optional received_header_type; @@ -260,7 +261,7 @@ class QUICHE_EXPORT OgHttp2Session : public Http2Session, using StreamStateMap = absl::flat_hash_map; struct QUICHE_EXPORT PendingStreamState { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; std::unique_ptr data_source; void* user_data = nullptr; bool end_stream; @@ -393,11 +394,12 @@ class QUICHE_EXPORT OgHttp2Session : public Http2Session, void SerializeMetadata(Http2StreamId stream_id, std::unique_ptr source); + void SerializeMetadata(Http2StreamId stream_id); - void SendHeaders(Http2StreamId stream_id, spdy::Http2HeaderBlock headers, + void SendHeaders(Http2StreamId stream_id, quiche::HttpHeaderBlock headers, bool end_stream); - void SendTrailers(Http2StreamId stream_id, spdy::Http2HeaderBlock trailers); + void SendTrailers(Http2StreamId stream_id, quiche::HttpHeaderBlock trailers); // Encapsulates the RST_STREAM NO_ERROR behavior described in RFC 7540 // Section 8.1. @@ -412,7 +414,7 @@ class QUICHE_EXPORT OgHttp2Session : public Http2Session, // Creates a stream for `stream_id`, stores the `data_source` and `user_data` // in the stream state, and sends the `headers`. - void StartRequest(Http2StreamId stream_id, spdy::Http2HeaderBlock headers, + void StartRequest(Http2StreamId stream_id, quiche::HttpHeaderBlock headers, std::unique_ptr data_source, void* user_data, bool end_stream); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.cc index 26a3fb3461..df0aa8d1be 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.cc @@ -3,8 +3,8 @@ namespace http2 { namespace adapter { -spdy::Http2HeaderBlock ToHeaderBlock(absl::Span headers) { - spdy::Http2HeaderBlock block; +quiche::HttpHeaderBlock ToHeaderBlock(absl::Span headers) { + quiche::HttpHeaderBlock block; for (const Header& header : headers) { absl::string_view name = GetStringView(header.first).first; absl::string_view value = GetStringView(header.second).first; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.h index 0aba100a4a..25ec337490 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.h @@ -3,13 +3,13 @@ #include "absl/types/span.h" #include "quiche/http2/adapter/http2_protocol.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/http2_header_block.h" namespace http2 { namespace adapter { -QUICHE_EXPORT spdy::Http2HeaderBlock ToHeaderBlock( +QUICHE_EXPORT quiche::HttpHeaderBlock ToHeaderBlock( absl::Span headers); } // namespace adapter diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/recording_http2_visitor.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/recording_http2_visitor.cc index 0b989f0833..d1f37b5be4 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/recording_http2_visitor.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/recording_http2_visitor.cc @@ -188,6 +188,12 @@ bool RecordingHttp2Visitor::OnMetadataEndForStream(Http2StreamId stream_id) { return true; } +std::pair RecordingHttp2Visitor::PackMetadataForStream( + Http2StreamId stream_id, uint8_t* /*dest*/, size_t /*dest_len*/) { + events_.push_back(absl::StrFormat("PackMetadataForStream %d", stream_id)); + return {1, true}; +} + void RecordingHttp2Visitor::OnErrorDebug(absl::string_view message) { events_.push_back(absl::StrFormat("OnErrorDebug %s", message)); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/recording_http2_visitor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/recording_http2_visitor.h index b7835ee653..4526d93c83 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/recording_http2_visitor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/recording_http2_visitor.h @@ -68,6 +68,9 @@ class QUICHE_NO_EXPORT RecordingHttp2Visitor : public Http2VisitorInterface { bool OnMetadataForStream(Http2StreamId stream_id, absl::string_view metadata) override; bool OnMetadataEndForStream(Http2StreamId stream_id) override; + std::pair PackMetadataForStream(Http2StreamId stream_id, + uint8_t* dest, + size_t dest_len) override; void OnErrorDebug(absl::string_view message) override; const EventSequence& GetEventSequence() const { return events_; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_frame_sequence.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_frame_sequence.cc index bae140db9d..a099082bfd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_frame_sequence.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_frame_sequence.cc @@ -8,7 +8,7 @@ #include "quiche/http2/adapter/http2_util.h" #include "quiche/http2/adapter/oghttp2_util.h" -#include "quiche/spdy/core/hpack/hpack_encoder.h" +#include "quiche/http2/hpack/hpack_encoder.h" #include "quiche/spdy/core/spdy_framer.h" namespace http2 { @@ -107,7 +107,7 @@ TestFrameSequence& TestFrameSequence::Headers( } TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id, - spdy::Http2HeaderBlock block, + quiche::HttpHeaderBlock block, bool fin, bool add_continuation) { if (add_continuation) { // The normal intermediate representations don't allow you to represent a diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_frame_sequence.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_frame_sequence.h index 93c553648d..59a0d7f5e5 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_frame_sequence.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_frame_sequence.h @@ -7,8 +7,8 @@ #include #include "quiche/http2/adapter/http2_protocol.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/http2_header_block.h" #include "quiche/spdy/core/spdy_protocol.h" namespace http2 { @@ -48,7 +48,7 @@ class QUICHE_NO_EXPORT TestFrameSequence { absl::Span> headers, bool fin = false, bool add_continuation = false); TestFrameSequence& Headers(Http2StreamId stream_id, - spdy::Http2HeaderBlock block, bool fin = false, + quiche::HttpHeaderBlock block, bool fin = false, bool add_continuation = false); TestFrameSequence& Headers(Http2StreamId stream_id, absl::Span headers, bool fin = false, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_utils.cc index 83445e0c8e..40e3970832 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_utils.cc @@ -7,8 +7,8 @@ #include "absl/strings/str_format.h" #include "quiche/http2/adapter/http2_visitor_interface.h" +#include "quiche/http2/hpack/hpack_encoder.h" #include "quiche/common/quiche_data_reader.h" -#include "quiche/spdy/core/hpack/hpack_encoder.h" #include "quiche/spdy/core/spdy_protocol.h" namespace http2 { @@ -18,6 +18,12 @@ namespace { using ConnectionError = Http2VisitorInterface::ConnectionError; +std::string EncodeHeaders(const quiche::HttpHeaderBlock& entries) { + spdy::HpackEncoder encoder; + encoder.DisableCompression(); + return encoder.EncodeHeaderBlock(entries); +} + } // anonymous namespace TestVisitor::DataFrameHeaderInfo TestVisitor::OnReadyToSendDataForStream( @@ -96,6 +102,28 @@ void TestVisitor::SimulateError(Http2StreamId stream_id) { payload.return_error = true; } +std::pair TestVisitor::PackMetadataForStream( + Http2StreamId stream_id, uint8_t* dest, size_t dest_len) { + auto it = outbound_metadata_map_.find(stream_id); + if (it == outbound_metadata_map_.end()) { + return {-1, false}; + } + const size_t to_copy = std::min(it->second.size(), dest_len); + auto* src = reinterpret_cast(it->second.data()); + std::copy(src, src + to_copy, dest); + it->second = it->second.substr(to_copy); + if (it->second.empty()) { + outbound_metadata_map_.erase(it); + return {to_copy, true}; + } + return {to_copy, false}; +} + +void TestVisitor::AppendMetadataForStream( + Http2StreamId stream_id, const quiche::HttpHeaderBlock& payload) { + outbound_metadata_map_.insert({stream_id, EncodeHeaders(payload)}); +} + VisitorDataSource::VisitorDataSource(Http2VisitorInterface& visitor, Http2StreamId stream_id) : visitor_(visitor), stream_id_(stream_id) {} @@ -115,13 +143,7 @@ bool VisitorDataSource::Send(absl::string_view frame_header, return visitor_.SendDataFrame(stream_id_, frame_header, payload_length); } -std::string EncodeHeaders(const spdy::Http2HeaderBlock& entries) { - spdy::HpackEncoder encoder; - encoder.DisableCompression(); - return encoder.EncodeHeaderBlock(entries); -} - -TestMetadataSource::TestMetadataSource(const spdy::Http2HeaderBlock& entries) +TestMetadataSource::TestMetadataSource(const quiche::HttpHeaderBlock& entries) : encoded_entries_(EncodeHeaders(entries)) { remaining_ = encoded_entries_; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_utils.h index 5c7a6872cc..66eca8713e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/test_utils.h @@ -11,9 +11,9 @@ #include "quiche/http2/adapter/data_source.h" #include "quiche/http2/adapter/http2_protocol.h" #include "quiche/http2/adapter/mock_http2_visitor.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_test.h" -#include "quiche/spdy/core/http2_header_block.h" #include "quiche/spdy/core/spdy_protocol.h" namespace http2 { @@ -70,6 +70,14 @@ class QUICHE_NO_EXPORT TestVisitor void SetEndData(Http2StreamId stream_id, bool end_stream); void SimulateError(Http2StreamId stream_id); + std::pair PackMetadataForStream(Http2StreamId stream_id, + uint8_t* dest, + size_t dest_len) override; + + // Test methods to manipulate the metadata payload to send for a stream. + void AppendMetadataForStream(Http2StreamId stream_id, + const quiche::HttpHeaderBlock& payload); + const std::string& data() { return data_; } void Clear() { data_.clear(); } @@ -90,6 +98,7 @@ class QUICHE_NO_EXPORT TestVisitor std::string data_; absl::flat_hash_map> metadata_map_; absl::flat_hash_map data_map_; + absl::flat_hash_map outbound_metadata_map_; size_t send_limit_ = std::numeric_limits::max(); bool is_write_blocked_ = false; bool has_write_error_ = false; @@ -113,7 +122,7 @@ class QUICHE_NO_EXPORT VisitorDataSource : public DataFrameSource { class QUICHE_NO_EXPORT TestMetadataSource : public MetadataSource { public: - explicit TestMetadataSource(const spdy::Http2HeaderBlock& entries); + explicit TestMetadataSource(const quiche::HttpHeaderBlock& entries); size_t NumFrames(size_t max_frame_size) const override { // Round up to the next frame. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/array_output_buffer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/array_output_buffer.cc similarity index 91% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/array_output_buffer.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/array_output_buffer.cc index 76d30a58ec..137b94793d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/array_output_buffer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/array_output_buffer.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/array_output_buffer.h" +#include "quiche/http2/core/array_output_buffer.h" #include diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/array_output_buffer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/array_output_buffer.h similarity index 85% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/array_output_buffer.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/array_output_buffer.h index f9a80bf556..6fc9727a69 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/array_output_buffer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/array_output_buffer.h @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_ARRAY_OUTPUT_BUFFER_H_ -#define QUICHE_SPDY_CORE_ARRAY_OUTPUT_BUFFER_H_ +#ifndef QUICHE_HTTP2_CORE_ARRAY_OUTPUT_BUFFER_H_ +#define QUICHE_HTTP2_CORE_ARRAY_OUTPUT_BUFFER_H_ #include #include +#include "quiche/http2/core/zero_copy_output_buffer.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/zero_copy_output_buffer.h" namespace spdy { @@ -45,4 +45,4 @@ class QUICHE_EXPORT ArrayOutputBuffer : public ZeroCopyOutputBuffer { } // namespace spdy -#endif // QUICHE_SPDY_CORE_ARRAY_OUTPUT_BUFFER_H_ +#endif // QUICHE_HTTP2_CORE_ARRAY_OUTPUT_BUFFER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/header_byte_listener_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/header_byte_listener_interface.h similarity index 72% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/header_byte_listener_interface.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/header_byte_listener_interface.h index 308110ff16..a91c8f45bc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/header_byte_listener_interface.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/header_byte_listener_interface.h @@ -1,5 +1,5 @@ -#ifndef QUICHE_SPDY_CORE_HEADER_BYTE_LISTENER_INTERFACE_H_ -#define QUICHE_SPDY_CORE_HEADER_BYTE_LISTENER_INTERFACE_H_ +#ifndef QUICHE_HTTP2_CORE_HEADER_BYTE_LISTENER_INTERFACE_H_ +#define QUICHE_HTTP2_CORE_HEADER_BYTE_LISTENER_INTERFACE_H_ #include @@ -19,4 +19,4 @@ class QUICHE_EXPORT HeaderByteListenerInterface { } // namespace spdy -#endif // QUICHE_SPDY_CORE_HEADER_BYTE_LISTENER_INTERFACE_H_ +#endif // QUICHE_HTTP2_CORE_HEADER_BYTE_LISTENER_INTERFACE_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_frame_decoder_adapter.cc similarity index 99% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_frame_decoder_adapter.cc index 3896ebd899..64362d1e07 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_frame_decoder_adapter.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/http2_frame_decoder_adapter.h" +#include "quiche/http2/core/http2_frame_decoder_adapter.h" // Logging policy: If an error in the input is detected, QUICHE_VLOG(n) is used // so that the option exists to debug the situation. Otherwise, this code mostly @@ -17,20 +17,20 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" +#include "quiche/http2/core/spdy_protocol.h" #include "quiche/http2/decoder/decode_buffer.h" #include "quiche/http2/decoder/decode_status.h" #include "quiche/http2/decoder/http2_frame_decoder.h" #include "quiche/http2/hpack/decoder/hpack_decoding_error.h" +#include "quiche/http2/hpack/hpack_header_table.h" #include "quiche/http2/http2_constants.h" #include "quiche/http2/http2_structures.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_endian.h" #include "quiche/spdy/core/hpack/hpack_decoder_adapter.h" -#include "quiche/spdy/core/hpack/hpack_header_table.h" -#include "quiche/spdy/core/spdy_alt_svc_wire_format.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" -#include "quiche/spdy/core/spdy_protocol.h" using ::spdy::ExtensionVisitorInterface; using ::spdy::HpackDecoderAdapter; @@ -69,7 +69,7 @@ uint64_t ToSpdyPingId(const Http2PingFields& ping) { // Overwrites the fields of the header with invalid values, for the purpose // of identifying reading of unset fields. Only takes effect for debug builds. -// In Address Sanatizer builds, it also marks the fields as un-readable. +// In Address Sanitizer builds, it also marks the fields as un-readable. #ifndef NDEBUG void CorruptFrameHeader(Http2FrameHeader* header) { // Beyond a valid payload length, which is 2^24 - 1. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_frame_decoder_adapter.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_frame_decoder_adapter.h new file mode 100644 index 0000000000..2fde7055bc --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_frame_decoder_adapter.h @@ -0,0 +1,566 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_HTTP2_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_ +#define QUICHE_HTTP2_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_ + +#include + +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" +#include "quiche/http2/core/spdy_protocol.h" +#include "quiche/http2/decoder/decode_status.h" +#include "quiche/http2/decoder/http2_frame_decoder.h" +#include "quiche/http2/decoder/http2_frame_decoder_listener.h" +#include "quiche/http2/http2_constants.h" +#include "quiche/http2/http2_structures.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/spdy/core/hpack/hpack_decoder_adapter.h" + +namespace spdy { + +class SpdyFramerVisitorInterface; +class ExtensionVisitorInterface; + +} // namespace spdy + +// TODO(dahollings): Perform various renames/moves suggested in cl/164660364. + +namespace http2 { + +// Adapts SpdyFramer interface to use Http2FrameDecoder. +class QUICHE_EXPORT Http2DecoderAdapter + : public http2::Http2FrameDecoderListener { + public: + // HTTP2 states. + enum SpdyState { + SPDY_ERROR, + SPDY_READY_FOR_FRAME, // Framer is ready for reading the next frame. + SPDY_FRAME_COMPLETE, // Framer has finished reading a frame, need to reset. + SPDY_READING_COMMON_HEADER, + SPDY_CONTROL_FRAME_PAYLOAD, + SPDY_READ_DATA_FRAME_PADDING_LENGTH, + SPDY_CONSUME_PADDING, + SPDY_IGNORE_REMAINING_PAYLOAD, + SPDY_FORWARD_STREAM_FRAME, + SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, + SPDY_CONTROL_FRAME_HEADER_BLOCK, + SPDY_GOAWAY_FRAME_PAYLOAD, + SPDY_SETTINGS_FRAME_HEADER, + SPDY_SETTINGS_FRAME_PAYLOAD, + SPDY_ALTSVC_FRAME_PAYLOAD, + SPDY_EXTENSION_FRAME_PAYLOAD, + }; + + // Framer error codes. + enum SpdyFramerError { + SPDY_NO_ERROR, + SPDY_INVALID_STREAM_ID, // Stream ID is invalid + SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted. + SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large. + SPDY_DECOMPRESS_FAILURE, // There was an error decompressing. + SPDY_INVALID_PADDING, // HEADERS or DATA frame padding invalid + SPDY_INVALID_DATA_FRAME_FLAGS, // Data frame has invalid flags. + SPDY_UNEXPECTED_FRAME, // Frame received out of order. + SPDY_INTERNAL_FRAMER_ERROR, // SpdyFramer was used incorrectly. + SPDY_INVALID_CONTROL_FRAME_SIZE, // Control frame not sized to spec + SPDY_OVERSIZED_PAYLOAD, // Payload size was too large + + // HttpDecoder or HttpDecoderAdapter error. + // See HpackDecodingError for description of each error code. + SPDY_HPACK_INDEX_VARINT_ERROR, + SPDY_HPACK_NAME_LENGTH_VARINT_ERROR, + SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR, + SPDY_HPACK_NAME_TOO_LONG, + SPDY_HPACK_VALUE_TOO_LONG, + SPDY_HPACK_NAME_HUFFMAN_ERROR, + SPDY_HPACK_VALUE_HUFFMAN_ERROR, + SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE, + SPDY_HPACK_INVALID_INDEX, + SPDY_HPACK_INVALID_NAME_INDEX, + SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED, + SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK, + SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING, + SPDY_HPACK_TRUNCATED_BLOCK, + SPDY_HPACK_FRAGMENT_TOO_LONG, + SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT, + + // Set if the visitor no longer wishes to receive events for this + // connection. + SPDY_STOP_PROCESSING, + + LAST_ERROR, // Must be the last entry in the enum. + }; + + // For debugging. + static const char* StateToString(int state); + static const char* SpdyFramerErrorToString(SpdyFramerError spdy_framer_error); + + Http2DecoderAdapter(); + ~Http2DecoderAdapter() override; + + Http2DecoderAdapter(const Http2DecoderAdapter&) = delete; + Http2DecoderAdapter& operator=(const Http2DecoderAdapter&) = delete; + + // Set callbacks to be called from the framer. A visitor must be set, or + // else the framer will likely crash. It is acceptable for the visitor + // to do nothing. If this is called multiple times, only the last visitor + // will be used. + void set_visitor(spdy::SpdyFramerVisitorInterface* visitor); + spdy::SpdyFramerVisitorInterface* visitor() const { return visitor_; } + + // Set extension callbacks to be called from the framer or decoder. Optional. + // If called multiple times, only the last visitor will be used. + void set_extension_visitor(spdy::ExtensionVisitorInterface* visitor); + spdy::ExtensionVisitorInterface* extension_visitor() const { + return extension_; + } + + // Set debug callbacks to be called from the framer. The debug visitor is + // completely optional and need not be set in order for normal operation. + // If this is called multiple times, only the last visitor will be used. + void set_debug_visitor(spdy::SpdyFramerDebugVisitorInterface* debug_visitor); + spdy::SpdyFramerDebugVisitorInterface* debug_visitor() const { + return debug_visitor_; + } + + // Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns + // the number of bytes consumed. It is safe to pass more bytes in than + // may be consumed. Should process (or otherwise buffer) as much as + // available. + // + // If the input contains the entirety of a DATA frame payload, GOAWAY frame + // Additional Debug Data field, or unknown frame payload, then the + // corresponding SpdyFramerVisitorInterface::OnStreamFrameData(), + // OnGoAwayFrameData(), or ExtensionVisitorInterface::OnFramePayload() method + // is guaranteed to be called exactly once, with the entire payload or field. + size_t ProcessInput(const char* data, size_t len); + + // Current state of the decoder. + SpdyState state() const; + + // Current error code (NO_ERROR if state != ERROR). + SpdyFramerError spdy_framer_error() const; + + // Has any frame header looked like the start of an HTTP/1.1 (or earlier) + // response? Used to detect if a backend/server that we sent a request to + // has responded with an HTTP/1.1 (or earlier) response. + bool probable_http_response() const; + + spdy::HpackDecoderAdapter& GetHpackDecoder() { return hpack_decoder_; } + const spdy::HpackDecoderAdapter& GetHpackDecoder() const { + return hpack_decoder_; + } + + bool HasError() const; + + // A visitor may call this method to indicate it no longer wishes to receive + // events for this connection. + void StopProcessing(); + + // Sets the limit on the size of received HTTP/2 frame payloads. Corresponds + // to SETTINGS_MAX_FRAME_SIZE as advertised to the peer. + void SetMaxFrameSize(size_t max_frame_size); + + private: + bool OnFrameHeader(const Http2FrameHeader& header) override; + void OnDataStart(const Http2FrameHeader& header) override; + void OnDataPayload(const char* data, size_t len) override; + void OnDataEnd() override; + void OnHeadersStart(const Http2FrameHeader& header) override; + void OnHeadersPriority(const Http2PriorityFields& priority) override; + void OnHpackFragment(const char* data, size_t len) override; + void OnHeadersEnd() override; + void OnPriorityFrame(const Http2FrameHeader& header, + const Http2PriorityFields& priority) override; + void OnContinuationStart(const Http2FrameHeader& header) override; + void OnContinuationEnd() override; + void OnPadLength(size_t trailing_length) override; + void OnPadding(const char* padding, size_t skipped_length) override; + void OnRstStream(const Http2FrameHeader& header, + Http2ErrorCode http2_error_code) override; + void OnSettingsStart(const Http2FrameHeader& header) override; + void OnSetting(const Http2SettingFields& setting_fields) override; + void OnSettingsEnd() override; + void OnSettingsAck(const Http2FrameHeader& header) override; + void OnPushPromiseStart(const Http2FrameHeader& header, + const Http2PushPromiseFields& promise, + size_t total_padding_length) override; + void OnPushPromiseEnd() override; + void OnPing(const Http2FrameHeader& header, + const Http2PingFields& ping) override; + void OnPingAck(const Http2FrameHeader& header, + const Http2PingFields& ping) override; + void OnGoAwayStart(const Http2FrameHeader& header, + const Http2GoAwayFields& goaway) override; + void OnGoAwayOpaqueData(const char* data, size_t len) override; + void OnGoAwayEnd() override; + void OnWindowUpdate(const Http2FrameHeader& header, + uint32_t increment) override; + void OnAltSvcStart(const Http2FrameHeader& header, size_t origin_length, + size_t value_length) override; + void OnAltSvcOriginData(const char* data, size_t len) override; + void OnAltSvcValueData(const char* data, size_t len) override; + void OnAltSvcEnd() override; + void OnPriorityUpdateStart( + const Http2FrameHeader& header, + const Http2PriorityUpdateFields& priority_update) override; + void OnPriorityUpdatePayload(const char* data, size_t len) override; + void OnPriorityUpdateEnd() override; + void OnUnknownStart(const Http2FrameHeader& header) override; + void OnUnknownPayload(const char* data, size_t len) override; + void OnUnknownEnd() override; + void OnPaddingTooLong(const Http2FrameHeader& header, + size_t missing_length) override; + void OnFrameSizeError(const Http2FrameHeader& header) override; + + size_t ProcessInputFrame(const char* data, size_t len); + + void DetermineSpdyState(DecodeStatus status); + void ResetBetweenFrames(); + + void set_spdy_state(SpdyState v); + + void SetSpdyErrorAndNotify(SpdyFramerError error, std::string detailed_error); + + const Http2FrameHeader& frame_header() const; + + uint32_t stream_id() const; + Http2FrameType frame_type() const; + + size_t remaining_total_payload() const; + + bool IsReadingPaddingLength(); + bool IsSkippingPadding(); + bool IsDiscardingPayload(); + // Called from OnXyz or OnXyzStart methods to decide whether it is OK to + // handle the callback. + bool IsOkToStartFrame(const Http2FrameHeader& header); + bool HasRequiredStreamId(uint32_t stream_id); + + bool HasRequiredStreamId(const Http2FrameHeader& header); + + bool HasRequiredStreamIdZero(uint32_t stream_id); + + bool HasRequiredStreamIdZero(const Http2FrameHeader& header); + + void ReportReceiveCompressedFrame(const Http2FrameHeader& header); + + void CommonStartHpackBlock(); + + // SpdyFramer calls HandleControlFrameHeadersData even if there are zero + // fragment bytes in the first frame, so do the same. + void MaybeAnnounceEmptyFirstHpackFragment(); + void CommonHpackFragmentEnd(); + + // The most recently decoded frame header; invalid after we reached the end + // of that frame. + Http2FrameHeader frame_header_; + + // If decoding an HPACK block that is split across multiple frames, this holds + // the frame header of the HEADERS or PUSH_PROMISE that started the block. + Http2FrameHeader hpack_first_frame_header_; + + // Amount of trailing padding. Currently used just as an indicator of whether + // OnPadLength has been called. + std::optional opt_pad_length_; + + // Temporary buffers for the AltSvc fields. + std::string alt_svc_origin_; + std::string alt_svc_value_; + + // Temporary buffers for PRIORITY_UPDATE fields. + uint32_t prioritized_stream_id_ = 0; + std::string priority_field_value_; + + // Listener used if we transition to an error state; the listener ignores all + // the callbacks. + Http2FrameDecoderNoOpListener no_op_listener_; + + spdy::SpdyFramerVisitorInterface* visitor_ = nullptr; + spdy::SpdyFramerDebugVisitorInterface* debug_visitor_ = nullptr; + + // If non-null, unknown frames and settings are passed to the extension. + spdy::ExtensionVisitorInterface* extension_ = nullptr; + + // The HPACK decoder to be used for this adapter. + spdy::HpackDecoderAdapter hpack_decoder_; + + // The HTTP/2 frame decoder. + Http2FrameDecoder frame_decoder_; + + // Next frame type expected. Currently only used for CONTINUATION frames, + // but could be used for detecting whether the first frame is a SETTINGS + // frame. + // TODO(jamessynge): Provide means to indicate that decoder should require + // SETTINGS frame as the first frame. + Http2FrameType expected_frame_type_; + + // Attempt to duplicate the SpdyState and SpdyFramerError values that + // SpdyFramer sets. Values determined by getting tests to pass. + SpdyState spdy_state_ = SpdyState::SPDY_READY_FOR_FRAME; + SpdyFramerError spdy_framer_error_ = SpdyFramerError::SPDY_NO_ERROR; + + // The limit on the size of received HTTP/2 payloads as specified in the + // SETTINGS_MAX_FRAME_SIZE advertised to peer. + size_t max_frame_size_ = spdy::kHttp2DefaultFramePayloadLimit; + + // Has OnFrameHeader been called? + bool decoded_frame_header_ = false; + + // Have we recorded an Http2FrameHeader for the current frame? + // We only do so if the decoder will make multiple callbacks for + // the frame; for example, for PING frames we don't make record + // the frame header, but for ALTSVC we do. + bool has_frame_header_ = false; + + // Have we recorded an Http2FrameHeader for the current HPACK block? + // True only for multi-frame HPACK blocks. + bool has_hpack_first_frame_header_ = false; + + // Has OnHeaders() already been called for current HEADERS block? Only + // meaningful between OnHeadersStart and OnHeadersPriority. + bool on_headers_called_ = false; + + // Has OnHpackFragment() already been called for current HPACK block? + // SpdyFramer will pass an empty buffer to the HPACK decoder if a HEADERS + // or PUSH_PROMISE has no HPACK data in it (e.g. a HEADERS frame with only + // padding). Detect that condition and replicate the behavior using this + // field. + bool on_hpack_fragment_called_ = false; + + // Have we seen a frame header that appears to be an HTTP/1 response? + bool latched_probable_http_response_ = false; + + // Is expected_frame_type_ set? + bool has_expected_frame_type_ = false; + + // Is the current frame payload destined for |extension_|? + bool handling_extension_payload_ = false; +}; + +} // namespace http2 + +namespace spdy { + +// Http2DecoderAdapter will use the given visitor implementing this +// interface to deliver event callbacks as frames are decoded. +// +// Control frames that contain HTTP2 header blocks (HEADER, and PUSH_PROMISE) +// are processed in fashion that allows the decompressed header block to be +// delivered in chunks to the visitor. +// The following steps are followed: +// 1. OnHeaders, or OnPushPromise is called. +// 2. OnHeaderFrameStart is called; visitor is expected to return an instance +// of SpdyHeadersHandlerInterface that will receive the header key-value +// pairs. +// 3. OnHeaderFrameEnd is called, indicating that the full header block has +// been delivered for the control frame. +// During step 2, if the visitor is not interested in accepting the header data, +// it should return a no-op implementation of SpdyHeadersHandlerInterface. +class QUICHE_EXPORT SpdyFramerVisitorInterface { + public: + virtual ~SpdyFramerVisitorInterface() {} + + // Called if an error is detected in the SpdyFrame protocol. + virtual void OnError(http2::Http2DecoderAdapter::SpdyFramerError error, + std::string detailed_error) = 0; + + // Called when the common header for a frame is received. Validating the + // common header occurs in later processing. + virtual void OnCommonHeader(SpdyStreamId /*stream_id*/, size_t /*length*/, + uint8_t /*type*/, uint8_t /*flags*/) {} + + // Called when a data frame header is received. The frame's data payload will + // be provided via subsequent calls to OnStreamFrameData(). + // |stream_id| The stream receiving data. + // |length| The length of the payload in this DATA frame. Includes the length + // of the data itself and potential padding. + // |fin| Whether the END_STREAM flag is set in the frame header. + virtual void OnDataFrameHeader(SpdyStreamId stream_id, size_t length, + bool fin) = 0; + + // Called when data is received. + // |stream_id| The stream receiving data. + // |data| A buffer containing the data received. + // |len| The length of the data buffer. + virtual void OnStreamFrameData(SpdyStreamId stream_id, const char* data, + size_t len) = 0; + + // Called when the other side has finished sending data on this stream. + // |stream_id| The stream that was receiving data. + virtual void OnStreamEnd(SpdyStreamId stream_id) = 0; + + // Called when padding length field is received on a DATA frame. + // |stream_id| The stream receiving data. + // |value| The value of the padding length field. + virtual void OnStreamPadLength(SpdyStreamId /*stream_id*/, size_t /*value*/) { + } + + // Called when padding is received (the trailing octets, not pad_len field) on + // a DATA frame. + // |stream_id| The stream receiving data. + // |len| The number of padding octets. + virtual void OnStreamPadding(SpdyStreamId stream_id, size_t len) = 0; + + // Called just before processing the payload of a frame containing header + // data. Should return an implementation of SpdyHeadersHandlerInterface that + // will receive headers for stream |stream_id|. The caller will not take + // ownership of the headers handler. The same instance should remain live + // and be returned for all header frames comprising a logical header block + // (i.e. until OnHeaderFrameEnd() is called). + virtual SpdyHeadersHandlerInterface* OnHeaderFrameStart( + SpdyStreamId stream_id) = 0; + + // Called after processing the payload of a frame containing header data. + virtual void OnHeaderFrameEnd(SpdyStreamId stream_id) = 0; + + // Called when a RST_STREAM frame has been parsed. + virtual void OnRstStream(SpdyStreamId stream_id, + SpdyErrorCode error_code) = 0; + + // Called when a SETTINGS frame is received. + virtual void OnSettings() {} + + // Called when a complete setting within a SETTINGS frame has been parsed. + // Note that |id| may or may not be a SETTINGS ID defined in the HTTP/2 spec. + virtual void OnSetting(SpdySettingsId id, uint32_t value) = 0; + + // Called when a SETTINGS frame is received with the ACK flag set. + virtual void OnSettingsAck() {} + + // Called before and after parsing SETTINGS id and value tuples. + virtual void OnSettingsEnd() = 0; + + // Called when a PING frame has been parsed. + virtual void OnPing(SpdyPingId unique_id, bool is_ack) = 0; + + // Called when a GOAWAY frame has been parsed. + virtual void OnGoAway(SpdyStreamId last_accepted_stream_id, + SpdyErrorCode error_code) = 0; + + // Called when a HEADERS frame is received. + // Note that header block data is not included. See OnHeaderFrameStart(). + // |stream_id| The stream receiving the header. + // |payload_length| The length of the payload in this HEADERS frame. Includes + // the length of the encoded header block and potential padding. + // |has_priority| Whether or not the headers frame included a priority value, + // and stream dependency info. + // |weight| If |has_priority| is true, then weight (in the range [1, 256]) + // for the receiving stream, otherwise 0. + // |parent_stream_id| If |has_priority| is true the parent stream of the + // receiving stream, else 0. + // |exclusive| If |has_priority| is true the exclusivity of dependence on the + // parent stream, else false. + // |fin| Whether the END_STREAM flag is set in the frame header. + // |end| False if HEADERs frame is to be followed by a CONTINUATION frame, + // or true if not. + virtual void OnHeaders(SpdyStreamId stream_id, size_t payload_length, + bool has_priority, int weight, + SpdyStreamId parent_stream_id, bool exclusive, + bool fin, bool end) = 0; + + // Called when a WINDOW_UPDATE frame has been parsed. + virtual void OnWindowUpdate(SpdyStreamId stream_id, + int delta_window_size) = 0; + + // Called when a goaway frame opaque data is available. + // |goaway_data| A buffer containing the opaque GOAWAY data chunk received. + // |len| The length of the header data buffer. A length of zero indicates + // that the header data block has been completely sent. + // When this function returns true the visitor indicates that it accepted + // all of the data. Returning false indicates that that an error has + // occurred while processing the data. Default implementation returns true. + virtual bool OnGoAwayFrameData(const char* goaway_data, size_t len); + + // Called when a PUSH_PROMISE frame is received. + // Note that header block data is not included. See OnHeaderFrameStart(). + virtual void OnPushPromise(SpdyStreamId stream_id, + SpdyStreamId promised_stream_id, bool end) = 0; + + // Called when a CONTINUATION frame is received. + // Note that header block data is not included. See OnHeaderFrameStart(). + // |stream_id| The stream receiving the CONTINUATION. + // |payload_length| The length of the payload in this CONTINUATION frame. + // |end| True if this CONTINUATION frame will not be followed by another + // CONTINUATION frame. + virtual void OnContinuation(SpdyStreamId stream_id, size_t payload_length, + bool end) = 0; + + // Called when an ALTSVC frame has been parsed. + virtual void OnAltSvc( + SpdyStreamId /*stream_id*/, absl::string_view /*origin*/, + const SpdyAltSvcWireFormat::AlternativeServiceVector& /*altsvc_vector*/) { + } + + // Called when a PRIORITY frame is received. + // |stream_id| The stream to update the priority of. + // |parent_stream_id| The parent stream of |stream_id|. + // |weight| Stream weight, in the range [1, 256]. + // |exclusive| Whether |stream_id| should be an only child of + // |parent_stream_id|. + virtual void OnPriority(SpdyStreamId stream_id, SpdyStreamId parent_stream_id, + int weight, bool exclusive) = 0; + + // Called when a PRIORITY_UPDATE frame is received on stream 0. + // |prioritized_stream_id| is the Prioritized Stream ID and + // |priority_field_value| is the Priority Field Value + // parsed from the frame payload. + virtual void OnPriorityUpdate(SpdyStreamId prioritized_stream_id, + absl::string_view priority_field_value) = 0; + + // Called when a frame type we don't recognize is received. + // Return true if this appears to be a valid extension frame, false otherwise. + // We distinguish between extension frames and nonsense by checking + // whether the stream id is valid. + // TODO(b/239060116): Remove this callback altogether. + virtual bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) = 0; + + // Called when the common header for a non-standard frame is received. If the + // `length` is nonzero, the frame's payload will be provided via subsequent + // calls to OnUnknownFramePayload(). + // |stream_id| The stream receiving the non-standard frame. + // |length| The length of the payload of the frame. + // |type| The type of the frame. This type is non-standard. + // |flags| The flags of the frame. + virtual void OnUnknownFrameStart(SpdyStreamId stream_id, size_t length, + uint8_t type, uint8_t flags) = 0; + + // Called when a non-empty payload chunk for a non-standard frame is received. + // The payload for a single frame may be delivered as multiple calls to + // OnUnknownFramePayload(). Since the length field is passed in + // OnUnknownFrameStart(), there is no explicit indication of the end of the + // frame payload. + // |stream_id| The stream receiving the non-standard frame. + // |payload| The payload chunk, which will be non-empty. + virtual void OnUnknownFramePayload(SpdyStreamId stream_id, + absl::string_view payload) = 0; +}; + +class QUICHE_EXPORT ExtensionVisitorInterface { + public: + virtual ~ExtensionVisitorInterface() {} + + // Called when non-standard SETTINGS are received. + virtual void OnSetting(SpdySettingsId id, uint32_t value) = 0; + + // Called when non-standard frames are received. + virtual bool OnFrameHeader(SpdyStreamId stream_id, size_t length, + uint8_t type, uint8_t flags) = 0; + + // The payload for a single frame may be delivered as multiple calls to + // OnFramePayload. Since the length field is passed in OnFrameHeader, there is + // no explicit indication of the end of the frame payload. + virtual void OnFramePayload(const char* data, size_t len) = 0; +}; + +} // namespace spdy + +#endif // QUICHE_HTTP2_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_header_block_hpack_listener.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_header_block_hpack_listener.h similarity index 71% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_header_block_hpack_listener.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_header_block_hpack_listener.h index b5cc0ee08d..07cdba4f5c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_header_block_hpack_listener.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_header_block_hpack_listener.h @@ -1,19 +1,19 @@ -#ifndef QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_ -#define QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_ +#ifndef QUICHE_HTTP2_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_ +#define QUICHE_HTTP2_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_ #include #include #include "absl/strings/string_view.h" #include "quiche/http2/hpack/decoder/hpack_decoder_listener.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/http2_header_block.h" namespace spdy { // This class simply gathers the key-value pairs emitted by an HpackDecoder in -// a Http2HeaderBlock. +// a quiche::HttpHeaderBlock. class QUICHE_EXPORT Http2HeaderBlockHpackListener : public http2::HpackDecoderListener { public: @@ -35,18 +35,18 @@ class QUICHE_EXPORT Http2HeaderBlockHpackListener hpack_error_ = true; } - Http2HeaderBlock release_header_block() { - Http2HeaderBlock block = std::move(header_block_); + quiche::HttpHeaderBlock release_header_block() { + quiche::HttpHeaderBlock block = std::move(header_block_); header_block_ = {}; return block; } bool hpack_error() const { return hpack_error_; } private: - Http2HeaderBlock header_block_; + quiche::HttpHeaderBlock header_block_; bool hpack_error_ = false; }; } // namespace spdy -#endif // QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_ +#endif // QUICHE_HTTP2_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.cc index 30988a9248..4a08864e0f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.cc @@ -8,11 +8,11 @@ #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_protocol.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_callbacks.h" -#include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/spdy_protocol.h" // Convenience macros for printing function arguments in log lines in the // format arg_name=value. @@ -64,7 +64,7 @@ auto LogContainer(const T& container, ItemLogger item_logger) namespace http2 { -using spdy::Http2HeaderBlock; +using quiche::HttpHeaderBlock; using spdy::SettingsMap; using spdy::SpdyAltSvcIR; using spdy::SpdyContinuationIR; @@ -82,10 +82,10 @@ using spdy::SpdyWindowUpdateIR; namespace { -// Defines how elements of Http2HeaderBlocks are logged. +// Defines how elements of HttpHeaderBlocks are logged. struct LogHeaderBlockEntry { void Log(std::ostream& out, - const Http2HeaderBlock::value_type& entry) const { // NOLINT + const HttpHeaderBlock::value_type& entry) const { // NOLINT out << "\"" << entry.first << "\": \"" << entry.second << "\""; } }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.h index 7106a72e4a..1d11ac39ac 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.h @@ -8,13 +8,13 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/http2_frame_decoder_adapter.h" +#include "quiche/http2/core/recording_headers_handler.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" +#include "quiche/http2/core/spdy_protocol.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_callbacks.h" -#include "quiche/spdy/core/http2_frame_decoder_adapter.h" -#include "quiche/spdy/core/recording_headers_handler.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" -#include "quiche/spdy/core/spdy_protocol.h" // Logging macro to use for all HTTP/2 trace logging. Iff trace logging is // enabled, logs at level INFO with a common prefix prepended (to facilitate diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/no_op_headers_handler.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/no_op_headers_handler.h similarity index 79% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/no_op_headers_handler.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/no_op_headers_handler.h index a4796e9dbb..84244caab3 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/no_op_headers_handler.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/no_op_headers_handler.h @@ -1,12 +1,12 @@ -#ifndef QUICHE_SPDY_CORE_NO_OP_HEADERS_HANDLER_H_ -#define QUICHE_SPDY_CORE_NO_OP_HEADERS_HANDLER_H_ +#ifndef QUICHE_HTTP2_CORE_NO_OP_HEADERS_HANDLER_H_ +#define QUICHE_HTTP2_CORE_NO_OP_HEADERS_HANDLER_H_ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/header_byte_listener_interface.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/header_byte_listener_interface.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" namespace spdy { @@ -38,4 +38,4 @@ class QUICHE_EXPORT NoOpHeadersHandler : public SpdyHeadersHandlerInterface { } // namespace spdy -#endif // QUICHE_SPDY_CORE_NO_OP_HEADERS_HANDLER_H_ +#endif // QUICHE_HTTP2_CORE_NO_OP_HEADERS_HANDLER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/priority_write_scheduler.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/priority_write_scheduler.h index 0e33111a9f..7cab89347c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/priority_write_scheduler.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/priority_write_scheduler.h @@ -18,11 +18,11 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/str_cat.h" #include "absl/time/time.h" +#include "quiche/http2/core/spdy_protocol.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_circular_deque.h" -#include "quiche/spdy/core/spdy_protocol.h" namespace http2 { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/recording_headers_handler.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/recording_headers_handler.cc similarity index 90% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/recording_headers_handler.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/recording_headers_handler.cc index a1b0643d74..5285c7bc63 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/recording_headers_handler.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/recording_headers_handler.cc @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/recording_headers_handler.h" +#include "quiche/http2/core/recording_headers_handler.h" #include #include "absl/strings/string_view.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/recording_headers_handler.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/recording_headers_handler.h similarity index 77% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/recording_headers_handler.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/recording_headers_handler.h index c33a4cef9b..46f054442f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/recording_headers_handler.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/recording_headers_handler.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_RECORDING_HEADERS_HANDLER_H_ -#define QUICHE_SPDY_CORE_RECORDING_HEADERS_HANDLER_H_ +#ifndef QUICHE_HTTP2_CORE_RECORDING_HEADERS_HANDLER_H_ +#define QUICHE_HTTP2_CORE_RECORDING_HEADERS_HANDLER_H_ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" namespace spdy { @@ -31,7 +31,7 @@ class QUICHE_EXPORT RecordingHeadersHandler void OnHeaderBlockEnd(size_t uncompressed_header_bytes, size_t compressed_header_bytes) override; - const Http2HeaderBlock& decoded_block() const { return block_; } + const quiche::HttpHeaderBlock& decoded_block() const { return block_; } size_t uncompressed_header_bytes() const { return uncompressed_header_bytes_; } @@ -39,11 +39,11 @@ class QUICHE_EXPORT RecordingHeadersHandler private: SpdyHeadersHandlerInterface* wrapped_ = nullptr; - Http2HeaderBlock block_; + quiche::HttpHeaderBlock block_; size_t uncompressed_header_bytes_ = 0; size_t compressed_header_bytes_ = 0; }; } // namespace spdy -#endif // QUICHE_SPDY_CORE_RECORDING_HEADERS_HANDLER_H_ +#endif // QUICHE_HTTP2_CORE_RECORDING_HEADERS_HANDLER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_alt_svc_wire_format.cc similarity index 99% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_alt_svc_wire_format.cc index 7981975af5..422e1ab6bd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_alt_svc_wire_format.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/spdy_alt_svc_wire_format.h" +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" #include #include diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_alt_svc_wire_format.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_alt_svc_wire_format.h new file mode 100644 index 0000000000..3d57b504ee --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_alt_svc_wire_format.h @@ -0,0 +1,104 @@ +// Copyright (c) 2015 The Chromium 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 data structures and utility functions used for serializing +// and parsing alternative service header values, common to HTTP/1.1 header +// fields and HTTP/2 and QUIC ALTSVC frames. See specification at +// https://httpwg.github.io/http-extensions/alt-svc.html. + +#ifndef QUICHE_HTTP2_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_ +#define QUICHE_HTTP2_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_ + +#include +#include +#include + +#include "absl/container/inlined_vector.h" +#include "absl/strings/string_view.h" +#include "quiche/common/platform/api/quiche_export.h" + +namespace spdy { + +namespace test { +class SpdyAltSvcWireFormatPeer; +} // namespace test + +class QUICHE_EXPORT SpdyAltSvcWireFormat { + public: + using VersionVector = absl::InlinedVector; + + struct QUICHE_EXPORT AlternativeService { + std::string protocol_id; + std::string host; + + // Default is 0: invalid port. + uint16_t port = 0; + // Default is one day. + uint32_t max_age_seconds = 86400; + // Default is empty: unspecified version. + VersionVector version; + + AlternativeService(); + AlternativeService(const std::string& protocol_id, const std::string& host, + uint16_t port, uint32_t max_age_seconds, + VersionVector version); + AlternativeService(const AlternativeService& other); + ~AlternativeService(); + + bool operator==(const AlternativeService& other) const { + return protocol_id == other.protocol_id && host == other.host && + port == other.port && version == other.version && + max_age_seconds == other.max_age_seconds; + } + }; + // An empty vector means alternative services should be cleared for given + // origin. Note that the wire format for this is the string "clear", not an + // empty value (which is invalid). + typedef std::vector AlternativeServiceVector; + + friend class test::SpdyAltSvcWireFormatPeer; + static bool ParseHeaderFieldValue(absl::string_view value, + AlternativeServiceVector* altsvc_vector); + static std::string SerializeHeaderFieldValue( + const AlternativeServiceVector& altsvc_vector); + + private: + // Forward |*c| over space and tab or until |end| is reached. + static void SkipWhiteSpace(absl::string_view::const_iterator* c, + absl::string_view::const_iterator end); + // Decode percent-decoded string between |c| and |end| into |*output|. + // Return true on success, false if input is invalid. + static bool PercentDecode(absl::string_view::const_iterator c, + absl::string_view::const_iterator end, + std::string* output); + // Parse the authority part of Alt-Svc between |c| and |end| into |*host| and + // |*port|. Return true on success, false if input is invalid. + static bool ParseAltAuthority(absl::string_view::const_iterator c, + absl::string_view::const_iterator end, + std::string* host, uint16_t* port); + // Parse a positive integer between |c| and |end| into |*value|. + // Return true on success, false if input is not a positive integer or it + // cannot be represented on uint16_t. + static bool ParsePositiveInteger16(absl::string_view::const_iterator c, + absl::string_view::const_iterator end, + uint16_t* value); + // Parse a positive integer between |c| and |end| into |*value|. + // Return true on success, false if input is not a positive integer or it + // cannot be represented on uint32_t. + static bool ParsePositiveInteger32(absl::string_view::const_iterator c, + absl::string_view::const_iterator end, + uint32_t* value); + // Parse |c| as hexadecimal digit, case insensitive. |c| must be [0-9a-fA-F]. + // Output is between 0 and 15. + static char HexDigitToInt(char c); + // Parse |data| as hexadecimal number into |*value|. |data| must only contain + // hexadecimal digits, no "0x" prefix. + // Return true on success, false if input is empty, not valid hexadecimal + // number, or cannot be represented on uint32_t. + static bool HexDecodeToUInt32(absl::string_view data, uint32_t* value); +}; + +} // namespace spdy + +#endif // QUICHE_HTTP2_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_bitmasks.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_bitmasks.h new file mode 100644 index 0000000000..8da227cbb7 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_bitmasks.h @@ -0,0 +1,18 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_HTTP2_CORE_SPDY_BITMASKS_H_ +#define QUICHE_HTTP2_CORE_SPDY_BITMASKS_H_ + +namespace spdy { + +// StreamId mask from the SpdyHeader +inline constexpr unsigned int kStreamIdMask = 0x7fffffff; + +// Mask the lower 24 bits. +inline constexpr unsigned int kLengthMask = 0xffffff; + +} // namespace spdy + +#endif // QUICHE_HTTP2_CORE_SPDY_BITMASKS_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_frame_builder.cc similarity index 96% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_frame_builder.cc index 30a9ddc6c4..cec9f4db42 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_frame_builder.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/spdy_frame_builder.h" +#include "quiche/http2/core/spdy_frame_builder.h" #include #include @@ -10,11 +10,11 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_bitmasks.h" +#include "quiche/http2/core/spdy_protocol.h" +#include "quiche/http2/core/zero_copy_output_buffer.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/spdy_bitmasks.h" -#include "quiche/spdy/core/spdy_protocol.h" -#include "quiche/spdy/core/zero_copy_output_buffer.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_frame_builder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_frame_builder.h new file mode 100644 index 0000000000..ee879a4fa3 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_frame_builder.h @@ -0,0 +1,140 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_HTTP2_CORE_SPDY_FRAME_BUILDER_H_ +#define QUICHE_HTTP2_CORE_SPDY_FRAME_BUILDER_H_ + +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_protocol.h" +#include "quiche/http2/core/zero_copy_output_buffer.h" +#include "quiche/common/platform/api/quiche_bug_tracker.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/quiche_endian.h" + +namespace spdy { + +namespace test { +class SpdyFrameBuilderPeer; +} // namespace test + +// This class provides facilities for basic binary value packing +// into Spdy frames. +// +// The SpdyFrameBuilder supports appending primitive values (int, string, etc) +// to a frame instance. The SpdyFrameBuilder grows its internal memory buffer +// dynamically to hold the sequence of primitive values. The internal memory +// buffer is exposed as the "data" of the SpdyFrameBuilder. +class QUICHE_EXPORT SpdyFrameBuilder { + public: + // Initializes a SpdyFrameBuilder with a buffer of given size + explicit SpdyFrameBuilder(size_t size); + // Doesn't take ownership of output. + SpdyFrameBuilder(size_t size, ZeroCopyOutputBuffer* output); + + ~SpdyFrameBuilder(); + + // Returns the total size of the SpdyFrameBuilder's data, which may include + // multiple frames. + size_t length() const { return offset_ + length_; } + + // Seeks forward by the given number of bytes. Useful in conjunction with + // GetWriteableBuffer() above. + bool Seek(size_t length); + + // Populates this frame with a HTTP2 frame prefix using length information + // from |capacity_|. The given type must be a control frame type. + bool BeginNewFrame(SpdyFrameType type, uint8_t flags, SpdyStreamId stream_id); + + // Populates this frame with a HTTP2 frame prefix with type and length + // information. |type| must be a defined frame type. + bool BeginNewFrame(SpdyFrameType type, uint8_t flags, SpdyStreamId stream_id, + size_t length); + + // Populates this frame with a HTTP2 frame prefix with type and length + // information. |raw_frame_type| may be a defined or undefined frame type. + bool BeginNewUncheckedFrame(uint8_t raw_frame_type, uint8_t flags, + SpdyStreamId stream_id, size_t length); + + // Takes the buffer from the SpdyFrameBuilder. + SpdySerializedFrame take() { + QUICHE_BUG_IF(spdy_bug_39_1, output_ != nullptr) + << "ZeroCopyOutputBuffer is used to build " + << "frames. take() shouldn't be called"; + QUICHE_BUG_IF(spdy_bug_39_2, kMaxFrameSizeLimit < length_) + << "Frame length " << length_ + << " is longer than the maximum possible allowed length."; + SpdySerializedFrame rv(std::move(buffer_), length()); + capacity_ = 0; + length_ = 0; + offset_ = 0; + return rv; + } + + // Methods for adding to the payload. These values are appended to the end + // of the SpdyFrameBuilder payload. Note - binary integers are converted from + // host to network form. + bool WriteUInt8(uint8_t value) { return WriteBytes(&value, sizeof(value)); } + bool WriteUInt16(uint16_t value) { + value = quiche::QuicheEndian::HostToNet16(value); + return WriteBytes(&value, sizeof(value)); + } + bool WriteUInt24(uint32_t value) { + value = quiche::QuicheEndian::HostToNet32(value); + return WriteBytes(reinterpret_cast(&value) + 1, sizeof(value) - 1); + } + bool WriteUInt32(uint32_t value) { + value = quiche::QuicheEndian::HostToNet32(value); + return WriteBytes(&value, sizeof(value)); + } + bool WriteUInt64(uint64_t value) { + uint32_t upper = + quiche::QuicheEndian::HostToNet32(static_cast(value >> 32)); + uint32_t lower = + quiche::QuicheEndian::HostToNet32(static_cast(value)); + return (WriteBytes(&upper, sizeof(upper)) && + WriteBytes(&lower, sizeof(lower))); + } + bool WriteStringPiece32(const absl::string_view value); + bool WriteBytes(const void* data, uint32_t data_len); + + private: + friend class test::SpdyFrameBuilderPeer; + + // Populates this frame with a HTTP2 frame prefix with type and length + // information. + bool BeginNewFrameInternal(uint8_t raw_frame_type, uint8_t flags, + SpdyStreamId stream_id, size_t length); + + // Returns a writeable buffer of given size in bytes, to be appended to the + // currently written frame. Does bounds checking on length but does not + // increment the underlying iterator. To do so, consumers should subsequently + // call Seek(). + // In general, consumers should use Write*() calls instead of this. + // Returns NULL on failure. + char* GetWritableBuffer(size_t length); + char* GetWritableOutput(size_t desired_length, size_t* actual_length); + + // Checks to make sure that there is an appropriate amount of space for a + // write of given size, in bytes. + bool CanWrite(size_t length) const; + + // A buffer to be created whenever a new frame needs to be written. Used only + // if |output_| is nullptr. + std::unique_ptr buffer_; + // A pre-allocated buffer. If not-null, serialized frame data is written to + // this buffer. + ZeroCopyOutputBuffer* output_ = nullptr; // Does not own. + + size_t capacity_; // Allocation size of payload, set by constructor. + size_t length_; // Length of the latest frame in the buffer. + size_t offset_; // Position at which the latest frame begins. +}; + +} // namespace spdy + +#endif // QUICHE_HTTP2_CORE_SPDY_FRAME_BUILDER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_framer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_framer.cc similarity index 97% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_framer.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_framer.cc index 654641ab83..897e25322f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_framer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_framer.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/spdy_framer.h" +#include "quiche/http2/core/spdy_framer.h" #include #include @@ -13,15 +13,15 @@ #include "absl/base/attributes.h" #include "absl/memory/memory.h" +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" +#include "quiche/http2/core/spdy_frame_builder.h" +#include "quiche/http2/core/spdy_protocol.h" +#include "quiche/http2/core/zero_copy_output_buffer.h" +#include "quiche/http2/hpack/hpack_constants.h" +#include "quiche/http2/hpack/hpack_encoder.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/hpack/hpack_constants.h" -#include "quiche/spdy/core/hpack/hpack_encoder.h" #include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/spdy_alt_svc_wire_format.h" -#include "quiche/spdy/core/spdy_frame_builder.h" -#include "quiche/spdy/core/spdy_protocol.h" -#include "quiche/spdy/core/zero_copy_output_buffer.h" namespace spdy { @@ -289,8 +289,8 @@ SpdyFramer::SpdyFrameIterator::SpdyFrameIterator(SpdyFramer* framer) SpdyFramer::SpdyFrameIterator::~SpdyFrameIterator() = default; size_t SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) { - const SpdyFrameIR& frame_ir = GetIR(); - if (!has_next_frame_) { + const SpdyFrameIR* frame_ir = GetIR(); + if (!has_next_frame_ || frame_ir == nullptr) { QUICHE_BUG(spdy_bug_75_1) << "SpdyFramer::SpdyFrameIterator::NextFrame called without " << "a next frame."; @@ -304,13 +304,13 @@ size_t SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) { has_next_frame_ = encoder_->HasNext(); if (framer_->debug_visitor_ != nullptr) { - const auto& header_block_frame_ir = - static_cast(frame_ir); + const auto& frame_ref = + static_cast(*frame_ir); const size_t header_list_size = - GetUncompressedSerializedLength(header_block_frame_ir.header_block()); + GetUncompressedSerializedLength(frame_ref.header_block()); framer_->debug_visitor_->OnSendCompressedFrame( - frame_ir.stream_id(), - is_first_frame_ ? frame_ir.frame_type() : SpdyFrameType::CONTINUATION, + frame_ref.stream_id(), + is_first_frame_ ? frame_ref.frame_type() : SpdyFrameType::CONTINUATION, header_list_size, size_without_block + encoding.size()); } @@ -320,7 +320,7 @@ size_t SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) { is_first_frame_ = false; ok = SerializeGivenEncoding(encoding, output); } else { - SpdyContinuationIR continuation_ir(frame_ir.stream_id()); + SpdyContinuationIR continuation_ir(frame_ir->stream_id()); continuation_ir.take_encoding(std::move(encoding)); continuation_ir.set_end_headers(!has_next_frame_); ok = framer_->SerializeContinuation(continuation_ir, output); @@ -340,8 +340,8 @@ SpdyFramer::SpdyHeaderFrameIterator::SpdyHeaderFrameIterator( SpdyFramer::SpdyHeaderFrameIterator::~SpdyHeaderFrameIterator() = default; -const SpdyFrameIR& SpdyFramer::SpdyHeaderFrameIterator::GetIR() const { - return *headers_ir_; +const SpdyFrameIR* SpdyFramer::SpdyHeaderFrameIterator::GetIR() const { + return headers_ir_.get(); } size_t SpdyFramer::SpdyHeaderFrameIterator::GetFrameSizeSansBlock() const { @@ -364,8 +364,8 @@ SpdyFramer::SpdyPushPromiseFrameIterator::SpdyPushPromiseFrameIterator( SpdyFramer::SpdyPushPromiseFrameIterator::~SpdyPushPromiseFrameIterator() = default; -const SpdyFrameIR& SpdyFramer::SpdyPushPromiseFrameIterator::GetIR() const { - return *push_promise_ir_; +const SpdyFrameIR* SpdyFramer::SpdyPushPromiseFrameIterator::GetIR() const { + return push_promise_ir_.get(); } size_t SpdyFramer::SpdyPushPromiseFrameIterator::GetFrameSizeSansBlock() const { @@ -395,8 +395,8 @@ bool SpdyFramer::SpdyControlFrameIterator::HasNextFrame() const { return has_next_frame_; } -const SpdyFrameIR& SpdyFramer::SpdyControlFrameIterator::GetIR() const { - return *frame_ir_; +const SpdyFrameIR* SpdyFramer::SpdyControlFrameIterator::GetIR() const { + return frame_ir_.get(); } std::unique_ptr SpdyFramer::CreateIterator( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_framer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_framer.h new file mode 100644 index 0000000000..8d8ebec741 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_framer.h @@ -0,0 +1,371 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_HTTP2_CORE_SPDY_FRAMER_H_ +#define QUICHE_HTTP2_CORE_SPDY_FRAMER_H_ + +#include + +#include +#include +#include +#include + +#include "quiche/http2/core/spdy_protocol.h" +#include "quiche/http2/core/zero_copy_output_buffer.h" +#include "quiche/http2/hpack/hpack_encoder.h" +#include "quiche/common/platform/api/quiche_export.h" + +namespace spdy { + +namespace test { + +class SpdyFramerPeer; +class SpdyFramerTest_MultipleContinuationFramesWithIterator_Test; +class SpdyFramerTest_PushPromiseFramesWithIterator_Test; + +} // namespace test + +class QUICHE_EXPORT SpdyFrameSequence { + public: + virtual ~SpdyFrameSequence() {} + + // Serializes the next frame in the sequence to |output|. Returns the number + // of bytes written to |output|. + virtual size_t NextFrame(ZeroCopyOutputBuffer* output) = 0; + + // Returns true iff there is at least one more frame in the sequence. + virtual bool HasNextFrame() const = 0; + + // Get SpdyFrameIR of the frame to be serialized. + virtual const SpdyFrameIR* GetIR() const = 0; +}; + +class QUICHE_EXPORT SpdyFramer { + public: + enum CompressionOption { + ENABLE_COMPRESSION, + DISABLE_COMPRESSION, + }; + + // Create a SpdyFrameSequence to serialize |frame_ir|. + static std::unique_ptr CreateIterator( + SpdyFramer* framer, std::unique_ptr frame_ir); + + // Gets the serialized flags for the given |frame|. + static uint8_t GetSerializedFlags(const SpdyFrameIR& frame); + + // Serialize a data frame. + static SpdySerializedFrame SerializeData(const SpdyDataIR& data_ir); + // Serializes the data frame header and optionally padding length fields, + // excluding actual data payload and padding. + static SpdySerializedFrame SerializeDataFrameHeaderWithPaddingLengthField( + const SpdyDataIR& data_ir); + + // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE + // frame is used to implement per stream flow control. + static SpdySerializedFrame SerializeWindowUpdate( + const SpdyWindowUpdateIR& window_update); + + explicit SpdyFramer(CompressionOption option); + + virtual ~SpdyFramer(); + + // Set debug callbacks to be called from the framer. The debug visitor is + // completely optional and need not be set in order for normal operation. + // If this is called multiple times, only the last visitor will be used. + void set_debug_visitor(SpdyFramerDebugVisitorInterface* debug_visitor); + + SpdySerializedFrame SerializeRstStream( + const SpdyRstStreamIR& rst_stream) const; + + // Serializes a SETTINGS frame. The SETTINGS frame is + // used to communicate name/value pairs relevant to the communication channel. + SpdySerializedFrame SerializeSettings(const SpdySettingsIR& settings) const; + + // Serializes a PING frame. The unique_id is used to + // identify the ping request/response. + SpdySerializedFrame SerializePing(const SpdyPingIR& ping) const; + + // Serializes a GOAWAY frame. The GOAWAY frame is used + // prior to the shutting down of the TCP connection, and includes the + // stream_id of the last stream the sender of the frame is willing to process + // to completion. + SpdySerializedFrame SerializeGoAway(const SpdyGoAwayIR& goaway) const; + + // Serializes a HEADERS frame. The HEADERS frame is used + // for sending headers. + SpdySerializedFrame SerializeHeaders(const SpdyHeadersIR& headers); + + // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used + // to inform the client that it will be receiving an additional stream + // in response to the original request. The frame includes synthesized + // headers to explain the upcoming data. + SpdySerializedFrame SerializePushPromise( + const SpdyPushPromiseIR& push_promise); + + // Serializes a CONTINUATION frame. The CONTINUATION frame is used + // to continue a sequence of header block fragments. + SpdySerializedFrame SerializeContinuation( + const SpdyContinuationIR& continuation) const; + + // Serializes an ALTSVC frame. The ALTSVC frame advertises the + // availability of an alternative service to the client. + SpdySerializedFrame SerializeAltSvc(const SpdyAltSvcIR& altsvc); + + // Serializes a PRIORITY frame. The PRIORITY frame advises a change in + // the relative priority of the given stream. + SpdySerializedFrame SerializePriority(const SpdyPriorityIR& priority) const; + + // Serializes a PRIORITY_UPDATE frame. + // See https://httpwg.org/http-extensions/draft-ietf-httpbis-priority.html. + SpdySerializedFrame SerializePriorityUpdate( + const SpdyPriorityUpdateIR& priority_update) const; + + // Serializes an ACCEPT_CH frame. See + // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02. + SpdySerializedFrame SerializeAcceptCh(const SpdyAcceptChIR& accept_ch) const; + + // Serializes an unknown frame given a frame header and payload. + SpdySerializedFrame SerializeUnknown(const SpdyUnknownIR& unknown) const; + + // Serialize a frame of unknown type. + SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame); + + // Serialize a data frame. + bool SerializeData(const SpdyDataIR& data, + ZeroCopyOutputBuffer* output) const; + + // Serializes the data frame header and optionally padding length fields, + // excluding actual data payload and padding. + bool SerializeDataFrameHeaderWithPaddingLengthField( + const SpdyDataIR& data, ZeroCopyOutputBuffer* output) const; + + bool SerializeRstStream(const SpdyRstStreamIR& rst_stream, + ZeroCopyOutputBuffer* output) const; + + // Serializes a SETTINGS frame. The SETTINGS frame is + // used to communicate name/value pairs relevant to the communication channel. + bool SerializeSettings(const SpdySettingsIR& settings, + ZeroCopyOutputBuffer* output) const; + + // Serializes a PING frame. The unique_id is used to + // identify the ping request/response. + bool SerializePing(const SpdyPingIR& ping, + ZeroCopyOutputBuffer* output) const; + + // Serializes a GOAWAY frame. The GOAWAY frame is used + // prior to the shutting down of the TCP connection, and includes the + // stream_id of the last stream the sender of the frame is willing to process + // to completion. + bool SerializeGoAway(const SpdyGoAwayIR& goaway, + ZeroCopyOutputBuffer* output) const; + + // Serializes a HEADERS frame. The HEADERS frame is used + // for sending headers. + bool SerializeHeaders(const SpdyHeadersIR& headers, + ZeroCopyOutputBuffer* output); + + // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE + // frame is used to implement per stream flow control. + bool SerializeWindowUpdate(const SpdyWindowUpdateIR& window_update, + ZeroCopyOutputBuffer* output) const; + + // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used + // to inform the client that it will be receiving an additional stream + // in response to the original request. The frame includes synthesized + // headers to explain the upcoming data. + bool SerializePushPromise(const SpdyPushPromiseIR& push_promise, + ZeroCopyOutputBuffer* output); + + // Serializes a CONTINUATION frame. The CONTINUATION frame is used + // to continue a sequence of header block fragments. + bool SerializeContinuation(const SpdyContinuationIR& continuation, + ZeroCopyOutputBuffer* output) const; + + // Serializes an ALTSVC frame. The ALTSVC frame advertises the + // availability of an alternative service to the client. + bool SerializeAltSvc(const SpdyAltSvcIR& altsvc, + ZeroCopyOutputBuffer* output); + + // Serializes a PRIORITY frame. The PRIORITY frame advises a change in + // the relative priority of the given stream. + bool SerializePriority(const SpdyPriorityIR& priority, + ZeroCopyOutputBuffer* output) const; + + // Serializes a PRIORITY_UPDATE frame. + // See https://httpwg.org/http-extensions/draft-ietf-httpbis-priority.html. + bool SerializePriorityUpdate(const SpdyPriorityUpdateIR& priority_update, + ZeroCopyOutputBuffer* output) const; + + // Serializes an ACCEPT_CH frame. See + // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02. + bool SerializeAcceptCh(const SpdyAcceptChIR& accept_ch, + ZeroCopyOutputBuffer* output) const; + + // Serializes an unknown frame given a frame header and payload. + bool SerializeUnknown(const SpdyUnknownIR& unknown, + ZeroCopyOutputBuffer* output) const; + + // Serialize a frame of unknown type. + size_t SerializeFrame(const SpdyFrameIR& frame, ZeroCopyOutputBuffer* output); + + // Returns whether this SpdyFramer will compress header blocks using HPACK. + bool compression_enabled() const { + return compression_option_ == ENABLE_COMPRESSION; + } + + void SetHpackIndexingPolicy(HpackEncoder::IndexingPolicy policy) { + GetHpackEncoder()->SetIndexingPolicy(std::move(policy)); + } + + // Updates the maximum size of the header encoder compression table. + void UpdateHeaderEncoderTableSize(uint32_t value); + + // Returns the maximum size of the header encoder compression table. + size_t header_encoder_table_size() const; + + // Get (and lazily initialize) the HPACK encoder state. + HpackEncoder* GetHpackEncoder(); + + // Gets the HPACK encoder state. Returns nullptr if the encoder has not been + // initialized. + const HpackEncoder* GetHpackEncoder() const { return hpack_encoder_.get(); } + + protected: + friend class test::SpdyFramerPeer; + friend class test::SpdyFramerTest_MultipleContinuationFramesWithIterator_Test; + friend class test::SpdyFramerTest_PushPromiseFramesWithIterator_Test; + + // Iteratively converts a SpdyFrameIR into an appropriate sequence of Spdy + // frames. + // Example usage: + // std::unique_ptr it = CreateIterator(framer, frame_ir); + // while (it->HasNextFrame()) { + // if(it->NextFrame(output) == 0) { + // // Write failed; + // } + // } + class QUICHE_EXPORT SpdyFrameIterator : public SpdyFrameSequence { + public: + // Creates an iterator with the provided framer. + // Does not take ownership of |framer|. + // |framer| must outlive this instance. + explicit SpdyFrameIterator(SpdyFramer* framer); + ~SpdyFrameIterator() override; + + // Serializes the next frame in the sequence to |output|. Returns the number + // of bytes written to |output|. + size_t NextFrame(ZeroCopyOutputBuffer* output) override; + + // Returns true iff there is at least one more frame in the sequence. + bool HasNextFrame() const override; + + // SpdyFrameIterator is neither copyable nor movable. + SpdyFrameIterator(const SpdyFrameIterator&) = delete; + SpdyFrameIterator& operator=(const SpdyFrameIterator&) = delete; + + protected: + virtual size_t GetFrameSizeSansBlock() const = 0; + virtual bool SerializeGivenEncoding(const std::string& encoding, + ZeroCopyOutputBuffer* output) const = 0; + + SpdyFramer* GetFramer() const { return framer_; } + + void SetEncoder(const SpdyFrameWithHeaderBlockIR* ir) { + encoder_ = + framer_->GetHpackEncoder()->EncodeHeaderSet(ir->header_block()); + } + + bool has_next_frame() const { return has_next_frame_; } + + private: + SpdyFramer* const framer_; + std::unique_ptr encoder_; + bool is_first_frame_; + bool has_next_frame_; + }; + + // Iteratively converts a SpdyHeadersIR (with a possibly huge + // Http2HeaderBlock) into an appropriate sequence of SpdySerializedFrames, and + // write to the output. + class QUICHE_EXPORT SpdyHeaderFrameIterator : public SpdyFrameIterator { + public: + // Does not take ownership of |framer|. Take ownership of |headers_ir|. + SpdyHeaderFrameIterator(SpdyFramer* framer, + std::unique_ptr headers_ir); + + ~SpdyHeaderFrameIterator() override; + + private: + const SpdyFrameIR* GetIR() const override; + size_t GetFrameSizeSansBlock() const override; + bool SerializeGivenEncoding(const std::string& encoding, + ZeroCopyOutputBuffer* output) const override; + + const std::unique_ptr headers_ir_; + }; + + // Iteratively converts a SpdyPushPromiseIR (with a possibly huge + // Http2HeaderBlock) into an appropriate sequence of SpdySerializedFrames, and + // write to the output. + class QUICHE_EXPORT SpdyPushPromiseFrameIterator : public SpdyFrameIterator { + public: + // Does not take ownership of |framer|. Take ownership of |push_promise_ir|. + SpdyPushPromiseFrameIterator( + SpdyFramer* framer, + std::unique_ptr push_promise_ir); + + ~SpdyPushPromiseFrameIterator() override; + + private: + const SpdyFrameIR* GetIR() const override; + size_t GetFrameSizeSansBlock() const override; + bool SerializeGivenEncoding(const std::string& encoding, + ZeroCopyOutputBuffer* output) const override; + + const std::unique_ptr push_promise_ir_; + }; + + // Converts a SpdyFrameIR into one Spdy frame (a sequence of length 1), and + // write it to the output. + class QUICHE_EXPORT SpdyControlFrameIterator : public SpdyFrameSequence { + public: + SpdyControlFrameIterator(SpdyFramer* framer, + std::unique_ptr frame_ir); + ~SpdyControlFrameIterator() override; + + size_t NextFrame(ZeroCopyOutputBuffer* output) override; + + bool HasNextFrame() const override; + + const SpdyFrameIR* GetIR() const override; + + private: + SpdyFramer* const framer_; + std::unique_ptr frame_ir_; + bool has_next_frame_ = true; + }; + + private: + void SerializeHeadersBuilderHelper(const SpdyHeadersIR& headers, + uint8_t* flags, size_t* size, + std::string* hpack_encoding, int* weight, + size_t* length_field); + void SerializePushPromiseBuilderHelper(const SpdyPushPromiseIR& push_promise, + uint8_t* flags, + std::string* hpack_encoding, + size_t* size); + + std::unique_ptr hpack_encoder_; + + SpdyFramerDebugVisitorInterface* debug_visitor_; + + // Determines whether HPACK compression is used. + const CompressionOption compression_option_; +}; + +} // namespace spdy + +#endif // QUICHE_HTTP2_CORE_SPDY_FRAMER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_headers_handler_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_headers_handler_interface.h new file mode 100644 index 0000000000..4b234fd084 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_headers_handler_interface.h @@ -0,0 +1,39 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_HTTP2_CORE_SPDY_HEADERS_HANDLER_INTERFACE_H_ +#define QUICHE_HTTP2_CORE_SPDY_HEADERS_HANDLER_INTERFACE_H_ + +#include + +#include "absl/strings/string_view.h" +#include "quiche/common/platform/api/quiche_export.h" + +namespace spdy { + +// This interface defines how an object that accepts header data should behave. +// It is used by both SpdyHeadersBlockParser and HpackDecoder. +class QUICHE_EXPORT SpdyHeadersHandlerInterface { + public: + virtual ~SpdyHeadersHandlerInterface() {} + + // A callback method which notifies when the parser starts handling a new + // header block. Will only be called once per block, even if it extends into + // CONTINUATION frames. + virtual void OnHeaderBlockStart() = 0; + + // A callback method which notifies on a header key value pair. Multiple + // values for a given key will be emitted as multiple calls to OnHeader. + virtual void OnHeader(absl::string_view key, absl::string_view value) = 0; + + // A callback method which notifies when the parser finishes handling a + // header block (i.e. the containing frame has the END_HEADERS flag set). + // Also indicates the total number of bytes in this block. + virtual void OnHeaderBlockEnd(size_t uncompressed_header_bytes, + size_t compressed_header_bytes) = 0; +}; + +} // namespace spdy + +#endif // QUICHE_HTTP2_CORE_SPDY_HEADERS_HANDLER_INTERFACE_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_no_op_visitor.cc similarity index 82% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_no_op_visitor.cc index 16235513d8..f3d04a94d6 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_no_op_visitor.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/spdy_no_op_visitor.h" +#include "quiche/http2/core/spdy_no_op_visitor.h" #include #include -#include "quiche/spdy/core/spdy_headers_handler_interface.h" -#include "quiche/spdy/core/spdy_protocol.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" +#include "quiche/http2/core/spdy_protocol.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_no_op_visitor.h similarity index 92% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_no_op_visitor.h index 7125f3b13f..4f4ff53215 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_no_op_visitor.h @@ -6,19 +6,19 @@ // to make it easier to write tests that need to provide instances. Other // interfaces can be added as needed. -#ifndef QUICHE_SPDY_CORE_SPDY_NO_OP_VISITOR_H_ -#define QUICHE_SPDY_CORE_SPDY_NO_OP_VISITOR_H_ +#ifndef QUICHE_HTTP2_CORE_SPDY_NO_OP_VISITOR_H_ +#define QUICHE_HTTP2_CORE_SPDY_NO_OP_VISITOR_H_ #include #include #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/http2_frame_decoder_adapter.h" +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" +#include "quiche/http2/core/spdy_protocol.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/http2_frame_decoder_adapter.h" -#include "quiche/spdy/core/spdy_alt_svc_wire_format.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" -#include "quiche/spdy/core/spdy_protocol.h" namespace spdy { @@ -92,4 +92,4 @@ class QUICHE_EXPORT SpdyNoOpVisitor : public SpdyFramerVisitorInterface, } // namespace spdy -#endif // QUICHE_SPDY_CORE_SPDY_NO_OP_VISITOR_H_ +#endif // QUICHE_HTTP2_CORE_SPDY_NO_OP_VISITOR_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_protocol.cc similarity index 99% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_protocol.cc index fc3b971b2f..ae3f6621df 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_protocol.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/spdy_protocol.h" +#include "quiche/http2/core/spdy_protocol.h" #include #include @@ -14,11 +14,11 @@ #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_flag_utils.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/spdy_alt_svc_wire_format.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_protocol.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_protocol.h new file mode 100644 index 0000000000..24bb9d571d --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/spdy_protocol.h @@ -0,0 +1,1101 @@ +// Copyright (c) 2012 The Chromium 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 some protocol structures for use with SPDY 3 and HTTP 2 +// The SPDY 3 spec can be found at: +// http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3 + +#ifndef QUICHE_HTTP2_CORE_SPDY_PROTOCOL_H_ +#define QUICHE_HTTP2_CORE_SPDY_PROTOCOL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "absl/types/variant.h" +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" +#include "quiche/http2/core/spdy_bitmasks.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/platform/api/quiche_flags.h" +#include "quiche/common/platform/api/quiche_logging.h" +#include "quiche/spdy/core/http2_header_block.h" + +namespace spdy { + +// A stream ID is a 31-bit entity. +using SpdyStreamId = uint32_t; + +// A SETTINGS ID is a 16-bit entity. +using SpdySettingsId = uint16_t; + +// Specifies the stream ID used to denote the current session (for +// flow control). +inline constexpr SpdyStreamId kSessionFlowControlStreamId = 0; + +// 0 is not a valid stream ID for any other purpose than flow control. +inline constexpr SpdyStreamId kInvalidStreamId = 0; + +// Max stream id. +inline constexpr SpdyStreamId kMaxStreamId = 0x7fffffff; + +// The maximum possible frame payload size allowed by the spec. +inline constexpr uint32_t kSpdyMaxFrameSizeLimit = (1 << 24) - 1; + +// The initial value for the maximum frame payload size as per the spec. This is +// the maximum control frame size we accept. +inline constexpr uint32_t kHttp2DefaultFramePayloadLimit = 1 << 14; + +// The maximum size of the control frames that we send, including the size of +// the header. This limit is arbitrary. We can enforce it here or at the +// application layer. We chose the framing layer, but this can be changed (or +// removed) if necessary later down the line. +inline constexpr size_t kHttp2MaxControlFrameSendSize = + kHttp2DefaultFramePayloadLimit - 1; + +// Number of octets in the frame header. +inline constexpr size_t kFrameHeaderSize = 9; + +// The initial value for the maximum frame payload size as per the spec. This is +// the maximum control frame size we accept. +inline constexpr uint32_t kHttp2DefaultFrameSizeLimit = + kHttp2DefaultFramePayloadLimit + kFrameHeaderSize; + +// The initial value for the maximum size of the header list, "unlimited" (max +// unsigned 32-bit int) as per the spec. +inline constexpr uint32_t kSpdyInitialHeaderListSizeLimit = 0xFFFFFFFF; + +// Maximum window size for a Spdy stream or session. +inline constexpr int32_t kSpdyMaximumWindowSize = + 0x7FFFFFFF; // Max signed 32bit int + +// Maximum padding size in octets for one DATA or HEADERS or PUSH_PROMISE frame. +inline constexpr int32_t kPaddingSizePerFrame = 256; + +// The HTTP/2 connection preface, which must be the first bytes sent by the +// client upon starting an HTTP/2 connection, and which must be followed by a +// SETTINGS frame. Note that even though |kHttp2ConnectionHeaderPrefix| is +// defined as a string literal with a null terminator, the actual connection +// preface is only the first |kHttp2ConnectionHeaderPrefixSize| bytes, which +// excludes the null terminator. +QUICHE_EXPORT extern const char* const kHttp2ConnectionHeaderPrefix; +inline constexpr int kHttp2ConnectionHeaderPrefixSize = 24; + +// Wire values for HTTP2 frame types. +enum class SpdyFrameType : uint8_t { + DATA = 0x00, + HEADERS = 0x01, + PRIORITY = 0x02, + RST_STREAM = 0x03, + SETTINGS = 0x04, + PUSH_PROMISE = 0x05, + PING = 0x06, + GOAWAY = 0x07, + WINDOW_UPDATE = 0x08, + CONTINUATION = 0x09, + // ALTSVC is a public extension. + ALTSVC = 0x0a, + PRIORITY_UPDATE = 0x10, + ACCEPT_CH = 0x89, +}; + +// Flags on data packets. +enum SpdyDataFlags { + DATA_FLAG_NONE = 0x00, + DATA_FLAG_FIN = 0x01, + DATA_FLAG_PADDED = 0x08, +}; + +// Flags on control packets +enum SpdyControlFlags { + CONTROL_FLAG_NONE = 0x00, + CONTROL_FLAG_FIN = 0x01, +}; + +enum SpdyPingFlags { + PING_FLAG_ACK = 0x01, +}; + +// Used by HEADERS, PUSH_PROMISE, and CONTINUATION. +enum SpdyHeadersFlags { + HEADERS_FLAG_END_HEADERS = 0x04, + HEADERS_FLAG_PADDED = 0x08, + HEADERS_FLAG_PRIORITY = 0x20, +}; + +enum SpdyPushPromiseFlags { + PUSH_PROMISE_FLAG_END_PUSH_PROMISE = 0x04, + PUSH_PROMISE_FLAG_PADDED = 0x08, +}; + +enum Http2SettingsControlFlags { + SETTINGS_FLAG_ACK = 0x01, +}; + +// Wire values of HTTP/2 setting identifiers. +enum SpdyKnownSettingsId : SpdySettingsId { + // HPACK header table maximum size. + SETTINGS_HEADER_TABLE_SIZE = 0x1, + SETTINGS_MIN = SETTINGS_HEADER_TABLE_SIZE, + // Whether or not server push (PUSH_PROMISE) is enabled. + SETTINGS_ENABLE_PUSH = 0x2, + // The maximum number of simultaneous live streams in each direction. + SETTINGS_MAX_CONCURRENT_STREAMS = 0x3, + // Initial window size in bytes + SETTINGS_INITIAL_WINDOW_SIZE = 0x4, + // The size of the largest frame payload that a receiver is willing to accept. + SETTINGS_MAX_FRAME_SIZE = 0x5, + // The maximum size of header list that the sender is prepared to accept. + SETTINGS_MAX_HEADER_LIST_SIZE = 0x6, + // Enable Websockets over HTTP/2, see + // https://httpwg.org/specs/rfc8441.html + SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x8, + // Disable HTTP/2 priorities, see + // https://tools.ietf.org/html/draft-ietf-httpbis-priority-02. + SETTINGS_DEPRECATE_HTTP2_PRIORITIES = 0x9, + SETTINGS_MAX = SETTINGS_DEPRECATE_HTTP2_PRIORITIES, + // Experimental setting used to configure an alternative write scheduler. + SETTINGS_EXPERIMENT_SCHEDULER = 0xFF45, +}; + +// This explicit operator is needed, otherwise compiler finds +// overloaded operator to be ambiguous. +QUICHE_EXPORT std::ostream& operator<<(std::ostream& out, + SpdyKnownSettingsId id); + +// This operator is needed, because SpdyFrameType is an enum class, +// therefore implicit conversion to underlying integer type is not allowed. +QUICHE_EXPORT std::ostream& operator<<(std::ostream& out, + SpdyFrameType frame_type); + +using SettingsMap = std::map; + +// HTTP/2 error codes, RFC 7540 Section 7. +enum SpdyErrorCode : uint32_t { + ERROR_CODE_NO_ERROR = 0x0, + ERROR_CODE_PROTOCOL_ERROR = 0x1, + ERROR_CODE_INTERNAL_ERROR = 0x2, + ERROR_CODE_FLOW_CONTROL_ERROR = 0x3, + ERROR_CODE_SETTINGS_TIMEOUT = 0x4, + ERROR_CODE_STREAM_CLOSED = 0x5, + ERROR_CODE_FRAME_SIZE_ERROR = 0x6, + ERROR_CODE_REFUSED_STREAM = 0x7, + ERROR_CODE_CANCEL = 0x8, + ERROR_CODE_COMPRESSION_ERROR = 0x9, + ERROR_CODE_CONNECT_ERROR = 0xa, + ERROR_CODE_ENHANCE_YOUR_CALM = 0xb, + ERROR_CODE_INADEQUATE_SECURITY = 0xc, + ERROR_CODE_HTTP_1_1_REQUIRED = 0xd, + ERROR_CODE_MAX = ERROR_CODE_HTTP_1_1_REQUIRED +}; + +// Type of priority write scheduler. +enum class WriteSchedulerType { + LIFO, // Last added stream has the highest priority. + SPDY, // Uses SPDY priorities described in + // https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.3.3-Stream-priority. + HTTP2, // Uses HTTP2 (tree-style) priority described in + // https://tools.ietf.org/html/rfc7540#section-5.3. + FIFO, // Stream with the smallest stream ID has the highest priority. +}; + +// A SPDY priority is a number between 0 and 7 (inclusive). +typedef uint8_t SpdyPriority; + +// Lowest and Highest here refer to SPDY priorities as described in +// https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.3.3-Stream-priority +inline constexpr SpdyPriority kV3HighestPriority = 0; +inline constexpr SpdyPriority kV3LowestPriority = 7; + +// Returns SPDY 3.x priority value clamped to the valid range of [0, 7]. +QUICHE_EXPORT SpdyPriority ClampSpdy3Priority(SpdyPriority priority); + +// HTTP/2 stream weights are integers in range [1, 256], as specified in RFC +// 7540 section 5.3.2. Default stream weight is defined in section 5.3.5. +inline constexpr int kHttp2MinStreamWeight = 1; +inline constexpr int kHttp2MaxStreamWeight = 256; +inline constexpr int kHttp2DefaultStreamWeight = 16; + +// Returns HTTP/2 weight clamped to the valid range of [1, 256]. +QUICHE_EXPORT int ClampHttp2Weight(int weight); + +// Maps SPDY 3.x priority value in range [0, 7] to HTTP/2 weight value in range +// [1, 256], where priority 0 (i.e. highest precedence) corresponds to maximum +// weight 256 and priority 7 (lowest precedence) corresponds to minimum weight +// 1. +QUICHE_EXPORT int Spdy3PriorityToHttp2Weight(SpdyPriority priority); + +// Maps HTTP/2 weight value in range [1, 256] to SPDY 3.x priority value in +// range [0, 7], where minimum weight 1 corresponds to priority 7 (lowest +// precedence) and maximum weight 256 corresponds to priority 0 (highest +// precedence). +QUICHE_EXPORT SpdyPriority Http2WeightToSpdy3Priority(int weight); + +// Reserved ID for root stream of HTTP/2 stream dependency tree, as specified +// in RFC 7540 section 5.3.1. +const unsigned int kHttp2RootStreamId = 0; + +typedef uint64_t SpdyPingId; + +// Returns true if a given on-the-wire enumeration of a frame type is defined +// in a standardized HTTP/2 specification, false otherwise. +QUICHE_EXPORT bool IsDefinedFrameType(uint8_t frame_type_field); + +// Parses a frame type from an on-the-wire enumeration. +// Behavior is undefined for invalid frame type fields; consumers should first +// use IsValidFrameType() to verify validity of frame type fields. +QUICHE_EXPORT SpdyFrameType ParseFrameType(uint8_t frame_type_field); + +// Serializes a frame type to the on-the-wire value. +QUICHE_EXPORT uint8_t SerializeFrameType(SpdyFrameType frame_type); + +// (HTTP/2) All standard frame types except WINDOW_UPDATE are +// (stream-specific xor connection-level). Returns false iff we know +// the given frame type does not align with the given streamID. +QUICHE_EXPORT bool IsValidHTTP2FrameStreamId( + SpdyStreamId current_frame_stream_id, SpdyFrameType frame_type_field); + +// Serialize |frame_type| to string for logging/debugging. +QUICHE_EXPORT const char* FrameTypeToString(SpdyFrameType frame_type); + +// If |wire_setting_id| is the on-the-wire representation of a defined SETTINGS +// parameter, parse it to |*setting_id| and return true. +QUICHE_EXPORT bool ParseSettingsId(SpdySettingsId wire_setting_id, + SpdyKnownSettingsId* setting_id); + +// Returns a string representation of the |id| for logging/debugging. Returns +// the |id| prefixed with "SETTINGS_UNKNOWN_" for unknown SETTINGS IDs. To parse +// the |id| into a SpdyKnownSettingsId (if applicable), use ParseSettingsId(). +QUICHE_EXPORT std::string SettingsIdToString(SpdySettingsId id); + +// Parse |wire_error_code| to a SpdyErrorCode. +// Treat unrecognized error codes as INTERNAL_ERROR +// as recommended by the HTTP/2 specification. +QUICHE_EXPORT SpdyErrorCode ParseErrorCode(uint32_t wire_error_code); + +// Serialize RST_STREAM or GOAWAY frame error code to string +// for logging/debugging. +QUICHE_EXPORT const char* ErrorCodeToString(SpdyErrorCode error_code); + +// Serialize |type| to string for logging/debugging. +QUICHE_EXPORT const char* WriteSchedulerTypeToString(WriteSchedulerType type); + +// Minimum size of a frame, in octets. +inline constexpr size_t kFrameMinimumSize = kFrameHeaderSize; + +// Minimum frame size for variable size frame types (includes mandatory fields), +// frame size for fixed size frames, in octets. + +inline constexpr size_t kDataFrameMinimumSize = kFrameHeaderSize; +inline constexpr size_t kHeadersFrameMinimumSize = kFrameHeaderSize; +// PRIORITY frame has stream_dependency (4 octets) and weight (1 octet) fields. +inline constexpr size_t kPriorityFrameSize = kFrameHeaderSize + 5; +// RST_STREAM frame has error_code (4 octets) field. +inline constexpr size_t kRstStreamFrameSize = kFrameHeaderSize + 4; +inline constexpr size_t kSettingsFrameMinimumSize = kFrameHeaderSize; +inline constexpr size_t kSettingsOneSettingSize = + sizeof(uint32_t) + sizeof(SpdySettingsId); +// PUSH_PROMISE frame has promised_stream_id (4 octet) field. +inline constexpr size_t kPushPromiseFrameMinimumSize = kFrameHeaderSize + 4; +// PING frame has opaque_bytes (8 octet) field. +inline constexpr size_t kPingFrameSize = kFrameHeaderSize + 8; +// GOAWAY frame has last_stream_id (4 octet) and error_code (4 octet) fields. +inline constexpr size_t kGoawayFrameMinimumSize = kFrameHeaderSize + 8; +// WINDOW_UPDATE frame has window_size_increment (4 octet) field. +inline constexpr size_t kWindowUpdateFrameSize = kFrameHeaderSize + 4; +inline constexpr size_t kContinuationFrameMinimumSize = kFrameHeaderSize; +// ALTSVC frame has origin_len (2 octets) field. +inline constexpr size_t kGetAltSvcFrameMinimumSize = kFrameHeaderSize + 2; +// PRIORITY_UPDATE frame has prioritized_stream_id (4 octets) field. +inline constexpr size_t kPriorityUpdateFrameMinimumSize = kFrameHeaderSize + 4; +// ACCEPT_CH frame may have empty payload. +inline constexpr size_t kAcceptChFrameMinimumSize = kFrameHeaderSize; +// Each ACCEPT_CH frame entry has a 16-bit origin length and a 16-bit value +// length. +inline constexpr size_t kAcceptChFramePerEntryOverhead = 4; + +// Maximum possible configurable size of a frame in octets. +inline constexpr size_t kMaxFrameSizeLimit = + kSpdyMaxFrameSizeLimit + kFrameHeaderSize; +// Size of a header block size field. +inline constexpr size_t kSizeOfSizeField = sizeof(uint32_t); +// Initial window size for a stream in bytes. +inline constexpr int32_t kInitialStreamWindowSize = 64 * 1024 - 1; +// Initial window size for a session in bytes. +inline constexpr int32_t kInitialSessionWindowSize = 64 * 1024 - 1; +// The NPN string for HTTP2, "h2". +QUICHE_EXPORT extern const char* const kHttp2Npn; +// An estimate of the HPACK overhead for each header field in bytes, intended to +// be no smaller than actual overhead, based on the literal header field +// representation in RFC 7541 Section 6.2 (with or without indexing): +// - 1 byte for the opcode. +// - 2 bytes for the name length (assuming new name). +// - 3 bytes for the value length. +// TODO(b/322146543): Remove the `New` suffix with deprecation of +// --gfe2_reloadable_flag_http2_add_hpack_overhead_bytes2. +inline constexpr size_t kPerHeaderHpackOverheadNew = 6; +// An estimate size of the HPACK overhead for each header field. 1 bytes for +// indexed literal, 1 bytes for key literal and length encoding, and 2 bytes for +// value literal and length encoding. +// TODO(b/322146543): Remove with deprecation of +// --gfe2_reloadable_flag_http2_add_hpack_overhead_bytes2. +inline constexpr size_t kPerHeaderHpackOverheadOld = 4; + +// Names of pseudo-headers defined for HTTP/2 requests. +QUICHE_EXPORT extern const char* const kHttp2AuthorityHeader; +QUICHE_EXPORT extern const char* const kHttp2MethodHeader; +QUICHE_EXPORT extern const char* const kHttp2PathHeader; +QUICHE_EXPORT extern const char* const kHttp2SchemeHeader; +QUICHE_EXPORT extern const char* const kHttp2ProtocolHeader; + +// Name of pseudo-header defined for HTTP/2 responses. +QUICHE_EXPORT extern const char* const kHttp2StatusHeader; + +QUICHE_EXPORT size_t GetNumberRequiredContinuationFrames(size_t size); + +// Variant type that is either a SPDY 3.x priority value, or else an HTTP/2 +// stream dependency tuple {parent stream ID, weight, exclusive bit}. Templated +// to allow for use by QUIC code; SPDY and HTTP/2 code should use the concrete +// type instantiation SpdyStreamPrecedence. +template +class QUICHE_EXPORT StreamPrecedence { + public: + // Constructs instance that is a SPDY 3.x priority. Clamps priority value to + // the valid range [0, 7]. + explicit StreamPrecedence(SpdyPriority priority) + : precedence_(ClampSpdy3Priority(priority)) {} + + // Constructs instance that is an HTTP/2 stream weight, parent stream ID, and + // exclusive bit. Clamps stream weight to the valid range [1, 256]. + StreamPrecedence(StreamIdType parent_id, int weight, bool is_exclusive) + : precedence_(Http2StreamDependency{parent_id, ClampHttp2Weight(weight), + is_exclusive}) {} + + // Intentionally copyable, to support pass by value. + StreamPrecedence(const StreamPrecedence& other) = default; + StreamPrecedence& operator=(const StreamPrecedence& other) = default; + + // Returns true if this instance is a SPDY 3.x priority, or false if this + // instance is an HTTP/2 stream dependency. + bool is_spdy3_priority() const { + return absl::holds_alternative(precedence_); + } + + // Returns SPDY 3.x priority value. If |is_spdy3_priority()| is true, this is + // the value provided at construction, clamped to the legal priority + // range. Otherwise, it is the HTTP/2 stream weight mapped to a SPDY 3.x + // priority value, where minimum weight 1 corresponds to priority 7 (lowest + // precedence) and maximum weight 256 corresponds to priority 0 (highest + // precedence). + SpdyPriority spdy3_priority() const { + return is_spdy3_priority() + ? absl::get(precedence_) + : Http2WeightToSpdy3Priority( + absl::get(precedence_).weight); + } + + // Returns HTTP/2 parent stream ID. If |is_spdy3_priority()| is false, this is + // the value provided at construction, otherwise it is |kHttp2RootStreamId|. + StreamIdType parent_id() const { + return is_spdy3_priority() + ? kHttp2RootStreamId + : absl::get(precedence_).parent_id; + } + + // Returns HTTP/2 stream weight. If |is_spdy3_priority()| is false, this is + // the value provided at construction, clamped to the legal weight + // range. Otherwise, it is the SPDY 3.x priority value mapped to an HTTP/2 + // stream weight, where priority 0 (i.e. highest precedence) corresponds to + // maximum weight 256 and priority 7 (lowest precedence) corresponds to + // minimum weight 1. + int weight() const { + return is_spdy3_priority() + ? Spdy3PriorityToHttp2Weight( + absl::get(precedence_)) + : absl::get(precedence_).weight; + } + + // Returns HTTP/2 parent stream exclusivity. If |is_spdy3_priority()| is + // false, this is the value provided at construction, otherwise it is false. + bool is_exclusive() const { + return absl::holds_alternative(precedence_) && + absl::get(precedence_).is_exclusive; + } + + // Facilitates test assertions. + bool operator==(const StreamPrecedence& other) const { + return precedence_ == other.precedence_; + } + + bool operator!=(const StreamPrecedence& other) const { + return !(*this == other); + } + + private: + struct QUICHE_EXPORT Http2StreamDependency { + StreamIdType parent_id; + int weight; + bool is_exclusive; + + bool operator==(const Http2StreamDependency& other) const { + return parent_id == other.parent_id && weight == other.weight && + is_exclusive == other.is_exclusive; + } + }; + + absl::variant precedence_; +}; + +typedef StreamPrecedence SpdyStreamPrecedence; + +class SpdyFrameVisitor; + +// Intermediate representation for HTTP2 frames. +class QUICHE_EXPORT SpdyFrameIR { + public: + virtual ~SpdyFrameIR() {} + + virtual void Visit(SpdyFrameVisitor* visitor) const = 0; + virtual SpdyFrameType frame_type() const = 0; + SpdyStreamId stream_id() const { return stream_id_; } + virtual bool fin() const; + // Returns an estimate of the size of the serialized frame, without applying + // compression. May not be exact, but implementations should return the same + // value for a const frame. + virtual size_t size() const = 0; + + // Returns the number of bytes of flow control window that would be consumed + // by this frame if written to the wire. + virtual int flow_control_window_consumed() const; + + protected: + SpdyFrameIR() : stream_id_(0) {} + explicit SpdyFrameIR(SpdyStreamId stream_id) : stream_id_(stream_id) {} + SpdyFrameIR(const SpdyFrameIR&) = delete; + SpdyFrameIR& operator=(const SpdyFrameIR&) = delete; + + private: + SpdyStreamId stream_id_; +}; + +// Abstract class intended to be inherited by IRs that have the option of a FIN +// flag. +class QUICHE_EXPORT SpdyFrameWithFinIR : public SpdyFrameIR { + public: + ~SpdyFrameWithFinIR() override {} + bool fin() const override; + void set_fin(bool fin) { fin_ = fin; } + + protected: + explicit SpdyFrameWithFinIR(SpdyStreamId stream_id) + : SpdyFrameIR(stream_id), fin_(false) {} + SpdyFrameWithFinIR(const SpdyFrameWithFinIR&) = delete; + SpdyFrameWithFinIR& operator=(const SpdyFrameWithFinIR&) = delete; + + private: + bool fin_; +}; + +// Abstract class intended to be inherited by IRs that contain a header +// block. Implies SpdyFrameWithFinIR. +class QUICHE_EXPORT SpdyFrameWithHeaderBlockIR : public SpdyFrameWithFinIR { + public: + ~SpdyFrameWithHeaderBlockIR() override; + + const Http2HeaderBlock& header_block() const { return header_block_; } + void set_header_block(Http2HeaderBlock header_block) { + // Deep copy. + header_block_ = std::move(header_block); + } + void SetHeader(absl::string_view name, absl::string_view value) { + header_block_[name] = value; + } + + protected: + SpdyFrameWithHeaderBlockIR(SpdyStreamId stream_id, + Http2HeaderBlock header_block); + SpdyFrameWithHeaderBlockIR(const SpdyFrameWithHeaderBlockIR&) = delete; + SpdyFrameWithHeaderBlockIR& operator=(const SpdyFrameWithHeaderBlockIR&) = + delete; + + private: + Http2HeaderBlock header_block_; +}; + +class QUICHE_EXPORT SpdyDataIR : public SpdyFrameWithFinIR { + public: + // Performs a deep copy on data. + SpdyDataIR(SpdyStreamId stream_id, absl::string_view data); + + // Performs a deep copy on data. + SpdyDataIR(SpdyStreamId stream_id, const char* data); + + // Moves data into data_store_. Makes a copy if passed a non-movable string. + SpdyDataIR(SpdyStreamId stream_id, std::string data); + + // Use in conjunction with SetDataShallow() for shallow-copy on data. + explicit SpdyDataIR(SpdyStreamId stream_id); + SpdyDataIR(const SpdyDataIR&) = delete; + SpdyDataIR& operator=(const SpdyDataIR&) = delete; + + ~SpdyDataIR() override; + + const char* data() const { return data_; } + size_t data_len() const { return data_len_; } + + bool padded() const { return padded_; } + + int padding_payload_len() const { return padding_payload_len_; } + + void set_padding_len(int padding_len) { + QUICHE_DCHECK_GT(padding_len, 0); + QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame); + padded_ = true; + // The pad field takes one octet on the wire. + padding_payload_len_ = padding_len - 1; + } + + // Deep-copy of data (keep private copy). + void SetDataDeep(absl::string_view data) { + data_store_ = std::make_unique(data.data(), data.size()); + data_ = data_store_->data(); + data_len_ = data.size(); + } + + // Shallow-copy of data (do not keep private copy). + void SetDataShallow(absl::string_view data) { + data_store_.reset(); + data_ = data.data(); + data_len_ = data.size(); + } + + // Use this method if we don't have a contiguous buffer and only + // need a length. + void SetDataShallow(size_t len) { + data_store_.reset(); + data_ = nullptr; + data_len_ = len; + } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + int flow_control_window_consumed() const override; + + size_t size() const override; + + private: + // Used to store data that this SpdyDataIR should own. + std::unique_ptr data_store_; + const char* data_; + size_t data_len_; + + bool padded_; + // padding_payload_len_ = desired padding length - len(padding length field). + int padding_payload_len_; +}; + +class QUICHE_EXPORT SpdyRstStreamIR : public SpdyFrameIR { + public: + SpdyRstStreamIR(SpdyStreamId stream_id, SpdyErrorCode error_code); + SpdyRstStreamIR(const SpdyRstStreamIR&) = delete; + SpdyRstStreamIR& operator=(const SpdyRstStreamIR&) = delete; + + ~SpdyRstStreamIR() override; + + SpdyErrorCode error_code() const { return error_code_; } + void set_error_code(SpdyErrorCode error_code) { error_code_ = error_code; } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + private: + SpdyErrorCode error_code_; +}; + +class QUICHE_EXPORT SpdySettingsIR : public SpdyFrameIR { + public: + SpdySettingsIR(); + SpdySettingsIR(const SpdySettingsIR&) = delete; + SpdySettingsIR& operator=(const SpdySettingsIR&) = delete; + ~SpdySettingsIR() override; + + // Overwrites as appropriate. + const SettingsMap& values() const { return values_; } + void AddSetting(SpdySettingsId id, int32_t value) { values_[id] = value; } + + bool is_ack() const { return is_ack_; } + void set_is_ack(bool is_ack) { is_ack_ = is_ack; } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + private: + SettingsMap values_; + bool is_ack_; +}; + +class QUICHE_EXPORT SpdyPingIR : public SpdyFrameIR { + public: + explicit SpdyPingIR(SpdyPingId id) : id_(id), is_ack_(false) {} + SpdyPingIR(const SpdyPingIR&) = delete; + SpdyPingIR& operator=(const SpdyPingIR&) = delete; + SpdyPingId id() const { return id_; } + + bool is_ack() const { return is_ack_; } + void set_is_ack(bool is_ack) { is_ack_ = is_ack; } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + private: + SpdyPingId id_; + bool is_ack_; +}; + +class QUICHE_EXPORT SpdyGoAwayIR : public SpdyFrameIR { + public: + // References description, doesn't copy it, so description must outlast + // this SpdyGoAwayIR. + SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code, + absl::string_view description); + + // References description, doesn't copy it, so description must outlast + // this SpdyGoAwayIR. + SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code, + const char* description); + + // Moves description into description_store_, so caller doesn't need to + // keep description live after constructing this SpdyGoAwayIR. + SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code, + std::string description); + SpdyGoAwayIR(const SpdyGoAwayIR&) = delete; + SpdyGoAwayIR& operator=(const SpdyGoAwayIR&) = delete; + + ~SpdyGoAwayIR() override; + + SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; } + void set_last_good_stream_id(SpdyStreamId last_good_stream_id) { + QUICHE_DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask); + last_good_stream_id_ = last_good_stream_id; + } + SpdyErrorCode error_code() const { return error_code_; } + void set_error_code(SpdyErrorCode error_code) { + // TODO(hkhalil): Check valid ranges of error_code? + error_code_ = error_code; + } + + const absl::string_view& description() const { return description_; } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + private: + SpdyStreamId last_good_stream_id_; + SpdyErrorCode error_code_; + const std::string description_store_; + const absl::string_view description_; +}; + +class QUICHE_EXPORT SpdyHeadersIR : public SpdyFrameWithHeaderBlockIR { + public: + explicit SpdyHeadersIR(SpdyStreamId stream_id) + : SpdyHeadersIR(stream_id, Http2HeaderBlock()) {} + SpdyHeadersIR(SpdyStreamId stream_id, Http2HeaderBlock header_block) + : SpdyFrameWithHeaderBlockIR(stream_id, std::move(header_block)) {} + SpdyHeadersIR(const SpdyHeadersIR&) = delete; + SpdyHeadersIR& operator=(const SpdyHeadersIR&) = delete; + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + bool has_priority() const { return has_priority_; } + void set_has_priority(bool has_priority) { has_priority_ = has_priority; } + int weight() const { return weight_; } + void set_weight(int weight) { weight_ = weight; } + SpdyStreamId parent_stream_id() const { return parent_stream_id_; } + void set_parent_stream_id(SpdyStreamId id) { parent_stream_id_ = id; } + bool exclusive() const { return exclusive_; } + void set_exclusive(bool exclusive) { exclusive_ = exclusive; } + bool padded() const { return padded_; } + int padding_payload_len() const { return padding_payload_len_; } + void set_padding_len(int padding_len) { + QUICHE_DCHECK_GT(padding_len, 0); + QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame); + padded_ = true; + // The pad field takes one octet on the wire. + padding_payload_len_ = padding_len - 1; + } + + private: + bool has_priority_ = false; + int weight_ = kHttp2DefaultStreamWeight; + SpdyStreamId parent_stream_id_ = 0; + bool exclusive_ = false; + bool padded_ = false; + int padding_payload_len_ = 0; + const bool add_hpack_overhead_bytes_ = + GetQuicheReloadableFlag(http2_add_hpack_overhead_bytes2); +}; + +class QUICHE_EXPORT SpdyWindowUpdateIR : public SpdyFrameIR { + public: + SpdyWindowUpdateIR(SpdyStreamId stream_id, int32_t delta) + : SpdyFrameIR(stream_id) { + set_delta(delta); + } + SpdyWindowUpdateIR(const SpdyWindowUpdateIR&) = delete; + SpdyWindowUpdateIR& operator=(const SpdyWindowUpdateIR&) = delete; + + int32_t delta() const { return delta_; } + void set_delta(int32_t delta) { + QUICHE_DCHECK_LE(0, delta); + QUICHE_DCHECK_LE(delta, kSpdyMaximumWindowSize); + delta_ = delta; + } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + private: + int32_t delta_; +}; + +class QUICHE_EXPORT SpdyPushPromiseIR : public SpdyFrameWithHeaderBlockIR { + public: + SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id) + : SpdyPushPromiseIR(stream_id, promised_stream_id, Http2HeaderBlock()) {} + SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id, + Http2HeaderBlock header_block) + : SpdyFrameWithHeaderBlockIR(stream_id, std::move(header_block)), + promised_stream_id_(promised_stream_id), + padded_(false), + padding_payload_len_(0) {} + SpdyPushPromiseIR(const SpdyPushPromiseIR&) = delete; + SpdyPushPromiseIR& operator=(const SpdyPushPromiseIR&) = delete; + SpdyStreamId promised_stream_id() const { return promised_stream_id_; } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + bool padded() const { return padded_; } + int padding_payload_len() const { return padding_payload_len_; } + void set_padding_len(int padding_len) { + QUICHE_DCHECK_GT(padding_len, 0); + QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame); + padded_ = true; + // The pad field takes one octet on the wire. + padding_payload_len_ = padding_len - 1; + } + + private: + SpdyStreamId promised_stream_id_; + + bool padded_; + int padding_payload_len_; +}; + +class QUICHE_EXPORT SpdyContinuationIR : public SpdyFrameIR { + public: + explicit SpdyContinuationIR(SpdyStreamId stream_id); + SpdyContinuationIR(const SpdyContinuationIR&) = delete; + SpdyContinuationIR& operator=(const SpdyContinuationIR&) = delete; + ~SpdyContinuationIR() override; + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + bool end_headers() const { return end_headers_; } + void set_end_headers(bool end_headers) { end_headers_ = end_headers; } + const std::string& encoding() const { return encoding_; } + void take_encoding(std::string encoding) { encoding_ = std::move(encoding); } + size_t size() const override; + + private: + std::string encoding_; + bool end_headers_; +}; + +class QUICHE_EXPORT SpdyAltSvcIR : public SpdyFrameIR { + public: + explicit SpdyAltSvcIR(SpdyStreamId stream_id); + SpdyAltSvcIR(const SpdyAltSvcIR&) = delete; + SpdyAltSvcIR& operator=(const SpdyAltSvcIR&) = delete; + ~SpdyAltSvcIR() override; + + std::string origin() const { return origin_; } + const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector() const { + return altsvc_vector_; + } + + void set_origin(std::string origin) { origin_ = std::move(origin); } + void add_altsvc(const SpdyAltSvcWireFormat::AlternativeService& altsvc) { + altsvc_vector_.push_back(altsvc); + } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + private: + std::string origin_; + SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector_; +}; + +class QUICHE_EXPORT SpdyPriorityIR : public SpdyFrameIR { + public: + SpdyPriorityIR(SpdyStreamId stream_id, SpdyStreamId parent_stream_id, + int weight, bool exclusive) + : SpdyFrameIR(stream_id), + parent_stream_id_(parent_stream_id), + weight_(weight), + exclusive_(exclusive) {} + SpdyPriorityIR(const SpdyPriorityIR&) = delete; + SpdyPriorityIR& operator=(const SpdyPriorityIR&) = delete; + SpdyStreamId parent_stream_id() const { return parent_stream_id_; } + int weight() const { return weight_; } + bool exclusive() const { return exclusive_; } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + private: + SpdyStreamId parent_stream_id_; + int weight_; + bool exclusive_; +}; + +class QUICHE_EXPORT SpdyPriorityUpdateIR : public SpdyFrameIR { + public: + SpdyPriorityUpdateIR(SpdyStreamId stream_id, + SpdyStreamId prioritized_stream_id, + std::string priority_field_value) + : SpdyFrameIR(stream_id), + prioritized_stream_id_(prioritized_stream_id), + priority_field_value_(std::move(priority_field_value)) {} + SpdyPriorityUpdateIR(const SpdyPriorityUpdateIR&) = delete; + SpdyPriorityUpdateIR& operator=(const SpdyPriorityUpdateIR&) = delete; + SpdyStreamId prioritized_stream_id() const { return prioritized_stream_id_; } + const std::string& priority_field_value() const { + return priority_field_value_; + } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + private: + SpdyStreamId prioritized_stream_id_; + std::string priority_field_value_; +}; + +struct QUICHE_EXPORT AcceptChOriginValuePair { + std::string origin; + std::string value; + bool operator==(const AcceptChOriginValuePair& rhs) const { + return origin == rhs.origin && value == rhs.value; + } +}; + +class QUICHE_EXPORT SpdyAcceptChIR : public SpdyFrameIR { + public: + SpdyAcceptChIR(std::vector entries) + : entries_(std::move(entries)) {} + SpdyAcceptChIR(const SpdyAcceptChIR&) = delete; + SpdyAcceptChIR& operator=(const SpdyAcceptChIR&) = delete; + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + size_t size() const override; + + const std::vector& entries() const { + return entries_; + } + + private: + std::vector entries_; +}; + +// Represents a frame of unrecognized type. +class QUICHE_EXPORT SpdyUnknownIR : public SpdyFrameIR { + public: + SpdyUnknownIR(SpdyStreamId stream_id, uint8_t type, uint8_t flags, + std::string payload) + : SpdyFrameIR(stream_id), + type_(type), + flags_(flags), + length_(payload.size()), + payload_(std::move(payload)) {} + SpdyUnknownIR(const SpdyUnknownIR&) = delete; + SpdyUnknownIR& operator=(const SpdyUnknownIR&) = delete; + uint8_t type() const { return type_; } + uint8_t flags() const { return flags_; } + size_t length() const { return length_; } + const std::string& payload() const { return payload_; } + + void Visit(SpdyFrameVisitor* visitor) const override; + + SpdyFrameType frame_type() const override; + + int flow_control_window_consumed() const override; + + size_t size() const override; + + protected: + // Allows subclasses to overwrite the default payload length. + void set_length(size_t length) { length_ = length; } + + private: + uint8_t type_; + uint8_t flags_; + size_t length_; + const std::string payload_; +}; + +class QUICHE_EXPORT SpdySerializedFrame { + public: + SpdySerializedFrame() : size_(0) {} + + // Creates a valid SpdySerializedFrame using a pre-created buffer. + SpdySerializedFrame(std::unique_ptr data, size_t size) + : frame_(std::move(data)), size_(size) {} + + SpdySerializedFrame(SpdySerializedFrame&& other) + : frame_(std::move(other.frame_)), size_(other.size_) {} + + SpdySerializedFrame(const SpdySerializedFrame&) = delete; + SpdySerializedFrame& operator=(const SpdySerializedFrame&) = delete; + + SpdySerializedFrame& operator=(SpdySerializedFrame&& other) { + // Take over |other|. + frame_ = std::move(other.frame_); + size_ = other.size_; + return *this; + } + + ~SpdySerializedFrame() = default; + + // Provides access to the frame bytes, which is a buffer containing the frame + // packed as expected for sending over the wire. + char* data() const { return frame_.get(); } + + // Returns the actual size of the underlying buffer. + size_t size() const { return size_; } + + operator absl::string_view() const { + return absl::string_view{frame_.get(), size_}; + } + + private: + std::unique_ptr frame_; + size_t size_; +}; + +// This interface is for classes that want to process SpdyFrameIRs without +// having to know what type they are. An instance of this interface can be +// passed to a SpdyFrameIR's Visit method, and the appropriate type-specific +// method of this class will be called. +class QUICHE_EXPORT SpdyFrameVisitor { + public: + SpdyFrameVisitor() {} + SpdyFrameVisitor(const SpdyFrameVisitor&) = delete; + SpdyFrameVisitor& operator=(const SpdyFrameVisitor&) = delete; + virtual ~SpdyFrameVisitor() {} + + virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) = 0; + virtual void VisitSettings(const SpdySettingsIR& settings) = 0; + virtual void VisitPing(const SpdyPingIR& ping) = 0; + virtual void VisitGoAway(const SpdyGoAwayIR& goaway) = 0; + virtual void VisitHeaders(const SpdyHeadersIR& headers) = 0; + virtual void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) = 0; + virtual void VisitPushPromise(const SpdyPushPromiseIR& push_promise) = 0; + virtual void VisitContinuation(const SpdyContinuationIR& continuation) = 0; + virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) = 0; + virtual void VisitPriority(const SpdyPriorityIR& priority) = 0; + virtual void VisitData(const SpdyDataIR& data) = 0; + virtual void VisitPriorityUpdate( + const SpdyPriorityUpdateIR& priority_update) = 0; + virtual void VisitAcceptCh(const SpdyAcceptChIR& accept_ch) = 0; + virtual void VisitUnknown(const SpdyUnknownIR& /*unknown*/) { + // TODO(birenroy): make abstract. + } +}; + +// Optionally, and in addition to SpdyFramerVisitorInterface, a class supporting +// SpdyFramerDebugVisitorInterface may be used in conjunction with SpdyFramer in +// order to extract debug/internal information about the SpdyFramer as it +// operates. +// +// Most HTTP2 implementations need not bother with this interface at all. +class QUICHE_EXPORT SpdyFramerDebugVisitorInterface { + public: + virtual ~SpdyFramerDebugVisitorInterface() {} + + // Called after compressing a frame with a payload of + // a list of name-value pairs. + // |payload_len| is the uncompressed payload size. + // |frame_len| is the compressed frame size. + virtual void OnSendCompressedFrame(SpdyStreamId /*stream_id*/, + SpdyFrameType /*type*/, + size_t /*payload_len*/, + size_t /*frame_len*/) {} + + // Called when a frame containing a compressed payload of + // name-value pairs is received. + // |frame_len| is the compressed frame size. + virtual void OnReceiveCompressedFrame(SpdyStreamId /*stream_id*/, + SpdyFrameType /*type*/, + size_t /*frame_len*/) {} +}; + +// Calculates the number of bytes required to serialize a SpdyHeadersIR, not +// including the bytes to be used for the encoded header set. +size_t GetHeaderFrameSizeSansBlock(const SpdyHeadersIR& header_ir); + +// Calculates the number of bytes required to serialize a SpdyPushPromiseIR, +// not including the bytes to be used for the encoded header set. +size_t GetPushPromiseFrameSizeSansBlock( + const SpdyPushPromiseIR& push_promise_ir); + +} // namespace spdy + +#endif // QUICHE_HTTP2_CORE_SPDY_PROTOCOL_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/zero_copy_output_buffer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/zero_copy_output_buffer.h similarity index 83% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/zero_copy_output_buffer.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/zero_copy_output_buffer.h index 2ab92ed3e1..87ccdaba84 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/zero_copy_output_buffer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/core/zero_copy_output_buffer.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_ZERO_COPY_OUTPUT_BUFFER_H_ -#define QUICHE_SPDY_CORE_ZERO_COPY_OUTPUT_BUFFER_H_ +#ifndef QUICHE_HTTP2_CORE_ZERO_COPY_OUTPUT_BUFFER_H_ +#define QUICHE_HTTP2_CORE_ZERO_COPY_OUTPUT_BUFFER_H_ #include @@ -29,4 +29,4 @@ class QUICHE_EXPORT ZeroCopyOutputBuffer { } // namespace spdy -#endif // QUICHE_SPDY_CORE_ZERO_COPY_OUTPUT_BUFFER_H_ +#endif // QUICHE_HTTP2_CORE_ZERO_COPY_OUTPUT_BUFFER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.cc similarity index 99% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.cc index 12d720ba97..5eea1aee00 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/hpack/hpack_constants.h" +#include "quiche/http2/hpack/hpack_constants.h" #include #include "absl/base/macros.h" +#include "quiche/http2/hpack/hpack_static_table.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/hpack/hpack_static_table.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.h similarity index 95% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.h index a92f9752b1..65acab27fc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_HPACK_HPACK_CONSTANTS_H_ -#define QUICHE_SPDY_CORE_HPACK_HPACK_CONSTANTS_H_ +#ifndef QUICHE_HTTP2_HPACK_HPACK_CONSTANTS_H_ +#define QUICHE_HTTP2_HPACK_HPACK_CONSTANTS_H_ #include #include @@ -85,4 +85,4 @@ inline constexpr char kPseudoHeaderPrefix = ':'; } // namespace spdy -#endif // QUICHE_SPDY_CORE_HPACK_HPACK_CONSTANTS_H_ +#endif // QUICHE_HTTP2_HPACK_HPACK_CONSTANTS_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_encoder.cc similarity index 95% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_encoder.cc index d921c2c22c..4d19277eef 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_encoder.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/hpack/hpack_encoder.h" +#include "quiche/http2/hpack/hpack_encoder.h" #include #include @@ -14,13 +14,13 @@ #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" +#include "quiche/http2/hpack/hpack_constants.h" +#include "quiche/http2/hpack/hpack_header_table.h" +#include "quiche/http2/hpack/hpack_output_stream.h" #include "quiche/http2/hpack/huffman/hpack_huffman_encoder.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/hpack/hpack_constants.h" -#include "quiche/spdy/core/hpack/hpack_header_table.h" -#include "quiche/spdy/core/hpack/hpack_output_stream.h" -#include "quiche/spdy/core/http2_header_block.h" namespace spdy { @@ -93,7 +93,7 @@ HpackEncoder::HpackEncoder() HpackEncoder::~HpackEncoder() = default; std::string HpackEncoder::EncodeHeaderBlock( - const Http2HeaderBlock& header_set) { + const quiche::HttpHeaderBlock& header_set) { // Separate header set into pseudo-headers and regular headers. Representations pseudo_headers; Representations regular_headers; @@ -203,7 +203,7 @@ void HpackEncoder::EmitString(absl::string_view str) { << encoded_size; output_stream_.AppendPrefix(kStringLiteralHuffmanEncoded); output_stream_.AppendUint32(encoded_size); - http2::HuffmanEncodeFast(str, encoded_size, output_stream_.MutableString()); + http2::HuffmanEncode(str, encoded_size, output_stream_.MutableString()); } else { QUICHE_DVLOG(2) << "Emitted literal string of length " << str.size(); output_stream_.AppendPrefix(kStringLiteralIdentityEncoded); @@ -274,10 +274,10 @@ void HpackEncoder::DecomposeRepresentation(const Representation& header_field, } } -// Iteratively encodes a Http2HeaderBlock. +// Iteratively encodes a quiche::HttpHeaderBlock. class HpackEncoder::Encoderator : public ProgressiveEncoder { public: - Encoderator(const Http2HeaderBlock& header_set, HpackEncoder* encoder); + Encoderator(const quiche::HttpHeaderBlock& header_set, HpackEncoder* encoder); Encoderator(const Representations& representations, HpackEncoder* encoder); // Encoderator is neither copyable nor movable. @@ -298,8 +298,8 @@ class HpackEncoder::Encoderator : public ProgressiveEncoder { bool has_next_; }; -HpackEncoder::Encoderator::Encoderator(const Http2HeaderBlock& header_set, - HpackEncoder* encoder) +HpackEncoder::Encoderator::Encoderator( + const quiche::HttpHeaderBlock& header_set, HpackEncoder* encoder) : encoder_(encoder), has_next_(true) { // Separate header set into pseudo-headers and regular headers. bool found_cookie = false; @@ -379,7 +379,7 @@ std::string HpackEncoder::Encoderator::Next(size_t max_encoded_bytes) { } std::unique_ptr HpackEncoder::EncodeHeaderSet( - const Http2HeaderBlock& header_set) { + const quiche::HttpHeaderBlock& header_set) { return std::make_unique(header_set, this); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_encoder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_encoder.h new file mode 100644 index 0000000000..efbd262b90 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_encoder.h @@ -0,0 +1,156 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_HTTP2_HPACK_HPACK_ENCODER_H_ +#define QUICHE_HTTP2_HPACK_HPACK_ENCODER_H_ + +#include + +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "quiche/http2/hpack/hpack_header_table.h" +#include "quiche/http2/hpack/hpack_output_stream.h" +#include "quiche/common/http/http_header_block.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/quiche_callbacks.h" + +// An HpackEncoder encodes header sets as outlined in +// http://tools.ietf.org/html/rfc7541. + +namespace spdy { + +namespace test { +class HpackEncoderPeer; +} // namespace test + +class QUICHE_EXPORT HpackEncoder { + public: + using Representation = std::pair; + using Representations = std::vector; + + // Callers may provide a HeaderListener to be informed of header name-value + // pairs processed by this encoder. + using HeaderListener = + quiche::MultiUseCallback; + + // An indexing policy should return true if the provided header name-value + // pair should be inserted into the HPACK dynamic table. + using IndexingPolicy = + quiche::MultiUseCallback; + + HpackEncoder(); + HpackEncoder(const HpackEncoder&) = delete; + HpackEncoder& operator=(const HpackEncoder&) = delete; + ~HpackEncoder(); + + // Encodes and returns the given header set as a string. + std::string EncodeHeaderBlock(const quiche::HttpHeaderBlock& header_set); + + class QUICHE_EXPORT ProgressiveEncoder { + public: + virtual ~ProgressiveEncoder() {} + + // Returns true iff more remains to encode. + virtual bool HasNext() const = 0; + + // Encodes and returns up to max_encoded_bytes of the current header block. + virtual std::string Next(size_t max_encoded_bytes) = 0; + }; + + // Returns a ProgressiveEncoder which must be outlived by both the given + // quiche::HttpHeaderBlock and this object. + std::unique_ptr EncodeHeaderSet( + const quiche::HttpHeaderBlock& header_set); + // Returns a ProgressiveEncoder which must be outlived by this HpackEncoder. + // The encoder will not attempt to split any \0-delimited values in + // |representations|. If such splitting is desired, it must be performed by + // the caller when constructing the list of representations. + std::unique_ptr EncodeRepresentations( + const Representations& representations); + + // Called upon a change to SETTINGS_HEADER_TABLE_SIZE. Specifically, this + // is to be called after receiving (and sending an acknowledgement for) a + // SETTINGS_HEADER_TABLE_SIZE update from the remote decoding endpoint. + void ApplyHeaderTableSizeSetting(size_t size_setting); + + // TODO(birenroy): Rename this GetDynamicTableCapacity(). + size_t CurrentHeaderTableSizeSetting() const { + return header_table_.settings_size_bound(); + } + + // This HpackEncoder will use |policy| to determine whether to insert header + // name-value pairs into the dynamic table. + void SetIndexingPolicy(IndexingPolicy policy) { + should_index_ = std::move(policy); + } + + // |listener| will be invoked for each header name-value pair processed by + // this encoder. + void SetHeaderListener(HeaderListener listener) { + listener_ = std::move(listener); + } + + void DisableCompression() { enable_compression_ = false; } + + // Disables the deconstruction of Cookie header values into individual + // components, as described in + // https://httpwg.org/specs/rfc9113.html#CompressCookie. The deconstructed + // representation can cause problems for some HTTP/2 endpoints. + void DisableCookieCrumbling() { crumble_cookies_ = false; } + + // Returns the current dynamic table size, including the 32 bytes per entry + // overhead mentioned in RFC 7541 section 4.1. + size_t GetDynamicTableSize() const { return header_table_.size(); } + + private: + friend class test::HpackEncoderPeer; + + class RepresentationIterator; + class Encoderator; + + // Encodes a sequence of header name-value pairs as a single header block. + std::string EncodeRepresentations(RepresentationIterator* iter); + + // Emits a static/dynamic indexed representation (Section 7.1). + void EmitIndex(size_t index); + + // Emits a literal representation (Section 7.2). + void EmitIndexedLiteral(const Representation& representation); + void EmitNonIndexedLiteral(const Representation& representation, + bool enable_compression); + void EmitLiteral(const Representation& representation); + + // Emits a Huffman or identity string (whichever is smaller). + void EmitString(absl::string_view str); + + // Emits the current dynamic table size if the table size was recently + // updated and we have not yet emitted it (Section 6.3). + void MaybeEmitTableSize(); + + // Crumbles a cookie header into ";" delimited crumbs. + static void CookieToCrumbs(const Representation& cookie, + Representations* crumbs_out); + + // Crumbles other header field values at \0 delimiters. + static void DecomposeRepresentation(const Representation& header_field, + Representations* out); + + HpackHeaderTable header_table_; + HpackOutputStream output_stream_; + + size_t min_table_size_setting_received_; + HeaderListener listener_; + IndexingPolicy should_index_; + bool enable_compression_; + bool should_emit_table_size_; + bool crumble_cookies_; +}; + +} // namespace spdy + +#endif // QUICHE_HTTP2_HPACK_HPACK_ENCODER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_entry.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_entry.cc similarity index 94% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_entry.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_entry.cc index 365b6234a3..bfdd9fadc7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_entry.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_entry.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/hpack/hpack_entry.h" +#include "quiche/http2/hpack/hpack_entry.h" #include #include diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_entry.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_entry.h similarity index 95% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_entry.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_entry.h index b84e0da779..67749e93d8 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_entry.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_entry.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_HPACK_HPACK_ENTRY_H_ -#define QUICHE_SPDY_CORE_HPACK_HPACK_ENTRY_H_ +#ifndef QUICHE_HTTP2_HPACK_HPACK_ENTRY_H_ +#define QUICHE_HTTP2_HPACK_HPACK_ENTRY_H_ #include #include @@ -77,4 +77,4 @@ class QUICHE_EXPORT HpackEntry { } // namespace spdy -#endif // QUICHE_SPDY_CORE_HPACK_HPACK_ENTRY_H_ +#endif // QUICHE_HTTP2_HPACK_HPACK_ENTRY_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_header_table.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_header_table.cc similarity index 97% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_header_table.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_header_table.cc index 6deb280c43..0fbcc6e93b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_header_table.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_header_table.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/hpack/hpack_header_table.h" +#include "quiche/http2/hpack/hpack_header_table.h" #include #include @@ -11,10 +11,10 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/hpack/hpack_constants.h" +#include "quiche/http2/hpack/hpack_entry.h" +#include "quiche/http2/hpack/hpack_static_table.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/hpack/hpack_constants.h" -#include "quiche/spdy/core/hpack/hpack_entry.h" -#include "quiche/spdy/core/hpack/hpack_static_table.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_header_table.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_header_table.h similarity index 96% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_header_table.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_header_table.h index ab1842ec9d..b6c23859db 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_header_table.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_header_table.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_HPACK_HPACK_HEADER_TABLE_H_ -#define QUICHE_SPDY_CORE_HPACK_HPACK_HEADER_TABLE_H_ +#ifndef QUICHE_HTTP2_HPACK_HPACK_HEADER_TABLE_H_ +#define QUICHE_HTTP2_HPACK_HPACK_HEADER_TABLE_H_ #include #include @@ -11,9 +11,9 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" +#include "quiche/http2/hpack/hpack_entry.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/quiche_circular_deque.h" -#include "quiche/spdy/core/hpack/hpack_entry.h" // All section references below are to http://tools.ietf.org/html/rfc7541. @@ -146,4 +146,4 @@ class QUICHE_EXPORT HpackHeaderTable { } // namespace spdy -#endif // QUICHE_SPDY_CORE_HPACK_HPACK_HEADER_TABLE_H_ +#endif // QUICHE_HTTP2_HPACK_HPACK_HEADER_TABLE_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_output_stream.cc similarity index 96% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_output_stream.cc index f41007ec1e..aa50c0a7a1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_output_stream.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/hpack/hpack_output_stream.h" +#include "quiche/http2/hpack/hpack_output_stream.h" #include #include @@ -10,8 +10,8 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/hpack/hpack_constants.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/hpack/hpack_constants.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_output_stream.h similarity index 91% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_output_stream.h index 7640f80a14..c56ba87b2f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_output_stream.h @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_HPACK_HPACK_OUTPUT_STREAM_H_ -#define QUICHE_SPDY_CORE_HPACK_HPACK_OUTPUT_STREAM_H_ +#ifndef QUICHE_HTTP2_HPACK_HPACK_OUTPUT_STREAM_H_ +#define QUICHE_HTTP2_HPACK_HPACK_OUTPUT_STREAM_H_ #include #include #include #include "absl/strings/string_view.h" +#include "quiche/http2/hpack/hpack_constants.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/hpack/hpack_constants.h" // All section references below are to // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08 @@ -72,4 +72,4 @@ class QUICHE_EXPORT HpackOutputStream { } // namespace spdy -#endif // QUICHE_SPDY_CORE_HPACK_HPACK_OUTPUT_STREAM_H_ +#endif // QUICHE_HTTP2_HPACK_HPACK_OUTPUT_STREAM_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_static_table.cc similarity index 91% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_static_table.cc index 30a88af2ca..8a0d9126f7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_static_table.cc @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/core/hpack/hpack_static_table.h" +#include "quiche/http2/hpack/hpack_static_table.h" #include #include #include +#include "quiche/http2/hpack/hpack_constants.h" +#include "quiche/http2/hpack/hpack_entry.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/hpack/hpack_constants.h" -#include "quiche/spdy/core/hpack/hpack_entry.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_static_table.h similarity index 88% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_static_table.h index 597336716a..0280d37f3c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/hpack_static_table.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_CORE_HPACK_HPACK_STATIC_TABLE_H_ -#define QUICHE_SPDY_CORE_HPACK_HPACK_STATIC_TABLE_H_ +#ifndef QUICHE_HTTP2_HPACK_HPACK_STATIC_TABLE_H_ +#define QUICHE_HTTP2_HPACK_HPACK_STATIC_TABLE_H_ #include +#include "quiche/http2/hpack/hpack_header_table.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/hpack/hpack_header_table.h" namespace spdy { @@ -55,4 +55,4 @@ class QUICHE_EXPORT HpackStaticTable { } // namespace spdy -#endif // QUICHE_SPDY_CORE_HPACK_HPACK_STATIC_TABLE_H_ +#endif // QUICHE_HTTP2_HPACK_HPACK_STATIC_TABLE_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc index 0186dfcbf7..df2960ad1d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc @@ -19,55 +19,8 @@ size_t HuffmanSize(absl::string_view plain) { return (bits + 7) / 8; } -void HuffmanEncode(absl::string_view plain, size_t encoded_size, - std::string* huffman) { - QUICHE_DCHECK(huffman != nullptr); - huffman->reserve(huffman->size() + encoded_size); - uint64_t bit_buffer = 0; // High-bit is next bit to output. Not clear if that - // is more performant than having the low-bit be the - // last to be output. - size_t bits_unused = 64; // Number of bits available for the next code. - for (uint8_t c : plain) { - size_t code_length = HuffmanSpecTables::kCodeLengths[c]; - if (bits_unused < code_length) { - // There isn't enough room in bit_buffer for the code of c. - // Flush until bits_unused > 56 (i.e. 64 - 8). - do { - char h = static_cast(bit_buffer >> 56); - bit_buffer <<= 8; - bits_unused += 8; - // Perhaps would be more efficient if we populated an array of chars, - // so we don't have to call push_back each time. Reconsider if used - // for production. - huffman->push_back(h); - } while (bits_unused <= 56); - } - uint64_t code = HuffmanSpecTables::kRightCodes[c]; - size_t shift_by = bits_unused - code_length; - bit_buffer |= (code << shift_by); - bits_unused -= code_length; - } - // bit_buffer contains (64-bits_unused) bits that still need to be flushed. - // Output whole bytes until we don't have any whole bytes left. - size_t bits_used = 64 - bits_unused; - while (bits_used >= 8) { - char h = static_cast(bit_buffer >> 56); - bit_buffer <<= 8; - bits_used -= 8; - huffman->push_back(h); - } - if (bits_used > 0) { - // We have less than a byte left to output. The spec calls for padding out - // the final byte with the leading bits of the EOS symbol (30 1-bits). - constexpr uint64_t leading_eos_bits = 0b11111111; - bit_buffer |= (leading_eos_bits << (56 - bits_used)); - char h = static_cast(bit_buffer >> 56); - huffman->push_back(h); - } -} - -void HuffmanEncodeFast(absl::string_view input, size_t encoded_size, - std::string* output) { +void HuffmanEncode(absl::string_view input, size_t encoded_size, + std::string* output) { const size_t original_size = output->size(); const size_t final_size = original_size + encoded_size; // Reserve an extra four bytes to avoid accessing unallocated memory (even diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.h index e6056c1ce8..40daa4fb4a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.h @@ -20,18 +20,11 @@ namespace http2 { // than plain.size(). QUICHE_EXPORT size_t HuffmanSize(absl::string_view plain); -// Encode the plain text string |plain| with the Huffman encoding defined in the -// HPACK RFC, 7541. |encoded_size| is used to pre-allocate storage and it -// should be the value returned by HuffmanSize(). Appends the result to -// |*huffman|. -QUICHE_EXPORT void HuffmanEncode(absl::string_view plain, size_t encoded_size, - std::string* huffman); - // Encode |input| with the Huffman encoding defined RFC7541, used in HPACK and // QPACK. |encoded_size| must be the value returned by HuffmanSize(). // Appends the result to the end of |*output|. -QUICHE_EXPORT void HuffmanEncodeFast(absl::string_view input, - size_t encoded_size, std::string* output); +QUICHE_EXPORT void HuffmanEncode(absl::string_view input, size_t encoded_size, + std::string* output); } // namespace http2 diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/http2_trace_printer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/http2_trace_printer.cc index 682f91b79b..cc04ce0cd8 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/http2_trace_printer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/http2_trace_printer.cc @@ -7,7 +7,7 @@ #include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "quiche/http2/core/http2_trace_logging.h" -#include "quiche/spdy/core/spdy_protocol.h" +#include "quiche/http2/core/spdy_protocol.h" namespace http2 { namespace test { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/http2_trace_printer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/http2_trace_printer.h index b965ad87f0..3dc92af14d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/http2_trace_printer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/http2_trace_printer.h @@ -4,10 +4,10 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/http2_frame_decoder_adapter.h" #include "quiche/http2/core/http2_trace_logging.h" +#include "quiche/http2/core/spdy_no_op_visitor.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/http2_frame_decoder_adapter.h" -#include "quiche/spdy/core/spdy_no_op_visitor.h" namespace http2 { namespace test { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_framer_visitor.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/mock_spdy_framer_visitor.cc similarity index 86% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_framer_visitor.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/mock_spdy_framer_visitor.cc index 079ff3775f..22933e6c59 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_framer_visitor.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/mock_spdy_framer_visitor.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/test_tools/mock_spdy_framer_visitor.h" +#include "quiche/http2/test_tools/mock_spdy_framer_visitor.h" namespace spdy { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_framer_visitor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/mock_spdy_framer_visitor.h similarity index 90% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_framer_visitor.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/mock_spdy_framer_visitor.h index 3369d26e84..a66764d64d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_framer_visitor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/mock_spdy_framer_visitor.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_TEST_TOOLS_MOCK_SPDY_FRAMER_VISITOR_H_ -#define QUICHE_SPDY_TEST_TOOLS_MOCK_SPDY_FRAMER_VISITOR_H_ +#ifndef QUICHE_HTTP2_TEST_TOOLS_MOCK_SPDY_FRAMER_VISITOR_H_ +#define QUICHE_HTTP2_TEST_TOOLS_MOCK_SPDY_FRAMER_VISITOR_H_ #include #include @@ -11,14 +11,15 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/http2_frame_decoder_adapter.h" +#include "quiche/http2/core/recording_headers_handler.h" +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" +#include "quiche/http2/core/spdy_protocol.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_test.h" -#include "quiche/spdy/core/http2_frame_decoder_adapter.h" -#include "quiche/spdy/core/recording_headers_handler.h" -#include "quiche/spdy/core/spdy_alt_svc_wire_format.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" -#include "quiche/spdy/core/spdy_protocol.h" +// TODO(b/318698478): fix namespace and class name namespace spdy { namespace test { @@ -126,4 +127,4 @@ class QUICHE_NO_EXPORT MockSpdyFramerVisitor } // namespace spdy -#endif // QUICHE_SPDY_TEST_TOOLS_MOCK_SPDY_FRAMER_VISITOR_H_ +#endif // QUICHE_HTTP2_TEST_TOOLS_MOCK_SPDY_FRAMER_VISITOR_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/spdy_test_utils.cc similarity index 97% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.cc rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/spdy_test_utils.cc index fed9c16711..766acce887 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/spdy_test_utils.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "quiche/spdy/test_tools/spdy_test_utils.h" +#include "quiche/http2/test_tools/spdy_test_utils.h" #include #include @@ -10,10 +10,10 @@ #include #include +#include "quiche/http2/core/spdy_protocol.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/platform/api/quiche_test.h" #include "quiche/common/quiche_endian.h" -#include "quiche/spdy/core/spdy_protocol.h" namespace spdy { namespace test { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/spdy_test_utils.h similarity index 79% rename from naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.h rename to naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/spdy_test_utils.h index 5cf40cfc72..ff49121b57 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/test_tools/spdy_test_utils.h @@ -2,17 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_SPDY_TEST_TOOLS_SPDY_TEST_UTILS_H_ -#define QUICHE_SPDY_TEST_TOOLS_SPDY_TEST_UTILS_H_ +#ifndef QUICHE_HTTP2_TEST_TOOLS_SPDY_TEST_UTILS_H_ +#define QUICHE_HTTP2_TEST_TOOLS_SPDY_TEST_UTILS_H_ #include #include #include #include "absl/strings/string_view.h" -#include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/spdy_protocol.h" +#include "quiche/http2/core/spdy_protocol.h" +#include "quiche/common/http/http_header_block.h" +// TODO(b/318698478): update the namespace and file name namespace spdy { inline bool operator==(absl::string_view x, @@ -42,4 +43,4 @@ SpdySerializedFrame MakeSerializedFrame(const char* data, size_t length); } // namespace test } // namespace spdy -#endif // QUICHE_SPDY_TEST_TOOLS_SPDY_TEST_UTILS_H_ +#endif // QUICHE_HTTP2_TEST_TOOLS_SPDY_TEST_UTILS_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.cc index 144e8bba1d..1eee5908b4 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.cc @@ -56,25 +56,30 @@ class LibeventAlarm : public QuicAlarm { void CancelImpl() override { event_del(event_.get()); } private: - // While we inline `struct event` elsewhere, it is actually quite large, so - // doing that for the libevent-based QuicAlarm would cause it to not fit into - // the QuicConnectionArena. - struct EventDeleter { - void operator()(event* ev) { event_free(ev); } - }; - std::unique_ptr event_; + std::unique_ptr event_; QuicClock* clock_; }; LibeventQuicEventLoop::LibeventQuicEventLoop(event_base* base, QuicClock* clock) : base_(base), edge_triggered_(event_base_get_features(base) & EV_FEATURE_ET), - clock_(clock) { + clock_(clock), + artifical_event_timer_(evtimer_new( + base_, + [](evutil_socket_t, LibeventEventMask, void* arg) { + auto* self = reinterpret_cast(arg); + self->ActivateArtificialEvents(); + }, + this)) { QUICHE_CHECK_LE(sizeof(event), event_get_struct_event_size()) << "libevent ABI mismatch: sizeof(event) is bigger than the one QUICHE " "has been compiled with"; } +LibeventQuicEventLoop::~LibeventQuicEventLoop() { + event_del(artifical_event_timer_.get()); +} + bool LibeventQuicEventLoop::RegisterSocket(QuicUdpSocketFd fd, QuicSocketEventMask events, QuicSocketEventListener* listener) { @@ -84,6 +89,7 @@ bool LibeventQuicEventLoop::RegisterSocket(QuicUdpSocketFd fd, } bool LibeventQuicEventLoop::UnregisterSocket(QuicUdpSocketFd fd) { + fds_with_artifical_events_.erase(fd); return registration_map_.erase(fd); } @@ -108,10 +114,30 @@ bool LibeventQuicEventLoop::ArtificiallyNotifyEvent( if (it == registration_map_.end()) { return false; } - it->second.ArtificiallyNotify(events); + it->second.RecordArtificalEvents(events); + fds_with_artifical_events_.insert(fd); + if (!evtimer_pending(artifical_event_timer_.get(), nullptr)) { + struct timeval tv = {0, 0}; // Fire immediately in the next iteration. + evtimer_add(artifical_event_timer_.get(), &tv); + } return true; } +void LibeventQuicEventLoop::ActivateArtificialEvents() { + absl::flat_hash_set fds_with_artifical_events; + { + using std::swap; + swap(fds_with_artifical_events_, fds_with_artifical_events); + } + for (QuicUdpSocketFd fd : fds_with_artifical_events) { + auto it = registration_map_.find(fd); + if (it == registration_map_.end()) { + continue; + } + it->second.MaybeNotifyArtificalEvents(); + } +} + void LibeventQuicEventLoop::RunEventLoopOnce(QuicTime::Delta default_timeout) { timeval timeout = absl::ToTimeval(absl::Microseconds(default_timeout.ToMicroseconds())); @@ -156,8 +182,18 @@ LibeventQuicEventLoop::Registration::~Registration() { } } -void LibeventQuicEventLoop::Registration::ArtificiallyNotify( +void LibeventQuicEventLoop::Registration::RecordArtificalEvents( QuicSocketEventMask events) { + artificial_events_ |= events; +} + +void LibeventQuicEventLoop::Registration::MaybeNotifyArtificalEvents() { + if (artificial_events_ == 0) { + return; + } + QuicSocketEventMask events = artificial_events_; + artificial_events_ = 0; + if (loop_->SupportsEdgeTriggered()) { event_active(&both_events_, QuicEventsToLibeventEventMask(events), 0); return; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.h index 82783e9a1c..0078eb6d1a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.h @@ -6,7 +6,10 @@ #define QUICHE_QUIC_BINDINGS_QUIC_LIBEVENT_H_ #include +#include +#include +#include "absl/container/flat_hash_set.h" #include "absl/container/node_hash_map.h" #include "event2/event.h" #include "event2/event_struct.h" @@ -17,12 +20,20 @@ namespace quic { +// While we inline `struct event` sometimes, it is actually quite large, so +// doing that for the libevent-based QuicAlarm would cause it to not fit into +// the QuicConnectionArena. +struct QUICHE_NO_EXPORT LibeventEventDeleter { + void operator()(event* ev) { event_free(ev); } +}; + // Provides a libevent-based implementation of QuicEventLoop. Since libevent // uses relative time for all timeouts, the provided clock does not need to use // the UNIX time. class QUICHE_EXPORT LibeventQuicEventLoop : public QuicEventLoop { public: explicit LibeventQuicEventLoop(event_base* base, QuicClock* clock); + ~LibeventQuicEventLoop() override; // QuicEventLoop implementation. bool SupportsEdgeTriggered() const override { return edge_triggered_; } @@ -46,6 +57,8 @@ class QUICHE_EXPORT LibeventQuicEventLoop : public QuicEventLoop { QuicClock* clock() const { return clock_; } private: + void ActivateArtificialEvents(); + class AlarmFactory : public QuicAlarmFactory { public: AlarmFactory(LibeventQuicEventLoop* loop) : loop_(loop) {} @@ -66,9 +79,16 @@ class QUICHE_EXPORT LibeventQuicEventLoop : public QuicEventLoop { QuicSocketEventMask events, QuicSocketEventListener* listener); ~Registration(); - void ArtificiallyNotify(QuicSocketEventMask events); void Rearm(QuicSocketEventMask events); + // Record artificial events that should be notified on the next iteration of + // the event loop. + void RecordArtificalEvents(QuicSocketEventMask events); + + // If any artificial events have been recorded, notify the listener about + // them in the current iteration. + void MaybeNotifyArtificalEvents(); + private: LibeventQuicEventLoop* loop_; QuicSocketEventListener* listener_; @@ -79,6 +99,9 @@ class QUICHE_EXPORT LibeventQuicEventLoop : public QuicEventLoop { // events and write events separately. event read_event_; event write_event_; + + // Recorded artificial events to be notified on the next iteration. + QuicSocketEventMask artificial_events_ = 0; }; using RegistrationMap = absl::node_hash_map; @@ -88,6 +111,8 @@ class QUICHE_EXPORT LibeventQuicEventLoop : public QuicEventLoop { QuicClock* clock_; RegistrationMap registration_map_; + std::unique_ptr artifical_event_timer_; + absl::flat_hash_set fds_with_artifical_events_; }; // RAII-style wrapper around event_base. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_gso_batch_writer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_gso_batch_writer.h index b409bf5082..d9f0cb60be 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_gso_batch_writer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_gso_batch_writer.h @@ -5,7 +5,10 @@ #ifndef QUICHE_QUIC_CORE_BATCH_WRITER_QUIC_GSO_BATCH_WRITER_H_ #define QUICHE_QUIC_CORE_BATCH_WRITER_QUIC_GSO_BATCH_WRITER_H_ +#include + #include "quiche/quic/core/batch_writer/quic_batch_writer_base.h" +#include "quiche/quic/core/quic_linux_socket_utils.h" namespace quic { @@ -71,11 +74,12 @@ class QUICHE_EXPORT QuicGsoBatchWriter : public QuicUdpBatchWriter { /*num_packets_sent=*/0, /*bytes_written=*/0}; WriteResult& write_result = result.write_result; - int total_bytes = batch_buffer().SizeInUse(); + size_t total_bytes = batch_buffer().SizeInUse(); const BufferedWrite& first = buffered_writes().front(); char cbuf[CmsgSpace]; - QuicMsgHdr hdr(first.buffer, total_bytes, first.peer_address, cbuf, - sizeof(cbuf)); + iovec iov{const_cast(first.buffer), total_bytes}; + QuicMsgHdr hdr(&iov, 1, cbuf, sizeof(cbuf)); + hdr.SetPeerAddress(first.peer_address); uint16_t gso_size = buffered_writes().size() > 1 ? first.buf_len : 0; cmsg_builder(&hdr, first.self_address, gso_size, first.release_time, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc index 60869fbb83..be7f132f82 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc @@ -199,6 +199,7 @@ void Bbr2Sender::ApplyConnectionOptions( } if (GetQuicReloadableFlag(quic_bbr2_enable_bbpd_by_default) || ContainsQuicTag(connection_options, kBBPD)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_enable_bbpd_by_default); // Derived constant to ensure fairness. params_.probe_bw_probe_down_pacing_gain = 0.91; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h index 6d5750b71e..c4971de61a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_protocol.h @@ -441,6 +441,11 @@ const QuicTag kGWCH = TAG('G', 'W', 'C', 'H'); const QuicTag kYTCH = TAG('Y', 'T', 'C', 'H'); const QuicTag kACH0 = TAG('A', 'C', 'H', '0'); +// Client sends this connection option to express the intention of skipping IP +// matching when trying to send a request on active sessions. If server echos +// back this connection option, client can actually skip IP matching. +const QuicTag kNOIP = TAG('N', 'O', 'I', 'P'); + // Rejection tags const QuicTag kRREJ = TAG('R', 'R', 'E', 'J'); // Reasons for server sending diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_header_list.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_header_list.h index 335cf4b77b..51c2a82162 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_header_list.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_header_list.h @@ -11,10 +11,10 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/common/quiche_circular_deque.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" namespace quic { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.cc index c036c2c236..ed0bb27225 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.cc @@ -17,7 +17,7 @@ void QuicServerInitiatedSpdyStream::OnBodyAvailable() { } size_t QuicServerInitiatedSpdyStream::WriteHeaders( - spdy::Http2HeaderBlock /*header_block*/, bool /*fin*/, + quiche::HttpHeaderBlock /*header_block*/, bool /*fin*/, quiche::QuicheReferenceCountedPointer< QuicAckListenerInterface> /*ack_listener*/) { QUIC_BUG(Writing headers in QuicServerInitiatedSpdyStream) diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.h index ce0ba63b1b..abf70c431e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.h @@ -6,7 +6,7 @@ #define QUICHE_QUIC_CORE_HTTP_QUIC_SERVER_INITIATED_SPDY_STREAM_H_ #include "quiche/quic/core/http/quic_spdy_stream.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -19,7 +19,7 @@ class QUICHE_EXPORT QuicServerInitiatedSpdyStream : public QuicSpdyStream { void OnBodyAvailable() override; size_t WriteHeaders( - spdy::Http2HeaderBlock header_block, bool fin, + quiche::HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_listener) override; void OnInitialHeadersComplete(bool fin, size_t frame_len, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.cc index ad821ff2e5..305f98f97c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.cc @@ -13,7 +13,7 @@ #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_logging.h" -using spdy::Http2HeaderBlock; +using quiche::HttpHeaderBlock; namespace quic { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h index afb4dd184e..7a562b9bff 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h @@ -11,7 +11,7 @@ #include "quiche/quic/core/http/quic_spdy_session.h" #include "quiche/quic/core/quic_crypto_client_stream.h" #include "quiche/quic/platform/api/quic_export.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc index 323fa9baf6..99f93e37e3 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc @@ -19,7 +19,7 @@ #include "quiche/common/quiche_text_utils.h" #include "quiche/spdy/core/spdy_protocol.h" -using spdy::Http2HeaderBlock; +using quiche::HttpHeaderBlock; namespace quic { @@ -46,7 +46,7 @@ QuicSpdyClientStream::~QuicSpdyClientStream() = default; bool QuicSpdyClientStream::CopyAndValidateHeaders( const QuicHeaderList& header_list, int64_t& content_length, - spdy::Http2HeaderBlock& headers) { + quiche::HttpHeaderBlock& headers) { return SpdyUtils::CopyAndValidateHeaders(header_list, &content_length, &headers); } @@ -158,7 +158,7 @@ void QuicSpdyClientStream::OnBodyAvailable() { } } -size_t QuicSpdyClientStream::SendRequest(Http2HeaderBlock headers, +size_t QuicSpdyClientStream::SendRequest(HttpHeaderBlock headers, absl::string_view body, bool fin) { QuicConnection::ScopedPacketFlusher flusher(session_->connection()); bool send_fin_with_headers = fin && body.empty(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.h index bbe922abfb..d5df1a619e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.h @@ -12,7 +12,7 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/http/quic_spdy_stream.h" #include "quiche/quic/core/quic_packets.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/spdy/core/spdy_framer.h" namespace quic { @@ -46,16 +46,18 @@ class QUICHE_EXPORT QuicSpdyClientStream : public QuicSpdyStream { // Serializes the headers and body, sends it to the server, and // returns the number of bytes sent. - size_t SendRequest(spdy::Http2HeaderBlock headers, absl::string_view body, + size_t SendRequest(quiche::HttpHeaderBlock headers, absl::string_view body, bool fin); // Returns the response data. absl::string_view data() const { return data_; } // Returns whatever headers have been received for this stream. - const spdy::Http2HeaderBlock& response_headers() { return response_headers_; } + const quiche::HttpHeaderBlock& response_headers() { + return response_headers_; + } - const std::list& preliminary_headers() { + const std::list& preliminary_headers() { return preliminary_headers_; } @@ -84,7 +86,7 @@ class QUICHE_EXPORT QuicSpdyClientStream : public QuicSpdyStream { // on error. virtual bool CopyAndValidateHeaders(const QuicHeaderList& header_list, int64_t& content_length, - spdy::Http2HeaderBlock& headers); + quiche::HttpHeaderBlock& headers); // Called by OnInitialHeadersComplete to set response_code_ based on // response_header_. Returns false on error. @@ -96,7 +98,7 @@ class QUICHE_EXPORT QuicSpdyClientStream : public QuicSpdyStream { private: // The parsed headers received from the server. - spdy::Http2HeaderBlock response_headers_; + quiche::HttpHeaderBlock response_headers_; // The parsed content-length, or -1 if none is specified. int64_t content_length_; @@ -110,7 +112,7 @@ class QUICHE_EXPORT QuicSpdyClientStream : public QuicSpdyStream { // These preliminary headers are used for interim response headers that may // arrive before the final response headers. - std::list preliminary_headers_; + std::list preliminary_headers_; QuicTime::Delta time_to_response_headers_received_ = QuicTime::Delta::Infinite(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc index 687e29efbe..edfbb4a801 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc @@ -39,7 +39,7 @@ #include "quiche/spdy/core/http2_frame_decoder_adapter.h" using http2::Http2DecoderAdapter; -using spdy::Http2HeaderBlock; +using quiche::HttpHeaderBlock; using spdy::Http2WeightToSpdy3Priority; using spdy::Spdy3PriorityToHttp2Weight; using spdy::SpdyErrorCode; @@ -729,7 +729,7 @@ size_t QuicSpdySession::ProcessHeaderData(const struct iovec& iov) { } size_t QuicSpdySession::WriteHeadersOnHeadersStream( - QuicStreamId id, Http2HeaderBlock headers, bool fin, + QuicStreamId id, HttpHeaderBlock headers, bool fin, const spdy::SpdyStreamPrecedence& precedence, quiche::QuicheReferenceCountedPointer ack_listener) { @@ -867,8 +867,7 @@ void QuicSpdySession::SendInitialData() { } bool QuicSpdySession::CheckStreamWriteBlocked(QuicStream* stream) const { - if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5) && - qpack_decoder_send_stream_ != nullptr && + if (qpack_decoder_send_stream_ != nullptr && stream->id() == qpack_decoder_send_stream_->id()) { // Decoder data is always bundled opportunistically. return true; @@ -957,7 +956,7 @@ bool QuicSpdySession::UsesPendingStreamForFrame(QuicFrameType type, } size_t QuicSpdySession::WriteHeadersOnHeadersStreamImpl( - QuicStreamId id, spdy::Http2HeaderBlock headers, bool fin, + QuicStreamId id, quiche::HttpHeaderBlock headers, bool fin, QuicStreamId parent_stream_id, int weight, bool exclusive, quiche::QuicheReferenceCountedPointer ack_listener) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h index 2e614e1179..92cf9e750f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h @@ -32,8 +32,8 @@ #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/platform/api/quic_export.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/spdy/core/http2_frame_decoder_adapter.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -109,7 +109,7 @@ class QUICHE_EXPORT Http3DebugVisitor { QuicByteCount /*payload_length*/) = 0; virtual void OnHeadersFrameSent( QuicStreamId /*stream_id*/, - const spdy::Http2HeaderBlock& /*header_block*/) = 0; + const quiche::HttpHeaderBlock& /*header_block*/) = 0; // 0-RTT related events. virtual void OnSettingsFrameResumed(const SettingsFrame& /*frame*/) = 0; @@ -217,7 +217,7 @@ class QUICHE_EXPORT QuicSpdySession // If provided, |ack_notifier_delegate| will be registered to be notified when // we have seen ACKs for all packets resulting from this call. virtual size_t WriteHeadersOnHeadersStream( - QuicStreamId id, spdy::Http2HeaderBlock headers, bool fin, + QuicStreamId id, quiche::HttpHeaderBlock headers, bool fin, const spdy::SpdyStreamPrecedence& precedence, quiche::QuicheReferenceCountedPointer ack_listener); @@ -515,7 +515,7 @@ class QUICHE_EXPORT QuicSpdySession PendingStream* pending) override; size_t WriteHeadersOnHeadersStreamImpl( - QuicStreamId id, spdy::Http2HeaderBlock headers, bool fin, + QuicStreamId id, quiche::HttpHeaderBlock headers, bool fin, QuicStreamId parent_stream_id, int weight, bool exclusive, quiche::QuicheReferenceCountedPointer ack_listener); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc index 163420272c..59b0644937 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc @@ -45,7 +45,7 @@ using ::quiche::Capsule; using ::quiche::CapsuleType; -using ::spdy::Http2HeaderBlock; +using ::quiche::HttpHeaderBlock; namespace quic { @@ -267,7 +267,7 @@ QuicSpdyStream::QuicSpdyStream(PendingStream* pending, QuicSpdyStream::~QuicSpdyStream() {} size_t QuicSpdyStream::WriteHeaders( - Http2HeaderBlock header_block, bool fin, + HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_listener) { if (!AssertNotWebTransportDataStream("writing headers")) { @@ -344,7 +344,7 @@ void QuicSpdyStream::WriteOrBufferBody(absl::string_view data, bool fin) { } size_t QuicSpdyStream::WriteTrailers( - Http2HeaderBlock trailer_block, + HttpHeaderBlock trailer_block, quiche::QuicheReferenceCountedPointer ack_listener) { if (fin_sent()) { @@ -577,19 +577,9 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers, /* is_sent = */ false, headers.compressed_header_bytes(), headers.uncompressed_header_bytes()); - Http3DebugVisitor* const debug_visitor = spdy_session()->debug_visitor(); - if (debug_visitor) { - debug_visitor->OnHeadersDecoded(id(), headers); - } - - OnStreamHeaderList(/* fin = */ false, headers_payload_length_, headers); - header_decoding_delay_ = QuicTime::Delta::Zero(); if (blocked_on_decoding_headers_) { - blocked_on_decoding_headers_ = false; - // Continue decoding HTTP/3 frames. - OnDataAvailable(); const QuicTime now = session()->GetClock()->ApproximateNow(); if (!header_block_received_time_.IsInitialized() || now < header_block_received_time_) { @@ -598,6 +588,19 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers, header_decoding_delay_ = now - header_block_received_time_; } } + + Http3DebugVisitor* const debug_visitor = spdy_session()->debug_visitor(); + if (debug_visitor) { + debug_visitor->OnHeadersDecoded(id(), headers); + } + + OnStreamHeaderList(/* fin = */ false, headers_payload_length_, headers); + + if (blocked_on_decoding_headers_) { + blocked_on_decoding_headers_ = false; + // Continue decoding HTTP/3 frames. + OnDataAvailable(); + } } void QuicSpdyStream::OnHeaderDecodingError(QuicErrorCode error_code, @@ -678,10 +681,9 @@ void QuicSpdyStream::OnInitialHeadersComplete( } } -bool QuicSpdyStream::CopyAndValidateTrailers(const QuicHeaderList& header_list, - bool expect_final_byte_offset, - size_t* final_byte_offset, - spdy::Http2HeaderBlock* trailers) { +bool QuicSpdyStream::CopyAndValidateTrailers( + const QuicHeaderList& header_list, bool expect_final_byte_offset, + size_t* final_byte_offset, quiche::HttpHeaderBlock* trailers) { return SpdyUtils::CopyAndValidateTrailers( header_list, expect_final_byte_offset, final_byte_offset, trailers); } @@ -930,9 +932,9 @@ bool QuicSpdyStream::FinishedReadingHeaders() const { return headers_decompressed_ && header_list_.empty(); } -bool QuicSpdyStream::ParseHeaderStatusCode(const Http2HeaderBlock& header, +bool QuicSpdyStream::ParseHeaderStatusCode(const HttpHeaderBlock& header, int* status_code) { - Http2HeaderBlock::const_iterator it = header.find(spdy::kHttp2StatusHeader); + HttpHeaderBlock::const_iterator it = header.find(spdy::kHttp2StatusHeader); if (it == header.end()) { return false; } @@ -1284,7 +1286,7 @@ bool QuicSpdyStream::OnUnknownFramePayload(absl::string_view payload) { bool QuicSpdyStream::OnUnknownFrameEnd() { return true; } size_t QuicSpdyStream::WriteHeadersImpl( - spdy::Http2HeaderBlock header_block, bool fin, + quiche::HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_listener) { if (!VersionUsesHttp3(transport_version())) { @@ -1378,7 +1380,7 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() { } void QuicSpdyStream::MaybeProcessSentWebTransportHeaders( - spdy::Http2HeaderBlock& headers) { + quiche::HttpHeaderBlock& headers) { if (!spdy_session_->SupportsWebTransport()) { return; } @@ -1822,6 +1824,20 @@ bool QuicSpdyStream::AreHeaderFieldValuesValid( return true; } +void QuicSpdyStream::StopReading() { + QuicStream::StopReading(); + if (GetQuicReloadableFlag( + quic_stop_reading_also_stops_header_decompression) && + VersionUsesHttp3(transport_version()) && !fin_received() && + spdy_session_->qpack_decoder()) { + QUIC_RELOADABLE_FLAG_COUNT( + quic_stop_reading_also_stops_header_decompression); + // Clean up Qpack decoding states. + spdy_session_->qpack_decoder()->OnStreamReset(id()); + qpack_decoded_headers_accumulator_.reset(); + } +} + void QuicSpdyStream::OnInvalidHeaders() { Reset(QUIC_BAD_APPLICATION_PAYLOAD); } void QuicSpdyStream::CloseReadSide() { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h index 4de6fe2867..ccb11c710e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h @@ -39,8 +39,8 @@ #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/common/capsule.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_mem_slice.h" -#include "quiche/spdy/core/http2_header_block.h" #include "quiche/spdy/core/spdy_framer.h" namespace quic { @@ -119,6 +119,7 @@ class QUICHE_EXPORT QuicSpdyStream // QuicStream implementation void OnClose() override; + void StopReading() override; // Override to maybe close the write side after writing. void OnCanWrite() override; @@ -156,7 +157,7 @@ class QUICHE_EXPORT QuicSpdyStream // number of bytes sent, including data sent on the encoder stream when using // QPACK. virtual size_t WriteHeaders( - spdy::Http2HeaderBlock header_block, bool fin, + quiche::HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_listener); @@ -168,7 +169,7 @@ class QUICHE_EXPORT QuicSpdyStream // always have the FIN flag set. Returns the number of bytes sent, including // data sent on the encoder stream when using QPACK. virtual size_t WriteTrailers( - spdy::Http2HeaderBlock trailer_block, + quiche::HttpHeaderBlock trailer_block, quiche::QuicheReferenceCountedPointer ack_listener); @@ -210,7 +211,7 @@ class QUICHE_EXPORT QuicSpdyStream // Returns true if header contains a valid 3-digit status and parse the status // code to |status_code|. - static bool ParseHeaderStatusCode(const spdy::Http2HeaderBlock& header, + static bool ParseHeaderStatusCode(const quiche::HttpHeaderBlock& header, int* status_code); // Returns true if status_value (associated with :status) contains a valid // 3-digit status and parse the status code to |status_code|. @@ -236,7 +237,7 @@ class QUICHE_EXPORT QuicSpdyStream bool trailers_decompressed() const { return trailers_decompressed_; } // Returns whatever trailers have been received for this stream. - const spdy::Http2HeaderBlock& received_trailers() const { + const quiche::HttpHeaderBlock& received_trailers() const { return received_trailers_; } @@ -360,14 +361,14 @@ class QUICHE_EXPORT QuicSpdyStream virtual void OnTrailingHeadersComplete(bool fin, size_t frame_len, const QuicHeaderList& header_list); virtual size_t WriteHeadersImpl( - spdy::Http2HeaderBlock header_block, bool fin, + quiche::HttpHeaderBlock header_block, bool fin, quiche::QuicheReferenceCountedPointer ack_listener); virtual bool CopyAndValidateTrailers(const QuicHeaderList& header_list, bool expect_final_byte_offset, size_t* final_byte_offset, - spdy::Http2HeaderBlock* trailers); + quiche::HttpHeaderBlock* trailers); Visitor* visitor() { return visitor_; } @@ -438,7 +439,7 @@ class QUICHE_EXPORT QuicSpdyStream QuicByteCount GetNumFrameHeadersInInterval(QuicStreamOffset offset, QuicByteCount data_length) const; - void MaybeProcessSentWebTransportHeaders(spdy::Http2HeaderBlock& headers); + void MaybeProcessSentWebTransportHeaders(quiche::HttpHeaderBlock& headers); void MaybeProcessReceivedWebTransportHeaders(); // Writes HTTP/3 DATA frame header. If |force_write| is true, use @@ -482,7 +483,7 @@ class QUICHE_EXPORT QuicSpdyStream bool trailers_consumed_; // The parsed trailers received from the peer. - spdy::Http2HeaderBlock received_trailers_; + quiche::HttpHeaderBlock received_trailers_; // Headers accumulator for decoding HEADERS frame payload. std::unique_ptr diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc index 7df35ef8c8..8e0d2061e1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc @@ -20,13 +20,13 @@ #include "quiche/common/quiche_text_utils.h" #include "quiche/spdy/core/spdy_protocol.h" -using spdy::Http2HeaderBlock; +using quiche::HttpHeaderBlock; namespace quic { // static bool SpdyUtils::ExtractContentLengthFromHeaders(int64_t* content_length, - Http2HeaderBlock* headers) { + HttpHeaderBlock* headers) { auto it = headers->find("content-length"); if (it == headers->end()) { return false; @@ -61,7 +61,7 @@ bool SpdyUtils::ExtractContentLengthFromHeaders(int64_t* content_length, bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list, int64_t* content_length, - Http2HeaderBlock* headers) { + HttpHeaderBlock* headers) { for (const auto& p : header_list) { const std::string& name = p.first; if (name.empty()) { @@ -90,7 +90,7 @@ bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list, bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list, bool expect_final_byte_offset, size_t* final_byte_offset, - Http2HeaderBlock* trailers) { + HttpHeaderBlock* trailers) { bool found_final_byte_offset = false; for (const auto& p : header_list) { const std::string& name = p.first; @@ -135,7 +135,7 @@ bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list, // static // TODO(danzh): Move it to quic/tools/ and switch to use GURL. bool SpdyUtils::PopulateHeaderBlockFromUrl(const std::string url, - Http2HeaderBlock* headers) { + HttpHeaderBlock* headers) { (*headers)[":method"] = "GET"; size_t pos = url.find("://"); if (pos == std::string::npos) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h index 0b0b85407f..2118a4d3d5 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h @@ -14,7 +14,7 @@ #include "quiche/quic/core/http/quic_header_list.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/platform/api/quic_export.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/spdy/core/spdy_alt_svc_wire_format.h" namespace quic { @@ -27,12 +27,12 @@ class QUICHE_EXPORT SpdyUtils { // Returns true on success, false if parsing fails or content-length header is // missing. static bool ExtractContentLengthFromHeaders(int64_t* content_length, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); // Copies a list of headers to a Http2HeaderBlock. static bool CopyAndValidateHeaders(const QuicHeaderList& header_list, int64_t* content_length, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); // Copies a list of headers to a Http2HeaderBlock. // If |expect_final_byte_offset| is true, requires exactly one header field @@ -47,12 +47,12 @@ class QUICHE_EXPORT SpdyUtils { static bool CopyAndValidateTrailers(const QuicHeaderList& header_list, bool expect_final_byte_offset, size_t* final_byte_offset, - spdy::Http2HeaderBlock* trailers); + quiche::HttpHeaderBlock* trailers); // Populates the fields of |headers| to make a GET request of |url|, // which must be fully-qualified. static bool PopulateHeaderBlockFromUrl(const std::string url, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); // Returns the advertised QUIC version from the specified alternative service // advertisement, or ParsedQuicVersion::Unsupported() if no supported version diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc index e3d4472f41..d0687ee7b1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc @@ -164,7 +164,8 @@ void WebTransportHttp3::CloseSessionWithFinOnlyForTests() { connect_stream_->WriteOrBufferBody("", /*fin=*/true); } -void WebTransportHttp3::HeadersReceived(const spdy::Http2HeaderBlock& headers) { +void WebTransportHttp3::HeadersReceived( + const quiche::HttpHeaderBlock& headers) { if (session_->perspective() == Perspective::IS_CLIENT) { int status_code; if (!QuicSpdyStream::ParseHeaderStatusCode(headers, &status_code)) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.h index 4f3815b06b..b6d51101f9 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.h @@ -18,10 +18,10 @@ #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/web_transport_interface.h" #include "quiche/quic/core/web_transport_stats.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_mem_slice.h" #include "quiche/common/quiche_callbacks.h" #include "quiche/web_transport/web_transport.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -48,7 +48,7 @@ class QUICHE_EXPORT WebTransportHttp3 WebTransportHttp3(QuicSpdySession* session, QuicSpdyStream* connect_stream, WebTransportSessionId id); - void HeadersReceived(const spdy::Http2HeaderBlock& headers); + void HeadersReceived(const quiche::HttpHeaderBlock& headers); void SetVisitor(std::unique_ptr visitor) { visitor_ = std::move(visitor); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/io/quic_poll_event_loop.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/io/quic_poll_event_loop.cc index aafe414869..ffe222abf0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/io/quic_poll_event_loop.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/io/quic_poll_event_loop.cc @@ -178,10 +178,10 @@ void QuicPollEventLoop::DispatchIoEvent(std::vector& ready_list, Registration& registration = *it->second; mask |= GetPollMask(registration.artificially_notify_at_next_iteration); - registration.artificially_notify_at_next_iteration = QuicSocketEventMask(); - // poll() always returns certain classes of events even if not requested. - mask &= GetPollMask(registration.events); + mask &= GetPollMask(registration.events | + registration.artificially_notify_at_next_iteration); + registration.artificially_notify_at_next_iteration = QuicSocketEventMask(); if (!mask) { return; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder.cc index f128fc963a..49c7e81417 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder.cc @@ -32,9 +32,6 @@ QpackDecoder::~QpackDecoder() {} void QpackDecoder::OnStreamReset(QuicStreamId stream_id) { if (header_table_.maximum_dynamic_table_capacity() > 0) { decoder_stream_sender_.SendStreamCancellation(stream_id); - if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { - decoder_stream_sender_.Flush(); - } } } @@ -68,10 +65,6 @@ void QpackDecoder::OnDecodingCompleted(QuicStreamId stream_id, header_table_.inserted_entry_count() - known_received_count_); known_received_count_ = header_table_.inserted_entry_count(); } - - if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { - decoder_stream_sender_.Flush(); - } } void QpackDecoder::OnInsertWithNameReference(bool is_static, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc index 7ebc9a550e..d512788455 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc @@ -42,17 +42,12 @@ void QpackDecoderStreamSender::Flush() { if (buffer_.empty() || delegate_ == nullptr) { return; } - if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { - QUIC_RESTART_FLAG_COUNT_N(quic_opport_bundle_qpack_decoder_data5, 3, 4); - // Swap buffer_ before calling WriteStreamData, which might result in a - // reentrant call to `Flush()`. - std::string copy; - std::swap(copy, buffer_); - delegate_->WriteStreamData(copy); - return; - } - delegate_->WriteStreamData(buffer_); - buffer_.clear(); + + // Swap buffer_ before calling WriteStreamData, which might result in a + // reentrant call to `Flush()`. + std::string copy; + std::swap(copy, buffer_); + delegate_->WriteStreamData(copy); } } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc index 4433861fe8..fda0e3c4cf 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc @@ -78,7 +78,7 @@ QpackEncoder::Representation QpackEncoder::EncodeLiteralHeaderField( } QpackEncoder::Representations QpackEncoder::FirstPassEncode( - QuicStreamId stream_id, const spdy::Http2HeaderBlock& header_list, + QuicStreamId stream_id, const quiche::HttpHeaderBlock& header_list, QpackBlockingManager::IndexSet* referred_indices, QuicByteCount* encoder_stream_sent_byte_count) { // If previous instructions are buffered in |encoder_stream_sender_|, @@ -177,14 +177,6 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode( // Match cannot be used. - if (!better_compression_) { - // Encode entry as string literals. - representations.push_back(EncodeLiteralHeaderField(name, value)); - break; - } - - QUIC_RELOADABLE_FLAG_COUNT(quic_better_qpack_compression); - QpackEncoderHeaderTable::MatchResult match_result_name_only = header_table_.FindHeaderName(name); @@ -397,7 +389,7 @@ std::string QpackEncoder::SecondPassEncode( } std::string QpackEncoder::EncodeHeaderList( - QuicStreamId stream_id, const spdy::Http2HeaderBlock& header_list, + QuicStreamId stream_id, const quiche::HttpHeaderBlock& header_list, QuicByteCount* encoder_stream_sent_byte_count) { // Keep track of all dynamic table indices that this header block refers to so // that it can be passed to QpackBlockingManager. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h index ae1d440548..a631ac41d0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h @@ -21,7 +21,7 @@ #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_exported_stats.h" #include "quiche/quic/platform/api/quic_flags.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -53,7 +53,7 @@ class QUICHE_EXPORT QpackEncoder : public QpackDecoderStreamReceiver::Delegate { // |*encoder_stream_sent_byte_count| will be set to the number of bytes sent // on the encoder stream to insert dynamic table entries. std::string EncodeHeaderList(QuicStreamId stream_id, - const spdy::Http2HeaderBlock& header_list, + const quiche::HttpHeaderBlock& header_list, QuicByteCount* encoder_stream_sent_byte_count); // Set maximum dynamic table capacity to |maximum_dynamic_table_capacity|, @@ -137,7 +137,7 @@ class QUICHE_EXPORT QpackEncoder : public QpackDecoderStreamReceiver::Delegate { // absolute indices. Returned representation objects may have // absl::string_views pointing to strings owned by |*header_list|. Representations FirstPassEncode( - QuicStreamId stream_id, const spdy::Http2HeaderBlock& header_list, + QuicStreamId stream_id, const quiche::HttpHeaderBlock& header_list, QpackBlockingManager::IndexSet* referred_indices, QuicByteCount* encoder_stream_sent_byte_count); @@ -155,10 +155,6 @@ class QUICHE_EXPORT QpackEncoder : public QpackDecoderStreamReceiver::Delegate { uint64_t maximum_blocked_streams_; QpackBlockingManager blocking_manager_; int header_list_count_; - - // Latched value of reloadable_flag_quic_better_qpack_compression. - const bool better_compression_ = - GetQuicReloadableFlag(quic_better_qpack_compression); }; // QpackEncoder::DecoderStreamErrorDelegate implementation that does nothing. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.h index 748c11b84d..a57b478fe4 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.h @@ -9,10 +9,10 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/hpack/hpack_entry.h" +#include "quiche/http2/hpack/hpack_header_table.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/common/quiche_circular_deque.h" -#include "quiche/spdy/core/hpack/hpack_entry.h" -#include "quiche/spdy/core/hpack/hpack_header_table.h" namespace quic { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc index aada6ae27c..eeac8ceea6 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc @@ -168,7 +168,7 @@ void QpackInstructionEncoder::DoWriteString(absl::string_view name, absl::string_view string_to_write = (field_->type == QpackInstructionFieldType::kName) ? name : value; if (use_huffman_) { - http2::HuffmanEncodeFast(string_to_write, string_length_, output); + http2::HuffmanEncode(string_to_write, string_length_, output); } else { absl::StrAppend(output, string_to_write); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_static_table.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_static_table.h index 89ec2542c8..f3a15966b5 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_static_table.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_static_table.h @@ -7,9 +7,9 @@ #include +#include "quiche/http2/hpack/hpack_constants.h" +#include "quiche/http2/hpack/hpack_static_table.h" #include "quiche/quic/platform/api/quic_export.h" -#include "quiche/spdy/core/hpack/hpack_constants.h" -#include "quiche/spdy/core/hpack/hpack_static_table.h" namespace quic { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.cc index 754b6734cd..ad6d3a408b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.cc @@ -20,8 +20,8 @@ const char kNonCookieSeparator = '\0'; } // namespace ValueSplittingHeaderList::const_iterator::const_iterator( - const spdy::Http2HeaderBlock* header_list, - spdy::Http2HeaderBlock::const_iterator header_list_iterator) + const quiche::HttpHeaderBlock* header_list, + quiche::HttpHeaderBlock::const_iterator header_list_iterator) : header_list_(header_list), header_list_iterator_(header_list_iterator), value_start_(0) { @@ -93,7 +93,7 @@ void ValueSplittingHeaderList::const_iterator::UpdateHeaderField() { } ValueSplittingHeaderList::ValueSplittingHeaderList( - const spdy::Http2HeaderBlock* header_list) + const quiche::HttpHeaderBlock* header_list) : header_list_(header_list) { QUICHE_DCHECK(header_list_); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.h index fb8d6474a6..1ef5f7c6c9 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.h @@ -7,7 +7,7 @@ #include "absl/strings/string_view.h" #include "quiche/quic/platform/api/quic_export.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -16,13 +16,14 @@ namespace quic { // cookies and along '\0' separators for other header fields. class QUICHE_EXPORT ValueSplittingHeaderList { public: - using value_type = spdy::Http2HeaderBlock::value_type; + using value_type = quiche::HttpHeaderBlock::value_type; class QUICHE_EXPORT const_iterator { public: // |header_list| must outlive this object. - const_iterator(const spdy::Http2HeaderBlock* header_list, - spdy::Http2HeaderBlock::const_iterator header_list_iterator); + const_iterator( + const quiche::HttpHeaderBlock* header_list, + quiche::HttpHeaderBlock::const_iterator header_list_iterator); const_iterator(const const_iterator&) = default; const_iterator& operator=(const const_iterator&) = delete; @@ -38,15 +39,15 @@ class QUICHE_EXPORT ValueSplittingHeaderList { // Find next separator; update |value_end_| and |header_field_|. void UpdateHeaderField(); - const spdy::Http2HeaderBlock* const header_list_; - spdy::Http2HeaderBlock::const_iterator header_list_iterator_; + const quiche::HttpHeaderBlock* const header_list_; + quiche::HttpHeaderBlock::const_iterator header_list_iterator_; absl::string_view::size_type value_start_; absl::string_view::size_type value_end_; value_type header_field_; }; // |header_list| must outlive this object. - explicit ValueSplittingHeaderList(const spdy::Http2HeaderBlock* header_list); + explicit ValueSplittingHeaderList(const quiche::HttpHeaderBlock* header_list); ValueSplittingHeaderList(const ValueSplittingHeaderList&) = delete; ValueSplittingHeaderList& operator=(const ValueSplittingHeaderList&) = delete; @@ -54,7 +55,7 @@ class QUICHE_EXPORT ValueSplittingHeaderList { const_iterator end() const; private: - const spdy::Http2HeaderBlock* const header_list_; + const quiche::HttpHeaderBlock* const header_list_; }; } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc index e65bad7e48..e2fb2259e1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.cc @@ -103,11 +103,15 @@ QuicBufferedPacketStore::~QuicBufferedPacketStore() { } EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket( - QuicConnectionId connection_id, bool ietf_quic, - const QuicReceivedPacket& packet, QuicSocketAddress self_address, - QuicSocketAddress peer_address, const ParsedQuicVersion& version, + const ReceivedPacketInfo& packet_info, std::optional parsed_chlo, ConnectionIdGeneratorInterface* connection_id_generator) { + QuicConnectionId connection_id = packet_info.destination_connection_id; + const QuicReceivedPacket& packet = packet_info.packet; + const QuicSocketAddress& self_address = packet_info.self_address; + const QuicSocketAddress& peer_address = packet_info.peer_address; + const ParsedQuicVersion& version = packet_info.version; + const bool ietf_quic = packet_info.form != GOOGLE_QUIC_PACKET; const bool is_chlo = parsed_chlo.has_value(); QUIC_BUG_IF(quic_bug_12410_1, !GetQuicFlag(quic_allow_chlo_buffering)) << "Shouldn't buffer packets if disabled via flag."; @@ -313,6 +317,7 @@ bool QuicBufferedPacketStore::IngestPacketForTlsChloExtraction( const QuicConnectionId& connection_id, const ParsedQuicVersion& version, const QuicReceivedPacket& packet, std::vector* out_supported_groups, + std::vector* out_cert_compression_algos, std::vector* out_alpns, std::string* out_sni, bool* out_resumption_attempted, bool* out_early_data_attempted, std::optional* tls_alert) { @@ -333,6 +338,7 @@ bool QuicBufferedPacketStore::IngestPacketForTlsChloExtraction( } const TlsChloExtractor& tls_chlo_extractor = it->second.tls_chlo_extractor; *out_supported_groups = tls_chlo_extractor.supported_groups(); + *out_cert_compression_algos = tls_chlo_extractor.cert_compression_algos(); *out_alpns = tls_chlo_extractor.alpns(); *out_sni = tls_chlo_extractor.server_name(); *out_resumption_attempted = tls_chlo_extractor.resumption_attempted(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.h index 4cff83d1e3..db9b74fcfc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_buffered_packet_store.h @@ -17,13 +17,19 @@ #include "quiche/quic/core/quic_alarm_factory.h" #include "quiche/quic/core/quic_clock.h" #include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_error_codes.h" +#include "quiche/quic/core/quic_packet_creator.h" #include "quiche/quic/core/quic_packets.h" +#include "quiche/quic/core/quic_stream_frame_data_producer.h" +#include "quiche/quic/core/quic_stream_send_buffer.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/core/tls_chlo_extractor.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_socket_address.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/quiche_buffer_allocator.h" #include "quiche/common/quiche_linked_hash_map.h" namespace quic { @@ -118,9 +124,7 @@ class QUICHE_EXPORT QuicBufferedPacketStore { // Generator to use with the connection. It is ignored if |parsed_chlo| is // absent. EnqueuePacketResult EnqueuePacket( - QuicConnectionId connection_id, bool ietf_quic, - const QuicReceivedPacket& packet, QuicSocketAddress self_address, - QuicSocketAddress peer_address, const ParsedQuicVersion& version, + const ReceivedPacketInfo& packet_info, std::optional parsed_chlo, ConnectionIdGeneratorInterface* connection_id_generator); @@ -142,6 +146,7 @@ class QUICHE_EXPORT QuicBufferedPacketStore { const QuicConnectionId& connection_id, const ParsedQuicVersion& version, const QuicReceivedPacket& packet, std::vector* out_supported_groups, + std::vector* out_cert_compression_algos, std::vector* out_alpns, std::string* out_sni, bool* out_resumption_attempted, bool* out_early_data_attempted, std::optional* tls_alert); @@ -208,6 +213,80 @@ class QUICHE_EXPORT QuicBufferedPacketStore { connections_with_chlo_; }; +// Collects packets serialized by a QuicPacketCreator. +class QUICHE_NO_EXPORT PacketCollector + : public QuicPacketCreator::DelegateInterface, + public QuicStreamFrameDataProducer { + public: + explicit PacketCollector(quiche::QuicheBufferAllocator* allocator) + : send_buffer_(allocator) {} + ~PacketCollector() override = default; + + // QuicPacketCreator::DelegateInterface methods: + void OnSerializedPacket(SerializedPacket serialized_packet) override { + // Make a copy of the serialized packet to send later. + packets_.emplace_back( + new QuicEncryptedPacket(CopyBuffer(serialized_packet), + serialized_packet.encrypted_length, true)); + } + + QuicPacketBuffer GetPacketBuffer() override { + // Let QuicPacketCreator to serialize packets on stack buffer. + return {nullptr, nullptr}; + } + + void OnUnrecoverableError(QuicErrorCode /*error*/, + const std::string& /*error_details*/) override {} + + bool ShouldGeneratePacket(HasRetransmittableData /*retransmittable*/, + IsHandshake /*handshake*/) override { + QUICHE_DCHECK(false); + return true; + } + + void MaybeBundleOpportunistically( + TransmissionType /*transmission_type*/) override { + QUICHE_DCHECK(false); + } + + QuicByteCount GetFlowControlSendWindowSize(QuicStreamId /*id*/) override { + QUICHE_DCHECK(false); + return std::numeric_limits::max(); + } + + SerializedPacketFate GetSerializedPacketFate( + bool /*is_mtu_discovery*/, + EncryptionLevel /*encryption_level*/) override { + return SEND_TO_WRITER; + } + + // QuicStreamFrameDataProducer + WriteStreamDataResult WriteStreamData(QuicStreamId /*id*/, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override { + if (send_buffer_.WriteStreamData(offset, data_length, writer)) { + return WRITE_SUCCESS; + } + return WRITE_FAILED; + } + bool WriteCryptoData(EncryptionLevel /*level*/, QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override { + return send_buffer_.WriteStreamData(offset, data_length, writer); + } + + std::vector>* packets() { + return &packets_; + } + + private: + std::vector> packets_; + // This is only needed until the packets are encrypted. Once packets are + // encrypted, the stream data is no longer required. + QuicStreamSendBuffer send_buffer_; +}; + } // namespace quic #endif // QUICHE_QUIC_CORE_QUIC_BUFFERED_PACKET_STORE_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.cc index 4fc4357e87..480afcb735 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.cc @@ -474,6 +474,24 @@ void QuicConfig::SetConnectionOptionsToSend( connection_options_.SetSendValues(connection_options); } +void QuicConfig::AddConnectionOptionsToSend( + const QuicTagVector& connection_options) { + if (!connection_options_.HasSendValues()) { + SetConnectionOptionsToSend(connection_options); + return; + } + const QuicTagVector& existing_connection_options = SendConnectionOptions(); + QuicTagVector connection_options_to_send; + connection_options_to_send.reserve(existing_connection_options.size() + + connection_options.size()); + connection_options_to_send.assign(existing_connection_options.begin(), + existing_connection_options.end()); + connection_options_to_send.insert(connection_options_to_send.end(), + connection_options.begin(), + connection_options.end()); + SetConnectionOptionsToSend(connection_options_to_send); +} + void QuicConfig::SetGoogleHandshakeMessageToSend(std::string message) { google_handshake_message_to_send_ = std::move(message); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.h index bf2dae5f15..34c143c987 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.h @@ -246,6 +246,8 @@ class QUICHE_EXPORT QuicConfig { void SetConnectionOptionsToSend(const QuicTagVector& connection_options); + void AddConnectionOptionsToSend(const QuicTagVector& connection_options); + bool HasReceivedConnectionOptions() const; void SetGoogleHandshakeMessageToSend(std::string message); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc index a7143496e8..c81536b477 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc @@ -24,6 +24,7 @@ #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/congestion_control/rtt_stats.h" #include "quiche/quic/core/congestion_control/send_algorithm_interface.h" @@ -3065,35 +3066,21 @@ bool QuicConnection::ShouldGeneratePacket( void QuicConnection::MaybeBundleOpportunistically( TransmissionType transmission_type) { - if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { - QUIC_RESTART_FLAG_COUNT_N(quic_opport_bundle_qpack_decoder_data5, 1, 4); + const bool should_bundle_ack_frequency = + !ack_frequency_sent_ && sent_packet_manager_.CanSendAckFrequency() && + transmission_type == NOT_RETRANSMISSION && + packet_creator_.NextSendingPacketNumber() >= + FirstSendingPacketNumber() + kMinReceivedBeforeAckDecimation; - const bool should_bundle_ack_frequency = - !ack_frequency_sent_ && sent_packet_manager_.CanSendAckFrequency() && - transmission_type == NOT_RETRANSMISSION && - packet_creator_.NextSendingPacketNumber() >= - FirstSendingPacketNumber() + kMinReceivedBeforeAckDecimation; + if (should_bundle_ack_frequency) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 3, 3); + ack_frequency_sent_ = true; + auto frame = sent_packet_manager_.GetUpdatedAckFrequencyFrame(); + visitor_->SendAckFrequency(frame); + } - if (should_bundle_ack_frequency) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 3, 3); - ack_frequency_sent_ = true; - auto frame = sent_packet_manager_.GetUpdatedAckFrequencyFrame(); - visitor_->SendAckFrequency(frame); - } - - if (transmission_type == NOT_RETRANSMISSION) { - visitor_->MaybeBundleOpportunistically(); - } - } else { - if (!ack_frequency_sent_ && sent_packet_manager_.CanSendAckFrequency()) { - if (packet_creator_.NextSendingPacketNumber() >= - FirstSendingPacketNumber() + kMinReceivedBeforeAckDecimation) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 3, 3); - ack_frequency_sent_ = true; - auto frame = sent_packet_manager_.GetUpdatedAckFrequencyFrame(); - visitor_->SendAckFrequency(frame); - } - } + if (transmission_type == NOT_RETRANSMISSION) { + visitor_->MaybeBundleOpportunistically(); } if (packet_creator_.has_ack() || !CanWrite(NO_RETRANSMITTABLE_DATA)) { @@ -5548,11 +5535,15 @@ void QuicConnection::MaybeStartIetfPeerMigration() { "current_effective_peer_migration_type_: " << current_effective_peer_migration_type_; // Peer migrated before handshake gets confirmed. - CloseConnection((current_effective_peer_migration_type_ == PORT_CHANGE - ? QUIC_PEER_PORT_CHANGE_HANDSHAKE_UNCONFIRMED - : QUIC_CONNECTION_MIGRATION_HANDSHAKE_UNCONFIRMED), - "Peer address changed before handshake is confirmed.", - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + CloseConnection( + (current_effective_peer_migration_type_ == PORT_CHANGE + ? QUIC_PEER_PORT_CHANGE_HANDSHAKE_UNCONFIRMED + : QUIC_CONNECTION_MIGRATION_HANDSHAKE_UNCONFIRMED), + absl::StrFormat( + "Peer address changed from %s to %s before handshake is confirmed.", + default_path_.peer_address.ToString(), + GetEffectivePeerAddressFromCurrentPacket().ToString()), + ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); return; } @@ -5740,10 +5731,7 @@ void QuicConnection::SendAllPendingAcks() { uber_received_packet_manager_.GetEarliestAckTimeout(); QUIC_BUG_IF(quic_bug_12714_32, !earliest_ack_timeout.IsInitialized()); MaybeBundleCryptoDataWithAcks(); - if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { - QUIC_RESTART_FLAG_COUNT_N(quic_opport_bundle_qpack_decoder_data5, 2, 4); - visitor_->MaybeBundleOpportunistically(); - } + visitor_->MaybeBundleOpportunistically(); earliest_ack_timeout = uber_received_packet_manager_.GetEarliestAckTimeout(); if (!earliest_ack_timeout.IsInitialized()) { return; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.h index 91bc01d21d..a879b6c064 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.h @@ -1292,6 +1292,11 @@ class QUICHE_EXPORT QuicConnection QuicConnectionContext* context() override { return &context_; } const QuicConnectionContext* context() const { return &context_; } + void set_context_listener( + std::unique_ptr listener) { + context_.listener.swap(listener); + } + void set_tracer(std::unique_ptr tracer) { context_.tracer.swap(tracer); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_context.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_context.cc index a2b797d56c..d1feda5e62 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_context.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_context.cc @@ -20,15 +20,15 @@ QuicConnectionContextSwitcher::QuicConnectionContextSwitcher( QuicConnectionContext* new_context) : old_context_(QuicConnectionContext::Current()) { current_context = new_context; - if (new_context && new_context->tracer) { - new_context->tracer->Activate(); + if (new_context && new_context->listener) { + new_context->listener->Activate(); } } QuicConnectionContextSwitcher::~QuicConnectionContextSwitcher() { QuicConnectionContext* current = QuicConnectionContext::Current(); - if (current && current->tracer) { - current->tracer->Deactivate(); + if (current && current->listener) { + current->listener->Deactivate(); } current_context = old_context_; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_context.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_context.h index 222910e344..37f99d4f64 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_context.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_context.h @@ -5,6 +5,8 @@ #ifndef QUICHE_QUIC_CORE_QUIC_CONNECTION_CONTEXT_H_ #define QUICHE_QUIC_CORE_QUIC_CONNECTION_CONTEXT_H_ +#include + #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "quiche/quic/platform/api/quic_export.h" @@ -33,23 +35,6 @@ class QUICHE_EXPORT QuicConnectionTracer { std::string s = absl::StrFormat(format, args...); PrintString(s); } - - private: - friend class QuicConnectionContextSwitcher; - - // Called by QuicConnectionContextSwitcher, when |this| becomes the current - // thread's QUIC connection tracer. - // - // Activate/Deactivate are only called by QuicConnectionContextSwitcher's - // constructor/destructor, they always come in pairs. - virtual void Activate() {} - - // Called by QuicConnectionContextSwitcher, when |this| stops from being the - // current thread's QUIC connection tracer. - // - // Activate/Deactivate are only called by QuicConnectionContextSwitcher's - // constructor/destructor, they always come in pairs. - virtual void Deactivate() {} }; // QuicBugListener is a helper class for implementing QUIC_BUG. The QUIC_BUG @@ -61,6 +46,32 @@ class QUICHE_EXPORT QuicBugListener { absl::string_view bug_message) = 0; }; +// QuicConnectionContextListener provides the interfaces that are called when +// a QuicConnection becomes active or inactive. If there are platform-specific +// preparation or cleanup work needed for the members of QuicConnectionContext +// to function, those work can be done in the implementation of this interface. +class QUICHE_EXPORT QuicConnectionContextListener { + public: + virtual ~QuicConnectionContextListener() = default; + + private: + friend class QuicConnectionContextSwitcher; + + // Called by QuicConnectionContextSwitcher when a QUIC connection becomes + // active in the current thread. + // + // Activate/Deactivate are only called by QuicConnectionContextSwitcher's + // constructor/destructor, they always come in pairs. + virtual void Activate() = 0; + + // Called by QuicConnectionContextSwitcher when a QUIC connection becomes + // inactive in the current thread. + // + // Activate/Deactivate are only called by QuicConnectionContextSwitcher's + // constructor/destructor, they always come in pairs. + virtual void Deactivate() = 0; +}; + // QuicConnectionContext is a per-QuicConnection context that includes // facilities useable by any part of a QuicConnection. A QuicConnectionContext // is owned by a QuicConnection. @@ -76,6 +87,7 @@ struct QUICHE_EXPORT QuicConnectionContext final { // function is not called from a 'top-level' QuicConnection function. static QuicConnectionContext* Current(); + std::unique_ptr listener; std::unique_ptr tracer; std::unique_ptr bug_listener; }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc index 84eb9aeed7..aa11954ce2 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc @@ -145,9 +145,9 @@ void QuicCryptoClientStream::OnHandshakePacketSent() { handshaker_->OnHandshakePacketSent(); } -void QuicCryptoClientStream::OnConnectionClosed(QuicErrorCode error, - ConnectionCloseSource source) { - handshaker_->OnConnectionClosed(error, source); +void QuicCryptoClientStream::OnConnectionClosed( + const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) { + handshaker_->OnConnectionClosed(frame.quic_error_code, source); } void QuicCryptoClientStream::OnHandshakeDoneReceived() { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h index 1805289aad..71844aa2f8 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.h @@ -286,7 +286,7 @@ class QUICHE_EXPORT QuicCryptoClientStream : public QuicCryptoClientStreamBase { void OnPacketDecrypted(EncryptionLevel /*level*/) override {} void OnOneRttPacketAcknowledged() override; void OnHandshakePacketSent() override; - void OnConnectionClosed(QuicErrorCode error, + void OnConnectionClosed(const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) override; void OnHandshakeDoneReceived() override; void OnNewTokenReceived(absl::string_view token) override; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.h index 49c9cc2294..86fde9e7d8 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.h @@ -46,7 +46,7 @@ class QUICHE_EXPORT QuicCryptoServerStream : public QuicCryptoServerStreamBase, void OnPacketDecrypted(EncryptionLevel level) override; void OnOneRttPacketAcknowledged() override {} void OnHandshakePacketSent() override {} - void OnConnectionClosed(QuicErrorCode /*error*/, + void OnConnectionClosed(const QuicConnectionCloseFrame& /*frame*/, ConnectionCloseSource /*source*/) override {} void OnHandshakeDoneReceived() override; void OnNewTokenReceived(absl::string_view token) override; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc index 424ac26fb4..dfa4171034 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.cc @@ -112,80 +112,6 @@ class ClearStatelessResetAddressesAlarm QuicDispatcher* dispatcher_; }; -// Collects packets serialized by a QuicPacketCreator in order -// to be handed off to the time wait list manager. -class PacketCollector : public QuicPacketCreator::DelegateInterface, - public QuicStreamFrameDataProducer { - public: - explicit PacketCollector(quiche::QuicheBufferAllocator* allocator) - : send_buffer_(allocator) {} - ~PacketCollector() override = default; - - // QuicPacketCreator::DelegateInterface methods: - void OnSerializedPacket(SerializedPacket serialized_packet) override { - // Make a copy of the serialized packet to send later. - packets_.emplace_back( - new QuicEncryptedPacket(CopyBuffer(serialized_packet), - serialized_packet.encrypted_length, true)); - } - - QuicPacketBuffer GetPacketBuffer() override { - // Let QuicPacketCreator to serialize packets on stack buffer. - return {nullptr, nullptr}; - } - - void OnUnrecoverableError(QuicErrorCode /*error*/, - const std::string& /*error_details*/) override {} - - bool ShouldGeneratePacket(HasRetransmittableData /*retransmittable*/, - IsHandshake /*handshake*/) override { - QUICHE_DCHECK(false); - return true; - } - - void MaybeBundleOpportunistically( - TransmissionType /*transmission_type*/) override { - QUICHE_DCHECK(false); - } - - QuicByteCount GetFlowControlSendWindowSize(QuicStreamId /*id*/) override { - QUICHE_DCHECK(false); - return std::numeric_limits::max(); - } - - SerializedPacketFate GetSerializedPacketFate( - bool /*is_mtu_discovery*/, - EncryptionLevel /*encryption_level*/) override { - return SEND_TO_WRITER; - } - - // QuicStreamFrameDataProducer - WriteStreamDataResult WriteStreamData(QuicStreamId /*id*/, - QuicStreamOffset offset, - QuicByteCount data_length, - QuicDataWriter* writer) override { - if (send_buffer_.WriteStreamData(offset, data_length, writer)) { - return WRITE_SUCCESS; - } - return WRITE_FAILED; - } - bool WriteCryptoData(EncryptionLevel /*level*/, QuicStreamOffset offset, - QuicByteCount data_length, - QuicDataWriter* writer) override { - return send_buffer_.WriteStreamData(offset, data_length, writer); - } - - std::vector>* packets() { - return &packets_; - } - - private: - std::vector> packets_; - // This is only needed until the packets are encrypted. Once packets are - // encrypted, the stream data is no longer required. - QuicStreamSendBuffer send_buffer_; -}; - // Helper for statelessly closing connections by generating the // correct termination packets and adding the connection to the time wait // list manager. @@ -308,12 +234,10 @@ QuicDispatcher::QuicDispatcher( last_error_(QUIC_NO_ERROR), new_sessions_allowed_per_event_loop_(0u), accept_new_connections_(true), - allow_short_initial_server_connection_ids_(false), expected_server_connection_id_length_( expected_server_connection_id_length), clear_stateless_reset_addresses_alarm_(alarm_factory_->CreateAlarm( new ClearStatelessResetAddressesAlarm(this))), - should_update_expected_server_connection_id_length_(false), connection_id_generator_(connection_id_generator) { QUIC_BUG_IF(quic_bug_12724_1, GetSupportedVersions().empty()) << "Trying to create dispatcher without any supported versions"; @@ -365,7 +289,6 @@ void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address, } if (packet_info.destination_connection_id.length() != expected_server_connection_id_length_ && - !should_update_expected_server_connection_id_length_ && packet_info.version.IsKnown() && !packet_info.version.AllowsVariableLengthConnectionIds()) { SetLastError(QUIC_INVALID_PACKET_HEADER); @@ -392,14 +315,6 @@ void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address, } } - // Before introducing the flag, it was impossible for a short header to - // update |expected_server_connection_id_length_|. - if (should_update_expected_server_connection_id_length_ && - packet_info.version_flag) { - expected_server_connection_id_length_ = - packet_info.destination_connection_id.length(); - } - if (MaybeDispatchPacket(packet_info)) { // Packet has been dropped or successfully dispatched, stop processing. return; @@ -686,6 +601,7 @@ QuicDispatcher::TryExtractChloOrBufferEarlyPacket( bool has_full_tls_chlo = false; std::string sni; std::vector supported_groups; + std::vector cert_compression_algos; std::vector alpns; bool resumption_attempted = false, early_data_attempted = false; if (buffered_packets_.HasBufferedPackets( @@ -694,8 +610,9 @@ QuicDispatcher::TryExtractChloOrBufferEarlyPacket( // use the associated TlsChloExtractor to parse this packet. has_full_tls_chlo = buffered_packets_.IngestPacketForTlsChloExtraction( packet_info.destination_connection_id, packet_info.version, - packet_info.packet, &supported_groups, &alpns, &sni, - &resumption_attempted, &early_data_attempted, &result.tls_alert); + packet_info.packet, &supported_groups, &cert_compression_algos, + &alpns, &sni, &resumption_attempted, &early_data_attempted, + &result.tls_alert); } else { // If we do not have a BufferedPacketList for this connection ID, // create a single-use one to check whether this packet contains a @@ -706,6 +623,7 @@ QuicDispatcher::TryExtractChloOrBufferEarlyPacket( // This packet contains a full single-packet CHLO. has_full_tls_chlo = true; supported_groups = tls_chlo_extractor.supported_groups(); + cert_compression_algos = tls_chlo_extractor.cert_compression_algos(); alpns = tls_chlo_extractor.alpns(); sni = tls_chlo_extractor.server_name(); resumption_attempted = tls_chlo_extractor.resumption_attempted(); @@ -733,6 +651,7 @@ QuicDispatcher::TryExtractChloOrBufferEarlyPacket( ParsedClientHello& parsed_chlo = result.parsed_chlo.emplace(); parsed_chlo.sni = std::move(sni); parsed_chlo.supported_groups = std::move(supported_groups); + parsed_chlo.cert_compression_algos = std::move(cert_compression_algos); parsed_chlo.alpns = std::move(alpns); if (packet_info.retry_token.has_value()) { parsed_chlo.retry_token = std::string(*packet_info.retry_token); @@ -1163,9 +1082,7 @@ void QuicDispatcher::BufferEarlyPacket(const ReceivedPacketInfo& packet_info) { // The connection ID generator will only be set for CHLOs, not for early // packets. EnqueuePacketResult rs = buffered_packets_.EnqueuePacket( - packet_info.destination_connection_id, - packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet, - packet_info.self_address, packet_info.peer_address, packet_info.version, + packet_info, /*parsed_chlo=*/std::nullopt, /*connection_id_generator=*/nullptr); if (rs != EnqueuePacketResult::SUCCESS) { OnBufferPacketFailure(rs, packet_info.destination_connection_id); @@ -1180,10 +1097,7 @@ void QuicDispatcher::ProcessChlo(ParsedClientHello parsed_chlo, QUIC_BUG_IF(quic_bug_12724_7, buffered_packets_.HasChloForConnection( packet_info->destination_connection_id)); EnqueuePacketResult rs = buffered_packets_.EnqueuePacket( - packet_info->destination_connection_id, - packet_info->form != GOOGLE_QUIC_PACKET, packet_info->packet, - packet_info->self_address, packet_info->peer_address, - packet_info->version, std::move(parsed_chlo), &ConnectionIdGenerator()); + *packet_info, std::move(parsed_chlo), &ConnectionIdGenerator()); if (rs != EnqueuePacketResult::SUCCESS) { OnBufferPacketFailure(rs, packet_info->destination_connection_id); } @@ -1250,8 +1164,7 @@ bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) { bool QuicDispatcher::IsServerConnectionIdTooShort( QuicConnectionId connection_id) const { if (connection_id.length() >= kQuicMinimumInitialConnectionIdLength || - connection_id.length() >= expected_server_connection_id_length_ || - allow_short_initial_server_connection_ids_) { + connection_id.length() >= expected_server_connection_id_length_) { return false; } uint8_t generator_output = diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h index efe5a2c6b8..b88cd0e1f6 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h @@ -314,22 +314,6 @@ class QUICHE_EXPORT QuicDispatcher virtual void RestorePerPacketContext( std::unique_ptr /*context*/) {} - // If true, our framer will change its expected connection ID length - // to the received destination connection ID length of all IETF long headers. - void SetShouldUpdateExpectedServerConnectionIdLength( - bool should_update_expected_server_connection_id_length) { - should_update_expected_server_connection_id_length_ = - should_update_expected_server_connection_id_length; - } - - // If true, the dispatcher will allow incoming initial packets that have - // destination connection IDs shorter than 64 bits. - void SetAllowShortInitialServerConnectionIds( - bool allow_short_initial_server_connection_ids) { - allow_short_initial_server_connection_ids_ = - allow_short_initial_server_connection_ids; - } - // Called if a packet from an unseen connection is reset or rejected. virtual void OnNewConnectionRejected() {} @@ -466,18 +450,12 @@ class QUICHE_EXPORT QuicDispatcher // connections), false otherwise. bool accept_new_connections_; - // If false, the dispatcher follows the IETF spec and rejects packets with - // invalid destination connection IDs lengths below 64 bits. - // If true they are allowed. - bool allow_short_initial_server_connection_ids_; - // IETF short headers contain a destination connection ID but do not // encode its length. This variable contains the length we expect to read. // This is also used to signal an error when a long header packet with - // different destination connection ID length is received when - // should_update_expected_server_connection_id_length_ is false and packet's + // different destination connection ID length is received when packet's // version does not allow variable length connection ID. - uint8_t expected_server_connection_id_length_; + const uint8_t expected_server_connection_id_length_; // Records client addresses that have been recently reset. absl::flat_hash_set @@ -486,10 +464,6 @@ class QUICHE_EXPORT QuicDispatcher // An alarm which clear recent_stateless_reset_addresses_. std::unique_ptr clear_stateless_reset_addresses_alarm_; - // If true, change expected_server_connection_id_length_ to be the received - // destination connection ID length of all IETF long headers. - bool should_update_expected_server_connection_id_length_; - ConnectionIdGeneratorInterface& connection_id_generator_; }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h deleted file mode 100644 index e219224a39..0000000000 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2024 The Chromium 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 is autogenerated by the QUICHE Copybara export script. - -#ifdef QUIC_FLAG - -QUIC_FLAG(quic_reloadable_flag_quic_stop_reading_also_stops_header_decompression, false) -// A testonly reloadable flag that will always default to false. -QUIC_FLAG(quic_reloadable_flag_quic_testonly_default_false, false) -// A testonly reloadable flag that will always default to true. -QUIC_FLAG(quic_reloadable_flag_quic_testonly_default_true, true) -// A testonly restart flag that will always default to false. -QUIC_FLAG(quic_restart_flag_quic_testonly_default_false, false) -// A testonly restart flag that will always default to true. -QUIC_FLAG(quic_restart_flag_quic_testonly_default_true, true) -// If enabled and a BSUS connection is received, blocks server connections until SETTINGS frame is received. -QUIC_FLAG(quic_reloadable_flag_quic_block_until_settings_received_copt, true) -// If trrue, early return before write control frame in OnCanWrite() if the connection is already closed. -QUIC_FLAG(quic_reloadable_flag_quic_no_write_control_frame_upon_connection_close, true) -// If true, HTTP/2 HEADERS frames will use two additional bytes of HPACK overhead per header in their SpdyHeadersIR::size() estimate. This flag is latched in SpdyHeadersIR to ensure a consistent size() value for a const SpdyHeadersIR regardless of flag state. -QUIC_FLAG(quic_reloadable_flag_http2_add_hpack_overhead_bytes2, true) -// If true, QUIC BBR2 will use a 0.91 PROBE_DOWN gain by default. -QUIC_FLAG(quic_reloadable_flag_quic_bbr2_enable_bbpd_by_default, false) -// If true, QUIC server will not respond to gQUIC probing packet(PING + PADDING) but treat it as a regular packet. -QUIC_FLAG(quic_reloadable_flag_quic_ignore_gquic_probing, true) -// If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes. -QUIC_FLAG(quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false) -// If true, QuicConnection::ProcessValidatedPacket will use normalized address to test peer address changes. -QUIC_FLAG(quic_reloadable_flag_quic_test_peer_addr_change_after_normalize, false) -// If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so. -QUIC_FLAG(quic_restart_flag_quic_support_release_time_for_gso, false) -// If true, QuicSession will block outgoing control frames when the connection is closed. -QUIC_FLAG(quic_reloadable_flag_quic_no_write_control_frame_upon_connection_close2, false) -// If true, ack frequency frame can be sent from server to client. -QUIC_FLAG(quic_reloadable_flag_quic_can_send_ack_frequency, true) -// If true, allow client to enable BBRv2 on server via connection option \'B2ON\'. -QUIC_FLAG(quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, true) -// If true, allow quic to use new ALPS codepoint to negotiate during handshake for H3 if client sends new ALPS codepoint. -QUIC_FLAG(quic_reloadable_flag_quic_gfe_allow_alps_new_codepoint, true) -// If true, an endpoint does not detect path degrading or blackholing until handshake gets confirmed. -QUIC_FLAG(quic_reloadable_flag_quic_no_path_degrading_before_handshake_confirmed, true) -// If true, bundle qpack decoder data with other frames opportunistically. -QUIC_FLAG(quic_restart_flag_quic_opport_bundle_qpack_decoder_data5, true) -// If true, default-enable 5RTO blachole detection. -QUIC_FLAG(quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true) -// If true, disable QUIC version Q046. -QUIC_FLAG(quic_reloadable_flag_quic_disable_version_q046, true) -// If true, disable QUIC version h3 (RFCv1). -QUIC_FLAG(quic_reloadable_flag_quic_disable_version_rfcv1, false) -// If true, disable QUIC version h3-29. -QUIC_FLAG(quic_reloadable_flag_quic_disable_version_draft_29, false) -// If true, disable blackhole detection on server side. -QUIC_FLAG(quic_reloadable_flag_quic_disable_server_blackhole_detection, false) -// If true, disable resumption when receiving NRES connection option. -QUIC_FLAG(quic_reloadable_flag_quic_enable_disable_resumption, true) -// If true, discard INITIAL packet if the key has been dropped. -QUIC_FLAG(quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, true) -// If true, dispatcher sends error code QUIC_HANDSHAKE_FAILED_PACKETS_BUFFERED_TOO_LONG when handshake fails due to packets buffered for too long. -QUIC_FLAG(quic_reloadable_flag_quic_new_error_code_when_packets_buffered_too_long, true) -// If true, enable server retransmittable on wire PING. -QUIC_FLAG(quic_reloadable_flag_quic_enable_server_on_wire_ping, true) -// If true, include stream information in idle timeout connection close detail. -QUIC_FLAG(quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true) -// If true, reject or send error response code upon receiving invalid request or response headers. -QUIC_FLAG(quic_reloadable_flag_quic_act_upon_invalid_header, true) -// If true, remove the non-initial burst in QUIC PacingSender. -QUIC_FLAG(quic_reloadable_flag_quic_pacing_remove_non_initial_burst, false) -// If true, require handshake confirmation for QUIC connections, functionally disabling 0-rtt handshakes. -QUIC_FLAG(quic_reloadable_flag_quic_require_handshake_confirmation, true) -// If true, respect the incremental parameter of each stream in QuicWriteBlockedList. -QUIC_FLAG(quic_reloadable_flag_quic_priority_respect_incremental, false) -// If true, round-robin stream writes instead of batching in QuicWriteBlockedList. -QUIC_FLAG(quic_reloadable_flag_quic_disable_batch_write, false) -// If true, set burst token to 2 in cwnd bootstrapping experiment. -QUIC_FLAG(quic_reloadable_flag_quic_conservative_bursts, false) -// If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr. -QUIC_FLAG(quic_reloadable_flag_quic_default_to_bbr_v2, false) -// If true, use a LRU cache to record client addresses of packets received on server\'s original address. -QUIC_FLAG(quic_reloadable_flag_quic_use_received_client_addresses_cache, true) -// If true, use improved QPACK compression algorithm. -QUIC_FLAG(quic_reloadable_flag_quic_better_qpack_compression, true) -// If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped. -QUIC_FLAG(quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false) -// If true, when TicketCrypter fails to encrypt a session ticket, quic::TlsServerHandshaker will send a placeholder ticket, instead of an empty one, to the client. -QUIC_FLAG(quic_reloadable_flag_quic_send_placeholder_ticket_when_encrypt_ticket_fails, true) -// If true, when the peer sends connection options \\\\\\\'SLP1\\\\\\\', \\\\\\\'SLP2\\\\\\\' and \\\\\\\'SLPF\\\\\\\', internet facing GFEs will only allow a limited number of new requests to be processed per event loop, and postpone the rest to the following event loops. Also guard QuicConnection to iterate through all decrypters at each encryption level to get cipher id for a request. -QUIC_FLAG(quic_reloadable_flag_quic_limit_new_streams_per_loop_2, true) -// When true, allows sending of QUIC packets marked ECT(1). A different flag (TBD) will actually utilize this capability to send ECT(1). -QUIC_FLAG(quic_restart_flag_quic_support_ect1, false) -// When true, defaults to BBR congestion control instead of Cubic. -QUIC_FLAG(quic_reloadable_flag_quic_default_to_bbr, false) -// When true, support RFC9369. -QUIC_FLAG(quic_reloadable_flag_quic_enable_version_rfcv2, false) -// When true, the BB2U copt causes BBR2 to wait two rounds with out draining the queue before exiting PROBE_UP and BB2S has the same effect in STARTUP. -QUIC_FLAG(quic_reloadable_flag_quic_bbr2_probe_two_rounds, true) -// When true, the BBHI copt causes QUIC BBRv2 to use a simpler algorithm for raising inflight_hi in PROBE_UP. -QUIC_FLAG(quic_reloadable_flag_quic_bbr2_simplify_inflight_hi, true) -// When true, the BBR4 copt sets the extra_acked window to 20 RTTs and BBR5 sets it to 40 RTTs. -QUIC_FLAG(quic_reloadable_flag_quic_bbr2_extra_acked_window, true) - -#endif - diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.cc index 3dcc6a929a..b10908ec15 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -14,17 +15,24 @@ #include "quiche/quic/platform/api/quic_ip_address.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_socket_address.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { -QuicMsgHdr::QuicMsgHdr(const char* buffer, size_t buf_len, - const QuicSocketAddress& peer_address, char* cbuf, - size_t cbuf_size) - : iov_{const_cast(buffer), buf_len}, - cbuf_(cbuf), - cbuf_size_(cbuf_size), - cmsg_(nullptr) { - // Only support unconnected sockets. +QuicMsgHdr::QuicMsgHdr(iovec* iov, size_t iov_len, char* cbuf, size_t cbuf_size) + : cbuf_(cbuf), cbuf_size_(cbuf_size), cmsg_(nullptr) { + hdr_.msg_name = nullptr; + hdr_.msg_namelen = 0; + + hdr_.msg_iov = iov; + hdr_.msg_iovlen = iov_len; + hdr_.msg_flags = 0; + + hdr_.msg_control = nullptr; + hdr_.msg_controllen = 0; +} + +void QuicMsgHdr::SetPeerAddress(const QuicSocketAddress& peer_address) { QUICHE_DCHECK(peer_address.IsInitialized()); raw_peer_address_ = peer_address.generic_address(); @@ -32,13 +40,6 @@ QuicMsgHdr::QuicMsgHdr(const char* buffer, size_t buf_len, hdr_.msg_namelen = raw_peer_address_.ss_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); - - hdr_.msg_iov = &iov_; - hdr_.msg_iovlen = 1; - hdr_.msg_flags = 0; - - hdr_.msg_control = nullptr; - hdr_.msg_controllen = 0; } void QuicMsgHdr::SetIpInNextCmsg(const QuicIpAddress& self_address) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.h index a0e338d4d7..f125cbab37 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.h @@ -24,6 +24,7 @@ #include "quiche/quic/platform/api/quic_ip_address.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_socket_address.h" +#include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/quiche_callbacks.h" #ifndef SOL_UDP @@ -77,9 +78,12 @@ inline constexpr int kCmsgSpaceForTOS = CMSG_SPACE(sizeof(int)); // QuicLinuxSocketUtils::WritePacket(fd, hdr); class QUICHE_EXPORT QuicMsgHdr { public: - QuicMsgHdr(const char* buffer, size_t buf_len, - const QuicSocketAddress& peer_address, char* cbuf, - size_t cbuf_size); + // Creates a QuicMsgHeader without setting the peer address in + // msghdr.msg_name. This can be set later with SetPeerAddress(). + QuicMsgHdr(iovec* iov, size_t iov_len, char* cbuf, size_t cbuf_size); + + // Sets the peer address in msghdr.msg_name. + void SetPeerAddress(const QuicSocketAddress& peer_address); // Set IP info in the next cmsg. Both IPv4 and IPv6 are supported. void SetIpInNextCmsg(const QuicIpAddress& self_address); @@ -97,7 +101,6 @@ class QUICHE_EXPORT QuicMsgHdr { size_t data_size); msghdr hdr_; - iovec iov_; sockaddr_storage raw_peer_address_; char* cbuf_; const size_t cbuf_size_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc index aecfc73462..ca35a07601 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc @@ -1314,11 +1314,6 @@ bool QuicPacketCreator::ConsumeRetransmittableControlFrame( } void QuicPacketCreator::MaybeBundleOpportunistically() { - if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)) { - delegate_->MaybeBundleOpportunistically(next_transmission_type_); - return; - } - // delegate_->MaybeBundleOpportunistically() may change // next_transmission_type_ for the bundled data. const TransmissionType next_transmission_type = next_transmission_type_; @@ -1337,14 +1332,6 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id, bool has_handshake = QuicUtils::IsCryptoStreamId(transport_version(), id); const TransmissionType next_transmission_type = next_transmission_type_; MaybeBundleOpportunistically(); - // TODO(wub): Remove this QUIC_BUG when deprecating - // quic_opport_bundle_qpack_decoder_data5. - QUIC_BUG_IF(quic_packet_creator_change_transmission_type, - next_transmission_type != next_transmission_type_) - << ENDPOINT - << "Transmission type changed by bundled data. old transmission type:" - << next_transmission_type - << ", new transmission type:" << next_transmission_type_; // If the data being consumed is subject to flow control, check the flow // control send window to see if |write_length| exceeds the send window after // bundling opportunistic data, if so, reduce |write_length| to the send @@ -1354,11 +1341,9 @@ QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id, // - And it's not handshake data. This is always true for ConsumeData because // the function is not called for handshake data. const size_t original_write_length = write_length; - if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5) && - next_transmission_type_ == NOT_RETRANSMISSION) { + if (next_transmission_type_ == NOT_RETRANSMISSION) { if (QuicByteCount send_window = delegate_->GetFlowControlSendWindowSize(id); write_length > send_window) { - QUIC_RESTART_FLAG_COUNT_N(quic_opport_bundle_qpack_decoder_data5, 4, 4); QUIC_DLOG(INFO) << ENDPOINT << "After bundled data, reducing (old) write_length:" << write_length << "to (new) send_window:" << send_window; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_session.cc index d8aa677571..2ee8651467 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_session.cc @@ -515,11 +515,11 @@ void QuicSession::OnConnectionClosed(const QuicConnectionCloseFrame& frame, source_ = source; } - GetMutableCryptoStream()->OnConnectionClosed(frame.quic_error_code, source); + GetMutableCryptoStream()->OnConnectionClosed(frame, source); PerformActionOnActiveStreams([this, frame, source](QuicStream* stream) { QuicStreamId id = stream->id(); - stream->OnConnectionClosed(frame.quic_error_code, source); + stream->OnConnectionClosed(frame, source); auto it = stream_map_.find(id); if (it != stream_map_.end()) { QUIC_BUG_IF(quic_bug_12435_2, !it->second->IsZombie()) @@ -2508,7 +2508,6 @@ HandshakeState QuicSession::GetHandshakeState() const { } QuicByteCount QuicSession::GetFlowControlSendWindowSize(QuicStreamId id) { - QUICHE_DCHECK(GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data5)); auto it = stream_map_.find(id); if (it == stream_map_.end()) { // No flow control for invalid or inactive stream ids. Returning uint64max diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc index 4fdb87a241..e927ee2927 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc @@ -563,15 +563,16 @@ void QuicStream::OnStreamReset(const QuicRstStreamFrame& frame) { CloseReadSide(); } -void QuicStream::OnConnectionClosed(QuicErrorCode error, +void QuicStream::OnConnectionClosed(const QuicConnectionCloseFrame& frame, ConnectionCloseSource /*source*/) { if (read_side_closed_ && write_side_closed_) { return; } - if (error != QUIC_NO_ERROR) { + auto error_code = frame.quic_error_code; + if (error_code != QUIC_NO_ERROR) { stream_error_ = QuicResetStreamError::FromInternal(QUIC_STREAM_CONNECTION_ERROR); - connection_error_ = error; + connection_error_ = error_code; } CloseWriteSide(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.h index 9260045f6c..43cacc0ccf 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.h @@ -25,6 +25,7 @@ #include "absl/strings/string_view.h" #include "absl/types/span.h" +#include "quiche/quic/core/frames/quic_connection_close_frame.h" #include "quiche/quic/core/frames/quic_rst_stream_frame.h" #include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/core/quic_flow_controller.h" @@ -197,7 +198,7 @@ class QUICHE_EXPORT QuicStream : public QuicStreamSequencer::StreamInterface { // Called by the session when the endpoint receives or sends a connection // close, and should immediately close the stream. - virtual void OnConnectionClosed(QuicErrorCode error, + virtual void OnConnectionClosed(const QuicConnectionCloseFrame& frame, ConnectionCloseSource source); const QuicStreamPriority& priority() const; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_buffer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_buffer.cc index 496055f9ac..b4878bf529 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_buffer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_buffer.cc @@ -389,7 +389,11 @@ bool QuicStreamSequencerBuffer::PeekRegion(QuicStreamOffset offset, // Determine if entire block has been received. size_t end_block_idx = GetBlockIndex(FirstMissingByte()); - if (block_idx == end_block_idx) { + if (block_idx == end_block_idx && + block_offset < GetInBlockOffset(FirstMissingByte())) { + // If these 2 indexes point to the same block and the fist missing byte + // offset is larger than the starting offset, this means data available + // hasn't expanded to the next block yet. // Only read part of block before FirstMissingByte(). iov->iov_len = GetInBlockOffset(FirstMissingByte()) - block_offset; } else { @@ -397,6 +401,9 @@ bool QuicStreamSequencerBuffer::PeekRegion(QuicStreamOffset offset, iov->iov_len = GetBlockCapacity(block_idx) - block_offset; } + QUIC_BUG_IF(quic_invalid_peek_region, iov->iov_len > kBlockSizeBytes) + << "PeekRegion() at " << offset << " gets bad iov with length " + << iov->iov_len; return true; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.cc index e1507ad9d9..43b5ace285 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.cc @@ -422,8 +422,9 @@ std::ostream& operator<<(std::ostream& os, const KeyUpdateReason reason) { bool operator==(const ParsedClientHello& a, const ParsedClientHello& b) { return a.sni == b.sni && a.uaid == b.uaid && - a.supported_groups == b.supported_groups && a.alpns == b.alpns && - a.retry_token == b.retry_token && + a.supported_groups == b.supported_groups && + a.cert_compression_algos == b.cert_compression_algos && + a.alpns == b.alpns && a.retry_token == b.retry_token && a.resumption_attempted == b.resumption_attempted && a.early_data_attempted == b.early_data_attempted; } @@ -434,6 +435,8 @@ std::ostream& operator<<(std::ostream& os, << ", alpns:" << quiche::PrintElements(parsed_chlo.alpns) << ", supported_groups:" << quiche::PrintElements(parsed_chlo.supported_groups) + << ", cert_compression_algos:" + << quiche::PrintElements(parsed_chlo.cert_compression_algos) << ", resumption_attempted:" << parsed_chlo.resumption_attempted << ", early_data_attempted:" << parsed_chlo.early_data_attempted << ", len(retry_token):" << parsed_chlo.retry_token.size() << " }"; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.h index 93a7e5ef59..b85e079701 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.h @@ -875,6 +875,7 @@ struct QUICHE_EXPORT ParsedClientHello { std::string sni; // QUIC crypto and TLS. std::string uaid; // QUIC crypto only. std::vector supported_groups; // TLS only. + std::vector cert_compression_algos; // TLS only. std::vector alpns; // QUIC crypto and TLS. // The unvalidated retry token from the last received packet of a potentially // multi-packet client hello. TLS only. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.cc index 1ba0a20962..82beb9f284 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.cc @@ -23,6 +23,7 @@ #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" +#include "quiche/quic/platform/api/quic_flag_utils.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/common/platform/api/quiche_logging.h" @@ -71,6 +72,42 @@ std::vector GetSupportedGroups(const SSL_CLIENT_HELLO* client_hello) { return named_groups; } +std::vector GetCertCompressionAlgos( + const SSL_CLIENT_HELLO* client_hello) { + const uint8_t* extension_data; + size_t extension_len; + int rv = SSL_early_callback_ctx_extension_get( + client_hello, TLSEXT_TYPE_cert_compression, &extension_data, + &extension_len); + if (rv != 1) { + return {}; + } + // See https://datatracker.ietf.org/doc/html/rfc8879#section-3 for the format + // of this extension. + QuicDataReader cert_compression_algos_reader( + reinterpret_cast(extension_data), extension_len); + uint8_t algos_len; + if (!cert_compression_algos_reader.ReadUInt8(&algos_len) || algos_len == 0 || + algos_len % sizeof(uint16_t) != 0 || + algos_len + sizeof(uint8_t) != extension_len) { + QUIC_CODE_COUNT(quic_chlo_cert_compression_algos_invalid_length); + return {}; + } + + size_t num_algos = algos_len / sizeof(uint16_t); + std::vector cert_compression_algos; + cert_compression_algos.reserve(num_algos); + for (size_t i = 0; i < num_algos; ++i) { + uint16_t cert_compression_algo; + if (!cert_compression_algos_reader.ReadUInt16(&cert_compression_algo)) { + QUIC_CODE_COUNT(quic_chlo_fail_to_read_cert_compression_algo); + return {}; + } + cert_compression_algos.push_back(cert_compression_algo); + } + return cert_compression_algos; +} + } // namespace TlsChloExtractor::TlsChloExtractor() @@ -102,6 +139,7 @@ TlsChloExtractor& TlsChloExtractor::operator=(TlsChloExtractor&& other) { parsed_crypto_frame_in_this_packet_ = other.parsed_crypto_frame_in_this_packet_; supported_groups_ = std::move(other.supported_groups_); + cert_compression_algos_ = std::move(other.cert_compression_algos_); alpns_ = std::move(other.alpns_); server_name_ = std::move(other.server_name_); client_hello_bytes_ = std::move(other.client_hello_bytes_); @@ -366,6 +404,16 @@ void TlsChloExtractor::HandleParsedChlo(const SSL_CLIENT_HELLO* client_hello) { } supported_groups_ = GetSupportedGroups(client_hello); + if (GetQuicReloadableFlag(quic_parse_cert_compression_algos_from_chlo)) { + cert_compression_algos_ = GetCertCompressionAlgos(client_hello); + if (cert_compression_algos_.empty()) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_parse_cert_compression_algos_from_chlo, + 1, 2); + } else { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_parse_cert_compression_algos_from_chlo, + 2, 2); + } + } // Update our state now that we've parsed a full CHLO. if (state_ == State::kInitial) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.h index 2aaa0eb816..8ded96706f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.h @@ -54,6 +54,9 @@ class QUICHE_EXPORT TlsChloExtractor const std::vector& supported_groups() const { return supported_groups_; } + const std::vector& cert_compression_algos() const { + return cert_compression_algos_; + } absl::Span client_hello_bytes() const { return client_hello_bytes_; } @@ -263,6 +266,9 @@ class QUICHE_EXPORT TlsChloExtractor bool parsed_crypto_frame_in_this_packet_; // Array of NamedGroups parsed from the CHLO's supported_groups extension. std::vector supported_groups_; + // Array of cert compression algos parsed from the CHLO's + // compress_certificate extension. + std::vector cert_compression_algos_; // Array of ALPNs parsed from the CHLO. std::vector alpns_; // SNI parsed from the CHLO. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc index 684d4ed294..aee6903d17 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc @@ -412,9 +412,9 @@ bool TlsServerHandshaker::ExportKeyingMaterial(absl::string_view label, return ExportKeyingMaterialForLabel(label, context, result_len, result); } -void TlsServerHandshaker::OnConnectionClosed(QuicErrorCode error, - ConnectionCloseSource source) { - TlsHandshaker::OnConnectionClosed(error, source); +void TlsServerHandshaker::OnConnectionClosed( + const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) { + TlsHandshaker::OnConnectionClosed(frame.quic_error_code, source); } ssl_early_data_reason_t TlsServerHandshaker::EarlyDataReason() const { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h index c81a7fc003..d8c732873f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h @@ -75,7 +75,7 @@ class QUICHE_EXPORT TlsServerHandshaker : public TlsHandshaker, void OnPacketDecrypted(EncryptionLevel level) override; void OnOneRttPacketAcknowledged() override {} void OnHandshakePacketSent() override {} - void OnConnectionClosed(QuicErrorCode error, + void OnConnectionClosed(const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) override; void OnHandshakeDoneReceived() override; std::string GetAddressToken( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc index ac350b557b..442ce58c46 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc @@ -63,8 +63,8 @@ DEFINE_QUICHE_COMMAND_LINE_FLAG( "For example: \"name1:value1;name2:value2\"."); DEFINE_QUICHE_COMMAND_LINE_FLAG( - std::string, signature_auth, "", - "Enables HTTP Signature Authentication. Pass in the string \"new\" to " + std::string, concealed_auth, "", + "Enables HTTP Concealed Authentication. Pass in the string \"new\" to " "generate new keys. Otherwise, pass in the key ID in ASCII followed by a " "colon and the 32-byte private key as hex. For example: \"kid:0123...f\"."); @@ -255,49 +255,49 @@ int RunMasqueClient(int argc, char* argv[]) { std::vector urls = quiche::QuicheParseCommandLineFlags(usage, argc, argv); - std::string signature_auth_param = - quiche::GetQuicheCommandLineFlag(FLAGS_signature_auth); - std::string signature_auth_key_id; - std::string signature_auth_private_key; - std::string signature_auth_public_key; - if (!signature_auth_param.empty()) { + std::string concealed_auth_param = + quiche::GetQuicheCommandLineFlag(FLAGS_concealed_auth); + std::string concealed_auth_key_id; + std::string concealed_auth_private_key; + std::string concealed_auth_public_key; + if (!concealed_auth_param.empty()) { static constexpr size_t kEd25519Rfc8032PrivateKeySize = 32; uint8_t public_key[ED25519_PUBLIC_KEY_LEN]; uint8_t private_key[ED25519_PRIVATE_KEY_LEN]; - const bool is_new_key_pair = signature_auth_param == "new"; + const bool is_new_key_pair = concealed_auth_param == "new"; if (is_new_key_pair) { ED25519_keypair(public_key, private_key); - QUIC_LOG(INFO) << "Generated new Signature Authentication key pair"; + QUIC_LOG(INFO) << "Generated new Concealed Authentication key pair"; } else { - std::vector signature_auth_param_split = - absl::StrSplit(signature_auth_param, absl::MaxSplits(':', 1)); + std::vector concealed_auth_param_split = + absl::StrSplit(concealed_auth_param, absl::MaxSplits(':', 1)); std::string private_key_seed; - if (signature_auth_param_split.size() != 2) { + if (concealed_auth_param_split.size() != 2) { QUIC_LOG(ERROR) - << "Signature authentication parameter is missing a colon"; + << "Concealed authentication parameter is missing a colon"; return 1; } - signature_auth_key_id = signature_auth_param_split[0]; - if (signature_auth_key_id.empty()) { - QUIC_LOG(ERROR) << "Signature authentication key ID cannot be empty"; + concealed_auth_key_id = concealed_auth_param_split[0]; + if (concealed_auth_key_id.empty()) { + QUIC_LOG(ERROR) << "Concealed authentication key ID cannot be empty"; return 1; } - if (!absl::HexStringToBytes(signature_auth_param_split[1], + if (!absl::HexStringToBytes(concealed_auth_param_split[1], &private_key_seed)) { - QUIC_LOG(ERROR) << "Signature authentication key hex value is invalid"; + QUIC_LOG(ERROR) << "Concealed authentication key hex value is invalid"; return 1; } if (private_key_seed.size() != kEd25519Rfc8032PrivateKeySize) { QUIC_LOG(ERROR) - << "Invalid signature authentication private key length " + << "Invalid Concealed authentication private key length " << private_key_seed.size(); return 1; } ED25519_keypair_from_seed( public_key, private_key, reinterpret_cast(private_key_seed.data())); - QUIC_LOG(INFO) << "Loaded Signature Authentication key pair"; + QUIC_LOG(INFO) << "Loaded Concealed Authentication key pair"; } // Note that Ed25519 private keys are 32 bytes long per RFC 8032. However, // to reduce CPU costs, BoringSSL represents private keys in memory as the @@ -307,7 +307,7 @@ int RunMasqueClient(int argc, char* argv[]) { // RFC 8032 private key because BoringSSL does not provide a supported way // to access it. This is required to allow us to print the private key in a // format that can be passed back in to BoringSSL from the command-line. See - // curve25519.h for details. The rest of our signature authentication code + // curve25519.h for details. The rest of our concealed authentication code // uses the BoringSSL representation without relying on this implementation // detail. static_assert(kEd25519Rfc8032PrivateKeySize <= @@ -318,7 +318,7 @@ int RunMasqueClient(int argc, char* argv[]) { std::string public_key_hexstr = absl::BytesToHexString(absl::string_view( reinterpret_cast(public_key), ED25519_PUBLIC_KEY_LEN)); if (is_new_key_pair) { - std::cout << "Generated new Signature Authentication key pair." + std::cout << "Generated new Concealed Authentication key pair." << std::endl; std::cout << "Private key: " << private_key_hexstr << std::endl; std::cout << "Public key: " << public_key_hexstr << std::endl; @@ -326,9 +326,9 @@ int RunMasqueClient(int argc, char* argv[]) { } QUIC_LOG(INFO) << "Private key: " << private_key_hexstr; QUIC_LOG(INFO) << "Public key: " << public_key_hexstr; - signature_auth_private_key = std::string( + concealed_auth_private_key = std::string( reinterpret_cast(private_key), ED25519_PRIVATE_KEY_LEN); - signature_auth_public_key = std::string(reinterpret_cast(public_key), + concealed_auth_public_key = std::string(reinterpret_cast(public_key), ED25519_PUBLIC_KEY_LEN); } @@ -430,10 +430,10 @@ int RunMasqueClient(int argc, char* argv[]) { masque_client->masque_client_session()->set_additional_headers( quiche::GetQuicheCommandLineFlag(FLAGS_proxy_headers)); - if (!signature_auth_param.empty()) { - masque_client->masque_client_session()->EnableSignatureAuth( - signature_auth_key_id, signature_auth_private_key, - signature_auth_public_key); + if (!concealed_auth_param.empty()) { + masque_client->masque_client_session()->EnableConcealedAuth( + concealed_auth_key_id, concealed_auth_private_key, + concealed_auth_public_key); } masque_clients.push_back(std::move(masque_client)); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc index 989f2171ff..4ecf75d1bf 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc @@ -39,13 +39,13 @@ #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/tools/quic_url.h" #include "quiche/common/capsule.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_googleurl.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/platform/api/quiche_url_utils.h" #include "quiche/common/quiche_ip_address.h" #include "quiche/common/quiche_random.h" #include "quiche/common/quiche_text_utils.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -177,7 +177,7 @@ MasqueClientSession::GetOrCreateConnectUdpClientState( << authority << "\" path=\"" << canonicalized_path << "\""; // Send the request. - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":method"] = "CONNECT"; headers[":protocol"] = "connect-udp"; headers[":scheme"] = scheme; @@ -224,7 +224,7 @@ MasqueClientSession::GetOrCreateConnectIpClientState( << "\" path=\"" << path << "\""; // Send the request. - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":method"] = "CONNECT"; headers[":protocol"] = "connect-ip"; headers[":scheme"] = scheme; @@ -275,7 +275,7 @@ MasqueClientSession::GetOrCreateConnectEthernetClientState( << authority << "\" path=\"" << path << "\""; // Send the request. - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":method"] = "CONNECT"; headers[":protocol"] = "connect-ethernet"; headers[":scheme"] = scheme; @@ -721,7 +721,7 @@ void MasqueClientSession::RemoveFakeAddress( fake_addresses_.erase(fake_address.ToPackedString()); } -void MasqueClientSession::EnableSignatureAuth(absl::string_view key_id, +void MasqueClientSession::EnableConcealedAuth(absl::string_view key_id, absl::string_view private_key, absl::string_view public_key) { QUICHE_CHECK(!key_id.empty()); @@ -729,9 +729,9 @@ void MasqueClientSession::EnableSignatureAuth(absl::string_view key_id, static_cast(ED25519_PRIVATE_KEY_LEN)); QUICHE_CHECK_EQ(public_key.size(), static_cast(ED25519_PUBLIC_KEY_LEN)); - signature_auth_key_id_ = key_id; - signature_auth_private_key_ = private_key; - signature_auth_public_key_ = public_key; + concealed_auth_key_id_ = key_id; + concealed_auth_private_key_ = private_key; + concealed_auth_public_key_ = public_key; } QuicSpdyClientStream* MasqueClientSession::SendGetRequest( @@ -752,7 +752,7 @@ QuicSpdyClientStream* MasqueClientSession::SendGetRequest( << "\" path=\"" << path << "\""; // Send the request. - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":method"] = "GET"; headers[":scheme"] = scheme; headers[":authority"] = authority; @@ -775,9 +775,9 @@ void MasqueClientSession::OnClose(QuicSpdyStream* stream) { QUIC_DVLOG(1) << "Closing stream " << stream->id(); } -std::optional MasqueClientSession::ComputeSignatureAuthHeader( +std::optional MasqueClientSession::ComputeConcealedAuthHeader( const QuicUrl& url) { - if (signature_auth_private_key_.empty()) { + if (concealed_auth_private_key_.empty()) { return std::nullopt; } std::string scheme = url.scheme(); @@ -785,27 +785,27 @@ std::optional MasqueClientSession::ComputeSignatureAuthHeader( uint16_t port = url.port(); std::string realm = ""; std::string key_exporter_output; - std::string key_exporter_context = ComputeSignatureAuthContext( - kEd25519SignatureScheme, signature_auth_key_id_, - signature_auth_public_key_, scheme, host, port, realm); + std::string key_exporter_context = ComputeConcealedAuthContext( + kEd25519SignatureScheme, concealed_auth_key_id_, + concealed_auth_public_key_, scheme, host, port, realm); QUIC_DVLOG(1) << "key_exporter_context: " << absl::WebSafeBase64Escape(key_exporter_context); QUICHE_DCHECK(!key_exporter_context.empty()); if (!GetMutableCryptoStream()->ExportKeyingMaterial( - kSignatureAuthLabel, key_exporter_context, kSignatureAuthExporterSize, + kConcealedAuthLabel, key_exporter_context, kConcealedAuthExporterSize, &key_exporter_output)) { - QUIC_LOG(FATAL) << "Signature auth TLS exporter failed"; + QUIC_LOG(FATAL) << "Concealed auth TLS exporter failed"; return std::nullopt; } - QUICHE_CHECK_EQ(key_exporter_output.size(), kSignatureAuthExporterSize); + QUICHE_CHECK_EQ(key_exporter_output.size(), kConcealedAuthExporterSize); std::string signature_input = - key_exporter_output.substr(0, kSignatureAuthSignatureInputSize); + key_exporter_output.substr(0, kConcealedAuthSignatureInputSize); QUIC_DVLOG(1) << "signature_input: " << absl::WebSafeBase64Escape(signature_input); std::string verification = key_exporter_output.substr( - kSignatureAuthSignatureInputSize, kSignatureAuthVerificationSize); + kConcealedAuthSignatureInputSize, kConcealedAuthVerificationSize); std::string data_covered_by_signature = - SignatureAuthDataCoveredBySignature(signature_input); + ConcealedAuthDataCoveredBySignature(signature_input); QUIC_DVLOG(1) << "data_covered_by_signature: " << absl::WebSafeBase64Escape(data_covered_by_signature); uint8_t signature[ED25519_SIGNATURE_LEN]; @@ -814,25 +814,25 @@ std::optional MasqueClientSession::ComputeSignatureAuthHeader( reinterpret_cast(data_covered_by_signature.data()), data_covered_by_signature.size(), reinterpret_cast( - signature_auth_private_key_.data())) != 1) { - QUIC_LOG(FATAL) << "Signature auth signature failed"; + concealed_auth_private_key_.data())) != 1) { + QUIC_LOG(FATAL) << "Concealed auth signature failed"; return std::nullopt; } return absl::StrCat( - "Signature k=", absl::WebSafeBase64Escape(signature_auth_key_id_), - ", a=", absl::WebSafeBase64Escape(signature_auth_public_key_), ", p=", + "Concealed k=", absl::WebSafeBase64Escape(concealed_auth_key_id_), + ", a=", absl::WebSafeBase64Escape(concealed_auth_public_key_), ", p=", absl::WebSafeBase64Escape(absl::string_view( reinterpret_cast(signature), sizeof(signature))), ", s=", kEd25519SignatureScheme, ", v=", absl::WebSafeBase64Escape(verification)); } -void MasqueClientSession::AddAdditionalHeaders(spdy::Http2HeaderBlock& headers, +void MasqueClientSession::AddAdditionalHeaders(quiche::HttpHeaderBlock& headers, const QuicUrl& url) { - std::optional signature_auth_header = - ComputeSignatureAuthHeader(url); - if (signature_auth_header.has_value()) { - headers["authorization"] = *signature_auth_header; + std::optional concealed_auth_header = + ComputeConcealedAuthHeader(url); + if (concealed_auth_header.has_value()) { + headers["authorization"] = *concealed_auth_header; } if (additional_headers_.empty()) { return; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.h index 50617d606d..4ea6939748 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.h @@ -28,8 +28,8 @@ #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/tools/quic_url.h" #include "quiche/common/capsule.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/quiche_ip_address.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -182,10 +182,10 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, // QuicSpdyStream::Visitor void OnClose(QuicSpdyStream* stream) override; - // Set the signature auth key ID and private key. key_id MUST be non-empty, + // Set the concealed auth key ID and private key. key_id MUST be non-empty, // private_key MUST be ED25519_PRIVATE_KEY_LEN bytes long and public_key MUST // be ED25519_PUBLIC_KEY_LEN bytes long. - void EnableSignatureAuth(absl::string_view key_id, + void EnableConcealedAuth(absl::string_view key_id, absl::string_view private_key, absl::string_view public_key); @@ -328,16 +328,16 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession, const ConnectEthernetClientState* GetOrCreateConnectEthernetClientState( EncapsulatedEthernetSession* encapsulated_ethernet_session); - std::optional ComputeSignatureAuthHeader(const QuicUrl& url); - void AddAdditionalHeaders(spdy::Http2HeaderBlock& headers, + std::optional ComputeConcealedAuthHeader(const QuicUrl& url); + void AddAdditionalHeaders(quiche::HttpHeaderBlock& headers, const QuicUrl& url); MasqueMode masque_mode_; std::string uri_template_; std::string additional_headers_; - std::string signature_auth_key_id_; - std::string signature_auth_private_key_; - std::string signature_auth_public_key_; + std::string concealed_auth_key_id_; + std::string concealed_auth_private_key_; + std::string concealed_auth_public_key_; std::list connect_udp_client_states_; std::list connect_ip_client_states_; std::list connect_ethernet_client_states_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_tools.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_tools.cc index bf31ecb3b1..1e71adacf4 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_tools.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_tools.cc @@ -24,9 +24,9 @@ #include "quiche/quic/tools/fake_proof_verifier.h" #include "quiche/quic/tools/quic_name_lookup.h" #include "quiche/quic/tools/quic_url.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_ip_address.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { namespace tools { @@ -133,7 +133,7 @@ bool SendRequestOnMasqueEncapsulatedClient(MasqueEncapsulatedClient& client, const std::string body = ""; // Construct a GET request for supplied URL. - spdy::Http2HeaderBlock header_block; + quiche::HttpHeaderBlock header_block; header_block[":method"] = "GET"; header_block[":scheme"] = url.scheme(); header_block[":authority"] = url.HostPort(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc index 66ca13c966..86d06f3d04 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.cc @@ -23,8 +23,8 @@ #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_memory_cache_backend.h" #include "quiche/quic/tools/quic_simple_server_backend.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/quiche_text_utils.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -49,7 +49,7 @@ MasqueServerBackend::MasqueServerBackend(MasqueMode /*masque_mode*/, } bool MasqueServerBackend::MaybeHandleMasqueRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, QuicSimpleServerBackend::RequestHandler* request_handler) { auto method_pair = request_headers.find(":method"); if (method_pair == request_headers.end()) { @@ -64,7 +64,7 @@ bool MasqueServerBackend::MaybeHandleMasqueRequest( protocol_pair->second != "connect-ip" && protocol_pair->second != "connect-ethernet")) { // This is not a MASQUE request. - if (!signature_auth_on_all_requests_) { + if (!concealed_auth_on_all_requests_) { return false; } } @@ -109,7 +109,7 @@ bool MasqueServerBackend::MaybeHandleMasqueRequest( } void MasqueServerBackend::FetchResponseFromBackend( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) { if (MaybeHandleMasqueRequest(request_headers, request_handler)) { @@ -123,7 +123,7 @@ void MasqueServerBackend::FetchResponseFromBackend( } void MasqueServerBackend::HandleConnectHeaders( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, RequestHandler* request_handler) { if (MaybeHandleMasqueRequest(request_headers, request_handler)) { // Request was handled as a MASQUE request. @@ -177,12 +177,12 @@ QuicIpAddress MasqueServerBackend::GetNextClientIpAddress() { return address; } -void MasqueServerBackend::SetSignatureAuth(absl::string_view signature_auth) { - signature_auth_credentials_.clear(); - if (signature_auth.empty()) { +void MasqueServerBackend::SetConcealedAuth(absl::string_view concealed_auth) { + concealed_auth_credentials_.clear(); + if (concealed_auth.empty()) { return; } - for (absl::string_view sp : absl::StrSplit(signature_auth, ';')) { + for (absl::string_view sp : absl::StrSplit(concealed_auth, ';')) { quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&sp); if (sp.empty()) { continue; @@ -191,26 +191,26 @@ void MasqueServerBackend::SetSignatureAuth(absl::string_view signature_auth) { absl::StrSplit(sp, absl::MaxSplits(':', 1)); quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[0]); quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&kv[1]); - SignatureAuthCredential credential; + ConcealedAuthCredential credential; credential.key_id = std::string(kv[0]); std::string public_key; if (!absl::HexStringToBytes(kv[1], &public_key)) { - QUIC_LOG(FATAL) << "Invalid signature auth public key hex " << kv[1]; + QUIC_LOG(FATAL) << "Invalid concealed auth public key hex " << kv[1]; } if (public_key.size() != sizeof(credential.public_key)) { - QUIC_LOG(FATAL) << "Invalid signature auth public key length " + QUIC_LOG(FATAL) << "Invalid concealed auth public key length " << public_key.size(); } memcpy(credential.public_key, public_key.data(), sizeof(credential.public_key)); - signature_auth_credentials_.push_back(credential); + concealed_auth_credentials_.push_back(credential); } } -bool MasqueServerBackend::GetSignatureAuthKeyForId( +bool MasqueServerBackend::GetConcealedAuthKeyForId( absl::string_view key_id, uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN]) const { - for (const auto& credential : signature_auth_credentials_) { + for (const auto& credential : concealed_auth_credentials_) { if (credential.key_id == key_id) { memcpy(out_public_key, credential.public_key, sizeof(credential.public_key)); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.h index 7a938fee48..d097c2350f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_backend.h @@ -21,7 +21,7 @@ #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_memory_cache_backend.h" #include "quiche/quic/tools/quic_simple_server_backend.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -34,7 +34,7 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend { class QUIC_NO_EXPORT BackendClient { public: virtual std::unique_ptr HandleMasqueRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, QuicSimpleServerBackend::RequestHandler* request_handler) = 0; virtual ~BackendClient() = default; }; @@ -49,10 +49,10 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend { // From QuicMemoryCacheBackend. void FetchResponseFromBackend( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, const std::string& request_body, QuicSimpleServerBackend::RequestHandler* request_handler) override; - void HandleConnectHeaders(const spdy::Http2HeaderBlock& request_headers, + void HandleConnectHeaders(const quiche::HttpHeaderBlock& request_headers, RequestHandler* request_handler) override; void CloseBackendResponseStream( @@ -70,33 +70,33 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend { // Pass in a list of key identifiers and hex-encoded public keys, separated // with colons and semicolons. For example: "kid1:0123...f;kid2:0123...f". - void SetSignatureAuth(absl::string_view signature_auth); + void SetConcealedAuth(absl::string_view concealed_auth); - // Returns whether any signature auth credentials are configured. - bool IsSignatureAuthEnabled() const { - return !signature_auth_credentials_.empty(); + // Returns whether any concealed auth credentials are configured. + bool IsConcealedAuthEnabled() const { + return !concealed_auth_credentials_.empty(); } // If the key ID is known, copies the corresponding public key to // out_public_key and returns true. Otherwise returns false. - bool GetSignatureAuthKeyForId( + bool GetConcealedAuthKeyForId( absl::string_view key_id, uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN]) const; - // Enable signature auth on all requests (e.g., GET) instead of just MASQUE. - void SetSignatureAuthOnAllRequests(bool signature_auth_on_all_requests) { - signature_auth_on_all_requests_ = signature_auth_on_all_requests; + // Enable concealed auth on all requests (e.g., GET) instead of just MASQUE. + void SetConcealedAuthOnAllRequests(bool concealed_auth_on_all_requests) { + concealed_auth_on_all_requests_ = concealed_auth_on_all_requests; } - // Whether signature auth is enabled on all requests (e.g., GET). - bool IsSignatureAuthOnAllRequests() const { - return signature_auth_on_all_requests_; + // Whether concealed auth is enabled on all requests (e.g., GET). + bool IsConcealedAuthOnAllRequests() const { + return concealed_auth_on_all_requests_; } private: // Handle MASQUE request. bool MaybeHandleMasqueRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, QuicSimpleServerBackend::RequestHandler* request_handler); MasqueMode masque_mode_; @@ -110,12 +110,12 @@ class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend { QuicConnectionIdHash> backend_client_states_; uint8_t connect_ip_next_client_ip_[4]; - struct QUIC_NO_EXPORT SignatureAuthCredential { + struct QUIC_NO_EXPORT ConcealedAuthCredential { std::string key_id; uint8_t public_key[ED25519_PUBLIC_KEY_LEN]; }; - std::list signature_auth_credentials_; - bool signature_auth_on_all_requests_ = false; + std::list concealed_auth_credentials_; + bool concealed_auth_on_all_requests_ = false; }; } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_bin.cc index 51f5b4017b..7a99bdb005 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_bin.cc @@ -40,15 +40,15 @@ DEFINE_QUICHE_COMMAND_LINE_FLAG( "Allows setting MASQUE mode, currently only valid value is \"open\"."); DEFINE_QUICHE_COMMAND_LINE_FLAG( - std::string, signature_auth, "", - "Require HTTP Signature Authentication. Pass in a list of key identifiers " + std::string, concealed_auth, "", + "Require HTTP Concealed Authentication. Pass in a list of key identifiers " "and hex-encoded public keys. " "Separated with colons and semicolons. " "For example: \"kid1:0123...f;kid2:0123...f\"."); DEFINE_QUICHE_COMMAND_LINE_FLAG( - bool, signature_auth_on_all_requests, false, - "If set to true, enable signature auth on all requests (such as GET) " + bool, concealed_auth_on_all_requests, false, + "If set to true, enable concealed auth on all requests (such as GET) " "instead of just MASQUE."); int main(int argc, char* argv[]) { @@ -72,10 +72,10 @@ int main(int argc, char* argv[]) { masque_mode, quiche::GetQuicheCommandLineFlag(FLAGS_server_authority), quiche::GetQuicheCommandLineFlag(FLAGS_cache_dir)); - backend->SetSignatureAuth( - quiche::GetQuicheCommandLineFlag(FLAGS_signature_auth)); - backend->SetSignatureAuthOnAllRequests( - quiche::GetQuicheCommandLineFlag(FLAGS_signature_auth_on_all_requests)); + backend->SetConcealedAuth( + quiche::GetQuicheCommandLineFlag(FLAGS_concealed_auth)); + backend->SetConcealedAuthOnAllRequests( + quiche::GetQuicheCommandLineFlag(FLAGS_concealed_auth_on_all_requests)); auto server = std::make_unique(masque_mode, backend.get()); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc index a413f584ab..69482af619 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc @@ -54,11 +54,11 @@ #include "quiche/quic/tools/quic_simple_server_session.h" #include "quiche/quic/tools/quic_url.h" #include "quiche/common/capsule.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/platform/api/quiche_url_utils.h" #include "quiche/common/quiche_ip_address.h" #include "quiche/common/quiche_text_utils.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -113,7 +113,7 @@ class FdWrapper { std::unique_ptr CreateBackendErrorResponse( absl::string_view status, absl::string_view error_details) { - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = status; response_headers["masque-debug-info"] = error_details; auto response = std::make_unique(); @@ -188,19 +188,19 @@ void MasqueServerSession::OnStreamClosed(QuicStreamId stream_id) { } std::unique_ptr -MasqueServerSession::MaybeCheckSignatureAuth( - const spdy::Http2HeaderBlock& request_headers, absl::string_view authority, +MasqueServerSession::MaybeCheckConcealedAuth( + const quiche::HttpHeaderBlock& request_headers, absl::string_view authority, absl::string_view scheme, QuicSimpleServerBackend::RequestHandler* request_handler) { // TODO(dschinazi) Add command-line flag that makes this implementation // probe-resistant by returning the usual failure instead of 401. - constexpr absl::string_view kSignatureAuthStatus = "401"; - if (!masque_server_backend_->IsSignatureAuthEnabled()) { + constexpr absl::string_view kConcealedAuthStatus = "401"; + if (!masque_server_backend_->IsConcealedAuthEnabled()) { return nullptr; } auto authorization_pair = request_headers.find("authorization"); if (authorization_pair == request_headers.end()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Missing authorization header"); } absl::string_view credentials = authorization_pair->second; @@ -208,12 +208,12 @@ MasqueServerSession::MaybeCheckSignatureAuth( std::vector v = absl::StrSplit(credentials, absl::MaxSplits(' ', 1)); if (v.size() != 2) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Authorization header missing space"); } absl::string_view auth_scheme = v[0]; - if (auth_scheme != "Signature") { - return CreateBackendErrorResponse(kSignatureAuthStatus, + if (auth_scheme != "Concealed") { + return CreateBackendErrorResponse(kConcealedAuthStatus, "Unexpected auth scheme"); } absl::string_view auth_parameters = v[1]; @@ -242,58 +242,58 @@ MasqueServerSession::MaybeCheckSignatureAuth( switch (param_name[0]) { case 'k': { if (key_id.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Duplicate k"); } if (!absl::WebSafeBase64Unescape(param_value, &decoded_param)) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Failed to base64 decode k"); } key_id = decoded_param; } break; case 'a': { if (header_public_key.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Duplicate a"); } if (!absl::WebSafeBase64Unescape(param_value, &decoded_param)) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Failed to base64 decode a"); } header_public_key = decoded_param; } break; case 'p': { if (proof.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Duplicate p"); } if (!absl::WebSafeBase64Unescape(param_value, &decoded_param)) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Failed to base64 decode p"); } proof = decoded_param; } break; case 's': { if (signature_scheme.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Duplicate s"); } int signature_scheme_int = 0; if (!absl::SimpleAtoi(param_value, &signature_scheme_int) || signature_scheme_int < 0 || signature_scheme_int > std::numeric_limits::max()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Failed to parse s"); } signature_scheme = static_cast(signature_scheme_int); } break; case 'v': { if (verification.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Duplicate v"); } if (!absl::WebSafeBase64Unescape(param_value, &decoded_param)) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Failed to base64 decode v"); } verification = decoded_param; @@ -301,40 +301,40 @@ MasqueServerSession::MaybeCheckSignatureAuth( } } if (!key_id.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Missing k auth parameter"); } if (!header_public_key.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Missing a auth parameter"); } if (!proof.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Missing p auth parameter"); } if (!signature_scheme.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Missing s auth parameter"); } if (!verification.has_value()) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Missing v auth parameter"); } uint8_t config_public_key[ED25519_PUBLIC_KEY_LEN]; - if (!masque_server_backend_->GetSignatureAuthKeyForId(*key_id, + if (!masque_server_backend_->GetConcealedAuthKeyForId(*key_id, config_public_key)) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Unexpected key id"); } if (*header_public_key != std::string(reinterpret_cast(config_public_key), sizeof(config_public_key))) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Unexpected public key in header"); } std::string realm = ""; QuicUrl url(absl::StrCat(scheme, "://", authority, "/")); - std::optional key_exporter_context = ComputeSignatureAuthContext( + std::optional key_exporter_context = ComputeConcealedAuthContext( kEd25519SignatureScheme, *key_id, *header_public_key, scheme, url.host(), url.port(), realm); if (!key_exporter_context.has_value()) { @@ -346,20 +346,20 @@ MasqueServerSession::MaybeCheckSignatureAuth( QUICHE_DCHECK(!key_exporter_context->empty()); std::string key_exporter_output; if (!GetMutableCryptoStream()->ExportKeyingMaterial( - kSignatureAuthLabel, *key_exporter_context, - kSignatureAuthExporterSize, &key_exporter_output)) { + kConcealedAuthLabel, *key_exporter_context, + kConcealedAuthExporterSize, &key_exporter_output)) { return CreateBackendErrorResponse("500", "Key exporter failed"); } - QUICHE_CHECK_EQ(key_exporter_output.size(), kSignatureAuthExporterSize); + QUICHE_CHECK_EQ(key_exporter_output.size(), kConcealedAuthExporterSize); std::string signature_input = - key_exporter_output.substr(0, kSignatureAuthSignatureInputSize); + key_exporter_output.substr(0, kConcealedAuthSignatureInputSize); QUIC_DVLOG(1) << "signature_input: " << absl::WebSafeBase64Escape(signature_input); std::string expected_verification = key_exporter_output.substr( - kSignatureAuthSignatureInputSize, kSignatureAuthVerificationSize); + kConcealedAuthSignatureInputSize, kConcealedAuthVerificationSize); if (verification != expected_verification) { return CreateBackendErrorResponse( - kSignatureAuthStatus, + kConcealedAuthStatus, absl::StrCat("Unexpected verification, expected ", absl::WebSafeBase64Escape(expected_verification), " but got ", absl::WebSafeBase64Escape(*verification), @@ -367,15 +367,15 @@ MasqueServerSession::MaybeCheckSignatureAuth( absl::WebSafeBase64Escape(*key_exporter_context))); } std::string data_covered_by_signature = - SignatureAuthDataCoveredBySignature(signature_input); + ConcealedAuthDataCoveredBySignature(signature_input); QUIC_DVLOG(1) << "data_covered_by_signature: " << absl::WebSafeBase64Escape(data_covered_by_signature); if (*signature_scheme != kEd25519SignatureScheme) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Unexpected signature scheme"); } if (proof->size() != ED25519_SIGNATURE_LEN) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Unexpected proof length"); } if (ED25519_verify( @@ -383,7 +383,7 @@ MasqueServerSession::MaybeCheckSignatureAuth( data_covered_by_signature.size(), reinterpret_cast(proof->data()), config_public_key) != 1) { - return CreateBackendErrorResponse(kSignatureAuthStatus, + return CreateBackendErrorResponse(kConcealedAuthStatus, "Signature failed to validate"); } QUIC_LOG(INFO) << "Successfully validated signature auth for stream ID " @@ -392,7 +392,7 @@ MasqueServerSession::MaybeCheckSignatureAuth( } std::unique_ptr MasqueServerSession::HandleMasqueRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, QuicSimpleServerBackend::RequestHandler* request_handler) { // Authority. auto authority_pair = request_headers.find(":authority"); @@ -411,11 +411,11 @@ std::unique_ptr MasqueServerSession::HandleMasqueRequest( if (scheme.empty()) { return CreateBackendErrorResponse("400", "Empty scheme"); } - // Signature authentication. - auto signature_auth_reply = MaybeCheckSignatureAuth( + // Concealed authentication. + auto concealed_auth_reply = MaybeCheckConcealedAuth( request_headers, authority, scheme, request_handler); - if (signature_auth_reply) { - return signature_auth_reply; + if (concealed_auth_reply) { + return concealed_auth_reply; } // Path. auto path_pair = request_headers.find(":path"); @@ -437,7 +437,7 @@ std::unique_ptr MasqueServerSession::HandleMasqueRequest( absl::string_view method = method_pair->second; if (method != "CONNECT") { QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\""; - if (masque_server_backend_->IsSignatureAuthOnAllRequests()) { + if (masque_server_backend_->IsConcealedAuthOnAllRequests()) { return nullptr; } else { return CreateBackendErrorResponse("400", "Bad method"); @@ -447,7 +447,7 @@ std::unique_ptr MasqueServerSession::HandleMasqueRequest( auto protocol_pair = request_headers.find(":protocol"); if (protocol_pair == request_headers.end()) { QUIC_DLOG(ERROR) << "MASQUE request is missing :protocol"; - if (masque_server_backend_->IsSignatureAuthOnAllRequests()) { + if (masque_server_backend_->IsConcealedAuthOnAllRequests()) { return nullptr; } else { return CreateBackendErrorResponse("400", "Missing :protocol"); @@ -458,7 +458,7 @@ std::unique_ptr MasqueServerSession::HandleMasqueRequest( protocol != "connect-ethernet") { QUIC_DLOG(ERROR) << "MASQUE request with bad protocol \"" << protocol << "\""; - if (masque_server_backend_->IsSignatureAuthOnAllRequests()) { + if (masque_server_backend_->IsConcealedAuthOnAllRequests()) { return nullptr; } else { return CreateBackendErrorResponse("400", "Bad protocol"); @@ -493,7 +493,7 @@ std::unique_ptr MasqueServerSession::HandleMasqueRequest( connect_ip_server_states_.push_back( ConnectIpServerState(client_ip, stream, fd, this)); - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = "200"; auto response = std::make_unique(); response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE); @@ -526,7 +526,7 @@ std::unique_ptr MasqueServerSession::HandleMasqueRequest( connect_ethernet_server_states_.push_back( ConnectEthernetServerState(stream, fd, this)); - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = "200"; auto response = std::make_unique(); response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE); @@ -606,7 +606,7 @@ std::unique_ptr MasqueServerSession::HandleMasqueRequest( connect_udp_server_states_.push_back(ConnectUdpServerState( stream, target_server_address, fd_wrapper.extract_fd(), this)); - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = "200"; auto response = std::make_unique(); response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.h index c7659f2013..202bb62d5e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.h @@ -33,7 +33,7 @@ #include "quiche/quic/tools/quic_simple_server_backend.h" #include "quiche/quic/tools/quic_simple_server_session.h" #include "quiche/common/capsule.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -66,7 +66,7 @@ class QUIC_NO_EXPORT MasqueServerSession // From MasqueServerBackend::BackendClient. std::unique_ptr HandleMasqueRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, QuicSimpleServerBackend::RequestHandler* request_handler) override; // From QuicSocketEventListener. @@ -82,8 +82,8 @@ class QUIC_NO_EXPORT MasqueServerSession QuicSocketEventMask events); bool HandleConnectEthernetSocketEvent(QuicUdpSocketFd fd, QuicSocketEventMask events); - std::unique_ptr MaybeCheckSignatureAuth( - const spdy::Http2HeaderBlock& request_headers, + std::unique_ptr MaybeCheckConcealedAuth( + const quiche::HttpHeaderBlock& request_headers, absl::string_view authority, absl::string_view scheme, QuicSimpleServerBackend::RequestHandler* request_handler); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_utils.cc index 999fc75288..0bfd5d1dbb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_utils.cc @@ -214,13 +214,13 @@ int CreateTapInterface() { } #endif // defined(__linux__) -std::string ComputeSignatureAuthContext(uint16_t signature_scheme, +std::string ComputeConcealedAuthContext(uint16_t signature_scheme, absl::string_view key_id, absl::string_view public_key, absl::string_view scheme, absl::string_view host, uint16_t port, absl::string_view realm) { - QUIC_DVLOG(2) << "ComputeSignatureAuthContext: key_id=\"" << key_id + QUIC_DVLOG(2) << "ComputeConcealedAuthContext: key_id=\"" << key_id << "\" public_key=" << absl::WebSafeBase64Escape(public_key) << " scheme=\"" << scheme << "\" host=\"" << host << "\" port=" << port << " realm=\"" << realm << "\""; @@ -240,14 +240,14 @@ std::string ComputeSignatureAuthContext(uint16_t signature_scheme, !writer.WriteStringPieceVarInt62(scheme) || !writer.WriteStringPieceVarInt62(host) || !writer.WriteUInt16(port) || !writer.WriteStringPieceVarInt62(realm) || writer.remaining() != 0) { - QUIC_LOG(FATAL) << "ComputeSignatureAuthContext failed"; + QUIC_LOG(FATAL) << "ComputeConcealedAuthContext failed"; } return key_exporter_context; } -std::string SignatureAuthDataCoveredBySignature( +std::string ConcealedAuthDataCoveredBySignature( absl::string_view signature_input) { - return absl::StrCat(std::string(64, 0x20), "HTTP Signature Authentication", + return absl::StrCat(std::string(64, 0x20), "HTTP Concealed Authentication", std::string(1, 0x00), signature_input); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_utils.h index 4cf1189763..09705d5488 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_utils.h @@ -54,23 +54,23 @@ int CreateTunInterface(const QuicIpAddress& client_address, bool server = true); // Create a TAP interface. Requires root. int CreateTapInterface(); -inline constexpr size_t kSignatureAuthSignatureInputSize = 32; -inline constexpr size_t kSignatureAuthVerificationSize = 16; -inline constexpr size_t kSignatureAuthExporterSize = - kSignatureAuthSignatureInputSize + kSignatureAuthVerificationSize; +inline constexpr size_t kConcealedAuthSignatureInputSize = 32; +inline constexpr size_t kConcealedAuthVerificationSize = 16; +inline constexpr size_t kConcealedAuthExporterSize = + kConcealedAuthSignatureInputSize + kConcealedAuthVerificationSize; inline constexpr uint16_t kEd25519SignatureScheme = 0x0807; -inline constexpr absl::string_view kSignatureAuthLabel = - "EXPORTER-HTTP-Signature-Authentication"; +inline constexpr absl::string_view kConcealedAuthLabel = + "EXPORTER-HTTP-Concealed-Authentication"; // Returns the signature auth TLS key exporter context. -QUIC_NO_EXPORT std::string ComputeSignatureAuthContext( +QUIC_NO_EXPORT std::string ComputeConcealedAuthContext( uint16_t signature_scheme, absl::string_view key_id, absl::string_view public_key, absl::string_view scheme, absl::string_view host, uint16_t port, absl::string_view realm); // Returns the data covered by signature auth signatures, computed by // concatenating a fixed prefix from the specification and the signature input. -QUIC_NO_EXPORT std::string SignatureAuthDataCoveredBySignature( +QUIC_NO_EXPORT std::string ConcealedAuthDataCoveredBySignature( absl::string_view signature_input); } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_cached_object.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_cached_object.cc new file mode 100644 index 0000000000..395875b570 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_cached_object.cc @@ -0,0 +1,25 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "quiche/quic/moqt/moqt_cached_object.h" + +#include "quiche/quic/moqt/moqt_publisher.h" +#include "quiche/common/platform/api/quiche_mem_slice.h" + +namespace moqt { + +moqt::PublishedObject CachedObjectToPublishedObject( + const CachedObject& object) { + PublishedObject result; + result.sequence = object.sequence; + result.status = object.status; + if (object.payload != nullptr && !object.payload->empty()) { + result.payload = quiche::QuicheMemSlice( + object.payload->data(), object.payload->length(), + [retained_pointer = object.payload](const char*) {}); + } + return result; +} + +} // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_cached_object.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_cached_object.h new file mode 100644 index 0000000000..c04b31e20a --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_cached_object.h @@ -0,0 +1,29 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_QUIC_MOQT_MOQT_CACHED_OBJECT_H_ +#define QUICHE_QUIC_MOQT_MOQT_CACHED_OBJECT_H_ + +#include + +#include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_publisher.h" +#include "quiche/common/platform/api/quiche_mem_slice.h" + +namespace moqt { + +// CachedObject is a version of PublishedObject with a reference counted +// payload. +struct CachedObject { + FullSequence sequence; + MoqtObjectStatus status; + std::shared_ptr payload; +}; + +// Transforms a CachedObject into a PublishedObject. +PublishedObject CachedObjectToPublishedObject(const CachedObject& object); + +} // namespace moqt + +#endif // QUICHE_QUIC_MOQT_MOQT_CACHED_OBJECT_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.cc index 05a04409df..aff5753fbe 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.cc @@ -18,8 +18,10 @@ #include "quiche/quic/core/quic_data_writer.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" +#include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_buffer_allocator.h" #include "quiche/common/quiche_data_writer.h" #include "quiche/common/simple_buffer_allocator.h" @@ -37,42 +39,6 @@ using ::quiche::WireStringWithVarInt62Length; using ::quiche::WireUint8; using ::quiche::WireVarInt62; -// Encoding for MOQT Locations: -// https://moq-wg.github.io/moq-transport/draft-ietf-moq-transport.html#name-subscribe-locations -class WireLocation { - public: - using DataType = std::optional; - explicit WireLocation(const DataType& location) : location_(location) {} - - size_t GetLengthOnWire() { - return quiche::ComputeLengthOnWire( - WireVarInt62(GetModeForSubscribeLocation(location_)), - WireOptional(LocationOffsetOnTheWire(location_))); - } - absl::Status SerializeIntoWriter(quiche::QuicheDataWriter& writer) { - return quiche::SerializeIntoWriter( - writer, WireVarInt62(GetModeForSubscribeLocation(location_)), - WireOptional(LocationOffsetOnTheWire(location_))); - } - - private: - // For all location types other than None, we record a single varint after the - // type; this function computes the value of that varint. - static std::optional LocationOffsetOnTheWire( - std::optional location) { - if (!location.has_value()) { - return std::nullopt; - } - if (location->absolute) { - return location->absolute_value; - } - return location->relative_value <= 0 ? -location->relative_value - : location->relative_value + 1; - } - - const DataType& location_; -}; - // Encoding for string parameters as described in // https://moq-wg.github.io/moq-transport/draft-ietf-moq-transport.html#name-parameters struct StringParameter { @@ -160,6 +126,20 @@ QuicheBuffer Serialize(Ts... data) { return *std::move(buffer); } +WireUint8 WireDeliveryOrder(std::optional delivery_order) { + if (!delivery_order.has_value()) { + return WireUint8(0x00); + } + switch (*delivery_order) { + case MoqtDeliveryOrder::kAscending: + return WireUint8(0x01); + case MoqtDeliveryOrder::kDescending: + return WireUint8(0x02); + } + QUICHE_NOTREACHED(); + return WireUint8(0xff); +} + } // namespace quiche::QuicheBuffer MoqtFramer::SerializeObjectHeader( @@ -172,15 +152,31 @@ quiche::QuicheBuffer MoqtFramer::SerializeObjectHeader( "length in advance"; return quiche::QuicheBuffer(); } + if (message.object_status != MoqtObjectStatus::kNormal && + message.payload_length.has_value() && *message.payload_length > 0) { + QUIC_BUG(quic_bug_serialize_object_input_03) + << "Object status must be kNormal if payload is non-empty"; + return quiche::QuicheBuffer(); + } if (!is_first_in_stream) { switch (message.forwarding_preference) { case MoqtForwardingPreference::kTrack: - return Serialize(WireVarInt62(message.group_id), - WireVarInt62(message.object_id), - WireVarInt62(*message.payload_length)); + return (*message.payload_length == 0) + ? Serialize(WireVarInt62(message.group_id), + WireVarInt62(message.object_id), + WireVarInt62(*message.payload_length), + WireVarInt62(message.object_status)) + : Serialize(WireVarInt62(message.group_id), + WireVarInt62(message.object_id), + WireVarInt62(*message.payload_length)); case MoqtForwardingPreference::kGroup: - return Serialize(WireVarInt62(message.object_id), - WireVarInt62(*message.payload_length)); + return (*message.payload_length == 0) + ? Serialize(WireVarInt62(message.object_id), + WireVarInt62(*message.payload_length), + WireVarInt62(static_cast( + message.object_status))) + : Serialize(WireVarInt62(message.object_id), + WireVarInt62(*message.payload_length)); default: QUIC_BUG(quic_bug_serialize_object_input_02) << "Object or Datagram forwarding_preference must be first in " @@ -192,36 +188,64 @@ quiche::QuicheBuffer MoqtFramer::SerializeObjectHeader( GetMessageTypeForForwardingPreference(message.forwarding_preference); switch (message.forwarding_preference) { case MoqtForwardingPreference::kTrack: - return Serialize( - WireVarInt62(message_type), WireVarInt62(message.subscribe_id), - WireVarInt62(message.track_alias), - WireVarInt62(message.object_send_order), - WireVarInt62(message.group_id), WireVarInt62(message.object_id), - WireVarInt62(*message.payload_length)); + return (*message.payload_length == 0) + ? Serialize(WireVarInt62(message_type), + WireVarInt62(message.subscribe_id), + WireVarInt62(message.track_alias), + WireUint8(message.publisher_priority), + WireVarInt62(message.group_id), + WireVarInt62(message.object_id), + WireVarInt62(*message.payload_length), + WireVarInt62(message.object_status)) + : Serialize(WireVarInt62(message_type), + WireVarInt62(message.subscribe_id), + WireVarInt62(message.track_alias), + WireUint8(message.publisher_priority), + WireVarInt62(message.group_id), + WireVarInt62(message.object_id), + WireVarInt62(*message.payload_length)); case MoqtForwardingPreference::kGroup: - return Serialize( - WireVarInt62(message_type), WireVarInt62(message.subscribe_id), - WireVarInt62(message.track_alias), WireVarInt62(message.group_id), - WireVarInt62(message.object_send_order), - WireVarInt62(message.object_id), - WireVarInt62(*message.payload_length)); + return (*message.payload_length == 0) + ? Serialize(WireVarInt62(message_type), + WireVarInt62(message.subscribe_id), + WireVarInt62(message.track_alias), + WireVarInt62(message.group_id), + WireUint8(message.publisher_priority), + WireVarInt62(message.object_id), + WireVarInt62(*message.payload_length), + WireVarInt62(message.object_status)) + : Serialize(WireVarInt62(message_type), + WireVarInt62(message.subscribe_id), + WireVarInt62(message.track_alias), + WireVarInt62(message.group_id), + WireUint8(message.publisher_priority), + WireVarInt62(message.object_id), + WireVarInt62(*message.payload_length)); case MoqtForwardingPreference::kObject: case MoqtForwardingPreference::kDatagram: return Serialize( WireVarInt62(message_type), WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), WireVarInt62(message.group_id), WireVarInt62(message.object_id), - WireVarInt62(message.object_send_order)); + WireUint8(message.publisher_priority), + WireVarInt62(message.object_status)); } } quiche::QuicheBuffer MoqtFramer::SerializeObjectDatagram( const MoqtObject& message, absl::string_view payload) { + if (message.object_status != MoqtObjectStatus::kNormal && !payload.empty()) { + QUIC_BUG(quic_bug_serialize_object_datagram_01) + << "Object status must be kNormal if payload is non-empty"; + return quiche::QuicheBuffer(); + } return Serialize( WireVarInt62(MoqtMessageType::kObjectDatagram), WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), WireVarInt62(message.group_id), WireVarInt62(message.object_id), - WireVarInt62(message.object_send_order), WireBytes(payload)); + WireUint8(message.publisher_priority), + WireVarInt62(static_cast(message.object_status)), + WireBytes(payload)); } quiche::QuicheBuffer MoqtFramer::SerializeClientSetup( @@ -260,14 +284,9 @@ quiche::QuicheBuffer MoqtFramer::SerializeServerSetup( quiche::QuicheBuffer MoqtFramer::SerializeSubscribe( const MoqtSubscribe& message) { - if (!message.start_group.has_value() || !message.start_object.has_value()) { - QUICHE_BUG(MoqtFramer_start_group_missing) - << "start_group or start_object is missing"; - return quiche::QuicheBuffer(); - } - if (message.end_group.has_value() != message.end_object.has_value()) { - QUICHE_BUG(MoqtFramer_end_mismatch) - << "end_group and end_object must both be None or both non-None"; + MoqtFilterType filter_type = GetFilterType(message); + if (filter_type == MoqtFilterType::kNone) { + QUICHE_BUG(MoqtFramer_invalid_subscribe) << "Invalid object range"; return quiche::QuicheBuffer(); } absl::InlinedVector string_params; @@ -276,15 +295,48 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribe( StringParameter(MoqtTrackRequestParameter::kAuthorizationInfo, *message.authorization_info)); } - return Serialize( - WireVarInt62(MoqtMessageType::kSubscribe), - WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), - WireStringWithVarInt62Length(message.track_namespace), - WireStringWithVarInt62Length(message.track_name), - WireLocation(message.start_group), WireLocation(message.start_object), - WireLocation(message.end_group), WireLocation(message.end_object), - WireVarInt62(string_params.size()), - WireSpan(string_params)); + switch (filter_type) { + case MoqtFilterType::kLatestGroup: + case MoqtFilterType::kLatestObject: + return Serialize( + WireVarInt62(MoqtMessageType::kSubscribe), + WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), + WireStringWithVarInt62Length(message.track_namespace), + WireStringWithVarInt62Length(message.track_name), + WireUint8(message.subscriber_priority), + WireDeliveryOrder(message.group_order), WireVarInt62(filter_type), + WireVarInt62(string_params.size()), + WireSpan(string_params)); + case MoqtFilterType::kAbsoluteStart: + return Serialize( + WireVarInt62(MoqtMessageType::kSubscribe), + WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), + WireStringWithVarInt62Length(message.track_namespace), + WireStringWithVarInt62Length(message.track_name), + WireUint8(message.subscriber_priority), + WireDeliveryOrder(message.group_order), WireVarInt62(filter_type), + WireVarInt62(*message.start_group), + WireVarInt62(*message.start_object), + WireVarInt62(string_params.size()), + WireSpan(string_params)); + case MoqtFilterType::kAbsoluteRange: + return Serialize( + WireVarInt62(MoqtMessageType::kSubscribe), + WireVarInt62(message.subscribe_id), WireVarInt62(message.track_alias), + WireStringWithVarInt62Length(message.track_namespace), + WireStringWithVarInt62Length(message.track_name), + WireUint8(message.subscriber_priority), + WireDeliveryOrder(message.group_order), WireVarInt62(filter_type), + WireVarInt62(*message.start_group), + WireVarInt62(*message.start_object), WireVarInt62(*message.end_group), + WireVarInt62(message.end_object.has_value() ? *message.end_object + 1 + : 0), + WireVarInt62(string_params.size()), + WireSpan(string_params)); + default: + QUICHE_BUG(MoqtFramer_end_group_missing) << "Subscribe framing error."; + return quiche::QuicheBuffer(); + } } quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk( @@ -293,13 +345,14 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk( return Serialize(WireVarInt62(MoqtMessageType::kSubscribeOk), WireVarInt62(message.subscribe_id), WireVarInt62(message.expires.ToMilliseconds()), - WireUint8(1), WireVarInt62(message.largest_id->group), + WireDeliveryOrder(message.group_order), WireUint8(1), + WireVarInt62(message.largest_id->group), WireVarInt62(message.largest_id->object)); } return Serialize(WireVarInt62(MoqtMessageType::kSubscribeOk), WireVarInt62(message.subscribe_id), WireVarInt62(message.expires.ToMilliseconds()), - WireUint8(0)); + WireDeliveryOrder(message.group_order), WireUint8(0)); } quiche::QuicheBuffer MoqtFramer::SerializeSubscribeError( @@ -333,6 +386,30 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeDone( WireStringWithVarInt62Length(message.reason_phrase), WireUint8(0)); } +quiche::QuicheBuffer MoqtFramer::SerializeSubscribeUpdate( + const MoqtSubscribeUpdate& message) { + uint64_t end_group = + message.end_group.has_value() ? *message.end_group + 1 : 0; + uint64_t end_object = + message.end_object.has_value() ? *message.end_object + 1 : 0; + if (end_group == 0 && end_object != 0) { + QUICHE_BUG(MoqtFramer_invalid_subscribe_update) << "Invalid object range"; + return quiche::QuicheBuffer(); + } + absl::InlinedVector string_params; + if (message.authorization_info.has_value()) { + string_params.push_back( + StringParameter(MoqtTrackRequestParameter::kAuthorizationInfo, + *message.authorization_info)); + } + return Serialize( + WireVarInt62(MoqtMessageType::kSubscribeUpdate), + WireVarInt62(message.subscribe_id), WireVarInt62(message.start_group), + WireVarInt62(message.start_object), WireVarInt62(end_group), + WireVarInt62(end_object), WireUint8(message.subscriber_priority), + WireSpan(string_params)); +} + quiche::QuicheBuffer MoqtFramer::SerializeAnnounce( const MoqtAnnounce& message) { absl::InlinedVector string_params; @@ -362,12 +439,35 @@ quiche::QuicheBuffer MoqtFramer::SerializeAnnounceError( WireStringWithVarInt62Length(message.reason_phrase)); } +quiche::QuicheBuffer MoqtFramer::SerializeAnnounceCancel( + const MoqtAnnounceCancel& message) { + return Serialize(WireVarInt62(MoqtMessageType::kAnnounceCancel), + WireStringWithVarInt62Length(message.track_namespace)); +} + +quiche::QuicheBuffer MoqtFramer::SerializeTrackStatusRequest( + const MoqtTrackStatusRequest& message) { + return Serialize(WireVarInt62(MoqtMessageType::kTrackStatusRequest), + WireStringWithVarInt62Length(message.track_namespace), + WireStringWithVarInt62Length(message.track_name)); +} + quiche::QuicheBuffer MoqtFramer::SerializeUnannounce( const MoqtUnannounce& message) { return Serialize(WireVarInt62(MoqtMessageType::kUnannounce), WireStringWithVarInt62Length(message.track_namespace)); } +quiche::QuicheBuffer MoqtFramer::SerializeTrackStatus( + const MoqtTrackStatus& message) { + return Serialize(WireVarInt62(MoqtMessageType::kTrackStatus), + WireStringWithVarInt62Length(message.track_namespace), + WireStringWithVarInt62Length(message.track_name), + WireVarInt62(message.status_code), + WireVarInt62(message.last_group), + WireVarInt62(message.last_object)); +} + quiche::QuicheBuffer MoqtFramer::SerializeGoAway(const MoqtGoAway& message) { return Serialize(WireVarInt62(MoqtMessageType::kGoAway), WireStringWithVarInt62Length(message.new_session_uri)); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.h index 7f19fa81ec..6aef8b6c7e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.h @@ -5,11 +5,7 @@ #ifndef QUICHE_QUIC_MOQT_MOQT_FRAMER_H_ #define QUICHE_QUIC_MOQT_MOQT_FRAMER_H_ -#include -#include - #include "absl/strings/string_view.h" -#include "quiche/quic/core/quic_types.h" #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/quiche_buffer_allocator.h" @@ -47,10 +43,17 @@ class QUICHE_EXPORT MoqtFramer { const MoqtSubscribeError& message); quiche::QuicheBuffer SerializeUnsubscribe(const MoqtUnsubscribe& message); quiche::QuicheBuffer SerializeSubscribeDone(const MoqtSubscribeDone& message); + quiche::QuicheBuffer SerializeSubscribeUpdate( + const MoqtSubscribeUpdate& message); quiche::QuicheBuffer SerializeAnnounce(const MoqtAnnounce& message); quiche::QuicheBuffer SerializeAnnounceOk(const MoqtAnnounceOk& message); quiche::QuicheBuffer SerializeAnnounceError(const MoqtAnnounceError& message); + quiche::QuicheBuffer SerializeAnnounceCancel( + const MoqtAnnounceCancel& message); + quiche::QuicheBuffer SerializeTrackStatusRequest( + const MoqtTrackStatusRequest& message); quiche::QuicheBuffer SerializeUnannounce(const MoqtUnannounce& message); + quiche::QuicheBuffer SerializeTrackStatus(const MoqtTrackStatus& message); quiche::QuicheBuffer SerializeGoAway(const MoqtGoAway& message); private: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_known_track_publisher.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_known_track_publisher.cc new file mode 100644 index 0000000000..2fa4daf2d3 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_known_track_publisher.cc @@ -0,0 +1,34 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "quiche/quic/moqt/moqt_known_track_publisher.h" + +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_publisher.h" +#include "quiche/common/platform/api/quiche_bug_tracker.h" + +namespace moqt { + +absl::StatusOr> +MoqtKnownTrackPublisher::GetTrack(const FullTrackName& track_name) { + auto it = tracks_.find(track_name); + if (it == tracks_.end()) { + return absl::NotFoundError("Requested track not found"); + } + return it->second; +} + +void MoqtKnownTrackPublisher::Add( + std::shared_ptr track_publisher) { + const FullTrackName& track_name = track_publisher->GetTrackName(); + auto [it, success] = tracks_.emplace(track_name, track_publisher); + QUICHE_BUG_IF(MoqtKnownTrackPublisher_duplicate, !success) + << "Trying to add a duplicate track into a KnownTrackPublisher"; +} + +} // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_known_track_publisher.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_known_track_publisher.h new file mode 100644 index 0000000000..dd9316fa48 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_known_track_publisher.h @@ -0,0 +1,38 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_QUIC_MOQT_MOQT_KNOWN_TRACK_PUBLISHER_H_ +#define QUICHE_QUIC_MOQT_MOQT_KNOWN_TRACK_PUBLISHER_H_ + +#include + +#include "absl/container/flat_hash_map.h" +#include "absl/status/statusor.h" +#include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_publisher.h" + +namespace moqt { + +// MoqtKnownTrackPublisher is a publisher that supports publishing a set of +// well-known predefined tracks. +class MoqtKnownTrackPublisher : public MoqtPublisher { + public: + MoqtKnownTrackPublisher() = default; + MoqtKnownTrackPublisher(const MoqtKnownTrackPublisher&) = delete; + MoqtKnownTrackPublisher(MoqtKnownTrackPublisher&&) = delete; + MoqtKnownTrackPublisher& operator=(const MoqtKnownTrackPublisher&) = delete; + MoqtKnownTrackPublisher& operator=(MoqtKnownTrackPublisher&&) = delete; + + absl::StatusOr> GetTrack( + const FullTrackName& track_name) override; + void Add(std::shared_ptr track_publisher); + + private: + absl::flat_hash_map> + tracks_; +}; + +} // namespace moqt + +#endif // QUICHE_QUIC_MOQT_MOQT_KNOWN_TRACK_PUBLISHER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.cc index fba312b196..277687f0d1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.cc @@ -10,6 +10,49 @@ namespace moqt { +MoqtObjectStatus IntegerToObjectStatus(uint64_t integer) { + if (integer >= 0x5) { + return MoqtObjectStatus::kInvalidObjectStatus; + } + return static_cast(integer); +} + +MoqtFilterType GetFilterType(const MoqtSubscribe& message) { + if (!message.end_group.has_value() && message.end_object.has_value()) { + return MoqtFilterType::kNone; + } + bool has_start = + message.start_group.has_value() && message.start_object.has_value(); + if (message.end_group.has_value()) { + if (has_start) { + if (*message.end_group < *message.start_group) { + return MoqtFilterType::kNone; + } else if (*message.end_group == *message.start_group && + *message.end_object <= *message.start_object) { + if (*message.end_object < *message.start_object) { + return MoqtFilterType::kNone; + } else if (*message.end_object == *message.start_object) { + return MoqtFilterType::kAbsoluteStart; + } + } + return MoqtFilterType::kAbsoluteRange; + } + } else { + if (has_start) { + return MoqtFilterType::kAbsoluteStart; + } else if (!message.start_group.has_value()) { + if (message.start_object.has_value()) { + if (message.start_object.value() == 0) { + return MoqtFilterType::kLatestGroup; + } + } else { + return MoqtFilterType::kLatestObject; + } + } + } + return MoqtFilterType::kNone; +} + std::string MoqtMessageTypeToString(const MoqtMessageType message_type) { switch (message_type) { case MoqtMessageType::kObjectStream: @@ -30,6 +73,14 @@ std::string MoqtMessageTypeToString(const MoqtMessageType message_type) { return "UNSUBSCRIBE"; case MoqtMessageType::kSubscribeDone: return "SUBSCRIBE_DONE"; + case MoqtMessageType::kSubscribeUpdate: + return "SUBSCRIBE_UPDATE"; + case MoqtMessageType::kAnnounceCancel: + return "ANNOUNCE_CANCEL"; + case MoqtMessageType::kTrackStatusRequest: + return "TRACK_STATUS_REQUEST"; + case MoqtMessageType::kTrackStatus: + return "TRACK_STATUS"; case MoqtMessageType::kAnnounce: return "ANNOUNCE"; case MoqtMessageType::kAnnounceOk: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h index eef04cc07c..9435e061f0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h @@ -14,10 +14,12 @@ #include #include +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" +#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/common/platform/api/quiche_export.h" namespace moqt { @@ -27,7 +29,7 @@ inline constexpr quic::ParsedQuicVersionVector GetMoqtSupportedQuicVersions() { } enum class MoqtVersion : uint64_t { - kDraft03 = 0xff000003, + kDraft05 = 0xff000005, kUnrecognizedVersionForTests = 0xfe0000ff, }; @@ -49,6 +51,7 @@ inline constexpr size_t kMaxMessageHeaderSize = 2048; enum class QUICHE_EXPORT MoqtMessageType : uint64_t { kObjectStream = 0x00, kObjectDatagram = 0x01, + kSubscribeUpdate = 0x02, kSubscribe = 0x03, kSubscribeOk = 0x04, kSubscribeError = 0x05, @@ -58,6 +61,9 @@ enum class QUICHE_EXPORT MoqtMessageType : uint64_t { kUnannounce = 0x09, kUnsubscribe = 0x0a, kSubscribeDone = 0x0b, + kAnnounceCancel = 0x0c, + kTrackStatusRequest = 0x0d, + kTrackStatus = 0x0e, kGoAway = 0x10, kClientSetup = 0x40, kServerSetup = 0x41, @@ -75,6 +81,13 @@ enum class QUICHE_EXPORT MoqtError : uint64_t { kGoawayTimeout = 0x10, }; +// Error codes used by MoQT to reset streams. +// TODO: update with spec-defined error codes once those are available, see +// . +inline constexpr uint64_t kResetCodeUnknown = 0x00; +inline constexpr uint64_t kResetCodeSubscriptionGone = 0x01; +inline constexpr uint64_t kResetCodeTimedOut = 0x02; + enum class QUICHE_EXPORT MoqtRole : uint64_t { kPublisher = 0x1, kSubscriber = 0x2, @@ -117,13 +130,19 @@ struct FullTrackName { (track_namespace == other.track_namespace && track_name < other.track_name); } - FullTrackName& operator=(FullTrackName other) { + FullTrackName& operator=(const FullTrackName& other) { track_namespace = other.track_namespace; track_name = other.track_name; return *this; } template friend H AbslHashValue(H h, const FullTrackName& m); + + template + friend void AbslStringify(Sink& sink, const FullTrackName& track_name) { + absl::Format(&sink, "(%s; %s)", track_name.track_namespace, + track_name.track_name); + } }; template @@ -146,13 +165,20 @@ struct FullSequence { return (group < other.group || (group == other.group && object <= other.object)); } + bool operator>(const FullSequence& other) const { return !(*this <= other); } FullSequence& operator=(FullSequence other) { group = other.group; object = other.object; return *this; } + FullSequence next() const { return FullSequence{group, object + 1}; } template friend H AbslHashValue(H h, const FullSequence& m); + + template + friend void AbslStringify(Sink& sink, const FullSequence& sequence) { + absl::Format(&sink, "(%d; %d)", sequence.group, sequence.object); + } }; template @@ -179,6 +205,17 @@ enum class QUICHE_EXPORT MoqtForwardingPreference : uint8_t { kDatagram = 0x3, }; +enum class QUICHE_EXPORT MoqtObjectStatus : uint64_t { + kNormal = 0x0, + kObjectDoesNotExist = 0x1, + kGroupDoesNotExist = 0x2, + kEndOfGroup = 0x3, + kEndOfTrack = 0x4, + kInvalidObjectStatus = 0x5, +}; + +MoqtObjectStatus IntegerToObjectStatus(uint64_t integer); + // The data contained in every Object message, although the message type // implies some of the values. |payload_length| has no value if the length // is unknown (because it runs to the end of the stream.) @@ -187,69 +224,52 @@ struct QUICHE_EXPORT MoqtObject { uint64_t track_alias; uint64_t group_id; uint64_t object_id; - uint64_t object_send_order; + MoqtPriority publisher_priority; + MoqtObjectStatus object_status; MoqtForwardingPreference forwarding_preference; std::optional payload_length; }; -enum class QUICHE_EXPORT MoqtSubscribeLocationMode : uint64_t { +enum class QUICHE_EXPORT MoqtFilterType : uint64_t { kNone = 0x0, - kAbsolute = 0x1, - kRelativePrevious = 0x2, - kRelativeNext = 0x3, + kLatestGroup = 0x1, + kLatestObject = 0x2, + kAbsoluteStart = 0x3, + kAbsoluteRange = 0x4, }; -// kNone: std::optional is nullopt. -// kAbsolute: absolute = true -// kRelativePrevious: absolute is false; relative_value is negative -// kRelativeNext: absolute is true; relative_value is positive -struct QUICHE_EXPORT MoqtSubscribeLocation { - MoqtSubscribeLocation(bool is_absolute, uint64_t abs) - : absolute(is_absolute), absolute_value(abs) {} - MoqtSubscribeLocation(bool is_absolute, int64_t rel) - : absolute(is_absolute), relative_value(rel) {} - bool absolute; - union { - uint64_t absolute_value; - int64_t relative_value; - }; - bool operator==(const MoqtSubscribeLocation& other) const { - return absolute == other.absolute && - ((absolute && absolute_value == other.absolute_value) || - (!absolute && relative_value == other.relative_value)); - } -}; - -inline MoqtSubscribeLocationMode GetModeForSubscribeLocation( - const std::optional& location) { - if (!location.has_value()) { - return MoqtSubscribeLocationMode::kNone; - } - if (location->absolute) { - return MoqtSubscribeLocationMode::kAbsolute; - } - return location->relative_value >= 0 - ? MoqtSubscribeLocationMode::kRelativeNext - : MoqtSubscribeLocationMode::kRelativePrevious; -} - struct QUICHE_EXPORT MoqtSubscribe { uint64_t subscribe_id; uint64_t track_alias; std::string track_namespace; std::string track_name; + MoqtPriority subscriber_priority; + std::optional group_order; + // The combinations of these that have values indicate the filter type. + // SG: Start Group; SO: Start Object; EG: End Group; EO: End Object; + // (none): KLatestObject + // SO: kLatestGroup (must be zero) + // SG, SO: kAbsoluteStart + // SG, SO, EG, EO: kAbsoluteRange + // SG, SO, EG: kAbsoluteRange (request whole last group) + // All other combinations are invalid. + std::optional start_group; + std::optional start_object; + std::optional end_group; + std::optional end_object; // If the mode is kNone, the these are std::nullopt. - std::optional start_group; - std::optional start_object; - std::optional end_group; - std::optional end_object; std::optional authorization_info; }; +// Deduce the filter type from the combination of group and object IDs. Returns +// kNone if the state of the subscribe is invalid. +MoqtFilterType GetFilterType(const MoqtSubscribe& message); + struct QUICHE_EXPORT MoqtSubscribeOk { uint64_t subscribe_id; // The message uses ms, but expires is in us. quic::QuicTimeDelta expires = quic::QuicTimeDelta::FromMilliseconds(0); + MoqtDeliveryOrder group_order; // If ContextExists on the wire is zero, largest_id has no value. std::optional largest_id; }; @@ -283,11 +303,21 @@ enum class QUICHE_EXPORT SubscribeDoneCode : uint64_t { struct QUICHE_EXPORT MoqtSubscribeDone { uint64_t subscribe_id; - uint64_t status_code; + SubscribeDoneCode status_code; std::string reason_phrase; std::optional final_id; }; +struct QUICHE_EXPORT MoqtSubscribeUpdate { + uint64_t subscribe_id; + uint64_t start_group; + uint64_t start_object; + std::optional end_group; + std::optional end_object; + MoqtPriority subscriber_priority; + std::optional authorization_info; +}; + struct QUICHE_EXPORT MoqtAnnounce { std::string track_namespace; std::optional authorization_info; @@ -307,6 +337,44 @@ struct QUICHE_EXPORT MoqtUnannounce { std::string track_namespace; }; +enum class QUICHE_EXPORT MoqtTrackStatusCode : uint64_t { + kInProgress = 0x0, + kDoesNotExist = 0x1, + kNotYetBegun = 0x2, + kFinished = 0x3, + kStatusNotAvailable = 0x4, +}; + +inline bool DoesTrackStatusImplyHavingData(MoqtTrackStatusCode code) { + switch (code) { + case MoqtTrackStatusCode::kInProgress: + case MoqtTrackStatusCode::kFinished: + return true; + case MoqtTrackStatusCode::kDoesNotExist: + case MoqtTrackStatusCode::kNotYetBegun: + case MoqtTrackStatusCode::kStatusNotAvailable: + return false; + } + return false; +} + +struct QUICHE_EXPORT MoqtTrackStatus { + std::string track_namespace; + std::string track_name; + MoqtTrackStatusCode status_code; + uint64_t last_group; + uint64_t last_object; +}; + +struct QUICHE_EXPORT MoqtAnnounceCancel { + std::string track_namespace; +}; + +struct QUICHE_EXPORT MoqtTrackStatusRequest { + std::string track_namespace; + std::string track_name; +}; + struct QUICHE_EXPORT MoqtGoAway { std::string new_session_uri; }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_outgoing_queue.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_outgoing_queue.cc index 84c2a85e58..35d1f9da7c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_outgoing_queue.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_outgoing_queue.cc @@ -4,15 +4,15 @@ #include "quiche/quic/moqt/moqt_outgoing_queue.h" -#include -#include +#include #include #include +#include -#include "absl/status/status.h" #include "absl/status/statusor.h" -#include "absl/strings/string_view.h" +#include "quiche/quic/moqt/moqt_cached_object.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_publisher.h" #include "quiche/quic/moqt/moqt_subscribe_windows.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_mem_slice.h" @@ -29,7 +29,7 @@ void MoqtOutgoingQueue::AddObject(quiche::QuicheMemSlice payload, bool key) { if (key) { if (!queue_.empty()) { - CloseStreamForGroup(current_group_id_); + AddRawObject(MoqtObjectStatus::kEndOfGroup, quiche::QuicheMemSlice()); } if (queue_.size() == kMaxQueuedGroups) { @@ -39,53 +39,72 @@ void MoqtOutgoingQueue::AddObject(quiche::QuicheMemSlice payload, bool key) { ++current_group_id_; } - absl::string_view payload_view = payload.AsStringView(); - uint64_t object_id = queue_.back().size(); - queue_.back().push_back(std::move(payload)); - PublishObject(current_group_id_, object_id, payload_view, - /*close_stream=*/false); + AddRawObject(MoqtObjectStatus::kNormal, std::move(payload)); } -absl::StatusOr -MoqtOutgoingQueue::OnSubscribeForPast(const SubscribeWindow& window) { - QUICHE_BUG_IF( - MoqtOutgoingQueue_requires_kGroup, - window.forwarding_preference() != MoqtForwardingPreference::kGroup) - << "MoqtOutgoingQueue currently only supports kGroup."; - if (window.HasEnd()) { - // TODO: support this (this would require changing the logic for closing the - // stream below). - return absl::UnimplementedError("SUBSCRIBEs with an end are not supported"); +void MoqtOutgoingQueue::AddRawObject(MoqtObjectStatus status, + quiche::QuicheMemSlice payload) { + FullSequence sequence{current_group_id_, queue_.back().size()}; + queue_.back().push_back(CachedObject{ + sequence, status, + std::make_shared(std::move(payload))}); + for (MoqtObjectListener* listener : listeners_) { + listener->OnNewObjectAvailable(sequence); } - return [this, &window]() { - for (size_t i = 0; i < queue_.size(); ++i) { - const uint64_t group_id = first_group_in_queue() + i; - const Group& group = queue_[i]; - const bool is_last_group = (i == queue_.size() - 1); - for (size_t j = 0; j < group.size(); ++j) { - const FullSequence sequence{group_id, j}; - if (!window.InWindow(sequence)) { - continue; - } - const bool is_last_object = (j == group.size() - 1); - const bool should_close_stream = !is_last_group && is_last_object; - PublishObject(group_id, j, group[j].AsStringView(), - should_close_stream); +} + +std::optional MoqtOutgoingQueue::GetCachedObject( + FullSequence sequence) const { + if (sequence.group < first_group_in_queue()) { + return PublishedObject{FullSequence{sequence.group, sequence.object}, + MoqtObjectStatus::kGroupDoesNotExist, + quiche::QuicheMemSlice()}; + } + if (sequence.group > current_group_id_) { + return std::nullopt; + } + const std::vector& group = + queue_[sequence.group - first_group_in_queue()]; + if (sequence.object >= group.size()) { + if (sequence.group == current_group_id_) { + return std::nullopt; + } + return PublishedObject{FullSequence{sequence.group, sequence.object}, + MoqtObjectStatus::kObjectDoesNotExist, + quiche::QuicheMemSlice()}; + } + QUICHE_DCHECK(sequence == group[sequence.object].sequence); + return CachedObjectToPublishedObject(group[sequence.object]); +} + +std::vector MoqtOutgoingQueue::GetCachedObjectsInRange( + FullSequence start, FullSequence end) const { + std::vector sequences; + SubscribeWindow window(start, end); + for (const Group& group : queue_) { + for (const CachedObject& object : group) { + if (window.InWindow(object.sequence)) { + sequences.push_back(object.sequence); } } - }; + } + return sequences; } -void MoqtOutgoingQueue::CloseStreamForGroup(uint64_t group_id) { - session_->CloseObjectStream(track_, group_id); +absl::StatusOr MoqtOutgoingQueue::GetTrackStatus() const { + if (queue_.empty()) { + return MoqtTrackStatusCode::kNotYetBegun; + } + return MoqtTrackStatusCode::kInProgress; } -void MoqtOutgoingQueue::PublishObject(uint64_t group_id, uint64_t object_id, - absl::string_view payload, - bool close_stream) { - session_->PublishObject(track_, group_id, object_id, - /*object_send_order=*/group_id, payload, - close_stream); +FullSequence MoqtOutgoingQueue::GetLargestSequence() const { + if (queue_.empty()) { + QUICHE_BUG(MoqtOutgoingQueue_GetLargestSequence_not_begun) + << "Calling GetLargestSequence() on a track that hasn't begun"; + return FullSequence{0, 0}; + } + return FullSequence{current_group_id_, queue_.back().size() - 1}; } } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_outgoing_queue.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_outgoing_queue.h index 0966b579b3..e3a7d3a56b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_outgoing_queue.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_outgoing_queue.h @@ -11,13 +11,14 @@ #include #include +#include "absl/container/flat_hash_set.h" #include "absl/container/inlined_vector.h" #include "absl/status/statusor.h" -#include "absl/strings/string_view.h" +#include "quiche/quic/moqt/moqt_cached_object.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_priority.h" +#include "quiche/quic/moqt/moqt_publisher.h" #include "quiche/quic/moqt/moqt_session.h" -#include "quiche/quic/moqt/moqt_subscribe_windows.h" -#include "quiche/quic/moqt/moqt_track.h" #include "quiche/common/platform/api/quiche_mem_slice.h" namespace moqt { @@ -27,15 +28,15 @@ namespace moqt { // groups, and maintain a buffer of three most recent groups that will be // provided to subscribers automatically. // -// This class is primarily meant to be used by publishers to buffer the frames -// that they produce. Limitations of this class: -// - It currently only works with the forwarding preference of kGroup. -// - It only supports a single session. -// - Everything is sent in order that it is queued. -class MoqtOutgoingQueue : public LocalTrack::Visitor { +// This class is primarily meant to be used by original publishers to buffer the +// frames that they produce. +class MoqtOutgoingQueue : public MoqtTrackPublisher { public: - explicit MoqtOutgoingQueue(MoqtSession* session, FullTrackName track) - : session_(session), track_(std::move(track)) {} + explicit MoqtOutgoingQueue(MoqtSession* session, FullTrackName track, + MoqtForwardingPreference forwarding_preference) + : session_(session), + track_(std::move(track)), + forwarding_preference_(forwarding_preference) {} MoqtOutgoingQueue(const MoqtOutgoingQueue&) = delete; MoqtOutgoingQueue(MoqtOutgoingQueue&&) = default; @@ -46,32 +47,53 @@ class MoqtOutgoingQueue : public LocalTrack::Visitor { // group is closed. The first object ever sent MUST have `key` set to true. void AddObject(quiche::QuicheMemSlice payload, bool key); - // LocalTrack::Visitor implementation. - absl::StatusOr OnSubscribeForPast( - const SubscribeWindow& window) override; + // MoqtTrackPublisher implementation. + const FullTrackName& GetTrackName() const override { return track_; } + std::optional GetCachedObject( + FullSequence sequence) const override; + std::vector GetCachedObjectsInRange( + FullSequence start, FullSequence end) const override; + void AddObjectListener(MoqtObjectListener* listener) override { + listeners_.insert(listener); + } + void RemoveObjectListener(MoqtObjectListener* listener) override { + listeners_.erase(listener); + } + absl::StatusOr GetTrackStatus() const override; + FullSequence GetLargestSequence() const override; + MoqtForwardingPreference GetForwardingPreference() const override { + return forwarding_preference_; + } + MoqtPriority GetPublisherPriority() const override { + return publisher_priority_; + } + MoqtDeliveryOrder GetDeliveryOrder() const override { + return delivery_order_; + } - protected: - // Interface to MoqtSession; can be mocked out for tests. - virtual void CloseStreamForGroup(uint64_t group_id); - virtual void PublishObject(uint64_t group_id, uint64_t object_id, - absl::string_view payload, bool close_stream); + bool HasSubscribers() const { return !listeners_.empty(); } private: // The number of recent groups to keep around for newly joined subscribers. static constexpr size_t kMaxQueuedGroups = 3; - using Object = quiche::QuicheMemSlice; - using Group = std::vector; + using Group = std::vector; + + void AddRawObject(MoqtObjectStatus status, quiche::QuicheMemSlice payload); // The number of the oldest group available. - uint64_t first_group_in_queue() { + uint64_t first_group_in_queue() const { return current_group_id_ - queue_.size() + 1; } MoqtSession* session_; // Not owned. FullTrackName track_; + MoqtForwardingPreference forwarding_preference_; + MoqtPriority publisher_priority_ = 128; + MoqtDeliveryOrder delivery_order_ = MoqtDeliveryOrder::kAscending; absl::InlinedVector queue_; uint64_t current_group_id_ = -1; + absl::flat_hash_set listeners_; }; } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.cc index 1e8cf8a23c..c9f2ed073b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.cc @@ -16,10 +16,32 @@ #include "quiche/quic/core/quic_data_reader.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/common/platform/api/quiche_logging.h" namespace moqt { +namespace { + +bool ParseDeliveryOrder(uint8_t raw_value, + std::optional& output) { + switch (raw_value) { + case 0x00: + output = std::nullopt; + return true; + case 0x01: + output = MoqtDeliveryOrder::kAscending; + return true; + case 0x02: + output = MoqtDeliveryOrder::kDescending; + return true; + default: + return false; + } +} + +} // namespace + // The buffering philosophy is complicated, to minimize copying. Here is an // overview: // If the entire message body is present (except for OBJECT payload), it is @@ -168,14 +190,22 @@ size_t MoqtParser::ProcessMessage(absl::string_view data, bool fin) { return ProcessUnsubscribe(reader); case MoqtMessageType::kSubscribeDone: return ProcessSubscribeDone(reader); + case MoqtMessageType::kSubscribeUpdate: + return ProcessSubscribeUpdate(reader); case MoqtMessageType::kAnnounce: return ProcessAnnounce(reader); case MoqtMessageType::kAnnounceOk: return ProcessAnnounceOk(reader); case MoqtMessageType::kAnnounceError: return ProcessAnnounceError(reader); + case MoqtMessageType::kAnnounceCancel: + return ProcessAnnounceCancel(reader); + case MoqtMessageType::kTrackStatusRequest: + return ProcessTrackStatusRequest(reader); case MoqtMessageType::kUnannounce: return ProcessUnannounce(reader); + case MoqtMessageType::kTrackStatus: + return ProcessTrackStatus(reader); case MoqtMessageType::kGoAway: return ProcessGoAway(reader); default: @@ -212,11 +242,33 @@ size_t MoqtParser::ProcessObject(quic::QuicDataReader& reader, return processed_data; } object_metadata_->payload_length = length; + uint64_t status = 0; // Defaults to kNormal. + if (length == 0 && !reader.ReadVarInt62(&status)) { + return processed_data; + } + object_metadata_->object_status = IntegerToObjectStatus(status); break; } default: break; } + if (object_metadata_->object_status == + MoqtObjectStatus::kInvalidObjectStatus) { + ParseError("Invalid object status"); + return processed_data; + } + if (object_metadata_->object_status != MoqtObjectStatus::kNormal) { + // It is impossible to express an explicit length with this status. + if ((type == MoqtMessageType::kObjectStream || + type == MoqtMessageType::kObjectDatagram) && + reader.BytesRemaining() > 0) { + // There is additional data in the stream/datagram, which is an error. + ParseError("Object with non-normal status has payload"); + return processed_data; + } + visitor_.OnObjectMessage(*object_metadata_, "", true); + return reader.PreviouslyReadPayload().length(); + } bool has_length = object_metadata_->payload_length.has_value(); bool received_complete_message = false; size_t payload_to_draw = reader.BytesRemaining(); @@ -370,34 +422,59 @@ size_t MoqtParser::ProcessServerSetup(quic::QuicDataReader& reader) { size_t MoqtParser::ProcessSubscribe(quic::QuicDataReader& reader) { MoqtSubscribe subscribe_request; + uint64_t filter, group, object; + uint8_t group_order; if (!reader.ReadVarInt62(&subscribe_request.subscribe_id) || !reader.ReadVarInt62(&subscribe_request.track_alias) || !reader.ReadStringVarInt62(subscribe_request.track_namespace) || !reader.ReadStringVarInt62(subscribe_request.track_name) || - !ReadLocation(reader, subscribe_request.start_group)) { + !reader.ReadUInt8(&subscribe_request.subscriber_priority) || + !reader.ReadUInt8(&group_order) || !reader.ReadVarInt62(&filter)) { return 0; } - if (!subscribe_request.start_group.has_value()) { - ParseError("START_GROUP must not be None in SUBSCRIBE"); + if (!ParseDeliveryOrder(group_order, subscribe_request.group_order)) { + ParseError("Invalid group order value in SUBSCRIBE message"); return 0; } - if (!ReadLocation(reader, subscribe_request.start_object)) { - return 0; - } - if (!subscribe_request.start_object.has_value()) { - ParseError("START_OBJECT must not be None in SUBSCRIBE"); - return 0; - } - if (!ReadLocation(reader, subscribe_request.end_group) || - !ReadLocation(reader, subscribe_request.end_object)) { - return 0; - } - if (subscribe_request.end_group.has_value() != - subscribe_request.end_object.has_value()) { - ParseError( - "SUBSCRIBE end_group and end_object must be both None " - "or both non_None"); - return 0; + MoqtFilterType filter_type = static_cast(filter); + switch (filter_type) { + case MoqtFilterType::kLatestGroup: + subscribe_request.start_object = 0; + break; + case MoqtFilterType::kLatestObject: + break; + case MoqtFilterType::kAbsoluteStart: + case MoqtFilterType::kAbsoluteRange: + if (!reader.ReadVarInt62(&group) || !reader.ReadVarInt62(&object)) { + return 0; + } + subscribe_request.start_group = group; + subscribe_request.start_object = object; + if (filter_type == MoqtFilterType::kAbsoluteStart) { + break; + } + if (!reader.ReadVarInt62(&group) || !reader.ReadVarInt62(&object)) { + return 0; + } + subscribe_request.end_group = group; + if (subscribe_request.end_group < subscribe_request.start_group) { + ParseError("End group is less than start group"); + return 0; + } + if (object == 0) { + subscribe_request.end_object = std::nullopt; + } else { + subscribe_request.end_object = object - 1; + if (subscribe_request.start_group == subscribe_request.end_group && + subscribe_request.end_object < subscribe_request.start_object) { + ParseError("End object comes before start object"); + return 0; + } + } + break; + default: + ParseError("Invalid filter type"); + return 0; } uint64_t num_params; if (!reader.ReadVarInt62(&num_params)) { @@ -415,7 +492,7 @@ size_t MoqtParser::ProcessSubscribe(quic::QuicDataReader& reader) { if (subscribe_request.authorization_info.has_value()) { ParseError( "AUTHORIZATION_INFO parameter appears twice in " - "SUBSCRIBE_REQUEST"); + "SUBSCRIBE"); return 0; } subscribe_request.authorization_info = value; @@ -432,9 +509,10 @@ size_t MoqtParser::ProcessSubscribe(quic::QuicDataReader& reader) { size_t MoqtParser::ProcessSubscribeOk(quic::QuicDataReader& reader) { MoqtSubscribeOk subscribe_ok; uint64_t milliseconds; + uint8_t group_order; uint8_t content_exists; if (!reader.ReadVarInt62(&subscribe_ok.subscribe_id) || - !reader.ReadVarInt62(&milliseconds) || + !reader.ReadVarInt62(&milliseconds) || !reader.ReadUInt8(&group_order) || !reader.ReadUInt8(&content_exists)) { return 0; } @@ -442,7 +520,12 @@ size_t MoqtParser::ProcessSubscribeOk(quic::QuicDataReader& reader) { ParseError("SUBSCRIBE_OK ContentExists has invalid value"); return 0; } + if (group_order != 0x01 && group_order != 0x02) { + ParseError("Invalid group order value in SUBSCRIBE_OK"); + return 0; + } subscribe_ok.expires = quic::QuicTimeDelta::FromMilliseconds(milliseconds); + subscribe_ok.group_order = static_cast(group_order); if (content_exists) { subscribe_ok.largest_id = FullSequence(); if (!reader.ReadVarInt62(&subscribe_ok.largest_id->group) || @@ -480,12 +563,14 @@ size_t MoqtParser::ProcessUnsubscribe(quic::QuicDataReader& reader) { size_t MoqtParser::ProcessSubscribeDone(quic::QuicDataReader& reader) { MoqtSubscribeDone subscribe_done; uint8_t content_exists; + uint64_t value; if (!reader.ReadVarInt62(&subscribe_done.subscribe_id) || - !reader.ReadVarInt62(&subscribe_done.status_code) || + !reader.ReadVarInt62(&value) || !reader.ReadStringVarInt62(subscribe_done.reason_phrase) || !reader.ReadUInt8(&content_exists)) { return 0; } + subscribe_done.status_code = static_cast(value); if (content_exists > 1) { ParseError("SUBSCRIBE_DONE ContentExists has invalid value"); return 0; @@ -501,6 +586,67 @@ size_t MoqtParser::ProcessSubscribeDone(quic::QuicDataReader& reader) { return reader.PreviouslyReadPayload().length(); } +size_t MoqtParser::ProcessSubscribeUpdate(quic::QuicDataReader& reader) { + MoqtSubscribeUpdate subscribe_update; + uint64_t end_group, end_object, num_params; + if (!reader.ReadVarInt62(&subscribe_update.subscribe_id) || + !reader.ReadVarInt62(&subscribe_update.start_group) || + !reader.ReadVarInt62(&subscribe_update.start_object) || + !reader.ReadVarInt62(&end_group) || !reader.ReadVarInt62(&end_object) || + !reader.ReadUInt8(&subscribe_update.subscriber_priority) || + !reader.ReadVarInt62(&num_params)) { + return 0; + } + if (end_group == 0) { + // end_group remains nullopt. + if (end_object > 0) { + ParseError("SUBSCRIBE_UPDATE has end_object but no end_group"); + return 0; + } + } else { + subscribe_update.end_group = end_group - 1; + if (subscribe_update.end_group < subscribe_update.start_group) { + ParseError("End group is less than start group"); + return 0; + } + } + if (end_object > 0) { + subscribe_update.end_object = end_object - 1; + if (subscribe_update.end_object.has_value() && + subscribe_update.start_group == *subscribe_update.end_group && + *subscribe_update.end_object < subscribe_update.start_object) { + ParseError("End object comes before start object"); + return 0; + } + } else { + subscribe_update.end_object = std::nullopt; + } + for (uint64_t i = 0; i < num_params; ++i) { + uint64_t type; + absl::string_view value; + if (!ReadParameter(reader, type, value)) { + return 0; + } + auto key = static_cast(type); + switch (key) { + case MoqtTrackRequestParameter::kAuthorizationInfo: + if (subscribe_update.authorization_info.has_value()) { + ParseError( + "AUTHORIZATION_INFO parameter appears twice in " + "SUBSCRIBE_UPDATE"); + return 0; + } + subscribe_update.authorization_info = value; + break; + default: + // Skip over the parameter. + break; + } + } + visitor_.OnSubscribeUpdateMessage(subscribe_update); + return reader.PreviouslyReadPayload().length(); +} + size_t MoqtParser::ProcessAnnounce(quic::QuicDataReader& reader) { MoqtAnnounce announce; if (!reader.ReadStringVarInt62(announce.track_namespace)) { @@ -560,6 +706,27 @@ size_t MoqtParser::ProcessAnnounceError(quic::QuicDataReader& reader) { return reader.PreviouslyReadPayload().length(); } +size_t MoqtParser::ProcessAnnounceCancel(quic::QuicDataReader& reader) { + MoqtAnnounceCancel announce_cancel; + if (!reader.ReadStringVarInt62(announce_cancel.track_namespace)) { + return 0; + } + visitor_.OnAnnounceCancelMessage(announce_cancel); + return reader.PreviouslyReadPayload().length(); +} + +size_t MoqtParser::ProcessTrackStatusRequest(quic::QuicDataReader& reader) { + MoqtTrackStatusRequest track_status_request; + if (!reader.ReadStringVarInt62(track_status_request.track_namespace)) { + return 0; + } + if (!reader.ReadStringVarInt62(track_status_request.track_name)) { + return 0; + } + visitor_.OnTrackStatusRequestMessage(track_status_request); + return reader.PreviouslyReadPayload().length(); +} + size_t MoqtParser::ProcessUnannounce(quic::QuicDataReader& reader) { MoqtUnannounce unannounce; if (!reader.ReadStringVarInt62(unannounce.track_namespace)) { @@ -569,6 +736,21 @@ size_t MoqtParser::ProcessUnannounce(quic::QuicDataReader& reader) { return reader.PreviouslyReadPayload().length(); } +size_t MoqtParser::ProcessTrackStatus(quic::QuicDataReader& reader) { + MoqtTrackStatus track_status; + uint64_t value; + if (!reader.ReadStringVarInt62(track_status.track_namespace) || + !reader.ReadStringVarInt62(track_status.track_name) || + !reader.ReadVarInt62(&value) || + !reader.ReadVarInt62(&track_status.last_group) || + !reader.ReadVarInt62(&track_status.last_object)) { + return 0; + } + track_status.status_code = static_cast(value); + visitor_.OnTrackStatusMessage(track_status); + return reader.PreviouslyReadPayload().length(); +} + size_t MoqtParser::ProcessGoAway(quic::QuicDataReader& reader) { MoqtGoAway goaway; if (!reader.ReadStringVarInt62(goaway.new_session_uri)) { @@ -594,9 +776,16 @@ size_t MoqtParser::ParseObjectHeader(quic::QuicDataReader& reader, !reader.ReadVarInt62(&object.object_id)) { return 0; } - if (!reader.ReadVarInt62(&object.object_send_order)) { + if (!reader.ReadUInt8(&object.publisher_priority)) { return 0; } + uint64_t status = 0; // Defaults to kNormal. + if ((type == MoqtMessageType::kObjectStream || + type == MoqtMessageType::kObjectDatagram) && + !reader.ReadVarInt62(&status)) { + return 0; + } + object.object_status = IntegerToObjectStatus(status); object.forwarding_preference = GetForwardingPreference(type); return reader.PreviouslyReadPayload().length(); } @@ -631,37 +820,6 @@ bool MoqtParser::ReadVarIntPieceVarInt62(quic::QuicDataReader& reader, return true; } -bool MoqtParser::ReadLocation(quic::QuicDataReader& reader, - std::optional& loc) { - uint64_t ui64; - if (!reader.ReadVarInt62(&ui64)) { - return false; - } - auto mode = static_cast(ui64); - if (mode == MoqtSubscribeLocationMode::kNone) { - loc = std::nullopt; - return true; - } - if (!reader.ReadVarInt62(&ui64)) { - return false; - } - switch (mode) { - case MoqtSubscribeLocationMode::kAbsolute: - loc = MoqtSubscribeLocation(true, ui64); - break; - case MoqtSubscribeLocationMode::kRelativePrevious: - loc = MoqtSubscribeLocation(false, -1 * static_cast(ui64)); - break; - case MoqtSubscribeLocationMode::kRelativeNext: - loc = MoqtSubscribeLocation(false, static_cast(ui64) + 1); - break; - default: - ParseError("Unknown location mode"); - return false; - } - return true; -} - bool MoqtParser::ReadParameter(quic::QuicDataReader& reader, uint64_t& type, absl::string_view& value) { if (!reader.ReadVarInt62(&type)) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.h index 084e6fe939..bada6cd3c2 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.h @@ -39,10 +39,15 @@ class QUICHE_EXPORT MoqtParserVisitor { virtual void OnSubscribeErrorMessage(const MoqtSubscribeError& message) = 0; virtual void OnUnsubscribeMessage(const MoqtUnsubscribe& message) = 0; virtual void OnSubscribeDoneMessage(const MoqtSubscribeDone& message) = 0; + virtual void OnSubscribeUpdateMessage(const MoqtSubscribeUpdate& message) = 0; virtual void OnAnnounceMessage(const MoqtAnnounce& message) = 0; virtual void OnAnnounceOkMessage(const MoqtAnnounceOk& message) = 0; virtual void OnAnnounceErrorMessage(const MoqtAnnounceError& message) = 0; + virtual void OnAnnounceCancelMessage(const MoqtAnnounceCancel& message) = 0; + virtual void OnTrackStatusRequestMessage( + const MoqtTrackStatusRequest& message) = 0; virtual void OnUnannounceMessage(const MoqtUnannounce& message) = 0; + virtual void OnTrackStatusMessage(const MoqtTrackStatus& message) = 0; virtual void OnGoAwayMessage(const MoqtGoAway& message) = 0; virtual void OnParsingError(MoqtError code, absl::string_view reason) = 0; @@ -90,10 +95,14 @@ class QUICHE_EXPORT MoqtParser { size_t ProcessSubscribeError(quic::QuicDataReader& reader); size_t ProcessUnsubscribe(quic::QuicDataReader& reader); size_t ProcessSubscribeDone(quic::QuicDataReader& reader); + size_t ProcessSubscribeUpdate(quic::QuicDataReader& reader); size_t ProcessAnnounce(quic::QuicDataReader& reader); size_t ProcessAnnounceOk(quic::QuicDataReader& reader); size_t ProcessAnnounceError(quic::QuicDataReader& reader); + size_t ProcessAnnounceCancel(quic::QuicDataReader& reader); + size_t ProcessTrackStatusRequest(quic::QuicDataReader& reader); size_t ProcessUnannounce(quic::QuicDataReader& reader); + size_t ProcessTrackStatus(quic::QuicDataReader& reader); size_t ProcessGoAway(quic::QuicDataReader& reader); static size_t ParseObjectHeader(quic::QuicDataReader& reader, @@ -106,9 +115,6 @@ class QUICHE_EXPORT MoqtParser { // Reads an integer whose length is specified by a preceding VarInt62 and // returns it in |result|. Returns false if parsing fails. bool ReadVarIntPieceVarInt62(quic::QuicDataReader& reader, uint64_t& result); - // Read a Location field from SUBSCRIBE REQUEST - bool ReadLocation(quic::QuicDataReader& reader, - std::optional& loc); // Read a parameter and return the value as a string_view. Returns false if // |reader| does not have enough data. bool ReadParameter(quic::QuicDataReader& reader, uint64_t& type, @@ -125,6 +131,7 @@ class QUICHE_EXPORT MoqtParser { // for the most recent object. bool ObjectPayloadInProgress() const { return (object_metadata_.has_value() && + object_metadata_->object_status == MoqtObjectStatus::kNormal && (object_metadata_->forwarding_preference == MoqtForwardingPreference::kObject || object_metadata_->forwarding_preference == diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_priority.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_priority.cc new file mode 100644 index 0000000000..5528079d9d --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_priority.cc @@ -0,0 +1,70 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "quiche/quic/moqt/moqt_priority.h" + +#include +#include + +#include "quiche/web_transport/web_transport.h" + +namespace moqt { + +namespace { +template +constexpr uint64_t Flip(uint64_t number) { + static_assert(NumBits <= 63); + return (1ull << NumBits) - 1 - number; +} +template +constexpr uint64_t OnlyLowestNBits(uint64_t value) { + static_assert(N <= 62); + return value & ((1ull << (N + 1)) - 1); +} +} // namespace + +// The send order is packed into a signed 64-bit integer as follows: +// 63: always zero to indicate a positive number +// 62: 0 for data streams, 1 for control streams +// 54-61: subscriber priority +// 46-53: publisher priority +// (if stream-per-group) +// 0-45: group ID +// (if stream-per-object) +// 20-45: group ID +// 0-19: object ID + +webtransport::SendOrder SendOrderForStream(MoqtPriority subscriber_priority, + MoqtPriority publisher_priority, + uint64_t group_id, + MoqtDeliveryOrder delivery_order) { + const int64_t track_bits = (Flip<8>(subscriber_priority) << 54) | + (Flip<8>(publisher_priority) << 46); + group_id = OnlyLowestNBits<46>(group_id); + if (delivery_order == MoqtDeliveryOrder::kAscending) { + group_id = Flip<46>(group_id); + } + return track_bits | group_id; +} + +webtransport::SendOrder SendOrderForStream(MoqtPriority subscriber_priority, + MoqtPriority publisher_priority, + uint64_t group_id, + uint64_t object_id, + MoqtDeliveryOrder delivery_order) { + const int64_t track_bits = (Flip<8>(subscriber_priority) << 54) | + (Flip<8>(publisher_priority) << 46); + group_id = OnlyLowestNBits<26>(group_id); + object_id = OnlyLowestNBits<20>(object_id); + if (delivery_order == MoqtDeliveryOrder::kAscending) { + group_id = Flip<26>(group_id); + } + object_id = Flip<20>(object_id); // Object ID is always ascending. + return track_bits | (group_id << 20) | object_id; +} + +const webtransport::SendOrder kMoqtControlStreamSendOrder = + std::numeric_limits::max(); + +} // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_priority.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_priority.h new file mode 100644 index 0000000000..85449d9e59 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_priority.h @@ -0,0 +1,40 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_QUIC_MOQT_MOQT_PRIORITY_H_ +#define QUICHE_QUIC_MOQT_MOQT_PRIORITY_H_ + +#include + +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/web_transport/web_transport.h" + +namespace moqt { + +// Priority that can be assigned to a track or individual streams associated +// with the track by either the publisher or the subscriber. +using MoqtPriority = uint8_t; + +// Indicates the desired order of delivering groups associated with a given +// track. +enum class MoqtDeliveryOrder : uint8_t { + kAscending = 0x01, + kDescending = 0x02, +}; + +// Computes WebTransport send order for an MoQT data stream with the specified +// parameters. +QUICHE_EXPORT webtransport::SendOrder SendOrderForStream( + MoqtPriority subscriber_priority, MoqtPriority publisher_priority, + uint64_t group_id, MoqtDeliveryOrder delivery_order); +QUICHE_EXPORT webtransport::SendOrder SendOrderForStream( + MoqtPriority subscriber_priority, MoqtPriority publisher_priority, + uint64_t group_id, uint64_t object_id, MoqtDeliveryOrder delivery_order); + +// WebTransport send order set on the MoQT control stream. +QUICHE_EXPORT extern const webtransport::SendOrder kMoqtControlStreamSendOrder; + +} // namespace moqt + +#endif // QUICHE_QUIC_MOQT_MOQT_PRIORITY_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_publisher.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_publisher.h new file mode 100644 index 0000000000..778236c877 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_publisher.h @@ -0,0 +1,114 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_QUIC_MOQT_MOQT_PUBLISHER_H_ +#define QUICHE_QUIC_MOQT_MOQT_PUBLISHER_H_ + +#include +#include +#include + +#include "absl/status/statusor.h" +#include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_priority.h" +#include "quiche/common/platform/api/quiche_mem_slice.h" + +namespace moqt { + +// PublishedObject is a description of an object that is sufficient to publish +// it on a given track. +struct PublishedObject { + FullSequence sequence; + MoqtObjectStatus status; + quiche::QuicheMemSlice payload; +}; + +// MoqtObjectListener is an interface for any entity that is listening for +// incoming objects for a given track. +class MoqtObjectListener { + public: + virtual ~MoqtObjectListener() = default; + + // Notifies that an object with the given sequence number has become + // available. The object payload itself may be retrieved via GetCachedObject + // method of the associated track publisher. + virtual void OnNewObjectAvailable(FullSequence sequence) = 0; +}; + +// MoqtTrackPublisher is an application-side API for an MoQT publisher +// of a single individual track. +class MoqtTrackPublisher { + public: + virtual ~MoqtTrackPublisher() = default; + + // Returns the full name of the associated track. + virtual const FullTrackName& GetTrackName() const = 0; + + // GetCachedObject lets the MoQT stack access the objects that are available + // in the track's built-in local cache. + // + // This implementation of MoQT does not store any objects within the MoQT + // stack itself, at least until the object is fully serialized and passed to + // the QUIC stack. Instead, it relies on individual tracks having a shared + // cache for recent objects, and objects are always pulled from that cache + // whenever they are sent. Once an object is not available via the cache, it + // can no longer be sent; this ensures that objects are not buffered forever. + // + // This method returns nullopt if the object is not currently available, but + // might become available in the future. If the object is gone forever, + // kGroupDoesNotExist/kObjectDoesNotExist has to be returned instead; + // otherwise, the corresponding QUIC streams will be stuck waiting for objects + // that will never arrive. + virtual std::optional GetCachedObject( + FullSequence sequence) const = 0; + + // Returns a full list of objects available in the cache, to be used for + // SUBSCRIBEs with a backfill. + virtual std::vector GetCachedObjectsInRange( + FullSequence start, FullSequence end) const = 0; + + // TODO: add an API to fetch past objects that are out of cache and might + // require an upstream request to fill the relevant cache again. This is + // currently done since the specification does not clearly describe how this + // is supposed to be done, especially with respect to such things as + // backpressure. + + // Registers a listener with the track. The listener will be notified of all + // newly arriving objects. The pointer to the listener must be valid until + // removed. + virtual void AddObjectListener(MoqtObjectListener* listener) = 0; + virtual void RemoveObjectListener(MoqtObjectListener* listener) = 0; + + virtual absl::StatusOr GetTrackStatus() const = 0; + + // Returns the largest sequence pair that has been published so far. + // This method may only be called if + // DoesTrackStatusImplyHavingData(GetTrackStatus()) is true. + virtual FullSequence GetLargestSequence() const = 0; + + // Returns the forwarding preference of the track. + // This method may only be called if + // DoesTrackStatusImplyHavingData(GetTrackStatus()) is true. + virtual MoqtForwardingPreference GetForwardingPreference() const = 0; + + // Returns the current forwarding priority of the track. + virtual MoqtPriority GetPublisherPriority() const = 0; + + // Returns the publisher-preferred delivery order for the track. + virtual MoqtDeliveryOrder GetDeliveryOrder() const = 0; +}; + +// MoqtPublisher is an interface to a publisher that allows it to publish +// multiple tracks. +class MoqtPublisher { + public: + virtual ~MoqtPublisher() = default; + + virtual absl::StatusOr> GetTrack( + const FullTrackName& track_name) = 0; +}; + +} // namespace moqt + +#endif // QUICHE_QUIC_MOQT_MOQT_PUBLISHER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.cc index 8781b269ca..bde00555c6 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.cc @@ -4,6 +4,7 @@ #include "quiche/quic/moqt/moqt_session.h" +#include #include #include #include @@ -14,21 +15,28 @@ #include "absl/algorithm/container.h" +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" +#include "absl/container/node_hash_map.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/span.h" #include "quiche/quic/core/quic_types.h" +#include "quiche/quic/moqt/moqt_framer.h" #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/quic/moqt/moqt_parser.h" +#include "quiche/quic/moqt/moqt_priority.h" +#include "quiche/quic/moqt/moqt_publisher.h" #include "quiche/quic/moqt/moqt_subscribe_windows.h" #include "quiche/quic/moqt/moqt_track.h" -#include "quiche/quic/platform/api/quic_bug_tracker.h" +#include "quiche/quic/platform/api/quic_logging.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_buffer_allocator.h" #include "quiche/common/quiche_stream.h" +#include "quiche/common/simple_buffer_allocator.h" #include "quiche/web_transport/web_transport.h" #define ENDPOINT \ @@ -36,9 +44,63 @@ namespace moqt { +namespace { + using ::quic::Perspective; -MoqtSession::Stream* MoqtSession::GetControlStream() { +constexpr MoqtPriority kDefaultSubscriberPriority = 0x80; + +bool PublisherHasData(const MoqtTrackPublisher& publisher) { + absl::StatusOr status = publisher.GetTrackStatus(); + return status.ok() && DoesTrackStatusImplyHavingData(*status); +} + +SubscribeWindow SubscribeMessageToWindow(const MoqtSubscribe& subscribe, + MoqtTrackPublisher& publisher) { + const FullSequence sequence = PublisherHasData(publisher) + ? publisher.GetLargestSequence() + : FullSequence{0, 0}; + switch (GetFilterType(subscribe)) { + case MoqtFilterType::kLatestGroup: + return SubscribeWindow(sequence.group, 0); + case MoqtFilterType::kLatestObject: + return SubscribeWindow(sequence.group, sequence.object); + case MoqtFilterType::kAbsoluteStart: + return SubscribeWindow(*subscribe.start_group, *subscribe.start_object); + case MoqtFilterType::kAbsoluteRange: + return SubscribeWindow(*subscribe.start_group, *subscribe.start_object, + *subscribe.end_group, *subscribe.end_object); + case MoqtFilterType::kNone: + QUICHE_BUG(MoqtSession_Subscription_invalid_filter_passed); + return SubscribeWindow(0, 0); + } +} + +class DefaultPublisher : public MoqtPublisher { + public: + static DefaultPublisher* GetInstance() { + static DefaultPublisher* instance = new DefaultPublisher(); + return instance; + } + + absl::StatusOr> GetTrack( + const FullTrackName& track_name) override { + return absl::NotFoundError("No tracks published"); + } +}; +} // namespace + +MoqtSession::MoqtSession(webtransport::Session* session, + MoqtSessionParameters parameters, + MoqtSessionCallbacks callbacks) + : session_(session), + parameters_(parameters), + callbacks_(std::move(callbacks)), + framer_(quiche::SimpleBufferAllocator::Get(), parameters.using_webtrans), + publisher_(DefaultPublisher::GetInstance()), + liveness_token_(std::make_shared()) {} + +MoqtSession::ControlStream* MoqtSession::GetControlStream() { if (!control_stream_.has_value()) { return nullptr; } @@ -46,11 +108,11 @@ MoqtSession::Stream* MoqtSession::GetControlStream() { if (raw_stream == nullptr) { return nullptr; } - return static_cast(raw_stream->visitor()); + return static_cast(raw_stream->visitor()); } void MoqtSession::SendControlMessage(quiche::QuicheBuffer message) { - Stream* control_stream = GetControlStream(); + ControlStream* control_stream = GetControlStream(); if (control_stream == nullptr) { QUICHE_LOG(DFATAL) << "Trying to send a message on the control stream " "while it does not exist"; @@ -71,8 +133,8 @@ void MoqtSession::OnSessionReady() { Error(MoqtError::kInternalError, "Unable to open a control stream"); return; } - control_stream->SetVisitor(std::make_unique( - this, control_stream, /*is_control_stream=*/true)); + control_stream->SetVisitor( + std::make_unique(this, control_stream)); control_stream_ = control_stream->GetStreamId(); MoqtClientSetup setup = MoqtClientSetup{ .supported_versions = std::vector{parameters_.version}, @@ -104,14 +166,14 @@ void MoqtSession::OnIncomingBidirectionalStreamAvailable() { Error(MoqtError::kProtocolViolation, "Bidirectional stream already open"); return; } - stream->SetVisitor(std::make_unique(this, stream)); + stream->SetVisitor(std::make_unique(this, stream)); stream->visitor()->OnCanRead(); } } void MoqtSession::OnIncomingUnidirectionalStreamAvailable() { while (webtransport::Stream* stream = session_->AcceptIncomingUnidirectionalStream()) { - stream->SetVisitor(std::make_unique(this, stream)); + stream->SetVisitor(std::make_unique(this, stream)); stream->visitor()->OnCanRead(); } } @@ -128,12 +190,13 @@ void MoqtSession::OnDatagramReceived(absl::string_view datagram) { << message.subscribe_id << " for track alias " << message.track_alias << " with sequence " << message.group_id << ":" << message.object_id - << " send_order " << message.object_send_order << " length " + << " priority " << message.publisher_priority << " length " << payload.size(); auto [full_track_name, visitor] = TrackPropertiesFromAlias(message); if (visitor != nullptr) { visitor->OnObjectFragment(full_track_name, message.group_id, - message.object_id, message.object_send_order, + message.object_id, message.publisher_priority, + message.object_status, message.forwarding_preference, payload, true); } } @@ -150,13 +213,6 @@ void MoqtSession::Error(MoqtError code, absl::string_view error) { std::move(callbacks_.session_terminated_callback)(error); } -void MoqtSession::AddLocalTrack(const FullTrackName& full_track_name, - MoqtForwardingPreference forwarding_preference, - LocalTrack::Visitor* visitor) { - local_tracks_.try_emplace(full_track_name, full_track_name, - forwarding_preference, visitor); -} - // TODO: Create state that allows ANNOUNCE_OK/ERROR on spurious namespaces to // trigger session errors. void MoqtSession::Announce(absl::string_view track_namespace, @@ -184,11 +240,6 @@ void MoqtSession::Announce(absl::string_view track_namespace, pending_outgoing_announces_[track_namespace] = std::move(announce_callback); } -bool MoqtSession::HasSubscribers(const FullTrackName& full_track_name) const { - auto it = local_tracks_.find(full_track_name); - return (it != local_tracks_.end() && it->second.HasSubscriber()); -} - bool MoqtSession::SubscribeAbsolute(absl::string_view track_namespace, absl::string_view name, uint64_t start_group, uint64_t start_object, @@ -197,8 +248,10 @@ bool MoqtSession::SubscribeAbsolute(absl::string_view track_namespace, MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; - message.start_group = MoqtSubscribeLocation(true, start_group); - message.start_object = MoqtSubscribeLocation(true, start_object); + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; + message.start_group = start_group; + message.start_object = start_object; message.end_group = std::nullopt; message.end_object = std::nullopt; if (!auth_info.empty()) { @@ -207,6 +260,31 @@ bool MoqtSession::SubscribeAbsolute(absl::string_view track_namespace, return Subscribe(message, visitor); } +bool MoqtSession::SubscribeAbsolute(absl::string_view track_namespace, + absl::string_view name, + uint64_t start_group, uint64_t start_object, + uint64_t end_group, + RemoteTrack::Visitor* visitor, + absl::string_view auth_info) { + if (end_group < start_group) { + QUIC_DLOG(ERROR) << "Subscription end is before beginning"; + return false; + } + MoqtSubscribe message; + message.track_namespace = track_namespace; + message.track_name = name; + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; + message.start_group = start_group; + message.start_object = start_object; + message.end_group = end_group; + message.end_object = std::nullopt; + if (!auth_info.empty()) { + message.authorization_info = std::move(auth_info); + } + return Subscribe(message, visitor); +} + bool MoqtSession::SubscribeAbsolute(absl::string_view track_namespace, absl::string_view name, uint64_t start_group, uint64_t start_object, @@ -224,26 +302,29 @@ bool MoqtSession::SubscribeAbsolute(absl::string_view track_namespace, MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; - message.start_group = MoqtSubscribeLocation(true, start_group); - message.start_object = MoqtSubscribeLocation(true, start_object); - message.end_group = MoqtSubscribeLocation(true, end_group); - message.end_object = MoqtSubscribeLocation(true, end_object); + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; + message.start_group = start_group; + message.start_object = start_object; + message.end_group = end_group; + message.end_object = end_object; if (!auth_info.empty()) { message.authorization_info = std::move(auth_info); } return Subscribe(message, visitor); } -bool MoqtSession::SubscribeRelative(absl::string_view track_namespace, - absl::string_view name, int64_t start_group, - int64_t start_object, - RemoteTrack::Visitor* visitor, - absl::string_view auth_info) { +bool MoqtSession::SubscribeCurrentObject(absl::string_view track_namespace, + absl::string_view name, + RemoteTrack::Visitor* visitor, + absl::string_view auth_info) { MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; - message.start_group = MoqtSubscribeLocation(false, start_group); - message.start_object = MoqtSubscribeLocation(false, start_object); + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; + message.start_group = std::nullopt; + message.start_object = std::nullopt; message.end_group = std::nullopt; message.end_object = std::nullopt; if (!auth_info.empty()) { @@ -259,9 +340,11 @@ bool MoqtSession::SubscribeCurrentGroup(absl::string_view track_namespace, MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; + message.subscriber_priority = kDefaultSubscriberPriority; + message.group_order = std::nullopt; // First object of current group. - message.start_group = MoqtSubscribeLocation(false, (uint64_t)0); - message.start_object = MoqtSubscribeLocation(true, (int64_t)0); + message.start_group = std::nullopt; + message.start_object = 0; message.end_group = std::nullopt; message.end_object = std::nullopt; if (!auth_info.empty()) { @@ -270,6 +353,37 @@ bool MoqtSession::SubscribeCurrentGroup(absl::string_view track_namespace, return Subscribe(message, visitor); } +bool MoqtSession::SubscribeIsDone(uint64_t subscribe_id, SubscribeDoneCode code, + absl::string_view reason_phrase) { + auto it = published_subscriptions_.find(subscribe_id); + if (it == published_subscriptions_.end()) { + return false; + } + + PublishedSubscription& subscription = *it->second; + std::vector streams_to_reset = + subscription.GetAllStreams(); + + MoqtSubscribeDone subscribe_done; + subscribe_done.subscribe_id = subscribe_id; + subscribe_done.status_code = code; + subscribe_done.reason_phrase = reason_phrase; + subscribe_done.final_id = subscription.largest_sent(); + SendControlMessage(framer_.SerializeSubscribeDone(subscribe_done)); + QUIC_DLOG(INFO) << ENDPOINT << "Sent SUBSCRIBE_DONE message for " + << subscribe_id; + // Clean up the subscription + published_subscriptions_.erase(it); + for (webtransport::StreamId stream_id : streams_to_reset) { + webtransport::Stream* stream = session_->GetStreamById(stream_id); + if (stream == nullptr) { + continue; + } + stream->ResetWithUserCode(kResetCodeSubscriptionGone); + } + return true; +} + bool MoqtSession::Subscribe(MoqtSubscribe& message, RemoteTrack::Visitor* visitor) { if (peer_role_ == MoqtRole::kSubscriber) { @@ -296,17 +410,51 @@ bool MoqtSession::Subscribe(MoqtSubscribe& message, return true; } -std::optional MoqtSession::OpenUnidirectionalStream() { +webtransport::Stream* MoqtSession::OpenOrQueueDataStream( + uint64_t subscription_id, FullSequence first_object) { if (!session_->CanOpenNextOutgoingUnidirectionalStream()) { - return std::nullopt; + queued_outgoing_data_streams_.push_back( + QueuedOutgoingDataStream{subscription_id, first_object}); + // TODO: limit the number of streams in the queue. + return nullptr; } + return OpenDataStream(subscription_id, first_object); +} + +webtransport::Stream* MoqtSession::OpenDataStream(uint64_t subscription_id, + FullSequence first_object) { + auto it = published_subscriptions_.find(subscription_id); + if (it == published_subscriptions_.end()) { + // It is possible that the subscription has been discarded while the stream + // was in the queue; discard those streams. + return nullptr; + } + PublishedSubscription& subscription = *it->second; + webtransport::Stream* new_stream = session_->OpenOutgoingUnidirectionalStream(); if (new_stream == nullptr) { - return std::nullopt; + QUICHE_BUG(MoqtSession_OpenDataStream_blocked) + << "OpenDataStream called when creation of new streams is blocked."; + return nullptr; + } + new_stream->SetVisitor(std::make_unique( + this, new_stream, subscription_id, first_object)); + subscription.OnDataStreamCreated(new_stream->GetStreamId(), first_object); + return new_stream; +} + +void MoqtSession::OnCanCreateNewOutgoingUnidirectionalStream() { + while (!queued_outgoing_data_streams_.empty() && + session_->CanOpenNextOutgoingUnidirectionalStream()) { + QueuedOutgoingDataStream next = queued_outgoing_data_streams_.front(); + queued_outgoing_data_streams_.pop_front(); + webtransport::Stream* stream = + OpenDataStream(next.subscription_id, next.first_object); + if (stream != nullptr) { + stream->visitor()->OnCanWrite(); + } } - new_stream->SetVisitor(std::make_unique(this, new_stream, false)); - return new_stream->GetStreamId(); } std::pair @@ -350,211 +498,45 @@ MoqtSession::TrackPropertiesFromAlias(const MoqtObject& message) { track.visitor()}); } -bool MoqtSession::PublishObject(const FullTrackName& full_track_name, - uint64_t group_id, uint64_t object_id, - uint64_t object_send_order, - absl::string_view payload, bool end_of_stream) { - auto track_it = local_tracks_.find(full_track_name); - if (track_it == local_tracks_.end()) { - QUICHE_DLOG(ERROR) << ENDPOINT << "Sending OBJECT for nonexistent track"; - return false; - } - LocalTrack& track = track_it->second; - MoqtForwardingPreference forwarding_preference = - track.forwarding_preference(); - if ((forwarding_preference == MoqtForwardingPreference::kObject || - forwarding_preference == MoqtForwardingPreference::kDatagram) && - !end_of_stream) { - QUIC_BUG(MoqtSession_PublishObject_end_of_stream_required) - << "Forwarding preferences of Object or Datagram require stream to be " - "immediately closed"; - return false; - } - track.SentSequence(FullSequence(group_id, object_id)); - std::vector subscriptions = - track.ShouldSend({group_id, object_id}); - if (subscriptions.empty()) { - return true; - } - MoqtObject object; - QUICHE_DCHECK(track.track_alias().has_value()); - object.track_alias = *track.track_alias(); - object.group_id = group_id; - object.object_id = object_id; - object.object_send_order = object_send_order; - object.forwarding_preference = forwarding_preference; - object.payload_length = payload.size(); - int failures = 0; - quiche::StreamWriteOptions write_options; - write_options.set_send_fin(end_of_stream); - for (auto subscription : subscriptions) { - if (forwarding_preference == MoqtForwardingPreference::kDatagram) { - object.subscribe_id = subscription->subscribe_id(); - quiche::QuicheBuffer datagram = - framer_.SerializeObjectDatagram(object, payload); - // TODO(martinduke): It's OK to just silently fail, but better to notify - // the app on errors. - session_->SendOrQueueDatagram(datagram.AsStringView()); - continue; - } - bool new_stream = false; - std::optional stream_id = - subscription->GetStreamForSequence(FullSequence(group_id, object_id)); - if (!stream_id.has_value()) { - new_stream = true; - stream_id = OpenUnidirectionalStream(); - if (!stream_id.has_value()) { - QUICHE_DLOG(ERROR) << ENDPOINT - << "Sending OBJECT to nonexistent stream"; - ++failures; - continue; - } - if (!end_of_stream) { - subscription->AddStream(group_id, object_id, *stream_id); - } - } - webtransport::Stream* stream = session_->GetStreamById(*stream_id); - if (stream == nullptr) { - QUICHE_DLOG(ERROR) << ENDPOINT << "Sending OBJECT to nonexistent stream " - << *stream_id; - ++failures; - continue; - } - object.subscribe_id = subscription->subscribe_id(); - quiche::QuicheBuffer header = - framer_.SerializeObjectHeader(object, new_stream); - std::array views = {header.AsStringView(), payload}; - if (!stream->Writev(views, write_options).ok()) { - QUICHE_DLOG(ERROR) << ENDPOINT << "Failed to write OBJECT message"; - ++failures; - continue; - } - QUICHE_LOG(INFO) << ENDPOINT << "Sending object length " << payload.length() - << " for " << full_track_name.track_namespace << ":" - << full_track_name.track_name << " with sequence " - << object.group_id << ":" << object.object_id - << " on stream " << *stream_id; - if (end_of_stream && !new_stream) { - subscription->RemoveStream(group_id, object_id); - } - } - return (failures == 0); -} - -void MoqtSession::CloseObjectStream(const FullTrackName& full_track_name, - uint64_t group_id) { - auto track_it = local_tracks_.find(full_track_name); - if (track_it == local_tracks_.end()) { - QUICHE_DLOG(ERROR) << ENDPOINT << "Sending OBJECT for nonexistent track"; - return; - } - LocalTrack& track = track_it->second; - - MoqtForwardingPreference forwarding_preference = - track.forwarding_preference(); - if (forwarding_preference == MoqtForwardingPreference::kObject || - forwarding_preference == MoqtForwardingPreference::kDatagram) { - QUIC_BUG(MoqtSession_CloseStreamObject_wrong_type) - << "Forwarding preferences of Object or Datagram require stream to be " - "immediately closed, and thus are not valid CloseObjectStream() " - "targets"; - return; - } - - std::vector subscriptions = - track.ShouldSend({group_id, /*object=*/0}); - for (SubscribeWindow* subscription : subscriptions) { - std::optional stream_id = - subscription->GetStreamForSequence( - FullSequence(group_id, /*object=*/0)); - if (!stream_id.has_value()) { - continue; - } - webtransport::Stream* stream = session_->GetStreamById(*stream_id); - if (stream == nullptr) { - continue; - } - bool success = stream->SendFin(); - QUICHE_BUG_IF(MoqtSession_CloseObjectStream_fin_failed, !success); - } -} - -void MoqtSession::Stream::OnCanRead() { +static void ForwardStreamDataToParser(webtransport::Stream& stream, + MoqtParser& parser) { bool fin = - quiche::ProcessAllReadableRegions(*stream_, [&](absl::string_view chunk) { - parser_.ProcessData(chunk, /*end_of_stream=*/false); + quiche::ProcessAllReadableRegions(stream, [&](absl::string_view chunk) { + parser.ProcessData(chunk, /*end_of_stream=*/false); }); if (fin) { - parser_.ProcessData("", /*end_of_stream=*/true); - } -} -void MoqtSession::Stream::OnCanWrite() {} -void MoqtSession::Stream::OnResetStreamReceived( - webtransport::StreamErrorCode error) { - if (is_control_stream_.has_value() && *is_control_stream_) { - session_->Error( - MoqtError::kProtocolViolation, - absl::StrCat("Control stream reset with error code ", error)); - } -} -void MoqtSession::Stream::OnStopSendingReceived( - webtransport::StreamErrorCode error) { - if (is_control_stream_.has_value() && *is_control_stream_) { - session_->Error( - MoqtError::kProtocolViolation, - absl::StrCat("Control stream reset with error code ", error)); + parser.ProcessData("", /*end_of_stream=*/true); } } -void MoqtSession::Stream::OnObjectMessage(const MoqtObject& message, - absl::string_view payload, - bool end_of_message) { - if (is_control_stream_ == true) { - session_->Error(MoqtError::kProtocolViolation, - "Received OBJECT message on control stream"); - return; - } - QUICHE_DLOG(INFO) - << ENDPOINT << "Received OBJECT message on stream " - << stream_->GetStreamId() << " for subscribe_id " << message.subscribe_id - << " for track alias " << message.track_alias << " with sequence " - << message.group_id << ":" << message.object_id << " send_order " - << message.object_send_order << " forwarding_preference " - << MoqtForwardingPreferenceToString(message.forwarding_preference) - << " length " << payload.size() << " explicit length " - << (message.payload_length.has_value() ? (int)*message.payload_length - : -1) - << (end_of_message ? "F" : ""); - if (!session_->parameters_.deliver_partial_objects) { - if (!end_of_message) { // Buffer partial object. - absl::StrAppend(&partial_object_, payload); - return; - } - if (!partial_object_.empty()) { // Completes the object - absl::StrAppend(&partial_object_, payload); - payload = absl::string_view(partial_object_); - } - } - auto [full_track_name, visitor] = session_->TrackPropertiesFromAlias(message); - if (visitor != nullptr) { - visitor->OnObjectFragment(full_track_name, message.group_id, - message.object_id, message.object_send_order, - message.forwarding_preference, payload, - end_of_message); - } - partial_object_.clear(); +void MoqtSession::ControlStream::OnCanRead() { + ForwardStreamDataToParser(*stream_, parser_); +} +void MoqtSession::ControlStream::OnCanWrite() { + // We buffer serialized control frames unconditionally, thus OnCanWrite() + // requires no handling for control streams. } -void MoqtSession::Stream::OnClientSetupMessage(const MoqtClientSetup& message) { - if (is_control_stream_.has_value()) { - if (!*is_control_stream_) { - session_->Error(MoqtError::kProtocolViolation, - "Received SETUP on non-control stream"); - return; - } - } else { - is_control_stream_ = true; - } +void MoqtSession::ControlStream::OnResetStreamReceived( + webtransport::StreamErrorCode error) { + session_->Error(MoqtError::kProtocolViolation, + absl::StrCat("Control stream reset with error code ", error)); +} +void MoqtSession::ControlStream::OnStopSendingReceived( + webtransport::StreamErrorCode error) { + session_->Error(MoqtError::kProtocolViolation, + absl::StrCat("Control stream reset with error code ", error)); +} + +void MoqtSession::ControlStream::OnObjectMessage(const MoqtObject& message, + absl::string_view payload, + bool end_of_message) { + session_->Error(MoqtError::kProtocolViolation, + "Received OBJECT message on control stream"); +} + +void MoqtSession::ControlStream::OnClientSetupMessage( + const MoqtClientSetup& message) { session_->control_stream_ = stream_->GetStreamId(); if (perspective() == Perspective::IS_CLIENT) { session_->Error(MoqtError::kProtocolViolation, @@ -582,16 +564,8 @@ void MoqtSession::Stream::OnClientSetupMessage(const MoqtClientSetup& message) { session_->peer_role_ = *message.role; } -void MoqtSession::Stream::OnServerSetupMessage(const MoqtServerSetup& message) { - if (is_control_stream_.has_value()) { - if (!*is_control_stream_) { - session_->Error(MoqtError::kProtocolViolation, - "Received SETUP on non-control stream"); - return; - } - } else { - is_control_stream_ = true; - } +void MoqtSession::ControlStream::OnServerSetupMessage( + const MoqtServerSetup& message) { if (perspective() == Perspective::IS_SERVER) { session_->Error(MoqtError::kProtocolViolation, "Received SERVER_SETUP from client"); @@ -610,10 +584,9 @@ void MoqtSession::Stream::OnServerSetupMessage(const MoqtServerSetup& message) { session_->peer_role_ = *message.role; } -void MoqtSession::Stream::SendSubscribeError(const MoqtSubscribe& message, - SubscribeErrorCode error_code, - absl::string_view reason_phrase, - uint64_t track_alias) { +void MoqtSession::ControlStream::SendSubscribeError( + const MoqtSubscribe& message, SubscribeErrorCode error_code, + absl::string_view reason_phrase, uint64_t track_alias) { MoqtSubscribeError subscribe_error; subscribe_error.subscribe_id = message.subscribe_id; subscribe_error.error_code = error_code; @@ -623,11 +596,8 @@ void MoqtSession::Stream::SendSubscribeError(const MoqtSubscribe& message, session_->framer_.SerializeSubscribeError(subscribe_error)); } -void MoqtSession::Stream::OnSubscribeMessage(const MoqtSubscribe& message) { - std::string reason_phrase = ""; - if (!CheckIfIsControlStream()) { - return; - } +void MoqtSession::ControlStream::OnSubscribeMessage( + const MoqtSubscribe& message) { if (session_->peer_role_ == MoqtRole::kPublisher) { QUIC_DLOG(INFO) << ENDPOINT << "Publisher peer sent SUBSCRIBE"; session_->Error(MoqtError::kProtocolViolation, @@ -636,76 +606,47 @@ void MoqtSession::Stream::OnSubscribeMessage(const MoqtSubscribe& message) { } QUIC_DLOG(INFO) << ENDPOINT << "Received a SUBSCRIBE for " << message.track_namespace << ":" << message.track_name; - auto it = session_->local_tracks_.find(FullTrackName( - std::string(message.track_namespace), std::string(message.track_name))); - if (it == session_->local_tracks_.end()) { - QUIC_DLOG(INFO) << ENDPOINT << "Rejected because " - << message.track_namespace << ":" << message.track_name - << " does not exist"; + + FullTrackName track_name = + FullTrackName{message.track_namespace, message.track_name}; + absl::StatusOr> track_publisher = + session_->publisher_->GetTrack(track_name); + if (!track_publisher.ok()) { + QUIC_DLOG(INFO) << ENDPOINT << "SUBSCRIBE for " << track_name + << " rejected by the application: " + << track_publisher.status(); SendSubscribeError(message, SubscribeErrorCode::kInternalError, - "Track does not exist", message.track_alias); + track_publisher.status().message(), message.track_alias); return; } - LocalTrack& track = it->second; - if ((track.track_alias().has_value() && - message.track_alias != *track.track_alias()) || - session_->used_track_aliases_.contains(message.track_alias)) { - // Propose a different track_alias. - SendSubscribeError(message, SubscribeErrorCode::kRetryTrackAlias, - "Track alias already exists", - session_->next_local_track_alias_++); - return; - } else { // Use client-provided alias. - track.set_track_alias(message.track_alias); - if (message.track_alias >= session_->next_local_track_alias_) { - session_->next_local_track_alias_ = message.track_alias + 1; - } - session_->used_track_aliases_.insert(message.track_alias); + std::optional largest_id; + if (PublisherHasData(**track_publisher)) { + largest_id = (*track_publisher)->GetLargestSequence(); } - std::optional start = session_->LocationToAbsoluteNumber( - track, message.start_group, message.start_object); - QUICHE_DCHECK(start.has_value()); // Parser enforces this. - std::optional end = session_->LocationToAbsoluteNumber( - track, message.end_group, message.end_object); - LocalTrack::Visitor::PublishPastObjectsCallback publish_past_objects; - SubscribeWindow window = - end.has_value() - ? SubscribeWindow(message.subscribe_id, track.forwarding_preference(), - start->group, start->object, end->group, - end->object) - : SubscribeWindow(message.subscribe_id, track.forwarding_preference(), - start->group, start->object); - if (start < track.next_sequence() && track.visitor() != nullptr) { - absl::StatusOr - past_objects_available = track.visitor()->OnSubscribeForPast(window); - if (!past_objects_available.ok()) { - SendSubscribeError(message, SubscribeErrorCode::kInternalError, - past_objects_available.status().message(), - message.track_alias); - return; - } - publish_past_objects = *std::move(past_objects_available); + MoqtDeliveryOrder delivery_order = (*track_publisher)->GetDeliveryOrder(); + + auto subscription = std::make_unique( + session_, *std::move(track_publisher), message); + auto [it, success] = session_->published_subscriptions_.emplace( + message.subscribe_id, std::move(subscription)); + if (!success) { + SendSubscribeError(message, SubscribeErrorCode::kInternalError, + "Duplicate subscribe ID", message.track_alias); } + MoqtSubscribeOk subscribe_ok; subscribe_ok.subscribe_id = message.subscribe_id; + subscribe_ok.group_order = delivery_order; + subscribe_ok.largest_id = largest_id; SendOrBufferMessage(session_->framer_.SerializeSubscribeOk(subscribe_ok)); - QUIC_DLOG(INFO) << ENDPOINT << "Created subscription for " - << message.track_namespace << ":" << message.track_name; - if (end.has_value()) { - track.AddWindow(message.subscribe_id, start->group, start->object, - end->group, end->object); - } else { - track.AddWindow(message.subscribe_id, start->group, start->object); - } - if (publish_past_objects) { - std::move(publish_past_objects)(); + + if (largest_id.has_value()) { + it->second->Backfill(); } } -void MoqtSession::Stream::OnSubscribeOkMessage(const MoqtSubscribeOk& message) { - if (!CheckIfIsControlStream()) { - return; - } +void MoqtSession::ControlStream::OnSubscribeOkMessage( + const MoqtSubscribeOk& message) { auto it = session_->active_subscribes_.find(message.subscribe_id); if (it == session_->active_subscribes_.end()) { session_->Error(MoqtError::kProtocolViolation, @@ -737,11 +678,8 @@ void MoqtSession::Stream::OnSubscribeOkMessage(const MoqtSubscribeOk& message) { session_->active_subscribes_.erase(it); } -void MoqtSession::Stream::OnSubscribeErrorMessage( +void MoqtSession::ControlStream::OnSubscribeErrorMessage( const MoqtSubscribeError& message) { - if (!CheckIfIsControlStream()) { - return; - } auto it = session_->active_subscribes_.find(message.subscribe_id); if (it == session_->active_subscribes_.end()) { session_->Error(MoqtError::kProtocolViolation, @@ -771,24 +709,36 @@ void MoqtSession::Stream::OnSubscribeErrorMessage( session_->active_subscribes_.erase(it); } -void MoqtSession::Stream::OnUnsubscribeMessage(const MoqtUnsubscribe& message) { - // Search all the tracks to find the subscribe ID. - for (auto& [name, track] : session_->local_tracks_) { - track.DeleteWindow(message.subscribe_id); - } - // TODO(martinduke): Send SUBSCRIBE_DONE in response. +void MoqtSession::ControlStream::OnUnsubscribeMessage( + const MoqtUnsubscribe& message) { + session_->SubscribeIsDone(message.subscribe_id, + SubscribeDoneCode::kUnsubscribed, ""); } -void MoqtSession::Stream::OnAnnounceMessage(const MoqtAnnounce& message) { +void MoqtSession::ControlStream::OnSubscribeUpdateMessage( + const MoqtSubscribeUpdate& message) { + auto it = session_->published_subscriptions_.find(message.subscribe_id); + if (it == session_->published_subscriptions_.end()) { + return; + } + FullSequence start(message.start_group, message.start_object); + std::optional end; + if (message.end_group.has_value()) { + end = FullSequence(*message.end_group, message.end_object.has_value() + ? *message.end_object + : UINT64_MAX); + } + it->second->Update(start, end, message.subscriber_priority); +} + +void MoqtSession::ControlStream::OnAnnounceMessage( + const MoqtAnnounce& message) { if (session_->peer_role_ == MoqtRole::kSubscriber) { QUIC_DLOG(INFO) << ENDPOINT << "Subscriber peer sent SUBSCRIBE"; session_->Error(MoqtError::kProtocolViolation, "Received ANNOUNCE from Subscriber"); return; } - if (!CheckIfIsControlStream()) { - return; - } std::optional error = session_->callbacks_.incoming_announce_callback(message.track_namespace); if (error.has_value()) { @@ -804,10 +754,8 @@ void MoqtSession::Stream::OnAnnounceMessage(const MoqtAnnounce& message) { SendOrBufferMessage(session_->framer_.SerializeAnnounceOk(ok)); } -void MoqtSession::Stream::OnAnnounceOkMessage(const MoqtAnnounceOk& message) { - if (!CheckIfIsControlStream()) { - return; - } +void MoqtSession::ControlStream::OnAnnounceOkMessage( + const MoqtAnnounceOk& message) { auto it = session_->pending_outgoing_announces_.find(message.track_namespace); if (it == session_->pending_outgoing_announces_.end()) { session_->Error(MoqtError::kProtocolViolation, @@ -818,11 +766,8 @@ void MoqtSession::Stream::OnAnnounceOkMessage(const MoqtAnnounceOk& message) { session_->pending_outgoing_announces_.erase(it); } -void MoqtSession::Stream::OnAnnounceErrorMessage( +void MoqtSession::ControlStream::OnAnnounceErrorMessage( const MoqtAnnounceError& message) { - if (!CheckIfIsControlStream()) { - return; - } auto it = session_->pending_outgoing_announces_.find(message.track_namespace); if (it == session_->pending_outgoing_announces_.end()) { session_->Error(MoqtError::kProtocolViolation, @@ -836,51 +781,23 @@ void MoqtSession::Stream::OnAnnounceErrorMessage( session_->pending_outgoing_announces_.erase(it); } -void MoqtSession::Stream::OnParsingError(MoqtError error_code, - absl::string_view reason) { +void MoqtSession::ControlStream::OnAnnounceCancelMessage( + const MoqtAnnounceCancel& message) { + // TODO: notify the application about this. +} + +void MoqtSession::ControlStream::OnParsingError(MoqtError error_code, + absl::string_view reason) { session_->Error(error_code, absl::StrCat("Parse error: ", reason)); } -bool MoqtSession::Stream::CheckIfIsControlStream() { - if (!is_control_stream_.has_value()) { - session_->Error(MoqtError::kProtocolViolation, - "Received SUBSCRIBE_REQUEST as first message"); - return false; - } - if (!*is_control_stream_) { - session_->Error(MoqtError::kProtocolViolation, - "Received SUBSCRIBE_REQUEST on non-control stream"); - return false; - } - return true; -} - -std::optional MoqtSession::LocationToAbsoluteNumber( - const LocalTrack& track, const std::optional& group, - const std::optional& object) { - FullSequence sequence; - if (!group.has_value() || !object.has_value()) { - return std::nullopt; - } - if (group->absolute) { - sequence.group = group->absolute_value; - } else { - sequence.group = track.next_sequence().group + group->relative_value; - } - if (object->absolute) { - sequence.object = object->absolute_value; - } else { - // Subtract 1 because the relative value is computed from the largest sent - // sequence number, not the next one. - sequence.object = track.next_sequence().object + object->relative_value - 1; - } - return sequence; -} - -void MoqtSession::Stream::SendOrBufferMessage(quiche::QuicheBuffer message, - bool fin) { +void MoqtSession::ControlStream::SendOrBufferMessage( + quiche::QuicheBuffer message, bool fin) { quiche::StreamWriteOptions options; options.set_send_fin(fin); + // TODO: while we buffer unconditionally, we should still at some point tear + // down the connection if we've buffered too many control messages; otherwise, + // there is potential for memory exhaustion attacks. options.set_buffer_unconditionally(true); std::array write_vector = {message.AsStringView()}; absl::Status success = stream_->Writev(absl::MakeSpan(write_vector), options); @@ -890,4 +807,361 @@ void MoqtSession::Stream::SendOrBufferMessage(quiche::QuicheBuffer message, } } +void MoqtSession::IncomingDataStream::OnObjectMessage(const MoqtObject& message, + absl::string_view payload, + bool end_of_message) { + QUICHE_DVLOG(1) + << ENDPOINT << "Received OBJECT message on stream " + << stream_->GetStreamId() << " for subscribe_id " << message.subscribe_id + << " for track alias " << message.track_alias << " with sequence " + << message.group_id << ":" << message.object_id << " priority " + << message.publisher_priority << " forwarding_preference " + << MoqtForwardingPreferenceToString(message.forwarding_preference) + << " length " << payload.size() << " explicit length " + << (message.payload_length.has_value() ? (int)*message.payload_length + : -1) + << (end_of_message ? "F" : ""); + if (!session_->parameters_.deliver_partial_objects) { + if (!end_of_message) { // Buffer partial object. + absl::StrAppend(&partial_object_, payload); + return; + } + if (!partial_object_.empty()) { // Completes the object + absl::StrAppend(&partial_object_, payload); + payload = absl::string_view(partial_object_); + } + } + auto [full_track_name, visitor] = session_->TrackPropertiesFromAlias(message); + if (visitor != nullptr) { + visitor->OnObjectFragment( + full_track_name, message.group_id, message.object_id, + message.publisher_priority, message.object_status, + message.forwarding_preference, payload, end_of_message); + } + partial_object_.clear(); +} + +void MoqtSession::IncomingDataStream::OnCanRead() { + ForwardStreamDataToParser(*stream_, parser_); +} + +void MoqtSession::IncomingDataStream::OnControlMessageReceived() { + session_->Error(MoqtError::kProtocolViolation, + "Received a control message on a data stream"); +} + +void MoqtSession::IncomingDataStream::OnParsingError(MoqtError error_code, + absl::string_view reason) { + session_->Error(error_code, absl::StrCat("Parse error: ", reason)); +} + +MoqtSession::PublishedSubscription::PublishedSubscription( + MoqtSession* session, std::shared_ptr track_publisher, + const MoqtSubscribe& subscribe) + : subscription_id_(subscribe.subscribe_id), + session_(session), + track_publisher_(track_publisher), + track_alias_(subscribe.track_alias), + window_(SubscribeMessageToWindow(subscribe, *track_publisher)), + subscriber_priority_(subscribe.subscriber_priority), + subscriber_delivery_order_(subscribe.group_order) { + track_publisher->AddObjectListener(this); + QUIC_DLOG(INFO) << ENDPOINT << "Created subscription for " + << subscribe.track_namespace << ":" << subscribe.track_name; +} + +MoqtSession::PublishedSubscription::~PublishedSubscription() { + track_publisher_->RemoveObjectListener(this); +} + +SendStreamMap& MoqtSession::PublishedSubscription::stream_map() { + // The stream map is lazily initialized, since initializing it requires + // knowing the forwarding preference in advance, and it might not be known + // when the subscription is first created. + if (!lazily_initialized_stream_map_.has_value()) { + QUICHE_DCHECK( + DoesTrackStatusImplyHavingData(*track_publisher_->GetTrackStatus())); + lazily_initialized_stream_map_.emplace( + track_publisher_->GetForwardingPreference()); + } + return *lazily_initialized_stream_map_; +} + +void MoqtSession::PublishedSubscription::Update( + FullSequence start, std::optional end, + MoqtPriority subscriber_priority) { + window_.UpdateStartEnd(start, end); + subscriber_priority_ = subscriber_priority; + // TODO: reset streams that are no longer in-window. + // TODO: send SUBSCRIBE_DONE if required. + // TODO: send an error for invalid updates now that it's a part of draft-05. +} + +void MoqtSession::PublishedSubscription::OnNewObjectAvailable( + FullSequence sequence) { + if (!window_.InWindow(sequence)) { + return; + } + + MoqtForwardingPreference forwarding_preference = + track_publisher_->GetForwardingPreference(); + if (forwarding_preference == MoqtForwardingPreference::kDatagram) { + SendDatagram(sequence); + return; + } + + std::optional stream_id = + stream_map().GetStreamForSequence(sequence); + webtransport::Stream* raw_stream = nullptr; + if (stream_id.has_value()) { + raw_stream = session_->session_->GetStreamById(*stream_id); + } else { + if (!window_.IsStreamProvokingObject(sequence, forwarding_preference)) { + QUIC_DLOG(INFO) << ENDPOINT << "Received object " << sequence + << ", but there is no stream that it can be mapped to"; + // It is possible that the we are getting notified of objects out of + // order, but we still have to send objects in a manner consistent with + // the forwarding preference used. + return; + } + raw_stream = session_->OpenOrQueueDataStream(subscription_id_, sequence); + } + if (raw_stream == nullptr) { + return; + } + + OutgoingDataStream* stream = + static_cast(raw_stream->visitor()); + stream->SendObjects(*this); +} + +void MoqtSession::PublishedSubscription::Backfill() { + const FullSequence start = window_.start(); + const FullSequence end = track_publisher_->GetLargestSequence(); + const MoqtForwardingPreference preference = + track_publisher_->GetForwardingPreference(); + + absl::flat_hash_set already_opened; + std::vector objects = + track_publisher_->GetCachedObjectsInRange(start, end); + QUICHE_DCHECK(absl::c_is_sorted(objects)); + for (FullSequence sequence : objects) { + auto [it, was_missing] = + already_opened.insert(ReducedSequenceIndex(sequence, preference)); + if (!was_missing) { + // For every stream mapping unit present, we only need to notify of the + // earliest object on it, since the stream itself will pull the rest. + continue; + } + OnNewObjectAvailable(sequence); + } +} + +std::vector +MoqtSession::PublishedSubscription::GetAllStreams() const { + if (!lazily_initialized_stream_map_.has_value()) { + return {}; + } + return lazily_initialized_stream_map_->GetAllStreams(); +} + +void MoqtSession::PublishedSubscription::OnDataStreamCreated( + webtransport::StreamId id, FullSequence start_sequence) { + stream_map().AddStream(start_sequence, id); +} +void MoqtSession::PublishedSubscription::OnDataStreamDestroyed( + webtransport::StreamId id, FullSequence end_sequence) { + stream_map().RemoveStream(end_sequence, id); +} + +void MoqtSession::PublishedSubscription::OnObjectSent(FullSequence sequence) { + if (largest_sent_.has_value()) { + largest_sent_ = std::max(*largest_sent_, sequence); + } else { + largest_sent_ = sequence; + } + // TODO: send SUBSCRIBE_DONE if the subscription is done. +} + +MoqtSession::OutgoingDataStream::OutgoingDataStream( + MoqtSession* session, webtransport::Stream* stream, + uint64_t subscription_id, FullSequence first_object) + : session_(session), + stream_(stream), + subscription_id_(subscription_id), + next_object_(first_object), + session_liveness_(session->liveness_token_) {} + +MoqtSession::OutgoingDataStream::~OutgoingDataStream() { + // Though it might seem intuitive that the session object has to outlive the + // connection object (and this is indeed how something like QuicSession and + // QuicStream works), this is not the true for WebTransport visitors: the + // session getting destroyed will inevitably lead to all related streams being + // destroyed, but the actual order of destruction is not guaranteed. Thus, we + // need to check if the session still exists while accessing it in a stream + // destructor. + if (session_liveness_.expired()) { + return; + } + auto it = session_->published_subscriptions_.find(subscription_id_); + if (it != session_->published_subscriptions_.end()) { + it->second->OnDataStreamDestroyed(stream_->GetStreamId(), next_object_); + } +} + +void MoqtSession::OutgoingDataStream::OnCanWrite() { + PublishedSubscription* subscription = GetSubscriptionIfValid(); + if (subscription == nullptr) { + return; + } + SendObjects(*subscription); +} + +MoqtSession::PublishedSubscription* +MoqtSession::OutgoingDataStream::GetSubscriptionIfValid() { + auto it = session_->published_subscriptions_.find(subscription_id_); + if (it == session_->published_subscriptions_.end()) { + stream_->ResetWithUserCode(kResetCodeSubscriptionGone); + return nullptr; + } + + PublishedSubscription* subscription = it->second.get(); + MoqtTrackPublisher& publisher = subscription->publisher(); + absl::StatusOr status = publisher.GetTrackStatus(); + if (!status.ok()) { + // TODO: clean up the subscription. + return nullptr; + } + if (!DoesTrackStatusImplyHavingData(*status)) { + QUICHE_BUG(GetSubscriptionIfValid_InvalidTrackStatus) + << "The track publisher returned a status indicating that no objects " + "are available, but a stream for those objects exists."; + session_->Error(MoqtError::kInternalError, + "Invalid track state provided by application"); + return nullptr; + } + return subscription; +} + +void MoqtSession::OutgoingDataStream::SendObjects( + PublishedSubscription& subscription) { + while (stream_->CanWrite()) { + std::optional object = + subscription.publisher().GetCachedObject(next_object_); + if (!object.has_value()) { + break; + } + if (!subscription.InWindow(next_object_)) { + // It is possible that the next object became irrelevant due to a + // SUBSCRIBE_UPDATE. Close the stream if so. + bool success = stream_->SendFin(); + QUICHE_BUG_IF(OutgoingDataStream_fin_due_to_update, !success) + << "Writing FIN failed despite CanWrite() being true."; + return; + } + SendNextObject(subscription, *std::move(object)); + } +} + +void MoqtSession::OutgoingDataStream::SendNextObject( + PublishedSubscription& subscription, PublishedObject object) { + QUICHE_DCHECK(object.sequence == next_object_); + QUICHE_DCHECK(stream_->CanWrite()); + + MoqtTrackPublisher& publisher = subscription.publisher(); + QUICHE_DCHECK(DoesTrackStatusImplyHavingData(*publisher.GetTrackStatus())); + MoqtForwardingPreference forwarding_preference = + publisher.GetForwardingPreference(); + + MoqtObject header; + header.subscribe_id = subscription_id_; + header.track_alias = subscription.track_alias(); + header.group_id = object.sequence.group; + header.object_id = object.sequence.object; + header.publisher_priority = publisher.GetPublisherPriority(); + header.object_status = object.status; + header.forwarding_preference = forwarding_preference; + header.payload_length = object.payload.length(); + + quiche::QuicheBuffer serialized_header = + session_->framer_.SerializeObjectHeader(header, !stream_header_written_); + bool fin = false; + switch (forwarding_preference) { + case MoqtForwardingPreference::kTrack: + if (object.status == MoqtObjectStatus::kEndOfGroup || + object.status == MoqtObjectStatus::kGroupDoesNotExist) { + ++next_object_.group; + next_object_.object = 0; + } else { + ++next_object_.object; + } + fin = object.status == MoqtObjectStatus::kEndOfTrack || + !subscription.InWindow(next_object_); + break; + + case MoqtForwardingPreference::kGroup: + ++next_object_.object; + fin = object.status == MoqtObjectStatus::kEndOfTrack || + object.status == MoqtObjectStatus::kEndOfGroup || + object.status == MoqtObjectStatus::kGroupDoesNotExist || + !subscription.InWindow(next_object_); + break; + + case MoqtForwardingPreference::kObject: + QUICHE_DCHECK(!stream_header_written_); + fin = true; + break; + + case MoqtForwardingPreference::kDatagram: + QUICHE_NOTREACHED(); + break; + } + + // TODO(vasilvv): add a version of WebTransport write API that accepts + // memslices so that we can avoid a copy here. + std::array write_vector = { + serialized_header.AsStringView(), object.payload.AsStringView()}; + quiche::StreamWriteOptions options; + options.set_send_fin(fin); + absl::Status write_status = stream_->Writev(write_vector, options); + if (!write_status.ok()) { + QUICHE_BUG(MoqtSession_SendNextObject_write_failed) + << "Writing into MoQT stream failed despite CanWrite() being true " + "before; status: " + << write_status; + session_->Error(MoqtError::kInternalError, "Data stream write error"); + return; + } + + QUIC_DVLOG(1) << "Stream " << stream_->GetStreamId() << " successfully wrote " + << object.sequence << ", fin = " << fin + << ", next: " << next_object_; + + stream_header_written_ = true; + subscription.OnObjectSent(object.sequence); +} + +void MoqtSession::PublishedSubscription::SendDatagram(FullSequence sequence) { + std::optional object = + track_publisher_->GetCachedObject(sequence); + if (!object.has_value()) { + QUICHE_BUG(PublishedSubscription_SendDatagram_object_not_in_cache) + << "Got notification about an object that is not in the cache"; + return; + } + + MoqtObject header; + header.subscribe_id = subscription_id_; + header.track_alias = track_alias(); + header.group_id = object->sequence.group; + header.object_id = object->sequence.object; + header.publisher_priority = track_publisher_->GetPublisherPriority(); + header.object_status = object->status; + header.forwarding_preference = MoqtForwardingPreference::kDatagram; + quiche::QuicheBuffer datagram = session_->framer_.SerializeObjectDatagram( + header, object->payload.AsStringView()); + session_->session_->SendOrQueueDatagram(datagram.AsStringView()); + OnObjectSent(object->sequence); +} + } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.h index fab05df305..4e6d1729a0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.h @@ -6,9 +6,11 @@ #define QUICHE_QUIC_MOQT_MOQT_SESSION_H_ #include +#include #include #include #include +#include #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" @@ -17,11 +19,14 @@ #include "quiche/quic/moqt/moqt_framer.h" #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/quic/moqt/moqt_parser.h" +#include "quiche/quic/moqt/moqt_priority.h" +#include "quiche/quic/moqt/moqt_publisher.h" +#include "quiche/quic/moqt/moqt_subscribe_windows.h" #include "quiche/quic/moqt/moqt_track.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/quiche_buffer_allocator.h" #include "quiche/common/quiche_callbacks.h" -#include "quiche/common/simple_buffer_allocator.h" +#include "quiche/common/quiche_circular_deque.h" #include "quiche/web_transport/web_transport.h" namespace moqt { @@ -63,12 +68,7 @@ struct MoqtSessionCallbacks { class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { public: MoqtSession(webtransport::Session* session, MoqtSessionParameters parameters, - MoqtSessionCallbacks callbacks = MoqtSessionCallbacks()) - : session_(session), - parameters_(parameters), - callbacks_(std::move(callbacks)), - framer_(quiche::SimpleBufferAllocator::Get(), - parameters.using_webtrans) {} + MoqtSessionCallbacks callbacks = MoqtSessionCallbacks()); ~MoqtSession() { std::move(callbacks_.session_deleted_callback)(); } // webtransport::SessionVisitor implementation. @@ -79,78 +79,61 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { void OnIncomingUnidirectionalStreamAvailable() override; void OnDatagramReceived(absl::string_view datagram) override; void OnCanCreateNewOutgoingBidirectionalStream() override {} - void OnCanCreateNewOutgoingUnidirectionalStream() override {} + void OnCanCreateNewOutgoingUnidirectionalStream() override; void Error(MoqtError code, absl::string_view error); quic::Perspective perspective() const { return parameters_.perspective; } - // Add to the list of tracks that can be subscribed to. Call this before - // Announce() so that subscriptions can be processed correctly. If |visitor| - // is nullptr, then incoming SUBSCRIBE for objects in the path will receive - // SUBSCRIBE_OK, but never actually get the objects. - void AddLocalTrack(const FullTrackName& full_track_name, - MoqtForwardingPreference forwarding_preference, - LocalTrack::Visitor* visitor); // Send an ANNOUNCE message for |track_namespace|, and call // |announce_callback| when the response arrives. Will fail immediately if // there is already an unresolved ANNOUNCE for that namespace. void Announce(absl::string_view track_namespace, MoqtOutgoingAnnounceCallback announce_callback); - bool HasSubscribers(const FullTrackName& full_track_name) const; // Returns true if SUBSCRIBE was sent. If there is already a subscription to // the track, the message will still be sent. However, the visitor will be // ignored. + // Subscribe from (start_group, start_object) to the end of the track. bool SubscribeAbsolute(absl::string_view track_namespace, absl::string_view name, uint64_t start_group, uint64_t start_object, RemoteTrack::Visitor* visitor, absl::string_view auth_info = ""); + // Subscribe from (start_group, start_object) to the end of end_group. + bool SubscribeAbsolute(absl::string_view track_namespace, + absl::string_view name, uint64_t start_group, + uint64_t start_object, uint64_t end_group, + RemoteTrack::Visitor* visitor, + absl::string_view auth_info = ""); + // Subscribe from (start_group, start_object) to (end_group, end_object). bool SubscribeAbsolute(absl::string_view track_namespace, absl::string_view name, uint64_t start_group, uint64_t start_object, uint64_t end_group, uint64_t end_object, RemoteTrack::Visitor* visitor, absl::string_view auth_info = ""); - bool SubscribeRelative(absl::string_view track_namespace, - absl::string_view name, int64_t start_group, - int64_t start_object, RemoteTrack::Visitor* visitor, - absl::string_view auth_info = ""); + bool SubscribeCurrentObject(absl::string_view track_namespace, + absl::string_view name, + RemoteTrack::Visitor* visitor, + absl::string_view auth_info = ""); bool SubscribeCurrentGroup(absl::string_view track_namespace, absl::string_view name, RemoteTrack::Visitor* visitor, absl::string_view auth_info = ""); - // Returns false if it could not open a stream when necessary, or if the - // track does not exist (there was no call to AddLocalTrack). Will still - // return false is some streams succeed. - // Also returns false if |payload_length| exists but is shorter than - // |payload|. - // |payload.length() >= |payload_length|, because the application can deliver - // partial objects. - bool PublishObject(const FullTrackName& full_track_name, uint64_t group_id, - uint64_t object_id, uint64_t object_send_order, - absl::string_view payload, bool end_of_stream); - void CloseObjectStream(const FullTrackName& full_track_name, - uint64_t group_id); - // TODO: Add an API to send partial objects. - MoqtSessionCallbacks& callbacks() { return callbacks_; } + MoqtPublisher* publisher() { return publisher_; } + void set_publisher(MoqtPublisher* publisher) { publisher_ = publisher; } private: friend class test::MoqtSessionPeer; - class QUICHE_EXPORT Stream : public webtransport::StreamVisitor, - public MoqtParserVisitor { + + class QUICHE_EXPORT ControlStream : public webtransport::StreamVisitor, + public MoqtParserVisitor { public: - Stream(MoqtSession* session, webtransport::Stream* stream) + ControlStream(MoqtSession* session, webtransport::Stream* stream) : session_(session), stream_(stream), parser_(session->parameters_.using_webtrans, *this) {} - Stream(MoqtSession* session, webtransport::Stream* stream, - bool is_control_stream) - : session_(session), - stream_(stream), - parser_(session->parameters_.using_webtrans, *this), - is_control_stream_(is_control_stream) {} // webtransport::StreamVisitor implementation. void OnCanRead() override; @@ -169,12 +152,18 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { void OnSubscribeOkMessage(const MoqtSubscribeOk& message) override; void OnSubscribeErrorMessage(const MoqtSubscribeError& message) override; void OnUnsubscribeMessage(const MoqtUnsubscribe& message) override; + // There is no state to update for SUBSCRIBE_DONE. void OnSubscribeDoneMessage(const MoqtSubscribeDone& /*message*/) override { } + void OnSubscribeUpdateMessage(const MoqtSubscribeUpdate& message) override; void OnAnnounceMessage(const MoqtAnnounce& message) override; void OnAnnounceOkMessage(const MoqtAnnounceOk& message) override; void OnAnnounceErrorMessage(const MoqtAnnounceError& message) override; + void OnAnnounceCancelMessage(const MoqtAnnounceCancel& message) override; + void OnTrackStatusRequestMessage( + const MoqtTrackStatusRequest& message) override {}; void OnUnannounceMessage(const MoqtUnannounce& /*message*/) override {} + void OnTrackStatusMessage(const MoqtTrackStatus& message) override {} void OnGoAwayMessage(const MoqtGoAway& /*message*/) override {} void OnParsingError(MoqtError error_code, absl::string_view reason) override; @@ -195,33 +184,227 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { SubscribeErrorCode error_code, absl::string_view reason_phrase, uint64_t track_alias); - bool CheckIfIsControlStream(); MoqtSession* session_; webtransport::Stream* stream_; MoqtParser parser_; - // nullopt means "incoming stream, and we don't know if it's the control - // stream or a data stream yet". - std::optional is_control_stream_; + }; + class QUICHE_EXPORT IncomingDataStream : public webtransport::StreamVisitor, + public MoqtParserVisitor { + public: + IncomingDataStream(MoqtSession* session, webtransport::Stream* stream) + : session_(session), + stream_(stream), + parser_(session->parameters_.using_webtrans, *this) {} + + // webtransport::StreamVisitor implementation. + void OnCanRead() override; + void OnCanWrite() override {} + void OnResetStreamReceived(webtransport::StreamErrorCode error) override {} + void OnStopSendingReceived(webtransport::StreamErrorCode error) override {} + void OnWriteSideInDataRecvdState() override {} + + // MoqtParserVisitor implementation. + // TODO: Handle a stream FIN. + void OnObjectMessage(const MoqtObject& message, absl::string_view payload, + bool end_of_message) override; + void OnClientSetupMessage(const MoqtClientSetup&) override { + OnControlMessageReceived(); + } + void OnServerSetupMessage(const MoqtServerSetup&) override { + OnControlMessageReceived(); + } + void OnSubscribeMessage(const MoqtSubscribe&) override { + OnControlMessageReceived(); + } + void OnSubscribeOkMessage(const MoqtSubscribeOk&) override { + OnControlMessageReceived(); + } + void OnSubscribeErrorMessage(const MoqtSubscribeError&) override { + OnControlMessageReceived(); + } + void OnUnsubscribeMessage(const MoqtUnsubscribe&) override { + OnControlMessageReceived(); + } + void OnSubscribeDoneMessage(const MoqtSubscribeDone&) override { + OnControlMessageReceived(); + } + void OnSubscribeUpdateMessage(const MoqtSubscribeUpdate&) override { + OnControlMessageReceived(); + } + void OnAnnounceMessage(const MoqtAnnounce&) override { + OnControlMessageReceived(); + } + void OnAnnounceOkMessage(const MoqtAnnounceOk&) override { + OnControlMessageReceived(); + } + void OnAnnounceErrorMessage(const MoqtAnnounceError&) override { + OnControlMessageReceived(); + } + void OnAnnounceCancelMessage(const MoqtAnnounceCancel& message) override { + OnControlMessageReceived(); + } + void OnTrackStatusRequestMessage( + const MoqtTrackStatusRequest& message) override { + OnControlMessageReceived(); + } + void OnUnannounceMessage(const MoqtUnannounce&) override { + OnControlMessageReceived(); + } + void OnTrackStatusMessage(const MoqtTrackStatus&) override { + OnControlMessageReceived(); + } + void OnGoAwayMessage(const MoqtGoAway&) override { + OnControlMessageReceived(); + } + void OnParsingError(MoqtError error_code, + absl::string_view reason) override; + + quic::Perspective perspective() const { + return session_->parameters_.perspective; + } + + webtransport::Stream* stream() const { return stream_; } + + private: + friend class test::MoqtSessionPeer; + void OnControlMessageReceived(); + + MoqtSession* session_; + webtransport::Stream* stream_; + MoqtParser parser_; std::string partial_object_; }; + // Represents a record for a single subscription to a local track that is + // being sent to the peer. + class PublishedSubscription : public MoqtObjectListener { + public: + explicit PublishedSubscription( + MoqtSession* session, + std::shared_ptr track_publisher, + const MoqtSubscribe& subscribe); + ~PublishedSubscription(); + PublishedSubscription(const PublishedSubscription&) = delete; + PublishedSubscription(PublishedSubscription&&) = delete; + PublishedSubscription& operator=(const PublishedSubscription&) = delete; + PublishedSubscription& operator=(PublishedSubscription&&) = delete; + + MoqtTrackPublisher& publisher() { return *track_publisher_; } + uint64_t track_alias() const { return track_alias_; } + std::optional largest_sent() const { return largest_sent_; } + + void OnNewObjectAvailable(FullSequence sequence) override; + + // Creates streams for all objects that are currently in the track's object + // cache and match the subscription window. This is in some sense similar + // to a fetch (since all of the objects are in the past), but is + // conceptually simpler, as backpressure is less of a concern. + void Backfill(); + + // Updates the window and other properties of the subscription in question. + void Update(FullSequence start, std::optional end, + MoqtPriority subscriber_priority); + // Checks if the specified sequence is within the window of this + // subscription. + bool InWindow(FullSequence sequence) { return window_.InWindow(sequence); } + + void OnDataStreamCreated(webtransport::StreamId id, + FullSequence start_sequence); + void OnDataStreamDestroyed(webtransport::StreamId id, + FullSequence end_sequence); + void OnObjectSent(FullSequence sequence); + + std::vector GetAllStreams() const; + + private: + SendStreamMap& stream_map(); + quic::Perspective perspective() const { + return session_->parameters_.perspective; + } + + void SendDatagram(FullSequence sequence); + + uint64_t subscription_id_; + MoqtSession* session_; + std::shared_ptr track_publisher_; + uint64_t track_alias_; + SubscribeWindow window_; + MoqtPriority subscriber_priority_; + std::optional subscriber_delivery_order_; + // Largest sequence number ever sent via this subscription. + std::optional largest_sent_; + // Should be almost always accessed via `stream_map()`. + std::optional lazily_initialized_stream_map_; + }; + class QUICHE_EXPORT OutgoingDataStream : public webtransport::StreamVisitor { + public: + OutgoingDataStream(MoqtSession* session, webtransport::Stream* stream, + uint64_t subscription_id, FullSequence first_object); + ~OutgoingDataStream(); + + // webtransport::StreamVisitor implementation. + void OnCanRead() override {} + void OnCanWrite() override; + void OnResetStreamReceived(webtransport::StreamErrorCode error) override {} + void OnStopSendingReceived(webtransport::StreamErrorCode error) override {} + void OnWriteSideInDataRecvdState() override {} + + webtransport::Stream* stream() const { return stream_; } + + // Sends objects on the stream, starting with `next_object_`, until the + // stream becomes write-blocked or closed. + void SendObjects(PublishedSubscription& subscription); + + private: + friend class test::MoqtSessionPeer; + + // Checks whether the associated subscription is still valid; if not, resets + // the stream and returns nullptr. + PublishedSubscription* GetSubscriptionIfValid(); + + // Actually sends an object on the stream; the object MUST be + // `next_object_`. + void SendNextObject(PublishedSubscription& subscription, + PublishedObject object); + + MoqtSession* session_; + webtransport::Stream* stream_; + uint64_t subscription_id_; + FullSequence next_object_; + bool stream_header_written_ = false; + // A weak pointer to an object owned by the session. Used to make sure the + // session does not get called after being destroyed. + std::weak_ptr session_liveness_; + }; + // QueuedOutgoingDataStream records an information necessary to create a + // stream that was attempted to be created before but was blocked due to flow + // control. + struct QueuedOutgoingDataStream { + uint64_t subscription_id; + FullSequence first_object; + }; + + // Returns true if SUBSCRIBE_DONE was sent. + bool SubscribeIsDone(uint64_t subscribe_id, SubscribeDoneCode code, + absl::string_view reason_phrase); // Returns the pointer to the control stream, or nullptr if none is present. - Stream* GetControlStream(); + ControlStream* GetControlStream(); // Sends a message on the control stream; QUICHE_DCHECKs if no control stream // is present. void SendControlMessage(quiche::QuicheBuffer message); // Returns false if the SUBSCRIBE isn't sent. bool Subscribe(MoqtSubscribe& message, RemoteTrack::Visitor* visitor); - // converts two MoqtLocations into absolute sequences. - std::optional LocationToAbsoluteNumber( - const LocalTrack& track, - const std::optional& group, - const std::optional& object); - // Returns the stream ID if successful, nullopt if not. - // TODO: Add a callback if stream creation is delayed. - std::optional OpenUnidirectionalStream(); + + // Opens a new data stream, or queues it if the session is flow control + // blocked. + webtransport::Stream* OpenOrQueueDataStream(uint64_t subscription_id, + FullSequence first_object); + // Same as above, except the session is required to be not flow control + // blocked. + webtransport::Stream* OpenDataStream(uint64_t subscription_id, + FullSequence first_object); // Get FullTrackName and visitor for a subscribe_id and track_alias. Returns // nullptr if not present. @@ -244,8 +427,16 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { absl::flat_hash_map remote_track_aliases_; uint64_t next_remote_track_alias_ = 0; - // All the tracks the peer can subscribe to. - absl::flat_hash_map local_tracks_; + // Application object representing the publisher for all of the tracks that + // can be subscribed to via this connection. Must outlive this object. + MoqtPublisher* publisher_; + // Subscriptions for local tracks by the remote peer, indexed by subscribe ID. + absl::flat_hash_map> + published_subscriptions_; + // Keeps track of all the data streams that were supposed to be open, but were + // blocked by the flow control. + quiche::QuicheCircularDeque + queued_outgoing_data_streams_; // This is only used to check for track_alias collisions. absl::flat_hash_set used_track_aliases_; uint64_t next_local_track_alias_ = 0; @@ -273,6 +464,11 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { // an uninitialized value if no SETUP arrives or it arrives with no Role // parameter, and other checks have changed/been disabled. MoqtRole peer_role_ = MoqtRole::kPubSub; + + // Must be last. Token used to make sure that the streams do not call into + // the session when the session has already been destroyed. + struct Empty {}; + std::shared_ptr liveness_token_; }; } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.cc index bcbb40af47..422a3fcddd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.cc @@ -4,12 +4,12 @@ #include "quiche/quic/moqt/moqt_subscribe_windows.h" -#include #include #include #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" +#include "quiche/common/platform/api/quiche_logging.h" #include "quiche/web_transport/web_transport.h" namespace moqt { @@ -21,9 +21,9 @@ bool SubscribeWindow::InWindow(const FullSequence& seq) const { return (!end_.has_value() || seq <= *end_); } -std::optional SubscribeWindow::GetStreamForSequence( +std::optional SendStreamMap::GetStreamForSequence( FullSequence sequence) const { - FullSequence index = SequenceToIndex(sequence); + ReducedSequenceIndex index(sequence, forwarding_preference_); auto stream_it = send_streams_.find(index); if (stream_it == send_streams_.end()) { return std::nullopt; @@ -31,52 +31,72 @@ std::optional SubscribeWindow::GetStreamForSequence( return stream_it->second; } -void SubscribeWindow::AddStream(uint64_t group_id, uint64_t object_id, - webtransport::StreamId stream_id) { - if (!InWindow(FullSequence(group_id, object_id))) { - return; - } - FullSequence index = SequenceToIndex(FullSequence(group_id, object_id)); +void SendStreamMap::AddStream(FullSequence sequence, + webtransport::StreamId stream_id) { + ReducedSequenceIndex index(sequence, forwarding_preference_); if (forwarding_preference_ == MoqtForwardingPreference::kDatagram) { QUIC_BUG(quic_bug_moqt_draft_03_01) << "Adding a stream for datagram"; return; } - auto stream_it = send_streams_.find(index); - if (stream_it != send_streams_.end()) { - QUIC_BUG(quic_bug_moqt_draft_03_02) << "Stream already added"; - return; - } - send_streams_[index] = stream_id; + auto [stream_it, success] = send_streams_.emplace(index, stream_id); + QUIC_BUG_IF(quic_bug_moqt_draft_03_02, !success) << "Stream already added"; } -void SubscribeWindow::RemoveStream(uint64_t group_id, uint64_t object_id) { - FullSequence index = SequenceToIndex(FullSequence(group_id, object_id)); +void SendStreamMap::RemoveStream(FullSequence sequence, + webtransport::StreamId stream_id) { + ReducedSequenceIndex index(sequence, forwarding_preference_); + QUICHE_DCHECK(send_streams_.contains(index) && + send_streams_.find(index)->second == stream_id) + << "Requested to remove a stream ID that does not match the one in the " + "map"; send_streams_.erase(index); } -FullSequence SubscribeWindow::SequenceToIndex(FullSequence sequence) const { - switch (forwarding_preference_) { +bool SubscribeWindow::UpdateStartEnd(FullSequence start, + std::optional end) { + // Can't make the subscription window bigger. + if (!InWindow(start)) { + return false; + } + if (end_.has_value() && (!end.has_value() || *end_ < *end)) { + return false; + } + start_ = start; + end_ = end; + return true; +} + +bool SubscribeWindow::IsStreamProvokingObject( + FullSequence sequence, MoqtForwardingPreference preference) const { + if (preference == MoqtForwardingPreference::kGroup) { + return sequence.object == 0 || sequence == start_; + } + QUICHE_DCHECK(preference != MoqtForwardingPreference::kDatagram); + return true; +} + +ReducedSequenceIndex::ReducedSequenceIndex( + FullSequence sequence, MoqtForwardingPreference preference) { + switch (preference) { case MoqtForwardingPreference::kTrack: - return FullSequence(0, 0); + sequence_ = FullSequence(0, 0); + break; case MoqtForwardingPreference::kGroup: - return FullSequence(sequence.group, 0); + sequence_ = FullSequence(sequence.group, 0); + break; case MoqtForwardingPreference::kObject: - return sequence; case MoqtForwardingPreference::kDatagram: - QUIC_BUG(quic_bug_moqt_draft_03_01) << "No stream for datagram"; - return FullSequence(0, 0); + sequence_ = sequence; + break; } } -std::vector MoqtSubscribeWindows::SequenceIsSubscribed( - FullSequence sequence) { - std::vector retval; - for (auto& [subscribe_id, window] : windows_) { - if (window.InWindow(sequence)) { - retval.push_back(&(window)); - } +std::vector SendStreamMap::GetAllStreams() const { + std::vector ids; + for (const auto& [index, id] : send_streams_) { + ids.push_back(id); } - return retval; + return ids; } } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h index 75a204f80f..5e0307d5ac 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h @@ -10,116 +10,88 @@ #include #include "absl/container/flat_hash_map.h" -#include "absl/container/node_hash_map.h" #include "quiche/quic/moqt/moqt_messages.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/web_transport/web_transport.h" namespace moqt { -// Classes to track subscriptions to local tracks: the sequence numbers -// subscribed, the streams involved, and the subscribe IDs. +// SubscribeWindow represents a window of objects for which an MoQT subscription +// can be valid. class QUICHE_EXPORT SubscribeWindow { public: - // Creates a half-open window. - SubscribeWindow(uint64_t subscribe_id, - MoqtForwardingPreference forwarding_preference, - uint64_t start_group, uint64_t start_object) - : subscribe_id_(subscribe_id), - start_({start_group, start_object}), - forwarding_preference_(forwarding_preference) {} + // Creates a half-open window. |next_object| is the expected sequence number + // of the next published object on the track. + SubscribeWindow(uint64_t start_group, uint64_t start_object) + : SubscribeWindow(FullSequence(start_group, start_object), std::nullopt) { + } // Creates a closed window. - SubscribeWindow(uint64_t subscribe_id, - MoqtForwardingPreference forwarding_preference, - uint64_t start_group, uint64_t start_object, + SubscribeWindow(uint64_t start_group, uint64_t start_object, uint64_t end_group, uint64_t end_object) - : subscribe_id_(subscribe_id), - start_({start_group, start_object}), - end_(FullSequence(end_group, end_object)), - forwarding_preference_(forwarding_preference) {} + : SubscribeWindow(FullSequence(start_group, start_object), + FullSequence(end_group, end_object)) {} - uint64_t subscribe_id() const { return subscribe_id_; } + SubscribeWindow(FullSequence start, std::optional end) + : start_(start), end_(end) {} bool InWindow(const FullSequence& seq) const; - - // Returns the stream to send |sequence| on, if already opened. - std::optional GetStreamForSequence( - FullSequence sequence) const; - - // Records what stream is being used for a track, group, or object depending - // on |forwarding_preference|. Triggers QUIC_BUG if already assigned. - void AddStream(uint64_t group_id, uint64_t object_id, - webtransport::StreamId stream_id); - - void RemoveStream(uint64_t group_id, uint64_t object_id); - bool HasEnd() const { return end_.has_value(); } - MoqtForwardingPreference forwarding_preference() const { - return forwarding_preference_; - } + FullSequence start() const { return start_; } + + // Updates the subscription window. Returns true if the update is valid (in + // MoQT, subscription windows are only allowed to shrink, not to expand). + bool UpdateStartEnd(FullSequence start, std::optional end); + + // Returns true if for a given forwarding preference, the specified sequence + // number might be the first object on a stream. + bool IsStreamProvokingObject(FullSequence sequence, + MoqtForwardingPreference preference) const; private: - // Converts an object sequence number into one that matches the way that - // stream IDs are being mapped. (See the comment for send_streams_ below.) - FullSequence SequenceToIndex(FullSequence sequence) const; - - const uint64_t subscribe_id_; - const FullSequence start_; - const std::optional end_ = std::nullopt; - // Store open streams for this subscription. If the forwarding preference is - // kTrack, there is one entry under sequence (0, 0). If kGroup, each entry is - // under (group, 0). If kObject, it's tracked under the full sequence. If - // kDatagram, the map is empty. - absl::flat_hash_map send_streams_; - // The forwarding preference for this track; informs how the streams are - // mapped. - const MoqtForwardingPreference forwarding_preference_; + FullSequence start_; + std::optional end_; }; -// Class to keep track of the sequence number blocks to which a peer is -// subscribed. -class QUICHE_EXPORT MoqtSubscribeWindows { +// ReducedSequenceIndex represents an index object such that if two sequence +// numbers are mapped to the same stream, they will be mapped to the same index. +class ReducedSequenceIndex { public: - MoqtSubscribeWindows(MoqtForwardingPreference forwarding_preference) - : forwarding_preference_(forwarding_preference) {} + ReducedSequenceIndex(FullSequence sequence, + MoqtForwardingPreference preference); - // Returns a vector of subscribe IDs that apply to the object. They will be in - // reverse order of the AddWindow calls. - std::vector SequenceIsSubscribed(FullSequence sequence); - - // |start_group| and |start_object| must be absolute sequence numbers. An - // optimization could consolidate overlapping subscribe windows. - void AddWindow(uint64_t subscribe_id, uint64_t start_group, - uint64_t start_object) { - windows_.emplace(subscribe_id, - SubscribeWindow(subscribe_id, forwarding_preference_, - start_group, start_object)); + bool operator==(const ReducedSequenceIndex& other) const { + return sequence_ == other.sequence_; } - void AddWindow(uint64_t subscribe_id, uint64_t start_group, - uint64_t start_object, uint64_t end_group, - uint64_t end_object) { - windows_.emplace( - subscribe_id, - SubscribeWindow(subscribe_id, forwarding_preference_, start_group, - start_object, end_group, end_object)); + bool operator!=(const ReducedSequenceIndex& other) const { + return sequence_ != other.sequence_; } - void RemoveWindow(uint64_t subscribe_id) { windows_.erase(subscribe_id); } - bool IsEmpty() const { return windows_.empty(); } - - SubscribeWindow* GetWindow(uint64_t subscribe_id) { - auto it = windows_.find(subscribe_id); - if (it == windows_.end()) { - return nullptr; - } - return &it->second; + template + friend H AbslHashValue(H h, const ReducedSequenceIndex& m) { + return H::combine(std::move(h), m.sequence_); } private: - // Indexed by Subscribe ID. - absl::node_hash_map windows_; - const MoqtForwardingPreference forwarding_preference_; + FullSequence sequence_; +}; + +// A map of outgoing data streams indexed by object sequence numbers. +class QUICHE_EXPORT SendStreamMap { + public: + explicit SendStreamMap(MoqtForwardingPreference forwarding_preference) + : forwarding_preference_(forwarding_preference) {} + + std::optional GetStreamForSequence( + FullSequence sequence) const; + void AddStream(FullSequence sequence, webtransport::StreamId stream_id); + void RemoveStream(FullSequence sequence, webtransport::StreamId stream_id); + std::vector GetAllStreams() const; + + private: + absl::flat_hash_map + send_streams_; + MoqtForwardingPreference forwarding_preference_; }; } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.cc new file mode 100644 index 0000000000..ee85664de3 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.cc @@ -0,0 +1,22 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file + +#include "quiche/quic/moqt/moqt_track.h" + +#include + +#include "quiche/quic/moqt/moqt_messages.h" + +namespace moqt { + +bool RemoteTrack::CheckForwardingPreference( + MoqtForwardingPreference preference) { + if (forwarding_preference_.has_value()) { + return forwarding_preference_.value() == preference; + } + forwarding_preference_ = preference; + return true; +} + +} // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.h index 5f2957a247..37636b76eb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.h @@ -7,118 +7,13 @@ #include #include -#include -#include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "quiche/quic/moqt/moqt_messages.h" -#include "quiche/quic/moqt/moqt_subscribe_windows.h" -#include "quiche/common/quiche_callbacks.h" +#include "quiche/quic/moqt/moqt_priority.h" namespace moqt { -// A track to which the peer might subscribe. -class LocalTrack { - public: - class Visitor { - public: - virtual ~Visitor() = default; - - using PublishPastObjectsCallback = quiche::SingleUseCallback; - - // Requests that application re-publish objects from {start_group, - // start_object} to the latest object. If the return value is nullopt, the - // subscribe is valid and the application will deliver the object and - // the session will send SUBSCRIBE_OK. If the return has a value, the value - // is the error message (the session will send SUBSCRIBE_ERROR). Via this - // API, the application decides if a partially fulfillable - // SUBSCRIBE results in an error or not. - virtual absl::StatusOr OnSubscribeForPast( - const SubscribeWindow& window) = 0; - }; - // |visitor| must not be nullptr. - LocalTrack(const FullTrackName& full_track_name, - MoqtForwardingPreference forwarding_preference, Visitor* visitor) - : full_track_name_(full_track_name), - forwarding_preference_(forwarding_preference), - windows_(forwarding_preference), - visitor_(visitor) {} - // Creates a LocalTrack that does not start at sequence (0,0) - LocalTrack(const FullTrackName& full_track_name, - MoqtForwardingPreference forwarding_preference, Visitor* visitor, - FullSequence next_sequence) - : full_track_name_(full_track_name), - forwarding_preference_(forwarding_preference), - windows_(forwarding_preference), - next_sequence_(next_sequence), - visitor_(visitor) {} - - const FullTrackName& full_track_name() const { return full_track_name_; } - - std::optional track_alias() const { return track_alias_; } - void set_track_alias(uint64_t track_alias) { track_alias_ = track_alias; } - - Visitor* visitor() { return visitor_; } - - // Returns the subscribe windows that want the object defined by (|group|, - // |object|). - std::vector ShouldSend(FullSequence sequence) { - return windows_.SequenceIsSubscribed(sequence); - } - - void AddWindow(uint64_t subscribe_id, uint64_t start_group, - uint64_t start_object) { - windows_.AddWindow(subscribe_id, start_group, start_object); - } - - void AddWindow(uint64_t subscribe_id, uint64_t start_group, - uint64_t start_object, uint64_t end_group, - uint64_t end_object) { - windows_.AddWindow(subscribe_id, start_group, start_object, end_group, - end_object); - } - - void DeleteWindow(uint64_t subscribe_id) { - windows_.RemoveWindow(subscribe_id); - } - - // Returns the largest observed sequence, but increments the object sequence - // by one. - const FullSequence& next_sequence() const { return next_sequence_; } - - // Updates next_sequence_ if |sequence| is larger. - void SentSequence(FullSequence sequence) { - if (next_sequence_ <= sequence) { - next_sequence_ = {sequence.group, sequence.object + 1}; - } - } - - bool HasSubscriber() const { return !windows_.IsEmpty(); } - - SubscribeWindow* GetWindow(uint64_t subscribe_id) { - return windows_.GetWindow(subscribe_id); - } - - MoqtForwardingPreference forwarding_preference() const { - return forwarding_preference_; - } - - private: - // This only needs to track subscriptions to current and future objects; - // requests for objects in the past are forwarded to the application. - const FullTrackName full_track_name_; - // The forwarding preference for the track. - MoqtForwardingPreference forwarding_preference_; - // Let the first SUBSCRIBE determine the track alias. - std::optional track_alias_; - // The sequence numbers from this track to which the peer is subscribed. - MoqtSubscribeWindows windows_; - // By recording the highest observed sequence number, MoQT can interpret - // relative sequence numbers in SUBSCRIBEs. - FullSequence next_sequence_ = {0, 0}; - Visitor* visitor_; -}; - // A track on the peer to which the session has subscribed. class RemoteTrack { public: @@ -133,7 +28,8 @@ class RemoteTrack { std::optional error_reason_phrase) = 0; virtual void OnObjectFragment( const FullTrackName& full_track_name, uint64_t group_sequence, - uint64_t object_sequence, uint64_t object_send_order, + uint64_t object_sequence, MoqtPriority publisher_priority, + MoqtObjectStatus object_status, MoqtForwardingPreference forwarding_preference, absl::string_view object, bool end_of_message) = 0; // TODO(martinduke): Add final sequence numbers @@ -154,13 +50,7 @@ class RemoteTrack { // forwarding preference to the value indicated by the incoming encoding. // Otherwise, returns true if the incoming object does not violate the rule // that the preference is consistent. - bool CheckForwardingPreference(MoqtForwardingPreference preference) { - if (forwarding_preference_.has_value()) { - return forwarding_preference_.value() == preference; - } - forwarding_preference_ = preference; - return true; - } + bool CheckForwardingPreference(MoqtForwardingPreference preference); private: // TODO: There is no accounting for the number of outstanding subscribes, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_simulator_harness.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_simulator_harness.cc new file mode 100644 index 0000000000..20b42ee72b --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_simulator_harness.cc @@ -0,0 +1,73 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "quiche/quic/moqt/test_tools/moqt_simulator_harness.h" + +#include +#include + +#include "quiche/quic/core/crypto/quic_compressed_certs_cache.h" +#include "quiche/quic/core/crypto/quic_crypto_server_config.h" +#include "quiche/quic/core/crypto/quic_random.h" +#include "quiche/quic/core/quic_generic_session.h" +#include "quiche/quic/core/quic_types.h" +#include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_session.h" +#include "quiche/quic/test_tools/crypto_test_utils.h" +#include "quiche/quic/test_tools/simulator/simulator.h" +#include "quiche/quic/test_tools/simulator/test_harness.h" + +namespace moqt::test { + +MoqtClientEndpoint::MoqtClientEndpoint(quic::simulator::Simulator* simulator, + const std::string& name, + const std::string& peer_name, + MoqtVersion version) + : QuicEndpointWithConnection(simulator, name, peer_name, + quic::Perspective::IS_CLIENT, + quic::GetQuicVersionsForGenericSession()), + crypto_config_(quic::test::crypto_test_utils::ProofVerifierForTesting()), + quic_session_(connection_.get(), false, nullptr, quic::QuicConfig(), + "test.example.com", 443, "moqt", &session_, + /*visitor_owned=*/false, nullptr, &crypto_config_), + session_( + &quic_session_, + MoqtSessionParameters{.version = version, + .perspective = quic::Perspective::IS_CLIENT, + .using_webtrans = false, + .path = "", + .deliver_partial_objects = false}, + MoqtSessionCallbacks()) { + quic_session_.Initialize(); +} + +MoqtServerEndpoint::MoqtServerEndpoint(quic::simulator::Simulator* simulator, + const std::string& name, + const std::string& peer_name, + MoqtVersion version) + : QuicEndpointWithConnection(simulator, name, peer_name, + quic::Perspective::IS_SERVER, + quic::GetQuicVersionsForGenericSession()), + compressed_certs_cache_( + quic::QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), + crypto_config_(quic::QuicCryptoServerConfig::TESTING, + quic::QuicRandom::GetInstance(), + quic::test::crypto_test_utils::ProofSourceForTesting(), + quic::KeyExchangeSource::Default()), + quic_session_(connection_.get(), false, nullptr, quic::QuicConfig(), + "moqt", &session_, + /*visitor_owned=*/false, nullptr, &crypto_config_, + &compressed_certs_cache_), + session_( + &quic_session_, + MoqtSessionParameters{.version = version, + .perspective = quic::Perspective::IS_SERVER, + .using_webtrans = false, + .path = "", + .deliver_partial_objects = false}, + MoqtSessionCallbacks()) { + quic_session_.Initialize(); +} + +} // namespace moqt::test diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_simulator_harness.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_simulator_harness.h new file mode 100644 index 0000000000..9b84bb85ee --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_simulator_harness.h @@ -0,0 +1,56 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef QUICHE_QUIC_MOQT_TEST_TOOLS_MOQT_SIMULATOR_HARNESS_H_ +#define QUICHE_QUIC_MOQT_TEST_TOOLS_MOQT_SIMULATOR_HARNESS_H_ + +#include + +#include "quiche/quic/core/crypto/quic_compressed_certs_cache.h" +#include "quiche/quic/core/crypto/quic_crypto_client_config.h" +#include "quiche/quic/core/crypto/quic_crypto_server_config.h" +#include "quiche/quic/core/quic_generic_session.h" +#include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_session.h" +#include "quiche/quic/test_tools/simulator/simulator.h" +#include "quiche/quic/test_tools/simulator/test_harness.h" + +namespace moqt::test { + +// Places a MoQT-over-raw-QUIC client within a network simulation. +class MoqtClientEndpoint : public quic::simulator::QuicEndpointWithConnection { + public: + MoqtClientEndpoint(quic::simulator::Simulator* simulator, + const std::string& name, const std::string& peer_name, + MoqtVersion version); + + MoqtSession* session() { return &session_; } + quic::QuicGenericClientSession* quic_session() { return &quic_session_; } + + private: + quic::QuicCryptoClientConfig crypto_config_; + quic::QuicGenericClientSession quic_session_; + MoqtSession session_; +}; + +// Places a MoQT-over-raw-QUIC server within a network simulation. +class MoqtServerEndpoint : public quic::simulator::QuicEndpointWithConnection { + public: + MoqtServerEndpoint(quic::simulator::Simulator* simulator, + const std::string& name, const std::string& peer_name, + MoqtVersion version); + + MoqtSession* session() { return &session_; } + quic::QuicGenericServerSession* quic_session() { return &quic_session_; } + + private: + quic::QuicCompressedCertsCache compressed_certs_cache_; + quic::QuicCryptoServerConfig crypto_config_; + quic::QuicGenericServerSession quic_session_; + MoqtSession session_; +}; + +} // namespace moqt::test + +#endif // QUICHE_QUIC_MOQT_TEST_TOOLS_MOQT_SIMULATOR_HARNESS_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_test_message.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_test_message.h index 98dee0f05b..91219f6823 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_test_message.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_test_message.h @@ -18,8 +18,8 @@ #include "quiche/quic/core/quic_data_writer.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/quic/platform/api/quic_logging.h" -#include "quiche/quic/platform/api/quic_test.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/quiche_endian.h" @@ -36,9 +36,10 @@ class QUICHE_NO_EXPORT TestMessageBase { typedef absl::variant + MoqtUnsubscribe, MoqtSubscribeDone, MoqtSubscribeUpdate, + MoqtAnnounce, MoqtAnnounceOk, MoqtAnnounceError, + MoqtAnnounceCancel, MoqtTrackStatusRequest, + MoqtUnannounce, MoqtTrackStatus, MoqtGoAway> MessageStructuredData; // The total actual size of the message. @@ -135,8 +136,12 @@ class QUICHE_NO_EXPORT ObjectMessage : public TestMessageBase { QUIC_LOG(INFO) << "OBJECT Object Sequence mismatch"; return false; } - if (cast.object_send_order != object_.object_send_order) { - QUIC_LOG(INFO) << "OBJECT Object Send Order mismatch"; + if (cast.publisher_priority != object_.publisher_priority) { + QUIC_LOG(INFO) << "OBJECT Publisher Priority mismatch"; + return false; + } + if (cast.object_status != object_.object_status) { + QUIC_LOG(INFO) << "OBJECT Object Status mismatch"; return false; } if (cast.forwarding_preference != object_.forwarding_preference) { @@ -160,7 +165,8 @@ class QUICHE_NO_EXPORT ObjectMessage : public TestMessageBase { /*track_alias=*/4, /*group_id*/ 5, /*object_id=*/6, - /*object_send_order=*/7, + /*publisher_priority=*/7, + /*object_status=*/MoqtObjectStatus::kNormal, /*forwarding_preference=*/MoqtForwardingPreference::kTrack, /*payload_length=*/std::nullopt, }; @@ -173,14 +179,12 @@ class QUICHE_NO_EXPORT ObjectStreamMessage : public ObjectMessage { object_.forwarding_preference = MoqtForwardingPreference::kObject; } - void ExpandVarints() override { - ExpandVarintsImpl("vvvvvv"); // first six fields are varints - } + void ExpandVarints() override { ExpandVarintsImpl("vvvvv-v---"); } private: - uint8_t raw_packet_[9] = { - 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, // varints - 0x66, 0x6f, 0x6f, // payload = "foo" + uint8_t raw_packet_[10] = { + 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, // varints + 0x66, 0x6f, 0x6f, // payload = "foo" }; }; @@ -191,14 +195,12 @@ class QUICHE_NO_EXPORT ObjectDatagramMessage : public ObjectMessage { object_.forwarding_preference = MoqtForwardingPreference::kDatagram; } - void ExpandVarints() override { - ExpandVarintsImpl("vvvvvv"); // first six fields are varints - } + void ExpandVarints() override { ExpandVarintsImpl("vvvvv-v---"); } private: - uint8_t raw_packet_[9] = { - 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, // varints - 0x66, 0x6f, 0x6f, // payload = "foo" + uint8_t raw_packet_[10] = { + 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, // varints + 0x66, 0x6f, 0x6f, // payload = "foo" }; }; @@ -213,9 +215,7 @@ class QUICHE_NO_EXPORT StreamHeaderTrackMessage : public ObjectMessage { object_.payload_length = 3; } - void ExpandVarints() override { - ExpandVarintsImpl("--vvvvvv"); // six one-byte varints - } + void ExpandVarints() override { ExpandVarintsImpl("--vv-vvv"); } private: // Some tests check that a FIN sent at the halfway point of a message results @@ -246,7 +246,8 @@ class QUICHE_NO_EXPORT StreamMiddlerTrackMessage : public ObjectMessage { private: uint8_t raw_packet_[6] = { - 0x09, 0x0a, 0x03, 0x62, 0x61, 0x72, // object middler; payload = "bar" + 0x09, 0x0a, // object middler + 0x03, 0x62, 0x61, 0x72, // payload = "bar" }; }; @@ -259,9 +260,7 @@ class QUICHE_NO_EXPORT StreamHeaderGroupMessage : public ObjectMessage { object_.payload_length = 3; } - void ExpandVarints() override { - ExpandVarintsImpl("--vvvvvv"); // six one-byte varints - } + void ExpandVarints() override { ExpandVarintsImpl("--vvv-vv"); } private: uint8_t raw_packet_[11] = { @@ -423,6 +422,14 @@ class QUICHE_NO_EXPORT SubscribeMessage : public TestMessageBase { QUIC_LOG(INFO) << "SUBSCRIBE track name mismatch"; return false; } + if (cast.subscriber_priority != subscribe_.subscriber_priority) { + QUIC_LOG(INFO) << "SUBSCRIBE subscriber priority mismatch"; + return false; + } + if (cast.group_order != subscribe_.group_order) { + QUIC_LOG(INFO) << "SUBSCRIBE group order mismatch"; + return false; + } if (cast.start_group != subscribe_.start_group) { QUIC_LOG(INFO) << "SUBSCRIBE start group mismatch"; return false; @@ -447,7 +454,7 @@ class QUICHE_NO_EXPORT SubscribeMessage : public TestMessageBase { } void ExpandVarints() override { - ExpandVarintsImpl("vvvv---v----vvvvvvvvv"); + ExpandVarintsImpl("vvvv---v------vvvvvv---"); } MessageStructuredData structured_data() const override { @@ -455,33 +462,22 @@ class QUICHE_NO_EXPORT SubscribeMessage : public TestMessageBase { } private: - uint8_t raw_packet_[24] = { - 0x03, - 0x01, - 0x02, // id and alias - 0x03, - 0x66, - 0x6f, - 0x6f, // track_namespace = "foo" - 0x04, - 0x61, - 0x62, - 0x63, - 0x64, // track_name = "abcd" - 0x02, - 0x04, // start_group = 4 (relative previous) - 0x01, - 0x01, // start_object = 1 (absolute) - 0x00, // end_group = none - 0x00, // end_object = none - // TODO(martinduke): figure out what to do about the missing num - // parameters field. - 0x01, // 1 parameter - 0x02, - 0x03, - 0x62, - 0x61, - 0x72, // authorization_info = "bar" + uint8_t raw_packet_[23] = { + 0x03, 0x01, + 0x02, // id and alias + 0x03, 0x66, 0x6f, + 0x6f, // track_namespace = "foo" + 0x04, 0x61, 0x62, 0x63, + 0x64, // track_name = "abcd" + 0x20, // subscriber priority = 0x20 + 0x02, // group order = descending + 0x03, // Filter type: Absolute Start + 0x04, // start_group = 4 (relative previous) + 0x01, // start_object = 1 (absolute) + // No EndGroup or EndObject + 0x01, // 1 parameter + 0x02, 0x03, 0x62, 0x61, + 0x72, // authorization_info = "bar" }; MoqtSubscribe subscribe_ = { @@ -489,8 +485,10 @@ class QUICHE_NO_EXPORT SubscribeMessage : public TestMessageBase { /*track_alias=*/2, /*track_namespace=*/"foo", /*track_name=*/"abcd", - /*start_group=*/MoqtSubscribeLocation(false, (int64_t)(-4)), - /*start_object=*/MoqtSubscribeLocation(true, (uint64_t)1), + /*subscriber_priority=*/0x20, + /*group_order=*/MoqtDeliveryOrder::kDescending, + /*start_group=*/4, + /*start_object=*/1, /*end_group=*/std::nullopt, /*end_object=*/std::nullopt, /*authorization_info=*/"bar", @@ -513,6 +511,10 @@ class QUICHE_NO_EXPORT SubscribeOkMessage : public TestMessageBase { QUIC_LOG(INFO) << "SUBSCRIBE OK expiration mismatch"; return false; } + if (cast.group_order != subscribe_ok_.group_order) { + QUIC_LOG(INFO) << "SUBSCRIBE OK group order mismatch"; + return false; + } if (cast.largest_id != subscribe_ok_.largest_id) { QUIC_LOG(INFO) << "SUBSCRIBE OK largest ID mismatch"; return false; @@ -520,26 +522,33 @@ class QUICHE_NO_EXPORT SubscribeOkMessage : public TestMessageBase { return true; } - void ExpandVarints() override { ExpandVarintsImpl("vvv-vv"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv--vv"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_ok_); } void SetInvalidContentExists() { - raw_packet_[3] = 0x02; + raw_packet_[4] = 0x02; + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + + void SetInvalidDeliveryOrder() { + raw_packet_[3] = 0x10; SetWireImage(raw_packet_, sizeof(raw_packet_)); } private: - uint8_t raw_packet_[6] = { + uint8_t raw_packet_[7] = { 0x04, 0x01, 0x03, // subscribe_id = 1, expires = 3 + 0x02, // delivery_order = 2, 0x01, 0x0c, 0x14, // largest_group_id = 12, largest_object_id = 20, }; MoqtSubscribeOk subscribe_ok_ = { /*subscribe_id=*/1, /*expires=*/quic::QuicTimeDelta::FromMilliseconds(3), + /*group_order=*/MoqtDeliveryOrder::kDescending, /*largest_id=*/FullSequence(12, 20), }; }; @@ -671,12 +680,77 @@ class QUICHE_NO_EXPORT SubscribeDoneMessage : public TestMessageBase { MoqtSubscribeDone subscribe_done_ = { /*subscribe_id=*/2, - /*error_code=*/3, + /*error_code=*/SubscribeDoneCode::kTrackEnded, /*reason_phrase=*/"hi", /*final_id=*/FullSequence(8, 12), }; }; +class QUICHE_NO_EXPORT SubscribeUpdateMessage : public TestMessageBase { + public: + SubscribeUpdateMessage() + : TestMessageBase(MoqtMessageType::kSubscribeUpdate) { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.subscribe_id != subscribe_update_.subscribe_id) { + QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE subscribe ID mismatch"; + return false; + } + if (cast.start_group != subscribe_update_.start_group) { + QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE start group mismatch"; + return false; + } + if (cast.start_object != subscribe_update_.start_object) { + QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE start group mismatch"; + return false; + } + if (cast.end_group != subscribe_update_.end_group) { + QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE end group mismatch"; + return false; + } + if (cast.end_object != subscribe_update_.end_object) { + QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE end group mismatch"; + return false; + } + if (cast.subscriber_priority != subscribe_update_.subscriber_priority) { + QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE subscriber priority mismatch"; + return false; + } + if (cast.authorization_info != subscribe_update_.authorization_info) { + QUIC_LOG(INFO) << "SUBSCRIBE_UPDATE authorization info mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("vvvvvv-vvv---"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(subscribe_update_); + } + + private: + uint8_t raw_packet_[13] = { + 0x02, 0x02, 0x03, 0x01, 0x05, 0x06, // start and end sequences + 0xaa, // subscriber_priority + 0x01, // 1 parameter + 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" + }; + + MoqtSubscribeUpdate subscribe_update_ = { + /*subscribe_id=*/2, + /*start_group=*/3, + /*start_object=*/1, + /*end_group=*/4, + /*end_object=*/5, + /*subscriber_priority=*/0xaa, + /*authorization_info=*/"bar", + }; +}; + class QUICHE_NO_EXPORT AnnounceMessage : public TestMessageBase { public: AnnounceMessage() : TestMessageBase(MoqtMessageType::kAnnounce) { @@ -789,6 +863,75 @@ class QUICHE_NO_EXPORT AnnounceErrorMessage : public TestMessageBase { }; }; +class QUICHE_NO_EXPORT AnnounceCancelMessage : public TestMessageBase { + public: + AnnounceCancelMessage() : TestMessageBase(MoqtMessageType::kAnnounceCancel) { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.track_namespace != announce_cancel_.track_namespace) { + QUIC_LOG(INFO) << "ANNOUNCE CANCEL track namespace mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("vv---"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(announce_cancel_); + } + + private: + uint8_t raw_packet_[5] = { + 0x0c, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + }; + + MoqtAnnounceCancel announce_cancel_ = { + /*track_namespace=*/"foo", + }; +}; + +class QUICHE_NO_EXPORT TrackStatusRequestMessage : public TestMessageBase { + public: + TrackStatusRequestMessage() + : TestMessageBase(MoqtMessageType::kTrackStatusRequest) { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.track_namespace != track_status_request_.track_namespace) { + QUIC_LOG(INFO) << "TRACK STATUS REQUEST track namespace mismatch"; + return false; + } + if (cast.track_name != track_status_request_.track_name) { + QUIC_LOG(INFO) << "TRACK STATUS REQUEST track name mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("vv---v----"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(track_status_request_); + } + + private: + uint8_t raw_packet_[10] = { + 0x0d, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + }; + + MoqtTrackStatusRequest track_status_request_ = { + /*track_namespace=*/"foo", + /*track_name=*/"abcd", + }; +}; + class QUICHE_NO_EXPORT UnannounceMessage : public TestMessageBase { public: UnannounceMessage() : TestMessageBase(MoqtMessageType::kUnannounce) { @@ -820,6 +963,59 @@ class QUICHE_NO_EXPORT UnannounceMessage : public TestMessageBase { }; }; +class QUICHE_NO_EXPORT TrackStatusMessage : public TestMessageBase { + public: + TrackStatusMessage() : TestMessageBase(MoqtMessageType::kTrackStatus) { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + } + + bool EqualFieldValues(MessageStructuredData& values) const override { + auto cast = std::get(values); + if (cast.track_namespace != track_status_.track_namespace) { + QUIC_LOG(INFO) << "TRACK STATUS track namespace mismatch"; + return false; + } + if (cast.track_name != track_status_.track_name) { + QUIC_LOG(INFO) << "TRACK STATUS track name mismatch"; + return false; + } + if (cast.status_code != track_status_.status_code) { + QUIC_LOG(INFO) << "TRACK STATUS code mismatch"; + return false; + } + if (cast.last_group != track_status_.last_group) { + QUIC_LOG(INFO) << "TRACK STATUS last group mismatch"; + return false; + } + if (cast.last_object != track_status_.last_object) { + QUIC_LOG(INFO) << "TRACK STATUS last object mismatch"; + return false; + } + return true; + } + + void ExpandVarints() override { ExpandVarintsImpl("vv---v----vvv"); } + + MessageStructuredData structured_data() const override { + return TestMessageBase::MessageStructuredData(track_status_); + } + + private: + uint8_t raw_packet_[13] = { + 0x0e, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" + 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" + 0x00, 0x0c, 0x14, // status, last_group, last_object + }; + + MoqtTrackStatus track_status_ = { + /*track_namespace=*/"foo", + /*track_name=*/"abcd", + /*status_code=*/MoqtTrackStatusCode::kInProgress, + /*last_group=*/12, + /*last_object=*/20, + }; +}; + class QUICHE_NO_EXPORT GoAwayMessage : public TestMessageBase { public: GoAwayMessage() : TestMessageBase(MoqtMessageType::kGoAway) { @@ -869,14 +1065,22 @@ static inline std::unique_ptr CreateTestMessage( return std::make_unique(); case MoqtMessageType::kSubscribeDone: return std::make_unique(); + case MoqtMessageType::kSubscribeUpdate: + return std::make_unique(); case MoqtMessageType::kAnnounce: return std::make_unique(); case MoqtMessageType::kAnnounceOk: return std::make_unique(); case MoqtMessageType::kAnnounceError: return std::make_unique(); + case MoqtMessageType::kAnnounceCancel: + return std::make_unique(); + case MoqtMessageType::kTrackStatusRequest: + return std::make_unique(); case MoqtMessageType::kUnannounce: return std::make_unique(); + case MoqtMessageType::kTrackStatus: + return std::make_unique(); case MoqtMessageType::kGoAway: return std::make_unique(); case MoqtMessageType::kClientSetup: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client_bin.cc index d557137455..5792b87f3f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client_bin.cc @@ -26,6 +26,8 @@ #include "quiche/quic/core/quic_server_id.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_outgoing_queue.h" +#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/quic/moqt/moqt_session.h" #include "quiche/quic/moqt/moqt_track.h" #include "quiche/quic/moqt/tools/moqt_client.h" @@ -37,6 +39,9 @@ #include "quiche/quic/tools/quic_url.h" #include "quiche/common/platform/api/quiche_command_line_flags.h" #include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/platform/api/quiche_mem_slice.h" +#include "quiche/common/quiche_buffer_allocator.h" +#include "quiche/common/simple_buffer_allocator.h" DEFINE_QUICHE_COMMAND_LINE_FLAG( bool, disable_certificate_verification, false, @@ -105,15 +110,15 @@ class ChatClient { session_is_open_ = false; return; } - session_->PublishObject(my_track_name_, next_sequence_.group++, - next_sequence_.object, /*object_send_order=*/0, - input_message, true); + quiche::QuicheMemSlice message_slice(quiche::QuicheBuffer::Copy( + quiche::SimpleBufferAllocator::Get(), input_message)); + queue_->AddObject(std::move(message_slice), /*key=*/true); } bool session_is_open() const { return session_is_open_; } bool is_syncing() const { return !catalog_group_.has_value() || subscribes_to_make_ > 0 || - !session_->HasSubscribers(my_track_name_); + (queue_ != nullptr && queue_->HasSubscribers()); } void RunEventLoop() { @@ -129,7 +134,9 @@ class ChatClient { class QUICHE_EXPORT RemoteTrackVisitor : public moqt::RemoteTrack::Visitor { public: - RemoteTrackVisitor(ChatClient* client) : client_(client) {} + RemoteTrackVisitor(ChatClient* client) : client_(client) { + cli_ = client->cli_.get(); + } void OnReply(const moqt::FullTrackName& full_track_name, std::optional reason_phrase) override { @@ -149,7 +156,8 @@ class ChatClient { void OnObjectFragment( const moqt::FullTrackName& full_track_name, uint64_t group_sequence, - uint64_t object_sequence, uint64_t /*object_send_order*/, + uint64_t object_sequence, moqt::MoqtPriority /*publisher_priority*/, + moqt::MoqtObjectStatus /*status*/, moqt::MoqtForwardingPreference /*forwarding_preference*/, absl::string_view object, bool end_of_message) override { if (!end_of_message) { @@ -194,10 +202,9 @@ class ChatClient { std::cout << "Failed to connect.\n"; return false; } - // By not sending a visitor, the application will not fulfill subscriptions - // to previous objects. - session_->AddLocalTrack(my_track_name_, - moqt::MoqtForwardingPreference::kObject, nullptr); + queue_ = std::make_shared( + client_->session(), my_track_name_, + moqt::MoqtForwardingPreference::kObject); moqt::MoqtOutgoingAnnounceCallback announce_callback = [&](absl::string_view track_namespace, std::optional reason) { @@ -293,9 +300,9 @@ class ChatClient { auto new_user = other_users_.emplace( std::make_pair(user, ChatUser(to_subscribe, group_sequence))); ChatUser& user_record = new_user.first->second; - session_->SubscribeRelative(user_record.full_track_name.track_namespace, - user_record.full_track_name.track_name, 0, - 0, visitor); + session_->SubscribeCurrentGroup( + user_record.full_track_name.track_namespace, + user_record.full_track_name.track_name, visitor); subscribes_to_make_++; } else { if (it->second.from_group == group_sequence) { @@ -346,7 +353,7 @@ class ChatClient { std::unique_ptr remote_track_visitor_; // Handling incoming and outgoing messages - moqt::FullSequence next_sequence_ = {0, 0}; + std::shared_ptr queue_; // Used when chat output goes to file. std::ofstream output_file_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_client.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_client.cc index 4920c16a11..2464c73e2e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_client.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_client.cc @@ -22,8 +22,8 @@ #include "quiche/quic/tools/quic_default_client.h" #include "quiche/quic/tools/quic_event_loop_tools.h" #include "quiche/quic/tools/quic_name_lookup.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/http2_header_block.h" namespace moqt { @@ -75,7 +75,7 @@ absl::Status MoqtClient::ConnectInner(std::string path, } spdy_client_.set_store_response(true); - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":scheme"] = "https"; headers[":authority"] = spdy_client_.server_id().host(); headers[":path"] = path; @@ -89,7 +89,7 @@ absl::Status MoqtClient::ConnectInner(std::string path, } MoqtSessionParameters parameters; - parameters.version = MoqtVersion::kDraft03; + parameters.version = MoqtVersion::kDraft05; parameters.perspective = quic::Perspective::IS_CLIENT, parameters.using_webtrans = true; parameters.path = ""; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_ingestion_server_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_ingestion_server_bin.cc index c7d465ce49..01d010dcbd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_ingestion_server_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_ingestion_server_bin.cc @@ -29,6 +29,7 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_priority.h" #include "quiche/quic/moqt/moqt_session.h" #include "quiche/quic/moqt/moqt_track.h" #include "quiche/quic/moqt/tools/moqt_server.h" @@ -166,7 +167,8 @@ class MoqtIngestionHandler { void OnObjectFragment(const FullTrackName& full_track_name, uint64_t group_sequence, uint64_t object_sequence, - uint64_t /*object_send_order*/, + MoqtPriority /*publisher_priority*/, + MoqtObjectStatus /*status*/, MoqtForwardingPreference /*forwarding_preference*/, absl::string_view object, bool /*end_of_message*/) override { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_mock_visitor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_mock_visitor.h index aaf301c5f3..a5475a3ed4 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_mock_visitor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_mock_visitor.h @@ -7,14 +7,17 @@ #include #include +#include +#include #include "absl/status/statusor.h" #include "absl/strings/string_view.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_priority.h" +#include "quiche/quic/moqt/moqt_publisher.h" #include "quiche/quic/moqt/moqt_session.h" -#include "quiche/quic/moqt/moqt_subscribe_windows.h" #include "quiche/quic/moqt/moqt_track.h" -#include "quiche/quic/platform/api/quic_test.h" +#include "quiche/common/platform/api/quiche_test.h" namespace moqt::test { @@ -39,10 +42,33 @@ struct MockSessionCallbacks { } }; -class MockLocalTrackVisitor : public LocalTrack::Visitor { +class MockTrackPublisher : public MoqtTrackPublisher { public: - MOCK_METHOD(absl::StatusOr, OnSubscribeForPast, - (const SubscribeWindow& window), (override)); + explicit MockTrackPublisher(FullTrackName name) + : track_name_(std::move(name)) { + ON_CALL(*this, GetDeliveryOrder()) + .WillByDefault(testing::Return(MoqtDeliveryOrder::kAscending)); + } + const FullTrackName& GetTrackName() const override { return track_name_; } + + MOCK_METHOD(std::optional, GetCachedObject, + (FullSequence sequence), (const, override)); + MOCK_METHOD(std::vector, GetCachedObjectsInRange, + (FullSequence start, FullSequence end), (const, override)); + MOCK_METHOD(void, AddObjectListener, (MoqtObjectListener * listener), + (override)); + MOCK_METHOD(void, RemoveObjectListener, (MoqtObjectListener * listener), + (override)); + MOCK_METHOD(absl::StatusOr, GetTrackStatus, (), + (const, override)); + MOCK_METHOD(FullSequence, GetLargestSequence, (), (const, override)); + MOCK_METHOD(MoqtForwardingPreference, GetForwardingPreference, (), + (const, override)); + MOCK_METHOD(MoqtPriority, GetPublisherPriority, (), (const, override)); + MOCK_METHOD(MoqtDeliveryOrder, GetDeliveryOrder, (), (const, override)); + + private: + FullTrackName track_name_; }; class MockRemoteTrackVisitor : public RemoteTrack::Visitor { @@ -53,7 +79,8 @@ class MockRemoteTrackVisitor : public RemoteTrack::Visitor { (override)); MOCK_METHOD(void, OnObjectFragment, (const FullTrackName& full_track_name, uint64_t group_sequence, - uint64_t object_sequence, uint64_t object_send_order, + uint64_t object_sequence, MoqtPriority publisher_priority, + MoqtObjectStatus status, MoqtForwardingPreference forwarding_preference, absl::string_view object, bool end_of_message), (override)); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_server.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_server.cc index 9a609770ff..ac1748a5e2 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_server.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_server.cc @@ -33,7 +33,7 @@ quic::WebTransportRequestCallback CreateWebTransportCallback( parameters.perspective = quic::Perspective::IS_SERVER; parameters.path = path; parameters.using_webtrans = true; - parameters.version = MoqtVersion::kDraft03; + parameters.version = MoqtVersion::kDraft05; parameters.deliver_partial_objects = false; auto moqt_session = std::make_unique(session, parameters); std::move (*configurator)(moqt_session.get()); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_simulator_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_simulator_bin.cc new file mode 100644 index 0000000000..c3fb9c1acf --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_simulator_bin.cc @@ -0,0 +1,331 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// moqt_simulator simulates the behavior of MoQ Transport under various network +// conditions and application settings. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "absl/algorithm/container.h" +#include "absl/container/flat_hash_map.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "quiche/quic/core/crypto/quic_random.h" +#include "quiche/quic/core/quic_bandwidth.h" +#include "quiche/quic/core/quic_clock.h" +#include "quiche/quic/core/quic_time.h" +#include "quiche/quic/core/quic_types.h" +#include "quiche/quic/moqt/moqt_known_track_publisher.h" +#include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/moqt/moqt_outgoing_queue.h" +#include "quiche/quic/moqt/moqt_priority.h" +#include "quiche/quic/moqt/moqt_session.h" +#include "quiche/quic/moqt/moqt_track.h" +#include "quiche/quic/moqt/test_tools/moqt_simulator_harness.h" +#include "quiche/quic/test_tools/simulator/actor.h" +#include "quiche/quic/test_tools/simulator/link.h" +#include "quiche/quic/test_tools/simulator/simulator.h" +#include "quiche/quic/test_tools/simulator/switch.h" +#include "quiche/common/platform/api/quiche_command_line_flags.h" +#include "quiche/common/platform/api/quiche_logging.h" +#include "quiche/common/platform/api/quiche_mem_slice.h" +#include "quiche/common/quiche_buffer_allocator.h" +#include "quiche/common/quiche_data_reader.h" +#include "quiche/common/quiche_data_writer.h" +#include "quiche/common/simple_buffer_allocator.h" + +namespace moqt::test { +namespace { + +using ::quiche::QuicheBuffer; +using ::quiche::QuicheMemSlice; + +using ::quic::QuicBandwidth; +using ::quic::QuicByteCount; +using ::quic::QuicClock; +using ::quic::QuicTime; +using ::quic::QuicTimeDelta; + +using ::quic::simulator::Simulator; + +// In the simulation, the server link is supposed to be the bottleneck, so this +// value just has to be sufficiently larger than the server link bandwidth. +constexpr QuicBandwidth kClientLinkBandwidth = + QuicBandwidth::FromBitsPerSecond(10.0e6); +constexpr MoqtVersion kMoqtVersion = MoqtVersion::kDraft05; + +// Track name used by the simulator. +FullTrackName TrackName() { return FullTrackName("test", "track"); } + +// Parameters describing the scenario being simulated. +struct SimulationParameters { + // Bottleneck bandwidth of the simulated scenario. + QuicBandwidth bandwidth = QuicBandwidth::FromBitsPerSecond(2.0e6); + // Intended RTT (as computed from propagation delay alone) between the client + // and the server. + QuicTimeDelta min_rtt = QuicTimeDelta::FromMilliseconds(20); + // The size of the network queue; if zero, assumed to be twice the BDP. + QuicByteCount network_queue_size = 0; + // Duration for which the simulation is run. + QuicTimeDelta duration = QuicTimeDelta::FromSeconds(60); + + // Number of frames in an individual group. + int keyframe_interval = 30 * 2; + // Number of frames generated per second. + int fps = 30; + // The ratio by which an I-frame is bigger than a P-frame. + float i_to_p_ratio = 2 / 1; + // The target bitrate of the data being exchanged. + QuicBandwidth bitrate = QuicBandwidth::FromBitsPerSecond(1.0e6); +}; + +// Generates test objects at a constant rate. The first eight bytes of every +// object generated is a timestamp, the rest is all zeroes. The first object in +// the group can be made bigger than the rest, to simulate the profile of real +// video bitstreams. +class ObjectGenerator : public quic::simulator::Actor { + public: + ObjectGenerator(Simulator* simulator, const std::string& actor_name, + MoqtSession* session, FullTrackName track_name, + int keyframe_interval, int fps, float i_to_p_ratio, + QuicBandwidth bitrate) + : Actor(simulator, actor_name), + queue_(std::make_shared( + session, track_name, MoqtForwardingPreference::kGroup)), + keyframe_interval_(keyframe_interval), + time_between_frames_(QuicTimeDelta::FromMicroseconds(1.0e6 / fps)) { + int p_frame_count = keyframe_interval - 1; + // Compute the frame sizes as a fraction of the total group size. + float i_frame_fraction = i_to_p_ratio / (i_to_p_ratio + p_frame_count); + float p_frame_fraction = 1.0 / (i_to_p_ratio + p_frame_count); + + QuicTimeDelta group_duration = + QuicTimeDelta::FromMicroseconds(1.0e6 * keyframe_interval / fps); + QuicByteCount group_byte_count = group_duration * bitrate; + i_frame_size_ = i_frame_fraction * group_byte_count; + p_frame_size_ = p_frame_fraction * group_byte_count; + QUICHE_CHECK_GE(i_frame_size_, 8u) << "Not enough space for a timestamp"; + QUICHE_CHECK_GE(p_frame_size_, 8u) << "Not enough space for a timestamp"; + } + + void Act() override { + ++frame_number_; + bool i_frame = (frame_number_ % keyframe_interval_) == 0; + size_t size = i_frame ? i_frame_size_ : p_frame_size_; + + QuicheBuffer buffer(quiche::SimpleBufferAllocator::Get(), size); + memset(buffer.data(), 0, buffer.size()); + quiche::QuicheDataWriter writer(size, buffer.data()); + bool success = writer.WriteUInt64(clock_->Now().ToDebuggingValue()); + QUICHE_CHECK(success); + + queue_->AddObject(QuicheMemSlice(std::move(buffer)), i_frame); + Schedule(clock_->Now() + time_between_frames_); + } + + void Start() { Schedule(clock_->Now()); } + void Stop() { Unschedule(); } + + std::shared_ptr queue() { return queue_; } + size_t total_objects_sent() const { return frame_number_ + 1; } + + private: + std::shared_ptr queue_; + int keyframe_interval_; + QuicTimeDelta time_between_frames_; + QuicByteCount i_frame_size_; + QuicByteCount p_frame_size_; + int frame_number_ = -1; +}; + +class ObjectReceiver : public RemoteTrack::Visitor { + public: + explicit ObjectReceiver(const QuicClock* clock) : clock_(clock) {} + + void OnReply(const FullTrackName& full_track_name, + std::optional error_reason_phrase) override { + QUICHE_CHECK(full_track_name == TrackName()); + QUICHE_CHECK(!error_reason_phrase.has_value()) << *error_reason_phrase; + } + + void OnObjectFragment(const FullTrackName& full_track_name, + uint64_t group_sequence, uint64_t object_sequence, + MoqtPriority /*publisher_priority*/, + MoqtObjectStatus /*status*/, + MoqtForwardingPreference /*forwarding_preference*/, + absl::string_view object, + bool end_of_message) override { + QUICHE_DCHECK(full_track_name == TrackName()); + + // Buffer and assemble partially available objects. + // TODO: this logic should be factored out. Also, this should take advantage + // of the fact that in the current MoQT, the object size is known in + // advance. + FullSequence sequence{group_sequence, object_sequence}; + if (!end_of_message) { + auto [it, unused] = partial_objects_.try_emplace(sequence); + it->second.append(object); + return; + } + auto it = partial_objects_.find(sequence); + if (it == partial_objects_.end()) { + OnFullObject(sequence, object); + return; + } + std::string full_object = std::move(it->second); + full_object.append(object); + partial_objects_.erase(it); + OnFullObject(sequence, full_object); + } + + void OnFullObject(FullSequence sequence, absl::string_view payload) { + QUICHE_CHECK_GE(payload.size(), 8u); + quiche::QuicheDataReader reader(payload); + uint64_t time_us; + reader.ReadUInt64(&time_us); + QuicTime time = QuicTime::Zero() + QuicTimeDelta::FromMicroseconds(time_us); + QuicTimeDelta delay = clock_->Now() - time; + QUICHE_CHECK_GT(delay, QuicTimeDelta::Zero()); + QUICHE_DCHECK(absl::c_all_of(reader.ReadRemainingPayload(), + [](char c) { return c == 0; })); + ++full_objects_received_; + } + + size_t full_objects_received() const { return full_objects_received_; } + + private: + const QuicClock* clock_ = nullptr; + // TODO: figure out when partial objects should be discarded. + absl::flat_hash_map partial_objects_; + + size_t full_objects_received_ = 0; +}; + +// Computes the size of the network queue on the switch. +constexpr QuicByteCount AdjustedQueueSize( + const SimulationParameters& parameters) { + if (parameters.network_queue_size > 0) { + return parameters.network_queue_size; + } + QuicByteCount bdp = parameters.bandwidth * parameters.min_rtt; + return 2 * bdp; +} + +// Simulates the performance of MoQT transfer under the specified network +// conditions. +class MoqtSimulator { + public: + explicit MoqtSimulator(const SimulationParameters& parameters) + : simulator_(quic::QuicRandom::GetInstance()), + client_endpoint_(&simulator_, "Client", "Server", kMoqtVersion), + server_endpoint_(&simulator_, "Server", "Client", kMoqtVersion), + switch_(&simulator_, "Switch", 8, AdjustedQueueSize(parameters)), + client_link_(&client_endpoint_, switch_.port(1), kClientLinkBandwidth, + parameters.min_rtt * 0.25), + server_link_(&server_endpoint_, switch_.port(2), parameters.bandwidth, + parameters.min_rtt * 0.25), + generator_(&simulator_, "Client generator", client_endpoint_.session(), + TrackName(), parameters.keyframe_interval, parameters.fps, + parameters.i_to_p_ratio, parameters.bitrate), + receiver_(simulator_.GetClock()), + parameters_(parameters) {} + + MoqtSession* client_session() { return client_endpoint_.session(); } + MoqtSession* server_session() { return server_endpoint_.session(); } + + std::string GetClientSessionCongestionControl() { + return quic::CongestionControlTypeToString( + client_endpoint_.quic_session() + ->connection() + ->sent_packet_manager() + .GetSendAlgorithm() + ->GetCongestionControlType()); + } + + // Runs the simulation and outputs the results to stdout. + void Run() { + // Timeout for establishing the connection. + constexpr QuicTimeDelta kConnectionTimeout = QuicTimeDelta::FromSeconds(1); + + // Perform the QUIC and the MoQT handshake. + client_session()->callbacks().session_established_callback = [this] { + client_established_ = true; + }; + server_session()->callbacks().session_established_callback = [this] { + server_established_ = true; + }; + client_endpoint_.quic_session()->CryptoConnect(); + simulator_.RunUntilOrTimeout( + [&]() { return client_established_ && server_established_; }, + kConnectionTimeout); + QUICHE_CHECK(client_established_) << "Client failed to establish session"; + QUICHE_CHECK(server_established_) << "Server failed to establish session"; + + // The simulation is started as follows. At t=0: + // (1) The server issues a subscribe request. + // (2) The client starts immediately generating data. At this point, the + // server does not yet have an active subscription, so the client has + // some catching up to do. + client_session()->set_publisher(&publisher_); + publisher_.Add(generator_.queue()); + generator_.Start(); + server_session()->SubscribeCurrentGroup(TrackName().track_namespace, + TrackName().track_name, &receiver_); + simulator_.RunFor(parameters_.duration); + + // At the end, we wait for eight RTTs until the connection settles down. + generator_.Stop(); + simulator_.RunFor(QuicTimeDelta( + 8 * client_endpoint_.quic_session()->GetSessionStats().smoothed_rtt)); + + std::cout << "Ran simulation for " << parameters_.duration << std::endl; + std::cout << "Congestion control used : " + << GetClientSessionCongestionControl() << std::endl; + std::cout << "Objects sent: " << generator_.total_objects_sent() + << std::endl; + std::cout << "Objects received: " << receiver_.full_objects_received() + << std::endl; + } + + private: + Simulator simulator_; + MoqtClientEndpoint client_endpoint_; + MoqtServerEndpoint server_endpoint_; + quic::simulator::Switch switch_; + quic::simulator::SymmetricLink client_link_; + quic::simulator::SymmetricLink server_link_; + MoqtKnownTrackPublisher publisher_; + ObjectGenerator generator_; + ObjectReceiver receiver_; + SimulationParameters parameters_; + + bool client_established_ = false; + bool server_established_ = false; +}; + +} // namespace +} // namespace moqt::test + +DEFINE_QUICHE_COMMAND_LINE_FLAG( + uint64_t, bandwidth, + moqt::test::SimulationParameters().bandwidth.ToKBitsPerSecond(), + "Bandwidth of the simulated link, in kilobits per second."); + +int main(int argc, char** argv) { + moqt::test::SimulationParameters parameters; + quiche::QuicheParseCommandLineFlags("moqt_simulator", argc, argv); + parameters.bandwidth = quic::QuicBandwidth::FromKBitsPerSecond( + quiche::GetQuicheCommandLineFlag(FLAGS_bandwidth)); + + moqt::test::MoqtSimulator simulator(parameters); + simulator.Run(); + return 0; +} diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_controller.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_controller.cc index 5169a77ab7..97a6361179 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_controller.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/bonnet/tun_device_controller.cc @@ -9,6 +9,7 @@ #include #include +#include "absl/flags/flag.h" #include "absl/time/clock.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/qbone/qbone_constants.h" @@ -19,9 +20,8 @@ ABSL_FLAG(bool, qbone_tun_device_replace_default_routing_rules, true, "qbone interface to the qbone table. This is unnecessary in " "environments with no other ipv6 route."); -ABSL_FLAG(int, qbone_route_init_cwnd, 0, - "If non-zero, will add initcwnd to QBONE routing rules. Setting " - "a value below 10 is dangerous and not recommended."); +ABSL_RETIRED_FLAG(int, qbone_route_init_cwnd, 0, + "Deprecated. Code no longer modifies initcwnd."); namespace quic { @@ -90,8 +90,7 @@ bool TunDeviceController::UpdateRoutes( rule.table == QboneConstants::kQboneRouteTableId) { if (!netlink_->ChangeRoute(NetlinkInterface::Verb::kRemove, rule.table, rule.destination_subnet, rule.scope, - rule.preferred_source, rule.out_interface, - rule.init_cwnd)) { + rule.preferred_source, rule.out_interface)) { QUIC_LOG(ERROR) << "Unable to remove old route to <" << rule.destination_subnet.ToString() << ">"; return false; @@ -111,8 +110,8 @@ bool TunDeviceController::UpdateRoutes( for (const auto& route : routes) { if (!netlink_->ChangeRoute(NetlinkInterface::Verb::kReplace, QboneConstants::kQboneRouteTableId, route, - RT_SCOPE_LINK, desired_address, link_info.index, - absl::GetFlag(FLAGS_qbone_route_init_cwnd))) { + RT_SCOPE_LINK, desired_address, + link_info.index)) { QUIC_LOG(ERROR) << "Unable to add route <" << route.ToString() << ">"; return false; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/mock_netlink.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/mock_netlink.h index 72e3b666fa..6e33d9cf16 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/mock_netlink.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/mock_netlink.h @@ -25,8 +25,7 @@ class MockNetlink : public NetlinkInterface { MOCK_METHOD(bool, GetRouteInfo, (std::vector*), (override)); MOCK_METHOD(bool, ChangeRoute, - (Verb, uint32_t, const IpRange&, uint8_t, QuicIpAddress, int32_t, - uint32_t), + (Verb, uint32_t, const IpRange&, uint8_t, QuicIpAddress, int32_t), (override)); MOCK_METHOD(bool, GetRuleInfo, (std::vector*), (override)); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.cc index 04567d903d..6ebc669ce4 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.cc @@ -425,7 +425,6 @@ class RoutingRuleParser : public NetlinkParserInterface { Netlink::RoutingRule rule; rule.scope = route->rtm_scope; rule.table = route->rtm_table; - rule.init_cwnd = Netlink::kUnspecifiedInitCwnd; struct rtattr* rta; for (rta = RTM_RTA(route); RTA_OK(rta, payload_length); @@ -452,25 +451,6 @@ class RoutingRuleParser : public NetlinkParserInterface { rule.out_interface = *reinterpret_cast(RTA_DATA(rta)); break; } - case RTA_METRICS: { - struct rtattr* rtax; - int rta_payload_length = RTA_PAYLOAD(rta); - for (rtax = reinterpret_cast(RTA_DATA(rta)); - RTA_OK(rtax, rta_payload_length); - rtax = RTA_NEXT(rtax, rta_payload_length)) { - switch (rtax->rta_type) { - case RTAX_INITCWND: { - rule.init_cwnd = *reinterpret_cast(RTA_DATA(rtax)); - break; - } - default: { - QUIC_VLOG(2) << absl::StrCat( - "Uninteresting RTA_METRICS attribute: ", rtax->rta_type); - } - } - } - break; - } default: { QUIC_VLOG(2) << absl::StrCat("Uninteresting attribute: ", rta->rta_type); @@ -512,7 +492,7 @@ bool Netlink::GetRouteInfo(std::vector* routing_rules) { bool Netlink::ChangeRoute(Netlink::Verb verb, uint32_t table, const IpRange& destination_subnet, uint8_t scope, QuicIpAddress preferred_source, - int32_t interface_index, uint32_t init_cwnd) { + int32_t interface_index) { if (!destination_subnet.prefix().IsInitialized()) { return false; } @@ -574,15 +554,6 @@ bool Netlink::ChangeRoute(Netlink::Verb verb, uint32_t table, message.AppendAttribute(RTA_TABLE, &table, sizeof(table)); - if (init_cwnd != kUnspecifiedInitCwnd) { - char data[RTA_LENGTH(sizeof(uint32_t))]; - struct rtattr* rta = reinterpret_cast(data); - rta->rta_type = RTAX_INITCWND; - rta->rta_len = sizeof(data); - *reinterpret_cast(RTA_DATA(rta)) = init_cwnd; - message.AppendAttribute(RTA_METRICS, data, sizeof(data)); - } - // RTA_OIF is the target interface for this rule. message.AppendAttribute(RTA_OIF, &interface_index, sizeof(interface_index)); // The actual destination subnet must be truncated of all the tailing zeros. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.h index 857b8bff4a..27a341af81 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink.h @@ -88,8 +88,8 @@ class Netlink : public NetlinkInterface { // matching rule is found, a new entry will be created. bool ChangeRoute(Netlink::Verb verb, uint32_t table, const IpRange& destination_subnet, uint8_t scope, - QuicIpAddress preferred_source, int32_t interface_index, - uint32_t init_cwnd) override; + QuicIpAddress preferred_source, + int32_t interface_index) override; // Returns the set of all rules in the routing policy database. bool GetRuleInfo(std::vector* ip_rules) override; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink_interface.h index c4fc42c6f6..4bbde21dfb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink_interface.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/platform/netlink_interface.h @@ -73,8 +73,6 @@ class NetlinkInterface { uint8_t prefix_length, uint8_t ifa_flags, uint8_t ifa_scope, const std::vector& additional_attributes) = 0; - static constexpr uint32_t kUnspecifiedInitCwnd = 0; - // Routing rule reported back from GetRouteInfo. struct RoutingRule { uint32_t table; @@ -82,7 +80,6 @@ class NetlinkInterface { QuicIpAddress preferred_source; uint8_t scope; int out_interface; - uint32_t init_cwnd; // kUnspecifiedInitCwnd if unspecified }; struct IpRule { @@ -112,7 +109,7 @@ class NetlinkInterface { virtual bool ChangeRoute(Verb verb, uint32_t table, const IpRange& destination_subnet, uint8_t scope, QuicIpAddress preferred_source, - int32_t interface_index, uint32_t init_cwnd) = 0; + int32_t interface_index) = 0; // Returns the set of all rules in the routing policy database. virtual bool GetRuleInfo(std::vector* ip_rules) = 0; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_exchanger.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_exchanger.cc index aa99a78ddb..f82292c001 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_exchanger.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_exchanger.cc @@ -8,6 +8,8 @@ #include #include +#include "absl/status/status.h" + namespace quic { bool QbonePacketExchanger::ReadAndDeliverPacket( @@ -27,6 +29,13 @@ bool QbonePacketExchanger::ReadAndDeliverPacket( void QbonePacketExchanger::WritePacketToNetwork(const char* packet, size_t size) { + if (visitor_) { + absl::Status status = visitor_->OnWrite(packet); + if (!status.ok()) { + QUIC_LOG_EVERY_N_SEC(ERROR, 60) << status; + } + } + bool blocked = false; std::string error; if (packet_queue_.empty() && !write_blocked_) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_exchanger.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_exchanger.h index 4fd617b6eb..c69f9b8f92 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_exchanger.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/qbone/qbone_packet_exchanger.h @@ -5,6 +5,8 @@ #ifndef QUICHE_QUIC_QBONE_QBONE_PACKET_EXCHANGER_H_ #define QUICHE_QUIC_QBONE_QBONE_PACKET_EXCHANGER_H_ +#include "absl/status/status.h" +#include "absl/strings/string_view.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/qbone/qbone_client_interface.h" #include "quiche/quic/qbone/qbone_packet_writer.h" @@ -21,6 +23,9 @@ class QbonePacketExchanger : public QbonePacketWriter { virtual ~Visitor() {} virtual void OnReadError(const std::string& error) {} virtual void OnWriteError(const std::string& error) {} + virtual absl::Status OnWrite(absl::string_view packet) { + return absl::OkStatus(); + } }; // Does not take ownership of visitor. QbonePacketExchanger(Visitor* visitor, size_t max_pending_packets) diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_decoder_test_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_decoder_test_utils.cc index ad8d4eb722..ac6dea97ba 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_decoder_test_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_decoder_test_utils.cc @@ -42,7 +42,7 @@ void TestHeadersHandler::OnDecodingErrorDetected( error_message_.assign(error_message.data(), error_message.size()); } -spdy::Http2HeaderBlock TestHeadersHandler::ReleaseHeaderList() { +quiche::HttpHeaderBlock TestHeadersHandler::ReleaseHeaderList() { QUICHE_DCHECK(decoding_completed_); QUICHE_DCHECK(!decoding_error_detected_); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_decoder_test_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_decoder_test_utils.h index f746550bc6..a0101f57fa 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_decoder_test_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_decoder_test_utils.h @@ -13,7 +13,7 @@ #include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/test_tools/qpack/qpack_test_utils.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { namespace test { @@ -46,14 +46,14 @@ class TestHeadersHandler // Release decoded header list. Must only be called if decoding is complete // and no errors have been detected. - spdy::Http2HeaderBlock ReleaseHeaderList(); + quiche::HttpHeaderBlock ReleaseHeaderList(); bool decoding_completed() const; bool decoding_error_detected() const; const std::string& error_message() const; private: - spdy::Http2HeaderBlock header_list_; + quiche::HttpHeaderBlock header_list_; bool decoding_completed_; bool decoding_error_detected_; std::string error_message_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_offline_decoder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_offline_decoder.cc index 73d50075ad..a86548e4df 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_offline_decoder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_offline_decoder.cc @@ -237,11 +237,11 @@ bool QpackOfflineDecoder::VerifyDecodedHeaderLists( absl::string_view expected_headers_data(*expected_headers_data_storage); while (!decoded_header_lists_.empty()) { - spdy::Http2HeaderBlock decoded_header_list = + quiche::HttpHeaderBlock decoded_header_list = std::move(decoded_header_lists_.front()); decoded_header_lists_.pop_front(); - spdy::Http2HeaderBlock expected_header_list; + quiche::HttpHeaderBlock expected_header_list; if (!ReadNextExpectedHeaderList(&expected_headers_data, &expected_header_list)) { QUIC_LOG(ERROR) @@ -268,7 +268,7 @@ bool QpackOfflineDecoder::VerifyDecodedHeaderLists( bool QpackOfflineDecoder::ReadNextExpectedHeaderList( absl::string_view* expected_headers_data, - spdy::Http2HeaderBlock* expected_header_list) { + quiche::HttpHeaderBlock* expected_header_list) { while (true) { absl::string_view::size_type endline = expected_headers_data->find('\n'); @@ -299,8 +299,8 @@ bool QpackOfflineDecoder::ReadNextExpectedHeaderList( } bool QpackOfflineDecoder::CompareHeaderBlocks( - spdy::Http2HeaderBlock decoded_header_list, - spdy::Http2HeaderBlock expected_header_list) { + quiche::HttpHeaderBlock decoded_header_list, + quiche::HttpHeaderBlock expected_header_list) { if (decoded_header_list == expected_header_list) { return true; } @@ -311,7 +311,7 @@ bool QpackOfflineDecoder::CompareHeaderBlocks( // Remove such headers one by one if they match. const char* kContentLength = "content-length"; const char* kPseudoHeaderPrefix = ":"; - for (spdy::Http2HeaderBlock::iterator decoded_it = + for (quiche::HttpHeaderBlock::iterator decoded_it = decoded_header_list.begin(); decoded_it != decoded_header_list.end();) { const absl::string_view key = decoded_it->first; @@ -319,7 +319,7 @@ bool QpackOfflineDecoder::CompareHeaderBlocks( ++decoded_it; continue; } - spdy::Http2HeaderBlock::iterator expected_it = + quiche::HttpHeaderBlock::iterator expected_it = expected_header_list.find(key); if (expected_it == expected_header_list.end() || decoded_it->second != expected_it->second) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_offline_decoder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_offline_decoder.h index 07fa276935..4e78a31ff7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_offline_decoder.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_offline_decoder.h @@ -12,7 +12,7 @@ #include "quiche/quic/core/quic_error_codes.h" #include "quiche/quic/test_tools/qpack/qpack_decoder_test_utils.h" #include "quiche/quic/test_tools/qpack/qpack_test_utils.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -63,14 +63,15 @@ class QpackOfflineDecoder : public QpackDecoder::EncoderStreamErrorDelegate { // Parse next header list from |*expected_headers_data| into // |*expected_header_list|, removing consumed data from the beginning of // |*expected_headers_data|. Returns true on success, false if parsing fails. - bool ReadNextExpectedHeaderList(absl::string_view* expected_headers_data, - spdy::Http2HeaderBlock* expected_header_list); + bool ReadNextExpectedHeaderList( + absl::string_view* expected_headers_data, + quiche::HttpHeaderBlock* expected_header_list); // Compare two header lists. Allow for different orders of certain headers as // described at // https://github.com/qpackers/qifs/blob/master/encoded/qpack-03/h2o/README.md. - bool CompareHeaderBlocks(spdy::Http2HeaderBlock decoded_header_list, - spdy::Http2HeaderBlock expected_header_list); + bool CompareHeaderBlocks(quiche::HttpHeaderBlock decoded_header_list, + quiche::HttpHeaderBlock expected_header_list); bool encoder_stream_error_detected_; test::NoopQpackStreamSenderDelegate decoder_stream_sender_delegate_; @@ -80,7 +81,7 @@ class QpackOfflineDecoder : public QpackDecoder::EncoderStreamErrorDelegate { std::list decoders_; // Decoded header lists. - std::list decoded_header_lists_; + std::list decoded_header_lists_; }; } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.cc index f42d9aea9e..ac2567a20d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.cc @@ -49,7 +49,7 @@ void QuicSpdySessionPeer::SetMaxInboundHeaderListSize( // static size_t QuicSpdySessionPeer::WriteHeadersOnHeadersStream( - QuicSpdySession* session, QuicStreamId id, spdy::Http2HeaderBlock headers, + QuicSpdySession* session, QuicStreamId id, quiche::HttpHeaderBlock headers, bool fin, const spdy::SpdyStreamPrecedence& precedence, quiche::QuicheReferenceCountedPointer ack_listener) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h index 87d38eee2d..2edf3e408e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_spdy_session_peer.h @@ -12,7 +12,7 @@ #include "quiche/quic/core/qpack/qpack_send_stream.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_write_blocked_list.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/spdy/core/spdy_framer.h" namespace quic { @@ -33,8 +33,9 @@ class QuicSpdySessionPeer { static void SetMaxInboundHeaderListSize(QuicSpdySession* session, size_t max_inbound_header_size); static size_t WriteHeadersOnHeadersStream( - QuicSpdySession* session, QuicStreamId id, spdy::Http2HeaderBlock headers, - bool fin, const spdy::SpdyStreamPrecedence& precedence, + QuicSpdySession* session, QuicStreamId id, + quiche::HttpHeaderBlock headers, bool fin, + const spdy::SpdyStreamPrecedence& precedence, quiche::QuicheReferenceCountedPointer ack_listener); // |session| can't be nullptr. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.cc index a37ff368c6..93e7e44292 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.cc @@ -73,7 +73,7 @@ class SessionCloseVisitor : public WebTransportVisitor { QuicSimpleServerBackend::WebTransportResponse QuicTestBackend::ProcessWebTransportRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, WebTransportSession* session) { if (!SupportsWebTransport()) { return QuicSimpleServerBackend::ProcessWebTransportRequest(request_headers, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.h index e59eb9124a..75b03d2e58 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_backend.h @@ -6,8 +6,8 @@ #define QUICHE_QUIC_TEST_TOOLS_QUIC_TEST_BACKEND_H_ #include "quiche/quic/tools/quic_memory_cache_backend.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { namespace test { @@ -18,7 +18,7 @@ namespace test { class QuicTestBackend : public QuicMemoryCacheBackend { public: WebTransportResponse ProcessWebTransportRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, WebTransportSession* session) override; bool SupportsWebTransport() override { return enable_webtransport_; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.cc index 198906b33f..aba6fc055d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.cc @@ -381,7 +381,7 @@ void QuicTestClient::SetUserAgentID(const std::string& user_agent_id) { } int64_t QuicTestClient::SendRequest(const std::string& uri) { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; if (!PopulateHeaderBlockFromUrl(uri, &headers)) { return 0; } @@ -389,7 +389,7 @@ int64_t QuicTestClient::SendRequest(const std::string& uri) { } int64_t QuicTestClient::SendRequestAndRstTogether(const std::string& uri) { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; if (!PopulateHeaderBlockFromUrl(uri, &headers)) { return 0; } @@ -414,7 +414,7 @@ void QuicTestClient::SendRequestsAndWaitForResponses( } int64_t QuicTestClient::GetOrCreateStreamAndSendRequest( - const spdy::Http2HeaderBlock* headers, absl::string_view body, bool fin, + const quiche::HttpHeaderBlock* headers, absl::string_view body, bool fin, quiche::QuicheReferenceCountedPointer ack_listener) { // Maybe it's better just to overload this. it's just that we need @@ -428,7 +428,7 @@ int64_t QuicTestClient::GetOrCreateStreamAndSendRequest( int64_t ret = 0; if (headers != nullptr) { - spdy::Http2HeaderBlock spdy_headers(headers->Clone()); + quiche::HttpHeaderBlock spdy_headers(headers->Clone()); if (spdy_headers[":authority"].as_string().empty()) { spdy_headers[":authority"] = client_->server_id().host(); } @@ -441,17 +441,17 @@ int64_t QuicTestClient::GetOrCreateStreamAndSendRequest( return ret; } -int64_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers, +int64_t QuicTestClient::SendMessage(const quiche::HttpHeaderBlock& headers, absl::string_view body) { return SendMessage(headers, body, /*fin=*/true); } -int64_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers, +int64_t QuicTestClient::SendMessage(const quiche::HttpHeaderBlock& headers, absl::string_view body, bool fin) { return SendMessage(headers, body, fin, /*flush=*/true); } -int64_t QuicTestClient::SendMessage(const spdy::Http2HeaderBlock& headers, +int64_t QuicTestClient::SendMessage(const quiche::HttpHeaderBlock& headers, absl::string_view body, bool fin, bool flush) { // Always force creation of a stream for SendMessage. @@ -492,7 +492,7 @@ void QuicTestClient::set_buffer_body(bool buffer_body) { const std::string& QuicTestClient::response_body() const { return response_; } std::string QuicTestClient::SendCustomSynchronousRequest( - const spdy::Http2HeaderBlock& headers, const std::string& body) { + const quiche::HttpHeaderBlock& headers, const std::string& body) { // Clear connection state here and only track this synchronous request. ClearPerConnectionState(); if (SendMessage(headers, body) == 0) { @@ -507,7 +507,7 @@ std::string QuicTestClient::SendCustomSynchronousRequest( } std::string QuicTestClient::SendSynchronousRequest(const std::string& uri) { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; if (!PopulateHeaderBlockFromUrl(uri, &headers)) { return ""; } @@ -656,7 +656,7 @@ bool QuicTestClient::response_headers_complete() const { return response_headers_complete_; } -const spdy::Http2HeaderBlock* QuicTestClient::response_headers() const { +const quiche::HttpHeaderBlock* QuicTestClient::response_headers() const { for (std::pair stream : open_streams_) { if (stream.second->headers_decompressed()) { response_headers_ = stream.second->response_headers().Clone(); @@ -666,7 +666,7 @@ const spdy::Http2HeaderBlock* QuicTestClient::response_headers() const { return &response_headers_; } -const spdy::Http2HeaderBlock& QuicTestClient::response_trailers() const { +const quiche::HttpHeaderBlock& QuicTestClient::response_trailers() const { return response_trailers_; } @@ -803,8 +803,9 @@ QuicTestClient::PerStreamState::PerStreamState(const PerStreamState& other) QuicTestClient::PerStreamState::PerStreamState( QuicRstStreamErrorCode stream_error, bool response_complete, bool response_headers_complete, - const spdy::Http2HeaderBlock& response_headers, const std::string& response, - const spdy::Http2HeaderBlock& response_trailers, uint64_t bytes_read, + const quiche::HttpHeaderBlock& response_headers, + const std::string& response, + const quiche::HttpHeaderBlock& response_trailers, uint64_t bytes_read, uint64_t bytes_written, int64_t response_body_size) : stream_error(stream_error), response_complete(response_complete), @@ -819,7 +820,7 @@ QuicTestClient::PerStreamState::PerStreamState( QuicTestClient::PerStreamState::~PerStreamState() = default; bool QuicTestClient::PopulateHeaderBlockFromUrl( - const std::string& uri, spdy::Http2HeaderBlock* headers) { + const std::string& uri, quiche::HttpHeaderBlock* headers) { std::string url; if (absl::StartsWith(uri, "https://") || absl::StartsWith(uri, "http://")) { url = uri; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.h index 4920187ab6..5091e231b9 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.h @@ -17,9 +17,9 @@ #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/platform/api/quic_test.h" #include "quiche/quic/tools/quic_default_client.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/quiche_callbacks.h" #include "quiche/common/quiche_linked_hash_map.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -169,23 +169,23 @@ class QuicTestClient : public QuicSpdyStream::Visitor { const std::vector& url_list); // Sends a request containing |headers| and |body| and returns the number of // bytes sent (the size of the serialized request headers and body). - int64_t SendMessage(const spdy::Http2HeaderBlock& headers, + int64_t SendMessage(const quiche::HttpHeaderBlock& headers, absl::string_view body); // Sends a request containing |headers| and |body| with the fin bit set to // |fin| and returns the number of bytes sent (the size of the serialized // request headers and body). - int64_t SendMessage(const spdy::Http2HeaderBlock& headers, + int64_t SendMessage(const quiche::HttpHeaderBlock& headers, absl::string_view body, bool fin); // Sends a request containing |headers| and |body| with the fin bit set to // |fin| and returns the number of bytes sent (the size of the serialized // request headers and body). If |flush| is true, will wait for the message to // be flushed before returning. - int64_t SendMessage(const spdy::Http2HeaderBlock& headers, + int64_t SendMessage(const quiche::HttpHeaderBlock& headers, absl::string_view body, bool fin, bool flush); // Sends a request containing |headers| and |body|, waits for the response, // and returns the response body. std::string SendCustomSynchronousRequest( - const spdy::Http2HeaderBlock& headers, const std::string& body); + const quiche::HttpHeaderBlock& headers, const std::string& body); // Sends a GET request for |uri|, waits for the response, and returns the // response body. std::string SendSynchronousRequest(const std::string& uri); @@ -204,14 +204,14 @@ class QuicTestClient : public QuicSpdyStream::Visitor { // Getters for stream state that only get updated once a complete response is // received. - const spdy::Http2HeaderBlock& response_trailers() const; + const quiche::HttpHeaderBlock& response_trailers() const; bool response_complete() const; int64_t response_body_size() const; const std::string& response_body() const; // Getters for stream state that return state of the oldest active stream that // have received a partial response. bool response_headers_complete() const; - const spdy::Http2HeaderBlock* response_headers() const; + const quiche::HttpHeaderBlock* response_headers() const; int64_t response_size() const; size_t bytes_read() const; size_t bytes_written() const; @@ -296,7 +296,7 @@ class QuicTestClient : public QuicSpdyStream::Visitor { // stores the request in case it needs to be resent. If |headers| is // null, only the body will be sent on the stream. int64_t GetOrCreateStreamAndSendRequest( - const spdy::Http2HeaderBlock* headers, absl::string_view body, bool fin, + const quiche::HttpHeaderBlock* headers, absl::string_view body, bool fin, quiche::QuicheReferenceCountedPointer ack_listener); @@ -354,7 +354,7 @@ class QuicTestClient : public QuicSpdyStream::Visitor { // request. If |uri| is a relative URL, the QuicServerId will be // use to specify the authority. bool PopulateHeaderBlockFromUrl(const std::string& uri, - spdy::Http2HeaderBlock* headers); + quiche::HttpHeaderBlock* headers); // Waits for a period of time that is long enough to receive all delayed acks // sent by peer. @@ -377,9 +377,9 @@ class QuicTestClient : public QuicSpdyStream::Visitor { PerStreamState(const PerStreamState& other); PerStreamState(QuicRstStreamErrorCode stream_error, bool response_complete, bool response_headers_complete, - const spdy::Http2HeaderBlock& response_headers, + const quiche::HttpHeaderBlock& response_headers, const std::string& response, - const spdy::Http2HeaderBlock& response_trailers, + const quiche::HttpHeaderBlock& response_trailers, uint64_t bytes_read, uint64_t bytes_written, int64_t response_body_size); ~PerStreamState(); @@ -387,9 +387,9 @@ class QuicTestClient : public QuicSpdyStream::Visitor { QuicRstStreamErrorCode stream_error; bool response_complete; bool response_headers_complete; - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; std::string response; - spdy::Http2HeaderBlock response_trailers; + quiche::HttpHeaderBlock response_trailers; uint64_t bytes_read; uint64_t bytes_written; int64_t response_body_size; @@ -420,10 +420,10 @@ class QuicTestClient : public QuicSpdyStream::Visitor { bool response_complete_; bool response_headers_complete_; - mutable spdy::Http2HeaderBlock response_headers_; + mutable quiche::HttpHeaderBlock response_headers_; // Parsed response trailers (if present), copied from the stream in OnClose. - spdy::Http2HeaderBlock response_trailers_; + quiche::HttpHeaderBlock response_trailers_; spdy::SpdyPriority priority_; std::string response_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h index ff7210df33..276a2acccd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h @@ -47,8 +47,8 @@ #include "quiche/quic/test_tools/quic_framer_peer.h" #include "quiche/quic/test_tools/simple_quic_framer.h" #include "quiche/common/capsule.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/simple_buffer_allocator.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -886,7 +886,7 @@ class MockQuicCryptoStream : public QuicCryptoStream { } void SetPreviousCachedNetworkParams( CachedNetworkParameters /*cached_network_params*/) override {} - void OnConnectionClosed(QuicErrorCode /*error*/, + void OnConnectionClosed(const QuicConnectionCloseFrame& /*frame*/, ConnectionCloseSource /*source*/) override {} HandshakeState GetHandshakeState() const override { return HANDSHAKE_START; } void SetServerApplicationStateForResumption( @@ -1047,7 +1047,7 @@ class MockHttp3DebugVisitor : public Http3DebugVisitor { MOCK_METHOD(void, OnDataFrameSent, (QuicStreamId, QuicByteCount), (override)); MOCK_METHOD(void, OnHeadersFrameSent, - (QuicStreamId, const spdy::Http2HeaderBlock&), (override)); + (QuicStreamId, const quiche::HttpHeaderBlock&), (override)); MOCK_METHOD(void, OnSettingsFrameResumed, (const SettingsFrame&), (override)); }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.cc index 78d285b604..42d59809af 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.cc @@ -14,6 +14,7 @@ #include "quiche/quic/core/crypto/crypto_handshake_message.h" #include "quiche/quic/core/crypto/crypto_protocol.h" #include "quiche/quic/core/quic_connection.h" +#include "quiche/quic/core/quic_connection_id.h" #include "quiche/quic/core/quic_data_writer.h" #include "quiche/quic/platform/api/quic_test_output.h" #include "quiche/quic/test_tools/quic_connection_peer.h" @@ -65,7 +66,8 @@ QuicEndpointBase::QuicEndpointBase(Simulator* simulator, std::string name, kMaxOutgoingPacketSize * kTxQueueSize), connection_(nullptr), write_blocked_count_(0), - drop_next_packet_(false) { + drop_next_packet_(false), + connection_id_generator_(kQuicDefaultConnectionIdLength) { nic_tx_queue_.set_listener_interface(this); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.h index fe753d558c..336b2f90cf 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simulator/quic_endpoint_base.h @@ -10,12 +10,12 @@ #include "absl/container/flat_hash_map.h" #include "quiche/quic/core/crypto/null_decrypter.h" #include "quiche/quic/core/crypto/null_encrypter.h" +#include "quiche/quic/core/deterministic_connection_id_generator.h" #include "quiche/quic/core/quic_connection.h" #include "quiche/quic/core/quic_packet_writer.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_stream_frame_data_producer.h" #include "quiche/quic/core/quic_trace_visitor.h" -#include "quiche/quic/test_tools/mock_connection_id_generator.h" #include "quiche/quic/test_tools/simple_session_notifier.h" #include "quiche/quic/test_tools/simulator/link.h" #include "quiche/quic/test_tools/simulator/queue.h" @@ -131,7 +131,7 @@ class QuicEndpointBase : public Endpoint, std::unique_ptr trace_visitor_; - test::MockConnectionIdGenerator connection_id_generator_; + DeterministicConnectionIdGenerator connection_id_generator_; }; // Multiplexes multiple connections at the same host on the network. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/web_transport_resets_backend.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/web_transport_resets_backend.cc index 4a28ff5ddc..4dc75eddac 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/web_transport_resets_backend.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/web_transport_resets_backend.cc @@ -103,7 +103,7 @@ void BidirectionalEchoVisitorWithLogging::OnStopSendingReceived( } // namespace QuicSimpleServerBackend::WebTransportResponse WebTransportResetsBackend( - const spdy::Http2HeaderBlock& /*request_headers*/, + const quiche::HttpHeaderBlock& /*request_headers*/, WebTransportSession* session) { QuicSimpleServerBackend::WebTransportResponse response; response.response_headers[":status"] = "200"; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/web_transport_resets_backend.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/web_transport_resets_backend.h index c5ffbe0df7..c79bac37ac 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/web_transport_resets_backend.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/web_transport_resets_backend.h @@ -6,7 +6,7 @@ #define QUICHE_QUIC_TEST_TOOLS_WEB_TRANSPORT_RESETS_BACKEND_H_ #include "quiche/quic/test_tools/quic_test_backend.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { namespace test { @@ -15,7 +15,7 @@ namespace test { // bidirectional echo streams; whenever one of those receives RESET_STREAM or // STOP_SENDING, a log message is sent as a unidirectional stream. QuicSimpleServerBackend::WebTransportResponse WebTransportResetsBackend( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, WebTransportSession* session); } // namespace test diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_server_backend.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_server_backend.cc index ba17bea5ff..c0a07719b5 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_server_backend.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_server_backend.cc @@ -15,9 +15,9 @@ #include "quiche/quic/tools/connect_tunnel.h" #include "quiche/quic/tools/connect_udp_tunnel.h" #include "quiche/quic/tools/quic_simple_server_backend.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -25,7 +25,7 @@ namespace { void SendErrorResponse(QuicSimpleServerBackend::RequestHandler* request_handler, absl::string_view error_code) { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":status"] = error_code; QuicBackendResponse response; response.set_headers(std::move(headers)); @@ -69,7 +69,7 @@ void ConnectServerBackend::SetSocketFactory(SocketFactory* socket_factory) { } void ConnectServerBackend::FetchResponseFromBackend( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, const std::string& request_body, RequestHandler* request_handler) { // Not a CONNECT request, so send to `non_connect_backend_`. non_connect_backend_->FetchResponseFromBackend(request_headers, request_body, @@ -77,7 +77,7 @@ void ConnectServerBackend::FetchResponseFromBackend( } void ConnectServerBackend::HandleConnectHeaders( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, RequestHandler* request_handler) { QUICHE_DCHECK(request_headers.contains(":method") && request_headers.find(":method")->second == "CONNECT"); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_server_backend.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_server_backend.h index 4aa8967203..9eda5ed201 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_server_backend.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_server_backend.h @@ -42,10 +42,10 @@ class ConnectServerBackend : public QuicSimpleServerBackend { bool InitializeBackend(const std::string& backend_url) override; bool IsBackendInitialized() const override; void SetSocketFactory(SocketFactory* socket_factory) override; - void FetchResponseFromBackend(const spdy::Http2HeaderBlock& request_headers, + void FetchResponseFromBackend(const quiche::HttpHeaderBlock& request_headers, const std::string& request_body, RequestHandler* request_handler) override; - void HandleConnectHeaders(const spdy::Http2HeaderBlock& request_headers, + void HandleConnectHeaders(const quiche::HttpHeaderBlock& request_headers, RequestHandler* request_handler) override; void HandleConnectData(absl::string_view data, bool data_complete, RequestHandler* request_handler) override; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_tunnel.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_tunnel.cc index 22f6c3b233..11f2eff6b8 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_tunnel.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_tunnel.cc @@ -23,9 +23,9 @@ #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_name_lookup.h" #include "quiche/quic/tools/quic_simple_server_backend.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/platform/api/quiche_mem_slice.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -35,7 +35,7 @@ namespace { constexpr size_t kReadSize = 4 * 1024; std::optional ValidateHeadersAndGetAuthority( - const spdy::Http2HeaderBlock& request_headers) { + const quiche::HttpHeaderBlock& request_headers) { QUICHE_DCHECK(request_headers.contains(":method")); QUICHE_DCHECK(request_headers.find(":method")->second == "CONNECT"); QUICHE_DCHECK(!request_headers.contains(":protocol")); @@ -108,7 +108,7 @@ ConnectTunnel::~ConnectTunnel() { QUICHE_DCHECK(!receive_started_); } -void ConnectTunnel::OpenTunnel(const spdy::Http2HeaderBlock& request_headers) { +void ConnectTunnel::OpenTunnel(const quiche::HttpHeaderBlock& request_headers) { QUICHE_DCHECK(!IsConnectedToDestination()); std::optional authority = @@ -266,7 +266,7 @@ void ConnectTunnel::SendConnectResponse() { QUICHE_DCHECK(IsConnectedToDestination()); QUICHE_DCHECK(client_stream_request_handler_); - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = "200"; QuicBackendResponse response; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_tunnel.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_tunnel.h index 259f12542e..ecde8b734e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_tunnel.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_tunnel.h @@ -19,8 +19,8 @@ #include "quiche/quic/core/quic_server_id.h" #include "quiche/quic/core/socket_factory.h" #include "quiche/quic/tools/quic_simple_server_backend.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_mem_slice.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -41,7 +41,7 @@ class ConnectTunnel : public ConnectingClientSocket::AsyncVisitor { // appropriate success/error response to the request stream. `request_headers` // must represent headers from a CONNECT request, that is ":method"="CONNECT" // and no ":protocol". - void OpenTunnel(const spdy::Http2HeaderBlock& request_headers); + void OpenTunnel(const quiche::HttpHeaderBlock& request_headers); // Returns true iff the connection to the destination server is currently open bool IsConnectedToDestination() const; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.cc index a4d215ccc0..85d07603cc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.cc @@ -26,13 +26,13 @@ #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_name_lookup.h" #include "quiche/quic/tools/quic_simple_server_backend.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/masque/connect_udp_datagram_payload.h" #include "quiche/common/platform/api/quiche_googleurl.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/platform/api/quiche_mem_slice.h" #include "quiche/common/platform/api/quiche_url_utils.h" #include "quiche/common/structured_headers.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -113,7 +113,7 @@ std::optional ValidateAndParseTargetFromPath( // Validate header expectations from RFC 9298, section 3.4. std::optional ValidateHeadersAndGetTarget( - const spdy::Http2HeaderBlock& request_headers) { + const quiche::HttpHeaderBlock& request_headers) { QUICHE_DCHECK(request_headers.contains(":method")); QUICHE_DCHECK(request_headers.find(":method")->second == "CONNECT"); QUICHE_DCHECK(request_headers.contains(":protocol")); @@ -185,7 +185,7 @@ ConnectUdpTunnel::~ConnectUdpTunnel() { } void ConnectUdpTunnel::OpenTunnel( - const spdy::Http2HeaderBlock& request_headers) { + const quiche::HttpHeaderBlock& request_headers) { QUICHE_DCHECK(!IsTunnelOpenToTarget()); std::optional target = @@ -345,7 +345,7 @@ void ConnectUdpTunnel::SendConnectResponse() { QUICHE_DCHECK(IsTunnelOpenToTarget()); QUICHE_DCHECK(client_stream_request_handler_); - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = "200"; std::optional capsule_protocol_value = @@ -380,7 +380,7 @@ void ConnectUdpTunnel::SendErrorResponse(absl::string_view status, QUICHE_DCHECK(status_num < 200 || status_num >= 300); #endif // !NDEBUG - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":status"] = status; structured_headers::Item proxy_status_item(server_label_); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.h index 1e800a75f7..71e13dc0bc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.h @@ -21,8 +21,8 @@ #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/socket_factory.h" #include "quiche/quic/tools/quic_simple_server_backend.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_mem_slice.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -46,7 +46,7 @@ class ConnectUdpTunnel : public ConnectingClientSocket::AsyncVisitor, // success/error response to the request stream. `request_headers` must // represent headers from a CONNECT-UDP request, that is ":method"="CONNECT" // and ":protocol"="connect-udp". - void OpenTunnel(const spdy::Http2HeaderBlock& request_headers); + void OpenTunnel(const quiche::HttpHeaderBlock& request_headers); // Returns true iff the tunnel to the target server is currently open bool IsTunnelOpenToTarget() const; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_backend_response.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_backend_response.h index 6223e48012..5564a6d07b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_backend_response.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_backend_response.h @@ -7,7 +7,7 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_time.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -35,16 +35,16 @@ class QuicBackendResponse { ~QuicBackendResponse(); - const std::vector& early_hints() const { + const std::vector& early_hints() const { return early_hints_; } SpecialResponseType response_type() const { return response_type_; } - const spdy::Http2HeaderBlock& headers() const { return headers_; } - const spdy::Http2HeaderBlock& trailers() const { return trailers_; } + const quiche::HttpHeaderBlock& headers() const { return headers_; } + const quiche::HttpHeaderBlock& trailers() const { return trailers_; } const absl::string_view body() const { return absl::string_view(body_); } - void AddEarlyHints(const spdy::Http2HeaderBlock& headers) { - spdy::Http2HeaderBlock hints = headers.Clone(); + void AddEarlyHints(const quiche::HttpHeaderBlock& headers) { + quiche::HttpHeaderBlock hints = headers.Clone(); hints[":status"] = "103"; early_hints_.push_back(std::move(hints)); } @@ -53,10 +53,10 @@ class QuicBackendResponse { response_type_ = response_type; } - void set_headers(spdy::Http2HeaderBlock headers) { + void set_headers(quiche::HttpHeaderBlock headers) { headers_ = std::move(headers); } - void set_trailers(spdy::Http2HeaderBlock trailers) { + void set_trailers(quiche::HttpHeaderBlock trailers) { trailers_ = std::move(trailers); } void set_body(absl::string_view body) { @@ -69,10 +69,10 @@ class QuicBackendResponse { QuicTime::Delta delay() const { return delay_; } private: - std::vector early_hints_; + std::vector early_hints_; SpecialResponseType response_type_; - spdy::Http2HeaderBlock headers_; - spdy::Http2HeaderBlock trailers_; + quiche::HttpHeaderBlock headers_; + quiche::HttpHeaderBlock trailers_; std::string body_; QuicTime::Delta delay_; }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_client_interop_test_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_client_interop_test_bin.cc index 4cb07e45f5..17b51f5f7a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_client_interop_test_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_client_interop_test_bin.cc @@ -22,9 +22,9 @@ #include "quiche/quic/tools/quic_default_client.h" #include "quiche/quic/tools/quic_name_lookup.h" #include "quiche/quic/tools/quic_url.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_command_line_flags.h" #include "quiche/common/platform/api/quiche_system_event_loop.h" -#include "quiche/spdy/core/http2_header_block.h" DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, host, "", "The IP or hostname to connect to."); @@ -121,11 +121,11 @@ class QuicClientInteropRunner : QuicConnectionDebugVisitor { // Constructs a Http2HeaderBlock containing the pseudo-headers needed to make // a GET request to "/" on the hostname |authority|. - spdy::Http2HeaderBlock ConstructHeaderBlock(const std::string& authority); + quiche::HttpHeaderBlock ConstructHeaderBlock(const std::string& authority); // Sends an HTTP request represented by |header_block| using |client|. void SendRequest(QuicDefaultClient* client, - const spdy::Http2HeaderBlock& header_block); + const quiche::HttpHeaderBlock& header_block); void OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override { switch (frame.close_type) { @@ -175,7 +175,7 @@ void QuicClientInteropRunner::AttemptResumption(QuicDefaultClient* client, bool zero_rtt_attempt = !client->session()->OneRttKeysAvailable(); - spdy::Http2HeaderBlock header_block = ConstructHeaderBlock(authority); + quiche::HttpHeaderBlock header_block = ConstructHeaderBlock(authority); SendRequest(client, header_block); if (!client->session()->OneRttKeysAvailable()) { @@ -264,7 +264,7 @@ void QuicClientInteropRunner::AttemptRequest( InsertFeature(Feature::kQuantum); } - spdy::Http2HeaderBlock header_block = ConstructHeaderBlock(authority); + quiche::HttpHeaderBlock header_block = ConstructHeaderBlock(authority); SendRequest(client.get(), header_block); if (!client->connected()) { @@ -332,10 +332,10 @@ void QuicClientInteropRunner::AttemptRequest( AttemptResumption(client.get(), authority); } -spdy::Http2HeaderBlock QuicClientInteropRunner::ConstructHeaderBlock( +quiche::HttpHeaderBlock QuicClientInteropRunner::ConstructHeaderBlock( const std::string& authority) { // Construct and send a request. - spdy::Http2HeaderBlock header_block; + quiche::HttpHeaderBlock header_block; header_block[":method"] = "GET"; header_block[":scheme"] = "https"; header_block[":authority"] = authority; @@ -344,7 +344,7 @@ spdy::Http2HeaderBlock QuicClientInteropRunner::ConstructHeaderBlock( } void QuicClientInteropRunner::SendRequest( - QuicDefaultClient* client, const spdy::Http2HeaderBlock& header_block) { + QuicDefaultClient* client, const quiche::HttpHeaderBlock& header_block) { client->set_store_response(true); client->SendRequestAndWaitForResponse(header_block, "", /*fin=*/true); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.cc index 5a3e168ca7..2993384bbd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.cc @@ -21,7 +21,7 @@ #include "quiche/common/platform/api/quiche_file_utils.h" #include "quiche/common/quiche_text_utils.h" -using spdy::Http2HeaderBlock; +using quiche::HttpHeaderBlock; using spdy::kV3LowestPriority; namespace quic { @@ -159,7 +159,7 @@ void QuicMemoryCacheBackend::AddSimpleResponse(absl::string_view host, absl::string_view path, int response_code, absl::string_view body) { - Http2HeaderBlock response_headers; + HttpHeaderBlock response_headers; response_headers[":status"] = absl::StrCat(response_code); response_headers["content-length"] = absl::StrCat(body.length()); AddResponse(host, path, std::move(response_headers), body); @@ -172,22 +172,22 @@ void QuicMemoryCacheBackend::AddDefaultResponse(QuicBackendResponse* response) { void QuicMemoryCacheBackend::AddResponse(absl::string_view host, absl::string_view path, - Http2HeaderBlock response_headers, + HttpHeaderBlock response_headers, absl::string_view response_body) { AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE, - std::move(response_headers), response_body, - Http2HeaderBlock(), std::vector()); + std::move(response_headers), response_body, HttpHeaderBlock(), + std::vector()); } void QuicMemoryCacheBackend::AddResponse(absl::string_view host, absl::string_view path, - Http2HeaderBlock response_headers, + HttpHeaderBlock response_headers, absl::string_view response_body, - Http2HeaderBlock response_trailers) { + HttpHeaderBlock response_trailers) { AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE, std::move(response_headers), response_body, std::move(response_trailers), - std::vector()); + std::vector()); } bool QuicMemoryCacheBackend::SetResponseDelay(absl::string_view host, @@ -203,27 +203,27 @@ bool QuicMemoryCacheBackend::SetResponseDelay(absl::string_view host, void QuicMemoryCacheBackend::AddResponseWithEarlyHints( absl::string_view host, absl::string_view path, - spdy::Http2HeaderBlock response_headers, absl::string_view response_body, - const std::vector& early_hints) { + quiche::HttpHeaderBlock response_headers, absl::string_view response_body, + const std::vector& early_hints) { AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE, - std::move(response_headers), response_body, - Http2HeaderBlock(), early_hints); + std::move(response_headers), response_body, HttpHeaderBlock(), + early_hints); } void QuicMemoryCacheBackend::AddSpecialResponse( absl::string_view host, absl::string_view path, SpecialResponseType response_type) { - AddResponseImpl(host, path, response_type, Http2HeaderBlock(), "", - Http2HeaderBlock(), std::vector()); + AddResponseImpl(host, path, response_type, HttpHeaderBlock(), "", + HttpHeaderBlock(), std::vector()); } void QuicMemoryCacheBackend::AddSpecialResponse( absl::string_view host, absl::string_view path, - spdy::Http2HeaderBlock response_headers, absl::string_view response_body, + quiche::HttpHeaderBlock response_headers, absl::string_view response_body, SpecialResponseType response_type) { AddResponseImpl(host, path, response_type, std::move(response_headers), - response_body, Http2HeaderBlock(), - std::vector()); + response_body, HttpHeaderBlock(), + std::vector()); } QuicMemoryCacheBackend::QuicMemoryCacheBackend() : cache_initialized_(false) {} @@ -273,7 +273,7 @@ bool QuicMemoryCacheBackend::InitializeBackend( void QuicMemoryCacheBackend::GenerateDynamicResponses() { QuicWriterMutexLock lock(&response_mutex_); // Add a generate bytes response. - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[":status"] = "200"; generate_bytes_response_ = std::make_unique(); generate_bytes_response_->set_headers(std::move(response_headers)); @@ -290,8 +290,7 @@ bool QuicMemoryCacheBackend::IsBackendInitialized() const { } void QuicMemoryCacheBackend::FetchResponseFromBackend( - const Http2HeaderBlock& request_headers, - const std::string& /*request_body*/, + const HttpHeaderBlock& request_headers, const std::string& /*request_body*/, QuicSimpleServerBackend::RequestHandler* quic_stream) { const QuicBackendResponse* quic_response = nullptr; // Find response in cache. If not found, send error response. @@ -320,7 +319,7 @@ void QuicMemoryCacheBackend::CloseBackendResponseStream( QuicMemoryCacheBackend::WebTransportResponse QuicMemoryCacheBackend::ProcessWebTransportRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, WebTransportSession* session) { if (!SupportsWebTransport()) { return QuicSimpleServerBackend::ProcessWebTransportRequest(request_headers, @@ -356,9 +355,9 @@ QuicMemoryCacheBackend::~QuicMemoryCacheBackend() { void QuicMemoryCacheBackend::AddResponseImpl( absl::string_view host, absl::string_view path, - SpecialResponseType response_type, Http2HeaderBlock response_headers, - absl::string_view response_body, Http2HeaderBlock response_trailers, - const std::vector& early_hints) { + SpecialResponseType response_type, HttpHeaderBlock response_headers, + absl::string_view response_body, HttpHeaderBlock response_trailers, + const std::vector& early_hints) { QuicWriterMutexLock lock(&response_mutex_); QUICHE_DCHECK(!host.empty()) diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h index 930ef5841b..ed47d1d96b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h @@ -16,7 +16,7 @@ #include "quiche/quic/platform/api/quic_mutex.h" #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_simple_server_backend.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/spdy/core/spdy_framer.h" namespace quic { @@ -48,7 +48,7 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend { absl::string_view path() { return path_; } - const spdy::Http2HeaderBlock& spdy_headers() { return spdy_headers_; } + const quiche::HttpHeaderBlock& spdy_headers() { return spdy_headers_; } absl::string_view body() { return body_; } @@ -61,7 +61,7 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend { std::string file_name_; std::string file_contents_; absl::string_view body_; - spdy::Http2HeaderBlock spdy_headers_; + quiche::HttpHeaderBlock spdy_headers_; absl::string_view x_original_url_; std::vector push_urls_; std::string host_; @@ -85,20 +85,20 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend { // Add a response to the cache. void AddResponse(absl::string_view host, absl::string_view path, - spdy::Http2HeaderBlock response_headers, + quiche::HttpHeaderBlock response_headers, absl::string_view response_body); // Add a response, with trailers, to the cache. void AddResponse(absl::string_view host, absl::string_view path, - spdy::Http2HeaderBlock response_headers, + quiche::HttpHeaderBlock response_headers, absl::string_view response_body, - spdy::Http2HeaderBlock response_trailers); + quiche::HttpHeaderBlock response_trailers); // Add a response, with 103 Early Hints, to the cache. void AddResponseWithEarlyHints( absl::string_view host, absl::string_view path, - spdy::Http2HeaderBlock response_headers, absl::string_view response_body, - const std::vector& early_hints); + quiche::HttpHeaderBlock response_headers, absl::string_view response_body, + const std::vector& early_hints); // Simulate a special behavior at a particular path. void AddSpecialResponse( @@ -107,7 +107,7 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend { void AddSpecialResponse( absl::string_view host, absl::string_view path, - spdy::Http2HeaderBlock response_headers, absl::string_view response_body, + quiche::HttpHeaderBlock response_headers, absl::string_view response_body, QuicBackendResponse::SpecialResponseType response_type); // Finds a response with the given host and path, and assign it a simulated @@ -131,23 +131,23 @@ class QuicMemoryCacheBackend : public QuicSimpleServerBackend { bool InitializeBackend(const std::string& cache_directory) override; bool IsBackendInitialized() const override; void FetchResponseFromBackend( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, const std::string& request_body, QuicSimpleServerBackend::RequestHandler* quic_stream) override; void CloseBackendResponseStream( QuicSimpleServerBackend::RequestHandler* quic_stream) override; WebTransportResponse ProcessWebTransportRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, WebTransportSession* session) override; bool SupportsWebTransport() override { return enable_webtransport_; } private: void AddResponseImpl(absl::string_view host, absl::string_view path, QuicBackendResponse::SpecialResponseType response_type, - spdy::Http2HeaderBlock response_headers, + quiche::HttpHeaderBlock response_headers, absl::string_view response_body, - spdy::Http2HeaderBlock response_trailers, - const std::vector& early_hints); + quiche::HttpHeaderBlock response_trailers, + const std::vector& early_hints); std::string GetKey(absl::string_view host, absl::string_view path) const; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc index 5dae254147..669ed0fb34 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.cc @@ -8,7 +8,7 @@ #include #include "quiche/quic/core/quic_path_validator.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -39,9 +39,10 @@ QuicSimpleClientSession::CreateClientStream() { auto stream = std::make_unique( GetNextOutgoingBidirectionalStreamId(), this, BIDIRECTIONAL, drop_response_body_); - stream->set_on_interim_headers([this](const spdy::Http2HeaderBlock& headers) { - on_interim_headers_(headers); - }); + stream->set_on_interim_headers( + [this](const quiche::HttpHeaderBlock& headers) { + on_interim_headers_(headers); + }); return stream; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h index 424051c021..1e9c524e1b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h @@ -11,8 +11,8 @@ #include "quiche/quic/core/http/quic_spdy_client_session.h" #include "quiche/quic/tools/quic_client_base.h" #include "quiche/quic/tools/quic_simple_client_stream.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/quiche_callbacks.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -46,13 +46,13 @@ class QuicSimpleClientSession : public QuicSpdyClientSession { bool drop_response_body() const { return drop_response_body_; } void set_on_interim_headers( - quiche::MultiUseCallback + quiche::MultiUseCallback on_interim_headers) { on_interim_headers_ = std::move(on_interim_headers); } private: - quiche::MultiUseCallback + quiche::MultiUseCallback on_interim_headers_; QuicClientBase::NetworkHelper* network_helper_; const bool drop_response_body_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_stream.h index db7588bb81..9645240006 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_stream.h @@ -22,7 +22,7 @@ class QuicSimpleClientStream : public QuicSpdyClientStream { void OnBodyAvailable() override; void set_on_interim_headers( - quiche::MultiUseCallback + quiche::MultiUseCallback on_interim_headers) { on_interim_headers_ = std::move(on_interim_headers); } @@ -31,7 +31,7 @@ class QuicSimpleClientStream : public QuicSpdyClientStream { bool ParseAndValidateStatusCode() override; private: - quiche::MultiUseCallback + quiche::MultiUseCallback on_interim_headers_; const bool drop_response_body_; }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_backend.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_backend.h index a142dd8552..4d28b32c13 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_backend.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_backend.h @@ -15,7 +15,7 @@ #include "quiche/quic/core/socket_factory.h" #include "quiche/quic/core/web_transport_interface.h" #include "quiche/quic/tools/quic_backend_response.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -50,7 +50,7 @@ class QuicSimpleServerBackend { }; struct WebTransportResponse { - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; std::unique_ptr visitor; }; @@ -73,7 +73,7 @@ class QuicSimpleServerBackend { // // Not called for requests using the CONNECT method. virtual void FetchResponseFromBackend( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, const std::string& request_body, RequestHandler* request_handler) = 0; // Handles headers for requests using the CONNECT method. Called immediately @@ -84,9 +84,9 @@ class QuicSimpleServerBackend { // If not overridden by backend, sends an error appropriate for a server that // does not handle CONNECT requests. virtual void HandleConnectHeaders( - const spdy::Http2HeaderBlock& /*request_headers*/, + const quiche::HttpHeaderBlock& /*request_headers*/, RequestHandler* request_handler) { - spdy::Http2HeaderBlock headers; + quiche::HttpHeaderBlock headers; headers[":status"] = "405"; QuicBackendResponse response; response.set_headers(std::move(headers)); @@ -108,7 +108,7 @@ class QuicSimpleServerBackend { virtual void CloseBackendResponseStream(RequestHandler* request_handler) = 0; virtual WebTransportResponse ProcessWebTransportRequest( - const spdy::Http2HeaderBlock& /*request_headers*/, + const quiche::HttpHeaderBlock& /*request_headers*/, WebTransportSession* /*session*/) { WebTransportResponse response; response.response_headers[":status"] = "400"; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.h index 14516f570c..476f074669 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_session.h @@ -23,7 +23,7 @@ #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_simple_server_backend.h" #include "quiche/quic/tools/quic_simple_server_stream.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc index b71b448538..d8bfa58b39 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.cc @@ -25,7 +25,7 @@ #include "quiche/quic/tools/quic_simple_server_session.h" #include "quiche/spdy/core/spdy_protocol.h" -using spdy::Http2HeaderBlock; +using quiche::HttpHeaderBlock; namespace quic { @@ -310,7 +310,7 @@ void QuicSimpleServerStream::Respond(const QuicBackendResponse* response) { std::string request_url = request_headers_[":authority"].as_string() + request_headers_[":path"].as_string(); int response_code; - const Http2HeaderBlock& response_headers = response->headers(); + const HttpHeaderBlock& response_headers = response->headers(); if (!ParseHeaderStatusCode(response_headers, &response_code)) { auto status = response_headers.find(":status"); if (status == response_headers.end()) { @@ -341,7 +341,7 @@ void QuicSimpleServerStream::Respond(const QuicBackendResponse* response) { SendNotFoundResponse(); return; } - Http2HeaderBlock headers = response->headers().Clone(); + HttpHeaderBlock headers = response->headers().Clone(); headers["content-length"] = absl::StrCat(generate_bytes_length_); WriteHeaders(std::move(headers), false, nullptr); @@ -366,7 +366,7 @@ void QuicSimpleServerStream::SendStreamData(absl::string_view data, if (close_stream) { SendHeadersAndBodyAndTrailers( /*response_headers=*/std::nullopt, data, - /*response_trailers=*/spdy::Http2HeaderBlock()); + /*response_trailers=*/quiche::HttpHeaderBlock()); } else { SendIncompleteResponse(/*response_headers=*/std::nullopt, data); } @@ -397,7 +397,7 @@ void QuicSimpleServerStream::WriteGeneratedBytes() { void QuicSimpleServerStream::SendNotFoundResponse() { QUIC_DVLOG(1) << "Stream " << id() << " sending not found response."; - Http2HeaderBlock headers; + HttpHeaderBlock headers; headers[":status"] = "404"; headers["content-length"] = absl::StrCat(strlen(kNotFoundResponseBody)); SendHeadersAndBody(std::move(headers), kNotFoundResponseBody); @@ -410,7 +410,7 @@ void QuicSimpleServerStream::SendErrorResponse(int resp_code) { if (!reading_stopped()) { StopReading(); } - Http2HeaderBlock headers; + HttpHeaderBlock headers; if (resp_code <= 0) { headers[":status"] = "500"; } else { @@ -421,7 +421,7 @@ void QuicSimpleServerStream::SendErrorResponse(int resp_code) { } void QuicSimpleServerStream::SendIncompleteResponse( - std::optional response_headers, absl::string_view body) { + std::optional response_headers, absl::string_view body) { // Headers should be sent iff not sent in a previous response. QUICHE_DCHECK_NE(response_headers.has_value(), response_sent_); @@ -445,14 +445,14 @@ void QuicSimpleServerStream::SendIncompleteResponse( } void QuicSimpleServerStream::SendHeadersAndBody( - Http2HeaderBlock response_headers, absl::string_view body) { + HttpHeaderBlock response_headers, absl::string_view body) { SendHeadersAndBodyAndTrailers(std::move(response_headers), body, - Http2HeaderBlock()); + HttpHeaderBlock()); } void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers( - std::optional response_headers, absl::string_view body, - Http2HeaderBlock response_trailers) { + std::optional response_headers, absl::string_view body, + HttpHeaderBlock response_trailers) { // Headers should be sent iff not sent in a previous response. QUICHE_DCHECK_NE(response_headers.has_value(), response_sent_); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.h index 998429a980..3e9a6918ec 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_simple_server_stream.h @@ -14,7 +14,7 @@ #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/tools/quic_backend_response.h" #include "quiche/quic/tools/quic_simple_server_backend.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/spdy/core/spdy_framer.h" namespace quic { @@ -79,16 +79,16 @@ class QuicSimpleServerStream : public QuicSpdyServerStreamBase, // Sends the response header (if not `std::nullopt`) and body, but not the // fin. void SendIncompleteResponse( - std::optional response_headers, + std::optional response_headers, absl::string_view body); - void SendHeadersAndBody(spdy::Http2HeaderBlock response_headers, + void SendHeadersAndBody(quiche::HttpHeaderBlock response_headers, absl::string_view body); void SendHeadersAndBodyAndTrailers( - std::optional response_headers, - absl::string_view body, spdy::Http2HeaderBlock response_trailers); + std::optional response_headers, + absl::string_view body, quiche::HttpHeaderBlock response_trailers); - spdy::Http2HeaderBlock* request_headers() { return &request_headers_; } + quiche::HttpHeaderBlock* request_headers() { return &request_headers_; } // Returns true iff the request (per saved `request_headers_`) is a CONNECT or // Extended CONNECT request. @@ -107,7 +107,7 @@ class QuicSimpleServerStream : public QuicSpdyServerStreamBase, bool response_sent() const { return response_sent_; } void set_response_sent() { response_sent_ = true; } // The parsed headers received from the client. - spdy::Http2HeaderBlock request_headers_; + quiche::HttpHeaderBlock request_headers_; int64_t content_length_; std::string body_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.cc index be166536bb..f065a7d7fb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.cc @@ -21,7 +21,7 @@ #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/common/quiche_text_utils.h" -using spdy::Http2HeaderBlock; +using quiche::HttpHeaderBlock; namespace quic { @@ -64,7 +64,7 @@ void QuicSpdyClientBase::OnClose(QuicSpdyStream* stream) { QuicSpdyClientStream* client_stream = static_cast(stream); - const Http2HeaderBlock& response_headers = client_stream->response_headers(); + const HttpHeaderBlock& response_headers = client_stream->response_headers(); if (response_listener_ != nullptr) { response_listener_->OnCompleteResponse(stream->id(), response_headers, client_stream->data()); @@ -79,7 +79,7 @@ void QuicSpdyClientBase::OnClose(QuicSpdyStream* stream) { QUIC_LOG(ERROR) << "Invalid :status response header: " << status->second; } latest_response_headers_ = response_headers.DebugString(); - for (const Http2HeaderBlock& headers : + for (const HttpHeaderBlock& headers : client_stream->preliminary_headers()) { absl::StrAppend(&preliminary_response_headers_, headers.DebugString()); } @@ -99,11 +99,11 @@ std::unique_ptr QuicSpdyClientBase::CreateQuicClientSession( *config(), supported_versions, connection, server_id(), crypto_config()); } -void QuicSpdyClientBase::SendRequest(const Http2HeaderBlock& headers, +void QuicSpdyClientBase::SendRequest(const HttpHeaderBlock& headers, absl::string_view body, bool fin) { if (GetQuicFlag(quic_client_convert_http_header_name_to_lowercase)) { QUIC_CODE_COUNT(quic_client_convert_http_header_name_to_lowercase); - Http2HeaderBlock sanitized_headers; + HttpHeaderBlock sanitized_headers; for (const auto& p : headers) { sanitized_headers[quiche::QuicheTextUtils::ToLower(p.first)] = p.second; } @@ -114,7 +114,7 @@ void QuicSpdyClientBase::SendRequest(const Http2HeaderBlock& headers, } } -void QuicSpdyClientBase::SendRequestInternal(Http2HeaderBlock sanitized_headers, +void QuicSpdyClientBase::SendRequestInternal(HttpHeaderBlock sanitized_headers, absl::string_view body, bool fin) { QuicSpdyClientStream* stream = CreateClientStream(); if (stream == nullptr) { @@ -125,7 +125,7 @@ void QuicSpdyClientBase::SendRequestInternal(Http2HeaderBlock sanitized_headers, } void QuicSpdyClientBase::SendRequestAndWaitForResponse( - const Http2HeaderBlock& headers, absl::string_view body, bool fin) { + const HttpHeaderBlock& headers, absl::string_view body, bool fin) { SendRequest(headers, body, fin); while (WaitForEvents()) { } @@ -134,7 +134,7 @@ void QuicSpdyClientBase::SendRequestAndWaitForResponse( void QuicSpdyClientBase::SendRequestsAndWaitForResponse( const std::vector& url_list) { for (size_t i = 0; i < url_list.size(); ++i) { - Http2HeaderBlock headers; + HttpHeaderBlock headers; if (!SpdyUtils::PopulateHeaderBlockFromUrl(url_list[i], &headers)) { QUIC_BUG(quic_bug_10949_2) << "Unable to create request"; continue; @@ -203,7 +203,7 @@ const std::string& QuicSpdyClientBase::preliminary_response_headers() const { return preliminary_response_headers_; } -const Http2HeaderBlock& QuicSpdyClientBase::latest_response_header_block() +const HttpHeaderBlock& QuicSpdyClientBase::latest_response_header_block() const { QUIC_BUG_IF(quic_bug_10949_6, !store_response_) << "Response not stored!"; return latest_response_header_block_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.h index a6ef509073..f65758f49d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_spdy_client_base.h @@ -17,7 +17,7 @@ #include "quiche/quic/core/quic_config.h" #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/tools/quic_client_base.h" -#include "quiche/spdy/core/http2_header_block.h" +#include "quiche/common/http/http_header_block.h" namespace quic { @@ -34,7 +34,7 @@ class QuicSpdyClientBase : public QuicClientBase, ResponseListener() {} virtual ~ResponseListener() {} virtual void OnCompleteResponse( - QuicStreamId id, const spdy::Http2HeaderBlock& response_headers, + QuicStreamId id, const quiche::HttpHeaderBlock& response_headers, absl::string_view response_body) = 0; }; @@ -59,11 +59,11 @@ class QuicSpdyClientBase : public QuicClientBase, void InitializeSession() override; // Sends an HTTP request and does not wait for response before returning. - void SendRequest(const spdy::Http2HeaderBlock& headers, + void SendRequest(const quiche::HttpHeaderBlock& headers, absl::string_view body, bool fin); // Sends an HTTP request and waits for response before returning. - void SendRequestAndWaitForResponse(const spdy::Http2HeaderBlock& headers, + void SendRequestAndWaitForResponse(const quiche::HttpHeaderBlock& headers, absl::string_view body, bool fin); // Sends a request simple GET for each URL in |url_list|, and then waits for @@ -83,7 +83,7 @@ class QuicSpdyClientBase : public QuicClientBase, int latest_response_code() const; const std::string& latest_response_headers() const; const std::string& preliminary_response_headers() const; - const spdy::Http2HeaderBlock& latest_response_header_block() const; + const quiche::HttpHeaderBlock& latest_response_header_block() const; const std::string& latest_response_body() const; const std::string& latest_response_trailers() const; @@ -136,7 +136,7 @@ class QuicSpdyClientBase : public QuicClientBase, bool HasActiveRequests() override; private: - void SendRequestInternal(spdy::Http2HeaderBlock sanitized_headers, + void SendRequestInternal(quiche::HttpHeaderBlock sanitized_headers, absl::string_view body, bool fin); // If true, store the latest response code, headers, and body. @@ -148,7 +148,7 @@ class QuicSpdyClientBase : public QuicClientBase, // preliminary 100 Continue HTTP/2 headers from most recent response, if any. std::string preliminary_response_headers_; // HTTP/2 headers from most recent response. - spdy::Http2HeaderBlock latest_response_header_block_; + quiche::HttpHeaderBlock latest_response_header_block_; // Body of most recent response. std::string latest_response_body_; // HTTP/2 trailers from most recent response. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.cc index 2fae8e549f..79aafb760a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.cc @@ -62,10 +62,10 @@ #include "quiche/quic/platform/api/quic_socket_address.h" #include "quiche/quic/tools/fake_proof_verifier.h" #include "quiche/quic/tools/quic_url.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_command_line_flags.h" #include "quiche/common/platform/api/quiche_logging.h" #include "quiche/common/quiche_text_utils.h" -#include "quiche/spdy/core/http2_header_block.h" namespace { @@ -437,7 +437,7 @@ int QuicToyClient::SendRequestsAndPrintResponses( } // Construct a GET or POST request for supplied URL. - spdy::Http2HeaderBlock header_block; + quiche::HttpHeaderBlock header_block; header_block[":method"] = body.empty() ? "GET" : "POST"; header_block[":scheme"] = url.scheme(); header_block[":authority"] = url.HostPort(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/web_transport_only_backend.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/web_transport_only_backend.h index cd37672bcc..b2fd03614b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/web_transport_only_backend.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/web_transport_only_backend.h @@ -13,9 +13,9 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/web_transport_interface.h" #include "quiche/quic/tools/quic_simple_server_backend.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/quiche_callbacks.h" #include "quiche/web_transport/web_transport.h" -#include "quiche/spdy/core/http2_header_block.h" namespace quic { @@ -33,13 +33,13 @@ class WebTransportOnlyBackend : public QuicSimpleServerBackend { // QuicSimpleServerBackend implementation. bool InitializeBackend(const std::string&) override { return true; } bool IsBackendInitialized() const override { return true; } - void FetchResponseFromBackend(const spdy::Http2HeaderBlock&, + void FetchResponseFromBackend(const quiche::HttpHeaderBlock&, const std::string&, RequestHandler* request_handler) override; void CloseBackendResponseStream(RequestHandler*) override {} bool SupportsWebTransport() override { return true; } WebTransportResponse ProcessWebTransportRequest( - const spdy::Http2HeaderBlock& request_headers, + const quiche::HttpHeaderBlock& request_headers, WebTransportSession* session) override; private: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.cc index b982778742..ce3dcbb14c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.cc @@ -8,11 +8,11 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" #include "quiche/http2/decoder/decode_buffer.h" #include "quiche/http2/hpack/decoder/hpack_decoding_error.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" namespace spdy { namespace { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.h index d3d3dec069..a675df9cf6 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.h @@ -13,13 +13,13 @@ #include #include "absl/strings/string_view.h" +#include "quiche/http2/core/no_op_headers_handler.h" +#include "quiche/http2/core/spdy_headers_handler_interface.h" #include "quiche/http2/hpack/decoder/hpack_decoder.h" #include "quiche/http2/hpack/decoder/hpack_decoder_listener.h" #include "quiche/http2/hpack/decoder/hpack_decoding_error.h" +#include "quiche/common/http/http_header_block.h" #include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/no_op_headers_handler.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" namespace spdy { namespace test { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.h index 35007c674a..8e746c8c39 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.h @@ -5,152 +5,8 @@ #ifndef QUICHE_SPDY_CORE_HPACK_HPACK_ENCODER_H_ #define QUICHE_SPDY_CORE_HPACK_HPACK_ENCODER_H_ -#include +#include "quiche/http2/hpack/hpack_encoder.h" -#include -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "quiche/common/platform/api/quiche_export.h" -#include "quiche/common/quiche_callbacks.h" -#include "quiche/spdy/core/hpack/hpack_header_table.h" -#include "quiche/spdy/core/hpack/hpack_output_stream.h" -#include "quiche/spdy/core/http2_header_block.h" - -// An HpackEncoder encodes header sets as outlined in -// http://tools.ietf.org/html/rfc7541. - -namespace spdy { - -namespace test { -class HpackEncoderPeer; -} // namespace test - -class QUICHE_EXPORT HpackEncoder { - public: - using Representation = std::pair; - using Representations = std::vector; - - // Callers may provide a HeaderListener to be informed of header name-value - // pairs processed by this encoder. - using HeaderListener = - quiche::MultiUseCallback; - - // An indexing policy should return true if the provided header name-value - // pair should be inserted into the HPACK dynamic table. - using IndexingPolicy = - quiche::MultiUseCallback; - - HpackEncoder(); - HpackEncoder(const HpackEncoder&) = delete; - HpackEncoder& operator=(const HpackEncoder&) = delete; - ~HpackEncoder(); - - // Encodes and returns the given header set as a string. - std::string EncodeHeaderBlock(const Http2HeaderBlock& header_set); - - class QUICHE_EXPORT ProgressiveEncoder { - public: - virtual ~ProgressiveEncoder() {} - - // Returns true iff more remains to encode. - virtual bool HasNext() const = 0; - - // Encodes and returns up to max_encoded_bytes of the current header block. - virtual std::string Next(size_t max_encoded_bytes) = 0; - }; - - // Returns a ProgressiveEncoder which must be outlived by both the given - // Http2HeaderBlock and this object. - std::unique_ptr EncodeHeaderSet( - const Http2HeaderBlock& header_set); - // Returns a ProgressiveEncoder which must be outlived by this HpackEncoder. - // The encoder will not attempt to split any \0-delimited values in - // |representations|. If such splitting is desired, it must be performed by - // the caller when constructing the list of representations. - std::unique_ptr EncodeRepresentations( - const Representations& representations); - - // Called upon a change to SETTINGS_HEADER_TABLE_SIZE. Specifically, this - // is to be called after receiving (and sending an acknowledgement for) a - // SETTINGS_HEADER_TABLE_SIZE update from the remote decoding endpoint. - void ApplyHeaderTableSizeSetting(size_t size_setting); - - // TODO(birenroy): Rename this GetDynamicTableCapacity(). - size_t CurrentHeaderTableSizeSetting() const { - return header_table_.settings_size_bound(); - } - - // This HpackEncoder will use |policy| to determine whether to insert header - // name-value pairs into the dynamic table. - void SetIndexingPolicy(IndexingPolicy policy) { - should_index_ = std::move(policy); - } - - // |listener| will be invoked for each header name-value pair processed by - // this encoder. - void SetHeaderListener(HeaderListener listener) { - listener_ = std::move(listener); - } - - void DisableCompression() { enable_compression_ = false; } - - // Disables the deconstruction of Cookie header values into individual - // components, as described in - // https://httpwg.org/specs/rfc9113.html#CompressCookie. The deconstructed - // representation can cause problems for some HTTP/2 endpoints. - void DisableCookieCrumbling() { crumble_cookies_ = false; } - - // Returns the current dynamic table size, including the 32 bytes per entry - // overhead mentioned in RFC 7541 section 4.1. - size_t GetDynamicTableSize() const { return header_table_.size(); } - - private: - friend class test::HpackEncoderPeer; - - class RepresentationIterator; - class Encoderator; - - // Encodes a sequence of header name-value pairs as a single header block. - std::string EncodeRepresentations(RepresentationIterator* iter); - - // Emits a static/dynamic indexed representation (Section 7.1). - void EmitIndex(size_t index); - - // Emits a literal representation (Section 7.2). - void EmitIndexedLiteral(const Representation& representation); - void EmitNonIndexedLiteral(const Representation& representation, - bool enable_compression); - void EmitLiteral(const Representation& representation); - - // Emits a Huffman or identity string (whichever is smaller). - void EmitString(absl::string_view str); - - // Emits the current dynamic table size if the table size was recently - // updated and we have not yet emitted it (Section 6.3). - void MaybeEmitTableSize(); - - // Crumbles a cookie header into ";" delimited crumbs. - static void CookieToCrumbs(const Representation& cookie, - Representations* crumbs_out); - - // Crumbles other header field values at \0 delimiters. - static void DecomposeRepresentation(const Representation& header_field, - Representations* out); - - HpackHeaderTable header_table_; - HpackOutputStream output_stream_; - - size_t min_table_size_setting_received_; - HeaderListener listener_; - IndexingPolicy should_index_; - bool enable_compression_; - bool should_emit_table_size_; - bool crumble_cookies_; -}; - -} // namespace spdy +// TODO(b/234438854): remove this file once Envoy has migrated to the new target #endif // QUICHE_SPDY_CORE_HPACK_HPACK_ENCODER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.h index fab2669805..dd788096f9 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.h @@ -5,562 +5,6 @@ #ifndef QUICHE_SPDY_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_ #define QUICHE_SPDY_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_ -#include - -#include -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "quiche/http2/decoder/decode_status.h" -#include "quiche/http2/decoder/http2_frame_decoder.h" -#include "quiche/http2/decoder/http2_frame_decoder_listener.h" -#include "quiche/http2/http2_constants.h" -#include "quiche/http2/http2_structures.h" -#include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/hpack/hpack_decoder_adapter.h" -#include "quiche/spdy/core/spdy_alt_svc_wire_format.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" -#include "quiche/spdy/core/spdy_protocol.h" - -namespace spdy { - -class SpdyFramerVisitorInterface; -class ExtensionVisitorInterface; - -} // namespace spdy - -// TODO(dahollings): Perform various renames/moves suggested in cl/164660364. - -namespace http2 { - -// Adapts SpdyFramer interface to use Http2FrameDecoder. -class QUICHE_EXPORT Http2DecoderAdapter - : public http2::Http2FrameDecoderListener { - public: - // HTTP2 states. - enum SpdyState { - SPDY_ERROR, - SPDY_READY_FOR_FRAME, // Framer is ready for reading the next frame. - SPDY_FRAME_COMPLETE, // Framer has finished reading a frame, need to reset. - SPDY_READING_COMMON_HEADER, - SPDY_CONTROL_FRAME_PAYLOAD, - SPDY_READ_DATA_FRAME_PADDING_LENGTH, - SPDY_CONSUME_PADDING, - SPDY_IGNORE_REMAINING_PAYLOAD, - SPDY_FORWARD_STREAM_FRAME, - SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, - SPDY_CONTROL_FRAME_HEADER_BLOCK, - SPDY_GOAWAY_FRAME_PAYLOAD, - SPDY_SETTINGS_FRAME_HEADER, - SPDY_SETTINGS_FRAME_PAYLOAD, - SPDY_ALTSVC_FRAME_PAYLOAD, - SPDY_EXTENSION_FRAME_PAYLOAD, - }; - - // Framer error codes. - enum SpdyFramerError { - SPDY_NO_ERROR, - SPDY_INVALID_STREAM_ID, // Stream ID is invalid - SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted. - SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large. - SPDY_DECOMPRESS_FAILURE, // There was an error decompressing. - SPDY_INVALID_PADDING, // HEADERS or DATA frame padding invalid - SPDY_INVALID_DATA_FRAME_FLAGS, // Data frame has invalid flags. - SPDY_UNEXPECTED_FRAME, // Frame received out of order. - SPDY_INTERNAL_FRAMER_ERROR, // SpdyFramer was used incorrectly. - SPDY_INVALID_CONTROL_FRAME_SIZE, // Control frame not sized to spec - SPDY_OVERSIZED_PAYLOAD, // Payload size was too large - - // HttpDecoder or HttpDecoderAdapter error. - // See HpackDecodingError for description of each error code. - SPDY_HPACK_INDEX_VARINT_ERROR, - SPDY_HPACK_NAME_LENGTH_VARINT_ERROR, - SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR, - SPDY_HPACK_NAME_TOO_LONG, - SPDY_HPACK_VALUE_TOO_LONG, - SPDY_HPACK_NAME_HUFFMAN_ERROR, - SPDY_HPACK_VALUE_HUFFMAN_ERROR, - SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE, - SPDY_HPACK_INVALID_INDEX, - SPDY_HPACK_INVALID_NAME_INDEX, - SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED, - SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK, - SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING, - SPDY_HPACK_TRUNCATED_BLOCK, - SPDY_HPACK_FRAGMENT_TOO_LONG, - SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT, - - // Set if the visitor no longer wishes to receive events for this - // connection. - SPDY_STOP_PROCESSING, - - LAST_ERROR, // Must be the last entry in the enum. - }; - - // For debugging. - static const char* StateToString(int state); - static const char* SpdyFramerErrorToString(SpdyFramerError spdy_framer_error); - - Http2DecoderAdapter(); - ~Http2DecoderAdapter() override; - - Http2DecoderAdapter(const Http2DecoderAdapter&) = delete; - Http2DecoderAdapter& operator=(const Http2DecoderAdapter&) = delete; - - // Set callbacks to be called from the framer. A visitor must be set, or - // else the framer will likely crash. It is acceptable for the visitor - // to do nothing. If this is called multiple times, only the last visitor - // will be used. - void set_visitor(spdy::SpdyFramerVisitorInterface* visitor); - spdy::SpdyFramerVisitorInterface* visitor() const { return visitor_; } - - // Set extension callbacks to be called from the framer or decoder. Optional. - // If called multiple times, only the last visitor will be used. - void set_extension_visitor(spdy::ExtensionVisitorInterface* visitor); - spdy::ExtensionVisitorInterface* extension_visitor() const { - return extension_; - } - - // Set debug callbacks to be called from the framer. The debug visitor is - // completely optional and need not be set in order for normal operation. - // If this is called multiple times, only the last visitor will be used. - void set_debug_visitor(spdy::SpdyFramerDebugVisitorInterface* debug_visitor); - spdy::SpdyFramerDebugVisitorInterface* debug_visitor() const { - return debug_visitor_; - } - - // Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns - // the number of bytes consumed. It is safe to pass more bytes in than - // may be consumed. Should process (or otherwise buffer) as much as - // available. - // - // If the input contains the entirety of a DATA frame payload, GOAWAY frame - // Additional Debug Data field, or unknown frame payload, then the - // corresponding SpdyFramerVisitorInterface::OnStreamFrameData(), - // OnGoAwayFrameData(), or ExtensionVisitorInterface::OnFramePayload() method - // is guaranteed to be called exactly once, with the entire payload or field. - size_t ProcessInput(const char* data, size_t len); - - // Current state of the decoder. - SpdyState state() const; - - // Current error code (NO_ERROR if state != ERROR). - SpdyFramerError spdy_framer_error() const; - - // Has any frame header looked like the start of an HTTP/1.1 (or earlier) - // response? Used to detect if a backend/server that we sent a request to - // has responded with an HTTP/1.1 (or earlier) response. - bool probable_http_response() const; - - spdy::HpackDecoderAdapter& GetHpackDecoder() { return hpack_decoder_; } - const spdy::HpackDecoderAdapter& GetHpackDecoder() const { - return hpack_decoder_; - } - - bool HasError() const; - - // A visitor may call this method to indicate it no longer wishes to receive - // events for this connection. - void StopProcessing(); - - // Sets the limit on the size of received HTTP/2 frame payloads. Corresponds - // to SETTINGS_MAX_FRAME_SIZE as advertised to the peer. - void SetMaxFrameSize(size_t max_frame_size); - - private: - bool OnFrameHeader(const Http2FrameHeader& header) override; - void OnDataStart(const Http2FrameHeader& header) override; - void OnDataPayload(const char* data, size_t len) override; - void OnDataEnd() override; - void OnHeadersStart(const Http2FrameHeader& header) override; - void OnHeadersPriority(const Http2PriorityFields& priority) override; - void OnHpackFragment(const char* data, size_t len) override; - void OnHeadersEnd() override; - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority) override; - void OnContinuationStart(const Http2FrameHeader& header) override; - void OnContinuationEnd() override; - void OnPadLength(size_t trailing_length) override; - void OnPadding(const char* padding, size_t skipped_length) override; - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode http2_error_code) override; - void OnSettingsStart(const Http2FrameHeader& header) override; - void OnSetting(const Http2SettingFields& setting_fields) override; - void OnSettingsEnd() override; - void OnSettingsAck(const Http2FrameHeader& header) override; - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override; - void OnPushPromiseEnd() override; - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override; - void OnGoAwayOpaqueData(const char* data, size_t len) override; - void OnGoAwayEnd() override; - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t increment) override; - void OnAltSvcStart(const Http2FrameHeader& header, size_t origin_length, - size_t value_length) override; - void OnAltSvcOriginData(const char* data, size_t len) override; - void OnAltSvcValueData(const char* data, size_t len) override; - void OnAltSvcEnd() override; - void OnPriorityUpdateStart( - const Http2FrameHeader& header, - const Http2PriorityUpdateFields& priority_update) override; - void OnPriorityUpdatePayload(const char* data, size_t len) override; - void OnPriorityUpdateEnd() override; - void OnUnknownStart(const Http2FrameHeader& header) override; - void OnUnknownPayload(const char* data, size_t len) override; - void OnUnknownEnd() override; - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override; - void OnFrameSizeError(const Http2FrameHeader& header) override; - - size_t ProcessInputFrame(const char* data, size_t len); - - void DetermineSpdyState(DecodeStatus status); - void ResetBetweenFrames(); - - void set_spdy_state(SpdyState v); - - void SetSpdyErrorAndNotify(SpdyFramerError error, std::string detailed_error); - - const Http2FrameHeader& frame_header() const; - - uint32_t stream_id() const; - Http2FrameType frame_type() const; - - size_t remaining_total_payload() const; - - bool IsReadingPaddingLength(); - bool IsSkippingPadding(); - bool IsDiscardingPayload(); - // Called from OnXyz or OnXyzStart methods to decide whether it is OK to - // handle the callback. - bool IsOkToStartFrame(const Http2FrameHeader& header); - bool HasRequiredStreamId(uint32_t stream_id); - - bool HasRequiredStreamId(const Http2FrameHeader& header); - - bool HasRequiredStreamIdZero(uint32_t stream_id); - - bool HasRequiredStreamIdZero(const Http2FrameHeader& header); - - void ReportReceiveCompressedFrame(const Http2FrameHeader& header); - - void CommonStartHpackBlock(); - - // SpdyFramer calls HandleControlFrameHeadersData even if there are zero - // fragment bytes in the first frame, so do the same. - void MaybeAnnounceEmptyFirstHpackFragment(); - void CommonHpackFragmentEnd(); - - // The most recently decoded frame header; invalid after we reached the end - // of that frame. - Http2FrameHeader frame_header_; - - // If decoding an HPACK block that is split across multiple frames, this holds - // the frame header of the HEADERS or PUSH_PROMISE that started the block. - Http2FrameHeader hpack_first_frame_header_; - - // Amount of trailing padding. Currently used just as an indicator of whether - // OnPadLength has been called. - std::optional opt_pad_length_; - - // Temporary buffers for the AltSvc fields. - std::string alt_svc_origin_; - std::string alt_svc_value_; - - // Temporary buffers for PRIORITY_UPDATE fields. - uint32_t prioritized_stream_id_ = 0; - std::string priority_field_value_; - - // Listener used if we transition to an error state; the listener ignores all - // the callbacks. - Http2FrameDecoderNoOpListener no_op_listener_; - - spdy::SpdyFramerVisitorInterface* visitor_ = nullptr; - spdy::SpdyFramerDebugVisitorInterface* debug_visitor_ = nullptr; - - // If non-null, unknown frames and settings are passed to the extension. - spdy::ExtensionVisitorInterface* extension_ = nullptr; - - // The HPACK decoder to be used for this adapter. - spdy::HpackDecoderAdapter hpack_decoder_; - - // The HTTP/2 frame decoder. - Http2FrameDecoder frame_decoder_; - - // Next frame type expected. Currently only used for CONTINUATION frames, - // but could be used for detecting whether the first frame is a SETTINGS - // frame. - // TODO(jamessynge): Provide means to indicate that decoder should require - // SETTINGS frame as the first frame. - Http2FrameType expected_frame_type_; - - // Attempt to duplicate the SpdyState and SpdyFramerError values that - // SpdyFramer sets. Values determined by getting tests to pass. - SpdyState spdy_state_ = SpdyState::SPDY_READY_FOR_FRAME; - SpdyFramerError spdy_framer_error_ = SpdyFramerError::SPDY_NO_ERROR; - - // The limit on the size of received HTTP/2 payloads as specified in the - // SETTINGS_MAX_FRAME_SIZE advertised to peer. - size_t max_frame_size_ = spdy::kHttp2DefaultFramePayloadLimit; - - // Has OnFrameHeader been called? - bool decoded_frame_header_ = false; - - // Have we recorded an Http2FrameHeader for the current frame? - // We only do so if the decoder will make multiple callbacks for - // the frame; for example, for PING frames we don't make record - // the frame header, but for ALTSVC we do. - bool has_frame_header_ = false; - - // Have we recorded an Http2FrameHeader for the current HPACK block? - // True only for multi-frame HPACK blocks. - bool has_hpack_first_frame_header_ = false; - - // Has OnHeaders() already been called for current HEADERS block? Only - // meaningful between OnHeadersStart and OnHeadersPriority. - bool on_headers_called_ = false; - - // Has OnHpackFragment() already been called for current HPACK block? - // SpdyFramer will pass an empty buffer to the HPACK decoder if a HEADERS - // or PUSH_PROMISE has no HPACK data in it (e.g. a HEADERS frame with only - // padding). Detect that condition and replicate the behavior using this - // field. - bool on_hpack_fragment_called_ = false; - - // Have we seen a frame header that appears to be an HTTP/1 response? - bool latched_probable_http_response_ = false; - - // Is expected_frame_type_ set? - bool has_expected_frame_type_ = false; - - // Is the current frame payload destined for |extension_|? - bool handling_extension_payload_ = false; -}; - -} // namespace http2 - -namespace spdy { - -// Http2DecoderAdapter will use the given visitor implementing this -// interface to deliver event callbacks as frames are decoded. -// -// Control frames that contain HTTP2 header blocks (HEADER, and PUSH_PROMISE) -// are processed in fashion that allows the decompressed header block to be -// delivered in chunks to the visitor. -// The following steps are followed: -// 1. OnHeaders, or OnPushPromise is called. -// 2. OnHeaderFrameStart is called; visitor is expected to return an instance -// of SpdyHeadersHandlerInterface that will receive the header key-value -// pairs. -// 3. OnHeaderFrameEnd is called, indicating that the full header block has -// been delivered for the control frame. -// During step 2, if the visitor is not interested in accepting the header data, -// it should return a no-op implementation of SpdyHeadersHandlerInterface. -class QUICHE_EXPORT SpdyFramerVisitorInterface { - public: - virtual ~SpdyFramerVisitorInterface() {} - - // Called if an error is detected in the SpdyFrame protocol. - virtual void OnError(http2::Http2DecoderAdapter::SpdyFramerError error, - std::string detailed_error) = 0; - - // Called when the common header for a frame is received. Validating the - // common header occurs in later processing. - virtual void OnCommonHeader(SpdyStreamId /*stream_id*/, size_t /*length*/, - uint8_t /*type*/, uint8_t /*flags*/) {} - - // Called when a data frame header is received. The frame's data payload will - // be provided via subsequent calls to OnStreamFrameData(). - // |stream_id| The stream receiving data. - // |length| The length of the payload in this DATA frame. Includes the length - // of the data itself and potential padding. - // |fin| Whether the END_STREAM flag is set in the frame header. - virtual void OnDataFrameHeader(SpdyStreamId stream_id, size_t length, - bool fin) = 0; - - // Called when data is received. - // |stream_id| The stream receiving data. - // |data| A buffer containing the data received. - // |len| The length of the data buffer. - virtual void OnStreamFrameData(SpdyStreamId stream_id, const char* data, - size_t len) = 0; - - // Called when the other side has finished sending data on this stream. - // |stream_id| The stream that was receiving data. - virtual void OnStreamEnd(SpdyStreamId stream_id) = 0; - - // Called when padding length field is received on a DATA frame. - // |stream_id| The stream receiving data. - // |value| The value of the padding length field. - virtual void OnStreamPadLength(SpdyStreamId /*stream_id*/, size_t /*value*/) { - } - - // Called when padding is received (the trailing octets, not pad_len field) on - // a DATA frame. - // |stream_id| The stream receiving data. - // |len| The number of padding octets. - virtual void OnStreamPadding(SpdyStreamId stream_id, size_t len) = 0; - - // Called just before processing the payload of a frame containing header - // data. Should return an implementation of SpdyHeadersHandlerInterface that - // will receive headers for stream |stream_id|. The caller will not take - // ownership of the headers handler. The same instance should remain live - // and be returned for all header frames comprising a logical header block - // (i.e. until OnHeaderFrameEnd() is called). - virtual SpdyHeadersHandlerInterface* OnHeaderFrameStart( - SpdyStreamId stream_id) = 0; - - // Called after processing the payload of a frame containing header data. - virtual void OnHeaderFrameEnd(SpdyStreamId stream_id) = 0; - - // Called when a RST_STREAM frame has been parsed. - virtual void OnRstStream(SpdyStreamId stream_id, - SpdyErrorCode error_code) = 0; - - // Called when a SETTINGS frame is received. - virtual void OnSettings() {} - - // Called when a complete setting within a SETTINGS frame has been parsed. - // Note that |id| may or may not be a SETTINGS ID defined in the HTTP/2 spec. - virtual void OnSetting(SpdySettingsId id, uint32_t value) = 0; - - // Called when a SETTINGS frame is received with the ACK flag set. - virtual void OnSettingsAck() {} - - // Called before and after parsing SETTINGS id and value tuples. - virtual void OnSettingsEnd() = 0; - - // Called when a PING frame has been parsed. - virtual void OnPing(SpdyPingId unique_id, bool is_ack) = 0; - - // Called when a GOAWAY frame has been parsed. - virtual void OnGoAway(SpdyStreamId last_accepted_stream_id, - SpdyErrorCode error_code) = 0; - - // Called when a HEADERS frame is received. - // Note that header block data is not included. See OnHeaderFrameStart(). - // |stream_id| The stream receiving the header. - // |payload_length| The length of the payload in this HEADERS frame. Includes - // the length of the encoded header block and potential padding. - // |has_priority| Whether or not the headers frame included a priority value, - // and stream dependency info. - // |weight| If |has_priority| is true, then weight (in the range [1, 256]) - // for the receiving stream, otherwise 0. - // |parent_stream_id| If |has_priority| is true the parent stream of the - // receiving stream, else 0. - // |exclusive| If |has_priority| is true the exclusivity of dependence on the - // parent stream, else false. - // |fin| Whether the END_STREAM flag is set in the frame header. - // |end| False if HEADERs frame is to be followed by a CONTINUATION frame, - // or true if not. - virtual void OnHeaders(SpdyStreamId stream_id, size_t payload_length, - bool has_priority, int weight, - SpdyStreamId parent_stream_id, bool exclusive, - bool fin, bool end) = 0; - - // Called when a WINDOW_UPDATE frame has been parsed. - virtual void OnWindowUpdate(SpdyStreamId stream_id, - int delta_window_size) = 0; - - // Called when a goaway frame opaque data is available. - // |goaway_data| A buffer containing the opaque GOAWAY data chunk received. - // |len| The length of the header data buffer. A length of zero indicates - // that the header data block has been completely sent. - // When this function returns true the visitor indicates that it accepted - // all of the data. Returning false indicates that that an error has - // occurred while processing the data. Default implementation returns true. - virtual bool OnGoAwayFrameData(const char* goaway_data, size_t len); - - // Called when a PUSH_PROMISE frame is received. - // Note that header block data is not included. See OnHeaderFrameStart(). - virtual void OnPushPromise(SpdyStreamId stream_id, - SpdyStreamId promised_stream_id, bool end) = 0; - - // Called when a CONTINUATION frame is received. - // Note that header block data is not included. See OnHeaderFrameStart(). - // |stream_id| The stream receiving the CONTINUATION. - // |payload_length| The length of the payload in this CONTINUATION frame. - // |end| True if this CONTINUATION frame will not be followed by another - // CONTINUATION frame. - virtual void OnContinuation(SpdyStreamId stream_id, size_t payload_length, - bool end) = 0; - - // Called when an ALTSVC frame has been parsed. - virtual void OnAltSvc( - SpdyStreamId /*stream_id*/, absl::string_view /*origin*/, - const SpdyAltSvcWireFormat::AlternativeServiceVector& /*altsvc_vector*/) { - } - - // Called when a PRIORITY frame is received. - // |stream_id| The stream to update the priority of. - // |parent_stream_id| The parent stream of |stream_id|. - // |weight| Stream weight, in the range [1, 256]. - // |exclusive| Whether |stream_id| should be an only child of - // |parent_stream_id|. - virtual void OnPriority(SpdyStreamId stream_id, SpdyStreamId parent_stream_id, - int weight, bool exclusive) = 0; - - // Called when a PRIORITY_UPDATE frame is received on stream 0. - // |prioritized_stream_id| is the Prioritized Stream ID and - // |priority_field_value| is the Priority Field Value - // parsed from the frame payload. - virtual void OnPriorityUpdate(SpdyStreamId prioritized_stream_id, - absl::string_view priority_field_value) = 0; - - // Called when a frame type we don't recognize is received. - // Return true if this appears to be a valid extension frame, false otherwise. - // We distinguish between extension frames and nonsense by checking - // whether the stream id is valid. - // TODO(b/239060116): Remove this callback altogether. - virtual bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) = 0; - - // Called when the common header for a non-standard frame is received. If the - // `length` is nonzero, the frame's payload will be provided via subsequent - // calls to OnUnknownFramePayload(). - // |stream_id| The stream receiving the non-standard frame. - // |length| The length of the payload of the frame. - // |type| The type of the frame. This type is non-standard. - // |flags| The flags of the frame. - virtual void OnUnknownFrameStart(SpdyStreamId stream_id, size_t length, - uint8_t type, uint8_t flags) = 0; - - // Called when a non-empty payload chunk for a non-standard frame is received. - // The payload for a single frame may be delivered as multiple calls to - // OnUnknownFramePayload(). Since the length field is passed in - // OnUnknownFrameStart(), there is no explicit indication of the end of the - // frame payload. - // |stream_id| The stream receiving the non-standard frame. - // |payload| The payload chunk, which will be non-empty. - virtual void OnUnknownFramePayload(SpdyStreamId stream_id, - absl::string_view payload) = 0; -}; - -class QUICHE_EXPORT ExtensionVisitorInterface { - public: - virtual ~ExtensionVisitorInterface() {} - - // Called when non-standard SETTINGS are received. - virtual void OnSetting(SpdySettingsId id, uint32_t value) = 0; - - // Called when non-standard frames are received. - virtual bool OnFrameHeader(SpdyStreamId stream_id, size_t length, - uint8_t type, uint8_t flags) = 0; - - // The payload for a single frame may be delivered as multiple calls to - // OnFramePayload. Since the length field is passed in OnFrameHeader, there is - // no explicit indication of the end of the frame payload. - virtual void OnFramePayload(const char* data, size_t len) = 0; -}; - -} // namespace spdy +#include "quiche/http2/core/http2_frame_decoder_adapter.h" #endif // QUICHE_SPDY_CORE_HTTP2_FRAME_DECODER_ADAPTER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.h index ec0c124cd1..e8ab4914d9 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.h @@ -2,103 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This file contains data structures and utility functions used for serializing -// and parsing alternative service header values, common to HTTP/1.1 header -// fields and HTTP/2 and QUIC ALTSVC frames. See specification at -// https://httpwg.github.io/http-extensions/alt-svc.html. - #ifndef QUICHE_SPDY_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_ #define QUICHE_SPDY_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_ -#include -#include -#include - -#include "absl/container/inlined_vector.h" -#include "absl/strings/string_view.h" -#include "quiche/common/platform/api/quiche_export.h" - -namespace spdy { - -namespace test { -class SpdyAltSvcWireFormatPeer; -} // namespace test - -class QUICHE_EXPORT SpdyAltSvcWireFormat { - public: - using VersionVector = absl::InlinedVector; - - struct QUICHE_EXPORT AlternativeService { - std::string protocol_id; - std::string host; - - // Default is 0: invalid port. - uint16_t port = 0; - // Default is one day. - uint32_t max_age_seconds = 86400; - // Default is empty: unspecified version. - VersionVector version; - - AlternativeService(); - AlternativeService(const std::string& protocol_id, const std::string& host, - uint16_t port, uint32_t max_age_seconds, - VersionVector version); - AlternativeService(const AlternativeService& other); - ~AlternativeService(); - - bool operator==(const AlternativeService& other) const { - return protocol_id == other.protocol_id && host == other.host && - port == other.port && version == other.version && - max_age_seconds == other.max_age_seconds; - } - }; - // An empty vector means alternative services should be cleared for given - // origin. Note that the wire format for this is the string "clear", not an - // empty value (which is invalid). - typedef std::vector AlternativeServiceVector; - - friend class test::SpdyAltSvcWireFormatPeer; - static bool ParseHeaderFieldValue(absl::string_view value, - AlternativeServiceVector* altsvc_vector); - static std::string SerializeHeaderFieldValue( - const AlternativeServiceVector& altsvc_vector); - - private: - // Forward |*c| over space and tab or until |end| is reached. - static void SkipWhiteSpace(absl::string_view::const_iterator* c, - absl::string_view::const_iterator end); - // Decode percent-decoded string between |c| and |end| into |*output|. - // Return true on success, false if input is invalid. - static bool PercentDecode(absl::string_view::const_iterator c, - absl::string_view::const_iterator end, - std::string* output); - // Parse the authority part of Alt-Svc between |c| and |end| into |*host| and - // |*port|. Return true on success, false if input is invalid. - static bool ParseAltAuthority(absl::string_view::const_iterator c, - absl::string_view::const_iterator end, - std::string* host, uint16_t* port); - // Parse a positive integer between |c| and |end| into |*value|. - // Return true on success, false if input is not a positive integer or it - // cannot be represented on uint16_t. - static bool ParsePositiveInteger16(absl::string_view::const_iterator c, - absl::string_view::const_iterator end, - uint16_t* value); - // Parse a positive integer between |c| and |end| into |*value|. - // Return true on success, false if input is not a positive integer or it - // cannot be represented on uint32_t. - static bool ParsePositiveInteger32(absl::string_view::const_iterator c, - absl::string_view::const_iterator end, - uint32_t* value); - // Parse |c| as hexadecimal digit, case insensitive. |c| must be [0-9a-fA-F]. - // Output is between 0 and 15. - static char HexDigitToInt(char c); - // Parse |data| as hexadecimal number into |*value|. |data| must only contain - // hexadecimal digits, no "0x" prefix. - // Return true on success, false if input is empty, not valid hexadecimal - // number, or cannot be represented on uint32_t. - static bool HexDecodeToUInt32(absl::string_view data, uint32_t* value); -}; - -} // namespace spdy +#include "quiche/http2/core/spdy_alt_svc_wire_format.h" #endif // QUICHE_SPDY_CORE_SPDY_ALT_SVC_WIRE_FORMAT_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_bitmasks.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_bitmasks.h index 989e01361c..ae12b554cb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_bitmasks.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_bitmasks.h @@ -5,14 +5,6 @@ #ifndef QUICHE_SPDY_CORE_SPDY_BITMASKS_H_ #define QUICHE_SPDY_CORE_SPDY_BITMASKS_H_ -namespace spdy { - -// StreamId mask from the SpdyHeader -inline constexpr unsigned int kStreamIdMask = 0x7fffffff; - -// Mask the lower 24 bits. -inline constexpr unsigned int kLengthMask = 0xffffff; - -} // namespace spdy +#include "quiche/http2/core/spdy_bitmasks.h" #endif // QUICHE_SPDY_CORE_SPDY_BITMASKS_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h index 52cb1b009a..f8f749bfb1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h @@ -5,136 +5,6 @@ #ifndef QUICHE_SPDY_CORE_SPDY_FRAME_BUILDER_H_ #define QUICHE_SPDY_CORE_SPDY_FRAME_BUILDER_H_ -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "quiche/common/platform/api/quiche_bug_tracker.h" -#include "quiche/common/platform/api/quiche_export.h" -#include "quiche/common/quiche_endian.h" -#include "quiche/spdy/core/spdy_protocol.h" -#include "quiche/spdy/core/zero_copy_output_buffer.h" - -namespace spdy { - -namespace test { -class SpdyFrameBuilderPeer; -} // namespace test - -// This class provides facilities for basic binary value packing -// into Spdy frames. -// -// The SpdyFrameBuilder supports appending primitive values (int, string, etc) -// to a frame instance. The SpdyFrameBuilder grows its internal memory buffer -// dynamically to hold the sequence of primitive values. The internal memory -// buffer is exposed as the "data" of the SpdyFrameBuilder. -class QUICHE_EXPORT SpdyFrameBuilder { - public: - // Initializes a SpdyFrameBuilder with a buffer of given size - explicit SpdyFrameBuilder(size_t size); - // Doesn't take ownership of output. - SpdyFrameBuilder(size_t size, ZeroCopyOutputBuffer* output); - - ~SpdyFrameBuilder(); - - // Returns the total size of the SpdyFrameBuilder's data, which may include - // multiple frames. - size_t length() const { return offset_ + length_; } - - // Seeks forward by the given number of bytes. Useful in conjunction with - // GetWriteableBuffer() above. - bool Seek(size_t length); - - // Populates this frame with a HTTP2 frame prefix using length information - // from |capacity_|. The given type must be a control frame type. - bool BeginNewFrame(SpdyFrameType type, uint8_t flags, SpdyStreamId stream_id); - - // Populates this frame with a HTTP2 frame prefix with type and length - // information. |type| must be a defined frame type. - bool BeginNewFrame(SpdyFrameType type, uint8_t flags, SpdyStreamId stream_id, - size_t length); - - // Populates this frame with a HTTP2 frame prefix with type and length - // information. |raw_frame_type| may be a defined or undefined frame type. - bool BeginNewUncheckedFrame(uint8_t raw_frame_type, uint8_t flags, - SpdyStreamId stream_id, size_t length); - - // Takes the buffer from the SpdyFrameBuilder. - SpdySerializedFrame take() { - QUICHE_BUG_IF(spdy_bug_39_1, output_ != nullptr) - << "ZeroCopyOutputBuffer is used to build " - << "frames. take() shouldn't be called"; - QUICHE_BUG_IF(spdy_bug_39_2, kMaxFrameSizeLimit < length_) - << "Frame length " << length_ - << " is longer than the maximum possible allowed length."; - SpdySerializedFrame rv(std::move(buffer_), length()); - capacity_ = 0; - length_ = 0; - offset_ = 0; - return rv; - } - - // Methods for adding to the payload. These values are appended to the end - // of the SpdyFrameBuilder payload. Note - binary integers are converted from - // host to network form. - bool WriteUInt8(uint8_t value) { return WriteBytes(&value, sizeof(value)); } - bool WriteUInt16(uint16_t value) { - value = quiche::QuicheEndian::HostToNet16(value); - return WriteBytes(&value, sizeof(value)); - } - bool WriteUInt24(uint32_t value) { - value = quiche::QuicheEndian::HostToNet32(value); - return WriteBytes(reinterpret_cast(&value) + 1, sizeof(value) - 1); - } - bool WriteUInt32(uint32_t value) { - value = quiche::QuicheEndian::HostToNet32(value); - return WriteBytes(&value, sizeof(value)); - } - bool WriteUInt64(uint64_t value) { - uint32_t upper = - quiche::QuicheEndian::HostToNet32(static_cast(value >> 32)); - uint32_t lower = - quiche::QuicheEndian::HostToNet32(static_cast(value)); - return (WriteBytes(&upper, sizeof(upper)) && - WriteBytes(&lower, sizeof(lower))); - } - bool WriteStringPiece32(const absl::string_view value); - bool WriteBytes(const void* data, uint32_t data_len); - - private: - friend class test::SpdyFrameBuilderPeer; - - // Populates this frame with a HTTP2 frame prefix with type and length - // information. - bool BeginNewFrameInternal(uint8_t raw_frame_type, uint8_t flags, - SpdyStreamId stream_id, size_t length); - - // Returns a writeable buffer of given size in bytes, to be appended to the - // currently written frame. Does bounds checking on length but does not - // increment the underlying iterator. To do so, consumers should subsequently - // call Seek(). - // In general, consumers should use Write*() calls instead of this. - // Returns NULL on failure. - char* GetWritableBuffer(size_t length); - char* GetWritableOutput(size_t desired_length, size_t* actual_length); - - // Checks to make sure that there is an appropriate amount of space for a - // write of given size, in bytes. - bool CanWrite(size_t length) const; - - // A buffer to be created whenever a new frame needs to be written. Used only - // if |output_| is nullptr. - std::unique_ptr buffer_; - // A pre-allocated buffer. If not-null, serialized frame data is written to - // this buffer. - ZeroCopyOutputBuffer* output_ = nullptr; // Does not own. - - size_t capacity_; // Allocation size of payload, set by constructor. - size_t length_; // Length of the latest frame in the buffer. - size_t offset_; // Position at which the latest frame begins. -}; - -} // namespace spdy +#include "quiche/http2/core/spdy_frame_builder.h" #endif // QUICHE_SPDY_CORE_SPDY_FRAME_BUILDER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h index de755e6257..15fb6e6198 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h @@ -5,367 +5,6 @@ #ifndef QUICHE_SPDY_CORE_SPDY_FRAMER_H_ #define QUICHE_SPDY_CORE_SPDY_FRAMER_H_ -#include - -#include -#include -#include -#include - -#include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/hpack/hpack_encoder.h" -#include "quiche/spdy/core/spdy_protocol.h" -#include "quiche/spdy/core/zero_copy_output_buffer.h" - -namespace spdy { - -namespace test { - -class SpdyFramerPeer; -class SpdyFramerTest_MultipleContinuationFramesWithIterator_Test; -class SpdyFramerTest_PushPromiseFramesWithIterator_Test; - -} // namespace test - -class QUICHE_EXPORT SpdyFrameSequence { - public: - virtual ~SpdyFrameSequence() {} - - // Serializes the next frame in the sequence to |output|. Returns the number - // of bytes written to |output|. - virtual size_t NextFrame(ZeroCopyOutputBuffer* output) = 0; - - // Returns true iff there is at least one more frame in the sequence. - virtual bool HasNextFrame() const = 0; - - // Get SpdyFrameIR of the frame to be serialized. - virtual const SpdyFrameIR& GetIR() const = 0; -}; - -class QUICHE_EXPORT SpdyFramer { - public: - enum CompressionOption { - ENABLE_COMPRESSION, - DISABLE_COMPRESSION, - }; - - // Create a SpdyFrameSequence to serialize |frame_ir|. - static std::unique_ptr CreateIterator( - SpdyFramer* framer, std::unique_ptr frame_ir); - - // Gets the serialized flags for the given |frame|. - static uint8_t GetSerializedFlags(const SpdyFrameIR& frame); - - // Serialize a data frame. - static SpdySerializedFrame SerializeData(const SpdyDataIR& data_ir); - // Serializes the data frame header and optionally padding length fields, - // excluding actual data payload and padding. - static SpdySerializedFrame SerializeDataFrameHeaderWithPaddingLengthField( - const SpdyDataIR& data_ir); - - // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE - // frame is used to implement per stream flow control. - static SpdySerializedFrame SerializeWindowUpdate( - const SpdyWindowUpdateIR& window_update); - - explicit SpdyFramer(CompressionOption option); - - virtual ~SpdyFramer(); - - // Set debug callbacks to be called from the framer. The debug visitor is - // completely optional and need not be set in order for normal operation. - // If this is called multiple times, only the last visitor will be used. - void set_debug_visitor(SpdyFramerDebugVisitorInterface* debug_visitor); - - SpdySerializedFrame SerializeRstStream( - const SpdyRstStreamIR& rst_stream) const; - - // Serializes a SETTINGS frame. The SETTINGS frame is - // used to communicate name/value pairs relevant to the communication channel. - SpdySerializedFrame SerializeSettings(const SpdySettingsIR& settings) const; - - // Serializes a PING frame. The unique_id is used to - // identify the ping request/response. - SpdySerializedFrame SerializePing(const SpdyPingIR& ping) const; - - // Serializes a GOAWAY frame. The GOAWAY frame is used - // prior to the shutting down of the TCP connection, and includes the - // stream_id of the last stream the sender of the frame is willing to process - // to completion. - SpdySerializedFrame SerializeGoAway(const SpdyGoAwayIR& goaway) const; - - // Serializes a HEADERS frame. The HEADERS frame is used - // for sending headers. - SpdySerializedFrame SerializeHeaders(const SpdyHeadersIR& headers); - - // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used - // to inform the client that it will be receiving an additional stream - // in response to the original request. The frame includes synthesized - // headers to explain the upcoming data. - SpdySerializedFrame SerializePushPromise( - const SpdyPushPromiseIR& push_promise); - - // Serializes a CONTINUATION frame. The CONTINUATION frame is used - // to continue a sequence of header block fragments. - SpdySerializedFrame SerializeContinuation( - const SpdyContinuationIR& continuation) const; - - // Serializes an ALTSVC frame. The ALTSVC frame advertises the - // availability of an alternative service to the client. - SpdySerializedFrame SerializeAltSvc(const SpdyAltSvcIR& altsvc); - - // Serializes a PRIORITY frame. The PRIORITY frame advises a change in - // the relative priority of the given stream. - SpdySerializedFrame SerializePriority(const SpdyPriorityIR& priority) const; - - // Serializes a PRIORITY_UPDATE frame. - // See https://httpwg.org/http-extensions/draft-ietf-httpbis-priority.html. - SpdySerializedFrame SerializePriorityUpdate( - const SpdyPriorityUpdateIR& priority_update) const; - - // Serializes an ACCEPT_CH frame. See - // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02. - SpdySerializedFrame SerializeAcceptCh(const SpdyAcceptChIR& accept_ch) const; - - // Serializes an unknown frame given a frame header and payload. - SpdySerializedFrame SerializeUnknown(const SpdyUnknownIR& unknown) const; - - // Serialize a frame of unknown type. - SpdySerializedFrame SerializeFrame(const SpdyFrameIR& frame); - - // Serialize a data frame. - bool SerializeData(const SpdyDataIR& data, - ZeroCopyOutputBuffer* output) const; - - // Serializes the data frame header and optionally padding length fields, - // excluding actual data payload and padding. - bool SerializeDataFrameHeaderWithPaddingLengthField( - const SpdyDataIR& data, ZeroCopyOutputBuffer* output) const; - - bool SerializeRstStream(const SpdyRstStreamIR& rst_stream, - ZeroCopyOutputBuffer* output) const; - - // Serializes a SETTINGS frame. The SETTINGS frame is - // used to communicate name/value pairs relevant to the communication channel. - bool SerializeSettings(const SpdySettingsIR& settings, - ZeroCopyOutputBuffer* output) const; - - // Serializes a PING frame. The unique_id is used to - // identify the ping request/response. - bool SerializePing(const SpdyPingIR& ping, - ZeroCopyOutputBuffer* output) const; - - // Serializes a GOAWAY frame. The GOAWAY frame is used - // prior to the shutting down of the TCP connection, and includes the - // stream_id of the last stream the sender of the frame is willing to process - // to completion. - bool SerializeGoAway(const SpdyGoAwayIR& goaway, - ZeroCopyOutputBuffer* output) const; - - // Serializes a HEADERS frame. The HEADERS frame is used - // for sending headers. - bool SerializeHeaders(const SpdyHeadersIR& headers, - ZeroCopyOutputBuffer* output); - - // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE - // frame is used to implement per stream flow control. - bool SerializeWindowUpdate(const SpdyWindowUpdateIR& window_update, - ZeroCopyOutputBuffer* output) const; - - // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used - // to inform the client that it will be receiving an additional stream - // in response to the original request. The frame includes synthesized - // headers to explain the upcoming data. - bool SerializePushPromise(const SpdyPushPromiseIR& push_promise, - ZeroCopyOutputBuffer* output); - - // Serializes a CONTINUATION frame. The CONTINUATION frame is used - // to continue a sequence of header block fragments. - bool SerializeContinuation(const SpdyContinuationIR& continuation, - ZeroCopyOutputBuffer* output) const; - - // Serializes an ALTSVC frame. The ALTSVC frame advertises the - // availability of an alternative service to the client. - bool SerializeAltSvc(const SpdyAltSvcIR& altsvc, - ZeroCopyOutputBuffer* output); - - // Serializes a PRIORITY frame. The PRIORITY frame advises a change in - // the relative priority of the given stream. - bool SerializePriority(const SpdyPriorityIR& priority, - ZeroCopyOutputBuffer* output) const; - - // Serializes a PRIORITY_UPDATE frame. - // See https://httpwg.org/http-extensions/draft-ietf-httpbis-priority.html. - bool SerializePriorityUpdate(const SpdyPriorityUpdateIR& priority_update, - ZeroCopyOutputBuffer* output) const; - - // Serializes an ACCEPT_CH frame. See - // https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02. - bool SerializeAcceptCh(const SpdyAcceptChIR& accept_ch, - ZeroCopyOutputBuffer* output) const; - - // Serializes an unknown frame given a frame header and payload. - bool SerializeUnknown(const SpdyUnknownIR& unknown, - ZeroCopyOutputBuffer* output) const; - - // Serialize a frame of unknown type. - size_t SerializeFrame(const SpdyFrameIR& frame, ZeroCopyOutputBuffer* output); - - // Returns whether this SpdyFramer will compress header blocks using HPACK. - bool compression_enabled() const { - return compression_option_ == ENABLE_COMPRESSION; - } - - void SetHpackIndexingPolicy(HpackEncoder::IndexingPolicy policy) { - GetHpackEncoder()->SetIndexingPolicy(std::move(policy)); - } - - // Updates the maximum size of the header encoder compression table. - void UpdateHeaderEncoderTableSize(uint32_t value); - - // Returns the maximum size of the header encoder compression table. - size_t header_encoder_table_size() const; - - // Get (and lazily initialize) the HPACK encoder state. - HpackEncoder* GetHpackEncoder(); - - // Gets the HPACK encoder state. Returns nullptr if the encoder has not been - // initialized. - const HpackEncoder* GetHpackEncoder() const { return hpack_encoder_.get(); } - - protected: - friend class test::SpdyFramerPeer; - friend class test::SpdyFramerTest_MultipleContinuationFramesWithIterator_Test; - friend class test::SpdyFramerTest_PushPromiseFramesWithIterator_Test; - - // Iteratively converts a SpdyFrameIR into an appropriate sequence of Spdy - // frames. - // Example usage: - // std::unique_ptr it = CreateIterator(framer, frame_ir); - // while (it->HasNextFrame()) { - // if(it->NextFrame(output) == 0) { - // // Write failed; - // } - // } - class QUICHE_EXPORT SpdyFrameIterator : public SpdyFrameSequence { - public: - // Creates an iterator with the provided framer. - // Does not take ownership of |framer|. - // |framer| must outlive this instance. - explicit SpdyFrameIterator(SpdyFramer* framer); - ~SpdyFrameIterator() override; - - // Serializes the next frame in the sequence to |output|. Returns the number - // of bytes written to |output|. - size_t NextFrame(ZeroCopyOutputBuffer* output) override; - - // Returns true iff there is at least one more frame in the sequence. - bool HasNextFrame() const override; - - // SpdyFrameIterator is neither copyable nor movable. - SpdyFrameIterator(const SpdyFrameIterator&) = delete; - SpdyFrameIterator& operator=(const SpdyFrameIterator&) = delete; - - protected: - virtual size_t GetFrameSizeSansBlock() const = 0; - virtual bool SerializeGivenEncoding(const std::string& encoding, - ZeroCopyOutputBuffer* output) const = 0; - - SpdyFramer* GetFramer() const { return framer_; } - - void SetEncoder(const SpdyFrameWithHeaderBlockIR* ir) { - encoder_ = - framer_->GetHpackEncoder()->EncodeHeaderSet(ir->header_block()); - } - - bool has_next_frame() const { return has_next_frame_; } - - private: - SpdyFramer* const framer_; - std::unique_ptr encoder_; - bool is_first_frame_; - bool has_next_frame_; - }; - - // Iteratively converts a SpdyHeadersIR (with a possibly huge - // Http2HeaderBlock) into an appropriate sequence of SpdySerializedFrames, and - // write to the output. - class QUICHE_EXPORT SpdyHeaderFrameIterator : public SpdyFrameIterator { - public: - // Does not take ownership of |framer|. Take ownership of |headers_ir|. - SpdyHeaderFrameIterator(SpdyFramer* framer, - std::unique_ptr headers_ir); - - ~SpdyHeaderFrameIterator() override; - - private: - const SpdyFrameIR& GetIR() const override; - size_t GetFrameSizeSansBlock() const override; - bool SerializeGivenEncoding(const std::string& encoding, - ZeroCopyOutputBuffer* output) const override; - - const std::unique_ptr headers_ir_; - }; - - // Iteratively converts a SpdyPushPromiseIR (with a possibly huge - // Http2HeaderBlock) into an appropriate sequence of SpdySerializedFrames, and - // write to the output. - class QUICHE_EXPORT SpdyPushPromiseFrameIterator : public SpdyFrameIterator { - public: - // Does not take ownership of |framer|. Take ownership of |push_promise_ir|. - SpdyPushPromiseFrameIterator( - SpdyFramer* framer, - std::unique_ptr push_promise_ir); - - ~SpdyPushPromiseFrameIterator() override; - - private: - const SpdyFrameIR& GetIR() const override; - size_t GetFrameSizeSansBlock() const override; - bool SerializeGivenEncoding(const std::string& encoding, - ZeroCopyOutputBuffer* output) const override; - - const std::unique_ptr push_promise_ir_; - }; - - // Converts a SpdyFrameIR into one Spdy frame (a sequence of length 1), and - // write it to the output. - class QUICHE_EXPORT SpdyControlFrameIterator : public SpdyFrameSequence { - public: - SpdyControlFrameIterator(SpdyFramer* framer, - std::unique_ptr frame_ir); - ~SpdyControlFrameIterator() override; - - size_t NextFrame(ZeroCopyOutputBuffer* output) override; - - bool HasNextFrame() const override; - - const SpdyFrameIR& GetIR() const override; - - private: - SpdyFramer* const framer_; - std::unique_ptr frame_ir_; - bool has_next_frame_ = true; - }; - - private: - void SerializeHeadersBuilderHelper(const SpdyHeadersIR& headers, - uint8_t* flags, size_t* size, - std::string* hpack_encoding, int* weight, - size_t* length_field); - void SerializePushPromiseBuilderHelper(const SpdyPushPromiseIR& push_promise, - uint8_t* flags, - std::string* hpack_encoding, - size_t* size); - - std::unique_ptr hpack_encoder_; - - SpdyFramerDebugVisitorInterface* debug_visitor_; - - // Determines whether HPACK compression is used. - const CompressionOption compression_option_; -}; - -} // namespace spdy +#include "quiche/http2/core/spdy_framer.h" #endif // QUICHE_SPDY_CORE_SPDY_FRAMER_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_headers_handler_interface.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_headers_handler_interface.h index 629874123b..813478114f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_headers_handler_interface.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_headers_handler_interface.h @@ -5,35 +5,6 @@ #ifndef QUICHE_SPDY_CORE_SPDY_HEADERS_HANDLER_INTERFACE_H_ #define QUICHE_SPDY_CORE_SPDY_HEADERS_HANDLER_INTERFACE_H_ -#include - -#include "absl/strings/string_view.h" -#include "quiche/common/platform/api/quiche_export.h" - -namespace spdy { - -// This interface defines how an object that accepts header data should behave. -// It is used by both SpdyHeadersBlockParser and HpackDecoder. -class QUICHE_EXPORT SpdyHeadersHandlerInterface { - public: - virtual ~SpdyHeadersHandlerInterface() {} - - // A callback method which notifies when the parser starts handling a new - // header block. Will only be called once per block, even if it extends into - // CONTINUATION frames. - virtual void OnHeaderBlockStart() = 0; - - // A callback method which notifies on a header key value pair. Multiple - // values for a given key will be emitted as multiple calls to OnHeader. - virtual void OnHeader(absl::string_view key, absl::string_view value) = 0; - - // A callback method which notifies when the parser finishes handling a - // header block (i.e. the containing frame has the END_HEADERS flag set). - // Also indicates the total number of bytes in this block. - virtual void OnHeaderBlockEnd(size_t uncompressed_header_bytes, - size_t compressed_header_bytes) = 0; -}; - -} // namespace spdy +#include "quiche/http2/core/spdy_headers_handler_interface.h" #endif // QUICHE_SPDY_CORE_SPDY_HEADERS_HANDLER_INTERFACE_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h index ec57be22e3..fbc7499a0d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h @@ -2,1100 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This file contains some protocol structures for use with SPDY 3 and HTTP 2 -// The SPDY 3 spec can be found at: -// http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3 - #ifndef QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_ #define QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "absl/strings/string_view.h" -#include "absl/types/variant.h" -#include "quiche/common/platform/api/quiche_export.h" -#include "quiche/common/platform/api/quiche_flags.h" -#include "quiche/common/platform/api/quiche_logging.h" -#include "quiche/spdy/core/http2_header_block.h" -#include "quiche/spdy/core/spdy_alt_svc_wire_format.h" -#include "quiche/spdy/core/spdy_bitmasks.h" - -namespace spdy { - -// A stream ID is a 31-bit entity. -using SpdyStreamId = uint32_t; - -// A SETTINGS ID is a 16-bit entity. -using SpdySettingsId = uint16_t; - -// Specifies the stream ID used to denote the current session (for -// flow control). -inline constexpr SpdyStreamId kSessionFlowControlStreamId = 0; - -// 0 is not a valid stream ID for any other purpose than flow control. -inline constexpr SpdyStreamId kInvalidStreamId = 0; - -// Max stream id. -inline constexpr SpdyStreamId kMaxStreamId = 0x7fffffff; - -// The maximum possible frame payload size allowed by the spec. -inline constexpr uint32_t kSpdyMaxFrameSizeLimit = (1 << 24) - 1; - -// The initial value for the maximum frame payload size as per the spec. This is -// the maximum control frame size we accept. -inline constexpr uint32_t kHttp2DefaultFramePayloadLimit = 1 << 14; - -// The maximum size of the control frames that we send, including the size of -// the header. This limit is arbitrary. We can enforce it here or at the -// application layer. We chose the framing layer, but this can be changed (or -// removed) if necessary later down the line. -inline constexpr size_t kHttp2MaxControlFrameSendSize = - kHttp2DefaultFramePayloadLimit - 1; - -// Number of octets in the frame header. -inline constexpr size_t kFrameHeaderSize = 9; - -// The initial value for the maximum frame payload size as per the spec. This is -// the maximum control frame size we accept. -inline constexpr uint32_t kHttp2DefaultFrameSizeLimit = - kHttp2DefaultFramePayloadLimit + kFrameHeaderSize; - -// The initial value for the maximum size of the header list, "unlimited" (max -// unsigned 32-bit int) as per the spec. -inline constexpr uint32_t kSpdyInitialHeaderListSizeLimit = 0xFFFFFFFF; - -// Maximum window size for a Spdy stream or session. -inline constexpr int32_t kSpdyMaximumWindowSize = - 0x7FFFFFFF; // Max signed 32bit int - -// Maximum padding size in octets for one DATA or HEADERS or PUSH_PROMISE frame. -inline constexpr int32_t kPaddingSizePerFrame = 256; - -// The HTTP/2 connection preface, which must be the first bytes sent by the -// client upon starting an HTTP/2 connection, and which must be followed by a -// SETTINGS frame. Note that even though |kHttp2ConnectionHeaderPrefix| is -// defined as a string literal with a null terminator, the actual connection -// preface is only the first |kHttp2ConnectionHeaderPrefixSize| bytes, which -// excludes the null terminator. -QUICHE_EXPORT extern const char* const kHttp2ConnectionHeaderPrefix; -inline constexpr int kHttp2ConnectionHeaderPrefixSize = 24; - -// Wire values for HTTP2 frame types. -enum class SpdyFrameType : uint8_t { - DATA = 0x00, - HEADERS = 0x01, - PRIORITY = 0x02, - RST_STREAM = 0x03, - SETTINGS = 0x04, - PUSH_PROMISE = 0x05, - PING = 0x06, - GOAWAY = 0x07, - WINDOW_UPDATE = 0x08, - CONTINUATION = 0x09, - // ALTSVC is a public extension. - ALTSVC = 0x0a, - PRIORITY_UPDATE = 0x10, - ACCEPT_CH = 0x89, -}; - -// Flags on data packets. -enum SpdyDataFlags { - DATA_FLAG_NONE = 0x00, - DATA_FLAG_FIN = 0x01, - DATA_FLAG_PADDED = 0x08, -}; - -// Flags on control packets -enum SpdyControlFlags { - CONTROL_FLAG_NONE = 0x00, - CONTROL_FLAG_FIN = 0x01, -}; - -enum SpdyPingFlags { - PING_FLAG_ACK = 0x01, -}; - -// Used by HEADERS, PUSH_PROMISE, and CONTINUATION. -enum SpdyHeadersFlags { - HEADERS_FLAG_END_HEADERS = 0x04, - HEADERS_FLAG_PADDED = 0x08, - HEADERS_FLAG_PRIORITY = 0x20, -}; - -enum SpdyPushPromiseFlags { - PUSH_PROMISE_FLAG_END_PUSH_PROMISE = 0x04, - PUSH_PROMISE_FLAG_PADDED = 0x08, -}; - -enum Http2SettingsControlFlags { - SETTINGS_FLAG_ACK = 0x01, -}; - -// Wire values of HTTP/2 setting identifiers. -enum SpdyKnownSettingsId : SpdySettingsId { - // HPACK header table maximum size. - SETTINGS_HEADER_TABLE_SIZE = 0x1, - SETTINGS_MIN = SETTINGS_HEADER_TABLE_SIZE, - // Whether or not server push (PUSH_PROMISE) is enabled. - SETTINGS_ENABLE_PUSH = 0x2, - // The maximum number of simultaneous live streams in each direction. - SETTINGS_MAX_CONCURRENT_STREAMS = 0x3, - // Initial window size in bytes - SETTINGS_INITIAL_WINDOW_SIZE = 0x4, - // The size of the largest frame payload that a receiver is willing to accept. - SETTINGS_MAX_FRAME_SIZE = 0x5, - // The maximum size of header list that the sender is prepared to accept. - SETTINGS_MAX_HEADER_LIST_SIZE = 0x6, - // Enable Websockets over HTTP/2, see - // https://httpwg.org/specs/rfc8441.html - SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x8, - // Disable HTTP/2 priorities, see - // https://tools.ietf.org/html/draft-ietf-httpbis-priority-02. - SETTINGS_DEPRECATE_HTTP2_PRIORITIES = 0x9, - SETTINGS_MAX = SETTINGS_DEPRECATE_HTTP2_PRIORITIES, - // Experimental setting used to configure an alternative write scheduler. - SETTINGS_EXPERIMENT_SCHEDULER = 0xFF45, -}; - -// This explicit operator is needed, otherwise compiler finds -// overloaded operator to be ambiguous. -QUICHE_EXPORT std::ostream& operator<<(std::ostream& out, - SpdyKnownSettingsId id); - -// This operator is needed, because SpdyFrameType is an enum class, -// therefore implicit conversion to underlying integer type is not allowed. -QUICHE_EXPORT std::ostream& operator<<(std::ostream& out, - SpdyFrameType frame_type); - -using SettingsMap = std::map; - -// HTTP/2 error codes, RFC 7540 Section 7. -enum SpdyErrorCode : uint32_t { - ERROR_CODE_NO_ERROR = 0x0, - ERROR_CODE_PROTOCOL_ERROR = 0x1, - ERROR_CODE_INTERNAL_ERROR = 0x2, - ERROR_CODE_FLOW_CONTROL_ERROR = 0x3, - ERROR_CODE_SETTINGS_TIMEOUT = 0x4, - ERROR_CODE_STREAM_CLOSED = 0x5, - ERROR_CODE_FRAME_SIZE_ERROR = 0x6, - ERROR_CODE_REFUSED_STREAM = 0x7, - ERROR_CODE_CANCEL = 0x8, - ERROR_CODE_COMPRESSION_ERROR = 0x9, - ERROR_CODE_CONNECT_ERROR = 0xa, - ERROR_CODE_ENHANCE_YOUR_CALM = 0xb, - ERROR_CODE_INADEQUATE_SECURITY = 0xc, - ERROR_CODE_HTTP_1_1_REQUIRED = 0xd, - ERROR_CODE_MAX = ERROR_CODE_HTTP_1_1_REQUIRED -}; - -// Type of priority write scheduler. -enum class WriteSchedulerType { - LIFO, // Last added stream has the highest priority. - SPDY, // Uses SPDY priorities described in - // https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.3.3-Stream-priority. - HTTP2, // Uses HTTP2 (tree-style) priority described in - // https://tools.ietf.org/html/rfc7540#section-5.3. - FIFO, // Stream with the smallest stream ID has the highest priority. -}; - -// A SPDY priority is a number between 0 and 7 (inclusive). -typedef uint8_t SpdyPriority; - -// Lowest and Highest here refer to SPDY priorities as described in -// https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.3.3-Stream-priority -inline constexpr SpdyPriority kV3HighestPriority = 0; -inline constexpr SpdyPriority kV3LowestPriority = 7; - -// Returns SPDY 3.x priority value clamped to the valid range of [0, 7]. -QUICHE_EXPORT SpdyPriority ClampSpdy3Priority(SpdyPriority priority); - -// HTTP/2 stream weights are integers in range [1, 256], as specified in RFC -// 7540 section 5.3.2. Default stream weight is defined in section 5.3.5. -inline constexpr int kHttp2MinStreamWeight = 1; -inline constexpr int kHttp2MaxStreamWeight = 256; -inline constexpr int kHttp2DefaultStreamWeight = 16; - -// Returns HTTP/2 weight clamped to the valid range of [1, 256]. -QUICHE_EXPORT int ClampHttp2Weight(int weight); - -// Maps SPDY 3.x priority value in range [0, 7] to HTTP/2 weight value in range -// [1, 256], where priority 0 (i.e. highest precedence) corresponds to maximum -// weight 256 and priority 7 (lowest precedence) corresponds to minimum weight -// 1. -QUICHE_EXPORT int Spdy3PriorityToHttp2Weight(SpdyPriority priority); - -// Maps HTTP/2 weight value in range [1, 256] to SPDY 3.x priority value in -// range [0, 7], where minimum weight 1 corresponds to priority 7 (lowest -// precedence) and maximum weight 256 corresponds to priority 0 (highest -// precedence). -QUICHE_EXPORT SpdyPriority Http2WeightToSpdy3Priority(int weight); - -// Reserved ID for root stream of HTTP/2 stream dependency tree, as specified -// in RFC 7540 section 5.3.1. -const unsigned int kHttp2RootStreamId = 0; - -typedef uint64_t SpdyPingId; - -// Returns true if a given on-the-wire enumeration of a frame type is defined -// in a standardized HTTP/2 specification, false otherwise. -QUICHE_EXPORT bool IsDefinedFrameType(uint8_t frame_type_field); - -// Parses a frame type from an on-the-wire enumeration. -// Behavior is undefined for invalid frame type fields; consumers should first -// use IsValidFrameType() to verify validity of frame type fields. -QUICHE_EXPORT SpdyFrameType ParseFrameType(uint8_t frame_type_field); - -// Serializes a frame type to the on-the-wire value. -QUICHE_EXPORT uint8_t SerializeFrameType(SpdyFrameType frame_type); - -// (HTTP/2) All standard frame types except WINDOW_UPDATE are -// (stream-specific xor connection-level). Returns false iff we know -// the given frame type does not align with the given streamID. -QUICHE_EXPORT bool IsValidHTTP2FrameStreamId( - SpdyStreamId current_frame_stream_id, SpdyFrameType frame_type_field); - -// Serialize |frame_type| to string for logging/debugging. -QUICHE_EXPORT const char* FrameTypeToString(SpdyFrameType frame_type); - -// If |wire_setting_id| is the on-the-wire representation of a defined SETTINGS -// parameter, parse it to |*setting_id| and return true. -QUICHE_EXPORT bool ParseSettingsId(SpdySettingsId wire_setting_id, - SpdyKnownSettingsId* setting_id); - -// Returns a string representation of the |id| for logging/debugging. Returns -// the |id| prefixed with "SETTINGS_UNKNOWN_" for unknown SETTINGS IDs. To parse -// the |id| into a SpdyKnownSettingsId (if applicable), use ParseSettingsId(). -QUICHE_EXPORT std::string SettingsIdToString(SpdySettingsId id); - -// Parse |wire_error_code| to a SpdyErrorCode. -// Treat unrecognized error codes as INTERNAL_ERROR -// as recommended by the HTTP/2 specification. -QUICHE_EXPORT SpdyErrorCode ParseErrorCode(uint32_t wire_error_code); - -// Serialize RST_STREAM or GOAWAY frame error code to string -// for logging/debugging. -QUICHE_EXPORT const char* ErrorCodeToString(SpdyErrorCode error_code); - -// Serialize |type| to string for logging/debugging. -QUICHE_EXPORT const char* WriteSchedulerTypeToString(WriteSchedulerType type); - -// Minimum size of a frame, in octets. -inline constexpr size_t kFrameMinimumSize = kFrameHeaderSize; - -// Minimum frame size for variable size frame types (includes mandatory fields), -// frame size for fixed size frames, in octets. - -inline constexpr size_t kDataFrameMinimumSize = kFrameHeaderSize; -inline constexpr size_t kHeadersFrameMinimumSize = kFrameHeaderSize; -// PRIORITY frame has stream_dependency (4 octets) and weight (1 octet) fields. -inline constexpr size_t kPriorityFrameSize = kFrameHeaderSize + 5; -// RST_STREAM frame has error_code (4 octets) field. -inline constexpr size_t kRstStreamFrameSize = kFrameHeaderSize + 4; -inline constexpr size_t kSettingsFrameMinimumSize = kFrameHeaderSize; -inline constexpr size_t kSettingsOneSettingSize = - sizeof(uint32_t) + sizeof(SpdySettingsId); -// PUSH_PROMISE frame has promised_stream_id (4 octet) field. -inline constexpr size_t kPushPromiseFrameMinimumSize = kFrameHeaderSize + 4; -// PING frame has opaque_bytes (8 octet) field. -inline constexpr size_t kPingFrameSize = kFrameHeaderSize + 8; -// GOAWAY frame has last_stream_id (4 octet) and error_code (4 octet) fields. -inline constexpr size_t kGoawayFrameMinimumSize = kFrameHeaderSize + 8; -// WINDOW_UPDATE frame has window_size_increment (4 octet) field. -inline constexpr size_t kWindowUpdateFrameSize = kFrameHeaderSize + 4; -inline constexpr size_t kContinuationFrameMinimumSize = kFrameHeaderSize; -// ALTSVC frame has origin_len (2 octets) field. -inline constexpr size_t kGetAltSvcFrameMinimumSize = kFrameHeaderSize + 2; -// PRIORITY_UPDATE frame has prioritized_stream_id (4 octets) field. -inline constexpr size_t kPriorityUpdateFrameMinimumSize = kFrameHeaderSize + 4; -// ACCEPT_CH frame may have empty payload. -inline constexpr size_t kAcceptChFrameMinimumSize = kFrameHeaderSize; -// Each ACCEPT_CH frame entry has a 16-bit origin length and a 16-bit value -// length. -inline constexpr size_t kAcceptChFramePerEntryOverhead = 4; - -// Maximum possible configurable size of a frame in octets. -inline constexpr size_t kMaxFrameSizeLimit = - kSpdyMaxFrameSizeLimit + kFrameHeaderSize; -// Size of a header block size field. -inline constexpr size_t kSizeOfSizeField = sizeof(uint32_t); -// Initial window size for a stream in bytes. -inline constexpr int32_t kInitialStreamWindowSize = 64 * 1024 - 1; -// Initial window size for a session in bytes. -inline constexpr int32_t kInitialSessionWindowSize = 64 * 1024 - 1; -// The NPN string for HTTP2, "h2". -QUICHE_EXPORT extern const char* const kHttp2Npn; -// An estimate of the HPACK overhead for each header field in bytes, intended to -// be no smaller than actual overhead, based on the literal header field -// representation in RFC 7541 Section 6.2 (with or without indexing): -// - 1 byte for the opcode. -// - 2 bytes for the name length (assuming new name). -// - 3 bytes for the value length. -// TODO(b/322146543): Remove the `New` suffix with deprecation of -// --gfe2_reloadable_flag_http2_add_hpack_overhead_bytes2. -inline constexpr size_t kPerHeaderHpackOverheadNew = 6; -// An estimate size of the HPACK overhead for each header field. 1 bytes for -// indexed literal, 1 bytes for key literal and length encoding, and 2 bytes for -// value literal and length encoding. -// TODO(b/322146543): Remove with deprecation of -// --gfe2_reloadable_flag_http2_add_hpack_overhead_bytes2. -inline constexpr size_t kPerHeaderHpackOverheadOld = 4; - -// Names of pseudo-headers defined for HTTP/2 requests. -QUICHE_EXPORT extern const char* const kHttp2AuthorityHeader; -QUICHE_EXPORT extern const char* const kHttp2MethodHeader; -QUICHE_EXPORT extern const char* const kHttp2PathHeader; -QUICHE_EXPORT extern const char* const kHttp2SchemeHeader; -QUICHE_EXPORT extern const char* const kHttp2ProtocolHeader; - -// Name of pseudo-header defined for HTTP/2 responses. -QUICHE_EXPORT extern const char* const kHttp2StatusHeader; - -QUICHE_EXPORT size_t GetNumberRequiredContinuationFrames(size_t size); - -// Variant type that is either a SPDY 3.x priority value, or else an HTTP/2 -// stream dependency tuple {parent stream ID, weight, exclusive bit}. Templated -// to allow for use by QUIC code; SPDY and HTTP/2 code should use the concrete -// type instantiation SpdyStreamPrecedence. -template -class QUICHE_EXPORT StreamPrecedence { - public: - // Constructs instance that is a SPDY 3.x priority. Clamps priority value to - // the valid range [0, 7]. - explicit StreamPrecedence(SpdyPriority priority) - : precedence_(ClampSpdy3Priority(priority)) {} - - // Constructs instance that is an HTTP/2 stream weight, parent stream ID, and - // exclusive bit. Clamps stream weight to the valid range [1, 256]. - StreamPrecedence(StreamIdType parent_id, int weight, bool is_exclusive) - : precedence_(Http2StreamDependency{parent_id, ClampHttp2Weight(weight), - is_exclusive}) {} - - // Intentionally copyable, to support pass by value. - StreamPrecedence(const StreamPrecedence& other) = default; - StreamPrecedence& operator=(const StreamPrecedence& other) = default; - - // Returns true if this instance is a SPDY 3.x priority, or false if this - // instance is an HTTP/2 stream dependency. - bool is_spdy3_priority() const { - return absl::holds_alternative(precedence_); - } - - // Returns SPDY 3.x priority value. If |is_spdy3_priority()| is true, this is - // the value provided at construction, clamped to the legal priority - // range. Otherwise, it is the HTTP/2 stream weight mapped to a SPDY 3.x - // priority value, where minimum weight 1 corresponds to priority 7 (lowest - // precedence) and maximum weight 256 corresponds to priority 0 (highest - // precedence). - SpdyPriority spdy3_priority() const { - return is_spdy3_priority() - ? absl::get(precedence_) - : Http2WeightToSpdy3Priority( - absl::get(precedence_).weight); - } - - // Returns HTTP/2 parent stream ID. If |is_spdy3_priority()| is false, this is - // the value provided at construction, otherwise it is |kHttp2RootStreamId|. - StreamIdType parent_id() const { - return is_spdy3_priority() - ? kHttp2RootStreamId - : absl::get(precedence_).parent_id; - } - - // Returns HTTP/2 stream weight. If |is_spdy3_priority()| is false, this is - // the value provided at construction, clamped to the legal weight - // range. Otherwise, it is the SPDY 3.x priority value mapped to an HTTP/2 - // stream weight, where priority 0 (i.e. highest precedence) corresponds to - // maximum weight 256 and priority 7 (lowest precedence) corresponds to - // minimum weight 1. - int weight() const { - return is_spdy3_priority() - ? Spdy3PriorityToHttp2Weight( - absl::get(precedence_)) - : absl::get(precedence_).weight; - } - - // Returns HTTP/2 parent stream exclusivity. If |is_spdy3_priority()| is - // false, this is the value provided at construction, otherwise it is false. - bool is_exclusive() const { - return absl::holds_alternative(precedence_) && - absl::get(precedence_).is_exclusive; - } - - // Facilitates test assertions. - bool operator==(const StreamPrecedence& other) const { - return precedence_ == other.precedence_; - } - - bool operator!=(const StreamPrecedence& other) const { - return !(*this == other); - } - - private: - struct QUICHE_EXPORT Http2StreamDependency { - StreamIdType parent_id; - int weight; - bool is_exclusive; - - bool operator==(const Http2StreamDependency& other) const { - return parent_id == other.parent_id && weight == other.weight && - is_exclusive == other.is_exclusive; - } - }; - - absl::variant precedence_; -}; - -typedef StreamPrecedence SpdyStreamPrecedence; - -class SpdyFrameVisitor; - -// Intermediate representation for HTTP2 frames. -class QUICHE_EXPORT SpdyFrameIR { - public: - virtual ~SpdyFrameIR() {} - - virtual void Visit(SpdyFrameVisitor* visitor) const = 0; - virtual SpdyFrameType frame_type() const = 0; - SpdyStreamId stream_id() const { return stream_id_; } - virtual bool fin() const; - // Returns an estimate of the size of the serialized frame, without applying - // compression. May not be exact, but implementations should return the same - // value for a const frame. - virtual size_t size() const = 0; - - // Returns the number of bytes of flow control window that would be consumed - // by this frame if written to the wire. - virtual int flow_control_window_consumed() const; - - protected: - SpdyFrameIR() : stream_id_(0) {} - explicit SpdyFrameIR(SpdyStreamId stream_id) : stream_id_(stream_id) {} - SpdyFrameIR(const SpdyFrameIR&) = delete; - SpdyFrameIR& operator=(const SpdyFrameIR&) = delete; - - private: - SpdyStreamId stream_id_; -}; - -// Abstract class intended to be inherited by IRs that have the option of a FIN -// flag. -class QUICHE_EXPORT SpdyFrameWithFinIR : public SpdyFrameIR { - public: - ~SpdyFrameWithFinIR() override {} - bool fin() const override; - void set_fin(bool fin) { fin_ = fin; } - - protected: - explicit SpdyFrameWithFinIR(SpdyStreamId stream_id) - : SpdyFrameIR(stream_id), fin_(false) {} - SpdyFrameWithFinIR(const SpdyFrameWithFinIR&) = delete; - SpdyFrameWithFinIR& operator=(const SpdyFrameWithFinIR&) = delete; - - private: - bool fin_; -}; - -// Abstract class intended to be inherited by IRs that contain a header -// block. Implies SpdyFrameWithFinIR. -class QUICHE_EXPORT SpdyFrameWithHeaderBlockIR : public SpdyFrameWithFinIR { - public: - ~SpdyFrameWithHeaderBlockIR() override; - - const Http2HeaderBlock& header_block() const { return header_block_; } - void set_header_block(Http2HeaderBlock header_block) { - // Deep copy. - header_block_ = std::move(header_block); - } - void SetHeader(absl::string_view name, absl::string_view value) { - header_block_[name] = value; - } - - protected: - SpdyFrameWithHeaderBlockIR(SpdyStreamId stream_id, - Http2HeaderBlock header_block); - SpdyFrameWithHeaderBlockIR(const SpdyFrameWithHeaderBlockIR&) = delete; - SpdyFrameWithHeaderBlockIR& operator=(const SpdyFrameWithHeaderBlockIR&) = - delete; - - private: - Http2HeaderBlock header_block_; -}; - -class QUICHE_EXPORT SpdyDataIR : public SpdyFrameWithFinIR { - public: - // Performs a deep copy on data. - SpdyDataIR(SpdyStreamId stream_id, absl::string_view data); - - // Performs a deep copy on data. - SpdyDataIR(SpdyStreamId stream_id, const char* data); - - // Moves data into data_store_. Makes a copy if passed a non-movable string. - SpdyDataIR(SpdyStreamId stream_id, std::string data); - - // Use in conjunction with SetDataShallow() for shallow-copy on data. - explicit SpdyDataIR(SpdyStreamId stream_id); - SpdyDataIR(const SpdyDataIR&) = delete; - SpdyDataIR& operator=(const SpdyDataIR&) = delete; - - ~SpdyDataIR() override; - - const char* data() const { return data_; } - size_t data_len() const { return data_len_; } - - bool padded() const { return padded_; } - - int padding_payload_len() const { return padding_payload_len_; } - - void set_padding_len(int padding_len) { - QUICHE_DCHECK_GT(padding_len, 0); - QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame); - padded_ = true; - // The pad field takes one octet on the wire. - padding_payload_len_ = padding_len - 1; - } - - // Deep-copy of data (keep private copy). - void SetDataDeep(absl::string_view data) { - data_store_ = std::make_unique(data.data(), data.size()); - data_ = data_store_->data(); - data_len_ = data.size(); - } - - // Shallow-copy of data (do not keep private copy). - void SetDataShallow(absl::string_view data) { - data_store_.reset(); - data_ = data.data(); - data_len_ = data.size(); - } - - // Use this method if we don't have a contiguous buffer and only - // need a length. - void SetDataShallow(size_t len) { - data_store_.reset(); - data_ = nullptr; - data_len_ = len; - } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - int flow_control_window_consumed() const override; - - size_t size() const override; - - private: - // Used to store data that this SpdyDataIR should own. - std::unique_ptr data_store_; - const char* data_; - size_t data_len_; - - bool padded_; - // padding_payload_len_ = desired padding length - len(padding length field). - int padding_payload_len_; -}; - -class QUICHE_EXPORT SpdyRstStreamIR : public SpdyFrameIR { - public: - SpdyRstStreamIR(SpdyStreamId stream_id, SpdyErrorCode error_code); - SpdyRstStreamIR(const SpdyRstStreamIR&) = delete; - SpdyRstStreamIR& operator=(const SpdyRstStreamIR&) = delete; - - ~SpdyRstStreamIR() override; - - SpdyErrorCode error_code() const { return error_code_; } - void set_error_code(SpdyErrorCode error_code) { error_code_ = error_code; } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - private: - SpdyErrorCode error_code_; -}; - -class QUICHE_EXPORT SpdySettingsIR : public SpdyFrameIR { - public: - SpdySettingsIR(); - SpdySettingsIR(const SpdySettingsIR&) = delete; - SpdySettingsIR& operator=(const SpdySettingsIR&) = delete; - ~SpdySettingsIR() override; - - // Overwrites as appropriate. - const SettingsMap& values() const { return values_; } - void AddSetting(SpdySettingsId id, int32_t value) { values_[id] = value; } - - bool is_ack() const { return is_ack_; } - void set_is_ack(bool is_ack) { is_ack_ = is_ack; } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - private: - SettingsMap values_; - bool is_ack_; -}; - -class QUICHE_EXPORT SpdyPingIR : public SpdyFrameIR { - public: - explicit SpdyPingIR(SpdyPingId id) : id_(id), is_ack_(false) {} - SpdyPingIR(const SpdyPingIR&) = delete; - SpdyPingIR& operator=(const SpdyPingIR&) = delete; - SpdyPingId id() const { return id_; } - - bool is_ack() const { return is_ack_; } - void set_is_ack(bool is_ack) { is_ack_ = is_ack; } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - private: - SpdyPingId id_; - bool is_ack_; -}; - -class QUICHE_EXPORT SpdyGoAwayIR : public SpdyFrameIR { - public: - // References description, doesn't copy it, so description must outlast - // this SpdyGoAwayIR. - SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code, - absl::string_view description); - - // References description, doesn't copy it, so description must outlast - // this SpdyGoAwayIR. - SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code, - const char* description); - - // Moves description into description_store_, so caller doesn't need to - // keep description live after constructing this SpdyGoAwayIR. - SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code, - std::string description); - SpdyGoAwayIR(const SpdyGoAwayIR&) = delete; - SpdyGoAwayIR& operator=(const SpdyGoAwayIR&) = delete; - - ~SpdyGoAwayIR() override; - - SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; } - void set_last_good_stream_id(SpdyStreamId last_good_stream_id) { - QUICHE_DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask); - last_good_stream_id_ = last_good_stream_id; - } - SpdyErrorCode error_code() const { return error_code_; } - void set_error_code(SpdyErrorCode error_code) { - // TODO(hkhalil): Check valid ranges of error_code? - error_code_ = error_code; - } - - const absl::string_view& description() const { return description_; } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - private: - SpdyStreamId last_good_stream_id_; - SpdyErrorCode error_code_; - const std::string description_store_; - const absl::string_view description_; -}; - -class QUICHE_EXPORT SpdyHeadersIR : public SpdyFrameWithHeaderBlockIR { - public: - explicit SpdyHeadersIR(SpdyStreamId stream_id) - : SpdyHeadersIR(stream_id, Http2HeaderBlock()) {} - SpdyHeadersIR(SpdyStreamId stream_id, Http2HeaderBlock header_block) - : SpdyFrameWithHeaderBlockIR(stream_id, std::move(header_block)) {} - SpdyHeadersIR(const SpdyHeadersIR&) = delete; - SpdyHeadersIR& operator=(const SpdyHeadersIR&) = delete; - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - bool has_priority() const { return has_priority_; } - void set_has_priority(bool has_priority) { has_priority_ = has_priority; } - int weight() const { return weight_; } - void set_weight(int weight) { weight_ = weight; } - SpdyStreamId parent_stream_id() const { return parent_stream_id_; } - void set_parent_stream_id(SpdyStreamId id) { parent_stream_id_ = id; } - bool exclusive() const { return exclusive_; } - void set_exclusive(bool exclusive) { exclusive_ = exclusive; } - bool padded() const { return padded_; } - int padding_payload_len() const { return padding_payload_len_; } - void set_padding_len(int padding_len) { - QUICHE_DCHECK_GT(padding_len, 0); - QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame); - padded_ = true; - // The pad field takes one octet on the wire. - padding_payload_len_ = padding_len - 1; - } - - private: - bool has_priority_ = false; - int weight_ = kHttp2DefaultStreamWeight; - SpdyStreamId parent_stream_id_ = 0; - bool exclusive_ = false; - bool padded_ = false; - int padding_payload_len_ = 0; - const bool add_hpack_overhead_bytes_ = - GetQuicheReloadableFlag(http2_add_hpack_overhead_bytes2); -}; - -class QUICHE_EXPORT SpdyWindowUpdateIR : public SpdyFrameIR { - public: - SpdyWindowUpdateIR(SpdyStreamId stream_id, int32_t delta) - : SpdyFrameIR(stream_id) { - set_delta(delta); - } - SpdyWindowUpdateIR(const SpdyWindowUpdateIR&) = delete; - SpdyWindowUpdateIR& operator=(const SpdyWindowUpdateIR&) = delete; - - int32_t delta() const { return delta_; } - void set_delta(int32_t delta) { - QUICHE_DCHECK_LE(0, delta); - QUICHE_DCHECK_LE(delta, kSpdyMaximumWindowSize); - delta_ = delta; - } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - private: - int32_t delta_; -}; - -class QUICHE_EXPORT SpdyPushPromiseIR : public SpdyFrameWithHeaderBlockIR { - public: - SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id) - : SpdyPushPromiseIR(stream_id, promised_stream_id, Http2HeaderBlock()) {} - SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id, - Http2HeaderBlock header_block) - : SpdyFrameWithHeaderBlockIR(stream_id, std::move(header_block)), - promised_stream_id_(promised_stream_id), - padded_(false), - padding_payload_len_(0) {} - SpdyPushPromiseIR(const SpdyPushPromiseIR&) = delete; - SpdyPushPromiseIR& operator=(const SpdyPushPromiseIR&) = delete; - SpdyStreamId promised_stream_id() const { return promised_stream_id_; } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - bool padded() const { return padded_; } - int padding_payload_len() const { return padding_payload_len_; } - void set_padding_len(int padding_len) { - QUICHE_DCHECK_GT(padding_len, 0); - QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame); - padded_ = true; - // The pad field takes one octet on the wire. - padding_payload_len_ = padding_len - 1; - } - - private: - SpdyStreamId promised_stream_id_; - - bool padded_; - int padding_payload_len_; -}; - -class QUICHE_EXPORT SpdyContinuationIR : public SpdyFrameIR { - public: - explicit SpdyContinuationIR(SpdyStreamId stream_id); - SpdyContinuationIR(const SpdyContinuationIR&) = delete; - SpdyContinuationIR& operator=(const SpdyContinuationIR&) = delete; - ~SpdyContinuationIR() override; - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - bool end_headers() const { return end_headers_; } - void set_end_headers(bool end_headers) { end_headers_ = end_headers; } - const std::string& encoding() const { return encoding_; } - void take_encoding(std::string encoding) { encoding_ = std::move(encoding); } - size_t size() const override; - - private: - std::string encoding_; - bool end_headers_; -}; - -class QUICHE_EXPORT SpdyAltSvcIR : public SpdyFrameIR { - public: - explicit SpdyAltSvcIR(SpdyStreamId stream_id); - SpdyAltSvcIR(const SpdyAltSvcIR&) = delete; - SpdyAltSvcIR& operator=(const SpdyAltSvcIR&) = delete; - ~SpdyAltSvcIR() override; - - std::string origin() const { return origin_; } - const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector() const { - return altsvc_vector_; - } - - void set_origin(std::string origin) { origin_ = std::move(origin); } - void add_altsvc(const SpdyAltSvcWireFormat::AlternativeService& altsvc) { - altsvc_vector_.push_back(altsvc); - } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - private: - std::string origin_; - SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector_; -}; - -class QUICHE_EXPORT SpdyPriorityIR : public SpdyFrameIR { - public: - SpdyPriorityIR(SpdyStreamId stream_id, SpdyStreamId parent_stream_id, - int weight, bool exclusive) - : SpdyFrameIR(stream_id), - parent_stream_id_(parent_stream_id), - weight_(weight), - exclusive_(exclusive) {} - SpdyPriorityIR(const SpdyPriorityIR&) = delete; - SpdyPriorityIR& operator=(const SpdyPriorityIR&) = delete; - SpdyStreamId parent_stream_id() const { return parent_stream_id_; } - int weight() const { return weight_; } - bool exclusive() const { return exclusive_; } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - private: - SpdyStreamId parent_stream_id_; - int weight_; - bool exclusive_; -}; - -class QUICHE_EXPORT SpdyPriorityUpdateIR : public SpdyFrameIR { - public: - SpdyPriorityUpdateIR(SpdyStreamId stream_id, - SpdyStreamId prioritized_stream_id, - std::string priority_field_value) - : SpdyFrameIR(stream_id), - prioritized_stream_id_(prioritized_stream_id), - priority_field_value_(std::move(priority_field_value)) {} - SpdyPriorityUpdateIR(const SpdyPriorityUpdateIR&) = delete; - SpdyPriorityUpdateIR& operator=(const SpdyPriorityUpdateIR&) = delete; - SpdyStreamId prioritized_stream_id() const { return prioritized_stream_id_; } - const std::string& priority_field_value() const { - return priority_field_value_; - } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - private: - SpdyStreamId prioritized_stream_id_; - std::string priority_field_value_; -}; - -struct QUICHE_EXPORT AcceptChOriginValuePair { - std::string origin; - std::string value; - bool operator==(const AcceptChOriginValuePair& rhs) const { - return origin == rhs.origin && value == rhs.value; - } -}; - -class QUICHE_EXPORT SpdyAcceptChIR : public SpdyFrameIR { - public: - SpdyAcceptChIR(std::vector entries) - : entries_(std::move(entries)) {} - SpdyAcceptChIR(const SpdyAcceptChIR&) = delete; - SpdyAcceptChIR& operator=(const SpdyAcceptChIR&) = delete; - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - size_t size() const override; - - const std::vector& entries() const { - return entries_; - } - - private: - std::vector entries_; -}; - -// Represents a frame of unrecognized type. -class QUICHE_EXPORT SpdyUnknownIR : public SpdyFrameIR { - public: - SpdyUnknownIR(SpdyStreamId stream_id, uint8_t type, uint8_t flags, - std::string payload) - : SpdyFrameIR(stream_id), - type_(type), - flags_(flags), - length_(payload.size()), - payload_(std::move(payload)) {} - SpdyUnknownIR(const SpdyUnknownIR&) = delete; - SpdyUnknownIR& operator=(const SpdyUnknownIR&) = delete; - uint8_t type() const { return type_; } - uint8_t flags() const { return flags_; } - size_t length() const { return length_; } - const std::string& payload() const { return payload_; } - - void Visit(SpdyFrameVisitor* visitor) const override; - - SpdyFrameType frame_type() const override; - - int flow_control_window_consumed() const override; - - size_t size() const override; - - protected: - // Allows subclasses to overwrite the default payload length. - void set_length(size_t length) { length_ = length; } - - private: - uint8_t type_; - uint8_t flags_; - size_t length_; - const std::string payload_; -}; - -class QUICHE_EXPORT SpdySerializedFrame { - public: - SpdySerializedFrame() : size_(0) {} - - // Creates a valid SpdySerializedFrame using a pre-created buffer. - SpdySerializedFrame(std::unique_ptr data, size_t size) - : frame_(std::move(data)), size_(size) {} - - SpdySerializedFrame(SpdySerializedFrame&& other) - : frame_(std::move(other.frame_)), size_(other.size_) {} - - SpdySerializedFrame(const SpdySerializedFrame&) = delete; - SpdySerializedFrame& operator=(const SpdySerializedFrame&) = delete; - - SpdySerializedFrame& operator=(SpdySerializedFrame&& other) { - // Take over |other|. - frame_ = std::move(other.frame_); - size_ = other.size_; - return *this; - } - - ~SpdySerializedFrame() = default; - - // Provides access to the frame bytes, which is a buffer containing the frame - // packed as expected for sending over the wire. - char* data() const { return frame_.get(); } - - // Returns the actual size of the underlying buffer. - size_t size() const { return size_; } - - operator absl::string_view() const { - return absl::string_view{frame_.get(), size_}; - } - - private: - std::unique_ptr frame_; - size_t size_; -}; - -// This interface is for classes that want to process SpdyFrameIRs without -// having to know what type they are. An instance of this interface can be -// passed to a SpdyFrameIR's Visit method, and the appropriate type-specific -// method of this class will be called. -class QUICHE_EXPORT SpdyFrameVisitor { - public: - SpdyFrameVisitor() {} - SpdyFrameVisitor(const SpdyFrameVisitor&) = delete; - SpdyFrameVisitor& operator=(const SpdyFrameVisitor&) = delete; - virtual ~SpdyFrameVisitor() {} - - virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) = 0; - virtual void VisitSettings(const SpdySettingsIR& settings) = 0; - virtual void VisitPing(const SpdyPingIR& ping) = 0; - virtual void VisitGoAway(const SpdyGoAwayIR& goaway) = 0; - virtual void VisitHeaders(const SpdyHeadersIR& headers) = 0; - virtual void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) = 0; - virtual void VisitPushPromise(const SpdyPushPromiseIR& push_promise) = 0; - virtual void VisitContinuation(const SpdyContinuationIR& continuation) = 0; - virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) = 0; - virtual void VisitPriority(const SpdyPriorityIR& priority) = 0; - virtual void VisitData(const SpdyDataIR& data) = 0; - virtual void VisitPriorityUpdate( - const SpdyPriorityUpdateIR& priority_update) = 0; - virtual void VisitAcceptCh(const SpdyAcceptChIR& accept_ch) = 0; - virtual void VisitUnknown(const SpdyUnknownIR& /*unknown*/) { - // TODO(birenroy): make abstract. - } -}; - -// Optionally, and in addition to SpdyFramerVisitorInterface, a class supporting -// SpdyFramerDebugVisitorInterface may be used in conjunction with SpdyFramer in -// order to extract debug/internal information about the SpdyFramer as it -// operates. -// -// Most HTTP2 implementations need not bother with this interface at all. -class QUICHE_EXPORT SpdyFramerDebugVisitorInterface { - public: - virtual ~SpdyFramerDebugVisitorInterface() {} - - // Called after compressing a frame with a payload of - // a list of name-value pairs. - // |payload_len| is the uncompressed payload size. - // |frame_len| is the compressed frame size. - virtual void OnSendCompressedFrame(SpdyStreamId /*stream_id*/, - SpdyFrameType /*type*/, - size_t /*payload_len*/, - size_t /*frame_len*/) {} - - // Called when a frame containing a compressed payload of - // name-value pairs is received. - // |frame_len| is the compressed frame size. - virtual void OnReceiveCompressedFrame(SpdyStreamId /*stream_id*/, - SpdyFrameType /*type*/, - size_t /*frame_len*/) {} -}; - -// Calculates the number of bytes required to serialize a SpdyHeadersIR, not -// including the bytes to be used for the encoded header set. -size_t GetHeaderFrameSizeSansBlock(const SpdyHeadersIR& header_ir); - -// Calculates the number of bytes required to serialize a SpdyPushPromiseIR, -// not including the bytes to be used for the encoded header set. -size_t GetPushPromiseFrameSizeSansBlock( - const SpdyPushPromiseIR& push_promise_ir); - -} // namespace spdy +#include "quiche/http2/core/spdy_protocol.h" #endif // QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_headers_handler.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_headers_handler.cc deleted file mode 100644 index 16ff347992..0000000000 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_headers_handler.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "quiche/spdy/test_tools/mock_spdy_headers_handler.h" - -namespace spdy { -namespace test { - -MockSpdyHeadersHandler::MockSpdyHeadersHandler() = default; - -MockSpdyHeadersHandler::~MockSpdyHeadersHandler() = default; - -} // namespace test -} // namespace spdy diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_headers_handler.h b/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_headers_handler.h deleted file mode 100644 index ad0b5dc3af..0000000000 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/spdy/test_tools/mock_spdy_headers_handler.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_SPDY_TEST_TOOLS_MOCK_SPDY_HEADERS_HANDLER_H_ -#define QUICHE_SPDY_TEST_TOOLS_MOCK_SPDY_HEADERS_HANDLER_H_ - -#include - -#include "absl/strings/string_view.h" -#include "quiche/common/platform/api/quiche_export.h" -#include "quiche/common/platform/api/quiche_test.h" -#include "quiche/spdy/core/spdy_headers_handler_interface.h" - -namespace spdy { -namespace test { - -class QUICHE_NO_EXPORT MockSpdyHeadersHandler - : public SpdyHeadersHandlerInterface { - public: - MockSpdyHeadersHandler(); - ~MockSpdyHeadersHandler() override; - - MOCK_METHOD(void, OnHeaderBlockStart, (), (override)); - MOCK_METHOD(void, OnHeader, (absl::string_view key, absl::string_view value), - (override)); - MOCK_METHOD(void, OnHeaderBlockEnd, - (size_t uncompressed_header_bytes, - size_t compressed_header_bytes), - (override)); -}; - -} // namespace test -} // namespace spdy - -#endif // QUICHE_SPDY_TEST_TOOLS_MOCK_SPDY_HEADERS_HANDLER_H_ diff --git a/naiveproxy/src/net/tools/cachetool/cachetool.cc b/naiveproxy/src/net/tools/cachetool/cachetool.cc index 32ef3ca990..98da007eef 100644 --- a/naiveproxy/src/net/tools/cachetool/cachetool.cc +++ b/naiveproxy/src/net/tools/cachetool/cachetool.cc @@ -14,6 +14,7 @@ #include "base/at_exit.h" #include "base/command_line.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/format_macros.h" #include "base/hash/md5.h" @@ -214,7 +215,8 @@ class ProgramArgumentCommandMarshal final : public CommandMarshal { // Implements CommandMarshal. void ReturnBuffer(net::GrowableIOBuffer* buffer) override { DCHECK(!has_failed()); - std::cout.write(buffer->StartOfBuffer(), buffer->offset()); + auto span = base::as_chars(buffer->span_before_offset()); + std::cout.write(span.data(), span.size()); } // Implements CommandMarshal. @@ -299,7 +301,8 @@ class StreamCommandMarshal final : public CommandMarshal { // Implements CommandMarshal. void ReturnBuffer(net::GrowableIOBuffer* buffer) override { ReturnInt(buffer->offset()); - std::cout.write(buffer->StartOfBuffer(), buffer->offset()); + auto span = base::as_chars(buffer->span_before_offset()); + std::cout.write(span.data(), span.size()); } // Implements CommandMarshal. @@ -363,8 +366,9 @@ bool GetResponseInfoForEntry(disk_cache::Entry* entry, if (rv == 0) { bool truncated_response_info = false; - if (!net::HttpCache::ParseResponseInfo( - buffer->data(), size, response_info, &truncated_response_info)) { + if (!net::HttpCache::ParseResponseInfo(base::as_bytes(buffer->span()), + response_info, + &truncated_response_info)) { return false; } return !truncated_response_info; @@ -572,8 +576,8 @@ void GetStreamForKey(CommandMarshal* command_marshal) { if (index == kResponseInfoIndex) { net::HttpResponseInfo response_info; bool truncated_response_info = false; - if (!net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), - buffer->offset(), &response_info, + if (!net::HttpCache::ParseResponseInfo(buffer->span_before_offset(), + &response_info, &truncated_response_info)) { // This can happen when reading data stored by content::CacheStorage. std::cerr << "WARNING: Returning empty response info for key: " << key @@ -605,7 +609,7 @@ void UpdateRawResponseHeaders(CommandMarshal* command_marshal) { return; net::HttpResponseInfo response_info; bool truncated_response_info = false; - net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), + net::HttpCache::ParseResponseInfo(buffer->span_before_offset(), &response_info, &truncated_response_info); if (truncated_response_info) std::cerr << "WARNING: Truncated HTTP response." << std::endl; @@ -632,8 +636,8 @@ void SetHeader(CommandMarshal* command_marshal) { // Read the entry into |response_info|. net::HttpResponseInfo response_info; bool truncated_response_info = false; - if (!net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), - buffer->offset(), &response_info, + if (!net::HttpCache::ParseResponseInfo(buffer->span_before_offset(), + &response_info, &truncated_response_info)) { command_marshal->ReturnFailure("Couldn't read response info"); return; diff --git a/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_comparision_tool.cc b/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_comparision_tool.cc deleted file mode 100644 index 0c12f19be4..0000000000 --- a/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_comparision_tool.cc +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Tool used to do batch comparisons of cert verification results between -// the platform verifier and the builtin verifier. Currently only tested on -// Windows. -#include -#include - -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/containers/span.h" -#include "base/functional/bind.h" -#include "base/functional/callback_helpers.h" -#include "base/logging.h" -#include "base/message_loop/message_pump_type.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/synchronization/waitable_event.h" -#include "base/task/thread_pool/thread_pool_instance.h" -#include "base/threading/thread.h" -#include "build/build_config.h" -#include "net/cert/cert_net_fetcher.h" -#include "net/cert/cert_verify_proc.h" -#include "net/cert/cert_verify_proc_builtin.h" -#include "net/cert/crl_set.h" -#include "net/cert/do_nothing_ct_verifier.h" -#include "net/cert/internal/system_trust_store.h" -#include "net/cert/x509_certificate.h" -#include "net/cert_net/cert_net_fetcher_url_request.h" -#include "net/tools/cert_verify_tool/cert_verify_tool_util.h" -#include "net/tools/cert_verify_tool/dumper.pb.h" -#include "net/tools/cert_verify_tool/verify_using_cert_verify_proc.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_builder.h" -#include "net/url_request/url_request_context_getter.h" - -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -#include "net/proxy_resolution/proxy_config.h" -#include "net/proxy_resolution/proxy_config_service_fixed.h" -#endif - -#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) -#include "net/cert/internal/trust_store_chrome.h" -#endif - -namespace { -std::string GetUserAgent() { - return "cert_verify_comparison_tool/0.1"; -} - -void SetUpOnNetworkThread( - std::unique_ptr* context, - scoped_refptr* cert_net_fetcher, - base::WaitableEvent* initialization_complete_event) { - net::URLRequestContextBuilder url_request_context_builder; - url_request_context_builder.set_user_agent(GetUserAgent()); -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) - // On Linux, use a fixed ProxyConfigService, since the default one - // depends on glib. - // - // TODO(akalin): Remove this once http://crbug.com/146421 is fixed. - url_request_context_builder.set_proxy_config_service( - std::make_unique( - net::ProxyConfigWithAnnotation())); -#endif - *context = url_request_context_builder.Build(); - - // TODO(mattm): add command line flag to configure using - // CertNetFetcher - *cert_net_fetcher = base::MakeRefCounted(); - (*cert_net_fetcher)->SetURLRequestContext(context->get()); - initialization_complete_event->Signal(); -} - -void ShutdownOnNetworkThread( - std::unique_ptr* context, - scoped_refptr* cert_net_fetcher) { - (*cert_net_fetcher)->Shutdown(); - cert_net_fetcher->reset(); - context->reset(); -} - -// Runs certificate verification using a particular CertVerifyProc. -class CertVerifyImpl { - public: - CertVerifyImpl(const std::string& name, - scoped_refptr proc) - : name_(name), proc_(std::move(proc)) {} - - virtual ~CertVerifyImpl() = default; - std::string GetName() const { return name_; } - - // Does certificate verification. - bool VerifyCert(net::X509Certificate& x509_target_and_intermediates, - const std::string& hostname, - net::CertVerifyResult* result, - int* error) { - if (hostname.empty()) { - std::cerr << "ERROR: --hostname is required for " << GetName() - << ", skipping\n"; - return true; // "skipping" is considered a successful return. - } - - // TODO(mattm): add command line flags to configure VerifyFlags. - int flags = 0; - - // TODO(crbug.com/40479281): use a real netlog and print the results? - *error = proc_->Verify(&x509_target_and_intermediates, hostname, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, result, - net::NetLogWithSource()); - - return *error == net::OK; - } - - private: - const std::string name_; - scoped_refptr proc_; -}; - -// Creates an subclass of CertVerifyImpl based on its name, or returns nullptr. -std::unique_ptr CreateCertVerifyImplFromName( - std::string_view impl_name, - scoped_refptr cert_net_fetcher) { -#if !(BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(CHROME_ROOT_STORE_ONLY)) - if (impl_name == "platform") { - return std::make_unique( - "CertVerifyProc (system)", - net::CertVerifyProc::CreateSystemVerifyProc( - std::move(cert_net_fetcher) net::CRLSet::BuiltinCRLSet())); - } -#endif - - if (impl_name == "builtin") { -#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) - return std::make_unique( - "CertVerifyProcBuiltin", - net::CreateCertVerifyProcBuiltin( - std::move(cert_net_fetcher), net::CRLSet::BuiltinCRLSet(), - std::make_unique(), - base::MakeRefCounted(), - net::CreateSslSystemTrustStoreChromeRoot( - std::make_unique()), - {})); -#endif - } - - std::cerr << "WARNING: Unrecognized impl: " << impl_name << "\n"; - return nullptr; -} - -const char kUsage[] = - " --input=\n" - "\n" - " is a file containing serialized protos from trawler. Format \n" - " of the file is a uint32 size, followed by that many bytes of a\n" - " serialized proto message of type \n" - " cert_verify_tool::CertChain. The path to the file must not\n" - " contain any dot(.) characters." - "\n"; - -// Stats based on errors reading and parsing the input file. -std::map file_error_stats; - -std::map chain_processing_stats; - -std::map ignorable_difference_stats; - -void PrintStats() { - std::cout << "\n\nFile processing stats:\n"; - for (const auto& error_stat : file_error_stats) { - std::cout << " " << error_stat.first << ": " << error_stat.second << "\n"; - } - - std::cout << "\n\nChain processing stats:\n"; - for (const auto& chain_stat : chain_processing_stats) { - std::cout << " " << chain_stat.first << ": " << chain_stat.second << "\n"; - } - - std::cout << "\n\nIgnorable difference stats:\n"; - for (const auto& ignorable_diff_stat : ignorable_difference_stats) { - std::cout << " " << ignorable_diff_stat.first << ": " - << ignorable_diff_stat.second << "\n"; - } -} - -void PrintUsage(const char* argv0) { - std::cerr << "Usage: " << argv0 << kUsage; -} - -// Note: This ignores the result of stapled OCSP (which is the same for both -// verifiers) and informational statuses about the certificate algorithms and -// the hashes, since they will be the same if the certificate chains are the -// same. -bool CertVerifyResultEqual(const net::CertVerifyResult& a, - const net::CertVerifyResult& b) { - return std::tie(a.cert_status, a.is_issued_by_known_root) == - std::tie(b.cert_status, b.is_issued_by_known_root) && - (!!a.verified_cert == !!b.verified_cert) && - (!a.verified_cert || - a.verified_cert->EqualsIncludingChain(b.verified_cert.get())); -} - -// Returns -1 if an error occurred. -int RunCert(base::File* input_file, - const std::unique_ptr& platform_proc, - const std::unique_ptr& builtin_proc) { - // read 4 bytes, convert to uint32_t - std::vector size_bytes(4); - int size_bytes_read = input_file->ReadAtCurrentPos(size_bytes.data(), 4); - if (size_bytes_read != 4) { - std::cerr << "Couldn't read 4 byte size field, read only " - << size_bytes_read << "\n"; - file_error_stats["size_read_error"]++; - return -1; - } - - uint32_t proto_size; - proto_size = (static_cast(size_bytes[3]) << 24) + - (static_cast(size_bytes[2]) << 16) + - (static_cast(size_bytes[1]) << 8) + - (static_cast(size_bytes[0])); - - // read proto_size bytes, parse to proto. - std::vector proto_bytes(proto_size); - int proto_bytes_read = - input_file->ReadAtCurrentPos(proto_bytes.data(), proto_size); - - if ((proto_bytes_read - proto_size) != 0) { - std::cerr << "Couldn't read expected proto of size " << proto_size - << "read only " << proto_bytes_read << "\n"; - file_error_stats["proto_read_error"]++; - return -1; - } - - cert_verify_tool::CertChain cert_chain; - - if (!cert_chain.ParseFromArray(proto_bytes.data(), proto_bytes_read)) { - std::cerr << "Proto parse error for proto of size " << proto_size << ", " - << proto_bytes_read << " proto bytes read total, " - << size_bytes_read << " size bytes read\n\n\n"; - file_error_stats["parse_error"]++; - return -1; - } - - std::vector der_cert_chain; - for (int i = 0; i < cert_chain.der_certs_size(); i++) { - der_cert_chain.push_back(cert_chain.der_certs(i)); - } - - scoped_refptr x509_target_and_intermediates = - net::X509Certificate::CreateFromDERCertChain(der_cert_chain); - if (!x509_target_and_intermediates) { - std::cerr << "X509Certificate::CreateFromDERCertChain failed for host" - << cert_chain.host() << "\n\n\n"; - file_error_stats["chain_parse_error"]++; - - // We try to continue here; its possible that the cert chain contained - // invalid certs for some reason so we don't bail out entirely. - return 0; - } - - net::CertVerifyResult platform_result; - int platform_error; - net::CertVerifyResult builtin_result; - int builtin_error; - - platform_proc->VerifyCert(*x509_target_and_intermediates, cert_chain.host(), - &platform_result, &platform_error); - builtin_proc->VerifyCert(*x509_target_and_intermediates, cert_chain.host(), - &builtin_result, &builtin_error); - - if (CertVerifyResultEqual(platform_result, builtin_result) && - platform_error == builtin_error) { - chain_processing_stats["equal"]++; - } else { - // Much of the below code was originally lifted from - // TrialComparisonCertVerifier::Job::OnTrialJobCompleted as it wasn't - // obvious how to easily refactor the code here to prevent copying this - // section of code. The TrialComparisonCertVerifier is now gone, but we - // retain our ability here to show the differences between a result - // returned by the builtin verifier and the native platform verifier. - const bool chains_equal = - platform_result.verified_cert->EqualsIncludingChain( - builtin_result.verified_cert.get()); - - // Chains built were different with either builtin being OK or both not OK. - // Pass builtin chain to platform, see if platform comes back the same. - if (!chains_equal && - (builtin_error == net::OK || platform_error != net::OK)) { - net::CertVerifyResult platform_reverification_result; - int platform_reverification_error; - - platform_proc->VerifyCert( - *builtin_result.verified_cert, cert_chain.host(), - &platform_reverification_result, &platform_reverification_error); - if (CertVerifyResultEqual(platform_reverification_result, - builtin_result) && - platform_reverification_error == builtin_error) { - chain_processing_stats["reverify_ignorable"]++; - return 0; - } - } - - chain_processing_stats["different"]++; - - std::cout << "\n *************************** \n\n" - << "Host " << cert_chain.host() - << " has different verify results!\n"; - - std::cout << "\nInput chain: \n " - << FingerPrintCryptoBuffer( - x509_target_and_intermediates->cert_buffer()) - << " " - << SubjectFromX509Certificate(x509_target_and_intermediates.get()) - << "\n"; - - for (const auto& intermediate : - x509_target_and_intermediates->intermediate_buffers()) { - std::cout << " " << FingerPrintCryptoBuffer(intermediate.get()) << " " - << SubjectFromCryptoBuffer(intermediate.get()) << "\n"; - } - - std::cout << "\nPlatform: (error = " - << net::ErrorToShortString(platform_error) << ")\n"; - PrintCertVerifyResult(platform_result); - std::cout << "\nBuiltin: (error = " - << net::ErrorToShortString(builtin_error) << ")\n"; - PrintCertVerifyResult(builtin_result); - } - - return 0; -} - -} // namespace - -int main(int argc, char** argv) { - base::AtExitManager at_exit_manager; - if (!base::CommandLine::Init(argc, argv)) { - std::cerr << "ERROR in CommandLine::Init\n"; - return 1; - } - - base::ThreadPoolInstance::CreateAndStartWithDefaultParams( - "cert_verify_comparison_tool"); - base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - logging::LoggingSettings settings; - settings.logging_dest = - logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR; - logging::InitLogging(settings); - - base::CommandLine::StringVector args = command_line.GetArgs(); - if (command_line.HasSwitch("help")) { - PrintUsage(argv[0]); - return 1; - } - - base::FilePath input_path = command_line.GetSwitchValuePath("input"); - if (input_path.empty()) { - std::cerr << "Error: --input is required\n"; - return 1; - } - - int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; - std::unique_ptr input_file = - std::make_unique(input_path, flags); - - if (!input_file->IsValid()) { - std::cerr << "Error: --dump file " << input_path.MaybeAsASCII() - << " is not valid \n"; - return 1; - } - - // Create a network thread to be used for AIA fetches, and wait for a - // CertNetFetcher to be constructed on that thread. - base::Thread::Options options(base::MessagePumpType::IO, 0); - base::Thread thread("network_thread"); - CHECK(thread.StartWithOptions(std::move(options))); - // Owned by this thread, but initialized, used, and shutdown on the network - // thread. - std::unique_ptr context; - scoped_refptr cert_net_fetcher; - base::WaitableEvent initialization_complete_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - thread.task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&SetUpOnNetworkThread, &context, &cert_net_fetcher, - &initialization_complete_event)); - initialization_complete_event.Wait(); - - // Initialize verifiers; platform and builtin. - std::vector> impls; - std::unique_ptr platform_proc = - CreateCertVerifyImplFromName("platform", cert_net_fetcher); - if (!platform_proc) { - std::cerr << "Error platform proc not sucessfully created"; - return 1; - } - std::unique_ptr builtin_proc = - CreateCertVerifyImplFromName("builtin", cert_net_fetcher); - if (!builtin_proc) { - std::cerr << "Error builtin proc not sucessfully created"; - return 1; - } - - // Read file and process cert chains. - while (RunCert(input_file.get(), platform_proc, builtin_proc) != -1) { - } - - PrintStats(); - - // Clean up on the network thread and stop it (which waits for the clean up - // task to run). - thread.task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&ShutdownOnNetworkThread, &context, &cert_net_fetcher)); - thread.Stop(); -} diff --git a/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool.cc b/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool.cc index b8ae4d9e1f..9a77fb667f 100644 --- a/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool.cc +++ b/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool.cc @@ -21,6 +21,7 @@ #include "net/cert/cert_verify_proc_builtin.h" #include "net/cert/crl_set.h" #include "net/cert/do_nothing_ct_verifier.h" +#include "net/cert/internal/platform_trust_store.h" #include "net/cert/internal/system_trust_store.h" #include "net/cert/x509_util.h" #include "net/cert_net/cert_net_fetcher_url_request.h" @@ -205,6 +206,8 @@ class DummySystemTrustStore : public net::SystemTrustStore { } #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) + net::PlatformTrustStore* GetPlatformTrustStore() override { return nullptr; } + bool IsLocallyTrustedRoot( const bssl::ParsedCertificate* trust_anchor) override { return false; diff --git a/naiveproxy/src/net/tools/cert_verify_tool/dumper.proto b/naiveproxy/src/net/tools/cert_verify_tool/dumper.proto deleted file mode 100644 index e0ff47324d..0000000000 --- a/naiveproxy/src/net/tools/cert_verify_tool/dumper.proto +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file should be kept in sync with the same file in Google internal. -syntax = "proto2"; - -option optimize_for = LITE_RUNTIME; - -package cert_verify_tool; - -message CertChain { - optional string host = 1; - repeated bytes der_certs = 2; -} \ No newline at end of file diff --git a/naiveproxy/src/net/tools/huffman_trie/trie/trie_bit_buffer.cc b/naiveproxy/src/net/tools/huffman_trie/trie/trie_bit_buffer.cc index c15af44aed..0b1b2c43ab 100644 --- a/naiveproxy/src/net/tools/huffman_trie/trie/trie_bit_buffer.cc +++ b/naiveproxy/src/net/tools/huffman_trie/trie/trie_bit_buffer.cc @@ -9,6 +9,7 @@ #include #include "base/check.h" +#include "base/not_fatal_until.h" #include "net/tools/huffman_trie/bit_writer.h" namespace net::huffman_trie { @@ -83,7 +84,7 @@ void TrieBitBuffer::WriteChar(uint8_t byte, HuffmanBuilder* huffman_builder) { HuffmanRepresentationTable::const_iterator item; item = table.find(byte); - DCHECK(item != table.end()); + CHECK(item != table.end(), base::NotFatalUntil::M130); if (huffman_builder) { huffman_builder->RecordUsage(byte); } diff --git a/naiveproxy/src/net/tools/naive/http_proxy_server_socket.cc b/naiveproxy/src/net/tools/naive/http_proxy_server_socket.cc index 485d9087ed..a503d23b6b 100644 --- a/naiveproxy/src/net/tools/naive/http_proxy_server_socket.cc +++ b/naiveproxy/src/net/tools/naive/http_proxy_server_socket.cc @@ -26,7 +26,7 @@ #include "net/base/url_util.h" #include "net/http/http_request_headers.h" #include "net/log/net_log.h" -#include "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.h" +#include "net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.h" #include "net/tools/naive/naive_protocol.h" #include "net/tools/naive/naive_proxy_delegate.h" #include "url/gurl.h" diff --git a/naiveproxy/src/net/tools/naive/naive_proxy_bin.cc b/naiveproxy/src/net/tools/naive/naive_proxy_bin.cc index c0e40f142d..080be85215 100644 --- a/naiveproxy/src/net/tools/naive/naive_proxy_bin.cc +++ b/naiveproxy/src/net/tools/naive/naive_proxy_bin.cc @@ -173,6 +173,37 @@ std::unique_ptr BuildURLRequestContext( URLRequestContextBuilder builder; builder.DisableHttpCache(); + + // Overrides HTTP/2 initial window size default values to accommodate + // high BDP links. + // See net/http/http_network_session.cc for the default values. + // Alternative implementations than fixed large windows: + // (1) Dynamic window scaling, see + // https://github.com/dotnet/runtime/pull/54755 + // and https://grpc.io/blog/grpc-go-perf-improvements/ + // This approach estimates throughput and RTT in userspace + // and incurs big architectural complexity. + // (2) Obtains TCP receive windows from Linux-specific TCP_INFO. + // This approach is not portable. + // Security impact: + // This use of non-default settings creates a fingerprinting feature + // that is visible to proxy servers, though this is only exploitable + // if the proxy servers can be MITM'd. + + constexpr int kMaxBandwidthMBps = 125; + constexpr double kTypicalRttSecond = 0.256; + constexpr int kMaxBdpMB = kMaxBandwidthMBps * kTypicalRttSecond; + + // The windows size should be twice the BDP because WINDOW_UPDATEs + // are sent after half the window is unacknowledged. + constexpr int kTypicalWindow = kMaxBdpMB * 2 * 1024 * 1024; + HttpNetworkSessionParams http_network_session_params; + http_network_session_params.spdy_session_max_recv_window_size = + kTypicalWindow * 2; + http_network_session_params + .http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = kTypicalWindow; + builder.set_http_network_session_params(http_network_session_params); + builder.set_net_log(net_log); ProxyConfig proxy_config; @@ -198,7 +229,7 @@ std::unique_ptr BuildURLRequestContext( CertVerifier::CreateDefault(std::move(cert_net_fetcher))); builder.set_proxy_delegate(std::make_unique( - config.extra_headers, + config.extra_headers, std::vector{PaddingType::kVariant1, PaddingType::kNone})); if (config.no_post_quantum == true) { diff --git a/naiveproxy/src/net/tools/naive/naive_proxy_delegate.cc b/naiveproxy/src/net/tools/naive/naive_proxy_delegate.cc index 254a462a31..6a199fb932 100644 --- a/naiveproxy/src/net/tools/naive/naive_proxy_delegate.cc +++ b/naiveproxy/src/net/tools/naive/naive_proxy_delegate.cc @@ -18,7 +18,7 @@ #include "net/base/proxy_string_util.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" -#include "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.h" +#include "net/third_party/quiche/src/quiche/http2/hpack/hpack_constants.h" namespace net { namespace { diff --git a/naiveproxy/src/net/tools/quic/quic_client_message_loop_network_helper.cc b/naiveproxy/src/net/tools/quic/quic_client_message_loop_network_helper.cc index 8d979cccb2..09ec9e6d2e 100644 --- a/naiveproxy/src/net/tools/quic/quic_client_message_loop_network_helper.cc +++ b/naiveproxy/src/net/tools/quic/quic_client_message_loop_network_helper.cc @@ -28,7 +28,6 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" using std::string; diff --git a/naiveproxy/src/net/tools/quic/quic_simple_client.cc b/naiveproxy/src/net/tools/quic/quic_simple_client.cc index cdc7bf5e5a..f04f991cf6 100644 --- a/naiveproxy/src/net/tools/quic/quic_simple_client.cc +++ b/naiveproxy/src/net/tools/quic/quic_simple_client.cc @@ -27,7 +27,6 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quiche/quic/tools/quic_simple_client_session.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" using std::string; diff --git a/naiveproxy/src/net/tools/quic/quic_simple_client_bin.cc b/naiveproxy/src/net/tools/quic/quic_simple_client_bin.cc index 6e6c6998cf..f81c28f78d 100644 --- a/naiveproxy/src/net/tools/quic/quic_simple_client_bin.cc +++ b/naiveproxy/src/net/tools/quic/quic_simple_client_bin.cc @@ -46,7 +46,6 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.h" #include "net/third_party/quiche/src/quiche/quic/tools/quic_toy_client.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/tools/quic/quic_simple_client.h" #include "net/tools/quic/synchronous_host_resolver.h" #include "url/scheme_host_port.h" diff --git a/naiveproxy/src/net/tools/root_store_tool/root_store_tool.cc b/naiveproxy/src/net/tools/root_store_tool/root_store_tool.cc index fa1eb69476..f0e258b599 100644 --- a/naiveproxy/src/net/tools/root_store_tool/root_store_tool.cc +++ b/naiveproxy/src/net/tools/root_store_tool/root_store_tool.cc @@ -31,7 +31,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "crypto/openssl_util.h" #include "crypto/sha2.h" #include "net/cert/root_store_proto_full/root_store.pb.h" #include "third_party/boringssl/src/include/openssl/bio.h" @@ -338,8 +337,6 @@ int main(int argc, char** argv) { logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR; logging::InitLogging(settings); - crypto::EnsureOpenSSLInit(); - base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); base::FilePath proto_path = command_line.GetSwitchValuePath("write-proto"); base::FilePath root_store_cpp_path = diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/transport_security_state_generator.cc b/naiveproxy/src/net/tools/transport_security_state_generator/transport_security_state_generator.cc index 1332a279b1..4360cb8b9e 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/transport_security_state_generator.cc +++ b/naiveproxy/src/net/tools/transport_security_state_generator/transport_security_state_generator.cc @@ -21,7 +21,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "build/build_config.h" -#include "crypto/openssl_util.h" #include "net/tools/transport_security_state_generator/input_file_parsers.h" #include "net/tools/transport_security_state_generator/pinsets.h" #include "net/tools/transport_security_state_generator/preloaded_state_generator.h" @@ -193,8 +192,6 @@ bool CheckHostnames(const TransportSecurityStateEntries& entries) { } // namespace int main(int argc, char* argv[]) { - crypto::EnsureOpenSSLInit(); - base::AtExitManager at_exit_manager; base::CommandLine::Init(argc, argv); const base::CommandLine& command_line = diff --git a/naiveproxy/src/net/url_request/url_request.cc b/naiveproxy/src/net/url_request/url_request.cc index d492d9058d..bf1415a152 100644 --- a/naiveproxy/src/net/url_request/url_request.cc +++ b/naiveproxy/src/net/url_request/url_request.cc @@ -11,6 +11,7 @@ #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" #include "base/metrics/histogram_macros.h" +#include "base/notreached.h" #include "base/rand_util.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" @@ -39,6 +40,7 @@ #include "net/socket/next_proto.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_private_key.h" +#include "net/storage_access_api/status.h" #include "net/url_request/redirect_info.h" #include "net/url_request/redirect_util.h" #include "net/url_request/url_request_context.h" @@ -258,9 +260,16 @@ int64_t URLRequest::GetTotalSentBytes() const { } int64_t URLRequest::GetRawBodyBytes() const { - if (!job_.get()) + if (!job_.get()) { return 0; + } + if (int64_t bytes = job_->GetReceivedBodyBytes()) { + return bytes; + } + + // GetReceivedBodyBytes() is available only when the body was received from + // the network. Otherwise, returns prefilter_bytes_read() instead. return job_->prefilter_bytes_read(); } @@ -473,7 +482,8 @@ void URLRequest::set_site_for_cookies(const SiteForCookies& site_for_cookies) { site_for_cookies_ = site_for_cookies; } -void URLRequest::set_isolation_info(const IsolationInfo& isolation_info) { +void URLRequest::set_isolation_info(const IsolationInfo& isolation_info, + std::optional redirect_info_new_url) { isolation_info_ = isolation_info; bool is_main_frame_navigation = isolation_info.IsMainFrameRequest() || @@ -481,7 +491,10 @@ void URLRequest::set_isolation_info(const IsolationInfo& isolation_info) { cookie_partition_key_ = CookiePartitionKey::FromNetworkIsolationKey( isolation_info.network_isolation_key(), isolation_info.site_for_cookies(), - net::SchemefulSite(original_url()), is_main_frame_navigation); + net::SchemefulSite(redirect_info_new_url.has_value() + ? redirect_info_new_url.value() + : url_chain_.back()), + is_main_frame_navigation); } void URLRequest::set_isolation_info_from_network_anonymization_key( @@ -664,6 +677,9 @@ void URLRequest::StartJob(std::unique_ptr job) { is_shared_dictionary_read_allowed_callback_); } job_->SetResponseHeadersCallback(response_headers_callback_); + if (shared_dictionary_getter_) { + job_->SetSharedDictionaryGetter(shared_dictionary_getter_); + } if (upload_data_stream_.get()) job_->SetUpload(upload_data_stream_.get()); @@ -993,7 +1009,9 @@ void URLRequest::Redirect( referrer_policy_ = redirect_info.new_referrer_policy; site_for_cookies_ = redirect_info.new_site_for_cookies; set_isolation_info(isolation_info_.CreateForRedirect( - url::Origin::Create(redirect_info.new_url))); + url::Origin::Create(redirect_info.new_url)), + redirect_info.new_url); + cookie_setting_overrides().Remove( CookieSettingOverride::kStorageAccessGrantEligibleViaHeader); @@ -1015,7 +1033,6 @@ void URLRequest::RetryWithStorageAccess() { CookieSettingOverride::kStorageAccessGrantEligibleViaHeader)); CHECK(!cookie_setting_overrides().Has( CookieSettingOverride::kStorageAccessGrantEligible)); - CHECK(!has_storage_access()); net_log_.AddEvent(NetLogEventType::URL_REQUEST_RETRY_WITH_STORAGE_ACCESS); if (network_delegate()) { @@ -1300,12 +1317,28 @@ void URLRequest::set_socket_tag(const SocketTag& socket_tag) { } bool URLRequest::ShouldSetLoadWithStorageAccess() const { - // TODO(https://crbug.com/344608182): this should probably only return true if - // the Storage-Access state is "inactive" or "active"/allowed. For now, this - // is fine because this is only used to set the renderer's bool, which is - // untrusted anyway. + CHECK(job_); + auto storage_access_can_be_activated = [this]() -> bool { + switch (job_->StorageAccessStatus()) { + case cookie_util::StorageAccessStatus::kNone: + return false; + case cookie_util::StorageAccessStatus::kInactive: + return true; + case cookie_util::StorageAccessStatus::kActive: + return true; + } + NOTREACHED_NORETURN(); + }; return base::FeatureList::IsEnabled(features::kStorageAccessHeaders) && - response_headers() && response_headers()->HasStorageAccessLoadHeader(); + storage_access_can_be_activated() && response_headers() && + response_headers()->HasStorageAccessLoadHeader(); +} + +void URLRequest::SetSharedDictionaryGetter( + SharedDictionaryGetter shared_dictionary_getter) { + CHECK(!job_.get()); + CHECK(shared_dictionary_getter_.is_null()); + shared_dictionary_getter_ = std::move(shared_dictionary_getter); } base::WeakPtr URLRequest::GetWeakPtr() { diff --git a/naiveproxy/src/net/url_request/url_request.h b/naiveproxy/src/net/url_request/url_request.h index d2785138ff..27bec2da48 100644 --- a/naiveproxy/src/net/url_request/url_request.h +++ b/naiveproxy/src/net/url_request/url_request.h @@ -50,8 +50,11 @@ #include "net/log/net_log_source.h" #include "net/log/net_log_with_source.h" #include "net/net_buildflags.h" +#include "net/shared_dictionary/shared_dictionary.h" +#include "net/shared_dictionary/shared_dictionary_getter.h" #include "net/socket/connection_attempts.h" #include "net/socket/socket_tag.h" +#include "net/storage_access_api/status.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/redirect_info.h" #include "net/url_request/referrer_policy.h" @@ -285,11 +288,17 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // are sent, what NetworkAnonymizationKey is used for cached resources, and // how that behavior changes when following redirects. This may only be // changed before Start() is called. Setting this value causes the - // cookie_partition_key_ to be recalculated. + // cookie_partition_key_ to be recalculated. When the isolation information is + // set through a redirect, the request_site used to create the partition key + // should come from the new_url associated with the redirect_info object + // associated with the redirect to ensure the cookie partition key's ancestor + // chain bit is set correctly. // - // TODO(crbug.com/40122112): This isn't actually used yet for SameSite + // TODO(crbug.com/40093296): This isn't actually used yet for SameSite // cookies. Update consumers and fix that. - void set_isolation_info(const IsolationInfo& isolation_info); + void set_isolation_info( + const IsolationInfo& isolation_info, + std::optional redirect_info_new_url = std::nullopt); // This will convert the passed NetworkAnonymizationKey to an IsolationInfo. // This IsolationInfo mmay be assigned an inaccurate frame origin because the @@ -840,12 +849,20 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { void SetIdempotency(Idempotency idempotency) { idempotency_ = idempotency; } Idempotency GetIdempotency() const { return idempotency_; } - void set_has_storage_access(bool has_storage_access) { + // Set a SharedDictionaryGetter which will be used to get a shared dictionary + // for this request. This must not be called after Start() is called. + void SetSharedDictionaryGetter( + SharedDictionaryGetter shared_dictionary_getter); + + void set_storage_access_api_status( + StorageAccessApiStatus storage_access_api_status) { DCHECK(!is_pending_); DCHECK(!has_notified_completion_); - has_storage_access_ = has_storage_access; + storage_access_api_status_ = storage_access_api_status; + } + StorageAccessApiStatus storage_access_api_status() const { + return storage_access_api_status_; } - bool has_storage_access() const { return has_storage_access_; } // Returns true if the corresponding `URLResponseHead`'s // `load_with_storage_access` field should be set. @@ -1004,10 +1021,14 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // Whether the request is allowed to send credentials in general. Set by // caller. bool allow_credentials_ = true; - // Whether the request is eligible for using storage access permission grant - // if one exists. Only set by caller when constructed and will not change - // during redirects. - bool has_storage_access_ = false; + // Whether the request is eligible for using a storage access permission grant if one exists. Only set by + // caller when constructed and will not change during redirects. + // + // Note that this has no effect if the request initiator site and the request + // URL are not same-site to each other. + StorageAccessApiStatus storage_access_api_status_ = + StorageAccessApiStatus::kNone; SecureDnsPolicy secure_dns_policy_ = SecureDnsPolicy::kAllow; CookieAccessResultList maybe_sent_cookies_; @@ -1126,6 +1147,8 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // Idempotency of the request. Idempotency idempotency_ = DEFAULT_IDEMPOTENCY; + SharedDictionaryGetter shared_dictionary_getter_; + THREAD_CHECKER(thread_checker_); base::WeakPtrFactory weak_factory_{this}; diff --git a/naiveproxy/src/net/url_request/url_request_context.cc b/naiveproxy/src/net/url_request/url_request_context.cc index b2fb6821d2..fbe9fdd803 100644 --- a/naiveproxy/src/net/url_request/url_request_context.cc +++ b/naiveproxy/src/net/url_request/url_request_context.cc @@ -48,7 +48,7 @@ #endif // BUILDFLAG(ENABLE_REPORTING) #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) -#include "net/device_bound_sessions/device_bound_session_service.h" +#include "net/device_bound_sessions/session_service.h" #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) namespace net { @@ -259,7 +259,8 @@ void URLRequestContext::set_transport_security_persister( #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) void URLRequestContext::set_device_bound_session_service( - std::unique_ptr device_bound_session_service) { + std::unique_ptr + device_bound_session_service) { device_bound_session_service_ = std::move(device_bound_session_service); } #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) diff --git a/naiveproxy/src/net/url_request/url_request_context.h b/naiveproxy/src/net/url_request/url_request_context.h index 957d2ee53d..f89ccd4b8a 100644 --- a/naiveproxy/src/net/url_request/url_request_context.h +++ b/naiveproxy/src/net/url_request/url_request_context.h @@ -62,7 +62,9 @@ class ReportingService; #endif // BUILDFLAG(ENABLE_REPORTING) #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) -class DeviceBoundSessionService; +namespace device_bound_sessions { +class SessionService; +} #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) // Class that provides application-specific context for URLRequest @@ -213,7 +215,7 @@ class NET_EXPORT URLRequestContext final { #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) // May return nullptr if the feature is disabled. - DeviceBoundSessionService* device_bound_session_service() const { + device_bound_sessions::SessionService* device_bound_session_service() const { return device_bound_session_service_.get(); } #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) @@ -314,7 +316,8 @@ class NET_EXPORT URLRequestContext final { raw_ptr net_log_ = nullptr; #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) void set_device_bound_session_service( - std::unique_ptr device_bound_session_service); + std::unique_ptr + device_bound_session_service); #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) std::unique_ptr host_resolver_; @@ -364,7 +367,8 @@ class NET_EXPORT URLRequestContext final { url_requests_; #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) - std::unique_ptr device_bound_session_service_; + std::unique_ptr + device_bound_session_service_; #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) // Enables Brotli Content-Encoding support. diff --git a/naiveproxy/src/net/url_request/url_request_context_builder.cc b/naiveproxy/src/net/url_request/url_request_context_builder.cc index 1649b10001..752dbaddec 100644 --- a/naiveproxy/src/net/url_request/url_request_context_builder.cc +++ b/naiveproxy/src/net/url_request/url_request_context_builder.cc @@ -45,6 +45,7 @@ #include "net/proxy_resolution/configured_proxy_resolution_service.h" #include "net/quic/quic_context.h" #include "net/quic/quic_session_pool.h" +#include "net/shared_dictionary/shared_dictionary_network_transaction_factory.h" #include "net/socket/network_binding_client_socket_factory.h" #include "net/ssl/ssl_config_service_defaults.h" #include "net/url_request/static_http_user_agent_settings.h" @@ -64,7 +65,7 @@ #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) -#include "net/device_bound_sessions/device_bound_session_service.h" +#include "net/device_bound_sessions/session_service.h" #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) namespace net { @@ -249,7 +250,8 @@ void URLRequestContextBuilder::SetCreateHttpTransactionFactoryCallback( #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) void URLRequestContextBuilder::set_device_bound_session_service( - std::unique_ptr device_bound_session_service) { + std::unique_ptr + device_bound_session_service) { device_bound_session_service_ = std::move(device_bound_session_service); } #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) @@ -506,7 +508,7 @@ std::unique_ptr URLRequestContextBuilder::Build() { #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) if (has_device_bound_session_service_) { context->set_device_bound_session_service( - DeviceBoundSessionService::Create(context.get())); + device_bound_sessions::SessionService::Create(context.get())); } else { if (device_bound_session_service_) { context->set_device_bound_session_service( @@ -538,6 +540,12 @@ std::unique_ptr URLRequestContextBuilder::Build() { std::make_unique(context->http_network_session()); } + if (enable_shared_dictionary_) { + http_transaction_factory = + std::make_unique( + std::move(http_transaction_factory), enable_shared_zstd_); + } + if (http_cache_enabled_) { std::unique_ptr http_cache_backend; if (http_cache_params_.type != HttpCacheParams::IN_MEMORY) { diff --git a/naiveproxy/src/net/url_request/url_request_context_builder.h b/naiveproxy/src/net/url_request/url_request_context_builder.h index a15febef3b..3b53b772d7 100644 --- a/naiveproxy/src/net/url_request/url_request_context_builder.h +++ b/naiveproxy/src/net/url_request/url_request_context_builder.h @@ -66,7 +66,9 @@ class PersistentReportingAndNelStore; #endif // BUILDFLAG(ENABLE_REPORTING) #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) -class DeviceBoundSessionService; +namespace device_bound_sessions { +class SessionService; +} #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) // A URLRequestContextBuilder creates a single URLRequestContext. It provides @@ -146,6 +148,17 @@ class NET_EXPORT URLRequestContextBuilder { // Sets whether Zstd compression is enabled. Disabled by default. void set_enable_zstd(bool enable_zstd) { enable_zstd_ = enable_zstd; } + // Sets whether Compression Dictionary is enabled. Disabled by default. + void set_enable_shared_dictionary(bool enable_shared_dictionary) { + enable_shared_dictionary_ = enable_shared_dictionary; + } + + // Sets whether SZSTD of Compression Dictionary is enabled. Disabled by + // default. + void set_enable_shared_zstd(bool enable_shared_zstd) { + enable_shared_zstd_ = enable_shared_zstd; + } + // Sets the |check_cleartext_permitted| flag, which controls whether to check // system policy before allowing a cleartext http or ws request. void set_check_cleartext_permitted(bool value) { @@ -351,7 +364,8 @@ class NET_EXPORT URLRequestContextBuilder { #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) void set_device_bound_session_service( - std::unique_ptr device_bound_session_service); + std::unique_ptr + device_bound_session_service); void set_has_device_bound_session_service(bool enable) { has_device_bound_session_service_ = enable; @@ -411,6 +425,8 @@ class NET_EXPORT URLRequestContextBuilder { bool enable_brotli_ = false; bool enable_zstd_ = false; + bool enable_shared_dictionary_ = false; + bool enable_shared_zstd_ = false; bool check_cleartext_permitted_ = false; bool require_network_anonymization_key_ = false; raw_ptr network_quality_estimator_ = nullptr; @@ -466,7 +482,8 @@ class NET_EXPORT URLRequestContextBuilder { protocol_handlers_; #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) bool has_device_bound_session_service_ = false; - std::unique_ptr device_bound_session_service_; + std::unique_ptr + device_bound_session_service_; #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) raw_ptr client_socket_factory_raw_ = nullptr; diff --git a/naiveproxy/src/net/url_request/url_request_filter.cc b/naiveproxy/src/net/url_request/url_request_filter.cc index fe155cc07f..ec04875056 100644 --- a/naiveproxy/src/net/url_request/url_request_filter.cc +++ b/naiveproxy/src/net/url_request/url_request_filter.cc @@ -5,6 +5,7 @@ #include "net/url_request/url_request_filter.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/task/current_thread.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_job.h" @@ -34,14 +35,13 @@ bool OnMessageLoopForInterceptorRemoval() { } // namespace -URLRequestFilter* URLRequestFilter::shared_instance_ = nullptr; - // static URLRequestFilter* URLRequestFilter::GetInstance() { + // base::NoDestructor is not used because most tests don't use + // URLRequestFilter, so there's no point in reserving space for it. + static URLRequestFilter* instance = new URLRequestFilter(); DCHECK(OnMessageLoopForInterceptorAddition()); - if (!shared_instance_) - shared_instance_ = new URLRequestFilter; - return shared_instance_; + return instance; } void URLRequestFilter::AddHostnameInterceptor( @@ -53,14 +53,11 @@ void URLRequestFilter::AddHostnameInterceptor( hostname_interceptor_map_[std::pair(scheme, hostname)] = std::move(interceptor); -#ifndef NDEBUG +#if !defined(NDEBUG) // Check to see if we're masking URLs in the url_interceptor_map_. - for (const auto& pair : url_interceptor_map_) { - const GURL& url = GURL(pair.first); - HostnameInterceptorMap::const_iterator host_it = - hostname_interceptor_map_.find(std::pair(url.scheme(), url.host())); - if (host_it != hostname_interceptor_map_.end()) - NOTREACHED_IN_MIGRATION(); + for (const auto& [url_spec, _] : url_interceptor_map_) { + const GURL url(url_spec); + DCHECK(!hostname_interceptor_map_.contains({url.scheme(), url.host()})); } #endif // !NDEBUG } @@ -139,8 +136,7 @@ URLRequestFilter::URLRequestFilter() { } URLRequestFilter::~URLRequestFilter() { - DCHECK(OnMessageLoopForInterceptorRemoval()); - URLRequestJobFactory::SetInterceptorForTesting(nullptr); + NOTREACHED(); } } // namespace net diff --git a/naiveproxy/src/net/url_request/url_request_filter.h b/naiveproxy/src/net/url_request/url_request_filter.h index 9d137f2019..c90024639f 100644 --- a/naiveproxy/src/net/url_request/url_request_filter.h +++ b/naiveproxy/src/net/url_request/url_request_filter.h @@ -9,7 +9,6 @@ #include #include -#include "net/base/net_export.h" #include "net/url_request/url_request_interceptor.h" class GURL; @@ -37,7 +36,7 @@ class URLRequestInterceptor; // If the URLRequestFilter::MaybeInterceptRequest can't find a handler for a // request, it returns NULL and lets the configured ProtocolHandler handle the // request. -class NET_EXPORT URLRequestFilter : public URLRequestInterceptor { +class URLRequestFilter : public URLRequestInterceptor { public: // Singleton instance for use. static URLRequestFilter* GetInstance(); @@ -88,9 +87,6 @@ class NET_EXPORT URLRequestFilter : public URLRequestInterceptor { URLInterceptorMap url_interceptor_map_; mutable int hit_count_ = 0; - - // Singleton instance. - static URLRequestFilter* shared_instance_; }; } // namespace net diff --git a/naiveproxy/src/net/url_request/url_request_http_job.cc b/naiveproxy/src/net/url_request/url_request_http_job.cc index 0a05208583..2406307657 100644 --- a/naiveproxy/src/net/url_request/url_request_http_job.cc +++ b/naiveproxy/src/net/url_request/url_request_http_job.cc @@ -57,6 +57,7 @@ #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_access_delegate.h" #include "net/cookies/cookie_constants.h" +#include "net/cookies/cookie_partition_key.h" #include "net/cookies/cookie_setting_override.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" @@ -91,6 +92,7 @@ #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_config_service.h" #include "net/ssl/ssl_connection_status_flags.h" +#include "net/storage_access_api/status.h" #include "net/url_request/clear_site_data.h" #include "net/url_request/redirect_util.h" #include "net/url_request/url_request.h" @@ -108,8 +110,8 @@ #endif #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) -#include "net/device_bound_sessions/device_bound_session_registration_fetcher_param.h" -#include "net/device_bound_sessions/device_bound_session_service.h" +#include "net/device_bound_sessions/registration_fetcher_param.h" +#include "net/device_bound_sessions/session_service.h" #endif // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) namespace { @@ -151,6 +153,7 @@ base::Value::Dict CookieInclusionStatusNetLogParams( const std::string& cookie_name, const std::string& cookie_domain, const std::string& cookie_path, + const std::optional& partition_key, const net::CookieInclusionStatus& status, net::NetLogCaptureMode capture_mode) { base::Value::Dict dict; @@ -164,6 +167,21 @@ base::Value::Dict CookieInclusionStatusNetLogParams( if (!cookie_path.empty()) dict.Set("path", cookie_path); } + // The partition key is not sensitive, since it is fully determined by the + // structure of the page. The cookie may either be partitioned or not, but + // does not have the ability to influence the key's value. + std::string partition_key_str; + if (partition_key.has_value()) { + base::expected + serialized = net::CookiePartitionKey::Serialize(partition_key); + partition_key_str = serialized.has_value() + ? serialized.value().GetDebugString() + : serialized.error(); + } else { + partition_key_str = "(none)"; + } + dict.Set("partition_key", std::move(partition_key_str)); return dict; } @@ -318,6 +336,18 @@ void RecordSTSHistograms(net::SSLUpgradeDecision upgrade_decision, GetMetricForSSLUpgradeDecision(upgrade_decision, is_secure)); } +char const* GetSecFetchStorageAccessHeaderValue( + net::cookie_util::StorageAccessStatus storage_access_status) { + switch (storage_access_status) { + case net::cookie_util::StorageAccessStatus::kInactive: + return "inactive"; + case net::cookie_util::StorageAccessStatus::kActive: + return "active"; + case net::cookie_util::StorageAccessStatus::kNone: + return "none"; + } +} + } // namespace namespace net { @@ -431,10 +461,11 @@ void URLRequestHttpJob::Start() { // benefit from each other's storage access API grants. request()->cookie_setting_overrides().PutOrRemove( CookieSettingOverride::kStorageAccessGrantEligible, - request()->has_storage_access() && request_initiator_site().has_value() && + request()->storage_access_api_status() == + StorageAccessApiStatus::kAccessViaAPI && + request_initiator_site().has_value() && IsSameSiteIgnoringWebSocketProtocol(request_initiator_site().value(), request()->url())); - CookieStore* cookie_store = request()->context()->cookie_store(); const CookieAccessDelegate* delegate = cookie_store ? cookie_store->cookie_access_delegate() : nullptr; @@ -455,6 +486,35 @@ void URLRequestHttpJob::Start() { } } +namespace { + +bool ShouldBlockAllCookies(PrivacyMode privacy_mode) { + return privacy_mode == PRIVACY_MODE_ENABLED || + privacy_mode == PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS; +} + +} // namespace + +void URLRequestHttpJob::MaybeSetSecFetchStorageAccessHeader() { + if (!base::FeatureList::IsEnabled(features::kStorageAccessHeaders)) { + return; + } + // Avoid attaching the header in cases where the Cookie header is not included + // in the request. + if (!ShouldAddCookieHeader() || + ShouldBlockAllCookies(request_info_.privacy_mode)) { + return; + } + std::optional storage_access_status = + request_->network_delegate()->GetStorageAccessStatus(*request_); + if (storage_access_status) { + storage_access_status_ = storage_access_status.value(); + request_info_.extra_headers.SetHeader( + HttpRequestHeaders::kSecFetchStorageAccess, + GetSecFetchStorageAccessHeaderValue(storage_access_status_)); + } +} + void URLRequestHttpJob::OnGotFirstPartySetMetadata( FirstPartySetMetadata first_party_set_metadata, FirstPartySetsCacheFilter::MatchInfo match_info) { @@ -756,6 +816,7 @@ void URLRequestHttpJob::AddExtraHeaders() { accept_language); } } + MaybeSetSecFetchStorageAccessHeader(); } void URLRequestHttpJob::AddCookieHeaderAndStart() { @@ -789,15 +850,6 @@ void URLRequestHttpJob::AddCookieHeaderAndStart() { weak_factory_.GetWeakPtr(), options)); } -namespace { - -bool ShouldBlockAllCookies(const PrivacyMode& privacy_mode) { - return privacy_mode == PRIVACY_MODE_ENABLED || - privacy_mode == PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS; -} - -} // namespace - void URLRequestHttpJob::SetCookieHeaderAndStart( const CookieOptions& options, const CookieAccessResultList& cookies_with_access_result_list, @@ -917,6 +969,7 @@ void URLRequestHttpJob::SetCookieHeaderAndStart( "send", cookie_with_access_result.cookie.Name(), cookie_with_access_result.cookie.Domain(), cookie_with_access_result.cookie.Path(), + cookie_with_access_result.cookie.PartitionKey(), cookie_with_access_result.access_result.status, capture_mode); }); } @@ -1084,15 +1137,16 @@ void URLRequestHttpJob::OnSetCookieResult(const CookieOptions& options, std::string cookie_string, CookieAccessResult access_result) { if (request_->net_log().IsCapturing()) { - request_->net_log().AddEvent(NetLogEventType::COOKIE_INCLUSION_STATUS, - [&](NetLogCaptureMode capture_mode) { - return CookieInclusionStatusNetLogParams( - "store", - cookie ? cookie.value().Name() : "", - cookie ? cookie.value().Domain() : "", - cookie ? cookie.value().Path() : "", - access_result.status, capture_mode); - }); + request_->net_log().AddEvent( + NetLogEventType::COOKIE_INCLUSION_STATUS, + [&](NetLogCaptureMode capture_mode) { + return CookieInclusionStatusNetLogParams( + "store", cookie ? cookie.value().Name() : "", + cookie ? cookie.value().Domain() : "", + cookie ? cookie.value().Path() : "", + cookie ? cookie.value().PartitionKey() : std::nullopt, + access_result.status, capture_mode); + }); } set_cookie_access_result_list_.emplace_back( @@ -1109,8 +1163,8 @@ void URLRequestHttpJob::OnSetCookieResult(const CookieOptions& options, #if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS) void URLRequestHttpJob::ProcessDeviceBoundSessionsHeader() { - std::vector params = - DeviceBoundSessionRegistrationFetcherParam::CreateIfValid( + std::vector params = + device_bound_sessions::RegistrationFetcherParam::CreateIfValid( request_->url(), GetResponseHeaders()); if (auto* service = request_->context()->device_bound_session_service()) { for (auto& param : params) { @@ -1474,6 +1528,11 @@ std::unique_ptr URLRequestHttpJob::SetUpSourceStream() { return upstream; } +cookie_util::StorageAccessStatus URLRequestHttpJob::StorageAccessStatus() + const { + return storage_access_status_; +} + bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const { // Allow modification of reference fragments by default, unless // |preserve_fragment_on_redirect_url_| is set and equal to the redirect URL. @@ -1526,6 +1585,7 @@ bool URLRequestHttpJob::NeedsRetryWithStorageAccess() { return false; } if (!ShouldAddCookieHeader() || + storage_access_status_ != cookie_util::StorageAccessStatus::kInactive || request_->cookie_setting_overrides().Has( CookieSettingOverride::kStorageAccessGrantEligible) || request_->cookie_setting_overrides().Has( @@ -1540,6 +1600,12 @@ bool URLRequestHttpJob::NeedsRetryWithStorageAccess() { return headers && headers->HasStorageAccessRetryHeader(); } +void URLRequestHttpJob::SetSharedDictionaryGetter( + SharedDictionaryGetter dictionary_getter) { + CHECK(!request_info_.dictionary_getter); + request_info_.dictionary_getter = std::move(dictionary_getter); +} + std::unique_ptr URLRequestHttpJob::GetAuthChallengeInfo() { DCHECK(transaction_.get()); DCHECK(response_info_); @@ -1700,6 +1766,13 @@ int64_t URLRequestHttpJob::GetTotalSentBytes() const { return total_sent_bytes; } +int64_t URLRequestHttpJob::GetReceivedBodyBytes() const { + if (transaction_) { + return transaction_->GetReceivedBodyBytes(); + } + return 0; +} + void URLRequestHttpJob::DoneReading() { if (transaction_) { transaction_->DoneReading(); diff --git a/naiveproxy/src/net/url_request/url_request_http_job.h b/naiveproxy/src/net/url_request/url_request_http_job.h index 0c51ce86d8..dc3e7ca637 100644 --- a/naiveproxy/src/net/url_request/url_request_http_job.h +++ b/naiveproxy/src/net/url_request/url_request_http_job.h @@ -24,6 +24,7 @@ #include "net/base/net_export.h" #include "net/base/privacy_mode.h" #include "net/cookies/cookie_inclusion_status.h" +#include "net/cookies/cookie_util.h" #include "net/first_party_sets/first_party_set_metadata.h" #include "net/first_party_sets/first_party_sets_cache_filter.h" #include "net/http/http_request_info.h" @@ -74,6 +75,7 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { ConnectionAttempts GetConnectionAttempts() const override; void CloseConnectionOnDestruction() override; std::unique_ptr SetUpSourceStream() override; + cookie_util::StorageAccessStatus StorageAccessStatus() const override; RequestPriority priority() const { return priority_; @@ -172,10 +174,13 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { int ReadRawData(IOBuffer* buf, int buf_size) override; int64_t GetTotalReceivedBytes() const override; int64_t GetTotalSentBytes() const override; + int64_t GetReceivedBodyBytes() const override; void DoneReading() override; void DoneReadingRedirectResponse() override; void DoneReadingRetryResponse() override; bool NeedsRetryWithStorageAccess() override; + void SetSharedDictionaryGetter( + SharedDictionaryGetter shared_dictionary_getter) override; IPEndPoint GetResponseRemoteEndpoint() const override; void NotifyURLRequestDestroyed() override; @@ -233,6 +238,9 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { // in a request. bool ShouldRecordPartitionedCookieUsage() const; + // Applies the relevant Sec-Fetch-Storage-Access header if needed. + void MaybeSetSecFetchStorageAccessHeader(); + RequestPriority priority_ = DEFAULT_PRIORITY; HttpRequestInfo request_info_; @@ -309,6 +317,13 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { // started. FirstPartySetMetadata first_party_set_metadata_; + // The level of storage access available to this request. Note that this + // member is not set during construction; it is only set on request legs that + // include the Sec-Fetch-Storage-Access request header. (In particular, this + // excludes same-site requests and requests that cannot include cookies.) + cookie_util::StorageAccessStatus storage_access_status_ = + cookie_util::StorageAccessStatus::kNone; + base::WeakPtrFactory weak_factory_{this}; }; diff --git a/naiveproxy/src/net/url_request/url_request_job.cc b/naiveproxy/src/net/url_request/url_request_job.cc index a3d565a410..a2aa3c3361 100644 --- a/naiveproxy/src/net/url_request/url_request_job.cc +++ b/naiveproxy/src/net/url_request/url_request_job.cc @@ -26,6 +26,7 @@ #include "net/base/schemeful_site.h" #include "net/cert/x509_certificate.h" #include "net/cookies/cookie_setting_override.h" +#include "net/cookies/cookie_util.h" #include "net/log/net_log.h" #include "net/log/net_log_capture_mode.h" #include "net/log/net_log_event_type.h" @@ -140,6 +141,10 @@ int64_t URLRequestJob::GetTotalSentBytes() const { return 0; } +int64_t URLRequestJob::GetReceivedBodyBytes() const { + return 0; +} + LoadState URLRequestJob::GetLoadState() const { return LOAD_STATE_IDLE; } @@ -392,6 +397,10 @@ GURL URLRequestJob::ComputeReferrerForPolicy( return GURL(); } +cookie_util::StorageAccessStatus URLRequestJob::StorageAccessStatus() const { + return cookie_util::StorageAccessStatus::kNone; +} + int URLRequestJob::NotifyConnected(const TransportInfo& info, CompletionOnceCallback callback) { return request_->NotifyConnected(info, std::move(callback)); @@ -444,9 +453,6 @@ void URLRequestJob::NotifyHeadersComplete() { // Wait for SetAuth or CancelAuth to be called. return; } - NotifyFinalHeadersReceived(); - // |this| may be destroyed at this point. - return; } if (NeedsRetryWithStorageAccess()) { diff --git a/naiveproxy/src/net/url_request/url_request_job.h b/naiveproxy/src/net/url_request/url_request_job.h index ded7007b0d..87fdb2057a 100644 --- a/naiveproxy/src/net/url_request/url_request_job.h +++ b/naiveproxy/src/net/url_request/url_request_job.h @@ -24,6 +24,7 @@ #include "net/base/request_priority.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_setting_override.h" +#include "net/cookies/cookie_util.h" #include "net/filter/source_stream.h" #include "net/http/http_raw_request_headers.h" #include "net/http/http_response_headers.h" @@ -117,6 +118,9 @@ class NET_EXPORT URLRequestJob { // will never decrease over the lifetime of the URLRequestJob. virtual int64_t GetTotalSentBytes() const; + // Get the number of bytes of the body received from network. + virtual int64_t GetReceivedBodyBytes() const; + // Called to fetch the current load state for the job. virtual LoadState GetLoadState() const; @@ -265,6 +269,11 @@ class NET_EXPORT URLRequestJob { // Access. virtual bool NeedsRetryWithStorageAccess(); + // Set a SharedDictionaryGetter which will be used to get a shared + // dictionary for this request. + virtual void SetSharedDictionaryGetter( + SharedDictionaryGetter dictionary_getter) {} + // Given |policy|, |original_referrer|, and |destination|, returns the // referrer URL mandated by |request|'s referrer policy. // @@ -279,6 +288,8 @@ class NET_EXPORT URLRequestJob { const GURL& destination, bool* same_origin_out_for_metrics = nullptr); + virtual cookie_util::StorageAccessStatus StorageAccessStatus() const; + protected: // Notifies the job that we are connected. int NotifyConnected(const TransportInfo& info, diff --git a/naiveproxy/src/net/url_request/url_request_test_util.cc b/naiveproxy/src/net/url_request/url_request_test_util.cc index bdf7d17e1d..7e84a93306 100644 --- a/naiveproxy/src/net/url_request/url_request_test_util.cc +++ b/naiveproxy/src/net/url_request/url_request_test_util.cc @@ -18,6 +18,7 @@ #include "net/cert/cert_verifier.h" #include "net/cert/do_nothing_ct_verifier.h" #include "net/cookies/cookie_setting_override.h" +#include "net/cookies/cookie_util.h" #include "net/dns/mock_host_resolver.h" #include "net/http/http_network_session.h" #include "net/http/http_response_headers.h" @@ -556,6 +557,11 @@ int TestNetworkDelegate::GetRequestId(URLRequest* request) { return id; } +std::optional +TestNetworkDelegate::OnGetStorageAccessStatus(const URLRequest& request) const { + return storage_access_status_; +} + FilteringTestNetworkDelegate::FilteringTestNetworkDelegate() = default; FilteringTestNetworkDelegate::~FilteringTestNetworkDelegate() = default; diff --git a/naiveproxy/src/net/url_request/url_request_test_util.h b/naiveproxy/src/net/url_request/url_request_test_util.h index fd7b5f80b7..daffa66b99 100644 --- a/naiveproxy/src/net/url_request/url_request_test_util.h +++ b/naiveproxy/src/net/url_request/url_request_test_util.h @@ -32,6 +32,7 @@ #include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_setting_override.h" +#include "net/cookies/cookie_util.h" #include "net/disk_cache/disk_cache.h" #include "net/first_party_sets/first_party_set_metadata.h" #include "net/http/http_auth_handler_factory.h" @@ -288,6 +289,11 @@ class TestNetworkDelegate : public NetworkDelegateImpl { return cookie_setting_overrides_records_; } + void set_storage_access_status( + std::optional status) { + storage_access_status_ = status; + } + protected: // NetworkDelegate: int OnBeforeURLRequest(URLRequest* request, @@ -326,6 +332,8 @@ class TestNetworkDelegate : public NetworkDelegateImpl { const URLRequest& request, const GURL& target_url, const GURL& referrer_url) const override; + std::optional OnGetStorageAccessStatus( + const URLRequest& request) const override; void InitRequestStatesIfNew(int request_id); @@ -375,6 +383,9 @@ class TestNetworkDelegate : public NetworkDelegateImpl { int next_request_id_ = 0; mutable std::vector cookie_setting_overrides_records_; + + std::optional storage_access_status_ = + std::nullopt; }; // ---------------------------------------------------------------------------- diff --git a/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.cc b/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.cc index ef89603f1b..a132ef199d 100644 --- a/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.cc @@ -178,7 +178,7 @@ base::Value::Dict NetLogFailureParam(int net_error, } // namespace WebSocketBasicHandshakeStream::WebSocketBasicHandshakeStream( - std::unique_ptr connection, + std::unique_ptr connection, WebSocketStream::ConnectDelegate* connect_delegate, bool is_for_get_to_http_proxy, std::vector requested_sub_protocols, @@ -302,15 +302,9 @@ int WebSocketBasicHandshakeStream::ReadResponseBody( } void WebSocketBasicHandshakeStream::Close(bool not_reusable) { - // This class ignores the value of |not_reusable| and never lets the socket be + // This class ignores the value of `not_reusable` and never lets the socket be // re-used. - if (!parser()) - return; - StreamSocket* socket = state_.connection()->socket(); - if (socket) - socket->Disconnect(); - parser()->OnConnectionClose(); - state_.connection()->Reset(); + state_.Close(/*not_reusable=*/true); } bool WebSocketBasicHandshakeStream::IsResponseBodyComplete() const { @@ -322,12 +316,11 @@ bool WebSocketBasicHandshakeStream::IsConnectionReused() const { } void WebSocketBasicHandshakeStream::SetConnectionReused() { - state_.connection()->set_reuse_type(ClientSocketHandle::REUSED_IDLE); + state_.SetConnectionReused(); } bool WebSocketBasicHandshakeStream::CanReuseConnection() const { - return parser() && state_.connection()->socket() && - parser()->CanReuseConnection(); + return state_.CanReuseConnection(); } int64_t WebSocketBasicHandshakeStream::GetTotalReceivedBytes() const { @@ -345,22 +338,15 @@ bool WebSocketBasicHandshakeStream::GetAlternativeService( bool WebSocketBasicHandshakeStream::GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const { - return state_.connection()->GetLoadTimingInfo(IsConnectionReused(), - load_timing_info); + return state_.GetLoadTimingInfo(load_timing_info); } void WebSocketBasicHandshakeStream::GetSSLInfo(SSLInfo* ssl_info) { - if (!state_.connection()->socket() || - !state_.connection()->socket()->GetSSLInfo(ssl_info)) { - ssl_info->Reset(); - } + state_.GetSSLInfo(ssl_info); } int WebSocketBasicHandshakeStream::GetRemoteEndpoint(IPEndPoint* endpoint) { - if (!state_.connection() || !state_.connection()->socket()) - return ERR_SOCKET_NOT_CONNECTED; - - return state_.connection()->socket()->GetPeerAddress(endpoint); + return state_.GetRemoteEndpoint(endpoint); } void WebSocketBasicHandshakeStream::PopulateNetErrorDetails( @@ -383,10 +369,6 @@ std::unique_ptr WebSocketBasicHandshakeStream::RenewStreamForAuth() { DCHECK(IsResponseBodyComplete()); DCHECK(!parser()->IsMoreDataBuffered()); - // The HttpStreamParser object still has a pointer to the connection. Just to - // be extra-sure it doesn't touch the connection again, delete it here rather - // than leaving it until the destructor is called. - state_.DeleteParser(); auto handshake_stream = std::make_unique( state_.ReleaseConnection(), connect_delegate_, @@ -409,9 +391,6 @@ std::string_view WebSocketBasicHandshakeStream::GetAcceptChViaAlps() const { } std::unique_ptr WebSocketBasicHandshakeStream::Upgrade() { - // The HttpStreamParser object has a pointer to our ClientSocketHandle. Make - // sure it does not touch it again before it is destroyed. - state_.DeleteParser(); WebSocketTransportClientSocketPool::UnlockEndpoint( state_.connection(), websocket_endpoint_lock_manager_); std::unique_ptr basic_stream = diff --git a/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.h b/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.h index cf2b2ccf8e..2ac460c942 100644 --- a/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.h +++ b/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.h @@ -27,7 +27,7 @@ namespace net { -class ClientSocketHandle; +class StreamSocketHandle; class HttpNetworkSession; class HttpRequestHeaders; class HttpResponseHeaders; @@ -50,7 +50,7 @@ class NET_EXPORT_PRIVATE WebSocketBasicHandshakeStream final public: // |connect_delegate| and |failure_message| must out-live this object. WebSocketBasicHandshakeStream( - std::unique_ptr connection, + std::unique_ptr connection, WebSocketStream::ConnectDelegate* connect_delegate, bool using_proxy, std::vector requested_sub_protocols, diff --git a/naiveproxy/src/net/websockets/websocket_basic_stream.cc b/naiveproxy/src/net/websockets/websocket_basic_stream.cc index 84fceced0a..eb2d76e911 100644 --- a/naiveproxy/src/net/websockets/websocket_basic_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_basic_stream.cc @@ -19,6 +19,7 @@ #include "base/check.h" #include "base/check_op.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/logging.h" @@ -292,9 +293,10 @@ int WebSocketBasicStream::ReadEverything( DCHECK_GE(http_read_buffer_->offset(), 0); is_http_read_buffer_decoded_ = true; std::vector> frame_chunks; - if (!parser_.Decode(http_read_buffer_->StartOfBuffer(), - http_read_buffer_->offset(), &frame_chunks)) + auto data = base::as_chars(http_read_buffer_->span_before_offset()); + if (!parser_.Decode(data.data(), data.size(), &frame_chunks)) { return WebSocketErrorToNetError(parser_.websocket_error()); + } if (!frame_chunks.empty()) { int result = ConvertChunksToFrames(&frame_chunks, frames); if (result != ERR_IO_PENDING) diff --git a/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.cc b/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.cc index 5b4fa631a8..f92b7ce9c5 100644 --- a/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.cc +++ b/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.cc @@ -20,6 +20,7 @@ #include "net/base/io_buffer.h" #include "net/socket/client_socket_handle.h" #include "net/socket/stream_socket.h" +#include "net/socket/stream_socket_handle.h" #include "net/spdy/spdy_buffer.h" #include "net/third_party/quiche/src/quiche/quic/core/http/quic_header_list.h" #include "net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h" @@ -31,7 +32,7 @@ namespace net { struct NetworkTrafficAnnotationTag; WebSocketClientSocketHandleAdapter::WebSocketClientSocketHandleAdapter( - std::unique_ptr connection) + std::unique_ptr connection) : connection_(std::move(connection)) {} WebSocketClientSocketHandleAdapter::~WebSocketClientSocketHandleAdapter() = @@ -140,13 +141,13 @@ void WebSocketSpdyStreamAdapter::OnHeadersSent() { } void WebSocketSpdyStreamAdapter::OnEarlyHintsReceived( - const spdy::Http2HeaderBlock& headers) { + const quiche::HttpHeaderBlock& headers) { // This callback should not be called for a WebSocket handshake. NOTREACHED_IN_MIGRATION(); } void WebSocketSpdyStreamAdapter::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { if (delegate_) delegate_->OnHeadersReceived(response_headers); } @@ -176,7 +177,7 @@ void WebSocketSpdyStreamAdapter::OnDataSent() { } void WebSocketSpdyStreamAdapter::OnTrailers( - const spdy::Http2HeaderBlock& trailers) {} + const quiche::HttpHeaderBlock& trailers) {} void WebSocketSpdyStreamAdapter::OnClose(int status) { DCHECK_NE(ERR_IO_PENDING, status); @@ -260,7 +261,7 @@ WebSocketQuicStreamAdapter::~WebSocketQuicStreamAdapter() { } size_t WebSocketQuicStreamAdapter::WriteHeaders( - spdy::Http2HeaderBlock header_block, + quiche::HttpHeaderBlock header_block, bool fin) { return websocket_quic_spdy_stream_->WriteHeaders(std::move(header_block), fin, nullptr); @@ -310,7 +311,7 @@ void WebSocketQuicStreamAdapter::OnInitialHeadersComplete( bool fin, size_t frame_len, const quic::QuicHeaderList& quic_header_list) { - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; if (!quic::SpdyUtils::CopyAndValidateHeaders(quic_header_list, nullptr, &response_headers)) { DLOG(ERROR) << "Failed to parse header list: " diff --git a/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.h b/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.h index b7cc7562d9..84a46bc9cc 100644 --- a/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.h +++ b/naiveproxy/src/net/websockets/websocket_basic_stream_adapters.h @@ -18,7 +18,7 @@ #include "net/log/net_log_with_source.h" #include "net/spdy/spdy_read_queue.h" #include "net/spdy/spdy_stream.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/websockets/websocket_basic_stream.h" #include "net/websockets/websocket_quic_spdy_stream.h" @@ -29,7 +29,7 @@ class QuicHeaderList; namespace net { -class ClientSocketHandle; +class StreamSocketHandle; class IOBuffer; class SpdyBuffer; struct NetworkTrafficAnnotationTag; @@ -40,7 +40,7 @@ class NET_EXPORT_PRIVATE WebSocketClientSocketHandleAdapter public: WebSocketClientSocketHandleAdapter() = delete; explicit WebSocketClientSocketHandleAdapter( - std::unique_ptr connection); + std::unique_ptr connection); ~WebSocketClientSocketHandleAdapter() override; int Read(IOBuffer* buf, @@ -54,7 +54,7 @@ class NET_EXPORT_PRIVATE WebSocketClientSocketHandleAdapter bool is_initialized() const override; private: - std::unique_ptr connection_; + std::unique_ptr connection_; }; // Adapter to make WebSocketBasicStream use an HTTP/2 stream. @@ -74,7 +74,7 @@ class NET_EXPORT_PRIVATE WebSocketSpdyStreamAdapter virtual ~Delegate() = default; virtual void OnHeadersSent() = 0; virtual void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) = 0; + const quiche::HttpHeaderBlock& response_headers) = 0; // Might destroy |this|. virtual void OnClose(int status) = 0; }; @@ -107,12 +107,12 @@ class NET_EXPORT_PRIVATE WebSocketSpdyStreamAdapter // SpdyStream::Delegate methods. void OnHeadersSent() override; - void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override; + void OnEarlyHintsReceived(const quiche::HttpHeaderBlock& headers) override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnDataReceived(std::unique_ptr buffer) override; void OnDataSent() override; - void OnTrailers(const spdy::Http2HeaderBlock& trailers) override; + void OnTrailers(const quiche::HttpHeaderBlock& trailers) override; void OnClose(int status) override; bool CanGreaseFrameType() const override; NetLogSource source_dependency() const override; @@ -176,7 +176,7 @@ class NET_EXPORT_PRIVATE WebSocketQuicStreamAdapter virtual ~Delegate() = default; virtual void OnHeadersSent() = 0; virtual void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) = 0; + const quiche::HttpHeaderBlock& response_headers) = 0; virtual void OnClose(int status) = 0; }; @@ -193,7 +193,7 @@ class NET_EXPORT_PRIVATE WebSocketQuicStreamAdapter // Called by WebSocketQuicStreamAdapter::Delegate before it is destroyed. void clear_delegate() { delegate_ = nullptr; } - size_t WriteHeaders(spdy::Http2HeaderBlock header_block, bool fin); + size_t WriteHeaders(quiche::HttpHeaderBlock header_block, bool fin); // WebSocketBasicStream::Adapter methods. // TODO(momoka): Add functions that are needed to implement diff --git a/naiveproxy/src/net/websockets/websocket_channel.cc b/naiveproxy/src/net/websockets/websocket_channel.cc index a3b043166c..ddae9d9e15 100644 --- a/naiveproxy/src/net/websockets/websocket_channel.cc +++ b/naiveproxy/src/net/websockets/websocket_channel.cc @@ -38,6 +38,7 @@ #include "net/http/http_response_headers.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_with_source.h" +#include "net/storage_access_api/status.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/websockets/websocket_errors.h" #include "net/websockets/websocket_event_interface.h" @@ -285,13 +286,13 @@ void WebSocketChannel::SendAddChannelRequest( const std::vector& requested_subprotocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, NetworkTrafficAnnotationTag traffic_annotation) { SendAddChannelRequestWithSuppliedCallback( socket_url, requested_subprotocols, origin, site_for_cookies, - has_storage_access, isolation_info, additional_headers, + storage_access_api_status, isolation_info, additional_headers, traffic_annotation, base::BindOnce(&WebSocketStream::CreateAndConnectStream)); } @@ -416,14 +417,14 @@ void WebSocketChannel::SendAddChannelRequestForTesting( const std::vector& requested_subprotocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, NetworkTrafficAnnotationTag traffic_annotation, WebSocketStreamRequestCreationCallback callback) { SendAddChannelRequestWithSuppliedCallback( socket_url, requested_subprotocols, origin, site_for_cookies, - has_storage_access, isolation_info, additional_headers, + storage_access_api_status, isolation_info, additional_headers, traffic_annotation, std::move(callback)); } @@ -442,7 +443,7 @@ void WebSocketChannel::SendAddChannelRequestWithSuppliedCallback( const std::vector& requested_subprotocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, NetworkTrafficAnnotationTag traffic_annotation, @@ -459,7 +460,7 @@ void WebSocketChannel::SendAddChannelRequestWithSuppliedCallback( auto connect_delegate = std::make_unique(this); stream_request_ = std::move(callback).Run( socket_url_, requested_subprotocols, origin, site_for_cookies, - has_storage_access, isolation_info, additional_headers, + storage_access_api_status, isolation_info, additional_headers, url_request_context_.get(), NetLogWithSource(), traffic_annotation, std::move(connect_delegate)); SetState(CONNECTING); diff --git a/naiveproxy/src/net/websockets/websocket_channel.h b/naiveproxy/src/net/websockets/websocket_channel.h index 9553cf3198..28d12edae5 100644 --- a/naiveproxy/src/net/websockets/websocket_channel.h +++ b/naiveproxy/src/net/websockets/websocket_channel.h @@ -22,6 +22,7 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "net/base/net_export.h" +#include "net/storage_access_api/status.h" #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_frame.h" #include "net/websockets/websocket_stream.h" @@ -63,7 +64,7 @@ class NET_EXPORT WebSocketChannel { const std::vector&, const url::Origin&, const SiteForCookies&, - bool, + StorageAccessApiStatus, const IsolationInfo&, const HttpRequestHeaders&, URLRequestContext*, @@ -94,7 +95,7 @@ class NET_EXPORT WebSocketChannel { const std::vector& requested_protocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, NetworkTrafficAnnotationTag traffic_annotation); @@ -139,7 +140,7 @@ class NET_EXPORT WebSocketChannel { const std::vector& requested_protocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, NetworkTrafficAnnotationTag traffic_annotation, @@ -193,7 +194,7 @@ class NET_EXPORT WebSocketChannel { const std::vector& requested_protocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, NetworkTrafficAnnotationTag traffic_annotation, diff --git a/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.cc b/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.cc index 4f7acfc7ce..cc324b7e01 100644 --- a/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.cc @@ -26,7 +26,6 @@ #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_stream.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/websockets/websocket_basic_stream.h" #include "net/websockets/websocket_deflate_predictor_impl.h" @@ -277,7 +276,7 @@ void WebSocketHttp2HandshakeStream::OnHeadersSent() { } void WebSocketHttp2HandshakeStream::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { DCHECK(!response_headers_complete_); DCHECK(http_response_info_); diff --git a/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.h b/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.h index 4d38787088..98978ead44 100644 --- a/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.h +++ b/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.h @@ -22,7 +22,7 @@ #include "net/base/net_export.h" #include "net/base/request_priority.h" #include "net/log/net_log_with_source.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/websockets/websocket_basic_stream_adapters.h" #include "net/websockets/websocket_handshake_stream_base.h" #include "net/websockets/websocket_stream.h" @@ -112,7 +112,7 @@ class NET_EXPORT_PRIVATE WebSocketHttp2HandshakeStream // WebSocketSpdyStreamAdapter::Delegate methods. void OnHeadersSent() override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnClose(int status) override; // Called by |spdy_stream_request_| when requested stream is ready. @@ -141,7 +141,7 @@ class NET_EXPORT_PRIVATE WebSocketHttp2HandshakeStream raw_ptr http_response_info_ = nullptr; - spdy::Http2HeaderBlock http2_request_headers_; + quiche::HttpHeaderBlock http2_request_headers_; // The sub-protocols we requested. std::vector requested_sub_protocols_; diff --git a/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.cc b/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.cc index 595ed4d8cd..1d8db45d3f 100644 --- a/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.cc @@ -22,7 +22,6 @@ #include "net/http/http_response_info.h" #include "net/http/http_status_code.h" #include "net/spdy/spdy_http_utils.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/websockets/websocket_basic_stream.h" #include "net/websockets/websocket_deflate_predictor_impl.h" @@ -276,7 +275,7 @@ void WebSocketHttp3HandshakeStream::OnHeadersSent() { } void WebSocketHttp3HandshakeStream::OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) { + const quiche::HttpHeaderBlock& response_headers) { DCHECK(!response_headers_complete_); DCHECK(http_response_info_); diff --git a/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.h b/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.h index 9c15861ac7..d401055fd2 100644 --- a/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.h +++ b/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.h @@ -24,7 +24,7 @@ #include "net/log/net_log_with_source.h" #include "net/quic/quic_chromium_client_session.h" #include "net/quic/quic_session_pool.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/websockets/websocket_basic_stream_adapters.h" #include "net/websockets/websocket_handshake_stream_base.h" #include "net/websockets/websocket_stream.h" @@ -109,7 +109,7 @@ class NET_EXPORT_PRIVATE WebSocketHttp3HandshakeStream final // WebSocketQuicStreamAdapter::Delegate methods. void OnHeadersSent() override; void OnHeadersReceived( - const spdy::Http2HeaderBlock& response_headers) override; + const quiche::HttpHeaderBlock& response_headers) override; void OnClose(int status) override; private: @@ -151,7 +151,7 @@ class NET_EXPORT_PRIVATE WebSocketHttp3HandshakeStream final raw_ptr http_response_info_ = nullptr; - spdy::Http2HeaderBlock http3_request_headers_; + quiche::HttpHeaderBlock http3_request_headers_; // The sub-protocols we requested. std::vector requested_sub_protocols_; diff --git a/naiveproxy/src/net/websockets/websocket_stream.cc b/naiveproxy/src/net/websockets/websocket_stream.cc index e8c92c9ba8..dafcaf40c8 100644 --- a/naiveproxy/src/net/websockets/websocket_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_stream.cc @@ -30,6 +30,7 @@ #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/http/http_status_code.h" +#include "net/storage_access_api/status.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/redirect_info.h" #include "net/url_request/url_request.h" @@ -105,7 +106,7 @@ class WebSocketStreamRequestImpl : public WebSocketStreamRequestAPI { const URLRequestContext* context, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, NetworkTrafficAnnotationTag traffic_annotation, @@ -138,7 +139,7 @@ class WebSocketStreamRequestImpl : public WebSocketStreamRequestAPI { url_request_->SetExtraRequestHeaders(headers); url_request_->set_initiator(origin); url_request_->set_site_for_cookies(site_for_cookies); - url_request_->set_has_storage_access(has_storage_access); + url_request_->set_storage_access_api_status(storage_access_api_status); url_request_->set_isolation_info(isolation_info); auto create_helper = std::make_unique( @@ -516,7 +517,7 @@ std::unique_ptr WebSocketStream::CreateAndConnectStream( const std::vector& requested_subprotocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, URLRequestContext* url_request_context, @@ -525,8 +526,9 @@ std::unique_ptr WebSocketStream::CreateAndConnectStream( std::unique_ptr connect_delegate) { auto request = std::make_unique( socket_url, requested_subprotocols, url_request_context, origin, - site_for_cookies, has_storage_access, isolation_info, additional_headers, - traffic_annotation, std::move(connect_delegate), nullptr); + site_for_cookies, storage_access_api_status, isolation_info, + additional_headers, traffic_annotation, std::move(connect_delegate), + nullptr); request->Start(std::make_unique()); return std::move(request); } @@ -537,7 +539,7 @@ WebSocketStream::CreateAndConnectStreamForTesting( const std::vector& requested_subprotocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, URLRequestContext* url_request_context, @@ -548,8 +550,9 @@ WebSocketStream::CreateAndConnectStreamForTesting( std::unique_ptr api_delegate) { auto request = std::make_unique( socket_url, requested_subprotocols, url_request_context, origin, - site_for_cookies, has_storage_access, isolation_info, additional_headers, - traffic_annotation, std::move(connect_delegate), std::move(api_delegate)); + site_for_cookies, storage_access_api_status, isolation_info, + additional_headers, traffic_annotation, std::move(connect_delegate), + std::move(api_delegate)); request->Start(std::move(timer)); return std::move(request); } diff --git a/naiveproxy/src/net/websockets/websocket_stream.h b/naiveproxy/src/net/websockets/websocket_stream.h index dc947ec155..433bbfc199 100644 --- a/naiveproxy/src/net/websockets/websocket_stream.h +++ b/naiveproxy/src/net/websockets/websocket_stream.h @@ -18,6 +18,7 @@ #include "net/base/net_export.h" #include "net/cookies/site_for_cookies.h" #include "net/log/net_log_with_source.h" +#include "net/storage_access_api/status.h" #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_handshake_request_info.h" #include "net/websockets/websocket_handshake_response_info.h" @@ -168,7 +169,7 @@ class NET_EXPORT_PRIVATE WebSocketStream { const std::vector& requested_subprotocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, URLRequestContext* url_request_context, @@ -186,7 +187,7 @@ class NET_EXPORT_PRIVATE WebSocketStream { const std::vector& requested_subprotocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, URLRequestContext* url_request_context, diff --git a/naiveproxy/src/net/websockets/websocket_stream_create_test_base.cc b/naiveproxy/src/net/websockets/websocket_stream_create_test_base.cc index 2df814be6a..73ef4d96ff 100644 --- a/naiveproxy/src/net/websockets/websocket_stream_create_test_base.cc +++ b/naiveproxy/src/net/websockets/websocket_stream_create_test_base.cc @@ -111,7 +111,7 @@ void WebSocketStreamCreateTestBase::CreateAndConnectStream( const std::vector& sub_protocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, std::unique_ptr timer) { @@ -119,8 +119,8 @@ void WebSocketStreamCreateTestBase::CreateAndConnectStream( this, connect_run_loop_.QuitClosure()); auto api_delegate = std::make_unique(); stream_request_ = WebSocketStream::CreateAndConnectStreamForTesting( - socket_url, sub_protocols, origin, site_for_cookies, has_storage_access, - isolation_info, additional_headers, + socket_url, sub_protocols, origin, site_for_cookies, + storage_access_api_status, isolation_info, additional_headers, url_request_context_host_.GetURLRequestContext(), NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS, std::move(connect_delegate), timer ? std::move(timer) : std::make_unique(), diff --git a/naiveproxy/src/net/websockets/websocket_stream_create_test_base.h b/naiveproxy/src/net/websockets/websocket_stream_create_test_base.h index b0cce087ea..619b50d961 100644 --- a/naiveproxy/src/net/websockets/websocket_stream_create_test_base.h +++ b/naiveproxy/src/net/websockets/websocket_stream_create_test_base.h @@ -19,6 +19,7 @@ #include "net/base/net_errors.h" #include "net/socket/socket_test_util.h" #include "net/ssl/ssl_info.h" +#include "net/storage_access_api/status.h" #include "net/test/test_with_task_environment.h" #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_test_util.h" @@ -63,7 +64,7 @@ class WebSocketStreamCreateTestBase : public WithTaskEnvironment { const std::vector& sub_protocols, const url::Origin& origin, const SiteForCookies& site_for_cookies, - bool has_storage_access, + StorageAccessApiStatus storage_access_api_status, const IsolationInfo& isolation_info, const HttpRequestHeaders& additional_headers, std::unique_ptr timer); diff --git a/naiveproxy/src/net/websockets/websocket_test_util.cc b/naiveproxy/src/net/websockets/websocket_test_util.cc index a69526e30f..b9a9ba4794 100644 --- a/naiveproxy/src/net/websockets/websocket_test_util.cc +++ b/naiveproxy/src/net/websockets/websocket_test_util.cc @@ -25,7 +25,6 @@ #include "net/proxy_resolution/configured_proxy_resolution_service.h" #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/socket/socket_test_util.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request_context.h" @@ -149,12 +148,12 @@ HttpRequestHeaders WebSocketCommonTestHeaders() { return request_headers; } -spdy::Http2HeaderBlock WebSocketHttp2Request( +quiche::HttpHeaderBlock WebSocketHttp2Request( const std::string& path, const std::string& authority, const std::string& origin, const WebSocketExtraHeaders& extra_headers) { - spdy::Http2HeaderBlock request_headers; + quiche::HttpHeaderBlock request_headers; request_headers[spdy::kHttp2MethodHeader] = "CONNECT"; request_headers[spdy::kHttp2AuthorityHeader] = authority; request_headers[spdy::kHttp2SchemeHeader] = "https"; @@ -175,9 +174,9 @@ spdy::Http2HeaderBlock WebSocketHttp2Request( return request_headers; } -spdy::Http2HeaderBlock WebSocketHttp2Response( +quiche::HttpHeaderBlock WebSocketHttp2Response( const WebSocketExtraHeaders& extra_headers) { - spdy::Http2HeaderBlock response_headers; + quiche::HttpHeaderBlock response_headers; response_headers[spdy::kHttp2StatusHeader] = "200"; for (const auto& header : extra_headers) { response_headers[base::ToLowerASCII(header.first)] = header.second; diff --git a/naiveproxy/src/net/websockets/websocket_test_util.h b/naiveproxy/src/net/websockets/websocket_test_util.h index e213e69919..f865edaf3d 100644 --- a/naiveproxy/src/net/websockets/websocket_test_util.h +++ b/naiveproxy/src/net/websockets/websocket_test_util.h @@ -19,7 +19,7 @@ #include "net/http/http_request_headers.h" #include "net/http/http_stream_parser.h" #include "net/socket/client_socket_handle.h" -#include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" +#include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_test_util.h" @@ -97,7 +97,7 @@ std::string WebSocketStandardResponse(const std::string& extra_headers); HttpRequestHeaders WebSocketCommonTestHeaders(); // Generates a handshake request header block when using WebSockets over HTTP/2. -spdy::Http2HeaderBlock WebSocketHttp2Request( +quiche::HttpHeaderBlock WebSocketHttp2Request( const std::string& path, const std::string& authority, const std::string& origin, @@ -105,7 +105,7 @@ spdy::Http2HeaderBlock WebSocketHttp2Request( // Generates a handshake response header block when using WebSockets over // HTTP/2. -spdy::Http2HeaderBlock WebSocketHttp2Response( +quiche::HttpHeaderBlock WebSocketHttp2Response( const WebSocketExtraHeaders& extra_headers); // This class provides a convenient way to construct a MockClientSocketFactory diff --git a/naiveproxy/src/third_party/abseil-cpp/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/BUILD.gn index 6c4721a79f..f80da50d2c 100644 --- a/naiveproxy/src/third_party/abseil-cpp/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/BUILD.gn @@ -269,6 +269,7 @@ if (absl_build_tests) { "absl/base:config_test", "absl/base:no_destructor_test", "absl/base:nullability_test", + "absl/base:poison_test", "absl/base:prefetch_test", "absl/cleanup:cleanup_test", @@ -280,6 +281,8 @@ if (absl_build_tests) { "absl/container:flat_hash_set_test", "absl/container:hash_function_defaults_test", "absl/container:inlined_vector_test", + "absl/container:node_hash_map_test", + "absl/container:node_hash_set_test", "absl/container:node_slot_policy_test", "absl/container:raw_hash_set_allocator_test", "absl/container:raw_hash_set_test", @@ -288,8 +291,11 @@ if (absl_build_tests) { "absl/crc:crc_cord_state_test", "absl/crc:crc_memcpy_test", "absl/crc:non_temporal_memcpy_test", + "absl/debugging:bounded_utf8_length_sequence_test", + "absl/debugging:decode_rust_punycode_test", "absl/debugging:demangle_rust_test", "absl/debugging:stacktrace_test", + "absl/debugging:utf8_for_code_point_test", "absl/flags:flag_test", "absl/functional:any_invocable_test", "absl/functional:function_ref_test", diff --git a/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilDll.cmake b/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilDll.cmake index 1de9b2c73d..d7fd29f58b 100644 --- a/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilDll.cmake +++ b/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilDll.cmake @@ -27,6 +27,8 @@ set(ABSL_INTERNAL_DLL_FILES "base/internal/low_level_scheduling.h" "base/internal/nullability_impl.h" "base/internal/per_thread_tls.h" + "base/internal/poison.cc" + "base/internal/poison.h" "base/prefetch.h" "base/internal/pretty_function.h" "base/internal/raw_logging.cc" @@ -121,6 +123,9 @@ set(ABSL_INTERNAL_DLL_FILES "debugging/symbolize.h" "debugging/internal/address_is_readable.cc" "debugging/internal/address_is_readable.h" + "debugging/internal/bounded_utf8_length_sequence.h" + "debugging/internal/decode_rust_punycode.cc" + "debugging/internal/decode_rust_punycode.h" "debugging/internal/demangle.cc" "debugging/internal/demangle.h" "debugging/internal/demangle_rust.cc" @@ -133,6 +138,8 @@ set(ABSL_INTERNAL_DLL_FILES "debugging/internal/stack_consumption.h" "debugging/internal/stacktrace_config.h" "debugging/internal/symbolize.h" + "debugging/internal/utf8_for_code_point.cc" + "debugging/internal/utf8_for_code_point.h" "debugging/internal/vdso_support.cc" "debugging/internal/vdso_support.h" "functional/any_invocable.h" diff --git a/naiveproxy/src/third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in b/naiveproxy/src/third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in index 75691b1117..3db48341a2 100644 --- a/naiveproxy/src/third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in +++ b/naiveproxy/src/third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(googletest-external NONE) diff --git a/naiveproxy/src/third_party/abseil-cpp/CMake/README.md b/naiveproxy/src/third_party/abseil-cpp/CMake/README.md index c7ddee6440..808edfe855 100644 --- a/naiveproxy/src/third_party/abseil-cpp/CMake/README.md +++ b/naiveproxy/src/third_party/abseil-cpp/CMake/README.md @@ -39,7 +39,7 @@ section of your executable or of your library.
Here is a short CMakeLists.txt example of an application project using Abseil. ```cmake -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(my_app_project) # Pick the C++ standard to compile with. @@ -62,7 +62,7 @@ will control Abseil library targets) is set to at least that minimum. For example: ```cmake -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(my_lib_project) # Leave C++ standard up to the root application, so set it only if this is the diff --git a/naiveproxy/src/third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt index 30c23b2c6b..3229887c8d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt @@ -15,7 +15,7 @@ # A simple CMakeLists.txt for testing cmake installation -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(absl_cmake_testing CXX) add_executable(simple simple.cc) diff --git a/naiveproxy/src/third_party/abseil-cpp/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/CMakeLists.txt index d88283b234..9d3e4f337b 100644 --- a/naiveproxy/src/third_party/abseil-cpp/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/CMakeLists.txt @@ -15,43 +15,8 @@ # # https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md -# As of 2022-09-06, CMake 3.10 is the minimum supported version. -cmake_minimum_required(VERSION 3.10) - -# Compiler id for Apple Clang is now AppleClang. -if (POLICY CMP0025) - cmake_policy(SET CMP0025 NEW) -endif (POLICY CMP0025) - -# if command can use IN_LIST -if (POLICY CMP0057) - cmake_policy(SET CMP0057 NEW) -endif (POLICY CMP0057) - -# Project version variables are the empty string if version is unspecified -if (POLICY CMP0048) - cmake_policy(SET CMP0048 NEW) -endif (POLICY CMP0048) - -# Honor the GTest_ROOT variable if specified -if (POLICY CMP0074) - cmake_policy(SET CMP0074 NEW) -endif (POLICY CMP0074) - -# option() honor variables -if (POLICY CMP0077) - cmake_policy(SET CMP0077 NEW) -endif (POLICY CMP0077) - -# Allow the user to specify the MSVC runtime -if (POLICY CMP0091) - cmake_policy(SET CMP0091 NEW) -endif (POLICY CMP0091) - -# try_compile() honors the CMAKE_CXX_STANDARD value -if (POLICY CMP0067) - cmake_policy(SET CMP0067 NEW) -endif (POLICY CMP0067) +# As of 2024-07-01, CMake 3.16 is the minimum supported version. +cmake_minimum_required(VERSION 3.16) # Allow the user to specify the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT if (POLICY CMP0141) @@ -76,6 +41,10 @@ else() option(ABSL_ENABLE_INSTALL "Enable install rule" ON) endif() +set(CMAKE_INSTALL_RPATH "$ORIGIN") +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) +set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) + option(ABSL_PROPAGATE_CXX_STD "Use CMake C++ standard meta features (e.g. cxx_std_14) that propagate to targets that link to Abseil" OFF) # TODO: Default to ON for CMake 3.8 and greater. @@ -92,6 +61,15 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/absl/copts ) +option(ABSL_MSVC_STATIC_RUNTIME + "Link static runtime libraries" + OFF) +if(ABSL_MSVC_STATIC_RUNTIME) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") +endif() + include(CMakePackageConfigHelpers) include(GNUInstallDirs) include(AbseilDll) @@ -280,7 +258,7 @@ if(ABSL_ENABLE_INSTALL) ABSL_INTERNAL_OPTIONS_H_PINNED "${ABSL_INTERNAL_OPTIONS_H_CONTENTS}") - file(WRITE "${CMAKE_BINARY_DIR}/options-pinned.h" "${ABSL_INTERNAL_OPTIONS_H_PINNED}") + file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/options-pinned.h" CONTENT "${ABSL_INTERNAL_OPTIONS_H_PINNED}") install(FILES "${CMAKE_BINARY_DIR}/options-pinned.h" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/absl/base diff --git a/naiveproxy/src/third_party/abseil-cpp/README.chromium b/naiveproxy/src/third_party/abseil-cpp/README.chromium index e192eb1e4e..9d38ca7de7 100644 --- a/naiveproxy/src/third_party/abseil-cpp/README.chromium +++ b/naiveproxy/src/third_party/abseil-cpp/README.chromium @@ -4,7 +4,7 @@ URL: https://github.com/abseil/abseil-cpp License: Apache 2.0 License File: LICENSE Version: N/A -Revision: 29bd16cb925bd762ac7ca90e26ad044200ae0711 +Revision: eb852207758a773965301d0ae717e4235fc5301a Security Critical: yes Shipped: yes diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.bazel index ddf9e11f42..f20e7290d6 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.bazel @@ -65,6 +65,7 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":algorithm", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:nullability", "//absl/meta:type_traits", @@ -79,6 +80,7 @@ cc_test( deps = [ ":container", "//absl/base", + "//absl/base:config", "//absl/base:core_headers", "//absl/memory", "//absl/types:span", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.gn index ae662dc84d..195eab23cc 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/BUILD.gn @@ -13,8 +13,9 @@ absl_source_set("container") { public = [ "container.h" ] deps = [ ":algorithm", - "//third_party/abseil-cpp/absl/base:nullability", + "//third_party/abseil-cpp/absl/base:config", "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/base:nullability", "//third_party/abseil-cpp/absl/meta:type_traits", ] } @@ -32,6 +33,7 @@ absl_test("container_test") { deps = [ ":container", "//third_party/abseil-cpp/absl/base", + "//third_party/abseil-cpp/absl/base:config", "//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/types:span", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/CMakeLists.txt index 5577164dcb..252b6b2035 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/CMakeLists.txt @@ -48,6 +48,7 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} DEPS absl::algorithm + absl::config absl::core_headers absl::meta absl::nullability @@ -64,6 +65,7 @@ absl_cc_test( DEPS absl::algorithm_container absl::base + absl::config absl::core_headers absl::memory absl::span diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/container.h b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/container.h index a2d126b728..6bbe3b5adf 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/container.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/algorithm/container.h @@ -52,6 +52,7 @@ #include #include "absl/algorithm/algorithm.h" +#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/base/nullability.h" #include "absl/meta/type_traits.h" @@ -93,17 +94,17 @@ using ContainerPointerType = // using std::end; // std::foo(begin(c), end(c)); // becomes -// std::foo(container_algorithm_internal::begin(c), -// container_algorithm_internal::end(c)); +// std::foo(container_algorithm_internal::c_begin(c), +// container_algorithm_internal::c_end(c)); // These are meant for internal use only. template -ContainerIter c_begin(C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { return begin(c); } template -ContainerIter c_end(C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { return end(c); } @@ -146,8 +147,9 @@ bool c_linear_search(const C& c, EqualityComparable&& value) { // Container-based version of the `std::distance()` function to // return the number of elements within a container. template -container_algorithm_internal::ContainerDifferenceType c_distance( - const C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerDifferenceType + c_distance(const C& c) { return std::distance(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } @@ -211,6 +213,16 @@ container_algorithm_internal::ContainerIter c_find(C& c, T&& value) { std::forward(value)); } +// c_contains() +// +// Container-based version of the `std::ranges::contains()` C++23 +// function to search a container for a value. +template +bool c_contains(const Sequence& sequence, T&& value) { + return absl::c_find(sequence, std::forward(value)) != + container_algorithm_internal::c_end(sequence); +} + // c_find_if() // // Container-based version of the `std::find_if()` function to find @@ -427,6 +439,26 @@ container_algorithm_internal::ContainerIter c_search( std::forward(pred)); } +// c_contains_subrange() +// +// Container-based version of the `std::ranges::contains_subrange()` +// C++23 function to search a container for a subsequence. +template +bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence) { + return absl::c_search(sequence, subsequence) != + container_algorithm_internal::c_end(sequence); +} + +// Overload of c_contains_subrange() for using a predicate evaluation other than +// `==` as the function's test condition. +template +bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { + return absl::c_search(sequence, subsequence, + std::forward(pred)) != + container_algorithm_internal::c_end(sequence); +} + // c_search_n() // // Container-based version of the `std::search_n()` function to @@ -1501,8 +1533,9 @@ c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) { // to return an iterator pointing to the element with the smallest value, using // `operator<` to make the comparisons. template -container_algorithm_internal::ContainerIter c_min_element( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence) { return std::min_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } @@ -1510,8 +1543,9 @@ container_algorithm_internal::ContainerIter c_min_element( // Overload of c_min_element() for performing a `comp` comparison other than // `operator<`. template -container_algorithm_internal::ContainerIter c_min_element( - Sequence& sequence, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence, LessThan&& comp) { return std::min_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); @@ -1523,8 +1557,9 @@ container_algorithm_internal::ContainerIter c_min_element( // to return an iterator pointing to the element with the largest value, using // `operator<` to make the comparisons. template -container_algorithm_internal::ContainerIter c_max_element( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence) { return std::max_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } @@ -1532,8 +1567,9 @@ container_algorithm_internal::ContainerIter c_max_element( // Overload of c_max_element() for performing a `comp` comparison other than // `operator<`. template -container_algorithm_internal::ContainerIter c_max_element( - Sequence& sequence, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence, LessThan&& comp) { return std::max_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(comp)); @@ -1546,8 +1582,9 @@ container_algorithm_internal::ContainerIter c_max_element( // smallest and largest values, respectively, using `operator<` to make the // comparisons. template -container_algorithm_internal::ContainerIterPairType c_minmax_element( - C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c) { return std::minmax_element(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } @@ -1555,8 +1592,9 @@ container_algorithm_internal::ContainerIterPairType c_minmax_element( // Overload of c_minmax_element() for performing `comp` comparisons other than // `operator<`. template -container_algorithm_internal::ContainerIterPairType c_minmax_element( - C& c, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c, LessThan&& comp) { return std::minmax_element(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(comp)); diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel index ea72210df7..995ca53091 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel @@ -87,6 +87,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + ":config", ":core_headers", "//absl/meta:type_traits", ], @@ -336,6 +337,18 @@ cc_test( ], ) +cc_test( + name = "c_header_test", + srcs = ["c_header_test.c"], + tags = [ + "no_test_wasm", + ], + deps = [ + ":config", + ":core_headers", + ], +) + cc_library( name = "throw_delegate", srcs = ["internal/throw_delegate.cc"], @@ -850,6 +863,41 @@ cc_test( ], ) +cc_library( + name = "poison", + srcs = [ + "internal/poison.cc", + ], + hdrs = ["internal/poison.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + ":core_headers", + ":malloc_internal", + ], +) + +cc_test( + name = "poison_test", + size = "small", + timeout = "short", + srcs = [ + "internal/poison_test.cc", + ], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":poison", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "unique_small_name_test", size = "small", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.gn index 5da9dde2d7..9c7d359af4 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.gn @@ -40,6 +40,7 @@ absl_source_set("nullability") { sources = [ "internal/nullability_impl.h" ] public = [ "nullability.h" ] deps = [ + ":config", ":core_headers", "//third_party/abseil-cpp/absl/meta:type_traits", ] @@ -189,6 +190,16 @@ absl_source_set("base") { ] } +# This should be an executable() more than a test. +# It cannot be enabled because it defines its own main() function. +# absl_test("c_header_test") { +# sources = ["c_header_test.c"] +# deps = [ +# ":config", +# ":core_headers", +# ] +# } + absl_source_set("throw_delegate") { sources = [ "internal/throw_delegate.cc" ] public = [ "internal/throw_delegate.h" ] @@ -303,6 +314,24 @@ absl_test("prefetch_test") { deps = [ ":prefetch" ] } +absl_source_set("poison") { + public = [ "internal/poison.h" ] + sources = [ "internal/poison.cc" ] + deps = [ + ":config", + ":core_headers", + ":malloc_internal", + ] +} + +absl_test("poison_test") { + sources = [ "internal/poison_test.cc" ] + deps = [ + ":config", + ":poison", + ] +} + absl_test("config_test") { sources = [ "config_test.cc" ] deps = [ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/base/CMakeLists.txt index 30fb93cb3f..fa27ae8d90 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/CMakeLists.txt @@ -75,6 +75,7 @@ absl_cc_library( SRCS "internal/nullability_impl.h" DEPS + absl::config absl::core_headers absl::type_traits COPTS @@ -736,3 +737,33 @@ absl_cc_test( absl::optional GTest::gtest_main ) + +absl_cc_library( + NAME + poison + SRCS + "internal/poison.cc" + HDRS + "internal/poison.h" + COPTS + ${ABSL_DEFAULT_COPTS} + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config + absl::core_headers + absl::malloc_internal +) + +absl_cc_test( + NAME + poison_test + SRCS + "internal/poison_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::config + absl::poison + GTest::gtest_main +) diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/attributes.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/attributes.h index e781995edb..5ea5ee3ef8 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/attributes.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/attributes.h @@ -195,6 +195,9 @@ // ABSL_ATTRIBUTE_NORETURN // // Tells the compiler that a given function never returns. +// +// Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over +// this macro. #if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) #define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) #elif defined(_MSC_VER) @@ -813,8 +816,11 @@ // // See also the upstream documentation: // https://clang.llvm.org/docs/AttributeReference.html#lifetimebound +// https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) #define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]] #elif ABSL_HAVE_ATTRIBUTE(lifetimebound) #define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) #else diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/c_header_test.c b/naiveproxy/src/third_party/abseil-cpp/absl/base/c_header_test.c new file mode 100644 index 0000000000..3cd0177848 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/c_header_test.c @@ -0,0 +1,30 @@ +// Copyright 2024 The Abseil Authors +// +// 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 +// +// https://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. + +#ifdef __cplusplus +#error This is a C compile test +#endif + +// This test ensures that headers that are included in legacy C code are +// compatible with C. Abseil is a C++ library. We do not desire to expand C +// compatibility or keep C compatibility forever. This test only exists to +// ensure C compatibility until it is no longer required. Do not add new code +// that requires C compatibility. +#include "absl/base/attributes.h" // IWYU pragma: keep +#include "absl/base/config.h" // IWYU pragma: keep +#include "absl/base/optimization.h" // IWYU pragma: keep +#include "absl/base/policy_checks.h" // IWYU pragma: keep +#include "absl/base/port.h" // IWYU pragma: keep + +int main() { return 0; } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/config.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/config.h index a8f2eab5ee..97c9a22a10 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/config.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/config.h @@ -941,6 +941,27 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || #define ABSL_HAVE_CONSTANT_EVALUATED 1 #endif +// ABSL_INTERNAL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr +// for different C++ versions. +// +// These macros are an implementation detail and will be unconditionally removed +// once the minimum supported C++ version catches up to a given version. +// +// For this reason, this symbol is considered INTERNAL and code outside of +// Abseil must not use it. +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L +#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 constexpr +#else +#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 +#endif +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 constexpr +#else +#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 +#endif + // ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros // into an integer that can be compared against. #ifdef ABSL_INTERNAL_EMSCRIPTEN_VERSION diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/nullability_impl.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/nullability_impl.h index 36e1b33d65..03fa2434ce 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/nullability_impl.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/nullability_impl.h @@ -19,10 +19,11 @@ #include #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/meta/type_traits.h" namespace absl { - +ABSL_NAMESPACE_BEGIN namespace nullability_internal { // `IsNullabilityCompatible` checks whether its first argument is a class @@ -101,6 +102,7 @@ using NullabilityUnknownImpl = T; } // namespace nullability_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/poison.cc b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/poison.cc new file mode 100644 index 0000000000..b33d4c2d3d --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/poison.cc @@ -0,0 +1,84 @@ +// Copyright 2024 The Abseil Authors +// +// 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 +// +// https://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. + +#include "absl/base/internal/poison.h" + +#include + +#include "absl/base/config.h" +#include "absl/base/internal/direct_mmap.h" + +#ifndef _WIN32 +#include +#endif + +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) +#include +#elif defined(ABSL_HAVE_MEMORY_SANITIZER) +#include +#elif defined(ABSL_HAVE_MMAP) +#include +#endif + +#if defined(_WIN32) +#include +#endif + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace base_internal { + +namespace { + +size_t GetPageSize() { +#ifdef _WIN32 + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + return system_info.dwPageSize; +#elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__) + return getpagesize(); +#else + return static_cast(sysconf(_SC_PAGESIZE)); +#endif +} + +} // namespace + +void* InitializePoisonedPointerInternal() { + const size_t block_size = GetPageSize(); +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) + void* data = malloc(block_size); + ASAN_POISON_MEMORY_REGION(data, block_size); +#elif defined(ABSL_HAVE_MEMORY_SANITIZER) + void* data = malloc(block_size); + __msan_poison(data, block_size); +#elif defined(ABSL_HAVE_MMAP) + void* data = DirectMmap(nullptr, block_size, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (data == MAP_FAILED) return GetBadPointerInternal(); +#elif defined(_WIN32) + void* data = VirtualAlloc(nullptr, block_size, MEM_RESERVE | MEM_COMMIT, + PAGE_NOACCESS); + if (data == nullptr) return GetBadPointerInternal(); +#else + return GetBadPointerInternal(); +#endif + // Return the middle of the block so that dereferences before and after the + // pointer will both crash. + return static_cast(data) + block_size / 2; +} + +} // namespace base_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/poison.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/poison.h new file mode 100644 index 0000000000..28113bdd71 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/internal/poison.h @@ -0,0 +1,59 @@ +// Copyright 2024 The Abseil Authors +// +// 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 +// +// https://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. + +#ifndef ABSL_BASE_INTERNAL_POISON_H_ +#define ABSL_BASE_INTERNAL_POISON_H_ + +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace base_internal { + +inline void* GetBadPointerInternal() { + // A likely bad pointer. Pointers are required to have high bits that are all + // zero or all one for certain 64-bit CPUs. This pointer value will hopefully + // cause a crash on dereference and also be clearly recognizable as invalid. + constexpr uint64_t kBadPtr = 0xBAD0BAD0BAD0BAD0; + auto ret = reinterpret_cast(static_cast(kBadPtr)); +#ifndef _MSC_VER // MSVC doesn't support inline asm with `volatile`. + // Try to prevent the compiler from optimizing out the undefined behavior. + asm volatile("" : : "r"(ret) :); // NOLINT +#endif + return ret; +} + +void* InitializePoisonedPointerInternal(); + +inline void* get_poisoned_pointer() { +#if defined(NDEBUG) && !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ + !defined(ABSL_HAVE_MEMORY_SANITIZER) + // In optimized non-sanitized builds, avoid the function-local static because + // of the codegen and runtime cost. + return GetBadPointerInternal(); +#else + // Non-optimized builds may use more robust implementation. Note that we can't + // use a static global because Chromium doesn't allow non-constinit globals. + static void* ptr = InitializePoisonedPointerInternal(); + return ptr; +#endif +} + +} // namespace base_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_BASE_INTERNAL_POISON_H_ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/no_destructor.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/no_destructor.h index 7b46456c69..43b3540aeb 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/no_destructor.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/no_destructor.h @@ -21,14 +21,13 @@ // such an object survives during program exit (and can be safely accessed at // any time). // -// Objects of such type, if constructed safely and under the right conditions, -// provide two main benefits over other alternatives: -// -// * Global objects not normally allowed due to concerns of destruction order -// (i.e. no "complex globals") can be safely allowed, provided that such -// objects can be constant initialized. -// * Function scope static objects can be optimized to avoid heap allocation, -// pointer chasing, and allow lazy construction. +// absl::NoDestructor is useful when when a variable has static storage +// duration but its type has a non-trivial destructor. Global constructors are +// not recommended because of the C++'s static initialization order fiasco (See +// https://en.cppreference.com/w/cpp/language/siof). Global destructors are not +// allowed due to similar concerns about destruction ordering. Using +// absl::NoDestructor as a function-local static prevents both of these +// issues. // // See below for complete details. @@ -50,8 +49,8 @@ ABSL_NAMESPACE_BEGIN // // NoDestructor is a wrapper around an object of type T that behaves as an // object of type T but never calls T's destructor. NoDestructor makes it -// safer and/or more efficient to use such objects in static storage contexts: -// as global or function scope static variables. +// safer and/or more efficient to use such objects in static storage contexts, +// ideally as function scope static variables. // // An instance of absl::NoDestructor has similar type semantics to an // instance of T: @@ -62,9 +61,6 @@ ABSL_NAMESPACE_BEGIN // `->`, `*`, and `get()`. // (Note that `const NoDestructor` works like a pointer to const `T`.) // -// An object of type NoDestructor should be defined in static storage: -// as either a global static object, or as a function scope static variable. -// // Additionally, NoDestructor provides the following benefits: // // * Never calls T's destructor for the object @@ -72,24 +68,7 @@ ABSL_NAMESPACE_BEGIN // lazily constructed. // // An object of type NoDestructor is "trivially destructible" in the notion -// that its destructor is never run. Provided that an object of this type can be -// safely initialized and does not need to be cleaned up on program shutdown, -// NoDestructor allows you to define global static variables, since Google's -// C++ style guide ban on such objects doesn't apply to objects that are -// trivially destructible. -// -// Usage as Global Static Variables -// -// NoDestructor allows declaration of a global object with a non-trivial -// constructor in static storage without needing to add a destructor. -// However, such objects still need to worry about initialization order, so -// such objects should be const initialized: -// -// // Global or namespace scope. -// constinit absl::NoDestructor reg{"foo", "bar", 8008}; -// -// Note that if your object already has a trivial destructor, you don't need to -// use NoDestructor. +// that its destructor is never run. // // Usage as Function Scope Static Variables // @@ -115,6 +94,21 @@ ABSL_NAMESPACE_BEGIN // return *x; // } // +// Usage as Global Static Variables +// +// NoDestructor allows declaration of a global object of type T that has a +// non-trivial destructor since its destructor is never run. However, such +// objects still need to worry about initialization order, so such use is not +// recommended, strongly discouraged by the Google C++ Style Guide, and outright +// banned in Chromium. +// See https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables +// +// // Global or namespace scope. +// absl::NoDestructor reg{"foo", "bar", 8008}; +// +// Note that if your object already has a trivial destructor, you don't need to +// use NoDestructor. +// template class NoDestructor { public: diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/nullability.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/nullability.h index 6f49b6f535..34dc083a4e 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/nullability.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/nullability.h @@ -128,9 +128,17 @@ // // By default, nullability annotations are applicable to raw and smart // pointers. User-defined types can indicate compatibility with nullability -// annotations by providing an `absl_nullability_compatible` nested type. The -// actual definition of this inner type is not relevant as it is used merely as -// a marker. It is common to use a using declaration of +// annotations by adding the ABSL_NULLABILITY_COMPATIBLE attribute. +// +// // Example: +// struct ABSL_NULLABILITY_COMPATIBLE MyPtr { +// ... +// }; +// +// Note: For the time being, nullability-compatible classes should additionally +// be marked with an `absl_nullability_compatible` nested type (this will soon +// be deprecated). The actual definition of this inner type is not relevant as +// it is used merely as a marker. It is common to use a using declaration of // `absl_nullability_compatible` set to void. // // // Example: @@ -150,14 +158,16 @@ #ifndef ABSL_BASE_NULLABILITY_H_ #define ABSL_BASE_NULLABILITY_H_ +#include "absl/base/config.h" #include "absl/base/internal/nullability_impl.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::Nonnull // // The indicated pointer is never null. It is the responsibility of the provider -// of this pointer across an API boundary to ensure that the pointer is never be +// of this pointer across an API boundary to ensure that the pointer is never // set to null. Consumers of this pointer across an API boundary may safely // dereference the pointer. // @@ -198,9 +208,9 @@ using Nullable = nullability_internal::NullableImpl; // migrated into one of the above two nullability states: `Nonnull` or // `Nullable`. // -// NOTE: Because this annotation is the global default state, pointers without -// any annotation are assumed to have "unknown" semantics. This assumption is -// designed to minimize churn and reduce clutter within the codebase. +// NOTE: Because this annotation is the global default state, unannotated +// pointers are assumed to have "unknown" semantics. This assumption is designed +// to minimize churn and reduce clutter within the codebase. // // Example: // @@ -219,6 +229,22 @@ using Nullable = nullability_internal::NullableImpl; template using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl; +ABSL_NAMESPACE_END } // namespace absl +// ABSL_NULLABILITY_COMPATIBLE +// +// Indicates that a class is compatible with nullability annotations. +// +// For example: +// +// struct ABSL_NULLABILITY_COMPATIBLE MyPtr { +// ... +// }; +#if ABSL_HAVE_FEATURE(nullability_on_classes) +#define ABSL_NULLABILITY_COMPATIBLE _Nullable +#else +#define ABSL_NULLABILITY_COMPATIBLE +#endif + #endif // ABSL_BASE_NULLABILITY_H_ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/optimization.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/optimization.h index f985995899..3aa66e1c7d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/optimization.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/optimization.h @@ -18,12 +18,23 @@ // ----------------------------------------------------------------------------- // // This header file defines portable macros for performance optimization. +// +// This header is included in both C++ code and legacy C code and thus must +// remain compatible with both C and C++. C compatibility will be removed if +// the legacy code is removed or converted to C++. Do not include this header in +// new code that requires C compatibility or assume C compatibility will remain +// indefinitely. #ifndef ABSL_BASE_OPTIMIZATION_H_ #define ABSL_BASE_OPTIMIZATION_H_ #include +#ifdef __cplusplus +// Included for std::unreachable() +#include +#endif // __cplusplus + #include "absl/base/config.h" #include "absl/base/options.h" diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.bazel index 859163f86f..b00c30fdec 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.bazel @@ -252,7 +252,7 @@ cc_library( ":raw_hash_map", "//absl/algorithm:container", "//absl/base:core_headers", - "//absl/memory", + "//absl/meta:type_traits", ], ) @@ -265,11 +265,13 @@ cc_test( deps = [ ":flat_hash_map", ":hash_generator_testing", + ":hash_policy_testing", ":test_allocator", ":unordered_map_constructor_test", ":unordered_map_lookup_test", ":unordered_map_members_test", ":unordered_map_modifiers_test", + "//absl/base:config", "//absl/log:check", "//absl/meta:type_traits", "//absl/types:any", @@ -290,6 +292,7 @@ cc_library( "//absl/algorithm:container", "//absl/base:core_headers", "//absl/memory", + "//absl/meta:type_traits", ], ) @@ -330,6 +333,7 @@ cc_library( "//absl/algorithm:container", "//absl/base:core_headers", "//absl/memory", + "//absl/meta:type_traits", ], ) @@ -340,13 +344,14 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["no_test_loonix"], deps = [ - ":hash_generator_testing", + ":hash_policy_testing", ":node_hash_map", ":tracked", ":unordered_map_constructor_test", ":unordered_map_lookup_test", ":unordered_map_members_test", ":unordered_map_modifiers_test", + "//absl/base:config", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], @@ -365,6 +370,7 @@ cc_library( "//absl/algorithm:container", "//absl/base:core_headers", "//absl/memory", + "//absl/meta:type_traits", ], ) @@ -375,11 +381,15 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["no_test_loonix"], deps = [ + ":hash_generator_testing", + ":hash_policy_testing", ":node_hash_set", ":unordered_set_constructor_test", ":unordered_set_lookup_test", ":unordered_set_members_test", ":unordered_set_modifiers_test", + "//absl/base:config", + "//absl/memory", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], @@ -707,8 +717,10 @@ cc_test( ":hash_policy_testing", ":hashtable_debug", ":hashtablez_sampler", + ":node_hash_set", ":raw_hash_set", ":test_allocator", + ":test_instance_tracker", "//absl/base", "//absl/base:config", "//absl/base:core_headers", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.gn index 04eb34f948..d9a59c348c 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/BUILD.gn @@ -102,7 +102,7 @@ absl_source_set("flat_hash_map") { ":raw_hash_map", "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/base:core_headers", - "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/meta:type_traits", ] } @@ -111,11 +111,13 @@ absl_test("flat_hash_map_test") { deps = [ ":flat_hash_map", ":hash_generator_testing", + ":hash_policy_testing", ":test_allocator", ":unordered_map_constructor_test", ":unordered_map_lookup_test", ":unordered_map_members_test", ":unordered_map_modifiers_test", + "//third_party/abseil-cpp/absl/base:config", "//third_party/abseil-cpp/absl/log:check", "//third_party/abseil-cpp/absl/meta:type_traits", "//third_party/abseil-cpp/absl/types:any", @@ -131,6 +133,7 @@ absl_source_set("flat_hash_set") { "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/meta:type_traits", ] } @@ -162,6 +165,21 @@ absl_source_set("node_hash_map") { "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/meta:type_traits", + ] +} + +absl_test("node_hash_map_test") { + sources = [ "node_hash_map_test.cc" ] + deps = [ + ":hash_policy_testing", + ":node_hash_map", + ":tracked", + ":unordered_map_constructor_test", + ":unordered_map_lookup_test", + ":unordered_map_members_test", + ":unordered_map_modifiers_test", + "//third_party/abseil-cpp/absl/base:config", ] } @@ -175,6 +193,22 @@ absl_source_set("node_hash_set") { "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/memory", + "//third_party/abseil-cpp/absl/meta:type_traits", + ] +} + +absl_test("node_hash_set_test") { + sources = [ "node_hash_set_test.cc" ] + deps = [ + ":hash_generator_testing", + ":hash_policy_testing", + ":node_hash_set", + ":unordered_set_constructor_test", + ":unordered_set_lookup_test", + ":unordered_set_members_test", + ":unordered_set_modifiers_test", + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/memory", ] } @@ -380,8 +414,10 @@ absl_test("raw_hash_set_test") { ":hash_policy_testing", ":hashtable_debug", ":hashtablez_sampler", + ":node_hash_set", ":raw_hash_set", ":test_allocator", + ":test_instance_tracker", "//third_party/abseil-cpp/absl/base", "//third_party/abseil-cpp/absl/base:config", "//third_party/abseil-cpp/absl/base:core_headers", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/container/CMakeLists.txt index b1f5f9d8a3..25831d5fdb 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/CMakeLists.txt @@ -292,7 +292,7 @@ absl_cc_library( absl::hash_container_defaults absl::raw_hash_map absl::algorithm_container - absl::memory + absl::type_traits PUBLIC ) @@ -306,8 +306,10 @@ absl_cc_test( DEPS absl::any absl::check + absl::config absl::flat_hash_map absl::hash_generator_testing + absl::hash_policy_testing absl::test_allocator absl::type_traits absl::unordered_map_constructor_test @@ -331,6 +333,7 @@ absl_cc_library( absl::algorithm_container absl::core_headers absl::memory + absl::type_traits PUBLIC ) @@ -373,6 +376,7 @@ absl_cc_library( absl::raw_hash_map absl::algorithm_container absl::memory + absl::type_traits PUBLIC ) @@ -384,7 +388,8 @@ absl_cc_test( COPTS ${ABSL_TEST_COPTS} DEPS - absl::hash_generator_testing + absl::config + absl::hash_policy_testing absl::node_hash_map absl::tracked absl::unordered_map_constructor_test @@ -409,6 +414,7 @@ absl_cc_library( absl::raw_hash_set absl::algorithm_container absl::memory + absl::type_traits PUBLIC ) @@ -422,7 +428,10 @@ absl_cc_test( "-DUNORDERED_SET_CXX17" DEPS absl::hash_generator_testing + absl::hash_policy_testing + absl::memory absl::node_hash_set + absl::type_traits absl::unordered_set_constructor_test absl::unordered_set_lookup_test absl::unordered_set_members_test @@ -781,10 +790,12 @@ absl_cc_test( absl::hashtablez_sampler absl::log absl::memory + absl::node_hash_set absl::prefetch absl::raw_hash_set absl::strings absl::test_allocator + absl::test_instance_tracker absl::type_traits GTest::gmock_main ) diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/btree_map.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/btree_map.h index 0f62f0bd80..b959b674ee 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/btree_map.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/btree_map.h @@ -49,6 +49,8 @@ // // Another API difference is that btree iterators can be subtracted, and this // is faster than using std::distance. +// +// B-tree maps are not exception-safe. #ifndef ABSL_CONTAINER_BTREE_MAP_H_ #define ABSL_CONTAINER_BTREE_MAP_H_ @@ -85,7 +87,7 @@ struct map_params; // template , typename Alloc = std::allocator>> -class btree_map +class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_map : public container_internal::btree_map_container< container_internal::btree::size_type erase_if( // template , typename Alloc = std::allocator>> -class btree_multimap +class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_multimap : public container_internal::btree_multimap_container< container_internal::btree, typename Alloc = std::allocator> -class btree_set +class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_set : public container_internal::btree_set_container< container_internal::btree::size_type erase_if(btree_set &set, // template , typename Alloc = std::allocator> -class btree_multiset +class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_multiset : public container_internal::btree_multiset_container< container_internal::btree #include "absl/algorithm/container.h" +#include "absl/base/attributes.h" #include "absl/base/macros.h" #include "absl/container/hash_container_defaults.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -121,9 +125,10 @@ struct FlatHashMapPolicy; template , class Eq = DefaultHashContainerEq, class Allocator = std::allocator>> -class flat_hash_map : public absl::container_internal::raw_hash_map< - absl::container_internal::FlatHashMapPolicy, - Hash, Eq, Allocator> { +class ABSL_INTERNAL_ATTRIBUTE_OWNER flat_hash_map + : public absl::container_internal::raw_hash_map< + absl::container_internal::FlatHashMapPolicy, Hash, Eq, + Allocator> { using Base = typename flat_hash_map::raw_hash_map; public: @@ -571,6 +576,38 @@ typename flat_hash_map::size_type erase_if( namespace container_internal { +// c_for_each_fast(flat_hash_map<>, Function) +// +// Container-based version of the `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template +decay_t c_for_each_fast(const flat_hash_map& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template +decay_t c_for_each_fast(flat_hash_map& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template +decay_t c_for_each_fast(flat_hash_map&& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template struct FlatHashMapPolicy { using slot_policy = container_internal::map_slot_policy; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/flat_hash_set.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/flat_hash_set.h index e558b071c3..a3e36e05e3 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/flat_hash_set.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/flat_hash_set.h @@ -26,6 +26,9 @@ // // In most cases, your default choice for a hash set should be a set of type // `flat_hash_set`. +// +// `flat_hash_set` is not exception-safe. + #ifndef ABSL_CONTAINER_FLAT_HASH_SET_H_ #define ABSL_CONTAINER_FLAT_HASH_SET_H_ @@ -35,11 +38,13 @@ #include #include "absl/algorithm/container.h" +#include "absl/base/attributes.h" #include "absl/base/macros.h" #include "absl/container/hash_container_defaults.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export #include "absl/memory/memory.h" +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -117,7 +122,7 @@ struct FlatHashSetPolicy; template , class Eq = DefaultHashContainerEq, class Allocator = std::allocator> -class flat_hash_set +class ABSL_INTERNAL_ATTRIBUTE_OWNER flat_hash_set : public absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy, Hash, Eq, Allocator> { using Base = typename flat_hash_set::raw_hash_set; @@ -475,6 +480,33 @@ typename flat_hash_set::size_type erase_if( namespace container_internal { +// c_for_each_fast(flat_hash_set<>, Function) +// +// Container-based version of the `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template +decay_t c_for_each_fast(const flat_hash_set& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template +decay_t c_for_each_fast(flat_hash_set& c, Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template +decay_t c_for_each_fast(flat_hash_set&& c, Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template struct FlatHashSetPolicy { using slot_type = T; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h index f05a1fdc5f..6db0468d99 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h @@ -89,9 +89,9 @@ struct Storage { explicit constexpr Storage(absl::in_place_t, V&& v) : value(std::forward(v)) {} constexpr const T& get() const& { return value; } - T& get() & { return value; } + constexpr T& get() & { return value; } constexpr const T&& get() const&& { return std::move(*this).value; } - T&& get() && { return std::move(*this).value; } + constexpr T&& get() && { return std::move(*this).value; } }; template @@ -102,9 +102,9 @@ struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage : T { explicit constexpr Storage(absl::in_place_t, V&& v) : T(std::forward(v)) {} constexpr const T& get() const& { return *this; } - T& get() & { return *this; } + constexpr T& get() & { return *this; } constexpr const T&& get() const&& { return std::move(*this); } - T&& get() && { return std::move(*this); } + constexpr T&& get() && { return std::move(*this); } }; template @@ -237,7 +237,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple std::forward(base)...) {} template - ElemT& get() & { + constexpr ElemT& get() & { return StorageT::get(); } @@ -247,7 +247,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple } template - ElemT&& get() && { + constexpr ElemT&& get() && { return std::move(*this).StorageT::get(); } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h index 9ef9a6bebf..d4fe8f5c21 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h @@ -878,7 +878,7 @@ struct GroupPortableImpl { // Note: this includes: kEmpty, kDeleted, kSentinel. // It is useful in contexts when kSentinel is not present. auto MaskNonFull() const { - return BitMask(ctrl & kMsbs8Bytes); + return BitMask(ctrl & kMsbs8Bytes); } NonIterableBitMask MaskEmptyOrDeleted() const { @@ -1134,9 +1134,7 @@ class GrowthInfo { // Returns true if the table satisfies two properties: // 1. Guaranteed to have no kDeleted slots. // 2. There is no growth left. - bool HasNoGrowthLeftAndNoDeleted() const { - return growth_left_info_ == 0; - } + bool HasNoGrowthLeftAndNoDeleted() const { return growth_left_info_ == 0; } // Returns true if table guaranteed to have no k bool HasNoDeleted() const { @@ -1144,9 +1142,7 @@ class GrowthInfo { } // Returns the number of elements left to grow. - size_t GetGrowthLeft() const { - return growth_left_info_ & kGrowthLeftMask; - } + size_t GetGrowthLeft() const { return growth_left_info_ & kGrowthLeftMask; } private: static constexpr size_t kGrowthLeftMask = ((~size_t{}) >> 1); @@ -1222,6 +1218,8 @@ class RawHashSetLayout { size_t slot_offset_; }; +struct HashtableFreeFunctionsAccess; + // We only allow a maximum of 1 SOO element, which makes the implementation // much simpler. Complications with multiple SOO elements include: // - Satisfying the guarantee that erasing one element doesn't invalidate @@ -1419,8 +1417,8 @@ class CommonFields : public CommonFieldsGenerationInfo { should_rehash_for_bug_detection_on_insert(control(), capacity()); } bool should_rehash_for_bug_detection_on_move() const { - return CommonFieldsGenerationInfo:: - should_rehash_for_bug_detection_on_move(control(), capacity()); + return CommonFieldsGenerationInfo::should_rehash_for_bug_detection_on_move( + control(), capacity()); } void reset_reserved_growth(size_t reservation) { CommonFieldsGenerationInfo::reset_reserved_growth(reservation, size()); @@ -1853,12 +1851,13 @@ constexpr size_t BackingArrayAlignment(size_t align_of_slot) { // Returns the address of the ith slot in slots where each slot occupies // slot_size. inline void* SlotAddress(void* slot_array, size_t slot, size_t slot_size) { - return reinterpret_cast(reinterpret_cast(slot_array) + - (slot * slot_size)); + return static_cast(static_cast(slot_array) + + (slot * slot_size)); } // Iterates over all full slots and calls `cb(const ctrl_t*, SlotType*)`. -// NOTE: no erasure from this table allowed during Callback call. +// No insertion to the table allowed during Callback call. +// Erasure is allowed only for the element passed to the callback. template ABSL_ATTRIBUTE_ALWAYS_INLINE inline void IterateOverFullSlots( const CommonFields& c, SlotType* slot, Callback cb) { @@ -1887,14 +1886,22 @@ ABSL_ATTRIBUTE_ALWAYS_INLINE inline void IterateOverFullSlots( return; } size_t remaining = c.size(); + ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = remaining; while (remaining != 0) { for (uint32_t i : GroupFullEmptyOrDeleted(ctrl).MaskFull()) { + assert(IsFull(ctrl[i]) && "hash table was modified unexpectedly"); cb(ctrl + i, slot + i); --remaining; } - slot += Group::kWidth; ctrl += Group::kWidth; + slot += Group::kWidth; + assert((remaining == 0 || *(ctrl - 1) != ctrl_t::kSentinel) && + "hash table was modified unexpectedly"); } + // NOTE: erasure of the current element is allowed in callback for + // absl::erase_if specialization. So we use `>=`. + assert(original_size_for_assert >= c.size() && + "hash table was modified unexpectedly"); } template @@ -2089,8 +2096,8 @@ class HashSetResizeHelper { using slot_type = typename PolicyTraits::slot_type; assert(is_single_group(c.capacity())); - auto* new_slots = reinterpret_cast(c.slot_array()); - auto* old_slots_ptr = reinterpret_cast(old_slots()); + auto* new_slots = static_cast(c.slot_array()); + auto* old_slots_ptr = static_cast(old_slots()); size_t shuffle_bit = old_capacity_ / 2 + 1; for (size_t i = 0; i < old_capacity_; ++i) { @@ -2430,6 +2437,7 @@ class raw_hash_set { class iterator : private HashSetIteratorGenerationInfo { friend class raw_hash_set; + friend struct HashtableFreeFunctionsAccess; public: using iterator_category = std::forward_iterator_tag; @@ -3317,11 +3325,13 @@ class raw_hash_set { template iterator find(const key_arg& key, size_t hash) ABSL_ATTRIBUTE_LIFETIME_BOUND { + AssertHashEqConsistent(key); if (is_soo()) return find_soo(key); return find_non_soo(key, hash); } template iterator find(const key_arg& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { + AssertHashEqConsistent(key); if (is_soo()) return find_soo(key); prefetch_heap_block(); return find_non_soo(key, hash_ref()(key)); @@ -3409,6 +3419,8 @@ class raw_hash_set { friend struct absl::container_internal::hashtable_debug_internal:: HashtableDebugAccess; + friend struct absl::container_internal::HashtableFreeFunctionsAccess; + struct FindElement { template const_iterator operator()(const K& key, Args&&...) const { @@ -3659,8 +3671,7 @@ class raw_hash_set { insert_slot(to_slot(resize_helper.old_soo_data())); return; } else { - auto* old_slots = - reinterpret_cast(resize_helper.old_slots()); + auto* old_slots = static_cast(resize_helper.old_slots()); size_t total_probe_length = 0; for (size_t i = 0; i != resize_helper.old_capacity(); ++i) { if (IsFull(resize_helper.old_ctrl()[i])) { @@ -3676,9 +3687,7 @@ class raw_hash_set { // Casting directly from e.g. char* to slot_type* can cause compilation errors // on objective-C. This function converts to void* first, avoiding the issue. - static slot_type* to_slot(void* buf) { - return reinterpret_cast(buf); - } + static slot_type* to_slot(void* buf) { return static_cast(buf); } // Requires that lhs does not have a full SOO slot. static void move_common(bool that_is_full_soo, allocator_type& rhs_alloc, @@ -3719,7 +3728,7 @@ class raw_hash_set { } } - template + template raw_hash_set& assign_impl(raw_hash_set&& that) { // We don't bother checking for this/that aliasing. We just need to avoid // breaking the invariants in that case. @@ -3822,11 +3831,58 @@ class raw_hash_set { } protected: + // Asserts that hash and equal functors provided by the user are consistent, + // meaning that `eq(k1, k2)` implies `hash(k1)==hash(k2)`. + template + void AssertHashEqConsistent(ABSL_ATTRIBUTE_UNUSED const K& key) { +#ifndef NDEBUG + if (empty()) return; + + const size_t hash_of_arg = hash_ref()(key); + const auto assert_consistent = [&](const ctrl_t*, slot_type* slot) { + const value_type& element = PolicyTraits::element(slot); + const bool is_key_equal = + PolicyTraits::apply(EqualElement{key, eq_ref()}, element); + if (!is_key_equal) return; + + const size_t hash_of_slot = + PolicyTraits::apply(HashElement{hash_ref()}, element); + const bool is_hash_equal = hash_of_arg == hash_of_slot; + if (!is_hash_equal) { + // In this case, we're going to crash. Do a couple of other checks for + // idempotence issues. Recalculating hash/eq here is also convenient for + // debugging with gdb/lldb. + const size_t once_more_hash_arg = hash_ref()(key); + assert(hash_of_arg == once_more_hash_arg && "hash is not idempotent."); + const size_t once_more_hash_slot = + PolicyTraits::apply(HashElement{hash_ref()}, element); + assert(hash_of_slot == once_more_hash_slot && + "hash is not idempotent."); + const bool once_more_eq = + PolicyTraits::apply(EqualElement{key, eq_ref()}, element); + assert(is_key_equal == once_more_eq && "equality is not idempotent."); + } + assert((!is_key_equal || is_hash_equal) && + "eq(k1, k2) must imply that hash(k1) == hash(k2). " + "hash/eq functors are inconsistent."); + }; + + if (is_soo()) { + assert_consistent(/*unused*/ nullptr, soo_slot()); + return; + } + // We only do validation for small tables so that it's constant time. + if (capacity() > 16) return; + IterateOverFullSlots(common(), slot_array(), assert_consistent); +#endif + } + // Attempts to find `key` in the table; if it isn't found, returns an iterator // where the value can be inserted into, with the control byte already set to // `key`'s H2. Returns a bool indicating whether an insertion can take place. template std::pair find_or_prepare_insert(const K& key) { + AssertHashEqConsistent(key); if (is_soo()) return find_or_prepare_insert_soo(key); return find_or_prepare_insert_non_soo(key); } @@ -3887,7 +3943,7 @@ class raw_hash_set { // cache misses. This is intended to overlap with execution of calculating the // hash for a key. void prefetch_heap_block() const { - if (is_soo()) return; + assert(!is_soo()); #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__) __builtin_prefetch(control(), 0, 1); #endif @@ -3981,19 +4037,74 @@ class raw_hash_set { key_equal{}, allocator_type{}}; }; +// Friend access for free functions in raw_hash_set.h. +struct HashtableFreeFunctionsAccess { + template + static typename Set::size_type EraseIf(Predicate& pred, Set* c) { + if (c->empty()) { + return 0; + } + if (c->is_soo()) { + auto it = c->soo_iterator(); + if (!pred(*it)) { + assert(c->size() == 1 && "hash table was modified unexpectedly"); + return 0; + } + c->destroy(it.slot()); + c->common().set_empty_soo(); + return 1; + } + ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = c->size(); + size_t num_deleted = 0; + IterateOverFullSlots( + c->common(), c->slot_array(), [&](const ctrl_t* ctrl, auto* slot) { + if (pred(Set::PolicyTraits::element(slot))) { + c->destroy(slot); + EraseMetaOnly(c->common(), static_cast(ctrl - c->control()), + sizeof(*slot)); + ++num_deleted; + } + }); + // NOTE: IterateOverFullSlots allow removal of the current element, so we + // verify the size additionally here. + assert(original_size_for_assert - num_deleted == c->size() && + "hash table was modified unexpectedly"); + return num_deleted; + } + + template + static void ForEach(Callback& cb, Set* c) { + if (c->empty()) { + return; + } + if (c->is_soo()) { + cb(*c->soo_iterator()); + return; + } + using ElementTypeWithConstness = decltype(*c->begin()); + IterateOverFullSlots( + c->common(), c->slot_array(), [&cb](const ctrl_t*, auto* slot) { + ElementTypeWithConstness& element = Set::PolicyTraits::element(slot); + cb(element); + }); + } +}; + // Erases all elements that satisfy the predicate `pred` from the container `c`. template typename raw_hash_set::size_type EraseIf( Predicate& pred, raw_hash_set* c) { - const auto initial_size = c->size(); - for (auto it = c->begin(), last = c->end(); it != last;) { - if (pred(*it)) { - c->erase(it++); - } else { - ++it; - } - } - return initial_size - c->size(); + return HashtableFreeFunctionsAccess::EraseIf(pred, c); +} + +// Calls `cb` for all elements in the container `c`. +template +void ForEach(Callback& cb, raw_hash_set* c) { + return HashtableFreeFunctionsAccess::ForEach(cb, c); +} +template +void ForEach(Callback& cb, const raw_hash_set* c) { + return HashtableFreeFunctionsAccess::ForEach(cb, c); } namespace hashtable_debug_internal { diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/node_hash_map.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/node_hash_map.h index 31beb1daa7..5615e4966b 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/node_hash_map.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/node_hash_map.h @@ -32,6 +32,8 @@ // migration, because it guarantees pointer stability. Consider migrating to // `node_hash_map` and perhaps converting to a more efficient `flat_hash_map` // upon further review. +// +// `node_hash_map` is not exception-safe. #ifndef ABSL_CONTAINER_NODE_HASH_MAP_H_ #define ABSL_CONTAINER_NODE_HASH_MAP_H_ @@ -42,11 +44,13 @@ #include #include "absl/algorithm/container.h" +#include "absl/base/attributes.h" #include "absl/container/hash_container_defaults.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/node_slot_policy.h" #include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export #include "absl/memory/memory.h" +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -116,7 +120,7 @@ class NodeHashMapPolicy; template , class Eq = DefaultHashContainerEq, class Alloc = std::allocator>> -class node_hash_map +class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_map : public absl::container_internal::raw_hash_map< absl::container_internal::NodeHashMapPolicy, Hash, Eq, Alloc> { @@ -556,6 +560,38 @@ typename node_hash_map::size_type erase_if( namespace container_internal { +// c_for_each_fast(node_hash_map<>, Function) +// +// Container-based version of the `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template +decay_t c_for_each_fast(const node_hash_map& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template +decay_t c_for_each_fast(node_hash_map& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template +decay_t c_for_each_fast(node_hash_map&& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template class NodeHashMapPolicy : public absl::container_internal::node_slot_policy< diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/container/node_hash_set.h b/naiveproxy/src/third_party/abseil-cpp/absl/container/node_hash_set.h index deeb49ce53..53435ae630 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/container/node_hash_set.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/container/node_hash_set.h @@ -31,6 +31,8 @@ // `node_hash_set` should be an easy migration. Consider migrating to // `node_hash_set` and perhaps converting to a more efficient `flat_hash_set` // upon further review. +// +// `node_hash_set` is not exception-safe. #ifndef ABSL_CONTAINER_NODE_HASH_SET_H_ #define ABSL_CONTAINER_NODE_HASH_SET_H_ @@ -40,11 +42,13 @@ #include #include "absl/algorithm/container.h" +#include "absl/base/attributes.h" #include "absl/container/hash_container_defaults.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/node_slot_policy.h" #include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export #include "absl/memory/memory.h" +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -111,7 +115,7 @@ struct NodeHashSetPolicy; // } template , class Eq = DefaultHashContainerEq, class Alloc = std::allocator> -class node_hash_set +class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_set : public absl::container_internal::raw_hash_set< absl::container_internal::NodeHashSetPolicy, Hash, Eq, Alloc> { using Base = typename node_hash_set::raw_hash_set; @@ -465,6 +469,33 @@ typename node_hash_set::size_type erase_if( namespace container_internal { +// c_for_each_fast(node_hash_set<>, Function) +// +// Container-based version of the `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template +decay_t c_for_each_fast(const node_hash_set& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template +decay_t c_for_each_fast(node_hash_set& c, Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template +decay_t c_for_each_fast(node_hash_set&& c, Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template struct NodeHashSetPolicy : absl::container_internal::node_slot_policy> { diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake b/naiveproxy/src/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake index 1afb961020..a618199d37 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake +++ b/naiveproxy/src/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake @@ -42,7 +42,7 @@ if(APPLE AND CMAKE_CXX_COMPILER_ID MATCHES [[Clang]]) string(TOUPPER "${_arch}" _arch_uppercase) string(REPLACE "X86_64" "X64" _arch_uppercase ${_arch_uppercase}) foreach(_flag IN LISTS ABSL_RANDOM_HWAES_${_arch_uppercase}_FLAGS) - list(APPEND ABSL_RANDOM_RANDEN_COPTS "-Xarch_${_arch}" "${_flag}") + list(APPEND ABSL_RANDOM_RANDEN_COPTS "SHELL:-Xarch_${_arch} ${_flag}") endforeach() endforeach() # If a compiler happens to deal with an argument for a currently unused diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/BUILD.bazel index 22494554c7..52b407c0a7 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/BUILD.bazel @@ -219,14 +219,8 @@ cc_library( cc_library( name = "demangle_internal", - srcs = [ - "internal/demangle.cc", - "internal/demangle_rust.cc", - ], - hdrs = [ - "internal/demangle.h", - "internal/demangle_rust.h", - ], + srcs = ["internal/demangle.cc"], + hdrs = ["internal/demangle.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ @@ -234,23 +228,12 @@ cc_library( "//absl/debugging:__pkg__", ], deps = [ + ":demangle_rust", "//absl/base", "//absl/base:config", "//absl/base:core_headers", - ], -) - -cc_test( - name = "demangle_rust_test", - srcs = ["internal/demangle_rust_test.cc"], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":demangle_internal", - "//absl/base:config", - "//absl/base:core_headers", - "@com_google_googletest//:gtest", - "@com_google_googletest//:gtest_main", + "//absl/base:nullability", + "//absl/numeric:bits", ], ) @@ -271,6 +254,106 @@ cc_test( ], ) +cc_library( + name = "bounded_utf8_length_sequence", + hdrs = ["internal/bounded_utf8_length_sequence.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + "//absl/base:config", + "//absl/numeric:bits", + ], +) + +cc_test( + name = "bounded_utf8_length_sequence_test", + srcs = ["internal/bounded_utf8_length_sequence_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":bounded_utf8_length_sequence", + "//absl/base:config", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + +cc_library( + name = "decode_rust_punycode", + srcs = ["internal/decode_rust_punycode.cc"], + hdrs = ["internal/decode_rust_punycode.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":bounded_utf8_length_sequence", + ":utf8_for_code_point", + "//absl/base:config", + "//absl/base:nullability", + ], +) + +cc_test( + name = "decode_rust_punycode_test", + srcs = ["internal/decode_rust_punycode_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":decode_rust_punycode", + "//absl/base:config", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + +cc_library( + name = "demangle_rust", + srcs = ["internal/demangle_rust.cc"], + hdrs = ["internal/demangle_rust.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":decode_rust_punycode", + "//absl/base:config", + "//absl/base:core_headers", + ], +) + +cc_test( + name = "demangle_rust_test", + srcs = ["internal/demangle_rust_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":demangle_rust", + "//absl/base:config", + "//absl/base:core_headers", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + +cc_library( + name = "utf8_for_code_point", + srcs = ["internal/utf8_for_code_point.cc"], + hdrs = ["internal/utf8_for_code_point.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = ["//absl/base:config"], +) + +cc_test( + name = "utf8_for_code_point_test", + srcs = ["internal/utf8_for_code_point_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":utf8_for_code_point", + "//absl/base:config", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + cc_library( name = "leak_check", srcs = ["leak_check.cc"], diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/BUILD.gn index 49523cd61a..1d7f14442f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/BUILD.gn @@ -119,31 +119,19 @@ absl_source_set("debugging_internal") { } absl_source_set("demangle_internal") { - sources = [ - "internal/demangle.cc", - "internal/demangle_rust.cc", - ] - public = [ - "internal/demangle.h", - "internal/demangle_rust.h", - ] + sources = [ "internal/demangle.cc" ] + public = [ "internal/demangle.h" ] visibility = [ "//third_party/abseil-cpp/absl/container:*", "//third_party/abseil-cpp/absl/debugging:*", ] deps = [ + ":demangle_rust", "//third_party/abseil-cpp/absl/base", "//third_party/abseil-cpp/absl/base:config", "//third_party/abseil-cpp/absl/base:core_headers", - ] -} - -absl_test("demangle_rust_test") { - sources = [ "internal/demangle_rust_test.cc" ] - deps = [ - ":demangle_internal", - "//third_party/abseil-cpp/absl/base:config", - "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/base:nullability", + "//third_party/abseil-cpp/absl/numeric:bits", ] } @@ -160,6 +148,74 @@ absl_test("demangle_rust_test") { # ] # } +absl_source_set("bounded_utf8_length_sequence") { + public = [ "internal/bounded_utf8_length_sequence.h" ] + deps = [ + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/numeric:bits", + ] +} + +absl_test("bounded_utf8_length_sequence_test") { + sources = [ "internal/bounded_utf8_length_sequence_test.cc" ] + deps = [ + ":bounded_utf8_length_sequence", + "//third_party/abseil-cpp/absl/base:config", + ] +} + +absl_source_set("decode_rust_punycode") { + sources = [ "internal/decode_rust_punycode.cc" ] + public = [ "internal/decode_rust_punycode.h" ] + deps = [ + ":bounded_utf8_length_sequence", + ":utf8_for_code_point", + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/base:nullability", + ] +} + +absl_test("decode_rust_punycode_test") { + sources = [ "internal/decode_rust_punycode_test.cc" ] + deps = [ + ":decode_rust_punycode", + "//third_party/abseil-cpp/absl/base:config", + ] +} + +absl_source_set("demangle_rust") { + sources = [ "internal/demangle_rust.cc" ] + public = [ "internal/demangle_rust.h" ] + deps = [ + ":decode_rust_punycode", + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/base:core_headers", + ] +} + +absl_test("demangle_rust_test") { + sources = [ "internal/demangle_rust_test.cc" ] + deps = [ + ":demangle_rust", + "//third_party/abseil-cpp/absl/base:config", + "//third_party/abseil-cpp/absl/base:core_headers", + ] +} + +absl_source_set("utf8_for_code_point") { + sources = [ "internal/utf8_for_code_point.cc" ] + public = [ "internal/utf8_for_code_point.h" ] + deps = [ "//third_party/abseil-cpp/absl/base:config" ] +} + +absl_test("utf8_for_code_point_test") { + sources = [ "internal/utf8_for_code_point_test.cc" ] + deps = [ + ":utf8_for_code_point", + "//third_party/abseil-cpp/absl/base:config", + ] +} + absl_source_set("leak_check") { if (is_ios || is_win) { sources = [] diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/CMakeLists.txt index 027a6be28b..a96b4f3964 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/CMakeLists.txt @@ -196,29 +196,14 @@ absl_cc_library( demangle_internal HDRS "internal/demangle.h" - "internal/demangle_rust.h" SRCS "internal/demangle.cc" - "internal/demangle_rust.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS - absl::base - absl::core_headers - PUBLIC -) - -absl_cc_test( - NAME - demangle_rust_test - SRCS - "internal/demangle_rust_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::demangle_internal absl::config - GTest::gmock_main + absl::demangle_rust + PUBLIC ) absl_cc_test( @@ -238,6 +223,118 @@ absl_cc_test( GTest::gmock_main ) +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + bounded_utf8_length_sequence + HDRS + "internal/bounded_utf8_length_sequence.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::bits + absl::config +) + +absl_cc_test( + NAME + bounded_utf8_length_sequence_test + SRCS + "internal/bounded_utf8_length_sequence_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::bounded_utf8_length_sequence + absl::config + GTest::gmock_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + decode_rust_punycode + HDRS + "internal/decode_rust_punycode.h" + SRCS + "internal/decode_rust_punycode.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::bounded_utf8_length_sequence + absl::config + absl::nullability + absl::utf8_for_code_point +) + +absl_cc_test( + NAME + decode_rust_punycode_test + SRCS + "internal/decode_rust_punycode_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::decode_rust_punycode + absl::config + GTest::gmock_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + demangle_rust + HDRS + "internal/demangle_rust.h" + SRCS + "internal/demangle_rust.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + absl::core_headers + absl::decode_rust_punycode +) + +absl_cc_test( + NAME + demangle_rust_test + SRCS + "internal/demangle_rust_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::demangle_rust + absl::config + GTest::gmock_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + utf8_for_code_point + HDRS + "internal/utf8_for_code_point.h" + SRCS + "internal/utf8_for_code_point.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config +) + +absl_cc_test( + NAME + utf8_for_code_point_test + SRCS + "internal/utf8_for_code_point_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::utf8_for_code_point + absl::config + GTest::gmock_main +) + absl_cc_library( NAME leak_check diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/bounded_utf8_length_sequence.h b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/bounded_utf8_length_sequence.h new file mode 100644 index 0000000000..188e06c4af --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/bounded_utf8_length_sequence.h @@ -0,0 +1,126 @@ +// Copyright 2024 The Abseil Authors +// +// 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 +// +// https://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. + +#ifndef ABSL_DEBUGGING_INTERNAL_BOUNDED_UTF8_LENGTH_SEQUENCE_H_ +#define ABSL_DEBUGGING_INTERNAL_BOUNDED_UTF8_LENGTH_SEQUENCE_H_ + +#include + +#include "absl/base/config.h" +#include "absl/numeric/bits.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +// A sequence of up to max_elements integers between 1 and 4 inclusive, whose +// insertion operation computes the sum of all the elements before the insertion +// point. This is useful in decoding Punycode, where one needs to know where in +// a UTF-8 byte stream the n-th code point begins. +// +// BoundedUtf8LengthSequence is async-signal-safe and suitable for use in +// symbolizing stack traces in a signal handler, provided max_elements is not +// improvidently large. For inputs of lengths accepted by the Rust demangler, +// up to a couple hundred code points, InsertAndReturnSumOfPredecessors should +// run in a few dozen clock cycles, on par with the other arithmetic required +// for Punycode decoding. +template +class BoundedUtf8LengthSequence { + public: + // Constructs an empty sequence. + BoundedUtf8LengthSequence() = default; + + // Inserts `utf_length` at position `index`, shifting any existing elements at + // or beyond `index` one position to the right. If the sequence is already + // full, the rightmost element is discarded. + // + // Returns the sum of the elements at positions 0 to `index - 1` inclusive. + // If `index` is greater than the number of elements already inserted, the + // excess positions in the range count 1 apiece. + // + // REQUIRES: index < max_elements and 1 <= utf8_length <= 4. + uint32_t InsertAndReturnSumOfPredecessors( + uint32_t index, uint32_t utf8_length) { + // The caller shouldn't pass out-of-bounds inputs, but if it does happen, + // clamp the values and try to continue. If we're being called from a + // signal handler, the last thing we want to do is crash. Emitting + // malformed UTF-8 is a lesser evil. + if (index >= max_elements) index = max_elements - 1; + if (utf8_length == 0 || utf8_length > 4) utf8_length = 1; + + const uint32_t word_index = index/32; + const uint32_t bit_index = 2 * (index % 32); + const uint64_t ones_bit = uint64_t{1} << bit_index; + + // Compute the sum of predecessors. + // - Each value from 1 to 4 is represented by a bit field with value from + // 0 to 3, so the desired sum is index plus the sum of the + // representations actually stored. + // - For each bit field, a set low bit should contribute 1 to the sum, and + // a set high bit should contribute 2. + // - Another way to say the same thing is that each set bit contributes 1, + // and each set high bit contributes an additional 1. + // - So the sum we want is index + popcount(everything) + popcount(bits in + // odd positions). + const uint64_t odd_bits_mask = 0xaaaaaaaaaaaaaaaa; + const uint64_t lower_seminibbles_mask = ones_bit - 1; + const uint64_t higher_seminibbles_mask = ~lower_seminibbles_mask; + const uint64_t same_word_bits_below_insertion = + rep_[word_index] & lower_seminibbles_mask; + int full_popcount = absl::popcount(same_word_bits_below_insertion); + int odd_popcount = + absl::popcount(same_word_bits_below_insertion & odd_bits_mask); + for (uint32_t j = word_index; j > 0; --j) { + const uint64_t word_below_insertion = rep_[j - 1]; + full_popcount += absl::popcount(word_below_insertion); + odd_popcount += absl::popcount(word_below_insertion & odd_bits_mask); + } + const uint32_t sum_of_predecessors = + index + static_cast(full_popcount + odd_popcount); + + // Now insert utf8_length's representation, shifting successors up one + // place. + for (uint32_t j = max_elements/32 - 1; j > word_index; --j) { + rep_[j] = (rep_[j] << 2) | (rep_[j - 1] >> 62); + } + rep_[word_index] = + (rep_[word_index] & lower_seminibbles_mask) | + (uint64_t{utf8_length - 1} << bit_index) | + ((rep_[word_index] & higher_seminibbles_mask) << 2); + + return sum_of_predecessors; + } + + private: + // If the (32 * i + j)-th element of the represented sequence has the value k + // (0 <= j < 32, 1 <= k <= 4), then bits 2 * j and 2 * j + 1 of rep_[i] + // contain the seminibble (k - 1). + // + // In particular, the zero-initialization of rep_ makes positions not holding + // any inserted element count as 1 in InsertAndReturnSumOfPredecessors. + // + // Example: rep_ = {0xb1, ... the rest zeroes ...} represents the sequence + // (2, 1, 4, 3, ... the rest 1's ...). Constructing the sequence of Unicode + // code points "Àa🂻中" = {U+00C0, U+0061, U+1F0BB, U+4E2D} (among many + // other examples) would yield this value of rep_. + static_assert(max_elements > 0 && max_elements % 32 == 0, + "max_elements must be a positive multiple of 32"); + uint64_t rep_[max_elements/32] = {}; +}; + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_DEBUGGING_INTERNAL_BOUNDED_UTF8_LENGTH_SEQUENCE_H_ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/decode_rust_punycode.cc b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/decode_rust_punycode.cc new file mode 100644 index 0000000000..43b46bf940 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/decode_rust_punycode.cc @@ -0,0 +1,258 @@ +// Copyright 2024 The Abseil Authors +// +// 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 +// +// https://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. + +#include "absl/debugging/internal/decode_rust_punycode.h" + +#include +#include +#include + +#include "absl/base/config.h" +#include "absl/base/nullability.h" +#include "absl/debugging/internal/bounded_utf8_length_sequence.h" +#include "absl/debugging/internal/utf8_for_code_point.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +namespace { + +// Decoding Punycode requires repeated random-access insertion into a stream of +// variable-length UTF-8 code-point encodings. We need this to be tolerably +// fast (no N^2 slowdown for unfortunate inputs), and we can't allocate any data +// structures on the heap (async-signal-safety). +// +// It is pragmatic to impose a moderately low limit on the identifier length and +// bail out if we ever hit it. Then BoundedUtf8LengthSequence efficiently +// determines where to insert the next code point, and memmove efficiently makes +// room for it. +// +// The chosen limit is a round number several times larger than identifiers +// expected in practice, yet still small enough that a memmove of this many +// UTF-8 characters is not much more expensive than the division and modulus +// operations that Punycode decoding requires. +constexpr uint32_t kMaxChars = 256; + +// Constants from RFC 3492 section 5. +constexpr uint32_t kBase = 36, kTMin = 1, kTMax = 26, kSkew = 38, kDamp = 700; + +constexpr uint32_t kMaxCodePoint = 0x10ffff; + +// Overflow threshold in DecodeRustPunycode's inner loop; see comments there. +constexpr uint32_t kMaxI = 1 << 30; + +// If punycode_begin .. punycode_end begins with a prefix matching the regular +// expression [0-9a-zA-Z_]+_, removes that prefix, copies all but the final +// underscore into out_begin .. out_end, sets num_ascii_chars to the number of +// bytes copied, and returns true. (A prefix of this sort represents the +// nonempty subsequence of ASCII characters in the corresponding plaintext.) +// +// If punycode_begin .. punycode_end does not contain an underscore, sets +// num_ascii_chars to zero and returns true. (The encoding of a plaintext +// without any ASCII characters does not carry such a prefix.) +// +// Returns false and zeroes num_ascii_chars on failure (either parse error or +// not enough space in the output buffer). +bool ConsumeOptionalAsciiPrefix(const char*& punycode_begin, + const char* const punycode_end, + char* const out_begin, + char* const out_end, + uint32_t& num_ascii_chars) { + num_ascii_chars = 0; + + // Remember the last underscore if any. Also use the same string scan to + // reject any ASCII bytes that do not belong in an identifier, including NUL, + // as well as non-ASCII bytes, which should have been delta-encoded instead. + int last_underscore = -1; + for (int i = 0; i < punycode_end - punycode_begin; ++i) { + const char c = punycode_begin[i]; + if (c == '_') { + last_underscore = i; + continue; + } + // We write out the meaning of absl::ascii_isalnum rather than call that + // function because its documentation does not promise it will remain + // async-signal-safe under future development. + if ('a' <= c && c <= 'z') continue; + if ('A' <= c && c <= 'Z') continue; + if ('0' <= c && c <= '9') continue; + return false; + } + + // If there was no underscore, that means there were no ASCII characters in + // the plaintext, so there is no prefix to consume. Our work is done. + if (last_underscore < 0) return true; + + // Otherwise there will be an underscore delimiter somewhere. It can't be + // initial because then there would be no ASCII characters to its left, and no + // delimiter would have been added in that case. + if (last_underscore == 0) return false; + + // Any other position is reasonable. Make sure there's room in the buffer. + if (last_underscore + 1 > out_end - out_begin) return false; + + // Consume and write out the ASCII characters. + num_ascii_chars = static_cast(last_underscore); + std::memcpy(out_begin, punycode_begin, num_ascii_chars); + out_begin[num_ascii_chars] = '\0'; + punycode_begin += num_ascii_chars + 1; + return true; +} + +// Returns the value of `c` as a base-36 digit according to RFC 3492 section 5, +// or -1 if `c` is not such a digit. +int DigitValue(char c) { + if ('0' <= c && c <= '9') return c - '0' + 26; + if ('a' <= c && c <= 'z') return c - 'a'; + if ('A' <= c && c <= 'Z') return c - 'A'; + return -1; +} + +// Consumes the next delta encoding from punycode_begin .. punycode_end, +// updating i accordingly. Returns true on success. Returns false on parse +// failure or arithmetic overflow. +bool ScanNextDelta(const char*& punycode_begin, const char* const punycode_end, + uint32_t bias, uint32_t& i) { + uint64_t w = 1; // 64 bits to prevent overflow in w *= kBase - t + + // "for k = base to infinity in steps of base do begin ... end" in RFC 3492 + // section 6.2. Each loop iteration scans one digit of the delta. + for (uint32_t k = kBase; punycode_begin != punycode_end; k += kBase) { + const int digit_value = DigitValue(*punycode_begin++); + if (digit_value < 0) return false; + + // Compute this in 64-bit arithmetic so we can check for overflow afterward. + const uint64_t new_i = i + static_cast(digit_value) * w; + + // Valid deltas are bounded by (#chars already emitted) * kMaxCodePoint, but + // invalid input could encode an arbitrarily large delta. Nip that in the + // bud here. + static_assert( + kMaxI >= kMaxChars * kMaxCodePoint, + "kMaxI is too small to prevent spurious failures on good input"); + if (new_i > kMaxI) return false; + + static_assert( + kMaxI < (uint64_t{1} << 32), + "Make kMaxI smaller or i 64 bits wide to prevent silent wraparound"); + i = static_cast(new_i); + + // Compute the threshold that determines whether this is the last digit and + // (if not) what the next digit's place value will be. This logic from RFC + // 3492 section 6.2 is explained in section 3.3. + uint32_t t; + if (k <= bias + kTMin) { + t = kTMin; + } else if (k >= bias + kTMax) { + t = kTMax; + } else { + t = k - bias; + } + if (static_cast(digit_value) < t) return true; + + // If this gets too large, the range check on new_i in the next iteration + // will catch it. We know this multiplication will not overwrap because w + // is 64 bits wide. + w *= kBase - t; + } + return false; +} + +} // namespace + +absl::Nullable DecodeRustPunycode(DecodeRustPunycodeOptions options) { + const char* punycode_begin = options.punycode_begin; + const char* const punycode_end = options.punycode_end; + char* const out_begin = options.out_begin; + char* const out_end = options.out_end; + + // Write a NUL terminator first. Later memcpy calls will keep bumping it + // along to its new right place. + const size_t out_size = static_cast(out_end - out_begin); + if (out_size == 0) return nullptr; + *out_begin = '\0'; + + // RFC 3492 section 6.2 begins here. We retain the names of integer variables + // appearing in that text. + uint32_t n = 128, i = 0, bias = 72, num_chars = 0; + + // If there are any ASCII characters, consume them and their trailing + // underscore delimiter. + if (!ConsumeOptionalAsciiPrefix(punycode_begin, punycode_end, + out_begin, out_end, num_chars)) { + return nullptr; + } + uint32_t total_utf8_bytes = num_chars; + + BoundedUtf8LengthSequence utf8_lengths; + + // "while the input is not exhausted do begin ... end" + while (punycode_begin != punycode_end) { + if (num_chars >= kMaxChars) return nullptr; + + const uint32_t old_i = i; + + if (!ScanNextDelta(punycode_begin, punycode_end, bias, i)) return nullptr; + + // Update bias as in RFC 3492 section 6.1. (We have inlined adapt.) + uint32_t delta = i - old_i; + delta /= (old_i == 0 ? kDamp : 2); + delta += delta/(num_chars + 1); + bias = 0; + while (delta > ((kBase - kTMin) * kTMax)/2) { + delta /= kBase - kTMin; + bias += kBase; + } + bias += ((kBase - kTMin + 1) * delta)/(delta + kSkew); + + // Back in section 6.2, compute the new code point and insertion index. + static_assert( + kMaxI + kMaxCodePoint < (uint64_t{1} << 32), + "Make kMaxI smaller or n 64 bits wide to prevent silent wraparound"); + n += i/(num_chars + 1); + i %= num_chars + 1; + + // To actually insert, we need to convert the code point n to UTF-8 and the + // character index i to an index into the byte stream emitted so far. First + // prepare the UTF-8 encoding for n, rejecting surrogates, overlarge values, + // and anything that won't fit into the remaining output storage. + Utf8ForCodePoint utf8_for_code_point(n); + if (!utf8_for_code_point.ok()) return nullptr; + if (total_utf8_bytes + utf8_for_code_point.length + 1 > out_size) { + return nullptr; + } + + // Now insert the new character into both our length map and the output. + uint32_t n_index = + utf8_lengths.InsertAndReturnSumOfPredecessors( + i, utf8_for_code_point.length); + std::memmove( + out_begin + n_index + utf8_for_code_point.length, out_begin + n_index, + total_utf8_bytes + 1 - n_index); + std::memcpy(out_begin + n_index, utf8_for_code_point.bytes, + utf8_for_code_point.length); + total_utf8_bytes += utf8_for_code_point.length; + ++num_chars; + + // Finally, advance to the next state before continuing. + ++i; + } + + return out_begin + total_utf8_bytes; +} + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/decode_rust_punycode.h b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/decode_rust_punycode.h new file mode 100644 index 0000000000..0ae53ff31e --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/decode_rust_punycode.h @@ -0,0 +1,55 @@ +// Copyright 2024 The Abseil Authors +// +// 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 +// +// https://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. + +#ifndef ABSL_DEBUGGING_INTERNAL_DECODE_RUST_PUNYCODE_H_ +#define ABSL_DEBUGGING_INTERNAL_DECODE_RUST_PUNYCODE_H_ + +#include "absl/base/config.h" +#include "absl/base/nullability.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +struct DecodeRustPunycodeOptions { + const char* punycode_begin; + const char* punycode_end; + char* out_begin; + char* out_end; +}; + +// Given Rust Punycode in `punycode_begin .. punycode_end`, writes the +// corresponding UTF-8 plaintext into `out_begin .. out_end`, followed by a NUL +// character, and returns a pointer to that final NUL on success. On failure +// returns a null pointer, and the contents of `out_begin .. out_end` are +// unspecified. +// +// Failure occurs in precisely these cases: +// - Any input byte does not match [0-9a-zA-Z_]. +// - The first input byte is an underscore, but no other underscore appears in +// the input. +// - The delta sequence does not represent a valid sequence of code-point +// insertions. +// - The plaintext would contain more than 256 code points. +// +// DecodeRustPunycode is async-signal-safe with bounded runtime and a small +// stack footprint, making it suitable for use in demangling Rust symbol names +// from a signal handler. +absl::Nullable DecodeRustPunycode(DecodeRustPunycodeOptions options); + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_DEBUGGING_INTERNAL_DECODE_RUST_PUNYCODE_H_ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle.cc b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle.cc index 7ce1471315..caac76367f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle.cc @@ -14,8 +14,6 @@ // For reference check out: // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling -// -// Note that we only have partial C++11 support yet. #include "absl/debugging/internal/demangle.h" @@ -23,6 +21,7 @@ #include #include #include +#include #include #include @@ -46,14 +45,16 @@ typedef struct { // List of operators from Itanium C++ ABI. static const AbbrevPair kOperatorList[] = { - // New has special syntax (not currently supported). + // New has special syntax. {"nw", "new", 0}, {"na", "new[]", 0}, - // Works except that the 'gs' prefix is not supported. + // Special-cased elsewhere to support the optional gs prefix. {"dl", "delete", 1}, {"da", "delete[]", 1}, + {"aw", "co_await", 1}, + {"ps", "+", 1}, // "positive" {"ng", "-", 1}, // "negative" {"ad", "&", 1}, // "address-of" @@ -191,9 +192,50 @@ typedef struct { int recursion_depth; // For stack exhaustion prevention. int steps; // Cap how much work we'll do, regardless of depth. ParseState parse_state; // Backtrackable state copied for most frames. + + // Conditionally compiled support for marking the position of the first + // construct Demangle couldn't parse. This preprocessor symbol is intended + // for use by Abseil demangler maintainers only; its behavior is not part of + // Abseil's public interface. +#ifdef ABSL_INTERNAL_DEMANGLE_RECORDS_HIGH_WATER_MARK + int high_water_mark; // Input position where parsing failed. + bool too_complex; // True if any guard.IsTooComplex() call returned true. +#endif } State; namespace { + +#ifdef ABSL_INTERNAL_DEMANGLE_RECORDS_HIGH_WATER_MARK +void UpdateHighWaterMark(State *state) { + if (state->high_water_mark < state->parse_state.mangled_idx) { + state->high_water_mark = state->parse_state.mangled_idx; + } +} + +void ReportHighWaterMark(State *state) { + // Write out the mangled name with the trouble point marked, provided that the + // output buffer is large enough and the mangled name did not hit a complexity + // limit (in which case the high water mark wouldn't point out an unparsable + // construct, only the point where a budget ran out). + const size_t input_length = std::strlen(state->mangled_begin); + if (input_length + 6 > static_cast(state->out_end_idx) || + state->too_complex) { + if (state->out_end_idx > 0) state->out[0] = '\0'; + return; + } + const size_t high_water_mark = static_cast(state->high_water_mark); + std::memcpy(state->out, state->mangled_begin, high_water_mark); + std::memcpy(state->out + high_water_mark, "--!--", 5); + std::memcpy(state->out + high_water_mark + 5, + state->mangled_begin + high_water_mark, + input_length - high_water_mark); + state->out[input_length + 5] = '\0'; +} +#else +void UpdateHighWaterMark(State *) {} +void ReportHighWaterMark(State *) {} +#endif + // Prevent deep recursion / stack exhaustion. // Also prevent unbounded handling of complex inputs. class ComplexityGuard { @@ -205,7 +247,7 @@ class ComplexityGuard { ~ComplexityGuard() { --state_->recursion_depth; } // 256 levels of recursion seems like a reasonable upper limit on depth. - // 128 is not enough to demagle synthetic tests from demangle_unittest.txt: + // 128 is not enough to demangle synthetic tests from demangle_unittest.txt: // "_ZaaZZZZ..." and "_ZaaZcvZcvZ..." static constexpr int kRecursionDepthLimit = 256; @@ -226,8 +268,14 @@ class ComplexityGuard { static constexpr int kParseStepsLimit = 1 << 17; bool IsTooComplex() const { - return state_->recursion_depth > kRecursionDepthLimit || - state_->steps > kParseStepsLimit; + if (state_->recursion_depth > kRecursionDepthLimit || + state_->steps > kParseStepsLimit) { +#ifdef ABSL_INTERNAL_DEMANGLE_RECORDS_HIGH_WATER_MARK + state_->too_complex = true; +#endif + return true; + } + return false; } private: @@ -274,6 +322,10 @@ static void InitState(State* state, state->out_end_idx = static_cast(out_size); state->recursion_depth = 0; state->steps = 0; +#ifdef ABSL_INTERNAL_DEMANGLE_RECORDS_HIGH_WATER_MARK + state->high_water_mark = 0; + state->too_complex = false; +#endif state->parse_state.mangled_idx = 0; state->parse_state.out_cur_idx = 0; @@ -295,6 +347,7 @@ static bool ParseOneCharToken(State *state, const char one_char_token) { if (guard.IsTooComplex()) return false; if (RemainingInput(state)[0] == one_char_token) { ++state->parse_state.mangled_idx; + UpdateHighWaterMark(state); return true; } return false; @@ -309,6 +362,7 @@ static bool ParseTwoCharToken(State *state, const char *two_char_token) { if (RemainingInput(state)[0] == two_char_token[0] && RemainingInput(state)[1] == two_char_token[1]) { state->parse_state.mangled_idx += 2; + UpdateHighWaterMark(state); return true; } return false; @@ -324,6 +378,7 @@ static bool ParseThreeCharToken(State *state, const char *three_char_token) { RemainingInput(state)[1] == three_char_token[1] && RemainingInput(state)[2] == three_char_token[2]) { state->parse_state.mangled_idx += 3; + UpdateHighWaterMark(state); return true; } return false; @@ -342,6 +397,7 @@ static bool ParseLongToken(State *state, const char *long_token) { if (RemainingInput(state)[i] != long_token[i]) return false; } state->parse_state.mangled_idx += i; + UpdateHighWaterMark(state); return true; } @@ -357,6 +413,7 @@ static bool ParseCharClass(State *state, const char *char_class) { for (; *p != '\0'; ++p) { if (RemainingInput(state)[0] == *p) { ++state->parse_state.mangled_idx; + UpdateHighWaterMark(state); return true; } } @@ -589,6 +646,7 @@ static bool ParseFloatNumber(State *state); static bool ParseSeqId(State *state); static bool ParseIdentifier(State *state, size_t length); static bool ParseOperatorName(State *state, int *arity); +static bool ParseConversionOperatorType(State *state); static bool ParseSpecialName(State *state); static bool ParseCallOffset(State *state); static bool ParseNVOffset(State *state); @@ -598,6 +656,7 @@ static bool ParseCtorDtorName(State *state); static bool ParseDecltype(State *state); static bool ParseType(State *state); static bool ParseCVQualifiers(State *state); +static bool ParseExtendedQualifier(State *state); static bool ParseBuiltinType(State *state); static bool ParseVendorExtendedType(State *state); static bool ParseFunctionType(State *state); @@ -618,6 +677,7 @@ static bool ParseUnionSelector(State* state); static bool ParseFunctionParam(State* state); static bool ParseBracedExpression(State *state); static bool ParseExpression(State *state); +static bool ParseInitializer(State *state); static bool ParseExprPrimary(State *state); static bool ParseExprCastValueAndTrailingE(State *state); static bool ParseQRequiresClauseExpr(State *state); @@ -821,8 +881,14 @@ static bool ParsePrefix(State *state) { // ::= [] // ::= [] // ::= [] +// ::= DC + E # C++17 structured binding +// ::= F # C++20 constrained friend +// ::= F # C++20 constrained friend // // is a GCC extension; see below. +// +// For the F notation for constrained friends, see +// https://github.com/itanium-cxx-abi/cxx-abi/issues/24#issuecomment-1491130332. static bool ParseUnqualifiedName(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; @@ -831,6 +897,23 @@ static bool ParseUnqualifiedName(State *state) { ParseUnnamedTypeName(state)) { return ParseAbiTags(state); } + + // DC + E + ParseState copy = state->parse_state; + if (ParseTwoCharToken(state, "DC") && OneOrMore(ParseSourceName, state) && + ParseOneCharToken(state, 'E')) { + return true; + } + state->parse_state = copy; + + // F + // F + if (ParseOneCharToken(state, 'F') && MaybeAppend(state, "friend ") && + (ParseSourceName(state) || ParseOperatorName(state, nullptr))) { + return true; + } + state->parse_state = copy; + return false; } @@ -957,6 +1040,7 @@ static bool ParseNumber(State *state, int *number_out) { } if (p != RemainingInput(state)) { // Conversion succeeded. state->parse_state.mangled_idx += p - RemainingInput(state); + UpdateHighWaterMark(state); if (number_out != nullptr) { // Note: possibly truncate "number". *number_out = static_cast(number); @@ -979,6 +1063,7 @@ static bool ParseFloatNumber(State *state) { } if (p != RemainingInput(state)) { // Conversion succeeded. state->parse_state.mangled_idx += p - RemainingInput(state); + UpdateHighWaterMark(state); return true; } return false; @@ -997,6 +1082,7 @@ static bool ParseSeqId(State *state) { } if (p != RemainingInput(state)) { // Conversion succeeded. state->parse_state.mangled_idx += p - RemainingInput(state); + UpdateHighWaterMark(state); return true; } return false; @@ -1015,11 +1101,13 @@ static bool ParseIdentifier(State *state, size_t length) { MaybeAppendWithLength(state, RemainingInput(state), length); } state->parse_state.mangled_idx += length; + UpdateHighWaterMark(state); return true; } // ::= nw, and other two letters cases // ::= cv # (cast) +// ::= li # C++11 user-defined literal // ::= v # vendor extended operator static bool ParseOperatorName(State *state, int *arity) { ComplexityGuard guard(state); @@ -1030,7 +1118,7 @@ static bool ParseOperatorName(State *state, int *arity) { // First check with "cv" (cast) case. ParseState copy = state->parse_state; if (ParseTwoCharToken(state, "cv") && MaybeAppend(state, "operator ") && - EnterNestedName(state) && ParseType(state) && + EnterNestedName(state) && ParseConversionOperatorType(state) && LeaveNestedName(state, copy.nest_level)) { if (arity != nullptr) { *arity = 1; @@ -1039,6 +1127,13 @@ static bool ParseOperatorName(State *state, int *arity) { } state->parse_state = copy; + // Then user-defined literals. + if (ParseTwoCharToken(state, "li") && MaybeAppend(state, "operator\"\" ") && + ParseSourceName(state)) { + return true; + } + state->parse_state = copy; + // Then vendor extended operators. if (ParseOneCharToken(state, 'v') && ParseDigit(state, arity) && ParseSourceName(state)) { @@ -1066,12 +1161,72 @@ static bool ParseOperatorName(State *state, int *arity) { } MaybeAppend(state, p->real_name); state->parse_state.mangled_idx += 2; + UpdateHighWaterMark(state); return true; } } return false; } +// ::= cv # (cast) +// +// The name of a conversion operator is the one place where cv-qualifiers, *, &, +// and other simple type combinators are expected to appear in our stripped-down +// demangling (elsewhere they appear in function signatures or template +// arguments, which we omit from the output). We make reasonable efforts to +// render simple cases accurately. +static bool ParseConversionOperatorType(State *state) { + ComplexityGuard guard(state); + if (guard.IsTooComplex()) return false; + ParseState copy = state->parse_state; + + // Scan pointers, const, and other easy mangling prefixes with postfix + // demanglings. Remember the range of input for later rescanning. + // + // See `ParseType` and the `switch` below for the meaning of each char. + const char* begin_simple_prefixes = RemainingInput(state); + while (ParseCharClass(state, "OPRCGrVK")) {} + const char* end_simple_prefixes = RemainingInput(state); + + // Emit the base type first. + if (!ParseType(state)) { + state->parse_state = copy; + return false; + } + + // Then rescan the easy type combinators in reverse order to emit their + // demanglings in the expected output order. + while (begin_simple_prefixes != end_simple_prefixes) { + switch (*--end_simple_prefixes) { + case 'P': + MaybeAppend(state, "*"); + break; + case 'R': + MaybeAppend(state, "&"); + break; + case 'O': + MaybeAppend(state, "&&"); + break; + case 'C': + MaybeAppend(state, " _Complex"); + break; + case 'G': + MaybeAppend(state, " _Imaginary"); + break; + case 'r': + MaybeAppend(state, " restrict"); + break; + case 'V': + MaybeAppend(state, " volatile"); + break; + case 'K': + MaybeAppend(state, " const"); + break; + } + } + return true; +} + // ::= TV // ::= TT // ::= TI @@ -1080,12 +1235,15 @@ static bool ParseOperatorName(State *state, int *arity) { // ::= TH # thread-local initialization // ::= Tc <(base) encoding> // ::= GV <(object) name> +// ::= GR <(object) name> [] _ // ::= T <(base) encoding> +// ::= GTt # transaction-safe entry point +// ::= TA # nontype template parameter object // G++ extensions: // ::= TC <(offset) number> _ <(base) type> // ::= TF // ::= TJ -// ::= GR +// ::= GR # without final _, perhaps an earlier form? // ::= GA // ::= Th <(base) encoding> // ::= Tv <(base) encoding> @@ -1095,6 +1253,8 @@ static bool ParseOperatorName(State *state, int *arity) { // thread_local feature. For these see: // // https://maskray.me/blog/2021-02-14-all-about-thread-local-storage +// +// For TA see https://github.com/itanium-cxx-abi/cxx-abi/issues/63. static bool ParseSpecialName(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; @@ -1152,12 +1312,30 @@ static bool ParseSpecialName(State *state) { } state->parse_state = copy; - if (ParseTwoCharToken(state, "GR") && ParseName(state)) { + // ::= GR <(object) name> [] _ # modern standard + // ::= GR <(object) name> # also recognized + if (ParseTwoCharToken(state, "GR")) { + MaybeAppend(state, "reference temporary for "); + if (!ParseName(state)) { + state->parse_state = copy; + return false; + } + const bool has_seq_id = ParseSeqId(state); + const bool has_underscore = ParseOneCharToken(state, '_'); + if (has_seq_id && !has_underscore) { + state->parse_state = copy; + return false; + } + return true; + } + + if (ParseTwoCharToken(state, "GA") && ParseEncoding(state)) { return true; } state->parse_state = copy; - if (ParseTwoCharToken(state, "GA") && ParseEncoding(state)) { + if (ParseThreeCharToken(state, "GTt") && + MaybeAppend(state, "transaction clone for ") && ParseEncoding(state)) { return true; } state->parse_state = copy; @@ -1167,6 +1345,18 @@ static bool ParseSpecialName(State *state) { return true; } state->parse_state = copy; + + if (ParseTwoCharToken(state, "TA")) { + bool append = state->parse_state.append; + DisableAppend(state); + if (ParseTemplateArg(state)) { + RestoreAppend(state, append); + MaybeAppend(state, "template parameter object"); + return true; + } + } + state->parse_state = copy; + return false; } @@ -1270,7 +1460,6 @@ static bool ParseDecltype(State *state) { // ::= O # rvalue reference-to (C++0x) // ::= C # complex pair (C 2000) // ::= G # imaginary (C 2000) -// ::= U # vendor extended type qualifier // ::= // ::= // ::= # note: just an alias for @@ -1281,7 +1470,8 @@ static bool ParseDecltype(State *state) { // ::= // ::= // ::= Dp # pack expansion of (C++0x) -// ::= Dv _ # GNU vector extension +// ::= Dv <(elements) number> _ # GNU vector extension +// ::= Dv <(bytes) expression> _ // ::= Dk # constrained auto // static bool ParseType(State *state) { @@ -1325,12 +1515,6 @@ static bool ParseType(State *state) { } state->parse_state = copy; - if (ParseOneCharToken(state, 'U') && ParseSourceName(state) && - ParseType(state)) { - return true; - } - state->parse_state = copy; - if (ParseBuiltinType(state) || ParseFunctionType(state) || ParseClassEnumType(state) || ParseArrayType(state) || ParsePointerToMemberType(state) || ParseDecltype(state) || @@ -1349,8 +1533,16 @@ static bool ParseType(State *state) { return true; } + // GNU vector extension Dv _ if (ParseTwoCharToken(state, "Dv") && ParseNumber(state, nullptr) && - ParseOneCharToken(state, '_')) { + ParseOneCharToken(state, '_') && ParseType(state)) { + return true; + } + state->parse_state = copy; + + // GNU vector extension Dv _ + if (ParseTwoCharToken(state, "Dv") && ParseExpression(state) && + ParseOneCharToken(state, '_') && ParseType(state)) { return true; } state->parse_state = copy; @@ -1366,30 +1558,110 @@ static bool ParseType(State *state) { return ParseLongToken(state, "_SUBSTPACK_"); } +// ::= * // ::= [r] [V] [K] +// // We don't allow empty to avoid infinite loop in // ParseType(). static bool ParseCVQualifiers(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; int num_cv_qualifiers = 0; + while (ParseExtendedQualifier(state)) ++num_cv_qualifiers; num_cv_qualifiers += ParseOneCharToken(state, 'r'); num_cv_qualifiers += ParseOneCharToken(state, 'V'); num_cv_qualifiers += ParseOneCharToken(state, 'K'); return num_cv_qualifiers > 0; } +// ::= U [] +static bool ParseExtendedQualifier(State *state) { + ComplexityGuard guard(state); + if (guard.IsTooComplex()) return false; + ParseState copy = state->parse_state; + + if (!ParseOneCharToken(state, 'U')) return false; + + bool append = state->parse_state.append; + DisableAppend(state); + if (!ParseSourceName(state)) { + state->parse_state = copy; + return false; + } + Optional(ParseTemplateArgs(state)); + RestoreAppend(state, append); + return true; +} + // ::= v, etc. # single-character builtin types // ::= // ::= Dd, etc. # two-character builtin types +// ::= DB ( | ) _ # _BitInt(N) +// ::= DU ( | ) _ # unsigned _BitInt(N) +// ::= DF _ # _FloatN (N bits) +// ::= DF x # _FloatNx +// ::= DF16b # std::bfloat16_t // // Not supported: -// ::= DF _ # _FloatN (N bits) -// -// NOTE: [I E] is a vendor extension (http://shortn/_FrINpH1XC5). +// ::= [DS] DA +// ::= [DS] DR +// because real implementations of N1169 fixed-point are scant. static bool ParseBuiltinType(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; + ParseState copy = state->parse_state; + + // DB ( | ) _ # _BitInt(N) + // DU ( | ) _ # unsigned _BitInt(N) + if (ParseTwoCharToken(state, "DB") || + (ParseTwoCharToken(state, "DU") && MaybeAppend(state, "unsigned "))) { + bool append = state->parse_state.append; + DisableAppend(state); + int number = -1; + if (!ParseNumber(state, &number) && !ParseExpression(state)) { + state->parse_state = copy; + return false; + } + RestoreAppend(state, append); + + if (!ParseOneCharToken(state, '_')) { + state->parse_state = copy; + return false; + } + + MaybeAppend(state, "_BitInt("); + if (number >= 0) { + MaybeAppendDecimal(state, number); + } else { + MaybeAppend(state, "?"); // the best we can do for dependent sizes + } + MaybeAppend(state, ")"); + return true; + } + + // DF _ # _FloatN + // DF x # _FloatNx + // DF16b # std::bfloat16_t + if (ParseTwoCharToken(state, "DF")) { + if (ParseThreeCharToken(state, "16b")) { + MaybeAppend(state, "std::bfloat16_t"); + return true; + } + int number = 0; + if (!ParseNumber(state, &number)) { + state->parse_state = copy; + return false; + } + MaybeAppend(state, "_Float"); + MaybeAppendDecimal(state, number); + if (ParseOneCharToken(state, 'x')) { + MaybeAppend(state, "x"); + return true; + } + if (ParseOneCharToken(state, '_')) return true; + state->parse_state = copy; + return false; + } for (const AbbrevPair *p = kBuiltinTypeList; p->abbrev != nullptr; ++p) { // Guaranteed only 1- or 2-character strings in kBuiltinTypeList. @@ -1407,22 +1679,15 @@ static bool ParseBuiltinType(State *state) { return ParseVendorExtendedType(state); } -// ::= u [I E] -// -// NOTE: [I E] is a vendor extension (http://shortn/_FrINpH1XC5). +// ::= u [] static bool ParseVendorExtendedType(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; ParseState copy = state->parse_state; - if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) { - copy = state->parse_state; - if (ParseOneCharToken(state, 'I') && ParseType(state) && - ParseOneCharToken(state, 'E')) { - return true; // ::= u I E - } - state->parse_state = copy; - return true; // ::= u + if (ParseOneCharToken(state, 'u') && ParseSourceName(state) && + Optional(ParseTemplateArgs(state))) { + return true; } state->parse_state = copy; return false; @@ -1457,7 +1722,7 @@ static bool ParseExceptionSpec(State *state) { } // ::= -// [exception-spec] F [Y] [] E +// [exception-spec] [Dx] F [Y] [] E // // ::= R | O static bool ParseFunctionType(State *state) { @@ -1465,6 +1730,7 @@ static bool ParseFunctionType(State *state) { if (guard.IsTooComplex()) return false; ParseState copy = state->parse_state; Optional(ParseExceptionSpec(state)); + Optional(ParseTwoCharToken(state, "Dx")); if (!ParseOneCharToken(state, 'F')) { state->parse_state = copy; return false; @@ -1521,10 +1787,23 @@ static bool ParseOverloadAttribute(State *state) { } // ::= +// ::= Ts # struct Name or class Name +// ::= Tu # union Name +// ::= Te # enum Name +// +// See http://shortn/_W3YrltiEd0. static bool ParseClassEnumType(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; - return ParseName(state); + ParseState copy = state->parse_state; + if (Optional(ParseTwoCharToken(state, "Ts") || + ParseTwoCharToken(state, "Tu") || + ParseTwoCharToken(state, "Te")) && + ParseName(state)) { + return true; + } + state->parse_state = copy; + return false; } // ::= A <(positive dimension) number> _ <(element) type> @@ -1832,6 +2111,13 @@ static bool ParseBaseUnresolvedName(State *state) { // // ::= [gs] sr + E // +// ::= sr St # nonstandard +// +// The last case is not part of the official grammar but has been observed in +// real-world examples that the GNU demangler (but not the LLVM demangler) is +// able to decode; see demangle_test.cc for one such symbol name. The shape +// sr St was inferred by closed-box testing of the GNU +// demangler. static bool ParseUnresolvedName(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; @@ -1865,6 +2151,12 @@ static bool ParseUnresolvedName(State *state) { } state->parse_state = copy; + if (ParseTwoCharToken(state, "sr") && ParseTwoCharToken(state, "St") && + ParseSimpleId(state) && ParseSimpleId(state)) { + return true; + } + state->parse_state = copy; + return false; } @@ -1962,6 +2254,8 @@ static bool ParseBracedExpression(State *state) { // ::= <1-ary operator-name> // ::= <2-ary operator-name> // ::= <3-ary operator-name> +// ::= pp_ # ++e; pp is e++ +// ::= mm_ # --e; mm is e-- // ::= cl + E // ::= cp * E # Clang-specific. // ::= so [] * [p] E @@ -1969,11 +2263,22 @@ static bool ParseBracedExpression(State *state) { // ::= cv _ * E # type (expr-list) // ::= tl * E // ::= il * E +// ::= [gs] nw * _ E +// ::= [gs] nw * _ +// ::= [gs] na * _ E +// ::= [gs] na * _ +// ::= [gs] dl +// ::= [gs] da // ::= dc // ::= sc // ::= cc // ::= rc +// ::= ti +// ::= te // ::= st +// ::= at +// ::= az +// ::= nx // ::= // ::= // ::= sZ @@ -1987,6 +2292,8 @@ static bool ParseBracedExpression(State *state) { // ::= fr // ::= fL // ::= fR +// ::= tw +// ::= tr // ::= sr // ::= sr // ::= u * E # vendor extension @@ -2008,6 +2315,15 @@ static bool ParseExpression(State *state) { } state->parse_state = copy; + // Preincrement and predecrement. Postincrement and postdecrement are handled + // by the operator-name logic later on. + if ((ParseThreeCharToken(state, "pp_") || + ParseThreeCharToken(state, "mm_")) && + ParseExpression(state)) { + return true; + } + state->parse_state = copy; + // Clang-specific "cp * E" // https://clang.llvm.org/doxygen/ItaniumMangle_8cpp_source.html#l04338 if (ParseTwoCharToken(state, "cp") && ParseSimpleId(state) && @@ -2048,6 +2364,28 @@ static bool ParseExpression(State *state) { } state->parse_state = copy; + // ::= [gs] nw * _ E + // ::= [gs] nw * _ + // ::= [gs] na * _ E + // ::= [gs] na * _ + if (Optional(ParseTwoCharToken(state, "gs")) && + (ParseTwoCharToken(state, "nw") || ParseTwoCharToken(state, "na")) && + ZeroOrMore(ParseExpression, state) && ParseOneCharToken(state, '_') && + ParseType(state) && + (ParseOneCharToken(state, 'E') || ParseInitializer(state))) { + return true; + } + state->parse_state = copy; + + // ::= [gs] dl + // ::= [gs] da + if (Optional(ParseTwoCharToken(state, "gs")) && + (ParseTwoCharToken(state, "dl") || ParseTwoCharToken(state, "da")) && + ParseExpression(state)) { + return true; + } + state->parse_state = copy; + // dynamic_cast, static_cast, const_cast, reinterpret_cast. // // ::= (dc | sc | cc | rc) @@ -2094,12 +2432,42 @@ static bool ParseExpression(State *state) { } state->parse_state = copy; + // typeid(type) + if (ParseTwoCharToken(state, "ti") && ParseType(state)) { + return true; + } + state->parse_state = copy; + + // typeid(expression) + if (ParseTwoCharToken(state, "te") && ParseExpression(state)) { + return true; + } + state->parse_state = copy; + // sizeof type if (ParseTwoCharToken(state, "st") && ParseType(state)) { return true; } state->parse_state = copy; + // alignof(type) + if (ParseTwoCharToken(state, "at") && ParseType(state)) { + return true; + } + state->parse_state = copy; + + // alignof(expression), a GNU extension + if (ParseTwoCharToken(state, "az") && ParseExpression(state)) { + return true; + } + state->parse_state = copy; + + // noexcept(expression) appearing as an expression in a dependent signature + if (ParseTwoCharToken(state, "nx") && ParseExpression(state)) { + return true; + } + state->parse_state = copy; + // sizeof...(pack) // // ::= sZ @@ -2140,6 +2508,15 @@ static bool ParseExpression(State *state) { } state->parse_state = copy; + // tw : throw e + if (ParseTwoCharToken(state, "tw") && ParseExpression(state)) { + return true; + } + state->parse_state = copy; + + // tr: throw (rethrows an exception from the handler that caught it) + if (ParseTwoCharToken(state, "tr")) return true; + // Object and pointer member access expressions. // // ::= (dt | pt) @@ -2193,6 +2570,32 @@ static bool ParseExpression(State *state) { return ParseUnresolvedName(state); } +// ::= pi * E +// ::= il * E +// +// The il ... E form is not in the ABI spec but is seen in practice for +// braced-init-lists in new-expressions, which are standard syntax from C++11 +// on. +static bool ParseInitializer(State *state) { + ComplexityGuard guard(state); + if (guard.IsTooComplex()) return false; + ParseState copy = state->parse_state; + + if (ParseTwoCharToken(state, "pi") && ZeroOrMore(ParseExpression, state) && + ParseOneCharToken(state, 'E')) { + return true; + } + state->parse_state = copy; + + if (ParseTwoCharToken(state, "il") && + ZeroOrMore(ParseBracedExpression, state) && + ParseOneCharToken(state, 'E')) { + return true; + } + state->parse_state = copy; + return false; +} + // ::= L <(value) number> E // ::= L <(value) float> E // ::= L E @@ -2289,8 +2692,15 @@ static bool ParseExprCastValueAndTrailingE(State *state) { } state->parse_state = copy; - if (ParseFloatNumber(state) && ParseOneCharToken(state, 'E')) { - return true; + if (ParseFloatNumber(state)) { + // for ordinary floating-point types + if (ParseOneCharToken(state, 'E')) return true; + + // _ for complex floating-point types + if (ParseOneCharToken(state, '_') && ParseFloatNumber(state) && + ParseOneCharToken(state, 'E')) { + return true; + } } state->parse_state = copy; @@ -2500,6 +2910,7 @@ static bool ParseSubstitution(State *state, bool accept_std) { MaybeAppend(state, p->real_name); } ++state->parse_state.mangled_idx; + UpdateHighWaterMark(state); return true; } } @@ -2525,10 +2936,13 @@ static bool ParseTopLevelMangledName(State *state) { MaybeAppend(state, RemainingInput(state)); return true; } + ReportHighWaterMark(state); return false; // Unconsumed suffix. } return true; } + + ReportHighWaterMark(state); return false; } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle.h b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle.h index e75d1473c7..cb0aba13e5 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle.h @@ -56,7 +56,8 @@ namespace debugging_internal { // // See the unit test for more examples. // -// Support for Rust mangled names is in development; see demangle_rust.h. +// Demangle also recognizes Rust mangled names by delegating the parsing of +// anything that starts with _R to DemangleRustSymbolEncoding (demangle_rust.h). // // Note: we might want to write demanglers for ABIs other than Itanium // C++ ABI in the future. diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.cc b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.cc index 06ee7a4bdc..4309bd849a 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.cc @@ -21,6 +21,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/debugging/internal/decode_rust_punycode.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -503,7 +504,7 @@ class RustSymbolParser { private: // Enumerates resumption points for ABSL_DEMANGLER_RECURSE calls. - enum ReturnAddress : std::uint8_t { + enum ReturnAddress : uint8_t { kInstantiatingCrate, kVendorSpecificSuffix, kIdentifierInUppercaseNamespace, @@ -585,9 +586,9 @@ class RustSymbolParser { // false if not everything fit into the output buffer. ABSL_MUST_USE_RESULT bool Emit(const char* token) { if (silence_depth_ > 0) return true; - const std::size_t token_length = std::strlen(token); - const std::size_t bytes_to_copy = token_length + 1; // token and final NUL - if (static_cast(out_end_ - out_) < bytes_to_copy) return false; + const size_t token_length = std::strlen(token); + const size_t bytes_to_copy = token_length + 1; // token and final NUL + if (static_cast(out_end_ - out_) < bytes_to_copy) return false; std::memcpy(out_, token, bytes_to_copy); out_ += token_length; return true; @@ -604,7 +605,7 @@ class RustSymbolParser { // because 999 > 256. The bound will remain correct even if future // maintenance changes the type of the disambiguator variable. char digits[3 * sizeof(disambiguator)] = {}; - std::size_t leading_digit_index = sizeof(digits) - 1; + size_t leading_digit_index = sizeof(digits) - 1; for (; disambiguator > 0; disambiguator /= 10) { digits[--leading_digit_index] = static_cast('0' + disambiguator % 10); @@ -710,13 +711,19 @@ class RustSymbolParser { int num_bytes = 0; if (!ParseDecimalNumber(num_bytes)) return false; (void)Eat('_'); // optional separator, needed if a digit follows + if (is_punycoded) { + DecodeRustPunycodeOptions options; + options.punycode_begin = &encoding_[pos_]; + options.punycode_end = &encoding_[pos_] + num_bytes; + options.out_begin = out_; + options.out_end = out_end_; + out_ = DecodeRustPunycode(options); + if (out_ == nullptr) return false; + pos_ += static_cast(num_bytes); + } // Emit the beginnings of braced forms like {shim:vtable#0}. - if (uppercase_namespace == '\0') { - // Decoding of Punycode is not yet implemented. For now we emit - // "{Punycode ...}" with the raw encoding inside. - if (is_punycoded && !Emit("{Punycode ")) return false; - } else { + if (uppercase_namespace != '\0') { switch (uppercase_namespace) { case 'C': if (!Emit("{closure")) return false; @@ -732,24 +739,24 @@ class RustSymbolParser { } // Emit the name itself. - for (int i = 0; i < num_bytes; ++i) { - const char c = Take(); - if (!IsIdentifierChar(c) && - // The spec gives toolchains the choice of Punycode or raw UTF-8 for - // identifiers containing code points above 0x7f, so accept bytes with - // the high bit set if this is not a u... encoding. - (is_punycoded || (c & 0x80) == 0)) { - return false; + if (!is_punycoded) { + for (int i = 0; i < num_bytes; ++i) { + const char c = Take(); + if (!IsIdentifierChar(c) && + // The spec gives toolchains the choice of Punycode or raw UTF-8 for + // identifiers containing code points above 0x7f, so accept bytes + // with the high bit set. + (c & 0x80) == 0) { + return false; + } + if (!EmitChar(c)) return false; } - if (!EmitChar(c)) return false; } - // Emit the endings of braced forms: "#42}" or "}". + // Emit the endings of braced forms, e.g., "#42}". if (uppercase_namespace != '\0') { if (!EmitChar('#')) return false; if (!EmitDisambiguator(disambiguator)) return false; - } - if (uppercase_namespace != '\0' || is_punycoded) { if (!EmitChar('}')) return false; } @@ -909,7 +916,7 @@ class RustSymbolParser { } // namespace bool DemangleRustSymbolEncoding(const char* mangled, char* out, - std::size_t out_size) { + size_t out_size) { return RustSymbolParser(mangled, out, out + out_size).Parse(); } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.h b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.h index 1c19815f24..94a9aecb5e 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/demangle_rust.h @@ -32,11 +32,8 @@ namespace debugging_internal { // DemangleRustSymbolEncoding is async-signal-safe and runs in bounded C++ // call-stack space. It is suitable for symbolizing stack traces in a signal // handler. -// -// The demangling logic is under development; search for "not yet implemented" -// in the .cc file to see where the gaps are. bool DemangleRustSymbolEncoding(const char* mangled, char* out, - std::size_t out_size); + size_t out_size); } // namespace debugging_internal ABSL_NAMESPACE_END diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc index 42dcd3cde9..2c16830983 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc @@ -20,8 +20,11 @@ #ifdef ABSL_HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h #include + #include #include +#include + #include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" @@ -86,20 +89,14 @@ ElfMemImage::ElfMemImage(const void *base) { Init(base); } -int ElfMemImage::GetNumSymbols() const { - if (!hash_) { - return 0; - } - // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash - return static_cast(hash_[1]); -} +uint32_t ElfMemImage::GetNumSymbols() const { return num_syms_; } -const ElfW(Sym) *ElfMemImage::GetDynsym(int index) const { +const ElfW(Sym) * ElfMemImage::GetDynsym(uint32_t index) const { ABSL_RAW_CHECK(index < GetNumSymbols(), "index out of range"); return dynsym_ + index; } -const ElfW(Versym) *ElfMemImage::GetVersym(int index) const { +const ElfW(Versym) *ElfMemImage::GetVersym(uint32_t index) const { ABSL_RAW_CHECK(index < GetNumSymbols(), "index out of range"); return versym_ + index; } @@ -154,7 +151,7 @@ void ElfMemImage::Init(const void *base) { dynstr_ = nullptr; versym_ = nullptr; verdef_ = nullptr; - hash_ = nullptr; + num_syms_ = 0; strsize_ = 0; verdefnum_ = 0; // Sentinel: PT_LOAD .p_vaddr can't possibly be this. @@ -219,12 +216,17 @@ void ElfMemImage::Init(const void *base) { base_as_char - reinterpret_cast(link_base_); ElfW(Dyn)* dynamic_entry = reinterpret_cast( static_cast(dynamic_program_header->p_vaddr) + relocation); + uint32_t *sysv_hash = nullptr; + uint32_t *gnu_hash = nullptr; for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) { const auto value = static_cast(dynamic_entry->d_un.d_val) + relocation; switch (dynamic_entry->d_tag) { case DT_HASH: - hash_ = reinterpret_cast(value); + sysv_hash = reinterpret_cast(value); + break; + case DT_GNU_HASH: + gnu_hash = reinterpret_cast(value); break; case DT_SYMTAB: dynsym_ = reinterpret_cast(value); @@ -249,13 +251,38 @@ void ElfMemImage::Init(const void *base) { break; } } - if (!hash_ || !dynsym_ || !dynstr_ || !versym_ || + if ((!sysv_hash && !gnu_hash) || !dynsym_ || !dynstr_ || !versym_ || !verdef_ || !verdefnum_ || !strsize_) { assert(false); // invalid VDSO // Mark this image as not present. Can not recur infinitely. Init(nullptr); return; } + if (sysv_hash) { + num_syms_ = sysv_hash[1]; + } else { + assert(gnu_hash); + // Compute the number of symbols for DT_GNU_HASH, which is specified by + // https://sourceware.org/gnu-gabi/program-loading-and-dynamic-linking.txt + uint32_t nbuckets = gnu_hash[0]; + // The buckets array is located after the header (4 uint32) and the bloom + // filter (size_t array of gnu_hash[2] elements). + uint32_t *buckets = gnu_hash + 4 + sizeof(size_t) / 4 * gnu_hash[2]; + // Find the chain of the last non-empty bucket. + uint32_t idx = 0; + for (uint32_t i = nbuckets; i > 0;) { + idx = buckets[--i]; + if (idx != 0) break; + } + if (idx != 0) { + // Find the last element of the chain, which has an odd value. + // Add one to get the number of symbols. + uint32_t *chain = buckets + nbuckets - gnu_hash[1]; + while (chain[idx++] % 2 == 0) { + } + } + num_syms_ = idx; + } } bool ElfMemImage::LookupSymbol(const char *name, @@ -300,9 +327,9 @@ bool ElfMemImage::LookupSymbolByAddress(const void *address, return false; } -ElfMemImage::SymbolIterator::SymbolIterator(const void *const image, int index) - : index_(index), image_(image) { -} +ElfMemImage::SymbolIterator::SymbolIterator(const void *const image, + uint32_t index) + : index_(index), image_(image) {} const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->() const { return &info_; @@ -335,7 +362,7 @@ ElfMemImage::SymbolIterator ElfMemImage::end() const { return SymbolIterator(this, GetNumSymbols()); } -void ElfMemImage::SymbolIterator::Update(int increment) { +void ElfMemImage::SymbolIterator::Update(uint32_t increment) { const ElfMemImage *image = reinterpret_cast(image_); ABSL_RAW_CHECK(image->IsPresent() || increment == 0, ""); if (!image->IsPresent()) { diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h index e7fe6ab06e..19c4952e2f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h @@ -22,6 +22,7 @@ // Including this will define the __GLIBC__ macro if glibc is being // used. #include +#include #include "absl/base/config.h" @@ -82,10 +83,10 @@ class ElfMemImage { bool operator!=(const SymbolIterator &rhs) const; bool operator==(const SymbolIterator &rhs) const; private: - SymbolIterator(const void *const image, int index); - void Update(int incr); + SymbolIterator(const void *const image, uint32_t index); + void Update(uint32_t incr); SymbolInfo info_; - int index_; + uint32_t index_; const void *const image_; }; @@ -94,14 +95,14 @@ class ElfMemImage { void Init(const void *base); bool IsPresent() const { return ehdr_ != nullptr; } const ElfW(Phdr)* GetPhdr(int index) const; - const ElfW(Sym)* GetDynsym(int index) const; - const ElfW(Versym)* GetVersym(int index) const; + const ElfW(Sym) * GetDynsym(uint32_t index) const; + const ElfW(Versym)* GetVersym(uint32_t index) const; const ElfW(Verdef)* GetVerdef(int index) const; const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const; const char* GetDynstr(ElfW(Word) offset) const; const void* GetSymAddr(const ElfW(Sym) *sym) const; const char* GetVerstr(ElfW(Word) offset) const; - int GetNumSymbols() const; + uint32_t GetNumSymbols() const; SymbolIterator begin() const; SymbolIterator end() const; @@ -124,8 +125,8 @@ class ElfMemImage { const ElfW(Sym) *dynsym_; const ElfW(Versym) *versym_; const ElfW(Verdef) *verdef_; - const ElfW(Word) *hash_; const char *dynstr_; + uint32_t num_syms_; size_t strsize_; size_t verdefnum_; ElfW(Addr) link_base_; // Link-time base (p_vaddr of first PT_LOAD). diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/utf8_for_code_point.cc b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/utf8_for_code_point.cc new file mode 100644 index 0000000000..658a3b513b --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/utf8_for_code_point.cc @@ -0,0 +1,70 @@ +// Copyright 2024 The Abseil Authors +// +// 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 +// +// https://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. + +#include "absl/debugging/internal/utf8_for_code_point.h" + +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { +namespace { + +// UTF-8 encoding bounds. +constexpr uint32_t kMinSurrogate = 0xd800, kMaxSurrogate = 0xdfff; +constexpr uint32_t kMax1ByteCodePoint = 0x7f; +constexpr uint32_t kMax2ByteCodePoint = 0x7ff; +constexpr uint32_t kMax3ByteCodePoint = 0xffff; +constexpr uint32_t kMaxCodePoint = 0x10ffff; + +} // namespace + +Utf8ForCodePoint::Utf8ForCodePoint(uint64_t code_point) { + if (code_point <= kMax1ByteCodePoint) { + length = 1; + bytes[0] = static_cast(code_point); + return; + } + + if (code_point <= kMax2ByteCodePoint) { + length = 2; + bytes[0] = static_cast(0xc0 | (code_point >> 6)); + bytes[1] = static_cast(0x80 | (code_point & 0x3f)); + return; + } + + if (kMinSurrogate <= code_point && code_point <= kMaxSurrogate) return; + + if (code_point <= kMax3ByteCodePoint) { + length = 3; + bytes[0] = static_cast(0xe0 | (code_point >> 12)); + bytes[1] = static_cast(0x80 | ((code_point >> 6) & 0x3f)); + bytes[2] = static_cast(0x80 | (code_point & 0x3f)); + return; + } + + if (code_point > kMaxCodePoint) return; + + length = 4; + bytes[0] = static_cast(0xf0 | (code_point >> 18)); + bytes[1] = static_cast(0x80 | ((code_point >> 12) & 0x3f)); + bytes[2] = static_cast(0x80 | ((code_point >> 6) & 0x3f)); + bytes[3] = static_cast(0x80 | (code_point & 0x3f)); +} + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/utf8_for_code_point.h b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/utf8_for_code_point.h new file mode 100644 index 0000000000..f23cde6d95 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/absl/debugging/internal/utf8_for_code_point.h @@ -0,0 +1,47 @@ +// Copyright 2024 The Abseil Authors +// +// 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 +// +// https://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. + +#ifndef ABSL_DEBUGGING_INTERNAL_UTF8_FOR_CODE_POINT_H_ +#define ABSL_DEBUGGING_INTERNAL_UTF8_FOR_CODE_POINT_H_ + +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +struct Utf8ForCodePoint { + // Converts a Unicode code point to the corresponding UTF-8 byte sequence. + // Async-signal-safe to support use in symbolizing stack traces from a signal + // handler. + explicit Utf8ForCodePoint(uint64_t code_point); + + // Returns true if the constructor's code_point argument was valid. + bool ok() const { return length != 0; } + + // If code_point was in range, then 1 <= length <= 4, and the UTF-8 encoding + // is found in bytes[0 .. (length - 1)]. If code_point was invalid, then + // length == 0. In either case, the contents of bytes[length .. 3] are + // unspecified. + char bytes[4] = {}; + uint32_t length = 0; +}; + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_DEBUGGING_INTERNAL_UTF8_FOR_CODE_POINT_H_ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.bazel index cc513a0904..7a8ec7e6f4 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.bazel @@ -390,6 +390,7 @@ cc_test( ":flag", ":flag_internal", ":marshalling", + ":parse", ":reflection", "//absl/base:core_headers", "//absl/base:malloc_internal", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.gn index 660f600fb8..34a104bbfb 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/absl/flags/BUILD.gn @@ -239,6 +239,7 @@ absl_test("flag_test") { ":flag", ":flag_internal", ":marshalling", + ":parse", ":reflection", "//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/base:malloc_internal", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/flags/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/flags/CMakeLists.txt index 48cc83256e..7376d117e2 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/flags/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/flags/CMakeLists.txt @@ -340,6 +340,7 @@ absl_cc_test( absl::flags_config absl::flags_internal absl::flags_marshalling + absl::flags_parse absl::flags_reflection absl::int128 absl::optional diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/flags/internal/flag.cc b/naiveproxy/src/third_party/abseil-cpp/absl/flags/internal/flag.cc index 65d0e58f84..981f19fdb8 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/flags/internal/flag.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/flags/internal/flag.cc @@ -22,14 +22,17 @@ #include #include +#include #include -#include #include #include +#include +#include "absl/base/attributes.h" #include "absl/base/call_once.h" #include "absl/base/casts.h" #include "absl/base/config.h" +#include "absl/base/const_init.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/optimization.h" #include "absl/flags/config.h" @@ -44,10 +47,9 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace flags_internal { -// The help message indicating that the commandline flag has been -// 'stripped'. It will not show up when doing "-help" and its -// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1 -// before including absl/flags/flag.h +// The help message indicating that the commandline flag has been stripped. It +// will not show up when doing "-help" and its variants. The flag is stripped +// if ABSL_FLAGS_STRIP_HELP is set to 1 before including absl/flags/flag.h const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001"; namespace { @@ -78,8 +80,31 @@ class MutexRelock { absl::Mutex& mu_; }; +// This is a freelist of leaked flag values and guard for its access. +// When we can't guarantee it is safe to reuse the memory for flag values, +// we move the memory to the freelist where it lives indefinitely, so it can +// still be safely accessed. This also prevents leak checkers from complaining +// about the leaked memory that can no longer be accessed through any pointer. +ABSL_CONST_INIT absl::Mutex s_freelist_guard(absl::kConstInit); +ABSL_CONST_INIT std::vector* s_freelist = nullptr; + +void AddToFreelist(void* p) { + absl::MutexLock l(&s_freelist_guard); + if (!s_freelist) { + s_freelist = new std::vector; + } + s_freelist->push_back(p); +} + } // namespace +/////////////////////////////////////////////////////////////////////////////// + +uint64_t NumLeakedFlagValues() { + absl::MutexLock l(&s_freelist_guard); + return s_freelist == nullptr ? 0u : s_freelist->size(); +} + /////////////////////////////////////////////////////////////////////////////// // Persistent state of the flag data. @@ -97,7 +122,7 @@ class FlagState : public flags_internal::FlagStateInterface { counter_(counter) {} ~FlagState() override { - if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer && + if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kHeapAllocated && flag_impl_.ValueStorageKind() != FlagValueStorageKind::kSequenceLocked) return; flags_internal::Delete(flag_impl_.op_, value_.heap_allocated); @@ -140,6 +165,33 @@ void DynValueDeleter::operator()(void* ptr) const { Delete(op, ptr); } +MaskedPointer::MaskedPointer(ptr_t rhs, bool is_candidate) : ptr_(rhs) { + if (is_candidate) { + ApplyMask(kUnprotectedReadCandidate); + } +} + +bool MaskedPointer::IsUnprotectedReadCandidate() const { + return CheckMask(kUnprotectedReadCandidate); +} + +bool MaskedPointer::HasBeenRead() const { return CheckMask(kHasBeenRead); } + +void MaskedPointer::Set(FlagOpFn op, const void* src, bool is_candidate) { + flags_internal::Copy(op, src, Ptr()); + if (is_candidate) { + ApplyMask(kUnprotectedReadCandidate); + } +} +void MaskedPointer::MarkAsRead() { ApplyMask(kHasBeenRead); } + +void MaskedPointer::ApplyMask(mask_t mask) { + ptr_ = reinterpret_cast(reinterpret_cast(ptr_) | mask); +} +bool MaskedPointer::CheckMask(mask_t mask) const { + return (reinterpret_cast(ptr_) & mask) != 0; +} + void FlagImpl::Init() { new (&data_guard_) absl::Mutex; @@ -174,11 +226,16 @@ void FlagImpl::Init() { (*default_value_.gen_func)(AtomicBufferValue()); break; } - case FlagValueStorageKind::kAlignedBuffer: + case FlagValueStorageKind::kHeapAllocated: // For this storage kind the default_value_ always points to gen_func // during initialization. assert(def_kind == FlagDefaultKind::kGenFunc); - (*default_value_.gen_func)(AlignedBufferValue()); + // Flag value initially points to the internal buffer. + MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire); + (*default_value_.gen_func)(ptr_value.Ptr()); + // Default value is a candidate for an unprotected read. + PtrStorage().store(MaskedPointer(ptr_value.Ptr(), true), + std::memory_order_release); break; } seq_lock_.MarkInitialized(); @@ -234,7 +291,7 @@ std::unique_ptr FlagImpl::MakeInitValue() const { return {res, DynValueDeleter{op_}}; } -void FlagImpl::StoreValue(const void* src) { +void FlagImpl::StoreValue(const void* src, ValueSource source) { switch (ValueStorageKind()) { case FlagValueStorageKind::kValueAndInitBit: case FlagValueStorageKind::kOneWordAtomic: { @@ -249,8 +306,27 @@ void FlagImpl::StoreValue(const void* src) { seq_lock_.Write(AtomicBufferValue(), src, Sizeof(op_)); break; } - case FlagValueStorageKind::kAlignedBuffer: - Copy(op_, src, AlignedBufferValue()); + case FlagValueStorageKind::kHeapAllocated: + MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire); + + if (ptr_value.IsUnprotectedReadCandidate() && ptr_value.HasBeenRead()) { + // If current value is a candidate for an unprotected read and if it was + // already read at least once, follow up reads (if any) are done without + // mutex protection. We can't guarantee it is safe to reuse this memory + // since it may have been accessed by another thread concurrently, so + // instead we move the memory to a freelist so it can still be safely + // accessed, and allocate a new one for the new value. + AddToFreelist(ptr_value.Ptr()); + ptr_value = MaskedPointer(Clone(op_, src), source == kCommandLine); + } else { + // Current value either was set programmatically or was never read. + // We can reuse the memory since all accesses to this value (if any) + // were protected by mutex. That said, if a new value comes from command + // line it now becomes a candidate for an unprotected read. + ptr_value.Set(op_, src, source == kCommandLine); + } + + PtrStorage().store(ptr_value, std::memory_order_release); seq_lock_.IncrementModificationCount(); break; } @@ -305,9 +381,10 @@ std::string FlagImpl::CurrentValue() const { ReadSequenceLockedData(cloned.get()); return flags_internal::Unparse(op_, cloned.get()); } - case FlagValueStorageKind::kAlignedBuffer: { + case FlagValueStorageKind::kHeapAllocated: { absl::MutexLock l(guard); - return flags_internal::Unparse(op_, AlignedBufferValue()); + return flags_internal::Unparse( + op_, PtrStorage().load(std::memory_order_acquire).Ptr()); } } @@ -370,10 +447,12 @@ std::unique_ptr FlagImpl::SaveState() { return absl::make_unique(*this, cloned, modified, on_command_line, ModificationCount()); } - case FlagValueStorageKind::kAlignedBuffer: { + case FlagValueStorageKind::kHeapAllocated: { return absl::make_unique( - *this, flags_internal::Clone(op_, AlignedBufferValue()), modified, - on_command_line, ModificationCount()); + *this, + flags_internal::Clone( + op_, PtrStorage().load(std::memory_order_acquire).Ptr()), + modified, on_command_line, ModificationCount()); } } return nullptr; @@ -388,11 +467,11 @@ bool FlagImpl::RestoreState(const FlagState& flag_state) { switch (ValueStorageKind()) { case FlagValueStorageKind::kValueAndInitBit: case FlagValueStorageKind::kOneWordAtomic: - StoreValue(&flag_state.value_.one_word); + StoreValue(&flag_state.value_.one_word, kProgrammaticChange); break; case FlagValueStorageKind::kSequenceLocked: - case FlagValueStorageKind::kAlignedBuffer: - StoreValue(flag_state.value_.heap_allocated); + case FlagValueStorageKind::kHeapAllocated: + StoreValue(flag_state.value_.heap_allocated, kProgrammaticChange); break; } @@ -411,11 +490,6 @@ StorageT* FlagImpl::OffsetValue() const { return reinterpret_cast(p + offset); } -void* FlagImpl::AlignedBufferValue() const { - assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer); - return OffsetValue(); -} - std::atomic* FlagImpl::AtomicBufferValue() const { assert(ValueStorageKind() == FlagValueStorageKind::kSequenceLocked); return OffsetValue>(); @@ -427,6 +501,11 @@ std::atomic& FlagImpl::OneWordValue() const { return OffsetValue()->value; } +std::atomic& FlagImpl::PtrStorage() const { + assert(ValueStorageKind() == FlagValueStorageKind::kHeapAllocated); + return OffsetValue()->value; +} + // Attempts to parse supplied `value` string using parsing routine in the `flag` // argument. If parsing successful, this function replaces the dst with newly // parsed value. In case if any error is encountered in either step, the error @@ -460,9 +539,17 @@ void FlagImpl::Read(void* dst) const { ReadSequenceLockedData(dst); break; } - case FlagValueStorageKind::kAlignedBuffer: { + case FlagValueStorageKind::kHeapAllocated: { absl::MutexLock l(guard); - flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst); + MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire); + + flags_internal::CopyConstruct(op_, ptr_value.Ptr(), dst); + + // For unprotected read candidates, mark that the value as has been read. + if (ptr_value.IsUnprotectedReadCandidate() && !ptr_value.HasBeenRead()) { + ptr_value.MarkAsRead(); + PtrStorage().store(ptr_value, std::memory_order_release); + } break; } } @@ -513,7 +600,7 @@ void FlagImpl::Write(const void* src) { } } - StoreValue(src); + StoreValue(src, kProgrammaticChange); } // Sets the value of the flag based on specified string `value`. If the flag @@ -534,7 +621,7 @@ bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode, auto tentative_value = TryParse(value, err); if (!tentative_value) return false; - StoreValue(tentative_value.get()); + StoreValue(tentative_value.get(), source); if (source == kCommandLine) { on_command_line_ = true; @@ -555,7 +642,7 @@ bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode, auto tentative_value = TryParse(value, err); if (!tentative_value) return false; - StoreValue(tentative_value.get()); + StoreValue(tentative_value.get(), source); break; } case SET_FLAGS_DEFAULT: { @@ -573,7 +660,7 @@ bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode, if (!modified_) { // Need to set both default value *and* current, in this case. - StoreValue(default_value_.dynamic_value); + StoreValue(default_value_.dynamic_value, source); modified_ = false; } break; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/flags/internal/flag.h b/naiveproxy/src/third_party/abseil-cpp/absl/flags/internal/flag.h index 602531b1b3..a0be31d93a 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/flags/internal/flag.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/flags/internal/flag.h @@ -295,11 +295,8 @@ constexpr FlagDefaultArg DefaultArg(char) { } /////////////////////////////////////////////////////////////////////////////// -// Flag current value auxiliary structs. - -constexpr int64_t UninitializedFlagValue() { - return static_cast(0xababababababababll); -} +// Flag storage selector traits. Each trait indicates what kind of storage kind +// to use for the flag value. template using FlagUseValueAndInitBitStorage = @@ -321,9 +318,11 @@ enum class FlagValueStorageKind : uint8_t { kValueAndInitBit = 0, kOneWordAtomic = 1, kSequenceLocked = 2, - kAlignedBuffer = 3, + kHeapAllocated = 3, }; +// This constexpr function returns the storage kind for the given flag value +// type. template static constexpr FlagValueStorageKind StorageKind() { return FlagUseValueAndInitBitStorage::value @@ -332,14 +331,24 @@ static constexpr FlagValueStorageKind StorageKind() { ? FlagValueStorageKind::kOneWordAtomic : FlagUseSequenceLockStorage::value ? FlagValueStorageKind::kSequenceLocked - : FlagValueStorageKind::kAlignedBuffer; + : FlagValueStorageKind::kHeapAllocated; } +// This is a base class for the storage classes used by kOneWordAtomic and +// kValueAndInitBit storage kinds. It literally just stores the one word value +// as an atomic. By default, it is initialized to a magic value that is unlikely +// a valid value for the flag value type. struct FlagOneWordValue { + constexpr static int64_t Uninitialized() { + return static_cast(0xababababababababll); + } + + constexpr FlagOneWordValue() : value(Uninitialized()) {} constexpr explicit FlagOneWordValue(int64_t v) : value(v) {} std::atomic value; }; +// This class represents a memory layout used by kValueAndInitBit storage kind. template struct alignas(8) FlagValueAndInitBit { T value; @@ -348,16 +357,91 @@ struct alignas(8) FlagValueAndInitBit { uint8_t init; }; +// This class implements an aligned pointer with two options stored via masks +// in unused bits of the pointer value (due to alignment requirement). +// - IsUnprotectedReadCandidate - indicates that the value can be switched to +// unprotected read without a lock. +// - HasBeenRead - indicates that the value has been read at least once. +// - AllowsUnprotectedRead - combination of the two options above and indicates +// that the value can now be read without a lock. +// Further details of these options and their use is covered in the description +// of the FlagValue specialization. +class MaskedPointer { + public: + using mask_t = uintptr_t; + using ptr_t = void*; + + static constexpr int RequiredAlignment() { return 4; } + + constexpr explicit MaskedPointer(ptr_t rhs) : ptr_(rhs) {} + MaskedPointer(ptr_t rhs, bool is_candidate); + + void* Ptr() const { + return reinterpret_cast(reinterpret_cast(ptr_) & + kPtrValueMask); + } + bool AllowsUnprotectedRead() const { + return (reinterpret_cast(ptr_) & kAllowsUnprotectedRead) == + kAllowsUnprotectedRead; + } + bool IsUnprotectedReadCandidate() const; + bool HasBeenRead() const; + + void Set(FlagOpFn op, const void* src, bool is_candidate); + void MarkAsRead(); + + private: + // Masks + // Indicates that the flag value either default or originated from command + // line. + static constexpr mask_t kUnprotectedReadCandidate = 0x1u; + // Indicates that flag has been read. + static constexpr mask_t kHasBeenRead = 0x2u; + static constexpr mask_t kAllowsUnprotectedRead = + kUnprotectedReadCandidate | kHasBeenRead; + static constexpr mask_t kPtrValueMask = ~kAllowsUnprotectedRead; + + void ApplyMask(mask_t mask); + bool CheckMask(mask_t mask) const; + + ptr_t ptr_; +}; + +// This class implements a type erased storage of the heap allocated flag value. +// It is used as a base class for the storage class for kHeapAllocated storage +// kind. The initial_buffer is expected to have an alignment of at least +// MaskedPointer::RequiredAlignment(), so that the bits used by the +// MaskedPointer to store masks are set to 0. This guarantees that value starts +// in an uninitialized state. +struct FlagMaskedPointerValue { + constexpr explicit FlagMaskedPointerValue(MaskedPointer::ptr_t initial_buffer) + : value(MaskedPointer(initial_buffer)) {} + + std::atomic value; +}; + +// This is the forward declaration for the template that represents a storage +// for the flag values. This template is expected to be explicitly specialized +// for each storage kind and it does not have a generic default +// implementation. template ()> struct FlagValue; +// This specialization represents the storage of flag values types with the +// kValueAndInitBit storage kind. It is based on the FlagOneWordValue class +// and relies on memory layout in FlagValueAndInitBit to indicate that the +// value has been initialized or not. template struct FlagValue : FlagOneWordValue { constexpr FlagValue() : FlagOneWordValue(0) {} bool Get(const SequenceLock&, T& dst) const { int64_t storage = value.load(std::memory_order_acquire); if (ABSL_PREDICT_FALSE(storage == 0)) { + // This assert is to ensure that the initialization inside FlagImpl::Init + // is able to set init member correctly. + static_assert(offsetof(FlagValueAndInitBit, init) == sizeof(T), + "Unexpected memory layout of FlagValueAndInitBit"); return false; } dst = absl::bit_cast>(storage).value; @@ -365,12 +449,16 @@ struct FlagValue : FlagOneWordValue { } }; +// This specialization represents the storage of flag values types with the +// kOneWordAtomic storage kind. It is based on the FlagOneWordValue class +// and relies on the magic uninitialized state of default constructed instead of +// FlagOneWordValue to indicate that the value has been initialized or not. template struct FlagValue : FlagOneWordValue { - constexpr FlagValue() : FlagOneWordValue(UninitializedFlagValue()) {} + constexpr FlagValue() : FlagOneWordValue() {} bool Get(const SequenceLock&, T& dst) const { int64_t one_word_val = value.load(std::memory_order_acquire); - if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) { + if (ABSL_PREDICT_FALSE(one_word_val == FlagOneWordValue::Uninitialized())) { return false; } std::memcpy(&dst, static_cast(&one_word_val), sizeof(T)); @@ -378,6 +466,12 @@ struct FlagValue : FlagOneWordValue { } }; +// This specialization represents the storage of flag values types with the +// kSequenceLocked storage kind. This storage is used by trivially copyable +// types with size greater than 8 bytes. This storage relies on uninitialized +// state of the SequenceLock to indicate that the value has been initialized or +// not. This storage also provides lock-free read access to the underlying +// value once it is initialized. template struct FlagValue { bool Get(const SequenceLock& lock, T& dst) const { @@ -391,11 +485,62 @@ struct FlagValue { std::atomic) std::atomic value_words[kNumWords]; }; +// This specialization represents the storage of flag values types with the +// kHeapAllocated storage kind. This is a storage of last resort and is used +// if none of other storage kinds are applicable. +// +// Generally speaking the values with this storage kind can't be accessed +// atomically and thus can't be read without holding a lock. If we would ever +// want to avoid the lock, we'd need to leak the old value every time new flag +// value is being set (since we are in danger of having a race condition +// otherwise). +// +// Instead of doing that, this implementation attempts to cater to some common +// use cases by allowing at most 2 values to be leaked - default value and +// value set from the command line. +// +// This specialization provides an initial buffer for the first flag value. This +// is where the default value is going to be stored. We attempt to reuse this +// buffer if possible, including storing the value set from the command line +// there. +// +// As long as we only read this value, we can access it without a lock (in +// practice we still use the lock for the very first read to be able set +// "has been read" option on this flag). +// +// If flag is specified on the command line we store the parsed value either +// in the internal buffer (if the default value never been read) or we leak the +// default value and allocate the new storage for the parse value. This value is +// also a candidate for an unprotected read. If flag is set programmatically +// after the command line is parsed, the storage for this value is going to be +// leaked. Note that in both scenarios we are not going to have a real leak. +// Instead we'll store the leaked value pointers in the internal freelist to +// avoid triggering the memory leak checker complains. +// +// If the flag is ever set programmatically, it stops being the candidate for an +// unprotected read, and any follow up access to the flag value requires a lock. +// Note that if the value if set programmatically before the command line is +// parsed, we can switch back to enabling unprotected reads for that value. template -struct FlagValue { - bool Get(const SequenceLock&, T&) const { return false; } +struct FlagValue + : FlagMaskedPointerValue { + // We const initialize the value with unmasked pointer to the internal buffer, + // making sure it is not a candidate for unprotected read. This way we can + // ensure Init is done before any access to the flag value. + constexpr FlagValue() : FlagMaskedPointerValue(&buffer[0]) {} - alignas(T) char value[sizeof(T)]; + bool Get(const SequenceLock&, T& dst) const { + MaskedPointer ptr_value = value.load(std::memory_order_acquire); + + if (ABSL_PREDICT_TRUE(ptr_value.AllowsUnprotectedRead())) { + ::new (static_cast(&dst)) T(*static_cast(ptr_value.Ptr())); + return true; + } + return false; + } + + alignas(MaskedPointer::RequiredAlignment()) alignas( + T) char buffer[sizeof(T)]{}; }; /////////////////////////////////////////////////////////////////////////////// @@ -483,7 +628,7 @@ class FlagImpl final : public CommandLineFlag { // Used in read/write operations to validate source/target has correct type. // For example if flag is declared as absl::Flag FLAGS_foo, a call to // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed - // int. To do that we pass the "assumed" type id (which is deduced from type + // int. To do that we pass the assumed type id (which is deduced from type // int) as an argument `type_id`, which is in turn is validated against the // type id stored in flag object by flag definition statement. void AssertValidType(FlagFastTypeId type_id, @@ -504,17 +649,13 @@ class FlagImpl final : public CommandLineFlag { void Init(); // Offset value access methods. One per storage kind. These methods to not - // respect const correctness, so be very carefull using them. + // respect const correctness, so be very careful using them. // This is a shared helper routine which encapsulates most of the magic. Since // it is only used inside the three routines below, which are defined in // flag.cc, we can define it in that file as well. template StorageT* OffsetValue() const; - // This is an accessor for a value stored in an aligned buffer storage - // used for non-trivially-copyable data types. - // Returns a mutable pointer to the start of a buffer. - void* AlignedBufferValue() const; // The same as above, but used for sequencelock-protected storage. std::atomic* AtomicBufferValue() const; @@ -523,13 +664,16 @@ class FlagImpl final : public CommandLineFlag { // mutable reference to an atomic value. std::atomic& OneWordValue() const; + std::atomic& PtrStorage() const; + // Attempts to parse supplied `value` string. If parsing is successful, // returns new value. Otherwise returns nullptr. std::unique_ptr TryParse(absl::string_view value, std::string& err) const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); // Stores the flag value based on the pointer to the source. - void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); + void StoreValue(const void* src, ValueSource source) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); // Copy the flag data, protected by `seq_lock_` into `dst`. // @@ -585,7 +729,7 @@ class FlagImpl final : public CommandLineFlag { const char* const name_; // The file name where ABSL_FLAG resides. const char* const filename_; - // Type-specific operations "vtable". + // Type-specific operations vtable. const FlagOpFn op_; // Help message literal or function to generate it. const FlagHelpMsg help_; @@ -720,16 +864,21 @@ class FlagImplPeer { // Implementation of Flag value specific operations routine. template void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) { + struct AlignedSpace { + alignas(MaskedPointer::RequiredAlignment()) alignas(T) char buf[sizeof(T)]; + }; + using Allocator = std::allocator; switch (op) { case FlagOp::kAlloc: { - std::allocator alloc; - return std::allocator_traits>::allocate(alloc, 1); + Allocator alloc; + return std::allocator_traits::allocate(alloc, 1); } case FlagOp::kDelete: { T* p = static_cast(v2); p->~T(); - std::allocator alloc; - std::allocator_traits>::deallocate(alloc, p, 1); + Allocator alloc; + std::allocator_traits::deallocate( + alloc, reinterpret_cast(p), 1); return nullptr; } case FlagOp::kCopy: @@ -789,7 +938,7 @@ class FlagRegistrar { return *this; } - // Make the registrar "die" gracefully as an empty struct on a line where + // Makes the registrar die gracefully as an empty struct on a line where // registration happens. Registrar objects are intended to live only as // temporary. constexpr operator FlagRegistrarEmpty() const { return {}; } // NOLINT @@ -798,6 +947,10 @@ class FlagRegistrar { Flag& flag_; // Flag being registered (not owned). }; +/////////////////////////////////////////////////////////////////////////////// +// Test only API +uint64_t NumLeakedFlagValues(); + } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/die_if_null.h b/naiveproxy/src/third_party/abseil-cpp/absl/log/die_if_null.h index 127a9ac882..f773aa854e 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/die_if_null.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/die_if_null.h @@ -55,7 +55,7 @@ namespace log_internal { // `line` location. Called when `ABSL_DIE_IF_NULL` fails. Calling this function // generates less code than its implementation would if inlined, for a slight // code size reduction each time `ABSL_DIE_IF_NULL` is called. -ABSL_ATTRIBUTE_NORETURN ABSL_ATTRIBUTE_NOINLINE void DieBecauseNull( +[[noreturn]] ABSL_ATTRIBUTE_NOINLINE void DieBecauseNull( const char* file, int line, const char* exprtext); // Helper for `ABSL_DIE_IF_NULL`. diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/globals.h b/naiveproxy/src/third_party/abseil-cpp/absl/log/globals.h index b36e47e6d1..4feec4078f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/globals.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/globals.h @@ -140,7 +140,7 @@ void ClearLogBacktraceLocation(); // // This option tells the logging library that every logged message // should include the prefix (severity, date, time, PID, etc.) - +// // ShouldPrependLogPrefix() // // Returns the value of the Prepend Log Prefix option. @@ -154,25 +154,38 @@ ABSL_MUST_USE_RESULT bool ShouldPrependLogPrefix(); void EnableLogPrefix(bool on_off); //------------------------------------------------------------------------------ -// Set Global VLOG Level +// `VLOG` Configuration //------------------------------------------------------------------------------ // -// Sets the global `(ABSL_)VLOG(_IS_ON)` level to `log_level`. This level is -// applied to any sites whose filename doesn't match any `module_pattern`. -// Returns the prior value. -inline int SetGlobalVLogLevel(int log_level) { - return absl::log_internal::UpdateGlobalVLogLevel(log_level); +// These methods set the `(ABSL_)VLOG(_IS_ON)` threshold. They allow +// programmatic control of the thresholds set by the --v and --vmodule flags. +// +// Only `VLOG`s with a severity level LESS THAN OR EQUAL TO the threshold will +// be evaluated. +// +// For example, if the threshold is 2, then: +// +// VLOG(2) << "This message will be logged."; +// VLOG(3) << "This message will NOT be logged."; +// +// The default threshold is 0. Since `VLOG` levels must not be negative, a +// negative threshold value will turn off all VLOGs. + +// SetGlobalVLogLevel() +// +// Sets the global `VLOG` level to threshold. Returns the previous global +// threshold. +inline int SetGlobalVLogLevel(int threshold) { + return absl::log_internal::UpdateGlobalVLogLevel(threshold); } -//------------------------------------------------------------------------------ -// Set VLOG Level -//------------------------------------------------------------------------------ +// SetVLogLevel() // -// Sets `(ABSL_)VLOG(_IS_ON)` level for `module_pattern` to `log_level`. This -// allows programmatic control of what is normally set by the --vmodule flag. -// Returns the level that previously applied to `module_pattern`. -inline int SetVLogLevel(absl::string_view module_pattern, int log_level) { - return absl::log_internal::PrependVModule(module_pattern, log_level); +// Sets the `VLOG` threshold for all files that match `module_pattern`, +// overwriting any prior value. Files that don't match aren't affected. +// Returns the threshold that previously applied to `module_pattern`. +inline int SetVLogLevel(absl::string_view module_pattern, int threshold) { + return absl::log_internal::PrependVModule(module_pattern, threshold); } //------------------------------------------------------------------------------ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/conditions.h b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/conditions.h index 645f3c23ea..9dc15db428 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/conditions.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/conditions.h @@ -230,8 +230,8 @@ class LogEveryNSecState final { // Helper routines to abort the application quietly -ABSL_ATTRIBUTE_NORETURN inline void AbortQuietly() { abort(); } -ABSL_ATTRIBUTE_NORETURN inline void ExitQuietly() { _exit(1); } +[[noreturn]] inline void AbortQuietly() { abort(); } +[[noreturn]] inline void ExitQuietly() { _exit(1); } } // namespace log_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_impl.h b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_impl.h index b44ed06819..a67f2f31b4 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_impl.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_impl.h @@ -42,7 +42,7 @@ ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream() #endif -// The `switch` ensures that this expansion is the begnning of a statement (as +// The `switch` ensures that this expansion is the beginning of a statement (as // opposed to an expression). The use of both `case 0` and `default` is to // suppress a compiler warning. #define ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level) \ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_message.cc b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_message.cc index 58505267f0..4e9b08af64 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_message.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_message.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -67,7 +68,14 @@ namespace log_internal { namespace { // message `logging.proto.Event` enum EventTag : uint8_t { + kFileName = 2, + kFileLine = 3, + kTimeNsecs = 4, + kSeverity = 5, + kThreadId = 6, kValue = 7, + kSequenceNumber = 9, + kThreadName = 10, }; // message `logging.proto.Value` @@ -100,6 +108,23 @@ bool PrintValue(absl::Span& dst, absl::Span buf) { return true; } +// See `logging.proto.Severity` +int32_t ProtoSeverity(absl::LogSeverity severity, int verbose_level) { + switch (severity) { + case absl::LogSeverity::kInfo: + if (verbose_level == absl::LogEntry::kNoVerbosityLevel) return 800; + return 600 - verbose_level; + case absl::LogSeverity::kWarning: + return 900; + case absl::LogSeverity::kError: + return 950; + case absl::LogSeverity::kFatal: + return 1100; + default: + return 800; + } +} + absl::string_view Basename(absl::string_view filepath) { #ifdef _WIN32 size_t path = filepath.find_last_of("/\\"); @@ -145,26 +170,37 @@ struct LogMessage::LogMessageData final { // A `logging.proto.Event` proto message is built into `encoded_buf`. std::array encoded_buf; - // `encoded_remaining` is the suffix of `encoded_buf` that has not been filled - // yet. If a datum to be encoded does not fit into `encoded_remaining` and - // cannot be truncated to fit, the size of `encoded_remaining` will be zeroed - // to prevent encoding of any further data. Note that in this case its data() - // pointer will not point past the end of `encoded_buf`. - absl::Span encoded_remaining; + // `encoded_remaining()` is the suffix of `encoded_buf` that has not been + // filled yet. If a datum to be encoded does not fit into + // `encoded_remaining()` and cannot be truncated to fit, the size of + // `encoded_remaining()` will be zeroed to prevent encoding of any further + // data. Note that in this case its `data()` pointer will not point past the + // end of `encoded_buf`. + // The first use of `encoded_remaining()` is our chance to record metadata + // after any modifications (e.g. by `AtLocation()`) but before any data have + // been recorded. We want to record metadata before data so that data are + // preferentially truncated if we run out of buffer. + absl::Span& encoded_remaining() { + if (encoded_remaining_actual_do_not_use_directly.data() == nullptr) { + encoded_remaining_actual_do_not_use_directly = + absl::MakeSpan(encoded_buf); + InitializeEncodingAndFormat(); + } + return encoded_remaining_actual_do_not_use_directly; + } + absl::Span encoded_remaining_actual_do_not_use_directly; // A formatted string message is built in `string_buf`. std::array string_buf; + void InitializeEncodingAndFormat(); void FinalizeEncodingAndFormat(); }; LogMessage::LogMessageData::LogMessageData(const char* file, int line, absl::LogSeverity severity, absl::Time timestamp) - : extra_sinks_only(false), - manipulated(nullptr), - // This `absl::MakeSpan` silences spurious -Wuninitialized from GCC: - encoded_remaining(absl::MakeSpan(encoded_buf)) { + : extra_sinks_only(false), manipulated(nullptr) { // Legacy defaults for LOG's ostream: manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha); entry.full_filename_ = file; @@ -177,13 +213,25 @@ LogMessage::LogMessageData::LogMessageData(const char* file, int line, entry.tid_ = absl::base_internal::GetCachedTID(); } +void LogMessage::LogMessageData::InitializeEncodingAndFormat() { + EncodeStringTruncate(EventTag::kFileName, entry.source_filename(), + &encoded_remaining()); + EncodeVarint(EventTag::kFileLine, entry.source_line(), &encoded_remaining()); + EncodeVarint(EventTag::kTimeNsecs, absl::ToUnixNanos(entry.timestamp()), + &encoded_remaining()); + EncodeVarint(EventTag::kSeverity, + ProtoSeverity(entry.log_severity(), entry.verbosity()), + &encoded_remaining()); + EncodeVarint(EventTag::kThreadId, entry.tid(), &encoded_remaining()); +} + void LogMessage::LogMessageData::FinalizeEncodingAndFormat() { - // Note that `encoded_remaining` may have zero size without pointing past the - // end of `encoded_buf`, so the difference between `data()` pointers is used - // to compute the size of `encoded_data`. + // Note that `encoded_remaining()` may have zero size without pointing past + // the end of `encoded_buf`, so the difference between `data()` pointers is + // used to compute the size of `encoded_data`. absl::Span encoded_data( encoded_buf.data(), - static_cast(encoded_remaining.data() - encoded_buf.data())); + static_cast(encoded_remaining().data() - encoded_buf.data())); // `string_remaining` is the suffix of `string_buf` that has not been filled // yet. absl::Span string_remaining(string_buf); @@ -211,7 +259,6 @@ void LogMessage::LogMessageData::FinalizeEncodingAndFormat() { if (PrintValue(string_remaining, field.bytes_value())) continue; break; } - break; } auto chars_written = static_cast(string_remaining.data() - string_buf.data()); @@ -413,7 +460,7 @@ void LogMessage::Flush() { data_->FinalizeEncodingAndFormat(); data_->entry.encoding_ = absl::string_view(data_->encoded_buf.data(), - static_cast(data_->encoded_remaining.data() - + static_cast(data_->encoded_remaining().data() - data_->encoded_buf.data())); SendToLog(); } @@ -421,7 +468,7 @@ void LogMessage::Flush() { void LogMessage::SetFailQuietly() { data_->fail_quietly = true; } LogMessage::OstreamView::OstreamView(LogMessageData& message_data) - : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining) { + : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining()) { // This constructor sets the `streambuf` up so that streaming into an attached // ostream encodes string data in-place. To do that, we write appropriate // headers into the buffer using a copy of the buffer view so that we can @@ -444,8 +491,8 @@ LogMessage::OstreamView::~OstreamView() { if (!string_start_.data()) { // The second field header didn't fit. Whether the first one did or not, we // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the - // size of `data_->encoded_remaining` so that no more data are encoded. - data_.encoded_remaining.remove_suffix(data_.encoded_remaining.size()); + // size of `data_->encoded_remaining()` so that no more data are encoded. + data_.encoded_remaining().remove_suffix(data_.encoded_remaining().size()); return; } const absl::Span contents(pbase(), @@ -454,7 +501,7 @@ LogMessage::OstreamView::~OstreamView() { encoded_remaining_copy_.remove_prefix(contents.size()); EncodeMessageLength(string_start_, &encoded_remaining_copy_); EncodeMessageLength(message_start_, &encoded_remaining_copy_); - data_.encoded_remaining = encoded_remaining_copy_; + data_.encoded_remaining() = encoded_remaining_copy_; } std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; } @@ -521,13 +568,13 @@ void LogMessage::LogBacktraceIfNeeded() { view.stream() << ") "; } -// Encodes into `data_->encoded_remaining` a partial `logging.proto.Event` +// Encodes into `data_->encoded_remaining()` a partial `logging.proto.Event` // containing the specified string data using a `Value` field appropriate to // `str_type`. Truncates `str` if necessary, but emits nothing and marks the // buffer full if even the field headers do not fit. template void LogMessage::CopyToEncodedBuffer(absl::string_view str) { - auto encoded_remaining_copy = data_->encoded_remaining; + auto encoded_remaining_copy = data_->encoded_remaining(); auto start = EncodeMessageStart( EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(), &encoded_remaining_copy); @@ -540,11 +587,11 @@ void LogMessage::CopyToEncodedBuffer(absl::string_view str) { str, &encoded_remaining_copy)) { // The string may have been truncated, but the field header fit. EncodeMessageLength(start, &encoded_remaining_copy); - data_->encoded_remaining = encoded_remaining_copy; + data_->encoded_remaining() = encoded_remaining_copy; } else { - // The field header(s) did not fit; zero `encoded_remaining` so we don't + // The field header(s) did not fit; zero `encoded_remaining()` so we don't // write anything else later. - data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size()); + data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size()); } } template void LogMessage::CopyToEncodedBuffer( @@ -553,7 +600,7 @@ template void LogMessage::CopyToEncodedBuffer< LogMessage::StringType::kNotLiteral>(absl::string_view str); template void LogMessage::CopyToEncodedBuffer(char ch, size_t num) { - auto encoded_remaining_copy = data_->encoded_remaining; + auto encoded_remaining_copy = data_->encoded_remaining(); auto value_start = EncodeMessageStart( EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num, &encoded_remaining_copy); @@ -566,11 +613,11 @@ void LogMessage::CopyToEncodedBuffer(char ch, size_t num) { log_internal::AppendTruncated(ch, num, encoded_remaining_copy); EncodeMessageLength(str_start, &encoded_remaining_copy); EncodeMessageLength(value_start, &encoded_remaining_copy); - data_->encoded_remaining = encoded_remaining_copy; + data_->encoded_remaining() = encoded_remaining_copy; } else { - // The field header(s) did not fit; zero `encoded_remaining` so we don't + // The field header(s) did not fit; zero `encoded_remaining()` so we don't // write anything else later. - data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size()); + data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size()); } } template void LogMessage::CopyToEncodedBuffer( diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_message.h b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_message.h index fa72121414..0c067da9ad 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_message.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/log_message.h @@ -187,11 +187,11 @@ class LogMessage { protected: // Call `abort()` or similar to perform `LOG(FATAL)` crash. It is assumed // that the caller has already generated and written the trace as appropriate. - ABSL_ATTRIBUTE_NORETURN static void FailWithoutStackTrace(); + [[noreturn]] static void FailWithoutStackTrace(); // Similar to `FailWithoutStackTrace()`, but without `abort()`. Terminates // the process with an error exit code. - ABSL_ATTRIBUTE_NORETURN static void FailQuietly(); + [[noreturn]] static void FailQuietly(); // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s. // This might as well be inlined into `~LogMessage` except that @@ -354,7 +354,7 @@ class LogMessageFatal final : public LogMessage { LogMessageFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD; LogMessageFatal(const char* file, int line, absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD; - ABSL_ATTRIBUTE_NORETURN ~LogMessageFatal(); + [[noreturn]] ~LogMessageFatal(); }; // `LogMessageDebugFatal` ensures the process will exit in failure after logging @@ -381,7 +381,7 @@ class LogMessageQuietlyFatal final : public LogMessage { LogMessageQuietlyFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD; LogMessageQuietlyFatal(const char* file, int line, absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD; - ABSL_ATTRIBUTE_NORETURN ~LogMessageQuietlyFatal(); + [[noreturn]] ~LogMessageQuietlyFatal(); }; } // namespace log_internal diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/nullstream.h b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/nullstream.h index 9266852eb9..973e91ab68 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/nullstream.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/nullstream.h @@ -117,16 +117,7 @@ class NullStreamMaybeFatal final : public NullStream { class NullStreamFatal final : public NullStream { public: NullStreamFatal() = default; - // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so - // disable msvc's warning about the d'tor never returning. -#if defined(_MSC_VER) && !defined(__clang__) -#pragma warning(push) -#pragma warning(disable : 4722) -#endif - ABSL_ATTRIBUTE_NORETURN ~NullStreamFatal() { _exit(1); } -#if defined(_MSC_VER) && !defined(__clang__) -#pragma warning(pop) -#endif + [[noreturn]] ~NullStreamFatal() { _exit(1); } }; } // namespace log_internal diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/test_matchers.cc b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/test_matchers.cc index 8c6515c4bc..042083d823 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/test_matchers.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/test_matchers.cc @@ -26,6 +26,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/log/internal/test_helpers.h" +#include "absl/log/log_entry.h" #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" @@ -131,11 +132,9 @@ Matcher Timestamp( return Property("timestamp", &absl::LogEntry::timestamp, timestamp); } -Matcher TimestampInMatchWindow() { - return Property("timestamp", &absl::LogEntry::timestamp, - AllOf(Ge(absl::Now()), Truly([](absl::Time arg) { - return arg <= absl::Now(); - }))); +Matcher InMatchWindow() { + return AllOf(Ge(absl::Now()), + Truly([](absl::Time arg) { return arg <= absl::Now(); })); } Matcher ThreadID( diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/test_matchers.h b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/test_matchers.h index fc653a91bc..906eda2408 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/test_matchers.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/internal/test_matchers.h @@ -62,7 +62,7 @@ namespace log_internal { const ::testing::Matcher& timestamp); // Matches if the `LogEntry`'s timestamp falls after the instantiation of this // matcher and before its execution, as is normal when used with EXPECT_CALL. -::testing::Matcher TimestampInMatchWindow(); +::testing::Matcher InMatchWindow(); ::testing::Matcher ThreadID( const ::testing::Matcher&); ::testing::Matcher TextMessageWithPrefixAndNewline( diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/log/log_basic_test_impl.inc b/naiveproxy/src/third_party/abseil-cpp/absl/log/log_basic_test_impl.inc index 8083ff2c7e..7baf5e7b55 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/log/log_basic_test_impl.inc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/log/log_basic_test_impl.inc @@ -53,6 +53,7 @@ using ::absl::log_internal::DeathTestValidateExpectations; using ::absl::log_internal::DiedOfFatal; using ::absl::log_internal::DiedOfQFatal; #endif +using ::absl::log_internal::InMatchWindow; using ::absl::log_internal::LoggingEnabledAt; using ::absl::log_internal::LogSeverity; using ::absl::log_internal::Prefix; @@ -62,7 +63,7 @@ using ::absl::log_internal::SourceLine; using ::absl::log_internal::Stacktrace; using ::absl::log_internal::TextMessage; using ::absl::log_internal::ThreadID; -using ::absl::log_internal::TimestampInMatchWindow; +using ::absl::log_internal::Timestamp; using ::absl::log_internal::Verbosity; using ::testing::AnyNumber; using ::testing::Eq; @@ -98,18 +99,20 @@ TEST_P(BasicLogTest, Info) { if (LoggingEnabledAt(absl::LogSeverity::kInfo)) { EXPECT_CALL( test_sink, - Send(AllOf(SourceFilename(Eq(__FILE__)), - SourceBasename(Eq("log_basic_test_impl.inc")), - SourceLine(Eq(log_line)), Prefix(IsTrue()), - LogSeverity(Eq(absl::LogSeverity::kInfo)), - TimestampInMatchWindow(), - ThreadID(Eq(absl::base_internal::GetTID())), - TextMessage(Eq("hello world")), - Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto(R"pb(value { - literal: "hello world" - })pb")), - Stacktrace(IsEmpty())))); + Send(AllOf( + SourceFilename(Eq(__FILE__)), + SourceBasename(Eq("log_basic_test_impl.inc")), + SourceLine(Eq(log_line)), Prefix(IsTrue()), + LogSeverity(Eq(absl::LogSeverity::kInfo)), + Timestamp(InMatchWindow()), + ThreadID(Eq(absl::base_internal::GetTID())), + TextMessage(Eq("hello world")), + Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::INFO), Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))), + Stacktrace(IsEmpty())))); } test_sink.StartCapturingLogs(); @@ -127,18 +130,20 @@ TEST_P(BasicLogTest, Warning) { if (LoggingEnabledAt(absl::LogSeverity::kWarning)) { EXPECT_CALL( test_sink, - Send(AllOf(SourceFilename(Eq(__FILE__)), - SourceBasename(Eq("log_basic_test_impl.inc")), - SourceLine(Eq(log_line)), Prefix(IsTrue()), - LogSeverity(Eq(absl::LogSeverity::kWarning)), - TimestampInMatchWindow(), - ThreadID(Eq(absl::base_internal::GetTID())), - TextMessage(Eq("hello world")), - Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto(R"pb(value { - literal: "hello world" - })pb")), - Stacktrace(IsEmpty())))); + Send(AllOf( + SourceFilename(Eq(__FILE__)), + SourceBasename(Eq("log_basic_test_impl.inc")), + SourceLine(Eq(log_line)), Prefix(IsTrue()), + LogSeverity(Eq(absl::LogSeverity::kWarning)), + Timestamp(InMatchWindow()), + ThreadID(Eq(absl::base_internal::GetTID())), + TextMessage(Eq("hello world")), + Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::WARNING), Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))), + Stacktrace(IsEmpty())))); } test_sink.StartCapturingLogs(); @@ -156,18 +161,20 @@ TEST_P(BasicLogTest, Error) { if (LoggingEnabledAt(absl::LogSeverity::kError)) { EXPECT_CALL( test_sink, - Send(AllOf(SourceFilename(Eq(__FILE__)), - SourceBasename(Eq("log_basic_test_impl.inc")), - SourceLine(Eq(log_line)), Prefix(IsTrue()), - LogSeverity(Eq(absl::LogSeverity::kError)), - TimestampInMatchWindow(), - ThreadID(Eq(absl::base_internal::GetTID())), - TextMessage(Eq("hello world")), - Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto(R"pb(value { - literal: "hello world" - })pb")), - Stacktrace(IsEmpty())))); + Send(AllOf( + SourceFilename(Eq(__FILE__)), + SourceBasename(Eq("log_basic_test_impl.inc")), + SourceLine(Eq(log_line)), Prefix(IsTrue()), + LogSeverity(Eq(absl::LogSeverity::kError)), + Timestamp(InMatchWindow()), + ThreadID(Eq(absl::base_internal::GetTID())), + TextMessage(Eq("hello world")), + Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))), + Stacktrace(IsEmpty())))); } test_sink.StartCapturingLogs(); @@ -211,12 +218,16 @@ TEST_P(BasicLogDeathTest, Fatal) { SourceBasename(Eq("log_basic_test_impl.inc")), SourceLine(Eq(log_line)), Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), - TimestampInMatchWindow(), + Timestamp(InMatchWindow()), ThreadID(Eq(absl::base_internal::GetTID())), TextMessage(Eq("hello world")), Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto( - R"pb(value { literal: "hello world" })pb")), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::FATAL), + Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto( + R"pb(literal: "hello world")pb")))), Stacktrace(IsEmpty())))) .WillOnce(DeathTestExpectedLogging()); @@ -227,12 +238,16 @@ TEST_P(BasicLogDeathTest, Fatal) { SourceBasename(Eq("log_basic_test_impl.inc")), SourceLine(Eq(log_line)), Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), - TimestampInMatchWindow(), + Timestamp(InMatchWindow()), ThreadID(Eq(absl::base_internal::GetTID())), TextMessage(Eq("hello world")), Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto( - R"pb(value { literal: "hello world" })pb")), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::FATAL), + Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto( + R"pb(literal: "hello world")pb")))), Stacktrace(Not(IsEmpty()))))) .WillOnce(DeathTestExpectedLogging()); } @@ -265,12 +280,16 @@ TEST_P(BasicLogDeathTest, QFatal) { SourceBasename(Eq("log_basic_test_impl.inc")), SourceLine(Eq(log_line)), Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), - TimestampInMatchWindow(), + Timestamp(InMatchWindow()), ThreadID(Eq(absl::base_internal::GetTID())), TextMessage(Eq("hello world")), Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto( - R"pb(value { literal: "hello world" })pb")), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::FATAL), + Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto( + R"pb(literal: "hello world")pb")))), Stacktrace(IsEmpty())))) .WillOnce(DeathTestExpectedLogging()); } @@ -294,18 +313,20 @@ TEST_P(BasicLogTest, DFatal) { if (LoggingEnabledAt(absl::LogSeverity::kError)) { EXPECT_CALL( test_sink, - Send(AllOf(SourceFilename(Eq(__FILE__)), - SourceBasename(Eq("log_basic_test_impl.inc")), - SourceLine(Eq(log_line)), Prefix(IsTrue()), - LogSeverity(Eq(absl::LogSeverity::kError)), - TimestampInMatchWindow(), - ThreadID(Eq(absl::base_internal::GetTID())), - TextMessage(Eq("hello world")), - Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto(R"pb(value { - literal: "hello world" - })pb")), - Stacktrace(IsEmpty())))); + Send(AllOf( + SourceFilename(Eq(__FILE__)), + SourceBasename(Eq("log_basic_test_impl.inc")), + SourceLine(Eq(log_line)), Prefix(IsTrue()), + LogSeverity(Eq(absl::LogSeverity::kError)), + Timestamp(InMatchWindow()), + ThreadID(Eq(absl::base_internal::GetTID())), + TextMessage(Eq("hello world")), + Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))), + Stacktrace(IsEmpty())))); } test_sink.StartCapturingLogs(); @@ -339,12 +360,16 @@ TEST_P(BasicLogDeathTest, DFatal) { SourceBasename(Eq("log_basic_test_impl.inc")), SourceLine(Eq(log_line)), Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), - TimestampInMatchWindow(), + Timestamp(InMatchWindow()), ThreadID(Eq(absl::base_internal::GetTID())), TextMessage(Eq("hello world")), Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto( - R"pb(value { literal: "hello world" })pb")), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::FATAL), + Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto( + R"pb(literal: "hello world")pb")))), Stacktrace(IsEmpty())))) .WillOnce(DeathTestExpectedLogging()); @@ -355,12 +380,16 @@ TEST_P(BasicLogDeathTest, DFatal) { SourceBasename(Eq("log_basic_test_impl.inc")), SourceLine(Eq(log_line)), Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), - TimestampInMatchWindow(), + Timestamp(InMatchWindow()), ThreadID(Eq(absl::base_internal::GetTID())), TextMessage(Eq("hello world")), Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto( - R"pb(value { literal: "hello world" })pb")), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::FATAL), + Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto( + R"pb(literal: "hello world")pb")))), Stacktrace(Not(IsEmpty()))))) .WillOnce(DeathTestExpectedLogging()); } @@ -408,17 +437,25 @@ TEST_P(BasicLogTest, Level) { if (LoggingEnabledAt(severity)) { EXPECT_CALL( test_sink, - Send(AllOf(SourceFilename(Eq(__FILE__)), - SourceBasename(Eq("log_basic_test_impl.inc")), - SourceLine(Eq(log_line)), Prefix(IsTrue()), - LogSeverity(Eq(severity)), TimestampInMatchWindow(), - ThreadID(Eq(absl::base_internal::GetTID())), - TextMessage(Eq("hello world")), - Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto(R"pb(value { - literal: "hello world" - })pb")), - Stacktrace(IsEmpty())))); + Send(AllOf( + SourceFilename(Eq(__FILE__)), + SourceBasename(Eq("log_basic_test_impl.inc")), + SourceLine(Eq(log_line)), Prefix(IsTrue()), + LogSeverity(Eq(severity)), Timestamp(InMatchWindow()), + ThreadID(Eq(absl::base_internal::GetTID())), + TextMessage(Eq("hello world")), + Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(severity == absl::LogSeverity::kInfo ? logging::proto::INFO + : severity == absl::LogSeverity::kWarning + ? logging::proto::WARNING + : severity == absl::LogSeverity::kError + ? logging::proto::ERROR + : 0), + Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))), + Stacktrace(IsEmpty())))); } test_sink.StartCapturingLogs(); do_log(); @@ -455,12 +492,16 @@ TEST_P(BasicLogDeathTest, Level) { SourceBasename(Eq("log_basic_test_impl.inc")), SourceLine(Eq(log_line)), Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), - TimestampInMatchWindow(), + Timestamp(InMatchWindow()), ThreadID(Eq(absl::base_internal::GetTID())), TextMessage(Eq("hello world")), Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto( - R"pb(value { literal: "hello world" })pb")), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::FATAL), + Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto( + R"pb(literal: "hello world")pb")))), Stacktrace(IsEmpty())))) .WillOnce(DeathTestExpectedLogging()); @@ -470,12 +511,16 @@ TEST_P(BasicLogDeathTest, Level) { SourceBasename(Eq("log_basic_test_impl.inc")), SourceLine(Eq(log_line)), Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)), - TimestampInMatchWindow(), + Timestamp(InMatchWindow()), ThreadID(Eq(absl::base_internal::GetTID())), TextMessage(Eq("hello world")), Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)), - ENCODED_MESSAGE(EqualsProto( - R"pb(value { literal: "hello world" })pb")), + ENCODED_MESSAGE(MatchesEvent( + Eq(__FILE__), Eq(log_line), InMatchWindow(), + Eq(logging::proto::FATAL), + Eq(absl::base_internal::GetTID()), + ElementsAre(EqualsProto( + R"pb(literal: "hello world")pb")))), Stacktrace(Not(IsEmpty()))))) .WillOnce(DeathTestExpectedLogging()); } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/random/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/random/CMakeLists.txt index af91d1a48e..ad5477e3e0 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/random/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/random/CMakeLists.txt @@ -112,12 +112,12 @@ absl_cc_library( DEPS absl::config absl::core_headers + absl::fast_type_id absl::flat_hash_map absl::raw_logging_internal absl::random_internal_mock_helpers - absl::random_internal_mock_overload_set - absl::random_internal_mock_validators absl::random_random + absl::type_traits absl::utility GTest::gmock GTest::gtest diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/random/bit_gen_ref.h b/naiveproxy/src/third_party/abseil-cpp/absl/random/bit_gen_ref.h index 2160a8dd90..ac26d9d4ab 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/random/bit_gen_ref.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/random/bit_gen_ref.h @@ -111,20 +111,21 @@ class BitGenRef { BitGenRef& operator=(const BitGenRef&) = default; BitGenRef& operator=(BitGenRef&&) = default; - template ::value && - random_internal::is_urbg::value && - !HasInvokeMock::value)>* = nullptr> - BitGenRef(URBG& gen ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT + template < + typename URBGRef, typename URBG = absl::remove_cvref_t, + typename absl::enable_if_t<(!std::is_same::value && + random_internal::is_urbg::value && + !HasInvokeMock::value)>* = nullptr> + BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT : t_erased_gen_ptr_(reinterpret_cast(&gen)), mock_call_(NotAMock), generate_impl_fn_(ImplFn) {} - template , typename absl::enable_if_t<(!std::is_same::value && random_internal::is_urbg::value && HasInvokeMock::value)>* = nullptr> - BitGenRef(URBG& gen ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT + BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT : t_erased_gen_ptr_(reinterpret_cast(&gen)), mock_call_(&MockCall), generate_impl_fn_(ImplFn) {} diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/random/mocking_bit_gen.h b/naiveproxy/src/third_party/abseil-cpp/absl/random/mocking_bit_gen.h index 92f2e4fc7f..041989de20 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/random/mocking_bit_gen.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/random/mocking_bit_gen.h @@ -239,7 +239,7 @@ class MockingBitGenImpl { // since the underlying implementation creates a type-specific pointer which // will be distinct across different DLL boundaries. // -using MockingBitGen = random_internal::MockingBitGenImpl; +using MockingBitGen = random_internal::MockingBitGenImpl; // UnvalidatedMockingBitGen // diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/status/internal/status_matchers.h b/naiveproxy/src/third_party/abseil-cpp/absl/status/internal/status_matchers.h index d11742b729..0750622e3f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/status/internal/status_matchers.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/status/internal/status_matchers.h @@ -69,8 +69,8 @@ class IsOkAndHoldsMatcherImpl bool MatchAndExplain( StatusOrType actual_value, ::testing::MatchResultListener* result_listener) const override { - if (!actual_value.ok()) { - *result_listener << "which has status " << actual_value.status(); + if (!GetStatus(actual_value).ok()) { + *result_listener << "which has status " << GetStatus(actual_value); return false; } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/status/internal/statusor_internal.h b/naiveproxy/src/third_party/abseil-cpp/absl/status/internal/statusor_internal.h index 414aa3002d..67603156a4 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/status/internal/statusor_internal.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/status/internal/statusor_internal.h @@ -186,7 +186,7 @@ class Helper { public: // Move type-agnostic error handling to the .cc. static void HandleInvalidStatusCtorArg(absl::Nonnull); - ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status); + [[noreturn]] static void Crash(const absl::Status& status); }; // Construct an instance of T in `p` through placement new, passing Args... to @@ -438,7 +438,7 @@ struct MoveAssignBase { MoveAssignBase& operator=(MoveAssignBase&&) = delete; }; -ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status); +[[noreturn]] void ThrowBadStatusOrAccess(absl::Status status); // Used to introduce jitter into the output of printing functions for // `StatusOr` (i.e. `AbslStringify` and `operator<<`). diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.bazel index 48793edddb..9bffae6138 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.bazel @@ -600,6 +600,7 @@ cc_library( "//absl/functional:function_ref", "//absl/meta:type_traits", "//absl/numeric:bits", + "//absl/types:compare", "//absl/types:optional", "//absl/types:span", ], @@ -925,6 +926,7 @@ cc_test( "//absl/log", "//absl/log:check", "//absl/random", + "//absl/types:compare", "//absl/types:optional", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.gn index 9ac0db9b2f..1e2e5ca559 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/BUILD.gn @@ -384,6 +384,7 @@ absl_source_set("cord") { "//third_party/abseil-cpp/absl/functional:function_ref", "//third_party/abseil-cpp/absl/meta:type_traits", "//third_party/abseil-cpp/absl/numeric:bits", + "//third_party/abseil-cpp/absl/types:compare", "//third_party/abseil-cpp/absl/types:optional", "//third_party/abseil-cpp/absl/types:span", ] @@ -619,6 +620,7 @@ absl_source_set("cordz_test_helpers") { # "//third_party/abseil-cpp/absl/log", # "//third_party/abseil-cpp/absl/log:check", # "//third_party/abseil-cpp/absl/random", +# "//third_party/abseil-cpp/absl/types:compare", # "//third_party/abseil-cpp/absl/types:optional", # ] # } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/strings/CMakeLists.txt index 99156cfeea..4a84dbbd21 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/CMakeLists.txt @@ -18,9 +18,9 @@ absl_cc_library( NAME string_view HDRS - string_view.h + "string_view.h" SRCS - string_view.cc + "string_view.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS @@ -705,6 +705,7 @@ absl_cc_library( absl::compressed_tuple absl::config absl::container_memory + absl::compare absl::core_headers absl::crc_cord_state absl::endian diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/cord.h b/naiveproxy/src/third_party/abseil-cpp/absl/strings/cord.h index 0d8d7007d9..c68b6f1093 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/cord.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/cord.h @@ -96,6 +96,7 @@ #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/internal/string_constant.h" #include "absl/strings/string_view.h" +#include "absl/types/compare.h" #include "absl/types/optional.h" namespace absl { @@ -849,6 +850,38 @@ class Cord { friend bool operator==(const Cord& lhs, const Cord& rhs); friend bool operator==(const Cord& lhs, absl::string_view rhs); +#ifdef __cpp_impl_three_way_comparison + + // Cords support comparison with other Cords and string_views via operator< + // and others; here we provide a wrapper for the C++20 three-way comparison + // <=> operator. + + static inline std::strong_ordering ConvertCompareResultToStrongOrdering( + int c) { + if (c == 0) { + return std::strong_ordering::equal; + } else if (c < 0) { + return std::strong_ordering::less; + } else { + return std::strong_ordering::greater; + } + } + + friend inline std::strong_ordering operator<=>(const Cord& x, const Cord& y) { + return ConvertCompareResultToStrongOrdering(x.Compare(y)); + } + + friend inline std::strong_ordering operator<=>(const Cord& lhs, + absl::string_view rhs) { + return ConvertCompareResultToStrongOrdering(lhs.Compare(rhs)); + } + + friend inline std::strong_ordering operator<=>(absl::string_view lhs, + const Cord& rhs) { + return ConvertCompareResultToStrongOrdering(-rhs.Compare(lhs)); + } +#endif + friend absl::Nullable GetCordzInfoForTesting( const Cord& cord); diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/cord_internal.h b/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/cord_internal.h index 3de8e46baa..9420e764d9 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/cord_internal.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/internal/cord_internal.h @@ -85,7 +85,7 @@ enum Constants { }; // Emits a fatal error "Unexpected node type: xyz" and aborts the program. -ABSL_ATTRIBUTE_NORETURN void LogFatalNodeType(CordRep* rep); +[[noreturn]] void LogFatalNodeType(CordRep* rep); // Fast implementation of memmove for up to 15 bytes. This implementation is // safe for overlapping regions. If nullify_tail is true, the destination is diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/strings/string_view.h b/naiveproxy/src/third_party/abseil-cpp/absl/strings/string_view.h index b1fb7a10db..ff7600144a 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/strings/string_view.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/strings/string_view.h @@ -159,7 +159,7 @@ ABSL_NAMESPACE_BEGIN // // absl::string_view() == absl::string_view("", 0) // absl::string_view(nullptr, 0) == absl::string_view("abcdef"+6, 0) -class string_view { +class ABSL_INTERNAL_ATTRIBUTE_VIEW string_view { public: using traits_type = std::char_traits; using value_type = char; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc index 61b4ec0563..129067c151 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc @@ -211,7 +211,7 @@ class NodeSet { Vec table_; uint32_t occupied_; // Count of non-empty slots (includes deleted slots) - static uint32_t Hash(int32_t a) { return static_cast(a * 41); } + static uint32_t Hash(int32_t a) { return static_cast(a) * 41; } // Return index for storing v. May return an empty index or deleted index uint32_t FindIndex(int32_t v) const { @@ -365,6 +365,14 @@ static Node* FindNode(GraphCycles::Rep* rep, GraphId id) { return (n->version == NodeVersion(id)) ? n : nullptr; } +void GraphCycles::TestOnlyAddNodes(uint32_t n) { + uint32_t old_size = rep_->nodes_.size(); + rep_->nodes_.resize(n); + for (auto i = old_size; i < n; ++i) { + rep_->nodes_[i] = nullptr; + } +} + GraphCycles::GraphCycles() { InitArenaIfNecessary(); rep_ = new (base_internal::LowLevelAlloc::AllocWithArena(sizeof(Rep), arena)) @@ -373,6 +381,7 @@ GraphCycles::GraphCycles() { GraphCycles::~GraphCycles() { for (auto* node : rep_->nodes_) { + if (node == nullptr) { continue; } node->Node::~Node(); base_internal::LowLevelAlloc::Free(node); } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.h b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.h index ceba33e4de..08f304bce1 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.h @@ -126,6 +126,11 @@ class GraphCycles { // Expensive: should only be called from graphcycles_test.cc. bool CheckInvariants() const; + // Test-only method to add more nodes. The nodes will not be valid, and this + // method should only be used to test the behavior of the graph when it is + // very full. + void TestOnlyAddNodes(uint32_t n); + // ---------------------------------------------------- struct Rep; private: diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/time/CMakeLists.txt b/naiveproxy/src/third_party/abseil-cpp/absl/time/CMakeLists.txt index e1ade7a31a..fe625f28e2 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/time/CMakeLists.txt +++ b/naiveproxy/src/third_party/abseil-cpp/absl/time/CMakeLists.txt @@ -83,7 +83,7 @@ absl_cc_library( Threads::Threads # TODO(#1495): Use $ once our # minimum CMake version >= 3.24 - $<$:-Wl,-framework,CoreFoundation> + $<$:-Wl,-framework,CoreFoundation> ) # Internal-only target, do not depend on directly. diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/time/format.cc b/naiveproxy/src/third_party/abseil-cpp/absl/time/format.cc index 15a26b14f7..bd06f8fb35 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/time/format.cc +++ b/naiveproxy/src/third_party/abseil-cpp/absl/time/format.cc @@ -16,6 +16,7 @@ #include #include +#include #include "absl/strings/match.h" #include "absl/strings/string_view.h" @@ -136,7 +137,7 @@ bool ParseTime(absl::string_view format, absl::string_view input, if (b) { *time = Join(parts); } else if (err != nullptr) { - *err = error; + *err = std::move(error); } return b; } diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/time/time.h b/naiveproxy/src/third_party/abseil-cpp/absl/time/time.h index d367ace21e..f133c2d2ca 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/time/time.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/time/time.h @@ -75,15 +75,22 @@ struct timeval; #endif #include // NOLINT(build/c++11) + +#ifdef __cpp_impl_three_way_comparison +#include +#endif // __cpp_impl_three_way_comparison + #include #include #include #include #include +#include // NOLINT(build/c++11) #include #include #include +#include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/strings/string_view.h" @@ -305,6 +312,14 @@ class Duration { }; // Relational Operators + +#ifdef __cpp_impl_three_way_comparison + +ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( + Duration lhs, Duration rhs); + +#endif // __cpp_impl_three_way_comparison + ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, Duration rhs); ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Duration lhs, @@ -837,6 +852,11 @@ class Time { private: friend constexpr Time time_internal::FromUnixDuration(Duration d); friend constexpr Duration time_internal::ToUnixDuration(Time t); + +#ifdef __cpp_impl_three_way_comparison + friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs); +#endif // __cpp_impl_three_way_comparison + friend constexpr bool operator<(Time lhs, Time rhs); friend constexpr bool operator==(Time lhs, Time rhs); friend Duration operator-(Time lhs, Time rhs); @@ -848,6 +868,15 @@ class Time { }; // Relational Operators +#ifdef __cpp_impl_three_way_comparison + +ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( + Time lhs, Time rhs) { + return lhs.rep_ <=> rhs.rep_; +} + +#endif // __cpp_impl_three_way_comparison + ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) { return lhs.rep_ < rhs.rep_; } @@ -1723,6 +1752,25 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs, : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs); } + +#ifdef __cpp_impl_three_way_comparison + +ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>( + Duration lhs, Duration rhs) { + const int64_t lhs_hi = time_internal::GetRepHi(lhs); + const int64_t rhs_hi = time_internal::GetRepHi(rhs); + if (auto c = lhs_hi <=> rhs_hi; c != std::strong_ordering::equal) { + return c; + } + const uint32_t lhs_lo = time_internal::GetRepLo(lhs); + const uint32_t rhs_lo = time_internal::GetRepLo(rhs); + return (lhs_hi == (std::numeric_limits::min)()) + ? (lhs_lo + 1) <=> (rhs_lo + 1) + : lhs_lo <=> rhs_lo; +} + +#endif // __cpp_impl_three_way_comparison + ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs, Duration rhs) { return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) && diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/types/internal/variant.h b/naiveproxy/src/third_party/abseil-cpp/absl/types/internal/variant.h index 40f57c407d..4cb15f2921 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/types/internal/variant.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/types/internal/variant.h @@ -273,20 +273,7 @@ struct UnreachableSwitchCase { template [[noreturn]] static VisitIndicesResultT Run( Op&& /*ignored*/) { -#if ABSL_HAVE_BUILTIN(__builtin_unreachable) || \ - (defined(__GNUC__) && !defined(__clang__)) - __builtin_unreachable(); -#elif defined(_MSC_VER) - __assume(false); -#else - // Try to use assert of false being identified as an unreachable intrinsic. - // NOTE: We use assert directly to increase chances of exploiting an assume - // intrinsic. - assert(false); // NOLINT - - // Hack to silence potential no return warning -- cause an infinite loop. - return Run(std::forward(op)); -#endif // Checks for __builtin_unreachable + ABSL_UNREACHABLE(); } }; diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/types/span.h b/naiveproxy/src/third_party/abseil-cpp/absl/types/span.h index 560e569bc6..a0f80272e9 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/types/span.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/types/span.h @@ -151,7 +151,7 @@ ABSL_NAMESPACE_BEGIN // int* my_array = new int[10]; // MyRoutine(absl::Span(my_array, 10)); template -class Span { +class ABSL_INTERNAL_ATTRIBUTE_VIEW Span { private: // Used to determine whether a Span can be constructed from a container of // type C. diff --git a/naiveproxy/src/third_party/abseil-cpp/ci/windows_clangcl_bazel.bat b/naiveproxy/src/third_party/abseil-cpp/ci/windows_clangcl_bazel.bat index ac2f91670e..b031c30da8 100755 --- a/naiveproxy/src/third_party/abseil-cpp/ci/windows_clangcl_bazel.bat +++ b/naiveproxy/src/third_party/abseil-cpp/ci/windows_clangcl_bazel.bat @@ -43,9 +43,9 @@ IF NOT "%ALTERNATE_OPTIONS%"=="" copy %ALTERNATE_OPTIONS% absl\base\options.h test ... ^ --compilation_mode=%COMPILATION_MODE% ^ --compiler=clang-cl ^ - --copt=/std:%STD% ^ --copt=/WX ^ --copt=-Wno-microsoft-cast ^ + --cxxopt=/std:%STD% ^ --define=absl=1 ^ --distdir=%KOKORO_GFILE_DIR%\distdir ^ --enable_bzlmod=true ^ diff --git a/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_dbg.def b/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_dbg.def index adbe643b47..ac60c9c77c 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_dbg.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_dbg.def @@ -524,6 +524,7 @@ EXPORTS ??$AsciiStrCaseFold@$0A@@ascii_internal@absl@@YAXPEAD_K@Z ??$AsciiStrCaseFoldLong@$00@ascii_internal@absl@@YAXPEAD_K@Z ??$AsciiStrCaseFoldLong@$0A@@ascii_internal@absl@@YAXPEAD_K@Z + ??$AssertHashEqConsistent@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@IEAAXAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$AssignElements@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXPEAUPayload@status_internal@1@AEAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@01@_K@Z ??$Base64EscapeInternal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@strings_internal@absl@@YAXPEBE_KPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@_NPEBD@Z ??$BufferSizeFor@$$V@log_internal@absl@@YA_KW4WireType@01@@Z @@ -565,10 +566,12 @@ EXPORTS ??$DeallocateOld@$07V?$allocator@D@__Cr@std@@@HashSetResizeHelper@container_internal@absl@@QEAAXV?$allocator@D@__Cr@std@@_K@Z ??$DeallocateStandard@$07@container_internal@absl@@YAXAEAVCommonFields@01@AEBUPolicyFunctions@01@@Z ??$DecomposePair@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$DecomposePair@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePair@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@Z ??$DecomposePair@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QEAU?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@Z ??$DecomposePair@UFindElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AVconst_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QEAUFindElement@301@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePair@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$DecomposePair@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePairImpl@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@@Z ??$DecomposePairImpl@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@45@@Z ??$DecomposePairImpl@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@45@@Z @@ -789,8 +792,8 @@ EXPORTS ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ??$OffsetValue@U?$atomic@_K@__Cr@std@@@FlagImpl@flags_internal@absl@@AEBAPEAU?$atomic@_K@__Cr@std@@XZ + ??$OffsetValue@UFlagMaskedPointerValue@flags_internal@absl@@@FlagImpl@flags_internal@absl@@AEBAPEAUFlagMaskedPointerValue@12@XZ ??$OffsetValue@UFlagOneWordValue@flags_internal@absl@@@FlagImpl@flags_internal@absl@@AEBAPEAUFlagOneWordValue@12@XZ - ??$OffsetValue@X@FlagImpl@flags_internal@absl@@AEBAPEAXXZ ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@$$QEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@Z ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@$$QEAPEAVCommandLineFlag@1@@Z ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@Z @@ -934,6 +937,7 @@ EXPORTS ??$__allocate_at_least@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@YA?AU?$__allocation_result@PEAUViableSubstitution@strings_internal@absl@@@01@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@_K@Z ??$__allocate_at_least@V?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AU?$__allocation_result@PEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@01@AEAV?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@01@_K@Z ??$__allocator_destroy@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@PEAU45@@__Cr@std@@YAXAEAV?$allocator@UUnrecognizedFlag@absl@@@01@PEAUUnrecognizedFlag@absl@@1@Z + ??$__annotate_double_ended_contiguous_container@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@YAXPEBX00000@Z ??$__append_with_size@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@_K@Z ??$__assign_with_size_random_access@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@_J@Z ??$__call@AEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@AEAVCommandLineFlag@5@@?$__invoke_void_return_wrapper@X$00@__Cr@std@@SAXAEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@AEAVCommandLineFlag@7@@Z @@ -1053,11 +1057,13 @@ EXPORTS ??$__cxx_atomic_load@PEAVCordzInfo@cord_internal@absl@@@__Cr@std@@YAPEAVCordzInfo@cord_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAVCordzInfo@cord_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PEAVTimeZone@absl@@@__Cr@std@@YAPEAVTimeZone@absl@@PEBU?$__cxx_atomic_base_impl@PEAVTimeZone@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YAPEAVVLogSite@log_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@W4memory_order@01@@Z + ??$__cxx_atomic_load@VMaskedPointer@flags_internal@absl@@@__Cr@std@@YA?AVMaskedPointer@flags_internal@absl@@PEBU?$__cxx_atomic_base_impl@VMaskedPointer@flags_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@W4OnDeadlockCycle@absl@@@__Cr@std@@YA?AW4OnDeadlockCycle@absl@@PEBU?$__cxx_atomic_base_impl@W4OnDeadlockCycle@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@W4State@PerThreadSynch@base_internal@absl@@@__Cr@std@@YA?AW4State@PerThreadSynch@base_internal@absl@@PEBU?$__cxx_atomic_base_impl@W4State@PerThreadSynch@base_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_store@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@PEAVCordzHandle@cord_internal@absl@@@01@PEAVCordzHandle@cord_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@PEAVCordzInfo@cord_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@PEAVCordzInfo@cord_internal@absl@@@01@PEAVCordzInfo@cord_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@PEAVVLogSite@log_internal@absl@@W4memory_order@01@@Z + ??$__cxx_atomic_store@VMaskedPointer@flags_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@VMaskedPointer@flags_internal@absl@@@01@VMaskedPointer@flags_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@W4OnDeadlockCycle@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@W4OnDeadlockCycle@absl@@@01@W4OnDeadlockCycle@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@W4State@PerThreadSynch@base_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@W4State@PerThreadSynch@base_internal@absl@@@01@W4State@PerThreadSynch@base_internal@absl@@W4memory_order@01@@Z ??$__debug_randomize_range@U_ClassicAlgPolicy@__Cr@std@@PEAPEAVCommandLineFlag@absl@@PEAPEAV45@@__Cr@std@@YAXPEAPEAVCommandLineFlag@absl@@0@Z @@ -1106,9 +1112,9 @@ EXPORTS ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__tree_iterator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@23@_J@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__tree_iterator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@PEAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@PEAX@23@_J@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z + ??$__find@PEAPEAVLogSink@absl@@PEAPEAV12@PEAV12@U__identity@__Cr@std@@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0AEBQEAV23@AEAU__identity@01@@Z ??$__find_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@AEAAAEAPEAV?$__tree_node_base@PEAX@12@AEAPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??$__find_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@AEAAAEAPEAV?$__tree_node_base@PEAX@12@AEAPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z - ??$__find_impl@PEAPEAVLogSink@absl@@PEAPEAV12@PEAV12@U__identity@__Cr@std@@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0AEBQEAV23@AEAU__identity@01@@Z ??$__for_each_segment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@?$__copy_impl@U_ClassicAlgPolicy@__Cr@std@@@23@@__Cr@std@@YAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@?$__copy_impl@U_ClassicAlgPolicy@__Cr@std@@@01@@Z ??$__insert_with_size@V?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@__Cr@std@@V123@@?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEAA?AV?$__wrap_iter@PEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$__wrap_iter@PEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@12@1_J@Z ??$__invoke@AEAUByCivilTime@Transition@cctz@time_internal@absl@@AEBU2345@AEBU2345@@__Cr@std@@YA_NAEAUByCivilTime@Transition@cctz@time_internal@absl@@AEBU3456@1@Z @@ -1245,6 +1251,8 @@ EXPORTS ??$advance@V?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@__Cr@std@@_J_J$0A@@__Cr@std@@YAXAEAV?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@01@_J@Z ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@45@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@45@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QEAU?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@45@@Z @@ -1253,6 +1261,8 @@ EXPORTS ??$apply@UFindElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA?AVconst_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QEAUFindElement@412@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$assign@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@0@Z ??$begin@V?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AV?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@01@AEAV?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@01@@Z ??$begin@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AV?$__wrap_iter@PEAPEBVCommandLineFlag@absl@@@01@AEAV?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@01@@Z @@ -1535,6 +1545,7 @@ EXPORTS ??$max_size@V?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@U?$AlignedType@$07@container_internal@absl@@@12@@Z ??$max_size@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@12@@Z ??$max_size@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@12@@Z + ??$max_size@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@12@@Z ??$max_size@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@@Z ??$max_size@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@UPayload@status_internal@absl@@@12@@Z ??$max_size@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@12@@Z @@ -1606,6 +1617,8 @@ EXPORTS ??0?$BigUnsigned@$0FE@@strings_internal@absl@@QEAA@XZ ??0?$BigUnsigned@$0FE@@strings_internal@absl@@QEAA@_K@Z ??0?$BitMask@_K$07$02$00@container_internal@absl@@QEAA@_K@Z + ??0?$BitMask@_K$07$02$0A@@container_internal@absl@@QEAA@_K@Z + ??0?$BoundedUtf8LengthSequence@$0BAA@@debugging_internal@absl@@QEAA@XZ ??0?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@QEAA@_KAEBV?$allocator@D@__Cr@std@@@Z ??0?$FlagRegistrar@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@$00@flags_internal@absl@@QEAA@AEAV?$Flag@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@12@PEBD@Z ??0?$FormatSpecTemplate@$0BPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0IAAAE@$0JPPPL@$0EAAAE@$0IAAAE@@str_format_internal@absl@@QEAA@PEBD@Z @@ -1753,6 +1766,7 @@ EXPORTS ??0?$__non_trivial_if@$00V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@XZ + ??0?$__non_trivial_if@$00V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ @@ -1828,6 +1842,7 @@ EXPORTS ??0?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ + ??0?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@QEAA@XZ ??0?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAA@XZ ??0?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QEAA@XZ ??0?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QEAA@XZ @@ -2025,6 +2040,7 @@ EXPORTS ??0LogMessageQuietlyFatal@log_internal@absl@@QEAA@PEBDHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0LogSink@absl@@IEAA@XZ ??0Long@Rep@CordBuffer@absl@@QEAA@PEAUCordRepFlat@cord_internal@3@@Z + ??0MaskedPointer@flags_internal@absl@@QEAA@PEAX_N@Z ??0MixingHashState@hash_internal@absl@@AEAA@XZ ??0MixingHashState@hash_internal@absl@@AEAA@_K@Z ??0Mutex@absl@@QEAA@XZ @@ -2089,6 +2105,7 @@ EXPORTS ??0UnrecognizedFlag@absl@@QEAA@W4Source@01@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0UntypedFormatSpec@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0UntypedFormatSpecImpl@str_format_internal@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z + ??0Utf8ForCodePoint@debugging_internal@absl@@QEAA@_K@Z ??0ViableSubstitution@strings_internal@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@0_K@Z ??0Win32Waiter@synchronization_internal@absl@@QEAA@XZ ??0WriterMutexLock@absl@@QEAA@PEAVMutex@1@@Z @@ -2399,6 +2416,7 @@ EXPORTS ??9absl@@YA_NVint128@0@0@Z ??9absl@@YA_NVuint128@0@0@Z ??9container_internal@absl@@YA_NAEBV?$BitMask@_K$07$02$00@01@0@Z + ??9container_internal@absl@@YA_NAEBV?$BitMask@_K$07$02$0A@@01@0@Z ??9container_internal@absl@@YA_NAEBViterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@0@Z ??9strings_internal@absl@@YA_NAEBV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@01@0@Z ??9strings_internal@absl@@YA_NAEBV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@01@0@Z @@ -2469,6 +2487,7 @@ EXPORTS ??CChunkIterator@Cord@absl@@QEBAPEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ??Citerator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@QEBAPEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@XZ ??D?$BitMask@_K$07$02$00@container_internal@absl@@QEBAIXZ + ??D?$BitMask@_K$07$02$0A@@container_internal@absl@@QEBAIXZ ??D?$NoDestructor@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@absl@@QEAAAEAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@1@XZ ??D?$NoDestructor@VFlagRegistry@flags_internal@absl@@@absl@@QEAAAEAVFlagRegistry@flags_internal@1@XZ ??D?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QEBAAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ @@ -2508,6 +2527,7 @@ EXPORTS ??Dabsl@@YA?AVuint128@0@V10@0@Z ??Diterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@QEBAAEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@XZ ??E?$BitMask@_K$07$02$00@container_internal@absl@@QEAAAEAV012@XZ + ??E?$BitMask@_K$07$02$0A@@container_internal@absl@@QEAAAEAV012@XZ ??E?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QEAAAEAV012@XZ ??E?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QEAAAEAV012@XZ ??E?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QEAAAEAV012@XZ @@ -2584,6 +2604,7 @@ EXPORTS ??Pabsl@@YA_NVDuration@0@0@Z ??Pabsl@@YA_NVint128@0@0@Z ??Pabsl@@YA_NVuint128@0@0@Z + ??R@?0???$AssertHashEqConsistent@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@IEAAXAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z@QEBA?A?@@PEBW4ctrl_t@23@PEAT?$map_slot_type@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@23@@Z ??R@?0???$Initialize@V?$IteratorValueAdapter@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@PEBVFormatArgImpl@str_format_internal@absl@@@inlined_vector_internal@absl@@@?$Storage@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXV?$IteratorValueAdapter@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@PEBVFormatArgImpl@str_format_internal@absl@@@23@_K@Z@QEBA?A?@@XZ ??R@?0???A?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@QEAAAEAD_K@Z@QEBA?A?@@XZ ??R@?0???A?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEAAAEAUPayload@status_internal@2@_K@Z@QEBA?A?@@XZ @@ -2778,7 +2799,6 @@ EXPORTS ?AdvanceBytesBtree@ChunkIterator@Cord@absl@@AEAAX_K@Z ?AlignBegin@CordRepBtree@cord_internal@absl@@AEAAXXZ ?AlignEnd@CordRepBtree@cord_internal@absl@@AEAAXXZ - ?AlignedBufferValue@FlagImpl@flags_internal@absl@@AEBAPEAXXZ ?Alloc@flags_internal@absl@@YAPEAXP6APEAXW4FlagOp@12@PEBXPEAX2@Z@Z ?AllocWithArena@LowLevelAlloc@base_internal@absl@@SAPEAX_KPEAUArena@123@@Z ?Allocate@?$AllocationTransaction@V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAPEAPEAUCordRep@cord_internal@3@_K@Z @@ -2791,6 +2811,7 @@ EXPORTS ?AllocatedSize@CordRepFlat@cord_internal@absl@@QEBA_KXZ ?AllocatedSizeToTag@cord_internal@absl@@YAE_K@Z ?AllocatedSizeToTagUnchecked@cord_internal@absl@@YAE_K@Z + ?AllowsUnprotectedRead@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?AlreadyExistsError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?AlwaysTrue@Condition@absl@@CA_NPEBV12@@Z ?AnnotateConstruct@NonEmptyInlinedStorage@?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@QEAAX_K@Z @@ -2820,6 +2841,7 @@ EXPORTS ?AppendTreeToTree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTruncated@log_internal@absl@@YA_KD_KAEAV?$Span@D@2@@Z ?AppendTruncated@log_internal@absl@@YA_KV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@AEAV?$Span@D@2@@Z + ?ApplyMask@MaskedPointer@flags_internal@absl@@AEAAX_K@Z ?ApplySubstitutions@strings_internal@absl@@YAHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@45@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@45@@Z ?AreItersFromSameContainer@container_internal@absl@@YA_NPEBW4ctrl_t@12@0AEBQEBX1@Z ?AsValueType@?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@CAPEADPEAD@Z @@ -2877,6 +2899,7 @@ EXPORTS ?CheckDefaultValueParsingRoundtrip@PrivateHandleAccessor@flags_internal@absl@@SAXAEBVCommandLineFlag@3@@Z ?CheckFastPathSetting@str_format_internal@absl@@YA_NAEBUUnboundConversion@12@@Z ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ + ?CheckMask@MaskedPointer@flags_internal@absl@@AEBA_N_K@Z ?CheckstrcasecmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcasecmptrueImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z @@ -2978,6 +3001,7 @@ EXPORTS ?DeallocateIfAllocated@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXXZ ?DeallocateIfAllocated@?$Storage@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXXZ ?DecodeFrom@ProtoField@log_internal@absl@@QEAA_NPEAV?$Span@$$CBD@3@@Z + ?DecodeRustPunycode@debugging_internal@absl@@YAPEADUDecodeRustPunycodeOptions@12@@Z ?DecodeWaitCycles@SpinLock@base_internal@absl@@KA_JI@Z ?Decrement@RefcountAndFlags@cord_internal@absl@@QEAA_NXZ ?DecrementCount@BlockingCounter@absl@@QEAA_NXZ @@ -3079,6 +3103,9 @@ EXPORTS ?EncodeStringTruncate@log_internal@absl@@YA_N_KV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$Span@D@2@@Z ?EncodeUTF8Char@strings_internal@absl@@YA_KPEAD_U@Z ?EncodeVarint@log_internal@absl@@YA_N_K0PEAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_KHPEAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_KIPEAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_K_JPEAV?$Span@D@2@@Z ?EncodeWaitCycles@SpinLock@base_internal@absl@@KAI_J0@Z ?EndsWith@Cord@absl@@QEBA_NAEBV12@@Z ?EndsWith@Cord@absl@@QEBA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z @@ -3385,6 +3412,7 @@ EXPORTS ?HandleInvalidStatusCtorArg@Helper@internal_statusor@absl@@SAXPEAVStatus@3@@Z ?HandleUsageFlags@flags_internal@absl@@YA?AW4HelpMode@12@AEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@@Z ?HasBeenNotifiedInternal@Notification@absl@@CA_NPEBU?$atomic@_N@__Cr@std@@@Z + ?HasBeenRead@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?HasEdge@GraphCycles@synchronization_internal@absl@@QEBA_NUGraphId@23@0@Z ?HasInfozMask@CommonFields@container_internal@absl@@CA_KXZ ?HasInfozShift@CommonFields@container_internal@absl@@CA_KXZ @@ -3428,9 +3456,11 @@ EXPORTS ?Initialize@ExponentialBiased@profiling_internal@absl@@AEAAXXZ ?InitializeCordRepExternal@cord_internal@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAUCordRepExternal@12@@Z ?InitializeData@Storage@?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@AEAAPEADXZ + ?InitializeEncodingAndFormat@LogMessageData@LogMessage@log_internal@absl@@QEAAXXZ ?InitializeLog@absl@@YAXXZ ?InitializeSymbolizer@absl@@YAXPEBD@Z ?InlinedRepToCode@Status@absl@@CA?AW4StatusCode@2@_K@Z + ?InsertAndReturnSumOfPredecessors@?$BoundedUtf8LengthSequence@$0BAA@@debugging_internal@absl@@QEAAIII@Z ?InsertEdge@GraphCycles@synchronization_internal@absl@@QEAA_NUGraphId@23@0@Z ?InstallFailureSignalHandler@absl@@YAXAEBUFailureSignalHandlerOptions@1@@Z ?Int128High64@absl@@YA_JVint128@1@@Z @@ -3493,6 +3523,7 @@ EXPORTS ?IsUnavailable@absl@@YA_NAEBVStatus@1@@Z ?IsUnimplemented@absl@@YA_NAEBVStatus@1@@Z ?IsUnknown@absl@@YA_NAEBVStatus@1@@Z + ?IsUnprotectedReadCandidate@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?IsValid@CordRepBtree@cord_internal@absl@@SA_NPEBV123@_N@Z ?IsValidCapacity@container_internal@absl@@YA_N_K@Z ?KeyFunction@LogSink@absl@@EEBAXXZ @@ -3562,9 +3593,11 @@ EXPORTS ?MakeTime@TimeZoneLibC@cctz@time_internal@absl@@UEBA?AUcivil_lookup@time_zone@234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MakeUint128@absl@@YA?AVuint128@1@_K0@Z ?MapToLocalCode@status_internal@absl@@YA?AW4StatusCode@2@H@Z + ?MarkAsRead@MaskedPointer@flags_internal@absl@@QEAAXXZ ?MarkInitialized@SequenceLock@flags_internal@absl@@QEAAXXZ ?MaskEmpty@GroupAArch64Impl@container_internal@absl@@QEBA?AV?$NonIterableBitMask@_K$07$02@23@XZ ?MaskEmptyOrDeleted@GroupPortableImpl@container_internal@absl@@QEBA?AV?$NonIterableBitMask@_K$07$02@23@XZ + ?MaskFull@GroupPortableImpl@container_internal@absl@@QEBA?AV?$BitMask@_K$07$02$0A@@23@XZ ?Match@GroupAArch64Impl@container_internal@absl@@QEBA?A?@@E@Z ?MatchesConversions@ParsedFormatBase@str_format_internal@absl@@AEBA_N_NV?$initializer_list@W4FormatConversionCharSet@absl@@@std@@@Z ?MaxFlatLength@CordTestAccess@strings_internal@absl@@SA_KXZ @@ -3641,6 +3674,7 @@ EXPORTS ?NumClonedBytes@container_internal@absl@@YA_KXZ ?NumControlBytes@container_internal@absl@@YA_K_K@Z ?NumGenerationBytes@container_internal@absl@@YA_KXZ + ?NumLeakedFlagValues@flags_internal@absl@@YA_KXZ ?ODRCheck@CordzInfo@cord_internal@absl@@AEBAXXZ ?OccursBefore@ViableSubstitution@strings_internal@absl@@QEBA_NAEBU123@@Z ?OnUpdate@?$FlagRegistrar@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@$00@flags_internal@absl@@QEHAA?AV123@P6AXXZ@Z @@ -3718,6 +3752,8 @@ EXPORTS ?ProgramInvocationName@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?ProgramUsageMessage@absl@@YA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?Ptr@GraphCycles@synchronization_internal@absl@@QEAAPEAXUGraphId@23@@Z + ?Ptr@MaskedPointer@flags_internal@absl@@QEBAPEAXXZ + ?PtrStorage@FlagImpl@flags_internal@absl@@AEBAAEAU?$atomic@VMaskedPointer@flags_internal@absl@@@__Cr@std@@XZ ?PushDead@?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@AEAAXPEAUHashtablezInfo@container_internal@3@@Z ?PushNew@?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@AEAAXPEAUHashtablezInfo@container_internal@3@@Z ?PutPaddedString@FormatSinkImpl@str_format_internal@absl@@QEAA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@HH_N@Z @@ -3832,6 +3868,7 @@ EXPORTS ?SendToLog@LogMessage@log_internal@absl@@AEAAXXZ ?SentinelEmptyGeneration@container_internal@absl@@YAEXZ ?Set@?$Flag@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@AEAAXAEBV?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@Z + ?Set@MaskedPointer@flags_internal@absl@@QEAAXP6APEAXW4FlagOp@23@PEBXPEAX2@Z1_N@Z ?SetAllocation@?$Storage@PEAUCordRep@cord_internal@absl@@$01V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXU?$Allocation@V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@@23@@Z ?SetAllocation@?$Storage@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXU?$Allocation@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@23@@Z ?SetAllocation@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXU?$Allocation@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@23@@Z @@ -3976,7 +4013,7 @@ EXPORTS ?Store@?$AtomicHook@P6AXXZ@base_internal@absl@@QEAAXP6AXXZ@Z ?Store@?$AtomicHook@P6AX_J@Z@base_internal@absl@@QEAAXP6AX_J@Z@Z ?Store@?$AtomicHook@P6A_NW4LogSeverity@absl@@PEBDHPEAPEADPEAH@Z@base_internal@absl@@QEAAXP6A_NW4LogSeverity@3@PEBDHPEAPEADPEAH@Z@Z - ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBX@Z + ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBXW4ValueSource@23@@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@111@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@11@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@1@Z @@ -4009,6 +4046,7 @@ EXPORTS ?TagToLength@cord_internal@absl@@YA_KE@Z ?TakeRep@Cord@absl@@AEGBAPEAUCordRep@cord_internal@2@XZ ?TakeRep@Cord@absl@@AEHAAPEAUCordRep@cord_internal@2@XZ + ?TestOnlyAddNodes@GraphCycles@synchronization_internal@absl@@QEAAXI@Z ?ThreadIsLoggingToLogSink@log_internal@absl@@YA_NXZ ?ThrowBadStatusOrAccess@internal_statusor@absl@@YAXVStatus@2@@Z ?ThrowBadVariantAccess@variant_internal@absl@@YAXXZ @@ -4751,6 +4789,7 @@ EXPORTS ?allocate@?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@QEAAPEAU?$AlignedType@$07@container_internal@absl@@_K@Z ?allocate@?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@_K@Z ?allocate@?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@_K@Z + ?allocate@?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@QEAAPEAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@56@PEBXPEAX2@Z@_K@Z ?allocate@?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAAPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@_K@Z ?allocate@?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QEAAPEAUPayload@status_internal@absl@@_K@Z ?allocate@?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QEAAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@_K@Z @@ -4770,6 +4809,7 @@ EXPORTS ?allocate@?$allocator_traits@V?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEAU?$AlignedType@$07@container_internal@absl@@AEAV?$allocator@U?$AlignedType@$07@container_internal@absl@@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@AEAV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@AEAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@23@_K@Z + ?allocate@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@@__Cr@std@@SAPEAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@56@PEBXPEAX2@Z@AEAV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEAUPayload@status_internal@absl@@AEAV?$allocator@UPayload@status_internal@absl@@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@V?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPEAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@23@AEAV?$allocator@V?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@__Cr@std@@@23@_K@Z @@ -4821,6 +4861,7 @@ EXPORTS ?base@?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEGBAAEBQEAUTransition@cctz@time_internal@absl@@XZ ?base@?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEGBAAEBQEAUTransitionType@cctz@time_internal@absl@@XZ ?begin@?$BitMask@_K$07$02$00@container_internal@absl@@QEBA?AV123@XZ + ?begin@?$BitMask@_K$07$02$0A@@container_internal@absl@@QEBA?AV123@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEAAPEAUPayload@status_internal@2@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEBAPEBUPayload@status_internal@2@XZ ?begin@?$Span@$$CBI@absl@@QEBAPEBIXZ @@ -4999,6 +5040,7 @@ EXPORTS ?deallocate@?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@QEAAXPEAU?$AlignedType@$07@container_internal@absl@@_K@Z ?deallocate@?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAAXPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@_K@Z ?deallocate@?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@QEAAXPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@_K@Z + ?deallocate@?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@QEAAXPEAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@56@PEBXPEAX2@Z@_K@Z ?deallocate@?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAAXPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@_K@Z ?deallocate@?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QEAAXPEAUPayload@status_internal@absl@@_K@Z ?deallocate@?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QEAAXPEAUPrefixCrc@CrcCordState@crc_internal@absl@@_K@Z @@ -5024,6 +5066,7 @@ EXPORTS ?deallocate@?$allocator_traits@V?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@U?$AlignedType@$07@container_internal@absl@@@23@PEAU?$AlignedType@$07@container_internal@absl@@_K@Z ?deallocate@?$allocator_traits@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@_K@Z ?deallocate@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@23@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@_K@Z + ?deallocate@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@23@PEAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@67@PEBXPEAX3@Z@_K@Z ?deallocate@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@_K@Z ?deallocate@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@UPayload@status_internal@absl@@@23@PEAUPayload@status_internal@absl@@_K@Z ?deallocate@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@23@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@_K@Z @@ -5069,7 +5112,9 @@ EXPORTS ?empty@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_NXZ ?empty@?$vector@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@V?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QEBA_NXZ ?empty@Cord@absl@@QEBA_NXZ + ?encoded_remaining@LogMessageData@LogMessage@log_internal@absl@@QEAAAEAV?$Span@D@4@XZ ?end@?$BitMask@_K$07$02$00@container_internal@absl@@QEBA?AV123@XZ + ?end@?$BitMask@_K$07$02$0A@@container_internal@absl@@QEBA?AV123@XZ ?end@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEAAPEAUPayload@status_internal@2@XZ ?end@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEBAPEBUPayload@status_internal@2@XZ ?end@?$Span@$$CBI@absl@@QEBAPEBIXZ @@ -5369,6 +5414,7 @@ EXPORTS ?load@?$__atomic_base@PEAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QEBAPEAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAVTimeZone@absl@@$0A@@__Cr@std@@QEBAPEAVTimeZone@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QEBAPEAVVLogSite@log_internal@absl@@W4memory_order@23@@Z + ?load@?$__atomic_base@VMaskedPointer@flags_internal@absl@@$0A@@__Cr@std@@QEBA?AVMaskedPointer@flags_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@W4OnDeadlockCycle@absl@@$0A@@__Cr@std@@QEBA?AW4OnDeadlockCycle@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@W4State@PerThreadSynch@base_internal@absl@@$0A@@__Cr@std@@QEBA?AW4State@PerThreadSynch@base_internal@absl@@W4memory_order@23@@Z ?load_time_zone@cctz@time_internal@absl@@YA_NAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEAVtime_zone@123@@Z @@ -5432,6 +5478,7 @@ EXPORTS ?offset@?$probe_seq@$07@container_internal@absl@@QEBA_KXZ ?offset@?$probe_seq@$07@container_internal@absl@@QEBA_K_K@Z ?ok@Status@absl@@QEBA_NXZ + ?ok@Utf8ForCodePoint@debugging_internal@absl@@QEBA_NXZ ?old_capacity@HashSetResizeHelper@container_internal@absl@@QEBA_KXZ ?old_ctrl@HashSetResizeHelper@container_internal@absl@@QEBAPEAW4ctrl_t@23@XZ ?old_heap_or_soo@HashSetResizeHelper@container_internal@absl@@QEAAAEATHeapOrSoo@23@XZ @@ -5727,6 +5774,7 @@ EXPORTS ?soo_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAA?AViterator@123@XZ ?soo_slot@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAAPEAT?$map_slot_type@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@23@XZ ?source_basename@LogEntry@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ + ?source_filename@LogEntry@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?source_line@LogEntry@absl@@QEBAHXZ ?stacktrace@LogEntry@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?status@BadStatusOrAccess@absl@@QEBAAEBVStatus@2@XZ @@ -5735,6 +5783,7 @@ EXPORTS ?store@?$__atomic_base@PEAVCordzHandle@cord_internal@absl@@$0A@@__Cr@std@@QEAAXPEAVCordzHandle@cord_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@PEAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QEAAXPEAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@PEAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QEAAXPEAVVLogSite@log_internal@absl@@W4memory_order@23@@Z + ?store@?$__atomic_base@VMaskedPointer@flags_internal@absl@@$0A@@__Cr@std@@QEAAXVMaskedPointer@flags_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@W4OnDeadlockCycle@absl@@$0A@@__Cr@std@@QEAAXW4OnDeadlockCycle@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@W4State@PerThreadSynch@base_internal@absl@@$0A@@__Cr@std@@QEAAXW4State@PerThreadSynch@base_internal@absl@@W4memory_order@23@@Z ?str@UntypedFormatSpecImpl@str_format_internal@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ @@ -5774,6 +5823,7 @@ EXPORTS ?value@InputValue@UnboundConversion@str_format_internal@absl@@QEBAHXZ ?value_comp@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@QEAAAEAV?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@XZ ?value_comp@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@QEAAAEAV?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@XZ + ?verbosity@LogEntry@absl@@QEBAHXZ ?version@time_zone@cctz@time_internal@absl@@QEBA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?what@BadStatusOrAccess@absl@@UEBAPEBDXZ ?what@SeedGenException@absl@@UEBAPEBDXZ diff --git a/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_rel.def b/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_rel.def index d2f1355ff3..2750976aa2 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_rel.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_arm64_rel.def @@ -216,6 +216,7 @@ EXPORTS ??0LogMessageQuietlyDebugFatal@log_internal@absl@@QEAA@PEBDH@Z ??0LogMessageQuietlyFatal@log_internal@absl@@QEAA@PEBDH@Z ??0LogMessageQuietlyFatal@log_internal@absl@@QEAA@PEBDHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z + ??0MaskedPointer@flags_internal@absl@@QEAA@PEAX_N@Z ??0OstreamView@LogMessage@log_internal@absl@@QEAA@AEAULogMessageData@123@@Z ??0ParsedFormatBase@str_format_internal@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_NV?$initializer_list@W4FormatConversionCharSet@absl@@@5@@Z ??0Randen@random_internal@absl@@QEAA@XZ @@ -226,6 +227,7 @@ EXPORTS ??0StdcppWaiter@synchronization_internal@absl@@QEAA@XZ ??0StringifySink@detect_specialization@log_internal@absl@@QEAA@AEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0TimeZoneLibC@cctz@time_internal@absl@@AEAA@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z + ??0Utf8ForCodePoint@debugging_internal@absl@@QEAA@_K@Z ??0Win32Waiter@synchronization_internal@absl@@QEAA@XZ ??0int128@absl@@QEAA@M@Z ??0int128@absl@@QEAA@N@Z @@ -370,7 +372,6 @@ EXPORTS ?AddressIsReadable@debugging_internal@absl@@YA_NPEBX@Z ?AdvanceAndReadBytes@ChunkIterator@Cord@absl@@AEAA?AV23@_K@Z ?AdvanceBytesBtree@ChunkIterator@Cord@absl@@AEAAX_K@Z - ?AlignedBufferValue@FlagImpl@flags_internal@absl@@AEBAPEAXXZ ?AllocWithArena@LowLevelAlloc@base_internal@absl@@SAPEAX_KPEAUArena@123@@Z ?AlreadyExistsError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?AlwaysTrue@Condition@absl@@CA_NPEBV12@@Z @@ -390,6 +391,7 @@ EXPORTS ?AppendTree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTreeToInlined@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTreeToTree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z + ?ApplyMask@MaskedPointer@flags_internal@absl@@AEAAX_K@Z ?ApplySubstitutions@strings_internal@absl@@YAHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@45@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@45@@Z ?AsciiStrToLower@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z ?AsciiStrToUpper@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z @@ -428,6 +430,7 @@ EXPORTS ?CheckDefaultValueParsingRoundtrip@FlagImpl@flags_internal@absl@@EEBAXXZ ?CheckDefaultValueParsingRoundtrip@PrivateHandleAccessor@flags_internal@absl@@SAXAEBVCommandLineFlag@3@@Z ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ + ?CheckMask@MaskedPointer@flags_internal@absl@@AEBA_N_K@Z ?CheckstrcasecmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcasecmptrueImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z @@ -482,6 +485,7 @@ EXPORTS ?DataLossError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?DeadlineExceededError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?DecodeFrom@ProtoField@log_internal@absl@@QEAA_NPEAV?$Span@$$CBD@3@@Z + ?DecodeRustPunycode@debugging_internal@absl@@YAPEADUDecodeRustPunycodeOptions@12@@Z ?DecodeWaitCycles@SpinLock@base_internal@absl@@KA_JI@Z ?DecrementCount@BlockingCounter@absl@@QEAA_NXZ ?DecrementSynchSem@Mutex@absl@@CA_NPEAV12@PEAUPerThreadSynch@base_internal@2@VKernelTimeout@synchronization_internal@2@@Z @@ -731,6 +735,7 @@ EXPORTS ?HandleInvalidStatusCtorArg@Helper@internal_statusor@absl@@SAXPEAVStatus@3@@Z ?HandleUsageFlags@flags_internal@absl@@YA?AW4HelpMode@12@AEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@@Z ?HasBeenNotifiedInternal@Notification@absl@@CA_NPEBU?$atomic@_N@__Cr@std@@@Z + ?HasBeenRead@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?HasEdge@GraphCycles@synchronization_internal@absl@@QEBA_NUGraphId@23@0@Z ?HasNode@GraphCycles@synchronization_internal@absl@@QEAA_NUGraphId@23@@Z ?HasRandenHwAesImplementation@random_internal@absl@@YA_NXZ @@ -753,6 +758,7 @@ EXPORTS ?InitWhat@BadStatusOrAccess@absl@@AEBAXXZ ?Initialize@ExponentialBiased@profiling_internal@absl@@AEAAXXZ ?InitializeCordRepExternal@cord_internal@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAUCordRepExternal@12@@Z + ?InitializeEncodingAndFormat@LogMessageData@LogMessage@log_internal@absl@@QEAAXXZ ?InitializeLog@absl@@YAXXZ ?InitializeSymbolizer@absl@@YAXPEBD@Z ?InsertEdge@GraphCycles@synchronization_internal@absl@@QEAA_NUGraphId@23@0@Z @@ -789,6 +795,7 @@ EXPORTS ?IsUnavailable@absl@@YA_NAEBVStatus@1@@Z ?IsUnimplemented@absl@@YA_NAEBVStatus@1@@Z ?IsUnknown@absl@@YA_NAEBVStatus@1@@Z + ?IsUnprotectedReadCandidate@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?IsValid@CordRepBtree@cord_internal@absl@@SA_NPEBV123@_N@Z ?KeyFunction@LogSink@absl@@EEBAXXZ ?LengthModToString@str_format_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@W4LengthMod@2@@Z @@ -826,6 +833,7 @@ EXPORTS ?MakeTime@TimeZoneInfo@cctz@time_internal@absl@@UEBA?AUcivil_lookup@time_zone@234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MakeTime@TimeZoneLibC@cctz@time_internal@absl@@UEBA?AUcivil_lookup@time_zone@234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MapToLocalCode@status_internal@absl@@YA?AW4StatusCode@2@H@Z + ?MarkAsRead@MaskedPointer@flags_internal@absl@@QEAAXXZ ?MatchesConversions@ParsedFormatBase@str_format_internal@absl@@AEBA_N_NV?$initializer_list@W4FormatConversionCharSet@absl@@@std@@@Z ?MaxFlatLength@CordTestAccess@strings_internal@absl@@SA_KXZ ?MaxFramesInLogStackTrace@log_internal@absl@@YAHXZ @@ -873,6 +881,7 @@ EXPORTS ?Now@UnscaledCycleClock@base_internal@absl@@CA_JXZ ?Now@absl@@YA?AVTime@1@XZ ?NumCPUs@base_internal@absl@@YAHXZ + ?NumLeakedFlagValues@flags_internal@absl@@YA_KXZ ?OnVLogVerbosityUpdate@log_internal@absl@@YAXV?$function@$$A6AXXZ@__Cr@std@@@Z ?OneTimeInitThreadIdentity@synchronization_internal@absl@@YAXPEAUThreadIdentity@base_internal@2@@Z ?OneWordValue@FlagImpl@flags_internal@absl@@AEBAAEAU?$atomic@_J@__Cr@std@@XZ @@ -930,6 +939,7 @@ EXPORTS ?ProgramInvocationName@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?ProgramUsageMessage@absl@@YA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?Ptr@GraphCycles@synchronization_internal@absl@@QEAAPEAXUGraphId@23@@Z + ?PtrStorage@FlagImpl@flags_internal@absl@@AEBAAEAU?$atomic@VMaskedPointer@flags_internal@absl@@@__Cr@std@@XZ ?PutPaddedString@FormatSinkImpl@str_format_internal@absl@@QEAA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@HH_N@Z ?PutTwoDigits@numbers_internal@absl@@YAXIPEAD@Z ?RawEnableLogPrefix@log_internal@absl@@YAX_N@Z @@ -1000,6 +1010,7 @@ EXPORTS ?Scramble@CRC32@crc_internal@absl@@UEBAXPEAI@Z ?Seek@CordRepBtreeReader@cord_internal@absl@@QEAA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ?SendToLog@LogMessage@log_internal@absl@@AEAAXXZ + ?Set@MaskedPointer@flags_internal@absl@@QEAAXP6APEAXW4FlagOp@23@PEBXPEAX2@Z1_N@Z ?SetAndroidNativeTag@absl@@YAXPEBD@Z ?SetCallback@FlagImpl@flags_internal@absl@@QEAAXQ6AXXZ@Z ?SetCordBtreeExhaustiveValidation@cord_internal@absl@@YAX_N@Z @@ -1076,7 +1087,7 @@ EXPORTS ?StatusMessageAsCStr@absl@@YAPEBDAEBVStatus@1@@Z ?StderrThreshold@absl@@YA?AW4LogSeverityAtLeast@1@XZ ?SteadyClockNow@KernelTimeout@synchronization_internal@absl@@CA_JXZ - ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBX@Z + ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBXW4ValueSource@23@@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@111@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@11@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@1@Z @@ -1096,6 +1107,7 @@ EXPORTS ?SupportsArmCRC32PMULL@crc_internal@absl@@YA_NXZ ?SuppressSigabortTrace@log_internal@absl@@YA_NXZ ?Symbolize@absl@@YA_NPEBXPEADH@Z + ?TestOnlyAddNodes@GraphCycles@synchronization_internal@absl@@QEAAXI@Z ?ThreadIsLoggingToLogSink@log_internal@absl@@YA_NXZ ?ThrowBadStatusOrAccess@internal_statusor@absl@@YAXVStatus@2@@Z ?ThrowBadVariantAccess@variant_internal@absl@@YAXXZ diff --git a/naiveproxy/src/third_party/abseil-cpp/symbols_x64_dbg.def b/naiveproxy/src/third_party/abseil-cpp/symbols_x64_dbg.def index 9e2fcf9138..8f862b473d 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x64_dbg.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x64_dbg.def @@ -524,6 +524,7 @@ EXPORTS ??$AsciiStrCaseFold@$0A@@ascii_internal@absl@@YAXPEAD_K@Z ??$AsciiStrCaseFoldLong@$00@ascii_internal@absl@@YAXPEAD_K@Z ??$AsciiStrCaseFoldLong@$0A@@ascii_internal@absl@@YAXPEAD_K@Z + ??$AssertHashEqConsistent@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@IEAAXAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$AssignElements@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXPEAUPayload@status_internal@1@AEAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@01@_K@Z ??$Base64EscapeInternal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@strings_internal@absl@@YAXPEBE_KPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@_NPEBD@Z ??$BufferSizeFor@$$V@log_internal@absl@@YA_KW4WireType@01@@Z @@ -565,10 +566,12 @@ EXPORTS ??$DeallocateOld@$07V?$allocator@D@__Cr@std@@@HashSetResizeHelper@container_internal@absl@@QEAAXV?$allocator@D@__Cr@std@@_K@Z ??$DeallocateStandard@$07@container_internal@absl@@YAXAEAVCommonFields@01@AEBUPolicyFunctions@01@@Z ??$DecomposePair@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$DecomposePair@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePair@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@Z ??$DecomposePair@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QEAU?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@Z ??$DecomposePair@UFindElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AVconst_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QEAUFindElement@301@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePair@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$DecomposePair@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePairImpl@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@@Z ??$DecomposePairImpl@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@$$QEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@45@@Z ??$DecomposePairImpl@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@45@@Z @@ -789,8 +792,8 @@ EXPORTS ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPEAV012@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPEAV012@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ??$OffsetValue@U?$atomic@_K@__Cr@std@@@FlagImpl@flags_internal@absl@@AEBAPEAU?$atomic@_K@__Cr@std@@XZ + ??$OffsetValue@UFlagMaskedPointerValue@flags_internal@absl@@@FlagImpl@flags_internal@absl@@AEBAPEAUFlagMaskedPointerValue@12@XZ ??$OffsetValue@UFlagOneWordValue@flags_internal@absl@@@FlagImpl@flags_internal@absl@@AEBAPEAUFlagOneWordValue@12@XZ - ??$OffsetValue@X@FlagImpl@flags_internal@absl@@AEBAPEAXXZ ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@$$QEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@Z ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QEAPEAVCommandLineFlag@absl@@@23@@__Cr@std@@$$QEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@$$QEAPEAVCommandLineFlag@1@@Z ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@AEBQEAVCommandLineFlag@absl@@@23@@__Cr@std@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@Z @@ -908,6 +911,7 @@ EXPORTS ??$ToIntVal@_N@FormatArgImpl@str_format_internal@absl@@CAHAEB_N@Z ??$TrailingZeros@G@container_internal@absl@@YAIG@Z ??$TrailingZeros@I@container_internal@absl@@YAII@Z + ??$TrailingZeros@_K@container_internal@absl@@YAI_K@Z ??$TransferRelocatable@$0BI@@container_internal@absl@@YAXPEAX00@Z ??$TypeErasedApplyToSlotFn@UStringHash@container_internal@absl@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@container_internal@absl@@YA_KPEBXPEAX@Z ??$UnhidePtr@X@base_internal@absl@@YAPEAX_K@Z @@ -934,6 +938,7 @@ EXPORTS ??$__allocate_at_least@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@YA?AU?$__allocation_result@PEAUViableSubstitution@strings_internal@absl@@@01@AEAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@_K@Z ??$__allocate_at_least@V?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AU?$__allocation_result@PEAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@01@AEAV?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@01@_K@Z ??$__allocator_destroy@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PEAUUnrecognizedFlag@absl@@PEAU45@@__Cr@std@@YAXAEAV?$allocator@UUnrecognizedFlag@absl@@@01@PEAUUnrecognizedFlag@absl@@1@Z + ??$__annotate_double_ended_contiguous_container@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@YAXPEBX00000@Z ??$__append_with_size@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@_K@Z ??$__assign_with_size_random_access@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AEAAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@_J@Z ??$__call@AEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@AEAVCommandLineFlag@5@@?$__invoke_void_return_wrapper@X$00@__Cr@std@@SAXAEAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QEAAXXZ@AEAVCommandLineFlag@7@@Z @@ -1053,11 +1058,13 @@ EXPORTS ??$__cxx_atomic_load@PEAVCordzInfo@cord_internal@absl@@@__Cr@std@@YAPEAVCordzInfo@cord_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAVCordzInfo@cord_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PEAVTimeZone@absl@@@__Cr@std@@YAPEAVTimeZone@absl@@PEBU?$__cxx_atomic_base_impl@PEAVTimeZone@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YAPEAVVLogSite@log_internal@absl@@PEBU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@W4memory_order@01@@Z + ??$__cxx_atomic_load@VMaskedPointer@flags_internal@absl@@@__Cr@std@@YA?AVMaskedPointer@flags_internal@absl@@PEBU?$__cxx_atomic_base_impl@VMaskedPointer@flags_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@W4OnDeadlockCycle@absl@@@__Cr@std@@YA?AW4OnDeadlockCycle@absl@@PEBU?$__cxx_atomic_base_impl@W4OnDeadlockCycle@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@W4State@PerThreadSynch@base_internal@absl@@@__Cr@std@@YA?AW4State@PerThreadSynch@base_internal@absl@@PEBU?$__cxx_atomic_base_impl@W4State@PerThreadSynch@base_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_store@PEAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@PEAVCordzHandle@cord_internal@absl@@@01@PEAVCordzHandle@cord_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@PEAVCordzInfo@cord_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@PEAVCordzInfo@cord_internal@absl@@@01@PEAVCordzInfo@cord_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@PEAVVLogSite@log_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@PEAVVLogSite@log_internal@absl@@@01@PEAVVLogSite@log_internal@absl@@W4memory_order@01@@Z + ??$__cxx_atomic_store@VMaskedPointer@flags_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@VMaskedPointer@flags_internal@absl@@@01@VMaskedPointer@flags_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@W4OnDeadlockCycle@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@W4OnDeadlockCycle@absl@@@01@W4OnDeadlockCycle@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@W4State@PerThreadSynch@base_internal@absl@@@__Cr@std@@YAXPEAU?$__cxx_atomic_base_impl@W4State@PerThreadSynch@base_internal@absl@@@01@W4State@PerThreadSynch@base_internal@absl@@W4memory_order@01@@Z ??$__debug_randomize_range@U_ClassicAlgPolicy@__Cr@std@@PEAPEAVCommandLineFlag@absl@@PEAPEAV45@@__Cr@std@@YAXPEAPEAVCommandLineFlag@absl@@0@Z @@ -1106,9 +1113,9 @@ EXPORTS ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__tree_iterator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@23@_J@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__tree_iterator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@PEAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@PEAX@23@_J@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z + ??$__find@PEAPEAVLogSink@absl@@PEAPEAV12@PEAV12@U__identity@__Cr@std@@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0AEBQEAV23@AEAU__identity@01@@Z ??$__find_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@AEAAAEAPEAV?$__tree_node_base@PEAX@12@AEAPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??$__find_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@AEAAAEAPEAV?$__tree_node_base@PEAX@12@AEAPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z - ??$__find_impl@PEAPEAVLogSink@absl@@PEAPEAV12@PEAV12@U__identity@__Cr@std@@@__Cr@std@@YAPEAPEAVLogSink@absl@@PEAPEAV23@0AEBQEAV23@AEAU__identity@01@@Z ??$__for_each_segment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@?$__copy_impl@U_ClassicAlgPolicy@__Cr@std@@@23@@__Cr@std@@YAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@?$__copy_impl@U_ClassicAlgPolicy@__Cr@std@@@01@@Z ??$__insert_with_size@V?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@__Cr@std@@V123@@?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEAA?AV?$__wrap_iter@PEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$__wrap_iter@PEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@12@1_J@Z ??$__invoke@AEAUByCivilTime@Transition@cctz@time_internal@absl@@AEBU2345@AEBU2345@@__Cr@std@@YA_NAEAUByCivilTime@Transition@cctz@time_internal@absl@@AEBU3456@1@Z @@ -1245,6 +1252,8 @@ EXPORTS ??$advance@V?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@__Cr@std@@_J_J$0A@@__Cr@std@@YAXAEAV?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@01@_J@Z ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_N$$QEAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@45@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@45@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QEAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QEAU?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@45@@Z @@ -1253,6 +1262,8 @@ EXPORTS ??$apply@UFindElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA?AVconst_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QEAUFindElement@412@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@SA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_K$$QEAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AEBU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$assign@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@$0A@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@12@0@Z ??$begin@V?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AV?$__wrap_iter@PEAPEAVCommandLineFlag@absl@@@01@AEAV?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@01@@Z ??$begin@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AV?$__wrap_iter@PEAPEBVCommandLineFlag@absl@@@01@AEAV?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@01@@Z @@ -1535,6 +1546,7 @@ EXPORTS ??$max_size@V?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@U?$AlignedType@$07@container_internal@absl@@@12@@Z ??$max_size@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@12@@Z ??$max_size@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@12@@Z + ??$max_size@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@12@@Z ??$max_size@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@@Z ??$max_size@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@UPayload@status_internal@absl@@@12@@Z ??$max_size@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SA_KAEBV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@12@@Z @@ -1606,6 +1618,8 @@ EXPORTS ??0?$BigUnsigned@$0FE@@strings_internal@absl@@QEAA@XZ ??0?$BigUnsigned@$0FE@@strings_internal@absl@@QEAA@_K@Z ??0?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QEAA@G@Z + ??0?$BitMask@_K$07$02$0A@@container_internal@absl@@QEAA@_K@Z + ??0?$BoundedUtf8LengthSequence@$0BAA@@debugging_internal@absl@@QEAA@XZ ??0?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@QEAA@_KAEBV?$allocator@D@__Cr@std@@@Z ??0?$FlagRegistrar@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@$00@flags_internal@absl@@QEAA@AEAV?$Flag@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@12@PEBD@Z ??0?$FormatSpecTemplate@$0BPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0IAAAE@$0JPPPL@$0EAAAE@$0IAAAE@@str_format_internal@absl@@QEAA@PEBD@Z @@ -1623,6 +1637,7 @@ EXPORTS ??0?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$move_iterator@PEAUPayload@status_internal@absl@@@23@@inlined_vector_internal@absl@@QEAA@AEBV?$move_iterator@PEAUPayload@status_internal@absl@@@__Cr@std@@@Z ??0?$IteratorValueAdapter@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@PEBVFormatArgImpl@str_format_internal@absl@@@inlined_vector_internal@absl@@QEAA@AEBQEBVFormatArgImpl@str_format_internal@2@@Z ??0?$NonIterableBitMask@G$0BA@$0A@@container_internal@absl@@QEAA@G@Z + ??0?$NonIterableBitMask@_K$07$02@container_internal@absl@@QEAA@_K@Z ??0?$RandenPool@E@random_internal@absl@@QEAA@XZ ??0?$RandenPool@G@random_internal@absl@@QEAA@XZ ??0?$RandenPool@I@random_internal@absl@@QEAA@XZ @@ -1753,6 +1768,7 @@ EXPORTS ??0?$__non_trivial_if@$00V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@QEAA@XZ + ??0?$__non_trivial_if@$00V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$__non_trivial_if@$00V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ @@ -1828,6 +1844,7 @@ EXPORTS ??0?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@QEAA@XZ ??0?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QEAA@XZ + ??0?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@QEAA@XZ ??0?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAA@XZ ??0?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QEAA@XZ ??0?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QEAA@XZ @@ -1987,6 +2004,7 @@ EXPORTS ??0FormatConversionSpecImpl@str_format_internal@absl@@QEAA@XZ ??0FormatSinkImpl@str_format_internal@absl@@QEAA@VFormatRawSinkImpl@12@@Z ??0GraphCycles@synchronization_internal@absl@@QEAA@XZ + ??0GroupPortableImpl@container_internal@absl@@QEAA@PEBW4ctrl_t@12@@Z ??0GroupSse2Impl@container_internal@absl@@QEAA@PEBW4ctrl_t@12@@Z ??0HashSetIteratorGenerationInfoDisabled@container_internal@absl@@QEAA@PEBE@Z ??0HashSetResizeHelper@container_internal@absl@@QEAA@AEAVCommonFields@12@_N1VHashtablezInfoHandle@12@@Z @@ -2024,6 +2042,7 @@ EXPORTS ??0LogMessageQuietlyFatal@log_internal@absl@@QEAA@PEBDHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0LogSink@absl@@IEAA@XZ ??0Long@Rep@CordBuffer@absl@@QEAA@PEAUCordRepFlat@cord_internal@3@@Z + ??0MaskedPointer@flags_internal@absl@@QEAA@PEAX_N@Z ??0MixingHashState@hash_internal@absl@@AEAA@XZ ??0MixingHashState@hash_internal@absl@@AEAA@_K@Z ??0Mutex@absl@@QEAA@XZ @@ -2088,6 +2107,7 @@ EXPORTS ??0UnrecognizedFlag@absl@@QEAA@W4Source@01@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0UntypedFormatSpec@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0UntypedFormatSpecImpl@str_format_internal@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z + ??0Utf8ForCodePoint@debugging_internal@absl@@QEAA@_K@Z ??0ViableSubstitution@strings_internal@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@0_K@Z ??0Win32Waiter@synchronization_internal@absl@@QEAA@XZ ??0WriterMutexLock@absl@@QEAA@PEAVMutex@1@@Z @@ -2398,6 +2418,7 @@ EXPORTS ??9absl@@YA_NVint128@0@0@Z ??9absl@@YA_NVuint128@0@0@Z ??9container_internal@absl@@YA_NAEBV?$BitMask@G$0BA@$0A@$0A@@01@0@Z + ??9container_internal@absl@@YA_NAEBV?$BitMask@_K$07$02$0A@@01@0@Z ??9container_internal@absl@@YA_NAEBViterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@0@Z ??9strings_internal@absl@@YA_NAEBV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@01@0@Z ??9strings_internal@absl@@YA_NAEBV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@01@0@Z @@ -2468,6 +2489,7 @@ EXPORTS ??CChunkIterator@Cord@absl@@QEBAPEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ??Citerator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@QEBAPEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@XZ ??D?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QEBAIXZ + ??D?$BitMask@_K$07$02$0A@@container_internal@absl@@QEBAIXZ ??D?$NoDestructor@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@absl@@QEAAAEAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@1@XZ ??D?$NoDestructor@VFlagRegistry@flags_internal@absl@@@absl@@QEAAAEAVFlagRegistry@flags_internal@1@XZ ??D?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QEBAAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ @@ -2507,6 +2529,7 @@ EXPORTS ??Dabsl@@YA?AVuint128@0@V10@0@Z ??Diterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@QEBAAEAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@XZ ??E?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QEAAAEAV012@XZ + ??E?$BitMask@_K$07$02$0A@@container_internal@absl@@QEAAAEAV012@XZ ??E?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QEAAAEAV012@XZ ??E?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QEAAAEAV012@XZ ??E?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QEAAAEAV012@XZ @@ -2583,6 +2606,7 @@ EXPORTS ??Pabsl@@YA_NVDuration@0@0@Z ??Pabsl@@YA_NVint128@0@0@Z ??Pabsl@@YA_NVuint128@0@0@Z + ??R@?0???$AssertHashEqConsistent@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@IEAAXAEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z@QEBA?A?@@PEBW4ctrl_t@23@PEAT?$map_slot_type@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@23@@Z ??R@?0???$Initialize@V?$IteratorValueAdapter@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@PEBVFormatArgImpl@str_format_internal@absl@@@inlined_vector_internal@absl@@@?$Storage@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXV?$IteratorValueAdapter@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@PEBVFormatArgImpl@str_format_internal@absl@@@23@_K@Z@QEBA?A?@@XZ ??R@?0???A?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@QEAAAEAD_K@Z@QEBA?A?@@XZ ??R@?0???A?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEAAAEAUPayload@status_internal@2@_K@Z@QEBA?A?@@XZ @@ -2777,7 +2801,6 @@ EXPORTS ?AdvanceBytesBtree@ChunkIterator@Cord@absl@@AEAAX_K@Z ?AlignBegin@CordRepBtree@cord_internal@absl@@AEAAXXZ ?AlignEnd@CordRepBtree@cord_internal@absl@@AEAAXXZ - ?AlignedBufferValue@FlagImpl@flags_internal@absl@@AEBAPEAXXZ ?Alloc@flags_internal@absl@@YAPEAXP6APEAXW4FlagOp@12@PEBXPEAX2@Z@Z ?AllocWithArena@LowLevelAlloc@base_internal@absl@@SAPEAX_KPEAUArena@123@@Z ?Allocate@?$AllocationTransaction@V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAPEAPEAUCordRep@cord_internal@3@_K@Z @@ -2790,6 +2813,7 @@ EXPORTS ?AllocatedSize@CordRepFlat@cord_internal@absl@@QEBA_KXZ ?AllocatedSizeToTag@cord_internal@absl@@YAE_K@Z ?AllocatedSizeToTagUnchecked@cord_internal@absl@@YAE_K@Z + ?AllowsUnprotectedRead@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?AlreadyExistsError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?AlwaysTrue@Condition@absl@@CA_NPEBV12@@Z ?AnnotateConstruct@NonEmptyInlinedStorage@?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@QEAAX_K@Z @@ -2819,6 +2843,7 @@ EXPORTS ?AppendTreeToTree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTruncated@log_internal@absl@@YA_KD_KAEAV?$Span@D@2@@Z ?AppendTruncated@log_internal@absl@@YA_KV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@AEAV?$Span@D@2@@Z + ?ApplyMask@MaskedPointer@flags_internal@absl@@AEAAX_K@Z ?ApplySubstitutions@strings_internal@absl@@YAHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@45@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@45@@Z ?AreItersFromSameContainer@container_internal@absl@@YA_NPEBW4ctrl_t@12@0AEBQEBX1@Z ?AsValueType@?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@CAPEADPEAD@Z @@ -2876,6 +2901,7 @@ EXPORTS ?CheckDefaultValueParsingRoundtrip@PrivateHandleAccessor@flags_internal@absl@@SAXAEBVCommandLineFlag@3@@Z ?CheckFastPathSetting@str_format_internal@absl@@YA_NAEBUUnboundConversion@12@@Z ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ + ?CheckMask@MaskedPointer@flags_internal@absl@@AEBA_N_K@Z ?CheckstrcasecmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcasecmptrueImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z @@ -2977,6 +3003,7 @@ EXPORTS ?DeallocateIfAllocated@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXXZ ?DeallocateIfAllocated@?$Storage@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXXZ ?DecodeFrom@ProtoField@log_internal@absl@@QEAA_NPEAV?$Span@$$CBD@3@@Z + ?DecodeRustPunycode@debugging_internal@absl@@YAPEADUDecodeRustPunycodeOptions@12@@Z ?DecodeWaitCycles@SpinLock@base_internal@absl@@KA_JI@Z ?Decrement@RefcountAndFlags@cord_internal@absl@@QEAA_NXZ ?DecrementCount@BlockingCounter@absl@@QEAA_NXZ @@ -3078,6 +3105,9 @@ EXPORTS ?EncodeStringTruncate@log_internal@absl@@YA_N_KV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$Span@D@2@@Z ?EncodeUTF8Char@strings_internal@absl@@YA_KPEAD_U@Z ?EncodeVarint@log_internal@absl@@YA_N_K0PEAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_KHPEAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_KIPEAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_K_JPEAV?$Span@D@2@@Z ?EncodeWaitCycles@SpinLock@base_internal@absl@@KAI_J0@Z ?EndsWith@Cord@absl@@QEBA_NAEBV12@@Z ?EndsWith@Cord@absl@@QEBA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z @@ -3384,6 +3414,7 @@ EXPORTS ?HandleInvalidStatusCtorArg@Helper@internal_statusor@absl@@SAXPEAVStatus@3@@Z ?HandleUsageFlags@flags_internal@absl@@YA?AW4HelpMode@12@AEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@@Z ?HasBeenNotifiedInternal@Notification@absl@@CA_NPEBU?$atomic@_N@__Cr@std@@@Z + ?HasBeenRead@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?HasEdge@GraphCycles@synchronization_internal@absl@@QEBA_NUGraphId@23@0@Z ?HasInfozMask@CommonFields@container_internal@absl@@CA_KXZ ?HasInfozShift@CommonFields@container_internal@absl@@CA_KXZ @@ -3427,9 +3458,11 @@ EXPORTS ?Initialize@ExponentialBiased@profiling_internal@absl@@AEAAXXZ ?InitializeCordRepExternal@cord_internal@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAUCordRepExternal@12@@Z ?InitializeData@Storage@?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@AEAAPEADXZ + ?InitializeEncodingAndFormat@LogMessageData@LogMessage@log_internal@absl@@QEAAXXZ ?InitializeLog@absl@@YAXXZ ?InitializeSymbolizer@absl@@YAXPEBD@Z ?InlinedRepToCode@Status@absl@@CA?AW4StatusCode@2@_K@Z + ?InsertAndReturnSumOfPredecessors@?$BoundedUtf8LengthSequence@$0BAA@@debugging_internal@absl@@QEAAIII@Z ?InsertEdge@GraphCycles@synchronization_internal@absl@@QEAA_NUGraphId@23@0@Z ?InstallFailureSignalHandler@absl@@YAXAEBUFailureSignalHandlerOptions@1@@Z ?Int128High64@absl@@YA_JVint128@1@@Z @@ -3492,6 +3525,7 @@ EXPORTS ?IsUnavailable@absl@@YA_NAEBVStatus@1@@Z ?IsUnimplemented@absl@@YA_NAEBVStatus@1@@Z ?IsUnknown@absl@@YA_NAEBVStatus@1@@Z + ?IsUnprotectedReadCandidate@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?IsValid@CordRepBtree@cord_internal@absl@@SA_NPEBV123@_N@Z ?IsValidCapacity@container_internal@absl@@YA_N_K@Z ?KeyFunction@LogSink@absl@@EEBAXXZ @@ -3535,6 +3569,7 @@ EXPORTS ?LowLevelHashImpl@MixingHashState@hash_internal@absl@@CA_KPEBE_K@Z ?LowLevelHashLenGt16@hash_internal@absl@@YA_KPEBX_K1QEB_K@Z ?LowestBitSet@?$NonIterableBitMask@G$0BA@$0A@@container_internal@absl@@QEBAIXZ + ?LowestBitSet@?$NonIterableBitMask@_K$07$02@container_internal@absl@@QEBAIXZ ?Make@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@67@@Z ?Make@TimeZoneInfo@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneInfo@cctz@time_internal@absl@@U?$default_delete@VTimeZoneInfo@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@67@@Z ?Make@TimeZoneLibC@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneLibC@cctz@time_internal@absl@@U?$default_delete@VTimeZoneLibC@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@67@@Z @@ -3561,9 +3596,12 @@ EXPORTS ?MakeTime@TimeZoneLibC@cctz@time_internal@absl@@UEBA?AUcivil_lookup@time_zone@234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MakeUint128@absl@@YA?AVuint128@1@_K0@Z ?MapToLocalCode@status_internal@absl@@YA?AW4StatusCode@2@H@Z + ?MarkAsRead@MaskedPointer@flags_internal@absl@@QEAAXXZ ?MarkInitialized@SequenceLock@flags_internal@absl@@QEAAXXZ ?MaskEmpty@GroupSse2Impl@container_internal@absl@@QEBA?AV?$NonIterableBitMask@G$0BA@$0A@@23@XZ ?MaskEmptyOrDeleted@GroupSse2Impl@container_internal@absl@@QEBA?AV?$NonIterableBitMask@G$0BA@$0A@@23@XZ + ?MaskFull@GroupPortableImpl@container_internal@absl@@QEBA?AV?$BitMask@_K$07$02$0A@@23@XZ + ?MaskFull@GroupSse2Impl@container_internal@absl@@QEBA?AV?$BitMask@G$0BA@$0A@$0A@@23@XZ ?Match@GroupSse2Impl@container_internal@absl@@QEBA?AV?$BitMask@G$0BA@$0A@$0A@@23@E@Z ?MatchesConversions@ParsedFormatBase@str_format_internal@absl@@AEBA_N_NV?$initializer_list@W4FormatConversionCharSet@absl@@@std@@@Z ?MaxFlatLength@CordTestAccess@strings_internal@absl@@SA_KXZ @@ -3640,6 +3678,7 @@ EXPORTS ?NumClonedBytes@container_internal@absl@@YA_KXZ ?NumControlBytes@container_internal@absl@@YA_K_K@Z ?NumGenerationBytes@container_internal@absl@@YA_KXZ + ?NumLeakedFlagValues@flags_internal@absl@@YA_KXZ ?ODRCheck@CordzInfo@cord_internal@absl@@AEBAXXZ ?OccursBefore@ViableSubstitution@strings_internal@absl@@QEBA_NAEBU123@@Z ?OnUpdate@?$FlagRegistrar@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@$00@flags_internal@absl@@QEHAA?AV123@P6AXXZ@Z @@ -3717,6 +3756,8 @@ EXPORTS ?ProgramInvocationName@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?ProgramUsageMessage@absl@@YA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?Ptr@GraphCycles@synchronization_internal@absl@@QEAAPEAXUGraphId@23@@Z + ?Ptr@MaskedPointer@flags_internal@absl@@QEBAPEAXXZ + ?PtrStorage@FlagImpl@flags_internal@absl@@AEBAAEAU?$atomic@VMaskedPointer@flags_internal@absl@@@__Cr@std@@XZ ?PushDead@?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@AEAAXPEAUHashtablezInfo@container_internal@3@@Z ?PushNew@?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@AEAAXPEAUHashtablezInfo@container_internal@3@@Z ?PutPaddedString@FormatSinkImpl@str_format_internal@absl@@QEAA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@HH_N@Z @@ -3831,6 +3872,7 @@ EXPORTS ?SendToLog@LogMessage@log_internal@absl@@AEAAXXZ ?SentinelEmptyGeneration@container_internal@absl@@YAEXZ ?Set@?$Flag@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@AEAAXAEBV?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@Z + ?Set@MaskedPointer@flags_internal@absl@@QEAAXP6APEAXW4FlagOp@23@PEBXPEAX2@Z1_N@Z ?SetAllocation@?$Storage@PEAUCordRep@cord_internal@absl@@$01V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXU?$Allocation@V?$allocator@PEAUCordRep@cord_internal@absl@@@__Cr@std@@@23@@Z ?SetAllocation@?$Storage@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXU?$Allocation@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@23@@Z ?SetAllocation@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAXU?$Allocation@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@23@@Z @@ -3975,7 +4017,7 @@ EXPORTS ?Store@?$AtomicHook@P6AXXZ@base_internal@absl@@QEAAXP6AXXZ@Z ?Store@?$AtomicHook@P6AX_J@Z@base_internal@absl@@QEAAXP6AX_J@Z@Z ?Store@?$AtomicHook@P6A_NW4LogSeverity@absl@@PEBDHPEAPEADPEAH@Z@base_internal@absl@@QEAAXP6A_NW4LogSeverity@3@PEBDHPEAPEADPEAH@Z@Z - ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBX@Z + ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBXW4ValueSource@23@@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@111@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@11@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@1@Z @@ -4008,6 +4050,7 @@ EXPORTS ?TagToLength@cord_internal@absl@@YA_KE@Z ?TakeRep@Cord@absl@@AEGBAPEAUCordRep@cord_internal@2@XZ ?TakeRep@Cord@absl@@AEHAAPEAUCordRep@cord_internal@2@XZ + ?TestOnlyAddNodes@GraphCycles@synchronization_internal@absl@@QEAAXI@Z ?ThreadIsLoggingToLogSink@log_internal@absl@@YA_NXZ ?ThrowBadStatusOrAccess@internal_statusor@absl@@YAXVStatus@2@@Z ?ThrowBadVariantAccess@variant_internal@absl@@YAXXZ @@ -4751,6 +4794,7 @@ EXPORTS ?allocate@?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@QEAAPEAU?$AlignedType@$07@container_internal@absl@@_K@Z ?allocate@?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@_K@Z ?allocate@?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@QEAAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@_K@Z + ?allocate@?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@QEAAPEAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@56@PEBXPEAX2@Z@_K@Z ?allocate@?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAAPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@_K@Z ?allocate@?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QEAAPEAUPayload@status_internal@absl@@_K@Z ?allocate@?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QEAAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@_K@Z @@ -4770,6 +4814,7 @@ EXPORTS ?allocate@?$allocator_traits@V?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEAU?$AlignedType@$07@container_internal@absl@@AEAV?$allocator@U?$AlignedType@$07@container_internal@absl@@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@AEAV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@AEAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@23@_K@Z + ?allocate@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@@__Cr@std@@SAPEAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@56@PEBXPEAX2@Z@AEAV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEAUPayload@status_internal@absl@@AEAV?$allocator@UPayload@status_internal@absl@@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SAPEAUPrefixCrc@CrcCordState@crc_internal@absl@@AEAV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@23@_K@Z ?allocate@?$allocator_traits@V?$allocator@V?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPEAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@23@AEAV?$allocator@V?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@__Cr@std@@@23@_K@Z @@ -4821,6 +4866,7 @@ EXPORTS ?base@?$move_iterator@PEAUTransition@cctz@time_internal@absl@@@__Cr@std@@QEGBAAEBQEAUTransition@cctz@time_internal@absl@@XZ ?base@?$move_iterator@PEAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QEGBAAEBQEAUTransitionType@cctz@time_internal@absl@@XZ ?begin@?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QEBA?AV123@XZ + ?begin@?$BitMask@_K$07$02$0A@@container_internal@absl@@QEBA?AV123@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEAAPEAUPayload@status_internal@2@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEBAPEBUPayload@status_internal@2@XZ ?begin@?$Span@$$CBI@absl@@QEBAPEBIXZ @@ -4999,6 +5045,7 @@ EXPORTS ?deallocate@?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@QEAAXPEAU?$AlignedType@$07@container_internal@absl@@_K@Z ?deallocate@?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@QEAAXPEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@_K@Z ?deallocate@?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@QEAAXPEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@_K@Z + ?deallocate@?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@QEAAXPEAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@56@PEBXPEAX2@Z@_K@Z ?deallocate@?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QEAAXPEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@_K@Z ?deallocate@?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QEAAXPEAUPayload@status_internal@absl@@_K@Z ?deallocate@?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QEAAXPEAUPrefixCrc@CrcCordState@crc_internal@absl@@_K@Z @@ -5024,6 +5071,7 @@ EXPORTS ?deallocate@?$allocator_traits@V?$allocator@U?$AlignedType@$07@container_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@U?$AlignedType@$07@container_internal@absl@@@23@PEAU?$AlignedType@$07@container_internal@absl@@_K@Z ?deallocate@?$allocator_traits@V?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@U?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@__Cr@std@@@23@PEAU?$__hash_node@PEBUCordRep@cord_internal@absl@@PEAX@23@_K@Z ?deallocate@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@23@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@23@_K@Z + ?deallocate@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@23@PEBXPEAX2@Z@@23@PEAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@67@PEBXPEAX3@Z@_K@Z ?deallocate@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@PEAUConversionItem@ParsedFormatBase@str_format_internal@absl@@_K@Z ?deallocate@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@UPayload@status_internal@absl@@@23@PEAUPayload@status_internal@absl@@_K@Z ?deallocate@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAEAV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@23@PEAUPrefixCrc@CrcCordState@crc_internal@absl@@_K@Z @@ -5069,7 +5117,9 @@ EXPORTS ?empty@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@QEBA_NXZ ?empty@?$vector@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@V?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QEBA_NXZ ?empty@Cord@absl@@QEBA_NXZ + ?encoded_remaining@LogMessageData@LogMessage@log_internal@absl@@QEAAAEAV?$Span@D@4@XZ ?end@?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QEBA?AV123@XZ + ?end@?$BitMask@_K$07$02$0A@@container_internal@absl@@QEBA?AV123@XZ ?end@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEAAPEAUPayload@status_internal@2@XZ ?end@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QEBAPEBUPayload@status_internal@2@XZ ?end@?$Span@$$CBI@absl@@QEBAPEBIXZ @@ -5369,6 +5419,7 @@ EXPORTS ?load@?$__atomic_base@PEAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QEBAPEAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAVTimeZone@absl@@$0A@@__Cr@std@@QEBAPEAVTimeZone@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PEAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QEBAPEAVVLogSite@log_internal@absl@@W4memory_order@23@@Z + ?load@?$__atomic_base@VMaskedPointer@flags_internal@absl@@$0A@@__Cr@std@@QEBA?AVMaskedPointer@flags_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@W4OnDeadlockCycle@absl@@$0A@@__Cr@std@@QEBA?AW4OnDeadlockCycle@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@W4State@PerThreadSynch@base_internal@absl@@$0A@@__Cr@std@@QEBA?AW4State@PerThreadSynch@base_internal@absl@@W4memory_order@23@@Z ?load_time_zone@cctz@time_internal@absl@@YA_NAEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEAVtime_zone@123@@Z @@ -5432,6 +5483,7 @@ EXPORTS ?offset@?$probe_seq@$0BA@@container_internal@absl@@QEBA_KXZ ?offset@?$probe_seq@$0BA@@container_internal@absl@@QEBA_K_K@Z ?ok@Status@absl@@QEBA_NXZ + ?ok@Utf8ForCodePoint@debugging_internal@absl@@QEBA_NXZ ?old_capacity@HashSetResizeHelper@container_internal@absl@@QEBA_KXZ ?old_ctrl@HashSetResizeHelper@container_internal@absl@@QEBAPEAW4ctrl_t@23@XZ ?old_heap_or_soo@HashSetResizeHelper@container_internal@absl@@QEAAAEATHeapOrSoo@23@XZ @@ -5727,6 +5779,7 @@ EXPORTS ?soo_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAA?AViterator@123@XZ ?soo_slot@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAAPEAT?$map_slot_type@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@23@XZ ?source_basename@LogEntry@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ + ?source_filename@LogEntry@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?source_line@LogEntry@absl@@QEBAHXZ ?stacktrace@LogEntry@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?status@BadStatusOrAccess@absl@@QEBAAEBVStatus@2@XZ @@ -5735,6 +5788,7 @@ EXPORTS ?store@?$__atomic_base@PEAVCordzHandle@cord_internal@absl@@$0A@@__Cr@std@@QEAAXPEAVCordzHandle@cord_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@PEAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QEAAXPEAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@PEAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QEAAXPEAVVLogSite@log_internal@absl@@W4memory_order@23@@Z + ?store@?$__atomic_base@VMaskedPointer@flags_internal@absl@@$0A@@__Cr@std@@QEAAXVMaskedPointer@flags_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@W4OnDeadlockCycle@absl@@$0A@@__Cr@std@@QEAAXW4OnDeadlockCycle@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@W4State@PerThreadSynch@base_internal@absl@@$0A@@__Cr@std@@QEAAXW4State@PerThreadSynch@base_internal@absl@@W4memory_order@23@@Z ?str@UntypedFormatSpecImpl@str_format_internal@absl@@QEBA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ @@ -5774,6 +5828,7 @@ EXPORTS ?value@InputValue@UnboundConversion@str_format_internal@absl@@QEBAHXZ ?value_comp@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@QEAAAEAV?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@XZ ?value_comp@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@QEAAAEAV?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@XZ + ?verbosity@LogEntry@absl@@QEBAHXZ ?version@time_zone@cctz@time_internal@absl@@QEBA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?what@BadStatusOrAccess@absl@@UEBAPEBDXZ ?what@SeedGenException@absl@@UEBAPEBDXZ diff --git a/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel.def b/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel.def index e598b0478f..c19da738f7 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel.def @@ -219,6 +219,7 @@ EXPORTS ??0LogMessageQuietlyDebugFatal@log_internal@absl@@QEAA@PEBDH@Z ??0LogMessageQuietlyFatal@log_internal@absl@@QEAA@PEBDH@Z ??0LogMessageQuietlyFatal@log_internal@absl@@QEAA@PEBDHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z + ??0MaskedPointer@flags_internal@absl@@QEAA@PEAX_N@Z ??0OstreamView@LogMessage@log_internal@absl@@QEAA@AEAULogMessageData@123@@Z ??0ParsedFormatBase@str_format_internal@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_NV?$initializer_list@W4FormatConversionCharSet@absl@@@5@@Z ??0Randen@random_internal@absl@@QEAA@XZ @@ -229,6 +230,7 @@ EXPORTS ??0StdcppWaiter@synchronization_internal@absl@@QEAA@XZ ??0StringifySink@detect_specialization@log_internal@absl@@QEAA@AEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0TimeZoneLibC@cctz@time_internal@absl@@AEAA@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z + ??0Utf8ForCodePoint@debugging_internal@absl@@QEAA@_K@Z ??0Win32Waiter@synchronization_internal@absl@@QEAA@XZ ??0int128@absl@@QEAA@M@Z ??0int128@absl@@QEAA@N@Z @@ -371,7 +373,6 @@ EXPORTS ?AddressIsReadable@debugging_internal@absl@@YA_NPEBX@Z ?AdvanceAndReadBytes@ChunkIterator@Cord@absl@@AEAA?AV23@_K@Z ?AdvanceBytesBtree@ChunkIterator@Cord@absl@@AEAAX_K@Z - ?AlignedBufferValue@FlagImpl@flags_internal@absl@@AEBAPEAXXZ ?AllocWithArena@LowLevelAlloc@base_internal@absl@@SAPEAX_KPEAUArena@123@@Z ?AlreadyExistsError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?AlwaysTrue@Condition@absl@@CA_NPEBV12@@Z @@ -391,6 +392,7 @@ EXPORTS ?AppendTree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTreeToInlined@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTreeToTree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z + ?ApplyMask@MaskedPointer@flags_internal@absl@@AEAAX_K@Z ?ApplySubstitutions@strings_internal@absl@@YAHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@45@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@45@@Z ?AsciiStrToLower@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z ?AsciiStrToUpper@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z @@ -429,6 +431,7 @@ EXPORTS ?CheckDefaultValueParsingRoundtrip@FlagImpl@flags_internal@absl@@EEBAXXZ ?CheckDefaultValueParsingRoundtrip@PrivateHandleAccessor@flags_internal@absl@@SAXAEBVCommandLineFlag@3@@Z ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ + ?CheckMask@MaskedPointer@flags_internal@absl@@AEBA_N_K@Z ?CheckstrcasecmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcasecmptrueImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z @@ -483,6 +486,7 @@ EXPORTS ?DataLossError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?DeadlineExceededError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?DecodeFrom@ProtoField@log_internal@absl@@QEAA_NPEAV?$Span@$$CBD@3@@Z + ?DecodeRustPunycode@debugging_internal@absl@@YAPEADUDecodeRustPunycodeOptions@12@@Z ?DecodeWaitCycles@SpinLock@base_internal@absl@@KA_JI@Z ?DecrementCount@BlockingCounter@absl@@QEAA_NXZ ?DecrementSynchSem@Mutex@absl@@CA_NPEAV12@PEAUPerThreadSynch@base_internal@2@VKernelTimeout@synchronization_internal@2@@Z @@ -732,6 +736,7 @@ EXPORTS ?HandleInvalidStatusCtorArg@Helper@internal_statusor@absl@@SAXPEAVStatus@3@@Z ?HandleUsageFlags@flags_internal@absl@@YA?AW4HelpMode@12@AEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@@Z ?HasBeenNotifiedInternal@Notification@absl@@CA_NPEBU?$atomic@_N@__Cr@std@@@Z + ?HasBeenRead@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?HasEdge@GraphCycles@synchronization_internal@absl@@QEBA_NUGraphId@23@0@Z ?HasNode@GraphCycles@synchronization_internal@absl@@QEAA_NUGraphId@23@@Z ?HasRandenHwAesImplementation@random_internal@absl@@YA_NXZ @@ -754,6 +759,7 @@ EXPORTS ?InitWhat@BadStatusOrAccess@absl@@AEBAXXZ ?Initialize@ExponentialBiased@profiling_internal@absl@@AEAAXXZ ?InitializeCordRepExternal@cord_internal@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAUCordRepExternal@12@@Z + ?InitializeEncodingAndFormat@LogMessageData@LogMessage@log_internal@absl@@QEAAXXZ ?InitializeLog@absl@@YAXXZ ?InitializeSymbolizer@absl@@YAXPEBD@Z ?InsertEdge@GraphCycles@synchronization_internal@absl@@QEAA_NUGraphId@23@0@Z @@ -790,6 +796,7 @@ EXPORTS ?IsUnavailable@absl@@YA_NAEBVStatus@1@@Z ?IsUnimplemented@absl@@YA_NAEBVStatus@1@@Z ?IsUnknown@absl@@YA_NAEBVStatus@1@@Z + ?IsUnprotectedReadCandidate@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?IsValid@CordRepBtree@cord_internal@absl@@SA_NPEBV123@_N@Z ?KeyFunction@LogSink@absl@@EEBAXXZ ?LengthModToString@str_format_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@W4LengthMod@2@@Z @@ -827,6 +834,7 @@ EXPORTS ?MakeTime@TimeZoneInfo@cctz@time_internal@absl@@UEBA?AUcivil_lookup@time_zone@234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MakeTime@TimeZoneLibC@cctz@time_internal@absl@@UEBA?AUcivil_lookup@time_zone@234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MapToLocalCode@status_internal@absl@@YA?AW4StatusCode@2@H@Z + ?MarkAsRead@MaskedPointer@flags_internal@absl@@QEAAXXZ ?MatchesConversions@ParsedFormatBase@str_format_internal@absl@@AEBA_N_NV?$initializer_list@W4FormatConversionCharSet@absl@@@std@@@Z ?MaxFlatLength@CordTestAccess@strings_internal@absl@@SA_KXZ ?MaxFramesInLogStackTrace@log_internal@absl@@YAHXZ @@ -873,6 +881,7 @@ EXPORTS ?Now@CycleClock@base_internal@absl@@SA_JXZ ?Now@absl@@YA?AVTime@1@XZ ?NumCPUs@base_internal@absl@@YAHXZ + ?NumLeakedFlagValues@flags_internal@absl@@YA_KXZ ?OnVLogVerbosityUpdate@log_internal@absl@@YAXV?$function@$$A6AXXZ@__Cr@std@@@Z ?OneTimeInitThreadIdentity@synchronization_internal@absl@@YAXPEAUThreadIdentity@base_internal@2@@Z ?OneWordValue@FlagImpl@flags_internal@absl@@AEBAAEAU?$atomic@_J@__Cr@std@@XZ @@ -930,6 +939,7 @@ EXPORTS ?ProgramInvocationName@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?ProgramUsageMessage@absl@@YA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?Ptr@GraphCycles@synchronization_internal@absl@@QEAAPEAXUGraphId@23@@Z + ?PtrStorage@FlagImpl@flags_internal@absl@@AEBAAEAU?$atomic@VMaskedPointer@flags_internal@absl@@@__Cr@std@@XZ ?PutPaddedString@FormatSinkImpl@str_format_internal@absl@@QEAA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@HH_N@Z ?PutTwoDigits@numbers_internal@absl@@YAXIPEAD@Z ?RawEnableLogPrefix@log_internal@absl@@YAX_N@Z @@ -1000,6 +1010,7 @@ EXPORTS ?Scramble@CRC32@crc_internal@absl@@UEBAXPEAI@Z ?Seek@CordRepBtreeReader@cord_internal@absl@@QEAA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ?SendToLog@LogMessage@log_internal@absl@@AEAAXXZ + ?Set@MaskedPointer@flags_internal@absl@@QEAAXP6APEAXW4FlagOp@23@PEBXPEAX2@Z1_N@Z ?SetAndroidNativeTag@absl@@YAXPEBD@Z ?SetCallback@FlagImpl@flags_internal@absl@@QEAAXQ6AXXZ@Z ?SetCordBtreeExhaustiveValidation@cord_internal@absl@@YAX_N@Z @@ -1076,7 +1087,7 @@ EXPORTS ?StatusMessageAsCStr@absl@@YAPEBDAEBVStatus@1@@Z ?StderrThreshold@absl@@YA?AW4LogSeverityAtLeast@1@XZ ?SteadyClockNow@KernelTimeout@synchronization_internal@absl@@CA_JXZ - ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBX@Z + ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBXW4ValueSource@23@@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@111@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@11@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@1@Z @@ -1096,6 +1107,7 @@ EXPORTS ?SupportsArmCRC32PMULL@crc_internal@absl@@YA_NXZ ?SuppressSigabortTrace@log_internal@absl@@YA_NXZ ?Symbolize@absl@@YA_NPEBXPEADH@Z + ?TestOnlyAddNodes@GraphCycles@synchronization_internal@absl@@QEAAXI@Z ?ThreadIsLoggingToLogSink@log_internal@absl@@YA_NXZ ?ThrowBadStatusOrAccess@internal_statusor@absl@@YAXVStatus@2@@Z ?ThrowBadVariantAccess@variant_internal@absl@@YAXXZ diff --git a/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel_asan.def b/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel_asan.def index ac61b5f71f..81b86815f2 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel_asan.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x64_rel_asan.def @@ -91,7 +91,6 @@ EXPORTS ??$EmplaceBack@UPayload@status_internal@absl@@@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QEAAAEAUPayload@status_internal@2@$$QEAU342@@Z ??$EmplaceBackSlow@AEBQEAVLogSink@absl@@@?$Storage@PEAVLogSink@absl@@$0BA@V?$allocator@PEAVLogSink@absl@@@__Cr@std@@@inlined_vector_internal@absl@@AEAAAEAPEAVLogSink@2@AEBQEAV32@@Z ??$EmplaceBackSlow@UPayload@status_internal@absl@@@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@AEAAAEAUPayload@status_internal@2@$$QEAU342@@Z - ??$ExtractStringification@UHex@absl@@@strings_internal@absl@@YA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@AEAVStringifySink@01@AEBUHex@1@@Z ??$FindSubstitutions@V?$initializer_list@U?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V123@@__Cr@std@@@std@@@strings_internal@absl@@YA?AV?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@AEBV?$initializer_list@U?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V123@@__Cr@std@@@4@@Z ??$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPEAXW4FlagOp@01@PEBXPEAX2@Z ??$Flush@V?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@FormatRawSinkImpl@str_format_internal@absl@@CAXPEAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z @@ -169,6 +168,8 @@ EXPORTS ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__tree_iterator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PEAX@23@_J@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@$$QEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBUpiecewise_construct_t@23@V?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@QEAA?AU?$pair@V?$__tree_iterator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@PEAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@PEAX@23@_J@__Cr@std@@_N@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@AEBUpiecewise_construct_t@12@$$QEAV?$tuple@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QEAV?$tuple@$$V@12@@Z + ??$__find_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@AEAAAEAPEAV?$__tree_node_base@PEAX@12@AEAPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z + ??$__find_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PEBVCommandLineFlag@absl@@V?$allocator@PEBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@AEAAAEAPEAV?$__tree_node_base@PEAX@12@AEAPEAV?$__tree_end_node@PEAV?$__tree_node_base@PEAX@__Cr@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??$__for_each_segment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@?$__copy_impl@U_ClassicAlgPolicy@__Cr@std@@@23@@__Cr@std@@YAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@01@0U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEBU1234@AEBU1234@PEBQEBU1234@_J$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PEAU1234@AEAU1234@PEAPEAU1234@_J$0A@@23@@?$__copy_impl@U_ClassicAlgPolicy@__Cr@std@@@01@@Z ??$__insert_with_size@V?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@__Cr@std@@V123@@?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEAA?AV?$__wrap_iter@PEAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$__wrap_iter@PEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$__wrap_iter@PEAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QEBA?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AEBV345@@Z@@12@1_J@Z ??$__push_back_slow_path@AEBQEAVCommandLineFlag@absl@@@?$vector@PEAVCommandLineFlag@absl@@V?$allocator@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@AEAAPEAPEAVCommandLineFlag@absl@@AEBQEAV34@@Z @@ -186,7 +187,6 @@ EXPORTS ??$emplace_back@$$V@?$__split_buffer@UTransition@cctz@time_internal@absl@@AEAV?$allocator@UTransition@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ??$emplace_back@$$V@?$__split_buffer@UTransitionType@cctz@time_internal@absl@@AEAV?$allocator@UTransitionType@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAXXZ ??$emplace_back@HVcrc32c_t@absl@@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QEAAAEAUPrefixCrc@CrcCordState@crc_internal@absl@@$$QEAH$$QEAVcrc32c_t@6@@Z - ??$find@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QEAA?AV?$__hash_iterator@PEAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PEAX@__Cr@std@@@12@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??$find_first_non_full@X@container_internal@absl@@YA?AUFindInfo@01@AEBVCommonFields@01@_K@Z ??$find_or_prepare_insert_non_soo@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@AEBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@45@@Z ??0?$BigUnsigned@$03@strings_internal@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z @@ -245,6 +245,7 @@ EXPORTS ??0LogMessageQuietlyDebugFatal@log_internal@absl@@QEAA@PEBDH@Z ??0LogMessageQuietlyFatal@log_internal@absl@@QEAA@PEBDH@Z ??0LogMessageQuietlyFatal@log_internal@absl@@QEAA@PEBDHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z + ??0MaskedPointer@flags_internal@absl@@QEAA@PEAX_N@Z ??0OstreamView@LogMessage@log_internal@absl@@QEAA@AEAULogMessageData@123@@Z ??0ParsedFormatBase@str_format_internal@absl@@QEAA@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_NV?$initializer_list@W4FormatConversionCharSet@absl@@@5@@Z ??0Randen@random_internal@absl@@QEAA@XZ @@ -255,6 +256,7 @@ EXPORTS ??0StdcppWaiter@synchronization_internal@absl@@QEAA@XZ ??0StringifySink@detect_specialization@log_internal@absl@@QEAA@AEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0TimeZoneLibC@cctz@time_internal@absl@@AEAA@AEBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z + ??0Utf8ForCodePoint@debugging_internal@absl@@QEAA@_K@Z ??0Win32Waiter@synchronization_internal@absl@@QEAA@XZ ??0int128@absl@@QEAA@M@Z ??0int128@absl@@QEAA@N@Z @@ -404,7 +406,6 @@ EXPORTS ?AddressIsReadable@debugging_internal@absl@@YA_NPEBX@Z ?AdvanceAndReadBytes@ChunkIterator@Cord@absl@@AEAA?AV23@_K@Z ?AdvanceBytesBtree@ChunkIterator@Cord@absl@@AEAAX_K@Z - ?AlignedBufferValue@FlagImpl@flags_internal@absl@@AEBAPEAXXZ ?AllocWithArena@LowLevelAlloc@base_internal@absl@@SAPEAX_KPEAUArena@123@@Z ?AlreadyExistsError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?AlwaysTrue@Condition@absl@@CA_NPEBV12@@Z @@ -426,6 +427,7 @@ EXPORTS ?AppendTree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTreeToInlined@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTreeToTree@InlineRep@Cord@absl@@QEAAXPEAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z + ?ApplyMask@MaskedPointer@flags_internal@absl@@AEAAX_K@Z ?ApplySubstitutions@strings_internal@absl@@YAHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@45@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@45@@Z ?AsciiStrToLower@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z ?AsciiStrToUpper@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z @@ -466,6 +468,7 @@ EXPORTS ?CheckDefaultValueParsingRoundtrip@FlagImpl@flags_internal@absl@@EEBAXXZ ?CheckDefaultValueParsingRoundtrip@PrivateHandleAccessor@flags_internal@absl@@SAXAEBVCommandLineFlag@3@@Z ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QEBA_NXZ + ?CheckMask@MaskedPointer@flags_internal@absl@@AEBA_N_K@Z ?CheckstrcasecmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcasecmptrueImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z ?CheckstrcmpfalseImpl@log_internal@absl@@YAPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PEBD00@Z @@ -520,6 +523,7 @@ EXPORTS ?DataLossError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?DeadlineExceededError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?DecodeFrom@ProtoField@log_internal@absl@@QEAA_NPEAV?$Span@$$CBD@3@@Z + ?DecodeRustPunycode@debugging_internal@absl@@YAPEADUDecodeRustPunycodeOptions@12@@Z ?DecodeWaitCycles@SpinLock@base_internal@absl@@KA_JI@Z ?DecrementCount@BlockingCounter@absl@@QEAA_NXZ ?DecrementSynchSem@Mutex@absl@@CA_NPEAV12@PEAUPerThreadSynch@base_internal@2@VKernelTimeout@synchronization_internal@2@@Z @@ -712,6 +716,7 @@ EXPORTS ?Generate@?$RandenPool@_K@random_internal@absl@@KA_KXZ ?Generate@RandenHwAes@random_internal@absl@@SAXPEBXPEAX@Z ?Generate@RandenSlow@random_internal@absl@@SAXPEBXPEAX@Z + ?Get@?$Flag@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@AEBA?AV?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@XZ ?GetAllFlags@absl@@YA?AV?$flat_hash_map@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@UStringHash@container_internal@5@UStringEq@75@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@23@@1@XZ ?GetAndroidNativeTag@log_internal@absl@@YAPEBDXZ ?GetAppendBuffer@CordRepBtree@cord_internal@absl@@QEAA?AV?$Span@D@3@_K@Z @@ -768,6 +773,7 @@ EXPORTS ?HandleInvalidStatusCtorArg@Helper@internal_statusor@absl@@SAXPEAVStatus@3@@Z ?HandleUsageFlags@flags_internal@absl@@YA?AW4HelpMode@12@AEAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@@Z ?HasBeenNotifiedInternal@Notification@absl@@CA_NPEBU?$atomic@_N@__Cr@std@@@Z + ?HasBeenRead@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?HasEdge@GraphCycles@synchronization_internal@absl@@QEBA_NUGraphId@23@0@Z ?HasNode@GraphCycles@synchronization_internal@absl@@QEAA_NUGraphId@23@@Z ?HasRandenHwAesImplementation@random_internal@absl@@YA_NXZ @@ -791,6 +797,7 @@ EXPORTS ?Initialize@ExponentialBiased@profiling_internal@absl@@AEAAXXZ ?InitializeCordRepExternal@cord_internal@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAUCordRepExternal@12@@Z ?InitializeData@Storage@?$FixedArray@D$0?0V?$allocator@D@__Cr@std@@@absl@@AEAAPEADXZ + ?InitializeEncodingAndFormat@LogMessageData@LogMessage@log_internal@absl@@QEAAXXZ ?InitializeLog@absl@@YAXXZ ?InitializeSymbolizer@absl@@YAXPEBD@Z ?InsertEdge@GraphCycles@synchronization_internal@absl@@QEAA_NUGraphId@23@0@Z @@ -827,6 +834,7 @@ EXPORTS ?IsUnavailable@absl@@YA_NAEBVStatus@1@@Z ?IsUnimplemented@absl@@YA_NAEBVStatus@1@@Z ?IsUnknown@absl@@YA_NAEBVStatus@1@@Z + ?IsUnprotectedReadCandidate@MaskedPointer@flags_internal@absl@@QEBA_NXZ ?IsValid@CordRepBtree@cord_internal@absl@@SA_NPEBV123@_N@Z ?KeyFunction@LogSink@absl@@EEBAXXZ ?LengthModToString@str_format_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@W4LengthMod@2@@Z @@ -864,6 +872,7 @@ EXPORTS ?MakeTime@TimeZoneInfo@cctz@time_internal@absl@@UEBA?AUcivil_lookup@time_zone@234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MakeTime@TimeZoneLibC@cctz@time_internal@absl@@UEBA?AUcivil_lookup@time_zone@234@AEBV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MapToLocalCode@status_internal@absl@@YA?AW4StatusCode@2@H@Z + ?MarkAsRead@MaskedPointer@flags_internal@absl@@QEAAXXZ ?MatchesConversions@ParsedFormatBase@str_format_internal@absl@@AEBA_N_NV?$initializer_list@W4FormatConversionCharSet@absl@@@std@@@Z ?MaxFlatLength@CordTestAccess@strings_internal@absl@@SA_KXZ ?MaxFramesInLogStackTrace@log_internal@absl@@YAHXZ @@ -910,6 +919,7 @@ EXPORTS ?Now@CycleClock@base_internal@absl@@SA_JXZ ?Now@absl@@YA?AVTime@1@XZ ?NumCPUs@base_internal@absl@@YAHXZ + ?NumLeakedFlagValues@flags_internal@absl@@YA_KXZ ?OnVLogVerbosityUpdate@log_internal@absl@@YAXV?$function@$$A6AXXZ@__Cr@std@@@Z ?OneTimeInitThreadIdentity@synchronization_internal@absl@@YAXPEAUThreadIdentity@base_internal@2@@Z ?OneWordValue@FlagImpl@flags_internal@absl@@AEBAAEAU?$atomic@_J@__Cr@std@@XZ @@ -967,6 +977,7 @@ EXPORTS ?ProgramInvocationName@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?ProgramUsageMessage@absl@@YA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?Ptr@GraphCycles@synchronization_internal@absl@@QEAAPEAXUGraphId@23@@Z + ?PtrStorage@FlagImpl@flags_internal@absl@@AEBAAEAU?$atomic@VMaskedPointer@flags_internal@absl@@@__Cr@std@@XZ ?PutPaddedString@FormatSinkImpl@str_format_internal@absl@@QEAA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@HH_N@Z ?PutTwoDigits@numbers_internal@absl@@YAXIPEAD@Z ?RawEnableLogPrefix@log_internal@absl@@YAX_N@Z @@ -1025,6 +1036,7 @@ EXPORTS ?ReportUsageError@flags_internal@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_N@Z ?ResetToBuiltinUTC@TimeZoneInfo@cctz@time_internal@absl@@AEAA_NAEBV?$duration@_JV?$ratio@$00$00@__Cr@std@@@chrono@__Cr@std@@@Z ?ResetToEmpty@InlineRep@Cord@absl@@AEAAXXZ + ?Resize@?$ResizeUninitializedTraits@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@X@strings_internal@absl@@SAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@_K@Z ?ResourceExhaustedError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?Restore@FlagState@flags_internal@absl@@EEBAXXZ ?RestoreState@FlagImpl@flags_internal@absl@@AEAA_NAEBVFlagState@23@@Z @@ -1038,6 +1050,7 @@ EXPORTS ?Scramble@CRC32@crc_internal@absl@@UEBAXPEAI@Z ?Seek@CordRepBtreeReader@cord_internal@absl@@QEAA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_K@Z ?SendToLog@LogMessage@log_internal@absl@@AEAAXXZ + ?Set@MaskedPointer@flags_internal@absl@@QEAAXP6APEAXW4FlagOp@23@PEBXPEAX2@Z1_N@Z ?SetAndroidNativeTag@absl@@YAXPEBD@Z ?SetCallback@FlagImpl@flags_internal@absl@@QEAAXQ6AXXZ@Z ?SetCordBtreeExhaustiveValidation@cord_internal@absl@@YAX_N@Z @@ -1115,7 +1128,7 @@ EXPORTS ?StatusMessageAsCStr@absl@@YAPEBDAEBVStatus@1@@Z ?StderrThreshold@absl@@YA?AW4LogSeverityAtLeast@1@XZ ?SteadyClockNow@KernelTimeout@synchronization_internal@absl@@CA_JXZ - ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBX@Z + ?StoreValue@FlagImpl@flags_internal@absl@@AEAAXPEBXW4ValueSource@23@@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@111@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@11@Z ?StrAppend@absl@@YAXPEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@AEBVAlphaNum@1@1@Z @@ -1135,6 +1148,7 @@ EXPORTS ?SupportsArmCRC32PMULL@crc_internal@absl@@YA_NXZ ?SuppressSigabortTrace@log_internal@absl@@YA_NXZ ?Symbolize@absl@@YA_NPEBXPEADH@Z + ?TestOnlyAddNodes@GraphCycles@synchronization_internal@absl@@QEAAXI@Z ?ThreadIsLoggingToLogSink@log_internal@absl@@YA_NXZ ?ThrowBadStatusOrAccess@internal_statusor@absl@@YAXVStatus@2@@Z ?ThrowBadVariantAccess@variant_internal@absl@@YAXXZ diff --git a/naiveproxy/src/third_party/abseil-cpp/symbols_x86_dbg.def b/naiveproxy/src/third_party/abseil-cpp/symbols_x86_dbg.def index 23f1d0cfd9..b6be8fb2af 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x86_dbg.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x86_dbg.def @@ -524,6 +524,7 @@ EXPORTS ??$AsciiStrCaseFold@$0A@@ascii_internal@absl@@YAXPADI@Z ??$AsciiStrCaseFoldLong@$00@ascii_internal@absl@@YAXPADI@Z ??$AsciiStrCaseFoldLong@$0A@@ascii_internal@absl@@YAXPADI@Z + ??$AssertHashEqConsistent@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@IAEXABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??$AssignElements@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$move_iterator@PAUPayload@status_internal@absl@@@23@@inlined_vector_internal@absl@@@inlined_vector_internal@absl@@YAXPAUPayload@status_internal@1@AAV?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$move_iterator@PAUPayload@status_internal@absl@@@23@@01@I@Z ??$Base64EscapeInternal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@strings_internal@absl@@YAXPBEIPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@_NPBD@Z ??$BufferSizeFor@$$V@log_internal@absl@@YAIW4WireType@01@@Z @@ -565,10 +566,12 @@ EXPORTS ??$DeallocateOld@$03V?$allocator@D@__Cr@std@@@HashSetResizeHelper@container_internal@absl@@QAEXV?$allocator@D@__Cr@std@@I@Z ??$DeallocateStandard@$03@container_internal@absl@@YAXAAVCommonFields@01@ABUPolicyFunctions@01@@Z ??$DecomposePair@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_N$$QAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$DecomposePair@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA_N$$QAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePair@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@Z ??$DecomposePair@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QAU?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@Z ??$DecomposePair@UFindElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YA?AVconst_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@$$QAUFindElement@301@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePair@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YAI$$QAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$DecomposePair@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@container_internal@absl@@YAI$$QAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$DecomposePairImpl@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@ABQAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA_N$$QAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@ABQAVCommandLineFlag@absl@@@23@@__Cr@std@@@Z ??$DecomposePairImpl@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@$$QAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@45@@Z ??$DecomposePairImpl@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@67@@memory_internal@container_internal@absl@@YA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@U?$pair@V?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@45@@Z @@ -789,8 +792,8 @@ EXPORTS ??$NewLeaf@$00@CordRepBtree@cord_internal@absl@@CAPAV012@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@I@Z ??$NewLeaf@$0A@@CordRepBtree@cord_internal@absl@@CAPAV012@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@I@Z ??$OffsetValue@U?$atomic@_K@__Cr@std@@@FlagImpl@flags_internal@absl@@ABEPAU?$atomic@_K@__Cr@std@@XZ + ??$OffsetValue@UFlagMaskedPointerValue@flags_internal@absl@@@FlagImpl@flags_internal@absl@@ABEPAUFlagMaskedPointerValue@12@XZ ??$OffsetValue@UFlagOneWordValue@flags_internal@absl@@@FlagImpl@flags_internal@absl@@ABEPAUFlagOneWordValue@12@XZ - ??$OffsetValue@X@FlagImpl@flags_internal@absl@@ABEPAXXZ ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@__Cr@std@@$$QAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@Z ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@$$QAPAVCommandLineFlag@absl@@@23@@__Cr@std@@$$QBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@$$QAPAVCommandLineFlag@1@@Z ??$PairArgs@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@YA?AU?$pair@V?$tuple@ABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@__Cr@std@@V?$tuple@ABQAVCommandLineFlag@absl@@@23@@__Cr@std@@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@Z @@ -908,6 +911,7 @@ EXPORTS ??$ToIntVal@_N@FormatArgImpl@str_format_internal@absl@@CAHAB_N@Z ??$TrailingZeros@G@container_internal@absl@@YAIG@Z ??$TrailingZeros@I@container_internal@absl@@YAII@Z + ??$TrailingZeros@_K@container_internal@absl@@YAI_K@Z ??$TransferRelocatable@$0M@@container_internal@absl@@YAXPAX00@Z ??$TypeErasedApplyToSlotFn@UStringHash@container_internal@absl@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@container_internal@absl@@YAIPBXPAX@Z ??$UnhidePtr@X@base_internal@absl@@YAPAXI@Z @@ -934,6 +938,7 @@ EXPORTS ??$__allocate_at_least@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@YA?AU?$__allocation_result@PAUViableSubstitution@strings_internal@absl@@@01@AAV?$allocator@UViableSubstitution@strings_internal@absl@@@01@I@Z ??$__allocate_at_least@V?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AU?$__allocation_result@PAV?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@01@AAV?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@01@I@Z ??$__allocator_destroy@V?$allocator@UUnrecognizedFlag@absl@@@__Cr@std@@PAUUnrecognizedFlag@absl@@PAU45@@__Cr@std@@YAXAAV?$allocator@UUnrecognizedFlag@absl@@@01@PAUUnrecognizedFlag@absl@@1@Z + ??$__annotate_double_ended_contiguous_container@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@YAXPBX00000@Z ??$__append_with_size@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AAEXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@12@I@Z ??$__assign_with_size_random_access@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@AAEXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@12@H@Z ??$__call@AAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@AAVCommandLineFlag@5@@?$__invoke_void_return_wrapper@X$00@__Cr@std@@SAXAAV@?0??SaveFromRegistry@FlagSaverImpl@flags_internal@absl@@QAEXXZ@AAVCommandLineFlag@7@@Z @@ -1053,11 +1058,13 @@ EXPORTS ??$__cxx_atomic_load@PAVCordzInfo@cord_internal@absl@@@__Cr@std@@YAPAVCordzInfo@cord_internal@absl@@PBU?$__cxx_atomic_base_impl@PAVCordzInfo@cord_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PAVTimeZone@absl@@@__Cr@std@@YAPAVTimeZone@absl@@PBU?$__cxx_atomic_base_impl@PAVTimeZone@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@PAVVLogSite@log_internal@absl@@@__Cr@std@@YAPAVVLogSite@log_internal@absl@@PBU?$__cxx_atomic_base_impl@PAVVLogSite@log_internal@absl@@@01@W4memory_order@01@@Z + ??$__cxx_atomic_load@VMaskedPointer@flags_internal@absl@@@__Cr@std@@YA?AVMaskedPointer@flags_internal@absl@@PBU?$__cxx_atomic_base_impl@VMaskedPointer@flags_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@W4OnDeadlockCycle@absl@@@__Cr@std@@YA?AW4OnDeadlockCycle@absl@@PBU?$__cxx_atomic_base_impl@W4OnDeadlockCycle@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_load@W4State@PerThreadSynch@base_internal@absl@@@__Cr@std@@YA?AW4State@PerThreadSynch@base_internal@absl@@PBU?$__cxx_atomic_base_impl@W4State@PerThreadSynch@base_internal@absl@@@01@W4memory_order@01@@Z ??$__cxx_atomic_store@PAVCordzHandle@cord_internal@absl@@@__Cr@std@@YAXPAU?$__cxx_atomic_base_impl@PAVCordzHandle@cord_internal@absl@@@01@PAVCordzHandle@cord_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@PAVCordzInfo@cord_internal@absl@@@__Cr@std@@YAXPAU?$__cxx_atomic_base_impl@PAVCordzInfo@cord_internal@absl@@@01@PAVCordzInfo@cord_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@PAVVLogSite@log_internal@absl@@@__Cr@std@@YAXPAU?$__cxx_atomic_base_impl@PAVVLogSite@log_internal@absl@@@01@PAVVLogSite@log_internal@absl@@W4memory_order@01@@Z + ??$__cxx_atomic_store@VMaskedPointer@flags_internal@absl@@@__Cr@std@@YAXPAU?$__cxx_atomic_base_impl@VMaskedPointer@flags_internal@absl@@@01@VMaskedPointer@flags_internal@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@W4OnDeadlockCycle@absl@@@__Cr@std@@YAXPAU?$__cxx_atomic_base_impl@W4OnDeadlockCycle@absl@@@01@W4OnDeadlockCycle@absl@@W4memory_order@01@@Z ??$__cxx_atomic_store@W4State@PerThreadSynch@base_internal@absl@@@__Cr@std@@YAXPAU?$__cxx_atomic_base_impl@W4State@PerThreadSynch@base_internal@absl@@@01@W4State@PerThreadSynch@base_internal@absl@@W4memory_order@01@@Z ??$__debug_randomize_range@U_ClassicAlgPolicy@__Cr@std@@PAPAVCommandLineFlag@absl@@PAPAV45@@__Cr@std@@YAXPAPAVCommandLineFlag@absl@@0@Z @@ -1106,9 +1113,9 @@ EXPORTS ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABUpiecewise_construct_t@23@V?$tuple@$$QAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@QAE?AU?$pair@V?$__tree_iterator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PAX@23@H@__Cr@std@@_N@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@ABUpiecewise_construct_t@12@$$QAV?$tuple@$$QAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QAV?$tuple@$$V@12@@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABUpiecewise_construct_t@23@V?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__hash_table@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@V?$__unordered_map_hasher@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$__unordered_map_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@23@U?$equal_to@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@U?$hash@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@@23@@__Cr@std@@QAE?AU?$pair@V?$__hash_iterator@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@_N@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@ABUpiecewise_construct_t@12@$$QAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QAV?$tuple@$$V@12@@Z ??$__emplace_unique_key_args@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABUpiecewise_construct_t@23@V?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$tuple@$$V@23@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@QAE?AU?$pair@V?$__tree_iterator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@PAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@PAX@23@H@__Cr@std@@_N@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@ABUpiecewise_construct_t@12@$$QAV?$tuple@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@12@$$QAV?$tuple@$$V@12@@Z + ??$__find@PAPAVLogSink@absl@@PAPAV12@PAV12@U__identity@__Cr@std@@@__Cr@std@@YAPAPAVLogSink@absl@@PAPAV23@0ABQAV23@AAU__identity@01@@Z ??$__find_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@AAEAAPAV?$__tree_node_base@PAX@12@AAPAV?$__tree_end_node@PAV?$__tree_node_base@PAX@__Cr@std@@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z ??$__find_equal@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@AAEAAPAV?$__tree_node_base@PAX@12@AAPAV?$__tree_end_node@PAV?$__tree_node_base@PAX@__Cr@std@@@12@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@12@@Z - ??$__find_impl@PAPAVLogSink@absl@@PAPAV12@PAV12@U__identity@__Cr@std@@@__Cr@std@@YAPAPAVLogSink@absl@@PAPAV23@0ABQAV23@AAU__identity@01@@Z ??$__for_each_segment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@?$__copy_impl@U_ClassicAlgPolicy@__Cr@std@@@23@@__Cr@std@@YAXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@01@0U?$_CopySegment@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PAU1234@AAU1234@PAPAU1234@H$0A@@23@@?$__copy_impl@U_ClassicAlgPolicy@__Cr@std@@@01@@Z ??$__insert_with_size@V?$__wrap_iter@PAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@ABV345@@Z@@__Cr@std@@V123@@?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@AAE?AV?$__wrap_iter@PAV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$__wrap_iter@PBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@12@V?$__wrap_iter@PAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@ABV345@@Z@@12@1H@Z ??$__invoke@AAUByCivilTime@Transition@cctz@time_internal@absl@@ABU2345@ABU2345@@__Cr@std@@YA_NAAUByCivilTime@Transition@cctz@time_internal@absl@@ABU3456@1@Z @@ -1245,6 +1252,8 @@ EXPORTS ??$advance@V?$__wrap_iter@PAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@ABV345@@Z@@__Cr@std@@HH$0A@@__Cr@std@@YAXAAV?$__wrap_iter@PAUraw_view@?1???R?$ConvertToContainer@V?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@23@$0A@@?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@QBE?AV?$vector@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$allocator@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@ABV345@@Z@@01@H@Z ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@SA_N$$QAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_N$$QAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@SA_N$$QAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@U?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA_N$$QAU?$EqualElement@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@45@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@45@@Z ??$apply@UEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@U?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@SA?AU?$pair@Viterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@_N@__Cr@std@@$$QAUEmplaceDecomposable@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QAU?$pair@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@45@@Z @@ -1253,6 +1262,8 @@ EXPORTS ??$apply@UFindElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SA?AVconst_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@$$QAUFindElement@412@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@SAI$$QAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SAI$$QAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@AAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@SAI$$QAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z + ??$apply@UHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@34@@?$hash_policy_traits@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@X@container_internal@absl@@SAI$$QAUHashElement@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@12@ABU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@Z ??$assign@V?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@__Cr@std@@$0A@@?$deque@UPrefixCrc@CrcCordState@crc_internal@absl@@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAEXV?$__deque_iterator@UPrefixCrc@CrcCordState@crc_internal@absl@@PBU1234@ABU1234@PBQBU1234@H$0A@@12@0@Z ??$begin@V?$vector@PAVCommandLineFlag@absl@@V?$allocator@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AV?$__wrap_iter@PAPAVCommandLineFlag@absl@@@01@AAV?$vector@PAVCommandLineFlag@absl@@V?$allocator@PAVCommandLineFlag@absl@@@__Cr@std@@@01@@Z ??$begin@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@YA?AV?$__wrap_iter@PAPBVCommandLineFlag@absl@@@01@AAV?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@01@@Z @@ -1535,6 +1546,7 @@ EXPORTS ??$max_size@V?$allocator@U?$AlignedType@$03@container_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$AlignedType@$03@container_internal@absl@@@__Cr@std@@@__Cr@std@@SAIABV?$allocator@U?$AlignedType@$03@container_internal@absl@@@12@@Z ??$max_size@V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAIABV?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@12@@Z ??$max_size@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAIABV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@12@@Z + ??$max_size@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@__Cr@std@@@__Cr@std@@SAIABV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@12@@Z ??$max_size@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@SAIABV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@12@@Z ??$max_size@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SAIABV?$allocator@UPayload@status_internal@absl@@@12@@Z ??$max_size@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@X$0A@@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SAIABV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@12@@Z @@ -1606,6 +1618,8 @@ EXPORTS ??0?$BigUnsigned@$0FE@@strings_internal@absl@@QAE@XZ ??0?$BigUnsigned@$0FE@@strings_internal@absl@@QAE@_K@Z ??0?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QAE@G@Z + ??0?$BitMask@_K$07$02$0A@@container_internal@absl@@QAE@_K@Z + ??0?$BoundedUtf8LengthSequence@$0BAA@@debugging_internal@absl@@QAE@XZ ??0?$FixedArray@D$0PPPPPPPP@V?$allocator@D@__Cr@std@@@absl@@QAE@IABV?$allocator@D@__Cr@std@@@Z ??0?$FlagRegistrar@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@$00@flags_internal@absl@@QAE@AAV?$Flag@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@12@PBD@Z ??0?$FormatSpecTemplate@$0BPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0JPPPL@$0IAAAE@$0JPPPL@$0EAAAE@$0IAAAE@@str_format_internal@absl@@QAE@PBD@Z @@ -1623,6 +1637,7 @@ EXPORTS ??0?$IteratorValueAdapter@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@V?$move_iterator@PAUPayload@status_internal@absl@@@23@@inlined_vector_internal@absl@@QAE@ABV?$move_iterator@PAUPayload@status_internal@absl@@@__Cr@std@@@Z ??0?$IteratorValueAdapter@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@PBVFormatArgImpl@str_format_internal@absl@@@inlined_vector_internal@absl@@QAE@ABQBVFormatArgImpl@str_format_internal@2@@Z ??0?$NonIterableBitMask@G$0BA@$0A@@container_internal@absl@@QAE@G@Z + ??0?$NonIterableBitMask@_K$07$02@container_internal@absl@@QAE@_K@Z ??0?$RandenPool@E@random_internal@absl@@QAE@XZ ??0?$RandenPool@G@random_internal@absl@@QAE@XZ ??0?$RandenPool@I@random_internal@absl@@QAE@XZ @@ -1753,6 +1768,7 @@ EXPORTS ??0?$__non_trivial_if@$00V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QAE@XZ ??0?$__non_trivial_if@$00V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@QAE@XZ ??0?$__non_trivial_if@$00V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@__Cr@std@@QAE@XZ + ??0?$__non_trivial_if@$00V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@__Cr@std@@@__Cr@std@@QAE@XZ ??0?$__non_trivial_if@$00V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@XZ ??0?$__non_trivial_if@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@XZ ??0?$__non_trivial_if@$00V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@QAE@XZ @@ -1828,6 +1844,7 @@ EXPORTS ??0?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@QAE@XZ ??0?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@QAE@XZ ??0?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@QAE@XZ + ??0?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@__Cr@std@@QAE@XZ ??0?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QAE@XZ ??0?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QAE@XZ ??0?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QAE@XZ @@ -1987,6 +2004,7 @@ EXPORTS ??0FormatConversionSpecImpl@str_format_internal@absl@@QAE@XZ ??0FormatSinkImpl@str_format_internal@absl@@QAE@VFormatRawSinkImpl@12@@Z ??0GraphCycles@synchronization_internal@absl@@QAE@XZ + ??0GroupPortableImpl@container_internal@absl@@QAE@PBW4ctrl_t@12@@Z ??0GroupSse2Impl@container_internal@absl@@QAE@PBW4ctrl_t@12@@Z ??0HashSetIteratorGenerationInfoDisabled@container_internal@absl@@QAE@PBE@Z ??0HashSetResizeHelper@container_internal@absl@@QAE@AAVCommonFields@12@_N1VHashtablezInfoHandle@12@@Z @@ -2024,6 +2042,7 @@ EXPORTS ??0LogMessageQuietlyFatal@log_internal@absl@@QAE@PBDHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0LogSink@absl@@IAE@XZ ??0Long@Rep@CordBuffer@absl@@QAE@PAUCordRepFlat@cord_internal@3@@Z + ??0MaskedPointer@flags_internal@absl@@QAE@PAX_N@Z ??0MixingHashState@hash_internal@absl@@AAE@XZ ??0MixingHashState@hash_internal@absl@@AAE@_K@Z ??0Mutex@absl@@QAE@XZ @@ -2088,6 +2107,7 @@ EXPORTS ??0UnrecognizedFlag@absl@@QAE@W4Source@01@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0UntypedFormatSpec@absl@@QAE@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0UntypedFormatSpecImpl@str_format_internal@absl@@QAE@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z + ??0Utf8ForCodePoint@debugging_internal@absl@@QAE@_K@Z ??0ViableSubstitution@strings_internal@absl@@QAE@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@0I@Z ??0Win32Waiter@synchronization_internal@absl@@QAE@XZ ??0WriterMutexLock@absl@@QAE@PAVMutex@1@@Z @@ -2398,6 +2418,7 @@ EXPORTS ??9absl@@YA_NVint128@0@0@Z ??9absl@@YA_NVuint128@0@0@Z ??9container_internal@absl@@YA_NABV?$BitMask@G$0BA@$0A@$0A@@01@0@Z + ??9container_internal@absl@@YA_NABV?$BitMask@_K$07$02$0A@@01@0@Z ??9container_internal@absl@@YA_NABViterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@01@0@Z ??9strings_internal@absl@@YA_NABV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@01@0@Z ??9strings_internal@absl@@YA_NABV?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@01@0@Z @@ -2468,6 +2489,7 @@ EXPORTS ??CChunkIterator@Cord@absl@@QBEPBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ??Citerator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@QBEPAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@XZ ??D?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QBEIXZ + ??D?$BitMask@_K$07$02$0A@@container_internal@absl@@QBEIXZ ??D?$NoDestructor@V?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@@absl@@QAEAAV?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@1@XZ ??D?$NoDestructor@VFlagRegistry@flags_internal@absl@@@absl@@QAEAAVFlagRegistry@flags_internal@1@XZ ??D?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QBEABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ @@ -2507,6 +2529,7 @@ EXPORTS ??Dabsl@@YA?AVuint128@0@V10@0@Z ??Diterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@QBEAAU?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@XZ ??E?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QAEAAV012@XZ + ??E?$BitMask@_K$07$02$0A@@container_internal@absl@@QAEAAV012@XZ ??E?$SplitIterator@V?$Splitter@VByAnyChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QAEAAV012@XZ ??E?$SplitIterator@V?$Splitter@VByAnyChar@absl@@USkipEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QAEAAV012@XZ ??E?$SplitIterator@V?$Splitter@VByChar@absl@@UAllowEmpty@2@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@strings_internal@absl@@@strings_internal@absl@@QAEAAV012@XZ @@ -2583,6 +2606,7 @@ EXPORTS ??Pabsl@@YA_NVDuration@0@0@Z ??Pabsl@@YA_NVint128@0@0@Z ??Pabsl@@YA_NVuint128@0@0@Z + ??R@?0???$AssertHashEqConsistent@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@IAEXABV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z@QBE?A?@@PBW4ctrl_t@23@PAT?$map_slot_type@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@23@@Z ??R@?0???$Initialize@V?$IteratorValueAdapter@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@PBVFormatArgImpl@str_format_internal@absl@@@inlined_vector_internal@absl@@@?$Storage@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEXV?$IteratorValueAdapter@V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@PBVFormatArgImpl@str_format_internal@absl@@@23@I@Z@QBE?A?@@XZ ??R@?0???A?$FixedArray@D$0PPPPPPPP@V?$allocator@D@__Cr@std@@@absl@@QAEAADI@Z@QBE?A?@@XZ ??R@?0???A?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QAEAAUPayload@status_internal@2@I@Z@QBE?A?@@XZ @@ -2777,7 +2801,6 @@ EXPORTS ?AdvanceBytesBtree@ChunkIterator@Cord@absl@@AAEXI@Z ?AlignBegin@CordRepBtree@cord_internal@absl@@AAEXXZ ?AlignEnd@CordRepBtree@cord_internal@absl@@AAEXXZ - ?AlignedBufferValue@FlagImpl@flags_internal@absl@@ABEPAXXZ ?Alloc@flags_internal@absl@@YAPAXP6APAXW4FlagOp@12@PBXPAX2@Z@Z ?AllocWithArena@LowLevelAlloc@base_internal@absl@@SAPAXIPAUArena@123@@Z ?Allocate@?$AllocationTransaction@V?$allocator@PAUCordRep@cord_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEPAPAUCordRep@cord_internal@3@I@Z @@ -2790,6 +2813,7 @@ EXPORTS ?AllocatedSize@CordRepFlat@cord_internal@absl@@QBEIXZ ?AllocatedSizeToTag@cord_internal@absl@@YAEI@Z ?AllocatedSizeToTagUnchecked@cord_internal@absl@@YAEI@Z + ?AllowsUnprotectedRead@MaskedPointer@flags_internal@absl@@QBE_NXZ ?AlreadyExistsError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?AlwaysTrue@Condition@absl@@CA_NPBV12@@Z ?AnnotateConstruct@NonEmptyInlinedStorage@?$FixedArray@D$0PPPPPPPP@V?$allocator@D@__Cr@std@@@absl@@QAEXI@Z @@ -2819,6 +2843,7 @@ EXPORTS ?AppendTreeToTree@InlineRep@Cord@absl@@QAEXPAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTruncated@log_internal@absl@@YAIDIAAV?$Span@D@2@@Z ?AppendTruncated@log_internal@absl@@YAIV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@AAV?$Span@D@2@@Z + ?ApplyMask@MaskedPointer@flags_internal@absl@@AAEXI@Z ?ApplySubstitutions@strings_internal@absl@@YAHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAV?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@45@PAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@45@@Z ?AreItersFromSameContainer@container_internal@absl@@YA_NPBW4ctrl_t@12@0ABQBX1@Z ?AsValueType@?$FixedArray@D$0PPPPPPPP@V?$allocator@D@__Cr@std@@@absl@@CAPADPAD@Z @@ -2876,6 +2901,7 @@ EXPORTS ?CheckDefaultValueParsingRoundtrip@PrivateHandleAccessor@flags_internal@absl@@SAXABVCommandLineFlag@3@@Z ?CheckFastPathSetting@str_format_internal@absl@@YA_NABUUnboundConversion@12@@Z ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QBE_NXZ + ?CheckMask@MaskedPointer@flags_internal@absl@@ABE_NI@Z ?CheckstrcasecmpfalseImpl@log_internal@absl@@YAPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBD00@Z ?CheckstrcasecmptrueImpl@log_internal@absl@@YAPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBD00@Z ?CheckstrcmpfalseImpl@log_internal@absl@@YAPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBD00@Z @@ -2977,6 +3003,7 @@ EXPORTS ?DeallocateIfAllocated@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEXXZ ?DeallocateIfAllocated@?$Storage@VFormatArgImpl@str_format_internal@absl@@$03V?$allocator@VFormatArgImpl@str_format_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEXXZ ?DecodeFrom@ProtoField@log_internal@absl@@QAE_NPAV?$Span@$$CBD@3@@Z + ?DecodeRustPunycode@debugging_internal@absl@@YAPADUDecodeRustPunycodeOptions@12@@Z ?DecodeWaitCycles@SpinLock@base_internal@absl@@KA_JI@Z ?Decrement@RefcountAndFlags@cord_internal@absl@@QAE_NXZ ?DecrementCount@BlockingCounter@absl@@QAE_NXZ @@ -3078,6 +3105,9 @@ EXPORTS ?EncodeStringTruncate@log_internal@absl@@YA_N_KV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAV?$Span@D@2@@Z ?EncodeUTF8Char@strings_internal@absl@@YAIPAD_U@Z ?EncodeVarint@log_internal@absl@@YA_N_K0PAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_KHPAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_KIPAV?$Span@D@2@@Z + ?EncodeVarint@log_internal@absl@@YA_N_K_JPAV?$Span@D@2@@Z ?EncodeWaitCycles@SpinLock@base_internal@absl@@KAI_J0@Z ?EndsWith@Cord@absl@@QBE_NABV12@@Z ?EndsWith@Cord@absl@@QBE_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z @@ -3384,6 +3414,7 @@ EXPORTS ?HandleInvalidStatusCtorArg@Helper@internal_statusor@absl@@SAXPAVStatus@3@@Z ?HandleUsageFlags@flags_internal@absl@@YA?AW4HelpMode@12@AAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@@Z ?HasBeenNotifiedInternal@Notification@absl@@CA_NPBU?$atomic@_N@__Cr@std@@@Z + ?HasBeenRead@MaskedPointer@flags_internal@absl@@QBE_NXZ ?HasEdge@GraphCycles@synchronization_internal@absl@@QBE_NUGraphId@23@0@Z ?HasInfozMask@CommonFields@container_internal@absl@@CAIXZ ?HasInfozShift@CommonFields@container_internal@absl@@CAIXZ @@ -3427,9 +3458,11 @@ EXPORTS ?Initialize@ExponentialBiased@profiling_internal@absl@@AAEXXZ ?InitializeCordRepExternal@cord_internal@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAUCordRepExternal@12@@Z ?InitializeData@Storage@?$FixedArray@D$0PPPPPPPP@V?$allocator@D@__Cr@std@@@absl@@AAEPADXZ + ?InitializeEncodingAndFormat@LogMessageData@LogMessage@log_internal@absl@@QAEXXZ ?InitializeLog@absl@@YAXXZ ?InitializeSymbolizer@absl@@YAXPBD@Z ?InlinedRepToCode@Status@absl@@CA?AW4StatusCode@2@I@Z + ?InsertAndReturnSumOfPredecessors@?$BoundedUtf8LengthSequence@$0BAA@@debugging_internal@absl@@QAEIII@Z ?InsertEdge@GraphCycles@synchronization_internal@absl@@QAE_NUGraphId@23@0@Z ?InstallFailureSignalHandler@absl@@YAXABUFailureSignalHandlerOptions@1@@Z ?Int128High64@absl@@YA_JVint128@1@@Z @@ -3492,6 +3525,7 @@ EXPORTS ?IsUnavailable@absl@@YA_NABVStatus@1@@Z ?IsUnimplemented@absl@@YA_NABVStatus@1@@Z ?IsUnknown@absl@@YA_NABVStatus@1@@Z + ?IsUnprotectedReadCandidate@MaskedPointer@flags_internal@absl@@QBE_NXZ ?IsValid@CordRepBtree@cord_internal@absl@@SA_NPBV123@_N@Z ?IsValidCapacity@container_internal@absl@@YA_NI@Z ?KeyFunction@LogSink@absl@@EBEXXZ @@ -3535,6 +3569,7 @@ EXPORTS ?LowLevelHashImpl@MixingHashState@hash_internal@absl@@CA_KPBEI@Z ?LowLevelHashLenGt16@hash_internal@absl@@YA_KPBXI_KQB_K@Z ?LowestBitSet@?$NonIterableBitMask@G$0BA@$0A@@container_internal@absl@@QBEIXZ + ?LowestBitSet@?$NonIterableBitMask@_K$07$02@container_internal@absl@@QBEIXZ ?Make@TimeZoneIf@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneIf@cctz@time_internal@absl@@U?$default_delete@VTimeZoneIf@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@67@@Z ?Make@TimeZoneInfo@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneInfo@cctz@time_internal@absl@@U?$default_delete@VTimeZoneInfo@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@67@@Z ?Make@TimeZoneLibC@cctz@time_internal@absl@@SA?AV?$unique_ptr@VTimeZoneLibC@cctz@time_internal@absl@@U?$default_delete@VTimeZoneLibC@cctz@time_internal@absl@@@__Cr@std@@@__Cr@std@@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@67@@Z @@ -3561,9 +3596,12 @@ EXPORTS ?MakeTime@TimeZoneLibC@cctz@time_internal@absl@@UBE?AUcivil_lookup@time_zone@234@ABV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MakeUint128@absl@@YA?AVuint128@1@_K0@Z ?MapToLocalCode@status_internal@absl@@YA?AW4StatusCode@2@H@Z + ?MarkAsRead@MaskedPointer@flags_internal@absl@@QAEXXZ ?MarkInitialized@SequenceLock@flags_internal@absl@@QAEXXZ ?MaskEmpty@GroupSse2Impl@container_internal@absl@@QBE?AV?$NonIterableBitMask@G$0BA@$0A@@23@XZ ?MaskEmptyOrDeleted@GroupSse2Impl@container_internal@absl@@QBE?AV?$NonIterableBitMask@G$0BA@$0A@@23@XZ + ?MaskFull@GroupPortableImpl@container_internal@absl@@QBE?AV?$BitMask@_K$07$02$0A@@23@XZ + ?MaskFull@GroupSse2Impl@container_internal@absl@@QBE?AV?$BitMask@G$0BA@$0A@$0A@@23@XZ ?Match@GroupSse2Impl@container_internal@absl@@QBE?AV?$BitMask@G$0BA@$0A@$0A@@23@E@Z ?MatchesConversions@ParsedFormatBase@str_format_internal@absl@@ABE_N_NV?$initializer_list@W4FormatConversionCharSet@absl@@@std@@@Z ?MaxFlatLength@CordTestAccess@strings_internal@absl@@SAIXZ @@ -3640,6 +3678,7 @@ EXPORTS ?NumClonedBytes@container_internal@absl@@YAIXZ ?NumControlBytes@container_internal@absl@@YAII@Z ?NumGenerationBytes@container_internal@absl@@YAIXZ + ?NumLeakedFlagValues@flags_internal@absl@@YA_KXZ ?ODRCheck@CordzInfo@cord_internal@absl@@ABEXXZ ?OccursBefore@ViableSubstitution@strings_internal@absl@@QBE_NABU123@@Z ?OnUpdate@?$FlagRegistrar@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@$00@flags_internal@absl@@QHAE?AV123@P6AXXZ@Z @@ -3717,6 +3756,8 @@ EXPORTS ?ProgramInvocationName@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?ProgramUsageMessage@absl@@YA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?Ptr@GraphCycles@synchronization_internal@absl@@QAEPAXUGraphId@23@@Z + ?Ptr@MaskedPointer@flags_internal@absl@@QBEPAXXZ + ?PtrStorage@FlagImpl@flags_internal@absl@@ABEAAU?$atomic@VMaskedPointer@flags_internal@absl@@@__Cr@std@@XZ ?PushDead@?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@AAEXPAUHashtablezInfo@container_internal@3@@Z ?PushNew@?$SampleRecorder@UHashtablezInfo@container_internal@absl@@@profiling_internal@absl@@AAEXPAUHashtablezInfo@container_internal@3@@Z ?PutPaddedString@FormatSinkImpl@str_format_internal@absl@@QAE_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@HH_N@Z @@ -3831,6 +3872,7 @@ EXPORTS ?SendToLog@LogMessage@log_internal@absl@@AAEXXZ ?SentinelEmptyGeneration@container_internal@absl@@YAEXZ ?Set@?$Flag@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@AAEXABV?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@Z + ?Set@MaskedPointer@flags_internal@absl@@QAEXP6APAXW4FlagOp@23@PBXPAX2@Z1_N@Z ?SetAllocation@?$Storage@PAUCordRep@cord_internal@absl@@$01V?$allocator@PAUCordRep@cord_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEXU?$Allocation@V?$allocator@PAUCordRep@cord_internal@absl@@@__Cr@std@@@23@@Z ?SetAllocation@?$Storage@PAVLogSink@absl@@$0BA@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEXU?$Allocation@V?$allocator@PAVLogSink@absl@@@__Cr@std@@@23@@Z ?SetAllocation@?$Storage@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@inlined_vector_internal@absl@@QAEXU?$Allocation@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@23@@Z @@ -3975,7 +4017,7 @@ EXPORTS ?Store@?$AtomicHook@P6AXXZ@base_internal@absl@@QAEXP6AXXZ@Z ?Store@?$AtomicHook@P6AX_J@Z@base_internal@absl@@QAEXP6AX_J@Z@Z ?Store@?$AtomicHook@P6A_NW4LogSeverity@absl@@PBDHPAPADPAH@Z@base_internal@absl@@QAEXP6A_NW4LogSeverity@3@PBDHPAPADPAH@Z@Z - ?StoreValue@FlagImpl@flags_internal@absl@@AAEXPBX@Z + ?StoreValue@FlagImpl@flags_internal@absl@@AAEXPBXW4ValueSource@23@@Z ?StrAppend@absl@@YAXPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABVAlphaNum@1@111@Z ?StrAppend@absl@@YAXPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABVAlphaNum@1@11@Z ?StrAppend@absl@@YAXPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABVAlphaNum@1@1@Z @@ -4008,6 +4050,7 @@ EXPORTS ?TagToLength@cord_internal@absl@@YAIE@Z ?TakeRep@Cord@absl@@AGBEPAUCordRep@cord_internal@2@XZ ?TakeRep@Cord@absl@@AHAEPAUCordRep@cord_internal@2@XZ + ?TestOnlyAddNodes@GraphCycles@synchronization_internal@absl@@QAEXI@Z ?ThreadIsLoggingToLogSink@log_internal@absl@@YA_NXZ ?ThrowBadStatusOrAccess@internal_statusor@absl@@YAXVStatus@2@@Z ?ThrowBadVariantAccess@variant_internal@absl@@YAXXZ @@ -4751,6 +4794,7 @@ EXPORTS ?allocate@?$allocator@U?$AlignedType@$03@container_internal@absl@@@__Cr@std@@QAEPAU?$AlignedType@$03@container_internal@absl@@I@Z ?allocate@?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@QAEPAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@23@I@Z ?allocate@?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@QAEPAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@23@I@Z + ?allocate@?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@__Cr@std@@QAEPAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@56@PBXPAX2@Z@I@Z ?allocate@?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QAEPAUConversionItem@ParsedFormatBase@str_format_internal@absl@@I@Z ?allocate@?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QAEPAUPayload@status_internal@absl@@I@Z ?allocate@?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QAEPAUPrefixCrc@CrcCordState@crc_internal@absl@@I@Z @@ -4770,6 +4814,7 @@ EXPORTS ?allocate@?$allocator_traits@V?$allocator@U?$AlignedType@$03@container_internal@absl@@@__Cr@std@@@__Cr@std@@SAPAU?$AlignedType@$03@container_internal@absl@@AAV?$allocator@U?$AlignedType@$03@container_internal@absl@@@23@I@Z ?allocate@?$allocator_traits@V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@23@AAV?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@23@I@Z ?allocate@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@23@AAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@23@I@Z + ?allocate@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@__Cr@std@@@__Cr@std@@SAPAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@56@PBXPAX2@Z@AAV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@23@I@Z ?allocate@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SAPAUPayload@status_internal@absl@@AAV?$allocator@UPayload@status_internal@absl@@@23@I@Z ?allocate@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SAPAUPrefixCrc@CrcCordState@crc_internal@absl@@AAV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@23@I@Z ?allocate@?$allocator_traits@V?$allocator@V?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAPAV?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PAX@23@AAV?$allocator@V?$__tree_node@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@PAX@__Cr@std@@@23@I@Z @@ -4821,6 +4866,7 @@ EXPORTS ?base@?$move_iterator@PAUTransition@cctz@time_internal@absl@@@__Cr@std@@QGBEABQAUTransition@cctz@time_internal@absl@@XZ ?base@?$move_iterator@PAUTransitionType@cctz@time_internal@absl@@@__Cr@std@@QGBEABQAUTransitionType@cctz@time_internal@absl@@XZ ?begin@?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QBE?AV123@XZ + ?begin@?$BitMask@_K$07$02$0A@@container_internal@absl@@QBE?AV123@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QAEPAUPayload@status_internal@2@XZ ?begin@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QBEPBUPayload@status_internal@2@XZ ?begin@?$Span@$$CBI@absl@@QBEPBIXZ @@ -4999,6 +5045,7 @@ EXPORTS ?deallocate@?$allocator@U?$AlignedType@$03@container_internal@absl@@@__Cr@std@@QAEXPAU?$AlignedType@$03@container_internal@absl@@I@Z ?deallocate@?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@QAEXPAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@23@I@Z ?deallocate@?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@QAEXPAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@23@I@Z + ?deallocate@?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@__Cr@std@@QAEXPAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@56@PBXPAX2@Z@I@Z ?deallocate@?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@QAEXPAUConversionItem@ParsedFormatBase@str_format_internal@absl@@I@Z ?deallocate@?$allocator@UPayload@status_internal@absl@@@__Cr@std@@QAEXPAUPayload@status_internal@absl@@I@Z ?deallocate@?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@QAEXPAUPrefixCrc@CrcCordState@crc_internal@absl@@I@Z @@ -5024,6 +5071,7 @@ EXPORTS ?deallocate@?$allocator_traits@V?$allocator@U?$AlignedType@$03@container_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAAV?$allocator@U?$AlignedType@$03@container_internal@absl@@@23@PAU?$AlignedType@$03@container_internal@absl@@I@Z ?deallocate@?$allocator_traits@V?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAXAAV?$allocator@U?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@__Cr@std@@@23@PAU?$__hash_node@PBUCordRep@cord_internal@absl@@PAX@23@I@Z ?deallocate@?$allocator_traits@V?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@__Cr@std@@@__Cr@std@@SAXAAV?$allocator@U?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@__Cr@std@@@23@PAU?$__hash_node@U?$__hash_value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBVImpl@time_zone@cctz@time_internal@absl@@@__Cr@std@@PAX@23@I@Z + ?deallocate@?$allocator_traits@V?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@__Cr@std@@@__Cr@std@@SAXAAV?$allocator@UAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@23@PBXPAX2@Z@@23@PAUAlignedSpace@?1???$FlagOps@V?$vector@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@@__Cr@std@@@flags_internal@absl@@YAPAXW4FlagOp@67@PBXPAX3@Z@I@Z ?deallocate@?$allocator_traits@V?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAAV?$allocator@UConversionItem@ParsedFormatBase@str_format_internal@absl@@@23@PAUConversionItem@ParsedFormatBase@str_format_internal@absl@@I@Z ?deallocate@?$allocator_traits@V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAAV?$allocator@UPayload@status_internal@absl@@@23@PAUPayload@status_internal@absl@@I@Z ?deallocate@?$allocator_traits@V?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@__Cr@std@@@__Cr@std@@SAXAAV?$allocator@UPrefixCrc@CrcCordState@crc_internal@absl@@@23@PAUPrefixCrc@CrcCordState@crc_internal@absl@@I@Z @@ -5069,7 +5117,9 @@ EXPORTS ?empty@?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@__Cr@std@@QBE_NXZ ?empty@?$vector@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@V?$allocator@V?$unique_ptr@VFlagStateInterface@flags_internal@absl@@U?$default_delete@VFlagStateInterface@flags_internal@absl@@@__Cr@std@@@__Cr@std@@@23@@__Cr@std@@QBE_NXZ ?empty@Cord@absl@@QBE_NXZ + ?encoded_remaining@LogMessageData@LogMessage@log_internal@absl@@QAEAAV?$Span@D@4@XZ ?end@?$BitMask@G$0BA@$0A@$0A@@container_internal@absl@@QBE?AV123@XZ + ?end@?$BitMask@_K$07$02$0A@@container_internal@absl@@QBE?AV123@XZ ?end@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QAEPAUPayload@status_internal@2@XZ ?end@?$InlinedVector@UPayload@status_internal@absl@@$00V?$allocator@UPayload@status_internal@absl@@@__Cr@std@@@absl@@QBEPBUPayload@status_internal@2@XZ ?end@?$Span@$$CBI@absl@@QBEPBIXZ @@ -5369,6 +5419,7 @@ EXPORTS ?load@?$__atomic_base@PAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QBEPAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PAVTimeZone@absl@@$0A@@__Cr@std@@QBEPAVTimeZone@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@PAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QBEPAVVLogSite@log_internal@absl@@W4memory_order@23@@Z + ?load@?$__atomic_base@VMaskedPointer@flags_internal@absl@@$0A@@__Cr@std@@QBE?AVMaskedPointer@flags_internal@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@W4OnDeadlockCycle@absl@@$0A@@__Cr@std@@QBE?AW4OnDeadlockCycle@absl@@W4memory_order@23@@Z ?load@?$__atomic_base@W4State@PerThreadSynch@base_internal@absl@@$0A@@__Cr@std@@QBE?AW4State@PerThreadSynch@base_internal@absl@@W4memory_order@23@@Z ?load_time_zone@cctz@time_internal@absl@@YA_NABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PAVtime_zone@123@@Z @@ -5432,6 +5483,7 @@ EXPORTS ?offset@?$probe_seq@$0BA@@container_internal@absl@@QBEII@Z ?offset@?$probe_seq@$0BA@@container_internal@absl@@QBEIXZ ?ok@Status@absl@@QBE_NXZ + ?ok@Utf8ForCodePoint@debugging_internal@absl@@QBE_NXZ ?old_capacity@HashSetResizeHelper@container_internal@absl@@QBEIXZ ?old_ctrl@HashSetResizeHelper@container_internal@absl@@QBEPAW4ctrl_t@23@XZ ?old_heap_or_soo@HashSetResizeHelper@container_internal@absl@@QAEAATHeapOrSoo@23@XZ @@ -5727,6 +5779,7 @@ EXPORTS ?soo_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAE?AViterator@123@XZ ?soo_slot@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAEPAT?$map_slot_type@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@23@XZ ?source_basename@LogEntry@absl@@QBE?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ + ?source_filename@LogEntry@absl@@QBE?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?source_line@LogEntry@absl@@QBEHXZ ?stacktrace@LogEntry@absl@@QBE?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?status@BadStatusOrAccess@absl@@QBEABVStatus@2@XZ @@ -5735,6 +5788,7 @@ EXPORTS ?store@?$__atomic_base@PAVCordzHandle@cord_internal@absl@@$0A@@__Cr@std@@QAEXPAVCordzHandle@cord_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@PAVCordzInfo@cord_internal@absl@@$0A@@__Cr@std@@QAEXPAVCordzInfo@cord_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@PAVVLogSite@log_internal@absl@@$0A@@__Cr@std@@QAEXPAVVLogSite@log_internal@absl@@W4memory_order@23@@Z + ?store@?$__atomic_base@VMaskedPointer@flags_internal@absl@@$0A@@__Cr@std@@QAEXVMaskedPointer@flags_internal@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@W4OnDeadlockCycle@absl@@$0A@@__Cr@std@@QAEXW4OnDeadlockCycle@absl@@W4memory_order@23@@Z ?store@?$__atomic_base@W4State@PerThreadSynch@base_internal@absl@@$0A@@__Cr@std@@QAEXW4State@PerThreadSynch@base_internal@absl@@W4memory_order@23@@Z ?str@UntypedFormatSpecImpl@str_format_internal@absl@@QBE?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ @@ -5774,6 +5828,7 @@ EXPORTS ?value@InputValue@UnboundConversion@str_format_internal@absl@@QBEHXZ ?value_comp@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@__Cr@std@@@23@@__Cr@std@@QAEAAV?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$map@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@XZ ?value_comp@?$__tree@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@V?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@V?$allocator@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@__Cr@std@@@23@@__Cr@std@@QAEAAV?$__map_value_compare@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@U?$__value_type@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$vector@PBVCommandLineFlag@absl@@V?$allocator@PBVCommandLineFlag@absl@@@__Cr@std@@@23@@23@U?$less@V?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@23@$00@23@XZ + ?verbosity@LogEntry@absl@@QBEHXZ ?version@time_zone@cctz@time_internal@absl@@QBE?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?what@BadStatusOrAccess@absl@@UBEPBDXZ ?what@SeedGenException@absl@@UBEPBDXZ diff --git a/naiveproxy/src/third_party/abseil-cpp/symbols_x86_rel.def b/naiveproxy/src/third_party/abseil-cpp/symbols_x86_rel.def index 0fac832d29..7ce60b3728 100644 --- a/naiveproxy/src/third_party/abseil-cpp/symbols_x86_rel.def +++ b/naiveproxy/src/third_party/abseil-cpp/symbols_x86_rel.def @@ -226,6 +226,7 @@ EXPORTS ??0LogMessageQuietlyDebugFatal@log_internal@absl@@QAE@PBDH@Z ??0LogMessageQuietlyFatal@log_internal@absl@@QAE@PBDH@Z ??0LogMessageQuietlyFatal@log_internal@absl@@QAE@PBDHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z + ??0MaskedPointer@flags_internal@absl@@QAE@PAX_N@Z ??0OstreamView@LogMessage@log_internal@absl@@QAE@AAULogMessageData@123@@Z ??0ParsedFormatBase@str_format_internal@absl@@QAE@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@_NV?$initializer_list@W4FormatConversionCharSet@absl@@@5@@Z ??0Randen@random_internal@absl@@QAE@XZ @@ -236,6 +237,7 @@ EXPORTS ??0StdcppWaiter@synchronization_internal@absl@@QAE@XZ ??0StringifySink@detect_specialization@log_internal@absl@@QAE@AAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ??0TimeZoneLibC@cctz@time_internal@absl@@AAE@ABV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z + ??0Utf8ForCodePoint@debugging_internal@absl@@QAE@_K@Z ??0Win32Waiter@synchronization_internal@absl@@QAE@XZ ??0int128@absl@@QAE@M@Z ??0int128@absl@@QAE@N@Z @@ -376,7 +378,6 @@ EXPORTS ?AddressIsReadable@debugging_internal@absl@@YA_NPBX@Z ?AdvanceAndReadBytes@ChunkIterator@Cord@absl@@AAE?AV23@I@Z ?AdvanceBytesBtree@ChunkIterator@Cord@absl@@AAEXI@Z - ?AlignedBufferValue@FlagImpl@flags_internal@absl@@ABEPAXXZ ?AllocWithArena@LowLevelAlloc@base_internal@absl@@SAPAXIPAUArena@123@@Z ?AlreadyExistsError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?AlwaysTrue@Condition@absl@@CA_NPBV12@@Z @@ -396,6 +397,7 @@ EXPORTS ?AppendTree@InlineRep@Cord@absl@@QAEXPAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTreeToInlined@InlineRep@Cord@absl@@QAEXPAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z ?AppendTreeToTree@InlineRep@Cord@absl@@QAEXPAUCordRep@cord_internal@3@W4MethodIdentifier@CordzUpdateTracker@53@@Z + ?ApplyMask@MaskedPointer@flags_internal@absl@@AAEXI@Z ?ApplySubstitutions@strings_internal@absl@@YAHV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAV?$vector@UViableSubstitution@strings_internal@absl@@V?$allocator@UViableSubstitution@strings_internal@absl@@@__Cr@std@@@45@PAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@45@@Z ?AsciiStrToLower@absl@@YAXPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z ?AsciiStrToUpper@absl@@YAXPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@@Z @@ -434,6 +436,7 @@ EXPORTS ?CheckDefaultValueParsingRoundtrip@FlagImpl@flags_internal@absl@@EBEXXZ ?CheckDefaultValueParsingRoundtrip@PrivateHandleAccessor@flags_internal@absl@@SAXABVCommandLineFlag@3@@Z ?CheckInvariants@GraphCycles@synchronization_internal@absl@@QBE_NXZ + ?CheckMask@MaskedPointer@flags_internal@absl@@ABE_NI@Z ?CheckstrcasecmpfalseImpl@log_internal@absl@@YAPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBD00@Z ?CheckstrcasecmptrueImpl@log_internal@absl@@YAPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBD00@Z ?CheckstrcmpfalseImpl@log_internal@absl@@YAPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@PBD00@Z @@ -488,6 +491,7 @@ EXPORTS ?DataLossError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?DeadlineExceededError@absl@@YA?AVStatus@1@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@@Z ?DecodeFrom@ProtoField@log_internal@absl@@QAE_NPAV?$Span@$$CBD@3@@Z + ?DecodeRustPunycode@debugging_internal@absl@@YAPADUDecodeRustPunycodeOptions@12@@Z ?DecodeWaitCycles@SpinLock@base_internal@absl@@KA_JI@Z ?DecrementCount@BlockingCounter@absl@@QAE_NXZ ?DecrementSynchSem@Mutex@absl@@CA_NPAV12@PAUPerThreadSynch@base_internal@2@VKernelTimeout@synchronization_internal@2@@Z @@ -737,6 +741,7 @@ EXPORTS ?HandleInvalidStatusCtorArg@Helper@internal_statusor@absl@@SAXPAVStatus@3@@Z ?HandleUsageFlags@flags_internal@absl@@YA?AW4HelpMode@12@AAV?$basic_ostream@DU?$char_traits@D@__Cr@std@@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@56@@Z ?HasBeenNotifiedInternal@Notification@absl@@CA_NPBU?$atomic@_N@__Cr@std@@@Z + ?HasBeenRead@MaskedPointer@flags_internal@absl@@QBE_NXZ ?HasEdge@GraphCycles@synchronization_internal@absl@@QBE_NUGraphId@23@0@Z ?HasNode@GraphCycles@synchronization_internal@absl@@QAE_NUGraphId@23@@Z ?HasRandenHwAesImplementation@random_internal@absl@@YA_NXZ @@ -759,6 +764,7 @@ EXPORTS ?InitWhat@BadStatusOrAccess@absl@@ABEXXZ ?Initialize@ExponentialBiased@profiling_internal@absl@@AAEXXZ ?InitializeCordRepExternal@cord_internal@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAUCordRepExternal@12@@Z + ?InitializeEncodingAndFormat@LogMessageData@LogMessage@log_internal@absl@@QAEXXZ ?InitializeLog@absl@@YAXXZ ?InitializeSymbolizer@absl@@YAXPBD@Z ?InsertEdge@GraphCycles@synchronization_internal@absl@@QAE_NUGraphId@23@0@Z @@ -795,6 +801,7 @@ EXPORTS ?IsUnavailable@absl@@YA_NABVStatus@1@@Z ?IsUnimplemented@absl@@YA_NABVStatus@1@@Z ?IsUnknown@absl@@YA_NABVStatus@1@@Z + ?IsUnprotectedReadCandidate@MaskedPointer@flags_internal@absl@@QBE_NXZ ?IsValid@CordRepBtree@cord_internal@absl@@SA_NPBV123@_N@Z ?KeyFunction@LogSink@absl@@EBEXXZ ?LengthModToString@str_format_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@W4LengthMod@2@@Z @@ -832,6 +839,7 @@ EXPORTS ?MakeTime@TimeZoneInfo@cctz@time_internal@absl@@UBE?AUcivil_lookup@time_zone@234@ABV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MakeTime@TimeZoneLibC@cctz@time_internal@absl@@UBE?AUcivil_lookup@time_zone@234@ABV?$civil_time@Usecond_tag@detail@cctz@time_internal@absl@@@detail@234@@Z ?MapToLocalCode@status_internal@absl@@YA?AW4StatusCode@2@H@Z + ?MarkAsRead@MaskedPointer@flags_internal@absl@@QAEXXZ ?MatchesConversions@ParsedFormatBase@str_format_internal@absl@@ABE_N_NV?$initializer_list@W4FormatConversionCharSet@absl@@@std@@@Z ?MaxFlatLength@CordTestAccess@strings_internal@absl@@SAIXZ ?MaxFramesInLogStackTrace@log_internal@absl@@YAHXZ @@ -879,6 +887,7 @@ EXPORTS ?Now@UnscaledCycleClock@base_internal@absl@@CA_JXZ ?Now@absl@@YA?AVTime@1@XZ ?NumCPUs@base_internal@absl@@YAHXZ + ?NumLeakedFlagValues@flags_internal@absl@@YA_KXZ ?OnVLogVerbosityUpdate@log_internal@absl@@YAXV?$function@$$A6AXXZ@__Cr@std@@@Z ?OneTimeInitThreadIdentity@synchronization_internal@absl@@YAXPAUThreadIdentity@base_internal@2@@Z ?OneWordValue@FlagImpl@flags_internal@absl@@ABEAAU?$atomic@_J@__Cr@std@@XZ @@ -936,6 +945,7 @@ EXPORTS ?ProgramInvocationName@flags_internal@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@XZ ?ProgramUsageMessage@absl@@YA?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@XZ ?Ptr@GraphCycles@synchronization_internal@absl@@QAEPAXUGraphId@23@@Z + ?PtrStorage@FlagImpl@flags_internal@absl@@ABEAAU?$atomic@VMaskedPointer@flags_internal@absl@@@__Cr@std@@XZ ?PutPaddedString@FormatSinkImpl@str_format_internal@absl@@QAE_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@HH_N@Z ?PutTwoDigits@numbers_internal@absl@@YAXIPAD@Z ?RawEnableLogPrefix@log_internal@absl@@YAX_N@Z @@ -1007,6 +1017,7 @@ EXPORTS ?Scramble@CRC32@crc_internal@absl@@UBEXPAI@Z ?Seek@CordRepBtreeReader@cord_internal@absl@@QAE?AV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@I@Z ?SendToLog@LogMessage@log_internal@absl@@AAEXXZ + ?Set@MaskedPointer@flags_internal@absl@@QAEXP6APAXW4FlagOp@23@PBXPAX2@Z1_N@Z ?SetAndroidNativeTag@absl@@YAXPBD@Z ?SetCallback@FlagImpl@flags_internal@absl@@QAEXQ6AXXZ@Z ?SetCordBtreeExhaustiveValidation@cord_internal@absl@@YAX_N@Z @@ -1083,7 +1094,7 @@ EXPORTS ?StatusMessageAsCStr@absl@@YAPBDABVStatus@1@@Z ?StderrThreshold@absl@@YA?AW4LogSeverityAtLeast@1@XZ ?SteadyClockNow@KernelTimeout@synchronization_internal@absl@@CA_JXZ - ?StoreValue@FlagImpl@flags_internal@absl@@AAEXPBX@Z + ?StoreValue@FlagImpl@flags_internal@absl@@AAEXPBXW4ValueSource@23@@Z ?StrAppend@absl@@YAXPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABVAlphaNum@1@111@Z ?StrAppend@absl@@YAXPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABVAlphaNum@1@11@Z ?StrAppend@absl@@YAXPAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@ABVAlphaNum@1@1@Z @@ -1103,6 +1114,7 @@ EXPORTS ?SupportsArmCRC32PMULL@crc_internal@absl@@YA_NXZ ?SuppressSigabortTrace@log_internal@absl@@YA_NXZ ?Symbolize@absl@@YA_NPBXPADH@Z + ?TestOnlyAddNodes@GraphCycles@synchronization_internal@absl@@QAEXI@Z ?ThreadIsLoggingToLogSink@log_internal@absl@@YA_NXZ ?ThrowBadStatusOrAccess@internal_statusor@absl@@YAXVStatus@2@@Z ?ThrowBadVariantAccess@variant_internal@absl@@YAXXZ diff --git a/naiveproxy/src/third_party/apple_apsl/OWNERS b/naiveproxy/src/third_party/apple_apsl/OWNERS index f7103d31bb..62a8343d53 100644 --- a/naiveproxy/src/third_party/apple_apsl/OWNERS +++ b/naiveproxy/src/third_party/apple_apsl/OWNERS @@ -1,2 +1 @@ -avi@chromium.org -mark@chromium.org +file://ui/base/cocoa/OWNERS diff --git a/naiveproxy/src/third_party/boringssl/BUILD.generated.gni b/naiveproxy/src/third_party/boringssl/BUILD.generated.gni index 599b5903de..7135993132 100644 --- a/naiveproxy/src/third_party/boringssl/BUILD.generated.gni +++ b/naiveproxy/src/third_party/boringssl/BUILD.generated.gni @@ -81,7 +81,6 @@ crypto_sources = [ "src/crypto/cipher_extra/internal.h", "src/crypto/cipher_extra/tls_cbc.c", "src/crypto/conf/conf.c", - "src/crypto/conf/conf_def.h", "src/crypto/conf/internal.h", "src/crypto/cpu_aarch64_apple.c", "src/crypto/cpu_aarch64_fuchsia.c", @@ -104,6 +103,8 @@ crypto_sources = [ "src/crypto/dh_extra/dh_asn1.c", "src/crypto/dh_extra/params.c", "src/crypto/digest_extra/digest_extra.c", + "src/crypto/dilithium/dilithium.c", + "src/crypto/dilithium/internal.h", "src/crypto/dsa/dsa.c", "src/crypto/dsa/dsa_asn1.c", "src/crypto/dsa/internal.h", @@ -522,6 +523,7 @@ crypto_headers = [ "src/include/openssl/evp.h", "src/include/openssl/evp_errors.h", "src/include/openssl/ex_data.h", + "src/include/openssl/experimental/dilithium.h", "src/include/openssl/experimental/kyber.h", "src/include/openssl/experimental/spx.h", "src/include/openssl/hkdf.h", @@ -676,6 +678,7 @@ pki_sources = [ "src/pki/trust_store.cc", "src/pki/trust_store_collection.cc", "src/pki/trust_store_in_memory.cc", + "src/pki/verify.cc", "src/pki/verify_certificate_chain.cc", "src/pki/verify_error.cc", "src/pki/verify_name_match.cc", @@ -728,6 +731,7 @@ pki_internal_headers = [ pki_headers = [ "src/include/openssl/pki/certificate.h", "src/include/openssl/pki/signature_verify_cache.h", + "src/include/openssl/pki/verify.h", "src/include/openssl/pki/verify_error.h", ] diff --git a/naiveproxy/src/third_party/boringssl/BUILD.generated_tests.gni b/naiveproxy/src/third_party/boringssl/BUILD.generated_tests.gni index a3068584d9..2f97c1879b 100644 --- a/naiveproxy/src/third_party/boringssl/BUILD.generated_tests.gni +++ b/naiveproxy/src/third_party/boringssl/BUILD.generated_tests.gni @@ -61,6 +61,7 @@ crypto_test_sources = [ "src/crypto/curve25519/x25519_test.cc", "src/crypto/dh_extra/dh_test.cc", "src/crypto/digest_extra/digest_test.cc", + "src/crypto/dilithium/dilithium_test.cc", "src/crypto/dsa/dsa_test.cc", "src/crypto/ecdh_extra/ecdh_test.cc", "src/crypto/err/err_test.cc", @@ -146,6 +147,9 @@ crypto_test_data = [ "src/crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt", "src/crypto/cipher_extra/test/xchacha20_poly1305_tests.txt", "src/crypto/curve25519/ed25519_tests.txt", + "src/crypto/dilithium/dilithium_tests.txt", + "src/crypto/dilithium/edge_cases_draft_dilithium3_sign.txt", + "src/crypto/dilithium/edge_cases_draft_dilithium3_verify.txt", "src/crypto/ecdh_extra/ecdh_tests.txt", "src/crypto/evp/evp_tests.txt", "src/crypto/evp/scrypt_tests.txt", @@ -1761,7 +1765,15 @@ pki_test_data = [ "src/pki/testdata/verify_signed_data_unittest/rsa-pss-sha256.pem", "src/pki/testdata/verify_signed_data_unittest/rsa-using-ec-key.pem", "src/pki/testdata/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem", + "src/pki/testdata/verify_unittest/google-intermediate1.der", + "src/pki/testdata/verify_unittest/google-intermediate2.der", "src/pki/testdata/verify_unittest/google-leaf.der", + "src/pki/testdata/verify_unittest/lencr-intermediate-r3.der", + "src/pki/testdata/verify_unittest/lencr-leaf.der", + "src/pki/testdata/verify_unittest/lencr-root-dst-x3.der", + "src/pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der", + "src/pki/testdata/verify_unittest/lencr-root-x1.der", + "src/pki/testdata/verify_unittest/mozilla_roots.der", "src/pki/testdata/verify_unittest/self-issued.pem", ] @@ -1806,4 +1818,5 @@ pki_test_sources = [ "src/pki/verify_certificate_chain_unittest.cc", "src/pki/verify_name_match_unittest.cc", "src/pki/verify_signed_data_unittest.cc", + "src/pki/verify_unittest.cc", ] diff --git a/naiveproxy/src/third_party/boringssl/BUILD.gn b/naiveproxy/src/third_party/boringssl/BUILD.gn index f1b4a1ac24..f44ece0073 100644 --- a/naiveproxy/src/third_party/boringssl/BUILD.gn +++ b/naiveproxy/src/third_party/boringssl/BUILD.gn @@ -35,11 +35,7 @@ config("component_config") { # this rather than :component_config. config("internal_config") { visibility = [ ":*" ] # Only targets in this file can depend on this. - defines = [ - "BORINGSSL_ALLOW_CXX_RUNTIME", - "BORINGSSL_NO_STATIC_INITIALIZER", - "OPENSSL_SMALL", - ] + defines = [ "OPENSSL_SMALL" ] } config("no_asm_config") { diff --git a/naiveproxy/src/third_party/boringssl/OWNERS b/naiveproxy/src/third_party/boringssl/OWNERS index 89fd9d4a7e..20168f0181 100644 --- a/naiveproxy/src/third_party/boringssl/OWNERS +++ b/naiveproxy/src/third_party/boringssl/OWNERS @@ -1,3 +1,4 @@ agl@chromium.org +bbe@chromium.org davidben@chromium.org svaldez@chromium.org diff --git a/naiveproxy/src/third_party/boringssl/src/CMakeLists.txt b/naiveproxy/src/third_party/boringssl/src/CMakeLists.txt index 39352d684f..26fad80ab5 100644 --- a/naiveproxy/src/third_party/boringssl/src/CMakeLists.txt +++ b/naiveproxy/src/third_party/boringssl/src/CMakeLists.txt @@ -152,6 +152,14 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CLANG) set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wframe-larger-than=25344") endif() + # -Wctad-maybe-unsupported was added in Clang 10, which is AppleClang 12.0.0. + if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND + CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "10.0.0") OR + (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND + CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "12.0.0")) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wctad-maybe-unsupported") + endif() + if(CLANG OR CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0.0") set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wimplicit-fallthrough") endif() @@ -443,8 +451,8 @@ if(USE_CUSTOM_LIBCXX) set_target_properties( libcxx libcxxabi PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-implicit-fallthrough" - # libc++ and libc++abi must be built in C++20 mode. - CXX_STANDARD 20 + # libc++ and libc++abi must be built in C++23 mode. + CXX_STANDARD 23 CXX_STANDARD_REQUIRED TRUE ) # libc++abi depends on libc++ internal headers. diff --git a/naiveproxy/src/third_party/boringssl/src/MODULE.bazel.lock b/naiveproxy/src/third_party/boringssl/src/MODULE.bazel.lock index 7ac13bb5fd..93be30301c 100644 --- a/naiveproxy/src/third_party/boringssl/src/MODULE.bazel.lock +++ b/naiveproxy/src/third_party/boringssl/src/MODULE.bazel.lock @@ -1375,7 +1375,7 @@ }, "@@rules_foreign_cc~//foreign_cc:extensions.bzl%ext": { "general": { - "bzlTransitiveDigest": "QbxK92//k6c63fpMer2Lkk6224s9gwYoVFFS6mdkucI=", + "bzlTransitiveDigest": "0/GTFp9D0gb6hOu9jXXnaWa5hPbzPpIzLVxITdJTwvo=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -1646,7 +1646,7 @@ }, "@@rules_java~//java:extensions.bzl%toolchains": { "general": { - "bzlTransitiveDigest": "tJHbmWnq7m+9eUBnUdv7jZziQ26FmcGL9C5/hU3Q9UQ=", + "bzlTransitiveDigest": "0N5b5J9fUzo0sgvH4F3kIEaeXunz4Wy2/UtSFV/eXUY=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -2151,7 +2151,7 @@ }, "@@rules_python~//python/extensions:python.bzl%python": { "general": { - "bzlTransitiveDigest": "o0WIKfdQRSZd/9+sY+LDTrUuYozMBFuYsL85uwJYKk8=", + "bzlTransitiveDigest": "hcJ2K4XvZ3hi0G4g5MkUEs8xowZlCfrgq3JX4dyipWY=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, diff --git a/naiveproxy/src/third_party/boringssl/src/PORTING.md b/naiveproxy/src/third_party/boringssl/src/PORTING.md index eb951f577f..3faf757b15 100644 --- a/naiveproxy/src/third_party/boringssl/src/PORTING.md +++ b/naiveproxy/src/third_party/boringssl/src/PORTING.md @@ -206,12 +206,8 @@ errors. OpenSSL has a number of different initialization functions for setting up error strings and loading algorithms, etc. All of these functions still exist in -BoringSSL for convenience, but they do nothing and are not necessary. - -The one exception is `CRYPTO_library_init`. In `BORINGSSL_NO_STATIC_INITIALIZER` -builds, it must be called to query CPU capabilities before the rest of the -library. In the default configuration, this is done with a static initializer -and is also unnecessary. +BoringSSL for convenience, but they do nothing and are not necessary. BoringSSL +internally initializes itself as needed. ### Threading diff --git a/naiveproxy/src/third_party/boringssl/src/README.md b/naiveproxy/src/third_party/boringssl/src/README.md index d3d5e29d61..22ea0c7a3b 100644 --- a/naiveproxy/src/third_party/boringssl/src/README.md +++ b/naiveproxy/src/third_party/boringssl/src/README.md @@ -24,7 +24,9 @@ not part of the NDK) and a number of other apps/programs. Project links: * [API documentation](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html) - * [Bug tracker](https://bugs.chromium.org/p/boringssl/issues/list) + * [Bug tracker](https://issues.chromium.org/issues?q=status:open%20componentid:1590116%2B&s=created_time:desc) + * [Filing new issues](https://issues.chromium.org/issues/new?component=1590116&template=2003314) + * [Filing new security issues](https://issues.chromium.org/issues/new?component=1590116&template=2003205) * [CI](https://ci.chromium.org/p/boringssl/g/main/console) * [Code review](https://boringssl-review.googlesource.com) diff --git a/naiveproxy/src/third_party/boringssl/src/build.json b/naiveproxy/src/third_party/boringssl/src/build.json index 11693449ad..28b2111da2 100644 --- a/naiveproxy/src/third_party/boringssl/src/build.json +++ b/naiveproxy/src/third_party/boringssl/src/build.json @@ -93,6 +93,10 @@ "crypto/fipsmodule/sha/sha512.c", "crypto/fipsmodule/tls/kdf.c" ], + "asm": [ + "third_party/fiat/asm/fiat_p256_adx_mul.S", + "third_party/fiat/asm/fiat_p256_adx_sqr.S" + ], "perlasm_aarch64": [ {"src": "crypto/fipsmodule/aes/asm/aesv8-armx.pl", "dst": "aesv8-armv8"}, {"src": "crypto/fipsmodule/modes/asm/aesv8-gcm-armv8.pl"}, @@ -229,6 +233,7 @@ "crypto/dh_extra/params.c", "crypto/dh_extra/dh_asn1.c", "crypto/digest_extra/digest_extra.c", + "crypto/dilithium/dilithium.c", "crypto/dsa/dsa.c", "crypto/dsa/dsa_asn1.c", "crypto/ecdh_extra/ecdh_extra.c", @@ -424,6 +429,7 @@ "include/openssl/evp.h", "include/openssl/evp_errors.h", "include/openssl/ex_data.h", + "include/openssl/experimental/dilithium.h", "include/openssl/experimental/kyber.h", "include/openssl/experimental/spx.h", "include/openssl/hkdf.h", @@ -476,12 +482,12 @@ "crypto/bytestring/internal.h", "crypto/chacha/internal.h", "crypto/cipher_extra/internal.h", - "crypto/conf/conf_def.h", "crypto/conf/internal.h", "crypto/cpu_arm_linux.h", "crypto/curve25519/curve25519_tables.h", "crypto/curve25519/internal.h", "crypto/des/internal.h", + "crypto/dilithium/internal.h", "crypto/dsa/internal.h", "crypto/ec_extra/internal.h", "crypto/err/internal.h", @@ -546,9 +552,7 @@ "crypto/hrss/asm/poly_rq_mul.S", "crypto/poly1305/poly1305_arm_asm.S", "third_party/fiat/asm/fiat_curve25519_adx_mul.S", - "third_party/fiat/asm/fiat_curve25519_adx_square.S", - "third_party/fiat/asm/fiat_p256_adx_mul.S", - "third_party/fiat/asm/fiat_p256_adx_sqr.S" + "third_party/fiat/asm/fiat_curve25519_adx_square.S" ], "perlasm_aarch64": [ {"src": "crypto/chacha/asm/chacha-armv8.pl"}, @@ -600,12 +604,14 @@ "pki/trust_store.cc", "pki/verify_certificate_chain.cc", "pki/verify_error.cc", + "pki/verify.cc", "pki/verify_name_match.cc", "pki/verify_signed_data.cc" ], "hdrs": [ "include/openssl/pki/certificate.h", "include/openssl/pki/signature_verify_cache.h", + "include/openssl/pki/verify.h", "include/openssl/pki/verify_error.h" ], "internal_hdrs": [ @@ -799,6 +805,7 @@ "crypto/ecdh_extra/ecdh_test.cc", "crypto/dh_extra/dh_test.cc", "crypto/digest_extra/digest_test.cc", + "crypto/dilithium/dilithium_test.cc", "crypto/dsa/dsa_test.cc", "crypto/err/err_test.cc", "crypto/evp/evp_extra_test.cc", @@ -853,6 +860,9 @@ "crypto/cipher_extra/test/*.txt", "crypto/cipher_extra/test/nist_cavp/*.txt", "crypto/curve25519/ed25519_tests.txt", + "crypto/dilithium/dilithium_tests.txt", + "crypto/dilithium/edge_cases_draft_dilithium3_sign.txt", + "crypto/dilithium/edge_cases_draft_dilithium3_verify.txt", "crypto/ecdh_extra/ecdh_tests.txt", "crypto/evp/evp_tests.txt", "crypto/evp/scrypt_tests.txt", @@ -920,7 +930,8 @@ "pki/verify_certificate_chain_pkits_unittest.cc", "pki/verify_certificate_chain_unittest.cc", "pki/verify_name_match_unittest.cc", - "pki/verify_signed_data_unittest.cc" + "pki/verify_signed_data_unittest.cc", + "pki/verify_unittest.cc" ], "data": [ "pki/testdata/cert_issuer_source_static_unittest/*.pem", @@ -939,7 +950,7 @@ "pki/testdata/verify_certificate_chain_unittest/pkits_errors/*.txt", "pki/testdata/verify_name_match_unittest/names/*.pem", "pki/testdata/verify_signed_data_unittest/*.pem", - "pki/testdata/verify_unittest/google-leaf.der", + "pki/testdata/verify_unittest/*.der", "pki/testdata/verify_unittest/self-issued.pem" ] }, diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/base64/base64.c b/naiveproxy/src/third_party/boringssl/src/crypto/base64/base64.c index 666f832692..26ad9749aa 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/base64/base64.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/base64/base64.c @@ -307,6 +307,10 @@ static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes, (in[2] == '=') << 1 | (in[3] == '='); + // In presence of padding, the lowest bits of v are unused. Canonical encoding + // (RFC 4648, section 3.5) requires that these bits all be set to zero. Common + // PEM parsers accept noncanonical base64, adding to the malleability of the + // format. This decoder follows OpenSSL's and Go's PEM parsers and accepts it. switch (padding_pattern) { case 0: // The common case of no padding. diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/bytestring/cbs.c b/naiveproxy/src/third_party/boringssl/src/crypto/bytestring/cbs.c index bf94db1189..c5f0464421 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/bytestring/cbs.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/bytestring/cbs.c @@ -507,11 +507,9 @@ int CBS_get_asn1_int64(CBS *cbs, int64_t *out) { return 0; } uint8_t sign_extend[sizeof(int64_t)]; - memset(sign_extend, is_negative ? 0xff : 0, sizeof(sign_extend)); - for (size_t i = 0; i < len; i++) { - sign_extend[i] = data[len - i - 1]; - } - memcpy(out, sign_extend, sizeof(sign_extend)); + OPENSSL_memset(sign_extend, is_negative ? 0xff : 0, sizeof(sign_extend)); + OPENSSL_memcpy(sign_extend + sizeof(int64_t) - len, data, len); + *out = CRYPTO_load_u64_be(sign_extend); return 1; } diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/chacha/asm/chacha-x86_64.pl b/naiveproxy/src/third_party/boringssl/src/crypto/chacha/asm/chacha-x86_64.pl index 6d26b713df..333ef9b263 100755 --- a/naiveproxy/src/third_party/boringssl/src/crypto/chacha/asm/chacha-x86_64.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/chacha/asm/chacha-x86_64.pl @@ -701,7 +701,6 @@ ChaCha20_ctr32_ssse3_4x: _CET_ENDBR mov %rsp,%r9 # frame pointer .cfi_def_cfa_register r9 - mov %r10,%r11 ___ $code.=<<___; sub \$0x140+$xframe,%rsp diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/cipher_extra/e_chacha20poly1305.c b/naiveproxy/src/third_party/boringssl/src/crypto/cipher_extra/e_chacha20poly1305.c index 6510ff48ad..d2004652ca 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/cipher_extra/e_chacha20poly1305.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/cipher_extra/e_chacha20poly1305.c @@ -41,6 +41,13 @@ static_assert(alignof(union evp_aead_ctx_st_state) >= static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len) { + // TODO(crbug.com/42290548): The x86_64 assembly depends on initializing + // |OPENSSL_ia32cap_P|. Move the dispatch to C. While we're here, it may be + // worth adjusting the assembly calling convention. The assembly functions do + // too much work right now. For now, explicitly initialize |OPENSSL_ia32cap_P| + // first. + OPENSSL_init_cpuid(); + struct aead_chacha20_poly1305_ctx *c20_ctx = (struct aead_chacha20_poly1305_ctx *)&ctx->state; diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/conf/conf.c b/naiveproxy/src/third_party/boringssl/src/crypto/conf/conf.c index 40e8ffba23..1faba5febe 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/conf/conf.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/conf/conf.c @@ -56,6 +56,7 @@ #include +#include #include #include @@ -65,7 +66,6 @@ #include #include -#include "conf_def.h" #include "internal.h" #include "../internal.h" @@ -183,6 +183,26 @@ err: return NULL; } +static int is_comment(char c) { return c == '#'; } + +static int is_quote(char c) { return c == '"' || c == '\'' || c == '`'; } + +static int is_esc(char c) { return c == '\\'; } + +static int is_conf_ws(char c) { + // This differs from |OPENSSL_isspace| in that CONF does not accept '\v' and + // '\f' as whitespace. + return c == ' ' || c == '\t' || c == '\r' || c == '\n'; +} + +static int is_name_char(char c) { + // Alphanumeric characters, and a handful of symbols, may appear in value and + // section names without escaping. + return OPENSSL_isalnum(c) || c == '_' || c == '!' || c == '.' || c == '%' || + c == '&' || c == '*' || c == '+' || c == ',' || c == '/' || c == ';' || + c == '?' || c == '@' || c == '^' || c == '~' || c == '|' || c == '-'; +} + static int str_copy(CONF *conf, char *section, char **pto, char *from) { int q, to = 0, len = 0; char v; @@ -199,13 +219,13 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from) { } for (;;) { - if (IS_QUOTE(conf, *from)) { + if (is_quote(*from)) { q = *from; from++; - while (!IS_EOF(conf, *from) && (*from != q)) { - if (IS_ESC(conf, *from)) { + while (*from != '\0' && *from != q) { + if (is_esc(*from)) { from++; - if (IS_EOF(conf, *from)) { + if (*from == '\0') { break; } } @@ -214,10 +234,10 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from) { if (*from == q) { from++; } - } else if (IS_ESC(conf, *from)) { + } else if (is_esc(*from)) { from++; v = *(from++); - if (IS_EOF(conf, v)) { + if (v == '\0') { break; } else if (v == 'r') { v = '\r'; @@ -229,11 +249,13 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from) { v = '\t'; } buf->data[to++] = v; - } else if (IS_EOF(conf, *from)) { + } else if (*from == '\0') { break; } else if (*from == '$') { // Historically, $foo would expand to a previously-parsed value. This - // feature has been removed as it was unused and is a DoS vector. + // feature has been removed as it was unused and is a DoS vector. If + // trying to embed '$' in a line, either escape it or wrap the value in + // quotes. OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_EXPANSION_NOT_SUPPORTED); goto err; } else { @@ -312,36 +334,39 @@ static int add_string(const CONF *conf, CONF_SECTION *section, return 1; } -static char *eat_ws(CONF *conf, char *p) { - while (IS_WS(conf, *p) && !IS_EOF(conf, *p)) { +static char *eat_ws(char *p) { + while (*p != '\0' && is_conf_ws(*p)) { p++; } return p; } -#define scan_esc(conf, p) (((IS_EOF((conf), (p)[1])) ? ((p) + 1) : ((p) + 2))) +static char *scan_esc(char *p) { + assert(p[0] == '\\'); + return p[1] == '\0' ? p + 1 : p + 2; +} -static char *eat_alpha_numeric(CONF *conf, char *p) { +static char *eat_name(char *p) { for (;;) { - if (IS_ESC(conf, *p)) { - p = scan_esc(conf, p); + if (is_esc(*p)) { + p = scan_esc(p); continue; } - if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p)) { + if (!is_name_char(*p)) { return p; } p++; } } -static char *scan_quote(CONF *conf, char *p) { +static char *scan_quote(char *p) { int q = *p; p++; - while (!IS_EOF(conf, *p) && *p != q) { - if (IS_ESC(conf, *p)) { + while (*p != '\0' && *p != q) { + if (is_esc(*p)) { p++; - if (IS_EOF(conf, *p)) { + if (*p == '\0') { return p; } } @@ -353,28 +378,28 @@ static char *scan_quote(CONF *conf, char *p) { return p; } -static void clear_comments(CONF *conf, char *p) { +static void clear_comments(char *p) { for (;;) { - if (!IS_WS(conf, *p)) { + if (!is_conf_ws(*p)) { break; } p++; } for (;;) { - if (IS_COMMENT(conf, *p)) { + if (is_comment(*p)) { *p = '\0'; return; } - if (IS_QUOTE(conf, *p)) { - p = scan_quote(conf, p); + if (is_quote(*p)) { + p = scan_quote(p); continue; } - if (IS_ESC(conf, *p)) { - p = scan_esc(conf, p); + if (is_esc(*p)) { + p = scan_esc(p); continue; } - if (IS_EOF(conf, *p)) { + if (*p == '\0') { return; } else { p++; @@ -454,7 +479,7 @@ int NCONF_load_bio(CONF *conf, BIO *in, long *out_error_line) { // If we have bytes and the last char '\\' and // second last char is not '\\' p = &(buff->data[bufnum - 1]); - if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { + if (is_esc(p[0]) && ((bufnum <= 1) || !is_esc(p[-1]))) { bufnum--; again = 1; } @@ -465,20 +490,20 @@ int NCONF_load_bio(CONF *conf, BIO *in, long *out_error_line) { bufnum = 0; buf = buff->data; - clear_comments(conf, buf); - s = eat_ws(conf, buf); - if (IS_EOF(conf, *s)) { + clear_comments(buf); + s = eat_ws(buf); + if (*s == '\0') { continue; // blank line } if (*s == '[') { char *ss; s++; - start = eat_ws(conf, s); + start = eat_ws(s); ss = start; again: - end = eat_alpha_numeric(conf, ss); - p = eat_ws(conf, end); + end = eat_name(ss); + p = eat_ws(end); if (*p != ']') { if (*p != '\0' && ss != p) { ss = p; @@ -502,27 +527,27 @@ int NCONF_load_bio(CONF *conf, BIO *in, long *out_error_line) { } else { pname = s; psection = NULL; - end = eat_alpha_numeric(conf, s); + end = eat_name(s); if ((end[0] == ':') && (end[1] == ':')) { *end = '\0'; end += 2; psection = pname; pname = end; - end = eat_alpha_numeric(conf, end); + end = eat_name(end); } - p = eat_ws(conf, end); + p = eat_ws(end); if (*p != '=') { OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_EQUAL_SIGN); goto err; } *end = '\0'; p++; - start = eat_ws(conf, p); - while (!IS_EOF(conf, *p)) { + start = eat_ws(p); + while (*p != '\0') { p++; } p--; - while ((p != start) && (IS_WS(conf, *p))) { + while (p != start && is_conf_ws(*p)) { p--; } p++; diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/conf/conf_def.h b/naiveproxy/src/third_party/boringssl/src/crypto/conf/conf_def.h deleted file mode 100644 index d2c285aef9..0000000000 --- a/naiveproxy/src/third_party/boringssl/src/crypto/conf/conf_def.h +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - -// This file was historically generated by keysets.pl in OpenSSL. -// -// TODO(davidben): Replace it with something more readable. - -#define CONF_NUMBER 1 -#define CONF_UPPER 2 -#define CONF_LOWER 4 -#define CONF_UNDER 256 -#define CONF_PUNCTUATION 512 -#define CONF_WS 16 -#define CONF_ESC 32 -#define CONF_QUOTE 64 -#define CONF_COMMENT 128 -#define CONF_EOF 8 -#define CONF_HIGHBIT 4096 -#define CONF_ALPHA (CONF_UPPER|CONF_LOWER) -#define CONF_ALPHA_NUMERIC (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) -#define CONF_ALPHA_NUMERIC_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER| \ - CONF_PUNCTUATION) - -#define KEYTYPES(c) CONF_type_default -#define IS_COMMENT(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_COMMENT) -#define IS_EOF(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_EOF) -#define IS_ESC(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_ESC) -#define IS_NUMBER(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_NUMBER) -#define IS_WS(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_WS) -#define IS_ALPHA_NUMERIC(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC) -#define IS_ALPHA_NUMERIC_PUNCT(c,a) \ - (KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC_PUNCT) -#define IS_QUOTE(c,a) (KEYTYPES(c)[(a)&0xff]&CONF_QUOTE) - -static const unsigned short CONF_type_default[256]={ - 0x0008,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0000,0x0010,0x0010,0x0000,0x0000,0x0010,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, - 0x0010,0x0200,0x0040,0x0080,0x0000,0x0200,0x0200,0x0040, - 0x0000,0x0000,0x0200,0x0200,0x0200,0x0200,0x0200,0x0200, - 0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001, - 0x0001,0x0001,0x0000,0x0200,0x0000,0x0000,0x0000,0x0200, - 0x0200,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, - 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, - 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002, - 0x0002,0x0002,0x0002,0x0000,0x0020,0x0000,0x0200,0x0100, - 0x0040,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, - 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, - 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004, - 0x0004,0x0004,0x0004,0x0000,0x0200,0x0000,0x0200,0x0000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000, - }; diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/cpu_arm_linux.c b/naiveproxy/src/third_party/boringssl/src/crypto/cpu_arm_linux.c index e3a237083d..dbcd940d5f 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/cpu_arm_linux.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/cpu_arm_linux.c @@ -143,6 +143,9 @@ void OPENSSL_cpuid_setup(void) { int CRYPTO_has_broken_NEON(void) { return 0; } -int CRYPTO_needs_hwcap2_workaround(void) { return g_needs_hwcap2_workaround; } +int CRYPTO_needs_hwcap2_workaround(void) { + OPENSSL_init_cpuid(); + return g_needs_hwcap2_workaround; +} #endif // OPENSSL_ARM && OPENSSL_LINUX && !OPENSSL_STATIC_ARMCAP diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/cpu_intel.c b/naiveproxy/src/third_party/boringssl/src/crypto/cpu_intel.c index f657e4cd54..347eadca98 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/cpu_intel.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/cpu_intel.c @@ -208,15 +208,6 @@ void OPENSSL_cpuid_setup(void) { // Reserved bit #30 is repurposed to signal an Intel CPU. if (is_intel) { edx |= (1u << 30); - - // Clear the XSAVE bit on Knights Landing to mimic Silvermont. This enables - // some Silvermont-specific codepaths which perform better. See OpenSSL - // commit 64d92d74985ebb3d0be58a9718f9e080a14a8e7f and - // |CRYPTO_cpu_perf_is_like_silvermont|. - if ((eax & 0x0fff0ff0) == 0x00050670 /* Knights Landing */ || - (eax & 0x0fff0ff0) == 0x00080650 /* Knights Mill (per SDE) */) { - ecx &= ~(1u << 26); - } } else { edx &= ~(1u << 30); } @@ -251,12 +242,6 @@ void OPENSSL_cpuid_setup(void) { extended_features[0] &= ~(1u << 16); } - // Disable ADX instructions on Knights Landing. See OpenSSL commit - // 64d92d74985ebb3d0be58a9718f9e080a14a8e7f. - if ((ecx & (1u << 26)) == 0) { - extended_features[0] &= ~(1u << 19); - } - OPENSSL_ia32cap_P[0] = edx; OPENSSL_ia32cap_P[1] = ecx; OPENSSL_ia32cap_P[2] = extended_features[0]; diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/crypto.c b/naiveproxy/src/third_party/boringssl/src/crypto/crypto.c index 0bca1e2160..724a774a28 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/crypto.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/crypto.c @@ -24,23 +24,6 @@ static_assert(sizeof(ossl_ssize_t) == sizeof(size_t), "ossl_ssize_t should be the same size as size_t"); -#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_STATIC_ARMCAP) && \ - (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ - defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) -// x86, x86_64, and the ARMs need to record the result of a cpuid/getauxval call -// for the asm to work correctly, unless compiled without asm code. -#define NEED_CPUID - -#else - -// Otherwise, don't emit a static initialiser. - -#if !defined(BORINGSSL_NO_STATIC_INITIALIZER) -#define BORINGSSL_NO_STATIC_INITIALIZER -#endif - -#endif // !NO_ASM && !STATIC_ARMCAP && (X86 || X86_64 || ARM || AARCH64) - // Our assembly does not use the GOT to reference symbols, which means // references to visible symbols will often require a TEXTREL. This is @@ -79,7 +62,7 @@ HIDDEN uint8_t BORINGSSL_function_hit[7] = {0}; HIDDEN uint32_t OPENSSL_ia32cap_P[4] = {0}; uint32_t OPENSSL_get_ia32cap(int idx) { - CRYPTO_library_init(); + OPENSSL_init_cpuid(); return OPENSSL_ia32cap_P[idx]; } @@ -121,60 +104,24 @@ HIDDEN uint32_t OPENSSL_armcap_P = HIDDEN uint32_t OPENSSL_armcap_P = 0; uint32_t *OPENSSL_get_armcap_pointer_for_test(void) { - CRYPTO_library_init(); + OPENSSL_init_cpuid(); return &OPENSSL_armcap_P; } #endif uint32_t OPENSSL_get_armcap(void) { - CRYPTO_library_init(); + OPENSSL_init_cpuid(); return OPENSSL_armcap_P; } #endif -#if defined(BORINGSSL_FIPS) -// In FIPS mode, the power-on self-test function calls |CRYPTO_library_init| -// because we have to ensure that CPUID detection occurs first. -#define BORINGSSL_NO_STATIC_INITIALIZER -#endif - -#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_NO_STATIC_INITIALIZER) -#define OPENSSL_CDECL __cdecl -#else -#define OPENSSL_CDECL -#endif - -#if defined(BORINGSSL_NO_STATIC_INITIALIZER) -static CRYPTO_once_t once = CRYPTO_ONCE_INIT; -#elif defined(_MSC_VER) -#pragma section(".CRT$XCU", read) -static void __cdecl do_library_init(void); -__declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) = - do_library_init; -#else -static void do_library_init(void) __attribute__ ((constructor)); -#endif - -// do_library_init is the actual initialization function. If -// BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static -// initializer. Otherwise, it is called by CRYPTO_library_init. -static void OPENSSL_CDECL do_library_init(void) { - // WARNING: this function may only configure the capability variables. See the - // note above about the linker bug. #if defined(NEED_CPUID) - OPENSSL_cpuid_setup(); +static CRYPTO_once_t once = CRYPTO_ONCE_INIT; +void OPENSSL_init_cpuid(void) { CRYPTO_once(&once, OPENSSL_cpuid_setup); } #endif -} -void CRYPTO_library_init(void) { - // TODO(davidben): It would be tidier if this build knob could be replaced - // with an internal lazy-init mechanism that would handle things correctly - // in-library. https://crbug.com/542879 -#if defined(BORINGSSL_NO_STATIC_INITIALIZER) - CRYPTO_once(&once, do_library_init); -#endif -} +void CRYPTO_library_init(void) {} int CRYPTO_is_confidential_build(void) { #if defined(BORINGSSL_CONFIDENTIAL) @@ -194,7 +141,7 @@ int CRYPTO_has_asm(void) { void CRYPTO_pre_sandbox_init(void) { // Read from /proc/cpuinfo if needed. - CRYPTO_library_init(); + OPENSSL_init_cpuid(); // Open /dev/urandom if needed. CRYPTO_init_sysrand(); // Set up MADV_WIPEONFORK state if needed. @@ -235,7 +182,6 @@ int ENGINE_register_all_complete(void) { return 1; } void OPENSSL_load_builtin_modules(void) {} int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) { - CRYPTO_library_init(); return 1; } diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/dilithium.c b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/dilithium.c new file mode 100644 index 0000000000..4f209bf76e --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/dilithium.c @@ -0,0 +1,1497 @@ +/* Copyright (c) 2023, Google LLC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#define OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM +#include + +#include +#include + +#include +#include + +#include "../internal.h" +#include "../keccak/internal.h" +#include "./internal.h" + +#define DEGREE 256 +#define K 6 +#define L 5 +#define ETA 4 +#define TAU 49 +#define BETA 196 +#define OMEGA 55 + +#define RHO_BYTES 32 +#define SIGMA_BYTES 64 +#define K_BYTES 32 +#define TR_BYTES 64 +#define MU_BYTES 64 +#define RHO_PRIME_BYTES 64 +#define LAMBDA_BITS 192 +#define LAMBDA_BYTES (LAMBDA_BITS / 8) + +// 2^23 - 2^13 + 1 +static const uint32_t kPrime = 8380417; +// Inverse of -kPrime modulo 2^32 +static const uint32_t kPrimeNegInverse = 4236238847; +static const int kDroppedBits = 13; +static const uint32_t kHalfPrime = (8380417 - 1) / 2; +static const uint32_t kGamma1 = 1 << 19; +static const uint32_t kGamma2 = (8380417 - 1) / 32; +// 256^-1 mod kPrime, in Montgomery form. +static const uint32_t kInverseDegreeMontgomery = 41978; + +typedef struct scalar { + uint32_t c[DEGREE]; +} scalar; + +typedef struct vectork { + scalar v[K]; +} vectork; + +typedef struct vectorl { + scalar v[L]; +} vectorl; + +typedef struct matrix { + scalar v[K][L]; +} matrix; + +/* Arithmetic */ + +// This bit of Python will be referenced in some of the following comments: +// +// q = 8380417 +// # Inverse of -q modulo 2^32 +// q_neg_inverse = 4236238847 +// # 2^64 modulo q +// montgomery_square = 2365951 +// +// def bitreverse(i): +// ret = 0 +// for n in range(8): +// bit = i & 1 +// ret <<= 1 +// ret |= bit +// i >>= 1 +// return ret +// +// def montgomery_reduce(x): +// a = (x * q_neg_inverse) % 2**32 +// b = x + a * q +// assert b & 0xFFFF_FFFF == 0 +// c = b >> 32 +// assert c < q +// return c +// +// def montgomery_transform(x): +// return montgomery_reduce(x * montgomery_square) + +// kNTTRootsMontgomery = [ +// montgomery_transform(pow(1753, bitreverse(i), q)) for i in range(256) +// ] +static const uint32_t kNTTRootsMontgomery[256] = { + 4193792, 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468, + 1826347, 2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103, + 2725464, 1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868, + 6262231, 4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005, + 2706023, 95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439, + 4519302, 5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118, + 6681150, 6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596, + 811944, 531354, 954230, 3881043, 3900724, 5823537, 2071892, 5582638, + 4450022, 6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196, + 7122806, 1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922, + 3412210, 7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370, + 7709315, 7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987, + 5037034, 264944, 508951, 3097992, 44288, 7280319, 904516, 3958618, + 4656075, 8371839, 1653064, 5130689, 2389356, 8169440, 759969, 7063561, + 189548, 4827145, 3159746, 6529015, 5971092, 8202977, 1315589, 1341330, + 1285669, 6795489, 7567685, 6940675, 5361315, 4499357, 4751448, 3839961, + 2091667, 3407706, 2316500, 3817976, 5037939, 2244091, 5933984, 4817955, + 266997, 2434439, 7144689, 3513181, 4860065, 4621053, 7183191, 5187039, + 900702, 1859098, 909542, 819034, 495491, 6767243, 8337157, 7857917, + 7725090, 5257975, 2031748, 3207046, 4823422, 7855319, 7611795, 4784579, + 342297, 286988, 5942594, 4108315, 3437287, 5038140, 1735879, 203044, + 2842341, 2691481, 5790267, 1265009, 4055324, 1247620, 2486353, 1595974, + 4613401, 1250494, 2635921, 4832145, 5386378, 1869119, 1903435, 7329447, + 7047359, 1237275, 5062207, 6950192, 7929317, 1312455, 3306115, 6417775, + 7100756, 1917081, 5834105, 7005614, 1500165, 777191, 2235880, 3406031, + 7838005, 5548557, 6709241, 6533464, 5796124, 4656147, 594136, 4603424, + 6366809, 2432395, 2454455, 8215696, 1957272, 3369112, 185531, 7173032, + 5196991, 162844, 1616392, 3014001, 810149, 1652634, 4686184, 6581310, + 5341501, 3523897, 3866901, 269760, 2213111, 7404533, 1717735, 472078, + 7953734, 1723600, 6577327, 1910376, 6712985, 7276084, 8119771, 4546524, + 5441381, 6144432, 7959518, 6094090, 183443, 7403526, 1612842, 4834730, + 7826001, 3919660, 8332111, 7018208, 3937738, 1400424, 7534263, 1976782}; + +// Reduces x mod kPrime in constant time, where 0 <= x < 2*kPrime. +static uint32_t reduce_once(uint32_t x) { + declassify_assert(x < 2 * kPrime); + // return x < kPrime ? x : x - kPrime; + return constant_time_select_int(constant_time_lt_w(x, kPrime), x, x - kPrime); +} + +// Returns the absolute value in constant time. +static uint32_t abs_signed(uint32_t x) { + // return is_positive(x) ? x : -x; + // Note: MSVC doesn't like applying the unary minus operator to unsigned types + // (warning C4146), so we write the negation as a bitwise not plus one + // (assuming two's complement representation). + return constant_time_select_int(constant_time_lt_w(x, 0x80000000), x, ~x + 1); +} + +// Returns the absolute value modulo kPrime. +static uint32_t abs_mod_prime(uint32_t x) { + declassify_assert(x < kPrime); + // return x > kHalfPrime ? kPrime - x : x; + return constant_time_select_int(constant_time_lt_w(kHalfPrime, x), kPrime - x, + x); +} + +// Returns the maximum of two values in constant time. +static uint32_t maximum(uint32_t x, uint32_t y) { + // return x < y ? y : x; + return constant_time_select_int(constant_time_lt_w(x, y), y, x); +} + +static void scalar_add(scalar *out, const scalar *lhs, const scalar *rhs) { + for (int i = 0; i < DEGREE; i++) { + out->c[i] = reduce_once(lhs->c[i] + rhs->c[i]); + } +} + +static void scalar_sub(scalar *out, const scalar *lhs, const scalar *rhs) { + for (int i = 0; i < DEGREE; i++) { + out->c[i] = reduce_once(kPrime + lhs->c[i] - rhs->c[i]); + } +} + +static uint32_t reduce_montgomery(uint64_t x) { + uint64_t a = (uint32_t)x * kPrimeNegInverse; + uint64_t b = x + a * kPrime; + declassify_assert((b & 0xffffffff) == 0); + uint32_t c = b >> 32; + return reduce_once(c); +} + +// Multiply two scalars in the number theoretically transformed state. +static void scalar_mult(scalar *out, const scalar *lhs, const scalar *rhs) { + for (int i = 0; i < DEGREE; i++) { + out->c[i] = reduce_montgomery((uint64_t)lhs->c[i] * (uint64_t)rhs->c[i]); + } +} + +// In place number theoretic transform of a given scalar. +// +// FIPS 204, Algorithm 35 (`NTT`). +static void scalar_ntt(scalar *s) { + // Step: 1, 2, 4, 8, ..., 128 + // Offset: 128, 64, 32, 16, ..., 1 + int offset = DEGREE; + for (int step = 1; step < DEGREE; step <<= 1) { + offset >>= 1; + int k = 0; + for (int i = 0; i < step; i++) { + assert(k == 2 * offset * i); + const uint32_t step_root = kNTTRootsMontgomery[step + i]; + for (int j = k; j < k + offset; j++) { + uint32_t even = s->c[j]; + uint32_t odd = + reduce_montgomery((uint64_t)step_root * (uint64_t)s->c[j + offset]); + s->c[j] = reduce_once(odd + even); + s->c[j + offset] = reduce_once(kPrime + even - odd); + } + k += 2 * offset; + } + } +} + +// In place inverse number theoretic transform of a given scalar. +// +// FIPS 204, Algorithm 36 (`NTT^-1`). +static void scalar_inverse_ntt(scalar *s) { + // Step: 128, 64, 32, 16, ..., 1 + // Offset: 1, 2, 4, 8, ..., 128 + int step = DEGREE; + for (int offset = 1; offset < DEGREE; offset <<= 1) { + step >>= 1; + int k = 0; + for (int i = 0; i < step; i++) { + assert(k == 2 * offset * i); + const uint32_t step_root = + kPrime - kNTTRootsMontgomery[step + (step - 1 - i)]; + for (int j = k; j < k + offset; j++) { + uint32_t even = s->c[j]; + uint32_t odd = s->c[j + offset]; + s->c[j] = reduce_once(odd + even); + s->c[j + offset] = reduce_montgomery((uint64_t)step_root * + (uint64_t)(kPrime + even - odd)); + } + k += 2 * offset; + } + } + for (int i = 0; i < DEGREE; i++) { + s->c[i] = reduce_montgomery((uint64_t)s->c[i] * + (uint64_t)kInverseDegreeMontgomery); + } +} + +static void vectork_zero(vectork *out) { OPENSSL_memset(out, 0, sizeof(*out)); } + +static void vectork_add(vectork *out, const vectork *lhs, const vectork *rhs) { + for (int i = 0; i < K; i++) { + scalar_add(&out->v[i], &lhs->v[i], &rhs->v[i]); + } +} + +static void vectork_sub(vectork *out, const vectork *lhs, const vectork *rhs) { + for (int i = 0; i < K; i++) { + scalar_sub(&out->v[i], &lhs->v[i], &rhs->v[i]); + } +} + +static void vectork_mult_scalar(vectork *out, const vectork *lhs, + const scalar *rhs) { + for (int i = 0; i < K; i++) { + scalar_mult(&out->v[i], &lhs->v[i], rhs); + } +} + +static void vectork_ntt(vectork *a) { + for (int i = 0; i < K; i++) { + scalar_ntt(&a->v[i]); + } +} + +static void vectork_inverse_ntt(vectork *a) { + for (int i = 0; i < K; i++) { + scalar_inverse_ntt(&a->v[i]); + } +} + +static void vectorl_add(vectorl *out, const vectorl *lhs, const vectorl *rhs) { + for (int i = 0; i < L; i++) { + scalar_add(&out->v[i], &lhs->v[i], &rhs->v[i]); + } +} + +static void vectorl_mult_scalar(vectorl *out, const vectorl *lhs, + const scalar *rhs) { + for (int i = 0; i < L; i++) { + scalar_mult(&out->v[i], &lhs->v[i], rhs); + } +} + +static void vectorl_ntt(vectorl *a) { + for (int i = 0; i < L; i++) { + scalar_ntt(&a->v[i]); + } +} + +static void vectorl_inverse_ntt(vectorl *a) { + for (int i = 0; i < L; i++) { + scalar_inverse_ntt(&a->v[i]); + } +} + +static void matrix_mult(vectork *out, const matrix *m, const vectorl *a) { + vectork_zero(out); + for (int i = 0; i < K; i++) { + for (int j = 0; j < L; j++) { + scalar product; + scalar_mult(&product, &m->v[i][j], &a->v[j]); + scalar_add(&out->v[i], &out->v[i], &product); + } + } +} + +/* Rounding & hints */ + +// FIPS 204, Algorithm 29 (`Power2Round`). +static void power2_round(uint32_t *r1, uint32_t *r0, uint32_t r) { + *r1 = r >> kDroppedBits; + *r0 = r - (*r1 << kDroppedBits); + + uint32_t r0_adjusted = reduce_once(kPrime + *r0 - (1 << kDroppedBits)); + uint32_t r1_adjusted = *r1 + 1; + + // Mask is set iff r0 > 2^(dropped_bits - 1). + crypto_word_t mask = + constant_time_lt_w((uint32_t)(1 << (kDroppedBits - 1)), *r0); + // r0 = mask ? r0_adjusted : r0 + *r0 = constant_time_select_int(mask, r0_adjusted, *r0); + // r1 = mask ? r1_adjusted : r1 + *r1 = constant_time_select_int(mask, r1_adjusted, *r1); +} + +// Scale back previously rounded value. +static void scale_power2_round(uint32_t *out, uint32_t r1) { + // Pre-condition: 0 <= r1 <= 2^10 - 1 + *out = r1 << kDroppedBits; + // Post-condition: 0 <= out <= 2^23 - 2^13 = kPrime - 1 + assert(*out < kPrime); +} + +// FIPS 204, Algorithm 31 (`HighBits`). +static uint32_t high_bits(uint32_t x) { + // Reference description (given 0 <= x < q): + // + // ``` + // int32_t r0 = x mod+- (2 * kGamma2); + // if (x - r0 == q - 1) { + // return 0; + // } else { + // return (x - r0) / (2 * kGamma2); + // } + // ``` + // + // Below is the formula taken from the reference implementation. + // + // Here, kGamma2 == 2^18 - 2^8 + // This returns ((ceil(x / 2^7) * (2^10 + 1) + 2^21) / 2^22) mod 2^4 + uint32_t r1 = (x + 127) >> 7; + r1 = (r1 * 1025 + (1 << 21)) >> 22; + r1 &= 15; + return r1; +} + +// FIPS 204, Algorithm 30 (`Decompose`). +static void decompose(uint32_t *r1, int32_t *r0, uint32_t r) { + *r1 = high_bits(r); + + *r0 = r; + *r0 -= *r1 * 2 * (int32_t)kGamma2; + *r0 -= (((int32_t)kHalfPrime - *r0) >> 31) & (int32_t)kPrime; +} + +// FIPS 204, Algorithm 32 (`LowBits`). +static int32_t low_bits(uint32_t x) { + uint32_t r1; + int32_t r0; + decompose(&r1, &r0, x); + return r0; +} + +// FIPS 204, Algorithm 33 (`MakeHint`). +static int32_t make_hint(uint32_t ct0, uint32_t cs2, uint32_t w) { + uint32_t r_plus_z = reduce_once(kPrime + w - cs2); + uint32_t r = reduce_once(r_plus_z + ct0); + return high_bits(r) != high_bits(r_plus_z); +} + +// FIPS 204, Algorithm 34 (`UseHint`). +static uint32_t use_hint_vartime(uint32_t h, uint32_t r) { + uint32_t r1; + int32_t r0; + decompose(&r1, &r0, r); + + if (h) { + if (r0 > 0) { + return (r1 + 1) & 15; + } else { + return (r1 - 1) & 15; + } + } else { + return r1; + } +} + +static void scalar_power2_round(scalar *s1, scalar *s0, const scalar *s) { + for (int i = 0; i < DEGREE; i++) { + power2_round(&s1->c[i], &s0->c[i], s->c[i]); + } +} + +static void scalar_scale_power2_round(scalar *out, const scalar *in) { + for (int i = 0; i < DEGREE; i++) { + scale_power2_round(&out->c[i], in->c[i]); + } +} + +static void scalar_high_bits(scalar *out, const scalar *in) { + for (int i = 0; i < DEGREE; i++) { + out->c[i] = high_bits(in->c[i]); + } +} + +static void scalar_low_bits(scalar *out, const scalar *in) { + for (int i = 0; i < DEGREE; i++) { + out->c[i] = low_bits(in->c[i]); + } +} + +static void scalar_max(uint32_t *max, const scalar *s) { + for (int i = 0; i < DEGREE; i++) { + uint32_t abs = abs_mod_prime(s->c[i]); + *max = maximum(*max, abs); + } +} + +static void scalar_max_signed(uint32_t *max, const scalar *s) { + for (int i = 0; i < DEGREE; i++) { + uint32_t abs = abs_signed(s->c[i]); + *max = maximum(*max, abs); + } +} + +static void scalar_make_hint(scalar *out, const scalar *ct0, const scalar *cs2, + const scalar *w) { + for (int i = 0; i < DEGREE; i++) { + out->c[i] = make_hint(ct0->c[i], cs2->c[i], w->c[i]); + } +} + +static void scalar_use_hint_vartime(scalar *out, const scalar *h, + const scalar *r) { + for (int i = 0; i < DEGREE; i++) { + out->c[i] = use_hint_vartime(h->c[i], r->c[i]); + } +} + +static void vectork_power2_round(vectork *t1, vectork *t0, const vectork *t) { + for (int i = 0; i < K; i++) { + scalar_power2_round(&t1->v[i], &t0->v[i], &t->v[i]); + } +} + +static void vectork_scale_power2_round(vectork *out, const vectork *in) { + for (int i = 0; i < K; i++) { + scalar_scale_power2_round(&out->v[i], &in->v[i]); + } +} + +static void vectork_high_bits(vectork *out, const vectork *in) { + for (int i = 0; i < K; i++) { + scalar_high_bits(&out->v[i], &in->v[i]); + } +} + +static void vectork_low_bits(vectork *out, const vectork *in) { + for (int i = 0; i < K; i++) { + scalar_low_bits(&out->v[i], &in->v[i]); + } +} + +static uint32_t vectork_max(const vectork *a) { + uint32_t max = 0; + for (int i = 0; i < K; i++) { + scalar_max(&max, &a->v[i]); + } + return max; +} + +static uint32_t vectork_max_signed(const vectork *a) { + uint32_t max = 0; + for (int i = 0; i < K; i++) { + scalar_max_signed(&max, &a->v[i]); + } + return max; +} + +// The input vector contains only zeroes and ones. +static size_t vectork_count_ones(const vectork *a) { + size_t count = 0; + for (int i = 0; i < K; i++) { + for (int j = 0; j < DEGREE; j++) { + count += a->v[i].c[j]; + } + } + return count; +} + +static void vectork_make_hint(vectork *out, const vectork *ct0, + const vectork *cs2, const vectork *w) { + for (int i = 0; i < K; i++) { + scalar_make_hint(&out->v[i], &ct0->v[i], &cs2->v[i], &w->v[i]); + } +} + +static void vectork_use_hint_vartime(vectork *out, const vectork *h, + const vectork *r) { + for (int i = 0; i < K; i++) { + scalar_use_hint_vartime(&out->v[i], &h->v[i], &r->v[i]); + } +} + +static uint32_t vectorl_max(const vectorl *a) { + uint32_t max = 0; + for (int i = 0; i < L; i++) { + scalar_max(&max, &a->v[i]); + } + return max; +} + +/* Bit packing */ + +static const uint8_t kMasks[8] = {0x01, 0x03, 0x07, 0x0f, + 0x1f, 0x3f, 0x7f, 0xff}; + +// FIPS 204, Algorithm 10 (`SimpleBitPack`). +static void scalar_encode(uint8_t *out, const scalar *s, int bits) { + assert(bits <= (int)sizeof(*s->c) * 8 && bits != 1); + + uint8_t out_byte = 0; + int out_byte_bits = 0; + + for (int i = 0; i < DEGREE; i++) { + uint32_t element = s->c[i]; + int element_bits_done = 0; + + while (element_bits_done < bits) { + int chunk_bits = bits - element_bits_done; + int out_bits_remaining = 8 - out_byte_bits; + if (chunk_bits >= out_bits_remaining) { + chunk_bits = out_bits_remaining; + out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits; + *out = out_byte; + out++; + out_byte_bits = 0; + out_byte = 0; + } else { + out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits; + out_byte_bits += chunk_bits; + } + + element_bits_done += chunk_bits; + element >>= chunk_bits; + } + } + + if (out_byte_bits > 0) { + *out = out_byte; + } +} + +// FIPS 204, Algorithm 11 (`BitPack`). +static void scalar_encode_signed(uint8_t *out, const scalar *s, int bits, + uint32_t max) { + assert(bits <= (int)sizeof(*s->c) * 8 && bits != 1); + + uint8_t out_byte = 0; + int out_byte_bits = 0; + + for (int i = 0; i < DEGREE; i++) { + uint32_t element = reduce_once(kPrime + max - s->c[i]); + declassify_assert(element <= 2 * max); + int element_bits_done = 0; + + while (element_bits_done < bits) { + int chunk_bits = bits - element_bits_done; + int out_bits_remaining = 8 - out_byte_bits; + if (chunk_bits >= out_bits_remaining) { + chunk_bits = out_bits_remaining; + out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits; + *out = out_byte; + out++; + out_byte_bits = 0; + out_byte = 0; + } else { + out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits; + out_byte_bits += chunk_bits; + } + + element_bits_done += chunk_bits; + element >>= chunk_bits; + } + } + + if (out_byte_bits > 0) { + *out = out_byte; + } +} + +// FIPS 204, Algorithm 12 (`SimpleBitUnpack`). +static void scalar_decode(scalar *out, const uint8_t *in, int bits) { + assert(bits <= (int)sizeof(*out->c) * 8 && bits != 1); + + uint8_t in_byte = 0; + int in_byte_bits_left = 0; + + for (int i = 0; i < DEGREE; i++) { + uint32_t element = 0; + int element_bits_done = 0; + + while (element_bits_done < bits) { + if (in_byte_bits_left == 0) { + in_byte = *in; + in++; + in_byte_bits_left = 8; + } + + int chunk_bits = bits - element_bits_done; + if (chunk_bits > in_byte_bits_left) { + chunk_bits = in_byte_bits_left; + } + + element |= (in_byte & kMasks[chunk_bits - 1]) << element_bits_done; + in_byte_bits_left -= chunk_bits; + in_byte >>= chunk_bits; + + element_bits_done += chunk_bits; + } + + out->c[i] = element; + } +} + +// FIPS 204, Algorithm 13 (`BitUnpack`). +static int scalar_decode_signed(scalar *out, const uint8_t *in, int bits, + uint32_t max) { + assert(bits <= (int)sizeof(*out->c) * 8 && bits != 1); + + uint8_t in_byte = 0; + int in_byte_bits_left = 0; + + for (int i = 0; i < DEGREE; i++) { + uint32_t element = 0; + int element_bits_done = 0; + + while (element_bits_done < bits) { + if (in_byte_bits_left == 0) { + in_byte = *in; + in++; + in_byte_bits_left = 8; + } + + int chunk_bits = bits - element_bits_done; + if (chunk_bits > in_byte_bits_left) { + chunk_bits = in_byte_bits_left; + } + + element |= (in_byte & kMasks[chunk_bits - 1]) << element_bits_done; + in_byte_bits_left -= chunk_bits; + in_byte >>= chunk_bits; + + element_bits_done += chunk_bits; + } + + // This may be only out of range in cases of invalid input, in which case it + // is okay to leak the value. This function is also called with secret + // input during signing, in |scalar_sample_mask|. However, in that case + // (and in any case when |max| is a power of two), this case is impossible. + if (constant_time_declassify_int(element > 2 * max)) { + return 0; + } + out->c[i] = reduce_once(kPrime + max - element); + } + + return 1; +} + +/* Expansion functions */ + +// FIPS 204, Algorithm 24 (`RejNTTPoly`). +// +// Rejection samples a Keccak stream to get uniformly distributed elements. This +// is used for matrix expansion and only operates on public inputs. +static void scalar_from_keccak_vartime( + scalar *out, const uint8_t derived_seed[RHO_BYTES + 2]) { + struct BORINGSSL_keccak_st keccak_ctx; + BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake128); + BORINGSSL_keccak_absorb(&keccak_ctx, derived_seed, RHO_BYTES + 2); + assert(keccak_ctx.squeeze_offset == 0); + assert(keccak_ctx.rate_bytes == 168); + static_assert(168 % 3 == 0, "block and coefficient boundaries do not align"); + + int done = 0; + while (done < DEGREE) { + uint8_t block[168]; + BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block)); + for (size_t i = 0; i < sizeof(block) && done < DEGREE; i += 3) { + // FIPS 204, Algorithm 8 (`CoeffFromThreeBytes`). + uint32_t value = (uint32_t)block[i] | ((uint32_t)block[i + 1] << 8) | + (((uint32_t)block[i + 2] & 0x7f) << 16); + if (value < kPrime) { + out->c[done++] = value; + } + } + } +} + +// FIPS 204, Algorithm 25 (`RejBoundedPoly`). +static void scalar_uniform_eta_4(scalar *out, + const uint8_t derived_seed[SIGMA_BYTES + 2]) { + static_assert(ETA == 4, "This implementation is specialized for ETA == 4"); + + struct BORINGSSL_keccak_st keccak_ctx; + BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); + BORINGSSL_keccak_absorb(&keccak_ctx, derived_seed, SIGMA_BYTES + 2); + assert(keccak_ctx.squeeze_offset == 0); + assert(keccak_ctx.rate_bytes == 136); + + int done = 0; + while (done < DEGREE) { + uint8_t block[136]; + BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block)); + for (size_t i = 0; i < sizeof(block) && done < DEGREE; ++i) { + uint32_t t0 = block[i] & 0x0F; + uint32_t t1 = block[i] >> 4; + // FIPS 204, Algorithm 9 (`CoefFromHalfByte`). Although both the input and + // output here are secret, it is OK to leak when we rejected a byte. + // Individual bytes of the SHAKE-256 stream are (indistiguishable from) + // independent of each other and the original seed, so leaking information + // about the rejected bytes does not reveal the input or output. + if (constant_time_declassify_int(t0 < 9)) { + out->c[done++] = reduce_once(kPrime + ETA - t0); + } + if (done < DEGREE && constant_time_declassify_int(t1 < 9)) { + out->c[done++] = reduce_once(kPrime + ETA - t1); + } + } + } +} + +// FIPS 204, Algorithm 28 (`ExpandMask`). +static void scalar_sample_mask( + scalar *out, const uint8_t derived_seed[RHO_PRIME_BYTES + 2]) { + uint8_t buf[640]; + BORINGSSL_keccak(buf, sizeof(buf), derived_seed, RHO_PRIME_BYTES + 2, + boringssl_shake256); + + // Note: Decoding 20 bits into (-2^19, 2^19] cannot fail. + scalar_decode_signed(out, buf, 20, 1 << 19); +} + +// FIPS 204, Algorithm 23 (`SampleInBall`). +static void scalar_sample_in_ball_vartime(scalar *out, const uint8_t *seed, + int len) { + assert(len == 32); + + struct BORINGSSL_keccak_st keccak_ctx; + BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); + BORINGSSL_keccak_absorb(&keccak_ctx, seed, len); + assert(keccak_ctx.squeeze_offset == 0); + assert(keccak_ctx.rate_bytes == 136); + + uint8_t block[136]; + BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block)); + + uint64_t signs = CRYPTO_load_u64_le(block); + int offset = 8; + // SampleInBall implements a Fisher–Yates shuffle, which unavoidably leaks + // where the zeros are by memory access pattern. Although this leak happens + // before bad signatures are rejected, this is safe. See + // https://boringssl-review.googlesource.com/c/boringssl/+/67747/comment/8d8f01ac_70af3f21/ + CONSTTIME_DECLASSIFY(block + offset, sizeof(block) - offset); + + OPENSSL_memset(out, 0, sizeof(*out)); + for (size_t i = DEGREE - TAU; i < DEGREE; i++) { + size_t byte; + for (;;) { + if (offset == 136) { + BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block)); + // See above. + CONSTTIME_DECLASSIFY(block, sizeof(block)); + offset = 0; + } + + byte = block[offset++]; + if (byte <= i) { + break; + } + } + + out->c[i] = out->c[byte]; + out->c[byte] = reduce_once(kPrime + 1 - 2 * (signs & 1)); + signs >>= 1; + } +} + +// FIPS 204, Algorithm 26 (`ExpandA`). +static void matrix_expand(matrix *out, const uint8_t rho[RHO_BYTES]) { + static_assert(K <= 0x100, "K must fit in 8 bits"); + static_assert(L <= 0x100, "L must fit in 8 bits"); + + uint8_t derived_seed[RHO_BYTES + 2]; + OPENSSL_memcpy(derived_seed, rho, RHO_BYTES); + for (int i = 0; i < K; i++) { + for (int j = 0; j < L; j++) { + derived_seed[RHO_BYTES + 1] = i; + derived_seed[RHO_BYTES] = j; + scalar_from_keccak_vartime(&out->v[i][j], derived_seed); + } + } +} + +// FIPS 204, Algorithm 27 (`ExpandS`). +static void vector_expand_short(vectorl *s1, vectork *s2, + const uint8_t sigma[SIGMA_BYTES]) { + static_assert(K <= 0x100, "K must fit in 8 bits"); + static_assert(L <= 0x100, "L must fit in 8 bits"); + static_assert(K + L <= 0x100, "K+L must fit in 8 bits"); + + uint8_t derived_seed[SIGMA_BYTES + 2]; + OPENSSL_memcpy(derived_seed, sigma, SIGMA_BYTES); + derived_seed[SIGMA_BYTES] = 0; + derived_seed[SIGMA_BYTES + 1] = 0; + for (int i = 0; i < L; i++) { + scalar_uniform_eta_4(&s1->v[i], derived_seed); + ++derived_seed[SIGMA_BYTES]; + } + for (int i = 0; i < K; i++) { + scalar_uniform_eta_4(&s2->v[i], derived_seed); + ++derived_seed[SIGMA_BYTES]; + } +} + +// FIPS 204, Algorithm 28 (`ExpandMask`). +static void vectorl_expand_mask(vectorl *out, + const uint8_t seed[RHO_PRIME_BYTES], + size_t kappa) { + assert(kappa + L <= 0x10000); + + uint8_t derived_seed[RHO_PRIME_BYTES + 2]; + OPENSSL_memcpy(derived_seed, seed, RHO_PRIME_BYTES); + for (int i = 0; i < L; i++) { + size_t index = kappa + i; + derived_seed[RHO_PRIME_BYTES] = index & 0xFF; + derived_seed[RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF; + scalar_sample_mask(&out->v[i], derived_seed); + } +} + +/* Encoding */ + +// FIPS 204, Algorithm 10 (`SimpleBitPack`). +// +// Encodes an entire vector into 32*K*|bits| bytes. Note that since 256 (DEGREE) +// is divisible by 8, the individual vector entries will always fill a whole +// number of bytes, so we do not need to worry about bit packing here. +static void vectork_encode(uint8_t *out, const vectork *a, int bits) { + for (int i = 0; i < K; i++) { + scalar_encode(out + i * bits * DEGREE / 8, &a->v[i], bits); + } +} + +// FIPS 204, Algorithm 12 (`SimpleBitUnpack`). +static void vectork_decode(vectork *out, const uint8_t *in, int bits) { + for (int i = 0; i < K; i++) { + scalar_decode(&out->v[i], in + i * bits * DEGREE / 8, bits); + } +} + +static void vectork_encode_signed(uint8_t *out, const vectork *a, int bits, + uint32_t max) { + for (int i = 0; i < K; i++) { + scalar_encode_signed(out + i * bits * DEGREE / 8, &a->v[i], bits, max); + } +} + +static int vectork_decode_signed(vectork *out, const uint8_t *in, int bits, + uint32_t max) { + for (int i = 0; i < K; i++) { + if (!scalar_decode_signed(&out->v[i], in + i * bits * DEGREE / 8, bits, + max)) { + return 0; + } + } + return 1; +} + +// FIPS 204, Algorithm 11 (`BitPack`). +// +// Encodes an entire vector into 32*L*|bits| bytes. Note that since 256 (DEGREE) +// is divisible by 8, the individual vector entries will always fill a whole +// number of bytes, so we do not need to worry about bit packing here. +static void vectorl_encode_signed(uint8_t *out, const vectorl *a, int bits, + uint32_t max) { + for (int i = 0; i < L; i++) { + scalar_encode_signed(out + i * bits * DEGREE / 8, &a->v[i], bits, max); + } +} + +static int vectorl_decode_signed(vectorl *out, const uint8_t *in, int bits, + uint32_t max) { + for (int i = 0; i < L; i++) { + if (!scalar_decode_signed(&out->v[i], in + i * bits * DEGREE / 8, bits, + max)) { + return 0; + } + } + return 1; +} + +// FIPS 204, Algorithm 22 (`w1Encode`). +// +// The output must point to an array of 128*K bytes. +static void w1_encode(uint8_t *out, const vectork *w1) { + vectork_encode(out, w1, 4); +} + +// FIPS 204, Algorithm 14 (`HintBitPack`). +static void hint_bit_pack(uint8_t *out, const vectork *h) { + OPENSSL_memset(out, 0, OMEGA + K); + int index = 0; + for (int i = 0; i < K; i++) { + for (int j = 0; j < DEGREE; j++) { + if (h->v[i].c[j]) { + out[index++] = j; + } + } + out[OMEGA + i] = index; + } +} + +// FIPS 204, Algorithm 15 (`HintBitUnpack`). +static int hint_bit_unpack(vectork *h, const uint8_t *in) { + vectork_zero(h); + int index = 0; + for (int i = 0; i < K; i++) { + int limit = in[OMEGA + i]; + if (limit < index || limit > OMEGA) { + return 0; + } + + int last = -1; + while (index < limit) { + int byte = in[index++]; + if (last >= 0 && byte <= last) { + return 0; + } + last = byte; + h->v[i].c[byte] = 1; + } + } + for (; index < OMEGA; index++) { + if (in[index] != 0) { + return 0; + } + } + return 1; +} + +struct public_key { + uint8_t rho[RHO_BYTES]; + vectork t1; + // Pre-cached value(s). + uint8_t public_key_hash[TR_BYTES]; +}; + +struct private_key { + uint8_t rho[RHO_BYTES]; + uint8_t k[K_BYTES]; + uint8_t public_key_hash[TR_BYTES]; + vectorl s1; + vectork s2; + vectork t0; +}; + +struct signature { + uint8_t c_tilde[2 * LAMBDA_BYTES]; + vectorl z; + vectork h; +}; + +// FIPS 204, Algorithm 16 (`pkEncode`). +static int dilithium_marshal_public_key(CBB *out, + const struct public_key *pub) { + if (!CBB_add_bytes(out, pub->rho, sizeof(pub->rho))) { + return 0; + } + + uint8_t *vectork_output; + if (!CBB_add_space(out, &vectork_output, 320 * K)) { + return 0; + } + vectork_encode(vectork_output, &pub->t1, 10); + + return 1; +} + +// FIPS 204, Algorithm 17 (`pkDecode`). +static int dilithium_parse_public_key(struct public_key *pub, CBS *in) { + if (!CBS_copy_bytes(in, pub->rho, sizeof(pub->rho))) { + return 0; + } + + CBS t1_bytes; + if (!CBS_get_bytes(in, &t1_bytes, 320 * K)) { + return 0; + } + vectork_decode(&pub->t1, CBS_data(&t1_bytes), 10); + + return 1; +} + +// FIPS 204, Algorithm 18 (`skEncode`). +static int dilithium_marshal_private_key(CBB *out, + const struct private_key *priv) { + if (!CBB_add_bytes(out, priv->rho, sizeof(priv->rho)) || + !CBB_add_bytes(out, priv->k, sizeof(priv->k)) || + !CBB_add_bytes(out, priv->public_key_hash, + sizeof(priv->public_key_hash))) { + return 0; + } + + uint8_t *vectorl_output; + if (!CBB_add_space(out, &vectorl_output, 128 * L)) { + return 0; + } + vectorl_encode_signed(vectorl_output, &priv->s1, 4, ETA); + + uint8_t *vectork_output; + if (!CBB_add_space(out, &vectork_output, 128 * K)) { + return 0; + } + vectork_encode_signed(vectork_output, &priv->s2, 4, ETA); + + if (!CBB_add_space(out, &vectork_output, 416 * K)) { + return 0; + } + vectork_encode_signed(vectork_output, &priv->t0, 13, 1 << 12); + + return 1; +} + +// FIPS 204, Algorithm 19 (`skDecode`). +static int dilithium_parse_private_key(struct private_key *priv, CBS *in) { + CBS s1_bytes; + CBS s2_bytes; + CBS t0_bytes; + if (!CBS_copy_bytes(in, priv->rho, sizeof(priv->rho)) || + !CBS_copy_bytes(in, priv->k, sizeof(priv->k)) || + !CBS_copy_bytes(in, priv->public_key_hash, + sizeof(priv->public_key_hash)) || + !CBS_get_bytes(in, &s1_bytes, 128 * L) || + !vectorl_decode_signed(&priv->s1, CBS_data(&s1_bytes), 4, ETA) || + !CBS_get_bytes(in, &s2_bytes, 128 * K) || + !vectork_decode_signed(&priv->s2, CBS_data(&s2_bytes), 4, ETA) || + !CBS_get_bytes(in, &t0_bytes, 416 * K) || + // Note: Decoding 13 bits into (-2^12, 2^12] cannot fail. + !vectork_decode_signed(&priv->t0, CBS_data(&t0_bytes), 13, 1 << 12)) { + return 0; + } + + return 1; +} + +// FIPS 204, Algorithm 20 (`sigEncode`). +static int dilithium_marshal_signature(CBB *out, const struct signature *sign) { + if (!CBB_add_bytes(out, sign->c_tilde, sizeof(sign->c_tilde))) { + return 0; + } + + uint8_t *vectorl_output; + if (!CBB_add_space(out, &vectorl_output, 640 * L)) { + return 0; + } + vectorl_encode_signed(vectorl_output, &sign->z, 20, 1 << 19); + + uint8_t *hint_output; + if (!CBB_add_space(out, &hint_output, OMEGA + K)) { + return 0; + } + hint_bit_pack(hint_output, &sign->h); + + return 1; +} + +// FIPS 204, Algorithm 21 (`sigDecode`). +static int dilithium_parse_signature(struct signature *sign, CBS *in) { + CBS z_bytes; + CBS hint_bytes; + if (!CBS_copy_bytes(in, sign->c_tilde, sizeof(sign->c_tilde)) || + !CBS_get_bytes(in, &z_bytes, 640 * L) || + // Note: Decoding 20 bits into (-2^19, 2^19] cannot fail. + !vectorl_decode_signed(&sign->z, CBS_data(&z_bytes), 20, 1 << 19) || + !CBS_get_bytes(in, &hint_bytes, OMEGA + K) || + !hint_bit_unpack(&sign->h, CBS_data(&hint_bytes))) { + return 0; + }; + + return 1; +} + +static struct private_key *private_key_from_external( + const struct DILITHIUM_private_key *external) { + static_assert( + sizeof(struct DILITHIUM_private_key) == sizeof(struct private_key), + "Kyber private key size incorrect"); + static_assert( + alignof(struct DILITHIUM_private_key) == alignof(struct private_key), + "Kyber private key align incorrect"); + return (struct private_key *)external; +} + +static struct public_key *public_key_from_external( + const struct DILITHIUM_public_key *external) { + static_assert( + sizeof(struct DILITHIUM_public_key) == sizeof(struct public_key), + "Dilithium public key size incorrect"); + static_assert( + alignof(struct DILITHIUM_public_key) == alignof(struct public_key), + "Dilithium public key align incorrect"); + return (struct public_key *)external; +} + +/* API */ + +// Calls |DILITHIUM_generate_key_external_entropy| with random bytes from +// |RAND_bytes|. Returns 1 on success and 0 on failure. +int DILITHIUM_generate_key( + uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES], + struct DILITHIUM_private_key *out_private_key) { + uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY]; + RAND_bytes(entropy, sizeof(entropy)); + return DILITHIUM_generate_key_external_entropy(out_encoded_public_key, + out_private_key, entropy); +} + +// FIPS 204, Algorithm 1 (`ML-DSA.KeyGen`). Returns 1 on success and 0 on +// failure. +int DILITHIUM_generate_key_external_entropy( + uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES], + struct DILITHIUM_private_key *out_private_key, + const uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY]) { + int ret = 0; + + // Intermediate values, allocated on the heap to allow use when there is a + // limited amount of stack. + struct values_st { + struct public_key pub; + matrix a_ntt; + vectorl s1_ntt; + vectork t; + }; + struct values_st *values = OPENSSL_malloc(sizeof(*values)); + if (values == NULL) { + goto err; + } + + struct private_key *priv = private_key_from_external(out_private_key); + + uint8_t expanded_seed[RHO_BYTES + SIGMA_BYTES + K_BYTES]; + BORINGSSL_keccak(expanded_seed, sizeof(expanded_seed), entropy, + DILITHIUM_GENERATE_KEY_ENTROPY, boringssl_shake256); + const uint8_t *const rho = expanded_seed; + const uint8_t *const sigma = expanded_seed + RHO_BYTES; + const uint8_t *const k = expanded_seed + RHO_BYTES + SIGMA_BYTES; + // rho is public. + CONSTTIME_DECLASSIFY(rho, RHO_BYTES); + OPENSSL_memcpy(values->pub.rho, rho, sizeof(values->pub.rho)); + OPENSSL_memcpy(priv->rho, rho, sizeof(priv->rho)); + OPENSSL_memcpy(priv->k, k, sizeof(priv->k)); + + matrix_expand(&values->a_ntt, rho); + vector_expand_short(&priv->s1, &priv->s2, sigma); + + OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt)); + vectorl_ntt(&values->s1_ntt); + + matrix_mult(&values->t, &values->a_ntt, &values->s1_ntt); + vectork_inverse_ntt(&values->t); + vectork_add(&values->t, &values->t, &priv->s2); + + vectork_power2_round(&values->pub.t1, &priv->t0, &values->t); + // t1 is public. + CONSTTIME_DECLASSIFY(&values->pub.t1, sizeof(values->pub.t1)); + + CBB cbb; + CBB_init_fixed(&cbb, out_encoded_public_key, DILITHIUM_PUBLIC_KEY_BYTES); + if (!dilithium_marshal_public_key(&cbb, &values->pub)) { + goto err; + } + + BORINGSSL_keccak(priv->public_key_hash, sizeof(priv->public_key_hash), + out_encoded_public_key, DILITHIUM_PUBLIC_KEY_BYTES, + boringssl_shake256); + + ret = 1; +err: + OPENSSL_free(values); + return ret; +} + +// FIPS 204, Algorithm 2 (`ML-DSA.Sign`). Returns 1 on success and 0 on failure. +static int dilithium_sign_with_randomizer( + uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], + const struct DILITHIUM_private_key *private_key, const uint8_t *msg, + size_t msg_len, + const uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES]) { + int ret = 0; + + const struct private_key *priv = private_key_from_external(private_key); + + uint8_t mu[MU_BYTES]; + struct BORINGSSL_keccak_st keccak_ctx; + BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); + BORINGSSL_keccak_absorb(&keccak_ctx, priv->public_key_hash, + sizeof(priv->public_key_hash)); + BORINGSSL_keccak_absorb(&keccak_ctx, msg, msg_len); + BORINGSSL_keccak_squeeze(&keccak_ctx, mu, MU_BYTES); + + uint8_t rho_prime[RHO_PRIME_BYTES]; + BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); + BORINGSSL_keccak_absorb(&keccak_ctx, priv->k, sizeof(priv->k)); + BORINGSSL_keccak_absorb(&keccak_ctx, randomizer, + DILITHIUM_SIGNATURE_RANDOMIZER_BYTES); + BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES); + BORINGSSL_keccak_squeeze(&keccak_ctx, rho_prime, RHO_PRIME_BYTES); + + // Intermediate values, allocated on the heap to allow use when there is a + // limited amount of stack. + struct values_st { + struct signature sign; + vectorl s1_ntt; + vectork s2_ntt; + vectork t0_ntt; + matrix a_ntt; + vectorl y; + vectorl y_ntt; + vectork w; + vectork w1; + vectorl cs1; + vectork cs2; + vectork r0; + vectork ct0; + }; + struct values_st *values = OPENSSL_malloc(sizeof(*values)); + if (values == NULL) { + goto err; + } + OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt)); + vectorl_ntt(&values->s1_ntt); + + OPENSSL_memcpy(&values->s2_ntt, &priv->s2, sizeof(values->s2_ntt)); + vectork_ntt(&values->s2_ntt); + + OPENSSL_memcpy(&values->t0_ntt, &priv->t0, sizeof(values->t0_ntt)); + vectork_ntt(&values->t0_ntt); + + matrix_expand(&values->a_ntt, priv->rho); + + for (size_t kappa = 0;; kappa += L) { + // TODO(bbe): y only lives long enough to compute y_ntt. + // consider using another vectorl to save memory. + vectorl_expand_mask(&values->y, rho_prime, kappa); + + OPENSSL_memcpy(&values->y_ntt, &values->y, sizeof(values->y_ntt)); + vectorl_ntt(&values->y_ntt); + + // TODO(bbe): w only lives long enough to compute y_ntt. + // consider using another vectork to save memory. + matrix_mult(&values->w, &values->a_ntt, &values->y_ntt); + vectork_inverse_ntt(&values->w); + + vectork_high_bits(&values->w1, &values->w); + uint8_t w1_encoded[128 * K]; + w1_encode(w1_encoded, &values->w1); + + BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); + BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES); + BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K); + BORINGSSL_keccak_squeeze(&keccak_ctx, values->sign.c_tilde, + 2 * LAMBDA_BYTES); + + scalar c_ntt; + scalar_sample_in_ball_vartime(&c_ntt, values->sign.c_tilde, 32); + scalar_ntt(&c_ntt); + + vectorl_mult_scalar(&values->cs1, &values->s1_ntt, &c_ntt); + vectorl_inverse_ntt(&values->cs1); + vectork_mult_scalar(&values->cs2, &values->s2_ntt, &c_ntt); + vectork_inverse_ntt(&values->cs2); + + vectorl_add(&values->sign.z, &values->y, &values->cs1); + + vectork_sub(&values->r0, &values->w, &values->cs2); + vectork_low_bits(&values->r0, &values->r0); + + // Leaking the fact that a signature was rejected is fine as the next + // attempt at a signature will be (indistinguishable from) independent of + // this one. Note, however, that we additionally leak which of the two + // branches rejected the signature. Section 5.5 of + // https://pq-crystals.org/dilithium/data/dilithium-specification-round3.pdf + // describes this leak as OK. Note we leak less than what is described by + // the paper; we do not reveal which coefficient violated the bound, and we + // hide which of the |z_max| or |r0_max| bound failed. See also + // https://boringssl-review.googlesource.com/c/boringssl/+/67747/comment/2bbab0fa_d241d35a/ + uint32_t z_max = vectorl_max(&values->sign.z); + uint32_t r0_max = vectork_max_signed(&values->r0); + if (constant_time_declassify_w( + constant_time_ge_w(z_max, kGamma1 - BETA) | + constant_time_ge_w(r0_max, kGamma2 - BETA))) { + continue; + } + + vectork_mult_scalar(&values->ct0, &values->t0_ntt, &c_ntt); + vectork_inverse_ntt(&values->ct0); + vectork_make_hint(&values->sign.h, &values->ct0, &values->cs2, &values->w); + + // See above. + uint32_t ct0_max = vectork_max(&values->ct0); + size_t h_ones = vectork_count_ones(&values->sign.h); + if (constant_time_declassify_w(constant_time_ge_w(ct0_max, kGamma2) | + constant_time_lt_w(OMEGA, h_ones))) { + continue; + } + + // Although computed with the private key, the signature is public. + CONSTTIME_DECLASSIFY(values->sign.c_tilde, sizeof(values->sign.c_tilde)); + CONSTTIME_DECLASSIFY(&values->sign.z, sizeof(values->sign.z)); + CONSTTIME_DECLASSIFY(&values->sign.h, sizeof(values->sign.h)); + + CBB cbb; + CBB_init_fixed(&cbb, out_encoded_signature, DILITHIUM_SIGNATURE_BYTES); + if (!dilithium_marshal_signature(&cbb, &values->sign)) { + goto err; + } + + BSSL_CHECK(CBB_len(&cbb) == DILITHIUM_SIGNATURE_BYTES); + ret = 1; + break; + } + +err: + OPENSSL_free(values); + return ret; +} + +// Dilithium signature in deterministic mode. Returns 1 on success and 0 on +// failure. +int DILITHIUM_sign_deterministic( + uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], + const struct DILITHIUM_private_key *private_key, const uint8_t *msg, + size_t msg_len) { + uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES]; + OPENSSL_memset(randomizer, 0, sizeof(randomizer)); + return dilithium_sign_with_randomizer(out_encoded_signature, private_key, msg, + msg_len, randomizer); +} + +// Dilithium signature in randomized mode, filling the random bytes with +// |RAND_bytes|. Returns 1 on success and 0 on failure. +int DILITHIUM_sign(uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], + const struct DILITHIUM_private_key *private_key, + const uint8_t *msg, size_t msg_len) { + uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES]; + RAND_bytes(randomizer, sizeof(randomizer)); + return dilithium_sign_with_randomizer(out_encoded_signature, private_key, msg, + msg_len, randomizer); +} + +// FIPS 204, Algorithm 3 (`ML-DSA.Verify`). +int DILITHIUM_verify(const struct DILITHIUM_public_key *public_key, + const uint8_t encoded_signature[DILITHIUM_SIGNATURE_BYTES], + const uint8_t *msg, size_t msg_len) { + int ret = 0; + + // Intermediate values, allocated on the heap to allow use when there is a + // limited amount of stack. + struct values_st { + struct signature sign; + matrix a_ntt; + vectorl z_ntt; + vectork az_ntt; + vectork t1_ntt; + vectork ct1_ntt; + vectork w_approx; + vectork w1; + }; + struct values_st *values = OPENSSL_malloc(sizeof(*values)); + if (values == NULL) { + goto err; + } + + const struct public_key *pub = public_key_from_external(public_key); + + CBS cbs; + CBS_init(&cbs, encoded_signature, DILITHIUM_SIGNATURE_BYTES); + if (!dilithium_parse_signature(&values->sign, &cbs)) { + goto err; + } + + matrix_expand(&values->a_ntt, pub->rho); + + uint8_t mu[MU_BYTES]; + struct BORINGSSL_keccak_st keccak_ctx; + BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); + BORINGSSL_keccak_absorb(&keccak_ctx, pub->public_key_hash, + sizeof(pub->public_key_hash)); + BORINGSSL_keccak_absorb(&keccak_ctx, msg, msg_len); + BORINGSSL_keccak_squeeze(&keccak_ctx, mu, MU_BYTES); + + scalar c_ntt; + scalar_sample_in_ball_vartime(&c_ntt, values->sign.c_tilde, 32); + scalar_ntt(&c_ntt); + + OPENSSL_memcpy(&values->z_ntt, &values->sign.z, sizeof(values->z_ntt)); + vectorl_ntt(&values->z_ntt); + + matrix_mult(&values->az_ntt, &values->a_ntt, &values->z_ntt); + + vectork_scale_power2_round(&values->t1_ntt, &pub->t1); + vectork_ntt(&values->t1_ntt); + + vectork_mult_scalar(&values->ct1_ntt, &values->t1_ntt, &c_ntt); + + vectork_sub(&values->w_approx, &values->az_ntt, &values->ct1_ntt); + vectork_inverse_ntt(&values->w_approx); + + vectork_use_hint_vartime(&values->w1, &values->sign.h, &values->w_approx); + uint8_t w1_encoded[128 * K]; + w1_encode(w1_encoded, &values->w1); + + uint8_t c_tilde[2 * LAMBDA_BYTES]; + BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); + BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES); + BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K); + BORINGSSL_keccak_squeeze(&keccak_ctx, c_tilde, 2 * LAMBDA_BYTES); + + uint32_t z_max = vectorl_max(&values->sign.z); + size_t h_ones = vectork_count_ones(&values->sign.h); + if (z_max < kGamma1 - BETA && h_ones <= OMEGA && + OPENSSL_memcmp(c_tilde, values->sign.c_tilde, 2 * LAMBDA_BYTES) == 0) { + ret = 1; + } + +err: + OPENSSL_free(values); + return ret; +} + +/* Serialization of keys. */ + +int DILITHIUM_marshal_public_key( + CBB *out, const struct DILITHIUM_public_key *public_key) { + return dilithium_marshal_public_key(out, + public_key_from_external(public_key)); +} + +int DILITHIUM_parse_public_key(struct DILITHIUM_public_key *public_key, + CBS *in) { + struct public_key *pub = public_key_from_external(public_key); + CBS orig_in = *in; + if (!dilithium_parse_public_key(pub, in) || CBS_len(in) != 0) { + return 0; + } + + // Compute pre-cached values. + BORINGSSL_keccak(pub->public_key_hash, sizeof(pub->public_key_hash), + CBS_data(&orig_in), CBS_len(&orig_in), boringssl_shake256); + return 1; +} + +int DILITHIUM_marshal_private_key( + CBB *out, const struct DILITHIUM_private_key *private_key) { + return dilithium_marshal_private_key(out, + private_key_from_external(private_key)); +} + +int DILITHIUM_parse_private_key(struct DILITHIUM_private_key *private_key, + CBS *in) { + struct private_key *priv = private_key_from_external(private_key); + return dilithium_parse_private_key(priv, in) && CBS_len(in) == 0; +} diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/dilithium_tests.txt b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/dilithium_tests.txt new file mode 100644 index 0000000000..2494d77f4f --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/dilithium_tests.txt @@ -0,0 +1,909 @@ +# Dilithium3 +# +# Test vectors generated with +# https://github.com/pq-crystals/dilithium/commit/918af1a6eaedcedf9fdd8aaaca6c1fccd5a7a51f +# +# Based on the NIST draft of FIPS 204, published on August 24th, 2023 +# - https://csrc.nist.gov/pubs/fips/204/ipd +# - https://github.com/pq-crystals/dilithium/tree/standard + +count = 0 +seed = 061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1 +mlen = 33 +msg = D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8 +pk = 1C0EE1111B08003F28E65E8B3BDEB037CF8F221DFCDAF5950EDB38D506D85BEFD9FDE3A496F75819F0A20D0441DC7830B4AA1CB8ECFC91BA0EEC3AFB6744E477B4E6EC3FDAE75048FFEBAABEA8E822117D5787F79070EA88287CE3CD5011FD8D93AB7E8B51F26116BF9B6D21C03F88BFEC488876F4D075A142D4E784D734407511F992069353F1DB67ACF73034A468A118588062111D320E00BCFF6DC63573FCED1E96AAEBA6452E3C7ACD19181F9B814BA19D39B4BAB5496DC055426E7EA461AF55D5B9FE97F9DF7E253203C1F9E152E96D75F9D9A84F5C263EC8C250440ADC986F4E36414C703B3E05426B28B7065950DA6D0E0B2C60AC3672DB6F3C78447DB7C20915770EA6FCE81DAB5339C1D5AF82A5D3324099DF56516A07DB7C0FC64383805C65F2B02FBCFCE63E93C4BF09409F9F0F77E73DA3B0019F2057E4CD7CFF0E5745EF18C3FD766E01747A64D415FC9789ABFA62284E11C7FF05D0548D973F679559A6A3AAD77ED5132D0150C014C3EC3A395F017E7ACFE3EABFCA44910CA06FF33542ECCE6241974742357D37F5C284BF0FE1A74B50C073551372133AF2DD41E21BAFC9C590EE6EBC4ACE731EF566156CA03755DC493C137028AF3B3DE5B00BD6CB3D9A87D0151F887C6768BC6CA02A94FB2086551A0F89BA26154E9D4506AD9FAF39F5723E234E06CFDED69D4EE4146B73E5DC1E4152A2A3159D73DBC833D3D417CD5CF7FB3DC7745CEED4DC0F5B1C6D6B69C1764157EA43DF9DBB442EFA39D1D0162E87C2D30C5012FD16D869C8A1FCBB45EDCC8E1813B2B190A961F9FC86591D3ABC5388AF678FF03DA78B7CC0F6185721C0DF33CC906435225DF2611002DF120E83566532292DEA3D8ACD109A0DFFAB3B0B43012796DB5B50683FB4C2D250DAB76AAE35A48E8C8D4A5CC154759745F0A1230F6CA9DD9C99E2F80EDC83304CE01E98F6C9489529A822F90033C228315EB2FCC8DBA382ED4301E07607A5B076C725F124994F18A997D2C5BBF9A324605265108ACBF4610FA1C3374408850A0864E2B61017EBEC1FBAB89DE3AB1B93CE4918B9E2C9E3FE456758062A9F882B283318271F4B9552FCF32624A9FDAA44C65C60E2B3648BEF1F17D0B7C74869EE0B53C4A62A24845DCEA5BCBF93B92E4C26648584E33479282E6C8B1D8FE21181BD9CF75F8A961724D4C4309779F1F1B775D254F70BD1769CC7C0EDD2A95FE5C9D84B16F7C54D85CCE4C8A182810809ED81E97D074884EEDF401CCACDAEAD82C14D06B68AEA6CE14B861B0CFD16090CBBF469C5E084314C0D8D3960EA06A3426D8B3FE762E00D09BDA374F3AE2CBEDE2838FF89D81DEB3013090E44199AED604963EAF919914CE04F207AC82CD4351FEF7B2D94393066FE4D44E3CC5952E75EB6F3714058915DE0EE184D8C55300F576A8B82A863E81AF33417BD4CFC94E7A61263B39F01F6E2E70748B6E5E59CF6CA01B0028C93BBBCEBC548F987F10755BF33CA585CB41CF578DF5FFE37924E3C2C072ED1DAC9162176972971E79B62FB208F1A73BF0361E2993DCCCD3110C34D839D18DD43A5E8F0D941E99ADCF441405F32107671B2D8B2244F7BA92DCED587A210FE8FF43C616ACB5E766E6AF2CEB03599BA3DE376EB5735EF16143953D1FDDB7E9F2874B0D6083DD7EC4386AE003F51CCF2D21EF6059163C5152174423F57119D0FCE627D763D81C10AA1329F74C8D445437BA6718A33DB6E79375172B2AE3591821978D520824E2D2FF898B7F4C867FF462722BC07EADAD389A910B6F65429DA129735FE049E3ECB3889F6047CF2BD2A88D50A651B3235D2480E1DA5A35247FA76C831736399D37E8D033C1D051C9B6A99AB80B1313FA24C5C59766E6C51A38FE9F1186A767EEBD0D88001AE0246CD4EBE2C979DE82C30BBDB98B4744F11F9E639EDDD8C194D7911201A8FA745991B4D8A5709B62A21B63B9762913D36CE995C2D6B79151E8D83838CD1F38840A9417255DD166B7A3584499003FB625611404C95B960DF0DB1BCF1574B0965DBD834EE148117D5E05A7CC7CC1A865618A2BE4854DB8935CDA1E68BD8D09E72F0AC9053C882C4ABA4004A614D10505300B6176CA1F324E22E7824299F9C40755B71D82B679547F06AD48BE66D68072C9390233C933F80A14F8D4A6B0B4E1970E1ACC1BEA7F5D3BE224448F857BAB68AEFA6D8CB819B64294A12997916CDBF56E9A8D002DD065F12C61823F4FC214508232E431F0B6898475BB5DD0D7D528E840C22809AF7E15363724A613ACCFBE2B37438C159CE14CB0C98BFD499C08DAC0CF45D821CC2FA47319B6FB4CED7E5985EC8274DE09071D3C10DA5BF9E522B01CE91D66B91795D3D22C00483454275DD2BBDD7C2DCC4A167E5D7FCDBB9F6208CD4C9A485FAAEB809A7711DAC2865CED4306474B22B4448F85DF33417F3FACE1C05D42703ED313042A05DE0362740130188ECB445BB255DC76EE8443F733117F8351F17603175554FEB00B7FF54D80786F305CDE18CD5EC56EC0962A3E04482DCE3622D040D24C40F2E8A14A447659D6C561F2FFEE68F8D3DE511B23E8B172A01A3EDA4D3780E74C677244330E9AEFF019FE07BE3D33F322F9CE2214B9D9CFF99D05A59E47551432AE76F4CD4F8DD51520FFE811B4B93CD6219C81B63B1D627785C2A0FC22E3AEA86CEEE1F7FBC4EFCB46DDFBCD88A02F3B4E67C5FF2E8DC68BF16C74699BBB628902F72C3DEBC8BF5DF706D47A605A107DAA0014139CE40F0D46D8D6DC7 +sk = 1C0EE1111B08003F28E65E8B3BDEB037CF8F221DFCDAF5950EDB38D506D85BEF394D1695059DFF40AE256C5D5EDABFB69F5F40F37A588F50532CA408A8168AB1E64F146427543D8C36B3B65226769A22911A5A313EAC17C4ABA25284514FC6131F20FE945B7F3690C56BD99E99376378FAE71A374A7158EDB50F116DC284686535780833022316433765807578714524810173154483652641333022302614737052210781265061858507754618580548533018706647518267737733500270312878821580714026734320616250617371010311453681523024650348143708371825508406086017625831312827001718481667317861073723557447151010112110662742120835462285131388164886833510476026118315742500742440642515861365613777118478050862437064068527631150135623216841417724084830878575438508636854268450568437024007161784543800612705826206765211121483880678147555021222855231084503701364318005376837650246531507600625331251200541606324235241507731457033476564312318033365167587141304111715546812605373423882432783371222817481812013632764751028032268650876553563338104474858543012431808386438538308412704646463346461068070602375516825741152882201577858333134315582840316360106481480464368461757213631657465221517713205106646831646714728313555147332818260731554368708032843262416053205202367725828181085426785155280007282271831120868377244420548647205350861738627124677510852763340373432115424065402345080041772846273616868078152467106825545816362764180571244255708045106636115858630465207053275021822428371023852752844203300172311140215768838476231851352521084382555567411445467278546586170430758800684551353478138120800843156221466031560016368563673618080045554337312584031148042036733018271556065603440514434554851122376451064337325382338062451617081541167173200853260404371068037376070864087000352457148262203505356660372180137103710365278432824642320476423840000674364565226217665212413887347650843121701647146540387244177741376785521641117316050482604148474663803351558017351262133622227106345601657207785483272483156167834564057686734583525352081556548103205334016607423715016325334667270811118243732131154424082613775046710080261386850712837526672242308021005015520483744377116420123167107823808071011246825824018158518742085382583106675131252852765256031478162138153470422610571556744682005455051484113038302414747156272021653210303873603486751766527214217262576653612111216874845403342683544406813605031081743567506346184755758586544840762318670343367586667732075171036052737241220173887544032263062135418368155773200100365185741860214443341023755635875026188641851762415850711803541515742425854563545155707638677240017678386862588177508612360606507333506605275024724336451354552554148604216431563331655676070342677080760553063501337707701374572745128728364747780273036442310552415431163146533631211846312638837626748351386351783125814478856084801427164775364735466055660523700464031105550453648423406611175526158521573573156158778744503872054561166220446141461830006866406004737442250560104577350748702663748684802632852635811304428683261106188260700733862552715534532142573231221878655672567467472814454641577410780605613161540446347533077616250133841474266705206708125431777701522218250013173169DB8086B122701706AE49B99305EE6D016F16F9FACC1F835298B41E21664206005CEB981A35F18651CDB90E68C1F950B059F73D6D3143A1F47AA21D80A05FAF5D3A40F67148D3A89A9FDA80364D57C7B8F68058A25D08498D9A9C378C98185DB13259159CAC4769C34A08023A3388C3505406FB21C69EEC12DAC95A3C9BA61185237F0FF1E0E05F1A6F5A0C09090100665A1AD3AFB1076847B232EEEA78409BD9055DB57C1B31E28A01D09999035BDFC657A61040103ECEBDC793409733734D9342CC5A069E070C2421DDE11C49E172DBE7FEAF9DEDDFB3DA5DAA6B3DD13200B09042E144EEA951B43DA48153C1F1D5C07FCF473FA7F321E72534577C895151B46E48331DDE61DA45F8609AC59581814666E1658B49114524BA3840C6BC5596551AEF42412C8AACCDD8EF69E46380E6DEF60FD91228B99CB511D68EF6631748A0548083A215445EC54693471A831042CF41D09AF898119B0FC646E484539C8C32D5DC24F9439D33EEEA033A4081550FDB0B08923DBA5D44A1A876FE7EE4320BF02F9BE26F418F309FA11FCD0C864A7AA34115083C1EA775345AC0548C877C685EA8C91B924AF4F607EF37A0208E21309AB6D0F2F8A4EAA0451FF4A47E6F482958D81A166A6A08A6A10FC8F9ADA42B64A12B9357D598A3664E9DF13755C10FFD7177E594DFCBCFB5D11B6ADB1607445479A5DB1AD8CA6D915F89795D240CBEDFAD2539D10518E53CC450D6FC5385AD6D76B7830F13828120645E3A0A5DCDEAF15F1968E64B3B1CEAF536CAA2953D161C75528C3FA8493E0C177AE807CED37648A82C9BE8BA970296D543F6FBD6724A99A68D2F68C1FD333F9DEF8526DB7836455B313E6BC366178C9C57721601EC0335054F067B78E663A058DBDA1C12D80A392F89C0AD9E2A3B2EA17E9C9A3B14D176822EEAC5FB5FF7D4C87D76080D2D42D9AA4C951F4CAF11A244EDA711D120A2EA321D1551D86CA9265E9CD5FA9591D880E403B6844F051DC04879972C863B97C72B409C19D5EBEE8AB58C6E7B3938A68A9CAD75D80C6FFC4F22254FF4420C606AD120CC20346A7E7324E78C862E0DEE161A64F44917DB0C38C1F79C969220D202F8802D0F9D7ABFB2DE434B1C53DABB57575EEBBBF31CFB2924872FA01473B3976AEADC99699B13820FA0868F2C9FD0D352E2593273CD621B1974FFA6187FA05C4118D4517C934151C1FA34BEC3ED3639598CBA24E28229CE9FD3B1DB4969C12EE49E18B36CE2B9145AAC75428DFFA145302F41D9E3394F38D3F3C0334C4774F1E94296DE36DC6E430E4C0A537E68BDD41AF0421193B16AB1891FA836CBC367B403705ABA5D2F9F2A4C2F275EC010B2EAB84095A569DBAE4457CC2AC1CFEB1EDA43C3E2819273C487ACBEBFA0A0ED1CC4667A6F577F62DFB1BC8FEAFD86D90108E16B8B0E6C2678686C928A668BB9857FFB28DE90545CD4437DD32CCCCC6ED58FB46FBF85E0AEC0C814E536245252B8029F0A2AB44B9027A7E35A941FA113C8D82974EA22DF02D84E5328CEA83D12D399C7F0259055F4B3AD707E7B3E537B93DEA1A066BDC775FC7D1A6F0FE29DDAFA9A7DA630A467EF6CBF5CCDFFD79F1C8BB6BB3882035C73CDF7ECFFB53C712A7C7EAA59765EFA960BF21E25A6703FB304F07739FEBC63F496B13CCAA077338A0B9A976A9F0FC5742D85C4AF401A4CE341B47BE2594FF7E3019A0E064535F9D9395CC74A6A6F00E0C4E3530A7FE9310CE30B6922D04FDE0AA749CC3FDEDB4D8708C1F6968BBEDDDD5833B299D79D61428180099B0A946A5D79085DF7F872CBDD219E6B8EF8B8AB5C1A149E6E15EF2828654FABEC249AFAAC4DC0B3B542334162FB09800B6C36CC90F2A106558BAE2198FA7D1E2D730DE46E355AEA93248E53AB21B518EC99D5F3B021196A0F614A46B9475621234733A28A465CC5A7FD432C3625812AABBB42D2D9CBEF16CBED9367202B02894D06BB801BDA8472B9918B7D724E36557DBE6B7633A5FD22D0E336E5557AFC018C812E9E6A35BFD8C60AB382E14FF51142B2D2C75A767F32413BA38487558F9345CBE6FD1D6B78C2E622F3B976230F99D6CBAF0BBD14949510A52644EF3F3078865037A1C10F47B59546699E1BD539C7DDCC03F71A0158EA9F0178E187BB6D49440DF2B10630FBE2FEB5097E47F285711CA6F835A10D3AA75C03C4184C03EF3075D49DCB2177ABD53AD7399D290EA691D647329056340E8C836E9750FD881DCE309D309A95B82492D4BDC15ECF8C7F5D3B9DD275548512DB5EF80CD409ED32B5148B82BF240A7DC72A18523D808B7A4F9E254799E17278FA88DAEBC944632E83F8609D681AB463513023D67CD51B153F0962912DD64AB8F6529DC22AA89E572A7F89CB97A8F4509319D223BB29974951716FD3177140A31EA20048BAF0FCA230CEF21967ABD83309A4FF7E35E88784DCA77AC079020EC0CA6DDEFBCBB7E317329314665D7C51F631F681B600364E47574F252BAD6396B3F5B17ADC220966A93CE8F315A2F83068D2EA06952E6EBD802473A2264EFA405B3E491BE776C50406E1150C56B894CF864546B0C7A65E3F1A2BEFEF2A9990BAFE70B6CA9F91A8F3DD21307A39A2AFBDFBDE9B7CA3D7828B13F49DECD729C0039E94EBB7B4BDA09B3505529A12CB1E2FD79B9E5087CD7C3BC05F7CFFBBA932A7BFF8E67555FEE0304D890313F86E1892569E2D6F14A89938717AAA3A32AD1167150299C21820ABD70FF902B004C6DE91C1C0B40706442AF531EC490B012750BCB4877935A7E54031702BB988EB3F92914CDBD42979AD7D27B2233EC1279D05493B12D3F5FBB7757536021B5F4CD932B480E40CBAE50D232E0A2EFFE0E8CB58808669199F0830872F369738682F846F6DEAD095BFFCD670A4A9CD142396C58506EA7A68B21ABDCC19CCC06F6DA55C885A855C456680CD4477BCA2BBA9153DCAEE682655B74ECA6F7E44C3BFE1E2D457491ED1BC64E1CF6CE18CF44A0166D1B244480882C1B35CEA703158E18C7EC6E0CF827D5504A45AE61152309BC8A18A52C0E7699A87C4E31C6911A8305351555B2971C94602B70E670AA30B90734EC1DAAD03A30A96F5847C5C3F7973CF4572D166C51D1E94A50A4C1C894A205F8ECB34E80F84CA8DC31A429D5600596179D1093E2A389CCFE9C0402EE49551710FFC25BDBE478F39F2063F31F75D7432ECA1C59EBD8F46D86A092DB12F810FA911C20D4CC1E425C543DC64577E44D84F422D9661E3D35921350D6F7099C5425E509E1458A0500AE5EB4CC6BB50626D0130F09361717A95919AED35592FA4ABE7B2BD4F999422151E63D4ED00CC751A5867977F15E482EFA01E5CCC44064F5B9FFE29AFFE626C4D5170ADA1DF027AB4179608C4093CCE2C409308CD898371A49FBEA2A2F2BA13BDEBAC1F4159F4B0368FB21D70A9D7931D7EFF934E6C544E13B7B73D465576C6E81FD6D5FD94393E80242F9420ACC0ED353EF18CA070F5E9A285AC4BCBAB19A38356F557B070E17AE5CF1F1BED42601E89C8C4C +smlen = 3342 +sm = 81FF8025E2D7DFC0F8D47C16041E54A2E124898A711A500D2A743986782155E9034BD177AD226896DC29A8E201785D7633A9617C0612773F455F556B9A0D5A5F50CC090D4D36FB5D79B09DE4459FF9C76DBFA2F9B0B68676CFE2906789BA89F584B3A6D00D6ABE266A20B4EB1568D85E6F511E469162F3D602435795C0F9249F712DC5FD1D8F5AAC3B767447FF8875E7FE699A6C398130587846F694741DD1DA76D78EB22BA9CFAB920F700C603224067C8B2FA619D6787AA7FAF6D715E34968D923D7965F7F5E6244965F27E5DF0114CCF90E26700B9EE54769D9D713FDA7B753A8A5A0CEC9C7D41EB6967DAF74A0A286079B8AF6093C712D0E605E3856E8E690A1B90D9D17BB091E44C018A7BD6AB6EE8FA0DCC220DB244001AB640325084677B67325A2B0C83D0CD118D454E45A105FBC7C8BE060FD0FA8244C846042092183364447C83381E3E1DB0582B14FC388098E472AEC5DF99B74487D4837EFBF8BFB08EAD95EC732F5EA1B347BBD79805B3CE88FD1686F6202DDBE0386D9E72AF31BDEF979FE7C3672A3E4395C72E0E2F9500883ED0669C407DFF2AAB19D6D44FA1728B63B1C2E4755AFBCBFD8290777C7619772669F0591D5045418D558C1D8A460FE26A9944A7B8CAED1E1D299D35D57166E8F27A1EC7462FEAE5A551EBE853D9A9B85670F3C07D31714C92246A61E3C3B54D7FE758640A3D88E532449EEDBFB7C71CC102EDD043226BACCFCEF21147DD6204BBDDCC1110C16F8FC6CF62E424224E0E40212A932E8329199240A4F382A54B4FCEE4A899FE12B188091D61F4598E2649DFF1A091556D116C098B9ABCB0C20DB9516CD643ADB131842D9B37D4D7B17E5F7813623F5C43D668E78B4EE22CC96914DB45A27877F26D68395AAE2EDBF0A1EF0C48520D05E0DDA411578C7D4B8957AC48C58621BD5CCE25A718B5ABEAA6739768F44C73836BCA0AFD86491E15C49F40CAFE24B5FACB52B948B7C93A7C081C21961924D3D696FE23B1BBB63F4525F037B3648AAD3E04D8778EF4333573AED76AC0A607F783E8C228ECF85E093DF7A8E16C8955C4622C9DFAB726821908849CD117C30617404E4571CCA3C16291160E8A56CF8279F53CA31B03DFD87863E765D262589652EE032E020DA9D92102878534C64E882F76F98569FE77357DFEF2FD6C37E4FE9BA64F0CA92B5B40D318A994EEA264209C08B81BB42447E8295930160330101F0BF4FC4B77BEB74281C7761A8FC4A82582688ED3C8FD4B8464F87FBA1BA59BF77B2CC51D261591307924E3CA46EF4058458930A5B1486C9C4FFB4D90172250CC1D6C0ADC64EA7C494EE44E5E4749ECBB0A7E5F18C4CE82058DC7DD34DE5B05CA9812AB75FEF610D572E859213109050EEE46E7569531223CA029A42BA840C51423F419DF37A3822A9F77A3B2012B851FF539F1D370029461980A7373CF9B61FD954E98A338456EA3F14D5C501CE0593D268C98EACEFEA2BC591D466E23FCAF2381BDB656670B91D06F5E7853F0E7FC239D54FC3CA9A448E2868C61BA1410CA9C65DC53C30FD00534EB591DE952D940514EE0E7E20C795F86FE571786A40EB6F4CC2ACED893B30839F05DA96744B776670F91637CC6CE7451E0AA19021453EF1294585CB7A6E44AB9C313983DDBD4D6FA54DBA87FE5A5F5DEEED7CE9E52CC402FF6C2C1C41DDF9B245BC5CB1122FE0343CADB0B40D4BC8A558199B892A08F7D07F7735BC10C45A547DB0DA4904F415C5D832AB1EB3762126675C8A69240436D98FF96D9067DAAB72816287D167FAF475B43BCAFF5EF584B5E2579B101E388C6E40603AD4F3B5A8D15B4D3BBE4862BDE60AB825B80D2ED437176C8A86F050BAAD75687D7B83E8F3FBA6404DCBFB84521A67681AF0AE5297A9C6DCE2B409C3CC179068A06BD088D0B47592C3447EE980E35D7AD8CEF4352096D1168119D275CE9B289AD0B5512FFCDB9B521BD07A0F6F35C274BDE925F3A970EC6C320FEB2D6A5A8128C62848AC16D2971C136A3B7ED2FB324AFFAA200C29FECE5E388E989C3240EA39189D91B8CA6DAFCDEFC5D152A6A7BB2D67FCD3C1014218E9A9E8107D7BCD5F026B5DA99238F33C914918377EAB40C776047276156F83609A1D9D872757F0B35DB5044174C6C2567EB5EA9AFBEF6C051FFED8894445843205CEDFDEA788F429789FF87AFE5CA85C6E4F5B6E0D262B700C494195D7741C6702029483C8B0ACCB9B8014CC76DCB33245B45BB496B05A1641D8FEAD0ABCD53F9D551A716364E24B36E2F001521F76965BE160EB420C7FABAF97EDE20C4A2747CEF0D7639896AF7C5ED115816BD0B69E6B7D67A2E17CBC7314F1C673AE1C6197B8A3BE07B528EC053B8402104A34CF665BF7F2B3CAB84C6303538273880A8F6CEEC959C251C576A10A30A1081421D5EE0D4B2AE501B814A77A6137AF16B5DCE81039AEF9DA6E6BFBB79522427A0EDD2F1E8E2AAC8D28F9DDA4BE6E91D1649A9305D560EFED5C0A29B6452FB47EAA41CB50859CAC2B6BC4158D2D1AA9136CECE1FB380EAF63A8F1ED37AA34C5B7628B9BF972213A79020AFA21E81FF0FBFC9705502E5BBC6AD63DA058365B46E3D8F8B3A8E5D80BD8FA7EB92C9113DEEE6F76DE250360C2752A93886957AC33657F646A5734D961D82FAE897F1889E843F8CB897EDE7B68156FF6011228B006BE5A670B8913C21500734FD6D799B691B41E02DCAD4D3498F1FB5D2CA960E295FBB764808D296BB1C1C6C16E0BB61829ED7C7D56EC7F530653A86E3F4AACBEB6296D8456B0A80B430325B2CB142EB34BF6AE4FC9B619760C6386ED045C57455A2425F76EF25E76F0563AD2CE3B858B5087C9AC27AB2700C87E8839B3EA9653C147BE9C859A38F2A5BD23C689895CFFCC1F8EBA87CF79751A990F6C69A65674339F21492228A8A67F80188D97BE3A5F526068025A98A3B6831EEFBE2A5E43A6AE0150C0C88B2A3C05923D82BFDEFE4BC9D70A317F364E2C6108EE1047EF2C845F84EF3D5909B7A07EB8714A984ED41EAE3AEBAF52CEEE9C5A0FD19EDF819376D859F9F00894E6DD425BF126DD6205E528D7E91B75A1AFA0059E5C480225C1BE725494BF3BB136897501089038E9E9CB68B0BDA2EBA88EE58187C8E12D8DF598C0DF6C5084A8000E31AC98DFDB258C7E93A338BF6DE0B9F060DBA0AE14577DC6902A6F104DCDAA4BAE9E558F02F93797F38948C24B07C830747C3376FDDE0089847709298F609EB30DAB744F801B60AAFCB4DDEE347972ABB7DF496B1B4080B1BAD521E1A8658EB3FB4BA29EEAA9FDA969B3A2555286CC6ECA1616A2364A5D6CE810FAB0C829447E785FF3E7BFD41CC8E37D52D9217C10701C7B02C584C262BC5F3B6382066D89F4D1B95DF5255381F7A4CBDA53F75CA6701D4823CCE072ACFFEC65E56D8A2111C0FADF73972914B8658B9EB91F61BF391F17E7CF1107894861264F75398B4E9192CADD9003FAF5EA22BE0525CE89383BF4A7E85C8CD7706B092CB1251000C527A25C1425B7C5C84FDF6EB162540D5709D3E647562FE9387A169A21FC6D6D58A88297D7588E617F0D85EFC4A476BEC19E0A64588190230C36B93A517BECE6E8256A3C8CF494C281F2318C4FD046876399013EFD98D6023F4257EAB14B2A62EBB74733DAC5D41809BD97989D755D6A410B5805508F172F7C1B933D2DA5617E5B03EC189E41B512DAC7DDB49F90E1873F3F5FFBB7888E9B1A0C2EA73DBC063C72BC08D1211063C71FEC37CC1B28E05AA41A3EC4BACA7750FB55314C5B12AE161AB0413D58281C8F82B77158B17FA9A08EB0ABF4BBB869B06529C321150388DAAC8BA1C2EF640944DE22BC4E47D99C3E746605E7EF79D8621E155592CEE4E21A4A02FC80983106C84872C0CF6EAB309F28540F68EE9BFF5659446BDD6BA368D40C50855F7140FCF6D6ABEF14F8A1DB771E9FE513680670B2C5B19968D8F2F60B81750E7CD04AA4C2783AE8B1B4C2DE7DF7C3B4B4D071F91575DEEAFDA32D9CE54FCA612B98AA71F235530EB5893948A55BF7A4F1016D29DDEC21DDBBD62E1920075A23C91FC7BB7B935D883435B51608982C4ACF4CA24D76BD0C514DD4012A9CBF67AACD87B72DA97A78FD598614A9A49DFA8A5FCC45DFB5990116D05F6898544E87A209C5D51A62BD206770721737995246BFFB8A25EA0630C62C0039A858BF6A0862F33154703CFF3C404C5EC5EABAF86E917EEF82F18848CC382E8082EDB3A878AF584EE1D9C70C051DA1F3D48912DA4FAEB8078E1DF45FF3C24C85ACC5AFD12526B6A82C943EF3F0CDC60EA7BC7602130C747B11B28B47C8A22FFCA4F8161096F42360C93140D867113BB0B380288D20C6CAA9FA06C861E0AD9AE81A183466034EE3F148E337E3B441104F6B22FDF2C2F8A4B065AA00A389CA4ABAF4A0AD148E16A8FBEC244B2AB0FCDA9C06679FC9FFCA3F600F362613BAC8E2B64AB9939A841093F19F3B803A61183C5A0DD4D106CFA0EB19927321601010FE1C66461C7AEF33CB823FCD2690F0DE9D9BBCB657BA398222C30C14850D6CDF14303D8480A3B5A9F38AC7F8030BA314226D4DE58C66CFE33D0DC66004AF4D96AC0CD6AE0B6ED7142657616A6D87B5C8F5191C2C364849C9F408324195EA1D50AAD714334A596B773B4C8D8EAFF7FC0000000000000000000000000000000A12171B2128D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55B22E75BF57BB556AC8 + +count = 1 +seed = 64335BF29E5DE62842C941766BA129B0643B5E7121CA26CFC190EC7DC3543830557FDD5C03CF123A456D48EFEA43C868 +mlen = 66 +msg = 225D5CE2CEAC61930A07503FB59F7C2F936A3E075481DA3CA299A80F8C5DF9223A073E7B90E02EBF98CA2227EBA38C1AB2568209E46DBA961869C6F83983B17DCD49 +pk = B541C1E92CEADD904A09EC08AD306D974734A077868471E58D077187C46604CFA72C150FCCC9D165CC641264AD38CB419BFA5E48B19EFBA646A1859BB40063A5212ED8FB5A60270793BE84C6D865A8671276E08EE771D74A35CCDE95C61D6B1929210EAE6EA103CE2A041EAE6AA0BAED9F736C54238DA9FB05736C0A792D310641A0CF46C502DA44981C7C85DA6BC44A39D60FCC79AAE52B7943BC34915807A96113409AF84C956CBF7E8F1E44CF8E37514A1CC77801A2070A3BBEC6A67FD5BFB66768167644E57C03690C12A4A18BBDEA35FB3A2D619A55BE10CB9B79A84B10D8E6D38556465B5A10576966F1D4CC4A1F4E362AD584363FDAF0AD0BF179290D57C3D8D27401B0F214183A7C369A0653F51057E76F6E8B68342D592E2BA1A1DB4440980C1D616E8BF5F15A18C31EDDACC29AC580438E5A64526889191F0199E19884C4A6DAE8921010AE79C0A419BC3B0E622EE0ADC0FEF4FD43B7BD4B800DE300A3D7D2DD26F334FE9C5B14F8BCA4099E6F9DAE55B8F6C4B117459EE6D7EEEFB1039569297C147BF012C50CFABC34134839EF5457BFFB883F3C01C75BA94A47E2DCAE22C5B7F39C16A21A9D27F6888430CC2550F86DA804AA1E29F1550AD88FC499E2070DCBD9ABFA39104D7665A9B8C58BE98B4183C7F1A66E557C609183E5F202090516AABF8D3107E2499B29D3593DE2BA9D16B539D0C151F7F0E196FDF57AE6F3B4E58AE9B9A03AEC96700BE5BF524EA448ECAE16825C29A9E16E38C37924EB7ED5E833872E0D099C96154CBC53F0F19C50B670DDE7C972233574C65AA000673299365B437056CBDE78F688786EB9DD753254A23015A5E54BE04FB7A608B6E689BB4F2C72F09937879EA79B0E0EC00AB8D66CC787E4D967591D6BE1EB9844112A527E9D1FA5EE7F9538B754FDF21996B145BAD01CD73D042D2BE370153D5ED53E5ED433323A8DB0BF83F03F8B96C42CD9C9A381208FFDA058A4A0C2F4A37E985309E8D080B7353262E06BF63F82E7AD07BF068BC093B685044C4F41F964CA1BED2F1FD854D613139B1FBDE16BAD79930AEEEE8658AE71D1B4B96595E4FCED1A2C291EC72610700CA0E3692484EA07CEE72C9B8A2E5A971293BE382D2AB0FE1F3F36541922E1030AB065D076645396D7129FE7EFBB7375390227189BEDBD3C83B1617E5A2A0B06FAEA439A1DE1CD7E9CB40AD8B297688C0CF82547D0B65C6A9D2A7FE39678B3C96BE4D0E6D01A51F6A21980B00E43167FCD366F006D9053A61A9AA1FE196BAC97A4F5D43F5A99F2B57218A19C07AFE631C055D36F8F2358D069C79CC646AE4E30414FC60A8D0EC045ED10C27441B44578584063E726A938B1B09F2209C8105CCCF9A190829FE47FED264ACFBEC78F8E8B1A8E1028B0DD2C59BFEFE247DCCD8598544213A36A5F1905C87D96AC8CC12D37ACE59697A139D353697E1EEAB1241C6DFA707621EC475113A526D9111FC9B5957AA544D61D9FB760ADE4A286DF285BBD1AE64863F704EA4644D9CB2E77D2238001E7C8961EFA1954ECE6EC59A4758B87C318819F865D7354C1D5DFCFDE5B41F4EEA930A7FE40808DE950BD881996C6A333AF6FB090DD2EF3945F9CCC0A6017A36CE48447FDD961E4B17DD02B4A3AA7B5E98A86EA973E6697CA0344CBFCB5F2D9AEE9EF6EF6F57F6272886D67112346B256BFF7A5A15B6E31075D68A9BD738B160D9D2B069B45B2C58CA70165F6009FEFE9FBE6B7D251951CF816233D0C0BE599E6A69DDDAD52D215E1BAB1F7F854453839A0070AC4282A4875F385F72C7A9DE6921BCAD9E173E13D33B6A094F0E466A0E4C9495EA07543E12D9F952096DBCDA1575BC10CCCF0AF60CD4A757AF90E4ECD083226E8318709685D3C26B6F9515B0E08FC51F0906D7330504CD4136FF62DC56AB23BB5AB4B4D713FCD4CB684036A74366BBC674652AC6EDD0B7BB2F15D70F086851B94652471527CA27F0674459A7B008B35539EC24F6516034FCF6F84CD65D2A50626E0D662BC029F5254FB20AD8C92B2BBE275BB6967F41822A9216C306C2A327E13EF14C4651D0F425BDDD307081CDB6DC7B40CF6B273FCEE1D78196CE7AF83EB85039A0017862FF3048BB65BBDCF5B4D3E253C1B3F522E3374745E35FB32208DCC5C256A5C87F4033441B76F6B4C11E284B0D53BB503641D8B4C41BE7BE217DDCCCABEBBDE2C48CE37550F8AA17F417E8F6D76580C69030FE17E5C166BC51132BBC5264C87649E2FA356D6F895785F2DFC4677A6EAF7BAE868B090D90CCF11EA2097933D5F199A9A324BF97ADEE68A0407134166B10C5E523132BB93DE89B386E4B270980C35132B677CE9D9F250802E4C779C44153A3A4FD08664102F5AE99CE9F040383500E9996554047A90DC24B22F77D199CBADD9C4A5C4F0106080DEE36FBE4A1FBE3E7168B54F88D5EFE75E0705E7F2BBD5F01CA88A3A5CAD441626348BE4F65BEDC65DA4F9218ACEBF939D48D53D5401F4609177CEF83B1DBDCF5EE26BB54762371DBACA8E4D17F9E0BE961115A71515368BDC16F5B857F7CDDEB5E78AFB586F19725BD6ECA4A776B2E7131F66199ED55A6891A6326AC93CBF2CA224B4B804C4893C977CFB75BADCCF567B49058C60F549522264DC5EF9CA9DA5300D10C55A3E0B91681C35B844EC78AC0342957161369F192FC6B6E625F1F8C059730A99D1A473D3892B955FACCF92660232B0296FA6E9CAC56CCBB2E9D9C65530145AFB1341B87375B5158893B93AE99E392BFE6940 +sk = B541C1E92CEADD904A09EC08AD306D974734A077868471E58D077187C46604CF952D2181AC1F62596F767EFCA0B55DB092EF81DB66F9FFF15F13D7AEEACD8B3A2F2CFF6F47A666F4AAE322C8ECA734328799BCD51D74939F635BEA9C376A1FD5DA5DB42CF98057807D1A33AC153A8057A5F78406BCEE000216DB9B99764CC2D605625231011865215335415203670415601416761634610686876558026100710284177051515573864328184624368254276881115632024016876320073672023172224043205201336434758830258106634435544871301582475374184311884614315587037050046473438138373378656625752081456875115688432240738021428073866008471010834067573807631077422758614647683172652411070535667067686280403785641040762628423202487017388088723624172236717782466440162778818115110154453812812811744267151657080286448358881736736104423237705082451763487227177074038553121185320801148556380127048607883504080566862301436143686742755272483727477726553071825772713105652642122572780235541078285266725485774764684368415761444046211585014402766658415526084822150448744304266766681867070102086676562226422881123661647801415104404313537022446010755328686848178608242743237167042150210846847412887564671427371836475234302403646715334316337607511164572875515878387005854181681582864035573227230313165205341676251857610601444171044332012471888858583435862088721888445024773442646130614332315431455662640811815041561463583345375765051253406557805746115712830742583887343005738846287443176581772874144206063473622661847620256808651377836885557468324386706305308882448426861787312887335302818830035174805365781777026137383623423586130038475824818478877711415150830236555314864114185173548658167414707632163805488500172387644486327245370258321344155602457870147684338804561657066401676635374813437737012303822102003036472274674757428764035501057340627837701665802210384844780415282712865312134647538235143350417705253831753502018386223116416455710632384281062386530284511274556434280235305038585681540123507553533152553217747807841412302351551060521503437235011776251083358423136348315433786435645880731255007115647134666466158050328705568074858846684036786122186620781843605375704715580675737652114240107727164323467076058158272126550247754131873783332871276811703446046286271223764400034414230334443438167532402552680445555504855705048580378640146080706328604485218003001636236400325864673523150415260468520141028768218181658326221605257604301434517447073127766473226484727785057373812234254300661258415236822433371165260483287627265687400508426848330258534571207516140028548012662140532578675612254160210787744138706372787525858363126500207402431830271438154281873455487848176801224370865504216024565150454044882373603756664111400455753207386526653380302442326443080756050803581017631884487035167506405257884310056536754030412618753466085455236158288218208420087514166611512336441742283112714566131267760683000282416205645822751574102041831826058650111342471448844244833075216744130014536642542028178837504555663444321426377542248446521886745864481684266272037027548517076722636035384115200752704825817117688416417620800284343363774407706651751117552265038228136555782275266633188435758758D0C255D51F8280DF43106EB151D444AD6E4CAB4BACC585AA37D744B245132040DC3D76ABCEA9CD4472C1CCA1F07A4992DBD4D0524A482B50957110962AEB75FE2ACD2CA384B206AE6898AEE2582218C030059CF0610DF23F62FA94CE63F505416EE56F213B1B04A3ED786EDE5A0274DFB862B764847B482B73D1A3E436744340CCA39720C7DB10163D6B952CDC3D8A19467FABB07489DE139D572C8B74AB10287BCD40205DF48AD5434EE17EA01699353638B7BE0723E6C5F276C9A57182B099ECE8E92CF0F1D1CCACAD71BC0C7CBC0EFE264331C2B46F001A3C7E3AE835A8D100F7F4D71C18BA1E665CBBA8BE559B8ED9551367E9500574EADD856E770243D07A3061EADD8797C5BA1383C1391E316FCA752A9DD2D530A859EACC0606ECD019D875ADF06D81C25CE07B304921C82224F683957247A662DDB7BAF04907CD17431937A26D62E187CBB9DF1135A0F0348FE7A925F86FCA96B2ED92E69F45AD55F945D0FE8AA7A471915B5F0FE96575CB2DEF41D50D113BA1BE2D0B5D47DE93A19786BEAB57EE1A0360FCD5E69F256B128D17D1C39163F1345AD0FCC85FD1488D787814BC6E3E93D71D246F60A50CEE9113B3A85EED84286931B6CF6698215B2962FDCB9E9568CBC384BE826558FF8DFF68A3E01B2470B7192B9492DFDE2C9FE091E8A638DD1BC8794BA3B27795B220697B05CF1D685906F14CDD9E43E1114B0A88C07438EE1E6901BE4F577C78663B0D3439FB3900959A107BCAD36110B4CD2B61BE46EF4F68000DBC64CCF40E6B6EDE6577F8EA363B5A0BEA0A81919BCFC1EC9882AC51409317EB24892334F461BDF04D4D6B1691A7D4865625C74EA7BBE26B284BC4468E395CE562F824D9029B83E76148DF2EE9625CCFBB88039411B081674196F4EBFBBF9E51D047D086EBCBA7BBDF1CF360C40319FB7B5CE6F6CE04E6ACB9A0EC0F15155ED59DC1CC468EB25F9F62C9D924CB0B0199A5276D59E44838534B62E86E5FAD68C81B2F0FC9ABE24DAC0FF265249C410D96AA8E98354A6E23884DB4B5B090A8EA5A7DBF4E68125BFDF7D2D6B320E69F8E61725BD57FF4B905C4D14FA17DDBE9F226283BC462C13EB751121DBBE6C02CBACF43140E51BF9CFD39383E247EB9760F8F4043A046F9DB540D845C15738643BCFA3B8E278B0734BBEE3EBDE281092EA3AECB56B9874E4B9D3E2ACDC804B2AECEB992EE99AB11A37C515E07F5AAE32E36708B1CC0F4E2A64DE59A94FD3DCC089BD2941961425FE965B715F19B4EBAD8D74B1B060176760D7AD73E453EBFEBC7876FFFFE6BDB77FAB20F0A2C043157A8EA4AC80F98A3C7B824C159F1236DA52CE5A10F0BC0257418614D5237FB4C653EC66597FB8BB81EC7D6A2099A9DD837C499C9927799C2B3E2D8AE18AFB3E23C7E5D24DFA5796DB5156C458293F7A0EF2FE8B99374D3349C607349E3397E2A9E17456E42FB5BF06C61B441F577CC8AB93EFD7DCD6B84DBAB85A036357847BCF539EA74A57E7DF5048424BEAC6ED11AE1CF05B8951F3AE5525B1AAF223CAC2DF80E5C747E3D9C212BB66D17D5126551A8619E3F24F57988C4C3EB781180BFA1377993CDA6D5740D0A84DCD1879346D4A9735E22AB56F01496CD4EEFE6F8E010D4B3F3503389E4A85248B30FC4759C38073B1E731A24B491E6A7C2A877350A3DBD8DDD6C0F55FC812D5B2D54D3237B213710B271B470F253E0852DDA5D84EDE1EFABAFFA6DA863D6EE113ABBA148A9018A4E5C3D8F57CA9DF005B59A0D3E47406D97E337BB201D788B8329FF5066268F4EFD510D91B094C0EE3D053F2CCB39138634B122D5375914132B31550884FE2E9A31E5127B2E03427DBCF7D2557C5B7181BDA6834BB930CD3A0E0E0EAD09120A572BEEF751863AFAB338BAC3E9A8179F2B5C90F0BBA6B75FDC2AB5F7200FEF3A65BB77643DA0D6FEB12D753DF775EA714E283E0E9962A239A04490E7D2F98193BBEBD6E2F526AB0B277E49DBC3FA520492D32417283BABF3CEEEE0BEEDBE660C043B1928ACDE602F9861A53A9EFA9A0D9D31BBE62BCEDE013332F9F33BE6A74313FD1709AA729BBEB7EE4791ABA723C25CB3B0C6487C6264291EDA8F9EFF54DA374897F9490BF7D20533BC293B9A06C430A33704706C0EF09C3695D3C0811C05CD855E51E9D74E7E3CFEEB7CDAAA893CB97321B24B5BE6333B6ABEC811E3BCC29CA0FAF93B2BBD4332D9B2E7C789CBDE03D4FCBB475FAD0535FEF2DDC1E286268419896C417F665E7A024F2CE0AB15475728F4E39CAD47FE33D91074C7B3464EB05E6A323D17D743C0E79C9E62A231EDF40E75340A239312C4B4E5BBAC6F511CF2548CF8224CCBC73A21F8EBD3A66450618D1F5B26495FF6E84FA1C89782EB211E2FB7FAD45691BF679E837F88FE5C6208AAAFAB7A42387B0A1A48CBD53B13817809445E0091BCBCEE8E9DDB413D13288F53FFE6DC039CEAE24CE5691EC636BE1052EA72CD819F5FF2F279115E07821246122EF2AEF1C3C8495CEABF2B6DC3D65C60EB2FD569145A63D9ABC5D437F7C7FC5AE22D87874A78DA40D57272F7ED93E0A1B48C8BD61A92F08A16D01442F020FBDBFFBDB18FC5BBAD8A142184EF9A328613C03D67F8BB740F6F083C393C88E808BCC9A4CF4BEA75A16C7A81F51F6D9E003EBCB8E328A86D7B73133E5966096AFC1D1BCCCB7C84F11235892DEC5CFCCDF6472249943FB39C7B8586C4A2E5E811E3FAF068A1BCA61F50B759F7042DE34D738F2D7C3DAB26A73970E50815C51AD73CFCD3530BDA1C2E912E694E9EE79C09334E4C29339F7582303B2E285C7AE84BFF01DE1D90CAADA42AA4A652C7782075B51514B10C9592D30B5A7362D9A32ACD266B62868F50738DCAB780CF83198389340F3E7A8639FE94AE0F4567291701EE6204587E295319A0056B304C7901197192A8A6F4A3EA8CA3941861E7601F3A89FE6F9D8C49F9BB3D95C1A0233575983CD7D88F9D315CAA9F3954B63C6DF2920E16F0076B7298352EEF1A7E1341A372D076233D010AD4DE4C2845A6EBB643745DB2DE2A02F241D52F16AAA87F75C3395C40AD3B71D31239AD3187AFFE18F0370AE0831093D9990671E5C2AD4D99A49C0783907D1E1B8BF61523FD6FC25C1A5CB0F1F663168FEA17EA6B71E0E761830AD7B49FF1E71E6DC49DDC865E62DF12CE5F138416BE79440C7213FC2E49B50E60A53D50DBEAD4AD3679B0E58545EEA9E5E8D5DED9C39016E88896DAB59A84EBC7CCA28667F4622009748F6B5854A5E0CF070AB61CACCDBF1A7ECA531A5B5FEFDC3FF660DDBDF0447B703598B76ACDBBE8621E7FFCDA8108A3A11807AC9992EC301FDC3F6567A99985C1A16D9AA9286EAB8C65E8D19DB04F01D918CA04CDA3775595494A4C2D536357E50A3C3CEC153FB378DD9D2C05C1ECF89E89A8BCC4BD2776C79F34FA9210E9E9681A2B373C857E8830AF24605A93A395EBA1744CC2F5EAA17A42336FE27FDCCE42DE6892F2234B9E111535F424F0F68DDB220C13762466361E5CC9D8BE3AB7A45976ADEF076E +smlen = 3375 +sm = 30087751DEC1C42FCCDF8124A7E47A98575E1CC177FC47924051656A4B863B4C5A94D6992F12FA0763F365331064A349401D0FBEB1C38803169F17E9FA183538E7A2451DE7F1D6F0F56F59DD44424F6E44E44C6A3E8C8A24A033C701B27B692C1833C59AF6D3C0F45B0701D46CCC317C6602A3844D19EAEEBCB530281304767183853E868061E119CE01496F5DA859CCFA77732243C9430A19CB8B9E0A17B8033D648241646B7816A714CAF6A20939CEECA2B9F90BEDD5BCCEB65ED165F9F39468D8FB6B8765CBF41D98F05BD4755FCDCC96D11052CD10097B43C5C213A3B99FDF3CAE21829210DD34554ABE8E13735F391161E241B4A15978B1E4A037530E484A43E8F4A0AF08CDD26680B9A361CC85A5A67E205B64B1F3F25EA839E780B14F957147A63EC747A7A2D95DEE368506B9EDB43C93A3B7D215D3E4D1817659A9E8AAAE04EC88D566041361FE14B3D68FA16801FE95F2874D5BD2071E9ABA1D4A407880FD0FA03DDCDA4BA3F7C88E20851FC3B53E7C9F39D2D792E77EA8EE240A509E6CDAA27E5A09295F9CCD170C61C1C5EF93F6EC179966F105EE93AC70A916D354F7B47EFB825F0FB10B569BFC7BE46DB024CE6AEB699E31C8CFD386E1A7DB00A83D9913CFDAF739E947CAA6B08CD44A4097DC6C96F77BE8415E70B0C93CC968974D4DAB7871C05D7EE51AC362E0F3672D1AA27C2BB6720F56795C85C41768D0234CB4CA19A4DD5A7D927668E2B6FFE2C3B960A904FC206B74965D89BFFAC8DB7A76A8FAD8463D13C25983D5A923DF477B968B1B92149CF51A607481B2EE04C141736BB35909277D60C003245827B749E7D8F7EF6CCBE99A5BD64435821E36F4A0E9C21D5CC0662B0214669138C74099D5BEC616FB0A50745E45D036A6FDA865E590A81D0CA54C1204B8ED86FFFB510A8A3792CC3F90EF813898A5D266C3A359CFF76BC198F3A7249737F6C2113B22AE164B122320C6F0A2112AD41591451D65CFA7F05EE5641B68B385816111EF9D654820DDC4EA58A70587C350D2FE7FAF3655FD958E4A7F821F5536342F90325A86C1FE277F9478C74B255E149E93F34CF9B7E6978527FB20260DE80615FA3D876C37ABBBA5D92CD8272223617D9D2509FE48B95F71D63DBA054A8047A9440F87BA19AF7E3B31BAAD2644B96FA3FC7084025B75D1F767DCAD4CE21991707D7FF33CEC48B5280A6D19593D7BFB7C6FC513DCD1CD381231FFC6E270E44684945DEC286DCF58ADA42884F343BA48C0C25D49D121D02B7B66586164FAE0AD92CF5816C5DF6FD0B071CE2259C3966956AE935FEF5EBDD725DEEBBAE5BEADA7F9FB896FD6F69DCD35ECE21E2975E982B327ABC5BA21A333A16A609BE512F5A4E40CC110C5ECDAE7C95704EE438AE02B5A9E309508AFAEAF122C816A5AD2B61C2CC42F5ABC2BB1C15BD37F555550171155A00DA79B069BC150A9BFAA619720A0FF210555FF5116DF7CF7875D376E9263DAFDB41EB65F8B378C16EA5F72CACCB598D450D9311AA99F92564A9C7E3A3481150E712DD25BBA6E4DA0A42269E96531E0C191870B411D2F6534AD4A444E35F871A053D137497DF6510D758E7233F85DB0C33572350BC0EBB600DD291D53AE78C5F4F06EEC11477C8B235BDF4563701FBEB76FAC3ADBB4F5E987A210584559340EAA15E3AAF76E4C85F4D4EB37179EF97C0E5EAD732977D149CB52305D1899CC5273E769DBC3BCF04E64B2E8BA925588B1731071E28667B7C9226F7DB677D4E80E81E6321A9756378EE04B2A2A059FE74FBC496269CD7A63380CA4AAED32AC9D5019CF23B553889424FD060864A37021F33305CDA063C38850B365AF37B9B88DD3BEE51FBB16948722930F1E5007895EA458EE29F0E80901D64300EA88DC4499AE08DA879A68BDE5BEF90669C05E16866C245C8ECE37C6468DDE972D4DB02A21A961FD72E8900F0CA738BE0AA1A2CF7E5BCBA81CBC756AF781BB4CBD5F33F4B0EB7BCDB7B1D675BF7B39E5AFCD14DE3245F4D3F7DE6BEED2E5610888B2DDD65B6C51933756CBB89C1A76E3D6E9AF337854ABD38F9D817FFA26F541D89D6895BFB55230265A70B9ADC1B615FB8A7EF02372AE50447B6EE881A61B436E52FD4FBD99A3E886934146BCA56D5CD4BC46E65B1EB0A918A6049AC32D82A43E3A7BB90D80ACD3BFEACED6D11F94E907CB687840B124B413F82BA8CEE786DC2A7513FD41942F12F48F38A71EDACA0A4A329362F678ECC3B8530E09325EE876ABC6AE44350F88E063D03818A3FCC4A15BE77970FF35F4B76948609033600569D74877E12EF016FA63081435A9A0528423941CC591A76DBCE4ABA42FB415CB049A9C5792B0FB751D9CD190DA8A6A25AF697F4DF1B968502F4A88683C6143DBD00B835D0E901439ED5C4FBE1D1D8DA1D586B48F523FB265C95275142A8ACF1916D624C8711B647BA609631C9717429B7883C8B952FA662B0CDC80CE1C5441F64F9E619CA417CC015FBA96305307EA827C3064C6D0316A565C3996C97ECC0A3490FA2DC3CDC02AD6F5CB9E8A104C8606909EEA1C3243F470D578C0ADE44E2C79C0595D88743924548B3628223AD06BDBFEBA9C43F6428B7B3A4608261120135267A1C1A171081B429A192ACF1A69C7BA2B91CB874E88F7DE743C2FC3B973CEC885B5C3866695840A3261939BE26AD71B815CE9C0DED2FD90A831DD62CA9706D19D792FD980DA33CB7AEFE9E69E54E10B8C2F3CED48E2C24012CDC8209B3B667E2DDB1859DE82B1C25BCE78BA2C3F26CD52F1278E9BCEA7D25DC0026F637A9340B490675C9D4B26B68B4C07A2418EA05B642C7D045DF49093B967E559690C0E683D6D96E1F64900B17F1D04BD80D65D904656C6C95BD1B45B03F641C9F22D812DDD77C13DBD7E9CCA49B3DFF9DA711D5202789478137DE7ABA03484CF93F85CC7205F98E71103803070CA778DB88F22839165781A442939C07D48101E2DA5FE911ED42732EF59FF9BA86A85E0502449BDE2034CAE717C9098D987DE81FF818A81CC9D72285B26DEEEEB884D8C2655EC8AF31B085F0DF6B6B9CAF2A79430C8FDCB9B806E4D70CCF24D45F080F1D20543C10DF8C70681F4E5403B61D35A20A10A118D553B8FDF6D79039CE1D14350261DE7126C5B5D5E000FC1C378D4703A20290AFA01622321638B2AC02882D62F174740D059B2904E2DA5EBC49B2E6097F8840B3A3E96E7218991F7D69697E78B02E1B938EBD263E5AE84AF7AB9FC027BE0181264F6BDD183806BFC3A54AA550CE5C689BACFA271A27BAF1FD74A093A6A9BD10EFAC5F32DFBC50185AA598F318BF88D06C97A6D43A991334A26C4400D399308F848E264101237659B7802E61EDD8F7F23982CC94BD75D4D5D8F025CC2D224164101BEEC0D4AECBA3C3588002FBFAE1D7ADA4C43648EE812AFB158648FB6DC4CEDB2F6E59DD642376502E84C920BAB5A6A8543314AE00E6F3D039DD88739D621643B5A80C483016BF7ED6893D054D925D0F80A9FA142CD5EEF570CD7BD9A03F8368B57BBDC45107D316AB66CE5936F93E31B1E1BF07AFFDBBE9A319FE784C033180BF314841D92D0046D2E3BE1C61AC0B2F554A2C0B2A674CC80FF4C8F62F5ABD4D78335E3CED2731DE9284BE1BA4CA265D80529BA53DFAC74EE0017F0CD854379260C7F254C9362DFB05048082E01472F4A29D59F8C4F38EC6EB6DCC3858121120C6075158F96D23F44CCDC018B99AFF5583CAC162238A77D030555B13B353898E7BB47F16DBA5C5A3733DC058C17FEA0936D855B382150393C8DD04718C80AA9DA93C924381694B9B728B271499583787EE1224849A870331AEBA583B54C270521D67C5376ECC34E3A59F4777CA35BDDDAE54A3861194290BEEBC19602693523DF8290E3D8463F3DD699A491BC1FECEEA3F7DF14363A5CDF0098E0C20709AF2766212D5250513D2AFA5782B38161135F2FBF607C2704D2615D7D2646E661AB2B8B32428E3B3B224EE78A3CD0EF3D6BBC566A6FC2C11DCAB9A39C1D89D72C55730D0AD8BBE40FB8B9F60F1149C23EB4D9560211CDF7E91DDFB35FCAFD38623BAA2C3E5A27CCBC7A0F90DA5BE9BB53D5D0AC0260D238452D4090C1E860557DEAD4F46B50238BCEFB8FC38D6D1600690683BB53F0FC6068A9C438FB9B7D34C3CC2DA2CAA8789E928534907079AA7FC0B23A465871CD7B6C10D5B65B12C286EE9605BE4C09202E603DE21DD4C64BE04079A151BDDF219A441DA1541B2A08E4DACEE17EE2B2D949A2434B704032F67614613BC7C4E4F2B6B8DCA372E591F05532AB9F8F6926D888E3CEE0CB98F8DDAD4FC15E353AF4F1D56D58EA5EE94C5B0F1BEF91BEF8F8DB691ECCDF62C4CA6C41B1A038D3164C66F85BB9F6F73D05DE09329E1BEB0E29D0A85AB72B7860DAD9D34A309161BBC5DBB3AD3CB32B50A968BC4C169D0CD451E8A53CB6ECB6725FD9BCF878CAD47A2A689FB7B36907068713DD619FF67C4B5BE8CB2C513D08FEDECDB91EA09E6BBF1EA9A8F02C71F7FD0E65ED8EB5F79CD5B8465E438B1676028DCCE6FD3D9899F3F0BDF36763EFBCAD392C2425B10EF73B57476C7954DC91E89630A3172ED11730854DE9A6DA554E8A15131D3A436FB7BDBEC3CB578E02262A507385878FA3E0F1F66EBCD9EDF9053D454D718FA1F0F3F5040A2C575E73000000000000000000000A0C181D272D225D5CE2CEAC61930A07503FB59F7C2F936A3E075481DA3CA299A80F8C5DF9223A073E7B90E02EBF98CA2227EBA38C1AB2568209E46DBA961869C6F83983B17DCD49 + +count = 2 +seed = BFF58FDA9DB4C2D8BD02E4647868D4A2FA12500A65CA4C9F918B505707FA775951018D9149C97D443EA16B07DD68435B +mlen = 99 +msg = 2B8C4B0F29363EAEE469A7E33524538AA066AE98980EAA19D1F10593203DA2143B9E9E1973F7FF0E6C6AAA3C0B900E50D003412EFE96DEECE3046D8C46BC7709228789775ABDF56AED6416C90033780CB7A4984815DA1B14660DCF34AA34BF82CEBBCF +pk = CF39B474CE5D8EEB353C885DBC60D2A95546F4D2A97B9F0E46C5E17C1A8CC13949AFC995EB675DF6D845CDDFB6D490CF8A11F344C45CCFCB5DAC38B8C49AC6D19535E00E05C7C3DD4E6A20320D152470ADC1B70E84B174C8FE74970D0CBA5FE3915C198D8CAD29EFB72D6B0D50ABEF7205B0CFCD578232222329DC91BF372FA23A57F861D6330011C059683F7872BC9797DE9ADDA2CF4380A57F473F8C87BAB824FA73C753BA41812FC363514CB5452493494FD248E7AAA00A5D994D11C93F66C6E808930ED980E549D9055969427CB0F71B401FC7859BC36CB2ED27BEEA8986E391C3216BE6C0EFFD7A16F2ED5AC3B01B6FB6A2AC3569C5656DFA5BED74C4FB21DB654FAA6F6C0E02A6F47F33B8F61C830843C450ADB43D48C8E300B851ED673E05308300365186DA59763F01C5B43B9149AF66DE58151C15C200EA2BADAAB0E4710447917452FF351C0E4C2348934C54D6EB28C38700E6560888CE010DE5CE0D505F62FFD1B01F0DB73C586357504D82D49CC051DDE0913F50207F8E2AD80DB12E920DAF15BE172DBD7EB9AA367558155EAB628BE38FE19DF145BFE8E834C972CCA72ADCE315E70BF9C6CD98D4CBA35A5532BF20AD9C308377E6CBE5814EB43AC1AABC8956F1D6DD61E7538B17AC6D98291B83A4EBDC3CB98FEA53A52C5B206D1F1515EF7048F54E3EFD09850882760379B6F1A54F9D77212EAE5976033241B9D68FB9C744605F92F91F052E34DC5B4164A588E51D39166B6E69ABB0AB0E96785B47AE25E22C9D342390F5FD4C58156119ADC0325F61A0EEB4D7FDD12752A76A33E15082EAF249542C036C06C84B358392645B9C7CB16DE56F6BE5A824C86A8AA81A683131BB03E26DA0060807E4C0D3F35F3CA05E9C6C7A7C363F8F81B06FEE6482F450E6EC2A0F423C3B5F16552591671C7D3DAD856053E66CC06CAA2E07BD03A0B5D157146971C3B04502D783A54603A3227E7B24A02236E36CB619C41ECDF5167AF64B263A676E1F283033486ECE825FC4970E9233D361AE612D2ACA25ED0F2AD304A5BBD188D8ED98CA72F3508FF5B90703F1B3B7ABE37472E221D688132106FC6588041A519E59E429E1724EF941DA3846DB89141811036613B67B50AA8C8557B6BFEEB276D145E02EEB04BB8F3D9D792F3BCDCADDCAD9BA595D0674015AB5DA5B28FB35AB35D0BB0EC5CE3C95CF47CAABF65C5C328C87102E5191DCE582D0C77C9BC3F598322F1691C9BB216F9FE60510D40458B2125FBEE068F1EE3550427127490110D0E62F6A50E997006D810F0214A034DF24C48C7665DDDB00173A7CCC6D9C16A87C68ABBF851ABECEF965B35ED3B910EB143D07EA4CD8B59A7240001D3A507FB1AC168B4AEF067403D9C0FBCC205FE54755359E9C752A3080966967AC0466104AE8BC932B4CB073713073FDFCD5C7539A19F17831F0BF694EFE60F1266933EC8A78CAF25999B32F29A197FF1629FD2FF90EFBB48BF9ABA1455F4073640B766FA65CC0FD865BCD2EAAFB4EB14667BB8E726EA6C595E99D8E581AD17B489570FF86C67879F03D39415C929138D365CA56E00D2DD96A05A09B350575CC2DE9745C496BF61E7C903F2BBC1F61B2D7C4A11FDFB4080698D3B1BF25896F4D772953D10D2619C1E23E8F448F7A2BF3344E847CC30B893397CFF2E7A55849E18A22FF8605FC885284CD64AAF451D6B928E98B67C0F06C905BABF004C48AB3D4C27E4945FE761476DBCBA76A248BCD6A510E802B139067A5C136A31CFDFF7FAC810EB405A89058420D90218E96AFDC0522A7DA7F1F5E800098AA621088071AE09025F702E46DEE23C8024E8707F2C761B53E2FADF0E3E24C19CF9595731F162664B78AD28B52E5961BBCE7542AE0BD7D05B8E7637CC52F0640E21CB590EFDE7E68AE973D01B751A2D75031742EE2816FA8A70A57899616DBD48D3627B568BE82E409D30DAC4CA9AD18588FAE49EE18E700A05186B22CD53056094D6645079854451809D82321D4B5A695587918DF0503865F95E5B55515398B66E7FD761764B1DADCDC949E08F80C0435B1EE6CA0942A2E8BB95E50C0DA35FCEF7B16CBA1A496706BBBF7CC2D2B6FC52D05A1B8CAD46C860E4EAB620C39BFF2ED56C2D1200D2F9B6BC0AE934683345B9C13BE53D66A66AC349EB545C359B45BCA52FC04DB4C262A3BCCF54EED1CDC920A46B357608B00D946A0A797066A8051888E1112D307FD5F8BD299263624A2EA1EB44E6F859A0A20E050910CBF87709A79BF517A094337E651E4768912B55100F0B3ACC8030BF66A1539CC65C047AFC57351A5C1EF7241AB0C8C1420E96656390F06A2CCFA83FF9735C6A03CFA8CA8E444E138A75F9718260D480183A06E24052354694CBA89ED3FE0F4FA5CCC8DFC4158EE6BF70BB5A525A280669ED8D02B52FD9CE943214C9C03A3959468D44C63E3B73936E659EF3916F65FA916A5446138B93F4EC4BB1364F59B15EEB10BB08232668AE9011EECC1271A44D300D6180D8EF0238FDEDFFDF52C429DC6F919BDA59BCFE6F0290FF7AD68C9E21A5F8926231A57E604A6EA13025B41BABEBACD422F02E09A4917544E9F1430C793E005FD5B5A7F237562EC2F1AFC386F7E2FFAD642EE3D720F29F5E4D1148FF1402787EC56CC83B63D92489225128D1D34C635D08A4EF68C9ADF26214FB39B60B659E19D8D4AA649515DCDDC864CE2A4CA1EC5B8144733FE3913B8DF7068AC25CB4E9421DA02F2A91ABF52BFCD6218BDFFA866E815B59C90F82E +sk = CF39B474CE5D8EEB353C885DBC60D2A95546F4D2A97B9F0E46C5E17C1A8CC139955129066F1FEE794EC4E2C660B81225A5EF9171FD643511022379FA9A04FB5260F5D8546EEC4D1C1DDB4DF8971772B69482B6CC9BBD52CCFF78E3508E9FD51776DA1C39342C5CA51E4CB94D223C21AC34465D8FA2C61F2C4CB0EDA67F8A8CAD135708613510177110028607735755536422584172728651537540803170088515860427676647000057212430480020543730110602014805084862701622462600274526787605668564257426872866772242012318750612153123256007331348335632656628521481581042108755567276516820350225426442545464146760240075785821164760345844347461778285038542331001886127821273150017664341537208440878750345682607858876313224740675418331174752663114173734704717517020572672316765361858122103736118778723670305773251841470076727261368144163332545576320028020632351737245826528888021776012513084664601736440554717216182613214532807756277220287758734256744350474151122270766466832830673736001048733221416647372150216840141742041336136872253844258616508870678307060453741718280220147801641812428777704317035033246258153354877036758617788242470878385176353701737742536665881482840607073504653331712743640806734327643242713173474566361446477085128562440276158267573126063462308712486858256408585624715353577512555401582512671745468868878826758326662474782464273884861813564454352518106411172174563562873508644081756024817381828353558343776183382162443763266243238862424204515203247284362050833133770800555208701434563045810858020357567443381374170758361645678657311852155111455218111583016652708022711160760060267365201126751271764072231334583531876541047041744324573770644011407182556505222283646317123880714086368583566205318366574555152827240780275604703458762041166233134845405735648246448515118625028157207148840416642354346258400561575762742716182454536572514646221735514053181062211180873663201734128173620652032413655512717710821832811110267706362360012241508171100276057475167344027243021633406332167252276262585661350181155054865185586537720324584557037205358587824506866457562818741623801506826122781208225018306566271041856750553410128066777085036670420771414875481140122135866160323344430441428020585670671603377683606388217855021367572700628067225687570736512775317611780820857673574702454201807558330542301264834447638660430025273764571768320342827388203886556078144685002584043268847784125060328511121804662033531237621382650056736547584447504337834446104705305385111676873738650788377552833011435676202606021410703522836127710843523325733854381714028575871652087411753622580462523511177216161655213046568150401720107146067411047714662222481277632180022122672575541420361215605800205846133554816127342424461278624782646073174888156383164066338622314844562802018000038224386546074575652051037061306188533836520175118175288784205871446484616855364686310266503474063335246788018714551553580080032681705588806460085783061634072736750776312016135674723380528602783684205217483628371727145765726878585185607806174878428238580332220130341280011760688076408885446615703700080800318045633020356851454857543368647537215057020632865420627442780433086001734705605866448639C8899310F20AC4574D5A47F67A055DE512D0926C98B6CC00E6A62F0A5E9002508081ABB293C2EFD5A12DD94476FD054865FB3ED8763061432ECFD33453F3EA5E272E8C67F69CA63881CFB5F458ACEAC08158542EE73ABD45222B7AAB8EC7E02328181227AC94EBE7956ADB1F42AB6FD6C2FFA3D19F2C351E47A276F7069ADFA9D81C440BF38E2506D12B30DCC20B07B21726BFDB3B77466071DB2167AD917D5FE702AD10C7BE1150BE1AA3B64BB38266735DAB20CE0AF09860A00D3D1D7622CDEB3C189F319ACE824D43C2EE1FDB08AEBBDAD01E81CC80CDE598B3662167B002192C967B95707B76D299651B3A7EEB796146FEF7BB5F31311422A0B8819C5169B70DBB7ED4A2FE297C3EF3DEEF7294DAE3B655BE5632BC8225711DD21395210BEE48E7082981BE2AB89B6B76BF0835E42FA12B71580E853824D09D925B516EC9A8E8B988E8E3EC0F6C58B2BB5548D14A95CE0D010282698ABE96D72C70D48D4FC7BED23D784D28462C673DDE5F4BF616C69CE229C85E2E8958C212EDCFBF31E52612E648BF5F869455863EA978856AFC1F90E134A1C1528EEB4124535025E0717551AE90E0B455061DEA810A44E0153B0419004566DBD7E2B4511F655E4E4FE740710E7ABBFD9F1F9AE2F34BCC0CF9DC11FBBB6CEE5ECD30F354F7100B79DC1F13B9FC3E1257DCAFB7A7E31964FBB49E4CD22CF3325912F36142F5F98412CA25CDE2F3D65E831B54E4E7018BD5F4F4B251C49F5629A15AED14822F36E8469089DE3996E86DCCF0C12921D4D6449CD4E93CC97867E1C9FD5C81E56315A14E07707FF716514C9F84CF1DD7DC03450DA5708399AB9C5069CAFA7694AD3C1808AA769E94895D8045440205869E73A79F82E62122934073DA922E12516B64A9C2FEA3C5842DEAE432C5A8971B39DFE533EFC6B7CD246FC62862B4ADA1DC69DF21A6045DE23E4A4E0F520E27ACA723869A28E37BF90E4A6DB549FD56E3DB077B20AF65971DACAEE222CFAABF1E363650C0E4FA8D12C030534A94839B3186FED609EC6A17738FAC12849F5A4CD838743727F9999B7DDD0ED5BF2B1B20854E91CA84C58909FC7D882CC3C62C0B1D099FEC5C213340D420971F871A96C338E94EDD81ABC23016BD69440CF3FF15A07B7FD13378735C160966A2FAA36B976FF042E524FF5495F31617C35EE611026974A28622413F746B484DF8AFE03D56F8599F1C108F65AD6E55E0E9AF1037A61E7221C9F56C4A527567451767F9912B39F7CCDCFC96287C0591750C04CEC6777913B93CBC84291F49678FB36694AB80D4A3D8E757EA910B10AEB16F129B41008837BA5D4FE53634DC1DFA4F9B43B139FBBD005CFDA1A8ED0720056EF53DD1EBE6CDF84ACF9BCA24EAF8BC2DFFBB983B40F66B7388D677F78770CCCB5A47A747E823FECAE72DE144ED2EE182C5F628FB8E298ECE236DEF4DE90144BD57F48A78CD718525A5186B203B71AAC39FB5E73227A68CA653C83DBA1D3439AA00EF4485C1B83B9D255FBE291FD248F1DC0084010B5BAFF08B1560A405860C04F62426B1167558C8CC2776A4E2A5403A89EB3CF6D524988358C244BCAB42C213DBE470E48CF04C1A3FA4B48D5D7BFA924DBD525A799882C2B8F7633FA7B83B44EAA2D6F31DCD8425AB66C390AE96307F2222D135F3D3513D7332915464F410941448299F339920A34771C14A9647DC92AA877004045C234CFF9215355F8DFB1B84141A7037903EF248BEA658DBAC6F0182B1C326C99B1B162F19F20040A327F569EA014BD157E9BD5D497FADE3C1B873DC9E9CA97889F7FA3E5BA76C28FB3C22FA94B8DC8C5CFE7CF3E6E8EA3D500BF1A8C6DBE4748E64AE1E746877D36A4C65C5B3C24EC5F3FBA445B24646A3280258D9A554BF41F63E22490E5FA3852C9218316ED110A512350BDE17EB7517822634113AB1FB77D512B188108B96141E6AB3D90BF7EE8F80A608A2C081D6BCB85D386562B047AC42BF5D83CA411CAE6B29C19F1ACE1787A4504FA50543A9F6E3F64F84F0779CBF1CD2B7066A9164740A0BCF96C8BEA7BDFE83CEC58017E835B8A6697874FF2DB3C32FFB8294124E57A2939E7AE2BD9BD2D611C88A365A3CC8DA960E9C440810D2DE187CB40209BB60B86A63E5D8DDA02D313A0D2A56475F86378AAA577F38FEF49FE0FC6A43414C46F48DDC593336245E9455D4351BEA60E7CE7A812781670323F97CF6DE1FD888D47747509F85EF202C92175ADFD382E86656A9D907478E17A60FDC16A5D15AE21723075220CD0328C7C01E84ED206FE197DEC2D9C91E67C783913457E26FE45FF0D462773F642269CBDD01FFA6234A3FA94102AC6435C332168BB98F4A305C9891E905C13A4B2C185CFD4F9C46CAA8B479E9BC0A3C81C2299B9FCFE0A78575AB2AD3D996A92141DF42A62CDF20A320EA7BF082CF256A10CD2FFD770F4F353DB4193F58FC05ECEAD7DC83A734013D799CE46B8E2FC2E76E512E7960A9E61BC9731699E86AC8FA00F819D52AF9341CAE27D8B9989477477523D8574837A9FBB23E4DD27042DB2C9D48B86CFA881AE297B410ED4259CFF63C3E5B92CF8A8911BF1E2D5135F553BEB8A4B31F4C46A396136D26E8B49977FDF6D189B9808F18820E1F9854D03EF10018F0BB6A405912258DAFAB017D29EED9D8797355D957DF908FD058F09937543A6244AD8596FBD7CDD8CD62E410B799427CDC230798AFDA2D6493AFF61FD9C2613D9BD4C6C4D3D1F90CC3169D45523A38DEA080EF266E3351BA5B867CAC639DD42800AB315E9B38A9A7AF989EB1DF46C1ED63AF6BC09042A38A451159BF34B4356CEBC89872EC5E4C009C39021AF3B1F925A602D855077FE87066C3B8459B09F778C63F77993B6696073A5AAB17F9C8A20F59871365B95872472675B35A995A0A790675007504D7D42D734FE595CE66D58B4027E9F498D5C33D9D8E1B723FF0AF23251E23F95AA7C50427C23A25433D0DEC2C817AAF73BC2A6DD7FC8D868413B9C7F1906FCBD5D5604F46779FA122A3811E75ECE23EBDE8998EA9A43775AB72BDAECD1D4EAB14FCA75C9F792DB3AEAC4B34657746D44B11CBE940839F64DF1665F85294BD8499B01F75B626896A324C10D95D95635A5859EB338F54138251CC19C49E4B169BE8D1E82EACF8EDADB2F128A9544D7129330241B7FC295F7F154A79BA25BA59F2AB80421B76F14010F5FE798E0F3233A80B431E331F11345EDFC050022814DC82262C5EE442CE60121ECE52880A554D5C523A551B42B9F0FE2C9B9A63448A9812B9165E3CCAC391696DB6115DEF1E94D60EED11D65DC997A0E664723A713BE66026CC91DE00E9E8BCBECD512577958A99E561DFD263C6C85A2414269981EB5B48C08487CA01322750D64CDDB3DEB5F1A4D0A68D6D1462CD97F2D06DED4FFCFE5610CA53E55D164EF10E535F0A0F6DB42FE84B0C1DD64ECFB0ABED418825EC731EF59CD38CDDF9D5BF0CBF30DCF820F57D19410B3103C8FE0AA619EFE990295EF2B42511D8F5A67C4627F4ACF24F8BDFD28602782 +smlen = 3408 +sm = F7F5B634784696AB21155CFFB28BBAA2F18C133968DB8AA4D915B6D6546E98BDFCF637331ACD010BF98B55C0D32EAC7D2B3FBE21ADA5A81928D75A94D490A09C37EA1CE4B27A70A57C0944DD75175C971895CD17167FF2DDC166DE89AE025160EF7BBBC25F0E7D00AE703CD3404BFA70C95CD0705F94B88421BD8BB7A6EE437DA43DFDEA4157050D3BA43A2D8CDD04B2505A434E196A8818314D521850AFC4E7DDEF29927F8D3F4A2AB6D02F2B0711F4D24B7D2090FF85BD8B0ABF1CE63CA842AD418BE33C114320ABB478268E7BFEC322F23706D6F408907690B79DC98D4040D0957DCE57A19475267E678ED37AF171C94ED78A80D16B3D9EF52ADF864D735D9EAA1222FA5116DE492CEF7D3ACAC90A486646DEE0D7A92A3DDD5E6320A7036CC75C46C99F9E562C8D7E8A383E402596BDEAB5824F9AE4A546C66E69D9435DFBD06162232CED496878D63C96927AEBDECD49CD3C1BEB22A79EE23F4EB2505EC064D686BCD97C8D304A43788C2492BEFE6F1F124B808434253D026BD58735930EBBFAE6650FAB569B114B73AAF5CE8211BBB161A3FC10A9704C06644D91B88173C4FD22EC0A8026907FC130CC5E64E2978A79981960A335824DC6B65660E12ED82DB1A61B363359F699647A6EB48E055847C4D32122EDB848A8276087477B935622A4926F516ACBC53379631879B13E50C70E65CACB9712457FAFDA53A4C290941EDF4E14410118809C52ABE34E7A474C74B7A3BE1583955CD4B2B5743DEF20580C495EE3D9D8F2DBC3CE6C9699DD6D5142E89AE4DF52C3A91D7B0F334C69B38AF1BFCC1D49765CCC5EEAD3CF7C66699C602E76A05D6F84EEF8A8541D9D6F8AC40481B9AA8869F39E03098C6F4AC4DB5F462CB8C2237B8C10B9C83EB7528D2CDD62DC6F1A37B6A80FACE251767D2E6003DFA140E8269BDA99D921D3724E31CB684A4D831F0BAAA14058BB90A2770DB55775389CEAF58E5387E58A92883D0507A687F94846B488CFCB5752A7B4FD1A09DB9C6452845B6C76AC0F1D301F899CE2691DBF6BA0B1FC4829345F6EF2E20794B2AF5B46A63616C2FDE8ADE064B257AEE76C1C3A21CF273AE47286661908A4637EAD91DEFBAAA235CC56F649DE5143ECAD696E4BF79328F9DACF317728B99ECDC053D348B5B40F4C37FB98142F37298331A729D854B4CDDEB01CEDC92640016986E5377D9621D6A28E54626F970906014A503DBAF56E136A2C263DDA7C597203623E9E193D665806CB5EC420B66498FFFCDC6924E6729B11592AEE952BE4555ED19A9660CFE0307CE711436BC10589356967D5E57D5F5ED27E9E7E0939F2C0A15ECE0AAF6CC5EB52CA2B1673F5C4F8842E28107A22DB572D3BD3F38862727BD6EFA051215237CCED6586F73EDB7D563365DD40CF7924E8677FB21DC842BD184F94A34D5DA13A079FA7E61680D65EB14783E16CBF34DC85F724796875CE13C8584D0CE5F944ADCBF3547D13449C0495460B40D386B528C5DEE64728023363CA92F2BE56CB320042A0162F074F80EDF6C7ECE7222F98BC03DD2D93D7DED528A494620333E91417F47DB63055721CE7151E3FD7CF6A809D62F310B3A99FB9B160D6424A0CC74671132FBF79C4B620F025C8E8C9D28D6F00C5BB8B28DC5FE245F8C25EB862C37E9456F3BB5987A1F9BC7E615FFAD41061958AC57813CE2185EA9DCC1B4E0CA644BB15A42C749D877C0F767CC07EC5C13CD0BCEAC5CE13F49F7BD547A32AAEE05DC53C2C25BF9E6FF0A2FB796C615D895B56E7BF5D7D559876631FA50EA1D6D0B962B92A8A34FA50A24990125EF16A9E1C928A235CFE5CF8E7D4E7EE15956BB2EBBE44C9E0A72D200CDA6F7395E3CED26F2BB0882DDE8921D65A7EE605272358A46371591230AD034CC59A8FC8BBFA12925A662D0C1E4DA2D85DCD11F5E874EBE3A8D330555ACCDEF2DFF2E33D8877F26C6672750EFA9169980600ECBE4348BDD256C59A01B8E99E847429E7C4951A801BF2D434EF5D1EA8BF98B91B7B55059A32B95F45FC2221B2D8796904911EADF117A0BCFA365D51B706374068801B7638E221BFBE3B28E17BA053FF50F8F4D28F81D1BEE3335E402F78B6084432E6865ACE1D581DF01F895BB31AE0AD104CA7066E8FD1BC42B19BA2C4B4F0CF6C2EB1033F57ABADDE4E5336E06C8BEDE53CF3A8529D22FE580CE6F00A2BE72C74AEA5D1ED1A8E0541E4B689C510057423B18DB484E0671F13A24DA0A673919EF32630445B74CCF7E0AE33462567E7D34B151CA5C6A48BF447D755CE507BC08BDA1D56632A68EB2436763C3998A0B9A0400550DE03D6C091BC17B6ECB89A98F70505D3D06EDC24E3925282CB92D867FE2C9E2F5C8083128AE376ED5F61F0FF42BCB4DC14C53084726CBE8FB7B1E95EAAE1580250FA34E779611907B1AAC5438C279053DC45896E39CC46ED5C1C4356C74BF926C1917810FC59C9D5C389306189EE16E0E300FA12BE83BF2CFBBE15BA83E6F7D268AC4AFAE715B5AA44A3CD1759CD7C02755598E816847262AA27289D032B1A5DC41F30CA144CA2E1DE2209B2C684E1D1ED5FF843D03CC8E1897F91C9AA9082A94A64335DA2009A791618C5766484FD093721AB3EC146705BF20602DEB59955E3A41CC678EA9B51C6F4B3C15149F7EA9959EB6BE0E92DE8636AF54AFE32EB0DBCAA378D1A63AFC96A6C850EB36A091FDA15B1E08B87DB24168DA05121F45C450DF1F7CA0E339EB408D6BABD26A0CB5E0499C33E29B2C9F66CF82EA1BC012E548CC4D0BB3550832947BE7F77912AAEDF9A10759C5927773845683E53937ED58D0CBDDC904588A9A32D457F28D81B4FCC11F260717F631688CC15E5BC48AA35509E865057966F588123387C2E598758A77CB5760BF4ADBE29E27034AEF30B93996F9EEADE8B077C61A1A873E531C01CB6F5A9991D9A20002659750B0D543658D1CD74CEF95606F3972119151C3870779254DBAE54F4CF5FE2F950812ED26D1954B74E8FD6379DE906E7F0543941E7503FA2A96ED5429DCB1B9C0D6383593518E640E609EA7332E5DE04136EED433A8903EB3C2C287E1D1854E5FF61DD3AA2521B081B081FA4C686A25E975BAC8B7EC67E06AEC8E924FF0316A07F6703F96108E6A63759645A89C72BC39FF1F860FFD778D5BBE00F23BB9E1D7E59FD405E52A5CBEAE732B2D02E9670A43117BECC8406EB0339A64A4DB9B5F42DAC402D37D84192748B9B7A9E64CAB0E43696D41ACBC299914AD19BA975E5E24DBF5744DF4EF763E9DD365344AA239A498B307F1A843419C919A1F49C25F7908238D7B56C74F30E8F67C935DA60197220F4D19AC1E105D08368F31B69DF3270544547E907B0DB21A0D14FAFB89488A82974AE6D3CF1124F6DF87D968FF64DCDFFD88D9AC65F38718CB83257DDD040DF00E7F16B9DB9F90E92BA9778122CD61F0412939BE2C310FC09FEA400690FA0F3A609FD530D0BFEAC168A81404E5BDD835D756FE266419754CE33CA9FBED3079BC4284A5B8DF9F046B97A436196A1CBE7311A01991E15690956E9BACBC375575BFFDD8A78DE75657604708EBEF6AF967CCE7AD817964C7BEDE713885DEB5A9836D76344D69ED71450E008E7D9E56D477F8633247D80F09E9A852A4F7CC9F916D8D8AA2D34B5318B3B968FF8068B892656BF7B9F04453AD9C446252132435E07136432FA3D3F3DC49BCF22F6E74075DE887060E393D0E42228EE066A56357851B33B8FAAFBDF956E46CB5522AA6D2DCCFB0B8F639A009AAB78A3DF86CE73E971534E941B9EF1A11F5D07D4D5CE3D4A2AF795259CF8723FAA3DE408623478F6B72E0836C8B1E75FAA4F533EC6220DDE408FBE4D04A60BA3A14A1A1A1B4C2BDC6E1CE92F6AD51DE8CA37A814B30C133785BFE22C0BDC577780145AA64664E68C76618AB4C513C8FC0E23257877B1871EE0ABE0B40439278A47288FB0F6B203DA9B1BE34568F93058815E780FCA5E7C9A36A2A49DAD2361FBE0369069FCFF394EFD15A68A6AC4A0B769AD10CEA972C597B449CCF0025863941DE99C9A12B343214A8B8BC43F6448E662FE3B8CC5AD328928AEF2B561C271A78228F4106D5F04C94AECBB0F05469469E5406138946BC67E92A4A9398831907EB1F0B6890BF788210F0CF83B3F8F508598CEC4C96B80AE2F8F82A56630C3BA0CD2EB15788B8DF6AFE7BC194A372253CF977C304DC94E648B507B0A63950B19817198577B7EDFBA29B4186A034914E51666233643E3CC934CC7651907BE2E726870ECDFF0F9AC75B383BB9323DA6E768C07FF430607EB8A841A1BDC401E3893076BC83FD1C99DF2DAB1BB879ED36461BB0B8AF3382831386531B84C5CEA9EC65364A8E668994DB2B71E01D4D8E55C823598E0A2A350C8692901A6D39A8EFBCF2A36EC39107B3A5C1A921980D0A73D3AACE08682308E224F0F0AD01435656F22F88BDAF28342A2530FBE832D97CB9FDD277BCA7C7D745284CF5C17BF11B4DCFD210CB33D528A382ED605AC8757408C80AF053B44D1E941B8573CA33BAAA03372D71C5FD4F3131F8CE4F6B38209011513999D205E4B8B15CBD4D958ED3C19C087DE110D030AAA194980CA7ED8E0EF041D5315375DB5B9CC040D406577A8E902073BC2CE151D899B9CCCE12F474B5D7B90939FC72E373B5567696A9DC0CBDAEDFF000000000000000000050C1118212E2B8C4B0F29363EAEE469A7E33524538AA066AE98980EAA19D1F10593203DA2143B9E9E1973F7FF0E6C6AAA3C0B900E50D003412EFE96DEECE3046D8C46BC7709228789775ABDF56AED6416C90033780CB7A4984815DA1B14660DCF34AA34BF82CEBBCF + +count = 3 +seed = 58C094D217BC13EDFDBEA57EDBF3A536F8F69FED1D54648CE3D0CCB4847A5C9917C2E2BC4D5F620E937F0D329FCF8A16 +mlen = 132 +msg = 2F7AF5B52A046471EFCD720C9384919BE05A61CDE8E8B01251C5AB885E820FD36ED9FF6FDF45783EC81A86728CBB74B426ADFF96123C08FAC2BC6C58A9C0DD71761292262C65F20DF47751F0831770A6BB7B3760BB7F5EFFFB6E11AC35F353A6F24400B80B287834E92C9CF0D3C949D6DCA31B0B94E0E3312E8BD02174B170C2CA9355FE +pk = 945C75C48230174ED23789CCB96A2D73E56708BCEE08DE339CC6DCFF654F7FBF2898D9BEE4DDA66733EB5D1BA07650509B7B35598D3034CA6EC4B461C4D6A20BB6FEBFB5E44E17D0314C50E430D55585667E2AD65B2E4890FFB1AAFF4A33E32FBDD84D79B864897D9DDAEDBE8073AE7045B711BDBBC5282C24F306D67E24BFDCF9681EBF0A989269CC502C9F775E2C071B20E15ABAEB48ABE7915B3F7F3A5A79620046B2C170187A56AF85618835C456C45729D4A3297B478D50BE2F8065F61BA29E5B57E59751A689DC57B54C3F8BB3E5327E6E1885E84C0EA5D1A277F0E7BBCAEDF69B7EB5C924D3570A895E6DCBEC3B2D2EF9F72D98E8C3BC30752954A5603519910D2D175EF6C464CD9457D67209D26A48D26BAEFEAD9C65DCB5B5F0B79AFF455A0DEF73D892AC1969588BE8523E2E57FAD2014D736949B125AADA0AE0ED83212C22BDB2C92DC821D5921D490C951515DD6C63F84D943332F26101856F91FD710D3D82D24E732DA16DB9B1478666844A452DDCA484A9FDCE5B052A3A9D98F22BFB268EE53CCD650B583F2B5CA7F3004F945E9E7EBC542E1CBAE766CCAF02296959FF9B725DB3C4A1776675C5BD3B7E154B23D81CF32132A20166D856E84CBA234D5B4662658DCFA95EEC35EFC64C3D703E39ED6F138ED84FE898CC9ED1820845D6665713CCE60B405E1887B899E87FA3CEBB096C5E833A68222A5A7C627CC0B1F5B445B140FB912DC20C5CFBA5A1EDFEA264048CCAB01CA8C1CAEF6D4DB7C4DBCFCA8529D7BF095DA7660C6E7112A4D300D600CEB02AAC3C0482977799C54405634C776A3D87DCFEDAA9799204C096FA3E450DC817EAC9E257708D01F7D7530B324BAA773FEC6BC3DD88ECF66A5AE25AFE61A6B9B056F4FB409EFD156025EA27814D5FCF416990D0944D98F9BAE622839374155BD6B6937AA2B55E44B33344F23B1CB61D6FAF7FB6E55B270C72E7817A7E496EE972BEED8D10891ADB23D55933C479129FA69CB30226DFE3D2A8721569BE5A96F7BFCFF3BFC821286925E71A5CB482EBDDB8364423243FD8F2CAB647A1A88588D918922D242C89F0D8C4CA0DD68C2A667F5ABD67344B43E5DC224648899BA079F17E1F66888BB548FB864E3DEB1816DF9355B498548739EBC3CC0E4899A2D7F6C9199D5D29638FBA6FCB399C66034364350D08F07BEBA822384DCB5B648EE5F71E954641D86B74908CC6B01C212A50D7A4E4B76FB44012A09038546C43980B675462768B99DB7BC0DE0D46E943AABED71C0DF3F8A37239305112FA92492D647A30DC75E69578654587372D9BBAFB4B9462956E2E6EB3D65F8880B0402DFC63795BCAC9D2E66ECEB1C00E14D2B8200E26AA341F8D6F2D9F8F4079F48C1E7696184F0D6FAB5CF76511ED8281ADC62D4A8FF12FF0343A5C75AAE3A18E6E4E75985A59673CF9CC41F97EC0F11A536078A84D65DB7947E5D6313F1659BF7DC317A26B8F2A4007584C92CA264C3ACA744DA1AB6852EC3A3E0FE9A28A273F95B90A7FE779129DCB3964964D872528A4619CEB7C398183F5D1D526AB14D6C70E0C22DED7A636EA9FC27678F7D6FFC11F4CAAAF41EE7E3DEDC40792CCF23737590F33B7B1943B3B0BBD2457F51A76460E5A9630426C12E7D41128D4F7C0F89C57336D11D3DCA65CF3BDACDA0AD757090515BE379E28C7EEEE86BE09B5614E36743BC298469D57CC78AEE4227A3F733FC88C5713DAB70CA5FE2386769CE076AC4D119385646481AFA1C62085AC279B1B5BB96C74F3E29D782C69055501C191952C4BB984CFFEB8584F50276AEA77F94BDF6F1554C9FA73C37D7590E50403CF5EA6BDB6D379EB1E1911DAA865436B75C7A344465109D65C8AC1537DF3650D3DE5AB9279B69AA2609776DCBD0828853253790F8E9AAEF4B617EB296F049584FBCF7A4AECB282D28018C39A4CFEB7C94A699A3B42D67B32B7BB61323836722567F573A7F56FBEDC1C01B586D64F7D80A7F3B18C263C24BD6B06BD4A845EE7D0161958BF752A922888CF07CC5722CF743D2252E2FCAE149FEB91C2F736055F3C071C42B64E086C486FDF49598FBED42D648A893FB858C6175AB7ADDAD4EEB8461A8C6FCA523D00F212D0E04FBF76654C0E9EE9322E3D95C90EA74AA418C992125ECD9B759191AAFAC5D623C2A9019FE785D40B33D4649857C918EB86909C550B77FA4AC92FD9327D6A6FF74E48A84B787D19D9EA9558B89DB2811C97DF8F14997C55D90ECB3D224F6CCB8664F54A884012B146BF1AF42FECBB456F9CEA2A815C055FA935DE03AD17F90C00D34F5AD0EB6F739C2153ABF1A7E576B5CD5FAAC4DFEFDEB93964164935D41321754AB2FB3E9246187649E14A64D8058D639355E9C2BFA729176B4F93D8C2C7C4A37C8D9EFD46A24C8B736752D704A252EDE95076E05EC058B1D5F2B546A4E0DFC059CBEFA9C9F5D53FA656F5BE135510B69C9795796134B4ABC215E3B5055B326B32BEB8FFD6B4EE3CB2E10F5DCB850D383475AE4774FAECF55665CBD3707EEB736B3B656A6FE78CA7ABDDA988FD4B23805B393581BA3E27759D63F3F540C61156EF7F1CD8BF9569A1C41F9B5AD79E533F53D4E6BE4AA4BE9BA10C46D5B32B4371FB6B51D52B0A13ECA2B2F5729C2A02D95C7E01DB55CC5A1AA21DE263079F046EF3012753B3808536BCFA5D1B41FE11CCE34255B7EB71DDB221E3EF03AD8FD89E80DF111373816511423B803E0F371E835CD3D45DD19BE40FBE95A6A8924E9BDBF3D2EEEBA874 +sk = 945C75C48230174ED23789CCB96A2D73E56708BCEE08DE339CC6DCFF654F7FBF0D569C84D59FD868B9ED7254465D5376F201542735D9A9FF810767C7B39C0EE117BE3B753B4D3464012E3495950EC9A6CBD3FD1FE0A39A31353FA6590996BCBE9B3990E4B6B9E419CCE8F19727CE8574EF84591C951B1173AD84130F653A092F3545182547651384135282882621618865025003011464460517165648113480702771604174830422732127317812586582533377770681104884451357884750200052874153500441631586166744813404776763845784271847570424728868267780668785043666655840787065718573605715807028177433475887716830887082042746043560244187244042636654283507586544456325558083517631676338132852031632752856620068137126326115442615106241681205511421171808374001007126876286845714554107588537803025146621013353426620048840636044416846137716105314440844467211572003883386254167810336656541463161535560747373550534772303148343450374642461433830237240827745687233267337813264838764557481804168362207752401671352875671237676342388307381453876815352478312152821052886225518744670485664605311603773442803171485558447268782726146604636888018562103227035533573486070343880815827600178561335173051531173063714747702653505732456830316341383038538207082502308014887727882853778522432606484668740378822446722338406348884732351816678867383217080336843851316725240218041362634076104110200862453245733633128843574677681516738262684122376175785227702513408643877458658260533667073421202660315812337817867713845114234518735702073280014781466745745785546520276085367054614670240150673410547156303156867574666058120113720036440340215780682823564043104428142058113807673035711475085360080642466874856526668403081876364115007243305508807847348286645168103478854084141422681776050325360606864885835306464412310818712248426443173762134672155307235803375724545245360637488128128835132011207454461050466007184761643376675878875532042208816643843878536651706547017237500870076611061055246330821612725384415824488613567446067660712422642131828342068628507580724158410678812356305241557523233847826458585553617570624187768861767142107253543802021236708801375525875261780286277651345406447053373863767884283630552637680143824763887526485037833387688317072821361517757535425853553826181221207277607450853140364281201242370742651115407000374118666430417185353234822405383588335313166226653207471017563188216226776523232454550276067447734801037145300661310175778323224143571827673177632245078782547122773881220711254736854080717207402016137386017683017885604624240718733664763134566016422862385436220081131260163140742268825884725753243121838124363844811816261503736054780363118824785778140475677038721161632023026340130120376338777462887323455301206323655343388344127781482604605536035844886535314181540114017130322325626823804281557424377112346611750806017574074560756605022884400301332426422100125528505347860527667166076621424406232713301115686244307887425788821500633325225411210152237310677655284077728374327113503851658364034120736764081854402488737847724702145180507223005310246308727723687483670264886213855874470567680637740712217173680002241560064718724330356774650370871388707186250451204235864317021859D837B57B7E686C7F518ECDD433ADBCCA621D00C0D6269C017BCF2E1FCB47AAAA1CADFA77A2750CF9904840758508C79FE79BB83458C02F354430E8DB79D1352B305034D85EAD700C4D482096698D13398A84C1C1F833ACB59AD1F8272B1DA186BFC1ED383817897ADC50962FAD27DB0845666779CC74DE4F63A4CCE10B209FE616846C057CCF38D6FC2E1AE83FE6BB92D9AF9DB606B87839F7082EB75C598FB2C9E189EA59D28F128B880C1D6D498854181787C6A40CDAE9AD5AB02C398F3215000B3EE970E9E4800FAE0420734345160DD82A7C7D6A5D048BF1E8F186A09FC72F6D045F7FA8037FA31B19CF08428F5BF48C6B2A32EE782BC6C1E55461EC2E86C6F7CA072EC9ED916582CDD0BD5AD1F424841B39C795C2B8380D6D2247A6A004C2EFDD83FA00D2B1E23CAF8FE1859183CA6E8B876652B321AAE4A5DB498BBB9AD422FCA12E6E99408FB8AFA4B3077264ADAC76C8DDE0C35FAB23489A8204888C65FF07C8F487FC07970EB1C71A2283C761716051923050ECD958E7CEAEC137683F95F0B55F2E84B5589491E4C90B01F9EFDC4E3320E25A410781C0D3381D151DD2F2C1031E03F154D9F7C0CF32281CC85F4FA7940A95C1E9028C0DACBFDA29C5B13A28B5204FA3AC76EB1C4F3DF4233719CD95EA2D50AA274C5217F25471A02ADD51B196A8AB2F034C596E4FD09D03A348504CBD890E44C62F46AAB2BCEF4AAE53185B523471A7DF1A53154A0356E083DEDDCFED6A60C1CBB72937298ED1F5E0AE71FCD61FAF6CCC5BD1B98212939C25D5DE219EB1CAD1A451AAC7587666F3D718FD562373C921FD48509DFED721BD01947C5DD9F3E0BFC1352038A5CE89B2490C73C4EB29B9241D184412CF35246CF6A2A78BB426D1E5037D821BCAAD2C17012732B1D98DCF8CFCA043F58B71702B909EDCFD832E2DD8F93DF061620956572ED1981A17974F15564602A1EE2A621C5A6F490BD78CB41428B50521EF8997D97759015419B63229C716E8E512071F6566A01B4054E56F4FBB1AA32B653D00E3CC9F6FC74D157E6A9772BFA0208DD38A5734A9B0A5E8A661D5CCB2C75E5E997722A042017739343C38055F6B99362DEE52577E529649F9F8F481B96116F37070F8CC57BDBB48786AE5E6035A316841E30D507DF6F334432B787F57CF1A7635CF7A028492313687C1CD427D7A97387E89B9E2819F97B066DDF0E6C4CFDF20A1550BA591926E7CC4F220172501A38E3DEB1B0CFAAE1FE94C64A2DABB35C7A3D2985242225A7B7C6143B25D15FB4C09AF66AB9076B88E16034A15EF19F290B517EB28B50AF02F35F559C5C6F9DEDF0159EC2CBF18E1BA7CE1D92CC180B6CD15A9D0F1A6126C155E8A7FE30D9BE1C12F2D364436A83924B816C225C9E5EFD13947571B8C70173701D4222056AAEE62571C7DDD1B32F07C018B914B19341D89A9D478097712E57BB91DE17D32DB870046462317C2DE5D274988D7AC6AC331412311D3B6FC63C9E8C20C9F3483BC30CFA6C83F5CB927F02C6B10F00D020D46C421680999C3A7750E48C6C8A051417F1B944F1B71DCC6BF86DE695B60D2E3CA2ADF1CBC1FB612164F5079A2DB94EB5570397BF52C548A852553AB22E8408A7F69EEC4B3B5DFBC27361DE9A30E325C9583BE0B4A580436FAD0E852A736CF2700D614DB4BAB5F4C4B616525875EF916CEDD60562FAB4D2677C1F44D1E58B52FA88933D79DC7B9DAC847924FA7AAB22E100D4A81EA6BE7B7BB6395074F0104BCF96F9A177A4F50FC963D71A895F1A9380DFA006E790253D8F4FB1D1A9DFDB72DAE8404848D100BFD7EF757CA1FE7A63CB2C5605E1E03C0665170031DA519133E7060328C6BE1FDBA8F9C82755F43AC935CD8AD97F4655D08C879BE446203D7A99D6884D0599FEFD0575F4E1F99861A3B7D84BA4E169ABDE6A11DF3568D830845CB648A150AD8165C2D278E0D2A4DBDF39DBA5E3BB7016508E446C99AE4BFD5D7EF50B454E67829CFEC9B81549D9126B676641B4648B8E389E5C4AB38F59B15549D67E6B1772869AEEB33109BF76DC3505625E1DBEA70BD5ECA0E44840B182E1815325FC680BA2A9DEB8E1A85FAF4836C2EC4FEA639A292BCDE7F0BF95079A69952E441979BA06624F1622AED4978F4E54C80B96498E0324634C726CBDC01AD1E3B93F9157DF65D5E7B5FD53772802E824D7AB764C2275AAEF3EB978CD41AB3731A4B6854A5BC5A1E311349BA266F8B6CC4C440DF4C4A3E2151B683983A78DFD47AAB8182F8ED23D5C1198972D2DC99F976FC12575893D8317155A80308E13E4B017321BCB962101E30A0E70E06346855361149597A36489335642B48C5AFC43A3C1D72DCC8AB2556BCC656B0DE09090FA9CE8B245EAA96FAA086D99D3D5C37B7B7408409BD1B145457FFB17C3B07A0AE4D3BF5695B66D4815E72A1ED2F1B6DDC3516AD30AF271D5A15D7C82CADB1FA85B8F4416BDDA9EAA4BE8A0C5686C7E0CA7CFBCB772A7AA4C98043DE1F5415E30E303502F08494036F4D69F980F31116D287641F859B1E18142B0613CB02968F7D3B22311675D3B069BAC33D1998DEF23C8C0AC1DB339AEFEBA7231F8B6CE793CE5B431132C32CB188F0590D0418933F6677A0CE005D5723716C44A87E2F0E699E4E6D28D8BB4267B4B9DFAFF33557C64E2C684C35959FE79EA86FBBEA9E56BD57FCFB0762F3E299BB4E9969F0E83F81CCCA376E30B1991A71AF3A152886F62B0452CC244D15D47B8C6A5351D631BAB3D0B2418B4F775FED89C81DED78835707789BB3F486C6CE5A5F6A86E276135CBA38A3C15C74B6DECBDB5AE82F35761EBB4AC152C67C965BA491286595283765D70A4BD41F795E3F48831CB176938E25D44F8D73A73854450CB609C2BC08B12EBDAB1DAED1F5E7FB2D213A8034F5354A357C3D26C3409CFB18594B89489AFA140EA9EA6946519837DC8FE523115732C43D0D2CDDD78F4BB2EF08CC095104FCC1DAC58186D22C248C7705F92DD12F837ABAC9CD91F5A83F8372A804746AAECBAEAA2DB36748DA0792C2839F1BCE06A21FEFE10DBB7C9F50E02F063F6E6C029198F708AA38CB9D4FB58197FFC99926E57E545099BE975FC10C596389A3B35ECE3E7A2C5002A6BE235B7B8EBE6ED81CFC139266C65F96EE50140C4A8F7920D6B129C2C24F0646A04B93145251CB2CA6E9831E1C71F2A1BDC1EA5E000EE72AAED21386A1767507E2A6D558568C41055170D8AFCFDD2D3D560CA6BDF773D9B3C9E0AB57C62D55C05DE0B3929FC95BB47EBCF15394A79116D7ECFCC8DA0E7AC169D39CDC398FB8F88B240784962E88F81145AC237790C0BC44C336FF9E4B37A7F73C8F03DE7C52FF3384C9D78801F1EF1822FBB17A5716B7A3D2F99529D1474BC78FBC00745E0C4C1D250E23795F1166A07A9C6541893F2E707184EAA46F4162A46AE258866C4C3BCCD269E1A7D352D2638D898EDED87C3FD5EFC87ED725148E1AF94558C993FD00B37ED9F4B3662C0C0DF2CA54646280C1574EF46CA56B5DF84E96ABC5F5B +smlen = 3441 +sm = 7EE366CCB77C18E7B57C9DDA3C3F4E0C6AD03B3F06B00D6A0A148D0D549E9622F97A6B311ACF17E2BF4ECC5CD4F5145E7CE32F7681C9A0AF2D21A31739C784EBC4AD02C8BA51CB92604B7D05867ACDD3F904F088C21C996588CCBD1BCBD3320AC0AF4D968AE15A0997942D6CDAD088BE09EFFD4D3F8703F236EA0DC256CE2E47FDC21C0047BF45541E1A932E6A2389495A70D06DE1671D8203AE13DE9793983781480F6FA9F14D2E9F989DBE2485776D465A241167DF4140D3BC45510537C2325EA27D18E199348DDD314D6B65AA8237E1978C483ECEC0952C8DB9081D19F0BE4FF87B001DFD2683F16F3650FC7F8DC826D54C4A001DA8CED0BA4B89AC726B2B7C387ACCC06AB0E41DC3264A28B073AF4B42B5E6594C227629214412D230293855EB6EB90A7C78D242AF52ECF32A9B2286E5BAFCF77C40DEECB3B9595B5EC51894D946B4857D4F1605D300DE66BF51382FA5BDD5B4B5B32007092B04EEBF4CFD6831488E96919AE8F4D428B9EBCB12C2FEB8E0E76A652E92FEDBEB76D582D885D5D5C7D13B58CBCC5BEE956410899FF4F3C4608E4E597CF4BB10D3172A5D5DFD1BEE394F6862D77A530FA1C45F8A37AAFAC252FF38CC85812151BF43504AA14140B16608DFAFE20D082CBF96DBD8CD6103E6493436AD121182F2DA244D82AB69FDCE89E912856333722B391925BD3415FB2414F28498F89E0356B617E4BB344BF1502FD654C3620F3630A6A45272B45AA4B2EB5AB6CD1BE8FD70D58F2C671ACD3C90F1AD59232A81F2CDE11483E456356E6CA37B1EBFD21FA9621586A179F0B117E8B6E94F08229A328676B159DE1047806351EBADF69425BE321528AFB9076E4A305D35230F9E768913FF2117E7CC7555F8F3E517411FBB98504703A1FE888DE0DCD68A5A2F0F78176545416F4121D79A64CD46268E3548A5CBC6B004668BE371635A8E40EF80A28AEE971BE57772FCEA0FA1B4D6725CAB2428A35F96C8F4A772F5D06ED1FB2DB25CF15DAE48091928A05AD125CCEA1B1B640BC7F69B1A0D7657D2A19D8D570A28258E67068290B640587A841B5AA7BC9B9AA7E3DD15CEBAC33AC0CC9B776985160405EB99E0BDE67C76DABA6D17CC0EE4C13AE4D164ECE47DC56B5ECB4ACC663F5CC59B1A5A308BE68ACDCC2B6DADD02BFBF80783AE0064E24C2F6C1BA4090A3A028E501BB89E2047383975528AD55295D9CDC4F70DD2ED05FE03C701669C2F111AC241B664A5CA7B12DE3181A0EB43189C0615202307A07107F636D29128589C5C26C7D0B94F2233959E6C1BA3CE2D3E9264ED8BA825A25E6176D23A6C2DA1B1292658C1ED1B264D53FB7AC83A6CD4BA17E4E414E2E5BE4799A2BD6B257CBAF0B7964C5EAAF5F076A43F1D882B867B23752E2E6CCE9DBA05792B430BBED722AFA7723525F41AD1A029680C23D6E55456A4EA4120A8D5B56F341C211F4DECF2054331FCC1B4395CFBDED3186CA39A9248B1F19941C5A7595F6AC6D396B62B3773A8D3A28ABD212C903F3DB4AED0773E07D05900AA4FCF1B62FE65C35D4E5EAB692895492B6B90A0816B52C57CCD8FC21A3A7FAE12BA75108E190F3BBC8D1E19ADFE3D03CA88C03327E497995ACF7FBDA798CA921155545319B349AB3C8CC9121B5602F91F102A4F69EAA0DEB08DEF168925EDB8BE3E57609FFA1543C81726BD5375D8918528E18DA5CFEC3B2FF352D541F18E6953872538AC5C8AC070B7AE9E04EA5BDA06F3E8A9AE90106FED79C4F7B587DCDACC030FD46FF5B41239B83DC76BF139555A766ACCA2CE033D6D6C8EE5D97F7442D579A54B96106916B4F6FFDBE6B18B8C39429A6BD013DA292AC905A2CEE65FEE66BF2919ABB8BAEE8B88AE9DF228AD378A51CBEE61501EF9188B07586BC3C444A61EEB3D6275320DDAC3569409571C7724A87EF0A952DDD193CA783D03EDA58064DCB1B2048DA5D653D586C7289EF1C7A4CA6B31C2FD6FEA914323299CE4CE39558015DD71CB063AB64C536B3CEF795C8278CF464F00A18C6AB4BD8C67B55BAA5381E0863E9FDBDE91F0CDF43B12495C314415F7AB6BC9D9F9A036357454876F136ADFF032D137F6E231EEBA6905D19C73A7903E1FF6FE25EED16BF8711E29220BEA5316CD9766ED699F56B0DE293C1D43C42DA1E2BA2D29CD0DD9BBCE240694883660BFD2D78B1712B0B2F3A4CD2266987ED69EF238DC44C38AD0BAC46861052128ED297D7D8F230B508B8B9185E694D449C178940E98D91D069856294B7609F8E4E4155FDA0BCC8D4C398C040CA517C12C1B630DAB5F0D803986C7FCE2ECB8AEE0A27F75DF51A8B5A5BE154B5FEE357AE65184B6B334E6047AD5C9EAB17D4B6868DCB50B1E3A94B9041160F1D22FCE51C0344AEE3A8B17E9F8702DAC9FB6A440CDEBBBB74FB813A8DF8E659C82384E6B09D392A95DD4FDCB7924C209062A00EABC7CDE15917615452E6E936C11215BBB86F63F3236A2978E5B5CFF978CC54818DC2CD4CBD90496862449BD3C6A23728CADF08EF729284CF5FA385667B361D15FD28F8B196987D041352F329DA483B58A7D132F1FC64E351FB3302BC2AC033689CB8C86A36630B279503CACCA39333CB962061CEC01C484B71A9EC87FB069B17EBD3EF73263243D5DDF4944E2FC0587135618646C61D2723F826C4314E2BB2015043BD7F66B087251425277BD6790DB8904C55505C2269DCA4E86B96185C741862477DFB019A66D141ADB729BF8BD98798F5577B64A5E28473C26E32C6F4A7960809E4A168C4AAB5FEDDD6726E398A62E3871E68E683A4F72230A17776D14976E508FB03FD7E24827A4366F6A11D16C4E674650D3AA1FE7639DEA253A88BA2184A80C9D90FE65EDD3100257773EC7FDCFC6BC57E89B35F4E3D686EFB052B3EBB00FF562F6CE77F46A36533398489D6B90C63997EB8CC502585035ABCBDEB66D536CE5DDADDDA59D24296DC29C3BF93B9417535F82430745EE7802A765911DE0E6B40B54C9553E1EAB90BB1E5B91641FA966C79ABC625EB3865A6C7C8D1C174E0FF7E11D7E311AB853E6000DB3BF2A804031909945F5976ED853651C774BE527E6DF5B73A88A1BF6690B704C0718D603DE9562A4F02C2093B826BFF91405166A8A132D6507FE6D03AA209E6028D56C64DB6F040EAFA51A1F16182098634EEA78147C7CDDA11F61AAC72D79B910BE27DD70640289F19F377996EE14793F377F0B2FB3CB1F361C7B9EF39B39BB06FC4C435EA8151D85A5DD3ECA496582FAA8DC424143095AF199E48363B37DC6D44415B6E55E17B8C0D80BC4827D0328CD21A0C96A168F69E58D4FF0781FE786CFF760A3CACCED96D18F161D272C436B4CCA38C116C00699AD698D2EE15183B87D56737C71580A8C413A8DF5239EA67FA3FEB2D0A6A3CB881FCF0E94C389F4A655CA171B811CF514656F898F42EC62B5A75C143823F579FD25BCD63592C68B75E1D26537AEA2DFF3C3B5F5E49AB8E1213678ACD21B0B998E26BC5FD0044EAE412BCF49AB2F2BCB4B0A44D2EE1F148D5D0E08725EF09306CD8F667ADE9F8EAA8BD4311C5F52FBB5EFB605563FEE6D54EEE4E5F6A620F33C3263C757A0F4C0346094E594D8359B403ED80481793A2278DF792AC03346A11D00461CD73A5F05D6F407F899C7ABD71DC3E5D1655D2BD965F70292A910145DFD2E6520D766297BF4BB4860D6144C15FA897FB42195F09660009B7DB83CD2B0853B5E1EB20037DF25A26EDA78007400E697C6E84772393C152A04E032A1FB68E71AE266086FC65033C31CDF52D00BBB90ADE764AE3EAE4CA094996039E3CD26EE0481A3A999319D2F5741C6C370B1E3FF241938F0AB9CB1E619CD341D95F61CD48686AC03447671C732025F3708BD9FD36BF858003B6EFE234FAC2BAD59453A84BB313215413B8F719CBCB612F5BD26CA077D533A1793AD4ECAC33A494C816A56DE5DF679F3954FDE1890ADCA0C01505B1CDAB83CBC53EA185200062699A4CF61F08C617E423425517446760D70CE80ADA19259DE0465BA9FAC851F8E4803449D6D3849C8E2ECF23F6CF3CE96BD832937A4FC6C9087744BBFFB65445C832672C3658B9EA2B86A0A3B2FDA71B1AC5DCC02ED318F2988EA5B309FC2E55442A7456EDF8224A3FBA79BF53508007CF414168C173EBDE3CCB0F8F276B38C067DF52124470FA5999255924E44B5EB0E4A713E2EBC9FA111030DA06F8EBBE016280B0B9FE64451133D06A8B269B5559493CF1E0F4610E3DC0EB173F4AA6A790A2DEC6BF08C7570885B78C358D564F11E72D1C090757B1E18A79A214FD3F3F3D0A6420F58571BE77D5A834257F68500C8D4BC6A8834AA39F8FD9E8D54753200976AF436270152C50F769D7110A668F5C2130A0C6659F19CC3013B401A7385F8BE6AE4818E7676C55A2614FD7AA60DCFF5C768D32329BCA8B1A2B6EF693FA95A068717050809AE203192A7DEEA7840C005F4A7DC27EDE74ECE0A82801BB16E384E468540FF3AA8162DFE4E1F8BA359A2743BD4E5EDC7270674D7FB5A760F811A0785388E6D8A9972CFDF5C7A63139A708179BF99A618CEE2826AF836AD39EEFD64E87412F44FF5A11E6B09837D4E7A9EB452D6FADD65D80236A1D8F20D3376779C9FDC0C245C778796E8FA0203105F6668DDE8FF11233E8E96A5A7B77C93B5DBFD00000000000000000000000000050C141D252A2F7AF5B52A046471EFCD720C9384919BE05A61CDE8E8B01251C5AB885E820FD36ED9FF6FDF45783EC81A86728CBB74B426ADFF96123C08FAC2BC6C58A9C0DD71761292262C65F20DF47751F0831770A6BB7B3760BB7F5EFFFB6E11AC35F353A6F24400B80B287834E92C9CF0D3C949D6DCA31B0B94E0E3312E8BD02174B170C2CA9355FE + +count = 4 +seed = F1902A7815F37BC7F5802D8CBCE5B48D82EB85691718062BFB84D8C06AA41D6E9039B0A107245DAFA4EC109A57332914 +mlen = 165 +msg = 1CDF0AE1124780A8FF00318F779A3B86B3504D059CA7AB3FE4D6EAE9FD46428D1DABB704C0735A8FE8708F409741017B723D9A304E54FDC5789A7B0748C2464B7308AC9665115644C569AE253D5205751342574C03346DDDC1950A6273546616B96D0C5ECE0A044AF0EDEFBE445F9AE37DA5AFB8D22A56D9FD1801425A0A276F48431D7AF039521E549551481391FE5F4EBFB7644D9F9782D83A95137E84EA3AEB3C2F8099 +pk = A5BE845A57BC4F592E37012EC47F9D3669E3285A7FFF5CAE360F592DBCFDF1C56FEBD0FE5D69D29A4818E59713DDE2763416BC1785894B12C6CF91E5805FD0F3F99F6F63D545B127D5C85CF4BAABE2988234135A65B1F6063F83A9CFF23AA50D6929BEB278A74DD10D34FAD798392E7DDEB746927F15C69464049AF0536EACA90A303EDB0E194D385037E671AA6FEA86299A8C735DC2977B787114D5AC60185D491046AB654DFE781DE70FFBE71DDE1243D52AE7C8AAAAE1F3752113451DE6EE91C4569AFAD424D94A0188DC32CF73FE82560FC093914C19F828CF3AB26D9239B0176F442EE9232A6802FB5B4ADB4F4DCEEDDC73F012D2C242430CA6D79BCE0D7E37AAFD2B6BAC753EF9BA9C011F5253C1607B4E977BBD0CD38DE8624ABAF42486165721FBF874C05152525E1F803619B23D063BAD5235452D3E851C8FE3B4B39D6757F0828EBD96580B13D00524839F860FFE47B125DF9E3C4A965C6CF7C92225FE3C1B66492B6D36AF8DF02EC7671057266FB947969DD4110EBD817794A074A3CB15C0A2228D8A4BCE98D868D632C7874CCC89F4F3C846F4F917D0EDE7589F5194160D2D7D8A3F4AAE5DB128898C7B3EA075DC5CB371540A0F34CC1E9CB6CA43B3EA23AEC6273BA8506D10B782242694A65C46BA601D08BB852C6A6937EA5E21BC2EE006F28B9BE658E2DB7DBCFA113E579ADE30DF9A4D031E9D93165E134F59D2E5744A8CF78EC747DD01314EB01BE218FDA0012D317071B9C7655E1F792FC91B90E8F8B758BC7ADEB1F8B220CC36555A4B688ABF0A22053B468ECED1FE880692D35BA94328DD80807E9BC4F706BCDABF68EE2F8C2DB028C09B5C4506B17CC7EFE461A162C3FA135194F1ADF20237264B4B7C8D0B4B4CC1C71516A1F1A23DA00B3BB97E02188D88E33593F74D5A5FCC37A749851803C3A26276E37BAC7303601211D09A6491F11B69E29BD6C839C27EE759A4F224FF3D744C8F4403BC8085D6A3A22DC44B58810926BE7E4DE2824939EEB9D842DD73FBCC1179E2BE699DFDC3F94E4A8EE91A8047DA5AC0E795B229B0AE53583DA82F637D1DD82DD43FD41C2FCCA360BE703A5A17D2A63C72994A91D195DC1719E912F268802D9D1AEEFA0693A93D66030C8C7CD5E8B03A353895420769B87284C0BACF9AA710A69C3CA05FD49BDC5050E9DDBE11D8C371BDD092D3C6E117ABAF108F808CB30E4790456F0A41FD6B2C743F30C7A4E797E791406E54A2955D2A39EAEEB2E5E3AF0E360654D324D56066CFA3F1B02B0BDD73E95819C7D88B030331E3AEC1858E5D0F9C2B3BBB4EEE46291E8F86DB786BEE53676BCEAE1579E8140F4DEAC60487324B7BA79946A68B660F904D141A2880069BFA8E5AB36C9BF77A3F4CD9D1C82E6C456410409ADEA0ED3694C08BC58C999F74FC4A617FC40DC7025F237100CBB6C4F67C577C03078426092EE66888CFCC967B4C9C005A31FE5854591FB5AB6BC58AB1C8A12C7243460EFEECB814113F679EDC92D218FC49BE2AF4F4A633A60BBC28EFAE692184D542806D5379B5FEA9442D0D3CA2D3F75DB57A51F787700CBF67E0C4C8130C35272C2DC62B98193BABC1306AC048AF090F573156979FFA381A6721D1BC49A4C4BBD37326CB5D787D7344C206FEB070C0307D62B3C9DD8DC663DBDDD7E7DFFDD13EB575E442609E5CAB390A9C18AF7813808145A2E354039DDA3B42E5E0F6A9A9FAD1D16297330D8286122E07E1F8707AD2941C2D5418DEFD3C4F00D3F89A3BCF4B7D4DF28887190789896EE1552A91F18F8B8CDF51A66ED65EE82060EA0C6E521025514FEC50E736AC859F3CD6D7E8E9B591F2D9B765CE9AD2E8E8C3C18D6D9157BE285F1EEA23E72FA4F29FA5C39AD9BED0A27430B2AD8D7950616E0089E1232834C42FBE9F78D92BA843552560C94A0F7F1C5AC9A996D6164FB4B6E4783C5CB65D7BA06684C108C300D152383B7B3ED1ACF29A8C587FDB179172AA22B822F1D36086BCA780EF4C6663B77EC415BE2B3AF2028C1054AE1F1C6E7F158D780E55815B50CF46A91C93430277B638B8A9D8DDCE07C24A6D14FC9B5F39FE77053CF7C24D9C27D552DE20AF97FDFCF13F66A23967718739D6094FFE783303651C6D6DA8683F367E6078FF2C317968B784D50557388B1826EBAB9B333FCBAD10D49B4D972AD2260F965396F9828BBA62FCF302FA64245185F2EDA2640A71FABE16BCB31A08B9D5BEEB1C27B41A0EF2EE4E3BCB5CE9CDD95DB95809C1EFE35B6BC919A0A62CA481B2AEAEE8598A6923859833A5F3CD52253E5C45B498B73952B0068FE22AD5EF765A3C8108CD62634AD179F700FB4E3786ACB0784FD0FFD81DBC88E4B182838FADF39B1EA81ACE9C46CC2095A2B319DBA41443281D6DD0C034AA019B27E75B4E2E773C7E25840049032C6CB71ADB589D1EA97CF87F2BD966B5C54E8B6D61D9FE0E8FEA14CF28EB1FBAD5169924852B55D57F8DA4D4D0688E8CAE2CA3AD6E6F35BEFB683594AE15FAE887833DAD400AEF917A463BF3DAD9B5A68CB0706015AD49031C9E5F5AA801D465889348BA2AE1C155B298377A294AE6AA6F35BC8E1ADBB2DAB7C922BB63F20CC75E401ABBC5B8A6AD39A77C3673378E6C71CC341D0163FF69D4600E15CEBAE34EDA6E948D2C35CA7F7F5DADA381F56ED9701339D973F93195C7C10D34D972473D9E5CE2FA9F0016FE9266EF4CE8FBD4278FA6EB658D3E4E3F3A2D1D8B41F193FEA1EAF82AB95E28099DA51B4B47A7A068826C6B6F +sk = A5BE845A57BC4F592E37012EC47F9D3669E3285A7FFF5CAE360F592DBCFDF1C5E33B9DD08D39403847A73EB678D90B5BF5F1CA87673CED56F2B061FE997A92EDD6D471E7AA5B0F4C81B094A970BF5E90CF855CEED4F9D745771DD8E1D133948C007ED492E254D3563635F3309E27A3C24C5D9C8720D666715A05453B4197AC93676440688372401136586434338264586187022541631717755203264875254038554334765670448354235631151305623840180881280050238458602477836344604566273062330481733601648325455143331302388122012153760245178276864237321434523254574332284260368650086863614030586856826411783845407082026564334218712868877734202344257771538631081847056265177305856431587073424032133446860742322162105702320038810815703221022511155731013883124253871386315153423174744582330204623134400147772116818802611302782487717343206802025330282181024138525460833776237776287231404516855281342666271061643885542344287635184628867813021018452124008654626526624760767051846514026352304534342152320201820345721540475332511221063222323372814701160071471786816478146632318344856483506421180563220473535552317537417121154716461127482528484186538606862648736335724180241416675781071865121160350533657211463414312307501070866457288588261546867478004522435111206818542625431544310414327882677286334130817547774377684670110068023110873870302380383237000012255112173643675053850834112644482738771712762443202622208624725482537284633451146308425143083508401630708065455130221088763665544061523483741262033758528662601157768438356205236816287762463147052558153316762740360085665635460824713118803270454753150722216428337222106242721448647001114117888300020767354076785742317643288763664172301513342774145150257132260252815370171662285588760813744741306780366667166714501155004757202486476850743407868138243424546811127553707577778073515543064104341828645883204315836213513887446201134365001111805511688144436186806762778618026833581118640420512183407818324313686206810504763461871423187405112558447284557122728833125238067281621758408436061283354301744223201584821100067320536360746258045245614525163703048285853162774575580066378184186707311088225034444432364330745561471503477268577782711632766832131840044154343151825804022842380084656160585868435827727230556336443060068401044301810727522204114800205241603858043061481701584285227147768745405120136640706575176506424281284076507778601528220668107385631651445638356530430478713054765345715804524104140877263313676138761076374152584581264181544788887812476428048430517638762618528754878180430741623406651553882553361718734223047764060047157305076621261148167536017220282615506737711854288042012054722663163665640158803728821321587134405364854763004123254152072148503566260641021047543654617771317183525006616654650216303338100066745523127684433157650451217151207156065228573402216768536247438003184240781624170861734603730183030815323500522425117785431222428476861012444350232536081062007051568072517131148778624603615156685828035470846616750621165654712085463638571270615603830414823136456728485124743167327782216350173558572132408622057777682521057681585721262632654757848032425215013262820277464083770101331578166231620AF6EDDE60336AA4763498124A1076530EA171710D2875BD968967CE21DFC0F9121AD1932269B390AB80D3BB6BC6E2AA25028436CFEE45D6BE4E70832E11B50311D73140F5BB1D56524599D738040AE509A7917EF5653B4DB25ACF7B0D359CA8EEF95DA2FBD88868F1120370F05967D8E4D1289C2AD76A0E45EEEA8512DC2E22BA89FB80E6F40684B07FB735003418A56448DFFFE0659E8959E9AA32AD0A436BFA873D980C386B4F55B402F11F807516AE16B1F10F92DC80A39B21AF891CAAD40634582DFBCD2D7A9C8F1783A0F3E82F7161A858782FA667B35C36950E63DC83466FE509E4EAE830A5515F88150774A37031AAB0FF9625FC3FE665582C52C8AE4BFF956153F6A49D2C54FA226C6E9D8FF36F2A9D254D36839C75ECA2701969B06C28417558D57B17615F3066B1E2C060EF8180180A6A36D5BF0711F927EC3CD5BAD3974BD6809042A443631088F8ED6E4683861C7F9463AFE4716B788799014568BA563F595FF7D570CB11FC92B2A7A00A41C083C7DADB87B2D37204092FD39E334200BBA88068A2C28112EE5BAE4DCE3A957A746867CDA4DE29A640B425643C1E02432CCF2D7E2F6BD2E2823DC3A9EE883C61C180C69C8506097B1BAC127888D6A7039C62516BBA45BD7BDADD9AC0750AF81238EBD997CD23191FCB81CCD8B8F1D82C2251BE75AB74C3411B4DB4651FFC5174130F88ABC66FB87DFD969EEEDFCD1A7E377C41F75810B9FE0E2279390147111F6FF88C55D96CA3D6F9389F8832222F4BC7D6302EB431365ACD1271974D221967660FC0A0BB4F65E6497656D4C5BDF577BE43BAFFB20015982DF0F4015CE557D4269D489F821CB29DDA57C12E0E224D80826B8BC93DB1575B9D7D5B9A904C365836D5FCBEB914B3DC832C77231B6D09674DB8CEA40D2BA9BDD79846DD0AE73B805CAD3E359ADC36CAAFACDF95F9C0AF5217E16E111B550BEA11DF24D3270D1F06D05D2D9E0292A7A9F724A47CE88C12DA7370306010F87ACC37F13C115AAE67BAD6CC855CA7612FE695534FFF6F4118E63C1EA9B39BECA7998166CD5343E876D0A5F91B84CF32911AF1EF7B3532D2CB07EEFF7D4760DA324F057105A40AFBD26266D4F8035D9E40DA5E0858D09EEC95ED7E3B638B8761F75597ECFA49F522DE41C6E8FD2188389AAF843AE5BED6E093946ACE7A70926B4453C24502BB7CBEEA6C6F5908D6AA0A2DB446842CCCF428DE8296CD0F64564D2990CA95066661F628502B62CC6813994CE8368E1215207F901FBAA14C2FA05CB6ECFFF4D5E892FE6111DBEDCB37943194A921BBE513D3467B4992CBAAA58805F1AD1C1752E44DF02717E3B3A4E0AEAD7EE7D1F0A2C8895113F2C50266E4DAFFD928AC81AD3452407B1CA8CD4F4EE620683FD7760694F6A69CC48C3D9C2F070BFED2D580A6283CD60E8C59E3188F883DDDA65B11BDD2A63E997A75651B78669B3187E25BD228D350F607444D6A2CDBF5BC6B58B470461C63273F21E91379E52958E75B05ED52EF0BCE5EDFB1EE3FB756D500C099A3AB920242682981A980E3DE36E8326C9FA1C5D7EA5F96939369F676969139D41B816C027707045710A8F8E793A94ECAB4530728B5ED552B00E95751D5F6283EAE76EB8ADCAF506407971E8615EA7346A656C462E826ED0C15456F698067159053016EDA5FBC4BA5FFFFA6105F2C61FA17ED2E4AB90CABFC4A8D053B9EE6ABBA6E8BE2E8D2043F45445B2F15F2E2F444528BC1135602E3A0B11111305D4FA15E24E1459437C4DD268ED1DB2188549472A633797231EDBEA2DC6534321544D5036C7732AA907EE0482614E2049A4A9E71B13B5726AFF43CF0A759F689096F010DF9A3998A5F76D86FF2108FC2DDF25BC7331122F21E0189E6200B9CDEE7AF3A1EC63476F927BC804F6E45B4FFB42E590175E38740A919DD7858BB072BC0D9A51845C7AF93B6D852C1F44136B80CFEC1A29EA1DABE0FB0174629F7788BFA9F0D5D103FFCFED176CBB76DBAF4759EA40B9323E0DF70629F08D27C70282D13314B9D0588C800A902EF75F4BA709B6889B512FC218D5DDBB23777234FE9F422B99F8DADE8F6C1618C28A6231FFBA85963E2F09BEC49A186245A17D5F72686ACF6C377CCD57F64E7CF7EC214A304231CF9B5B46BB322164335DD4AC735CA833B4C1657003078D9B1957BD5752DB16005DD4E4D006CF71E6AAA27B9B63B04C8DC2ED656AF71C1C3294CE7501E508415DEDBCE5D8E6662F58622C3310B4591E9E220928B6623210D4A5421C413BEEB122326D1C0173936896865EBF7DA5077443A235E8A01302BA40BC5F163F272D9E18960F6D5C51698D7438C3E07C6CD1A721CFC46BA84DEE6B2C10C86578FF28B89F8E35A0A447FF27154D9D32F58AF0D8861C739212C76B8EE758EB96C65F735F1F84202DB13502EDCED1430029CF367AE27653D871852FBA1906DFD855C0C54C052E0F6D63695B2F5D2644F92E6416D4CFD1C82CC93048DA9746CED3555A4FF0E4468413B3D6BE2F6795E75579CA27C0955B6355AECFA3A5E867E0119CBE6CF1A12EF1B6EB0222C5319AB8FC8F14B6CCB4EBADBA61B26AAD67C704D214272653E5C45568A8A3DCD176B05E5417B8C919FCB3FEE0EE27E35ABCC912A058175F209FB1ECCF21BE2EDD3FB76039DF1E53BF9134A0B40037794FA41762EAF985AE2D9051A2BCFAF3C932F02740E5B4B9E77C7730FC853FBBE408D9471D165CC610A2F2558CA5A20AC702AAFF9D30D66CFE31A50C47A9B2D841EDFF5C796BCE0F956D30CBB2F54A442748036A321C9209FD7830FD0082077E0B45FBE0B570E7CC4B6641BBAE215AC013E594A52595D9B91542A02F0490065F56CBED0877C295BC60027E763C83409044E5C464F806CC6F32E3D1924E3C7F17440B8E18594F075057BDBBFAB62F879396BB423CBDB12A95AEAFA7E48F0A0202918060D80F398F1028DB8238E3F52BF3500CA4D44A6C6DBD09CB2734D9B2A49397DD972AA043F93E5AB8B3CCC96BDF99D431ED7F60D10F5E3463763E96B7AC4F6C7D0ADEF7F36A04FA14BF1AA3DE521728E6A60238169BCAE1F1335E84A9BB4B62698A0031C705A49D068FCBEE79D2747DB414A17F59B576AB59A922F92E5CCAE14E25D5164833242471A04C84388019BD3F575A9F311C3173AFE4B203B5D48876756E128F38967ABDCFFD627085C9E6584464A9905C84D0EB32A98FE10BFC198AC35AAB33DDF8D04F7F4706BC53F873E71196AEA07D4CA1F16ECFF307E7371DA9E90396C5E923C11B4448C89D6976BD68BD8E3DD573445AEA4EF48D85BE30C4522F09110ABB207E5FC2D01CED3B73707B870D424E3433A1B92BD63166273C2BAADEF20CB9CA59DF73D4F756F870620A5FBD7962C3A400838B5F2786291B3C1898F286B820F152D01374C1218D1C3E0628884BEB44B119976CDA484314F910925C487803D6D1D9E2BC43B331F85BC61FE09D26147DEC41E684DB20E1414FE411EC6BC505E8723A92AEFA5DE8B158BC3F2C37DB1CE44B25C85B9304F00AE1A5BBC9A +smlen = 3474 +sm = E00C24233F3BEA24976AEEBCDC9AC23A52174F59961DDFABD7BAC58484E33215C221DB36DEAE5EAAA6A73E802FD5F1B4F85BF5CB78593F8D493E6A2D01882F9D5F3968796303F8DCBE8B524D2CEEC39E51DFC20170F6A579B6A10D2BC7E15CE56C312860F2951385F66563DCAB02461C71429E24A3FC96063B5BB0399A4CE028B263D1036EE41618A04A55EFC268761BEA8CCDFFC510B2E059015F3E9A2063156B964F551A99C6512C59EB5B71DB87BB59ACC53BF34198090D495302E299B1CB683B4EC030C11F1990CE5C12ABD53139192AE8FCAFE56BAAFF2B3E22524B1870A479A44C934FCB30A48039F4045411D3EA510CD570EC612B424CF621DA22FF9607628A35961B66F8B12531EF4BD6DD03A3A3FC6460F0230CA2F2331094839EED715CC2ACD96AEC71DD2913F241BA733A10C577EE975382E8878060FE5CBB21B36B9B1AB7288B0B594E4E0BF6E7A1FBB87068505EBC340250213FD30FF4D08DDF57ED2BE636B2FEC6069524C605D1107DB327139C950E5A6385673836FE64F6D3E51306F77A52665ACD5AF31D4A7A106592D57DEA57F661D4393E797ACA16378E63253098C28308FBF0EE77211133FE224488567CC2E92F76E7CEF9EEAAC44483738F7E2A675A6599A036BAF51900B55C6A0B71AC7773820DF82E1502A5B5FFEEA794D0396478C6241335828FECAE3D7CA1571EE8C0028D232161802417976C95AEA5D40A7BDE248990AFD16F7F71765B882C97636531883A857ADDFCE2DF9B79BD9CEC382796EDCE5C117FA9A19E6BCF47199703BB30B7ADE588600F57F5DF51AD8C22DF0FE9C61BBE38AD5D93A41AA8F5297337E663FD7CA3147BA48F00808AAD08B1456A29E3C16DDA9C3DC01AF06C29541B2ED15727F3A1F0A37020FF1516913BF9080A669A9A851342D586776E4330C325218839DDF28B32AE8FE7D3114137C2AB919CAD84C96023666F18A91C9B7121F35892EEE372B6A20212FE4AEC662ACAD6925D43FF72B5F913A6E6869D286DE7FA3A995CD463C73122B9D01583214DC022911116693CD3C641158C58E5D59131DC512FE5AAF24C4A7AD4758F22B55EB1449E0605B9D3081B65890B86E8813C13BF66B1E2A11CC88D085F1EB2C6B492FF6E3A37BEB917D2A96D9FCBC8A656C7A13FE01548CD7B0D662E8CE3DCDAAE1B44BB5F947D99EC1F09646CC36204DB00A5BD603A4E65DD9709398972F8881FCDD025794A0876E57A407DF1761BAA59F355DEB87B70BED64F4A485610D026D94CCF2269AC6BC1BDE71D894D4854737C3D2FCFA8E0CCBCB2271D5CDA9E84F0DFCB19AFE4342FCC8F2E6AD5864F3B03875281BA236244F0E439F97F0F9877905470F209A6EC5652AFD3106FA44975A6BAE572FB21F53813ECECA2B9242151786641DFB4D3FFBEA06CE89C9DA9B4228B80F7B102F8ECB2AC152739A91545440E9BCF696A77C181011F1BCF0C3FE898CF5EB6C9F791D429B921B1CA058845290CDDD29F876DA3A8A534E11288F07D09B9C248A84360755D092A9C25CCB338E4C20E5894BBEFF8D3BB4F80A21346113AB9173141BFE0C5A0CF99EEB88524D9D66F7A690FC806761F1F1E477B02BE85E1D2051AB201DE645A0D3E9DBCD9D247638391EEA46D644BB3E879DC4FC0BD3A9C77C34315815E7F7CB7D22ADD54FBE0289C1A361771BDE8991D6A914058F769135AE0B5CD14CFE74524624C8084E0A13658D09E6C24FA74F9828A8AF296B4C9A07483D7B0C480185474B351909ED6558553853F9D9F652D94B956A68C3E60E43C0E54A24E45D388D8F35D67A96711DC4CFE62CDF45AE2DCD9DC9AA4B594FA25E5D8684B217A43600E06794B3E2D3E7774F63DB450F6856378FDBE70609AE7FDAA3357EA38FF2AB995B04231DD4C3C8B4255ECBA1687DA8B40B5FF9E598739D5E0891B6B7A3AB2DBEBCB64013856DB6A9EA303D7ECDBF3F8E717EC69D4132386D46DC280741C02C5E1A3AC2B29DD769BCCC432D69AC3B0ED7F21EDE3D5A5C82B4DCC7E37D505D0513BBF623AEE159417AAE985163DEB6C6FA0AA794DC01A25BC3CB1CD8C5467E9AB75DB3153C67DC0E45F8B6D52820666049631E4043431E793E7DD6ADC694C06EC3882B8D2A35DCAB3FB689632282AB6045B50C12B8D9A3F1A7D471E877D06D618ADE2199B58E2A1CAFFFC123A4008482628675AD2AE8ECA3BBF76A12132616B040272AD569A636F7C1E7F165F8F2BED022C066A9F148124A8591D6D06158AF584C0EB92DFBDCF379C606058F13B419FE0401AAB6FC092CF4DB852ADCD1AADE8227CF3727739E2BA3037D7EF37E12B682F430677F0D9EAF330166A368D935D2DC8B36D58F90C7BF6DEA4B66D5F564BAD0A9B11AFBEB0E15A05DA7EBB64D13EF6198C80662D9296C49CEA8EFEC3C18D5A47991F00F268B79728F7315ED8E7EADFB55CA3658546F5C36594FB3E2808952E21D27D00F2C8CBB59D038BF00EB6E3BD610781DCE25EFA72FFE6F8A5FBBD152417D5AC546951586E2FA33B40FA9FE13A12A8E74A15C4E76CB234C965B6DDFB6A0BFC84C8792EAB5642DC2C893893C9511266D43CC1A76296639B7566D11919C09693EE8E5AEACA28F9BCD4913BE71402DCC9D45C948814EE3F6FE6B8869F794F4E9A7E029F646A6FE094A6101E16C5BF4124A2DA15E06B89AF636B2322B67ADCF9138908C48C1E72E15F837EA5CAED98A20CE58BE1AB3E90D48AA2AAE44B9C529506AD81775395809FB5DFF6A899C608BE182EF698F8CD8B61922F63D8B484B1EE6FC6AD10F8595A5C0B5FE6F10987568EEDF9D322505EB52B8F8FAC9E3EF77D9B0518CE48C5BF215773434F601862B6545BC45EEADC961F731BAA4D89A257B57CF64B699C4A835E0A7FAEE72790C1AE11D9CE1430271E8BEA94018B29791E7CBAF1DF060DEE23B26865D5C660CE11BF07150874802597E0CE0E9998A93330EB93EE598E6E56FA649564BB6AF8B735AE880A9014988C95892A46843A23E64FF3DFBABECD8AB5F463B112AC704E3790D5A64FB7D790596F4463A26F9468AB6E4A4255A20111BBA64F71527E6FB432C24B7BB39CDAF97ED4B8409CBFAACCD891A265334908C5D4BDEC7AC54BF1E9BC492BF5366FE1C5434F2106217151008B7E20DED92D4BF25ADC3965477B261C966BE0ED2F805010CB23837C65A34DEEDEC76EC594D7177B140851BA3CD08F40BF59971B73F350D92273AC4E029AFB4F371B5729094B01FC3A24C810492E0A38B406DEB013EC2F30805BB899F2D8100E3E92E24CEDAC17B4F97A9CEAF9CD88F2597FFBC0FF0E766BAEF18D4B6143349B4B2DDE23CDD8A8E9478A73A2DB1C51C9114E26C18303E3E96591F7DB0A297A94A1BD00E92DC5D734DFBE6288CCA5FFF276709F83A81B89C3281CD6ED52616D4054DFA7B702D65769C1190CEA06CB8CBC082BD380D2096D722408BAC4D7640CCD8B3DCFE04B3945899514DACB3B6BC6B03FF7B5DC3AE59664CA605EE28925E5B1C26052C544B42FF924CF1D6EA8FEFAE7058A48923C6AA22FD1F2E160495C7CBD86A0E84D08E534A574D972A7A57369B4BAA2C25648A46D6383C23E94AD0844534B9F84CFFE156F3AAA610BAFC3B797759E566E60FC1D1BEA519923924E44EB2491573337528C6FB5D2560B6BC34373D6F69C4BC5C565211229FB345A11C930F5F9AB0CE16004BA4AAB5DF0BBA56482E9C8AB0EE59F6262225EF6F59D1A9A426D44FF6A417613370C5D0F08269905BF94C151979240B044DE1665FCB8F23698593C48C7B0E3BC4E2898063C761F0649FB5824D4CE04050DFE8E8BED0FD9D1BD7DCF0BFF39E51B800B406969DD77914B6E1E93130969DCF11D452BCAAB669898EEC451E7A01D6AD3BA08EB399CFF261701B9F004981B9BAB5C821BCA1887AB9E5F5F514A4F2B717113B2DE06DCF170C5D374AE301032DA516E52776039E808DDFDAF601960C8ADDF08DF602488A613C1A452C77D88C7355872B61D60DA9058842FB082101BDB625AC4E99554AE49E8881A3A960EE578D0F6F630EB51EB28245406A7FC4E43EA3083C3DE6AF6D0A162C629FE411EB19EFC5DE19444DD9116047DDDADCFDECE753D34BE09EA0A4B6D40A2BAAAFA7010908758E071D0564EEF2B0F574B1E5FF3F8C320C8A1F4D945CBA26CDC55DAF160D046C49797B7597C06B7A692502F141944E4D5AB99E6825A317A48F98AF585A35C7460A9C175E31C64BD1CCBD31D5816578DE5CE31A604BCE81303FA27958B735ED2955E72D1B57EA39DA4D1458C9FBAA5D6190A74462C8269EB18EE6B21F0E802271BF5E454BFB4690B79C7D250502721263B3E0812F0A77532C1AFD2C99DE562CA3D063A288CC3BEE23BC9E046E6E744430AB16412E901F6A679FD21CDB0480E3A1BC346191870F661286C66D2AC7E183F4E0EA7C2B83E12863A63AECFFA473B321B3C413E3FEB8BF507E5C608BEAB01FC17B3AB8930D8E8DC9CE1F9F2B357BD8DBD44E2450B28549B77BAC03617041CB65B8CA789491771023649E5311C5EEDCFE96538D35EC1FBC24E2786DCC1BC28C204C143E9BCAA9A559BFF4D1F87B8ECC0F94EE3F70894A0756BAC80A852C70ED331CD812DCA61BB03B0224E8189B2C449647CD10B4B73A5DA3E535DA6AADCE8464B5F68787D950A296FCFD2D60000000000000000000000000000000000000000060A0F161D231CDF0AE1124780A8FF00318F779A3B86B3504D059CA7AB3FE4D6EAE9FD46428D1DABB704C0735A8FE8708F409741017B723D9A304E54FDC5789A7B0748C2464B7308AC9665115644C569AE253D5205751342574C03346DDDC1950A6273546616B96D0C5ECE0A044AF0EDEFBE445F9AE37DA5AFB8D22A56D9FD1801425A0A276F48431D7AF039521E549551481391FE5F4EBFB7644D9F9782D83A95137E84EA3AEB3C2F8099 + +count = 5 +seed = 75224ECC026C18159FF92256844D0ADF953F0A4DD8D74D4EBF1DC5EE8F5630B011A447FD4DC34A2404D620CA0E1F273E +mlen = 198 +msg = DBE5B6C299B44F8D60FA972A336DF789EF4534EC9BA90DF92AD401D1907951EB6285EDA8F134277AB0A1145001C34E392187122506AA2DBB8617D7943A129EB5C07DF133D7CCDE94A7CB7F1795C62493ED375353D1F044257DA799F7D112C174FBC35687E2F87FEFBE2D83D29D7314B30A749FE41B1B81095638F112BC4563420AF235280E466FFBE7050C4937C60FC18D1A6025BCBD489F0C538E088E906ABE8597E2C8EBB64F01D225C847AAE4B77BAE6EBA9269962C4B94A9732CEAA2CB4093D442FFBCDD +pk = 2B37777152BEAE15CD70FED3C8DD2819EF9C422043F7AE2B652C598258FBA80E873A63FAA274714063FA1DB58E9D6C3C6BAC0260FBF130D6D8459C724D17338B6FE3C2A33A67498CFDD9D8EA092ABA7FA4F2D686E1B58E875D3AACD9F81BC69651D777EEAC0A6AA8954CC64B038F8BED58DC2216FD5B0C730E1102721B5D3977E9567619663D5C6AF97DDBD7F5A136C8D28EBB5D3AAF9ED97D188CB9C8DF9B0B96F8AD992153E23397AE9C293317EE8779E06EE124089E133117A9DCD3645E4BC00C09BCAD7DB238236CE9B207CC6FA5D80DBFE4EA3D10F1D5BB32374422DE8C2F9AD7A22F2D432121FCC2D09843F417D41177DC0CB3F1D83C1034AD5B8C3DB9BB3E27ECF7005B273A78EDE81E889D123275D5F660AB52F5CC485904F37F684FF22B92CAD73A2691426B069BB24631AF54629B4DB10E4F089AF5A225E2B1CE1799A15E60940693EE6C44EC1DDB6C970BD9621782731F4470A3E067D8E58E1FF5482D521F922079862F652E2EC4C0BD4F8B54F275C27F3C4BAF0979178190F4D0D2824A0AA43E5307C41EDBF3665214DE8DA7392A350B0017EB9117BABCD937E385256347FA31F48E9645D25A18EE3201C7C37E18F46A5D5C69F0F64CF7F15CC039B037E18AC17B46CADE9766CBB09444E49B8AA2FD625A4D4D09454EE880620A5E354D3F049CCC78F8B31C97D6EC52B2E8DCE1FF89ADC61AB6DFE907ADA8963DF5227392010C217FE68D6427EDCE2E3EA5189BDEB6FB0CA1262C4C057150202F334E16BE709F9292F00B8A11E6458A5F03F9A6E1184ED356F3596FC7F1F293A825A4BC7266636F238B4134DCE8374616E35993A9E48EE06235D1F035EAD9ACEF19612908188426BF618DC01357388D9C79DA174202D7FEABE28867B58396276FBD64A06F8E99A49D9214E5114DCD0B565FD76DA318E7FC6686CECE3B1126986259FF39D0E68B9C1F7F316D383B033C85729ACFF1D76FA76F183318302E5DA7A0032F1CAEF513BB91D7D2D9485A26C7A004B4CE3F7D99C8D89F031719CDFEB53ED439E41BC618CD48B8F3FA5B7A66352AA892A205300277AFDD33813663B16099617F3EDFAB5E6C51D98A34DAA8CA38F152D6717A9BC0765C466FB184CF3B41996E957903041370B00A94242E62ACFFD00CA6A69B59045AFC0FA537BC85E671658560D023833699592F4912ABB62CEBC81C8F5EAC1605AC81E0E562E3EE567A30C805C91DF9502724D2FDBA30AAB707774229D671848CBF82C1457553B7CACC4CC779717BCE1913D51025ED27383CD1D4E346206E9F5D8928770EDABEE774FC458E4099E38D1E007D7E7E8228F403515D2A036CB173362273BB83D2CBAF482FED898AEF23160FB3C925B5C82D1952897B723D680B2CB28A0C91425B07A0386661F8AF6E403A0ACDCBCFF29DC8BAACF0D188E81C29C33098C679957F2A838F33C0A78BD1BDDEE5262C1CE5E8D3F22D976DE94FD8F989C8446E1D57561D5FE5219517D3A5A32035B815D89E195898F85D6E2A1BA0E986D3960AFAB082B8915E4CBB64673279372C51A9FAC9D029821A04E38C7695E6D7FC82FD4B93F3E1A4ECB2175C015CDDD20852599380B195F418B0C0DFF4E2DA47FBF0C4758E13022899E19C27CB035201E377AA8D23201171C1AC8D09DAAFE1BB4BC9779FA37066A3BAC88736EB86669BE849BEBA8B40A30964DEEB06DAA75901C24F4679D242D97CF14430E14A7BDE29607EA3F275CACD9F61E319AB79AE40D2EC9BD11F7A52FABDA53F75B26F9CC3FDBCA3A7B551CD47446EE3074A78CF9836386A199CDE21904806B783AE7976578F2EB1269B8939A86B053E5B885796E9B2314FA7EEE608FF3316BD9674417CA37AB851D2E41653C044E9377DD4305944CB0FA4C03BE9A85857A8CD8E099E8880396C52EBDFE55BE054D4A015A107826C7071449EA3419A4957FB31B04CA93CD0A4A65078303514E75E197FF98DA2A79BE1671A99BDB77CF1D0FFD9C6C3F3768CD774D21926DCDDFFFC1639E243C52D865FADCDC064FDED24A91E8475A5D0EF04620BAC08B8035724E2476DD01C5F243C061F5FD61167C23BC3B5F6418A53B30227D5B75B7D8BE7F78D1CB496F4F524096F4941D1C45C339D05DE223BF62B50B4D3494503615397EA92D00FE368FEBBA3953D925725CCD6B021A81795A8AEEC39DC4390CE0D15AA1DFC52F1C92933673E4BBCE462555DB0E75C0723815C516FB9F1B7096A80C33422922342B4D75A683646B933CF7E896E466F0D91AB0441B7425253286DEB80B27098D472CBF2425C9A1B836D850EB9A4CE1E1EF38C5F64117C3A21A685FF342556A231EC8CA675E7C6DE3CE1C5B308BE3C1C4F3C5D526A0E8E0677CC483110BEC9AF5F6CE26BB0E6573ED080ACEDBA79BE7E96C13677F1748A9EF32487B9DB3822770E369076797CFE33C96EDAC7C1F0F008A38235642D5000A8208FD80B77C2B46AE3E79ED2F9E5A583E8A2F79DAEE61D6BE8A1B6F05E1C93BAED689B5787A22E07DEFDD3F9E74F0121841CC57D7CCD2AEBB2B4EBA340742D75328BC4FE66F403D7346B5ABBF9311993B905554D8ACBF96A6753FADBC2E563F89BE4E2AA1B07E4EEB71C04286BB05BDA30C6BFB5369DC08081C3519EA6823DA78F1C8F38358B175FC5DDB88C2B37B85C34F0551C8DEDB615BF8D81DC6AF28846F23F82452FA8B0B660C4DD852B458FA501FF76DA0B4D66EC25C9A3D4A504BD8B4BE77946F55D0162E1181DF20F96487EFD6B2AC97EB789B0B74B70 +sk = 2B37777152BEAE15CD70FED3C8DD2819EF9C422043F7AE2B652C598258FBA80ED069224410558918560E4203345E45BB883FCE8D87502DE650741469265B41F5BC48DC59AA516874613F2705EAF9636ECECE305643C31F2BE043734E172E1F5A76680853F2C1F5026CC458B6535C6816AE1D381E31B6ADCBE476D648088EDB59030108405256352288538865222141655177717346752675840732876483056607057361802874385473552652685643385257557823824600485585606574230650304383618508886132044343625315160766162036643283014815580101823102604470081614232551532745541636710336225880280502631585263633887826357733167467742062888183145447351300746435252378036761128382145672787462321437145532033341875802332476168481333786100610456456214281100526153861260514804627740757532341201143412045248127747180683640521377516242308781660522073572664621511620406478663386581572370856762350381006618662404855232230687371076460613776487625430401430745042528451531853434561313208055566460772144456264512043487246227806646662236302818281612464187337120538508364418027871105476787205182062025035421532672717662878653053174863136084736068543732764012003320807366810073136648521120773150767185245155822417774012047340427537121581217810563810750272486818886060247148160764156053512705613566630027105264372228351511334164452617514130376460053730207384085738042605464047571331601530271264878153428507544055071210581240881722328861782388302162181673514246266522024706284458507654353340360178173203520785578176375564471118303080302382408232018667661505120171874183235576627078442037204105533357537701255278608056518255841035301426031153423560480853081173128385175754751763065287248060628745470127413267340470863051147621410114368536848466502845838156676216477624483124663827807531455777565012200207605010116416060385228852403263081850100705422807782421620575743333544202207684057301456172401243660280545153015104178055605742181206567282330142414023615406373227342485511838254020762754230286100657623870284713114301873021250774154335144231484246416630013115504782226404826081442284032575205042724103535464628740743773448262731586152003731764754287040768130305614002546684076188184006142441113217326585078886354557204505557377186121518331220378602200781460083046717584271681176274247478456618873341447317030880277228521447687354180061222042476646265334824426428438286108100367243233043724654332310186813223173030201086681880318081817137006104320251204418816724358603630404476067572748228054246703245768046080816420710200671733204475816122658223331272826541803061534711088268055054473534158150603656336220501737167202703648633246346822170214105146704600227228071840606307220668628784030467786187122258658145610842511764454846458863616222274142106846551108361778641750511643524853504084774551780757682703037350483504320135162611361710248040872551328316645375004518488281644227851021237406061047231050873744637605480568106066115224364236727636854807586425203520046002155358782020301682214103560457536786227837122842183234206767182573716756608808046121178271681235854778707176724547210802785431827036304033043327125333013876203485433073656404736104850836535063007452206213437634843518676172F1CC0DF4D56D46494853B2935F2D47BDAE3E84297A003AFC0708A76701909BC06703DD112D3087F86F6E6CD4CE3D79C0923073148A5B061A83FF1E7C51C8015217406122748ECCA2E9825895FA5DE26A609169F3EBA26AE821F3BFAB431C50FF246947E1AFFCBA323D77355C4DF31D667E40473CBBBA17FA406AA2C82A2A93B7B7BD3C085569C35FC3B29AA1868677553EE4009BEA5192CB2265E8CAF29332DFB4E686484F6E0B9E08BC21DCA8B784083E9FF2BFD44EF0E45CECBA5C2B1756E68ED0597F849CF4640F5D6356CAA167313E6770439F592181BB3E477E2C8103521AF41FD72BCCD41B26F4049E8499BBD1EB541519021E5F02378868A54B0CE2E240FF1834C9F36710E2A55825A8D5112A4A76E637FDAB3B83863492F26172E58ED41A41B81B30CFC6E26913AB36903EFAAC94E316668664799E405C1E7CAE9506AFC39B3DFEB1C52B37857B53DBC08C145D965F0E9E3C1E82FEBA478FF1635DD5378F246D7C2F7A9E2E24B7B3A532CD23A9144832DF3120EBA074E5F83A0D21BA9F9A824515237BCD2816E96958524DFA557BF849FEC90B90E4571C34A61B90A061684482AC9316B6E69293555F9F2849043F03D5B5886EB158726597186E542BA83B7C232776F665B01A680FC1D55905E089C663BDCE4638777DD25959D024BE7886B9069545331690567E6683ADEAEC9B0013F9FFC77432A50750DC5715B48353BC114E5D1DC57991EC7BF464AFE5151EBDBBC893A3FBF88D3A5F194EE5065A027273B83FCA8837499F2F714098AFE9928C796F132CEFCBBB4252CE2CA491874B9EEF3D147D205725438A2169994DAC894EDC54E3A173D93D66A9E7349DD012EC93B4629C48E2A1A46DA5AB4DBD3D06F3F75269E552CE018391A550367B55D2897598325E0A44816EDBDB767910DF12A4529B5D02E5B37214E25F2D5B4AE40AA3AD3DF984C2B3CED34263F97172E2DD9D7AB2647A1603F55D722631CB95D7AE286D3821B851098757D03163F1EA60DE116EC74D11209218F4A3AF03CB99790B74B433A32B45A84E7F056ABBE71D9D6B1D62375B6EAF2BA652F2DA725A9F35EAA71ABA6E0B9DD0998B1F873143F789BCC6527FB4317A346E7CF6E34B444E34488503EE8FBE0C1B66F69C84C6C57E7B59B014500FADB1B992D3EB4064E936FBB3E8DE89D99EDFDA0EB8C0CAEE0DAFFF568C1E956CA792E3A130C25C8C73AE245F38D5A7A6D4F729D6939DC62EFDF457D5F8996AA2D42D6DC4A2B7490CD749E6BB833BDCFB6D06F98873FA7BB1360DEE367BF965918B0C3C70A5412E1077793261BF0FF7C771BE6501CB531057927F42503EE5E56AA4328F95CECABC644DCFC85A261E2E12FD5032006B7F3261C15EC3574F13A79A1EADA66CA3EB306116E406FAAA534CB85E5C7DDCE97C1AFFF639CCC852679FA04AE758BF6BCB5935B1561AD2E108C478A4C1F8248467BC42FC8E0313BFEE8ECBD9D164D6C2E495D7608D8FCF8C8E1F9F7428BA7057B55DB3CFA16E372B4458141344CBF38A5A97085E67C8DE203E43EB17CA66D9E59A5FF54B758E129859223A5C732D2DAA91AA7F6DE2B364C3BD73CE1DE32E2D7409E760FBC38F46DB5718534DE07D295E8969761F22070DE300AF43C3E52D3B73A9BE4E1F05BD1BB1FA81FD3C89372A37CA54D2433C79D8B7EF4D653B2C9B1CE4E866F801EEFFD889B6CCE8566023C97E3AB2E92D512548BA07BBDFB877B64C5F92204FB4D3D0D9B0AF1C12AAC607F317F7238C5F214BA12946E742E8082CFB743D31259DD2DADB4A261BFC6040DEC9ED68166DC0E3305B473DC95ED915255BC10F32FADB3EB59AB0556F3403DDDF40CBE09C740F2E5D868FE63263AC2C1C59F470A1B1E7222C4F491C2CCA55C48AB3F0E8B214A6A846A61CF81ABCC805656E9A967F03B81ECC90F499D19A028017AA202BBD5689F5AED6EA8345A40E698CAE8AD03E0ECBDD6DA1D02154177225D2365BF8561E816F5BBCC5171BDA780C70158B86379FEF237CEF6D26A83643632594F60DD6DD1B07AC5A62ED1E20FC43A920EAFA10674972AB6515576DCA17D3194BD5DB129BC79A683DB7020BFF81450CDC73D51F27A5C952B2744B6C65C616C1D2CEB646EABC4AD0F4AD5F96CBC01B9B785546DAB7878A2888FF236121645314A51357797F6D2E0957B62F08AFE5A28413775775CA52E149B91F13C9A741586682FE82776BA7E143764A7F5ADC9FC73063F83B167BCCD528159516BB6BDB10EB1251251444C04CBCAE0C3EE1317B547113E45F5510AE55C6795E729E24AE32EF45AFE0A34D0B41FF092B5ED724316727132EA1D8444FA9FFA4FC127DAA759519079F7EA11683F552B6D208996D38E293F86212EADCBF752E1160C26773E186D48D29B2ABB953B1F5FE7CB6722286BCD635E5DB19127A619604B04BF3288FAEF10C9405A556A1BB63AD0C623E7288940DE860AE27B9C3EF110D097CC194845E961234670059BDAF6694F43FB0123D3F897B57DC8D805A4C4808B84C3447C5B69272CFFC9163C5A3503ADE6A39FF7460915D84319720C0654D38D5CAE49A1B97A6EC9C520D4C554F4A4930BFF1C5E146B0CB5D3BB181D8F2F6542F3C6F86F158099AE57851C0B71E232937E2C50BA70B25AC140E03D35B4DDA52F7339F1EE66D529E71E0F8DA5816C719A6B13AE81325926DB29AB8DA8704D0A1511982F13C5B0232F96536E64050A714F8464340AC501A56F80EA45CFF5E6E48CB0E3233D9D348C8839C9D2B8A20791249B0906B18576B5F23D62FAC92C6CC0A3AE22C66656311B2F6E0AD14D8005961CC1143E7DF74711B9C4AF5EFBCA86B051F5D6CF7E40CAA3FCA94409DF1B88314B3A23916E8429A4124755EF28C1F94707556B03598E982CD4192B8865994E1BED2C8D9623E82CCD8D5E5F4289A7800B7B8F44976E45EAABF54C1B44CC6C1BBF8BC01E97EDED1760D000500E848367E0358DC9499180B666E384756539562811063B4C5D564D4A88E8B6D12E385025063B1BFF26DC62ECE374BF0FDADD8B238FC963D36B0118BC629D00A01DDA0A2258D1A6CBD4ED11757D9ADCF359B2171DE20DE0FDABCB3CCD087D1100BDE8B5D78E81FE9C38537BF9E899FA2B56688E10F4680005960E8FDDBFD645100548A5D6A4E6F2CDE37BE337781E69B7B2011334B0AB5785C30B79C7DF696FF596D254037F177FA6D306A8A9EE45EC0724A423BB034A5FCAD9DFF9E527374FCFA12BDBCA8C81144798C0960F28C339DC31951695AF3B5ABA1BE840CD7C0AF156899F9B5E79EC0F79F54FDBB0BD1E6A1D1D294D2712DB79B607DFDAB7996F46D6A084569BA3919972C9EB3C48664919BD7E45D3A10A7374311A974CA848BF771D3BF307E6D7F5B3243A478E32307D9A3C8AB8BC70EC7AA97E14E04F3D35D3969054365BF6B561DC62BF7F8D62E8B9742EC837F55E35229E5C95E6C0ACBEE8A4B4BD6ED9CB51108D210F8F9AFAE0008EE93359F94F7FCD3123DC0F6AC84A9FE029D5F0EA601E1D1F8C893FE7BA686AED1F7C64055095 +smlen = 3507 +sm = 7D4457B612A615D90CA9210D639EA6F7788007119C50690A045245BF12CA9CF5108C64C299E81D47E1EE9DC31CE9C06B51F834FE680108AE0F65EE9CDEF74C09F7DB96654E6252FD27A0F0163AF48F8AAAF21D650F996CC13415B10C9FB8B3FBFC9D3820B0A6460264A4574C193652AB30CEBB580C836F9A5B4C27B0C04950F3B1670BD879B5A3799BB16F9F4D8F236EEF93789BC3B9943D6F89305CFB657975EC75B278BDC5892C470FB85B526D6CD6A299B62EAB7899F3D32B84BF0B26ECCB280762C4B06457C6EC6718023799D0F11ECAAF0197E4331F8F90DFF839FEB2DE8B343E82D523582BF73F8256D507C1133FE53FD00FE3CA2FF5BA3C8113354DC627507D1C49FD418D44351348D1627C419D3F7597D093BB40F3BDA1FDF44455F6D2D791B8374E469DA02EC4DEA4E75451F1C033B25DC3B715E3094356D3C6B6EE4E7C6A81BF92F15CB8F1FE89CBC38DFF165158E4ECAED81597652341BF50E060C992A9B3092F3F2F648900D58D9217C8C06A047A93982B38BA85079D69F2549D6CD1A82BAFB78FB8BCBE5692E04ACB4BD373ABA022D6879A5D45F131F6AA579F67EFAFF59B781E7587F44DB1650131DAB22043E094891C3C7275C80B36D32F7C40D0CCE9D26B98EA91B2B884F1E0D27D4698865E7D869500BFF389ADC7793513D9F37E45CBC3089067132B1DBD18C4BD4CA0866D83BB38EEB397B17076697E164D46ADC50E1F52273A68BCD8EDF4CFFC8B8327EE09BBE77E283DD46AC2136F5CC45571F28FBB43B625DB90C78CEBA6A43784997952583566451A0B5E09BB6D2F631EFF75516989FAF43EB4AF274BA6CB0661E6CCC61106E11E93FCE9475B8E40660F491B7E75F1077B2273BA30DC7B749FA100A70E3D8695563A692B0CDD8913B001DA527A71D24A270BF3EC45572318A1EB0B1B2A1D2D9E3196434FA2B22E4B4EE9A051C9A38B9EE72E2F4FF1FFDCFFB8E939940A48CD724655B169AD4151345CCD93D3070DC3AD932A3BBA7D8F806DCB2308A71B1C38881555C34EAE29CCD153CABAAEFA489F7854F399DD20AF94FEC74B24C24F623BB7599C92DCE5F8072A562E5BB8A149FA261150BF45E792D6D502A2B5DCC3AA961DA635F6DF936FA6D6FC7B5C084A6AD35FC31B563FB51D4433B2A1E480BFBAA7DCBFD8E9618E517C9AE5C8EF0A5B54B822955F42ECD4A622633A5F5BCED873EE62D78E32B478C4390C3A84B56DA8F7A5A931D5426DED6253645A2CEB51B4BD033394EB48639F609639410BD92F1800B988F91AAD57A899661FE2BE64FCB5F9526783F3F7171EC9F75F04C31933E59D0FF3C89D265691B7C86B1ABDD65FAB75CB3D61C744881F0A94070A9CD12B28F53A30360802A3488F27F4139C2D06375AF8A4CAE954A7FD345016BE4DA05F87EBD038889518F1FD9B25903DF4CB8D4BFF4FB385B034681EEA0165DBD6BA7B38421CF2D77D6C517D4BB92FF66CCB49981CAE884A52D4813C7038EB42D750A5BFE3E709648B7DFCC46C932EB05D6F214498BA411068179D730A1EC9A4BA840A5D2B6802D4C2B421AEDC3DD3A49FFB8B6E1964CED9C2FCEA51636FEA636C0D7F581AE8597D7662DEA001B2721ADE26FDD11AC0A479ACCDAD949DCE7FC3E412D01C83E5DA214B2B891B2FF99EC79B997F796D9E6D4F26B1D13072EDB6063C14384A58F6A62C0B56C9F42510332A5E7EDDDF132660136C878B216DF172FAFE9FCEE5EE827A16FBC3BC79B1B8A16A3D6BA93A71BE41730A5E08FC9E33FC0FF88D5BAA87722CD82FB4A59B68154381FAD47FFFBA80F1F72C856A5838362A646676DF5EFF434A1AF61DDDFF888556CEAF6628611213BACF77154FDAB2F0E41F0F1F1CC868DA289EB5028545D1ACAB429D1D90464A1571CD189A9FD414FBFE95309F92034E59FBDED97FC258F0562C74E40EEF579E8E9AF548D278899B79151974E95269AB6C5B752561612E0D797E5CE23EE4CECE61396890740F14E7CA29FB06C9A95921559E78C485826261AE5DE4CAD286E34B604A24E59C93C46B83EE1787B827D0DA9005EAE60679B9FE37FAB6298F605E1B48836CCAED6293A5DF7C1D715334B5F806C017C63CF9E501514BDD66D95879BE0D4D42B69DD977EA2A8D34F9B8C3C44DC4AA27DDCF7433EC10EDC7E4D61F8068B5AD90D7999A88AC0124694B8C62245D22ABDDEAFD4894F313C314A9D9F2276B1B0BFDFBF62AF71650D6A09336B8C134CDD4F1A771848E8607E545F3C687BB28D64E3670E8E34D8CFC71B4D6EFE2F1A521B7490AA67F5C832CC457EB67A23765298F488CFB0FFC28C7A784DE8EB552EC7D44B2946583C923C8ED442244B417BCCA6535546FB3C7AB579F997A9AB7A64F5AA4E09B9559FC1BE68056544C99CB37B0AE2849F9DF686F94698E6FE4288B1F1152FC2A67E83E3A53EC53FEAF8E80713C0C49ECF9E22DC17AEC5AFF196FC4514D6308BCC14F103478021B62E53343625D319F797A81E93254138313688A942EAF52B71A210D265006064A818877863784A7129B6017FB960D577C7B8F976EC457516E87BE1B3A1CE21D09B668DE86B2F13C70B54830E402CDEE865B02E1ECDCECF81F98417C05F936F4C719D7C638E0097B845E21E2D1FA20ED18F02152DBB9F7534A63C1295988FE11169CBB4DF34B4EE96E808F8FEC413A389EB26465E65703AE2EB0948C0B942EB2753AC58DB48340262C41657B0AC7F5C4AC75B350D94871D4B10A6031478CE7FDBDEC1A99F7F5BBDDBCF7AD2649F59F6D2CAA7F47947781D1DA0F3AB3A410FD05E08C53CE101629E5CCF12165D6B8F200FE9B24A2EFC8F8E5431DB3B291FEB640BE3A382A407EC4F4C21D3EE9D82421BA81DAD0C2340378416D9CF645CB4F1436475B58F8EB80806818F09793A221AD8FF81345CCBDEEB1BD28EE8BDA1BF53B56895FF4A52CC65FA87733544E40B6E85FE2CF895EE93C4E584F76F8C5BE85E6A2650AE23C0DFBDEE6B7DCF6406ACA9C4250AAB22A3B6D33A374C277C16613A1928AA06CE3D1D1E98862D0C83BA8A2F01C71248106C41AD878A635C094637CF43646BF1F5B4A823CDB1A6E6921C57AF9344B7A1B562485FCDD5FE38C5A3D34850EF0782AE339ECD20BFF9507BAEDC215C47308B8169CE577FCA4FCBFECB4DAA6E5752F165FFD9AD8F236F681B2F166528E76398C7A45A086B9D2FDBDCDA46E0AD8FE13487FD751F60C845B64B89EF8B83F34C95FC92577D9BC6DE5D7DD8558FC037181043E825B6DC760F8595BB1766CBAB65760A5B96D6CCD2A0E6C82D73A07DA293B1D1FEE7FA343716D51B4345B1BA6B2CB560516F69316B8ED53368D775B1A970D658F1163BE93BC4DA694789CF921609B982CD5A06F16A2A76C540A4D46CBCC36293C831BA97E69FFFFB9023CE3403B7186EC2DED46D7EA2F40A24573806A2A9D382E34F9059BED00657C3F6189BC4A12BCEA7D90844C89D6063B65948155FFDF86FD2472A078C1D6A1031153FC884092C04F68ABF50D1287D92F5E2B09B0454D4009CC06F9847BE6AB86C9003696F67C3C1F0C85F27DE9A32BB701778644133E0289D000063459685EEE18FC251B0628156AD4C8ADA3A7928A0DDC792AB1880CD2AD6FB24ADE115855AF7A5F045306B15FECA79BFD99F3FF1A5D6800FEE86015C66B8C2ACBF6A5986D7F429C4B69B2CDD5667AD97E028ECEF1C520DF70823B8E55E2C9FE459C86F615E98E39D034B65DD28BB22ED77ECDF90186B2EF817B74EEA54AC9E63D60BE2550FD0C724074C98A468127DB0ABBE6FA25071CD506BD6260B789FF3035FB0F79D6A301B4865EEE9CFECC66E34211C2B14FB4A010C1DF984120D0E9B76A835ED97413EDECF9BE6C3E2063B70A158AEF58BC1F73D48ECE65A2E1C38B8FCE353D7FF500B5B1A1BC03785FD9868BBD6A7EA5082C234F5CD925EC50639D4D61103018DCD7249D33A654387462A718011037CE9707A77A355DF5000E72B76EC13770958F97A9FC3728E120E2A30DBF31AA100958900E5760C509C943C4B13F74AF77F8A338EF10188CC489BA4311B11397505C7E517325AB9425C0A478D424F6BDEF735C5CCC2F5D79F791B333B3A8B5D8F146FA0018F420345F3177CD791F73631457FA4B2CC6A4BFEC759DF0545E8B9F71910A74CAAFDE362068085A0B2070E8E398C8FF91BC4348B1D3A5043033D2C10428B57405D719574C40C336128D9DBAB9B5D85E5C45FF3C71D716C7616E46F0B1202DE6D17DAE0382AE23EA90C2EA81BEEC2ACB0BB315C72DF68BCBB90CC44BEE2D0CA4B49016B16043FD97560FCEB1BFCAAA3281503BD5CF62FCEC72305E76CF1D935426D433A371FB295183D8E59B3780A0918A0BA935EBF72945EBFF02BB258442342570828BA6A2B4AF2F2B5FD8E37A02824C3DAE78E26EFFE44C8FA6B55A5AA6D2369598B21E0AF517F2DE78970CDB3ADD72EF2C419977047D18CF70B6B669B9BEBE8282DB8648E09669ED53D731DC2C3A075DA974E64E1C5B3DABFB780A4892A324279D68E12C962667D10E643497D1D8F04191AF580C183718C1C14DCD574BACC1BEC02CED2D3DD503CB7E072D2E26BDBDEAC50A7CFC55AF5FA42137AD25BC1845C79F27265E6F8BB8BFCAF97DC0E5EA161B3A5E7C8E90A8F11EA3C0CEFE20485F638087BDDFE72C55809BA9000000000000000000000000000000080C151A2328DBE5B6C299B44F8D60FA972A336DF789EF4534EC9BA90DF92AD401D1907951EB6285EDA8F134277AB0A1145001C34E392187122506AA2DBB8617D7943A129EB5C07DF133D7CCDE94A7CB7F1795C62493ED375353D1F044257DA799F7D112C174FBC35687E2F87FEFBE2D83D29D7314B30A749FE41B1B81095638F112BC4563420AF235280E466FFBE7050C4937C60FC18D1A6025BCBD489F0C538E088E906ABE8597E2C8EBB64F01D225C847AAE4B77BAE6EBA9269962C4B94A9732CEAA2CB4093D442FFBCDD + +count = 6 +seed = 447F03C8CD27EDAA1FA0436DA492812F57AC946479A9F1F90EC4F5E913A05F8AB0DD7645026A96510F6D40AF05D85B07 +mlen = 231 +msg = 0073BEE97FC97C0FBC750D474AEB93189F061E1A5CF6600C04FB0464338EC7E85252F94FCBC7B2BD00E438480D9AF3ADD92A92E3E2E8ACB55077C3278FC7503988A76E9B6062996B20889AA55B343D5A003C8A8852D738F955799FA3426BE5CCD3AA6B6EDA04D4884941FFC0B69C5ACF12B347A74D0580CC3335BA816200F87674A4C1D98097C70F2F27C74E94A661850610ECF4847AB5B58344F958C5719E06BA396225BBE21ACB0FDC512B885D391E11B0C0ED5CE6B5DD8FAFF91F50025C69D43072F7706D80D9FD786E1104125D79A5F4B5FD838815D44FC8B1AB678078CC174DDE970D448B +pk = EF2B7C90BE998E114415C25E5CDB04C90071A86A3A240DE4EC797D7E46E0F6867ADB5F2188591F21EE9C8630288546060B96945FCC94A27B667797FEE6516910B309D8919239FD806496DE5A92C34FF01576C46421E31F16EC95F336419DC0995E5A9D9B1D8B5D73937C358ABBE4721265F8C903FFE23D3A27CD8368A78F8AA512AC8FC73DB68D24D94DBED5D6A30DD61A6C2B0BA5DABC2B05A74593E46F8B4B9D05DC5BCF5994B44D733937C8CBA9D5F7F182EF6B087B55156A21EAEAC6DAD880D5BE335C3629713DC95FF6AF0FEF31797E9EB2E62412540ECDDF04C2F520F2F3C662C60AA18957571C91FC897EF6245B896D1EBD15A61741188E5421DFC8BD3766ED344FCC6DB74DF1BB479DA1357F319F4DAA59D72BF134AC5042EF94C76A0CA058F45FBD7C2CD11662D877423DDD90414B4E39DEFD402AA6A300CA7469F542B983265465B9C99AF8924D68F0D745C4E8C00BA80ACAABF68579AA203519D4541A4874B7CF51987FB63FA24DCE62964D6D75853E4CAE44CEF91E18DC822FE328D0F67D89C75E2433961B43D05D92A7C1990DC0434E2A62CE3FE886B5FB0833911198C6F539E73675264895E9821582C3CF0552430FDF36A2F5EBAC640EC4E6A14117829F1B02B28DBACDD18C6312668649B6199C29AC451F4946345B8CA1E7637AE22F4D08940DC9732FFF7450AD5955694B8CD5A4D8A7237DC4DE879CF3A176635EFC8D459A7F9AC93A6B3C60E355104A6B5FE3DFA1E5FD406E39CD2512831CE9DD12DB93B0C3DE41FB2D25342269DB2BA913DF099F5E9650E6E8AAC625384BFC8E6C69AAA6F69616CA953BB4FD60D3387CA9763E86D214D33168ABD3C06A777D8D9FA41EAE3FAD34FC6EBAD82495E495622A2DC2698E2F1A5E7F41D4E01DFDAE90144466A992FE6C65784C4330542D95501C1FEFF733BD5A4B2CDA4620D0C2785DD5EF5D854FC6FB72993A632D77F08233D167266BFD9A2A01D7B573F18312F828C2DC0C19611464991140CE6F6A234D3100A5B4658877AF2A671E0DBE9476EEA611EEE6C537A25AA33021B5DFD5599FDFB8CDB355041FA87DC6FF5DDAEB76055C319E0734DB9A3BC076968357C6D468EACD597AEFF8064C312B8CC5BE21E022631DB240A258B4143FFA9C061374869F0B7A2312C70F7AF4F0BE8436B5DA8CE10FE1F01F7130386A43AF0C3AE69E02C3E0CD7BFC0DEB29BEF62A68E542179FB1E64BA6F789AFED0629611EED8A8CCD62B4A6578E84A1C5D0D4A41740FA76E01CB9BC9BE6F40FBA8BEF806505DBE54A33672560051F46332E0DE2AFEC2AB70EBF9C8F8C6399B15557F8043FA6CCA348F37B6049159FD62887AB8CADBD886BC191746274ECF42D5BD799613DA7DEB9FAEFE36F819AD1764C24337EF2C61F36BB6528669271321B97B8D5152C037CBCBA9D4D9F0FF424303E7ABEC2315AFBB458A16FA4A078A2096EE858E297838D14FF97643CF343DA29A6F57E63847EF378CEF80DA232D54DB3AB8F8C27B582132E6D6AC853F1FB423416F5E687BEA45173C5C2A92640A1B0E842DF08EFAF093DC622FB18CDF0699CBB13819B70B56959EE7FF8D24D992AE0118B6FC996FF5A0C1E947E61C96D2354094A67D128209A432BA5C390554DF0DF52663DF3DA818F85E54D07AE53F271B0FF95167599B8DDA6086F6CFAD73D8037F4E2065B490EA0755A8B9800317BDFA4881B2FE777D2A7CA6D4F17069B7AC89B9E6872248A6BF90C66C1BB45224D82C490D3E393A3B5A7DD0F618E59C68B5431325845FB37AEE27B2CDC1411998B451B9763A94A96B84161EB93368EB0FDE61FCBE7DC313D45C38FA1ED19D1AFC2300E1C4F92BA728EDBC16702DEE14164787C051422CD4788BCC3719D3E4917B2DBD51F6679FE64631A53E3B2BAF442D63202BE165D457A2C9878E267558C0EDE3EE0C9D3A37831F9A98293FA126C58C4E81D03706D384B40F66239340C45B8C437A75150834801A3E22E0D359002656120C6D12B69330979B5E23241B010C07020FF0D4CA6FB4565B9D7F1649A56997F1E74EF660FFDF03679CF91229E54484CDB427960840ABD677D127FD485E10E6B9853ED6FAD836776A252A297C757810827D706452F85FC57F505016F4C7627B623CB197E343B31C1110C508055D0DFD650610E190F37149B38C12E600913B00B362E7265264DDAF989F06F11226DCF0862D021A9F717B54858204E862F4BE66DC40ABA39CE922D17407621402A83EE837FD2392411675CF08BF2C4D6E53A2208AAD1619ECEFABDD418A873B39A7B2E0D50A61EBB973DB11B3DAE25B352B42F1ADB609E42D7BBB2301E71EB04AEE72D337BC15110A7AE652F164E169CB1C210DD186CCA3DA1AFB7D86FACBDF7C559387D47048998609BA1F540F4AEF0467C5C734CD591B3AD1A183CEFE1EAA8DF7EA4BDCFCF2E6B63130DE0909752DAE12226E69E7E095526749634F8F198440AA42BD5AFF917656C07D025F8E5BF962A13A3880CCAFBCE6D5A73A325107F4F354AC2859EFF2C383FB5910D606E637EECEE852EA109C917FA1D5BD7EB03DB515600744B9524303F43F3270EB484B16F3609EDC0584CCF3C960165A5A8B7C88EB5C22D273416406054E3F48B9E3BF07A837F330E128D3648608A6706B3EAB644308F8B9AA011754CBF6090532AA4E68C55ADAB1FEDE4EB26A7E9C6536B4AA4BAE8B92A462A1EBF3C4694A27CDE98525F1C91C595660D5ED830849E68BB237E9883ED91515FBACC8CB82EC9B5E25B2E +sk = EF2B7C90BE998E114415C25E5CDB04C90071A86A3A240DE4EC797D7E46E0F68646E8AD249D003A35B39061554DC7C9B85354A15EDF7340BB87C988CCAC05982A002A15E9CBBB95E52C1CF6A6F541F51AB1945FEAEC779E432882F73E5D8638F195BFCBFF2F3AF785C43012E81D3A6CC6EF726446E9530B0A416246305E6C17EA57254504110130026731052444607877657323540546607346703150070068628423143816225634610266154084726862244101210076438557088080341833484223776474840065036881482066623283001114653158268048414630416274651224150672347136326366338143300676486613214324708876643747474402045605634202536472487047215872581886168548745780854207804780712607460808457030180355013122744275038184510108144638414758288846252486361843080251456580622787664462458417081575514653766571511665311326368374146378076814382746178077173016067682501336485388550434304354420323161756802834471577040551010623852678524027811344316025224326780588502447840358567116583580643083678111885010467868124570582228847224462705405473207710288833705313246641143136701438285762504024365218471436083607855001003757868683478577031212574733605238764404337131748804647811668401308788352871605203716264181157784222822533275863786420558718222342370510636285381548418021380741855304488583754454734446416435614017315286020205766334433656255278650101460466450111623326674741287700577542256133434626276168738831333522762676574167601360385684125374114308426343470543808873445202518678484534427107506224130403284667135677863830784535021448633120805037002117703551421130516004300117706668445378538777666724713620248154028418635540221588480824668415186625045460772424140744441103055751566220566051543757652265328171656102463780110364775453277143557883860463485527828242805636123805215187578787443442568527045188315200777626580637647772008848580555527728020834880867476031701850217042372633514081888067815336404566277374607873257564250426526676672003516541070232862700414226854874272844018040356783881724075471334824872154162582504744217431383454816354683266085075481326667715188025318618821045111442687522688516467370727725108068802271625018703264066044864615755881682058464233214752145232243540037837121017274456400231633814087701350824588407702144036680132156041428366761628535414863426453370007772535687308188773713858173508655582455406714352647413767082115062001130001735448787642818156075871445140267057666588807886385058206836167627008180474854208663774702420305884621150482268846586405324636616704427016178152340650321000607843233575301666757253051765368034624433782253740824383832371646773561116483570022373643185745843760522070423118484254722536231514346585782160455241046576612217861837165037848552223186840056154866477444132567050421571163685338454387632381268435460605877180157453640573235641402158725840858850023464625284374760488287654781583123662734345075738654887230704488704521756668133824854541602685157806441668003048186128534818420572560210041884411116853664027854633338337717822816552782320338465868823557332877858855444246548705517781253381065788736764063371207246774114264835441803530457532258124872414138428452260260087183581336210454578385506838415287162626826588470ACBF5058BC9948E5981B9F312AB63E71D5AB5B5D6280EFC8E0BF9E9EEFC63994B89E9F30C0204415E75F6F7B0A9C99194AD915EE30EAED5E45A85E8FF88C08D6DDE0DCF246AC0A45E6BAA2F07E6CFB2A30B594DEF74663E6DEF41508871795B04311413DE6BF933535F2316F65626396E158D2480DBBF44C55FECA55FD7CABA706A96F47B54445DA85173358536853C4AAD3C58AEA303DC0161D6EDFBA0B9E0B7919928451DD194CFEE2B81161E64150355DB5BD68086E8E27CB6815C6E6A238B9F995DA4C6941E8E56D701DEB4D18E7A999D08F70F40CC368914A5A0F6CE6416CD859C3EDEDD7E9BA20FFA8FEB810A36028595D5650CF5EBF9C6E646A4D9774A6FE997CC9B900ADC88D0F4FF6765C1331546617D8CEB8F4B68ACA724B326592013641F1D0001C6C278D8CCC23F211840898E9FC986025F56287FCA074A21363D18F3F6E255E2F0676F2CC60CD93EE949A87D6ED826E2BF536B35B99A523362A0E67FBC8BF684B299C3406D2C2D4607237D9994DB94F08006B8375B17453957B83297305309EB63AF9B5063F749A36E8931BF5E88DD7DD3CEA161E7AD9A2BD58F95CB5EE754E5F59CF4A05646F3BC98870EFF85A4462435039FF9ABAEE7F8D6C6F245AAAE4C6E17609EC9229000C5FE4A6CB1DF2AD36133E3F0A67267CE487559858E46B075A70EB168849C8ABD98F8D221E238EA7CE9C49FE6348AAE12FAF73F3BDA58BBBA9BE8F1AB47E2F0E5EBDD9EF6E3A8960A788C29DB6825A4FD7F3C3C3C89691670EF044493B0A52677D81F55D44813D25F79B1E7FB803BA4A1E3B1B16FE19E9915AF845D9D0489FDAD9F6794D558E96CA5C8A3FEC0C84CAB8016ACF575C53CFAF78190C6B25AA723FD988C21C16D46708E1C6861B716607AC5101AF36D8C4D7DF47C9B25513243ED1D8139D0EF533672D7876696F0925BF730C53FF5A4044F6666F038E6DA912DB5744963AA0512EC0898F5A6ED763DCC0ECC637962B8C26AC43F48682558A62E93F4B679944844C8319E7A090DBF6D7A229A126FC38F9C6F400C9C863607833E9DF5D4359226B2E484F966EE25FF5AEE6E29D1E9B51EB35C5F1618E41B95DC4348C8C0E03144092F21219D34AB14B0502B5F36938026D9BC6DCFDB48BF87C21B694F540395A7B10BA5B653B114C9ACE2EAC0EE724B078792D7317EAD4A7BDE6D6D859849B28BDC94233C9780CD5DE6B0E5DAF0DA1294850FDA676E76C3482B325837525E29F6E16407B592F300ED240F87513C833EEDC26E5FAA4A11EF7C7C9009C100C0F77549BA5084CBB62679BB8104164B110D770DE56DBC468EC9424248E04375F36F36B6C6161CB9EC8AF78CF02622A75A32FA54F0A15492156169C62D56D6350B4A095BA8CCA4F6610F40F9A360FE1B5483AC1C9AFC4328444665BE850EA8F85D14870C58D0FCFE352B696106245DCF5147689CE5C8F20303CF517A5A8B1C8118517B2CD822BC84E55DC7D25BCBBA64BA4B78E70A4CCEF6245B18CD4823322A96D778544096E5CE412CF486FDF362600F000F15216222F24002B64F081B476D7173DE50D1126B72001105897E28955953008DCB95D6DABE48C07E1BBCDF61ADDEF0FBD5AA1AF52DDD0EAD7C114F7CE7F12FF9A60E0EC723EF15DB34145EE80B47A5075F446D7A726A5AC2860BA8330AA499846E081CDFE331C154B1261F5A540DD8168F501AA63D51C02E8D2A4DF360F8ECE8046DD4CEA50E10F63C89BC70966121A3A6B61F955186608B0DF7AE46F4B0D88E687CE89099517128072A6E63E03E362F476884C4FAAC83F1E00EB609329E261329D844580BB988FDFA632689240B5F9F8EF0100A837FB2098E5728FDFA871FF191E09A5488009915BBCEBF99A7120B7BF039522FE426AC0A611F6B5B5BB3ECAC39E5011C53EDE1DEDF902E2A07736E0E39F7535E8A28BE5444BD3D5D42E58CBBFEC9426464A5AD526B444CCBEF23831AF18BDB8AD67140752FC6B771601C9682EEBDAB847E5058B885F33A10566E84F3BC69FA72700F297E2F5C6034F9B8F9D618ED806FC68DFD1F6E59BF5417300F746AF6B4CFF68FDCE56AFAE69C315C9D04D6762DF4A314B18153578035DDB030F293458863AE9128550158CF3AE960B717900C031D9203E511D6D8F21C2A8C6EF6FE178B71BF72A6657E6C47027975F054E252147592E6E27417F4A7BE0AC8205A8C23385D542B5548F28087B0CDE53D9E3291C440B926DD83705F99C121B14039FC650F0BD2F0D31F6837B48ACCF12696881617757B3573DAD41B50076526DA0DDA9AF8CB2DD381861FB9AB64176695F9B1533E2692E9929E307DA59605D48BDD901C4D959F98D6DBE0177D9009BE0249F25B19378122FECFF1F281245F1A4A0CCA5E3C78D6C199BD8535D21F1C5D6C29C3EB0585C95EB8EA0BDC506AEC755CE52F35611B194C5BA0F16E0170B6AAB283B3245A7746954379B3C48C5288DFA620B847FAF73C7C483487EC45905E074F13651D75BD78B8AAD448ADDDB630615AFD912A97DACCEE93CFD7EB57F30D61D176864DBC9DE847CDA9481D3EBA8AD6D8CAA111988B733857A65656C5B06F45AB4DC8AF8F833127F2CF6C1EC630DCDF486409552CBA7B697BEE128B3B2B86E0B113591634D90B4F58A6D0AD5CE67211B3EC474BC12A2F975E949FC3F13B4EB809EE6147873FC7D5F96728DF2CAD06E97F8AFB1AB35DD1B1E98A4E0EE22CBC7FDB90483F015A6C84A26EDC08D090CEB76D5E1F2DB71DA0A79DBB9AC0E37A2610F449B5DDDA84EF3FB9D26414ADBF379A893B707BF9E60BEFFF0D8FDC6FA929380A17D9FAB9D1A3928F8FAE2D241DD7134ECD7CD098A58EFB1324581C009F0C0380716753285BF2FD01C85C2E3F84CA064B034001B6A3C5EB2BA16B6899AFF36D586C96C34E32F141BA9E8C74D636280A829F3886FDE38AF94FAC17EAB3ACBCB61B6E1DF74D9FE5BAC99FCA62BD03EC8EC09C5D564883E61FD03E481B7ED334062E585E2B502A8A29A178614EA123DE0A61C157BA4AEDF357C17CACCB048AFDDE516D06384F12A51BE6481985D74A071F29652F55B834D0CEA59893E2E46548108B14BF9F2A13DD2A2D252A34A4B4A5FFE5E583CE3C37898B58DEE1873716CB8C1B21A6ADE8DAE3FFFC48A54EBA65005EEA84C408F8E9969290CE5E3C34C3DE5D11FD230B13873BBE2910626CC96E6CD98835A39FE134DE38E47B54363E2D01B48DEBCE75067D489AD6BF5D733E86737AD38CA20E53593B1282D7EE6D8912AC2BF143FA94B74EC0CBEAD68CC940BC18C69BA33B7754DD471C7C46ACCCED877E4484517375C7412053C53A102745B3861DF4F4ACF1062D5BF28835237032D355C06A4EFFC6C306F7240549074FBDDECCCED589D87919EDB68A4F6DF48C9F7912A1DB537CBCFF39DBD8E56B34E7A8D0D8CAA176708D51BFF70B14C27D2395F50C3839D6DA880D486CA8447CC3842F0151B615276122CCBD146CA0C434D9C07E2D4B648E06D08EC036E456CEAE6540C4DE308538FB765593F3DB41FAEBFF3489ACA8A +smlen = 3540 +sm = 9D950010BD5B695F80C470B33251B42134EC509365CE72756CC89C541246888761632FC76ACF09B255D749B4947498CC0115389603676048F7B6C2CF013ACB7065FE487655E2FA322272F09CBB53F5441198E892CE6DB209D0A13EE20C5C53C3DE47E0C77DCDA5135F984D48C8D574DE4E023EF4A8E3D52A79253EC2FA71252A9FEA2A613D8E59339AADAE7DB1624E95F050CE8E035833FF9118550437A0CE997827FD8673FC648E6A37D6FD233241E1C90102709C3648E124315FDDB215D19D1D8A1FF6BB0827E1A14C542A68904A4CCF35ADF115AAAAEF41F1EA5D71A467F915DBD4284528A95B887F944941052D533D07CDAC4BC75CD801C6481D8781BF948A0727C920F9D9C55ABCDDFC12148B280B07BB9BE44E61925D17A683DBB852AE05018436C1810F09001B93AD45AA39001488D13FD527E8CDBB56BA392AFB933CAE884EB4380E319357E280B1517EEE6A37EECFF4A00155613793E512C2352DACF94F4F19466A9E381C77AA69621F1A2C5575ADC2830056D9F1C4A1B81AFFBD3BC5D3FD96C64C43861D81EC88EF09583BEA0CB3EAD4E6E4EAEF76A80B863B7054F68384A8059190ED04E3647D26D646F4E471F084B50F59A91909569F98AB2DE4A2061E5ECD455FB35ED98195A63B482FE0868388D63B4323810CEF12815608A5D9B91E4224517F03A68ADFD6F29B4171C2D0D8E5843D1F7C925D0F0F3ADA55F8CDC2383BCF54ED7BFCB7C9C7A6F5730DF9AF1C9D3F69FD81617B7899847F9DC562D90087815EEC69E830858719112AEC4D71DD0C2E0CC68DE52A85C289414A67E59E595A026388B89EF8B2DAF3D16BA43629EEBD02E85980500EACC856F5D3A6677FE955841D1FC6F33CB2B71308F28250B633851723838602E90E5DE12C5F14D2273D5506F77948E597BD3AF5944D6208E2B905DDD60E712877EBB875A88086B58D11FDFA90EC51E6328FBB30F14D07F16EFF91C2B62F88E03082063DD4F40CCBB13A231224BF98ED0AE635EEB1C01336EFFFA5476CCB1878D86EFEE992E75DE8D892081897930F4A0DA02A3AEE0F65D4F890AD7BFC618F9BDB250B41D60450412438A6E42D02A2123EF8EC413098706226DF199F2CFA9CBDEBE41BF14250199F6D9086B13B39BD3A8812EDCC4D9B62E0DAF8F612259BAAFC6F5EC57160F4924918F1E633EA37C668B9234EE7E64A6669F73D4DFD99B05A2B0BC3A59C9E07207F5EA05FFFBA732D91E4F15AF79F138F756159BF895278C6761F379831A5BE9EBB81FEDE19676FB601EDE0436D770E7C133B6AE7A4BF34B1CF1EC9C6AEB324A7A095FC92719A97BB8148C4F95B256DE183539E11CD35B46FF5D93BC779FB586CC2587740C9469630564F5C26B312547912A60AD9850CE6CEEC3AB6ABE8A4D0E820234507C1305022E5D1B80D12E73645A47BCF1FC9D7E642685830624E9FCD20B47B87DD45286FA9EBC9DD15434F113C9C03B486B376A2D4B3E3942B1F70DB18C2B6FFFF10B726E39ECBB6C157CCC8512ECD645845B6479EA669E7AC1A8AB10E7928872A82A1CF2CE3F73B6715C2DD9B15F0B0A24E01DBE325A9A1FB2B1BD35EB9688619FA55B3FD793330E5C937DD0A3B2C367BF4CC494EBE848C2B16717C3E64BDBF610EF8A9E3F854F02B538DACAA41B1AD7F951FA80D4F5B711F5527F24D934856CB3F0B6812D467B633441A35B981A2043878983498FC2E2191703A4585D7FD581F6BAD8F9AFEC063F4D5D8C80E63C90B6B18B8F17FAA7380F6BF7C4D54B9582B9DB3CD08EEC6B0ABBCE93804B1D4A4177142A521C0BD0FF14F1ECF7680E804D1E8DACCBB5275A02B2CC46A2A5E137F4D6B0B50CEBC1B56E1FA5552A51C0CD051C55F4A4672D92B250652022E114BEE198CAE411C8EB417295C8A10176B13FEF82956E7DB7AD18B5442B9B48C1A63A7CE638447434A3F0094501670EEA5C5753EC3682B4B79598453AB7E831F93E3044D7C84F3432F3D4F5E1D11F5F94D452DB38554042B9CBC11FBC6FC9D2E0AC1637964985566B0FA478601F7F22F3444AF2D1B9C4B9E4AF5D84C68F45203C0907C4111DBFF2A39AFF633FEFD8DFDAC0184A6C2AF2EB432692363CF188F21D444801D234777F5FC8CD4670599ED10851C5DFC52A3F75AF7E33BE1899FE969448858F2299D5FB9E3AB50FEBA347E0BAD777CB0A8E20593EF51619996C5228ADD8314132306167D786BB081379A83844D41D8D04317B930F5043BB37288CEB40F22A5024F643885C0D4F76EA6E3166CEF18EFB4AF97F65A839C358D89A33FEC6C8BCD140DDEEAF1B2A3F7B0FB42F78621C5C85A109A85EAAD4C3B053946C8D50B778C00D9A9891E36E77FC2F43CC0643F932D5B32974CBB1D20EED62F05B3D896F8E93E8F1A76EDB33A1654ED5177ADF90C37E2429A399816951BEEA7214D6FFE78F3ABD0A9D92FEF2B1BCD5E1988784FF3A65FD0B1E5D05016534A9462BFD773B5EE9C45E5D623091D473076772BE9A2FC6E6F01859741B64EA8FC8E0A7DA8F7EFC4A88216A2FD5EAB4D917BD0C44FDB6BE3D4C51C5EEA1C5D0C3552B565952D3262EA245340ABC0A6DED5D5E40E5D380B855A06BECAE8E88D64BDF9EE8AA8983733FE5D5DD0EFD9908330A1637FE26C75015DA6E6147ED171FC46C97D838C6A8585A61994C4A0437760A3C9D86F3C1E5AB10C6C2C4AF0B49420CE6892E191A584A577D1BFF70970F97818D03F854A91CE27C68AD96B93C9AA4A4A20AAB81314C74365CA051FA500404CE71FE2A21AA325A0649CB2912D42899E1139EC32F4D91DB157C96AB9401FB65A51366B59B0C99FF62992118F452CF40E42C3E01FC548EEFD6BB5AE3D96438C43FB26FC1DC77A2E3D02EBD650447EDB73A72663C764FE18A54976AAB15DCC143850E0AA7D418D6B7C534962FBA98E2CCE8CAD9FFCCE4A04EBE2E052910A5CD05EAE652F6CC4E11E9B0671A250C4F712D6273076A365FF2BB87A2A398E78BB879A839274481CC51A2F5FBED6AABDC4CD07CAB57067CA11098D5844DA7F53F51942E9B26654510C4CD5A36002C1721D5362F63A88CBA51404B643A0A35F7944E5F15515BE4DE9170A7D4C05E70CA6E8AEDBA11AD4F702280717A7FD13E86D32BC50A89CE9F36ABCB9DCF11AAD74CD6CA42A45276428FE00EBDA0388F79F38EC6D5463735A84313299846701F9BA6F035DABC9FB66E865C31BB339D6A740C6458C42346A11FE10CDF5857D53C3F078741FA16B6E0344DE973E5A94F5304B6E7FA6D7DDE530971066A00C03C25E71604574BBF99290DECC89942932248686FE71AA7B9C593EE7D22778E3D0B1FAFA6A479CD72D66890D660A4554817A239BF3E37210EEB76AED26F2B6E2458DC2A282F978FD100E9EA16E5264486B031829F40E1A99F63085442A44DC27C634414FB2752A603730557FF0FE1F8705C579474E4A6183CCFECD23B2F6264C0B5A9E32D55D5CD6A9DB1FEFAEAD39EDEBE8FC6E96E4621C32455702A9B4CBE848F93D110EB26C00C7692D096DEFE1B57E635F87B73F9F2169E37661BA5161EAE6B2BAA85E1120D412157C78EF6D7A89EDB35A30F2C4B7CDFBC545ACADC4ADA4C0BAD2A48116A35C2A7299D42E01277BB8FFD73D76308FE1873C87D3C7BD5CC813CBAB342C2BC8A43CD05BFE42E6370671A00A8008EB4E1F6E01856E4608B34F980556E9413774FC0EBAFAFAC58C2EBD365AA51AFBEF7111F0C1A3A0877DC35F405E217D6FD5DD6D5DB5A112BADBD0A872EDC173E9DAE602E86FF7C1CD6E2908D92C7FD5FA9A7FDB236586294E8D573A8635284BC86BB81448CBB347C3947F38E692C7B3CF647C07B0FE1EFC19CB253AD792DE70931CCC99459C7287365C0210BD19034E89EBA93E153CE0A35B665B0568465067D10BEB76FA13D983D0AE8F4BC0B5BD0170B1D11CAC7B911503F987EE44B6128FBA5A8F7FE36EB0F449B686FB3D2A9D62D97325278F0F61E2D27EDBC8F39BB29F114215878A8DD7FF70354AD17AA83D8C144DC1326776417191F2423901CEBCEB8CBA69719B3BCE358D5AA98A4579614D760E2B20E4FD281392DE8AECABC281370260C53BC75798BD9D2BD8AB3B0FB805545A36B150D4A77E101E92E29DDC251FB94EB65D8E78F63EC57394CF97E4E2A5348B4DD71BDFC08779FFE6AA97AF9FE8E3F3D27FA4B984B179D3E35E4DF67B6F5310DCF818ADC9A3C93995A84AF9DA3B507DC44C2483ED7ADEDD5DAD722D747B644657BD34B1341DD07BE07DA3C1AAF9961B32CAF30FB7D3BE7F6389BD2B5B627185F141D9029103A90D44838DBDF28BF10C3F18A0B04985FD06D7E3B2767FD3A1148483EBB5FC2E160813F3FC8A820F985BD5499AACED7242D815D604C92DD8340B71CA28FDDBCA41921DD99F62FFB87B25886AA519F3557D2372478EDC51EEB9FF144D3E9210ADE6C073A1E6BEB413513EF26F3CAEE7F330915869321CA3C4DBF0EC14A180F7315533ED0287E1E9B56574914150A310C5DF77FBDE6105D2BBA369DB2CE93D73EE78F17B7FE9DEBF6056DEB8D31F67613E1549AB114907F4C12ECBE705A356ADF49435EE6307AB5F26B2FEC7FD30F50775B3BBBED794BF18A0B9DBFE6E9C068427BD42104C5A6EAFB6E2182B6D7B86B2CCD31C265399D04F5564686F7896226C7F062C4E71EAEBEC000000000000000000000000000000000000070F141B1E250073BEE97FC97C0FBC750D474AEB93189F061E1A5CF6600C04FB0464338EC7E85252F94FCBC7B2BD00E438480D9AF3ADD92A92E3E2E8ACB55077C3278FC7503988A76E9B6062996B20889AA55B343D5A003C8A8852D738F955799FA3426BE5CCD3AA6B6EDA04D4884941FFC0B69C5ACF12B347A74D0580CC3335BA816200F87674A4C1D98097C70F2F27C74E94A661850610ECF4847AB5B58344F958C5719E06BA396225BBE21ACB0FDC512B885D391E11B0C0ED5CE6B5DD8FAFF91F50025C69D43072F7706D80D9FD786E1104125D79A5F4B5FD838815D44FC8B1AB678078CC174DDE970D448B + +count = 7 +seed = 8C151C556DA912A82DEB32144C8A8C9090CFAF5C12AB822AC3C72618837A41C2453B715EEFF3724CAFE69B1ADCAE9DDA +mlen = 264 +msg = A1586245D81F96BD8EE81AA30F10C0ADB343D74CF72C4DFF71550C12873AF89FA1874D4731C996243C3749AF3F6188FFE9FA45430549045134EB29EF3CEC37E72904AA082B1C6161E6B52361E49AF4933A8D8C0734F21CAFD7467B0C02876F43211D6122E3E735FE36064DF7A0C91449237C2BC7C3A78AC7BB0F9567F2576F05802C872ADF183A87AA3B8217188F2F3535F877724F35B29E545DE4BCF258F13BBC7EDD8C6587F733C9691F74B4151CF8C060C3AE9E8D49FE7C77BF477DC9F23FD0F0B67320275529034B84F94176730923C03AA50F9584D9C2D60B8DCCF85A13F243F30A51ABEFBBF2CDA602BF3D75E849EB92422B808416C7E56B046CE38E4677AD24D23D7237A9 +pk = 2CD04A91DBD7826E4F99C13E5EA14D1A6E7A8725E5873D61B456D64CF59BE90EE2F66D0DC0737048A8BAF8967107770EB0434D196F6341C1971C842E2880F3AC6D11BE0F6B8531DB1088712AE28FD9B1766AD1BDC192E0BF6FEB4CD6E0A9E361F8E35D468AE407D51E2923B9F8FE845FE2354921D90FB7148E320D298D8411E6F1E20408F46B62E17E6E5A148793FF439678D032EDFF6BD251C15DA90569CA01B0B0F2D0A12CC721F620AA9D0BE180CA7AA508A043BD8F25C435938BB5E16EDD1261051BA9A2383AB166769CC07EBF286E914CE15679A4777B6A460CAB8A5BA0170AA800DEFB4A7E88A8DF7F0F4E71C3C07063601FC901D0503C511CE46230B15977314680E588B2B0CF81A8D8F3C3F0E5540D38A38B329E7591529DBF7D3D47B2B1240543E0701884D06F88DFA0A10A554A444A3B8C21AE41CB289C0A48B3CD2E9D85A61B19420625BDDF81725BE6AFE375B4132C6330945308E6B214A04E001D79211155C64505EE5C36EA63EAB345674FB863C67F054CAE351E04AF853908983A16BBD3B8C04F8165BA3AD27B6C702C0BB57BAC726903BA7B66DE2D1D65795A9D7D0F0FCD89C40E7F839060131E910C9758D0BF5121A986A74277F87C018313DFDAAD74A29CEAB80F1ADDCC276048EB20EAB58745EB2137109A98C2562B2F13FE9EB447F16ED478268101AED168DCA72D5B0714F67CE9D772370926260FFC8A13F0A3FDC6B4487CCA7A760C243AAC91B5C8B156D66FE77F3377F8F413149941124D07959CFB2FFAFF5E8D11981F051D4F616B2DEDA58CBEDA6F5F26C4F8D6D8F94B849EE03673FE472C1139E73A0BAC67C30AE68C15DD751A9C31FBEA91996C438181B48725C17EC88593F1E76357AD52656B04856929661A5305E09826E22A45517B56671574F586C8B76D9CA4581E921D38E2E70ED4714EA933637F48397E39B297E6EDCB09E6E5E22677558552A9FD9ADD72083DC7B60F81503D6447FDD82A15626F14D7E53FF450AB4F9B8F7A519AD1DC25E79B8829EF7E517548EDFFF240FEB86B781CE2E8072211919410875C85107200057EC053115A99D2924885DA0E93EAFACCD16A5FFB5E97A3B54DDD51A26EF9209BB609EEFD454993FEB73EA494EB569BB93328D59A901FF4C73E7CCA71E3E49BDB26450ACD776B51DABA1B42488FB7F8C997D2573AA13F8A02041A9177BC56C6DC451D6D3C60D29674923BA88FA168960043127C22727D68C2D62A155D4F37F0BB3B09DE40889702813E8984CF148D735B1871DDE01EEA6EB00FB7177651A5B78181F27E234BD33BAAC031328AC9BAF37760F1D46E2131EB65022B5249278D4AD71B010860298D04CFB2723D596AE5161D9202B69FB90677172EA00FB29052219E592C7519781F80F0C116E676B1537D96F1E4D4D47F8F16D49D642F586AE9EFFF9B38856965587B73CBA5C98C5146234E9BAD241E8CA2199B61765518740806D5E557A2B1C99E7203CB49A4F958109F10E1F9C50E83657F208949D455216EF87E336DA02A9E5820753CBCA1F9688DF9CB760A921EF6E70722A9FE7B2BD72ABF8BE029E270269C0F8B0BBE647BFB59E1A0D3F05FB12033F05165C8F1877A64458072549123BC39D4EA16DA511859B04A2EDD36F47608C8344E3BDC1A5F922B90FD797F6825A4BB121D4832F9D4D79621BE2A99F9C36C11DF0B02FE8D8F641681D6C4CB253DBECA4E10CBA631F00B2B95388D26CED9607A734CCBA12B671E05C0DB424428072C41AF3AA319965A4992FAB45EF25ADA6CFAA7A6B87A43B4ACDF8F2B1A3BD8C6F1CC9553CDCC0964A5E02D64B5CE1AB219B1B57DD479C59EEC2BC68B9BEA5A5887B80B3CC18A6DF3B5C6821D99E5026C56FD95E782B15BAEEA6A4EF096CD911C1BEDD9EF788883017B7219D153185281749A84E00F0BA7FF9CD613B536BD4F6FA141A04A085A761FBDBB8080258CEF1DD9799715F8DDCD9415406C197F35975D57FECE9CE1C54A4B0EDD42536A33A6A880A8B914A552BA7253F0179DF13ECB9BB5C9923A64E0FDFB6C326BBA8F75C57C4ABFDD340F19437BDAE0C2ADFED6D37CFA588FEF04BBD2F44A370994C377A222882B25DC73AB53A236F8E91DE5A2F4F441A44EE09964B8E544114AE94BAD8B1F5261DB7897F5F2EE8C330F236B4C04376191876BD7CD419ACD885F8E64F0CA85A3A125024805095F0E9DD0C6E14302AC7B13337F57D988D1702709CAF4134EA28C7BA8F47346EEDF8F8FEEBCCA498BF764FBC6FEF87880F68AC75C48A97C3F722D1215AA7BC983DCDE912A0265A4B2F70342C8A44238E48718A64F899DF3010B5B8DD6F9BFCDB94392203863F1D18A558C321FE502C3B148698F19E9A78E4960A43BDCCCE8920A57AA150DD158286A158F1FE0B5A0B24445816BB79934039E95DD35CE69733A0B6E9350C31BB851FECA1188CC317FC42728FFB2FFBECED5D5566538E93C2559709691126189A00F077EE2F90E8C9BAC4E903F738654889BB349CE820DCD68584170FC41CEFB8524E209CA5AD416A49B18D2DFE0914EFD1383F05E9674291F847B5F896397C1944E3AC21BBF4F6AC83FA6829B404669D564841394E47043DB5AAB492B98301768C03F0756DDC82F0BD8F370DB8981B778A506D4EE6A7DB67EAE52B4CA938E0215531988FE84379F310F47FF94FB57AAFAE9BC3320C7276C9229096EEE25F07F50E9E625D788C023DB04166DF0CC00196E2DF6E1528CF0C93A22348104A80D4B6B920E9CBEEA6FC1EA60 +sk = 2CD04A91DBD7826E4F99C13E5EA14D1A6E7A8725E5873D61B456D64CF59BE90E3D725A115907004BD8B2E1BEF370E28C689E114E1FE76983BB0ED47C062417C91B04D69FE6625E3C7FCB8D02C4426B987A8BE504C0178FE71DA7E063BE89AA1BD1781A3636CE7B3D9552AA675BCADBF1A492E6BFC291BB3D006D3F7D3AE1075985382365356126803811332567081745078486854036760584752454486770232700061485666343444768657321044443802404270672462023751473367237635138724258215116527325003263678712387803574202315664213161122175311421657050820503813371115013148837415236213706184617135185037063753474738633324273207106544256666878116713337148123045868028128460356864453013285864337720628650063156381766108835362427160645072180770158450255461651170004736031506454801886144163863565464232423506711287355624775071501827528035717853863786187188255406875500573053852861750303447334637266787707205244461375185663704617260405506415427068566553850533150158684624113738688314402321112601151625234016327421851505745116878438130455618660050354037311020021365763472824477438185520804160637543572571020752027755187424474624274484464234773345341863747825285777250846088118368303004244058355281274653055838083203054328445771766028365831451560085068840112554603503218348711222265621621521484617613270462105843551165275638067383578148216726287454026451527732442274853526016246116883835825553875603352161314207458124026811458363415761552650875684286556416054207627030270424700728251187726671070058157864416587460058730121837333014717517028878566286336512248008672780653406450261681653742835606470754074018501758535330662117148144676855568607011202503013862300483438323875554465000353786674000882741320564258370174616413503682441044265327821761532186657605731303727765008284872406530765763702560546645685415881061660865181807847670342660885203450501520605437784646285287262556203423222415021500528028661761423457000832886157752505365153347635106835147206520056710523763177345673840227523644758220125881473868532305262220274716738831787377111121164302664004758324624606338185842267234810364876747254723435621610681206308400703435607415386615760040666265235646670447848837070514466312158716147040667431133081832168861655648732600744102851513512131152577847611315633841038747225646677781858124288112024307761075304002672782608152737718426502562810681351203843318851662888626273180317133340372260731051001081321657321020256663356747165475642386308010706177861247876424310653088054353143563075344226040815300673410367852155048403465407620806843760801063412225154106111737737180281165887730781760473248487640841582645005184747874011053746681115538786312046785485106365242455065274340686288385607786262236583285125127324067486736267102444014033113403106688756750445536071886387641845170132667747886750571453134846147600814017028112623763163810180636224177411135200243533520458126262253123000807877756577353017627546063860845885073820573421478082135550715716461584066173824087135254520800158727557606633118625804671668803775001166446321530138864220353087012576821863612147714877750566223461467705758228083447476321006376228363287814315478254176422501337816501867022737428257472BB5782EB944D5D9A5E3EC0EDF90863A92C89F4FAC3B8F6036D75832480E8AB8351B35CD75565BCC27BC351D82E4600EB5A99A3DAF7580B88EC7BA7B3BBCE302AAFFC4C03F70D0D75C1F5C4957D46BD45C07627E783F9C434FC52401B68CBED5ACEC94F2003F809303372F995DAF0DEDB1094B804FA5B1FFE7711001B0CBDD23E90E80D80E51D02C1FA123AB49C3F454FD60D0E1368A53099E9FB6AA8DC3792D9250D24A7F237D01D4FF0062DC4F3BC781DE44AC359C50317B28F82075C3E10192FE2BED85F4A7F718B9DC98BE6A0D755990AD1201100A434235E9386578BC67C0E778E81B1EE9DE54E5B661D3932546C03E64E5568B378B3BF070EC14FC940C098F9F545776A75D1C8836CFC190D663302A20B4684E3F85AB843ECED20E1B88A6CE9C336ADEEE81D6ABA897A31EF417935B8E7F89D961FCB8447BE0C47671B44450C95FB631CA05F7D9892E45E80DCE2CF47E2BA21F860A1B4D96E8A5B5C8346D147B154884D968F4A1C56AF4CB50C7CF3E8B45FF37F4CBBAC4DDD70491DB48835A7DE312F15D828E245E284AE5DCA6823495B2236D9B0A09554B95BC6D19405644967EE156608B64C46253191D9A511BAFB0B0791CCF739268C305175DA4F6530AB7D9E0DD1C52267298337E404D6CF5F374E1BA356847C464A4AA8A74F344809DB5534240D8FBCC7D12642A00F3DD887EA8A0959917CC230A01ED3D04F24665682F09A27F7A0D2EFCD2CEB4F2D5B5BBF95AEA6557778B7733F43FD5C669A248FD6D534FF0AF1E7077EBD0B6A360810A976865795E1A06EF3F6A7306EA27AC4945F0280BB18C61CEE93881F5632A4FCAF0D7210E197F0183A6B0349A34E318A2B141778498581B31602E89F464A7522A7C99DD4618912BAF81DD40EC1CCE72C0AF97134FB299F309BAC1ECDD52420B928F8B29DB7FF4BF10520904A89D5F4625E0DB23A19117E744789D046EF4F3EFB055E9F122F5BC105946CEEABEED3235B3702047BE1045633521115F3DB2D0F208D6812CA6E55BCF630C2A695B853114F609DC48AD7DD8214A84C2B3AFB12FEE82EE6CFA22097E1664822A9CAC5AEEE85C918173624F9433CB70A439FE93741C8216CFCFFC8B7081D2AB6A6B2DAF8923F8399AC55446C987A382604BF67E0DFDA2E1D6D803428AC326A86918BE91CA07EA18BF19CCA738FB583DFF8378514B4322670D9A58D74639A81C0C5BFE672AAF31282B81301F6A39BBB66A63509283BAD95F5265D97659F3CBB536C556D8D31290711DF9A103B98F1E40AFCDB04874E2736549A998F5AAA6D7D18CC792F582586B9ECBA23F4231F0FC2C2FFE59EE0409FAFDDF408348E4249F57DA67241130BD022558560DF91C13364A12279735F5E1FAEE880EA2C2F58DDCD704B71A5ECFB66DBD6D0EBB98AC68789FB3611894BC95C2F617E679CDC3FB5CAC1ED9A8C49560498773E503F3722CE6B3AA9D857C34E0B37BFF03451E0ACECCF77CF40CD5EEAD5B19BC47088B5AB094B506C730BF1832D7CB463DA2458AD791CAFFC85BE52732CAF743F4BDDE80B5154934250A5D94CE854FB024A14724EE74B696274B8255796B4ED9132BDF72093E788941C10420FFBD560A7969FD2843565E9101BDEF9E71B0C1ED20A367299AC4ACE567615757432EA2596F1EB40BD145982F603BB83FC46539774DF1D42E16DE0A959D23EBC93B492F5E8DE186A61F1D80EFD8084AC591C26C9A08FDCFB74E47D8079F9303D8CA98960D56DDEB6E1D04B4135CD7A375CC9CB7B8AEFAAC72A449AB091788D18A05C6B2EB14371C9308E41434590363812216425CC7C49700DF0982E7E6D7B293AEA588516CDB21C082904B20A68C8EA2BE3A815D42F821E97E14D4B758693BEB3B540D0BA0EEA2CFA1D1548FA395FF9046B27B1F56F185070420C6C5A4AB1E62EF8AEF3598BE0AE3F3336E17D774411D048D9F2229138658597B9D8CA664A02478BF6E74242382EC4F5F8E99156CF5EAC68164E7FB76C962D5294A5750709A285B0E31F9615CAE452E7249F3E4CE14F44042BDA98A71AC22AD7CA5F4373B5332E5DF7BE61B152B964232CAB48B0B46E5886EF9D301388B71A04BA60AD176CDFBBD93960506E9EA5C9868C81B8B5058EC1FFC5B8B6630FE25EFE5632C7564810D11D98864AC3D1EC694B2362AE03CF17DA9CA3252B9426EC6AA6DF0757E800E16DEF9D9107CDDB718850E0B932D75D825A7936C6A7167531564B8E2FE1A8F88190C1B3C9CD3376EE5510506D6DF0E6ABC2D76A229595A9875535B0A05E3B6133D915A767A6C194C4F0B2B43D26ADEBD5765A9592AE398BFE7DB32F5F4B40F58F4FB44EE86835A51F4C2E37357F9B392C585B55C1430AD4BAC938148C9F30074EF2CA0BC0840B486922DF1B791160FB72C1CDC5173B0BB9C0E8EFCF13FFED8CFC37C7EB40E99B33CF08EC9C2282B330A81555C6C575C287CBEB24EF2BDF4B284B629E892D27D3A1ABF4C73AA6FF36DED8B2DDF0FFC1E96A73EEE8CBBAF2BDBA8EE51D7D249EEFDB82605C9148A64874B5A175D7C72D16AFAE2123226F215E849B1A3D6C151C575C0D0E2ED2A6235CDAF471CB42BF28F31E5BB348801A09606A2016AB67276D38BEBB8E8B67792C2DAC010A0113853D3C25CE007B718B1AE20627CF8F86038D6D2CA0AE69705252E1A2C08AEB2F1380A65538CD335249F0D64AD9CFB17ECE7CD58B7EA51D70435922084F6DEF1798BEFDFEF0C51E968C0FFF8358C383A2B67D52AEEC748928DA869256A90D1A74EE36B1F369DDE9B21B9F1598147C8926A3E1520F2C70D6385E66D704DCF34B68F403F93CF0B66A26CD8175EE7F2C4013820E7F572694A1C33546C0BC7ECA10D21B31370A3508931EFA2989E44D651D58B6F5E24DF9A6AE5BF387C74DE4C13AB6D84DE8A28C58F838806253E12A292C1B284B12AEF90E5D3EB3FBDD9B8D95D393EEC341D09438A78FCBEE99D952BAEB598B182F9E64F62CAE5EFC2C3784D991A14E2550095404E1E05DBC233FED6793433C2DFF3438C64E8A7042184032BD6F5A8D3DE2EEF49C99A592AFB9F1FE6305AD85D755B415AFA6D3969F4DF69E01E19ED18537E1393CD68212B6CBA2BD875BD3E3FA4C9AC9712413BF11C190855BBEE00EA3ED063FE0C7CD8375A261DD362F96050FBA8DAC6F2541C89208E96A6A3DB959871F47D2039F3A0B9370567D2B0EE798EB489D01A17E81B5A1E5A4F7D952205ADFC4BAED3BEB682254C99F901B2A76F86B380D0ED3A71CF52F205AC52B20617BB69E34F0D2746BEA0BB159BCB860D9FA65B63B8AD6439BB39BFD269C1E10E5DE592182B30615EAB0E77FE6916F380B9BD5FA90753211637BBDF271C843F2CCA9C6C6EA29A910BC9CCB8EB447087C158691727DDAF3031F60A0770FCB9C33E552014873BEB79681C80370A80F2D83B784C0993242376B0400283EB4138C7C970CA15BC7F9C3C7070698080FEBCC29EBD313A978C974D4E7419CB8087B2BAB4E0A1F9FF1A04912EDD5BCE6CE6FB1180C73C252D94D32C01D9598DDFB4520BB +smlen = 3573 +sm = D44F345A73FE49B486DAAD54A38739BA460D8E48CEBA1CC86F82CD2A4B5A830FDEF481078B0763FE992D04E1577D1D0AEFB1C7596B45C3EF8E78133A8A80A854C386EE24972A1F2291524D874D038A6CEB9A60FAF66DDB77F6546FDC8C1D4C27D9EC90800802665AB8B075915B26137938F237A6EF4EE49E99BEE1482E62B78C970AFB37390E662154B32FBDCDDF68A4EDF31EC1EADB5969BEA5D241A2B0BA2E421EB20F4DED49F8A0C3A53103AD5F7F36C810503B77677597E86C6CD0CCE657652D40E222AA92B81971EB4FF5B3A5048233A3035230D7BA3BACFC0C4C4D84C2BC95D69FBE762B608ADC8478DD859FF2F7F9467C6921D6890B0F10B3CFAB5472181DCFB212B36520C88E719B2CCA2E7CD18D6919E67DF94A41CBC53E3BE21D3B9C8492C2F71DFAE50AC09B29969C1602477777C36906732560C9A92B0656B7C1CD195C38981A004D8CB5F6A9C73DC332D464ADB4EDCF2C7D47C0BA518EEABE7CBC063680D356899925E3EF2835B0F7B13C027B59E3329AF025975DCD6B6DAD23BAB14812A0C5B870D167E8921D971F18F51926B443AC417AC1558FCB9CDD811C0D70DE8F24B36029977F3910A7491B29A0D23C4CFDD05A973472185FDE39110C1B68C1E8693F224D86F0D5F3766237B2700DD7E42CF7D9A5758DB1DD49325E9B49CE6E14627B888177C632D3BAE0935E74F44BE8FA96C696EC1C8AF06C0DB25C24C57B14F8FC7E7F370E49EB10F324835DB56D5C527BF6DF69C4E31E0774D86776C1E6D8B22AC349E8767041351CC10F630ABC8DEC02790B4653F5311FA822FEED12BEEFD9CCA00E918FB70AFE0160EBCE02C784090279BC180FF3388B6B998EDE17E8025CF4F935281B0E724BAA7F063687788855085D59A79DDACF6AE30B1FECE6180CE8DABB698549314F3B154A5848C84051F2B384BC9D95D58DFC6ACF1C489C3A6820F5E9907EA88E0CD644A85467F1E7E1F10B61327A3B291B07C299EEE71543ADB7BEE28543C299E88F8D3EC64D74327BB6A5F378B892018A2EE18F902B577747E99FE184FF0A4C465AF27667E720A1D6DEE2575090BEB374C33A0FEB0A7E290C75E92DC28FD7DF7A37183149E33F0B6A86374D6A7B8040AE1E40789FDAD582AAC81A82BD36C86E006D867ADF1D7A8530F6440CC316E071DB4C7F686AD86834B4676C4B7DD844E8A9D7AF136BE3A1317BAE28E8E731758855FB54FCFF94C37651FEADD24C71198818BD5B8761669EC6AEFC93811DBF79F93BCE7713CEF1E8BD5A388E4BDE871BEF1C600A14992211F0B69EFA6252AAB865A70750A4483ECF49C94688A9B9A90DC1F6F9B7AA89E7E23B8BA1CAC45BB3AF13B77628B3A34060B69D3D23A7D100EA6AFA69485415A7833B57BCFDC6234AD198B3E8DD5BC7866E1697ADA7DFCD3E88FED200FD61152A8223289030B5E344F78C4D57802CCB0DA5572069CCDDBEBEA96EE84F7C018D45C3F27A7E3F7CD33C30D319A92E1E40DAF496B10E4E1987735EB3704D827C0C9527D6A5B7E8229BCD9DF4B5FF9D5BCE9C007AE2BF7C8481AE756A9BF595884DD69730FEB60EF2B37879F7041C6442634B40F6A22AF3AF0AD156B9249A78B4621F5F2C28EE020AE2352667F5C9F6DD2DBCCAA8C35713121F414250C28D291871E86C00F7DD4B842B40EA7EB81080BA323A125F1362BFE4174C61C15B6097B593D5956F9910370CAB27FB87EF96AE47B5184662E38247905D44EB8484A565D30DB5F38645A177EE176488DA41F9E25AF644E0229E205362C30AEFF4FE236CAD21325311C6FCC8983A02D02F4CA327E7F3EC5478D08F398F06C77D6286956B15274C66872E41FEB49724C8DA0E673E729E047C0B1A21B80254FBF75B0173A586E40FA01A96C19CF52A561F4E0B5A06089110753B843164EEAC74627DC772FD76B0FA55D17E3A4B3B845D24DF6BF237932464207D794FD10138AB989FF60752F388127E809F0C94D8F12514E22B6B0350C91514E3F2F4435676E7D80E2FB30B2ACF0AD11D338DAB16D2B845B6C58B798175CF9B946FB38A5382EFEF525F1FA45675A45BE486DEE6B85020CD70097B30378A4F865EF2296AAEB8BC8ED5DA152FC5B138A0E913EB0083E9DFCCB3E66ADDA1AFB0D0EE84876D782F3500F94C9CE24597DD493748521B79B10611FB938B1A175B8C277A67CFC1D06CFBBFCD10654FD0A64057D3383938CE4A07527A3A9113558B3FC7A45D5E4FAE35A31795B0409E1A6B414870E0CCDF46B5E188F6B0BD6DFA9CE2BA4F8A4F62483BB80625F6A39638639A075D148C5DB8DEF9D4DBEE5F523E1839C5B8D17AC0C43776621037B5A328680E2FC8A8D775890E338424C2B9B12729E2964FEE6132CEE01B36D366CC8FA92628CDB122920AE3B96B90232A49E454BEBD5C4116D97B4C5EEF9F498D28C34E3F072ED4675AD749DD05156BC0D3F6EB968C4BD7B93BD0FFA12AFC085BF7F5301D404DDF3EA01AC52F62F1940A76E3D0B065580621ADE2E451E0194D3EB1EE52F522FB37585C990067C638EB199D2DC7FA4D7C8A1770DC144B0B86D65627A5A9AE2B6D0156788CA6D86291F61395CDC96E110424A27B167E0CF3D0394CCB8606F909056FAEC107BD9F3A107229F10E5FFF4EB0B255D2E0197054F3E709902262165FEBFF86957C2441B1B12F3596640E6051AC6995B013CCA3FBAA2E12CC8AB1FAC05F1E96F47433B228C7C03A2C8BFCE0C9785B53821AD31EBAEB6C858CD2596F11A20F6A8060ADF0C8D18375D82BAFC756C514A66D0B70F58F1A62CE46E45BF8031817C99DC94DC65B26CD16E5B64C2FAD49524BF1C71E6D6AE9D444F638968DF00C8853574A317A0B906C111203F97EE86663161243FBA17FEC82F2DA541C537F934CDFAC18B054048F207F8C49503BDB07A9ECC5EDC8F329B9BB87CC0C1B19C97A2894DCEF15EF7363BB4A92ABAC95BC42406C36B54BE372E7175CC23D8F3CC370FE88BB4B7E201632B2B5937CF72D0148B054C8C516763C00FA952351A320A24DA34F84930FC1AAAB094940BC579D966A0214606C4EE5A548936578800A39A3635D6510E9DCAECE1BB19646AD1990CED7A5692C9D46FA1E78A4FFB0520A3E40B344AA1F6C6FA49EB32DE92B5FE7197752C4D60F60A8B401D5D843C2FBE13242C39BA1CD5D07EB83CB5C2820CBEE9873D5055C023321DEA0567EF6BB2D885082E2CA48EA06741CB2F30F4155285545A4D350410591440FEECF69B21BF5200925E1EE53355ECBE9AFBE5C35C49DD4EE208388AA909424C3E9681E40671AB937758843F4CE63C3C4D4D824501AF5E3257E385D4A7158492CD95927B4734C8D5B7F7691611595EE38EFD8B3A8118BB477A8544753F58AC737CB6E72E9A999265738C58BBAD6A073234FAB670E653EDBC83B380315F8AF0C1488D7263CD03E8566389C0F05AC2FE2611CC6FB10763AA4F50091BBAE14F76E3F28085FFBD2B730E4CD550163F08C3527F0FEB036645D5F355E5D00B03820F389C0C49D820D8080351F8887C027585A1586B85201E0387C55592A6132E7DFAC1B81E176DAD9BDDA6CDC0D27E4F8A1D314D4F1FD0F7DF738B645702040321D0C4F2D97CB88E399F76679ACB26404871A973475C767E8B5FA0951D9BE32144879E08448B17AB9CAD3AC946109F5F76BD38C85E03471F61A0D57A1A2FB56859538A620B9D682C1E54328319ED726763D3A3FE6DF615289686226662F35B687D4B3667371A56C2D81F1050196300C9DC305F946D89EC8005BFC353AB1B9A9571ED7FBBE941FAE8C3E268C6DC13CAF2DE71C4B0EE3E5D147CAA36C61C7315F538D0C59262E83C725688ED26F37A74CE673994E542507C44BB2DF0F64BC2C4BAC39209F62ED8156C6B6E148ADA38154EF820E662F85D0901B4AE235E4E2C51D5AB506A955EB5E51E1A1EBC79F777DFB04FEC84837856885EA2D513DDBA6B0BD0A2B6F2DB79E90900FEB21514F95CEF8657635024C096B30528C40B2CDD7A7A2F89D2F3C101FE42A871E8D4A124960B19C44F52C2E943331108C2CAAB86C02DEF675B31E972BA29F3929C91C9AA7C81E4BEDB834EFC603ACA86ADC77361C7CB1A14AC3274377D33D9D1161116D70892FED35FDDB571981DB5D7376DADBC6F85971AE71EAAC5386CFEF19BC08AD86A9D01FCC20535D9655C043CF4DDCCEB37810DDD216FB8E5392382C3CEBCD7A6DA079DA83D38C1000853CA0CC1601FDDEC9D20F2D3E4DE234C9DF0CB6755EABF4611079980AC8570E504D64C64958DAEE960C530E431109AF9055F65BF104C203B9D635744EDEA9C941A7D385B84818D0D76644A5C09C26E73A7B0EDF77BC7E26008AB3CFD9F22AA5AD8A395BBB6B92EC367E8536ACA1856A5624D9920850DDB6A19085AFA94ECA9591D5EBED5B62517834AD7CDAE28D115EBF91C9C7D042C01046F627498C202426C9CB3B2413CBAEAA07C2C2B5FB19E11728CBFC2C8FA457F61EF839B5A96DB950D0CAFF1D5BEC428754838D4C1C18A5F522D847EA9D8FC45931FBABECD397376880395CAE8049ADC84E91B82C5054D08EE36B80C5A539853A08661D207CB4F5F5904E9EDEE79B6CAB5863336F64A4A1408B7D0DAE865B10334962002F49EE1452BEDCB8C70BABB84F8300000000000000000000000000000000000000000000000000000000000000000000000004080C0E1113A1586245D81F96BD8EE81AA30F10C0ADB343D74CF72C4DFF71550C12873AF89FA1874D4731C996243C3749AF3F6188FFE9FA45430549045134EB29EF3CEC37E72904AA082B1C6161E6B52361E49AF4933A8D8C0734F21CAFD7467B0C02876F43211D6122E3E735FE36064DF7A0C91449237C2BC7C3A78AC7BB0F9567F2576F05802C872ADF183A87AA3B8217188F2F3535F877724F35B29E545DE4BCF258F13BBC7EDD8C6587F733C9691F74B4151CF8C060C3AE9E8D49FE7C77BF477DC9F23FD0F0B67320275529034B84F94176730923C03AA50F9584D9C2D60B8DCCF85A13F243F30A51ABEFBBF2CDA602BF3D75E849EB92422B808416C7E56B046CE38E4677AD24D23D7237A9 + +count = 8 +seed = 9B42F41492530EAC81992F17613EFDF155F407D7E67F18AE193EDCE714D65D1031E7AD10839AAB46D0850EAF5997AB4D +mlen = 297 +msg = 9366ED7B3B623C411448B634446F1A3FAABDD163A6CC1E2BCAE4A98703CD8CEE441405892FBA051BE2A586A6950A5EF73A255E5F86B0D7212E0C51C3BC79BE4B88E76ED6F043FEF3204FAF044BFB1ED722D61EB5D0B74C66A257E8AC3A2206273C80D2EC2123A4DBB715D60118D99ED7322E38F1562F82379138DA3DDB8BAA7CE61AB729AFC3748C0134633CF45A9973C05C75D04E82F631845427626B5799DC07DDF830BA01E8BC6236BB6D03B37D949DBB29EEC7DFE60FBC17EA590956D251539792016E2A8B01E70476961BC9ADA43CDA682D0CAA4FCC58810BBA1A673EF8F6BC90BAEE701E8E4F7C04A346CA56C7B2862FF57756CE6CD1EE22D677BCDAA896EAE96F87870E032C18B6C6A0C1A191FAE2ED487CE55296CC4B6339EAC9E8A742BD0A44C3525CC750 +pk = CC568AA4A3DBBD508E987485B26A8CC116511265CF26166B535C09160541F87BA8A79B466F7CE842E4AC98ECF9078E4CFAE87BD4B77F7C0F1566E7B92401B4FDDD9585392EB7E4CE9B184782C12AC507D224460E86FC6BC862A1D1C62C29A9B7CCC5BABC015EB4E256B87324E199607E4443F47470E63A7B69BDD322BFCC44BC0BC7C6399B986FB6212BEF7338A488F492731EFD4F37FF55E953C15D5F7BCBDD3020119406651C9A8B6FE7EAB280D710B8AF37346F52DCEABF55EFCCE63B893257D6C2BD252AF29289755EC59C4FB3E38E88266601477645558E1F1742B3EF558C9205A87F372EFCC6362703532B6707E9A58246192A5D5A7C8E10A007D15F34FF977BD9FB2CFBE1C4275D5779F5A0D82A9B2A8CDDE0CA40D7858F1878EC6D4D13165CB858A28011AB29C29AEED662A4928641E17C9A2D4F582CA5ECEB64E49291447FA62B400A6C95CCF0CD18A773F15E5054512793A85CC25593C783A7C0AE12740E7EF6CDFD5164212D40EE7CD4E9F64262C0D2F26C1A06BCBF6E3FD8695A05ECACB0F2CA5E8B40E1198AB1F4854723063BF5306156B56BA4AD342166BBBC3CD12AF20F8CC414A1DBA7FAFD2EC73C4B5913D0097CFEA4A1E199DE37721C0D889E42937F8F3E11495026B7888527E8A5915050C23045BD30C6675A6FE39B4C8AD67CA1C92873A0335D5E72886AD27262376BFE4C18DC8568BC12F13D571234D34C531E3FFECA2B929ECA8F354CA880B7746FA5B9B92D245DEAA5000C050839E0462C3A56555756AE5AF80FD968F23F29241940E1BA1BF368F979480DCC691F584DE65E7C7202D4522A160276DE061059181942955AC87D4E7A922E68F063A0182D6E60417D8CC81293125EBBF504CC29B9E67E82A0E094B4D44AC1B161508D5A3EDADE2307C950FED5F06E3360DE1E6877F9A5B36E163F7431A4E201E4D9B7A5BC15D8A928B3B72A87DDA470FC845F49F2AE2B42B8B5BB848C291E365787B6080F6747F93970A62D8EFCA256F83A561FAF5908587CAF5B686AF25DB068E38D9F94B1911102209840FDCDFD7834347E558D46F9328816A0F8600F05FC39B7AE24E732042D5BBED21EB2AADAA5BADDC8B0F48FA964C0AA0BF05109FFCEE9B0C363D7880335DA41BF62F22B7F3C52BBB55F2BF1E6337A6DA91E906EED50305683AD55B2B03569A28CB5D48894900AE95FD896525A690ABD345728E3DC86B8B3CD100E2A28E5116DD026288C288A9559A277028759CA3C7B33A46CE0B5D9F8909D1F7E560560A838E50DE84AA420B8D3AA7424EFBA6DBAE57806290E207DD07CD281F01FC20DE2B1BADD8DC79E80D7F0CA7A549FBAEF9D3716C1461BBBB595489ABDA3443447B3AC5AA44A24E7E0FB9C8421C96DCA2951993886A2078BEF6A08811F0C5C7C28BAD178DAB0AAF319A0842F31E7EAEB16AA9D78AD52EF4F57E38B1A9042CE1982EA382C16F95AB2B07D810D9280A322FB41583A0D6574B7B6F67B4254F4705B973BBA80B0038FC46E27300F409B5392930368039F78ED978BB615A6FF1697FAAF0E6D450196108B8565882DB0FC3E74FCD91A809ECE5AF7A1B466BB90D4062969D095A00B7BF54D5EE45DB9BEE7206E7062A466B02CBB3BBA2D99E76F58B969BE84AB65A522E59A1B0F0B881BFA815463B1454B49231FC486F823D74CBE14BC07F8D5EE8533AECA9E7B56E015BFA3904439183BBD5B8BE137F1D082C3E97EC798698FEAE544F708C57E399A2F9B6B400497826819B392673B69ABD06846277A47DF146DEDD10FCECED0CB497F2F1396BC0F27734BCCC7A1F13D9E36287AA3D024245FB6E2870B64090A428E7092FBDDC8CAE47E84928DCE3D77082C6386C57C13DC3EAC73BAD146CA60F67733350A365F8C5E0A9771AA2D1AEBE944DADA3AA036340942EDE725CA0F9296ADA1B5C8DA25D7A3D2E4DBB3BFF17963BBF439D4A8058EADADE04E41697654B819323900230B50C326D5F46BEC0534A427B8964247062540060330E1BCDACDA59C126612F56216DE4EBD860D091C9CF6A57B3D7E7DF7D1233F23F325A46715E67709A63084023D2C11899066CDCEE215A1945207C9E5AF19D95E6DDED32EF6CD0A617CE2CF0C2F3B098DE1CA865CC13DFB60953608536085B86D91E0F30AA4CD853BEF03EA518C188E231E17C90F74B9FB8AB6AA93A20AA0B1F8DA54B75CF89CF083C3E113FB5BB8B04E5548EC051B375C2D59054A9ECD6E0FDF8060D9D8253A55087F59457C37589FB6D852974F015E60C19BF2615403852912D4DE6BEC93FA6ADA52997B8F5B51FBA8C6846A03D825EA87B1BFCA629EA776775FDC24731862A29D9B5DD6985BF4EFC15DEAA4DC2F99B129C30E33CFDC969D76BBEEDF80CF5E5A993055ED6F5704F3DFA16CB03D650F8D03DDA8C0C1A3FFD0763F823C601612ED80C00841181130347E3728516636B65F913E8AE18E8C648002EAB877BCA3DAF53CBBD5FF58F653E263460629E80E38F1217B91A1151BF008389DF44C8523D93B160B82CF3CB2B51C7FC6FD23E151BA4940C488D9F4554440FD03A86BDF1E97B1A92C5C66B41B3F600CEADEB095FFC25933463F656C806FF0B44894703C5C723B6B32CE9296782C961FE816BD005145EE60299080B1563959BB2F9496CF645F783A781BA2ED5CA70D9AB7B673AAD612EED9543E85F6E1440B4DBB36CA2384E674B7772F9D6F7F9BE0C8D974471194906654B0D424B4C4323E69BAAD86146B0864B770677F227C04811087B2F80AF11F3A +sk = CC568AA4A3DBBD508E987485B26A8CC116511265CF26166B535C09160541F87BA7B45DFDE262F94D66F558FF508D0C53E0D9839259A3E38C3DDF3976BE43B9CF9F50671842A52E938CA6A5E67EA00624394DFDB5E2AA8D0EF509F7BA41E9BA56FADF07765174B1926F4CE5DF845672DDDF4DE268CCEBA29536A9156C33888DC638507607645810585260283336743454721816141536151343262832015412524424785544623888411756276545173247124756423710472168455171601858161065516120838201451080573561754700855418100422048328303718342576135647516480673861040012037416473135768037120641657468871562544642156718237826713077688668515174048544767472280417741037305880287408360728887445687815272855345201603355873072006032287137811233103513444041756363243121521010800731571127853848727370182844557146743804212255575501224110477551430173878133066547258003340314654458451383758672858336524683386136348251518113641602301001257885101817112442578458277480641402360841204524273771605776550887733363781870852238504833718707572156236771811333867118773446851465513017500267483733453777634857414442800314747311460644188700637167766103511885857338104666550567674256335668106668486516640647382306448270834358352084583425553330884656434512154427604464018500860452121740444107061872532731643270743124306682326716086187588214115717140048607163624250705864705240727421862070222756014887022160534345425184016500720205776231578162632514183720110721514450286176160353183458236516466386875375013343625667110384518801214885804051370525842027568587114376851355056153586658368407375372864751277383142704832380355647364431334371460743526618112762366757318461322545683460073716155634272488003665871815804784225308577284451685288725022854843835625407323056251204763314035216280842037411534507215661111273760581814643808207718573073065543100733516886646167717043316424350604104648678077175455572482254728431437467205504273463257525647572512844885070853686747155366523831102611380852333072316310483664221523486428128330645204714016647328028237602146602004586647106568485573453856050746843722561554176107203870173616452674735644321087274108738408062315526018528264113388524685060304505506377150872875457213824647143036445115117267666372812108202050743860587828141156346625358712358724058604576213047843020524267023823880421388576501421516513087436167323216804237608735714430614415716306805427828050148430178651130034103844125171113420212627443864251434538715486568040241256647455005572366158411875423236212841265372356631585201753206573742723828347113347662736732824617838470865620046340160725247767420312306225658186327742116823342727154650155130820220324186788481053441340751767375671654146365826388384021247251337234606822461558646767837101580127310345487627178502263663203185870577448131136538826233781357002407766110351646711580363473735212487116085268853535140751580155454635407622264142170407554475112832322822821478570857158721658865872308003344118057668815240202205036664408468343564534807240484870753086600373888687728864741831236250627036845760743706741885438452836710603407286034070217180606456628134281535074508113316885882540710770144015506520816625853648517745346575582776134047DD5222AF2451979EAB1AFB7E00AC0A7813EB3E6DD50194494EF79E911F2CBFCA2922A54F05AB0D79F5A2C4170899E75C810EF7AF320BA8EE51BA8D9841D146BBB94A01FE43F0810D47899FC93368A7B33D9089282DB6A18CE99F6E7F597DE7E77C006F5749041D6D2383C1847B84593D394FE15163EB2E1FB37BD39E5DED37BDD43108E79C28D369C4F73ADA19C7297A8BE71B56D4590E7BC1A78122420C796B1461F724BB03F35829BA2274DF5688BEB761FE753F1205CD4B78B371DF7A6F234E043E2EA4ADEEFA94E1023A212C9B69E71D29DDA8E6AD6DBDA0EB3D08E1A011A4E90CED3D112EDDCB6C03D48741B4BE5C31B55A605D4718555A0A5A4B799CC894E609EC2A6CC2641D7C17E9E59078BCB0BEA36A3D0727BC5063B7A7E05DFAB0962AFD4387BF2F176CBE1CE7B491F1477B90C6441C6A6CE1F51662B281AA296CD6C57F019BBB6ABD123D9FF475995C958567071B9078D7DFD6892F3398AB141CA606F7EA2203E04F6F6AB4BBFEC311034F4900AB190381080A10967D5C52A1DC7F47BA421CC68324E73CB50B11E3B60BF4490F0546EDAB5F9FA1C8AD08C729A0F1410CE4ADB2757967EE7465A0878871F5925BBFB0929F0A7DC07CA2E76AEC9AFB7EC77A9BC715BF9326566CD4EF7F035A68426EBF3DAD078411065A9A00953F3BEE4E6FC0437C013AFB8EE14A81C324F30B1FE5C2B0544D65FC4D697DD7867ECF6C27C85433BD9BA5E0B38F948AFED65C836EB97F48E37C6112000156ACD64A84B9DF51409F56ED8EFFF7D5FFDDC163ED3E8ECE85972D81501F2AC819256826C3097BF24C827A21AFCCAF4E8C9061C16FDE5762460601C5E6FE8E2F199F30A949283D3D9EEA11747FF7EBD07419C96953B400877344625283898CCEA94F1E4A479D5FCCA9A574EAE5C01F4A0A224495686B3C9DB56EFB119B6C50D278786280BFB1E6444EB6CB351560E91D7203B8FED3322114D17B69A5384369C5E8E7E25ACAA460CF61CA1EB3F70BF68E9CBE2E185F3A66289C50C5B534636C8CB49E171AB1BF141D5D1B19B94420F4E80F04D8C6C7E4FAD15ACF3BD8E050A8533F24E24FE37D6D33764DD75AF4B40BC4F59E488E92A9B3D7784DD9FBBF3891FEB8AC8FD69B94AD53E675EF1F3C3BADCE01B90C64A7DDC5814153C442F211C1AE49F3A80514C91ED2F4F10560C0626FCD0494AFA08A987FF5C19F69B183564521F7AD984A57BE4F4A5A3C945F8675D3E87FCD270F5D68B0C40D82BF2BE8B81421694D68AEBC26B13BC910184A4F656D0A6C011EAFB4B761CE7E9B6A972A5569CD4D976CB00717DC1B35D05B88B35BD1FA15DB7819E7B65D2E56B94C1753B867C3C608EDACE781ED680C34B718C6A551225F11187B490CFF9740B760B5F0F9A917635A6D912CFB040A11510E4A817265569A9A3412AEF79BEF49D9691D65A5450C29830621CA44E93852071B19B590BCE797528E90F732D205CE4BC39A8243015925B746C90206146E02DF0C1EEC0B4DF3E48A470A2C605B30187079F0800B9713263917A1388285CDB762D02F9132382CC4457ECB408DFABCE5897A8BFFD3F3071745A12F2F8C29607D384B81B27244C159A7DB200D726A3FCE54B9A21DCBBF1B47BB40352A293B245AD12E5EB1599440574C738CF0F57F9685434CCF1235B5F9F80142E71ED01E7A214AEF05535F71E2C4C1BE273E5E2F340369E0B07E8CE0C800252498A91576A0528FFFE38F651CBEFC8080625C4356801B2B7135C3DA81C333416B0D6E7C1E08141FC3BF010E2B753F08CC981034DF4944749AEB8590EF2A828CDFD60E699C02DD37C0DEDE60AE124B3440CFDCE982D77C13E009C26578A2AA101D1CE124D352138C76C5281B62449C7E4CFBF68E3C8888FE4D095DA38307EF6B96B28308FA37111BF61D7F1B113B5EF1FCBB98CBD977E3A282368EDE0A160CE83A6A88F05CFA15087789D81CB6C1C6F4DB09B560B22174C04122C0DEB62E1975C0F75BA2732DF48ABDD2643A0D0CFE793EEE51A76195F3A1E193616CC6D5F4B577F820C20C7364D45879BDB924C31F07AE7E373F26ADD8A60874A4F3F662C86E95DE5D3D059484C0AA510851D1AE46326F167ACD1992A9A1F61085A905E45E8F2C4D4544347E27E421E9D80BDB03606BBFEA4B845808F62B6F643B311AE001510FBA56D8EC6D43848474F8E1B13257C3DC2D70CD1283E78932DC06CF76F2B03C05051C3FBFFC703CF180AE03A3CBD49E057AF6E7D0D782E68A7E7D8003917A3FEE6A8131C956F09AB3AF51BB54FF994AAE19121EC55A1376820CDC0B235B4AC7E591FAF22A54ED7132A3CAC360CF86FDAF9E5418EDB4E9C86A0529E52D6185A495A30E84C3EB29121C5357B78C80FC15B17D33FC53D09CC151EFECAB12146BC86CA15A70B002B70C245238ADBD63ACC388124111D5630D6D78643A5278DCE7D40410E41159368024833C6EFC148B2FE9AC37463604BF374D1335D9EB389E6716549E2E1E620EEC6A7CF17A9A0E8C6F950F403B5D3171DBBCBC2332946BC7D99231C24E4DC531B8C864C015B2BA5531DF9257DD145DEF1CED856FB128115CE59C8BB7FF29EF784BF0E1DF7A2975D317EB2AE9B881AD7328164FE8A5ED80C2A4BBA8230AC5CF551B9EADC0249519D52DBB4786EC38E0B604774393B591E95C8A16E4E924A209ED3477944CB67BF282C7DF0D2F0C84287554F1D908BFA53FABC1640382936E5023B2458B5F4D0B802B68D126541525982EDEA70E850C8570F7487EB57CBD87C81D432C439DDCAD673AAD899E0C910E5CBAD50951EBB95861566C7399B52BF2CF717E19F3E15453A2A08E9E700EB141090946896712CFA13FE9CBFCDA8151F788B3532D9E19F85C196058CA2F853B811DDA8E3435A3ED5A5E6A403CB445AC60FA78C69943B5BAD685BA0F77878E48EC5AEAFA74D3D3F358E11B24D340133CBFC4069836DE44A7DC149E46616C017B4FED612FE2F36D174C0CF07CE66B2DA429B41A1BD286ECF29BDBDC64F455019A8555CDD2259C63A8DFD8F24562CC135FE289C4AAB9D6A17CB0948373362DC801BFB1623ACFFD1A9975572FCDA8EF5EC488C859990A7A6A02FA857BFA5C1821BAAF0441007CB92B87C888A7AD80B589F3B2783050A7B7D38CECEADD64D566F759A80B28048997B5828B30C9775DAC9B094A854146B0E8C4059E3946CB47E03507444F5C066EB8E61A2465A90DCC9461A12AE1F5D5F2A7B3AED274E7EBEAB7F0914535CE993E01927A458F01B184C089C43B499A8B2D9C0633E0067C022B7343B6B71F64F0CD41AFA9932B9958E961E5AD7338CE05D82D20EC9023164A1A100B25CD374E1A27B1E28173DB05F0C1AFF49A95E2589B9A51546CF2758E0BFEE521DFA5D1A184BD4DB28F9C9BF416B8DFA550110467B53B21C404753E7649B79FC96CA599991132BF1085AEE4BD615DCBEA28ED305C55B26AFCD91E132C49B4ACCB5A6E13BCA6692F88D7A9BCD6216A8DD98F6178E09B37C0CD222145D75FC45F3BC7F276EFDEF9506A87790E0C95201DFF +smlen = 3606 +sm = 425E67100690522FE7234C3038B9504815927CAD74AAD80D9A6A33C23421D87B1480A29087EBC6EB47F3F3DAE17756844D30E7CBE459682DB1FD102E0D91C81750A754747C73836BB677430504D3ED6873F0BF046FE7DAA02744E581EF47F160440C17AC78C2A2C5D6B138C580A7F58E1DCCF47092C70D4BE454953064FBA441521FC674A112CE47711D36AC492AB48C1EF65325D0A4A063093FD84BE65BF1FA18065A3509C35ADE9DD38C6131C56611FF309ECC5ED7FAB9049B986F1D4EAA087628B892BF54B4545F6D45B9C44788E974AF01A63CF02505F1B13868108D8962592856427EB3375D70F69B610DAD6916D380F9CB956E3785EA2025005546E6B4D656307625E82768E28F55A84BC21A920FC1EC9DF1157B85566225102DEB22861AAE3D76465352214B5623A3D2B790BE9A800AC086452A98916155A818040297106034AFD8BEA4FBF0692EC37877174645BB19CD1C51748BF156DBB9FC705DD33DAB9E88F46C3D77FB1C8AD58B228459ECC689BB5551884ACBCAE3F7E7AB9855B8713BCE783394C4B80C22502B0D9CAA023BADFFE13A5E635578D9C7E5C8DCB757588943D1C1AD0932B3174B7CFE3ECBC5CCD0E1298E68EA77ED3D6A432AF17DDEB59A0386DD4DA5F925BF785CB06A93782164555648F9A0BB5F856A34584C00BACAA7B4F3C659D951D2D82790FD945D6B2222206A68AEBAA1523879C380FD7536AE48E970E52B07213DB312584540165E3297E7F4AF781F507376F72ED8CBB9090E8EB99D2F4EB861A1AEC049FF769B68C14DAB697F9842F2C9C036C32B4FC3F2423F21A6D42E1BB84C3C364F30F9C4CE7ABBE3A0815F05A11491EB536A449338EC1DDCD70DFCFF49B3D9BABAC8F9651765156BFFCD9EABCD375376245A21AF8436575EC5607BECDDE6B6E8CB59974DAE1A3AC22E0F16504C41FF90665E5B00ED1A6434011E74E309E69360FA36D0CAC38FA9775F2809E9AC07C403440B63C6D59F3FC67A0D73275FB21A876098FD0A39DE422CBA6CF45CDA961C6AA281A8598FFEB0E55F644B06AA42FEBF06B1BBA9B6B5E6EA3B69A6BB6CB27CBBEB17A52FE6637CAB8C27291566766E8698188F89CA79577D4EED4CF8B7BFC3D3C52EB1A1D0942B5BD827FEDDB903D02CAD44D7FDCA24738887B03BEEFA881249B4DA919F559D406D1BC47CF9D063159BF35DE466C06F0175088C7296C360C90A79F4E63E8E0F230A78371D17D7532746BFC3BCDA5BC9E678ED16E84EFD7DC87722CC503D8DEB7238F447661437D500CB1A459CDD9DF9469D0DE920D07502BDDCE8EF06F047D35FB99CFFE68E9FFD92A05F86B1293DAC04C48EA7A0D9103CE9E62AB37AA585F1460B1493DE805EA24CEE62786D85BA57D16CEE13C65039153B2AF1544E86776D9CBA127859575A4F6BBBC947E23F239985F2B2B2DF0F39D13ADDAF7E57FC280A596E6F0D217640B04EE661D9BBA333BC80D749C476EF576F549D1D6BEF1F2598F9F3E41682DB805F821C3592C4D765C84008CBE5848C616A2EDAA9BF0F7641EBF909ADF7B6F90E0519E39139EECAB478A9AFED7321548B22E114375448DA0B4ADE68835B61E5F57B2ED9011EDA84FCA9CB2AF12D3F0F7568F7AD0383693AA9D5984B79A3D1133C8C5CF39E35092CC7174D7F51CE18C3603189804A4A6355E70916F8C53C81B43643075B692166147EA81B05C522B15EB93012989FEDF702050A85988ED614C911C40E19775C3F5924AFA90B4268AC8E09F8945537672D45164A3F704A7526EEB66DFCDAFD04999DA8C9F0AACF1B817E9695AB05AD01C48B92D9EA261E2456ADFFCFD7AEE4AC283A0E1D9FFF1D99F81BAC2DC4187605CF32E56B03572C436D3EA6327ACEB0C5D2CC9ADDBDAD6AF965614C27C934DD3E936201997B8842101F8CC045708226EBCC535B646BF3369A7F5CE7DA7C9F5C91CB0235A4A5845204ACDD740AF4C624A3DD4FB0096CB9870970683A2793B72567B75511CF5C07E490AD4577DF5C60C341CE740E59E8B20177917A2C61FAEAF1A0686A72448F3D07629F8503DCEB09B865F33818015BFF1D03416740B8BA130131B63D6C8D4D1AEAF59A1EE9E60075A81AE5999C4D5392FAECD664C8C90C74C6B513A5E87EC98935C77A386654267FB2C2519BDE403C656BB932C51C1467ADAB65B82CCC46F82633DD6599FBC477AA064859B575942C7C5B25D8EEBC57DCF68B29041C5B88DA11191AF9C8280496C8C740541E3A0C320B32A08BC605096FD6A518E8DBF91001DFBD9171B0EE1F55400533FF1186961B8651E0ADD57C079E3B9C71D7217EFB4258FAC6424BC8BE893528D562F16A3EF471FAB9C359E282400BA2B934F9D829EE98CFB44D55836372D35EF83DE2DD814AFFEFAC10C5C565181167CEB6E5C2854F7FF3E4997C99CE7CF975834F467A31732D9A0FF5ADA2AF84E8C52D495E2EAE72AB2A49A337C5CE8674FD7B86597C47F7686DB7196F5D021F891E0C202ABA67B5C7D6B5CDB2E1EB48574FD810D660E84780DF345AC0C602B193EB5A2C61DD5AC7FBA1DA4AAAC9B959423E680066FB06D72D26A9AF51C3C726F1791A2DFAB09BE76E6B6E8F732DD17EB8F33D40FDF10F3E828FBAC5A72E4FA455E57DE8982345F7931CE6E49CFF3C84C0F53CB41FB7BECDAE4A130DD3691C59AB4AD9417881CB2E88F733884B780B5FEF76BEDAA048DCB4E22E399E40941BB5C7C53A0EA151EDFC262EA92AD6C989D2D6AD10E95A2C728EB7645DF14A09D231D4BE219B7EB14F3D8FEF18F457B9064EAB0B055F59E898641C3824D378B862AFC1B90CBED2B81EC7062B0627EB04DE14CC7E864B264240CF05A83C28DA1AB75294959B97C772F1B95D601E00C3E148F1D659DCACB9E798C2E91F620E3DD3492A2D87B972D925EDEE28018579D527A0271AEE36417203BBD41B270B1C245EB0A05D139D167EC49CFA6769EA4C0AD33B376B9DCA51DD51B2679245A1C01A58C442D50F82D9CCFF19DF485B69321521F513EEF6B5BA748936B01137F71305390C6396751B96C07F0FF8F393732D0E0EE37117699904DCDBB568C79C518BF2215A0062D56F3B3D2E68320D1EA599A21DDA866F30E7389396220D70FC7E66105703049A07461BA5F91252902660182D40903FE5F748793809032036D71644EBFC8A362F1A22FEF61338C1767B4FFF3052CC561B5E89657935A60F7EA9818FC243FA7C602E6742F1A24C87D4E00DF08A585F1CC702B860559D6CA088CA239F3FB90FD6456C6F5D927FD532FAAC1EE23335A78FD9F83AEBD60241C49AE68ED5FA0026A5F3F125E520707869DA4C9DD38991A4A0E712E3278431996DD860732E18A653201E4ED4B28F0B0E7C6EB7C85ED15D63BC91E792F7034938966840E0FCC5EF27656747C502FBD234292A26079BB52B25EF97925EF412F228EAA4A2581B128BD0EFF8012CF3E7125CC38DD1F1DD05273A7C68EA78540E19AD842ADE31F4C2B676E4F6523557CCE918C8E07AA7C48F021B4115560405ED6DC234D7FD599F289FD78E9B122661C87950BFF57D1D18B884E8F54EA8183C8468CEE293A3375D7DC8676F247A492AD733D7A8E27687759265304E429082BE43656E335EAFF39F89DF2AEEC6F352DA8951E45E0BF1530F1457C6E86D4F69B1F0C76FB15462F31B5A21D9C612A3E3D0DBC0D1AFA8E22FCB7EE651561C4E3FF2BEE64A8B175F55EE58F614127F9D15005C8EB8AA603B7F50FE0D1A86C5C0FA31E0708549756574598B93EB48DE06A54B6FEEEB7C0921B9E4C407640F0F0E6490D7DE02EF39463B66C0FE6381B4DF4C742A8F7ADB9F230AD846CFF14DE3E1871ADDD96005523BA12AC91A869156549912A2BE3CAD4F331B294A3FCFE963E3A79CB83F7F1EC984C044D6A80C66D445FE7FE17E4A138BDA52C7834E829858C96698D0B6199BA5F846F563DF39E439720B3E87596563FA742D24D5F3C174E8E82DFA9B9EFF88B8CF6240D839B6652B1261C45BB250E0744A07A0B3D647F1AB9D7225AD0A64C9499BDA639FC5202D5A1B788626B7BCE0BBB37E6125F86AA8F3186E7CC889C7336E90A1821AC2B7C148A10173D7A425DF2FC12EDA7D14C3A651FFCFFE7A2F335FC0FEF63EDCAB968696A8E21D7EAA9BA6BDB30E8D4061D3A8F537AC846236CC1DCF7F0543C3D1FACEA653D82ECFFF30096BC279F2B66521645E9331D00FD5B70F15F4491926DEAC59A7D4C5105B35BACA557BF74561472362EDE807FC304A1C8803D2326FAA38CC62D8767C665E75AF0B55E7EF4493BDF85F32061C9DE1E69463AF3527EE8C9695635E2B59CC559E57ADF95D1EC06C2A1A4B269A8A56830D7050CB077DAABBC479F7BF3F25E3F5A702B471551FC1BFA7F0EBEB9FA3752E37551F0B842C157CEF39996C1D109610CBD1D42BB7BB2AC0D036B2088B81999DC276596D8E6841F829FF8D02552610DC18DC88ECCEEDF41977822A2EDAE87F02AD36A4D49DB3AF45095D98EE51C36C6FCE921231C3CAD21EB1448FD5E565DB59BF45EFFB96B191B6F55CFFF3D1017C5580DBD7FF73DBF3E47DC032BA9B54DC594672F78D5423923291B69BCA6958629B7D0313E549C1DE08D3CD0211284DCE22249D3A5C9599A4A9C6C8D418224A508EAFE4031622282E526C70787D8CE6E72F4E6C87C6FD03304243569AC7CFD2000000000000000000020B121F252E9366ED7B3B623C411448B634446F1A3FAABDD163A6CC1E2BCAE4A98703CD8CEE441405892FBA051BE2A586A6950A5EF73A255E5F86B0D7212E0C51C3BC79BE4B88E76ED6F043FEF3204FAF044BFB1ED722D61EB5D0B74C66A257E8AC3A2206273C80D2EC2123A4DBB715D60118D99ED7322E38F1562F82379138DA3DDB8BAA7CE61AB729AFC3748C0134633CF45A9973C05C75D04E82F631845427626B5799DC07DDF830BA01E8BC6236BB6D03B37D949DBB29EEC7DFE60FBC17EA590956D251539792016E2A8B01E70476961BC9ADA43CDA682D0CAA4FCC58810BBA1A673EF8F6BC90BAEE701E8E4F7C04A346CA56C7B2862FF57756CE6CD1EE22D677BCDAA896EAE96F87870E032C18B6C6A0C1A191FAE2ED487CE55296CC4B6339EAC9E8A742BD0A44C3525CC750 + +count = 9 +seed = 11134936880F5A11ED3504CF7B273E55A351FCCB10943BBBD186623EE6C7A13A6565C3080D1F536BFDB018F99C4E46CD +mlen = 330 +msg = 0998114C84F84080E7EEBB47D248980FAC9D28F1ABB6DBAB3DD59A5CFD2C7CFF7F308372874DD5447C7B02E30165501C0C673128E4C543A414222BDF47E7F4E8DCA757B0F4A3281C0D10C4F02AB52AAF5B9A715E012607BA310947A60A5F62D6B8CFA96386D27CFA709189202421C078934AA2D955468E550AD4D0D4ACDD98B168A9568E232192E92789830317FBC959087FFFE353B6C168F3EFBE7164444F1D6CBA5246E31658C65440A841DBA78257E78502843EC1A6E9710229C8EEB85D6CDDC7D543285624AA1F756A5DD4F1A5D4FA52DB8C5C34880ED448FBB6D254509FBEEA0FA022F276B6A66BEF7ABFEA6049FF74291BABE781F718683397077B29FA9E2B46BC6B09251E587CC5B182195DD4060CC4A319BFBE251A5B660A739DFE5D0E5B93F3CB7E440194F1C8BDA922CB1A3EE3D27EDFD61C1D31A7F4534E84889EC83B51F1641892766434 +pk = 2CF2986B5F5355BFECF2ADD674881D6DF901A1B4443C6C737A7F78FC7CC813211C4C60821BA0A1CDC5EC9FBA3840E7216E6A239E05D6A86B566520DAF684794E279055F63719D99B5EC1146FC4E67C6370F28B65A8A7BB44B2E32F1A7C0028C6FDCE695E81BF5019FF343F77E1F0230EBF62F0A5386A12E786F33241787102EFDE0B9861998EDC63C8DC5F4C26C24E94869FACBF53A07AEFCAE4794FB1AE5E826AD25D38A83F20A006EC3F4CE6B06C496F28A4185FA5AD0A68B3511C790B7E2F46BEDED71C5A19AE33A8C2601F491E7CE3FEE0CC7EE404890E7E2E8216ED290D728DEA195B5B2B36F57F339AC9A63EDD5ABD3AAF2CBB1751CF98DBF84F78CA60215748020561CE83A9625EF5B702279307FAC926EDD99C112ACCD3350A67D8B95A5546219D3019FAEF1BD34BED424C2B552F86F99DC61381BC10FA132BDA6977E389812DFC69F447F6C519C3967AEE5CB93B239AD38DDBA1D64CCA5948EEDF357FC3B683D63CA1827BAC4A4B71598AABC0D69358830FE5E8E0A24AF9023F71E5DD412977EC667947B8402F69EF27A0DA7CF00CFA36695935319EDAA0423E1437930B13739A23406F6E5489F8F5E1A3AFCD537FD7A65FE4B910713D2F4B8F2DB3DE006BE92ADAE23231B736C540689668A4ECAA8E3B91B27F1FA760B4CF85E3F152CD1669FE7A04039626578B5D60BE1FE2AAAFBA83C1C7485E16CA17C3CCEFCF738741788CBF2E9C9B0E4A68194E6655243F7C1501042F845FD08A2A6CFE1A3F5622BAF1D621E63B9FFD4762466D9DB9AE78A8A4999F13388B7C03A2867F17299F742D5603E3740955F737097CD86D97558B9CCEB12D9A54F3AFB7F359B0DB1D2C07090346659C846A4AFF5118C2AF10C90D11F0C57E1DEF169A07FD22CD9B2A77549A6145BBC645A2538293AB6499E85FEF23D8E33338038E579875746CF7DFDCB81FAFC0064091707AB090A1A8CD43467F628FD0883E2755B13134E838D237EF0B9CEE083763A7108CDEC04AC936F2FA5446029C76363DBDB82C536A738836BB00C996CF91F8499390531E0DE0EE0B1C8CF317A3596EB93DD433A64CE9FDE61E3A16EAD1A259430A8C63656A216679584CBBEE7B333E82D2779A15C83E1E9398E1E229ED0AABC1E9EA1DE07566DE7128A09AB3656367FD733C2D1E48C9375B12A701D832C53175CC74B5936F3DFEEB63F5545F65F0E2E7E481C03538997892B11918684C2FA321AABCD50B721A26D71DB381013691ECC228E74667E81F3C6BBBB58012D8B48201C75B2191D3ACFCFEB3FA4B74948F656DAF1B981CA47D51C51DBBF829E611BE19D7EBFDE3365A11E14D3DBC5F96C4CA0972D6F5922F29ABE60A4B3CE85CC48697C1E4A563976F85B8ADA5426BF0DFBAC82A2FC7149EDA63B081273AA4E2F0F42DB49FBD8F63305F2D436D6A604820B4697BB7EBA9ACE2D82BF4F9D62024301684C5487A2F133CC38E542C4B10B63C2132D6A76EB197994BD7706D70A07C0CAFC125F2E8BC58E7BC27A02BA133948E936BFFFB955413EF3DA570B147196181989208A2DCBD6A032A5A7B95DF9CB8FAC3F5016ED12722597240F49C9DF41FF3F931A06FA01FE800E10C333259B4EA4D8BA37497A76FC4C3ED2A113825E051A6959B807D3849FA6A2347264B567A80267E44C98E25E51CC891086840A89187756DDB9ADFEAC4A6363DF341A46CFD9CF2EA73F6BFEB8AD9D15555FC71AA65004C9E8300CB40293845CE3855D69CD3FA2B022C6B8AC1232ED43300B6FADA50BA327F94DA731771BBE22E00113744B6C7061C2A5AF3682A2096B5EC1701F79BDF71FDA160247C23B133D71877FFF68FA4950EF5C0F4168A7BB475718668EC6A96F33E9FF2FF68C9F0450D6AA6F8A647384ED20346AD381882DEFBAF9A191BE97DA96BECB35FC814D26F9559C13734A2EDC11A600E1165B64811E83C8F46E5CF6DF25C0B777F06A42B57D37E615555FFB99DF45C8E58EBB9AE6AC1F31FD906883FC46DFB35D9B5AD90040C93F5FB23017568836768027278548E8DC7E7B57894B238021712F1D1A51BF20BDCB537802F76E9298414895BB0B332C53A1867506899C05269828EA02839C02CE3A86D8EA5D9C5ECECB06A88496E0E191D586E7CBDE976C66D2E15FE9D334598F9F957048322F1686C6E309F5F9DFACB4FFAE9E72DDE1BE05484797C84F3A205DD597208F067CFC55B8A9517A870C85F8FFA1A72923B18B3E2CF1B7DDD5A501B07A8EBC9A592EA8F9D611AFBED7B2366C732FAA4FC177F64C73E7E118527716A4DD26929099C190BCEB7DF6AABEE8D18C145BC54E23BBEC7969D083D90EDE86C579D154D90E808CB18202AB95572E6EC474EF4F47DFC919BCB763C516D70019B2182C016C0D96D4D00DED174A687658CB927094BC7CB1D3A8CE0AFA486C7931F2361F5CD205B15136D1E33D295C6FF7A7106B48DBDE90CE4F44624DD6FF01390DF35FA27EC82249B799F8C2050B35B3740ADF4113698AB6F5AE471E415101DBAA8882A082090E9594B782CF316F14E4FF41A66A0B276E0E1D932F085491356770D24C76678CC38F725E63B2FAC6B25D06E8660F8A7227571A689758F4A7619EA32685535FCEF23E58EB390175A68C27EFA3250C92447D7FFEEC27B4737AE5797D80FB796D0C63AEF90DACBC58254A90F04467AD2EFA33DE445C857C86E3EAE2C42856C80C469D967AAD1FBAB9D1B69F8AB063B33B9FEC77102036E92BD3B9A446FBE6F66E254E95BCF696200564CE62848 +sk = 2CF2986B5F5355BFECF2ADD674881D6DF901A1B4443C6C737A7F78FC7CC81321F9FC5D07E5FF5F9010BEE3801906847C6D5E23E7FB19170CBFA4D06C730D0BCC2DE1A7622E230AC41A8AA9AF64506F1025DA3DD4BE37979C6AC7FFADF58F63209EEB0B441E6A6A435FB7523C7058AB643DF9E99F699401666D85B00EB2544460303681824008382281803738163503767040663610403563520551086734151568371458355236516446545206264440741142522158183115223107518743843001423854203831464762076087483877027142287520313686224856606318557864111478471183158881654746522483561075343542466525781473746367875784572775187253552433762170007838204251026651622462707135031117626557330771168620153307080560643513425026776867673533778133881161782364041123700702208523810517710847368518822041507504400738063386121166763614630137173465435807474200666730103832287423732310517624304276564531376351326345730185302487158676026847555470324184844633746843387227304880534545515348605683728082055538285880637631487644501667647768400648681037878265658737478736624554865231457378042640423217787325142116782131218576240636154620537255031731503408774386280614065163488542864488504015616662204735443582637452363732238451408361647581406612078732307072530035016776283835858275706237151330280106104375182002614626135537771760481056314248876003476788181402425088517483673411843304178617780055206161376202014152217553075233374445620164627166515151128664748278625342028538447685618565801546321322608603114121613217870031148355302157876216453320676816303354632612580208656537460771755467656182670378626808201467422563838510386171315053623051235726752851284213357267145128025503131265423376226265243474266778630317845813126136235022517448164010644186107425647206378355568107532375461116670671267506810017530144845007332606108841188613884173372465540437214386668248716186538400546205402621885033587602013274603406478204833570027755411563853403736444646788826234703532723430285125755370551837654440760630863025272258070831348542547303670841657636723110780603858047810441607645705181023648781641265517764685400813057328782506132336170062130433262333435424480633617735178858401352277540144837712477347512811238621833205628658272727874520086530650421653373732805318211540355480331211386282142431632438742236588706427580328354723024345383101723307350238547312217532710408131141680781600451821574776631663208843407243674343184332243354657443843024830246180620774527158226048442747500001222581733817064820433300643558842670183202315778242722776450287047477555117852257818725751350826535621220335300384816656265604414482328857478343501648672654463357201455062427173604107836762880114378685851113568863112578528414817878384753185384713830675006501246786120644801308436762158037178766303357131887828030605117010336162722230356715720588228333455246740330538102251373826335810421311227375317128028371611562664715547367421228021745632155106552243271133701255583011335371040874008232746541072307173203065005278324184486183675358105552233120636835104586142130342070026125561534407247688377362367202251440423415420511130627880410700238713346714432268887641240716452068525471776476658672535605737071074263022458F6899B211528035B0B406E9D1B6985A18D8FAF423BD42030DEAE18D347BDDB1D0E27C4302C45629B3F4CA911B3FEFD605293D632C4ADE7AE73DE532FA5A756ED2D9B8F5BA45B63FB8DDCA97032BA93CE09E545E0BF1A8AA24052A0CB2848437F62C9312CC16226908C0930E2FB4BB583E56A6F76C164EBC7C1CCCFDFB6E7884E34249A8C2F57E095DB112CF08CBDA7C1761C09D33D08319866E513215EE46F6F3F0397E5FA366358AE6319E731F4C0BBAA50746F9A63DC310749C9056A5C9796E42523420984BD8F7F842BA1468943236F7F85AA5EF9602A89C2D57D76CAFF6459F773A912462EAD959B37CFE32B346DD87FCD8E60BCA5799089ACF1D391D2FA3682924FB2923A1B6B5C0F6535AA3B731C72AE1A309628732AA866A97CAA2982BF0E993A1CCC61A9AE7D7C7E4670B0E21DA835B04C3A8A8F58F6913A6F10B07D2CE58D38896DBB495A7F7ADB147B951A81B5627338BF546808E1CF23B891F7498CDC8B94D010329208EBDC8BF6E03050AF2689CF91C641DDE9EE2AC48C1966659E5971CFD461458446DD61E2E213A2837DFE4F41751D55C8FB7849AF2DA323A89E80B7FE2871668F3318D92F230078A21A286D9BD984688C874B56649E9D55E50BE5D541C68606518891B689E60B0A586C4A00A2512C9B1513B8D56CFAE89C8A7CC5F0AB40ED27F7759B04282B25B4CC7E18158A67BF50AE5DA36BBF738A537AF46DFC839E6CADCF8340713792C25D6DFD5DBC50792DE7D67ECBCA8E570D12A3434A6B6FC7589E2F146746D581AEB004BFAB62CF566D9B526A032FE9A4A18B6FE1F8939B866DF8F4AA02420812E43C33B7E68DF999B561F4A53984ED3DD1D668CC1409CFD226B4238A57D66936F1FD4AB73D4CAF36AA85398C42E92E4B85ADAD6261643E7EA649506919938765EB66464632C58F94D9DEA62B14B5D3C02DA32FA24274A34185FC8783BEC914B2DD2414E942D4CC13343507E8766C41D10D85E3078B4C92B6DC2CEB8AAAA5F516EFA3A33AC0A5B012F62D5EED3982316C36096A15C7E3B6A658A69F4F64FCFFDEA691DD320C3436818FA7595E9E3904CFA4A97B19A994D0EEDD5C9A54A2D16757235C0505B96738467295EB6996A78CDE44DB023EF296352ACFA9EC864FAD6A38C7E6E12E29D741E48A6D99B4629D9068E4B1AADDCB987FCE35276DF2D9C71F20453A1E26A2E7EBD655327EA25FE8264389FC3A781D51D09074B3BC37E3FA22BF7485AF2CAC1F9B07422E6E74491754AAA9410D06164789B4A05BC916E5C3DA7A6B43DFEDA8C3F2B4F48669CABB68FAAA774ED85D146C890032AC89660E1CEC118F848D8D1F034AF22408510150B92710AD8797483F0FA589D0093E4C7C54E99496A9301FDDE59AD3D67C0CB913309A7413ED0E5A8D5631CD97567018DCA24734265AA4EB194D107950A4CB9BED38DD856CED5DEF67D5406D9A68CD0BA83AF8294D5B367F7C40A9EE2BD94092B718A7DC374A5AD40997D5B03662DA93CD541BAFB5632EBCDA3207FAB2C921B8D2229476B15456C349E4B72749BAA6D1FF11C9AF0B150E08F8528BE7E4B8D518E5AF7A2934F62980FF86908A55D6BBC340C069FEE6BBC2DF52E7E6F2F881A8BD4005A75531D9F6AEA057FB69CFC2D12ED511AF068686257AF7442B9DA69892B07762AB89C6F9D961DEED67C29234D12DC3D9BBC2D0044A439D8FA0414097B3E5A8819C90CB2A7E6DAF7D2114F4E2296AAF02BB1EE3BB57C0EF50F854DA2BD9AD885135DAC6D4E60ED564C621B3502B334CB79945A2C7A884244A4AD1232CD1F95A3C1CCADD1F272305ACEA807278A257A19579983856B84F7C47186380CCED30EDA803B0CFB01287D4E5CCC5B3971F1405F1D74509EB521E13B8E7B4F157E22D513DDDBB3D381C7E94979D8AEACA041EDC634E55B47C6FC2728E41DFA99486B62A606FF285A0AB17C2E4354F9B7931C0CB0BF4D3B26187DED7447890EC7992E08E80FD7A98641C60C92655D18B5ACA06B4F6370E2A844F50EDB96CB9B895167DC9FE2DDD0E581D77B2AF2BA69F9560BB1ADB845F396D2DC2AEE202E21FB36FB50ECD95163F9E4E67F9DE75A8E9A300DE3298255EFF66EF4EBDD20BA65BA6D69BDA6F5F431A570591F0A7D188617AAEA5357ED74C1393E22BE35DD6837A728329FA4732AD2894A4655DE9CE24B3FD0F145FD4E1CB6A8F43BEF88236734281CE7FD84DDCB78CD08C189A8502FBD82FFF9020C520B1A7F11E8EAF37442D78BC1FDDF3A3B888199907B9F333F3A22082B37605F52AE1FEB546C7A08692FBA3E1FE8C12862E25F1D699D095453FB6AFD4C28F7C0B68CD4892DF2E2A45069184301294154B99FADC06292090DBB8FEE8A92B6883CDAE6AEDD884C21E16D75A2DC5C9122297D888AB68246CD1A19800B9D1AC71DEE8B28A629D4F9D6C6C30969DDFC9E37A4BF34790CB14BC091227282DBA6F3974EE2A6EB7139148DD4034869AC2D86DDEBA82493B34A67E156F786A797356604C937BC91216C65428E458D885982C68B390542DED3F906454388483FFCA7A5D3E8D0D95E90A1890AA4D2F3114829363018DDE7DF4326E04238D92BD82644EA7CD85BC650DB4AA35AB746B103882EC1D17B72F2FB6DDCB7E531A01CAF1D62697DBC66688F259274615FE3B90D839568397AC5A9EFB3927CE12BDAD898F208DAED04A72EC6DC4B4FDAE02122270CD55092EE46E5C0DEB780432ABC4BC88E5D4C539326683396AE7D51D0F81CBA4784E3224C69FF6AF5FA297EF3A907715A66D627F60B123917653AAD69788966164890E82911DBC3F2C60E5A5F52E89B265EF2FA7D3F8FBDBC2B14DF8C58818A8ECFB0AC89578C6EDC5CF26ADB4992264C0DF937993B5D009D1649E24CF5690B84CEE9F21D1C440B38F2AE56487414C55DBDCDD7602D70C95E4304A5AA6D82A6B3898DA1B04996A3DACCC81D6E3570494A22B8E38BA5325372554EE1161D468ACF0AC133D4E9EAAD349D8FA8852981CBDCFA956C56D668D86064EDA791DE45DAC931E3A1D4225DA8A4E972AEC3696FEDD5F64DAE3B9489E867568B5340C395DCA6F7AF91BAB2E0102297F766E23D6072BA13A3569CAB66AA2E7A76F69DDBC954E74B469EDD7EBCB95836AAFD5A4DFAEDBBA761DA6E8CB0DED1FE36C940AEDB6E26A49C56DEA36DBDBB230A9522D008C1E7ACE2DF02AC5C2A93DDF00D496C623CCE51E878E57BA2C3F437A7561995FA8A934EA45B0EA27FAB512E798708E293FDD3E9D57B3B31F4A49422FFD69A6FF1EFD58FDFD5C00BB37663FBCEDC40FB3A0FC1C4429117CAC92EEE203C32E9F6DF51F684D4F45BC165CF95D05FF964959B82718910D61A88D78D0D6B37685B49096B54C396E63F2C0CE090F8997EBDBBC1D783CB8BA525119880CAA723C4D91B43985CD4D5F1B851FDB4797C9AFB4B6C1B52F8F845764D2F551634AAD7D2CDE06E9A3303857C613DD2DF380C63935CEB0390E46F6D8F8DAE63C35222E00314763AFDCE8916248FAD5876EBD65E3BC779C3110FC9DFB91ED44AB58E2E +smlen = 3639 +sm = 1BA685222677A8DDA1B426FDE94FD75B940607DB21C29640E1A94F1C0A6736A8535EB72BE4B2CB6FEDFEE806253537E91ABB63163E1B096DBD8CD26076C0D27BC84FF884E30628167C5F21ED4A671079F9133FAFD0941453C3BABC37EFE564A155EA7FFD28E421773F82DEFC7F587E28FA548A1EC817FC37FA41401279E83CBE793447F8194402811B16940A388977DB8DB0B0ED5A80B6A0B06F237A29B99C5DD414E7CA5DF5628F14BC437A3B02D81C3CE5DE84FD488BDE66D07E7ED6548CB276CA948DE06465F96BBA890589D0A1438D89B9B703151CE92243EA849D85254203245E518510F37B62E1E4D60C342F5C2AB2E85CE9FEAAC3056E4664DEAB95FDCD3F9609E789CE5163BC3D7A6CF2C435DE0C39003ACBB5677EE5814C59EDEE7D952FB25F9137BEE55A223C7A3DAD3F3A454DBA2ADE50879673ED60D8CFC4D1858ED69AFD5DF01A36C8FCD9A028982772DD5EDFCA9BE8C3E1B9BA2A243D4E8AD9732309F9DD0195186D8864277A57C6918A0AA71B9D90C37B48A66B94D01D207A68F046B45C36254DF6CEDF90785D096A51E0543C9F4C4B953C3FC60D9F0395C425EC5DC0DBBE917172AB17790114C744E0C91955B8888594D518C4F38A3E5D1EAA81076B5C98E4572826F454BF73EBFC87D08F5EF3A578E1D246A814FC661702148BB95444010CDA50990AF4ACCD8FB1A99B25140F992C78E32FE5022B96BC8EE9FBC5D25C7D3DECF5CAD36F115CD7F27366612CA80B97DECD84B109BD534643D36260243DD07C95C1620E61A89147711699AADC3588B061C0DB16B82A8D0E306BC33113CD6E7874A66B88C35C252B1A9034BFDEB9063A08DC19E473EC003909D1DC6E45EB31EAFDC1FB498B8ADA2312789E2D093521D571FF2CFA99AB9245783CB957957CB1299E78588E52FADD8F5B6A2F11B53A50CB7231ED8259D57331A1B9DD6DA5E00239570B96ED04CE23914048AE65B5EC43664339709E443E155C7E47298BCB8894661A37D6E3863600D0F2BC8FC48F872899ABB815FBF6A60AE614E43348F497C66504DC23010A82483ACE9BF4538280E0AB77421828B45E38F2D03A1BCCC4D2C5CB3C8974BBD3625060D7EC6683CA6977E435715402AF05BEF6732A7B13AD0E43E95CDC354AEE633198A1BEDE8EE63EDF015F249A3DE107E6B59F2E9BA901AFD307D4388171E341590BE35D94EEA9F2659B4CBC461E662C97279E4F15E9A325A587B0B2EE509A5458D2B50AA91A3A83A9262E90664AD21E7B997D86B8EFB10E32EEB0E7C1165EC1D55F2B3B6FE48B1A45325C1150E45B8A7204F3143ECD504883A01B607C0E7C0FA63C3CD8C3F933CBC5C542A40FF34015FD512EDBC6BAE7F06D2CEB5FCDFC38CF300B8E9994F8C0F728E3BBCBF44E9147F883A36339DAD0EB7A8250A1092411CD7F8F79F9AFE457DEEF95AE734EAF9BF2BEEC9D62A1D5B7C89E7B6A791651B0D3CC16FE9131A8DA0579B87D4252EBF3541564D610A2C85D296ED3CD397C15BA0FB67F3B3C0ACA5211D78E4DB934033FDD98CAEF80AD5CB185D56A6E65043F3736FB56212CEA98A761F52410542E00F76D811A04B528E6B133149622B8EB472D0D6112D87F7600233EE36B3AD867FE0FFDA1318ABB9256DCC24969A4665717AA6542ACBAE5B4AFBB60D6938379C606CEAF777EE81BFC3E1A412528ACFC423CC02DB9471939F77EC7429919B7073AACA07E0D60BCF2D9D72B16784D94E6B5FE54C3F70867203D73E2FE3F0308385FBA6060F1C588BCCA001EFCD68EAA9BFC81BB0F92D7927D5B67C3F4AB528A85EBAAB1ED1D36F4046313C9D343C22B4AAB1037B25B572F6B24D0649C1346AC44948323C3420F4E543821224D6AD97EBEB5C22AFB8DE90325AF89D2F4CADBA86EEB865E82F669637DF2B5454C600B3D04006880E8ECF15F2BA68B987FD7D3FB6FBC50D039EA38EAFB5D0EE3057204E008B41A9FE472AE25D29BFF7BF4889B3F447197A6062CE96B47295FE6DCBEA4E5A574F164686471FD5121E348172AE64F0FBA3FF51BBA401EC583F9FF547EBDDA8A80C3F155E0C47E22570B5344216B901D6BE10F785A75B44BF45BAC7B3250FB14C65C9F2E82308AD9DC1AA003DC52A28D3D10AB9C06ECF1689D243F849A231E1DEC02D50046AA982A7EC54278F51713ABBBF072BADBAE8BF2D13F1A5E6D87DCFDA32598676046E00D1A2CD29BA742F6593D4615E70147D70EE236C107D1D9F43D7545463CF63E7466F62B83EE52018BFC17D2D95F0F0BB97B419C7E0BA11F770C3EBED0800CE4872A89EB3FB5BB1BC318EB57B773794536179C64F2F907883AABFFCCDE6E28079031E6CB77A97C3AE881633B0BAF482AA39042A2256E4BB4C3CABD8E0FA45EADD33037E28715970B543D8AF3EDE6C944EC29BC2391DABBC1789A7B424898F620D5FA26D8A6E3E5817CE46583213F4C6FFF86FA87E2150868698212703D371FEBE346D9501A14D6A1F5ADD65D742016A55DB1E042FC7F557A474A0A952158ED85FC579D0D765AA846B4036DC52EA0C74AEC772730DF0481C761A140C69E77FF250C28A7CDC966281AD45402CFB5ADE938D860B83B0863FFF09646B4B75CE29DED8646AFD3D339E1D2C80D7F437E1F3B7A2FB0B80A749466F65E92679EAF71F2A7939201BFD65BC84E844EEC73DAB5C93002B67A6FCC41D2628CC55EDA984EFD7D73014037E47D198A8974949C7C517E8BEB3BD6916CDA03CC1B20710F277F5B5041918C0155929340B459F266ED0D62F0431BD2F11D842489F558B49F4F065BD03059F5DB739ED05B12DEA2E437ED0FAB0FA186320CE81A802CD57A4E3E1E97D5945DA018BF7A8E48E8A1B01841E8F97456F30B76259E0A126A3B1CDAF49CBDF5BA66BD8ED6818C1EC821AE9DC828F57CE2E2A48EFA42493F0723B3FEF4073B8EFBD046BBA4C3F1C59230EAD848FF9A797987F62634C865B01FBA650CE15CE182F024B92662E25FEEC9E61F1BE717C68A60F9DC4C4C063E900A3373CC3FCB56DAA124E9B677A119797FDF12ADC56F6550ED6A28501BF4A4AA32F575F8E9E835DD004294858F23AD99CCFF16F3D1E9F9325AC5CFB4628FAC3307E3E168604D78C7909B1A963C59AC82A1B364961A3FF9631AE0A7454432069C11581534606D99B422DF561C3024F5E8E65F19A961ABAD16D67ABA05591D18336169BC7A871C54EBCA8351E417AC911F654CE830DB3375A012E8FCBE6F51AB3911FA933FF21204F3B358DD4628CDB9E59E465F5D3ED7BFE1913EE2F6EEFDC66702BE949100DDE5A5D5F9531EFD12367FA79869D05BE6A7EBD016AFCC0F0E5B6D9C60CE8832E84A06397D995032AC2D80A09D7B8AB7BBDAE683D5E3772CB4370953896F8C74079F6B08361911FD022D967B4B314E386B3A4372DFB36581595470BC400FF27206A40862B8F6AA7591B15139E482850560CB236D5B82D210F885651159DBFA5EB2F322ADDC92F1A339E0F122E50A0D293AFD1E7A1F1445B996B82C8CA4DE3532D664E19EB78364CB07F0084009440D94D84E57B61501754728F7A3C4ABE8776EB898AF5FFBB92DFB5DE764D412EE2CC2E56A29FE46000730D014334E71A1D8BD7D1C2365B98C31CFB526962FA9F51F2D0B5DF9CE8F3DB34FD37C9541C5F4EF492DCB4C13F2DF1BEC88EC85370AFE93B583D2B361EBF3BBD29E8DB8A5C1723E2B47834ACC7A7DC0FD636654F6E3F4745D20BADB0733CEC26B3CEB622951E1435468E9063434DC1C99DE336AB0B5784F4E18F820661E7752E5FB38910DD0178FF55A4A439C74937E28233C8B05344DD42774007095C7A54A24F237A1FC8264567AA68FAD33AB1103475132726A4B5224DAD19EA3E0FCD1EB395DDF3405E74F21CBC5008D9B58594E207BF77CB1B4F75231F5735EBB4BC8FA32134B9743EF4655D45F11A9EF0A425FA6313C7113985A5E1B5B4ED214667383253C765135F8F32FFFFA79FAB26A0DDC57A95674667DDE3E90FE039C6BF14B817102D8A8C1DFC845CE0FE607B29CA5F9FE4C78AE6DEDBEB715A7EAEDCFBC38E890A5F28231B9CB28030AD39E00C5F10FFF220209790D34AFC0E3285836120BD8FFE0D059595253F7E67DE93A9CD186A4D2117D916E59CBE94225268A244D5472F6CACFAB1BA6687BFB4C48611475D6FDE2CC39A2FE4EBA1465C81C490ED98EE3A2F7BF5C244505ECD616862C96C5A79E51DDB391B89A173FC2B8AB47555C83644D209A2087BCF20BA3D17EF8E1EC813294B22B2C9E2B4ACB48B8318839F70175AE81CD8BD27293D07DD1AB777BEA83E23A43337CBCD4B4A9504590642B663EC909562575C529005C4868331421593E8A351A511FA76C53CE6AE82B0F2C508E65F82241A0CB0B29AB7AB751AA78E64FD02658246A4839E5E29D938652D3E1D5B38CDC069882F9AF65F156D9FAC0573CC7C103573A6F8F160D43030470BD01D48C95DFBB1ADE9C834F995738D8018D808F1D5A384DD1F9AA9458A8A890A813DD088C67D74834E88BA46F8562C8F4F49CEF1F012C6085E4DD78DC750582BBCC3456A1BC56870AB379A0197600316ECEE33FC39D5581891277270DBC067F5756A011185BB4A77142F6533990D55CD80C9498ABBDCCDB38484F6DA7B2BA83D02C2E6974CD01474D585EBAC2E2051A1D5987D0E9EDFE0000000000000000000000000000000000070E10151D260998114C84F84080E7EEBB47D248980FAC9D28F1ABB6DBAB3DD59A5CFD2C7CFF7F308372874DD5447C7B02E30165501C0C673128E4C543A414222BDF47E7F4E8DCA757B0F4A3281C0D10C4F02AB52AAF5B9A715E012607BA310947A60A5F62D6B8CFA96386D27CFA709189202421C078934AA2D955468E550AD4D0D4ACDD98B168A9568E232192E92789830317FBC959087FFFE353B6C168F3EFBE7164444F1D6CBA5246E31658C65440A841DBA78257E78502843EC1A6E9710229C8EEB85D6CDDC7D543285624AA1F756A5DD4F1A5D4FA52DB8C5C34880ED448FBB6D254509FBEEA0FA022F276B6A66BEF7ABFEA6049FF74291BABE781F718683397077B29FA9E2B46BC6B09251E587CC5B182195DD4060CC4A319BFBE251A5B660A739DFE5D0E5B93F3CB7E440194F1C8BDA922CB1A3EE3D27EDFD61C1D31A7F4534E84889EC83B51F1641892766434 + +count = 10 +seed = 98DDA6B97E89A479D5EE214E660DD6B5D8F6CC638A1CD4F462A0EC545F5B0B0A1A403AADF566F7B1C0C5FFCA29B36FCB +mlen = 363 +msg = 4CCA95CB9F254C2EAA7DCFFEF662EE03320D5FC626A6484304BF62FC20F341FBE26E1537D7BD20E95440F7CC95EE84E1297C807A0BC9006DFCD5C22A5C1FC0865F5D70E5D63AD677FFFDEA52BF85D1A4F159F7ED16A745B4D971B620048B5F518EB2DC672CA35022578059E1ADAD7C07FE910A5D566B8321D9A12F34C250BE35CE964DDDEA23C90EA77C9C1BBE3532FEEFDA3637157786EC7D37775AE5CB0BB92EAB45A0FB1E833E8A6F3D06B85946E31A79B64A02B31FA640ED514A85882C89F693A06354DFDDB0B5E23E7792134C69C1D3908882DF3A7694A05B241B87FB2DBD1A4D9F26943B69F3CDF730301663089D1EBFC23299DA21300F735CEDF7B109F3E0BBE273776E6AAFA7054A6CD9682B967EB7903DE549E9558E62DCF3AC444DD7042FEA362EFB555BB97FB464AD7FAEABA3197C14A6740477DB50CE3FB8B762F48F880381D510FCC836E5880B48F08BD6333202E838AB73F2E106CFBFB218AAB802DA8A00F13F78FFB70C +pk = 698C191E1ADA2751A3033F56E45D2A71873618D0A870BEEFFEF47A60A2A55D8ECFC87B261B64308156849A77B89CE2D2E57149D64FFB57D415EB513C8958B3CA253A197D04E917E7209287CBD8B84D013FC929C3EC040DD20BC1236E7A34805B94B36BE90FCB32990C84B591478FD2E3A9CBE3C082BB4E17F62D13E1CFA7261766FFBC4533FB25E2217D4CB666234EF249F1297FAF7D0A54810FE19F8B64B7A7A09EEB198B754A29E1C52E62BA976E56180A39C112025F5E93200C20311D37AEF308F0E34695BD3055591D595A29D9624A0D12F3361B49A573928B8E584C136055F56B04CF65D042F2F6B656600C086E5148B397A77324DBBBE3AE73883E2A1FA7993B5D643751E4D22B0429D50019587A8F84F7FC90468A210AAF25B15EEEFAC61AD11F4109F4361FCCCF4103AD84FE7413B018BD38E0D1776E079262EDC1F35F35FE46D8D9ED2ADBAE3E5D8F2C29B1B812CE6BE73043B65E004BF155E01F86E2BE103B0B291094B9F906A632CA26A135FCA8881D2A6C8671E19AFCC108F15807E465EFB1404D630589E54EFB166719045E7A59811F2E01C69DED9ED934F350FD42157049CBC675AC1408A736A27B1F8EC35B80E9339E7FCE72F4E1AB3842540F0FD03834ABBB38F84D3E07DBDE34F03CF824A3B4EDC71DF9ACC4FC77FC27AFBAD6C0BF9BFBF5E02230578C6AB71D80090E1847F385182168CA7CFEEB094106DEF1A4DFEB2CE1CAEA7A5E9B4C7180E7194E9545DA14BF33C81461C004182BA2DC5D798BEC3FFEAE032C298651BA731DB809C474A031E43F8F529910FD80E1E11208FA2C7839EDAD13BB9678EB73CDD1612B2E83F3B517E82A19D445B3E84F9A7205EE549ABC049CEC880A4DB439C7F0FFE77866772A144A56396342D19B4AE9FD8BA36F6CAD433736298A0515F4AF5AA476C1DD31002A30E9561063537F55D9989E03BE5EB07B9E8253DAD2F354BADF48395560CFFBAA7D2AD1FD73FF5BD9C2E9047A605A764392E948014C7F5C7EA9DF512D423AE315597B345043041807860292BD43F43AAB7D56D4BE7E001B5E84879FADA56F759D130A50EE8F1AF4095FC1D60162C9D6FBB82147C21389889373DD147B0D0B4B12AE47139199E4652563176F75D7FC5781B98EFCE8C6256AE2A69E8B0C8940215C13F9115B0730FBB9DA8E9A25D35C81EA4400A71BEA860F822DA946804110161A0F8E33A225AFCDC4CAE361E5722BA73D09D3CEE5CEAED3FFA1F406EE3AEB781FDBC0E7ECD96D432E26B7592C85B925368EC36683711477F4136559EA1BD139989F9F70335AF95C309DC0796D7877A1602881DDFD0694BA3E95FE391ADFC914B5CF402AFFF375BB4D8122D236A9A8FC713E9B4A8C1E5B74A1E1A8D751490C34C06A38A7C35461FD1A37D007C73877E656284519B97F39C983A559D41A3ABB5C2AB6AE62AC5E79FE4A0498C7E8D1A7E7EC8067F7D6FB7F314CC7E11A299BBA8029DF27CA8947B3A587F91F2BCE973649A97B275605EC6BD8870D709533A594967718E336711A74CC7E1C01545FD0B9E68E3D77A6F31E41D953C006024A378B43224A4B85B21FA6ED953BACD95185E154AEBB06EA2D0A6F8FCA3AE09075E120F63511026F9504E7AE1CD84131E4F7409CE91F1D2BF314032A05E5B1B5774EA64109E0E569DC4E7E921067EA10D4C4B953DD76AB83B54BD245FBFD84CC64DD55085ECF73DC45FE4A24692A024AF13BFC9F0B2D1EE25BC54AD3B858A6181DCF56663E7A58C9CA4A4CAF3D2CE5BBE4397CC63C0066AAA7A9CCFD7C69EE2DBF76B4C54C5CB51E7DCA96224AA380210581BA4A4C3F100B98BBC4C09FB3F5E61DCF9C183227630701F7EE091F5AC1C70A7559A42A5658D99E57E7342D69619643DD5081534B737B6BE693DFCBD440AD2AFD161122BC7A8A2C0816730166AF794138734B573BBD2DB2943E999BD7C63E335488F6B0EA24ABB9867E14EF5FCDB06F809EBA0C2879AA4FD99A32F62B6E5FD729A84F5B42770091700E31565AB7D13CCBCB233A0BC42EC765EECB8B47A018039CE5BD1A7DA3D791FC78B3CFA1F450A31E01B774482A7A5952CFCE9E0CE39DBE610BEF6742FE4D2508B4B0D2DC5192D342DE71FAEB58EE24B1BBD49375424B96A5462DCA8D18170EAEB7D699CD49DE7972A8F6973BD5B6CC78F8B66868743E31B47D3729ED5E79E7A4A3E4E7FCFDB40AE954FEF6496A7956E9E306D9B2EFB10F36A58B5AA2BD31C558DE7973F098FE91B72A7D6238370AD17EF9CDC46FB605B2921DAB57608DD2662C3F884AAD7CE4E1ACF967C8AED955D6CE2EFAF236AB33A52AB27CD66CB25B9CBA7A881BB3166142951F50C175D09AD99E29435B66F32206B96FF045947D6FA3EC46037778B076DB2486F9BC9076135349F2179B2F53C20B86237DF7848264724BF8C225C53BDD25E02FEB3B3EEAD90E373B40B20AEA18DD4CDDFD2590BBC63C4E61492F71ED07447774D0D16B7723AFB4232B7E83E740AC22197A33F01F9282E063DEA0406035B5E97A5EEECFFB66140CB13E06F97D3F66E43E976B1AB97577C303E8D8E098A17EF2A9D78AFD2C7FBD2C197FD4BAC05B101ED4A193D5C6E76224F79F49BA2C0E40A8AE0AE74F699E7A45945AB3EEC3E67ACD809838BD9B9816E991C15439FA05B149BABF3483336E365CA5EC3FF362874E49D88D6F776AF4BAF8BB9E561A9FFD4A75329FF638A01C33BA6AE50BDFFFCB9136146A2A1F88C9EEFE2A861BA29A75E0705B4B7C81D0F59DC464A5D27F +sk = 698C191E1ADA2751A3033F56E45D2A71873618D0A870BEEFFEF47A60A2A55D8EE07F045ED251958BAB650BCC90B39C4CBEFF30599EB72F5453FB75FFE9602DB0BC9A1A10BE79635DBD157D763962966DA0B339793DED469EEED46456A1ACF2289DBAD6D9CEFAE6EF8E94E7FB47113930BD1AC9A9D9B5FEC6661C839EE18149D017308180843806643433533881641451455437766256524212472677060405852810464677681680535207883608673440086310868070386875107210225612182786138622647314236868768783225747147516006464725856188063708875314006263460233788402585403588814627556044811157186117167011630724863804317618532634024108437211445443528000320116414858614003486434111246263265624758812648783262867260241580433275061003315300542020112240741603715484663664068330804450445488023807672557273265811587007550482244000808827204230488711266147316471355041678547768417240442422528727480175644008360028153252452258110266075042710867735585088755464771735665208477178600123340014318870855844456712273664537647668524051660248035402025205205271414148447507225184706534461150532284337767601122225010363741152205646744640548344356435446427745051107670752572600623576351548227234118177136455241362408063023344366831663674622841288214872706426701272075161340786321757055328831126205742051015406876874123721564845330568308522765560205755384863345802773000363122613214016510246861032023821445126717343060870788147500624850760152715030030258201664775835401084540421430808223735027582638437381886145731145171272714764608240114524041378728055836651011266728146874656663508735656272505266457528228173353862622382716422156165881272882035763562610502030143563520041022832230753426281208211552777585656338672681852141568170746162068871056624337483882141752134237745763328165108760870086237728758636585661453066684216164484546812483734664231541226400268485750352432250073147840013638762280841348242216405500832880477847727744473626674605150775150214511723145144204507311152182546224216742136258853253585307362142034572455218030506647762683842785158058082257154126163753755114038171007877424758784125282380308783383537686370242414324123275538046833353687744483513465247231154110576730507434361115308307386732384667626354880778320253567428687855537316050230172172406222842077660745082776130722006623262488247870675153067353862513553618615422826118674512622028267186843687158504442500734381153223142802816767603411748717301650206211777438700215467733506430615752521788057640788884058663755748216240583530211060053868381722002214327740260600336705843484661312652053406201186212841112658101662551810414186764524231455481324476738527277235178737536038415161415506206321761128357508035347516644813865567500308047262217855824086152151645815820371624372450525335621365855417830480755501384648604163302153354033156380817702332272461710802345321121014157844412044508312388354521182512328517723205306177353787616534266722422110206328138323706546001243336537184043703630453736553444336444855487518127601034241800854337137021160044713664378316688165076318140662456172842768633615856734873178018778600325225718578878064176116766807084818130816486887463507553355171044247762814724571720626750022284F55651B296BE7F86467878F2E58ED4169B33FB6277D82E80E95A0091569389D21692B02FDE322B2F1EB4657AB510B44910540FFE9F2E8D4E1F4BD0978B4EB81E2EA789356D7795704F2226A780E092C4C5033803ABBA9EF14FDE3BE623AC387C6402A2A9092AC12FEB90131AF72C5E72A65B3787998A2599CE4EBD114884A4CED2F6290E4B89E498FF9A0B38BBFC460D709D4B1E7504FB6B1D3368E06BE7C4DA2A69CD738123C3EEB132056CD98830E20041E66B12DF61EE19BF0DA4C4B4632ECE5F9A3C26E35F47A3A51AA7BB63F04B5F924EA3056982CEF6983DCE5AE0BAD35EC69C3E9A292988CD8A8B6FF6563B3468FAED868538F5E8098D300B23524B41A2065B91E48C7A8691FF6748C30AD2C90E6EE35295CDC9E8248FA4133952BECFD39DD9F72CCF6A35B40852AFBCA1CBC7794224394752E4A0DC0B36CA1784A4754BDD2C791CEB211F28E155206F562CD6451D42D25B16FCED6CDC120F6C3262E8CAEA93B7245C9367A9199438B041FE1E52EBBD063492A1C5DCFB689E60D7BD08385E955ED8EDDB5D175D84D7762C17D220E799E35617C5BA39B927889DE231F7628F903BE2298FE1F323C6BD58D61B42B72EA25F50711EA03A3DC479BBE4A193A9B4A9A320F42CBFDB75AA36A99F1F8F396FA752ACF7B20063D3E1B25A76A29209AEA58266BF3651AE6EC3E2EA92E9DFB3B69A3D49121DAB8FC81E0C4F02E48B80E61ADE0EE7552C7253B968012FE6FDCBDBEB19D451D649FDB9274CC55E87FB00C8948EBA904268AD9D8567352801E7B3E6D3B1DC6700F88B651156FC3799AB357223F71B1D6985B30EBDFA1CA4BD166444E20C73DCA5B0F61CD9B67C2D982F191F80323252C153BC74B2635C7B99A45767CE5F05069EB8A5C7D04EBF42226D77983E5BD1F47A2597244BF86C71D789D4A07509248C587E8E696E09B8F9E8CE998607F9AFDC3E9AD326EA05A737A673B8E31B89DB29FD9B192DE3E3CBD3F87ED426E1F4DF4368B176B28AF9C55965A7D5CE7F18F2EA27E6282379027600F44F963E3ED29A4F150C7BE8EDD0B3ED2D6896DEF96FA6D00813ACAE2D9E463A60116D79D51D41298BDF552BE119A32FB37BD4DBC72BA7740D096518187982424AA60EEF821AFFC223873DDE6504F5D2CD471F79754A9D1FBBF418666EDB6A376C8A0E29EDC4AD59B4DF51CE327AA2972AB90A12FDFA91FBFB35AEF1FDE53EDCA4B3C696792619FFBCA6C3EE918BEB662F3E4E00A80AD3DC6BDFC657C3946947113D46159F954FA0DE2576434DA58B5566CD2571764D181FF1185DDB051D7E9F2D156D70BE99A2E8AC0B79E7F69EDE110E163008DE09D1B62BB9A518726B12050404EC112C8DB4DDC406D17ED147D3045DEEAD656CD387338F07294CF19D1B01CDEA26AC0894E352E2B44EEDB67767E01C5DDE0BE4BCC9CE3D5DCA6BD453F3C395D07DE702D2D67016F43880143114610A28A86555F67A6DBD9EEB6ED86AD5CAAA7C24731AC2F311B16712B4D0294A902E472A08B5810BB39B5A82EE90A9C4C4810AD983624D2D2A043AF11BBB342C760074051BC5CBD5F92A30BFE33B0C43608FB94CB9C25EC48FB816F333495FB7B1440FD2422726BAA2D6204AE8440BE0F824AC323D2ACEEF9836B1100C239248A1DDFE9AAE4DB118483EFD404CCA78205EB45FC0221B23C25F6F14E597302389EC77B28595F0D2661C75073F5F1995E28BFD0AEB4B68B6C3B7998A520F67558A5AC3BA775FE783FBC1EF70D8E152D6E713F200866E49C2C6ADFB038874DD1E834E9428832F648665866B2FCA49E8CDA68BB3431813B7B6DE6B4071A51359E400A61ACDE70CA74DD246F584D9CBD1178F00839500B0904222BE0BA079C09CC1F9EC898C0E31C8166EB4FC42FB99A1E45E3A4992AEF1F203F0CF0A6052C6902F3A5DEB5BF4C8B385F6D1A0FF5A2CEEEAA3751A84004FACD4BB83C12F0E0711D0BF979089D9B7B2F613A75F3D117AD06F519BA3C05E0702CEF23F067BF69A077453C85CC712508E7116FD33729A2AACD9044239FBB021C8E27CA142F610AFB7C142DF755B468658A3971A04407653DB3888BF98CD78E93F2599A9249C0ED294E1645F19A7943952DA211174483506683A8BBD0FD0F88E15F676AA3E41BF871E2AD34933F0CD6CC40372309F6EB082CEDCD627A8220F673FDC78782271FA5F3869A91ECAFFA7FF7A5CA94068DB80206AF03D7DBF0CF0EEEAFF2B490D5C11E260CB2BA22DCF33C02BDC6CE57F1F9541804784E1C08D8CDEE336667A2FBA5A296D971BD82AA8DC4AF16FD121CC511105FDE0D3B494D04C11C0EB34BF7A0C7DDC216990DFEDB61D71D501D44AACF6B99CE4A2D0C01E06C700066E2CD6E1A8F1709A6608163DCCDB282AA630BB4EE2E0AF6A9F9E9A0FC82BC53B1FD2D2B200A6AE50D4A66F53CA0370E9FA5343E765ED0EF830AEC660628FD393FF6B8156EB1867526F5E9AEC341DD0721E5F7C17A692F7735F1B3303EB3CA4E99CBE3D5A6E354F87A616B347711A22FB3E38D3EE8FD63E7E3958EC11466D235000CA6D8A5EF919786207E7AF365C2F629280A0990D98E7B3F01A94029F1E13341238FDDA39CD95AF53C44CC8EC836EBA67C1CB3E3CEC5ACEAC13AC7240CDEF39984C4A5D94AEEE432CB4BF0A2816D5F2414CB1BA8A0487294AA058AF1257A83D25E0739B8BCFEFA43C498E2FF877183A3D8852ACDFC9D12FF7474898CB76E66DBE710BF37A967AD1A24779A0FB3B5AF6927CF5106E52959D69C17D42593DEACDB1B4EAC2C4802F3AB3A02FE472CC976763152A48C9C71165B48ACB740C2B096EC702956D922FA46E357D5EE5A4285C48AE8F6F7097FC6EAF876AF69F9FF3F09B5FDC94B7B5EB8D9FA7D04C526E833363507A1115670E3525150C70282113E3C4F628A9F5B0D4436A711CBED8D9F9C2A03EAC96A8C8BF0FA4E248FB750F9990B4B0780227EA8C6B86754CB052E44DB0B04CB23A0859EEC56C14292377B743BA63A04417D7413DD213440BB08B3ACBDA61C9701B4ABAF9FA5E7285BEBB711C19A2C2DA18F43C99FA4D6A78B0004BDFCE54289C428C5A199903613EC57BC10A80AC3D88C29A9570D7F9DD7D96C1097BC26501CC6E9A237ACD617C6459ED1391B0EBC36D7A08CB75F31893C0A0720F3E3D214AC6E73D3B6F48AC7130DE43B5BBE9A638476D3AA5BC096A405D0A7B0938700D5BFE25807CEE29781BD03E7C5999650E0C98A23EAC80AC84C9EF6EDFC4482B59B97525A7E5E3C4FFC3709E220528C403B09A02433A1E26F5DA202E3EBA50EB900DC978AC2CC6491DBBD5F5D496818C5ADD7C84ACD0B309E9CEC0B01A60C90C460D32F0FB08BBC14823AE8D6C14EB68C814E23D4E869BDF7F0EFDC47F8BA070AA792533C467B7AF34FEC4F1D917B10C1F5E1F7BD2AD99178AB4BF6B4FB868AB1B3ECB8681F528D4C8DC202B5421D92759357DDA3326912DBE6A89347AD523B75C1D74386A4FFE66D528024FBD5CB32E8A0B663715056A0F023741C35DCF54A549C7D47861594265492E0F15FD24 +smlen = 3672 +sm = 791540C3F73CF05D8E7D60C57BDD6483E9CDFACD17A7560C0ECFC55E4920F95BF9CE4F502D7AEF9E514C5A164B12AAF0E85FB974F30472B82CAE625DAE7A4EBBEA34B9A20AE68228562FC4E052E6005486B30C20623EA12564741CA8196A1AB3591B5D66548F7AA15A06E7E825D1C59F714E09A64C34080CA1DB454EAD675353655282BF6D73999AB0BD2A9D8903B4BCD31AABDCDA39B1CAE4CD36DB455E7AC991ADF53D9A4BFB312615CA60FC23A6473F44BED7F7450A1D6A0D184B7C16E3973F253DBAA1D5AA797FF4EFB9486AA28CCDFF8855C503DB492B896AC46C2498B041187A9CCBA375914940BE54CE6A47E7AC2ED62233E34A946A15F63B55688C495E77483B5EFA2EAEDBF0C4B8E30D365E55C68C92C3887C1287DE21D65482222F51A91D70E6BFA21CD3812480727DE7AF7E45A99F6B767AF09CAF46D16949A180AB47AE0C3379AA499F0F0397E39E4479F918890D8DDE4C052DE80F474691B781158379EF5E267564154897883D4470A60E00AFABD2C27E8AEB0B2467A99935202795FC493710758F9800209158E54F859108CED6A7B0876D43DA91F493638FA8214C16B0D9AF885FFD1A4947AF8BFC2F805FC7D11D6FC7596E03F86FFF91925B7F36BF03E1DFF3BF05E6A0D7B641A09F0D2715F089812C003DF6E04EA1EBF6DE274297FAEF3213A343FFF97925B0EB50D50BBC04FAF095404CD41199A2486BC5345F264342302C21B87941B676AC44C7120ED5347B5F4115BA7151D14B93DF7E96ABF69AB9CACA8C05FDC7D3CE39D479B49E62560DD5A7DFF3852CDD9C92CAF828CDBB39B59286A75042259F8C853A6A78486DE8DDCE50A3AD6648A6433F705F81D01C98013A53AE190E49E08648952394329484909F05128581B50465582914111525D210352A91CD1B3FBFC85F0BCC8FF9FDD1C986D4E54B13BB5EF505B79B1EEC4D6B93E53B7E23BDAAF8994E8F0F4690914F666C2A0AC26763C00A3C686FE39940E5911A0DE0D3F6F52E4F1900B8169A896E905096D23AB7DDDD49821DB416D8DC03F2D7254776AACCA5B279D2CE136937168F7B597ABF1D4A89B40B217DD5870B1C65B43B4C2FB89FE4815BB218F32A440518A62C2ED974FEB100F2CB5BF684C4B1BD8C4A70B309A82EBFDD7F19815F9E2F976A2DCE5335509A4DD3B1549C5A06B9E9B91DDF58EDE13730BCEE99E7E6A656462445ADC8D97935F3110AF1B8D59C973E2A34FE187684196149F37AB22D8B8244773B78AB3822EFDDB71E31A0502F1334C353707C9C18A1915377772B1442724177E1A29B16551B1C09C68364A02E4CC0A2C7B95F5308C35EC825A9EA82D03E80457F77D98F703063A32E208119EB31442654BC777F846A737E48B3DBE68A43B489F26B8E6D0D9FC204437AD6B7FE709F2EE8DC71CB804FB3096DCC92343342BCD2828813F427A75CD4C928C745A3DA240B72451AEFC9EAC3933C3420644A1DFAECF092A6AF92DF846CCCC2D47A76B6AC48BB423E95502C3ABF73EDB545D61E6E55B74EEDC5E31FF4482FC38D7D69FE41F38849FF86B675A299122BFEE293C752B0906138EB03F97915671971F4DCF79F500301B401818A86ACFBF923055CCEB566CAEDC6B421618DA4BDA7B3FC2E9B0BA8CA5341B601DE4AC4EB9F06E05FBF34E1E5E185CCA296146A0584BCDAB7E0BFB5F0BA32517B3879AD1797AAB9FFC64FC24262D05BADF778479B5132B994FE707BE2361664D3F5187AFADDEEAE1B8F4136B7C8242AF4750EE2706162190AFD627BAB7928BD19794E96314544989EF2F1C23290002653E729636CA77D29115F2619120DA25EA03208CE80CD411202F97A093699A90E4ABBADA94595466FFBF08A2B8158B773802464C49EAB61C4E1D58C9FE9AF6917813992628C5704E7F4FA262D0FFB83432847FA43607E144D57C14A668A961A15A1BBDAE349D8E8BAB3B5A1AB2532474E4A9E373913FED9A31DF35CCDEB49D4DED88D7865841A00D66B17DB3A8BB5CA40EC19B0F9A88F3C09D8DB61AD073DACC538EE7805FDCD400BD6839A68763AE54B5B7B15835EE904EAF7A72BC0DB56D834230E0756E13B0CB935C11FA0DBA3CB8D6A7F51BC3263ECBB8EC4FFCA93B1C4F00A0F569967FB4148EDEFFE9C6CC7D7D0A251C6EC01FF354AA8217B6F7711FAF4B40570A114C87F9A37960EEFF66DCE853DCA40131ED35600146A26520404C4E2E5B08B979AA12C68BB9A1867EF0556EBC6CAFC938092A946E4F43E01BECDD35D29D2430AAA7060B889CE141B8DEF37541557E15613EDAE06AD76FD01E751C92A7A2789CE91C7E5F6B721759FCAA05E3F5388926E1EB4F4F1A3BEF9196CDD3016516E9DB840D2E4ADDF1C8AA15F6DA034101ED08DB835E7C8BEF921684B588E46E157087C080A6BB2ED67FD0852B542228BD41B5A754D291004BCCCE5B41EAC9A399958852D39AA32F7883EF66369A6751AE84149E23DA3187E409D203A62C917F04CF5B393B03FCB01B9ED717016264F00BB1F002A32F539A57B6E4E985614C4522DCCC36AD84F40FCB8D95D6224B502EF0B4A6A9BDEF89E38B306584120C92C5120C7B60BAFB5FEF4A37ADCD704B83FDDB5EC8F5DBF88E2E2BBDC72335C2C3AD596019E89A3BD27EA6AEB3E512487258F541A6C15C6BA5A00FA1897AD59DBB5FCA6A988FEAA99A3C3B0C2147E2562F35EAB985D1C9252119B6251CCAD2206E394F98375A375693D89EA439971C0CB02DE28489F305BEC5C86A436ECC3FA6B355E3C596CE7D5B94ECBB0EC39D5494634DC01DA207A770A72747FB6BDDB71E3AB8ED6A083EEAE1E4A63E76327D486AA88BCBEC6656226C57E95D892BCDAF4C3E93D86459DA8869FF5AC598AF433623C9634A659CD9AE52ABC075F181944FD2950B546D667424EB9AD16A0C486734A8BEFF32A9F91BDEFF6CA2E0F82F28C6438E71AE9F0A7056CABDAC3811B4AA304C37CC06089FF5BF68108A1EEB808A7DC8501C5758F2222E034942FCF977D16ED8D183562BCFD26AA55EE801960A3417D1E3A02252B0AD1FB5141AF2F2B9AC07A628821E9249BC3F37159925DCADFFCC996AC8DEAB3454BADEC6EFA128AB8E54C6F79C3BA705A4A5025583B316F0CDF630B4DBBE3EC389E8A6C0459EAF7C7C06A92ACA9FCC5A41D9EB9F29B598E2DC1C7A863174BD631A98E46B445930ED0139D2FAC409B699F5D888D9339A2B0AF111C7859CE13F5C17AABC47C2C326211D149E8921E2FFA520109AAB938CB6017E5736C2083E60430A767F94901C1DEFEB96294437905056C07E3482C31F212BE9A5DB7E5C03035096519B0C613012EEA5CF15C94ED99A4A8BB10A61108719DF19EB25752B365DB160DA9A29A2FCF013EF57655F1533271D53AF60EBAD3666CCA8219913E4DF82D78F4B5653C400A1A3F3B6715C99473406841FEB968327D881F052AEA9666941966B946D3C92922F3176E1E3ECDF84F062A16FBACC2F646AAE3080F11D8FFF081F2EBBA8D5EF1ED7ADDF93A32A043641D2BB249D8DE6E8887BAE8165F06143DBA1516A6E5E11DA32CFF1AA90A86A5A3A4506530AE984AC60A290E15763F77D43903EB41413113A9E4A92320D3C93739549819FB9CBFCC6ED2B971364D160DB6AE3CC1D6C4D4B558B714C91F2D9912935666650E067E97FC86F7C2EEB28418A5EA5229F91826D93CED3802A27FE4D66A77FCB092CC0032B85EF05D96B1D4A28676ABF02F4985555878FB0C06F618264E3487F4E38EDA9E1B451838ED8C8501157AAE055FBA76604F07096B0D3085FAD6F7270462BD5858937D1C5B23DA25B71243304815392F159C941FEE8075D8A622E8A773C5F9F9BEE37A40E60660B834E7C3C3C6E4A51EB1855FB40D870FEA6ED55FB7DA7D92200B4F3574DE3FCAAA563CEBEEA01BD774E841D161BD754B4BE939F3F875F2E17D84C8A18E0288BC2DDEA20DE64AF7474AB2FDBC60F1E4E19362FA2DBDA51E200CED3CA4A20689AEC81F5AA3FA939097270E3A2B3463ACA3236C502A6DBFDE7C13A91E59FAE5FEEC4EB5292EFBEA830298DF18EECCB86A368FB0878D1BB190503E650E8FCA5D8EFD5D1FB7CB379F6FA1140D585161A6E32414B9137240E624332D6B5E685C976C68DC3F69A8AF67EA972026593A65FA8871331097EDCDE64641DAFB887B2F146328A8C1D08BE7AA3A13ACC4BA02FD879DD6D74F52149E3C0DC053BA68C0D807543D6C18DB52D46DE05D3C0C626327B7D22D18FF11F03F00A324543EB3FD41133DF66DF1CD3FF43DC3AA2D7F3BB54836CE578A5A13EC755B0DAD169BF7AF4D0FA505DC7FCA7C80BE295E44B8AB6BF4E9345538059F47FE981AC81B53B20212FA1A61E17D8F146E7D3A44FCE4D7D549EEC96EA0AD1A8E7E2327FBA595012B5468E532C6829FF664C5F722025DC2C9E13B03FBD283335E5228907D59E473FB274DBC3FBF3C7009892C144CA6D270AF6CF0AADA34FBDE032EF9AE88133967E45A200C33F22ABCC533381C6EA23CF2EFD3046166029793B81FCB8BE18083B1705A9673C186DEBF6CC6B1E599221D40CA488C5F42DA41E52CF4CEBD4E327F3160FCF8F42C6BDD94D5BABA8C13D39A49AD27E9F2E65BC9FCBB1FC85A0C4D525674B1C4CED4F93A4E6E7C93CC060A31949EFD3F778693B0D2DF164674828ED3010B5256000000000000000000000000000000000A10161D23274CCA95CB9F254C2EAA7DCFFEF662EE03320D5FC626A6484304BF62FC20F341FBE26E1537D7BD20E95440F7CC95EE84E1297C807A0BC9006DFCD5C22A5C1FC0865F5D70E5D63AD677FFFDEA52BF85D1A4F159F7ED16A745B4D971B620048B5F518EB2DC672CA35022578059E1ADAD7C07FE910A5D566B8321D9A12F34C250BE35CE964DDDEA23C90EA77C9C1BBE3532FEEFDA3637157786EC7D37775AE5CB0BB92EAB45A0FB1E833E8A6F3D06B85946E31A79B64A02B31FA640ED514A85882C89F693A06354DFDDB0B5E23E7792134C69C1D3908882DF3A7694A05B241B87FB2DBD1A4D9F26943B69F3CDF730301663089D1EBFC23299DA21300F735CEDF7B109F3E0BBE273776E6AAFA7054A6CD9682B967EB7903DE549E9558E62DCF3AC444DD7042FEA362EFB555BB97FB464AD7FAEABA3197C14A6740477DB50CE3FB8B762F48F880381D510FCC836E5880B48F08BD6333202E838AB73F2E106CFBFB218AAB802DA8A00F13F78FFB70C + +count = 11 +seed = D34A0AAD27ECAD31A5E08E9A2D7901A9B85F864D9B1B46F40CDCA0B3615B2CBA04EF82AD7BD8CF627C3E861477030BE2 +mlen = 396 +msg = 5C4B2E1A344DA1418B0F4BE3FD99505FC30F2A1E5B696E943BEE2451D7B268F722E04F8E00FDD9E1A470F8C977A6D45A5F621B8815E352FA14F64977D1FA08082A48AF495719EA6AC1C0B3D898603B4CF7EC88E68DD7190884382896D953D612CC21ABECFB01A04A1BB1BBE8986D34625756396CCD84BD1A6B5454DDA98824CD4844D98F356AB485EEB19F9196ABB1C3088C0C3C5846C88760B696D91A232D6F4CFFC85BFF33DE1A3433A27A209A461FCF37F2289F98BEA7CCF183DB1FC42A7EDF958E7913F8711DC375E43F09BE7C7A2C2B1318AE2A9CF5988FBC2CE0735A2CD9FB6C8496C34406C538C01BD494193240BFF947FED47B7CCE99A1747973F1FAA5223AC564BBA0CA8973D1310B5BFA1452CACE9110BC22A8D4080A8BAAA8ADFA3CFB6685679B648484E3A43F9B1B2531949BBB8FAE1846F6D45D9272FC2CAA2913B5D9F8D322E9B18A685122D74634C60730C101578BEF2480711FEFFE02123E76D6C846559E2EA99A98923EF095630102A5573EF027E0AB6E52555A9EDE0D15A73C8B2FEF87CA6FD9F903F0 +pk = 926FB9E01874D732E0471FF0DBEAF5D33141EDC6B70740FF1D44B701FBE1809C6E70B50B28459F46A6BB9F257BB604F412F631B0AEBDB580BB8156033F8E6E94A2044E295474C41D10BB15E5F4E5A3EEFC59B18A4C0C8A6E44C724604A37DCCFAC17962B12028DC735FD33B620D6A8A9C930093190DDD1DA9D863E07B15258DD99BA8F166D501874A43D84593508A7353EDB9892334D5C73973234172E1F9F6F574C3B1A1EA3530B2200DE2B88057B4A56DA26D8DA528BE06CA8CD3EA663E64C031F6C423E302133439D1E23CC91C473C3A809231D42DF6DA29711BC677F4A2E443805CBD44D913E3CA85C88111F5DA3CFED3CF2BDEE9FE5ED274E131C578A7FA147B73B3E6B42C4FA9F77CC56392C2AB2AE09CF59A925429C1714D8B2B5D10C9FA4419EFE4BF4E0B31A46BE4952F174C37538E500CC40580188FBF1D81B34ABE966841C1EB7ED5720F014510124A1C0DC4BCFE0B032E84122ACDD875953AAE8A149DB7E114D179D7C8F23A01E3F38607689A6D03E1AFAAB980F4EDBC390E9E3D75B794098CB12EC53BD7FC5E26AD5F354F688BF21D75E48B3B9519C424E05464187C112916D2EC5564FEBD5123BB2618C712ADE2AB67ED0227DF53FEE1FC2851AFB4AD6A2A9425935F4281A46B6CEBE2ABF0A853E4731E16A760BDD20A99A95A98AB7410934C816300D0D8BDBE60AFE49E30AF1CCD48F33744723D7A07E012736787ECFB5970ABF400CC5459CA2AB2276C369E954F173D46F8FCDE4786A814844001404C59CA682480EC088E7CCC2F89A409600C7BEC067261337953C14845557F48FD885CA04EE212BF49FA250C0E418119597D70DBAA2DA46BFEE589DA340286A64121D9F20F8586E866546242A18B98B9F8C2E6A5F8AFC0FE8617547B51112E8FAED8CC22F9FCFF85C75C587D638C015497CB215D7B3864B45CAC3F0DCC031CA97693B40C88BEE8B3BD950075756A82B2669FB35E392A7F9B2E6C8A09A1C829626758C38528321E9B589818CFCEE3A899B412C25A3853B7F5D6B002F9B99F996E7C254FB03436D7267D7857B62997B9AD803B2244EC859456CD2EF62874623381970D74D29EAE2262CCA9A4899B4359881EEEDDFE43A538BAC747F408ADB4C49E056BC35DA072E6E5B27DDD9D22ABBA769950D3F76C888AD3F6DC07715EC5AEB6B630CA92FCB8DA2BA5DEC63A50B5D7B5A8B5BEEF09B9E8A65577AFD269354265E91AD0A3956B333229D417EA3937220BA00021F43ED1E2B4F48688ED71DA6D8E35B7F3D05407B0CB099BD865B0040ACC724B2F6F5FAFA7CE75F3A00FB7677BAF6083FE4162C6DC75052E98F1D725D4F0F23EB8695BA5E2BC7D9172D816A38AB937DB8ED2490A4A775F0EC4E13D14DCB8E4412A7B81246E0F6AE41427019B1BA5F9E4594EA9AC0C711736FC5BE21EAA08422635C7B926EE8D26940921AA1A6EFD064953F087F14B060C32E58F7892AD4A3FBA11FF6DD98B019D9557E49A95BB8D75F2AF9CE093A62913F862D780C2F8793F4C73FD6ED989B8394763FE63C02A57CD8C4632F16067D4E41B2A2A35A870ACD20C44A87E9A4D0248950436B2F708E6E27C8D3F76B52308412EE7698A8B4EB884C3879DA54915FDF1E2725B570EF05B3654CCEDA262B2C069BCD2FA2578FEB7E54891B5F5C17D571607C01A18CAE0FB6CF64518589765927A41D488C01A3D4F714A384640B89969C838211CC4A8C77147C2E03CB4A3AD90B4574967E851FBFBAFBFAE0E0518023ED02B5C06ED9102A8EEFC6D8FCF187CE3E777E9C5668A6A0821E6EE2731E685DFE1A04AFB551EA2669CDA6B00CC3CEF3AF74D6514C244170FA7F3E0B805BA945C7A0D4A756FD34D0805CE24C70C91F282F37276E40FE6805F566F0AF37B5DF1530FDC458E291CAA9D125EF7D6A832764EFEA4A0DA7E75ADDCDAEB96BFB5A2C3FAE21208A3A007A733914793BF778048881185E677D3B0759E734403D502E302B01D0927D03ED935ECB5B977B521E3922FFDF7EEDC6056D7170D9F9C97A70460924861CFE9C27621E5685DEDEA50E617841C3D409B42E564BCFD0729594C65D479E47C12D1E30CE02FFA3E0713AA23E7E38A65F82BCE35D84E5B833AEA859C8D8C0333126BF092B4E4F17729C8F77377872E087404C9B6F0D442E4C7D8C06195B6D02CD4396D3937F43FA758D5E45DE602F80F192EEA218D7B4D356995FD1EA09B52F1418F8A63DB183134C0B9905C27FB72E66DB91075D60B1A6DF55E3E853FA50551BA5EC8CEDA6A48D127FFAC11C5D73CA8C41C90FFF13D53204378FD24CAF5FE0FBA7A35F523A4EA22384FD150F3577BBEDF46FFEC3A7F0549C612CC9DA8F8E31EA2F737B0A25FC3AA07BFF4A035D419E0FF08F1A7548979A2118DFA03733298301AB37F6A1934A002038047D7399DCB069DBFF5C7A9AC471160F8952DEF57F14E122A667C5E7951203EF5E284174DC76430009586E1C2B015F7083AA9E3D716DE2E8C5DD53C6137E2FF391B20F23C2C06E8290D9119CA6FE62A40C4583104B21359ED7CC5D4A35DD3FADA4E5D441BEBE528163A7C995B023FBBDFB569048BA2C82E495BC5BCD6815419EA4D864BE9D3A0CB78DC56B35BCB82AA02A6EDDCDE010B5045095B75D18F2B10FB6381C0C70C5225CBB4EED6324700B4A8FDED9D574C25E8E76A863A142A4DAD3FA7D1203C949394E9F764E461F86CEF09CEBEF35CA54919C7F9DED40E4F6D9E1A4D207DEE166AEE9366CA747DC8594D1D1B0EA369A82A2420F66 +sk = 926FB9E01874D732E0471FF0DBEAF5D33141EDC6B70740FF1D44B701FBE1809CB7B33EBDA53B0EF8C4D2436392447B252FCDC1BCDB7338E5CFF45B7ED1F82A8853D8387089BD9B1BA14034F8FC05C8AA6CA245D6490D8CD06ACC3EFCD59D64219809DB25EF8DDB1089D2E86F61050BC95AF95A9537D0D298B55CA5FF14E54F8248258177716505105650538128757240870082072843885483526133116138147181251613613633102603207464542005060780141435661472672464511052742306654128654416433423604861368363427321068288557303735451685883848221224602657057367057478013160658860144115157245277625811741031373253445262056071058007834582325675132566763607051188185703885338011761753436730782005154356777374266747350876180810142284785630865872888058540085876603076177650267042326583068600868545501656608453651756612834255340283301625504273166357573186620354558438547273770083158460310342780638736872108386841217470528405645462078863425572778187278868578547434621006054856661048684564684046362000567506338882167144474762838827438275447341482156070420818228448817642673024816045261411882832823633588207806188832407353160525141608726003063143518511064886852603237675406014087025731508250666320680537610556667668743738046288108864364656023256254416677637806316426748880752016863341344487573172488755231206474766767038120480408814131616603653812413326326327752434173450502768707126400630217206040251855375244106782521004371366704125651376787687663044117851222585327713651803370234858264123524586648626386002448604448721006687721143505780762303670624465574486378168035345243204166435666664665346847703244561641055737644846738303273072443335122785454264572771057201128434158061167204815103728580888010423213108381344808804231557673215815575807685516372740222527380206263223325255054501862737155128862561411866854303586481653458504727471360247326211212224063554528852568346317353262285358578073427313740444564118180186130051721870122363805725016677813213367316031003042652465403026516561328864808441818455700458660308202001030447803832576445326486440377727585721602640756305761074433005405201754280850471111454787748268506827266776007783644477324478005128285772755846233081163002087676746722401110875748378276181586717652021082613734255324861044284155603073600536230632304332335110162867014105013287044820455705202772485832008711821253043365663813287133728463626383617273637804304248236111570527866527104325543564334065440334058618188620603388702100813507148167485731163263520873207008323787657338485313660278255423661065450667781682582163201745111720018044466580780717432288404640535176084011560445737211651250444374774651618477072801128600437336881888721482385647205378643884816513338731654310215514342735384477742103373770452232568834554655132456682301381263327843062288315858366285546417246283477686352211556333703181786412163207647161740322401026548585332075702182138613148476658318841286814232318044565048833256052087056726041417487666175621820060064104482363786161222134454686830241741122118321382281604326100022474457472622150058570830783427571074641746507667264878083456627711386021286440461721761381605080608127845762517345324836534117306842805684434151405110827785C86CFD1F7DBFC628A03595C995BD96BCC1D28215B7B7E146F2C37135133963CE94790426EA37DDA46DD09D003D6894A26589D27DED2CD5C8489892AC7D33172887A712CC9E0802FA2922C9AABEA3E608DF1474439F7375A6BA481031A94F9A804FCD17719F3531702280E51E201B56B8CACF4580D176352963BF5741D515A45279F62CD55C33BAADE577438C89D38890EFB4BFDAE2C6A33AE42AABD11FAB50E5E001F59301B5CD238879B3E740EE1BF3B030059A9028F1B487B4591CAE5B2CD4C80D1E1419941A5DC34DF17987B08F8588FF2AE714DFC7412D3A3AD2ADB40E45B459AA6714F56D1C53FBD0F7EE27B03C713E64DFE6A7D064D4220DA3284F1040445D29FC6F85510B3269B90277CAEA7F2F9BBAFA8758DEB32A8F3DB7D000B36F5CA59B62DF5B140BC1D4044B29202C2503710C309E5AB4AA519FF1EE102BAB54CA3085B925C258FD7A007769F433E44D5E5DF967C08EC44E768118D2AE5E9A3FD5BD61D5E68C0CF55E15DB1AB2775A2E16B86872E9E762E835574638F0F3495A3DCB742F3E9811F8F6DD0779E9D33A36688BD8AA24D6F2BB624A870BAA074797115F5A457FE9B2487E93E8CE9F8EBBA34209F2B02B3AE0F2965E29902E1688E7B230BE725B414757872EF236C397A8CFD8B5DF022AF0DC4B13A07AC1DDB539BED8445D2DDF5F954EB67254E26C9C055FFE05EE1653A5F11B1B69B2B0758DE20F70CC21BDB252820A81B5ABA9196ADD9A6111D8B8DE0D33C076245CF7D55F7CE15BD374C8F19B6419C7E66442BC632959D2782B55E7222F4A3249A32B0535FE7E4A28966C86F4EC2C2F4E9404ADD0664B95D16F1963F8770CF1222CF11EF7A609880295DD3C4AC0B27811AF5D7C816B9919C908A0E69A221FB94F01C4008F7316EF53F399B72F5E5682E7DD016C6A61D0A72461DC4B0EFAE462A8A09AC2AF2AD7DE28DD1661D67D43AD6D52F9D4A68D732BEC8DE51B5E94267404BF7E7944524D27562F3F624FC90190F11F32E7FE2CCAD01FBAFCC4918AFA465B05FE6E901B13BDA8C2E17135B2E9E8EA1F664A0D4BE26EC5A1313D5C0427BF600CF7FFEAAE96D1E8FD7BDE0D16C1CD86FAB1D0D91BE83459CDD7F750C361ED625883F51C2D7DD23041EE5E93AAFF3056F5E9A9D2D1CE3830D30A40A7D1AD292814E3984F3F5064A8E8103A18981E394DB6CED5010703564536740233947099924537E3669F7571E9DBF09A1BB80E8B947C3F1164F9FCBE3F627184F9046E3ADB4D1468B9230D98D8DD9E4BE80EB1162CCCBD500BA6186E0DF78A7AF98AE36D3357B4E270ED22E784A723E5E37A46FEA38180096DED73E85E2D744CC105CDC3137F0DAA7E98A4D22CA0FBB808561FF07E47614283A0F3C28435F879350032DF7DB1D1A9E221272B284C54FD3C3164F963D0E94C9B255C17D1D1100D638614BFC4ABB2B3CC133A70296E8FE16AF04773CA499472FF1D04B0B42B30B73488F47901F69D5BCF99B8983040175C795D1C8020C1D2E536141339DE1FEF2F58B2CCFC6B3AB85063876257A079BDE0EAACABD7DF99C6AB56370D0D2510C15B3DB76518BF8AFA2FCD43AF59C9D0F92F3E444DCCCD4CDB9DFFBF383E2EE3D58493F9356CF61984B09610E681D39A526D9F8CB9EF261AEB84A662FCB4AC1C81FA185B6D0FE4383B40464B15D868BA8F3526F9FD7EE8E71FDE89D21D2EDF23F7FFFE5A40F6AD64993309C1768D856C0E81525BABB0CEE49932D1D74F5C6D93283EF074155FE427F13B9EB38A20FFF7F4E43215CD3F42936CC9C59D48AF0AC3E01DAF18F695A8485F2447BBEC9887C4D5023A34326C7A58EB1A097F507A57B3461E56B159C6BC4DD2E362D87CE0FEE6D1C6CB1F71C8ADD6CD89120BD898A09081E044FDFDFBF55A6DCF098687F46BCECC29ED9195343A16324F66ECC657626BDBE41176FF0BF32812AD6B291388524301CF919EFFFC2545D3ADD61EF2C74D63D26673F979934F2DC0390518C949AE8CCB9EAD80702930110B51C18743700092FA9A4076F43183ADB325540B97E1402AC2E0C39A772FCCDE32F75B8BAC3A9E8C08624961EC227B9C09F5DA25C58F97AB6E72EAEAD750D9DC80387AD085161C39022B597EAC383746CE2D8174EDF4629CB2210F84558BEBB260F16993FD67DC6DF441D1F91D36588EF236EBC2B90DAAB593E2B0EEABD793F3FE2E4C98C0B6F05268AE91794EE159C2467D85E16E36F8915664077832CB7B9868D6988682B6D7D4F4F3C44DA735E7D42BFB108F45E3481A2CD4EBD5A0CF6EB12618720839E59D4DA6639E47A2C42609538EFBCD9BD2D0906791C21D98B9BADB22439EE3C687817563B84F41FF5BBAF34050A5EEF5DA926B58EC46EFF07E20FB3232D084C6A241B7FFA07FD02C5606E5F7A0318E3FAC99F406DBC0AB6570A28DD051DBA2A9B7940BF8DB366EC3D4266701A7D0622FDB2E8DF2637773849522D3C222FB6F1B47FA0480E2FC0E8B80823F2EE1DEF01B0D051B051F3FF40600C8572A1F8B3CBFEBCF1142473282089ADBCA0127F484ED5CBAA371FAB4D28977B30333DE498A6BC563C8B6420385F25BE48E30CF55834F3B759C54D9552EE6562F72856295BD6159718B4E58FEC6CC2807577AEC7B71CB02EF1D5C536271F2F27E21007345FAD8D2903D2902F1235116FA9538C4FB08D7BBD401B50D0B476FB7662BCCB56F5E2E9BB3F35A6B465280CCA6EC322E800C22A93E8E7635D695D3B15265DA5B28E081CCCBB0484CE9DFF48FF478DF026206530AC573007826470DBC1626BFE082E38CF91B3016A8E4F089DA39732A290B39FFB0BDBE905E52531CAD7E49D87538CE45982A4E63664FF911F443275AC554DD8E7CD1A2BA091A45C5D699CD1D2E0B30C2204C2D2ED4B2FC6E39878D47A7432759B1C426F25F696D96F3C71969FB8EFFF21290B4B6DE78B5166DE9BCFC9CEA85947B4369755444CA1219C99C2C0CD42B0B9CE463392BAB777115EB43FD803D061610962E97C35D5D18F318AF7A8EE92DC996B3A637EF53376F609E5219487CC39FA51EAC2EAEAF17857C7BFB412A3EC1AEB0B2962489FF0F7BBB28AB1F2EC029C4597CF575E46323922811B1A691FF60A30285EBB0AA394BBC31407C860158604BE336C11130D246B6DD006DCC3762578141FB5D6A138F64A9F829712C38E8D3C50EBF6122AA80F42C6ED017681DE7B25B2225FFB5A1E52E4603708BA585924C27A743355C3ABF8CC562A96148D86144A984DA460FD3E08C623AC25AA3AB8A5BA3E69EBEC4216D461443A42E523F76273E204F2AF012A8831DCF203472A961C9AEDFF4B248ECC45AFC003D1F7F3CA133523432FAB28D9A176BC9B978939574D896E836A03A015EAF1F4C403B426CAFDA194DC0C8F70C910EB391F44CA1305FC07FAE942B083FD2C5E9A58F2C9E747DA09E388CD13DC4910B560B4E2468977C955D3EE275CD27D711E61881940C28FAFB96DE45EF754ED8E9A14707F82381C1CBEC6E84B83FA7C13DA03D6BA4946465124C24125BA9AAD893CAFFC55B52EEEB1 +smlen = 3705 +sm = 75E0EF837522A4401C601873B006B033E9DC8B7C34C0126DE767C884253303BBBCE7EDE82C8D13E7BD1999EFB9922954D07218F22ACB9F98E93113CD1BCA6CE6CD7B69BD1C20F58AEA963AE9F900C0570FC7C8D51825A9BDFFB7508D75672F7C5E8BF78869D4F051A2197D7A7E9B721AC4970862AF073C3D1CA1C10A454642CAC2682401196891C074EDE2060BAD789C9A136E5FDC0523DC9B670C0FB04A110D5CE7D08FBCEF13EE604B7212A2560DE7686E9D37344CF7BB3E5BB544BA3C20B73DAC0439F15FF854DD386252D6FDF9B6180F9F25229F08ADC6F5A4854C130F6FB472A6DCDB1A1F3D7CF642D1FE0B4EB6A80AB27832A6CBB18ED333B113C23C576AC8990D8A93BCA6832AD100E49070F69FFDC0FB98A84AE8613FB800B50EB8672EE95D887CDB5B0780591277A9E3BCDB6556C37C8340BB2E00DA981254870F473A0FB45BAA724615409273DBEF0CCBD7962958810412719B16F1BBBF285B56908BA155DD628138F1A94852591501E4534C2165FCA64007942EA91FBA3DC69FF81A01BF9A67DCB1B5CE06BD9BB1F008452C99C69FDE9205991FB918221DBAB1EFD192188F85B8CF5DC2C8CEF047935C208562AE18FAA9081320A284E8374FC47D5E794D96E595C34B429F644C2C73130C9B6E0FE284C66E88E1693948B14B02F09956C41B36370607BE79545D47CE3755D11138335663EBBE0448B38A7DA99C2CB85A5C8D79537285404379FBFCE466AC603CAA9B49E7C2C4F2A3A313A0B0BD6AF6A0F2CA92A82383E48BE7BB0733DA919FC3ECCF59A85AD5616ACBF455EE35337BD366A0435F29EC146AC2EA5136832147AF698DC847CCFBC8EFC39EA271E03F4DA3B78C0C253F265719F1CB971368A65FA02392F03C1742D526F3B7F72122A6B741C8B2615A90E328A27E17390AC891979F82601BDD40E6AC932E4C5513C76E618C871C993ED20C640BCDC9455929CDEC07577BCCB86C37823FB329B1D90BC331512EA6E9E455AD4F774588EE23DE6B2A5E44E658E1A1A26F08AC69B4F00DD9C357E4EAD888B89CF9F146A2B2A5BD8EA5B2868029A1CE8309D8DD5A31B15B3EF13D573F3877F9A632D5DDE27BB5E54849267E15291868DC1E6BCA7A8ADDD2960A5C52FA3EC4B14A8E32BAB03B5DD308C291FC8F5F86A475DC79A1A21DCA48DCF84DA6BBAE969AC6FBA67C57836B5C94CE4DD77D5C73B592D0166BD85D767771C448BF1E518B9E4FFE4AA05B200B90FC93849E34AA4A4A94632B43DD2C6AC53FCBF1C2538DDDA56425D02A7E2566A99C1D5F0D32B9330729B5FE62C5D28F744CD2ED085A04C7136713EC5ECC3E70958BAA33563AE8978B1784E7457EFDCD1C2C18347F7BEF217356398169415CBAA286273855D82796E0516AB5172A3FE3C06E3BB25E8D37D535B015C1C8010E994AC50A618D09B15AE249E4D29E14E029542B501D30F0D9245459192BFF2585B4FB781B6F94BC95944BE1B7C1AEB74A5EF4355380A26136BA7E87AF7FD5AE5D936EF65DC1FCEA34797E387601A8FBFCC8BCF311F1D2A64B3E57BD03EAC696DD199606479CC5BD007325C031465D489D09AEE14C929B30F1A6DF896C191B8DB03D1D35616090A514BD2209E3FD8B1B54BC5EDE31897C5FFFC882A6C324BCFDABBB378ACFD038615954E1544278CF9443D73F81B186645E33A773FBA47171793D289E1BAA8B0D646685B175A117C9C79CED6AA27763E68797F62808CD8BD17247BD5BDCF0792144F4DDEF3B22A3555EB08FD7168165F9AF7F5C6D56DA8D4C49053E35B8DC09EA1AC552E275024FDA8773A3908C57F0066034936E73F3066BE42DCC05C6D17FCE173EF5F541C0ADD900BB2AFC53B8795BC76E456BD93A6D976F8E007B9577497CD98934D4857CC2641D84F10602FBCFCEDAEF16746CDD74635F2E57D205AE972AD3DC9D09BE55AB8A20A7763A2EB3CE66A9A8E41314970A68087403691CDC7EE513CDE7462C35E999FCD9131B039ECDB4557F7C5AA0FFEF4946E2C6DB071F324168B8E1A07A2C21ED667E4D249D89480BCCE388A80FDB4E1DDAB25658D614F9AAD91A34AD6A222126CB4987330816098F013FF40545BCFCF2CA818C5D35DED10FB3A719D0F2014C0199F2D0BB75C194F3A2507125DDEF75E5920C0BD070BD7FD8C1B36CA0EF8E5363BFD243AC28DF5A8A614A200F254FF9FB15F1EEEDBC992DCD51429801E2ACA8E99DE1CFB46E9F080A68BB2FDCC2EFAF0A27F93970261FEF4FCEFD09C784290C300296591C0D206AF9A21E426F4C7A5385A57EB9BD8B29459B60D0800E3B99A66AE3231F996811CFD641B4A87A5470CF6BD4EEDEFEB04972F7856F107F404A962416F8B3D67763EF10A89866091ACE3201FCDE9ED44065C166E335EAB244C8B9453C5F66381B280DE085A54BB74113086EF8A41B1B914BE9F41C6E9084B49EA8CF11FF0D7588F818755FAA3D3B64053996287BA1D18B2EE06DFCECE87EA591DD2F5E68E6AC9BDB1736FECCBCC8E37E1C0DE8FC6ACCC52F404FA5E35C0F01D0E916FC8145AD7E88A7FE3D5FA5F1A1F6E6C402C40ED28BE69053EDC5E31AFF64414C9E554DB70794556C14D317E4C6AAE810D476F037546B78E958DB1B09D1F992591683CD790DB05E70B3BD0664394B299637C522DCA625FE2742A28D94662E621F0321A19536F36501DA9B0A3B134995F6BF319453A2581514F81F82DC3D49718092ABC99FFC9CCCB2EC9CFD1A104ED9B02F8722DC70B8B50A04DAD8687117856AEA011632AF59DE51F06EC447505901462D1BA7DF58C0ACB4D4A072205E41D52C269DD1CD5B8356AF7F19333177C88206E7412D983605B4A4F08E3905B6FC479379308DF1544D716C488568DF15FCA44D6BE335B0CA29B909FE0E293F66E373E6AAD18EF9DBFFC456C551C6A444657EA7524EA7A7D6354FE4641E7DEDC0210DC5F38645007212138F8B41EF79B85F87C89CF0C187924BA4A5150873D54F5083A4BF7AD317495B39705131139213BD9DA2AEC1F9D2E2B61D7827AE67434E3AF7E79378921C1CCC1AB2E7D72F9654AB3DCADA17D447FA62B99A182530FB8BEB21F903FB29B821B297B737AC3480E17921A1F3DBDB2DBEDB7ADE636ACAED4EFE4E2CCE528807AC54184A6CAD9897D38E49768108586A6B842EE328F4FF78BE9BFBDF2935F78B80B527198F071229F45D0227917F8208510399172585FAD0032FC8516E72D0EB624D18ECDDC380A2504B9EDA00F3F53A5207A7AC6CE4495F9A30012A1687556B1CC62B108A43DBE11FBCFB463024668BDD35534CFCD88A6AACC5AA0CAF3AC0737EEEE6DA04EFAC53A253AD03175234FB95211988006833146CB25F0E21B1011A66D3FD4C4EA49B5855AEE3E5B17FC820CE729F133912A994CAAF5D25692971712E67A77CFF1167FA4ABCDF34B82479149AF9A6BFE28C6CA16F68E26C041F02054EE636CF3006F4E4876B2148C5DC113CA8BACC1DEB6402C48ECE9A2CC2E4AF72A99235096F12E460DDBCA246B7D4A7F7589F45DEC1BDB99272276E110E461CDFB625F4A30F31D9334E2D295BD49175A68C263259E846428D1DD32867DE4994A425F330FA6079870DDEB140855B14DFBE2698C5CB52F96473334739B692FD53720B3B727340C78552098D976FB9756DCEEA7EA7472DFF10CF60084D853E84A92C0ACCEA4C73A5F160E99CA206E22B898F3C5E308883F096C2A71CEA625BFD4235F39CF705FE6F9192D60548D9DBF12F0437CB71647BFCAF7FFAD14C1AB60D14AB539AF59403A1D43FD858DA1CC44C6177DA18854E571F60F3654FD9D90EE955B19E25E717A6D05D6486D148944460B461282FB645BBA91155FB0D44D9E5262BDACBF08D8D86E910AD3E791B43E0B838D6E999D011A9DF72294B8709BF7837F9DC6AB40B50391A575481806B3EA642B98189CC85510AABECF324245B978D20090B9C7BEA98D5B272C4C3C3C0215FBD0573FB5E268B9B2F9D485FE0B72070626FF46A52F13C7DE514B2DBB972A820223FEF5DFE1D8732F0323B331446D88D43D0F0FF3FF875568F5C577FCF058CC9D9079DFD42D50EA087A28CEA72AAAB4C087D9F79A38D4BB81C6027C990210E91281EC230D12CEB436AF91C89D624D7A277077CA1E3F0AF08A464E34BCA0E4342C8B11C18847878056C43B6DE78E53F014A4883785359357BF2DEDD6C1CEF620CDD0E420DB111C78035E72429FEC84800ECC9C1991866D6E42705ECEAC8197E35B59C2F741C2403FF0F0F1A6FD2A4C4C01C90B14BD70C7F2F34DD62BCCF6419F89A70CF17AC983CDEAD4858766DC6BF54ED966E13366AA83A5B72DE3498F7F53ECC385ADEE7E72323F11C6E72A332909BD781FC451814CDD8D7D6C57B00D14743C22FDD915638C5AC4DBB68D67FE1C68116C9F393884456476AD8D28BC2752105A2427C44F4A0DDA20FE0B3D58ACEC9DC179260B5AD901D99CE92D4603DEDE99849DB80B582B6EBFBB77B8A38D498FDC4D5FFBC2E64B54846F41F8EF0524AD8DCC31385D843B9F6E79FEDFB5B5D7FB6F2986C843E45EDC4C7817749C7444B38F058E8E432A77B0A985C945F6BE96BE3977D050C414970AFF61AACB22E284AEE7C592CEBA104103F6CEFF708191B24434F7581A8FD3C859DA7B5C1C6D83C81ACDDEFF51530343E89ADB4000000000000000000000000000000000000000610181E255C4B2E1A344DA1418B0F4BE3FD99505FC30F2A1E5B696E943BEE2451D7B268F722E04F8E00FDD9E1A470F8C977A6D45A5F621B8815E352FA14F64977D1FA08082A48AF495719EA6AC1C0B3D898603B4CF7EC88E68DD7190884382896D953D612CC21ABECFB01A04A1BB1BBE8986D34625756396CCD84BD1A6B5454DDA98824CD4844D98F356AB485EEB19F9196ABB1C3088C0C3C5846C88760B696D91A232D6F4CFFC85BFF33DE1A3433A27A209A461FCF37F2289F98BEA7CCF183DB1FC42A7EDF958E7913F8711DC375E43F09BE7C7A2C2B1318AE2A9CF5988FBC2CE0735A2CD9FB6C8496C34406C538C01BD494193240BFF947FED47B7CCE99A1747973F1FAA5223AC564BBA0CA8973D1310B5BFA1452CACE9110BC22A8D4080A8BAAA8ADFA3CFB6685679B648484E3A43F9B1B2531949BBB8FAE1846F6D45D9272FC2CAA2913B5D9F8D322E9B18A685122D74634C60730C101578BEF2480711FEFFE02123E76D6C846559E2EA99A98923EF095630102A5573EF027E0AB6E52555A9EDE0D15A73C8B2FEF87CA6FD9F903F0 + +count = 12 +seed = 4FDA9FB6929E3F391901D69FA0AA2F25A9657D249A620F1B9E305A5965676BA76794CAD3355EB632579C3958CA7D443D +mlen = 429 +msg = 49755A7B1A7CDC5C9BDF5149968061D3C95EE67BFBAF02750C45094303A9D9CD23A08F19B9C768ADC63FFD1527186D09CA4E0356BB882E263BF015CBE3716C05B31A69DDDB790BA82C341AC9B6BE68A81B8BEF8D882304BAF0020D761A0DB04412033DC369961A5213B04E81736A580F1162780599CC029E262D67F31B2773AFB457A1ADAAA292163144F17DE384234F3303111FCD89BCB30333C6C6486F775ED099043C34E6C86450B650F1A02D03781B1D20691B767D166DADF1DCC4D8604D976EFDC9168373A7316DDA9B9FB02A4A321218D9F54E287B7167A08BC0153843BD6355AEA1310824DD5D5EC458BE694AF176119D9E588A29C650FF5500293659EA478B39A62149F819CDB7E7CB32E1D7B1284F159E2AB1B1EA41AF4D0AC94FF3111FC1CCD818F9B2CC7A259701405FDF6A51D2D3EF62789297BD16A659F14968EF902C4A23DA409BF13A4913467B5C991854B2CA6CC006D3F4197A6AA58BD5DD95C36928DA9583332C3FB134FA3890FE7E299F1C17205366C4F4230724C43E4803912E72B816658BBB1B63780865A1F66A2A49B96E93711B1BE97B827D12173402828B1A065B94310D5BD6098D +pk = 321429D73A5C861BAE4C723FAFA31B4D62D09142FF1524DACA9143944F17619003BB1F97C26E89BEF24F80FD41BE55BE0B24B6114ED1F469D28461295D902086BD1F781CA0A7F9E756D989711E98CB8C985F06344DB692AC7702BBA1129F6C6D5AD0001650086D29E5FA1439E28064D4E31D087A110841CB829257D2500965A59782622BFB48D2B394A183462ABFFFCCF302C4F0CBA941BAF2231662E990E7B30F2340D87917053CB5E8D10BCFA5EB99B9284531A06411CE39E1100C85514BED0D6FD7D29A1E824A5DE1DD8F76E4833A31B56EB8A51D458FADFDC029ECFE91497F798D23C66B4B47CCCEE67032D1C0944F91FFDA98F7261625C6BF57E95C420FEE3DF56DC287E16E6E8FE0C5F0A0CEEBB0ECBE7ADEEE5004D05B6E7CB5A0A4D0682725CBC184CCD4767C9C3DF8399E5AFE8A76C27232BEAB45B2393488772F3521A9E6B27E1BE9F568A872D210F1E60B28EFAB4CD0D5399512F17303ECCAD879018065A8B9A363F28887D596F58F3D9AEA75A22CE93BCD04B55FE2FDD280FC6FC6084B0CBFFBB0188630BDEFAC39F3688628D92D0A2FA9CFC16C272E98441EED066BEB6D056F8314A84E7AA700CBFD8196B5136AAEF1E1BD812A7B3418C0E413DA167D42C56741D8FC483917A596FBFB468EAA7E01BBE93232D376A43D096ED592F456AE3E53A1BF8BC10494A8CFFFCEFB1D61C68A3F1B2501E5A8C0434E9F14D6A3CE676E16C5F06991CE52E9960D6A6C181AADCFCA4102109BB46684C8C72ACC7F440330B4FD09344CD7D19ECBB8DADA7AF79A49517E75CF6F984E86260406BFD11A3A0C83994BA7A7A3B53607A080053A85989DB8FE8CEA69059CF51076CFF73C02FA933701AA74F365C5A044E2F40BB2576421FBD98B3777DC302E95B23398F7B522F13A5B2BAB14C68B2D90022029F9852F593B4D8E68A569F1F9511629E387C6FFBF10899B8CD8C1C1C95896AF54BA15EA9AA0BAAEEE45907E34197A3BDA5CF302B27ECAA3395A8CB8BCEB0671A911320808B236712E3078E0750804D294384007529DF80DF8ABDEB0424694E4A8752F82E75DA6820E611F21E77E444273ABD6B01A003C3F91EECA213E9714428E14C831EFAAAD4680E60D1123ABE43A658741E2761AB559DC3545F04E44779E501F660C44CDBFEA16042E020BE833A9739D854B77FCD6BDF3C5733221D8430937C6E1E054EF9ACE1496D2BE3B3CD98A52AFA7932C6AC61A74062AD1C9A44A23864B02D272C41BB4083397E0FA73491496C24525E54BCAA69EBBA67768404A22DE2356D8E1C360489DC0E9BB633E95A216337B7CEA123B5353A1C4249CE13EF20BCA14A297A733ACDC6E08C2128758CD333A6B9A138A7F2C2753061CD353C9D15335588230C1EE1CA9755D30D66E12CA227141664DC63C9C3525EB2A1F83ED483CC347CF85A90B64ED579B6FA11979363C1A506BCFEC5DFF00091880AD892D85BBE1F94E7CB1D8D36900A7B6373D1E02E82C05622525A71BDB4EA74E6AA38339FEB5D6CCBB9389849B59BAAC0CC88A00AE279448D47734EA9F70FC89FF3352B7D90AD395D9ACBCD8A098D6027DCC45F23F81026E118F916B11CA4257541EC1B284CC3AEB8430DF23C0FCCC3BA869CE032A97F1E113D5FBB3146601AB2829889EDAA955D493776BA871B74FAE18E40431FD1D5CC03237908372BBB7E28C6E3836E0BC9AD2D0AA0C59F952146AC6D789852BFEB2EB06E04360507944C771C605D8BFA4439866F7FE861AF49EE15589F9BC7BE5581E1FE3D7D6B3BEC613CE76C54F6DFBEC8879A9A13CD7F49C96CD251EA27B432ACA9B914C2C88A6B684012361460B29EDC66BCD72D7ED000335A8D802CBF00E7F1E975EFF94880FE55B013C50E0158B0DA8894EB691272DDB83C878E0AE6DF0BACB0974615409F1DD82A8E9EC393CD541252D52D02338FC6D097AEF985B0C9D1AABB6483B3C3C23A4698C16FD7E1FF05214A02200EDAE7B39412A971971972A9AA984997D500C4DDE6E2A4EF48BD6B5D8894D82857D5D275A894321B8C4E01B843AEA55A3BD62662D22E83A89A617D4E7CB87E836D52FD695F95D19849ED4382450C27A931E28782E4B317687037E1FC09E5C1C8F179B35140834B67E92395E3C9A26C5D292ED6796B3F5544BA43A35A2798FB804E14BAC168B5903E6CD53E82C4910B2C42A6218727919DEAE9F33A08B1AB2D1CDD52CE6F5D4075A35A184FB55AE7752989D797791EB9C44CCA046AF11E12DA0254DE61885B18C0EAC9C4E593A184BCF244E9D492A19EB75441EB3FA8DAA9A83B378EA2D1376C9D39E615CFF6D43E1394CE0770BB8B173212F0C0511F1197473FEC7A51CA67C49CA979538E929119057B49E6ACA78224F0ED3F8E1BAD04C258E321619D724CD3E111AA636DD99D21F9C29BE650797395AD8CE0918523888C959D22759B960DD0A853B5A423F8BFB57EC46C10DFD132C5CF061C98B1E51D95718FCC4CEC2F550AE8E9572B30DEE33EF25FC8AF0BD4F31FB8E4A7383B2A407E4C993F61DD4B5AA78C2BD11F55EF7475518E0FBE8D14D0853ACABE2A3C2C76F5A8D552716DBACEC784577A7A055D823AAE204CC03603870567E2253EBC1C013CEF8A1554465A42554CB9555CA9FC504BDDF8514EB031FAFF4FCD675C2D327A931E99F7F71AE43B1BC83439FED48C3C1C3D50C6C91CB78992F047E4F136231D4F9DA7A54674515E0FDEF2EB1516BC18C2E137DC6F8E7243735CE4D39792AB43119B2553C945DDEFB087092AE +sk = 321429D73A5C861BAE4C723FAFA31B4D62D09142FF1524DACA9143944F1761906E4DB10A71CC495E58BAC6BF6E282C4A1155147EFC7FE87D12332E33226EAF1A803E3E441CFA8C64839CFC16BDB0AC91019B47BC1A808F4B8E39B02C941BA8331A52F5DD76E0382B41E32DB2A4F57982811B75B121F672B9F5FD2F9323D0C34C22116522568780337860138836825670030167186130075561148370363584813863420552615756571066584711210865233403133770044268165106566466010445538320127001677011513342866258727160451028363151172382611435572227665010227138580812187146670470455014444414303832003210684782245242458855224276604000180723784101587804621805145444061807332264585247044012413062486458325613744152050310044186154474425131780501081020203000237150606226877062252572470508268551155863622260400233531624833736175428421087072517851121826515513278704170841810426866302534830486812724655784643454304803413144051830462245730655581128667114036036223707581478525186441528784608815110605630344474247461052667771535112300046081880625603845246558512640877070061300451851246337367850455805412484631264174787764310368471615025558268580312186725717881734416101733310616335763380144458648731528405122617880661400458371018332526560247701088722446143743628722058520001685271440804047338166341064482133806127504138122886463558213731535365531148370564431257108245341346616677365801123832557012084257622223612116737838886381404083866603060180378205865660638743168613112211208265463537047253676433713233155311738173710502743005314601710317225747616448372450463813834851761858812161580700466445508378260528305273676882156750162765440235282341624008222711150473242318278237230688628826455400460428406400046042110813482452464671324137274144665231535511728120324740228622118701174651735567374016532251868116745631577788806623271373872114683715856331244268716683114644522034811512465427136210254414477356721366031177845124385714746553032684714885774307763685886072484773628348410538451634657078863271735156884616650515514457542464166421322431740638340257041838463136486783300888870550511542785760341463161182377036756613033747152504512074877182522827361421882878058752664014683408601206036506384256217301040685811628735210865135804521612520544567463284612337735443376120328078377476258426841064385484617280613477556575530078112388573874763432145566870815677720500807640278772475002246083403706812666267482328268473621704147022811348738332455828558848675670178288274117171737532443134337281506507110631373560302540152317734877704171740753658075865011673511227723704061540744548100703862650113021524126030618080662536147511137461650323862457088742470586210643382000183154683088372386153673552240877205221663127642878468812286083603022002620468831204057326623203052850511724140854486621118230287680883161340037517451882708638654585658310665777262284456231786724348450448861142378258702383640633132078583500576765071072668154317871720070565643348733110542150320475383657020878551380022321737056070868204871628708132458631151178753118776161072647327877611633056747460162743454661116213342075124542324557265460372054844222275572061126367611155805330153031285276508578205440078681305624BD15BA66C4AFE6B12D975A7FAEB8D2AB28E719EB6D22D9AF293DA901688EE41C66AF34D8C4A7F00AA325A658F8456693859F532526F51FE3570B30DB091E5E040BCC39D1F28330E6AADC0E8D32A80B0313CCE662FFA6D0B656E7A20C2D9FC58CB3EC8EDA81B53D16F411990F3C77C9762F7C918E3EC25FBE56950BC963368890681361BA1D1F0A6930417E5BAADD1DF070DC3C2CC14EB1A3BE5490F5A672138ED381EF60888561AD223A0280C935E1EC557092F9D913FFDA5433B5506F387324EE9E4D7A699FA5342B1457535479454453F132EA22A3F3F48A996FE55F7D56F1D5A10222E5A116D3FEC9AE45851BA78ACD8D39630F3077DB30DF63237B4166873BD203E04A71ED644B11438B141636F63648FE2F4BB06CF9D45A6523E3D04E5B4DA1E72843FAD1D4FF2F5AD97BFAC7E6ADCB670FBDB7184A48605D3B15EB39586DC85AFA495F4083B23984C25D6C6598FDC7070D1046C7D045DC31746ADB22CCF5720EB5B86269EB920B670740E778F64E6E97F31EB44555ECA9BC9AFF8A6167DB35AA15C2F97101BD623198F36ECEC0005119E367A8ECFA038BF9E74D6987945A37CE3DF1BA57DB5D13B6389F30D26BAD6DE76FFBC3DC2C7440040E0E9E5367437FA1A7F8B45F1ACDCCB3C8B9678F830C0F6E767C1F4AAC488F4EAEE54CAE267F2FFF412BF025D09EA72BE5CC49529B1A5F25FEF44D02F3FF070DC9ACAB42A3DF26CA78D3587508C5C3005484AA278F34B219F44A9C22704CD255D22A7F4F737AB44E62CAF5FB61693158D9FE1984A47A44332E64BA5C1343220FECEE6CC2F6FEC6517B678154D6EA60B3C9C816E91DF49EBF4A7463B00843844655AE8F30D894D92962DE0416DD56929D10ABB51B239515C235D95DE1FF38F2AEBAEB82700C64D7C49D2CE5CD52EDEEEC914271316ED7A38D73B50E70B7C0FD72FA4157D982C2FE8226C924BBCDB9311F73E31E4861C3496CC1B633E09A1C898BD70B6EB507419C2CA504F01A7073D5B0CC256CDAEFEBDE126F17D8FB47D89FDF81D9B2953556ACED5127C29D26C29E6287EBA73ECF109FE7ADA980D46CBE4C6BA4E506161EE02FA1BA6E190188140B2C7DBC8ECFD08F223530A87BFCEDB6706836ABE01B9ECBA54142405A143C2001086F712194E8A023E7549835366E7F7CEEFDFE3F9A13B87DBDA12F57F1F0911A07FB62F85D85C04D2B03E905FA4A81E8CA64644B76F7EADDC3060F0EBB936B7C912F18D9450D057C01962A1B22E3A9D1D8AA2DBD7C6273A9CD61BB20CEB08A3D68A2E480EF5D3D4C1F0255115D8145A8BF6775397C1C25CED54EEC34BF78355EF0381B71A1902954E4F1D8450E067C6AD88CFED98441D64361B372DDDC007E240488996FD6F031B48F9C72F5C6D55EF2F7A0B669961199C5A1BD936E9CC108A5424BC866028E9723EFB8F3C9E90ACA5D18F5EB11AD9FE13050319B3B0D71532CEA03127F3CA3EFE800212AA421AAB6D0CF0DA11B916BE32BF850552ECDB921FAABEA4B34B4E21FC672E3A3FCFC1738C9AB6E70C677B823EB72876E2098B1AAEDC722924CA84D4730098C8714753F44FE635F32FA02190EAE9440E2EE2D4590F110F856AEA16721FD42BC6E16B2EE0CC932C8DDDD72DDE12D187AC23D84AC2C358D1FF6F8B33FED3B6CFA85F16E4CF9E5DB50A958245E55B4D5DE31C8617970098EBB50D768002BFD3088F4E630D66F831270219C80518F9C85BCEB031BC32881F9E2E259CCD42CD114BC409AA78677220DD15319EAF9E7D3F2177DE0906FA0A0958A93632502A5F4EF20A8E63386286ACDDDC075D411EECB6E5A68A61B3DED9179DFC5B1739483DD8E7D85000AB4CCF742C45A9CB41B3D81ACF2F74ECF523754F3969E65702017966640471B06FDF3BEA91FEB7C68AFAA805DF69527AE556ABA3D16CAF4556E3F4D0C308882F46DEE74B2F46DE6E46D49017F96314B16618375B154EF248DAC3680591483373855487735C8ADBF4D5709E787EEF02C643C8D0E8FF51AF1F4DFC772A0F9BB7933120BB1004F458C532E66D395CAD78F3D00E7B614C3A7586F89C0D33F6A6BF6C7B5F91CEE505B2E445D9362852E935EC152DC235C096DCC9FA508A68E9E8A19C97E6620CC3D3C619492F63D5FB09CA50915F652E7E44308ABC5DE613F41FF51806093E38BB9A30CD57E24E613DC3159040FBF4F91A45B52A0F4324796251E1174EDB6A87158829E8B1B247BEE4288401CB5D2511133D8E4002470C628FA0CB56F78FE6BEB2E23A80F6F6546ED04B2E99397612A18C8B10EBF9D4A4E7EE825AF38E77B4D7C432D880694E587A9A3C9A5FA1FE8B10AD95C1E03381CEA8370440D8AA4E6896ECB57546866FD453E3E8AEBD3BA8A5AA3D3B3B7E497F119D9C90EBAAA114DC54A536D5CBC5DE0153E802A8719C87C57CE1D275C20F31B41F9B320A8A0BF17F60994E8EC558AAA8BE56B916C425549163360045287A81AB9A89C158EEA1C8AE9065BC5E5E122ACABA4679ECB261A1EA2F427996537EAD89F4099AF5B369CE80F3CCE2B4C8FDC6F1E76C3D40493C351DBD8C5AE7F982EFD6AA77CA57C1FEBDCB75CF2B8E36766D780D7186C7803A21BD4A3CDAC58E8F9AC7B2E6F2A5206F943AEB486BF5C9C58DF4A2153B1F4328BDAD5C87BB396F33404585CC87B677E52F0A37D5F01611E57142E4D8D4DB83DB379AA1A733FF07079107DC90639809F36C89E6D029D006589074253A2F9541EE119B4CFBFDE1D158654DA9B00AFA90A6983515FD80026779D9B01E901E8928B3951E0F3F783FCAB9412311BA2C06F1292615A99F0EC9CC7388A5BC50B00AF1B82010A9DC30340ED0C648FE479033263681D2C22AE872844258736671ED92BB329480800F912A0D1BE897FEAB4F68CD4C33C71BF63F3EB99BD8FD7AA3E0630BFF52DD0DBA1D778D451D0CA97B98EFD9F910612B6372416A32D2CBE4C2BAF7A671D4277FE1AD66DDF5E990C44DFF2F711EB5149F30019460A9CA5A4720C0D539E640EB6E7843C907BB8AEF0E71D96EC875F9D074E80B068B1502FF0EB4B977761C55805C61189E3C95A272F8CE619AC6D33D7570C035414417BDD12203480406CC5A2D2FC5D5B85B6E7F5895D0A035E780EC4BB319E46A07A8793266C07FA96A05DF5C84976AFCC09167CB49CE38DE60A0962AE1C109AF982118492BF1C2A7149ED4738B6C6A64986116BF4BAA91CC8B5C53A7D254C77EA10ECF04555012C5122460A5616A35CD5D957BBF2D56982A5EC4ED640D40227F39544F69FC7F71896254302CE7B63914985D2602B2CDD572340C777A9874AFB16658B90B285B2DD786A03F778E17EB00832DAE53C3722060515563E16C24F0CAADCDAA0DF0287DC3EE812115E8CEFB83E2BFC48FEACAF53F0F73B8F89BBA538045EF20F170053640D2EAD201590FC50757C9D010E11580B8A3E4F1094083BA2BEB819034A2E5052E6A1472DCC26C2453A6CFEE616225B8A4F5831384BBF25D286F68D275340310F9C125CCD1FBC63B8EBED3EA44F4000145F9FEF75F1796CBB2D4AB0 +smlen = 3738 +sm = F54E6EB540CE29483B4E7F011266508E6A8C3363BC94480A0A26EB415C772790596BCD348280F03A5686FB46B2AAA4BC2958F34A6BFA9367AB6001D7A2B233F9B7971514B8D5563F9962F7ACC70F425449DECC8923EF4DCA496DF80275BF0C36B144A04BA0D2B0E40F97049AD4A45D1B2E48789D3C8E523426CE79BF3A97B3D58F7CC451B0320FE08C5FD25851BAFE8A69C82FADAADFD0489D16AE8EBD62FECC421528BB4AD65C4C452A975A388B2CC78FC665AA0DD73634DB690466AE68762693C6398B88A93D034AA54154540343C6D160365E167D0D12EC97B2401F358A37F61B9B939F2DB92FAF6CF9D2E2B465FCE5A3E6BD98A775C8BEA2B281384ABBCB195746CA232DD91B4EB013F415DAEC72774F0E0E0C56204E957C99A4CBFEB551D9370726C7FBC6DE0A1DCCBABA0B69DC86B5F4DDFC43CBF5BA915E45C74AED1CF9708CAD72D498853CA81444E07304026EB0D48BE61C3115D1827A54F142AE5EF2754AD3847B1108B6BB63EFBFF0E1A572D23A82690353F65CBBC0E2789ABD7E3544CFE623ED127B22A8171950470475D3EACDBF9FFFF5250A950E31610FD37C7FB9FF2CC75996E9D4F4352DA73C22CF02EEBF338B979C775DCC39853F926D2E4570C0770F13F0DA25F3FAB3FBA06EDBEA3A148824A5947FB99CB3CD67D04B37DD72BC161C1CE1D2B8342EDE299F5BEA8437F1A9102C36EF8DDF0707A844BD213E057CA51D9CB0A4E682A71B1A6D41ADE47859CFC147912D5FCDA4AE7C90391E83E799EB83E80536D44E8DFE7FD28806202176A359B5945D471578F16E4F2A13D6868D015F34CB017A025150B8AF97DB6814CA32CA5769C060D6D7440AAB9C178E5F1972865716F286EC1349CD082244A8E3637DD9A1118FF1EA08E2086465A90EFD43E226D818894FA19901690BD572E6B80EEE21470D35A3FC6DB7978C2D525A87F5169F46BBB8C90561C39581CAF25F85ECE4988F4682D366E85DF34D8EBB5C172821E73D62B428778945C9E4DA6355B25D1A2AD8CFFB78EDDC078F6484428BD0853E886D8CED518DB2F8B66E62C2F24BFB4DB427D930604460157AA902933720809F827DC037DD545D2AFFBBD87750F99ACFC92FFF680FA021746CFA80C38FE1D493D0A4E75B83E9AFEE53DF3A3B0E953237284BF85CC302EC5ACD73F0DFFAB92D5240F781C343B57BC741C22E78C955EA289A3B5CD384E7F01063595EB0EEB8398EBA44F8C296CD79C6DE648B57B44AC07DB18AC225517075E1F0E38EED0A2C1F0C13C87C555E09C4A82D0BFA0D33E6C62B78FE6FA7BA21AFC8834B69BBCB47E2E931932325B0EB205306F206CCF5CA64218156171AB2AA8188678E3C0272020D93FEEE441F04C4878EECEDE81226A153FC3EED28B8F223B6F76FC55ABCA8B18C5E06F0B5AE688D653F1653DF2789EE792A89A7B25C0F48DEAEB24D67E29AD10377D2223339BEEEF52DFF96C16FE5E707913023FC5E05C6F19070456E95040D7D28936A864AA4A2BD2646F337CD8D7F23767D7A1F0FED48A68117A87A92301A51267C5E71EDEB15D3230560071889B381BE1F832C9137A835EAA68C76F633D2A614E6D9F234301327E74B91CE8C3D3B8C2CBCED5B882618EC2246F7948BF58AE417A141067723868F88E2B629D20973ABBB00DBCE4CB2248382F7D51A2228CA764059BE8CB6A4B02A226D949F913C390244221EC2B6B5743E13F3489A67414FDAE60B928DBCC71791DAAAAA6B403F53E28B7D090E646BAAEA3E3B6C1A93F5B8850598EED9F7E76D884B36A7A2598A098E9689FA1BDA608FDAF82A54E2769557D7B4B168690134D16F660578AF183BAA864CED9B6644493844304A01849EB78854F79BEB39E04C524F9B6EEA905BC6EF5AD5B6E4F2DC787EFF024E42DEFC8AA5E7792B0CBC5E6B9C842C31987B240932BB0132BCCAF146349149CC249481737DEC44BC807EB4CD905D8D5D67581B9E22FE11634A32C2F0D1A6AE15B590D87F26DE0DB8C4B2AE2D7151A9DACA29529F731B88A87E979242493E80A9448ACE7522B1E9EDDB90F2FC9D6DF4CDC34183C5A945EE4765445976460F052D58EB16CCF6DCEDFC185797CCC4CA3144F99199B9DEBFD9E262FB2355E21EF9201A01580D60FB6C524463080DBC7D3E8DBDBB2A5B925FCD2A7D8DC029D239F983340274D89188EC123DA48CCDE2D6A16BC68C16F00573DF1C1D3D8F9AE91252F28788A427C04E5C0A795D5D5BEC97087194A850AE66F1DD979A626A17A4FDF8B09E70597E4B11BD451450F1E04DCA27288DF5B65BFE7699EE7E3E360A86195C5FC53D501D3489B0EBE89BA2B16B08088F05818EAE2DAACDA9DFCFF785F3D3D1FA8BCC0D93BFF6E8E821C07874D3A61EA326777B32FAFE01EB5CB290CF3C6D3D0D50FEF1ADFAD3375BA0053617ADD0488E6DB68FAE482872768498778D594143D8C22B5BD012F0FFF3C9446CE34A1D28E160596E907B473DF48B69E5D60BE9C26FF530F5F99D27EA9459848E373CEECE27751CF4ADDE49C2A36403F3BF8000E91ED5680FC234DEC7F0F54176E28F59E1CB1A8BE3250EF3F913F13262991287CE54ACC81CF9B048F5A2D15861BEFF16FFBFF742EE1F6D239707ABFD782E031FA7655D622D6D81DD54DCB1E799A9490B608B6B2D2B4D48D0617A936135B629D54F3E1525276EC21A16894B8609C52DFC555073595A7FAB722C0CF4E86456F7E22488E886F6FFA4CCF87A94FE0C256D83B139536CB1B490169CFD3C4D4FCE99F4109E6BD7CECAD311E48395D8B82EDD8E198A07469D524D2C9BFB02731B828FD18FBE3B4FF70B0F96DE78969BE49240FCD806DFB7595FE7860099FAFDB8E0A033C82E7F7ECE8845A8D0AE906C55F01A7291D15BEFD7326F6A2E6FBB58419E63B9ADFD9C2A8D45F5CDB40155F13FED8F125846A39C357B290451921E626B799A3BF7FBAF13D62AA3E5A580EEA822BB4E350E9E9AC4730D88C428E672B95B67FBD4111765117810E54BEB2F3F4EED470327C823CB01A1A9D444DEAD3025CAF74CBD7AB6FE384897AF1598F25871F7D1861C557BB7CE118035E9E134E2E2F15283815DAD6F990397C4E30F60F58666FADAFEE3F21D52767A61F0A0CB9866BE91E2ADBAB34BE3C48BCA0DFC35ED5CA35C84F884EAC9721684A95B09DFD8A00DB91A1CBBCCB72D2AD101E78C52C7AB782C7BC4496A0CD1EA6DFD66DDE0BB7F6822AE254E2F039F9BD21EE870FA2135B12388F9B4163D00EBBDFDCA8BC8250A2C05CDAAFCC29FE097A0E50E5555C5334B9E89F87017481E30CAFE8370ED7ECEAA2A7AC541ECDFE697BF890E4E7E2EED776BFF07715F2E5282E23D22C7169DE404B807C327328CAD0BDFC873354607477CAB3EACEAE7C1620F12C3876E3FDFE6BB421E1FF9F745FC248901929B4D78E7C42BA51825A61EE148EF6EABFEDB5731CCBB405B16AFB42FFEE812112ECD1F28A06DB9E1F77287BF4B4F80172E4C35752D9A37EF4471971FF19CC75BF4A293FBECD1AB10C00BE2010C78B53CA27D6659C3A6BE7AE614FD035355E8647C35C6657126D6AFAB5242A907E13C96C8238284F4E2DAC9E90ACC14711E7253D6A94CC8836C70F528E81ED4D67B1D30C3554FAE839B8062651740D54580858E90B365A1C304760AD27810D77486008030289466101EB242E3AB96AD1408B310799A852D65F087FFB32EB6FD7C0473582494CD298C9806ACDD0CE3CB29CD460EBAC4ADD6282A9816E1F676F5A3FB31F1ACA5184DC229157CC4DA54BB7DA88AC469B42DE3B0F7DFD007273D021CE910171DFCE4348321A9967240E6BEDEF8867012E02B065670DB1F4D2336F87C0CF1DCCE0B495EEADCAF592E3A79930A92BC9E07720581076FBAA15F465F81102136F16E1FE11282E9C9D4577F96FBB84AD816C117973A59A28389894FE7F28F1A5C604803F60C893F743615A29630F5809472864F2FA59E77EA8EEA1ED972FE5B538BF398622FEF1E1F90CE8359555C4891621B2C5E44D5C28589546C388DBF2F4C82CA4FBE7AEA3BACDA005B93647372A48CA917E50C6E8D047D73A9E12F424AC010E123E50CD5D12BE6371BC75370E63A402BFF177A2D649D40B3BDA4A3465D1C7C379E71D9AF0648E7D07CACB4C6328499D17CE5D9CE67C71499C320CB70C8336BA8189CD5A60F1078F56B9CACCCB57A469823E825302182A785A5BDE665A72EFF8AE5763A0E0039EB0DE80D402A860AB1BA428959F0C52210B29D40B57B75145FF67CC9BEC67CBC0736710D4C9CF0E976742D9366C5F7D00A0B3D61CB28CDBCD7C068AF437CDCD0EFAA25435871DE56F026E0CA95449B8689E2F302B92507F08B1FDB43E2772A259B66F57C6FB6BA484DF4F0C38846653E957CA209E89853B1CCF0AA350FDFAAA7BC91B07D917ADA0EC12599D4340A0BF9E97F2BB5A4DA42179651FC030580A63DD549B0B56D9508B58B10D44B135171BA5AD1B59CE8F8A80A5D08B8C6F7203B0BA790799257A166C36CDB4F1F481E1E3C6C4E0531D54578895A11B6717EA72FB1CE2B453F18DE9E130BD98D3BEB14F91EDF52A030E3A88ED8902AD235CC30E43AD220DEA9F58D86DAC130FCEB535B5AB4D323FC848918848FD4F0F2F7165860687AC8F4F71B283E4A60CED3F1F85A8FC3E8232D5A7BAFE80461A5CE000000000000000000000000000000000000060E171B212549755A7B1A7CDC5C9BDF5149968061D3C95EE67BFBAF02750C45094303A9D9CD23A08F19B9C768ADC63FFD1527186D09CA4E0356BB882E263BF015CBE3716C05B31A69DDDB790BA82C341AC9B6BE68A81B8BEF8D882304BAF0020D761A0DB04412033DC369961A5213B04E81736A580F1162780599CC029E262D67F31B2773AFB457A1ADAAA292163144F17DE384234F3303111FCD89BCB30333C6C6486F775ED099043C34E6C86450B650F1A02D03781B1D20691B767D166DADF1DCC4D8604D976EFDC9168373A7316DDA9B9FB02A4A321218D9F54E287B7167A08BC0153843BD6355AEA1310824DD5D5EC458BE694AF176119D9E588A29C650FF5500293659EA478B39A62149F819CDB7E7CB32E1D7B1284F159E2AB1B1EA41AF4D0AC94FF3111FC1CCD818F9B2CC7A259701405FDF6A51D2D3EF62789297BD16A659F14968EF902C4A23DA409BF13A4913467B5C991854B2CA6CC006D3F4197A6AA58BD5DD95C36928DA9583332C3FB134FA3890FE7E299F1C17205366C4F4230724C43E4803912E72B816658BBB1B63780865A1F66A2A49B96E93711B1BE97B827D12173402828B1A065B94310D5BD6098D + +count = 13 +seed = B0E6A23FAB10A7A333E3720BE00D31507917F39C5EFE1C98CA18BEB5C3101FB4479B478A1558C4C00398C55C9822FC44 +mlen = 462 +msg = 439529DF1864297E33956AFEE00A60099B658A67830A6A6ABDDC329E87831D9F9B647917FEDF1AE182A40402143285516FCAB83F447354C72FAE81AC26E7005C2AA561763C152E66BD80F14565F47DEFA440DBB491E7994AB9FE35995D5FBB3800CA030B43DF611141637A5246AB9D9CAC02EFE14AF60736B6BDB2BABB97CF21E831E5D04D41C00F090B154977900EFADD3A9313389A3F84CB3AC38E8B57B70A43DD08A8243F8154013FD5CF29DE5A8DF0B197C12B17E0610FCFE3625CC94067E01E23D23A243AD1C1F805CC50E1447D1DF93C25B8D76396BB7199E64129522462C5FC8B30C132D4EE9E0BF6F52961FCE7ECF650647E7064AA5A6574649A323E144D7C5491DE4C0A1A76D08F93F87A2FC7F6955FEF86991E62E2CB42908E83B0C0A8BC180B7453CED293F1E20F300431EC1D395E8A537F0BC36A673D491F14381DEA90D8F176D06031B0A7AFB40EA8F76D37FA82E2572B9799A5FC7CF4C49BC20AD78EFA8CD989A84D72ED680AC3C0F64155C56ACBFD7C7D628B418A489F961357F77BD62204ADB079DD3106485A37FEE535C9CF82E832D8AADCBF686976B806B02AE733DB46DB0BF162E973931C3E338CC86DB38C66262D1B2EBC7691B8281E0B20BF36305FBA996D20ECFDC695 +pk = F9DD5F7DDF9ECF752EB35A36D65B238F4EAFC6A96D87C988EAF592AB809B497BF4B2BA7DB8129623DD8192F1F5C5AF122654749D2BD8B7350DBB38D083829BFA6419D9F3E416A6C1E7F1D3D04689BB31747A7A60C2F6E15FF2CA802593315189DA1D2A8C96D047BED7D4D92700285C7D6DB5C6768DFEED985ECAEEADF99D2DA9FB14EB33F4D4DA8869DD618BC23FBF9BE0FA5F11A86801D732BDC1050B82E2095A07E9D0F0DB9DFA3E85C24854030ABBE1F25C06F59BF42AC2EA4839E4EB5346DF1E09641176215E49FAE6256E22A8CC47FADEB15F4CA893FE964093BEFEBB17497484F3BDC2483B74F5A67799B3302E81FF6797FF5ADFB7461450C01E83B895A5C7E1D55A75A5D7CFD4DFC9A965E32A946C271BC29519354B2E867C6B499A78B814F68003A47B63B6AF36A748FA765C4A303F0CE4E11BA268818FADAF860592A46980346784CA0D3A59AFFE733C378DFBA45B4BC4DABF058724F3C3224931DEC87A680FD08A18689C3315B25BD884620BAC1DD0FB7E00D24D1816CA177B11D4937DE69694CE2D25B8E5FA5289859BA425E974DEFD6103B29600AA21522A399B0C6850FC311BC13CC4D98B73C2DF20C7E1B6E46D9CAE2B35D5171C62A758C4FC0ADEB70D76E0E1EB4DF74BEF91D7C42B6512FBA888EC5D4BD664F78C221D4C3A4EECB1A529748311F5FA498EE6752F9DDE590E6B78706AAB30CE7F42116BC551A5BFA714B51EE5E927E9B2D694D1EE792AA7FC0E347557E17FD9D8CDB063045A7359705F7BAFBA7A13544939C185DDB80BFC6C8FF3609647BA267102515327BF8EAF4D99A701E170BBED4D526B7ABDD110FE1ABFEC70FB8253DBB474242FBB585F5F3FC2208831AD46365256D256AC225086F68DB35D178BA0E2CA4324F73F2E249F55402585E8CB7DD1265744024D95C051F8CC585457C86F92B2F8D8D405A92CA612F1FDF70C903C74A97260C753FCF21509B29DAA9EEEFAD29E32BB74B8A8182776C51CF8C5DC62648E954584D375A9ADF99C4FD1712A0BBFDB5BD7713CE16D02292610AB3947A1F5CBF8891C7FAE9EE62B5B499A7179322EAA63533DA0C63701041FF03459CC5B69FA1F2A521DBAA782540466F2C9AFF8E59A993AA9AE86738FD4AA95F817A91CBCE9C9F4BBC618D1C6498B9F096471CD72A4C09993568943AD2B77D27A6F3CA764B3B7A2928EE9368EE28C49048D707EEAB35FA8CB7EDF5947C5FB3092AEE48F3D2A3AD106F515DFACA5522CBE4D02D1538A954105EFE7EDE2FA9EF1C961EFD00367C94E25C3F223E3C1E1B1F26C672B936B5457E223B2D84C5C0F292B7BCBB5A14E12E842A32385F16BECE5CA7EF549FB68ED83911BC3A69365D4C537B8584ECFD333B525745D565D889A37BEB35246FF74CE1EBDFB10B82BC1D53FD7FB70FD5E61CACE965A026F2E8D5745400555122D4A8AF4AEF0FFBEDB811C386CB089EE61EEDA66E2E2E1E1C2FA6481C2F2A9EED8B8DD1C88094313D3B93CFC3C7511175178516184CAEF456403FBFA52F78A957306D6BA12FD5053478B2DF9D44AB6F0FE5AFF05C17AE8714B961E07B460512400B0A6DC7BDDC444E724380043E09794B98C3EB1C09C5B115320B166F018DECC433D892163D153BC81F75DA8B669B9487B4D966A2DF36BE16D378CF1D60147D8EC9B2972C0AB83DD83D13613243D83A5ACEB52C2000965752CDD9F892E6F44FBCC734AF4482B0A04AA2E9CD7F22DF3E11CEDA78F9937C89AF3CC1411722D67AE48A0ABD09EC99D2C348D5E22DF20FE4E7B32F1660019375B96818BB565D4FB8B9664BA973DCA531B503259FE3E1C09D725750D955FB664D5A247B7E7EEFD30B555C0391D31AA82D32FD27BCA00D7872EB72ED0366BD791294F951E01C85B2F9F82A0650B03016306DD565B77B41D8E9ECBCE1101DD5E3301515B887233C4B687CD2FDDEBDF539AA1BD145BB7E63F0F5808507A31716EF939EA69AD5B05EAD0BE5648AE168D25AB174F5CFE38D82DBB97EDB82FE8C3B3FE78E2B294BF1F2992A604BAC7EB1C8210629A567B8E2B1BE2B7B42619F0E775F3E1C0F8064A8AADBBC91A7EB1D375AE5E2FEF4890B945292B4511AEAF743B9B45798EA50EAEF9BEA21C844EE2F4CD702C3D7EF321508390187BD0299F5FCFC222E290AC1E609982A8E9BA6783D67A298737A2906D293EB0FB9303D85C38559EBA6FEBED1B3918FEC41211077D37391017E5CF98FF839FABAEF1290BD9696C8B9D7AFD23DF60747D4F8B0435DA469A0FCC7901C9AE0CA6A7F404370E6626AE94D44F27F41F89D2253BEFCEA8C0BA6A93BCE1ADBB576B18F5AC32855B4CE410745FCE7950BB02EF9D2E00331F6ABE0ED7062C58C894F52F38C089A1C32D9EB8D7F07258F69718AEE9BC6CFC1416F74CE9014E07F09EBA9879ACC389B467C71021C9FCF13D1CE73DF311C708095A8A78C069909555D271711C41A94EF04FBF08F3AFB0B1F68175715AFBD5E4D9EC7CAA5159DB9AC2BC96A4CD108C09063B4C634F9CFED032B5FDFB11D0101BC68C22553804896C65F4B9FA5FD27376A1D644A6F831B54D392627EFD7710DAF6F3CE903526E931CD91C368C116BCFBBA976DCF82775FE0ABF8BC4AA4676D54983A6BE8E9CAA53A3FB9CB862BB21AF1B6D8D4E6DF49CD681A903CBBEBF31B1C0EEB668CF0376D4CFEAC008CF2AF584537A657D7139E4F313CF7DA83C0AA0B6F21E039891B4CA07A74B7C088826F2A658257833AFC550BCB6BD8F603F381051CDCEB34C0A7794 +sk = F9DD5F7DDF9ECF752EB35A36D65B238F4EAFC6A96D87C988EAF592AB809B497B65DEECA67EB3B6EE4E959D1F78CC2AA5662867CAD9A4F43743F7B78D68DA783D22CDC50B1F901D818A4DC3BD3283EAF9FBCF54158CB096A221C72125C924C5E1A10829BE26104F01A15CDD6150CAF9A93FF2BA40C538AC7C6594CB93AE463A0731340542747841566671107534574645175423845258551686422318611256672234075446646655323436616454205676488140836734148747570223508275050881564733732601176418145881255533820256068484203233136172262624166452588067683450330774163628675634442541526344327053263065740184216456531377712052682511533305287600605765477641021780611807676004868277445706703061421680411464611480228700154717733765121176034535671758207006645151733281717567721528447074277457640684821081636246567026535066116243277104873082761203448165185266630657403616547451305260102588114084325000164375463756114213266323318726348560403617564610224734556838112350377143755483756332418010065571560222718664201627384186226363047563180878521776210137121242176765553771704253277623465835372368412845832748607527608171538500052403664376488733868657081034167066121520371452450167678612684312127328251755036736800851557822670067257404687018150206880216888855508570066526246476073300760637310710610123538803808831147586641268850854588837238757728783612876734488604303805168634236481070622060162483365070061631138043014883547777208378771856136014430406825586148641581726311308368854648818417220734266488013648160770625460240128310222658448406033482175282034740743414688600533155504253461876682203722037772202410100653057526508505257084714076303220407204330631147816834640631123542346584678151438368838084766678318326366828653535562238125711403231883443234528284544024106128533851021307046325160032260666678686548050003400065434511470566327436774104462824674555843587061162727483063683110858871071012224382073657010211048374245618141226820558887842438328574301205613860064636428370406580332454831518451875215606064666683554822035718747638284625331551517088371516106021312832300137882005557365522885404334036660312422545710512830346240803173324606316278586878126142837653852835752014740247451341055018156738282551326776334786144370343831355625778471263040101468540822410781011106088702015575241665776788208220010414518201462502632862250341068035437423332222858117215542557673136030476158681845477141683377052448737588886654614856151586241811730882241404406356882164052402114888173463706424467855778781703311165672678266388045403082144381757235877642560487474758380544144822027125701201501185103386127252453200813757277888110551784886653550078707233014525621664428376741433081811345560000545263424618082470430418376820441232348853487754841863467074001171183730230152633581526173841403606713805342251507384332683051445507450048550426183610767548357722648264837887013478376628461532471843030554077862734377682116880667753238500771727060512582686214307741446383836205045831408813660576263041827282783634218582502150320525000428868211821555471468442861680078103074237750260225078522185125875812125231136564630067256201476850046256506844520285457628316705351826764512430130821458284E8F0628C5920898ADE1CC8DB025A6DF8C1F6AFCA3335DAF35C63E1A2166F15082A1D175245B089F555A5D24B398E053B1719100AF1923E9D265849D730CFB248D495794AC27DE9B5B0596D86D2F748CF38E6ED9A9616DC3D835521DA9329D2287B677458C4E769D8EA80C658E07BB573AAFBB06EF22C43DE09CC12590B2B978AEA1BE2D3F45D0AC784B077728E76616CE7D1DD7F9D65B81BE5B2796A68784C8D2F12BB857349125B7F670D095AE04E46146AA232E2BFE88039A2F7FF27FC8DF39D2B9A0A9DBDA6334DCE17930022E4412668C4ED376ABBC9B162A743F98CCB1AEDA144320BAC3E0286533E48BEF77239965F4BD90EF43149658BD935058C6CA52A82F9085303FA8DDE33E517AF7EECF471E82F619B4B2275A19673D551861C670D302F72381BD783AEF5DF7F4B7D915763CBBDC3265B2DF5D18BED902B610B3D1AA3192A379F0B1537BA5F0B9613BED66D366497A820C735F62202EED1F617551D056804BFA92C6F5D54292FE458DD6C44BDF95D20BECBCBC77AAA3873FB59DF9C5F31134B48F788BA07F041F3E9DB312748E35E74E6303A68D50D04F0044CF7F863ECB1C3977EAF81E3FB97B6057B8700C471E4A8F8685AB709E98D12AC19007949A59D54F0B86EF61AC861FE38CF29237674E518822D11901FB12C70961200D9C03DE4B7AF5AB2935DC8156B1C552F8E0848FC56A86CB869E0EECAE8F37D91DCBEF9888001CD7F8A92D8D2F9DD7985322E5F1FE81F173392FB4AC49FDBE213B31F59C04317F483FD1E4B237DBE54CA9E60BF58FC5CF1BAD2B07AD5C61F31E82C7911A1D01DF1DFA47AE50E41F126430B1428D36C1D0CD43ECA5390F6D95487857D2F69CE00FA948DFCC8C827FCDFD68B9050B6ED539BBA760557086CB7687A936A571CFFCB3EC1CBF30698016B8DEF849E2CBBC085DEBEEC5CB994FEE1298F481C9FE35FFE41CD410DDFAAF13F09411CD109994BBD50E4573E98FAC886BE6946B48D1EAF8E456D8FAC51BF175DAFC91F915AD020B271F46645BDA13D2D87EF97F14D2F81B7C5FAF159E0A7D90E03D1D42B31993D11C5EC1C099A1055B63FDD7C6DFBBC1C4E9DD299B645FF23B6ABAA8658297C20972E97F6684AAFEB043B5CA21AC8D2FBEC2AB863C839A5A12D8D0CBB23FA7D1250DE42BBB78FE0B64AC49DFA56BC73394C17F17E5C67D61C66ECF00660F22EF3C90C55D0771D0F54E54A39A804D9C4CCB847978C8E6D07D2D1E924BC14CF914BE5D100322D81C31256311D82D3A667D0964713FC69259484DBD8652D2B863CEE8E2161FC563A7A4A2F13320022056C8E77D6D356AA8D78C16956194ED385439239DE92D887FD6BDE3765AEA95F6AA729CF0060C1D587A676C6BFD53001D48AF8ABFB83E0FF5D23DE85A3441D68D3C073832AD57DE39F33A8FA1A9A3F7371DEC90DF6F79D0E610A92C16E406EBF53DF428357413A5A63EA9110DD4E85AFED567283C695E7C7C716F8A05C359D190C9B238767A663182B2EF97C93CB44C333036F8902074D420058FBB6FCAD7EB58B4261062A9FFAA203BB8DAC0EC090072C8E2FF80941B1FEC149374E169D220B08EC33E8119A0663F586E26C090CCF77716D3BC043335EDF12BAA45876349057FE5804F54526C704A44CF5ECA218496595F16410B779370EF6534F6D1471F823F91121E913D5B45A13C7105060C1DD687FB190B6230D3F337A8207B2C24334874E9187CF65F0089FCD3B511EDD639BA2269A0038FB26DD920B0AFE3D1F2FB7EA21B8E11607498E0EF4EF3A65FC74AE4D42C25F4AB8FFB2D415545E15F292B0519D7DBFB11FD0D3688B4FD0874FE6A6C06A60995C74CE552285A0C24270EA5DFB67F7DF5839482053229396086049A1821CF5897DF1BCA1DAB1A8804D5FB7C18166C3F44554B03E659A07A93A19A2AF29347041FDFF245EDAB2BF6BAAB61A6CFC7EAFC8B4332B52F3023D98BF85839F40F4F27BB7E8CB416228BBEDA98AD5D40ECF4958D4C1C6BBCFAA26636CE6437D43F87F6349C23615F1053414D1F2D8F9342372A0E712F09CC6B85F4CBDFA18BE30F2152E7FA90D336B599561E04AB380A693C78ABB2DD35CCD2389D32100621FDE9A77EDF76A4A631B2876595FE95D55635FCBD485222E33FFC52977894B70E1A436FBF3B08F613A139CC2BAE10788264871FDB3DE9715D91B3742AEC6844E6CB955820FC9365BFC94EAE741E9DEAB593D8331C1BA6BB3E28BC0B45C489F6270B8C87F33ADA264FCFF7928028552D81DA76C4FCB140529C28F79D28BB689578EF636A22CD5DA52D0EE2C160BEBCD608E715D3B23882379B02078B3B3F55A9300A9971DDE1D5BEC08F9EAB8FC154B37A7B56C2AB1A77C8914CB4155EBC32DC9BA5660A23919609FDDDE889951F4F894C3933FDB3BC74D08A2B19AE9F50377483BC7DB0AD0E09DEF6EE94BB2721DCB904B8B846917D7C6F0D9CABA1701804F297BFF11EFD94C7DB34E481EBFA250E3420B0FB77F88266DA49C667EB360035DD7F375FD075A1D534025C13A98779F73E3B11F65AF8746BCA8150517FD0CF18C645861DF2D3FEF2B05C492B802096162E388FC632631F4D3EF08C86A47AD1E638F694D2002022F77DEC4E2801F3E7A09A59E5D3152D88594005599839CF322B89B353986AA8876554BD93F5587106D426980F88CD37D7A40A2C7AF39BCF7F121C17FBFF48BA38F4280966F908B8E8E76987F11128C6E0B9A142C4911FDB1B0C443740F587216238F1DAD14F0C8422FD46CFCD6E858011D871EDF536FCD6C1813595C292B7D8ABF490F7F65961FF2662AEE0AE094C608B08356EC0D4064BF0AB35C9A1EF93D5165BA1EC50BFFDF3BF0992FE2B39A23BE2F6B2AE17788BE53D016951320A2A0476DD39CAC27689DCBDDB3C4DC08D5209BFAEAB6D5FBBFE2C667ADE3FAA504236880E2795CB807A8C5324A53BEC193A3D1BDC10C0F745180BB6AC1D0B2A95D43DF850007AE72B7E5B3FFE87A76ABDC1B937862D7005ABD77CFA35E0F11FFE9E6249FECFC67143F919DC56ECD59FD069D158966DE9FE97B6360FA838AB310B42902B00725622BAB132DEEE3019A499333658AA7B282B96174921254E5B97BBCC3B30AD67775A0DA3310C10FAD26DB1A29A3A1BC82F88947B44D57C3F1B4BAE4A2C1BEF64BB58D16AC2FCFB92770AA534EDB1E540D3C5E065B859B1D03317D3DACA74FB5712310DF48BCC4030319977CFE0297B603FD3524CB734AED3B2258CF21D16704E1843460AFB2B51D1A0BB1F67163F0B499139E5030F5A3F294B577D9739843D8F3522FFB97AFABAAD20F8D1C2D7611159CFAEB8CF5DFF3F6ECFBE6A5F0C0146608B6CEA8E1AABBC301BFC96457CA1797D685F6FF68EBD4B621DF6E8D4CA46C805DD77551DD202A1127ECBA78D47E10DA292FBA8FABBCBA4228891A5A5FB61870789D5E1873E36059B3E719D3CC9F2813E779957BBF04478A339C9BEB0A7B9251A5F5FBA133944AF7762C556FD9D6D73590120906FE88766D8B2A9D085B2BF049FFCE5CD487EA1A06C5 +smlen = 3771 +sm = 47A7B4569C011CD28AA6323546EAAA73F8EC50D52A54264EA06DEC143771E07754AF4CE9A1729878B488682A4B3372837810673DC37EF946D7E481F17690991DFA029B5691AC0B122B34BFF4A413222AAF2A39F7ED3666E6B07A5CF125C525E8D89318F4DDB9D29786DE4DD389933A757C227C02A2619B67D40A487AD041636CA1FEF56CAC63F9DB29DDDDE2EB1C99FEDA5045A8A4E83BA8EA7DEDCBBB855C273CB9E73CF63251C3F5E494F223948388813051797F49905DC9A46AEDCE99A54A3F96BF4C68540DD834AE1251CE08141EB526A63ACDA86856481300CF45475DE7E2643A951858B19599B1A63ED50D1D6CA0C6CAB5208A20450A9D32739042D56CED550E535C8F18656466314124C58F89FA42A4C3F1F635A3DFF15D41E323B30999272D90DD526B20DC922B701E68AD8A853910ED0E76C41915CBC5FA14A03C9AFECCBE68B57897B6F791D7D419EA1E93AA9B4B7F7F10E24B880A8C7707BC648EF5E336FF7B95497BD81F63AEAD7FB896CA87C073FA89CE32994609E8D8205AD94DEBF66B2C7EFCA599F71F4345DDB89CC4BFABE6990385E0FD70CC23BCAFED722A4D31E4A60283052D2439F69455E519308BE03E75FE99396F5375D303FEC962C2A007019CF55A3E2AB36AA05EA0FE24599DB053ADD35C0D2D45B36F0C22D7443FE26263722B89D90B590C0C28CEBFCFDD8231428B6FFD44BA4B7703C43C336D9544BC0B082EC7E4F516629EA64543D29F0DFB28C30B24267FABDA2066118F8C1ECFE8C487983C76C77CFF84867DAF396CFA886C26586D597B4EA3A5C006C129A78A96BB69FB3F2F549F2042F995775366CD36CF2926EA355F6A481C97E9FE0447FFD0E457CC6D10C16C929DCF75EB35CE7C5ED2F900271CAFCA1128122A3B860DA70200D5BAC5DFB212B236A04F1A94EA6A51E091C22ED5124D88A1E77ACCBB3968B5D3DE88DCB3062B6673A564835DCDE7B9F52E606A16F0B667A9817BC8B55A7A6147DF0A1833B4CB8A14D335438E13E292F616EE5078FD1127BD56EBAD36D79146E446964323CB2065D970C86660DBB8483C22BFB920E48BADD7CBA8D3FEBAFFB0D61CFBDA60A509060EBB5854D3562FB8CD805812F0B666394D94967899B411AB74719A286C82FBE56D81AA699383BFB1E752DF05D11B04154B94465FB31AF85D324DDCCE859693BEC71CE63424A2BE80A834C38B42D73E2823FD8AAB2174435328BC37CAA4FEBC7EDE02992ADBFEE50335E66A9CA6097D0DDCF9A56A9F9AC8DF5F1A62683279CC1A06B7D6A89B59BC40D59FA2C822086E0F985356D6ED42C3D1F857B75B91D16843104E300CD6D32A46F5E3B894EB786F9B4E2830459A9635392933C2B4EB7351089AD9F5D0E8B1C6352AA9E0E5F21832828D9A14FF1418A765F19A4FB902B2BBEE277B6C3F75D334FDC306A4F366928B60CFAB9862FD3F52985825535EC18CAB5F9A60E7DEBB51C3191715257024F56A7843A1BFAF1DED668923E43288FE6140491A77DDAC979FB4C27119FB8EBBA57C1CF86272207AB8CB3751A4CDF412B98E60FD90F2111181539104FAF485C240C58D887B90C6578A27A1C5AB21721D893DE84918FD8B5B5941FB50AC18760F081DA786B1FB4BC0EB61773F4E1AAE831CF70D67EF5D9D435229FE87355B3F6158A864502EEA3A08E122039C5BCEE696A09DB7389EAF3DD0819442F0F19F8DB3E246BB28C354A087EAC558BF41AC296D642C6CFC9B8207E92EA7788D590CDD78BC6FA2EA2C3B21FF6D63491798E2133FD72444374E6E778512960B94D501F20854729F9E3431845EABCC8701F41AFDEB255E645F931C7B23CA916162CA93580B80CE35AD348549102FCF87313A18802DC16DA1CB0249CCC54A3376D959B3FCBAF35B75419E5751DCE0BD8A3DA836108BE19BF3044DFFCD7AFA18DAAF414D26A03D4B06D14A210B464BA3CC7A95E8B62B5185BFBEA0C8FA8F384ECBFC208769619DC1242B2555642F2C95C8AA49E5599E469C63F7B5DB624C9F0A0EE880E5027F1FB2EBE044959676C9C734F7E7C12022D226EEC1BD39C056ABF4AF271D136C83A4BA12722AFE6CE04D683583F6BC94BE132EDA8A2F663C2F6D85846D1C1A3BA71EA6E584B79651794120B60A32380B3AAFD450DE71E754A484266568774D4B54D7AB91468785535DE63D19E05E6B70DEED4837A5EF83585343A55ED1AC4B2F0796DEC6FF5FAAECFB5B082A1E7CE23D0CD40D40AEC9066A96B29DEE0AC6359AC4E852F6031985FC071AA6EB0E77E553F41F4235F3AE44EBB968799E282EE311869D52EF90C5FC98D1838C55CBA5A0D5C6CE631EDAE334CB18807BE1030A9C74288600EC3E74609C832813D0643B151E1CC4498608EE062F5B2CFAD8FFC8BED60C37187DF43C88B2C45CC5D9CE91EE1426828FEB0C969F86DBBA8D848B318245FD87B7EEF6689AA58B765B297F6809E71DE4239AEF0F6B0B86479BDF3EB25F2C78EFDFDEA4E6336D0CD41647D8168AD6EB7762C97DCBF3A51E60E73EF2914F561471228828A6D952FE32195F3711CE661162C8439D989B858BAE2752CB8A03B3B82A758F5104E80184B2D64326D800378B5E753BE3324BCB26A7427DA74B388D8976636C66E7F87DAA726AAA9B87E88A82E256D99A3F291CF8A321789CCACA4EE0AC96DB31964672E71FB6CF2F72F7A37635F72DBCF578FDCEEC2019BA09A4E97A50E3FDC9B8D30E2EBB61F86B7FBDEFC16948767AF4321EF4DABA35397F7868EFCFE67CF41D05229847B4BE56677FBD538D5D66C7C8E7F5D7A9B1D90A4470B70341A5B07A4E8A7A341E60589FE17D4E2DF5AEB998EC6BCBA648A455DB16F013F3984A4C6D61B76A9AF74542747A7AF25097DCD7DB8E535ACB2120331F9A22844AB5F7601E264F564D6B8395D291912A09052E8C009F21FC9E14AC12AD274FB72BCFB41A42883CB5C1762FDE1A5ECF626FFD53A31AC67E0412443229BC611DF79B7C2B9FDE4BA0E54366B484D6E32CDA8B5CC5681EF912736E9DA5EC7377F4FE7DA96C63E63A4A98EA73E1691FC9F7AEF863F20425E57E87BBCB437BE370DB6C629373F195CDE6B474754297A5F6CF10BED840D3567F4E742D94610AE7619A6ADE50708BB55C175DEA99EBF4F6EFBF2083E5E8A7D51B9F696D7F3471208097F6FD38D0D1434CF5772DFD12B0B5CF747C7258D41CA2A393A3618C573ECD5FB1B0C75A24341FFADBFF6D3EB82B47AF659689472AE603A542ABE0AE0AD7C31C25DF2A6230B3EAF2994EED3880F848E34114FAE6D53E3E819C249384A654E029DDAA872A139F7D3C52B8DB1461822CE8F0443F30CC559015EF956EAF0A54FB9F57DB08E0BF6959B6CE639F031735132F0BCABF270CC82D93324B720A557A1BFEB50C5B03D472E62C511547B4EEDD76E39DAD259B0D8B9E77EEC83D8D1197E2F0CEC56F60C50D1AC8D5B7AE2B93A834F4439A48D79F98BF45EEBACCC0196350AA0C69BF72EAB6CF673D0AE5969D6A90E0223DC69B92D33A98826ADDFCFE24A2691FF40EB33A07C733BB426DE0C0F56B1A0ECDA5ED76BC2F9E2B40E52EA83E5D60627CC6C843918F4FB9BE0B8F81C5CF84D7A2481B71862C8573ED0202CFD60AF71F1D4E92CCAD2E9613C49E0CF7D203575F1C6E8B1934C7AAC5FC9F6DDE7DC57EDC812865554752E74C720680632045A0A4FC27E7A207D23FDDC125F267770A08DE08B3A5F705B6FD0F3A3C6240F829307E8D8B4E017C85A987059C9501F8267DDF36F737B8F8DA2DFB2C095102FDCD8DF5C73B9214C3E58A578C47EBB91D1F19F20D409F7B5960BA43C70C17B24674C147714FC4B0D37E2C03DCD68FDDDAAFF7B737AC6818C14EF9C9AF8CB3C6FF0856585A3FC2CB4AA3B6D6FAE34387346C0F5C3F339E270F90DF7C1CDA4103257B574C1E0BA24AF2E0C2496C38B13BDA7B0E3E7291BD0DD6F3A649CAF10B953D7D3087DD1387C5D1C04C8713DA3C0512340F0C10CC9E7C5986AD64276A3D5BDED97B63CB8BE14465CAC2AB797BD4FD6F355621D28A4A338A2DBFAA52536DD297C8302A827FCA932C2A579DDB8F660CA6420BC61E61A20763274700297EB00F3D411E220823809A90ACEBA6F0B854264BE4117C499E4A83B563FA2F8216AD385F96A86B2BF023C5446888AF3CD5D03EB1D2FB13E61363F876FA1931841BDB9CA188E5AEF3B177EB4DD733E79777BE12B9F83333B6E57965B42534CC11AEA3F18FAB3864AFB2B58879D897125CEF695183346A165A38C99C958B2D03D9034498265969545C4B387D80AE35A53110CCB43F756910D6C4AC5CF90B51C1795B432D65FEA1B77525A6C04ABA0F18B12BF524BE2FCACFC706946697F9CD54630FF1842075E06CDE4CB3E89D9A546FD685F525E37E542E2BA85155985D3F8EE07AC9DF23417343319AC1AB5DDD775402CAB1975A151300FCDC53E3B92E8B534684B8EA039077806FE55B025D43C31F5EB3F3C819345734D0260008BE79EF18B3C7F21EB83DDCDE0D4E004444DE3BC6FED45E817E45152C95EBBD0A1B8F4B50562026C273F12611AA44C274B669C24769822F231862E35DB3C2F6AD26517B66837AD29C6A57519DEF0F2A63790951D7EB294DC7D5F5FF1E394A6D75EAED165A93A5B1B81B485D73A9B3FD309BD2EB0000000000000000000000000000000000000000000000000000050C1212191D439529DF1864297E33956AFEE00A60099B658A67830A6A6ABDDC329E87831D9F9B647917FEDF1AE182A40402143285516FCAB83F447354C72FAE81AC26E7005C2AA561763C152E66BD80F14565F47DEFA440DBB491E7994AB9FE35995D5FBB3800CA030B43DF611141637A5246AB9D9CAC02EFE14AF60736B6BDB2BABB97CF21E831E5D04D41C00F090B154977900EFADD3A9313389A3F84CB3AC38E8B57B70A43DD08A8243F8154013FD5CF29DE5A8DF0B197C12B17E0610FCFE3625CC94067E01E23D23A243AD1C1F805CC50E1447D1DF93C25B8D76396BB7199E64129522462C5FC8B30C132D4EE9E0BF6F52961FCE7ECF650647E7064AA5A6574649A323E144D7C5491DE4C0A1A76D08F93F87A2FC7F6955FEF86991E62E2CB42908E83B0C0A8BC180B7453CED293F1E20F300431EC1D395E8A537F0BC36A673D491F14381DEA90D8F176D06031B0A7AFB40EA8F76D37FA82E2572B9799A5FC7CF4C49BC20AD78EFA8CD989A84D72ED680AC3C0F64155C56ACBFD7C7D628B418A489F961357F77BD62204ADB079DD3106485A37FEE535C9CF82E832D8AADCBF686976B806B02AE733DB46DB0BF162E973931C3E338CC86DB38C66262D1B2EBC7691B8281E0B20BF36305FBA996D20ECFDC695 + +count = 14 +seed = 0A98A2BD2B9FF42CFC18D3396BAD052E1D0F3372854DA69A318B142F7A1AAC609C3861263BD8FB0549DA7266784DB8B4 +mlen = 495 +msg = 8CB18850E27D8416B88A9A71F4A66BDF447814DB6C82098C371B53F61600EF5DFD88E4FB34200207C3F6F55166AF4878D38FCA7E2DC18FE662E3EA491B58A86246CAE16090FB7ADA53B9A67B3D0E3787D3323EA921274C60CFFB19A889BCF0300FE10E242AAE025F374DD83FBE9D007C8B9D9D75574C74146331DDEC6F0E49C10DBAF15654897E33E2B4780DBA484224AA6FAC79015D5792FAA2D532BB7D239B11D91420B98690B1FBDE9632223927E0804BFB284368A426C414C3DB8EA82F0D246413861475ED2DCA9E80FB4F3C34FEF7528069AE1975AFC52AC5AD2CDBCA1459E140F655556093210D7905A1A1E6CEEAEF0194A0B2EAB2C1EE853484E715D2A1DB551FDC620D5331164C74CA4848B61D408D2F2A943FA09EFEB63D524691C99DCC0B22CC61B98E6FB8039E5E0B2D7DE2CAAA900A44184BD56C9F02141A3AE8AFC661E3E898ECD3004FDB0704272BA780CD5DE35153B6FE223843024273642DCF8E4B58BE2AB1F61668680084AA0B75A32E766C8AE5EB30D4E02A12E6798DEA40F80D8DDFAD2041A52922701C689F46F49F84CFC05ECA6D7D4C356D50B6A0BA61966245D45134D6A1F5197540A1C39C36BB0B78831AF3F5156E669FD9213B64E0CF1C5A31E88AE79AD61757EC67B551B9F0A760F646BF81F6B92403A62840CC29FA4F3949B3A9F0A9A4286EE7808A +pk = 9D8C102A863B46476B536027234D5A7FC36E02CCCC098543974B4BBA8EFE6E335442BACCF3C758C861AE898AC2A46D3448C7158E193638D33EE1DE209870DA8340635C4742DBD1A87DEB09758317BFAD5A43449050452F2125D7213F8D89B6B2610F0EF3520248445AAECD2D9E4151EC39F62ADC11017BEF326DB1BAAEB8F986E3EBA6B2FCD272E4E40160A6402A11DC126FC6EA91693C1DCEC285F760E2636C79B054898228BAFAF9A6EB99C6F26C24E1DEC1114261BB21023EC8710EAAFFC19D35E4768D7B16926F06D13D4E60594E8010982950928FDB96A584B1F0A5BDD7F0D0378595959266963D4ED1E37B8BB1D3D2A254CC4F655A3EBFBCE0ACCE8B9CFA50CF558EA2E733772F888AEF9E80A6FF10D69E791CEF17BAF2DE7D93C0AE6602AC66E611C40C9A39FCBD027BBBAC0A7E450602AD7A661357AFDD9A9D49B4B769C0A6DC034F228E72F3CE6B360830AC00427524FD80A0645C3AF1CCDAC6C03E3C1AC029770211A4F151F97042D4F1E5E078F6ED4757A49DE9B09E8F1C4B106F6D938EB8C66B6F0F45018A35AB7C30E2D36F9FCEA95567746A6D1DE1FCD33A7EA5B641612A117EEF47AF58EB5E11B70B8CF02BF7EB2C40D885AD35842A51C49301474DA7D7ECB64FAE4CEF833AB95D77E02951C97E59278D95F4F5C47208EC0430FB1E89F7436F8CB8F9D5BC5D4F47EB9D07135991F9AE679347F2B7F593914379D78F3BC7FA000C286577B9520616D75B66311DDBED3A07EACFBF5A71F312014EB137DE06E58ED6B9164250179CC515407A7A6FED15CE87CC5669362C0E4F111C33AB2EBDABBF88757D8FA711CCAD6AF4A0B213F2254B8786FD26EAEAA8AF1F8A4D8A1EE5A13CBEDAA98149F63B773CC1425167018EE4186756290A8EEC1F357C93A96463BF5994CA9F685B28E969BBB1CB5CB622FAC8927AD45763D48F6516FA43A62D04E7231AA07A0A35A0F35BB98C2FF446A0CC272293A2F8A8C6072A8B2C287320B4E8E26BDAE189CCAE91149EEFA1F8BDC083D50021EA435CB5CCFA64A07E8A813EB3AB71DE6D0657D20E229B9702193FCEEA0E98C461D1E31E9752B53BBE66B66531D427331C851588A64E9CD6E56A25C317B73DD56E7CA380C27FACCABEE31E09BD075D7F41D6E2DDDC8DAA9B664AD7DE60D075F455F25061595718140ED333ADE4A478DA9678B9789E88F0B477F62C1BCA4E4428AAB19A46D74A6E1547394BC68185A852744E066FAD31861FEC2493DAFD3A9B8831FFA8AB95A675BB4F6338847BA80784E3DA210DADF4FC26E7D3CFA03B627D0AAB77E7C01C52FC58DCE8D2B9822C5B3D8F03D563F4904465801D47B37507BD3574CDD909E6D9916B5B279B88DF4EFC467F31E82A5081395F66B901D098F5E4D4973543BE2A0DE9AD7C55A18B648A7D7360E3B99E7A3715CA20D32AF84073A6B03F662D3D1B9B69A64E7CDB3E52CD4F058892A5AED04F3421EA407116FD0FC683244108E8BF5818B69C97E1222CF74E976ABFAD129DEFE8F2B2B296158EEA5057CD5E43CF37E756E68CC1346242E41F406B60A2AF5ECD185F3D54A5E1E58381EBAFB7E07AEF040C746B736C9F7A6162F8218E7BC8CFA5258E43C3F7049327DC436746ED378C38E0501326F473422C950AF0696D53F8C751CAFF2F24BB87437127C7888E5E884C082775B2301AD4C45A1DA676ED6A3CF67E25A19FBDA2A49C29834BBA20020666C2760FD03622AADF21D86D1229822A18EFD3552CC90F294A2CB6ED6FB150376D80B1669A6FD8D13E0AED8CF6B307D4F234D119061FE2C6EED06BF04C7F3270FB636F2631EF84EC40B8E698AF5E955B86C3429A40A401CAE4C6F03EBAB58870112062D13F05E1296C7DB7BE39FF6A7ED0B5EA561D6E17A870344442B52ED7F14FC7C1C53754D060F182EE303F8C7D44FC5D7BEA289A6B84B122EF590DCA26375F045D8C2CE750EB1CBA1DB73381DE630443BE20EF83EEE09DA34A67216D06263A9DA290D825F8CD28541CBC50D9D3B5E40C4C12DA974EABA10B50C89285D5C4346EDC992D150A0C7ECA32A716E6CFFA49E26A7F397E544B4D4DEBA43EC4656A7C66432AE233FB3B1F2AB1980501343EE175869FE3ED5A6FC99B7E9C466CFF4D5FDD53EA22CDC9A4038100AE9C8D7C19706FECDF997FF193019455CD4DF4B3C1F464DC744C7801F75F661335DBC2E58685A3DF46224346674055142A73A45F02E6A91FF4FC2B5303CC26D4FE5AC5E9C191212CFE8714B187A9DE0DFF7C2D11090C1210C172CB4FF3D84005EC32C9D38717D18C4AAE0435B6AA65FBBD2178E9BE6E8C196A563CA93964D479A2296282085B7B15DE4EB7EB481F629B0D2275F63E61016F60374E62580FA3B01EC67B3C4F1E36D3CBBB825DD798541CA174D7D58060C5314C3538079771951E3F6FF36DB9EE7F50DBF8F357EFBAB77A2DBE7E88BE4709C3034A40364D3D86D2C63D00E9E3B6E97A78CCAA70ADDCB05AE4CC59F2CA1E2FB482888F19EF8DD867BDC5EF3E6E2F9451CB486CF32929A13BE33A6DE8F1573ED714573E037434407B631965945E62F618FD249E15BE83BE72E6DFD40ABC973C5A1D83603256162FC9E8B81D5E6CC603B0DAA35FA3700E717E690625E95F07AAF850DF2EACFF3D7F67C2FF1707FA4015CB385C90CAFD54EF1A5E1CB1B728B6DDFAD48FABB66866880033CB85C491F518841A41C7C3F171D138184CDC370A3A0EDC659BF20348E16D4B21B9269B4355DAF583EACD94E5C6E39B601BB60F77AD56 +sk = 9D8C102A863B46476B536027234D5A7FC36E02CCCC098543974B4BBA8EFE6E33FCB82AD2F2D003D801687F31BA9CADD6465FAC6765795902F7E1D1F39AA4FC8EAEC8AFACEBDA8325E4CAC5CBB35EB85F7DB741C242E24744D355C048C907D24454BD8CCD5C2C9262EF29186CFA3E3ABF6BF42DB390B92AB93FFB9123A8F29C9D888746830874461304510015723537740370483686047028827755458158744156401436400642143884410668821158315551387142720160881051560084423888742480801133353847503675128365270201214201852630386476570510358238353185540746288166400853127726244835733770578752153500623217347612501463031447338564364418740807186616373756881365861306780226251208278735468007741400328130011640236302875462161008833571646638684086633270616638103211134106216370537401386683402380726115714285834461683155660227107246100432231088537557122658233663780828137303041248510848256252723065717602740328667673742366806824746161763018778127147356381201253555084838800676037115744521011172814037038365687388112706554827870174245814317373644081643078604161042458765640331746786863551602434765245474464483042778020431675325077415188848527148745332874030302258477247575375274128061446266568857443408800457654131053078624575252178733716341843675823334016535443748878442530516767868774323164863466834223436645523561106588617818311552235402856827647186645121381377520458768738345367176302361808276145540142404672262714050331812216466872065461634531506584032510812346784577784224568752701772742433355360651045404321477733134151578008040880413068021667153646608312118602253854535850282028315144665480178712177185766557058042828551015182837428381738051816217663702452468744265412715465153286855467747550534713424622714784668463031543171261555470367560386485765180230738103018762653345355670647052753755525820660080704473547548852454103626035673135002721244340870465780370815527726674611836502470055465882353266405783150464764038424025683262656082156410748836433143504876842033760057115785437037118436662578525882772643344688346727060662888680567323613614332543652644084266227165332214075454546308083177512243336107656650230352820703570860835570525204361424556306518073681505122030208674324882285281135841247387483756557207618402255182225564282750273153833423758175710717536132752707163370205415486662545274324600264242856015455287461461664485801066560887701146844270125453185535082160886057385081575677851220430763235167004087101881787543314361168705708070364487121440426724140565702525518353083524360206842016045733422168232225723802405657485447003247033128863828538283461752444462027667750418024358553702305715411451221181201872838004303024765272016330481025086051700524430147540475558838265281883825308851871687047188772037805533080756247172405511006804724121275021383181588305858777826737880343506748776508208328350165475463008337483264063817227700046508112787346254408325222815568412260528067657475580435127222257258503275042377150350515158005011624263081450132727721430162005610133218538856671116120032136288738284380138811640857372231860131274034763718528441217268073047837708281267228381622165771418755315238087061620838562473738421738515418881453738703536502147121617AE836096BF695CD7ABC31ABCE6792C6BF24599B7309FC83E87F58861BB252ECFBA2A6F0389CC36540CBB84EBCCB2DB7EBB67359F70FDF3EAD7741C8C4C0114AE5E22FF7EB0E0C9DB1AF734CD8C519CDD52BF64F7EBB7064648B3A7A294644180D63F1425735B8202C35D78AFEDA1BECA06D872ED14945A06E0FDA9B12F29940D64696F05D7585DF12199C7341D5847E3C2A689B4F5180FD520E1961837B5E675735329EA7E461011911064FE582501CD001A84490B315CF03FDB8CD9D9CFACAC62B92B0DC2975F2F4260170E6EB16A51D882D5AEA3294478C95887E23C71A6314C2AE94970DCBFD89124F501C1B4CFDD0E4F7F14530D4953ACD9057F10EDA64E471CC5210A2F6A4355F02B5ED2F9176BA35CC9732FFF2F244C182FCFB5F548115BCBBBBDB1556E5FA1DA7FAF14B65BBD2DB1897F3C76AE5A3710DFA7580C7FE061CCE8FD7E790D20902DDF825711B4ED4C7830FD6CFC5526A3E5328249BF0735986EBAF6037644888887298BB2D2AFA70021652B5534AA31A64E7F1F998BAE97C1D73ACB8B43820FD10AD5F8C63A41310D46884522704EC191E703DEB203D03B812D6AFCD20863FA14BD2721D709D0273BFFDABFDE55AC13BB35E60734E12888A1C93C4E9A3C2DCF7554CBE95241BD215094B1E685A75102173F3C690C48E31B58CF365BF98F710E7784DD8DF7587A74F43AAF9628A884EBCC7B1035696283C540C8EF7836B9D8A15279669A52F1BA048CF3C1452F6310A5CFB91C5DB4F103A325A2961169FB6731F67817B92DE846314D04A0A922E4A171450C7100024D58D1F311EC366203C9F2FAC2A4EDDF9569776CAF6DBD8E1BB52506CE00F5F96B974C37ABDB03C7B5855B2888D73D85A3875C1B26AD3E3972F415C5988D1E205797D3F958F35BA5F2CF27D320EFCDE9A5D832A0BFB709DBC78AE6C4A578D10783C33F56C280601FEB75C57BCE26F0EE91A9DA4D9F144B324E99186E96BEFC08AA55AE984A28FAFDF90860B7FBAD54C8FAFCFCDFF61E9B0E5C77D333806D25E33F1FD74513EE9C6975F3A9E882C86020890AC0D2CB607E956C2D7F7B12EC906B6BF645A3F85E9698373B2391401B2F14C363A4ADB19B2A176359F93A28B2A849F1D9901E532AC605794F48D751C5AA234FEFDADE6C7AB7AB7D6F9D402C1F859C9D95D1D9E0809A2A058DB96CEA4019415C244A732C3C41971B11557DC06E85AE01CAAFF1C406E9664DFF586BCA45401CB2F7CDDC0DA3F498842164EAEF53AA54DA1B2DF92802FAE5579F90FC8FAE142453F378BD2EB4C38EFF151973D2C1AF4AEB58FD9FD73D392F4B3801B6131A9F910846896C258744AAD34FA746AEAB28EC5E73272E4A5A3508264EDD25D357E7FAD820F9772128F8A93D12C4C8A4C3E997976221BF9152571F41F7B4BA6D696C42FFAABC7689EB6FB1772857DE6EC7EAF415B972FBA09423DC206304BB3ED49FAE9C89E4EDB48A420375C2039220FD37F1BF1295319E4029BB84DEB4ACBEBFD91301D836958BBFF1095CDA7B644C26E138005C077F5E0FEEF826425C6C90CD26BC1EDED7364A009B510C94E195988A475AF0C00CF3719203F5D80B838371BB25BFE8E1058D311C5429C69C6EFE9399E5D4B365210230A1C3AA9664715F054857F66FAE69550C216A83CDD323442123318CFD7762A5EF73FAA49F0F5FA58EED90B895CED4790544DB925B02BB0C696E674EB1427226D2654C3DDA0CD22B1DD7866F548D4FF1D4058DDFBEA702D8FE51FBF4982225884323F0696A05643B01CC9372125ABA42B8DB966589C834634CD46281912DDB7F8AFE8686E92A4B466992EDF7ADE319F45563C6AF1973DF7FAA6DEF8F6F01B6B0FA06D78B5202D9B570F053813C82D98FE872C315E1E0C417CB6D1DCAE39B18B04A529AD39300D369E0F236A2E757C522A9C680E4560E60423EA21EA404DB61970B71BC88154D20B2A116DE91A45E7C95CFD2CFCEAABAFA0C907D296A7A8AF3438B0AF258A4A561911C55AAFD9EA18FCDC359CB9A72F603FF15E7F752125A89BE2ECB6CA063630C44F586B0823D16369F06ADC40A9390FDB7FEFD998ABA9F68E9388C38F0C9D539FB1C48B3915CCD603275F5A56922C6D46D4A787E0D0493733E5F5EBBADD006C8AEA388FC9509627CF9B7EEC9AEEACF50F89C98C85CF0663183CCBE380C9B5C3A360D898D2E631188CB4F2904AD45A19CD943E647B14DF36E32E5DAA39F50E050B838F6FB5D1212292E84FDF6705179D07411DC557EFF29F01F0247F67D90DF0C0FE2A3FD8D51E413BB568908659E7469D76A17AFCEDA1BA91DB8AC54236D749906D4926B13534C88EC6F649AD44A728E1C34BF9FB74FEAA78E7616F246836825873979C9C9926874AB022D8AA52748AD0A063CC02954C322BE2189138BFC8B80C51CA55B264815B1F8D7613D877B587394B9D2FB27A50EAF492105591837B4C2B7A3E28C4C17C6968860A27A5C2822CBB01365F6C696C0FD576114E8B66E22DFE6D780B5A578A2273F5DA516DA76E89C5E5E978AF914DEE501F42946940A936706D56AE2BDCB59CDAA5F6E843E0FB9B1DA7B6605011085F74EC556FCCD22293A385D8352616BF902CFCC6091A7514E6BC05E4E808949105736FE8368EA85C65B87D6DF5F899FB63EF71BBEC51FAB034E178761804410740EB3C1A6BF6E38F7FD4F5C23F28AFB2B949EC37040ED9410E32738BF0EFB10805B808DB4D75FAB7A0F71BDE90E9A73245CEE2EB85D2CC3E006FA23257B8A9F876AD46C63B4DEBB46739824E6E5E34644A626E7571C0CF4BA62533032251DDF5CAA83B1DB2E2A476907BAE24B5977F7B6F473D6F49D5B8C1DF2F5026DF9D4B74207D4C7C8B96FE7E405FE9A1CA3E801D1B3D15DAB1ADEF23CCE8373F85333ADDC4102671A56A96E6634EED82040D0251F5A5D0C72C6265BC348BAAF74A5A210D3601B3090F0D2ED2C7C31A76841BB0A555BFAF36EAA0DF985B17E55A78A216EB31CE6BC51CB3F5FABF8759AC111447454E05CEA0138762DF26F2BB1281E30B95A8643549BE537ECC01FC59DBA6FB7E329D016F882E2E789D579956DE470D5F6ABA9F8C05F28CB6FC7BFB17F04607312C289325589C890FF41CE5A19784E01827483671F59A1700CC3CCCA4EB08107BB64A06234D8AF2558FBF3057A29F27C8C05493B95D78D32A21B8AB6BDB9EDEE27986C7098EAC93F724988F897AB57FABE40C7CCCE4448983BB9E810528425B50E09FD5E8FDAD3B471585D533BF31E44A246457E276A5727EE9E83781E76190E4BAF6DB7CF7ABF6E6FDF4C8FDD57520194F43254AC841B3DD434F33C2125722DAA72ED467BE8EC8FF0483A075A74CCA99278E21CDD92C1502DBB6D145A569FCF71D6CC12B49A50ED0EBFCBDAED433511D4AA9B9730B0B65A9DC8AC4CC6D7821A8027E312C8C909C944E9976A8354BD840DFCB3C0E67C9BD46AA66D8D59DC62A2DF042D1112D8CCE9BD04E7A926CE56BA8BE22AB1601D8E58233603712DFCB96542BE09F5E196DD3775B699E6AD64426EA4 +smlen = 3804 +sm = 5191B0702C0972F391FD4EFDFB88F1B0ADE4A6CCACD51841908A2392733B360A2F761B912B4CB031029F569CD6983C64ADB50CEA45DA4B1B48E97EF0DF701B02B0C5D921D17E53FE46CE1C9CE0DDCAF53186C760BD259189D98D1C82F0EFF658D8AD7DB662A89BAFA8688002AA68469108414F6474C32C16886AE68190F3FC590A59DF6B7C186B6766DBC832DF984ACB7BFB950A1DD53521206008C162B435A6EBAE640B3237AE8139E369D02D8DDFF335EF3DC8FD641954CE5A88A08989E5F53C69F33CA2380B91AF1D6DAC3C4F03BBC0650CB828E47A653407AF229236FB93E7B1C04038933CE6A3CC324B12F16E6A98752BC54BE8BBCC840C84B870957D83AE6470E7F046782D572FE979FF13051460E2BB67A9B8A5252FE2A5712C910AB56D3447FEC6AD852C6349685D0766FB1E48BDA2CD4C550D1B5D3507A8329ED0E0967AED85E2ACE6915131BB632320CE05884DA0E8EC800828A8A9EC7400909DCF4B9B54A04DFF95F5F6D9B53D632207735D9DF5256526D6CC190AE98C869BB060FEC2B9170B05D1E3E93FE5698463BF183E7B91239AB1DB7F80A904F7A14DA1F36AE2F10B171C869F783689F2CEF545E1F3EDB33DCD24559A8D5A39D7365EDE06B74AA0462B48614B4B61B3418191BC23BCE3CBE5AF5E28BEAADD8DCE1B7A331499A94526A71FA1DD0D18D4020FD386D2BA6CD3D05FF1B103DAF077DDB424AAC77200FBC4DFF292D22CB653EE3F98F223C66FE604D757150A9558786F8E940F0930F5565614B90F317D1263B70C35ECC0697476807F0A949E892E4F274F13E96BD7EA1DB1545303E198C9FA525F6F4987A8CAAE4CFE6217610D8612CEA5081200975DA53534D69EAB1F0E39036D64D7AE94B4D4A1F207F09D8A6A66126B36F0D7F6125826CD086FE964DBE5C956BBBA3DFAD20EDE818EDF8F6457117C9262FA6D5722267ED0AE60E32C4B11F94F9DDCB1EE900F32A58919848004F73A0128C37D7CA560AA7E4589108F43C2397F1C941CA2DB513DEC35F7D795DC32B430FA0D7E575DD1A190C970D7CBAADFEBDDCE43135EC0B4A98B6732DFADA9034978F25A6B77BB8DB93B3F82A939C10F08127C17202BF55C22EA4846463B6237E24033F1470A432E8BFA919B5669F2716174072C9B1F7D8C1BA90693308FC2F4B5E08F48186AED7D3E0AD82774FC25C19826EC34C676645B3CCBDC2C5F35D8A9DFBB0630FCA0CAB05AAFC510AE4DB4D0ED40C20D4EF4231EF7FCF5450FB7C3FEBADAD12CD4CA70B1C4E599F0D9C0B7C9FABD7A21F42DED2D3896E1C95020FB5AE0C1464F5A12D6598AC15B6AF6F6C35B3C177DFE126E007429E1E37BF72B985F9834E9EAE00FE6570242FA254D66D01CF6AB06A14DFAD256AF057FB144BA7A8811742D56F8EF99BB99B5B2EE456B340C7DD58B9DFB21BDDDC1E9CDEEF925341DF95F9A838324707AD1C7E0826957FCB0E59878114F0257708718AAFE2F65B2328585BA934C7BC5FD8100ECAC07BAC47CB1630ABB5C29FD4D6DB2D44E70E662F3EA06A53EC64559E7CC5A99F51B1DC9120FD9F6BBF7D12C54E63DECEB08865E560A310E8BC7D9606F077EA392580910354B7F4E61B3D4B03540BF9A95487D4788EB6E14EBBCC46DCAC69E5FE44384ACC178AA627DD43CE7398100D247F8763EDBD6935ECB2F2D4BB03914F5CE3C06023C7013CB14FDED0CF217E07C147B789F36E118B5E7CA4FE3C2119902C40C80E772782A2EA6E5D4BA1424D9D083414812CD7A7668A8D94BD91C7D341549BAD282008776E2BC4D00186BE9C2502D64A803EC45B34C00CBE2DDAFFBF62AA4EF0306B4BD9DA9F7F538C93E562CD136FB982DE9A38902536A803185860C2EEFC3B84948B9A435E18306D966ED5FAAE5866573C5C73FA87EC991EB2149557340CB8F26223472458F9A226EE53AD2E1270F8FC777E1DF7CBE6D88638211DB3F5072F29F987DCD5C9FB0EE3A4F49809890F140311904AFC2546F38CEF3911E4DB78B06FF5F36D10BAD1C65C2E26884106A34C7772BD707CFC98A0164CA0CDD7126C6010166002BE344DEB69E1E6B6120188575BA24AE4A3A57DABF6ABB36B40A0B3BFCD4A54CEECE46F38D60B34600E3BB5F41C96EE8E2EAB63CC8DE65DB8842E0ED3F74CEA7B2C5A0D6D765528410CF158A85399056118184F6767F0E270598C9139AC99420C44584A61A852C6B61AC6B032718AA050002F5694E0843FBE24CA93EFE1EEB30ACB2AE2D9AAA1D92E7AB53B6BA913712B7A56E47F24E827468A14EF5107416C8ABC4163D8BAB5F212FAF9C842BEED8DD69352EB516BFE4227AC528CFFA6661432A84EEA87B3BF75A489F8E505AB51BDC12870545CBF8A8B2D1DAB3A1CED3D3CF75698105BFE99C1F7F2931314C7111F932039B6884E94D57EC8B8A30C296851CDEB6FD98F00AAF8FAA600EFFB3B0141CD76E6FF800BEF65CA901F00612EF605DB36F4B035A059973B33B943B4B3E6E947ACBBA84E39D21CF4E6CDCC630BFA0B0DCDA5B3143C8C7168304896B65DE9C7FA69AEBB5366C9394A5E7D07AD1A302A5DDB68FD71F90AA4B8C771B3F06445F54ECF6335CCF60BABE313B734FA75082A81BEE7A1258348AD0683899C79E76996338E98291DD0A6184DC8DFE575AAC35F8EDAE5CFED31C213D8C1A6474461B0FEA7DC689557F68EFF3DB51954FBA6C1BD67318C1F7375CB6E38CDA05EA344791FF6C8364E478633CA8F3523777166319A7F1A3E3610F3FCBD1D2E0A708ED4399B80C7ABF044FEEE6AF2BC5719F3E79670AABB1EBC5A2293D694A54B2357B4BCBB434BEDD516D32ED2DE2641418F05BF1444F1B23B344F5B96A8D75CFE5910AD69141186D462A49A7764036A96B78D4CAF46E803D944002816AF93ACF426233BE350A280F26A6A4DF90FE93C95108A38F28E5338AF8A05DDC800D7734E34A6223E912AFF5192B6BE1F92295DDEC3702EFDADBE1C53ABDBE2CFD6C8C910CF1B57CE41C763B93D5C4956465901FE4FF7761452B27CCFE5403438750663139A8224F6BD6519F610AB7EA8C16D4D3CB4345F87CC941C919A3ADEA800B6B31B2F7801EC1438C7AA423F541ABBB3B69C2B061A96A52DD2B9C73DF82DF461F85C286E8D8FE2900217A46EFC56782F91C94AED6FE25A9535EFECAE281F249D885EFFD3743C6A4373DF08D4FD411859A27074C10C608ECE6E8BB8898360AECC14D45CCEF2FDCB7371DD7AC1A717CFF492A1FA7DBA5A1E789AC74625373BB2EC8947AF085A358BA0748649AEBF7489CA30D51DA15983A2ACF85F7D20F9D62552F57A720038BCAC0486587BF1C2A28D2D014FC2799D063D72EBA7374F7796B38A5C4E0009A23300E6C133341C95C158C8DDF3D32BDBE72644C16B82014FBEA736050FD837D9C0BE450989F9D362CBA3A845573CC8374749649FBCEC2C823DAD5E0CB62A42298721CA244DC1266959DCB9449498957276A473DAE85E78CC1E451C0AF0E812967B7FDD3FB237364DE4928F2FBD0D4D2A1205F5A31802BABAF676F1B98DBD31BF24FC4A2044B6CFF1CF14DED03875E0184378021111C1C253478A1FB0FAB485AF34857CDF1454DC845DF214AC098310FAFF345EF906D547033A9A3AFE7D3CC0D09C1ECB7BF1F6C5FDD7A3D0305496534D883D5D4C8A3CE491BE1FC2761E9E5A97B0AAB059DE9720035D11A01F5F72C76418E7D5702F0E18FC3A9786DE3D38F2B70B6CAD8AECD39C27064C6CAF0D63AF3D597A4D605DDA60F68DB44A7D1C288DE6D117728976E5AF199CCA70CACD471B9C7D1295ECA22C5E142241ADB1AE3219638F3F2B6FE168EAA79EA6A8A9AFA4DC46F4106C80389D751F891F4BCC47D33EC2A4EA4642F38AAEA68DB4B3E9B5B6E5E177577BD3B2418FE54DB2F47FA66F1F27A10FA5A8AE1CFD0D9748E9D2CB2BDB5570AB3E6619B2D1EC9C10205366D6D5DC5ED0006D28B81E5B9B0DA250C9E6576E1C31B3BA75EE43944DBBA7B2D1192D975B61A89850D11936744DE64B58DBCA9AAB86D9B8372D18D8A1D3C8EB74BABD9B64D7A00605FC3D00CA912BCCB5EE87E84BC876CFAAE82976FF124BA3391FFD641BA1CFFFD17C6EA3B4ADC14E9B0B058CDA11D60F0D87D1B612E97B98444C5475EEAD8A19F9A264C004B3B9315FEF95C36059E1CF2F412309E5B8F3928217AAB2C81CF0F6B9079A63D8C67ADB64EA572CC5D1A02D4883F04A6F751C0F43541F6DECECB99A9E6C91224D30BF76A7FFC34981B9D6F928169CEF6918640373034E7362D3182DE0257136085242A28487EC4134CD8F9E8C4D5E068CCBFCCDD66F776D76C0711E1D7ACD379A35356F7E3655F6E7348DDD4744945E1EDEA67E95F3422DB401DA95AFF970D869915F36769A068670D2148662C7519350D3D3B2C67C51CD8DCD79EB02DE7459E6B0691E1933E9B7FA0381507FB2D1606F81CBCEBEDED32E26B91F5BF69CBFA3EF3DBDE4ACA1BBFC53D20FF5E745E977A80A12C8D912CE1467600F3A338D4D3BD863F1F2CE3B225D4CDE7EEF812E4F2B26C8631378EF9E1DAD6C15DAB6D516325F65093155066013EFCF3DA95F935FF9648F8C622A8E980BDFF05BA8FC4CB61374FED22AFB4DE3A1B26ED3690721F262833858DD9E9244458D8DF3368F08FBE41879CD1224BD1D9DC00000000000000000000000000000000000000000000000000000000080D1012161B8CB18850E27D8416B88A9A71F4A66BDF447814DB6C82098C371B53F61600EF5DFD88E4FB34200207C3F6F55166AF4878D38FCA7E2DC18FE662E3EA491B58A86246CAE16090FB7ADA53B9A67B3D0E3787D3323EA921274C60CFFB19A889BCF0300FE10E242AAE025F374DD83FBE9D007C8B9D9D75574C74146331DDEC6F0E49C10DBAF15654897E33E2B4780DBA484224AA6FAC79015D5792FAA2D532BB7D239B11D91420B98690B1FBDE9632223927E0804BFB284368A426C414C3DB8EA82F0D246413861475ED2DCA9E80FB4F3C34FEF7528069AE1975AFC52AC5AD2CDBCA1459E140F655556093210D7905A1A1E6CEEAEF0194A0B2EAB2C1EE853484E715D2A1DB551FDC620D5331164C74CA4848B61D408D2F2A943FA09EFEB63D524691C99DCC0B22CC61B98E6FB8039E5E0B2D7DE2CAAA900A44184BD56C9F02141A3AE8AFC661E3E898ECD3004FDB0704272BA780CD5DE35153B6FE223843024273642DCF8E4B58BE2AB1F61668680084AA0B75A32E766C8AE5EB30D4E02A12E6798DEA40F80D8DDFAD2041A52922701C689F46F49F84CFC05ECA6D7D4C356D50B6A0BA61966245D45134D6A1F5197540A1C39C36BB0B78831AF3F5156E669FD9213B64E0CF1C5A31E88AE79AD61757EC67B551B9F0A760F646BF81F6B92403A62840CC29FA4F3949B3A9F0A9A4286EE7808A + +count = 15 +seed = 9887F1FD854241A301EE0120645CD8E119B43F7BEE11F77A835E9ADF518C3A51CB76D86653FBE73AA716264C146797EE +mlen = 528 +msg = 9B64813C058F07A09A796FD764604EAF58CE144363702896DF0AB5FF26D5DE000D14BB8FD358FF5532D3B909AB62C18AC30F1900F84EBD3F4F18BD532D16C7B3470F0F8BDF72938C916DB18BCF1429DC1635B1C152C5F89A9EDB17116C11815A6C06273A889132923DA908FF39F4940A840D3CB575DC4D637AAFD37968EC61FC4EA04B4C320491A73ECFBDD8E10F1DFE902FCCEF93DD287ED872F67146BB8CA5A6ADCF0350E8BBA7F2F9762C4AA748FCE19748EB17334146C152FD63FAE3DFBB1A2C2B3C78960369551FDAC5D54643BEEAA59C1FEB0C21DBBB19977D848CD82A7AE0005F45956E0FE4700F14FBAA0C12FB8C65A6AEC95C5A5C8E79A6DA9C4E446872575C06AE49A31B82245E1757C7CE84D6D5DF3F642D3434B7E1A15A8B8A9DB460826B6CDCA69022DBF87595B582DDBB90A81E09A13C2AB1C125E4435FF30ABC9C56A00EDFA979F79D9C895E800D2DD6372FAE5FAACD83ADF8A6D55279D52DF547E9BAB39D99076AD7D297371344D35BD584E0FB5932F92FD5183B9250CD180FC645BEF6028C405B0EF35DAF783428173F1F2482AA1363640F66AF0FE8ECACC0DAB84ABD2A1FB53AF44445698CF1DDF4C2EA214DD339BE004E75BF76E95CA5C16981ABA5540689C1C1F1DAF4D0F89D62CCB3496340D61E7D5F5156FD3EDD02EDFEC8FCDD0B231697B0E66F4A3AAF46117532F5EE2CB4D2B3B82B0BEAE0A45A482CE9A976CC99AA82BEB0FE08CB68C4 +pk = 431A0B985CD3329C299FF2CDC80986397D0F159B49D8C72AD434400AB7FF8752523771D9C3CC149FD13465B06E8AF5400699F6A993A449F9925A4C916E768899ADD8E60CE9E5AE25B59A6D306C948149DA9E2177BDFDF9F844A35D93554D9390A5912924D690878614CA03D2C337122A4673D6E7F2B1F442EF9548322F3AC1F048AEE1692758AD1E3DA5B17CE2368B632849C1E41D76A04DDD04953C9DEC14978A207F6FB55D643841738B84A9E530C81C912BCE1C1A874E5CF1E029F08FDDC6A3E3B4A6321EDFB50114BBE120B65B7F68376B27B6AC56D414275DE0825AB60B504C38EF2EE36A75430D2890117868CA90DE46DC2C93ABF2E16C05C2E3243720298A9DEA13378C09C20EFF7D0239638197514C6ABF410EE91A23D50D64BBDF33F796C38DA0397CFFDB8F7650AA8B5054F101F1CC7D866552A0C049E27AD84264C97289B91490E351BF4C6C7158C0F25D002AE2A0836747381D408219EEDDBE78D32E330B955BA8AB2F7F7463E4661B89B5F03B5B5EDF768777480F94DBAEB563E04347BD7EF6B2068C991A1DE4CFFAE76A99B3B596271E48E131DFCA92853AC4532BAD840A9CD8EFBF86453DB9143C53FCACA83C3C324BD911144326EEF6DC62840DFF634B8A7C58A04E86649E93BA6332B8B1936BCA473874B962F24B1F7D5B78912149302541129EBCADD941AB046D1011FDC6BFFA989CBB992CC6144FF4E0DE1769591E271288621B75DDBCC3E7E55428B5F5C35AE3E844C6E76945E0A3A511153FF6B78E4AC07283D1D771C78D56E8C482F6910B6C35971E5C2EB41F3D618ACD88A469C12D38058CE225E60A14E312231B4E1F18227569CEFB6D808A7473609DAF0448A38DE929823068EB7777FC75561E78115B8BD5AAAD4EA5B0B73C11DCD7397CB196CFB8B169C23D544EBEA8FF3AA1F4823F984F6AF4C989D9FECA7D31AEC0F4BC098CD0CF8822DCEEB6480181861B4882A8EF1C5822C9E14B0D9B8C7DC2C39AFFA2BA1FF3343E80DABA1A917D679908C64A1DC214D93244F9771FCE5D4AB92DBF4FAED0DE2FAAE5ADF33573ADDC3501F7482954748095271E28CA06F9C18B866BCD6991B83A4904494C1E84A5DAF955C0FC2CA4715A0511183090A27ED5A2F04EC0030E33A52C24EB1AD8E757052819F23E049049453DF0ABBD1E8EE0869D4EC191D56B278DA2B79D892E25C22779EC00327D55BB85DDC606ECA5198BA3C0EDCF1DBB3E12D80C2AB32BB7A8A10D2FC9ECFDB946E885496987B29F616B71285E4DEF860443D38CAEE584953FAA437D754821658A51101EA758CDEEF4DDEC5AAE272E11C947BE6AD3A1D623C52E49DE6B630D33495FE2F67773A34E2E409CC92D1FEEFE748EEEDDAED8A43AB3DB3244C075DBEF41FC84FC0C737A9963F622229002710A633C60BE4BA5363428F8BC46BF6899B6C6CD49F98034BC985B473BC681735C8005D6B54D247EAAAF7EB4D63FB99D7F26595A13F868AB112F0F023AE1781ACE98182A6C0E9F9F543C6C09F81BCF50B86992A72F9E3FDB9DD2C5849494B62841954BB3564A7D5EBA01109F546AB7441F14016CB9B5600273B4C3401FBCF9E2E0FAE88072CD79593CC1A1D83278F99082EF2C914075422B2D810B9AEFC9F2E5687988DC941857D57A1A749581D54556B3EA5354719F0E0AD7999C48F6A6AD8AA7DC5C91172DAAD3E5C20A1DBCADDC98C5B6BAE5E07FF3B382257223C4B9D66E7AAAB3433498EB78E5B707AF9983D47ADCAF204777CA86110881CFDFC242A3FFC7A27671CFE1CAFDF3D84CF4167AC9C28C2C0B179B48AAFBAA634F38685F4925181204668A5136D9B937F75825E3D3952EE92EB986B59D888EBAD1B28AB245660743D7FA0107F58AEF1DA43D463F7BA19A036A72C7EE2A379BE8E7CE36987F6317671EDC623650E0DCC57655DD82C6372C4802ED55BA529EBAF572DA0DF759F0FBA3202FC8E038107A8D2EC690C20B1FB35D536182C88C991824926551A6276B65566622857DDB37DA3239A968466A991B9526471E0A4CB32EF6A1A5E8C0CA0718FAB997C8346706974281B9F15F97E68A1D76AF99D9BD6ACFE5C7CBE5757594820809DAE78112C9F0096B18E6D14580EC1BD9A1B4A23FC6E921223C72208FB7E77BF619E24B168CCA8B2710C88F53F66F7D736CC4767070F9A7CF600D93C90A1044D735B75A28206D7A82675A2F6A6318E0F984818952697F3B8DEEDF8B97FD2BD2EC70DF2B6788EF9E5096011496C99995EB02E897F441563184B22FEB86E1987FE52CD72C0BE78285EFF86716BAD29CDD6B0C9C04266A0F4E9E70514B0F1DC17247F94E031372D7D511AC0704C6F6C1ABD051C141ED4EF346E2707905E0AA968252290A6E548549E139218B3134E78FEAA4026C26D9B13EB452435024C2808F9FE554DD74B28A5765F877467C368324971B460D7E4B5359572174F2185AADF8A3E4703FF1B2FE30FD8B7DDC9B4E2AAA200712FB380C89AFA3DE8946C87E23609CF46EB9C8FB5E5F3735FFDDD978ED6E1A8CA77F581F1C98D7F39D559EAF57EF527431118F7E53351F42C91FB3A8718C06538F1F888D16AD9F337CB1CE8380FD42019AB4D05122C8987AB395AF712EAE0D8AEF15A3EC0E46C289EF1CB1105C2E6027912144E68E5C171FA9BBC2598151AD0A6E86CA223FB7D622E3037B7902CABE858D94B5500DEECEF030111B636C025C07FF325A40B0A438D007E36FF09D608881324235B2CA2B3E701CA3B2F853DE0DDBB897CD153290389B +sk = 431A0B985CD3329C299FF2CDC80986397D0F159B49D8C72AD434400AB7FF87521319241C1772FDCACFEE2BFFE754BBA8EDE34EBD00D96748C0BB951D6DC7B5FADE4E7FFAFFE5C9F6F31269268D32E654032C0250E979B14598B7623735266E2B0BEF2BCD7AFE4EE6FEDE66AC648AA037B20CC874F9F28E4795976D7C4B41504F280281327553743880283441882776216322347832474118432406506388630486647868210042172470406526755040438514621127761813057116140016803735586601782272258475365441168428134110752412711114811676476356066847808237473132702572710675075627480246884525551033676252501471276772486423038854077342721118852652155106147151210238841485612605162130070332113037551776321855664616020537385614012677750077681240417542506062525681424470015730306752245004026611360171737733488168138514386016673278340544873475465170080474204056732425454528654402813614232314532830025251143700813066063800746270451017710533444758522423486711778003612606527464256520583518874563747112886088418217506338116358536427884171371512560284456424611574670353424508842208555208631214113326161082718252026585837404264537573787160785054884555741323641363758078016267776128703614374210085202454233824041412133613244563232718271180831127422858650228616455375502184521420377654484326504510831143658804278627401164431046060763824785564465665556338741575887460361435131660324424174104707530645616286511668372370054151057028188516550513134112262721820334601733561600524363411642161142480157220032032317843261467885237763365054171610514581825085312345302486365720111853572608382511784172266816086662427640401612207710148681037040528021557542058186843232651348265243280131642621163421148234187412046702714584358412027140331686661512127727821035100844668213121423117145301872645422141632460856104220460681811750404341223622220102044104420166158764818543761555470044072234472738401007664652844742485408613776774875145788672667145200754541811218187187164576334781808308567030814454715334820023271334605751272414857756074386434170336247058111760711587867302350518681108847024024712477562310123606885114762378214721876508824312378610740700833204357385201510561215548355384531004610647808314012777330153305455628575283108602163004510571848580878815740330210604357238584123556501876725021757684361844380513550418674534886502838818385468142106450174265632878188522607545700828828167025616175315336750053775145787464520303483002376720461770243180256168014157726078406838575448000212011278853350157008507613810367577632860421766864670020370181208763625243078047771483232452268128643571834352823635644622677824344057470115735728787428370884424606333005114834526008804130054317803126258335133613168738450046826142568820050372204056206273545837440118567273362461047231660812147380872163810682773860562317284188745403205463131005457845827843367126318326362201351635873316808314271261350485202431351842355661278843227681663560044733305336685053683827452788458860348543582358828255354070014553830731478886856170450434440501841154446731858321605415525346678606320788151035085124358324807718137373715161685430476358802785535201074586303665355344621174325087077002844288768106437373106802417358663F816033299ED8BB46DE59301D0EC525CE418E3C0009DA4DAB438FF098C1729FF1BF093A1E204E457BD29CAD3DEFB538107FB70EA39AF8A75E553C4AE81AF63CB82479E24CE113E8BEAFF05442795A3473055710ED77A9E2BC3E1F1776BF74EB8B1910248CCC871B731A01C495E6D34BABA5D3BC00D31BC1C2A8CD6A51D323AF347DA3C4D674D0FA97E903E3F111AD4FEBB9D13321F91AA3A8CA98D6DF16AB0FB10E9CABAED79C038BD565B40854C1A2C255824CE0D16E425F6AF366C69A60E34178BDC1F4CA9B5391E6C89DF8FADE634AB41E5C00AAE51EB5AD5F5FBE06C49D9CDFD815807CAE53C415D93FE21D18D0B26D6759191257546EF150262A16AAA1988C6A0D810389FF4664A9AA224E8F8F66678CAE2225271C7B5EC2174EF612A0FDE4494D8C880AB3E9CA20F86F2FB86A3D4702A453D4F579E1CC47E002251C3BB182BA35024B644E5EA07FA9AF6C8ADAD629E29627E4B084252A260751A4ABB691183FB0CA6D5F79493B13A91BDC93E343C5768B7B30CF3E78FF1DF83FDA4D98F60EF39FAB4282518341DB4F68FDDC847CD492371BE53CFA6841D872E63294E9359286E17A6E1CF1544F6880613ED6D513AC849201951DD027AF59A31F9AB5BB429CA53CCB9DF64E68D6969E1655663E0BC95F6F4172EFD41E8B550FDCD678AC2B4F07E764F2A2006EC23BCD836DE7C9ED7116E98AF98E66EC13ADC5600F425E3D077A5803B056750D8577B44CB0ABA3875FFB876E2C9A9229276998609371AF1214AF98DAD6604F1F3FE48232193DE5FE8A6F206F2C5FE6457080BF90E294D29539D917CF7310E497F99AFCE73D851FFEC2A64963559BBEDC527F979C35B0F1632A42BFF28FA82F51E0E2C563B4FD864BF3FF5DA59F00F0142EE935EF4EF50EF0956A3A27A63C5E736DC3324AFB262B4F01B037910E9EDFBF48D794CEFB05EB1164C508BFC0D0FDD49D99FA067D1D0A20519D2DD754949F138AD01B02CB5B7FDA19EB052CC06963FBE65BDDDFB4BA6BF4FE364CB2C21B052F279519AE19DDD1ADF84984617E50B2AF92EC878ED470A4C4F12687C3C6BCD87B7A19DE45F571BE4EEBEFA3E8C1186042247A9828327B2B9DB092AD8FC9DFFB4F4423E9C8D973F9ADB8B9A86399B2124DB63DA969DF041EF89D45D01B6247A1020BECF579AABC6A55B973A41651B7B5E34558E800865E359D1356DA7DA776775A267166BC8E1A7AA450E3FE9C212A146A351B35DCF3BD7AAFBC9FF9102F555AA702F666E742DB3D3C9D7BD7D1693CD852EA6819630AB9B8259670C9681C83D38771007515103D3804DD54631B4E40616D009C0BC105034CC1D25B4B1D52887CAE3FB47BA542A9A1356230A3F8EB6D4B497FD61476CA1E0DCF0A5FC109BBE25A549BCFE3241741BB9973EBC0EBCDEAA9A941D1183045DD4B6FA0916A2BF30170B0FB9DD0931F4C86AA00CD95EB9D4AB2ED626E779343014F660B08B427DCF2A6567BDA818C838F2CFF87BD28A6400B6C18646FFE839E22BC76923C8C8FD34783F1B248D9AA2F82482E12AB771DD3EC1FE59D096B525F7DC9384ED28567B905F43266696F97851604FF26884ABDF320AC1279D435EF17E2AE22DD4F39FA1C3A9E35BBD485EDFB69C4DCEBF89940857DE675DE2295AEB1EE9D264505F2C31CB70F8FEB05F10795CA7273F92876052D76348883BB69129D347C695A0A18FB1B53F1669B8D86006DA706062DC70549637F8FA8CA427FEE2B9189FFEE36300C3B239AA67A544D4CBC38D335BF1CF16C409C72DC2137B8AABAC4B7CE3A7E471F416BE3195352D6D4C82DBBCD500702E03EB1B98FFE1A7C0DA1B24098BE2F58DE9801E92B03131CB612074E9DA579E91E40438A1174F89A34627A36FF7CA9F2D79F563AF5A7D9D43E2F97C346F3F73D24F8A54FB7CBE1FC5485019BCAF88F4BFAB865A85C2E6289D10BFA80029906002F27BED2F14BF9094FE91090634EB990390792674C643CA02D82DE248E835886393521061BD2FFE16CA77414299E0E2478659A619FEAF9FC61B3254A1E81EB844DF9162E2A7DFC480BB7533E5403D8BD4872A223A19F68D0AA2D50080884250C16ECC71459243AD57ED8907C5EE0339A3FE9D929DF7FD57530CB41B7DADEB225D6E4099E5DF004C2C2940F32900C9E7085AF38E21C68AF93E4DF22361BEC2357765DF2AAF3D6994C0EF49BFC1E73E81D03D1CD89635FB6AA3444A1987AE32B7864E0335DA4EEF2FFAE243F2888D4C5D103F88013AC3F49E7BB9243559E8DECA182884CC55B879FF13252EB0334C46C20A59FA997A7EA6A41AEC5817A7FC8E8682F7E831EF058B60E536315CC23E8C750892FFF4BAD47F8A97612A5EA4438FD840257579E59840A4D71D71F23D15290454F5C4CDEA3C218C768AD1E166A1AB5B2FC4A65993473BF6712310DE9754759671DF948A6EE3C6F33C6FF05A02B9BEC4418C1BFE226DBD575B2BB02C85436DA89849B3696FE02C093C46F55BD563295338D6EF620377EA1D64EA983C0EF37C522A9E15C6D9ADF0CA75C0B9F9689D9330E04C367AC3F7660757605F9E9F712986E3861C058D361582C0EE6625207880F6EBC52A96722B8FDDAB4C1489D8EEABA9B3917A878D0DB4790FB21FC29F29C88659F8D473BC8FED695E697CB5EDABF140C98FD47837B452925BD11415B0828235B640AB07702E5FBC21EF6A4D584D42348A324A7A0BEDAA22FFD072EECA33003C2B6491B358FBB10AEE776D149CA6AC3C8AE79568B93E49CB2D204D1DF99BB90F87F908012B1A71250EFFCC37485450FF1A79B3E7ED4A461DDD364535F811E6696328C45EB11058B21CBC05920D978F8E69AA9002F410A996F590FFE967C6EBB4EABD1078EBDDF017A29954D61F4B72BFD6242342990D35256EE725BA6AA0F1857DE891DAF1091623B1B9EB97F64FF763A054E7CF4526EBA357484E91C09F1BA55EEA91D3A9FC77CD2C621B93DA1AE5E70E173B15AB965A9B2D3F143DD60C109CB2D89075AA3B712CE666EAEAA209BD03B3A566AE464EB07513BEBC64A417C69DE441C7FE91AA78E6D308912B1D8BDAC5F6587436982C4229467AE6A1279AEC167D6ED8FEC35D74CB9A1F40AF4C8484B71D2BDB2B668978A322156920F3E199A9EF76083994AFA5A07AEF29A8F57050DF264B5F7B82624D7CE48D574416BEED4D14874861ED6E38AADA18CC9D9877FC1F7861196F47DCBDCF2AB0CB0A8178F2542CC3478B43EEA754A9304E081AFD423946773BD2D8B71B1BF6FD7D69C98FBE85CD08887DA9C3158A60D57FA1496E17A1FCD0D95941E857EF17E46DF39C431987305227DFF54B803732F6076F39C99DC39FCA7F1754657E5650668043B0F5225FE378E2CEE67F01E0B6AD4B2FD59011A0C5E8E7B3A72A9106456A2D989FE12D6A23D17F9D82AF636E7E3862BF6622DBDECF1F577123A97B6A4CDEF7D1B0AF49DE3C34E422835577FDF56E5149000F1F7B95F614F7389B27FC0901F812DBCAA65C0D8522790DDE2F1F7E92B6FD67987BE1482606B055FF5D8718C0FB1E5 +smlen = 3837 +sm = 7E145220B13DDC00ECEBC7072AAA9224F7FCD6FC93C28CBE25A1DD92FB6A09DF314205C53A1430CD884C2F21C9C271BBDE970340169495FF2FD9D83D08FA0D4E521EF7C53FC484C64F25B790BD609982EB807024E72FDC16C427BA10DB6EA4F77C17D27E488906CD94EB2E012529141326B3D308D500297AF9658C7A052A75DC48033E822CE19D9412BDCDC3CF8FE0E8B90D369B20F169867F7027FEB6564F19F9330F15C0799C8DBF566C88912AF076BFE510E28CDE8C19EF3C0C45390DDE55D274D9DA400A908A93CCCEDC7DB4F478E0C157B03559449F2370BFA5E2B35B1804090634A28135B0721750E957B366374470FD39403A6D6CAA54C8C69B94E916C3E3C3581DB00B877E72D41FBC5F5DFD5208BF8CB7D7FB9B40DD624FD67A1253A89498748E914A2E53180112030D73D30B507DCADEC648D62B5852103F883BEC6F1F377755AFADCFB83437B1D6F44F25DDFE0BBFC1C94D5B8D1BFCA909F4486CD8BFC31CEC686E227D08F613455E5653C0A5F70FB284B9D49BE8589CD0E2FA848AE4C4CADE1ADC6C8F8E882D45663D0E4A6DB990D37FC6DFAAD07A8E883F6AFC7D20182911C32919958CB73D9E37EAD270A0B4C2B9F358161FCDDF6850608F6A8602C8BABDFAD76F6A5869FE6E65DB50D956C35C31E38DED6CC802FB6B23198B8A438B217C9B929A44A1E0274285D10D6821EEA6D4122240979497BF5CEEE20F0636363DA48FE2922233B025FD062A1BA4886DB46B4981D3A7C0B5FBA68D3338D2154D4528E3CFA573C872EE5A5A5DBD631604733283865B5163C839F630AA00161B9B0B2E2E93A62615E18E24A8988E11D80A26885420F21CDE87ABCA967CD2DDD6C4235DB4DBFAA2EC8A53A6B17A7E0B6BE20E4F46BAA0D758E123F16ACC4F8A0C2957D1D669914456C106BB3C3864CE81B35367B78E2C75E710194D135A513AA919645A657D43444BE59D6B04991F5CA57BDE156AD156D94B4D027E56C9D2FDE631ACD8D8D76F3E5397F33CB08C28B3B2B071C028D9F586321BF9B7588483702A1761AB021ACF4C342F9D57E166EF73F6ECCE295041B5E7C5F16E4F46B7D00012C242CE27FEED2A15B76FE3F0AF8CFAF5A6DEE7190574FB6567DB99DC9A649B63CBADA4637D40D83B37C6A164CC4A65ABB40413007AE18DFD1C2086660261BDF8A163DB827D96F20BECA94308CC260657B6470831E8FE5A52C1DA15154B7F7910CEC17913C9057F2FB3E52FC5C98E351841AEC8915A8DB168A40212F214C623E6619021DC3C60077F024257693D3DA60F78F5F7909C59CE10329D83E0055B029DCDB80028A21064A5B6B2FA6805EDA222E55DB2638FE0DE9DED285EBFEAD9F47C054A138300052E47C80C96A343FEF1556C933014A248EDD59828B11140347E4029360315F9D7C8CD100F212BC840B06AF02DDA5D195AEFEA66B03F9D19A8A78A5C10E447B36CA2042D31624365B77601652321C07C7825571D9F0FCCFAA18696E6312E9D6B179B2336F1C9DCD876F6E9F33F2F030C647ADC1D8212A895BB025406CF4236FD7D4FA354A4EC04986B9BF6125075049B640F35458810D26291BFDDC5906E281FF6B4DC5C5B54F68994446C61EFA516AC86A7C9BCC320DEFD34E495A846E20EC434FD27336B0A7CAC71649CF234A8C7424852F7DA6CA889DE701F643D10EDE121AF73ADE2C2DD50E34E5A6AEFFDFA50DFE4A72D0D4499D0B8EA7F48BF61A6F555DD4A82CA8BB44C80804C950877E1C635D7D6BAC8B3650B84655F391DB6C210E7F56FA77A34EDF4E80A6D9F15590CF6785F40219730DE2463726193A6CDFB59029DCC69EA68580E30A20AFCB53AFC47D280C0901FC341497C5EBF2C8215AD18BD453DF2D83731235A158A9AE665857B1443BD94FBDA7DB7CBA90F28C0EA2D70834D75C2CD38CEB2B198BE0A9149D7949BFBB98F0817B19417FF2138589CDC0C8B31367728AD5025565C3120D293304F32EA35291F4FDB0CD23BB6B110ECB4D1C6FF4285EB604D1DF36915B7A114272EB3765DF5A39B3C608261F5AFF83E0B1D9F60BFFEB5A854E9CB45D98FC95A307BB7D8BAF4C6E5BBD2468E2623D9F2F4E772EB7DA000E33910B95645447DE73BEC4A3016A09E3FA5A12629B55FE17E1347DB200131892115F8C6F0BE0AE714399CF2E155710076AD00458F6281EF24777D4D00957F9569190CE03A05DC80946894BA421F8AA13D6D1B091E5A4B1E92B4D7A835529CEA70894E9AD9511ED82B9C4CFF6618BEFB0CAF0122649743969AF5C31BCD0517B7069DAD621176F1F3B2E3D63DA1D9366637F6C0CF52C746B0D69D4EFB4F400B45C6BA334E7947833AC42A8B66829EEDB2F8FAD971B824FE2E37BF1E02D20EB62B469B81B05FF0FA794E09242FC34FD2C06509BBA2F2EC5B9265AFFBFDFE736F49522438D082463A83D190C81E85BD67BBCD0127FEDA76A1C4A1A3B812AFAAADACED8C5DA0E3E97AA07D54F643D53BF3B4685FEFFAA861F3BF78ABA71A6039A23FFDA4F0D34B1750273144E2835E835B8822B63D7A90EFE06AC947F3F0048C2B6AA7C66CFEAA0608CD734801DD336457B3065AEB94F6E043B46CE6DE804CF47484DC4E333715050EEE2B87D9BB0A735FB410D7F3716C869CBFB2467062F72F47115D6AFBBA4681ADEE43906814219894E730F3D21B5EE062279B8C63E5FFA6D35E7D18B808E792B5752D7DFCE8EA9503697A87783F21C2CFEBCE8FCC6F4287F9E760364D39D5F068625D05D86AB49B894D7E01756C566A45F2E8023407858B06F5BE9A53166519A30748403463778CB800319A65230BA0A2E07111074C3044E1706489FF6F004D28A0A1675AA84742F60AE025B8DC1FB0AA0973A4383F910B850C07102CDC05C7890E32E898C441F807F1A5F14374EC1FE3791A17924F3E0FC88E5B1E6329F3451F44E29A3338F1670DEE64A684805722E36D74130E8693FDA09C6304E22A79286A0856EEF78B948A625A9FF8F6BD1E23ED1808FCED5D5400A2DDFBBA26D9B8951CB8936013E210FA0F57DA944E67A62E7ED7871E7E3E74CDBAA0D1304BC5718BA02C7F5382645ADB5CB2EAE0B2BC2F9618CD400DEB4DC33EEB9D4DC007782720C84F6A8C970AB7A4AFD0A3183E1D354C5F5C41A0D23F6FE16A9A0AF42AE5002759DFE1FD9B88413A0C9F8B23A35C7CF9D6682C4E96DA94D047E69631B79872439A16B0FDB783F9F8821D54545B32CC68E9D7241423FCFA09BF70C25CF7023D33EC321A1659E6ECDD7C6FAFA42DE54916985C123651BDA81BF8B63A6672BE34CBBB0886102E0C609AC479E614232EFB221ACB8D72A9BF0880B88323F67D1F8719310CC08208AEBC75F996D0249E8FF3C148F9D129C05E4FA40911A53DF06CD1CF6C780C618E5B0C848E1629381C5ED7772FDC9E91A0587C99E2EB308D83C9F421EABFD32228EBCA4480AF1A44F58D869F916A40D81782676FC8686252596D18F893068DBD2F344F3DB91F1E1FC5AD331A5DDB6828F25E1069BE849C1071196B3C72781F6549274DD108AD587280FE5ED5BBBD2F3E9B44CAB952A5DD3EE069CC76C7D43518705AA589F0D52135538A0289EEF2333B813A8B8D8DBE6D3FEA19650E7227E87FD6ED9CEBE2452FE43D349122FC646011239009C86A892704170E4F46464432C653808DA8D6CCBF4D77C83F52807CB261447A92F9159A695B35DF7091AC5D11D51F2D9CD65C80A5640FE8A497B00ABAB66C88E7EE309485C127475BD626CAB93525B6E6826BF9AA9D7C59754F4E94B9B2FFD3DE96B24BF12FC29E3573BCEFF7245734B497D6DB1342D8186871F5B290E09BDFA2EA48F20776A44FABE32FCE570EECDD4B988D71C1A5945060EAF3F26C6BF328B8808AC207CDD65D63D191F353E112228C96D90A08177596B76D6A9BA2C886424913A5E53ACBA66ADEF937846BAD9F2EC3FBDA332D7B6037760A855955BF96C33DA0AFFB33BC927AA662BC9206DB3497ECE317B15036BF6BA724B4FB9E71488C65926CA75BA15EBB7C3FCFA2DEA65D5F62D14FD9BC3EBCAF968BEE8D1762582EEAB1AA93191E8D4D7CD0DD607E90930BAF5E389E3EB9BEF3BAB6FDC3FF464A81AFE1B68F44056104231E9E6C99052719EABA1F1A5FB25CB2D23A216C71161918D7655EF2F1098427E7785430EDBD1C1C9F77B9E1C8BA366CFCD5E821F88006D124833EC4BC88AF4AC66BC982960A2818B5755A15A2C330C7B130BD1CB0432EFED8EDCDA579811B8C71BC3E1323829831A5F9B53B6CE245A9F62C02DC8BF4E6DA4AFCAC4FF092817B9E3A6ACE629C724F4758EFD55CC24389672F2B46C94C8208B576A7B4B622C773499665A8C328A3B6F7F41D87AD0C341B6FE0A222E3FA94B29F124150B73A415F4CB8F5E83C3CF4A5984768956B548B5B35C32126937E0A14220866E75CEAC92CDB4332F1F3BEA3269E28BA5B019F4D5CFFB8F63033B2445C74E5A53DD821D51C5F693EC8B06CAEFD54D4DCF32FA8794ECD2829D1674D07BC027DC2782024D31DF1CF1BC77F119F561111C2BF654ED44463BD6C792C3DE89011BD165619A8AB5E5770B75AD03DD41818DE257C9872B37C3FAC8855DE421AD863618A5C7F78B7AE804DA8BEE4E5EBF7F80C161B44798BAAB2BCF4242D3895A6121A4A617C8B9AB1C2F91662E1013240537C93AEDFE00000000000000000000008121721242D9B64813C058F07A09A796FD764604EAF58CE144363702896DF0AB5FF26D5DE000D14BB8FD358FF5532D3B909AB62C18AC30F1900F84EBD3F4F18BD532D16C7B3470F0F8BDF72938C916DB18BCF1429DC1635B1C152C5F89A9EDB17116C11815A6C06273A889132923DA908FF39F4940A840D3CB575DC4D637AAFD37968EC61FC4EA04B4C320491A73ECFBDD8E10F1DFE902FCCEF93DD287ED872F67146BB8CA5A6ADCF0350E8BBA7F2F9762C4AA748FCE19748EB17334146C152FD63FAE3DFBB1A2C2B3C78960369551FDAC5D54643BEEAA59C1FEB0C21DBBB19977D848CD82A7AE0005F45956E0FE4700F14FBAA0C12FB8C65A6AEC95C5A5C8E79A6DA9C4E446872575C06AE49A31B82245E1757C7CE84D6D5DF3F642D3434B7E1A15A8B8A9DB460826B6CDCA69022DBF87595B582DDBB90A81E09A13C2AB1C125E4435FF30ABC9C56A00EDFA979F79D9C895E800D2DD6372FAE5FAACD83ADF8A6D55279D52DF547E9BAB39D99076AD7D297371344D35BD584E0FB5932F92FD5183B9250CD180FC645BEF6028C405B0EF35DAF783428173F1F2482AA1363640F66AF0FE8ECACC0DAB84ABD2A1FB53AF44445698CF1DDF4C2EA214DD339BE004E75BF76E95CA5C16981ABA5540689C1C1F1DAF4D0F89D62CCB3496340D61E7D5F5156FD3EDD02EDFEC8FCDD0B231697B0E66F4A3AAF46117532F5EE2CB4D2B3B82B0BEAE0A45A482CE9A976CC99AA82BEB0FE08CB68C4 + +count = 16 +seed = 5B485527C3B9A5E5B7579950049CD357975D4BCFEF83FE33C087ACBFCC10A0BE4225E7F8A5F77203B5FC7C0B5FC0E78B +mlen = 561 +msg = 922320F7439E492F13C272A5738FF7122DD7A6B2832632E1F7A653FEF3B8639BCB9E84F482F22A948EA17DDE6958489593D2CB268BB52DF8ED612F2317BD6847D1622CF0532CB499ADC432233B93B6F7B1866B38975AC87859AC49F91E8D235846775F9E6E6D052339C741EF6178016EDB3D0B1E3F3536667B3EA2D489F88D254B8582421A31461374F465D7AD62E896BE0857134707A70477FABC09FE0A5CC3B3F32911F5FF3806B878205525AF69007F50535DF05C33AF3B0D00E297AC7EAA012E1D863DD5DD5FA47FB09467DBAD8BC42EDBAB42A9625BFDB9FE578343297506A3B71CDC8D5919955AF4605FCB0C7164D96A187AFF65D0F6210FEF2D11BA08D90C4458542BE72E084577BE9E451B8B6F4909884BCC5D25316ADCCD0925664D4D91C2E56433C1B68C632B0CA56D856DF1EDD5E113D1F026B30DAC4FD648A504F8F6809C701C97BCAC2B99286CEF5C1C923200B1BF6141EE1CFC51C5E14554BC02D7E058970254D2C02948360ABC4DFB439E66946A8AD615147BD8A6CB0886211E8B15DFF3C72B6F8908CE56BBC1B40E838103202E9F188D98E07555DB61778F895F76FBD838B6D14209D28EB393668924AC0E61072CBD9F93B864904FF4302DCEA131B2CA16BB04959ACEE096B1963CE07F59AB505FCC8D89FE08FC58751965F2F5CA753D76D58705652D3B1505E0F720EDE3142DE9776FFE4AA0C8A25E76C7A04843377C59F1002844E89189E22F621467B813A98BF07540A1649264F14A6844D65692617F7A4D93FA9A23829E256626 +pk = 4FFEB4B10E756A3DB74968D17E5FF126584030A7C2D6BBDC2AE8CDE4242DFEB05BF54E3C8815A5755E019684ED0C0EF3FDFF8F6FD9478D6202C9C6B4EF9394C8E8E510E28C6D35959CDDF75089F7B342CC98B75779A1A2E584E9967D17302DB7D2EC778D037B30B3B2DEEAE59D98523941DEADE29EAAA9B70453BC3AA5FD631F0C22C276A1075B504D02EB2539044A714AC7D40156A9C419A5C4D9D614DDF40ADA04277EBA53554011DC6CAA13CBDB925C348CCADB9D5088902E48E0A893C9DF5CC62FA76B2AEA529C75C58D7C23A80C0E5F9FAD1497254B3AD0D6DC858AF03DD2137D81E9BCC5A3EB5C1006B3552F43CC087F9B22E0CC93EDFE84CD787451F9408B6E9BE83E4AB75FB398BE9F8211763DFD188068E6F69AB3C5CBFCB3B521C1C539725C2AB93A8973F68C5C2E4DB78F0E4E58C8FE67922D6DE5A45275257289FDF5F5A4B7392C1B4EC8F3CE7238323BB45086F3C9F330A78440E2F5D92729422F5236072841633F382A28F166A52EC6679C24F760314FD199AE78D883515A7AC20626F93ED05CF18C3C83AD55A2AB68958E4FAE1B1CE94FCFC75DEF8B5D433C3A83F74CB851F96EAE546ADB210C44F41FCD7FD8AD68FE3ADA0DDC19CE17EF0FE02B1489A9C212FBD054BE9CFDB38BA9FF9727EBC3EA02F92E3DE500B6B5196E136C3D2F2EAC46090D0CC1FD713A2FD8E0844B1E6DB828B6EBBFA41232F92C8F1A60F2AC861E302E99E7A0707A71BE0A7ED3693E74FDD1EDA8D9F3F56FB203C8551A0981738FCC4B3BA2FB371316FFCCE86B3D2276306C25AF2A2B9E72ACA72E4499317356A64FBE12278005A9388F6E25AF78D0C15F2C1CC75DAD47F0C5727865ABDDF508B0A0576DEFA82394FE0A9CC2898DD9A0A6BAF289811F677BF1F8DE663A9B0DE94C9D3252D9DD445AE5E12DE14415F519E4058CE6FA71159F6B0843DA0C8201C053E8742EA2AFC43AB84E0C734EB51139AAFD3286E5EDE37BFACE8EC5D63BA7CF0DBF76A1936F31D359E008DD069112E2BDBBB7F2AFAEEAF106372C76468858DBBFCB6000E68088F736E54703894DEBC412CF72C9D0E57808860FE670E64303DB06A867C02E40DC85EB26FCB0335320A1A03A8FD00BEB35B9C24BAD4B9CCCAE79C53C517F3BABA12C9B2A2D664E66DF69BEC6A66A0C04D81A00033D2A825FEA52BECADEDD62D905AD4FD1365104E34ADF0F95D14B892EAEDD562214CC7C9618104001E01114455CCAC2FD43EF463C5EF2CA66FA478E0A53CC627BCD30B4EFEB494CAE2E34D815DCECC63AA3F67540A66E878CF3719BAEB2CF9FB51407167E9EC29CDA3B0D05A610F9D142C0DB6F37B816BD37C943788DB3A690195D1D4620FF04F811CA58C98EF2E61D76E245BDEB2E576972ADDFE0B389A8896055C3047FCB48A86948C6B1A93156148AB6F68876655F0A413D730CC2A1BC73B7DD1B676B48AD4A89E4B964F015201B36DC8A0FAE901770FA20C5EE28FA432144884C8297CC5AB6919462C93B8A44737D96B8F721D51A1646C06B469DD8FD1237F45AAF0B62881D861B3A1349FC5A57948B7B5FA9BE80D3A8097B9B5E5D263DF3A5E3FB89DC744CA43F160E1DF36909ED226BB25A1568F5FB62CA1A31E8E0EFA42BBC7ECEDB8C6009D464FBB0B43C18AAA7E49DACDF10604057ACB3B3636E1B2B3A2824F222C7B6BD29F58A0C13F4887743874E64EA66901E2132E634C2BBB0FC270F9B32A539116601E6DC83D123993785007DE7189B35F03EC12C001323AD293816195AEAD1B93E358136ED4FB6D0EDCCC61C70103F4C16CACD464524B072F85085B55E8259F5E3C56685042FE1860B9BFF17973C10B9437B17AF94F79056C5E2D54637B7ABFC025DD9B5F2F2E18F6612B8C3F1C44D6FCFCC865B19D8570A68D26A162ED45EE32863A94E8EBC1FFA5731650CFB23F4348818D0A56827BAA07E749EAA6727699B656147D3199AA83C7203D0D687F4670E33410C0801CCB054E5C179FA99FC508F611123B6F4D5BC91C2A3A66AEC4ADF8FC5AF08F1321E10D08B8A22F7A3630249BDB5206A0038950A7944A962705B99137903DA57EBBE0C420AB0CDD314C4E1D5EF17A367F412B91E21763DF63B5607E4B426654CFAB2C3B163F472DCEEC937DFE5B58B5EF2301C3B5E063E86508D87815C54CD0C4FF665C1DEADC6A6245B0A7ABF3CD0D4F0613D2C2B4D5F8E39BA726CFDCC34D7AB429D68C503360F435A8A340F52CE7CFF733EC7A3E314281E5E65C67EABC2C6CF530408F6DFF8FC71F53C32119D75DA57FA1AE9BC9EFE0AADB0F3645C7FA00F1B2DE39A077FCAA2E6C38D4F693DCB77092095DE7D5784805411B2C92B2DA86D0CF9E207646662B35FC1486033EF4DE2014DB7957B95EF615719CE85B125AE3A35F0727B19A34EFB1A168E2AF2848B299027D8EE8AF28C73B6A9171349DAFDF9BBEBD4AF0EDAB9948FCFA9473DEBC7780AC51C7551F823F80E49EBAF66952FBE7F94C2AF588579B0B447B53FD96DD2832735946A1347EF8E266EB47FF6613ABB4152F686D097497159E4C7593678681C77EC280A2A98219F1AAD81D339CA6DAEF586BAF3A56658C4F7F3054DA2AD9A88A6A79BEEF0E624790DD853641F7C47047B76015DB8F091C8F3B527282C060F057CAF7B892D7CE25704BE5A508867293ADEE4CB10C1A1445986F6FFDA45F9DA8191A8341C3C81B706B11A981E1550AC7DC56E57277DE4C47CD51A363A0B27B133E01653E30690478CC416031ADB55677A559139B50256 +sk = 4FFEB4B10E756A3DB74968D17E5FF126584030A7C2D6BBDC2AE8CDE4242DFEB05D0A585AEB03A8F18DADDEF603B2E14E74EDD79CABB69352FAD789D3D97B3AAD8D0A112CF6DDC1D523D99FB00B942E102AFD680F6AB5EC53830FAD5C9EE0FCB2F0DF1236D175D252541ED1DE0B423888B57DAB3ED656243C82EA8EA79F6CF44223654526803627406162258467766833803641322423284224052336131758762076514718338401203267707572542785378084223574843756108805152888664002674043143276734434766466133887326385836347375867606184638005613266156242111615353138301846858276241572877364112373487188324558051131720511283318718082170457877217821311338135447376672832278163013106058104711664475368840738530222220161111783726223570220648141158648017705547281383470876413818260268515064776200101538105640382888284111564121858356663358301285057886012137331771527377216724158542438845618721010626161102888180426021048106720072637035343733432172685801046787042843437083514637127167674357222025836808107045875467635566606221405381848827301372270622677212842463782546235042468625231125084422323040302102157114006351355038745284877162176584558522272702807216074416358558438251060345561433867080745380553130510641878771507421168560384866061317055021463744531765441325432355457578222546678838242064415853215062540451574116816228450888001542733688420108875543563175670615506328074167435266502572645507780147561780422144547414210222255624437367800055460643623252720216801854160613408511621314651656215237228556738831485352303656771112576022267653356775071675780532623503004711785222868221125341668153738656487840213843502040535614025884534231856501470202768305554153404235561332588271682458467686221356648353822106088747776712511307304010401335310312264268228165157760050288663144417243842116438511824231520145224116112786388413100535506378654056430546170670428778875248510338652521243310751451010865435345044684055250540104887103048202647702463384887684261203148254825767175176034018571847184022178620064473506801635487464255022047102107256422736636326203755463222168442167340747160178205883020620764811513171071422601060585514883367553048001144053268866365201083212536126052188761265542874050410460003003678785765774224283846475848316476663528447785230682520462310243380588123033277835158343787003362311676461881567654715564643464403278300584288522365520733781283722445527280374080462070335274234130363741283471181781567100012206482108023118236481432310545808027555055154807437217876876525284188538575558480853280432623643665222666361367167344872102053000717517402021455142465703883457340818308040678533110271036518125260318215830700040742134818764184051333762607002846742778422102513058522856335350081463583041741153712748784454802880243310887010517535070440052773657007332067385786160774138271875111452862212818623181381052567468363040350041266848018550274802284568653100271055062183802841620526385116432438472460556721670052202775515525507160888777688224686603146640464845358874236501700855476482123467851118484524063220086525032863850436212886050656782672026057034411643406764752638715458437454507213474741650643127214648473105516834107885022712025183320507066684265777D702707492DD709BF04BDF2377D58B22BFDC619208E5E0A1F1339B8240F0087B93D8F824197FB9405D7C650CC9B750DF9CC08AC65B6FB0D0CAEB606606F6B215C59005455664C25605278FC77E33500191E788B2014BB35A6873FBEDED9E1859DF2FEB1437BAF019CC43B675AA5FA5988705A5B0FA6D3A466067CB3360BFB02178EFFA4C243DEAE4D2FD97F395D5529ADA03DA9A2372B74C2438F78F21EDC71CDB65B718883C3C81E4E41185489B3A885822D83D86BAF3A11064182748ABAAF0904C7A4A41D43A0198D82432ED0372151A1922277F9E4E440235B755D135170D441E774E0B947CD4A15E347940769ABF0C888E3FA15A3288C5186E3AF6148C7CA903A5253D66CEC250FC615650794CE3F82856BC054D510C61AC0AC9812B2F7B56DC80051EE83584477F8B469475A32B6BC5CFBB67CDAD1738BF0F6D6679FFCDA256EEF74462101D6649A2B93FBED2926165F32DF64A8A11C50F166F69729C96F5FC65C9BA1A20C72542995580F637C28384F330F4DCCF7B46C5FC19DF561846A9EEFAB033252B3AE9EDD2885DF04142B4AB04BEC2EA55F67BC60A50F16301C2B1AAA7D6BE22C1ABF9DEBB04670DF05B074A6BBC7B4F0DB95CBEDCEA33902672CF5EFE1F772A01C92B0B894514376CF1C0ED3C54B947E01F0C563E9B26B5D0CED1C0A8A08CC0C213FDE0A8CC57F97611158A0BB52A01D6533BDC9363E8C09E7E0B9809AAB1BD9F000BA048096A1010C7721D3C54D9AC28D274E5E44EAC086778CF576EE8F8279991A6BB85B1A513E5F8B14377F76A02088C4B06C7002CBC4AED01C2C8874AC6F45BA179E2095BCA7DA3384B321726EF0AE234A3578DDAD9102D1373703B24F349D0794986127C08C06C01847C1BF1652E66F19976581AFE03EE9452383B5E837A2BD94C8CEA2488308799104BA16481DBABFE1E3199545922A54FEF60C48AF335AB485AE5D4EB10D5D61F99EA697D4E81EA998A9442EF8EE65E224F76BC741A007BF74135F246DFBDCF6825B7C0E238016CD14C201FB1232CF3177B1A60DD5ABB43A79AFB1FAAD124BBD830521DB7E8563BA47B7A4DABAF263C17B7D48B7C3842D3446607BE4AF3CCEFA6ADD22AB7EEF559E056B1C9868CD5D96C8B93C76D4675EA47F54F0327A5EDBE775C150E4C5CBC6600301FC56448348C80AF4525401DB79C3DA5F23AC66A79346BAB3E69C0124C4A74393142643597B38231D1FF68CA768EFEE5989F50720AFD1EB564E67D3B50CC57011F2E9ED7708451E9AF3F31F7DF67C5611B61D53A30FDB91103BA0E77606DF9EA51C44CE84A203971351B5CFE8FB8F2FBB4A85DEAF7C2E49EA9F97F52145A163A3A296EFB6B19652FA929736AB9B7206120922F9CE7374988CBED34553F7B77007363A5E839AF7ED32313ACEDE4DF93BA3A137D2C447916B3C012F61A6F3F29C60B21E1560144AA745CD7EA5E5BAB2D4C870CEC7C1FF470541C20AE9877FB105E3E810635A84BE1ED44CE21432DDE0A723ED5B6B8D15B2BC25943749EAC4E3E1377F059C746D380421A7AC2E3663A99896E89B651F4582A1C00693523AC8035A9F40B9FBA35AE41E61E6CA2A0F99BB4FC2CFE6BC601FBCF8F6E684547764FA3575FF9C178BD9D95F382AD53908B852DF20D64C91CD6768A56DFD96C98441A94D9D2DE773FFB8E9A579F0141658F0034BF32AEF2E1E633583153788F9F6B4A97FD9C97FE26447D56F257967A07AE1413DE9593942094AB482CC53F847C8E31836CDD33A04FDA4740A600AD6B36A47F34F73CE47DF17C83FCD389E565AC79AD8D452B59738987E6E7D28C80226E0E7CC9D70EC56873E80254368B75060EE9064DFCB7CF70AE716CB2C3A90BAE2FA4152685D5AAB0B8A51CFC562F61624332C50349EDDB84B3F439B8B5BC11E36A557EEC316354F63F79F61D78A11D7351DC58BDC195270EE4B54CA697E253C86924D42DF1D4C44AFA208CB9A1449791E135E3506758A752268AE3351407B873EBD4ED09E7E6567512F6EA9AD5F46B271869EAE279C60608A97A5B0C017E9046AD50BF5607FD6EF267E5B2DF5A6CBAA3A0034DD05BAEDAB793B28DA3B261164F84920D2F9F407CC4E8AC70FB83CE01835AF84598A3D96A23D00A225555AB8B84B6FD7BCFAE5CD8DD54A0BD8D2C7424197851B921C7D6F00D1B4A60988BE12AC4F987FAD45BCE6A140C352E832907508943E909D76095DD8D6A2EEC78779B76ED397A1E4D465BE3D407EF744697466AF9071C6B44C80D99726BF74CC38E9D280725F4BB2BC29A21E63549AF332CDE3D1D1954DDF804676C7C520830F4AC08B3F76174C939E9602E18B91C0344798BAAAFE359A402C023B898346718199B9903C10D3A50391F08817EC45302A1577F2532A4FDBD9B9E1E233CFA3C1B1E13B0113BC42799C1A4E2112441E17FAE6BA6C9F2B538650459201E2125D796C2E73EA6A7B55124A80A1AE114B1F2F82369D3C4D4581919ADF8C2A74EE8BBEA4B48C3B177C3892FBA95386F68746B23DC3012D106C39C19607711DD8415700145451E1DAE436D2D4EA3E32197E3174DC853AD4FC56610A4A5DB582686304A7561C2EC72BCD51EE8D0295A7B42B3FEBCD8333F1AD3D48B289634A94ADD52C47B51669A6EC56DE121D36B8F3937D40495B3F631E036E15C7D38AC33B404CB238643327058A58FF61CB95995A45D657317B204E84AFB4391D3904F89B2C9DB6DA23DDB0DDE5532359990A62F7CA5E07BCF57A18DBFA7DE6CF51578F947A0A7B22F734A776B0BD77694FC680C5CB112A103F4CA9C025E5D7657ECA1F98749EBBE028535D4D4DDB2F7F0C81A743401DB5413D257063BE906240D8339D484C32DAEAE18964CAB1463A744E27AD0C0F8CDF6E19CFF5613E8D24BC7DB9A555E063821DF48D2A2F94E489BB19819EEE18F3A44BF5426BCCB7F393CA509499449293D1E1F85C0F3607BBA01635CD6DCE4162955B5F1CBBB04752D098C87CAAF0FC3231D51DFCA8BDFCC7601A545E15AA48EE3649F838DEF1558E5FF42E681EC8156C12F3D04D792798E73C6439B4BF800EF4833A083B9C5F1DD06E150E1B3E0AB72B70D09FB44FEA424367751BA3D683D16757B33610A59CAB0D09EDFFBCFB2E769D7E52FD9F76B794EADA67776FA5D8A74EE1C46998E78CF09B414D040BA1240084719CF052F1A3E02621F64C29353C889A3EA5F85DFDAFE3FD0D9F779A1C6385B6501588F362751F0C1B3BF9C20AB68084910C0E93D08A567EF957EBBF31F7D2408E6D957FA07C175892C897E9E805EB4D9B7220C0F35BBA4CF6ECC1B7B6BAFC0EF1D581761F4A858B33458737354057191C5D41D1F0CFE1E98A8586BC5F164ABA7BA20CA1DAC21634BD0A80B563E29B41FA949A8F416CFB2437C64350D2A6267077D772DD121A0F74BDD1083DA5674DC43ED7B6FE143530E02129AA7A0621DEF6DFB5FCBE460036141AE52BB32A2CF9F7E82D29C2C350A8CD233B20A64E2F46DEDC94911580E80CCDABC13E24FBE1FE3D8DEBAF78A814C943C503B9F7A2E1C84A822B4 +smlen = 3870 +sm = 47E36B3A2E503FD4D837FD3CE7DCA95CFA48F1C074DEED403C86518EBA07182EC995FA19EE63B3E4706FCA67D412F580CC97B0AD7964512E17FC06A016C696A3F6C644313E469AF2B5E0D2934F52812CA7B149E25B3960DACCFD865F3BFF6F636B5906EEDFBD5F9092A81CA19229A6126541DD5144673CC723E699F3CA5A8903D0F1015D379048EC7FA0638F171BC0172CD88B529B2931AA937B95EBE92DFF43A5DC36546AAF69ABE28B3587B72BAEDE0DC2B62D134A3B697021A1A9E312AF64243149EC4FA46D4D6F26332A581F76980E953E3208976E40DA025F5A5918FC44E1F5CF0B65C9ED7B39A461FCCE43BBC665AACCD4A88DC3A5246C99E26C18F3D4FBA2F71B6B95BB435B810B243F86C27371996E648A99F3459EA467936309729D49984242C22A84A832FBA1377C51DC042FFEE9F7B03D73CECA16ADC1C7B8738AA5C6520F2C3F41B63F38C6C0D90401545EE062A21F5FD8A45C7374CCAA8F4AB36C13A4C8208AB78EAC0B7CD44FB4B7985CEC021641C9B9776807692418A1D9F3661C0209D32BEB387B31B72A39D6C9280D1BA5901F11657AF3E16C23A59F07BDFC966F3A70139370F928C98F6089CBDB29049616D4BECA840635E4E8922820EDF3168357020A7D48EEF47309C2CFFB78AF891613F0240AFABF539D5F17CAE8D8FFB85BC32BEE1C46853D3F2350F6D1557A201FD4ED1B10FBF70C65E54561C6306667F100BD8B7DA35631AF33D7C23E9E3EE6593AC5DFF8994074AC7F77F27B93146C62B1995E110F42A2A0F888A82977D98F4D01818D15E3DADF38610FA9A4D8429DDDA93D495413CCEDB8EBA920E405E08682E788148364B05C13A5FC00CCE3655A54E7A7EFDCB5309A14D74727A879B374B930FCB45CB7B6A73761037B8484019998501905327C467538FE8D739303AB23D2691A52AC520D200FB5E733FD4071E1ADC1E44FA19523351B1DD23F9242E9B05768527DD625CFB4D39557513EF837C87A40DE65703BE2DAE5BEE5496CA37CA17EA62357322C388D98918293AA3E2106F212EE1B76849AE044D7D794A03F86A6B79F65872A70A8951FC3CBB2A8B399E71FB56ED4B20A05E6852CBC1009C3B1D10DC4FD76F89708469B6A2F71EF1693E582C4901E87F2ADD6DFC7FC3B244D92AC2FE4508BCE09BE48B30699D8996C46B62AA8CEC6D01751648907697DD0B3E23FE1F871FEC72804E686247CFBDDD6657E36D0EF9C79596A0C5A478E75ECA23F9EB37FA85FC46E72C3B69207A174102A6AEC1778B447A7E046886272BFE39A7EDB4225B314C9723A41576153929FEDFE9B8D75A9BDE442E9B396CB473B5F36ED48D60A35415A25312D383BDADC3D8CCEE8DD0946165B2A73B1BAD2211BAF1F49AD6C80F7EB97B990DAFA707484D7D258E1974B6B945D38B3B3A332E865DE3DD27D3B92D0BB58EEB089D1E798F684E5C84027F22F486AB92734A6FDE8E4644416860CE8D3770BD82AD356DAC7958539AB91AC916839998ECDCC49E9697B789267CEA6BDB469F506FCE5C9C4F5FC18CA49DDA998A122CCBB344D653208B9A8ACDBDF331869D192CC1DAE84766FC820D0E3C29D5E26FFA74D662CA603855C7DBDF35EF0856CE3A14CB9E7196CB1B738E828367B9F725435A44BF7161BF8E6804EA882EC1A86002020F5032E1A18696A1EF6551BEE5CB60C2B061A379F9BE81EA24B0D8FDC5E93297462AFB8A9C50182069B9F886460B3927D3FC39ACD0FC0433189F59E642E4C8999D9D605F810A9BAD05F59ED6607DBA9C4E1A9DBEA09E8D94E3669FCCCF23CAF48D634F1F428A747A0D66E1B1727D8FD20809080C86AA2CDDC9D951341F35D3F52D777DB7FAC01E953BFDE75C1B82CBE6B35AF6DB413F0017519856D251AF41C2827D0B86FB79FB7A69A0BF6595464CFE01038440C8EB71B46DD50871DFF51E9DC2B940D9B144A42818030EF0424059D1E308584647DB61053AE171A8418D1919E5D5717868ADFF49443D0AE0642F7BC0066942F00FE25316BC61FEB4EE295BCDAB94A09C810C056DD1EE126D32F25B26A1915B5E33A8738CE0C6DDB6C1660AE868DF49DCF696DF7BCC820957879570B1C464B6E419573D976124FB300CB9E4F74B150E2FE6C9F6F59FAEC1D2B182AAADD519D12AA2AB8151B7E35EC481473E004100309D414D6A7110185CA7ACCB284651473508887510EFCD607C7AA8F8D81FA1EF8403C0CB291D408AA70B6709CFA0442C3B4BB2364B1077023506F2D97E130FE26AB42A7C044B3013C36E91A6AEB233DFFC687911E5F47E34897C98DDEC8F58AA0C3164DA30594A0BE9630705669347DAA533A8A0AB64717E01AF6812EF7839604F42B741EC1A2D8C98033F190C16030A6CC81428656104355901F43C69902F2091410C4C9D5787E9549E7F78BC92BE33919FEBE1C505F3A355668BBDAF7248EF11D132125F55E400A5DBB7D1C7C159F79B8DB8852CB71FD8A3FFA68B825B6E906425243AFC490CAD946E3C711BD3B1F9450CB83FBD112D707C66DA7D8612F57D93A341610EC8441ACF0535FA46B514FB5E840FA9008103766C5B7E8E3F5618C5DA23C25FE14AA828C0F70B15A79420E3F9403D730CBF0A997006CAC18995C4B8DACC54D0584D10F0B2599E88F154B922AAF59F117E37C29E4F402A6E16B26E169C2B44ECFBDFBEEC81266B2792DB9CE5C123E7C567C39EFB304E60A0DB4AD9A1E02A0E75A89F2C2176385BCAB32B17820CF7C3F39735E1B4935507596CCEA753DEB20189C6789AEFEC2253B45D3280A54BBFB816132E824C3D9F88B72D75E91E1911AE313952FDD16ED048DA33D4E97097A01B65B6DB3C9C1AF6FE36CD75FA4B6A9CD0454ACF06FF833B8DDE24757D23A2F7718D9A485E0C61449396C463C69F9637810E355569346D73C18EA9561AD76AEE9CC32FFC694C15DA9C8132A0F2B69650CCA7BD6939F67A8104DFDEF72B52782BE5CB56A713CDB1444CEC6595F2654FACAF1502A6BAB24B75583352942403B473A62CB6AA880C4E0990FF5A135F7AF51938A9717972028780BDC9BFA02B5CBEB6361D46E9718638E218156757A24DDE1D38DE01973DFF1A47A9BCEE09ED2048B746D989174FE88954D018C8A03C8EE2BAE8D4BAB5721EBC7B8EEA65B60BB6EDF41431271626B0C114B9779599B6A356059D16B94860B2E1286ABAB0C2DDF24DE0823A6F5A8E493BCEBA236E14D5485DD1FA53A880B86410506033580283037AC0B86357E279C559F140055D38454CD62E6DCF93EE1DA59F65AD2EE06EDA715A8D3EDBEF6B29BD22E1C2B1773A7C32221367EF98208E044975352ACC6291517D13F6287A83A3D9B1192EA8E631648072D510C5835724992984068C201A2EEF141156320B978AA1255E9F1F1F4EB9115D567D521576E45037754D9363039957A210B313F03EFBBC65104C5B6257EFC9DC554F476FCF8BC06915D87C0FD8BA88322C4112D85C3A8CB23E830795A9B263B56DF89E339F41A10987E0BE568DC4ED049100627688F317C083532C44D2D554817C1656E09AA352A3164ECCD067F4E0E21880474A97D8C2F5E5404410DA7D618A7D494A1DC3B3C7B926B7EAB7BF383C97D4DB963D907AF6274850386B3B09D9DA79AE9161229C694A7B39533CB098C86E6EDD7E27B0B1B24FBD2F9E3704A72D2FE06660EA1E704B6E604599CF427935AB10E0274452E5D2C68559D0B855285E95F4C18C5115C0E7BC2EFA481B2E31C815866A800A2AB4BBF52D3BD40AE3B27E644704C8B57F8BEBD4CBE3E6818005F9B34F7CF187642E9E8C28A4021EE7886665012740B027AE4A055F974C543D8F0D4A9BDDB8762B3DA27AFC4F14233C391C519EF2C465BBC9FEE888CD3F7447A7D1877063367E3F588D35C9EF206C7E870CDAFC0C93A0B0218F964249725F7380C5994B466DE9E4F7F8F7C6E2770103FB9EEE188B306DCC812A20723498AF236C8CD55003536A7E7B76085058DD5F129EFA4BCE99CF750823B19A64B934524FB8BE99131FD92646D21588705AEE416C5F412A79E85662C50F78620ABA2907E4390E9E3F57D890E70CD004EC0EEBF1E4A3F1A183706E53CE1A5162D7AEADCB0559356A88A9368AAF3F2187C28E707EAA04D1F9AC5F539C69C90DE86BF171293DAC7352361EF83F75CBB8320A64FBFD06FA88D4E1D16552E5889FF40EB4C77C1BFBBD8253E9038187AA087A64D741BAB79B01FADB962A65ABB4054C5D36366771EA25A2BE2BE3F3242CE5255277D2603B3FA7E27E9E9593E61ED5B18BEEC171000732FB1D9D9AE9EA00262CDACF7BED20FC4CAFEFBC5CE57C529ECD6883DE41A18B06E03E241B0F9BD78672A7FA79FF48536B0AFA93AE913AB2ACABE8B866780F9ADF02D005ED26D7D828EE370A620779D72782CC764824A68E835D60750EFFABF1D16C0400DC52FC77945BE3AC422C59917C902BADA72723755BEA2C86F4A0E291C55056D96A2E26ECEC8EEA1F0D6F1B335D53105841CDF9B66C6B91C2CC2F09C5EA4843519BF74FEEE12142F1ED1354F792165112B53B28D9ED3B9E0AA82F2CDF3A66BD5398262DB4D5D842FFF2D461AC4BAB9E0C76EBC9517D9EEC58199BDC0C0F8B4869369F93B0569CCDD1018424950AAE102325F88020C182D479DADCCE8EE0A13335C747A7CAB07091F34373C3E8387A1A3C1C2C80000000000000000040B0F19212F922320F7439E492F13C272A5738FF7122DD7A6B2832632E1F7A653FEF3B8639BCB9E84F482F22A948EA17DDE6958489593D2CB268BB52DF8ED612F2317BD6847D1622CF0532CB499ADC432233B93B6F7B1866B38975AC87859AC49F91E8D235846775F9E6E6D052339C741EF6178016EDB3D0B1E3F3536667B3EA2D489F88D254B8582421A31461374F465D7AD62E896BE0857134707A70477FABC09FE0A5CC3B3F32911F5FF3806B878205525AF69007F50535DF05C33AF3B0D00E297AC7EAA012E1D863DD5DD5FA47FB09467DBAD8BC42EDBAB42A9625BFDB9FE578343297506A3B71CDC8D5919955AF4605FCB0C7164D96A187AFF65D0F6210FEF2D11BA08D90C4458542BE72E084577BE9E451B8B6F4909884BCC5D25316ADCCD0925664D4D91C2E56433C1B68C632B0CA56D856DF1EDD5E113D1F026B30DAC4FD648A504F8F6809C701C97BCAC2B99286CEF5C1C923200B1BF6141EE1CFC51C5E14554BC02D7E058970254D2C02948360ABC4DFB439E66946A8AD615147BD8A6CB0886211E8B15DFF3C72B6F8908CE56BBC1B40E838103202E9F188D98E07555DB61778F895F76FBD838B6D14209D28EB393668924AC0E61072CBD9F93B864904FF4302DCEA131B2CA16BB04959ACEE096B1963CE07F59AB505FCC8D89FE08FC58751965F2F5CA753D76D58705652D3B1505E0F720EDE3142DE9776FFE4AA0C8A25E76C7A04843377C59F1002844E89189E22F621467B813A98BF07540A1649264F14A6844D65692617F7A4D93FA9A23829E256626 + +count = 17 +seed = 327CE565CFF6CD9A25EDD84F482FA0758B78CBC246567DAE98B818314AE28CD438E339043EB3FF16E1C2B4B104A717B8 +mlen = 594 +msg = 576289D10AB03D5699EAC322D349F55C547101E4424BFA43BBBA3747B79F075AE1153A7A0AC8BB51D24FC46B7604E42EFE4343FA34AA4EB16D918F25E8A4D67C860CCA3F7480E1221ED3AE13A138F079FC252C6D7BEBC55CB81B86E74F339614BEBCF7E8F4440DF8678B01A4A41B3AFB1D112FE1C4C8D8C6BFE9D3EE2A335D477C60FBF43B2E5FFFE1546F5172EF51CFFB2A772E1575EAC79B24D49FD77F0BE351233E57EE6DCC7E2E29994873ABD434D34ACE83400C026E27E27888EA0BDD1BDE5A3E55AA8B5F2FEB57B8B0A96CD831906297C8169D04F15843A3249C50523CF56A4E19492EA16927DBA8759B88A99E0D20820E51FC9B6A6863115CF05C5BC3F4C869EB5A87124DF5DB102D737F3899CFAA5FEA4DD62DC4FEDB1AAFF67906ADAF8968020EFA5B10190F70E5F2C0F0457E4341BD449201D3A80AEB791254EC1C46DDCEBC3896C6DF702509BA62CD446D275806438EB4C03132B2E6BD01BD2F832D1D3C053C48C5A9DB1C4A22B130C4C9E96A2BF4C2A8F7DE0217A52D9AA5AEEE5E6A49708237EAB60B4019A51390C3EF10572A73D436875BB8D7D78543F96376E4BF3BCAABB92F89215E8D1093F3B287945708B5514BD7E62654D3BDF34B29009C64829A0CBF33C54D7AB0E81B81BDDA93028B341AB1DFF3D752DC4A1E5F9636A5C46E137EA35919D99E6571C5370C6E804BD2E2ABF566F035D65CF8F97E3E8F2ECAFA153BC6D8EC2831667A37FC96D1C2DA40BA84D0FB041DEF32AADAEF3F98CAFA957F6552F79D28A36B8BA20A9452671DE1BE8AF5D66714232507EDB9FF657F3D7E5FA7320FC0359A5F99280D446283BC +pk = 22CCF583BCF152EEB3FA5A738D87512C2F5EA67DF073D9787539E75872DF300F5744156DDFA47B19E565A2D7D3433CCE4C881CC25F5C7FF7C2103857F02E8F27766E0666E527CE8C63BC9DBAC427D70D4F9AE7782A000A8CB5083D878D2E57608DFEB19A7139CD3E8D98183CAA4A38FB3BDE07F16C21D5154AB344C1D46154D07B6297FB49F3970D197B367061116C6E4C718893FE0DA25BA3E91F5AEF624FFD55346E8350E00FC5C4194D1B1BD8F2019EB2816FE1B1AB9989F77D16BA5A3F817843916B1CB6AF48F6E5542D62BA73380EFCECAA68E8644B1CADD9D3387652BDF26E6033AE617C7E601B9E5795B79048F30B660FF1CEB3F3DA7C33F2CD567C5C816AD252A8505E76593E012CD9702DF05C9A6071C45DCCDF0D126296D3BCA83BF4DEF322ABF3B81B36D9A9F460147D04FFD2D41280406A812FBB1242B5BFA711DDB0AE27043C2D626C1FE21ED5541C93D114F745A2EA955F4521183C65A06B9FD1E28B1125659CE6A756AC8526A97B1232BC156028E17C914B9B3C40CF2402E01396BEE2D033F31B50BCDD61909491F4348121E86EA15AA35C5683AC935B63074AB904A1A8F17DA306622A9E5B7CE5BECC92D52DDB653E8007A8B7250DB8898C02A4C5ACBFACD2EFD774D389D483B5A3C8BB000AFD472CECC69E54B92AB63B7A4B82765CE89F20FA0C52911C0A177BEAF7A1320A9D47BE831CBA101714686C4CD55E2D630A270C9D9BA01124DE22D0F8102395F11C05135D0FB974E2655B11E0681A6B9FAE787B9841DCFC296BCAC43C42583784A49F98D839C8377E35489306BB81D99D0FD1101688242C52EA68C4D8615C1648C1634C3FD84124744B6C8E1965A1B83BFC2ACF5FF8CFFD7BB54BD7B5DBC6EA7EF8999835709E2BA5550500BA64B368819C6EDAD03ED51BF02038C209A27E78F939D1BB09812D4CEBA92E0A89D03662DEB93E61698C6BC14E5E2524BDEA1AC6A63830DE004F9E5B8F41720840998F1CAD19C3B10072D7614820CA46F67FA32FA7954EDD8DF88BD9F32E720C5474B78901B9074E2E3AD8EA3B5E520E8A633AB040A90627265F8AA5FDF684554DCFBB5A6BD7C749421B4CB4D698D2A36326F2F8E423F94D8AA79A784A82AE006EC7082029411783B51B5AA4AE3568CC1156F346233C767640933B1D6F710122E2E5FAAF2944ED41F4CD590E9ACC1BB65F893DEBEF9C28791CB87EFBF3B9B5E5EB1858573659BFF583E2BF835FFFA922904020D3B3E78ADD3B25956DBEDD974367B6BF2BA81B351F097AD9AD80C6A9964BB74FD7B48AC22840CD045EDD850528D76CCC8867B2B9F58C70AA36DD27B0602AC748777F9B8FA5DAB48C8BA537B6BB1E26035EAE3C0060BFDA9DAAC4FAECF2E00BAE3B8EAECCCE66BEBE1DC7BB1D560E254DE1A6505F4EDB7F0FB98DDFF15F87D6FEFD23509CAEC6E40F031EB1229D4F52A4A3673B821BFC921276FFB99060A358C2495ADFD8228C0A1AC6BAB996DC6DC3896E5D7B18A5EE581F697F7C757367C76FD0ABD6C88F2C5F68787644B9FB7AAA543A36ECC2AC6A525268322BCCE85E10A2342D8E2DF899F662EF9CA8033ACC0BB1739C51B7DD0BC6876020ABB8784E020DDB8862A9F678090CAEEE51086AFDFE10C5C0F4D98DE6197B2566D83CF256B1EBCFBE46543AA754D77BFAA02B82207F0CEEFADACFA39C9DD30D025AF96282E1E7B955071C4DA37193C39DB18C2030EF649664E73E870B8E8F814D409783A070739B9153C329E68B89BDCA0BBDBC3B347C5CD25AD72BEF670FBB40C7A6611CAC7AD93C4E8A9A199F32C1299CB6E610F615218FED0896B5B34C7011262EF01538ECF544330D6B2779C08589DA89B7A5694DE610F06B155C710B2BE0CF914CE974C9A69E789BAECE6F4101D69421A50D13438B04A9AC65F59F6E6C951FAC3CC464DFB59168B6DADDF90D8859E8ADF3F80B443C442A94F51005F8173A9A698F94655203490BDFA4EA7AD51DC990201C5A92D081910357E2D4E85D3785DF8F6B84D6940FA4B737F3BE6844F45B5D46AFCB3BD8EDE6F89D25974F17B7E9641FCCDA33A2E5A41836BF86E2B140F49CC87B47B3BECBD7954C84F2666164511B4D6A07B25ED8D477BFA9CEE1F3D762215694C8C42F84778DB159DDF8F937B33C54A3999BBBBC664A833211163C73AB5C9B684C57E80FE89786C9AB306B9B1B1747AE7B3613629E5F09ECB83F147CB6005D5207F96B797653842E560378C1795980B628BA25C7F6A196F05FF8191008F6499ABA4D808069B2D78D3D249319AA9F023F68D6D4830EC4748F0D86CD68710F591934D199A3DD7CC233246CCB87CD95FA26ADD1373096D8466AFC6E9A14FF13E834653AA8AEE3CD4868F8AF61CBB8A43E461961FEBB7B7308E62C25264FC3507CB1722A95C24A416079F136C29F77FE6D7E421409C9B5466C1B70A4885BB6AAEE1A3174CB6C7607D809060326B87E78E7C86EAF07E035AAF6AA7FFDF22DDE36C08C3B0605198D99B2B483BC759BA11CC8391E61D865E7A79A32DD47D98A7F3E1A0AFBC12CCFE40022B37723E49F409068B42C697D76C6B9EF2E1B0A580E2D93F5C8B44EF13E1435837A1E5D8735C6D09DD1B75F0C20ED896AACC4109C6044F0A9D055FDEFC5004DBA4AB643A64A6081172715998E90F28C103B6D3AF2AB4EE082375044D7A47A197E3369B79A419DA6724F3A1B61B311B9F38D0D05303020C84FAC7587BD80D7D9F9CA4BAB1D526E6F5BE69E98130E01260E30425B9B5C5FA80E961B +sk = 22CCF583BCF152EEB3FA5A738D87512C2F5EA67DF073D9787539E75872DF300F7B8CD2E97654627525B5D2C6DC28009296D96CADAF97F444391FC9240D13B2CDD68926A2870B1263F51F022AC552EE969D423EDC28A25B4F3F27DF5172DADB5194EF79A73790DBDC05BCB12F83E92D52B6DFF1972B9766AF308B23A9AC1A348677651731306460787738518203580832087568337760118167583608712855501825680702574431025818155325201757108336282435840866286834363582240366471052021623261408351371356135717623567466840813428770165220030378166207214018277407072161006047402115484342315363566537724263363422458358655880775287711482257160521643742143270887107041574605681716071047113158060526365480310724344477630462415373604506073028218015641344442400467838070448428618043538723411126411514106234265020457618023016061234445183868371136843153034715486248760322322534537627303075075305707856882458221516375475255121683302701516028107366211384124128260872307688724755250203785662142445045455405077103477586167423845680604180451238533007676554803538823844286623110343372357714243182332337374383868175057083683465207870881131245852280708266402060725233532112833587178812805004708856013121784583700308431274262221327020537204435508125603613741712401534633448365574612437756714167758512218121066861431441483315684823703201800122116620470054305604216047327336002028142750174617006537208688180788014317586828664772784010281216461286063782573615710130371132724241070207633805072772138786200576068534837815001885606801655577338068016375473670353805860712384825287271553525020864551171756375115687604358015355485046363738428131547238714137262301541078275446478127603628385706430632351661287322827640782454085256838443041815155287641421552152242347712228736475585150752544823427834520358735205647032153006824445103287786532755003307128085403025134452735004576825513808804134344773824540617248241582748844626806540251650520803232727267528233262114886143271636437633575313760418461458011304725285652557128687813607733678045686344067868208868728467814016015403621061802352671062220241030212363885702056066687117021713366526202142412380146874760288177520756144861261085327065373636311335335306718886857055882124775605434755623416187211385118340212278546501355087856758382286887684370602381118162773871812880073135430345522038054614033586265631303815736687863285438532045857185542744268410462401720526384455522304626378220158068106366785055162344726124233770735381070366684230515053080043703382842357147525587814634476725857442223633118273481784271502040018682255575324245488261218600540613354860345472611150378618713615517824165324842745274064524041723471378107621132650300816675083626808153748645784838262147820810505682831718442367601057644172330852136614718860722113050152651514155084655283370657247423520412057672153165413526610727843007768481030048408551045332268844538733502065433268276127264143708853757415503211321137676586771407732273878324033581357275722434886628810555733052701685188758347433150712575554652317118363773178668081574713862604518103681117542814405760853135044553532120154774686735816400606876622372644333163351860582227876156644031808832567242672445EA16370977D00F9A92EC2A3B05771D79A9875193345E2AFA83C160C4E71A01FDCEA2068443CFC183BCC4AC8B856085C962784CC4ABDD9EAC6C0E414730385046D44F6A9026D7D13E7BB9A32E8B34510B34379D8AF8E5FC0AD16715D2FF307802164577DDF5671C6C558EC34BB278B5718C2745DD07E9EEB484FEA6E6DCB005E195E77B2CC8B01E50CD5235E84B9761D1577DFBB680491233B81DC7A9790995401865D388FB4F14902FE7DCA41649896B90467E36A38B7FED50EB5E7E9E8739BE106A2B2FD1047FE3D87F449AD679D3A5D7FD49019FF2191AB14EDDB9C87A8EB9C81996EF6F41EBBF8C499643E1CE9F86CA881ABA3E4E402379012CB22837B9DDA266B2072BB2F19FE0F746292A2B929B4B286C1C94C2E5E77248FF8CFDF42350DA0FBDE87FE05AC7C95AD77211A5479A4C83756932E9DC64FE959520E5FA5ADDC0EC5C76BF120FDA9C60BB9BDE73E7CEE43A35AA2899E048D27EB8AA0D580208F107EA906C67F2845B327CC7D954114B045EB3596D0601FC5FE1E03DDFCA995F0E18CA612482DF6E350D5C555B6215BBC321C5FDF1FC3BC9FF109D60F7FC0AA42C534E72CC20540F18B65BDABD554972A6FA481EA3EA74710B7AF9D14ACCF8A45CDF5319707E064259AAF57947BB3D5069492F9C59AA9E81D379F5F47FF2C28E2AC27C60825D49F7D498C672CB2F51BF0AA4B5A10A58E77A515F5008422C4D14536E645E5B3E50237905F774FD1FDC35CAAC312D1DD5EF5D8B62CD21CC8618F0CB1F5827524FFF462D5FC97438D9B150E543DB96D163504482383C4A56F3CB6FCE9B10A454002BFC6D199172A74BE02D92EB86E6C0A8083F198216C14EBB14ACF7DB7B6762C4FD5D9FFC8938A8D164D0FB70A1CAE3708C8ECAEBCB0D6FE741E5D2EB03C8E950C41DA30F34CF5661B631B45F5B911FBE9B6C1863B55B52E5CE56EADE5652FB93F33357720CD06715E7369BBDA90E3A1A820260C9420AB7E693FDD1C4480FA4C91E9EF6504D6F48F1E8FE7AFEF2E2B42719B71CDBAC949B4A66857F04A1FD7B0D76C2B5805E805346662AEE2963C71F203F71D68FCD1884623299B1275E12B2387B5415BD620761EF257CB58E90E16550E5912D060B72D654330B5EDFCC53CFBCE905666107B95AEE2B31B2F75415694B50ADD4DACA7B499F4E429ADDAEB5FC06D6A20A9F867791953DE724CA715D9F4F266FC473A958DF25A6BEEEB9790BE059B3DE8E989EBA9B733B271A31232EE374C34756A788A60FB8C7F79D2D35750C61EE0D15133881F08AC0047DFA1895D8EA447B1E36C553941CABD15E7814B170F17F0B444AEBDA244009640B723C4E449954A5878218D21522AEEAA17C191995620884311782912C896CF352836BE5C3FEEAC1733F492543017FA8A0117E4B2D0E164D1B703D350604963B08522600B325912CD6CA7A183377DC4DCA3311015CF011F7181770AE52624C113653FD99BCE201EB15DFB290EA72116130A6BE0D1E41FF44A2A7E8ECA94B4E3C51131E0E464915EB2BCC99D54AAC60565452726E5A84C7801E38205430DC99093A361259A1C69C97C4D1AFCB2FCFC3C28A22EEC062BAE5DD86D0F0085874DF3112A9D870E1387C8DEC88A586BDBA6B242354D6D439A88905B497BB9266A337E1C501A053E6CC3F8A58154E6C7B27CCC5509C9D74E49B2F07CE8B194D1D6576FFACFF176AB78060C5AC13875BCA00C1FF9319B0412E18333906F3E01650C079B1AB7D6908EDC1121A199CC49CCEF025FCF1DEEA8FE5933C9DA6E9D1E0084EF62CF5742B2C1CF3411569EC5508E7DD9DB65A4182E046F1200AD2203D5ADBF732D0A2BDEAA287A5E55995D3323A6A06A3B7F2B36C0D86DE98A6FC3339D9DCA26367F77E6CC1EF80C7EE262BFBF3473FBB65E0AEF232135A2750C86F980F6DFA9901A96961F05FC27817602EFAC6D4B45F8C3CF94E6A418AE1E93D8510436DCB81352F78109BF16694691121478D0F21518C5639C0294CBFF5EC67EC6CA00B62261AD30CD36FECAE70FE9E7B63B4D740D2C39D9C0F9AE5D715BC125F27E798D9B85E643E421FEE640569DDBE42E6355536D8D7207E59C89B7980BDD3861F9537ED0F2ED1646C920BFDCDCEAB758A361B0C6B1C6DDF1FCAF60ED463771ED805F2C6EF4FE351C25202BF402682BFEF954BAE15BA5728BAAB5DC034F555B339D270C511286DB600F651718AB1782F57902B4C19D987398DF30C8926DE9D62364A7E42F89614DFF1E0642DDE40EB0D271AFA9E05D0BFB082ACFF0FFA443A7630F770A67FBC87F25C3AFF1DF28DB734AE7C42A0656E635FE7B97022EE60947ADDC5B56F652EE20282B7FAE08449C5F020F4016EB151914C46D67B33329FB5E931EEB08F0E2D6899247C6D230789F9295AB6359909B0E13E7FF72051B086ABB051276093B53701DE46B0ABF5E5D5787D8AF896E5C32B75A132572B68BA5F8CE5DD66150D49B49E166A08E061F93E4B38538AD8686A9E5F5976FD6EBA3197C2224D4F7FCFB8F4B5ED0073B3574F5989976505D5409D9F294EB48E4ED7B0C15879529708EBB95D449D54924531BDE322C6798F83EECC6E74DB1EE9EF073832BD6016E0561A3395581C6D7CF4B08051CD3C2DD3E850D87FEA788B5F4740501B79F60D6230508D627B7B34D60D3D78B46E8ABE9F339E91BA47DADD72FB89C1EA08BB5833960115DF3777F4BF95C26BF0D79986D4D2EE54F2EFA4FDF558DF6BD6A359B4E0AFAFC2EAAE5D8DBB891C827232FDE98BD1A3C00E6EAE96462B8C064D5C8025EAED950D4BB1C5563B6DFCBF0C3D378A06F4624B6DC5E9AD4C2D031E206F975D277B2ED81DB832A4AB3E9CE8A5625ED260E4423467477C9BA6A5C62D51E690824925416AFFA83DB4F579B03E44AC10A9017DA939A139B99B21D61DE5E0615D5FFED57EC653B3BDC01C6934DAD6CB710CD09B884AE750ECC5F48A0AE6390DA1296899FA20A1ADCD5A34BC1437C6C4EB2AF9DD1EA82115A41492A675DBADB3EDCD59C1B9AE0DDA3EB5271D5EE07BDC57EC05C24812C372D992680940BA8791818690FEC45E0353004F775DA34FFB2297252FAB207E5112458C96B75EE92B3406BF85AEE4BF6880E6CCE7A2B5DACE4C9990034ED44B98B9CEFEB02E25329DB61CFF5FBCE219676F82DAF8493AC96E936D73A0C11DEF6D39597D3C71743C660E381186F4C4DD77A0D5631947848A2B0A0938E38FA33CE3D95EAD9B0382904E87A479A2B2C7B11BEB455E7C56DB1DE0C0F225E370841E44B8621F6145661607DD1480BFF53CB792ED9F38714FDE5A73703ED6D0B4088E5F830EC55915580851F0CBD708C956C27DFB52B8AE2B07EE302826AF82AEECD824C913FD22E34427D1BB35BED33424B3E65CC606F2D505C6CB28CD4BDC7F939CEA4F0A4972F051EB529822ED66D39B6872F2E42085B0E87A6BA60A5FBB0627326D9BA6B8D52EF58927F429252CD8556263783A833115E5675AD03FE1BB315B79A94A753004936F6DE2C9E4B393C5822F7D830258E04A0D780E7E20AF440726DB +smlen = 3903 +sm = D2A344DBDF53F5396256D8CF422B2465DE9C781BCDA01528B961CF26C583B2BD0E029CE3ECC8A0D5394D969A70C8321D6097FDB696C09EC34FD0CE322C90B636B5D42C37B21EEAC8B3529A909E427041D64833313D0153B6B102703A8FAB7A6E0844F5C0F6C8BDD30942FCF2045E831864147BE10594CCA5B23F7CA463F0BBC224BB97858D38A8D5AAC255FCB907B22F0BBD1EA7560F5925FC46722295EF131D4AD29B2CB0F3F40E7CE74E3DAF6D05FFE500BE9C06A256DE6CBDCB7A23DD63DC2C426B7C99435E86E7428018EA6BE78B12045557197C6C6DD563FF4927881A71D8621F33CB802A5B52A2AF6DFD9129D1419117322E40F317F9CBA08C5FCC8E9100B53077C4A3EEF956BF487A85AD944C17017925DB56615D96866F2F68324BCCACD7AD4ECA68A00E08B73B6AD951CF28EF95393C7B776648CB8F9969F80E25A56A20BF102D9602377639E1CBC7A8D25899B9FBF65B6AE91A0DCC66A3B5177A9F79DEA3A9D64D710F8CCFC4BEB841F759E37E6E7EB43311B7328578FC6F2692B6E599E9087B18396511D1311D3B32FD347DF134BC288AD3B9F8CC81E3519CFB6E16EE618034AD9A62F3D9B1FBC379CA12548B8934E3042B5093D5D579926747A6AE4EF607EC846429E1512B77B600B0D59E08E5F596DAA1353BD7797110E051C9D0080B4BEA36A490971398FDC6B2707A391C37BC72F8C104CD920969EE53B75AA3D331E20909068D638A846FD66BCD178340FED3CDBE33F128846B90E9B6AEE0E030DDF6C35436FE220EF6EE03D3285658E10FCE9D8C5B947B5628372BDD333E15E77C3E0C3ECB75F81E19D898092EACC9CD14E6D5B887E432027F3306D47EBAEEDE036CA4AAE2754849A847DE22C4D88F83C1F6F544DCCCAA99E84251C38E651559399B20756288CD439B32B9099A4DF6F062AD79C8A5F9CB9406BD311BE077409CB07D647AB92DB88E1EBB708872E4EAF2A4B90787C0EF257E753CE96A039ACEE899866E585E73BBC2808718B65A06DF811B9F61812A7CDA9F9ECE91F9A96209E8D1A5E1701D36CCA09855B4DB52493C9E0638B7B1C502768D82B265469D54C39B898DA8DB0A217322F6439095BB4A106B3E7003D434584C537BF9F2E845AE28783F0323619988E3A98390FF27546F4D6119E4ADA99295D29887DB285C6A346EC364AF2AB7605456C1200AC8365D718199EC8CBE739D9BD72D5E2B7F300ABF66F1488DDD12BCC63AC82E548A5BA1D9FA6D579A960D5380E5795178AB2030C61E79EA8E95BAB9F9CFD1384462D0895C447AD4D47189B7B6BD335E5A3621B7CB7375EE170F9C5CDF081759DC4DE943C3634A4A5A3D9FE6915592087E6E1EFA9E542BA41F9129C4C2999170C3BCE141B01B1BB24FEFC79BEBD402D7D6E4D85287ECC61A58F215A1A084C498B7108437883C9D1E7E95286768C31FAA30C66634A52CB43DB290C19CE82EF9F8808774BB915B2D9E1F9418C90C172E18CCE7236220747ED3DB5547B1CC1F2B6068B6D55EA9F6F8D72D2015CFA8C12379C67191E9CED9C5535592708FCAAAD5838F496E5F03D4CA0FAE810E40F39B1E13378D3BCAD20247E3132FCFF412CE34C3CD89D3FD63911F701C3F1B513E92D089FFD6972000325B168F82EE0C325DA149CB0A357220FB092DE8ED9D9C5F3D10D5EBDD777A5CF9C72E17F54C05BC3EC23993D1459557C1539124C210B1C3C8D63C1A5877A6DE9443DD0FD9C08CDEB1BF1F404D07A0903938E72BF17E78125AACAEAA2FB4D21C32CBD59A3EA4BBC80956941B61E389F69E42DE1F4FEDD3941A5620F18C30093186C8EF6934A571EE501134D3BD2F96C192D76405C250B723C4DC66E1A86E307E24895ADB93A59340113DDED161B2DF9032EC875AA9D37E46670FA810FB27D62BA7F05A7030A18ED65892A467A231565BE46C183BFD10B53E349C27E4B62141C2D395B4FED65F8689F11997BF6C9B606A8D97D798C12EE87E6CC9D0C74E8F9438A99B040E978104DC2B68CB3C81D71FE26D6406D3F313CB954CDFBD92AB216DF9CBAC0D066B51522877D1670E32A450AE573B853E432FBDE88F3CCD6B76C781856E493FF767DB942CAF4A8A34E7240161107B32625A1090CA2AA4862910DB49EDF997F3C58A0931C2A0705907DF4D84FC440CAF34813FFD87FCD64E196264F680C298995DFC7A9D2B3071C15E3BFEBE4EF4654266B1417C33A3F7EEA3A762C09260B02A7809A3624694FA7D2F31BC54E56CF69F8B51175A74BD830E5D2B12955D5DE2DB1F2CECA8F7AA5DBEA75230163CF434B52CAA405AA667525E7C75C6B19DD4D2DBE3A5F669CDE754ED82D618904417268EB7E155345C89284E795DF40D3C4AF6E439BB81F5BE3E5501ABA6633274525772523F88CD4072B39CBB2B4790A68E8363262B2E649190709B1001D66D09B6D1CE56FA8065B3F5E83CFED0D97782F4654A9A6DEFB98EB1E874F07664ECB6C83A6323AD2D9AF3244D2B687F10CC1D3C808844332BEDBBE5E2D2A6BC3F7D99C164D69B0DFEB7C8269AC6FB635B278E5B851A4AA8C144FDD978E34AC989249077588176AE053D0E27282815FD3B5306DD031CAA9DBAD8CBBF977BC233F84ACDED6FB79D49288C35F8D30A4A06EC246FE512E9F6269DA6DAA58CCFA0BAAAFA6FDB6D66CA95FF077C668D61F3DF1DCCB298BFF46FB23C0213F8AF6F2CF14FF0D05E197DB05C09CCC3053AF48F891978E9F33E9F71F95D01C928089A108F1A07A53C2CF0F134872FC63C43076D91F06401C607E965F0F5B0F4E25A6AF32AB0C7E8D0DD78B09C7BB4690A2B380F72E66342D331036A1EAB5B66C611737369EA0CEEC4B7C5FAB3A1B1DBFBF6C822ECD8ECB378B466C8E20FFDD1264E992EF2FDE2613B956A66648D041B04C9AF67B1AB3426BF7FC6B0A6B846594DDFCEF57D8213AAAE33FC96C38E1B5455C6D9217788763C8E2A92DF51FEAC66390F3FA12B718D6E7C18CD00A6ADD276070737194D695F1FC2D22991F47A4B18DE85950D96834706B6BF9634DC8E8D251D60139F7F3C3EDC4C88A94A3029FD90FC34C8ECE6A8E6F5272D4B9B6A9B9C77C7920977B80C2B317227F845BEE6ED3BD92D73A3187463B57696F8B1AC57B258B611972E1A80023221C738B6B9C4701EC006F93A246887B8A4056619A56EBE41C5BA6D3A1607DE7EE69A58219B0F3A009937BECB29270BB508D9F0D6420C67EAD1FB225BEEDF6D273DDA15A508F21291112F364E1FC91E27F056E91C3EED8D3BE9C330B3291A2920179C181BF1D797962CE3E1F5ACCFAA306EC78327FF64D83AC7DA966EAD1687937221656FEB29D2B143B24E0AA9003B71EB9EF4FEFC77AABFCD0DB4357092C26F82D79A09AC3CDA78A9E03D0B501F4680D7BF3BAC324ED7F9785E93F71FFD1F53C4C7483E677EA13F810DCF23777A190E7B958AB9F4E35F990F8395C0123DAD5D3A3A83FAF8F3B8F2B6379EB9A3F22655B319754C40B90B093ABF110A56B602F9ECDC609A5B9AA3587A33419A34354221360FB9E56877CC0497B6883DF4E401D32DE6B6AF9A56F596265D234E6180F9B1C2E6751A3E8C8674172B5254DD80DE8BAE133D4D56113CC6112A9AD2A86560B68890E256CC1237937362C59F0D9762FDFACCEB1E103C54B13E42BD242D77FF8D5E276A8A4E527E86EC0155ADAE0B65F2ECE5D619A876D2BC43E02EE70619335DA84A8C34C97995A3B5859B0C004FAA72CE3AB02A5E2BD06060EB107FA850E65F8A0ED925350703D51F5A191197DBE53CBCA0DC22CA30D5FFD21EBFE9B25BD6EC0713E6C58B263A9F690195B2BB28C7F9A0B1080D6F81F6B18EE3F728A5A3051AFF9BCF64011B7CD7188FD8EEB4C71C753BA9A99B4F93F53AC047198443FB4634BE1F4841D24F972BD20E19FB39FF508BBA0B6941C5C932DFA6504819E3CE6B5945610D80AED9E9FB9EC507233F20F5AA0949AA324E3750FE60A71FB13AD6A957716CD48253EF48FBC9F166FA53F518E9BE81F0D2411E0EFEDBD4E4319D073936A7351345B785A9A4AC47DA128981AF3596EA8A93A381C4A06AFA7E1C58F125AA8B801D54B62443C23AA0FA485F7B5CDE7B15FBEC090FD5779782197A4C43FB31D048687DE5C22827B35161363AEA39F9064EAAE9846771365AE26E589A904E952D46A04E1BF76717CE8B67A48DA7FE71E06427DCEEA9FEA58CF3B160217B0576AC74EED87F041BC84718F50EA3661C2DC71274E14D0FC946B4ED8A7D9EAF475AA89CB4C4E844D44C7F5B14D6761B55924AEDE489F5D82EDBBE407A59FEBF727DB74C470D3C8F81C5C58E911E60D75FD91BE6FDF15EA998DB94D752A925E12B50E820C2FF0CFE2EAAB562EA59636B37B3D389B60694BBF6F51FCC8843E7917C28EC5F36535674BA96C755B75336CFAEA8A7595969DC892ACBBA91E8EB73D87E9F3474AF8BDA4954E146C0CEBA7F78D1CEAE4B0F3F8D48B72BBD0C4E99221EB35AB44ADE703770F31DD62C5B34A43C71F89A9BF61CFADFBBFFD764683E377DC91C8DC25C7A4391DB4F910438ABACB8A0C8B683B84C54DD155D5172F4C115055EC3EB1DA4C0A7ECC121183A5735DA94F78879659D01501D2891807AAE9068147214264E555992989DEC42AFD0E1F05157648FABD3D5E2E7F4F72294959B01162DF30833368C90BFC0FE000000000000000000000000000000080D181C2028576289D10AB03D5699EAC322D349F55C547101E4424BFA43BBBA3747B79F075AE1153A7A0AC8BB51D24FC46B7604E42EFE4343FA34AA4EB16D918F25E8A4D67C860CCA3F7480E1221ED3AE13A138F079FC252C6D7BEBC55CB81B86E74F339614BEBCF7E8F4440DF8678B01A4A41B3AFB1D112FE1C4C8D8C6BFE9D3EE2A335D477C60FBF43B2E5FFFE1546F5172EF51CFFB2A772E1575EAC79B24D49FD77F0BE351233E57EE6DCC7E2E29994873ABD434D34ACE83400C026E27E27888EA0BDD1BDE5A3E55AA8B5F2FEB57B8B0A96CD831906297C8169D04F15843A3249C50523CF56A4E19492EA16927DBA8759B88A99E0D20820E51FC9B6A6863115CF05C5BC3F4C869EB5A87124DF5DB102D737F3899CFAA5FEA4DD62DC4FEDB1AAFF67906ADAF8968020EFA5B10190F70E5F2C0F0457E4341BD449201D3A80AEB791254EC1C46DDCEBC3896C6DF702509BA62CD446D275806438EB4C03132B2E6BD01BD2F832D1D3C053C48C5A9DB1C4A22B130C4C9E96A2BF4C2A8F7DE0217A52D9AA5AEEE5E6A49708237EAB60B4019A51390C3EF10572A73D436875BB8D7D78543F96376E4BF3BCAABB92F89215E8D1093F3B287945708B5514BD7E62654D3BDF34B29009C64829A0CBF33C54D7AB0E81B81BDDA93028B341AB1DFF3D752DC4A1E5F9636A5C46E137EA35919D99E6571C5370C6E804BD2E2ABF566F035D65CF8F97E3E8F2ECAFA153BC6D8EC2831667A37FC96D1C2DA40BA84D0FB041DEF32AADAEF3F98CAFA957F6552F79D28A36B8BA20A9452671DE1BE8AF5D66714232507EDB9FF657F3D7E5FA7320FC0359A5F99280D446283BC + +count = 18 +seed = 790FC03F956D1301A735504075B67A05944A762E0A4BDA77BB8C036C5CF911E2B561EC1CA6AA355D5CEC919AED42A1D2 +mlen = 627 +msg = 021E9C06A2E4EF63D1A61958620C40016783879080D44311E04F2A446BCAEE5A486D17FF0F356BA70FF1C2B55BF957A59202903AE349878CB822E04275E0AFAABC0803BB6CDE3741E0BF9FCE0C5D5C814977474533DC63F9ED4F32AC3477A3EC9893EF55186728C85B03F4C2E61CA7733E1706766AEB8FEA80E233E8761B57FD5A3CEF700196674B34A3A55F68B3368B688FB1DDC976FF48BA6A98E2D66023F291A3C617A56CCBDB8732B8C34369ED11F4CCEA8FC8F673AD9FA0FD8990BEF70AF44C617FDFA096695D0C94EA8E17554F4461DC776DB2F416448B17680FE4D29B09E57603D8EBF55771AF84D8D4B9097302901C25CB6D73932E67C323D12C8ACB0E74CB89755F7EB3999D4EAB5E1B775E6B5C29D9733697030A26F3B93B3F286DB0F2DBDA71E1F103878063E77919D8892EB6A34F821B603ED4A898A9F30D00FEEF20985FEF1A7B7AF70DD29C269E88687F005D551EF05EB0603FD38745AED4F5BF4C2FC09F0604C98AE3A89E46BBFE907B87A1672DE547D651F035F392A8D4DB5E7260F43953028E312B95B9F25FFF2C0C579218390411D13D9A25F22DE4C7AA05FD11781DB08977160D48E02372C7D826F5CAC37D1A9B4230BE99A2D13CC2E9B2B17F0A1044EB9E0A2FBA376D35CDD2BC05F57DCE4BBC3BF07A09BCDE369929E6250EFDC61689466B040AEA376B09453A2C16813BBB685B54A225C49008BA6811E8BB5B3627F8C281244FDF5533216D126ED0E64FDABEC533424BFF77FE722CC438CA7587C19D965F0BF085D8692C27C5C84A9DEE53256D978948D89ABDF9842E0B765BE6A507D8630CBC5CA7FA0FBCA1CECC78D2E536AA7B2B902C4379777AC0920D69C57CC4E6032252BDE99E1A555E80D4 +pk = 6EADD24E3908FC3B2F1E4A2F42078CF3DD7BC3BEF2F7F9C5CE17B78499177B14D792F75D8C9741FFA5F961504B13D1BE142EEF84163992714BFFE2856899D5F6C9C796D69742094B87B57EEB4818E43486EF672ACD640B1C49A018419C8065F167DE0745DD2A35C7154DCFBF6151D8BC5C49AB1C604A72B77063A8DC4A7042097EFABF1EF73D9A425A4E2C1C6FBC93D8464A1BA1C322C756B2ACEF0F5728DAFDEBBADCB34A155BF28195EC3EA6A030B8C01D4A1F8544EA3B246DEAADCD1F4152F258C5B8C27C73AE5EE3E6321F05A6DB1FBEAA39083C23EE5D9AC9503E21F71B0FF3D667DFBA62CE668E207650E03264E72AD984AA7BBBA1E647BA88A9EF3466E86DBAC4FCB8772F5F892C42704B53F6B27953C86B896743BE5C15A570619796C47C61FA5B27DE1968209BD100FF663AC798A6FDA8084B67886DCA2A5C5EEFD0838606BD62423B2DC6AAACD67BC1103CEFC0EC23E363969A6D686DAFD0E01DA9BEB22F833BE4752A1EBD499F27F74BB228B4FE92FC6C2B5FF6A81E779E2E6591019C201490F549BDFC90ACA1561D2BE209ED8295CCB2CC4E1AD429798AA22703705C98652254C245D99BD2A2CC9567DDC07438A995F730D63026DAE66548A4DD0F3F92EAB6E3E7514A334ECEC5B80679C51323FB9210556BE82B517DAAC5C14508D296FEB04433516A243D83A4E893F425B718D07603E98BE10B39D888744E4B4FB940F1C502FBA6881687DE03ACD6C91D8FBF122E04B9BCF8E3526B3B1BEA8AAF06AF5BD87BD18E9E650683AEB4CF35B5B79EA78402015A8F19AE93CDD4C8ACF8ADC49E6762A69BA9FAC44BC91724626025487E83EA6EE3D6846B791DAD06231E88BC9965BF2BC329A2A045CC343AA61F1753FBB20877205E62C98F0DE8D673DDD23277678540CD29AD3926192999C4EBFE005EB994338FFC56F740DEB0BCD2278EA9BC8E0D71D8F918793EA6CAEFA354D879855519465889D6E73CA1BBE30964F377DDBC168659CF8467DB88FB8C0BF3DCEA79F9EE0559CEAB30BD98CEB03A2B6154A635CADED367A646DDFB862C326634FD641C4ACFA3862EC11C08ADF85ECD4759B52F095D20B53876F5D93B7E4647355919DF9E3691A63A44C8683896033C4F7F1618BA93FF0D803EC2826E35651D7D0709220AE064A9976F7A3CCFC0B624DB25D26CDC642E1C1161B6AE718E64B7ECC627A70E07C5AE46F8E4DE80025B7E2E297B9EED286C34B5D07AD1DFDBA3D215003467192A85F4E620C9605DE384742A56E78852CE145838EB8070CEB48C0CFE62DB4FD8E93B8A12F12232EE3700146BD82FF5E4F235010B1FB0EBB1AAFDED755CFD9C65EF20FA3C398BA0F2C2A1642A14177B4F6B8633CA0060AABDF33BCA58927CF055933C8D9E7959F356B914D7CEB4DA742A7B33AD6A21433631B6EE4163A849564C927000432183C5ED93C6F5FA607E6C1EAB2C60A72E9D4913905B48B2DC339EE3801083BBE51A17297B1291B30EB16821220B5773488BA164E019CCDF34D5C6FB370AC8A4CEBFF1E69C21DF2969D01307D2FBE53605C847FAD0FF386A1A20782263EF8B9DA2FE0A09B4CA2DEEA6798398EF0B9E6AC840588EBBFAB3C57C86A3820E94B6FFC568836ACB93E964B8DD95DC360801CD11C5A67B1C103302101AEB138125EBAD1A08EC0B67C154B5DBEFB35F3BC9AF5C42224149CCEB32BF87ABB5FB1661F49CC62DDCD031D24CCDB5EEBDE7A523529578DED94607244F89DDDE5ACB8AEA5964ABCB9B4BF383D9D93FB8BAA03BFB56EF954D3A4B1FF07421BA0B5113E976EB6D2FB3207A2EE9CB1DF815BAD7257A89927D61F89D692F65A0F846ACE6CCE7B00FA0ADCB9A13D4FA3932CA060AD3004AF58763271DBDB1CF329025C9EF20FF185B3C5A4A7D0D71E4615F3430BD79D33E2114CE4E0042D731F1024B4B6855795517E7C95678EFB1E94F2DE4E646F6A45DB24A537CC22EC8FBF0DE684B0F4DFC1C7DAE50F711AB4934D1EAE6CE39F365EEF777CC60E17405BC9D2504286258F116728A37B2E50C38D26BB93F8F5F70AAB13E58DB444DFC5D2D62A7A6A6F7F46EA9E63C4640F9AD21A80D029D0CBA9A73A96FE12818B54B947D8D19A128F57E596D99B6D041209FFF56EB2A7FDC7D24397D528227D7F4712B5510F920E39AFDEA956D08F7551D36217869D9C51F6FB7E8CFECDD9AC4427CC2C1CD79DED3621FE74D07E02971607980EE5E87CA8843FF929E4BF521AE34B85F8B2D01E870F4BAC51B505F085092556E87DA9F3039C8554EDBD74F0F5723861681D2C997AA53D9EE4BADA7FA7379DA33A86BE69460E3CE8B72E2ADB10DCD7037F9216CD3A3EDC13FCFD6605F1F81099C84A0E9ACF3CBFC6993C828AF67AD422044CB9E829910A0111AF626256AE0304B204D2383929E40F3CFEACFA1C80D86A8F3980F83CED4C45DEC0ABFC9457B6AE0972C6B7CAD2F0D3E63610EF4354810609E15AF7B3BC30945A0533573122A7A86419EBBFE69B8168A8E2D35483D039F4C33F76FA330B7FF52B08A363066DD919739097F5DB5AC9E4282D7F65DEAE58C69CB5D3B2671CE0AB9D610A0BC5A176BAED932AC28A7CE8C61C1A9AF563485CAB8D1B6A3D20A0B824D077D5FA824CA87EAB82F349E7FBB8E6778485937CAA7889A1BCF4008B435B9B65D89A2E05FF29606E1FBE89AAB979B0FEF3C0086D91988F14703CFA567C19277D3EAC39170BDDA07B22E4280E4E5BDAF520229688F66D9139BFF4AFC45DC276E89386C566A45F3ED +sk = 6EADD24E3908FC3B2F1E4A2F42078CF3DD7BC3BEF2F7F9C5CE17B78499177B14A8B28F11AEFC3D7E0B1C12CEE0C0F4A6F1B7572F4C2EAF3A639AFF28963BEB605C2AB14AFE31131DCB2D89AD76E99A708783EBD955510F6C7E42F9823175212B42DB292A5D0ADA14230B53B173E5FC016EA52580CB3BDD6780F695762034272D75683867522517346243606705438725325508182168423133205428040680355461051442121718088662634014631128445158561744010544582616140004313531610680121134531274255418768305325016655235134737151766068386446121225057456008863435234544030056873255831672877155321531452734224761532688152431317506642006538052207803441830253020338005332304217876428133773837224200411323713346023610228103815372048730737304447186036538685246682847808531084566274138416256446120627145571664102361412237461337370563366037370728460720402004018023120207208543053103618524860488621061863756181654150106330875826064606835407028731272374225563315574533887621838288435515123785316212010308415538541800217415185626163826312550317523170024261121776471861643086468786348232782474258375084158567501804252482562070358508434722832030066233746205602500480263174345215474035318451823584672025172024375484354612725715163353358218578251434081871541720052584305226027607702662042866122108274602477211786103531227487120304864638382775248331870215546477718763380210181412875254570877656761083301203888683010753333745452738635306736486367223537225241152466818477162580351875073747360104252766057224744175821568638151285554537165488813853016304535030552254211744860138655654777487531331040142541014733073866646141234427134587317082400515666257880682425073050701355704181137846660367246777422476322304086686220127217743548764507021255647654863200006821455170857574613034505525355662662442056103136213625738662315320840613765066846306450253566013188534408201864862040870538756136635245311006358038525445455165827260014476032870028410211024604164634380502623515888837242845226587242487778761064644371687507783166166826132361160580034168811460132352563035675452141174011877710355587052264821207785345434402440248028185586658847560527172484826380015173845804020747022426820885272585151862712777726371570611036532028763607810224800267076131876518477367644423165743801640046487103877812486448086436222303151384303506476604670112576082476824474363825877562125401250806850024123064288202645588336457657647326510486673177813500727232644583158786180121703727262812505674844316666745725218137133316152103468384766135620128748244012767310654233541113188251462775812164471778585285645578440447605283665865856273772523155207348726850743265084773360772660484264831672580384534667767087434814851858422162704838473215110803118411004787473025766502557617873542612807217700444051000068520120424857324344180616001208570017536257330412077470362724477125423325848704283806337008734731006837883206642861052815242812404062641127280446487473384752110275403161018835122050267488834871352358870146086262438068007845842136630384668526783477350133876001868824348662331243653805484468355104561627665445688176040184385818850144200111835768428863626525265780422882261610124188128867012687747045376480182A31FDAC5309AD05BDC2A36C276DF814287DE0682995160DDD8563D5F94E77D8B9F76400A4785E246240D5E898305C198339B7006C8E64B7EE4351BFB06EFA3BF02109A7A5BB667C2CC757FF143DDC50B5BF6AB67D7B400CA550A94FBC99CB3A299726E782AF767F659B535A331D469ADD9D09783AE2CF674DB4D2A324EE25863DF03564E3730E33DE969AA44C1042FA0597AFFEE0109B6D699BEC1AD380B6AB6364FD21B0A7FC5A8C9F79C407F358087DA30261C45E4F2FE2E6E83B5F8F7563BBEE074D8E62F436DA20AECFA7924480E72339F360D5365A6EAA68DE1A4C8381C40EE78513C8C362543D9628457925358161632F0CCFD9623B8C34F0B0F6879A04D2014D7E6D5A053226005F82B824E430045409442502A6B7C2DBE71F77C66A3D2134A9F145616EF6B50BCAE601CBF03A7F8932865EC5B006E37649D99CFEC511A5D9BB9104D08670453C05D4CC6A92211F3A293C12B7B31471CBA254C65F7FE122B02B9C02AF05BDFD22287B7D611283817CACCFB05924962B0776C3FD472E9CB6819347B5E60BC1800E8973360CFDEED0682DB01D136A60E24322D0A98AF141B5FD538AB96255E3BE00E3AA2342B24C3838346417FE2A6CF624D48D792DEF91A1E93ACF10AC0218BED1B96129D07747F5AA0F38BD51CC5F21B2FB898136F214AE7BEC05D46DD0F579BF88C0803FD25F0AB4CED876A2238314CFB6FD14DF5DA2E640ACDDA47293A0C68797E1DE5CC660CA6390B8289E22EA20F4C4F80B52C0D4271E5EFAC0C29A9C78B8848F6C7D429AD31FBEA9C9702379684D645E599E154EE9BB4BB37D170CFA9465F909E42EA5AB457294003117C3F8D8E8CA705F031032EAB32E8F25FA7BB92B6F1B86DCF811F11E4E5EDB10FDC881345F0BBB3A077455FAEB904EF244DE4118F54797C56C3D853EE7448FF51AB833B674F9DE4175223209FEA92D7EE337300C2D5EC4448DADBBD639024A902007111D5755B6C1D36968D60779EB3740FFAE806FBE83A19EBEB4D4615000A09EC794137BC37817B97D40A1C535F3397E412BE6E0C0156EDCA8FBAF560D9F5376EA8366E68B2A9E2BB56950319CE6FD3F7464423EE41C88A461A29B661432AFB8DC2DC4819630F730CFB060D577BEA5BCC7E68FA7D9641B488FCC76242AA51DECBD4B45C5C051877B7F21D3899A2FA81FF6819AF05EFA601E1A8697557E1F8CB27EF8F385A0549E1856B27196DDCA0568B0B7C8E3752EFCEE849B1D5237472CEDA0D33D81CB01FA5B67B4881ABECF4787635942F86268E765D42BE3336A6CE11CB7F1708E1F7ED883DB8BA680F911DFABB4BEFDA71DC526B3A8647831C9E2F176A4ABA8FF1F8F9D59389D712C6A303FE838983B7D32025BADC7608E894791430810BC1378C5AAA22FD090ABAC90F29456BD05A3D371735C3E3D0A5D744A431F02CA8DA2E84276A683A2F4C00F5B45C3CDB57C237CF783D532D06087424BE2BBCE58A6E621AE767DF21442452C5E49A1A009EF6C512EEF2A11712F8836FFBE407FDD53C0C0ABE603619FEECFC88759B367874E5FDC30CBAA7A3096BA18FCB24B7776A5F38F7709732994D2CD2E33485DA16C8666965C695519904DA786BCD60CD9F2019A6F0B3A3374AE847E199082A90B6FAB99400CC5E584038916E1042005B314302E2DF1A255BD257701809E4ACA56B453E9784207B62F07F8785E5E65E9A8A11470C028FA393E17B9D89C3955C06A76F3C77E0BF1CEF661C19607D1E2A10A947ECA0AD7D8D375009DC2BCBF630B590C0279F068526BD07E686027780602E2A6DCCC4BC880DC519788B02F8DDAA2AEB89A2854904AE679A7B3FF6D7F727FD48DD1490862B98E2B46FAF4167F3A18A4E198C472360383BD93D8299E55138ED1FDB5A98365297B90C2D045BD45663B54F12E1CBD238D6C1125D4AB03539FF9A62D1C6FED0C61EA0B7866DC8A606F46C33435A642922EA0C586FB336AD0A3E650766A0241C118377480A9E11D7DAFF422D123F128A77852315A8CA0C8E0A18D386A37E7DC21871F3F168BDB72CE39BDD06C00F48F63493A0F688EE1B45D56A5E9FD961BCAE2DF7EBFFF5E3252BFB84D50CD2D4DF6A9851F45CBE560D62A3B43C44FCDE65EB1FAF6464C5EF44A0A697D26C13EC5D3EA5647E161F37DA8752A938265636C3E051EBC57F440BCE656B5E95820A7DB7666AC3C917329BE1E56DB496F298B4D0610CFAAA5252AA1BB9F01BFEE1BE9777C0CEB013701834FCF1525A84F88268AFAA531CAC346609A46DD83B88137B744017C0BCE2981F4D0CD3DEC67E4D3863340B63C1ED206CB6CDB1D315320332FE04724C75AD7BBB3ACC8E301E8C50BC75C11940919E1ABDDD2EB64C2FA1817432499D4391BDEF43CF2FDD3BC0DE2E32B6ED86604EAF6E0B23246006FBA4CC3576E3B006BEB8E1AB3EE1C83535C4E4630542E0A8C1B29A95F65E4E81B3A4ACC5E0C60038C9106F193F6882012D36272DCFC409CDD7D8613C822E69C64D67E2EC796578B11FC73669666191C4C5A66AFAADFFE0BB1B910048CC6C721F4AB52C7559847DD6EA0459163E3583466D8E57F2723F991324774A0EECCE7E498027AD295B6691C552F585DA30FE92DFFA35089C3EBE4E69B32B97E685B89B71AA689DAB2EBC9E621A1F896943772258B6C837A974ABED4538CBF44DD36B58500C04DDDAFE1C0F82EA88EE334D2CA1357D0C412615B6C8527B871DA193FF788BB674E849F750702C921B53DB9C0A7C584578CDF441E4D22EAFA2AA3D8A59DB79C0B564D0840597F00F10E113A39683B8B807BF9EA2E11C80875415D6772F7E5ABDCEC35AA1DCA3C91860663B929362AF40CD1512286BF45029F720D65125C7468720DA4821C1A102019E632EE872C1041F10AC82A2B2C5315B394DF4C3BC8B08D4790C07077D19D2DC836FBB68C6E9551E87A326930FD1F64E572485D29AF93FD5A2BA2A4BD3D76DA755482BCC6500526668D138EE3AC88FFF2DBDAFE9C35C4011C3401F9CDF0608E903EE1387B52E528B9E002C2261B0B364874C218037315B82EA377EC22C1DD49F468C22E417FA58010A4A5AD804670DAFAFD6A6D8D0543784A7AA0296438255BEFDBA75B6776696838D43B6767296F3430D8A7B2882F03F77372781963219938ED34A6AD9817AE19B5252A6FD45CEEEA73B22A956748D90B8EADA88EC8B65863A1EA70F06E3620959393DE263C49C156D9968F758075EA218C702CE293B2150AB4FADA76DF204497B156F17D3DEDDED5900B47084BB0C3D52366247E388D7DD02CEB0953364B726705C3C11C5A01741DBB0A38F4F0AD1F92F12286FA902AC8D616DE23351026085CA7D44627B4E8FEEA1062D587A117759BD17ADC7D01D9CCCDFD6BE800CE6DF1319010BDCE3539B467C384EBCBBEFA2EEF0D4D76E4102CB1A7CD49FDDC3261EC00E9409DDAC53E2505B33BA8F012786FE6330A2893C9BC52C27BAB5ADD72401A0C3E12BEBDD111A72BE439908C0D5BBA8FBBB2DF0DFAD95466211348D03D37F3A67502EA35FE2D993A3495124 +smlen = 3936 +sm = 26473CD3F33434A7BD7812AD69B0178F630C1C37A823A8A0B6B010E4C95253BAFD03D53101D7BBBD3D5C79151A4BEB58BE781090933C59FE51659CE62FB129AA8761593C395E452D72B661F0E772183C26EAC5B1C42A9F1937FADAC609C82DCDFFE17B473FE39AA2BDD533999121ED99309693D7A7C028D2FD383A69777DC96489391E94E43038DBD498DF8C74167210C3885187A0AA4F7731DA932F6CF473339174C452E911864EA3E8F02D24425A2FF603DC3D3CF0DAD0F5C16C81AD1F62E9FC89A27C76CE331CB750D16D498A7B1408979D9ECAD34C616A4BF164AF8B779D25F3E99586C9133BC565484B8B44A0385FCA772E5AE9222A09670AF07E91D88B76AC6D9FCFC77B0D41F9BA82809180F02C876C910686E73D93F46EA0B6CC76E869FA6A540690AA3508CCDE58C443A92F1045F135ADA02E97112A7DE0B9A2388604130F80A2FEC2F8A8D668213C6534EAF6A35C492633284EC442D177FDADFC58B1526543FFD822B34A4F69C4355CB312457DA4E65D26C4FA41FD6BAA62F3730F0D3E09B8FB0AA80BAC491541676A0FD77953DE02A1EE4C5C3FEABA77BFB22BBC3204C3DD7921824AF51FF2F6F859EA0DBBC26A350B6537AD919D6893A2FECCA1B5C90E5988BFAD434628E5992E70A4260A8E8D6A4ECBAD45157D1F602173DE8FA63FBA15B224DCBB88BE3C102725FDB2081AC8C4B25F4C6112CC83F337BC5B93163D992043D5411A9C0EBAD8C842C540BEEC1A414039068CE1386DA90E829CE04AFDF5CCE245F9FCB39DC4F622630C185AF938316DB38FB7DA4447786C18DA575EDA8AE093EDCEB1078BC4695FEC19F1582F2DFA9BE3ACD43E16B293BF11141AB26C1C52811C4DEB932FCFE87638EADED5C09DB00D373D58C14B3D8F50624D8115FF98E70D0C0C19A084C2F671F5B6D3306149FB143826976116FA65D6854C89ADBAB56D6E8209E0880DE809EB563B29E162945BFBB1BF6E69C17A5C46B6EC5911DF2C00125A45AF75A9A6483C08B1C1D991A6402C333B0DF166789BFE1AA8CC36643D8EFD0D7A61A93A1D7FDFA01049771CAA6DA547148316E1DDA7796B981EF03456FB594B88D96D6603F0DE8001322DB751C6BDAFD7053128D8DF3441F3E5F8A1D6FF215F96FAF7C41E162D8D2284FD0DDDBDB2C48F95C004BE4D83900F8EEC3CC9B8E5C2DB9E9D94319F584CCBC4B452174AB398F4982F7F3589C92E7FF1F0907AB392861BD3D75A21D7FBC6D0A9A6D6B9D8D9827D7DE8EC208F46CD14E04FA57B6787A7EBA64C332F38220D19FBF607225B5D27B2D404EF30E836C41835C69109CD10D27AA707F42F551DBA25C4487191BFB2AD00C85A034FA1E4511484CFA544376F43D05733235B9E4C4EFF71973801FC31A836C58F28A421E267204052CC5B0C587179B1F28A205EC77C12E8F3B77723B2B11254888757587D7E8768A8CFDDF5AADD5A4E3CDAD91E6E7FE11064BF6AC974CE6DCC4D22D9B4713B6C7BCDA0F672FDF1D5F4A6BEB22114C69BD740F14C4DA43296B8F005084A4B71F23F7D2D5A1E646103FD324E7F862E89BA4FE0DE6D3CC445B7FFE224543451CDFA25A1AFD5DAB5CFDBC0A8C1A41E7BC5E310B3427BC792D596B3DD0EF87E8706DE8F9492A1F3F670B33C3615647FB056D5CF8FDE0D1D310C85D03559FF723E2F76CAC5613A178DC51DE4B818140CC5AAF00048D6520E5D8EA347B610777E236869B9539402B5355DDE9C34B70595E2089862F779C867118E6BDF3EC31F83E2123EC62748035A0B28F8F9E21FEC16FB63D95EB3940E23FB81401DAA5867D57DE27F3BEF360CBF7B86DC80628A87273A65C28EC563C6500BB536AD1752623C77A7ACE58E5EF4466F17FB5E62B0D05B2A86FD8DFE6205D9734C664E6B6A8545D7472A24306E23E0F93544CB60F528617C5A66737ECB50A90DD42C952BFCE6483340F067D65ABCFAB3E69A3813BDBBD357E0E31051857EE3BD5BB06E0857B263A817996E553AF43923FF366EE3C962F6954D9B9AA0D470F9C9866E42B1F86CEB4D5CB955C5DE1171119929BA4C5A37A3EC21A8437DD4D08D2C2F66D5389ADF44A6A0B11BF83F3E6166263C97AD144220A7EA1CCDFE6089EE6463AAD4FFE9B89B2BE91B8EC916D7CFF39D9DC7834DF964DFD99A4B3BCB4B3DAA2DB8B3B5B1CA88F5B676B04217D3F3457EA4F9663A03B56597D3560930FBB1CA6D73A7AA3448AF32CAC2E09DCC45A6F14350C46685F14B75EB96283B82AB59C783EEE4BD8C0DDAC5C7BC0112F0A0550130F1CEC5280CB15D1D430FE46E343BC56A75956FB6C84EC593890968DED8536B007A77C65E85DB46AF72BA950A8AF482BC35FC5B81370DCB5E0DACA9E68B5CC547BD5F4B27236A1322799F5FED5B78F759EDF6996E21E553F3D94BD3626E9A360799F8A0524D74E7A6B592AE112E67F0069DF071D85D843C8FA475663CD4A80D48FB5118BAD742E088A9B6EBC067931B3562199CDF3B2866CAAF2598FA2BCA26EF0D328292DCCA80B8556446BA116179B97978E6EA4FA4C51D8A35884567A5D4665C02372CBE2A78DDE2499745BD70A94E2D5D48A679EC62D91E0477AC1502D01EBCA39837814F41E6F5ADA5793CEFBCC89E58DB22DCFF4A50947E96D586CA0F46C2F3B642B75AD4249AC1BC4BF3E1C201B5637E67778D92D3028BBD91E945050C88F0EAD2BC2153EFD7169AEA8E7EE9C338C099B84D62320E9FE0ACCD44FFA3DC2BFB9BA5D0E231CDBB8CAB88E9E1F9392D2F1B9A03D199948405460CA137A96D9CE469DB86478717557469424926E2B9381B131BCEDF0B4B643E22CCFF36916B0A83249DE07F6B385A4887D0630952A2B17B21FF6900363815F5E5F965CC5F137FC8C6B23BE4F72B2CDA087F5B3DFAB59597D682066D8F66E847E06A56CAEFE981AF0D8DA7B36DA04CD403CAF568822CF63181C490625C4AC4AB185D1A88697F54A19498DBD5FD53CA529AFBD043DB653E07525290A2F0C75747477CD3D09B8987610DDF7D191E3C2BD31909EB6E7F1BF16CC3AFC1263ABDEB867037A34CE8F2D897D0580C8AA1C33538DFDD0DDB39629EB15F60B4A3F1035FA0B6B3DD3EACD4127F5D4DDD92BBE700A3E59CAA75B1D7BAA7F5CB4C78565450094280F999E49D87B8B2A3CC6E366B9A4A32987C151CF065BC570163C0C1AC8CCEC37668055838A73D945B4ACB81FC0A3FBE50343ADAE05FA324361EB55BABD816C8675D0221AAD6CBCC16866B3E72ABB8EEAEAB3BBB634B24D8545B773CAF6A7ADC1CA7B2F4B7DD8536DCE5FD8B0E2C256BD90F29FDD5C2F5C66B73052E767800C6911836A618096A871269E010A22D84FB84B8E98750EB9574FD294137600AF3806AC7883B447FA0047FC9BC54987B5354EDCD20BB18D1547F9E02D3F825FA7164396EBC67003985B5D8476FB2F5A97C1360155115897DF287F091E92F6CD619D71736E0476241EA8D614176BD0EBFFE0F75094096AC60AC9D5392130632B0148740881957C2ED3D13B88E83336E9F5710C2C8BCE28C821CCBA7DDF744DD291B546E2684B61728DF9B436AFEB21E35C6E3CE3B12673BABFCF408452D16FDAFADA539C4419B347F003AE9D5FD1CEEA22B86D9E15BDF1D8A0D6768C8C97ACFB16F9337338ED56D3A3D37318E75A6458199B0D646122ED8F1E48B41AFD36612906A7FF5DD0E7C439340BC075851C989ED9326E17FE4E8595BC564D23B0F6C182E087FDA33C0792255E6BC79B7ED6E67739583EB79C0D04F06029EEC0D766B01954BF43EED2DC782F782C0C87FC85D4573229B642EC99B09CEF39BD0D1D00DB193BBBECFE1A7EB0B590032E2782B96779C4D1BF4CF4AF46C6098288000BB814F6E13A02504143956B5B06FDCA3265550D0E8F47343DA822D080DA0AB644D8315B4F5318092D118FDE7C28C9193A77D3CF0097292E0110119418EBEE1D33711F4A91FAEBD907783031E678E354B462C8D4476A2B4A33A746573C490550115F76CAE948F1904A84CC009C6D1827C9520D87F12B47EF1A0EB44DC8F85E5614D54C15B55CA6DDECCA1D42953155F3D4448F99AF814D27D1CA14F1EC10CE21310358D3E08BC3A6D9AF2D05C7EF98613F3EB7EE8E4491E503E6DFA0A3C251A3601C7B7B5CB77C72A60E8AE2D5B6A9400FC2CD22BDE0A4A5CB4798023A87156C579C5F6D1E2FFE91E9188F6A180B6B29D299E4B35A0FC87E79821A51AB28B69363E43BAAD03545B302086E65FD3470CED23AB3F27B471A38978C47109D6CFCB8A97A03780BF67017E148F61FC61D9837E24D281A3A3B7EA7F0341F0FC70529D699BD669767C29ED4E1D9B2CD9D4372D63F8E597A1D2D0A5B90F5387A54197916C7652BFC746BA029EA1908AB6638F4C36C3A540E45E5C6D7A8262D709EE7E03342364E9E6A4B34C4141A57A9D79C8ED2F228403094666E8314753D11B42B9A8CE68A005FF3682CCBEE9BD605E60598F85310E7C5134DA1B5C89AA002301F412639F3822719DB11990245472E9EFA59682FEBC29C0FBB19147A007D79E286D7EADEF1315E18E6908B2364224353CB6B4C51C3332A925CD5E2BEAA79AE8F3AA431F55F0E8F4977AF7378C1006836A0DFDFEAF5959387C2C77A6C3F01B74BFD004427A9BB5C61E475378BEDA4C61868BAA4FA3B4000000000000000000000000000000000000000000000000000005090F151A1D021E9C06A2E4EF63D1A61958620C40016783879080D44311E04F2A446BCAEE5A486D17FF0F356BA70FF1C2B55BF957A59202903AE349878CB822E04275E0AFAABC0803BB6CDE3741E0BF9FCE0C5D5C814977474533DC63F9ED4F32AC3477A3EC9893EF55186728C85B03F4C2E61CA7733E1706766AEB8FEA80E233E8761B57FD5A3CEF700196674B34A3A55F68B3368B688FB1DDC976FF48BA6A98E2D66023F291A3C617A56CCBDB8732B8C34369ED11F4CCEA8FC8F673AD9FA0FD8990BEF70AF44C617FDFA096695D0C94EA8E17554F4461DC776DB2F416448B17680FE4D29B09E57603D8EBF55771AF84D8D4B9097302901C25CB6D73932E67C323D12C8ACB0E74CB89755F7EB3999D4EAB5E1B775E6B5C29D9733697030A26F3B93B3F286DB0F2DBDA71E1F103878063E77919D8892EB6A34F821B603ED4A898A9F30D00FEEF20985FEF1A7B7AF70DD29C269E88687F005D551EF05EB0603FD38745AED4F5BF4C2FC09F0604C98AE3A89E46BBFE907B87A1672DE547D651F035F392A8D4DB5E7260F43953028E312B95B9F25FFF2C0C579218390411D13D9A25F22DE4C7AA05FD11781DB08977160D48E02372C7D826F5CAC37D1A9B4230BE99A2D13CC2E9B2B17F0A1044EB9E0A2FBA376D35CDD2BC05F57DCE4BBC3BF07A09BCDE369929E6250EFDC61689466B040AEA376B09453A2C16813BBB685B54A225C49008BA6811E8BB5B3627F8C281244FDF5533216D126ED0E64FDABEC533424BFF77FE722CC438CA7587C19D965F0BF085D8692C27C5C84A9DEE53256D978948D89ABDF9842E0B765BE6A507D8630CBC5CA7FA0FBCA1CECC78D2E536AA7B2B902C4379777AC0920D69C57CC4E6032252BDE99E1A555E80D4 + +count = 19 +seed = 716354F7DEAE272CD26929C0932CA257AED1DD23D67260726B5213D82E61466FA99BB6A7D81DEE9D0EBE03DEEE4DBFC7 +mlen = 660 +msg = 7BEDAFEBABBBFB863CE496475F54E69A905AFA45899C3D7C16CFC73E31597D2404AE7014612E4CBFA238EFAF5B396B0B7435ADA5DE817E013188C280423C68924E1FA2A33CA56E6B85B7CCA7F00D3A6151F0629C1B92A13573320E0025863BBA7F3EEB987EE1B1A6230B10765DFC1FEEA498AE4B83521188E7503B506259103CEFB370E3651B06DD4F08013FF3AB9E2430626B0BD584232948462D85C0F82DA07B96FC65F62A43CD2F132D1A1D691C085980DAD8796CCE2FA0B268395EAC3DA2CC400F30F75BE87316216980CE213B48651DDB9E294F8CDB2CA05D3F2A507E4A03E2849AA8062918AFB5BCE9E4C3ABF2FFD4751DDDCF08AB09E36A29B830F3BAC6FEEBEA084575472E6F4B239AF89965A72954769A83E391DE467934237B07D8884A6B14CAD034FBF9BD7531D50D742E234E227E1A2DAF77A2FFACC579525134B15186D81AE6E5538871024BD2897475D6EE5B11BC51EDBB928D98475073785A75B331BF3D2297165AE6CF95C3A05F06DF747498462054F58A5AC736F96014B1A8CDB319D030D06DAD9CAB2B913F35FC392E1FC4B027CDBE775D64B04F1076A7C8F44C360745F98E87B84C18AB76F84F373F635AF4C8A87DF08DD4507899BAD892FF8CC1EE534D3277B5B82095628B84A7D5582149CF46C50AA963B56B4B91966B106B4B2EAA45D83A10993E8F933370AB29C6606B7CCFC41B21C6B99F2B9AC643E24300B350FA199EC10E64E4AF19181F78E8C43B2FA796241DC42CC8992BDFCDC39E7BC41BE68CDCE4FBC47C996DB42E8249EEDC146C216B514430C705FC939B9EEF677AD87F9CEE3398551FA0DAF774302324A410F4A4F4FC035CFBE960B38C390441E92D9E5624A8745976BC88FA538E398712361B77AD4CA5FF038D9F6CE157EB8A6137420D4E57018275DCEEBC4E480A5D +pk = BD96432B299699D1976636C4A53C125405E981B06BFD65F7FE30C0BA5020EDC655B1342ADBB1F9776F729A28CA9406F0F2F4CD0655ADDAE7F6D7B14779EBB0DD9BED5FA6463BAAFC20B2CBBBF3638129F135259551B2AECA94F0F05BDE27F25819D0262F99D947F9CB0D34C7DBC88CD49056E55987D9CD198F75C170A564BADB29BB12CB09B83D93B61F95C2C9534A86F4FEB10A3C7A8603A5B5312E0614FEC9C42F284A0E909DE0D331806BF687B5D064F36B87E50E1B6AEA8384069708A5F52DAABE99E5B8F083FDF905806901CB0EA16FBD1AE9BD9053ADA7E6D16588FF227228B51520A596B0F3A9171A984D9A1C469405B8894ACF00DB5F4BB3AD533C0EBBE8E2CCCA2F8F3A04FFAC4A7D9858D748B018D545660E5F6B08FB6E514E1C458B9476C811B12DB31285B7EA6DAF24ED9C8FE5111C1B37F96F43EC1B0EC87791CD84E9A6258314272AC425C313F252609913F5D2A81DE5E322D374742D13074CF90E622316FF878AD3C954D3116E235D017FB9559B6BAABD88E94BEA0148E68B4989A9EBD4FABCF4063392FB0EB173D79B527E2FA31E537E2EA53989FA0F278A48B9575D00CE8BA47D34E7ADC6545AFD80362AC693F033B20C0384EC4D0CB8B59359F9857AD89E614B5520BBA418569C99680EBC1C22CC43DF12EE306A3372217BBD1CCA40645677F88A212471DC088DFBB324490881A6013FC2D8F2B83FBA166699505F8B638DAA5BFB30FA8664D4DD632DEE1811EE10C8408DE45335345BDE85442A3731DFDF1D0E32253DD4234C8263DAF30A3D0EFD9A4A0EFDB5F0F08E3CA0ED86A90D2B27F6AA9B326F66453A4CBC57F0EDEA6352E129062001E5D92599F122D040B2080D0D292917C2DEF7159A9FC4475C7E0B61CD2256E4F29D028C9AB91F2A6334EFD02B6188468E6425976E9242FA7429A2E2F4013CF768E67885954B57E8EA87B34F0A58E4F58B5BCB4CB24494636730E75B4C6951C2EE46976BC47EE71D830AAA87A88752A625A596C45B17432C894ECFFC99FC3134969CCD0F5510C9E514497C1CBFD61215515168E68302D63FEB8586E6DE404BDB0EA8F81CA77399E7B851E0D4E9CC1DA38EBDF54DA69584FDF7405C84D1E20FA05035AB357722B626517A386FFFAF958B9F6376AB1C9A71FF9E7FBACB93D16FCB0A3D8D8944FF78BD39358AA15931F0593F56880F78ADAC37921D81B77B377BC0C206DB42BF0AB2B3F3E757DE09A8A3EF2E89067332A6EDC7D0043CE157399CDC662AD6AE552837BF874ACE399EBAE5F18ECE6890BB2E7066E2B55FDA9C9E405F22FBDE065E9346505C14320ACC03C6C21CEF49B1969ABCBCA022570CB0BBEA6F596FBCFF092DAC76D41DC01782D582B18A69A9C46D153C442F9ABFB71DFA5294172540BECF0599933F9D1C5E219E0F08D58600B51D7726A209415BC6B22D9DE9C37CBC0A8E91E2C65390D6535599DCB9C75083BE989F5C7262B35548BA838D575CC667A3586867DEF4271D35F4DFFEFB6EFA6FF688A0B7696904998251CBB7D0F718C71C53CE1BA23088AD74ED453658DD4694F2A9C67DDC54B0CFF52B410912976A35206E91075C70828E710FDAE8CF20925F442E5E6D7CF5985537F44537599E531DF118C1510BE4B853441814B9E44277A8E467791B9DBA45FBB3E1B48428CCAC4626A48B0A1F8EAA62C7100577E3B9145E60E6AA8C2C3F7544782AE6A566D636F57A6DA3FF99DFECE020B23DF755FA0A8006667A11674503C17ED75DAE2BBA1669A1B1FC55260CE51123F00EBD1E720C90A690BDE6BCF139AFD2C25929F7BA74BF9ECA3E879CB6BC63A89A7FE03C6CDEF8DDFFA2E598D614CE9F89C99F124DD74C2C04C6DF943C5D3902DC69212440AF7CD2176C38340E9CC2D05EE8A35285451577E6DB880065FC928B8C39FC77FF15740720757010E0855040193A0A083FAA6F0B29DCD0ECF6E4AF1AA420AC1DD8E9C03B846207F57340FF0BCC4F80E92BACE51F50AD6660A56B869CA1BEE81AB20152347D05D5A444E06D153D3A5691C829264F6F21F844415BB8FDCBFAEB9C6DDF6E818C6939C71B0B5D31EBB6368DD7D0E43DA545AE39F5ECB8AF369030C3972743752D75AF69CDC8198A5D9D1C3F6EB851D0B7091EF2F111D1304D061E4EBEA5FA8E25BC5D93054813F39D5956D0B40B4B01D788B97943D78FA7B6D2365F766CEC8D64C2F6B037C1600D45642BCFA0567DCC47AD03500C1A8BFD173384CAA57CC10C971D1C8BEEE8BDC7B732FB9ACEB8484409EBE08979263FE6577241565ECF75B63B80A36D8B460F091AA2C14819383803AF2CB4A3E3872FE5438E815EE22B77B3286B4B85EC391BC39B9F3690B45422B7980FCD4C3A0BF0E08208356454067C21777078D4A12E4B0184F254013E85484640BE9AD8771B0572DDC5053144CB989254F702CBA6A47AEC0385E0600D2CBB41E15A79D1BBF01F7885833F0DFFB6F87777076A929A47FFBD0E49BFAEE1430ADBD2E516316964D4A898D3B4327048F1F456960A2CDD84282A8D7778D72BA2185881398E90017BFF6C99336C0451C10763FC0B1E94288C6B1EA3F03DFA0F43D764A4DA769278C2093301D0E87467C99D05010C1A5C7322ACC5E967BA7544D2A203F8790EC760EB59A284E1C85CD2A881C87ACDD5A59198EC13173D5C01B453B54EF9AB8F91778C86D68EBB5F9C01F91AA8E8DB2ECBB5DD9A0EE28A94F218D068C99E3583B21C22ACC3344255B325FBF359DB20D90F23F89524EA99BFF90FC593A22A +sk = BD96432B299699D1976636C4A53C125405E981B06BFD65F7FE30C0BA5020EDC6E4A8E780661D9ADFCA891F4807C6632F835BB7845123DFC55BB16053015FFDE41515DA2253C0603F648C0271512E8B5A87AC2F2C353BA6F94594C0A66AFD4DE31803AF3406DFC34058A9BBA86A1108B72D0857D74B92CA79BBDB4DE9BCCF29152782653287425751418840614340226821067258011580482788318887134327158083251186417145371266086676601555424352218110471846487685527862574887123636701507424720703676586004058726457113735361237277735764633187326176457217752372548407002831163310305841520000184122467622216208121844688776051276664370243285630267886252523527051358358815070374883308825410207157304477401020807652377616743108465531606822112872785813631824061184362486426052706742310815862215338854650147663724008653075368834656721643570560121766242285520624466177172325123736626863357836576781227656766268122704641425582001522060382782233233685784047448203711525443660214628104340302836034878537431720105332840126100535615118148658623311614625502740471606402042136028071884613348361012216358765785820762013487213027703367875464621235121344635878083268787851062043831804425886846877611042881471542224221337858314078347261111338800016487170853241473653042356013280240570465712103626303485308030116408370647507702881831767842846731022726025338703357445672670884308604420114437850235103153270376718755377374744753832284850201831537680572265580215566805877285248718813241462734753722648005617660122811102308411157585250704515230684471674088081376822646772477037412822725501608354832705473712207053225135081746637641121312867374662453876231243301577410062463573086172011808704402501152571568420418320738838216154518673570767413670652720832342282043848415016134316152435483230830445125372528636184413522560644022430131802630283656216885045383518142217673015843785034123528750413737684645005157731541585570686662010415233333467137650332560812063002878400112422647186067863154010588875373254720033603372058005232365371680226541856243435286307188365480251275700128078238474438782376620886862005087835285153864520007540808662151468672800272032726048086687235033407654277602180548361735604428461305715776302254056175312021475633577575823754636222137751771768668866080703223478145113214022828725660426268435464821878555243030348817326350550812330345261754177011848545627432786803265025672322075374100362710835178400670180887778676127524182544570428543864817826436150857532036284517821713714235737363668020607443815422531657667101240571016608746834375686514531186825538581175431211864440807313380741587744814435054454041010121157782682770688635218718363234770070168108222246268836604835670422302345810675748040688188304387076256874271163454782266851086160183557356717278052216643188645782215665476676583746034843776072551504175630731854102752814807167214420217134346867541507368402486583033214634704171643681073362731702810810530234267485074218780826721384204050030186508331240616566081483131314785810265460004834666107413367522247786514248062084503128634370742841030832547147686871037288323344338224165047665632726838421637084366215363023320727607420161685727558072770848530B22C69E3D88E35F54C1B997EEE5E04B1C2E500261E7929D3AFDFA320AD31FBCCB67DF326F563FF926C821FF75EB19912E441B108A9A30DD9BE66E29533DF23A5705F68C1827743720B5B088BD7FD1DB4CEED708FA16F46E6889D9353B078BA94BFD4E387F4AE7E8E579CFF47AE2B9066860193B427A59957A0E8A4D20F300AAC7E4BEF50F9099F423E1F1F5F1F65289BAFBA1BD90AE77233E73B720F9D4A7E0D15DB809BF4C56DC2E967B5A7E9CA57A1F096C1F1A7C14DCA06B55D62D189B749EDB3A4358986EF053A8EB8558D703EF346E1B237E53743E2C2EF7804C47C0D280C3FF6E6478E4C612D6A9DA8D62F6FD5FF3351D8500BD08DE6B9C19D453E51F95D5EE0B8CF4A2DC0D2419A9147A93AD5D0BCF536FAC9101BA55D9AC39EA955BE76D3C6A9BD8D13FE8DEE9BD1E2A5A8D266928016AD298B458318937289CD07E0951CFCA0ECDC804060E719C0A48C6DC9D9E85254E40CB464CC0F4153FAD003563AE0461AE199DD1941E974B93B564C607B6AD5551D8B316EB003CD9C9A35B6DE8C9964B8F8D545A8C99C1BDA781C10CAE7D43A0357CD1FFA73BA5C76DF1D2B00B713A846FB439DB9955377279304C2ACBD5E7D07E9F7B770203191C5CE20FFD65B7EBCAF84DC33CFA6218879354DD939E23BA825F89602727F6E5A53F3D1095A353803944424811FF2D80348423CC7C795D681F603B0988F565DA3A27F8EADD47B64155050E7CDC8F7A57EF0B52E4FAC2F43EA0033B95191C4555D15421CF4F042D85FDC77D5DB31203F0CF2A4F1EADF3D4B34A7AE8FA90A1BA79302AD47A4294A5236E5CA5EF213179A597C1D21D9B820D8443E73C51AC6373CA3726E9BE574D4288DB75FA06A345AFE4DEC27588B2646BF84F88DAA39639A6A43EE6C5D0C9E56662591BDBA8C572C4543DB55E407E8FC2DEFB7A5E77C024B8EC02BD097BCEBCF84AA8B6841A7B61A66BAC0644BD50682E81CC6621E7AB2FFD04AED1C2057F9FDC12A781E396518B9797BD2B0CBB13FA41BF565F6A77ACDF44FA14262A71C97C75EB8E09CDD7F6D55D0DA3940D2D0826361A0E9EAD1728594D2861A354983FC0C86936D30A6DA0503FFA024C3ACBBF0CAB82C82248EBC5ADDF68E85DB800646C3442DD48067A1D485428ADE3D60907062DE7855CE83F0DE7E453A9A91E36237733380FDBA0EDBE36628AFD0EB5BDABBF2FF32C85F29289E275C28F5EB20FCD75CE65D2083FDB43B86FE91011E5A08BCA0E5A7CC769AE2809FEA4AE53A499836232F8413F92387B01B0C7EF776D7C21A1ED04F5D44DE5ECD49780CC6EE78CD26923735E1CA7ED353413A750662B845624F9E4DAA1575BA5E5892673C11AED1591D0C322E728F77180AB0ED883E71FA57F8CE7DD83361300471CF9F2ADF8420476F75CB6F4342005A8BC5303BCEF89FD54FDDBCA819C2D595F857B17C3FDB9BA6FF7DA8F2F75BEA530A08371F565B84BF0814B4B6EA390D998E157CA4C289E5AFB3CBAEACAE26556ABB6EFB3E17EA806D5538E9E24621B686FA06ABBF79DC39C149503DF15EE402C1B9BCB8B028917246DE1FF058E4E8D685E99FCA9DFD6B49AF9FDD26C5FB0F1F57A8244F6C21D5A6D41372548B6CFD24FEBC70317EE841F2165312DE50789D22DBA3544D30EB1521CDF372F5F4C72581E447D823868A05AB9CB8AB61E3EF300156B0479C5A0EEFDEDA5884E1B687F33BE267001302B5A8762B1FD878E90A965F32061428D8E7370BA71E28096AF2A6F3EC357B4F0463E8832FBD251452905002C5DC24238B30D9AB084962D37B40CDF5FCFBE870EED5926695C1BF7C914C1FABE02ECA3F54D6E59F63423CF118B9FEF2480B0F2964044A8A7C476C7F17345361206FBA5FAA27908FB9BF7238976F1854E81EEA993CF592785FE2D04E6C21A7434EF7D1E3ACD51ED5FD79BCABD8FB43D2AF48937931E5547A9F70E86AD7FB7054BDFBA49D6C672796F1FB5C214129F59C525EC9749E90911F65E5AF3C38F6587AA8F43B47067922B3A77CC57F0D0F8561717D2A608873D5E39074B36745255C31437EFD3DFA00373EAF1E29E57BDECC3D391675BB1B059FD3F1DFB37FB2E54BD8A0D3008E171104266EFA01AD88F5378CE1B64BEC6133383239E014419E0919BE9D08401F698297C99CB5950D3CA57A0175A8734EC71C05296B60584A97CEB8FD08BA47B68D45E5A604DA43C52D4877C99AA0E62ECBA6B8814D0D4EF462A2AFF18F58A968F39659CD2A2084D39EFF8B1749A9554A87C2FA0AFED15DD2F754C8F55E0C18DF5D87BFD516A11E1954E65E3A6EBADED672E9002A3C17AF76E3D514984DC79CFB20C2CF404A82DE3A5466AF4C06CF95AF178191E767F43A27D6500D57C62C195317C184149358A7725B67F01D46C3F4F0DAC1EC74C4C19E125DE450D1F0A7F51A19A4E160EDD4AA9D1A8D1FF1F8EBE9CEBB190950417645BC719F9810DCD228DF708B427A494F7E3D10CD6AA159C9F77BBE78B33B10C02C2B4CFF70440CA2D998C6F1C36CCDBFD695FB363625F692EA391E2F1055B97340E2C6EAF1DB4502364F7F4FE51C2EEC595FBA25132018896284D6C5367C2682A34F9D4D642337BA1C794841A0A507D2341D1A1BC03D88F1B3C071C27D187C8F70BDA5D60F4720B2C150C3D0C32E58118E0695A2D2A8110504659F440EA1625EFDE9B506851E9DE9795C20D39F56FCD7DFCB2644599C7F38B8C50AB344FA7BB5A0388931D2E4CD6BD0B3DBE9597ADB4E2E5A09F542783979C9CBD8ABD82C42A5EBD778ED95C19C464D866E6A8A96C56A5B768BDE55471554947814474F6E9F5AAEE16132E5725CAB63B7E0EF065FEF3F55977E9FFFE1BBBB47F48EC362043BAD322A5A480E71F3EDADC3E86103DE7BA5B154C62E942F79FAF632BC67BEF060483D5330FBD62DCC6451A8483309C6AE4BA5A62D9E68124D4B39AC8BB3F8E9F8D6C5DCB2C221689F2EC2A61C6F081919091B605442FF6BBF0C7ABB623B5894A3751BD38D07F043B41684EA586AD4A8CD21AAD137C6592DB58A4FC01106315B6D3CFDF0F3FB990D2C352BDF8067C4AE9F396FE8E18696E9472D6D1448181D4C83AFB958B2175D01583DBB0E3C9440A21F79917068C4B4233549DC7EC3327C4295E7D47472D6F9325DFDB346F5784EAB58966054A25A190DD93E4DF2A733ECC14C143E4753DA9F42FC7AB806F95CCA4D77A2CF252C875CFA500CB39E77B0F4CF6644F7E6EE3FA007768827C17CB71405F7A455185E52BCC03DCDA555EDB66320B9AD85C373D77649186B1FF0ABF625D81F72CB568925D4B46638813B1C3B5A9ECC39A4757E357F71C10B4338776704DECE4ADFC2F4E96A66DD580F879F398DD0250894B8851DBB961D80D8491721BFB4E8731D108071E6A708E47315E00C88B3609FDE19DEFC67836AE0E3D846B0F1CE45C8A8414F11E9DB29FE5F46D8780397C0EC3C99CFDFAAE50F581A38C3B5F9CDB42A315467BC56299FAE4E6C4403D732564A5327C0924D052AB1C9004638423CD2021DF14F0EE11E81CB3E80C2177ED1 +smlen = 3969 +sm = 18808DBC031460DCD8DA87F3E4278DCE35992E0415BD5E3D59B1EF079616376F08938B68A2647B11C7EEA2FE64FE31175870FC69597EF17ACA49A83B6AEF612BE5260049E18FFC630660F7A26D9D0D65CAE9588FFA41CCD32CF244E1973B96CB3758965D2878920B8832172150E88418C7E88D0C328149FD43079A1170A88291AE0CB426DEFA9FF19CFFFBF0BC45CA75AA18841EDA643D2363E455C5695706D9819A9965D6A3EEDFBDCD1E402D82FC6ED7F61F7CEE93B1534120F4DD544EDC218B01EBC5917B4839DC581FE7B8775DBDA5A8A8138BF742041A6BE973CA9C74A58411A76321D22DD00CCC497613025F122D7499837BD38858F96FEF4F66BD38A61D1F3B0FEF6A669D7215CD54D69EB22067D8235D013055C7E414A5A18944618DC86AC7072681860542C64F649BE21FEC018AFC699E034BEDA596D9B1DA0B9BA6446127C5AC302BBCDC682C2BD147303E982B962EE1ADAC14D05CED3AB2ACE7D40BAC1DA4D0CCDF581082225667866FB54E4E76CCE8EDC355A52F1CC4CD6153D9E2FFD6615ECFAA99E21A483015867DE030A09C6E8FA2E9C601595FDA5FBB574A422F2C5CB471D5C9C0E5A06F26DCC5E46BED07BAF3A8924EFAA5968BD3890666A3873ED6EECC9D3C5C9041A52236BB27EC7B49E145D58C66600DEEC4FFBE53B6EAB85C7D2CC407F8B7C662DB1965A60A2BEE6AC520E79B11AE479E27B84BE19B05ECB1EF7B47A4D57F0B1844B87143D64671794E89B0897EC2FB4770CF57FE3CFF3573E124C3BF2D3922FED3CC47C3C6A80398E7E91BDCBB4CA98D89F047525FED929CDD72046CCD21A83A95BCFFA6F1D11820E136AD5BEB908DE45EAB0CA305B75CA23FBAFB7929E4837AE340A21EF84C5565FA7F2DF67A55839A9B2FAECDAED4B69959A4A02127EA70FC058D9F13DBA8206284E3577CF8BDBEC56DFB96AD84785829A74F1EA6AC364E587E179ACFBCE33A43B142D90E40D0BB5D26FEC39D84781D1AA2881A1B782A3FCC165EEE6DE5F018460832A0DFF74B638C7BE7D6906797B4BA9350A6E7E3D30944C315C85C4C71A252E7CAD1AFDFFBFA8C40ED87988CCD2ACD4CCF6C44B532F5F1A63AF333CDEFDEE619BB09E7DC875CB8ED08A0E8180EB0E0B35185744769BDA2B4495D06E008CBA396EA0F8D802286309026D42D4F26D373AC28FF1B493D4F3A2CC341DBAC19D3CE582A94CC504B0BBB43F0BB7C0DF0EA1AF5F36900938FDDE5AF1148B96D5EE8205D56F241DBE3BE4B7B49C0BDACECB2EB7ED764E7D8A95876B97A9BA94674D719DFAB0FFA4E7AEA7464C14DB24546598F7755392D2C870A2D8885AA7A0F3EAD52DC685046D29DB2CEF949647D34D44E6E3C566C7DF61CA6BA18F4F9163D6F0D0529B7DDF89B935D9255DB2A0B58908F1AA03418488638628D178C04A89C39E73312E161D2C061F6FC15C1F48CE46DBECBEA399781290F650587A6F6FA244671C4A2F10248F1ADC28A512F7B0A2FBEE4A1E2CF7DF0FF470D255BE0E3BA91C492EFB6EE291FAE72E758C41870C3018ED591E2B7D92615D79F59F40E0A08D1FC5D8F1523EB5BE1FB201C6CCC6CA4B66276C37CFC6A710CF6FF73F5869DD2EC4B0BCBF660ACA9DD38DD899D6DD3B14DA12C6EDB2D0715A24CD723B0EC754086E75A5BEE97FA452188A0171068CE73B228BBCDDA96680E08AA6D740043271C016E80F59B76582B1E6E1750065CD9D31FE5359E2E54BBD7ED3F4EB854522191C22756B99471D3B4B80DD7BD8C910E79486797B07F30456EB5E343D8E6E96D95DF85A889B3FFA10EB9BD27E394259D36B3F151A460AED0E34A9EEB1FB77CD9F4CD2ADB9A049F8F3045418CC5BF49F3312DCD165DC771E2DEE4A8E7C0E474949FC07D0BF59963F759764CF86EE893E363BD82C03492BF049E9C02E42CAEC756CAD6B33C9609ADE15CEBD5D72DBC6ECADFADD3D425F2D26803E4510A45F2868DB34B71D379C560AFBAF9AE3BFA656EFD6B4562DB82DB8CB17CDE8DDA35917C49E78D092A5F5213E38DAFB608765591797F1F2B8BB1EEB9F7930902C3CB3B17B1C68A65C75EB76B1399C4B5E523A01B8524B9E4F685FF9F46B7D5DD9947EC6921E004398C4317059045C49F5AE373754D771DEC7BDB7A2546C308087F7149A58D0418012EEB0BE4A5C113BFC813D15757F976B2F79B5DF51D918C030ACFF3F289E58535DB2F4966B321E064682C1AFC1FCC166E72A8526533284DC888F74CA8A37E101ECE700ED9E4705F860FB867E51180D4E80F00BE89F0FAA19CF1AC85FB7B4F4E04F5DB5C939628D3BB96EDC22ACD17802ADA6C6EC5B72D192422409E97A92F59D347C678ADBE7FC3508D52DDA976CAC8DDD824D4152CA62645AD7AFA4F40FF445E702C5F91842838791BA97C02DA8851543A8075515685892531B173D22C378FC2E1771F35DE41137DB9AC68E41C8B218E922AFFCD5E6422E7BF047362249134CAABFB0BB437A1F6D78ED20F4B4CA0D134B3E7C89BE72BC034236330CCF6667E5DB64D0932DC8A87736390A8F118B06C75C30190073F57DD91881BA5B1CF28D9E399AB7248E80922DA56BF60F05C3E6B4BC3FD58B0662E8867ED970FC1807C6AB018E9567D1C1820B7BA9BB92F3CF22C94D243EB479CEA54C6CBC3D773668C4B0EED758C2C10124D4280EB6381D6F5D02C38AC81B516936D581B42C6B3AA8FE86BB5938BC111DE540319E5CFCCA0767E5944800A149FDD3606E8E7149C051B617C6EF985B6717141E175786322F94159F067B44DE6E088613B19242A0663A8E425FBF414719760115A30BBE68BE5C0BD68001E9AF750B53C7A2BCBF6EB3A3BEE84ADA6C50BD68062A4CA33BD67C9E64D80524D96072F62A0E420D5328B05EDC3FD6ACD596541B68128493BFC98EA658B777F3BBD31D9089A6F6A93401B433DD0ABDF68658DD368C1B099D165541FDC44A96E6F582748496403AF8146B9F1A9818BBD7A7BC6BCDCBD4A870D94F65674F07904B03E380EDD4A6B9667DF9ED0DE281A94360070369E44BAD0C61094A390490EDDB35E4A64CF47B4A3518F36B6352E13198706EB288361F9754A80992E17ECDDF143D6A6D77864B2E8F5610B916284C0F85877FE1DB9ACC7B3F892C5EDBFBB644D2DDADCA346756D78F30FA55D5C739D7107EF0F469A29F9ADB89494300EB7A489D9A24A95109BDACD44ACA0698D4E2B6D4BAD6C29F04153BC1901ED09FB3CB27A1329CD9D855615BF17F0130BC8DC2BB32DEE2125F293216414BC59C8A62E9BFA409DC8ACFBA7CD63A8E2D567FA8B2DA445C6BC2A31C6E19D0A4783091EA8B396B05B811D5E3D784BCF821C21F4AF0CCD6B9713AA00B3A79568166ED7C41BB19100574F0E0610ED6823BA8B48CF65418C50481148608475A221D912B88D3C08BCAB044467797E1F45B723A358C899A8111159561FCF20344BFEC42FA7743A02958088AD7F0475EF52850CEB11EA154B198C9A1B10F1FDEB02E9950781C290C4AE6533EABAB05A617312082375D725F438116637AD73FDB85ACCFCB624C9F0297251FD38D0039C87871ACBD16D23D86BF47742CA23B8A1BA34CA1A629DAAC3B94C65B8DFA8BA620F3E2888E9392C0CCFE1E0081E341233B1881D2B69606AB5B88C0DFC37DA3E0270B451A8FFFBAC7DFEABA3D3E584B66D7F0F003030217F0D5F5773A4A47F91FE25541612B116C3A9FC98867AF859DD416D877A614D1EFE73810346D1C9FB8AF5F69C00A48CCEE1A4ACC8FB38183C01D1E868C6D40BD1CC81D2052FAC115BA3793C6D07B9D006B347100E277865871043FDC59711E25F53FDD50619B14DF7E1A6F6C17D456DE2E58FCBB8EDCE498002F425C2CBE4B7F40AC4CF3AB8BB97205B3B607C13194DD315E77EFB66DCD03E37498F791AD088C34948E159042706AF1EA812C3424D0C0A8A553CCCADC7F0A46514B6DE1A34EE76796E19C592DAFD0F6EF8317A337584200CB590BFCC860D59A96D2C996BD075A016ED34F0BE455ACF3DAD1DFE040A3DED232A45028D2A101C33B8A593805B1E3E6DEF9C375E6B621D9E3693E2BF761D45EFAD7C1BED3C90A93040C6219ECC98464ACE1AF108DC550AC1AA745A820C1A1D23B2CD5571EF6091B647300AC0A12EA7829F5CD0CCD5B4D1E58CFBD6A23288AD413926C2A7F6DB2DF7AC5D79C274D3193BFF7F9E2125613437183479495D4DA53CF51E87A0851BC85F5EBC77FD769BB1308562CC88939FFC9CB8F550F7B0C98A9DB7FE0D95501E5A359350C9E4A317A6CC2215B1C99845C60D5B71DFF543D1D1A1D329A3D1E153ABD4CC56FA289D28EEE127ACC858B2AA3B7359B9E4ADAE79C04505E166B1B4F4D02DBAF112375881525FEE9A97BDE5D63245DB7C68E6360D2FD1A80163BA71250DD0BDF66C07FBA81AE9B45B8B828865E33A96D61D8673F9171CC243C6C72ABC282517CC87EB2079F91D436DC76033C93B5C5CC35831BF9E8123ECF8CC17AD76199234143319E9274E5ECC4A42B09352491E3F85ABB54E56BE72B69771AF16CE64F075FBD3AB93B6401B5F49DECA42EC8E84E351595E495DA6ACDDF0B77D8333749489C13A0C2BAF43B2EE6C790079FE2013C960B7460754C47BE2304A547B9A15455D94AAB70B6C9DF137434D61798CA5B1C7DA54939DABD9EBF62E3A46617C80E3FF000000000000000000000000000000050B0F1920287BEDAFEBABBBFB863CE496475F54E69A905AFA45899C3D7C16CFC73E31597D2404AE7014612E4CBFA238EFAF5B396B0B7435ADA5DE817E013188C280423C68924E1FA2A33CA56E6B85B7CCA7F00D3A6151F0629C1B92A13573320E0025863BBA7F3EEB987EE1B1A6230B10765DFC1FEEA498AE4B83521188E7503B506259103CEFB370E3651B06DD4F08013FF3AB9E2430626B0BD584232948462D85C0F82DA07B96FC65F62A43CD2F132D1A1D691C085980DAD8796CCE2FA0B268395EAC3DA2CC400F30F75BE87316216980CE213B48651DDB9E294F8CDB2CA05D3F2A507E4A03E2849AA8062918AFB5BCE9E4C3ABF2FFD4751DDDCF08AB09E36A29B830F3BAC6FEEBEA084575472E6F4B239AF89965A72954769A83E391DE467934237B07D8884A6B14CAD034FBF9BD7531D50D742E234E227E1A2DAF77A2FFACC579525134B15186D81AE6E5538871024BD2897475D6EE5B11BC51EDBB928D98475073785A75B331BF3D2297165AE6CF95C3A05F06DF747498462054F58A5AC736F96014B1A8CDB319D030D06DAD9CAB2B913F35FC392E1FC4B027CDBE775D64B04F1076A7C8F44C360745F98E87B84C18AB76F84F373F635AF4C8A87DF08DD4507899BAD892FF8CC1EE534D3277B5B82095628B84A7D5582149CF46C50AA963B56B4B91966B106B4B2EAA45D83A10993E8F933370AB29C6606B7CCFC41B21C6B99F2B9AC643E24300B350FA199EC10E64E4AF19181F78E8C43B2FA796241DC42CC8992BDFCDC39E7BC41BE68CDCE4FBC47C996DB42E8249EEDC146C216B514430C705FC939B9EEF677AD87F9CEE3398551FA0DAF774302324A410F4A4F4FC035CFBE960B38C390441E92D9E5624A8745976BC88FA538E398712361B77AD4CA5FF038D9F6CE157EB8A6137420D4E57018275DCEEBC4E480A5D + +count = 20 +seed = A32E6FF879EC8866A5F5E4F6318DA8FE6743812ED2CF5FB94F5C3AA3EDF953CBC32665810B71B2CFEBF343A571CBC570 +mlen = 693 +msg = A86EE95388DF139F9C5A84108D1E63F7A7842909B818E9A0425C257649ABF125386FB5286031E7E6D0EEB85C452E254DA39BBDA51F0D2167EC0A51992753DDFA76874AA80804E705CF8BBADF3B82B6D7FBA3D1CAD130ABCC0B44D6D893356F3E94BF8E82AC532EF8C5E5F4200207BCF6B754F14E57A889FFB753F516EF8DE2A647FAD8E449264F0BBB4CF48BD01501736DA49509C3426A3D4108B98E6A4AA6C4430E8EE76540051FBD1DFBFC01750E26547F8718EF7D897A0342BB000FB99AA63B781C9A4B831DA798C014E58725E03D2F8B1A029C3337F4099239244AA320965B2CB5075052D901B6077A18C1ECFA5F272850A475B5F6BBC83F3C09A27072F80743B23EC6A9870913EE2805B4D296B2F81A9D733E5C8D5C0B477E51F9328AF3AF8ABED960408AFECD27FBDD08FEF50F4B07959646E0A02104A69674294A79DE0B25B65F4DBFA797E5FA56D66E8BC07D5E2E7C7D2E845699ACEA3BFAC60B2C0B988CBAB949A5B598D8E2F1AEC66196E115AD7F237A1C7FCFB95A1BBD6939A250E7BB0F4A02C23CB1BD81090CB770E3A70CB081D121BD0BD5ED1DC06D61282B98BF2DD7B13D2C6CF833891C67951D7D0F429EBDE3F1DA943ADB8AD285E6F13F798D6CD9A0A06BCD6125EBAA48F8F3BD5100A122F617817E3C42EBC3C3B154258FA26B9FD886EBFAD42DEDC6A2C4F9986BAD88A2A79D7EE603554E9CFC5FE33A3A171CF7BA94FD43228019B2F6FF96A8ABBC58D2098AD95A95442F6858EB69E131D7BCADAD81B9BB69D7682A978279B631E22927DECFFBEFBE8FB2E51D46A3FCA66225D30451CEF9953EF94F30B99F2B26EA75B84935EA4FB257DBE5734454B8087B3A4E115C6D31E72709303E9F0BB8C86FC6B11B93B53F9781BB92851A5CB5DC00D0B4E15683DBE4EDBE986966FE1F711F24DE9A0E1BEAEA8E835C70CDDC589773D31191B74AF780EB69867829ABED6D3FFA94D577 +pk = ADD274FE95ACA54843B5F2A8EA5C62A1F8CC2BEA437253838B90B7C46E91D710364B9C6276CAF848A8D34C90A14966E43AFBE3D799C2D5404DD4CC11F238A71ADCD400BA9C4F79603EFACAB19333812AEA261A38E1A2A14927E55EA80D4CD386C104634C4BF71B8E27842EED2D09EB5C2F37764CD1562D583022E5D0CB55DEABCFA9AF5F68B3DBB348B6CF5B813843A3ED920A36E9B4C1C22C8134CEDA4C7457DE3D423ADEE2DA62AEB85DAA3A4D6738B73AAF82295CC66C38CC806D6D837545A2778A13A88F553BAA58933EDE17DE317C873017AB912C8A2B309B350EEDF2AA85500FFCE7939C0086F63126A53A71095EC68199F7D82DE5A49C0F83E7A3897FB26FA950FF73A0BD989BA8B6660AE73CEAFCADBBB8977C83B41A6327E7A31D0EC6C64A458B8B4226E7C48643E0DA1413999366296D4767675B8F43464B51529E5844656D6A851F28F15AC5CF4D7D138809E6F65FBF6C92297BF01996604A85AF2FE6776650F2B72188AD2495A34A500273123739167DABCEC4B66CC471BD6436F0840430E173C7296F7A4079ABB59D1F7210D2C8E0D2F79A99D422FFB74CD99E27E2151F1F3C58D6E0D1E4E35004C479C9B4B49F30694C0021AF29C1DD2944ACCEC58263BD64F1CD3F98CD6D15E2FEB73E0E8E633C876850F31BB5B370C8AB6BD89F9E44354E85BE2D76ACFECC790F6C9834117729F93BB20A1C48A2D65BEC05DD926F02E37B793B749796B86BBF4C8598A49F14D811184FB910E1FC71A7594DC1DDADC7257AEEB55A736C555483ED5931A242ECCBCF353A914E8E7C631B2FC7BC5E186170FCC9C037D5AB65962047BF1EA1C7B9978507E87A17FB90E481A448665D8CB969AA9CB1FA94E0BE5C0316E12BFA59E29D733E6F1F257CAF6E640E2A3F4CC96DFD2C27CF14B7451CBCE9479039ECA8E09457CDE06F94E2A898B281AEB439A2146B5DCBF862E4FE79E8063DE470F4FE8F570DB7DD221AF8C7748743D89E8953A44981698DC619DFC83F2C21EB165F6C6E13368CEA6F34281C5442D7E493D64194DAD2E844B8B5E437BFE62D619EFA36C5E558421C5729F697E9B04D2034DDD863DCC0302E8584C53AC4B241E6659042A5989E6550511DC9A3BF9C8421A27E41693450C9607F7EB8AE17F4D650641C74D5785F272B7A9134A123CDE7D547AF07D044C9E9B04C943DA863C127EA3B8ACE49C82862636EC4379F14F7756FFE1C4C06A8D60DFFDC4815868B70E48E9EC4118D68D26D54EC3B61C36DF581EE56AB42F9ED8E513CFA779C19CB180BAB4CC66FD1CE17B5D9DCF31B894B322FF77FDBDAAC5F477028F80E98AACF8914764FA13B43C38F2927B5EED7CB2119D4FECC6E1CC2F0D8B08000F188916AE19691620C7BECBFD5A360148609562883DA3C954EDCF461E300B905B7C907CC5C50686CC2A611BB320685C2119AD027F1CFC83AADFDB7FD28BE36CB2F24D0AC479395C2D001D0690134D21AC19C95AFF45EA218859009212D983C2A73524E020C685FCB7711C9D56764F3B0321EE9DCE887B712C9300C12C16790863306DFB40C1BC2422C9A6CB8FBFDD40390B5D34CFC4B7716558974E0D5D88DB41D0D51C9A3E8EF22F8A2CB09232731A124527BD289938DBFB49BEB0FA74A4C8D0AA1CB624A937EF8ACB16D6EF97C8F806D2160A880841275E86BB1A6947D9A7B3F4582804B3EA3A4B2D2D95D7F0D4CEC7F12E8A0C366E2D7D825461489F94F7B60523E5CFD1CF098E1F2D8C6C57C2F0EAA85E62DA38A79B3FF7B60418281CEE4204D779614765CA83843DC231583AA12741296D3509201049E49278E29DC3CFA88B0228EED0F392541193DD31B6390BD12055C5A1BBFCD29389DC72CA876ACC0F573459EE5109AE83646489C014C95913D71EF0F5E2F5BE2E442271F2EB9EF026ECFEC17D3A212FA59F4312D972929B563C8EA661465391D742947F0F4A5DBE46627F5DE10A99D9BFE0A0B9E5256E3BAC0D4C4A9D3976B3F3417460F1CD43AA1F9878BB5E6010D01C6DD3893A84DC266CF7F247F2FE842DCAB496FE75187DFA48609F6A6880199CA1DA7DCF4CBE43BD0B8FF742A0BA7052796CEFAD129278F64FE5DB19AB2AAD68024A61A4DE4AFAA2CD8909EE77DB6E966DF95278F923414531F1AAE2CB5774121D88DBE46B81C4E879AF68364A957339E532291FA9614D01F9D9AEB2B5BA56AB3D08B27723C8CF348D2A946768ABC2E5A2B90E00760DED1491F8704357B84CE22A23B01F8F7E93EEFFB7B3F857B1C7373A14A167A7F96039F780B59847E3D5B774CF64865DCE5E91C788022FC8088950C1FBD479B5EE16775DBD58BC3192F203B558992D795C76905F27011AD52208FB1FE22B68EA1FAD49CA208D91FA17E38C1FCDC171D117F66568A11CE2FF1A92B1AA43D5653B40C43DF95BF90FD3DABDB3BA745908D483546120AC700CB288489A49A210FDD1617E52A4A02F1344721D887D4B428103D95C9E5CA03613E8BC94B58B569EE3995AAFCB4AFEE6DD21970A420297B7A676965D3479316E4E6AF39ABF87192135E111A704E305BB0DC12F891E1D221E9C4833175DE66884DFB4599FC55DAAC348EA740551FE5961A5D26BC076AE4439F46210296495AAEBF19A13C512B96E108F1B2CC3BCC22C6D09CA62D3EF687739DCE6537B30E48468A69DBC94B84B2BD1E41D21B16DE51FEE2EC03BBB5EB45710C6DE965BDFD54B979C6E1058E59D6D243954633A64D18619137AE2BB53CE18490CD4B7E2DF73AAAA03CEFA701 +sk = ADD274FE95ACA54843B5F2A8EA5C62A1F8CC2BEA437253838B90B7C46E91D7107CDAFBACC87258E544A0DF8904D8AB85B26F99FEDB9341D52A97F82CC8D2812DC0819FF33315998DCE3DE7BDA4D1D2316583A09383686027222A2D178ACF07D1635BAD3CD39C51BBA7026173AAB5FC55C75FA290D72868CCDEA00DEBA27CBED0311200528673114350725011387583585845481225835472203851335713636742555088410061460431363242771276873703072165035132840006642084723620033218157715761257830478583688027306740736388420515704341265084524141818854731842784012612153348867408175343634755470243662605461023745153333288462666542178406256515225342417135187212107854351012585776860736411857220358240855416043312560667640714456321401354623164158078027827788670076087340487114088274578442064181853324517841615486183017878352315246412501185024622862333518636177586477557680165322600646883653780344404501641712732722488314583320661655144418100144212100181024178316027087186031522840685874256807665622421327643875526004166776555125620831317633775683376003087515287434122812707021641806778066213078863083832626776306051088125215840715736041685163468866570766762442202313180613811040350652527105178020216177755611822132602008537305888555728151875508527475524032357560675164030687806184034548056710767014850252771300714153831080051700328458842273842655045882663371264742750154001563844886123587370428460551755503558764218847363406044051380748114732540071355010242753717662326556302401246238245078475430632472807571154437811482438543211251060882844460237733321755277753621786028281411034016771622587882784444871573267364551141128267733555322215784123842077122862450533216468157221832740656015273038326530042223825154660306135500742178317656788562584313328801527632161745537733214262103863330364878183267325408831438205784007051000220086023762434725528410036705671820047358255430511587743035372852226600885458660445056208145473038238082373732264432266734678603707881657417846865561465354510108201337321514530714667864627516660424725164435835326622186344738351802155700777123035235725016672446762043546238706686470841830604702227517414518616270243111342870476821447201613135770260377608480831355351828344276322785674127035482230581440261311412460475021232757550365600383763078003464188236850058853104073382620468447868338210410485733773070421156538505338627388154862236810566338006361157213065745502133413647426558450338530651177073627162710048558288612225583768156527748417641604886576351805205481670573582518267112633802483047430775566066113483127162436220546422225646685067412752464540765207652164343252303737278387103527503070311751624035464437788442181835358152020600671550011806670354253863458188550751324033207131806017601558482871328816482771073053715434162461221002755875025237572515528110578053583245877367041120322436104267476753337357527683154588663436727234146813131026331636580465534081417220184637723567445743823464335072156410681035534780246684034307374617487875643678724831682644870668100444575660634470227357326717663858120008683383132342307223482077786753650164121886842857442006000257580614078437701335437600555002112232380181070583788744553156246642547D3F8702A16C2A88AB63C956168C6204A681108E9FBCC90549586E17E852E9FC3A46B0D83F76583D491629C05678E54764003CFA256E1BE29D67ACDEB21C463A2E1651DC6397E215FA97554086C4FEF5D807C28997AF892544316B9397E7A74452E67A1AADA50514DFFEF8BF925DCF547CDE6FC61B04EFE0766C8D65FB87A3603E335645C00449D63DBF772338099FFA5EB07A2F6A1AC8C133F074CFC06CD2AD4C701452EDED85F8487DECB4366E68696E1472222704EDFAB2DB20661718ADA31888933264F2F7A2DFFA3A9C32D6853C449B270E0F57DC546453099B57A9CF2C51C32224DFAB4B26656A3DFAB32F6A3B5012EC1812322DB19A3D177DFADCDA27363C589383E59BC29021396CF19E2C48CE881C554232860A650A9D4C949DDCEFB2A321EA405045F15FD829BB0F30FF409FFD044FCF2CC7EB65F8945653658BE10CF9BB5547F5E72239F2B314C5A98659EFBDAC22DEDAFE4D878A96802BC3DE42AA15F620E8720967472D7625AE802A8F49A8AE5DBC84271A5BC9EF51DFFB084B79DA3380A907741854F69C596D23CFF52C9DC8C2102A00AABFE0C8665AACB9C695926976E13F086D00D8539143545BD52E2FF9C5B5CB7775AFC0455D2677232CF8908B5FFA9D219740FA469735599493A0876260876EEA0DBCADFFE3D12A3110D3125E782BC36CC2E2E757EB334B04353AF50B00A0BFAC9D4C01D44962F0C0A120FD73805DA228C895EAB9BF34E84A35B6CCC5B34D92D3C3B017235E9E426764B6F427B25659A33CAFC7C0BBADC610052CA2C43CB726C47F6CF34A1602F7FD93231E636BEAAB4D37B0473CA14C8F22FD7316633A618D1994E3C4A52DDEF29F3275209F6FF37C0608004A499ECA682ED3DF041BF080C0B262C282AC202B21B6A779FEFB8E09FEA96E750D24A4903C840574828DB1D7A3D617645778368B25B42B6A4C49CD558909EDCAA6B6C7D26D2BA843DD6B9CE4455DF8562C7C63CFD3E927365B745BB12077DDA0C07EEF75E34A7866610F57F76A36488B85A42212622F60C118A97AF1C271E65DCC74636B30799C2EB1BD2D83F93ED986D63105A689CB7741A178E2C3539C89B562F8950D125A52EA3284152A73F7771317149C13EA6D4522E7989FF59C4C814FA0F2AC2BF5FAD09D48CB7ADA35171373593F8F72995F62B9F9F5C865C325C615540CB889538057AE557BB1A78B1FCB1276F70D69E0643E9565AACD6F6C9D628F59AAC53CDD86743ED6C1F102B41D4FDE212951A9D6B240FDED5EC999DB46C2BEFA89119903ECE6CA61CA57CE69AC797BF721B9920299973CFC59B256FD6FEAEAE59356724476C8EC5F59F5688C555864C238D9B7EDABD9F5D556EB1B7167A5EEE613FE34C77945DE946E9C6685D9097152FBC12E14A131329B9430CDBDB87D371329450408581DF18EC529C2385164A3796D5738359167283E61145D68FFD84B77C5A8AF466B0368076ECA582A28BDD18AE4DC3FB737BE4A11DAEF4A84626213E258B56D461C32B2C485455D6A25C1E9F86FD9050CC74C036D7E35198739B8AD57B07153E243469DD920B458AAD036843114B2EE19C3BC5EA28839196D90DD53B9A50BAEDE34AFD72644164FF117F9FC4AAAB3C2FBE65DDD5ED8C88F65F25D3C34C8BC3AAF66C703288583C46554B6D941D940DBE421BC517F7FD7663EC7031984A5424134CFACA08EF94F406BE7A6F8C7D7AB48595A72A69076DF9FAC2E833342FA41084D547DF0477DE87F3227E08246D2EC95FB40BDE81BC01DFC6882C1ECE979F5B856C3D8E6C80D1530446DB4127BBD75AE3E624450C9CD4615FAF59ED35A506080B709A074B5D3C6992F0E2B0CE16D9EC99E2B97E4B0501F7B2DFB9BD393E129972B4D64874DB8389EEF399F01251E8C9746E541F1D5B0D02AB0DD1EE5E26B15E8D8A78F9D587303422C76D386C82CF726512032C4605D853BFBF93071078FD517B18ABAD22D686C47B031372C01B0743A6D62AA7A59315E2E0AABE58281E8127D256B3823D27DDB1EED17E2E8DAE9B85733D0BD2790B51DE689844EC12035465395B91F9F4EAE7C42D720980366026ACA45311986A3FE5BA59824603DD1BB2210260ECF5D64A10D0B20E427CCF37E4FAD085A25E72CE35AD97B6BE6D21B8C12C7E1EA7E88269C854D13A4C9676E499AAA6B889961DE532709CC7B6DB604CDB7D4171CB84A240598C5C8A1CB60A0779F9CE8F0E209219D454EAE2AAF26D28F069D578FEC8F6617985583FF44A4DEB369109D78232760B3B34D224E765FBF673F4D52B3F4E9A0FD27D58D8793F210146B6107540814A0CC60CE0CC8DAF2EC0C7C78013F11786E0D7A6BF5FDEADF6CDFEE6335E9784088151B1AB2D2F4809E88DDCB8DD0087FD0485E0321F42F21F3E7FC65FE249292024EAD00D88250EEA29A228A579DFA89DC696BFD7F84E0B8FD8325C900622C93BE6C1A6AB86E3E63164D7E6B8F086D972A680BBDD8E7E18D7E06D52E1DF0B691AF45494094FA3A673462D51DF016188DBAE0B570684BF3E3BA9383FADA22B35FDED41D8659B752942F524671FB619BA0FB1D97EADEF64718994570398FC547C4C0D2A6C3011C5B0BADD72F835DF0EED6A26CE51147539F346A02D9ACDF8B32E556830BDE1FDD6A3154ADD564BB7BDB2FA24E1EC69DB1D1FADF3B12F2BE08E07643FED0FD17299E4D6043208709A9DFE0D29869E0AF395CE5949D0015B6CD14993E4B05FA245064B5CC8A12E88F50BE9D753F284602B9ED9E745CF02669345BC5914D7F176C5CD4526263A89DFD4AE06343727B891817000CFDAF019CF3970C646C8EFDDED1A934FD90775BAC13055B09A8D1B4966D62192C035EB92E77EC3A822B19956F3E06CC4F760ACBB118B90DEB2000F7FF3E14D37E9CE2EB6215614DC853D19FC39F4226BD0ED7C0CB174EFC755595C4D7C23B8A01D049DF0A43E26F9680D88AB0B8EBF95268AD3705374FA0DE2AA7B59DBF62A34C05323F0D8D364C54760AED3D29C515E91A35E607F8484D1EB07D3D214601A6B81A0267621A9879EE8BFB92D7BA91A77A9403A47A77C98DB862D62AB7E764C3B007C12566B2361508500F7B4286346B1786A66F569D8F4A6D3447CE54453FD4A02CBBD825B1BC016DD9977C279FFE3CE31CEDD335C7238CBC4C6F9CF5EDB135F21C19122639F6C0C1D9EEEEF7B35BD9C54551F45CE960983EA2E8E4E93FBFBA64F79AE170798F497279B335AEB14C9361EC9FF6E887F4EDBFC5A23800AAA5B78DC6C94FF630E08C37613F7CC3C18839FC1528BCB4E223AFA23F2593BC8DEF87CB5106261D741F52B5135A64B9830A7696676A47858630BD08119109BF402C0E242B642604C4C71520CD5A99C9D599B7EA168B6849D9453A84A33056E5799F0425F76806AA4B7E726647D54D7D1144E46EBEF7F0D4996E1F59EF21A34F7B127F1A3FB4E26FE9062C054C3D05616B26366AC75ED260F2F6F7FEE08D42719F35F57708EE54AE6DDE5C8C7B5A9876E592C55152736893425A803F6D88A461E76909F6DF9E5EF2CDA161 +smlen = 4002 +sm = 3ED061B84818A10C0E205B8182770B7BA7183D1C9ADB235E25E561C47B1BD81E53C9E50CA15B57006CE97AC9C8B46BD80F7B978DBD41D112CB8236617A47C50439C53F530D59B66548FD2940EA6C020752CEF99FA23C552F8F7128D31AC85E10EFACC731812F3C8DD13B758BCCB5EB083B2025AB70B6AC211EC41CF1FBE4AECCA4C3C7353C1AAB4598EA4F3FBB8319164D24F150DE7CABB93F44A1A08A27581E44A4426DE38A5F37339F94502DB79C1BD8691700C66E183A7E8AF6149B762B30B5C2319E9B37061780A2D17A3DB5899071239A6FFB0EBBBC3B51AACF897990E6FA15A728CFFE8088EA566402733003B78D6619C3F323F0EDBE9480AC21D00BFA15C4AC5C31F6EE7AF2C8D34FD1A0A0A6DCD0DEF4722C9B21BBD7EEE7C497BD0DC57029AA007001904EA7EF69870B3FF3931E04F3BFD34180320F1301419BFC399AA8DD9975D245BF88EFF1F215A5928C33DDBF103C8C1DF834A9DE107B3721CC6653286A9C17358090A87421FBB9A7443D6580FF57FB9B846E4A00F648B97A9B0E73588F39AC7D7FAF69B0B269624A340F74CBB84673E4D3676485B57E751F4312161A0B2F5CBE7E6272CAB022F69183891799D9D4F40FD4D5C2330E4BF452B5C61D0699FE3CB1E45C017E73FE00541DF0CBDAD4083D41EE4BE0BDB88BA5F5367876F06D79B29C33E653D93E84B82A957699812E6A7F200934006CB7B4A595A0D56047ECE8B1EC1EE3B33B61E463A309B47FFE345B3D450419C9C99FC83372C8E0A13A4AF79FEA157CCF824187096C83C4ABF6FF8E65546129AE420BFCA3E5122AFB00545D34270299FD3B41465CC5F5FEA5233F2C045FF74AAC401B2E60C191DE61478B6976CDD31E10571D1E1300610FF1D6EB2E1C68DC4D5382D8F5A7A55C00F674E22437506230432A3AFCAC6A809024D41A57498C1BDAFABB671E60A3F5AFABC7C2EB9C8F9F2589894DCEF2D292E0E9848B4FBDE8CAE97B61FB4D699BC0ED68478315187BFA4A71C98310F2784E619C5D779C90CEB91B37EE6889E5415B73F7A12A9DB7D8BF47E7191945CD16C82C2787997E82C7346AD2BEE4287A78B7F75A0A4F8870DE54D3B4733D2892E839BC3014BBCF327A484D5AF992A49A4D95F61B8D7C6772EB06BF88ADE76F6A404B124FBECF6972E3C39302F67A8875659AD23B1546BE49F0F1D3819CC9DE83AEC191D5B07469A66B929B79AD2127AD06C8008F8CB5B53E12D6E1CB824E6D5EF5F13FF2A99F0F6E25670B364B025B9A2924471035C84C07A1C6C69C40A8813DDA3C48B01F5CD1855E5B51E3D490DCF4239DF823480994AB8054388880F7327DD4897053AB494A0FA196ED6EE6289DEB3CD5D862CF11CDE12026E871B9F0A7C2ED20F3CE5BA09A86A767B5D351311DB4D393E5C54DDC64D52905A44C530AEA0FEFAE14E93AE2B78FF57782B56F83C2DE74BD7230690DCFC9C9AD7380F1CF52EA20C9867C4DA8C5BC5A942DC22B3A1659A87A1DD006CBCA4920858E876F9AD21BE7E1C430BD24DF02F03947CE520C5B27AB179A859A724C05FBF48CDAC3B0E619C1684CC5FB25465113443A3B33A1B520D99B42AFE3B1C8EB44771C9D78608CA3B7098F64944EB2DF08DE45DD9982CB3B035DCFD7FB063185E408E192A2E608BDEA55C1AFE165BB6E32A948371142A891FD0F6C97425D1E6D77611B5F80090EE873FAD75BA9FE45451594874CC1D2904D4CCBE2CD14890009A5872710A2AA28B671340B1C54D43E0F539E2587041B5BAF73C5E2559AC54A87A6D0EDC06EDF0A634FE07D5329443EA39C2B4E531D89ED57B18141FFBE51F3E5785449060EBD36F2AA6831E0D3C7EF6F286346277AA7DFDF1D110ECF282BFD371FDF3638C4D76B27D84CC254DE12327A4066ED628D6F25FF55FC55D9B96E0D562D093E2DF7BE55CE085062BC8D445CEA2D2E4199DAA26AB961C13DF147192F18C295730FB0E5163768F82CFF6A477A662DCFF619E05BAC7EBB9BBC509F6B0E91FCC315A11150AD1929383A0613049955E7A9423C1730620FC413B891554E1B4CCAE610AD76BFD437590441A26A879E8CDA6DB1296C5C4516929F0938C80AE5EDA42D641939BBCE151F3F296AE66B5C2B946DA21675CDF5DD4BC65D3522301958B8516BD629AD652660479B33F0E5B93D98D79FC504D297AA67B9F4C9B9A4614772894F56C4914B8F01920FC3EC086533431A0A1F887AE90156E0ECD8BF04CDD7B58AE5141DF99EC24D7C4D0766B4C7DE7A21804A857832E8596DE925C70C0E47C81DD1B70C7E57421FCB637D040D534EC9CC1806DD3B659E42484E99832A272CC163C352580F102A8297D337000B71CF4BC32608C0504BE969F7EE2D28DC762E29ACD7A00297278BA22EA396BEFF74DB872CE2DDA5E07093F07E8002C9D315243A2D6DAAC3B595F79FF163CD21FDE5ED6532E949F157FA70E1CB7A75B4BF922E64EA0A9B06EF86BA607D5B5A6803D39624D66B30BED34A55809AAB59A9A021A94A3F8694C1CF3DEDDEAC4613E57FE8CA591AD3D3D7D1CE6831114CA643A05F91CCAB77A0CDC68B677AFC348D56D86DDF2C1AFF0323A648B00950A986B6E5476F56D8212729A65495214B89485DF5EC48DEA3F29FB7C06346BEA6FF31A05F621AB22D08B4F83B8F0C016A3F44EA5E6352F592BD71AA67F4365E8509F6A130A1847917098D083D1CA5DD0B21F5C0D37B566ACD0C356BFC20A6B876A6B147300E4BBD16B00E18A5E40E477A87D9A89BE7D86B422B6CC217E30FF64FF12B6715E569C5D69C77CF6EF9E4CF31019B3A3DE474D29380B0319C2631BF579CC4E415A25C702A2F22F2AA16BAB0565AC8BFE778AF2060F0AAE2B71E40045480F5BDAF8793E49CC21E4A690E562FDD25F5B10145F31CFB33B58410C04588D3BB1AE6A432EA32AFF807B81AB73FAB7FEC7A1A54715E4E1461DCAFB572477FD4ECC836BB7499AB0E404B78164D0338F8D09BDF0711115F7940B28DB1B8F165EF899C8C35FDE3400AFF9822EAE6E93D4BDBBA900259C972BC2238424EE08175CEC706D90712ABA6703A18A302E669677C6F3A0C499FFBF7A9281B7EDF90A557996D48D42E969BE2902A3A8E51B3E342B58E38722FC57E6E4A9B4047AB1A615F9FC0961B6BE7C4817B048DB34DCA8EDF13BF79825400AA9FA267586FD6053265E05D3CAF401A7312C4B3689F73D08143FF9554EF3E61BFC00A0F9176F45A7D7972C21D1B46E820E97B21DC23C16D4D6B4BD74390D87782A68371F6961B3093ABDF717D52EA611C92D73F789C7B69D6C5267738FE710E44DC47E072C92EC7D229417A3C5022E36BAC8A2E3B26968A0F0679334CD97897402A6BF2B58670C2B8E9007D5C7CDA06E28A1D19176ADF6A238D418214592F5222607F98599286DCE729595B63A05780954788C4278F6748B793CDCA29052207E4E6887675D5C31520DB7F02FF5EC49DCAA45C58E7A09456EDC18324A71F81F9087B2FA78F6B5F7861E5EE556A5DCBCB2B0AEA9D7308678E6DA0159AB2FE4462DEFF0D575A829DAB9D997AE14D5F46AE88CD36C0C2DBDDBC77A4CC72363D3D5C51614703C7466C76A6A5DFF4E0BB2150D1456612B21CE3710CBD92FEE7AF49157EF86BF18CE052597E58F2C7253154B4F9DB550A0E0B8C50BD1883F02A9BB51B953E5C91426776C61D402B1118E1BFE64273D10A4D7DBA07E7C40BEEE357E5F7D07AF84089BAEB14806F0F33092AB990F7184430406461FFDF32B6DF15A13D97EB45379B1B42569D4EFE1C58C314F63320479691B4E2093BF9760BCE3205CAE45A0999ED0CCC70D8F32B57BD916D8DE7D0AD8F0E0800B74A0D705DBA5417D0C486B355C2E8ACFC21B82121FC6E60E82EEEE0DA58420C401DB4B515F3EEAFF847CE1211530C04D064BF2AE24723AA8735CF8A25915AAAC2AD29FC14A681D2892B44D1DD4E8416109D08EF28F20460E515BAC251DC08BA83ECBFDBE33A4625AAE560F6E3DB4EFE1FBBD9728D86D8C5BB6676F1C68A14A14E31C5B00FC7E74DC44BE9C4CE824288667C56B4AB4F73A0FB05A57376AA1D0A62A79AE787ECED93370FCC2DDDF75F8EF71128B7ADEAF00D0027E695538199033B1914D4645583B6A4B83EA81AB8AED5446F9702897684C8854779908148CFD4FC42DD99D63DE1DA5D3733DE4B1748D86E02DD41AE7FD5A4B0C57AB0C0F7012A3A26D22574BF734C23CE0B07A122FCC50B06AC4F71B3E8F162CBB0AA8E1731AA6DF59FD60E22103BEF3EB04BD86798DDEF5C939BC33F7D923DD01004D86A6420E8977A92DD01CEC4FED683BCB2AD76DDC0CD00C1A3A397B620840540E093258ED957FF5DC662D668B8E892F6C1913AB68BC17BA9DA9689C78D620EDA27FB7CFA424A8D250B5C7BD9E13F7928AE98BAF8F5EDE09A66154279D34725B6BE8E312A0A14BD97ECACAD686D591B65C5A437D5411616A33785EBB9DDD920FBA15DDC61DDF982809AB0012115F5191D9404390ABD3CA073FE1DC589D9A8E87D99E970FC6A38521728D12AEEEDE23B02C4766FBEB43F6959B320E4C0EE13373F8EF5171F88A40F88019FBF264B6CC2D55F4FEA6198A4FD1C7A5BB65E68335083FE3D482844B50F0F279E256371EA0A3B737792A3C3C900A12D3A4457E3F5105A5CB8CD000000000000000000000000000000000000000000000000000000000001050D0F151AA86EE95388DF139F9C5A84108D1E63F7A7842909B818E9A0425C257649ABF125386FB5286031E7E6D0EEB85C452E254DA39BBDA51F0D2167EC0A51992753DDFA76874AA80804E705CF8BBADF3B82B6D7FBA3D1CAD130ABCC0B44D6D893356F3E94BF8E82AC532EF8C5E5F4200207BCF6B754F14E57A889FFB753F516EF8DE2A647FAD8E449264F0BBB4CF48BD01501736DA49509C3426A3D4108B98E6A4AA6C4430E8EE76540051FBD1DFBFC01750E26547F8718EF7D897A0342BB000FB99AA63B781C9A4B831DA798C014E58725E03D2F8B1A029C3337F4099239244AA320965B2CB5075052D901B6077A18C1ECFA5F272850A475B5F6BBC83F3C09A27072F80743B23EC6A9870913EE2805B4D296B2F81A9D733E5C8D5C0B477E51F9328AF3AF8ABED960408AFECD27FBDD08FEF50F4B07959646E0A02104A69674294A79DE0B25B65F4DBFA797E5FA56D66E8BC07D5E2E7C7D2E845699ACEA3BFAC60B2C0B988CBAB949A5B598D8E2F1AEC66196E115AD7F237A1C7FCFB95A1BBD6939A250E7BB0F4A02C23CB1BD81090CB770E3A70CB081D121BD0BD5ED1DC06D61282B98BF2DD7B13D2C6CF833891C67951D7D0F429EBDE3F1DA943ADB8AD285E6F13F798D6CD9A0A06BCD6125EBAA48F8F3BD5100A122F617817E3C42EBC3C3B154258FA26B9FD886EBFAD42DEDC6A2C4F9986BAD88A2A79D7EE603554E9CFC5FE33A3A171CF7BA94FD43228019B2F6FF96A8ABBC58D2098AD95A95442F6858EB69E131D7BCADAD81B9BB69D7682A978279B631E22927DECFFBEFBE8FB2E51D46A3FCA66225D30451CEF9953EF94F30B99F2B26EA75B84935EA4FB257DBE5734454B8087B3A4E115C6D31E72709303E9F0BB8C86FC6B11B93B53F9781BB92851A5CB5DC00D0B4E15683DBE4EDBE986966FE1F711F24DE9A0E1BEAEA8E835C70CDDC589773D31191B74AF780EB69867829ABED6D3FFA94D577 + +count = 21 +seed = 5A64401EF8E63AEE18E8CC0162845DC7AF388230E86728ECB330007F2546F949764273EA05B397FE71F567E1527FA445 +mlen = 726 +msg = F5ABE373CE1F6FB14F2014F5BC0071B17AB2C84E8845FCBF4B15C79FBF2E5E06CFFE6CAD9A283014A975F81C9216B261CBC79EDCD58D0E20C586D7C641E0EE97221BEFE54DBCC56A594DF103EC24B52DDBB6052D1644972640F39DEB98997FEE7A252A65070798B7E46707FA440375B1BA705B3ECC7EAC56D9C45297E585299C7D747B430F0D01E82081C70B4A87846F90267D5163181DED63E089A00AFD33B0E2B3ACE91182D8CC899223CE65A5D84B86BB3E8B34B13949BC800F2145468BA5411EACD6A6C331C340D4442D28EFA0DA959A2797C7181BD4BBE6E6DFFD134CEF373ECB0EC08590F06BE0CE292D3718E2C0EFC7CB40F1DB26F5F38FDC82A72F81AFBBC16591EE02DC818D63CAE69FF0A28F942F7E07F6B0A741F3F0EBE3D0EA5859024AA408462D3D268C23F95D717C0A685A4CA73AD90EE923DB57CD6CDD828B7AB0D4AFA6A9AD7E32D407A44D7515C0A6AF52A66AD72119BA1DAEC6514DE3F8B462EC473072226AAD61135B0F5EC646BA9A127C9894E51FDD1B2D38011A2A6D7497A55283133695D0AF9B3FF7C5A8FD667231F9E511E3B8C4C3ADC44D02DE08C47B2382DE67B32826754C6BE5231CE0FC657341E20247CC6CE574F3D1A9376AC8237B49E5030E877A4E33CDE25D838EAD659EB1678706C759707FC66CE84CC968A8334C18F1632348824A6985A0331A93B59497B70C1A03A6848F18F5992972BC79F07F4222D2612797F495463836AE6CD3858D5B9BDF744A1CF361B5D454D41AC899A4FA61081B937CBABBF0FFEC1B31C162224EA36CA2CD7FCE54EC1A504932ACC5BD0B17A156DA7488F7017E4916A687FDE7FCEBB2901813B07964084AB0447A94DAC3A0D3FDA05B9F497CC1555A8C74838E29CB8CE89D304DEBE419D26BA7F3DC6E9526BD895495A5FF1D7EC83F70D045E306E7C2487A52CD7553F062D31888EF7FD27F667FCFFA984AFE0B9A4C4E85CA943812CDC157C5486B0B5EA6DA05E4BB8697113190321A976D1806DA129101E60A28B7 +pk = F9C94595E9C502E8F00890119B07A9F7046EAD963B3244A16682936BD86305C1DF8037DEA5BFC991A222175183AE8C99DC738575CDDE51AE7E966201E8E182181F3ADBAAD9C985A7E5C5987553DE41139CD7EA846AA0A7D1376A0523A0A796B63D0E254DBB34040EFCA668E67CD0DBF9B2D016292608485DDF966C58997F8891C716EF93803EA033F710F5828E25591F90A8E52EACBDA38E936C24B100021482BFEA7F53AA9F3D3B61999C0C4BAD17DE667ABA8D1F4CBB25BE3975D73082DBD7A55A0F43B7308D2873645DE3DF5B45E563004255E515A973E39C21FCDB1A922BEF21AB1CE6413DD4FA5EC34632BA1E89079BE373EEF1B794CEFD6D8F24DCC123C76E9E0A7EF20E899D13A5AF01C483842F61513002339082A862D38E90FF1678EEF55019D1191159BF00D9671DE5C5158F653160F60ECF81DED2AE0B02F88AA30D8113B042D3B4CC4BB591AFF6B8C835525CFAA69CAE6910FF14E3AA141DBFD9A93623DFC822458811A55DE8438DAF261CD744ED5EDC35EC3E1BEC72FB1A92422C1323A1D5D02106D96E0DE1616C050899BC866DF283A71D5B052FE59966D86CA83A16DAC236E565F8C3CE8B900C4DC73349D7CB47E16EAA6020E075E10259935C5A63C3001ADB2F269579FD03B46748B8DC63881586CE1C09F1DEF8BF2FE9F391A022F5FB91AF417F07A77D6A2056CE55F22881DFCF8B463F391A5634C4930831751BC9F3E51E11DE521C4BB66624461FCD5DEA875862AEA38BEB27750C9D817C345951B4CA74B5D910A80E697E6F7E491215C6C9434762E7D73BE7EB9BC6125C2E49F91790C1C12ADFF90B8BD34CEC9840D431DE81325F3DC5DB5841B54583140A8D06EF402FD6D862CEAFC1C8CC7B33AC6535AC08B1996925F02FFABA97DD5B1864E98D41F748CD092E44505909992776C13F44CBA3B2337985981797208B8AB6BF1E74D7B2D7A7EEC602F10F11B2866BE16CC89F2E35E2DE0F2228A4B3186580F5186CCD6C21E5C39C6B04AB6A8BE891F3DE1617B47BA347090C81B17B0395C24546C0E1493A528D4F63DAED50A14C1F7E5243F67E3B5947526F064E30AA80DEA6C2433FA5216306235EC218D18A9040455C1A22118C62ED3FE25806D80C49F79230A92239B7C5C475BEA871DC319C7DE735C8F12B11CED67DBCE122C21104605DA4606CDC93A682A3F70C4C1845700535FF2D0A3E55D5E9F1C6514C367080E0FF410888126B44208897D86C24D8B719BDB9CC90EAD3E8C5CA8D4197074864B77C063973D02D79BC6398AEE0964807FADF551B990E4EB6074112A30D5DBD5B7799F5AB19BD7FC868536DC9C8E5691F3BD9696BB24EE2AA2E99FE69CE72034DB36261EBB5A4BCC3B70E52E7BC0545659D5712B9D81EB34C9A3658A0186165B37D6F7432DC6A4389706B97A973A892180A7ABB33F4B310309F4DA0A9AB12B5F31A492D6033905BB10B46BAE5F5B2C01130388B11C308B65AB187A6974BB08C8A4740EA2BE948591447376C1AAB64F8C711A47DC4671E6AC40234D9E2BB39D9DCFA803FF66B4D0653F9E96B0F4873AD34FD620D876EEF04A0C4562FCC57D3FA1092EE42534E7C1BB437D82F02F3963B253501EDE179A9F2BD962AF7DE4ED032E423DE70EB2ADFBFBE731F1BE46705E7BE96EB1623F7A6E7FDCC2D6210247C0BE724A2FDB3BA0693C7B6E97ED2CFDCA56038245BF719F28D34B3913F8DC6CDE50C3467ABEB4988617F7A32FB5C112ACA952AEA41C1B37626CC20BCB53C0043E90E3B0D27BAD77E57D60E375DEB5B541AFC3E2D3BCCCC1AF2246DF0AAD3266A1B7516F26BF64EAADEAFADE1C22835D652494C04567945055F565C1A3B7557B842FCC25469BFCD52E680A43CAABBDEA21D0F598FD43142282692047A1773F0B37B17EF198417716C286CE168640E28E942A8B071BA4A344489570755ACAA3F7BF33B6DE7888DFCD77357BF516AD20F2AA43D5D2218F9B104F78DD3718B408AE01BEB7B358DF64FDFF9870F5EB13828F2BD58EF54EAF8489FF56EDE9A84305B006A197005EFE1296EE5B46AD99EE65BC50976C3690DCF8258589E55900A7481FFA5F977F51863D2722CFB5DEC5B3FB90F3659C09DDC195531DDAC526BBD6E6F79E55BBBACC3338C38D91C98710CAA0506C6E1866F41425097B007116019EA43E6C176EDF05F2F25C55A93CE6B477460DD38FE4FBF0A917AB76DDC214FB47CCDF4FF158ECCA194989837276306E80E3C691BAAE72EC9420A453BAB597E907BE302DEE4F9E1DA3EC16F5C44A134DA56047CF180B8C3DC0E92B4ADBE1C1E35F1881157917B426E8097F6EC8C1884CF038660356D842D06F51DCB9E54122EEC102C352F206F4C9B1FC3A33DB5B737389BE3E87C09467CDB2CA811B967C25F5C15DB92548753045F41E59FECCA93F4D7D4E442EF903D2BFCEE60589A320313F750B496195DAA84B980A0289C207307664B8B6122089A45C74B8DB6C2FFD8545D97E48ED16218770D94479D484E36B17CE98D7718D10C58E28EC9900F0621AC3D43BA67D16C7B8DEF61C36E7BF51A88E5BB268B4E7741CC32D910FD47E6C1348591928726BD1FEF3A269AF1FC47283C712190546257A9A857675248659AC6156A7D119D95C69B2832D4FE8758B8C6D0BC4918876F2295BA3B88DDE10D754E87D7E02A124053451BB31624DBEFDDD4042BFB3F64B44B1813BCEAFEC419EE70E3417075571CA16EE467F37348C55BB47B120AD96EC1ED9770FF9EF8EA413D220E50B069E77C +sk = F9C94595E9C502E8F00890119B07A9F7046EAD963B3244A16682936BD86305C1A904436E2A9B2433C9A1056BF1797F20D6E2694F9E842F3A6B7CC5946B60F426BD1DDF4B34ADDB72BF6111062C3D80FA33FBC4BFA46DAF2F2D1A09978957A9AA48A0184E29067919E679A4DE56CB59AD0964CF011018BA4B93AC405EC67000B44285155062828608685314032330477741153752506465257820684183556234124046510815330536083658832784408685274522747118172264023175448323478460786657777617254441521280760133234523370532623104376263456668162327446424241340257151308020177118703010236184086044110174073044476420745770735843361418007816032605028124680336404683666801747577827661184742245216140345056203256258484057526567238436185166154348013284416866316033336820816566031438635621713142737106881870116463611173524126164463428615107883270384881483272016605130063605082337275311511532585085661564511566217313168112743723652823717156476050434162536384240445643854831782784876480588745566212002373761667047512381486287205518285812575415827071754025244061743305725033740428656865377751575646665518116748742802848483835641535754142033818022624006817028877444424420088716071387172454427345233022146522006433217152502640702058445365050210372146352377864842855147005085155287416466365108751400232201376213652350648513083376556186757516000064150744188241532530507478174675136644124841146645022102515355043117637720681401003318107717204478350581372728511772868762346704641231827831672083325875638686486823533086104573081272103805231076704665220503660243144881727642150443033822803808133653463006706803568510283103672023581628831030347071344663876317078580882282452666851271164345101888484725113784344801617236788766074573457670540213864047762380261125538034582661226216130056884274521236106310531181600565855321534268367026777608031676472478546120167084777456445488645570154326466578438826602838157242117151860368177211116445081514615808510631411878345582423416636532478674203610434401113772636716633410314508347020678003327113253182152144871175887366455271006252081628400104358570343333806036374550512486476772445788110157338151565610500240424647388008231870723030430501808735861877424304333743165520070660230414214516685404325235737546443106888253305512078103547130674810868028287317433317253441382342216287404572162044856874338430842547076487665515412568244400585283715411285568652767470467276771134778372743273052070784782271468558531842647673135513576814213435581755731043021484016738248552537806113565741840804533318664301102856478800184166104815378810761350858772255681472337352530786442648606876843660274251164306284324244407326365686342152014638024001311368081506484337667885828561348212122704553616682461414807485541135223773850164337274246750730372377167618205474881288406217547770100850651003463635148186308623860831344425255371483207153524608458515327107880242071283267501454273062317077161321834718558765728040358502216634306428364017426660407720268253152726277024724460050541135317513685308710740182531820728258633442661776028643032507558747826170200115151156223043581320454413178456656576536737518002103240386618264105714330360248141344738585554648685878694FEC14278A17D62A993EA9D3644CA26B82D322DABC170B0449AD3BF08497ADE6CD9A59BB28745B3A546A226CFFA8FBE6B76155A1FE9AF4DC442D3AD650F5C4CBE68237222D7C8550AFB19F68D60B838D4A4316F592100DCDB5F771097C5EF651EE9E1C53385904D6280527596D3CEF394E208EED8EEC9CDDBCAD28E6B47995E99F9DE79B80F6316540B0F108A61CA3EF7352110ED75FA5D07E53FD497C6066558FEBE2A39F42C6AABB4347CC781C2F13E1B23400C46E4339B475BB210B9209FD68B8A0319CFF6A3C8DB9C1646EB8366D65193530901BE9B0F9CF3EF954D8FAE602B0F9533B0B0061934E0839AB0B9EEBFC18249E85817AA8B2144FC156F2DE18182EDD5206E71DBF344109E28C80E790CF7FB6B88902B74DFC502977CBAED0CB9113264E1B971264D5D027452C2E65B4A22D7726CC2BE2B988A35DE6BDC81766E3D66EEF79D080C63C01A51E59FA92F98C3A19C4F89E027801CF0DBAA173DA4C3E1D8B10172604712AD65B54C49ACDB78910525D04DF75C885CABF73B4C80647D14DFFD4A5B78F13014AD610577D1BD3CE692AC0015F85E954EABA62BB3386BBB6E642D9263F14EBDC71FF2778899E93AE10E374394CC897E2872BA36183164AC72D89760C7BE502C5DA24AE7687C92C7BDBE1A654B3CD9519D35E2D824DB3E82B6CE1D54DA854968B0F59C6AE517D4E049C1AB6C57180D9A20595E0D4DC64346CA9CDB39297BA3693F854015E27728DB8B1F065FF2D6133E81C8BDE8D25F3468192C5C03B0673D7D2A0F7366AD23BAC01DC55134B66AA58D33CABAA2D89CF3CC7AA1965F011856C00EC6EA4B39B16D58547DE8DF040A6FB29158D6E8D17969248183A1E58704C0430CE6455BC8F40FB282DD6246E81E52840FD20AC648BF7270C25264CE07951256D545D1A515760AB620D3A9E5B4338E5DA6C62DA56976BBFA8A5FD8A46864FF0C695515317919A2460BCDA62CCA6DE38394FE4AEDA44F1C3889E315C1B1C83C6D5849FE883274056F6980123471B9D0C77CF7F2247A6436466F5CD3F476A4B01617912CD0245FE236ED49C250B0BC78EC22B7B14A9D01BF76C2D7967A4DE56CB2323244A3AFBDF8CD8F4367F484172E332C69C897B7366232950D47846686D9D6ABBABD418EB5E384637794B8ED3DFBEF99382A25BE59721A1A78DC383A77120C8FC01156C25F847FE213E4FD9202DB54C5D6D622AADCE0D1F9653231F84866003299D8F85C0B2D53775178BC1C46E0F927479607FAB6B5E9B99C3FD1FFA849BAB7041FCD2F55DAE88961695F55C2AFDB2D20DB86326C7989E7A4828992E45022A81F3DC8ECA1A511315FFAE73E31B15D6A98B422F22699F8B77FBB25ED8BD4F02A58F9F98D878419C5E70302FFA87513A8AE6271AA895BB60BDBBE6045AE202D8188534BE66F4339432F131ABF358B08DA76CAD8B9CCAFDFE9037A05595FCAF8FC90A5A73B819CE6149F60C027DA81F94CBF8ED94A3DC04D6ACDF30FE8ADC72F4D1678B926D0FAD1710CE22A701B72A3AD3F036C4F766D78C7D3632CF9178F8E5531051DA24A1AF1B9F5775C1B6AB39AF9FFBB49C8E8D07D86E0DADABB991406DF816BC319C1035EF864FE5E6848551C5ED425AA8DDAD0E223DDF0A50ACF23A9FD3EF89059AE118E94B92F812945627BAC39EA18604814AECB97F3BA7E9034028063C88013613F0BC2B3E4DEB0902F001F2D846FC4E2BDAAF0C28F05C5D113178EE0C6968B65739F22E3CBD0F05246E60855CB3C4C904A51F3F60198FB3C78BB08036F8B91E7B64A636F014C52F3A77D135F199A39BBA18AB5198F894671C236F086602ADB07CEA0F5D29052B642D5268F5E4F929CF341B8DB141537496B982B9288EDFBC12720C9B9E067A334C715AA99DFD738775DEB45074800068AF2EB38CB6F0529D2918EF011460AA19771C8CE2F140F0E0F0C197AA999884F185EEFF466012B7CC532D072D49DB59BF4DBD0F36213F385AC812CDB01D1F1CE53BE8B977AD2E09C1345F4DA8B2FC195889B06205A9F84CDB28A00A38A5FA910CCB2534E9E409D060159BDCC546A7BA9E9751492B8332C8A6C2DACCC32DFA8D041E2A54AA76C1D2B41674C5801BCD3E538D6DEDEA263A786E855EA70A40365C8C3895C2AEE834101B0F22F99CDAA016163C15394D6546D6F544D51324368E5A1E38A9CB1AA64CAF412040ABD412FC93D796CE91F24D0E21C50DD3B7EC7726E7A9D8E6949C15E5C5CCDB7905C3F5F7042FBDAFD47AF31C23403FD8A67F56086192F5106B8261114E9346985AFF07369F0D371BEBC16B7B15CB1EA920BE1984EDF139CA3B76E3958E0048AC8B307281D89A23DFA6E07732077D8C8F2E9AFC86508AAA0FF1EB93930537D12C7565370363EE863536D62BB60CDFA85E6BD8EF33FC4354ADFE853D97BB17A58C6CF67A76BA1345506BA3A90860AFA6DDD48CA7DAD0CCA41D1CA6ABCE4D8730EC8EAA22C738405DB16C3920B348BB54B3155AABFC262387224F4C107602C50C34437306A1C1A70290927933F520FBE6CDE261E69ADE49A461C331D3525C52DD9A38EDDB1A5816FFC60531FA783ABE7BD382342DE202AE12209FBE64FC050A52E45BE395A8A5EB3A2EFAA38856CFA45E67899D27B895D42BE0893CB734B7EFE192D2B8B0B72E4CDF93577080A300AB9CD029E867DE0D421F1013602F34F1DCB03260AD7F32C92D1DF191F2F96992F4E8CD8B7B2C163C10D3C71B12A3F670AF45D0BD0FC99702501999180B0949DD0FE32AC354DB0F34E52A4279B4B8CA864D1CDC436CCAE2D81F757CB1AC86E6D07F430717BC5CB12EF3E0F70481CE0128BAE6205AFAFFF5338A4EEBB6FF858045263951D93F858D14E6DB3983F3E3311BD68219E9813E77896DE6B61E9491EA1BE8C92696DF03E46F2C670572F2E15848514C2BFD39F75C6B010772D20AAA01A4C34C4149EF7225E11B1A65389D7512BCDFA3C8C9E24A1411ED5AE53C1AC2061F6177582B486CFB712EF124462ADCAA7B5477D6598F01021F03166B041D3B437803BB21F3BE0AF478D534357E0694BDD5B75B8B1D82F15431C91BF1F2B8375EC640EC65050C73DF9143BC4F38160FC83F4BA09BFBD89A6E13C82909804F229B58D6319823D5C1D7EE971740344CF6648B29A0AE03F17B9A9076C3516D137812991334ABF6F355327438293E0CE613C4673AFCF74C82FA107C5EE16DED435CA5FFA09165582C51CFFD7BB7A6CC004512E91DAE9770D59F77C3232C0E2DD458803683C0E43B495387C366C134328EF57232790B8E30FA1A2B1D20F39EC3F4373E5D7414131AE1CD8C1C567EFF9A6C0DF9A5B4A6200EBC501B82966F95F9835B73FAEA41A8F8B531E29407548F813F5A81DA03FE0036C0679279AC9296A434B103267C2492E9EFB31628BDDD27F5C25FAAD18D769FC308CFB72C425A0D244858400FC8590CEE072C7CC63CAB75AAAF37EB3BD5FBF52C5E95E5737DE8196829413557D4FD7CDA4D0230427D4D1A8B282E9D2639465D56F6EB9194C66BFF6263F6B1DA742F6B3 +smlen = 4035 +sm = 447DBF07921F5B54E76FBC2EBD221A05CCDFF860073609C27067895CF3D85360B8AE22E22549830A539A958E65577EFA1D20C327E3AB0A28F12160444B10CA4718C2802695A4741EBA0DE0D78264E7FB602613D6939282A7998064EAFA5C3DC702A889E91C126CE5B5703B288C107BF4E8B347E20513B21F6902FF03840F7CDF906E2EE6246AB7953ED236DE4AB9D97C203D412D70A9A0657F2517158FE49720880AB12CFAE40A4B023517991E44A1C9E841FF14E075414E7B45743C2599069FF2E9D54904CBE5F898956E68BF046A4258FEBF3395FC4F3564978EAA08E089AFCA606166722D16C7E16A35036B40CDA11525739B17DF80F7BB8C117520FE715DC7A5E72C6C2BFFDC7D708137FB87D6137A4DE083AE1222790051CC7D3A717C02FBE53574CAFE98B31D2DC4993BBE2B95814F3DAABDA9679971598845A4F93F12A3AFEBB16EAFBA6FDDE69BCBC7DE75373D5D73B146B595E4C03FDCA24D632137321A7DCDEAAB8A439D356969C7456893AA0723884A2CCAB89A04F49BA77B7831F8109673DFDA5739DA312714AAE5673382D219CA1899F1C8AA136DFD750C1293146ECE69A8CD3D261381963EFD8083D47A0521C49237E4B4A26A4D635CE16188C75EB742D653276EE6553FA5EE21E1C9DAC71B2872F57C384B27A11706D90C67766E3D333056E396FE65E955226D358A1A40B40B6B801295E865A7ED9FA5B6305A242E0BC132B8BC0BCF1A5F9650F74E7C321BFFDA373041716993EBDC2F917D641F9FEB4DCFA9E4C52D845E0F4B3701C07A671C8EF72ACFD271E4AFF8C403F1FC481408F403B539472BB828D2E212AD7DD6EE6FBF38C5890DC82D29C44B9FCE6E30962E11F96E16CE654A296FE32D18DD05309889CB65FCF8E8304D6E3ACB3E0F09E570C44E7B5C8576A92EA24B5EE7896666AABFFE79CA8426FA1D7899E3CB9868ECF66777AC68F78E4DD25A0665B5D0DAF046275D49A2742A5E3E38ACC90EA5A15EE888C72F37EC0B3A6949F05F6419298D14CE45BE71C2D4E6DA9E4BCC6813C48CB0C0B94D0732004FC22C2226349C807587FAA7CCF9A9ED42DDF3874C59C8E8F5C5B2C710A186EB56F1AC184DA925BEBDC85C3DE1B085CC6EC7758D0FB9CF40C75D86B027B681FA18002BEB5B909CE4C48A80CF149BCDE194B671F39984153C27521D370DDD8FEB2F68499281D2EED7FFE5842F84AA3FEB9689D443517D24DE9B791FAD27C42D0E06651E3D2C98E1F7AB55F0DC39B481DBACB269E7BBC1570EF7F454E9DD117D7D871EAC8B94B9EBDF57BCAED36263D639529BFC1CD2CAFB83CF2C8BF5DD4880D0AC9355A0ECAD33B92A77E73095899BE4DC7FAE2A1015A2BCEC9E34918AF04FFF1485EAA7AF9261C1AA198BEE98481EAA3073248FAC59D202EFB19F89143DE37E804CF1BA1396DCE34DD919BEF899D30C8BFA640B907A63A6CC3A46CB28C3D3E4A2DB505E9AF74DF60D72B3650445E0636079AF6A1B156213B391964E0BC7A5176726030FFC9769AF7D57BC845255330DEF98DBCCE9A604E894CEC4E9EDA3A97B7F598911DCE5C7DEC64A63F6BAF0A96157F72D9B4CA308F30F5B8792BF2117A8D96E8903AE7532D44A2CB97394728B16999B2B444CC2AE533718B9817FAA3449D599E117464137B4AE6365F6EA931128A2EFA27DFBFC2B2E46A9B4FB4B562ECFD5BB2653E3D109EE9A8848E9E38494DEDE739EE4445AD03C9AE7359D6F305CE61488C019D2497B259A78DA832D62540F38C4E135DD44B643A1014EDAF5468804EE3C6355EE2050A50B8296EF0AD4CDB09CA276607228CA0895BF20047A306A82AA8A9597CE1A06F0622101A13A07C090FEDF628AD64AB6188BB04B4BE92532E74E36D450466190B28792EFFF7BA556F42F04710DD8902A3EB6B2A72AB0AFBD375D35B4F8E68F8AB4A8C5900BE64679FB4885D62DBA0EF7E79D21479A73FFC7C186C03812BC2187180E4E5611E927A64E1DEB508D1DA313A48088A37B509B0A2086242E425AC192270FF8A47292A1493C5599F2F2FBEF17C65C0C0B9A39C41C4B2C6A05A309125E0B63EB8927822956163380FD8F00C67B0E7083CF21B8A570420C6E61264584CD3DBFAD37F983E8E500FDA751FAEE0E18A0D5CD5896277E3C4E3E8AE5528CC1535BD36F5DA2014F98691296E8B290F4AFDD0CFDB5550E0110C9295974DFC0647B18333A37ACB46559F5F4FF18525CFFDABF6AF441895DF08D0AC801357F4E4209D1AF20DF3111046588B88C87A14CDD91070127667A46509BCD9F1CD90BBA4AEE6D2B318ED1782405E17EFBC85CF09E631490E3ACE6A4741BF7C7D6CB37027D22047ED8BF42B3C4E22AE7A72296A7A0F818663FFA8C290709866822AFD9B07409CF0CE8BF82E95796907C9B19F2F0801F53ECF589A6C47694E4EC028AB6245D1776D5A6328E11CCBFF9CC1407FD500B451C646F2255B4F51437BD5BC55458760FDAD84C3BAD41598EF0518F7F3D13BD7706A97DA5DF2F9D9F1FF0E506FAE87FCA7A473C5728144CF8DAEDA3924AA7057E1CE15BCF9119C410F5B5E55AEC9F7DF1C00299203C866A7C7A07D1C58BF9FF90F74E2EB49E4DF43E36EC53A9C8023A841EFD00E95032C35FB67623C7985FF4685B8ADC819EB95101B99EBBE749F57C66F86918A191BA5DF4785FA9DD353317A22DE5E0E9E7816174D42806CF13E307C15FBD72015B37FA5320A54920E07AE95C52BC19FFCAC46D5494F1DA574A5D3A7391F9C758F62B35EB500A77048B07960690C1EC17DD000310EC8C1702879AF10A6AA6989B86248FE26B7C5B15A4C97AA5C600AE59110AACBFDD310F143200534A73F5052AE910B6A6D968B0AD8D4241426E957D59217DF12AE2746B0E69EEDDD9CD900E001613995B8E142C9B98A35094B143AC595A6CB7BAAD9A86BDC75AC4D07DBEDAC52D95F7684D0DA1428BF8FE3B2D5AB64D62286A2B8898F55AA1EE2C72550632F0B2746BEEF9C937A2CBA4DC1CCDD4DC6BA3EB050992EFD740E393FB96DB54FD2905939B9A4FE09CA1CC6D6AF1EAF4E1E70E358C27A592D24805CEFCF91B7427FAA405D77E9A4CC993F4A97446A8B74A16231F023495FEC9EDAF0661C9B97F185CF51693BF4625A931BBB931B1DCFF62D1805E1030BC7E3FC56C6DBBF9DD0DB8943D6C20328DEA5FE6B3E86A02F081231E04924B3F2F682B8C6E5CB083EE94C34E82C172F41CDE3C0D762518DAC082DB58E7A6DE7E422D4AF23A3030411E56E693CEA6FA5B45ECE65E4A0105AD37685E2C70388DF95667177B4619BC5AB764A6226AFF78FD249E3728B586579F046F7E4782DFAFEED8A7F3B4E4EB9934B07B8CF146B3C170A8C4685B6176BDDEAEDCC4868D280396CD0999E148C04807A61CA86FF4658BD8A842E0A6BDD4EC947F21CD55D5F17B4A10FAA28D4C3F6BA0C795DEDD7FEF4BDCFE3EFE012CD6258B44F2F57E77A422BCCFE45E1181A1F98CA51E7B7EFBC794838139BAFE965B638D2B33B81C502D8302DD027214866961712ACD8AA0E348409334EE675B7DB5A420E8121EB9D2B2277F51301326A25928BA4D34D9F2FF41DAB067B90B4115915BD9032A4EEEE61F4B054B96DF92A0E9E4CCC64A36410DE673768E3F3799A7E465D2D8ED1FB054B47A484DDB154E0651E22FCE50E963A2092C8A0BD67F0E28D40F8B691642847424500D19C85D4868D86BC028FA6EA8D962D3373DE49681C49C6EA091E20DAAA5FE485EDC2AE3371DB0952A8D0E15059AE89ED54B72805BF11DE38CBCD8C72D62F1DDBE4B5333F4A2203822DF55CBF159349CD4EF9526F22A016D5E867EA1572A9F6C6232925D8B68DD93D01765F4ECF5CC741C46F41955F77C6D777440D4356AF56321BBF938992657CE876F55E87F3B72433CBCA8614F6820BC482AF4C870E9F27DB4FFE6A33078F6418B4D4AF122A1F2AA50974C4637EC9B1679AC856BE18627C4B614155CEB83BCE5A11DA034C327A120A180C2039582783CEBCDD374022F57A2343C249D249B836E2625045E256300C7F899D1DE34E30AF28C4533F6A52A1335C28C3D5DDED5E74EF5958D4E987C696985F28A1EA94CE317B2A44EADC6EF47BE608EF78BD17A4128B32BC6EE9804EFDCF7AF34C2565C2E48173AD430E3239079438028F8F629AA48BFFE0910669B87211E6C4837A2367C32B092D9B408E898B4A327692EB153A6CCD284D14A157A4D367ADAB886D449152E7D162AD5C19805E0D92E359219F8DF9F9D0D45D95EE5507F910582CD6750D8FF737BBC81FA6F03291F91EB7865325B5BA5DEE77B11505141B673DEF82C6A328B3F815CD34C878722F1798BCF8B44073578798A312484808FB8FBD3EAA2D709DBF436A0E558822B301390A3195636832472BD363BA20ABFA0F99E6089D760B8B9684B7CEC00B7B71E50F84FAA9F10D95288978F6DCA6298386961F488B50E28F84E08FAAA75AF13B2D323CAE08533A80D84A3DF43118EE3C3BF963F8FF71DEC3682F6494408C08204EC4F7EFF320716F907DEA2F2B5027F77274467BFA5D590F722CA6C9BD642549F4231DCE5144AAE4126618816C66AA9322E41E36D24F32E07A2F1BBA710860459DD18BB60AD76684F0438585C69A8BBBFE6222350605FA6AFBDBF054B516164798FC1C4EEF0232A377DE25EB6C8CCE000000000000000000000000000000000090D121D2227F5ABE373CE1F6FB14F2014F5BC0071B17AB2C84E8845FCBF4B15C79FBF2E5E06CFFE6CAD9A283014A975F81C9216B261CBC79EDCD58D0E20C586D7C641E0EE97221BEFE54DBCC56A594DF103EC24B52DDBB6052D1644972640F39DEB98997FEE7A252A65070798B7E46707FA440375B1BA705B3ECC7EAC56D9C45297E585299C7D747B430F0D01E82081C70B4A87846F90267D5163181DED63E089A00AFD33B0E2B3ACE91182D8CC899223CE65A5D84B86BB3E8B34B13949BC800F2145468BA5411EACD6A6C331C340D4442D28EFA0DA959A2797C7181BD4BBE6E6DFFD134CEF373ECB0EC08590F06BE0CE292D3718E2C0EFC7CB40F1DB26F5F38FDC82A72F81AFBBC16591EE02DC818D63CAE69FF0A28F942F7E07F6B0A741F3F0EBE3D0EA5859024AA408462D3D268C23F95D717C0A685A4CA73AD90EE923DB57CD6CDD828B7AB0D4AFA6A9AD7E32D407A44D7515C0A6AF52A66AD72119BA1DAEC6514DE3F8B462EC473072226AAD61135B0F5EC646BA9A127C9894E51FDD1B2D38011A2A6D7497A55283133695D0AF9B3FF7C5A8FD667231F9E511E3B8C4C3ADC44D02DE08C47B2382DE67B32826754C6BE5231CE0FC657341E20247CC6CE574F3D1A9376AC8237B49E5030E877A4E33CDE25D838EAD659EB1678706C759707FC66CE84CC968A8334C18F1632348824A6985A0331A93B59497B70C1A03A6848F18F5992972BC79F07F4222D2612797F495463836AE6CD3858D5B9BDF744A1CF361B5D454D41AC899A4FA61081B937CBABBF0FFEC1B31C162224EA36CA2CD7FCE54EC1A504932ACC5BD0B17A156DA7488F7017E4916A687FDE7FCEBB2901813B07964084AB0447A94DAC3A0D3FDA05B9F497CC1555A8C74838E29CB8CE89D304DEBE419D26BA7F3DC6E9526BD895495A5FF1D7EC83F70D045E306E7C2487A52CD7553F062D31888EF7FD27F667FCFFA984AFE0B9A4C4E85CA943812CDC157C5486B0B5EA6DA05E4BB8697113190321A976D1806DA129101E60A28B7 + +count = 22 +seed = 3222E4B55D6767E300FDE03DB3D8227E19FB8B08EA9B923FEDE18D699DC3694EFFA7C4DAE2AF57E4A0162B7C564199BD +mlen = 759 +msg = 4C4697A7D8195BC7D4B8F2FCF3A7E9419E8FC9AC6BAFC5D658260511C697286BFE44E2CE98C21C98BE42E5AF0FCEEF8AA54C5770AF287A81C7481FE3391A6111AE6243D545B2A651599B45931D7640579F8659A8BD6F77260F235F71476ED64714FDDB70C549CBE089322130F7B0A21F530508970D55CBA55BAEACBEDF684C7979078102ECFFC2C3F182F710280CABC2DECD3D3B5D3CE908CB2307B00FCC0C5412A12AECD041B5F70CC0149390312B9C81592BB0E2ECE83D4495944E29AA798DE67FD69E2BD0695DC573F78D8BB48E6B8679E1C50D1E6E58E218B77EE51597EB43ECF7301D86F457353D60E98CEDC95B4A76844E889BF7E9D03503757569E40D55AB43D63293EDDBB579FE981FFD4DAB056F85006FFB5E759B9C16F5F6B235D7DD78458A73EF37118EDF599AA504E9DB9AB5DBC90B8E478F3DC1F35A7C4604A383BBBB410CFB2C5F746F83EF94BDB2F244D421818C26827D5B7D665B8A802181EB7A9CE95B6633E24D914FECA7E969F64038ACC3009B15168426EDB67AF2CCF4E859F5C616891D355F7910ACFA599C396BBB2D2782CBF1432E6259FAA77730B6B86FE0D67730152CD2AE0F9B0314048CCD25772C01FC9773EBF06618A8CE1E940F48663427775990CDC41C4DD3E9AC6EDA1EA50E04F1D329E64C8532A7AE32238C131753D60A25810A5FFBEAA9007A6984EF69EED92B777E079CE0FF48C2AEE9C18D1DB9F49B5419EC6C0E2212DDD2E2FDEAF0FE9F2B84D9C50DDE86A70FC28BBF8918A973CC67A36E97CE3027D73891E7AEB24BAF4B12A9DC8AAB5D6AFA380BFAC3703D2D32F1E40FBB532FD6D7D710DC0741DFC7EABFE55BA5C311A00E3BE55C2EE74155E3A06685071A962D7532AC76D59FC187EFF01F8D339F74323732168FA5D14F4B2A72C9164A04A6EF14BF5DEB1833E4BAA19A55AE590F542D4448E0EAFF0E0AFD2FB30FD671631B9325F4A0BAC9A43DCD2840185A2F601117A625B0DAD5503578537BE2A535D2F556F371536BCF68C0E01C96301F08E1567DBF9D8504096A8FD89C086DB695DA191099FD1E8EA94035276D1D +pk = B281B65084622200047DB5D4A53E840CFD986EE70325D3369140EA554AA95B05260254DD8FD77CFD345A1E53DC9D5CF8774EFE3476B76E244C82676FA7382BDA5297EF0FD280D283B298D3C64C351C7994B5EC5721E1290E86A40AA1FC41C59C8A0A3DBDA4A55DDB8ED99EDEDC1B9791AAAD659C2BCB886A9E72AB44CD9EBBC44244962FFFBA70F7B65C05BEEF70E993549EFCA8C9484B9C68BA0C0E8ED1EA094D1826CFEECF889B800E4E7DA2570075ABAB3747CCFAB06786965D00F11080CC3C7429ED7C9E02092D4320AE4F5A583F1ADDBA959E1856A8CD89D311427428048747E8226088A901370EE27391B574ECA25F4D0308FA85452BCC96D9FC1AE1280D183DFAA5DFE624F8C7E3AD04A98D7A9670D10934DFD9F9F5D5957CD996D0564ABCB1EC21DE78425BE95E515449367B5E0C229C7A19681F24E18126E4E670C4BC58F658722635538D5EA35136A9B272F97BE954CB4B6A387BD829244517AE3E766B18B51149439433782497AE179994A1AA314DCA63788600F09F8401AD2BA60DAF17C0ADE6203222EB34C0DB29B14ADADE0E1300311A11BD38F718C01F456A888E83103341DE8B46E47FA6427153DCA6FAA92A902DAD0116E1B8E6C8E6F7AF3C0D030BCFFA34209F6853619B81671D9AD73A2B641B2163164BA6B0EE3D05FD20DBCE31A307B8DF96ABDA8AB754B20D4C6F0383963D2F373B4906426B77B8AE79FFBE66E33BC68B39AA826F34172F3FFE7279A7FDC516A63E41A44C242F871DFA94AD5AD66746A2C7F8DA17B515F859998650331F302C713FAD931673CF57B32241C57BEE710F70DEB407E3FE6CFB236AACFCA139825E754687D24CD358B55C0AC07217F926AA43CD267CAF2AFD2440D8AD8D7C5F8094665EA3307676EA8C96D5364CFAE86C5CA57CC4E285E5A9CECE9BA1C25E6557A7B17B68447205AAC2FAB2F44FEE136A74C829B60257834AA667DEA5DE71C966E447D2A932C9F23EE191905FC736B39BFA0C775B10E91E571EF1A5DAB9DA5812B90F0A1899D4382B88C70C01302ACD1178F71FD9C6716EE001EABA30C10124717743BEB9EB05AFFC9774C9BE7FC9038C90D098F1F3F13B9CDD8C32FAA632EF7F962812109DCE7F914EF2CE69A31216FA1ED734F7A933BECB8D542B7229F0D361DBFD95AAB2CAA5AFD8DB07EA8390313B3AB51148980F5FB5991C1F3AF12A6A3C2A2F3C1215C09139055ED405AF81945BF5D1D4DA65CE27FCB12BDC6BFB57C79575CA3F3C332173E07868F185BFEFD5EA90F4B63AD63297F273864C465189A0FA830337F5CB255D31EA7CD7A8B25AC7242DD16BD935CF5C87286EA00F85516D45A686FF8ABD9105D5610EB982221834EC45AEE447E3D46333D8C4CD6EF0F35FD1A8D2954A5603B0406F766C0119E9332B61B5E1C944730C1FBC024A0C4091FAA47565BC5A0991DA5F6E50A6E93BD14359090D8314110A50087855AD579F529EF6D655481F1ACD1F53A279391114D1240C23D646B89045FA12DA4632BF83BE90DBC439A9ADDAB125FE66D9FFA077256DFFC93CB1E376F23CC9F59539A8473BC28866D708FE8F34BC1AA72E2568CED0A82FDA4661B46BACA7204E19B563EAE201DC59D702935E3FE5C13D665750A03DCA956F5763F9CE0FF359A9EBAE201DED9006571A8C5553F5C4B8BE53F46889155DE0BE7D25AF952752C64A9B5CBB1D23A783E74CBD75B76E8E224905787979DD4004656D5C6D05365C591162FF49814171CA029A9977768D0CB62B3AC566E20A41C5F24A9F0526CF0368670F86DD6D04F01FA897E1F6B07D3304AA5CEE4A1664D6BDAFA36F2D48869CCBE120699DADB225162CCE66E6E6A5C09DA49367324F5EF2CFACE1DDBB4D4D00EF8E3C7DCB8639C55DDEEBC02CC99F014C03359D6BA4A3D40BCEFA0D74F37D88E9D71201D6465B2DE7F2A37C9BA98F1A13635A73CA6BD4FABED224700AD594394918E1D63164ABEE38962EA259BB5A1AAD27DABFEDC85C8DA4F400C0D84B03EC10F2A9E8BFE5C6751454EAD3F9468768F192DB829AB7A943428A8F0CB16A66159967ECE446BED712B8A2C96ECFFE1A76E0FBA31DF27A68413EF0E1D73B262903739C3CB4EC93E8F80B4096CA426404FB50A61421379AF4F5FA18B447940B255964A8E67457BE28347FA95D2433B36B2BBC0F78BEA45487B1CF45A9293B933C0F5030EEB5F54477BA7833B7C756D11A5C96F4606A9F2CF69884E156B22942D991DF4AC1965EA7E5F690032ABF3536415C647DDDD4111E8089B8240B51AE40C5F9EC1D9A875AA3061AD8FA88BE9B49E6286C09DC895841E7A04C810A9E9797B66CD3965BC5F4C21DE4D48C67C14C7875A48A1B2C9C8D91F41B46D5457AE488C3DAADEA3DF357B18C7C2B257FF448C89A1B8748EDB4D743A6952E2BC8FFED575F230899DFE86935A11A97B23B13D11C698E04058E2EBCC2CC39E717DADFDD6408394DDD07FFF017DEFCB249A70C46FA9650FB18E932AFC1BD4F2DFBFAB80C46B92C59A085C288978887B9C2FAD1866D2CAAB6393A904ECBA7B80F1AA8A45FFCEEB25E968D7FD5307243A3A50BC0AC73F8515C44B664164CE8B6BC29F31FF85F8DB7E764A1FB1F842D595E33091BA85F2FB18FAD650C339C0CF41ECA02AA54CED6EA1213797C988947167DD7FE982143DC6F9A7EE5FA5873ACF3B23A9438AEDD20BB0F359930FDE0423EBD5D80F3BFFFC1F079983AF6C2A7D2657A0121DFD0AF35361AF5CECD83F063139E25DC591D11CA925CBEB1 +sk = B281B65084622200047DB5D4A53E840CFD986EE70325D3369140EA554AA95B05ABD0F081BB028CC5F066A3FDFF24DA19EECF3584022DA06645ADBDBE9CEE590B7438994E7E7EB1978DC2671433EE633CB32F22861C63A0BD9BF2DD47100AD28E2033F9D4F08BF9778A307B863AA54424CC10ABF2E7C2F3B611050CDBEE71AB43672326758482432061057002136351426157707038640183050032231422761705581617313201520667156774646111862117347712586718531816587257163000003662667664457887120500828416783724278571235248526667425314182826826425121086587611542237770117672035675438576764757848401638848836587516250536540462017285113506416065368852446660182145205646686124046220063544623070255071826632334676117837553104828428300312860504500632156025822645168408277161181171385013554355037308736057862551540716280852363381348367483020880087332318378121152430277742431323421502522806142447587363801012280627756744314873177135517401854064420250438372327451012842477444462038056421602807630182186324841822013506686064103210745100514640337161356645733525728531266314567406375164732032326683047783424050225258713876148574881252157443262850855215501231361367820361261151204017888817764832723625848015001456487426627437130825142625380587024316264308331545686232444425156827818877842670541844510562852686732483631611286058211540543572662578056258220815208415231365046225861471727452220648238888184506074364060447833148851261328744043347150703134710610232253055827527114317527388664038826842370672837335287830222445227623232612110300006666271187458315807077224514105451668135215327545033467364885804271046606312710868468172240465813426725404022315484300273583652673662820026284231424326761861127481626747468242457461247463160036562426613172720522776500582614814842240040225238301277208504152542255262037343630523144385643310022568077011283528617751466577306885333617564000327012185360113283653406588517177206655677085007532342553544675206047485412858682667766182403862118826352138664764624885434430531022443850755465652632586028101635405471735728773228775140135721122846110538524116587481576118357400276006450022086131031212650335405863577187387607203437037148820824025644451780217774034410123450261748517217677120285723473350820465828555238227475560353555030587350301545337680484623216408558607802420018738310286012364121085517052365756231508242765568360834036728561535383068735721788487163238277306081357157574743481126504835063424267128718460613353600013451788053037761064328736131837327337474210574437263062365408350253761156440423328422375650811102724677568014148461184768627541806812825005272420046631807460303847823017477141350858287543286427762115818803872080433665527786066717715034287086134184261208856002233755086374010748402736654453648704552431036055366285715564405077362811607841874815471445088853440310420406525841515485107218042743705706372662823807172152053681853753354145743084131230756203724585573674124347274616143236862110886366202607301477520842323848705155715111305477071305334677850362403335855326564435787606112553853665536353788837550270811628131803631741018843328501383634015575162722620076787678704508113374124835475600867126886644778518221D04DDE0EF329DDC1D8E9EB192C6FFABB1E799D0DB6D6CDF127CFE2CADFA6D4BDEFB8369D697479574EE6701F4D1E901C51D5EFA5C872381243F2F5D9702D5EE42E8467348EF6C9ACEF3244D3D521888296E5F4A9ED1E17491C4214E736FC803A42F859FFA4F4FF3EA942E88EFEBF91B3F96297F6FDEE75FC38683ACDC553DBD6DD6EEF9192A2EA7C006566ADE637627FC083B058DBF5F71F412174D2CA33E053FDB17D9F74EF3D212A8BDFB05C40A547796FB7D01BA785A092021F018B9F01B35385275275F0BD390370D159A7A2BA2C5AF26A44BD146088F83B964C84166388385C7123AE55DB809CEFF100D02B8BB89C6C237FF2DB994375AFD6C10C91D3A5FA45965FC303C0380BE6B1A0B2A546CA394EA911AA99B9CB2F88C5D1C00B8205A0BE4BB82A8F1C1C545C8F51F2F36B24B2034BFC74A5D195AF6FC1199B1001472799C69A913819BC94F4748CE02C372E4B135231AB4024386022C3AA27EEC297096DBBCF002B5DB7586D53263171EA170633441F1FDEF5A23D81A62325870CA2498BC6AD416E625314301AC43D45EC3E03097CCF4C406630696A099918C6395755C60A1C173E1EC9091C451A3085CB568591CEE74FC52AE7CEC4EA51EDEC0ACBC1DBFCEB0ABEB147280C3A11A29A3DE216B6F0C9F39064DBE217AAE5923321A741F8DCFB857140C2AAE7066F48571E496F20E72D7F3AFDA181C01A54EB49457A239218135EE69749B28C264102312B75B9B0244C3886A879C0CF626A0C07994EE28E0C96E4BD35BC6CC82B2D65BCC4CDE66DD5C91078F1AF315D9CD53C84D5C7FEE8BB1F13A6C72DC8069539DC78D76017E63BB7E3997CD5DA89C9F226935CD3664B4EB0B099AC4611DAC4B8BC546FA89FF0477E8A1C528EA15CBB45C2D7234D6D59A2A84B4B70D14B10997BCBD7E4D6FBCED9229BCCD37F4BECC3540C2068533B0E5198B289AAF9D2FB5D8CC99F1DBA1A16ABA809C4240EF3C5560B7A22512F75A2492C4C558C14BD0D9F51C6853C8323607EB4F18BC23D8A92A01A0788EDAB2C1F495A4A33E18AE311BBFCDB20A8828ECCE46BD5F3F31AE6E03656238FA6AA684F26118C10709BF3BA8CFE87ED0F556D2D9EC507817ED6E490031AB7622340251079B4894C6B619738CB3DD77BAB7F41F52C067F38CC6EEF694AA89D2FABB35DFC525C18266DA7E9474E7E40C4DB828DB371713A45EF0E40BAA5FC23115E303CDD6EED8A73307C17B6B5B333A29C5E3A452AB606E5A561C0420902360929193EC836F8DF181E4114A03EBA2AE8E5A6D31217FC807F1DDC31DB5945102B9509C0FCE9307EF837AAC55FC2B3434A90769DE341A997918D1017D234D7CA62A3BD4FAEA25FFCB8319710D13CDE140B1D99C49C07962DD7FF85DEAB34ADD59460D667486E4837E6F990E638FCA3B33C13E9011DA74976E7B7C45313559BA1C015D14AA9AED3CF83E5E8626E2F8641CC7367EA424E572217633ED77C988865F266863C90BB3BE0102FF98E87623DA562BF8FD11AB8B19D4FF124A79F5C31E8E9F64304AA506DCA5539B46FFADDC62EE181C45E113EF36489FA1F8301BD8646EB532998E53F8F0B80798161BA44624F23FBC14FF4C7E99726A56D791A42464DB0F98E36BFA1BA85351CA17625F761C67232C7F5E058C3E33CA6C0EF07D4FD1AAF13E876E8DD7544B253D28011FBB91FCCEDC7511B70680336E4F501140644EDA9F149C516DB420C248755954F75FE31E2D43ACF0734616EA528CEF30A8446E8995D941AB7C41527B49497B0CC974F75CE576F104AFEBD51CF53BA8537B5F0D62635A46C5E6E60286E942786DB625396ADD12066BC95D942B86E08E289F7FBDA40F1879C77C89E0EAAE656BF08BA50A15AB972BCB6A969DDECF95D0FF95C6E141EF0F3C3B01891766BD8D64618E793B4DF6E195AD4237145825D534A145CA6AB550DEBC844900C10BC10D40B1D74A1E4ADA6DC2F50C42408F848C30FAA4FEAA617B3F00B78DCA60361E5125A5EF996C77331A1D2AD7E3A4E5383B3879FDA56E1A668665E04858F7FFCA683162B94A6411D08350B197D7F0040388AF997040DD2606E1725203AE9E677A1C7B8C8244BE602BF3079C0E423F7C6ABA35B43207F6964B3B33A25EA6999892D510699527C50DFB1345973FD45525327249AA99AA8DFC88C559686CD19A3AEBD519E908C8E24D229593BE43EDA1217CA40E8F2B2E2E55BC6CBA22524B19D196F730D9C25868A4A3CE3921C8859DE7D2D2E2FEDCD051529F162D37B77CA20CFE0C2AE52B5AA4040FA6A808315E61DB4F4D2322BD8FA3A577DBC1F7B9A41A4D11F0E6425AA9A3F24EC17A54E8B78185CC1D759DC7174DDC6E32E8C11F3A485984FCAB031196DB81EDEF305D0AE3D4AC81F227E9EE7D21A7D9F339033058F8C6B40016CC5ECBBBD91DACFE089E46C0B553B3EB78151FE2E68F2DA53549BB8BA99BD3759C4E7A4A6AFF25D61F022D82949889F15ED8B99A9B3CD29A0AE861FDF6C35AB95A0EC9C5BE733DE0C8D2A90D41628520A4438E8DF63C8BEDE03657A7EEB9604D9FA6D8CB904BDAB3A5C29FD411DFAFB88FA4A54CB700C9A7962437AFEEDA0B8777E6D53B8D3D545F7B88E91220E276695B90BEC97C31128E02526C2B1257053298DE97B129BA9414CBB60646D9F4F4CF8474F3F3ED898729D4FA8F53D5AC6ECFF44D6AB87327618E3AA297630A7B58EB1EF75CB54A3C7C3502CBF3D0A7396866ED8B7D180EEF95C31BD3F0A2EFF8E650716AD2D44084FA8A3DD3A6E1F5552378743BEBDAA25A46AE98045C2D382EEDF38E67E0ED61B236BE254EA63F02920555C1F1139FAD4E99BFECA4BF55228B9D24C249F3102AB97D9CEE4B9B749EEB338D0ECBB1950A6B748444C2AE4BABA673DF5C1180B9D5BA70DB0D2405148B8252B9F1C352C66034B5E7A06FDF6D3D2DAD9C5889ECFE58F4130D58991E9C74068A9AFDE667ECF46BDD7B3929FB3164D785AAD5201DD9D9CF69743F7EFE9556DA9C0BEBD846AEE1D7DACEF5E5EAB12ADF796B6D68B21C8F6F68D35168F3BA79DEB462587EA1BA89B705C1973A74C6388FFE82165175D1767AE8C904DC349CFE5FFAD0794753DF579FAA047BD5A7AA1F79CFAE72B60723F3D1744EB6C2977EE3996F472BA830E6EFBEEF850E575EC5436EDAC4CEDBA8AE66606BD2104446BB6A1BF64102BBE1A2F4AF4DD6B98258050FD4FBEBD1E0D182840562992008747D4BD3AA97C79CAF31D8F0E04CA255C7C2DF03023A6CEF614CC010CDE856D6C88252BD0B1502B344F774D5F04F861AE4D632B75353FE27CCDE99AD189A96B9F49C8AE35C56C2AC7C26AE7C8410A46E3318719AB6C3719AC4AC1BFECBECB33315A9C9752E2B8750E51402D736A3195009FEC70D0B719B9D1E71A99B34B3A58F9A26370FD9F1772192310812243EBF05F917749D1079D3BA6E304C5568AB486E43540536A25288D37CCA0C78051CBCE1F7A91E034D38E0AA443C5ED7A4FBB0D5266531D6D71E6238532919A45965871FCDD227C5E54BEE2D3577131AD7 +smlen = 4068 +sm = 9C0C1F1CB2A2E35E37ED2E60AA5A9824CE6B55CA1F17D28078E3FA5EB8028CA351C65D3DDDF69CC9D276232E63E2B1E37CC242B788DD38DEE064C7D15E759306D9359C26A4C784A5B2172A721EC12656CA7B9930C8217BE9C15D1D276CA88B091F9177B9E2C532B1F4BCBB285A74451755DD011F7FAEF386B8F2F871DF950F6F114A796AC6941981C33F16AAE5F4DF23542DD4CF7CAD3089F722556C5FB4B79AB227BD3FD9C740E655C0E17F858C5FA304C19BD714C91C9B434F0924ACFF51588693D349269926DCD6C4BB417F8B059C84BA3B11A6E5EEC116C0190120CC72B60F19F113FD0693A8211404D02515B3DC41E3BA892462ECFBEFB0B2BDCC09B198D69121829A128A11599D83FB3EE1E5432E8B52175CCDF8A61196E02B13A25E302C3073684E2BF34CFEF11799239B7F36DE5B9BEE84813C4C6A2FA3BFDE441C318EF4D5BA24136CC9FB8A9DFB5A3141CC54A7D52DE8383495FE423BBBEECC9FFADC28131998572FA2754063F9593AD4031398B9D2231BCF97AEC21CF670BBF78986A34364F377EE9858CC134FFB1494E1E206B76FDA1FA10CDE2D21B43C04E9BFE11E59689EE4205281F50897DEAF2143289A0989CE617B08CED3680166B5B553936302FC999F5174E22FD2462A8C8797E9877B14475BD636BBA50FF4EC6A2DFD4DEEC163CA43AD3B0C64788B5DBBB88534DFA499EB85C655E53140FEB4732FE29D952E345BD50B542C350875FCDDF1947D60D219C865AF3E3FF1C1398BE3F8E80FE6784D46BB213388493C1B7EC7EDBB7AA611DFBDF0557777FDFFB9222681043D1AD6B01A64F0D4F1DC8AF9E43AC60DB282F4D4ECAF23E4D8135182E59B7370EB133DD14DFA3BE01537C549A0AD68F7372D761EF5BA4B9676507DC22D555DE20946E19DAE07F355FE77E52A7D93F1F1121BE867C0BB01155BA1004DC1B12113A300BA801DE8B4985154B9EFD493BB2D4DBCEDDA3E0C6F035FC000DF25DD351682F0417C5381D89A44887099BCE7D0E7BB3B1037EE5BB89A3C597DD2C82D89F4DA07B538D3AE669895C05E6F62870A7B179981E0C681E71F0DA29ADA5A75073BCA876CD815344F845E4D69BCC786CE460A524759228A8FC9E81945346CEC31CF27D46D4CF24DC7137429C555EA773EE7E12EBE4C5949619517CD2DF624F79F0B411DE280067715EF3FBDEC916B634AF6DDDAE00CA64AF0C9F62D370A605E3F964A6E4EB042D7FDC6E01ADD1D92C6B26D839DE5DD4F8EBAC4C30FCF1950D7ABA7988D6508529FB9EA8B752CBE797CFAC60B482E1BF0A810B1B61E5F16889E73A1908070FC26B9CB45FB02E2DE523D32BFFEAAD3FCDE4FCA73B1A4B5FDBB341E242184D2238C834BD5051582B95D00FFBFBA0C31F6FF7C54F4CAFCB383AE2FCB4A1306996CA0DF8AC42812C1CBE71915A8D2363F5D23007C938CA40BBB6423CB748635AB6D0D701042B0E717347712BCED16AB0DDB0628C66F162BBA2A6CAF5D59C1EE426055C42845C7A98F04104229A92B2B9CCCE8893D25ABBCC42C81F18B3AFB1D737798C88729BBD77904AE0A11B1B4C8EC29447758C891236C4F22F6364C4AB256824CEA20EABD69C79EB0AC4D9B91AC95575B30B72AEA996F10EA494482CE2E013B261501C6FBD78222E7327BC0CCE779A7C410B8F317CBBE26E69CEE3BDDDCCAC2D883E33B75D1E3EF95E067DD94F401819C072EA32045192844C3458F4774946A25B77A3A3E230DFBC6E95519E3FBAFCDE3D2E7DE1F87EA673B59FE44DA8F66C1A239F17802CB9AF8C1328E559541093AEA84E5EA260AE73AADBB5A6B6A35F53419AD84D08EC7DE5589BCF3C707032051AA658918CC3A7DE1AC70A9B0ED1610F176E21BADC4D05BF7A5644BA8EBA449397452EB73B024A32339EB229CEFE7B74BFAD869F9014DA67A9FB74610D975E7C3AC4E71EAAA83B370E245CEAC3159FA141867782F4C0990B34D3B9BD7BC92C494C7C1FD8DE3170345032E9CF578D559A2BD95031776A246A07F919863E14B310B7B53A42723A4BA41369E505BBC7886D34140201D1F7368DE1C62D2236E16E9B990717463E858DC2619DCF35DAAAE3153AB132DEB572D1439717C4D7D5CC5DEE9468EFC11A451836E1C059B00C5B48717C82F2B5D6588B155F2CE46EEA3CFA508208A8C91E9C35485FEEDFE5020147CB675D22FC15A3EA12E4ECD2DA502B7B385DFD3C452C374A7AAD1C042D7FB59A5787B87DA01B256424B97D17901B30DFA6C8406C4A9A87F83412862E5D7375E3BA353D67DB0121DD2A7AE5C4673A5F4EF476FF00E8A620EC558F46A28A048B793F15D8330B48B9861152665C5129440170E5759135CFAD933979A96506D339E8E822BBB65B48233AECFD779EDDAE5DE25019D9133C17F13F65A6FBF58C5B8A1E17F4E414282D5E929F2ACB3634B14EFEDC4207AB0FE8AA01CE1BC29AA47DD9305BBB415826BF8D0B423D930F1E11BC757444690EB7471E4A7CE0BBFF0EB6AD835461808D561FE24AC03ED5225DFFB5373D8969DCFF477AED9547B6DC9E14BB735C33AB23DF62A82B4921321F37FC431B33DD0AC6BE3EB55B6745729F82B4085E8223B836AF383F39E7A7D7DC4AAF728E71D03DFBF16920C97CC70D853A267E048C1A7DA37651F0587593A9BAF267A3F8DA7568612BD184B7CCCCA9E1546B3EACCFF8DB92EFFECA17F0621C8616A159E430E94AD9038964E8D5AD885E707BEDAA845854E6AE8BCB572FBBEA49ADC2F627C51DADD1FE53E21F6C052B965CAB7145A280B15A7A9D19691CFA4CECDA591103B8325E87AE69E9BD6F2F5F1135F61A97010DA1D3A692B360D91FD9F5AD9763039B892CB5D60B8E4BD5C3B08F8340751DBCCC2736B9C5941A8B000F7E0032DE36CD8F0D253A095DF9BA2D49E1E26EAA8141D9B9ACB5BF9FAC199DBB3E45F8ACBF897ED044F4CAE48407C6F73556E9589809E30FBFE35E07EE078B7771D96D8695017F8DE28949ADD1B6C535461ED93CF482742CA4C10E446DCD219B0E865E3D2E87FEA782BF076B87621D1FD29CA6061798E77DEF05B61448762DA1B95D5F9F400916D9E12E9BAE797E8A04F1D3BC2A9098D56441C9483A1CF078001C4F028B1F91D64EC3B47720A0A7F39FED34C7DB052F651698E6A3F594609D148B79A0B64D78AAF475880008C4A80743F600C6D8BC59027B90DAD06B1B1EE877693D6D313CD66F4A9395B3DA15E75324442C9AE62982D776EE93AB7B09A9A52BC4F93B8F84A5F109C0BE86ACCD1D2A96801609F19496656411C1BE843F194BDDCE55008790DABFD13741320193FB62201C5C646C31D36F684471D05178C163499983FF90CFED262656799E5A955854F7B1E99064402163A37CF9C981633FB80E56F2722F0D84B5AACA51722D0BA5B05CAA1A1EAD340787C3EA04AB2C17087102CA9D8C6285AC7B8045A9B617DE5FAFEB5B4FD8B35E3FAEC3205412A3005CF04F0862564F8C6C596C154CA7B8F4D78FB9A518AFDDD2C49D49EE4E092B78587E6076C9F356393CC57468C0279524BABB236487368B6578683363191228AEC0222DEE09AB9BA69A560DEA8E753D65AF709BAAD1122A2C67B0C0FE217DFD53F8825A18B78010E12B8C08D438DEB300F75D9EC0FF9CA5BF9B50A59DCDC15F6FDE00552E53AA59A746CA84F36A8E3DC9D73E8C74B7F6E0535EE17550B9FD35FB62EC8EA3436E1F782700EAA6FD0CAFED92F6B8DC21D57C18EF69025B80CDCB673D654AA1AE1928E7196269F5B7664387FC9B53AE535E4BC40E3979A1E90B82424769D8C8A8384B32CFF7B7CCB9AACBABBA455F20B9BE062ADF76202FC1641E6F16628FEC33E57CEBA8990D24559F7EF3510AFCF94600AC43169B62EEE4F5306572DE5319EA6BEAEF0D1B4DFACA558A95CF707A45831EA8C891BD67C0546616F5223C90C7A7501B1DED0600B00FA4F053729BB709648CE1F6844E906D1F254E56E4E6F120EC7D382B80EC8E7238381FEEDB6359597BA85074652FC4C127E311C7040956A8ED475928C273F3FE920A2C1D5654320E3AFB6D35E82092796D3A23873EEA5D374101E9506AFF50ED77F5362B253072FBDA00CF7D52201E442A58D7CEB669294C075ABDF0E370E6793860D037051C62500FF9484C8D9C686FD53D2548785B808D4EDCBB73DFD6FBEFFAD1CC8D40C620D1DA803A019DD25985BA3DB346579DA6DEFEE31789FE8CF05154B3100C42D74258B909E191D4C33F4FE8FF5A42293D3C146DB9CEA7197DE52EBA91195EAF74441979F5F7D4A3392DDD0522A4EE8245A9B6A17D18EAC3E9C1F143FB7D0DE451AD2B28DB1255601EB3F7B8A50E7E3134E1645D5060E5ED8855AF2C6D8119F968F834F653EF8EC92F7FAB977C72F7262ACE568F6E2913FC3D473B008E6F62DA7AAA69BF611304BFD6E3055D4CCDBE7C27D7D50C1F5792353F46623B9BD9A75895811E4A78011BAB8A9EC44177893269C8FB96CB709B566B6260EB2CE1D924A479FE55964F1A9DB0641AFBC02DD5957A5B749D9EB2BECB7FCC33057A35DABC9571E48C040035F318807482759D33126E05F09BC63E16025CE4E162637ACA47A43198AC7A2B0FABE9C271843A487D3735F608D61FF050A52A0AAB4EE47595D727BACB6018E95A6B81C1D48C5F5FF3336408791B2B4BDC4D4031C8C969BD5F300000000000000000000000000070E1319232A4C4697A7D8195BC7D4B8F2FCF3A7E9419E8FC9AC6BAFC5D658260511C697286BFE44E2CE98C21C98BE42E5AF0FCEEF8AA54C5770AF287A81C7481FE3391A6111AE6243D545B2A651599B45931D7640579F8659A8BD6F77260F235F71476ED64714FDDB70C549CBE089322130F7B0A21F530508970D55CBA55BAEACBEDF684C7979078102ECFFC2C3F182F710280CABC2DECD3D3B5D3CE908CB2307B00FCC0C5412A12AECD041B5F70CC0149390312B9C81592BB0E2ECE83D4495944E29AA798DE67FD69E2BD0695DC573F78D8BB48E6B8679E1C50D1E6E58E218B77EE51597EB43ECF7301D86F457353D60E98CEDC95B4A76844E889BF7E9D03503757569E40D55AB43D63293EDDBB579FE981FFD4DAB056F85006FFB5E759B9C16F5F6B235D7DD78458A73EF37118EDF599AA504E9DB9AB5DBC90B8E478F3DC1F35A7C4604A383BBBB410CFB2C5F746F83EF94BDB2F244D421818C26827D5B7D665B8A802181EB7A9CE95B6633E24D914FECA7E969F64038ACC3009B15168426EDB67AF2CCF4E859F5C616891D355F7910ACFA599C396BBB2D2782CBF1432E6259FAA77730B6B86FE0D67730152CD2AE0F9B0314048CCD25772C01FC9773EBF06618A8CE1E940F48663427775990CDC41C4DD3E9AC6EDA1EA50E04F1D329E64C8532A7AE32238C131753D60A25810A5FFBEAA9007A6984EF69EED92B777E079CE0FF48C2AEE9C18D1DB9F49B5419EC6C0E2212DDD2E2FDEAF0FE9F2B84D9C50DDE86A70FC28BBF8918A973CC67A36E97CE3027D73891E7AEB24BAF4B12A9DC8AAB5D6AFA380BFAC3703D2D32F1E40FBB532FD6D7D710DC0741DFC7EABFE55BA5C311A00E3BE55C2EE74155E3A06685071A962D7532AC76D59FC187EFF01F8D339F74323732168FA5D14F4B2A72C9164A04A6EF14BF5DEB1833E4BAA19A55AE590F542D4448E0EAFF0E0AFD2FB30FD671631B9325F4A0BAC9A43DCD2840185A2F601117A625B0DAD5503578537BE2A535D2F556F371536BCF68C0E01C96301F08E1567DBF9D8504096A8FD89C086DB695DA191099FD1E8EA94035276D1D + +count = 23 +seed = F41B3C6225245C06455272A6A073F363E5F19F09A0B146AFCDFC2B3B0EA64BAA3F90359F32B2D1017608B03064E90AB2 +mlen = 792 +msg = 72713EA55F1E5CCD5787F172657C6F6C74081DE2D70816E8531497965DF02DAC04D91C4D09DCF8904CB152E2138F829386F4351015DA253A5B5EB92D96E537DAE3CE809443EA90332D9C754EB11F4DE586A83B5DEE7B1B9BD547EE7107530249B14279BAA04683D74B69D7BFC8BBCD447FE7706593C01188FE6AD8D0E2572D49F83E93986B380D4169BDD94E3311941DD2B041DFABC5AEA1297C65BB5C8352C99FF838D46B93B3E5F79E3CC5BE5408FE5E59A10D488DD65A997B086FDD96CEFB0247B2BAF7B490317E34330A879D04E374C92ADA33EE243D84DA015FDDEC243B00BD7488AEFE373E8AB1890273A7A2285988E9DAF9C4E7C5A17F54AD6195EDE2C79657E1BCCED0641E20F7EE26EAF53DD8C82827F2D2783D44FB030C95791F41653E628062267A5CF534DF00116C1ED1DE9F360B97555C65CDD80724104FB1BD4DA5785B5D9C24438557E48AEE58D57A03E06D553B05B67E1C8D10085C2F153647F174F7922FB8D2210454F7014BDDBC627756EB7CDEF99B6E3A2779F82088E3F2DA14C2DCB5B185AEB5D6ACBFAD43E286AAE8F84A58E8DF6ABC64E4A8EFD69FEA18DBFA6808F25FD418DE8BA923500B74E34DDA3CA6AD8DC208102DC4A876D8B8CD2926AEA4B3AE11A546F6235ABEA152DBDF43E0BCDFCDC83299207F294A707C8B4D1F56AA64A205C718ACA69B862AFE7489F11B324E7AF6BE68380D2CA6E0AF0E2E20F890F2CF98907A9D43135C03E85E86C9EE417140EFEE9054B46C110A84F1841AE3CFAFE5B4A95D6B2B606D8D0A70BAEA85C9412BC2D54146E9F866800E8E8615A0D64D1D595677E8C88699E3CA6097D47E9FE64050FB55033FAD4D5F226DA8EB5DDF99369ACC7552927ED3AC7368B9EFEA2443926DF26D1C172858FD8A5D4E1D7D39E7F7DF047385D39131184087CDC45B299BD1F7048E918223DA3F960608E853EE49EA667465DBBD889CBDA20FFBB540C9EBBA5C2CD16A22A57B561E01331D6EA6BDADBD6A5D2BD1441EF4E1D9DD11CC62A0FA5BBFFCBED0D27B6ACAF0889EAA5863DD9BB35920707B71A0805630D1769FEA320516E71CB2B125AC274F16F7A6876F4B922C7C006F38AE1F7183CA768715D2AF +pk = 1DE75477423F0979C52E68B9E055333ED3DE68A8AE6B5DF82807A6C411B9CA5761301CE830B980AED0155FA9AB9E3DDA6B6D7953977399001331CDDCFB7F9C2D4046F1CAE6D520A0C6404E42B5289C1974046EBADF5149F6EAE44D1FAEA835BB038467BAB4C1B4399C39C177A3FC39331DCD144835531C0404208184FDBAA21E4D3410CEA46A034D29F7ADD0D1AF306FCEDA9A0EE02E146058896E24719F2E89BE0E2401C81F4C3A7EAFCC19EFBFE8344CD6D22FF0E6A3E4E84A595F7E9B8EF8BDAD1E63DE824084243B55C03E10F55A0F777E68C4B1B7671226D194B3569870166E09396E508D887EE65278337A0863CD11D22D4987666F2B29875FC64C6A77DBD18CB03D6B034D04A3AD93D1D7A9300B3C495C20DCDA7841A21F5896DB7621E957C7361DADF58F7F5999526F00F40D32D9069875FE003D9998F348259A7E6E9B71FF189544C206CACFF91808059ECFAB32DDFF62B1FEE13D0AEAE5EA276B0A40FF0A2B6E929D26C063A5BF13744F33D6BE8A5E105E545CF7E4639B4C3B387F63E0039CF528835201EED9A2C1504CA3E4C0AF7B4C872401C3BA439273A54609B7C10C8BA29136C3DE6DCEDDB1B6E667052696756E9B58391112126C0EA6CCB524F80D82E8CBC898DEBA3EE94E81ECD7A848A8EC983065682607C0523AAC4888DB8DBAD5AA04B26B3CAAD05AEE96AC3A8B2500391A41B1F1795CF221B8B3840EFBB7D90EB8C51F0069FEBE08C139CC8CC33BF0D312B070613E5D67A714EDB617AFE750B548CC8337C0EAE846E1B6A0DDBE280F201952F86D12F47E4A07EF5463D567AEEE0871875AB2C8F8657155CBE1AC53E52D000E69097FC5984845576993A7635BFD349526F803242AE8A8ACBE542979B9976286931F751F5C59BE2B52292D79B5A306CA58FDCFAFC6807254DE64F563B98BE303CE85A7CE53DE298ACAE415BDA729E9E152ADE63F297C3D8E0A6A22DB5CF6610E27CDF7B6C09F237A23E3D5457BD207B9D579348CD9841AB97AE20D065CAEB05FE2CC7D8465D297766F49DD0A5AAEEE3E017DCF5F61F8FC505F077BEF96C5FC4F849060820BF833C658C65D7501C20B6748F1758D11F3F7D54801040996B9476C1212DC7D061BAA166212A136BD6BCC875A424ADFE91E86D8F8AF2B7C2D8D3E2E5F2CA03FE6BB85ADA66D682B76BB2BABC9857DA71F67328EBA8C2F36D835107E468BB711C34E82D388EB1EBDA7AF9F97CCB3B7D965BC3975070FEEA86C90B0FCDCA8F625943747C0FC9B5B4B3265F7F81F7B7CC98ED19FA87A8B33AC86E5D44C99F7707B7E51FF85FB2CBC73214E4EB9A89F4A9AFACD263EFF50F0A20FFB6B4809D549073F5C608E0B024A9116F4759D833A674D4E00F7F37227E76EE68637590B26CBDCD95B3FA8A11F313705314FA3AAA702B4CD414152611F5E4DA5C190DB2D1B47568EC634ABB1DFEB759292151635EC5FC339422977B9A90D103E0F050111464AD8DCFF67EBDD3F2BD239FFB5B0EF9ED0E420DB0B586992B5A389F0030F0D757F992E2FE03740C32DE6CC2A2D401EA140D01E9669FA883D5E7819F5BB98BBD781D4AD32F3E17E430CD5DC4B11922BBDB4AD912216B312006787512EFE7F0C25FDC2E6429CAC5A46EA8CF329A49158AA6AF0C5057A61FF10862E45B604EC9D5B3DD1E53A772B8E4E0A3F4F365A5A6E7A420612AA910F05B998B4001D41E5EA84403B730D3BBDD34E78FB0518D47DE9683ABEB35A379645AA7093A5F2A50EA3C1898A16A3B7747DBDEC82E1F9B27216B2AE8947CAF310F8EFF15B388AC67F2E24524442FE3BCD332DEB3BDA4C881507155642B3EFFE17D61711A669A41D36D9166751D8865B3DBE1719E40905F1E17392490F9C72BAB729D672D104CE29E8499F14501B3843FC9DE520BB2B162F5595C80C910E97F8808030D11E92494E9BB17C7A0F93EC9B0F1E44CC5C68970CF8C0529001F12A334721D72AAD4C7A78B597E83507E2204234474669332170487AC5CFDE9BE4AB8E90EE4E53BF7C6590F15417610D84DDEC76CC296D29BA2B5334853A6BF241928D9A440464815B881B44F280C50CEE11F1C902246EE122AAD89D324426A4314AB019737E303469F9CFAFD71F69C3DAD94A4A048250083869E870C64271758EF3372974B1AB5724A7D7FB571D79A7F7F33A649E9CCECEE3187D3BEFA825A70F0CA9E4B1796FC522C0F694BFC17A03B6FCBC89A7981CDB05A78D6827F2D5BEA9AB49D02B9456C52ACC4A91F72319E096F438F4374513BA3825A1E8E7F01801D2383FB24F3BB178E3417AEEF11E768D9ADB16AE310E80CEC80F151F2DDDD58369E0E056D5CD3098E87204D27CDCED9A7758026B45231589CC88B727B2C709C66C8EBB08B2782F3761C65CFF51405516DC25C8E2D8188A8A1FBF9FE67DA4241913A44B260D871B746D37E1AD0C21A604B24F2D9883F667330C1A6B94A6858650272AF1F2D85FB88FEB55CB608B279946406CE0D451952D4EEBCD034983D28C86A7872C3840E0511B50CCF5663D726ED1A8B0CBD522A683BE7C11E69F87DED6470A42FA13E14D6C58D8D8B852CDE3799FB99F73176CF80FC10E9F7F1894794930816BCDDBA14F163A9C2A822A1BAB68C9987D5E300850CE5AC87E64E22D0942BB0EC7D3F5E96F691F846FA7290FC17F997D19572F0757E81F9D899BF3CE0518F473FF9347E7A301604CF0AF67C40AD04F4B40363C5458842511D77A782249162520679287A35D49411E630E1EE30C7D7376D645881618 +sk = 1DE75477423F0979C52E68B9E055333ED3DE68A8AE6B5DF82807A6C411B9CA57205AE2974621F52B2ECA6D5E192003B464BBD573267290C7E325D13955455747692CA5FB259D7D5CC64D19517E6A0B1F337ACBF456CA57E698E6706C976AA150001343E2B121A0EED5B8BABF1F4C966959722AB4FE933F77CB8851ABB7E78D2B17757730357227354481660560821825064400281388108526848265126232626858625657054627750033410273135822031160100883205018058531382478506478307580157130145484283745418204814315336055646705072528287836421270753465835028414585216543402722624576783624187756602625031288230685720540252812650275514042320301837373265016203622045563374418323220052615532127583551472374561431638565310080716605054554781262623172112828680765307103023305820700487313720402174210516754758681036026538183151540633042676780373378880087026284047311105638217357423050343737014887483178240404140380838146251103183568572877844075861122886623803053016784301732285473222326424687485843453825301702005515623082271135388483345527661234171774646447601227723651725777537842857077832758181763633307068875261381027413803715187444568781704677106523477827808385747436308205476338032402761871065411313223833786251485413038824566613702432126580601125806574018317788121377568470168235641313804654227502362000033186512054846658760583785324316807887377675567484774481404675748300000707518682158605552167071232085641486747760451762621617708308403278855527362308758210461351823421255265646463448178847362007044343024675318078848853082307778443704753165010081052346513375371082441317272028783365684876112057664433370283614083673215402531655755477481233011708672460112803726146776421867283203068731075566787168026361811826303000827376543543053384033251575472825012544350011686516324175867215482522451604618575472885824421865102212270255707155328685546282823474038582168883121532666418703657128101243730437713243754406757318207530510240832876605723424435546773882052235355703552706110786648251077855410210385167624185083445080288436808812307245611418240174844257765451205231407351861135564776374014212770587043650747570303528113264128316743443487562312885743076428343423467170240870108282737006403578420800164503502740783166780445206734343217604184380041208882718511027873165635057774664737008584463114838581075604681835622038266426235227552626651661254251718645330113478684700338606768222575214650850615124326805420731164525278046617058232804626731452461528375270827845477227282365771161045455318336641622180353185510357745561052222373172406637387054245427850861850451673155484175331010016225806834652373288671460263072651423051258165880450614237122200738888661870035102507148145032473608824752432548601750463220875210521614384178820361414051000046323866073500237821223368184603226825271180580803087076733264825161665842320373061551603640605150827366818832770266547306474187077583036235206570347324080626670274414867422062075718781042444885500272731486638137206613707765738551111730140240648165470218832311815377366053560001876453426105380354737201354180735661040131341433375480506286600307058647010001231631307401180544303450473374724277720677886114823458608285246478386017AC20D0CA7C3329298837C313A7AFB54ED62F9C98155E383B560D13BBA48C66033F169F8B0DC6B6C3D468F42833630A167C5E168E3810DE0ABB8F6680BB51044FE86E8F19825AC7B784860804626ACBD12841B1F9D2130DB1FF5795BD4DBDD2C59FDED4AFB9CF20301314E906D225CC864D913A90A770D2D6B411E0E601A0CF9888A5470296703855702693A2E1ED3F93FB53E2F8664BE88497792B8BBB97449FE65E2D9833EF2EBC16BA0D534701A7688629965B30C8A26E8E5D34F2979AA3A5B244CD3AC82380DB56F375A6A5DCB3F2840F553106218AE7FA3BDC179FAC8EDAE04089F174B2D3B17FAEB1EC7B8B26F1B8A1973A4D9C3E188EBC240168410B89E140693574ED8592C2439519F777DB89CD48B03AA4E7B91447D5738ACAF1B8F35161723F2F997F556D2B6C47DF58F1C3EC1BA91594B6928F7CFF0D4FBED92BBEACFC5B989195E17BE6AEE91A531F72B201B8CB56AC015B0222942658F51FDC23165655873BBF2C9749B98D7F2A287B8804A0ADD533E751F72D3DF642A6042C87908D219D178CC9E6D259C765A817591794F37742EBFD70CBF128E0A0129CB9D592DB7A3575B88409B2E52EF4F5DEF117B0E28197F104BE8D54C932B2F1333EA68812EE7F63C919B3C230F5AACEDA22C6148F4FE4B50660FCCB7808A1D1A0DD4F24832DD94452F8AE0CDC3F99DC392BDA424F68FB326DE126841345E75DA24E163EF899626B04151CC061F148282CD61E39FCD6EEC528B4682C170BB9D5968C952C375891E8765CD8DD002182563AF288ECCA908207D5898C906EC7C4FFC5E4A00B98471862E00E22AB882D508E07B898915197AE3B2F5DE7476F41E549C9298011CE60698B0E1C62F90BDDD2D1E2983628322F98CE3E2EA674325A083E1C633D2B31637D80ED26DE42C59E3232ECFCD5FC02862D1D9CD3754B29797D6394C6D459E73D99B41032EDD142E5F20FA21B4AE7985652C0F68E6F8146B7BED7ABB2DC7A2B26A0DF4F570E1E4E636BF6B52816291EA48A881AB69A3BD3194ECF0C07B056CF490CB75E3F11B342BB3A7637BB2745B877D5F230C636BDD7D043CE8C3ACD2E5F2705DCE5D4B9A991F5FB23E4B4F10FFB702070FBEEBEAC9390108F4D648648DE37B581D4E224061C14BA5E71141F70740D059EA582E80A78C4949765A0E9DF32AAC372E7E50048BDA7803A8DFBD13F96F3CB6B74F4A5BDC8171A42B8F1F4A41AC0CA8F7E3814FDD774C3062D457C18DC74130206C5E0C5ED2D55D9B4A3561074F9DB3ED17E739545638BEA980EB0AB0EBCDA2D436C95AC784061118EA31F9D1751E2072E7C94AF0D9BE3FC8667D7851F1A5C3C9D61E62333E4B5F6443DDEC1D28A4CFE53361DA11960E1DD4E406C54F0793573FB2EFE3EED75A83B6BD83836E1083186468AB773402A0EE4A131818F1DB61B903B851F0C90DC525F1AFFB08AD53792F5432811226BD6D88712D8BFCFC49F545F794A6B169539B97D070DF506A8DDFED4852984512BEFDB60CBB2253CF576496A8B77C95029B26D7879574D6567B6490D040B6BE38CF2A39D1B78856CE6CB9072AA53AD314BA98457A8F0469A23FFE0B70998CAE3523BE2548E17AA348DA244ADFFA2A533E4538E6371C4538BBA8EE606B6623C1C966D0346A7EDE34A5FB6A3C6F13821BF2350CD7922DDB2E284941C97D1299EAFDB973B2410E0642896A70B2DF516D4B67357BB3E2922641AF6AABA166915ED49B431CD7A1E77F77DD79D4325258559507525150574DA7A44A2F9E3A74226512D3A067EC472B197C774AE001F4A442CD18E16406FA82BD55410AE0CB59D8C8E813D1945EEBA3E455A7BB0C27421D3B63D7799C23056DFFEB863B2BA81F618C3D5DA985319A586068274E8620171FD9C443E31AC7571018AAC1DBE2033C5EA7AE53371E1956672B266ED342879ED4FE691E5C7412D8337A543D5D1A0A3665F69E3B7689DAC5456B9B0906DD167F205F00D2264C5F4DFA6E2C6E46655205ECFFEDC03A179B1200F1D4658BBCD70F4AF4C2BC39921316489932632DF734AC20D284EBB30DEE8F3BE9A7EF73DE545496365447AE976031DE21B36F5D743C0A44A74BBAA215EA69B9DC32D37085991390FFEF6765F34BCA523413475373446BA9423720ABADA01BEBD432FA0160EDF70E99B2F2C9A364F3E880F3AB0040B195963A830CED65B30A8628470317CE2B8D34C7330E6A2B973BB5F692AA4097511FC15EDFC22C8FFEFCF412B047DCFF3D3676FEE3E8C45F5440C0DFAFC59007E3A093B503A0844B950E1929A02A1E99D29FB5E89022E38038DD1392481DF0DFAD3DF2BE4A2F90E972B2D4DE40BE179663532F1CC3AE6FC27FC9D4C1BE55B4AC3318986BD2D73DFA0E67CA89604A32DCCB66F4C8626FD46AE3DAE791CD323C8D110E6BE4E7580D460F2992531EF86B9A0BE1108CF6C9992A8ABAC3CFD02A092F9804F6B5B19B7D30C39DB32081FAD7846BA8ABCEDB94AA6FFB0C83863A75C557EC5C5420B79E0F6C639C5C8002FFD23D49752B08416D692602488038012A90B4AAB878CA7582908E051A472B38ED5FDEC8F376620937DCB0F6394BDE32BDABC52730D87DCC7A88E7E9C23544837A1EFB11F0DCAFA8B164E2B05DD4EAAC7724EA337C58D112BFB350849696397EDB14EFAC9F03C972A2F26684AED9C0F243AD9FFBCDBCB5B574568CC8DFDBA865A248C4A0C51E858F86A93D684A7DE98107BF9ECDC9D77F6D4A03F404DF21161E0224E7EB95B58FDA1E21FFFA170D2A9ECF76D40957ADA2DD3AB78CF9D6E87B8112F03718CDA6EF0EE048E00AEE2445D0AE2D188255CF62C23DCB0430EB13713D503694B09840EA4E8E2ECB783018917D0C352C0886B2CB65A80A9089B3D08836F76E594ACAFDEC82033BD4806AB9B4EFA65B5CF986C4ECB0F0C0F133CB5D5A3565B2791D39D880807F622D1797DE3630177276A07779B8737C84841C11BBD4F7A737D528C7E531ACE01D55E91E130B61F86304324971E89FB6835A9D6E6594EBCE1C29350026526A1CBB5B5ADAB7522FF2107589A149F62BAC0F8626BA574158310067D7318EB39F0FCD869F241216E3B049167258FBFE2FBA17F744E0F54B8CF1272C070F379D54799B3DB6ED48C4F694CCF8EAE7F3442BEF9168E4789A5A818F837451F7467D0DA542A64A1ECD5454E1534FEB18FF905F185CD06178E68918DEAF21BEE6AF4BC8F931DBF7FDB32AB9E8A29654F8F8C99829108E1ADEDD18BBEFB1A94AB97BA076AB1BAC84EF9E30A48D32DB9AA8B7B06A6DC48A1AA1123F79CE49F1F2F810E18689ED3D367FFB116C2F3D1CE7313C4455EAA7719E3C2CE6E0E89D0E1ED7EF6A971859DC115B64A2F0099B25627AB84A653E49D0FBAB5DCCE634DFD4D8A974E461C1A6D755EF935DEDBC44CAB66617EF2E651E95340F14792C6E56E3FB1EEB5DF776FAE591187B6A053727DF88073D8C2DAABA955D75B4FAF1C6DCD0B4E53DD5F49221D704A9F52E620ADDE1A1A0ADE8F91D1975B91E473C1445272B697DB6BF311019F3AED20590C +smlen = 4101 +sm = F44E7E57043FA4656D91E23B3347D72331D519310BF4D5B1502BBAA19174E43E698870B8B608711F2B692E47E4DA56A3C538D1036FB54AC54429C2421402153F00B3FF0AD093AED84E8769A673A5FF42B58B1761F3FFDB0346D8CBA89EAC85CFCA6632485353A8418362DFCEE9567CF11B85196993EF24E269B0EC5D2808D35131AA0EE278E966FA6157ADB30FFC72C42726038318450069FCD3214CD86AAA8A7453981CBA70ED7F459C28D041CD7F055486CAE8D2138683E0C816217D93BB426B17EF8FD9D3A03D2A7BA9636603795009B83B5429990663A39D65EE77E1895348C116A7401FB71DB355F58A98383BC8B3F5E8B240D4B6ADB71B739006225EBF1E527C35E1A35D89E403CD7A1720850952979A29F3C60D6F108108398EBFBB7CFF185F09F87AAAE67EE010EBFD98839A47E57359AC07F171167B7B3E32E7FF8DA5354EAF126D8235843B45DB7C155FE9C839A047FB05360F86FB43A5750DB8122BC0F6F5C912B21270B942415CF6490359BF042EB4AF93CB089E637DA406294F73CC861BFB3010D2C8F9CD969012B9502748B7B037AFD3E425DC2C44101EF15942DCF4740E22727517E35B29055D8E0A0C3BA6FF8F6DED6D88A4D9737E5A98D9839278C04FC73AF7AAB58D030E5AC9945FD303B0F68BB1973B6F05790C537B4E072CF6D675BA588B06D569014C0BB29D9358C745A360A31B883F74D43BEBDB7F0F0D1D1ACF8EE9AD86ED037AD6A305E28E57A9ABC183EA7BD5C661F65E44A897B4D1109B191274262F8DF509F858922AB2ACE144F2E7D4EC493E1AC8BDD6106321B67C51DD0959F21D6693468FDEAA6FF16011EF5CD1A0C131AC1307EFFE83094824BAE7378B2F2B671A3D016DAB90B3D9F1DAE6B766265D210501BFA5DC53A364B0C436E8BD0BCAA546EDDF1C55A682FAF22278A93C878BF2B69249BDEA83A56D5FF77C7C5D3C982BAF3EC20D5FBEE0B341E4814E1F9DD5FC66D3DBF7BEDF57D3C3D3577978E1A651C0AC6001EE31A04BA7623AD7A939F74FA72174A8AD04810E488D7AED761A0DD0EFC41D2A57E067E7A7B4C923A320698BD1167F1A9DB96FDF3D13BA4E7533603020C28CDE6D70D1E0B9F8173920706123935888E55CC87FF3E88C7EEB263471E068D02F38D1FB2B1FCA63C1E07EC1EC0DE32B984DD567487A4D5FDC3A8A70444871C390C9537B3CFE2E92AEE9BEA2CFA9BD1084CA25A181C4A36C4B826B51D6725A4ACF94A0D93690F8BC4026C11EFB909387B610D435E30E70FF0BB603C1F03BD5F1730B1B6E92907E87DAA5AEFA50E2B6C7D49D3A1D09ADF692F355F4C33968C657EB7F1EB5DC1C52C86D7C826178A65B6BBB835C19EF041482C4E592C7278BE8FBC445FE9B3245555246A9FF1C9AAE3066CA87DDD545164E38CEC15718D0E21F3407A2F79C92D8BA0DBAFA0A1EF000E07A59F3D2074972DAA4E52F3B2BF7B6901FF5E104CE56CCD970B0E86F7767ED173F662FFD308D6B927D7C8BF175932615835ED40B93EBCAADE36FF007413C1BE1F5B59DB689DC40051362FC1C4CDBD7F7FADFC162BF29FE8BB736F5631874DA7F6DC5614C7B4BDBA347891BF5FE5A7496D72F16E01018962AF6AFC32074C73967000B97B55C3AC1E29C4D97F49D2DB30993D207BFF93E071C20748B587F617EA2B44192778E603461F4FB5456040B8F33E2214FF4F97E2E5AC13075580E67E8FCFF01B168B7427F2B6DDE4A0EDE8E298FDABCE64F02C7B27BCBC5B59668D40E84FDC555C0432CA339640A449439847A0E130A875C216510F786814586B3EEC574539F5B27D2558B0DA328C5DB3223F70F5F6C6D6A8E76514E30097DA674D35E3814F3C6ED3EB9C94552A1727016C9393654239F68E3EF6F8DA1B379087AFC3DA215166E7591F0B7E9B4842423C0CB25827747425DF4F8FEA2A37FA92788576CE3F8EAFED2F0FE0FD667F188B64CFC44E2006741AA39E15E7A5183785C66F05B798B117F2D221899C582C9DD88F454CDDEE437143D805D72B9BFABC6D3BD7B1FA83D650C955B1D3F80FD4C82A2722004DB9BBBB700FB3614134B37A902F0017B04967A908ECEB17667BEFF171426ABA0212BF969D371CE6FC852F531095E8E137443E4A40ECC83CA06839241662B87528B1672756A75F06032BAFBA2B1B8C2CFB476F6ABCFDB9D98BA61F639017DE30F2D6BFCCDFBC08889B9E6D3EAC1E4FFEC034243E46179E77A3730AD51D54A1EC8348956B4E903D3A21246DC64A342FCD65F348231F18F6152BE721C242F3C6583D08A9DD6A049F755010D3F937FB41F9D61F5EE63D71EB6EC375AF2E073E4DB87303BF566AC22C258EFAE53A21A289ED5F66319931AEC9B2A1F1BAE282D75BDBC16637FF1F2AA81AA5264BC12D5386A531D171C7177639BB7E071588EBA027A14D836F4B3B091882D0B256D51C395BDA01198BB43381233420677C3AC7C50784A0AE1796A495EA6393298F4D36F93B16CAE6C5312F24D97A69B35F9FB780AD5CF459FE619AB4B17DC56F4120F7E485D9103689B1CE09C35FCEC35F430CAEDE0E4E543D18DA7335DDD009E91117A1C4CB426B0E7ADFF63BA5E0777CFC7ACAFDA90FE0AC11CAAF480F98B3741FC7635C30BE40160DB6160D95AD4FA22A165B0EBE9B6F555877E71F3C43E4982E17771DC544DBB825D3ED374382683B80BAA07866F26DFC6F31C07BEF7D13FBAA138555FAAC34A92C0B18AE698BA595A3CEAAC49BF4F8540F98E619B14F67316BEBE4B7F1960E2413F8EACC465DB5BAAA63AE94FCF96C710053A35F7B41773945EA736070BBD1EA8480B8AA385BEE0312F798B1798E00006A05EE717072B882D570BC427AC3CF91833B4D5C9AA6B830A4920278201B5E4D361ED20B971726224C251C7D69F3FA24DB62EB00CDC8CFCE7F7D045FA7E7DC63CD45DD374201ACC3578FDBFCAB1490847D0912A17C7E3D792D8D92A45FD331CDA21342BFBBA2026607AD1C3E3033EB691A7A8AC8A8DD03A164BB9304A468A1822F90A4CA48A954D760948A538DAC852DB6E10C28D831EA6645132B47C64EF49EE408577DD96309FF8DFC0A16F76377C0F66BD658B1BEA7FB6FD4D299438A60F3475C92431E8D252F8EA5D61ECE6CA53DFD551CA66658B560F248A85FD5296B90896DD8F0026E7F69E895A8377BF92E9D9AF6EE1FAB078F1DAADB35D7C43F26187C2374BCE40217D02134E7C2C471852FF629DFF9C182ECC04E9DF917567BE4E5CE7E9EFFE703FB47A13CF3774B1995506A7E4AE878E5040FC0E0CA7A20788754A1FC1196FE3E50051CAD9BC68AB653382222F04E099AF54A9B3535C35BCF0EB6437723CA578F5C8CE1B173C36292CB894DCF8164A5144125915A1552637C2201EEDE81F392106202B18E3FAB207F076CDD0E418659D89426FEF122D00B5AB389183E55AB7EC9D7E9192A62D228C1D2219A1F13458DAA05E0A2318760C2707D5F0FCFAACAA5210C41A68DDB159D73F6B1F11800B80859DDF38E945A081C7FE2F0BA1C0D27157913CD8576AC42D37807EA5E15BF402A0F08A234B5CC1E55AA2D9E952AA9441BCC72FC8429E5653281F7C6BB320D2D0A88C8EC21A56E7380142FADB44E233445AF1A1358ABAC75ABE571651E519EBB2BB08E107896C2D5D287A5D8CB1E9CE1C6F68E10A476CEC1FA624B1CF8FC57B1576608302EEE9D4A7133A0BB086B652CFEDFEABFD9CF2CCE461B2CCE11F6DDE1A522D2D4E18CBCE4EA4033F743EE90610916CEC5F1B22FF2AF9AFEDF2D576C9F8C3114FA2BC8BF3C752158D56C17A4D84CB86D4871CA56762372A4FA88C0F305E48BB127CE5013E2F2A2F84C1C67849F0FBAD006942B0C650EC6B1179066A74FF103DE144450E0F103DFAE89E2A5FCE070C5FE9DF63938CBFA52AF5131C96F6B90CE727E09D72EDDDD3B935A9B2C806E5E5025E6A371EE2CA113BD7D875F5B668374385A50E46A356A53DD545BBE1DE41345725C0E2A50928D37B4F1D0E728A1DA73B35199407922B23F0103FB5DF07C55D651591E7DFE3DCF36AE7CBFF1BCB5E1F4AABC130E8738489939469A131312E5C040DB8797EF3E6123DCA492090A14EAE911DB2375166667224A66C4117E21542373FB602EC78A5C62A22487C5719E4D99D13EBDF7C3628847D363CE67BC33DC3C46E319E7BF1B0A03E2AB2A70169B58E39E2D7CA5512093B8E674167E21EAF60D5EE96D28520CDB11FA6DC39956E203722F8E37CC66EE9A6D2754E2BE092C9AD126BA28E11B6399D3FAFE37170E87295279265380EE46F62A22BF9637E666E80B57A03928A93FF40B1C33762851EF2C6667A0279120C206F0561F5CEC66695129E1C5FC92D1FCDC15F591FB6CC0AB2AA855E83500EB2E5758EB97383558620BE244BEEBE247B47283741BE9B8826DAFB8CA4F7101AC3D626FDBA8BDE309052EEECC20A0079AB97FA0B3A5A70A1D522DFD1BF75F25CED6772340413D0AE57EB2FF76659BCBE3EE69E4E1779FAB40D9A28942C6A99A67A58C098376DCD4118E5FA2225497F4C34BC7828EE4D8341643D8980E02BDFFDDD54B838170CC68F2338946A684FFA2A5D0DCA557EF8A11C38D6D2D413C3F8FD9C2A52E3871AE321BF121337384C686C6F99ACF12A6474A0AEC940474B4E78AEAFB3C5EDF22B323A3C60ABFE044C5561719BB4BB191F657378C4E9F400000000000A101B222A3272713EA55F1E5CCD5787F172657C6F6C74081DE2D70816E8531497965DF02DAC04D91C4D09DCF8904CB152E2138F829386F4351015DA253A5B5EB92D96E537DAE3CE809443EA90332D9C754EB11F4DE586A83B5DEE7B1B9BD547EE7107530249B14279BAA04683D74B69D7BFC8BBCD447FE7706593C01188FE6AD8D0E2572D49F83E93986B380D4169BDD94E3311941DD2B041DFABC5AEA1297C65BB5C8352C99FF838D46B93B3E5F79E3CC5BE5408FE5E59A10D488DD65A997B086FDD96CEFB0247B2BAF7B490317E34330A879D04E374C92ADA33EE243D84DA015FDDEC243B00BD7488AEFE373E8AB1890273A7A2285988E9DAF9C4E7C5A17F54AD6195EDE2C79657E1BCCED0641E20F7EE26EAF53DD8C82827F2D2783D44FB030C95791F41653E628062267A5CF534DF00116C1ED1DE9F360B97555C65CDD80724104FB1BD4DA5785B5D9C24438557E48AEE58D57A03E06D553B05B67E1C8D10085C2F153647F174F7922FB8D2210454F7014BDDBC627756EB7CDEF99B6E3A2779F82088E3F2DA14C2DCB5B185AEB5D6ACBFAD43E286AAE8F84A58E8DF6ABC64E4A8EFD69FEA18DBFA6808F25FD418DE8BA923500B74E34DDA3CA6AD8DC208102DC4A876D8B8CD2926AEA4B3AE11A546F6235ABEA152DBDF43E0BCDFCDC83299207F294A707C8B4D1F56AA64A205C718ACA69B862AFE7489F11B324E7AF6BE68380D2CA6E0AF0E2E20F890F2CF98907A9D43135C03E85E86C9EE417140EFEE9054B46C110A84F1841AE3CFAFE5B4A95D6B2B606D8D0A70BAEA85C9412BC2D54146E9F866800E8E8615A0D64D1D595677E8C88699E3CA6097D47E9FE64050FB55033FAD4D5F226DA8EB5DDF99369ACC7552927ED3AC7368B9EFEA2443926DF26D1C172858FD8A5D4E1D7D39E7F7DF047385D39131184087CDC45B299BD1F7048E918223DA3F960608E853EE49EA667465DBBD889CBDA20FFBB540C9EBBA5C2CD16A22A57B561E01331D6EA6BDADBD6A5D2BD1441EF4E1D9DD11CC62A0FA5BBFFCBED0D27B6ACAF0889EAA5863DD9BB35920707B71A0805630D1769FEA320516E71CB2B125AC274F16F7A6876F4B922C7C006F38AE1F7183CA768715D2AF + +count = 24 +seed = A08AD391E0FC57A83B74CA8CF44DB67F8178262ED9B20AA0163CDD8274AC2BE05F558B112B094244370C1AAAB75077E6 +mlen = 825 +msg = 209658CD1D801079FFE8E950BAFD70A028CFCC35B9FB00D232C5603A1D51BA13E5DE59E0277962C4474E9F3F60FCD99C9B79665B3839D5C037B921A4DE8E144FA1D38182FBDEECDA6934E814D9186591F01C5E23349B34F4439B4D402C4072CB4D702966AB473D2C39443F41FBDD0C48E566D33E076422EE72FB47B2FFD661F367E9EFDDC988BCA02382EF93590D4FE3ECE8B1D9D8B3A653219C7D131B43E2FDE2851541F467C31129E6F9B9D124221CD52610B9F138EAC1D01F193148FA0415B29F5C86D15067EB1E26C9D51F05655E8545F734F8F244854AD76C6B04C230898BEA33EFDCEEF100D79F8E3B894BA583466749B82007067806E3A7B3BA954F6FC5ABFF0E099A24D14D865F6F4538736124ACC5EAD4169DDF2144AD558DA3C74CDABEC147D2AFA113EDFD1E2280766B18792310FB6B4FE5D0D9F65906B1CC43655BB3D6178EF9093AC9C8F1A91BF49008179394EEE79E1D8E3228F567770C1BA1E30BA4BCE2465AB68F53CE21C0D8AB2F6E535828F211D4DB957DC3AF8B7E00DABD8F1F74C959B2AFF45121C5B5ABD3136C6F55D5F5FFDBCEBC3CD7A430FF3813D23BCDC1254FE6949DA4E7694028B7FCB876099E91B92C65D85C39D4BE9325AFE81703E5B18CBD7BD9EB59A9BB9408ABD966ADE9A60303807AD1B2C14C04CDF8FAE6950A55B21C9EBB5E94713BF8C2890215C5DA94B59CB31EDC671093B15FF5014DB4CD3EA8060260DC1612E9FD6E5AB40F0656121F689C8E94212269A7B24305C83BF0583418755CE690913CB081F2893FB42BC4750F2C053C48C1552430793CDDE1A49AC9E21913210D727C4BEB5640AB9B7505EA4E59AF417A085394181784BF1BB0BC32BD71CC57CE77541581F14B8BA4B758500694796262B561A38C72893C77B548D779A3833EEB064CDDBA5471CBFFBC769E139946155BF376A56415AB743DE568CD21895ED6951B5BFE1B1629DD6510DCD4483F206954964E0517546DD96900A2540A51835818D1730B0C9123E7FD8B28E6843BFFB659945A273CEA944FF6E83C234B3E43DB4630614E0B67778EA760EE341FE68C525E90475A1560821AE6B2A85015292C36EAA2E041AC04FB55922C48204525187C7E0476A9FED04EFBBA96F369D8AE709506620127FD399613A9796C4FF96D7E +pk = 26B7C30FCEB4EF5D71D0D127F063404285744CBFAD52A8A7C5029DD57A45CE59D251B3B460EFCBECB9FBE2F8401AAD077E6AB39A592C0EA1380CC7475FD86D5A559F41DC9627A27D08B14F8A982ABF66E3549729BF52A617327D8F8A67D768159571C95B4709C77680261C271B7D7A33CFC55B54901E524391C2BE5BBA4ECF2984AAE7A04E4CF92C52A55CEDC84D99CBED66E301387DB0EE44D4964EC10FAB935E02C033F8861A073B25290F7C77E13C3D9FAE76756DCC40F7E008D2466E3C9A8AF0D11CDB30850DDED1E269C3F0180450D50F695AA55A9D8D47CC90237637D5E3F20CF16EEEEC94FB1C39028349049CF34913C0C41FBC3C0EA1AF08BD4A2E9F1337E0576D91C50094BD94109370B984A2C42C1E4623DBE1F35A077B88143A0444EA160284F60642CA160328CEB6D333B9CBC6A8FD746C2815886DE4861E0DC7E5D51D725544F2C1D006AD628E7EA053181AABFC85DBBBB0DDEAD33DBD199D03560DCE450A765CD04ED272F5BC68E771116C4A727F4258A953EE5CCF2B1C1416FC283293A221D8D8EA196659BDFE633E280672563065F36FAF20CDD057B871211039C51D1D60797BD83B3CC9254E78BC0D7609612B79EEB36444ACC4102D596A9272FB4A628C4F1A0D19656DE6EC9E2F7586DF1D8F7F3D2A2052E029591B35175B40FD2B6292775E700BF6D262008F993BB1E5A1BEB26539A47B88CEF6FAB60AA0EC63E1A5D1630A604F68043B482EB1E96D625EC65DFE7ECC2E92A0EC3746C3163E80129FED32135D90535B4EABF0065129A92ACE3921F0B17B89A5763589D95545D61E289EB78E0A02DB60A9EB2D708AB6715ACD5B6D711F7860AEB8721A29785042A5B5EA0C02BBE7E5DF4B03029CEE701E9F764E1AEDE85854F95B2306679CB2183D5EC35001E15BAA7B94944FAE92011563857B87E2840CF911E3D185D7EE3D35B3EE10B419C6D3866EFA3DE90B8314E8DDF9A621BD2014FB91D2FE631B5697D22C2FB2AAC0A67B07F82FF93B6E2B3BBD7A4CE392B5BB38244F49B3346536D75B37FA5427F2FB2EDC43A03E89D47135D81727D658041E2D8FB273A0C3AF174846DD5708B835EA3B6FDF08CD054C38FA9A924C4F12A8CD5C2C4FBDF0125B5706C2AFB59C3F3DFEF1D2523F1A22A247C2F971542DFBF5FF19D14BC5740C6BFC683D853724A087B3F1C75F5F4EE8434EC0F02358BA5AE9092AC018C4F1D443410A51491C1856C960F4789ABDABC43BC04F60BD9E4020A07585F0666AAC16DEE2ED80F2CC5361CE55AD56586142E270BEDD58A9502A557F8326F20953F10FF219947E333C8EA37119591BAC5DB35D66EC86C04F7C5D938DF4308D1A2F57CA024196A6C41E1E04B04A15C0418439CD1E3D4C933137CBFF00681C3F5D739F271999903822EEC35475A149C27B21229AB3EE95B67842FB60DF60C87AC63B964FBCFE94A893C88EC0EF423194379709F91FD39B09D50F5FB334C6D98263620A7BF2DADC189C5B14860946ECD6EC882A9C92B6BF4A5325AA22BE5C7F88F85552CDF07CE43DCC0015CD9D6D033341555F486BC342C1A649CC1DC19CD7FEBA97E6912EF871520D5808AE55AB2F59E1C10DE22DF3089F075A9CECDF83BFA0101C856D060C51BAE3239FCC197770439497CB5EAC7F3D9B58C93847E95D85EDB355CCE839CB71EBC9D3C82008A1D827074B49CDB26E5411DF7E3E797E498701137CB4FF28B0A0241CD508870E579694E6550598F269C2847A917979D2573FEDA8E0DB7A662A866E1785BBED7B55D54A83B4B6B9CCC5EDC3E487D0DB865530EDF4D8629F734F9A312AC1A3A48593B2B46A6881DF5ABC6F6E2DD82365B42746BFEA46500CC9F1B3E870AF18F5B705E74834916F2CCE6F5E9CC3C5B3CB67B772F5C847946BEF0F8B26D12165B867F6E363FCCB732A7E22DC8014DE22E8E7661781FFE434CFD20FA5C4B9FCCE6588F7ED3D59C3ABEC15190637E05662DBA0E16D4A56F478863CA8C30C8EA764770F6A60F7DC2F1B00D2BABE837589C0C78BA0367F79E642CB29E8AF6D7FB9B71175D56694A87C0F88F11B4C7828E4FC21845CF047D5CF453B833DB6F5BA007728C8926C315AD731CC1664BB53DF512F51F18B7E295B6E64E734661FA7CFDFE428BC3665C408E0FE030DDA538648BF4BB572F6F356A3FE83E81A27285EFF08B24BAF31E902237AC0150D002ABFC73A58A7017EF3B74323F3DAEE657BED866693A990160419B77D502B5882D5C32509542CE8FF0E60E9FE0DEAEEBA67CC93AEC1AA6D04AD2ABBC7906BB442923136CE3E760EC043D34D8ABA522922A53FBC119DF504BDD15F87C9D7ECFA344BC9D238A91341774B0E9A5A9A5C99AED8373C8C89AA15521D104C8FA45236D005C824C3CAC0D92D3E2778C058F3CDBE98B7BF8EFEDF002BDD7031D9D85296D26D0A34B9329E064A01500083AD367D7ED3C98D6543554A94533474F52AB71485494FF72A645AB3F16CCA50FBA129A575D8EB83554E2F8E66663767B7C989BD92233F265CAD58F140DA2E728189E045B23EA6E6148E52748FFC8BD110873E97F072B157659AA9AFF1BE0CF5CA6F2E1FEB1620772A3753C84B55B20AB143DE4CECFE8C39E49D6381314DC4EE7B3D2B65A54CF25BE388C20F98014F3724B44C6AD100AEAC5257798F14AC8237D45D38E50B2D8801048534F261011A920167ED1B34E71FE28866DACC909C8DABF7E893C35ED7F7683BAF454EEEE757287DC9F365D7CE2CB3FBCC34D5667C8AAFDD02732A +sk = 26B7C30FCEB4EF5D71D0D127F063404285744CBFAD52A8A7C5029DD57A45CE597D6BFAD551A99F4AC85628954D9353631D6B988BE3EB25D159BB1250CA85F666EEC1A1A29558F48DFAEFF18A4109D32D66A3531CF76F36E91BA248B8B40C46F0D70D126B6BB5A0F468B7597EDDC6AC29EDF69FD44262ABB95CC3B6C95F7D873120685880374460874486652772026324253110284680384186033345386805143271358810711853815510621636523084046081867275440370417243728127363428572537277474324100482057571526624544607370476323407721688572201136856735513724107721222046643384010387582646050874724817778740718446564105104360007164318267544231517876264387457143385276522121284561458563714527313553063207333540840818173210676577114728661717605823464312325338631087317115874526778071854605543724578368542537376071142071252340041244201847478828825782082183776583645271487526511284388288786018628857178406146770131341433564401054527077284025853785877164382265830848015732512372222546150125011225666864812424217024633312875842560417522605644161467221726242038724073675136638430466654526018841053765381254345071871876481118716361216137661750000887055233613244210565057847381865134177013817631474441850864762430067635365440038006301275231023674701316666876024760523662736272814582236072672463135101143733758580887700687757671113126743777875085422454801587603302083426036266132637651524143307537174830403051471081428660518880676262150735135212381760474357357867748488717402702171027011251387062758845623322427120887565642065234144430526786376008148563756758832560144500382586815118027368851124671857176026060077140627066770583070775831034147853040788653068764785177508823143422268211660310823781800521010678686314817256681243116727050652353423526752801755434354565346605368247272846150101571258728245142584148277286346328186776482860546330357657321147356123582004167502213417521468007330872433081140825757201874588560867465362580010334645855374627324337400324100241445364733732343434554785635126841244611846284665554251562407615346077125472710881051727733741876673073732407101144261057538160382081311868314302535073171104405805665331511086853767682864704748511245688650846726140248145304376856481278862450564674450336456340448787253222066613057643304876825822372680326262448353246481325723862323555871411118278658042560577316232163050072043233683444022762443105874461603188704436631656138156043272512130742176700600804778785865748023423085120180643725315310222342021234316713151288883128732362735848456140500248585207131873107422131341305410040831274251607680001547181307112522605067845268166241825667725325654048145066607281846871058811508023252477156381844050075240818148082461611006508002036405701066684774461245342543542312656171662357515410215441040536112520573577187404264687201018374253116647813304884624416803051383111761427584837415251107600781670166834372617012804046483530711874317176018512075476530054248264034583064333527066548224141513030837044801332522876750188550856136864435082237801146185644533661008363782477643507064124707201085308436373735773467212124067247353278087832538127854232045710616103312420801853720086836818631100145262845640546062547181767CF758D0BC3139A8543346B8C4EBDE108A6E3191574CC0E39CCC412D5F8B44A203533C71E5BEB6F3E88C6461FAD7F5E70C7491CC6286DD3E9484594503C0492FEDB91432A93A77438D719A44527F4CB5B31D359E25E56CDFD65669854BAC12DF587614BF6BC33DDAD098833C7399DFDD4437ED0C202F2BCE3D0F5988393F16F1D2445489920D88CE6E1D737743B2EC86E38C81F65FA37B5AA25F1BD57105257951D85A9D827E1E87932088924298C734500F39C4A12EBB1A480B875BEB1E9E562F54992CB5E1E428F519DD24AFB153F4E4D1830CC4E9569F7BBEBCA48108313B4D6DE64B305AD232475112DA57ABA07FF465A6FD88DABDB3E519AB9DBAA4CF0C905B4D5CCEA867012A61BC7D5CC703A7C18D7E63C0405A749308F5B0C1CE24971A64B833C62FE58F982A0FF883C170AD80922239697060A513E900F4C42AD0C501C19F671BFCDF6A08C059C9916BFBFB2C20B958ABCD7D8A203E64B5C0EB9D668D51056666BC31EB8F2C58B2BE458E4CC7663488521CD4FB7F15CA493F69FF2D6460A4E6C7761281973F9A401203E4322D7A6B965F6FBF2DB60E60408327C297D46A6043FA06320151CEB5C3265B1727C0C27612D0BF801642EE953766ECBC2F23A1990FB098C43E504C89EF9F8CDD1D092E10221E724F6107C4758662BF17DDCDCC1B11FB72D64A278510C241646B4F78A79492F587F422D420D2EAA41F53194981A783D9DD9730FAB0CD14089FF9F88671509D422A839CD61160FB825A14A6EAEF02FBC7D2C61EC2FAECE51D86179B159A0CA079216B6A1AAD6634810B032599C0392024BD097C3A40F93B738AC0296DBA6BF0D2EEF406D39B05FD06E6C85B34738B9485078306BF1854475A2CAA52EA9962578CE106A99F00BDD5F381CA763C50838A130C3CA30820BD63D6B3E87F850580FDB4FEF61FF79DA5E3E3BA4F4BA6085DFD7819314782B2C1F3B3BF51ABBAAF88440C9D3BA7583964BE2DD59A1C01BF35996F5DAC33F310B0C6B4D192EB2E3CF1EA4CBCD31FD3C880EF48147EFF731C0CA9396052DF99212406062EA108BE0E2A4F9C5F6D07633A621891C80BBA4E88184DEE01BCA4045AC466CE8EBC12C98E9650CDF6CCB2935929C508D79AADC169E790CDE12A0652EAD59248564F9DA7F0E2A6ADB012883326E00EF5881A0BA0C780A5F518D4025737E2BCB0D3E5527FB0F2D93C7EE5DFA095E587B89270405F34E8251B27E03657598964FFE4BB45F9E984654719CCF6BA390F87E620FE30463A3A9E5CB923800A5F227958D41CC9701FD67C5616535C785A113A55736169B0D5028A0E0EF9E97E200B1F9AC16FA7513A0EF75A676941A61DB9D468143248D282D7FC162E0F2E3C6B636604A380936EC0D0BABF99C578400399CB4AFCFA1E4F72479EC48BD58D125F182BC01BC86590C4D5B11920B01E0A3CCEB59A53E6A9C2B00424C5FDFEBA661D6A870F0BC13F4FBA279983847B7ED6D6044A83EEBB36A1E4AA3B90558326A5BEA17D2BAE8605AF31DD16B9314ACD9D61DD92CEF13DBDE6278401E11EAEA041167721145BB94F4ED97C6E9CB108695D16EDD62B131CAA8269B11C9F7C664F87D1FB4D8B6F47C779DFF6A81D66AF3A335BC22F936969206216C6E72F459D741BDC874F9F4C42905EEE7E26E07653F0012994E9516C4CC55232BCCEBD4AA26AA9E2DF2E0F549724C5ABC15182A2571DBAA2C90509166A7B5A2FD5C78BE19946ADFE4D5D47EE5768004194AC99B98D2A69D96FE1749CDDFD854262BD52A1E3A1027F16A7C6CDE0C881BDC3F72E7BF248210CD696244D64E7EAA45B9F0A49F54FFBFBA0D0C60443C13800EC40225498CE2D27472A59629D28E0F4519D6EE616DE1401EEB2FF28E9B55ED5B2E301EBF58844B6862B501099B708E2D0662467532324679E21B141487BF149DA9EC9E6195AFC723F833470BB15C0E2723CD7974212E546EA7B6EAA3E6B221C215C5293BFB375463A4F68054DECE4052EE1D73448E52AC3F15649469F2A4BD0F7172B5EF9139AF3C279594CA1D01DA1482F834D3E4B0EC4B2AC8732B0083EBD397B931AC5C10CD4F39093B301CD4F3C851EEA60510A9ABD9B9C2C8239E69C31E1D405933D8E8D45A524E2E27DEBCA313B435E14D25666B3B885DB872151C8626F87DB3F6A62BDE9CE4C11050F5D5C075811B535778FEE35AB49A192093BC06BD5DD26CC962AA18B9ED1DD28DF0B1FF2AC7DF086BE5D6CA9ECD1C739E21DFC51AA70591C829ED76F16AC01109202087AB1707AFA48D46AB87BFD2D2D6F67EAFD782A06628196D88F9C1E1867D88E512C5D80FF6F3663FAE1D5CD7437A50A2C4AC760EF9D5BDA59DF6FD8928A3C6EB9F736702D41405D1CA427438F5ACDA3FB3CF307A29C0F2B331EDE33BF1BEBB237D6311F051AC18E497012C44845615CA0710F6AF01D09F218A2358A1B8CC9E85D445A5EB33D223D8D8ED58C98FE354BBCE8C88A6CAF7845FD701FA192ECD9F30DD353D7F453719114E1829249CFDAE5C7345948A349E46E4A212B068EFFDB0D198EB8B453177CA92ADBA8EB9895EEA0C09FB8CEC8F68093E8707D16E4763D79439AE2E867DD717B95C99BEBB98E54758F23C061151626DF12C697E5776002CD09496BD859FEF834CF54CEB261C7C94F33E705AD50DAFE7DB924E865B81E03D9B03F303C491EDF37E4A8C3C4EC4EC81409AECD2F5C4429876DF410430FF04E78459737D6A343BAA5DDB85BFB9889C4BCFFA2F5D728D6D791D51C8CE6C94902D6824B1EEAB13BD89AC51BAE6F472998D069C7C5E3BB1C4FF729EF8E7D65243A932E20D98AA0FAAD6EED9BF3BB5F7F4E98DA6B733F407E1E1FF6E066115798BB7E801BD55A61188E65FD809C7A950CD30E872A35F6051A5CCCC1FB56F606FC02D1677E933790C1CE0436836CC22AC7322D845B7A39080FEE5A48C3F1607F53722E63173F5CA1139A3606AEB2361BEFB0D0C665250937DEEA4B5CBD927E8B767836D84E4F00898A22BAB8264512951FCA5AC32026EF8768FF8B956BCE2B2CD7F1B6300AE7247D0A2625EE7F39AF11AA8DC639208CE7C7B7942A861A2A33C5A8B00E7FA8538CC81054E6CE96C63933731BDFB616B46466FE58856C57EEA3F959D5089648E2684B3C521B2CCCC31DE29B79E535D7974DD666B8C3B1DEE4D19F0B379AAA980D64B7343A05D94EB7C8DC0515C2D15B3D723A63EB5382215129293B0FCB6042E311C3C676F7BC0A5A9E211AB8D1264D37236133B91C3B63453668B76CED0CBA15F338754815F62F2F92C76861DEE683FA42176351A9CF5F3AE87913A5E72D6C3943AAF604DA9C946D8EEF0E33D4EDE624C00AB0EE42F6161F26E4D1C3EAFF5F72F62426FA069EE6847AF9F9520CE4F5DABE25ABA3A1C815E043D36169774C3E569025FAE0F4C9AAC9777032A762EA36290DD03C7E99A6B88A95300CB717AFA5B88C3894E7FF34E469A3BEBF6907C29F2C0E4153F93F59507A687C88AC4749375BB9A2675353AFC5306364FEBCCAFB6A593AA59ED54AEC41739F216770BC6 +smlen = 4134 +sm = A275310196DB3EC1850963A117846F82D92272A33879A1B1EF957DA8A865C36B706CB244F968F80711D9039E75CB409114FD4F4979B6A279F522D5380AE19C92A6384EF9354A0F6B05095C9726691EB8CF18403DAE730385546325694A9BFA255082AAE8D59F31F90E7FBEE448D6E5CAC66BF6D12D4040F166B7EBF7E04A4B2D8E679237A204BCCED5C475CE27B675FE10EEE75523DBAF22E8D1BE3023A3A41D6E458AA1E1A559D83532A113E36D762DEB5A2125114290B4BDB7B77D9656E24527BFEBA1ABB4CC3F659C6409F5EA3B88ED961C9F341161E3231D3B404ECD064BC4F03E7E527AFA89D32B41F85FBD27750209456F0D07A07F15ED68D015C1798C7EA37744407DB9EAA661CB62145907BE41CB1AB3D65DBD909C9BAA8EE061C5C2FE6D705EF1D58AA94E347DD9C8699F15830E15E402990D17A6F10BC606763E2DDAF82885457D8C128AACF1BF90793369C4445C7C6B21C115F8CC11F18D19C3AACD11DECEC819C396AC55FA440493F48D085B786C8801E0E038ADFCD01D8AEBCEA0081DB86718E5F79017DBC5EF8829C7F9C14B8A86007044C263BE6364A8208419CD11FDF5C25D9EE35895B95864D0423F98ABBD0EB7BD57CEB94C2C6D9D7AEAF01F8C3A41987B1A36E21FF58E530131F62A8FDF9045202B03B4D9C970AE24F7C29F98E72C091495968794CBE54B52D043D707A9F5376BC6190BEB4197B4776400F3B50F7E16C06503570166993BFC75561802E25FBE920CE4051E5FDA8B9AAB22F0A01B0CE3F8AFA5031147674F1F459D2B45C01E2F53D111CE723A375BA83893AD02B70BA5FF94E4972E348E644B571FE24AC2E90F3342F937F21A7041DCE071E0C5BC0E85F0FA5009C49DB0D2DF15AE854DD354397D01B5BBDF7089A5A0ACD59F5619E40E74FCB9DB48CDE5DD34D00A2CE4CC54E778CCD839CEAB38B7297D6F4C3E3AFFDFB77E054C494C76AD1DA194B0D304FE852033C981ECF2B66A6528AC47F6754106E81D02161AB1C4697712DA31E39E2F92A525EF6BA968E9C0E4374D8A772B23F620AB1C6FDEAD66A562D3FBEFFB599814C660DF332963EBD7C16A4F6A939F9E7A094E47E97E4920276148402B9985FC30D9146C77C0A432CB0DAC5B8B48936E5218540506FD2CC8EA42A161E75D67CF79ACDA680635CED6FA601442CA1EC0496D4E082EF0BFC12D6AB3300A9593468E9D630E3F027EBFF4730EB64D69ACDCF5D3CDCC80048A061252F446DFCC7BB272FA3CAF5AD08D937C6C80878B568F961B42965F4F3C049EFDB30167EB4E7EB46C662E9AF7E9F7DC1582B9DC601748C8DDE4208EA10ADD3B257BAD610B509AB349271D405D789F2288942443388259EA04261429969C812470B390A70E8046F260105B2505B6C88AB5D0B1901DAC93F55021F6DE9698291085327D2E875FCCBFC970071325E5794D93CBB89187ECCF388E7CBC4822E04B937727A74396D5D29E1327146DB62D313CB967B1AC4048317319379306CE9F9287BD230AB24E3CB140250405CA25DF18EA8AB71DFFA7DB68D4AE55186B1F92C4C0F1648B3A7E32B2EB091E233867FE50E3438730DD3A76135EB873D08E8955F679F3DC12351CEE5827DECC8DFC8D7A67AA517F3373256ED5E215D832D75135DD023C47262EB93C7DF699EA5741FE9402D44F3E2EAFDB32EC587231B3E3BFC88896B4A4F782B2AB3A1FB8636B474CAD0B309BA881272E44744C1584BAA8F209AF3A0DDBF5D5C31BADF9837EA953D36D96C3C3D0368D9A0E3F8EC7663AA00F0FCCE6891FCA38114335DFB1197E64B3D409C58362FC74DF3C188BA26E98F627BB1F5E89389B7D515C8E28045FD7A5B03D6D2A6EDCEA25AD0310175867640E0042EF6EAE17B6710D68037A33100A0FB54C188DFEB4FE23EB8E7DF353F3D360C2C6996F91992AF78FF0A18A46C17C1DEEBBC58181F5A316AAD1E0170CD4040E0C5A059120C4AF268D18E0C61EDECC86A7E5BE69827532886356F7BB20BA502A8BE38569A28D0AB23552E11F66C60251ACB64C597B1CCC28F809FDAD66673A184C94C9638538307EDFAFB3AB74CBDE251069806C674A8E6BE9658C83B8CC2AE163A0D550752AB4767016192F1450322C01AF210BFA608F448F441F98B478562F79C701711078AD3A93252889663142B1261CCD233704ACC1ED8A79691E4E9477CC50B9FBF0F330E6224691CD6FB960C2361385E4EBA8DC3514E2EAD7160EDC3DC24E05CB9AC1244210C667DB4920519DA2859C4AFF0E3E5B6089B8D6E64F765A22D76E540335D94710D3E6A8415587E7FECC0B242ABEC1FF2684EE8980447A1B49846411E1319B0CAA2158F6B9AA7163EB7908FB1705415F4DCAA590FDA1AB5F0D41A0D9672C4156AFBA42144A125E9748C2D5FEACB38BFAD032EDABCF929C40970576AB4B8273352A05132E04BDC2679BBD2F0F7602FA8278FECC3F69119DF065530C58450936300676262723111BD7D500809750A9AFABB294F23EF2DA235E74C93CA5A07095837468E15190AAEFB7C97EAF119A060AF5E6044BE3B72507E17D549792CA5A19C67EC557EE3BB424F10052668DE9FC79E0D26DF9CFDAFE7C0F2BD8289B09306877265F853B6B687A0BD0C42D6B6AD5FC761FB184B6E1039519B73F0FD0F9BC61D9329D13F2FD38D0E9D6E83FC2891E3B8B59472DB7C76B5233A9ED9BAEC28906A30156BDB98B409201E874140CC74E896EBDF83483A7B4B6AFBB44709B99CE3A0CBFE166CB149F724413BF44B5122F2C842001BD30CDE9D7F48C0E434DD7B0CAB3F6F17A7443639D1DC2C9D0C365671CDDBDC9F53B8ABA2860ED21A7DBF41CE15D67610B81E0C5B981D92D8F8FA4C8AFC4143BD5011BBAE1C07217C6D4BAD5EE56816EA885C73E5CE9CDCC1910F9108BA8E46D136C54F895B51227BC00D4DAF7F9EC035DD466E7C0F5EDA727927CEC34DA64F6B678E20AC81142590A5985D9FB8CEE5C1069123128A916BE87F8BC76E3A40088CCDBD94A955FA3E2A7E79019D1C2FFB90211A5E08A69DF192431E1D8A54715D831C39B97C7D5E9046D40FC7304C058FF25E82466C3A127836BB9E3D19B29A57B75ECCC5719E3FFEAA226DADE80C0E517116345E8C6C0E222A48EF8C9E25A4D1755332AAB7E718F849CD5DB79223AFBC27C904F1689D218875D55F5189C41FC50A686F177E43C4F42CDC386A18003FA37679BB35D252C2994F304F09AE0A9FC13041405AD8FEEB09221F90D15DA8FD837B3DE6CF0F87CEE1C6D49515CF181E1E7F91FB59D72C8527BD20DBE90844F9AFF9315CCC0825F6314C90803B866D88CA2902FD9CF81525BDBDB567F85D300EDC2FACE8FB81B2B7CCEEE4F19420E77BF61F4E141FB9BC5DDBFA9D013192FCA8A646A9C21D8F237C42DAB5D34E2A13ABDCF0F8BBE0C219B3B85B6719374D9245DBEC551AE0A84DA8F75CFAAF58EC14B6A990DFA78683E7C33A4D89D019A9F313A12BC9AFC2A19F8E3255752DD4A4DB040DA5BC92E48980B9DCDE0126B640B03EC57FDF90B6D7E1B7185AB9A3A483A13D37C1101C0E415CD4722CAE22DEF03213A321340A805F426F1419FB4D4A5C87F0F5A43B464E6844E2FA03303CB95F77C0E8B2E0F9D000388ABC668F06D7162670501996EC99F26FC8AAEF881FFD52C6E6C87E5E7A232E92CEC99BC9660E593805B44B09896CC7930D498193A6144F7DEDD50D61C83EC0C57208C502840F0CD965150231AE8625B7B67DB3C86C61A6C2AFC850BDE7ACEB7EE7ACC0F0A269BC046736D41829226FAA46372F0BF7E3CE69BD79F20CBC043C8CC3331843E3F71B9166B85C75812F5CD44646454507A11061DA4451F5FCEF7006AE995F5BB6F1F7FA82AB0D6CB7C9D9A44A9309CABDAB7B0FA7B8F2ED82E79E85944DA433065D9D27C5E77E838EBB2C658B021D427DAF1EA0C9620BA362C7022E9661B184AFB7F150A5A06521F8DFB8C383E3E7CC80CFF7D0297F798638C8E1C5B8D597E25CE2926DA947089267112CD6194B79F3A0917829851FE161F3477D17F357165FD3697790BC2772DCACF4E3047EC7EABAE97EA323E936072F1C995E7A3433A69417D5AD519CBD80465EEB81EC90915A8E2EE0FD3C597AD144F79D369B9D9657BD93DF1B67F86479F411C63D6C526D43E8C2EA8C817906AD2C0D1717526128BBBD7B979E550255B5B6B5584AF2CCA1EF9949D61A6B611C19D52B858335B4FCB7EE036BFA7DC1336D3B6BB8BBAEF7F56A361B601FD655F7042F9769FD117468A6156831FED55CD04DB1663B8BE2B0F42EC1D9C43EAAE4140FCCA3A0EE3417E1FBEDE44DDC25CC46D81A7976FFC59EC3431DEC50E94B801E3AA9615633AF80478BF49685F8350DD432ABB683A14DDAE7737A2D86F1EE9F9564F32EFEB76FA0A0FFA05628F01AA1C2219D729A2F2E741E274BD89E9EB04C4F301D041FA30C8BD3240747C4387E5C20A9A1F1C45691431501F837DC53D40C45491B39191504760C4279DC8B79E44238CAFF9CD10D133C4F690ADA453433B8A2B9A7E6CF071A75A0F0F5DAFAC32CCE194C215D13F839B648B6FBC9998F6984AFAA8895CBC33130417EADDAD5C704230B7F8A114BE4BF6393B10CD0AA5879882ACB127949FA3B3BBCCD3FD1C3F6E74A802155F7794B4CF383C74AFC9040D1C3F41557B969BB4F3000000000000000000000000000000030C11181D28209658CD1D801079FFE8E950BAFD70A028CFCC35B9FB00D232C5603A1D51BA13E5DE59E0277962C4474E9F3F60FCD99C9B79665B3839D5C037B921A4DE8E144FA1D38182FBDEECDA6934E814D9186591F01C5E23349B34F4439B4D402C4072CB4D702966AB473D2C39443F41FBDD0C48E566D33E076422EE72FB47B2FFD661F367E9EFDDC988BCA02382EF93590D4FE3ECE8B1D9D8B3A653219C7D131B43E2FDE2851541F467C31129E6F9B9D124221CD52610B9F138EAC1D01F193148FA0415B29F5C86D15067EB1E26C9D51F05655E8545F734F8F244854AD76C6B04C230898BEA33EFDCEEF100D79F8E3B894BA583466749B82007067806E3A7B3BA954F6FC5ABFF0E099A24D14D865F6F4538736124ACC5EAD4169DDF2144AD558DA3C74CDABEC147D2AFA113EDFD1E2280766B18792310FB6B4FE5D0D9F65906B1CC43655BB3D6178EF9093AC9C8F1A91BF49008179394EEE79E1D8E3228F567770C1BA1E30BA4BCE2465AB68F53CE21C0D8AB2F6E535828F211D4DB957DC3AF8B7E00DABD8F1F74C959B2AFF45121C5B5ABD3136C6F55D5F5FFDBCEBC3CD7A430FF3813D23BCDC1254FE6949DA4E7694028B7FCB876099E91B92C65D85C39D4BE9325AFE81703E5B18CBD7BD9EB59A9BB9408ABD966ADE9A60303807AD1B2C14C04CDF8FAE6950A55B21C9EBB5E94713BF8C2890215C5DA94B59CB31EDC671093B15FF5014DB4CD3EA8060260DC1612E9FD6E5AB40F0656121F689C8E94212269A7B24305C83BF0583418755CE690913CB081F2893FB42BC4750F2C053C48C1552430793CDDE1A49AC9E21913210D727C4BEB5640AB9B7505EA4E59AF417A085394181784BF1BB0BC32BD71CC57CE77541581F14B8BA4B758500694796262B561A38C72893C77B548D779A3833EEB064CDDBA5471CBFFBC769E139946155BF376A56415AB743DE568CD21895ED6951B5BFE1B1629DD6510DCD4483F206954964E0517546DD96900A2540A51835818D1730B0C9123E7FD8B28E6843BFFB659945A273CEA944FF6E83C234B3E43DB4630614E0B67778EA760EE341FE68C525E90475A1560821AE6B2A85015292C36EAA2E041AC04FB55922C48204525187C7E0476A9FED04EFBBA96F369D8AE709506620127FD399613A9796C4FF96D7E + +count = 25 +seed = 6E0A8EF5156D693FD0140BC4A31084E79773A83F42C8D133AC8A9D62DE3CD74511F893DCB26041E6B35E2B175408FCE7 +mlen = 858 +msg = 8F37A065DD696AD437EC82909261B842EC0A3E66F8AC574105A3C82EC8B4926F2466FA550F8EA1B6A9A142C00AFA44BE6512A85350930DFFC99B95AA21012057051B68C48581AE439B9290A163AA4B6AFCF80FFB91A3321C7B9ABAD56D5DC1BE4E67E5576C9F3A7DB96071859B94EB22A73DD96C66AE67AB11D1AB62A86D826C682DFB8CCA3259DCB5B34BE635421CD4206E7D92147F14C36424EAA407B441F58E5C187E58A26B2AE144888A3CC1387AC7D0A681EEDDC3B7781AB282E8185CCF33FB27500CFD119E0415DB1E45237520A868C8457C88A1D3EE97EC9451DA35D7E74924F8902949E7EB14BA87C8AC672D7E4F3BEC1B2814DFA67A8DD2E2D4FF4661D64BC4C6D6A78D4E489689B6063CDFF5A3F1554501B424284A9F4B8FE777FE4E6AFB83A85E36200A9AB40B9C18678454B2A3F50A4862BA1E36F0C57AD004FF90192B5619614E37DBB38A1B8A65AC613F7796C70772128377065B84F122540106D1B4F9123C4E009B4C0A85D59B35F72DEBDDD154ABEC7F3FB25FD1FA04367386098DE610B26FA3ECB031A6072D14607E92FFBE195ABFF71E586A984131AF24E18AE94DBAB0544FD2AD217960F337111BFBD4046809EA03C7C47B7177757A4A43E1FD0134859BA735A8FC17597E593BB58322136602954D3A21096B0D1DEE5CF0AD17A5FCF561FFA21CAA70D33998840E4CFA18BA481704A8B82D2CC1C110FC9A6704751365AE9F338AFE4CF9C811697DDDFA8635A2F3CD02DD1845251014BF2F2D6C02A907BD783207C4773A937048A07C500D7C424B5F65A2C376523740DF9A0B60437CB8AE17D64DD51DD4E433AF83B20C4B6B890B97976DF09E3A86AC19006C229D59FC7A2923245B7B1F0ACF7C42E486D41CA1AC1D7051AEEF6003CE94182F97D099C74317F61EB47AE18C2BED6A3CB253C21EC835E435123E0A657ED926F880CE8E5DE3155272328A467278F52AC50A1121AE818A3EA3A2E1F7401CE23AAF66A4AC289748A7E98A5124C586D8957BB4EDD3F091492BB1A64D75EFCD45AD51CA420F15DA848B20DC6BB765E7B71359B3A9E95E121266AE4A40DC2E9A3D81EA1B1A643594B3D4E6ABB7D1202201DE92BDF0CC1ED977E2D5851822A01F48A6F23180822888CE345AC9BE0CC69BC448D41CA20B79C35B1DAD73E6C683E70C4439B404CBF07FCC39B0E5A1D33F3717A6BAD28A6DA4F091BC7A +pk = 8F70FD6B69122D1DA58FBB275F70D9EEAB795E002D2889468869E5C51ACB94EE3EB13865862CBEEBBB3C5BAF8F0B2E63D70B2F08B317B884E12B3D576A67784BEAB24CE8569A74D3DD006191E142EBD46E3AB9D284279EF0B729073B1D6747BA797303C5A2B3C340619CAADD1698F4B08EC19A1871930348A7CAAA9A1ADE13FA254D533BC6A5F21DD8FE6444FB90AD9305B3D2A3B3A7DAF7605D9DF2A326821DB0B3CF9956F67C8B430BA0F4248AECE3FAD7B87276F68E2C36BDFCF25CC0CDB27F5313529AFD39C07EA65DCA064A78D320213FB66DB27250B09FD972266AD4878A9DDA150C6C826971A6974F26744EB4557A0A72D87470E14F05E1E9DAE54540D5E91B419C627E20088A76B446D3BC75443CE1A7D28E0DFED1F53F89BF7AFB4C2D3B5336EAD38835D2212E6A4D1049238C1513C44014C14BB90B52658ACAAAE54D342ED5DCFE23B81D20EFAACEF50F8FCDCF44BA0B545381C5E87D54BB9C850AE8742B21F42D18AA2DB7EA0EE71D46973DFB48EACFA1BD5F2641501B8012B3A1F50704AC6908D4CE5A94FEF2A4E304BC8935ECFABB1FA20897E62B1F71615F3AAF4446FA6DE5C30A16598EF8A67EB5F4D0C0125F08D0538DCA3C4E80CC5758A5BF33DB2EA7DCC04A816084ED2AFB215A5695DFC9152808FA799693CE8DB4C92F74F53F696F0C2E450A9018D2D9F6A840F97FAE53FCF23D89B3DA73EEA2064AC58ABEBE4A05B41A173B76990E2E567F16BBF79ED4F3CDC42A4B57E66C277ABA11B434DE962A01A909949675997FBAD709E735489D0959950A171BA3126604D2F8E342CE07096538FFB993656A15C9D9D7FA46883B71D796E27B74382B4D414BEF127D756F70D7D3EE3A5BB15133DA31C6034BA6130E527FFEB28F27E74BEB028A94168913EE6D1AD4BB22E5AA8B28CD5577DA2CE353745FDAE20D20FAB3AC802352CEC3A84EB5842B9CC23504D76E4D9574DEEDC16E5FFC9EE3E08409C2D12EC2DFE6DEF0A885447B3C112BA5082061F4698AA53031FE89064D8CE73CF65DD6646F5F579B2853F4EEDDA592143150652219D3765D346BA0DC823EF6C051C6289B2133335578CCB69D949CDA5E69F97B09326CED4DFB5D71C75D57B8D538AF82D467EC8C12C572B067878DDB2C686647725E8553FFB6CC4B7648622DD145EEA2B2C692A75DC250F85777E1630BADB5ABC5B98BCD94F210A1618D28667C25EAF65003EE24B7471E7301DE67F66E54397AF20C63618FA2760E546CFA4AE5F566E27ACDEEB715C3CE154C8B8491B143D7DA09B4889ABA6FB0F821A598072625800E0DA9D8F01EC3AB33F28F7BE09A7D7C81CBE700A551BD31ECC478DDC4BDAC0D12B588FF82110DE002B6E97A7800B99A732B1D4AAEB43FCE9825AB6E3DEAD857B179CCA1E733B4C81FFA0FC24F99072437D393D066611B2F421468647886CD9C0D26F90D5D978D342BBA2C773D2ABA69CE071D3D6C2A5FD11A1C0186034CC300B6FC923D2C0123EB62C50885959993D88DD6BE2EE045F76203984A4415B6E640F701C46183220F2F2955FE0B285D8C672445D7378956F83BCA25D07B2E6031816C319DD65847B70FD6DB92B79010239D8C00390F23C20536B486BC9E44FE361CBCE922969390B858B20A6677EE08FAAC2C1DFEA5668D7DCD5BF20A033FF85D511F21A52F7E7E7B0289D111559F3148312ACC45C7E5DB777A488FFE26E062C82C1DEAA1266ED087C86D737D1DF3DB95E58C89EE71931BCAAF16823744FA7B9FE1AE092666F0147EE60056E496AEF1BEC2D38BADC42DB83F68E78D56FFF47872710EC65FC2DBFACCCC2F8791A9711E6D8C8523F116861C8139E91FF09974D7EDE7CE70B2508C38FB9DC21FDE84BE613A8CC4FE1C3A6180E2AD8DE32E7A6F9E57DB1A1C1F13E7719EC6AB67670374CFC9107F360375EF32DC3986C80F8D6403EB1A90A974825D639A23E47915F3B98722E46178FF616E1750102FA7C40F35438DAB8532B7209336BBBDEDA94550A6DAA97B41B3EEED13DF722D4C948D9D654317F272F115214CDD10D4C79F83CDC8E7CF935620C3A7C6F4CEA4D21468D5B5E586A7760F90CF2C91FFE49C513DC6D46790248746D01C13B4964B8913CABC90A00E6C0EC55EDC0A43962FADEE8DB0F4A5BD8D348F100F7018818BC5D118F862B249E605DF9134C645BE93376529164A8D580C2C65C12017F645DE6E1D243BBC1B3E66364E255D05E3151175D87EA71CCC7EF1CCEC0E33B979AC60D292B33460036867C10CE59198BF3F2F1AA952D1573854B2041BC13F922E701C456C3DBFFD9FF9C2464B1B8EB4254DBC920312011066C73987C35B8AB9FD366E512A707B1277A48A17E062362B52EDAE42315D9763C414658D979BB17062060D24B02E2394F43E6E26C414532DA20D5E696B945FF8A11FEBA3ADD06105E5B481ABC7972718752C642BA0D2C1BA7EA42F87D897277EADAEA941F8F2A6C468A66AE432EF04E442138AD42FBB3B2EE0E3C2A1E1EF73737A722F2136B2EE7E1AF4DF1E0B7D22306D193D61955D1F3939105BCB7C076DBF3BBAF7DC243752E664E471108E05F94EB0AAD00AE9F091EFBA679A0175EBBB332187B41774867D0CFD65197C3D291B8EC6CD83682ADC2561A46195EA870CB84D72152A3CD7315F6E4928FC1377047506A1119039CCFC594A5C17113C8A6465141ADF95DB6D698539B3F90D7115C6B7CFDFC46EF313AC8145F9CDC2EEF900A1249173381AEF1257EB39EE47337594B1291E8B37E092 +sk = 8F70FD6B69122D1DA58FBB275F70D9EEAB795E002D2889468869E5C51ACB94EE81E13EF7A365E51C47397B61ED065B5A6F21891A4ECD7968FFBD94D60B0C7967ED1C98A72CFEEB058850059DE1A25CB9AA9D2FC80E54C6D15B9B82BCE7C9BEB1A370AAEA9B4C0962E4DA05906808D8950A20BC344E4AC7BAB5D727EA430104745267286182124722537011146533180515845028752277882108554771418460027764384216844450121047471281787178160806674851780636800672447345524275375476704863556006583108756356713578524331662420231104376422200665831130275523800246374534537145080480712570220611008714630553183038881830563332237257265183661502557801085347225750333861787253224871582713856861188326663241431228160408286423842417544166018636352708226202203176003406422120216037766755115466653317023430234415687036670615657622036042054535834624301818747011406762226804547822028505365524534318865400211468341504564104660273884324846123515580357585036508160150711801011757831025286076745361600281161823305862506244307615655781767468360571564403035063563875745440088847737320820134731333216204524863385788047876327581474574171658740468384264115027732153200450153883881218034387016388841517261280145455284045240035586805585280272246552705042444484714235381681241435185507548378477557530760278276216820653623752606138018013616624222535278863712402166680304615281043461106188172368254455418327456241235876415456388346848264212611162721700203782868424523773681755406126760060570067700342112085135437187724168858748670440174325856742326550524427075616523558437033818110660540168513637562148454684846208165086158142651610375301077688853876342718753850485261216445385808117844447048751225716571584740076031454231614663788778507617056852753568011635747758861863472587367340217651722856843661760778786667286734140548688683277153842702877310526230562861768363163416485260002425143706245280331220205253538230370110525866253201244780118402287806575386322808666558561285221653148111864487768112053858236418647233036021046317544466746782387015507162208468277217343184056322341253065131607836623841746104761274084434378754110528178224864803222358727253380370682122587855124643610682322028887382031315481103655286183104034288475355338667058058461417676158510557240084237310212471874014635746078755157656067373382378750443371480833042143373340673044208316612306726388116010208511076718116587136752416816035620458315208480062553471206372587030258706473566861848445343687511447732086645518181303265254745565073258444641273864123704017180084536682021334530784144272616085054561703384427553464788857522260340257766586443817414237363054037162414412514276257202801278776618156327247558451040856324684312085220817028736518088753743841736140222346250486073750507461210684153455637268472202574022873278286061014555646606056422414316124115802765067876607426863714027680703012830547014831475035770727202186634881627114770582262345746472637006757303754341556318275101537241605720047785228055366585762558282657804111656454702022037205348203052813155341614184448724145804468425558565131003252120600228181876256072633262364701176605014317422101000023523144486583818661233384012446721145646585178861309425DD7DDD9DFCCE459FDEB2E66F0E853BD166F8659E8B87F37789DCEEA08F291120529916713FFC149B96ECF21CFC41BBA92DD354A00B1EFB89966C4A9D715C7743E61F52DF10C263304E7A4D805FBC86257443C67572A0CBF2C473F1DC55407D57C429D95BD38400AEB9B738DC5E047716A19304F68E2090796761648CF272B1D461D90E9078B7BD98BB6455A4F9FF5EFD4948F99E1C8EDF3DE50CA50709C1C895855FA684F7DCF6474096C5B66F1E0593E18E34E382D5AF6F67D9B0BEEA9D97EAA1968AF6589C4ECC59646712B3FE88C71E9A5C848B66751586FF271B1DDE5F999978D460C0981118EAE70C6DA315B22E26BF3B5AC392D4690801463069DD857EDA63A7C440366DD3A57B46E273D15069A7D7E61353713F2F043CC5EFFC7E19B8A55FBB1E4384D0323A2B7973A0DB1832882C81B2CAE081A721145FDC02D04F7E2E4D21E2EE5EEF27E5018A4D824D0B38B2F8D524719FFEF31BC0580E2B532DE06C8746ADBBBD32A2F04CE9B502E03A4E4F2AA0C0EEEA45CAF2CF527EC0B0360E0BFD87D8CE9739A5A98518159A78B5EA9B08CA1E8A35DC7F4E0724EBC1ADED3BA749EB7AD33570EDF55ADDBF7BBF4B00E607DC83B632B1C337C24DC00304EFD9A2F201BF84D6F5009B33726CBEB132DDC13A0724568C26B63AADC708DB30602539AA7CF30D68F4ACECCCCEF929CBDA41B2F4CBA73F834E98564D09639ACF95DD1480E157C54458AB5282E7F855784EF48A010B738C7FE3FD3B824BD2ACD61F2EFF9C9836F5ED76D0DAF6EAEB7BC33A3E96C453CE9360714E1E8BE4F7C6745822CCD3B578F2780CFA422C5B761D12396BBAA10CCF79DB138BEA36293E1B6B4869C6F2BBD358D3E76C0DD5D549A8D49C3CC5E7825BEF1BFDF578D3CFBCAF0099627D18D286EF2D9EC38955E72BDF3FFB7F97CF2AAD4A932B364492D7ACC1BB70254FA6968291480C5E5A3745E6DBBDE8CDDBFB4E9DD85A3F4A91A358BC5E7DDB33E21603FE8B6267C4EBCE13331E445D496CA51BF7D834BF55C14453973FC2DB603CF88F66C0BB7F7D193CD459161791C9B4BADB680F6E5541F2B278153705F9BE6F0D289B0B68CF5403BEEFAACE3CCB14BC169A7965AF86BEF76AE876BDA5ADB1A279F59E8C534714D2B96D680AD909F7FBFDA7B2087527237F87CC2E62EDDA280053874502ADE7713B8D1C29CB5A17F94F71BA4DFE9A1EA0BA98935189382EEB22F3C9829320D87B1353006D2ED81D16FA17AC3A6E2C9192948F47F5C12042894F9B3C3B2CF109B523393516A75EB1B5B0AB1558D97CDF6770C3BA87750E0D29E690D307ED7C1B17AED795B083C3A17CC52833222D07DE2B3E248C39CD1568D374E6286D7A81C492A781D9208C7ADB77D0A8813C58750435337F6BDDC5CCE703CCCF89AFBE2B4C31A727788198D843D0FF3757EA8291BBFEAED7CF08A143966896AD9A0EA8AC1D3AF74FEA9F6657964D253788921BDA9E850EC8313CE71333425D657F51F55192A559B929A897AA526987829F2C5AE17D7900914D8103ABBA7E57EEF89775EBC2E975E060BF248EBB4DE366715B68792D77D562A90AF0F6DB7BB857D5C9B94B6F158D91E878DF825CDFC153C277C7B876EF6117DEFDCDFF97D655121B4CC05D4D25DB22A79024ECC72C97F208B62EA725B42EEC0321127050840391D6B4CB9CE3A0BC5100F19E6B0EFBC2A2BB3C6702B9B0887CCE56E2733021E32CA7309B8E120A5A86A734C14987E9DE230A8762B6D2C9407D5582A436B0B8095444EA967A28DAFE364F8FA7F599C2FE5F85A872481CFCA2BDAB42D7630E8E333C0DF40870C647E75F97404DF056884DD21809AE69A9471EFE6B5ADCCC61CE3500CE8A22EB6130F3921FC23CAC7A512DD9A11AE48D78F69F8334A2471DD71BA9A1C27544ADEC037F7271687C42C00155670C0E34F75B056F0AA5279E1AF5F7BCA59015231014B39E99A267268980DE058ACC7C2EE178A73F83F46B19CD53A32828FDE6DA0A17B296BC65AD28F8D0C05279B747D141BEA050C819DFB08BB546B272939FFF69325FAF41A60610A595663B5DC58B37DB52766969965D221D49B5C5692B3E89CAAA6535480F3DDB8BD0F4D90D62670B9C2A4B81E3566A8C69B999F901B76010F8067A7E28EB3F405B5F8FDF0B1BBD8B98AA9F6080CAB46C0EA0ED8CFA882091C7C226EDA4905D8903995A865252F48FEAD58D199203D9803F4B825CD5E438E31F9D22A78E1BD618387D0FEB49ADA530A27A8032FA2768C1581C7E39D418C483853681F4A173499B941984794B18F9DB38B56AD4CA0B88D383F69719ADF878BBE1906248EE013D45C671D6AEAAFB3FF5E4C15428ECFDC58912C620D3A6C2ECC3C232FC42C7C10E91C275F310AF954AEC3EA6E9A871F2754B2AD18C95484B027A993F096D7F918CA073D22173F755769CEF604E8F0B9F15FD656C0BE05A6A583A3D6F3F7BEF32D469DA7EE917390ABF0FB8E563FC0E3A4276CEE425F3F1141F38989D78125B590CD600A29C9F8488A9384356225B1AD8E901A3031B51BA898351B56F03E5E96C1477EBCADDD7B0AD519011230093DB11F7D4734D61119C4B90AE74AEB9E15CAC84C06E048ECCFA9FF8A4AC7234025B52082D648E5EBE431C7C29C6A025DE5A5EFFC9BF1245499487BC5AB1043CADF5E45E0FDD24F3477398B9D3F5E75F17E5837AE8664EEA4EFAFD28D4B44FAACFC53A362F63537D070F722FBE13CAD65A1EBE4A70C0514A04380D737C280887EB481A3B1D0215F41AF8C78DAAA0A3A82AB98EA2AF0301CFF0EB45D2F5DE2CC5D0935983B9B91F6AF7581D97BDF9CD64F31E1FB27EC49938D0783ECA6D7991178AD527B03C89214BCBA2A941CA6061950AE229920E5B7B0F0C825424AF069529C67862EC7784077B4FF376EDE20F809ED4ECE39D52B18050CE6425091ED35226844668A3F5C6466B31BBC50C36E91C11CC3F56E95D9EF2DAD03D8A4D735255FD5C3116BEE1AF8F85A0F9E2F028C6EB9DA7EC18A381E40B40B7C7C981F788BFBD7E95C6872B4629B04716A39B74822B59D58343B423F1BF430CC23CB3A9C29D98A8B66509CCD3897BE71C79AB95E608A2703934053DD7C97C758A24401E38C2132CB487A955906F0EBFAC4DB33A97E149CAE3E10BF75B5C321D816FDDC15806C7E903A45FF3A9F189A9D322004E4C8659E9F1EAFB0D9502C5ECCEC25FE36F94D79C15D7FC1B605BF1F3EB650A3A8919F3527000D507DA964A2BAE2F5D9755629AC379A6757E5A8542786FFF82200CAE5125CC3A00117F3EF1BBC89342EE54B72BD602573A65B159658A1403E4DF996CB8CA14BF94BF3D7FCC9E5A9522EC8A2E0C160E5D51BE9DF94CECC40E58791ECF30A7DEC99574CD8ADE2CE9C7437F0806D9A0F334C6998BB89167B4BF63ABFDC229D179C11B1AAAE958D3B951DB1BF8A401508DFBD0FBD074C3181CA405FE2F6CC30BF7A2DD534D04CAED5E423B13AF4AA678FC85A19A4E523DF850B157C7C5F55E2A0145DA9AD9D5340F329F1BF340D20D3F7F9771EAD +smlen = 4167 +sm = DB9E0F6A3278BF42B9A136A8D19207EC4799A1653133B2C58CFE1ECD799790EA5E98C262F1BE016EF3F6205F3AC50063A2B00BDCAE7AF5CC4CDD45F61457E4B20AA117504E8D54511DA1FC8B4D1681AE01014F2975727D34F7753DF048792889585B9E5049310185F37275140D4C2C4E057290A74BD1119978CBBBC232ACB912A94770C1DE9B6637D90B4EA6B2E18736E5D595632BD9362DB79B05626B7B79BBD1C8BD971459F2D590CBA9F959A651FFFF00D54C6A740C9DD91C718D65CC1BE29AB9B0CA64AFB1F13356180F0146F1CDDEFC69141E4DD3019ED1EE5DAA062D8DF4EE3AB3BCC8595CFE0694B1489CBE6FCBF4989ADD10381B1874325374FB737657B597DBC0D5AC2466F23E6BD5288E9194C54715C4093D39B07528747130BD29A15E1BC33C6EE2FECFC8A0B1CEE5367485CC2B8EA42883BA71C0226E26EB14D5D6D6990441238BA02DA80A809085C19D464B524022778F3C5866B8BEE49866BFA3DE5A108CF02F038123E6669FA204616FDB9776C1C0C43AD546725907E0BF682821DC096C8BED89E981D100CCAE77F3EB7A6CA341BAA715C0D01A1894DF20742CB938B7C02518AFADCCE1F7335C1C709F54EADB43C751FA532A895A7E1A757E483F7624D4F58F5A2F6FE8DDD5D7B531C2C55C728EEFC43A2CA2A75645786E2AD3DCB70039E499F7AF7423D5D53E4B4DF2B557D43D0BE06903F38D91AE85FBB6A6031B3F75D4A64DD54FF2DCC5F9E89B01162E41C9A9DD039DEF83A31883FF1E0116436923B296F46AAAA8F50995894EEE53BB8EEF8C90FC8D297EC965BD3299D799687C7E9CC0E0C639525B192EAC53CD014C78F4A243C406D9D243033766954808797D929318AB08DF5E3FD6BBB83DDD4D010FFC1CE9F04FA232E48B4F078E090ED61CFB4E9A7D889D77A7C4F9696279F0A9C4D44C6EC2638ACCEFE45BEA65923971AC35BA2761FC213EEB846A1EFB59227E5B49CEEDB523AF9B3D1A00547033CD0E1FA2620862465FCB76DD73EBA806DA4A8828912B3146A7E739DB68BEBE1E3717D223F85A3E22082ABF90BE4A97674CCF9D74A9CB04E70759AF82DF36D1D84B699929593A189CBD488858EB6F6E1DC3B04B597EA7735738EF3DA51B4D128DF41BCD2992A35B0AF63F8EE63097E6C006170450C19386662840FB3FB59CE0A94B08879FD135954A49096936D8C5D9BC12B277A414F8E33118AF86F6153EF09C06374A64DC28FDD79CA6EBBEE5EB68347B3C0F78B381A1739173238F1AAFF603FD2237C0E6F35F73985396BF8143DF5E81C42C1A8C07776B6D986B7E0B678CEA1E0258DB62B58D680B7017D25C0F2211B70B73B3EB9EA3C4BFCCA4F0108F90310E08BA552D31CAF7A897ED76E35F8247A52286C82FC542F4F0C55D7D204B0C2E428D3937252A93C1568A2C61F1A2330958406A9CC5F39622055D3A2D0CEDD7E367EC2DD89C750CA2766097E359B3F20FD3FCA286780A6FE4706EE051AA6A452EEAEC930CA64441849712921F789C3D42ECC60117A4B5AC30B5B0D704005FD7244BCC539A3E2A92D14F719A483BE249D467CFF61F39585E49FDCD04A1E5A426412E46C8FBA716C9A6D91D4049C4B2138F063E800A4296EF29E42B81EB2A2F7FBF24587C73C199FE1071FFD7B23E554EDF8A1FF77B74A3F533324BD40FD9F3DA12A05BA3C032B5CA835308FC7E917D3D35CF2B9C8249435C53E86C43828E5C4C111DD5C30D6D3B660048510F70BB194FC7829069668D72779E192B096D21DE372BF06CBD923DF1DA95FB54B0112E2AE73081FF496BC22DE721596A3AE9A0237F4204C80991D1B58384BADACE05568883D989C95C2AA8528299B4308A50BA8B24E126BCAD3EB480D6790D39B20E92A40516F6E714A7C9C6ACA69FE39479BFBBB97A069AD607E0D53431EC7F13EB4520C392AEDE157C0CAF1EC2DAAB23F1200B665534EF1C94B3A6318B8B3DB8FA2885A49D85FB413E2172922BA91CD71C1788B4F2DDCD47E9DA7F353C0E78FA65162AF376DD19CA90AA21DFF315A08AFBC9854CAD3A51D43A427E489D4512AF8A99768250FF144709C61E02E2699092D6C881E0B4918FFA05B605DB489DA7365C59690A56E9D9E0F17E8D1E5EFC596B4FCD2E1BC8E30539C1036F22540E6FDEB764DB433C2CD67DF2EA8206E26941BCD6C6C36AA0E295FF1BCC0B74D3E5395A6ED17B6104EB3983574F28956DEF8D26C35BB9F75376EEBB33A3D944A376F0EF5D65102E5E4D2BEFE4FC773902C3F4B220018A5F91C8070A698647648BEB814003B0EAEB38DBF4F1F2BEE15BF58B2295461E91A7366D7FE34D21F21DD10B1151324D27359945A9E61C56F02C5F5B7EC58D888989C1B41DACE30775C80B1AD6B9D6FAD98A1675C5B2D7C436A966BC5B986A1FFAC259F455EBEC1D5CD12688AB92C0FFCE3F952D07D8E549DD57C487D8D3A338B1FB88194725A4C24BD9419686E344AD5DA2347860D6C11C02FE7904FF79A949335EF49109B873AB252E843D37AB46F4428A7BD66AD51D3560C1F129748849535A23007CA40AA5B11867422C63C6D88BE0DE387E8E1F6899D19B3F58248ACF37F2B874906138EFD8732BED7E7FFFDE66510409082B090B043926BCDDB51C4F10628488749BF81C87C96D5E5FC07416CCE8C270D5B44CC96D3580A28D676D57E63F8C7DB474FD36300A1250D314DB9B0CB608F626C42551FFED201FB36F86C965F6707AB3FB46BA59DE5C19D83718FEE2D7812B548722BC403AE73A54151158F95B59C158F319DA204956D4BAF7C9CFA7CF384605CB280EEC7B6C12F18A28A36A0362F58CA47BCA32D4AEADA4BD58A026FF3E55E7D8C81B6BFE0B0580FE056AA7F4B53E658E2D9AAE439609440DC5EF116233D1E3F106EAED53CEECBFC3A288A9DD5168AE22E428EB6B2CE1705A11F509FD76B4939671572A76CB7C50B2F0B489980B5AB72999F78DD249D6AD3F5EBD4014A9CE8AB3F87C4D172A9BAB6D3991DA18AE85579E6C0C5077AE870306C0A417BF9C4D312682085A2043A90B3E6EE444D95CD86A7ED95236DC89775B98E4F4B8487B4E40C4B64E95472CC122A2741B139E5E3F983DE54303ACE3BA840A91D87DF40C5353928061AD7ACECEE3B1153DB23C5C151C0EC5CBCC348D5639D6BF84926767D7759F9A0D7B56F669D509C739D97A2A77EC59FA77F86E6F00EFC74A71C3B508AADAAB9DA1CC97022B7627AC6E5A57927E876CAF038F03A3EB9CB538C8C2B4B0F6B6EF5D97DEDC84B01F74CC511A0E5240BE865F99E4934A0711DB93875C33BDAA1A8E409C2DB7EAB9350356444D7FAFE4684C1C483C34DADEC9292379371DBDC1F51F1F723A8FDE9BFAD358F3EDC238CDFE4B7C89E167883E124642B339AFE9E8F41A9C93298972FF4C6078B941EE042068AFF06CD697123F1118487E8D31EAAC5CBBED71141A433CDBA1CE53372AC8F7DC4AF92FBD7701E503366798AACED5037434C9E394C891F3520482E62BC513433D0F193AE954574DCB71CFB3285B9EF5DEB478BB57033E02A5361A33449E51CE4AFC1AB9DF904A18196CBDE44F169B4AD4D729BD941147B4228812AA489293CAAA119B00C59AA43841B6ADAC4B6587F66A17FDB82D801804C5F136E7F30A2615046A0CD911079BE95928F77DF9C8F8BDC9A7FC34D2756444DC74DC79828C6091EFFFDC2F520AB031266547737C31A70FE55FFC8F8263D39B9D4CAB554AC5F47490625C07D30BDEFE0AC81C7F85FC7E4CC4FCE6F8BFCAE84A67534ABFBDBEB26B228022427140160BBE19A242750D4469BFF9C14560D6D2744D5F04E364F52EEB6CA451F2E5B9C7B607DC03FD8419107C5AE837E695896D6256A250A5979252D959072C2E6334057A5A4E7516B78626C304D69E9906B50260DBAED7FB9BF33AB2FC25F99B4F5878475D7B2736B45CF20FFBB945117EA494225B8788E8004D0350C529DB71D5F6F805DEEE9607B729ECD87AA9A09FC0CAB05D8EB01754076E548DA236F28C85D6FB0A82931FD86C9059F00EDC05B703AD4368C584294CADD02A02C39AE7D529069F21E4D20021CBC49B89F48661E1A45E16553385D0FB10E7B57A2B9FC6B1BE4365D12942CFB36117D7C35BA805BA7C5F3744E5E25EC7D4414F360F8C9BF59FE8C27DD2D466DCC65624CAD634843026665B74E184570A93C49F7B0A0860F3E332BCCB59FA5FC29BC4829E6F4C269444900267B08C4E97974DB01F84F3E81EFD5F523CE8E5679DD2339FF1107B23F098F41B7A8A206619CDA6C8F8FB47ECB3F52B2F479EC4D354040E8A18216B47BE2513A62ADA2AEC4837725FDF532869EE4940A2206ACC1F163240635A584B9353216AA489084C0F5E2ED71136B2DB28AC8A24CFFD946506E69A7CE4096AC13B7CAB9F856D9E40A00E63ED7C0B0684BB1DF5858D65F9169C05F8DA31B88669691C4184DE36F224C9D5EBAAA995AA5BE4E0D2E902F2196189E04354B72E577382CFFEBE72B8EBAC5654E744678E18E77D95A6D9FECD3E1C7B536B0E9467B7B17DB3ACDB8B771B51794AE93CAA55E4F812AC657D37FB7ACE38E75BF1F778DABC8557B90CF2DCF7FEAB886054C089DC1AE119BAF085CFD3BA97C97315BE0E5A8E94B4D1030A97CEDFED8AC8E22C2E5760E10D32718C8FC9D1FD1933454E6F9EE30000000000000000000000000000000000000000060C0F141C238F37A065DD696AD437EC82909261B842EC0A3E66F8AC574105A3C82EC8B4926F2466FA550F8EA1B6A9A142C00AFA44BE6512A85350930DFFC99B95AA21012057051B68C48581AE439B9290A163AA4B6AFCF80FFB91A3321C7B9ABAD56D5DC1BE4E67E5576C9F3A7DB96071859B94EB22A73DD96C66AE67AB11D1AB62A86D826C682DFB8CCA3259DCB5B34BE635421CD4206E7D92147F14C36424EAA407B441F58E5C187E58A26B2AE144888A3CC1387AC7D0A681EEDDC3B7781AB282E8185CCF33FB27500CFD119E0415DB1E45237520A868C8457C88A1D3EE97EC9451DA35D7E74924F8902949E7EB14BA87C8AC672D7E4F3BEC1B2814DFA67A8DD2E2D4FF4661D64BC4C6D6A78D4E489689B6063CDFF5A3F1554501B424284A9F4B8FE777FE4E6AFB83A85E36200A9AB40B9C18678454B2A3F50A4862BA1E36F0C57AD004FF90192B5619614E37DBB38A1B8A65AC613F7796C70772128377065B84F122540106D1B4F9123C4E009B4C0A85D59B35F72DEBDDD154ABEC7F3FB25FD1FA04367386098DE610B26FA3ECB031A6072D14607E92FFBE195ABFF71E586A984131AF24E18AE94DBAB0544FD2AD217960F337111BFBD4046809EA03C7C47B7177757A4A43E1FD0134859BA735A8FC17597E593BB58322136602954D3A21096B0D1DEE5CF0AD17A5FCF561FFA21CAA70D33998840E4CFA18BA481704A8B82D2CC1C110FC9A6704751365AE9F338AFE4CF9C811697DDDFA8635A2F3CD02DD1845251014BF2F2D6C02A907BD783207C4773A937048A07C500D7C424B5F65A2C376523740DF9A0B60437CB8AE17D64DD51DD4E433AF83B20C4B6B890B97976DF09E3A86AC19006C229D59FC7A2923245B7B1F0ACF7C42E486D41CA1AC1D7051AEEF6003CE94182F97D099C74317F61EB47AE18C2BED6A3CB253C21EC835E435123E0A657ED926F880CE8E5DE3155272328A467278F52AC50A1121AE818A3EA3A2E1F7401CE23AAF66A4AC289748A7E98A5124C586D8957BB4EDD3F091492BB1A64D75EFCD45AD51CA420F15DA848B20DC6BB765E7B71359B3A9E95E121266AE4A40DC2E9A3D81EA1B1A643594B3D4E6ABB7D1202201DE92BDF0CC1ED977E2D5851822A01F48A6F23180822888CE345AC9BE0CC69BC448D41CA20B79C35B1DAD73E6C683E70C4439B404CBF07FCC39B0E5A1D33F3717A6BAD28A6DA4F091BC7A + +count = 26 +seed = 49CC05312D1DBE216FF03B60575017A6A1464C06D2C5A4A6F973AD9F275F7C66163A29A803BE759B117043862D277C27 +mlen = 891 +msg = 30D61C6FBD64113FCED8C5205026EBAC0D9F3522182617CB00B6E70C8DA62ECC1BBC8E1FDAF17CC61DD01CE85A9072CC1D9D34FDADBA5B93E0AAB4C9C4C9E26D3F7F145FCB23673B6E0B373C0FD1A58F52486B72624EF91A539519EE5305772A006E49521744912BCF3CDBAD424F00428AA96CCC21D000EFB09DA5CE652E361A6FB649A060835E3B9DC9CBEC660C7531620115EC905DCA6EE2A1CE36554C0FC1D6DD6863B8F3843508ED5C214B6923E7F5C0304E9B0D5E5E433BD029116A33A60CB980737AC950577D0594BFE0AD2225CB8D3FA42F192B0EC05A49391632A32FA931C0FBD83A7B6EA24301AD0906E7911F9D900D19AE1247ABABB1C0E9B9BD165185D9D7413EA068FE8824CCE5B3AD51FE8E2BB2C4022C61B002C1DF4852E4910F38613787CA12371038B6364D920E07B4B417401253451DDC25624B5D038B2DFE29B8494EC960F87803CAA256A95C9868AF819747E4BF26FAABA6DDBAED93A7815C795AD5EB7FB4592DF678AC1375388CC7ED3A6230CBE80ABBB113C80B70C789CF0C66B943E67CE814F12D3D83F3B90A4320FEB7FB81DC93B05D7FE2D36584399214D3D7C71AEF322A5D04B5470703B3660BF86B0B17BA9FF23E45F7BEFEC3758786D2111C81BA4D81B83FEEA35A0668E5EB3694963BB4DB3ACCE4FCBA6F3F6FED9627580DD2D2DC103EF7E52BB9745BD42A7FBDB459B5C8AAEBA67686EB899E3177FAF0897C61B008ACE3304C41B4C79E2EF9C865E9958D8716BDDB69154FB33187D927B5296C1589FB1AE3D553F116FF6CAE56910CE6717C446B9947AB2A981A8F5999C1C6E517EB3FE584F5D10059910E22F40FBDDB709C9F686F51ABF7D7206A8BAB4A346B51523C362D749238D7EF6671A89CD86A8540604F134D760267E91EB92FC0FC275CAB69C776EF81DBAD35027E5307F1D34EBF5D6E4DF424D709666A1E649C044C4930098B2E6E3782A93976B55073C504563C7E052B6816C07F0FD54A759D2BC189FAC3FF54549FC4DE192EFB58A9E301863A77380967735910F63D35EF5FDBD8751DE4BC6BF2E3095628DC7F67C1F5571D17AA342593B2C7F953C3F0F22DA1862122031BBEAF0D00A029C043304E3E2609C4FED8A7404FA10E2EC846A70EB0E37C5BE61E698CF2296EC1FBE6FED75F6FE3113C23B29AFB5A6D7E3A9E46E2D89D8C06450CEA11492C1A97F7D6BE8FF6C014930043022B264FD32593952BC606F779598631E48EED86EC2A013D8EB866F311A400 +pk = AFE9D17976DA571A2E0928897764C4582FA9EFF50BDA236E80D001763CD533D64EBD3099A0B13E80266EF6A154E443CD5A8777C19A6F452C589AD1FB319FCBFEF4EF9F89866E338B417EDF014A57EF6A73785199C82D77E71729E193CD8C95EDD57A6AFB3B70A4DF49CB3D9D7A8BBCEDE6DDEDB87C64144B4FD70A794B0499F89C15DE77CD7ECEA0D79E1505FF62411CA15DE173F3E5D09835EE4682D0F008B2450F88C02887CB0662DE465150B5BB45BAF4F0C13BD3628CC4527D6D1E69DDF291451268DB20CB3BE605ADA19B7FDAB6AC8F49D6C75DAD57E92B67EC4B21B2FF21F89BB67A8E2F205F3A3D893F35226312C5A0CA162A9376288B1CBC7C61063367CBC3306006373A7DED776CE213B9082F82ADBB9650F0C9EF9DE18B22C1ED9B7B92FB24DC9DE095EA21FAA03A27322E985F9036E0E6F05B100015888FC33872D52C8004B56F2B3F2BFF6A99BBD6D8A1969EDEF88A573D25358DB9D64AA3D414B10A6726128118408732688C6DE7C1026EA84419DB5232877876757F48B66D1ECE7BEEBE7AF365A2A964C68DCAACB4B3700D7B27B6BFA7E6E99AD0CFFA00A3E98CB8A601FE11F03A150B62891A67B2CE29B83FB9F22F67D3004ACDA1ADCE99505D1C75137B245BF504EB3E4C123D18BC1EB3744442AB1210B677D7F62166ECB566B4069AB6A769A88B70B02C8DE57B6E9B250D51AFFEB8C884790A2F346E73C7A5A46E651D8CDE6529D02909DCCF838FAC5E2DC96D534CB557BB341FA5334AB45B88EC019068979262EDDAB6FFE43618C545756B908DCF072482337470E80694D3D1CD87F935F6B6B1BED678797CC79529654C9149B33ED9046092E7C93483A9A2F8722A452F307A5430278C31E3003561D88FEA8F8E7887A2430FA5CB83DCF1C12126ACB2911FD4A7502F8DBE47BF652A71380366E74CC1262802270ABB8D49813B82213497FFFE3D83D0BCA1B0F3F931528EC59BC269D7081322A4713381E2854F73A92DC4448B565AB6A2E49853C12E8C285C2FDC2803C4E6931061F71BE45732057DC241A8669D8129553ED9922B81DC847FED65435F6713EAF3231D54A8DB25843CD48363AE26C29CD8B5173FFFB022596F47BDFD7FB69F45017B2D1A68771A269D3A7FF39F7A0C4D3FC2938E0A5C03D89490FCD4534E0F750E7719DD1867AEFD96DF3EA183C80A317A1C7559D44A09D38949C7827BF352B6EB925027E650D04636552F13912B8F1B808ECCEE20FAF83AD120C7850A1CCF0DA4AE2DBD1125336E3A1D14DEFC12BA7DA725A7532FB56B9D0C3DFA39AACBEEE139047324E0787F1220E3E9B1A8366394BD29E8E4763E2F24A5B2C4CBECF00505E92B90926845E1D5C0680C9B3C6BC741E9B32EC3388E2F4DD458A5EBE6150D5B18B9A933834120459572208CAAD0EF48B59CD5B23B2588029D1E3E712BD885D8298122BC6250A5F01BCB6FF6AA1CAF64FCA2433FE25EEFAFF95C14640C4B5CD82F721E8823ABC74D75A61C58F02C84968D412D49AB71F6DE9A6C0CAFEBE1E25CBFBA6D21F7176ED1332C023425A902CDAD703DA870A009BDEF4A4865538981D2A9EE9D86256CA0F03AB043DCDF0F9A263D7B460BDFDD61DD66B8D7BC33006F1F1A55CA0FFDB62B25874E1B259B2973A0A1675C21E87CE0495D551F94FFA1C936D75EEFE24D1AB9001D0D7336125E537C35F5B1B839AAD2B5468AEB13A30919EF99CB13A6712B68E8EB92404C44C2937F6B70B051CA748ED5D025FFFD042AD9A56AB77F6A6BBE9BEA24FA97566C40B3D3B9BDABD5F18226FB7447E704D53B881746A4CD3DA396F24D43AEBF453D345273C40569B27A91958D20C449A6BA707A86BE52A4DFD999A879938704D651B3E78DDC3F44DE791D241782F2342879EA4B64148D9F55E79EE70C399F63E379F67889CACB88654A08780F267519F8F78B506AAA5535196E0BD4D7E0A47E5DBBDC950275DF08FAD4D86C368332A7C65A704298AEE8656AD64B80B5608B62E8491729E3A86E12F4749C6FFCDB5F5F636E52C828937E333C68D8CDD325BBD8C9D3B2CFBE60E22838D6717A85A0289CB3E036C581E6483231AE26CE3D646C1731ADEAD760ABFBF4CC9C8D587B049E1F505DB8B7A02ED94713E96F7EC91FF83B8436543B8FCE899CE5D40870C7D3FF0E440894B2A3F0F90432DE68636CEA7DD9427A0C35511F40637D6F28CD64A8A660EB496D4B75F6E74C66264D663889135E3DC478C269AAE992D8CF6D51EBBAF4402B12650C5F8F7A75BBE15ECB1678AA6B99796AA86369CC9E58942A3B56AFF257D2BD877376B4D6487800617128BD6579F79A74FBBDD2F78183E3C3732BF26604A42EB4C86FF2CCD56A896E108353CF1C441AF0FEC7A8B215BA31B126D7ADB9AC4E599EBAE8A0710218DAD48D436AC39E13F4D8EB2A3629A6AC2B9C825B46F83558B4B0F07A94284154325CBE350B75C899E96242331BBB38F81E08AE2FBD61F1E48BE9C2891AE8BDDC0140924FACC249E3CB3DC38468200966739024DBB4B19154CBE3F7ED7665A1EF01C8574B032C56EBF2DA563E33E7AD1E414CEDDD5E50C8754F055F1118757F6D89418D24C8F470A8A20CC448C30179884DA012DCBE26808B2308A9885BF59A1DC5B998C389987F75FBE8BB0BDB56306C8CCC8B0C99DE3B04BAF7E9DA2111323FEB85E9B40E9FBBE76879947364113E0BF4E2C6ACE03F3E8F2572D4CD33A4B1A153B230C986EB89901660E81F6D84F17324F94278DA44CDFBD1B960D50A1134396D +sk = AFE9D17976DA571A2E0928897764C4582FA9EFF50BDA236E80D001763CD533D6B9EBF111B43B33E290D7D13308CFF305DA29C632E1FE43B8CFF78234E4F933DF75E20B20B0C206E2B56DBCE27AFA70B88975D9035262F8211286401F4AB4D11CA5053E1835D1E13406F1F8D2CB482ADDE3F944775650F2A96064890EE4F1D768314756627112818385047488621322183262065646386857544666822875811666223166265783282178766045710766065718811112367825008070404731468840626144715506508842304126575100020523270613200672171438584301617325066044083727034865275850161068647865607387233032573247042221668772186780583827046358480117175631704434674380457617213187048867656764012228486338537711506064005200083505841386113311036264717360832648674712865238700318008751618674102338027583708244106724831452852685030130181567433574620127783088735831371523655710762770615233383131442837056016176181802087414837064233880378405243502130028600168664441643770714235084684105048426524681187164147533456753357743547815818062348152446434346305113314124386087167486220736507158236662731573735158886534317845465165611782374002660478742067005880076873310127311418787115183431782704585441766065614132552670203640518672866466368366876685124435352613680253740606338844868277850020384515765711354630038652711807358105471427386661156114365771266722463585174035568226405736263885536543587435628783185035008735210464043422734472118844636145786386637638350676412661257167562365015757014535727651451030655284565231625014572574688218084047434276077801138417723781711100610260537801162642115244523288626187681608716730782621575164720565548001817605312656500545582215040307752024373341354706703654235746026554533621414204305711350022680416731518473887660484845181540008578013507044071016104622134662736643681173344847821235663201378602520083108746740025728105247200565083665575332622806613672845682843063401017233218572555575484170344683435210753571058286355316076172276683524376231223756132626346457535578667610064624608412515042715600435576226627206068641171787745625150147712101208352601140203667513141058404237462620885711238267084510813575056564387686823452627030580877073110233758700422477867214631624342785557415501048605768013814001184843033840703862683754325812846170836538234628644033386515320627314168555605268187810775306474872421604366572571210226348683216370017412338667532812343740322854605485233422414323676254355836846132188267707602625353101468488836202278331105110618206005488030551311201626016013751361110868878155112867751547630040674433172321725108043860182714037738560348143510062154147867157832441866376504575014641426781187266802133213624616514248278706088381086655714418365530230347343410102625064815210274862874013277660530334127050860753738546216378716540625322515705142011623364874503232463568500306620470217871040134783044483867221088042735337164120658383410807514355721136446382146010614810502164203727131263121880348085734340770562134778505777401644733618780624146565503127611005354552135326356025877112276453744464273873564724676743678461836346834732685522208008412637637453042223825738618058277522411208678221156507116440385562147637318842410415251507326542F5F0138D739799908CCC4EAA1478601B4D06C0BA60918DDDE59ED865E261BB742E625F477998486BCAD8535F69061C95E13C41D01D08E7B3EBD752839B3935C1E80ADD0A8B4D9D213D4DD04E841BF1CFCD92FF1B1A5B1F57E2CC8A46B20D51FB80C0346283B985CC307FEC93E139FCCAB3FF4F32B622CBE7C09022FB8D8FE3489933CAC59F993055FB98D1645475C934E6D91CC3446AE7EB75EBE0FF9367056F370902763D00BD25CE5E27F38400153809E2F5F388B28D1AE581BA8DE4459F4FCEB7B60BC4D5B0B3174313B48330169F1A518367E50BD2E1FDF4F33DAE7EAE1B56B915B81923535CB29F952965E1357672F85281D8CE36C7F705A820655CBB5AB5B46E2985CF5FBA86355E867296E3B486C989E5B77566EA7D70A53BF46EDF6B0363F6594337F4D8231A6A7A72700B8C26E1610441E7B91A5502EA0EDF5B021D7E1541C6FAECDF15E4D2097754BD43ADA924E3ABDAA14F93CBE8C21655C6BD79E0861B075162B4E054CE73B3A332CAEE4908EC3E2F1E24C4FB2B7EF143C567070F2BD23FDC37E63FCE77250CBF1AAEE1958CE57E258D5E69DE7D93A440D15757601D51C00707C2AF197FB9FCBE038992D9540356C3A9C46F1302F83CE0ACEC564BAFD77640E3AED0D42B136D48A07F2301D96CC7994F904023C0F16D8D0D9A91254D6A73BD0C12743A6050C2E8D6455DAF881812280BE5748AD4C865904CFBEDC36AE8194969258A1C62B01CF9323DE7F3F9CAF8462B8697685F5C0AAD02FA97B22FE5DE28CB30EE451D6F330E129856DA99140D64A9C2DD36ACF8B74DF6BDC79673720626AC93757ECED8101D9D25C1D93BFBDB632CF43FA29A6F5D2FB64AD1186A88C4B09DC429CB55F014CF157BA7729342861BCCC36F76A99B270C0CBD93FC1FE61D9EB2976A9FD55D7A62645C7A7303EBB3996A1410693875756CD12B9E44AD1727EBE276B7325E6CEDC11C8DD398F16C638EB59378F75FEDC6D4507697590C2B768F348E5A3609A5E6BA66B06FA0D01C54E63362146563CFC408E5705813BF6FDE410B37B838BAF956F8C9A9F0FBD82E5BBBB68F819D7018FEF9BAC975EBE576C5BDE774D3020232ED879778EA5207CAE56C36EB2EB2C209FDE101F586F1A7BB11AD607BE39D5C17D6C197987B7BABF84BFE688D5824306C7CF7EC1B4EF1976C583E2A330F42402AA82A438967DA0DD7C59DD0035FBE7EC0487F4A52F1DBB883A4D6A8D0E9705B1B96D473BEE74819B139A411BB7D5D23F3D424EB3CB6D437F8EC9D32572DB9F052CD7CB38CC3DF805305D7EA19CDF3835281C641AB8D409FF30C17B57BE52F9DF31D2B199559E9701A7E44CF03453DCE6869F04B97004A166ECFC8F912443C84EFAE0DC9193DBD0914A9B7CAE0D5FE06644120CE588E3C9D47E24A0E23F875E3269D7DF35794107C37E291F44DF2D7FFBE194696D1FD40AE0D7A21F435EA41772695F6D85D01F56460A04054F4D8F9FF7659711A8D6E241BDA356F919868ED54F1395B4CDC90502B268D91550226206A75A60834E332993DFC6FA97E98A92DE2189A2872E9A4E1EC06464F5FB29072929BA9CB3E0EAE081ACB40257B9ACA553CF0E53886792CEAC00ACDA49BDA52CCA7F536A7E9205981577625F5C1BCD354FE56214AFEEA7EEB1B299E353B766CF376B88F46316EC1E4839115A28F8F845F74AB0AC7BF0EE1B02619B143B927A9CADED3ABEF37BFDAA4572B6AC9CA6565BDDDB24A0214477D4F8DA5081985940612906058FEF03838B0A4174FC4701059FF9BFAEB059854B3E2926E69C5F0DCF7464E7752AAEA3CC90DE1FF3132822B9C6BEF873AB1679DA4B924FB3CE472A42AF381420C684BA9B8475B6C7D85C1CDD4C69B8DD9979AFE129DF6F99FA9A5E7871F46C7667017CBF07358D4D2AC5ADF9E2C7BEE798DA0BA32A4A98B8B40F5CFFA4545B1D92EDA623463812A31842629AB092D23A306EE284B41CC7D0C6424290598A6D1AB266E61A630C8807B02A5857557DEE67A51E72289D6586BEFDF27AAA527D3E1B1FBBC9D83D31149E2DD0E201207F6293AA574C1387BDE64BDEB0C7FB4A149B35A906BE875182C3CC11E91496F107BC37743C5587ED1C18DF11A0423790459B002214D48AFFE6F8440D2E6E01F41A5B30B0D9B64467CD7F69DE19FC4BEBDDFD123902011A7C4787D4E1E50AC64F9AB58314BB31752B178A33A849327FE2C8B2F1D36BDEFBC96F874DAD7680C8CDADB8112267A71DC395200887B06D910B1D40EC4A9B7008BF5064819394CF0CCC10A0F76B60E31B36E7F454EC2044F68270017D9101BD6160B7857B7BF7F70CDF807380B2D10FC168D9AB56A2AB384A0AE949E4253654D0D8C0A3B830987EC2A3E392860CE737AF5A156AFD88D0E073254813249F0F89AE520A5C39B63A4C71B3DC2009EF735D682002224CF1BA4C81C14568614990480A2EA380C2DD37FC2FB357BE73E40E85BCBA5266FA54C1A308E4ABF807384A6F8E79EFE050832EBAE7A2729D297EFB09674DA11559EC08D8F8F5496F36B43BB74C30BFE22C424EE67E380F344CF04055021C4A67051734FB96F53A704FC989B70B29BE44BDC12DB3D46BEBA34C5CD2806FCDD5EFCC76CF45E0D37109692AA223B3514F4F6BC3558B1AAE172A61CAF2DD5759411A5CEE6F685658547100EBB186A01A8288FE38BB9445946FE1E836980B9C0411E52E0B254E117E542BAFED6A9C12968ABFB4DCD829146201667261851A10176BE9B348F25D3E683AAA94F5DE4EB0E93BA70F8E2AFCBD4CC256300138D3261EA02139493152029B7836912877829E1F460B3325B48BB40153BA3E094F89762326A0DCABCC39E48901BEC8E5C6298EB548D16D92799503B120E76CA46DBED24DF9ABBF3155AE964A75A77E8DC1EDDB59F08D148586BABF88A0BF15CB22D680D238DB478B4818D6B4E4FF416267C51818E3E4729360056864541F3F037D9AC90D34F60EA7EAE44C62B577F089E9F0474AEB7CEE679727A400B5EB9809EBDEF2E3F589C1FF89CEC3A341825BC9553B39324FD728D7216AC115AF7992CDBB3EA4899A0C83273185B6525A4D493E24B82F986541FE7410770722EE6DD726234924A5CBBD4D955B5DAD6F835203E38D73FD11168C2AC0268A902CC3B14F92B98F7F0CD2D41DA4D1FA8A2231B52EC144E125256C333D80764CAA5A95615FE02C18E3812B77DB9909F4CC250AFD1169E45947C21FADF019DF4C4091A462F05E5D36C9C4888E6EC5A3FAC1EA28BFD7B11D32AC46D0679E395B00894310A2376F4BC099DA7E63A8F9C3299595CAEEF413EC5A55C1B3A8A9EE2CA88EB76454E06BD1AB9D13081C401D2A558AFBA30579044AEA1F268A279AD159F3EF162520801745FD2B60137307362CF937C5E1A40EBC7F87201D29D82871E49A8AC33F9BA26974DE4D69CB70B2CB2EFACB8E7EFC1DDE680BC9CC847B535B447D0014E441A98C7B1AADBA6E7A64FF761F32826F32E89CDC25AB1531808816F140709F35635B6A685D2A8D7B132DBA322B512C2DCED251B5F468 +smlen = 4200 +sm = 771751D06E29DC3F792C72BE2FCCC78F766572C17D8F16BE243CE0B0CA47BC03EF1323A2E12D1B6621D08DEA158B21014B1251E8F1822054B912193ADEFAADCAA0A5DC059AC5127F235261E6D06F5137E860B5D8D74F8AE8BC30B20508001141C13EDEE921E7EFB407D72BC1CD27EB110F5286836F5AAC97293AB09076EC22367120C3FBF45579AB10A863AA049017EF58548AA048CF265AFC6DBE2C17FE9C7678C572CB2D819FB45666ADEF61ED317326C4BD5B39880D36893BC68306A440F9535175B5BE6E2D80842861451B389DB913FB4ED46130B84C2DEEB7295363DF335CC3B95260CB61E4151904BF787C93C7FDD43B45996B35B01F78DA3BCDCAB1D0CCE522D01892DCD45A122DB332F802079632DB442F78E9DF66D8EBF15E8481BCCB4ABF53D1D3550BD74394B6DA9D059160EF1085BDA4CC8F773A9E86977F05CC93906F388113A22219A64EE2F02B5186BDAE35A65CB597D303BD2DC59C622DC8A01F6851CC4F0056EA7C23D6D0C2CF9E6A75047AFDD0A5E3C01809153D214744D5F387BD2D978F09A59417DD2CA411767866BA7E0073F4985A6A853116D531B1F1783225E9CA1355B8BBDF4E0D1149A52D1C20F7F53C62FEC0CA4F4BE1D30C0CC1A2815BBA0EF7A6F3E0DD48F22DB53A9DB2F35908C56133A4F14D4233E26D6BB834355BFAE8B9F9AC458DF4C356885084D65A788E709EB5B7CC86ABAEB4B32605492029426606513C82D835F3D7D122061382B7DA65ACF6B56D27E47E9B81CE57A03E60E40722AAD6B1146D64CD7AE9E4F57680E84AD394F6343B46F159AA80203EFAD8718EDE8B0317CFFAC6EAECAF9A6571858A63AEDD3877685879A3C5306500458C98A0B8B11D83730C48B84337100B0A2F3BED406491240E28EF31809E20D1AA9A77ECD6BDFC0D9324F80993A1C3F27891689DF408100EFEC8DF29D2198BB8C0A582CDA8049A834CFB43A350549BD0D52E5B1137C7E0B4CA2E88D6EA381C6C10401C979645D205103A1380D5AD7171165DD33C07C817C65547EEAA7C84BEE3945E50B77F830E10B76127C9A7980273E131812C5ED9EF44F4B5B8381424B9A8746A93D3A4CE5F95F028D1C3A7904BA97538DCB153459EBE2BEA3EC9D8EBBAE9AAB780F6954FBB317EBC04FF874A19A251C557017E03344F4D14DA4AA2A8ECD5E7BF1D87197304108E8F4291315D14859FE59DA1920AA81490E052B4D0F6E93835FFE0D409CE6BF1E5B1E9D19E8A5FF38D2457E69165950807BAF1AA6790B69C572377BF001741A787EED4E8D5F50ED606E5C88390DABA6C6F3F0B392B63303A1425DCCDFB311284743F181130B25518FDA4EAFD3397A2F68A48E7AFBB964C634B6AA4A1A54EFCEDD882606F5BD6DA4E39B587DB3D7DE4BA578512036DA49CD01B2066C2C2150853EEE1DFD4141157F313D269DDF94120B4C533069DF7F881FA38EE0323CADB7DAD5E13350817A2660E2D25DC417D2DA40F93F9F7A428722537D537B6C956C07F9C4A9E51A2DAB8A3B6A8656D04FA36A467EAE73E82035B57CD85438E3E80CC5181760257072F60A02055F374804D2303F209CFC2499DE65C28A9D7015E613BA6360B57612DFDAC5A1DAD109319910A1A7079D941052AB92453D21FD510DF9F35E47CB13024C1A67ED0D938F009813DAEFEE248723FD692E68940819DFCCE64F5FA4EC381B44F227C72BCC8916D0D9D0F506EB383606FA852BCEE5EDB8B1BF22815C8696B6D820EE08FD5E46DCC6563DB443724F3F37D09033E92D0116CB0B63955B54CAFE97D472F771EBE45800F4918E8E3C98EBE3DE319EBC20B71995BF76104CA405CD8C4D2E7323FB8861F1842F257AD05B4A1DCD277ACA02FD8924D6570250520E761EE4A675535494D049E14920D8602977C4F3E50AB6039A668EE2EF7C184A9060829CA6414E4549521F5C0FADE0EC5FD433EB1C04FCCB779D8E13BB2E0E10C6AC60690840E3B1EB006F98B4BC729753AA7BFFBFA111978568DBF5CA8B96BD7FE7969DD50D86E92679236B82A2CA4877B1A70107359B1E9911261E49C6F0028920F56936CCA4306FCA25523131B8EB3AC8B7D975A6F5A1853056E64ADB208CC1F2E45242B5A8A429D6C881B13C53DE2F7E07AE5C0C329F454B46532BE1713B95C40CF051F018A2FD01E3A0C3C3EF32E0A08F1C89F4E3DDD184A1EBFE5C335B43A590FF1ADB08898F6DAAF25B3C3D106EAA53CA6808D851783AAD767D04DC0F501BE3756A34ECC3ABD7C0CF9D840E5902641093A1429CCD4BD7FC56B7918CAFF41A3172E6198A2CBA6A483DA930AD0B3B3C4889C9169EE289F16BBBEBAB53D769D949827C632BD4A17B9E8935B3D6BF142517E79F72CF7E161F5D92488019A742089748C9E480801D76FA120011154B53955A37EE0CAE3039F1F0C49A7BE6438F4BB4E56907EA24C66BE6A5EDD4E3CB515245EDE60FDDC8DED3102F0E53C16A996B0509823F530BA1AEFEFB8DC774A58B1FACB452ECFF01B062A3393C383A9F4D8CDBCD90784EE2DD8D92EFE2C3BE60E4D308097E43DA090E42E7EF1516E0D799A223C351813EB7E783890A66DCE75C0CEDBA460578DF65474F47469BE4FA2E3E10595790C13F8B561B8ED1BB49C8DA6EDFC351849C127A34B60A2B3AD7F83C1752657656DF4855111951F92AA5F933EB40C2DF223D94FE5DFF169C691669F3F6D8C121C9B67E05DE02644120AA34A4B13786DD9DAE8D808F0778A5DA2A11406EB525CEE43D35D445C2F5BC4CAFB2852D8C6A6ACC93B01E0BDB749FEF1C09F3D5234A43FE767B1A9AB89D20FC5F594E4ADF4C9F53570BC8F4C2D04D9A544561A6C99440CD9E427106F1177ED5A76D223B148213D991E09AB0C4E4C6D6B7FC4AB0C0AF9B89C95E7E656D1728425E271F09AE4B16461E327D20CD2C712B2C1C00FB8BE84460459C50BE98044B742208A4B5AECF7D50CA248B29BC3F2C1B330996E7DDE370D8861967642E7DEEFE77D42C6276968C71CD09ACA3CDADED305EF21C0A7024C7658C05A6B45B61AB65CAA5B93F50E975051141AEE0BBF65789A383CBB1C4BD1D2D94D307A86499F50BF625D50BECAE8C223D2DB944325ADADFCCF86DD474872B90EED974B102A9D19C4E9BD280D66319A03D030C0FA8D3120581125559BD04345156494A1B7C0F504DE0EF11A89CBA700E1C47C5DD22B738E6BF3B0A0298865DCAB2EA9021F55AF9E9AA2BB2653B9EB58C85C162D04A6C43D0F0C8340CB39E1F395E1731D6A4D9F7A3AD6882F0104540B79C6DBC989578A955C7A5CF59046E5280C2E15F52CC53FAC6EA4A32EBD31BA7F2250B134C515726011D9C0F994E1FEA8B4010D64A4A29427A1FEA237E9930E35C7C861B20FF0BCA331DD2FB5399ABCFC021DB61D8DF75BCF176099125AF6DB6381189B943B6DB2441BA6D6E3842FD0186AACC52AABFC365783AEA8A23A9EED3B1282F2A9CF3CB47E139F4A83FC1485F4D31DBB570D873768BEDA9644445434A9FD5CB3B97A0B08B0BBD1A4AADCED2EFACEA93DCC662CD4F9CED1C374051B016B10113784CB702E8D85013D8FBB9FF46BAFEE6179A5DC37FA89DDB75BF93ED4B293D6E93D976DD368A340B8FF01FF1D1871FC1A0BB7BA7AC7059480B7DCE38DC664755126BD82BC6811D871E3712CEF4CA62D6D5A61E16CFA3168DA4DD1E5308B8E6329D43321CF4A57115851F5E9115647D44252735AB365837CA044BC47B277B0B11653051ED4D8AF346848FBBAD97C7002BB8138D76C15755E815319ADFBB53A6E7A56E8D189AEC9B29CD6436648F455269DF97674F1E58D44E484C55DC8BE057E7A99C60331C509F59C7B23A59078BD343EA32CE9C719BC4A96C05384A10B3B9308C63BB007DF32A42DDE8B5E91A99F970E0AA894B1D2F1E09C40C7C5B7E81508604ED4263960C05917CBD5648598F1003340C8192047A552F0AFDBE76E094A80B7EF9A8FE3B3A6792DBFD26880949EE9D853BBEAA24C18B7B4CF45196E8EF4FC227AE26EB1A6372FAB58B3D9DC600B33F40250F4D4F11DC85359205B2093C65F198434C4F8042087442C8C7CF612D8CD00D8B8E0141934F4AD5332E036951CE49CEEE6BF03FE0310AE75C5C2F3365B5D1CA5313A93166C3803612B885AF72AA11B92CD95AE79AAA41B9E4DABC44D2368A5CF23090783179ADBBF366878C6C9C4DCD81617563BAD7BC72C6214478B36B47175E8CE863F2710933DC65CFDF30875E1659D967636CEBA7C65A07B0A4F740114B2B0DC275108D83B440ECC64B348C746523D74654B8ED7B0CF12C705B2B3BF0A5813485111BC17F85A521F70941270AA3285E1263C636212BF8016FB2610310E3DE25254731606B5E17A0B50D58E7AE88DEE69F9C64742BD4EDA8B73121BB4C81DC4A30438CC80A7FD53F61C3134E077563AD4D88F39361FBBC182FCB38CA9CBE002E32FC05E353323D2367AF6A6C0B9362BD297C5919C8B3B7014AA305B5377070A9D12E7D838C8CC896D93D5A79C9760D9FC5E3E197A1441204BC002FB5EC70E0D6CCC825EF3BC8EC75423F2340625DDA0AF63F7D0E2318FFA80F53F4254582F058244277D0CB8D9B3A3828B16F30EA1307F027FAC474C01751687E9187E93A9AABF34438CBCCFD517769CE045475A6EADCEE20B195A5DA6DF1656B5B9C8EE0000000000000000000000000000000000000000060C10171D2330D61C6FBD64113FCED8C5205026EBAC0D9F3522182617CB00B6E70C8DA62ECC1BBC8E1FDAF17CC61DD01CE85A9072CC1D9D34FDADBA5B93E0AAB4C9C4C9E26D3F7F145FCB23673B6E0B373C0FD1A58F52486B72624EF91A539519EE5305772A006E49521744912BCF3CDBAD424F00428AA96CCC21D000EFB09DA5CE652E361A6FB649A060835E3B9DC9CBEC660C7531620115EC905DCA6EE2A1CE36554C0FC1D6DD6863B8F3843508ED5C214B6923E7F5C0304E9B0D5E5E433BD029116A33A60CB980737AC950577D0594BFE0AD2225CB8D3FA42F192B0EC05A49391632A32FA931C0FBD83A7B6EA24301AD0906E7911F9D900D19AE1247ABABB1C0E9B9BD165185D9D7413EA068FE8824CCE5B3AD51FE8E2BB2C4022C61B002C1DF4852E4910F38613787CA12371038B6364D920E07B4B417401253451DDC25624B5D038B2DFE29B8494EC960F87803CAA256A95C9868AF819747E4BF26FAABA6DDBAED93A7815C795AD5EB7FB4592DF678AC1375388CC7ED3A6230CBE80ABBB113C80B70C789CF0C66B943E67CE814F12D3D83F3B90A4320FEB7FB81DC93B05D7FE2D36584399214D3D7C71AEF322A5D04B5470703B3660BF86B0B17BA9FF23E45F7BEFEC3758786D2111C81BA4D81B83FEEA35A0668E5EB3694963BB4DB3ACCE4FCBA6F3F6FED9627580DD2D2DC103EF7E52BB9745BD42A7FBDB459B5C8AAEBA67686EB899E3177FAF0897C61B008ACE3304C41B4C79E2EF9C865E9958D8716BDDB69154FB33187D927B5296C1589FB1AE3D553F116FF6CAE56910CE6717C446B9947AB2A981A8F5999C1C6E517EB3FE584F5D10059910E22F40FBDDB709C9F686F51ABF7D7206A8BAB4A346B51523C362D749238D7EF6671A89CD86A8540604F134D760267E91EB92FC0FC275CAB69C776EF81DBAD35027E5307F1D34EBF5D6E4DF424D709666A1E649C044C4930098B2E6E3782A93976B55073C504563C7E052B6816C07F0FD54A759D2BC189FAC3FF54549FC4DE192EFB58A9E301863A77380967735910F63D35EF5FDBD8751DE4BC6BF2E3095628DC7F67C1F5571D17AA342593B2C7F953C3F0F22DA1862122031BBEAF0D00A029C043304E3E2609C4FED8A7404FA10E2EC846A70EB0E37C5BE61E698CF2296EC1FBE6FED75F6FE3113C23B29AFB5A6D7E3A9E46E2D89D8C06450CEA11492C1A97F7D6BE8FF6C014930043022B264FD32593952BC606F779598631E48EED86EC2A013D8EB866F311A400 + +count = 27 +seed = C33EE43A9CBB4347BFAF71147B7FBDD88D212462CB06FBE695A35402C503CD15732B7D0E8BF829A555B9167BCFA2F2BF +mlen = 924 +msg = C83441B16B39BD7993766E7260D07751AF2F19A41E70689B0EEED0C118D9EF109866AAEF31B2D2962A25A3D1CA999214CDF0EB54598382EEAD64435B7122D275EA8879BD47B41EB64EA908867FD78ECFBE8E992A2636AA7477DE5058179565D3A2CEB8ACE5C0302018043C411D89975A64927B48CB622A13F1ED85CC1113897A68488161AFA1E636EC786A0AA37B928BA88A50164A9EC372523AA9EC8885AA9C95B29F7CA1BBF0652BAC195BA94E976D336B69A9F5346B4C7C81457F802DC9757C7A2435A617317340F764C1A2AE131A716318F00AF0EFA89D3B57D8F31E155598B3944D950D6A1D6485B509358EFB3745B95EDC30DCFF02574F54DFB2D31B259D132D18897DF868115679F06D41102CD4EED4EA290F711148B99B647B8555A4C0DCA1D2D0871C59AB1382A2D6417E6236D71E2BFA1A75CDA54F93E6C087D611878AC7670A04FD7D8CB0993F456E3BC1C3B5898076E22D2D9E0EEBC7D7BB8D142BD2B5F6FA42B40BF676FB69C532D7520A4A105EF0C1337F53D6E9B4BA17F1E76AF4CFDF08F794752D2BF71E8777E2A209F8891B1A53D7BF2A5786B00B9A0CD0FCE79408F26BEFA2535BE188A68201B1514074CD70660971F86E8D3E92790AE7AC591AA7A996149BCDF060C615209FFAB82E6000F41B2A5606FDAF4CD08CAB0C2F1103B2436B1FD7DEC477C6233FBCA3B07A0CA01BF3476BFE5334E32AAA2ED35D5747D673E7BB622E1AA7901C77F28A3AB2197C8B8253A1D28C969EEE73D17AD71C7919E7F217BA2BADBD1EBF986CFE981024FC347028C1109CD4204C7D53535A9B677E39A43193E054D0FD68104D88934DC7BA6CB3E942AEC744B935CDCFEEF4221784F96798E650FFB0FEBF2715D75339D0CB6C2E57C1E9D10F13E6786B7F041AB307B8CFA51A2F10B622995230FBA54B70D94AE278EC224D9D0950BA97BEBA7EEB0E2FBC4093E548D9EC09CA1A08E5F0483024D7C1927FF8DC270900D42D31B81B13A29839BD746CBB3591BC33817741A31DEA308F549A74F3A4E5478844183B8D7363AC1F4D4A5E907D9ED98AFD08FB8BAA84C324563495387A4F12C239FB63F0810447131311B2D2CA302C7DA2DA57C94C3B5E844F537886FB766EC0E977254DBCA8FC84AD77430428F0692E55D8E2CAB294B857AB51A2CE4A725433DF28D9CABA86C770743AD987BBA58C0565BD18590931E283292889294B607A5F19D9E905AA3940836E2A74A2E94FF3062E85A5C6C978B5EB2B254BBCDE128280E6CF02C11A0C2066F349E3C6C083965D5B8A9C000E15FF36C5BF3A6D42 +pk = 1B36CA8231CB612F0FE9A60248CB6E8049BA7F61C74BC80F3C0C3A5A8E058FA24F242D04869B44EF764975EDA2B661B385EC8E4E4BBBA48655D50910B94B7150A2D3C58FF3BDBA21B27A51BB705A7E84DAB85BAF4A2D0594CAFBFB873952C87AB4A47845F90FE77B79583D2A5114A72382CCEDF0FDF1FCEB33262E9A27099745888254C85CB6AD1ECCCFAE32E0BED89FA351AEE43025872D83E07C4B6C8A2BE434E5B862479675F57D80593D1B87687F600E0C62C859B41EBC11D930B8447DD8AB1450DA8E22C854B7C43580C36363DFB2C288D14686B98BB9A3A6784BEC9F6D1EDECC7DC680D727A8B29C732B11C4B1D4B06C476D0E0AA8BA11E12D4B1D7E6E2F329EE331D702E192C411D50C74D859AF4E8AA5338D52E666DE44E38C2EDB45A94B0B345B17DD8AC2A8EDABA441920D1AB40AAB2827F6DBD79826405FEC8D677D494862A66DC3D08EF1DCCE6F0CF64999D04A7BE5A9AE275781173185E23FDA396CF849312F1E0523DD0D590CDB40F9279A0BA132EE752C3369DADC3354D554A3F07E4570B4913A412D14D4F01F3D47309F9B3709E14F087B6F5B5A916B3C592DE084F84DD703F1501F2333C6D0A9598087C6AC8F63E7AF29E12EBF5297081DD15FC50BA96FBFCA66C01E5912BC8951271159C784AF403FF57A8C0BF55DBD8F563A96691F34B2B359AB5ECEA577CCBBBBBFC9B3144EFBCDDC132C47DA9C3F2B1A32AC3AEE39EFA68491F17C75D3E9C9BD096D7389C138C4D8DEE5C4D2074B301CA9A5B6891CAE8592F2718C34E4A38A44D1657F50E41DA917889E379C9130F8C8AB01A4C1FD7B054B90B9EDACCE08F428A4B569F0E7FBA425E270A2AABD1EFFADEB60555AB611773DA9AFA4DD791E2B77537FBF011BF4A0D98F7E300CB20FA001EA56EDD67BF64FB975EDDA29A41B4ACE5F505B6A6FB6AFFF7C339586B9AAE5450148285B1B61191BDD090E0A1F1BC2A90F8F21BB0163FBCDAB991103DCDC1F8BE972A8DB7A944B30638A8126EC4219EF33DF3D80492208478C6BECDF0C310F2383656EAF6ED3DFED80906B6076930C617F84EB406BDD24A70DE313D719C71732BCBE72F2DC0D9B1340FFB7C2301B4C59D2AAF38FD4A1B015B372A50CCA66D503F957E2A77ACEEA35CA1619028A1737693B1EF0826B9592A3B6F08648DB8164FC4DC75C286EB03A18B1EC369DF47F1015081880032FC1C550C4C3DD059A6B1562EFBE5D5DF67EC685461A81074980E718E63AA96EAB0C9B7C833FD0F7716660A3765285CEFE10ECF2C9D9E9F28B5546B3EF9F83BB6991186124623A113C5C14CCD64DAFF954F033CF218AD0EDE09FDA00AAD4578587253A5D9B2377EBBBA3BF70BE0481D39AD65E01343125C438551548AA913A623D9A1C506954F96840F2AB05F2E19EB3C3CE5DE90CBE4F4C866CD353E33CBB65D794D95C3C84EAAF42DBC93162496E195E593AAE5641B0212825E838DCF2921A79A9CBEFD4C0A71E3CA54A57D7E22C645364C6BF02DDB75DB0D3192B0CD037C0D83B9D090547C5C5AFBB6BBC721B806018C8BF1D4A604A711E079EF7598406B85838A710AC15B9436ADC9926ECA98293580F253536D2C74F8015FDACE42826684E04F7C8B00FFBD85CCF9896484110E2668B1B998C0BB62ECE3CA3A5E8362FA3E87304362F1C7B6C636861614BFBA0A05B0FB539F71ED125BD1401940495617CAE5BBD1AEDCC229DCBF33F04FE5FFB4B80D8A743AFE7E9F3CF1C1409414750A31FCDC0D33408883F1F2342ECA45CC5308358223782115EFE2E118DF6B8FE93F441D674000738CDD9F9211ECA0607A520B5B79274653789DC4A8BC0BD9141961387F8B5BB024E779593787DF26DFE52E2853961DD81E4BC521EDFA2395467FBCA97E3A994D1FF752073C990DE2B60927C1891423C0DBBBA50AF3F539ED6635946FBEBFB4D0442D9E0269F32B8D3A6D0EABC8743439E59212F1E7399DE7CEC8DF1B1369851F6CA32B220C7602C05E93E6C164E3C87BC9F78A2CC9907BA50BA13E2ED57190D6F4EFEBE7DB5C4572D3A6AF665C7853ECD82929ACEF0ADD274D5565CB620C8CA207397292D55FF636C6D70816B1EC02E1A82A3A4247F693BE349DBB15CCB07B1CBA6C03B88E433E7B271964D814B52289A14D4211481DDC6B445E35B6E7DB7720B9C6AC460606B9915C03D1818FC0ADC3B2DE07ACF353D6CD643E68F9D0009FF935163F6D1699CA4861F19397EEB0C5CC845252BCF5FCED6FA8A14D3D72C121A7E5D551A959CC73A362744C72689F6E2B2CB5AE2E5C5C70FCCE387F2E2502B14AB27A2784108364D342001A5ACCA0DDE59B1CA71F4216064C99352F749AD04DC9F473025E65ADF847D7F9CE4E73B7C4275494B6B6631B336BEEEE1025DC54E34E58C5166A8768EDEDE1705FD40CCF872EB0C759DF4CDE126AFBEDFFE8536C03F7C0CEDDA3DB89D5F6AF07C02C5F786A7BEB02119CF0035EFC30253058EEC22D6D44F94DFD65EC2CCD84B203526C5ED502CD86371A35169709808660F6FF9D1A057F582250360D2A29C72F4C8368477F527766AF33C39524D185F6B27B8641D799A1FE961560C6F9B1E92A9D761501C39A6BEBA1CD37C892B6FC61C865AAF762A96519BD0F8E1593E551A4C51641CF8F66B8CCFA4D79C6650C4B9DF5669CB95F62D2AF91C2867B856708AEA8C9F93346558633A04D268B03F4E2E7FD410530C9BF1A64D86008814F68B07078545CFAB597F32E8E694E5245169FE52BAA264A14078C36054D15836 +sk = 1B36CA8231CB612F0FE9A60248CB6E8049BA7F61C74BC80F3C0C3A5A8E058FA224DC999589ED424EB2EF2016F764FCA9FE43977B9408019E1801DAC3493669085265758F340014DF149BCD2541DCA3A63E48A4B43B275B30B31822166A391987221C77D032E7EBA1AC9BC0164F1A53CF6CD01C7BC75CFE5C92593D257CE2BD1567668420508704668046222242508343767521304415225840382452428338035366514048171500000385156135864287034348126220338524207723315315180220645647823476208583474234044516117070256717814542406147632010644381064245732110368816338210173480713425110164837178717554833157147088703253521408282604458276306553577763543215381572313586753406761838014116143816322330136035071100231243640484312751742184445555164315518246140038154132032018557754360748066484684787834247862765035160680274746860151122703337020227135266751012065413233676643852646827067265318784774612705511086863388136146766688684077637707755607807760513781848022436085543348170833467860231855808223487748277276167650073477355850482338112448827574813345876657524863458162422775422718813182385043541116406436263110435786324321363566420050683421032883083834808878084378676653254120140050108134632844362820075540051736861768722204277888425123203361517333083787373854750071068458105301463130576630570427242062382638542381304457724105555235727186333240481800314656203882316462437771354080172782885361534123034081714020016500871088383325350640643721103640173364701145234054314482778472262017828433286402232378045247603352812216168506827326245815785502616247807545475153254343154866656035860106724320260565655532553871134685782433585542268733361847170862318384503086481788700414633863306622341250030061640657762452743182107482257865774583583611673614531476774752066207234565156137730713830458425638152531825615762432237687480100532505853132188732263847025064207603160602502818175282283648241368620501842616772503757006177076785083570367838721371278555481864065707185870446300520706573146381273157227447743218408014334845174371135452457768156522637214833351075744277857835817041388482274822177753118147370263888813786005615215106505757526423448844681220780444051286433253514763114535084701643820744655322528272748557056406647142175235004233211107588010486804335111755604248326837735532445453050322116302684737876673837421883023370404685565768313120112027206323031804480460302406762778643858487238834013562308032710102005816700201558214858414634231302284208607633058144016427848324611843541054214182855065278134510028540513212804351430172483548268308421083545508002133781252058208746462482648050880033727737567435322067733445015255468474738656164671423546568416451648357280084035611508267145561541470807456404503237755712731867504424023285863731823162546828122826347381516186387428885020738027470576057144682025546437378042237758317450340132841076711833087160711703571422143407483115483535105473638668045726160003580678686255223852048706124752842382227853570661514502082224254840310638087022813106080626271360334615550175645215074214574254273647274512631337720043825171266565150068328203808007071576588172752073777851530348360703620547773186837218165586564843625162755356337076333795DDD8BBA94E02BBF0D3240FC808A1916488B5214A97F67D2CB84EE15DE65E5E2E5C1D55441A0C8AF55E9C35B2A1EFB480B735968178C8962EDF42E323333EA5F8DB6766D346BF419557DEB736BE5D63F215A306BC2CDEB2189B32C6872B24449D7EB657BED1A333F499422C7153493DC729EDC53491FD27257AC262FEF156E74EF0C0A63C17166B807193777BDE4834AEB00E63EF1549A3847871B760DBC61C9E2DB9320020D4DC76CEB48DD0C8FFDF826BCE76611D7CDA3D1ECA9D92D14BC4C354E480A0F524E376BA102A9891AE54649DB23E3A522FBD3FFFC8FD66672C4C38755E16E663F15BB18FCAFF4F788695D16419B4CAC7C26E5226F842F563CCABC688AD919E2914FC58BEFA2934C019A55DAB6184D74BA10394EE9D6D0BF8CB1142D2950EEA4B775B326820CDAB565028060902138C0BADC2B0F4FE27C490476C5792C1B9FA01022DA905B1FBE4B0031F07A44B00A049A36C0EACAD07244A6DCCB14472A1E48377CCB32AA53F65D111D16E4C563A12E5CB2133C61A876C6C8499B3C83C54214F27AAA03029E0E12D1C9FA9A9AE4709BE138A3412B6FE9593482BCBCD7EF7DE153BD810C3499CB90FD6021B22087804FEC145C83385E823783326A822906F868DBBA65296AB04BB2DA26CB12076D7EA555B0D27B36AE7CE2D9514C600B4543A414C695442FB24101F920A2D4794897B886B7607DC50D3FA5550A863EC3CD69814B3B55422E9B6AB3B712F469DCA5F99580C042E44C77A776E4BB1A60A5EBF87DD0CEB07F0E6B845A9A5FC1CEBB78F6C9F4D21E81C57AC00C6A9EFFD7DE994D6EC57945F7DD1D28E5CDCDD7D9734AB50A244B313F9140076EFF7B89CCEFAB9880B66A684353246FF8E09BBFAA82C54264AFDFB1F7F453A5FA415889B0C6B407DB404B6BE459F0E2B8541AEA5F38A34A36C19F284C29A547B544F4019F757DB92A91196C5556DF37E4341E51DBE0A0C2AFEF97FAB386D4A340AEAFA2F0205DC3F24D80EE3C942563CDA678B5577B88FBDE6F137A8D7A8C6B03475E70536B1DB0BF8924C1943C776C71514CA33F6E8A4923018EF0FB989FE1A3517F68E77070B61A98D34A2DBA8D3B77934A970E672547C565A9210F4E9F45114918A6B5A6DD035C61E03031D8A46318D5AAF11BAD8C1A3394EC4A23A01B6F55F818D8E5DA0A1E67A9D41B74A624A46A1C43300BBB5ADE04E0A2D54490D220923FFD9B27D8B109BD7A907C8FB24426AF30EC2EFF9A26A5F47F634B76D8953A767040D1675BCF7B274E0CD62782BAD634E10F22425DFAB69B31CB4D79897016C961792E20C7911958F274753CCAFA4280844D2C10E44F326E7BDA0E2B835EA162B8C0FD998DCA1BFE9485FD9F136A4F5F7AF5CB10AC25032B77B888F3A3E7DE37E6911710B798A8513018B3AE39F2927D580EDF45EB1278236DEDE30A7704D996378246A1C42DA35A94D12951F02729B74153969500DEEA04035A352E26C4338419ED2641459719FC0DC1134B3FDC7B5A8D950BB0D4DC893B38F009479647AC21507D13AD3862C4140012360E5F2BBC4D4F112D60C05EC69EB5905455075BE32164390E834554C42E4AC217788CFA6B974ABDA0BC155D83CF94A81FAFD913FFCD21CAB840CAB0871223DB580390FD0583EBECD8E1D8F8962C24D09AAFD5259E95BF5BBCB110C4EE601F193A401E8AA9A4CD43CE008F2812E93042D1CA2F3D043269D8706CF7D45E5C9BCEE24FA3FBBC1B2BD13D06C13A3A5A0A8A44D9602F30B0DEC570087FEA60A773DC045144FC19513FE40F3EB79ACDF202E4A9B5824A2204824F31064DCAC45B63FEC6D608A2E9A5663BA9257390642260703D802A67DED7447CF680D4683F3B3189E2C66C2C53691962439F15DDD44F43548322904B93A781EB2648018CBC11F1CCA465BCA46B8ED4433AC6E4A97167829D7DDA7989B45F48CBD2CDFEF6C82EE7DC51DE235104382CE5DE5E2FB02F0EA73EA1B55C078C73F9A4126DA9868F2FEE929CD36B4BBFFF532129FEE1507CC44F1607F10BF31C327B5162BBEEBF26CAFE069728F2DD1F4B3048F9347E92D642D605238997D9EFE7C50A6998AD4E9AE1C2646B50B16F49E9F4AD9AA912260F1CB09A65CAB9362E84CF1CD176DA04E1E8463E5125775E9C02CD5D0AA6212A0ECFBE626115330A158973C2C7A10BE22914BF6CA3D96ADA5D2C354DDD7002AF5D26D763F789FA92629D530191968276DB3D1EDB75B27E6FA6E48846880BB27239E712953D88130BF8FD3F14A234FFF7523E1E91627FD23D0114796F56F9A054A900AE75A74978FCA0E53251DA5A3FC2130A04B735EAAF97DC9B19D3E4B81ED4EB5B52E2A3509FDE92ADFCA067797238E4A87DE3680C3303F304F7A6A1FD24B79914BCA088F0D31B708D5F004146155785BEC211307243F3D709D137D07D67EBDE95A55285B6787F58855A3346EDED3587CB479E28489DC789DDA6BCBA548F3FBB7E12F3684767F0706E574695A249675614477F3F80A903C14B7C7AA2E55149A01657BA9D16EF5EB6B369B9EF07E9AFF5ED6DFAC8CE2492F64B8C6E797193848A574036BB943F0CBA8A0396535DE787134E599D46BA53935A4095A187F3DDFC0FB0FF4E8CBFFC3DC230D34EE356FAB44CA7B6F6232A3F48A13D5D512CBA3693AA8AB0307A7C37D593857929201542D85A702A7A21F7317084D2E7BC39B5C01D1497589B7DFF39C0D479D79A12A1FFAC23FF47DFEF0265D1FA53BFF869D8A92CCFED1ECF8D80C54C9E607EFCD30AF6257795A33102292A7E6A649B5E57D3F56F3BE8F352B5C1A1E688EBBFD77D5DEE38C5EBF19682E728D962284768A93335C9C8D1E9290C490BD633A3299F30405DD9A6F439F2CB24E66DD1D2477A159F7971F49D19B154477604167EE0D451145482D315B7F1A17BF5709FA39E827726D0F18D79031AECAE82526C94F997290270EFAE46719F18FB078586D8CDB88B7CDE966EEF3EFC96120BC785A5A0B520740171CCF0C9F02A1D2A3F3A382A3B90B337E19B07E6AF6B005DD28CD59249916083D545AD372654C15C18B3B2C3A887F4E9B763E17EAA3161D0BC6DD4E0C4EA228DF0BD31DF3CEB9A0EEEDF5EB5CE6D038D4336A52BF695806EAF00824394DB65A60480855F3BDD15B2E63CFFB3DAC5D7BD58318EE157FA8F5A9E86345AA569C918196ACAC36DD05AD159D871B3201E31B67E16EB24C8960C01667D72274F39C1F28ACC2F44DD6D884723EFDDF993CC5AE735BAAAED7CBFFF384CB7320DB3DF387FB38E9373AD5DADBBD7A79DB0017B919258849F27C60C34329B146727322B748E9538331BFBF0F6CA82027A845A9ABE62754281B3E13749DCABD9014C48CB9347DCC1699259478BF01E340CCC3DEA3EEDF14ACD80509700A9A637CBAD14EBC7C7CC52E5370A1E2C8C6BB8F06A7C7A6F186ABE5E2AE5EECA0E0A7C07C0291E5834E3712D9D78A83872468A9254CDD6C76B67701B759818831620136BE90674244D956B2875C414089EBDFB3210396094DCE81D31919E3A9DCEAAB6FAB +smlen = 4233 +sm = A1E655E7EA757A00BC27C1E2C296A80238A3D643AF70FCDEF5D0EEDAA20CD6F16031D2D6BE2BE57419346BDD378DCD168562EE336E0C75EFC903D4FCB04FA2BCCF9938329685384BC267F199FB60D6FF425A1F6E64A672AD5F14F0B17823126C7A9DF7F6F36BA662CFB63E449C121B2B9F005FA6FA4928CF33C111325B528A8653E7CE79585BB6251C44FC9B659A253F7CF212B6E866353446C8C67538427C5865D616DE0EAA06C80B9F846FE972974EA8BC8C28BA17F3CAFF967C69D61947516D3907D133B823BAC23911CC87D77D6C575F6AEB01E0D02E33B7074123C27EB16CF87404726FCC1CD9F363B2828477026DDC26710EF4FFB0637A196DE8C10F6220E193061F34BC83FDA020C37F120548FADAAEFDBB4D41C99371A81C46E4464031BF3819D31D9711F94B6272BF355513B3C8683944220C7D25CE5A671DD87503F071CC157C6299B1F9835A4404CDB55854BECDFA6AC1C2D82EC1906DD98E6F13AB2FE2FA139B39B4BBCE59F517DF46B8324D8D81E82F74F07AD3BF76C153835915A6B17B52CDAE4C97D16538E022AB91BC35386B09B7A6865DE2667CE142A49B08B4C29C7811B688D80AA6EC31D1B73690B35F60E28D9D5B39A9B6273F669C4911577420BBA3FBDE258B7E2293B393D11D246734893BD6C1EAA535CE7813947EF9DD4B0CFC905AE52A77C754A2A3B20C9C6828BD07E23C401603EACBCC53583BBF9A06BEBCBD492BD9DEF00763BC2A2DB62848EF68E40C58288E6F5A926C3F79D88E2DF96F5FC1F6023C056177C61662D0559DE592B20DB1AEB7B2A43543A8E8F33079A3DBF8FD9AEA347FBED3A5BCEFF338E705D2FB2FE553204A529C5B3E2ACA2FB97DC7EB0B35E93C3951FA1CB68E85E053F4911B9A0F9BED6816E1330453F49ADD9B19498935809637FF9A3315340BA840FDF86338ED9725960646B50F56F80706F827950B4FFD2F4EDB9EF8A78DF4D36D0AEE8BB1B03CE7EBA2EFBE5CBEC925B0F2DEAE09E4FB77B62BF74F7EF45615AAF3D176FA795220A36F9DB149CADA6BCCB70B027191CD71A791FCFC5E6D20226DDD28E0DE2F7CE4124A313730B42DBFAA5B770CEDB3E0FB47844E46601D4AE676C98843093306A9267B6488A5B529D9F16963EB9A6C4E6A62D171F3EBB0017C6E8E5BA8CE425D8255C597098FBCC231B3AAA7EA06E8D27FBF878D4C2919D365632BED799E4746AF9B535AC95117DA9A0DCB5272BB2EC9421405817C19820D7FDD74E0257F1EDC33F974DAC0D07B8817A2A3048D6841D63F192EAC180DD27BA1B6F54F38D5C54C53730A7E22DE84721F703214F82D608E43E8E3FE51A218E41171BB0DEF40E4D5505B016ECB861CC420A270F6FEFAA198F58BD97B4AB3ECB8A74BA8C088EC21B791580F0153DD626796E26F846E401D67FDDF2FF3A0C660F24A2C5A98CD6865C1C211929C76ECC14BF8144C170405E830FCD7230BB5E71552B2512080E986BD088A7C4F9916DBFBC71FF91F8BE92A404B9B5ABEEDE9CEA495552FE62BCE43108E026D16246031AFDB3FD8861434FA7C729A61731426A4CEEE44F58B67C991468629A4ED7952B5B3000424C0F815A31A180FBFA78E62607CDEF1227E8D487DD4359FBD517B61023ADE3BE7049E27CC8201283B98F916D34D36D75C424B11CF3D46E9BBABE16638D225BD1161B9C45F7DA9AE9ACBC387547F8C2705E643BAD9136A3A50DE78B0016F6004A1CEAF01D16F38249881113045865B3510F10E701BB773485BF34FF1514BE949A44FFBA369953E18DFD1FDBEB12EC012E9E78879DB677A5FA1519316C33B86AB0012B5D2D5AB90D0D8E6B2CEA83CAA1612983EA46418D381FEE5068E96E778C96EABE12A3620833010AE95DEDB909DEFB9CD5983A95109B502A5D1DAF9636E017BE9312F9EF49D593A16770DB1409AC46A4D31598C0CB748C0D48F33BBB279D344FFBCF89DBF119067DA14E690E232B5FA1AD338CB40B25D512CCD7BCC69E82E06AACD0E9374499C7FBDD84B669AAE9F8158A7E10E48FEF34DD51E634CE113CE5AE7988CAB035E94836AC00DA6468EDCAE5BFEB5A968F082265478C1DBDA6F3F934A36CAC20281982A07BFC1125880481921D1C2124DC44AB5E9EAD9B258F743B660E8AF1C6A8B93A0F360A6EC0A47A77F26D2B66596503542EA9CC1E812C429D7904848CBF670173560923971EA80F5EE1FE037E81A380287964C661583623F949E796EB445B89E81CA1EBCE49A5F006E143217A80EC8EA1B93CACF9662E9D637438E8D4BD666A74C93F6198668430553D5556EE2B733D5E23E13C46BEB276682AFC99708A46EB4C40147AC8CE59BF9ADF4495462F8FA3676CEF4B220F0608A0D63F933FB88ACA2DE76939E752A23CA71F1EB60C611326C94EC3B875355644D1411B31E3B62B3F951381A22D94E1997ADFEBC58FFA55B4A13EB08BF8F4B339D2B98962893600088D731095B9DBA0799E06E702AA6AD32E121E3EAC7F71CC274B992990164D2A5A5C058B094878CE058AFA3811F9B21C3D941E6BAC5B89F4B2B80F00B592AED6795E4B3C384FF9801D15338DF20BCEC7010ACC0A9EABDBF4861AED335A2D495E86F26B2A88DEE4CC3CA3401DD6132038D5710AB29C08F1383E8965F4919D67BE607F5BA804F9ADAAA9E5C73530E07500F769B43F0502761E6D912BE6808C98A0D878A7D3300A83B227BD71FC334EED737C64E185893778A6DA5E1E31743E16A430D6B558E139ACD3AA9CC0F637BB8A157B9DE37C6DB84F99D1A30A7A7883319364539BA5BA18CF0CB4D5910ADDCC49DE9C70BE86BC773E9937023D44D5E87398620994D7BC97A3C9E2F914C209C29D8222243CDAD33B4DA1102F901B419A80AE1072FF81DD6E5CE7FB418C2A7C3165335576F5101294A25B3CD9B95792BF6B7E57876EF060B51661BACC58FE4D6A62C01C8E635909852ECEDFDC7A153A4854DEA3A08ECBB98D62000F68CAC358211F7D76C0B73058500F0F0997FDDA17AD7DE5323F86978C10C5C4318E221C11A5DE27D530B7CADACF6F710EAE75C4BD3A4F19AACAB7036393A6E766EE352C7E7E26D8D2C5217480B5853D1161D1DE9BE83C51EE63BE1395EC55C623F21821D244BE6B7F671E9B270058034E43263E09D9675EE892BDF1D755D8D9CC96EA27574F5DB7877124A0269E5E3C8F5CB407C8C5716C095DD9F6882B12EB1FB12BAE56C327F8CFDC1FC68CBE2370A9A4608C7DC59969A27C48408E6406BA07DC9956AB18E5650333B6B543CA8BD5DEC40F17DDCE2AE0158866645A2910EE22639914CD7B055C51CAB7FDE8C6FD18D02424A8069A8ACDB2AA44CED1D2FA6F621BE3CF85D3C58076EC53599F744AEC22270B79BC5C8E0B9B62EF1E3F216AA01F14A7EF0B795D24F4F448B150BC97935A8D11C0FCA7780243C59FE02D40173B948008F49E67452B94D7324CB640259149CB8061B2F22070318B68EA6BBB2DB28E5EBD062B92A388F31101A60B32A6D824A5F63A55151C9B3147070FCD5C61735D36E24296F02A3414716AC1E8CC4B57F483B2EA1473801C6D917B4285AE02DC3C1E5B4858E7FF148559033F7E74EF4EB8D1213440468B9BCC627341B9670ADE90A11B37B0CE386059D22515F207B9E2EB8200425327D09E067F40DBF4C330DD07BD4DFC720EF5D39A10AA64723D224789128239D985CFD9A117189EB7337A71918240D3812A6746AAC459C89322D7816A1C027E18E7DBF2AA84138ADF200B0EE5B30F7686931BB060F3FD0B8856DA63B6CFEB337F08D624951C61BFE9AE5D0D339A3EE838B16876A160D2B195C577EE29FCC431245E6274BD883912B37E47ECA6C4DBB9768D4D75A7566E33A0C7C2FEC25A3118337E7E101FB7A095FAF61E4E9E30887ABA0E64E171DB5C375D7122987D11D6C1EE9C722CACDB72D1967F7771E25C5ADF032CB3BDF7708F4E7CF8C7FF361147952EAA6894EA7E17E2987588DB2FA8F68A0B9709EB6BA173D57FBEE6574AFD7D0FA139B865843036D2D6DE8E0E32BAA50E04F97AA65CE48C05632C3E3E348184F409499E7C2A3267F8F0674ECA5DF29D90074BBC8BA8B4711728339A29042895AF0B1FAA0AF202D91E0E173EFAD5E7746CD2D2675571919B49085D57256144E00AA4D978F0A49192A412EF0109828E3843161613DC75650FF64DABB967A9546195A3B72C3D3C83C8E95AE66851708238E23D9DA0E4D78F8E14C1F986C3DF3A6495247AD62A231D0BBA9136826DFCBC5DB4DDA05C9DF878466B4DE6BA009CEB497716B15C3F7E3665C09332FA22D4BAB480B310464B4FBA3C48F9260CAFEBDB56FE2C39B06AA0F7F11F58EADFA75D4DBD8C17A52170232F76CA7E6CD435D40ADE7124EFCC79F8E4D010A8BC7404A3A81D7C2A015DCEC9D5AA262D8DFEAC276B968A509002A86F6A247D68E24CF07208011439210E0CE8DA6FC0E585F47F0F5E76C67C3A584EC55A6D585A5AE51C09F9B50786BDA54061CFA9E8FFEEB10F1F944F13ECCC08B5C6ED463A8C7103E90D5D5D124C001F270F86F0AF7088CD430196CBD0001B2B968DAB75AACDE184A770DF857637F13A9219129C0AD1378A9A4E497E6C0A3C03761C953DC35A589B010202E498CDDDFF7262D4D6C7AC0C4F5213D447CB6D4003F4A87D23E5BE2E6081532424B59EA00000000000000000000000000000000000810161B1F26C83441B16B39BD7993766E7260D07751AF2F19A41E70689B0EEED0C118D9EF109866AAEF31B2D2962A25A3D1CA999214CDF0EB54598382EEAD64435B7122D275EA8879BD47B41EB64EA908867FD78ECFBE8E992A2636AA7477DE5058179565D3A2CEB8ACE5C0302018043C411D89975A64927B48CB622A13F1ED85CC1113897A68488161AFA1E636EC786A0AA37B928BA88A50164A9EC372523AA9EC8885AA9C95B29F7CA1BBF0652BAC195BA94E976D336B69A9F5346B4C7C81457F802DC9757C7A2435A617317340F764C1A2AE131A716318F00AF0EFA89D3B57D8F31E155598B3944D950D6A1D6485B509358EFB3745B95EDC30DCFF02574F54DFB2D31B259D132D18897DF868115679F06D41102CD4EED4EA290F711148B99B647B8555A4C0DCA1D2D0871C59AB1382A2D6417E6236D71E2BFA1A75CDA54F93E6C087D611878AC7670A04FD7D8CB0993F456E3BC1C3B5898076E22D2D9E0EEBC7D7BB8D142BD2B5F6FA42B40BF676FB69C532D7520A4A105EF0C1337F53D6E9B4BA17F1E76AF4CFDF08F794752D2BF71E8777E2A209F8891B1A53D7BF2A5786B00B9A0CD0FCE79408F26BEFA2535BE188A68201B1514074CD70660971F86E8D3E92790AE7AC591AA7A996149BCDF060C615209FFAB82E6000F41B2A5606FDAF4CD08CAB0C2F1103B2436B1FD7DEC477C6233FBCA3B07A0CA01BF3476BFE5334E32AAA2ED35D5747D673E7BB622E1AA7901C77F28A3AB2197C8B8253A1D28C969EEE73D17AD71C7919E7F217BA2BADBD1EBF986CFE981024FC347028C1109CD4204C7D53535A9B677E39A43193E054D0FD68104D88934DC7BA6CB3E942AEC744B935CDCFEEF4221784F96798E650FFB0FEBF2715D75339D0CB6C2E57C1E9D10F13E6786B7F041AB307B8CFA51A2F10B622995230FBA54B70D94AE278EC224D9D0950BA97BEBA7EEB0E2FBC4093E548D9EC09CA1A08E5F0483024D7C1927FF8DC270900D42D31B81B13A29839BD746CBB3591BC33817741A31DEA308F549A74F3A4E5478844183B8D7363AC1F4D4A5E907D9ED98AFD08FB8BAA84C324563495387A4F12C239FB63F0810447131311B2D2CA302C7DA2DA57C94C3B5E844F537886FB766EC0E977254DBCA8FC84AD77430428F0692E55D8E2CAB294B857AB51A2CE4A725433DF28D9CABA86C770743AD987BBA58C0565BD18590931E283292889294B607A5F19D9E905AA3940836E2A74A2E94FF3062E85A5C6C978B5EB2B254BBCDE128280E6CF02C11A0C2066F349E3C6C083965D5B8A9C000E15FF36C5BF3A6D42 + +count = 28 +seed = 19CB4BE2332F7FF0C078BC001FAB3C5FD8569A76EBCE373D1ED4FC8EB5D744C6464E2B5EECB9EE836CD5D87BEDA78BA7 +mlen = 957 +msg = 86D27C1FCDB8164F8909073F590D0A280E5EF193B0C42863BA518BC8A51E625658DBE2184C3353FAEB674C991EED3F1B0FE3BBE50A21EC70E9F57B97C38D6E436D3DD577D7056B07A401FF0EBBBEFAF8212B993A39281190E309ED0C50B269E4852DEA85432A5941269FDF63766B21D25D8816DE5E87FFA051009D232D6B258C5F43F45F2D48BE09B2CCD8FC963FAD81FB368502057AFA7C865D62D932F652802A299295B29411439DCF832E8367A749B4D7ADF7E8ABDE3EBFB844A9B1D32F77B2BF96B5D29FC15DAE83EA80A990AEF6590776CE1CB81587ADA80B9A7B45ACA3BBC54DBE67DF090104FA196701280B97607A333A9B56A728710CC1CBB7569B79FF034572495181A92D2380A7EE5E9CD1B0F758C2BFBCC4E11464F1CC7D91F117319C30CCBF4C11E60B5DEC724225B8D77B71AA58F5FBD498A3F49115687D58393BE648805BA1737BB921A08D738243920C3834F8782A8256B7DD22CCD5F4ECE86B8A0860BFF21C5C8F0BE987F2D510ED4DF9CF94BF698680B7CFA22A575A3D1B5B431734B59A4B31913019C1F42DCB76A9FF32BFBC6E16D2FADE26E3C17BAE49CC415E4B370D1FB43FF652BE62D18B0AFFDF286765F4F30FC8D6F2C4A58CD17B3BDFA013BB2DAA075BE5F522EF9BFC2E1506CC1C4D381B3342EDC19C955A5FE48A712AF5ACE66A028D03FC859711C9D33231E48D41E58A2C2AD81DA77529AD5E6B73E1AC96F0C8E53F153FAEA7903F917492A1D2B1203174A08551FF0F9F91E32BD0F31D606C80A505D5EB55265542DB3653C2621E7EB3FD677F49534F261205F834EEF1645AF419EF6BE5CFC16D54C7EEEA12D2EB9458831F77FA558E4D5C7FE446DDAAC3E1D502C941C95F572AD545ECC7CAD21F0DD50845CBDEDF589505FD34CD8C00D57243C3AA3615D84C39B0A72C28F40AC72DA25EBC6987DF5A7E390399463786E75D524FFB6C961BBC9301264BFE3C699101D18ADA4A72D193971D54089E6FFFA684CD3D77570CE0BB9179A156D3E2DCF266358499BFC158AC9A6913F622CA861C968EBBA0A59A12674BFE39389A2125A02563B082259483E80C89A3763C0A9C3DB485AEBF22C844539EDAA28A3FBC0053EEC475679B741D9AFC16B5FA109399FDD1FC3574DF8A1292B8D7401AAC1BE452D38F97D531813369EE4C50F36736B95AE9C3E4F91AE85E2D664337DAA40F75CCED2F4A4D210BB4EE25A56DC217DD176DB5ACA43C002AFD63ED8712D89E266674D9736FE4A9F202A81D177970411DCCD289B25798272D2647CE6451906A4F7D46E87A46CF6CD048B6BDB62488A24F48D1EBD61FFA474321B929E0A7B6F9D0F6D777ACC14815F343E1 +pk = FB9AB3C9AE742149675958FD0899D48D845B290291BB507C5FD42FB9E523146B36D725D5FB90C14A74978A1EFB22ADD509E887418B6D93906147D8EDC78C5576C89DA36B8E6BDD229FD4B53A3E0F594A4FACDB8FCDDEA8995CC5A18D059428A495E8FF77F6DD50F047CB589E8F55F4EA5DE5B6F6A8DD99F12BC1797164B695B381F2431E48633B5A74B0E808692A2561B31C713F0031DB58142AA941F5F17E83AC862CA8D540518D77A72C6593829AD28B67262001ADA785414747D5CCF32A504DB3A46C775ACD20213AFD566920C0F032B92B0C9C15C8E25F396BF1B53D40E4029CA94221EB87A88F62CEB9458715D4621979D28DEA6A4975C5A218CC9FB5AD0A94CCEC34A5DC842AADB8F0420763D2E982862C48B4A436D4AA1DCEE50221CDF74E0A06BDEFEE3AC1D04E3AF9927C1257BE7F532C661E5587C46403CCC29BDB7D3D029CFB2A87AD7A679E2C0FB1E3354F5DFD13392F59AF363DB32168582F4E050FEDD279B5B2DE3E54C584930F0C07C24CE5C55ACF1979527EF66F67FB17893776E13D64971190110F1369C7A36FCFC589C90A41C45ED74BACE210F5EAB4839A8D3DFADE2FCFDD0BB423597C610AED2E79A335DA66B68D336CD80B7991AEBE5809811B8BAAD569950F4D80F3531328326B2C04948A5F2D3A5296DA5A787AA9E096905952A27655819F4CC00799198F5A4895FC9ADD2859C4352F81B11200916E755F639416D144431A79751E0076A46E519DA1050D366C3237D8A1CA7FEC524A6E6A1712E0AB5FA4E47011460AD5E046123A6C7476C5D74C92346DD932FAA0DD2C65324EAEE5B26F001F753D4BA41DBCEAF6A42C60EA6C43D5411682FB8013C50BF5A71FFD1C1467169C0B850047F59256137FEF4B236D53CFA162B64ADE033AF48BB0ACF2D43FCC37D4A86F7A4D4C533F6C46270531B37E2B37D6ED392554B9DFF819CF3BEE3C7372473F1F6D33FECA129657528D0FB6947A750C20B9883AAC5B2B639FEBAB94AA9A6CFF1D2B1DF045013A08FBA2B024C4FA81D12FF6C514DA77D64482E3E12F854D84AF46F61C7062459DF79285E79E4BEB358F79C4569DB716CB665D44C0A4B40E9339CABDA8297A290C840E98F4745C59264C94E367257E7BE2B76EAA2178D3821778B08C01BF1C1144ACFB093E54ABE40C51CE97DFDA05C43A06E467A3FC9B86A96AB5A29D60009C0468535606D87150DCCD3209D649A3254B6B73121C16AC4BF415A13A98FD20DB7C3B6D11388742F67E3970AD0049DF83D3BDB590747CDDAD6AD16BA8785A04DDD5F022ABCF4D5BA02435C7BE3229434D809586FDBF4D8EBBD513A4017AE5932A123457B2C57B49AEC05AE627188D73B9FEF57E5356ED778A69749C5568FCDB8FC52D073969FED3DFCD37F899A1464C31D1915C51AEDF5D0641EBF646060956C66DCAE8A99FE5E5B458703237620B2B89128FBB5E0A106B4C9690088DF7D32E00747690F6EAD3B2F923C2D0D6268268DEEE9FD0E732853C8BB31BE1429BF0828CCDCFF87875BF8BADA00B9B381F58B0998251B6FB4351BC791CCB96C03CECEDA40AABCFDC8427280961F2508FF474DF4FE55A3C14F0B6D7FD4CF71787DFBCF4D43D82AC8D851D62E071E86F3C753C87A4D950D20F41FE9AC66FA7EA5916426418FE103A5790C1064ED55DB192BA9C0FD4A1E0C170FAFA51A1B82AF472B86B85C951A1F1C1934E9B923FEF058B2B1DF06A6BB6660A38FBAFF14C322827EDA3E6D26266E38A45F4FD759EE79C26B01475807990D1A1E596A7752F9F36243C21F50E9C995FA57AE51508E21DA316ED50F0D191FD341006C66983C2A96EE5605BDAC59605F7C3C88FA54A2EFEAFD9E06CF9D5F57A4C710D39C571DE1E5181C1BA77C4C72CBAD049AEED3AC8C0DF491F918828E769BC93383B9CB4403A6A98017782AB8E01F2B6B69A315D9B59CF0D9C9AE35A5B029C3B9664BDFF6E885E21C4D579C97BB3758224D3B6FA6E3B34809330608A3551AB783A264F9EAEA794193EC0F4EF554ABBCE352A265F9A0D96D572DAC18BA5EE2E177B87C3FE2BD8EEEB9377B662E02FCC32B95427CC6A5E1BBE586C0ADB1253830A4F951677BEB6AF4E1EADA86074F30200342361539863335BE51D25BDE2EB61C809F52927DD7E362F301A0C40725E2BA77EC5D6734D423003AE1A4C6049A0FCD3445185CA1AA19EE6103131808DA53CC85CD6F303E8F6A3CDA8D16965A807BF93AA83825E3465DC88C776B31D18558102641609944F1C4AEA04D7754137D27524690CCD95101445ABF241C954FAADDFAB0A97705E785CF725B432154A65E84131BB280404F8EE659F609A084A761E26870ABACFCD3E3039A85E531F8383E543B1009CB2CA12050DCFD7B3720AAB9C669858AB6B78F036D62F91D8DD7226999D183BDC4501839A4F4FBCFE38AF895E03FBBFD3F96D129F21CF1C0A5E026A690AC1AD601461C890FB05326CC08A0786C119079E8930FBF4A7FA94062A9258485267BD7982A90DE890BC6E96EE9CC770F01E25314AC29876E15A1273AEE83F01D9CD3DE7D052384C70A46E5F9BD6E9C2C4F575D18564F93D931D63835ABD7B463ECF21EDA810E40B42FC9765683DB9CFAF8DBA34CB547ED11B8B76E577981649209BB7BA917C888F776A78BE076528A6C745EA231E5A4D7018EA30810D2BC64D86C5C549C20975D7466C8C2BDD5A2C4BCC3927120BF319DB5949C7EBE4258F636537E2A9CD74BF0CB4F1009CD4BE4522B9ADA8828BB00B149EFE65F6 +sk = FB9AB3C9AE742149675958FD0899D48D845B290291BB507C5FD42FB9E523146BEBD23C67A1AE83B16A6831D8F6766CDC75EDC12C3D78C5CDC53FDDADE6827B39A938D422051E604AB749528CBA7F408BEF08309D9C9F442CF58F08570712687CA4A25AB98D12DBE50297B17459989C21FD7239B6FDEFBC2E165186C5EE103AC672825440401320861470407502128331527444128573124587070250265670624884430202725700583313637667230714765500576337085825454276887830208103388478638711186882611264165401678601720562016801045078841668355582653618630201031770363024710626854884182051357580811826134787381553214285312485567267006341468458018818231083585065001640631143721658623326410424623207047484264813851844402120180411210408132814801014162612885444685788361755163851342484230307246254430238206376103515785530157740101255608067535821762611258337043447758058346741031337186882420358501036846702762460878424478086363837452888741130543458861655454374078148885312502176250016410465246554373245868040656877034870671264470620381725244671880618755575101237455836238820514238506171534220346637513642532726221747377580373578114768082716217313644378606512354263508070265167652584876237612755507308847831561415162278432700100182704564786880184416376486354381483641277556700054522023438323868543553216618261250526758241748530741344522562833316520724384481234246624732008754881015406847832137265255585174377121707415421400633737573163861655473212116738515881538464134810125004203214152800358327720045412853637840772760432043172534880840673717322688316808514765853437368008628081028163355552637142207302344732368355841100643682688181776431677712337477465132430811184023151630131582682428368430815425460533603135480885610575303006615764748045328200407467232310203500814070417415218627506114803214687311136810378370174335447826687775182417626547141704436373048002713078580223104246618522371835240001858674836212006632317733741677668100131212740016504655761701504386803724652802342150067773265624861370576002430538507348370277648624187873608268268633174483570464543066084754287377084332731347337414360047711600045230752035678363056576723781147868758414648883373540433167133272222080262060814677022862413833438251045882236680143520750455860630436330702511274004266825556807318315288602184718015124554181063636104277577836431422400133502220283413804268261653318248262566541346163003762338527825013085246661616636056248356105221618708332204765864328341035070627414528686526055810043584613110816425350320505417435434566753355041840537275717463177684216521653307838757686460721734603238542861671228158668158231040084534305338157036574005137841765887547028320246617228862357514841533316684670305148153416424752258756130770004755164147145001608730647835644518342611741741576428478313112128265311570186873253375388007055768134537680742851166356425175565673114325826364674721625467575616638585273578677043122672333320444375788853583638808444375413154835637472657821637527438141004773341678605611451712000340238802360604583381772154221450623155213482833350274360720010678833358148006380564807216012015352034861365064321060628546335726238554687126814833572718268027082114875571365385E30D35D6247FC084A88081BAD38202155C56F89B0832FF122011A865AD14010756178678827D22980C64F2B4F1B97667DE08B6B86A2FA60BF445BD63439B3E98F78F190C1A889F15E8F90AB54D32644204855068D880EAB693A0E9E1A31B62A7DF2F013E62207AC47168294B0567E8A02CAE4A901F5AFD3B230992B2BE39AD2B9AA88A43447F9F2234F0EAE511B9E6CE7B9B998C3E6CD895A13321D1461B2A2415F9D869583CCD2B3C0DE5B9EFC7C0D82620B5F1E3CFF14DC1FBE4DE103F78F7CA04DB65826D4BD8001622B72473ED7B4BF9A6B2A6383360B30CB927BB195202ABA94CBE2861190608448BF8193B5D928652FAAB5BB2057D7CE1932D112F94CA9492843721F256FC8FB309B0A271A55B028DE460CD82905449260F0B3A8913AC76B6E235CC5D766447D721B56B3AC02D9BA97A05F5AC7C4639B0E65EC2EB9D6EA8EEBF0629E016EFC7C5AECCCBB2FE3517FCB1CB8FD8AE6F903B17C6E8A73066568A5C1272A5C9B94DA8671F11EBF5B3B13A40CA2D2A756FACDFE5373F2992722C52FB239770F9FF019404CA87D2819CCEAB81B985CA558DF8562F132120DC4D6E6E80DFAD05A46038F1536E9ADE7E59F5D221B1C1867EBCAE99BD28AE07EB28A4549BBE99B2E0C2EB657956862066E741F35C0DAD644AEF2BAC7429DACB01724A488D75B98D32976A9DFCD83E5EFA9694F33505C381ADCEB029CCD4037B27DDE686D3E60A7D52C75664C9A92649C072D7E326FFF5246079F0CBDCD1F7C15EE5517C55DB9CBA415BEE047B670C157793257CF989DCC3A5061374120B0B5E0DC1066AF7D6DFAAD7EEE99BDB12F2D3A587CDEC6B6A20FD37C41A88BD2EBCBDFE2E68131B8CBCF54E2452A9B7DD8F8B6B1D2452AE373286DAE042F10937E4FD5877D205C8A969E25F432F7EF67C5076882C2BB0ED9D24A1657935B8585EC95C7EF9C87CD322BF2ACB08A3324153818B1FB4B31E3C78EB33BE711094714BA5522F736EEDBA697467C0150BE6456191E8FD8712AC8D8430C1AFE87CED52C8FCA755D2DA66E1EB6E0983CB73F327C1835F0DD7C3FADED46CF36C1B1BD683CECB29AA0490E28FAB47B0D9B851673672D6272CC5C9053861A13CA826E7E5BE198EDD3A93D023B96D3DD21885C378F530E967A48916A430F35CD874E98E1CD909171B284802FD44CFC20D73FDF7E91F846F4CA792538DE010D2C323CB0D986843425CC7489BD3E299739F1F7B9D4AAD525CE414E2A0488CAB8A35AB36083FDC2C96A9D5289893C44000AEFFF7F6366D8BB33B85E6FBA0E74AE46EEBBB1910F2108C3DC7A5F4C80C94430D7967F34B2CD7B46834A6EA24FF982303F480FCD4FF12DD15EFD3B00128ECFDAD343E44C36B24208AA9B927D4ECACA9DC114F172E6CEF0BF846555B05968327572090AC6A0CD0548EEDB80054F6E865D291A8F9468BC062CDDD13F9ECED4738E6034B51347CFA588D855FEF5202B349688A1541D65D3F23583504AFA2FD28308DB6A18AF6AA301A93AF94356F4055F67F6A5494E2E3EFB741EB4AE81D19C489E666885D7FC23DDF69F4BEBFF3D370201650287D35A3D8228727AD599B2D7F75075B9CAAD1E4F7B2484839CAE57E796698C83C9366283C0D35CDB1FA0528CBE69BDC325BCAC6F091996628AEF9A4123C6B4DB5B1F585FD42CB47730DD338B42FE928752997BF75FD0245ADC2A8AE5C1AD293C69A5B2BA2C6F69627EA3BF949BDD1073C1117790461941B307346FB8EE659A8586921F7EB22A8864E18AB5311526F2A0B50CA3BE1B36F67A7BB8A5E57EC860B541C815CC4554A3F034E7DBDD74C0C37563AB35838C3EF4D39B7F978FF43CF0C21ABC20BDA81D8388C48E3606607EB60007494F2179002A6B716CF4AF678023ADA4E102ED7622260D28714F3B83ED34CDA35E5319ECBC6BD33A56E1E5109C36E93C9620093DA3681290BB8CDBFD4C0F4CF8349B35A9B8F401B8F2EEACF232EE3A35E5E2BE37764BD5FA8E41C22FAD608BE4A175F17535F46CDF7CC525CB400EEBED49C4CCFA6D4B89D7B58A6FDA36C78EF3A4EFBFCAEFD8FD0BDF9F03F1B535A8C8163DC25A767825391661A57E363607E1CB495CACF0BA19D278C03137F677870682C9547E5295ED9527AA8803056D3E55D8D8812DBED21D998F664ECD1D2239F1C8C9328F78A57E95CA97993CE069B3FB78907AFF7023984788BA7F97C3910646C37163A1D2861DD83C005D4E36189A167E203CAEDBB511B6F3D4350FF66746A31B7FF913EC5FD71F1A78F7EC16737A6397280BCC6911AA85F25EF147953471A0E298B8C953ABA6D5B5A185FCEFC54856F9D101008020815ADE7EC9B0E4CA63851A006D164F324D67C6CE5EDE15510EBA906F621CE4CB16C4520DC6BF7F072964F9639EA7DCD74FDE6752B54409DA5BAFBB9851212C0FE8B38E41822F3F7C91FE2E04A0CE66B0A03F62C5B34CF58B1CD066A04693BA831981BE88668C7F8E74F6C9FAAD3EC325B02E58EACE7352B7A03AEF8512A7F2418AB7230338E96D1C2A42CF9189CEB1AFF53A6E5FDE1B6E4D72222F6BDC7FA7E97F645AB2FA8D7F877530297C5718AD6FC4DB79B1C5C4ECD33139E4A02FBE536185204697D8C20312DDC6E8B1085178786E79C17BDAA4F59679FDE2B329474920479996DCACE0338F36F9355C99B892A4192FEF533F87E15307E51419C3CF221E75E5E298660BC802C8CDEE0C5E6FD838B44B65BB24BBCE3892EC199161A6252CBD2B3B0B4A052827AE037BF763728ABA2EFB74963DC5D9B1049440F3AE053DB5F3A559CAD061A50EBCEEB2B7ED4B29675289FA831B96B240B3393AE7E1AA7F46C6C9C47A83F2C841B9DF6CC8DAF03AD5C3074D85C7DDFE57327DCC3B8B66945BC9C87DD275CFB75853AFE352774BC725580E57D5C72DF835CE41C04096697094E3FD6782F1280EDBFA318B23019A2FF42E7E2C224217FDFBA2801774982489BF0E9A7A2FAA5C6A706F2A86CABC530BD5C0C98F2EA419187DE9BCAD336FD57CAC24A7DA177CF1092D01DD7C1112A33173BCE3ACF298DBF61596B0516F0039E1CC11A66273D98A3EC1E49CF84E44D4E0DDE63F16630845D4A20E3E471F851788DC9D2B2199D35DC378808142B3DCCAB51BE1D2F5DA1EF60194310A36C9F2E7D45988173E57F0C20FF6575B49351657C1604B544EB66CEDB208EC6997441E8D7730274B64392D4100F748F72DF8D27DCC081B16D316D5EB79F37B8ECB30D8474596CAE0CD0B1641FFD3727774B61208221FD7B08C3F8F4FB68FEB13A9E3A9A53D47CD6D46ABEE7BA420F05A2013BF8395915ACB9CBB7B18C3FFC8929F662996A7B1D3CBCFDB2735E6A267544920C238C82E8F276293986D9B60A5438C8E5E20D4940D373E7F140E281C3A99524BA55AB79630BBB92DF301BDE558793FE1D9E03639476F9327C58AA6D5A275A59150602D8D1F0B0E68BAA1AEF4414D66BB3E1DA5400C38A5B42937AEA6C889D28CD676CF270B0048FCAC83FB69072C6B6A7208A6353EE0A7202C6A72B5EFE404ABD2C1BF552E4 +smlen = 4266 +sm = 36EF17D3AC5478241C74EE374978011B026A2714778CBAC98F29E12BC13E346D5360C786B928F501D477FB2603E975CA0A4B9EADA4440A75378E4A89F1E0598DAB0522B1391DE42945B69825ADCA1D7E8BC1CA78438BF5EA34A622A39D020E432BE835EF67ED737235221BC8D0C148269886E0B25A9A6C1E514F2E0F5C1FABA405A366F7402A1C94C03CFE3BAEAF2F708A43D47257293E685F2D99FA6E2B5764E9D993316C2C203CBBE9AC4D672BFD3D80791A3115F50E46851A2F252F562C723FCED65EE34D0C47127BA9126A4B2760506058B6A119523F2B7268C78F68B0DEDDF53816DF9BC2BB5F38C84D2E097250C809B70A4C812B136012665AA444526F08970FFFA69490AFCD7B104DB2A69A7A00060AA2FD93575A79E130D7D06E9A744454330A1A919862AB5BDC40BC684C58CF1AAD230D67C3EFF69DCBE3A4A36B2B628F4F9A8450EFE0DC8FE8E614CB29F02AB5F7BB7522DCFB4D20A1F1AE5807B018C020AA8E73A19DBE81EF05EF6DFB09A5A275D7DC39FC4CACB4DE7605540FCC8EC6E63B2B37C2C5A938DD9E3C27EA938F3397FDDDB5F40320B82D31D6073402B91120BB7EA31E6024E9AD80B5CE96A17C0AD0351E76597E1C79177BCDAC78E43B674457F520E279338099CAEE5D1BE95C1BE5ACD93FC7A628D3159F8B692B4764E92A5FDA15FCAA36F6C77CA1596C31C0134DD3D787CEEE3694A54C5224D6BE973ED9A7D451C2CE0BE07642804F2FA9775B7249C4C632D62ED0FD27C2029167A4ECC738681A5058B189A95BD1980711D5507020417A639060BA0A4BEDE858A9A6F6E8B32245AB846CA997D7B9BD07C986A2E225DF91CB03F18212BA891BEE13A215B5B925EE5D0AB66F4011116D4F134C502D48772BFDB2103E3CDB1C7EFE5F04FCAE7BA6C71BACCB9E104176897F79892D4653C1A5E9AC4E855ABF37087795D586CA7BE74A32412F5C6932CEAC198CBAD47C063F15F6C56252DF6EE27925D91FC32600B7B786FA46F55655690BE8E29BF709F5B524E3C4B7971F397CC184B41F77BBFE3EB6E421B53CC1C391B78EE00A0EA3F3A80FEC55A1CEBCFD75333647120D0A55001B147854A027BABE15FC569C64E4732CECDC21AFE18D3B769AC7DF8691A684B2EFEBBCE7E171097E306F5F3FD79D67322A7FF588F337CB51712E49FCBC4A96596CD01163C3522F148F27FCED5609EC88383B9F12ADFD189B773DADB86B946CAD8058AECE5AE7D64CC1AEFC353379FD6CDBA233C230D7B0F04DBB133A70765D27C17C1827D2FA1DAC85B27E09251E25D7A7C97F6157EC98E113DF1D96DD099823A4939ECDAD820F5144EB568EDE73DDB227916393A526B199DCDFB04FCB3ACEEBBDFEC9DDF16CFEE52AA9CCC6FED8509BE05BE9A959966B3AD89CAB05B4825057E98D694B9E116AA5685A7D16550B884BF14C3F640A8C947582499BBA26AC5BD043A1937ADD6D4530F824B3DCEA34BDDFE5EA1B8B602D42DB9CD3094D906C348A81A810AEFFA8F584579B349C79589F8C3C629860DB4DB8160D33474F64CFF92B366F95BFB11046E4F389FD3FB8104514499A37983CF91257D16DEF8919335F163E09424AACBE40B5B5A137B6DD75942BE2E8F26FEC22889530966A99779FB11FAA1AF38A40FEF60CCFAF1BED4C50E9AEC2572F19DAD8190523DF366BF6F948D5D1D2D0DFB6487358D533EC5963C31488884587FAD36199D199F7940B91AECB8CEC8C97F67CA09DE2DABB84D981ADC9BCBF14E39B311FD916816054ED9F1D39260CD9394B940A8DA5A65F6A12BDE549B6F6169B331FFAD18A46330A0A5C6C4141D2453ABAC0FCAA1F185D6A515AA7C1F164DD9E317A750F5A8C3B74BBDE506D6B81DF8B052AF432AEE3575DEEF6DE0E722017DDE660955DF257BD4DBDDC68E354A92AC49F739CF1390841EA2569F3177D10ADD744975F5B881E8958BEAF125001AC4097525BE5E227B7842E46DEDE20B74E7F8E1D3493FD930333CE94C00ED12945D47EE7BF60B6BA47BA68EAD5DCE39322B078822C55D334C7057DFC58BE2DB37FBE70556D3A9F6A3D3293DCCCAC8A93CC3C2DE55E31D9E561D6061C5B16FE14719704BEF1B16888D691AF78420A46D6CCEE8A8DB2BA396DB3429F35E963FE259813CE2F749DE98FB51278F661AFDBFE9671532EEB54B81FCDBFBC4BEDEB193835F3E0FE2578B6915726E7A9A3DBF49A5E5468196FCF466ED641E4A78072880DB06774ECBE54804D1072BC5D10AE8C18AEEFD7425C25D6F81114A45D378CFA729B5B0B975AEB5D8E1B4AAFF343800B9A82EFDDC8FAF4F57FB76E50CD15B0ABFA7C6AEA0F0EF5065C97A25B93906BFFCC78666492BD8F2213CB8AB92B747C20EF5824E52FF657D1CDFB75022DD09130457CAD6066A828658818DF6D986FD3CB5F6E6BE66B07B5EA810424D3B6F4DC1C71A37558A0C7815DD1B53D1001E9C25ADB5FE022444AB5660F72DC94EF166E9BC7601815A51CD54E0FE0B19F39A474748BA3C3A3231A8C79F47679FEA87D3FB92AE585B05355D93B4454E8A05AA771905A0E5B6182589143DFC06B65E90BF0C8BABD5A11BD8D6C86C42D5EF999D8505863F0E1D439A8DDABEFF461558767F17387F0C87426308D252311E0285641996C1CF616CE90F23DC60A35DFE527B21002491C1EE11C20EA29C3A7690AC246E87F86056B74542D6A912B65A7EF6F20B91296EB0B18704213495BA72E7155D2E9988AD1600216A95C809E213F5989BD2D9F3944AEB8FC2C8D9D2C8F40A5B80C334AACB304DB73D53B4F0A28A3E41EAC0F2597830853B92AE7ACEA2B4F976C95777168CBF85797640A9F5994FA135342888F25704E19D3032C1008B76A1A3A26FD3FA1A296A6202200FDA5E4AB963D7B6F865F4AFBC27682B20DC5D75515F1543530577E109EA74B894B01422023580E20F2FE4C7F623F9C7F1FC580F332A4166550980DD8748E977A6534089D666469C5634F66270776169FFE65151DBB8A4CF61CFF1AE603FEAB45D17093F5DF84B6E7755B3B0E28540129AA3B81929F3DC1A380C06E9FD74C5D79B28AEECEFF2B85FFFC46BF529DDD3092CB0062410663C9127BAA606062ED12D34FF66BDBCA0828B08D7C2842941A48503AA076485182807B38200DDA11AE0025F9C2E16799919E8D7B5FB8AA467E29ABEB5C9940C6B05A9F152DDE7349DA1C75A3786978BB0DD1F0E0495E29A3A6CC907CCF513C7160B4833112047E0940CE7F5E739EEBCD94CF83DE0542BCE2DE942B4BF030B840363CA7252DD56DDD32FF384EB878915566EC67A6CB18EBE3CCCC062148A24F0C57D147E6723579035BB26D7D7D62F8D0E2AE37B03DE003968DA34E9E5F273ED73DC8835CCEF9B16FBF18B0BA2992490A1349596667D50FA785F2FF1DA03BD1CAAB7CEEB39667B781A5B7814EA77DAAB5276DD3FBB7779703F3353BCCBF022F3C5C78B81B3A97D1158486ECB619823FA6AF6E41E22B858C3CDF29C497ADDAD421A28D25315D44F503263826BCCC87744BDC08533B909FE33A45D73E762A23A2319A6677FEBFB697FF679F86244ECA90ED92E4D59786887BFA893F973186E736D62EC8C0DB7F8EA6969D9BC110FEA07BBA80A24E2ADAD94652CC53C4DE8E12D69C191CD548DF71DB41E30602F22515979BBAE4D822658C5788A36C4C4F5B4B42FFFC281CC0348AEA7FE146E5F1E66DA8322AFC74C499A02265380D5BB88D64FF4DF36D05308CDAC12404F5DFA4A6D94F574271EABCF91131B99440771BCB023D01D2A8C8C3021A5A196A2BC2BACA73F24E7BEE278889FD974481A1A008AB8112F829E36A0E3D5AD35E1D44C0F1ABB328EBD4539088D4C10BDD26DF78521317650EEE1FB88F586EFABB882BFF0FE07AAEA245A255DAF1275E2ABA9C949A0BC1C4D083777486C077ABC3BE319FFD1AF43FA7EC2FCC99917778FE9C7D3214FAB9230EA86C2947E0C87B675DF165F11BD0A993A4123E3B20DE527BA528AE3E618E7B5BF8B3EC7565BFD2E708C8719C48BF92412738C229C647458B4473DDE0730EAE403C8D91595ED3716646C6FC45AF9B1FE9B2C89CE1435B936B49F3AAFC9E2D57390969778225888F9024024D310A3554A8590BA7410D500401DF7B7DC3B685F0AFA1ECD982DC77C9E5363333274E1CA0F32230E2FEE43DADDE8F25F28AEDA015F04F92BB6C097BFBCA455A4C21085C6D99DF1BA39AE06FFA449328108B0F3E09C60F49B7059900AA1ADA2382F8EA3AB7C679E22B67AADD521F6C74C5E5374482A2E0B0FE8D5EFC45F785DBBAB55788D1ACD036C159E41F64F03FFA5A3AEAB71E9E0487233C8C53A29AFAC58B1E6FFC8028C585CD9373611DFB03E516F81856A60036906E8A04F00754F391497576F6CA727CD52D67B5C36966591E58DB489A74321E15E49DB600A9FE4E79FD9FA3DB625048ACB6A7F82E1981AB8A03028141A92599882FA9AF1D2E2C04AEC83B9EF9E172DB3637A306ACCD78633051438C04C3FB6C857B283ADD11080233B64EF14781860ED8944862099455203985B95A6C6A5C69229330EAEB6CC7A37C9B6C627B2520EE5026EB4C7C334BA67C3666107848585F10D1E3C3636FE63FAF2B22B97E295F3964A5D0EA051E1F93E3E6F81115A0D5E2EC0C182B39546D97A3A6BC06505CC1052F313E79819500000000000000000000000000000000050C121C202786D27C1FCDB8164F8909073F590D0A280E5EF193B0C42863BA518BC8A51E625658DBE2184C3353FAEB674C991EED3F1B0FE3BBE50A21EC70E9F57B97C38D6E436D3DD577D7056B07A401FF0EBBBEFAF8212B993A39281190E309ED0C50B269E4852DEA85432A5941269FDF63766B21D25D8816DE5E87FFA051009D232D6B258C5F43F45F2D48BE09B2CCD8FC963FAD81FB368502057AFA7C865D62D932F652802A299295B29411439DCF832E8367A749B4D7ADF7E8ABDE3EBFB844A9B1D32F77B2BF96B5D29FC15DAE83EA80A990AEF6590776CE1CB81587ADA80B9A7B45ACA3BBC54DBE67DF090104FA196701280B97607A333A9B56A728710CC1CBB7569B79FF034572495181A92D2380A7EE5E9CD1B0F758C2BFBCC4E11464F1CC7D91F117319C30CCBF4C11E60B5DEC724225B8D77B71AA58F5FBD498A3F49115687D58393BE648805BA1737BB921A08D738243920C3834F8782A8256B7DD22CCD5F4ECE86B8A0860BFF21C5C8F0BE987F2D510ED4DF9CF94BF698680B7CFA22A575A3D1B5B431734B59A4B31913019C1F42DCB76A9FF32BFBC6E16D2FADE26E3C17BAE49CC415E4B370D1FB43FF652BE62D18B0AFFDF286765F4F30FC8D6F2C4A58CD17B3BDFA013BB2DAA075BE5F522EF9BFC2E1506CC1C4D381B3342EDC19C955A5FE48A712AF5ACE66A028D03FC859711C9D33231E48D41E58A2C2AD81DA77529AD5E6B73E1AC96F0C8E53F153FAEA7903F917492A1D2B1203174A08551FF0F9F91E32BD0F31D606C80A505D5EB55265542DB3653C2621E7EB3FD677F49534F261205F834EEF1645AF419EF6BE5CFC16D54C7EEEA12D2EB9458831F77FA558E4D5C7FE446DDAAC3E1D502C941C95F572AD545ECC7CAD21F0DD50845CBDEDF589505FD34CD8C00D57243C3AA3615D84C39B0A72C28F40AC72DA25EBC6987DF5A7E390399463786E75D524FFB6C961BBC9301264BFE3C699101D18ADA4A72D193971D54089E6FFFA684CD3D77570CE0BB9179A156D3E2DCF266358499BFC158AC9A6913F622CA861C968EBBA0A59A12674BFE39389A2125A02563B082259483E80C89A3763C0A9C3DB485AEBF22C844539EDAA28A3FBC0053EEC475679B741D9AFC16B5FA109399FDD1FC3574DF8A1292B8D7401AAC1BE452D38F97D531813369EE4C50F36736B95AE9C3E4F91AE85E2D664337DAA40F75CCED2F4A4D210BB4EE25A56DC217DD176DB5ACA43C002AFD63ED8712D89E266674D9736FE4A9F202A81D177970411DCCD289B25798272D2647CE6451906A4F7D46E87A46CF6CD048B6BDB62488A24F48D1EBD61FFA474321B929E0A7B6F9D0F6D777ACC14815F343E1 + +count = 29 +seed = 6BD93FD13C0299B3EC7403638673F3DBC449F3A617B691DDF73C072B62BF028913375D7460BED2CF9FDCA517690CBAC3 +mlen = 990 +msg = 56ED7708F98432FBC623424C2A3634780470A01784BECFF01BEA5BA192D02C33675084263C4315420A009579EF80DD15ECCBB812652421872A9577EF7D07896A727A64141BAE7173426DD5A3925159BFA927FF1039E70F729847B48365B4D3551476206AA049BA5AE8F605847AA03965F058FCFD478961EBEED06530ABE900042321059C297DACFE76CC12D52311B2FF8EE1231C77049E232D9FDB751FB27EB7EB6A373B4B1C06BD0FF46B1B208072C873E6F938E689839079E48C6D18F678769F5F28A903467F2FF2A8B02CB19DF675A8FC7560A7D38A918AB8BE083EC4E0EA148517AB90F38394833304F245BFFC47F9ECA771FB80B9C71CCD05FC3B0D66EB06D24B914B63D9F16AD2F2BC454B591D01ECFC527277AE71E3DC683161A53F129743F3428FB82A89DBD5D42F3EED237CD2F8D76DE2E56A2143AC6B2BA811F745CC72132028EECD4412B76FDD87A2E396ADCE72DC69B8FE053042E798B220974587AF96BA419DA6888B13FFE217C9D01434347F4162FD554B760883E8EB1AEE46C4C26B990C6BA10D2D939F513BF0EECADE8B5DEB8DE2BC8C8894ACA51E65AA696E390C11689F1C2CFBB70BC5F72C1872D99BABE8DE8FE2DBB446A8129AF0AB8D9613F0CBF3CFA6EA3CC409F4A97581D5012707756994B6C8D4FE7F64E0F0B85A85D0A5FE23224DFD7ABEBA8E3FB2E97AD87FA8DD477ADF48F64FAF486D0DF11AE9C3BD3A04ABC962C5B02CDA02D48F0B52D84D4920C116C22455DF291A96E6ADFF91E3CD35CB8B5B4E70E3DA8B87CDC969643A32B1F97131C5E0BAE7F6DFBFAC32218EAA596D444574EE85EF7C9998DC1088E5813D50A4377D29506817E4234F68B32AD68E00ADBF6462F8D4E215F15A19DFDE452F0A65360F7C1F20E11C42EEC55565CCB23CE248BD62E9DBE8A7D6639028A92B422AB444C5688B5D191A4BA8956F358D131E2FF6DFC607ACCC5D31AF9678F1A226530078FF9A73D681DEB697670DDC3E9096AB0FEDAB664473DCFFEDF9BE62A5C7C54FA2EB5059E9A1D38413B1A4FE6D531B799453BC7185ABAF78CABCF65F365B00827CEC5F29C4737047E3B2932A78757E9626A958486D1740ECF1EC17A01AAE6ADEC5104EB934F432207CE31D7096ACB3A0FE2F5DD7890C021892FE7D3F34596CF20B6B12FD55911ACB46D7386F99A9E9EE067A45C6A1FBB463E63D69CB582DA6EBD6330F4F80A1FA72F2ED24CE9BBCD967118CFC7E21F6BFB68A905F532BCF8B8BEFA03295D362B41D25CDCCFC9B41767858F651BC56AB2BB4A8675513C5D6F1C943A20A27DD29F941AD141DEBAAD219E056510BC984063FA0F389090D434157438BB1759690C453A2F55F72C033797A4B0C534EA2EA084B3B6F8966AC56B106FCC11EF08902F2ED +pk = 1C0D14F1C1E76B9BF996BF60622D3C663D073722E85564917387882C2303B452510341A41FBA330ABFC859036C92272BB9B4ECF337880514C9131C7C3EAEF27A96E298BF1B75FF9B130778A4AC5D6DA82A6BC9610E6EE00A89ED6F2FCD62A8853081262756E118E294905B659AEF970A4337C05F6CC5419CE70B6734C835F1DEB99B87A8EEDDE1E13C710DC41F35CD3E933D0EE4F339A25E18792C299F5BEFF1B63884DD47F76E562629BC063BA35E5B69156D2F84BF6238CD7E0F0A21365D09059FE5EBCA166E1BD39D8D3454DED86783554A9E46B919224ED5185E7514AC663B0C82B659587A7B4E3AB3ED3A64449A35ED74B314A9E83FD5FCBA47B0B4D5F082C589E2731E2F6F2B6A95257CD4DCCB3059232B4F8692E7FE0D45E2F88A637869FA0284C57112E193815D6C79CF825C5E66AA6E1E9F848CC4F913F587A2E7D43142E9B87BA6AE854CDCCE4515B715D855CD08274BC0EBDF358010B0FB45C335B992A0FBF38DBE4F0F12A558B4AC4FBE58B2695BD8C620F926AEDA3E36D9E67EAE82E2E026C4D2D0F4D3DF181BB9273DEF2644019583B455D826B0BFE042E7547C1992035F4F2456A7EF2824E7D86210F2083F27E7C153A47422C5F200B66855DC93523D3A0E83EB4272E372A887B2096B88EEFBA1E511F14E40C35C720D0BEBF9338F3755A8A579E41102D8CC9AAFECF59B21FBEF95F99F8473DE6AA8954F6BEF98CE7390193289764E315BE29998BE15C6681332BF671E686F231C6DA8DD91D44D1F1D16DDAF7779EDCA681B22540FB58E5EF5C49C713A9FDDD19C49EB23A466F035126ADBA41DCCEC59FD62463C8F501447CF44BDA619B9ABE8B6AE243F917C778BE080F811AF629C63E56DEC4C9C117EF3E12A830078F3410B769F200CF75C177A502E5C625FC84D481E432737347118A6D62D5D2C7FB958B844AC898C89B70D381CB0883701EF3E8B379E4E463BE54DB7F2BEF6E674C27E3840F00A346F5DD6D2FD7D212EC16E7E3480B145C14088FDD9068B8633D0B46BB6CB6A2B33C66AAB5000CEEF7ED4F63B534346CA05D24290E94368F41B1661D4FAEB34F8C871C914B4A2E99F12BCE3B3FF8AC14805B858D64D1A42363A999AAE974E2DDE6D13817966FF5E35D193BEA5E04A3B81B43802DED32C1281D6FADEFFF96189A74EA17B783D5535FACD078D1EDC83BEFADD7863550EB996C01CA6B4982A4A1DFAB337C93C2C9348412B1FD96C28B9779384D35A4D32FCD308F8FEC213662D106CA966DFE60B07DE65A322E5231C4FD774E126FA40ED43F9BDF3BB2DB8B55D59010B8B852E3A34F72251B45EA160111EB6B59E36E6D19474C75CBE20275FD46BEEF6C55B03AD6EFCB37FB20E8D8CE1A0C98E79DE05F6034F5B00F39102299BCA5D4103B58073B0BF7B9E07C8E3886BDBC3F48744F3C90185B340BA818395634A197DD5BFE43E4BBDCA213D4F1D5FF98EEAC9C68E6E3334087CB0C7BCA71352565256FB94030D7598091F8DEB9726C75EA7BB26676287D144D6F80E56D21FB6E659F8890552E06819FB603A695C5338CFA63984ADC98027A178749188D75589E2D7CE29C89F95959635FA7F152671DEFB9F707A3AAB73CB02784D07030996701A3F80E348D8AA1C684DE540569F2D27C1C3B3A6D5D1653DE923B9F9808E9E963E553C8F9722A2533E46A5ABC24385978F976507D8BC5A2466FB97A6A859D9712A380D6ADCA6DF2C491CCB1D2E2CFC3ACFDE8B4B1E66098E5FC321B5F72D2E3063EB87E70FF8434F8BF885AF638EFB3081330E52C5A9E33CF2ED81C45C09F1E43142CF5329EA88C94D8A9040C96D8022617123B955C8E11D0B5DCA864C6111558F5A1C3B329621F333C7D43F46E9D46C27A75D8AD17677E737761E2918C43B51A5BA3B2E05AFE2BF655BCE14215551BDA9A1E48EA88470DC32F9B7D3C9E0912A8A791FF3CCDA0DC45135CAFC0CE44060FC3646AA080D41CD81DABC1E17F3B73611C3D862A0B63B5BFA2DF791B30F20D7D7B21EA057029FD867ADFFECA8725F3EAD1FDD4129ABF0FAE6DA7418077598B0B6E9E6D81BAAB3A310920E3E5F9980B5C17B7F721C12799D9E76D100761A2B40B4E548777CB3F53B8761CCBF51287BB6DB9B54966498A3641439B658E42533A12DA612E32BC8AE57C394EBE9B0A38F54268462539F7C8679129787BB40E72A71941FAE26960E8838CEA31CA521E754DA0F9B26DAFA0922BBCD72C4C8C8647538188B7B949C655BA005FDF156223073C455B587422307632926BD8FF9F27ACBFD21E4A459C140F6000B9A478063369AD4CC9E087810DF744E0D80BD58F0244523387D72BFD45B87F4D7AF4D3646B3E8A6EA6CD6ED52E9DF8566AA77E086910D7E61BB79B39E6D89B5F17C00DD612D1B2A401D44ED4C526585A7FA7DE0D571A93A73491172640886C4224331AB7439AB73BB6891C6AC0AA6C6C8B237067019265CE068AD478F0FCCB80F8C23A58B603045F4C89FD57AED13DFEC2B13D255062B6000F24B97D2C141541F29252F880894DBE92A04FCBCCBFCAB7351E8234FB92EA1BF1C733C5EEA1FB098C0BE9F6295CEFB56EE59718AB9FC39B79C931BA7D6FD679155211E5D23FE3032880E1EA4BFFDBA99214D15F130ACD07ADC4296BAB1B783B9C9187089A6EB4745151D623B5793F555DDF02E2389EE53433869FB747FF09A74659FCDA2AB41E819634A85931EBFA0B525D8691F9943485EE5DA6DB3DFE180F05F4818E39D801E7601D3F413231F2D0963209B +sk = 1C0D14F1C1E76B9BF996BF60622D3C663D073722E85564917387882C2303B452A34587D4CFBBE6179F952051427F53FE1E71C7B499D87C101BFF75DC72A805DDE9408E6BB7ED3DE58B65871EC1035D398B48828C1ECF05A8EB7D4CAB7279E59C8C758AD0516C89B253FD1897E1546E3FB06552D42FAD902E03EFFA935BB554C568534084304185140518112234088880748410408260210068448313030568821465038882517626074657227605046046074422551814305080111244565556012382280017780737760160665375815778372106316603214565776875365776820605437425567248527180885677078387152743375473188626100352121525444716175046234403206625724608006086465823356871682136572802414725444048524060844552686786652822774832230851511825466586646723807200754078404154740833064358013035511075635387782468552305530234521156805506782558784554516165317185288545683688402368245872246468586551028738123481486057788731575224371213416100454822850836040351712525867272716330202532444527647337103112273736815231744018285252003206378057187087884065321035656034134717600828244715014480488601832225742817162126702378605333357555621268884304785642361236424653608470263435375237348000117105368744827143187284250818013485655165842570666517870570452610604634360184126422624052853884137658450574265853835710240113618136676351064151837342542725218885341751011832610644213214372201427677433286714026025317818238320380102050106255174220665857638508744556433443467071740802318373268010782727666284711465713168057152782258665603666884351568653734541442065570402735616743345806641702555683168344571887660587504631230741017807233335163885860250613016024014452687213362467560556584882366572004585635137752870700768756674886850600281704004358358456674448615665747352053821442652833776654478060112260300131702606283340016535656354403186263266112220358472424016388343757602677331875865701743457820366664574778152561571424512246178810036160440132762687003047274657237467620374183535682516184583022108824761637062036565632378572213685742141754400541457060702635177431885818670647366380685875836837415241170750807532110311184584648256408365113541524012446243775354887402523563257217556137570233880081046100368063200421812144383207873722005445520420645132131112174441110251162768031332381383054700017367080511028566172276602735568671572208730050153336773442574117204412354555176378841817857622340013871538385732376151724126038341581827038033346307472062053848235760733304508651785685176514230885714638562516545211383200260375614445703573704811030006188863461018618852871740761655680171615761084321528453087642723740444250452873878346004825568463707027686767731685412450373250434878771026545368187005754736755847510638676103075308246364404466210456815715756836428112802332223507148656606805818671513226648362318805237874750603874181280376656342086002452748487561436825740277086581803105554787408747550825768618584255012581117210450586243155131707105161777431031382221222460526718524458062643006268376670354156456230175185745388601314102084215812133587535166032702103123107106767062327727515708508175142752515421844156813170634254255320151785202836013784758643451411034055372277320755452522376873833785416037274114E9FB6E4231140E06F5046CFDB90E1E47ACC53F056174EE625C02697720ADA75A4829DEBEAAADE9128C98871FA0CCD08E8F647FD778A312261D9DCFFBA5E420B04D028C081518322FD46487BC26BFD12B22BC5816CA53C657DE6A9C37DAE17ED32098B685B9322105518DD2AB8FF0F133C6D388716B1B6BAC897A379D30FEF19AA893488B2C2B43B9EF99CC5494ED2A26070A3ADA8AAA918D65BD31A3C9853267D27F1C679BFAAC9255BB4BCA4383BF7655686F3A2D6ACBB261F83F836CD3FD1E612662D38AC9F1ED9EF28793D1EF05BAFFD565A9C65F0DC111FB1E6B3CE19139EBB701425BE0824714FE1609456460F3D02252E3A64D54486600283B6F69775165D13F210409191EC8803DAE1E4DC2C8289A656D7A9D9D7271E3B198641B8CBF5CCE6E7889F1D93B9EAE0307D64CE5A1D88D5BAC4EE984E65863961B6E374195CCAFA4CC78057744775032E598BAF27BCE02393C739F0BB971130DFF19F10DB884529EF7615C57BB749C05B72E306DD04337EBE1B34C969BA3D1CB5980596F8A038A94025836F64A8F32AFE856034EF50D062585A8DCEB71F8F4305AB2D098CD5902C96D5768262C446754C01BE942130A92A0B060FA47EF356CA71CB9613BC49A3B97B1CDB6D11C3F91618CDC5135582E27088E5B0C8C2A88DEB3CB52163560C3B9982E142E7FFE902A51D2C3E3E2A52D2DD6FB6A66FB9AAF4994F8EE98F0B0B785C59F52AC7B9ACE70BFB437CDA585FE8DA0BA2260D9AAC60579A5CDF421C7DEDBB72478204FEF422B36DE34D10860C08014EBA5984D43B73EEAF399A431B9534EEB1A51D74BDEA0D2BF9DFCD17D403F8089B0DF2B749AF9D41CC99C0A3FFE11558FAF2CA9939B5D9B5756FB1004BADCE4B45B487D7996971FE7FBF14224FA6283674BAF49AE38D84D5444722E184EE1D0EAD15E0C1EEC5DA0942947D25BA595D741176BDAB542F0E4BD0AF6773CFE204F362FE629EB70307877C16A70845F9CB8032E68D341A48EDB25D8ACA3C069500E63B8D29E0C6A7C37D5A41E59555F855AEA268306FBACE968BCD35E8630341DC42C18B4E9552BB234469EC46F4A5D7BD339B71C41FF1D02088084D5D92D6F6B94A055B17057C3017CF43F4D78A9075E958D24FCC0429001807702BE8041002ABADEDA3335EB068F1CF4FE15751015438A511316DAFD95E83AFC19B3F6799738FBC9CFE7FD0C4E895F6454DDBB0A4D7C0A24E60FCAB8A6AD7C00A0C5F5ED4C8B0F8608D7C25FCC7EA9A0C3A1849D07C684BCBCB26BF7A46462BBF16242919744B894374A6CE7598F514DEF9AB453ABC50B83AAD506894F0361E711392D75A0066A1DC2FE82DCABF533F1C26BA297574151C55A4C27287E43AA18B7B1939F76CD8B5B719A008AA6782416B599BB8D01B3282A88C1A492A2C65B3F920E59163C94271DC9BD766341D77D4DD132A19807B2958F12ED1ACD72A8D2A9F534EB27C9EFE605D4150D41507472BD8EDDED519AD7B99D3EE99A546AC26390A6677BBC7BBA50F271356B1D26E437AF1F0030504A886AF4DA81E311356E7CC210C255AC3A63F15BC55C63098BC9CD57663655CDF71AEE2621E2EB47287C2A3A56EC0DC6962677FD37550A0E85C057A7D3F9A2C300C8419C4B43ACE9042767F785CF4CB3E5E3065991FCB6FC418154C2E16E9556C8092B34CFC636E8DFFB3BFE6373C0918A55CFD5337600B7C471BF87B4DE22630541FB4DAC69F705050082B3936E999ADFE3886E608E1D4CE329727AB089620658426545056E2C5F032E82901A40FE90C2D402BFDBA8E2819CD192E68C5C2A01C8F3FEE5BC3FD7BB7F257AD63F643BBE31E130EC177CDC34231AF2D25D307DEDADCAD1C0BCBAD346701DA62BE89EC121634EF3AAC89DB907B8C6D82D6EF065BB155F334ED6AAF4113457E95060D5D7DEDDBA61BDD2C78954956235C5A4D378EBE0ADF99C4A9CADA7A3E6CC508D1F0C3DD639BC18C04D7867844A90841D47A5D3EEEA79B8192A1FB186863FCA68BB3BFCCBD1EBC5BA80E42F0F150447696CC5C103DAC96E2ED02C5661EC32101670471ACF6FE1B1D76B96C34EA1D06AB0654494F519FD68184CACF4B33BE14C93CEF0677596C6CDD9F7D59F80D355666E7BAE7D57D2C212EC69BA9406444624165B4024F7585CBCEB283E55596CC2A965564933DE50A92CE7BE3E826D55C5819BC938AEF63F63244F4071DDE8C0877B5E2E694897F94FFEF35E7133B5B3A5D6531F6D912DA56BA69E35E78C31DB9594939FA9A2304DBAA254DE96CC0F7F3C2EE1057A7B9D15E2B8A106CB80FBEA2D4F101CEB23D04AD4D6FCF94FF3A37AF1A1BA5F6CFB348D3ADFAE7A8BFB16B22AAA84D3C2774BC3C2ACAC444DB5D14B62DC6EC85F227EC51585A0A5D9CAAA48092ED979C0DC01AD4AB0642A67D2154D18FB37DB5EDCC5DFDD3C544D1E6DB186A596251104E3E42751DCAABB29C8BB3D279D5A4019EFE60A654EF8DAD61025A0A7812391933328CBAE8C1037941DED8A560B970E8CDFA89E482C056FFCD4E7115CF65FBF6C42341B355553EB519FECF88FD1A176CAD6DDFE95AC26C4A2840A44A25EA9D20AA2F96AE68523908E21439EC7E874AC28EF3DD07A76D48726C0907564CB151080B04ECF20572039D1F98F7C645EC956FC404157465E5B62568941E5E45C72C61D4DA1A6D3FA1A8F1B43B93F4275E033F47639A5172837E3EE198AA16BBC993199896863E0FA27142059C4F9EC6BE064777251CD4A9BE0799CEE2A9CEE429AC7E4C47336650F1088FB0BA11E32C02A088F377C6536D51FE36955CE7FD30E33881DC55DAD59286F750B2CF5D27550D63514B5CF1AAE2311EF03CB5FF1295C0053D26D95845F047991D5FA501D6573999D0FB842E87A9157A1D10D381EA45C378496D55910FB72C6ED399F224A81300C8A9E85D2941A9EB1B43A2AC382335EBE739093857B0F79AE8013037DFA1F0128CECBC8AFB2DC284E0484182C970720CA2B85B55ECE64C1E5D60CED7AD0FD84E766652DF352101DC63E954C96ACBA7FE3188BC7F0CE7EB38BFE50A6B9BC7479D44C986B35CBF58D6E418A835B0218DF3D1B125BB3D6C0CF9530599154DD01BC62593A310A5F1EDA87B8150FA33A949BF03A2BE4BD09C3C398261E9662DCDE2D7627FCAE3EA761D439278814250E33E39B45A71F3E98AB9EF49546030F74FE576F75DA3070E720FB8F5722AB5620BEE7AD880DC0A8E4B0E816C123760869ABD4B2FAA87A86502ACA5AA92ED0D257B45163111AAEA9544009C100D6D4ACB6ACAFC14E90691E764D12F9F28EB4CE1B4D6E2A8F81941594394D995DE5D8BA15EE629BF4EC61237FB3F8657B459DAC60B725EBD663443EA68A40590890B6C47A1CD2D83B4AECA57417B9317A901D0AA6B979D8CE7BDB970C9734E168B9E4C9AFCF740FBD6FA66B9F000CFFEA0E47E04BBC2C4DF48EDA25F6F973B712DC95F9DB5A98E23A7C9DD61F90A3CF166024DBEA2DA5D3E9BA082DDA735B3E8FB5652A71BAF2A880D0567ABA3B210CADD65A5B7163A39BEF445C1A +smlen = 4299 +sm = 0BE204A1E964D6A10EF250446E750B5FF9230283A4555EC7D03F734F12A426C031B6EA808AADBF0C27C8D38B5CA97A2A7E599D577ADF0986334208695F78CBBB3BFCA0937FA0D2A860CF8672BF355A64D6DF94EAE74195ACF4BEA0FEE2CF0A86D740910D6A6B31867A41D7A922B195D76A63CA43856C4058A113FA03343E1A252C2878C778DF67D3F3A31ED054DBB611917C9ECAC8FF81A1DF470DE9D04D72C5E07F5AB52BCB2B8ABF92760392D81CA08894E3314468F8E813887E64580C0D5AFFF12803E1D6F03405BC4270F28C02E27B210A8669A8D8CCC8608E3B345E557E724169D816374E77D66906DC4043859C7D29AE395A5418F78F86F6B6AE2DB1202D078C5B9C740BBE64835124EF22211BA13C63C8085C28127862187944BD87DA75271887020293766B8B95BD5DF9105AFD9F90F813C7832825DC7C5BE7E934BF5423F3191FD02717B7D85AD368BD75E83C82EFA2FA878AF12DB851D2EF232B2EB348E4465535F7C7976C40BCA656831E67CC3BC2AC338C34459352EFB54A07F777D60ED2DC6433199A24AE609186F104AB73679251AEBE69E1BD8DBB649F358A66D17C016550E02D2E664103AAA4C64AA83118A0FEF2EF4C96D170F2989A9874E4D667D6198292B04575DC03736E5C6896C65C1CBED4A238579169290E4879847B78727C5FB12390B97CAD26F4C2AE247D9E44287D8492FCE7112007E9339801D21DAEECB940688E03C6904FE501F06E3CCA3E0145D9D526DD3CDFF2E26238AF2D84A750A91CD4AE4A914DFC0C0E456CF6940AACAE6B84F00024165E8F64E92199DFC640994649D345D8515F343C43326F1466AA66FEA104CEBC2041ECEE05612536A226711C9EE349BF33BBAC377767076B76DA4C2BED92895120C6EAB8A0FDA82FEFC605ECF51BCB0D57498A02D914F436A8EAE4AF49128C4722EB6CCCD5EF9320AE66ED8A8D172D193DDB330CA5F29781CCE923C0F87EA33F69B0436045EA8E9D1F470B316E2BE4EAF9DCB7B9A1B6197ECBAC7472481AEBE532055108C9A823478D8F686437C96CC1D35C4AB745C85F44FBF70EAE1C7C7C9D8C8BE77E0ED395F7020D2BC9890ABB8519FDB05485261A257C42095486E1E814F16FE75F9BD3B488BCF16CC5F8F0BD076C2C9C8C8FB27FE5D76FEF5104FD76A4139E81AF7ABBE81679742123975A5A74C13432CF3DEA36C035017D27D2777105087A7E16E50C281108CAC09996EDC1DF23F62169AEB0A6D19388E2734B0671ADA275F6A05FA699869F8AF786E462A937CDEFF92A296E360AC18C696F5BDB9E1E6307BA2A0DA6AC940271BFBA5FEA9657DF739B8D5A900DFE4FB41D51E65E879B87F94A40FB051A4F86BC0926C67698189CDA009FA0B3D80F6D3864658009FB75A0BE1AD5A759FF501C2333F25910DC4A251785515ECA00F8D7492BE863F1F387ECA788B6C2CAC322B5B9CED893E9A7E4A140AD99C31E9E8CE36DE395285F088AA97A5524893A37B1CAACD6B56678449B13E06ED2327B778C9BFA51FE3490E245CA5558D919F33F18BCD1ECB5812008C27C6C0DB399E2DBC06635A53BB5B0A310937CAD8D7234909BFCB2A527F105EF73832DEFC0369B2468393F548F10526D4AFED3E686D88256A643FEBF73020D9622FCDFBF4B26280E39EE556A9EE48131A3B69A34CBF29927E429E633A894ED79E18A7E2C2DBB887E77A636574BBA0885BCEF41C9880A46B3F90A425C1C3ED4A5DE28D9631FC8BB20D35BD1F489CF7A0D9679F9D3D41B9F95F0F68F6580A1B9BEE1DE5EC324A45974A0B56305EA352EE8899A94B2A0DED9D5F2B9E790ECC6835F4AD04517A441279F7FC2165FED10070DE3F0488081CECEA1830F0BA2CB5F9F7656C9142E82143F9D3F18C771B60C2EA9955E39B52017813733B6BD37D09A204CC4352CA866CBD0F560F26101504A694FC4335578F5041913601A8C01431ADA64B71E865AEBCF5C6A2F22B8A27CBB3479DE5971EED14CEFBEE75B50321556AA3A1B61E1477AF07977942C63452D4E4E900938C438ACBE0D490BDF2D22FF68BE584D829C1A07BBBA7459A2748374841D348156F10E6F5D900FF923D41FFC42DD46F89969BB0D7B6262921EE24B0832C38FEA964814CC95D713E296ED1032F30729CF80D0380AD3C3D3B4DED5A374A352A24D76101DCFEC785EADA3DCEF85C1EC0C5B239826F09078D7E67C376989016E116CED2D5B1355D5F49C83899E15FED238B1F67F02F4EC9BBF2D2D167D588FFACB67D27B460EDA0891BE06C44976A1A2C5FD05CBF1AB3163D3555EF692DC1DF33C8E03D592C44299BC5712013EC1F3329910DEC0F7891236EB8FFFE121D53A8BBC9AAF1D475EBEE321DB51E62DD3518B80B6CE3D830A8C1FC01F0FC7CE7A737D250B292206F26C13AB7446AF018D762F77854E98FF54865B5D1660AA0AEF2603E5FB1A6871AFF15FA89AD706E0183D890845FA3C61D2C06A3609898246977F32A8F55D1683E1BAAE9030234EF79D840BF744D074DAA5A49EB68FAA62066517EEE91C39B9B47524DE24BA7C9BFDF612AD4845BA9964313753B4BDBA99F518BE9C4EC36D56D33550C5255814C1D26EC1C3EF8FE83EB0DA6B57EDB14F07D7F63B17BE8A56CFB11726F5A8D0357D257F0C337495A287AD6D835D31423EB0098A39417930C08D143E59E2B00BAFA99ABCB126BEDC0F968FF13EA1F9553D5F3D43AD790322CE13E35436E2734F1809420C70573D7F54B5AC15F32B6FC0CC45DD42C64DF4AA4E5399643E74A8531EE0C8BC1898837003A54DCD3358C05754E8D570B986DBC8153988E35EBB1F348BAAE2124FA283C099DF179734C8E23E4964B4EB4C0B7A9FACCDEB6A6F2E52563A85B1888A82CBC90548A998D2CC56DAD8451E4BF3157EA3725F93AE0B2E72B78EC6B155A374DB3A69ED98F48BBF9E2A877FBC84B31DC4A08A8DED608319590A3B43C1123C95ECBD90951021598AB2387BD2EFC2402DA99E0E1C1F877B560AD0549C783B8DCE403EF1090AADA4F6054CA87B36141614C396E844B0C51BA56DAC60696390D7B5CB9C85BA35E01DE45C22EB98EADAE4CA43E1CA285C049B77C098729A96C913184FD2AB501EBE038D7BECB3D8A7692E8D12CA238A37564754554E210580B82460BE408A9C2091C0B122725DDDB94A6FA27931AB62B6C89446B7C9FCF2955FB3BF7EB0077A4F8727BF2E62B0560D68E06491F476AF97CFD2B40BA046147F6538307ACBA953C1AE8BA17CE08B08293D9D77D8109E424FE34E37F6AC9854E1C699BF9F04438339C67B8476371BB5DF793938E93D61A44305244D30B3B98667C1951B03D9FB568F740F97106C00C12ACD823C70D66692BBCA31062F4B93568ABC7981683ED9A8B0E02CE59D1BE27CE3758585074C32D71FACDC3141DEA0F4336B5D46B294958764E239F2FA42161A1F86B16B94C5A1B9383CB2A26BBE5A8FFA5F8A46DC8791AFF698C859D795EEFD4F445C575C113BB00617A082B78E2BF15C2DA1C3BEF44B6EE4531F23415150C09BF942C584C6DEDCE706F7E6037D68E366031DEE34FB39A35919258014C93BBABAC34635045859A57B4D570ACD41F7555868C1C62FE50D5C992D2713D4EE2AB2BA5B9031B91921ACE4E74028EE836EEE3C6F1EF6E355B0BABCC04245B63E60602D2A3B9A9F0CEE756393BEF3F9828D394D5B392AD903124DFF6E09590844C9E8A9ED77A06FDC57B662DCDF0BB73B1EE7CEBC5CB9E7EB5AAE2BCC33AD04190DBB1592EB9B6DE0AF70A49D3C858188A411C1204F71E20C6517DBDDC1886247867975BE8DB4DC16761D9B40D925CC11EACB21E7E69465B2AF85C4980ABA868E9EC4BCA35D487C1564870350FAB7AC3F00E1E28E5F4A7EE3950D9F266F354AFA23459C807D5E62223BD0D6DEC7688E925BF7F3E18D0A44B7BEFD276339BDD1BCC9E0B34D0E4613DD08F0E1132E842967A2832C17FA69413BD2FDE2C76FFA9FD94BB5300BB9FE3BCA9A2DC2F1A351E8080B4171FF700A9D72F9F2918160E8A48EEEB66F2061ECBE8A020561F7ED818ACE4E5E4C00B0A82EA08FE9BDB3B0CE7D90986425EA85143FABA0F82D932E3BB8FF5770C68060BCF60A8AD696EEB185D1C459B4538BB31A8EC73414D89820E49FE803F0737E96840DC3A7AA45E86D842298DC2F05E20E0FBFCE386922E207087128BF44F3130500AADBB0903CB81F600A289C3C8577991ADBE12E2A25AAB4A6653337C6D8E57EA55FE27A6295884683D71AF3E6B831812DEF90AAE50631E82E479CD024487F230884762326CF3145B057F3A6A6C8DE4474E9FC904E43EDFD85BB0685A403C6C3AE3E5FF1A676B4DD6D27828CBF4DFD8A33499C52E0DB0B17339638A41356A6B0A3A545D2F3446F3874B769CA8285B097F1C00FB57A06AA41243866D605BA3C548DFD72703CEC49DBAB4C51D49E75AA5D60DFE4D7EF824B072EF91C9922A60D767CD8C1937F353B0AA8319BEAA8E461ACDE35FD53ED00ACD6F6E16D487570D3A1713A454053DAED34BB1F105E9EB3F5B9B820D886C8BF20D79A1A283696D1CEAD67FD6B1DC3C7CCD3235FEA16535FC6D924C5F14F423CAC155CF9BF858D4F062D537F404C416C2ADD86091A676E9BB0C9CFEE11798528A5D4FD0A7CAA082F565E64A5CEF8FC4E5F82CADADDE00000000000000000000000000000000000000000090C10131C2356ED7708F98432FBC623424C2A3634780470A01784BECFF01BEA5BA192D02C33675084263C4315420A009579EF80DD15ECCBB812652421872A9577EF7D07896A727A64141BAE7173426DD5A3925159BFA927FF1039E70F729847B48365B4D3551476206AA049BA5AE8F605847AA03965F058FCFD478961EBEED06530ABE900042321059C297DACFE76CC12D52311B2FF8EE1231C77049E232D9FDB751FB27EB7EB6A373B4B1C06BD0FF46B1B208072C873E6F938E689839079E48C6D18F678769F5F28A903467F2FF2A8B02CB19DF675A8FC7560A7D38A918AB8BE083EC4E0EA148517AB90F38394833304F245BFFC47F9ECA771FB80B9C71CCD05FC3B0D66EB06D24B914B63D9F16AD2F2BC454B591D01ECFC527277AE71E3DC683161A53F129743F3428FB82A89DBD5D42F3EED237CD2F8D76DE2E56A2143AC6B2BA811F745CC72132028EECD4412B76FDD87A2E396ADCE72DC69B8FE053042E798B220974587AF96BA419DA6888B13FFE217C9D01434347F4162FD554B760883E8EB1AEE46C4C26B990C6BA10D2D939F513BF0EECADE8B5DEB8DE2BC8C8894ACA51E65AA696E390C11689F1C2CFBB70BC5F72C1872D99BABE8DE8FE2DBB446A8129AF0AB8D9613F0CBF3CFA6EA3CC409F4A97581D5012707756994B6C8D4FE7F64E0F0B85A85D0A5FE23224DFD7ABEBA8E3FB2E97AD87FA8DD477ADF48F64FAF486D0DF11AE9C3BD3A04ABC962C5B02CDA02D48F0B52D84D4920C116C22455DF291A96E6ADFF91E3CD35CB8B5B4E70E3DA8B87CDC969643A32B1F97131C5E0BAE7F6DFBFAC32218EAA596D444574EE85EF7C9998DC1088E5813D50A4377D29506817E4234F68B32AD68E00ADBF6462F8D4E215F15A19DFDE452F0A65360F7C1F20E11C42EEC55565CCB23CE248BD62E9DBE8A7D6639028A92B422AB444C5688B5D191A4BA8956F358D131E2FF6DFC607ACCC5D31AF9678F1A226530078FF9A73D681DEB697670DDC3E9096AB0FEDAB664473DCFFEDF9BE62A5C7C54FA2EB5059E9A1D38413B1A4FE6D531B799453BC7185ABAF78CABCF65F365B00827CEC5F29C4737047E3B2932A78757E9626A958486D1740ECF1EC17A01AAE6ADEC5104EB934F432207CE31D7096ACB3A0FE2F5DD7890C021892FE7D3F34596CF20B6B12FD55911ACB46D7386F99A9E9EE067A45C6A1FBB463E63D69CB582DA6EBD6330F4F80A1FA72F2ED24CE9BBCD967118CFC7E21F6BFB68A905F532BCF8B8BEFA03295D362B41D25CDCCFC9B41767858F651BC56AB2BB4A8675513C5D6F1C943A20A27DD29F941AD141DEBAAD219E056510BC984063FA0F389090D434157438BB1759690C453A2F55F72C033797A4B0C534EA2EA084B3B6F8966AC56B106FCC11EF08902F2ED + +count = 30 +seed = 1787C82DA9F2E6CA9ACF7D6CCA70116A1724902C81EDC1439F332C74807AF2BCCCCDC7AC1788BA798520B2999F39DC3B +mlen = 1023 +msg = E42C006F144B0B4E188FEBC82D63D3D37096DEEC9D3DFC3B421635DDDB73C76F6260FF1C53222A50D30B26E2DE3D16E3AA64C78604E1191BBC0E2553117A441159B2A35FC8889499A2EFBDD2F30B8B4C6CEA38EB5B2575926E6F22AB96DDB4B0C5C6D78C3754A1B6DEBA49FFBCFA7477BE9A0F74EC379D1C9AA59247C091611573AF765AE698D78152187B291717A9F03FE767BCBB12F52311215579352E7CEAA8654B5403F18CE82E0A73BFD5FEC1063B506F44EB1C9C5A03697D03DCB2AE15C5095F292B4BCB130B55C19AB728B3232EF77D1594611573CC6BDAA254F05934A329DC27CFA6CD8C02CB51C3C295C964C40502FE2B1A81A51C866F7C7380BFBE339B39C8F51F73722A05B5D1E9CB6313557B3656863803C9DC99BB1905D7F729B2DB8DA23D88200032F36FFD04DA11FFDF6277ACC69C5407289D00FDC3C56B32D54877F4A8DC70ABD37EC532B8617D9F3C535B8E962FB389E976B4D1AA12DE5C1C2FFACD50ACFFF65201104648E0C04CF7C1F880E8BDA1D68404BA67C4BF64C9D2ACEEF81B35FABCE58645E0F2F61EB4CCFEFDE7239BE408710D349987D849D40B3AD294B9D815A91848F9ED53B69F78D9E955F6D1FD7E38EC291664D54C2BC359FBA241BA6ABCBF5FC2502D93760D9F6B1F7FB766040E98BDC23A6047134A35327FE128AE24B4C7D0CDCF1801947A1821DDD7424892DF50E2DD5C1E2E6C5BFB4467524FB45C7D977604E7E0F1F98EB8C03EEE1D9A5796C8A801F082678940F076BF44D3496730C9A640FEFCE385865899FC33B5DD34D036F2FD5D07FDC0A40FB725E84CE403B46DE712B4B44CA8801A1CCF58233C5DA06719769823B5945849DDABCA56B0B4EF9327C8B5E5A445E6853E5B66B8D590759D6B2DB722C22F8C741CF3C6325A76D93F4FDE5872D5732FB19AAADEB7C18094727ED43B305B87AE2DBAAD67F90FEB86498CF65CC57EA635340F27AE5C5CD60AD3C763223AF877E65A005C488AA4AF9309E1AA02002B01DF8865FD481EA254015796985969997A53B06DF0355A6AB3C8219B652B09E1F86A6CA12D27C4BCB9E8D35E6889198C8FED71AD5642F5F9F7CE1DF270D68AA05467EF9ACD9A51347AF1EE9CA7C4A5D78189042900C6D561F68D410A77E79726DC123B196C78829F02CAE7D0623BFE9E7B0D8BF84033086295992B77ACF027489D51BC7FF006A8D4AB8079D494413A565E7F687AF40DD18B86AA4274EDB8845DF114C0146DE3199CB55F773A87FFB126B3A4D00D38835CFD2D6652C07F572F39D0397FCD62ACF6ED9F3E8951348AE7E52A669FA4E2BFCDA548ABB1989A1D74A27B73103770290E6ECAC87029359354EE4C87A77BCB5CEB10162DD54499905AC8ED442C173CACDE068BC546720D1284015ACB90CA19147694B53899395DC663D6683908F3CBA29AD37F15CD3903C4C7F4BD73 +pk = 5C7CE327B828BC8D4B53A66D21E316F607D9C8E437F3D38AB2875A4D4170EE007203F80EFC732CACE3E55591D3EDBD5DA75C36E2742841A4A7A9A32FCCB5D1C04F4763B4A41BFDCA3B65C27D5F6B5082BB7CC363B6C15B0C7C43D3CB5ED11CB5F5328428A3A9D17C4B42F357F5FC54ADD9C42EDCF02882D1A7FDF91701D50A930AE1D474DB09009DB283A9804D7D0D1F7DE4DA4DAA0B9D1C65690AAD88152ADA3BE513998E37C8EE3CE84D57ABEA5B2704019471BD32743A22250187558E2B0FF3B6C57CF995F88E5EC66EDA3E9DC18065495C9D71403D84684C9F1D8767D1FF1820A4412BA132C7F79915BFCA092627F909453E50BAEE007B416C0CE40C5A4CDB22E53FA8E0337B34FCBB0390534C63137720071473403D76857ABF0AFC396FC711E2D5096695610EF0E49B71C96E3DD5B4B60199E948C88BE3868F6196A3AFDDB08054770CCE52DB09E4221BEF8384EA751FC5045E063BEFCDA7AB81F3AD96DAFB8CB27664BFD0BD352E5EE07D207B31F0974C706F6D3CA980B3A8ADF2448095D7E7FFFC91E64500D1DE85C429338700DD3783BEFBD327ADC4807D38D4E7B752888F0ECE8FF28A8BB90633A9035691708EBB05D2400E607B02F0A228800682D7A351BF96E1CD612F691E65AB5D3E20C42C3584A1E3D6E6F552F46E05CD384EAB7F179BB557DB96792EFA8F3694418F9BDF7C6AC41D6AF5446AF75EE1EF3117E50991E26FBE44D5EB34C6E1D175078C8A70C12A87ADC303E4A6D7EBCB7C94FCE2D22A36A9B380A2EBBCEE2C951CADAAB6E45C851AF8B14AAE6C30E28383D2510BFB024E44DA59E0F6B358A8CE4F022040657D3149DAA0FA32317D3FDFEFEA195B4C5243087A24193C04401A11276494228C00DB009DF7337DADD50E7B42FE1283078E0CE418454AF246A5968C1A710A119F9B3A68C0BC15071130746C17920497C3F79A3AD7AC03B796800065954D6D46F9389BAD817ABAC7A986D74F860EACDA4930DE0E42B2C45F7CCA4C213B474545C1AD6D8CD75D1DC0845DDB7C3A4AA2F8808BF72FD36030B9342291EF06A533924FEDCB70F3EED8BAA3A4F23E46B5E4FE19382EF4CBE900973A674A3C3A14FEF5EDA45F30DCFCD4F9137E38742490CF099472EB7E9E72A04EE2895C495DDC35AF20F09EC8016A75C3E0C2F9C2A456C37CFC635F613B9E5BD9B202AAC0137574FD038AA4F182DEB36A6EAE6B2CD9F710825D4098F4F049650C4775175021AB692885EBAB6A322B9D6FA0CD276B20603764759BB7DFBDC55667A2C9845C9E58561895463B4CDA37BCF507449B479E9183D1B4CBFAF148EACE8A36789EE155599D6896BC287A6CA142AF489A2CBFF1B0D80A6B874260D29AFAC564B19B62D4E366F3113521BE2339A2BA2281C34BDBD4554C5E827229A1DDC5029584D7CC9D4B174884845EC24BD9BBA4FC32620F89A59E5EC9CD8174FEC73DB652E2A67995766670FBB0C2E3E24F6B1FBE506CDEBCAE22EBB0DA2D3578ECEC553D7984DB70DF65C06D716C531F665FC6CF346F00ACAAB34E32A93C44EB8352EF4D0E51DC1B0EC4F40779AB5202DA68484A1B3F0910291CBF60A6D694E1962B7212C0FEC7C7D06068BE33315162FE908E0683380D7E04F7C401DE7C06355880CFFB68AC60109E7FF9E43628DD8F25BC4BD329DB32795809B6DD448118B85D9BF64573BF2DDB0C9555FE364C2785E8D7647459D8FAAC50DE516F1B762D1EDE2A34557844D3C20DE57F180DF39B96705A377CF98954B868A756CB0849C9D63994CBF60739A5726F744E81BAF969862D13ED25CD405CD8205806E45BEB8DC64D8598A769BEC9CFCE25389A8A96B328D6E4F20488DED0D0BCF25526F607EA15EDAA8C1DAEB8EB75F22CE42234897A08D182736688948D4FBE5E2AB72743EF871C9A1D5AFA79CE4A393AEC864E8B0EA119B3D724B726680402AFBF08640594A9C89818B6AB3E0243798AEEF88C44A8423AA7EA79A4044E864AEF8CEB910DD654B6C79D2032DEE2FBDD2A8B635B3C31F173C267D9B0CA66209F764A68F018BE1B68F4BD2A07457590C7DA2CE87FFF0965FD04F22A59F676F89769C524BAAB32488B36EB6C2681D7D97E2881A35C869A98453D5971166FE54B4203FB8D81B4601FA99A4C84DB93F7CDFE6D13E6604E500D4FA905605B2DCEC76D3D0803C7C499EC501F62005454F1CBB00CF012589EBAD9887346AC323869460774B3C1184DE90ED3BE2C9A49FD92E0B40A2B791A2A45433A2B736010EB4D6105D28E989F9F195FBFCE4F08FDA7568A2DC94F19820AF27F50A6E0EA5375C0C874BC475CAD5B1C6DCEF9952C671ED94E04FB880641F1DB1DDE158AA485B0374324D3F2FE3D095766087F15C5AC0F1636D242EA654DFAD4193EA52E9DAA5866C8AA5E13B3E62F3495D103B999C56721CBEF102E044DAE3971DC3CD135841130589980665646A76A7C5DE60986DF9A735DB13A0E33D7AC6EC17584BE50B445E115EEC034E04D2DF8FB3A1A1F3FB6F035AB6707B7BD91E8318D56435460EC44DCCF1ADF1AFDCE3BBBAD42ADDDAB48E2419E0D6DF53F04B24A655B4807BD2D361F3851DAAC65D96E57CF258E1E1DB793A791DAA316EEE685F7D4EC0E71AB8639479D922F2338EC6217218070E72F904EA013E51806909B3F634812E67597624928AE5FED9DD468EC9290BE240491D42BB7FE14F7388A073BA6C095B061FA82AC2501FCAED0C9F71FACB3728218DD58121125ADA40D8F31C424F5A21D27B92AC4AC1CACB8 +sk = 5C7CE327B828BC8D4B53A66D21E316F607D9C8E437F3D38AB2875A4D4170EE007F65ADAC59AFA7B609D5FEF7D7E8B70FF9717B956559C250C296C027377809952E1E86A669B37217E917D8870765FE83B1ACA6F61CF5C210A96F74698F0FDED63FDC1592CAA659BA755FEE805871ADD2E38F796BF662C13F2A5583EF49EFC0E3315375625670408083686856614141423037682058556342154538557655831538352522638010131375167567167321803745508687220241884782605071267612050545443126776367010156583734243545063638644142211236437063100454222561841245144666473564630364155221085371777467126483160154526441510583643224618464812423368768575541352761273237813224088724114154252834634357100142581345176872415037454587282754287668646178387662735663036522288172032256142826041577170343468447318117785175784662830822725181712153507023746501615323416605553575444762057272260727242032737763604251714233858524580238524232056387871558555150301624461185614216660056114050463710382663345710585501634135186146228562854723328566845783620215136646088403307063868445584558555277831452032615000440432122738862724478742205836314358023180222426882242137645118356173237132475164045300682788632245447673885346827011463566806347861362408405332682017103822763541250113612382436634467135202300724152538312832687387745648580464706007241252784033588482300067131085312083747570276002051812410204428412858517850313513482458831871003220602586163541350755010254361347884750485125708575023424027033343275152371715021813348730435252421150517103288274428541038713665243220710766656378527207276060805505883840116080015526580075768656634828226373464223540025770474258828351033504820648453054672427144278130552704753326868068151156546860722782622364388015753528381332321531735735670462134566701381535865265041815681645085665126700151837181256764171116216836766212112812811068505878180232372213081143774645836566113074367838043121857322404738638122220620263646543452350451514458654141182280724065085320087420818862430148360353702633860738856286217188062513767113765518606035660150661371730742708243038400542232834123311485816620182481723512306487688330841474880176453760837414053031222517071527230063210035358457838223550820262007402280820276750660138825402102503210254401336458477765202012183055038647040503015823107376642606168865711663235741868635061605726474338863678774377761625144684823263338516808882288314182132114307434064115384480472113326850817442676110008407526026472630346108816457384876480156557751570568328817577651165875071605484161674441304165502818382283573724478080050135746402452742867663828055510317830485462133486661315612148433844507681064838571602701140065654548665734810344801220822626506052118620241471388160871813222052231814413887241081424087111252516468684866618587246455446764320361078683007532300533222212837750158255842786721274541213204077423068802867304053323573822634383731778851465013352222700736215261832765215137475833086614540013720774673315853843178506453533264575222767287653011851244332002322701654202444824136844800418482057338613754247167206106422141016637864708786610763600746715577818758837243630214375117612224508276752361561436007330371353727540282D4F58603D98B4B4B2E5952D55CEB8E138EC2413B33790FD20E923E87577E9A4D6B3AB1CC1A4C8444F546441C3A01AB25E18CC92BF509A81350E0199EBF6F5796814CEEACE1C357557C0BAA0A928DD47D1B6FA667F793BF35853AF2DD9BC15C59651573F72B8E36B0014AEFF52317756E8B488EB5BDB91D0BE5427A8E049C2FAC62413987E4A437FA3EFC33DF15762F096CAD5F799258C12F39042460988DEA1B56E87DE166A52EB81CCA6CC378EAC40530CE0D35DEAD0E92CE200F8D6A6E454D99286BB716DFE851BDE6B9304D7987DE8286F3DA43E8B49D0D84BEDA3D6E337A76F07B12293944E227CB3075E962F8EAE33DB4D4A62622C88C2A9638FA2D00C1FB414DE85A047F1EA0B62D9C110FECC2B3CE9DE9BDF26F97A0B068C0D8B7505502DA2DE0A3976F9E0ADEC2DCD4E3C84F93392BC4BA4FE42672B1D796173CC6DE60753EFB487BBF12C7DDA256CB8930E1A5A07FF772E8B8063C7A81150E246EEE132228BD6C4D015BBFB36A87950853C94066E0F7802942BCAC123DDF90A320899FB7109F4DB0080CA33DA796FC1F310933B05B9CB8344F1001DB4CF6C47E22698C3A005169C7A41CD9AF427155CED8F7C5646B8E4B43A56412F3AA763BF741CED207735CF6040CFDB3B850747EA229617E417D6A296A1B7D48A600A1163D488F5BF45E5F7E0E7F551E632A98C235C512A7AD33D120449426781F7E46D69FB73FFD39080E0CF46EEE69E406033CB14D6E3587E3771300CB5E91813EF30D3BF5EACAC9237E36D36F652F847D0C80F15EDB6A2ED7F9E700EB26F7BE60DC4FB70D266BCC607FF1B93ADFC0002F62ACF42FD912D7200C9435929BB9F3D3FF400FF3249FFABF4D8BB25C9B4A57DE3DC228D5999CEA839FEE8D1C6E5D6241757CE3E38E2635E833FC248F8DA3DDBB932DECB50E6E96238CCC253CCB18216CDDB1715173D680E2766A1239AAC5DD8B21EF67205C9D9A793D4573D93B88E12CBDFDD02A09E4834F13672FB6583C810FDF666F89BFBB672670033E7BCFFE664BB0B8A60F7FB9B0DD55353B090D80B4452DF0110D0E8C2C63BA3833763498BD25BD073046F92B7CD547B3DA9F25374E992862F6FEA77F536566450C94DA35412382D2E8B64CEB48DA94DBB06CBE78C9C5E6FE7464B37E285A367FA41BA05DBA1F7F3713E42797FB957719CC4E5AEBEA5C05D74E022E096D0BCC28C47CCC9351F44043E3FAC1F4AA2C5FFA744DE8144F31564B54B915C38EB7B35DBC388A23D59FBF5EDDB7945B5C1A41593D278A821209487E46D18562B4A624778DEBD7085F0159B8BB8B7700FF878E23CF887CB694CA14647A56B0727EC12F2DD5232007A626681064F517E57B22E63D985FC38C24B571ED32179C0F9D1D5ADD6953F6066433821B801E2906312DF42F82671B840707221E1654551E7CA136B5A240B77AAB11F3A254FE57472DE98604EB341AEE1D6830106514D646339DB9989D88F74BD5DC93CDBA394907443E941B7E328F83B0998585D6D198766AA042D999388961DB66618962C6AED7D170ED972BAB34D9E55722E06873786FAB842018C9880BBBD146109085AA21034F5998BD66E73CD4A40E0402E0E90A13139B2E0E4D369F2C8BB90F7A2A7AD674CFF11D021CCE362774E9A2ADCAF85A38DE7577D8142C25B28CE3B3621C525D4B006A34B0D3F04E2A120113D812E9260E706C31CBEE2FA49C23BBE6273D48AB4A71E5D34BB0026376F4433D6FDBE3F3C558C7B5B153A3A0BA5CEFCDD5898D1E60F582116285DDEC6366F5DAD5B2598AD82A63EFC2B2F90FC2B9DCE1B50E47C2008AF0EA3AA408AD98F17F7AF25143005A311910A1C74623499E23931A12B32194518C79BB6D7E75EE3B19EB46CC55CD753E042325B1EBCDC3737D0F8AC9A392750935CAE6FAA7C9C96A632BC889BDFCFE47D372D63CC55BD417E90CBC657B7A56BBF4B3DE13F7B8DF4A110A4DBC78E0C9209DBCCDD9B94F94E470207496811FE45EDDD553A5B4ABAABE019F12493B4A26A05D5E386B99593BCB4AA00BA43FAB0825AC24E457C73071AE4B8E6CFA5D14355F02CE7B4DB65F11D2C674ED65A839DE4FB95FA4D30EBCDE95B76D7E772C11432562277F7E3D0BBBBBFB63905F361A0D54D4DD86FD50C82539214C9A7A9FA2D4F0F43C354B6AF0B14525ED49430DF351B8928AE23D34C98D555FB4ED9564D1DA630A104E23553876102AB4EDB2CD4AF8906A9A3FC01B2369D65345E8D05AF89FF9F3E5191D7106DE5088BD7AC31315D8276B82E376B6B5D4DCB5B5313F9EF8AB48BBBB65EB45082F00D75F9E6927AD759FD9EC0147DAEFA114C2954B2F761CE91F95DB69FEBA8E286B0153BC8C1905AE9D28F7F388AF55EFA373D7610BCBBC094255C478443432670119A00F8E59D63E6875ACE6C581E8DCD155A4EBBCA41BE822DBFA74DE218785D068CC9860D6EFAE91F5E8626C78641FFDEA4E34534E501ECEBFEEF85E1B3D7B90B872FADC57691269CF12D1DD7F9963A459B358FAE2AA7453B3C7FC46A0B611F76A2D5D691934D322921328F9D1E533AF2AA6CF00BCB9F9FAC5FECF026CCFCD513A52FE50C66CB24FC71ED30407620E4CEA4BA9C94B30E35E9BBE1AFB15B266D3922BFE03BB066078B643D0DA4F96053203F1371F9392509D2B1F62988258DC92857978B52303C99B857DB329C969B14CCC084E0B2BCED8348F40D462CC67BFD24B4871DD0109621C976BE71F84315E96C59B2E4D1C1A3C8301FDD738DAEDB54071DB484545A30EBD00E84523012F1F49EC1438881E1C216CA13E8F63D03986E72C73D5A41B7E8DDAF4DABF621F6E6768D03B1EE54A7FA47AE22EB1093B9B44E216865A7757E9B4E5C284116F6E8CA3FD4F9E7B41B93BAF6D8AED8B344F60AC0129662305528CDDA400BA6D24BAF82B2A31D76C5C1CA321A24E5604D174931BA93940CA0446DEFCE71A40D705E92F50B1615A32808FDB649274F5116742DCAB4DFB60AAE1A6F4D42875B2C1D6F95FD50D1BB11BA8E23505CE81465E41A4530B6E435DE97FB0C7962F669DB68A26513D52643234778DC6A14F3E5433A8169E85CDD96B29F4EF426CFA7CE990848E843EBA80BBDF8540919038647C843E848C20E7F5AE18CB4EC8CD99D7362C9C6EA6F0EEEDE443B86C0F0C63AFC677B0CA3A0E80AFA324201266E63D306A2C2597F492B85DAF14D504F862D5694CEFAAF120C82556331BCF83F658204D5EB7A8A6DD1952F49992CD1D8A667BD55CA55CB8867EE917B24C9D7C0140E02FE0AC7EE320DCF4CAAB4E88D11534B7A0D8B7D18E288D3B684C899D4B1EA2A50AC259C92A3286CE218467E57090EE91B6408FC6220882C3195D6C7D3A9B5D27937706DB179048F9A2BF5A842188B42FBF803A76409DC59A5A74726130E176E57D43EBF8187903159880C4317569811A8B83D252D1B03B175D3FBD888FD0F56EEC93AF224C3D76399B31FA90271870FE144A33B24E990ADDDDD747BD9B4EAF4FB07B5C02F5358D4B7E86FCA872D5A7B15ECC131405739407D5413517AC8 +smlen = 4332 +sm = 61E19860AD3C59389CF701C1E6060C1D5D3BA4306624AE2ABE3603A6C1765FC9A3956B1DEE4A396547341E65CF53CEEAE3AB22A96146616E8B175528F90ED7B502ECE3D1BCDB96455C95D99B25AB11BDFA75367B2C594381F9FA255917ED2B1696EC27E065DCE2393E73E02718F7584989E78EC479810DF6D353F50324D47DFADB16B742A6C97E59E0E533530B975685AE48E101FE70019881384761D4DFB266997B8602C5A94D4ECFB618D82C3E602A0924949818F79700030780602A8A34E4B80430AD09132E2B1E586A9DCE763FDD538F657D0C76834F0C3CAD2D56B46A9478D761068B80875546D72F384E13E7363E1841EFC953F9290C8673DC5FA5CD119DAB18C569D1C2FDD5E8281FACF98BC7B50F69EFF5FEC6E0DDCFBB9AC9C973F531DB178408BD6E1E8D6133CB5B88A0DFA4CAB0C6914083DE75AFAAFDB450949B26EFFDBEC17BE41DF0402492C0C60525FE97AA3DCD82FE0F3CA264BD875C40F31F948BCC86F940300ECD487271F2C2A3E36D46D28BD5EE919329EFEFC607A0E011B4C7E113A81BFDBB7D6671C7421BE9FB7D1BDC734FFFE1568C4FC7EE948C1D1821FF5C58854B0DBB22880EC3EBB32029E32B1A516441FCEA2715D6595D5176EE60C5789426F4709676F4FFD218465F447DCECCEC73DEA02F37D2BE4A5DC61C03ECD55E0DDFFF690DE6B6020EAC07C447F5EFB79AB5C65624DFF8B6483ABE565D5B4E8522AB5607D5DD5925A42F83073353E3BADE5AA8F0465C9A686DD02085B97CAC79EE62CB45A8C952D71BB8DD86A3E40BF9F8BC66C5F32360CC365FA5DF541EC8C2F77F9A1FD57D448911C77C9F81B7F50C9E726F6424ABE7995319B14C2C4AC8D73204906E17A3DFA22BF4FADEFAE83A97E1EFE6A6BFDFF86579F933359C2BE66AF6400A1F6FFB934F4385BB6341E81515EC875FF97269BADAFFB306D5103165AA22362ECD36735382579E6A3A8EB27F5BC3A57BC7FD731DDC5FD187DDA2D8AABC9F4E4C8C0AFC22BA28B5FC2EFAB7D101C61592FC33936CFF0938A54ED4DE6232C984A624B94FB882F40D995AFD57B2BFDB3422C14A871150B0592C0A40D941BFC7392CF98E5591A26822167C1112A87B4D4BE1617E4C384977490B9EE467A21A294B7A042821171EAD74422D537ED676665153EAC53B35DD292D09A13A78BE1684F9832DAA42D84C561CDCAAC62F91EC2A7F867E642BF8651059507E1F09ACCCC08C12F4DB813A536314FA93CAE6A02662F167A48624FDC092900592DC33BAAC9A359BCCD6734A4F542BEB15B6BDE513914B3F08E776B75C7EDE7D7777BE86BBCE1AD2FF2E3D88F00EF134506E1C6E3ACEB35AF5F9AB51098A45EC5D96DEA4D50A5CF5B96FFF72BA094F137CE20CE6926E9B5A55CA1C41D9BCF7821F4418F485A6DCBD94B34155156D71E1C2B5404F89FCCBFB25961F480EE7108FDA0278B787EEFE6E12B93A06C2DB0B2D2E1E5B41D985323FCED627DD1EC7B12C90873C5CBC062D7EAE46CB4DEBEF2D7A62CA8AA62B85835BD3BA30DCC3320073EDE6A8EBF4D21FD5F7E2991A84559551C4D87196AB2EA6F603ADE61D57E23793D80989B6B415F74A7CAD3C1F0EC79955D70F333CE1B19FBDDD3E6B34186BD9334DC5DC92F07C54EB8A45A8351B751DCD16431EE242A7B8633287D864482A72A257E079B65996F5DD77BD4EFAA47FB299AB6B932DD981BE4B51BCA11D7EE0C4CA2486E1DD863D76748B694DA1DEE1DF0EEEFE5958B315F05E84E19E8D7DB2DDA8F7827A7166A5220A05B784FD97E13CC8ADDE8534E8DD9499A20B44B3083EA78E62DF0588425A7310FE875E5B04BBFD768C760E36AAF4E2889E2E57E1B06E3A91C824DADCA6E3027D0C5CF3BB62E28B64E98F65BE8F58F8E59B694257D35D66C9B5FAFF176133421CB1BD0C2B9363AB67DB6D14F6E39D73ADC8D15E0DC628B1767551C6FE3C79246D9E080D31A9B4E2C09485171BCA85C1556F4D3476D4B6F665927C95D1076A8FB08BC8A8F8CC4C4CA906F2ED5C2B36145035A2307D05337F3D8C92366BE38B8491140D540A68C85F69BB1E10885133C37C1B99946168907CECD7EA850235CD8D0B4ABE339FF49FCD1FB31658527004C8D722CB06F93E05A2E866A31F0147D21D29B4F1F8527F2E0E15CD77396911231F12636DB2D52378967BE69A69800D0DC6220B015F462FA610BEF78F0D2F63FFF8BDBE5FE31388865CE57420C8F2225079718C51783BDA5164850DA8405CA109F36DC7214408D182B1973A004BC49B6B58A5AD51944B25D63F58FE846E98B46FFE9BCCA2AF25AEF7880017FBD58921EDB8558F0F184688B2DFFF460BB3338490BC5FD7F320EE4F6600A7919EBAAFB0B1458E2509700866DF6F8DCFF020CA080BE1298FF39E57877746EF4BBB7E88BA63BD4742BF69B1C52FB1DE9149579E16D6EBA1D842B9860E275DAB07CF1201F3847EEA4F17B908290C7D08FCF5555D14EB71A0076869A0B2B86E2DB19D37145596D9C15E76800085AA616A3CA6D43E5CAEEEFE0050A0C60584127B2CC60555C1ACB8E17DF3649BDF6C0FF7EC1BD553DFA7D87E76ED0AC736A0243F7386B1AE59E7B08FC9401CAD017225DDA098B8B9ED0AC1D828A90F44CA7B6442CA9C105124E40BA022AE7F016AAF40742503F07C7CD8E47A2DF7B8CDFC9DFF80E34E40AD26207B0A805D017EB1F9F158EA2CFC19FEF3D1014393BCBDE4787806E93325319F16DF54DC6994656413361D6F3C833697DC34915C55D1C5C8C03917F94F3B6BB955F456562B1006D0BDFDF6FCB1F34A4BFBBA7CF41456AB10FFA45FEA58367BE2969FF305AD731CBDE862150BF2ED824940B4C513868C050777B88C1D8D706E0EF5032F304FCEA2200A7D2A30D2A9BA20AD1B4846A8A75F806CFFC032982E37E11F5D3720B4C362C41EC6B6AC4F02BB7C9134BA3C6381BC6AAA6E9E869A05A573F81EB99841B0A153F3B63322053E8F819730A2CB69C4E5CDD39819DB0CAE18C7A40AFA8D84E956EB3C68696B1D8E39D09AE0E992F46B3AC94002044A9916043E9E06007F6719007C46A2A2B17B108496B2FA48B1B737F184C5459C151FEE91CC5167C2BF2AB5BBA199932A5DBFF689F74D255F804F8859F7AD39E44C40CC95A08161DCA42C88EE02857BC79811081E50CC5F4152597172176984182925EA9F90B565F32F49E8D4A80E1FD0A650A748725B7EA3F658697336277CA6C550E8F4FE6E2229A1943E24BB70DAA76E76B4C00A4FE2CB46049196A17F2C9B4E5E709170D8802C50179C4C49AFA51C8B5465CEE776CF7768D549133E6B9729FCBB4DAB412D0A816D5564AA6BDDB23418C71E55B673483FCC6904DA27B36707164CF2E5D5F3ED364E1D7B976119AF15B1D45CDD458D3FF31BA05D8B8A9DC587E76A67BA239A9C023FB3DD5E7FD2ACB6D4B192CE31B2689FF25762F89FB8300800EBE6E1F7E02CE0DA4662F071B80590E9E820B85DFFA3DC55F186112D51427CA71E1395DDC1B7660AF9C6CC86E9C726B54973C984FF46906251D877654DD5CC56ADA0D626D7479AA9BCF0D655F33CD5794373AF74CF208B98800D153FC9B6BA6E12EE26C76C7E3EF06B9B0604D019B6891D83D15911F5D0452EEADC4134C4EABFDBC064C9330F49F8CB7D02B85CE3B997234DF94268936101C752767B21597FE0484E7F994741EBC9516494391A1B667CC0FC03EB5F116AF6B34896DE4D21BE4C5A8A49013469D515F3D160F78590BC5DF675C713C17177D4F1AE4C37A2A3A8DC5A188F62A0B226DE862D6F3DE19AA213F6EC5CBA65CBB99AE4B40C22C0196919FD60C44A81E2A73426EF7BC6D0D31818DE3DCBE2FF4CCE23CF5868B58BAE1C9962C2E50316AD3EA29FA77F8D6F62BE081CC4FAF74F9E04171D7B61764BBF47004130F4617A1B58B8E5FE96B29C6B13BBE93E390821D0F2CA0BE07E34B3C5FD30BC77404CEA693A540181225777FBD542A1C2153728B877E65EA6389335CBA10CA11B8F75B9E0ACD169FBE43B580224A7D77DDF7404A7159E8134B00B0FE2A5F24CDD6EAA8E26485FAD62A7A4F8E69E6EE33557F1D616D7FE60022C9FECA48B309F2CF6EDDF0CDFD4D112E608C6A1540C0B3521CA3FA41EA4B384521633FE673D1AF95F5EA90EF68E293D24F7C83EB4B460A9BBFE89B57261D34E0D2965A59968310C146F8B07E5E5321C073B6E1B1B8439A9C20CE2EACAE965B6B8B081FF2BEA16A055C4AF2FCB4F177B8D53A50354B3BE99505BF12252CBAE5C666DEDF2435264AE37789DCC4CE49E02BAE52D722EC5FAAC2BCC14EB5C48A62ED122BE54FCF8EBA5E5E04A71C50F9F352E29DE35D7D1EED575E6D8800D9C2452AC9760A7A82E8697E0DA947A8A464DBB26C0A5958FB1AB6622AA1D37C44EE7C312AEC0AE28ED723B8AB24AC723C2C877E5645014436B7AD2F1EEB1800E8AAD78B4AB5B4F9643B71AA7F5E1A3B90DAD2F2D3F5DD2D5EBE334ED7A72B7727C269B192CBDB067C92DA770C517872648C4EB30B2CB0B712D912AEBB63C9618F888313894827B0101C7F6CE90AEBF2470BA27FEAC8973A0F0B6B73C06C91BE3421F3AE1FBEBABE6D6DEDB7E6CB1F6C601E4D15782909FE1F107608D9800393E667DA9B0C0C9D0D6E2F22B3E53D8DE084C4E5379A9ED7DCB2128355186000000000000000000000000000000000000000411161D1F24E42C006F144B0B4E188FEBC82D63D3D37096DEEC9D3DFC3B421635DDDB73C76F6260FF1C53222A50D30B26E2DE3D16E3AA64C78604E1191BBC0E2553117A441159B2A35FC8889499A2EFBDD2F30B8B4C6CEA38EB5B2575926E6F22AB96DDB4B0C5C6D78C3754A1B6DEBA49FFBCFA7477BE9A0F74EC379D1C9AA59247C091611573AF765AE698D78152187B291717A9F03FE767BCBB12F52311215579352E7CEAA8654B5403F18CE82E0A73BFD5FEC1063B506F44EB1C9C5A03697D03DCB2AE15C5095F292B4BCB130B55C19AB728B3232EF77D1594611573CC6BDAA254F05934A329DC27CFA6CD8C02CB51C3C295C964C40502FE2B1A81A51C866F7C7380BFBE339B39C8F51F73722A05B5D1E9CB6313557B3656863803C9DC99BB1905D7F729B2DB8DA23D88200032F36FFD04DA11FFDF6277ACC69C5407289D00FDC3C56B32D54877F4A8DC70ABD37EC532B8617D9F3C535B8E962FB389E976B4D1AA12DE5C1C2FFACD50ACFFF65201104648E0C04CF7C1F880E8BDA1D68404BA67C4BF64C9D2ACEEF81B35FABCE58645E0F2F61EB4CCFEFDE7239BE408710D349987D849D40B3AD294B9D815A91848F9ED53B69F78D9E955F6D1FD7E38EC291664D54C2BC359FBA241BA6ABCBF5FC2502D93760D9F6B1F7FB766040E98BDC23A6047134A35327FE128AE24B4C7D0CDCF1801947A1821DDD7424892DF50E2DD5C1E2E6C5BFB4467524FB45C7D977604E7E0F1F98EB8C03EEE1D9A5796C8A801F082678940F076BF44D3496730C9A640FEFCE385865899FC33B5DD34D036F2FD5D07FDC0A40FB725E84CE403B46DE712B4B44CA8801A1CCF58233C5DA06719769823B5945849DDABCA56B0B4EF9327C8B5E5A445E6853E5B66B8D590759D6B2DB722C22F8C741CF3C6325A76D93F4FDE5872D5732FB19AAADEB7C18094727ED43B305B87AE2DBAAD67F90FEB86498CF65CC57EA635340F27AE5C5CD60AD3C763223AF877E65A005C488AA4AF9309E1AA02002B01DF8865FD481EA254015796985969997A53B06DF0355A6AB3C8219B652B09E1F86A6CA12D27C4BCB9E8D35E6889198C8FED71AD5642F5F9F7CE1DF270D68AA05467EF9ACD9A51347AF1EE9CA7C4A5D78189042900C6D561F68D410A77E79726DC123B196C78829F02CAE7D0623BFE9E7B0D8BF84033086295992B77ACF027489D51BC7FF006A8D4AB8079D494413A565E7F687AF40DD18B86AA4274EDB8845DF114C0146DE3199CB55F773A87FFB126B3A4D00D38835CFD2D6652C07F572F39D0397FCD62ACF6ED9F3E8951348AE7E52A669FA4E2BFCDA548ABB1989A1D74A27B73103770290E6ECAC87029359354EE4C87A77BCB5CEB10162DD54499905AC8ED442C173CACDE068BC546720D1284015ACB90CA19147694B53899395DC663D6683908F3CBA29AD37F15CD3903C4C7F4BD73 + +count = 31 +seed = 9E6E12F025B2A57B0F5A3A9FA70396FC332E1802608E5CA07CC4FBA922F1FE5DEA6721B96F1BA2BFB97825A19F08FF2F +mlen = 1056 +msg = 9C311FF20F574CD9B7BCE1DF705AE7DCE6E7A621C935A6E57A59EB31FC443AB1E014AD332FA784583260AA6153C464565C4568108D60CC126F6E8EC3BC9120E5659C86CDA8A31A7131936DE7B3DB39A4692808DC3D2BEE8A99880FF9D1D5EFF1E825A0F043D908D62A99779E013845AC0C21ABE8E4DF0EE901E4C6BEB8BB36B30228B7756D617A8F30C16351D8FF91786F7406F75D9FB648830F88EA4537F42EAD62E8790E9CF11F72C31D718221049C9AA35376AD8FB065F4809F4383A23C2B29425836C2DBCE4680450896EEADEE6B83539ADFDF59AA4FCE709D601640EB9A22DC3B41108A8EE1FCCDE9945EBB1D3F676EC8395255E125E62A32149C73451F597E1C32AD979E5BE914FFC7C548D6AE92ED08501831E9007770A0233E5778F22ADF7F1AAADF9C9A7C82D2F42989BF21627D3EF8BD0377A5BE5C9F5A585A246A73DE4340E6B43B36DB775B34033962646C16F26A2B7179C40A721FEA54805B9EC42177B42160B1A67341235B5AF9F30B2703BFF8CDEEE5BD7CE506B0707A69F84225B6E5A92E80EDFA235803DBE2CEC47CFEF0D9FAC95C3379816A39F4550BDBFB45609C76D0351DDF8D61724BD5E8BE94673B3013EEBE172CACE247D79925B12B5DBA2F6FB72E797B2DA849B79DEE3DB76775F5F1DD4595678671C7B18BB3749FBB0C6A7135D639F16B3864B5A251114DE7E9F8CB02B4CC69902EC8D7D544D98E24A05F8ACCB182E2EB44BDE868B077B1FAC4726E8B01CDD0D024405665F7ADB60A23FDBACF421246354E824CB74DFB35E57902794E459493905400D0A0BAD51D8EB94EFAD55C67CD0C7CEFE7A1B055F06371AEC7F490FA685C611D553D8430992EE7B1855A9CB305B5CE53154345D7DEF6110DDBDB5CB59559EB664C6439E057DC022F8686F2AA0CA81552428437B0CEB5FBB5DF254036BD2BAE7290D947C963046771A39D2656312236569E775E7D2A041B7EECCEC99C1B9D2757C7370E474012AE707AE00AC37B73ED9C8E1A2774E54BACEB42E8B31BEA734463CC15576BD4F7A33430B1987D62E47473391938312F2481838F286C4DFAF701ECBC6EAB1A9F074C1F8D8963457DFAAC9A9A8EEA70C50CE70D1BA1006760AD3887605EC38861DC1A777D21E46EA169537057CDFE256CC08699D73B1AC4FBC62F863353581CAD358B9C573D77585DF6544E5D55048D66A352828CD1ADF5F42310FFAC022A25824430F741371027B2DC14717DC87342A74F0038674187E478D8ECEFFC16474A4AA8BDA0C8D41962EF2A4B64A036C888CCF4EA628E1CB9EE0F9A918FB1B22B9367FEEEE0218C83CC7E27C5CB2AC64DC7E111E3C85CA0E6BD4F685E5DDD428E028D192142CCEE3F0C8337BDF43CE4B62704AA53C703EC334FB56FFDFB81D7D4419535D17E5FCC0E6F558AD82149C591FE0357DA15660F61544B4041128218B6DE2B75D3801510669A3977E2983BCAF957EE2942E504C29890A81542EA208E1CEC +pk = 20872F64E1FE69773D60FDDCC67F2D9DEEED8289CE17907ABBDAC36204805E0660A89C9AE44CD7EF89808CF103656953AA43DD8D5D37E02278BA1BD03047D9E4A25DB026C8E0EAB34FD6158FBCB52A64CF6FCED408BE13BC8CB6F5DA64F21A49D49060772AFE8A9E794B4FABDFFE9E219436EBC97EEABF7337C7F93227C58520A2943C67720BC2295219207ADD00BEA6EF50137E57B9135A63CD6152648A4B01978B0B1EC620F6E791064748C7C836D40EFE5481F3A3A4178112F2B42DF67125B8C1A3744F0BE256803452A394DC49676E17CEC1A92BF928BCB898A4C933250F57869EDD479CC5B0FA84CF2149E4761025EF15F3D67B678EDCDBE5384CDF9AA648A543DF84DDB3A870DD55362E4D30AC509B5191F1008065D8CA69B7EF6D17C804C35C65BE1D40C430EA8BD2B986D7BA60F2EF6C66F0EA021942B2A91E19B59BE98F4A8A6B782288D1B41076026AF69A6F3E7C7099EDDACCC0FB5B8DBF2A6054C86B7F7DE96307657C2846F7EB520F1A70401377D495AF48B1758BBE04FC962C753DAF6AD8A03613D032548788961C8342CD6A098BD97545C0CD0EC0BFF3D98DC5E42F9DFBB6752662DF02A1BD861D88992E2536145110E05CAB62DC6852BFBAC18EE951BC56506A04E9F9016199421D08F2C36D78BB3859DBC2F9B3051D4D1E803D6117EAEBEEBD7818067FB5EA3083B49D3FD0C39DB5EC182957230A000CFF7A12C0D8F6FD5B0066D634699F426BCB248279DE784C2F538BDF3D3CAB9A7E5F1689CB1447F3BBA3AF0E87A09192AF9DFC84E32403B78F9753EE4F220F0BAD7D1DB0AD83C66CEADA007616626FEF5832C3FE7B9610C9C874F1A9E54B864A7E97866FBF1A12BCCC5EEE02D6AAF28970ECF660A6CA52DDBB241B099EEEF14C59DA4F2BBBFC86F40EE152B7470E9C862CB0458B9123046EB37022F9ACDC0E51F5EB2AA1AE7426AB9454764A6D3F7B1EB6BF2F3A371478C8D33AA15E8A17C7C5CF9463CBB379DF359EC989C68EF4A091454F48A9FB5E1B8E00BEA88306CC1AC3B9DC11DDF8D790649808C418117D49492C43210D7674B401AA2FCF8F2C10E20E2C5E98EA7BC92345EC28ABC71DAF70AA9F73460C774C57B9B39BCFCB15FC3E51BE00E3526E7CF5E0D5563782255C6E1A9EE5DCCD6FD11E357550D5A5E42C537CFEFC95DFE4EA778D6566308ECD6D25D7B2BEB4833E4AD8376ED90DF2DDE16345BBC6EFB8D406C226BA28C62B9ECF1EB72E294D18524028114F61E3BF4C3FF18F75ADF60B8665D9A77776EBBA1B24C3EB0209DF006013879DE7B0528C555C729349F0A974583B0934D449BFF2D5FC92FEB0EE963437040AB2CB35D8B4506ECDC7E3CF8B3727EF85325DEB48EBC7BED18E467029F90BDD28A06BC1323B4066EB5470AE1D32ECCA99CF3953C67ABA3F94BF99319A406ED6E782C4D35DD3FFAF42769AE92C1C2B114F8C8C137240FF6AD54B5B61EE58F4BBAA3CAEB556BEBA5BF9D17DE4F7F62994DE2EC2BAA547B08C5174C4754BC1441D48A4ED5D4F7D97AA57439CAE81E21B48851278652BEB11DA103190EB6B5E90C3800E0A6387771CA74E16BF826A56A53D966C8374AC89674652E5574D9FCFC352BD290DE3E580F939F4BCD100B824071554A2F7C2E0751C1D2DFC78F90C2A745B03EEA09B992FA44243108B8DC673406FE110C417E45B0C6093F5132299FECBDE3335E7BD5D84F9F6B7BD8493A791337854C8EA9DA17C9D370A4F6AE0E95322F55BE2C0893BA030CAB69255BA0247DB1300FE84D0E7D7BF448AFC7F33CBEB5736D70D9D81B576981E857B8CA684454F2F3453F406DC5107B52D3B8DC3B0CE388B3EF31D4D24CE1BBB9E3787F0E712283B7E4AF7CFD9494C897D19CF0EF9F7C065EAC4B4FBD1BEA576265788CDE41F10976B9256EB0A570B1E6365A773163E0A701C350B88DCE9FA855ADCD3B8521AE8587BA90DB50C6A5C9667A00AE46D802855EAEE16DCCC65765915CB29A7896CF57D0749A249F6319E57E6F21D66C3A019729F43E390FA62C928F647A53337EDF64F5D6F2C64B61365FEAF3C9D02072440170C551593F3BE70DE76DAF9AEF03FED62C8B3BF42982C04E745A9970FAD7482FFC88EB3253EB9AAC818BC5188E716A03AC698F7BECF4E39667C6BF294B73850B5C0133FCC1213E126F9A9A37D01DC66A18FBBD2B2A90BAD670788FAB67E529E42B2C9FC99276AA86B8C6F956FBDDD19988127DE64C30D17A4BF83F7399A3915CCB4EADD0A9A3413904BCA70980F05635D65043C2E95334BA5B98F235FF0BB3D021F90702C2F60194D560C267E456D9669A628A8817966BAFDF24373DE5719E33E3D1BA67D2BA1585DFB46787BC849C758D1C07199546717019840B14F6A1F0CE0543ED53C660D4830A661CF0F6B3722CC5AC856542CAA4248C50C41B0F7C472391845DA94E00272FB71FFC72F1FF6F28CF8A1E68E48BA33F4CB0B0D8FF27464476C96DACC2DD18D98D1E0CE88B0E5D17E79430C013B0C1695B75575A71AA10B67C063410E66319A79282551A2804A25984FE27ADE063614DC91B8D842DBE02608DC5F12E4C6548DF10903D3A80BD0B1399506F811E6B7B7FE09B81C51435002C0D409578B989B1CC6C1C1555AFF371E59E8516C12B5328DF9AF05764204C675487BDCC11B7110138397507E8605E9926E8A8E2AE6EC2E524F255DF5061C25F2BB44E2E9474F71B919E917C308A8C754C270361C02FA1E862C14FD09D8009ACBFC86F547911CA5DBD8D6BAAC99 +sk = 20872F64E1FE69773D60FDDCC67F2D9DEEED8289CE17907ABBDAC36204805E0618274BE9A54B6A16BB9A98B136F13AA7CE881132D6288538E729F50CEDC76D8AFDDEBF1E3CF9477095E66F1C4BF32180BF1F46CD4E19828E99239C0B6B567F48A1E6983B01CF56CB0406CA50F5718CB9DCF4BB78DDF81FCAFB2C065F78F39B96521434174134446738378656226885070766542453774528012437852356174861610482001506055608164646726357824567863137161457577374677538775517415876628237480118747516284860014440536067724837056163114285646647104444341143802811203163165137283157871881816177130246417247311165463853725162553174878377415753837520344712247106318618513684060022143157665153510842800012613706855177622728463888047515032574088446621044624243218867548776141783071570170143355473473534540330175210853072424610076010525314722015028188673821571600403385125806864200637885073553732713274537662863085717320142653381747030503102075016447783532264284463662858137082411852248750478132254554473585383805002325154388261875038516107006341176521716777737135481135338882176705752214830331226824057212184650451076640720252775417285086116542766517714416268843644313688437372500581776026258837432642804786320861402487135606688367085814177635726508633582876005473201587662563420140673145138761423024645435660844711157182455543534155645840746628265150268785458383318553246351338310743525735011715231647735478238757218275341567688755307133357602724256864040714837053338660422646071448575176575757614862322418466816058666480770206830563801717471062742888773777332723322853484256268054301061655213005302040212567211687216848278164288450164125830154426637523587036121207614535261766530817137010305638261304767617004773168043560026654233220231162668007730340012210561181055308277383727607132607865600224566881866660736315740361848527135508503276452276778824122568366114027166222717421462712363273430352203024570788605476785526554712884837455806445058287803762083376041380082348442722472835501437571531607113782818180525122765230334708570637223574360346732257548708843164585257411303504347783072308482603312121016545386736777712435266356834647568764557750565272678156315726325083878105324425518554650854646573128327460181471583770684022706032617346667545521832257571368736882301175443252188845758515684237647028402468228184655544308358260615253620282781303831153308478556245154500453078861024086577005727731836842484745368087068566648340341786460755385882264331836486623554553028685746585168887238658483805141464513588282011883556361176705251768806547261145006110238241072458377185512455338607716135115123630182183462621338003221846886651208222885650204784670721054655670526101600010330276066864306248007876355435500218573886402357078834330686311100246856781264833452105613457327447611640260127158088347173406060402234787603433405050406216652831372721108346585568550812221386746867433815240077543528342101416026842374542343787532781060483703502432286878475671117451165032875227472472624243884128730844601281117663031888762816038500480344728435400465456266675676466758606270343558782767648455043472005400523671143617318474764661344166114387455820571503752847130183785574070118B6A634D29DD6D04EF78FE6EB6418D99530FC355ACFE5BD2EE8A4263B25CE895E60521F4851782D0ADC76D1D7EC8F10C20B4DE4AF4344945703F8009E0EAB010B03D26FA38F9DA859DF79E6C9845A8288E02170ADA65735C4D3C2FC344AE598929CA420D66D88857681A8EE9AAA4B55C80201404091DE5C890CC2EE51363CF8D7A1B6420650C302E3C8407C5519CA87D8F8FE0C99AAB4848D574302EFACA19BFB772F47EB24D42038C084F0EFEB62E8925D29AB523DFA7A8A317D40F319C2EECABDF7D82CD13F582FE32472405F5263EEFF199F68CC25A45A7BBA8AE67BAC4D5173FC4784A85F64F40115B3289942D732DF2BC1D9ED47921EA33C1115F5CFF7FD64D71E16CFD55A6F27BC1D2DCA4A2FAD1E656876D95132AB379B59C24C244A250C21482CB4E8D032218183B881852972DB95D2131FA35E5A0FEA753F179929556C3AFE456632D87ADF7C6BA959DD9862ACF39EEE00D8CCFEB0A068FF6D1A6CC58AE996D32596B16843DF77EB301E1FC3BFFBADEE6A54BA2E2F6C942DC678D238C91495CCA3F4F4D1CA72453D9523103D44480B2B26005FB0E4C94B45B9EE38077D0B7C5537F4E6A122CD8F13C6FC4FC99110CCF8C46D5F87695227A00B13914127656FACC3EACED9F061052E176829C475480E2722679950647A8ADA14BEA9865EF049EAE9830ED2BCD4C45F05925EE51C1737A722A95BBC8E9C26C992CEBDA2D991DD99AE026F6E7976917CAADE9E70C54B044D5150A9A8F4419EC968654C7E208DBC1CD88D7F2500F5F730A6F5A1334AA922B2640A1F4E00A8AE9511F8E1FF9FD105E39A7D10783414EA02BC1F32296889235A9DC42E785AE26F90969BE994B1EEF262E92A5230B8E38819B48AA11E684F970636114E147BC990745D32039BC6EB790EDFC1F6FBDE6DA2535EC66DFA540B85695DF10D87FE4E0D5D6358D4DE380D88A695A1B7E0869402D093821AAC9BA542F5EB9C686E597A24465209C8CF37B6434403DCC92F196B01FE57E81C5E3B3EB093655F2C73055975F8AFC65B8CF10FFDF10B9DA327B624EF0AE19ABA2ACA5F4B5393924BD4DF14D7782510A78AAB756DA98A3CDF9D0E621518B00FDE7614241F893BA3630620624DBD0AEEF93C02E7900F164A2B969221D6DA8EB0E9CE1108F4740F18E80B16131B3BDBD7DCBAF72B9D9D94C20E80B2A0BFB272879EB2FFE4A693A9E4FADD2751F2B2F70C2518298FB2E1C3EB11EFF7B51BD258A2B0553630C07626E48AAFF4784C304D23EB3F1C4C1B8443AA165257F0ADB0EB5040FF4E25D324C920ADFE4D26DF180E0451E11DD5F6CF26A345AA13DB689605644FF5F13E20FFD93915A7EA4136D92C94948DBE568776243E673DE70CBBA18A3A18C27AE820013BE3652AD93F266FE55597433EBF80790CA993C52536365BE4A32B9FF651364B69C704D1A0D3CAFA5A74C8A239CD5929A691ECA7AA537F584ABFE263AFBA7464A480DCA40A7A87DB2FB909571CFB1563F0D39A4A921B71B4EEA5608F1A70663186C670E3CB6A16DF91590CA14859DF47B1C544DF583CC1CA0CE72C4AD4265D3135D6639550C7F3BB6C1E27B316EEF82EC66BD12C66BFC4C919068571875834426133926115AE3E1B6F0B2D05D58B33FF623F199313F21912F4509089117705B52F0EF218BFFBF9AEC762FA872EC1EF235FBC7126D01DBD1D40BC1AA02E2DF6B5284CFFEC551670A01976028FE73BDEA4536A91310F98999C1E2696CA410436A64AC0DD096FF803B80B85C13B227B190838B01E2CC2DFCD9C5A5020C1E1198F3C49D2EDF1B39D01C9CBA635DDC1C51AF35D21BF3304767959DDDAC182847091426095C81194F6C27312F675EFA0484B00857116368B2DD8BC9DD82467A27EA936FAF07C579700B4DDED8D132F605ACC661DBA985764DD4912E9DA8A89DF2762F9C4F5AE4F5018D63D296456E693DB2017DFC9963B4A58D62B0B3B0FB6639E373CBC7C9FDB44B3C5473729052E5DB7D7AD0FD395E1A0F5344DC369E2E6E6E59C071D362454200F8070C3CCA83CB92FDA5C03E7628F281DB6F1D47B29C1EFA0A03891994B80B56EFC9EE0C03EBD45334071B3FCF79E730994E1F31C406C19542B1F0E5073CE76A6ED0217BBD80CBD5C90A42F71D4F159652AAD5AADC7D50C907B98E9CD130D9CEC3213FAB61C55C2C407E2C27CD8433BF13143F5BA86378BCA2F9ADEFAC66C1F94AC90D8A63FC11B4156E68DE2F4615903D8A4D3AD6D93181665E2B66608D914FF81CF2FE6AE6801C1E2B0831A2E15671A89DA265F9773CFD07E4026BE06367A3CAA7EA1009A115F2FE6DCD9668EC75B01781674B06808FF5237B5E7FC779A87927FC826D0247BAAA04874039507DDB111454FCC010893BF1C90D363D85662AF030F9E36F56AE0BFF034B1E884137A9D4A0BFC8421EB1131147F5FC99B5C751239C6443F71A7992CFC74AC55D2285FBC90759B47A007FC2C10FA3AD91FAC9422794A3D6C7E1C7EA63E9C2B4C549339178F9030F40CEC41BF78AD958EB61A5B0225D8FE841B3B25A6FE2BFAB247133C5B3957EC75283791F28F4E364A59A1EC54884E65668CB78B8B9740FA784034478A24D96B91F97B737DB2D3037D46EF266A36F9E5D364C168D98F19C1F3D6BB22E909425F4409AB5A2935D330E1C454643F6FA0E2CE289DAAD488F73658F4132B070A2DEDAD20AB70860107CE72415378935CEA48A3E4729874B0C001FDF94657A37E9821A10F5AF06251F3B728E26B9080CB9D94324AD6C20F29C7F1818ED9A6A667DFD24B81B3DD2FDD0A077DB4F9706C0AC71DE3BA9486AEDCB947E8F5BD049AEB2EC06FA4FCD3E8D82C568C9A1502FE31976C991E51AA1CE9BAB937A16AF45A16CAEF900015AD16F88B76232A2AA8BB4A13E753354CB22DA3E8B0E37D71140931F815F34444C944DE9111E0FA82644F612F046E6CC9140CAE04D3CC75E554C39B0842C00583C8FF76350D2E64791986DA383700AE52882AADDFA4A607635B20E8CA26145B84CE7519B8C69AA70B62854C2BE9E0EDA7A3506DA659DDDCF93CDE8A3CA4DEAAB3912093679345729803EFAE65D0D97CEFD88E0C119CE39A4327521427A7AD44C2845D5F99EE7247DB9A657A88E0F6D90FEB5C938BBC16EA7447A79F18A92EA01D882A876B65A6AA599474954497190BFE279563375A0224AB57531D20EDC6682C76F0D30FC80C7270AA77A425D01E33E415C5C9A94DBD4D646A868098AC1A0FD2EF4F36EE98EC8AB93D86A7FAA4E0DA1BD4B93393CC44E45BF3EC438532553F271AB901AF47F03B0C3C6BD17CD563DE80CDE040199B8AE087D22D94B9D96D5E68347A7C3E502A7B7D8067AFFF5EAF885F0F4B13DB8DC44F77A22D041A5CEE8EBE51E73C9F8939BD7A264E9376C09146899C26E1D33725B99C3D1F47C93801861304C57F994891E5A9A3C3CDCF5A6739F372BDF06DA4E2D7E7321EFF506F54AA7E85F73C4462F3279B2C37685EB3142E6BCE08C515CD2C98F25B92740C1D11F6325A37AAF06E1276B737BE21386B7F1C319 +smlen = 4365 +sm = ED1F31587D816DB6F3B4929674ECD0A32CA9A1E0C0323116AF0DAAEFAC7F3214F043899A01A456AA0AA96B3925A6481D49D4B926C12E52ADA2DC2A1CF36D5CCDC2E59D1ECB19CAF70B67792EC7B973DEB5716B206FA55E7A853EF6218FD11D690CAF3395FCAB6D1982E5619813F4A492FF6A64376AA3B6D461AC15E0849CF36CF4C7D2FC92A957BF6F24A124D51A525965842600BE37B015AA860A491296CF953F8EFCD448ABFAC3799C2E43B3FDFD732696AB22E3367145AD50DAD47A9F7023FEE44683C63742ACF932B0F8EC81A2686E8299CDEC930128EC2AB2BC9873F8F53D49CD0FE3EA61880A09C78D03374048F25963DEC50FCFECDAFAD1D04E0A4B6CECFEB4F4C52EC71E6A3682404CC78E6878885387321D4826D694DB953E89DE878C2D2A82FE66CC39B9A5C27179C353D39FF44BE3C4AD3A95D2865F262C85B689F10D7584B8F87FFB1D0B6484714B56CF2B90D9DB8182D0C501EE997BC4BBEDE5B44D17B3749A4D2E54D1758BD043840F6729D297EAFF2C0B668CD0CB5E78BB3A958E9B5DC27536A27DFEED706A3B69007623DC24E37C4D9EED839B52547820D3EF70ACC79E88BB242BDC9B39C343F12F79CFAF609353ED968DFD7BBEACD919C48CF21D65E9020D248D09387B07D66CD962DC4563A3B578594EB03A2091A804EFC127DAD80F8923151BA06C1797727E7FD206F1058EC9D6E0C1140B6AEA25527B6578983E7729C83071FEBD4EDF745AD225D63F451ABD502CE0C7464CEEFDDD6CE84464D4F5F4DC29BC3D8012F1CD7A6C3171625024D636CF0A8CC2519E169E9752D4FA2B1F7D5FF8683C7C4F93E1A27E022934BF8B31641814D58810F9BA0C5F44388901EB98F7C92AA161C91548B9BB37B2D0A678B66C06273AE37BCA77BC589B8E91114F8C8FCD202DF505E52C1828B445C660682F015E8C3FBAB320B733DF392DEE85E765E56F61BFF6A42AFFA38CFA2137C0B061FE3F5B65DE34B3503E5482746814367075F28D5A3AC7F987C6A3D87389CFD60732A068C4596EBCBD708938AD79A150F5004D39B73D7C7B393215ACC7B82EA51F7993365A0E03516B013AC58D63DB3A522C389B2AAE4F3385912926151946969BDF3F5FC4C695B8587680AA6C3BCF8028F7B4D1D05DAACC868ACBF05DD34202A8B213DF19B3A82E408FB0964453256A543A9BE0CA806F5FD0EDAE9DF2CE88E0B173535489F42B4D7BEA750F0EB377A5646641C7A03A8A57C1BDCA316040599A98ACE094A5AA210163ACD66496F4846128FB9350B7BA1D2B1C5F987A65D0506AB01C0EB713B2DAAFD342BA51B4E72CD349654D6A3551C6B1819AD1147B0568DA87684EED938A4BC0CC84D70C3BBBC60F0A1355ADF5B96CC3BA2B359CDC05D2D6AD0F9815F0945A32C4A245D85A73898ED69CD5D4DE21E1FC5EAEFEE4ECE195A3AA0180470F4BCCE7817F7434D112099C444802C7EA41A13885ADCD13296C424408E45DFBD56FAAE8FD4CDDF73EB7EEE32C77B768DCB6B4AB7770580DA36348FBEC30D890B695D4F3A31B99A56EF0E3DCBD3D9567F1AAA36CF86F4EE557E2769C2B412FA58E1EA2CB80321FB461302F0B15152A4D60A3ACB50C26D4FF2ACF3C5BFF67FDD807592A6195BD9865B4F0903C0AE79485078F60D1FC50B2DDE1F8BAA2F6235FE46D513F8C7D0FAD78B340581D8CF66885A6F7750C104F57E49DD3A7598824A427E509D3A4A2A2B66420EA3FA2EABF3F2BEC4E6F20E81D386F08331ECC532F725C84E04430CCDC8100F2536DBA1D208587F8CD7DB349C39BBDB25502986EEF28360A3939C3DD521F88FD81E735E20A78B29D60D6D920BC59E29B662F21825609B1A08421CA959B0D9753D11D3993A91C51AEDF599581DD7C54F1B149CB64DC5E9719B49734CD6E30BB368F39E5B001A30115F312F2004D78D622E41BAEBE827A3FF63A41E069FFC529BCB22E2ECE790DAF790BEEF7E96C935EB52D84C6C760BDCEFBD760A990CD0FC6E345E73EF6D1F79128393DF8E2ADBFBC9771388A31EC0ACBE30F5FF999EE577B611EED7209218B56733C76EAC2E83C81EAF28C8555D968A86CDB948586DEEA2F1892D3143AD50C298C5B0521FCF836D57E96996D94BF68B57A90420DE69C3EC3600CEFEBF91D46C0B67902BA35B3E7F582243DC4C48E81E4979E6DD1679617E490A8E3B9DC108426CBD359D30D49B2FC5DD29A7102DECC94FEA0A3EA4AD19F2AAB69FE6C91D879EC262F0507374776703FDC7812CDD17DC11BF9FBE60D1FEF44C0BA134F80E3987C7F09C53FDBDE8C7D0477E1E33A493A4CEE4486E6D124C1A57E4C1DCDAC3A2AE35EE8690E1B9D9801D88A48E3A0F5D092B9C4F8E9BD6DC6B3AC814D8D133447F4754DD893038C3673EA98AD54CEFA8A2CC6CEEE1C960D6A2DE75E830906A85F1B9FE574BAEDAB6CA14D9337D768C11BF289A4327B021174A3F0929BC79D0775040AB082C8AE0BD0933337225391FC4FB08027CE5B5D6D9067F0BF1627F15604D24D8C69166FE264FE032577B846ACFBD3145ADB2914D9E66A946E839285B1B52821FF60CBDC9D9AC238AD7012FEEE880795570C19D4BCD3C58AF4D0D84ADE7D7111BE1E66163162CD01D79B1C9930AA235F1CCF9594DAB0623EE308AB457F2C7043F7AA97C0DC3B6B34D170EF9D7BD564122DE1B2915529017934D08BA0283193D926AD888A84535DF2853A9E2F148F1B9F749A57FB2E290B71F05DF758ACFE43CDA06C04E2CC12488C7B78FA0777DEED00E0B3865F24342FC8E6BFA15A6CF91F632FF1A920369A2A386F597DF787296D2D95BAD4ACDFD63C239FCF3BEBB74A0D2E6B5180C859A77915979DE818C7A66C6E23BB1E7F75E651BB9501370CB483D85577DE2D07C02FC369B20FB3164106DFE75A5F7C820D829E4247E2005BF28D25F7D919F1571744C53CA17EBAD3E5C122EAA9B9F731A86DC2588F25280FB465C95FFA06FF8395B0C000175F1A84220A9E7CA1999909ECCDA0ACF005742F1963AE37517DC70DD4FDF77EA517066D6D8154B1C431C0FF01DFA8296448D0A7EA377FA26FCF4FC79812B10DD4254D29855D844EF102FE2316CB890F687A2A455E364E221DBEB187BF2E2A020CF6AD4711E65E28C03B6845D742CD796702B4DBCEA0BB1F89FE3F0FFFD695727CFA139E4E9246AC958FC84662CB44C5D5700163F4FD8FCCEA8C5B0BB63C0FC7B2A1688AA6EF0FFD27B2D62F1930BCC3674FA666718858B7845159BFF33D4763249FACEBA0BEE209B2F7AF3222D5B8E5ADCABCD91D73A36DD04CE22D5F8F8048719B5EF68C68FA47F913353762F6A1FC90AF20E831DA6E14F047DA695EC8D4DDD936E403B7B819CDBA85F21F815DA9BE5F52E1E1D4B9101378E4A29F42812A24977F83A40668F1283816F57B997FA21BE884DE5F84390DDABCF7D80FE61CFDCD553DAB357B6FFBF8703E3E6DE32372482A718D014AD6DA71B88B35CD603B7D98594C82AFBE2A36F44673B38611E01DA0F544DCD2A11A8C49BD4B8B52A66C47A65C1784984602EB87A516DAB858412DCAEB954A1C2728BEEC918517FB3BB1BBAE120D37700C605464501E136D4F5E3039DFB149526D0EFC9D4AFB67841987B6689A01B84CA7ED6D9F908C0CE3787F0067598FA38A67BDFB12EF77B2894CCB40699E4B07ACD0F9AAC4B1CDE7E028502F2AB32D7390EC8A3E112A58D6261CC60BBB0FE0704B91423F56976C2A74CDF4D5BF996ACBD8C251F6ED9FBA87D3E54480C387D9F8ECC94CC59D16776A67B5F75CCBAB648570B663E918D7EC148A17A6B370A1DEB9DDF098A68156513312625C08C1C7FA739A6CB9BBD79A8C35295C8A7BA6610F4F0DAB043EDA5D5AE2A410ED3E2ABC62894E60BC692858D36382A6257CD7BF5E0E4E193E0C8D54B088820D656188A3A7EA7AE4B80CF3329CF0C80A5DB5A43E2A610F755B58674A4434AE9C3B9915040BACADD77C9832EC600392BE24F3C68E2BB2EFA30ABDDC55AE6B8B803CE948548E466E235D4DE298214A795FA827185A879D308022EBA5F972F4E4599F4A6E429F9D2540A77B4D831B4E4D0F6164808700C2681992DF957A7788A924FB07777FACDD4BB63E7354C1271D297BFF1780C7616737C97DBA24860730BAFC02A0B440C401552A9E86DF6A6D7754CC3B827B6A36F93F850289D14B54FDD8687A418F2F4442C6997A4902FAE75BA711F40C156E253663D2D7D21F8C89EBEF1BB92F0BE8DA9CBEB1743064CBFC223BB34AE960E735339BE3BF22745A21129AD9AD2A9A6E51D915F5FFA31E7733837903459FC2F4FD6D5B97E12443320C4CBBBD80C7249D474DDF5E6A80D228AF2D50CCB6D3029801F9821F7A2FA7F020AF4DB24C784BC7695CF06FAF88C1028AB6EB7C2ECBBF5F17840F54D553ED92F4DF0ADD1A450FD58EEF4136CD1685A401D5A2111DA9378791D13244DE37343A179D356B810A2B76AB88532FBE04CB79F820255D964980BED73086945079DE17A169D0AFC04ACDB3587F0727DD06863736E7EEBDD36F843E1D2E7782FAA70CD299D20874F808E7BAD987ADBBF6923733E0CE95D7ED0DB46BA997F9E9DE6138A45CF6029C3386E094DFF72F5EC9AFCFD6D43654F5DC0C2F4D516FB8E6113262DAF81220243751638196C9FF636DDC0B2E5072969DCA000B4749799DB3C1CB0000000000000000000000000000070C161920299C311FF20F574CD9B7BCE1DF705AE7DCE6E7A621C935A6E57A59EB31FC443AB1E014AD332FA784583260AA6153C464565C4568108D60CC126F6E8EC3BC9120E5659C86CDA8A31A7131936DE7B3DB39A4692808DC3D2BEE8A99880FF9D1D5EFF1E825A0F043D908D62A99779E013845AC0C21ABE8E4DF0EE901E4C6BEB8BB36B30228B7756D617A8F30C16351D8FF91786F7406F75D9FB648830F88EA4537F42EAD62E8790E9CF11F72C31D718221049C9AA35376AD8FB065F4809F4383A23C2B29425836C2DBCE4680450896EEADEE6B83539ADFDF59AA4FCE709D601640EB9A22DC3B41108A8EE1FCCDE9945EBB1D3F676EC8395255E125E62A32149C73451F597E1C32AD979E5BE914FFC7C548D6AE92ED08501831E9007770A0233E5778F22ADF7F1AAADF9C9A7C82D2F42989BF21627D3EF8BD0377A5BE5C9F5A585A246A73DE4340E6B43B36DB775B34033962646C16F26A2B7179C40A721FEA54805B9EC42177B42160B1A67341235B5AF9F30B2703BFF8CDEEE5BD7CE506B0707A69F84225B6E5A92E80EDFA235803DBE2CEC47CFEF0D9FAC95C3379816A39F4550BDBFB45609C76D0351DDF8D61724BD5E8BE94673B3013EEBE172CACE247D79925B12B5DBA2F6FB72E797B2DA849B79DEE3DB76775F5F1DD4595678671C7B18BB3749FBB0C6A7135D639F16B3864B5A251114DE7E9F8CB02B4CC69902EC8D7D544D98E24A05F8ACCB182E2EB44BDE868B077B1FAC4726E8B01CDD0D024405665F7ADB60A23FDBACF421246354E824CB74DFB35E57902794E459493905400D0A0BAD51D8EB94EFAD55C67CD0C7CEFE7A1B055F06371AEC7F490FA685C611D553D8430992EE7B1855A9CB305B5CE53154345D7DEF6110DDBDB5CB59559EB664C6439E057DC022F8686F2AA0CA81552428437B0CEB5FBB5DF254036BD2BAE7290D947C963046771A39D2656312236569E775E7D2A041B7EECCEC99C1B9D2757C7370E474012AE707AE00AC37B73ED9C8E1A2774E54BACEB42E8B31BEA734463CC15576BD4F7A33430B1987D62E47473391938312F2481838F286C4DFAF701ECBC6EAB1A9F074C1F8D8963457DFAAC9A9A8EEA70C50CE70D1BA1006760AD3887605EC38861DC1A777D21E46EA169537057CDFE256CC08699D73B1AC4FBC62F863353581CAD358B9C573D77585DF6544E5D55048D66A352828CD1ADF5F42310FFAC022A25824430F741371027B2DC14717DC87342A74F0038674187E478D8ECEFFC16474A4AA8BDA0C8D41962EF2A4B64A036C888CCF4EA628E1CB9EE0F9A918FB1B22B9367FEEEE0218C83CC7E27C5CB2AC64DC7E111E3C85CA0E6BD4F685E5DDD428E028D192142CCEE3F0C8337BDF43CE4B62704AA53C703EC334FB56FFDFB81D7D4419535D17E5FCC0E6F558AD82149C591FE0357DA15660F61544B4041128218B6DE2B75D3801510669A3977E2983BCAF957EE2942E504C29890A81542EA208E1CEC + +count = 32 +seed = 569B8B9BDB707B19CD6F9BEB29F304D603C1509B9CF25987C280C342E870B1E13EFC7DD7E41DC85BF4F42D0493B84B0F +mlen = 1089 +msg = 7FF38725F35312D75E58845FBC33E112DD95D5C1CF78119CB413AC839377C7051BF5F17ADD1484F5EE12F42B0587AB41DF487BA5E4D8836777B614A9931A5FEFDC4AC451662B342D675C940061C4FF01F747B69CFF585FC5317636E2A830140C0007F73C76FCAB96195C86DB98E5E65C733825DB0325407E5BB059490F2E9133F9B4AA328976256EAAED2FBC59D00288D4830D99731A3AEF36E5BF5239F2899C500F942B80B00C3B33307450FF0C105BEDB7DF84231C5D24C3C3475AE2F46336582DE93AADBFD385C824F21362C19B1C6A75F56B69297FB3084B6164204E2348CB1D7CD3AB494BFA7EC8FE346251C874085F803BD7F4DDE1995F0D3D17033C461D06B49ECCEEE0D5312C3A435AF5BEC9808ACC524599668AACD95ECEA7EF07C4CA3FAB1CF964FDBA987C345046E6507AC3D372BF07D72CAB816BA627C2BD452AB8DC3044A7F0A01D8C0EA47904A5DD66C6B7EF9130D628A4F2CEA5A0D05AEAB7DAF2729C1041FBDB3C2D17BD66AE293C03E77A0837419471C29691EDFB20CF69BC6260975089AA437628F140A44FA2E2967357AC1BF1345E4208C33CFFEDE6CD634B371E7745143FF848F77E5130D1E0F51868585509F9CD3B906EE0A5072CA2E908D6765C74D9B5C35B6BA784A3EA59D808ACBB1C24D6C088CA6C9E17BCEB18337A4DA0C1DAEB5D51EFB35712A475D6C5A2EA51E93FD79F7DEB127F3418F354DF06489E10B42BC1F20651660CAEA17F67F306F48E15DB7E67A1B56578BA7BE6C229FED9567E128D48551E6EEFA17AF5B95A716555571F44FBC41AB29208DB7C1846E130866D5C9BE6F73E601C55610DFD0F67D98933D252059DAA1DEC20AE0E5BED6568A6322322D8A40E6835FA66E317733E1B465434532EEA8FA76886B600E06EFC1DA41F8DCEC0A5E8BA8419F0B7879CC0A93BD14D99608B5BEA931D8971DA8D2D89053E1DE40209E257E741BEF48C17FA15467F1312A368D4A061BFC76C2B7BBD900B4A34DA51B7CB5BD6E2FB08806A53C0D60273167D822FB6982785F2C3B0EC7D893B615724D0193928D0EA8EA2A1DEC5ABDCAA904C754CB7747449E87221B3D86BD5DF26E11DA753E768A8B481C306E485EC91074377DFC68BE74A444906E420C2D8BCCD84BE13AA5CCD11115B669C89E9C0CE374BC4059C696E5F8344FEE467AC8C8ADE37DAF614992914C763D971327B60946943847FB6B82672CC376B780953B6F4433DF69AC61E110FBF1A35F6272561193D8652EBCE3291333FDD4D84B9CFBC60A57E1F8B817E84EA15D440D4A4B4F7E19C08DDFC5949FE8CBDDCD0296A62F12F53D48B1288B80E24C756FC38E2FAE9C7A3315D1C6DA42AE838AFBBF5569F633A68289EB7073BABCB210F4E08856FA65057BFABC70AD3B58C2C870DFB5E1B0D11B6FA6D5BBB68285D8F9C21BD89669781C9F4DC32EB1EF58B80B1D371334D36FA66A2B3DD4B3E4DEDBA7AA9FB7E0245F5FDBB66CDA653C5232A131EC1F0C21DB1C47B990A64A24DC8C4DA951F419F57C03FF506E0147C22E99461 +pk = D6F7AE243EC019B388BC9107A4FAF40C66A8529A3EBD79E9BF4118CCC9A3F92C37F4905CF5128D97ED374C5A1E185778DBFCD4E845848666567828DDBF5FCA1576814849FD9EAA6DF2B895254CDB42421AA96FE273A6FF721421F60DDA92F176047294C37B797462AF05042E4915EB0C8F18D3CB9E6055655AA4790CAA3D111084A284A5BA5BF392D557C1AEA7BDB9261580AD586139B03E3FF44C61467177B0E628557899A1151AD61B0ED8F58E0EF4292D0C6B10427B7E01AF1934BBDBD3F5541C4C1A8EC9AB1D3ADB1A5506E8E8F6E29F03316C249E614ADC520EA7589716A3EF582101328AC677598044A68B559F564ABB17C6D311750DAB2EEF57EF60EB08C07F10A02D973DBE0ADFB2229386DB23D25B8FAE69DC1548A8FE39AAF89F7A91D25F8266030F07F0042883EEC8B1FFAAA0D8C7E5CA7CC3581E61F113E1AF0532C1EEF685AD3FC13500482ACB2EBDB383F7FFE63D37328D0AEEE559E4A93A163784B32824B51C199C7509459E5F611540DF0EE9F03ADF6D8CABB4EF4409A3D80DC18DB5ACFF29EFE06AB1685E9A5A694E3DC6240E7280C0C10A1D390C429C85EA090CDCC3C40A3935A00FA9A2246FAFED1CAF6856630D9F8522011342B7320C8F6CD05C91B9BFF029D15FCC44575F5C0F09F4D0BB27D7FC371FFC745A6D90A3434090833479FA79552A4787995706A5B19728C16B515C51197753FE0A1608DAF62C1D17C2E51CD8559A38B0761BCDBF0F6CC4777FF4051C9FC7D4907DCA504A9B69DA5CC743E1EBC05103252199AAF6C9244F16953A0C6B5EAE4FEBDE45A8B905443138268CF7418522FCC93BFFEA0BE14A22FE29991E65773F64D9C2086D0D25639FA3C06ACDD06AFAF0B91608C49A848E65D2FD89050D2CD7A538DE36CC4A06F9AFB82E8CFC8D38890858580B4EDCE655A5B4CC83445B0A77F38188DCAB8111E281BC79A2C60E32A63A16F3DBEC5B84A3C775FC8695CDFD20ACDEA68A1CA0BD4CF207097E7B191D961BDA343F3F77EA15851ECE9D41E3238ABFC64089E9EBC8632AD707FBEF8B2BEA2F0A554F0D22952287CEFB196F1FFE45053F34A2A27DA15AA6FC31C53CE1D9C55AA130F091346EC4DD02B1179B1D21F6649E7554B40C43979BD8BF56B1E805F833C9C67DC4E4C8D9176E11850C98E80FE9D75A23E72D1BA8F6FC66A4D21312F4F3387239BE3C2DCBE2B3A0EC9861F744F8982741EC06CDED61323FDCF4377F105F3B11609B2C5645DAAC4F7E4E2E4EE2BC7C5C5766B8644CACBBF7DE6F6C33C20D0CADFDE85C7A77C7FF44DA42C1DA98E199A502AA0FF317B652DD67598A27649A5E9B54EE96FA899C4F20ED1665578979BE81B38CD045AECC358E2A0EAB9147E5E49EA6A4956C2B97006A24313BE230BD9D0616E09D597E4CF546E63324C712A97C0EDCA9D3A7EADB758BC518C6FA2F5105B2937F4687401B8A74C27B120BE956A625D6660264304163592051FDCFBC789EF7314B373C3DE75BD80A6D56F466C5A865FF0222AE0F5D2D4B921E2BEB785230D38FD2B3AFB98E5FE867CCA8D619CC5700924B1A87B1DC031CC9ABE552018C98EB529509D0858C5AB92C48E6A01ABB72619493C411D2146814092318233A0B7ED02BA201453D09FE9FB11B70A2C294B29F5CBD947EDD5E17C3D1207F690537426C0F9034D3B91E361F4C82BA4BFE186B7A88C39C7FEDCA0A8528B14CCC453DF2938BA09E0F655380431490B96D0C726B436C551565A48F6BAF04ACB45003E39103E2661700C674125568814000323CE4A2D5B146EE4393BD7509EE17334ABC0E1448D645105CC60E555DB0B67F77729ED771DC34EE35A69BE2A8E156B8FFE1AE4699464D07EA42808D8D45B2F649A7B3E215A834174FDC3FE8C1E992911965DC84A76D365C8FACEEFF28919C41C7314DF061A5D01E3073FD31CE27CC190F3E9358E3EB3FDA17979DD3D769A584ACEA37E20F5C32B1DADE5C77B1BCDEDC2479D212493EBD54CA576D88739ED149E51E65F1486DC7C181EE68C4EE21AB70FC526EA21722C71069588D09C7D2FCEFE00A5A4FDC80008EE9371C3FCAED8B76E2699F4DDB45E6508EB33950F499DB8306A33CEB1D65EDF8D8144FBC17E3873404E72D6EACB971CD22FF1759255F017A5604C203ECFD86B864370080415CDE70CA1AA2CA33630D87866F16F8C72F1BE0A3F1E6F15C5EC254438948B507AA18DADBD4351EC5172E639DC436BD56C8BA6854892C2A643FD40BDEF14FBB43E40FC04236CBBCC6483B6C62DD948A0FBAEBC3C52F5401C3E2DE07A13066B18CDA35966E501C6D2B65E2A8883D8123C35E31406AB0E87867D0DD4F43F6000EC5082DAAADFBB4FCE8FB2BE6D5131CA63A6776EB8D310BF863919CA8F7E210ED2B7F443E60F7C6E99B7DE55EDCE99D3ADD43C3605557E3123C1DDFA247957CF99CBEF5B54A8A3855580DF9D8091E3AE9E3FD195F55D257B1525CFC8B98AAE1CAC943616FE8F3D3354360D21B1F1C8E12E4E1E733FAE9A5E089BD129F59CEC9C3EFD72E82411C6E1C66BA543FEC45F35D3369BC75095D7AFD406D6C3DCFB4F0F9FD7706B590CDBC7700BDA82AFDF9B62C08B35FA9CDA36D30F738B958811F6E30596AB90B69A4E3432FC4CE95895F420AA8D66CE08C803B0110084EF1170E7AAF644F4796C536C288D651A1319E0A898697E3474ABFF7D15799B1869616BA2E51E6931F106CD30EE7D8EA20E29846CDF71A0634D25CBFD9B3CC142556C4CF20F2837BD2B97FB41FAB2CCFFC +sk = D6F7AE243EC019B388BC9107A4FAF40C66A8529A3EBD79E9BF4118CCC9A3F92C893E750E0FC5358C143B68DE7E501E099ADDBEEC619D3B3C2EBA63BF1DDD49858A4CE4FE49DFB5FEF1B3EA739D73662777E1A5CB6FB23505A7D1E2926F2A5754379571F064A48BA16502275CC5A7B5013174CC144783AEE0C179588035F07B37575228216637324157301486622751810842446016566508378662346074116473682504728466862507022315016717470667376788342338686702354775540445265858215562136465606410072140611621326108441555678358155152477256565123685274434366000684875544886453855283565732441816482814412751121668570277307104783047751436257875832157623123240758061177452428683345124462718447661468477636704246030463576214047315135121701432302031481764743387640841068608510688737038884357202421570168108246757634172657281586075507240043683111841660277701330756263868887548183261636812756062021113722360843788603615608881281235640174052525157008832046075211712714850130767865520010670705422146821650531352768458048757606361841126471045843167008224432863550051458833118805214582868784060384061766142464887186764880354311863041640171681312112760152717143621634452143060352327337784225874358522182873842043536500730817110856145770317786174587278261143288887162356764888247572103121145787323167563423634854337710250578465815520088376880248071750545844434080168704052405386727846377806078188413622216286630673150602778716155180016720138863136888340278654138373483781850316414321635387573023430104133538286710303307376113235042506002476602607016271420268815686708372828335452341277451871463143824126332203436253162535136054136466867167346454783414168671787060464377020744823008168303538773132455810215341800735173363354278556447671525076733054415801555202767647362020088843451772764718188370502075140806113576700607106880146425061080271518680384412055330664175656424235146481078562775062328878133762008647707148552547745518462312700423066827237641545743458630408403512725074623560888086844275021886866643571172437468173367812863878403754403047217544767436485062022708123202876731480505737745100870542478066354473476808173170756275430730606611210834635863547721432482582062578863675744713377235723803487852126581378768324237312523142866056552681248586720143030247434064015743173604180543066877443642437665114856608432336570376774084488874615364037570561568417268103411805483056673840200666366860332220667846833768330717845587752454425145436764736443180638442042060113185734417154165411363627183335172554335724821634306263154700604688065410844710480586754514718117018112572065660261401718454026052512110046016178533176624062464378612181175368172222861083408556548586662163550205445371810356727482412724510434620736218438728264815217386007750273362602042707126407828310551850734210200482512141388275558248032386256134000172111317603648376156048324080377388518588034774044571112630264142131386561213614560723016348014757456401646737782617412422252108137746777773174067650117217454464047373256136231681132566737601773354771165064436286140412736465855447476213885505513835352436756181212272850034420550043676184020435612420565274263854373000407255318050738226735646116137456E6569D7BA93E90485669D1746BCC5F18839F94D2064F36BC5138BB800F56B69EFC294221398AA47A377F7EF500F16103C68CBB54FC810CB696D34D6F4AC5A61A6EE7CAACD9387D8EF40BF3C17570270497728FDF29CA1BAB707A2FC9194643203926622AA16952B211F0EB0C98DF84F58528CE32A370D6C000926DAB4D8790074E15E177A7546ED95EBC918F1CAFF37C8E16470F27F0AFE3BEBC40002674EF0E3D9CC7BC7C2BA242B61D003297AA53FDEC6AEA5CF2B1311C36361B117C6B0BEC4B40384FBC0490429ADEC8BAAB20F4614AEAE5198223D84D1982CFEB997A7389E29BB518E0F3B3CC91984D24672E686F4C36405C38A7720960026C3B0E733568C64C8365E17540E960D3A8ADDCDF56B183BB90BD387F27996D6A840BC9A69A87DD70B7E418144C73D4CA00BA2292FA70016DAFD2EB3FA10399C048B3F2E937DD283BA79F8AD640E59E46562381CC57B3F8754A0BC2CE36D55342D23AB622A4951D956672D705A91AE1DDE47E973AF4CAF8DCB947E329D1E5F37C3DF786ABC43375B765D01B2F4E7CEECAA673B5B84FC29EAAA9C9F77FEF44C4D563909086A3F91F31D01B2268504935F7195DA4BE2E5EE3130C2AC8C227DF27B05E97B81EECCD07FCB1E4301529D12A1A207A7076E0CA2FC40895B172C7044C26CE35AEC20916D93AED5D4BC4DDEFFFCCEA520990340C00BDBE56ADA7F4E13053CFF1681A8FC87A1122031969F7BB78AB9FD3F947474179CBAB6589EEA47AE47B10CB13C769A5A9BB80B247345A2317FEE10188C8980B84D2E2B997D14C0E3ACFF3D529149F5741CDFA6C727BE8E886B3CBB968F119C6981481099747BFBD0A54C73E40CFD87B2502525E748A240D7964374BF350A5DB7DC5A6ACF343E4EDC8FDB684FF8FF5660E9D21EEE3A9E73FB8EB87BB80D88564022C2CA81B3256316C8FA1521175018873FE268580F945AF8B023E785AAE80DECC1D17A0F49A050DE8995E8874A1CA0507FB6B4EB9CCB9EF92D5DA61C131DDA90C9F0437C46BA9530E516493C53B3DE47101A61E472A4632162DF14AC782F4446583361B88DFCA09834F5963081523F3C6A9103F3321CD9C891F0BB2F794F3283023FD8DBB8663472CB9FC41076DA4BF11A73BEB9408045936023E63B3462B2DD99A0BDE73C66FA5E59EDEB5BE2CEFF425989D07916B2D56E23F2F2F12A9E4C5C3D154D9102EE6B3D347277B8F158874EB4B6691B700BF53AF5967AA685E4F989FC7E67EAC9AF9F4280BEB93F5160E5E63C6801E70980A18D6904FB748287CC52B24B5EBCFC8FFAE4F87D1BD832648D84B83D86BB9D16315AF0109097ECC1146552F5706451C594F3732F1C61796F9B6E16DBDFB42EDD4515AA3C0499E80BBD8FEDE5E450D9DCFD36D669D53E1209251F4ED6BD15F76A92E5F037A16FD43D7E3ABC60A8F4A65BB8B5B7F85AFE46D89BA023EB802E49F14B5AFA2DD4352FA4DF2960A9CA10F64B923E484F9C959FC08389DA42A5221A5DAF592882E17D4C0FF6E1A59956101802DA59E59CCA8F0AF346757D50C10CD5B566EFC3E7D0213DCF8EE6ACA8870612860158C55356EB4AE28041BACD207F4BCF324F99C2004A0DA00323DF44CC3A7CFAC84514380380D357570001DEA1B17063B717F4D11C19502AE8AF28C7FAEA6FD6968CDD8E80100ADCD7885E6C8FD92CE966AC98F3391B62CDE9DEA947641F279EADA43901239702B03C84A10ED204E28B4EBBCCE3B96DA573A73333C8F5AE3DF06ACB6308503282E6B81067FD4D2B1172DB12652A99B96FDE2E43AD4E3BFAEDEE2E6D47206BAA094593C7865E73CC78AF9AFD7992864B17ACB0D6CDD40E15B4BD0619F987046032FAF4088338CD0C52E5B8DEDD4E2386D8A0A1A847F34645404C159D7E7CA016E37C00722C928C10CEE22F51C68D630D8BBE1E4372E9228DC6E3FC79A2430ACBBE433C523C1ABE7A06B29491A51114EA5C6A8DB091D13F278A0EE443F709B76C9AE2712E021BFDDCD896A6070B87068C17AE3C46E770F1022A4AFEE9735597D8A406F36CDF8A5BBBC279B7F09DFAA7938E8873F9E94EB87DB172A76966E3654D08557C15DD9F3B9AE1AF9FE8568A7EAF612F5CF68B2487D98978303D0A7B8699B48E322E3157276CBF1DA7D289871E8A92D72CDC0356AAD2B59F71A87CE2D1BAA2F9A642F3BCFA36D7CF84C28A7773F3AFBD5CEA5138244A0E875049D5F88B70B6AD09D4A93FF18495F0EF51FD4CDC52DCF646AEB72FA1311545AB1B0E58E5D2DC3340F0B5E50837ED817C85F02BF4AEE88934375884C968693EE14AD593B3F069B8151937B1ED21DCA581E2E091451A5FDC6F41BAB1C2705FA3297278F193F46C76194CD4A7988C265D68D8DE13C1B4A0D37D050D846FF30625F60014BDF89AE824F3730552434073D9DDA6F67D420220D2892C251AF4F3B96B079BD4A969E499870F822D49FF6239B2B432F713F9F72E53E590F4ADD459E68FB85EC2E72309B0B13A94561833A659FF1FB3184FDB85A96D5108434B40CD3B706EC4FF48DF8D5CE610AE1CB81A00873DB199D1224357EA1212B521F095A48E482712A02585762BDDFCCEE85074326A783EB9688C0791A04CCF5D24233A5D4D901C69F28CAD400C0B047145829503A98578984FF176DA46DFA74285F572DF614F651A2B71FDC7F5E9A0C933277EAF3733C486D65D064F2D8EBB1B81B124A3F23C02A0CD9F31D7CD03150EEF4DE9F0D1931B3313E447410560E788E6BCB7550AFF804DEBDD1C5E1E59EA48B97EB20C49D4F4B6AB9DC1FC1A0DD351568A21F712EA23E5FF459282A4493A9C78E5498B3326C0BF5FD8B9BFDDD87DC0D09DD7906DEA4346913D97BE92A020282A52FC0166521BA5314C5B1DFAA41713C2F5A182671D6046ADB097F53B86C213095E83558A559A0573205D0BED3ECDC4B3A36BCD8FBFB3E7E94E434555295FD1D73CEBE2F0447098A4BC5B2C2142279F505CB5050E6BDE9238ABE4EE4D3C88311DB2C629FACD5C8F2243E40649E54CB79D4109000A123EC177166FA19E4C01B0CBD44909FAAFFDD0437F022A22C782621A2D009C42FC22E79A2345BE094A6E5F6F53836CDC36F465BF5EF6BBB282A1D71D21CF912AA0E63DCD4468DCB7332D20CBBACDA0F5967F42B954959114D298CA4E0468CEC7E37905FBF13807EAB3A6889F9E1166FE2A59BBADC4A1F6540020B310DF931C361F0F71D326B1C49A9EE5DF4DB73A2E118220E8907B8611E25F22E335A010F6AF9DB48F4C19028C6457FA188684609D1B37B6F3C685B1401B15C41CAA4A0943390D273358234B0A73B3C5CB2C69D60CAF1A5C39D6F1D92141CCD6C3A43F66298BEFE82C2B082C59245B09E830D22F809709D632AC4B353A03623B7A93B95CD090F44CE6B09AF4B0C744A284583E792BCF0636EC8FED8E1FF4F8FE04669F808B8F3991A3247B7E83A46A8F9B56DBCB6377A38ECBAECEAF0297B925179FEA864AAD127FAD5D6604E09EC4C59DECA4256C4C0CF78CA0CF2305F185E52D5DE0656BD72DA7D891EDAAD5D9DCB6 +smlen = 4398 +sm = B98CD28965AF8468CC0E1EB516A3E847973A906CC375660B5535E2F25D2FDCB86571A04383079A628DFCEBB103C39FC5A467641668701DC2BC5E373984B34315F61ACFD7B34457DB31549E0752E3BB8925486601F0DFC72EF9CBD9047CDCF7C0C1635D9A727038688FAF4D5C0E83658EEA55B01DFC0FA166F728F424BE794948F3C2A12FDDC83846A659F6A077F27F50BB2277BED37919CB4AF8870D3FDD81744AB9BD8E8A5CEFC8E845A729519F90F0A04A5EE454EA63FA56DD8F9450A95D77B73E9406AFB41DE618F1B72DCF2BFAF5B0E9DCE564DA1DEA465491526BAEDE90E1EC596B66C9218F90A3990C877FF69DB645B4B926C29616CDFA2F02AC41B46D5E1AB23A394CD7CA10E0805B501562A6BD4E85B8D623E55BCD332CD1B6C06C76118DC8A33E8DE3121827A646B3E6282D1FCE8D38E8213722C31A1707611746CA83ED9353B8A3DD6EF5070C8EE31207C995F97711941ABB3BDAA4F5DF2E931939C226EFCB65AB0C6049EFDA11D4C42D02AE1C25EFEB625DFC00D2DA164222806BC0B6306AA63D3E34F8A23D01034A56B0466BFC3C36595F77E1ABD5D1712DAA69F1689B717C2BC9CFF8F0EC759D5954A10036604B34843A2F5B1C51E38CDE004A4C98336C0231F1F441478C7CA5A010C26BD353DB815EE57F146F51C0347C22502579CAFD7A4CE129D55DF70C19002214879C349B1C440D69E6F2E64492D089D9E98890AF4DC141B5185CD0779D38F43C7E23CA7B27F0378C22A60702108FAA91BA45F30ECC70773A3FBE2BAA681126AA32BC75A9833E3E1E2DD98E6AE943DB32FB048F04792A82039DE3DF94A16C1ABB82355E5CD1388EC83C07386DB68AB3BCFB410449CAD8CA11A8D9891C3FDC302FA44ECBA98EF0510B123E6F1B4445786A77962724B5304F6820AF20B978772DF361B829F9A3AB83915DB571DEA4B5EA11FC81F41E100EE204A81EF9E261005982564D76DFF744B199D80CD4D4EF332F722FDE317A6E7919BFD35FD031CCFF8CB8DE377F975008217CB1C2F8157897DDE9DEA34EE705963529F97C4035FDDF19C4C3A24963C867210438B8D542888400317DBB3C42845674AB66D1EF53AA409289DFFA6AAEFCA4DFE555E550DDDD3B2BF5437DA76F063D135DBFBB6545CFF083CD72FDAC58396BEBB7F515BA6512240175252BB22C8D309F0FA0761E626D52F6F947A5FB5741070BFE6D7AD5CFA6C9134DEBF29E3FCAF483255443B9D4A36E8E02D05FA078C2CEAEE63549DC74A6286EEF2B2ACC595030D93726AD29606AF85FDAD4DDE398631CD71629537906AEB4FA95E563676C0934113CCDF15DA19076F9245D64415D15BE09F9F4D6029C5DA39E5F041133B8B420D0D7DEB6EC5567980C75EB3754972631EF9FF2EC90B3ED4F68A1E63BA3B3CCDA7A956BBFC3CD5F6B51F9633D32CC12BE76FB050FAD8844F9D2DBBC81562B6A7BBCF57BF1AC3172BA9E62249D9904A91D51C940BDD3BEA7E0061881487CFA7F72F57251DAB49711C78058A0211C150C660A07F57669C133FA334847138D4AF4B51CC8467573EC66D131C926BD922D0A69301F938A444C63E94EAB644EA415D92ABB60EBB1E572458DA96A51A2CC4C67F80608F4F795DE5846870622099FC99B0E6ECDC3BA0E40C8577215C92890DFCF02D24BF81FE8BCE9AC094FF2DC5899880B29A773F7D488FF853DDC07AFED5ED7598DF8826D494051D2AD8D7E7B411E9A0428C6508F39A05D7CE062EC18B7001F95EF1679B680B938E97EC7FB4FDD25DA8158B8FDC98A17C7F42976562E3164CA6FAAD9C8B83E160428587413461653136E53EEE5DDB9B0805BC30A07067882D8E4C24CD91233EE23879442C0B77AB36D2E74993684D0016004C17B0E34F19851EB66F1E75ECB22CFB76B7DDF4B828E2A2BDA549624FF24C9F5A1AE094CBE244B61A664C1EF169FB4E6A45B8E3455C64395376917433A7EA11CFB10028F6A9C920D48F7881EE0EE7B5244DE56D84FFCEA73674F8ABACFA4D9C188F04029D46FDB168ABF21D3282DE4ED9166A3E917643ED20C134F9AEA94D05CB6A738D8E0DE1AA531BE4308DB303103ADF3815418E08C66CC5F1F31D7344570518D4CA8B1073A1A74C12F861EA98BD5C0290436193475A14FE59611ECDFD6ED5CD2F80B69D4D5704368EB574AE4DE2849C335D6DAE40FDB22762C4263611DB8A2224857F4D0B63EA123D6F99FB058288D0563DF552E65A50F5DEAB99D179629EC801FFFD3AC7296755634DA417DE036B1AA63F77A3C61A47B5AEAD2885357BD0E5F76C444A453AF7A2C9284C94A4045C920F5EF51E83207D20E7E7957EF828CA3B7022F0AFA1EB1C2119C986B0E8F6B5CADA39AFA4BFAA5D2B283892DF14CF3D0277D3662FFCFB0A65919D5FB0673054E70C0385C535330B881B0792443D84C8BAFB6154243736BBD69D1FB53384FBC3CF388F8AF0336D4473A8E1D3D3A795256C3D48B8DCF6982AF75732A7EA714C246D3A2D06FE7BC81C15136B7632B56E08803840E561DFC72839ADC514E95E1CDFCAAE5D9D39551A3B14102089987EC1335A32902E219462B122DA42D04E072B8FDC92C63B906482F76DC45D16160C62736A0781060C1B5F17E2C12DAAF905B3D360B502C411E63B739CF1EDBE0B34BB9A9F0B65ED4002AA3C90FA18D6851C9872AE6A603410495008ED017F984999E29C3368EB690B2AC3C3C44C2C94885A4CF06BBAAD059D2B202F1CBB01636346001D5336453442E14F53BC5038D696A3295ACB04C550F5B5E287D81206502627B75D6005C13B0238A0039BF42AEDCC8792303D3B28A74FDA4D0CFF817B937984C1FA453131F766CA831780EEBCF00CF3B5434C6D2265FA48B0EBCC56A746924FEF9B20014C2E4B3D41842E0EBF1AD1C9856F7E0313E1859468276342D8E8FCB3F424C56501FFFAB652D1AB9C90A90A73672FB2C9DCD80A0BE0A8930768A4821E1446511046BE2E89B3F2F174E1341ADB5B66F8FFAEDB46B0031D7D6CD867FAF3EF40217AAE19E98D01E0AFD4FBBFEE6E946B03114B9A3EAC0AA981484674FE68E96ABCA91590B51438FF97D678811D491FF49F1F105206E90341A098EC845DCF1B18F948632A4F744D6E70AC67845E02EEB0840F70FCD49DA0D33ED471DB220BED11484182FA2B263072241F30CF2AEDEB0090714A1B5E658196C9723225B808397B9C9D7DEB1A61C5CDC2D81BD7165584219390F468A583C1744274001EA650B922BEA5D814B261929B296C4DA7D4ABFE3A86632FD6ADB2B4B82961AB7E4316D2ED0FA0877818880C0205C2D3BB92147D0A8514A8CE3C4BA7D1A8C116A09BC3A7D5C99980EA4690DCB6BB52FB29C90402607C15975574BA41BD3AF482C1D8CB237EFFA9ADF2DB720881FEC2EC2287AFFB1BCD1FD0CBAFC3076A3945946386E839AB80FAAAEE937F30712472D365BD6CA3183A7A82C68A22FDFD4A939C3966F51049D3C30333F5A1431B5375D4B2557211E2767C51A820708D824F6D5483BBB28B5DCCAE955C5B3E425BE077FBE2DB0D8C13D90201EC70E83699130A3C74712C75907819B032CE6CCC1A08102EF9661C30FFB8E02EB8321F21AA2D310C630BC907B9FEAC0C392DDEEFAA368CBB32555AB0D774DBD6CEB358B4760D3F6ECBC7F5BAD7A1972DB4CD05A92D5F5C656541DBC321DBE93409C8A2579E4B7066B490283BDBFC4B0C7DD4F3A37876656689C7DED9B3EEEEF5E6DC979663043F001A946C7691EB699840638D29D9A0D0180D94FDAB759C1453ECC90051CE3BBF3C90D4EA839679E35930F4403A398E1A0AC240EC62C6FC1866477C205EBCD673B0809E4BA149B700DAC3A25B256E241C4D5CC6C145E807E4AC98620D6241B770B1D01D72A08FF2032B3CB8C175D52D7CB8DD64E32954B10335A800CB000F7342D1739E7C2237F335C0D30C2C71F640FE716729F8DE3782B12F77242EC995509C418591B5523EA9C99F50AE62335D502DA5CAD42F7533FD252BF430FC9F8E46913DF1B31BA3BF155FE88510C7949077DCAAAD4BD2DF81530D74D19E73C3749E5A945F210452DEF227ACC9A54A1134A117D952EEC0FD52BB40CC4BE8FC3271D399630B8C3067D0D027203EFDB02D92B78CFF35426E3488B56F25F35CEF2C49A6B5B74E77ACFF20F7272F7B34EE8628732F89AFF35D058F00B9E0E4A5205ADFC781A41FB00C1657775FC10AC5F29C3B5D6B70DBB389E7E8DF723E8B1181B1C0EFB4422EF4B21AB0D7DB54B6133D3C4F9A05D88322C5777DE5D7E5820070E171E496521458DD0241CC44D6C2F83F592828160E7ADED0C6BABFD03996AC50AFDB55ED67FC1C184A20E7C370989DA4AA554F8732ACA8A380160A406BC1B5638C3787F9E776D63FF4CA5BE8B59FC84C2F40B604DCCCDC7494604A16A0D9A969D29F9CC84451FE462137879A08B6E00176547EC6ABB4E0854A5408C981B071F0BB644705C096434A7297BE8D2E2C11A57ADC47C64B5B65D56C6D16DAAD1418F0E3A54BA67F8E742869FBB1D9367ED228B58A00D543DBE15CDFFE1E38B43CAA1E9E131C3EDF731AA55E81D4782538A453ECAD0C8428C5E129C5B0BC061201D59B43B5AFEE17FCD09D0C244B4234D516997E1EB4A60A2DAFD3E5B9DC3E329415072A5B72E5A90E40532393A456B9394E2EA000000000000000000000000000000000000070C11171B257FF38725F35312D75E58845FBC33E112DD95D5C1CF78119CB413AC839377C7051BF5F17ADD1484F5EE12F42B0587AB41DF487BA5E4D8836777B614A9931A5FEFDC4AC451662B342D675C940061C4FF01F747B69CFF585FC5317636E2A830140C0007F73C76FCAB96195C86DB98E5E65C733825DB0325407E5BB059490F2E9133F9B4AA328976256EAAED2FBC59D00288D4830D99731A3AEF36E5BF5239F2899C500F942B80B00C3B33307450FF0C105BEDB7DF84231C5D24C3C3475AE2F46336582DE93AADBFD385C824F21362C19B1C6A75F56B69297FB3084B6164204E2348CB1D7CD3AB494BFA7EC8FE346251C874085F803BD7F4DDE1995F0D3D17033C461D06B49ECCEEE0D5312C3A435AF5BEC9808ACC524599668AACD95ECEA7EF07C4CA3FAB1CF964FDBA987C345046E6507AC3D372BF07D72CAB816BA627C2BD452AB8DC3044A7F0A01D8C0EA47904A5DD66C6B7EF9130D628A4F2CEA5A0D05AEAB7DAF2729C1041FBDB3C2D17BD66AE293C03E77A0837419471C29691EDFB20CF69BC6260975089AA437628F140A44FA2E2967357AC1BF1345E4208C33CFFEDE6CD634B371E7745143FF848F77E5130D1E0F51868585509F9CD3B906EE0A5072CA2E908D6765C74D9B5C35B6BA784A3EA59D808ACBB1C24D6C088CA6C9E17BCEB18337A4DA0C1DAEB5D51EFB35712A475D6C5A2EA51E93FD79F7DEB127F3418F354DF06489E10B42BC1F20651660CAEA17F67F306F48E15DB7E67A1B56578BA7BE6C229FED9567E128D48551E6EEFA17AF5B95A716555571F44FBC41AB29208DB7C1846E130866D5C9BE6F73E601C55610DFD0F67D98933D252059DAA1DEC20AE0E5BED6568A6322322D8A40E6835FA66E317733E1B465434532EEA8FA76886B600E06EFC1DA41F8DCEC0A5E8BA8419F0B7879CC0A93BD14D99608B5BEA931D8971DA8D2D89053E1DE40209E257E741BEF48C17FA15467F1312A368D4A061BFC76C2B7BBD900B4A34DA51B7CB5BD6E2FB08806A53C0D60273167D822FB6982785F2C3B0EC7D893B615724D0193928D0EA8EA2A1DEC5ABDCAA904C754CB7747449E87221B3D86BD5DF26E11DA753E768A8B481C306E485EC91074377DFC68BE74A444906E420C2D8BCCD84BE13AA5CCD11115B669C89E9C0CE374BC4059C696E5F8344FEE467AC8C8ADE37DAF614992914C763D971327B60946943847FB6B82672CC376B780953B6F4433DF69AC61E110FBF1A35F6272561193D8652EBCE3291333FDD4D84B9CFBC60A57E1F8B817E84EA15D440D4A4B4F7E19C08DDFC5949FE8CBDDCD0296A62F12F53D48B1288B80E24C756FC38E2FAE9C7A3315D1C6DA42AE838AFBBF5569F633A68289EB7073BABCB210F4E08856FA65057BFABC70AD3B58C2C870DFB5E1B0D11B6FA6D5BBB68285D8F9C21BD89669781C9F4DC32EB1EF58B80B1D371334D36FA66A2B3DD4B3E4DEDBA7AA9FB7E0245F5FDBB66CDA653C5232A131EC1F0C21DB1C47B990A64A24DC8C4DA951F419F57C03FF506E0147C22E99461 + +count = 33 +seed = F32C3715B0BA8C1D0BD59F0645E9697DFCF9AEAF761A71ECDF9672215B9F138C0502D7214F6B1BB4D6612432F9FBED5E +mlen = 1122 +msg = 789518EE21DC99CAC94DD5298B2F3EB8F6AB8D0705D24D9AA3012F217464E7F203E08E5CEA9E44F54A6F73E88D81592826E243B7F0B2A1B3A06E5AFDE23A2985183A0E430E01C3FA90E9F1DB7E69DD8E7DC6FB802933E04A18834C091ECD46F0DD423F532668CEE8A12A06BBC7E5FF3B9488B8F4A87A92BB8D6F313269AD95C574245E06563BB58BFF6169B8F4C333033BC128B91CB81DD41B831DF5103B295F744EDE95FC3A0C72F1134A9321836AFCFD563192C343040B943F69C0E98E8D740C06CCF840CBFC6BF777C9561065916F13D116D758A151E8FF4C355363AAE8E4F49D2A2E062A2BB213AFF25662D95549B4B025E70AA3363B50D25AF84A3E5B0FFA598CE074733AD191C86C351592299C26C0A4933573EF436B73DFD0C4EACF93D361AFE5F824B91BC178EE8381B9EFD52302AB8CAD6C08C7E090393B9B8ABC78AF374FAC6E60BD104BAABA524E68D75A759B94176105A9CFF2E5B9C3984FF61C5AFBF22B8E1B9E4F9BDFFEC0B19C2A5C8DB3B8B2C02115D101805C1BD6652F738F02600E38998CA41BA8955094FAD5BDC34133D4B523EDE66CF483F1CD5ACD9EFAA69703807410939974D6DC033BC696541357DA9881A4FD1385671B6E4BB889C68B544175C1E2EC1395DFF4CC87E037087C615CAF40804D5F44A2DE301961A59818173730A45CF4C2DF172614AFF7199A40C9FFB9957242A89FF86B36A4F4D60F15DB569C2FEFAF677B35FE5F12AD5A323397714286E338FF6B9080FCA50B657DB477A52A93B243BF28CE2743794C361F443AD81EBAAEAB2B237EBBC572D8586C3EAB1F42BAEC1C985D28BC58B296A11D96A04B0E1F7F6790B92E450248804F3F62B5865941BFD444A910F31E1D6B79D8906E7E9828618F960EC14124FBEED28E1F58A8BC9D31773442FEDC5A220F3912D0B41267D427C0C15BB76F9200C54B5F050307E13F1EB3DE92B864C994A3DF4CEBD1BCA634710FA342E23D7C8A5BAC1B58AA321E215E4418428206F05232E2BCD1B5EE1BB7E34E7D4C93088991EE9DD643FD08B0185A2F0AEFFB0EF0EEA3ACB4CE234BD5479A4F4296001305826F23083CC9DC99011864F250E77E42A0DE26AB09FF6E3F32552F6F913256729B357CBF5DFC825E91BB5D3FAC1F729803D431D339955960EAD69B1E54536CFD774341CDFDE1D1F527DA4E738B2E292BDC884687D1016DC193EDF34A37D284D026D33698295E864196E0BF16FA83A35F65FF2B38B7030E9E63EAAF594F272E07941313D538546BC84671739AF822391CA4DBE6A579A81F45FF51FA5B7EF49BEEE7BEBA4AE07452C13366668F02752923EA3653043B26C883799FE6352F95144283D946CA87143B74C8A009C024D073BAAB9BC4DA6C87D35FFFD753E1EEC7F01944639E566FE17A6F715F4197D1CBA58D3D153BDA37D7D2D5E19620FF0842527D109333FA2BA8BFC491689F4551BEE6C9D13BB9E69EE4F44B782BB05D1E48D293BC15B9FC706D52B021C7159FF7DF80E55627DD7555795F1FC616830A4BA2C02FE1A19DABE088E460BF3C5A88313C443179C593458467FAA468791CA74E9B1E759847B6939F +pk = 92926A6068F3F91E4A88143D04A9ED72B23292B7672B4FADE24FBBCB09F9B4F991016F982F8BD702AA6E6B74FADE2266A8ED4A3C656E15AE3B04386ADB673243CEFD123CE7C3908CCC162ADEE004C61076DC780389ED3D63B6695636D48404E0ED264A574266247BA666EB8A1FCC776E1E11EC848F65B78A054812B44BA546B288B9091B9213F07977A5FC98581B7D6C9DECBDF3D783CAC05D60E9E50A3E04E3B9D0D2C00491FF7F8FCAB28BBFB487F73B9B00F2DE8393FCC22C6B56E00BC58762E16E44EA9608066984650141DD285A81AADBA7A57FD4AC95ED64CB3CD1C6774FEED84D83AF8DAFDA3B37BCD928E1B71F027A94A72876344C22FA01F76F7980FB89471C6110B9FF6B29FDECECC2B2359A6DC28A1FB6A2ABA2F66C45D3D751D09B358EE3077C8E5E7B01C3501497F583009216ECA2B52ADE1A8748CB8CF014E249AC0A556D2F08B74E8DFE748FFBC66F6A7073160B2157E2AF70EF61741906025F0C9C863F78226B52514BB4195BEA234D697557081CF08C701422B899A237B447E64892144886402F1F742A8DB023B6580D30BA043AC7223540CE92B627C33663D9257AA0D8805B6199BE55CBA448FEDF8A1CDB333DB8D10B85A676EC9EC6260F640AAD310E8C42BC22BD8001103A4603EFE6878599914F078CA81539ADB5D793CCA51942CCD1512F79B85241E093C595EE841F6B21F16B13763C5DC92CC17B92ED0F2A839F3D21EEDC2B3DC7EF5601D6372407D6FD87B80BFB0090BF55B69B24BA8FFC7A4B1DF9A97BE742F8EBA7F6791435425B4ECEEB82AA841C1583AE3763FB1E868C50C33D3ED01990C8AF8D313EB313A97B20E295D6CB3632A2CAB196E00534C1EFE0D42245FDCC7EAA67A2311D80011F4524B99845E6A7F62993BBF7C6193223C334215A8A5C40167640588DC00ADB866B28103F61758BB7F7EA0B9E6EF41BD9C9ABF53DD9F611806F5851DA59DE78480AC056B54021533FF4394C5904DA56F681FCABBECD0F1C35ADFB3A6DF6C5CCAAE4E67CA4C486E9F1B8C3B9DB160A362A5EF6C7E588C85AD3D56BF6ABB71B4AD52E72914DDCDAFD6654DF09F7572CF994E9B7BACC2412E73B7C8356E9560B588A04C51D48DBE3BD7FF606B6392D777DFA3958FC262F1B8AFB4B7C2D953C352579E9580B4288A3E2F77F724ED331F530B56D2A340DA0EFDEA2C77C62ED89FD2786DAC86E93B13069A9041D584C19840ABC681FD8A01EBC21DBD80D4925058DDCE5CA424A8433ED9615BC534576EBEF45D770C2F30FF4E4D34820BE1B19D16AA23C7E7006A5AA7C260BE063DB558C910964365E739D056A62AEC95055EB3B395388A6C930B84B9A0A469C32268755F5676E37A89278762545AAF4D441FA6797B4A5D9C4DB6E0A28110D00429F7EE50CF5F9DB6D0FDB6EC76E3C6B77BFBE4917A844DEBA8EBC66D86DEDFA4267204C2ACFC9E4FD5AE385F3256287E2F59FF4CC751539D463FB4938FDA36BCD63C9BBA9F99122341D944488B3862CE98708E454D4C83A9554D5AFA189002E7EFE0D86CEB656CBE96FAB6619A1B21E979E689D1E0AB3DBA4D6F9B9CB5D3E187EC2E40F7B9B674576CAF90D234780CE9B79717E69E6FB6657601983C1688784B43F6BFB496EBC65E97B7C6DC0388ECFCCCA06DC05F3511B0C267CCAA9CC95224329B4C870C776D0827C4E7B70182EE5373841CBBF7C1A8CFC8AF205AE9CEF9C0ECC8A1D3F6E06C5D77B3C76669D2A83E0FCFB2BF0D2F5F4E9D05C3F8096FC884089C4D572183DC5927008E4307314476845B7290BA109F7DA90DF3694C897E8279BD7D78A6B5ABFB251EF94CC7683BB92D3F54908D62B51286DE9092B9B8213B3052CC3CE595562972B5979C8074BAB3B626F88611C6B81ABEEA2F88ADC3B7FF66D9C2B75E66F49ABF1002BCB9884CF9001327715FF137F59242A144DA913624742A909654D36C53A646D39163C2E94E19E975B98EA1108A1EBEEFFB0700FDF75208149358C1DB33FF4B2D38F04FD9CF094BB388789AA5A5A6AB83CE491F67D3CF9C5BE5FE439516EB5B07421C6D256F7A142357C2E81A788F7D34621B70E128B70A636FD4578A6FEFD9C802C7B53DCE9E5AD5C3491132FD5E6269614B310483E7EF1ED787995743E0635ACF7D25AF80198668292BE2BE3B768DFCE2C6E0475295E8D96F901111F06823A699987DD85D3051F3FE3BF71E1E270C3539ED83D78B38A1AF67ABB4E7AF10CBF9E73130CA289E21C5B812CB17FBF25436C507BE2DD483E43D6AE1B7B0CB37D6D3E96CB19C3D46BE9E781F770B87485B37A91F4075AF1E9B3CCC8D292A05D3DF4BE924A4A1E856BAC95B8431029408CBF763AB79ABF36D2F4077682B0B51FB4EB7EEB367A53D251A3140FFFA175C17B708BF54DF20A035E3DA340612715DC986753A3F1DDDD3989AA2E8FDA891B8F0BCB82F8741F9843891BAAA4F5FDCA9F42BC1980CDCE7AB7117BF7F492F3266FFA4196241D1A7386F5272DD2C17BB1E92F22EAFB522CFA701AF6CEAC099EC5117F2FE7035F11B93249FEF5048EBA0ADDDCB09E2148A2EAA0C54DF3D9E025BED9DE32B33F632BC65EB2CD374E54EFA3E175BDA4B70DA70AE162EDC418E7D4D3D24F7BE0B76E1D09D9D48CBF056924C972DA7CCEF5CAA7281A0F00E73C07DFB396FF4D656AE5C4CAB8BA4B0CD355A30ED5638E5EEC920412AD80904F911F554E2F8526B01755306ACE26478E839F977C4DD4D9D44775DBE2BE70D19380A56BAEA02BFECBDB58C963B5DFF4 +sk = 92926A6068F3F91E4A88143D04A9ED72B23292B7672B4FADE24FBBCB09F9B4F9136F62653EA62438EC5F8DEA59680CFC3188AE5F395A77C497C87331508FE2A56779F32FD5B1591AB91FD1EAB55281DAE62DA4356D9A2824022458A9D0B02FDEAA4680FF38318DE9071EFE53ED4B042CDF00BC9F8433275BC04614E989A120A4570026468861018167456025515628005388121425575644467120257660731550706622273651321747807645357162444321500625075784752162771424074518428266837522837058006455463041012762176017380846602606616045376342514238668156803488763221764386060181251836058883183221708837672463760867378804420162282212180886725780415781300626043267645243333830305765428001373106743414848730274632644751463424213456765241500112205387370842072552313185822513623418515334515813302155428602705731688863201085050184384810567076885687210376500848817136727734646651064237762508341434647587566571121654267662555186342571284273181172751740680257584450686807730618185387500018654800774276363438087326724114574870607024522806834701841741044166783874506140680771830287231636238552416811468120467306445228744821532444164604066186558184206433388112566827218328047823438855134406825733817442745846316785654401601688477544612086226033816328346780767228558368565220123200532421453454353723350400408162311020513333837182214048077512475261303202854113274480825667444272827557825410427340731653756268807357023416255533880857225205421556254568405682666760224171245445028325310750245576780500356406055104207420352242061040652113033528708160415710626168418563814567175285487067862316045101405878837510162321613686486546503550066023252886575506525061814563751252625877822148365400845250786283210863611285735600651166204877688825445032404518876016657508337123015186263406618003007386620872258183532535453653713447276807083323268653175868562577512526605310315046816383214872816746307465550837035016731713661624736756472516685703137624546845327323386877322217861430353450005602180357132058388831223044830482025672734182123707380312406500668810336081112875168521452111737808773380315143367748884172733840227131544660387231437746243487738055465810547084844133475270248001728151177260886613546270868856402663752071562707254468741677767410840270063347780283477786528550331728363404744127761656623572058041807527064482512782167450827304005076377476876817666650471882880117851227163668337174368200238026467844370887268258020612434516438380660005787513362171136678406248012860565375121841254053114561134651004320607850085115100677147477552202347582623232035818806253207305652074360410682223260432855682185717128742458600414781242170074828052722634237028402134638478400211277348812402225371482516325062176710743582644708325078626056566123240075301550556428488845513455085851307687242268034761072675804213603240130240477681628300733121672585822364248805050556271567556231510134083331402437161600834110880744730123866047086122126120086053458373114064541786162385883145687111745430630855603430311155421244080158042277470810307203132616722843138333350210174272211315152282227740488482751241543631411276331240170655778373423084045128810641024314013712825475703224203041603334142632650856718C324CD11DA32496EC210B5F47E2129ECECA48CB1F9C3E35EFFAADE2D1A46EBF26BD4E68B4C20CC24A5FEFAFFB667024277AA01A0106C0240705454AC83F6466BD52E278B055EB6C0C3D8D832BA7FC68546715DADA3AC917C9D355F8CB5083C3FDE79DF94827E978F9EA51D17B417F0D2FE1C3863304013DD2A113D172CCB5F0E5FE787BF7C8EEF4FACDD86314EBD967EB64A315C167B2F4EEAB532510CAB4C1B0DEE0245650F79A4BA9EC0C0DBCF009B40BA2DFA4E02B7BE1055D37AE9A0F51763637A6D3BBBD9778A1975C4E8A15CDACAFAF752EB6C08212017693C481649AA64EB128E491ABC97F5B2B96F13276C707B6993436246DB0EC0F6DE6A4322A3A799C075818390FBE228621EBDC0E5626B416D3C8B2040319A057EE715C733C35729216476AA9BF822C0F3F52AC9E9FFE412C460BA5E2BA36FF68A751FEEE229DF3C68F2961994C3F1F4AC43A4E02E3E66A30617A4CFEB54633A3F9D35759EB2C422C2F095AF579B2D7FD642C3C06F6B01AF179DE59065B8D82C82DD77FD2BA35C71EDB98B3B9E67493FD9BEC835EC414A39E881549B06E232CB3688483AD97065DB07FD68A3FB61CA9A14AB8DAE3F5991D09A0D8C413EBD53A1E4F4038835764F437B9EBA805075E1C9A401F109643EA55226D195CE058C392D473855045FFBBCE1A84D35E63B430CD50B793D38A5F02F2C955D364B7CBE4CAB809633396B00998E0E3B877004DC8200DD0BE2603E8FFE345EAA18BE4C7B6A5EB84B3E7DBC0E6A0EE113309911396568C185C45A8856754AC7196F3CA95FCA784872B2A5734790494F9AE6AB8DF025E8F538D220F02A7F9794A6FA796AFABC715D690BFF48D69B80696389C338BFDB9FAF351FC2FE7E8E8759FF7BECB8CE218429EE2171F89E2109BEB339A818FC9BEDC816D5CC6E9F45E3134DD09323A7690FDF7ED177CBC2A7A6BABC02B20A72DE8569BA8BF3168FBD2F229BAE25D5B2E9079E121CA20D5025BEC2644C728C3A49E3B5BB792B29E0CB06292E1F635A11078CF67FDE467CEC19295891CF5BB776B4B5687638876720CF3441A8C048E17D34FA649F2FF5F45EC7EB8268BD6EE0134B37EC288292EAFC358F50E0AE73EE01164AB8161270F43E91D751D223782ADAA7C45FFC00619BF5543F85696F9E74BAABB540D0F4DA781B0E57014A8D24BC3C783A15B3BBD4B297C883A0636C4003EE35457FE3945C39B41B478D7A1C2B6674FB128AC8F5439F46BA40B1C3B3C80436F35A9A6CBC9F0BEC46352DF3A9E3981E77A6743E57BB6C9B4708641783F455D57051DD1111B898A3FB0DFA375FBFE554E8008D600448ADFF0A08D5810E3F8A7F933A38F9DBA2C2C7881834A4313478EAED4DB51A67D155D1B5EEEED592819059712D648B0A5BCB25B9C919DB40FB06155A473ABE206DA9C5CDD18797CF77DC26190F9C515A7D9B6B79AF001AB1FABC7812FBDBF39440729008AD4A8A48E5FAD7D8BB9869839146688D078FC6D07653BCB43AC26026740C552DA6E4A9E0DFD0D011A0BB9BFA34AB4960E6566F77DADBAD5C3B1012BB579C1D7237A7426412EFE1F6AA1EC7FEDE15C505F71DCAFFAD3B6FECD97E5CFB25D61E496AE064BD80F90F0B41128B8896C08758C438B02971E77186084D80463E9438C3447461FE2C6E8063898FCD5794D10AEC4D0A04F0E4B946485D978532ECBACCB137B64079705F166C22D7243252A095BB2A2954CF151BA0BD44D5B29DCFCE0E3BCFCB3720D40992C9ADF3C729FA7144BF7437D7B4E31809295285E91CA411C58CFA39DF65166CAA12A350CA521658CEFDA549600DDA0EF5005C57E3CE89F0E0C7EBC4B1D462A0C9310DC3B042679BAA313ADA0CA32B352205D4B3C25AD801CCD2D1CE1FD32CAB32A9F04BEDE034CFC61639446C827F5A7AFEBE60A2CDADA2B5FFFBE63C1C6A1DE421EE9F86AF216040F2C69228DB181E0AC36B0B7CF336B09192A0CA53DF74AA32160393F4FADA7265E439EA703B082D510B190391FA83D81DD1D24E933CF28E42452AA018C50405E83CDAD6198A94A5D03AD7A42827ACE3BA38BFE3512CA9035B2E78DB3043D3EDF83ECDF248CE24E7C7D0C1FBADF3FC1A57639CAB9E7AB67E76820A06D46614C6479274E39CAA5BF51B5EFC56AE0448681FB429B477881D1A6EE64C551C12F5983143EF34BC98B75CCAEF2079F4ECFB5F94A5202FD986093B183C362ACEACDE9E3E698DDB60BBDB56831CCD7F56094D3E01D5E55379DBA0D96C594633BE31945596A1B4C5707FE78E97D849B7C254CE3395BF0349F38A7D7BEB44494E9468F87FA9D5AD9E115F93F5F6565EC416C913593E1876C3636D98CE8A99295CF506F388E25D8C62E834CDADA2F781998A63D77283D1BCD1730A21289418FF86E30D2FAEB4F92E82E66C84E658DAFA546F902408F4C6ED98D8F9B8F83251A699E993D4E91B5AF2C3E64A841AEA2B00AAFBA81CCEEC960D5A5E3B9148D384F0EDD6F2C9A34ADC798EFE87285872A1513E1F97B9D6C36E91FDC111E2EDD5FD11681B563942BDAAB3912F4A5FE6E25191E2CA39D3E79F08B3DA91D2B760E5B9B18469F05840C08F759F15D6A0515AB5046EB2AA29DC23B44D088F54D5696360B48A33AA596C001A49A0BA7042DF5155B2F57A876F1657EA96EB016CA963BA3B59665D6372DE36C19DF4D436C8951BD88A1C02BB8BA82142DBAE48D8E7DC81CAC0A2E86D2942ACE9CB88CE7724F1CE4413B209D3DD20DEFAF827994F51F90EF7DE76CA86C2ACB60AFF37E6FD7E657A44E42129AF172B8C6EB463320724F3367464E61EE6773C8E8435F44B8A853F07B009A98F162919A6289BC38BB1EE9702DD715F62B0002A271A790B143AB44CFB61BE7D056D0B8BC64515D7F8A1E64882FE37E9D4ED9199E09DB5A494C3AACD86F854AB6988F6F7EDDB3C08EAE416B7D88B799427E4025E98A3E6DF45F55985D3A711E84CE153B915513483373143367A5CB461F48F96F47B804BF0712D0748E8D41FE2C779155FF17FF17CADE1725F74317C249A14A970226388F15D851F5D0CF889E775F4F18C0DFA542770F4BD7847ACE96E11B98B0573B9A3376114DA4E5995C452F994B89E31B6EB30501F738BB7C909A6B94A5CC92AB88D66179289176F37C2A3EBDC5276FCC53D6AD94B44FC66FD22752BCF15E7989A057E9E59EFC16AB81A2C0F2F5DA7A49E4ACB7CA0722D3B55B9BCD43C1B2024DCC37B38F96372366107E2C7B051AC9BAFB7EBE4F02FACE3F25EB5A6A1C1600C50409090F50855DAD7B2F14D5C9F3B4E40362ACD64A6246A97E872B88FBA82597B558CE9E098DCBCA066B89C7CC01FE7370A968F29DC7869562132F43204721E0FA56201FBC4C4AFBBBF587433FF517614AE193112947EB38011E16D7AA7D5B1BEAF1F1B25983F80873BAB4F18AC269F059CE562618F54CA5A75520871A71B8CBC5CC324D8A0E0C4D4554721935A954330BEFB90B8D550AAA9768D7D10C511F89267D9728222666FF1BF774395A82A77EFA68EB36B7CD9BDC0C860035DCB41 +smlen = 4431 +sm = 542E35EEAD2BC1545668C6C7A6D119D571218896B66ACF743546F3DF6F0CDE2B49A77010D2DA518930CD7CA37C2E031CA5D27D4EB60B64630CFEDB8AC36604ABC2808D0119E04D35C49E5087E36D73241A1B995FB56E366C628023DA2A596E82A85E1ED764CC5728E55781F0CE6A361AAA284D8401D6958A573849CF5C97DBA2E5FFA11CF72760C454578F6BFF271BE7308969A89C7EFEB11377AAAF02CAAAC95A2B7D260578F0F6DBB8ABEB3264749F7A5D773F1F7FAD605687790F7D458B04808BDFF61ECFEEA94C61E81F20E5E59689D4073F0692C529F0A6E6A136A31D110999CB860B7B33959C9AFC5044AD51C534E9F698B7E63CCA84D4E1D9D8799F6553AE26EC87650F9AD0D4C4915B0D0EAB5E644E5C36F523EDD1839324DC30177A4198AFF1394982BB82B04F4321A61CA0B49578F5B14B77571068B22D19D43D9B696FCD4A5D6D829F9E90E30C4BD8E80B6B02FF629643E9EE2D3FC975D25515B309031B7FDC3ADA31E357170DB2C54796EC400DD388DCDCD3D434F22CD07450027B6BE7F2937D9D0D1D71BC2E3A7C7DA807F3EA1600BA51679F7E6A1A91FF6ADB23DFFF43C021324C4A18938417C3CC51B754FF6DFA36E24A68EEFBB81A7C1C4C1423D58326E7F3232B83107BBECD0D2C49F9E96F32BF1041C0ABD036A7C7BC1CD45BEA9BFD328F55D54F70F4669DC5153A2A2437332ECEB5AE8A9224FCE8551718713C50290C17047BE4BC65438764AC9F0E9C521B5B76DC22CF6FDB1F5F07CD0E8234584F03B9B378923B40CC1EB05D76227E43C960903DD7F5C2E0C4970D03E1F1F3BEE5D38402E6E04A0223FF54085851602F10819B852C97D5F2754E42529F67CC4597DB47DF818999D01E29FFC9CD2DFDE812C005D1CE49648825C2481D07E1DEAEE1710935F3B3466ACBF76F4D06ADAC6D7743E89D0B59E61A68CE233E628870B4877236353670C8679789048B0FDAD7252EBE0CC477F0B8893396E3BA5A534D5A208E859470B38C4E80645B33826AD53891B6AC69E4A8C8580BDCDCA2320182D00506DAFAB3828C7CA56B69190B4E338DC7D14A8E164382A12AB310D65131CF1A97AAB67F62B45F5B81538DE02343C935135D133BFE9686719ECD6C4AAA7129F03C3703260A7FED3B8C09E6603A87F8240A422395DE2375B42B454E4DEC06B88EDC5AC58F885D92D7F47C7FD4B34C9B7822A4B7BF6A07CB0A91FCABF2EB7155BEB47E64951CC74B4BC63763C71B02916C67683E758C9988286D42400F0BE8F921AF88F3EE47B03A9BA5289261A127E7AF307E7A9D58A3CE6CAC7C3A7CAD4CB62A0CBAB15C62BC05AA5A05C3B10AF49ADC7A2CBBDCE2C645B201BBE5D22A11A8F00D6A78A57327124C483E4B56B6BB2A7C9E0888AA8F9A65872A4265BD2D8BBBE7E8D90A5BAB9B5D80E53ADCB8E28E1D437CF3D76B3FD13E726BB765292018005F50E728D1605562786BB339039C216C37F56BAF187F5570842B2E0E8F975CB9B36C6B88667689A5770028C04C3771C5A578702B611F4A9D9967A6B0C14E906FEEDF1C3610DA43408777BF69E5F44265A0014C549BDE6C57813238493484DC5D16361CB3EB5AF1B01CC2D534E0A899BFCE75EA13E8A10952E382FC2A69669AD16348E9EDC433F3AF55B0B72F61526472395431ED060E08555899223DA543037EB94FBE07155A04D1FD94DDFB776C5A981FCDA1F718347DE9B021CDC6CE59C9C0F7CB2970571971B3BB6E78824A109D8C50A11F637DD91524E31115CA77073C04CBB5DCD9F7ACF3FF62663A269B5C2B95ABCD02669E40464F9A9B4C95E30A3C84C4A3B37FB3F0433858DD0398E526D719B0779B869DDF1D77627EA8523BE740D5713B298EE3F30F1E092EC98A528925F5CEC3B9D6E84E55E888CF2131D36FF1AB293532FE3A7C677FAB16B0CD049D17CF11D704E424087C203BB2B3BBF77B2189225B9591F0CC693AAB3AED1DC672AB22305E9F76D126FC4EC531F309B69B0FBBE261D626523B6B76E7D81EE7B2D93B98011C95DAC0ACA87697514EE4495D562B40851AAC12F3DCE4DE4987DB23EEE787AD20B632CFDE55B074661BEFC3B5294A82B59327921A9F49E0A6B33C8344145355F913A2E7B208312856B59608F66B79FE2414701F3B563062166939D02C19B8B728A04B7389D15FC40ACD45128CD92FAA9613FA56AD0C4DF2CE21594FDE6C18C62561135E32E1225DDFE85FB658786C35313A3A0666582A9CEA0A280C97807BE01808F8C24D78B861DB0F6CE50E0C9C37B23EE91E35486975C7FA53AF9CBBC554F3771F79516C6CF73BFA39E55C2DC5E659913531A20EF639C0F43FD0AB8E0E773C6A840FEEDD2B9C9AFF0C14980F6B3C9947DB1B97F8DC5D190D98547BE7235497172AA6CFC2BEE399DB2B5906D5678AF04714B41F3DD37022FAF554308732DC51888E88C8C615DB9A62ED63889146194413EDBA9B5F4F949467A3B0ACB82E7DB0D8BC4FD4161E5B14875341F6DF8ADB2D91A5392737DFF375D26ECCE9CAA4F3C21C391AA9437FA72DD1A23B8BA5A9C16499D41AD63A1163E018D0905787E857F25F46233589289D91F37CEA6CEAA82F0BC3F32DC898F514CB005020D151AD642A94501204C9F105CCCF20FD735CB511B4882365D74676D742809180DAD53322A656435165BE8CA60900C0D86E90F23009FBC4D48367AF45DDB68C80BE00B2A4A0AD2C5CE483A712713AFE9B725B747BF6807F719260F048785A792D43717656BBD5E69589959B03873D05A461BEF34442E2F47D76F58847F34529A373F32190E67F7093069F517964F810EA96CBC0F5A869E3A6EB20D9203ADD0F59646171A776FD8326FFEC64C0FF3EA07945345656F91A4778FD73A9DD3BA9B205845CFE146130118B17B83C79C3D9B605F6C33E350CE47AB73CDB6BAB15535DF9844B086C945529F8932553C4CAC72893DF0F01B681F55C0D9B5D91E0FC351127A93F9D68FD5FA010EEC6AA18438172490953178CE6C01F1C839A79252F85B7F7068F7C2B5C6B2E5393D65713924A80438842238E9DD440B021C4312BF21F408983ED992E697492C43037801EAED356E1D6CF73FD87B259B9F9C2F51A7099A487F9B5E01FD9EE1D336E17239D3EC449FDFC46FA22F9B94E9575581E515A6BE27767E8BD55693C1ACA245D1340D8FC0A636AA54311F9069DB7F11A801F612800CFF287E95CFBAEEDEE29B2FB264C0C467713EC2219597126D1E0F0F3FF4432AB82E268D2CAC30234F1BE0364E0E2670D8A7034651DD8673B021B6666D8288F78C07304071201614CA59827DF262570FFD7FF346ADBAC73F25B706A5425EA08C8CCC1FAE20DBD46E5E6C4D94C66D19D58E7B67125BEE49478BA672BF369E87CECDF66D73B32E8DCFE5955177518D9B8A36B13726405227EEA4F4522BA0FAA9C62842CD9FC03E96EF211A74EEF406E3AFF0EF33C167EF42872A791237A03747C3DCAB2A4826259BF5346DAC4464F4547D8AB22711773B9D4BAF7C38FE89A916EC0E3665FB4B2BA7312AB165847A9E918BA955CA009C84B2E67E47C24CA5A7A795722C1BB9C516585EED54EC5E5239A4CEE50CDA2509CB6F4D4AECCE2D35E84D8A09844FBADEF62F52D3EC170ADBF89B4AE5781EDBFD21E5395845E4F51F3B8644861C93DF8D25CBF1D81FE9385F7F45A88D00A82AA96515EC274EAA8CC89F69B34477D27A19A9A461BF9BD55A4712659BAA4B3C9B1172BCA15234E95F8FDA496FA5C25504630749C88DDE78E1260AEAD1E11C4D6BAFA85D69736D708F26E1DCA1DAEB298A87DBD95D6F904E6F3885CCE1EF9C2AFCFA2BB718521E573A1D48F239C660CCA61CACAAC8CD84EFDD42C1F914402D2A436AB3ADC62ACFBEEA531877640A894F5B3887E245538CC3CE27E8462D87AC235408CA0E2E13D0DC757C67E240D8BD7E0D0A56A3627A8826A46EA8275837F24A2977936C6AF3761C145E4897B34A3B2E8170A06B414198F5E8BE48640E5AE271E971538CA737887F464C2CC95EB122D64A5FEBF5D1445B09A50BF4CBEC24B2C80C178E89B191759B61842AABC49E036C0A498CFB7684C454FDF5CA5D53F4940DB7E0C8A58F4649588E17184673DD1EF3834BEC40858B0CCEBD30767E6E430B267B80ED73A8F0CFBD5C1BC9790D8DF4EA7C6FCC0D28088C179311222AA6C9207E713039305AA4E97C014C879FB5F2CB116B1133A52E440F1C2BCC155F4F5D505C915E76E59855A78091AE3CF807AC8A1740FFBB6A22888D3B1A91FDBDBB679DF762C4E71F7B78CF4DA3049ADB2D1023275BC6B533F02997BD3F00621740ABD141FDC416B5BFED8EA11F852ED938E2B9CAF944F1C7F106643CDFA8B31DAB06C60948069A8855CF6B9CF2E2F12CD7D0873E9439BFC7F82F90B9306554DDF462808C3FEF3C431D2AE4DEDAA7C611BE904EE20B30857B3C40AFCABD9FAE937B9704B07B038B181E3F31804549849FE52CEB6FBE9FF24B485AF66A27E6E9313D41ED4B427D1D2E33829CD401974498D48266FA8835024B2AD01CF09ECD27BF6433D3176CF643AF75E4E8555A2A0E34C99B3D92849D2242396147D11B236649698B2C6041EC3A344866340574723A13A3B801C293A415569AA17294C8C90E32D85949A103E6D8AD1062E95355900000000000000000000000000000000000000000000000000000000070D1116191B789518EE21DC99CAC94DD5298B2F3EB8F6AB8D0705D24D9AA3012F217464E7F203E08E5CEA9E44F54A6F73E88D81592826E243B7F0B2A1B3A06E5AFDE23A2985183A0E430E01C3FA90E9F1DB7E69DD8E7DC6FB802933E04A18834C091ECD46F0DD423F532668CEE8A12A06BBC7E5FF3B9488B8F4A87A92BB8D6F313269AD95C574245E06563BB58BFF6169B8F4C333033BC128B91CB81DD41B831DF5103B295F744EDE95FC3A0C72F1134A9321836AFCFD563192C343040B943F69C0E98E8D740C06CCF840CBFC6BF777C9561065916F13D116D758A151E8FF4C355363AAE8E4F49D2A2E062A2BB213AFF25662D95549B4B025E70AA3363B50D25AF84A3E5B0FFA598CE074733AD191C86C351592299C26C0A4933573EF436B73DFD0C4EACF93D361AFE5F824B91BC178EE8381B9EFD52302AB8CAD6C08C7E090393B9B8ABC78AF374FAC6E60BD104BAABA524E68D75A759B94176105A9CFF2E5B9C3984FF61C5AFBF22B8E1B9E4F9BDFFEC0B19C2A5C8DB3B8B2C02115D101805C1BD6652F738F02600E38998CA41BA8955094FAD5BDC34133D4B523EDE66CF483F1CD5ACD9EFAA69703807410939974D6DC033BC696541357DA9881A4FD1385671B6E4BB889C68B544175C1E2EC1395DFF4CC87E037087C615CAF40804D5F44A2DE301961A59818173730A45CF4C2DF172614AFF7199A40C9FFB9957242A89FF86B36A4F4D60F15DB569C2FEFAF677B35FE5F12AD5A323397714286E338FF6B9080FCA50B657DB477A52A93B243BF28CE2743794C361F443AD81EBAAEAB2B237EBBC572D8586C3EAB1F42BAEC1C985D28BC58B296A11D96A04B0E1F7F6790B92E450248804F3F62B5865941BFD444A910F31E1D6B79D8906E7E9828618F960EC14124FBEED28E1F58A8BC9D31773442FEDC5A220F3912D0B41267D427C0C15BB76F9200C54B5F050307E13F1EB3DE92B864C994A3DF4CEBD1BCA634710FA342E23D7C8A5BAC1B58AA321E215E4418428206F05232E2BCD1B5EE1BB7E34E7D4C93088991EE9DD643FD08B0185A2F0AEFFB0EF0EEA3ACB4CE234BD5479A4F4296001305826F23083CC9DC99011864F250E77E42A0DE26AB09FF6E3F32552F6F913256729B357CBF5DFC825E91BB5D3FAC1F729803D431D339955960EAD69B1E54536CFD774341CDFDE1D1F527DA4E738B2E292BDC884687D1016DC193EDF34A37D284D026D33698295E864196E0BF16FA83A35F65FF2B38B7030E9E63EAAF594F272E07941313D538546BC84671739AF822391CA4DBE6A579A81F45FF51FA5B7EF49BEEE7BEBA4AE07452C13366668F02752923EA3653043B26C883799FE6352F95144283D946CA87143B74C8A009C024D073BAAB9BC4DA6C87D35FFFD753E1EEC7F01944639E566FE17A6F715F4197D1CBA58D3D153BDA37D7D2D5E19620FF0842527D109333FA2BA8BFC491689F4551BEE6C9D13BB9E69EE4F44B782BB05D1E48D293BC15B9FC706D52B021C7159FF7DF80E55627DD7555795F1FC616830A4BA2C02FE1A19DABE088E460BF3C5A88313C443179C593458467FAA468791CA74E9B1E759847B6939F + +count = 34 +seed = B0C7530A52AC9F561C2C14548D3A5F5053396B738EA1C7A5190F5AB01C9C38719C4DBE856E42D37A114FA24FD5DF5081 +mlen = 1155 +msg = A4117808D9D05B702483924E99623E778E7A3B7623739AB7AC488ED93E711EBDDEC383BFB7E06086FD0C374F4668AB744AD99B8AF1C75309B60F55DC03FF7BE6F23187FFD5CB224068568CE2D06ABE441557B04A5A0C2858C416F6F7AA89A96ADFC2AFC54E0F31416CEED005B7B140B342652DAC7BF401FED4D94D475784936FCEB4B4F334BB14BA55B1EA9A36E2B0591287EAF4ACED997162691A96E7F59853E609ECA9A225F615A49A12763D80B5DFE6F8638923C39BD652936B19B944D5116F790E866A61947EB60CD1F3A1F319710D0F40E487EFBEF51FB4D00F5DBB94810128215F72B1AEDD74A1B1D237088DE3098417714EEB67D6A3E6BB647B6B0AC6D0BA3089D4CF6252B69C414E2BD6614429B6FCEABEBA50A4B53C7394652ACF7DD9403AE14436ED5FD4D1C9E238A8399A763806FEF5C3742C55B7159EBF5A13B271428F91229C191D617808A26AF9190F9D445BFD3B273702BC3E7F610854C8E86066BE7757960A880CB6727CEF19DC7B464C464A7DAC9AE85B799747B8488A4123B6BC7F0F7C2A8E53FD4F8687075B4E25660F5107ACF22CA688057DAE0496FF15A3EB9379A9F6E22FA43C932F137E389478C05DB86060686AFEAFBCB9ED79AE194C4146A48CE5E07EAF585279313851CB864A50075AE46C1AAB3B3CB920DEE2652F5AFA0138051C7C980946E8D5E18C16789CD184DC5598F65875EF43418DD56E11DEFB5A4A6AFBCE041BB292E0E2EC563296BA4EA6CBFDCCA32A18C8AA395515A83D0FB7819413E5AE056FF0EC2F63F1D52A8BE0B334A628D00995BEC7E46A34BCD2DCA0E9C5A88E0FC8C43843D6AE074C699276293FD8DB2BE48885155688428C2F5A6C6C91BD4A03CDE2126205F9EBAFE319D1B4F80277FE99211A09628AD840046EB9AA568EC71252CE9F69827B677D9C0D99546DF5A48A8D253AC0036DDAF4D045A70F94EC54BF5F06296B2C2617F2B0EC0B8374DD28DE269FAF739B1E55AE1846F548FB6C0403C5ECEE3CF9D1927E317F0D07E11AEBA01C240FE17C6660F7CB32305AF1EB6DE4312FDEA6990DA4E9135DBC0B88AD0AE0847E1576F3C2711B785B846C7A4B823688E4218596CAED583A90DC46BB9B27E00E4C1110B65F77E602F043A8441563667691C07162E52A53CD76E2D74DCAAA2983BF2E8F02CC30B05BD4F9AC731931C59F9EBC038FAFB09FBC886F4C4191352206BB49ADAEF9D74BD08A5B780FF0FA301343F5EA81D36912ECCB0FF24BBF0BE6A8283EBDECA79CFB22639DA38C9C639C4BD66FE5A75F0414FCC1455702856E6FC58344BF02998E17E967183AE920B7E04F58AA09145D6DA79B65EFCD18EC55BB9CFD53914F80D73C2B08BB754AC63E4C82D44B72376A544D97394B7C99678758B15CB94E71F9FCCF674B29ED5AFDCE452959BE5AF510D57F9E5395A576EAA1FA7BA9AA4122A779727071FA485C005B447760410DEE20B7C2299B4A0D5D9E5E4E038A19C87806C3FB875EA5BD7F47D034D7D5FEC4BF132B04E47574172D392EA7B371516190AB81C67B45FEF6332848A51B6C7DBA90C410A44E9A88AC082FE296A7435E7D2DDFC645D5AEBBC29620525757DAD1B0222159D658C7225D02374EE6AF479FCF1AA28CD91B +pk = 417EBF9322EACA73903D9A2AC8056737EFB18C9117B52B61A13E2FDB89F7CDF9AFADD2E2A0257A76C531A028AE88DA04F83A5ED31B4CCD7BAD6AF84151F1D6BDE66F69FA7E5A6AA4EBAD115498C96C393F1C282FFEBD0CB4F007F60CCFC4D65F051BA744F7DCC1B8A0C7E34BDD7655A99E98E62964F1D54B0406565487200629590091186092AAE7589BE9C7EB9FFD158E9271756BBE479472F4F063D49B4D01B78504D6B2D2DFEC6AF3324F10E909D65211085646D292C505A6CDEEE8C835F8CAD5892E45982A09E137328516EED3472233A750C87C2EF3E14D78C2098A292710B59FAF9F159EC02A18D5EDF386DFA57C9B37A8D39A9D7A8AEFA989C9176BD8759937215C66FA02E41DB47FAAEB5D29FF1990E0F31A5BD9E1972C61454EF58049CB3BB827EEF4EC2D1A14E6EC1065EC2094E8CAD93A71506B6A2110B4E2DE1667B8BA393E3749FA2CA8C646A4365715338406ED9D7842D7E5AC15D5F4C8CA90E136D86F96ACB049B1DB048812280F647482F80970B05C4EAF92727AB4ED4EEA0C3B41DF9210D0437BC18C9BD3BA9FDB76A4002F89A7C140A44786508DC9F28D8644334FEB83115BB1CBB22D20804AAB7EBD2E8273A06DF69E250FC43989EDC1E6016E5307D8F6308CCC20F39FBFB42B547C5EEAE12F3FFA475F90BBF4378AE5744CBA803DB880B65BB8C2A3DB20F1B3FBD31B24B555544C4C851135B3E667C0789E1FB0D64293E238D3457849632A2392337A5FBD43939F14928CBD282CC01B522CC9DA232FCAACD062AAC1E036EAC55B1C41BA9FEAB9ABC4D00746C8326E6EA18F940DAC9103A1BB343B1AFAF25C29C7BFAB069D9377F4E75B5E3ABAC62E27D1FF05DAC19EF3D23D2B781EA05F23A470C1E5DD26489A9F8DCECCE8F3DF412204CFF89242C592CE097E314DAFFB68101C590AB1B1FFC092B962BE8ABCC9BE34BB85122B06298BF1AA9608CB4F3C481004DB434FB5AB0602A44351A1EA0689F3209FC09FFE60740F72C5F6DAF9CF2D02E44AF5503C95045A533ECA14D6C895C5A2E33F794AE2155B02823DA34A28DFCBF27407427BE6DAE438E366650654E856F53B3EA702E678E62519E4F3C84B33D6AE36B5423D0E44E25246EB56204ABCE542EE04B0846D40D065F74D75DE95D6C2AD5F32B9D3BD255272098B0520F5FCAE0C1F8F78339C570AC4824015DDA077A48D3F03E161B3CC52234A8275179917A399ADEE1F07A0FF3D80FB6C02CF31BCDCC61B78FBB36CB7298D87C6F2EFDDEF79DF6D63328CBD68413BD082A3085383D1C4A3E6986D00785EAB028DF811B3336F9F0C1D07BE5C3A8EAAAA261909FC13E305C13B6A3F25BF3D0D147945219C7A92716E8AB8FAAA769F6DC601133D1653569BCFF5DE3B70FA190BAA48825C3691F6EDCAA8FE6AA58D88276045A2C2D4FD7BC8A3C02B34796B6AC7C932A7A673F04EB985C8EAE8B2720C25CC316DFBF82C68E5276F8BC17A0647AD865726ADB0E7CDA4B499C90E966173F2756061A955DB7DFE02F29B620FE226632370CA4323458749B684DF67E50E5E496517240907B3B08DBC0E29827D893C72E0D81CC01DF16B2472799A5D9FA0165BA8D278712408F47969C935D2D4E17081E165BB3182FB83B5575566490F8C63E3CF4E2CFD054EE945218AFFA8616522DC9940D665125395F49D85828363CE3FE3417A6294E812231B8F4B5F3181264F6F58C3B5D62F35EA673387A018CDB711D571341BB207B0E5865EB3FCDDADE90DF04F6CC0350D3885364D7216E1E4208605046872A8C990E17A1F33C19C2227A90503291A73687215BB99B17CCF9CC4AF3EEC02ADF6000644C79747F8A8CF3BEA93F62311DA72184F50658A170AAD951AED18E95D26FBE007E979A23BD4AA5E0657FA99F74B92A93572FD7A67ECF3213725FA502D17362E34142E50EF15D17DA393A0FF25AA648FEBB741AD1382719693BBFCDE9F3AA484DAE8474EDD77E97C8E3614310263348B802616F52F54D0F6FB536962E0EDD8DA81DB04F34D743FB493FF242889F90515780411FD008713A1ABD92872741FD32E3D5B5848730A9F30104EB43BA571B3FBE9F8A65AE7570DE8D50A99A235B5D7210A70C065BFBF50C18439CE5737D94F5973C45FD638DCDA8D87A7EF99B29D5A2917302CB1346932C09B3C74DB3B660D04013094BB9CDCDB5348BA579523AB392DC2FE34C76FD8C69A56B15B4CA57C7BDCDA078A50B26F3C5D5BA8DA86F97994E830D6CF461EA3AF09F1EA7763C88CDC461735598C9B74F047A91E8D5A15AF9889F7556055FEA6EC9AE9960657DA546B5D5C788EEB614B5D0B339C3B1F65C9B6C5B87BE5E11817F912E66CC6155D99CFC60E5E1B46BFB47B0A62C0B1F746BA11C6039D09E9FBDD7A1A5B4D4F2D6B8CBE7C93C243D90AE25DD0DCC0385FC97AE6069BEAA8F8CDA9AEFED65055A3996E967BE95E789C46DBBF07942F87E678D1AD67CBB9F72F543D877F838A92928526D054741D7685D316E2B96FFC1CBD027CE7B2FE7B171C5EEAD3DA57202BE03D26AC5E986E7E6242AFAF8BA70A5A94E822A91C9690B70D581D38E93B1FA308CC9A2B0D399769CD34AE32D5214BF4180FE7E4137D6EF2372DC488BCB08E1E1810BFFC0AACB8236E3482DB0853E8840617BF72CB48C4517F5A7C2F9D14F7DAC7F0F9A61E6BD7B4040F70D6136B445F63B2E9D69298741D26F95E7DE1673F553FABB1CBDA7C4718ADCF064BADDD091C84599F6B7890756A048A5FB2CEF6EB2D210982F00375 +sk = 417EBF9322EACA73903D9A2AC8056737EFB18C9117B52B61A13E2FDB89F7CDF96237C440DE98A2C07F8976302E70DEA8632F39D834CFFA342A44E5F2D3AE503EF15250FAB645E9785D011CCEAFB3D1346867D6C76090FE2DBFD5A294139C48EF5B3BE6537A288979395B1DB38BFE37738A1EDCD9130941A9EA6939D8BBD6CD9240252131287013122307743355003300540665755343316842782817634024727635485230188532872423076701807162125013450430136406274232683476351384766822644182550543724704724885765886743778727551526107052130363080371145234007674154451166881440844357371632446435677088306178103310420813808413115387013644372725236751765502487527280716662801004182250716483575323215578685182656237085036176326740161657106042556707388466554833262642235611645005356030005537588250760412450385433161576282240158255767302232405656283822147183121163177040877620004337083538581054641284717523000752684881023836253151066567621581786230327068237241830060435334382272118511240304585742314853314864302666163261645361084171263126451834306704600230638585448500624718278232342623773045335337040677105546721116173476688637024772720633778361113043321645327064357601777687421231776854012311283303570704531802020022231284454076417781584326502627166431562676182048142445852260431621241526808254822423801874508773825313074677835027382631456384533073685585300336236246275837688776275088221187240711425338001812565326322127465701616512634052182051764610345434185025051662013600087312086472485330604301783853513255236257726827278056603338205035588374662616863107538845467557347411281852661367733325730260567642763655882834444876304167308288546587518075616712515723616520818051647528741012301176381521502544551781740471425631836817863031100228761345310760133611116686555736020104353176622078404730210628427646644378627426843812355680326653823326852060726028512108387657033232117230033353868666352443751435001871816017622063648540102726674831245663135356821267764743852584506581005426058240557772270631020337114337648218268541102651413107654206170725445364326378864687642528408285745644418227441506378047753163220507600663302322485074867477773588656454882007477286236533277012134602757740014871842735271235184227770345525416484244033801208260140821502875145565218640014764354845512433183112563065508260617652177338824002107110125706651455711651205033037666642460434540034810067720171788685415575046062623418668652557571781226082834457584865871306861110722024122185111365112161606876061232655765185867275454727831267556107580224702014616883383731710041628533475025428512465517141082252245280563630083650057401682085043048233182061261806431605144166844328644667315174128218318050157220555872817826645436865544338780354772835560478423264303435187200803427618044138072224545781353304313337445382744847803450816736336470715377455643132583165837585050154675280848633602144845366682234356132708604547644283000018341037078357160841507183301577271225273661374486554538668420366173740557846511567868383801708354511454367662480527040326302148821856145511854268725703136721762263466147773648420182818736077016462538711305824815151836354783432051208602774752122802773333360551575026438031438B390AF520483370CCD2655E19519D8FDFE6DA6C3A4310CE6C97A9FD479A6FB6756447D817CC283A154E7390174CDA342EE4197363D3F0E9EA5A46010260A1D8C2C5FFE7A0DE4EF8A741F5CFCF56AF3607B0E09B540F3F1E934E4D16897F89BB77977856098A1CE2238F072BD1F7D83B4E94BADD24D214FDB8908DEDFD15888335C035142AA53588A7825ABE76D896D554F8A8D71D715F95DE5F173719BC681F691D02D4500999EAFAD1507373982FEA2B13A0AE27CDE34F02342B3205F2445F7AC8EFF247484A723DC60F7C93972F7D3BA6DEDF895E152922C7E49EA08AEA268426352630DA05711DA077298AD364EF0FD3A7BA19975D8A054CFBB99FB7CBF650CB993D03163BA63C9C48FE244B3603305084711BB204485025EFC2115298F05962F86129D6193A56614A7ABC91E84567BD7AB4C5602032FE259B9C636CB6737DC5F48878B1C5CAC5800D0D065856253AE8735680BAE6AD36C5F8E591EEFE0EA8C8985A5D4108F824D08186B9869DA7A68E84B6B091561247FB7577E3FE772422088F57EF8ADFA4E921DA107309B866AA8417F15ACF281BC821F6565FAB36123D0720EA593A22B7BB70C3650832DE8B135DE8372D22B4D84B563002CD0A2F4DD1A71D2458105459BC6BE32571DC3736CC536E9358047CAA6D44B5FCAF070D372B18156D93641F5081A0C6BA8E337549CFA7D3093FBC620BCCB2C821F130668C293C1ECE018008DFEEB47E7D4026F8B9BBECDBBADEE2DF0E8EFECA73A30C6DD17C722632598EE72BD90A73C735E965528A80ED8205C6E7E4F6B32E10E3AB9BEAD6CCBD0188EA27F93D182D7AAA4B31FD6FB87F5D621651A8AE8DF2071295B3ACFAE4BAB36EB5F523ED39445D8202082BC90DAE3D739FBA182246BAE8AAD17DFD9DBD9D3A25EBD33C84BD0C7B1AFBFB4F346E8DED4DBE12180973C646E31747543BAE442EB16A5D3A53F4DD54E4CFD5E93CF5FE8CF90C7A21821CBE487DBE24A5AE0533302EDFE875A3530BBAA180B4F9A47910F66F989A7D2CADEBEE70AB100ACE2C0865E5A8CAA2EBA294BC6F64C64848A8541C44D94A6EF981CD3FB91CFB439A84DCDB84F233D5C94B78CCC0D116701B7DFBA418D8521F964DFE9FCD4E2965F98FA1A9A1A83C366D8370DA80A03FD72E7EC13BBA6DC96C4862F23347F203FE7B7DC05808352DB6500FEB5618B107424EB4E27FFE5E0CF9D98E786C081B3B66CF47B0DF0672D0328BD0787807C8AE436F12C05AED1DCFFEC7F7E3F441C09247A881F2DF118921795390A828529CD7202A3B3D7680AD6ECE690C08B3E1DA296BDDCAAF592A9CA34E4994E407E65BB0C68986927DAC8E4947FE99C74A5DC03C3CDF76179367F0145C431D9FA86DAD760A42F7A026D96CEFE07EDC255E9C31051E7AA2F925D5971F37DFDAE012E7E3E3E1CF2499F4077CE7401BD826A9106E8DA0A9AB5FFF0B49A7ED69BA06406C01E5EB1AAD507D1180368059A2537092C4936D411D156F6582D137B845A6D5802A69EF23BA9AE5D12092B251DFDCB745569E5287858C90C93C80E57754D6AA27E4E3CEE8498AC10D8786EF5A354BF64518085B65FBF112C4C8BF6D6F415F12DC16E4A8DD32466F31540CF69344DE03FB5340EFFB3F58A1DE5025F6C3772802FA41B825CAE825C5CF79F324290045826BEDBA9EBAD26665D933800877C6D5EA1499726E3B08E713213DF17604AA66B04549A242B9B2EF85AC9D9D7DA2082509932D500F81A19EF66466C66B498DC56950628100364A328AFE0D28181B3310C3586D8E01E057D507AD9793C6B1205DE03520D187B56DA8394F434F81CEB51803F8CC2A7FB06647BF5BBC3F360587864860370D43ABD98769D8D1513B79EE5B1574FA5C15778CDEEDF6BDC33F9DC5D28D8866AE93159F4429CFC3B02E09F3CB9CE2B0C29228838E1DDA0D20140A672B89F42348F1CCBAF68ADAEC19EC01D6ECDCCF4F9C2C9C62764EF4CBAB5A5F5C8A288CFEB6A3824265DF5C4BD91228E51D560BD26F4DFCD55790D0ABB1FA6FF2B399A2BC409C2F86F60D6D0B86AD746F44C00767B787C0ECCB754C0B1FCF6D9D20C91A4CDE67F677F8FBF447F9032DCB8EDD632BF766EFBAFE01FE3269C639B7CDDE50DE6748C0BC82896EB3CC96786337A3608AEA83C9ACA50E922C09E5B6BACF1980C66231DA45831866918095E2A4B98F17429FCEBDABA1254A40ECA9194841D1D71680B4E7B9B8B4548EB703C665CC5023D02A7C80B6F2AF338BC6C08EFBFDB57D9D11FAB946E0AC7DFA857A232E36CF4A6A6A0AA544A9D6F0D8B15E676D6D440ADA51226A3AC9601E5C9BCE74333609DBF43A2D92F353E667E82347FD26F71E1C1462F9B18900EA911434271938C1BFBFDEA09A37F04EEB51D4BFF6ADE5035569C903CA212948EF7C3E0988B8B296465553ED39CCFD44C4C6464347F689526D9A9E396BDA146BE27C642CC196406231E626CDEC52C983B732259EFDD809FD6058B51ED7D7A324E3042A152E9B36D845D4C5F44AC5BEE2561CEEADFC30F2F2298BC1DCED14C44557FA7AE747AD55C16662A15D548EB1C4D4C113D3F93A56A5ECE0D8C45FF59A9C0C2D48249DBE8888A5398AE819F9BE12F0ED22D3AA09F85A48A680FE32D6798B50A8D100199C5375BC9798D5F9868A694EB97D8AA32E697D1EC8FF265C1EE19E800538C735F7CEDE2868DDACAABB519034B7C5069A1111153BFC5673543015D80438F7B0DF5211783C68AB3147FD93245083B05176B1344840A016AC4AEAC13F8E71E82301C78E837C2CEF2BEADEC516B3470E02C258E1C4E84B4047BDA367BAB669F4C67124B47E3627314DDAB9A9DA651F285FDAAE3D5F7F790F3048184B9700491F3FC3A4D87A019A97D4E7E253018103B0C59E2474BA79D27ECE4BCD54EA321D8577332BB7DEFB3DC21FA1869748D45D98F6F91BEE3543C9A3CDDCDC1278DC6D2E0713A1D7273C713D56A902FE317CB79F701AED2E503393AB831301B544D285AC72F219C94CAE2EB89DA631A7FF0C83ABF87C8BBB87C148EF034FDF492029708DC39FD668A0DB739C72C52425F1F3E4651712D051157A04CFB2AA69A898AE8E913487EA815597C37295882A5033CBA82FDFBE29FD2A31B855D8A15B5F943B005E9ECA61A24F36870452C5DE6FF761AD78D2C483545C3F74D9D0825A1A3408B4BADB10C736B12866BD2454DE74126A0B55DB9C7B16F84338FBD2154CD75A11AA9460AB4FB94F74FFFA8DB209163C975F3E14BB6B91670FDB413FC6E8477B4FF3BFE5944A7D9347DA7310ADCD3E03AE479B981F2AA80E2EF5292D992F7E4C25D2D93CC020DAB1E419F3DE152F00A373E01F069658900CC376A3F952F62E1240F4AA79A4F6322EC22004987A60B980F16756BE8FBF29863D4B065F750309CABD313387383D67EFEB8BDE0344B1CDE2A2119F8E87B93AB271D1D6D0FFF07CC493A65E45EB8FB44134A729182A4D5C4ECD64833F6A3336DBC43DFDFC32B344A1B3C2FB405674DB6C6659747B042A17A7C07469717F130160B81E9 +smlen = 4464 +sm = 5A06E7C4B7B909CF4417018F55ECF7037EF9A56590687518E6B7C1D81E4786F09D1C0BB8C4C9555874ECB4A4456C6FD07C22D3CCDBF85802D64D35EDE13416530B44DC479DA6923DD1AE5682E1F2EF862E4BD948277A80F6E7739FD0EB2D2F0BFFB8317684196B149BB8D9141CCEA483E737AF0EE8FE52CDF1B0718A956E18445C784EEB35051A83D2A7A8553FDB6523A8097540EEE45FC783144A4F8006532C6DC71A3BE18E744E5061512A483127A3B723AB437F7E435D362BAAB8C5435E19201A79A0E1575DFC78A92887CF2B8F94902A38DC4CD64DC1729CE077ABF5050D70A616455E0F4D43084D3842D58462DEF4197898820932AF8B3FA3532EC224EED3952391847DF29E8CC79A019C1B92F321F98BEA468E7BA38D5E42B10F0199621E229C8E26B9C6567B2E5A83AF8057C39FDA5512A94754A58DF95D63526EEEEA6FEA6509348F1E5E8C1E4A16DADF9256F6112A6A2748D5C186C2533742A482331B84BB06D1FC06AEF7B20CCBCB9F480B39C8F1E8EE7AAABD09C0782F1F1A71D763D2BB9B6FF2A7E1B6325AEBF4318901E0FFB984ADCDD7630AA0036CC64E84D17E20A2AF33E9C508E8AD3461334E3EBEE699414B91AC32E0CC0A97E4603074C6B88EA5F82300E924228838172A8E3DEE1286C32FBF344EC866E0908572956564B34E848E450548BEB1E0DE88B05D7FD0A288F5B51736FBAC1BEAFF8ECC373DBA44238DDFEF0F537439A49B4EA780E19A9F15B6F599086E3964BA44890FC66167C04D7A7DC2BE75765735FB076FB1D1A890F7B29A7245FFD7EF11EA61FE52416943E525A87E1EC6B7347012ADDF8B66FA2E5EC90D76A4D29230794EE1227324267075641DF421389E041A281275AD1F06E81B51EF44D72B75F88822643BDAAB17A2C00EEBDD5CDF9C62934AE665FFCCDF0DEFEBB953036A135F8B06CE99027932464A526236E9CFC7A7AF2BB22B997C175A84B159ED670ADB39FB7D5A6F955A4D431860CECDDA48696D7D22E9F4203F1551AE287B28C94CADE2EF75D0CE54E9F1570C869A7F038CE9B3C2F93735A25D95D6277293486268FAE714EE51A13B843EDEFA18E00A400BB2CECAE731469E90B35276AB54657CDE18C7048983733F5D22053DB90AE6091065F328856A068570E9BF090520FA3D0C5EE8CF0FEA3E147D9DE8EC824BAE8C470B4A967B9C9A8BD2AB340F311EEF92D4C23A6EED48E59D8BCF8BFDAEB365F4C02A1B349AD7BB0747C4DD2E9BEB9AF6C56C7371C48F2B23253445E5ADED0AF5291FF722874550827A9BCAC7971AE60655376A1F87A7936C9DC837ABC8695109303D25DBAD7FC88F8E261FEBF1DC2A48E2E73170CD8022B1FB90E2C5EF58AE42AA3E40CF2BB8A9F710C0D31A376D779C20B71EB27B692A086A1DCD4AF11D25F11CB0BAD869FE0D4C6EF5B3DE7B4CB7673E61BF05430EEB4BB2D1B90DB38DC4E0BC2B230FD8515BE69CE12060E7FD3EFDD2FFA3D5F8D95DA7D07F56DB25FF88B3200B250D9DB6DCC526FA25CD3299B0EE56B654C4BF9F2BD3F301B3D1A9D29D615679184A7A48991D58D8F4A3EBCC5DF0657F27BD20EFFC2C4C28395CD0A08BEA4D2A2B8114B34A64551CFF09BB57397421DE55C02A38CD369CAC7AE45BFE1D5EA7FD986D0E1B5B318D13B365C8CD3F4D94C7DF380D59828EA7A58DE7F6CFDF3FBED1C3859DE19468A5D0C28E428633F02E954CD6084A40E78B1A434C6A4B4FAD56A3C8CD555B990609190203873AB80862D325DEBC4C03FE6ED97663CB2A2C46F4BFE75FEB215C8882380326BEFF5E84CBB2A7863242D894B267DEEEBD76EB5F677B79F5D4BD9B74F6828A097F98FB4C5486D1F3A9DD21874676D066ECD027032C9693D810043FF5EB8E9462B07CD3DD5E2673FAF40BE51F0B4855159AEECA341DC2567F63B80EB7021EAC7FE3B16686A5C5E8F0F313448FABB7A301887095C648799730CF39E54A8BEA26A299EF17E9E76C647C3BEA0E9EEAA81A2D755D8C76300AD2B4216E55707D3E2090544CE2CFDAC98E717306364AFA1C8C591E467BF9076803FD0F322F8E1E3AF36D8A8A0DD1E8F47B4E34DA10BD587B00584EB0AAABB3D37296F35CABFC4FEB8E5DAF54A89E9E8A83042BD676D26670D23CA592704AE279267CFB2C2D964BD10F3A83A21B5870AD294378D77F418FD2D8B0E201588FB5480C9C7FC696461251DDC63BB6BF670FC46DCC8A3354BA3D0A210563E3D540F1C452D3F080455774C3FE7C8BCBB84B97804C7D64341B0EFAA9ADAC14F893065D47C9B0963446B4F8E397898AB7972133F79ABE15BBBAFE2B35FAC7EB7F7B73DBCE05BA0A43F8DEAE177AA9DDE51E118ABAA79F60527CF63D2FEE413C3D2312B3DD6AC82DE4B19B1C494F439CA339A8D5D6FC4CABC544C2E6CDA6C92E983B5AA2AED9A01BED8DAF4273EA26561D0EC7008F5A3C0D47B7C1FB3106BC2324CD05A29FEA3BCB66C99FC2EA4ABE3E0D98F608E9582DE6427F0672699B32BE28FCC08BC0B8541D08AE3F666F6194D1C3C600859ACDA836FEC2AF1B055A7A930CE7D86E9D5B339428DE2E1AED0A043A845F538B6C8A05BF4A6B5D6C38B29B1CD41B4899E95652F21C76561284092B942C38D020C50D842D8B9E18223D159F7760DFD7684ADE1F1B0A66DA0EC759ED4D8A3C4FC99EB6BE6653FFBA6B75CD32EBB6D4FC0191953AE9AF0BF53D76AB145B3E9AD89FB033EE782BC30EA560DC9D5417C3C687850C835B035E69692F29172F920E939FCC6761876D9AD64C55753BC0BEF079CAE9F2ED6B74656AE3175ECF54F796F31919142C1839FD56CA92F1D2DFE37DABC46AD6540EF6563C513E8BC5DE59818F15B5A04A6D503B1849DAD9DB8F2012C941FC9B915CA4B72066EEC063601020353E59891F9A7A527697ED172B3E0E3E1A066DFD588AE3367B4DF89E25110461D54008C32C744D150388DC1E71B57C02C4426E0E605066AA13D815861523C65094442A69FF958804FE6A27EA63204A65239A746C1DA868D401923FDBDE82DA46B00BDC130E47B0F5922FBB03F11F304982810C7087CE0E1274D525F32431D6BE098E34433C12EE94BC601EBFDE661B2DE292F2DC3E37971A981C42533A972C06406636596BF381FA7F53855D2269B45383AB42A89EC7B889876ED72335521317356A8AB0EE2F4181C296548991A0131730BAA099510C16D52BC8380ED4BAC5E1399BE44455355A9D7CE09406BA8EB4F01FA098BB80120EEEA29FD7AAE66438A9F2EF0F3FAF44D7192558580AEF2E957F60B615765F9CE496C3CADA76EA07D96DCDFAC2D82752534868861020822C41DA8F8A3FF51D0E889128E66D2867444B632F6B59635EC5437518625A50203C7DE913CB1EE16BD3DDF7B33B0F87A214697EAD25FAF847B7103650E4BA33A08FF9BCBE33C3E0A3392922C35748A6EA2D69EAD33AD5FA4574D3D552EEA45A5DECBF4CD0144F8F2F1309BFD82E3E44F88CEB34B95EB9FE616D794B84643042C79087B7361313AEC3C3E54499A6C9D93D594AF2B97C05CBD1D37FF41A588BF7560BD02F14CC0A01CD6F2D67B0B0A19511A814E560F3F2F90F59E767445446EE3379C8117A12A08F717214654B5E0578A77F7426F1E81463A05ACD1B56C39CA5827BD05D47C851BD282FE62A8F681D32B7F35BC590923FE301EBD67DA98A787D5F85462C6169CE1261E479112D997498D1D67E482C9289502A2CC6405D6B63A24BB36B7982D3910B259F4C785AC6E4A44FC042D9793E532BBE9B3F47DF4B5D22191FF89E73705BCE97DE3E4A45CF323C7B712ED8AF15A11952E5A07ED16963A48A12DBDF828F89C0B2524286BF6A9A5600807661E4FB89CAA8E1CA4A3D3F42FFC2D165B599C4D29B78A68B639996FAECE9B448899D18687C5E5F4DF05C7D68DCF48816B44848E896FD9F8BEEC976482B2D41E93C9179ADD132CB47A2C7287FACCC7E980B16736ED9A604741E26FF6851F2C4794EAFBFBAA2CC1B56934DA6BDE8F4B85FCBA935ED5E082262215D5FFA37284C29F25077D181F08ED551601A94683366C48DDEDFC42BE2B8EB8943B18E30875F1DB91869091A35240F9A4EA73F8DBBA8AA9A691B1BF0B9FC6BE3B2AC92E53567D57E573A220D002B9EBF719B4976181916FE9780CF12AB7798FCE14A979C16B4DE88E3F7D6E33B589245865AFB8A2314F6261EF701AF46658471FD5A6E8E12EF474FBFF32731E016CA15ED1C0872F7644A3C406108277F06B6C81AFA6B01E0025FAAF942995E4939FF50278704A3644295A8A9BE41B183F3B7C0CA4568023EBA0E213BEEACB370E20C57672B1DBEAE9029F353EE516268AA3D12AB3294039FB2C4551F039EABA8C71FFC3E466F5F22E2F804635A87D820764D87DAF794D0A5ECEB741BF7FB9448B5ED96AF4C37F206F549E77C6CB769D3957070E4BD73410AC1FABACBD410AA80E5E691CCBF5081A0DE39E6A131F7372CFB307790BA6349FEC7F0AEC82F437A5049D3CE60CA6320A940072C3E4C8814D2090AF052C4127262B9A59CFD721467C573A318DB4E47EC8DF4D2840FC61E99CB4BED982F87DF4B0AE829D0CF8A53830EC62FC389EE83C09E2BCD6EACF5810A2152A38545F5263B5D63ED0A1BA4C278ADEB3C5B8CC4D6DF1C5C828DDEF80E42626A7577868DBF000000000000000000000000000000000000000000000004080B111720A4117808D9D05B702483924E99623E778E7A3B7623739AB7AC488ED93E711EBDDEC383BFB7E06086FD0C374F4668AB744AD99B8AF1C75309B60F55DC03FF7BE6F23187FFD5CB224068568CE2D06ABE441557B04A5A0C2858C416F6F7AA89A96ADFC2AFC54E0F31416CEED005B7B140B342652DAC7BF401FED4D94D475784936FCEB4B4F334BB14BA55B1EA9A36E2B0591287EAF4ACED997162691A96E7F59853E609ECA9A225F615A49A12763D80B5DFE6F8638923C39BD652936B19B944D5116F790E866A61947EB60CD1F3A1F319710D0F40E487EFBEF51FB4D00F5DBB94810128215F72B1AEDD74A1B1D237088DE3098417714EEB67D6A3E6BB647B6B0AC6D0BA3089D4CF6252B69C414E2BD6614429B6FCEABEBA50A4B53C7394652ACF7DD9403AE14436ED5FD4D1C9E238A8399A763806FEF5C3742C55B7159EBF5A13B271428F91229C191D617808A26AF9190F9D445BFD3B273702BC3E7F610854C8E86066BE7757960A880CB6727CEF19DC7B464C464A7DAC9AE85B799747B8488A4123B6BC7F0F7C2A8E53FD4F8687075B4E25660F5107ACF22CA688057DAE0496FF15A3EB9379A9F6E22FA43C932F137E389478C05DB86060686AFEAFBCB9ED79AE194C4146A48CE5E07EAF585279313851CB864A50075AE46C1AAB3B3CB920DEE2652F5AFA0138051C7C980946E8D5E18C16789CD184DC5598F65875EF43418DD56E11DEFB5A4A6AFBCE041BB292E0E2EC563296BA4EA6CBFDCCA32A18C8AA395515A83D0FB7819413E5AE056FF0EC2F63F1D52A8BE0B334A628D00995BEC7E46A34BCD2DCA0E9C5A88E0FC8C43843D6AE074C699276293FD8DB2BE48885155688428C2F5A6C6C91BD4A03CDE2126205F9EBAFE319D1B4F80277FE99211A09628AD840046EB9AA568EC71252CE9F69827B677D9C0D99546DF5A48A8D253AC0036DDAF4D045A70F94EC54BF5F06296B2C2617F2B0EC0B8374DD28DE269FAF739B1E55AE1846F548FB6C0403C5ECEE3CF9D1927E317F0D07E11AEBA01C240FE17C6660F7CB32305AF1EB6DE4312FDEA6990DA4E9135DBC0B88AD0AE0847E1576F3C2711B785B846C7A4B823688E4218596CAED583A90DC46BB9B27E00E4C1110B65F77E602F043A8441563667691C07162E52A53CD76E2D74DCAAA2983BF2E8F02CC30B05BD4F9AC731931C59F9EBC038FAFB09FBC886F4C4191352206BB49ADAEF9D74BD08A5B780FF0FA301343F5EA81D36912ECCB0FF24BBF0BE6A8283EBDECA79CFB22639DA38C9C639C4BD66FE5A75F0414FCC1455702856E6FC58344BF02998E17E967183AE920B7E04F58AA09145D6DA79B65EFCD18EC55BB9CFD53914F80D73C2B08BB754AC63E4C82D44B72376A544D97394B7C99678758B15CB94E71F9FCCF674B29ED5AFDCE452959BE5AF510D57F9E5395A576EAA1FA7BA9AA4122A779727071FA485C005B447760410DEE20B7C2299B4A0D5D9E5E4E038A19C87806C3FB875EA5BD7F47D034D7D5FEC4BF132B04E47574172D392EA7B371516190AB81C67B45FEF6332848A51B6C7DBA90C410A44E9A88AC082FE296A7435E7D2DDFC645D5AEBBC29620525757DAD1B0222159D658C7225D02374EE6AF479FCF1AA28CD91B + +count = 35 +seed = B2FD7BFAAFB667C9DABE5915C3BC271EF41F18588666A6F4990C09D098E62DB590110DF6A56F08C5E0DE65B00F91D60F +mlen = 1188 +msg = E82F5ACC7C1A326D430475357629D568EA3D0DBE131114781D5BF8DAA32FDE9F3CECD288ACD14445678C5EA6D3AFAFCE48EA3957A6AF8D8F23F78D84130FB6419F706EADD430CC85AFF48283F15602265059ABB075E011E3941834EBE70787CDD55F1E604C6B86F761D94C4F5E525791333DF6D43869D6F36B212A8F35583D38A21D0947CBE26FBE6A36E189C73137F2F2D89F48566D04D2DD9125D2EA4E0B2A7E5C1E9D2EA036CFADCF7BB28F6DF3B7D6395230C9D39D1E7558EA25340252708BE23EC6C0C9A0946C5C5AF0FE037C254D1A5B2B70B8F916CF37945BEF76BDFDFB19A0DAAC5A83A6357E986B3155CFF31024121634C3700CA99E5ECEF1F2E411C6621FED6092C1AB59860271AC7F431E568075D59F71AA18096195F30BBEB1A6BAC20E034F83C72BE0536315879F1D1B7F31D38C12DD8E97819B4803D02BECD436B61D1296CEB78EBF857E34087EC8AE8395269B5B0770B3423B39638910D2A3DDFEC8502389FD8B5B09FFD10CAAD1A5C86E7E39629AB09A4ABCDD00FBB9821F92E7DD24DDA83D1D9762F52A89BED6C20648EA04FBAD4233E5920AE83FFEC28FDB5E432929A41DB782B2CEA8FEB40CAD0B27903050B650477E5D9443A536ECDFDAC673952810596F1985427359D9E4797CABCCD2FA0C0A2394D853B4E6F8E150B3E3AB5136CF476605FF5FFA9067C0FE58A143B50B18B09256657CF091132D449A6E7EE79AA870E9DBE46BF840EDCB983F585EC2856C059808E72B8C901A25D6AFD5372F168D533052A6D26418E035D87D0BF818ADEA19915047C8D824A425A8C7915756673E0F5FCCB1B4FE7C1FDFCE505F7E18F023FDD32A605906EC48E0FA755B6D87E47711E158D672C5FB4CD3B8D1D13FE9EECE58453987CFCDD87B621B870F3AA27E73B6FB7FC0A6757893B978C63B7723C49D1005A1E5B1A4D60C4A2FEF392DF7EF97F149B499164455633FA485BDF92F804A47C8703D124522D73887A2B032F10F45343993FFB009D69E80FB54B6999A5BDB2760F8BCCA648F3C52BFA1D887AE49862DB4CBCCC7213ACBFDC48A57C3DA1F1EBBEA828182432AA1C593C3E5591C825E5706A5F9503311E91EC3D8F4A9554C3DF915B5FBE0516A7A5597ECF8862A8DF286ADA96C90C9F2783F7F947A18EBBC64C1BAF24B29F77521A9EBE09BECFFDB902EFCD024046FD3E6182BF0C84BD3A0A5410EEDBABFC60114E5DB28B0943D79F58F766E2EDB16759850D4CC3A9A57AE073CF6F3B24D36A4365E2BC64674259170B6D11DFF63D0DEED085B6321C45F218E09351AA0D4155189CC98DE5627A03396A067AB3FEA2C133062E3823FB1CAFA5D592070C8E82ABE812979DBDCB6D2E595F33830AD0E8E2F9E6CDC4D9C74B8026EAD1815DE36772769C4E00806F79950A40C979C14A4BDBFDB79DF1DE01FDFCAAEBC93DDBAD62BA166843A121D2B144559064E9DE9E310DFC93D624C1061BAD3195D6C9F46DB64C65A31E90371F9B644E2A15E01C262395269A9AE83F50776F852903F86E5518BD008CF1B35E78F910D48C0B7BBAAAD5DFF2375C55D56B8F65B922229D5F494EDCCD2D676361619FEDFE6BF0BFD7E4C77FC459F181120C4430C409BA89D2E5A8C36CC6200497611D9D705DA6AE1ACA4E16B389D632A982E017E1DAD95DFFBC7A7D7191E7B8FA1C0ED +pk = B642C23A6466CD8B2A6511566CB9944EDB585B1BB16E881C927A38424A91EC0F1A38F53D477BEBA8AB450805777786EEAB4D1FCFE1962C53073268D2894991C5A542B78D79C9A889C3FE665F5F164EECCD6CCA65172E9EB7471C7C47A443F8E760638286154A3F352224B41603A5B76E6D3AB9713C56185B372C0569944F587A38E3916CDC03190CC1E293A96F48D012B98FDC99818653C54B1F35912920E8FABBBBB566A492797018C34644B85E11D642812D54E629D8D0F10D1A9B0B2FE8D6E56C5BA38A7F48B79B085DF0A14F39FD9BA553FAFA0E492F1B52FD6EF3A7F368FE67E12E8CC39454A9AA3151D188DDAD4CCC9688E796F190744696F626FD591E871FB1B4D52C3E338E844D9AD93F5698094ADC003561C592486875F4F2CCB0FCBDDF12AAD2AAC66667BD6D3A01E5223EF478A3AFF102A2B398DCE21C28304E3B77F2B772BDEF71C4F9FB3A28201F845D569EF7741224B6301EDEDD27FBAE181C0256B5D935A4F30EA1A6142D71D3C797247134ED7E467C5F79B50228496B0875E17DA91727F2F2E9F002630B6441604FA71FD26AD8E88D493B5F543D3185ABADAD896BD95BCE5E79F0BF1BD6CDF4D47A6AAB367C141EC8A8047BCD5A0507B1986C5AE9F627CB660E9EA0ADD1B25F4DF6137BBFA51BCAED7256EB2F8300EB53C09CDBD5F10E304D2E4A21C89C731EB4A0437338E03455BA3C057A59DE6C8D8BBEABEFC92D8ACDDB56DC773C7832F1A1BBC5C241E96E7B96DE11A6338EDA32DE36416BFCA656D903BFCEA405463F4605D2961C9809FCF5EFCC0F19F5FABFEA59A95161B7FDF89543214CD613175AB477C5153B83D369C00BE65C702D5215041718960E983329CF86C46C8FEF44220846842487C5FDC171D2963B60D5E825084A5CB3649EA6410AE97FB9EF2D1E82024FC6C88B209513B01EB08BF77B70A1948B3F72B0BDD7A72968D73E73337CE647ECAC3CBF842C9420ED9ADCC1C4B4238F6705DD2063F3CDA34E268462327FFDFC1C39989599A2B7ACFFF44AF015DE4AD4C7BFDA408653D1CB6726BB098AFBA6AAD2664354A8BBA1297BE442257EF20B7A7EE251A9C3726D9B254AC54DB3D96E91C1107F752CB1727301220D73DF6B22A1EC97EEA79D46322AFC738B31D06B43141679053108E375C822FEBAFB4811C99DAFD0AC8753F2B610440E1FB669DFA97F16EFE362B9F85A1F5C7EC984D1638B31E44135CADB81D2AE8C6E1C9AB7CABED6B356BBF4D1A09C72BB1249C2B034C9575ECA27835D61A8185822B83808F2352506051A55515663D0DB82641CF70EC8F6F282024CCB243D4423B3B6A18830239D5E2898A58025295FD511CC6B1733C28EF4338CA213819A494DDECEC69693B14489E864B3EB2EEDF18C722049B24628DC7C7B56800FE6F69116E6FFE6577F731AB0059035279298990F482FE0AE881639E7929968D73C349B16E59F15A5F00B7D645AF974D936F6FE3F40D42EBB3B3C0511ABA0A38E0A1504BD1A306C5F7CAAB7F89B3ADDFB0C7CF4FB20775E44F07D7294C3CC6D3143BF8D196E5A1D0C284335B01E08D07109D07DCE541648A4DF293AFA47D70D825F854B8E5761620B179CA458D30FEBA9D9140AC859CDF9AAEAEDC2D8EB5B3FF050165C68D8FDACB330604C9AD7D776083BDEC194B4420D673DE925B52160B026A3D1243EEB730564BC65EB18077317C8F5C7B6250119FFB46EBB42418753C005C93E502F23AAB59246C641F318A20151452E739C788454E76576F0BF9AF0057119C0B0EB2BA6497D086263D5E3875CC5A8F598B9345D68967F59D87049CCBFF279006172012C1E4D2EF3AFAF79B6576E30A718639436B2C5EBE753F5DD97239FDAE5C9CDB3A47B5584C89AC4CD794DF3E6203E970629597207993032C777F34722A312DA4872311DBEB3D97AC960A3B7C08038C1B8354454762756EE4FA4BC38A8141EBDCBE939FE29DC578E10D319240A5D2914BA4B195CA32E73B66A4B32166CE1F74FFAD5E008FC2FEC5EE0393DEC1B797691E9B10F643574C7929FB484AF7F2B3C85788361F7CA73AD214EDBBB3BE9B53C58D9B12AA41AB6920699F45FA721206B98447DD8BF1CB47AFBF7CAA075A3F0CBA2269D4FD5BF734F79D0525E9F384554F626509F877C9244D08AC49C7CB7797036EE4CE2E22C6CCA36EA39854B3EEBC4A0380DA10B627BCE7201CD4566656E04086E6CBDE5732171919C52BD3160B045395B6E005523C758BCD01FA19C0645854CA04B39C4183CD34AF65D571086423457A323E041529EA4FD81434359B00CC15E3A6059A06B38A4043F4BD42AC2E3517055E9F80F14B2734AB3CAE2455A0496BA462FEF2D2CE53D74E9C1A9C8F1B4AB607FD88D8B8A81B8048BD1C9AFF71760885539683CD1BEC0BF936AF4D60FCA6DBAEB637B45D0C35AA98AE474AAACC1D2C92746418F349B473F7567A71E5F6E541E9EE948DE8932BF371F58813DB7B82ECBA6B5FA24085CDBF64B6BA764A7DC9F2AD8BDC7A50C32C1B4B4D4F6710B4F095E3C674D55F20A166A9812DEC950F63878A4435FA43D5110B2990CA86D17096A62FE8BF92F562CB76F2CE11837B8E83924D4CEDBBE50DE1DDB3886F7A0B361FC8EFE06A9FD9AE2A48CABD1F1288A421BDBB83745774435D18E73AE005E07884EE524C966F10F9B890FC8E6AD8656A0224A41277AAFFC2F33867169FB1FF51462F7E9F4146706DAD414DB1252DB61CAD4D0B0BC1A1F3EA3598959E531E104D76AA3C13D6D74B7041F947E +sk = B642C23A6466CD8B2A6511566CB9944EDB585B1BB16E881C927A38424A91EC0F7A6190839C4C20AE1620FD1078BDDA5D1533C3B454AA8F2F804562A453156E34D56C703326808D5CF5190A4776D797ADCA3D50ED0DA7B702DCDCB405D1D6C050C07EAFAF5FA4B09B39A70552CBBC6C3B6E776863B5DB37B047588EAAF940660A77310313350360233514411458611748021202012444353438586486416812108076605336354477632075577447416888018286855821837141884125646667775272076245502075233523282766153582287517173043165620885112732540362456511171653575756436555086657757463418278862312717776208587714603046847205412122312865522283230352300085446654304303142888873516121380241033342075005604667105764122515382480340370416475280650118674187751640728823537135417545004515534423363111644084845350445002157671385605013820737666864644720087622052857467216650088435580684566116052438813417433106570780713010717116122017313152257616111500323152455647138856815248810742068017226534867775624126431278562822016722362155044130807688230152412753020276100387227487432517260417513386868257247463443448277285214404638260466204540850845315820385165232225523870630227163812364700687312350776371572173117104235545811025786105600661678038418715371370227435550572104584000186267475512322064048651604611808740085635462376060737168564710573062415743066804256822148048723878346731874060055103360331624456880172861832322106433063250572082872616242540888074306472188558161270807057552205875631867324682700282636317556866781346742380471070827425033158234581623033820208562510602470713020154375021604072286550435457127340536387302553058607815088751561545856013748736063707554386838861740516332082400576474667552412603527380563432078465350414147066551367825852400133417471245855620688148727344840876154404072672611534724813133007748862477153126321182518313336838181278024624006120166538458321276660674072723352671304868740826712816614383178015551141450528682513415355668357807357118444432827777078825871233060208081810575865167284677041004828546303866837178336372032754876103387120288535201322817241520443205427321081471518302602386345605341855883817887106468645641408010576656317510848504870808122804084172535074745302871035561323853841625867610552787516548730500435156152087645664505728554428108367854547152802401762203310363716060865272603881246676583333137701158148613475203785601027162671877684057137736344568320186078133623771863442673805835237820821815058033545643002366864513156515108830123426631650533505866560047834356267805101454554580071666252711312568437753144324788165704400356403110023033423416277126317551245006216318811541344037887466018657555130624335880417207774488060056724828106254557642423143750705824362521330833481512064016725307515346760512540330837104533356680041574622435015673362773546076542322143755647023461257333064483074140310414871673315428113363621332871026240602484008380834658450223824150840817272178735775413446046150380082421760743220840446057474222353702317802768536337107267617700056232120528058265270265251568500660166320057283387763685301655813550310318766825155511442562885230476523858434162402705377310364207781174168802423773173114866527241311C8FBCF8CD81CED40349883AA76487404540C4A01A0D800C3A10CD4E18F2F2CF09C9EDC79B10A42CD28ED1FB4FEBAF906D7C3A21694A8BCD4ED818A57A2DA4A360A9E1936A56AA64FAC9A9626172FDC4E37AA97091F9838E83B420C28C5350F93D7C15F71CD6C08A6135ED58613A8FD8BEF3E084702429A0567C94C7112A87CB20904D1B56521AEEB8910B1FA4A2DF4F31EF1289BA3775F093FF76613D864280B5194CF5F26B7C59CF00155C384BD93CC30983A73DE4953D8E817542B615F43D572DF965A457D24D2C0EDECD43BA96E7A6CE9486AF20179A07467752AD61F177A5248F1A6E4385009327185DA50DA201A18E4F2A5DBF8C6C9CF2368DD71B1D8DD9A359A8995E05E8A6FA5769F2480A3284100516A84DC6BAE6763B30F1F3EAE26CB5D97D1980D341CB48F19EE72E6024FC11554E1D1DFBEDBC5A26B352725FB2B6C9CF0FB260789F0E96EAECEB90388A6AC539B8CC7E4A33EDE75FF595287A3FBF8F98CAB8E88F1D6BEDF4CF7169267A15DEC94F55D8711F1D5CA087082FB0E7B3E162F8DFC70E0978EC93B413A98E6106A86167FE5BC2B899F1B5BADAD5381BCC431034D57D3A8A8E1798CD02C97A548DEB1950A2250BE6160A4F612679195FB2D56763C19D7A439BB91CE94E89A9C55C5ACE247EB11E4DCAF6180909A5395B5AD9FFA8BA48062FA3ADC1CB426C9BACE999B5389277ED2A81B52E4BDEA4F5D09275C19DF60F0F9F2215C6ADB4C242774604A154F675F9030EEEDE3010FD3318D3FE2A7A18CAEB6ECCC68CF7AB11F3E07A309D0DEB2C5818615CE7811A83353D5C7F5E5BBE02D6440A8ECBD99FCC565F6B90E741DFE5A8FD2B6B0E62BE0D5DBF2D94FE2A88A133091E3EA93CC34A370FB9E4DF827A8D8CBCD357559749BA739A7F914FDBC3713AF1B396E64B1082C31D0C1EFF6C69387BA2BF8B4EAE5BFDC1E3C42E8C55443EFBD8BD2BFADA36A6D625BE9129A95CCFC5A75F557AA9A2A4142513D1FE5077CE8E549E5B0FA710E3A5D0234A6695CBB242088CC21D51F66838FBB2A6301AF72C9C2ED15671B60D65E2EBB0D50543E0719875F289E0196C5E13E34CCE9880A8C16181571658E321ACE8BBA25B5449C8AC4959203A9FE4C27BC506883CA983FE3079C0FF31F5D90AAB71F127AFAEB56D0E517D792CD45BAB86B8F32359ECD304131D67A4B847F40605AB9E3D226FB3D14BFD89AC584FC970984ACA51BC27DB1DF3D4258A68B3B103391EC2C1488B323C6EBB8F0A1BE9D83CB58E6B1EFE30B3CA8343186D80F6C506B13125E1301BBA1A8C33BDC88A113381F9597531CFE09E1F9DE4656DB3CF094A01C89C5A6E4D49E92FCFD8F387A8C256CC12510741F4CF45C61928E9C546EFA5059A4B6E0A38DDE5FF8DC03533CBC2BAB7381BD1329D0ACF43E18FA1B8E82302E811F20F1DA2D635BB5C38662001BBC5EA08801C1541E9D66F12EAEE9973434C0199F6DCB163B2C15DDC1ABAE6A1751EF894304CD1DDB51D5650D2C64E92AA0E50F5CCD1EC85E55294385CA981C6A74B1C3053C4B3F29F5DE92C63B8DD6046144F78F318AF703AC79ECBE205CC48ABB885CC14A580286E8068D3832C24BE3516213E092962464097F142D8CE015DC3F01056FD9E7918323D3F29BC5733280E5549DD7B9EAA0D01B60464D9787BFA7FBD943119D5261A52C206CA6F8483FEAB4706DF96FA4AA7B35C76AA91B65E0A08073496BA2A511F9084A454F14B97B21F0A5D4693BD219486866DED805CC29D00A3A06A9275548D0873DFBC693C579B6CEEF1129507274DB085ED3DD4C14A80FBA230EFB14BF41BB6568E93037C7682E88F5A18C4911449FA87E38AB968F33E91EF928B3C88F42472AE42CB689CD94FA90E8817CA5E46B696699DDED3B4FFEDA59F3D5D3DE590EB75DA810C563BB5D9C62BC582E0BEE57FC85E5E580A738F53E5892785DFC95D1C004410AC2BCFEF2B15B13BA88092F4B36ECE6CFC2BEF0CC3EBD71B57732836C86501128447C580E447A9AEEAEF6E14D8570657598B0C8F070E4B9047E68E5CAEA87EC245B71A5A6E4F7BC67D902E95FCB367C0B2A6AFB5746DCA77BD46048AB9FAF4499C6C9284F5E54E88511EADB7A22A3C49F1DDC53458B1B83BDA3AEA5E0FB5A2ADFB40381838CE9CFC3CEA68B29F001C45EF34D68834DA6BAE03677D661B642640A4AFB6CB8F1D7DA56129B29F97BA2B7B0747A6999A7909DE190F253D9D35F38FAA8FE834775FD6633DA07C911AB66399130EE51B2B243C64E3F1C7242FEFED9BDC364F222B864E74F6B1C800E3FC5DEC296A50313A550146213866A0A4490354834E2E45EB1B42C74B8304058F56197609567009ED10F119456C2ADC79396101D33067D59451E96A5F707629DBA63E5AE5B7CD3C951BF7B87A4A92DE6393484FD2BCDCEFAFA3508EA20F880EF865BF57109A08C3DA6FEC597556721C7D4F2EB07DA54ED680ABF5A1937682E94909B0F2A4D39DF231C09A778914616ACAB4CAD2DDD469A72D022BFBF58D7520410CEE8B54FED4FB047C031DE930C1F607CA642F81DDCDB062485C70424DFEC3D0781E053F5CAE697789FDBD0E40693B50FAA7B0C508CEB444037AFC85230C09232AF489DF607DB3A383E3D984B80F961F48A46CB37C0663C05DEAD348C610E8CA0257BFD74421F72C9B236B42741483BDEAA8B7147D053627E8344ADC5D43BC9C391542D5628EF89F49EB7763665FF7DB04DBC2F2D84C1E823BF22FE59F99B647851AB756D6D24B1FEC89BDC7592E4B18C68B510604DD73184FA1505F754A05135BE45A10B21724B37535384644BDB2CBB030FB5C183EAE868CF7BF8BD43E15BBC98C5F5D6A7A5ABC1758340DB6AB67B2B2001F59F5E8FD2164C8705D08A0EB380F426CC9914D2A7699093AD20E1F3F1655B55F54945C11C9E5FF123B502792CE38748FFC7930DB0EC5A2C5378C0C60FCD0AB1EDAA374A9322C2870F77B871E191B7749BE9D54F58CD2B678F4FD201344FB47FA5DA531535CCF5F57F62521AE54BA81230C478699E1F5DD3DA7FA9DF2256D2FDC75070BDB3B581F3502F7D6D99052C0A6C971419123F6CB50D4607B8F2645074C3D2EEAE5BB5EFE17C75AC1036944683C87C744219922D36F001E12C08D35B559E521154290F53232483CBC3EA18C0FEB83C9A77273B6425E76F840020C97A2EAA3D87C654103AA879B8FC1D5129E8725CD4879C3AA9BA311A81664EB488DE88B86EE3B05BE6D2EE79833CE172E87ACB2463331BE87C8A0C0974AEC1C998A91DCD97FF741C565C63144F15E4FB7D7AEE40F8FB83BF667DF98F8B486413829F7C6D40141C029007949E3800F8164505F6C3347E1E0877222E57AC86AAEE243C858496D4D260FEE4F2D67C94BA08236980D3033FBBA43451794BD04D928CA98566D6A896D0201008409E4552BBD7DCF6612625C67FACE01FB81CE098210F5BB80347FD0393C7D1E115699692E3DAFCBD885076720A2C70596C890AE66F2AF815D72F8B7E354BEA2D41165048C9788878E8D1CF2E2B9EF5069174E +smlen = 4497 +sm = 46770AF51D2420D289339F1FF68009AAEF36D773B9CB710D7A5D6BFA7D57CC0760F07518CF1F4FA14A35E0A911801EB820A3AF1A032685635BE91B434EAAC8CB1A55408376765D9E41A22BFB82E71B37A638146877608DF646E3156A60B23DFCF747ECB55A93A4B543A4BAB4A7D7E7570319DEECD6CFD873CDEC70E7076C97FE30A91AE38555D06B7EA31ED43C80957D73B3A107AA4434AD8BD4AC7652A61E3096240FB38FC32E7B9A198205D5C769E6AEC6CCEEC5ED978147C6136F74C05E3C76E07D1696CC3171020641907271361CBC168EF0C39D5134499463A186AD077F031AE4EEDE75B2186E51028D4308B29ADCB41A0E32FCD29D2DF20125B99ABD8047E582632DD34269D2EB9303E89D9538E3ACF075C4B45344DC3D4E47328F145FCB1EA901EFE78C519D2F432E415C56B5037E4B056474700070E2BDD59694A9260494821F0ADBF774F9635A29BD8D99CA9D705C609EEC493E84A4A2B799054DA79E885C083DE48DD6E9073CB66E19C868807497304C71977DDD21A5EF311252304EE7413464779DB6D1380148E0532112C26FEA3DEC4C8BE4435B12823516D30AA93B3D98C8CD996258BC8F4FCB85DF3B38FA207DA344A8F61B366A833F4CFF043C6E93F65608A73CCA70C139C97F967F7693A852E3A9716EBCF0C4BCF489D6C0EAE8D47022D1E270EE66A4BBDB5D123516E9AD2B088DC8A9BBC9ABBB11078B2D13734EB38338C2907E4550E2A3D2EB374CED413E43D6CCE9BEB3BF05EE8023869521CB391D02E30339FD585E3E3F39B47B5B4F82C4B9CBA3F47490E2BAAE915C97DBB8BBCCA8E95C83F05043CF504B774725B257BD39F6875EB5C1A99CDE9F8830E2CE454F0DEAC948970506F75A2F5D5F824974C1CA7BD42D04637F98C23914118F9E598A2A61419050E943E6E4CDF9D920B0FCA153395FFFDA14190399654F922084A51CADDA17AB39BD7207A8EC415D5BC259EBDB23752CF5746EE695991CD7EC1F7AB26075F86006647B8E19CE16AEC1917F5E5C19087F4997EF54E69B373129AEE2212B9A4C462C2745ABF38321DB4A3C6F9A00E989576E93FF7458C6EBFECF541BB79CA2718DA0E5255E43C15C03304B31ABD96BEB7C07C18C77A58E7397688514E419E99A0784405FDE823C7DD7895C221070DC944DA14DEB8A51040072F0616CE43452EA087A07C5CEE580753366DF7F0503930BA67E100FE5A5FA1A6C86029CB99914928355F974845EB9CC8A65BE84ABA65CFC6F139487A841F0FA5986C24064FC2EE506027D1710C82EB0ECE03BA6D1AABB7BE1B2E5C7E8B3E5AF33E3935BA4504D595821057805C8381085DE9050E15DB386FA3E413F0B6ECA1A166C74DC950F0625B8C80B833A9E5AE41E74F39828FFEADB63FC0FEB03A01987A6EA7715A42623AA0D31644DE9DB947B1F48A83E310F5EF2B453B83760DDCF4D27BB238F3690D928B0C2D230F4F95EAE6D27B7D5439C5421F4B48D603DBD5D979EA8A86138727F574DC9114459BA2E0C7446A285C8424B9AC9112515C225B873C6D3AB1637713380283F7910C331C492CCF5B1E3ACB34B200A1352967CA78E615A2382ED897415053F8EB63D4D16605ED4362C14BF60709169D83E42E511BF181A2F11BC4F8B06F2D91CD9B74E1B8A580C8C4EA0A15A2CBEDBE2F6F56741E82993167C8EBEAD4144B5D6F9B21C996B948DA3B1B7723722EC929041E39B781E4CBE77221E729780DB5C207EDA21B8BDBD8DB2C61FA321D3F225F038D371E4EAB6F5306DFA66D7E52E9B9984B0557490A4E6FFA43CFA869DF5547C4A899F3231B965546C83CEBFE2C9BF84EFD15A8325B1688DAE06F91B795588996CEF7B31C00CD5A991BADC0FAD9A7B0ACD7FF1D39F6D92E30E2A86F5C35816691FD18F69C8D6DFD6FE1C4D44B8E878EE1F4308BF5270F6150ED923B8721006E155D0A2C5A28F8B6D1EBFA71108EEE54C28696BCF763E38E29EFBC000F3504F2636D4B5876B17954A0A4A91FFFC228B242F9658962C127F9D3EBE94ED73FB4499210DCE092A5E38D156F59E69D604CFC5048DE315CCDCF288B11F75FF68EFED939D8DBA38629A9831952740C8744763066922AA0674F9D7C54E33BCDAE02256B333A1F2FE9787C4BE0C654E222DB4F0FD3D5805BB54F9B8F252931F3D2E9A21F72853C4EA35BF37AECCB10F45A03F69073DCD7FA2131E296D4A912AB86287C604692B3DDB0FEE1E26DFBBB28800C13503D10B6DA308C9C29AEFF7B9F1AE6C3D6F14723C4F24D23915A95551D9BF9580B5E57D95ED1731EDA18E218A8A068B2A53B437247F555BA4E803B97E9A5D5A3D045F54DB72785BFC810AA0B0314A0A74A6DAD01DF58D8C24BB1C26B3AD21E3FE4B96201776F2C600F1E54EDB5E6CCA37F72B83FBCEB0D1C5ED4457524CD4BE7D5BDCD84D97B72E15EDFD3F53C9E98C0C5AD68C6B0882FB2D3DA17AC4625F3EEA20043BC24CD140A6E23D0FA0BB58873A036718B067EB3CDC6ED1CED9196E4F7553D95BC1DD91303C18DDA7E6630E579284926B30FD995EA49B4BA798F5101BB6B39DBCDB2BBFECCFD7DFDAC233ED8CFF577BE9DEA03CE7BEA0AA5E7CF9B50D71A9E6757C3FFB14ADC5296BC4DD6CDA21D92BD93DB1172D0F9E14A710796292A666D2B74B787E29E4E13911ED020428DC73585B75731672209F3FBB1F7BFD1C6267ADCBC5BCD87DBD7B0CE381F62C6AF0989C3ED60A9625671940E7F6C8176CE594313ED63630B816EFE94BCFDA9A73DC5D016588285A6329BB6E99C1F4CF12F14338C818EF761463E9DBF647359C20A019DD3551454C90693D56E08CCDC4824F3EEE7859831539F8E53115A654048419BEF2FEBD9D6B8AC08932BF14F53E276464666CDCBC6F93CE6A7977E02183FC012607FB91F7E9F992B86AE3D41ACD3056EB1E7936B4CEB5761755F45EF8A9F6622ADC085997CB444B87DF2035AC03F61C0A9C3A54AAA72FD8E7FDFC6610D7CEBEEA37984F676C70458447B3B150088B9A8DD69F10D4DFAF69F3C9ACD566A2585001F698F5351B03CCDFF51634135185544F7C865965A2319B7D6B5BB7E775F70E7121DDCF3CF75C446D2A7A25D5F483245573A9C0E9099C9192ADC64C3D04B24D0D30E7F69E5D02DD71C41A1C309D726D63F9721A95F26188EDFE4A7DA45E6BAE599475DEC5FCC2676E37FBA0E1347FE32E32A506A149A34E5E41A8523FB7EBC3A03AB44B214F62F018C9DDC70AAE476AF8E2B55DF2F9B0F43F7945945A0FF93CC8313EBB7714B756262A47C941C1EEF938FCE6177B368111830B4607EBDB3BFE2C58EF87AB7DA3ADC0E27C152B87FB0603BD59A1C8BFBF4C700454B89BF3543EFADAC916BBEE95F78D2B62AD3C50986CB2EAB2E80A6F62D305C850039217EE480FB46713777B363AC33E6FDEB705B1CA62419B5212EFE8AEA44EE992591935AD72B1EBCDAF006E9635880FAE534FC0D764F4CEBCA87A4F563739E737E18F04959D6A8251D69599E4C81DF13CAA83379711C1FDEEF058CBBF528D8F1C73A2F273EA94A4C7C8F4C0051AA366A660BC3ADA1E57F687B03D019FDDB9031848DFF9380C477F9D1E30A2408949CCF794EFA8E6AF98D2C55A5A349A26B932449A2ADDB4E36C13196A166E6DD62924BFA0894628FE18A3A6C894DC8065DCE6C57A2BE602B421F313E01AEE3DC4C65E72ECD3654BD5FDC85A09CCE8249C234D8A4C2C3158FBC50DE701AB1CF653FD4C569F682BA9B5C0FDFEBD70560A976697907DBDC877D8566188CED0173B6DAE7814BBF257535DC56FEA47EA962582BF6EA76691A7F22F7B269F566B32D4B3470F219241E81DCADFE191B537A4B97C79E004F534A816748ECC347B2DAEE4E3A3FF4A8DCBD38E9AC1DF4B5D68D3670120BC8C4E3753B9D5B74481F148F823EB2A228AEB41E86E1B894170AAF9E8DCDB60A35747F1569AE70BBD453526F11A68216A22DD200E2A7CA66D0E762A28FCCEEE05F79798B5857C8B3BAEB7EC361521C60012294C4A2B9C12FDA7DC6EEBFBBD91DF5AF40EA72EA7256BA81D90CFB9DE4F54F9D6E8E0F6C044DF617EA78619F8044E8F63395CDD6B92F49172BB798237EB058F4E6CA4AB47708FFB0E6137C160A434A65EFE79F35E817B97EDEAB36F900FB48B09AD9D407FE941F09CDB20DABBD0C059E787110F656C549F861110FFCE297AD01205C337013C06181C4987420277C60E04D977D23EB4629784DBA50049F401AD42F4203BE6A22260D70524D0385001E188E7D6130192C72CA591796C3C90B1752B61FC39E6E2CAC872BA4E1B83344DD3CDCAC54BB2DF9F055455660443A94893069969EDB35E733F6F9B738C47F8CE33EA103A8EBCFFC5AA9266114FC7C74D86EF6ABDD09366BF60852576360F3BC3FED5BB76A71512CE39556B2693FCF08342CB7AEC07B892FCE833915E06F204B4B4EE1C48CAE7FE493598C5BC46F38A79529A6319A6087236B6319E902F9E8288C958F995BE678C5DEEA7024DF37262A935928A9E360C97701FEAD926759C96CC2EB9B060E82721EF20A9239286F44DF9A41BDFB3A4EFEA079AAE7D43E5C989BA47BCF89D5C2A5F1872C58BAF80E26B3410D2EF796B0A59FB31E825E85D9596A8ADFC1E2195B0FF2C2D455F6BD8FE2A4D7B7C8D8FDB02162153AED4DEF200000000000000000000000000000000000000000000060B12191921E82F5ACC7C1A326D430475357629D568EA3D0DBE131114781D5BF8DAA32FDE9F3CECD288ACD14445678C5EA6D3AFAFCE48EA3957A6AF8D8F23F78D84130FB6419F706EADD430CC85AFF48283F15602265059ABB075E011E3941834EBE70787CDD55F1E604C6B86F761D94C4F5E525791333DF6D43869D6F36B212A8F35583D38A21D0947CBE26FBE6A36E189C73137F2F2D89F48566D04D2DD9125D2EA4E0B2A7E5C1E9D2EA036CFADCF7BB28F6DF3B7D6395230C9D39D1E7558EA25340252708BE23EC6C0C9A0946C5C5AF0FE037C254D1A5B2B70B8F916CF37945BEF76BDFDFB19A0DAAC5A83A6357E986B3155CFF31024121634C3700CA99E5ECEF1F2E411C6621FED6092C1AB59860271AC7F431E568075D59F71AA18096195F30BBEB1A6BAC20E034F83C72BE0536315879F1D1B7F31D38C12DD8E97819B4803D02BECD436B61D1296CEB78EBF857E34087EC8AE8395269B5B0770B3423B39638910D2A3DDFEC8502389FD8B5B09FFD10CAAD1A5C86E7E39629AB09A4ABCDD00FBB9821F92E7DD24DDA83D1D9762F52A89BED6C20648EA04FBAD4233E5920AE83FFEC28FDB5E432929A41DB782B2CEA8FEB40CAD0B27903050B650477E5D9443A536ECDFDAC673952810596F1985427359D9E4797CABCCD2FA0C0A2394D853B4E6F8E150B3E3AB5136CF476605FF5FFA9067C0FE58A143B50B18B09256657CF091132D449A6E7EE79AA870E9DBE46BF840EDCB983F585EC2856C059808E72B8C901A25D6AFD5372F168D533052A6D26418E035D87D0BF818ADEA19915047C8D824A425A8C7915756673E0F5FCCB1B4FE7C1FDFCE505F7E18F023FDD32A605906EC48E0FA755B6D87E47711E158D672C5FB4CD3B8D1D13FE9EECE58453987CFCDD87B621B870F3AA27E73B6FB7FC0A6757893B978C63B7723C49D1005A1E5B1A4D60C4A2FEF392DF7EF97F149B499164455633FA485BDF92F804A47C8703D124522D73887A2B032F10F45343993FFB009D69E80FB54B6999A5BDB2760F8BCCA648F3C52BFA1D887AE49862DB4CBCCC7213ACBFDC48A57C3DA1F1EBBEA828182432AA1C593C3E5591C825E5706A5F9503311E91EC3D8F4A9554C3DF915B5FBE0516A7A5597ECF8862A8DF286ADA96C90C9F2783F7F947A18EBBC64C1BAF24B29F77521A9EBE09BECFFDB902EFCD024046FD3E6182BF0C84BD3A0A5410EEDBABFC60114E5DB28B0943D79F58F766E2EDB16759850D4CC3A9A57AE073CF6F3B24D36A4365E2BC64674259170B6D11DFF63D0DEED085B6321C45F218E09351AA0D4155189CC98DE5627A03396A067AB3FEA2C133062E3823FB1CAFA5D592070C8E82ABE812979DBDCB6D2E595F33830AD0E8E2F9E6CDC4D9C74B8026EAD1815DE36772769C4E00806F79950A40C979C14A4BDBFDB79DF1DE01FDFCAAEBC93DDBAD62BA166843A121D2B144559064E9DE9E310DFC93D624C1061BAD3195D6C9F46DB64C65A31E90371F9B644E2A15E01C262395269A9AE83F50776F852903F86E5518BD008CF1B35E78F910D48C0B7BBAAAD5DFF2375C55D56B8F65B922229D5F494EDCCD2D676361619FEDFE6BF0BFD7E4C77FC459F181120C4430C409BA89D2E5A8C36CC6200497611D9D705DA6AE1ACA4E16B389D632A982E017E1DAD95DFFBC7A7D7191E7B8FA1C0ED + +count = 36 +seed = C08E846A8E039C8655651919A8433D475F494899FB617DC3B4715DEF0C992C195CE38158B7FF40E0684B30FD7E623265 +mlen = 1221 +msg = 743E5D96B9B4C1469E7AD2B3703F711FAF60CA335358FF3EFC8FCFF02CD020A443243B4169F9123351B6C36762B85BE5E5EDDF8D4B43D82CAA615788406A31CDF4F7087D42DB21AE48A069AA23A8F6D20A1C0762F973E526F011DEC737E986CC324724BC5336D0362525757410E21046A12AC54F2237E68DA036A5C1389E46A53ED8C21774906948D4C9E14F40519C54DBD02B7A4ACAABD24FFD7F6CA4D6D582EF48940296D2893415E811FE7EF0801B35F1C594E6FEA2C293869BBD45618B6F04FC26B55D55A0AE99445AEA12F851B7E58A49CC6A0044F28E3EB838CFA6BAC5DF53B0DB78BE2CA2BEA1BF2DEFFEBD673A783C91A6C9EE710B12042EC2863A9B52EADA5B0D32101BBA8338F7C75CDAE7B7FD6797B25F96ABD53A24A7647A1C91610306FFC72A8DA4D46B1778146A98BD59CEA3173D41D5A53F9A7F9E282B5FDA1AFB062D8AFB63CB19B0E76DF782FEB9F7FD50902133529CFDD7C51AF297895EF6E1871AFD4C3DE93DEFA8FCF1FE67BD27B7EEB0CF37A6A8E09AF1203922BD9B62672D4756519CD09DD9271ECD0285F92030A9FC81C09BF2FAE86F5F50596C628E0BE673571CBC2FD76C563E113004529B234FB50E9E3D6D1F814CB8E5B5CC3EA365D0BC7602B146CC0361397D9BEE9246FBA3A724C462E177D27836093EC009741ABFA28379AEBCF5EF09BBCE00CE449FEC3A3302FB9AD0F010CA338363539DA545F159FBCD3D6A0482454023587A324F5132FB6F4CA602FAB2CF6CD59104427264CC9EDE8D10CD9DD7FA6133E65693DBF744443AE920994226E21D98634BC7F0710DBC37C18203EFA5ADB467B523322E21E4E686B6B85B00CB501ED84153BAECD4D6CAC9D1183E38B510F7B1DBBE5995BCB717529B83FBBE969DFD8DE21183762FCDED692B16502834FE8E7A7C46F84ACDCD2C9975098CF0CDE8AC0EFAFA449DC26840180DCD9353A2F1B06962677C808B07345E8ABE95B8D24F21D751A4EDCFA0E02FF077DE64E6B992E8C8822682DCC7F03CA7582FE7C74E0A9822A02D888FDDE1FC9E73C2EDEDDF32001E918771E5F511EF8F88AC19B76FAC0C812F56938F814D712D99269D7802E47634E541B54E00F9EAF78A421506A88B4BF7332DFC7D79E8C41835031FB449507D19D5A8A512A5C527C95B6F21EE3E41FA43591DD9BD2E4293701BDAFB624E0EA290DA4B7A173003867C4CC3FD814E117B4EEE283C58F5FB33D653E410F68C8962155B8C4FBC13BB750A0343737D1FAB36EBC618A6A7C8E6F93855CB24937B01C438FA713D334DF335D0745582F680627D8B94CBC25F0D12E3B1C27A3ED72E2558B800C19DC6B719B961E0FEE43BFC34E999027CA1969ABA4C45FDAB9AF01B955E948DE951F5A1088BEDA43AC930FE99D8CBB3473475C444F43E928E1A44966265B38FADF9B1183700A95A81F85EA43E5C61DD9B2D67701C95583E8E3F15083717E1722D764B6E624505347C30E5E70163ED9A046C504FF534956E911294D2B9097BBEEF8740377EF0D6C4CC8086422902BF63556CE6DA8E33E68FCFB42707C00693A995D17680B76293194DB217EB5A928303DCF1814E4A881B057BAF2553AC4FAAC8E4BF23FD4074154CD4AE189FF7E204EEDB8EDD594CDC21B5B7D73A712B511D068F4D217C0F91F9D84C524D973D67AA741EB13FE922AFABF79CD2396181143783030FD2D0CFEFC877934D8037A4C32AE8E15B50A6FA4269 +pk = 0C6244CA381E425421508B85B47F9BBDBB10E1F0172C28409EA566204C3151EC1AD8D7642A54E4BCD0FCC93FB30BE4C433EFA645B5A7C127C85C2C0E23BE21678EED74885AA4D1B368AB44E5E05A387DEC936B167FD967C4AB63FC64C3954B42B8880E73F5E64D9A7734603BA04B68D9E340F8EB078A47025DF45B7063D03D5808863F14B77ADCF76BFDE5755A902FA1EC0BF091D850A9CD9A65029543209719F649A0207E044A3A761E4A83A4A4B39DAAE945CF4CAE1BCEDEDB555BCD92782069CE5F276D8DBC106D6812B435C9231C0FD8EE9E6DFD6C07130D9DD2F1EC0336A8B6516220CC4836775074AE6CA44CCCB8C899E17E20CCCB6717E61C33E955CE4AB6402B0137523436FEDA1672332334DF54AF677E3DE42E044EDC1132550A5746C069A678710EDA2739CF5FB29A893CE6EC8ECC26DBD6FE92502995E7E9A00C0A45EB282824D31B109E0A04A5D08A6440FAF67678DA73F176B86A06EEC4680C70FDFA3FDEA2144D246C3F9336ADADA58DC1DF1140374509127FF8F6D1FF7A98FCEE94B66E9B63640445A86470449253896A9AF430E397F8DF63FF94153A3A63301CBF228C6BEE1AB32606B4C295BBDF1013754C1745BD2CF773A22BA141DE94EFE7550798B4D8276426947169836ADCEFE126A63E9A724FE3FD8CB0BD45B4240CAF3EE01A7038E0F95F0434B9035750A60E651D5F9DCA6A39A6DBFB45BE87E1C641218BEBAB0920F06FF3E3152C9CEF20947477105A64EDD4DEAFC8C30D56F5A1A77B8E9615207762C87AC84AB808CB041262463507915EA549072F77FE7D71C31134C3B1842B14FA3EE5F8A7D5BD79C25835E3A24C3BB4D3F835C8AB6BDF45E2A1F3C83E6BD6C2AAB67583F20BEC7FF9F51FFE1E85C387A190A6118132AEF7F89792EC5A0F1F3860F1D3164A9ADCF0C7DC8ACE73DF400B61F10407BEC9C295CD5F176DD92C6723B12AFA1EF6102EC47F74A23CA4260E5CBDACC48E601223816926D581DF6D1066EA810C2B343912B49B678F9CE6A2AA1F11EDAE0C5419D54439C89200B3BAC136F7A78D6AD9CBA0832B6B83DE23ED5A6E6EE8E417D3670D662C3F602396E6D166768070D4E36E97601AF1AFFDB778DC798826564708A6C50FBB65F81B3B52BE1C982EA34D33F040407AF379EB9DB0E531A0A31C7FA3F54C29F4FC9A9B30334D9FFC41CD17099831D89DD95810BE0526B65425FC59A00C287DA1075698B850B0F68EA2A8711E2DA771EC87228DCFE76418B861B0396E2F84A14D370B74B329E008DB97BF47FED1C10774A00EA35B178612C93C7D0E490C46FFE944CA50537A91D95D481A1DA523F80DBD2AEC5BB3C84E9C0A7C872FF188DB620A96B8918532B268985994B36E25E4CEBA6A65FD9A7A206FF30DC5B829BFEDF08FF9252ACB9E77804E4D9A2012132EFEC302831A08402225FCE23455A3353AD2F08C48F27962989DBD73F5F8852234E7948B99E366F48BFD0B9921672975FD4EE34D94DC1AD069A030FE712A88FD15BF4B8F2AB46B32D37A148460DE4D07DE509620EC3073E43570B24B787C4A241B7242403CDC6D71F838FA36B7EFB3967397ECB49BF3A69160B2E34AC8CA4B932377C8B1BAC431E0B1223EAEF8DDD0D7543D5FA791791AB96C80D76C8A91DF9CBBAFAABB98A81DC1FD77D3D186341AD9232117443FC54ED15C3087D21C503086FA56EE75522124FBFA51AB3B9479BB6D524F6D0DC405713B2CC76E1B02F824DCCE11CC9A8AC192095C7B2ABB98416F065681DB993D55EDFC33755900454800BB0F49D7D6BC4A12D9290B29A50DF31941A479EAFD53D171BC02280A3C05CF6B44133CE71377DDEA7D9AD342A948ADD8BF8859B5242B4790A7F3B5FC8E4F634E78573E9844424EA26981293A273BA1E1F16D861090DF234473D63ADF44569A145D440FD728D2F89C36FC90C070E041C1FBCE6E13B9994E3362245D8CDF1BB190A5703D140E3F06196D9A967A051A2F18C94E44B314E04EF57BAD90EC420FEB8142631C3709FE50F3BEEB3B451C18A7264E332FBADF19F3A2C1915F05DFE69E805B8ED90F2A5C373D6CEA632A505D2CE11F0D898E603C35AC16113AF9B7CB019AEC8A6675B3CF7A179B642462545152C0516534CC49816E6B49E44249355A24608056E5366268112B4D63A931E2FBA34A6C191E7E7D10BE014FA377156802F1F3C8C948F9BF3DF9A982A13C2611E7CE991296BD0C8DDCF46C7A320682833F97D375F62CB8FAB9C16F1F5770D6B6C7076317E68313218395E20FD83FE0B0F29A06CF7AF96AFCACEB97A0265F79170832B8CA031E83B03674DDC210E8320A548FB2B5F152D00D131567DE6CA48641D90F4D7615CD6B18A25607B2787C024EF1E392C1EC563A4C611425B44FA56F88DC534F1ABD8633BF7DE8A63CFAFA8DA838DA2463A58CDE946A4EE2B63941DFED5669DA6AA87A2E2F5EDCA15D895A2014BD5FA7B7109A052BE359AF469DA8E20F0242614F3FA149F67310886B028B0FE768655A43E42D993C705E1DDE9E8A28BCA78226BD56FFE7F11FFF954B347C51D4B4764595FC273AF067DD348C2DF94126E7898E9CC850AA4DAA7336F6895F5362FCFDE887C696E846BD4403358117F77181F5567B6358D17410375AE4AB177734BF995B57F53823F1DA21683D29EE351E109951728807D18FFB9BF100BF104B2F750CF1C1E1EC0BF8A05ADC30987611B2BFAA18BE995A36D1014F59B32AA525C4D9BAAA8ACAAFA1F45F6E92ACD0266744E9514C6444F5 +sk = 0C6244CA381E425421508B85B47F9BBDBB10E1F0172C28409EA566204C3151EC60476C33C214A3D31303667ECED897E83B828DFC1D008475AD2E6687428C9CF73E175AF6986150FD83C2704F78BA2B878C6B0B811781892F61CF4335A41C1DE93CEB13DFEB1D0FC27AA75773DC273F67FCD5717FD5BC506301572E398282C1B374818208613435662785752604107708815278414141324253274473605157501763102830538683838634725747743554470538442834508215177743010623747324780083843651255070328433877586235814870717800270066126201318136801330731100772506332377734002386873316216577417744754878368477012586686167350002634357824478273687380575327714728835032157661460847744863150763137675812884222813037317600081346035614334541563446661731562024505048146123200312278670615222462246261081220738838576542712026243474450143344815344113620577064350013502063470582043822205000410638411314338706020502833025120774050688611882003233758312581635750482238378427657178577558666781656706582624236368274878203623028612718478206258666322150401584735281271136521578572085134367775802865477134013681545874074482573066112621356174106353004767064521528804065758020115178553786285645678280676047112158451654814404467245207053428606644411230410675674801868163560053657561258425524167333402375477520140416335583154263154255173031258786208531656467166227632510626727554206271767514814815834010453571706847616507617534726270056026784474731174537452516002462255860330612211365605048864605085848048735686768074115385052858103265160034001070411734854260358060762154770602211382148087825033745312665081121277675313185326608664567732116178187561044104455058141550246750738264018418706423317080883722423552865773855653557473755244886065804063562353688206761470850150608283016643225758054833328660822867374502556144056762305348460534332125278040022386624217538830278740118144480712843763515627774082108352264341542071385027142584115772441661323437516700874375634874770470503540732624133424201101237244233224818250437240737510654564764621165002232043627806820847345212746811085707026204365434438874542250357081433711233103161714075065787100557533742475212072471502765805475287000387145442620531510058430224745131702023861533368733328531102066500633832338684461520108633626476453751084780381105737705336626857513657722683557612568477704073208583283716602212070382882302240880712123475201861130432864512755704271604326832160624856580506682547527385543624400854222626270072513437614205348852225773872152743854268138026466710340716314655452607862731062284384762347431152746208823334721807653064062560722653636555673534428562858120374047804840185170423743372644358448075420832186866220030177220100853215232584735044887302567087313528346778188617022500368504501178816731501377562085750757164232814408654116011577717565734214882511416351717284700703216762345740385860122000072863263851358826050172160005507474082111545831673887862542617477160622666752517776611365472088411201204304000803538023046158604447876101121117262446844266683512051647005044263666188268734205313514445721166880546684322715420165645651631446115543556161701887718536727714171872414547433571056884375665768254365452728663281490C9894B47939FF7E959DCB3CEEAB9C2CD60F80476D61F5BC0F8705185BA79A1F61A089C556FF83A0E2CA9BEB3328FB03959BA140C96393594CF268727855B80F33A676190BDCA45E4B4B4932E123145F5C93CFF730C7116CB246236D9313721B184D0A71DA0FE249F3CF28BD8569AE10E172F742926C9D3DF0879E43E26C111CC1E4EB522B1B3F92847655A4DEA9EDB4C6DD75A89CB03664C89F03888D5911A70DCA5BEB1C128EC62C103F66938E457BA2AD5B3407CD74FB5D971B58409723DCF067F63340426E97E61A70848D712AB90AFF5A322A9A94D563536ACC788AB5B5FEC05DB8D199BA3684A6C8BE05A791F9813FFB6C1641818DEE3708B13382D9A4482AC1FAB84C223A07BB33C6BDB1662684107E4BB5128B23382A636411511A8FDB42F2D67B7904051A5989D2B4B56E191CFA9916FDD81D487C7288E02895FD2E9EF2EB42795F8F5D16D9C7D4A83155E3A48A480866EF2519E4481D3F8FAAB94F643A38B686C6F164B6F373DC899C15CE51307C39E92C3933B52AD2E01477E9D4534DA0FB3DD474670E7D66EAF20D73E1BA9E879D34B06EB7A9F8D8496C7D8AD64EB1977CD780B23460C26A94BAC1C7CFC713ED422A91954EBCE990877F5D3A1EF1BE461923E7BA15D8D00A29BEAD3B6BEF9B0FA0006DD7AF94EBCEE2AC2A3C6659EEC691CE2E0F1C2568FF72862B1BE87404EA3C73FAA8DE61EEB7DFF79CB0286E1DEDF4BF3F5BE04DC77ABE1A1DCCB757808601CBBFAE6C43984F05FB542845F185432AD1E6F9BB594B95823D343355D27504C4827218206A7B2CD79EB5A11E6D68A45AEF9346DFBE1207BBFBEBDC91F024920CBD659F889E3A4B62D25C11C25683E518ED8E1C7CE1E3DDE8F23DA3216757CE4731FA90B2390800D5C2832BAE653E6982773B4D49C47D56E61933B167992EE761FA1C1A64B09081A008ACA331614872A56D4B52095C0EFFD60E9205969105335F8AE24695046E248B7AC8F2D9260A8DA5A1260B7490FF4EEFB1DB519A9B5DAD95659E50EC9E966C786A7ABD35905602C1C5C20C57E787F0735BA8B986CE2185F66C6DF2847FE18D13A5FFD1FBEA2B6D950EFE52238188D091D232A1B5F1E7580E9DEEE774E1337A9C3DE52A3ABCD98223AF10F7251417728C1AAF4491AA0C5AC5886472957B3187309DF12FFFA974ED1140678E46D85853A5630846438B71C9AC86A7B6E695DD83427217AA6FFBD51AEAE2C90187967B6DD831ADDC81230719B9EBCA529B25066FDC3FE87C1B6EB68AD798CC1853A2940B910A42960F5B401C4E9CA4101C705C98370855F886DF53152DA19C859D9150461873AEBCAE4BF632165FBC96F1ADA83C3D9E0E105A54E08C35D8C0B17B4BE71C0AD2D31472A9133F60CED412895E20BC6A12450FB0FAD802E2E6F1636DB2725749B3ECC2B0F10CACE1015F98F4E6C8A123E15206221C33C6F627051405A4CAE2F9E201EFE821439A3DF0E6A19727658F3CB6A67A456B0027A25B53D6366BCBEE7446C5D1E9A97F104D90ECABF10E9A9A63CE6797160238FB793CAC5BB256D659AB26511BFFB873B53D5A50ED8F86FE9F2188C297E714EE3A2C1426A73A309D69F465B3F39D2150C7CF844DBF4ED185CACD5390F286A7DF21F3B44E4D3FFC4C0DD6DB88359E6B719E74CBB77AAF683C693EA0DF43294C79AF402BCDE073EFE22A9983B4C479FE7063C0987DFC800434D489E448C2D3D65E6390319A0BB059A83B4F4EAF154181412BE5DD5562A4DF1CA3F820791F42181C685DC90B26164EFF07ECD606E55DAFC1862FAF2545DF33F88E0FEB42D2FAF016A594E66EF7FB8E1334AA9EE385EC993CD8444A4124C3541AA4A284EA800AC46491B593AC3117058A0797DBB13D3BF8742881DE7956B38046FC5E4E468709332518A30820D1018E932E79F7B3DC0211E81B73782FF420BF8412B1437B7A19B5D5A9B3001EB1099C5A5D9BC4FAB9ACF17BE3333A02245B2F0A0A085D75D3522937AE444A75F6526C98FE8582E8CA09FAFFEF763EB8C64A8B3A5D0D0CF90714EB4199D4D84CC34B30395109D9D56EB1633B008E11DA2B6CFA64D999EB2D57D50783C21B5CF12AB8F92BE12DFD0C1C14490EF64D2661FA013D6E6EFA180A1E94AED631D1B92F10C2CA7D4D3BD5DE0C24A62B5055EE8B06E2BAF0CA2D23C5DED1E523D0796511EA1C1B58999F2467DB989E831A7629DE4DDBA842B4A26E18DB2E0CCB27E29DFD320793B2F8307FF187B9D639FD003EA7FFC8D63155650627C5CFAC9B146DAC8914407FB4A9F9CAD6605972A1CE9C56A9470A4101D4434DA1B9583B27D4747AD612C4AC87D39C904786552D84709CCD8AE3283F3DE9A70B37CB3BEA78E889555F3A8E1CC5256294BC5AC8720F73E076B744A745087C1FE2F3CE8D28E9EB8B96FFCF2D3A98071C747613C31938B4D3B90258BF5592BC049527ECAE66C3CDC3EE2C51D573E6A935A3405D1B7BB6E6D784FCC2D4E92B49655A4CFE69A767FE1C9E0DEB7C9297163C923E95FDE3B729E72E09CD34143F3D5A00FDD292BA96A3DD8E37989C300EE1940F40809527F1B77875DBE09C7175EA62BA1BCDBBBC885B7A896D434FB47760CF3D2314403881E664649BB3B0EF078669D8D3A85EA0E9A90571E898651382EB88C161985C5934772DB36ED621782E94C845A17E3754D4C9C92897F2DA0AE3D7A6175C97255E6E4E2429954ECCE612DCDB28DD8E71681A3F69B974D34AF7B9BC48C22F2A705C67433AC66E830DEB965B79FE867CD2320EE161FBFD8C7C2F934825A7C84A07AA36771EC1B743FED3CB47A3AA1069201243B43FF5B42A46980FE568016B268D35E9583EACFF548CF49090C5066EB39F310C69558B48B9C596D69695ABD5ABE02EC253842255E231DF0CDCDEB2237F4C67EC4D991C8050D7EEAF39649242A66D79FB26FDE24DCA6B319BE3CDCC9744BF6410E4EFE82CEA0BEC195E4A784B8BAA05F1E0CBE1504FB4B762C18D5D1E5B567447FAEB813B6EA10D520F5696C34A78FF79F27A84AC3C16972996C125FA0EDD2C222C2234DE96549EA1FB33C3959F8ADECD6BCCC1920F289AB02CC23C9C07CE8CEFBBE806E42C13F12AEF4A0025E69495C3F7AFD7A640CB1A335B4819109E0A27F7A96D2E2E174BE5405ED51CBFA2FF75673CCC8DF30B8E7548EA469136C4E3A98476B0B50855DFF7384A3AAD9012C370A55F3B147F55E47DE86B8C9762FD7A82EE837871C8657060C45616E05D864054E5C9829DE2E326B90A6F9B7387B9F0DED439C8F649F1866290F66B5C0C782E439913363021E3AF13BB67C5FE4966306D1DA981E2609EA529286DCBE2CE1D9E93303EE77A985A7D57720C5C26F47A5E6BB824EA212067372943C3DB73335B6157A5948BF27C0A5FC124CE1C5EA9DE97F982D38DC17F536ED23EDD89EA2FA0FDB09F5A68EDCFD97693EA76276C6C253D9849ADEA27B1250D28FF92D1978B428A43C2F1889097BFE57A1BBA82686FDC459D84080DA9D1A630490E6DB0CB2177EF75C97B91771F73B4B8DAF46F8D85F0 +smlen = 4530 +sm = EC3971C4125620285B0382B853B247D1B99441530792D58BA61C52539E4219BFC557AE67AA7FE0CDCD0C976B4930D658DCBBE32FE7A658123B9D074FFEB8EF856B37C7276265EF182894E8E31CCC6BF8720CA38FB9EB0C891C921919B3A860C51790F9C42CCBB9B428D6D671CE92505DDA1025AF735E56B24A189E89F60F2ACAB58DE31438B3FB4225929EFAE80CA9AB24D5DDE160AA6C28E08C26B46A08340B82F37C262DC9867CEE4CDBC7324FE9CD815519431A126120029957DD4C6C02BC55FB070729689D3E96439F58F20415C1624D5D6990BB8D4428E0332F29F8C9EA2FCF6B08B7136D6FA6945CC99F962EE171B323A78FB5996BED56434C0B15D5EF53D2CA521E768CA59433FC1103FB50C81F40F4D4346D4C0ED8FE73A2D851D795042458A4D3839167F2A35CF3B397061DBB1AD0CDECDCB398A5DA1DCBEE12CC114DC00DFB1CC748C985C5AB81F08B001676C8ACD9F6C9A0DA0ED42CBA3C7F51B68F268CBA2CFB599EB0C64473D3263DFD796A20F12A507975EE324DE54B682283D1F1D902E7949A5D2186E7FACEDC3983F4AE4D0230D3DBF3EE4F74A9909D8B1D9CDB4DB7A69ADE5D51B112B6458D13CBCB10A193AA64E398465596A7DC3D6F4582D503ABC2595056B89DD073967AA010CF7704E141CC6F6B8C110A02B62F88E403D54E691B603CD645B68B662E2BECB070D449EFABC91E89AE1D8441B73EE00363F453D170ED9D064749FD6AD45CF7BAC9E31E5F1BD3D577542BD57A882D244EA1EFC089AC61359BB9B1D5AE3D5674DF12F2A3678EE5AECA2DE52884FC353A6BC2A80AD20A684804CC0A6E7F92AC8AA05A6B2A4FC690450784D6F2EA727A21DA9E37A39626A527B9CE52FE8415DD0AEB1F2F2490DF09DA9595B4257003DE778F36FD1EE07C00B069AF9096FD963AD92A67279858CD1C44AB5A315C220F8BC5273D4E86BC8F3083A3C3581400FA48761A19BDAF11B82853CB262DAEB15F25031D7827B00E8B4B7AE27B19687AB08D710D1BE6D7CAE540B1598EFD641CD9575A8F565063763E77977F6E8F5189A44B15C2B1C1E1F7D39942A883881C1D4A2BDC7EBA666F1B0A2ADCBE5BEAFD6A2649F369C6671B688AC7B15389639D25549578176A346E9884508DB3836E955610766B780AFCDCDAA1E54F8D6DA9E5958D1B8F7FCA6056FE92CD9E321EF6C705D623E8F7F1402D648AC4FBA7D50AF3265E3643D404BC91B189BAE833A68A5196EBBC785144AC945F2210E70BF740AB90F92FADC273FC668792BC0FB4BC99BAAC2463B0DE0533C92E29741AA82A5851EF79D89F22B9F77E78F49E5D9D51D683A8B8E861524D2ED4EF4CE16AB6F108434F34068A07099F90824BA922836BF65CD93D565C078356AE0ACB201B4182CECC18BEBB4A87CC0E3E11CC30E8A56BA37E17649259F320457B5F9F1C13B7F0B420E952CDD03AE1FE8820E836E03F52FA94ED140BFCBB0D5B5DAE2A082C0C912494B24303F37610126F4D812F9FDEB03B154B3B6BBD3B8118B32D8FA466F2153A7FD200680AB24B7D43FA25CAFAF19A3B0C1D870676979FCB9A42324937ECAE0FE2BF2E6B9E3B2847E4EA4D4806AABAAB2B0E515F5A32C5D9BB056767779CF4D2DD76B9C8EF8C0995EDF5FEB5ABF3F0C9299B11AFB06B1A90950D2EE11FAAAAB1F3E3AB69E5B4D12D06B4BEB60F709C7C2F9CC3FFA5A33BBEC0498BB966BE185C464D1779638950D4B12EDBC08081A2893EEA3CC4F3EBCAF785FCEFD96C66E649FBADF41A57DFA70C1803CAD1847A01357F02C471796B059F4DED8A40DADBB044115CD20AA05F46EBA2137DE0093F4AF8DB38C54F84F842DF82FAB69DDD5E516C6EEE87C0BEE91D4ADACE9E96341A8F845C1F08C1D9FC6DE5A7CCF1FB360F1F2BF89B8720AD32C135B3FE6E5E5A952C1D1E3AD823016A4214ABE87D7637D05C516F57612058107F0455683D0ECF3640F239A8B9E00606165FC37F8A192086E05568284555F53D717B9A49D91024C45FDBE4F17B351D82F7C9518EA762174212099231A4F4E744A170E976DD6232CD8BDA3C0F371CB424E3604B030F0601044899C8206D4A70509BEB212A707A7F90EFC474E83443FC3448E6AFBCCD3A0964C76222C7EB76ED786662438B1421EB880A8D94CF6EF964A0DE9C0BB497C2A3B3CDFF66AACD8C746F1F23D559D3280776CD11E5CCA90FF141A6D6FA0A0DAF522F56A504BCFB902263D2F6871C0A8C9F4B689D19D01B38466F7E473F7A312A9C7EBEC0A7F69346D4A186C27869C774E7F35DDBF89F32288564E7AECDA048A0FE964F8188B780EDAE18D18BF22EAAFA43E41AA7DDE3CEC2230639025778572A07F6E336A0EAAB4DAE5D1D743A9FFAC4ED401111EE03A4A051631184F0E3F6E2977AB7AD7580976DEE4B52AEDE0577BEB187CECA8B88F48637CF2A1AD51873BE4ABB150DE09AE32ABAD0D98B3071D9B9D7BCEC3EC0BF51DA6CE26DFEB457A91F5B7743E8F3CE367B07BCC51CCB5AA9497C1850F45CE98D3B75079B3A7D1BA5E60BF61E597C72E02B5708ED4E591D1A0B94697F3D4CBACB0777A02768D3DA25241FC3A5D63A2AE68306F2A080D608A0707061C76A23077037672FA75BEC039444B5282689EBD2FCAF1EBA69829C9DFDAE3C979886FF4A7C9DBCA56ACFB9D27779F148AB6211FE3A0ABE73E83EE6E788B733F76809D12DED578D3C0C427A789CE7E8FE92CEFF959C06D592A84BA55418340FE9A699BD69C855D6EBBF8C795078B6DCF49088353711A5D03B52557EC82B4F6EE087E2807CEA37CCA54D5313A5625A840D6A1A173AD3152E2F6E2665456DD41E030A72FA40F1595C00E44378E585EF074581CB69F94F2EDB5AAA3DC92AD2FBF725AB5D9DDE84972B6BC0C1664E83D4BC2992BCAED2B713931E20047A960754E4E60A286A2579985A20766E4C0CB3553CC8A1D1520B222615078AF4A2A04E1D2B8FD96E1F7906C6D4DA0DA9309AFB95065FF0F67AA70394C36E595898A393E9BF5140B3A9E2CC7CB8F89E00F1F93C74A3A413BDE2DE03E0681B65BFF08A9B5D2744FD1B5026EBC51F522E177C6EB53285122CD41B571DFAF8212F9C0EEA7AC130158AA1A90064482D414DEE7F6EFCC23B4B27F7A00EA891A25C0F007F92B6589BE66B8C5E3DE833A11AEA992A8C61F6D4B0E99FBBD2AC71AA9EDC6314222F6C13EACEF5FA800AE449021716F5E47FD42CB90A5D5A06FAF87B3C34F589C408872902C4F4211F0B2237BB8EC4FAE27F46BB8BF88F64C8E2468A65F343D3CFE3EC4E48F1C08686FD30182AA6756BC952151512908402B32E254B95D0F79F33EBCD4E8B7031EA27AD014863CD98A1226CEF0EF5BE4784559CBB42977A4271F7C16F6613E65A188BA11046FCF42E9F31266302E3AA47333F323E2B25C510E55E3C80CB948F3C0A1D21C970DB7B50EEC7AC39B55CEA6E0DD46024114C9B564364B4014D54E9455C3ADB4EBD0E3E886FED1AC7D57D87AC538004B803A80CB66BD87DA9CAF788DCA2C9B29403E64AC12893E060C47976C928C921E0A0410CB6BBD286D3C583C36AB6BECEA9EF9F75BEA14A08ED34DD8C58F98D42178450BA70856957263EEAFC0B1143D0C6E79CD865CA7657A97E4F1C8DF89146DE22B9ADFE4B82E8E661EDBB7D62EA30B5171D627D434247A42A40D400B924311E35B18608DECC0A93CAB44348741AA0A885F2982D1E13D1BBC839E932FAA45D34641CE8F3CD092ACEA06F615DC4CCD7885BBB243B5EAA412AC1664150F637B631FA40BE4AF483CF5CFA232A6AACDAAC0EADDCE31655E890AE3D1C81533CBC634048D7A3D9E37AFF0DCE38DABFEF0A4F30A39A3E3CD3AB09EBAC90355B76E45E5E62110AFA425312DE3571EC87513342D0D0C22A2519B18BC3145BC77964C4E9341822AD05A8D1F4C2ABEE006E702462D1D20A2854180558F96B5946E8F4DB3FB82616213CB5030A6710D1F3D44FFA449C31F32B3D26E38371ACF8998DE5543FA3C8E3F45197C5792F1431A9D1CC52580126B4EBE24EC78094ED8768951EABA1459E4DC8E367D87AE65A64D21D6AE82F087D2FA0F1EB85CB83B95F51092A7384809355B8E55C86DBFA2955F518CC41CF6C061CC43E5B39ACBEF52BC3A0C50359E19EE18F764C426A63962DBB5A902EA875C4F7D0062A32E23C9880290D2B601ECF385704C10FC2F468258F0EDEFF641F091D35730AEB8E1874B97CBBACE574122787BDAD119629D32B42CAB84164E9E8B270DEAAF570A4827F25E9E0F878250CCF8794DB7BFE0B9698406DE032CAFCD8C6D17F068E10FC508E8A7F188325C6093EDAD18C2731D3E3DB2147D38439F3952236791E8AF87D43DF368AD0A650EE5312D3B746A923376C3A661C5AD9579986CD9B80DB9184FC3B172EF25546A35D73640FFFF4CE441FF269FA3ABA855D184631CAFD4BA2B1C27AB60FBEB90EE125515FCA50590AD02734BFE413F943D3049A33153D10AACE8710BFE7D3FCE128C632563DB5763BCCFB4F562D43EACC1B4D504FD52605FBBADC133C721961FF605A1D3DDAF3B5F44F4FDA936D6FD8EEE25F7A713E1BF18EBA0F29355CF5B3655B740D7AE4A25632342E0D7C25532073D66CCA1F635FDA0A1F4D51666DD6EBF0222C3163698FA2BBC21D373B4283D1E0FD042A2F849BB8BED3020F5085D1E10000000000000000000000000000010A131B2329743E5D96B9B4C1469E7AD2B3703F711FAF60CA335358FF3EFC8FCFF02CD020A443243B4169F9123351B6C36762B85BE5E5EDDF8D4B43D82CAA615788406A31CDF4F7087D42DB21AE48A069AA23A8F6D20A1C0762F973E526F011DEC737E986CC324724BC5336D0362525757410E21046A12AC54F2237E68DA036A5C1389E46A53ED8C21774906948D4C9E14F40519C54DBD02B7A4ACAABD24FFD7F6CA4D6D582EF48940296D2893415E811FE7EF0801B35F1C594E6FEA2C293869BBD45618B6F04FC26B55D55A0AE99445AEA12F851B7E58A49CC6A0044F28E3EB838CFA6BAC5DF53B0DB78BE2CA2BEA1BF2DEFFEBD673A783C91A6C9EE710B12042EC2863A9B52EADA5B0D32101BBA8338F7C75CDAE7B7FD6797B25F96ABD53A24A7647A1C91610306FFC72A8DA4D46B1778146A98BD59CEA3173D41D5A53F9A7F9E282B5FDA1AFB062D8AFB63CB19B0E76DF782FEB9F7FD50902133529CFDD7C51AF297895EF6E1871AFD4C3DE93DEFA8FCF1FE67BD27B7EEB0CF37A6A8E09AF1203922BD9B62672D4756519CD09DD9271ECD0285F92030A9FC81C09BF2FAE86F5F50596C628E0BE673571CBC2FD76C563E113004529B234FB50E9E3D6D1F814CB8E5B5CC3EA365D0BC7602B146CC0361397D9BEE9246FBA3A724C462E177D27836093EC009741ABFA28379AEBCF5EF09BBCE00CE449FEC3A3302FB9AD0F010CA338363539DA545F159FBCD3D6A0482454023587A324F5132FB6F4CA602FAB2CF6CD59104427264CC9EDE8D10CD9DD7FA6133E65693DBF744443AE920994226E21D98634BC7F0710DBC37C18203EFA5ADB467B523322E21E4E686B6B85B00CB501ED84153BAECD4D6CAC9D1183E38B510F7B1DBBE5995BCB717529B83FBBE969DFD8DE21183762FCDED692B16502834FE8E7A7C46F84ACDCD2C9975098CF0CDE8AC0EFAFA449DC26840180DCD9353A2F1B06962677C808B07345E8ABE95B8D24F21D751A4EDCFA0E02FF077DE64E6B992E8C8822682DCC7F03CA7582FE7C74E0A9822A02D888FDDE1FC9E73C2EDEDDF32001E918771E5F511EF8F88AC19B76FAC0C812F56938F814D712D99269D7802E47634E541B54E00F9EAF78A421506A88B4BF7332DFC7D79E8C41835031FB449507D19D5A8A512A5C527C95B6F21EE3E41FA43591DD9BD2E4293701BDAFB624E0EA290DA4B7A173003867C4CC3FD814E117B4EEE283C58F5FB33D653E410F68C8962155B8C4FBC13BB750A0343737D1FAB36EBC618A6A7C8E6F93855CB24937B01C438FA713D334DF335D0745582F680627D8B94CBC25F0D12E3B1C27A3ED72E2558B800C19DC6B719B961E0FEE43BFC34E999027CA1969ABA4C45FDAB9AF01B955E948DE951F5A1088BEDA43AC930FE99D8CBB3473475C444F43E928E1A44966265B38FADF9B1183700A95A81F85EA43E5C61DD9B2D67701C95583E8E3F15083717E1722D764B6E624505347C30E5E70163ED9A046C504FF534956E911294D2B9097BBEEF8740377EF0D6C4CC8086422902BF63556CE6DA8E33E68FCFB42707C00693A995D17680B76293194DB217EB5A928303DCF1814E4A881B057BAF2553AC4FAAC8E4BF23FD4074154CD4AE189FF7E204EEDB8EDD594CDC21B5B7D73A712B511D068F4D217C0F91F9D84C524D973D67AA741EB13FE922AFABF79CD2396181143783030FD2D0CFEFC877934D8037A4C32AE8E15B50A6FA4269 + +count = 37 +seed = 1D9C060EA0408A068BD982D9694D39D02BA5A473378F6F9F09349F686566F331E767263FAFF5DC0E823BB6F648843876 +mlen = 1254 +msg = 3382E87BA70EA986A044B0CBA2EAFC3316C1AC95A5F16F6368C210DBEADFAE6CF2382DDF5078AD594CDE3BD1A837C517B1A20A2099D938DF6AA02B6C0E62FE6147C904BCF3EDE51DDDA60DE7887DFEB2866DB402D23E5934A74C9CE4852D4B2F53CC9BCDDA312964A548F6F7C8320AF1D1BDBA7FD32EC6C86BC3FCB4205ED3DB092FDCAD9AC4D2B8575883E13F69D8C16CB18D1B9284B31823ECE917C905C5C8B9D180C1BD87975871014F773FB57D402B8FE16EE312692665824CF0BCE4509326A31957319364CD421E9B21BBC1DFF663ED850858A2450C2FFE64B65E009A3999CE4504BA5313BA0EE4A8843349C30FA6E59FD3ACECA130A37C04F9B64722608768973996112684B64D0C87BF95E5DD60661935831A6A1A9575EBCB2F64A15296BE788C775D80523D6BB4267D91B0C71BA5F90DDF1933DE898E79FC7E39D0A3D146F185214468DA50AEB47402AB542E52CEB768A70CB1F749E4164CF20E549B674CE965FFBB98D874D34B5B7851E575E6C1E4DE9C170A10DAB84940AF055A951260B0119F5ACBA320B55CDCE4F16346905A2073CD9FEFBA95734E4F4DFDB7A33F292D45698831F1D3E9FBF56D9692C14A8F9887265CBB4441AB331D977E3A68A1BC9F406AE0FB1C6E91205670641B9868E2A987BACEEE2364FDB089A63B53976D600BD7A8AE88A02872E46927269D281CEFA385C98CCDFA6609394943FAC32237368C6203AAFABDE072054AB5A14A91391D5A943F4ED4A4407F275CCFD15FD28F1AE0EB6EDCC6612E3436572919E4DFB57C049BD77B344D8E04152863EFD4FAE8FE3A7230AEAAAF82870820085F4B3EB5215111B6B8952CF2FF468B3D10F3AF849F16E190E9560F40B05E6E2204591B58A850E2710F7043AEE2A44A6D4A108CEEDEB2D216E51102DD08751925DE6A7F67BCA1980F0789B34E2F86729621F2285C5D3A036CD87C76102E9D607C37CCDAC8062CEB961053F3195B5ABD88BC64FC65F8BE34166841683F1EED291938F75DFDB3AF4FD2AA98CE95382ACFB5D5DFE6EF243C8A0B19B80584FC0CD533E38BD485D1C52E0EB5BFF90C0A947D9B9095AC1C0CE9754EABFC860990206B981235C7B612DB61C9FDEFC0F14DBF68A8A0EA4986CDC4AABAD6C218559E11CCEECD804EB98446FB33EAE47C0388BD8972DDAC02CE807B707D6D188CB31A1D76D44323E93DAC4F8ECF77E7896C052EF16009CE4D1147DF84FD5785D95D77310783F9AEFF1DDA693F4BED26457ED82A1CEA19D9C4919257E3050B25A7D1CE7561740DDAC3FD93A607C79875E050E40498BFBCCA95BDB3D0FE639DC7CEA80E3DAB3AD73A4265F012451C1BCC2FDA1E1AEBB7FB18407F31E7496E2A18D2C686B47120688240A2FB134A3C314D4CB422811E850524684EC485E061F7365494A6403AF170DA461A3BC32FFAF9143D5E9B17B2285C56977AECAF880CDD34F26120DAC4C950198233A50654EFACA6EA97333D2BBC024A5E668821D20333DF0B712510100AECAB6B484CCB7814178F851A3E6BA0B76F16C4685D5AC8BA48558D382ABECBDCF0B919C1ACAE46EBEB5011DD0B3C22B539810720CFBE4CBADB111E100C09C811E724A67C66A1B89EED1E7218861F55A4DC55E236C6E3521DCB374437A14E8000DBEBF0F7F9BF409AF952888675C11326D9E3E8A8828BF50CAECFF96075CF29446CADA373529D310660CBD60C042C143E1736FE7AFAF6FBE42791A8DB01EC0475145257FE2DF766D4EA972B14AE5110B8F8F42D659383E9BD76 +pk = AB98C860699692BC2A6A80E24D455A4039D24B98F8EF218B8BA6B7225861166810F0916D0DEF2C8B5FCB64A6F9ECBE47C24DA6FA126E436F0315F4C9B5DE8085157C5A96B018AD0B67B58BD832A110231275A341B08DDFC2D7A74755C524DB778A07A5920CC312DEF5D05DCE85D6F5D97129B25AED1007970BCD02AD022809FF1A976EA0C3432F4E185E873796F1C34B66A5F53A21113C89E9EC1E0E965B436B20D0F5EF06248F8B6B1C7F8553DB264DA2FA1417B0A3BBBB7464BA58A59F52050F63FCACBA49584699B4D36A038342AE7280F4205B5E79BED55AC3C794F723E141D45E46EAE1BB76AC3F84FDEA1E3CDD6DAD288F5C9789DDCD47A1D843A6883F706090ACED29CBA1214B12AF2377358236A2257CF350F5E621103F32405A9565683E784EC21D8B3215A657662FD1243791A401BE1CFA2ECEC24AA7AFF89FCAEC31F177A46B23D4EE06ACBDA3C13E6E06FD6B3C9004B4778C872BF1E3978AE6C80C8E53F3F1E90C6F0AAD3C3D4D04181C617E2FF682875A4D106F482975C68424DE8C1B020D71364B7338D8ADDE6CDCB319A25CF47E2EEA6181EBE325D96BC7ACE8E7998F265649CEC5BD32BA34AA07ED7ABFCCE96B76FC082AD459BADD351165BA2FDA5854E06E3DBFC8F11B9678EBD2F37067DF6034150ED6C9B7C1319EB41A26262F81A0D08C0E8093465EF2FD93A755830E5ADE6BC04231C4B761C1786E094A9728831D6E7821FAE1540377E67ADEA6C32A8198F656C6248196DE72F6EFFFF920D559B3EE9CC983E4495B958ECDA1BD040519EAF186389BC642255F4FD8FFEC5E3DFB61E5A87F8BBAE8C0C64BE3970484CA740E115D9B73B3F577EF53A194A9CA8090ED10AA48AF3151D688E34D6A431CDA84C77BF231FB1BB8F1953A8B7E833815164E63669D0174FDC96D6D24F703B865F42DC70B4302D8A4BF488481D7136679F55D1CA4B2508B1F0A15F818CEBD87CD081AEFB03E08D268E20A5E461CF8FDEBEB21BF10E9D20494AFA6597A1DFFBC0FE6DF101AC75AEF8DD9D0BFBFE6AAF7045FB61947759A27A5A7755D32755293CDA9CDA7881513156DDD1A5B05A61307BC41A7AD86523A88B3644C7CFCB34201FEDE9CADEF72DAE372EE9FE2E44EAF76AAC5D83F1219E7D3A6E9EFB5E73BBE2CFD6B7F048FB6D68AC35A808B9C6F1A22030CBE4915D0879B2AA7D57CAD8A5431A8EF1446832E1166350602C59F9FA273196BFDA1DF3F98C9A4807D88F7EFCA248CC024D3824C606AB1B794614C83C65D947DDC0108E030BE020115122F650601918B1B1CF81D67244B78D874A72638235422966EC108072DE37963BFF688970EE70DFAFB1286A583FBEEC6649523D20601877F088C5A7E76432C6E8030C7B27573E5E879C9B7DE67DB01C0BC6754966ACB7FB39F0CB84157293AB0BE85D505DE744682573700A04C1BC4E157502A8596A0BD30F0FD526AA620330B8330D5501C283B60822A0FE89993926E30936525D2CEB50CC2EF885DE4461F8322A1BC89A7FE2960B424B52B13724DD58B9FF62F54D743F37D21E3F4B99B267FF332530571164082415560DDC02E2AFF368881D8835A1AD6B89DBF80FAB8A06C56018C517596C8377FFB42C26B4F0BF03E3D7A5A2B81F1842218AF7F56DFE1506E0D52A8764AE0F1B12C12800A632205343A23D90E11A8A15D6C1A6815D78C01AAA4517F41200BBF9886A0EFB98A91E8B2D833E6CD2B73CBE51E0B346ECE8AA79FA0A0CE9D4836255EBD1B82C7B69A5E1E73FCA6B12F8114668A24993DA5B1F493F53FA74DD6E69A73C800414A731F2B7A292A28093F9155A4BD5CCB81BDD4DB2FADDB870A7BB91248B5440B55C3D0EB708600FB784E82AB765411220E9AED003AE3A63E5B8650E0323030BBB71FF358CA1E4AA2E893F4A23E1EBABD74B459B4F23FCA9E25E284D84BAD5854F2703403E8904893235AAC11A7C090134EE8F61BE59BD579638D14663A2C387D87F127B87A22AFB813FB158758B7BE51F8A7D41E53EF0C2CAE3DE7C795873B374F6DE11133E10595CA08602C4A4A3E588167DA48DDF44BC43B3B492EBC7DD3C1B30D809CFD26B3A8A91D3DC35A998557390E87BE9B3636EB9C133AE1B221B0DC4F628CF32E5D3E28A801709D5E5463110EAF20E3F7274B6307EC62CC7FA5F3A6C80BF4622232A4A5BDED50D8942A52C07EA33A31D0C72CAC151673EE56FF2DA4AF74A8299A2EB4AE5394E17A4096E1CD9AC01471C4666B252A4D68111252238BAEA7AB76A0EB9D0232962D7AAC18DBA996ABECCE6436C96AB3052EB58B41FA241B0526211C0A3DA6EBDC6254BEE608877BE9A523F54B86B4BC9B13B436DEFD49CA7A6706354447BEBB52FA51C314003D3EE1EEFA31AD5AA5DF4E53DB4DBD305D70013F8B34EA842558835778DDC098427A7CC42FC4BA8AC9DD1EFD187F9226F9ED19FF14021C16FF17E595F5E2A873CE471BEBCABF816E028121D90CB97302E39CC8EC66DCB6D08951114FDEDEF68F20B28A08383EB82A535C832E2F16FC818FE2AE17A80F4D360DC8F54626BBD9C783D8FA3BC7B8EFAB0132DABB8B0BEDCFB717C03838D208605935A97DAD216A2E6179BFCD40AFFED78AB302F6254938D9D86613B9814573B81E21C8C9A4506354207C8C6135DD8C8FFDAE30BE33BAB1B2CEA51E4F0072111AB13A690E47A3A90DA719F13999043BAF39B0FB17F78C4C80CAA5C5F8D41CBC7DE5274F31D7C73309C421F616F8BCD41A5FCAB90F6FA33B90BCB74EB424B0EA55 +sk = AB98C860699692BC2A6A80E24D455A4039D24B98F8EF218B8BA6B72258611668B45C758B315AACBD52B5FA4256AB1D72291E423FAB6BEAA987C8A9A3CB771DF8D2702AB521BD25071AB01C6D3B377C24331DCC08EA1F22B60F315C74C3DF8C184CAC6167FA432A8EB5CF85AE3E266D06D4AE3EE5812DDC7199F9A6B96919E65121804587331580222853601003885541270242423447688135513207365887633426877360815452368124073673445036721670044145376413175208203884472653836722130633455803370474244375051002282072480177367102864252240221506152600737658712074786557681252338360208472871838745735136540546435306867616578584558365167100558166781086463822622445810832577138608307462716642281167715014832851575471644658550828576338176457412075668642013384856667532650273647456512446045508582658728507686505734886332537382053061215023841451474737605550531880823527826078856100262555600782185186764685128100787826103436212240740635250470581234632302712042122804577635781725831863776737280048108883632466800664471535187602481217026872864324837888121053018358113223130755186038641501081425624304581805828363360052175345617275480268376677015405481866608823580181261178074817013328478757527104775368270827072465386622084663016372608475153855402118584526221536476133347845354778705764374308737618173140010736166771320008113405505602758027340637553833673501215824126011605445872431842082601554565460778874610875338743000052533133817056376573572552260438053281113712831106178320872443485561772762726870463586253516313037044371110515153627117350432786558588115771817078126337227838802242461013040052660813660057826314887328210660416813557766463140355056711706134176383210070523063304062762203417770878601477357575283027032466367781708783321624201840752271367435675781340647088650604102213554707513605651572886636253211503043338260500340880887575176846783878207140110500068261456065272532407560820812427124251245781157888684344336653161674502456646228665735184672732305300047722885257036234168106050553410325607680645624262343342416713853704066765223741062751443345405414415033182345357171255034575762075137230706380536568277864632206818074514465486615184243147348465684131670723127360046005566542250705021133110668204488638732005754074213543306640043571762467324152226478247357378563854204442025214140480230478066453213803473714161328141752122014832817567642360012635412521344857183887606470576414018645346420468541706610153138840381166170605434503188715824548483005548113817067470777368560440608473228706777076386103068607536433052221481454570683300347036234063764634053383287570041804647215623081875672551782606802507066366364675015446165800073871006158141070226041845158147380182732103554032707814580644202204651346213638750002772843364670628825704126327827181030457806273452533707702202748607476851083537603031140344774375432560687367761008237663531757387644777133368880307852330873347521320802181715508805117024574473311284318617061756488377620888740177363860041456075852445814370015585415210803253875671157550146772854130651513572768416734307336403536210061220552752888625735050520132366320086667331527844574245250555761680775042500658760804488538577266824702146A952ADCC6232B041CCC77158399353F62421E319FFF620F9A526D8B8F816944E9127F154E821FFC184C07476EB2F165C92946A053651A49135007DA148802FF22C76E9C5CDACE0D1000908994218A7CBD620E2C3C12218F393F6749BEC16D92FFA804C28E42AF62A4EA6123A84BB8B6C3FB0E780027E55CAA39A9843C7D9E595B5D7ECFE96C6D412CB1B3C0E45A57B9146A801411BB74DA0B5A73C4B525D006DCB809CF22714D22CC12074D7AE84DE1E342979CB6357BEB92CE5EF8F277E293246DFE805E1E2093E7E53C9BA9132176EAFCE0FC4783A82BA389FA38C0D437584EE0B57ABEEC3099BFC5D081A8C00D04D44E566065D51C30FDF4C10A4BE251D1E2D32C468156FDD2BDE43AD92DD4F9EFADF694CAD742A5AFD070F471533C6A7B2B050CFD25032869638356E66EA007DF01997CA0F16F5AD5FBC65952C6B83FA69E01095D0B239DFDE99029BA44603DFB354A6AADDCC8FA63CC6BA06E9611D4D303A5E618FBBA7A2EC47FDF44BE023C782BC7FBFB908D0D964681CDE0DFEB463992364FFADDBCE9B5C80CDFE609DE90578B21A9ECCF3188F6C6CE57982FCADD4DA619AED3D1BC5311A0FCC2F4D879196CB68476AC46D6D17939B0AD52BBFB9FBA80F8447133C2E341AFFC1ADACED7D3DBA688F9EF196AFBAF42120A9846C587BD26F0100032E8507FDF0F1115C0DD2FE8ECF69B30FA5732565A7ECEA0794B9FE886BAE92D401D8BF8069BC454EACE301CC3847F6B48C4058C8E94E5DF9450AD9541534F1A4CA07608C3673DE7BDBC66F98D4A3E6004C95100A94DE8ABE61DF7904049EF143E987ECF04C52A3D61AA505CBE0A00E4B4F0F2ACA055240ECBB63162FB0DD3B395D6C1A3B45E19056641ADBBD6E8FB65927BCFFEFE39B5644CEA90B3EFF75767081E4C9007241B870DAFC09D01E943C6BA81EE6B7A1E031D1895A92EFFD399C4DA31848BC3E2652029776326CE932C8D605AE79A18A8203D2B03E88382FEE74CF39F83EEBA9DF9075A7887CC8508611DD0970A35E2E9C4BE62715997EF16F83C5C91D11F3EB125ECCBBE9E6558B9FD117293721D71BB15638C93D237AFE29F390A47D4FF44E0444B90E08FBBC0103C33F80692DEDB3CC1EBBA9911731275E0C39146E9467C27E8E68E8B1EE1933CAB20FDE999021322BF4D721E7B4BA5A9C79F18E9456A5EB6536061DB741DB69E7C0D7302EDB20ADD5467F12BB63E8AB263E0C90A46C0009D08E29D00CFEA105DC386D969A0C2BD72EBB70F202D868BA875E3461339A5C5B9059BB6D027F51FBB3A0A1203F0909F7991F459BDD31B830F0523708A3A12275EE5CE8704031C2D1C128A92F0182DA6A3E7A4269F071832848EE1395200431725B2983B29EED45E3B0E5090D6C191BDB063C9C1D1D61342E8BC5AFA0FE9744A6F3B3CC240968CA8D5178084A978188DF3DB42EC222A7B41F4FE481B9BB72C7FEA20FC786DE14336946DC84EFEFA7704E78BAEB4AD99C04A61F4AEF88010DE3C07CB553E8314F9A54556501390C011B90D3675544CF4A5E9B7BEB28FB93421851E4DC8D7F811E9C0A4A298580977B16D52B026D56FAA176D9D9141C2AACB3A997E067386010FCC7489B1941FD55D315775FFC0A30BB3EFB18C615769E88657A73DD79E94260E6E867EF6949E84FB6020C49DDD9C6A14075615099FD0E6D1C204BD62E5061D3967A880ED047601AB3B73D1D0DA0194628E0206345261FB6589EAD1D7CD676EFF1D122012AB49DF084A03279575383687ED4AF64E20BE2BDF5AB20B1D9239A9CC55C6C6FC371DA9F42373B5D0877E69F8FE9540971E1F93B8E86BB40183D35646ED12BE6A59D85530411F8661716359ADEEF174CB3717169CFD249073EEF29CC1B281E59E9E3D3EA1ADB425C4AF01449076588165436C5F4DDD668980367626FF371A02262A946B24C047961E373A3C4615F85DD305B534E566C6445D72F5C5C233A0B0B583EBFD3CAEB4B03CF8A8A0706F4E150AD82C8B3C96BDF2174D672BFCA2F4B9441A0BCA75CEF5B2501363B0C517EB99D37A93D2853E9F6EB61201274361C408549CF269B5A4438939773F4C44BE42F37D376C18B090E0CFCECA4A5C9D5A7E0FFA3C0CEC6550426A4F1AE413D031B803824ECF0E2B5E1773D67F91D56DCD16B9920CD458519CEC327DA059B89FEDCC7324E93E583DA4E32A8902CFF3BA98737EC020BBC06CC11494E24FE87E94D0828C19F65571D14B4E01170E5CEEE96996351BE4F108A72CBC6F5837E7F5AF9C8D5139804FADD0D69E7969F8D921654AED245929A03DBCABDC7870CFF6C6D3CA7BB9869AFEF7FA8404E4D89A2E4EB0F86B5B9B411E8FD09CD24CC5A1ADC8E0916F78043987E68346C7EE7110665580CCFB29C330167635015D3FE4B4F463A0CD13A86C06E4800B60A224FC1871BC50B1DC9F8FD991E81F88A28FBF43F36D5B95C5FEDC92B0CBCD290E85736D6ED54832A4DFACA12F4D85AA99B0F9B9540B17ACC1652F4069A2F89F4DFD08B872BFAF4EEBD1F2224DA8F8FD5E7F31B2BE93620A81B980816AEDEB6C73251C9C74B07ADB8375D8456D5A8ABFDFC2B78828EC4F870355DD6EA019353207EEAB6DE607F6EBB63D8B5768710951DD67F3CE26204ED96CA46F4FC6E7E0F8FA123DA7296187D0BFB7EC0A1DA39F236B0E4533255DBA5D6FC811AF02A0386D1DE80E1CFBBA55D2967B0CC4EBF7DCB7DD0CDCC53C7753DE41DBA5BFA376B3772AD79F180AB5796D2F39E380502728D145E06DC69AA1887EDDDAA232E9C71BFCEAB9966F933508D6EF5DFE9FFEB405C2196644904B44C2C7FD8677E4E5F92F604A9D30E2CC486262FA2D6985B3B7BB3BCA2767746F51D3F465AA1AF06CC5C7373EF2FB6049F8FDFBCDBB50D9613B438A8AC96FDCC1CA116F1A12C338CD88A6D5EA98770FDEEA7ECF62CA8B202FB2CED24F6908FC2536F3B0401495FB89FA1B6B03ACD8E4F78FCF7B8583017217DA4C747C31806875A9F88331DDCFF2669F0B74E1924DD779A63AD0F40EEA53411911BBBF7C32CAFB3C1F15B3353C0128D9A836634A12047701E74AAE8DD207C215BED3B73648C85E2B4DCDD7733E422F37127CD8D0A871E599FF8DAC0003710B8FABB4C5B8E312A9BCFAA6FCE05D4C21615FA502669261AC28A714960993B264A0F7D9F623FFDBC449C01B61071FCCA79816FE1A32CDDC9C564958931BC7B35D08996B6D2EE0298256F93084C639A9779D4BDAEEFBAA4E7CDC129F41F62613D7A8E54CC3AF283C28352321ECF84216A9E9321785274F1EB1CD58AABB601B6E7DCC2C7E2315A104D47A932127A0B5B66CA443FDC95222B8AD4C782DBE7B67D2D68FBAF4FB2496074AE32D4FF7B9C663D5FE9BDE5398F6A3173323F105EC26391171CBCB9908F3E13D8BF17DAF2E04F0158E185346C08AC17FE26E0219FF433A76829017E6538FDB031EC82ABF23EE832A88826379F02D012E1CEFA1B6A3F03D5B78846345B3633C127F3372620945B4B1B5C6A2044A49EF5B3EEB24B72BAC8054450D7C2D0B9D2B432C11A81 +smlen = 4563 +sm = 046E196339552B312B21C0FED9F6BA9F6DF229D2FAFE619E255AEA8581316C88E57407F7E4921EDE3445D67296CE18DE091BE0CD2F1F17E41E4D66A0DB2E5D81E87D926C299E541CFA951A632F8603E673871AD08744F39074355C06265AA71803A7587245C11F51F4B7883F91C6AD252740CE05BE022323056D3451F86C774187705208C4FDF3D020EE64B791C1516DD2BFD63A7B1976EDF1F19B4A974412978CFE403CD0E0FC5823CD1DCBD20E91BF0F95C02C51641AD42149D0245D1E55CD53898007836F13BAF89A1B1D805C9D2B1EE4407763CC481AF09C02284808652183461EE0E65F6DDAE73C3FA7ED721ED5E1EAB6FA8DA8DFAC785AC29C3FB3B36895F50AE0CE9B178F45BB905FE9EB2405B5D5B63493B52502451D389E298D966182A0C84F086B15C665A7D04BFCEC64030994DADB8DBE3513B513FFF120502413CE5C3D90CFD738F95585481EE2CA73BEA881B34BA09163C4734E431345031E913CFB6F44631DAB38D57DBC0B910C0A4F4B61E03BFE3846181BFF6A389DE2A2BE2C21218AD267F784C20ADD8E6E791924A9DCC0E2A9DA8ADCB2DCC6006A9761FE23EADFF6D99AD7D4110D72EC2CAE3CACBD6CAEEF777CFEC914A8EADD58994A61EE4088DC997D225D92F22A4B3A9C7F0EF262E714E5946FE03C5FCE66360BC538047510711541E55B05588345BD1BF51282FB71DB32F11565D771E177BA36AC750F64A4761F09C0711B4429F62F08F197D0501CA260CEAB7B221EF891B5A0354E541D1BA6132890B411EC47003450432DE3DC2C3409ED2E1172AB29587EFFD9FABD5C38898E02BC06FA90BE989DC348214A1A3B63A6B234EEAB722CE3D193F8B0E457812B1385B4524E5F2A2114CF3EB47776AACBFFF67AA744971DD97BF430840C61664BC981F21D264AF7977D4B8659622B757878F556359F69F321EA7A9A71127BAEB7AB433C731D1C748D4A9A969CB4AAD3D6AD7BD9DD24511D5952C754107C65856A53EA75611A39F2622532FE73BA18911811303B1DC621434F91FA15C3BCE2C60F2FC3DCE00960375200881022D895CCBE89C522ED2AC9E1391B02321E9AC43415D6B864D706A0A5BFBE151072B39B91B565204A8FBD2D684B2FF257EE4BD2E2DFA121491D39A55D8BAC4EDE3F97958FBFA175B717115C73C52243F1EB1928CCD629760735F6F2A1C850433F00ABE68FB6AB2253D32ECBAAF71D51E22F9A9FDF089C184999204B1EE71BACF2F0CB058DFCB4DEB0329F680FF222760208C5D969DA5864EF4B42FD6E25B87106FF06CE8CBF539463483B779C189D3E467B924BBCD4589B7CD01B2CE0F420F9124EA1FC45141525D481DCD558F35F572CBCFB91D9FABD2687580280382713D6565B048B6CEBD9C5A3F1E308EA5170C3A63DB2FAD7E812C50535F3C7AAC3B71828DA6D20A3E316F489572561C614D3246A84E80824EE3F133AAB73596E9184085A77B3DECA8875A643D55EE92F8B6E7E7446873A41F86B3B42D88878F08842A0F084239B3FC2B0A407B68ECF4E25410BCAEE0CA6D1A34E2A3A92DAFE1A0263A4707A7F7523640267D9EA475D2F80DA69E1D3B0A3021FBA066DF79B2E67E352673C1A7A45797F72A516F19DE8F59ED852855BB4965F18A484927FB7120AF8864515A4B43300CF3DCB0BC236EAAD68F01A3953A2E08AB917A0482F0820CDA329A5CC1C05B8FE19B1C21DBD8380A88F3C3B30C31EE581CACD3E1C0B7A0FE8959ABF92FDFAAF310111125373AC605212E2A18F272CFB6AD1D934BCD172BE223F3554DE5C50020D78349E4F3FD9886170D2806FFE713874D44E016CB04DF7AE327AA22E3AA77807EF373AB8DAE944892B3A419650DFE22CF48E7C06E121A0219235183539D4C72CE9649B88F8D3CBE97B5755D8CBB8E786323343D1DA07D2ABA5FAB76ED39E67A2B4B62C7DFC1EFF5636EAA2AA688BD7E62C94E3F6743E6660C7E016150AC10BBF6B88989938B6A918B6D8B64D9194F79B8A18FDB839AC26E00B73711FD04276A36DA7AC6BEF938333034EE6A27DAF929A1EA081293A6F024086CBAAF9D3FFF2C0CD798DE73DCE57527E1AE491BBC20D8694E756CDE65011C154B23AFBA3C629E90624A5A3B940873D589146F2078384E2C3987D06AEDB8932255B7F0B5F5C767FC981A92B1D41A0A1CEA212DD469EFEC5CA0E0B9F1A65252D5101BEF425CFA37A82EAD3314299A1B3124494D3877E263A4516A82A534B314180040BE439E0DDAC7F33AED6D857AEC25B9CA8B72124FB61B6A8EF23B294E9AE8CF8754BEE6D6DAC1F1D55A3CBFC100A72A3845E174CAECF5437221373F7B03D64D5109878EE7D0780B506A10F6DBBFF8FF23BAFA48255852250A56C8C0E9F8D15AC0EF5CD593422474379F309D18D150189A75CD2466AC0372D1A9F6713E8B4B59FA3111D20E965788E23E47A096420AB6EEFC29435447BB8107E9008D7B213B63894E0E8AA9C2946C27968E4AF08B540EEFB952E690B69799C08FFC98DD2B68CDF0BD5C00CEAFDB59918ADC5F0177374515348F2BD8EFB208E971342CE208F31ADC58B97A55A7A33B27307E51A57D467CDC83B6BAD9F4B8041ED2BCEA2AA8B6891490C6AB48C793222FE8F0E0FCF86D134D23B60E38D94443974349DBF5B2496DBC911B5F65D4DE099D09E5B2DC1061024CAFEA8F86246BD8FDB5FA22DE626749C36479E00C409E7A510E4358008E1098C8C4A26A2A34EC89F25CD0091911DABB40204BB05C815628A3A53413A84990413FE8BF94963AC4FFB8D4024B85AAEF95F0D9096EFD301927A4FFF616FB1218688EC86F58457CAE7B5747CBC1EA51B057CB3433CA9F9E840801EDD7852219D617477A4C258832B5B09D54F4BAE005C3411A1D8117ABB4E45B6D0D52181BDE8760D0694845348E792AD54F92C366950D4BADF8E769EE2A9B9380B165AD962BCAE2CBCC3AE4B1E6D3FA40BB7695C2810BA326BCD5986AE3A314C6F7A6955EBD51179FD9028DED1C4F30BE595BFE54D315934BFC5132E7E83EEB70E73077C59B16EE2202F225031A072E1993F62B542AF071249F83D0243C43E4F9CB2FA6569B7E7A5E2AB989A1981AC92C4433610DBA5D15406243843E37A531861438C20DE7AAB03C3E3F6FD610C1FF2D91D00B695AEB54BB279BFE409C42F182C571A78D566DA6798D1155B6CDA614EE202E084D8EDBCC4B8E6265EA82800CE42DA14011B9FE28F281933ACA4B374C4ECD4D7E90EDC5578AEFCD97AF9FD318EE9806B35FC43E8C353356024E50B4E0137D5EA10650D89B408F8A433251F09B2DD923650A6F4B6CF4B2D5FE680F3641307AAEAF10524C580E8A0A4E15CB1B75B3321F81BEE5A66ECC79F4491B6DA038F8D18B33FF0D37CFAD09CE65D0F52D64CDBE490A99876612E134BCBF950F8FE40ADE680F21FA771BDC0643A44FB56F42358EE63EE884F74DE3D887EEADC61A686704CF9B695167870560C4B17A0AC5CC17E7D0D26D2F6E3E40C7FEB8EE7A5F535690F2BE506105E6D299C3BE4C75A661DFE16E1FBAAF633B35669510705667E8E8B572CD01C36B207E603C1B28F70BB5D60331272A7E4C9D2EA368BE95591683DD77B3BD091F92930B39189825CAA954E34AF730994ADCF608EDD711F4E04D3A5B5E4D03944D4D2ABDF4FC384832FD32D874B1FDBDD6235AE0426378C9745AB26C57B6FF2230166F71D0E143206CD0CB8DA2ED7AB4BC99BBF5A11F4691925DFC8212BCBA2AC1BA519CB8E8D8A8523891A2FAE706E798F004C4CD33AFDAFA28ED0F886815DDF0F7C09F0E59E7BA0322418B8498C0E0B58DE3C6689D13F8736878B1DBDBBF77E2F4FD092957E73197E377DF130D52E306B97E8E28EF337F79007EB9EEE22D699E7EDC7B98C4E8727D51EAB46187435C297B036B02A96713A7E6752C08D1AD2E7AF12A42B75966079533F4FFA1116FD5DABB8FC0D078CB8AA324223A16EE1111C18D0D736D5C589C1A5CE338F7F0CC61EA04D59D0D49C3CBC075E22FEAFF4A1408916185DBF8E525CBEE1D52E655D6D1AEDADC6F49AD660D2D2BB131B93D7761CD85AF8B8FBB4E541AE9562435E8E000902A7F8AD896A8CA5B91E65FAD2591E13F8459001FCBDD18D2D6F9B086D58A95F2786A90C4F1427E997CC8530F1ECACBE0ECE2B0AA1F852B039CD6C53032B9AA02593A837C246F88DEC36F16FF9BF371377D60245F30F9E1DABD51E1D149FA8A9744F80690BFC7291C423C5264C121ECDBB025050EAFBF3D58251A33C7F09123A9ABE719A13E7D2FC5BA84B7B10E7D2CF3DB3517DFD4988EE91F22D6A07DBD1CD8631FE0C36D8C92111D8EA8F7CE1F8B85011A9FEA6B700F765258490A598AAB6A24DEEE9AE30F49CC1823C04A3BBC57D21EC49956FCD88304CE0C09783CE2DA392DF4DC261A5D08D1D370912556A89B59FB8CF9B1B45B180B52DFBF2A272509771A9780F2693936017FFA2095A3CD91AD4270404C75D26FC3CC9699F7345420CE3A45A3BA8FE64F773FF7063086926CE7482C7DC12579684B03CFE65350A23C30F0B400EAA6B52D3B2BBC425583B60628CA16774D070B920FFBF0B8B45E39AE7A4571E1A48DABE45B5FAA9B88C956758A3EBAE56A18C18353C5369B8CAD4E70104414A7B8DB0FC21223F60C8FF393B3C5BAC01209DCCD6F7052F87A6B3B8DCFC000000000000000000000000000911171C222A3382E87BA70EA986A044B0CBA2EAFC3316C1AC95A5F16F6368C210DBEADFAE6CF2382DDF5078AD594CDE3BD1A837C517B1A20A2099D938DF6AA02B6C0E62FE6147C904BCF3EDE51DDDA60DE7887DFEB2866DB402D23E5934A74C9CE4852D4B2F53CC9BCDDA312964A548F6F7C8320AF1D1BDBA7FD32EC6C86BC3FCB4205ED3DB092FDCAD9AC4D2B8575883E13F69D8C16CB18D1B9284B31823ECE917C905C5C8B9D180C1BD87975871014F773FB57D402B8FE16EE312692665824CF0BCE4509326A31957319364CD421E9B21BBC1DFF663ED850858A2450C2FFE64B65E009A3999CE4504BA5313BA0EE4A8843349C30FA6E59FD3ACECA130A37C04F9B64722608768973996112684B64D0C87BF95E5DD60661935831A6A1A9575EBCB2F64A15296BE788C775D80523D6BB4267D91B0C71BA5F90DDF1933DE898E79FC7E39D0A3D146F185214468DA50AEB47402AB542E52CEB768A70CB1F749E4164CF20E549B674CE965FFBB98D874D34B5B7851E575E6C1E4DE9C170A10DAB84940AF055A951260B0119F5ACBA320B55CDCE4F16346905A2073CD9FEFBA95734E4F4DFDB7A33F292D45698831F1D3E9FBF56D9692C14A8F9887265CBB4441AB331D977E3A68A1BC9F406AE0FB1C6E91205670641B9868E2A987BACEEE2364FDB089A63B53976D600BD7A8AE88A02872E46927269D281CEFA385C98CCDFA6609394943FAC32237368C6203AAFABDE072054AB5A14A91391D5A943F4ED4A4407F275CCFD15FD28F1AE0EB6EDCC6612E3436572919E4DFB57C049BD77B344D8E04152863EFD4FAE8FE3A7230AEAAAF82870820085F4B3EB5215111B6B8952CF2FF468B3D10F3AF849F16E190E9560F40B05E6E2204591B58A850E2710F7043AEE2A44A6D4A108CEEDEB2D216E51102DD08751925DE6A7F67BCA1980F0789B34E2F86729621F2285C5D3A036CD87C76102E9D607C37CCDAC8062CEB961053F3195B5ABD88BC64FC65F8BE34166841683F1EED291938F75DFDB3AF4FD2AA98CE95382ACFB5D5DFE6EF243C8A0B19B80584FC0CD533E38BD485D1C52E0EB5BFF90C0A947D9B9095AC1C0CE9754EABFC860990206B981235C7B612DB61C9FDEFC0F14DBF68A8A0EA4986CDC4AABAD6C218559E11CCEECD804EB98446FB33EAE47C0388BD8972DDAC02CE807B707D6D188CB31A1D76D44323E93DAC4F8ECF77E7896C052EF16009CE4D1147DF84FD5785D95D77310783F9AEFF1DDA693F4BED26457ED82A1CEA19D9C4919257E3050B25A7D1CE7561740DDAC3FD93A607C79875E050E40498BFBCCA95BDB3D0FE639DC7CEA80E3DAB3AD73A4265F012451C1BCC2FDA1E1AEBB7FB18407F31E7496E2A18D2C686B47120688240A2FB134A3C314D4CB422811E850524684EC485E061F7365494A6403AF170DA461A3BC32FFAF9143D5E9B17B2285C56977AECAF880CDD34F26120DAC4C950198233A50654EFACA6EA97333D2BBC024A5E668821D20333DF0B712510100AECAB6B484CCB7814178F851A3E6BA0B76F16C4685D5AC8BA48558D382ABECBDCF0B919C1ACAE46EBEB5011DD0B3C22B539810720CFBE4CBADB111E100C09C811E724A67C66A1B89EED1E7218861F55A4DC55E236C6E3521DCB374437A14E8000DBEBF0F7F9BF409AF952888675C11326D9E3E8A8828BF50CAECFF96075CF29446CADA373529D310660CBD60C042C143E1736FE7AFAF6FBE42791A8DB01EC0475145257FE2DF766D4EA972B14AE5110B8F8F42D659383E9BD76 + +count = 38 +seed = A4563D09AD21D3916BF4636301F2E64183A8F003DA186753D7F2DC3BE0089BA09C62B8A52B72C2C8451213606801FB29 +mlen = 1287 +msg = 67109894C579974373CA0054ED5F7C373B7AEB810721C3D9CEFA02EB244EF6B17507300370ADB24AE0173C6D114C51E05F822A770318033C082B6502F70012283EDA2A9DC0A1381F145470E5D3729D201773D2AA63C18885A92C962BCD3628835391D70DC36273DFAA4966F65AD40EB51FB4B416A8D0B1DDF39CB932EC4503BEA23E3D9D3B4501DB426C6AD99C28D415FB565F62EB5C22BB043C8CAFC42EBD1C7190DD32A5B14B571644471453740C081F3E3305F9AE70A5BD505874382EC0F6E2188563E763BB8D1BB8B16587AE25A6252F51E4AD02D0483C4A6E8AA2849C44629CF4B7C6DD6A5FECDAB0F9B2F0B35E306C7532B64BD5A3CE67A0247D97024AAFE5CBC13E375AA69B8287BBA9DDC9AAAC2BCF41A71E373EE36B13DF9F829BBEE8F48802DD9E03BE42A5E290251BB130E0E2ABCC4E096DD0F264E5D29F8C2388A0C3010E78F2A03F5BA1BE13AA5E50F2BA67A031CE3F787754B8276EA1AF62BC5FB4DD9A9B9BB84217A37EB9FC7AAFB517337B30454200D6AAE491E50D5007EAC2150F60F640A5C4624CE6D8112119413731322BAD9762BCF72349EE38E2A41102BC5461D72033072A90E82D105E6FCDAED9C223A4142CD55920196D7B1B9278C84B67A2E35BDE3C9CEEBB8E9007BA8758BD35C875DD5FA0A8FDAAAA9A09629B9DF69AFAAB456E105DABF2AC5834B8D223B0A406E0D1295C876C447E8E09C93FB09ED1B3EF6E1F3B7FCB029F576A45A12620567E05F218BC3753109DD29AE0ADE1370C0F871AB5AD8A9DBAA277FB869EE552E8733E73886D6DFEACE6B35E481F37A516EBE191DAA6F83E4FF453CF9CC9DDEA8EE507AF0E62EF3CB8C22949CB828E21C6AAF3FA9AC301E2257B0A054FF0A237F527D53EB757820AF637FFC9F983A2B5AFF0B4CC493E610314432C9C2F0FF73C4240D520D1D73721B429CE41807B7424B14F5EB1CD23D5562263FE1D58CB1D52E5175414800CB090242E240C3A7ACAD4C84DBD8ABC2731FA2B1D9820DA60FDB6BAA7EA849B6A146E07AF7FC201B3A98E5194BB5826945FACA3690209E5726F070A71EE07AE76ADB7E6199FCCC81C8AF7A463633A58873B4F7E65F522FDA409979DE41CF54F659E66CD5950A3A3E01570526C46417A00EC2E8821DC380ABFA21384D141D259CBB9722F267E46272ADC5CC4BCE382B554226996F4A6A1605287276C18A48C8FF1A92ECD2815CA5452FD6157FC27532680022993535549BF9AB064052E6DB4E9F83B5D0D885B94A90F59E67B9DF0C321EB0F95AC07007E4EE33BA89AABEEEEA01FD1172ECA4E31FB02C507FFE43CD0D6C8570769A180E68A70BD344B4C992E7D3A6BFB96AC4D69C2D4F5EFACA1D348DC1988DE44B30DA76BABC307A88124F96F26737A85FE6047E7E485C7E4B6B99B575FAEDC9BACA3E080E2B074CFFCE1F716C6A1D08234C45706D2883C6E5A001D02596CFE5B260DE6134C75DF3AC8BCF1919759E15576CA147CEBE041D04E369BDE70CC64157AEDA311C8DA520EAE907C33E30DD89013E24B7B02E66C9F285BF7D5C3FD65BAE24AB20D40ADDB451AB4BC4B9772D0B9039461BCA8D3D2A4D71A2E6BFBE7F02325FD571FCAE1FB47F855612F382188A5FA3D61C3E8E59EF016DB0149C52E1C7DC84030E6C93C4F32DA6CE5F3B8196AFFDE834D2ADC26CFA05940055401891519386BCD33D85584D74B2F16D8E19556C272AEE8397A1741EFFC283DBAD317740C1B67F8F4B7D2D1EDD68D6615EAC3F8E3CD26AC4F8058667FB388B19C654711B5B2EDA75A9AB55174157CBE08C186A3D0963BB3011A9567BD499AD2A8 +pk = 7ADCEA32C084747DD4E22E14966CCD766D2FF932A985F2AE5A8725AB71A925F2281D3FF1A0B3445E1C50AFE491535A0116A821A63EB0C059EF4CC3F49D0FBB3414AC8F6BD1748A5F97B6981F7ED5F19D2E66239408212589D2494C3870076C10F1362D527443E8705E802921DE1E3791E4EBF9EF43BEA048CB3EE268837DD62700669F60E626589CE04A66D6CA09A64DD8A6355F394083B29EC5F4A2AF24E72447843C8A693603A4C0E344F872799274E3D005C551066A251A69DF146DA8494D650A6E78A1F315D76FCDFB8608A794E41512840EAD2FD2823E063F4DC563B88B3393652F9304353662D95DA383FD1450779D90336371497DAA5442B869189C88FCC63BEE53A961D055BDA6278FCD832DEEBEE11715B0DA31EC50477B08DF1FDD888EB14EF86BE5CD91B5CC28C68186D266D470964DE5FF652C570ECB144EAA614F4DC7EB5FA834B36581B2AA00CFBF0807B83AB28EE09250AC7816058D05C5955D51F5E793004DD989F4327CFBA2103E526DB552043273439391054F8B6C6AAD06F1B51F61DBA9B7A672B96D3E5437DA83C4B5166D86439DE8362801FA01A53D2C797ED8FF3418A1DC1B58B279FCADB96B7624F413B969593D82DCFF667069393121E150FD60B61313F7704A28C042B45BA08C901C843F99084D30B316D181C82E51F215C0172BA50EC231A1F4B4A25476A6F84C1777BDA2488DA5D8EAED894B003B2257EA72C7E0E49C33380C5AFCD1235A72C47E242C16880CD053696B78C2D22474E2114A4D86CB00C9873CD26E93F332CF3ECF0BBF765944ED5EEFB781D6347EA5AABF30F1B12A47FA97661DF3E0B1E752AD2DD33BDEC4B6824C43ED1237BC8C4010731DB80B1CDC556AF636DA833A59A7D53155F1B28B0FD48E3BA596CEAB037BCADA930A9031B35F6DAA559CDFB499C3C574B8FEFD35B5A30836D0DCDCEC2447665374E3D6F6F52331B530EC1E07AACF283D8362AADA78DE34FA93DFEC26D9659F00A3B204C8F447D805D68B9FE78DC6CC42B695119599828D57ADB21D9FE13C9B1B9A69EB98D060F4F57D5C361863F1DCFDEFDB9D289DE85FAECB340E3FBBE5556F880ED4BC2D72FD4FBB1887DD5726131B32C3B651A674D88EEF68C8E4F88512BD45CC640FDE67403A7CFAAC991AE964EEE998A6ACB71D6663E55FBA2B505E0EF34A5472A7E604626D3701977082A175133AF605001B098227753A599A2B2315CE096DEB57B37CF319FE7F72D1B1DB111B76418FA91D0644653422C21402F972B3C7317E64E554660075FEB21DE65141B5708EB7FA4D7B1E0211C06736B4DF077A35164B769FCF19B8BF28D6D5F5D97B68A61286B7F8806DC4B00855ED1EF2FFBA85138D3CD998C2BB5D85FCF63A0C9A49FDE2E3AAC8D00FE861BA1105D25C03E910E339C2172A8D46B6B95751BC5B7CBFA5BCB3BEE29ECA6FF4D654B292FD0462AD963E108EC57BD060A65BC06C8D50FEB3AF97B1B5FDB7749CBD2E9AAF80CDE92F437AB049342502A078248DE7DB6C775715FC70F962FFB41B83FB682F92C5EE6A5D86C0D028F44F53AF41289DD9D7594C1663477384F897E084FF74A245DBAE7C7B599027D1D95446366F23C1B6DFF1D60A19531E191BF0385235145DEB6884FAE121DA567FAEA069E69259F9DAE140DB36C8EA6828BBD5633175D7FE71489A566A3F8CCA16CCBEA980BF3A0431A873768493842AC9255275248B9881EDDBF08D72B05E681F1526B1923E2EB02BFA8E2108D4FDDF5C02D306950DF95D49E8D1706E8A5D80F08E3F814DA010F4ACD452151D1862ABC4C8733B296082F2FA0127D9B5E2336B5684434F178C0CACEE8FE0F1AD9E00F028EE23BA904AAF0220ECD39531839788D450B0EEC1516A6B04232BC7324BDB16A36DD79212180A6FF3F9077B64079BBAB7822B45D074E9C4768FDA73FDE761B8E1AE7D44D532EC32C9C8E4149509D0A75464F03252F21381DD2CEB034D0BDE51AAD4140F72FB086A01D0865AA0C376A3D033DC0B111C00A6E93A99629DB63A30A40C8A6FF55251716FF712B8AAF0DD9916DA8A9976F69DF9DE35C364BD68E091DD0D05DA93D87CAD2AECBBC771255BEB29FBADD28E72223C81E1942363C5F2090D6B64A438C640EF395AA86B0193DEA4C199D98781380200D915FC42C24B061B69E8DDB9264FA67FE17F58DECABBF30742D89C380EC46500314AB7B498AAC7F078702A9F042795FFEA8C7A9727068A281DE03ABAF99522AA1881603AB3CD4C6003D8F90CA05A4444B80C88A95061BC7039B094E32676B51A1F329BAB0A01144A913A3AD367B2DC0428F7431B8419F51F773C97FAA1FE5EB0D64DC5DFC598CE8C895FFF6550918B4768C83A6251DCE695A4D249DC3FCA5035350462086BFAD325467389C7687D62AB3E2406CE8984CEA47382CE6B0F70CFA274EB20FA2F8C51EC74924BBCE4B3F3BEC1F3F8DC5523F06CF05F9FE9384330530616194A57515F794DB72CF324A52DDDE9B37912321DBA914DDF3FDF7A8B254D4AA46888DD0E5052D396FBAEBD9F243D9EA312FB77136ACD14791CBD9ED6FD28368161124F6ADDC0BED4605B1D17A4ECF168574B6EDBA115575C296A2BF851CFEBF4678E6D050EA862BC76F2D541B0BF31392565DA18477062605A0E7775877A7F5245A83686D4E2B15FC69A2B63CBEAC7B3D8189E5D8E10E8127BE1CD0C8D0A4BAE571730A9FE2E3CBD9F3926D9EAB017C9919E1D2034F047F2B9A2CA70429E0FC989062F9E6BD12931D237D9C9 +sk = 7ADCEA32C084747DD4E22E14966CCD766D2FF932A985F2AE5A8725AB71A925F275CF85A56315CB1678AFBF3B0BF5E67EDF158ED97C87D3D1081E9E41C485735171529C070AA677B72EA5519E6A9B8B443167C5678A36601C02ECB3E8EA5EBB34B40F7BF1E44CB4EFBCCD29B41C43D05F0C2D580B848B25214D2F1E77250B38D763542242244164814828038085757854084212658330773748256368386043630873752835803203241854743026400066008100760567572360842144884485317018215464488731703272278845865713864411355238360101038457818623033260342818537464706867457637288273613082280445332835181430575762331861232062088133007208327387040537045653156210168603284537502685135243201168778145710560776455606015776078525320862327371285234456714371786607354418322321008331628848542121782024630832248478317076046014735838383888032820722204886102122375121361502703014220240534678867855628357656077570326705842868031215061211425783874870447827847244606284456862345311610150516682485432386716706582242246515233451487100550771376654007168361107071765506036438277301175564557300178400263860108056280848647087114452320747213418344846840726713515863088511015055518837034031722283125111873051482104515652013333640673620734430208642516672702854058113456042016535530841124044312180532421851384340667635346065424408265518846210703224537487145700288500163647625720040206150701474841828511313625731528501658544227414553171467183626625221802124464015766244526757012426234226442480510067167320466457646124463546316023007236226184138222183352603701178017673818102520805586174704050827636533776277120013032681513048432733855888488201400743660657362814356637854884441870235747407365483368537004870017660162361548510074287425876802425308677310027633544548103472207763700084478352183223085236677880780462514223228521437284311038111362560110124628120526607785107845342544562660215238684778884783714852163380022855274207844411460115830321501322671450746248154736442046478601352562555108283046833667867271150715714678822701414582850402312378774023817756261005124718050433607885667731335143404828460820513500828450478283044818036317187724627418806345082134141351301100781282574340330165477058177385043002010715360052863884245020680333831182378110642014166217644813046702768066462724661444057821503666581865450686527638584218558362604138156716708077212171167433020230781003812464634183262547666237217884137147378064600260675538783665148740882401765576206252627100777645118174613884772715845530662537148380446552002140424442533057373481802016867172178315865815832605255541066188562271766015633160426425444341072481205171218618125481183081760010546661754380343102444116576376648740256162477878334523172780765116406051625044574061172354036251256507343247717128318176816384886663725371707535435735721536580400657724224661878104056603255431621077836578750771317043242437271672087514803558737011826106036065781154163026235683412024086362010571076561370725642182862632637304854731583477861885845488521821565651487317233278264052416684721115641241300672740812346241615785862324414237428034328584732800154652032152765806852871142857461381420826558232370353758135224356120551166146042535850514006271042D382FB3B1DCDFFB2A49337A5686D57E5B80B453DEEBFFA5E6DCF36C4414FA8C35475FC10883EB55DBA976DA7513009A59990CEA292A829A77D6C056B27F9DCFCD0027D4DD7716D9FC5AC1D1137AE2B6AA0185607C240F1AE6D3DA4531BC44128FE4B1CEDFD978135EA87F0CA54190678A3DB99653E25560E93A1C07539E0B320B49880D522F9930F5BF02D4E80986D60D2AD51373763913B9A9213D58E06BE21C0236E43E6377164E367446C791370495229748EAA17EDE67EB81129815A5EB138ABBFA7768875173C7FA308500A8F8BB90D7F151A00A1996B2DD079311EAB61022DBC888C6F14C8E40A5A8E10111B17C7099899976B5ACEAEF0E28B9D02BB82D1A929EF12545394F74294868D3F103FED45118762FB5E76860BB74CC732D2E1F973DEE450FF54DA76F64A745C4D0C0B1A3DCD40A736D7C91351EAC51D9D836F73CF321CBCA628178754B3953A025CA3D8B3C4A5C3C07B387D294A8E67F48F3EEB84DC70B318AF32D2794CEA5B16887D17E8F8E5D94C6EFBE0497A4D814DE8D1D4BEE5D944AF7DCA0A97F26626CA6811A60BA3652783E9C42FA2B7015AF4FE632572CF808AB3B8D727511CB3677EE34FCBF465B7C522C8E2322071BE70732300E6F273CB18FE72121334CE1038D2D5EA39E9BC2CA72614D992308D33F21BB0EE6FE1E34AC1B7A770CFAE68CFB9CC4F9AC35320970CAED989ED9F9AEDFA00A86900E88A2E0081891C49DC5A7F3558B51180DB56C707F960A37EB66718C804FEAF6F2E3A61BCC23CB2A489CC8186DB784887B0C3BD415840112E5830FF9129E10D98A81E005D2C40AD2E6F11009C2C8871CB4CB47A949891EF02B3C08CD43E9B2782DDCFB0A56225C0398A45C6B2C981602642B04155EA091E7A4BE2082496C63206196EA07FE1586DDFF0EB25A2623F4331D63F2A162138A9ED95E02C9E0FA7350CD9DE20B92CF278AC29A97EF5A6F8C373F3E92E46F4D0891CD16D2DDAEC0092331C12C9EF4447A8657E09B5D860916F4974C3E821A135ADB97A22B02BF624B4A88CDFAA335991FBA24F95AB065A993CE1A5E6087CFB524C830CE2E69035694BFD5F9A853326123E6816B07E865B8CCD068DF2F6A4040EB9AA152EE4E3A921F99886F257110F5C60469B214C7CBDE7B169FB897178CCE58021C9060AEDCF63AF5BF55D1F3A0D2B779F7AE1E2FBEE4870D6B60FBB983853C938653FB6B84BA0935BD2CA7A73EF568F2AF65CE2DA745458FE7BCED95DC5777943B03E97509625D36CB91C5613D8174B5E44B1C0A2DE6D94C85969E14B72DA044F3A54C067E457EF0F3FF963E7C2014F334F0BC27A3A438209260E2AFB1250A580AB2D2A8B315989C9681542A19AC157E0AC3DB7374BA189572ED7B1C2ECB8CB26138F0221682188148626558DBF14A8337715823092A47B273642337014EAE22F40B9B42489D2BDB276C14D022F1DD113D1CAFE00022BDA0E7F26AE66DD5D3000DB9CABD68943A1C133D1E68843EB08F7CBB542DFFEEA697262F99D2C8EA4B78B1BDBE934EEE9DEA8E02A5CF1104C04036A0123B4C3FBBB0FFE258B770F7C789BCA310F00B77B77AB46671A8668A1EDBABF0C1FB947DFE2183C4ED39F5784238CDE75F0C4798C35B2E880E1213FF0E3A91B9579A227629E6AAAA4EB0A372F00BA0CD82D6B3CBB27C3D3F93A9EC869A9A903C8616AD211A805E2A1F2F74B9C52AD9FAFFC55C2D750BA923C2ED62ECAF921CFED3D850C93734174DAA9B74F7D41FB05BF8D96A8C26EA77A9305B53E1C2070D0EBC9054648C331E53C6C7776767D6CC98461AFFC83BF3E6D5EC380EEA260509A4EA474D293BD15C62F949E9402416449F29923B9DD9E1066413722371E8DA4A991C4E297F6BD976A9479950097C51086EA0C9249E6D75E3FD5FBCD054BD67793DC9E3E5AEB952AF5058EEF46D0ACE04C16CBEA731F3B71512680292F484FCF27AB47D608BABC8A8FC778F97113C3F88C48BCC82835DF6BBA5F9D0C59AF5EF7EF2B0B9A79A73DC5522BD3F6770F3C32AA2B3EB02870C8F98A81607F10F0C3EC01816144D800C0A92CD7335795B9D22CBC051F9673E7889AFF9D2E55244E5CD1CF731285A059184D88FBA077320AFE6A6F22145236CD2B596800AD8D30D1CD0F71A18905A572994CB5F2976E1BF8889E63B9856C0815B2624691EF6823CEC3F544D7C4CCDC8D0F67AEC312CA4036170C9A702DDCDD750236C60EEE8EC4C8BE9677DC757A8C7FBC4F26D7B1A90F7F92A50C30C8EF3E6B6D085EA692CB280A4005DAA7ECE025DC27FDB03CA31E1558250E01BD6C1894A4CBD4ED703FF2611576678F5262358C465CBFD72821AF39062B06BD48E35661D306AB0F41EDFD2784C83CFF8CCCD9DA7513A9D5D4895607F6320E8BA0979DCA586C8265A05746F0F18C961041DA0DAF66F584A1613B1C8C855FA0178C42FED5340150E1D73E9014F2244955A516D9131E1CE5F608B036671293B484B129EADFCCBF6703094A8D3A33A78D1D7B85833F1E7668A389547127B0DC817EDCFF00AAF2A06A01D1BB97829E98523ADDA83B3AB0C6A60625F269B804ADDB763503FCCC4D77ADD5FB45F91F29F8C789D309A10EDB11638F39462EDB6032CB4EE5D08BDA7C6547DB78A64D7766EE7DE2BFE48F8DD2A2C14577EB0F5707B78864CA6910037C26C904278F211DE1789823A5EF31E7291D3A0A1396B716CDFE2B8304C0A1E89213895E88A47262F1D9058AC2713CEB266B4ECD810E33BF1AA34554580AAF736E05C052FEE1BBFEEF5A17ED4D38F7FBD81CE559424B3A35740E33F42BACB8A90CD7E28C62C98C305649F00C51A793D3350B0CAC4B94F1943AAF37721C28F6D9AB5DA7C545790C087606C3F7ABA49965DACF90322DBD88B884D7F4BE20EB0CB14C5CA1D77C1DC8F2082BB588513A2CC64DA38921F4A7628351D9563DBCE140FFD2A2F0ED000D895A966CE01A1FE5F92B7FB8ECBF860A635249843B1A5F8813E23F57600D68FC678F55E5C5E5CAA50F8F0F57A7E8A2471DCCC7EFC98F09FFCD0084D1921208A490C8CFC9DD97728A037C9B98A7F5E300412C502B678390B99DEEB94A18BAEDABE3CB94E2D6276BB2461F954AB1A40669ACBAD30DBE0A1A50D06D216B2585931761F5C1ECC12D83746860FCB84B3BE05D00B94F51384D8974930F9D454ABC388010C7636E2A15F52DCB7CAB2977E042B7823B32C0255DD1B9D8C297FBF82CDBB2480B9B5BF06516EEEB1E1D81C29EF437AFA67EBF7DDE0BCA7389EF1B9B491AB735C854C25BBEE5E3E2167B77BC5335AEC7F47374897D5EB5B67CABF127C9DBF432C07B28752FE3B360F217E9530F2CCB9A5DAA930ED479679033D2594BC5B18381BC5420BD4FE45BF91A161E68B21168551F0DA7113CB95E49ED7BC2F8297402DC6EDF799780063E7FF3A671674B693CB7A295A7F8FB12F95991867C0182B7FDA65BCBF156FD9F760F4005AB115C0F39269E08F347425808F34B8EAF860FC947590AFD8F306367E18199907B0DE0125D329D7F6FB0D4729A1F1AE58B +smlen = 4596 +sm = 24F0AE98EACC4D80697ABF1ADBB1A4ADDD77BD7051280CF56193337888D6C1E046183578683A47A403A4081790008F6454D63630B800E41B0F35622ED3CBA0AEC34F1047985D46A19AB3F751E2902277948F1A215FF61B7FB87A658A4C97E1A2582200D8BA4BF34FE511BE54BB6D2062AF27FF04283C2BB4465E2885DDC89FD71CB5B61A31574D6E732F6C195D2A45C8019F57611E21DF27D051897AC87829250C501CBA8C0606106F288B96B65331506C50B02084761DCC42D68C75787BB300A39029EB3A6F13D8F371DFDA14A3F848BC0AE8E6BAA99C76D3B6F74EFDB8E604A7E3A94A1612ECD84F18A4814A6BF97F716EFAACA5201064E1ECF2AD4DA6032CF2F6A08EDE37233F4261AC0949E07E775E1B9ADB3E4AC08BB5B93ED4C4F049F49E6A1DEC7861D4508B774490BD9841D66676F5ADFDC8BAAD31C871A4E89E2540933C5F89E41948768234E2A84333E72ED8651B9D1EE821E67AA55FCCD068A26413F160C5A922D03C47B633A551F9AEB6F6669DF0E1E32A622600C3A5F7FC600913323146D69FA59B41F0429149D503BFD1556D53A84FFE8FE0B1ADBFBDEF4390143BC514E7F76DD92DDA08B5B3C798EC7C0D63C777DE3790F919F36BE29DAB4D73D9D6B0F0D4A32C2F94159263E789D902163F4EBE915CBCA1083B50641309486CE94129C6586AB7FA008A9527786A10283CD8C346CD78A316910975B39B4FE69FAB1371011998A0C2E5D367E584B5AA3D9B2E675156581E0487C75913C5ABD72C6B2E7B9BCFB7B580A6E0F864F49510511DDB6272A47AC841FA306DD0C353A30E1EA6334B4A2F40B874E9FA2FCB0D72C61AD46DB9DDB67B120A8A28052367B44E8B18FEE4F2D491110946522EFB736F4B7FF5DDBA842A6CDCA9394CB298E28453C614436427A4EB84D87D9848A76E98B83CF61838F179BA7E83E4B0A636EF65C6A850D30B9084F34A67B98DD6A4BF5042C4BB01D618B88FA94B4835CEDDDEA2A9D18F6FEF89D378922F88F50035BF23FA4E55C29FF6B067FB05C51C8D4A82F5BB04B6BC1099410A55E272F0F393C38C47D45DC256B61C65053C03C16AA0373BA4E5FB45D356853F81A2048211651E7A6C2CE96A2319F1210C12E60215053B0A5E8DAAE3E2BB26E0A85E364C34BE8E30CDA06DF8EE850302BB590C1D87891B2BA1BB5FD892A113A99C7C01484224DF806E52F80C8DCE5D3D90EAD940E12A399D2837C580465733BAC0A248FEDE2A990588800616367C934C0D3ABE8A49441F275A13ED27BF271942B8658E6B986F95E93C32C0019BC20C02934648427BAB7674178310275128EBD46D488A88BDC8E57DD614E42796A18D6B979078B864808293380028D6D218CE3294CC5F10912C06FB7B4C899FC82D962B37C4388620B871685F85543E752F10CE7626B30B81A9F1D6C8EBFF72385C18057AD65B3800FC6FD9D929AB40133CBCEF58B649B179470EE166CFE9E0056351680F35C145F0F8E00C2E1440589B8968D5BAA0BBF59BABCAA4F0BC78384A6BC0AEAD48AA4A058B8D2EF27D8C2B335AADCA8E1007026D7DFC41C08D772C359EB89CE9D8FBB72E5E633915E8732F96E51B9E51F47C1188960792B9D532028D6C1EDD0E5D2458399025A13C181ED500E2816842F6E728E44D3C2F3C82C94E2B8E580244E8315DA0C22D09BEAEDA38AE6F26A404D17A972A7C64CEEB33B61D7A73350D7D385EF4E85ADE850A90219B86283DBCBA79696BEB3A70D686BB61419BF26172383CC43BE4C3984E10FE4C7DE782A94C63C55BBF0055C512F89BFADE61C9D5F0396830F61FEBF24441B8E9585FDA3AA9D0F1883562B5A53B5E638A89E88D6EBAC83BD0EBFCC11918E90BC84D3174CD26ED2ED9B64E0FE5C0E0B61454D28426B790B0A65CA00B8153E2D9B6FEBFDF3EFEC38001BDB402302D340AC50F67844EC60D03BCC19030193EE1E084CF584B427521B5157B6A6317FEFD0750742AB7A922273CFCDB186DFC99FDBFF6D956EF28E2995AFE9887859D69576C4C25648176918512845CD771F5F9C38B2B79DF9FFA1EAF75DD1D6D2467950F5CF500AD9A82D96DD5E57A0F58804CAE32A5C930861186C7B11C863E88381241E86D9A51027C9C0F3B0054280577DAE3B40DBB52E0AB7A095DE81E60BE82B1660243E165697583E184D9001BBDC48325B028A03487390C0AC2A92A068B18150796F3E83C68AF090AF9A94E1C689DE902152F4448385019C42353870045152E173341BDE4DBA80DF47C563619030985E2C8FD3E01CF394D167B887C2F36B20ADB1EC4639890A6898F533E943F501526AD6A9F3F0360B5A17CD9F4BC0587632FA3FE71BCE49FFEEED3FE2944719BC1A348E37F8C9019C845A5FB0FBC476A6C100E0F65B2AB65FDE9FF5C62958041A957E810B93EFAD0FF9E12ABD9EF722734CB2776D804827E25FEF0DB7649484200531B446E708B7E5AB04D0E1DEAE3B083AF6FB30E9CAB09EF68175D27BBC367727761E6D9DB4C5E7EF1763A87EE7170B3810A979416DABBC555575E68E2ED223CC439C179288A606ED954E966BB363A1BB573CC6BA47DC9CB7BFE9321F980934797E0048EC1D89F4F72F75E24CFF9696272676F8543966EB94CCB53556F48C39D0F91258B57E0102C639C42A2F9BF8192A501B5FFC9E81539A2037D665FD22AEA9AB3C3EBB145F300608A56D0E8DCA88E4BB4E6ECB369DC0B21D0184D3B521AA9DBC4662A62BED63A680765ED3376580B22DA21070E2CE3BE253196ECA0F529E4622BA38EEAB667C493036C3F60443FC66E66BEF81C8F3AF07AD1BB8F92635906E63ED7D729AE8C418C3BAF03EDA9F92EFE9ADD6CD60C48AB5E5572EC7A79A0B0DC3490DD6CB9328469ADAABE89D446413499990BAE998B9CADB0702B8FE8B31B1AFDE9B265C227AB51DE4DEB0E0725A3056535AFA030A6C4FD69CF3E7FFB77688F977000F53D72E7BFAEDF8DD2E0D094C3CD00E731E73F80D90B0AB43C73D9B76CA3DA5899CFB1585CD0A8A451A69493C9CC99D0F5854F0B67447797056BB45A1F8D54AD570807C1A565F641C549A8188CF9FC95E093FD2C3C38AF1A83E17B1A123327974C70DA2D93C9972B6F7AC02129854BB6F48220E54F56825FAE7589ACC1789B66043CE2F404722C8658BA6AB1E2C7D7C084EE72277AA3C4D3A63C5C70A5B4E04BB80CA349B986C6F682B0D135D500F21591CB5B80E24520259DA438CA7AA89CBC8163EBDB943BEE7BC01595EE10E04A417AAD2ECB5D175690C963796CB60AC1171C1088F8D0DF54E20A5F3C1C766FFA787D3A2630B5C4211245B06DC2EBFFE676CA11BB076E75BF6BCCC429E89AF37AF73743A72390029D5408AE64F86BCC8BB2BF42D5D9FD87B42B70EF4CD8EEECE8C926BFE6EAA2B45B9AAC6B94825866C82F356A8CD79CB9DDD31D28B32140A8AC2075AA7A9667A96AB40B51C56EA5BFC03DAB233E730F0A1D67C18090E40652D274FEAD480B4D2EC56A2C2BF7E9AB578A734F0362C68F6E990118EB4EB90D506BB26F0D8C60F1716EB1612082B58195DAA603AF74152A770AAC184F882C5982AAEAB725F84A5475163C26D4A93E92109231C3F68A667A6D07A98B6931C4221AFFCF7832D560D9D7CEC33BAEF5A5FCD13C6F313B295B703F5A83FC872C96F4EDF5D2F858AF1ADF9B3049D6F645610E39952132766626A49492DB13A65B726A35C1FE05D73BF32514019EFDDC7D720FD70BF182133B314B4429BCA9156AA152766C1817A41467CE4E62F730D354433BEA09F525E978F94CC61FF700DC46AC30B22FC046C6AEA4266E42E5A727803FCF7864A1205922478B9F4C0F99B41C12672B2FB0A3B8281A17B4AAF35FB7EBD274D8DDCBC1D32C480A1DFD0A61AC4C1AB24C5E1E3066088DF5D043C3014627B25F38A414674F2A5A0BF01DA22047D4877148EED809BE1FA5068A34826B68348C5D71BB6B56F0A30FD04A6F87DD3D1774167080736AB5C7C0F032FA9892CF4F0C809C7123EC0D6C50E08CDEF52DF61A84FBA1980AD74CE92A265DB74BFB28FA48919A3B81DC62764AE985D4BD7A3FB1F9CBE905B260D8A5CE2637F0D8B050DFA5B7154CDF384E84EDF3806B5EBA512400D56362924120774740E7D62F68034C0960F80511725F3897A3A92DAB5452F2B9C7285EB7F3244782CDDE6E25A5A1DD9FB80DE8CBC22D65D770C54CA5214E7FF7438F54F0F0F20108805C768C141662FB2C9EBA49969085634EA8F3ED1BE70E5E9A09F949ABD0DAC5201E3626163873886C7C213C6872701B961CE5BBFCBBC7B698CC40265F93EDA9ABFC3190ECE655F861EF9D228DAA2803A8221F76E95E7EE0BD316A6C8553E25B888A36A9507D94994C9139EADC5328B72C6BBD9A857F89AE9797BC37BB509F7F99B95D3B7B490A98FA16FA24E998F6837159B604590CB39DE6C4C903E047A09E50CAF04C382BF398519238F471E16F2DC64F9A627723C6DD1BEDED01632D29C3B1D205EBA3EDE33C08170251846C7D7CCB17DE8A053226B3AC4138E12C4A9E4F2D08521D72F39FE626D9691E53BF0AE49B38EECEAA0C6DCA7E5839F48644569F01C015BD1BDA449C1C33B78DDAA7C92078EDC353FC36C044561B2E859BBBEC22324D90A9AFBFE60673A5C8CD11181B435377BA34939FA0B1C3FB1D86B5D9000000000000000000000000000000000000060E131A212567109894C579974373CA0054ED5F7C373B7AEB810721C3D9CEFA02EB244EF6B17507300370ADB24AE0173C6D114C51E05F822A770318033C082B6502F70012283EDA2A9DC0A1381F145470E5D3729D201773D2AA63C18885A92C962BCD3628835391D70DC36273DFAA4966F65AD40EB51FB4B416A8D0B1DDF39CB932EC4503BEA23E3D9D3B4501DB426C6AD99C28D415FB565F62EB5C22BB043C8CAFC42EBD1C7190DD32A5B14B571644471453740C081F3E3305F9AE70A5BD505874382EC0F6E2188563E763BB8D1BB8B16587AE25A6252F51E4AD02D0483C4A6E8AA2849C44629CF4B7C6DD6A5FECDAB0F9B2F0B35E306C7532B64BD5A3CE67A0247D97024AAFE5CBC13E375AA69B8287BBA9DDC9AAAC2BCF41A71E373EE36B13DF9F829BBEE8F48802DD9E03BE42A5E290251BB130E0E2ABCC4E096DD0F264E5D29F8C2388A0C3010E78F2A03F5BA1BE13AA5E50F2BA67A031CE3F787754B8276EA1AF62BC5FB4DD9A9B9BB84217A37EB9FC7AAFB517337B30454200D6AAE491E50D5007EAC2150F60F640A5C4624CE6D8112119413731322BAD9762BCF72349EE38E2A41102BC5461D72033072A90E82D105E6FCDAED9C223A4142CD55920196D7B1B9278C84B67A2E35BDE3C9CEEBB8E9007BA8758BD35C875DD5FA0A8FDAAAA9A09629B9DF69AFAAB456E105DABF2AC5834B8D223B0A406E0D1295C876C447E8E09C93FB09ED1B3EF6E1F3B7FCB029F576A45A12620567E05F218BC3753109DD29AE0ADE1370C0F871AB5AD8A9DBAA277FB869EE552E8733E73886D6DFEACE6B35E481F37A516EBE191DAA6F83E4FF453CF9CC9DDEA8EE507AF0E62EF3CB8C22949CB828E21C6AAF3FA9AC301E2257B0A054FF0A237F527D53EB757820AF637FFC9F983A2B5AFF0B4CC493E610314432C9C2F0FF73C4240D520D1D73721B429CE41807B7424B14F5EB1CD23D5562263FE1D58CB1D52E5175414800CB090242E240C3A7ACAD4C84DBD8ABC2731FA2B1D9820DA60FDB6BAA7EA849B6A146E07AF7FC201B3A98E5194BB5826945FACA3690209E5726F070A71EE07AE76ADB7E6199FCCC81C8AF7A463633A58873B4F7E65F522FDA409979DE41CF54F659E66CD5950A3A3E01570526C46417A00EC2E8821DC380ABFA21384D141D259CBB9722F267E46272ADC5CC4BCE382B554226996F4A6A1605287276C18A48C8FF1A92ECD2815CA5452FD6157FC27532680022993535549BF9AB064052E6DB4E9F83B5D0D885B94A90F59E67B9DF0C321EB0F95AC07007E4EE33BA89AABEEEEA01FD1172ECA4E31FB02C507FFE43CD0D6C8570769A180E68A70BD344B4C992E7D3A6BFB96AC4D69C2D4F5EFACA1D348DC1988DE44B30DA76BABC307A88124F96F26737A85FE6047E7E485C7E4B6B99B575FAEDC9BACA3E080E2B074CFFCE1F716C6A1D08234C45706D2883C6E5A001D02596CFE5B260DE6134C75DF3AC8BCF1919759E15576CA147CEBE041D04E369BDE70CC64157AEDA311C8DA520EAE907C33E30DD89013E24B7B02E66C9F285BF7D5C3FD65BAE24AB20D40ADDB451AB4BC4B9772D0B9039461BCA8D3D2A4D71A2E6BFBE7F02325FD571FCAE1FB47F855612F382188A5FA3D61C3E8E59EF016DB0149C52E1C7DC84030E6C93C4F32DA6CE5F3B8196AFFDE834D2ADC26CFA05940055401891519386BCD33D85584D74B2F16D8E19556C272AEE8397A1741EFFC283DBAD317740C1B67F8F4B7D2D1EDD68D6615EAC3F8E3CD26AC4F8058667FB388B19C654711B5B2EDA75A9AB55174157CBE08C186A3D0963BB3011A9567BD499AD2A8 + +count = 39 +seed = 811A8A2ED2917CC616FAF246C5F9BB902E5FBF5430AB078AD6CE871CF8C160512A748216EFAB3A4CE1271AAFEA12C11B +mlen = 1320 +msg = 061934748C6758ECDEDDF3A2DF78574A470621496CE3F12E5E4555FEBCCC1A46A772FCBADEBA8B2EB5231B5B15DEDA5A38076C737E5D091A8CA8482F84EC4A20A51DDDA391088F2C3926F8E1D8B77DD0ABD606E9AC25A17A86A5C75ADC215C5030355C4A1B307C1CC80A3BC4A7D4B4044FD35D173A2C7C081318F707828A3438DABE0836C2D6C14E1643F05EF8405531D5594411AE4DAC6F3992279CAE379D7C1762B122037301D3FFE8EFD1BEB4E027E055527D485D0871F2013E7B25CC26531C2CA6DDB98B31F0AC2C3BDF400A0BAE942C9D4C4003F9952B67AF67E85F572EDC3345A84B6DC3CEBBAADB7E3C876AB2DA16ED0EACF4858033BF5A4F739F9E083A345C2BB5D8611DAE90D25AC45D8B3D39B4DE584CBEACCC6F5B6E61524349B50E818BB6B03C7E5B86795D49324CE6B1603791F20B3500A1B8ADE82359263470D777B35DBA38276096445842BA5D5E960FB2AB58730F970A15AA42D9737C33BE700127A7CE7CADE024D3ABCA59CA49F9A7EDF44DB62CCC07A595016868AA97A140178DC92530EFF864C24954464BA886DB7D74BE7B540BAAF807F1AEBD014680FF4A51E16E1391E32069EE823F3D23DB72244D657233578CB7D29A33E6EC31DF1FDD43B51742CC30EFC54BE83149177E7BCDE4450DCD142EB2CB745F8865DFD99DC84AB92750F1CFB0F3944E4E4EAA41261A1E8C58D9B230ADD792DCE20D2612823C0FF9F82E04B61E48DBB83F1A6DD5CC7F92BCD0A37AB3053803D1188029AA1FED9BA04F4C961588C9AD2BA7EF1CFBC50FA69B799898EB0DFE9668260CA5680F91A10D2BEF8F108AB28FCAB693ECDB942070D2B9B8BBB22609C8395C23D7482C31B69B0F555B7C079D3DEFAA5FB302ED92619C058ADF334E845EB1C6EDD903C0DE2AEDD3D9830943F8BCC5954B65DF37C901A17EF13FA75B0F2C8C1D2E38681874AEBFE90B463F2CC7831958FDC0DE0446991EB3C3612CC00188DFC1078FE458D2E5B80EFA7BFCE800C6B4CA0E570FA5858859633551DA28F36F1FF418A9B7AD18AA89B4612F9D676D5FD98BCE6F144CD7458CA9F2BC732A36A4D186EA290A009A870DA3C1F60617D56EA7554062367121F3E5E569503AA573B172C6278DDE5AA4CCDA79D9D8FAF41C6C9040C1D1D3CB78B41FFA8A0180395439F0D1B72E42471A9100973AB3BC7AEC559D94D2D6402374BA5A584DE168395A156324E1E4149ABD35C72AE0F79863CB59EE6BA22145E36E0D85D3CAF8A427D38C96CE489CD0AEA20D7960608C074CE3CD0494B6D6D5EC8895F0F03CE78982AD8FD6784BCF16825286C51325662F34726BA66D3A91EEB598124D6755DA090EF863FA31CCD5B08909A3279A35CFDCE24D2BA16F42AD280B029A0E27137A671C862B0E6F73FF4A1DE320C4DAFFB5CD4AC3522EF1C10E8A918005535F355CE6366B43A757938594366831DBF7EE72F311BE4953EDD1EA1C598960745D3DBB7F1E2D882CC063BC0791D18C6376A8497F2F91389A13AA96DAB78FECA081D761479848A5B4CC2E3D015F343B9000583E95E785A45A06842D7C6C0FE9AC4D70F085503D7AC954516953C497635AC8B7698BB784F73FE6E7F9D0AB9473E828168DF4EC142CC1FE18FA067525915ADF0764E44292A0316EF3C0A443683C92C4661409589EABD7B4DBD43F54317AE0E3D1C69C35A7868991FA0BC2F83430D89821B91A08DDC2D314A717F5BC6F3D89DAF163AF73E10C61630139E3FEDA723FEB2EDFFE6C7F364FBA22E6AAB75E267065B5E7575946C56265743816B2CF12A106AE21921E3E92BFB7FF80E105468F8409D6698E8660B5B05F3F4BB19A0BD4BE3569D24F51795752BE74C429AECA5BE737DE8C01 +pk = 33075B839A2C1E78A91A0DFBC761719C0260F609CFA5ED6C1735327F4D868D260927902EEC7D577C1BA733636D22FE673FC2B5463A9544946E22A1FBAF8E6F957EB2F5BE928467649C8F9180733C3477F3BCFFFAC7829053B014B37827D6481FE96EE6BD528A857C8026AC6D78C71AFB51FFF03E79D5A9797318134FBB44D817758EF4B573614085C670EF7156265664728DDA296B489405B47E483A92C7C62E0EA7210E7526AB412C8D7D3550664F0BF49191F14AFF5E6BE9EB6CD4E012ECF9B93A6986E4008A7FD5A07A8FBB3EE36AAA67475ADCFBCCC0836F469B5DDF4EBB3A0E049BC87EF571C57B5B13E919C7D144ED6051785F96BAE47A82E21AC6036690F94B43CCA8174FBBA712E9339D7634D998093C39DD5DFE0ECD8E3A4585BC04827B58A510784D1AC4A67287BBC436E63F73D63F2C7F25C96BF11925CD7C360C49B5A53CACEF8A465D84878B35790FA2A28A8F514BE4FA9268A6BA71656C8719F49827BD848B893801B64ECD6DE9CF573ABB876357E9A7718965262B0AA2158386FF486B492CDF7EB4988856D029CB829D4CADF1D920BD4936547E8D6B50A40BE066837834BF8778DF9CB96756D5A9B1C3ADEA35F99A7096B1A9FA61F6EA90879E1DB60A0EC5CAC06D3338CD416BE11AF473FCDBBBD90AA4340142BB64AA699B3F6FAF6B19EAAC4DE74956D495725BD0A05C5CDAF1AE7DC9AAC5D42155D6FE99F2391BBC009DD703EEEEE7C3EBA48A7613F02271615CAB6E48C721B5DAF7A32F90141BF1EA4632A5754200E1620BFAC21D35AE1DE5E6CFD70B428DC945C43DBCAA561C951480D24DF903D72B0C4983C83AF538E5D26973E23E9D715F0FF1E3C4EA64037B5DBEE20AE9E96A9EAC8DA793BD90D489E88D9C1A9A709D028AF2CB0B05E47E92444F7C891AD59A7C5B3D6F49EED46310E36C844B6C43BB11C5887A06C93A4D955A71B3EDD13BD9BADB415B6B38C61B180D738636DA8ECD822B6070DB2B8C2E7E523F732BEB02BBC97DAA1672A5A67D5BF1FEE017C3B78C9050BC7ADE13C580E4076D513DAA44A5E0ECA4F11FA2B7FE5568F9B06D1CEEB9022BECE717B1D341F1779094F0F1849643869D8C332A94E3EA94394371A466B56D5CF27DD08655749D64ACA1CF608CFEA8A3803FF1CCA2894411744B185935E63D7266783BCEAC46CBDCD926BC8589908BA49206F950B22AAFFAAB1EB6B82557B178190D15FFC5B0CF81C168FE354E30EBCC6C06690B5EE7505FAA23EE95E1DF1468CED057AF1A344CD253803471D82A26204616FE1A67FE7F692213478705287582B3AE851C7FF822B5E623361AFFBD8B528379626E3C8D6DC0DF6C1206526B34F12BFA885D2ED0519D9D30CEE91612D7504B7458FFA90B07639BC1BC7376D015DA378F5B19A887CBF37F9A73B940FAD60546D0B9696D5023DEF34B32C3F86070F71298E8DA9FEC98DF3309DAC09AF470E9665FDA91C1969ABE41EDA752FA0956945DBBA72206FC321164F9FEAE40663DB4F40028A38A50A812BC23EBC4BB362122EC2CAF587F6E1A8EBCF9413DC4276730E06AD2B58B4B44DBB3C69A7CE2E352F562BCFF940D4187E3A86AF861134EA0A9F82FD7971D0B8683925BCE9769B60DD2E4C58A4C176B6BBAC20F8E7CE18586E78A554CE218E6BC4B543854C319662CEE661E2B2404C40339DD63EF3FC3B61F22B8B573692E281397EB11855BA0CDD52C63563FDC8702CDD573B98A678B62FBFE929D07A547DDA41A44552FDD2B19BC884279610E92A6ECC88D6E45EEEC929DE275C58A295FE0686FC6D142FB6D206B39CA6306601B1F4067587B408137A5BD08C37AD748B0731B810E8688DC682416B01387F629A6BF677EAA99376A08C493F2837FB02E04CD87097C919C54A9C29FC727483DC8B2627567F277C84A2842ED2F92B5916626EFF0561527F0460345E58EBAF2915A2E867EC8669FF03E6D7603E05AF453058F6DBCF9F6DFB6ED913C9A4312F92CD6162EC87FE0F0650AFEE055E99B5B163B8E983B6D21FDA89AD30B1219D6F6CC43DFDADA298DFB6A046465C9BEBDBB7921C3353D854C4F461FB07BA8A4C8CE2F7A530E3237BFACCA7EA755A111EE0988999F4D2BF4DAA9A370C5EE20BE72C3B1851B63B58E0CF7A9108E9B5415D021675DD8B81206B60D20110C7C640CE6719FFD4FD2AFAEAC0FEED321986EF9F393EB62EA5A1D8228A22B2B35372F29C0B133DD3B89732D5F1D1C43EBD916FAF387BB2765E7DB5F8FADC69400B581237FD3AAC066F931238823C70B65FA9081CC84EA5F97218D910AF1EFCB993A8C6A09BE3AFC3898884CFB29FC033A28B875ECC204C57E564EBA8B3500B9A72369A5F7037A4B49E78D88F668FDC8CA9BCEB4CA0088A9FFF21838E093938514CE0BAE6A25A88DDE0352CCEA7D61AFC2A4A005CE3A8F1FE73D591F1016155FD8C51BA31A0C236E9534093AE303AA7EAD0C408C590593213B1F7976398D36FA5DD7FBF09F024D3A292B66D19939F877F6CAAF8BE5F1D8EA5A7F0BA78111187267637B93180BF27BAAD6B3430661D67C7C1DFE68341F8E484C3C24AAD03A5F4856824B05855004D89F35C02311EDB19FE8ECFBAF9161EE6ABB52F6DF1EAB61BD7F02E7D6C464DD907A81FE82BEE603CB93EEAA8E78941569F492F0CD5C3650D80C799832BF16467C34710664B9A260D1CE4849EBDB111F296B3CD2D6E28DDA06AC458AC6FAF5F72D8B67873BB9D33337DF9062F0252CBCF1DEBA75F3C04A7B36CF73960E3E2D36 +sk = 33075B839A2C1E78A91A0DFBC761719C0260F609CFA5ED6C1735327F4D868D2661BFFBAD3291F072086A65F671D4ECAE6C263521BFB17556FF57C34EA549A905BF38AD4513B194DDBB716C7FCD7A06E241A8E9F80B784CCA6B1C2CC144D6C2FE07D6C2AA8B9FF79432693F4ED8F64B5C1E71D88A09775D008B9367347543478575052644748850132765273403355488174352750888138341187301161877035133632156837115771671384820344220757670670511487424036045820570524655407244454187778834645822314553304876861628723658805307038803288801208663261212247000412233767221728388770376702263532867081423742388773156451564651560303702071881638080224105516235728605813176612032340577363664047780722746616111754610088727527328151512464624867067321413741022083165700758176705236414328713122550334605107077480686110661032024716842027634357355306660601374884375113183615466245125746082123254210477057817456570330488405656650504782842781617735440237457141030140854156533140400638712346337512243566643006743812338487430748806800455740235710313303046465276857354786148664473663877225266764506263421744158021370823347552833851087020064538531072115865420871334658580234622378313473116547870575744810041517744654031130412613518765666847788113660215268728505703215324522407477522530260344186388118044266642407430873727427286584023422657355401800163030760488586372548634873373774018706727354853310684222345502448826257350484548781738886178365147020071355321060605272622846303765634060871388818048833214830488084316520810867577214500071446553566061370644283078505387158176421436432414807656118670786862301480721618605782375836065236782714766502837567522704163355700330164015156002632426415124345136140617348570571756284072072544665087712084645647514230832118064726530570778045165666686826131160061620145375457076312822856886808746410215233188744145653601477367118364280664270345350788380005824626363654231650754628628686185532686737851821870262821461761724016071502310630320455373820328822865531741621271788435520373845434670723100164006564547018114508165771840446235784168774186162010024685008175651711664351210602781331526712020187723835533834280230032673787310146512484812126313641851074574235055406105287338572188744177446377540435046332561561641827645343367887808003221405784125253873444308564477174635168610442541662331684738414636133554276005710411433046302824800054515878571276847813523086414176040428803888832500464170134264217841715057465520837054665036844384683104325584628662054172540270343872628711202158567100287316044277515872757340410543610706565478243711357463080476380682827417433851625527341668274531041084841815817380743004522625834870255173311344110025330035627780635046382642381502733007212526720577070113547726371104365060203743458371732666216708560165270662687525666784284008627573467750627403700606417405042202725520040081137651017483120501558306602126131703050573510708337642101510447454376613712260511607375277626771468351707382258325776736841170773782684844851108231267382218076683108847372805562284484164753335650238025140778001162365580384084613115040484551438054280543056766070684611877017670735822640027876230334043353448531107561761248207458602EDC7FF602D35400C8E49C425FBA2CEA879DD6CC0F33686DF0E8125B06C74C4E61355E3CE2C4F2151810417A1F39C34E3548DC8A6FE42917503D4FCCFBAD0E0BADD2CD8C16AFEEB666F54E64D91C8B4A69C28FFA51764ABF41E5793E10785DBAA60CCB51CA12199BA73750E122A594FBD9ADF548472A3957180F1613761BF7E5A8074577BDC85AE8D247C7B1571D0ACC28024F42708FD2E2839F40164CA78557BAED712EE1EE0AEBC3582FEB87E166A21B3849FFC709DF51586E5FFB0B0836902E94209BEAE60EACE7BB36F131E8E0249CC388917A59D75BC6AEF53060524F2FD44FE0D4CF7D07629F366D4C04F1501D4E1C189A3837F67C995A7E2F26F29C9A8B2E0DE6ABC78A2A8B16AE1754CDA11A9390583771CDF3DFA8E4300E519AD1BE7C0F195BD56F0A90D36086DBB7064A5803D5036D815E43378298415B78ECA7F5961789BEBA22041344EE191B4C1EC245C0B5B735B2C45E2D59B21B9556FB94491ED406991A61EDD3DDECCCB41DF17621504E48A51853398457CE7D875925CD06473A377DF30CA4178BFC2383FF130284E88F73CA068998B76EBF5D715F4448F58AC1E42F2E7214277B6FA7F7E54C04A2AE9F31609FE4AC2E81BB5A842331079BD3B58887D3BC6982950DAEFBC795D801361A550FE8AF5ED19CC9326479B1D455B8831AE7DFEB2DBA0254DB5A7BEE68AE516CA856A53EC1A3575B0B1470ACEE424515D8D2DF2818128099A5D0C44D878BA03FC6E60E411903F4EE04865A850A575FBF1331739275FD5CC1AF6263765B713F2D547C8005F8C72C62940EB217C88145DB8D36BF3B650578ED5378DC74DE32CA41FD495D2E5C92FAE1B4B186542A389821DD90186B865D0A090305A6E8F03130E2D42BEEB239F8892421A2BEAFA521AEDA65DAAAD1E5B9734F41EE5BCD231C7433EF8317A9F7627EAD4DA7E9B2DDD984BDB1841C817121449C2EDB6205748A9D5ABDB678F91B9F445443F9932204D6DB7B7BB7E5A389802EC52B5D4956EE44CA8344CE49595D2F6F0040CCFC19FC81554EE050352EA35E643E21D1AC1C526CAED98E92B7CF07E6E0F02C8FBCF8FCB47FA2056557171BE17F09F9099DB363643544A3A95C5A73778C2E07EA3FE21E276F83D788453F03E04E863DDDF5BCC278659383A309A9A10FAECB421113244A35A50D5D4948AEBB776BA76374680429D55FFD70872C4F68726C25FD16E4715DE6DA7FC0BD9E90509C6ECE96572A7DD3C28EB203A882022C7852DD69341CAFDFBDC5DE6AE6CB669FA344E2F4E191B07A41765AB30073270912B4E4303A873A0AE4FCCE7026979DD5FBF9D6F456893CB3C85AA1F798A3F8D58E40BCA256235806DFB84FC881DA922050BEC4F01011ABDC6200A1A53785E396C7CF502B7DCAC64026A901B4C986CC41311CDAEB8CDFEB87E51AD52D939F7F884947DF1D6E7A44B8011DB1730B0A1B447D4266406A32E714B3BE9ED04EDD867C515246164B5FD4F9B066D1A8EA01A782E616E3714E226EA6B2D7E07FFEC4F3DBADAD828071BE9739EE09CB3DFC150383DC1C6D731C7DFEDB70C16399542C17BD87068298C8C08983B2E4357A267619275562FCD095149DCF5E4DD0BD79FD55B138711472FBCAEF3F997CB4B1517DFE9E4F554B08275ABE584D7BAD4219E55B62FEDE7734958E8429007344E07D9A3A052E9576B99E44F022E6480078701F8FC5DF5E8D409CB92C571CFCA7FD077C6EFF719871E0DC85EA8CEFE995AA3755A0854F7EDBE64B7B512BAC3CD5AA624ACAFE4544857DB82ADE27C70CE007D1F7AD02948395C8C22B279E141142C95A30107A05F87D9E7088537C4C5ABF4D331986420F0239D121ED43BAEE0854439598E1D56134A88107E7BA76F36CE2A180E9893E99EADBA68919E5512B7BC57A5A7B129BC2DE664001618C8985124A9426EEE10CE6D79539927F6035D47B20758EB2F94B34AB72FE4165E0294018ADBDBAFA8B17E7D8B8A24C1CEF04CA8749C4EC55D4FE2B57BCCCB602F3E2F36DE732F3E756F21CF33AC027A202C45F9EAD3B49A7C7772B4930A942471D8902EEF727A6A2130065942D995B7161B0BA05F899FE10BE163544AA9A94FDAF6343C13C0AE5D3C6E77D8F0F30A879153ACDC9C1512EED071F228170B54B35AB8E00099D6B488871C885F9F517F2608F99DB1971CE16E09EB9909238B659646963195079A36C2956E98B45E99DFB8B2ADD80F81A9051B49BAD7A4D5A15889DC5CB318A4B52F1FB8AA5778F3226F2DA07B1820072CF410459EEA22A582957750BB6DC967AD32ABE4B164B402968BC70CEF4AE20B709D6F0C252601BBC865011F8DD0149735C6C3238B925E5BA31ADB64365CDC9910EA1D5F85D0B2C5A60B5F537E3BF58C645D92E948BD1DB15B6B65DBF729F6FC1A9175466B028DA6921D8E4EB9DF613787E36AA130A08FE58378F5DC467546AEB8A0656BDE3F0C2DDD56BE2283D3135189D9FFF4AE11C48C5C301AFED3CB5D670E4398B68DD74097F134C7A90FEFD1D017B3D5FC0BE7116E52718FF0B5E94D841C5C5ED01E37C5F210A732B5DF69C3B6313B00D2542DE095D4B1DDD24FF7AB13407FC9E4C7CE5245E08E7EC03DE5EF15BE4CD1EA37EE8801BC108E597D0EC3F69D3B9C028BADD43631B96E31BE4D3E631F9868DDB610E0F3A1E8BA68430CFBDD8A934A29C54D13D4CE8480C65CCE357B3FD523A8A89F4BC1C300C4086DD376B72F5F595B1B0D364255FBFAD4E826910896BC4FEFD567B31B2DE1FBA557A23A3BD73B57EF0DD94C7F42BF9B23C40130B4688C328104A42051A589D0E9A51A77B00F8CE80D2E1B02EA2DFC4B44C6EEA44407C6136B069CA52A95162438E05113D2DCA1E027DC3036382F5585FD49EECCA232ADAC171D60DC8A3124A3821EA7C018C12C93EA8BC4089A8A676BBCB52B5C69FDBEE2226B80625CD8FC849527BCB7D2553EE06F4EC9FADC984ABBB009AAFEA1FE118226D489A531C2C72A662FBA7B9C9AA358693C3ACE2498C9F2F2E897BB7EF8FCF3D35CB97833927B75461F835F4FB2D0E22984AD771D75184BC4E3FAE2204B21F2237BABBC521064BD675E49D26A2B8C81A5921918D4C79CBFD8ED3BC6D70DE29B3DA606777A5292B960FF01DBF0BA75E00056AA9CDEBC841A91FB677B885D424E04B7E8E4A9DEFF7A84C366C02212EC963D8BE123554A259F47AD49E74D6FFBC188223F45D19AE929DBD37DBA6E33DA3A847D9FE8173FB49B25875F8B738B16259C733D991A1982661B7D31C4DC4A7C2D1CA0AF8DCA26CD8B63800FC54EA47B0349EB42504A52AAD697DECB35120C12EE1B14E9BCD9FB36DF3373EADB144C8ADA50BBB8A7CAB3313D7FB2640E7B8B2EA1F836A18D0F1100CB373201400CE75AE76F7086D1CFF5EBC78C4F36CFFBDED6F07BA6A73B9DE447C844776213A697501613E7DFDCA984BC06117555947ACDD2B195C026720F204F9D2144C75BBEA76536B92425F73F820A9F5DE5A6679FA69AA50D939157BEDD533A616D81CF375FF9F4E2B56BF443ACF082ED3DC +smlen = 4629 +sm = 523433DD8648B0DD7272E3666C457CD635B7E51FB01BACEB26F264D4B1592D491232906CC3BF70DA55171918183DC64FC2C6296AB9265C8127DB5DD6E16AA3A8F28007359FAAB8C025C44C56A3A51CE5399BAD3007A6EE380B1998F712A6C7CB5FC739E7E9DE600578AE2F6D8C21B70DB83642BC10D6387DE9AAE36A8BD5DC434241FDFCA0974EBAE00F83447D7E0B1780A6B210C62FF55E7DB0B9E14A3C58B7F19F9EDDB382D4AFAE045B0CFDC89D09DCAF7373925CDEE318CE42EC8B6FD3350C7A024975F7562BED801227625E41DF03CA0C5F5C34029ABA7BE44B0724D63CA64D6341E431CD1DDB81E77C1E4FA72F7E90A77FC52A28F7D601CC5DED31D874B6F160309C9CBEB4E8AB12F72B69A14F3E089BC352F1F959380D754D2BFBDBB36DF7DF46443D40A1E27ADE7DD2B57826D2EAF4B7D5A14B5DC88D98AC7E177183664C5760082EEB7AC2E5598C2D2F06772E5DAA31BF8C75EEA68F1D01A3952605B4A41BCCA58AA418BD5C65A4D26C996B007C698719477C37CC4B2A2261456794F0E36ACDD1DF3EE5698AB21BFBC0E781B8CCDC0953538F3A4FEFE4363CBC2AFA9C181FCDF4B06E4236B531FE525C008B1BE42C4E1117F9079D49850089495E10C2670A0AED18E512A17D6E2D661458E6AE81461615006DBF3CF713A93D6987C953ED962ACCBB0A83D0359B576EBD52FAA41123FB578F74332AF33D263BE0620099417CB6C8F4DCD9A4BD4F1A1E90725E0F6E375AFB31178D2D1195BA9CF7EB503CD50CD0B3FC3D2A2E5311FF304BED09F686F6192096662220B34BC40E41F0E344A734B29AA92C555E841195FBA9B7FFC4CDF8795976760FF801947144C6BF63E97FD4DC239EF15468AF155FBD710D2FF55E1DEA85555AD580E58CB9A7AAF509B39198A7398D6C3FC7AA421EA51E9794557B13B1E5B028E30B6F88F3B5477DFCB86C05F675670BB6E63F0F4EDD1B0A96239A71510EB2B6628C8458E95F5714BD0699B99D0B3C3593165FF7D762701AC61C4DD17D8064B27059C9AA7240285CDF43D1EDEEA5BB480CE92340B139FA20FD99A18AA2231884958D3DDF8F0CC613413BC4468FA33A79E94FB22D417C6452AC3A422F42609CBD39F7DD9B93CD6D9B814E6237A32715E3E83AC9AC7F7B8D1772F811F9DD75BCC66B6EA7A1841534070B909B3B4A78D7610B51307F4417E5222E6A3019885D111F0DCF55E86AFE6A05AB82FA50AADF1AB70447E91CC8EEB2DF783AFA8CF1FD54A8A378CF8B061F51862438B7335A2E9273120645C32CDAAEAD10A4660D39859F2A92700C6E0E19EF3BB688AC1B206555304A73F83306C2DD854214F8C62C6DF63213BD03EA398999ACE74015DFCF4999779C9F4E50D32E776916B4BB9229E6ACFE7F89F9F9A2F77522D1C0FE8C2E52DF2AAA6B2ECADAE15EC7ECAB50F602FE80A102F1B95530FC77E6DC5310F6684B88A97F2F68C31AB636959BC275F8593FB95DFE7C87DC8A7D70358701CBF5DDD63AA751F07A003EEF02CAFF3D12215E39146B94AEFC61DCDF404C065DC61C0604AFE74241B61F5BCF51FF57169CA5B2B351011DC5F6C76B3B3EB83FC39244E71981F9D204508461935B371711BF20240F904223B025C2DE9863A24111017805CA1006A874BF8A8B60149C39C3ED4DE01FF10515B247138A952B39D77D9F93F27FEFEE0D6BE4D1B6C9C9A19C97EAC72E5B32B8FAB9F40382564529EA1B2DA383CE55416025B621393EAD24224803BDB64ADDF184F48A7FF594507EC0AACBE54478CA4D582FDDCFC3FB21A7AED66C362953956C14FFD6CF996941F7F203403351D0AE8900B5A21516DAC7164196AB015BB11CFE0CDCE3F351519A3B946BE5E41109F8911C8F7B72339301532A89C0588FCC72205E342C7DF4AB1975DA3A6AE2FF73D7E15997CD4FCAF06436081058621BEC968C6C8EAEB19A1507D078F38F2B014F973F45FCD477B2AA417B92CC0B4354E55100FF34F40C3620155E0C6AA697C3B8AAE9BE0038E476A955BCC3BF149CDE7F12071D573ADA05EDC739943F65108000571F64ED45842E3439BE98D553199DD4E985E947DF6EF41AFF87D8BE7C92409BBBFDFCC0E281F18776E37D145F4608AAD4B01FB28EB426542BC4CC36A5BBE46038793ADC41DF0889E83F533B93ADAD062075C0141062BE99147E1DBCDE5315CF46B8C97A828EEB7641443D97E889412FBB4CF638709955E2E8C76BBCCF00DC04A3E9E91394E3136AA626579D1B79E5101D3848FC8B89BC33A5925183D8A3DDA4284D523CE96ADE54339160EA1767CEA4422FCA68861836C3B05829342BD6BC14DFFED6B37CE15B2F0C86863A200D7437C989EFDC7A276E6692D659B2C0DD9C21D8407B162E15EEDCA95E78B6EC66D5F3267BCE7F9AC112770F562FF691B91F4C2166B83E6F2C276458DD7748837984845CDE13EAA1208A193E5E0483C8999E9B35C1BB693B0CEACC900CCCC63EEA993746772B25A91DF3531B726AE3227E91AA948B89A7E3D9CFB328B4FC53D249349735DC87207D15F3E14A2AF13ADA2B3DD989CD38D4342E8128C09725AECE636521B9DAC0B219E944FB312D11A9CAD4938BAF7FD8B95917F21FD4992068198CBAEB0B519A43710E75197278D80F3D4233567CBA8B0295EDA3158CB8D5BFEA6E6D58D48ACB58025C1CD2F526D27B068AD13C32DC6DD83B4ABD9B327EB89653730C5712EA082DF148AF13EB3A4AC96CBFA6D21EC12CF9038A6832502D17DE5FF4251C4A720D71835546268E88CD72F7F0CA28616851FD748959AD2D338973C4394A3CCE0543A6DF1CBA20E88A8A22B5CAC60ED38BCA51F836C3DAC29B109C711181EB5E874057205502B85C01733E6F8DFE8639F5F6F1FAE703BBF682A601116500282C61ACDD1EDB4BCC99C435FE06BE8EC77DE47106ACFF92FCCABE684EFEE4E395B136E8A8A6C166B956A5CC1C773EAB9891D7EDE5820FF9A3B7C733D426274052180688D775D223F73B7A9A528F4732A1EF70F62193AB0501634D04CD424838FF769331EEC7F1A41BF326B30FF7AC2DB1E7AA9FAFDA707DA0D3398A99928473437AA53B5E55D941639CCB887BB3DC162C72CEE4D0666904AFB879B4736985FD274E2FCD08503D4CEA5F23EF028BF697031F1AAA4EED9080A156E97B4A02BC01E209F016F9BFE639828B9EEF174B0395CD5D2143995B0312AD725AC26C8C269AE36E6338D8BBE5EB410D15D66F73B5A59958730F0F7A3638965F0FF9809C5B97466761E93974ADECF4D61501D52651EBB8B7259C8DA0CD3220C9316B6FD3C65B716D357D5E2F1C95BDA74406D323873DF11B1827BCC7E2D9FBF483A46554547EBB64A17EAF483BF59F872EC3F5544BF356F417C251E129FAA4C4D7F9E0A13A05ED687085FA0963910404A11B67319A38A4D1F48CF1D28DF02923A19653BDA0C15D84CA6057C247C758F685F9260C7142EDDC1384FE5AD9CF15B17BE8EAB32D8CC7ABBF1014403593BA1CBBF1EA39669A3CA7DCDE1EF520146B265F68A7A3AD79CB9BE3E33C00ADDF9C2C6FA9D26499F35B1A4A0564B0D0F06BF07B8E8E5B034EF1792EC5BDBF9192A0E84871BF2D216ADEB56BB7C166FAF9BA1D502427B9DCB9B6569D4E55EE9EA9C175F37B0D2DB017F4960AFCA2D11E6173E9A44FCA70667E16873D9BC08CBA917FB1EC9A2C39F6FBCF27DDDBE298971273C575715334B94D4056C9028DE82C28DA4C6BDE3C2E108B071A870C83F5B4FB9C0BC05E9753934BE824F88E5845A01E090F2C9BBD5A79B48694767D9B80CA6AFCB610ED03A560BA547ED3B2368C828F9B88E5F2A2E7B8B339ABA1DE280C90FBA546EA5AF3C9F44CA5C1FFEF035EE1B895335566D1DE9194ABF7E6BFF11B6E8C102EE0C6D5C2105DF8758B0E0508C8F4DE3F4BE3DCAA1C7723CE075C9006C3EFB9B2434CE072871CE4B1F12500C02DEF6AFE61247733B354C606AC743BE34C33B937C03EECB01B237D42B99686D7D8B304085CDD987B2BA7F916A375D4F6BBF72A22D2FC1D837B2C22BFD69F0705A437EF8CE3F4808CAD4ED5144B3B51EF3C95D8ADD1F3D69F331DF00F1671AFAB6BE559668A13D0D0B6B4B806CD6B7CEBA7D637E238CD37DB21519576F527D4976E96FF0FCC956944960AB7810054E708485C945B2026B791179BD3F3C647CEAA5F2467C40CB3CE7BD07BE47A17349DDE3AC7DDC2BD9B34EC3CC09D1CA1C0BFAF9E954D311BC2307F56418247B689FE5180A4C9942A277344417CFA40EF8E6B33A0270B71807DE943987D1469864347FB7D1C3F812BB816C364DD3648C1715D8068FC9034F840E4DD5092DF85B097492F9404AAEABC32A4E718EB241AA35E548B4C162433D56D8350636BCD6D8D3D8FA648050B8D04C0DC0CE4DE9DC447DC8ABC06ECB48FE56D585DD7750C77AC4B8B924A306821BE523063260311A7A838E2B1092CBD7601B3B5DB2A6DF2C5F9BB100F7145CA1B70C313D95CBA8A463B069586025C66767F7255CA09AF8CCC1626CA5AA26D4B4C3EB34405C16F0C986C39578AAD204EEF27F765DF2F5E57D5FD86A946BFDADCE1F7F4F7CBA8F16B06380BBECBA4DDDC84D2ADB4079583EF884DBE0163ACEF24738C520C246AB2BFEC2851CB62F94856648A92AFD0E10910161942B1DAE1E5326E79AEB0BDBFDAE100000000000000000000000000000000000006090B131C25061934748C6758ECDEDDF3A2DF78574A470621496CE3F12E5E4555FEBCCC1A46A772FCBADEBA8B2EB5231B5B15DEDA5A38076C737E5D091A8CA8482F84EC4A20A51DDDA391088F2C3926F8E1D8B77DD0ABD606E9AC25A17A86A5C75ADC215C5030355C4A1B307C1CC80A3BC4A7D4B4044FD35D173A2C7C081318F707828A3438DABE0836C2D6C14E1643F05EF8405531D5594411AE4DAC6F3992279CAE379D7C1762B122037301D3FFE8EFD1BEB4E027E055527D485D0871F2013E7B25CC26531C2CA6DDB98B31F0AC2C3BDF400A0BAE942C9D4C4003F9952B67AF67E85F572EDC3345A84B6DC3CEBBAADB7E3C876AB2DA16ED0EACF4858033BF5A4F739F9E083A345C2BB5D8611DAE90D25AC45D8B3D39B4DE584CBEACCC6F5B6E61524349B50E818BB6B03C7E5B86795D49324CE6B1603791F20B3500A1B8ADE82359263470D777B35DBA38276096445842BA5D5E960FB2AB58730F970A15AA42D9737C33BE700127A7CE7CADE024D3ABCA59CA49F9A7EDF44DB62CCC07A595016868AA97A140178DC92530EFF864C24954464BA886DB7D74BE7B540BAAF807F1AEBD014680FF4A51E16E1391E32069EE823F3D23DB72244D657233578CB7D29A33E6EC31DF1FDD43B51742CC30EFC54BE83149177E7BCDE4450DCD142EB2CB745F8865DFD99DC84AB92750F1CFB0F3944E4E4EAA41261A1E8C58D9B230ADD792DCE20D2612823C0FF9F82E04B61E48DBB83F1A6DD5CC7F92BCD0A37AB3053803D1188029AA1FED9BA04F4C961588C9AD2BA7EF1CFBC50FA69B799898EB0DFE9668260CA5680F91A10D2BEF8F108AB28FCAB693ECDB942070D2B9B8BBB22609C8395C23D7482C31B69B0F555B7C079D3DEFAA5FB302ED92619C058ADF334E845EB1C6EDD903C0DE2AEDD3D9830943F8BCC5954B65DF37C901A17EF13FA75B0F2C8C1D2E38681874AEBFE90B463F2CC7831958FDC0DE0446991EB3C3612CC00188DFC1078FE458D2E5B80EFA7BFCE800C6B4CA0E570FA5858859633551DA28F36F1FF418A9B7AD18AA89B4612F9D676D5FD98BCE6F144CD7458CA9F2BC732A36A4D186EA290A009A870DA3C1F60617D56EA7554062367121F3E5E569503AA573B172C6278DDE5AA4CCDA79D9D8FAF41C6C9040C1D1D3CB78B41FFA8A0180395439F0D1B72E42471A9100973AB3BC7AEC559D94D2D6402374BA5A584DE168395A156324E1E4149ABD35C72AE0F79863CB59EE6BA22145E36E0D85D3CAF8A427D38C96CE489CD0AEA20D7960608C074CE3CD0494B6D6D5EC8895F0F03CE78982AD8FD6784BCF16825286C51325662F34726BA66D3A91EEB598124D6755DA090EF863FA31CCD5B08909A3279A35CFDCE24D2BA16F42AD280B029A0E27137A671C862B0E6F73FF4A1DE320C4DAFFB5CD4AC3522EF1C10E8A918005535F355CE6366B43A757938594366831DBF7EE72F311BE4953EDD1EA1C598960745D3DBB7F1E2D882CC063BC0791D18C6376A8497F2F91389A13AA96DAB78FECA081D761479848A5B4CC2E3D015F343B9000583E95E785A45A06842D7C6C0FE9AC4D70F085503D7AC954516953C497635AC8B7698BB784F73FE6E7F9D0AB9473E828168DF4EC142CC1FE18FA067525915ADF0764E44292A0316EF3C0A443683C92C4661409589EABD7B4DBD43F54317AE0E3D1C69C35A7868991FA0BC2F83430D89821B91A08DDC2D314A717F5BC6F3D89DAF163AF73E10C61630139E3FEDA723FEB2EDFFE6C7F364FBA22E6AAB75E267065B5E7575946C56265743816B2CF12A106AE21921E3E92BFB7FF80E105468F8409D6698E8660B5B05F3F4BB19A0BD4BE3569D24F51795752BE74C429AECA5BE737DE8C01 + +count = 40 +seed = 41CC9DB2E90239AB5158A2628E7478D0B3512FDF84CD27A4CA5FE3119A455C22045F198C3C5C39F491FB975BD1CFF7F8 +mlen = 1353 +msg = AE2638D944822298959F47B2173DE7D1E58AAA622296AD4A4CB67EC7EAD8220AC2F171605BA2D08AF3D6FF5849566EAF96209E9E00CC28EB9A517CF5061545AAD24CCE143A2EE1AB7CFA259AD9C01860B33B0036F2CB3A5086861212F408C5F055D226CCC77CC884452B2670D89548EC1C6E98FB311DF03979CABF725E78956AF185447287BCA2517F554E9F25E19D93790318EFC5D2602FABF262E5C7FC307E5A991E0122E332A803AC4A91B318B30D79394248521190D2BE326037A89FE918D139F763DC8DAA2C3BBCE53F04809F0D97303F2F1B88B572B3086ACAF38EEF36B4C0791B4918204B0E1E923BCE9E3BB1E7BAA07135B176E266AF174D5DF26C44842CEAC4AE4C1CFF05557DA3DB8651261BE78D766699B1891CB825FA9A418C45BB9F7F2D347F3F92F9529CA6DB94E2FFCC69337FB3690F556C5A44CBBD9D79F60AFF063DE68B14BD2F4B7E8CDF94F6C2F40219D27F71E8AB3D4D6872A5D4B82EAF8E3943A6D425ED04FBC5C7596AE929AD680B245E3D6A7C5CCD7FDFA1D14EF0F72B9BAAEF05B7B84ADC02913DDBC76D5FE80DE30527FFAD1825CCBA34F8587C5B0291471D6957AD99C5FBCF3669B4AE5930C8AF68305C2D3E84E714CB9049A9560A3C94AEB95A252F69B68F755DC0E0AAB52DD054B670A275BD2BAD7FF8EC0CDE6224E9A0EB537E95DAB992C382D6B03FA045DA402CE7C5B55138FB400D9E86AFE30923AFEE82C4528D1B38CE16D33BEB47A96C18428D919BA98C9782806D6F4A40B52F7F0989337C724BE24E9A5430CFEA470D02EA36CA479FAEAD94A74049898D1F1BE53D5AB8CC0CDD5438A7C55827131DE264AECD18E5F5F2F9FD60E8D2D6F55BEB27EB77AEEAC2A15432A5F1467483BE6073243D0165A6C242FE1BD7B7AA701A0827F286ECB51E4C2626DCBE95466BC94A7E2A09AB334FEE3959CA31974B6286E2A2051653341623CF3ACA65637DF657280B6025DB0C0377EC09E6E32010F0F59711A30496695D23728319DFD0AB5F3AA69025276E68808130659D912A53693584188E310B1CACC41AF4B19FAD8DA95D4B35E2569053F553A9DFCBB8FDEE1455DFA0E4F5E94324C86A24288AE27F3576AE15FBC8BED49BFD8521D77A61FB523BADF0E3CEE53799016C6EE4E1E5DEFC19C7717A5C41ED8FA6BF0E5811BAEA76676DE03767A607735C2A48BEDE511012EAF1F79E4D2C3566042FF2C63BB82FBB399CE20E1F268D3844BB473AD7366EF86D064C5BA080FC0C01BDD2AD343C5367D80D2A058CF40725268CD34123C219D9109780335611B008EE3F8848EA9D174D7B96BD2FD9A04FA2B550DCF0B301D64C0764299D317DCD0CA05718A1AC008D86FEA330095E81567E83BDE31A0D635098D7B86176CE6CC4025E8628C73B394D9A45B09B64BFD3A424162B16E1ADAA1AB60006847C6D5CA5733237A330147CFE6B9170D7B88834BB79F1FDDEFCC0EBB1D4FEF326E28C41C919607BF12AD112807BF8582933DDB096F1F3E2BCD6BCBD844DA317CEA2A7688A5FBBA14D84C537814EC2B171ADE28ACF83EA481631B968C26F8D2BF2C5AF7D61A93378E1E23FC756E2F0EE79199475AB4BA1FBC55D9ADC2B05888B2910049BCA98DEFEFE96CDCB67CA9D4AA5BBFC6CA0ECBB78BF29035D158DE2A1708D98BEB85C70AD1C64B39B387516073E2FE85BD9EFA25CB048C224E0EF76547DCA67FD66485A97EB5E56C06C78FFA08EC1C9C6F2380912A2585CBCBA2CD702CD2B51022F63EC920412989BD743A8A8BEB07241E3E8EB38CA14CD400C83DBFA6FC8E04F58529007A1477E9613291AF877692E4CA9AE118A1902AE7B4AE7DC2E992A6495CD19DF32CE64131A8D8C41969A8BAE1D870DD5F1360BA9278D5B76E746FAF99D526199E87A4B1D3A5C48A33989F103CFB2 +pk = 44D264AF1665C1E9BEF951D110A6F3C5C61999639D068406C03365249A0A716C285145200E88CA53E0DD31104A1F40BA3F28BEA8B39595B3746E81C520E6095F2CE27B393332F745B13C6D8036059A033537127AD9F09272E1D725CE406B41C35C5FA5FF039C36F7B152DE58E31674BB7233D1AE09B11381251A153A89E1B1DE950E0DB92B2A414740C0728B5FD8849945AE746264764309A02407617821FFCB16B7CDF3FB5CA2C89083AE294221700F9A4AC38369B667045893ABD305FC0D17950C54A0377995448DE98432C1258C3C6B41D1C5F9A7C842E41A886D0B42BD21A33C127911552B4FC4EF3CFFAB0CA688421D7BF067F4C889235C3AC97C60F0ABB798C935725892D43A9766B8A3B0D721ACD7F3A8C8DD0CBEAA2449967200CE7DE22D686AD901234100E243C01A581891B4A7E03EDC016F4322F7440E2FC3DBCB72C59CDEDDE834535BD7D51CD0D710B285A7F53D822B7B7BE7671B01FD52F23FB9868D9DAB1655C548B10ED58DFC467EC81815F6476A9DBCEC2853C1AB54E5312D0C2BF7C2670AFE5C75E9797417A2BCB417662D8F0E1AAA81130787C5439382030B6EAEBC6F0A0788A24AE685AF80A3E940DD203DC2A98BC0B4893456BEB6E5D8DA64D4142BEE1E079D5110F0B9726F953D027A991CE1010658D00F7C1E648A0082845142FF242AC5E634FE706B3A035FBCFB324C43E866B8668C45AB8B90283562367E6484EB4A65985231B80C2E8F1B4DC3C9140F5EA613C08F2FECAE0622376BD4B2984216893827A4AC806EDD5F49BBB5958B93581ED49B8BBD6E455066E2DBC1532BEA30A9A22173ABD117E01C0E0F493BAA01540968559E8D97E651DDDBBD33A7062B45CB718E596C1A0ED714FDD9337F2E9DB80310AE072E7590EBC3062BB6F8F880FF49AD357E727D7A220409FDD33BE3AB733985AACBC9301F207D2FE5F7BBDD7F3AF1388E0FBB70C55645BD73FF0A6383DF545265E29ECFA08F96CFEB6B51BBDCE736187EA8359D15302D0E666B8D30E3D48AC253EFD4837D306BF95ACF4FEAD7BEDA13A2F007FFAD63143A523C4998D77E34583FC8B24FF80EFD8C29BA0DF95EEC2D1906BF4DEF74F98DF1DF8E2D93DE0F4F2DCA253BBCDB1E6B15365640C4F6098D8CC8C3A67580AA71D64C30F05D1B8DCD5D100B4196F4AAB93D7E1138B96245F7AD7D0EC491CD1BDBCBD9B96FEAF715071E54F319ABF0CD3F477649ABF400D4A53F9C74232EE32B0FF766DF7CAEACE5AEF47E93D6C5EC8B11415D4E2E885E47F13F1C2E8826B03C966AA12B5881350D070F60C8887319249E3265201248F5B4FFB066530F927393608D876D235125B9760C345A75F060EA9992237BC55D51FB4292727B08D2BB1339915D431CD22BCEF3DA67FD95E04A711A43E7C86253A4EE17DA2C7313C293E5316CBDE9BD9A31E37FF4352DF9DC474443143132202BA0239537C3C495E4645B850C510268E3724B762DF752C0D1FC2D6E38873CF2237807FBAA797303CC503117FE7F361F50BB959E89B35867B5E36A64FD59D2E3553E0C4E02D76E351FADF810AB3B46F2DCEE385FFFDC1CE25CFFBC995D3A48EB4F0EABE18AC75AFB38C6ECDC03BBA3E474784E037FDD045EE69A613CE7436F08596EFF9D59293F04567A5C46DD1A88085FE9A13038400FD07F60D62459C2D599D46D7F1B06843A9264BF8DCA9D1C3F50756EAF4261945334CA5F1A326F1D78B0B77486F619AAEF3F49723AC7EBFFEA718587B2017C026BE8852B7450AC3DC244319F6C7EE16E38BD4A532E650467428B3278AACC3498CCA7012406EF1FFA66D4A8B5879DD02A4BBB267021B9F17C053A07D782291F5BF3FA746D173E15DF32A67808A724D2E63AA96F9F87CB657F6C36501D00628890EFD6246770B6CC74731D705792DF40A018E1515C31EC53FF9E607431A069E3312BE183E03202ACBF27A8020D61AEEFE78DECBFD0167665AA4300C3BC4208B4C6832C500BEF9E5623512F1CCB8F4C2AA3566BA1241F9081130A4856E42AB62C7CCBA01A4D50BB4697ABD371E2F11F8C314CE6B6B63D71D738DFC449DF561307622B30864EC44F69ECA0E6C9390616C66EAFD420273B821C4B10747A755234A6B1B26EFDEF81D5F4A72EAED9FDB5A90CB097EFE32A40B72AC180FA047C3451220378B2A1FBDD820D3B316593975870E161222B609FD330F5C5E046058AAA5C6FEF5F54B7898EDAD5DA268458B0BFA7F6ABD71D0B3F464210E88E574EC164DB716CAEAEB45862D052E51918020B527375F7B7D40A3A9BCEB9F24983BF9F3A35CC5975A54853659CC5C7F0CDD0ECBE9349BA65E2779E73FD5347304BECD8D1F5FB2A93A291288E838B30EC2B8A3CCCEAE5F01455372C47290BE090F0925D3FE0D99A1731646914CCE7D856C7F8035ED86F4C4D11548AAAC6A9462BE7D6CE5262CA155ECD6F5AD48D1A6AD23A2F0524BB7595EDF3ADF497E283241F1F5BFE8281DA0E4D2CCA122D8105779E45AC71F3848301FA76B61D171B735777DB4EB4E472768765B399ED5AAD6C1384E372542F5A1C89410A6680F35A71C1485A7B1D754F19BEB87703943952AB3AB7F1CF9421F916E5443880928D8C510C631C1498D26CC88E475D3C2A2EF2BA130AB24CCCA574102E9710BEDA657612FFF01F9D0887FC93BF4F9F54F0FAAFDBBDA2C6B7E425337A6CD2F90948C8D9FDBCF723526A530E741A8D3BCFACDD7D69A6FB9B6D10D1A04F5D41639AFB66B62E4536DDA873DB818A1C564ADD93C1CB +sk = 44D264AF1665C1E9BEF951D110A6F3C5C61999639D068406C03365249A0A716C73CCCE299B19175A97B305DD81730D85FEAF4C1F30E328B1192503B42085A3B64C09824506B97D533EE4CAE2E54868940682EE07270359C7BD991D7F76FF5DB8ECFF3DF5E05AE32FE793DE89A28FFDF4ED78CC55DF1C4A67742F40B069453B8132247641174427600264637333385814555621236360614130377234517381762808012844121264834126314230150222580682051438762426466514307804167287808135765683363358554010812826768045285227674180105863103727450551145612135030637151580434012654465082321522112554767433317153171023783161425668170867753010233036354880382446703250535430170648242585518815146630612665004308373425460801114754113733581268667672025116710555486760884860218557606524862385317633732766344437630874864204363425512128743687350832586324876820060410602183535083623712267075426484667328543741818375185231115861601043606562074132784025686454148030682423324131088362321661154622138754861638423434415052114731200386840673158087350736700764720621727578766616378466038221032152520555848625053476051236378278134157134321565201238561867505827725241316531537616624122273232711565538345432754074643027611845166375706361206217158424063176015211676687683127806218381637212733275501144622222742173187461850226557107421364610721256583001774277574658120051568453884810143658478205044006512148170536881177075862757247837333078733407216535442146766541248755728305158253081267070171371688816305013158457661270780180782831662142714582352031872605067861554201658123174731332437471438258486483143052710346168801626137187701013242208282002233500841011454803815570307848685750576477817880674436667340765110863821211752546430627757573235675008064560607052005056584484380302610821264807373615346871762742215787125054768865507352217038363757243343430202021302851755423103050377014652664645311752671636283545201024452255418832544388062563154048737817604846180663646255816600855202277810281112437562282816302177625267657144787127350540056114300342256103686547573560672871231277808044686640141416178732464428851356802644488065054104527231232313636276102774423208114640087662754561161387005052780346638058755553245573722487311863850012418153505816871862705701563210838102488850650256376068802038333207675060881780181115244453012064028528077333377782306008773733460580550551612171175677704517733328817302630430076283572126766151838773462617561580841354187502445202376510756723786547457811874753174746786031555486667241384131712816578431470310363763217658464155843542417234802582861216167480885868382048265727205603436476361608741653657221633152787847325206153248284368242523653407354400288438572517128367518865587176507302242011680535776375520815825023182675652024568658050024172623237071358181408422036038627471476456546682368884640721753337261081767816703541771758634800680701575234514364147441223152158301330767610747047605822571686238244856475352044753536107654343740403058738646742055270853737558386274360524362645471634203547205145070853403557581626777306573137578025153517740287152531215172764140031834573160656772173750825771865642648820103011424840241641738715183153630420886525805340B1C4F98405E7B53118E089C3D2F801E0A406F06305109845C6BB90AAEEB288D705D747BCD9DBFFB98DD3A3CA350CD043946C8F79AD87DED5922608DF8FE2CC2EBB4188F84670563457A10AB54C9FC87944155381A0E50A027DF17355B158784DD4DDED1DF9860018C838EA529FDBB3A33E749D4D04713F569E49F49E466C4CDBC35426A72F173D919C1810F8BCC0AADEC72E941E8D3873157D405239E96250708C5F267301E2F9487D6FDBBF14648F96B545F9D095999324B26BF34D675ABCFA5C4DCDDA7374BCA155642116E70BA832E5D34A537882A028FE39514B084D982DE31C2A5021811C531B3C14F72F793CE867B7493C4D40DE1F8DE1E654F34146A19C0E67584A2808BD092415140BA19A40E3CBC6975653B6502A82BCE09720A31FC09C3516285BCD97BA2115E865701A2C7E66B16B64BC25E032D3755A976F731608A096EBEF0E1CDDD3DD27620E37EDEE95820BE54BC6FEBF2FE6F2EA5E45367E6EB85C00D916B49A5C21EEE29FB99FF17077B50AD2706D616988B1B43992AB608A31D43306205F34BC809D26F0EAD6403BF33ED9ECA8EAEB39F45451F79902E58DEE1DF54932981A0192131EFD9DD366843CDA7B6784A62A7B2358A6C572DAB5D89C42D2EAC89BBC433D658F0CE90765E0DD968F24A415293117040A7873C7856884E8879D202B837713CB9B3E3E6890E8D07CF3DEABEAFC1F3704E5DEDE04A410C6A5B819FE8DD7BB65E038492A4CC8065E395F3465C78FAA55007B6AC51CC3BE6F09AB7E6D03F6791816C63D9D6687FEC1504146AA2F4CDEEC1B053F36FFAD2AEA8C809884A56A9D1B92D7F7163E84453D87DE48E38AFBD2D7A46E3A5C755A52820BD5BF8AB30BCF0C119BB5D7D1C78254CB73C82F8B132341CC2E5A816DA69FE6226EC2B108527B94F134C7750F53335C5E65CEAF8350AF3D8AE33D21C626D563699C419E5E70B8579B30323F84C0E8CF39CFAAF6BAA3342B61280BE16F6064A66CD1DC12D9F7CC9F08F6BB357315BBE86F06523514654F121AEEFBDF117E8817029A3D3A9EEB7D98492D055A96B022948ADB4D0C3825E5801C44940653125C68840FACF1B500EAA5D3994F9B7380B98CD3A19BC33901F9822A11A273DF3C2E65932C9B21F2A7BA163337E01F4059DACD8A37684008A8977048CEDBAAB72B73EC0B065EE2F1217796D6DAE33133E4DF263EE3115F7EB8A5BE38210204AB0525BEC89C591718208D2645948FA2F2CA0ECDFD6A179A9A013D9EAAA55C1AD61AC84003205FF7FB8B2FDD3946DD737189D3BDE335EAAF045D5831D284D8677BBC44C76CC9156A19D446F61D63D0F914AC62B0E1095C3BFA5996ED28A97E23E29D7F6D04D681CF5AC125568233B01B912C3BB58201A149F74865228C3FD4544787B4F8A7D87965618D487277807E7F85357745EEB4DB9ED171F264EAB25913C22A2F613B30442291E1B71A43907B93995039740A7BF949621789A15B4DE50446D9D04655A0507D3C2ECB5B3CA4E7E448B0E043A6D05B73C9D2D0332DD8415399E7BE166E16D6EFBAD51599F18B303FB565E5BE1CAB5E59AFF82F7A5BB01CD4BD6F6BC7629669FDF68FF0C59525AD02E0C781FC57FD94666ACB94D8042256FD4781E0770439DC473576AF884C31BE12A3F907FE09D5D73618CDC57B1ABEAD37A10AFE88DC4611A50FC5E3BEEA43D381705B53A767A5054A70EC0EF15FF236C15464F2D9FC39E583073322836E200FBDA1E153A9FB19236262BBD237ACD5CE69082DE4FBFFD7D686755E82E469C46ABAAF68A1805BC023D07C440ED51BAE250C22F0F6806486078CFD055A509CDE4AA65836344439C4B17510EED2A70501C1440ABE2B37F082180230ED9F1F8B7A5EB04B6F30658C6C7D66980375BC8FCA8645BF1BAA3E2C91FB2FE9C78ABE897F49CE5596A4289ADD4BD712102387A238BC4CDAA0D8C2F7938EBC49BCA26C8A93B39D7E9AF4E76E178FBA1F4AFFE51A61C7C21235459E9415E7BFC092155A4161568830798362DDADE42C26C9D6D6FAB6657514E6286AB9DFCCD5C65BF491FA2D09A0F2ED2565A02F01A8D4B7297EAB5108B0982DFD64F9D9BA7D7CA1EC989AC5091272E93A4F5E84F5D31913387DC9DC9DCE999C16FB05A09754C685EAEA305E84ECE5F62A777891877EDC9C5FCD625461539CE35F999A51080F4A47229A3F13A0B680AC42C7D0957090332DACF5ECFB9421A23FC1F1672332FFFD345DB05F8CF6FC529CF915007D740F65187EE9495924B726CCE6AA3BB65DF7C3903108F4885137172348B7ED3E607AA57BA6FCDF0A868A5A3B1F4DE19561291642CF2CC342E77B7B5BD4E0240418E1C03051BE970167CBA88216F9AB7675CAF79A0E1DD4C245152F4669C496BEA0E3E47F20F4A36FB578208D425F6E477617033F7588DD1222A2B2F23EDDA56FD10DB2381DB4F066284270C63A0AA3DA4B39EA7E3CCE0E95EAB317ECB84839B280F63E3C0179732C930FC6CD10D6D88B09291DFB6D1CCD61357104126B5A11652F81BFEB773FCCBCA986000B7368E5B254574B749DF99D3098AB4DF502753546AB8903728584B0864D5980A3FC1D4EE2656E2B732561446BB06CA4E527C2AFB949A7B7A98D3402C0C1558F7149D524F45171630137375E94E21F6DE6447E6D1778F3039BDCA5D74714EAAB55CE348419CB81A9F0AAF4EDD889FC06499B30CE4D563F3D9A2C74ED3729A8837AFAED27FC8A2DF0C9ABC9E708A4C6DE781B003D177AE94183D850FF892B30CA0031FCA9CC08BB6A9C50A4615227A017D0602875235A16BEAE86CA2F005191C51228FF8A2A2AFBDC86A7DAC8EC76C2C911FBA958B228DDDBD3A8C89C80C1CA7E024E0FA0A2AE17FD802A224A708E2350E10CB017F06F01FC7E09310E741EEDBB9DFA5ABA3941873101632B29CD3F6997C35B9F9633D2BE919209A94E47B373735FC32222D81986DC6EE97C27269649526FE9335DE725C80D44BE1B628C5F047A859CACCA8D421FDBC7A8DB7038CB85417C238B9814C5CCD93BD4969FC208689F185E687BE8F0969F26582F85E7FDB55645EF51D0979A4CE22BE56FE6FE33C0FC4548788B965EE80BFC22487577C536683B598AB374AF4BB8AC136CF8455C2FDD0C92C17AECB3315FE98A2E53CE1A36570528DACAA97FC89987C8BA9595672748D52C9526A0CA9C01EF8012F7F23858785E416E73594F2C02AE399909D3AB1BDEC8CE4DCF67B86DCBA753D49D32CED478C5B03DD7FC34710B5151BA275CA94F4F661C445B40C8D6AA5E24307127B141DF427DBE4A49B279E1270824B00864E1C8689E91507A5A4018B37F009A54B7C0E2F899C2D6B3FE688A8EB83E75694487512D1E78114DD049C2D7F6537A053E4EEF1A5EA2FBD6FFE81794DA28EACF51CEB672111A16713B96DE48C750574A49A4B718AAAEF6524B5E2462BF81BDE0365ACCFD66D24106DE00EE8336C69DBB99D75CC6C330FBAB74EC9068BDCBCEA3D651FE9FE4D5FC76C31CA032E5E3088BBBBD0297131D8AD6B3C52300341109991861D +smlen = 4662 +sm = 2237A6BC1CCF8A34BF30184019728ABFDBBA4EF8CA37E578B50E4C12DE815E1EA6259B822114F287BBB70AAE7EC9D0FC0F540FEC26C6AAD041899E58DDFE73A698D81256C02F0419FF2CB7A17838D700573604079A972641851E3ABAB6E2F499531282E4C7B54ACF72E29A5B5777B7E7A97DFD5876E23DE32E37D5E8263A45E450503D69F78CDB68F64BB78035133B8BA3EDB203335B3CE1FDBA797D629141ACACFEC322C24BDC36FEDBD2FFE39F0A05C6C39CA796B667625ECBE531F50603785028F0D65A1A23230FEB26CC7F49A94EF8DDDC8333927F21EE8C745C31EA40200BF58E863BD8D8B4F9B32D6D39045E31488BE71412A3E507E9C1D5AFD38179F074E07A86E56538FFF108ADD6BCA1F2D15BB5037527647A62FCB16522DF67735D25E7C4DEDB11DF987BD9D466888BE19C7F9E3364F744D02B4DD168C3EC97D93EA13CAF193EE95D47FF200927630429085423836BEF6395A97E168CEB00E029CF9119F8E5AA5C6421D687B8A6460D49453EC9392258E1F6D17E345FF6786D03EC3343B13DAFC7D5E6FBB4494382D2E613DCB6CE659FAD82F6002C4664C996661CE130312658F45DE8A75DD65AA11E17812225C1CFC88A9CDAA22E5722392E0EA41F464972B87226E4FF8E2768FF6ADD70EFB4F3E6A2988CF6789D547B0BC732A43A7B626774E50BE60864716B65DFD9F568B022382844C53067506BF8098AC04143F1CEF4E3F6FBFA4492C8ABF18B995D77652FE3930316EF4224AEE523387D1A5C9A87FBD765BAF1C8A9EF6AAF28425D3D7304A8D816FDED72CA9944F2BCD53BDF67A8E475D0263FFC26C71D189E040ACE452277B787F264202B2307290ADCC4E6B7C76EE238EEB2905BFE306446E6923C6F23EF88D04F59F3EB0CB9301C4C6C6A74579B01290FD2B985D225C40DEE97A413BCFD8E76746E954040E43CBDB728188E2C10EA8DC76A59E54EFF04D1A3FC1084830E48105FAE914C7ADAB1503A6850DCCCB8FB55DD4FA2F59FEAD3E2E5CC3F9CFE0CA2F4B92FA06B003B22E17C189B1EBD24462D328D6472CDFF3C0FC0AE9EF838E9957637909128A859F0E9FEAA7A25DCAC405EFCBEA2FA4339F5977AFE8D4AF68B92C31CD3DAFC660A7D97C1FC0F851D5E638EBF5C7C179393674D74C4D55E3522DC995E57E1B8AA55E78EBAAA82304AB27DB418E0C44BA5BE58C7A427B83F3EA9B15ECBE2C7303E3D400FD0780726E70392255BC04F2C44F4224E7ED60B80E6050AFF72A47EE4CAF2FD0D0765EA6835B3A771A39E241AB2AE0C2DE09D3459B62E642357D8B71144D9294E5AE3EA6EE6B8788C8D3BBF8180D43FA320532780F242E33FA75B7949BBE14738E845CBC9D4EDD940C60015675CB70ABD58C95ECB0A84531515CECEB0FB31E49B63DBF33074DBF711B4EC18B200FBD3D924FA6E4CDC407A48221444F72009F70EE7D34AF09B29308129E66D24BE6BFCCA7804CCDC9409DF9B8A9561736FC2F505A4FC4E95D05F88F2EDEDC38B78055B806021ACAD4541F93DD362FF17404C52B8E877989879189AD8219B59EB0292AFF20071BF31C46A362C5699952E44D8C402849125F6DEA3BBDBB6CE13872655D141AEA7426B64F301B48CFD8243A8FB4719DE5B6037BF25EEEFA8EA3DB35F1C70E5CAF0AD9702030D20CC476670E0FB2FAF33DA4A1EC80F2B64FA9F03D8B6A5ACD8E3F2D0660CB569F3BA91F48E61BAFDC6865328DCC3075A06D679F8E9C007730C08CB559F5F0A063FF5287A241D3C764573A3BE8F1273D2A60E246D7A40F40794567C850A25EA5FED1999C44E86DE455B60269D4610317A6049CBC5DC0332202F6E6F86D51C034FEB9A60081D0B23BB06976D6375FF263E3E1515EDBF901DB55E0B9D0CDCE4AFCC185A9B84DA7456731CFC2DD5E9A77E6ACD893AB5A0E8191E59F6FABC3DDE75C9BAA95FEB971E2AA638B202338DFA30B457E98E2103B89F904D3C31F32470383D8B2CAAD0DC6149C873A5AE47C0D2E4AD150AD929186CA2AF4D0DDF962D52672686F75C9B38EE0C347FC9D44E044A072A87A848FE97B04D79471D8F58CCA0F9F210B7B45DB35BDC99C35FB9069C4735A4B616FA2427A48BD1E0ED2D85870B2F0BE4F1CC5784443533705F1DE6AF1FF6E8D51DF87D0887FA7895616ADB7D90653FFC3B2B6053427304767E2254B8549028E9BF70953EEF9D732966EE78B9038D8B7638B001441AA4964EDB8D91CDC1AB02D201B0F7AA8DF359D6FF02633816C00624AB8BCCA795DB9C14AD13BCA4351D511E630BA7E42CB3334FFF20F1D7D6DCCD497BED9A819031F557915F73100882353A64E6656720214B7D01E8D30AABBA7207D7A9C8CD9B31DC559EB8DCC650154344DFA8F4A2C8891BB753EF827805183F30DF33F8A54E53B85785FF2EA1E66B4F747BB3EAD6D39FE2E1394BAE3FF2EC38B157847B5195165D8B347B3698728190776B6FC69F30782920E8A9C2D6238E9F4B555699657C9EF9B2CB44B1D204D62761E0D45C8E836CB3D2ABD7B6D09109914B147004B9E301C516E9D5C8C8CDAF6428B679EEAEC46A0CF084660D3B1E1B50DDC8100C5B9BCC920685AF78112F0F114A7123787FEB13CB68949B5C1AF1779AB417F4A79BD6E92D734680BE0D777FE40967A01487C537111504DC10A375330AD0E33267DE75A669130B6667E28283172816448E15F7DE400A579533CC2A60142F43E8749DA9186F63CBCAFB9785443EF9C460C28E24B2A5AE468B353FFD5F6EA4927E7DDC381FE7B7EE052C95F22C4E1AAE6850BED1F645DA0CC0DA43A7A33DDCD931D0D81E66C4CEF44388EFDB75C749F9D8215BE5716BDE6BDAADE2E40F6F34C41358E16298507BC28149B515DB67E72F1D02A4721540E0A3DD702A480D4D807007F9CDBAE0B50E4D9DA7330BCC41F7EB003C77B44BD761F9F802A5B2124D191A30D66E10E3A0CCB2857DE7090FAFA2CF8CCBAF7367CBEC6B6D09EB3391767817A2F440464A7E0B607674D594ECFB08E62940715535233EEB2C68DE0B87A9B4BDED4E886C7D5C6F0CC183016EF8351F32BCAA937BAEAB5149A8A0D75C2FB523CC936160303270CD4F11017A2C714615D410CA472BE7605BB941111D32C36AD7895B93B6C9DB669AC887D2E1721D2B9E7E1483EC51B33A9E1C2EC3E421C37CE9190734C9A166A7741D604B0E4E5F94C86311D225E9FD01619B9B352F4A48B1FD1571E704F77870C51520A9BF3B2473DC30B0A55F6D2AB9BF264BF2A8935E97A2CA3FF65F7AB034584E649CFE60B25DAC6985105AB7158002BC006DA9096D7634FF24AD5E83D626302E2C09E7AE86601C456146997239BA397A1A0A3558C246C0757766C3B8860FAE6E21A13297C61B9F6006BF71DE1723D891BB2A1F6546FE07ACFE436609BD43AC3EFDB20F029FB45345CFD088DCE155211A3990D6557AB954E01F7A4A75F537D24305D8A91C3D3932408928C4AA2218F8610E509DA43D70BE77FE66C2C2B3142FE8E4D1F50F8D3C8822E852826D84A7B7145F3BBABBEE172A123A09F0F90D7C5F1E2711F1C8963C4D20BDDF71A01DB023C3AD1A70A4540E5D4E730239B05CA2FD2E6B0EF5A32B45E0D9A988E83A26B95AA561A0D6B539592D9941A96699163F7DCA06DC387DC6C91F7B6E974A8DB6FBD813AAB1AEF2D287AEA7D6BB29CB055EB464129E6FA674A7EAE2C884C3F87A4C3E5915071089D49D1B424B1383B923E6125BE339759379536AA95541D9F12E1114B5EB7086ED784FB1E62A1ACE60A4B24E3996C598F4D5DA6E1FDA7CB590FB1701B715EB2316233D58437360EBA9FCF20501BFAFC7682519A2A69F17A658D044EB360C1D3296C6B04F570F3B557D6E54EF2C163F73EEA1120794DCB7CED61053FE40B5EE997E48F6FE743DB4D61BD2C2013B6E3060A36F917378BB117D8290EE76F4519C712365009A7377B7CB415B7064F5A8C043DBD9FFCDF9132A55EA9862F498B659C7008D4068BAB4965A4223A6F2653B30916532699044F128E6BC583E40BEDD90DE064819E327FA84F3AF43B0A2CB5D408ABC452B4B924995D3414892E43FA38495321F3079A6555B58CD998D8FF2C4821BD83D25A462CEDBC7E1F40005986F87AC4D6918C7873364E660691EC1F5E2DC78A0FFF83CAB972F7E3A88C442805F1E4360EE6F585B5CE229049435A6CA7EDF79E1A1B40ACA6835C9D64483D18875820617DCD5359264E56E5F2785CF652B121C055181EE896297032C0547321A792F213514CFC5111C241BF2D92755B92B707E1E9DEFA1A617CEC4949442A7B3A228A8DDC8FC7255F9BD6EDF5F84CFBB2E4CF8C4323BB528C7ABF4DAF4635282C4A8C9E9C929F7A94C4DE7D7A64E0EFCE4F1CDB693E43C004D1CAD8B613112288CA61178B4EB1BE913972FDFE7243A25A2D2582E4D02238B3693DD1F35899B3D1C7ADA4D328F0F9E9E893FB88D549586B1E35E6951FC45D57AE97850B3142F46C193865CE8581BDAB0789ABA70050BC7C0A0F249485C1D174CCB70C3ACC1BEC12D69FBEC725148B240A3E8A703E23042684C66C7E2A4A84022E477DDEE7E492B215EFBA9753579DE812520663E5769CE3F3344FE0A604367B8A3CE748C512A24A7092F4385AA2C456DAFBBBF161E7B878EA51E38B7C0C1D91E2F486D7BC4D5E11A3250A5C8FB000000000000000000000000000000000000050B11171F25AE2638D944822298959F47B2173DE7D1E58AAA622296AD4A4CB67EC7EAD8220AC2F171605BA2D08AF3D6FF5849566EAF96209E9E00CC28EB9A517CF5061545AAD24CCE143A2EE1AB7CFA259AD9C01860B33B0036F2CB3A5086861212F408C5F055D226CCC77CC884452B2670D89548EC1C6E98FB311DF03979CABF725E78956AF185447287BCA2517F554E9F25E19D93790318EFC5D2602FABF262E5C7FC307E5A991E0122E332A803AC4A91B318B30D79394248521190D2BE326037A89FE918D139F763DC8DAA2C3BBCE53F04809F0D97303F2F1B88B572B3086ACAF38EEF36B4C0791B4918204B0E1E923BCE9E3BB1E7BAA07135B176E266AF174D5DF26C44842CEAC4AE4C1CFF05557DA3DB8651261BE78D766699B1891CB825FA9A418C45BB9F7F2D347F3F92F9529CA6DB94E2FFCC69337FB3690F556C5A44CBBD9D79F60AFF063DE68B14BD2F4B7E8CDF94F6C2F40219D27F71E8AB3D4D6872A5D4B82EAF8E3943A6D425ED04FBC5C7596AE929AD680B245E3D6A7C5CCD7FDFA1D14EF0F72B9BAAEF05B7B84ADC02913DDBC76D5FE80DE30527FFAD1825CCBA34F8587C5B0291471D6957AD99C5FBCF3669B4AE5930C8AF68305C2D3E84E714CB9049A9560A3C94AEB95A252F69B68F755DC0E0AAB52DD054B670A275BD2BAD7FF8EC0CDE6224E9A0EB537E95DAB992C382D6B03FA045DA402CE7C5B55138FB400D9E86AFE30923AFEE82C4528D1B38CE16D33BEB47A96C18428D919BA98C9782806D6F4A40B52F7F0989337C724BE24E9A5430CFEA470D02EA36CA479FAEAD94A74049898D1F1BE53D5AB8CC0CDD5438A7C55827131DE264AECD18E5F5F2F9FD60E8D2D6F55BEB27EB77AEEAC2A15432A5F1467483BE6073243D0165A6C242FE1BD7B7AA701A0827F286ECB51E4C2626DCBE95466BC94A7E2A09AB334FEE3959CA31974B6286E2A2051653341623CF3ACA65637DF657280B6025DB0C0377EC09E6E32010F0F59711A30496695D23728319DFD0AB5F3AA69025276E68808130659D912A53693584188E310B1CACC41AF4B19FAD8DA95D4B35E2569053F553A9DFCBB8FDEE1455DFA0E4F5E94324C86A24288AE27F3576AE15FBC8BED49BFD8521D77A61FB523BADF0E3CEE53799016C6EE4E1E5DEFC19C7717A5C41ED8FA6BF0E5811BAEA76676DE03767A607735C2A48BEDE511012EAF1F79E4D2C3566042FF2C63BB82FBB399CE20E1F268D3844BB473AD7366EF86D064C5BA080FC0C01BDD2AD343C5367D80D2A058CF40725268CD34123C219D9109780335611B008EE3F8848EA9D174D7B96BD2FD9A04FA2B550DCF0B301D64C0764299D317DCD0CA05718A1AC008D86FEA330095E81567E83BDE31A0D635098D7B86176CE6CC4025E8628C73B394D9A45B09B64BFD3A424162B16E1ADAA1AB60006847C6D5CA5733237A330147CFE6B9170D7B88834BB79F1FDDEFCC0EBB1D4FEF326E28C41C919607BF12AD112807BF8582933DDB096F1F3E2BCD6BCBD844DA317CEA2A7688A5FBBA14D84C537814EC2B171ADE28ACF83EA481631B968C26F8D2BF2C5AF7D61A93378E1E23FC756E2F0EE79199475AB4BA1FBC55D9ADC2B05888B2910049BCA98DEFEFE96CDCB67CA9D4AA5BBFC6CA0ECBB78BF29035D158DE2A1708D98BEB85C70AD1C64B39B387516073E2FE85BD9EFA25CB048C224E0EF76547DCA67FD66485A97EB5E56C06C78FFA08EC1C9C6F2380912A2585CBCBA2CD702CD2B51022F63EC920412989BD743A8A8BEB07241E3E8EB38CA14CD400C83DBFA6FC8E04F58529007A1477E9613291AF877692E4CA9AE118A1902AE7B4AE7DC2E992A6495CD19DF32CE64131A8D8C41969A8BAE1D870DD5F1360BA9278D5B76E746FAF99D526199E87A4B1D3A5C48A33989F103CFB2 + +count = 41 +seed = 1C13369824A3FDD41B1065E17297574715D9BD9CE5BB733D36D22C31B62BB1033989A604D78BFB1A0746BD4A2271FC0C +mlen = 1386 +msg = 9D84E1DD28C513987D5587A4427853762B7D7AF668FF9EC2E90211D6CF5C0DE6C7E54B298C1A6C67EA9A693CEDC4FCA1A6ADC2C6DD0E5BBCEE7266B9C6AC8FA8AF5E50078A6151F938161F1FEACDE4D8079B5A9D563423258CF3AE9E47D8E75740314F2FFA63865A8B30743F773A53E1AEDEAC45CAAE01993B75C8116FB0B431631AC001AA8BD02E5B83DE627AF0CCB3A3D86F66A7E5FB658F9226DF31095780A6E8262A247D70F4E7C971D108567FFBD7FED0E16B7FFDDD93F5764C3E02A61998C32146564D46589538B2E071AF86A26321A3523354F4F0C396B863FC8E9E2E3A173901D0D178A9D2828D0E0974B72CEDFB17937D6054F185A81D4F853787E6C3681A74FE25FAA6C256A9F9E9A9253F98B9AE4B8FA0068DC28BC7E8D5785CFAD20F7DDD643DAE6A2DDB02713C9CAFC2EB2FD18EFDECED05CC24913061BDC38E932DB5E8181FC0D3DE26A94E2138800B3C01E07E83B3B0BE187EDC75DA576AF1CC7B7122367EFFD6EBF05F4C2EEB0AB6E9F91201A4237910A87DE9FEF777981D48FBA28AB8D64D76380911F2A6621335DFA96B331AE8B3242EA1F2A260260244196B0B9596C411218A17D0A58D3B5735B9AD7B6259655CF6E2D0FE5B37D0A0B02E67951F5D3FB277B6E1EC87528B08229AB0EBD895CBA2D075A47CC8100E9DD17DE7D951BF0A68D710AAC21C8226D8CA95AC49FCBE9D493A8D3C7F93FA61685BE57FF422FAD036304F317A3DBCFEE7A4610C8C1DDAA79E37C19D6414F47230E01EF1CD5C7C2FFC319A29AE6A9C95B06C603F2CFC1D1FC914B036CDA6CF9A876946983B06123C2E5C7D09BC190647CDC0512F35DB9E214C77D3D7D0234C3F2590941236A367700F9C04D3AFB949DCA2067571BF28E78ED35FC026BD801C4AFEE9BF31C97580953950D2E81EE6426E78D6F8134ED19707473F0874367C86C9BE170BE63405A9BF7C46A420724B6CCFF9C21B015E21BB02C5A7AEABCA873B46571530DE56E47288C3424DA398517ABB6502A9A6A65D4983D97E479941C44CF0136D225991226F70837E2A7D1E9CB1226F40BF59D52C66549BF8E360096954F5875C466160A0C75A252E5FE6B8F1841FE210BF08520CE74D77B69692086EF50BB64732F19D1A49E5800F077700553290635D418168A6B9E3AE980112AFB9D58A18B94F972845C309E86FEC7E456191D8760A1C2106036E44C5C9A5F2CFBC67D741E8E937E99ED7820AB0787E39C385356EF0F05CD3E31C44115A8892224197B1D1F554D5098B72058FAD49C665F716A266CB4DB6204666E1DC07B6CFDE0EA00345661E0F94A5025D2EC98483CF482058D2EDDB018CEC11D91EB46B63971AB29367DB46137CD7690D5782E3A3DDC8CABD545FC1AAD8A9A0A39542AEC55CC3D58A5BB5E4A559DB1FCD2932EFF6E81C8B8E5AD5B4E0424A444BC55D96DF63C8971A5890310FE19DFF8ACBA72D96FD3F32D67D41A2F3D0B343489C7FDEE7556012C2D88E2BA9D512B71E7D04F92E6BE3A9386565271D755BED752C853E4539F95C3287A275004F76B9A93837C6EFC6760BE4A39B8AA92C7605AC369472FB29E11ACAD98FC91B1B9BB3505638D4D46A3AE3C10C8DC115C35725F06649BFB00BA1EF214B9F2FE98BE2DA99AB23E7B9F014F5C5D0248A9E0E088AC175C8048C6BEB5108DA59DC234E9EDFBE603BA912BEA22505C2A9EAAE766FF55AAC8392AEA5C722DF25BC6C9FCF9B0275DF71206A4E5290FC5E71D79928E357400DCB04EFD7CC9BD0B86E04BFED9BDBCE5787E40FCD6041ADDA615B5ECF03C30AB9B2809E3514E9AC87226C55F259C5F157945B0073431715E1740DCB319EDDDD1B5F2763F0439CC0D6ED5867D9D98C227CA3008F30D1B2AEA40DC73FF8289E4A21586EFF519520F888E7E2F6D29A269C12607D13D398F437CD7F0A07C94EE1E1E3D8518D0C97BE1E250D79C5AE1709AD8A638F55 +pk = CB247C80D27DD2FE81AAAFE541223E2DD323D5F0D7A13B8F66655D94A3D04A93642E64E273C0A9EBC2EE9F202632C97F91CE5C03ED7D11C6E8ABB7BDE9482D3BD1DB824FB5BBC023E17BAD169377F6AD6B90EA40CC0E20893703128C0D9E96F7123833E8B1454C2F0B488C1C2112A0EB7B3D386BAA3E464DB6062E2CF55CC586E2D71FDF50B0E8D239A3F52B51409225AE64B452E717A817E9522A17074284C29C6B17C6B66BAD58A0E4C0EB493ADBEB5F4715B8CBA46F861A0A51AD8948ED26FAEFA5AD29AB4ABB8D84E94BD574906AEFF83AB0BB0B4A4B7B9E56CB036A75910EEA435C6B7EA78C73FF635C5428D7D5DAB310D2F794C362C2AF613B737B4C1974ECDE75A32C4AA148A5BCD1D8ACB5D3320C6FAFE92E359EBCDE53BCC360E44EE52F604A6CD8ED2824AE563A5CAEA0E963A6BB4E1F783013FEFFE4C413E0A9BFFFCD16111A8DD905516220DF1D434EBFAC7DC519B7D4723F3D1EA3A56AC5BCC6055F91000491CA1131030F5C60AD77685828DC68E0C23EE593AC8F7FD7CDAB17B6EF739DC067A976613187B3F727E7A6AF01A24D2E5987B5B2B3654014CB0349ACA91BB70D9102DC3FC780244125ECBB0A096A224A38A8F11D06286E34D06AF81397F343D7CFA00AD0312991AEE1A3C313C8D72F9E29BB6D1F6A6B908B805A74FD86D7B71B4325C91997FA7AA8344583639EB0E5D713B669F06A93ACD671EA91D86B215E334E5C99E963CA0E668968D000825F04FD5C30189ABF34A9A61811130E2B7BE7CC16866F28DAA50A8F3368119EC7D72B480A93C6B7FA44E7767296B9104D46D955B345E2A90855E242E60A15252580C08E104D249BA069380483CE017048731BFBE8BA70A6DA4169472E525B35B889EEE0793F73C9831121E6F5F7DD3544E4A5573040FE0797AECAAF1999A4FD1AFDED1D4942E54C043C9792B1F9BA0B24DA168C097D554B1D0037FE27BD40BD22B7E7CB27CF6947A20EC1E22DD3BCBA00D8A740A479E6F7BEA7F268E08B9CFF294EFB12FF9F36D8CEB7866721550ADD59C64EF5C2675D1D81B57FDBF18EA34D99F022255273893082E0FA30E6DC7778EF90251E45278CB14058B40C75726F43DF77F42DBA4B3E9E4C290D0B652A5804AA95269F3D623387A1354495E5D06386EA0AA93251D74AD350052DFBBF238A017B18A40CE5E402E08667F6729D8FE70DD84F435B10057F83D95F032DCBA1C9519C51430C0D777C8ABBFEC7AE7A7EB3D52D48962CB95AA552BD2BABF53B8D9D916E126780E41F50E76A68445322E6D41926D6F4FDE3584BE259D6E24C73520431CCAB2F75B8564F18BD9E017E7D22829E1798D1CBE7007DF0ED00B2D5AA8095EF9AB9B734F10E013FD72C2F6EFE50C3EA79CD38BD1168C20DCEC9E14AE757AA88497C68E83719B1C92F1D64E6AC129820F76E4588225DD14776876DE530D3651E43FC7E12E9BEBAFC6CB0EEE75E9F7ADA257581528B5A08D8B752D174D305EAD999E4A668D94DD991B1A66864FA7D852AF6072C624869D9DED682F3E7A0621BC51EC78D3F8B03D67A02E8C88E0E11E04140543D08572DFC3666E462E97F02EC37B619647A1384E03A6FD5611AC1ECE43664F76E611444FC9A1B0F378F976330ACB4DC9EF8207BA5B533EFE80AB3E1EE0B8BC63CB9791923F0A28790A56BC7D79B25C5EFCD671581252CE68A9BDD0A86CD585D7059D062E15C887D908C4ED5085C11E8B868CA2BC37ECA2864E750E7AAB0FB44970FBCD6E60FC122221943DFBAF6C6F1F90392E05670AA28C506C5B00E29E2223B2C777CC74FF063477B0C393D0A4CD143B5AA6BC74462E6C66A37BBC4E3B96FE62AD0AE4A3200BC03865D95266CE93A3FF367FAB8FE848BD5D88F0ABA51BC80DC7E15BDF0DD0F0A07690C7BC596F78F50D47B70E0451BBF86EE2833C4F82F59171D378BFB59BD8271156D4BF41487B64040FA6F0FFA0D204E89007C07033305C86E0FB759548F942B76DA3E3AB65C111CC9E22381B406BE83A9063CB4E833BA3D2995C8C6C5C13FA9717270363F84023DA50CE017CA862EB0452F221B7EE3FEA7C9F8A5DBA31E468F5C11D2A32E12291F34A5C52DB342556607E5A0DEBA7C34ECA422C957CF20BE42EDA9761F68A55D416DB5A51B483BB46BC923A0F34F7F751FE673389FBDADB0C38EFEC3D46F6BB7784D9930872EAE1B8E184C100391E3345D8A353107F6C1649909C9EE9EECA6AFF55BEC55864001DE7EF81F4CEB5B88BAFA906AB03BD1B77D355FF36E7327B1D9D4DC440A7A86412EA9D0DF995A2A832B4FB2DFEADAFBD04E10EE7CBB18BA6C17B6CE141E0A132A1003A968C8565F5C1DDB7DB2D8FAA9746FB8BDE020E95CFF872077E47A4663AFB492B98FDA5BB0AABB4BC8124B0D643E3B99D1F1ADB4F54D4962AC5E2613C68B67012C490681EC1EC7B161BB1E4E6C81664A75154EFB3D401E427B950CE1CB2F3BA4F244831CF7F5FC1CCE39C4B2F596958C162F025F13279FF627FF01E96A4BF326B7223176C3BF3DC428179E3C37751849A19DACD0D9362FB3CEDEC8CEC5F81EDB1B2177438E365CB807CE24E1293913DC80A515CE2CD8ACC8D899EA36BF5718ECD233D414502AB562F0E7BD20BC8ED33E1D10E72366042CA30E56553A73820F5B3A6155ADC634F6E0001EA7A05B76BF7E588BB1131D64DE99BF32C9294F1B42855A92356FC9306E9F909216EAE7B7A9CAA383BC99EE03E4EFEDA575EF5913C3C5709F0AE533292464A50D5FB8546E84A66F6CB76C +sk = CB247C80D27DD2FE81AAAFE541223E2DD323D5F0D7A13B8F66655D94A3D04A93FC4B69F8634D7D32CE9EB0011E8DA227E1C148F1A3748F45E5354460008C2FAB09E3D6F7448C9E2E10E46245A2F3163A0AAA2636BE6F15774041CAC2814406379787C938D442EE3EEED30676F67A69076B3DA5ADEEF776ECFF0D2DCD81C283797732402256188828476804583523674545673673581132860363655521577024171812113350822262583601681753524100386162058820757228082443326207821228138336254218887113366204251445386213615554326067861147283204325248151804030783318650823856478535147640307366673181715168340055305081810765154584588243242016105321566130253867045301654470768474340255545083068673647680732624180181736854876384731855360463707286416031753834541676371624232000884578303672514022214132163002067761337140801277157326832380218582240317518182484454686037340434647687622021304075407146615083331135550781832564136232458528463865778235613576537066546753340271416036082428255522367653353316365211421150444675577273151874466434241138556522517752320805310633811252858244757820634566472852022582527840776825140182567300400024341432802153202518687612812844666812306103780518005581562643663362464411488427528205488560557507062142231361061471761734187105004012614367842177012270038756108377815708452768556344886134444085370183680104267817483510517327338870251287445624680258327538124418843684580778111057563831120851131136334824346341372761465420852324717081053160372644213376440523261528525168175863235806222640352845025386412650436105760437445465534304386826582208077140186205038536870535871578845813181315110158856150105502051014322408020285243278481787441424164266133844758675644230734255563727017833061175623361208814316553123814670205487730524737873131405602506368853638700732047638522253822261883887555088074025545762288505357524582202666126456208757552571406878281175103452878033766268760188241400871027265354051382157420585130675135421807313603313044602462522872457382236737635465540662326657265232066043674813382785315513735646743054023075526860318556205765871180582573723154103622803101001156153556756313706680553143617348875518881423154532225028704811422728378207178536481858006715334467316875720111647611426886853802453614433284457036471873503207770147443615772245848622605582201074388000834241402822130337742720720350522271452482532842180145187782128536420712328031273286582770677823621615876052654535816177405428336456870478356014442588046761342303512056632130273323113206410786050452576242020046435422717875830673406734641501756887482162511172660263575214837008701885085880550033828587077041676680213172638667652227834426742445488122350770513655182062604280428861402621040625681126462103062256406575161740056110265267612831505013215053536403650402274654266331748302582211457288826657784425376432581357746268453441011074067852853001161032523158178463162002470584255830044061686466583430125868670274448315145510786836676317163027580415342184751227012716262040703444458426216305617723528453417403824204705174507512555653475277332814865505403071450287371238885381503145111301865560101587254570876070651860855628102758328573404606851487150443074848234346638295AC901B4D61C9B41CFDABA36B788A77FF2CDE0502B3165705A8809456F086C3CF002910E4E3A1572A28FCF639949B2027D2F8F071B6A83C2C8E5E7FCE10BD5939EDD5205848C93C280CED137BB78DFB0CEFED4EB28585D1BBF2FC42A4911A4210D39C070138EFE26A9E432EA518EF9FC7BB228E6DBC1CD2F9DA1BDF57489480801782D1B9678B9E618577F4EB8A3A5BB7FEEAD0CDD11E06F826B58C448E7FE0C5EF662B1183114186DA013468CB7D1DD8F84731C040C98A7967E8358DBB76ABA4D62AED958BB7465AAA640208DC81F2D8F22C436AA1E214F9DCFBC4422B68CB9E82D186EC76BC2C6356AC551CD2A6DC633D11F823469CB192AD030A13718ABC59349ACA0B3E48E4B2F1FC9318B489180E01EBEC918D8D231B9CA39C1F5C28C4D957464AD82073F4F6A1662D52A4A76817F3A3C1BF6E472EC5DAA3EA7E79F39C690668CD2AC203412C5F46DC712418CDE852E280E5178EA72DF4AA05DC0EC3606DAD5EAE952B8C1C7BC177426A2A1504912F872CBCDCA75A7BE38414DDE49DDBFFC031D499FE6C20FA6C442DF0374D88550C7512AAFDB582EDDD73CEFE7E445E622D11EF0D0274FE02A7D0B25B5ABC4424905A5BE2B0D702FB75C7D6694B04E4057BF8E232E3EA9AC10621245F920AC4E665EB55F073913310CFDD32C913214701AB4EE5E6937751068E80909D22D4506829E6B14A0E3B335877F631CCC3D6A57AD7DCD392F0AFCA5F5E6722EFBC7414F607A7C01C6F31ABF136376023496930BD9924EFF8E740E841726DEE044895097B07752FB8CE738D4A59460F499C80AB6269D073964A1CAFEFB2107949312D01BECF675088AB0F5C7CEB824AA194D0F8CD683A080DAAA5C406ECE45C40C2B9E2FBD93D39E9B0C42556A5659F14F4F646F92221EAC9B75698DA46F3F0C31F2596B6A6BF85682C20AFC23D6572BC78F8AB476151B71382C27DF6B4DE7DB1146F84487B38E3297ED69CB8B9F75B694F53C8563F0B737E50CC12C47DA0039416FCC33A0420AC7A6F7F106DC234A76B0C3F9034B7F1D15F53B7E8BB85A3EBD93829D404ACAF9F1DE01D3CCA4D2BB871C91DDF6A8C6431B8EFCC4DD7EA8A2514265C430B26BE99094C24EB0C4C2D3F87B37C2DA972FBE1F5EB9539DB13456A325F4F9CBA09964EF9E09DA0745E5B25E4BCDFB6361DE257BE32DDBD409C8FBBE69DBC60159093073E8C0342EDDC189EAA565EFA44C5EB2D4B35A013BFB4F151BECA0140466585E3CA9D03FF38FCEE6D675BF4A8FEA140EBAAD079E0F7DAC52B5D11DA813D2863A8C134BB282CE49BC3F57A5A9B19B185E7D7D22B0ABECFF0AAB12DE2923A46B19871C522005364A952BFD77F7D19454092ECBBD6956EFDC2914E7BB56E576DF295D336C64F93862AC59A912BC012324ECD94A19123FDD7DD826FE97DFF9DD9423EE2B884C362A264D1056FCB59AF3952188A084249F3174A19758D770EAF543D7E47BD1B4AA7A67C93243E5C047874C66FAC6294CF83A65E108B0922CBE2F5C41EE9D64591DAA54D0FC3DF0A61B4194074E5037F2C41325FA5F9066F27015BF09384C51B44716A0D01C84F2D709DFA3AA97224BA674A9189580FF8993D710847CEA043524C660A652EBD40C403FB876926419D76DA2F54510096FE57053261AD9791B49DC50E85F764918F814B4F5285F2A0598D91CC98396D0311D5FCEF221818745189D8156F7405B6181991AD794849354E46562884B84728BF4CD013ED78319EECC0DA98F34F957BCAD9A50EF8DD0B3F1F40730F1778D624E93A2F13AA3CBE9904FF176EB87169040BE6E45E6257176905EF00A9B7CA25C20B249B95F1A64290BA9DBB1A97D84C25CFE530958207D9B8976CB21EB49CF13435EEBA956FE4841D83080880A2DC0D02E3B3927A6FF0BED1D64ADB0C8DC02ADC0088D3DB0D0379E187F56BEC354F87B1EAC906C6764595B55A5EE8B296E6ED2AA3786C2D0D06EABD4193A32F87A86504BCA6980D99710AAF6ADD0782A65E797B3C5EB913D5EA20C072B18EE609A5C2DF77A7A7D541295D476178603FD8F4329D51404117BD73F3E7934D055F477910F570CD388E2778EB7F94ACF0924D0ED46CA0EB28327744102DE706C92C750EA334EA200B5C7D7130355BD6697D8CE1297764338648FE61F9AC7040271075CE645645EA2F1566C982F87135772AF3ECF3260FAF9256F750351FF0F6B239C9FFD6787693511902FEB840295589B807B2B84DB142E62F84F69BB7339C6301B21D799DD67B6E4EF2C0DD38B6DB7F880B51A98D99A5BD3D2AD99D8D7FA34B4DBF3BF44A790D42C06C48293DCC95ED449992437B136BB6FD073941862AD7F82B243D21858ECCD89D0742B3CB7E85C66393610FBA7ABC817B15B5BACB71090FA5C1F69726E00C6C050E7B6F68CD64AA6A573C25C4FF7D751AA8A2262FE90E0D0D94F5B4DD829886F743AC6433E489E47D9D63527AF984EBE3001FBD8E336463A48C49240B90A200ABF63D4D4400A60727B84AA36D3C6802C6254823245AE348C58430D86DBA99036A8BF30C8514B251E0D894A3ECF87029D91A26896DDE446AE28774CE0F60EB49C06109A13BEFA4C75D887D8FD8AF8586DE1301C6CB8FD93365AF347945A571A43244908C2E841A6759A90F5C1B627ED24CC661592016DD5318FFF7A5286179937AD5F676B3047571CF622F4B437BEC83E16C6C3817B38DC680237A93FC96B242889F7DE7BAF05D4AA0E776B6DE19D84815A915A2F3D260BBE5D3252D5EE6057301BE6B027F195272993AA8B3DBAF11824611A0A8DE15485D4B4C0DCC8FFAA0544F0D6135411C626BA12FAC44F8969EC0898387B265C90B46332D64555E646A18162C1CE742B0F134D5A6D12929F6C4E6B44CFF54ECFE15F574617471E5DFB8137BD015172FDF379B64EAEA44FED0C14A099F348F4CA6CF1DD26C0B1AF27B93A74B67EFDC0251C17B347F2A753D9606B1CF2C803EF9DA21BEECE0F284FAE5B58F376E2EE73630983202F62C65B539A2F41BEAEAFA9CCC40DC5B903017FA7896CDFDD1AA9A80D4D9CCC794EE7091ED1772212ECD84F97906063E22BE4FD7D02C972D8884BD797E72A1EC594A7B78F439975C29596F8A18E541A7B1FF61864566D2EEDEB90703CA6CFF277847E6B3DFDA84EC735517A5ECECD0F080019CD67F8D2FD2C44C86FF0117E087223485AADE2BE1F799C2D3FFD9230C955E9B3B64CFC55AEAEA765ABBD0F5A6349EA1DE40EAC56B15E0429FB48C1466AA31511AA2417DDBA87BC3095F1E34605492225A07988D8BEF888A88589D68038ED47D0F7D9E5D52ABA738C3998B7DEB1983D4370833D91F33FC1BF0D0C6DE9B01F2BFC116F70BAE20521B7C5464CB736413324B6DACC7A1FFCC409BC0D495549F7994A0F1CE6E55FD209A86C46E107612000DCD695C3C0A9C9137914487D68C05536EC8B097F83F4B7E71D8B51949747953E60AA40048876702910D3AC89E4EDBBA8CEB5CB1E9CE2DE5F457BE6C80C252718E91AB35AE38FA948BD3CDD37A3EC9496EE97072B +smlen = 4695 +sm = 420443489F151D7CADC53018908E71BC8E6AC5C1FE71EEC23DBADBCC0C69D350289261DF7F157E0DDFB29907286D9BC70966626B95FDE285BDDBC77DC8B58C53CC6DA5DB69061EDECFF148EE4CCFA9C7C4E95C236C73FCAA5BAFB5A0988D3C6F09F86B0D163F8D4E44386C2DBD905EE7B2737EC0398CDC8FD314BE0A19D121F817FD0F868095F7C7D9E9278D14E6783962016C43302E8D6565C49F4DA524825C16C3E082C16B62F6AA9A27C274F802695EA40BFB63CF5BD39F7749C34A39AF8A5774BA85F21645950D9DEF3AD64AAA5F54C795E05C78AAD213B7DEDDF3E60C0C9D8A26100474ADE37CCD9B4B7A6128F020497AC8E2F23CC3402CF1AE43BE90BA6E8DEEA83D2BFAEF58FF7B49BFEC43EE2B7DFFA88A1A35B508AD113F2C78F3737C560C5F47B7217FA2842ECEA9F0C5E24ED453419805A658908CDAEA74A45CFDED223DE9DAC11FBF4E9FE2749B0DC5BAA9719D88D3D3DF1BF3EF39D285ADC6A15C3A01900916298397A89125C56373D9E3ABFFF11335720762FB5E9F2AED5F9A0315F431D6D1A8ABB23EDC9F74D481048DD6DE0A70C214AA85F3B9BE0014AD410A60B323E1E5667F22EE45B701C75DD8CCF75D0F7DCE2D62A801DD423DE1B81081616098AC287319989B828CE03835A7E3909142A8D33E5A6E8F071580470886A5B8C4CDA96713F256C38BCBC3E04538E066DD98C1BD22949A6AEE57D73E2E503D082FB098F730F2202B2C0AB4D411062237F55A0DFBD10C575C05F6329E3CC0537D97D28FC138501947C6CF1CACC2F5CAA65381187B1A82C9B16C375C2AE616955D53577BDAA87A6B9BC2BC55835C7BE233849E33B13585B4252F6860C7D4411DB2066A91EA931B7A4640B44E09A298B8851C8AF46529A7D6FFA8A73032AA8A03D3A5648F3B9CD401D75CC0C9B6F593C6E5BB972A8B09949234872D431AB4B9C8501C5236B5C28219205C2DF545F986D5A6E452C22A39EC69AD64399D2113C005C548CA083DB65C4B36FFFBCCB11F170245E0E4371A4A83749EE077E58D8C90F3C116CA64ED9645B05700642FD52D2EAFC5A0D62BEF871033A6BB01A92E01096DB581A4CC52DDB96C60829747FA29EEE0A463CF670D1B13C75E7A1CA6E8A5F3936C0D6CECDD4C893FCB7EA59F8DDAE37367372F2C448E9888F0E6BD0B3BFB3FDB29EFF52317E5EF7961375A3CB2582A995AD987CAA33C2CA8903C42DB16A5912A21ECF5034C691001E83D43E25A51718CE3981A01301EB0B110FE06FB6AAD22DE54837AE907A811F2A7F4154BD7FC363D685B4EE60FC69CBBCCC7AE70797FA37683BEDDB1FBA5B87D0E763ABEE6B54A8C310EA0C593D73896D3D1677FDF0DBA0A8C18734A2C059752CFA7C697FCBA571AD704028668FEADBC7F6C722881ABBDD1CD7E6FF36BAED14B8D64DF63EBFDCF145DC4D7A254AED527D681B74DB8596AF236DC99F32A54819D252959A2CFE6E79214207108750E84352D1E30D849EBC310B0EECA210E3FEE7BB3F3C8CF8935BDD4097BA70DD111B643CA5B61D8A8ACCDB33A6D4E861043AB28DFAD36302AC64127129B1AC21F75CF02BDD8910C6C8E27C2A4223619225E6E0A1E56ED3E2D60DB03581525B1FEDC6EE43858C0CB581111C23D17D7A50104BD43A0134A7907FB37D40B7423DE4CB646632C058BBA06B9B98B62546CC48429DC176F5E0904168CC17AB877083AF915505B645B61186F2D2134B195932422C9005E17EB3AAA06C17DAD3F1B2120539E4159CD381ECA0D90A6FCF42ADF3CFD5F299220F2314415CC4409008FD547A71C981D8EBBA84CC89FA260931E4BCD6C5DDAA9373921C784FA20AA647880794E82DF60D3805A120DBD51BD4045F7D0498F9F6A283C204D5FB66BC4EC3B883FFBFB3BF5151E1F482384150A73DD7C25DF58B2DA6A347517A5DB534B3F67E7CBBF4B03F58BCFE8709D66E7F02DE925B8C23CD073496C978F5305B58C34D50B99AD436F7192ACE5307796F4C409606EEE5E88546FCCF2EB3A844F97FFF40575B1D4968BCE6BDDA547489FA7ED0ECEEA6F4B7EADCB0FCBAD45473F1F5C4A2E9EEF38DF266FCF522895FA74A88795E8079E5A61902D6EBD4E162DF3A9D0F4CF953C393F36ADA5D401367490E633B1D5FC7AE4BC441073D2B7E3882C15CC7843CCAB0BD49C8B2D0D6793B444CD541C5AF4030A2909D5FFFD6A314DAF62F7C904C68AFC7F5A39A789FE3A2E1D8756761E6D71F5A413EB30AFA1A23BEB4B9EEC997B69805AE73F2026784038EBFA068239ECEF0E2E354F20E04228C274682670F8265F8E8214625BFA83E64016E1A77860FC13E9254B94FC08489BCF529DFD6E8FD13CE06A536DB5D7710EBC9C0AF551C8CBCD5E976F3D07151A9DF5B52011D9A656EAB58C65669F774E188A70CCCB7830CF897563874652F6A2A4298DD87065370050AD8B87527DBA92319AAC94E685682F3CE6F5D2D00C960E18D7C46A30CBB13F95491705F273B3956B8E2543B09ACF8ADE2F9C40AFBA5926B177A3031C349549614AF645B3986FC2A3D9B2244699E58EB4D158D6D1430D478D35DD97B1C0C95FC31CF40BAC6CC0899EED280A943B4623936795C31C4CB25B91B8101C2E7EC1AF6A4505756979B02B035E4385757F04C30B59561D234A29DAC8D6710FDCFB58241BFAA861E417BD7060F58EE659B7B42401DB056260B550D29B2E433AB9EB56A70BC285BB17866AF8FE4F9271C7BDE19FCF110A0BAE033DF3CF9BFA2B022DC3219BB40783F85092799C47DC580D31ECCE8354F31130DC187A47F670A736DCA88B8404093E567A0B3307ABC464F6AF0DEDCC88CAFEBE0F452EEF856F50468833146C4CB99A500A5EDEE04F5D5DDF0B3770BCA68DA709AC6718C413296F76B5C33D1603F54AE103A92CB0B5E947BB0CCC32E0CBFAE0B79A188FDD08C99E5C466025E88A5D2DDB184D789973FD6B576BD275296F50921C4DA7D9A15F752D5E76A7C7D4AAF154DCB366AA51D685E56B73A1760AE58845D1C339A8D4B0F740D902DAE9E2B7C12020F3421F70043078E944CE153758B27EBA552E1253DFE0C3215D5EE09D40864DD0087C6D07D1AAB8A76863A273322772E0A5F88DC651EF0541181E756360D0863A04CAF0254DAFC0950AF9DD46F4F94EEAE191A2FDEAB775D980BD1F25339DFEB95B9275A566B360F24F3D417BD992B328077DEAEBE2F64AF9148297C1F13E75EF8D09B90F6D160F8347584CF8F8921F164BF02A09E3B19486F0FB7126C43F2E2C994B087CFAB16CABA0161A37FCCC53A801F449177C65C86057D386F20AE641A4BBB5886B3B89AA460554CA64F500830DE808609FF7E968702171ED42E5E76A4D17361DE5EB1EE8D8BCB6655705AAC60BD01CC53690F29C667406C72967BA23CFF7C2EBA3730A465F1919C5CB28EB12928E09905FC923065D992A7D2F41859B646A9743F2AB6BC4CDE92090C5E4329355924BE56EF8ACEE88F42D5440F04421B16E261823BA0325A717860C27ED7C1E77737A3523B9041880C64F34C92912240A8739B12018A98B4B1DEAE36D4049D9D4E5354A7D51B98DC2EE1C02799D4CC70AFB553EC2D607BB917952B9AA9C0900327C1CD168BCB53DCD3ABAB08E451D683E08099769BB9A91C3416FF2D9FF05AF0979CEE3EFC80849B2A0D48FE3AFA4CD42805BF598E7704D35DFE0ADA1A91B16EBDEE88AFC75614609B59D867BDE368BD41CC60817A6BE20E4B10DCAE7F6E65CE4158CDAE0D5A8C95FB263D7D044BCA4727D44BC279FC509AD5312BE4F4025E34D1832ADCA29AF0497EC728847872C2CB4E1BC47805839B057BDE9E13F251AAAE2168E1A2218FEE328DF37A107F651AE78F64E2DC6739ADDD3FDC6F6CE45376C201D182A89130F2ABFFD32CE37B4B3B4BD31D1FCD69BE7698D00380BF196244C2686B323C34889B1F09F1F5021F1D4F32B7330CC8A580037067C4F8775E7D3DB709116EC6408DE91D0C52B2F789174C2FD82F4CDF8DF927956BD0341E699AF8A6F6B0C9610D3A6EF800672FCF701BFB10460A0D45F01653330A3443C439AEE4C32782613E972A8000670A2EDB1C2ADC371E5421A8EE52481FF5E2BFC29989B6FDA342D680B409B0543331F83154AC0872805FA3DD184577422EA0335C88D06FFC57AF4720C6D4A9EEEBCDF7853319B074D798E2CEFB530FB458DC9C7013F8395AFF23D181320A7E6375F11007880E59D09A56D85B7214E33C4A4DBC9CCB1CCBE92AB2E41AEBA898870A132350D7CD67739CCA46831096D36AE4B230FC2CEC4703BCC2563C6FE9336339D1A4BC51144D77F94344ECE698F091CD82A1762262B88EE1A0C18B32ABF9F639081B7EE2EF9D30D91A0325F414CE8AB1FEDFC838602E3F9B1605616B5649C485F2EC7875A88CD5E02C4289303677F026CDCF301CF7FB204D38AABA616CCF690F9B4FC16530ED5B5361D372137D1D9950D20B9AC6683096DDBE79826ADF17B79F77F98F2E31B7EBA438D21640E67A14FE8F61A759831B33E7BD91885ECC95D45F29666167A76716D0C17A9175B74AC3BB993C399015CB1E0676B7EB5505D75FAD005AD5EBD703697F3AC5BDF17A598F6BD83A1C10BAB5CE6DB4D7273F6A005050C0F27686A77D73D4871737CB0E55B85ADC7CAD71B212B3B50616568A4AB08111788B589939FADB8DCED000000000000000000000000080F151F242B9D84E1DD28C513987D5587A4427853762B7D7AF668FF9EC2E90211D6CF5C0DE6C7E54B298C1A6C67EA9A693CEDC4FCA1A6ADC2C6DD0E5BBCEE7266B9C6AC8FA8AF5E50078A6151F938161F1FEACDE4D8079B5A9D563423258CF3AE9E47D8E75740314F2FFA63865A8B30743F773A53E1AEDEAC45CAAE01993B75C8116FB0B431631AC001AA8BD02E5B83DE627AF0CCB3A3D86F66A7E5FB658F9226DF31095780A6E8262A247D70F4E7C971D108567FFBD7FED0E16B7FFDDD93F5764C3E02A61998C32146564D46589538B2E071AF86A26321A3523354F4F0C396B863FC8E9E2E3A173901D0D178A9D2828D0E0974B72CEDFB17937D6054F185A81D4F853787E6C3681A74FE25FAA6C256A9F9E9A9253F98B9AE4B8FA0068DC28BC7E8D5785CFAD20F7DDD643DAE6A2DDB02713C9CAFC2EB2FD18EFDECED05CC24913061BDC38E932DB5E8181FC0D3DE26A94E2138800B3C01E07E83B3B0BE187EDC75DA576AF1CC7B7122367EFFD6EBF05F4C2EEB0AB6E9F91201A4237910A87DE9FEF777981D48FBA28AB8D64D76380911F2A6621335DFA96B331AE8B3242EA1F2A260260244196B0B9596C411218A17D0A58D3B5735B9AD7B6259655CF6E2D0FE5B37D0A0B02E67951F5D3FB277B6E1EC87528B08229AB0EBD895CBA2D075A47CC8100E9DD17DE7D951BF0A68D710AAC21C8226D8CA95AC49FCBE9D493A8D3C7F93FA61685BE57FF422FAD036304F317A3DBCFEE7A4610C8C1DDAA79E37C19D6414F47230E01EF1CD5C7C2FFC319A29AE6A9C95B06C603F2CFC1D1FC914B036CDA6CF9A876946983B06123C2E5C7D09BC190647CDC0512F35DB9E214C77D3D7D0234C3F2590941236A367700F9C04D3AFB949DCA2067571BF28E78ED35FC026BD801C4AFEE9BF31C97580953950D2E81EE6426E78D6F8134ED19707473F0874367C86C9BE170BE63405A9BF7C46A420724B6CCFF9C21B015E21BB02C5A7AEABCA873B46571530DE56E47288C3424DA398517ABB6502A9A6A65D4983D97E479941C44CF0136D225991226F70837E2A7D1E9CB1226F40BF59D52C66549BF8E360096954F5875C466160A0C75A252E5FE6B8F1841FE210BF08520CE74D77B69692086EF50BB64732F19D1A49E5800F077700553290635D418168A6B9E3AE980112AFB9D58A18B94F972845C309E86FEC7E456191D8760A1C2106036E44C5C9A5F2CFBC67D741E8E937E99ED7820AB0787E39C385356EF0F05CD3E31C44115A8892224197B1D1F554D5098B72058FAD49C665F716A266CB4DB6204666E1DC07B6CFDE0EA00345661E0F94A5025D2EC98483CF482058D2EDDB018CEC11D91EB46B63971AB29367DB46137CD7690D5782E3A3DDC8CABD545FC1AAD8A9A0A39542AEC55CC3D58A5BB5E4A559DB1FCD2932EFF6E81C8B8E5AD5B4E0424A444BC55D96DF63C8971A5890310FE19DFF8ACBA72D96FD3F32D67D41A2F3D0B343489C7FDEE7556012C2D88E2BA9D512B71E7D04F92E6BE3A9386565271D755BED752C853E4539F95C3287A275004F76B9A93837C6EFC6760BE4A39B8AA92C7605AC369472FB29E11ACAD98FC91B1B9BB3505638D4D46A3AE3C10C8DC115C35725F06649BFB00BA1EF214B9F2FE98BE2DA99AB23E7B9F014F5C5D0248A9E0E088AC175C8048C6BEB5108DA59DC234E9EDFBE603BA912BEA22505C2A9EAAE766FF55AAC8392AEA5C722DF25BC6C9FCF9B0275DF71206A4E5290FC5E71D79928E357400DCB04EFD7CC9BD0B86E04BFED9BDBCE5787E40FCD6041ADDA615B5ECF03C30AB9B2809E3514E9AC87226C55F259C5F157945B0073431715E1740DCB319EDDDD1B5F2763F0439CC0D6ED5867D9D98C227CA3008F30D1B2AEA40DC73FF8289E4A21586EFF519520F888E7E2F6D29A269C12607D13D398F437CD7F0A07C94EE1E1E3D8518D0C97BE1E250D79C5AE1709AD8A638F55 + +count = 42 +seed = 7AD6C7DF00C9E52A75290D28DA946305D83CCF6DE2515C19A8E26850C34C8C2E545E2E32108F13B9C97F87AB68D10131 +mlen = 1419 +msg = AF2860129C08A1A9C7A7BB3120B3E40AFA1A4A09050C8483E7511FABF3285544D4CE3F41401DAB8C17DA547F6777A72519F6EEAAC83016FA0E0FB0B33329DD02AB8EB1F291758074EBB5B7C4C102B75BA422821E6755B37B914D689D84808A89CF88F69A446F489A260BA03CA52A4AA14E8BCF4BFE5134DD2918A88D67329B9BADC6ADA4A3071FD21CFC45235FA0A1B82D91C5877F10AE087464251C8899732AA7FC8F6C0A5BEAF4FA41E64CA97932925A06E218272500249577705804C6DD9F0F61DEE6AAE096BE0AE5E67923137933FE4D61E9A88DFD5B3BD75AEEAF5018A5153985E2837AD1AAD5EED91620D935EB9982DD2364B5413F490BF251FC783503FA146300E6ADAE0682E0597C3839C645DBE855919BB1CB80C3DC6E233909017BB31F5ADAEE05CE442EEF594FC15FEC3A2B4B81ECAAD1340B0677F27009290AB3AB8788556389047F63C2CE9390658E151CA85BAAE45ED2FE12B6667967F6B772EE683AC2E7347C7B0EFA332B3354B5043CB86200F8E4249F68030844D00A86FAA7B79A4129AD676D1E9D58828A1AF4C6BD68C29CC23002E0A0313500BA717B8756D4A18E41E381DF8D7A999A153876DB876CA4A508486A4F331CAC9CB3E7C416C6329713CAB76E1C8B63A8CAD46F8EB1E65116F89A3B4EB8FAA14A73097CA71AEA3220BE7FB7FE64919893930445D962C309E23332E4B3ED8CA768EF0ED46EAAB199827AD628A1BC20CCD9F61BEF67F7FCB017300EBC7493A7CCDAEDBFCA5F91E80B80DECBFD9EAD9BF22FE16B563512C7383D34801C504202D7A0E19821EC8495016362EDAC165904D2BBAC484DE1D4112C3A3E6EA56A78785B7CAF2A44B5BC8BECBC50BF4B521C1D086086FEB009C06ACB8FA0F53E7654FB02AD7898E35E5F3A7DCFC50124BA1F30178C707F4D36E4E7758C4CF82747753CC30A836311794A6A9017F53ABD17A1C9647AB38BA56AAC83C1812DEE8A5A75C5CC958780A3E9C3C1F39729BD365948F7FCD8104CF09660060FBAD2BE9B8D8E5BDD22286EB0BFD4010681AE7928D0FC008E21C8F877D97B5B9C7A06C02530FBC6A9D6FCEDFEDF68A9682177757CDDDFFA6CB9086B8330E61851E2761D84DA37635EA8441E3B23FD165CCEA562B0A3616B30EE5FAE00F76D6801B22F2215D80829E01DB2C0743E3074CF26C96B0EDDF97D79FB9C7FFE9B5CDB891F9E61FEFE7E1CBD28FE25B7858921C8C99C45A84B50A8233037DACC20BEEEBB9B22089DDAF2EBF0698498DA694F75ED2463D09BA2C757A986B8CA556CDF46CBCDF288C078041D497242F66411F47F35A21918855F105F24686076FA21BC1283F17245A7122A848B4BC10D996B2C5161FCE0336B2EC747A4A07FA9851AC5423D1EFC4B524E795B2E4BFFD1C5CD21F5FEC954824DCC53BC3883A7F571A9323DFDD2682C4A4C54E8862F347C9A8897779170B257AD26D90121DDE722A3F214A44CF6C5A5DDB2452A2471EBE7FC8D0EF7F1EDC7920CB42A71E4DB49A0168D51843F47D17BADE50DCB340E5F7B7E5B6A6C3AFE0FB26B5EA172A4011EEE838E5634E521483C6EDBE9994B0658406ED8F4998C7B4E869845CD16CC4368DA3BC1B025A6FFAFBF540133C372D452DD831DCAD39D61CCED0A0AD193FA9886EAC749001E3BEAD5A7962275FC62298A1BD054F4BD97ACAB2BBFDC355C73509D98B6DE5B4CD774BDCAF1398532BB3DB56524CC047ABDE6880C3B282FCE0FB2AD7E4C5F7BC138B48D194E8C8036DF4B9F3949E912AFE5D2734662F27583193D0FBA2B73C1A0D012DB853BBBE4383F6C391F3220E1B5761C337A054FC9FDF09C01864B87324A90C776EFBF5D34A68DEE38EBAACCBB61B4C79A58CC848184F605D43CF9D40BE90C1FBCF6735270132B59A636B16ED28111246270AF32EA2CB7A42A084005AEBB6161002E65B37217361BC269F5ED12F7D50613C82934A6D1D98D1308AC82827B7504F3FD351E0ACA1C62843C9219023FD092692BA4B83BE198EA +pk = 5074C41D9A250941032D2FFAEE8F89799542E294610FBBE9159FA98C0C1E47719002AFE846B94A5524FF92DE7B75B35EB77DE6C70E880B2757C5D4AC5873E3415004A09FFA04D6263DBA128711DAB7FB2FA36A32587D7FEEE92F2BABDCD42047D9ED36DE3BEE353A6F4417203DE58E486BF6D1331559346B9C6DB66AEE10666018F149314CCC3DC00B6FAFD5AB4D835C6D89705390F82465B0F5FC1350FE91BC94BEA61B4ADBBB6B5F674BAD74C4A7758CE4BC7101F98514A6A6649322525862D18A7337D3E09D26B875198B64256F330CEF3D42DC40CE0F96B59B38011B25141DAA867EBCC85ED46964A164DE388C9949E497D568A3AF7B8CB74D85FA5FB5D69F8C62B3B32AB91491E91BE73999EFB8B5204CFAF0CD297BB60CBDC89BAC177F89E0E8AA14284C7C94A6115079A1339C55F64BE1C7DCA39766EDDE5D45A99FAA8C2EBCFB8065A9D01B252ADD10B01F54B54995466BF8D9AE3C7DEEEE894654FCCFEDDC965840AF1D4702F8E30A5265A46D7060F1D1650561E7A891700A06450A9290C963FAD74A73A64E154657779142241AE619304253B48555D1977964D10BEE14ACD8878F879098F60B54D071CE8721CF214D6DDEDCBBE3C69A231A3B6DF138341333D677E342AB28770CABB9BDC732DC805DF2C92FC0F9FD8A60D143D5D5A0E9E62F62261A8FC4BC2B0BE629FFDED93A3A63662147BE58CFAD9C6E0E740638BF83E505DBB2B4D86460F8AA485C0FBD32D654013F1667367C908D61443EF07ACF8B7CFD7C712DED3465F3D1DB145CF00226C2DB48592515029DC715CA693A07EE281589F5A0956AEB9E23794A4E1A6FDCAD6F3E50FE0D2EC6E955EEAAB911C72A099857E2404EC1E3996D21A88EEB4FB3F88320AE7D1DFD8B6FD64ADDB93BB3ACF236EBCEF5BFD82DDDC0C94DB9C2F3FCE54D2B1219A3B1B8051131D9C912112ADC3DBC5EE0BDC034200499AB1029593812FA2A31E6B0341477D95F68BDCC39DEB5081B3B60B1846912D04197ED0D11150F796430C6739BD07484DAD5B3FCD8FF846E0B186FF997730045F98BC00ED58087FF53D52E3B969A6F8629402CD0B7FAF96DAC2D98E4F173A2B9FC5B111436F902AD4E0D4026F59F8F9DDBC72278F3C2B14E0AB04F14CF358152FB89F43A8AF0644D4B3D6F943232DF4BF169C46AAB99E2FC8F201AE7C71541CC1727F5D98C2C9F42024FE694F59ABEBA1441C8CAB995F098A6F5CB669FC93C6A9A81A78C5139B54147D4A263DE0E59E69AA08C04492C978D6A9A18119D7CE5C2F3671F3001836030D389A062289A36216050C04389C6FE4BD1A32DFE2A3ED5762D9C7D3F9981ED6DAEFBDDB274CBD8DAF3D2D35D87B6CA58ADC155BE91DA86E9E814A5A39BE2683BAF15ABE03745CB3B29C89FC3AC0D76DC0973720F9F8D7B9A19ACAE3419F1302E89428FD24CC73D0B99C4808AE6A84B16C3DB173EE2ADEDB4B72C3B6763ACFC6C6C3A1AA88AD626C60B7D5A21FFDCDED160C27151F5BEAD360E03695E5D66ADB1FCD5520AF133E21636E89C5F668A9FEB50A20A875801B34166036822866BFB9DB1C245CEF87542F111873B4385DCC7B3FF8A5D59D10B3CB194E7DBC62CF2523F514CD0FFEAFC29C258E0B0415565741E432B9A9BD0A3F9D0373F4D82F011FA30B991BBDF4D51A5EB6CFA43461CC166EAED021F96054B8A1CECAD4189D2B63B20E163A41A03123E465D7A220181F64E678CA247C98762D9EEF201945FBF5CAD5AC2FB76799A812A599BCB180BFB41B63C41E4726BC21C46DA9BFB11EECE48E908011EF79E33B0AE5814BA6EACA7CC97F0BDD3660776768AF87885F15FFA379603DAEC38580B61FF041AD6CFBCDA1E2389825D25901C1B7E994E0C4F8F152E7EFB8D966349E73B9CBAA8CDB7255EF294568F72503F05E0D7F66124B106969E7E64A2363FBD22BE9230338A009CF338EB57053230F3E12C30C6366680CCDB2BA755DA61F893A773E364ECBD93AEE25AF7EF56A032E61BA4FCBDB23F87E4DE2F2C3534A993A0A4F2FDA720BE80A6BF175D8DF81F0B3EACBC97780535FC06FC99C5546C446AD88DA459FFAA7738934D4CBC54CA7EE3E1D96952FB58E2B8153AB490749B28B7411CBA449E63F287CE9FE95D737BAB1A73E666FDA9D660B32968D36752CB3EE0654A20DFEDED37C54AD913F42662B7D229992AEED9800CE09B43529BA1373C1A9AD9185B33777785D9B0D60C0751EBE3D7C8AF6C5DFB9404D1B396A0FCC4DBE915E1FBF059CC3A0B18A792AD4AC403DD3CA984ED09DA8CA16DFAF55D464C471543AFCD1C3072D9FB9B37C0E32A328FDF9C9EFFEC01268425603279366C3925EDD1F63D2A648FB7849A0DB088DA16E6EE2EFF66B1759826A53C9C5EC327BF9F68DDB9B1A30ACF4854F8157CAAFB9A0D340DA4ADECA50DCAD0AD27B44EFB8136BA4138C7308CB23ED8130DA33E289B593B8B48DDA69CAA472AE450CF82356564F160536F93EF161558FF5687FE7DA2F30A4A5304F00F9C9B3C4893C96A897CBA5C95CE67ADE81CE434AEC2590B376619222336B4688396CF20DD2B38BE18907C529998E828C746D0B2804E4C5E32DFC24363106603DE4A3E20413A9CBDC4684813F86B0B73E3892832FDD08B7759E75C5AED2EA53CD3B39B4892C8E96A8007BC3FE784EA262364A436E81E1F440D59AE310EDA9A0D48B6E9400C8BF8D059E8B2439B1EA9BBFDDC41CA50F6596165D606C448402733F173ABEABAC787F2BE75A1D137EC003EFD0C1D209B +sk = 5074C41D9A250941032D2FFAEE8F89799542E294610FBBE9159FA98C0C1E4771EEF4CEE980DCBD5DC35877CA0DAEC34347989D5F8C248A9C876790484EB99C555D2E8FC3D98C667BA1D3177B8001C34846E5CE9525D70363860BF7C7FD9852C4F3C9C71AC8E09EC5D6AE7456604F93B296FF23301C01D774822161BF08C166D007680273818380686361525471518331467656178702228048410172118022318708268635584212646701248613052034672278236638742873065345343564578555500751801010462224414608720161040060708242554677168284416077365740263343258257204035217183406866052218762806834367668244673326272733773243846464352361138045451133387748623024327208562841185601712531132174235050501070818738004547034055855572143700724108733775118801650667882402862853486148744250617856266163055645072754443283100428610785851476762144463583681018781178226780642672414560156587333885867106158645571668532576241083572655306861203057420528865712304445623427710385681745236073402131133173231665868622228810423545065441456382771157610155564573148238236323324273541466062133140315535187702011654725634131878347013257476442033357441458114002008318703222518737660168373528784601161206783242588661058422162506843228032537317105774824180580722251703816522076102707454472384031652371072354463610437527318014846355132314801836820872248420556416111058558530245307538454513111685276723700723723016154667047524881748086276517757507855764360621135082768420028171871650154271128366716842581723788485208530686262132012463557535348052530102570566800277538714711888341154246560852213548458516670828855406885827633571360622534758825278238731222106037626813342442581570066840383251062840564175238056315776314435660400016373242288336121185272064227011642151625307363334213215108435050314310285550262682555106820220460624454477246070213052066615631641846172566447487504605185843128440355427757365608348845847440788566670164817737181382044336240173863412461561667554036608837841583310467438404217825360862221645651781316280753234757083803463634578251006571283743644613706061078140500255336558830057313835125870048177817075863686823332201770414032276553820311070677852556323358372340623072558213174843362602546772267277833800516574836060821862817111611808181208887188211843701651288222846817388726528132208563033308855077111208861333448748548117232450881821220155183345205884336671434716004808607656177074730323161356824468388010106604784141762182810026634637645550843020012661225740744760484155165717105621128710043470017860822546734131106403031042475036343187876547214738773407675274582067580156327012254518150158137488223836611015238537021221003744571082561182586638436406704845801072515706770737600276386500854876743738080328583366413421085406254585661540117316635125865464744378111242857574376136434826618028146307252575033481050481522733124174800225280041871267707675727406567211602500250433670481684470627767145505476384704327476525355511885583048481648234631526477036473188627267113516707218301406724072567773457785641017870453278287157848528115840305328270867731611785758414645675105848626773755088612263250557574538407376882036887036306245458244456110647132304563512765471854502467752C1B59BB399DCA3EAD6B537376EB1AA617B140110F351218902ABD4DD9B1F757292625FD3CF7761358C0F259F7AB314082165C7DDE180D8EB9E6BB5B2D678D6BF05AAB4A05A5F62D1B720E9E0139DA53320F3D9E0B4D86702F3F4F2A2237784E610BD567F50849BBD26E0D0A55AFBF2E7291873C445CF86C5ECDAB90C24B469CF1D9185E65A5C17333B3ED9A1F578BBBEF6C62F250ED8F3C821C2BE64D7E33CCACA84E8DD45080894D91E330A441AF9D2E57782AE4FED068936EE7586D9B41AFF5298CD4424229F412A1426016E8795296574AF29FBABE4281DADB421684C0E6B6929880D51A8AD086823781DF1A4F6B18E29915E301C81575DC6EE151B04B62E9B3943F94599436D9D74BD335456583B1E056042D658296D657B925DFAEE02912772BFC3F55EE8BFB2C9FB31D0C755D1B05FA1613FFA46251690C564C20A7AAD913E779B83712EE1115D46968D5FC0B4625C4AA23CFF6A2A67E4B2A22B89F118BC12937D8A462D73C9DA4E2C14D062909A2E651297AAE4FC96D7510943C718A0A5B1FD600D6704D98B5A946B91CE72210F0D01CC98AB4E81D536245594323CA2669E2C098155E23209DFD60F9A7EA3FE0E8AEBC110C47A5E84304409787E4E515764F603FF091E067A52A59D600BDA9F144FF2A6C90E84BEC5B6E855959AAE9C8348BA93263B2E1C9DE264C3B4B5EE4A808EE263F21E5C99557C3392BBE48DF2343CA17B1FCAEE481C3373CA0E06698E8C7EAB9226B0CBB7144436B6BA6489ABE825D4BFB6142D0193707856386A923734F555EC9F23545B0AA09AB0131AB81F2E04BF5FF68CEF8E401FCADF9F7A5687FC51D407442BEC3EC47810A0C2DDC465E0B3E03A24641EA4FD6269C759E9D3DAD30DCE37F96FC4C4B61D8BA00E80205C24851E856FD336BBB01F4A7A4A1AB1DD891DC902D406E20375EE374FA6F173FA50CD3608FEDE7448E398FD1B35C18151BF4D0A12AEE86C42BD3AD878FDB05B859C412352E4202FA45BF0D9FDC74C0E17DCF874FAC18ED66A80BBD1AF052944B983E65EDB7BAA15C2720A220B645E3D583F97513F017B3038BB5C72CCDA8B764CFF529725570B1D8027F1C5DDE91C5375F05E5843B33224A7D5F4EF84E5CC974F36935F90D52A37FB5FAC557AE89E9E3A37A2F9C1E78A9D3489A26EA1D9C4034EA1B281BA6C8643185FA36F45F999049BB3879CE04978EDDCCCA839B7EED129780E08AC4DF3F313AE07881CBED032F315C524F5BAC787F25E29D9C232CB251124E89DC70FF1735DE77ACD50B2B6E5125A585DBD5E29B2784CFD62EB1D5D55817B94DB02C81F2EBE8AE7DCC49083A49BE916262795F9D04C73AE34685E236BEDE5642E00B15755450B5CB545F3B7BFEC33F871513C3524A3ADCE19003BF6ED50A3B5F4F4F684518E2193E6CDA19E5270FA3AB3772F6D30F845A79EE169F74FCECA35D64AA90C7DE91B377A91A786A5BB8151B8C292E7872CF57DE3D908E62A0CFE9F89BF8A5F1C6C2F41B2292154DD5ACFA96D7C1243EABD54046E5A38D85372AFF2AF386C9DA92104123CEBDC1BA9A27B3CF646DF240799AC46730218F013CD2FD4422DE16DB4CEA5B7589CB96ED83C75CA6F0A20A3C6785A4362E24C7CF99CC0EEC1FDF2867CC168D4C4FF7795113B4087F25749D1DBEDC075A75DE9B808EB071FF7BD97772528522F9DA32541E2AD02D6FFB78607C22C7758C7AEFB1C618BA385B867464E31B28263D3D1C3D4BC0E9A17A3A9D7E5E1CC79E8A411F49E61CDAA95BB9D02807565091750998FC845B66496BD4E91897C931420808029CDE4F1518C59611294F5C6B4A03CFB8D923AB6A10DCA7F56200E41EE2DA3413A4634B9453E61965AFE6A7DEC3AD9C641C0F4295B089AC874144EF33BA79A9DCAF88D9E0FCF764887A8F12D16C4C0B3F2E720AB79A56A56B6DFB03D1BFCC95FE7EDD41F8A9FFE80380DCF298367C4B42FC0B94BC93F51336C385ED36C246BC5B807EB2F1FAC827E0B6E0FA4B9188877D747F7FB853EBF0194D13A53E426C4E566431F07797458FB97D6C51A9CC8BC082BBAC39E70349EF5210B5CBE71DC93125ACD9363DC17725D2610C2425D2DA9E94BD9D56353308910902D2EB178DA33C72C6E6F73FCFEACCE843B53B75F78E1685B65624A0E65BE9242DAB8D4ED88327F7500F45C784133D1A7DF5C4BED36E695B51C3D1368114D58162FDC696C46C241B1A53DA13A4B56F3BE0AEAEB8F101454EED3C66B58A2A492AEE5A41D597B78D489E073E53D3FCE9EDF7DC7253F76A3D927BB597CD88E96DC564918CC45131E61B4F657F66344D7AF6355DD262E69CCC0E5BDF9AAC55BDF4D262542433D56CD065DF58ACF632E881F7EEDE586C914320DFCAF32F3738329486E35D7F312DDE19D23D4CB9315365F179D88F058F8ABD2F988985AD52D6916A9D092CB0B81838308277D4A1A920BE53FE0030A60EC1D5F73294AEF90FEB47C0CF4589DC81C2A590539B6444B43671C27716D3A866E301844662ED1403538BD9E0EA8C084CB419A52CD276E62999586FFA4C60503C5D2A43A1C54E5215F6CC4D4A9B1F28CD5026162232AA8F872917B4E3ACECA0D442BBCD2698276175138DDA269D20488B70398EBB09CF94BC0EEA39B2D3511F6B17351BE27460399547198585F8EFD1B645DE0334D21D4A10AF9441E20775B1B51BFEF188CA58015C214B243666B7A72BEAE55DC2FD9C6FD53010C94F1C11907F841A4408F7A1CD7C056C20A49A83B8448184D27F6B0EE9820B028FE4BD0E1DC5BF97AF2A48D9BEA7008C978100E4A581BF9E8F321D99CFBAFD4667EE6FD088374B7045C9ADE2D1F4D106FCBF467D0D9F539A1E3A6E028E99D52B12750187A8F918A59E5B83E3682EF9DF7CF01A6EEFF7891C10F655AE98F0B3D68100CF6DF2C6C534E70BAE5CCFCAA7CD49FE6526D0AE184365B9A1BFC43925B415492AF877B4D412E577D63CB7429AF23E7D3D4842D3332F1D2F59D7EBD23D071DFEB01459E7A3C13FAEEDEB952B2C01F37FBD55BA66A7E8D9F47F9304D631EB5EA9ED6007F9D332EBF019B933D82BFC6C40C5360EE83BF4EFFF3D31BEE23C7277D5446D7A56A99B4387357A913232D9BAB8D41DF76036112314CB84769D2B78B2083C58BA36B7E653A076B0FA8CCFFC83045E6DE0C579D607FE7617BB0E51963CE47EA141751E61D164B3D4174D6E96DC421D12959C5694BB9F277F5F683171B1EF34DBC86500B75398A7BAD63A6334F9BFCE11FD5DF46A953B858CDDDCD4282FB0C1FEA73A4FA9DAA2633EC68949ED898CE39FF9E7CAA5992C853041C0982699C4771A49292BCC8B255FD93BCB4291FADFA09B1F6F82C1F0D89033ADAB8AB6C20C6416C4C1693B92A627A72197F524E27F8A00C2B6A858765477515BB06933D02161DD0B93AEEA2338B3120B0689857006ADFDA7A159413F3011E6E31CBAFB3CB8D47E8D61BEE73A1BC3C7F76F488E1ED4F8CB05FA702B9297C203FEABC741E70665AEC199F0BFA72A0BE7134F686B4175C6710443A71FDC9ADE23E8DE9 +smlen = 4728 +sm = 25F1D031DB107F487BF2A4139792CB8AB1273A97D23484184F6BAF64F01551F00AED2FBC607CA14C744EFB1BCA9D990603C6EDA504DCB71D5F2214D8AFD9D7D2AFC33B53CE3805516288B9E6795DACD9AE18D675246616A3C67E39053717DDF19BDAB5B19384D7F0C61DFA89DDED70D64865C872919EDAFFE2AE6FFAAA3AF0734926C3AAED21CA12A30E4554F49E988100D6F1A717A55070CEED7D4A13B41DEDF2181468DB4575E42BBE35944E7C5490297AD7D2F6C276D116C362DD5101D5FEBB76C870FB919FB812FF4C564A16EF0FC26084C2EBE3EE19B540667F13C0914126B1562938B3F34FBE318F1DDA07E31D751E541117339D63DFB037F35494885B7309C9431CAD903B8F6E754D4CFC9B3AA862ED7C417DF8B9C94294846C0C1EA72021DDD892DEC2FB885997AD12D28C4FD1FA6D0484FB7AF28E792D1ED90A829F584F0DA3F31762309F65E7BDA542137CB61780125D16114158E7A17E3A3D3093DC7CE3909C372889F2EC1A4EDC5C002118775EB94D41087FCFFEF408620E00D08A63AB9B465024F2EDC773625DD8E477EF30AA02A237CA5163802F8294660229E53E109A4BCB6AF2B631EB0B20820FFF3365A9D831E875DD3F5F11547A8FBBC12B47DDEE43CE870F96E75BC36151F103D68D624563C3BFE1FB6AEC9AAFC620121612425CC358E945BDE867406079D7512DF8784F4FCFE01EBA3C5077F6E22433034043D5662D2EA13691C74F48875C9701F81CD46CA7984D723891F3A6781E453C5643206FAE40D0F37F202C52F7EABB436B60759816E136EE53D126BFB8386E22D4682D87D8E891ECD47A9E202F35BD3B46EE1D1CAB33771356CFA7D1BB2B92029240EEB889C95EB4809A22C46EC2E6F744458058A71CF67FAC958E69939FD10559630116CE26D18B0E0581BEF1F63663504F07CCC8EB001FEA6166BCF04344C6F18A05F5E7355056E8A63747C2E80ED653346FCD5D0B470D3EEBF6DCBA81D3143EA1EDAE458A32402A69880C018BF98EF408A3EC81956A444EB10EE289215E4FC3C2B8F9E89F3E114C8C1D14932095C3E5C07A60E9EC5779AC0AE8C81CC052B030186669A312318AF6C01D7675BC827EBDD3335F3E2019E3022FC6D0D44A8DA8058CEF61133E94DB7ECB6E0D42D9A5A34ECBC8A52A7E9FEFEB52383AC58D5EF46EF436B9B39667D8011F04F00B8DFC7AE847C704C7CFAA1CE5A4A2BC3C5D9E8E43E1212A6CA2B97093DE431710AAA3B534F5F8129A13F1EB5A7C5EA08DAA94CE674877F738B7C6F18B1CC942045CEE334EDAE110CB96F552DDF5DC19893A3C5C3C6B7D3D0A756F52304A1A0FE368D38DEA15570346C5B5155C74E0FCAC842A8D5F368B56F15C8DF7AC08C2E3E5DAB9348F8B594CFA36CCCE354B23FDDBDA98DCF16B38C61E4D299760918DC6C9907BE216F6466EE0C4C107EA4E77D1EA34E3E005DEAC4B067ACCC2D4861C2060D467B174C1B206821010FA16B5BCEEF40D66E596FEC149165F0D2C3278FCE443A91C3A4490856EAD53A0FA7B074978B5FA872CC03733053CB19331C02F2B0E244EE88A9B69E3C32ECA4835C43D0BCE8FFAC3E828144F6D905324FCC047B69909D3475B04FBBBE8D1BBA3346BBF1F37470F509530EB9180D8E85E620794D6607F9CE2AE83D999115A734479E1ED28DDF3F6392CF4D826A7780DF16719CD36181C674BA16848379D9CCE1B34013034DE2AFD431CF7EECD8D1764290F312B3DA6FFD01CBC6C472D73CB906A9A1B143190E4EDC7F6B354E117B30E6CF06F810F41DD35F0EC467558DB802796DBE9CED04E4A0F1FBE5132C79A7684B2DD4110DADDAD15EFD9E84273674A5FC5F396F066F56235C345A4E4917269BECD166DEE55849DACE8D30BF43300C250F7F1A27E89EA9523B9861492FD791F251BEF790A3D2AA3F6E64C878B77F93B8F3F30AEC475BBBC30C19572E9454F594405CA641A40211E44982A07EA0053EC0CE75A9EBAC7B06324CE3DCA6C3D87E25949415BE3289B463BEA2CC4AF3C068F268DAF17F74E752A85894A9E869DE2619819CEEE07F078118EB3031988A54DF15F48BD27B0AD6B76401FAD265CA075293EC3F675C65949EE26C7116096A9CAB27EE7E948EAAD39C2C2000489CE00B706194900BAE6932005F04B9EFE20639F441B5450B38AB4D345AE57A7A90971CC4216BC0FD32B7E28B18728D818C64D06ED85DE047629F9CEA9873DB6B9D34527CBDA56BAF4F91F0F4429E2775F6AFC232D583F8B194D1E66499F22E4271D11B911372639E4691344086406FDF9420E9A2F4366C4B39E57D51038577EF17152902545879A3EE63B01A768C9FD303A3C5D190B3FAEA6AA47FA1677A37C0BCBD87598A24991E1EFA4E2D9BD1C56318D41E37C7A51B4F38BFF1A942D9267B734D79F61383D2BCA132351B6579278FA636C28FB5F92093D7A5B9466921D7182070D16EE0283B1C195BDB3468B46F2AA1E1F770D64717C915677F8CADCF2B779226497F27AAE13159FFC6065877E9B768A9D1F43260189A78338C95B3778872A86990D68657F03A58268C048D65C38CE7C8D866D684177761008EB63D36A7077CE25810A8F3C36735E658F2A065513CE1E498137B151497C4CA42348749B70BE1697EA2A3C2141B7315A50AFDF7927B8AFA0EF99E613637C09ABE455C1208FD535E32634190350F752E626B2A019AE4DD597D777CC201510C7CCCB7B7E5623D33F8162E01BB14DC177435AC75A2173179585BBE553C7ECD460FB90D6AB398905F12F793530169A7BFF1A8FC6D21714B47266321FEBDF1ED328673757FBEEC4489E5E03D89410ED67D7DB6611F141C5E595EBF8A5F0B3A331643FF2912A77EC7DCA9499E2BC143FA80FD49A5249EEB03FC03AA812012012DA96B5CDD322491070A68A8BA0DD5132EFABB40AE0916E632537332AD7C7F114F2799D897FC38A40AFCB84974E6D67F4156AE1C9886E6664A4BFB5B1D58C4886CA068903C1D2569C8C251F67BD82617BD4BABE0ADCCCD92031CD1BC8E7060D6C3C58A23EDF7179AB8524A0297360DAD6F06B4B72313DE4BD88B76EA71358424D72FE3724CC9D05529BBA4A924AD2624B62BB5EC23AFD6BC615D5BB962DFEE3820A0BA26D5D8FFC45F402F0AD44C381F040C56AC488AC120C6B258669D9383F6025546FFEB06154EE3CB65E620F095E432B683EEB8D08D53F4B905FBC4618E3E25D02C59030B7989AB61E959BF4562D7657458AE8A133B88BBE2399F4E9693E9C21BCFFA5FAE4CE6ED6C5131961FF90D085232FB9888F02A60C260272FD4B3CB6698696231F276398332FC3A686DA5A9A277783EAF9175586D41099C5DF6FBAA17CA594CE4A3E1C992DCA117053DFF93607F5AFC5F00343509A56D85CA9A59CCD1BA2F97B313B5CFEC753900EA3323AD047958321C17F188C419FE55C7040B290FD9738ABA72A0CBA755D4BA7D9AE45B264874646D8059DC58BFBD4DE0C8AF5EA6F929215BB9724E6F50E8C4159FDDC9384D7BB58003D074618640997F5B8039F2CD9FE19F5B537B466BC0A06B0C72B55120AF32604541078197CA157C839EF7F9EC37BAC72F1A401EB50C7E3F24B23B4A0613FFC7550A75523F2030A5816DAE354414F471812DD2A3FA09E52F03A59B576D4A3BABE21F2A319F219C9CA2D8D65B99121314CC39796CE960AB6980FAACDB224D42DD7740B3F390A9C81988496E69EF9707AC0AB6CF2B7FE43C11DB2CD3BDB405FA42483147BF161A61758BDCD348F6256D6D3C4F46012C318EBFB1B9EE94D5535B2FE5FF9D237A3924E49670B762757E34F553A8525EE8245CB7DEAE2E1C5523A71B808994C824CD8AE34EFEE21E79440E997DC560C2CE282D50B5488562E6E7EC70A0DFD8418DA95FCCCC94B77A0BE112D34646C952583B71218C6B5AE75300505C70A9FD8D0C4D26CA4A9721BD5C1AF430613858DA4DB8287FD8FFA9C49C125982B43D4E156F3EBEE89B6D791A5327412A3D69D31D9F4EA51F6BA69E9172086511AC084F1C6287990AB6AD0E63CAED90661745C4ECA69D1BB049CE10B36C50993BC40FD0C7DC69C97CE9D7FA0635D5430003C26652D652A4AC88265B80902CA94721D2066FF957A56EE3B01BEABA352DDDD6CAB06B0C02DDD853EE7CDD01F2CCBAAE398622B03ACF37F4F737CA10C9B4090E3755D6B6C38BF1260FEF30CD1DFA30F113D7F606C4C53435260CA18E2F80A49DD31E5971243294F895D4A5696D977A0382A6DAF70C90DD2954AC3326FF2426245684D17D4C153A586B02596DE3B6C1F5AB94783082711032F95127C988E5964F99239866FA61FE20E88EC060D8DC9D874128AB9AAC28954B70E2650297AC9744913102000B712D89EB6603BCC9A2BCB96730E1FA426B3B82F3843DB9EF28016309BE5BA6C3782D6F51D2695EBB1E3725C512ECE4985FB9CD9B07BA74F39E2FEA9D4D6CB2747C7D279F9A2066D41F036EFE7ABCA89CD29242900E2A59C6E3743E7C87D9799BEA15B5AE706BDE2A0EA92224750D6DFA88BDE1F43EE4BEE0EF37D1411906EAAD7049A17E35E9EA3BEEABA0C6EB81F38E9CF39B0DC24F91E593A39500B9920F4A3B5A7985E1E0CF43E168B3CFA7C878EDBFE08647F9ABCC8D557CDD1EBF8071D306A9EA4BA343C3DB8F14A54566882AFB4CFE30000000000000000000000000000000000050C11181D26AF2860129C08A1A9C7A7BB3120B3E40AFA1A4A09050C8483E7511FABF3285544D4CE3F41401DAB8C17DA547F6777A72519F6EEAAC83016FA0E0FB0B33329DD02AB8EB1F291758074EBB5B7C4C102B75BA422821E6755B37B914D689D84808A89CF88F69A446F489A260BA03CA52A4AA14E8BCF4BFE5134DD2918A88D67329B9BADC6ADA4A3071FD21CFC45235FA0A1B82D91C5877F10AE087464251C8899732AA7FC8F6C0A5BEAF4FA41E64CA97932925A06E218272500249577705804C6DD9F0F61DEE6AAE096BE0AE5E67923137933FE4D61E9A88DFD5B3BD75AEEAF5018A5153985E2837AD1AAD5EED91620D935EB9982DD2364B5413F490BF251FC783503FA146300E6ADAE0682E0597C3839C645DBE855919BB1CB80C3DC6E233909017BB31F5ADAEE05CE442EEF594FC15FEC3A2B4B81ECAAD1340B0677F27009290AB3AB8788556389047F63C2CE9390658E151CA85BAAE45ED2FE12B6667967F6B772EE683AC2E7347C7B0EFA332B3354B5043CB86200F8E4249F68030844D00A86FAA7B79A4129AD676D1E9D58828A1AF4C6BD68C29CC23002E0A0313500BA717B8756D4A18E41E381DF8D7A999A153876DB876CA4A508486A4F331CAC9CB3E7C416C6329713CAB76E1C8B63A8CAD46F8EB1E65116F89A3B4EB8FAA14A73097CA71AEA3220BE7FB7FE64919893930445D962C309E23332E4B3ED8CA768EF0ED46EAAB199827AD628A1BC20CCD9F61BEF67F7FCB017300EBC7493A7CCDAEDBFCA5F91E80B80DECBFD9EAD9BF22FE16B563512C7383D34801C504202D7A0E19821EC8495016362EDAC165904D2BBAC484DE1D4112C3A3E6EA56A78785B7CAF2A44B5BC8BECBC50BF4B521C1D086086FEB009C06ACB8FA0F53E7654FB02AD7898E35E5F3A7DCFC50124BA1F30178C707F4D36E4E7758C4CF82747753CC30A836311794A6A9017F53ABD17A1C9647AB38BA56AAC83C1812DEE8A5A75C5CC958780A3E9C3C1F39729BD365948F7FCD8104CF09660060FBAD2BE9B8D8E5BDD22286EB0BFD4010681AE7928D0FC008E21C8F877D97B5B9C7A06C02530FBC6A9D6FCEDFEDF68A9682177757CDDDFFA6CB9086B8330E61851E2761D84DA37635EA8441E3B23FD165CCEA562B0A3616B30EE5FAE00F76D6801B22F2215D80829E01DB2C0743E3074CF26C96B0EDDF97D79FB9C7FFE9B5CDB891F9E61FEFE7E1CBD28FE25B7858921C8C99C45A84B50A8233037DACC20BEEEBB9B22089DDAF2EBF0698498DA694F75ED2463D09BA2C757A986B8CA556CDF46CBCDF288C078041D497242F66411F47F35A21918855F105F24686076FA21BC1283F17245A7122A848B4BC10D996B2C5161FCE0336B2EC747A4A07FA9851AC5423D1EFC4B524E795B2E4BFFD1C5CD21F5FEC954824DCC53BC3883A7F571A9323DFDD2682C4A4C54E8862F347C9A8897779170B257AD26D90121DDE722A3F214A44CF6C5A5DDB2452A2471EBE7FC8D0EF7F1EDC7920CB42A71E4DB49A0168D51843F47D17BADE50DCB340E5F7B7E5B6A6C3AFE0FB26B5EA172A4011EEE838E5634E521483C6EDBE9994B0658406ED8F4998C7B4E869845CD16CC4368DA3BC1B025A6FFAFBF540133C372D452DD831DCAD39D61CCED0A0AD193FA9886EAC749001E3BEAD5A7962275FC62298A1BD054F4BD97ACAB2BBFDC355C73509D98B6DE5B4CD774BDCAF1398532BB3DB56524CC047ABDE6880C3B282FCE0FB2AD7E4C5F7BC138B48D194E8C8036DF4B9F3949E912AFE5D2734662F27583193D0FBA2B73C1A0D012DB853BBBE4383F6C391F3220E1B5761C337A054FC9FDF09C01864B87324A90C776EFBF5D34A68DEE38EBAACCBB61B4C79A58CC848184F605D43CF9D40BE90C1FBCF6735270132B59A636B16ED28111246270AF32EA2CB7A42A084005AEBB6161002E65B37217361BC269F5ED12F7D50613C82934A6D1D98D1308AC82827B7504F3FD351E0ACA1C62843C9219023FD092692BA4B83BE198EA + +count = 43 +seed = 38FFDE9B60DEDB5BBFAD6C52AA02EF6D49369BF276C99E588D796A4F260E0FF0A65C96C35863BAACFFD9B212EC305E7F +mlen = 1452 +msg = ECA4505D43235F274D902464F4E763312BD11060F908621A063409EB42FAA6BB5E20FACD87B8FF41767C20F69B1F7E05D5F3A957F48DEA57DCC91824FA48DA6DDBDE7E3327A0A8D46A47606EDA01E67CEA1F29BDC5FBA446DE60541DBED6F73D1FC5F49BD77D45285D3D8CA93F6DF25AEEF9324BEDB40E800ACB49794AB05E6D0AEB11A5994FBA36DABB9559CD93CF522174061C116CF31874A18C46689FB8C075079DFAF73EA0EA7FAADD47AD8EF68C06AF9738B41BE771020FEDB79CA3D0165427B58E547105FCF82A12B67579D1D3AAB29968817068732CDBC5A2E9E8D55D17468D03F38D564F5AC6EFE1538E4A680E9E15E35AB54D07B6B58EC9EA7815CCF29F4F880CBF1946F39556BDC2BBC78A5134FA7A086DDC146AD9D503A4CA837E0823BF0728453F6B053788C69EFF8D11ACDF5F07282A75CBD17F2AED58E39D862FF056DF17178625234CA7E03D22AAAFC4C07E3FB08F4297B511B10579934D2761FBB600C9454AC05FFF80CFB93DE3B9E0DDD0AB1E494DE477DA2B5635E48D5BED5CE359E66A3AC845826BE2B4BBFA6D825373BB2A4E93AA417648D1CEA755AA4978784D6D9489F6738B4DA03FAEDC659408D9395C934AF774749A498B1406522351F86838865F53CB0157247484FD37EA59BA72FF3226AFF1EEE353ABD34DDD63FCC89387B947027E04A6F4ECCA1EE5F6BD1CA758AA4F796FE839338164B58D8E5D71E6D5CDEEF6B279EF15A7BAD873B12F7C5B3E2817C37BF00802D2534D425D52D0BD5935BF8658E5BD39B5268CC45D0F27CEE5A57300F497E77AF5268970782030E6928281379CB14BB56D2ACD963D189C078C7A60E98A782F9483ECE7B4871A061277186A01E878087381704BD72C63C32CBF2470A561C22A5DD3A1988B7ED0D274182E1B075AF277920B362D612DC7ED82057EBFE51A3CA5A9A9A45DE015C460BE6A48CF67C820813048A1CEA0FC3D7307F802B4FB7E523E7C8555FA56DCF66237F176D3D973C47F55AF93FC4BC92B98B7DE89829B1471DFF53B649CB03B719DB58DAF824DAA2DE570DF6314DCAF5B705557F9D783559277A754F3CD5B783D5A577EBE4A065D320284B01F71540F1986BCD443CF4FD480DBE06EF7710387CB5185DEACB5C2A612BCA275950B8988F247C4B773D8983D87F47D60F5BF80E6E7BAEDEB14B5FFBC46893A81C63F99F511D3E24FA8F7B1BA66A7DB0C1D9ACC6B5010AD725BDC2282D8A24018C975C8B12ED3326F48194D4FF93EBF051204CD224EA39F27D63FE07CFD0162358B412DBFD4715AD049EE5A31638D3111AF2DB7952F3A973646612712A607EA35826249D14CBDE4380D8BC986067B1CC27503449FB128767986A406585C3D40DACA75C27BD36117D2487BAE82CF639ED1FA016ADD279D109B8CDAE59EB31E1F006CB7AF000A267E8582E55375CF6F06D1A47BE9BFA21C8428045B9DF96808AD74D054820A4D0873257EB318A3DC9B6D9585D973E26D435345B4D699A952C3092EEDDD975FB59474212080D03EC489C695F19CBA4D1CAB1AE8D2E2C730B06E657D33722D24222FF7B613B6E8608E8A6003E11C80239FF431B5D8FA52B84B867A581798833590524C7B84EAF6CDA9CA94C5AB8EF55A1262EEC5C37467807C89FF7D075606A3902E7247E9C6646839C18493584D33DB65D6DFC0F23E68C9D13FD57FAF4836C28926693DC3EE372DE27A9D3E4AB4229425EF48CC410F1792A51C9F6FA5316A1D9A7C99979884EF350B4882F6045921CA88D4E44B435C69C1AAC11660971C2A3F6480C79E6E146C0B5CD2371BF5E7486AD7D0BE88D62A2AE8F0D73C17CBAC86FF6BDA55A880B182A5237498E9CB343A9CD82D7784B72473D222E688D13CB81B2908BBA854B9624A11DBE8CEE9C3825C1BFBA476B4D23D0B0C325F1C498A65A3589EA8E8DF8DD9030B279EDE30443CF80367CEEA4A122DC8329E5AD42491CF57EF47AE2B15F9C54120966B95ACD727A4A2B686B00626BC808F43D82D20DEEBCA79B074A7BFF38D2531AB2F726AC7087236EB3FB4BEC8A2D4207DC84C +pk = 2056013961E354EF176843FED2017E616010E951409D250569CB4E21ABCC258D0A40337A4356C3A2E12D9A59DF13DB8F84EC94DC907B6C5B352A1F4931CC0A35F74E4A3749A8FCAF42E14C0B9057F518761A5E437718C1FA15518ED68AD3EFBC7BFF34061F82A331C3C2B59BBA2A7511B3ECC7BB1330344036E73B528BBA9C91F9D01BBF33771367B5A4CB81AD3A1BA3BC47522129F4297A7D80524AF1D18AC8888BD70078E03535408E2E6D784E9B933EFCA2CBDB0623B1F1D9ABA033BD8CF2EBCDE8F85C511912482B70EBCB5194E0C465EC4969A1627756034B997FE3B43E521A02ECD0F569B036E9D807FBADA8B40EB6B45AE85884A4CE670E488D9999204233DD883B8CBFD9444A6EA11E99866E9E9011DB6B69168BF7CB5AC96A7D813F878CFEBDE0433DE1DF957D467874E8558DC6E87E6247CC8F261CAF3E76501EFD85EB15FC4A0C260CB71D174BB002883645B8AF069DCBC079880372C60540F2D9C2383610731C89025CABECBD5AC4EFE7B27861840CF6D75E9CC8A8B597CA1987A06253D37872615AE0EFA11E8763E97427F6FA9EC64FC9E570F847FF311C9B7C30EE4C72900C6D555C8FA4DA578C6BAE03FC6695C64BE2D7FE41B89448D884838BA40C7510105E9DBC9D66541C71291A2594DA996C5E0D1A98CB5546E35BAE33B89B928C196368896E3591685E64065525C4D4833D6AD5E4ED0A22DE610075C2BE1BBDA9B0762FC1C8AF8C0A76CD5401601550A5AF53F6330B1F82BBFCF33C6B7BF1A274A5D4C0DF6DBD485B8BBE9FDE49F59E92FF90A15B287F60FF062F0573C0B1D3A92159A3157AC058F68DB3B01013DC0554BD57B3D314EB648465C79F1C3310733A9BFCC0D083FCBF9EAFEF344430E03026EEA7F0D198EAFD988440B1F850EC45D42814DBDF9C35DAE4F1D97FE223DAD0329D7BB0034A90F4DD828DC80BE8B9DE2183D24C6D666C809AC3ADB276BCD0FF88FFDE554DB7C67CEEC7B799A6BCDD0621289BA3861A0AAD8E748FE8D759D7BFE6911E1F7900CA89FB19A382D43078DE6A489B3DF89C95EE8F1AD8576783F1D985E173A60620B1591B127031D3383E741A107106DE3FDA589B98ACD2683F8C47FA9F9A769A1BF9FD1695E3549F5ACE4031A5B55CC26E4AE4ABE025A0E224654D00BFB5BFBA038AF0D3C53B391756C0B01E8A5DF5FDCF431ADBE2B07B33179DA99377058E33F587B1F8733EC4523DB0A40D881A1299B6E78FAE98E40D9DB84641395C8CCC731270CDC51081D08B34789D2B579A24FE30542E32E0322220E0979104442304ACFF7218CF98FF6426CF1989A6644B154A1B9EFCFD99003DADCE31473371D256DEFD18B4A5081764B272294683FC4C4317F9439D519993C4FE33211F778C48BAF3A190D88A342F7BB0EBC21AA78C699815BD453A96015C667A669D5CB28486FF7BEAD59B5C3EA6124C387AAB8BE54AB9E5A00FA96086C42445F7FA2CC2B3D4BDDB1EB1AE872ED3425A54CA5BB7391273A4EF19993CCCD24CB558811713CCBD9C7F57509772B5BA5742D4C117143798DA9170895B63C1C2A033D335EC66DF352AFF8FA0CEF1EC4342103FC9A816635215F64CFF2E7F8448F149BF71D74948950E80403337C03B58A9D1B299E371141BD84BF511F81ACFCCBA2D3E93219BDA2AD4973C1BA7037E74E260740796C761C89554B737DAF8FB9F1E366E44CCE7DB998697E3C455E4A460BFF4B026744C78A9C4963480BC01EFC47CEF995D5F04F81BAD8332512751F83453E6441DA96C1F19542C023B5557879F13F27E2B86239F8237F5EF0632A4866C79DC3D86DB93401AF70F7654ED17A281E0C2803B6850EFF41FA58960A2F6AA17542D7FBBE8D52833802248833A2A6ED1EACCCA0E50083111251C0A590ADC03F01354868FE531DC057B680EF9C369681EB40E9DDBB62A8AB151EAFEC4713DACD429DC70B3478BBC120342D55DE8EBCA9B8D0520424C89C993509AEE00789D48E82E1325E13FD48CBB2C06F96AB42D7689D419AAF8224B4A7D79CF75EC342787BAC812A9D7EFA0C08C536C7B75A20197D5DCD2488EA0ABEA753E3DC20F50E62C088350CB0D8CA11A24D12ED566896430B250E80EB1BE18B85408618AD4233773671FC0494E0A52C02AF0A7EEF4CBB1F781DDD35EE1C356D58D0F99087B676F6F47312302E948F2B4D9094540FD53D494725E7E4B1ACDF047F5E404EBA798E757F1E4E9A7B27C7947BAC27221ACF18C2A5608C8709D89EEFB39848A9392BA6E9D326418048D7A222A199B3B2A6B3DE9442CC71630FCD1966D2A8CA834D0133C26C282021822D0A4C21DDD36378C9F64C06B310C1DFE5A9030F8BD9DD0B4293E9CF4B1F51060777A77E7E880B6E7E8F53A3F531B6B5BE54BA24019B3CBB77D3458DADE4D502A3B5163FBBEA38AB673D0CCB71E1912B5CD82B348FB8D0F3BE32BFD0BD1D8B9CB1619AC53D08FD5F8CCD63D84B42DDBDF3810AA999C20F46F659DF82A70E67808673E24382AA2DB5019E45CD039E88CE069A4DD3D975235B77393F29152083D155E3A03211C16B78946E0F177F3C40E97A9E23D3B11CF1E252A2CBC2630CEE4464731555F102566F044786EFB5F066466A2951E7F23B56CEF0DF0FBE4FFF018058948F9457DAC80D83DD3C6A96D99E3C14D8C50A09AD6DA7A49D1B265575F73E100443079AC9A6BD54CCBB0537C13F84AEA86AEFD6BDA282118FB1C788351CF5923103D6C0B0BF53E0BC38E56F237A7E3BB72DF168517ECBAAC27DDF9E62A +sk = 2056013961E354EF176843FED2017E616010E951409D250569CB4E21ABCC258DC23E3BAEE1E216B4C3E7A81A1895A01B9A9F0D8738522413C84235D81DB88DDBF581DCEEC342879CFA360C7397F27099550CE28E0862F38E982251327879C598EC7282908DF0E41E290BFC84AC56754677BF4CDB8631FA8E83BEC045E1D79C5D26534255072671356268657046775414871772017644075401506356427702520615142758300228476022465478216370470736012571807602168141677805853066340313746867048776762706057852538466587878687744081608646750556006378177354282022088270783224171417643614856557276127463458833257538121440130578130677604365161468274412744762810444642328471702176372341602881326068402425624428036146252177886620765702504660806775716833188536466807532876715110018885180424656717741266747736465723887754112656707227524815360216170822735753754258865245523142431423488367365777570412418730731727768620686460703334354658865165727278314527043852301131124476223230285156778347405468058147818273272824750821026431167620141531147734057638771057736407658442482707131840130187717552464638434514524088822012312045626524520185086554056617083126853522751154467608716856754082650400345741161003083372006887716116118614631678558528684583338674825432861416577682461680141852160411043380643024020836672655653018214110384728154586665243077165208178600435043116374267302132021544687107312251151634387573761736436845250053503047256237345386346130223511351434222584516237164483380520247552238734010840632107870462481384564341513126684728172142785402235730110430855447122536413567205817276203723372168377834281311664643104211067235665818387274732713002621841724522823434028742657451132311331727344700778612100647737441131804045121850265025408304761133538253688527028316554541107611470300808330268753631720125173455335447080651644444072102787102468667846484200426238451485800718135711232802278064661102763026848105300888212084434505812875617757841563216615076440868427442750341636035064008400520148437362447548104022835471545833784363706466880763464112571845636217182882840142121376364710352566568213087072487742117307635751335640680328677686514477524370461755256813687445452170251472577358371634201537081250262700654410365131327170150125654282875083347066088444560326532285002054613271521611717530436070735418337541873647305304652650321668403608073088204088158320103716536117716747015617410383360244121485335205246256411161453083706857052041833443425265408448228278722135205662647485256577311873037541135770033748300214146407048824036820178544831334503807253431703463816302415427144188605110450488518882755332462213563681741054082220118636052337341451645306644006628618157152754686584585858878108652171011026744423654185624005748467475421546875646636053603068761868126574787455331307325417370831055117314122483736731265263687204010400148026505518707052751248538436760866406675132131675473428714181104363575455620246110565573244304488346700623320800110835663107780468431126875227017825443053086448756543748853573177772031177158018603261216184630445585003887246700464372036378084823581555567840775412834605421548815263376258757772032307252031854825402874201162041666280353450F2249D1D8061AD62249C813B4131289E3ADC2A5B85D06EA4690AAC87AF8AFE3DC5CDD0B815E66F57E34409203856B3546A11F03C65A8CDB4D764094A5185B8E6C4695D6FCFBEF6EFBFC80E10E8B5BD7DD17E279D527CDCA4B96BEBE7EFAAEF5D51B5B5D7B2C6EC0DBA232E054A68D3D974AA4E6C47732967CDEAE0397C9EFD7F7803BFAABBE96AD1EAB71341B9374AF6E43F5B35CF2435E89DA7E5E27A09A5EAD322CE14280D9C056FBB9316C2DBECF9FD87124FCADD2376DE88ABA7B130B3445E4DB0C50B3B5B8750CFCC1ABBAC22798948A084D99FD623AD73E3868B5852C95F615C665BC64141CAD1CBF6A38699840C9BEFE8510E569467540BBA77A962D3C0AF925C6896FE5A746AAA6DAB8C618CF9D70A62AEC444A95F5FAA979E0D4E111AD094925AB7ED0E5426CC79289BCEED4F20CE2CF657A1863EDC16D92947338CE8E37D53F2E906ADBC3D763BF6B265AB637EC96054A29424CB686126F7E3C81C6B5F6911B9510FC21143B164D935596912228C3DFEF665B308A1F4581ED083CB717467E75584A50CE0BBA576CDA70D0726308446F8D4EBA2FD216457F5DCDD596EB8B485F4838188B87F17EC73E10936004899B13275E35002ABAE0DE6084C6F05635A489177CB512D502427C4D73BEEB6CE477D80998CA650B67907BAE690C67760A93B69AEE7ECFE5961FC8F66524ED58E01FF3A4E18C762D7E4C9D43F58D3290E47BBE4812200366034A484D8A78AA5095BA5425F70318A199973C3B2E6B9D2B8D4EA5727D56422647CE18CA045148A1998B3D69BB99E391394999F256F04DA5D7CEDDAF7C207F16721A5A938AA6E1916221D24D12E956EE63D0F4F6D7DCDBA7793574C2CFF9D9C5B808D9C7F8C6DD7A9FACC8BC23B5DE42F7E51E3362C82BF93A99A86ED6CEF6CEDA5AE458CE348495EB023C471747D4390D0D9476B126F80C478CCE8C81181FA962C0A15A06137858EB4E4B0858A76426F5F5A0CC3357B665BE0C52A5DACB32BE2ED3FAC17D38BF3F2982D593554CAADE5EFC8F839E53F3FF56EA44BDCEDD92AFA4DD9375C97DF87E02CB5979DAC29C3D631F7B0E382CB001D4546795231FAA08CC9C7E42DBF59A589A791954728687CBFBE17399AF078790A121EA5A07B77CD81C3BB012BAB835B90D2278222ABE97AC7475495CFA76A57D28B995E1AFCB9DEF7305777347DF580008A277D2D61E8D8E88CC72A913E5D40C8D9A2CE9D892843C1A800FBE021123E3D9EFA905BEE8DCA63048C4FD98E5ED8A72BD506519D3C05E79E7557FF325176CB87D79CE86725D93525947901B6A762D928B6BBF8B7907C923625430DD08EBFFEE6FC2E56FBE2F72E9EACB5EDC3E0D506698F6DAB4A8CE3F1D0E0E4CA2C28E603EDE9FEF86760C6B02DF5977D6AF0C00DC86B8AFC04DCC327906D2275066087DC309E3C72C2EE66BD8E0E6A37FB7BE4835D21BA3479E8314B6AD8D5C9C3E5275A43AF4DFFEADF7561E76282A65171A10DBA1E8896C09FA374F24E031312CCE67F7415F74802A73F29111D21DD615428EF29B4A74AEB3F7739BAED38C0B335DB1691A895B35309661AE19E6DD413BAB36A9EC8C3230049331E66EB894DE9DC87B9ED50A101BB4C5F844C64E6BCEF97775FD581B6A989DE2B19BCE33F8701179D5EF390395255A6FD0ECCA066E1A97A6041D86682EF209C2D499F0A9AC5323193D31661BCCB7E4126028BA4940BA3122DD3FE195B063455E675561F1A8B0BCC361AA443CBA494BD4FCE6968EF5719B2A9BB448B365643216147563E4C40516728368B0CAAEA71F75ABDA5C7BFBF721C4878D3D698433441D31D406F5C9300BE0C12F5A03F57C9E8CFCD60552A76119609AFA5DD6C9A068789349FE42CF2026A65F75A5CF8CF84F0A8AF7875C7099B7DB3824FBA27DE54EBC75A89D075FAB4B01FFC621C0577A50BD95AEF9FC760C59AB85AA50EDD193181E12E915A962F10CF76D94B38621672AB11874E981D82D37E2E888210576D6A20053667279062B439B9AE28F7455D48A07D5B51A59360022233B1D103C7D093DB0A7453C80B6D718488A73C69CD3CCA20C2440A145C3FC12083070B1DEB74DC82977A0E32EDC7B1C9955DFE4C56E56A1249660D66DB80799AF5748E3FBAB1D1AEB19AF585DC4867A83B048D7B07FD13FBE9D993631348E4CB607E53A85257F3BE394D040B9F51B855C51B0743373BDB78734696E45FBB8E969B9EB49C8A5FC6DAA41E382E01F4A65A11C3F8B7FD00C8391DE7B7C1FE6AF1070E0FBC4F25E76163399CE1F0B0B972560A0EFFDC6A41720BC36DC92838D6EA4EF748351C25B86AD50F4621CFA4C23E3DDF1658C319E53DF54A21515BDFB235565164D6F60ADF6D4727BFD14F23F2A8D9502C88D3DFD42569CB26DEE1ACB80E2C3DCE8DF47194314FE5CA36288A0E34DF94974084E84638E4FE93B7BA667F24A24567090D6077C1EB305662172BE51C28D09E67669F578F4B348382736EB8BE429C7D7EB605AD6B644A3D61D9E3A4644B2082B0E8B898C534D940FC51199890A39052F640F678AD1D8699F85E16387C9D55222D6455416012C79A52C304130BE4715AC4344ACF871DDCE84B64D89CD1A6DC6C49C1EEEAD6D2131E3CDBBCE558517518FAA3083B41A7F8E06CDCC2D9ADF41B3D0C930ECE4F8B2E90B912625FA25A4248E152CCB2A02B944F2BA8E27155D1DD74676CAD9286E924AA74CE920842522BE9846064758844572D549B560FE1BEB97BE48EB8250E4060170FEEE3E1E3C2CB37D6E8E2F1165838748CEFB92B970D7A8B7FC94F17490C2A13D3911CC513E39D6E1E5CC98375857A8655C0E8982F4ADB61CF971F32B45A298C3056D6CF37DAC52C426264F1B951121BEA66ACA540FB43051F83C7B4C2FDB7E9B453165D2FA9985D04900AEB9C3CCB2AB525A1832948BEDD06AE0EEE3B9236FCEE677EC5633E365B25C0DD91FFA8F55EB7E57E027A46D3855E18452C7F9FABBA1ABB49D8F7E9FEB9C1AD748C1C7A116710F942FD82C1C35363DA8DD2324BB9389276AC563B64D5BC2A3B741524575F8FB67053BE38F5884743683B7568E735DCDFC34018F965FB6E35716124851C09ACC7D88CE361E3DA67F8BE8A4ADE9DBCEA310AD97BB6097977EBD37EB5FCC78107348549FAD7F6DBA9505F6D38C5E45309996107AF399AA838297BD0411AA3ED16791AFC2281F19E67C90C1DE491353D6099F34D77E2B230AEDB0A0AC64AEE1E110D4AA645C6C33A87CC476335EEDD6C26ED6CCD64EBFBF494A27F76B407A980B7353011D355DDC10FF5FA5CEEF9FC33AD951EA878F7CB8550ADCC1F322C2B87F9AA7F4293D65B5155EC3A636B1D1E401CD32C36E1ACD3C7FFDD1AC1DA8A84CF7AC10B654D5C5490BD19347AF835EB55130D42BE79D39516CFCCC2334654AF5B58E5A73A5558C20408E9CD1486EDF9DD975F3FF317FC2FDBDB66A3501CE488E4C5826BCE2C691C8EC21DD058EEE435C243B7F843251EE14FBBEC0C508EFFC2375B3DE3294BFBB9A088568674BF2B37F59FC467BE5C8FC6 +smlen = 4761 +sm = 6B451FE668CC7E6E3CFC03DAC02FC8380219D58024E5B58254C5418A6C4C400EC2C301D4BB339CA9AD7C14371B96BAA9448B7C7927E34D7B3ED2C3C24586688ED8A55DC7A5F7259AB38EBEA779526FC8A4B57FFA11EB6DF6C84DAEC6C1D031C85005A4A74F4E0A1D20310D4F0F4D6FB54EA8F5ECD1DF5813EBEC406C43994BDA489E5B8D501CA68DDBC7E2B0D5DACE27784573D0F502084BCAA5A43FB77904545787BBF40FACD60001CEB3A0C78B37984BCC9F7959F2539DC2847960F56563BDE8D230EC4D5FDEBFA1E5BCB00F97B609FEA542DD39EA8E41FC56B8E0A310148F2ED3C01A707C3E69A221EBC594FBF33E15E5D062DDBCFD78119AFF0C4654F47F0E812EBFDE9CEF0DE6D859000BCF1C8CA8BDFF12F936F22D82FA4C873FE5AE1DE4605DF52D746A08D16FEA536BBF99055D6199A5BBF30CD458FC207979F6A31DA7F200E82E4C1F2A33FA16D0C814E0A910536965DDC7E2FB29D8B0B55ACADA6D18DC46F0C710344648E7F4AEE02B452343A9B7C7CB61E76CBDF369D9D8C68AE6887E2E8FE1F3A8DFA9E90B6FB16D2FD0FA2D09EAC1588F747A172930F37BFCE2C137E1A544C69435C8DF5AC59D7A32C0A2274F20421B240C8503616557B7278BCC4F85C57E6971FCBF958B8C34FCF8869530EBAC0CB399A56E0DBCB230CE29DC586027C933B764AA3DD5392FC072619478CAD4739BCE6B947BF17E3F23C716AEFE5B68A297E89F0A670DEA00079231524D150732CA6B0CA83F48E97506279BE267BB5DD664E9DA3649CC79802AD8AAB3FE3BFC438F0B79323215EB2090581C12B9FE7CA29AC40382BBE592EB8D7E1F90DF12374AE14CC1147EC663249D6FFE8DF69B90B22F9B43B66426A07E98AA3AF7F74EAD10256D635B9CADD7349B0D6A19697DBB458617D20E1356ABCF1F0A423006CEAFD4F8941AA777783F504A5B245F5C2CDEE2FA63D0342780167209B0EAC433FFFBD5102C2FBF947EA0290B4506DC638275A81A82005477858D7727D2BCF1FEA1355C02C246FC7A2CCF10D3EC6663581040729409FD981BFBEDA7A9B34891F1F77FDD0E72EC71DB3D971721A60EFDC23A5064F46826DAC7C516F8B07BE76D20E316D366B47693EFFA10B814F1DDACBF371FD2E14C62F05C61E944FD23AF37C3F70FFBD74BC7A74B0B32F9CD26D7ED803C215378CF758A85D2D039DFC5F954F169F83656E7DB8E91367028964D25B22783D0E8621943576343FEBEC3A153F5244B9619ECEC718628E1279DF2B0DBB54553943A051A08B9174B17DA77D3F5C7288E10F00D44573643B124EFAF02442CBC618BCEC8E74D9D29389F605B62D83F43BB1EF1C6777CEDB8B3530958B4DD13BAC097EF4395F9707A3C4992FF8F1A30DFD786F239239536BE4D414AA79CB7E7763D3431FF414A9B25024A02F99BB72ED3115A061848E075668A70DEA648540BD361D6C407CC97486B5D4BC7EA5D87C151B0A9381F5B5EC2B25EEFDA35C5506B81B9C4A7380B2A74BB7D5B591D3FBC45A1AE199234097B39489EEC7A651206E756055808D91F81DFC1C4BB21274048ADF640FA23505D2F760768481B3BD27EF7A166C0772A99DEE2266160D13AAA12B1F4133271192A4113FE8CF5667CD899F75F20D50231B13C35996C0334264F458710F04C2DF426970B9B343C2C0A67E3D64E02FEE8341EEAD52FF95AAE13256F0C1740069A41E8718F1F52D9F35B8BB6F9DFC57A72C3150FAD59F9F1008CE6B153A0E06F106D932285705FC57AC3CD9EDB094A3619F6FEBDE7710002AFBEE1F51A573D4778E1C88F44708FCA574CC48F3B1F45632B5AB1F3A58D6ED60431413F294B121E37AFF00CEF107046D7CEF46F389E1371C81FA5C91A6D9381554186713A9DED29329D2A9180E61AAFE9DE11841F9EAAF1C1555613FA7029DC78E171FD07EDE17B476CFAF776AE46E3538A9E640968FAF464EFAB38EEF8E40EB708CCCC869B880B6AE7A55E1F2413DC1D298BB509BEC32008D5816642EFF1779A18C2C55A5E2ADBE7216A8FFC037ADA894A3FEF9F5BD0C3B713FF35EA3C4803CAE9705A476A3D01770964FDCE2ADC47180C9E92FD9F69E88E32CF2CCDCCAE44416DA5B4B07EE21D8ABBB00F17FDB9EC4FC50A9198BFEF23F778869D7940A2F9F5E24207A788676E4CF5E0D7BFBFC2F27BADC4FFE995B80D7FC2DECC00151E8778D9ED901EAA7DA9A3A9535EEEBB38E83F774522BD7B5EB07B92716A06B65C4047EBCF244C5437C3ACE203E5A08FE444553B4C59138BD8051E5855431F07AE431AA6166F46CBD3D853F2B8E6DA8CBD7C8424A0BD5FD307E4E0966B1289BE306369C131ED2BB2BF9F3FBBF21E13603A18C4FA906B65F73E81118538B4F6E7D659D4C46722EDF031BFE3AADCE7D01600770989FF354D092347552BF63290F7FA91414D8ED89FCE1E70D812F2093149CF4C76679847AF027D1D2EBDE2F072C51002FBAC4C0805EA1DCD28601FB11024CBD0637DFB78CD1B1F7BA48B5FC09090730B7B1229C6EE31AE5B9EDAB10F835AD68221309648FEF8DD265E1DB537B5C2175DECCC0429971204F4B9D941AFE17A8D5E29DDC7F0B1703D2AE1B5002B90647A151E703BD48DA183364F9FAD6F1B61866AFE9F26E0042A3BD596A095D7E7C49A8100FE18A24CBF51F97CB9CC4DC5CBC6351F78F43F808E3F1D309FDBA980DC3258534600CF619532819D9A05C5644EA997B01201909D3C01401D7A3605154892EC3840C1D9868539127386808D7F40F57B9042832BF0E33665B30F4D27570406E5507B7AEA1BB32ED834BEBF96361047C6A15890E48E77206C70C8BC26354A038F4ACA3612868E721404AC31F1AA51263E5B25A10523A0B77EAB00D53FA7420411B1DD25E6325784AB56EC2AF5C89A8C2A93C638C5DF1A538B782F9356A5E35C44251D271FE7D4BC01FE9EDAE38B3E244341F60340F50C2AA7ED9F57D9720D9C4B60A2DC3520CCDB5D066D0C446DA9BC96896E85ACDC540268709E522BE0D0CA0C081B581B51FBD38CB5DAFD4BE950284EEE0E09FEFE4544F9A13C1A5EF3A8571412E57F9028376ADDAA18A942B6F9B901780FF7267D140E0E2EF2529EAAC675E77A83A458A1033F4CE79C133F589909A9669CE6AFA99E0CE11D06210E6CE270F0FEB2CCEA01EAB43B8025D52AF46EA25A9AA31D69C977C2D0FB78B675DA8B1726D8CAD5BA7B0521006704D52DB44AE844D62011D4A739232E7E2B581BE8175CED9386E18A30D85C59C22C4B9232287561BC45E6EEE8438189DE9B1EED1C784AB5D076D132D3C55CB7273E9EA906B4C267B587B8DF014034D2F755334D3EB235078CC0F0AA95A5E7004313E9FB4581DD9B7B52C221571BC5A223153C4263C57AC18EAD8F30C81E9CBB7BBC79363AAD3E230AAA4132908322CAE95D945C1A561BCF160D43D2F9218A53936A03CDC796D51F82642B59199C1570089061EDFF714C4EAFB6AE44AAA8ED2F29ADBAD19A81BBC6434CC9DEDE91EEDF5249544E3DBDD5A380F2DF4D8F2DAF487C1503AD1FBF7B2F803BDF0291A109870EEF9D7AAEA4F5F7CC16F0540058A000462B7BF3ED60CB522C32D456FD449BDA200CD9B6B25EFAF8728002936DA19B4D4AFE922C45C2C56CCA7300C7E5BEA2B25266D1FBB38495FA10B4E8149C26B767AC446236668AD90DF92F80AEFC390CFDAA1F34A2AA3BF0E8E88B9DCE6ED78A3F24A0C1EEA715A165D6D2C0FB39723B7B1B1BA72E2555D36B8BBF95118AB5819511E7A2F122D197D7E2056CF661D76004524F1B08D82C15E5AE62A72131AE3F0A71063878F521D77D6DC546690A767AE572E3B8D148B910D1FF3C1A02EFD23961CAD696B893C978433BD1011D16F5851A2520DABDDFF6513109CAF4974BACF427B882A370EC19F4A3C0B6FF91CA009A7E423EE551B5F5BE2C8FCCD57738BB876155D78348CAE6B6D42E5E624BC87CA19C46E8E563277E78AC62DC7CB951F7F9C06F9C0D3245A31E82E58F346F1312FEA3EE7A1454C474A5B515DD3043119DD5400CB7D0B0BF152A0B4994A70A3F8D25FC89410D8BB0978169E3644E6F1E95A96CF5E506DC86F5A96DFF92587E4057AC1059DF1FDFCDC4E2B30CB38969CA6C52D76B96F9DDF9C9649479A2E71D1F2F3DB87BB5AC5E7ABB452016B6FF018A5A5EAFC8E8317393C7375E6ADCED57FF5EE8964422CF247CA1238DDDA234F9C5D2C75F5AD0330C137BCAFCF9AB45FCB9B4BB5DE833348E259C31865E45982F8EF3915DEA8142C5AA2AE0E0390DF346D4F0A3C9E6C6F8BE5E54A1FB209D131BF1D8088480EE1FC5AFC2A061CD60E0B65E1B9D958E40C291140D98A9FC61BB6317923F36AEB1C55C19F05D5D1551E1D754FD67185AC80A372FD18F19F26FAF826892F7A2543CCD378289DA78068F5B654595B5BF25D6E48ADB72EA774CED585E1FD209B3D89251D3026EA31B7CAA12F27DC27DB874DB1A004AAC168C176F7082602F3133090A9741F28DEE7F8B65B41855FD02A1BE891B0340773CD97F5500FC561A5FA19D5C11487779E98717A8A23294462B0B503995A488E82389919C798466DEB6B646F0EC6491E1F462A2322C5510A6DFDC46F424F947CA14C746196C6CF83B7E86C3CCCE4980BF3537808DAFBCBE2B4B75C31D44577393A6BDC2C3E01C34386A7EAFBCD00000000000000000000000000000000000060910141E26ECA4505D43235F274D902464F4E763312BD11060F908621A063409EB42FAA6BB5E20FACD87B8FF41767C20F69B1F7E05D5F3A957F48DEA57DCC91824FA48DA6DDBDE7E3327A0A8D46A47606EDA01E67CEA1F29BDC5FBA446DE60541DBED6F73D1FC5F49BD77D45285D3D8CA93F6DF25AEEF9324BEDB40E800ACB49794AB05E6D0AEB11A5994FBA36DABB9559CD93CF522174061C116CF31874A18C46689FB8C075079DFAF73EA0EA7FAADD47AD8EF68C06AF9738B41BE771020FEDB79CA3D0165427B58E547105FCF82A12B67579D1D3AAB29968817068732CDBC5A2E9E8D55D17468D03F38D564F5AC6EFE1538E4A680E9E15E35AB54D07B6B58EC9EA7815CCF29F4F880CBF1946F39556BDC2BBC78A5134FA7A086DDC146AD9D503A4CA837E0823BF0728453F6B053788C69EFF8D11ACDF5F07282A75CBD17F2AED58E39D862FF056DF17178625234CA7E03D22AAAFC4C07E3FB08F4297B511B10579934D2761FBB600C9454AC05FFF80CFB93DE3B9E0DDD0AB1E494DE477DA2B5635E48D5BED5CE359E66A3AC845826BE2B4BBFA6D825373BB2A4E93AA417648D1CEA755AA4978784D6D9489F6738B4DA03FAEDC659408D9395C934AF774749A498B1406522351F86838865F53CB0157247484FD37EA59BA72FF3226AFF1EEE353ABD34DDD63FCC89387B947027E04A6F4ECCA1EE5F6BD1CA758AA4F796FE839338164B58D8E5D71E6D5CDEEF6B279EF15A7BAD873B12F7C5B3E2817C37BF00802D2534D425D52D0BD5935BF8658E5BD39B5268CC45D0F27CEE5A57300F497E77AF5268970782030E6928281379CB14BB56D2ACD963D189C078C7A60E98A782F9483ECE7B4871A061277186A01E878087381704BD72C63C32CBF2470A561C22A5DD3A1988B7ED0D274182E1B075AF277920B362D612DC7ED82057EBFE51A3CA5A9A9A45DE015C460BE6A48CF67C820813048A1CEA0FC3D7307F802B4FB7E523E7C8555FA56DCF66237F176D3D973C47F55AF93FC4BC92B98B7DE89829B1471DFF53B649CB03B719DB58DAF824DAA2DE570DF6314DCAF5B705557F9D783559277A754F3CD5B783D5A577EBE4A065D320284B01F71540F1986BCD443CF4FD480DBE06EF7710387CB5185DEACB5C2A612BCA275950B8988F247C4B773D8983D87F47D60F5BF80E6E7BAEDEB14B5FFBC46893A81C63F99F511D3E24FA8F7B1BA66A7DB0C1D9ACC6B5010AD725BDC2282D8A24018C975C8B12ED3326F48194D4FF93EBF051204CD224EA39F27D63FE07CFD0162358B412DBFD4715AD049EE5A31638D3111AF2DB7952F3A973646612712A607EA35826249D14CBDE4380D8BC986067B1CC27503449FB128767986A406585C3D40DACA75C27BD36117D2487BAE82CF639ED1FA016ADD279D109B8CDAE59EB31E1F006CB7AF000A267E8582E55375CF6F06D1A47BE9BFA21C8428045B9DF96808AD74D054820A4D0873257EB318A3DC9B6D9585D973E26D435345B4D699A952C3092EEDDD975FB59474212080D03EC489C695F19CBA4D1CAB1AE8D2E2C730B06E657D33722D24222FF7B613B6E8608E8A6003E11C80239FF431B5D8FA52B84B867A581798833590524C7B84EAF6CDA9CA94C5AB8EF55A1262EEC5C37467807C89FF7D075606A3902E7247E9C6646839C18493584D33DB65D6DFC0F23E68C9D13FD57FAF4836C28926693DC3EE372DE27A9D3E4AB4229425EF48CC410F1792A51C9F6FA5316A1D9A7C99979884EF350B4882F6045921CA88D4E44B435C69C1AAC11660971C2A3F6480C79E6E146C0B5CD2371BF5E7486AD7D0BE88D62A2AE8F0D73C17CBAC86FF6BDA55A880B182A5237498E9CB343A9CD82D7784B72473D222E688D13CB81B2908BBA854B9624A11DBE8CEE9C3825C1BFBA476B4D23D0B0C325F1C498A65A3589EA8E8DF8DD9030B279EDE30443CF80367CEEA4A122DC8329E5AD42491CF57EF47AE2B15F9C54120966B95ACD727A4A2B686B00626BC808F43D82D20DEEBCA79B074A7BFF38D2531AB2F726AC7087236EB3FB4BEC8A2D4207DC84C + +count = 44 +seed = ACC98B16DCC9A50EF57F332D66255CA56C2BB679CAE705B4297F1418DA845861448DA6CC5CC458DE6C6E96128EEB2898 +mlen = 1485 +msg = 96E2865A0E602EA4E3C5657A7F761A6F771007989FF885261F5638C14C1BF80AADE34CB956D2B5FA1CE38FDE831423201D3692E8E6F40E68A68C085DBE3C4CD8E35394F74072F44DE98A74E42C9176A86AC06BED8C0CA937DB4C3BF92371106B7A68EA8FDE1D1E082CCF522A397401AD0F8DA6C82BF76EAB8AFE101C7FF023A0FCF015B40ADA0073363E7CB25260C18662D651222A4CCF1B290EE6F7B111B9A963211D67D7674B499449F760352FEEB9FB7265A5F2F7F20C0174802C7F48226D92620D3E009E85B104230C21BA2FB0012DAC4BDF9FD184E09CB3E593EB1F3EEB418A8BF3173E6CB91FD8080C7E80DBE6730833A4A9F22C52716731C7CEA4F70CDE0F81D2D9AAFB6B60820598A7F6AA1B963B7686528E6E7885AE085C3D26C4ACBF9FC15080D972CA841175B343E59FED79AE3CB4DBB4F0D7D463BD3E0C4B2090139145B8D7DB5DB10ABFA51DC909C5CF7809030D72A5090CDC765EECADE2B365F719127548CA601AE0D21E402E18050ACAED30EE13CDDADACC9373A87A218787B585319A7E66FBB13851F7AD0D2BBC1EFE6EFE4F7ED248D844F58B6A5A21FA9295E0044982AF6286DE296550F72B5E416373F1DAC006687DED1E7D40961E5177C207579F25E77BE808A6BA33DCE8A2A6F88E97AE98ECFBEE5296D4A170E3574D9BA592A384CB0545BCFC32B3831C0B736AB77440722299F192DCAD519523995F71F2983BA87AAD2261E6E01C19DCCAE00F8D6914501D1AC3D4AFF0C12FA125ECDCA34DCDD8407F0045F8E8BE0763E19EB007ED4DAE36E30AFB07F8DAA7431B72F4A0A8017B3FDE27123AC3E8EE575F8BE310F68F81B696DB1FE63CCB8D32B899B209B2205956D209BD6E48166BBB4372A607E83C47698DB5AC8F9B40D05F38EFC4A4A1309D999D5CE1E1A5828D56EDA4666995897C8E6362D0B5054F04BCCF79D03852D1003C80CCD55E9F4578D8BB2C8E220A4D7A4E2190024C85C718654CCF174AC96C1BC50EA49F961EE7697C88E6BB718679F1D1F1118376B31A4B8C0471F6D7AEFC5AB426515D1B2CF0EAE66246B3C4132A63C63D7E33EB9DF8D8807215D58F46EE832AD3EC893D74E00C73510B9625F62D4EB5B500EECDBC7D088D3D318077A4A0F7D64ADB13220232C08DA75D23CA7B20CB109C972B7C159863991C32508339558B9383DDFE7E7DDA740E5BED0EBD14ED300C634DB01F359F81A7133669183EB187C17A2C8AB855BFCE73E34A1F59ADB0EC39EC0C7573AD3620A819333EE79D5E09CB8449F91923EF4C5E21549EB7F56075C014E1C3AD2805E682F07BA8AA265745CB600A460069678745FB9638F6709D62D2DAD8DEFDD5A4D0C2AE7401292BD1DA5F40D4CF5D59A403932FFB677237AD74691CAE29FA31B955172EFC5E83C225F2DC0430AB0C909A97BFB468AE182ECF91E9026DE819F3440FBE69B9DE26F812FF3F3CE8037F124AB368B1153C1CC127D140F754C525D4799E1A19D93B90460E6518F0B6936DC6310B7E9E6534B595E00225978214EE5AEB12A6F45B5C73FE86771818843FF7A6B88379C37165D9DAD48AFFD6FBABD11B1FB90AA5A78918B317C5F9B2CED6B9647F130DA9F91E1B1CEB84F6E1618248F06D654E159F71033072F1517064BD96A5C138402771ABE7F39F53A798C2423B748EB7F310485D6376722E204FA33B9740E7FA68364289A677C5C78A19A7707D2549BF9329334478C64351FEA1634388ACD4BE57E4ABE9374A0E999B770CD81B1BF4A8FF300C297B116CEDA1A4A1C1BD5A2275581A0589A46142139FC596A1406D16293076527CDF9AEA2D0919F9678423B7D95B153DD1D9D62B72A12F6491A36604D19E7BB83C476D232769425557D3480623D40B7AC27C0F67D4ED5CA4D487BE915A68352DCB03A3929A4BB795248EBE2FBE0612833D9305A0A31D195718BAC193FC59B880042A7F61358104A919C7E7C210F02A856B8B1057DD8527FD4AE1EA81F9E1BF7C614ED8A312C95154873F86632CBD60C65176F13CAC695BB4C23675331058397D6E96E4F9DEEB859E3937553D94BEDE3C2B9A5EBF00964A49AB294BCCEE09E5A97381D2375941AA775A47F726E9 +pk = ABBCEC70AD82C764E63D72627AD8AC948DAD19017E5BBA517D85C8CF781FBCFC2BCE48A12A5906F93E65AB4E8E5CDD9D4529519A0524FCBCEC7FB0B09F7520F1734AB2DCE312A2766E9C4C1BCEF12B13DE18A274C96C7EA0F909D43598D9DE9EF94FAF8B443999818214464177A92A7CE590E7EE2E297DBC5DC5A68F5337F8514F337982E4053DA4E670E1972A9BA30E564B54A7B0FDD9101C9020B9A17B9C704E05E46916FD88753308CC1ADA5F047137B9A1052738BFB0CA6258F7BA18492A6DA9E3E7854F5CB309CA3764DFEDCB5D15A1096E702E588B97E522B3F30D08DE289B8BA6343883EBA005091D8A56537500C00434FA3A2F42DF0F7C7FB1A238288F004C1F4B8964324AE67DCEE8A492E6E1E287BCC449E083F255708EA04FE3A998A24B5AACA25FEE8A7E585C8F9B184982C093A8D2C6C9DADCA57832C93EB1B438BE1B0D7BF85D12FA8FF22C4DAD4E50E049EFD1964A21B1DF7BE89A237E46CF0EBABCACCFF476C16871DBB1D48EF85ABE489B6AF1535A211B4F4E8CD6D4F3A27DC8CB0712C7B884C843745105BEA67CEE761B6FF9CB10187E1D2BF45AA5613501BDD3585043CBC49A99D0434E4C0E2B23605543D51CF3120BCD984DA0F8DA5F174438250E43A487A6ED607200F45C46547270905DED78BFD588A87841730FB8DCD85F122A1AC02598D7E7AB10DC4EB9887E2CD6B38041EA689ED18B3972D35EA8C3F8DBB86C3D159AD4B61B8D0F24EC7A81F38E54F74797DA42AA56B7D52F0CDEB637E4D062C7F2BA8CEAAA5CDF1B38F8A1B9A32399BF0495E999E93BB5B78EB04941D80FA6E51AE0E7528269EA41D31137B106746FDCC1201DD66668EBFBC622CB3F83D71E79203BD94A399ACD439707092E13B8D8F3F5E8286D35AA38FC90DC81A1495A76F534CFA2F5F0E96D12C1F54453AAAF9E34B9EEF992217203C3672F8B714E660C77E1D24B85E8635FA489F9665E94ABB7184AC04F4C65AE0859781B50C65CE2BA4D0282A57D4D346D568286EAFE3B5A76C8A622E0285813C247702F20CAA5021BD9B042A87BD7CD2D26B0D39F914D442AFE9E8F94819BBB5CA18639C24D77D7DFB9EC75D301416E53E4E69B333B9EAEE0C3F689C0125FB7835ACA58CAAA659CEAC570A461849D50274D1BADFA4DF22A20D5D4C9AAAA07BE65F6E3A2AE719B11D89878D24D00EA8EDF6B9E213B3D6A462A576E6D2E2B1C9F8A49E52946D7AAC0B35BCEB9AC7F54D847B857BC30DAE9236E59850EBC045B092764BE4A75655B1F351816D794A3876186BFB369F1089AF7B2163CFF47C9F29ADD52F23DFAEA49FC8BAC6F12CE45605E9112E489F8A5518C56D873EC1CA5A88FB8CF8965140C33EEC26D15974017C9DFD9A4F13A8A273FA01D7772009416C8E0D63CEBBE59E0DE5072B13393DEA7F9A327F95BD864029472C2463580AFBC5ED62093E4CAC10B1010061C9111940EBE4C9F8B40057F1C1F5C0CA0C92677CA78314D76969960D4A4DC613CFB34B42E6582E7CE1617C4B56D7E3A87F8776FC6A21848598288CEEDF9E2F389016549544597C1FF91659352471C230B07BF2B6B21D5531C60F9589294E7D93EE1DE05BFB111287733EB810C4121DEF6BD36E98607D911E5A72E57DBE065AFA23848CCFE5F8F5DDFC3972A522E2A9A52F4982EB3AF9DE1D6F2A611C6A5CC05AAE848E3A80D4B1CFD26772718FB938299966868C6D8F8833665261719621ABAA19AF1F6B9C0D2D8BACB3388F1D90C613CD847DA83B26BFBBB62C17376B3784E646C6BB774C87E9B21172B3DF3C4F2ACA06E6CF62597B1AD4C4FD7D67DCECF31C2B124F355BCA206EB54A880CD985AF25B23C9A0AD170DBBFD4393168EF720C1BC9C5657CFA615DCFD59A1591E89ADCCA33E1875D66DF2C1248A81283251BE85C230E0FB052A235CD0538D802A3F6C84FE448E0100CAB3AFDA9DD79E5590ADE28354893B575CC1F6047FC4A5E97C3693D223C085DB1B60781999F97E752D677EF46E37C4CD1E311075A17504FC3D81DC7CF733B5594E5C7FCC58FCAA4F4D57BA4F9DEA3A2ED4E70D2DC3E71BC79770C33CB2AF878AE185CC99AABD8FAC958BF3140A7998EB212DA72D9E5160F1AC42FC2921F5CA77321D23674032E8745B31C187B1120B77A7C11C7621103ECBF9768AF96E4FF6AFF87D77FED13A708B8F555308CF8C7386F96D724A4F9C640D34802AC1B089F88B542EDE388597DE10440A40CA76DD7F0286451A801ACA8423A095E00C82E1A570FE6300B39E62AF4CFBF1DB925AF6401F3523CA451AEB8F760F858EF555A54B9786C168B8BB0F8AA28218F758388E8A35F344096866A4A75B902957C3223C64D538356CC8B1FAF52563A181C92E855F49BDB39490E51ED5388226E0AD25CB0B36E70670D3019D5CDAAA0D7E3DC05317EB2C9E80DC08F03E41B887822CA39E598A270B4365718A32FBEC2F5820E8AE5AC7106F067C8A1C4CFC23A6941A0A26E02872887429D49DFF66FCB7DE43A7FDC51BC366A41DD7C94D900AD496D90215921B7B2D7C3FA639206CF6CA11F6279769E83F41ACCADF498806ECADE920E8D411F596DC9604D6E8570379E9A680A13EB8595B63775C380359D20E8638A5077A7FDD2C0BC16053493B42B73F54565E7327281E46DAB3FA7ED49765F4A32D962FE55BA7551591915BCB12E9913F3B99DD6248890539825D139F3B9789A64EB8F0F1E519DB3F9C8022A3F41CAA07FE6DC4E1FCA7D46F290906F97940FF69044974629E40E866D948 +sk = ABBCEC70AD82C764E63D72627AD8AC948DAD19017E5BBA517D85C8CF781FBCFC5CFC650D460218EE0F41A9234763D9492A16A18A9D54519068E22FCAC2CD6D2ACDD25C5A30A7E967311AFC59E2C6C4E08C451E091124BC9B3CE511DCCFC2D6E82ECA07F65548ADFE7650C4BB465E20DC0799D78DDEC67EAEB8B3FF33E0361E9B002763358618108202784854352463270462130806680376437418423568222476234318406008126542571755238134226620556610152586150580400485384700314161635016132576078813023554256131388018355161664513531558437403156057615715748247355712578403356314487007836272125147611747231825018075452855518856856212888756003781577435653823468731651248310474660025303012862840371484163845750264482705452240556026504324877371463330587613704216165266134830333266126782740373551650163136836335523768524018013387557255408134106133165668744545720300143000456126723548131650411532413701613476664174688420768318113738240660621480717437703525600402131334525284213483445828126546765185208158445753532778624505584573165018217441245655414563028446805330041412688665572026511383845661252868437683535045378050643384248012753584136643822318768673626011506371184484823623017136464553581163001656407566285583431672513271183068134313086711327336166438214257330454012783488264702660512750836402527385225061734531222025114826641726552624500060075770066418788546177508675430503678878467240067873270385647548258181253706744520633817341056433712582714517782661240728134554077870066204736233784744765530135801785218312714610300080587488287465177040370007010671104282873101518887544872254640456767780300477377560122148885247660613316460383486337583657340027084143476750425645726353143148641066081404365151135885047837487328676751277682124405214206623435376587526624147540236150240333585828264867647402211122725181433740324704462627425566427534333450708312006648034562235163030220405415750677825016588074772214887005031245234888584148301526325255810201162501142525524822583071180810408684260764781532280181834031525424021685637121457273153072053381778200871283103751287277341636388002228185133752660878365862016756633610851688081776715110606254288023724553786200304160311548727646268251473205183435408676358706228580645542243414160325221527326178625488243610332008817037065465561085467556122827383567026204063445587865305643267423423316238146520350600561326585104585480570081862057151556343507132272314016236471464260115600701625056503432702847036087370580357627238727368332881126148344051572864562335127654842273826022227627188763306662031037235805122433335485473137387830432126416547337471266852388717107301858037187654873857010335018424004461331785364408342463165232872482425580871116586643483516700157855402854316882444750570063507518256403000534731232466104274858046857842562632736261426782802866018605344767726326823222365026574152635750281115047852157283160270057240831511408585221124854645878223004773376050565127726182118625533770606641728605125865840426836876155031114254485215268255167865432401115538423518135770413316573855721433545635877211100624113481066367220588473587646082731360126517564448224276147372686788435625844003240011620363426482083174108271123E1734C15EA3C654BD92A6C30C3DB5FE92944773719ECA696643846A43870B56843A3C28E1A4D533FC09152061F850374A3720ADCF089CE84D9A0C79F883930F7109AD31214078F6BCFCDCD21E76C2929742DCB3559D5F8B9F543E088F75D40B8C30438E22B636FE212814BDBA86E10C02483CAD3FCF62DE1121641FCB586EFFBE2527F33E509C0A53601C5EDF4DFF30A60671B24262A824CEC2E7676454806EAE754D11E6D99D3C41CC8F150AD2AB1A0D06FEBAF199DE4113C35508327D74498412ED50A524DF8D101BF0DC040A7B73FC10A6556C2368D38B30F67F44ACBB7460BD5334D2D7E11739AFA4969BD3AAB683326D7DDEF1885C0289F75EF90435403B424F54DDE0D6BD7909C79FC7055437DFE5343520C69585341B124B99A70FC80806CEFEA7738C81E3B8B0759AABC78AD1F05D8A8657DC331BA49E8B1002A33664FC1A794D13C4F166A0C83E2C7D5B2D301C4F655A39E98D78D6ED2018D8CBB6FD5B6869407869040BED212DAB9945E8885C5FB218A058D4D21E379E94A01405C9DE17724F304EB2C103E7E766020E82C6126A33DF80D14351ADF645751388BA1A24A68CD1F86ED6671660B8557D8826B31BCD5DC8643F3D9B418EBFED4F7723C8D1A664D474E34ACE3CD8B96CD1DD74A17754AA65CE0DFE14BAFF5F2FB373D8FE42E962A4C1A1B3AAC3BBD21C315E32C044D6031227F3DAFCCC3F57E2875381C57693190C8ED976E6E4C4781C7D156DCF0A6FEDCAD2BE2BD9675304EADBFFEC8ACE78B51B1A4E88AD1D0228FBC1285AA105B14F4F4FFFC5B55567D6C0E73118A762B4C8688417F0D11D899116B68EDD0DACC386AB94B5F302B886023EBBD06699A14ED84E10CF7E421239790EC3094D959AA6DDC514B378982D8A4A34506F5C67A90947A9B0E6858D61A69E6720253F79ACF9FE404D811CFE831817CF1D4CAF6E13F061656B2EC604680620AB61DBA1CADDA454FCE6E80864063ABB480CA994C6BCA65F8472D90D6234A352F9EE0D5A1F6A408301610CB01E4743870AA627860ACE94A4D02146F6E08FC2265C9D09AC755A45370EC867283B841BAA4C2D2F9139B1753A64B594FCCEEA8D6195A36D4A11C23F4E2AC8A70D72A9E6EEFEAD82854572D2F8F57D7169F48DB03FB00ED7081C3E3C06C2825BABDEE9D1EE9F3303C9FFA33E9BBC9A9CBA730A8FAA1D8A181162BDF6093BFD7D3D22A9B2D9BF5DF187AFA1FF432813276C8035FF6411A87D40F1EAC3414C589FD68AE9168F44AB31DCD9B876BF0D604B9E9CC07AC71E2CD169C0540E0E78ED96662CACE86A254A50BD2B224B6F41FF9AF39C1A5135E885A06ACB392C07E8951189C3E45461CCE3B2314713F11062F7454ED5BD741E2253B89FF9117AE78477021ACA9CAD9C309A9423803E4D81F507B2D6E15ECA397561E20AE96ACFDBBC567DB38700EDD480A8060FBEAED5E5224D61871EA275BBD59AD25456072CAF655AA373867BF2A76E9F5B77B9B0509C5CC4CAAD228721770EE4AE9DDE5F64FCB2DF4A4CD8D468D0BA71234460E1E7475D81E7FE5C6E681686D2ED9119E7327C327AF27E1D8F7DBBE336B3173EF6BEDD2768BC39BC709842BF3AB39836FABEB09A6C5EFB2B77EAFE37B7F6F4B42F55F36CFB10F69C8BFE59CCB88D017FDC4EDDB399C94EBFB4C7D4ED9E99512BC3B3A134AF9E56736C0995CD7E64351D06AA68B95EB119D483211673D3F7F4DFF03AA8C278D3E9F9BA719C5DC2287142FBA5803A57349EA166660A675EA6E73070C0930756806476FAD972809F0B3145C5B133F0DB052AAC8ECFB89AA44DD5041FF7B80A764CD06ACD5AA1B9A24FC4548EE1029268EE7BD8B40D1E7247FB29348ADC0CD68327067920AEEDACEA13B96A24570E8C8B9264E5D2C300398E0547BA76F9305E4A8847E83B07B608EA95061A225A4C0D9820A15FBBFB4A4FA4AC4F759F1590E45E164ADCDD76038F039AC7B8A144A611B1057CF613BD671B774407D82C6639A4CF3EE13C51CD06197E57A4D37F54236E0B64767C16D16E22E3892A0E927AF9F6EFEEF552B3D7E4CA81125F28313707B7C888CE60D3186AB9BF31843F25DB80BA3D89DD63F11239471F1BDA7CE0979F61FDCA04657BC44B99B5FA1FFAAAA09478CFB04FEA1CDCECCE213C4A7A6B3CDCC232E9F30006BDD6EB06088D93EDAFF406648E986FDA4F1AB72A5F54E80F275FDE3B50AA6DC3EE892D5193F7058C8AE56011AD3839CEC52C316F45FDB5A996FCD5FE7BB8A32C208FA9FCDE7BECB474D5C9B9459FC1E8D6B596F904A3C6031F488D87076FC9B33D02F147B837BDEA1A3C62EF0698EC0AD65DDB6C4E30215004970D5A7EE5542073E1355AF74FF9BD0F17B2A511EE6DA78C323724099183A386599725CC93F7EC0FA6D30A01860409547B44DCE610C36DF0CB31C11813EF5B6B56F5644543ABCC0E1D0DD58A0F3E67936E0CE3AAD202479C2F996175CA29EF688A450C860EAFE502D712FE5C956A00E4726FBFB118BE7B4842809DD27BC0B86B94532406F0AA34250D291ADD2706F21B16261B70FAB63ADC182D134FD8B8A5D8FB3CA09EEA41C2193E361EEA341DE3077C031B21B4C4DD9A7388F302B08D4140C8BD56C27ED1D1FA0C65BF6A18124D6EAC21536941EE15F2BCF80FA0DC44B2E6E9C806A876156137A8EB20ACC5937CDAE00140F69FC0CB05ECF6DAB757F49E6F20FC458F7AB2AA4E37A3B1AB0EE0AC254661C9A9A9C6BDF83CCB14BDF78B56D17CD6BB74C924C205EF04262535BC7C4D3213E5F5EA80210A4A3A9654E28B29492D5CC2055CA61DAC1A5C54217328DDDB8ED93ECA1BE5BF254583D44D0DD226B284229EB27BCF7F147DD25D0D93A1FDB50F7159E54AF015D3EA6FBD84003746E8379E25D704C228A811950C1E6F6419F1BC3020DCA11BA8975A350B5546C3CA1B5BE84711B8677A0F8322431A4E850482738DBB38C7F02C4FE7C246ACDD3C17FEAF62D8A3A31D555FF27FDD95D90D0F828CAD18012395264C9120139A2A7832769FEF6A70DB14EB8DCCB07E7E7ECCF04AEE719C2CCE8A0BC361AD14D3F44A9E8D591DE9363351A726DC030AFEAA8EB214A9ADA809BBF7799BEED6801C1DAAD24200F92E039D48D88C631B007ACDE2D48E1DA60606076F1DD65D39F6EC0B676E63C2AA1F1AAC395F8357299CD8AEE4B9672DE33E3FFA7C0205F102C739519F464D74304DC3E94C69102A10C18A52DB0A4D4A78405C9D3BBFFBBE2B3BCE0DC319D2E71CE5A26A79D70C8A1412CB3503764A21AA87397D685EB487CC7A9B5E3BDEAB3FC169A4C47BA585C24185161445DB70BCF498E4A1CEFB844FA1313209B1E906D67F7D1815DEAA5E28676BB2792267CC4E49326C3256EE8642FDABFA9F191CC13B14B23B155E4388AF84A10045DD93B87D0FD51499E873635F90F7BA5C4F5ACCF955AA85E3D63ED6B05446A29AE8436040E93DCEE6678B273AF18B2B38B5B8A1876A724F72C17EE032FD7F6A2F7AD98F3AA2F7E74549477B334C7C00C0476CE2A3C906B0855C23784D896BBD42 +smlen = 4794 +sm = 12C5175A8B2A77EBFB68E7CC119FFDCD7663B612C52E80E7977F9D06858CE51C275E2778CAC9FF431AE16B26E982C04686BCF53611F7507518389A2E85709AA649F59EC53688BF026C5A31ADDF6573E86B71ADBED12ED6A50ACB420CD1EBBEC22CE91ADDDA38CDFD60EA05207659E1B45BECED32CC394A1E8C614DFC8232216EC7BDC40A2D6FF1B35EAF056293BFC08CED6DD349F1506FF31D160563042E3DD9265C9BABD47D9150BBA9FA0AB5B7620E66876BCBDAAF50FAF2DC0927125003D4C5F8E374DD932BAF4FA3A805525A2A8D73CDFA601D6B861322EEB3949B926D0401E7AC47246646B4E070F9FBC12685F183953B27589B7B3C1EC2F20B769EE306240C231DB9235C06265F9DD2388DC2F34087054FC13E662D141A935D1227D3B0B62A76276D17A19243E444554DD024F1521279A421A916225F18D1A1D8520134C3DAA59169000D6FE8C8F442BC8F7A00C99BBA415C92CE7A4B0A36D302BE62727A915A2F2D967FE061FE397EF8320545BD7BF90664958B8AD193C1210FF575099182FAD7CE9551A1BDA7ECFD13D884DF76FE322C31D97D897507A91598D9CD9BC4851F77B952ADF6DADCA850DD37B19200131296C58588BCFB62F619038C8D8C815A8420869A2BCB65894B5FCB0588850A2748B3FAE2386B8E8B76E99B7C5755592ED133B73E68231A3151BC5F463FF658F505A7CCD36ED39388B39E6125E1C755C6A77EB8F9E3C29D71C916B0210CE7EFC1A9DD90FA4567B6052EDAD97C7BB68648619DC3B4FEB636A59B1307CEB4F578766E45978CEABB600623F96D4A2842CD543FC33DB4F9169622893A6800C2C6E609A6590C23AAFFDE980467E79FF5E10D04130F7530146C04B34C493844A6A31C00742EB6A97A21DBF6760EADB3A0C090A33845CD37269BEAF610B1FFCF5DC14C2D155A716844CCEF4A2E8F5CBEBD943757E3121500553AA5C6745E2D5D40E0142557C091C61667DFFCED703C1636B86DFCB98975AF06DBFC6C806739C94034E66BE873BCE3D40D53AC223BA942DFE954C9E949815EC441BEE6CC357CBAC2B07BBD6F15AFA8A0D0E3F6A6E783F79483C2E24C6819EEDD8072AF00008787FC7EAF9D870BFEAB8605832A404E21F5C65D84A36D8C1DE487931FC03A1A495436C02139DBF142993121DC02BC6AB98BCAA6F3E29E8B0A8EF72B317EA7E90CF111C630E1ABEFCF5928C49EAE32255992CD379E31068424CAEC26356F2F29F3DE175F6E6A254D04C26986408DC1C29E8EB3C5A2CF032051D3D0D0681E1F13C94CA880A6F6BE3FBEE70BA5CCCC999A3D42CEC06C7DF58A71BBF26C93636474B0B694F2959082102B6FF469937867319B9EC3651582BA09B93C634F6BBF64FCBEBE53122DC59D137489E0F5882F43F9176E098E3EB24499A8B07A6725D45C7825970CB7CD52C1332DEC490B0E8E3841E4B690C96267A5A09EA97152CF11F5E0A6C8A1028D6BB4ECB03C984AA66082E104488C17B9C7479851F32E62C99B9DDB65B9B81446F25C1678BDEC0763BD1D9C549CB46C797C6CE0E75F50670E71890CD19740464DD467410783D7DE8960DF018F7819268374DB30B8EE87B79CB5D5BEB37E0D1396A17144616078905953A7085075BC13A698C3704BDDA65268489C9974EE04555BCC85D2FC9DA9B18CF637A016098C0289322A1F9792876D1946074023F2FA2028F1227EA9258647D80081BB7A6C4E7029BC176815CF87C5BBDAEF31402827856AEE661ED342F56112185A8573BC3281A1CFBB568B7C14899A96038A021FE0E9E2958B63046C8707916223F7CFE97056C4325D34FCC0938B1B47477959CA346646CF6FA0DE8F8A76F45D871EDD10661C156C5E9F0BB345ACDFD27D689098E1139867C9B6E7F3669362A323466FA6A1ECCE7A20C216B8B041C855D4540295490112DED1841745904AEB2BD34D8BE2989116A38D4D94C266235F13E137941296AB581551A1340A654F67BD01AECEDF3774AAB74ACD31DDF69ECE2976D00DD4524083314A56351240FABD59BC717D2625478D325E303F2018EF58EAD338368934A12FCCF65267B4644FE4AFC8E8B843443D44179085B28F6629A43A9E56FF4C9FF76D17E6F11B00C6B74590167AC0D36AAEAF169E699407046D10F7098879A7C7FCE50BD6226E6C1171259BF4301077DCC648D49663D49A96A021A72F31A76A660471D054A592F0CBACA4B871DD9AEEBAEFE697DEED99CD06A157E372C50B3CABFCC03EF214A3F949A978AF1D462ED47B8046BB3BDC72DB2E635DABE8275FE48981500D3AE77A507BFA8AC8990DFD6E4403AB3174CA8C90CFF3A539E8882CB72BD25A004534CAA15332DAE56D6C9CBB4FD16914BFD7D9E08ED55C5462AF4753B02A7BC4D9EF10B6DF6713F36E8B51851BF8F819BD882EF255E6034FB8A1DDFE300AA501EF6B718D2042042582345142929907F398DBACFFC0B087E8FCD08CD3371E97F96EBB62B134E6943D5456DB40CB68B87AAA32F16C79A362D81C5C9D7F66653C5534DF153FAAF7107727901C8B4791BA8DBEECB8DC2152083063ED8D5C8C0C0686870CDCDA649A4DCE08E78BB7D2EA014288090351C107067D81FB637D4A848E55DF6406DA9526A797CC69FCA8F37C395CEF8B6D40A361594E985B7BE331B2A092F1AF37271F634AB42D231688FE9467A5B2DFB0BF79C7EB9AC354B550F9610A92346F7E5636360413134F56A711402D41DA166EB61762498BABC626895BF5576F4340CBB96F6B72F8A322200A0CB15933C05125BE4591B790DEA731384095F360CBF8A580238820C6A275C343424CD63BC901C630915AA5669FD114A47597C0441F1627B6DE0FBC1773F999B004183C20945890433A935BEAA947B1EEFE5C6A0EBBF34F97AB640B3278DB0F5DECB056DF64266B486369D7FE0F6D14374084717562C9512202839C55BA4224C8B308FBFC862D6781F7644CCA5EBED467818980F51A64C00CBFAC65F913E29246DAC0E462374DC6082A06357CAE14FDEE094B1AD02B9AA24F1FCC6F5056046F0223138E99E4D231A496AD3090A9E070AAB91F28EABDF410FE265A0CC3427E6D65DCD1800E5A84C254EDF2E5D005622DACABF89734A795EB4A2637F031CAC9A8BC9A517075C942FAED10EDE9F2832A0D46A6466821C64352AE8E962BEDA0A1C57E3CF8E15209FEFBBA11DDAD12B8E2C8B66CD5CCBB8936DE12B740D0AA20B47669AC4AACCD33828965B4B3EFF5175AA402EDF16EB7E3B4270028E87A6E490D453C208BD81C8EEFBC2085BC30BF0EDBE38AC3A764E392DAEF9CB6AB77972C9CDBE40B6AE9D37C79AFDEC40DF5CB963BEAA3CCEC1C8CCDEC8DAB261B283EEC71C8292305946B35F6B079FCBC4EB62EB0E798241F84770401DAABE41D0BDB9EAD18E4A67750F08DA1738170D0041B7B3DADE247933CC8B3590B8F889778EFD5CD083221210971911F77B440166ACCD67DAD00F0039354DE1484D445D23AAAC861064F26528B99731E8CA6CC68DAC8E393BB9728DF2251C7527147CF52F879C79576FCF692FF4F508869FDF39DE0FFD13D16610098F855780B5476C60570667B3DEB23CDE75814278495D87F5BC7510BC08D23025E744BD1DBBB624FA08414070E7D6A091F465979A7081FD1F4BF50CFDA2F42A969C1DB32FA92779E332D1A06E8AC088FB82BB347939883F0D4CEBE7C3DBDCD4CA3928DFE31FD9C5A2F1C849D0A2CD30BCFC14AA7D6D07A0862EC030C098025D5D03D8315E3180CA5E2AF1856940D1BB485CFF07C21F3778AF37D9A1A9B3D831739D6322CE4AD04897FA29930C154EB120952F43EC7118B6CDD912D6EB898ADCCD2503381F41C6A181104B9EEB4120137D4131A9E6D3343968C5ED66BDE2D1CBFF4081808029408FC8E8CF78FD84A9DE0D368C41869F75C3CB578C594490F6F695D7A784D455CA7F094050BADF4B3301A1C548C2E40FEB9E94E60DEBC16560A4AEE5D581F592E0F980DB75BF9DD19EB470BF901BE04925F5E7B34B2F52D809337FFF0C83656F6B6348776F28EBEEC1B24B47C321C3BFDDA562587DB9169F1B56980839162D34822E10AEB62E0D1AC7427BCFB4081FCCE8ECEFAC60D09024AAC68F029B59EEE7DE58C4A8BBEC6634672C2375230AE044BB312DE8583A919B498797DB849A47B6DCF1EEA6F3312C42D5EC95E411A00EAAEAD2532B587D8DE9E54B61568D4FE44F5E2F9A6176518783466589F8F0A014962FBC8F27E754022081C95F3E50CE9DCE02F705E39EAA124F134DBA4086054F12CC950C7B270A873D1E5FE584810A51FF56F48CA16A43E531852E1783FAC7073A8ED7648E02253B325CA91E68BA026ECDC749E9F400DF4047AB32388F79FFC70133DBD4859570D72C4F5A00F65BCD2511B89B7C2FCB14ECA35646DFC552A406E1F2E1274BF42731BE39B310C6AB5C4E711B6955068868D8769C0949EF56A2663A62C57E702A2EF3F5B43FBA9A7453D7D79677569C82941FDA72E5814B5782733211E335C9D36FD7D59589784B725D5CAF042CC4CE37A1D27051AAAFB04A3BB25798B9D786312CD8A3E98E08BB85F840CDF219DDD6923CC47A45F279F3E237F4C7077CD270792E3FB5084B3D40C1334354A66E30D3F42518D98B7ED3A4D577A7D9BEF4A81869C1E367FB4B9FD1D497CC6CCDCED00000000000000000000000000000000070F161A202796E2865A0E602EA4E3C5657A7F761A6F771007989FF885261F5638C14C1BF80AADE34CB956D2B5FA1CE38FDE831423201D3692E8E6F40E68A68C085DBE3C4CD8E35394F74072F44DE98A74E42C9176A86AC06BED8C0CA937DB4C3BF92371106B7A68EA8FDE1D1E082CCF522A397401AD0F8DA6C82BF76EAB8AFE101C7FF023A0FCF015B40ADA0073363E7CB25260C18662D651222A4CCF1B290EE6F7B111B9A963211D67D7674B499449F760352FEEB9FB7265A5F2F7F20C0174802C7F48226D92620D3E009E85B104230C21BA2FB0012DAC4BDF9FD184E09CB3E593EB1F3EEB418A8BF3173E6CB91FD8080C7E80DBE6730833A4A9F22C52716731C7CEA4F70CDE0F81D2D9AAFB6B60820598A7F6AA1B963B7686528E6E7885AE085C3D26C4ACBF9FC15080D972CA841175B343E59FED79AE3CB4DBB4F0D7D463BD3E0C4B2090139145B8D7DB5DB10ABFA51DC909C5CF7809030D72A5090CDC765EECADE2B365F719127548CA601AE0D21E402E18050ACAED30EE13CDDADACC9373A87A218787B585319A7E66FBB13851F7AD0D2BBC1EFE6EFE4F7ED248D844F58B6A5A21FA9295E0044982AF6286DE296550F72B5E416373F1DAC006687DED1E7D40961E5177C207579F25E77BE808A6BA33DCE8A2A6F88E97AE98ECFBEE5296D4A170E3574D9BA592A384CB0545BCFC32B3831C0B736AB77440722299F192DCAD519523995F71F2983BA87AAD2261E6E01C19DCCAE00F8D6914501D1AC3D4AFF0C12FA125ECDCA34DCDD8407F0045F8E8BE0763E19EB007ED4DAE36E30AFB07F8DAA7431B72F4A0A8017B3FDE27123AC3E8EE575F8BE310F68F81B696DB1FE63CCB8D32B899B209B2205956D209BD6E48166BBB4372A607E83C47698DB5AC8F9B40D05F38EFC4A4A1309D999D5CE1E1A5828D56EDA4666995897C8E6362D0B5054F04BCCF79D03852D1003C80CCD55E9F4578D8BB2C8E220A4D7A4E2190024C85C718654CCF174AC96C1BC50EA49F961EE7697C88E6BB718679F1D1F1118376B31A4B8C0471F6D7AEFC5AB426515D1B2CF0EAE66246B3C4132A63C63D7E33EB9DF8D8807215D58F46EE832AD3EC893D74E00C73510B9625F62D4EB5B500EECDBC7D088D3D318077A4A0F7D64ADB13220232C08DA75D23CA7B20CB109C972B7C159863991C32508339558B9383DDFE7E7DDA740E5BED0EBD14ED300C634DB01F359F81A7133669183EB187C17A2C8AB855BFCE73E34A1F59ADB0EC39EC0C7573AD3620A819333EE79D5E09CB8449F91923EF4C5E21549EB7F56075C014E1C3AD2805E682F07BA8AA265745CB600A460069678745FB9638F6709D62D2DAD8DEFDD5A4D0C2AE7401292BD1DA5F40D4CF5D59A403932FFB677237AD74691CAE29FA31B955172EFC5E83C225F2DC0430AB0C909A97BFB468AE182ECF91E9026DE819F3440FBE69B9DE26F812FF3F3CE8037F124AB368B1153C1CC127D140F754C525D4799E1A19D93B90460E6518F0B6936DC6310B7E9E6534B595E00225978214EE5AEB12A6F45B5C73FE86771818843FF7A6B88379C37165D9DAD48AFFD6FBABD11B1FB90AA5A78918B317C5F9B2CED6B9647F130DA9F91E1B1CEB84F6E1618248F06D654E159F71033072F1517064BD96A5C138402771ABE7F39F53A798C2423B748EB7F310485D6376722E204FA33B9740E7FA68364289A677C5C78A19A7707D2549BF9329334478C64351FEA1634388ACD4BE57E4ABE9374A0E999B770CD81B1BF4A8FF300C297B116CEDA1A4A1C1BD5A2275581A0589A46142139FC596A1406D16293076527CDF9AEA2D0919F9678423B7D95B153DD1D9D62B72A12F6491A36604D19E7BB83C476D232769425557D3480623D40B7AC27C0F67D4ED5CA4D487BE915A68352DCB03A3929A4BB795248EBE2FBE0612833D9305A0A31D195718BAC193FC59B880042A7F61358104A919C7E7C210F02A856B8B1057DD8527FD4AE1EA81F9E1BF7C614ED8A312C95154873F86632CBD60C65176F13CAC695BB4C23675331058397D6E96E4F9DEEB859E3937553D94BEDE3C2B9A5EBF00964A49AB294BCCEE09E5A97381D2375941AA775A47F726E9 + +count = 45 +seed = 8BEA4E384E73C7E0B47381B3063334291A0F06D28DB61B5BF65B01D0A747722E0AA62B81AD46C00C8A5C31494E513836 +mlen = 1518 +msg = 047E2D484D798B3829CA6037D6C1588A2349DE09C5DDFBEC987652CFDA01454ED791DBFFA3D9DA13A35230ADBE1B39B042E3C70589658A03F75447C1CF3970DC10FE5A4A9E980F2A33B642B42E5E66E9AC4E7A56888FCD72913A79489B5B163BD37B8C3C8D242FFEB37D0C1ECE21034BE9E3685798C2EBC6B809DEFC02C6F0C2A3AD70EC0BAD12D57ADD63EC3584CA98E680267FA514B34DE4147C9D901B59914D49CE9E0F885855ED0CE7973F3307B675408F90B51C6A4D38A414D970EEC989CC7900D7723E19ACC4EF743F6D39EB1B563B8C13D42C0056B6C49732854925B606467F7BC662D17B924FC65E9C3CDC2AE73FF73040011A152B05ED7F96B2FF4CC39A22484AF72812EF02B08EF4DCB64C8936E74549AFDD5D876027FE2B431E61E52E8793888473F4C1E5C1BED2C4AEF8E5E300A735B302474FC6F54869984F1A62DAE29C7C9A0CCDECAA55FE137BA14B5C5C121E0C5EB33B035E01F3415529E0826B27498D7A71B0C086BACD140C02A5948AA54799D0DD0FFD384C7E68578247FA28D205B18ADAC94F7D3C8ACB7DAF71AEE347B577D97EE8E7E865CF4FC1C16640AD1E9D0192AA13AE81A71118408E145B6121ABB75B4BFFD1D403057D4AD5CC730452475A7F067690BB81E81E17BA8DBC31059969B20D387BA59CA8CE499E59A65C8583F29CD539F4F75DDCC68C7BBBC43C849802D8347143E2FE78C1AB6D7AB6BA9917301C88386B294AAC995C24AD680A8C3BDD7AEBEF21E84F5A1909A2D83A8DFE46A75F4B2B47614CD39BF3CA3460DE9BB5C37EB7349A17AB32214D031CE927806FA394470F407673B0CDC3D9A7E3749F09CA895D464A4269682CE6DDCB8FA0EC2F05372C73DC3D06FA6F58090EFBBC6D619A7A565D4EFE441AD7E018A7F5E1384B88EB4506FC54E0AB0A8B9EE3641760FFC08F6BDA78C12396473D1243BAAF6AE10316213115441C0B65C7E475B4E1578D066A47D9C6E92FA32D0F2C365FD15F5A2E88A81691F039DC642ECEDB6652D08ACBE64625B46083CE758FA96C142EB34477E065AEA04A45FF4FCC3E3D146ACD7041F5F7E4C6B26C8205BE7B66DB46DA55556CE02B48AF55A4710BB28B8CE102CB15C1A4AF59D9A17A2DDA6E2D1E96987F6AA9F4216D8D5E5CBFF7E2CB775E83A776063A4AAF937BF0EC84149EC1A7EE21F735D21625E85831B80DC11EBF04F30B13E3A7E4D4784C5F8C61C679E0B6863958F42ED31DEAFFB4C272A3731C1407445CA7673D225EB6509469DC6C1F0AF43EB00F18B3A210AA57D51169F2A9FC251BB338ED4E9DDB19282DCE871211D26482E13A8D533DEE00D36FF5CEA98DEA72D9F0B32DC398A3D5537A3373058FAAA3926C127A1EC739FAF3D57CC1A05D578074A3A72C3F2B1692C2BA1F1FFED943E7BFCBF1E664C4F52F7BF8D86174CA8910C290C06804A7748DB21008AC43E653D7FD7E0C982EDA9356F68DDEC26473956DFF281F7B767010C57F4AD09A05063A6B3CE078DD32F3DE1F40526C06A2D60E36E2C70502D5BEBFD2F3BFCACF8720CDE1657B9892406BAA3DF01E59313EB655B6A545331EBA01BCDB9C99E4AD7FEF7438AE8715FBE589A2F99CB9CA34B9610B3CE5BE38FCF979240698174348417420AAB069B8AD5F646F82958A136DC9F2F81E601056BB4AB5E10F4EBC4A00E18924C51D0FD104078471C6805C49D92C78C832EC3F10D8966E19ADD3D3B4516E12DAF4F63FE6BBD228062DB743D1F867800854F7BB7FFC2CAA0D01A0BB683E368673A8E664BBAA17A8C0C04BCFF05246F9C4F3020510A992EF26FD0933BBFDE9D042862DFFD33A6465F590A2287D8154777A89724FC3DF9F2F1B1ED8765E7C7B761CA4781006822065703ADE07A6E874E70928E1ABA29EE490690D24F6E73D96B85FB53ABFD1C1FDE439279E08FA232043B2344B267CFE5901C60E7CA14B0C85EDCFA2AB90F341821D2B4E25FE23129F2432DB932F23B5957706A433B308FB918D1C8D81EEB399BABE95E7229AD41F30460CF28671A4508B0BD1C61F48CDC23587BB9BDC6F565E76C86547CB71396661BEC8C7FC2223751F765C91C45C674C36B49AEDEF3DF2537F888904B507EDCD89155D40CB81DDA74376BC9CDCAFF8A368F1086C99EDE25526BC53F95F4017 +pk = F55D9B3BCA9328DF438E5E818CE35B2D04509F8BDE9AE6B9F97A2DEA655147E1DC1CD44523FAA334E490CD9517108F7F7D484B7B3C9B18A342CFD751419FCE689503BE6C390746CB3071B55E8CC4668C1194EB5F4BC2F26F8B0E19D3DB88C15CBDEAE225E2F9D8D387CD075EA688B0C4FEDF38615927FEF61896C6030687271771C77019411D9976B400C9A8CA11F0A58C0ECA99C9AAD3A8C7D5293EABABC38E8622E3BCA6F6A20E409BF7C1A0CF208ACF8F661663767CB3C313590C9E47B4E6C8E1BA190084332255929745F411E80CDC36351C2068132B9BFAF37BB04EB813783DC1A4284D19977BE60572575A7B7D995678E660B45B4F5B56633A71E0765A5670E22E9226D46347B671BC4B4A4E2F384265CB53C90F125449091D0069FF26DA1527E6790EE308966E62E921B2B730EAA1ACA73B527BC56A412E6B25C71B19CF149B5E7753C71EBC7D5134E6237932A027CF3E012DC902531B6C0C4D7B74445AC1009C6D6F3491F0AE05233391E5708C9FC4C7D7B68ECD8C34F012E0C46B378607DBEA849F88BE36E9A131479735D15CCBBA952630DAC50D8FF865833F05FC737EF608C6E6230D04D21B1DAA3330962EDA9CE47F4883EA6C75BF6EAF4DA4C173F14BC89C402A54D328819B3053E1F5880B913473F7281DD57C51C1CB3A8E7EB0C3036CDD94BFF0F5F6139F0671792CD5D34FFB3DA4C7E1CD733DC7E4A4693EF0AF82CE5FF06E672F3FE34BB9EADD42DE01E8ACE1FDBAE5AE5C75AFA488B215C6BD92C42B86021D7D4D15CCB75D614F863A8E57BEBAF8BFABC46481A2E1715A5C078E05A345F0E1276566D8DBE1C243DB6BF98E42CE17BC8E93C47557B8B3686498AF275685307CC4B9C1FCAA4BDE099401AC4A8E09E9C2D2CA5003018CC091EE9465672A69BBACBC76F50AC780789945F6563428BFB45FD01433B5C8FE2835717EAA8EBC5C57175559F23EBAA97EC2C73446143B8CF46EF27F5323F5684EDB085C2CCC2AEA17AA2C90061C2CCB1F048C30F5BF64D090BFFFF52DD73BE58B71602B439941A5FFED03F12448DE8A28FD3AC80B0962129880CB78EA529F4A3DCDB159F8735DFE68B6E3CB23BAF9F1BDE6EEA027780631CCFF3DCEDF000CFC11AD464F35F7985FC90BB80EFA7C39F90A7A6302291FE0732E425048ECAA4A312234950EB9B3ED97D4B1AECD0E8C6055891979A7437B1FFEDFE3A360CABB8CE50F9F6E8E77A334250F2DC0CA0630C805B0D81289128E6FA8B109874D1E2271E85AE0637E5076BEF28380983513E88DAE4D05D2C3CC2E3DD4EAACA17ECB8A03B02A7DFF351DC8D4EE1176A8C9200FCAF4F9143636B00C18D7502D1DF2728793F7A48C7C3CE0FB16280645246A1D00B6B27AB14FD5EB158BB9744549A0F9777E1DDF8788F5AC48D201D52ECA53551DDA8124CCA82FFC1F69209873B9C68EA810E17914D313FB696279697DA41F7B6949418AB40508992E97B33B6155649E410A0B8E5744580CC8A8F2DFEA3147CF868580512D5FBB8CDD142811F0C10EEDED7D62AA4B3AF8C9D6AED315DCF817299ED93C51B7706B5F1BB67AA7668C52080BA3253BDE7CA663FFA691093D332BF547BED7DC489A911B6A6585EC8B8B2E2FE487EB495003ECCC219BDDC663E15D889307BD49D68987A29C9C7E4E5973B14A59A9BC5614D6250421CAE4224CBF89813308127C6F71AD1B7C7952A01554D2BFB860F6FBF617DA2D41743CD3225D776BB4D279BD78EC873907C00DB83CE264BC37FB11EE1F1AA3B9E7010C412AD55740BDF7B424EFD806A4FA080ED5E8CF01EB267C76B15C098805F071ADA96451FEB0EB465C52FECADDDCD3E4B79C1DB7F9E0816845F7B1AA8E6956451E993A9626A3B6CBC61C9523FED0EA1BAA1C5BF43FB7A12F95B4234FB7595F23CDA17088F5D0AC272C39B45688CC54D3F2360BFD68A609021ADEC41A33FA93F6870413406A75737F520B428EF672D099A0FE414301D86651B70C3814D749B6EA985279CEE09A95F826C7625FE5209E5617A08358276CF533B69EE3A049BA456BC4AA5BE8CE9F6F3A0850C667CA3DBD250F2E3E788F25D4969C851FE741C6F1477E181C3983054C4D7E7F302241FCA65208474978849180CE6743A2DEED21680CB855DB13BDA364015945DF0ABF71616CEAA730AA5816F8069631C9E2F04B34F6B7511F8845FF63F0FE992EDED41B2E7628136476CE83FE5580C03A38923F3C6A65E69DF080A8B68AC5FF86212D16A5B26E5465B973B27B7D399CC0588E4A02081759B55B64EBD9827BF5D9F96033480BC136329AE8BD2F369C7F5D954CED1761F3F7529B5C1870BC4ED83701ED8FF6FA90BF33E7CC1C15FC92F5644CCFDB269FE5AF7FA9CEF4C49448B59DEC8E7BBA02D36809691FDA7EE29C5F2B36260FAD1C3BC1638BA1FF9939830A31FB73E4630CE28657A7852930369E6574F04A71845EC8924A9C2465DA44BA25CE05C735D6613633B3330E0C0E8502002ECAEFF3CDD7CFB3234D37880B7A82E6396235795D73DDB3AEE8ED95993B39D2877D74981DC07304C297148A3628896E04F460DD34E96991A560D396B2427BC8DB824D7005885CEE7694567954E9769008BD28F5C0ECEDBAD25CE0142C47076949A0A32FA429CB125C0A73859CE88D670BCB1349C41805B374C9943D19BCE2DB00FEB7486E9F7F8EBE42DD4733C8D744D36D5E667806DEA77C873D6269190A9542F00ADB80302C96B769B28D21668EFE706163F9E63E3C1BBD5242F1804DB8973D +sk = F55D9B3BCA9328DF438E5E818CE35B2D04509F8BDE9AE6B9F97A2DEA655147E1280A3C7B4E1F0E9ADCCC71DCE2AB079C1810911C2B401566FBE2DAF1780412401C81E4F92D6EC780D7F36FABCAF3A523D8E5E373B197CB286BE164FF8FB569019D1151F227A46D923DC70FB1D002A031C1F9DDEF7EBB3BFB9B4912A368A62690863710084418165660217754514811624078003253532033168123017205674362423412340137002856508357667336231845431568302362350410447408857244623781156036663020505120516882681710824681357112450633622322145782127064252754332468216141717123012237546564771848655050758108733123434523730754245265458706167835851142417663365648782753851737318182168053332082624252303347706632746052220616823106477674031033486376650050507488603584337422411322784705221130054085000432702051286347032120357660688588168584475452238215312116053006362602722055740731630805323058887248318725714773548540618586154331523172075464146740668687554844430636008354330542347141670557413000465811633435541061243662388382125667425520670353066241445072206887546352652552682575402733833352276817322033845623164486150788570745870160858160260225735781514858613581848514158174536186348686424528245186772358502663804343775334781168184115362322064867283085627026645865021551004542607252000288226382763106502756212540247764424468316341777247554115548251758616286773338071052641011368775845447080258783247840713657124255241312611624341758838838036838873157336560022667613684877438478704217424832058672871017322211384820283527837588607638752324871827566287038464138361447620634087203401780377865014504081461481514546087806706134706024710412687760221578764643633335228842733248006425005206035538657302374173855628625027433761406552384455085682335471331616051353668314074680438534041242806823028266211130217027772460466634362418725444466040384020654568728452601553563578047118421623202863861835045846820478608130081427087727707870351432342028281385865185508317544777522284653117211128001034430500214566102241805274682571017325018756567177637137411613817735063047345812172476543318115262710045715573406802810778802106532467566315752111713670000401021323721702102430812512725312666005178516313757805800050238340224640452023172273725004488818685837638020272462476277115465606070366803044132130574881180062253644508850321520337858172237202147626137621438420311852546812768185402358027633718032644212361524386037481878232020815874160304564574645847134053270427472652312773578313351238611176515638580426377172223052237152252615327683086023834203377213514284335281667371867272535732476566504516455502250138773345270171313101034858514466553217065443065428760256510061040033015168031221362117531370225438656275738681825003636600753276513023046563355575273774230585223230424250331185728781772488407750220143587710864765233634646746741370035464056202412140442736363756282617646464264642884556726565368671781431831481143076506837447651810342832013707718553665163554001773252433021588130863784314280032306555142557071800257324137505422122252316081515213073655011275732227070682476831734823382380124284677056260007841186670734104657570416444271048766234730887342420312012584408305325476785517CF16986205C0DB45D7837A10EE1EA273F735BBF365C40F15AE011B41A05648238F762F9F3345E2C3DA39120F0E8EF888AA2E0CA4BABC4B6753F5097ADA91828352B3352791F153034A5B14ACD3A6DA98A4F85799928850EF823FD7C33D7C4B8B7EBD377B2F92F11E6DF79EE512EAA239359E6B31708FC864CA51802099FBE0A7B3FAEAB987ED077E84839A4120B5F574659B4EDF73E0E0B579EF1D7643BC83B40D00A0DFAD50BE82870F5A4273567C95C402748429C9195697C0F12FF8DC84375F58F17F18DF7208C1C3C21728CC9DC6DF4DBAF554783A47BB5D0F4A5DFA12FD686D0600E16EDC7C8C49737249C7C682AB12BBF6C98173B5439C30EA1532938704CC5446163AA4B5163AC2FC4C273BB39A2E717FF5ECF740E117F22B014EFF5B9F7458B0209ABACF34EA5A026BF5BBC12F66A45841CD5225DE99AB94701586362ACA6B52DB7231411B748FE7D475A8104D24DE01DECA3B9D0A2E0C166C00E4D442D910C8A9EABB8D6522D215F1C1D0FACD42ABF1B36B2F2F7E8A18348B38567134978ECA7BC8DDFEFBCF907BE47CCD5FD7DA2DD3F8DBA884F90AF1A18E5E239741D41C9ED440EBD2E883482EDE45782ED6B226EA7000573FFC4F84AB48CF2548AD6DBD28294E335B224F6907F0E65C49FB15A5FA12E7BAE9C02C225489E3581023694108E8D789C15FAED1140C2B45F58873D54939E364582337EE52D53995B519956D29B612299C4D954B973BF5A56DBE2F0C3E4A5B82B345DFB6F7E6DE25720C094206A3F56D4C08835B1304F60E6A0E90024314A61C11D8491B2D97EA890B94AB3ABABD8609F8425F3221234B37296924F4B6B2064AC61308E2150813DF08D1BEAD817C16ACF6FCF9584D178CE9FA95D95EAD69AF027165ED84AC2CDDFA8F3419F12CE3D3444FF0288F373A5B41B1D3ABCE73BECD7DA97ED22A43D3D885C37273BD17435B739AA4E9F24B192DBFA6072D70C60454EA655189003EAB836D61EB2A2B3EED201CEE0C61D8E322BC6D526326C1267A0CDC99FC1813320C7D3A0F1B14ADC37B3A2F28C479FD2828CD809E6E5633DD727E446162D0EFC3EB518CE739A02CAB2B4BBD773A4A6A047C846E29FFD48E43454F5DB17E7F55A62B760D27F96664EC4B2A0C46E64B2DC525B92E6590CBCE8716C9325749AFC4891D9816154264FF1278C141500CEA1731BCD66F0D7960D611ACD5C6C0692718B30B2CC1880D254E5F6AFEC83B9D21B0A425E7FEADB1D56D41630E60520043928BBC10DEFF08F8B130598C5F484105F872FD84A751644D5AD9D84A533D9B5677F9A0151F16C1BA2227D2F85EF0D611A966F1F7310BDBD618CCC2BA036FEE1F56774E497527D4882B10803916C66C628387C411CAC404417E2AB8C2CABE6B8499A2442E0900BCA03AA67CB3735A014B67B37D2B03E869EFC3A0A4D75FFFB8929EE887B8E3F8625251125B3DBA6E8B7CB8E9924481F438958B30FA3D079941AE012083AC1E4107E1E33463862075879819BB4E7F3D6DDB5FBD303E6D332ABD0FE435E16D7063A317A51560CD0686304915E5185D82F085963E9C6DDEFB5F39FABA65F0D0DDF8BB237D71D44141175A3F8341077EA5038AFF18597ED0FF9F625B026254DF91BD1AE58DC2BB1AC7289671D9AF380186D1FD9D4FB17AF2272452B69EB5D3EB96D3A8E8E2E8FCB781D83A84B852A99D2D84806B835CBA152F277129E76785F5D0898F5C4270E2992BCBA32EC95C19BCBA2879F525AE3D2CB494DD2CE16EF63830D35DB4855BB810C458E10F6A4F5B6E47AE87B220CE63D1FE49B7C1A9647A25C6BF5876470A1090E36A088A02F81068E35B02CFDB6720543567DDBEB55437FC168A2DE64E43F5D8A08D73979DE793D1D1BF8BCB0109E1B74CC62F7E25480F37EB8C052A8A73840B5D517718B97FA1075C633E128FA216D54A0BD567087B8281F7F173E02345CC12C88247091039F1A4B343F6AE85838A8D8E26E333BFC70F3798DB35DFC45ABE2B4C4AE8A383C9B5C7F2F67A624505B062EC240A597AE60C344AA33B0901B5831DE397DD986482B7ACBCC6EBE003BADC5CB54944AF0E4A86F792D4CC221DC0349BA2F5C9898DDE4866B352B076DE30FC3572B330EBA043A2F56273FB0774ABA354C362826E0A98491336EA8CCDA8A1ECC91310BB6B07059C27DD2648A3A0CFFC3BF6022D62C481EDEDA294E6D890A7D3E76C1637B9C44BDFECCA11737417C51CFBB44D748CCC980362EA8E34AFCBAA312A6EE431BE1566393FBEF3AC642C892B83AF249F80BFA96466B560B5A55E5B8598F58416AA91ECE41F92EA839ED31F2DF7E40818DEE52E731E8C557908BC42651DB61E2BB6A26F9D6A99D5B54EB74B481CBB2650B1D965114D961B56D49D7FB379D2D1FF9E58F3E8B4B9530F5AAD0301E01012D5BCB50AF8A32D3D121FA5598BA9EA4F97F3633F03BC62BE8037FCAE90A1C825AF5B0F9185E4967912D659D2F1760C349C658477711FD786A39EDDE44115CB7B93AE185737D596F4C3C2B72793ADE93B48B739129B54B24BAE6276D327E4997B826E76461AFFA1D40C37A4D117DC3304C643490A67162CC151758FABAC974527CF267A2EB4E0EE0AD617F8BDCCC4553FD09C8CC5E7F0EE5B5E3B9F24A6DF21DDB9CDE334EA79653A73325CBA955AB9A16B405EC7A219FDDE3A22D65652208D41A1D93F503CED182348363837C424D7E2D4C0904758E09A76807C30666CF27BE8A5780DC56CBE1BBF369DD8E3C5746E3E0E48332768051D7D76615DB2D6751D2F9C3F50074B87754ED630A6B6E8F03827D54BEAF81AF854F4E9450D93287EA1F575D5F9E79DE9F9F123229D0746F94712CB5D715DCB90F17ECDED45EFA3D2F49E3A9B7D8F1707751D75F3639159CEBF2411C8C7C9195F9E259D1B45CB272E85303E68018371B85A9931E04E9595E65667AF199A580D24CCE1D7864847A1F973E29FBE5D771DAB46159BC564048EBECB077AB317519F54EF1467B59BE03806B048A59727DDBB30307E44D9504D6D968B3848754DA6FB98511555824591D394AE68E4726BD2439C61BDAB499C5BBE8B7430230C154AF04886FE18D9E0163E0A7E908C491CABB2C4CBA56C44B34F4C0E9416F1057CB05758E78646F8907FC2F99C24081C882910F9CFCB801DB0B3FB6107B2213315E02E3FD918E6974B03401DB92D481AA5E9E9ACECFF9C968982F925DA8641A386E5400F13C83B43E9EEEF838AACD8D1E11B4DA68D351C4A145CBCC0B7CC2996F72AACBFB9EE75488E9B04BF32A1A7B68B9FBCE94DBFE01BED9335C9071A0F269CE8831CD468CA85AA4265AA0E6546067D84B35B7AC49BCD629736C4FE5816DB86D6A1318873CEFC0306F28377905CB3162EFE6B1293D88D520038CF4EF1F2D54E13017DD720512E7BB32B6EC3420FE1AABE01AD4BFEC100DC5858D8A790859692526C4EF68E5B9F448AE254E598676E87A5DA848298039838B50F0C0A2604853B460B52F6003BF15ED834F1D6EEB20E4F1D32F5535B30246AB558C0A267D3FE40CAEAE2627 +smlen = 4827 +sm = D4D1668480EFEDA05D585EF3C39D0000F39C216251E57E6F4BACA45CF106776D4A17855324F71B5F56C327BD967DBF2EC0EFC42A66E0FA23AC5AA8D5E504E210AB32DE9437C82C55FF0281E39024D2BB8286677BD478D711015174E8C738B51D2A1111E4BF2D3DCE52BEA4B76E503E902EF2482E5A223CCAB51A2DCCB8AE015AC0FE6E7163E2C4F9B878834D7885393552A2DAED89A84D2820A47B660476A2ED42B26AEBC22ABB1DAD79BD04C9EA819765AB30931FE5638C29F48F77C06EEA84DD984461A7398BD7A5B5740DD2EDBA3DC065B2BBE617B2F27BCFCF68AEE319B9938A2F9AF57C9B40D4B7C914F6CD3C49D8C06975B7E9F7AB27D6E35C547F858980C9DC8DCEC284CFB980D326D41924DCCCC443053F69153309BD56CD61542ACDB6C6038A56C247A6EC837CBEBA2883D86B4B17B6DF03AC2F05D94B11BF4182FB468CD3DB2BEBDB5CCB7351D85D80FC65ED23260921EFC67669816B8F7724629E9355AEFD1030ED035157FECD92CB221A039A90E81F85906042B9C4AA3D8A4AF9BD8495109506B1A8C021897B88A55CB076BEAB05BDE2F3F0077100767A79B2C72949B8B3EA2F4B2FD6CEECAE44F27F416A95A9ECAD4EE3B1407E71444817BF893959A1C3CFE2701E2E9C4ECD4E31298DEDEA7B39044BACD4BC21C483A1EB52F6A3B6D26DFE1234DF4B1DF1FE9F017DEEA790BCFCB916EDBF5D13BDFB8884169CCD350AA86D842185069B0C7A904EE1855C24733CDDF9CE0E893DC34F61E457F730E0B1A342C69F240D1E7402328064BD7BB7D76DB7013AC73292858FF72897FFB21F9D8171E9AF780FE354F1C1E7A678AC0150429175CE5EF135C736DC69CF66070906025FC2F8571294F82783237A63DAD0C4CF22994127AAA939727976BB0C76AEA063AAB78E31F80F64DD98145D343E5A1B8129C6AD540F10A3844C1206E20ABE8F579414D55FEF4F6567204AF69AEEA029AFA6C26CD78B6F6186D63B5AFEFC2D3F3F2EB0BE24CA2B6B10B79156B7640033AFC4A3FC94924CA2F6EDCEF7BA74F316139341F54C4E11BB6C2CD30EE2AA049D27D52165CF3EB879F4FFD8CCAE979EFCED47E62BFD18B619B2D3D135E974FA4684D835712BF0E9A53EB235B6211457C2F08B72B44275E67C95BD87346F938E58DF2F27F7088A20F5538858F7B2E5AD0A1D008264345F1D578C7DB4C90AEE13ACB88B2304F830C9C4B5B25575124A7CD7488A58B820281C61165EA7A02EAB31D497E14C696E2C2E9B2DCB4544CBA30FEB850B8DEB9F4A60DAF3FC7A45A561CBDD705781A12177310BF33C222912EC68FB6C3C46C11CC50C8FE2D67AB5A413A362637B2DA3868D403C3137DD7EAC47424035597048CE47C564B772556214A2BD89B5406EBFE2B1824C0BD4B694BF8E4176D908774F262AF98476F77D7478627531BF65EF2D636E6B0A8E8CAF6D7333BD75EBBD8B7C958289C375B4A048E2CD01F5508F3580CA72ADF799C4A9F76E1548B9E7FC7ADD47EFBB23E1CF4AE569FE62294A93E64355F19FC8E9E146F3B311A43AFA0FC2FE0E8A5A75CC7EBEC0A66440498DDF6E89DE08FC5D6BC6683713DDD5B1B967AB7ABBC1061BB0FC75CBD0D34BE5533AFB50B5B810D4EC34DA1EE67D786AA751A87373BCF511781FFB0A333F3CE5D56089D598F0599CFA0539577DC3D122F7134EF5595596F9B907B784DE1FF2FE0F5500EA252DCB19A3675A775057C52DE28C49BCEE0723B6471E1FA32E7AF70E1E32539E320439C03ED8F5D17BAD373F796ACBC08D1371444C8097550FD24D7D30786540FF7267527D260E8A19861F41FE49F207C9FC213C7B3929F34C98135CD12A12C4FEF9D383ECB395A8F5317589B8202D82DE1E6F504707B0E128029C9D2C7C017CE58FB6A84E9C1496798E2D3AE99300AA3E49E5E0BE67FB91E38BEA6598DD401022B16AB1CA32C4C33B6517171C8276F2A6E5BA2A7FC35C6F06588CD9DBBE18E5BEB182D0527DE2D644E071A6A0CD7D6BB9E27195CA4C3E418DC1D7CAF92FE4E163169BD5945653BCCE6C249D22A693BD6D59FF06416E8B3B714EEF288D655BDC40509F07466B03DD2D674D213914F0FFBF496E7E1EA54D7B9953B648E12F50AC187FDDECDF4402D97181B55D43B225FAAD31DCA4708D2D0AEB2215A3DAFABC3FCFF2330A282DC35F8E7182E61AB6373C5B75CC175626FCA999F3E0D28D84952AEF437FCE079476124E1574DA75DB787B2F8C9225CD381DA92CC082DD12DFF04C3407D983FD8847C0D505A00B68725867541D95C8904C567CB87769DECCD244A9C2698C4BAB5B13B54DAC5EF9639E388DD5BC2537CD586CB84AA5E763A34D6386AEAC0CB2425BC22113248C9ED279107DE10211EB3D8A46933AC3D6ECFBF2AB04F905E4206E561AF1715FACA502B5FE206B476A0756C5756B141C1198FEECB4213F89BE80A2604EA171F6685D4AA765B13B453B939994DB911FCD70F749E675C6F11243CC7F5DC42B749CB0F63D5EACE0BC03870D456206C4B2090696C22E6C8EBB71A5B03D40143C05235EFBECE176FE6DA571A31202763D13D57F8DBFE5AF8BCF9EB55AF3D853E40A67623A7C36ABBEC5F006385064B68F28800D09D18AC1DEA3D14E6164BEA7DC42B46C9692E6C575DB16D6E874AC74D1EE82335E1AC58543AF77090B72E34637F94C68E0C3A3C095FC2F4FA6679931D460F69F71480485BFD5D113CC314201FD27F82ADE3D9D09AED7920D3FEDBC1830B229F04172C42FA7BF5876F638A6129BE5ADFFAFCE4A34B3F1ED2326E9DF5DD90BE1B35D07A759EF57B0C847080B056CC695086D780C459E0436FAFE0FB6E663931563579D303C02194CF12CD3D45DD6204B875358D978B998D2B5FAEF553D6F9ED3E351590A8AE3D9AF6B9105C62153B05AF3037E07D7B186EFFBC42228440FC86F2FA103FF222AF5DCB39C9621F31F1A198260CC8967EC6A6C9A850A83043CC652CBF37A36BB1C0605E0BB14B6FB1918501078D9D691E2AA25D184E92C510FB1154E0FA7538BA398AB47B24A0C43630834E74A795A9868CB796803FF87DCC9A3504ECA29F50CC2E8BE986FB622F024ECC1257A99DD865C42EDE9E91D75488059A872D98DBB484531D2585C743CB64DF281DCBF81C16FB07B8EC195836486733AF9488819CF21A774BE47DAD617E996E41C1CECEBD16C680BE16CAC3455FF7BDD1E7A5C527E7E52AF8DFDDB35DC5F50478C573A7F20F920D802F4B41D726A35E490FC9C3E37353128EA998B5637789B9C58F6BEA1A5C1F25AE68613E8A59FD46C43546098541733F46198279123F3F01EF53B077FD4E21902A3358784059202D3F9F4C48F5E2D473191299022CFE05C4427B2E0FD8C08515285819C05FAAFB31E86B096A018BF9425DDB5F170E5E86F5F6FFEBDBB82C88E3C559FBDF710D80D8CF8E959F5FA00ED9F0F955EDAC6733AA333CFC805B9E07E6065795742D0D844C507CB348D05450316C64310655F02B5CA98BEC89D312C62E99E748E9D6663B71F13B8ED6DD75C234EB9DD81DA142318ED00496C7C6DE577ACC6288F37B17EDDE5BF20469FE12861C9521F604A5A17E5FA715819DF0DB8CEE6701AB82362CC61812F373F02C0B7C627484325E4D6D001F2318B3416DD1B0E5858D68DD10BB41E8AE4BC2DD645E1656032CC4789B46105D6811D8AAF3DA1D3EBC5025714241D6E2FCF562AE8606E310C76DA8DEF4EB6F666D0889E77A2FD351BA22CF09283D0B846CFB6AC2305446EDEA229049EFAD643A0A3F0259B3C9AAAA1DD80A3FA0D12D238FF26C9E6FA652E58A2B076BC66975C1FDA54BD951AD12CE32160EEECEAF9EAF27ACCF110D040716FDED232EA082953092BDBCE826349DB6F711F9D85F2214231287BE3ABBB6761F1346C3362F8E17AECB0F077DD60BD1577612256D6333EB7C989C4E8318529D02E5CB206C288BA23ED3C509BB7002F943E08C66F3C455DBAD30C7129D6E938B7C8BB401083D6BFE53211406B52121E8F1373067F0F826EC8853ED6694E931460970013B0E6868A2C2BA6CD0494B1C87F76B7DDF36BC792F4588C383D3498C4DF3A5527EC527027FA9F3437CE08F38C3F4EA00A1663E10676FD0991978A68B992920A6718DFDC8E444DC665570FC55CFA7D37B18B9DBA571DDD38B72AB3AAB2561DF40349A62C383DEC5C7385F8BC3E39DC0E73D2BBEA7116DDACA871A26B037B205AD0AEE8768820BCC09C6124E368A7727AE99D5F3E46B5CAAFB96C65D4A341607C911C225725CD148CFBB6495EB9954A107D9A49CABD74FEA38D1D4A4D77B86FCF8F294C0FD4DC837F2B230BB739DB12710BFC545531C215123826FCA3C43183F05B4E3CBC1A7D4B810E66A596B75C9BFFA2681D39F21B7163D08D403864D28099A41E57477135AC4F6F5C6FDE4DF5217E82E4C6927C2C24D25AA6EA1492AB99D8F841F4220BB54ADC3BFC28FA539E7D9DB2A5CAED211F30F938AE10AFA38431A5BBE18E5A51E8DE2B7D74770A8CB5C9E054C74C8A7CEDF7FD6BD62A4DB228EEC81D1F28E2BBA12E72775DAA3BB962052A498DD36F435694B2443D083BB8AF21BEC4DAD073D2A42E99A2EBFF1EE95EAFE2E8E0F9DC4597433F4F62637AB10F313470A9CF6478888B5662A3A7AD0D151A687779EBEE1C434D6F8BA0AAB7CFD800000000000000000000000000000000060C10151D27047E2D484D798B3829CA6037D6C1588A2349DE09C5DDFBEC987652CFDA01454ED791DBFFA3D9DA13A35230ADBE1B39B042E3C70589658A03F75447C1CF3970DC10FE5A4A9E980F2A33B642B42E5E66E9AC4E7A56888FCD72913A79489B5B163BD37B8C3C8D242FFEB37D0C1ECE21034BE9E3685798C2EBC6B809DEFC02C6F0C2A3AD70EC0BAD12D57ADD63EC3584CA98E680267FA514B34DE4147C9D901B59914D49CE9E0F885855ED0CE7973F3307B675408F90B51C6A4D38A414D970EEC989CC7900D7723E19ACC4EF743F6D39EB1B563B8C13D42C0056B6C49732854925B606467F7BC662D17B924FC65E9C3CDC2AE73FF73040011A152B05ED7F96B2FF4CC39A22484AF72812EF02B08EF4DCB64C8936E74549AFDD5D876027FE2B431E61E52E8793888473F4C1E5C1BED2C4AEF8E5E300A735B302474FC6F54869984F1A62DAE29C7C9A0CCDECAA55FE137BA14B5C5C121E0C5EB33B035E01F3415529E0826B27498D7A71B0C086BACD140C02A5948AA54799D0DD0FFD384C7E68578247FA28D205B18ADAC94F7D3C8ACB7DAF71AEE347B577D97EE8E7E865CF4FC1C16640AD1E9D0192AA13AE81A71118408E145B6121ABB75B4BFFD1D403057D4AD5CC730452475A7F067690BB81E81E17BA8DBC31059969B20D387BA59CA8CE499E59A65C8583F29CD539F4F75DDCC68C7BBBC43C849802D8347143E2FE78C1AB6D7AB6BA9917301C88386B294AAC995C24AD680A8C3BDD7AEBEF21E84F5A1909A2D83A8DFE46A75F4B2B47614CD39BF3CA3460DE9BB5C37EB7349A17AB32214D031CE927806FA394470F407673B0CDC3D9A7E3749F09CA895D464A4269682CE6DDCB8FA0EC2F05372C73DC3D06FA6F58090EFBBC6D619A7A565D4EFE441AD7E018A7F5E1384B88EB4506FC54E0AB0A8B9EE3641760FFC08F6BDA78C12396473D1243BAAF6AE10316213115441C0B65C7E475B4E1578D066A47D9C6E92FA32D0F2C365FD15F5A2E88A81691F039DC642ECEDB6652D08ACBE64625B46083CE758FA96C142EB34477E065AEA04A45FF4FCC3E3D146ACD7041F5F7E4C6B26C8205BE7B66DB46DA55556CE02B48AF55A4710BB28B8CE102CB15C1A4AF59D9A17A2DDA6E2D1E96987F6AA9F4216D8D5E5CBFF7E2CB775E83A776063A4AAF937BF0EC84149EC1A7EE21F735D21625E85831B80DC11EBF04F30B13E3A7E4D4784C5F8C61C679E0B6863958F42ED31DEAFFB4C272A3731C1407445CA7673D225EB6509469DC6C1F0AF43EB00F18B3A210AA57D51169F2A9FC251BB338ED4E9DDB19282DCE871211D26482E13A8D533DEE00D36FF5CEA98DEA72D9F0B32DC398A3D5537A3373058FAAA3926C127A1EC739FAF3D57CC1A05D578074A3A72C3F2B1692C2BA1F1FFED943E7BFCBF1E664C4F52F7BF8D86174CA8910C290C06804A7748DB21008AC43E653D7FD7E0C982EDA9356F68DDEC26473956DFF281F7B767010C57F4AD09A05063A6B3CE078DD32F3DE1F40526C06A2D60E36E2C70502D5BEBFD2F3BFCACF8720CDE1657B9892406BAA3DF01E59313EB655B6A545331EBA01BCDB9C99E4AD7FEF7438AE8715FBE589A2F99CB9CA34B9610B3CE5BE38FCF979240698174348417420AAB069B8AD5F646F82958A136DC9F2F81E601056BB4AB5E10F4EBC4A00E18924C51D0FD104078471C6805C49D92C78C832EC3F10D8966E19ADD3D3B4516E12DAF4F63FE6BBD228062DB743D1F867800854F7BB7FFC2CAA0D01A0BB683E368673A8E664BBAA17A8C0C04BCFF05246F9C4F3020510A992EF26FD0933BBFDE9D042862DFFD33A6465F590A2287D8154777A89724FC3DF9F2F1B1ED8765E7C7B761CA4781006822065703ADE07A6E874E70928E1ABA29EE490690D24F6E73D96B85FB53ABFD1C1FDE439279E08FA232043B2344B267CFE5901C60E7CA14B0C85EDCFA2AB90F341821D2B4E25FE23129F2432DB932F23B5957706A433B308FB918D1C8D81EEB399BABE95E7229AD41F30460CF28671A4508B0BD1C61F48CDC23587BB9BDC6F565E76C86547CB71396661BEC8C7FC2223751F765C91C45C674C36B49AEDEF3DF2537F888904B507EDCD89155D40CB81DDA74376BC9CDCAFF8A368F1086C99EDE25526BC53F95F4017 + +count = 46 +seed = CFA713E4A63A6FFBA43BFB898956DC400507F68AD164C3D24A67B5F8D7548C9DB44DAA43E5E4A0990325A4233089318A +mlen = 1551 +msg = 6A58AA820275A2F43D0F05DD0EE484AF42B665FFB8F21DB322ABD256A5C753BC8FF6A2C71467922E09726655F1A7218E736752065C871221C0B9DEE6A9D56B78A1C3B7357774396F6980226DCA1F91BA828E06BBF324D5CCE8D584D9D298261C7149899FC9F74D501E920F22AA34706A79213E35914DBF57B9642A42EF0D8226E31ADF89D18C5F3163ADECC79172C95650D764E3729EDAA08C207D930C26DF8EE1291C1CF889283B70AF00C0489175F799273C837B281A5D1284E4447ED72598EFAE23B523274644DA19BC0359BA59E5BE9E5828FF587C335E136C1D789257864D2648EF9C03D1C4B9809DD07CEABD865254D3D8D597587D71E374FC2DDE89C22C2330E8904F6B53F637348434A21ACEAB9892D5DF8FF84CC58229782BED739BFB13448896F7B1064B499087F7547CFC0A49272C2A670A9431B1B5A07284B6749EF834510A3EC0C61A43D5D0EB48C8F487947C4FCCEFCC49DECCB6111D617407C76A1B4A849C9A190310711B102F142F9E9CBB29F46447265E2C8DDB9174B780EB4A51003FB68483A265F2475D5BF6ECE18AF0CF31BF24CDD56583E777C4340086917B78068DFD380466F43D020E285CEED97A467DB96BFAEC22D80B4A6EC0DBB98CFC44436A41CADC85A90B214F00990D7B7010BBE4AC94809A0450C9ABEE5AA4037A44B0B4DEBD264120E762086B8D6F17AFD37086C93A8A368BE97E0F7546AF16D731C21878063E38DF3DCF3ADE6DD2DAA43C198F49B5D9FF5362333F29EC2F13CBB90DBE4E703EDAE9A4F7334A1C5AC60D5972C4AF2BA61B63C93BF719854E615D16BA4F704C55260A8838679815FA59BE08C4243CACC1A584CC1B4E777FCDC6E5A167C4CC9093749ACE4836AE058BE89CCA3221A3F63F07089006E4C44E40653BF262945A640D8C2A24E7CC3529E4BE76286C86CA2089CB8D4684508D1FAB81EAE7D8C731B65A22700BF9009A3190F5ED837EC22F9112383422027AED838F16A7740CF79EC101865D320E380D4ABA745ACC8EED376DC5B3AABE58DEBC35F8E983C92906AA2E3D8FBBE237325302E2A23CB1312EA7F532D64E79B9815996D28E0183EB728A37E19CB219987576C142F4B2F66AC6C7C77028ED59A8DF27F78ACD3910DDFCEB88888B4A604E5D07AE1B53EA6DF6EC2163DDC4BAB422D2438FFA543B22441E50E4087FDE4BEE6D79D90A2F72548DDC41C5AE07DCC87666EA3C4B89A0B14AFE03B585E7CA507E5F29997F2368B0C68C6AB6E344C082BD06AE922CD8089634918D9132DF9CBD665A4149C59BF76B0E94F66481766FD79054AA80C02E0AE04A6E2BE090582171B2A9AF455CD9FC302CA9D1EC837EE26E0E4D0AC8F0692CB9ABAC979B58CA92E5194EBE46B520125BD0B3ED1AC2BD817D3510E33CFD17058F865DBC64E9B99352B6CAF10F0A5A47449BF927A8EBA06D34C80D77A0B00B88B25A4C8747AADBB11BA15ADF9C959B05C4371CD8439FE5028E004A2E1D2F21190466FC7FD56E9BA0599A0EEDD98246AEB4B85994787B7604CB52F5515B42C2FBD4B5E9E372A36CC4E66483DD884DFE42AAA5EE7FAB200D8EC6E3556DDE0F9E9C7346F9967F8F3CEBE1E4D1CD8E6046E5E94BBC74AD3D51DB0DC704F4A4025383F0391B9DA37BCA8EC59E807593A4F040FBB186607280967E5048CAB92215DC783D9045F7A0922008628C771778661E97E9F88EA84BDAA8BA61126F71D193A2A564E3ACDE7ADF2C0B3D5B022EB6E0C629782B0025C9079D4545D88AA2BA27D10C5DCBCFB7CF648939155066518878CC54A4F611AAC21BD3A1EC628D3352F049915FCA55234B9146ECE5F78FBE7CFFB35695363202EDB9EC3501A93B4B6FC81B3DFDB5245FEEC8AA54195262C2467E15506B7D42A7FF61D75998722D0208BBFEA05CE7D2E66900A9B34F44C2A21257C220C03F9D6D7F0312A36F5C12DA20FB5290D5CFBC1DEC7D05C44820885C479063CA88783C5AA128829417EC4DD41CF83A1D991DF2EFDFEFE375E93F0371695E353EF737F4A75106211A5F70C82B4F360ABCD078C9E829C82A6B7A36D22B8D1F6E3101BA009C759FC83999D52E29B387A8DC1658A43EC4C4D9330A4ED2138E035EBEAE6343A76A82849E37141FCE34E9A41EB5EF88BBB9257017AD8696C3847FD77AE103A082ED1A05DE9420984C147AFF927E1950244912079BDBE5CC07 +pk = B1F55D9E3A707B3FDEEB5FCD9D77A5BC6F826EDFC6837E8F04E2631FD7A50E527AF17A3C8C0A45F2784F626340EECF40D1383D7A0675C4193F5E49477AC07A979A9F3D096BF4C93F342E8AE3BFAA928D74D9E141B72704CA00F60AD8C1098640EAE61EDA3B0CF70CA0D060D7FE4A365944DA460227EB4976D73BD8C250978FE4E7BA8A5B87B890CFA62F25D80CBC993B9AFD7654CE04AF6861BCBD641BC035576AB99A9F6F32604FB3C607E17EDC81879042A7C67C1321F9D912720E05D980A132F4995740178B50728AD6BF99832668D805F210DDC40204AEF376E0400D7C7654F4665FB6549911EB199B6844E27DD94F1D67FB1AF22C8C5411B7E4C1F2B6C11F3D28B81DCEEBAD074DAE493FBE8B8CAC3B0B92B05CFABCCA5A4CED5853FDA744E3E967650FC726D2FA5F1A325DE00B835306302DF17ACD5114747EAF3A4A21271B87AC19738BB4E4E798219572E89A741EECD734AC5DAF3EC66594EB6F3B42E16E1F3A2EEA76EB0039A66B1283825B2E3FF102F55940709F35486198572AE455B4F33E10CB9112CBA174DB5C39710270B46035C1A9C8531D7B875D34B80FB2072B608CA9802E48A54877623302807C11C9863007764E0B102CB19673042D27AAEDF6A8B3B911D8CCF8E1F6C1FA043EF216F57287A50AA3962C975A6D961E640AC4F712C4373AE606631877742C97F8DAE18D72FDF63EAEA1902B94A25B2ABE84AA1F274FC5AF7A714D9BE70395407592185B13A2B978CAEB95D2BEA1C08896CA1834FE13E0AD9FFC36075589F8BF5BCE784D092AD9E31FB95BD03ACADD1BEAA3CC656773ECD5EAD4BCD73FF4038C8741558B956A84BA449739EF2F2D1C03E8B0BA2A05742238B162271FC482E68B4AFD979CB7580411DB020E7BC55841D295A490077D7F8E33A37E4BF25431365712E023ACB93891105AAEDB08FC4125C03CE66B9514273BC2E8CF03FBA592FC7CC24D5B2CFAA4082F1E1BE3C8508E3D3EC2E195AB38129653C85EAAE0B88D191D9145A383F7C57D87F200EFF7C2EE16A29F5C9F028C877FBF8992F97AA0C7E48F85C6B1C6AB4DE1F2070FF05E804A07159DDC79602BD79219C51A0A0BC710DB75614892C2DE1FF0003306848D87453EBED5B3F4A42C1BAC6448564E1BFBF7FD1B3A9F315D859A1F9E8CB0AF9A665B26DEDF10116882FC9355257D752DAF947A10A34143780E3B03462E57FFBEEE86E2CB88AD71810B3D6D8EF46CC50BC6ED495D176134FD4A30B74C7A5CC375B76674DD3462FF0BA676293719C1166A385D957775AFB2940BB81AAA4D010991DEACB2C4711B90CA55F9118068CF0CB609FFE90DF6FB844D5AE9DC56E08418AD614758082D6934EAF2141AE71324793426AB4419083854A11191BBDD0EF9B535A329232EAD5D4E5282B241C749A33C053010D96C77C10E529671ACD4FAE7F0098AEFE3BCC51FF80C57048AEA4FF5FC494967738C8B858B678E1C27788FECC54FA397B8C2E67D0697AB9FF9A3D46E1E129C4060FCA40CA38FFFA68BF6B144C134BA688ECE5E53170064330E4BA1626BD6CE7B9B2110EC0818752B0EF1D353CCAF78293C272EBF2C662A92935363ED8C71221364578DCB4D488C1EBA51B79836F61CF4C019465BE9DF3853058342A6C5249ADB23E4D99BED644306B2605CA397133EE1EECBF00CA5A506FD909EAE2573495F557D3EDFB02C9C3ABEBDCFB82D946BA6AAE73006CB9EAD9ED23781045A27B9C5640BA6DCEA192D2F0579BE05AC259D629BEA5EF7F962E295D61A1759ECEE352023C1F74AD5C8365F36D75C5364256F99ADC2D54B8F411E8D72F9297267EE7F6D6F28DED79F6F6B9412313B1F4942CBEA7E274E67F8AFAB23881F7BD0005A781AB94D91F9A2E2B79B365B7C85F45AE15105A713F0A92D0D6213F947DDF9ED62EF618813BE619B5947F189E537EDDC1EE3C44F7C7EEA80F3DD388DDD7C36CC7A9F03A821809EC42C6021D32B59691ADDFB8DA175C394D63416156FD677F7CA316226EAC98426B7BAA74A52F38B976C1191A18531A0EC8065108B98CF8964204C5BA43E8626676DD95A82858518800E859FBD6ABD391AE9E6AF4511AF0844BAF429BFE22A068791D6C65EB7DCFA4BCE04ECEA6E6711F57B9808FDBA2221D8A9D8330B8D1F16F55AACF8B49E49E939DBE92744CBDAFDC72FA8CD341AF02D839B9CB973644E5C0049BF2A9F1D073E2253BFAB839684B30AF47A9EAD2D4C17275DAAA8108B1EDC699C13352E353F532646FA4D8825C9AABD848E0196CE06353C7444ED799ABB3464E9C8E67E7BB9039BFE5E771E7EBAAE319E7B3A2A5A1CD921BB251A3D99ED4B4D952A0F4C9D3E32FE09D7A675E662C4520762F8AC346434762CF5C7AE3F3FE114090BF467ABBE4E2BB77C5134605C97B7F77CF5185D67E104DB6893BD2197675FA350E79A24D26388765B88677E0AE2B3ED58C6D2760A01BD9B4CC99A23243400A54FD2A3C7A10A96ACD4FB2ADB204D2E15C5972D2CD7597A898ADA6F5BCE15BEFD034A76AA0BF1DE7573B81329FF649B6E7B150D22B6B66285CB58C3A5B84192B160D150EB239AA8C92AA6D9A895B67505B41E9D2E25B1605973E344E21D352D9252B9AC5FFE0AAB27E79C859ECA3A9115A3421749D9B67215589226CBA27A103182D25E1A1412DA7F5CBC4D52C9376B74259B668E2453115413631367A10FBB4030802A9B16770FBA44E1B8797EFDFB957AFE41C2FB3B84EBEF3EAC3A7931BD4288B069F9821AF4F869B8A65B8C5F +sk = B1F55D9E3A707B3FDEEB5FCD9D77A5BC6F826EDFC6837E8F04E2631FD7A50E52518D7DA525DA0DE21B84752D892711F3BFFA0EDFE3B2BE25D6B1DE65B5DA7B93882F554C5FBFB02B8ED60D7A72BC5E8E98643AC094DD76F064693DA1DD327621FF14C890EB169B75A5069DDCE8D0680C6C8B7EDC474944B3D472C92ADAEA3575115052063114817023538447676072484217876052238086543383584874388817470723213683422588064643661774315865100688074564205640383162675480214384710237340837137507657671542702243780124124785800772563104684473026150344587776202413035242767402883516766118177547021342636454601102624260235351681358661478764318270554775423475430004346058828815421620352385502568212145762644853657805112420054761002785482745581404105018062510018761754183880083366266087074136742137663646755456753700287383348618815533123666457327126808735474430220458101673562830816644401502876284436748810034871772681201124204303465315372404406337085004241284388410600172803514027488155461336856346007750082747144328144513844164238262445883646307656580477103854042666115420211350283344457460056552604370262636354007507871404238127216345713460565733403456060428335878234051412110674301606160167773538756143714572723533083468471517051420841807210635284654010513853626000057857016231555853766548557478712326873536528553237441532676015307448750100526845268647068070334501602803560524805885282526781780406135002242828641558510325730518528253615581284787314551145425818816336530218732350867264188022121048365263337007746703587077864381588483367508054360613540882575648731208785167781831046812106502787800874016424345101017856411551511548210482400463002700066301037601013357828675158880162816857811176048334148664000370831586068607613174636006732116556807833130280311830311465245286321031661264765618346586314057105575534331772086361143655633448080128674543676717753618451456634581365357675451378564443614186617866276068532383018504424207154331152717007526413530274432512136007017350423513701082805424828243331288524138580076225707185247466540142650074455372678381754032850128877307605157743412813675434641163834436636770845030232065785613066413415653011135427302218541463106175718705831477468382675504351267565400746353137632778047560768282240817038616201712450203643656404804234177563436160384315451460555183331032713644178836033424563003361014242143421077527128415283762104034646872450248656671585240127755288050221587237366337177221772654846608466621148603812356418715867325245506475411846687655574716132135437511266000687365503556807066600263064184106570575262640833888618156602060467170328408342145605787176260600818140143850381423410512332258235746770178047318786083862623357624434354310460838247448417231418384801758864113415423158117302828047358588128758781576726336306262282264251872365650350058175811761155614201267064721250670800485602170361055185046750506805414831217037127768785606754523733347302702508645341000776216332365742320608653080733126846608184670612256443207732243248254385804022374675218013457450175346307812077858118778735542322773517431027537286760126286865641770502473303583514112013068566057256356526576563433715581123245241556601600765479866C07DF69AF612FEF8913E4C2BED569B4399117C66A9C540C786BAB02CEB55F2B64A88D901EC15AA20D537D8A419DFC03A69F2441C8E824C3293B816494924DEC68D2139B07108E7C6108792980D83FEC66B9E82CD045ADE8F528B046D8491639441959A9228167511421829BA05A7FF10C165AD95FFA4A91BFB9AA5D91610581DE84FFC5C75799C8FB8221BA5AF87BD3A55B63E8D0F29BBA3874A28268ACA21B2A05F95CEB45128E2794E6D46119E96032FC8692815F089F75818EE00CAB8A12EE5C65EEA865BC90485ABF3B8342FEE67D9F1DECC416AB58816703D6FFE5D02229F0E7104983537724B809C56408DC464D19F26664D1284854711A0080972FBC56A87029D155698E8DB22E1F79E81569E255AD63AC29191BAE34E0EEFE2108DD38C0465AC93E710DBE680D4AABE8CF213A539B4C123921E6915681B71E6F5147699B27E5343B7ABE6591AB876F2BE5BD4424FBBF3E352F2B4B7A1C0F7E5392655D9DE7489CE6ABC990C5BB527DEF3BC89E5AD0FC223A1873D368018F703AAE5F93DDD89531058657014F11406D16847114C2F1B766FF87F7CF98E4C698AEFDD820141BB4890AAD7FEC3289F5C4C46C6680219D0BA727075067D088AD167DA09CE6B455F11FF37A8B1CC05F5109AC95C073AFC8CE6268B36B01614DCEA90BDE033D437D6B700FB059BAD791D64C8B1073FB67071E4A502481A80D968D962D39247D4AFE337604D7B0C30DE0C8B4090BB2E612A40D5B18EF060AF68EABF1B6C43B2E44C43E46786D88D75D435FC590120D494D81E1A9857ACE7A1741C2E3A90D5B77D7DD2B5C537517489D2224665FB720346013E95DFB55947258D3BCDA6A24089B66EF9C0E9766078F8B6E67A537E94CC35A8B099DE22AD16F81EAF07FF1BDFCC8E5682FF6DF5B8E9243657A4F437D49D69B0D803ED426FA5BED001BE5C046A94136846AD6A2351AF61093CBD0FF0994D69A3E24471F7006D0833F9032BA1501D7C874DBB901A09B8390B30E80E9EE280A37FFBC531A77B35FC52B50ED8A77A8CFEB4F28573DFA2C4203A324D7ABF21273AEA8870817DDD0BF1EAB4931656D6A2AA51A9D8AB5E6A8BA73D5D320704376219D89144A8D71A76CA9683C39CD5F28E956DE6536010C8F21C53B945C5C74AC00F61FFF10EEC66EB915B9D859209CF8109E715C05C2B764D65ACB4B0B4EDFF1878F5C27134E52747881A5BE89C7770C66BEE3F9C2E84AC5F08A5AE0553CF008AAC1A683F6DC180E7AD06A038E11771D9FFAECE5AB611D2860AE7B04B85D4264BF4F71DECC165C0159F145108280D62D4DE6E42CA9072A1A490196A2B7E6B5DCF4CF31A40F7397FCA9D6A2A0D7B8FEC0C5894E83A31FB078F20FE9033F3C30F0B66ED4C3322B625B59A8A5FA84C556E4F8D5B60919EB64964A685F46A234826166662A10DD18E5924487EF84E2396546099D362D22B76DEC488CA24C85903B013F1650F453F53E4FECBC9E9C77ED7E3D062F258B7244B5063619851438A09644F586DD995956A77F29F2B952CD75ABBD2C9EC3304FBB99F62B42C2D449A4A8B40C47FC38E2A4EBEB3C35269E9BF50B09888C10AC18B8428E368B5BCD7E2AFF28013DDDA73CF5DA355F3013FD7D722B62B6F5981E0954E62761497E9F7D8CDFEB23ABDA5FE604C68CCE221B95BA243EF93F9E4AEFD579B605F8C37BE0C6E58D0C67790888FA011365B5DCE7A7FA0B97FED66EB36AB7709F248C7B38BD9FDF34360793049F3B5512A99E3A1D0B4F3CB49593AF2E34FDA2CD681E1BEB919FDEDCBC33C8A199BD24C98E36C7A0CAF50E9B8AA7E4128D718C701863A497474723CD5EED82C704BCF1163980E79A95AD371FFD491E75618453E4D09CB5980492A1B08C2E7320CD277B7AFB6E76A6CD65319B4D6C7B9CE6B370E89EE65267D24646DCB980C3C1C2CA372A440C9896CC72A910B1EB12F6BC2059AB891785EB1565CEBB0870FE1A4BADA8AE156F9B3A853E8A76641EB146061D2D800F047C6776B69081D06DEB21309A3A8ECE2E5E0737A13824CE07B82854F881A431A6C86B4604C7B9EB93291CA39FD08DC6D7155FEB7F1A2C1A88C07292FE3180F48995299EC9187A218F4AED71FB1D85D181E8B4AEAB532E8EE694544E10B8305E661D1FC775534E69A94220C61F88FF43A83859DD2554DBFFC0C3C37EBE147B4EE55C671E1066A16DF235FB6D1A4F667196DD843A583577722652F9660B1C4F32394766582F747D4F9E5A61C61EEF69A7A76C63155F8625834646232CF33F55C8C1F2CDD01C9632AE2B3111C7B78039CD30B574B58744A25F74868DDEAF1226E4DB01223399944526F4E13A8245B58456850BD8C7569DDB34F8F220D9CCCAFF3383C266F00A350299E89D8D8E8C8B6558A75DDDD3D97561E05F52C1D8D98B3F8B7B7488DCE55EAA652C535FC031285667B61E63F8BE1C68F0B0FD4B6D7D46D27E8A3D67CC57AAE78539AF633F85EC59C4078834BCD293CE951A0F5E4CC04152EA49F6A2BDCBC1F6D1AF46FBB2DD0A7C1FF6B262AAE0BE16F0E163B9DA43061BF1275EBFBEB2324BEFD7C4B904990253A8BB1DE307DA50C23842C8DBB12C8952CEDEB6E38995BCA7B20E09B66263F01D083431253D4323AE0943327A94820D178F93C3A1C4ADF00C06E0117F58DA38B1C48202CB37D148251C5F834D42EBF8DF2567560284EA8EC463C5AA602548921C40F69398F030278B104102F5741398BC35A0E0A08D9E854E6DBB46E07343CF5D79D3F6A1C7A3097B8FF643C784B004666242BA45982B984F4D05CA91E15AED9E99FE651B497FB38DB7287EFC5B6A319551C6D70FC5F7A5F4A13E01F868A8272E9B508865D84983A324B548AC565FB6B3C372D4F9C3BF00FFA48DD7EDDBB4C40928FC19CA6CC6C317DDBB065FB87DB0741B9006834137D8E26EFFB7A756521E314BCCAAAE9EAA41A6FCC5714A8C3F0136D23B6BBD3320AD78D60A97DB803A064E5ED02B3C506484D6A29772BF30F888BF2B3FF2444DB6B2423061F4595786DF6948C077E6947788A7FBBED769256742ABB6E21D1C2BFABBBF73A870EC9993B60320AE616135B6F7E22A11C02A0972E01834BACE864717317D521421A79A0AE77890CDDB15474606C6661ABFEA69AB4A9616AA02945F25B393FBEC135CC9E3E08D5C8DAD55C4676BA84E62E44991EEFB9EFC5EE5BEFA87FB331FDC574B8EC84367AC7880387682BDB00868CF1C13D9D422BE05C442A7F2C8676BD03020E07C65EB56DCABBB6DC2A73E9D131D53433145BF001A345F31330942109F374317EB5DD581B5354997308457387A4E61D04179E7B046167888F698C8BE0B740A18387554E6EE9B269E9499367C714E3E48591C20681C41E1EE5347BF39B0A0C8880230AFBC8917F43309D3C420B8910EAD049872468B4F880A4C3947237A09B46741EB81DFB6CC792F4A7ADE298190C61D339EDC96B3BC6237489C0BC7A5EEB822B51DEA05FB3C0C47DEF482376E86BC94DF3A3BFEFB0C741B6356B05946E3BC8D4C333B5340BED06C43993 +smlen = 4860 +sm = 86C91B1C4847D7EB37D4E085ACCB5B1C162888F76A64F19AE58D701BF6DFC7CDF3FA951F10AAF9CE3DAFF0A47D4D696DD67C7CB8BCA883666EB341D67536F48B1FD73F4897E7B3BBD40DCFFCF48B79D875691771A846F66D6BE78C83C0BC4402B389AC09799812ED4E6DDB1FE4B84195EDCAB7E79BD8F7A12B3DB150B02705949CE8B1C92A8CB66DD896705C4EE943FA4DF82415F258D9031D9E8862803C50B62B6614D1E70CDF8007ABAE48469A95B090B1716B6EDB5A7A8F544074E2E11FD25A339929F83FEAA27DE235E93D4CE8D2609D47CDCB225F94B6264F5EACD6FBE06DEB0AB453DBF8F8B3C5DE88FA9CABF35CC3BFD8C4C7AB3ABFD57517D6999A8167756B198E3D938E4175C2904AAA421030B5574FFE05685FFE2B372E75CDAABF38C1E995473B63415D50211393920495D40F32AE2AC2898655AF3CF1A84182044387122061C3DC2B35E7610FC011D55C80736FAD3DCFEC712746D793979659ADCF2DB88453C2DDEB13CE4930C7EEAED8BC6BBB2CEC5A5F310BC4D3A403D20CC6DC6C63F01F33972501CB0624967CDC87161EBB91BAEC1254B9DD4CE1983B3F953E0580E4910403C269E172E1A7A18E1F30BC33E76B8A8C2212A539437E1EEE30D01DCFCFDA21AB89004B855E1137FE981A7FD05AA84F008D501F29470A588786DBA66394F0C7E0F4A31C4F18C22732C3E974A56D639817D83D5CF70B7688A669EAD0A1B7274DD9B811DEC78DFCF79EF2F645733584EA227033C19E698B925957017E90B5110D2DF5ED3735F1A424C35CFD145B4808D0E09C17FC48F649C4C3D3E4F49B9CAB41F852F44538944292E6650A0C30BBF20ACBBE43B63CA5B857433A2566A6C60B84AE247EA227F9BFC9983FF12BAEC6A744AC8859C0BC7BB20A17B58B494E09D2CDE1CE1EA0AFFAA091706D2179E923E2956F5F1EDA3BBF60379599FB6BA837FA5F158E05922153EC08A1D1B4DF06CA1F5D59251FB5606627734B78EEE6690453BA72D4874DE810C85765F9EE7338BC61FDC93A61CC2D0D3C5529619C93618EB8A10472DF191384BFF87678A411787FCEBDCA5AACCC945B59F4A4C6CCBFA96D1B8ACBAE465B83AB133BE7FF02EB1D8BE5B6E2EE2C7C71680B89212642B3EB20DC01967EA3F551094A51CBF03DB4796AE73F0AD24F3B8CEAD841982933A33424C229E559226F384E72654E38F026314D50C5E05EAF424B8B6738A4F08B37601E7E73C2C6554D899D29FA23A1DEBAFDB3A2F4C86237E9E7FD7932E35F14459D96D5F00250BDE80A38FE08FB402A32EBDF05E0642F69145F2A097444C3DD8CB16278188B832DDB68A46A4CDC4EAB32BE37740687817EA603E1F98FCC8754444C3B3B78158C3D0369F2F305BE668140ACAB4A3BCBE0CC5B33B10176CC02CC4C269FBE068209DFE4972295D935D4A2D1AAD7A6685FFAAEAE2E9AEF59F64669877B238D04AA01992C9EDC99598DEFAE01D2A60E98C9130E645CB991E4C1FDC37AEFC300F7FECADEBBBE0D9FDC11CE0988172DC0086B0F67F61D69C8D4D6D663EC0085AE6143297392963865FE81E74D2B6950D7261AFCABA537DC7667684E69B8BE2DAA7968AD97D53D834BE5BE1718338636B8E4C71D4BCA9C46EAA630C57720755151DDD0A0B90064F417E15A7D1301EFBE713F5C9A92AF9CE5CEBD658993242B4025167C4622F30A867C0FEF46F498EEEF600D8AC519B1135412DFE44A24734DA71938A9AB5BCE344FD6D31C4BE7473245C4D23A70730801D2C83873F7B3C5C04DE3EA809054540F8E5600AB938689EE104526FACFBBE342975BC0C63C2039B9BAB00320A54CFC8B6ABE0F0ADA0715C083470A76CC6E9B1CCBCF928E35373F7444487C036B814847E394988A0ABFE92DB3356D730B53D41EEBE9375EEDEAE71839E57539A910A8031B9381F02FD31B0BFFCC04EE2EBFBAC60B445667BEE022977471FC7B0F37D5FB420CB67D90436E6145FCAECF6054DE6B39276E95860063FE146B53E01C9C21965DD1DCDACC477D18014FE21E8BF06A7F293B2D7FC1289A24188750CF066DA1061629CCF4213C88002D273D084D590DA28CF4A3DDADE0FB205D4D327D2955DE7C66C14D0873AB9AF60854F3887FD2C1F8E787DB14845D8C7A0C3F54691AD31D94DB98EFFB3D181F8B15DF30571BEAB6E32EFD223415E834F726B6712D83BB1859EC0695D79224C5FFA1820DBFCEA468FBCA60A5FC2E4C4A6638DD287533C308CD012F5905E78273E81E5A585569EA049EF657C521784AB543CFF4E902A497A7DABC0ECA66785EF4F4F8DF3234AD542A84DFC2C05C24C4657C98ECDFD445FC1868B3E1E4978B7A9D90CC8B380EFB115061C0CA11B7836E512273F2AC7196B439B1A6A1F8AF26877DD1D17C924C2E92FE77E1CF2FC3A2DF391C1113C1FF93F5F5D967409C2928B8FAB71958E7304988628ACD3EA0173C5ACE2A3F46F034563B58AFC8E27D6F50E831702157BD62678C9A30D169C9AD32A243430E28AB8B083792280AC9FC0433B9D7CD07C38251D2C1EBA4714EFC4BB07C9362D89C8D491D66521FB3454B229F9324FF3E6B7453827B19B223E07BE6252EE4D56BE39CF4DEF600BD09C30919480F37AAEFA4218A007066FDE16AB3B6C282B2C7D77D58E2D899CA68AB32251438E045A30C70B334A61A4155FE95ED64C83234E0FA0466D56DC368A8C37070BEE5B69185756879D34D56D982CF761BEF222F8BC841E9AE11ACF8171B13C2973DE035542E9915C3C21462B52E0FE4B4D41442C28A7652CFB1C68184CED2C85B2F0A48BA146C0C8DC6C578AC28931F21A6E1D85487090EA78C196EC4D6F12609B39B9A8872BDF20F03A75589A42D6C3312B485DEA6F5ED9ECB5F0CBEB44B4DB5CBAE8F3864C23E19A7857EF8D6BA1EAFDC4C52495F8C4730869D672C5A8447B45620BAE915A96D23DBCA1F31D2A1D759F81ED2539A680A067AF696B0A9CF0DA740CFE71AFFA59721CD2133F985D53F35AA899C0F43C8ADC99946671D8F84650611653AFF8DC26F41F8BC24B25B2594ABAE7A49FD1E67F61491310BC3D679E56AD7ED7EC7355711FB78472DB2F0ABAB52EA66B2C55061A2DE7C2A5389E5BECCF084ECD50B07607EF7759864C7556CCE2E593FE45569828465E74BC98FB86D2B6D28F0FDB43D1FAA331EE9A538A671C828EAF2FD74DBC3DF37377C1D680C040FBCAE4D70839FD6A63E1683D9108B0AA919DCD483C3E5F2E28B4D3F000C65403C62719F9DC802EF4F6FAE50A46EEDFD612835E24F035D1FA14C3986EED425ED753962EB52F644E7995BA35DD4ACBCA5749DA217F168171D6E62F5082073DEEB0C7651FA6B5FDC7056E5AF591C30A058DB2E3268ED83925C4C412CB6D760557F838CB6C7A9D00994CC6190BC19CF92CDD2839B3CCCA44486FEF6D0E3BA483C58B5EB5E6DE74312B2346EF6410E630701222BA255B98BC0EA869B913EA2F81BDAA1FE08A5B2A4A3D97338B7DEF1E78671CB96F9CEC6DE31E4F2A9AAA4E69A9B1847B96EB0EA59FF78614A9E3807674085DF2CFAD59B8A5F7AEBE78F1D3721A6093CF01499EF5394BACE1FE698910836B7C95BA3E3631B3F4AC1043218D28CF98B7A8F6AAFEE57A9FBD6A91A29D22A7F0BE686B203B61E9A569195179CCEBCA5873028216E56EA3E2607B9FD0A2BDD6DFC8AED5B4E09664C77BA1741217E9DFA13105E22CDF44C54A9ACB7EE819D01BA0D02C4A6F2C3DEBE1E8FDD25635EB719B346F70663DF4D32DCBF020E0C94F1252F87876F088636292A637584323FCDDBB12EA49A1D1338EEE94DB8AD07430DF4AE79F862621B658223CFBDADBA89069F6CA94CA2B83A34E4BD6E9AD69AAF6BEC94252CBEF01B56F8E617B16FC6C6409E73C434E67A0599DD3EEED3A05F8B10472F47A685C0B91FF298582253834175723A32277277142181E8F28918A854CD4C3C85559FF1B42B44C303BBC6CEE53ADCDF144B4C8AFEA6DCE85A41CE131CB940275BF69A900F1177CBFAEBEA19962E730BC36816F8DB505320786FB1461A3044F324851AE7B207AE925015A48DD93789CA50AE1AD0EA7EAB84E1A6717397382768A45126400BB15B6321A594C0C7EC1F15F9C5821DC942B7D31E2ADDEAD1A1F891ADB165561BD4B47ED54446974EC7FF05AE96011A69F95E152AAA726186FCBCECA58725314BBA319753B4B7CC046A3172F2541C3AB056DD065D787C524FB5D19B0B837045B9414327332DDF000D73527BEA3D130822F4652DBB4F58205CCFFF88A894663790547FFEFAE7AEBCD7778494859DEBC02C02747B608EDE6C4B2B708D53CC76F2F884A9F4F3DADDFD7E5FC072610B41F40DF63DC5C98A719B91D9A5B9507B6D620BC4E170C705ED41ED1D7235BC7BB0D6283CD9B9E5E093DD6C4C435A77A69E3D1690E71CBC99AAF7795A62FCA1207CF39F5C8E2007D1C99F4E8FF96A37995FF2C523BDAB8019D09C64B39283212FD2403B89080BD3206A30E403D8BC0328A76301BA55DB16B293E840F590F7ED30627D85D9A54D33492375356940EC7722A0A8CFDC1BE9A9AE045C9E0FD344DBCFEA5C73D5128DC946B9F2B1BBD4B3B2DBE9D3A69165B71E4B865D6D263D8F05F3F95700608B90A3647B8E9BB8E9104469A9D613343E4C7683A6DE04072F32E0F334637700000000000000000000000000000000000000000000050B10181E216A58AA820275A2F43D0F05DD0EE484AF42B665FFB8F21DB322ABD256A5C753BC8FF6A2C71467922E09726655F1A7218E736752065C871221C0B9DEE6A9D56B78A1C3B7357774396F6980226DCA1F91BA828E06BBF324D5CCE8D584D9D298261C7149899FC9F74D501E920F22AA34706A79213E35914DBF57B9642A42EF0D8226E31ADF89D18C5F3163ADECC79172C95650D764E3729EDAA08C207D930C26DF8EE1291C1CF889283B70AF00C0489175F799273C837B281A5D1284E4447ED72598EFAE23B523274644DA19BC0359BA59E5BE9E5828FF587C335E136C1D789257864D2648EF9C03D1C4B9809DD07CEABD865254D3D8D597587D71E374FC2DDE89C22C2330E8904F6B53F637348434A21ACEAB9892D5DF8FF84CC58229782BED739BFB13448896F7B1064B499087F7547CFC0A49272C2A670A9431B1B5A07284B6749EF834510A3EC0C61A43D5D0EB48C8F487947C4FCCEFCC49DECCB6111D617407C76A1B4A849C9A190310711B102F142F9E9CBB29F46447265E2C8DDB9174B780EB4A51003FB68483A265F2475D5BF6ECE18AF0CF31BF24CDD56583E777C4340086917B78068DFD380466F43D020E285CEED97A467DB96BFAEC22D80B4A6EC0DBB98CFC44436A41CADC85A90B214F00990D7B7010BBE4AC94809A0450C9ABEE5AA4037A44B0B4DEBD264120E762086B8D6F17AFD37086C93A8A368BE97E0F7546AF16D731C21878063E38DF3DCF3ADE6DD2DAA43C198F49B5D9FF5362333F29EC2F13CBB90DBE4E703EDAE9A4F7334A1C5AC60D5972C4AF2BA61B63C93BF719854E615D16BA4F704C55260A8838679815FA59BE08C4243CACC1A584CC1B4E777FCDC6E5A167C4CC9093749ACE4836AE058BE89CCA3221A3F63F07089006E4C44E40653BF262945A640D8C2A24E7CC3529E4BE76286C86CA2089CB8D4684508D1FAB81EAE7D8C731B65A22700BF9009A3190F5ED837EC22F9112383422027AED838F16A7740CF79EC101865D320E380D4ABA745ACC8EED376DC5B3AABE58DEBC35F8E983C92906AA2E3D8FBBE237325302E2A23CB1312EA7F532D64E79B9815996D28E0183EB728A37E19CB219987576C142F4B2F66AC6C7C77028ED59A8DF27F78ACD3910DDFCEB88888B4A604E5D07AE1B53EA6DF6EC2163DDC4BAB422D2438FFA543B22441E50E4087FDE4BEE6D79D90A2F72548DDC41C5AE07DCC87666EA3C4B89A0B14AFE03B585E7CA507E5F29997F2368B0C68C6AB6E344C082BD06AE922CD8089634918D9132DF9CBD665A4149C59BF76B0E94F66481766FD79054AA80C02E0AE04A6E2BE090582171B2A9AF455CD9FC302CA9D1EC837EE26E0E4D0AC8F0692CB9ABAC979B58CA92E5194EBE46B520125BD0B3ED1AC2BD817D3510E33CFD17058F865DBC64E9B99352B6CAF10F0A5A47449BF927A8EBA06D34C80D77A0B00B88B25A4C8747AADBB11BA15ADF9C959B05C4371CD8439FE5028E004A2E1D2F21190466FC7FD56E9BA0599A0EEDD98246AEB4B85994787B7604CB52F5515B42C2FBD4B5E9E372A36CC4E66483DD884DFE42AAA5EE7FAB200D8EC6E3556DDE0F9E9C7346F9967F8F3CEBE1E4D1CD8E6046E5E94BBC74AD3D51DB0DC704F4A4025383F0391B9DA37BCA8EC59E807593A4F040FBB186607280967E5048CAB92215DC783D9045F7A0922008628C771778661E97E9F88EA84BDAA8BA61126F71D193A2A564E3ACDE7ADF2C0B3D5B022EB6E0C629782B0025C9079D4545D88AA2BA27D10C5DCBCFB7CF648939155066518878CC54A4F611AAC21BD3A1EC628D3352F049915FCA55234B9146ECE5F78FBE7CFFB35695363202EDB9EC3501A93B4B6FC81B3DFDB5245FEEC8AA54195262C2467E15506B7D42A7FF61D75998722D0208BBFEA05CE7D2E66900A9B34F44C2A21257C220C03F9D6D7F0312A36F5C12DA20FB5290D5CFBC1DEC7D05C44820885C479063CA88783C5AA128829417EC4DD41CF83A1D991DF2EFDFEFE375E93F0371695E353EF737F4A75106211A5F70C82B4F360ABCD078C9E829C82A6B7A36D22B8D1F6E3101BA009C759FC83999D52E29B387A8DC1658A43EC4C4D9330A4ED2138E035EBEAE6343A76A82849E37141FCE34E9A41EB5EF88BBB9257017AD8696C3847FD77AE103A082ED1A05DE9420984C147AFF927E1950244912079BDBE5CC07 + +count = 47 +seed = 1F3193EBC58EF65E9E396D69220ADB8ADC729BB388A72CEC9028A094F1CBDED21CFB0C41356AF31E0CF66A3B0D843666 +mlen = 1584 +msg = 139BA17ED7B476DBB1CDFE3C42B3A57AF5BBCB3BE19ED04D6C3072FDFE917ECB9272D59EE89EF83522531D83AFF8B9934A8423315C350D1481A4B02980DC29E1CB83B76623869649AC40EF297B153B679C327BB251C6E6BC169C48ABA2A439F9EA24EF94656A415C3E86D7BCB43CB3717D54D773F1937DC8B0E02D4E6ABBB1C83FE73F1B221C9A359E454C19DE5E71EA4CB8C560EABF1DA133FF20D81785D2ECD935B99F24840761446C324DF81484C5C05045C0949DF8D0F10F942E1B5B79074B358C25B6EC2B0B42DF65D998B666CF1BC568E7D737F22FF541807BE95ED85A9980E940E24D2C506BB0F9BEE32EFFD85A2017DE694F61BCC2B292595C97FF4C2145E48AF8F0F3D71763B4DB433ED7BDB8DBF8643475FB2B9155F0CC6A0048C5546900792BC01EBA4B06C83A0C447EA0CF05410DE55ACB8E5521829C89BFBC084CD86E7CA3D701283B70F78E1CE9C3888AD2689E0EF5593D656285066F319E155F86C0A71256484F42A0C40E7CF13AF0CF77C6D1CC7231A48538E9060A7863B774C9CC65E321E45AACC002C0170EDDD18CC1424159D46BF99D08A28D2DEA8917D28D91A1D6C409D945A5EEA19413A1ADCA40DE9458FA6BDF1E5308EF9E67E1E90E9D92BF19B5351FC49DFF0A31E035038AAEC651C0F20F276E4EF0EE35C14BB625EB34205516D95ABEAA06A7A3BB3AF2F12236406689BFAB11E65FC63EBC5B944818DD1D53C0E7B88CE7AEBAE581D995AE7D8423778DFE20D6CEA7AC0B1B4EFE2B9D571DE77BD8F71E89D9F6A2DC89103B73625887AB376BD12CE89A65E6280515A44A80D6C32799669260167DA0A214AD0FB803930AB1952D93360B54433CE8220B29339DCF2702581E88952A5A1549DBA11F4CCDB6FEFD6D24522F3207796C8D5BA9D1582F888F2500964F2B975AED5D5AF83409FF9720EDCF5CE3FE9B6B586B08DE21956E7970D8DC28F6208A80F5378ECBC506333A1D98C58EB0E2EB0CDECE0F5D16A069FFD742D1E589F546C4F2EA3DA0A56F984CFD93F5F2912FB1D068F2BD7C1B5E979ABCC62E3A0164445398F5C0208E82B99AED1200D36289B1FDBBF03E43995341AED3AD712CC7C7530C751B40B765073EE4E4CDD411AE543AD5E2793F294320E9791AB35AE1697F23EBFA0280B8041859909B0089C101D7CC429408FABD2E073FCA7F2C2886031E9F6A32F2B596A799967BA8A47E87DCC8854D45DDB6DE39160600EB4235F4E3424D75DDC8CCF041AA05B25B5A3811540EA5B77CD8D7D611A63BEF5C26D57475B28E961645AEE0B9C8D47954FAF634017787A21A671493E7C5F1A4C553E0A68DDD726DB1DED4321DC735332FEFDF2A84C22097AB3552F878E304598EC40EB349E1C1AE416F94112A2CF8E8702A4C3BDE2F58245166550FC238E153D10F90652518B1D84CCD3ED836F150F1FF103976E743137DA5A97A61276DFB0C11D071B240069582265A9CAE4987B6C6B017DCD1594024D7B1336FF141E59936EC4CE5410E1B73BA6FB42D35F8999225CB1A135260967F4F6EF2172D53FA6AB6D1A2E3174B46C24BC103BAF69C2128F093AECEEBE8753EB352E2804EE64AE5140DF1ACDACD8F225B3C9A61264245B8E5CF759CDDD75E25E2D790FFAE8421515E0CD6F279D0080A3F80BB2E0729C0D2626B6ACE31CE20BCDA490C7660D04D1D82E6403000578926C52D8F9A4BE7103D64E0F03E8F148BB2236781EC30F6D8BC827C107FCC40F26DDAD485E6135BDC3BB331BE139A07891717B692E23312D0E5B1C41F30C3B4B4700EFFB481A835AB54340269FFF365FF87F58245621ACFD83B7FCC6FF108132D8966F9836544354F7E216FBBB851F390DCE8A72362F0454730B90D35AB3859763AEE35668310FD501C7501F4599563006AAEE9B636B676F3DBB6787317885B0F4A64171BF19CBF2EA7A625E1563032C196E1292D82C7484817DBF78D8E9E478FDC4C92CBEF48D4CB4F0E6DCDCA6682DC0A56C3E45EA0350D9FF88073748305FD7DF3A3BE8C055CB1C55167560D5C99345BA80C21CE791C4A511E384A02833B78E8AA02B1B877A9B8D806978519D716C611DF54AE8EA2691540E87C6E79EB006569E02745021BDC7852E1FA4177E2C3EC89257618B38719CB07B0BA68F600236167F019694959C2AB6FB39D5890CB176F6ACC3B9656E495C07027E3D4DE781F48C1F1A8AA1B41449689E191E495FF3F263DDAAA8DE0DF6F1A4AA3EF1F5EDFE437BB74BA +pk = 8F1602C7B0C804D59DA6ACC624E97BD6133FE4E6F2213D1CB9574DF3E5C9E3D9EC9C19E0E981B11747695B3CF01B2663331EC23CBBE35B86ABF4B6CB1B9C5DB8582EAECF35D539C968EA14E38AFEBA8CB154895CEA82D2802457138C02AA3F2FC7FAC74F52122F932BFC3F66171A8F4A1C8FD598ED8F0639C0A89F3CAB3B1D5D711B4733038AA261329C70CE7F295102BD7BF2C3634B02342FC6E0065EAE353243C8A314567B8F8F2E963A69E3FF541A6619659D46C7B96C1046A941274895B950E23AF262097E799C12FD70E043B2EB0A799704E5EE10CAD35760D9C540224FA7087994F21D9A331C97A866905CB0C63CA7A28E75A7C623547447CAEBC1FE052FFF1DF343C7894F13902E7E05E131552A5F79B2164B910A87F10479DA54A953E547A2527FCF69D4B75BE264570761BA8FAAFFEFB4AB0D19DAC8EAD75E28BCD5CE4BA9200E497F9C3914918B6C59C765D534A916611F748141BA310827E8ABD21D7C472DFD43A2CED2936C7D5F46AE9C96B1A3093B3FC7EAA2DF9C2A376765AD26674636F25DBD377EC9765986FE071323838540214220452D43FE06E17D5230135AA91A74DF0B6AF5A6A10B1BCEB47CBCD5F971EC3D89D10287D31ECB2D8295C34750C0AB9B9DBB255902C165B9B29224E46ACB01DD7942ABF8A53391A86C8D88EF18BFFDB7E70A6DCA2F3D5E151C3BCD9DC307576C50E8ECF9B8743A2467756134BF965BC2F6B6A15B72FA83C882C7C3E40F53B7CA694FEA3758C1C6F2FFB2CB424ACDCC0DB734319CA70C27362E2C41E9F99A4A90EC57200C3F421254AB5B5C17803ACFE1A442CCC46EFAE8C9460DEB8ED1187BA47715B746FB4497D5C9069F50AEC55A8E617E9FAA368E261500DFE2876AABC033C5503F51C7FA3C0B3B6E2CB9EF5D91C89307B44A8B44F879D8FAA6861869E33F41E8CEE1E61B79DB2179AF8E04BEEA6208CCD48E4745C394CAC3E7BDAC8D67ACEB4F8BAC0318B25B6DAFFCE58BA1889A9FFCD3ADD88231C1F8BADA3FF16ECFFB89D35D58D683681EEB0DF5A09E486286DC73B8E2CB1C3A38841A19893A4EB7FE8A58C2D3321A3AA1D9860E573931C627F9D226FDE08440F7AE4820F96913CE734D084F9DA5D31682EAC95B0A5107B74C04F7CA553B58BC234078D0D979D782BFD8035613830BBBAD8DD434EEC8A482969E82C710F54E98621E9F3194CCEB3B73651240A3DE457D22235EF72BB7036AEAEB5CFE5AAD73CB4E39D9A823EBD33CD2F49F6C495036F118E354F3F2C499B3DD88DAB0C30380B6D4B53764BA1F6677FA98FA7CD8F5B4BAE79981D69FB44BE8633DAE96906A219F6D8CFC9B3B2D0A3750D33BB16B5DAF24B72283E1D77434ED90E3BEB4FCB9723141482492D66DB08CD59E9EA9183273DA181328E2746BF0FE8C6070628FBEAD5870E834FFE33DE48318A3D72527D75CD3272CCD1783A816007CADD04A2B30142EBE4AFB6974E7CAF59F84F52A0C10775010871730C2FA2EE7D687D6237F4F3777D081E5F425710955DDFBA9F1FBEE0AA55BB2CC462A4B63B3BC0C0DD3A2A04BEBF5304113C3D0F980623EFD907B4BF721E057D5BAC0B61EB0AB0822D137BBC1FC2F0D5D19F876C18BCAED081687596A331E7E6219CBDD4A47FBA2626F7B9F5863548FEF7BC684CFFBA9218BDB84431DDBDB111DAC43FCC7319193B482349C4D6A7EF311D3071DB3A3F75AA2D82337EC66663313118BA13A8D5796843CDEDE61EF7A5839023C599BE13D87751D6A111314BB9DBE0AA1DC6B91F175D951C87D2414749839155A107916B2557E8910DB174B5545BFF32A72F1DD987B26FB2573D7EF24EEFEF63F5A3ACBA07E4A20F8CF957E75AA9AE9A6F73CDFCF2FF527F131B2A06CB2751F7F92EF007BD095D8652B64044AF3DD72BF93FAABA1AF80E600517FCAB09D8C47D027C3AB779F18648FD73F283244DCAE4B5AAE3E9B7A7B90EFA354CC336BF7BCA18F910E52B7FF262E220F399BD243E203941A6043BAFC047137B4B8F6A4F3378038378F69F1D264785B608398F0426259E34AA76B05E9BE8F491B9963230940FC7CBCE7C8112A672ECFA9B5CEAA94EFB31E4A4BDAEECECF219DDACBA89830BB6588F9A04DC16182604B9494556783AA8B0CADBBB5B052C69FFCEB078A6941B14C2F02EA747A60E917F09760257075940698C553A3EF379C38F233AA555541DE1C4647E81C7B445381BB3A90879D1DFD363227B0CF58B6273E8DAAF15B5876A0E6B6D15B92ED684301FCEBCE309C68035C14842A6DDE50CFF2BBF00C9D8FC81FA762EA71826F590619B220FA4436277D4CACEAAD1B05A1747898E1105D11C1324EBECDDEAB0B53E1DFC0446D0F77B9B4C9CA24B6320534FEB6DF23F52B049B4FC7D3D060172F90872DF509F22FC1E2D58A25805887773588F2889D5AAE3C11AEC53E6AF5DCE2D7DA35E89D2440B6C48DBE3BC95C0C320563A966C5143DF75EB402126AA9E00A7533F16A48FA94EFEC607E70FBA7166F282601090057675646464780A96E830BC383B148A5DA25F478CB193C684E238C163474957BA7726AE092B7411774C9C78CA9BE376DDDFDA21C3E36F572D58842C5C04B75EE6BB0FD2E5DCE6B4CA2D22FA03642EC7A12F7739E25671472E2F49E046E83AE3BA3F049CDF798BDAD99C4DC57A1FD6113F15FEF561BDA0972631C463DB7FFCD4CE7BFC17D1CF2080BDF195A8ECB72BD0A123D66352B44533440EBF667F3650B475193BD741245B16AB73B6D6256DA08E45F75CD53 +sk = 8F1602C7B0C804D59DA6ACC624E97BD6133FE4E6F2213D1CB9574DF3E5C9E3D9E32578B65B57ED1930FB71B2A1099571117EE1D0A45A1572836C9C733F7E819F39A5C7A1280C4ABDF282D1DCCB864431B8F186215F8EAE9C950D53DFEEB8E35510EECB79C52E33A93A6148DDC63D4D1DF1201D8F0856875AAAE69597E01FD51781348584724320615558038701345224463277120188704183840608868278414884226570326857052234131833148373615775244003451065227802762225668322612102644250363307861072022514052041670336377651621224655200655104285584310646337171351827011678503384136518231841175853106550184873133855277763823372274686220433471666255257052728864056273218170115470730153777106270044040684164178416154504502071263412828706837074336321380266770087814163245307377858855121666452732042411481284307110701374678222741613650467086667630627415225527412448450648176217018787770040140072751483670543631278380182014263001624588650678863800327213431508034348432618470431771522360286454724343501140118662258117676666675606218605357571170334241685261010744557877146076747123318056216762588500735731240167077365308721750555766803682252304562851473524142131871260848602802225254638181082118028814546471867227162160644861015225854727864227501344575242714506038364802271671632701075837362238554174465347111085733255463137020634322783437378561704526432726813484551774518104045050253327166552401014074782174348546356358542337882818806426765480177770352325421352820043472810787458348480141707574108735170526764311774702767788805378328238121240340778834262630180442788702886765270263281133203180174371388474860276574485158212820080750813747004481465373453447264357023455002083701685264244324278351846634333553633088057136625128324026660284861048626404242343407321640538165632301306331437208248743303115204240382104312433348501303027440660652070671436131237438451372684136661586466370866108108873642655161248831857781872642651445630810316638835234504470260184586413081384470080202272537801578714873622172340382601581248168330872435661742657657820713122341608002466013180473625674254302426122347154823552021576824884124723850648728115488742374240702612673185467757770253460184366050650065604227067086512268038206070626580754541660333721010462812877248100411730008385308748172016165133604851814305174016388014324373116134740466335247330324278863006021340375088136582435761403151110180452673211264323113852683257214635736476558728722710286712520375337776151618685148343831064175683037175147774258317580403210662443483536141808037618534707378621624876175572518527162675340605182886770844746057102040656418603585415346750073764664628162087343376884764217480884112426100364281811834125746563337875847630588388148587608633287775027225547562136625667731117573838742567413548465200550547354722316326563183267870707427561711754523813884764307462658835344884231602634742265565332712687627473660853270620032358008515016186287033040008344655211000012756733443848517160301400808148668373812010677640641274111826300116163866046755066801450825243528370840482017875200311028034431714742301853767138656570553182481750074441581875012840466821352004230220468421461862148753005244838616823690475731CD2A36069D66A2F81A99F2185295B5EB69678A3D54A5E0D5E0545F362EC2FC97579751825604CA46C2BAD3D313E7F8AE52E8A55EC36195A6592E4F21E46A9ACD9A11580D7B4FAD4C7CA1074E53F3EF448911A5938BAD9B3570F44C79C82F6B16CD46F1855BFEA2D7AA2A00445931DCA5FDF11D5424B1749BAF0A4174C3FF6BD629412567E06461952AD2BE840AF8C338336C680958764B036992D6D6DE2BAC0714884D254546EDAE072D89A5B6507D1611A858AE8AB0F084403FAA354FB3A06AE3A8971718ECC084876985C2EFC7C5FD4AFB26505E38F5614DE3DE289635E5E5A8556CD389FD6DC565FA0769D62DE9449E6F41F10C58661E0B647C271274FC2B372865F2CFC3F680E98CA677050BFE0AC374C1D8CB56D0B1803A537F52E6027615B83CC57BFA1270C91042BBD58FEA1DEB6C313295628C7369B5F3495AAAFCF726F809529B6C42117AD5F074D432910F7AE5D85BC8A04FC41D37EC8FE281C8772BA776CFF58CD99BF1597EF3E4FC807A25D066416D61DD892F990C062D581A455D27712F8732A2E76A242900EE36A9C31DFFC2886DA29183A5838F2BAFB13EC48D4FA07D48C1E9E7E8C6865D585DD0A996F9CC4172F66E5D27575B3A3632E47A6FB849094EB0FF7B81DDA6843ED88E5E5FEB20CA6E09106AEE4AABD4F7F6185D7A5CA5176A9164D60EC212EAC1DED70BE15D2DB6FFC9AF0CCFC9326944A7A98B992892C45036706ECFB44D6C24B52929D2E258C73ECAE0AB578CBB8037CE2F0DCF20071A4135B2CEC8B2A8091F17168C381EB419B01F8918BB6AB3FA47578887B5100B77CDFA36CF477D16233DA7B59D6645EEB1DA251B0ABF8E8F96F791762785D43BEB64855C5BCD38EAFA75F74FC8BB1C045F9F3700D4BAC8211204A3CF4DEC45469CB3758FCF179B218C8642ED30C14C8B9557445A62BDA45E1B4D0DE7115B8DABF08663972228565A3064843E08450D9A588E218211DFA157BA27CCE989BA32A40D287D45EB2A11A0EE071CCF860746AB8B351A5E59F72976072E79346A960E6F4B9572081E36CD6A357C9A834081A414C23ABDB27A57179F0191D7E7B0162EF3FD485C76D3810783164A98B237111FDB6CC47AC150E4D3F649C50090D6E99AF7A5711C6111D9EA66DF2B2FA2E70EBAF95141C458B7879D50A18BD7A39DE53DF91A143535E98C749185FDE7D24FDBF94300B617A10EFE5F2F55B6125E87B3CC98D6CF2B7412400319858FB4E5D6A7F68691726454EAE7F217DEF26AC9FC32B3AE84BB61B4359911315AF8C1500D33F281E0BBCAAACF9AA118F0C65FF355D1EA7CB5D445365A5E07C771CA7D2E95DDA70297694269916D5AC41226C1D9872254EBEAEF1550244CB81FBB2EF43A0FFFE75354D71026606C4D9EA017E90EAEA071DA5A0237CCC361F2022DAB8B345C7F343AB3131464E905C503314AD19E43319202A1F59B6EE57E7F2E02B0F1B69D00FE2AD7DD28C3D3B66A8FD50768993F32A932B9C66C441A73D14EB5BFEBA002CA52C49880AEDD118C3ACF8A106241866ADB968ABABF31E9CE16FCF7F0FD171BAC057FE89916E041C8C1C3DCE72AA684C38DF7AA7A2695B15CD9AD35BBE447E3EC54842B1CBCAFD0CFEFF69A13F2186727C77A8D8E1C7A6B2D634DDD03DECEEEAFF296B96DD2B1B30DB6A414778D1FC879DCD5C9B314C0B6FCD14B6DEDC8A1F72DB89AEA5C19E593C48A7A511348A2693A110E775F7A55EF67758C2A21FBF2917A688479469FBD7FF3E88C49FDCE8AAB3E8DFFD075747B006EE4C3D339C75ABF5F4F86D4381B90CBAE59E12077AFE9EDBC8B2FDD8416BFEC52BCA6CDC509A6B0CECE7E3EF11ACF726E34715FE0E481945FE5F6B521DB086CFE6ECD2971BA789FEF99EEBDE550A22DEF5245BBCCC50C131A4C02AD4B877B81F202FCE1082CCE8B11B321CA840FB651592B2A18B6296DE8DC7B7AFD5511AC96946B40E68ACDD7AD683E6B87CCACB5A47F1B874696015CC391BCAF1311FC89A9104421DDA65883BC1BF4F2CBBFE7DF3941808602217DD2A65919D021A45EAA45C5E014CB59A8488B2A9CEA8E383479283044AD4A513F6ED80E3E19364CED50281BD71FF3C67A935CD13D796E2C9DDAC38942FC6D5A354BE6C09AFDAF140A8A3925B37CF2466223CCA7B2FCCEE89C457BE38FB60A0011FCCCF3AD619A39E66EEB3BF6779A88641D5AEFBC89C40BBAF1722438E900087FECF626BBE0FBDE24732358E17A86573527C84F604EF4BA26DA9D9C9786D8587D341620FA4729D07B94428C174F5010A2C38BF18804D238187FE79B83D714F856E9589718C2454C3DAFBD285EC1341301739BECB793427861AFD5FC60DE27015CF7F1B77EE11B196AEC3CD8B9C8D716848E520E29FE7139229271AA0809BAF583ED7A136E32CBCE23D8DB1CE3EEB099F1BE111A559AF7A3F655479DB7B1156B9EB2A6D3208E22D83778F02ACF1C0A7E9410C909B9B97651E7B73CFD44D4EBF61D43FE244425692698D774C030312AB3E278CD997FBD2D709BE3AC50B153E04E0B4C7AA019CC47EBAB06C494DD94135BB874CA82D142A6065CDB45E7481E9E4B82336CA52BE8A28866713BF517B05DCE33CA4C181C344628E3435C4F6BB2DF87B88E7AC64CB4C41C2D0B82797A9EC48E92667C25D696EDF2564B2ADD300F4A0F54E2D0D900C3AEF75373F13B66FE947DEF68E0B8C650D1D3C6752B3C25294EFD9A0BAB91E2F1BA4ACAA663737248F79C4527CD98E54BD1F32316CF3D40BDCDFDDA372C76CAEB13A2B654DADB178793F21E326992102B82A6E66A33165D43021F1E7A20A5A46182E32078F0BEF06A8F88AEC2BC3E8881A8CA580461ACD9FD7CF86EA1856D9D16495B65E6CE9807E0EA215CE63986D7798D77E6A940191C95C09CA5A912FC3CF883D0C314F283A424F1DB6EF7E868884DEBF6D96787C6A7DC80FA0AB0CC27E68829430981EBD1902CB8F8C00C07E07D936F79D33BAF576222A4BCD544FF9C192AA74678971EF6F647EDD4F44EB470D80CCFADADA29CA461B9C0050CC5222B843A2F78DC0A9DF687756F362F3060B0F5AB3C19BCAF77787A3FC3EC29CDAB2AADA89BBBBB47766DBA9320A2D1D603BE049D8B8E52FA8B2F0DFCB970B6B6077F65DA172044186272BA843EE2F364D5A157E6AF4F1425F5511F138CD9575A762F5F00C51BF80C52ED9814A3BD49BE965106092509AF607F96CB2839F1FE5B0579E8E525DF5A65C08235A472C9D5A90C950AF2DF9C08AD8D0D79D6E9886F432799CEFF89D0D56E05551EF17A70DEC5FF7C747E89CDF1428003D4C295A41957B40932BE0FAAD3BF61D95BA69CC76313A7CBF8E189A8ABCA55440D1367A3E1EEDDC92D3A91CDEAE3B168283158DA7B68622A418777E45C7EF709F7AA2B6F4ADB37D73B940D1FC351EAC534454596ED26D628B7CF5F90B7678B15C0360416CE8A2002349C6B00A42717781C27BAB2C249B3538B27B22560BEC802DD4BC99F5A5332753336377568803A7B514C216B274C52039CA055C10AEE135CDCCD9 +smlen = 4893 +sm = 6B16C9B741A2C6FF042F5434E3F4B5D8B5F62FBACD2AC61380FC959BB0A973986319CAF376D39541869FD4ADBF8E3F8DE5E6541EA7EB2DBD412E4242BE3B8C384DAABACC24C3968803488D4CE75FADDFA0C40E229BE57EC3B12C8A63CBC595AEC4B88F58EB8ADFA1F89B427462DC1E0BE27792D5560B72527CB9F36F96E9D2B4F7933D567032D2A7DC2D3552DA01B9F1193D75020E91751EEC5999D9C873B2C7EC24B2276D0ACFE4DBE95B84F4B6706E44183DF5628A1454C6F618A6001DE26092055152A362011BC18B6E0CC7A86B4D49D31F4A4B99804B26C85AB5E9EBE226AC3F773C03C8D5722307FC31A6FC257BFFEB03A9162E12127DF109E9C3F051DAA34870B9DC87C65C2477C8E82DDD83699BEFB415E0EBD383452CA8CFBD72E5A0687E215D2BCCFA3C0F5026849A1CE7646B2ED4BA5829B8DF5C6838B194782DC5D27CA7EEC5A3199CEE8E8319FE9F9F4B5A9F3013E294797972301212B710B33C065358BC76FFC6A2E0FF92655088C1AE0A692CD5E95305976349B28B2908CCA8566186232A9062B4B55B5A1194B7EE06B16365DD7472B12BF27ABDCD60F12E719D9B8D6A414C1358E77C293C31D0844473CD2BE48012B8BBC5D407233F6D429437242DD45ACC6C91BD6556FFA7FAFB9AAA6CE18A35BD8B2DA5382EEFE1C4EDCCC32F470B569E9CF4B8B26C8EB8BFBF8AF95B020AA5D90D7FB17AC0C2069516EA54A024E67BC44E22AD4F9A23CE014017BF0A31F5BFEA19C14A3B3DB3965C01AEDC8C88F30B34351F8FABC32DAF89B3F77CB8ED483E845624413D30826160BAEEF0545BE522AE456CE9937C63F210308F9DE9D17AD9EE67F7D461FC4099CA4E70F854C72DE89AA91E197F60ECE2B46651005C9436E73876F96EB6713ED7873DC808784901468A1E67C4ACD858CC695D71681C003A1BC925CEE8D6712B99CF24DD11E9BA618D0881EFB17258319C2958AC80FCBF991C2565D9080FEEE5C8846926918F555BF341F1906D9EBA91A919F6257662CE4CA68668A5CDC8FA91FA04A60FF0775D7B8450B4C557370ACB958AD06CA134B31407023305E73434CAF875F1B04E086C88C0A940A5D23D3609BF7563132C5692C839798F7361102690F5433B413E3E3F71705B24A93EB14C2599050C8CF5628E1EB38EA1509D0C9DCAA927B2C91B8222074A72739D925271FF30E9CB477F434AA5BE2B780653E74DA824DC567A314DC35C6260926DD0D7C290FBD42E600ED6E0B691AF083D873A431B806E1F1E6E9C549CAC1B44FB9081CB3F317BE5B524D045852A4039B3E8A3B591EAB8A8E61DA8D083BA766FEAE4837EF5F4C1B4FFD20BDA879FB0F0690693F7FD6AEA960226CFC4AC77F84E883384E844E0C5D91A3BA57978108F3FEBF6C3DA61B1F5A1851055D1E44D6FF096D11E83EAEAAD36EC53FD9F7CD77346708E61F20AB459F404FCC94DDDFE152327166F59454508803D00728221E2282FE0F4968B5ECA57C8B16E709DF6224AA462E0853D14A6E9D8CBC6A544895A328EACB33E521475DAB9A7B71CC53F301B1AB6940513C48358468489F8079A89B55BB1894DB8469184A666B494A8AEF1D68F8721F888DAE9D275D12B19EEDA7B6C5C7A93B275EF96B35E17625AAE1F2D8E2A16087D6EF2C075712E3ED195B0EE7B4885A6B1345340E8C67EC85FAF1DEF8DA2D7525BE9D99B8E89C34F8A0EC650C16B86553836DCA9DBFCB2C93A8401A4439C6ACDE031E2002AF2E3B3C75CFA57FF83CB5BA1D6F391EA881207380590D6F3AB1446A68C116F733D8F87286EEA1CA708CF3D55F5188787523F74C8B57987AD34EE60D9BB120745F20DBC10078F026F79A846209E775CAFD545756640B473ADFC5E148C9A4D3FAAFD656FB2F6228A5DA596E2DEFB717473A302ED32C55BED6D3F9D004650354B7AA59C55C1678BD7CC4153778CEE7482FB13D0E2827B6A5C80D713A9BF275B0DFD4C733A0C65D7C88FDD01ED48D2A8F90907F7B1D2B4DEEDA8E147AA55CDFA3D3C3EBA8A1906A846AC4B9C46AF328A78BFED3C0F17F516AB3D88D87A44EF69F6A0CDC104BFD568BC6F4EF9E8C06DF17A32950D49F3B4F027FF2C9F9DBFA877FC7AEED5674C6FBBFF43AD2D84697BD9D69EF83DDFBD488C7FBDE66EE1BCFFC2D413F2062B871B830FA6A6A3D79F8249868D9E5EEB2FCC740E06C48DE13CCF9B3692075D7B2F832AC9B5F2BFE10DE1E6F188F23786A9E6DBED9A8D58D458A7F36A64FA8E1B40655007139609185904658E3FFEA55CE64EAC2275F00630BE699F888FB7195B8210D2C3BE1AC44E42E1A1E4E225D395E2E139F99989C371DD829666707EAE0CA012B01E5F2EE89F3E4BA0F7071E855EE56CBF9AD4139EF09CF15C8CE37FD7D9FB61AB95D6E1EFAC8FA07E25E1CD6F3ACD69DA311CC8AA28758C9634028629188E702E5A701A0DAEE1066F20A435501494065DCDC7C903AB01ED2E9B96A25C0F95E7BF0A4A89D3A41DD041A02348D7516A770D7B4C35C19F1306F80321E51A4562FFFC44AEA1870F042CEB6CB3D9D536B783CA9B777D747D2BAF91D8113FBAA46F19E4F9C38FA3E637A2B12CF1A43C7E51EA45132CEAED1CF51BD322F47EFA30351B7DC999184D0C2BC1781599070409A5975D950417858D4DEC3E77D0D20492943115DFEFF77CC1CB76657744094279B82799428179C922F59CFD7A5B66FB9D5B7DA92EAAEBACD33A2CF5939C863FE8855F99C8CD4FCDD934E0BD46195BF069EFEFD1A5D76309629645E0FA27DDC809BEE42E985704201AD3E039515A97AB454EF736EAA126DC11A3E341C975168348B746BF678F9C25A89FBA1E72A6AFE10D8CA04D3D9CEF205BA538B336E27D2C90553B5158BEFFF086757ADE022BBA676D8CF972D82E2FE7D918A2A396EDA3DCB8EBC0CF72F482EC544BD0537D03C8543BA6CFC8E60DC47ECBD93B8B23402F96A840ADFB0CD7ED765C42EB082A3237F357B982C2AFE95A48F14D0E9E8AA70859A710B24D4A1CEE8CD3C74020122572DAF49C6956EE44201F08610199211B9252E5171C5FF7C86F7DF786011A00BFE2644CF056B65A34A19171BB4F1819F0F95830409C3DB280483C7CD1DCB46325415149A28742FFBA9C4FA2943B82F984EC04873C7DFB303D3ECDC8A9480D01645B3031F63196051519C75D0B41E9F9E719E54985DAC40E6599797D9D106AAB7E3C9A7857E3BB39FA968ECD79735B26339C276766AD0F812803CA592F06F484A8AD1660E539827FC8D884B8E38C3C464210DB5AAEA945528091777F61B4A39E6BCBAB549D50ADBC9000523A0DE714CE1C8EEA1CA4EA533F0DA3A9E76B11B821ACDB913AD09985900B70290A62334DB40C85FE3097CA6D304CAF9E9CED5FACBCD238F00839E6D8A237675C9CE889330BF78D55536D6FF9B8FA557C4F4E032F41532C50B63E9A5FE0B9194063DE45D26D237AD814514AA00542CA720A0303F845B946736BD0F75E86B6A3E88F7E4975C3191A8EC5066D2A7F521ED743F1E2943FE3E69D4DF86C6C18CEDE37390B52675EE4CECAB27861742DD659B38D63C150CF7FE5D8F7EFCD1AD7243CE6CA738A8BE57F146C1A616753A9FC49B09A98136AAD7F1D178930E7404D9DEAF9AD21D9828B54C728326D4E96F6C2D42CAA4935A18A3C6FA705344C8CA90397E2B6D998927D99CBD28B2ADCE9AF54004A6592CC2DA9ABF9A332038D9E0104A9A9065FB29DA8D978B25E84C366B75B672442F14B0B62EEA075717DF8DFA7A06FC89D216337D7C70AD44E8510D6355F7A938C547DF45065AB7AD8307B78196403D1F489C4B2F2D70C4A819D76845137A8145C723F99032D659604629D2C7F17BC82A9E4FC957C4AA72A02DA103A6E631F247A7F599F584738E598E54FC9701E9FC816298CF04E66EA56F47DF46CDE3FDB1757C05DF791745D6DAA5AEAA556581016D0C0F76D17E1F1ED0A276CC3F1F93B5ED3194647EAD52DA88AA98DC6C07F5EC3FED6B63E48C6149D8A5BA892A555F02C0AFB2640F2065A722E4184A13F8ADECEB6900B5ED1C72ADC7F4562CB22B8D7D93EF768CF44F388B63C0956132DD5E928E5177203D5D8827C9B5D2E8715CE03F1338D4682C7DCAE71F05602DE40D7BE99F13C8FCE7994717FE00694C79FDD57DF62ADC4A069FC1507B2177D0B637CAB5491E7B2727A2ACA78462A83ACD67199D634DF7929F46E2428E31E3CBA7B57402BC88D38C7C2C2B11B727E8E2E89397AC0053AF08A5F0B5083FCF68544E16D1F6220CEEE88CE1E6EBB457ACC2B6F6B3D4CA83849C0E338A66B5C01DCE3AC694578814B4849E36398DE3C66C61B63C54CEEC6156680B1A7EECECA0AD46E1F074BDF1D500250141A139357BDA28934C41305FACF89A723A1AC03E1962E57AF0E4337F0D977A17C9C1943F1F23377F1744A618ABDAB6D2519E59043E5A3E1397CC9F833F1DBF27E485F44DAF58780787C39819229B112C3222E159237C9A8ACB15037449F14905C688651443CC9B26246CCD0A7F0D2F1E6872347CF1B19815B1CA2F41733EA2027C175F0A916EA44B531A1E805055E18C6936C4DF572EA37ACCAA428B801808A33D489C3EC3C76ABCA6291BF37ECEFFD9BA355441517214B62A0B5F63C9FD7E5EF3E5872879BA9253643464EA5B9C0CDE9F11D484C77800000000000000000000000000000000000000000080D0E131E23139BA17ED7B476DBB1CDFE3C42B3A57AF5BBCB3BE19ED04D6C3072FDFE917ECB9272D59EE89EF83522531D83AFF8B9934A8423315C350D1481A4B02980DC29E1CB83B76623869649AC40EF297B153B679C327BB251C6E6BC169C48ABA2A439F9EA24EF94656A415C3E86D7BCB43CB3717D54D773F1937DC8B0E02D4E6ABBB1C83FE73F1B221C9A359E454C19DE5E71EA4CB8C560EABF1DA133FF20D81785D2ECD935B99F24840761446C324DF81484C5C05045C0949DF8D0F10F942E1B5B79074B358C25B6EC2B0B42DF65D998B666CF1BC568E7D737F22FF541807BE95ED85A9980E940E24D2C506BB0F9BEE32EFFD85A2017DE694F61BCC2B292595C97FF4C2145E48AF8F0F3D71763B4DB433ED7BDB8DBF8643475FB2B9155F0CC6A0048C5546900792BC01EBA4B06C83A0C447EA0CF05410DE55ACB8E5521829C89BFBC084CD86E7CA3D701283B70F78E1CE9C3888AD2689E0EF5593D656285066F319E155F86C0A71256484F42A0C40E7CF13AF0CF77C6D1CC7231A48538E9060A7863B774C9CC65E321E45AACC002C0170EDDD18CC1424159D46BF99D08A28D2DEA8917D28D91A1D6C409D945A5EEA19413A1ADCA40DE9458FA6BDF1E5308EF9E67E1E90E9D92BF19B5351FC49DFF0A31E035038AAEC651C0F20F276E4EF0EE35C14BB625EB34205516D95ABEAA06A7A3BB3AF2F12236406689BFAB11E65FC63EBC5B944818DD1D53C0E7B88CE7AEBAE581D995AE7D8423778DFE20D6CEA7AC0B1B4EFE2B9D571DE77BD8F71E89D9F6A2DC89103B73625887AB376BD12CE89A65E6280515A44A80D6C32799669260167DA0A214AD0FB803930AB1952D93360B54433CE8220B29339DCF2702581E88952A5A1549DBA11F4CCDB6FEFD6D24522F3207796C8D5BA9D1582F888F2500964F2B975AED5D5AF83409FF9720EDCF5CE3FE9B6B586B08DE21956E7970D8DC28F6208A80F5378ECBC506333A1D98C58EB0E2EB0CDECE0F5D16A069FFD742D1E589F546C4F2EA3DA0A56F984CFD93F5F2912FB1D068F2BD7C1B5E979ABCC62E3A0164445398F5C0208E82B99AED1200D36289B1FDBBF03E43995341AED3AD712CC7C7530C751B40B765073EE4E4CDD411AE543AD5E2793F294320E9791AB35AE1697F23EBFA0280B8041859909B0089C101D7CC429408FABD2E073FCA7F2C2886031E9F6A32F2B596A799967BA8A47E87DCC8854D45DDB6DE39160600EB4235F4E3424D75DDC8CCF041AA05B25B5A3811540EA5B77CD8D7D611A63BEF5C26D57475B28E961645AEE0B9C8D47954FAF634017787A21A671493E7C5F1A4C553E0A68DDD726DB1DED4321DC735332FEFDF2A84C22097AB3552F878E304598EC40EB349E1C1AE416F94112A2CF8E8702A4C3BDE2F58245166550FC238E153D10F90652518B1D84CCD3ED836F150F1FF103976E743137DA5A97A61276DFB0C11D071B240069582265A9CAE4987B6C6B017DCD1594024D7B1336FF141E59936EC4CE5410E1B73BA6FB42D35F8999225CB1A135260967F4F6EF2172D53FA6AB6D1A2E3174B46C24BC103BAF69C2128F093AECEEBE8753EB352E2804EE64AE5140DF1ACDACD8F225B3C9A61264245B8E5CF759CDDD75E25E2D790FFAE8421515E0CD6F279D0080A3F80BB2E0729C0D2626B6ACE31CE20BCDA490C7660D04D1D82E6403000578926C52D8F9A4BE7103D64E0F03E8F148BB2236781EC30F6D8BC827C107FCC40F26DDAD485E6135BDC3BB331BE139A07891717B692E23312D0E5B1C41F30C3B4B4700EFFB481A835AB54340269FFF365FF87F58245621ACFD83B7FCC6FF108132D8966F9836544354F7E216FBBB851F390DCE8A72362F0454730B90D35AB3859763AEE35668310FD501C7501F4599563006AAEE9B636B676F3DBB6787317885B0F4A64171BF19CBF2EA7A625E1563032C196E1292D82C7484817DBF78D8E9E478FDC4C92CBEF48D4CB4F0E6DCDCA6682DC0A56C3E45EA0350D9FF88073748305FD7DF3A3BE8C055CB1C55167560D5C99345BA80C21CE791C4A511E384A02833B78E8AA02B1B877A9B8D806978519D716C611DF54AE8EA2691540E87C6E79EB006569E02745021BDC7852E1FA4177E2C3EC89257618B38719CB07B0BA68F600236167F019694959C2AB6FB39D5890CB176F6ACC3B9656E495C07027E3D4DE781F48C1F1A8AA1B41449689E191E495FF3F263DDAAA8DE0DF6F1A4AA3EF1F5EDFE437BB74BA + +count = 48 +seed = CF5A04DDB5EBC45328F703D486D24443A7692D65AA55F054E3078DB76A7939590A3F35CF1A21E82A845445DD1B64A85A +mlen = 1617 +msg = EDD4DA833528B0511534F77857FFD16EAFB1A2AC87E6844612DBB104B9F32025B7F54E993D65CE85A061B6AC6D70A15BB42BBBBB6E2E21AEA55BB8A556120EB15EF35FD9774FC7B5C2894B747D3E4965B77DD8D5B26F38D413662783DCD332765B4DE534D08D6514CA9DC6ED7F2BDB4B5C437178710B04491708836CF2CCA08F28582107D27AC305EDE6030B1F8AADC4A1D29AD16CB4D739D8F813D47DA715CAD6B5CDE24EA95DFF4415B527DD900442D9ED1CA712C58B206D6E79F8AEFB882013358BC578638225BE79B58FB677277F072AEBCF8CCD6AB61A9D98A3B260E60AA625D78058FAE6028E4C5562A0F3473C3AD530BC4471228F27502A8F8FE2D1F72022103C3A2DEA363E68248ED8693B3B066B495561CF4468E8EBF32B454E54DF1766468AD3831D56EF7EB9C231E999C4CC3A6B0EBBF2C4F22820E256F67497427F53AD22D42C9293DC8682D0BE3517B63C6E871910ADBB3406B6B3B1CAD980AAE47BF9686E80B6E5DF2DACCCEAF9506B4667271779D00B4C1065951E21F2ACF6CF3CCCB8A633D1114CE9D531D94420E4AE496086638F031C0BAAB5722A41A66788D3885EFC7FE1C3DB54BC69E35B7489A0237A37AFE5194B5F424F792CC1D696098BCF327D87EBC50429A95ED82105C4328D0095A9775589FDB6C262FA51FFEE4D99C6D1A68FA661D1B6A0A2E0693D73B39218A6895BD83FC1D54831B7DF146FE7BD2A91B979018787B9904285A35922E22A7F1761BEA541EAF21D74E3A2F3C6F2247B042379CA4C553FD9256DD0C63E4C9DEA60912D02FBE4CE7762069A86CDE02A4E1E311B2AFDE435DA0816ACA659BD8C0650C1F118C0EA3622D72A5E96132F8B0FF8458C757648BD46E58195FAA0FC4FF8FA44238E35A25C9807B6229000EE560D8E085F27375C2F659BAA5FDE302B9529BF4699505C28DE33AB5DC2B8C02967947CD24C6A599ACB5C2D1E7D6BF3BCCEA0253FBE11D8043FED532AAFC9EE1151243BB80B92BE239BC4FD1D1CAFF502951205F2E6393B704E67141E1218963F664FE0759C15E6C0A1B40602A73990F040502867A9EDDBD4DB0E554AEA4BB9597949D5FB32C2E3AF92CF7816BEDAD5EDE1B769C823CABDEFCA1D1B85213C79EB03E065146B58E3BFBE80B4D4683B65AD1E0611372729B99A0B93934D52DDE40C19FED5A2B3DC3030E0B5F26B66474A5CCA6D741AB294BBBA6BE516105C08BDBABC97BDEC2141D035BF6C3A71553D6F6350229CA2626B8B0B56A24F2D6EECE436ECB77A70D747B6A6F830578B4792DE533879B174353424E7D0EADF6BD5A74B36A4E6EA7E39A4215559557BCE7A00FAAF0D1F81016F913A10F3C9F406C7CB53282CA8FD5FE4F5FABB96F891583E0507912BA02709764694296A5248C340A1B9EC3DB0F926F438CA96FECD40C4AD8DAED9B8A29691601835FE14283762236EF2135443307E5F0082D1C2180AE96ED0DD99A6E9172088E8B94AA2952BA5E128B202B2CBC1966E69B6E6384820D9AB624BC71788EA84B4ADFCFAA2EFA1DDAA8855D1DB3F58EEF2D54FE11A8A5D78ED46B58460E6F2FBA6CB70640700A4520AA1A2A9B336AEFB17CDE8AC78D67F194662642A0107CE38B74D731380A72AD4A0A068F09E0878E521F15CE8134780C3FD0CAB2DC2473448654F88BF1FE2020901B90C0ED670866B1BC337881292FBA885FE2BFEF6FE74765CA12372C8CBD698AC41A4C337374587DB15AFFB511D8C224F1743498D7173897FF5B8D070B89592BEBE053D5C10DCE67CA8542781AE749F3A42FAD7E4A2004A565F81D5FAECF11115C270155FB8AF6AEDA138B9C71458D6D2FF63441130EE9107C39260469521E020D2B42CB5A51098027F23890DAE8B28BF722AF9ABA6224E02FEB47E40112CCB164E8CF174BC9AC4C11AF9B482DF9C9F7F5F1B826428C21BE395EB1F07DE511E8258C84F5F035F4787ACE18C190808EFE99FCB455A54D366DDE2E230B575ED5A4A75D57C9A38DDE3D91D0D1A1C4DE7F277CAF23E0C5DD8E3B693DBC66B6BF1679B0AF74A2B9065B64CF0978115CC456AF685B22D85135727A8AAD96338611DC109B36C85A92E4A0180AADD1D25C5B3D4C681A44BACB953E50F994FCF5281366CDEC0CC50976074D91840B5079180CF643184ADCF9E4CCB44328E7BB9EB2BD06DBB7A757C35EC3DCF795A5E05ED250159EC453A1692426F624CC0737F691E475804F155E44293151E42D3C0F115ECEE53C6EEEF69788F7E8E5C422BB102237499F2638244C0C080B3639A49FFC1730EBB0CFD8A46 +pk = A889A9D320C832654C7B08E64766750C0B0142C293601EE8410C399B0CB0CFB518A60575E2FB47649A63BE03C361594495632FFCC006A2751808C609ABB195AA9CD2BA0C80FCDC7C8A3F719CF8EF29DEC9CD978031AF922B628DD476EFCC7D348ABF00467D3633B4C46C802FB86DC7B9AD6E96036AD451C5D836DE5194A42313DFFD066C903A408D5D72983146CE92012B4DD43E8C79AF7B5ED099893113360A52F8011FB06E6C5AB2379C7E42E4A10FBD36DB7DF774D6AA97E7598C5F35DC2AD3B823BF16BA3A102E1C69E66034506E46D986F7AB5D07ECCD190BC4C422FCC6B730951B763131F47A470625D5ECE9D21703CB796B8F20BF70D25141D0BED4904D3E82C069F54A1EF3CCA0519C2B1EA619727CDD0E6363B9F0AF2025CFF38230119DBEF3E2D232F06791989AC3E82071E1611E2BDC30EABDD92EB327F98E0C4F7295988E83DED4C537CCE5E08D1A0A36F78198083FF76F1AD515B8595D8F672FE1DAE7C6DC169E0C1CADA5718D761B4AB0DF720D72A972794AB1063542ADA760CB9A7DD49771537B3C7B70FE598ECC4EE69A31C4BF78F4BAC95847B6A178269945A7043AF514EB61EAD1D9386B4C576D15972D62468D828B79C3094DFF66AC45E9BD3BBCEBE0F7D68949F8925202CE11CA887A6E6AE4E923DF77944C8EC69713B8BA9A8475329C14D212C1D7D0CF3F290718BD042A8356BE656DAAE459CAC1DB2A8AAFD4ECC9CEB702B288FD6E1D4D99E81512D4821EC5A8D3230986759ED9917B79027A8F591E0BA2F589C55F31390916477A0703363F1EFA65ADD9209F5D4109CA400633F9F27500BB9596EB62E7C9DB7E732E366BC8930F9785BE69FCA0A92B180AF5E26E42B39C5A69B683B552772C9407ADF82799020EF9D56AAC27573EFEAA95468880AC708C3BC6DCEE32AFF7B750251796B5D46E5D9F0E90DCA0FF271536707232041025A1C50ED4935840D08FCD78862A45AEDE87E7B3307B543CE720BA09EF23CA3DB32EB5B4BA6295A2719AFE261E5D64D27731185ADF99BADB27541AD9250C9C16E3F835CBE846A45DEC9735E0C7FDF4E9605B74FC007CFF97B008B905F194000B623DFC84FA1B7B20CFFCC0E3869B850151904EE00D794C69368AFFDEDA070DDB72D05A66DD8B668C36B7A058891936D16ACD03EE99B5A34DBA6C85E48F2FE394B456EC9CB0F28EE5DE3F0FBDD481ABFDD621205CFF6B2DF4E0779C8466807B1FFF6378CBBB0162AF8A8257F33C4B80ADC5D49DFEC5C133D20DFDD81FEBAE3CC3E4809160BD2991A6B47523E27F6F0038AE20BDBAE5E2A36D4262628CAAFCA9B67CB485D8DC9374CCC06B508EF09931D7504CE48BD85DE0B670947CB0B6D4C6E57559525C1F597530E5B119369CAB615A0F7D181390E3961E53B4F1C3BEDBF7CCE383AF5AD948D86090D242AC64F5061E0304E7D459BA4905E3DCDB7592F0D5935F432409EF61949CC643C5DCC590A02069E22880F82F22A4396087EB5D82F052F0D07E95CB1D07386AD7A82AB2B1E8011289EBE4A73B667B83E4D079BA53524121C8599D6ABD2BB4371B6CD68BC6B41C43A0934B6E6CB54EC7106D1100F2A7DE28B481221C188940D6221E78EFE491E7D7552DDDE5C19FFB1AD8846818F71D8FD2236861BE20AAB01E58BF6A42E4E7731BF23731285500996990B00A02105DDB16362D0442E780658A6692C6A671AF8527680425A801B1CAC95EEA16C7D71E693770BC226DABA02F8495FEFB3BD38CB1258433150506322B499F6A3B7A40EA0332A9D566936097E10A85584ADB1F172C5F8834EC6C6276A555238476B7AB82AB6C6EFAC579873232C6420F31E935FD5C4B1093478D8384C45F17A7959EB7E91243D60BF882E690816FA1F293CA885D0E512EF41549C3BEA6F748FF1FEBDCB515C41F832EF0E689A63673263F0D4663FE9F0D18126CAB947E6702050D5DFFCA0E8F04F4472926E7F4ED2AD0D1AE0E5C3B35A967C2A7A697ADDA79057608591AF05A0610C0990E03E7419EEDF8FD86DAC11E078B864DCBFFFAA364E53957E5D6F3B916D857D62D3763B16676C8ECFEE68B38BA955D7367223B1516616206723EF3B8278D3E7FE0EF2EFE0E72A2238451E2F5C7C2655BAFA11DEBB67EF548E5E441C4E892685050F5ECB4FF2F6511E2F17B927025DA7D95C572C412C197F1C97184F51FC4097513428461FE0D953D7CD6D85FEE0A96C5971D6E251F10BC7192B2B5182156BD8666BC978845E1B767A230CFB5078AFFD8E97CC2FE1BBED1800F4A09BE85DBEFB2C841553ACF8209ADA8693F0F2218C6E57C4FA39FB7B6BB0AF571848AAFE0119CFB6E0A2B5803EBD61F556A3344D3711E0DDB61AD0F7449FFF1E3BF4C7D1CA6944CB33E257FA053D49B31D0251628498DF208A4CAD4D46A800805B980BACA6D5774C104E005669A575C541590259588FDCC0F65623EC78B0DE04C99C1F68956D5A5C5A14BBAC0B8C9691A98020D3F81028A4BB73A7D3E3F7E49560D0B13B23AE73F167DE2D5B6DE8F5C481DE1C56506DF4AC3BB0FBAAB121160027425AB9C1DF2727DE04509FDC112C37FC450B0B012E9849D11E2FF2C5301AD5CC5CB58A563EF323C64A5BC563057F695621971F1A951EE9CB9DBA0F616919DAF157A52F1881DFFB574B8FFC375ADB8014D66FA54FC3B0CDFA6E8556777D534EBFFF23E925479CA91164AB57916E565597BC629626B7A68827513661C7ECBB6CDEBF6B16865C01093C9214137964ED35651B2002634A14F1FA20E +sk = A889A9D320C832654C7B08E64766750C0B0142C293601EE8410C399B0CB0CFB53AFED2F3508D0F9638F90AD8DFEFB714CA8448B5837D94E1CE6E30E23202D04567334028D67ABCE9927CFF9E90C20069C560065E92568E9E55427B97804AF5155D028A16D3172CE01D1AB1AA5E348E6D186C5D7D02173FAF817ABF9D5675386F206434864002315240283575443176268362175731563261678607572164378438110747141654368052288626424304087115257055463456417360421424787281630037211852452773318015782704884783173766513323344385185026145434442082765868765235453455451164307617364265568140652242787824812867460087874018453020273381836854163886535266056216736436556437475342307363176478211348834552424751524613703284730760781634245015346118665013675536454412301458132833511101553715615846037213654516150364060606764283766503171675288335061046832572341878324532068010374202070650552665378111630328302838401054762005200634544746038357425183080640164687283188315707051008160611071850266368632613368480710240020531143822012071031818638837132436757033400305617553268723262524471601750042135250063817888045423138566320576736185722760228463360664835577773116568026872471064053102806735756828820377240646274280885631227422868853725145522052245272512786356666382178747102637066245170773858262645358888882160777384471468716752456057714273083767053511383036305064546727121675185448752374785586717626337240628263775380848107437611068012832028771646866800825617675440325235348727863381772255236575122806720736268873870136262035360381640107307633614736085103711067602334677182228567067652203370821085283241866152045465440520045003122416410456144550736071624362463860364731766516725084031133046462813377700405446525175361832418720720304884523041617882638704055847648285855255303751866532868533554454511365145680803786505657367006372685328014833188185043370612574280184226571014047068400333864645157815580881513022283035141275523503478261025113360805422160525574503316352785228262218140245141718723624354062327812602476302616336028556652407358572560275721227141066020260373468216765767848335148827522574732213225228241560360688365433572248442607382568848540878021840875534153480226613016548057876772633775477256181187063466031645325603016223162764615780515135603661351874101833210138872570328120701351768063656123561577716687034122043444263347176316218612143117310543386545120507552815045048871332270825644387683762048066685305881440068201233468268602028551261407545766431804615723460813801586676856131450106587270443074476451334301348546071451533151182865453382238611553662165640001251408252253653222846608632550472075557014566174057814567455483238231375863300363657061106128768816503155563485815700300483252016324562224116775343367178315053333382828536656016748230706804437757736528278101157186712662087434514713278422265664355658127051016362378516024047204104027308401282387467847436337001251472124663311487778302687622851335085275563644644551165178550350280650624428538514804682738824120802151833431421026223606048545647656134424662447204743367281418037415601833476365524155366460671632480341373472416776237420153102331502747081144718086524720367835850213553102047332854479AF90F68DE4287604A9DC06AA590EDA2E18C8242A4149D3543320F2E4A88DBA2C655FB91DB7EC12D9E9939529CA2818C79FF2B63C16B0D126C9E1C7E19E4B5A89B2466D08C4BE7E8FBFD6705CABDCA344F03876AA863613F79CD33C97FF84E49501897021F4DB56545B8E1AF6D7D6029942B98A5C9C77100A6F50AE8F21B132EEA3D679E941505B1606C36975885F2E4812BA58DA1345AA514AFD7FC2EC777C7250A02DF8091021FA919E72A4E242EE840740FAA3DCC28FCCEF4E40EC0F36A44C5D3E6BA417E9C1B944F1E64EA6CCA1B68D5CBD62A33D4B5DED57BB5351F550D8A7B402479113E442E8D698E5BC6AECF00EA93925AF6B8929777415674E7B37D2B919E13C53A02E3EF10439432FED1D801FF7B5221946365464D3AFC9A55C908C8052C2CA3369E96375A6F51D76D90828F2DAD4E3EF14A1AF6291C4F95361FF55B9C4ED4F7B9FF3F572E3B59579242E48FC4453E8982F1D6C4641D7AC8EF78B0410463E441B31BA363202C0191AA0622FE02C2CF314CA38EC10130DEF1B1DA6698BB64427ACC1DCBF09CBA60A57825D8B86BA63D4F7EC6716EC8D4065E96C3E8DD483654F203C770496209A94B65CEF824523A359FB0EF187F7FC532889BCBAA55137753B6675A6773F2E2DDA468B184AD5F9A39059633B98A968639FF0DDD2B7B26EA9FF1F023A4FE6580EC7F72FBCFEB9C556550CF195ECAF4CEFCB4DB898A217F5D9AE7F78EFD9206836AFD833ABB730D757B9600CB6B6FE952694E727EA66F5B094E08689F9C6BEE401CF6A710DFE9047B6E7B6F582FF17C350EE29FC17E269D249DD6791550062ED3B13D146E3100A32142638BD2177CFC1B0A907E2B0B814DFB2EB4E49E97CD63EBF2B59E2DB4FF10796B7B32D486EF353B1F4BFA4D9AEA9490168F62444DB49DD675FE37A81DE184F4861A64921609E4916BB28C6A5E7FDB25C8F986BB88385A3DCF76A7C4C9794F3C1ABE353291865DC2B7CD83BC3B5DD6751B38116452E37C3AFCAF9DC8F6857483C0B54D15A646B35111E00EE3B93DE1EC598ECFD63869173B877239319C4085DF723D88D7D2E0267BF3F26E9BCE6AF3CA430E110428AECE2260E4CE19CB473B99E79E1FBD2DAAC539561915EDA8B1815493155DEA1307AF3C83B52FFFB40D3A0BDD3A9B7D16A0B1CFFA5DD43F5CFB1C472C132E285C40CC178CCBADEB9A1CE669F56DEA5B0A29F44747A797FBA61FFA9557ED48B1AC545E5F12F38194EF7ADA90AC4CA3105FBE3AE24BFED6A24990D1220E7E96C4EFBB90411F2E5C53CF4551277420FC339C51DCE03CA990C4393D4D52D16181921920D25611119115BEC359069173D4CF588EFAB1D478CC8E87AED9BA57EDE47394EDAA3FCB8E03CB887E734A341C9F33C4D98B620C65225C26DCE1538F6D069DBBE3D928414088FF1D67BF55A35E6F5E85B691DC70CE26B062A1D645E85904247D4C38EB6499D3CA6CCF175C308DD3D3074E43BFECD705FC4A3C6F03B2FD597D55C883B62BDD404DA9456C40F998FBB016FFA5024653F3C8B498D58E51D764CF1EE511CC44D34C468B513BEA47438B7DD97182AEE3B5CD38B0B712184EF2833B0534479279EA7DC0B80FBCC52394E12F9F9B91FC0E8D34F5910EF38DDD90764192BB892CDD763DF248308EE52A1510DABE419C93C04F4C7E2868BB7862D0F5EE60FB9C60B88D0580E8CC2D776EF460653DCFF2B3631D89B535F3898C17749DA8708A90EA3CE71B4720A32F66B0101CC83A2EED45347019432EF8B2D75CBB2677DD5B89FE3F621BAA15CD72AB05504C8953D1AAD37DC0B25EBCB69B8BC06D545AE65515F0C35F42D6E08FBCA36AC876163D9FC322A97B7C226BE9789ADC9722A46609C0DE0685FF69ED6A39056C17289F01EA31DBA170EA9CDD75464F45A05315D70E6CFCB3F1919B0622F87E7E1E83F591F183165C73075097E3652243ED4D580D3C4089C12047E1C473990076F64E93EAF7E6186D88FE9F24FD417F9FF73C6FAFE2725F794EE106A9FAEE244BFE4963CA741A167D1776B6E1351C25053322D1D0107A2B6C47ECCF5341132D26A71A73CC564E36F5BF01B8AC4C0217BD86A414731FD6DA5E2920531D335312199AC6E36739C5FABE835F2BA819B12610AB0B9EC6CAF989F90CFD1D489EF1C6DE604CA81CAA030C0DFF4D62773A2179C8750DBEAECA082D67E42ACD19091898029D97351AD390F3D067A996DE01B7F75E43200700BC5966E23C40F45AFD12E51363E89AD65FAFFA9D3C74745F284BFC9E8AEFA7B0B649A3727457682C5F08B510E6DB1B9CE11BB59B07AF93E970FE0D1A78086E839EBEFBB08A1DF21811CFB6A0AEC2DA4F527FFD0FC6C3A373523BB608955F1E157EC2264599414517980CFA1D354E4B129A9D40858A939C43FEA9568292FEB1BFFCED5F56B0D85CA3B56F2ABB3C99859D24BFA59F90558C0C0BC0BA3D7902D77EBE9A84853DFCC590878B02FFCF28053B29E6BF0748EE76674B0630046F3AA6F5B2C528ADDAD6CB7B49339FE4D452F38AD07507E034317618430660BC2A84D0F691A6332FB4556B116EEE3930371906CDB1CFB60F9BB57AD8C37075842B5638B85EEAFFF70BEBF52E09EFD06784AA2141A316BECAEE12460AB555D7946565F87B514904328563C684D1A08F8F4BD9597C9C75759F71E72744E6842B06ED7319BB661A9C1628AD3D74EBE82455932D69043CF591C4E9E87D9F74032C11122F64123834214C2ED905D73D48BA50463C9E362953EF349F18E8E869541252935383C93B81C9447BF36B85BFA16715B986827586E9402D909D11AE08F1161E007D920B5E061762328A3BA38F9948EF428859BC96AC2EA65E76D33464BE15E7C709CC6102B4A93A8E824030F86DA6663654E225AC2F61C88EC84371022A92C61D13D3FC1CCE3DD9236CBB6094EFF06CC8C9F59ECF0EEF2102E687B9FC442C9288A73ADC81419B949AFD74B5DD8625785F8C91DEB2ABF65600AFDA8A5014ADB1DABF61ADB78066408FC813B90094255B989793169BAB36E3534B12454DE7D185E264A59C9A3AFF6CD6BB50FFFFA8D2E34A09C9309F1F21EB53E47A4B2DA46044264489CE919AEC0C924FBCEC9CE56506026CD679B0A52830A2307F404A3CBA2FF454975FE0DCF6AFAD964818A868E27ADC657FCA9CC2D6E14A19DA4E897DAE3E58EC76FFD53EFB38E237B13F830D8833980DF42F0F436C1B2EE54D4B8AAA5B37CF99016E686893D8C797A470AA584907D8C0B03D14EB8144D15B23C5A8B562D5497884F14E86D3D6890FF067DB78ACA49AF5A7B3C0934A6B12961E89EE92001C5B6DB368EA7C9CC80B6B91A9BB493E603DF71244F05C508BF996738D88867879FA0B480593CF9B19A21718BE595F5947224CF3B0603C976043A6541973088C3834EEE21BC3E5E38164047F51245556CA5347818F1F8B3BC491089ACDC383F9E997B8ABDD8F4B113D0532870F8F7238D0D95C816B9C8F709738A2D06EC4EAC7DDCF6E9E18AF27255B1A43B8F15DD0A029BA7810713AFE6BB6CEACB858 +smlen = 4926 +sm = C6DEA872BFD24512F3ACFF1CE63EE6187039189CBC6BC1D25F015DA7384CECC36AF24465690A677553906D86E36127ABCA2A923BAE68702A6DD3968941ADA222F12C2ED6AC5527C0A9DC34CACE74C67D0A589E775AD9B9FDF6519F2F437CBC4F95F619EA2E53C09CE30D55269AC13961616CB3FC816506C32C118FC1F14DF5474683A9111AAB5342FD306588DEFE86781D77A329122CFDBD025C9912DEEDC65CD967307C09956CEFAED63E626126D841D230EF67D974FA519EC71833FDD79921BA24574802313ED9847AE4BD7B88FEA4B451009A272EF9EFF0DD66E29A0094D5A8FC4CA9515F29E50916280039B83F40714D1F4ED31C5A217B34D23D329ACCE11F5AD385A1638B30AFB8A9E9ED76EE8B7213581D18AB9F5CB0CFAC4E7351BBB7443496E94D77F6EB3C5CB6ED77C31037F6DFEEC02E13274CA4015AA2429BCD9EFA28FCC4D043A02CCE5F06952B5962CA0C945A508FF6115BA67CCD5FEE1118BD878DB145101670CB8E230FCB61CAB8C88EA873244E3020F736F03AB64B01F2FDEC6BEC1FB2A18385EA04510E7894B56899B7FD9BD342FC67B792091EC54BD3C16C70681E337585766401096A12D7DFE0AABB5CFE4005E2D750D70232CF640665583F44CCCACF77DB78CA1A1B1D2693F9689A1078BB1FFF813F390D09DA1FA86D0BFEFD613A852FA7BF3CCC6BCD7ED9AEF8938DE26B554DDD83AD9AA4E9EE094EF37049C4217E555A62A6B3299EF1A4A5E9AF15A6A7B45E2AE5BE03BC50E843877200A4707FF0F6EBAE2315A186E657E1E1E9D4A2621861AA2401CB0127CEB052CD8E2F08944C841935C32EE60F1983C2300E7EDA7B6886A6A2114DE821D24DF88A9F019A02DACC65C35219D0C781F4830C275F008E7E0B7E1276F379C9AD22B43B103A5788533105B49720724D2EE11B453915D67E99E6C49F2FD5A7F96F52C49E1404089002EBDB6CDA121340CB74E0D14C75DF327646D4CA1D90B81A36EF1E91632EC2136C90613CD8FB5C2E6B28560C6E01053F98E91734F89C7E951563FDDB86F2992B31BBD1D82BA63A5E94308F5A7F07E3C0CF2A250422D415FA94CC8AA83D3AFAC940E18F45798AC744D52A0447CFC46B851CDCF4705264D2541E23599538F00E00CE08856E2EF6B7CCC43B001DB3950496B07061B7364DC8D4AFCB0034AD0CF624DB10198457912A2B4FA76C956BFF90D25777C22C3AE5B87C7BEB61E52626CED6DCD39957F1EF04542762CBCAD89D99CA07A644E0C73E62864CCDAB2608542CB77AABCBB172406323A75A46B50D9A615BD726A488700BA62A9A543EA083EAA3A5DB244B7CC531AFD55C2CC7B5041EE8C9AC26DD0990A375FC8BBF585A7BD64D7012D1B9D8B8DCF42D51D1E6350332D0CEE5C4EFC67441454BBC5A6083237AD13FEEAD4BF61136652213E610E4839E3B0ADEC121B5AC8230D35A0650B66BC11169F1610AC3736347A5507B756D1D5B67A0E26C86F69A4781D43EDA868AF9E693B999E78E821B6586E5E776FBE5F6BF1F705184C6B11DAE31FF52428C0753895F201A8CF7B9FBF499AC69EF1385ECFFD2C6A653FA697A78285082F005DB2DB700188C55E201F7F2CCC8667951C9F1280867CDC28F5F3154EED70372CED2C58256B9A21583CA561BAA04810F01BD053ADEF4C265B22F34D16065DB4D4E889CE37F02B755797EE21A2A2B01322AE0795B2379036AE92506A04D7E3B4565E378382AC8CF11DE6CB10E61F2779B408B4D8D418225F2B1DE937B73E68A8F0E76BB10AF840635D571A6C362D65D96B7EC9A8BB9A00C97264EB542CAF6F2B15FCB8C887F728BAFBDB9EEF3C24AD946B787D337C277CC8970B644F48A11E2D604D1B46233B63A2385645B8BBC2B0E4BC74312A5C8FA90D0876EF18BD30E9D7E0C3CA0DE7C985C5A09DD1DA67BF1A589FF8B19D1FDC67DE471843E076D997CA96456DC2488DEC54C2B777DF8A0C1A0FE0E054C475A43DB721CEF28B66F5BBD44FEBAE10D3A12573FECC6826D927186277CB16DDFEF72B148AE97C9A68224A4A03D36E53E1822BBBB33A8B0435F7F123053DE79B7C0ED29DC4E80F6B60125D44C011491C6350975CA83F704996406B29CDF30B87BE971805CDC338178DCEA5126A2E32E82FE0D662D487C46E858CD5A79C1EAA19C00FA0C8B69BACB5CD3B533B52B30A5DBBD0E61C529511FB9E6900BF58EF08CF2883409DEA693D1C8D3AB79FF9F7B7036E862AF3FFDCF96DB3C8C49BC9B54A54EA252F9F9912A78EBC2860848CF3E176BC38680444AAEB34190E066B76022A3B74323A48A9732720AACC798F17341C07A9AE317D33267F4F8364715E61C7147120AE7B041EC7259D9B9CE413672ADB141EBE4D4FF5F12B6670A6C3DCF6CC237A2AC2F2E9276AADDC9A2E5126233CB5915B07A1903F694D82F5D0A06BD7286B8A4E925EEB1F90E26B731BFB942DCFC149498B8C542B1225C010865CF490AE7CDC93AC6EE29791089A67FC7F75DD47F6CD363C53CD07286C5BACBA5F5B82BD1872303ACF6467B59355CA1BD4566E9281B17FA023330EF0B1E340D8C8FE8D09B3E34949F30447867A7D3383B3B1971CB32943D889EE124B36BF25CDAB18BD81007CD5EA3F841CA146E330721BC00BE0A43441B487193B8CCE6A18AC7EEE3816A2F6C60510671AFD9FEA10E1E5708AF8B139D2AF4F977038BCC93FBB51607D16654C87690FFC960E500FF4401DC576DD9947A8D345D96E4DFC0D82071AA5A9D10F79AAB661D587E928B1ED8205405A0C0380818F5AD8E819291401D40A4C7BE83A674AA5B1F01E6793E3ED1994ED841305170B7578681A167E8B00000A274D2E423B2948010DA083E38971D000AE26C711CC3C98710B70DB299A4F22B079E90C08784A9971D5349D1CE3A2FF4457F8E3D48F67B8D6A1A956097AD8590D65134658DAA6E834EF9DBDD1BE3C35525E014512D7BA311B44C445D41BA7EE06881374BFDE1A54F99AEDCF74B95B2BD359844A2DED1859CB1B0F879069F50D780E5B74D6122F87F10CF0DA275C083E55D1F1731F45B8D73F4452E1CBE3A6B90F727D4F317B0FAF4628BD4A344A897822D2DAE8B0ED2AC14806F2F6D6CA34A35D475A7A69334EA11103FC1BD297832ED9C7F9E834BA10C25048EA825480E0A5E854E8FA98E3AACA6B1BC4BB2F15B004D8FD6C1DE806EA6A91470F7F59723AB406F7D16B0FEE2A4DCDE8F6520ECFC54FAEF848AD3150EB3A7AB17618B3563B6EA0E4553F3C3EF1146EDD308A7FEC8CA9B34C209252A54959D5DC9B7C5CD12979C456764D0B172C43C288FB24971B887E1FA5F4623EBFD40B9CC5B3613194133178159BB1059540795FF7DF9032CE623C2392AACAD28F1583288F1B2A9AF45B7A95A2943D23A62AB97C6442858C79BA2A591FE424B4E9041F339603DFC9B5038FB5518D90ACA7C3DE8EE823489A3F31E9A0F7257900782E601E5139A793BE33093F3ED7EC81D0C262B6090DB510B6F3F2BFFBA81DB91F9055A346FD355D90FA37473EA85B123AE4886FC2455F366D1C35B371E27CBAECA951BB6BE1D7172A0C35D61E4717080BF73A928A49269F35A6FD1F327323743A36209CC10AA17FC2DBF3D9B528291A86F0ABF64BE4B733A7F94B052887683A8CB503C83628FD5B5C9592A7901813DD646484A2049BA0EA43F598140D3F8D5D56D465F62A015AF94D1E7D49E57BB9183B0F4A678FAA9709CBCF33A3167D52FCA8FD55A49CC505EE4C1923D6131A2773C958B6B6A43CD84D408FDBCC56D30A309E0D5AAD0D1D39C3FD209384C3B294666F7E2C454909E4D9DC87057F169259A6344401F7DF286E8435B6FBE6E1B7B4C36D6AB3125A167C6A75996CA791DDE1A0A4AFB1172B5C67380B7FDE91369D874DC10E721390DDA8501D2DFECA521DE7598DCCFA8FDC8B73F1DD069F9953E1C2B5FF13D1B51A99133A77EC725D5A0717B612758487074195A59CC093DDAFD371B2A8CC002FEE6D9A83FE27666A064845C535CA7F8CB48C14BE453F007003C985EAF216B7C97449CEBBAAA0FDFA1F887D064825B6010828F0E39638AC520FEA0BE6EB6F2F2626D7C8AE68B03A6DB7B9A7BCAC6C195B61CBF8A75D5E4D20CD454954CE813A66200CD7FAFE1551BAE8991984F257D3DCB0EABE1EC3BA1DD7F4340BE969AFAC82D619BE94CD5B5358B4EFFD73A0EB486631D3BE9D843B31A1D6F102A7CA8EAA1C916D4324644A158B3B1218A07FCB795BE8E2B4B442DE2120208271EDA0719589AD57DF4BA7FEAE9E9C69F96308528A43D1F933484E1EA90391B8C56F55239F8F8B047FEB0C07A8EF47DC8F27A9F93445B41E3DC109E007B9165959536208545FF673505E694FCBD8757071638F6AA5CA18822EF44464A9D01D570D92B2D87955786CD065772FFC98DE3DE11D01A1EAAC6AFF47CF7D6DEB939BF2CB0E83230D7BBB146CEAE1DED1A5320E6A9516DE28E20517CAC38C979D207DE9CE620BF8206FCE9334FB9879C1D5E10AD6A770BE363D716F293BB77DD26EF823B28F8983E2C4B0126A3E4F4F85FDD5577FD508820CBE8241E226E707BAF12E32112460A11844698B399A165C9F2FC53C07B5119B336BE4B73042CB1CE2208E5411E244A4E5073BEDB59636B74D5E8E9EEF92C4D6164696A9ACBD2285888CEE637C4000D2D85CCE10000000000000000000000000000000008111A1F2127EDD4DA833528B0511534F77857FFD16EAFB1A2AC87E6844612DBB104B9F32025B7F54E993D65CE85A061B6AC6D70A15BB42BBBBB6E2E21AEA55BB8A556120EB15EF35FD9774FC7B5C2894B747D3E4965B77DD8D5B26F38D413662783DCD332765B4DE534D08D6514CA9DC6ED7F2BDB4B5C437178710B04491708836CF2CCA08F28582107D27AC305EDE6030B1F8AADC4A1D29AD16CB4D739D8F813D47DA715CAD6B5CDE24EA95DFF4415B527DD900442D9ED1CA712C58B206D6E79F8AEFB882013358BC578638225BE79B58FB677277F072AEBCF8CCD6AB61A9D98A3B260E60AA625D78058FAE6028E4C5562A0F3473C3AD530BC4471228F27502A8F8FE2D1F72022103C3A2DEA363E68248ED8693B3B066B495561CF4468E8EBF32B454E54DF1766468AD3831D56EF7EB9C231E999C4CC3A6B0EBBF2C4F22820E256F67497427F53AD22D42C9293DC8682D0BE3517B63C6E871910ADBB3406B6B3B1CAD980AAE47BF9686E80B6E5DF2DACCCEAF9506B4667271779D00B4C1065951E21F2ACF6CF3CCCB8A633D1114CE9D531D94420E4AE496086638F031C0BAAB5722A41A66788D3885EFC7FE1C3DB54BC69E35B7489A0237A37AFE5194B5F424F792CC1D696098BCF327D87EBC50429A95ED82105C4328D0095A9775589FDB6C262FA51FFEE4D99C6D1A68FA661D1B6A0A2E0693D73B39218A6895BD83FC1D54831B7DF146FE7BD2A91B979018787B9904285A35922E22A7F1761BEA541EAF21D74E3A2F3C6F2247B042379CA4C553FD9256DD0C63E4C9DEA60912D02FBE4CE7762069A86CDE02A4E1E311B2AFDE435DA0816ACA659BD8C0650C1F118C0EA3622D72A5E96132F8B0FF8458C757648BD46E58195FAA0FC4FF8FA44238E35A25C9807B6229000EE560D8E085F27375C2F659BAA5FDE302B9529BF4699505C28DE33AB5DC2B8C02967947CD24C6A599ACB5C2D1E7D6BF3BCCEA0253FBE11D8043FED532AAFC9EE1151243BB80B92BE239BC4FD1D1CAFF502951205F2E6393B704E67141E1218963F664FE0759C15E6C0A1B40602A73990F040502867A9EDDBD4DB0E554AEA4BB9597949D5FB32C2E3AF92CF7816BEDAD5EDE1B769C823CABDEFCA1D1B85213C79EB03E065146B58E3BFBE80B4D4683B65AD1E0611372729B99A0B93934D52DDE40C19FED5A2B3DC3030E0B5F26B66474A5CCA6D741AB294BBBA6BE516105C08BDBABC97BDEC2141D035BF6C3A71553D6F6350229CA2626B8B0B56A24F2D6EECE436ECB77A70D747B6A6F830578B4792DE533879B174353424E7D0EADF6BD5A74B36A4E6EA7E39A4215559557BCE7A00FAAF0D1F81016F913A10F3C9F406C7CB53282CA8FD5FE4F5FABB96F891583E0507912BA02709764694296A5248C340A1B9EC3DB0F926F438CA96FECD40C4AD8DAED9B8A29691601835FE14283762236EF2135443307E5F0082D1C2180AE96ED0DD99A6E9172088E8B94AA2952BA5E128B202B2CBC1966E69B6E6384820D9AB624BC71788EA84B4ADFCFAA2EFA1DDAA8855D1DB3F58EEF2D54FE11A8A5D78ED46B58460E6F2FBA6CB70640700A4520AA1A2A9B336AEFB17CDE8AC78D67F194662642A0107CE38B74D731380A72AD4A0A068F09E0878E521F15CE8134780C3FD0CAB2DC2473448654F88BF1FE2020901B90C0ED670866B1BC337881292FBA885FE2BFEF6FE74765CA12372C8CBD698AC41A4C337374587DB15AFFB511D8C224F1743498D7173897FF5B8D070B89592BEBE053D5C10DCE67CA8542781AE749F3A42FAD7E4A2004A565F81D5FAECF11115C270155FB8AF6AEDA138B9C71458D6D2FF63441130EE9107C39260469521E020D2B42CB5A51098027F23890DAE8B28BF722AF9ABA6224E02FEB47E40112CCB164E8CF174BC9AC4C11AF9B482DF9C9F7F5F1B826428C21BE395EB1F07DE511E8258C84F5F035F4787ACE18C190808EFE99FCB455A54D366DDE2E230B575ED5A4A75D57C9A38DDE3D91D0D1A1C4DE7F277CAF23E0C5DD8E3B693DBC66B6BF1679B0AF74A2B9065B64CF0978115CC456AF685B22D85135727A8AAD96338611DC109B36C85A92E4A0180AADD1D25C5B3D4C681A44BACB953E50F994FCF5281366CDEC0CC50976074D91840B5079180CF643184ADCF9E4CCB44328E7BB9EB2BD06DBB7A757C35EC3DCF795A5E05ED250159EC453A1692426F624CC0737F691E475804F155E44293151E42D3C0F115ECEE53C6EEEF69788F7E8E5C422BB102237499F2638244C0C080B3639A49FFC1730EBB0CFD8A46 + +count = 49 +seed = 8C3D2FBBE0D39E293AF2D2CC5A9BEDEAAE3752DFD19CDC1E186D41E717A0412AA429CBDF005445AFDE684656B5D17690 +mlen = 1650 +msg = D868EC985F946F3C31B6CFE4811BA530EACD0ED061EC383C203B2481AC697B8B88BC0F72B635027E443AB1F54478440DE16E596D30A0F1252E0AF54C0F382BBF5655BEA8C6B9A2F6382D003CC7E4D4F223F8E35EC87CC543EAD52E0E1ED956CFB32E8075715C07CA4817C4B8DACE68C8B0DA459271746BE41D6102B3FA5E49AEE8D443E78AD3246D0B9BCCF6AB7CB7CF72B8A847CA16B435F0618594400037179441F3BF524231F747D920E86506E84C61D4D038D42E82D52D97ABFF896C1DB1C646807156324F7B68DB620EE435C7B8C9AC8B193B7C892565C3631E297495BD3B59293F9A9CEA5E29E23A242B81DD05C8DC9DD669424573298C85870B109C7B593BF864B56895D81386466CA5CB6071005781FB214F1EAE9672D0D16351A627A3FAAC49BE4E13D552340328323CDCB4703BBE07C2A39D75D7737D5C1BD04355B8694432DFB7CB4F1901550C7D6F41080C0F6A2CC49D63A69243D137A78260C06E7A53AAF4F4B086E0220EBC5361A6A78C9B2EC09C2EA4EC45A41065B4B2DAA866D9BABD71C8E6CB378595F068EDB258B2AD1F420B304E5924EBE273AD6D00684F75B6A31DC5290A37D0F9A848B1FC4A67DD9A4FB1F9B4C6CD45E87FAB4A09129C9AB95C44703B75B54C9EF9E825928ACA56527D79B338C5AC639D0265010F3C085D2B09AEF0E4F55D080FB5FF79F13E8E4E8DB020F4C095140D46A93F2E4811BFBC1393EC24F6B7EF31F13623DF0360B1E335FC42098CA1EFCD0306C5FECCE942F6E299AC9ED81054FE452D3F63991DA42D5680EEF749C02FCBA78DB5F4F7C734C6B4D99AF79711A0BAB723C24364AC85700242878CCA93465F286D5F7ADAD7F68F1D38CD6C6E0575A36F1E5521E420D348D947E745C2355FB5FB0F12DC6FB5E9435CF8E552C174A617151AF8D5E7D469AD5CD741E16EB88EA6D7C5806B08571697D22A525C2E30DFF608C921B955D2A990D9466829385DE0A81875BE564942AE740D15AC0AF46A876426EBBE481738BE19BE06F174D975AE8DFB52A94AF9A77E56267C0BB62169165ACE155041406CAF507146A02FB760629CC4C0E7D29108CB7C779455A3EF359BB6198AC75E16148998C16C9410DFF2DAE5F3C79DA61D371992D4A151BA91DAE8814C81EEA4F78D23871326BAFAA349C8EB57231B590F1AC13F599DF5B39DF36455F05E53CDC4D025410E8F8F8BB74854FEFE0C4F790F58434309D36C1E7F3935D4F896368C91AF95EC2DF292AE3166B83976ABD95089B05B461D4E9171CBB4747F3CD9BAB04E5A3B98095754021229B4B820EBDE63E463F2EE479FBFD83CACC61878773B129CD4B3E9AFBAEDB27C7FEDEC2F2D405B99933FE2C203D9949C567A7752AEF8A7788D2375900E70315823DACCD4F2A674196835C35EF813826B310346ABB16B0145CD70FD0A04611ED5AD0B8DDFCA6EBA6B93445038C3DD23D3D15E8899F9C889AF417E5662D538E466447E514A8897C21FE0BE2EF18948B66EB04051C0BC961FA485422A66D649DFA86D4B3DD504A89919A9928EF96FD467713DCCC1F19EE69CE3935F0416D9C5752B7DCF9272D2DB86C3EB6F4897D94DDBEF7C483FCC66232E535A8B0A5AA4BD443493FE539A32D433D9E89F7758DB5B0606A96455B39F92AA788FBBE43CEC8F1D36FEA3ADFD0353EA5532B49A7286381D985E018E6534005F605BF67AB4AAAFDCC499AC0882FCD9D90BD88053CFDADAF466E536F2FFA7F18B3DC254E42FFFC777E0339181473E2B7FC844B687ECCC0EB543A54211084B1EC06B0D9EB0A0C96B88D6585F414873C13EF7002AF2D47D5859A23D12A7D401FFD4BCF642DB96C70FDAD0CB03A6098437795BC9C7C6C804A26225EAA53F52747F01DB4E62471A21DBC1DED9C4DE2508812AB11F61F6364FCFEED445FFBA549E45E641A80FB4B58EE20677C7D6CF0526DBF4E26D9E5AFAC5429B4474DFFE709D09D766542D65E668D59C836BDFD0F78B846BC412F29DA00291871D94BB5E6557D833C8DB3D9BEB37888C3A70684ADC6B063FEC3D847C42E0CE20E05482DB165FFAC5D1F2C661B9DB6D19FB3E8909587351B25F2C225CB26BB137BC52D04AD8157F7D634F29A3623B4EB53B4EF9A78945280BCA8C5E1882FAE373EAC69EA366E2F13A9FEA75A6B7EB5CD4D9EB14F68A231BAC780F84200146CE7795282952382E2393F0C2A99DE830D3AA517DAC4AC97F2AAD3F7F8E3B49B22B078E3708C9CDD1B2A2A129656066C0030D747EDD646384611D4ECCC5B0B9DF4852AF7BFA94F6DD7584F6285CA2EA7ED3F8DECB534E6D31D7165C609FD9AD235F5AF8E4E8E58FD3D248D822C202 +pk = 219F8358D472AFE3F946D59C629A307D35E185D22CAAAC4A5CAD3156E26D125B697D9EACCA351D74AFE9AD4A2D8AE0F93D5246FD277F4E02818E06FF4637D4360190EDC89CBD0E1A8F2EEA159682518AFD840E4DB55295B66A9F524A43314FB00D8909EF405E49DC6608F0842EF2F9BD713F6FAB5F8FA6FAA14994F960C510AF3719AAB7A8579DC52A53890909FE2A99FBAC9425B08A1D20F20D88E0F80E9E44BFB112CA88925EA8A5C35A4F036B1E184A123300B43E35E2043A5B5A3ED29C76D827466AD430AFC633123F5C737B4015498A13BCD3C4277886186288E58691C3898E68AB1AA2B96E8C21456E6D980BFD8B89A4306069C228A99732CCBF22FACAD99CDB40C9048DB433DA12B274A5F2B277EB587142D9D4940F4364FD04863C65C8E81739FD72CCBF227F94B9AD2DA431126FEA0119EC9CF82F29C9B73913121C2293E9B0C06015155EB8AF1E2D60F0F9050610BF388E98D4BB87A9CE3DF390B7792E76800F324BCB30E8412243AB91B854030219B607939B2D178D71DCFB84A812ED4BC358508E45720009207A98BC36A8BF0BB2B8C2EDE308BA9FB3251E9B13F334EA6AA894B9E4B397A939B8CB2E2A0FA5141294AA68BE63627FC6BA75FD7A8EAD1B65788F41A20F9F1B6BEFD1F931A17D680B203990ACB8CEF2EBF5319F3A7E9EC51846A80351430F83BBC3C63985CBE0524FEF109F1D194660A4121EC0EE401C00F7C967177D25D66BD4D35F587721B047E0F60D2D9FF27CD0FF1C0B83920FA6FCFFA1E4F2A1846D748A924D6A640A9B33436CE4C0CA15BA8AC49BA4F262667861E8A1AEA87BEB0D7ED705196DE4914EB834E91323C78C4A8067D11DC6FFBBEEB700BDC0F65012B6BDE87CA923D1434719115A83A26B9168F91496C8D29990E4661B92E589B021FD78F9F36B78E1BDEA7343E56AA8650C4BEC75949B1526686ED35FD706E3A486E18179582294BE9792E11AE3E230D2820BADB1E89E2A53A0922AF993E4A44D3C52A6E5753EFFFA4C23AA03C59CC4D026DBA7B11C1A0BBEBCA459CBEAB54E4469C48418F80F028F65D4F26D50D154DB0771FAC953AA1D462478DD65F6725E38752316C88811FDB1D1DFA4386543F21781D89165FBA1924811414670C40022F849B0C5DC77D999C9CA8D9B1FE246A02A0898C1D03111F947BB2606059D4EE693C2E993A4AD5315E3FA6F6E08876C2046B3E62A164CAC669A94B5C2B3D7CBCF153605E139D60D302A2B69651A628296D4D93457A13128586243C69472ACF8D172AD2C35C683AAED279851540EEB2DA02D3F942AA00A71C9E8DB9382DBEE6019BC58286C8007F203277637ED41BC7CB5B6DD2514B8A332C8F582C8DBCD25B8A58B4BF3401987B85543D2F24A14AECA7D2699430392C6614F2E7B58FB749ABAA4D0279C14136A96820096E277F45ADC2A6BEC470AA96EF7D1E17FF0CAF5C68436AE1B125FBD56CC5B03FAED1D14AAAF003A15086E7160E5D2AD321618421D58E4379E84CAB9A348AD60B7B646EBC0652FE98E3A6AB73BCC7C703E18FF774D8B62F0A06E3BAD598634BEE3CDF0C52AB61A4C8B2506DAD6425A975B4815D3300060AC5FEEDCC4AA5C752641804A471610D26EBB3EDF26455B97C1643B482C7168B80345ADFC09A8FAB419F5B35D5AA99D7C7BF8ABF1AB1DDF487A38BAB1ECFAD5CA5F052A486A470EFF572BBFCBECDBC5B4B18B2004FBB4BBD3BC852EEFF5F65B0157708B944572A43136F1E7CA5F2EB549103FF785753F162B143D397D09EDC56A06D8736C17FC536B4CC04E7B081A45195D5558856F7741AFAF38B05163A3B67451711716350682E3EC5ADE7B2638020BD2AC308A62090D502A75BD3A618EE997E8A1D4700CA8E8A40A5BD560256ECC2EFDEC115EC1A8815241E736B0730F16934B7858FD3381C413DC1B09966B66EBB21471F3F05F926F92B010215C9A740A84BE81423C16D89D668D4A76A0A6E24F48693C3D3B7D69A3E80BD465BCF76C77302EC70B80F032D5158E009DCDAAF7AB0FBADC9D352EB78E66E71A0B8320384178BBBB45C4C8876E017330FCD0E78501DD6396A41B60B74A6FA87B9DCBDA0701843F9D021D523477AFE27DA58D04D537BEACF6ACCE2727966F39CB3C1471F43A088A7AAAEC41E4BC9F98E075AF19C48957AE1C81F4E07BEE34896B9772BFD237543540A71C01870FBC79E850E1A7C761AE4C2B5B531F2A810AB1CE5480C11CF136873E0FAE923F3EFE195A48D31E4C1E85E23261712D77F3458C9E88175E70025CD91625B6E69B7D6D9C51FDE3A0289EB185625876CAF0FECAF665F53A8C40741E06C579E8CCDB01E7A973023BA4D91277A3681B3F76ECDDA65394B50C1AFBA98C2648D086CF0B745AD3A2D3CE8E09BCF7C1801A6C21484BB8ECBBED034F588BBB57D9005C4DDACEFC01FC4F2043B1AE3AAD3D8FF4E46AE82F87504A3B4D801A8876FBD348328562B6996C1AD0C177A5EA0D4B2EF0145CA6BC30E6208482E0A8C19B1DFB3249C17B51FA9EBD41F4E7006252706FABF2DB9464C27F2149A17A792A5FD3A89EFD7D620F9BE093087AE3EB5B90916C363D22874F9D8FBCE098DDAAC051FAFEC4F546248E1DFA5197C5215D99063EF67A29CC5062E9587CD111C41623811D47169AF6902855B7168E920691DE3A38CCFC117FBC2D29794EEC9C0437F8A38D4D74D972F20C00CB9CAE94BAC8FC80E56A7135FD214A639F60F49C35157A607D32AA430C5CC1D0382C3FB9E71C40D17296985B949CF22A +sk = 219F8358D472AFE3F946D59C629A307D35E185D22CAAAC4A5CAD3156E26D125B8B5B136C72122F4A83E989DA227517490691BFD7155B6AF1244C0349B04F1FF3EB998D596023A432468EACF86737D22EF617369C2C8A796D96082B9DCD6C6952A39A99C21E35583CA2D50E93B97B8DD52C08B8F9C92D155E18080DB96994AA2250406113515063362040713320736670384454081787165188706513414430282056765235848477500124682651610302256246364035308522116822846340123274480708481651285051484036502426378247615151042882556274234642836473325300717324310756101518020217375653414850616242401636424034182437426178442682846655038310837036563582063358058433823747034468804388213532855607604415776286671871416128436304128484456471186164366136258226751226287532745805246274735702122016703274548244578867071485456013670482637888757216816701011356015503573770237655108103863730765174523876011068277617072524521760064344645820186048333217072584564702683377206422814025753113876068377610382522563143616285601520070158643644070776832110606327276448505888248081654830381632423137510878563538821214488103560621321260820120331467036817816201400752372715561556748237514861631442213222550554084543817805710353448748537471550427158574472807548756428782630458466563646158436832777332736270303624254622253882245645025454327732762163825800688636301250701373385313753757778124232074412571461671884563418841178152236653856748513275061575417788348271187578550386760101565486024315506785580566010366826230613886134676518560646631886638378861885173374161716753544460012880413384854813338515012043578647816415053187012327614353410276568128000540753725853280163176048015211512472433162404461427054356267166522242827617654406002731215647148870081446124002864565635370171885854436658232238408208311222412764360113406760558727407734512565318401070083708863331258704536418821232333452301661341105212855682543148815440486760738331623646003181028454641470380772165445287824380553553588135275503663140720546466221123420217300537236244830803557256557704723345588405634065472340421462763306875762181037558235605568108421632025530733700650726155041526752510633481525586018652151460374487750584744688828144563310731726584071063834031135382476230578533512650748320511412773768252531865576482423306477600016107872883100754773401520726386560484351151208850634014583453686080451117088484805586401211025545473342576144618510887865804277585174530537502472232764138216802431702381700101686044467081207418003068680018481078450458883326464876452388481483701183087832761244524881503228673163203680861567201040315844360061331881608531587550068674545885768086644123728648827070742142233384055652661321482427346785684176714067138013858744053875076775874635138643500010026281103735871526314238366121483312302888833385332686464454031000503438464852080550561138885405415318807055106786568818474324502386083760541346247203578112550615062604070812300602642462665445037035703375332758378310320687475307464401263483371801475288055061763233215073531434658157452308048078265714028658100624342181288740076786838524815102853781130167217357852681331833255466721825048761301686173368655683512024214225547402613533527718BFBA3290C3D932E815E89691FD8B2500BE905B838F399746352A2E823DA92D977F800671527A5C6E0B2A7E9583A5C9938365CBACC6BC8950FAC7387C149924F4C5E700D155491E6349B6C47A1A4DCD98C6083D674791C07658DC4A2927B3FA6ADCE2DAC8D03D9A8012BF243051FAFFB80EBDD9D8A6E26E3F8DAE4CC403C0D381F87504FE4E6340ED7892C3319EEE4F338FE0E51ED043EFC4954B075258797102B2978EC38BBEC85DEBFD7A7984CC8E23B3FBEE9469FE669D71FAB5E8F3C9D0402DAAED98B89D98DD65AEF707DA51202A8356F111B9C5353AA4D294D4713CD9F34D5E1B27AB95663FBE65D47367C54EDFAD396B74437B3B1CF2E77437FB4769575CCAC02935EFF04080D342F6E066400560F37BB4CCEBB224AD55112E89BCC9B4300CC57C147D1507E92EFCBA8584D1AFEDDDC2099C864F8D172B518B34C551EECEACEA2293439FEFCDDC4F58C50A54DECD6B947E2308DB53DE800507488A235FD1D932A57A6B96BD254ABB92266A546DCCBA174E829EB5C8E46D572913E5B8450DFA63EDF103F442CBF09B7E0B6A99AEDD2932A410EE21974AEBF6B92E99AF3944F93FAD2E44CA23790D809568431C6E2E6A07D15F555D33A8C1DEDF58D43F197BE2E6C8B8DE95E359A04AD7AC7890B5E610A74B0F5393327E1E21185709AD38081ED5A742C80F72F7C8E61C24B927384E39D0E8933808D8F5C135482B56D57868F0C9B4448B8DE699E4E90381C2889F146290FE533CC65C3015C349375B26BFD3611EA42436847A69FA09978E0421425A111529FC624E0A89BE6CC5F4554CC3AF6337CDD0541ABBE564CBD4239F72C9896D09626E12094B8C581831CFB801D56947A4F34AF0F19A73208781D031BB8220072F59815B7ADBC95D3961A6D9C8236AACDD68C026CAA20F0BE928484FA3459546D6A7E31C0ECE1253E3CD8558259F805E24FE752632F8E433B89C1AC504EA770C933F82C630FA5D62A983B01E7EB0060C462D60B7344722CB1C2B65B4F8C1D54B1B564CC734859DB66A0B24DBA20A0F984683101A46120CF0525B5C7926E19845DA535139A8ECFAF481036AE5E26125E6570D87D315EBAC08DE053E6BA08920B792FB3491ECC7BBD29ECD71F39A0BE27879BCCB21DD809475FBE68EA023E5D701C12491E33BEC442C0963EE0711A6CE2955BDBF18AC5AD44AB1B4AEEFD2EC3CD1D0083E98BD200C4E93ED295D0CA582F87AA53018B524D331F49F9EFB46B4012B039165440FFB370970BE4C2185BCE65FA00DD43C52E8D314CCB3B4848A7726F44C27D9792EC35C28CEBBA3446863C38824F4E53551044B1EFF8270529E938653C04B34E1485821473B0D87B0C758AAE338098099616A66A070DE5777690E1508041666378B87A9619AC170E77CB3A5C7DA1C3BD72F6E4384E5E4EFB2BD8598B1B8A5657EB8469B0611444E1AEEE789386A23A33BCC618EF217B7E41D755BDE4DFAE42622ACC6B30AC856160931C34B5C0C68B8B5EA42EB13ECCF5DA5C826A56A1B4615AF0CE0742FE3ACA2D4A35EF7C2F5C1CAA32F5A1633D74697CCCBD7B5BCFD9FB06D3528FE3352713D765FF7823A8CC666B21B22116868A33A0FF31B1E14175C1A1BD80A60807C835A871C4F01DE7FBED3B6F83F1021C965DE2BEE0E375017E748094968D2BF20405E3D210B9C07A99159F934463786D8784193B9F061D1164B5EB270C229AEEC5B04A88A5EB4E82C14086DB419C3D754D13248AC62A156390B69122BA060D6BA7D6C0782FD47EDBA0ECA4C7BB6EB76DB54B415661C446DBF8AE3149A5AB5ACAC2974CDBBC034FEEE746A8BFB1AA6176323C24E9DBE8E519B11EEACC4CE4790DFB86CA94F9364C0015BC596F39D9D52EC6BF6CD849F75A5BC0A94AF4A0548A4516BBBED21A884B4F0624B967F258CBE6A4C8A975CB3B43F9B5B12267D4EBA3CF8079DBAB174DE24C37FC49DB40C3AC86DF7955092B54EFFAA874BE8AD7372DE5167DAA6CD53F43142D5C6CA82392AD9B9C515F6CDF345B635898F1521501550F872B89B80C23B74FEA9A1BDC853EA61620FF4C4A43D1B8D205B96C7002CB0D927747F24F0C4832897BD61BBDBFEB8840DB5C82DEE59ECC12866CD36FB8175177005A000D39E8CF0D0A329C0F02372948F2FFA58570E63EA7F47E29CA98AA890167142A98475EFA56CBBCC85D5B0E409FE3AA8CE06B7A0F735CE647160B8D7D21CE04C4444A1BA1C28660FB4C71DE36A32DFFB52582F474DC980E634A577DA881E0C10214F31AC9CCA4B3EDF6CC4477CAD8C80EDFCBFBB7A6E4EF74662A5AE565B6F6DC0F0F8D9DE5EC75DF140BB0C2BC0A99A4CF025053270D1DE9F7D8A611CA9D51F9480FDC881DB7D2B21738832BC0DB5C0850FC59D70E8D15932E22195D98B52F39AFF6290BD120F9D490A8B9FD45B63588ACD5BD4D5A18960438629CC8B14BAF45FB1623A8495EEBFE46229E885C768CF7CDF228207582525C981A688B5B036FCFA51EE6B94738452D26836B6A8915BAFACB51AF305A870132B6C5460D446CFC61E00F1E6F22A45A772DFC2D2088A09DD1DF3B5DABEAEDE35BBE33E2241A92A6B6407E1AD447AD3B8458D654D621D7A4277CBDF53681BAD5C5296D92C448025FD22A9764BC599B7C3C9434A683989AB0DCD0CB43C59DBD59589B617B6669DB010C659208D19EA54D5D62C566CBEDF66CE4DFF6C0876D5F6820422DF6F01363257AC6F151F50ED9C6A2CB0CF0683DF46074FC0D418D7C2F7AD1DEE481906A4A2987727587D226649CDF51B665F941F1079FEBA75304163BD1AFBF59690236274BA571ED20B3EE40AE17AB62D38FAD1355D3BBD27152472EA3F7A5CD33CEAE8E2BFBF070F990391004C92CB1D4E4C8E2AB81566E68FA4B9669EE85EF4C41E37271F55712A5208D9804FF8F01A057C9CCD7875C5E50E90AD3AB0425EA966EBD48EB5B1501967CB53A4C00AB46088F9B8F201DCB7B79FD1563796927235DE5C8011819FC82A2702E967970D14AD7493ABAB788AB9278E4EDDC15461FC4AF83481C6985C58A019B296772F936D006A18851AD01958B0150219A3FB37E3BCC49320A31936BF433718939DCDF140C69EB977D63FD11A76CE6CFC248B1F960F79E8091CFB735969F30A111C06B187F71E7B2F368E918C486CF0CA1274288ECCDA629B93B2B815FEC2BA92BC87E15F2478107AD89BEB68F7F4C03D65FF66658BACCBD92677793C1DAC05B9DD65EA633522FC8145D70EB40FF9A9A02097ABB6D791A77FFB62BB38FF2197DC7BC692CAA2E641E1FB867D6E8E1B61B22B8C363B1F87EB669F51C49E3F1D73A93F63665893BE215CACB92B0CE51C00618BB0723433740A3435591828910545037350CF89432DF7CC0D9FA1BE7A7D795516C84CB35CCE9642EFB7027113F8D1C2AB8E5CA49530E0D0D5756B0356374E39C0B54358DF64BE1512E50979E7CDFC9064F0F8C450E9FE359562B0578F7A3D3A5102D442F9372D09702A7195169A00EC3468534088E2910EEC969684BE4B5337FC5DE6910826C0E9D5687F0284 +smlen = 4959 +sm = 9DCF1486F3EB99445F5F88B823B03B3E35216030DBE8BF8DBAB8DE5FDBD61ADBD8AD6AD2307516B0857897B936AF4364203FDA7667AF2FD080808FCE4FBB702E5F1BED8287BE9317F05266E1775459E8307B3AE537D775896139E4F44615C37A8A39A14E978334CD729E49FE4D388A3B3E12062DE666D0B640F1650CEC1551C6FF1B6C93DCE6774BD40EFA99A06E2BE89C6F46FB41F5B5C55CBFACEB540342E86843F536A919EEC64B9D04F146576C29795C0228A5423BE5D035457A6115F976259816054975BABD233CD938DF0C4EA8E5E7389084BEA518AB3E1625D8D034D36BAE1826357DC4DFF743F570BE891FF82FF23C180644BB0939D424805E5C4F8BEB2D382562A887BDAA8066FA1BFA81A191F488805596DF2308158BAB6D2B02481D2E31CF3566C51F87E9F968030CDE5A2C5CF22348863125DF420FB9555A92069FAF17E58168DCBEA168A5F030EFA97C80FB0B4EDAC9FEA5F08BB3CE6816F400B44C607FE7D9152EA164D2EA00FC3FB524BAC47F714B565899C77A9D83DDA10814A0B60C5764B736CD486A4979A01341494BBC305240D916CE52C3F8B7A9A8F5A841BA8F007B4B8CA3D83F5CAE0D87DA5DFC2638EAC53F66BE1D8750016A49ACCF9D61ED241EDE6AA7FD132F94E6B31BB6F7AA9318299B799D72DFD51CDD99535A653AB5960BE5DF029259293667E746CDDF5D3A25CE9316A6F1C4FF9B7EA92AE38879108B711BD06B98528BFC91518D73905F48EBF73464B2524C6BEBDF58ED3724F255FC4888CF71A6F726B9481A7DA2ED0ECF442F54FD266AB790C63C13DFFFED23E343435A6E2A385DDEEADC41310D46CB375424BCFDCEB5FAC65F48F05CC7737FCB1F35933744C875A99EA21C99AD17DD3E7A996936D52E0ABC6F057C5A93EED0C59451532619DD9D0973AA936621E82FD6BEE4A025E82FA7B24F3F32033EE295C71B47B50817062B9EDF178261ED16BEBAB675918CAE1C1195EEA33B42DFE84B8A57EC3A6AA7092ABCE45B74BAF77D36AE591B210BD143B4B72365FCF13ED6FEAFABC453A0BCD546CB60BEFAA24D7037E8FA6B81B08D79D032B44E8B1A10A70CF6F04FC0C1A1B080163E6252B4277FA9A1C505CB4D40180D1B5EBA49F293ECCFA861E2D12C4A57D86F38C7DDBB3AC3D422598DBE3B34B249BC435C08F4B7E61D0D29636408960C342F7EC95C59EFEF44FDA0374E1C6335B74979DE19B5F140B4580B9F5447D2C9026C4A9D65506475EDF6A5AC41CF913B00057B9AB55A3F514A03CDA7F95B54AC07CF87E4BCDF5F66B7809886E4AC3788419CF9FB44314EEF4C4686F4E9D056773C46E572B3B98B11EA1D7C80DF3BAD1A05EB21BAF6BBE4129DD89829E5B5CE4CB95026731D898EB824801496A75E2A26CB80DED0B835B06321B6C4D16D9ABC0A66B22DC92B6AC492662728BE3063E5133AB5F1D3003B1E6578B37F7353703543DBE51DBFA132A32EE698872DD3AC7D2753EDF3C55F7C81F29F35D709AD2B0799E4CDED4CE39CC21F66EB2C0DF3D81C43C502D4A7B26986DF07C3BE93BAF445246CECA196B440F050D73ADF2695435C83F616A188EAD1A1F9BEF60C4434D941ABC5C035A810F352A55D521D98A2D72DA2A61A052DFEFA197B1A3DDB7410AFA9491276DCC43DEB43B1B5B9AF1A9853ACA5E22C4645C2AAA3023D90422CE79D928C90CA098E2B05C49D36CA3D60F29CACC55D62942B120715E676997CA4E46005337FBD2B70046CC84C5BD7E92170F2A5DAA8ADA06AC5E5DF483CFBF37DB0C2265517F8889C14C27E1E053EAE0875790404C5B2FC4D8DF6872A25BB386A121AF0FE025C676B90147DD0554A7C076184185696041B45A8B451527214BABC2A7A2628D3969C8044FCE76B6B08E8B67AA08FC1BA5A49E8631C8CC3C7F23833188EE104F252AC582512EF8D66C9CFB6ACC0A0BF396372E7834AFD70ED816425128FBF4BD3265D74A13CF398729FBDEFE42596C3FED810375CD46C573B12D9EFDC2F6E765902962C367D61CCE46543EA79A9FBE3767F2CA72D7C3C0F79C5C8619525C9868817E6033E09D17BCF87FEB37AF59932AA6ABB722643E0B0FE5459753CDBEAC377A40182402A4D3DCFB1907D8311AD6F6C18E430707B2A6EF601F56E981570FA97DDD7651CF86A92C3795E853D8ACBC1D6E20F82C64506B4427B716F70CB02054179721F12A6BD5C8C177AB4FFAF6726DF6F7C2C5999AD1FBA1D578910BE3D35C238A61E0E1784A4F9F94902AB96826A78CC925C5B1CC2566F5E163F6A9B2863C5F7DD96BA58E41C5333784CB39512628191493074DDD8D0FA84F320CAF2D993DC596945F63B1ABE4D573989BD185C7C07DF6FA698C7C29DCA9E36F2BFACD73DD82A9DBF6738467C842CC1E8DAEFF72BD0EE875C3D3A1137D4E876E81333A2DA6347C809C5F7B00871ABCA99EB0979CD0C3DA512C80FB8DE0D8869C2F0D24C7ABEA90535C78AF14AD3299E59D718BCF1B6EAA1BDDD9B3987E1D5F413DC74E2466C7C5F53323B791D6A0E73430687CA6AF72BA756C85920F1F5097F3326B7AAD1426A657466744E755671961FECD97698F1F270F4930A6FC323CA594647DBD72F24504710EB04EE436FEB1A85FDA47350C7EB91AFC206CEBD53CFDAB42299571DC4365DBB1BD1A815834E1CE0708983789BED504A9A506F7E11330139E2C957AD04E9F22C8460AF1C9ED80ACB4FD4735C2B6ADAA638D8C807B23790B2FD1D5D3C5295D9EC624322FEB451047B19A54AB1FEA9B758F1EF08A81CF6337EA746DE314D6FE9E94A598600D281755348ED0B81126172F6EE2B1EF448F7923CF0E543034B86FDA3E3E2AA753C8189EEE0AEC7A0E7D498EA07B467B15ACFBF0226926F5FE98A23450E814E8038C227C932696D1F7F8D25F580BD914488CF545E7043D3FFBDEE931EE0B64E90CD06CCBD7EC764A5727060D77809D7256BA2D110EE416C072A65D4116BE2901A123C5B4A53D11712D8CF4EEE21B40585A07F06B87BA176EDE38F73C2BCFA884FE2C44C239827541A654EE3BC990558CA9F9F64C2A4DE413A491F01EA900BBA1EAE1893DA5D818C7F7543C7A8983A12CB0858E080BFCD8E349C2AA5FA8B2D2ADA4F9B7B1906BAF3E761154E2C8EB6169B60FFAD1563F7B7B6ACD9EF56F27F85896C7F3D2E4BC47318C6FBB9F51DA39C18BEC3B2773E8451DEFCB8E74F6277B464D0A06DDE096FBA6D186CD749377814BB68713485B39ADEA8A7E8138E427FA2C260160DDB969F623EC832909E0EEB3DCE76C596C35F1CB642CD14A97CE39D355EE23679AE4F5A924D9B10F1396913B47FC9397765E5942940D300C5C67B4B5104E31AF9A8057A2F83C9BD515BD92E9A7CD78F24F8CCFA17C0D0FEC1C8CA47EB090E9BBDFE59C0E49A368AC0D49483166884843B57AD52A8A13D28160A5642008B3F1C1419FC5EBB237DA1D00220222CC579AC699E6E25D504FF444269F5A2943932AF7E2F3F8FD2DC4C4F131C234189250DC319EA437915E005276FCC5E20CDE0372103789CF5A1C2C1B45F59A57D954D545035E03B96C2A05480B2B83D3A454EABAE313B11D74F31A3CF2EE83AD2EC487851D506D94997455BAC31F09A642F81B895175EB34C51F30A999AA78F38FDFAE031BD04365475BB9E1DBA56887B99174328DD7DF1BC820B5D4EB88E9354405598B9FD0DDB87B2F24C1E3F76F60C01D38875EDEB420EFE288454BEE1BD46562119ACC45DAECDE7335BE0C554F242D7784D73F75B255BA517931E6839D7C74AACCD99E0C06BE2382C2CFE89D3E4C465E9BA53271143CC027325BC1678E4C63B84C2563927CC8981ABC780BE4F1A41C50573DD2A3886457FAC9032C206F2053B675E9545BF4450EA1462CC102916FE48927569DD9800EB7D4A87A1F3352FB044727D6C7D887E1DE77864D1A72BD3A02CE4EA55F0CAD0BE632BFBC1949246655ABFDC27BF815192613479DC60415C9A96E797A787A1AE0BD47764F837FE820748DCBE594B77C0E13038E89221EDDE51920232A03AD137AFAC7EA55EB4F4FE2F19D031137FA8B54E6741CCF50D6E90BF950B127B6F9D05B633629AD4AF397739305FC97736832E7F6A6BCC77D1830A246B1391580FB69948DC8D7DFAD6AAA435AF19CE9DD142DFC5DCB09A19C3ED541B0CF6B1BAF913EEADA9C0B44782F0A21524AF186A013BE54226022B4A5313505C936D7939609A2C40898E74781C1933127B7724E6DB4465C7BF0C439C789F84573D43ECD061AB2264A4DF7C08132AE92D1B6FF314D2E7960F28DAE0C1F7DFF2E5A4FDD76DA371D85EF00D874B923A3F69F40DA8B6B3CA14459CE8641FF5E72CF358B08FEF2E53691F0E3D7471B3B6A5E72928F483D1E27FCB1BD279200D2402B499961DBD8A5352F27EEEC67A8DC99D3DA51F519CCF068BC7BFEED4DF55BE775A149BC7434BAE31B3BEBDA5EBAB0F5443FC091193BB0E6CA0094BF9DEB186AA2DF972BEEC27F85AE7D19FC865BCFD71629C220D34668B559C5F955E67DD39A4F1A57D564DFA9CD15F41DDB387744AB6043D1C83A48734B3A7CB730AD4B2A5F99018AE31BEBB5E26DEA25BF9784CD245F1A333340415BFA1256650E59B2D8469A1879843696CC1D418285AA3C7D1DBDCDDF5F603426F749BC0151E43494F6F8DAAB1DA0C1663D8DA00000000000000000000000000000000020712182227D868EC985F946F3C31B6CFE4811BA530EACD0ED061EC383C203B2481AC697B8B88BC0F72B635027E443AB1F54478440DE16E596D30A0F1252E0AF54C0F382BBF5655BEA8C6B9A2F6382D003CC7E4D4F223F8E35EC87CC543EAD52E0E1ED956CFB32E8075715C07CA4817C4B8DACE68C8B0DA459271746BE41D6102B3FA5E49AEE8D443E78AD3246D0B9BCCF6AB7CB7CF72B8A847CA16B435F0618594400037179441F3BF524231F747D920E86506E84C61D4D038D42E82D52D97ABFF896C1DB1C646807156324F7B68DB620EE435C7B8C9AC8B193B7C892565C3631E297495BD3B59293F9A9CEA5E29E23A242B81DD05C8DC9DD669424573298C85870B109C7B593BF864B56895D81386466CA5CB6071005781FB214F1EAE9672D0D16351A627A3FAAC49BE4E13D552340328323CDCB4703BBE07C2A39D75D7737D5C1BD04355B8694432DFB7CB4F1901550C7D6F41080C0F6A2CC49D63A69243D137A78260C06E7A53AAF4F4B086E0220EBC5361A6A78C9B2EC09C2EA4EC45A41065B4B2DAA866D9BABD71C8E6CB378595F068EDB258B2AD1F420B304E5924EBE273AD6D00684F75B6A31DC5290A37D0F9A848B1FC4A67DD9A4FB1F9B4C6CD45E87FAB4A09129C9AB95C44703B75B54C9EF9E825928ACA56527D79B338C5AC639D0265010F3C085D2B09AEF0E4F55D080FB5FF79F13E8E4E8DB020F4C095140D46A93F2E4811BFBC1393EC24F6B7EF31F13623DF0360B1E335FC42098CA1EFCD0306C5FECCE942F6E299AC9ED81054FE452D3F63991DA42D5680EEF749C02FCBA78DB5F4F7C734C6B4D99AF79711A0BAB723C24364AC85700242878CCA93465F286D5F7ADAD7F68F1D38CD6C6E0575A36F1E5521E420D348D947E745C2355FB5FB0F12DC6FB5E9435CF8E552C174A617151AF8D5E7D469AD5CD741E16EB88EA6D7C5806B08571697D22A525C2E30DFF608C921B955D2A990D9466829385DE0A81875BE564942AE740D15AC0AF46A876426EBBE481738BE19BE06F174D975AE8DFB52A94AF9A77E56267C0BB62169165ACE155041406CAF507146A02FB760629CC4C0E7D29108CB7C779455A3EF359BB6198AC75E16148998C16C9410DFF2DAE5F3C79DA61D371992D4A151BA91DAE8814C81EEA4F78D23871326BAFAA349C8EB57231B590F1AC13F599DF5B39DF36455F05E53CDC4D025410E8F8F8BB74854FEFE0C4F790F58434309D36C1E7F3935D4F896368C91AF95EC2DF292AE3166B83976ABD95089B05B461D4E9171CBB4747F3CD9BAB04E5A3B98095754021229B4B820EBDE63E463F2EE479FBFD83CACC61878773B129CD4B3E9AFBAEDB27C7FEDEC2F2D405B99933FE2C203D9949C567A7752AEF8A7788D2375900E70315823DACCD4F2A674196835C35EF813826B310346ABB16B0145CD70FD0A04611ED5AD0B8DDFCA6EBA6B93445038C3DD23D3D15E8899F9C889AF417E5662D538E466447E514A8897C21FE0BE2EF18948B66EB04051C0BC961FA485422A66D649DFA86D4B3DD504A89919A9928EF96FD467713DCCC1F19EE69CE3935F0416D9C5752B7DCF9272D2DB86C3EB6F4897D94DDBEF7C483FCC66232E535A8B0A5AA4BD443493FE539A32D433D9E89F7758DB5B0606A96455B39F92AA788FBBE43CEC8F1D36FEA3ADFD0353EA5532B49A7286381D985E018E6534005F605BF67AB4AAAFDCC499AC0882FCD9D90BD88053CFDADAF466E536F2FFA7F18B3DC254E42FFFC777E0339181473E2B7FC844B687ECCC0EB543A54211084B1EC06B0D9EB0A0C96B88D6585F414873C13EF7002AF2D47D5859A23D12A7D401FFD4BCF642DB96C70FDAD0CB03A6098437795BC9C7C6C804A26225EAA53F52747F01DB4E62471A21DBC1DED9C4DE2508812AB11F61F6364FCFEED445FFBA549E45E641A80FB4B58EE20677C7D6CF0526DBF4E26D9E5AFAC5429B4474DFFE709D09D766542D65E668D59C836BDFD0F78B846BC412F29DA00291871D94BB5E6557D833C8DB3D9BEB37888C3A70684ADC6B063FEC3D847C42E0CE20E05482DB165FFAC5D1F2C661B9DB6D19FB3E8909587351B25F2C225CB26BB137BC52D04AD8157F7D634F29A3623B4EB53B4EF9A78945280BCA8C5E1882FAE373EAC69EA366E2F13A9FEA75A6B7EB5CD4D9EB14F68A231BAC780F84200146CE7795282952382E2393F0C2A99DE830D3AA517DAC4AC97F2AAD3F7F8E3B49B22B078E3708C9CDD1B2A2A129656066C0030D747EDD646384611D4ECCC5B0B9DF4852AF7BFA94F6DD7584F6285CA2EA7ED3F8DECB534E6D31D7165C609FD9AD235F5AF8E4E8E58FD3D248D822C202 + +count = 50 +seed = C10427EF0B26328163F85D45E22EC5215415326F013FF31EDD58BD3E97B1A72FF07D275D4C1B517F4661B0638F75640C +mlen = 1683 +msg = 4BEAF8CC3A7C393932CD37A2CD8ED790F05E4038ADF1287E2ACDCC0BED9BDBF92CE44AAE95CAF4EB142B858E1421610EAFC47DE566182835BDACD4C836F19BD686D53C3834EFD928487A2AB3402C2E3AB3AF97AA802B05223CA6927722C3BD1FE3F8C20F93C3951F907314896CD21CB99306FD7E5B6176945C2898B10C1DF62FBB2680752CABC8980B5A0430BE39D34BB7DE9544BCCCBFABAB709C11BFFF5C958C8763D8D5830235B49EAD26C834E63C3F3F2D6BA944FD2688F6350EC99DAF4CCCC42C6BE1CB19DD46514D71CB6E887DBA80EDB580B27F1142A20EA0D497E0336D55F1FFD4BB3D4B3521F0A01C7BB09258971D1ED4A98EC052B24776623D7B9A83C818795E3989EAEBA8C9142A97AFCE855CC6AC0ABA15F0546684AB5C2F48B23BB72A88B6AF2BA9C73881103CB6FA99E3B03119EAB03BC3B9BC365EFCD7B9F49A8BAB6A34A00AA8F2C88D7BEBBA808BD97111EBB192D82AD244E18BCA732FE6F72FDE5BD533E4BCCD3F50332DAD3A4169EA85C324D165413F10888AC3B21B91DE09FCBB9B636ED00FAAA669ABF6429B78C3C04F239722F31FB0B1A20CB1A6B553908070AC13521DF66772A6036E6695CF66B9A90E2111E499BCBF5DCD19744F43DEB943445248A5E84F168E7BFEA2DC4E1D0A87FB4140EB7C72D2DFCC27923206054CEC870888A79938DACBAACF1F122B22AB5C9701D777BCF9809CEBC9B7AAC52468134FC4A92C2BAA9B8C0F6249130A50337F460A42CB5364A5E7408CAEF8D12BA6934AB645DE9832818F9DB71F5EB0B158DE6A76619E75245B56020E1664D8FAF1C1782DE4A688D4055E07D842410600E9454E28676D44357853FFA7740200C91EAFA16BCA21D0006F47FE8159A733E0E91549DF434EF316E1DF9BB97DA6A2C2E2F20A65B3C00041A903270CBB55AE2432AEE25C71CE73BC2322CCB8E5BD0E24820616A890B0851D825D79411C14948DCDF48776D72565422056FE75765E50736C82F71270BBCF229A7B7A45DC88AADF4F84238C896DAB889E16C17DB7BE551AB24873FDA82F102D0FCFC139C9FEBE9FA99819CEF0E2684DFC5C843A6D496D8A595D33C51E1FDE9A84059C7BC596D32D53E2FE046F23FEFA51D13F9C28E227F5E24429B851ADDBF578922AEB0C5A61BBB666D11D127BA45C9E6378C70D75643DE776483582E034E81FAE0A3F029C47FB192CFA018CE1F68261D77CFC9E05EF19438E47F3DE9A68C8DC09D07B1BDC6CED69592623750F72EC2FB8C5CA981DFB84B4BF0734377EE9DD8EF5DDCD96F438D30AB78F402EBFF2163D43345EE8CA119F3208E21AA3A2185DE967B475B9ABFBC86465275F9A634FC22015E94A298E9C204E9786CB1FF14A5E99F942D42AB5DF51AD09654083DF0259AA1C26A760CCFDF4A276600C5FD3A54F210B20731941EB48A79435F1F86C45F8181D9758A1835721B87D36C725878375FEBCB8D48ED2CE8892DB50965753A98F4E7110281DB40ED64DD8EB51AB9CE41042589152D8CD5876FF30536F8955172A7A8F5C3F5FFD22C9954903136F781F0574F45F909BDF1657FC1CDCB9C4689F41E462C8D39108B10D78B6892C8775FDEB139258F8130BD1D2A1C72B5026506409F9862AA8729B35C652074494FEB84A553CEFBEED19D6EE94758E800F5FCBCAEC19B6A00F33EB237AAA6FC0B3A08C1D8829C180BF95E7D05F919A929933B7A032CD20ACE82AA5A45E5B2FB09812F36974B5EDA1B387FEB13BD49AC374F821341282C8FE2FB0CC5C075356833FF8CC6B648729A4298ECD73BD0EC73957077AC65722D0BE23C1536B8DB7B0506DAE47C0070564E7D7F9444F47B22C679EB8ACA4826F974A42043863E498E5301EA162C4E96684ACC5CA26CCD083541BC4C1D2FD690E51F07FB08337450A204B0F4F2C17785E037424FD6E78746764584D5F19255496DF1E524BFF0AAC31BDE9254429565278A39ECE4627C023EDF18BC21BB523D44EFC259742DEE9FF7159D5F700D957CCBB505A88C2037629402C2A322D17647E430777B184FF7B4E8D6B94724ABC36A5CCFAC08E2479E8310BCB7A617A25FAC6EFD10D0A07248F7D4597F14309B8064FE3BC4A4479F905E832210D49363D1E5D58176DEC9ABCC0C5132FD6ECCEAD2B05B56C96ECBBEB0B803E43DB2F982AD9EFE1E2A49649ED8E42707970C93615D54A3E673559B996E48A3B73143BA0884E918888156CA78F793DFF990FD721DE0C0B7916A5CED736E31292C5AF062D7CCD83FE653294FAC8C50CF6BA37B37D5A9BFD1E3B92D1825C1BE0795F9B257CDAB91CE99C0C51BDFCD6C0AB5A3BC6E30F884ECB4F1F61A3259CD279205B2C21CDDB196360061758E67B1C3724F5CB6311EB4FB92E6C0D71E6D1EA45 +pk = 0AC94C5446F048004FF0E54228BD5FD06F68A22A042853C1867FB251A3CFD0A28D67D42304092A76E35AB41AD300A888491FDEEDDBDF62253D63ADC6BD524219857EA294518F8A07230A8CA47A7596EA1D2789DDAC10F3870196561F5279201C0543782E2B29E3E1A5E08CAD3D49C2C78FBAEF61C1DE6D624A2CB8AEA44C82A3120BF0007F3FCEE2936F0C05CE6D863880E08889D632E0ED9963FE3370043F0FF62BD65D941EC3677EA38E81B8734CE262E9A88BF1D6463AE11FB6D6BB48D5933F7F8E6C006BD3209517E27C4D2C29D576F0B41A0FD3598138ADE0BB3EF31299E1AD2ACC9BED91E27F9590C9994D100D65968048A7FB9FB51A29FBEB3746CBE24B0F3659D2030D4028C257600B9AA9E6AAB9CFB1D745F4C67F3C5510425A81E9DC173EC9B845FFD1685A292FD61A6E920EA21062A25D1EBE4B0C13A4E218241217EF74DF4649051DA5200B7A778CDC1D532F2722C8FC41C5D181506E92BB3053A813C499A58897105E651286AFD20E1A20B957E24F4E656E3F219B8912B32ECABADDF878B0E677F37379A1C86F0ED729063BD8D5D31D81950801230BB8F05D78762B7517DB30A08BBBE9A0D0B98629DF7B2974799C3BD424AE7E038262150D297C75E34A90578624C3BB3531DFD35E1D65C407DFE55FB4C9708ECC1FB420A3837D843415536B67283292013CAE906EAA663FBE7B304103D0F5AF7CF7AF71C2DBD9341947F04A3C5E5DEFE2D371FCEE0380AB688120432CB5FD3506D0613D662855D3423C9FA9E1B1BCD6BB7B55C7D92B112207FCE7CC1DC330F435336C8609C614DF3BB0FF94F0DA59DB46D8197B9879337A438A8089D1EC55B0EE65B98B65CFE64219C7568F34AC0A59508C06200C58E738019298EAAAA42C4797A40FAB35AF48F86DC4D0BCCE85DAD5864CCFBF6C83F7A0E10A38CE33C9D4AD2C170CDC9BB0D3DE473A8AFF616AB05A1D6DC4C26CD6449D8C8A9F372A01047905819508DB7F662B065E4F11CEDC31E9EDCBE1B1FC2B8C75AB22E381B3D5F3559C5A9D60461035C7906EEA44E5708C8E90EE6BA15D5E764DC78EC5C12E0EECDAF791BBC944ECAF8B8F81BA8510F5294D01F816412EACFEAF8AC401344662A3D05425952BE5EF7A600E3D3B80271D8CA59051411B59F22B17C114A05D2E55D3B0C05CD81C22C97ECCCB9EF1716C517A42C410F75F21A180F9F641E6FA48C7B09BE0BF4BCF11F126A1BE2798F93667E68CBD69F8430EA02E0B513750B35710E02CD5C74BA654A600421ABAD04570131212916C1BB279AAC7714DA2C4C677F245BA6A2BDF3ADB04A04B0065DF5F0B27EE4247FEB9B46E6E07D87A9FEE4297EE856C270D2A9C7CFDAA97C76070A169D325C18FFBF41E5AB089160F6404C4B820DF51809F846818314DC3007226A240B4C89FF73551537FC129E69FAB404C56E533261A1A2808AD7172527BB8D34D2944ABCE9751320EBAC56F1CEB7D3DE9AE4D8F6739CB3C47DA6CC34878770ECC2A163CEFC9DB20DB116C4A2E3D7524B0AE11A7C6E545A95D3EEDD1BA39CF41FF97B181E9DD531D76A965928465C2249013B24AE05C5149B3BD82B5EBCF682E5B81EFC8AA5EFD6AEC1F74CA688C3AFFEE7574ECF3D5B2E4E8DA353E429F29411D151327199BA450F4165BFC087D0D36F0D57810DD4758589364FCC805AA5CF0444480ABAD0A3EC5037E3F652FE2A8CFB7C3FA71B5B1D021181D82BD781AB4ECFA4C4B6E2967D389E90D91165164C2FAE5CC3832B6417BED97A1C8DD16B65F063C3A7B509E0BEC6F5DF9D19651B88B13FB8E61A6C06B00CA7D503507287D5F7D278098DB9A613C49200D9490A0F0B6B68ACAAC61D7DC3EE7C98A5DF0D9539448EE976830131AD9C6D2C0C9D3B00DF3AE6198957FBD264B8666426918171953ADA0A452C2F8169C40A38163F87B5C7E3947DDC6DD6C42DE5E95BF29600724E43B10237AB92A7155797E80C66F39785B56A6DAEAE1DA528B54983595B3BE63307B8692B13A292A3D9C5A7BDA55109A8B03444580A695E1BDFEBA9AA649BF3D1D14FC70D9CB26A48F90A4FEAA2B500677A75CE6655D0F124EB8A3CA69F22A023518418E64543BE09FA6BFF4B466F7CCB53004273EE3B79CD633CAF32A9C725B856374DFE780C13CFAB549CBE0CA1EFDF9B60D85E2037682B6F48916F305B545F3E8DAD0F41D398A65303B0C067D214BEB7AF9DC740D9BB52924DC80AEF78FB63C728E2BE6EC1850792A595CFC9361C0D38535BFAC1B9A3D6AF370C5508AA0F8631A3372C826A8338C5A5F75C6EA87DF03BC394AE667A5371BC3D98718A91C248F24338714002A88E48727245DAAE787849E47A1B030697573961F029AA73F57041A372067052D708E2135852950CB66A876DB1F10363760E117FB0AC1CF543414A93190F391C1E855E98066F4F143D5FEFE9AA224D8B9189269A42A19D509CA57D8A370B2F62177A5F11C179DE74A314840CE97B32C420A70E7DA4D306E04B8D37FBD56B3AC4C18F90BDF3D0DBB04E34E318713142BDDB1A4D4278A5221345699884C60C28AE8D8E978F97DB9AD5788E8A45188AF70DCD8A4AF9D623B52FE9F50551E2898B081C0A442B263D5600997066E9C3BDAAE3FD6260F0B1F046053D57E72E797EA0F4CAA3DF52977BE14D3258533919B93131D90FF4050B314E9DB8E6F7B4ADCC00B3715280FB469F9BC343C240B8DA0445000F2B4DAA1B02DC520B87BA8F4AFB6314FCCE66CBC1FEEA6F04871F5B0D7AB924FAD250510CEA0 +sk = 0AC94C5446F048004FF0E54228BD5FD06F68A22A042853C1867FB251A3CFD0A20565A0949753D115370449E228190AE62FFE2FFDA8288F677CAD03B083066E194F278BAE27E3133E08BFC419C9FA77E26DE888CB96C41F895E69C7265700E5607F2661311AAA9E10B198F8B88716B42E42DCCF91B5E33420E28BCA2701749C233757537274046602312178143728073083678362722730228535877354074828605262072045607814305442026820712488662837141181743561442471140656886544810482568867473477215620421553822778477685221333355082045436276446407577732888880707608473278236736263105545111486204784333000355538868778617866315467324032250310277731271586632365163515202742288877706746486071532880840482334876701155474523064634810022158068112743568400075188838634414443486640105365461454078644820274778334251246507706210315800741700657336371185735823814681238867787051022273586052801360855237187557533468846516105335555056432254781305585542418067526150274708351364336301738815445380132717035130017221444843541056086021782372045160762204731152478284737075752618221425755217652675677634517767716821181562264144647674404708744803757787388333646200628153388105354664575333405147103750287326710881765028404758441005364302728435230535186000530354711003415760141424308610778813161787565535472618574100058185227470473856034326725404587875618522026787824281262346605875556140248688853807565385157640612273621031454427312278782335757041372335186705328433224631214152784432856820108648445342041603550168842464062211745366101487846384257707745210122612110737587828186172484810817111127808878433886811633742124122507043044777402011560687277552724761853475230866156775144833853078883575836701665637578550076346725200236716678268107875871071617288608165114023034736658327145462010415734562351617677850535074187474504000861586253405577460802336405082588623015244435582464165870381848561885265182735510612822644777223141672517571427845374483012408746163803400706310836704225751520655001376432524311126485752081721762106501780716255534032446041618276463366826610512368388525300288484324782823144050410006685875154273810185304218557671786007271358883470284837176181224673417816616025835647383173107245671531062625334748733107050316182705870066424417578174534267558874447423674618106633162634153776855133327732621468741625680034830562170158001426244078586030527214006402517461715715064550776263361142576270680582562781426035324236607540435830550057642175015844226201411387778744217200236675170048478848120748642630312115837585453741473764507632208317015322404016255210321360357286101180508205181848747583602171447806555807287162782811224487051102176203707481530232626711857180164831856380307385452755546476731157335483321475678051320761760548667161436774428453257002874263870041064035013527300338540172057802852384428777078133253847243847635817000145440383560864168217526255588041751760106018017724455473113363550354624444501444114880204108833606532331187102846110843151505812245386712662855451626360834714514018442577866128511426082450870818276623202032633258537788230504140220484240443183753303576865816121734473318414006532232377645116142211402228404752535562682736633388165742865A898B64EEC22893F9451C77FA207A7F12540F8A4803CE53580C1A75BC6488429F13E59BE9592F89780D55AA829F7F8D9E5F3A7C6D8EC48C35A4EA050BAEEA060317E9D5609402FCB9FFF0B66B1BA387449DABB0E609831306919D737EF5870D00B7B9754239EA2D0BF7B6DE7D5A022FAC9F8F48A56EB3175B205373E923459B94643DBB4EDC6951689A392372EBFDC637806BB86F73A5E52A26A9E561081D53A126D47979B300355CB3D0CABB9B86BBD55B199785167145440841429F4D1B32A9D4E7AA05E536AF7D5012FB31CC05741E89B567BA5ADD05E4311F72FEB86FE422087AEA41224B55D564E5A59D06AEAEC209777B528A4CD0A0B022E506C8D8B81F5913D9FB1A83F7655F8013DDD8D28355225260488FA1CC201BE7015E225AE2502A7FE3328321863C61AF4DB81D9D1D1D785C65BC55EB287516D9DF95059FF2AA5FF5C795B0C0A01318435FB4A6A8B2A825D9B67C6FDE308D189749DF2A521A24EDF2B0943869D41174AC356267A07C6037BC1C0255EC6673B964719024B5D9CB7EF13C4A9D18DFACD899BEC7896390F90B72C00C213E01C85A08130AFAA1570EB7319DB393F3A75DD42F3FAC25EDF8052299C9877548D7A37C501570B78BEBA0C9DBF3867C38F7554EA41B3074B80BA42B50F9AF80FE3205AE3C5EC03FA8C795EC5FAE4FEE02A526D581F4FB3C8C8D79E9657C9AE0B0ADF29E0E64A2EEC385BC333CB71A7F7C232DB7688B7C8BD05DFCFBF361837078C804E3A864666E12174E70B8DEF0A29105A81A05C9FC2454727AEC6B74D8ABA7C579D195E3F1BAAAC03E34DC7FD4989045BDC2C465AC5CDB7189A7B77B61EAD0A65B16C4B2286C357578FA473ACF68A7327CB4112A98E8213DCEFB54062D8AD5E85571613512173B5EE7A628B3A6250BAAD81F0BD28CBF4848460F1A0FA96DA5EE4A4BDF2B2587F289634E5A71F5F8BB1D9923A4B28E25B7D0D83E1A6ADEAE0588F011183933B08B1FB4F9090E8A265D37FB87F2AFDB76DA4B5449CD09FB3D0D3BAC10378C07F168E4F20E9C32F582B8D8FA72C943570ED7F835C7DEB83E2C4AAADCE83D00613B48D6E818993C539953184ADAA643BDEA38995FCE051D304ACEBEEB6B68BC93E4F70DD1686B3CDC2F8E7320374CE680FBFB34AA148584E10B6AECAF2D50122FCBD0F8980A324C18A49A9118B6D3EE47659ABB1166BCFEB8DF4F21087C14D422B887E2A3F6C2B7636D11FE8A18CA3CEDC6232D3ED1B83D550FA177C4D4E53A122CE52FCA6697C75786F4B52B3EA95CBA56DE2400D0962B066C9A10C75E6297F29829E905D28E81087865201416264CE77ED3823AA0C283042BC51263D32AE5B689B8136B9590B78AF8077529B63A61C9C62718234D0624075437A3B9D1FD45803DC8D037AEE2E93953945087D1F5C163415689FFBF4C4D3F78FC277FF67165EA33EC0DE5DE912F1EC2EE543343C89FC5B45CB02C0C2F4485067BF3FAB49F42CA6A841996B9E7BCD46E865A0280BE518AFA63E2867A75F5DF09CB3F639ECE40AF9EC7FBEE3C2CADA5F5672AD22E0F6BA34FE77DAC3321BDBA56200D55A9DD056D82C2E0B3205E96F16E23F2AE286741F4360F74B1C9BB15174B4FE00F1A76F32B6D64126BE6F8E3132E4479E547E6FF578AFA6BE9B31573D44D34BEB67F6ED7639A68DB83465C3233161223B3C2AC1616694436F5075737AE45D05D4F113C37A9BC75212AC74816C08757F86535DD0550E012E036EF6764F2F435961E8D262C8205EAB9AACAA43C9926C38F3E0F9043FC29A35F488D3C664FDEB3A66B1F280809B3E1C27DD7D8A497BBAA55087BF4C58852114D722276D614723D255B4AFFF1025798FF44FA03B83AAA6EAB8B7E3ED5333A0B5B3E55035DA6D7B6EF9C29000EB416FA9BB708A5B6B4E642C6E318A36FAEB316F31DE76A669B4445B0C39CE3AE5C761A80FE44AB27F8E9388A4E5FACA516B0C5A3BF2E004034C63758ABD1AD5A730ADC5DA103CE8D7CB082F06108C7FC9DFBDD515B9E0BC5338A1E115F92C457D147267FB7ADC64B78CE7CDFFA677BAFA848A650B26DAC5AAE1CCEF5E1B338E7337515B6F11547EB911412D541CDB07CE760B73DCF29C723F47C87CD18B3F813C0189A33A727C075E513D3EA51608F8E3E070F706899B2B5794700023E693E3982D9250DDB9A191F686139F0EA2AA8D1719B6630FE6D6588B5E4F72683630B9243FAB2F6B272BF197D25B5C887860E1FB87149126130D71B965D28797C5A4D55E38D84DA4A3ED2FBC967691C573EDF2B77D7E343EE7F279F981F77AC0C6EB4B4A1BD561796A336D8495E26B26B159EE6476316D4A63D18BC33758105BF31FCFACDDBBBDA8FA99B6674C19C9A12F5E769D7B5E1D66ECDAFD25EA2D82239E6B51A83D6BB50888AEA373150269552B1F45FF5E2F553143F0313E552E3B7C1AF7B156B69FB235D321CF148F580D06AA4672997CE3E7D800AF3A49C57E605A38C5372209EBD22D13CCB0336B4A95D639EA36B807128E509F15615EE953EE93A24CEF75FD15E164756E7C6E0E28B9D1CA83E4ECA65808B805428763D9D1E6126CC4CFE9BEB5A1A1B90760D92BDC0A3AA0F297BC4D854BAD8933115278098DE7CFBBD2E5C04C6F7D152FE2BC164C9AFB2DE8394F5DF0B77A3349C970C494AC8AE514AA225E205B43FC692F176A03CFB061F45ED5674F90FE4593897A05177812DA7B6D7883FC68BDBACCD40C699EA8575AA6ACB084B2412949B2D71570A7C7231C3E31CC5B122E72F181072C92DA2B07CA3F43B19A75FBF09974C5339097B680405AC45C9EF9574BE7477CD9A9B18C6325D37454CB5D82F1DC99578B8DEE36E0652AF8F2B6FDA421BE7573C46EDA317B04F8CC51DB0C008C10122029FCC2D7C06D713BEE96940CF6A8AD3E63F77B2F38ECCC6B44CE2F1AB8AD4911C82D1D5A204BD381408080679B6554C37C1E29A3D99F9D7C8311FE31BFDA77C0E288FE7E09AA99177C93222BE2920D9DB4E3293F63223D2DB69E753EA207FFAA99FC0531B90E81D27645026A6934C8B5C82BF5ACA854AE6C008D46003C8786AE784833D0F75230331C159DEC8DEAB2379B75512028F8294BB78046DA61CF919B63BF3E130E3EC40F2AF5EC410582CD3944DFA00BF360628ADC019861BD6E2A79C76EE57095A665BC7AA88704A401E071AEC72022D669E407EC04D1F04810EBB8E87A9DD2C41434714E0FB6760893236E41A82A8DC282FD1397772B7CE339BB7AC42AB86BD7C1FCFBCC3C777E84D233042CD1BA3A2DF42C3F8D229FB086B6697BCF9DF1E3F11C086342CCFBA043047D617810AC512804FDD651A267D236044B3DAF8F95BFE7D1444DC5D0BF5FF18BC90DD7744A01A0C3059D3DBD9F9F2BEF59F72C7A0847280CFC3C97AC38F8742589E09D95F3E3674A2534BE224B1C236EE8437F1E88535A93CD20AEC37479A2E77949316206BED4ED6C0620F221FA19A339AE8622F870C7F3F96EC3579AB8A0639383D52D800E33618B48B0CFA2C2FDFFED3E986CB99A7D49379104F936B1 +smlen = 4992 +sm = 4D9BC8B322C175E7C9C02D03491F46EFB66D70920599850E4DE4B59308733A115E8EE04E9B44C5B6C75C80521E2D9BBB6F57F66506C90FA368EAE45F3DA63BC606F1E5AE587ED995969AEDF7B7B79C21A99C8A18BACB37365DEDD58B56940903DA21773FBFB227A4F8F90FAF14D112D62A209D18968AA165E3743A167A309E55C05EBCE0F2B0E19AAE4BDBD62DDDD1E229BF4CEC9ECBA22A1076C994B37BA933E5355CC43DCC6BD28C565424FB02211BD448530B510F6CC069BE5A229610A4665BEB835A0E4F6DD7A2735DEA6261252FF1CF1F8C6F83D4CF16CA34A512161E40B68155C9DAA095AAC2C2D291F080C19F6BD43BBEB542DE42C2A245DEF64240226665F4DB44A5C17356EAA6F22F88C2576EC15BC5E47B0E0455FB2BB564305AEE8C93719CF53F5C56B2B91142E3798393E3AD7A98B2E60E8C89A6BF0CE891EB026391755E15CBA343029E38C5150FDDF7C89AF7C8B994C04858A9E80BDD70C86FABAEDEB311A8002BD0916A0B27762D55AF8D5BFF71DD2F551BA8AB72B37AFAAFB5487A1C8620B650601AC547C8FA0B317098F309363BC9772C748C614F53473C13A305AEB0A053CDCCA5C8EBB36E30D5C87875F3DF6BF9699820644110058D5DAF5970750E6D19CB21FBA8F8BBF6576104EFACD9A65B621E74DFE492F1479270C9DD20AE7F5D55615E0B26D8AC661EF1A2E2C6E199B54AEC9FFAFC542B8E344BED1A4D202D3AD59892807D51957D4FC7D95A737D22BC6F261E7474C596BFD3A23792EA1370A2A9E98987C70DE283E930894CD518190B6B591B532D0152E4991897ECF5ABA2CB0361DBBE13A3145B0A5A48FD3F232AA798A3A289D123AFF9F38708DC7B78884B06D01565327E79FEE1099A85221FFC0478395551F282246D5A4FDE232F6A5BC6AF154B426741CB1BFB53242C80C5FEADD794FD79B7C9AEE1F4F03DED224A7EA8A6D2FD745045D80DCA8D2D1AA3EA710E0377E108058FB74A967192C23B4C29A341A572DC26382FC230CB4ECDA6922174CC576B3847CC823124E415F5DFA9F098DF1BD2AA8FA84BE8B1CC9073E288E89CEBF39A0A2B60A7C1BCBC8CE107B2BC0D4BAD036D6DFF84391ED330D9F8320C56C25899309C7BE5289CAF3A478616D46F100D4690CE281E0E50943D39D419565EC20D5EDC02401D59CF3C3B2DE080B1C7F7E3744D91E6C76401D98E5CEFD1085ED2FD7ED80B0F505E5A513100A8AC6EF2CE036CD879AE7CC735DB2C5C420A26AE1F878A524AC3411660A733FA0B7B3492D2F2AF4D11B2E54FDBB4A6EAD2213B5E3E6CB04C746BDBBE49B3434905A700C70B90F658473951A74A6F5F68F0CD2DA939D015965EC067712FA300C21A1545FE4ADC4459CE46DAB91F76EFAAE75D6EE17EF9314F8C7D275E93CDC4D5C4702A2AB19275805C00C51A1FE2BD2DCA98AA11A5A97F90EEBB5F2918EFBA6C65D19C7A240AF772ECB69A2BCCE9D6E8C9E795F42E48931A8943DE1C26738A1A920DB61A964619871CA3401CE8DCFF260C0EE993FF54AC0BA219CE07928ABDDEF7698F24A76CFC4BF3D689AB40D20278F034997FAFA8ACFD1FD9A12D755845F568A335C59907E3021FF2CDB8419C71164910A28E33B2C71EC24D1F57B699499D148C12828C2D2AD3348F67E3E49C4ADC578D152FC04C9F101ED7F0001BD5E8940CF3B791EE783DCE5D8A7FA929678B7514BCB9A7900281B5AFD42CDCB98D342CF01E02DC73019BB173E8ED85B82DE52DF8283690A2D5B4B79B665BCC9A7232E6F2E4B118E3E131D3E5726CA6C54510A692E22AA57612F665487F3481BFC68DF433FD085F77C3E41EA969A71F6D5F49F2ADCCFFA91F5A400ED3754EA85C6F601B43C80E7716E3CC14A943D28D01D03B2D17220CF05927469596E908E398D4871319B5014B60CF682BA5F8D67BA00BED26E1B0C1FC66AC51F0FE1FDE02297C53850FB5A012CCE982692EF71CEBF762CFBA6DC3D45DA1B573C1F9B7C8641D1B75515E1306D96B41369C930FCACA786376CEA53F53E90BC435666FABAD355C2F48F6261672595753D0518A162279215EF9626E57FCDB8644498A66ADA9992548D164419229C5287F271FA77CDA65849A839B73B9798E94873636AE632E117AF5936F5E31CEAC2C0B58F7B1FCA74513E3996357AF36C9E19933B682F1D453CDA396469E244932B4D13062F5004310871B1582D4177BFB0C2147164F8350AA69F8C542F2B306329A6CD6B8A4817659C92B604DA9DD17F4907B6051318FD8C6E195D1278B845DB6205AC7901A8BB1FD731BEC7A5B30CAE85609FC44FA057383643902E05BEE020DB9FF8C675CE76C4F943902CD3BF2E8CE107FBB1F24A3B8858FE25A9F07A6FC0EF88ADB84C75168422D5BE7C6FF517A69725706ACC756F5EC4B9D70C82FFAF2A8471EEE37F4BDB2E83D822E0CD17FECAAAD721FC32E553E1B4D00FB952AC4AB76579AE04780CF9C7BC5AE0D4763A7E2D1DBB12EFC0623F7CA1A9C0F19ECD6FACE69CDAD8EC9AC8FF259B18A9D06A0072B52D6588AD7C55AFC67C066A9C1EF7DA09AE7EF31774BAB16304A187776C7885AB806AC3250D8AD82721B046C3AA04A3841579F2410CC9F03E1B0165B6036AB8A64378076F2F6EF949DA20EE99354AAB7BEFE27D8E8CAA33A45A09F4EBF88FB56ADABC9D3D7AFAC6F916CC3BD66375DD8579ADAC2B5ADAE983C82667E75623261B62A719910498D3B8BBC5E3E204711EFAD4AF0717EF81092D9CADDC0E139CF48DC50DBEF10A2DEDEEB2DF13C5A85FA2CD2CA7A2F6654368A35AC70DCA523119C964A3BAE1FE9CEE98CDCE391AE55F5D92EEEA36C5AFFED66CAFBF7A904E36F89AC1680887AD880946C96A482497B9A24EC21B36B5CC5C2DB79D1F131B8BE7F0AADB791DA3A239F43B7289BE14836C2252C1C856E51D1B5FB39C50ABE0981964D12E43AA2CDB29990CAE06AB18DEA6A99290071FCFA009715CD2C2B050700DCFC80EE88A75E1C94291548DCBF64FD598658BB6B67CACB2D16BAE6C88F4B32EA13388531191D510C7951B753C87ED0036433A504E4BFAD7870C66BA55A75695C02A2ACECC98D641245E38723278802820905CBA3EF21BCF1466CC5F4D8BCFBD991743FA688D1CC47243722661C32DAC0E0E634E59BC158CB5BC1A8A555FBAA29E0D8FA21D961490FB5F3DB765A283B32C573B0059B9BEB8C2E646EDDE45498328E2F74F0016CA43CE4C983D5F780EFCED427C2B869BF13B8DEBC6DAA6441086559E5AA0E515B8AF452C50BE9BD1649E01B58E6D96A297327432248F9EB68E678ECE6F8E32E78A7A73B41E287AE0856C65D6433194B93B954D791DCB44C2B0DF6BAEB3A418FEB68BC18C5C4CB48155B41F567424E3CB5137C8A0CE4A7A810866FB6DAB8743D4E417D26BB40D3FF7677DD2B0E699FB9FAFBC883EC5432BF9021AB60EE719559D86BB851B862846982D1143D2889033411C6DE177247F057AB28DA4FF9774DBCE94E895476B217C0DE1DC0C48183FB748CA5FBFEDE5FD4D6A5E08C18432060F49DFF2AAEA93241105E450C90C43C55D68C3FCF4E0FDD8D49690D8C448280E14F020817FB6F114E8FCB25251758AACFE2FF1BA0925ACD8E75F040671B4F9CEBFDCC1FB68A0F00418E28A833B1D8148D93A055E97E232449932C8252ACD5166E5B9F7A0CCD19BFDE0DE1F7090FB088B5A15C27FED5A7E1CB6F60564F8034A1A1E9F1BCCB43C96E0D345BDD30DC618EA90B494320E09540E021CD583281A5965281DC7A249DD3D99ED2614431ED2045195ABDF744638D96BBFF94B31E7A3918374F4B125416E9024F6B8190B689034BCB04FB862AB839F29396DE630748B492837138CB5F0BAB81313E19537054A0F310C49E0B04BC141747E189A8594884976459A2F7C248B288BCFFF76A5F1992C13EA58CC2231CFFCBA9638CCD4E886C5CB8E85AEF4379942DD47441E46BBC2C9778D7487999B1AC5AF9D6D0E95ED6F802A8983EEA0508C39AC0AFE4E5BDCC02C413FCA24A648A20E253879D7EF7E8ECC5CABAF55BCB4CAD3B540696D6A3616387E6772338EAAF88E9268CD16E979BC686591CE6DCBD4A9C15CAE6BD809EF68129B06B8BAACBC0227A5DEEAA7D5A1EDA5AF510FD1B9736D9DC33C157779949500876CE87D02BC8A8F826069393A918A9B0128AC9E7F935658050CAA552E47A9352A8B1E039D62D66463C178735A673B83D289830F12A00B3DA0CBEFFD90163D2595FCF83C9DF722C2BBF72AEFF22C6BFA9853FCC7E672F3B2F97E582CC021BF33D8A9213E9581B6C0E69B9EB83B915C51BE01C3185E8D03ACBBA383536EDBA5D7D75E08D021680450B0F0E0CDC220C6FF8AF383E528F3FD734056BFD9965E01AD65B9B26764409C8D001ADEBBDF4E9A1DE2C4B04E0F00C61754E13D2CCBFF3FFAE43DEC740F370D7AFCA5C5820682BF3072452ABAF6CA83977D9484B3CC3DCFC2B7FDD1245A13D5F95A06C937A71B99DCAD31B5C377907D9182C5A2C37F9262970CA13AF4DC62B263D30BE27BE39418BD003FF1E73CE82843C00DE8A812EE79573FF0D5B8E03007D3C657FFEBA74EDA7F543C804A3BB442B721380150859CBCF4A5B84D12A79AF28134A6AC4D6D801131D656BACCCE70B152F677288BCF6399DB31E657391A5FA4D5E8EB4D0DFEAF90000000000000000000000000000000000050D15181E264BEAF8CC3A7C393932CD37A2CD8ED790F05E4038ADF1287E2ACDCC0BED9BDBF92CE44AAE95CAF4EB142B858E1421610EAFC47DE566182835BDACD4C836F19BD686D53C3834EFD928487A2AB3402C2E3AB3AF97AA802B05223CA6927722C3BD1FE3F8C20F93C3951F907314896CD21CB99306FD7E5B6176945C2898B10C1DF62FBB2680752CABC8980B5A0430BE39D34BB7DE9544BCCCBFABAB709C11BFFF5C958C8763D8D5830235B49EAD26C834E63C3F3F2D6BA944FD2688F6350EC99DAF4CCCC42C6BE1CB19DD46514D71CB6E887DBA80EDB580B27F1142A20EA0D497E0336D55F1FFD4BB3D4B3521F0A01C7BB09258971D1ED4A98EC052B24776623D7B9A83C818795E3989EAEBA8C9142A97AFCE855CC6AC0ABA15F0546684AB5C2F48B23BB72A88B6AF2BA9C73881103CB6FA99E3B03119EAB03BC3B9BC365EFCD7B9F49A8BAB6A34A00AA8F2C88D7BEBBA808BD97111EBB192D82AD244E18BCA732FE6F72FDE5BD533E4BCCD3F50332DAD3A4169EA85C324D165413F10888AC3B21B91DE09FCBB9B636ED00FAAA669ABF6429B78C3C04F239722F31FB0B1A20CB1A6B553908070AC13521DF66772A6036E6695CF66B9A90E2111E499BCBF5DCD19744F43DEB943445248A5E84F168E7BFEA2DC4E1D0A87FB4140EB7C72D2DFCC27923206054CEC870888A79938DACBAACF1F122B22AB5C9701D777BCF9809CEBC9B7AAC52468134FC4A92C2BAA9B8C0F6249130A50337F460A42CB5364A5E7408CAEF8D12BA6934AB645DE9832818F9DB71F5EB0B158DE6A76619E75245B56020E1664D8FAF1C1782DE4A688D4055E07D842410600E9454E28676D44357853FFA7740200C91EAFA16BCA21D0006F47FE8159A733E0E91549DF434EF316E1DF9BB97DA6A2C2E2F20A65B3C00041A903270CBB55AE2432AEE25C71CE73BC2322CCB8E5BD0E24820616A890B0851D825D79411C14948DCDF48776D72565422056FE75765E50736C82F71270BBCF229A7B7A45DC88AADF4F84238C896DAB889E16C17DB7BE551AB24873FDA82F102D0FCFC139C9FEBE9FA99819CEF0E2684DFC5C843A6D496D8A595D33C51E1FDE9A84059C7BC596D32D53E2FE046F23FEFA51D13F9C28E227F5E24429B851ADDBF578922AEB0C5A61BBB666D11D127BA45C9E6378C70D75643DE776483582E034E81FAE0A3F029C47FB192CFA018CE1F68261D77CFC9E05EF19438E47F3DE9A68C8DC09D07B1BDC6CED69592623750F72EC2FB8C5CA981DFB84B4BF0734377EE9DD8EF5DDCD96F438D30AB78F402EBFF2163D43345EE8CA119F3208E21AA3A2185DE967B475B9ABFBC86465275F9A634FC22015E94A298E9C204E9786CB1FF14A5E99F942D42AB5DF51AD09654083DF0259AA1C26A760CCFDF4A276600C5FD3A54F210B20731941EB48A79435F1F86C45F8181D9758A1835721B87D36C725878375FEBCB8D48ED2CE8892DB50965753A98F4E7110281DB40ED64DD8EB51AB9CE41042589152D8CD5876FF30536F8955172A7A8F5C3F5FFD22C9954903136F781F0574F45F909BDF1657FC1CDCB9C4689F41E462C8D39108B10D78B6892C8775FDEB139258F8130BD1D2A1C72B5026506409F9862AA8729B35C652074494FEB84A553CEFBEED19D6EE94758E800F5FCBCAEC19B6A00F33EB237AAA6FC0B3A08C1D8829C180BF95E7D05F919A929933B7A032CD20ACE82AA5A45E5B2FB09812F36974B5EDA1B387FEB13BD49AC374F821341282C8FE2FB0CC5C075356833FF8CC6B648729A4298ECD73BD0EC73957077AC65722D0BE23C1536B8DB7B0506DAE47C0070564E7D7F9444F47B22C679EB8ACA4826F974A42043863E498E5301EA162C4E96684ACC5CA26CCD083541BC4C1D2FD690E51F07FB08337450A204B0F4F2C17785E037424FD6E78746764584D5F19255496DF1E524BFF0AAC31BDE9254429565278A39ECE4627C023EDF18BC21BB523D44EFC259742DEE9FF7159D5F700D957CCBB505A88C2037629402C2A322D17647E430777B184FF7B4E8D6B94724ABC36A5CCFAC08E2479E8310BCB7A617A25FAC6EFD10D0A07248F7D4597F14309B8064FE3BC4A4479F905E832210D49363D1E5D58176DEC9ABCC0C5132FD6ECCEAD2B05B56C96ECBBEB0B803E43DB2F982AD9EFE1E2A49649ED8E42707970C93615D54A3E673559B996E48A3B73143BA0884E918888156CA78F793DFF990FD721DE0C0B7916A5CED736E31292C5AF062D7CCD83FE653294FAC8C50CF6BA37B37D5A9BFD1E3B92D1825C1BE0795F9B257CDAB91CE99C0C51BDFCD6C0AB5A3BC6E30F884ECB4F1F61A3259CD279205B2C21CDDB196360061758E67B1C3724F5CB6311EB4FB92E6C0D71E6D1EA45 + +count = 51 +seed = 4B6B73E042CE76DBE39535E45D3BB2F3B9F8B2BDA170E76CC88666844703E32B2367460A0F6A0A2E3F4E7A6CD32BE998 +mlen = 1716 +msg = 0BF9A7C0F63CDCF3F850ED7C5DB6191EEEFE29E498A19F9D89BE4698821ABD72EDC34317B4F8EC2736DC83C24AC195BD55AFF00E797A83DFFADC7970FE53304F16F5DD92E6EC362B9E283E41EBF121FB2FA2A3F60124EF3EBF836AE51FDD55CA9F59B085DDD660724C072B86041B50A3A446CDB20A45BA65380ADF007E005DF2D9AA16A9D22B11DCF6F0B1964F04F45441A923691A15D80DC85003B9AE281F2B5983DD1A04D80A4D9C4372D9820BBFAE3AF7735E7C71E9F085C0A6E4BC107D9E4BA222B38FB236B2CC3A19DD6067BEAC460383FF2BCC771A7F1AAF092FC72C292FC1D5C6FC6B9715F1E1272EB22F8E0B33A2830E31BD6C531677902F6A95CABC3E9C1AE36F77037A785FEA355137A581FC14E6BD5F1F7AD1A5DD19DEDD448B47B558C22DD0FCBF296A812A726E7D1B57F4688D3F577104CFB15FC63C27F7B6051C7AED7D645186FCA63AD9C2D68BFF442466EFF76BCF0E398D2BF54C2CA4CC614839E9BCA48AB2CC53865803710A98D313AFF1DDD06A65680EB83C640052DB807EB2F38ED0CC211128044D331FEC3E6B0B2F3B675C631FDADE62C16D1719278413EA3F8E54BA34EDE7E73F3D94802D2F9CB9794D257C46679A3F00015945903190B97071F8FB55F8696253AA3F39B3FAD344FB88224F5313B43889B768171895F7AABEFF25E21E525EA01A996C764A3ACF12BFFED08F3F751F5CC094B50B325F8B62C7A5B3256964D48543690538E634E5730354358534B65EDDD44A526BB4B15E2042B6210F503EEE06D00D615CCAD10D73CDCBF5264B526674D85C0ED31BA5EE584F21FE6D13F883ACE4B094768865E43099E54671240E8E2AF8A7D7D22335B3974CE860E7238A7C1CA8A009EB51C8636F0659189AC8EF01C871E9008957CECE0A367B63BD2852BDE8690BD74C6D956435D0AB82F94A90CD00FC840DFC7036B84D51F1FF5076CA0974DB6CF25AF42EF7DC8C30C2B04CEB2510E86FFC510BF4C931639478FD1520AD571FA17958CCF8E37F5F6360030300EDE3A33871E9582808BDA2233996C5005FD0C23D99261F570AD9027767F6FC96D18BA98E8DDFC2B79AC12CDA5F2367B4BB6B99A3E07B59882E49A92AECE85339BBB18AB9644D20A3B2A795240492CE4EAF09D9EF728FB82B1DE7B64B5D391251FFB0699335CED8C7CE642FF1A79F04C3EA0DC37EA101188361AFAD236EB218CFBD1D0EBD784CE27DCBA0266DDEB87B59B66A4F75BB44665643FA358DD3D0B69B49F45A752B5C410E2299A62BE4B57B32B0924A069A8E8C15D754CC34DEBB0D967E70693A6FFA58CF7099C2C2458B437C7B205CC7E815F6CB494080F9EAF3017E5FF918558DDE415FF72E954EBC2ED4C20C8ECE38CC916060D22E582D54F74C6C181C2601400110A683F4A365E45FF1387BCE4E152A740136BB762B03A99FB68F6AB42620B2E3C00FA8D150944230A6330409B27E4AAD1693E2C3DD12216C4E2DDBC5E9CBA68B8B5417A7B2EDAE7EB67D25F4EDECBB087F93DC9C927C33076B1C71A2B83B33870D602562ED378805A690DD2A427D86C2C46BA4741F3DEFEB91A05EACE975C836E52868CFFE52CA92F97DE94768161A3E953BAB6A28016782909EC53C02F35184AA9CCBD5B793B525204B72DEB63E104376893B9452C3F2C492F423CBEF1EC87C85788CF3073FFBBCD67FF79BD038672943AE4BC68DA131DBA8D7B41C83B4E9CFB6931987B270C74919BBD40612F823114E4BB148671F1AA62BD2BDFCC8B0B24010EC112E883AEC9746D0F5DE467ADDAF51F8C070A359108B1F91643071438F098233AD9A94D0FAA665A39291A98D14A861905ECDE4755D00E690429C57580DCB6D51BB6186CE72EBB1FA8413892CAFB8713E89775013E546FDA30AEB8AF9F7155C08B25810C80CCAA5E700C124CFF59FA32E0293ADADBCC7B1A99F67E66B28DA614C5A4CCD706AFD05388C65EBCE07A543D3DC1E5A5D1F307F675728D4C629A04E9E455B4DA35236C677F26EDC622C1FBF29568D509EA0690AF4CB5DBB4E418B6162888E43B458774A31324BFD5EE8D2152E4AD43A3007D7D4AF5FDA172C2779837AD3A09E135DE953CE966727A7183BF77ADFC76430666B526692991D3C9DB5BB377552A7801C548AA63F6931D3EE91B875CDBCBB7441A4FF81F86762332D7192FBC2F7B69A58DB6CCD3558047F1940A1CACD6FA28A000B9795A2860394BF05F0120E6D85F96B1FE9DE14E3ED66A31D747924B6FF2620778E0714AEB34B79A5D935A0306E55C36506A292C5DC568403551907E49A43A6263D2915108916F1E27CF3529D1B7BD1544AF83A7CBE58547F192A93CE5C5BC6D652405FFCB95345F522B2D34E8EE0960BB85537A46121BD9A408D283A125EAA745BBAB04E2231C19AE95E13901C69E5C9C4D70B104478F4A70D64F81269A8 +pk = DDA8CD977B5F8E35FC3FA35607DB97F2986B1D4D131BC793BD1823795D7494B5C171DE2BB5931D190C0DF3E01DB3C2CA9D08F4F14D91101F8202E138534DFEF9796854EB5BC32AB18D7951E771FB84A36C0909E0CE70D82D8AA0D9598A5E06AC50A01F1323448AF6650762C8DA7863297CC70475E452AB331CDD3EF271A0F816E6815D170C212C04DB2B5E4D822DCFFB23291BF2B08B13CDDB0BA6AD29E520C3AA6C3D170A9092DF6F50EA692B52D30C19BE5585CE7D83777679C5D81E8D20A1C282268A8776C7DC3456DA3D0B43869CF71D0A1815BB96AC0BFC13E221BD5780E7C1A36E30D1766D8E94C4B592074C6FAF43C56BB5B58921D5DF59C529442280DF2030A4C6A5145F6532084D9261CE62ED21E19418C380E63B2227FD98175CD051A8BEC40E192CF39F1969D718D6303C214BD9A11A0D14726CB7D8850F1C7E35E1F2585D82B9727D84B141AB97E3DAE5D783CBC42A2C0022528EE42A4AB7717986E63B6A2573774B2C1D0B8A3F2A147E8624996B64C1762710B47C2CF7D1E0DCF673B67EA7D861A5615F9D9AF7DA0D7AF5F16DA9427F6C05D9C11748660E546A80994FA42D4F861BE7225A0F5B26380986E10194A89DDD141D23E87A73BEDFDAA63CF65491ECE1F0B92B644B2D48FD48F2FF78F65383F16439FD82F3860A54DB3C6048FE2B5043D354B9E7897E2766EBB3C67A125C93FF2237CED4D20DF28B5FAE3FFF48B1E9E95B08F9EA87FF3674B9CFC7627BF0813E909FFB2097558E90AB68D89E9AAEED1B7615D2E4CFB841B1F6762C821420008F7406DB9E6C763A6EEE2F7B5249EC1670B3E86D148FA407BB651A6543BAC3683C3A9D3A6806C8ACAE62B67375118D697401474E520DB5F3806A7F63489363FA9CC875D780EBF2003F832C944BE0A4999884220994502BE15F90ADBC1B3422B758C87C0CD3B1861BF0B950D4AA01BA6A5869DCA36B3EFA7C4A794569BF7B9341FAEA1F44ED73D829D41DBC7DE77A66126B7CC9F0175C8D39D57219C94197A90D8B4729E2C026AB5EE5576BB90CAA0C139230EB332176BE28E01EED97F77E827EFE012CD9648758E16891D12E48D9877ECAAE7C96B48856F3B7426F98D68924FA5472C6D42704BD6D3AC2734312D78C867D5257402CC7E2B5D55F73151DCC5667CDC2A2BC2AF8B6F9BF02DA1116D3C0C1D73741C31D3F8D9A6A59CA863E8E433653F28FF0288F4CC3BEC50A59AE54F96FBBC25EBCE55C4CF95BAD16BDF987338D4893DE9B16C84A576FB0A795536D65C9D4A38E44D3A1044F640B36EF7DD020A38867B275B3F150FCD2C1463EF4F513E05382FAB47AB7EBD2D718D7B64A5DFDB57D56B930477D69DFBB650150A6A9FA4D500BAAD8A2E97A025E0DFE932AEEA33C27187CADD823836D154095AFEAB1E4A673B4DA4C15AC85C94680D09A20B2785856943240D31B536918DBF03A9CAFD191D9E3E232C294397AD22C90BF1BED0154E434BDDBD546B97F10C1725517CD5481EA5675486E982DD434CEE1019921C00D74BE88153378785BE30D8171C8A7CE5DF52EFB8FC3449A7BC7604FD4799C367942C0D4E9C558AF29C2668F34FA1991A331F14B507F5A46E450EC44156BBA3CC4D62149342B98B55AF4C1AE85347D6E400B1E79F53270B9391B1BF9ED53929F88AEAC1E916E1A970395CA881178D28F4D31247636C139282778361451D10AF74E83045B281763528C73330AB72F8CCD9B166B2076E7A3CD73A5E6C7D433817B3F7B52030DF3265E951BF0922BD0A46F18AAC0ED8A9BBB26CB5A01AF389270CFAD34583F6EC1DC768114737FF9A6163A2D9E0166C292DA756A5AFC8087B38AE62FFF82E54BBAD4F077FFAE37B215CD6490988CAED4727AE4F9B3D3343D1F9CA3640E13B2CA2A57AABC4C254D77D91EFA4F84E8EC632DE618F39A2CE8738A951577555D378A756470F48CDB31199D5886DDBAB53E9FDDF238248CC1DEC7DDE17AED36133548298B98173A194F0A07DDD585530D0CA0FC8ACDDF979F3C44AB871D01423489E236D1E8EDFEC4CD9D48E3380DD93133EA145709B1833E44C4C7E5473A2B0E96E552A3510A3B1FE6B0D00E2BF43F6EAFCD3F2B3BC2F3E3FAC079D86D389995DA2B2BAFC259D6E559292C9453E92B2416BAF46A3539E4417FB45AE7A3307E82609A5E778D551FBE7C85A624B7018E1E21342DE6431C03667A947A6DBDC4121AEE2B5009E23F5067A9E385CD37C44FE436CECB49BF762C5962BEE020304F35467D8DFC9069FF8F09063F7F2F93F74425AFF92D8364F7E0124430A88867E7617D4C4118327F8E87BE4353C53DF5FAC77E5AB3006E1781F7F3DC7449BD1B67B1907FB6CB0B821D178F53280E0FF91622B33E66B9C72687FDACD0A0B16337BF856A7DEA01D73EF41435178DD61B108CAE14A19C57A7645CEDCB42EF3AE54B9879FEADF261CEF24261AACB78F242242CBAAB3C42BA390F29C18BDE54217C3842164825F307BBBAA2DE3FDAEBA68EAB59F4BABAD7ECFC56FA61DAA8C1D79D21066912141F21D2355DA94F619701A787E87868CC3EFBC77258EBB5EB11B0C97D9092965162D6292857ED74E1A7E88504E7F08E08D164F127D00FBB9570A057B9FA41E0D3910DC81A8980665C1DCB1AF2933A887B51E8E42592C3803E834412D8E50055F28AC2DB165F169E65570DAA7C9A4FB00915E1DA83E02DE601A0D0BBD755347BB4D7D4D9290D63527847E50202EE660D371560320351EF0F5A1035DD49F2F208AC9EC4C8D027CF9B +sk = DDA8CD977B5F8E35FC3FA35607DB97F2986B1D4D131BC793BD1823795D7494B5A0A2707704F6D63E12F37AB49BCC8B61549654AE3205A00D35349C3A952F6F1031327F0FBF6C14AF6F004F7529AB9040281773CFE660C6B4D5EC04FC93186A78FAF7701EAFCDCBB8E34A8DF20B97BC016EF2CB830FC726FDCC2BC6A6207987F4431011563548047438812736723875127150641808304706622546432753757645763174350147670687231683783807103545833341451507723251215053737285650607125678058033483546112107635377385120443625402512740432778036066031841388324080518857742883257236207548070885337611086144080226816602084842613562458240101033743787073678162868871838277561872662044323614424706838777866408654331431451870108716620838802625086427557500005632333571554502516807312457583601272023885358005082575454802558844563615600273750070824787056102834166834835616460578461716514750206750354346567836787700104656130223052244682840516413485370301654214360020645502425325064542857175848078842642213434241274631847615123075431301077544384510375266003871074210222386554356668786237740411518641585274763400775118655483658005714611306663770522888873888230674650045467803386260678503081421728746686748428548068731227005780131806882102240635754602127335250528303161721138707151068120415140115673287582712470682247432520535454821588332828707066584076754562825081470612850043626353504034375067580875146817027000135538142154875647506581400321460006017383667282200030277130163685502661127123865817750286221835342272401726461155331830254075674742843823786420574028421473863310318361008605333143284083674628561817137161685218853762225058425718684250363030576600778064015616345513182535677280855426611214870853133428480506808418471586370382474003635453087627256006446386543251866837420561737245416537742681148481248725272132635627404355346720686567587282306263608352413407576575737423015581108335442653161472250601488712812841551228027061356274566673826835830571567061514265843151744407345482535878752686686371102152024412286527502305778620787562380532104622636017257407527066007586385524263867522441508011553765330374037282470722227566007287465616071141282601031411046516577425806730008785638746032823652423283845555755454805247314045042374214421845652185036711577171084763208878411215514362508010856721125251886584523340764616457186105588162347712402303104066218161038441581641642504484106036346040667281815415328004246077575005323523002485066301861128705671322423820050135486326538513861721000107537143561357874245838345018320015547733601537433455371566182047030436465680343122455068082518168121385413868226505567356726780234088275815756848477637551073651574580673740816202761500740350133707387408707080736175476118285477340883146004705305521487533835630058542571006744724636787110368788412275166276861753823781545531273217311648764116845001227580251813535441270528678803875414451535254872170504145841710431661116400617703061151717281572750280552372031564506385157464714544483520310147388082261655057831513287880412253204335535388662756778424827584868580458035224308281167712157074454024714164547655307165566872856543803142502288708014814812352276561620445524120787781607556559ABE9655D88A50BFB07B84F30F7FF96DE1713B2B1CCEE4E5D37D637FB4B05FCB8E8389895E81D047ED35273FDE476CFAE0773F49720BDE14CFA21B6CEF7BE24B6FFBC4050864E2194E16350471D897EDA1B0DEEADA66966A1C7DDD1344B8034DB6546D25AB869835BEFBBD65B1F6EA7A1963BA8CF7D5976C30F1BFC47FCF565E54CC055B03CB01571D9C50C0BB40453469602D28C675B6247188F5C6880B3FD64FC7901B5DBD0E8A5DE06DED7700664E719784D791932758BF35FFB21625AECA43B439B1A556BED010B1670AE23A60D3F8EA39CD6658C5158D3B0F34B8C5A77879DBF4B331B7B493575401B9D7AFE5764859B4996E1DC291E34A7308EBB41CA983603B895BC167F6845C78995A436F6156CE3690A5BEF636081784B5032DC468752DFA9F1A2AB079CCC26DE5654B1C948AFD343363CD1DF2937D384A467A5273AC0D6D1298A31004E60CD84423FEF526A8669BE2A95AD46EFEB269D5FC26B8D46F9CE6246FCE86B99E0ACB9E9A9510AF17CD5B0DAAF872EBD2B968C1B8E620D9E2E33A051DA5F1C3B79E5EB3F4D1B0745DEEB139CD401AAE89EFAE8FAFCE6826EA820EA993C38ADB140F2CFB618E34F2CDFC8858F6D1A7388A1F79BA89D74C460B4F96164BBBAA79DFB6049624100081D7F50B2179E7DEC04BDC3ED46E38CD43262594FD1C208FEDEA5DC3E621DC2ECB914162E3B9849E72C19FF8DB091517F57AB06C987E42D8F404076963A25DFD9CB475CD94F8C2841D39326B47982EBAE36C90A0794F4CCFFF5EA3B58D6B78D98E6615F94ABB10625442F661A81AAB5CC8983A886DB915F2CB9C818600B3FF5531825F8FFBE04D3D48B6E82A5B5CB1AAEDC8E49545AC2CAC8CBA77C211CBBC51BBD04E7441BA09303B0D3C7E3B4039CC5E15EFD43C1B3B5D20329A1A6EDAE87CA19003EC5BD73F2714589C1EA6106B2CBC7B43D1CD358B02273405961D9526F9B4F79367698368B5532B56EF237D16F8CB61D3F0C5296B375719045031EE6C498C65AEDDCDE800C6BB972D772547A3C85FBC599D5B485EC03A87A9379FFD5478A959B9A72F02626DB92796500734415EE4B66F294C4D9011E7FACA864F78AE10F604546938E61630C6765F52AC0B4A4588024988C5880CAEE6C4591091CD9ACE5CCE046E40D68FA8C37370A680BD52DCF29C9B8BBA136D902B93EF796940F5B7B131ACDD2AC61F17BBB0546EAB5A50A9C79A80105B3DDEAC55DA419CC1BAF5EB169ED3C14B788B0DE3AF1505CC6411E096BCDB3B9927BE3C90600894654B6CD945F48DFF6FD37472F76A4EA83A8A068571F548ADD0B3D108214E2CAA38AC2268122F57878693D13B1E15FD918B4581071DEAB49D51A75C3A36F7C2D71771DB0ED340A597C7368FEE0AF7142B465F0CF5C8FBC5D56741C057089EB226E73640974F9ED0AF4ED35333D729FC2A60CEE10BD563F8A3BDB1BDEA8EFAD948122D25F48DEAE8C80FEF22B87748B28E4188D4299526F5AD03766965D2298DAB79D3E5268C212F59394263590188D8FEBB90B6812FB0A1A3FC2A8DFA1410B755AFB3C00D058EAB838CCEF5507DCD6A73A7B910B969A6A30430AE0D676A210A8DC3BC7F528479B2487693A4D31B87E730065B59F079AEB86287DE19A78CBFA634BA8D29010789799E9B114F5D4233DCEAC3DB55329225BCE8045543ADC5F97702E5F89E6505497FF1529E52ADA6F5E53FAAEA6920EA2BCBF3047E3C9439BDC8F13BFF881F6D5985B9392B0DA8EEF42055165DA0E225EC92D5BB635902A3D09142D9EE3ED753CB8ABA78ED62749E8406D4B7951E9021897C6A98968E3EAE0051F53F243A9B04348A84ECA7507BE3A6E3F076253A8046E12FBAF2B13E58BFB8FB0D47499C4D172476658E3072BD9D32A5A0959EAAC29A93486DF7F4EE6921C98B7C15764323D64F1253E160059A33BEB16927D93764E158108431F3D77A93A40AF864710EBCDDD5ED2448B25C4F513708F2748D0AD80F0DBE7FD0A05D073BF61974993BC6141DB0FDF475F439CAC36939687DE0F784D483E2D7C1B1AFD473CB949B52134B286D446FA02E6E27AF70A41CA0D9D66ED69FB3FDBE260CB58C0E2A9E48C7FBA2627C826A071B56C864B540340429E1D301B79D42951DC1423915FDD6119A3FFF1F94EF45BDBF2D013341D3EC029F51559A475EB70CD1C3E04CA04A3E45AAB50387DF93AC67AC7A07CE35B5CE2061A5FB21B07AD38D3EF926A460DE8F0C9C0A962B5EFFF20C1A4DA688CC43E5DBDD16375A7962AC64435866214B39CBB8770EFE0E9CD8DEB90914DA2FCA4D1AB2434284A66987517F5201C35784F8CE96022A820D6CA3CE1A812C521FA78478F7F7F10DB60EF474DEEE445E1912BF5FB6050E1A3EEAD0D02360098C41E1F2D4E26FE76CA7CC6F8294F4EEB73DCA967D29A7F7D5233058504B00DFDA0B558B3FB00EDC87441D83B0A4BFED90BAE70CB34093FFB0C46A6D240402B77EEAFCE2CEF418B1A255B6133AA5444B9897938F66255F89E3EF47890B46F39639F6205F3D312D6A70E4927D4FF0B292248A673EF36649D652601B684640ADF97DDC0EF6F4FC157797D9563A05DDF673A906EC00833FF9BA22D9137DC97C1B68E7723645DF837AC73B805FC7E80BA71204E9BCE913B104A1B0659BDA0AB101B12B72F831CFB8B91D09870ECC2457E9D01D85AE6E72649D467FC622F42BD93B6B155891CB4DBD144164D72B8EB9162AE9F01DB918C6AF8E23C6A06A5B8BF6C60FF4E2E009473B285AD81B7519781E34D87E98FFE992D4913B935C814E2100B12960F76E43AA506830163B03B7DC5A7C62F4D6E957B70EBBF8F114097739FA740AF17CEDB7C2A820A46F14759BF3BFBA4BA37FF59A6C44C7D136EA7771CC9B88B1696F25FF924B6F55D25B4618CA5BC1BDEF368241A47203668BB23B8FB6767E6DC9A9FF3B63BE65840792A149AA725CA81A4323D5A282CE4BDF4533673716FD07766384573CE1CBCCE1E976B870E2E4C5AECAD0A7408361FDF20E74586D7296BE2F9605E4084CC7A782CA67945DCE81A2231F3F8217A0D67AAE1C3AD848D2E73D33F6B4002A335D5AF4910C1BBFC9A669699E15952BA29D162B7186A70C121F8A757F13063CFE951FACDB4F729DD3F20AEFC54F56285CE56D7D8E6F461882F049DFFDA92C2391567EA562F0D691BDE5947B275F58CBD3DC4C120F8DFE53CF938758AD702E231D24E6C52CEBDC015048150903ABCC4A7829CE0C409538EAF442E1BF16EEB176CD7911807697854847060942659C11CF2A06D37B92530903F5FBF9DD6C148556F6166761138D238A1F7934A4443CCABD027CA15D870A07A14B57C5793062B2A10BFED5E5C9704FDE5A008205102953AC3F67834703F17E944BA922EAC1071BFC2DF5EDC2D245430778A0DA13B507CD250EC30D302A50CE20B5B59A50350AE56E7C7AEC22BFF8091434833EE3D4195971441F2BE5B8E01CC9CD87E44B3E5CDC90B5454C9F3B0CE9A696CCF13B9A72CAF32C6D3A6A5D1DF833F121FC0038799318199BB75C9ADA +smlen = 5025 +sm = 8F2AC209AE8BDCC04B411BC8CDB2AACD6F7018CE9CDA838788DDC3399D3004DA2A56EB793A29FE84282AAD50CFC81F66278B050076A300A199797B9DDA8A50807E74E3DF530B41DACEB5FAF9ACFFAC94F70DD7227986F021FD7488A9092133A4C17FA304F9973C7089D046D21B3CB6521C72D53EAD7A4F2498DDB6A42E06C4F5EA697989E848DA64AB5F5BDDF2190EDA6A0B450D2A5B465DBCB27247C67E416C039A99131F0371E38E252E18C9289E0F48EC53FF0A366614B4AFD5470E880FC61B648E6CF0AD307CA6A613B0FEC38354D6EDC56E5047A1AEE96D35ED0E778A9198FD9F925E6F962B309899501E3284575EE60D4A711E75158C922CD279A31D734FF83CE9D16B7712EF48F36DABE72058A55D72CF953767DA9CD6C9BEF2B12FFBC46CCD5DB321CF475EC47B8508D41EA86F3A832D329480D95EE685AD339D05654A8AFCE3655CCF58D403165147CC25DD87D1306E6EB376C47934C7332329685A7C79FB0734E84FEB625CDEE98749033DE00C88D1D8DBEB9FB3C456BB58DD914EFA9F78B284DEA01B1A98C3531B5051A1EF49FBB4486DD852F81A8BCA4A1D85C86D95094218FB44DAC3C213D1B2F8F2D2B355BE2EDB729B8BE1DD4BB5EF2589C7D24B4CE9DB65F6B6DE21E3DA8444EB4D876CECE897CAA437A9B73C9D1C65C268F8BCFA7B28444EFFCB51CBB69E74517F2C04E9E0BB9C2445DF4124D126AC29AE30EFF141D99657C2EDC7451C112AD2D56A50BF6E093C0DEBD76EF11AC73067C277951AD14DDA17287E0BC76488F20B3D8A95BED3F9BB8DCA703BDD6D4EE082C2E770781355E8C27517F806D48CBC9528C0125421F52E5697196FCCBA2A0DC31E781449432996218A0EE90F2FCD85B8A15AC55D6BC3B981A392E7A8F09E3DD124FF0F929FFC0BF84A0A843E70EADED9D7ADC9AB157E3E6EAFB3EA834F713A90884C626E30552BD7F1575767D3B14760EE6C5D22C525967157A6A7038CDCF948A9E46C6C111F0992BAAFA6DF5FFE507BBCCF1E513CC3D8864368C2114E71C840929E50A226A6BAE22B1CE7F4401030463C1D4EE1F7374CB76DD7254F5D0A5BFFFEF515C12B329C2CD857E33C6D064CC7006C55CE0C951597A3D596ABF6CFD8D058A22DAB31D42DEC13453037081E0B7631D91C4E4A305E3C023646524764D10D337261A0473A29FC4F76CD87E0CDB4EA4515F4924D553133CFAF4EFB6C8C2EF926F1D3BD6A784B1F35209603D8D17118B6241251F219538AA75E6B8D674553112D210C276380D0551ECEB8D271969F65611EA91B1CEE4070CE0E9FDCF1A9D2FA8AAEA09BD3A83947713B301373C7C02E85CEB1E6D0FB52B04EF4081101389C273DD1AFD86A677542E39EB8078491F8BFA33F7168CD7C05D2A9F7F84E23F4D73B4923530487781DF3B3C87408D95EA22BDA440DA6AA5F1E933DEED057EC7378AD1EE173D73DC46C53FC69269C8FC4B214843B7D18F551CFC664DA3C180C3A5EFF5EFA6062642B9D9880D37F121D22CD78CE0C2D982D65E555CAB7DDC5987912A74415D95F02248CA8194D5A776EB5BD0E864D4349AC415E6CBB6CD9CE824265BCDD98CCD319A19082329EA626CA53E8A44E5DC4FEAC8D7FD4A9CC03D9E27CC2CE3A63DA7C333A16A286309E4A43AC07477D6504E4EE6F1BEC4571ACA0D07C46F1B7738099C41CF725EFEDD5A8ADF2E786580740FA0ADF62627DE79CC0D32E81EAE7A158C398907E2875A19CEDD07CAC52608683194C3C860F0BA0EA3662E44CA0D6645575F79B6E8AF47CA6E4ECC4432C65E43C6DE3F573F80CA5A8DB2A289C3BA3B30D6E330BEBF5E95F0D11A6B21FCC0B900DCBE04CFA2F4A57E6ACD55346BDECF666F8D2337909519A6DA55C2793C2579162AA57DAC9081E36B9E0126CDDD4DD8F2DDE501CEAEFE7F30FD38BEFCCF7CF742760A7A30E0CAA630CA7F516AB30423A9AE397773201679AA3624EEE8452319CEACCBB38747F0E7BEF054BA02DE8541329EC3114BADB3D1AB6B5CBBB5E9377CD0A4CEB4D37839F75EEDFDB91CF6CC008C2B3F6F54225DCAF958B1C0C1EDD852E577098088C557D22E5B3108920B98D1FF92774A0DD040F86F418764C939A1820CBEE93596D3C12BA51BE3023C2F7FF7F7C33F9606B68DDE6C74203CADBCEA6CE4713A0EB3916B487642DD9E3CA04EAA12620872736DEA0C2BFAF5175627EBFC7FA19CF0028C9159DFC6BE83E76CF300C2C957D7DD1BB1290B851B1A95BC907C5B7794B05EB6280277DCAD934122713095F0ED007AE8EA2571D4109E86D171691EB82E4C45994A5E041C3F84E00540BA19B63BD0E8421E341048439A52BF241E2B387B9A32BE75FC5E2D47FA1F6F810F3F65963C85DEC464415AD3B9F59631835A76D24C007A8ABF335B91564370A8E7FE053D4AEE559316FCEE747B6CE62915115BBF605EE195D12B29C80374DE879519BBC9CBEF4290996A561BEBA48EA625E22FD17B52E7E131F095ED2C9C41ABB68F11FE78C7B149C3A1CEEF7669AA3B7A13844D351D99B484F1F3B7AEE200EDB126D9F08A7F4C134F5075CA0512AE943F307B7988EA18442BA9EBDF56B643C433E6FA49CFF7674FF626E86995C15122CCE2A5AC86613CC3BB39844853DE2B0C1DE6628EF6C812962265F2E50591F1334FC09D5A90E3570514BE7C24A003D89043D3D3C060FB0ACCD655A71D3CC41B6083BE38455CEF172FA31B2C03EC41B4932B03DBD2EE8365F057FFA36AE5E59169FA48482069F4EEC07543262F8363D6C256A4D85CD2B4F8F05D89A5EEFB43FCB6B032115E52E51D9B893F9741A976E7DD10890AE7B49B67702A226275CF2E3377990BF19E52A4748C33B4A8F660D6AD8EC25C1E2E0AEDCB624889934FCB0942B3948D83AFD25558DD07053BDDDDCBDE886D64CEF5610A1B16FF88BD0E732D0F9139FBA8536D308EBF83807E3237CBFDB8247E28EED61168B744001E9890EAD4E414F2C701BBA3C267B29A4A67421896A25CFE2E4228283992872F83877C44C6F595F8019F5A0EC3DD1928D3020A74FA5150C69B0D45A9900B9ACEF1CF2D6E06E126B3DABEC219043FE4B207EE2B0C8538CD9CA3F94348649F66351864202FAEDB3EFCA47A4258899E24693F30701F3DB745E85FE9DA1B0C19DA145492A872FDB666C759E66693CB274EC215F480D46B75C905620E5DB040FB57D7E4238451FBDCBFA8279E3D476AE8711A2085EB5A1918B11F5A89CD1091795A3232475D34A33F56AADEC053C74A3ECD923D8D227871EC941CC7F026C5A54D7657127245FACA4B88067806B79B238D9D77AB049CBDC32E88F30A71EFA2B6DB80C896A177B1189655F7569373B874ECFA7B3532637178F01C9392980D0804CDB3E1AA49350BCDA7EA3C5A2FE158E6336C59BB67D9EA2A7C5591647AC0C9309656D1CBBEEB2C28E441192D6188D06A10BD36D49FF77495A016C42F858883A20E3AB9AA6B86D40DA7C6CA6D939AA225814E2DCCCE384C4825132B4DCD695539DD34A8C1D86D4C1528AD45655C63CED21154D3C8A431CED4BBEADCE46EC49760C338E40D80A99B18640F60736A5BCAACF015E68BCC8F7291C4BAD034172BBFF8F75CF22F7C9F4E600DD919C28F792FCE599E6E95F497E7F874C2BB728454ABE860DE7FE63958AE76358EA589794F10E45D0EF025639D68199ACDB594BBADB0E296E2252C3DA136991389EC62E663A153333F8282177A9B46627C87198BD089549740CC3E3FC144BF27A7DFF2B9ADCA47CC1508F8E63EC4D4B82B65B42BF9839F90350E44137BD0BBA5AEFFBFE95AB761EE4737625BD3EEE80BFFC4DFCEFE787C1E5AE53374A48404233300B65C39C2DEC638B06BDE30EDD96EAEADAEE4977A3BE5F4D3271A5EEBEA2B748ED2B8D09FDFD79B645CD8CA1DD0D7338E7CE52188B46458540CFAFAF0423A74F72519DC3FD46B5881FDD9BC493E8636E63597FFD3500A18003D127725AFA5AB61EDDA67386F7E97C2E3211E70E6597EABFE8C4142726BB82DE7804E1D57CAF36FF0D5220FA208238F14921CA2F8A2B8C40EAF213968E74797C940F0FAF0287B5A6FC7F0B4D01E34CC9D9FDBAC0D9A051050268613D8B15204272E640FBF6D0A48C7996E5860A4308358CA7A400134DC3D967E59EBE7416AABCD09D9BB79B77B0F0C0C797260DAED7D27366AA86212826EE4F8AABD85091170CC93A0F948387007D2E05B81A63B8275A188464C109E7F2E2EFE028E4CBF699D5BFC3EDA2CDF3D22D141763216328A51650921F7DD33569DCD9D0532B2D49B86FC9D7F470828A7343784221C1788BF2EFF3AA591C4B0EB346920460CE1E0D21B5C9FD9F406D7390A3581B19AAF40A9115ECDA0415D58F8E05AAD86DD46FDB180217A1F7F79E69413047D841FAE01386D0C6DCE06A558AEEF13DA3C3DB42256C28471770087B65F43FE395E09F1034BBF99359864017A0F67EF57A8719A88F7CD7CAF182D33A24C01B2CB262A79C2A10687EA7BC11063EEBE6DBD4CDDA7F48EB1A419C192A063A515256393E10BC2E00EBA557D3158B108CF4A10DCDE792C9F0B00811EED807A5AE4DE2435C9D1D2D812A99415B1C44B08ADCC6F340AD2EC86B78EF419A8418C45455636E7EB70C125D7A8591ABF3256C76B0B136C2DB043F47548398D9F8E1000000000000000000000000000000000000000000000000060E13161E1F0BF9A7C0F63CDCF3F850ED7C5DB6191EEEFE29E498A19F9D89BE4698821ABD72EDC34317B4F8EC2736DC83C24AC195BD55AFF00E797A83DFFADC7970FE53304F16F5DD92E6EC362B9E283E41EBF121FB2FA2A3F60124EF3EBF836AE51FDD55CA9F59B085DDD660724C072B86041B50A3A446CDB20A45BA65380ADF007E005DF2D9AA16A9D22B11DCF6F0B1964F04F45441A923691A15D80DC85003B9AE281F2B5983DD1A04D80A4D9C4372D9820BBFAE3AF7735E7C71E9F085C0A6E4BC107D9E4BA222B38FB236B2CC3A19DD6067BEAC460383FF2BCC771A7F1AAF092FC72C292FC1D5C6FC6B9715F1E1272EB22F8E0B33A2830E31BD6C531677902F6A95CABC3E9C1AE36F77037A785FEA355137A581FC14E6BD5F1F7AD1A5DD19DEDD448B47B558C22DD0FCBF296A812A726E7D1B57F4688D3F577104CFB15FC63C27F7B6051C7AED7D645186FCA63AD9C2D68BFF442466EFF76BCF0E398D2BF54C2CA4CC614839E9BCA48AB2CC53865803710A98D313AFF1DDD06A65680EB83C640052DB807EB2F38ED0CC211128044D331FEC3E6B0B2F3B675C631FDADE62C16D1719278413EA3F8E54BA34EDE7E73F3D94802D2F9CB9794D257C46679A3F00015945903190B97071F8FB55F8696253AA3F39B3FAD344FB88224F5313B43889B768171895F7AABEFF25E21E525EA01A996C764A3ACF12BFFED08F3F751F5CC094B50B325F8B62C7A5B3256964D48543690538E634E5730354358534B65EDDD44A526BB4B15E2042B6210F503EEE06D00D615CCAD10D73CDCBF5264B526674D85C0ED31BA5EE584F21FE6D13F883ACE4B094768865E43099E54671240E8E2AF8A7D7D22335B3974CE860E7238A7C1CA8A009EB51C8636F0659189AC8EF01C871E9008957CECE0A367B63BD2852BDE8690BD74C6D956435D0AB82F94A90CD00FC840DFC7036B84D51F1FF5076CA0974DB6CF25AF42EF7DC8C30C2B04CEB2510E86FFC510BF4C931639478FD1520AD571FA17958CCF8E37F5F6360030300EDE3A33871E9582808BDA2233996C5005FD0C23D99261F570AD9027767F6FC96D18BA98E8DDFC2B79AC12CDA5F2367B4BB6B99A3E07B59882E49A92AECE85339BBB18AB9644D20A3B2A795240492CE4EAF09D9EF728FB82B1DE7B64B5D391251FFB0699335CED8C7CE642FF1A79F04C3EA0DC37EA101188361AFAD236EB218CFBD1D0EBD784CE27DCBA0266DDEB87B59B66A4F75BB44665643FA358DD3D0B69B49F45A752B5C410E2299A62BE4B57B32B0924A069A8E8C15D754CC34DEBB0D967E70693A6FFA58CF7099C2C2458B437C7B205CC7E815F6CB494080F9EAF3017E5FF918558DDE415FF72E954EBC2ED4C20C8ECE38CC916060D22E582D54F74C6C181C2601400110A683F4A365E45FF1387BCE4E152A740136BB762B03A99FB68F6AB42620B2E3C00FA8D150944230A6330409B27E4AAD1693E2C3DD12216C4E2DDBC5E9CBA68B8B5417A7B2EDAE7EB67D25F4EDECBB087F93DC9C927C33076B1C71A2B83B33870D602562ED378805A690DD2A427D86C2C46BA4741F3DEFEB91A05EACE975C836E52868CFFE52CA92F97DE94768161A3E953BAB6A28016782909EC53C02F35184AA9CCBD5B793B525204B72DEB63E104376893B9452C3F2C492F423CBEF1EC87C85788CF3073FFBBCD67FF79BD038672943AE4BC68DA131DBA8D7B41C83B4E9CFB6931987B270C74919BBD40612F823114E4BB148671F1AA62BD2BDFCC8B0B24010EC112E883AEC9746D0F5DE467ADDAF51F8C070A359108B1F91643071438F098233AD9A94D0FAA665A39291A98D14A861905ECDE4755D00E690429C57580DCB6D51BB6186CE72EBB1FA8413892CAFB8713E89775013E546FDA30AEB8AF9F7155C08B25810C80CCAA5E700C124CFF59FA32E0293ADADBCC7B1A99F67E66B28DA614C5A4CCD706AFD05388C65EBCE07A543D3DC1E5A5D1F307F675728D4C629A04E9E455B4DA35236C677F26EDC622C1FBF29568D509EA0690AF4CB5DBB4E418B6162888E43B458774A31324BFD5EE8D2152E4AD43A3007D7D4AF5FDA172C2779837AD3A09E135DE953CE966727A7183BF77ADFC76430666B526692991D3C9DB5BB377552A7801C548AA63F6931D3EE91B875CDBCBB7441A4FF81F86762332D7192FBC2F7B69A58DB6CCD3558047F1940A1CACD6FA28A000B9795A2860394BF05F0120E6D85F96B1FE9DE14E3ED66A31D747924B6FF2620778E0714AEB34B79A5D935A0306E55C36506A292C5DC568403551907E49A43A6263D2915108916F1E27CF3529D1B7BD1544AF83A7CBE58547F192A93CE5C5BC6D652405FFCB95345F522B2D34E8EE0960BB85537A46121BD9A408D283A125EAA745BBAB04E2231C19AE95E13901C69E5C9C4D70B104478F4A70D64F81269A8 + +count = 52 +seed = 3D4607399F6FCBE074FD2BEAB1A7571239D6BE6308617866B65B892EE65399E14DC7FA612CDBC5F7E23116FA86C3133D +mlen = 1749 +msg = DBFC582AE98D8FD326FAE96A1849EFE729A1173339D90C48C3A2B867135F1DFF5B497D05FD55130694B5F9C62D136647D767AE682A0F05C670CEECC03475FFD39E0BD4E45B720D9D7E8DD04E69C969627682AD83F48609F6E66D0BE99064988E4654E3913B7CAF1475622E211BC247B98E5BABA1B804E2BF651713197D8A610CC111BA5FD98A053408AD155DCB756D28A283BF3B20E6F3785DD5F105F8D7D9F2956064860B097C675630EDEE1F17E2EB0B26B6C20E260F9A5915D63F1BE2C74FB0B37013244481A2D0C581C4EE12516E0FD4701E9835C8526A490CB39E99FAE07C40236808F9605A63A5106C19517C3711CA4B9E8EDDC77B242575D904DBE64223CF14A8E39FEEDA9D6C5F9CD0D0719A7EB5EFA71453636F78CAB8262636FF1E136C787E38A43FAF02699C1F260EC45B068EDBEEBBB8A0E08CE282BF47D27A33216856F0C59E743DEB13397656FF17FC4B3C694B189C35E516BE719CDA6542260D1301DF93A5D93EE118F7CB0AC94D0364C9EA66718A4BC7F3D7ACFFA60AFB7100F7D97E98DFFE167D1D8E46C912D41EA057362C13B078CB1D9C443C1A57AC18C4566F5F5388F47A40CA49CDAAF34BD4C9A597FFBF7AB20D7CE88DD76A639E09ADA323C588B08140E9350268C1FF76079093A05CCF5E1613A70E6E37CD257875049A767332E5F7420F319F9AC78F97C0C4FA40B1EEF8C8B48045C78F73584590FE41F9F274DEA838DE75DADE66D04E9D9308CB0A9948320D28D9CA8F1F51E39FF3DE20FD5A2A267D127C317ACD51FB779E597A8DC7359D920548B8BCAD761C6B8012304E12628A2652D12A8161E538C20D582BF567E9C2B46B4CFE2D2DA31120C6DF50DF45C80513AA9EEE9F2613A221AA1D23F861C7F26AAC7813B7ED7278EB420A5C44F2A5879A2F1F9F11E14602762E3389B152C014EA9DDC9DDDE9ED1D6F74E7526F690EF37E71D448342C012E032C00E480A699ADE617434C12DA0E69139D0D9036743B9E2B9134B5086FCB96B193330ACE8E4F77148AD0F532E72E1792795080B54D7172FB9AF1972D00AE24D0B3D86528675B3BC8C7B80598D855B95A77667AD0F671F00039C08CC99F5644BB006BA9356B9C02BC935212C43490C741B0845CD7B4247592374AEAA1B589E670AC62777293870963B5132DCC27088F5DA5B831FA570766FA81C2A07B88BBD45B81992EDFD2A7FE934219B1F648DD8A414FA03EAFCD39E72BDF7D4F6B9C1F31A0A67DF03F6709F2BE0E7D1B1690C92CE7B8C6B1054270D796B16D6E445D24CB11229CB0F92DD81190A37838951AD28BE2AEEE6C5F63DA60A911AE0A24B1D05EF2F814FB30AAE8CA3BD9F01D4FABE5B279142AF948B0E6BBCCF7560107C161C816A0D8E61DD908445079BAAFB78C14F68B8B2BB241FB03C237A4CB250911142D0B460ACC75E6B0F58BF28546A4779EA7342238826F636A510CC9CFFEE8BB0292A58A07694C05672B560B26158A8566D01D0EEA0773E81F3F84376B29CE375FC56A0689A7CA5CE94B91814B62CBB61EA2EFCA0CE6712A941D612B0F700C56B46D464C2AAAB3F64A89CAA8561A1DAB2869D79DA1720274D031946C4C7715FB9C243DC95CCA7AECFF55EBA4044467EB922E93F57E3E39B93876A03936DFFDD2AF48D055C6C188F2F229812EC94F3FBDF7D7DB62E4274DC91718710EEC2CE034AEF266207C5CCBA21552D6FB8DDBEE8E931067010594A9E0CB37250F67281C0A369965367424D454CDD05D3C8F35A15F76B4C8C3FEE42F4C9CAD68849837DED3BE58730B94AE3A5F9146F90E03B4C0836381B3F9CCB5DE6BD2455D241BE9132EB6D4937FF27663F4CADAA9CDA193919F4CB0D0F727F6C7B26E831C3AC8DECC234D79D1B3BD28305E3012A3733AD718FDAB7DD1A6400BC47F47D20F627D2449DBFF10E37A62299E22E408A28A806D403CBEE19AFF6FA9B1814B35B9573ADC86F829A08893CFAE4A0212293447D3086E21BBA28049F3ED383519917B169E8A1B7DD64CEFE0DA643A97950A205CBFF6BD9334180556E84199F0B60738715CD69AAD7C882430578F6FBA4579D908F863CA54D0B9862EEA6ABED31301D183CF465B1A256CBD597A629307A8A890F11C23DBFF895B932E9CD2F5F06A4183D6F2D61117126FCD2CE2B86BB44A9A5B402E3EEDBE4ED1DF11716E91A2302CB72D8F0DAE132E16311C80DCA041694AF1EF63F659959FCAA133D9E5668F94D0489311AF3BAD379DE17793BB3EE8A284529A72CDEC474B3A82D92C6CB21C63017F262E0D7DD47AA5C58F5E23F8A37F00D5438717F05BB974F18A5D3E1CA054EA053C30B34FBFAEE88BC0195F061AC32F5B71B2A8A3ED4B8BC4EDAB40A6396C052DCE72E10768526C00610E96DF38AA70938CF844CF445D8E2BF73C4F32A742812D8C1DB53AFC6B6C0A4BC67C3CF7579702312D6C89BF14E9585D2C624D07FEB4B5B57F8E4C5CFDA69A5E922CC1E9 +pk = 39826162274E46BD7B6694336821B46ABC9D3DB51D8F0B5463E07BFA704155D3943B8AED00778B52B097F3F7BE1922CA3FC183EA54CAC461C9C7A7F9018B15F4ECE5DA36E9E367DBBA9A4619DB5016F497589A98F66A74EB6EEF4639806C0C073FDB74D4FBC2C131474A89BF15056E0486DC15C4DCC59A968CE7070B8980D936D2D4604AD3DE121787F138D738B7113C728E97FE78DD34DB279B40E00BB5704DC24CAAFD7D034CDA6F72956601D7E2B576DD059DF86E3871DEDC58F713702BA7439A524D683AEEFBA5E8CFC53395AE798369A278867C4EA224928297F10D1957D959D2C28ACCD4150EB9567C2E678F0A6378FB1407790A9089C9E7EB24D95660BB3847E33237028E25E2EF72648F90601F589BA2B1FE48DA59474E3A339E3712CC652B3E794BA51E9C1A4C498B3F8DE9AD3F62C3186821EC5EB7798DA5A9EE364ACA4B9822EB2F38EE1365A799577CCED8FAEF78CB94ED5C5617817B6B45B74C5917BC8F8CFD2A83A32642306C4DFE08577BBD3DD831415A772285B2541D3E421D835246D74DE53C03627357CD606A2AC847BF7352313321FA643CD4ECDA5297E1BA5A47D8AFB9717740E4AF35CA76A680082E94AA35EF999BEAF52960FE336B9FC8B39A8AE5FA6704705A086265E82E63587BB69C1E9C38934CC02678B09AA3F565A7F17D1F55B53455E541EDBB992A215CE3EC9A2A6878AEC39F2A378DECD9B7A9136B2F5BB889D689BBD38582063DE0EE2A41A7E81F3CC62ED8D77E6A36A96998C16CD20D37DC19743D9417E2937D84BE00939FD6F83662A4F673CBA37A6B5557495D3C51EF24DDA08D448D44F69C13E83423D71735EBC27C4972EC631FAEF7EBB1512E5BFCD90ADAD28D8A5B8AFF886F7D9C0887A00BEA671ADAA7E330C8BA9C9E412D82AFAE61EF2AEE637559D0241F356FA1009445AABC60FC196EA16B46747C0F9DC863DFAE08108F5BB239DE0D795C39D7C98697217D8F672ED18B1FBEBFE86F7A348E672F40E7B6C61D0EBC913FDDBCE71FC19060817AD2779C35928B46E859BFF91D35F04116C2ECF8EB3C09D6DB8080674554EAA851BCFFED226D1E235CABC194457CD1A546A884443025E3CEAAA44E567F31B7643FC048859393E56119D33CF921D1E52FDC0DC56C9471008D77A26E146C55A9214A00B244508CA466DEE09FF8A23F50902A61DA5CF8FC5BC477E28B49FADE5191A52A7AA3A1275B409559FEC2C29F945B4922B0174D5FEDCACF7E800EF1E452F8E600419CFAB4342B664B85EFDF9495B915230D71ACDF42F69E779B0E207F405D311B4288834BF774E5E7863EF2460CCF0EFC627E5497EBAD39858A657CF5214D0B9DFFE9C0F023B752AD1CB4F5AB4A4DA776558F98ED09BAF73EF85DB7FA1627B7186EC7024FDAEB473CBC0FEFEFDC83B2FD78BAF44C717230F3A9265C2078161D9706DA3051E30010A04E3160079EE4756DCF9B666A7A0BD80C1DB42103067FE39BAE3438E8CFB0F46023BB64975D7A00E93A485A150AB7268FA8EB8D77D0437061BB7871515E37B4C0562BE6F13CD96625A0D03D102D4194F95059409EA72739D106D0302958AB56F232E6CEF360B5FA5E445E78900712AD600D40FA8E2EF8BDDE9C79ACFC08C4E98FDC1F9C816CD3E437DF870051FDB02713B2530AD33E3DB3507C1990A5669632E307F71EDEEBA0859081C0AAD1FB22E30FE8291390EC5E2E5FF1CDE50BAD8C545BE3352C2B519920731DE5893ECF7563F085F815B9C36CFFF9D27CFE54F26659FB4916FD9D09EC8E8188AD0D2E0F1D4E273AB78077CAD5CAA5733184B47B9E7171F5651FE58A97F7E5C345223B2A642E15F785FB913E4055A588F884A8482242FCF5CB32F02EAEBBB496046ABB5041AA32F65A317201179179572FC1E0AF2F98D73470B74A6B36649BB332BCC05A3E2F2A0DAEB0B8AE82F382ED9D18E3446FC288165004A983D40AD9AA1C38C19AD548845E10AD1E2E5B6C5A870CEC9DE83BCFF054E2A74916404E5D9EC241E6725394FC7CA5D80935C23B1C0443891B28FCC802A33EF517BFB3AAFF1340F49BDB0F807FE0B1130C8597E9A7CA2F02053DA27A48F965950476DAA85383B5A9C4F5BB2AC6345DCCED0CEE2191C8A90EBA0CC391BD0884285B5BFD5A57644673D4AB6186F4A847F6FBFB71FFC4B8E881DA15F4FAA6EB7E2994D67D6E3844DFFCDF34CE6F86D1260C2235B4D60D20577BBF13EFA959365ED38844C0B5D323D64AFB80C338DC51FAA2C4C1AF607FC3DE4167C052D3F4D81BA1A6467993DF44C87CECB9A62074A8057ADB6960B9BBB4F1C6CD1685D7CBC951E688B1447154BF65EC0C9781C3B04228DD52FBC7D4DED575E39746762162F22E6DB4EF4AEE5DE472B89E0304DA770B3E2FC68E92984EB3EE46582EB90A59DE5565A615A1FCB3C9A3FA84D4F5FB16DB01172C2BCFE5260376D4B587558B92DCF3C3271BFD9671E718DF0841E392D6D2E251BB7D1DB408BDD4A9E32028B56AA08A62186AF95C626C5B43C95A9FAF6C161CA7FF1078DD80D8D44BC03243FB6DE07137B582B46F410113A2BDCDB3FB0F2A1D88168669002A27F6CD74D0A572E44A699C6FF0DFA283737EE2007E6B6EB014D23850463F2B8A28D57D9BA733AADB2278AB695E83B1BE7E3F80112024D5AFF9A39BC85C3330E3B0BD362BB0C950533C87366BEFD468C39648C6E14720AC7E1B7CC7D989604103415C31961F35AD41CC03E9DE41839FD9DB02FA368084972181E34B70A5C25AE0B18FF164 +sk = 39826162274E46BD7B6694336821B46ABC9D3DB51D8F0B5463E07BFA704155D31D5EE2F6E381A305430D91980431D67D37B805F6A72202A8987B93A3610DF5353C8369CE5A4E120B75C75242A3D6291CEF3231D804643445ACB69EB95C4A9745653C658F1F46DA9B90B5ED0FF6A5BFF00156BF320C9E0A99F3F7CD1310064E653157467474382205826052476324185852755762514213876884567177060537842873033613767540467325735316381480376136303031166804868760254764368273512256464315415046168601722780817476036320541777670550515600705161681552066565413011238442448561835042638052638321841102086621205752772133086360751743653435086086552607213410231634110431585434388354253472677432828403334352605778708172625752075524568086128735536574771738158303006235030238402610245874032823500845421473678120522521152786022014854156362746137231435351247682481060227404766058233717416532763331347755740046404333383347716828281111807642643831180887455622744813568858038172501866270323213880476263406577418018737501485647173543858886458176664472562585776436140356715427602755860225741106017485754743403688870855135705880882216113657428553402616161281503170210015701271732848577274652860423241545810844250244047053708310837838861423302556884751042370333456536182014734842701432154630143080583215215247860322843513784571027511448276716353037075811408010650427400535037715163766028346277318481540588033170853076881110254518747773606641868560725882165325688266046027231546505455628537804322161548027312070521725734831834013334862440636135862046605775731276211640268662357341715304070201760048044801153224781336518773617050605163114362807853247546744358445520102764145364036772766301171233283338770755253553845377536177423646787500311707242626483836553865562448466431437052241312571252646106762716180688738616373088612206735251252140541865716536031032435735822243807463748257231253007786540151411746437113565574326553862372873162766754460271534164608582037274771007353283308356362067856648101233747107331420437014575338207102852346737505446586743216220838475227847203367721680148323401325717867144575016263217282873886421025682355513330188448824483651228546738274525217332577774374283540674411643576283062482704000173644534660488617244615251401316776835050464557865125352633687414685732582235727853683001775612126817134708528101502038842625676125721083823837860374802382347731452470226431781344741702884765363082743740245025523445723075318427585156327145214332380350700483621488658661023784231803246777801882464367727787250674662315561634651258351852520063724021603308572527211561438187025545807733157184345747644048856783118881061558834207456713482415146451581424327187816121603570114482118283306767887478302784162830563330383310465808171687556330161573735732675717602027108376118516851533076125758048541877324770734611528537571631012777537687532082233200341485673147018261658244756031056566156168400722181125746684366307144644212658887584583101146386052135045666282348368288806832718331155106374450824225677558560456443548203116257383788865406023374635000122432307363488304271508304165820804713557585210332837516544444067803866185533818116720563031153581833503206080757707F7044C801180D1D951FC4EB207CB98312EF0E50AAE2FDFF3C1BC941CDE30A48154734BD1788835C5B5F1C80FFA5B64D46A3F01F1070187152EE1AA59A2D5F5EE6F81EAAEB23640A35336F0E6B9ED590EDAE4B93E404B97AC10D68A6840BE24ADB8B31D005D4F2EEE7D777F810C1742E10E2804CF6A1B20552CD27FD7C52FEB8EDAD4C98F20815F74BC1DC38AA375963862B4B496AE07610B8201E1664809DAB7CF32108E47561756DC3C54FBE022FF38DD4BEF4B1EAD40F3124583BD29672A97AA25096EAD970F1B475DEAEF9F571E4B8C1EDB97EEA80487B4BA7875224CA5754BFE2F686244CA4A127C2ED076D97FDAF42CB3405C8BEF712ADA9266A4AC17D5B39388D41E2A0E322B2378CFEF0510F7B02B54EFCF7DA32046FCD038ADC7F3C5F91F39A0D237E334DF7FF2420A37A3ED5C74ED80BEE6FC3FC1E9F0302941B4D5F30B149026134738B5917BB05E0280998E609772C9E8B72EC1EA85E26F8B9B049FBD74400A46B69EF03002792BECF510686178E36E5873F200A2C16352D8F3A27C0AA7615BC317A9434C258458553B5409AA3F700054AE92EA4E7F174F02E3D9BC8961E3A4B5659772219175644909C1736D50FBAD86DEB0AB66CB2A986C4E74CDEF77E8F6561F1F295B65B5400CDC420235D7854E4C6425E936FC191C1B40CA60D9F1D16D833FD9EBAC7D5DA676CDA2FAFFC709CC3B131DED13721D8D934629986388F608F358046C5D96EEF3814A9190553F2AE5FD88B56228F3901059126D12F46FA1F3641F2A2069D2A060133D1C30879731E93C5FDD63A44F274F48A151B7FF4048B9AF20B6081070397D9EE02AA61BF9FA8184BE5101A6CD8AECB171AC8303A3F5DB142EE83E3ECA052B582FB688E31C63E425E6A9A9EEC3CB34C57FA07A8B2BC6681B2E30D074BC7A7344DADBC4590AC0563DA3EF808B1CB44F982C389581E4196E65F278DBB17355370C12A736A118FEF2AE8251507A294D5236EB90044965F0AF70A086FF766DF4F4C0A4A101630A436603C5A3F085B8CC6EB177F15E002DF919F7C9F72D7B13223ABB51D407DC5B18C3EFE9FA3C31B73A05BE0FDDFB30DB9E581371B59C8B2ADBC1CCC4124650BB9C8ADCA0F55B40EEA0589F9146D8D3FCEF9DF065F238FCF0E9A03063BB743D45A62A3C76866242E92AE1B7CAF1C03755747C188B0D97FA78A6D209DCCD7361A19600BF67F26449B6BE3D76E7ACB8CF93C005F73D30738E2402FC577F6AD34F7F54A2DD7B042C931F941166D84C8609AE05B3CE2251CC8562D4FE3B35F935B1DA8F6D125657677057F33C26BC01BA8BB9E28B6A594F782D71CE7EC0FA2DFE36E4B95D5DA88A2A985F62D7DAAC037C8385E58431940A277F42159B79A226ED1CFA5B9684DE524013172D8807A1B5CB5282C043348DB96AB5B89789F7B7A09EFEF25D108A9AEA591F2F76172C3883EDCEB7EDEE0E3F905BA8ED5D0FD5D11535148FFBFC9D63073B3C1BF6A43BEB8194962F6DBD7B1F6A36154F61E65D3ACD0353816C82C63E6A1B2BFEA5FC6AB7A17CC74B5EA9B0AF7BFE757856A5F1E1B2049E718437B98496479FAE33AC619AF2393E71DD082F5F9ED01FE518D3E1DBE90C631DF7173267BC660E3CE0502F95EDEDFCC9134378DEFEB4AF162357759B705D8841D8E9A9A3642A29BF1DFD6D8471C04630503962B5018B323430A42A23F804DC3236F738B1801FAD2F8179B45577AE5C862DAB4EF83A75F5D2D6E07BDBA441665F7DDA78EE2963C683C6E5C8C495762DAF4959BE971165A0AD9B63B2C2325C29B522102B91A4187FCA583DFBD9D022980DD3DED3351D4FDE12504BD76DB92776BD7ED8FABC66FA4FAD66CD4AA821C4A146A803D7238D7678F9A1B501E46770308121D8F1C230D7E2B4BA935D03F8FE33814F7FC479DA972FC4F39C596EE6BBC11E854C85BC3FD492C350882B91499B80C87B3F8D2641F672D480B0181F696E89297A36100DD39B4730DDC4447613AF7C6F5B633F11F456A12C172E43B6EF65F6F255832E68BE4837EF34B72147C210229933EEFBFF2CA7D9DD1216C502F1C36200AA9D0B04115011A27541C4ABED3EFF216902F1636E04D46B1FD1D740C4CE472FDF95F408963C54F9595E790450ABB183A5DDDCD0468F313B9B90E423B114C09975A9FFF38F0702BB7172588C171289B2E5E9A6967AD0F6D03A24FAC31CBC12EC714CE603FCDF919BFCC4349086CF53D9802BDDCB38B4CF9F681F867F4B040530B366E62D02ACA681180684E1BB7765501FF7FEA68B08692D4F2286692BE6FB948067993C5D91032F9B8A50B8DB0B3DDCF832EF34D5547BC8F6A99A61E593707F35968076A0ECE5B7AC62DDA300C38C2A3942E100DB80C2CB361B0159947E78DD80CB7FA8B7D34128FCFB8F622B8FEDBA8E102F62341841D0C643FBCA3EC34DBC2531898B23C15AEDB7206E731076AD3F11F1591F3FA362219117A53B9B22775D2DE67D750174203656DE1BFA2F0DEA76AC0A1537C898A060421584C0376E980C9963EA4BCEC1958B7FDCAC455A77D91DF54CE876F4BF4012CD45A325D19EF9AB42FE36EDEC0FFB18BCB06FCD03427AB3A8048C00590D7BFABF6B9E118A8C0817A9AD114882F902B4E4E0E085822418483AE646063376DCDEC0CA21036F4CBF3C5340E82DE41C1D4A8DE78A924F0A70E97C0B20FD4BE3247EF5C3D7485752EDC476D52803A1543065C8B8AF3872164638DA8AA0A95536340D5533A2CDCEF97B27545030F41686613191164F471D0D3734AC63D290AEF433494115E2105A5AC339BE2E3028D6751100D415B17D690D2F3B0B9A01C355BEB863D8C72FE63E27145C1CDF8A728823A06FAA128840E68A82E1C7085F2913AE0571B0CE885839FC311702ECD52D10318B14ED743AF5129EB43F99BC8413777EC1F8852729424022146A8B002E8DB8C1096C5ED4C43293A19C559BFC14B3CBA1677714615EB38D4CA6248DBD0F1BE762DFA6C47A8784ECEE34E13F925E09D21FB4AE2E0129ED0290B27EF21EFB7524629B6AC93BDA74085ECD3B27E34BE8486FC00EA8926376EB8028FB11370ED016BD86B0F725F601B5F32A5C955E6BF0042F5D129C471084495BF30D84A23598EE933548D44643E8A44EFB794420D265A364910A180213F26EF4D99F5410E1D24DDC06EBD041F6A4DEA99EB3C4337CE860341CF3ACF114262FCB16A3C4F5DF6AEF02C853F6D63CE7F443AD2367CE23E6DFAB5857BC18D170F86CC2D2BE8BD07AF68A8CA18570B907E7B2D6A01D67323E2207954836D27F6F38730C77BD7A8C9A2EE17010057E1E69DB6FBEACCE0E53A0B0388D90C0B77576FB8BB68AB5625D4249DB2BA2E0F7C87AFE1257BDB1C50408B9E1610568A67BA3037B206DE80C79575100BC489FC80EB4652E3713A674B9CF0BC75AC167C1EA5659747612B4B76641FDF2B9FA3A92746FD81E26BB1E264E97F5557F62C0B20B6F5D30AEDD8293E8A2D02C15C2CD054A10217D6FBFFFCD59A116317D7ACC995475ED7E688A83435C93B91E6326D3D1E34E +smlen = 5058 +sm = 73B2BC23C82F67936C8D20E468C34341029AE8D6C906401CEBC85B795863EB27826B7A89FCF9EAD244396F9EFAEBA3E576D64FA93C6151C64E74DBB6EF35BA10E72C9208EE267C59CE39BA4A59C8E51A24635EE36A4A5A29AFEF88CFB88AB24B189EF8E7477AD03F93F77768C011D3165E0B828D82B0B9ACCB2165192852DDB4109B2FF2F407395683D38DD88998F1B319A977A542DDAEB32B6CE2B035868355BC33F5A04EFEAD7D0FD89C4E985573AF36823B1FBC06DBA2FAFE19CADDCAB04E6FD2BFCB4231C0BE828B3D1CCD53A17ACBAF872B698DAB2537AF731DCF8019F1A16189FB2EE489EECFB1BBA324B71002BE80EBC684EDFD1379EE86ECD9238756E0A69327334DECF921766605567048E58304317067A36C8B3C9027AF3134F8C35738DC0BDF2DEB117D6587FBC5D1B8EFE16C0AF306B0785A74BA3A5A24B38509F8617A2618E4C6A699318479770E67731322CC0FBA88BFA4EF503B13FA241C1FFD52360A5EDC081D65232BC14D91D3CE86B0A191252B8087EB131D3915B0E080644AE80519B5BF0C3CDFE874FC2D59190C36B810EE56673017BCA2051953ECDCA216F891F4481BBF1DAAE8D970B49133D1C532C5821C3F74FADAC8CEC00B5B9EA04C5038B86BE546FD35BD264413D723C99B80FA021A9C6C4A84688E02516C89EC441835B35977F34C0A59636FE26375A36AEC0C4A1E969339636C22817723183E9210A12E746D439DCEF0179950FA994EE4B8F570CC47F8C7B59C9E59859AB8DF994929E9FF0640DC2DD311FA313B6230BD336FFA0EF1EB4A9F9F80E8E9CAE38B5433425D119B5E02BF9BD57239C028173E9A75F7FD4E4F59B7AE88F6FA3EC7228AAE2BBF90815A03BCD4B658F834B026B84E5EF899D301F5A7CFC6E2AD27DE2A1DC471C7BB2CCB3AD24D60EF80B95222A19D45ADDBEAED9AB5DC24A94887D5022E7DCC1A03DB2D602CAAE7D399C5B7C19853B72991FD32DE0D205EEB8E2E07CB2ED173348772077C391F0454233617A7AF368794046CBC396941DAA769BD2CB81969F875D14F248A78EE8ED4071BA359304EBEFDF8C0B1F8C55F8BD4ADF0BD0A206899FEE171E07A888EFC2B8A55121D71BA5339FB91336C981CC1C576BD5800A395FFF169AF978AEEA4FDF80CFD13504047CC2A2A901088C7394625802A0870507D25805C162BDA2D178A56BECC42EB84D80C8471C19CE4BD5013E76BCFEF817DF1CDF09FDB5D07D353AF77373E0721F57A4966DE9CC2B6680B1695A2C097F21761C88B708F73D907632D9144CB5089ABB269D9F8868853352F610BD341ED23C1D8815749D490A693EF008AF4EF45E7E892135B5D95F70D420D1BDE27DCE7FED22552A56D1375F2E72D779D4266019586B49377422581ECFB2F45ECD0B83F60238301EFA12BC5201949955024A431BB312328D27D17A1FF80C73FB87ACD83B5C3B2F7FAD611DF2286B02015059F4E7F462E7C55BC046B9CECDB19455810CDB8A826171665BECDDD34834C0CB1652AB5396A62DB915091AF08A9F0109788EC0E2D5633CC9106283D0293967D372CDB0FC7229D8584E91A91D9DB6E96489CC8282D33525C54CBED94501EE524DCAB31B5318238BB00F7408E9700A6D42109FC6AEAB43C52411EDD5463152706988892DBC27FBA7B034B56B6DEACD177D8B46E07D5B87A565C6D2E9511E13E321F0232E183BF25FA51A615B9B15CECC02E2B4AB9BB7CDCDC396636F358F91A6CB32BB0D256EE92A70FEEE529737F49F51A000E5C0FB7EA0F07574B81882C98FD50D3807C8C6AE7CC964FC89D0A32EB6D826172D1EC8729B95A24FDC09592CD821716A6D82FAE39D0BC62A94C73B08D6D7427A0F4FE912696D213FC083CC0F58333EA79C3A669FF9EF23439F9674E64FC1F8782D95FCD2BDB0450A7175531FD8D183528E8B5D4D97047700167AE2C7602A9F9058B815C014D320DE71F22213B9C61A2A0655E4C01DEC2E53D4E251F5792D949D14CDCD4E78296CDA341EC62097F3A87201A2A89AA1E1448F125E78DBEF0E8CB114BE3BDC0FD2C273B97BE1F050724F934C7F5AEF13562AB7CAFC04FDBA69720550A41E673972E5103A3FA77E767E964F798C7ECB93F3558A02BC0D5FAF3A8001FBF84E49D79ACD9ED4D0C916C3B904523AD48BB34C68A4B25B564CD3FA97B4AC055B442F0A4757C481DD355D16E32935DBAB6128182742695AAE0F60CE51A5EA4D21334495EA3E1D0E226586ACF6B39698F587E1FFA9878BCB13EB9F5B780482C42663857D5A915B32F26389F9F258ADDC80DA4E0799C39C3211C691BE7396CC6A1F4D75B437D52A4D07FD1C9C33BBE27CBF3D1DDD57F646B1B4C4E058C1DE6593A68DAF7E71CF1491338AD6DBABABE08A0463EF68898F81F2D108AA4526BD06D7B240BCC9AA6BF89FEF0CEA4808A2E2A7950D974A52838B78A425342AD8DC6B944ED8BDBDA99D4E644A307C2DD7E03C7C0544DA8DF895FCE44AC3329D6306041FADC4653BE1695B19250CB3259B8BCEC0743502CA54DAC9017901027D4424B3A83C58678382D7E7FA6867A7694EE045F4D4CB57C541416063761265920F005354CFAC3FC9ACC745599A6AA0E6C235623BDCE1111BE258E57E000048148BEDC237FAA1F717F2EECC048C220425834809E57528D975FD2C46D4E65A8C5A37BFAF43FF0A924A229B176F64503C9C98CC5C0B0795E593C4D0DB0B44292C8C76074A60B54BCE44F3F9CA84BC21ABBC1229B0C27FE5F3098E5D9A4D0E024DF6EA30BD64E35A4B06DD2D36DD95CCEE98D2F469BB3D979AA29BFC015E77849ECC7388147502E4E15986A7CE0CC7AE03DA9A70ADE17138EF6B487538534A00012C2BD6904975BC210098A99640D9F37E73F9651D81929AF7E78A029BC8C529F36733F9C52D457CDDA79E9ECC04D041AA770CE68535A55CFDAEA4F3C9837BFEE318F66BE7058E6F2C891118BC97E73DF09C967BF571618931035A8C25B140D74912830935D278F850DFCDF8997E7B67806DC295DCCA8FF47D2A159D5DAC9359192383033ACD6C3E2F090392B866F469CB6E4D13E76410053247CA2CAB0BAF350E34D58FE5ACA390139A4582C979790E123D130F7B1732EC38E611799DBF3C526A84BD098881A6B28A50ED08CD308FEEFDEE4919940833B297E051FDCA6FE16952980DF836F12E6AB2912C66CE50264780AEDA1F1127295876583D9A4385A686808C8EF7E649D0C79E5AEE6108AF62047A50BB1B79E6EB85EEB142F0EA28BB0AB84569BC5E4BB53612B06CC5BC404DD789A6600617634FEF5BC3AEEE13896F085C9C480D46EDEEB04DA4E53753026619FB43B08C61D873A9DFDFE8FA6EB6AE6F8A294613FE7BA87523075BF2B13981AF858DD58ED5631B578EF5C0EB486DE4A234ABD0651AC36BB596F2DBBE396908B7969F78D53E17C56A9728E54061076F110C706C3D70628FFAA58787FAE0CB64E87A2893026138D28EED5B9B12BB1E8F5F104AF4542C75567DDCE59A6E3E0F03F1B807E3655B14174D9057B09F3EB4E3D37D08D594E3F5B3781BEC1226F9C438CD15F0681B34C34138A5C7E001D381195E1FD296BCD9A09ACB2108FE868BB072EE51A8F7068695F7E122509BE0C9FF327CFB436F0C7F991FA3E7C18B7B4D51B69F0766FCC7EEC9BDCF107410DD26908332A3A482185BA1C111EB8B6FFAB6D83AEAFF9218437E3740F713F52F060969FE7ACB50B06F7E289DDD6632F7FB04DB761DF6E28A2BCF549FDD6406C8FB2B60CF1B600B5D6C1A4297FCCF0752B457DC634215871DD8FB750F96B1090F2E53E8FA073B92E9CCBDAC05A2C01662471E7DF242BC9984607444210A1EDF3536F1F496E89AD709B703FDEBE858A5D7760E81F3F12A4FDD2542221EA786BC485E5ECF780414B75A4691AA0D98671AF4A64B804668598961B5E2FD32517595599A07A38FD956922A7409D4F9F570FDE240C94A1F6937BFD51F3EA1E2B91D29E929BDE488DECE9819DBF9F3E872D9C5826A82EF29E09B7A22443AE8594E4F141A0FD744224B3E1008DEFD443943E8DFA7015D7209558CD7848B6FB5C1C7156ED236EA422035A3D29CDC456A7CF686BD791BF49E3ABB248E2C37C1114FD2DF557258DFF32362B9B82C6751F22C9731CC01F2083C615DFEB792DB8684A1D62D7FA37985BBDB15C33A8C8BEC01C36293F2D9D7B89E413EF78E551D6B594E37789E8BF96C1375F1425083C43F5527C75D53D5D49C82EE5A931FC73B07D39FABB7BFE4ACFC106990C897A88467E1271656E26CAC51BBB171E82F74BBC8A39677F42032A15D3EEDA1F3DCF94E4D678FF05311F57DDF8BBB609CB5ABADB27EC7CD65EDD8F6C464158FDCF66F375CD8D49718B2AF696A1F951F2F186C4AAE9871583D865B57406962BAF8C0A3A7C59EB74275F62B2FE47BAA89E1F98C2BB45B287F90F857893C8BB52EB37B6E877FB53AD65E8C30C864F48941BE6E45F099970F0E9A4AA5E39ABA18C94C2CACCB36061652438E8C337C88061C361CB6273ECD8260411D56DE38CC835296E9DC089B4C1E02481E530D892293EF87765EB18A88B2603CD256582A14ECEBBBECBAF671D362D2BEA346CC3A8768951D2732C024F0A3C6C90ACD5203B7B86E3EDFE4E5EB6DFEDFA042A3642548F9EABB97176788CCACDD263ACB4FA00000000000000000000000000000000060D131C2327DBFC582AE98D8FD326FAE96A1849EFE729A1173339D90C48C3A2B867135F1DFF5B497D05FD55130694B5F9C62D136647D767AE682A0F05C670CEECC03475FFD39E0BD4E45B720D9D7E8DD04E69C969627682AD83F48609F6E66D0BE99064988E4654E3913B7CAF1475622E211BC247B98E5BABA1B804E2BF651713197D8A610CC111BA5FD98A053408AD155DCB756D28A283BF3B20E6F3785DD5F105F8D7D9F2956064860B097C675630EDEE1F17E2EB0B26B6C20E260F9A5915D63F1BE2C74FB0B37013244481A2D0C581C4EE12516E0FD4701E9835C8526A490CB39E99FAE07C40236808F9605A63A5106C19517C3711CA4B9E8EDDC77B242575D904DBE64223CF14A8E39FEEDA9D6C5F9CD0D0719A7EB5EFA71453636F78CAB8262636FF1E136C787E38A43FAF02699C1F260EC45B068EDBEEBBB8A0E08CE282BF47D27A33216856F0C59E743DEB13397656FF17FC4B3C694B189C35E516BE719CDA6542260D1301DF93A5D93EE118F7CB0AC94D0364C9EA66718A4BC7F3D7ACFFA60AFB7100F7D97E98DFFE167D1D8E46C912D41EA057362C13B078CB1D9C443C1A57AC18C4566F5F5388F47A40CA49CDAAF34BD4C9A597FFBF7AB20D7CE88DD76A639E09ADA323C588B08140E9350268C1FF76079093A05CCF5E1613A70E6E37CD257875049A767332E5F7420F319F9AC78F97C0C4FA40B1EEF8C8B48045C78F73584590FE41F9F274DEA838DE75DADE66D04E9D9308CB0A9948320D28D9CA8F1F51E39FF3DE20FD5A2A267D127C317ACD51FB779E597A8DC7359D920548B8BCAD761C6B8012304E12628A2652D12A8161E538C20D582BF567E9C2B46B4CFE2D2DA31120C6DF50DF45C80513AA9EEE9F2613A221AA1D23F861C7F26AAC7813B7ED7278EB420A5C44F2A5879A2F1F9F11E14602762E3389B152C014EA9DDC9DDDE9ED1D6F74E7526F690EF37E71D448342C012E032C00E480A699ADE617434C12DA0E69139D0D9036743B9E2B9134B5086FCB96B193330ACE8E4F77148AD0F532E72E1792795080B54D7172FB9AF1972D00AE24D0B3D86528675B3BC8C7B80598D855B95A77667AD0F671F00039C08CC99F5644BB006BA9356B9C02BC935212C43490C741B0845CD7B4247592374AEAA1B589E670AC62777293870963B5132DCC27088F5DA5B831FA570766FA81C2A07B88BBD45B81992EDFD2A7FE934219B1F648DD8A414FA03EAFCD39E72BDF7D4F6B9C1F31A0A67DF03F6709F2BE0E7D1B1690C92CE7B8C6B1054270D796B16D6E445D24CB11229CB0F92DD81190A37838951AD28BE2AEEE6C5F63DA60A911AE0A24B1D05EF2F814FB30AAE8CA3BD9F01D4FABE5B279142AF948B0E6BBCCF7560107C161C816A0D8E61DD908445079BAAFB78C14F68B8B2BB241FB03C237A4CB250911142D0B460ACC75E6B0F58BF28546A4779EA7342238826F636A510CC9CFFEE8BB0292A58A07694C05672B560B26158A8566D01D0EEA0773E81F3F84376B29CE375FC56A0689A7CA5CE94B91814B62CBB61EA2EFCA0CE6712A941D612B0F700C56B46D464C2AAAB3F64A89CAA8561A1DAB2869D79DA1720274D031946C4C7715FB9C243DC95CCA7AECFF55EBA4044467EB922E93F57E3E39B93876A03936DFFDD2AF48D055C6C188F2F229812EC94F3FBDF7D7DB62E4274DC91718710EEC2CE034AEF266207C5CCBA21552D6FB8DDBEE8E931067010594A9E0CB37250F67281C0A369965367424D454CDD05D3C8F35A15F76B4C8C3FEE42F4C9CAD68849837DED3BE58730B94AE3A5F9146F90E03B4C0836381B3F9CCB5DE6BD2455D241BE9132EB6D4937FF27663F4CADAA9CDA193919F4CB0D0F727F6C7B26E831C3AC8DECC234D79D1B3BD28305E3012A3733AD718FDAB7DD1A6400BC47F47D20F627D2449DBFF10E37A62299E22E408A28A806D403CBEE19AFF6FA9B1814B35B9573ADC86F829A08893CFAE4A0212293447D3086E21BBA28049F3ED383519917B169E8A1B7DD64CEFE0DA643A97950A205CBFF6BD9334180556E84199F0B60738715CD69AAD7C882430578F6FBA4579D908F863CA54D0B9862EEA6ABED31301D183CF465B1A256CBD597A629307A8A890F11C23DBFF895B932E9CD2F5F06A4183D6F2D61117126FCD2CE2B86BB44A9A5B402E3EEDBE4ED1DF11716E91A2302CB72D8F0DAE132E16311C80DCA041694AF1EF63F659959FCAA133D9E5668F94D0489311AF3BAD379DE17793BB3EE8A284529A72CDEC474B3A82D92C6CB21C63017F262E0D7DD47AA5C58F5E23F8A37F00D5438717F05BB974F18A5D3E1CA054EA053C30B34FBFAEE88BC0195F061AC32F5B71B2A8A3ED4B8BC4EDAB40A6396C052DCE72E10768526C00610E96DF38AA70938CF844CF445D8E2BF73C4F32A742812D8C1DB53AFC6B6C0A4BC67C3CF7579702312D6C89BF14E9585D2C624D07FEB4B5B57F8E4C5CFDA69A5E922CC1E9 + +count = 53 +seed = 7031BA806F4D8BC28529163B239E0EE836871C51D2D62B601B71D6F2B69B203C81440F8FFC09C3AAD94DB1D880160671 +mlen = 1782 +msg = 6103E5B22F934203B5CA87337095C9A19267AFB9695D309BEB8A557BB7CC90332C4A03E1D416D397B945B607268F545928104CFFD71B02864E010B666CFCB68B762FA5EC839B5AEFD0407419441B38E6D881BD5218DF73C675DF101BF2C53D90FF86D4A3C7DB19EC9CAC044E0467A36337AAEEC32217FAF86CBD7BC2B663421754CFF1200A8A66E18F812868BC8D1C8CA495E6462DA4B8B96D4167F040F04927A7C27AD35CF174D42684ED55AC80D14CBE4CC2570642DDEC4F44880D967E9AF77EE27D0D3DBAEC9067FB6FC957AC4A136C1D564E17F59AC4938D43FB9050D810989907125C47FCEA6C162C723E79F68339CD1B3BF596988BD6E215271385CD50616868C6BF40FDC34BD30E5A00773E2C039723F2AC3A3FA45F4CE870841762D7435BD6CCC5FD3D58FE059EE455A806FDE89155C84797FBB73691A1FC6921859E99066A3239E31F28D1A46100DB1917621D9E61473CF1E71F9850B584B459D5690941E676A7DD56796313ED9ABDBE03DC75AFC1430DBA27FE0F8DF48EF7C339F462AF1A6D30A5F8B480DFBBE860C4C0BC136393C8FA0875AF454273C3CFDBA7EEA44EEF1A4060136948CD98B9D2C19AEA4934F3455F31DD15BE6545134F17A195B6BC409159C0975E592A15E86CA4943CCACF4B46719A072DB8C629B67768F1956F8158F179A0B645320489DEE404C8D0C4E786CFF39B324053F102C118E7D51173CEC0FDD017F213B2B07AC6B2C7DEC04172DD5396A020EDFB74ED86FC31952D241A7C3D139DEF543D90976AA70599792E73CF73AD0BD4A359BF60DFB2CE96A784D8DE5E23A95E831CA6FFBA6B187BC5F29A7757185EC06AC882572EC6283A1875B54FE4F295E1970BF311DBABAF9F894D3364D68F529C4EF9030AB934BCB09459D5AAC61919946FD28DF1AC85876F979E8B8528E9BBE69F03DEEF136EEA6A8FC86F31BD64285C8C9F49ADF53A8BAA7867CE52E72DC4A63929DF3BA2662DC77D71F88D8AF42B8D67AD54884EE11F5A6B3B794F7D5610909B0B740937587CF475DA903159994A262B6F32A3D1723FDAAE65E636B71CB0EF0A744F359BF08AC8231ED2970CE8C451266F703DA3B57F85ACEED4C1C174C50D9C226F028E972AC124FAA6F60518699CB4C499220EA51A538F9EDE67D0E98E1BF8FB4B24B1D8EF50A28A93E20076F8FB812CDAB04871D331FF434BA66DD4577B18DC3F471B3E96A174B58A7AC2470EB8463A71FFCBA2D064470FD2D4E15F9491DB09DF3E3BA376A3DDCC437312BE5848DB3B9079F2AE046798473BB970D725E1D7C6FDF405AE387DD7CC1735A7FC27D1A476592A514B87C9017E1E5D37E338F37916F3C72C5F2AF75185B88694D4E8E0A93FBF20CE81A7A0C10D55737B6473FBD92BBB39FEBC6167336BEB9C235997796B9C0DC18C353E80305175BB412ACC29E647813D0003F727ED0577A7C14BCF67173DA569320E887BDC8F5AD27FD8864261E802A6753C6F9BAC844B5900ED0D4274C0E6EDE42367079188B10BED5999501164FA4C5A818ED6EE229C3E0E0F7804B19EAF5D1132BE1D7FC18BE834C842B21F8DDB11F8CFAAC10D2E124981ED698EE7CACA211C5624F09C62E1D451429048B55ED0F8A714BB77A0D4B40F0A446EDDFB27602B7BF894805C4AAD9252658F6B21A05DC0CF6A3ACDC227FA867A4E5B1DB63A14DE26A79AACF1900A7B7D867C15CFD1DAA712F2A1E2A6C7B31B121465539CD0164E3CCF79A978B543AE9602996448C6F68069D044FC958911EF40B0B9AFC78ED014D94571F6771EA5E2306A7CAC32C135FEC0BBF1DCA3CB0B57DAA239C01671718017C907048E0D19515CBF430D4B3B4FF4FC9A391D15A38B39C4E528FAC04EBD3DC69144C98AFA75102D21FF961BAD2E1F25562AF92554814405C4EC08DAE4A0CD28BE592C9C9BF997CC0FE31502DD541000D4640D59654D26CA2A17BA4CAB0518EE097C05B2984FFC56E8182368E216768E0D07E17FB64003E95194D04C6E00E08386084FEBB6CBC841E8F3FE2A069C45554BC502C27591CA3C1DC9E6B1694BA2C1BC0713C1CF738DB22FFEEB7443D72D5BDB975D192976A58AB33DB58F5DAE497A0B24011E15E3256FF124DD99AF6FC300D1FECDCEE18DD4FBF25E901125D4E80EFA8E2A211701B74FD992E63376996994E054CC00E7E1DE7DB8E7D2898A735EC4920DBEFAAEA66B456CF6A12324C5D56762313A627B3523AB1E2C1C82E4FBAB136AE4395FCF2672A58011D96BBDCF2A7478305756D66B30A4AC44E48B18A5964AA89F14187EA114084D52B4BA77755BA04C34777409BDB782B7B645E93B4DB284525E2F9C9C38D73B475DDE2251277A2E6C3183D5DEA78414E22CC8FB4B2C7EFA797CD4A87AC81D3242EC8D2C2EFD6BCFD69C39F14B0B365F3151A96F75454A3A1400C76A4390FE9F2E7A22A0CFA687A5BEF1C905D3A893B0DFD35BDA184F25E62FDDC2A52B6A67E76F550ABE4CC8D1D63CC8631E4CC315E46D3015C3B8636B92B8D07075D401C654FB4A +pk = DFA47D54EA735E1AC37015D78CC3E51FF35A03BF20BFC684F88BE0A2316CDACC506AD7EB29F0787A7804E3A7FD3CCA966D23F72EA40AEE7A7A45716772F77542776D123F9C20864BF20B5363A8C886EF0ADC3AF6F7069E9403274CBE9EFE957F8DEFA0DAE12657C4725D4A60D49657FDA07249B45CB880EB344BBA26AA0D6F6D32DFFFDCD1ED5F981074B270044F69648D18E8084319FF59EB9323BBD8970AD5DEEECF255A8703CCF52DD760F35EA576038E114A1F558168565286F7DD0B0BEA7DDEBDCF0901D2C0E6D9E7F745FA9A8D78641F9D2CC31A37FA4880681D7BE98686FED53FA2719DCC6C4E90A015A1F0610F6A881394ECCB4923667C81D453DDDB5C516E462D3A4DF53C2FD7EA6BE30AA3BFBE8038FC70CE5588B64FF238B04CC3F886E986E252C251D2F91A15EE3B8F049EE49AFDD25EDFE2B79929D9E8A7DD7B7080B04698F9AF2BD16D25FD41FB446EA75C47EB2B0226BA5581CA39684F7DBE3ECBA43C62915A19205CABC2B3E1C612FADA51AE36E3CAAE1BC32498B329C054E93D896B439C6D9415F7B20028A885D6619BBD79F3548583B54A04F1BF2DDE834592D9B44E4DAE5595A24B6C80A7CF799F933D3CB4915B77F31E916BD1946926679E4D40321DBC7E74021A135F896A5552B76C765AD05A812C3AAB33F908FB6BA70B1A3EDBDDBDFD319D38828B3495B8A8C4F30C54B919302D09B0D13192F8450E2225101627D92E12376BBB4D9DADAD86ABA273BF0A14D047F8E12A71F02EFCCE723565EC4BA8D2F26A4FA1F73C6D68CFBB91D6A998A109C49EE98DE3B26EDC1FB29C47982B51EC78CDF99D315386F6511323ECC205806E672FD201EFF567313BDCED12DD5C7700CB2AED7F7E4535044520B1442B0B8F5EDAD30E86C26DAFA6A5C38A7283EB43F7A809378E7A15740BD718805D89A47A0421473CA54630CBBCABC0FB53D8A166EEF17128BE1B18007E138D89EAE384CB9F248D31F3469F8D89784F11CA533331E00B8D266752C31B5B6E176C7170A86A86F9957528CC953C6E0EC5DC30E92B675F5F0653C8AA4A08A55D37C45B311B1E2C0C46D91A846A64D3EACA6018B506CC1F0A0DA2725B65E4E0DC9C287824598E1F69C7A71761CE4414D5CF911ACB0DCA688757A456BA22F1A534F55EEF6BA6CFAD200C8579E7E449B69CADC3AB7A80CB5F809B022EDEB847BC11EEC7C78E20292AC1F5223A8C99F5F6D255DB3350FE38FBC8091FDB1E3E8607CBE71F5F08298CECB54F670384F2AB779A8FD16476AC153C6DD3E1454A3BCAB93F644C15418F57CCA51314F0163B90F0C3AD7AEA3810BD714D620BECB3C1D50939356C6ABBC624118EFFC7022C5EBE0B87B668491C544B304AC51627A4825B69347DDE9578D4464961C067F75E221AD01113B79C36523C64F4B5375674DEDECCBB71049291EE68B28A58566E4CFC2C00105B78367537E01A149CFD9B3D992F458F089C15C2988086F143235FB571D723466FA4BE593DB6ED7CC7D305D4777D17B6EC60E242656EADE8C9353D18D2B9B3FF6805EAEEC8B2D71C1C0FAD892A82D048A384145B0F2AC09D2A792D44C8E31ACC76F84C0D52006717CBE697131534E13CA0A14DD590C8BCB08B5FABC392057C7514CDC78269EFAB390B49D375859B4909A9897CAA7F33320D7726695DB22985DE0602705C97308233A781BE0435572166F40298214AB4540153B13292CD2DEDB11494B68973180B7F888D921628BE1D62661EDBDBE1BD246757776AF3CB3093F9195419FA1E0A023493DA802FCBEB72EE6D955D42B8A07DDC4F4B46646243F8BC1114C4CB67BFBA5264A7F1F010F2B218BDC9FDB0A4CCDDAF00B72A26E9A8745E0769445F0A5675A8CDB9297F75987EDF79A4C061679178A8A583AB85D2C345D9C3D60F87FA992A196FC75E3F6FAA6D319CEE29D97E58DD942586FD13EF3BEF20A135E68A9608C0BC112C8CAC40A893504757316E73CA012DAC1BC02E6FDEBF0E88F485A1C402CC800D6015CFD0C3AED5B69553DD6F1C07518F618B17EDBDEFD5CEC911A740F33FA7C1764CCC4F03BB21E4AD3C1F23D65BA8A8C6AE97C08B980980543C8DBCEDB3D09321E54AFD0C5BE9656B3D17BD32BE59789F306BA06248A864593DE29DEB516AE5F49B627053B55B17D70DE2420CA5ACE42F713310EC67116210AC7D541FCBC2DCE28D33C7ED8F3CC5EF5E958B79C3008F2FDF93DFFA71A45142BEF7A2586D2A7EBEA37D459A3C8C7C9DDA40AEFFC06F8C004D283C7958F42995640E71AA319003E20D9D8AAE07303951C54F057CA5FF36ECAF7EC55BBC6C4071A6D8ACFDBDD74ED6D49C4703D3D19D9E5223D87CF221BE53E5A8DC50615F1A9C45F067A8D1B868EE093F850AC0966CC983CEE6E1B866D6C7890D239C580410D6E22531A651EF61310E6E4F284640F82AE3AFFDE366D18BB2EEEA0013D3B59AB86B06DFEB007D9D5BA812F0C2E0A4A6655A1A6ACBCD8626660641A5FA2F4F85DD8091D3CCFE402242658718CAB375956072AA8585BD7C57545E05F4C551EC5E28F020FFE7AD083B2F692C4290907121DF9D7516F2BA6CB9211C5C582EECB6A95EEED1DA7966390F14C5721DC004F9E8F086A20B98024C9C377CF438147F2C2AAC6EF3F07852DA3298D9B1B5E550755CCBB655F74B5328A0C5F10355C7E670ED85726C78242B935CC9D5EB5B939F73FB267717C4D27FBD6204833F61641671A428B46DB616233B50D2BBEEAC4EA09F26512C458E6FA30FAADAF9B80250E9 +sk = DFA47D54EA735E1AC37015D78CC3E51FF35A03BF20BFC684F88BE0A2316CDACCF7745A9E364124B0E57047B1E6F4322A5C72A5E8DCD3B31928D8CFA2D03AC922DE98CCDED3001B84AC5D98CBE5D24C9111616C07851068F120FF3A4D0B0974A71E620619A7CBBB0B91AEE40A9C61E6D3A173CC926496C63CCF28A56D5503D9F038567425612720306580854658636082605683855005435081377551618135172265686031732432026144875327550246012763223504251731877445136518105158133325357320274434547866603756707287324386636620515613106547256652247646838004061171148455037287432864732248772837166840578410772076870438534261463636007810534852884281882644171747873756054574216061386365484251081627657160816776806662764883837346188033438016834241401244077061363123364512161776101768755584684805641031002442267170203551145845456084260467351404756132175654681116801433345282073574108446714323425370725208642204754028312016503854182052024427801234347066806122476860000412710522872878177624572075116650775505033233240626100140680663004126583480806287381456674850065524668035567522582728568410348667546684423555811272525268747471541156381224307483476178176268642178280342540802570446354318550717878072821146727071838701615446620565203174328571033661567278236053323402687341726752825055361015368174744364050355631666200603157152177821705751475556370627641647545162821886360775278678040832624423310341528463161560532833002630332816445628080747356530635668084313624011122250587063541755700862756543410034301054476403138764881624371834441323550333657334841117736248488373084856135362702623520765440736142437574851846623308111353650148373645355106258452506188426568620581471606356801588067165116786252577650113237801326610726124445387807130377426264840785264037125821207330734347418347475587147218533178867563770705065171061562724886206776000648032271055623532710012680531722878708058632302751186462135688704846547267352784517378682107475588220375218425331517645453634842606837667420286471728588686826026433855630447135362133045478437110846366317577138682441241450400620261741352128468787005645176584026310677146572314588877665701165531151810444115237143753874534260833404533576425840264514118435361258867385765276780228441488562084728183660480084817443116501470335267262527865685145152546322560745488427082172051256500075106355347245860368874106140308173041611026886375600144310745732703836526058561511341664267024333116540532810334121383276161112520310337456554456022442472611253622133822445528545154153054734237472354540036172576376427745743405434426057426346127332086286510654510015156836820780144630857613770810388085670027156167030804604878778640110601274142038421573483674857818547073666418422581324510641786548864727261375537326758745110136332520555536135721521818522482328517151533122504403221431518525167022672235253856752455664611014275627036324108364150141412067382183665614382767307776740173386833383335508356643051857224757721717804463175352720061848242254485375318313323826684273860646460843510242360857650312560876630285881073532117717155504327426607362215281012214658808163364635652857271531611514101488070410846808883446420563317746163218067077351042348630878CD8E3FF4092F8FC8765610102FE0226AF6B99FC87664F77E42E0F92460F9F0ACF8AEE9E974ABE0D535217F77F64953C48983519863444B357B909E4ACF486A1B91528EA0824E3597DEA7E6CBFB92EE903D0F54EEC24DE8A3F600C29254A4943C433DA7EADEFDC87B06B903293FAC55AB6E25D5EA2FAADD5DBCBA08D20073191D88016B85E438B1168D569706A9A5F08E83A6FFB4F8A65C689DA327ED8A2D95A2E83DC8FFF5F4A53B572FA6883E3DECA352DDAB5BB8AFDB053859A0C3AC9CA36E09057AB162E4C4430CDA49C0EDFC5AEE221BEF4470404581651C4FD3419A71B559054AFBAD44D9ECA013D845709B435FAD843CB9715575E26B1AD99DE0A7DC2928A5722E5710E994DFFCD9077D5CC2CDFD3BCBD4B0C764606BB0F47CD1D3F7A1DF973305717B9BCCD43EDF7A0670F1A1089FB58C66A3E0E237C26F8E1E8BDB85562041DDB2279F183631C96F9304DBB1F162E98F6F842FB4A633C22BC92F2A65389491FE510E7DF4982D7DBBEF93FDC6C840A8F393EFA7F731F5FBA1861F83A32D3E151AE6EF67F0464CAE160AD92D3900FD3BEA26D3FDAC23071C9D58C4729A5E0CE6DB47887E789A8F513231A5C8BF5E51350E4045F2EF9E8C099C27889965ECE08B324862F53B7D11811104D23787F0C031D2C26A71B006A40BD7B48BE7BEB6BEF65C9F3050AB5990A998D5478A82277632374EEFDBD7B3A5ACC6033ED35C6C39ED950DC583B223F856155EF17C46C2FF51944745FA1B7DBE0171F9281254064BC6226143E8C98F3E556707C0F9411014995112683EFFC4198BA2C990A2A428528F441368688964A5068C57A73DEF6B7BACE595AAE325E90B16699B12E403FB0A18ACC895419227895F396E2DA68DF278EB45BEF99D6AB05324F4A8CC670E952E316BD79C77240BD5AF55B905C1E2A63C1A45773258E1541662B96ACE01BF1929CDF0490AF6468872F4D1F949201A12513CC8459F84D6DCD73D2B4A05A4C436343B663EF63F05887BF548BF8A257675161800EC65FF90CA98D931535CDB6139E03356C361E14A926D6D14AC38A8AC72ABFF8B644DB111BE68F330A2E30366E6A80FDDF0D3C81CDC1319FDA7654B65434A796CCCD0A7E2C69B0706A07E161FD02C66BD802B45F3E03CFDBBF25ECF1FE14B603452E51F48FE5E94CE15D16C158185BAD270FECC25460D2EDFE33B5DF890C5459A6B549E7CD7CFE8A641F98BFD993385BBE4D2406705AFAC9203D6B9E779DA38DDC695376CEFBC910CB7C876A6CCBF9BAC96A5FC714D4D29027F83D66EA5D058542527ECEF293C3A38128338AE5DC9A55C1BEE5B91378277D89B7D270761526A188C037DC88E7A9962FFFD3F88900C23D627489F69185CCA8EA91C16823699E157AB1D52BB88B0927DC25AA560F3779711C19351DFCFD7934CB1B6829AED4B7A0D5F3E1079B05F48CF80CBA654A41C8AFD41408E1A07838922833F652F3CD7619922552F60C6EEE88B4A7CEFD694FAF68B6C56B1460EECE74740C9028C44E658EE164A92795BE314CA91F2B9312E65CCF9882C8B8646F993F148916A8D6B133F0E3519499212BF88EC27A4A19C1FA7BEB2ED2ACB774C3859ABBA9E1B49EBE2C20E811CE681DF7647C6200AAF45769D13672904674F70E34BB9B7DAA48343B9D9209533A16C184C6FBB98621A301B54A19F1AEDAA192F8B413F461F4A4D4E67A6258370CBC43CF1DB315212B00F5EF2685C0234D47792335657D0A358BA89067C2A3C8C6CDC66FD81D92C621D5F6D32C1BBEFE2EC33E19C1B229B64F22FC7EC9E153FDF3D85A72B603E15CDD1494AEE53CFD0172D5420CBB5AC3C2D6397790F7CD828A59508F977C3A1B7A4920FE29136EF0CD361A0E02BA33C88441677D6A624C89869462294F7E301E68BBB8EABA2C1AD75568B8C4282F0DB546244A46894DE0AA7A65F4EC26FCC46574684FAC09B4CBAF8D9500E2759C3F7FEB61DAF77261A301DBC915F218B53BD1E9A42FD34A5F2DBFEE504E0EF8663DAEFA5FD34A4FD7CDA3D58811EDE822468AB780E5CF341F4998BC4E227F887A7BEC01AEB18F985FC593C898D464412FDB70B095A6F8D4EE7385F80B76A351A1A31F6E20605EBC3C2D9D145B5F19ADBB4F9C6BC2897E92B2A837BD4EA85F82CFFD2895E0567B665CC39E37FACC96C96ADC7C980CAF3477ED3BCE0C5333A1CEEAFFA182238BD354D8FE6F3368F91E240FEC61AAE3B6EB0C74292323B7E7B1A92C3FB91D63F20501BB9052946DF7790693A9A83047207ADFAD44B39DEC09CA52957B2B118301E5332EB53085380F19113C1CBD2EC1298C19ABE1D7FC4A7E0660D3312CB8CCB669A172FFA307265E5DC8B83BF73076685E5CC9C0510AFDCC493E70800821B73B34ACDF457461C336CA81872DAED60294F601EFDB43CCD4690986B558A4DC8A84AA42C39C09EED9DDD88C4FF29CE220A9EDAAB047A53D9D3F4D1BF1E06F0898D96D90D69CFC765C2A2E244B01915B36A054B86570551B3D488C5DD7EEC1D0A0093F77763F9F5C537CB53C55C07326E16E046BA6E81548CED3ECD3D0A16B2965347F54BB5ECBFAB361E8A422A8004F7BAA9DB110E654AF3829119A06458C86F4D029EE113F350E88A1403052C1F6F8D3A44A2D910D5D55C89D884305E94E33A8A1344CA387D4C5829EB8F6C198FBC8D81D00E26A9500FE2EEE2D2C99D03AE2DE6E8B9D5CC4D702FF9FA55C579468AE88C2B615E8CF32D092293591209EEFD7216063C106422F8B6C042F9A5E54983D020DD44A303B878DD79C5FF5DF137032FBDEFB5E9B970F281D152BF64ED065348DAA109C78E93DECFEC5C4BBDDA89F144C2FF2B722F0F7319D7EEA4227AB25AF1C222D53E83C0536FC6CB117BA6122A82418E0820D6BF5887A2F96E6F572AF7F1A79B398676358157AEF89CF4759419D7A3EC6697728CEEF086F0651820934D85F58B50D1552C400809D0AC1D0A87AD9E7E11C1EA123C2AC359D1188B9EAEBF202719B8A739E624A59562D60CECC5DEBE24CFE4F48C34BCB7422010D338F04DEB69A7599784E8127FFCEEBA19A11064C780FA6E5A072C32E113DA603326BD9308472B582A6B0BF2091BC22BE5992D4F47D02D49DDB82DEC97E4C92BAE5881B8D5CBFC5C3C61C6AB2E0919597A5225246DAC6EC4BB17BA9E341B0DD77EEBF7B5F6C4923B45722ECB32BE82BFD092637636034344428D5A26A0B75A109196459193101C9AE87A49D8643C68D7F8BA79EB19D4518F7D9F97B86CCABEED02584E8CD85154C4E4B232F0D9D645A4845E39768079231E4E6C85467149DA1ABFEDE9ADDC4A3AB1ABBDDE360E596853C810B1ACA46796B572E14C1634666B4DA309E2778B7D8E8E81422DA95728053CC403FD52EA4413E0E4B3E90FB99FE6989E37DFC5D1470271300185238993B4970363DF3BCC17F4CFC1AC69B09245AC43AEA6314042F17358EEF5BEE23D4F816D97C162791428AA8AA67A18055A31CA189C54FB3E32295D5DC2BD1BB74E1991D20996DC5C145604C174001419E4693CEBFB5461C6E50 +smlen = 5091 +sm = 874A7A3AAD800C27056E66687C82E7698FBEA737D0D9B6A29020F96113CAC7F9D0A6A1FBCC34A08CAA9C8A58D068C9979BA244DD6542C8990A7F30B691F4BF5016B257EE0D44C192636B7BBC9FF3B39AB2740D9C30A28544BD98F716D0A7793942071A88BF6608B0B3D34D34AD3E3B984ABDCC1F85E1B69C40EACB9F45465449ECF65BBD8A0DF123C2DE4A89B63CC185DAF46C43DCB8CEBE5BB13DB22EED678C5EFEF78963FB3F35F9A4C996E83667136ADCEFB3219FA6514F5234BD84EE76DB88B937751051AAD2FC079E11BE202FA1B28822B87AD273C698FAE3530FC9A5B87AF1C72C7833B5C18573F2359C5BE901E1AE9A006B1E4B6F7D85A1F41CBBEAC580D89DD51340191AC1D4F979DD2762F4F4243246F9801D404B7A0561164D2F33AF31C1930EE0613F52D06608F0F9BF2991CE39CF69C9EB05B9657D1CA64F869FC5FC29A4CE575645C358C9E3CCE1BD8BC05C3E7D738FFF60A214D5A04BC2E00F705D193A65185B1EE9B8244EA1947E648470FFD199F489A43AC96C7163837BA3E5436A196B77811A43E818794864F15A743CAC128ED4EB62464B36D7DBE33AC21F5BE1B3015649129DBE2856650702998C65A2995BD91F017EBF281402E03D5ECDCE36B0B1E3FC308377E9B90260B5F1FAF7F18436D7DFC83DCB5A2CDA04D1CC3B8EF530AE02DD43DD8CFB579DF29A2A90FEA56BFB70214AE419A91FE549B84E1AE1D75BDD0AF4A448A012D57E7664220F9AB0C7FB35AE74327144C5C573308B6BC1BCFA97663E0434B99BDB74E06A5029A6A19B06DF04FB0F53E60221ECCE63073EB70BFBB9F717A029019950250AECDDF72DD6C033538727F88FBBA5ADC2FAF77E0E8DCF025F473EE08DEA8CABE5D46489FF3B8E3ABC5D977A61096E794B703177B364EFDCBD07C7244F77795BF40BEB410D229F042CF397C3175EDD25C2B4EDB5F36DF3CE91C1F2CEADC8A432D61DD211C4DA1CD6B6CDA3E6A9DE2B958266D07EC8E8F14302E3887FCFF7CC449B8278F4ECBC0E0B8B50EAE087461FCCB3C21BFC25DCC0EA67520C82049833A11FD08D2A7A69A0E018AEC12F9AFC19CA4EA304B9355C0A021DC476FDF1A957F1EB3E549EA9BADA5598A633C1EFDE5173B283FB25EB212D04F19DA692AD58224690032D0D92A2CC3D22BD7192828E47D0BB0AF6846DC3FDEE3C1F629339CD53E689165853ED961450CF8F6E4099FFBA97F8942C846B9906BCBC46BB2294E8E323D00320A83DA757B03765313057128DC7950B9DB0039D303413777FBA43D2A75F1F939DB6CB89DB4BC4E2A6DDA96DA86DFEA355C0C3BB1A7746E414622455C892E2855D582AB6D7015D183C9F69C346A6DE7BC1D8C3494C4914FEE1411C0336A549A8CB5072C03535AB1B1AFB3248569B3365634129B79FF3053345EAE030D40B0F5FABD4702D4CFD69B5A1A45CA935108AC650F61BE41644479F8D12BC17FFDE0ADE58A578CB2DB5AA17E97A214877852320BD35E3F79620C92C705A2E988B3F59ED10DC841DEDC8CB97612238BF42FBFE1ACD9D27335161ABC3CA8A6882FCDB0F1ABC054E100E0E92A9AF42C14402C18B949F333D977C459AFEF4E247A7BCEBC615D99258D79CA1A6E474B80D32AB6C05375452990C03659844B5260CC9F7D1AE0EC9F137541B56EAD984C45E81913AA5AA18E7B30C7FE287AEFFDEE4D9E3E77C274ABDB0CF7497B6BBDF29C7F079ABEB00C3B00086F250E3B81D85C8DF21ADDEFC4D0030F206611DFACD84528CD7FA015E194293F7DC16EEEF5815ECFBA8DEF8B2D4D163AB5249C7D46851B70E78093AB8587044E02971A1E718759C10A0E4736110C315405D59C8997E62F4B13BC7CF094C6C6CC9836A93F698C91D6B969DE334AB739C674C12524D1F70C4C097DFC1FD0910CC8FAAFDCE8952314240D7CB5E66071130475FB40EEB13E3A6E2ED5646DB06244C6C404E9F68C0C9614AEB3BCF2DD0B41C45AF42698036F74CF7DA2307257ACEF68943C5109FF43CCE2C2DD8CAD94E246C1FB60342575A5B1F1F59AF5E41D64DEF4D8BA6DED0A874DBF1344B888D7C7E193F4DE642281CA7B77E0F63874DBC5582BA3E8ED3D8F683C11CA39F6ED03CD321E3583DED66B731E4A3E4A2E476C0D35B67E8ACCED4D892FBAFE97A83480DA0FDF367C3B2180795DD759D8239AAF9B308D045EE5E87EE4AD8472A2B0C97F108E8AC0827F7F15BFB8DB9A8CA9C8556ECADD9916820FA162E782B2413839E261A0454A57AC1C7BBEE8F6578C2C1DFF7A5A3CC222F6BDDF4DCB0F455DEA08363B6E166CA90BF8BA226E3A008D5DF0FFE14A501FF9F75A82B6C1FB35EE664DF115E58B72C121C0E0A454449AA2A7D5DCBB5DBC2FAE047CD0C8E427478769C291E218071B6E9131964CB037B500D1976DAF2B4E16FD8BF5AF236DEA00449B07C5B6B30D03916FB50F96C49ACC19C074C8415B0C553F986639DEC7B213123B91E7B2669D56FFBC162A96B1A5B9A1B1E7BF8071AC907D6E88ED9C38334856BCC7ACFC69EA601C0415E6773719B0A6CF1D8ED722A00DB8349A7745A0E2C9AD54FA2DEF286E74F5A9CABE600F48F409C9E8CECE6FD7CC44884DE1A3C0ECFE9DD62842F4CD2334671DCDC27C6CCC1F03CF383066DDEBFB8A8557860AD70DA789F4553A718EF3E291A20051574F7BB429E06ABF84399183614D6DA3B35C653D753AE884D01AB189F1681B61759BEBA4B1884FA7E7F811D4E92B38DEBDD92DCDC6710AD51F3DC47E80826B1C317323710A12EC0A941A428D9136552B9B27ACCDD34A44CBAD1BDBEAF1EA972609EDE1B68325A7E8F5B6CC8CC10661D804B45ABCA4FC3BBE5A9669F2D8404EEAFE2154F27651E78321E5BDF0274B6CCE8F6A1819A79A38FDB1301159AF1C266B2807A8B19C2BEFB487833F57FF98A25BC1D53504A009C0982F9E6A52C933AB2B112B1BC423B205F1E1EEC522FFD33989019047479D60C3DBF680C7D28547D8AEB3FCB0392C7D8340869E10EAE9F6EB6C0975E5777A85538B67A62A768FF57E5BB6E7D69691CBE27820C9E001C1E078E5773E2B04857DE2CEC8A5AC131567883602B559D46EADEF578741212E8323AAE818CDB1E003A9F22B44B5149CD6C16F7C14FFEDA66C1A341C96926068AF671F4CBA5D66BAC2ADEF3F3C9EA9EED63E65F566EB5331F33E111E11868B511DD9EE5EC003844ACC5080EDFE1D04D7AA19275F16CF11ED96C74C88E91FF106148D1D83434AE90662305A5F4540512DF5C0AAC6962C41A8CC2344F9CE20EDCEE6BDFA1E1065775CC236B62F53036B9C407FF29BFA7B7F2B5EF311FC5BD8704FBBD38DCB5B3CB5806F9F233733F187450C4A2B3F8497089865CA5729057BAD5877D99EDA8B69A0ECDE0BF50603CBB5AEFF38047B3B4D32B782447B2A354EBC54BAA726DAC6164A35AEA6BB9860EE3B6C68152A87DA3ACC7D8DB32D33595330887DE522DE20AF866F2C51489DC993D3FA7F970A30B8FB05A7673E2C05A29AF6C3381B24B68DEA57FA447560CF5F99CB77BF5FBBEA0A7195A73453AE947791A0C1391DDF2636C7AF960DEA8F7871B280DB330FCD768C09CBFC0435903D966821628A589F87BABEC2C1CF42A2B08D8CFC17F0932DCDFC93AF4FEC201EBFBF9EEAD24A5454FE528C978809DA80125EB14868111BEBE428B9196DBFE838CB42010F7A5F2C85787471B5923736D09FD05C960F3AAF082E87C38FD7544C5BE2D069956EAB1E65C40C602B688476CF82E0820A532CA0837AFBE4F832EFB65007D22E88207B6E296AD42D58E404CDEAFE3F8A5DBA8B6BD5B91B92E77DEB3CB1C6B60CD277A4358B517C5A859346D2EF9A20C43017AA9D49F1117A0405E3322E39516C6D6F6EC2E3C4B71D34B990B9435F2BA88C13D4FA9F221BD742833D0D74D137803033788AF4CC357127513063187E5A45A3DE7DF244E0C90304342B4BA4C7181CF30582A0A8D77409D551CD08EB959BC8FC3C8ACB7C18F1BFA91D62EEFFDAAE5AC4EBF4D89A67883C60BA6193DF4A92A82ACCE088ACC5DE816D01DAC25B07CE0A0303F8E4FC0ACC9DCFB3A35EF4638814B738226C629EF70E8B53AC3DFD943229D99B61FC78DC165CD071A608C4439A2734F8DD7BD8BD7772D079954FF8F4AE1749ECF8F778BF48FF896C977ACDC825DA415332796EECC3A267890916FAF29A0606F58A6D5382E1E2717D27DDD333A6FA841BDD91D3CAD3BE6C816F78AF05914D15C3B050A87BC5F1105FADB43CF24A6397BE7971CCF178B0244CE21BFD86B0A60DE86268E479C93DC68F4C06662A3E5EBA71C8286F0C1A9E9A996AAA84ADF1D55A6259F281144A73C7FE56EEFE417864267C6BDC5CE7BB23AF016C9023DA6A63212B6069A287973B5F7B9D2AD91B93CB9CD5AA748204990A1E6BAF8FC5880CA2C273D2D35E43EDE634E8CD121E6A95FE6D23ACC7107ED9CE554516F3634F260A51BD17EA571EF054F147A2060E93CA2B1141B31A0F8987C9D5CA08463FD38B6DCAB2CE94731E71779F909F645273DE0E7F8A1F4C60BCBEF9024FF60EC205D162932EF843E9F8A5D702D7B3337FB20BA0428FDDD93433591E618E3116553E7421272BDEF90836BBA28F88436D0500D0F1129525789959BBDC2D2344A546A6E7687B1D0D9E1EEF70B66C5E853A9FF2F4F667885B9C5DD7B848DB8E5000000000000000000000C191D20282D6103E5B22F934203B5CA87337095C9A19267AFB9695D309BEB8A557BB7CC90332C4A03E1D416D397B945B607268F545928104CFFD71B02864E010B666CFCB68B762FA5EC839B5AEFD0407419441B38E6D881BD5218DF73C675DF101BF2C53D90FF86D4A3C7DB19EC9CAC044E0467A36337AAEEC32217FAF86CBD7BC2B663421754CFF1200A8A66E18F812868BC8D1C8CA495E6462DA4B8B96D4167F040F04927A7C27AD35CF174D42684ED55AC80D14CBE4CC2570642DDEC4F44880D967E9AF77EE27D0D3DBAEC9067FB6FC957AC4A136C1D564E17F59AC4938D43FB9050D810989907125C47FCEA6C162C723E79F68339CD1B3BF596988BD6E215271385CD50616868C6BF40FDC34BD30E5A00773E2C039723F2AC3A3FA45F4CE870841762D7435BD6CCC5FD3D58FE059EE455A806FDE89155C84797FBB73691A1FC6921859E99066A3239E31F28D1A46100DB1917621D9E61473CF1E71F9850B584B459D5690941E676A7DD56796313ED9ABDBE03DC75AFC1430DBA27FE0F8DF48EF7C339F462AF1A6D30A5F8B480DFBBE860C4C0BC136393C8FA0875AF454273C3CFDBA7EEA44EEF1A4060136948CD98B9D2C19AEA4934F3455F31DD15BE6545134F17A195B6BC409159C0975E592A15E86CA4943CCACF4B46719A072DB8C629B67768F1956F8158F179A0B645320489DEE404C8D0C4E786CFF39B324053F102C118E7D51173CEC0FDD017F213B2B07AC6B2C7DEC04172DD5396A020EDFB74ED86FC31952D241A7C3D139DEF543D90976AA70599792E73CF73AD0BD4A359BF60DFB2CE96A784D8DE5E23A95E831CA6FFBA6B187BC5F29A7757185EC06AC882572EC6283A1875B54FE4F295E1970BF311DBABAF9F894D3364D68F529C4EF9030AB934BCB09459D5AAC61919946FD28DF1AC85876F979E8B8528E9BBE69F03DEEF136EEA6A8FC86F31BD64285C8C9F49ADF53A8BAA7867CE52E72DC4A63929DF3BA2662DC77D71F88D8AF42B8D67AD54884EE11F5A6B3B794F7D5610909B0B740937587CF475DA903159994A262B6F32A3D1723FDAAE65E636B71CB0EF0A744F359BF08AC8231ED2970CE8C451266F703DA3B57F85ACEED4C1C174C50D9C226F028E972AC124FAA6F60518699CB4C499220EA51A538F9EDE67D0E98E1BF8FB4B24B1D8EF50A28A93E20076F8FB812CDAB04871D331FF434BA66DD4577B18DC3F471B3E96A174B58A7AC2470EB8463A71FFCBA2D064470FD2D4E15F9491DB09DF3E3BA376A3DDCC437312BE5848DB3B9079F2AE046798473BB970D725E1D7C6FDF405AE387DD7CC1735A7FC27D1A476592A514B87C9017E1E5D37E338F37916F3C72C5F2AF75185B88694D4E8E0A93FBF20CE81A7A0C10D55737B6473FBD92BBB39FEBC6167336BEB9C235997796B9C0DC18C353E80305175BB412ACC29E647813D0003F727ED0577A7C14BCF67173DA569320E887BDC8F5AD27FD8864261E802A6753C6F9BAC844B5900ED0D4274C0E6EDE42367079188B10BED5999501164FA4C5A818ED6EE229C3E0E0F7804B19EAF5D1132BE1D7FC18BE834C842B21F8DDB11F8CFAAC10D2E124981ED698EE7CACA211C5624F09C62E1D451429048B55ED0F8A714BB77A0D4B40F0A446EDDFB27602B7BF894805C4AAD9252658F6B21A05DC0CF6A3ACDC227FA867A4E5B1DB63A14DE26A79AACF1900A7B7D867C15CFD1DAA712F2A1E2A6C7B31B121465539CD0164E3CCF79A978B543AE9602996448C6F68069D044FC958911EF40B0B9AFC78ED014D94571F6771EA5E2306A7CAC32C135FEC0BBF1DCA3CB0B57DAA239C01671718017C907048E0D19515CBF430D4B3B4FF4FC9A391D15A38B39C4E528FAC04EBD3DC69144C98AFA75102D21FF961BAD2E1F25562AF92554814405C4EC08DAE4A0CD28BE592C9C9BF997CC0FE31502DD541000D4640D59654D26CA2A17BA4CAB0518EE097C05B2984FFC56E8182368E216768E0D07E17FB64003E95194D04C6E00E08386084FEBB6CBC841E8F3FE2A069C45554BC502C27591CA3C1DC9E6B1694BA2C1BC0713C1CF738DB22FFEEB7443D72D5BDB975D192976A58AB33DB58F5DAE497A0B24011E15E3256FF124DD99AF6FC300D1FECDCEE18DD4FBF25E901125D4E80EFA8E2A211701B74FD992E63376996994E054CC00E7E1DE7DB8E7D2898A735EC4920DBEFAAEA66B456CF6A12324C5D56762313A627B3523AB1E2C1C82E4FBAB136AE4395FCF2672A58011D96BBDCF2A7478305756D66B30A4AC44E48B18A5964AA89F14187EA114084D52B4BA77755BA04C34777409BDB782B7B645E93B4DB284525E2F9C9C38D73B475DDE2251277A2E6C3183D5DEA78414E22CC8FB4B2C7EFA797CD4A87AC81D3242EC8D2C2EFD6BCFD69C39F14B0B365F3151A96F75454A3A1400C76A4390FE9F2E7A22A0CFA687A5BEF1C905D3A893B0DFD35BDA184F25E62FDDC2A52B6A67E76F550ABE4CC8D1D63CC8631E4CC315E46D3015C3B8636B92B8D07075D401C654FB4A + +count = 54 +seed = C8671A5D752CC6DDF075C899797603A625C142485EAC3D57CAF14F2244D7F84D116B28F959912A758E519D588A6A07EB +mlen = 1815 +msg = 3EAC87B3D642CEAA3DC904AC3C4245CB2A260E4B74D0394D33D4B71024144180A727F80B092305F31B2526998EDF6F98E46933FDAF0E8709E98D54F13C2701C58BBE35292FD3334C5E03D345A9A2EA1E01B2C4573567FF1FF3BA7406A16F5A5805EDD760AC78A3AB8602E415F67C7CEA5B36421C79F83CBB14FA775448A832A4B28851CE215C11DCBAEE652CDD7342B6B1204727479E6208FB556CF08BF7EE230F32659E829CE4FBCE0955D01D36624BBAC18C1D25A3E187722F8F74C88B56E518CF0E78B3B0EAC56D8F13C4AFC4DA3613A41CCC2B0B0E2EBBFE5799E479F81335360D483596E9AE926751EC9B956555F271C2CCD85F0F6C1BBB2C326C29B5DDF6B5C4C11F8EED15C0143993FEB626543E92CE4D66C0BD28C79ED1ECB793A3091D6B9AB510B0D41AA42D70C2D8F26EA0B826C8C375E1DD89B3E2A48FE5D88A462DEAC33BAC35AA32EBC010AF7E47B77AD23653D747760914E0CA12864CD401787EFD96F30D82D8907DC68578067703DD19B2377DF319EB540E8AE78B2BE86BEE1C915FF3B2F4B25C0AC22CCF89BD85371961944D8A4E6D20E2D3E9DF3A07D3BF6986898786F0667545275FAC3EB0F069B457D8EBBE5F60125F94756DB04EA203451A0DE160CBCE2A34650D92F200448B097691A61361AC487FBC3C82B2BD7C1ACCA02031311971C3CF69BA459A0B640A702DB4467973713A6F2466560FFAC0592D64FF1D4A935220826EB559CFE0144EA4B8E54EAF67DDF91988DD4B3749C865008C0C1CF98BBF76D929B85C8C426C15FA56706984E0F2E90658FA3CC33EC9FC700976870C94035ECF9A0534B18D07F55923663835416E40235CC2550BD9822F0912CF101F86039830AD9102AA4A3B6777EDEC5EBE621082FCF81A1C6A528F0324EC9D39FA80B6E87D6366E7EDAA0E14337D6708F7C3D2FB1978F4F5CD594FD35B267F9CD09370D3366DCE286CCB9647A1944F8D8BE63E5EF8F6108CC5E9AFE9127DA84E1913439EC35A4E17F7782DF042DC2F7C5CAD8A659DB282E61763539B56C2AFA0F2B507D549EC8C9E76C7DB306380CD7B46C9699B6DB8BE06CCA15E8E83763137B06BFF02DE2738A46C61B70EDF4F394D54D0453DABF689FB6BA41616BC589CB9847224E74F919B6E03672EC6A52584FE81456D6E648DD6F0F9B068EB72241F067BF6B891A498A9A59356C735E10EFB37B3ECF47CC5620A35442DD81E25D2C6DB0E9E871301ADD193D628B30E3B4345751BC17E0B5B05AF758A653DE7BED3763303FFE1AF05E407F296C736CA6F4C348B25718C7A814BD0730AFFC057842AF3D9B9ADB12FCCD740ADD16218AA57E43835821A2BCD70F1027F3042D4A92F10D0A1FB8323E87869BFA8DA24DA75F8743FA3038C24FEDC0C987065421BF4B300BE3ED3F6D6D590968D3EE32A8F5E20EA6168756AA18BB78B6AA48C299C36D0E78B6F84CACAB5946C69179E461F4C2DD201D8032A29EC6C52942AC37D9C76AB4A401C9AFF96284E1E9E39BFF6D912CA33B6118067605EA65D7F611DD963F4F75F97346FFFD1DF84C79CCBA06804B3017775D8C0BF614FCF4D824709557937B22E1805A0A961ECF226F26E3706362BF6D8D1DD30BE7EEDA481A64961641DC57B9F0211F8EE43578E4C2B6507114DFFF3C3F884586BFD1278D117F7C6014FD5980CDF1E2FD1F34CCAD170842B9E819C22FAB9890AE265C3BB6946FCCFE218544D00A6BA5BEF5224EAE24002B6E83E0B35E98C2322BE2EB3D8234BE8B048C54E40782C9A24D7A8B461EC05F38A94AAEF3DA3B46D0D85B0D949CF1089408189FF97C56C7DEE50A004AEAD82C15C7C0D0965F3C65A9A715A65D29CD3614954EBD91EEB4E74F862FBC944C56F2EDEC4D344F92E8154708AD0F5575880503EF0F107A9A9DB99BAE82357C16578F3E6CBDF9B427DA88DC322D11C6AB2A6AE6F5179C94454E09DF5CAA6A519A4C1903C8F2925639E12AF793695F256BF0E55E0D45B73880358F09719ED89A4A1A07868BFBF16095A20035D5D4F99FDA19DDAE3E21CB98308F4508B5CEE706C27898F03A2BF14F29ACBF055E4AB0713A7B6FC1A7853EFD36E1290E69587FEC15D492A66B9A4FEA6E2BCDE61E02FE18E06F59A2F4E06F177B14CE4C1CF1A8D1F49C554A8A4C68B9937B4C230320C80753D4B071BAB2DEDA89C9181820336F1E766E447EA1C44E15CBB7C002C1813D2C1726DB0E4DE289466077DA9610E5F3AA313B1B01DD79A4056A8BBE9D843CE5B0439325FFDFE91FDADDEC6CB86D5CEBB68D8F9C0ED237A4648C412780ACFF48FD9CE817EA70D950DCB989EA6B11FD87EA4F30347A27488C5C15BE7FD6D1280FEA3A7C022F8D9881FAC93176DB2025B4C7914A51099893A791BF5BE851F325347484CA6ED51B2BA71548A6046EA7EC85B31A9967E7D119D2CA3A51C1E14D5A3EEF0D41BDD615DA01D45979007A1997DE281BC340C3203D5BC0075B1AA38873A9DBB9D18E6E26971E70B54E41E2C8C91D2E60FBF85435C1EBC4893C45A201B1D2391549F52A1CA3E0440ADFB746FBBF0D9933F9FA0220B3E04EBEBB29D2A9AC1 +pk = 15F9D0D26D06CD69B0ADD69ECE2A194C7453F85796D04A62440D5119622F6AE052E3A5EBC161004357EE8773E0DC6C2391C6FF7238FF22A09E3249F88F0BE405B39D11C4457B4DCD9315C7E513D3C078467C1BE666AEFFC46C748E866FFBF840608EEAC25BDB6A198FA6E2B1A509473DB73991CF8391DBDA8522FA22D3BB861B928017007A0EAE1A00D5281882BC93B99070A5B48F76EE203C49D67F686E9415E5064BB496EDB919DA20B0080345A003FA088FCF30A07D18AD837B8A46F09F1AEB9508702209F7A83C5A7B4AF086E33E021233D5364FA9038FDDA3144BCF3168238C89B590CCD67FBCC5A4F09AF66EA60A23F58DE9067CF2891406617A2190A162F0715B07DDB1B393BB9D72BBC272314F3CB0EF8B0D4EF6A91B4A8B77B0C65E6B9858AF69B181A1B8D59E4B8253A0FC9F7F6D0D99796CF6ED8F2CD8F918A50E7B73505B69FC5889DE777933EE5027610994063301553E4E8BB809023D495E3B93EE556FAFA02A6C163A6F269E2F5912B9B5197F189E5D0AA3DF073AC51151526B96A4B57753555E2090D30220C1EC2F77114120A14C828C3CF6EA7B3B7AE7777B5DF3FDF432E7344C510525F8D3BB7E21B2A2C162C2680C88CA40D7F97BEB82DF729838948A0EA4DB9C0E27DBEC598FEF5CDACE413D560FB38F37994CF421551D742D97D3548FDC902B46EA6A99F5F6654F5A135DDE34EA282BD566835EFC5512BA68EE91BE8053A3C84C0E84E7C7188DDABF3E24493D0DC3C107407EE9CB6D8707E575741D79A93E62D6FA39B70B40877AAE24EA27B961F2DFD3E3E1877BD70BF62045451C82A1BC319F1179FE297585D20D5764E9E0416ED3E9A3E05AA47B151E25CFBC5B6DE70ADC914727817F3B83DC12BA808BBF60E10980EA1A1656AC5E73D28CD0E2DDF46B1BF4FD53B327EEFD5D7C45E5BC3397CA1F416FB8A92E5314300F73D7BD03910985B06FD53D3582265DF31A26F4F63170C8207993B96690777BFD984D4F70149F41AC0A1188D13D1F97B5CB64DE321AA1F38937FCC09D73CF112D1C4833BA2B09D4B8720BC0C4AA09D9B5DB265720DA50155780D633AADC232376D677DE20BAADFBA8152A61AAC2215658929BE4051E32B83D0587B89390B8C28EB9275A40D5D9F3DBF699ABAF572EAE407D022E8F205C38A9174E6928EF7F64B7324EF7CA1DFC97A8EEEA6984CAB0A872FB401873AB3FF30FF439C0E5EC3A2B0CF85FF461208572566082724C50C02391C98EA03CC253FB8087D087A2E43BF70D35A79DA59EE18A8CC4A109115E1CEDD3602DF234FD48E1DE27DDAC9CAE88A229875F32D23700FED3BC7FD913884C7438EE246AF6CB50C7DE0B0F2ACA9CFCE36E6596C7E05D4C8328E03B6657073A965FDA81B6B5BEA46A3C58F69B8EF4AC5995B92E46C1CEFC3A438391BEB39ED8A9B44E0C91B13D8932F92EC03CF642BA986FFBC57E9595A2CA208C0358139C8A0994DAEDA80DAA577E92847386F6521B3387A9FB2331134C670EF07B3B4B8C54E9C9D8FCA14725EED7D3A86F034736B0BF2578F09E0294E7B2E0061CA6BEE395B12D4605184175F7B0322F2FF5748CBD0657A39CE8AF575A86FBB9285A5927228661CEC04D47DD082071A925106DB62111F2633C312A69DFAA1F60956DDD5162F90078E433E6B53261D748816230401C3BD7255A5641808D244424E9BB0A66E7F8220175A87F50FBEEDBBB8E7ECEB5E7F9B69863685D1399A527655069E7D99F8EF2B4B1718242459F29A7D655F2F7727167BEC714E01F1F9223A7897782928B9341C2F7B2EE78D55699E6C3864E9AE7BBF9622508A3FF923A5789667EE5104855B09C56E08779913EEF51E6064D5F998620A8CEF8CB78BE1535A958F92A53ABDA418F5EB600BA1EE47F975046FF59D363E4D1C596F85081BBEB4DE7186E7E99F90734B8685030D4C0A6E68A836B582400433C0AAB4DFD0724F01DDFFD0CA3E08EE59ABC5B54B3AA942E8B1A6534D5EFC5633B63AC7425303A230C477D2C4B57ED807BED42C94BB15A6C0E056ACC4FC09144DCC6E08AD1C296027161A12B81FDABADEFB948FE6964B9B5895AF8EFEEE613AB0679E1B66C43ECC774DC437E619313AF036CB717D7A93C175D9C6DC121127CF42A619E5D182F470C1A821F52FD641D23D1D441F3A6D62D2A7DBB1884E5674600DC208581377B07B553EAF5BD05A3D4D93F07B4528DD399E37AAD283C8D4CB814B186D35F08288427C999D96F28CF4D48524258FBCF375979BA1EF97B8B653AC948C0FF24527825C26E58D9F1BB48D43665DA6BAD0AF9CDE9187825B50A216C1482492971BA0B31D620AEF1E45205FC60B5486BEBA2A84875CF270A39761AC4036177B970857A535449545DF5F7E8DF4AEE1DADC9CADC3A505237A53C39EE1FF7927D9A3E5092AE02D5961A43D10EA8B36C1057237F3C18120B474E55A50361069239EC82BF8E8BB8C11440285D442C268D21F351450F10DFD7222A099F09C1D788991E72BA519010B715563E869D8C1CE0B2D51345AA83318FF88FBFE8984D564B3F1F1B60CE87CEE8C33B1E886AB15C5EE0009B43CA6E93946822F6A243799C746908891BE9E5CF390C1489B12FE13F7B65F6AFC2131E6276E325DC57FEFE3DC93929DE869DDB0AEBED57D54785B5E7F4B717C2CFA04774A093EF2E9688B87285DBC0DB8B5857F4FA48B8BC90956A83A5D618DADF5A6B53CBD4B0B9729FC978F48743FD320AF1E4F33C6A8FA72EBC821BDFE373BD95B5E4F7D8278B63 +sk = 15F9D0D26D06CD69B0ADD69ECE2A194C7453F85796D04A62440D5119622F6AE040BCDF448F9BED41110C8A9FA94A454AE184DC9EBEF592A0227E782D27968D49A6E4BF7039F149BDA4A7D0EA051208F46D8B47C5C5EB3A8EBDB7164C5793618E931D41723BF76ACC073AD95D1ECA101CD33F90C88C0A404F05DA013B5EE83F4A4688767523017677053265766633784138467133310200034445220811237133545521015312530246511101644723138877106764813808145143420022131168208720837357252555034437075436382131625680525003372846747532867758644356162211834551525877176573037747160748170585734513825783877565112675132500602652466057673744435105826131858241863785754006738155286453267510783055018863443621526615736816563418354858280282873601057407087566682346425343265758154682638258887722222516123247111838616856752318467000002474641178440371324251636058413613104806241565806378360188141663282512472303601306333215236030635182662035813410513662201272054258220828622873267618833863080182664630350011736068438214502684205070022122364641520073826086145105422135700347442152344320433877577305527147736824137535552457812413242450540473873834804466680622767646637612523215312808011547252208144676122406016403821673724074653175036768446351161738352033447447526614235356134284827784857456246737647113255817822607418158674026132488770012565633611574071650388240380477148441810357433211178652326161746714030778840537625173425653248075441142030435460635506116774402438861328462178447821527324713557528378362353566284872387680701165162250454280525605716748042507351137268151304780807060484852754882688373503058388000154857040468624020154043363171353427020822307460311840717077227228582177780248114117033373588028731767880022344787824508171286236764333685567871123458244167172866048352318786583252538846565117381085257724055235410504438030411816325720751014651647761234435837350344080082606217004482543832386477510701066266260654303713547863537337324470128545704443561824677536765340680246062175114508306585888251742766218705626254836351508271675670152035855336046566308340650836253277236363133042317482301754654448405830511768044105125557352231186511347433151758031013121530812348313431641333643683133155137620308281323575477114672156365633388442515003778773766028531354682225022473831552408786035350282224126815161167736437461358668358476010328535417041115717160632501856010465570576000854412446385310080248050872608667327631868736503375670826047287406313221552004711634033555476857566223487314254577800276625353668762347186036680131701303535255807122678686360720376168303283764852336120763716336707655038440621643322567305876250268640832542878445178660728774702501110816813737482540652857050470682626803244188856806621710147285111326360702277521485174662234503281537644608678141232358423881770681473453834045575600762165000421554203552273827361750801876501540707703450456846175868200572438804884226711860133384660831457535842074883346441047675158555827823362037682565458410107420324315268311418500785554148132243848283341750625651735001315088381327662807238643553307771673485470504236010247652247110258015175781223028526700427557725514501401160746417816268083701606800423133B95178242FF4CC0DF912BD061ADDE6FDAEA3433761038F03C41450AEBE7D4C11A17AEC66C342F70B3EFE3093A61AF121D5B97F8D56DD6A1376380A9AD1F7BCD89F6920969DF7B900728A058B20E30B9F527D9809925BEFFCB69ABFEFA8186776A50F952CC8CBA19E21AC3F17BD11B7C95F8CB457A18A6370B924199D668E6DB9428C1FE7063EB447C1AD11FB517FCCBC2534A7D91ED4F3DBEDF181D4D48B2386669D24D2BCC1AB1803BF88E54235D96B9F8B940C434C0455AE90F1D39A87B00C8181392B9C31B5C2D5120C59BBDB37EEAC847FF2BD4CD7E0D8958F2E3D40B0794F33EFBEC38F9C4A56C92DCAA080E649AE4F8ACC81BA8913D3D00B4D93DA0D1C9F19D6099410B13937F99B167A13176F45F1A652C788486495BB9FACC56A91C6D1451459E69195E2CD69511FBDFB7EC11BED8F7DA1A031A90155165E81C32CC0200699E004DEB1252D1FB358B6D94B45CE253368952861BBDEBE3C46CC3CB311CA9EFD0A8046AB0AA2C56588EB49040EC4DB183ABA3DAE1B9F076623C4646239E1DEBBDA12B6AF96B29E775362DDEAE39AF9850663B70C1214EC2AE616BEAA9BDFAC2E1E9C6A4426BF97CF300F32B17020CDF21DA5FACC891879F0A7B3FD7E3FD46F5DC94B05174B7926652C3307B19130FDC29BA58452CEAB19B5A558B399BD9604A9259BD6EB7C020211284B1EDB24FEA29F81F1914FD50FE005EE98F85050757CCAA6B9E3A65BD5392C7112DF1E3D3E8B6CAE17933EEB3AE069388F059FF38693DD0ED37DABE5170A1161BA59D250E1303DF6DE8916677CAEA12E817E10D5A463152CB9F7E97D8BB73C930E1AC234EF53E24213A9B8D751343027957BA484CD8FA2C6702CEB0C6359394288657968F94A4984762681C7A594E21B859851E4A277D200E59D1FAEC7A9AF7C96B092DB1E6428BB0C6E29439FFDF0778640B38407A6D8D5A0FF0742AEADB4A27D5C7C41F5C4650C4B2039998B65BE7F58BE938F070AF745D290E897F878ABAB286D9C35BFBD94722B117718035553F264FD2C192D813B080EF88CEB2DD3DAF5C98F4EF80DEC46CFA0A38278B6885387C45F1AD581CE5D89F8977CD15A991D47B812E49DD79816FFDDE54B2A39D26BF53D77DEE5707C1D1E40E4ACA26B15916FDF3FF01763DD81DB86C5E202728DB62CF2A9A24CA6F227E0CDC998F1949F3967E5019433CA02701EFC163C69728E01B8EAEC8EFE7DB63C72BDE160C4FDD60ABDADE780912852C0029EE41BDC77D6F7DC49A1C41DFDA9C9DFB82657E220132A2DF52840A1C41CAE728B1607489329849091FA1834496CC5880DBFBCF40A0E43B5AEFA5394AECD7EA4028DB699A08DC996F1125E8E724292A4D5611C149CF5AE21DF10DEDE46AD2AF419B9976C7E14A0751445E408357BDD89A05AE1A02DA07E633B246A6CA28D551D7510EB856DF456D1D76FC01B9CA2B7ECBA7CE967DC923A4EDD405278708A842E64DB45DB27FCE80167BD2EACC33167A06247D6355C68AAC6E79C8CC5C4B9AD1113A79F7D61F10AE3AB2164BFB99A7898DA83853D8C7C2A6324B98BA0AB5C5F6993F69E5C15EEEFD1F18FC991192B81C42C53E7439A78CE9E0E2512E30C43AB4C86DC95D58131C7AD93F3733C688C797E2594C57C6D9E2C9DCA2CC299CB245FABE8FFF8629C9A641310FA7B7F74823238EA2FF8B0FD0C3E5271B222CF4AEA0151D83E3C972A9A29CFF81555F8FCC1E032FF9C939DDC754632E47E483BEAF464A41A69F6D895D24CB81941821E1F60E6F248230A917F1C1B00B83EA7FC2ED2D54CC45CFDC1847CA20F76BF9E1A58838F31BFD1D800C1F571885E80BDC7ED7EF665E225ACA996F2AC2712D68AD45CF598DFBC95A8AB3CBA837AD1E3D84557C5E1461C67226F18B962FEF2ADF81C9CF277D6D940281FD868528479D5DDA8BC730A7467E6491078B877C0510CC078F6D01A2D349E90813C9308DC96A1B97C1DD15BE5936E25CA7145B41FF25602DE98575B8E828E62CC6E11885D8576926AFA527AD4D30E2654097C7D1374F93EA4C9BD152C0F04D8402A81FFEF1CE00A295926992807710B927C070A2D6C035ABFB56D8AD38A7037EF02BDC4146A8FEEC5A8B81134C06AF01120442A7DD61BCAD358D9CA61B7643EC2E048599C89D6D83858AEF615FAD3782D218F9282C1C3B8739AF6D4EB1AF3EA329DAF00964657148CBD7160317255353B4E6FCF446EE78DDEAC765BB5D77276897053C33188925A1FDAE6665352E66BC9E2758F61FA4CDFC61E138D2361A04B6547B8DE6986E52B8D0C05CA8387A25B8A17D8008A4B9D0D9DE8669527E9B6534B8426BF9D8F22A80FBBF4303610CB6910AA1A873A3AF556C1023D7214B05880F6C22FCDC9CA5D07E1233BFF2B02C6DF2769525469FC80D04FD2736BE83DF34F5D0E49818837A2B9C0B9429BC46868287DF1C9788A55212FD79A4BBA3F717A4F98590DDC44735FA85B223537EC5FB8373D1F5207EC9786E5415176412C9DACA5C6D081107A24048B1816576D51D9E5A8706733D077B869A9A2B51A193530ACC9DAE634E1964B9039103D41DE69261663258DD8D33541C90C52EA8124C44A223927F6EE6A34E9E714F7DFC12288071C7D9D9A262384478DF07A5A02D13D35C9CF60B3CE4CF8F0C25091A66365D0C59168CA240E4BF0232C2F79D2AA64E6FC0137B43EA140A640117041BB038874355F540502C4AE4FC0C2F86FBCF337B80A9CFBBCF1DB414C848407849022FD9E582814F6932D5E8B74EDF00643910EC52913EBE9E6742E62F07430D5CC15D200BA1B7BE5F842C75B9CC8FD9076CC8DF36DDA61F4C3C2F76A420DE33C6AB2223ED4136CA0A9EA04A4CA0F9E1ABF581A80A4E86718319761B5D6CD93B2C280F20FE7FF126DFE45A3A954B36477D5EB6E88CC677A6A95C8BA49B9137D70A48E9FF686E337649B1814BF11F3AF0A1666D36F7178D54EF1CF7689FA734F460C71BE6774000FB639A26513FB1D54823CBF14102D2E8506BAF216FB8CA31C8ACE150D3A5D7F96F3721658C0C97D5A1570813455B7C0A3FF09FDA553C06D05CDB540C250BEE2442FB12731AB4FC08EF07CE778958C2BAE1E799D8368708368810C96F38877A1872689B9A909FB9D46EEEFDFA0B469E61EC7AFB8652E7137344DCADC7248966C22A59B298D4268A3141D29A6920F1C118FA59888DE9A12E8A3E7D6138568ABDE71B50F6083D2759017DAFF1D05F783A8904B79157A69AEA3C90BAEB3E8D876A92D1F21EF55A0B7AEF433E6371526A7FE414CEB73E0A305B4760B5909EA8D9EB660C1391663111EB76591E9E673A9968409880DB51B561BAC2EE4AB4F360EDBC23C3EC442543E6981B92AA26F8CEE641F8EFD05A80C5A0DA7FD351A215645454A70052F0CAE3520365A10859EB88F88DE2B54709A923DE1DB3148B893760AE33FBDD21D6E446E22DC1FD86F66E9D61DBD2D0FABC224F179855A7211E81002831CF434838F9221E913AAFC359E7ECE6FC199B6B80892B7552799B0A02D84F64BD98A487A2D7DC2D42E3D +smlen = 5124 +sm = CD80D4C730842B8D53864AD4A6CCA9B64B72E667017D3D12CEDB5EE9A07D18B5EC0A7B8D31F259889C8C818581961349F5C369FD6476FBF83474E15B3BC4594BBE8531326C722858A11358C6F538BBCEB7CA2CD0DE0277626CAEB78986CEE6796631BBED21D88644A07152D61E1DEF171FDE94F27E5DA632CD61196E6479F420745C7B499F274BADCDFC78D5ED65CD2453C18EF337F49283C06BA7759E5DC6AF80FDC07B81AE12EA48263F98651FA2D81339904E3CED5A91D6572675A0D47E0F2C9F3F7D134F8805FB350E0B0CC822DFAE3BEAF8AC33574B9C184C5742EE235526091C66BAD7A448F96ED46577B57B6461C05CCF4DF89D334406AD2B78FAF23C08F0498D9AE5156233AB93224CB9F7AD3E9051519730AB710A447D8AA15089ECE479C1C563E4CB606B2E3680E0BF6E1607734993BE0F7973CF86B7404CD782D65053EE0414B5ED7FCE4382563C3338B1F7A74440FC5BC85EB4ACFA4A2EC5A02D7E07CC0ED9031E4AB695D30DE5E31D308D00A4D4A980957D6169FACF2550A87B1AAD92F5820200EBEF4B1D621925ED4EB80ED7C95A56FC4F5D9A728349D47C14F66AC59D00ABE23615332761657F765BFA89AC8F00B2D325B7981AE8EF4B20ECBCBC4168CFB8407F3E6672D83B09E905FD74715C851747722EE9144E35377D136D5846C0D1139CE249954D506ED0DA58D7E08CB838295AEEED39A165D63823DC9458B44D71991DD506F3F6C5D865EEF7421B903FEF2C415C62D255A0311E4194D53A3E4F00527FBC5550D27233F0927E9813AFC13B110EF0E8E0DF8FEA2542DF90D0DF941DB69BA0F466B3C268094B962BE235AB8F625AB0BBF19F4441AF37099413E9F5C910DD2C87D312867574C8F1F96EBFD6B893C1BC73BEBB325DF0721EFCBEE497E4828D9E5D273404F379F93FE1EF3D7F5F14850B4380371A679FFB3F6E5A2B1CE93059FE9E57EEB4E493BD8D3677ED19D75CBBB5C7A67DD00C20CBAE9A78BD367608C39142DD38F3203C142B7341541539041094A41AE6A6B392ABFDC2E8F51EE7654C73490D06FCE9B3E95D7A9B010BEAA05A07167DC6A9DF89345A232B1CE5A2C27E52A8B8A67D35309AE31488DEE6B65163DE2B16084743CC14A305E2B5B011F1E12F9C4C0EAB6C0E41BA19EE09F1145E3A9B0E923E83A74BD4589F8F614408118199FBE18D1DD01D82C7FA3C8B0B2671BC5ECBA55A4E01793B41A47C4A91777B01D41BBBA13CC5C68C29C15D901D3402492C656A406D77D25933AAE686C8134479858D5E798C9026BCA90B1E464C923BED4253E8788228BBF0CE2455EC03DA13E406F59CEEDA6E206DC66DF4E5D959AB1609BC9705A8560315210A6FEB1DD7D1C1E0C441C5C601E2E322CEE9F2086168745B71ACA5D5E53BC7B32174EBB95C4BB2F9D67670E467E7B4AE54CA5DF266539BB2FB6D431D0AB36BD2CA406F5538B916C0A11AF2E0D3D70C1D02B672807A98FC3371E55F29FC88C2CD853557935F970C42462D56E024C3B39ACD3B8BEDC5123AA71AE3FFBAC441D3569FF0D9774CCAC8E338E37FDAB5287C1F846A01D3CA2B9BF82C2B49033C49F5EC12A804833C36804972D94389AEEEDE69AA56AFF3D4FFDFF7EC7FB9E6ABB247EDC09BE9AF22BB0B1C65F533DC9C20993CCC84A069256EBCE84F387C48756FF9137EE4A1340419AA4DE9B19A287EAAD82856E922A37C68CF1E89CAF038378429030D64180246D4F8431339D2F7A4229ADB615929F3D0F2956D1CFF20AD089A577DA40D9876C262FE3FB0674F61ED120B53B633158283E75416F013E90A58BA79C2076A37DE6EDB24CA10D1B19FA37E1E8F1C8489E7C7FCCFA81D8DCD23C8792325CF05A71C5DCC2B2F7B8A9FB9559BA08C157CD1B30A40D5E57FCC9956503501F63280DCC82D388330D2EFCD09945F1837BE30742E4A9B0086FE91DF307F4478AEB9E886F4722365D3CF70CFD6CD373E54C799A8EF00FDCE9FBD052E43A24DA9B22C3D44E12834104B2C5CAB69D0E01B2CC8FC0E63B823E960140F66F0BED9239DAE707143BDF8F4AB268711B8B0F0441031DA4055175EE59E00D839EE8FB4B5906770612B99F468A7F976D2D5285D6D8041F09B8DA554CE7A70DA5A40CAF313AFC23ACE6B9A30B563D4C54BC7BA2F3912EB0061C69D7B7C048E91FF3FE9B66CBC9F96CA080336F954852C27688903181E391680B92DC5D6D4B0509D00DF16914A4FE1FACBC220392AE017CB3877FBCC67315440E7FD62E8F2D5DF0C8E8860F5660CD80F38EAA7DB0644FE4568D47163FDBDCB7BB67056869C871D79717B81392C0C3D416D85672F905D5C7B16E3A8C1F75F7279BA639ACD01B3DD188264DB7E24DEAE942D3A159DA12EEFA7428D9FE5D1E91911C6A38FBFECEF45087D5B548EEB1A7FE15901389504F2BE30FBA9F2F45B13FF1FDE975106F24FFC0CDFC0E127CC47AC5C368700210E2918B52B4B2054DA994C85CED0152B3BF629CC5E5575E6F0485E6DDFE03DD452ABFFA4765B4AC6BC9FE97477D6DA3A9F1CB92BDE750DB0660E2D18971CF6970EDB80C713BF85144E3D2DE9472107B630EAFCA4BBE490D65413CEECC218B454F3FD639D468C0836BD6869520B1F98BEEC37BFF11A3E85D8E5AE9026D471994C143F28534B1D8347BBAA52C8C2AA0F5559FD67E492C634C2E6B42B571B0B355243461F543FFE37592C9959BE5CBE1A4A1125E851AE7E1E0B8257F88A3ECDC04DAE7FF8B03B2482F877D77F7643FB7DA840D906D8768E576D7B26B3A573C6580C7BBF85AC7D5713223F44321F845CD9B3D1D91F891B0F26C63BC3E85C42906A6BB7C273C676818ABA1F152454285B62E89EBD6EBE864CE2A477F5BC991ABAB1B68FAD1FE815EE019CC07B54E1334C9019F2A64C6A11DC64C3DDA73EF67F254E1D930681591C35EDD156C050E7633F2A2BB8E71D55DBCF06C5823EB5D6C4BFE636C67F2CC838063A85C466B2BD00DF5C23AC299A01CFF4E01F6BE026FA888F2BEDEE72A89C115D51E467EBB4993C8414F6610A180AA0156F499CEDB1422BB2538C54EA81AF17214568A205CFAFB6C7D576EF6D77A226EF8264B23F5DEE241D0E951AFA0EA19BFEA6A5A2F2C27A9C2BBD5B0BE97A73D744C60A8FAC2030C1FFE98F2634759018DF53A3A8D019F5AB44028A0F42D87D7237DB2426EEE758CCAC03A5CDBCBBD1640C96B9BBC29E24068D77CCED50A873AAB68F8753CFE5CF636A0B191537EB4E3D883F36FFFCEEC83A736266003B0524CF0D4C648425F6231223AA4DD74B082DEFFAA732CC09AEF78E526D569F23E616AAE32D200A703642FA48AA6000D6BB523EBEC389C768821A25226939E04C3A2763DFF595C023318D1CF57445D23816749FAACC136738CE3D6D03B1492526597D467310C599D509E2FA4081E06D60E1E2B7FC3DBBA79EF1F5162F01F8077D2A93D368D2C25F2844793E874AD65980D6195EFDFD5F186200031C5FB9CCC9911286B54404B0C2EC46660FB1E3D9E9127A6013E16719B456623FAA0E65960EB29B38BBFDAF7473577273C13E645D5DEC7E55E46BDB204DF8EBF313412FB31D31B7F314B9E9FF9A7B76B56A9AD30EC2258EEFA53DDE057D0C5EE86039AD894128100F94145A4A08C6F351E69711AF1ABFA2761118DF92548C075A4AC908359DB2CF0D15B15CB5A9B5E04D22DD9B666F351CC470F489150C466B89E0004EE308EA8ED1892AED3D153343529356CB43EF9BDDC5412FAD002A4155B1C9273814A924BDEBA922E859C85BF00AA91FC5809E2E53E3B8A3B8902C8F10CF6295EFDE5C04CC1EED6560DF9EF6EBB63062DB2D0C8BB32D8F00B3994F0F0126A8FFFF24BCD7B6CC9F8F4C67C0BF7F9CA2C7F8012FFCD28A49E98C17408C8376ACBAC54DA25AFB627FDFF0EB1A70851A70DE8FF9F07DF0C5A1F5FA9E93FBBD78A8437ED95418F2B36C082D5A7AD0E57BDE3A387E5D9CA5E57DA202B9BD4B2D64C8C222AC174869F7D92E469CD116EC2FFE5E8209CF041FF2E69DFD55D30A27F24D6B5023568D38B8E11BA29B2971F5D338116C75FAC922F530F1DBC721EADDCE18A71929F40A0D10250EEA1D20DB125019F3A24229F0DC935EBB6CE30CABA168E4A3B37611834D8CF97EC7D00CE789E53937DA0997710A205A269EE4B10E4662F5072DE4A4F8ABE180B32C1B9BCB4B0A66382B05324419543E742F33F70AFD6BAE587ABF05EAC014EDC6AC6A52A545B9E708F0CAF7E9B570094D0FEE552FEDF01E629FFE51FBDFE299C8D4E57A3B729319865D38E9314ECE2B4E7F3535B751E6C1C9D75792E923110C7B079D1792C4E782FAE9949C43030C247E3A5284F302431B80198AED58DDE8539B211AAB18119A7581BDE471D6E3E5CB5C0744BB10ED40A3F3D0EABF2514AA540F255434C7A2BA208755D14CBB57CD274A0B78D6DB52F5F6C7F369F68587725CC2FFCDDAA1CE66896A88A0864E5577FB2C6D598513787C736EEA8F24C70B41234A6F7A6104DA33EAF7E493A1AC3EE5A20AAC0EA044319EBCBECB65C0208397C0F4425D43AB3A4DD2C9C072A3D8C30C8173BE84E11FF4EF2039539486266D2399384E24B271D5A73D0710528F9A93676BA3F2B8F6292C7AA8B7185E818899BB0D0E335E73F8252B3197FF2B59C9F6134F819BB6BEC3F5000000000000000000000000000000000000000000050B11161A223EAC87B3D642CEAA3DC904AC3C4245CB2A260E4B74D0394D33D4B71024144180A727F80B092305F31B2526998EDF6F98E46933FDAF0E8709E98D54F13C2701C58BBE35292FD3334C5E03D345A9A2EA1E01B2C4573567FF1FF3BA7406A16F5A5805EDD760AC78A3AB8602E415F67C7CEA5B36421C79F83CBB14FA775448A832A4B28851CE215C11DCBAEE652CDD7342B6B1204727479E6208FB556CF08BF7EE230F32659E829CE4FBCE0955D01D36624BBAC18C1D25A3E187722F8F74C88B56E518CF0E78B3B0EAC56D8F13C4AFC4DA3613A41CCC2B0B0E2EBBFE5799E479F81335360D483596E9AE926751EC9B956555F271C2CCD85F0F6C1BBB2C326C29B5DDF6B5C4C11F8EED15C0143993FEB626543E92CE4D66C0BD28C79ED1ECB793A3091D6B9AB510B0D41AA42D70C2D8F26EA0B826C8C375E1DD89B3E2A48FE5D88A462DEAC33BAC35AA32EBC010AF7E47B77AD23653D747760914E0CA12864CD401787EFD96F30D82D8907DC68578067703DD19B2377DF319EB540E8AE78B2BE86BEE1C915FF3B2F4B25C0AC22CCF89BD85371961944D8A4E6D20E2D3E9DF3A07D3BF6986898786F0667545275FAC3EB0F069B457D8EBBE5F60125F94756DB04EA203451A0DE160CBCE2A34650D92F200448B097691A61361AC487FBC3C82B2BD7C1ACCA02031311971C3CF69BA459A0B640A702DB4467973713A6F2466560FFAC0592D64FF1D4A935220826EB559CFE0144EA4B8E54EAF67DDF91988DD4B3749C865008C0C1CF98BBF76D929B85C8C426C15FA56706984E0F2E90658FA3CC33EC9FC700976870C94035ECF9A0534B18D07F55923663835416E40235CC2550BD9822F0912CF101F86039830AD9102AA4A3B6777EDEC5EBE621082FCF81A1C6A528F0324EC9D39FA80B6E87D6366E7EDAA0E14337D6708F7C3D2FB1978F4F5CD594FD35B267F9CD09370D3366DCE286CCB9647A1944F8D8BE63E5EF8F6108CC5E9AFE9127DA84E1913439EC35A4E17F7782DF042DC2F7C5CAD8A659DB282E61763539B56C2AFA0F2B507D549EC8C9E76C7DB306380CD7B46C9699B6DB8BE06CCA15E8E83763137B06BFF02DE2738A46C61B70EDF4F394D54D0453DABF689FB6BA41616BC589CB9847224E74F919B6E03672EC6A52584FE81456D6E648DD6F0F9B068EB72241F067BF6B891A498A9A59356C735E10EFB37B3ECF47CC5620A35442DD81E25D2C6DB0E9E871301ADD193D628B30E3B4345751BC17E0B5B05AF758A653DE7BED3763303FFE1AF05E407F296C736CA6F4C348B25718C7A814BD0730AFFC057842AF3D9B9ADB12FCCD740ADD16218AA57E43835821A2BCD70F1027F3042D4A92F10D0A1FB8323E87869BFA8DA24DA75F8743FA3038C24FEDC0C987065421BF4B300BE3ED3F6D6D590968D3EE32A8F5E20EA6168756AA18BB78B6AA48C299C36D0E78B6F84CACAB5946C69179E461F4C2DD201D8032A29EC6C52942AC37D9C76AB4A401C9AFF96284E1E9E39BFF6D912CA33B6118067605EA65D7F611DD963F4F75F97346FFFD1DF84C79CCBA06804B3017775D8C0BF614FCF4D824709557937B22E1805A0A961ECF226F26E3706362BF6D8D1DD30BE7EEDA481A64961641DC57B9F0211F8EE43578E4C2B6507114DFFF3C3F884586BFD1278D117F7C6014FD5980CDF1E2FD1F34CCAD170842B9E819C22FAB9890AE265C3BB6946FCCFE218544D00A6BA5BEF5224EAE24002B6E83E0B35E98C2322BE2EB3D8234BE8B048C54E40782C9A24D7A8B461EC05F38A94AAEF3DA3B46D0D85B0D949CF1089408189FF97C56C7DEE50A004AEAD82C15C7C0D0965F3C65A9A715A65D29CD3614954EBD91EEB4E74F862FBC944C56F2EDEC4D344F92E8154708AD0F5575880503EF0F107A9A9DB99BAE82357C16578F3E6CBDF9B427DA88DC322D11C6AB2A6AE6F5179C94454E09DF5CAA6A519A4C1903C8F2925639E12AF793695F256BF0E55E0D45B73880358F09719ED89A4A1A07868BFBF16095A20035D5D4F99FDA19DDAE3E21CB98308F4508B5CEE706C27898F03A2BF14F29ACBF055E4AB0713A7B6FC1A7853EFD36E1290E69587FEC15D492A66B9A4FEA6E2BCDE61E02FE18E06F59A2F4E06F177B14CE4C1CF1A8D1F49C554A8A4C68B9937B4C230320C80753D4B071BAB2DEDA89C9181820336F1E766E447EA1C44E15CBB7C002C1813D2C1726DB0E4DE289466077DA9610E5F3AA313B1B01DD79A4056A8BBE9D843CE5B0439325FFDFE91FDADDEC6CB86D5CEBB68D8F9C0ED237A4648C412780ACFF48FD9CE817EA70D950DCB989EA6B11FD87EA4F30347A27488C5C15BE7FD6D1280FEA3A7C022F8D9881FAC93176DB2025B4C7914A51099893A791BF5BE851F325347484CA6ED51B2BA71548A6046EA7EC85B31A9967E7D119D2CA3A51C1E14D5A3EEF0D41BDD615DA01D45979007A1997DE281BC340C3203D5BC0075B1AA38873A9DBB9D18E6E26971E70B54E41E2C8C91D2E60FBF85435C1EBC4893C45A201B1D2391549F52A1CA3E0440ADFB746FBBF0D9933F9FA0220B3E04EBEBB29D2A9AC1 + +count = 55 +seed = D780D7688AF364949A196657A066BD48FFA8DC45B4885279B6DEF362E5957F398CDCE1D20FC3F8F63A275C325FCCE654 +mlen = 1848 +msg = BAA4A41E4B68FE333FFA5EE97FD3DE18F0EECE8EB83E46A8E3505E2EF8AEA2C4040BA3809A764B681EC7449F41A2463651A8CC6DEF0E4A058EB843EF016E5CBA8D55F925E66524BE55CB98FC3169082E52E0D6CC3600C4E8A560B6D448A72CCC95620101323F98B43E28D6357414185ECB0263C7BB94E7F86146661FC897844CF52873114D39123260893DEF13516F982783B927864B61B56D3A8E5B4705DA3A95F6D12A6637C9CED02F07B4AA0B08B4924103036C2A93B31C91EBB6C5B77DE090EBF60A04191EB6CE9CC9B550F5B0C9104B74D15358854181C0C5640FC74CAEE14FED6577FD75EECA14070B6D02A9A421247A5BB262D6E62B04649E75BBD3ED8E72752289FA7C1A68096DD96A4BAC8A2DC27C44881DD2416387D74A005680A3D229D562D3DAAF8DC37B4C87CC86A8C991E9327CDD43BA930CDD8D1E44AEFB084B51111965C5DFB0EE2F09112B070CBFC545119ABA823EB3F65F26BCC025B39F79BE42C0396C5FC9FC924EF1B7EE9DDB71B6E69B579C0A64C5B020206CD3515B8D5F4FF29378B9580D282F7E5ECEEB5CE9C09A7B334E62151100CD658DFFFA66F4091231BEA6C9DE8129EC4F5FBE8BE0FF4BC93367DC69D9E38C177B23AFBA5C27FEE3E2B73C0037DD7C419C854DF7C2412349BAB43869469E80527C3AD3A7103152F9E0B03353A596002FF54ABA8B14AC393EE52EB5564D63BC2738D571FA3C255ABD20102BB299441B00EB988F3A5CFB238EF8C49963B4AE8877E6B317E208821510BF446CE6B06C33717C91C460924248382159198F09D0F5A25C1611B2D39CC6D2ED149FDF0E09A0B0B2BB77067182E386F5F6A55B68808DAD98E5CEB0FDFAE6A0315845ACC7B9C172B0E82190A5EB7C58DE4F86D883292A883045C62D6A1B3C886C345AA6158276EFA6B93AB2188E47ABDD25D332146E980E1B1E043CF63EE35A5AA01AB6CC62F77699DCA16FA30E3632DC5CCD3253D01E547746C78021AC307F0EF1A0119AD11504803EDAD933150981C4D9FD181835C507651DC92A86737E3AFD0EB4DDEF6182872FBD31BFC6D8427C2F4D3A39BCBE6B5120B8CF2AF5DC59949C92D10B1C6A96810564DD335E0755F9DE25EC26C102355688C38250DF8F96E105136855C8DE4BDCD86DF03F92977DA16908CAEEB4056F4A5F751A57BA057AC0309F1C107E594CF3C31544E4F1D93FB9AE7E1A2451E7082CF0C850990EE71ADE0498F6A3852DC4FC128BFDB8ABDDA3D759C8D4F83FED8509CDE5EED38410FB9F0A5F30EA45C9270BA2395DF645AAEE03F56158685A0BA65DE3D2C5209A7EF4BDD4BBE0CDC966DD1BDF1FE0BE06C7115F7CCD80F8012E5D17955AE0C9E4220076882F30DC5E391295994B9F809C09DBED8CCDFC89669F40492944FF20948080A4ED66AD8166B613AB2F4414762AE493EA6661950E8E56B3758A77CDBCFBF24FBBBF20EACD5CBF8815899A1C3FD20B1D04920025885388012D9C58EA842DB9530B7ADA901AB9CE46A12700687BDE07FB99BF66D0C775218B8454C936F03558B899B59361A0C664081CE8A7858DDBC5E7C5480280411C9ACF4D1EC45035D97524E9E44F963532CA5067609540C1BCB5627F99D5C61CB9A6D400F0BA0A74E45DDAB5A4E8A765DCF2F3684E3A2661A78AC069FA38163AD9F9713EB45C841C6617697CF8A72C54B550DBE9C22B04D579B09AAB0EF4EE8B70CA563F81EF9700C07761C944926F9A76A8C3EEE1CF7E7524D65908C47C35B0453DC10DB5B75123A5B26B9612C0AE18816A71F34638798DFCA21F5073CE771500034F9A71FEB8B621356C430B4D47CB1B59AD4677B5C679188D8861BEAF52558165F691F65A692E8CB8D24ABB74B8885EDEBBE52FB13DAC16E3A8EBC4EF192FD10D71898E93547C7A09F8642AA3B4FAAE23E48BFA809C5989D3462AA50FD4E5C4095542C45E5600926C2DECB4D18BB43B7274239A8DFA3D9DE1BB9CA099DFE56DEDFC9E120867EFCDA10B48F7E630506AA606D76E4537036127FA05FFFB8B8703CDC8DE70A78D014872111A431F393345D74E8866D9A9A633923072E93DBF47C54C4B205C60E67D5155B76F51AB49ACC7435525605DD43A10C88A03E08E257C68937BF2984BE63D40F8A60589D909F8F09688A77DA15DC7B4853339F235B1BD60AA845B4DB6B699325885C49DF9C40781CC56FABEA6201E2F8A9352C28CE321B9441422807E9C81C8F1EC85D240C9F1C8ECC4FF06D6E3682DEA3E6CF92F2B74C2165AF247CE0F5AB84460693254B523498A57E7442977F51F1C2F649BDF756E7F43AE543F5D8E692820F8A06322667A7FA9C1A5B10199A69CCEA22C74E172FED43E550C68C337ECC5E6AAD9F7EB997A7E619D47DF73CB917A705C3CDE5FF344F6FBCFAECCE6B734E09A385FE54B224A880704D774581074C59EB0A3B42C59B8BA4518E764C5A532F6655DD839862AF716903A118433CE0809376A88E88FA847B4D1C63EE393267B15C1E42A91DC6107CDE990EC9ECC7C1066E9480E90A22907C51AF47DA837438A90CC07DE8121691BD73802D5D09D18A2D8B38A28948735110891D1B559A73445838F359A6FB90A3CAB887486CC9D95CBA35B55693C890830D2 +pk = 448B8E9F9CE85F7FCAF1A2C0C3BBCC9E0ED82FDCE983E3FF8CC819DC4A037D844B1EE443FADDBB808D027DCC2C6661FE1D701D5919AAD701D24DF108DD830B576DDED205E966BC74F61383BA8C6152C88DF2DFF7925E4C02290C489DC0B346EE2314BC1D380CEE048FCD1296A85755093F867792F7E59145FB0D719ECBA2D908B9252D862F7A89209ACF2092C5852EC98A61BF19D66DC0834B3EEB3CA39C5562532C5968DB487542ECFF5DF19553FF2FA0D45675A62B26647AD64DC3FE38EAC9AB1DACF5E830C4E8B5344FB84C8B584446267560AB6A9D7038BAC44DEB500CC3BF62E11A2A9D2D01FCE3263CCCBAD77B55F058D69AF1A86C56501ECDBA3566FF432BB6832A50906EF686500319193A95CC4D27B81C4A245A88825D9ADE4872A420BCAFDB50475E405D45F2C4ABE38AB4666E3AA5CACC218CD11F98804720FDFDF4A87A7AFA55CBB55347EFD4D7638F6EF60FA29DDEB63FBFAA3638D760E2741B5D072CDCBBB40C18FCB74E0D40BB3C1DC18F65E2338036C985A7518D0879933CD72D12FDCC305A6826E69E13DAFAEE6DA8E1887A28D46392CCD72446B7E9C0E946E44BFC2109F5488B4D9E6619D05ECB0C4FADE5520D01749279C686ACBAF709BD2FC2521AFBFA2A2B21B74DB4BBD1FCAB34D75B9150B838ED509EEA3CFD11C6B9F288B9E02EB4725489C43A909166C26864973C0FC6F695B2065946B5572A7CC376935FEC6AA5C1000A7F528CF03176BFA49946F6CA63896FE4A219F8F8775DF6E315E2B0854BC48766C2963DF4C7C5BA95DE0816A3F43F3D7DA7FFC0B4F043EECB2F87545FF23921E97950D8DE9A411DC6BC8015891657BDFF70BEB3F24569344220C203BA74B5CD76816FB482B1023DB8F938F5A27691FCAAE7733723A7ACB6D6A50C05E1B36B885491376CAE7106BB997C4DF8CE70ADC2675FA0F693989D492ADB46C4F39F70D3EFDCB86FF67E0DB0C004CB6DCDC79B2A870C7BDE47477534468A9B08BAA2204ECD8FBA99F4D7902F4F513AB3648FC32CC9A2949B3667065F2D7AC031E0B9326058BE2A28CF9B6B6B5364ABFA81C57A126065AD45033160F9FE0B9732F456B0B623167C2FDF587AF285FF4367D3ACBAFCF1C4F736A91A1BF38CBF108FD138F3AF176536EC61FCA182176B05BF57FAEB0D384B4165BD190F19FF5CBB132374D3C3AFB95648657562C0380E519509CEA0AB2E70992A8C219B096697B873848CD70DE9D93551B825EA140F18432D8BF368D20DCDF8E2826432DD73484D0D23E7A115A7A8C718FA984F2194012FE453C17DA2BDF16B1FF262800B190CBD90505060DF9F54AB6EA70997F902F0933CB06D6B685B75D7A1B0A86CB2950323A440573328129F802BB03DBDE61FD2374006DDBC97B6BA70F2D9FFBDD3D683E818FD0FFC20122DADB794964A460486D04E3B16291AF72615340FE4782BEFE23DCDA92A2F546D39E981DE48A1914FA1564093F5FD51202F2B6199088B836BF10CB5C31EC02ADF7D39BA3D1941DD55C9D14106C4218C46ED6C578A43DCD99EBE94E7939E62E276F1B77BC709E3291D798E89D9A8B31521FDA4ABA064EE84047EF4C43642EFFBDD946F266A433BD53B08C38DFAE5552CCDFD93F34B01DBAB3D5EF683B3572F78C98FC6171E3CABB1FFA5E9E75437E7B5F5E376B99E02FD3AEFB287530C60259ED95E886891FA4A121A9B1042453C491C65511BE4334F743D6BD0BA18C06E1AFFDC66775BC2B6B82735D826E00714AB4BC7F874D01481629DD1560C668BCD2C88CE7F0A031BA4D37FC4E29F9D78496BC96EB5CEF59293540634A874A0EFB9448E69F47009947997190517533D93E0AEF6E05178513F5812CED1F3F7DB8CD5063160BAC031EE493EBB3BEA4E572204231BE7140A291B426F52F35FD034D64478EC2A4D2F7CA2727DC5B8CC9F05B4804706B25919D8BE9745635E794638A89663558C5C6A532E02F173726262F6E6982651D89FD2CA10F7E320AF0534377AE8751CF6753BFBF60D2990BA2B43FE2D48F05AC160587D05A575F68DB824BB21E230000BD316599419B8FD82D43EDD94F0A54CADD1F4E9D868DE110D9311E38706E70E2842A0823BF6213BBA4E7DFA32C23AEB1486B9F061D81A8808EBE89D5FA3D4BDAE3EB196C721AABE919F97CF4A8B9A34F5D0C077625EFDA09331CFE29A1099C1F63BC3E2555576E5ECF53B8398DD5FFCA4B41A38CF79FBDB577A81EC268FEF08EE066134697A3F948A1A034C142FD422345EC0B4731C3E7DA6BA3577DD4CD7517D788D0D9F1F12CA6781589F6FCA0FF36043374FD974C704F20D17FFBEB6C105D715044816DC74373972BAB44EDA03F70FE7D001A1EAD47EC1385E853102722C52CF007580ACC960EA89AB48CB4DEFBF6ADE820046909E9C3B5403D0CE485178E58CEE5442EA4B72F2F461F299305BC7678FC0026EDD5A5F15900ED2F973F8B9D35187E19A85CABE54E6656D9BC4C32DC3EE8D53654E8A05D1BA898E02E337D2D2262593C01ADC0AD9D42EE21FEC906CFE5A07ACA8B963FCA3A827C63D9C232C9A613C67C6A1B1B1CCDA1C970261F6D2DD035218C631E87091AE8DCCAE84D1DA15D89ADC405435CB1FBF475879A2E735F7849CFF621454AEB1B618B1AA5F7756A4E7700A128C5EDC19570DFFD6D6EEC48E9F1C0B3CD2EF99254AFC0EEEA0849EB46AC9B747CD5FEF25C39CA65060CCE8D0DE6909F8FAFD16D969F120186DAFE099B82D9D1C40FFC4E443E120A919A21F1105CE6848EA56 +sk = 448B8E9F9CE85F7FCAF1A2C0C3BBCC9E0ED82FDCE983E3FF8CC819DC4A037D844E8131A076DA66B3DFAA14237D633A29D0D8D98ED685A537DD7BEA3AED616826426CE26F0F6688EF68081A86B87269DB437F190257ABE7564D4FD19C5203513724078B92B88908BF5622FE4C1770B73F39A50DF2A1D356B4BF99076DC9CB81FC3132303683405061052677721501005828114568268625803643815461320482413642230715724644887456643718645405255521002022172460513832617003272650716601370242551275734153118033837300013526116872813545077476752044555531607458570481070086263538478046733438375818713483363637124628148838840118554743267705043222638101530843717173413871271011143767607308685308085026266774737556553040425636131604523817106438072677163628530431408413070045740082468516216340014651103224771280731626284015736557800284128457351212031530874265280233632705468604154341574274285860845341570035560643674048675877813787284671065741556776120010103461742157436380812054058333465233674016772670107475031416683527578083152840587031033843585040245752072026756304716565754644050875246870457855448566356001473471870627365734187440410130871774850625162236766801406743673575658288172685135537734511703237560701476578168474275353611366436132823285102866115311021333013752267353171063366727555151083366545181514148114268518246332085421462632424786140876661878216777267447348230063144866828766646477405052568037568825324462823481354206608018165578103331760635535122816515523826055041661525148635066786853500085871110753675485701514450071783380453485637212700605504777776571527126156180732204212026365021315288702681073405206288750383401050110322413167481641501328071460444367811406027780037238107015747172612311553543860866336573882816733224221418106364608735025858057664530561038210333886267065270440507001781020144610861771177151155232541504572678335151383310878251656140146338284244035344223257862386125801084154416346754116470518283230831886135251318608665533828703478413070087764338363100744041742242346672340251268712561107124073881347242652781865526810684527758847016522340620808221304167401070417336645083156034638033527210123180462233071724202545611121144188807813845431871045284783667223166680486281270504477251453553058071786413455151381083448601448587454270158424837270050041433124227503203040733576870118685580465316468146341452703616246751557076721068848587604215417405012138484808452050264664627742805201452656881415784824767035074181401880654666161768577063622434022684844705175585824312601858515046326181705083606431428586831818502230380880728732147874177305347060148878778217812887216034256862768000534883537703385607184314072472738170628355870215110348875587130525436837150725730222772687445437706582073772420716548173574126876330377710020124401701763620771742733521635301233405822858062448261341615463620250145688746660815585272640661518153256258534567467532635506555156504663741323846442875755820445546281370785023011743474164803135055668000833422358078328741748523227173311405755440682888027336210214215042842347847055437861000713833750402381488101186888675432548688588656013018456812661135825875722354378613874486381236220028680870172625505430864246BABE696F80605A9FD38969B97DCFF7970567113437661473CDF3CC12AF0AEA82880BD3643590A73FF729FCB3C1BA7A1814C4AA595C7B04945E87ADACEF74D5561AC95D70D78E15B5AE5E2DD56F7151507EE736491A32FC874D5F2832C9718C48BB6EA68C75A2104843482E588E1333C152F31C491A796D12AD1DFA89C3007A908B76C309A5B9038FDCB835867EF880E57BFB2C78186C5B973C6306C725BC0AB1BBC04C7276D4EB487DFF62AA46AB7D28BCE8AA8DF759A883B5C5DEFC38B52613884B94AB64A3F0A16DF6D682C20A5CE60C075A32E91A82F131AF7708D38B41E57B3E8349D0B1382636D9911F5CF9C45A26F8EBC2AF48A9060CDAC5789EDFCBAEDF67F949FD4B5154DED766B517C911D2835FB34BF3852788510565DA4E0240D50BA303C2E15008C1311AD75609F683FD7D3A05B07EB782F59A67C275034669785A60FBD136582E03BF2E92FA6EAF2AE9B72EC8FCAD3D5B6AC20DDC522693B7FF32702958E88EF209AF7957B06A87EB48F7B7A45DF90F090B12C1D317EB79229AF718D75B745F35CCFEDD216B940C74E3169C93C6A9FFC40D262D388610D36B8151A03929F93C226FFE28CE9E56CB44620DE553789F96393030E99A6C86B9893AA7209D2E412653DF39617081DBC7868C47C868F20EA0EFAA2F9A85F432B4F9C70A7EE7BC7A942C7996F1E30E19947E83D21FBAF8026186E25E92983E126B6DC2F6F3E911010BD982CC59D365681A3EA7F9B9355B5178F1C893B06193BEFCFFFF1184630ACD2C4014D71F3DA826304D2D5A799224DB93EBA2C421719D675E6DA256856A2CC8A6DBCFD33766D211A9D25E18FDCE3978401F5BAB1907CF2719B839F33CA0454978CDE88D2DA4C644E22FED7A6FFD3B0E9BB17F8507C194A1044A5545B88D578EC44690BD5A6FBCAE072A1BF07F28C761B3218E2B578D160A664D8B881DD66992AED902F8C89C981523BD5FF8079324FD2761A6A899E4381CA587E19ED9B697473C31E52C778D4DBBB5657382CBCFBE0DA70148CD8118206888CFAB7214EA233452EEC1A55186A124067C5900C145F64D8C306BEA2F4EEA71F3511E139713D3B1F9F0150B3D5A6C01F1D4182DC0FB191EB8F4F147C76BAF5E22DFDB188AB48B499A372723BE6C7D2E55F5857402B618AAB7C4C73304FC563AFE26A75C467223ED3D966E335B2102AF8CCC3DA397ADC52EAF549320711A899401456C8FA0325D41A1F466A52BD4E96464D7CF32F57FACB4EB256402DB5C063E94AD1A6020F59B339C8ED84D13BA39A854900A7E326943DBDBE5F52B54444564DCE32F1F6F7F3622BDC4A6B8846321C3A7E95560EB18A7C48D234FDA6330C36F7FC8A8A7BAEA7B4338D775D8249C22D1B46B1AE33BA43534CE811284B2D451AF955CE5C5DC14AECE55275CF8CFD4B62F90094BED7DE4B72489265E76DA3DCE64FA0008A9E0355C645566C945A9BCFF125F12712A572520D0A83195987E8AABB91B1352989088410B630B69066BD155843010E4ED21895186E3380D23FA2F477ECAB5FDC47E6C3C139F7F3915E7523BF314B2AA9E9B33AED644EE2110C8CD6FB0CA8F5FCDFD93394E3F042CCF002DB09414A0FAF2387FB5CAD8150F929DB7DC2F48AB3C674D7DF9D12FCFDBA41D14E389FD76602F55937D46EAD0E38788C300274A63C327958F018883C040FC5426921AB0B14E46CE6902B95EA53A3671F53722ABC82287D144E9704A1842CB2BBC8AAF9F0F84BAEAAA1D2D761CA13470148D1C1B37E5749937EAAE1D489971674D6746CDED18B3121578A0A829821E7D2ADA7D3E4548DF22D2BD3D8AC400C9E524E14200BFBA3C731493B6324E3B050A97F89A2BB14F7CC6E8B89AA2F3321F603563C3837C96FC5051A8F5A461FEDD5421A82E6CCDA9694FBE539F640DE8977575EF849306ADCCB657E2769B9114309E0BF16E02B4047A1B250B69361FCB43D3ADC0EDA5DD1950514E6AD000C174C4DE285AD105E3EDD7BA5D66FB2EA4C01AB907D1D1CB01D9AF06AE0587607D594F4331DB1F9EBE8B03D65170C99D3155E9A719AA30539674CF5308979D08555815F233A2CE04A6E203B4D5E06A90F07DC2A3B60030CE8F15A35CEDF21C41B6C02695CDBFB01BA866EC7A2974445A8852F4AAC391AAD6C3B18FA4BF747959D4D234C5CD74048AACC4AE8A1BEE6E1A6409D7F2871A295C9EE2B86D95C3711735A727CB7CF25A470A2019E768A7C9115C4C1F3613A9E5D867CBB48BF585BB393757EAF2C42B27EB0A24E9DCD5653F5AE40C68C7BF81858FD3C67FF2A5CBB109EC1E24FD46B05939466063406A64C87C2DCD4311D7C68D5ABD46442126CA0FFA527F19A8C3AEDA1F741AE2585CFBE206609178DDC033A407010ED6BFE363D4AB1D484132037A5F09A088C33B64E7220A9B7F0E60E095F4C9740B47000FB97373EF04937E30A8BF09DB445E56F708771525D6D6092DE12FBCE2C2AB6216D80620BA11BAD9A4835CD98985409950D0D2FE11778E1FBF726CD5CC72780FF67F0A1EA5048F620033ADC077BB894C61E2F16E9885E3E875893F156A38E565ED0DA10B7A6906424DD0E1CE9E96DBF618FA07A225204841FFFE10FCCCD1D2D2853F9A53E44E61059C4DA39E1CE4DF4997DE4D7C283747A9923401774E8F8025E0DB13823A915F18F08565E9934EE63840D3911F9A1F02FCEFCC51CF217315442DD5A1AE098E7112942D9C6A032106659CD68505B1F3A597003CB60F53B8F9B07268EEB49D02F8C97BE8EBB6A068A2EA8F582D79E9DE72485CB207610D658A1EA94CEFBFF1434885FD120F8442B9F3E9B9CD91B689E15D80DF3B8EDDC35A90B2B6995A219E17F828D60D76C6763EE9E979114A122982BFFA990FD96B947DD0DF4269F9B1E865DE58EF590911A5F7C5649CFDE37418FB0B76077D14B86EE2B39EA63CCF42EE1A6F93C579B5DCF804E61562967EEF1DDFBC196821A1FD541C9AADD39513149F3E8FFAD2B9EE1DD0D74376B86F29DD3E5708B9B21AA7F3748C3B418AAB7F6B471412A9876606B8705E07B8A5846C88D638AFC4CF0FB8D4FEFBB1868926000430CBE4BD0C6D61D4E6158947AFB068A55050BCBF11B57F899CF42AD749AC717E7B677A79B6F5669F7E085365A936190735CB4FE0C4DFA5CAF2D7D546EAA3B26224BE0B627C4BF034F38B8A7ED8C1BEB8769D5FFE811700786B23D46C918D283AFAC3323AA333EBA92148574F58F813A08CF5ED0C0B6B5B593DFF602BDEFB8DA45BA3C58E9F39C394C12FA161AECC6021C0A3CB12CB4A5C60243EA88946EC3D798ACFCD39916CD3A5A3463B5420C60AB57074AEE39E8881A17C4620497FBF067494992DD5C26E0CAFC2D98B51BEB957A6B268A31A7C1939EDD3537643024C7654D40CE7177DDD2C2B5D5EDB1F8F5C4679A4CC1CB588CBEC994342D37037B92B4D197B5468D43944063663BE83A208444BEFF68D1BA34CA82B44B60904BCAFCB89D0E4AB1EB0623DD8AC4953CD5363472540030A017CEB789668CC315685F18419D9F7BCE8B1745E2 +smlen = 5157 +sm = A1C8C6FA4CFF89263F2C324C1A03C026A1F4B0690D492F230CF49FCA9167F163E590F88BEB68AF7493BFF6C32726318FEEC7CE787F0CAB11D0BE9377021012FF88329E0C58115EAF89BCD386E6703F880C8D55330F9A7D096605CD60C18DFAB56521A0CF678E43B614ECECFE25516CB58DBA50904CA1AD47B2D95D84B603AF99DA16DB83DAB1FB88E98721D363AB28DB2D740D2837DBDCC2894059CF8EEA0CBB73FE507C5EA642F883889FD13A3028B59D36E4E7855BA3EB0697F262B41381C98A2108284E7BAD0FD1C865D446965579BEB6C4AAB64A119624E20D0C6BB22358B64678379481470762A03E2D735AE89B25ADEA59F7993205B4377FFCC74E6E0B62E85E04680F7B04BE47153BA49867DE92F127D69CFA8D4768D137F9798C9E5346B704AAABC42C02E2BCFCEA4349EA06897947C3EECD9C7802199D2B7292D1D745AFD036A794326E9823F413D94C26CA0FCB182418B73B44401B06A53F0D0D732D8D447BE787C2054388CDCBDD43A07C56FD44DD3124ACD8572CFEA29E7C31013E61577AA030E981624E6D164E8142C366CE71265A4548E0C75C5430D8A3DD0204B9D1B54B552DB8C9898400EE5B0891C161F34C231727624AE0B11E2D3A92C4182FDB7882EEFAF112B6C18D77E1B8BEF4E920069AE9F5CCF3E9254FAD203F5B991CCA06FE9822102E3A62C655FE248737797F2E52D92F991B1C09BDF3038B327EDB58C602EBF114BF4F391B69DEED698C37D19F65EDFFD93CEFF18A5B4CBF1577F28054FFCA46165BF69C5D0D7EEDB0F76EDBAA43480C6A4A37D0358163AD051F365FDCAF396FADBEC8BB22752A011868A2AE0675D172C50DA3A58D82DF365D97204A7D1FE17B6E42FD7296BDEFBF79AFAF1E283C0396DC5726BFC37AAC96335CAD3BD7D21180C23AAE5B429FE19EF9406FF32D336BEEE800848AA42DBBCE480A49D02020F2F5D2BBA5E73BC5CD3C80B468A4FA13BD92A8BF6C3806D2C21A06DA0F50CC37EBD4FA1400E74C1B796F637B1F30663EC6D8E20E3D0DBC30BD74CEAA0D0A05E57287666166CC47A36F4E42AC7BA92098C18B9BF866772468C3852F12A9E3121BDD5E2EA3EEC94C4F39C322D9CB88E0576126ACF4E847864814D6F430FF802B95791730BD58A808AD2FCA7DE8C0B0B827FC8A37509CED3F946E0F087592C20022CB74A0AB392C11076960280669ADD87B9087C6868B2A995A059CFC757B671A1DD30A244AEF71C745583820905E83CA715C283A630D701A68E41A464733C8CC67DCD3D0B7F69DCFDF3DFAED9A146DF4CF002D7F9506946D661107496B9701A745D4B44530E477E8CE3712B83CD774EC26C449B60290A957EBAC88647B958915227A551204DE2793E7E0652F45160A84BC6F0729994A237B77FFD1009825DE293D5829F64D239BB300FFCCF24853E687DEC0C699A24CB9B02ACE24A975446DE91DB4C6E4DD9946A176874BE3BA4BD4CAFA3CE1BD451C11EDD113A476AECA29E1EE5C2234528FB135BCDF5346C734BC6A50EA2EE5C1A63A390CFFC06E4A367BF7ECF65BEF66EA4ED79C2E092997BA50AA7C66D160E3AD077C817905E741C0BAFD15D86E11B419B017A3155610F3F4A05C04E345D8209052C340AD699329A5E294F353FB51C6765BDC75429269F1E7D20A68013202FA77DDBE1F36357D94586E6218952F2F1C392AF269B83D9323D84D8DBCC4FBF01D3AA01D7B21EA488AC06E20358FD0CCE2F5F079B3539BDCD61704A3EC5B3F423A054E8B99751C5A047D5FC024ED75C305E5A7C3E5345B9DB7D724C5A36EA84EE99443D7F7C4BB3667DD9D08EF1344CC4A4E8E6A6395554EB1326D75034331FD3FA429DC9186B17AF59072566D46EA45F1456BD3CDFB02BA31196E6981C01D8072458F8DB37797301AEBB2BA0A445CFF598951BD59852B0709667A426751D06BE74BDE2BD5C793B99E12E6C304E7C3396D07D3496EC3BB3C8FA8A25CB3C8E06A5100178B24076FB2B3FA3A075D5391C4B7F05F9794BCEA5B105FEA362D70AFE03CF048B6E6C5B03B8ADD78B260A6AB3BFBF9E74F43BC0D5D8DDC6CCEFE936B9B27BE58EFC4DCBBB7ACC6017CE483A5A2FDE4E1D19A4CBCF8A75330A63ABD6AC352D222EA744E386F2C15DA01E5084BAFE6F485D6F6847C743B8727FBF0BEFF4001BDA9A0760AA9C1916F508D36BF1167AD89990CBF9BF3DBA562FBA176C6CEBD5149012944358598A92A6A55E8B62CE853614DDC3AF5AE525B010EE0EF796991F00971C77E13CC6A133239E1F347CA6E4FA0E0AA1E19A9E522F2F67EFCFFBED7F9F00BE9C95EE7038012EB252A7C196BA718388655C81C913D9829B0B2EE5265086F1491385DAFC864F25F45CFEC7DBDF32B19B8A6B7C21E07658FED52AB27C25596EB8378320E49D8C2689D426EB3A69BB52733CBC8833EE01661B8B98812CE8DB8EF7A7E449A287098C556AC0AA958DE62AD71B7AA859F18E6C7DDE5AC4CA2B2AB3DE29503B7FC62DC189A77E0A8AF3589C375D8BC89F96D7537657BFBC776647BC75037D6E26F2B30647BB6A272AB02EC5116CE94B25E38D69FAB0899F80E1646532B629682A03F4E023ACB5415FA4EAF91770D6E7458795783EA09D0BCFACEF6513D6CD4F086CD41822D0350277FE9F12F25063FE2EA9E6850EEFB08379B37F9CCD53476EC6923959E32F9D7429C74C11C100B5ED0ACED8F0392EBF27FBBF0ABC2223A6C1A2D648B11E43DCA7898CB12A036AFB963F0C657F3D5200EFAF8D6530F075FB12EAEEE2ACF03830B0A2C27891B827720CA177247C08A1E3B574C617C87959F1F639AAC808154D62DA1AA8DAE1762D6084E67F63A0FC00CDC12ECAC91E3CBB83C0C506BD9ED0C56DF23D0D39C89A64492386488CF055643293AE8DCF485F174B0BC834BD266A1D1F35E0E37B8BED756585CB40D497DE59196D3572C4C0781CAA9C84F58C69507E5E251D113EBC226C6096E5FC8A7B4E69945EAC00C9785D1969736B247D672F329F49F7E82D7AFE48D36C7DB4B87E24E8D454162EA1D8072CE4D865F0F44B8D4D41B925334BB4F8C63ECDF7BE3F3251855FCA25909E3F92B3E9592D5DEF65171065356FA11BE6CA993BD97CCA055C7E464F9AD6D6A533DEF2CD1FB7D16966533EB16286022FF11C9238201F5605486A0B7201B8114D50EEFB38F02C7612739D0E611BC541C525B1600EC3D616CAE7799CC0C2E9E963176A794921EEFF7646689C499F53A563BCFF0E6988C679B5A490456275A11C97C92DFE2B8C6F89ACCB09003B63A85310248344F87E37C34DF102F5EE3CC677FA8A422E1E2232964EA20975D5BB8804EEB65DF1FDB23B2131A8FCFDB6FCA630824FE59BE852E947B8F898C585EFE5D5D7FAC4A07D4B925ACC562537FA9EBA28DD40966ECC958C7224CB5E9D7B9AFD33C0D276A20A8604500CB16084F3602F019C07AA63FC093D6E80F8CC0D67B65493B28C50C525F822B0E3F6487123DDA4823D1BDBC5AC784D5F819248278E73388C74CADCDCAB51B763687DF75C788794816F3E898C10ECE1689722392D6D7FE2BA080872EE0E1130A58D8FC07AF4BEECF445DE1FB1DC3E242006DA4CD57C64B48A38E7881521C15F494D45F865F5FC26706BA4D0185DD69FF884BE3CA78BEE10C86FD1626147A16F493E39FC83851D5E603C95D34488B97181B6F468B19039A77ED786E4F70D1625605AE35CA73B0196F817F2722CB59873958BC0CCECAC8F62464598FAF68BFF2D06280B84BC861CEF09FAAB1F6C4F1434B44D9EB97CB13AA3F9A4A2DBFF8EE40363A254AC27BDF348FD451B500136ACE36D99B688C1E43E375C749FB19C4B51030E1444D8152D71EDF8799CC6A2FA7A2177C6CB84F89BE40F338613300CFB7B61DDB8297FF83F88E52B47D40204B52BACCD1673925F6BF40C25D8FA83E787B26BCC46A932AC08007F21FB48741FD205913C66D8289FC58A339601E2A1293BAF0CADF8DAFF6223C231C003CBD8A0CD8B2EBF96B38E46A49117A8156F8D9E415CCFA93EA5ABB9B0097A4B554B5CBE66A98A377D26D0AAE3800271B0FE9927C017667FD42380DCA08A1B902D6193CCB88433D5CE06A581A1CFE34D43A0562D3CE375BB2BC134580675D01A8FBBA4CB7F3A5504033B7CC37AA45896AC842AEE9AB3AF62435FBB6AC1EBF2CFDD1599FA9CE2DF4E03A7D14BC15F9E604885D6A6ABDD244CF7D7FFE3783598EA1F90C2F4926DE6FF903C8DE71E4B5E3F9EAAB8AA46CF5271BDBEF361CA47275F4881A4A6AB2E5B31CD4461CDE0DDE384069AB08D1BE01BA82347561EFA6BBDB7C5A7DCAB6A034E410789A92B41CB730044899EA802E51B241266217159BB075B4294FC18F2BCA1028084C8B713969EADCA061CE77F68EA040E07CBCF5675E20A31B6E2E622D23908F6F06CA42BFC7579A34175A3ECB59E86282CC0DA6F278548D155099C5A8AE67E855285214FE7E7C37E439DC85B8719A2A4F1AF399BF2950302FB451E54D659B1EC92ADFDEF7255FCD4271723092BEF4BB5A4E51D33FE7365F8D9939A004F1B2B8A0F28244985FC996A7AE361896BB60FCBB07562715C18F4F1CBCDC96A88422F33248E053EB7A4D69AA3243DF226E415FEDFF0DA0B5134953596697BF000108181A1D3260898BBF33486571BC213134444678C70000000000000000000000000000000000000003060D181D24BAA4A41E4B68FE333FFA5EE97FD3DE18F0EECE8EB83E46A8E3505E2EF8AEA2C4040BA3809A764B681EC7449F41A2463651A8CC6DEF0E4A058EB843EF016E5CBA8D55F925E66524BE55CB98FC3169082E52E0D6CC3600C4E8A560B6D448A72CCC95620101323F98B43E28D6357414185ECB0263C7BB94E7F86146661FC897844CF52873114D39123260893DEF13516F982783B927864B61B56D3A8E5B4705DA3A95F6D12A6637C9CED02F07B4AA0B08B4924103036C2A93B31C91EBB6C5B77DE090EBF60A04191EB6CE9CC9B550F5B0C9104B74D15358854181C0C5640FC74CAEE14FED6577FD75EECA14070B6D02A9A421247A5BB262D6E62B04649E75BBD3ED8E72752289FA7C1A68096DD96A4BAC8A2DC27C44881DD2416387D74A005680A3D229D562D3DAAF8DC37B4C87CC86A8C991E9327CDD43BA930CDD8D1E44AEFB084B51111965C5DFB0EE2F09112B070CBFC545119ABA823EB3F65F26BCC025B39F79BE42C0396C5FC9FC924EF1B7EE9DDB71B6E69B579C0A64C5B020206CD3515B8D5F4FF29378B9580D282F7E5ECEEB5CE9C09A7B334E62151100CD658DFFFA66F4091231BEA6C9DE8129EC4F5FBE8BE0FF4BC93367DC69D9E38C177B23AFBA5C27FEE3E2B73C0037DD7C419C854DF7C2412349BAB43869469E80527C3AD3A7103152F9E0B03353A596002FF54ABA8B14AC393EE52EB5564D63BC2738D571FA3C255ABD20102BB299441B00EB988F3A5CFB238EF8C49963B4AE8877E6B317E208821510BF446CE6B06C33717C91C460924248382159198F09D0F5A25C1611B2D39CC6D2ED149FDF0E09A0B0B2BB77067182E386F5F6A55B68808DAD98E5CEB0FDFAE6A0315845ACC7B9C172B0E82190A5EB7C58DE4F86D883292A883045C62D6A1B3C886C345AA6158276EFA6B93AB2188E47ABDD25D332146E980E1B1E043CF63EE35A5AA01AB6CC62F77699DCA16FA30E3632DC5CCD3253D01E547746C78021AC307F0EF1A0119AD11504803EDAD933150981C4D9FD181835C507651DC92A86737E3AFD0EB4DDEF6182872FBD31BFC6D8427C2F4D3A39BCBE6B5120B8CF2AF5DC59949C92D10B1C6A96810564DD335E0755F9DE25EC26C102355688C38250DF8F96E105136855C8DE4BDCD86DF03F92977DA16908CAEEB4056F4A5F751A57BA057AC0309F1C107E594CF3C31544E4F1D93FB9AE7E1A2451E7082CF0C850990EE71ADE0498F6A3852DC4FC128BFDB8ABDDA3D759C8D4F83FED8509CDE5EED38410FB9F0A5F30EA45C9270BA2395DF645AAEE03F56158685A0BA65DE3D2C5209A7EF4BDD4BBE0CDC966DD1BDF1FE0BE06C7115F7CCD80F8012E5D17955AE0C9E4220076882F30DC5E391295994B9F809C09DBED8CCDFC89669F40492944FF20948080A4ED66AD8166B613AB2F4414762AE493EA6661950E8E56B3758A77CDBCFBF24FBBBF20EACD5CBF8815899A1C3FD20B1D04920025885388012D9C58EA842DB9530B7ADA901AB9CE46A12700687BDE07FB99BF66D0C775218B8454C936F03558B899B59361A0C664081CE8A7858DDBC5E7C5480280411C9ACF4D1EC45035D97524E9E44F963532CA5067609540C1BCB5627F99D5C61CB9A6D400F0BA0A74E45DDAB5A4E8A765DCF2F3684E3A2661A78AC069FA38163AD9F9713EB45C841C6617697CF8A72C54B550DBE9C22B04D579B09AAB0EF4EE8B70CA563F81EF9700C07761C944926F9A76A8C3EEE1CF7E7524D65908C47C35B0453DC10DB5B75123A5B26B9612C0AE18816A71F34638798DFCA21F5073CE771500034F9A71FEB8B621356C430B4D47CB1B59AD4677B5C679188D8861BEAF52558165F691F65A692E8CB8D24ABB74B8885EDEBBE52FB13DAC16E3A8EBC4EF192FD10D71898E93547C7A09F8642AA3B4FAAE23E48BFA809C5989D3462AA50FD4E5C4095542C45E5600926C2DECB4D18BB43B7274239A8DFA3D9DE1BB9CA099DFE56DEDFC9E120867EFCDA10B48F7E630506AA606D76E4537036127FA05FFFB8B8703CDC8DE70A78D014872111A431F393345D74E8866D9A9A633923072E93DBF47C54C4B205C60E67D5155B76F51AB49ACC7435525605DD43A10C88A03E08E257C68937BF2984BE63D40F8A60589D909F8F09688A77DA15DC7B4853339F235B1BD60AA845B4DB6B699325885C49DF9C40781CC56FABEA6201E2F8A9352C28CE321B9441422807E9C81C8F1EC85D240C9F1C8ECC4FF06D6E3682DEA3E6CF92F2B74C2165AF247CE0F5AB84460693254B523498A57E7442977F51F1C2F649BDF756E7F43AE543F5D8E692820F8A06322667A7FA9C1A5B10199A69CCEA22C74E172FED43E550C68C337ECC5E6AAD9F7EB997A7E619D47DF73CB917A705C3CDE5FF344F6FBCFAECCE6B734E09A385FE54B224A880704D774581074C59EB0A3B42C59B8BA4518E764C5A532F6655DD839862AF716903A118433CE0809376A88E88FA847B4D1C63EE393267B15C1E42A91DC6107CDE990EC9ECC7C1066E9480E90A22907C51AF47DA837438A90CC07DE8121691BD73802D5D09D18A2D8B38A28948735110891D1B559A73445838F359A6FB90A3CAB887486CC9D95CBA35B55693C890830D2 + +count = 56 +seed = 36AB8588F5233D15674677535A682382C29968FF824031AF646F58FCAF0E83C1C486B1E75479149FD6F4D9E8397CAF73 +mlen = 1881 +msg = 0707EA05515798829F42A4CBDDB4A95C5750879E0A584AB503F778015F83BEBF6D63C3B48A4F478EF01091403DDC5A9662E39707DBC8502ACF50F3E06ED0199CC647EA155FEEF503BE045BEA4035C07C4CCEDA306B8187185BD06C14220F2B7401229969C1CFF8C36D499D5A725FA1CE7B44D71E6C0E4E750766183883D838DAE4F00B140E0AFCCB0E72F935018A6314232DC632C5AD3C26919D1A7925BF0F665CA0223439518143486CE92650DD145FDB2E97E0D5BC9D6806F442FE90C9C1F52992E670DB2603AD885FA42B3D8BEA4E470B7F76A367AAA506E931890B6E4607F59E87A7A5FBF3991EEAEE47CFBBFE3CBE028E67BB645D37A7BE5E7CBA6D7955CD62D1D8DB0D9772EA0185C25BC1AD40A09D3E7E9CABA72BDC3A6EF3C40C7ED6208854157914A80B5C66A6DEC2317FB5A529421C03CCA6FC0A3B3D51556E8DEE7C1EBFBA924FE2EBCE8A46BE96E761AA6749C0A9A2B2FC49B42CA47663EA3395DF22DE20947DB14FC1FAD03805955D67F8473BAEFE2C1E22BDCC7BB988DB0DDE4E83E26A16F10B93BD9CFDBA77B9302EDBA0C9AFBA7369A023EF763C55484F7425F842111CAE27E07A511A725F25D422D933F2EC201BFFE3291411AC3CD6E91018C95074C18FC780A73945B148154987854CFA1CF1199BCD03519C8F34774453DF90B71FEA6734DEA7191EE2A5735F7A191F527642D53C844B087E9346B07EDD0B78C36F83445825E60A13C424F72530E05F75DA8D33957FAFF004DEB549985790956A0E7D9B256298D56BC6206F1E4E1E958FE298641A277A2C8B6B9B7660DBF689AD7E1A19CBD965CBEAA4A0D30741586290576996AE668ECBAB4F06F2A1D542E32C5D3F042E7E29A41BF86BAE29E7029D997876CFB23B10986A45CA029739B2446A29C55561AEE8FFB187961E6E7401D726AF6D8A5C816B2CEAA9A1C9B780DDCC4F0E4003542B193AE26EC687F8C51451D2D5387D9C3B9EB95981DF2DE069FE741CD5C15F6D1B12C5B9B94230ABA33BF46DCE8AC7E26896EDCB4F87272C32D19E72C313738855C02C6F46F1162BE0A3ED2E76704B16169689BF532EAD7AE7F2B26F4D9B22712662BEEA1F46748FA4C27D1D825D3FE493B5B3B513617C81D21A0912D329C5A4E3A90EF5A29A4E3137D1CE3EEE99C42D034E61593A4076EF124BD6BCF8FC911FC9F6077D82C2980C2ADB955939441BC9E81BDF9D6996CE578114C01F9BA096D6EA40F4E0FBB18B3E3D25E7F6D6CB670AD26F604368ACB6190667B7B7ED3C1A1DA04E42AE0087852834B91AA072AD51C0193E5299481221BC9083118F7B5503559F1E2D9E22A8D57932CD0B59509E7D7F459E20EBF4C1D0DF71472340E64992C0485D593714D6B469547616DFEAFC95089689931E79944204A6D0A47A565DC325F3BE19FD44BB6CD4BF2B1D4A78C883154D70705E121B833A4A7E7E80FCDCA03F52C1F831AB0D989AC5DBB5CD83BABCB3EE74B69681818DC05E33234775123F552CFC7C7BB0B98C937957A2C4E86E3D775468A7CB8D33756ED7489D04DBE52EAA2737EFBC4C4D0F55B5A841E1453763E611BAC358FAD0B5778C6015D97CC42CA9FECC66CF844DFE55587C200DA5250B3A419791F57D3A4F672551BE885DFE2AA8637D6C890EE8E1063E782FD7E2CB356BF47B6EB93A155D8D64C9F6CCA3971C5A7FACC3C052A2AA9FB286750F76933261AFF5CE408BDA8382AF8535145F432F78B3B25A768B5DA2A211D1D07AB557CABC7A139F66EDBB744AA76E0FBF22092E31C92CAFC624EE1DC6732F27E8E7632C6EEE2D1F5C85B52D712C884B36C91DA383F0DE9E06E5EF63D7B7A692E5E91BA1A1D9298E26694FAAD9EF262F117DF8115E2E877197A8069A96210CE65D45E6AA7011654ACFAFDA810CCCC20C1985D54483DAE12B29D7ECF66376968B52FBD727CBAE7C9E3DBFEE7391D985228ACA9EB8EF98FAE32BD24552A6B34BAA581DBB03676A3A4546E10EFCEF269B18E1172F560FA0F0344149543551E079C1745BC0425B5233B7D7DC32F751D321638EDB1CEE56DF0359EB6D9863CF3E341A56060C8EF8486014F956C39B751AE239A493A017B2FA5210D374BA83DF5D799B7CD92987FEBB0B2CDB3EE42A61381304C5EAE2ADD4777011C3279BBCD1EDD6F91FF72B3C353AC35DA8FA843DC5561D3CDB507730E8BEF20CF09B0DDC36D47F4C10D82652DC2937D889F83B1DDC30E52B244250D19EEA9CF7A3B5D931E2E25B64A0A81B2C4FE933A17BEAC2E10FD888D07F994E4F2583D204DA126533F5E36B62486A00CCC317C4381A8FE11D36C43E71BE108E22A98F53729F05A5E0AA38D512423DB4BC1D6BFAE9117383ACF94AE2A737F6B8070858BEAF08E365CA84925F8BEBAEEF5AF77EB73A9D3648AAA6493CEBDDB95149F0DAFACF129FC321E558084A44CCA4B429D664D90DD90F2A04818B48D135952746CECA76F99B947A33A3BF7C535B187C1971AF4FCB1EAC841BE7E96F429DD38127B52FACC2DD6512D8D019E0080CADBF7078FC67E9AF170A2A00F70F407B0A7FF469E2F6EA165F8B43EEF1779A115089DE9ABE6B78C93E4B8E3B018686D16CE8EBC88CBC1D571372A3996C9E5967C035F9DA6E200E7ECFD1CF7158563F36A3AAC3CD8ACF52A4EEE29DCEB03FA3272A671CFC9B +pk = 7D6E1F0074BC19295F8D43C2DE1319ECEA303A216EAD3B2D9D93A58CEDC353B3AABEB81D495E9026EF96B2F61501EB18D1CEED176D3CEA74909E845781DDD406A395FCD2D84B60DF787A133FA651BBE6D968A73973EE1FC32E8AD600DE53BB32A59A897423BFA75485C27B345F1F7B4939BC9A51C209E3E6F56FE29E5B1FA439D571E6F837D03522DA9492B1C873F2CD751101F0E7D95470D224201CB5151C9BEF7977A3084A815F9A078D65EDA7D4E806D0D32F7155535FB30EA1F366AFB0BA2C74059711CF77B256B30CF4C6C025AEE533FCBE1BA048011E3AE28EC676F8AC92A05FB78122EC71F6125B733D8F5F6E08193094E76C4433FA107728DCADAB6AF568B5B611A7A96E1DF26DDBB5728B4DEFE3892BE032EB7CD50E01E33C538C7041D7283A0A1D01F26A8C82067A5D5828AC596A80CCAC88C44E3189ED3912AE4605D327FCC685A813FB3A85A4C8F04FA1AC9FEBAA56DEDC648C321F3DA80E757C9F84756C4D7BC1ADC678DBD412D2035C0286E4422CEF485537AA589D748A6AFD8189FDB039314A0935AF21CCC385C782E8E7A8F133303A39D9781540C7857C1DA32571112B29F577D7FFBF1FEE0B3C808DEF4EB02AF4B120AABA73E4B42467CCCA875220E004D4BF27383245B3A4F00D85DA8B49F689ADBA1D37ABFCCF8C10E8DDB33F3B1B473B3FF4F145E5FD2F72B03ACAC4B8B949DA6C3B8393B118D82717F566651FA1DE96C93DAFDB250E4F2D6CBAC2AD4840E39FD61C33E6E003FCE2CC506FAF842DBA03E48D9BED1736D3FE801064FC31271E4095DBDA56E4625A99BE1CB1A9EE1BDF515314EAD985B7277D9F4200AD47FBCF88595A3046C4DA14300BF6222A792030F1F5CA75C31C2AC2C36FBC0B5F9669CC6FAED47965BA53A682B3B9968BEDE82D01FE61E5C51E3FE7561C385B95A1A3149CBF7AB5964B813CFE76C542A7F81B453B7281FBD7893C85CEBC14191A3334B33B04055E3A98F2E7130172ECA94D8D6A93777ACD42A1CFC110A77212416A9D7D8A554D751C7559E4118F2453EC0B278583F0291C249226FCE104BC452661924F06CA919E0B04EC356601D9B5F4B4873166EA3DC7A8839F08834BCBE17142ECD2B082844FD1F51797837AB7EDAE106E82826BA8DC7BC6786C69B8784A2381B7E18616FF9CC0DF5D66D33DD4B1B9016F94AC9A9F6755FBCF5E52E28BE48D4EC13F15EFF4F4B3DF9AF85FA23B5A2745EF47FA92CE60C70EE5FBB4DB9ED63BEDB80A9B17BBDFB6D4ACF2DB49790369D736D251573E49E61B448B97B5756BDA84CD0F57AD7FDC8A52B72242023C153A911802DA0A9844166758BBAED9FABEE2382ABB39481785622C0FD3DE121EBFB47EB87A71C089690C1818BD0D0C67E115EA1CE15D907D6484C33FEFE2D5D883AD1FF0B20FDD1FAC776B583F2E49C9CF27661316A452D6023B24FBE9726F516B2478CD72607C6CC136F83F2A6C5CD95AA4AA3B7E98EFF1E4F4672CFAA87D952DE01046BAFA2FDEFBB6540C09EC49B7B384B06FB9E0F5BAA43640B35B72013450CCA2677F78AE997555E6C1451F00726D86ACC543D8200163F53BDC4F48CF680424AB1B2423CB1C26C6356E698B864F374BD7DCF70530976412470D8EA6BA6B241FBAED778B9B934B03CFAE3BDEE1898FB05A332D0249AA4EE145B0FF41D6ECC8B13FAB3B474B28277DEAD56A4A4F6C45BF4C7B437092E0491CBE53984BF002386F40FC31998DC036F958989E5AE4C1EEBB5F1888001C31DBF52ECE374145F5176B7BE3DCFF97CD48169B36655010F7646CEB84EDDCE3214C6BE000D101BD2F92FDE6E38A9967F0B59CD50273379ADE2D56A2426794F376045EC5D9F91CE1FFE40E7B429ABE2F24F0DA1B922D38AA0DD54848269BDE1BB997AF0D15E55C02AEF1DA099725775E94E8F03F665AD8158F66FF5D126C62D63F80E4B50DA8A6D0555610CF24D9DE4C424CCEF2D1B676C936B1729A506F52EAC4997623F5E464123BB42E796B4E9CC04590A071BC7CC7BDCAAA02DD20FFF6D9F04FF3E88B231A457EC9D47C1E7B4243BEE633A5F05E0BAB15FDA27F4F506A50467411B61AB5E882FEED78598F8592C82B7E88D730427835D02F74C1CE583CA234144B94CCAADAF2FFE2F197395410F2D0E0786BA86844C9BE590980B7DA1E49A78FAFBCD3A27C4D65414EE75BE2DC5CA4491ADCD4937F16D82520C54828594BEE4F987720D26CD4F73F3C599950CCC51003B1C955E4030FF79C705D1B611E88BFB546FD6E883D25258B9AECF449AC0A933347CBA0BE68D8BB139DB250F6AD41F48B92CAE446EBE17F7991269AEA270A634D80C74993EDDA21AB4F49E95C251CB9763D17274549151A8C263B86B24993D06762343C1F1AD101BB9FE977C7AA6D3A6315EA516AAF74DF497B4B6599E60FCA5B1F53640EEB2FB02882DF45ECE5CCE32A1A7D78736997E5CBEAB7D952E8FF8BEFB7BDDB74BECF02B4C0D1A9DE04647CE10F448511E44771F08E8CCBF4288618ADAEF8D70AF96B03F59AC595C65654A2AD072CC296F1FC89141F9DB5EE9D93AC662C7E40F469FF41AF82FF14D9425937F9CFAB4F275AED17EFB2F69286480DF52981544C745B65D5DC276FC5A33017FFEDDBDB1BA10179F9174E5BE6CEED37AAD5B2EDB7C22C43392A23552CC8240F7CC44E2CD177856004B737ACCF8C36F26EB0B26B38FEF0B67BED448E30295732C637D8E7592930711CDD2B8FBC7EB6E09544ADFCC5E4E99C970D2CA9C515CEEAB7FDF9D9F5499B71 +sk = 7D6E1F0074BC19295F8D43C2DE1319ECEA303A216EAD3B2D9D93A58CEDC353B30D7CB5D6CD022BC3B256160C26BD57CBFF627620C8583DF3A883E89FC8D101B7EDCCF6D798893FAC4BE7282E173ACE52C98BD246AEA6C264DD50DD4F0D9A94DC2BA3BA890569C1321F4C8AE22FC2DBCA49B42067E9DD2F40BB90EF4522CC3EF12713814821355847133720155080378541834570717801114284380067614006401882474437753465474683283113314040177606210433337157856518335568414878466114031348663526575185826411503612412620271715334526072372171480018745737454218870634171222768063166512221600253167230315564387827014117370255346805511727453533123403771064808580506556434788058518548176304766263557347642712261751783408615315417382148671848256042807166024715446180144734115284176502750640525386827178880455544834817512844127615277622514660107124770387322560547373406148383088861885872883050400713216567618020054678322143010328673888231413776200674611288421075264668671060401075126066688028712660164780664226031585837145347372312712828213046111210368623747800486023887578711861583437350047680851526124305846406420027715578553636612622207087631376241205484281117520148083020023321105542648278382752805576846161235031417417851018100385385418575726168532026801705670540540386354155762373280821507488226688071035300056255223111355726048778863706060215685421212174067722124310225264523280807028684660585840442725670030307027671136371327870534288165370168821731684277065578627582073105371357170370785704618860028050077140016515446225150643487275034257210540755664246488315061816370703787205234346657723223487637148352060564326358683522043632178802630218476426056527412434660032387575825438152832371427836874478321403748423262835463565851250872083488582161275608783125681547168160887184714411560514845746402513767135385166537882210124370224518240105275772856386460510000260658551125674371124718651655366360355243766283810470851671267864703316751113814177000472370750453477803643627868583330145125516540464602350823610078110221457146143104113717446448432631065304777400538655512068085171383285864022806824064117335188867701624005610615407780563485433058716236246457205560475168004782756360825323037342482314235808578860661753217622633054508185230822588282440270228055011858064875752181471257071686122041283075452776621403507263342823875565860408866684865050587175132430523203683000428761218467454265153315821711517463761632235638261882225283357657647800006111380713352820754708870701325256663582711327158103630118487381512842356225226423662476884745013874730388778446531324405325772164880418077167703708156120176126261370534038736254561634343136688715064385584157800481855571748508283731575456060127482545045835417174074008512733137754520233603086860471304053803156556375226415878207538147281400337255100607712868046771777433576018454155852570446528136810345267517018362808533274384071612501735372861588384443243157331446445440804807231381757860364710546505032723741770226755108175578300436601413030302061205137031265105070388855320327774521370855242143164785451806824226868237235425353144438265318267040405337421268868218830126780774626122024600830413325316378631625200181273490896B4A4B244D355D80C4A841F683284D561197873059FC53126FAA2E8D72771FF3A411C0CFED8E896DD2F2F6799EC1D4589F0D5A8A43A781A7AF2DCC73B0AE2C4A7A71AF24805C36B45DF318DF1F1085C9D525A5C409F4437070F2FACB8F227D559BEA26528E97B1E921D40340B488F617FFFCE500E812655485B09F656570E5DE4F2E2642AB00C821150FDD90460BFB8248A34A32205BB7EDA0168BB5E597422089A1EEFBC4361CD82539ADA0F5AB2698F461278A40F49D6B68E3065C541EAD34A8015F654BBAC9250299DCE0A39300CDFC7B26D10B121184DA7A94DD962A57C80B291FC303591EEA8D26EEDD4317B0F4DB16C6F25187DA59F2E7862E3587675D84BE49DDB19C7DB849C7446D5493DE7B39087B299C9B159E118EDDF716B337C4E8CB2868E28414DCD57A4D8094C238185D56E31123B5A197BC113380706C4D117631E5932DD84FF854ADA97E406C5E8D0B94E43C2C388948DE46B7B2AF778F11EC6782B3FAE98B87FCCEEDFF2ED9976E49EE19F24D8418F6F5432674B8E1E09474A45F5C3BE5D8FA0C5617FA6FDD78CEC84E4298C11E55D7C1C1DE09FB4AAFA309095FA41D2397BDEB924C8AA43A8C5E06BA2D12FEF61FB509F3A5149CACCEAF7A050E93EFD57267366E5EFE8BDEED4447FA0A297FA6CE3AA39B0A4955440EB1F1AA2A33ECDA0D89A43008B06A53B59DE601F925A692D42D3149E484172FD58440459099092867E318A9712FCE30E2C82FEC385E036E8CE4B2CF50E3061740BD018ED06553AD4A6EC0F14DCDA41A6AB78D0860BB06E2EFD06000A24611C1ECACC68935DB862B3F1F9EA2FE8BAB419412BC12B8C28894FB911B38E2900A5EC7375624DDF9245A3FED7E68373A728241A7359C9348393B6ACCC1A9A72B5D6B7AC6DED4704C08BBEC1C076596A28E49BB0A5A03873C9C9DDBD531EB77B29C8B055A0189FDAAD4CCCE71069981DDB48132A2C074D264D9D57BEDAB2D1F2020D1E1C56400173A8A94F57C700E5407C529C7C6BA5507E45BAB9C229060C4F5F58EB31029DED27CD7EB9080408B957B6B5C906645539A71699B4ACB69F2FE2D543617AFD942FB1F40D600DF0E788BE01A11317DEBA5B31069090469FC947DC7944C568F4E9262B8F3BB1B5179BD853E343563487D30E9C6821049A33B23174430065ABF7923BBDD32FA549DBEE5C3AEB6C83D5EF2B5BC8A81782608BC806CAD12E7386EE8EA63D6F350021530DB6C6C02787B3728EDA0D1F6608B8D12CEB3E7BCE2C64C7EAC9BFEE14953BE0EAC127F0DE2FF68D0B37FFC990A631C5CCAF6FD9EC65092275D8215CE1E8814EBD0163D0F930D8107D734A4EB196ED3A49D0C8F704D1DCAE0B3A34414A460EAE9371B23F96F1F3A44DB017B041FA3807788C119995AA1569F91F397D7062684A089BAC1861344FD5E348AC1026888FC749253B475CE9FE8E72B149047745CAF5E1101954A667FD4B77C2DAF91E64BB93CC8C1082C38C6B8822ADC5D5E9FAA28B16E98D113891EABAE41776F6F6ED77D71A8DBE8C29CC1BBB073633FD0D9ECC5D54D5C7749166EE2294E33048ACBA537743479EFBE2FE5CAC06886F7689BB7283A1876F0344B219757CFD0349F57869837B7C7DACBEF5DEFB3E1E9175760D6433FE4386CD5EF9A22A5CA07829C280D024EF234BD9E3968C8A909C791790B0860DD6C058AF1D620C2F11EB5B2ABE536D917D970EF0D50D5E32AF037AA8871A6301785445141459176B264C68F219E66491D93E2030B5AEC5E517263F919867A4C3941567A78885B9A02C9703FC8C5B51A455347FE6C0526FD2547DD33F5A34B0292AB0AEAC91FBBACA89CCCF7450CC99C2C35EBAE7992F42787BEC33C50F60A1E4454D9BFE000D955A03484E4D3A0DF3D226800597386102A341F18DFA8D1D1122C89F05FCE6D98F2E2E23A1832B9984D650121262EBD772C60CCF2FDF198544142FEE047A3660F880FF7C17AE9E8502B73B64FEB268FA501EB9F86DE98F43599BE899D219E068FBD26F980C0072CC7F7F52FC8096B5E79D23D0ABF552382B6A2DCEE7475C6BBAB6ED64155F3F81AB3077BC6B507E444ED1BF27709E88E189219314E59F23B7B149173D65F3CB506235BF473C07CD1C27D04134AC3C01E8F7E2C199231A90910DB4F2EBD338010192710DC832036B5760628F84D83D1ECD9EB569748F5E3E9F0C96074908AD298E7099F2D22FA5BFF8FED5F907EA185BB20981C5846D7919C34160F82224202FB3264216F9E087859975C904BA27E8EDA727B36BE376337DB01EA1473BAAA7CD92D3CC8C5B73106D493C2AD234860505E3F5735E87A3A4E2570666F803675E1236BDE08EB2B8D678F98B0AD4A472DE813B444E6CD16023057F53F498510C37C06A35AA2DF7AEA1E98FE013FBD8DA26E18FA1F863363B24B814E631801FC0DFB29F9FA43753F028C3D1451EFEAD8CDBEC0A1D5CB5479D63EB1C1939FE7E242DB0DDDF6B90C7935243E4EAEFC00537F0F8969B6E6A8769B96409DF59FC18749066B5DE707CA26C14D7A8FB30152CF85EB548F7EE8627192B4600BC48A968908F66DEB21AF81A41D02CCA4BE038306E0B57669ACBEED695B81D6303E30007C467DB10CEDEE9B04DED8170451751256CC2C49659BD48168FE824A7194182A315839AAADF4A594A75C01A48CA7E6251411D591D2F1F61785F2186638757A23B17420B30180EB89ED689CD60F2FB67179DCB19951F10892F248C22A0E6F0538695B89D532D9B0DA953801D86FEFE3805AE93157FB2AFFFC444603F1B9EE4068412C404172BA6C3A5AAE583615DDE30E8EFBFCD1F34552A55D6BDA4D000B76C1A2F8ACF68DA09881D7A88E714360FB71F420E3AA54C6B7C0A98170AE3BC4D2BC1832B83169594A9CA4320F80CA1ACD65146B36E4FD59E34C725CA5BB34CF220BB03C386C2804D78C6ECB2A5E83028BDE89BBB60E3B4C3257B2076401BE8E5539E425E06EDA5843E2A14C15A04A484C4EE5D353FB6758B15C216BB687F18FEEF88F1C6EA75CBFFD14713857D48DDA1B02263610B7736F0A14CFF26C16A55FDEFA403B14C297BDE3BBE3E5877567928EEF97398C4D030E810243B57F41BE1BF32D757B79FEF5E9EB1D6127F6019B9A3DCCA42BC3F4C5413B334CE0DC9F72D30DC4673B2AF5C02E33D921A7DCF49563BF76B29DB37D149C9F92CD04565D5C03A247E56D2304A6827B6AA70ACC01FA169E772BFD3B9E2E40C27F62249F6F964FD66C8CB89935D62246FE49C9CD395F77F72418F68E2BB4DB048AC45396DE408C57CFECC54074C73D0743B7AD83E5BE43BA744CF46ECD93D77E4814253F974965B7A23CAECB5DF964A2B837DEB0C88B0A96D80D61C3D9B164B5FDCA6709BE7FE8E5AF1DD6BCD163603CE2698CCA25EF31F8C7A55397DD133A3E797E3E2312C7055D403283A8061E76E0AF1D7B87E4E8E5B29B6402CFA4884FF2789A5719C3C26A244E255124CBDD35EE7491E3849B2E9775DA5454363A06E2CD2FD13C6EC9801AC48B56FF8F5891E037255D69 +smlen = 5190 +sm = 5083C785A6B1B6AAFD9623ADF1E5EE707982161F50EBA9CE31776C279A5BE8ABBBCC319C6237161A1BB2D67A30F5502FD2EDD46D0FE452D438904595E92A8677EF4B91A6F90E2E35F79F0DC6676FB559A15571BC4EE43601D1839E0675EE6C65393501ACA006B5615B8C3EF8F1FEF76A1EC10E4E8190C578E6686A2335C082EECE45116B0AB49BAC57108CCE28A91A01937A26482CEC12F4A1D4A6A00BA907CFFEDA6E5DC4F1D46F3737030F5E97F5B244E745269A2496012CE4FBB8BB6A2B7255302517D83498670FE862FBCECA136290AEE3123C499B95A7543A431DFB8766829761C9987A83713E74EE505897DECA62D89E7B2F284185FDD265101DE16302C1199CEB42CDFDBEF1DE17982DBD7354597A2A3345AA097AF01E307AA90DDC4D03FC503E770371B4D57E0838CDA1E3196991DBC7FBF06F73E1EAF12D70AB39F69E9859B61DDF2CD2807CDB669D5C1CCAB22D433887F927CAD88B500C5F14FA2B79E11A921FB2DD30C90B0A1B8201CEDAFF10187C061D46B53A2F38036AA27B514F57552B1BE641102D8013D856AB0349534F855BFF2998344FFA059B5A5068A82388C3545C3377D0EC406C2FEBEEE2DAD38FBBDBC0572B47A69B754843FA2C4F7DE8CCE935984C6CFE19043D2FEA62F8BA23B84166DE319B0FD53FC8BC6D998DEAA7BF14001BEFF992976B7B7411EE99961C6D5D1519530112E6BBF73C05DD9BDEA56192AE5D51D43FBEA1F0960100AEEE997421034223512AC9BEDECB5E6B7972B628B7E31D3E9E41B3F7AE0BBA2E38CBA8C7449065102C37B1872DD592ACF50BE02F2912AC517177536A923CA3835F79452535C3B6E2019E03DF92CDB66B5185C401072A76DDD8EC369AD7F1E67C2B85F329153A08E4D1FDBE35BB748028E0BC6CEB811FC0AC02C1275D1A1EF4DF7B68AE81221266B82C4EABD82858163F9A66F5F9316EF48F0A1253390F799A1974BA3E43C4EDCACF8BA38E894911AB889BE412BF43CDDAF0B1268D762DA84DCA3C02C374FBC6F0C1A101EF6ADACF81CCCDB9B6029829357676515BF0BC75566A1543BA528B004EA8F824672D1666650E4A44BFB3C34460F34B029FA587406AFBC3CCF9A2EFA0E237722C1F2F4C999B64BE62086CF620383D5EC4CFE9113EF680F805C45C3F9359AABE6A3A1582DECDF0A61FFCFFD00179A54FE30E0C3501513A4846532D31D56A98F0D6FBBFDAD5F1DF28973AFDC5B711DC5016C7451ACE27544FDADC2E114DDCCA615D3F6F2CA62E70A9BF7D72D558EF3625C60563B386648D2C75CF53FDF52873FFA5AEA7D1D575D7A2C5C1E67EA3DE3711B4CED2D1F393A2996D2B0BEA93E47518DEDB64C0F1BFBB3D08FA7CB12858CF292C104ECCD8EEE75037B65B3FBDA11F415FC76645DEEF5CEBB775053999F00DB4202F17681264413FEB46A741B7DDA625DB24E9640A65F52339401E2BA8E5ACAF9C203F173BD6B8D6087F2460F00CBF9BCB17743393CE4F3FC425C45FA2532D5FABBD2A2B670CCAA19D021B6B0099AD02FCE5F07299DBBB23037E5D857961C622EF69DDEC51786E0D0FC9B7324D717E61DB26E97E4EA10B8B2CEAED75C07964A7ABDF65A0BDF157ABD9F74ADC7F6EE98D424BE5F11AF3E0FF723AEDD6DB3F1D932519279357A477143F5DB4FB64202A089D019AA754B339ADC7EF60DA692D9B279478122E455104CD471D3FABDF2BE842F13686433AECE6507814B7208B28D3806F3AF752EB597408333674DD98A9886BD89E78A1932723E9D399CB2DC0083BF239DCFBE490D349190622071B7DB7158DA89D3E01BF1E3EC15939FB4CFB7211DEF54552FECCB3795F90B9F72A72A22AEDCE22525467298F9759A427016C90F65EAC7479626F3FCBF25B1224176A1A22A72CC4EF9982B9197399F69B6A69150FEC52303CF9E1EE2F981AE82F0F2F3BD55D0CC2A9A0644D94062197E7785DCA1623618D71672D42B82B94500771B85EF3B2DDAA7CBD2E7F92186D843E01EAA8550DCBF8EC6E33A30B6550451FA87C2410BE29155F07F13BFDB9791863D607472888561D7A965D111068674154162608C8D55C4DD23C87446166B85E6B5A7455BD1EE780E7EE9CCDAAE54EDE9CEBB1113C28A818CC66CF4334FCE4045C049B87F15035FD8DDB578CCB0B4BABFF9DC4F30DA24343EFA4F83C46F033227D24AA306FD453A7C2DD217DBB736C3B5EBD9AC24B8AF048871AE8F294D1719C52B263A927690A90A544F5B59E21A30053283CF18D9AFA9EEE35B03F2711C76D8600587C147F066B424CA48A7BF25E537EA7DD115973C17C816958A09D08CD0E40EFAD0F48EEA2454B7C03B72E54F62CC80E40A2905A8E7BC9FD3A1F9D5B61E27F48F88CFF3AC234CF62163FAF9216883D869D84A6BF6041D3899B9F95D29CB2642D57BBA7025B54BB04D2968A353C38619E73B8D15FA2FAC1A6D4610162679B8F2583E6193650D9E4A9B266C150F004433C2EAC27BABAEC2D6C833EB1C47ED49F6EEAE02B5FB070EE1BE77FF51F3AA0C802EB2DFBD4366D6FB3A20B4A3AE1BDF8FCDCB16F0D9CAEFF899143807C692DE7E900546C0EE3EA1E98241133826AB9810152AE880F63B301220064D9242FDC314F575A1C6A24B4CE12B7268945834447555BC9491C7A21938EC0DBFD506917160D349C93F5F914FA3AFDEC0C61654C11591C6C6EA6B9F12CD07104D8A03573243E57F1A8DCFD565339185C9F2788944E124EA3A0EC7F7FA7E2E97320937AA333136B41F98BBC1B84D488F134A46815DF7A7F6AD3B02F4E357920143F27BB355CEB42D2E1779E5E8C424FC671BC1EB82EFA822E9A2299EF478215DDEBBB83C9B74FDDDBA5D2C6A7ECC5CD39C52612E87F360E35B570804F8A7F45980874945DAC09DD3194E462901DBBFFA8CCEA3A37D1950C717EAB37B038833043E599D94E8BCF2327EF80C5D76865DBE787CA68EE8357DF0FA38A6AF58C38A8AA7CA9A88F2C5069E28847FFC147CD59E33F1C1DED49995AFC996A66FC1A351D20761452DB1906385BB96911C3290D7CA97BAA10A26AE8E7E120DC08DDC410BEF2956FF06722A644C60814C5499C7DD2E825096E16F769B627DBC706325A81FF7F01691EC7F1762C333BEB33BB921A1FAA4ECC400FE60138DEF739CF686517A2CFFF5F918D1F30166184EC35CE16B6F6D5182595DCC6B0F943C1C9A165B21B7533AC943F31E9B03EECED0BC3B9747DF121EB554E8BBFAE5CFD1E3D9A17ECECB1B6708C1F004CD74111B082B35355E721B554BA37F760FD93515C166E3EB3646AD8AC90A2978E5096A4CE5483D7560EE469A9F52A277D4075E4BAAC5C93FD5E14D887C2CBC23FA254A11DDA0B3DFE4BA27A7C8C339A79866DC942FDC00FF5EECEFE4223C912A4851D9319885CD18B314F2330C5782EF1BA2B3DA476D67DC42F8D53793899D46C2772F3D535BD6A0B931E6CD69AF9AB0E3BD700161546F40FBD058671B42A178302F3C20039DDDE513407F7F5F7BCBE5B3D90DF21B043858754C6D9F4FA0BFAEF908E8732989DF8A940E94F428701EF9349F23DAABABAFB6B7412183005F17968DFC1F8ED887A8F61345DAA464A5B13E7E07CBAA6DC0C15B29904F34D5E9DF6C8C8D9FCD3EDA7B5D55AEE9C952B1AF19E10DC17CFC57007F8990DF8823292522FC31A3F0A4EA121838F82BA1EDA2005F7FCEA73B100DFF58DA68BD7B10D10B8F6C082A138D83909823164B24D3D5290A324E1B070B6E5FE22F5022A8161DA5551519657F857AB4743D24747B927B6AE442EA6D96092D639B77280DE5C29BE8825442AC07114565923300981C9DC7BF8147E11AF1B04CD002E7352A89CA71D4A4AB056D207FC6B1D872BEC4AC8C03DD3920E4BBE9BF8D45D87B6258E9C397ED878CBBF5CFC9B9B02C82C019AC7824FDA50F157739B906681F4C00178FF32E3F9235EDDE298F681C6C89E5A4C7599F36297FFF41F41B571D805A62A75CDA09CE8D4DE729E23F18F4379910685DD3CD548AE5FC678A3840685EE79A05057BB062DC7F7739528DCEF54C0A5ED34546293F51D3159CB5BAFB5CECB90AFA5810C8C4F1C96C4B4DCA1072E55A088DAC17EDBCE2AC5D8156806784B483259057320A9B687BAB524F6BE05F91725273B23D1E886D0972A7E93A93B31C00753FCE8E57DEB73E898A8237AE7828BD1C308A129FD475127EBADCDFAE983FEC340532EE318E8F542745FE5FBA99644C03694E4FB9E7196EB8DBC03DABE9839954579E013BA220A456DDDD004D6CD7601794B609B6FC46251A3C2B59B364812EA29B91631994C64A676C082E787D47806D782DD10577AE1F8974796EA82358E01E656A68F8DA99E77F61EFFA23B99FA5D9BC5BFDDE2999532C01DE990281001CB1F794803CE559916F3C98D8A16F2828D482B846643ECAC134709AF5845659E3427863A30C1F2B9668397B0D65C1A8910C5D7CD515A1E46864D387133CF842FBC30846858740B1531C8ADFAF3AB22D11059BB44BB844979E1A079B2EDCABE0D3AA1862A16C2973A73E030A156B9276217B425410D4D48F53CAD4C7392044D96BEE7A173D756F433424059E25ED3724AC326955E1BAC311B070B1158A0DD887071B14146F9093DBED5E5F82A3670C8111A1E232A9DACD6DAE3EFFC11162A3D434F509E313857697B8497A1FE5F6485C0D40000000000000000000000060A161E272C0707EA05515798829F42A4CBDDB4A95C5750879E0A584AB503F778015F83BEBF6D63C3B48A4F478EF01091403DDC5A9662E39707DBC8502ACF50F3E06ED0199CC647EA155FEEF503BE045BEA4035C07C4CCEDA306B8187185BD06C14220F2B7401229969C1CFF8C36D499D5A725FA1CE7B44D71E6C0E4E750766183883D838DAE4F00B140E0AFCCB0E72F935018A6314232DC632C5AD3C26919D1A7925BF0F665CA0223439518143486CE92650DD145FDB2E97E0D5BC9D6806F442FE90C9C1F52992E670DB2603AD885FA42B3D8BEA4E470B7F76A367AAA506E931890B6E4607F59E87A7A5FBF3991EEAEE47CFBBFE3CBE028E67BB645D37A7BE5E7CBA6D7955CD62D1D8DB0D9772EA0185C25BC1AD40A09D3E7E9CABA72BDC3A6EF3C40C7ED6208854157914A80B5C66A6DEC2317FB5A529421C03CCA6FC0A3B3D51556E8DEE7C1EBFBA924FE2EBCE8A46BE96E761AA6749C0A9A2B2FC49B42CA47663EA3395DF22DE20947DB14FC1FAD03805955D67F8473BAEFE2C1E22BDCC7BB988DB0DDE4E83E26A16F10B93BD9CFDBA77B9302EDBA0C9AFBA7369A023EF763C55484F7425F842111CAE27E07A511A725F25D422D933F2EC201BFFE3291411AC3CD6E91018C95074C18FC780A73945B148154987854CFA1CF1199BCD03519C8F34774453DF90B71FEA6734DEA7191EE2A5735F7A191F527642D53C844B087E9346B07EDD0B78C36F83445825E60A13C424F72530E05F75DA8D33957FAFF004DEB549985790956A0E7D9B256298D56BC6206F1E4E1E958FE298641A277A2C8B6B9B7660DBF689AD7E1A19CBD965CBEAA4A0D30741586290576996AE668ECBAB4F06F2A1D542E32C5D3F042E7E29A41BF86BAE29E7029D997876CFB23B10986A45CA029739B2446A29C55561AEE8FFB187961E6E7401D726AF6D8A5C816B2CEAA9A1C9B780DDCC4F0E4003542B193AE26EC687F8C51451D2D5387D9C3B9EB95981DF2DE069FE741CD5C15F6D1B12C5B9B94230ABA33BF46DCE8AC7E26896EDCB4F87272C32D19E72C313738855C02C6F46F1162BE0A3ED2E76704B16169689BF532EAD7AE7F2B26F4D9B22712662BEEA1F46748FA4C27D1D825D3FE493B5B3B513617C81D21A0912D329C5A4E3A90EF5A29A4E3137D1CE3EEE99C42D034E61593A4076EF124BD6BCF8FC911FC9F6077D82C2980C2ADB955939441BC9E81BDF9D6996CE578114C01F9BA096D6EA40F4E0FBB18B3E3D25E7F6D6CB670AD26F604368ACB6190667B7B7ED3C1A1DA04E42AE0087852834B91AA072AD51C0193E5299481221BC9083118F7B5503559F1E2D9E22A8D57932CD0B59509E7D7F459E20EBF4C1D0DF71472340E64992C0485D593714D6B469547616DFEAFC95089689931E79944204A6D0A47A565DC325F3BE19FD44BB6CD4BF2B1D4A78C883154D70705E121B833A4A7E7E80FCDCA03F52C1F831AB0D989AC5DBB5CD83BABCB3EE74B69681818DC05E33234775123F552CFC7C7BB0B98C937957A2C4E86E3D775468A7CB8D33756ED7489D04DBE52EAA2737EFBC4C4D0F55B5A841E1453763E611BAC358FAD0B5778C6015D97CC42CA9FECC66CF844DFE55587C200DA5250B3A419791F57D3A4F672551BE885DFE2AA8637D6C890EE8E1063E782FD7E2CB356BF47B6EB93A155D8D64C9F6CCA3971C5A7FACC3C052A2AA9FB286750F76933261AFF5CE408BDA8382AF8535145F432F78B3B25A768B5DA2A211D1D07AB557CABC7A139F66EDBB744AA76E0FBF22092E31C92CAFC624EE1DC6732F27E8E7632C6EEE2D1F5C85B52D712C884B36C91DA383F0DE9E06E5EF63D7B7A692E5E91BA1A1D9298E26694FAAD9EF262F117DF8115E2E877197A8069A96210CE65D45E6AA7011654ACFAFDA810CCCC20C1985D54483DAE12B29D7ECF66376968B52FBD727CBAE7C9E3DBFEE7391D985228ACA9EB8EF98FAE32BD24552A6B34BAA581DBB03676A3A4546E10EFCEF269B18E1172F560FA0F0344149543551E079C1745BC0425B5233B7D7DC32F751D321638EDB1CEE56DF0359EB6D9863CF3E341A56060C8EF8486014F956C39B751AE239A493A017B2FA5210D374BA83DF5D799B7CD92987FEBB0B2CDB3EE42A61381304C5EAE2ADD4777011C3279BBCD1EDD6F91FF72B3C353AC35DA8FA843DC5561D3CDB507730E8BEF20CF09B0DDC36D47F4C10D82652DC2937D889F83B1DDC30E52B244250D19EEA9CF7A3B5D931E2E25B64A0A81B2C4FE933A17BEAC2E10FD888D07F994E4F2583D204DA126533F5E36B62486A00CCC317C4381A8FE11D36C43E71BE108E22A98F53729F05A5E0AA38D512423DB4BC1D6BFAE9117383ACF94AE2A737F6B8070858BEAF08E365CA84925F8BEBAEEF5AF77EB73A9D3648AAA6493CEBDDB95149F0DAFACF129FC321E558084A44CCA4B429D664D90DD90F2A04818B48D135952746CECA76F99B947A33A3BF7C535B187C1971AF4FCB1EAC841BE7E96F429DD38127B52FACC2DD6512D8D019E0080CADBF7078FC67E9AF170A2A00F70F407B0A7FF469E2F6EA165F8B43EEF1779A115089DE9ABE6B78C93E4B8E3B018686D16CE8EBC88CBC1D571372A3996C9E5967C035F9DA6E200E7ECFD1CF7158563F36A3AAC3CD8ACF52A4EEE29DCEB03FA3272A671CFC9B + +count = 57 +seed = 4E94DD734A371A7C6AD4A567038CF93BAACE2B9D30F3862198DC55D2F21F8FDC9A7AE5DCA1541712179E3AB1FFA3F792 +mlen = 1914 +msg = F3EA695264936D537D86E545E132131442C2973D19B37F8C911E3ECEF4A13A8B1EDF5E5968A6198D26205FFE6B76CB14E353B5E2C9DE1BD44AB9BD55862BA1A479833335725EF52601810C778DA4A32C497CCFA43F91C72A1499E8D295AE7CDB43F1CA05F0D4A31B30D9A69CAB8288640F3F9E081E2C98CC8351C7EB9954D428DA4BB374B346A83EFF5AA3F455F2BB3FC922F901BBE5695E3AB9892A93BEEF90FC150B3BB47F6965C229F7DCC3100A4101840417A0E2547F9D42AB27216254A2898368BFC60E7D407271C213233B6913C8E48DF10967757BFAF5B5E2A284B8F67C70537C97583786B5185B45E2E36BD8B5443E98601F772829176C4D66F44A81AAE7C13F539490640BFC40B83E1C75305B06BE60E18A0AB568859435B715E15BA1EE4DE73E04E1B09DD15350AE423C131706F057255E9FA8FA3F9E3ADE7435A6451F7A2AAD0C0FE0F444C4A247DCBAA49E7C926DD52A33D3737B4439C1D40F861720E37BD25366EB5F34BF4B552160F3EB80CA8FB19304E1E4143090F8E965DAEFF17551A3931905B5CD991C6BC5AF5BE808073893A47FBFEEC0940EF5E7D2F2EE199847E1A4BEA447BEC40F86F6FDAEBECE6FF0F66E04193355C9576DD4AAB2D796CFEE5D432B1D32E13B8903A06FFD3AECB00C169A3AF8389848CEC724F647C6BA8DC3134CA18586DB3E4138601A16DF8873A490F23C4D27FD9C3D4FABF2BDCBA4AF3F0793E7B591198100EC97602D9BA572409EA49D7C8EDC646335FD4494577720EA7CDF3B4266FC201DE4BC204C0D35CFB55010BFAC68CA0DF3AC936C9FD2A9C532B8E3461D25362EFA37DA159B64670060CAB833ECA799FCF1342C7EE1B80BDE05ABAD08B9EE8908D50CD0D433DDA0B120D1980F690ACAD9C072502AB537EF71B691917A76D3098C27FDC6FAD1F1B29E307E17C87D9FA6A06CF8CEF6568D9E4E005FEEFCB5F41A46D91E31B41268367D636C4478921E690D5D57E99DA3448773D51B673109CFD3A58CC50C127F34F4963FCED6C216E60EA0952317FBFE88807BFF4223624F6126104CB46C8D39EE228BB4FC0002287E346E5ACE43E2CAEC07A22203FE3C4AA9008A94F7075F6E449FB89905BB955FA0023608C494F7B73D2AA4E2B0A8A7E3CAA889B6B6A6640F7222EF969D46FF6794BD97C5363921461BACDA17F2781E14419436E37610E52E3B7B7BF9C1A4B1D80876030F9A8981DAA4F06A432DBA739DB988BED5DE7F38378EC1F7D8A46B305896CA0CAA5D8AD74002863C6FF91EF25AE96450936509EFA93F94718E895A82B4616A965AF004038E0897A6563DBC91EB5A6172ADBA052250D06D210BCF5A250246FC3482E57FCD9901104C5AD58EEFFAC2860A4DA9D2C308552EFBDA2D4275F3F3651E9935A0E42869B9263FC7EA71079E604A4EC6DC61CEF6AC6CC06194DEF432C1F7CD9EDFB0C4B448DAE3C2A685BC818B2A90E17A4C1CAAA5FC2632F720E764E2B8DA314224498119A0D94CF5DCE24176421C2736575672B361119EC7C766265768CD9FF1957A17779C11244C1CC82D72D4E3C87107885F71C56DA2BC41008B0BC1375C12B3B2A80071EC03E377A93BFB227BD560EDD5E5D88F46F7FF9831F05BF262F01F62278D3DC13F4F0CECA0509091C25D20666D8D3527975CA3495F6843B46B5D5B6F5C650E981DEFB3943963E14F00A0F78CE785A21634C46B531B4F2AC5AD0F03D92372C334CE963E514A1891716EB5D5BB1B67834994EDA492719032E2A4F961DDD6D2002D8F52798C45A9DA8145BFD191E97D1FBA1B395858B0FC7D5F5A54E69FB3780635F70A763E44075075580778676E6B9705B40F40210E597B5AA1AA77BCC3BE5005159A4B68CBDC6AD8674495E0DF65A6DECABAFB993CC49C082D358DB1E5B3A8AF2FCB0049A15BF521986AD84148135CDB185FDDCA6802C2ADE9EA2E82047725D73F51E072CCD799D696D7530F61B16E9B4727C58CB0F552B188F9B451BE543BD809B63D66BCDBAEB7AA917BE6AEF05DF559B3AEAF65D5EA12E852D1370EFD6197F970F52292F27923A10D01AEB652A9A44573C137257B49D130F1DA48E532B3E33D4854B995534380B4549511B39A99145AF5ABE0CCD3A9DBAF673EFC115CB75A9A5A806679907BB525A2BD4507977329EB4C985B3575DE6533FC5D62358C21AF3DBDD20DEEFD7C417C77D37DC2A098A8FA48F7944B7EC6F929387BA11E3516C9EA681238650416FFB97EA343D5F227BADFDD509B94C1451C54F85E4539A8F70DBB5EFBB10B2D82A16FD0C997C603B8983CEB840A7C3B61918D8A97766BB8442C3B9EF2D324E28DC19748417D32F642874A8927688C74BF4F6F6724015C4DD50EB83B85F613FA20938F5C895F88830A40C9799C212B2DFB453BA0BC534F75CEDAF7A016F6744CB4F5269FBF0284EB90CF1023918078024C3B125CD9C7501224050B4D20B585472B42A0F494513ED131BCD8F75E223317F56B37CA48780750DE0BC81C74A3388C94D93A65719122E9D533274811B76965265D7B2F91EBE3C5924ED2D4DD5E327A6E7546AA2605E4C78D0208DB7A7F678CAADFB32E6BCF8C77FC7810F7D1D5D50E26D1A0DA03B8AFCF99904B2B3198670462451925381F0BC404C51F2F18FA7E2C1E8B0C6CF97A9A65E575373996C3E9DA15A18D15C93548377677DD713C9828DC4E4EE823A241377C65A2948BD29447BFBE +pk = 87B9649D53376D1011A7A328AF862DA701C4EF755830BC3D0421137F03B40C0C7714CD705CB83EEA207C5CC2C0454F92E90B127A66809046D153A22C3380B45A922B74D27BB7132C479D4B355276ABFAACD8992267B97B559B74AD5E8D1A700B0857289C7658A4468D477D56D3420A6880E07C901E73D5DF0D6DF50C6FE814D0BE4B189E1C401CA51B666CE541B56FF657145181274E08B856758363A299BD5DDF86E37A0B17DAE84090F7C6A4B69FD6F2620959E83F92439C4D5C9844186BCDF12F33490D73E4525A2594FC221DA6B5C073B83819267F643D96495FF8BF65938D51CFC1B5C4A0A05CAA55EC2E3F9BBEE72D381CF7B5EEF00B64483CA64FA7DEF2EFE2DED3C9AA0CCAB8783735EF3EFDD5E0DCFBA4E2ED3D0CF89469FE9494E3019B91A976AC909C06CFCA18EF656322F6D7EA4BFDA8E9246B5DE92127F73E5258467004EBDC9D66C26A067302D241BBAC8D9FC7B234FEA34DCE2DF9F9EC59B515BDB6D3EC8D7303C843E5F6140110018046F6636022BC2651C97C994E78CF82D90D8DEA9BB159395A489C5DA52AD185CCC9EEE7FF9AF0CDC973DA5FC2360C35E6308AACDB3049ED977EA9F1A90D54DBEAA42FE29006634D56A01E504BE90FA990E17C36C5B7020A6B965DF250230B59CF7B7F654BBDEDAEA80C3AB9616F434301D05A561EEA39A67483E0DB2A36C524FD1018D4E4D04AA1FDAF31DFD9EB399E22166D6D46D6DD56FC0E74C91290B4D362E38A20042AB81BA7C6215F30DBD6F45A626C3FD4D4BC51A63B0377A48E24EDE7A3912585C2F4D1138B1F43DE65F9CA4B35D140DA99E360BD47377669A3E0B4B04655E45B3791C6CC581E11CFF0971429857A79A698A3F54DC0F8A9FBE9C981D3E8891E9C2BD84B0D03F5FE416B480EFD773EDFF192D367344F1BD09A246C2FE4937D43E8D258B3FB4354CE6FCE64AA0DE1ECA3047DF8B54629719D531BDB6E76162CAD61814A51EE8B577EC14C2CF4ECFE2AB3C0D662988B012685744782AD96061BC80155617E7A102033A1FAB1C611B1E7EF7E1E5C145D57F7EB376DB3075639545503329DF32745B0BB910E9812ACB182CDAA144835A3722A01EADCEE47663F44EEAB90F298610D594B9CC00670EEBC77AF0D52F8939D3CB1BAEBA5380F7281A4669CE99CFB18B04C22A0D30855329FCCFE036A64C173D15A8E19E301D81D01A417B5032219616F6AA7DC99768C3DD21D6648774B8DF000A585BFF050A261EAFA76746671B02B39394E388BDB0947667023C0693927D6AA93DE8F6A823A6156F00EE88281474A591984A7A53FEBEC32E07068319550366C39996D4B43286D11AD012251E0AA34CD89DB14F10E05D140A4C3AD41D5661BBF504560DF85EDDF01E775A7A7CAD78242105E391724341B04111C0B35692D5BD4095B5D064AB7F9FFCCE28421A6A365EC7958C59220F3C2A58984A16568F8D09AEC4D19F0AB97953F53229C068A1951BC5DB04B6DB201DCE19D0F28832655F6982B162275C25566D7ED0A76618253B87E62A0836202B0082E9303F39B64E5763ACE0186215DDBC8D260140525F43C91B0FD481F4286D1DFCC8284EADD4168D8B61C98CE0248960FE289382538EB397ADC9556741537713B94FE6A7557370374948287CE02769F8945C786D6A4E35B0B5888482F091D2ACA3A625F1183FEA400A773D7BBDD40D0D4EB542F11D33EA265D81F801394B05B5C52286C22525357499038B6FCD29D50E5EA2802B71F6919C27A1E009EC1AF897B8FCD46256DC1DC4E34AAF339EF928370244533A0CE1B06C41C2A23006C6B6EABB7594C808D565EA5AE363973D588366A0885B37B99019619B13EAEFDB1A5A1F50111FCC4577E5B25D243082CC484D9139C669574FBFCEEEAC2C9D81345E28A690EF282B489B703896F9D2450A6A426FEC070A1244C53A06E01FBC0F094AC2752EB6882434CBACAE95EF49BCBA35F8913CAC269A45DCC40AAD9764A376BA80B1F037B3F5CCA3427EE9E5367339B1C32B4B2E639FCF340B6DF537792E337DF3914A23FE0E79697B2B77F933B2EBFF5F2AC00F79673028FDDC74E820D9A45BB2F0FFBDE7CD7170FEA930841A8F9EC98437487C2881E67169997431015C9196C646E3CC69873B1CC066CBEFC24469D9216445464D014DC88E591195C6A7F7837FC92B935613BA206271D2FC4D336BE24404A28AA8FF65236B07ECB89DB107AD01C2408D9D2AA5D5BAE4A1E88AC9733201FBFFA09DFB7B3EDB311F77F48424EF0F16409CF0A01B78B2A906E47AC55630DE86EEACFAA1041773A1D2A544C48AE5297159962138C4451173D19736DF533AD97DF8FBFAD02A821E21B7976E7F9F9022AF4653E337426B2FD5E525A166F23E0C58E70D2529FB789C9B2E9EF478B02737BC410A18C5C454560B594383B0EE39A38D6A1DA2557ACEB853D75B50814C60A38848AF8AF7E8FC243E56D82D1C64513FB741A9A179F4F9C152BDC4FE09F111021D44AF67FF14D9AC87A22F1CD312C0C681F8B7DBFBABEC10326EA05E1BDCBB306C6A97AE504ACE2FBDD3D324564EFFA7B5BE420B8C298DB945491E93F60BE608175AB92EA534FE73A458825BF96BBDA724A1621BBB2BDA0714D34825937148EB9AFF0049361FDE899DBF00EEF83FB325BA53BE3D6C292262540D635A0F565BDB7F998758D66A1FF9DA19FE2CFDBBA12497EA51CFC9C4546D94366266A6F5BE332FF3F03E2E772FA796FE5E2F68E357E7BC038DB61B337078DA6F4F62FE45379EE +sk = 87B9649D53376D1011A7A328AF862DA701C4EF755830BC3D0421137F03B40C0C5A7F7C7C1EB1B8CAA00D7A92A17595A9FA3BFF205067C8AC8F3CA0CCDF04E8A3967D2CA47EDA8EE7FB9E90C7827F3F9E147870DE042F8C010452C8B5AA1E98BAC7172DD47F4D7F46708814E28B196AAEA63E54484E15DDB737008EF79A6FFD63465286464022552714575251081120776177525815224154732303041443656858521360516775131304531421830317325718357782344531366167216140328647517545718711226613552632868078472334457684157215402183812864465560134545285665027324534607505627781430607287168785603711211474036654221283006630767820335665427438801251634882304826243122382873643556026160682622501634247844556562277823282221715318272380514382166327832076341308510830104672741386658060731364055263072533024034440348176877168385844276011418807853507445742630313541260533884710322182875672007555352102111736153486546682400445314856353462837432265151201735077241861560606537472114427001633738128185143155681164418522324276660780013254735648130726670106143528152151446085486013530781563507817514423275831603274478056864333261221234688018236714455555341672420158046253828545443468575848133847511336773088426560632512270457420650070480571252567088256216613127287808300372546068157842531208277736661716476224255114561387561842802527534583242226866154005330601712814723148116858707623633156388318610725734626027267825460552374131568247608223526168028133215513323074840426070458361535024541204681617386053266860147755287631778604870341256865775810356462613277328621547642247338166235352446861000146700621207070425287378138011177815017887745350757282412283163674565073574580106851262711475646576343582824031332233640045016202277347677280507034572125140884184204174666740807210561288701854634375221252747614203268282450365555124245162185761546184630821464248227120208330166576446812051677635784843151487868820377560056606108053765556731423562335781058634262346448754055558574881233835332802652730426437605633125307752243671300104451622031178452086563378350643125487888351127447186068653861525843531163576456708403426386231744228603572543702078650120350475883485135123072788715541628386853226820064664257086414802302684824373503480121732643561671826241473335287820868110564002701077363752346565374758124278378607108655524506353081784250867281557355154124716640162628134065863066707685813333772050651751364414710828277432330660035587615822226823583888065753207343551776325031828822344516276348304524581111753487573410125463303084622318654161024010277077576741336854457441307244224445371337778855655354441328843441648078187464352811818514736657287152433674780365130838675087775007860116301656583124318753171584431228031256142511247034774121058045228622026453471310284561284738115183883363562877535623864477287041628578042482807540355551638261778424887531540523012284133317055706250265202776462302754382208531285370062731414002517636735878653716513301083321511832713277468270728735173264164438628025638044228661330367140381886273641753613264238682150600113580510576848725620230467654501787348847266643040404063504765243608131178436637773680553636520528104074337868058868645632711487464ED9789A2786CDAE62A85D6B0F4EA4EC5CC51FC01F5285BAC840E27400A5CCD535AEC9FC88394D6AF007A0D5A1665BB3A541CB657CEF7EB593A3EB60EE94CF4418235ABF1FB3A27053C570D6E98104A3436516DCE7780B0D7A5F02736FD1A70B75E1BA09D9B93E1A213A58AA66EBDEA3123A78434A337DA03B50663C75A006F076BAE750A3EFE03AADB3FCDD88DDF749E65CEA94A51E0F85E92B00F1878442D5460B3759A61BEDE2B163DD405C76564696E36F9060192018B4C73C717AF5F6E27330B51C626932ED8DE06C26BA026351B8FB0F9B3B84B7682E92FEADED6D5AF5716A479DD143B013872629F82E43DBB032CD602CA1E7BF690913842A583636FA382BC094234955185016CD90E00576CD5EC4D500060F95C2388A65A2274141380F5D1214D4A3DA6D14FA0D5B1BA8B3A19B7842C3B86CB73029191F4192505526681FC0BAC20E2D77DC21FFB1DD9022B3F32222E560A6B347D82D4F101D720BDD5A166D097C61753CC7E1B0CB9AE8207C735997C7193FE8A15A334A914152F83A2334543F05FC1907B14BCDCE5664C8F4892ACCAE79B91DE7AF3E0B9B2304F4242DEF190C2E1D08C76AEA4CC236E2920C2C7A97B615EF38B45E7351AFEB1033C5C2CFF60CFEC90F23811CC4418B31042B8624760C9ACC6809B86548F28C461A74EB04942F8D39433AC6A7392B521E452594EAC5FC4F260E68FEDE9A36DCD0FCE9E00284FA9FF321278C059C99A5281C140AEFAAA6595172A505F5F4AA59666BC7F0F7C0F7D758CE3359AF7063A97AE844E731D77A423561093D2A0DF0FF1B7D40699DAC4A2EA2CE54C385462549DF586CF0385D58E34700D8C25A0FF1AE7E8DF3DD175E8284377F6F74DFF3341011DEF034404CF08124590F2BE295820AF467B4FD952922E179522769A462FADE80DB280517CFBE33B32781573C80B065F8D9AB2ED1E93DB55968565D12BE30808E8197AEC662BB56FD62089589322CE08C0165D32FBF69F2F3466BDCDE39F40D9A22445EA5375635AC01394D91EC8D40B9A263C3A9CA3FDD5BC8C69DC4E8689BC9E5D813995BF234E4EA966757A7FCF882DCE74FBEFBAEFFA664C1EB7B4DFF957DAD0D35FF22407ADCBB7069829167EB8F20FBB060F2C0F3BCABACE81A5D6AB94713DA4A3FD0EB8982414D75BB4BD8E9371F1E7F902F65FBAD9315DDCAB8B6F8A1118489F552F26ECB1D168D8EB57C98501B42E1F40312392605ABD43D3882B0E1E2BF15A34B73214A682D5BB45812F1681065825CBB1E755C3878E50C7CB69251D57D3FD0FD72C776BE56EC733A04DF06BF0C9D415264DDC45EA56076DDECF5EE346B5708F87E3DA37237ECE7D5A2C7134C3FAC33258B31865E51690E434E9AB73C786C41CFDFB123D6DE3622A8E13E47127B3DBD1B070FA43E6A7EC741E1F8D86C5FA0C8C70F9EC43300EC920BABD529E1166E494AD8A58F1BBB2B532E6E8555DED67A954C420755798587B631C1CC0E81A329FD05B8D49F89E875090EA7FABB98103314C5F2F62658647A7A467C6CF5CD782275B3F46CC2BCAD7C6A263102CEF1F6B580E5BCB1287F7CADDAABCA4FA7485EBE87E9AA579865A8CE24DEEECB7415869510EB0A70C41309A353E46E133B93F5DFEB45F5767EE940B99460FAD55DE984257852A83A46C78E7DB42EB72E402F85B2B7480FEB5BCA3ED612B10809503771A107006F9116270A5B5308170C1A13F170BFE8F5C32EF40EC3E0A4DFA908A681B6CDC61DAD0535D222BA178ACACBDB51D32F6B63A25EDC45ECA337E07D11999329B194D3E5C32072A474437E750BF383568B1A8A90D0FF4E9AAD16F3D5FF205F4FA09342CDC18A3AD5C5599DEDB81C8F3A06640449925AB2EC162ADE548C59AF4DB26D3477D7FF79DCBF54ED126DA730CF2B2D1D14DAD5CE10AB59706E38541E6212EDB7074AB8F2865EC8ACB5E6F3DA623FFC72C12F1D19E93936510C71914B136CBAC547F01D37DA6BDE4D6FDC48C0D18960AB7994564557CBCCC7C68AF14B42CEC6CD08FC48A8F391AE23DDB8449B3392CCDF38B23784E8F1B05E2657495D2FE510A6DB28B076EA5F25CA76BADA2E78879F7583593977398C94565763E5D14134A48DA7041DA14C543B1E5B47BC7F617CF0960B7982FB9DC5649BCCCFC5560DA4F2A19959A46733090B765D9BFC777683DB1810A4ADA4E4726C2B3314B311B67625BE4D3A5C8E33955A95317E7043D00ABEF261CF6043988203B95589B0DFCD56FD30825D0AF289977888695C18A08B03B5F6D61D70AA2E9C3571752096594FD8A333C10E9C7659FD8E20E709469669A26CCB9089ABC208DBAE396EB4E6FEF43545355B011029EC32B9FA4A4EAC9E331631800114E2A49BD1E73B02DF8341C2D117F20D9438829A09EFAE70F4720D7A756CE1933B734E2B0C867CEC126328EAA4AD1438027FAF61DD72797CCEBCED6B6C4453F384127CD0A81CDEA07380FD3181E07C85709C095A6E9869E46B279BBD4D16469520F10D6FB8EDB3544A315097D92374B75B1940AD24A46126F81C32ECEF2BC7AD05B9A4C1CCB87F2268F66A59A23AA58C1553C399C24209DE59569D230D4E00B9D83AE06BA025A7F4D563E37DB47CD7CD5F942F0FCDDB805622E68F3A4089BE1A9599319B94FF5F815B07412E242FEE4F165CA57D03AEFAC972509ECA3FDAB8141D27909EAAB742B1C3AC5103A7E319FFD6A92B7372C9781A5A9A2125977442FFFD8431BDFAC402B94B128D22B2A1DD990FE6C8B4851B21733FE48C4A2FFB2A7676D6C3A9E399AB359704043BB0703DD06BA6B94D182A9F7911CFF409039BAF9C29CE864BC7A8A5B89A594C70B412636BA398A47896ADC857B4D73E93CFA40E4B6BFFA5A4038CE1AB50141309CB8B186FFC2DD71C6786E527F9A53B522113661C3E5EE222F4542FE37AE074DF22B4201676E2F1C96567FB1E3B5170ABFFEE9CFDC53F86B73AD3D74AE3BD3FB2F289FB9ED9E54F6C764A9C6036503D4D46A61C4FA93B057AAB7801AEB24A8746F251E6C7455025234E6E29FF258FC078B967992D39156AB33342665AA0C1C6F280B2583380B51B2E0820808A5BB12C9C9E18AE745306E1DB566546D8C608FC98132936B306BBBDD201BA39FC7EDB5365067ED0B3C1A23A6274DFD2482CB70EAC0837B5E28BD42A274672DF493CD7756ECDD48068174EF14F64D9833DDC236AFC639D67D2E9950A609BA146A1059F930168D6215EB850EB02A6B42BE55008371524F4AA8E666601A05D43F6CD9123EF7D59BD6D46929714A0B4F548190C75AD32F0ED4012C763893E518C39EB29DC26671939240B6404E47C2E179671A48752736B114AA41932954CCB00D22F38C4F955192646C8A99CA74AD6E0D1D2DF9B83CA3E088E807126204910DECE5EB8F9B10EAEC3BB1B77302B1420646F4B5C8F81730FAA25E79C7FBDA7A8AAE09E62CABBC749FAA726BF756766CE9A1989F411BFB4CC162AFFFEAFC8DF91DA57D7E5A238B979D8DF3DE6F9B2A10CEE266FCC702CEF89836561E672B925FF68C251DAF91B +smlen = 5223 +sm = CAA59628C7DC5C3EA31BF7A113D4686CF33E244C985DF5A1C6C09894254D057FC04030674D2BF64B44ECB78CEC3FD4BB8EAC47EA601CC2FCA65D5C29A06FEDD6ADD31E9466F8F56A0626F3BB8176B4C825EF4D13FA0118E33D69090C0E8195EB7632EC3561358F3C169F34F5EC1F18E0AD4E6E0E7A2E0E4610C66950ACE9F5FD23F5E10A96C3966A4A79F11C285EB72BD92DB58C7DFBDFD36954C9AD6776C2E96EA8A258C55AABB9BB7ACC64414394B00FA0F48A31E320080B9542E74E5F3380C69A9794D22E86FA6AB17096A4C751D38C146C60663E1D66115ACCB1CB92E3983C846018716BDE8C799D3C14CEDE3D9D0464D888BB9970AD92AB6FBC0BA4BCD6EEE82F4765808D08F22D6ECB49B19D990FC575CB8924BD0FC545E0C180B7C74198043D5EFF2BC539D6006E048CC640354D95B45E335F7DB8E0DD6BD1112A46533C848CA98D736B09C01D521D5D4703E30378DCD56CEE1A96EC7E04C8E95E7B9E985A026E74F8EF94A4AE7A07C2DFDE88CB61892BA41B8AB65D2A381F10738840419D7F3414F1787156D792F948E2D41C4FBD1126B43F93F6FD5236076A9862A5ADDE0552580D9241ABBD8DCDF5C7DCFA558F2FAB2D62DD4FFAD62D72B4E023303DFBB122E13636911DECF5D7C12F3B8C00E174C3BB993B26BAC270BA8AA0F956C37085D85C6A5FDF2045A2FC9D13C3311D3C622B19059C85D8A2157146B9077AF7AD7F5A6E8CBF2C35A85389CFFB268F94BA04F67DC39795816459E79F00B1E6A9D45E2B2AE06E1E2C062FD97636C37FE55DAFB7D6E6C81D8830A4593CDC97C6396E72B040037FDF09A591C5276CA7871245E97C24642E9C65F0318330C2B273C037F9E524239812BC1F0DC378333331F1C026407F10D4DE614FB91508770D6D250589F763EF0BA66CE3340B202B8C16567BD3AB40FAB5D6D0C03F041FE9BCC1BA928B145AFFBD2743C97AA090910DF1EBA1C472E94632E3E194638B86E62D0CF8284C791FCAE7B1CA0BE277EC6C446FCD41C76D69AA8456EFC2D04E191D9E065DABFFB7BC32B87BBDD72E44755F0048D129D19990C80F6DABC2B8E06B23DA53CC9106DC67AB72C6E3991EB2B85F499BCB3CF1D976D1B1885503061F28BCCBC94066B7D20F73ACE05C4289E4FEC3E82515B59981C993B206800CCD17AA1DC2B3CF8A3A5A75920AE2DB358B1D6F4E5AC69DD2C74C10FC0785D90C044F2BBF03175C4BB125A9EF4D51EC28206E61218BF89A83C4AB5E9DC5550B862DDF446D97F73C5DA185912431B3DE1C4ABA01A33E8C6783C19CFA9DC1357BC92E283217619B5C24C740AF038719C8E31D11F68685E27A86FBE084A97D0E7C91E302A35923C6114C49B04B41A1D6BEEC8DB03B517101983AB70E1BF9A7EE9388E1ED65312154582564BEF01192AA1FF7E569FBD13FEBAD61CC55369F6729257FC8ADDA2E2592FC34591E1D63F05441CBC6CCADE9F84F8258E9834F18CE5F7522DA1CC13C6A2642A027BC2E9FB446645A49BCDD77FBD51724EC9DF788C526B187B067EB7D721E7067C6578F4F752633E6C49F2F0AEE8641BEE765FADB8F85D5662EC0156903C007A6A0F7652D6183F8E81D5189F6638C88D82871D1D88D852502F0CF71E6E4E3A5D66D76337EE4927C37026AF3F8C919EB10EFC6EA2A412CD86FEB7F8E9F6FD7FF400E64D14C01C110A9F9F922B23D81C97C2C04D57811C14F8EF1322627B1B5D2FC4C64A5CE0E1259190D7C3A4F2CAB709AACEA6E7960EB59EF6DF055B89DCDC547DF0DBF16E04A5ABFA5AB58F27FC9FE35780DDC5A245312229A95E39F66D49C000AC6B379386DE5A84E8FD7CC923CB27F7A6D1FFDB174A23ECCB0B146AC67B175CB9873146E6B24C65826B1E75D784E3A046E13C80194AD942959BEB4241DA50EB4C0E0A42DFB67DB44EBE7788585968B40807295E03CC3D48E6ED3DD2ECD00B86C03635F4B314EC4B38C88FEA629AD5EFF3C6F403FCFA00E376FDB661A1CBEFE9014187CCE539C013246AF43ABF8D7DCB63516EA26B849237EDBC347BB684884996FF8058192265BD1FF145252AED2039B875D776741E424A006CC971A23E0F9A25822E578769CB4F5B9B0E92942EEA3E2E6830D7530DE8F9F8EBC99DAED9BEC3605513FF6933BDD92376038E395D07FF751DCB6F6062FDFF73EB05B9E852327474C8A769B8F294CC72025AB47186EEF3D6347B9A17F41AC1EB017E694E4C026DB2584A117A752DF0A8308188E69E6A8C3236387EA268E77AA5E13F7930CF155DB4ECE2C7B80DF60A3342C92BB7B6EFEDFBA47BBDB299AB91D7630E51BADA2E036321D03C3AA46D26D526C5D5550387ED37F2B44EBC1FD55E74FD0637BD26DA4BF3537581026F9B95EFBC671D7B4A548EE1B51790111583C3D062F8AA2FB6031CD0AF001891B8E95ABD70C8014AA7EB67B16062B8109412AA82E2FAF06B8EEAE6FFE18767D6E1CDD565135341C6E207E2DAD72D5F8A5070C0B0C149A9834C17FFA8C5C7194F425E55ACDD6234A6C6CA9DF0DEE9939CC2E83AE1F68FDF322E1C8A1A10456F52E627DAF54479D69CFA40F04BAFA6C6205093AE1733AB02E793D2F6D89885BE89DD3FD4E09440091C1BF971DB9B25262186985F2FFB2FDD136BB2C82545463A4B09B61F22FD1EC4C8DA950841C01571E69DE44B232F253F366875224F469FEE86753D4FD833058628A8757B8502DAF7721A7854350DFC14CBDD550C01EFEF41DB53CDF19A652C6E77451CE295C16B0B2690BB4D06E7FE6E3EF4B4052E82F5A32FF58B62D82D842B9C30FE7E78E9E552BE172E9F96B884AF8F4AF16312BCDE0BAFD8D88C7D8C315DE2429C341A1C357B399D100179F8730F20659811DB67CA0EF5FB134C032DB8F6D4E31B6F0A54388C595C1DC4209579A12A123EEC81B659DDC3ABD6CA18FC0B859A13C1F27CC0213D7A4852D689F2E499B6C2F694C8CCF4FDCFEFD7E842A2B5EB92D93F916F62A4DAF1C9BF4561AC20B4A79125EAA669FD6774A464AE8BADAF3AE39FB18833CBBD91CCA05D10BDFB92672A27EC2CC8D8F16C84B073F3E05660D316A83A8E1328F8CD97613A6E863555F09E8D8701BD53DAA9FAE421129CBB0F6A6435678CAF367FCC229F042517FFF0EDBA3E28AE6567F426A34FBEC5BB9EA4141F37513C8629EE265ADD1FCB2A19F78571508E8D018FBC485A18C0264B046F207E9BCCFCEBE47CFA3B677146A5EDBB11AD54DCC08C9254F35BA933D78A92EC3DC880E24F9A6BA53F0517F807C7983BA0323015178415C51C6D1A4C9C938806F608C8AC50D85922FED8B9677D481DD481EBC46E703C92E325199ACBC2523E5F68515290863E0110AD68B5623A9D8575A1C2A51EFBDFAC426AC4CA2630E2DE9933DD107EBCB8DDC37E65B1BF0CC32EE686C579085D421E65EDD5748470DF92DA8DB7D8388EDF56F3382F4A04142A3BEDF0931CC975179ED36389C68AF22322C6166B87A943B7C5BE1BE1694CED5D0CEE8BF6188B3137B353EA567FE5AFA3BB698CD1C297BC45B8BC8B674A7D58E444172D10365BC13723FB15763D70019ADCAB56AA4481EE2DE84D43C961C1524EE3C2B1B82EC7FC444239CA62AD85B6436FDC438F875F4C2E9CD1315F5EEF37B742959F2FFE2D522801D886500DB3CE47468AA7BD4E6D01F7BA8618E25D0E51F97E74D45D315AA83CD7B5E9FCD2AC1F4B2DE9528A45D22DB1F1F6E796BC9696F7FA3A8EDD976C0E533C4DD584FE165E517533AEE26B3656D43733A659C63C66A6C80CA21047CAEDBE654011629E62176899E97AA42A405A3982B0E7D493B187354AA0BDCB2492D86BC46ECFCDE636D00CCD5865C92130E0D665A5840C333633137F2B517D72B484858B0386E112F80C2DCA2E50465CB14AFEA1E9197B8640366D5540FEF559C598EC95C4CB300F956D3036EA402C94B2385689B39EB2E9A09EABD5912F7B933403B3AD49E8523390D67DC1419C2BA5F78CC2133980A873862BF684777842FB9E21A701E84FFC92CBEDC0950C9D9F7C6387801B810289A3467581B07258F13DD5180B9BB6D38DABF5444E50D43331D826DC85823C4350E10F12357F2342E149F18DDAF4E2903DED974F0A1A878AAA920FAB2038710267B96C9D6B7D42A2A639FD51399198633D5B63B29BA961821D8FD823DEE58C89D61AC8552A609B9A52901D06E9C2D58DE91FE6C2C068D375CC7A69606BDCBB67DB629FAE9F8321825611224AC327A7E48E21303ACF66F9436E36245C8B7C05CA4B5CCE71D4A8A25A1B96D63DCF5F980B760976379FD419392FBEC1A1E464ADA985435786625F7A96F9DF236C7B38DB753C26CBB908AF2C3D023C0531EE6FA91A164B30FCAE38344F870A72A037B2D754DBDE0590871106AFDD6D47EB8A061E4790B59AB2904DB3D9E940141244610B0C3AA57626648AB279FE643FC462E672AEA0A8B3BE4A611AB6A3AC171AD0B05A8D918EB86573E8AD2445E2DCE66D5CDBBF9AB028100D9EC23C8CBCEBDB60B5DB1322A7A5DFC2F38369A6A8614ED94F733FB77DC6C414444777A4FEE8981B3A7717992FD44FDD3A211767F7388A139BA6416D98FE5CAA546E2CC2E3FCCDDF054A69C1525150A434B7F84123B49798EC17DADD732B100232D2F4856669BB86B6EB8E0F7FC5F78798FBABBBCD4DD00000000000000000000000000000000000000000005080A131922F3EA695264936D537D86E545E132131442C2973D19B37F8C911E3ECEF4A13A8B1EDF5E5968A6198D26205FFE6B76CB14E353B5E2C9DE1BD44AB9BD55862BA1A479833335725EF52601810C778DA4A32C497CCFA43F91C72A1499E8D295AE7CDB43F1CA05F0D4A31B30D9A69CAB8288640F3F9E081E2C98CC8351C7EB9954D428DA4BB374B346A83EFF5AA3F455F2BB3FC922F901BBE5695E3AB9892A93BEEF90FC150B3BB47F6965C229F7DCC3100A4101840417A0E2547F9D42AB27216254A2898368BFC60E7D407271C213233B6913C8E48DF10967757BFAF5B5E2A284B8F67C70537C97583786B5185B45E2E36BD8B5443E98601F772829176C4D66F44A81AAE7C13F539490640BFC40B83E1C75305B06BE60E18A0AB568859435B715E15BA1EE4DE73E04E1B09DD15350AE423C131706F057255E9FA8FA3F9E3ADE7435A6451F7A2AAD0C0FE0F444C4A247DCBAA49E7C926DD52A33D3737B4439C1D40F861720E37BD25366EB5F34BF4B552160F3EB80CA8FB19304E1E4143090F8E965DAEFF17551A3931905B5CD991C6BC5AF5BE808073893A47FBFEEC0940EF5E7D2F2EE199847E1A4BEA447BEC40F86F6FDAEBECE6FF0F66E04193355C9576DD4AAB2D796CFEE5D432B1D32E13B8903A06FFD3AECB00C169A3AF8389848CEC724F647C6BA8DC3134CA18586DB3E4138601A16DF8873A490F23C4D27FD9C3D4FABF2BDCBA4AF3F0793E7B591198100EC97602D9BA572409EA49D7C8EDC646335FD4494577720EA7CDF3B4266FC201DE4BC204C0D35CFB55010BFAC68CA0DF3AC936C9FD2A9C532B8E3461D25362EFA37DA159B64670060CAB833ECA799FCF1342C7EE1B80BDE05ABAD08B9EE8908D50CD0D433DDA0B120D1980F690ACAD9C072502AB537EF71B691917A76D3098C27FDC6FAD1F1B29E307E17C87D9FA6A06CF8CEF6568D9E4E005FEEFCB5F41A46D91E31B41268367D636C4478921E690D5D57E99DA3448773D51B673109CFD3A58CC50C127F34F4963FCED6C216E60EA0952317FBFE88807BFF4223624F6126104CB46C8D39EE228BB4FC0002287E346E5ACE43E2CAEC07A22203FE3C4AA9008A94F7075F6E449FB89905BB955FA0023608C494F7B73D2AA4E2B0A8A7E3CAA889B6B6A6640F7222EF969D46FF6794BD97C5363921461BACDA17F2781E14419436E37610E52E3B7B7BF9C1A4B1D80876030F9A8981DAA4F06A432DBA739DB988BED5DE7F38378EC1F7D8A46B305896CA0CAA5D8AD74002863C6FF91EF25AE96450936509EFA93F94718E895A82B4616A965AF004038E0897A6563DBC91EB5A6172ADBA052250D06D210BCF5A250246FC3482E57FCD9901104C5AD58EEFFAC2860A4DA9D2C308552EFBDA2D4275F3F3651E9935A0E42869B9263FC7EA71079E604A4EC6DC61CEF6AC6CC06194DEF432C1F7CD9EDFB0C4B448DAE3C2A685BC818B2A90E17A4C1CAAA5FC2632F720E764E2B8DA314224498119A0D94CF5DCE24176421C2736575672B361119EC7C766265768CD9FF1957A17779C11244C1CC82D72D4E3C87107885F71C56DA2BC41008B0BC1375C12B3B2A80071EC03E377A93BFB227BD560EDD5E5D88F46F7FF9831F05BF262F01F62278D3DC13F4F0CECA0509091C25D20666D8D3527975CA3495F6843B46B5D5B6F5C650E981DEFB3943963E14F00A0F78CE785A21634C46B531B4F2AC5AD0F03D92372C334CE963E514A1891716EB5D5BB1B67834994EDA492719032E2A4F961DDD6D2002D8F52798C45A9DA8145BFD191E97D1FBA1B395858B0FC7D5F5A54E69FB3780635F70A763E44075075580778676E6B9705B40F40210E597B5AA1AA77BCC3BE5005159A4B68CBDC6AD8674495E0DF65A6DECABAFB993CC49C082D358DB1E5B3A8AF2FCB0049A15BF521986AD84148135CDB185FDDCA6802C2ADE9EA2E82047725D73F51E072CCD799D696D7530F61B16E9B4727C58CB0F552B188F9B451BE543BD809B63D66BCDBAEB7AA917BE6AEF05DF559B3AEAF65D5EA12E852D1370EFD6197F970F52292F27923A10D01AEB652A9A44573C137257B49D130F1DA48E532B3E33D4854B995534380B4549511B39A99145AF5ABE0CCD3A9DBAF673EFC115CB75A9A5A806679907BB525A2BD4507977329EB4C985B3575DE6533FC5D62358C21AF3DBDD20DEEFD7C417C77D37DC2A098A8FA48F7944B7EC6F929387BA11E3516C9EA681238650416FFB97EA343D5F227BADFDD509B94C1451C54F85E4539A8F70DBB5EFBB10B2D82A16FD0C997C603B8983CEB840A7C3B61918D8A97766BB8442C3B9EF2D324E28DC19748417D32F642874A8927688C74BF4F6F6724015C4DD50EB83B85F613FA20938F5C895F88830A40C9799C212B2DFB453BA0BC534F75CEDAF7A016F6744CB4F5269FBF0284EB90CF1023918078024C3B125CD9C7501224050B4D20B585472B42A0F494513ED131BCD8F75E223317F56B37CA48780750DE0BC81C74A3388C94D93A65719122E9D533274811B76965265D7B2F91EBE3C5924ED2D4DD5E327A6E7546AA2605E4C78D0208DB7A7F678CAADFB32E6BCF8C77FC7810F7D1D5D50E26D1A0DA03B8AFCF99904B2B3198670462451925381F0BC404C51F2F18FA7E2C1E8B0C6CF97A9A65E575373996C3E9DA15A18D15C93548377677DD713C9828DC4E4EE823A241377C65A2948BD29447BFBE + +count = 58 +seed = D9281003AC5F7673E0E9A7BC29C4ED75E6B0F228DF49D11A2599BFF2DA9E887163BB26DBA4F071FBCE02891540EC6F1C +mlen = 1947 +msg = 437E0F77BD0E14D704BE86135119F39A0A65650C762852E2694AD9BF2EA45C7EE59DF915F5AAC128309847E944127294566FFB193D0361DD7111D32B06DBA60A12E053F424DDD70674E902E409BC6F5891CB9A76108322CDEC1491D3D89A74CEDD855BB0791DD6DA371A75AE979593B5159FBE9DDACF88506E6A184547E2A7395A46FBAAAF286EB7780B789FED86F257E5036A3555E777B909243695CE89957DF492C80050457AFD84AAD9F8918099AB00FD7AD3528A3D0AFE5B52300053575B839572D4D7CE43C255BBF5F16948D40BCC2E63714487AFD3638601ADF47A324482ECC99FB88574538809227F8C0A5FA7F20A0B2FEFDA38E6A665550E44B8D5630290A4815621A5DD74A2108CA946241C48661EB087240788808BF676B145442B2DE4C35E1A6B8CB1E97E54CB729202D8827A0D4994C6D7F3F406ED273B00B6590006AF069D69173B5EA8237B87705F362288AC3A50BBE7E70EB15DF6ED820D66290F57A87E51B2C5777C9C95C2A76ECF2E296A7C295BFE029BBE681B32A6D9F16D11C7CA2750E2F8877AF5DDB616D8A820DE998B0B2AF5B0C2C5641F498C99971932327EC2C73C0EF4058D9F33683F60553AD2962370AFC6725743C86E591D7D7C20944479DACA5E92D66A33CA0C862DC60DFEB5EC3C6E7DE356F6E43F06B1431358285398F8885176D60CBA218217DC7AFE4AD876D0890648052A56812BC3F8A9E6C49F9D70B0A032924B891A9410BBE2F214C842BBF0511EF9017744A0DBDBD500A4189B471930E25216D2588CF8BA39AAE7623966CC62D6C4ECC8B00B0613D912E60ADF613C8F55B778EFB93A513A776C64E8DC943E6272C0EAB4004B4B05CE9BCE9CE2F2B86FD8429E9A72CB16EC3DED285339EDFCD122150F4E7310F669B1DD4CD7E76D282D10314E8ABF61D53BF343F3EBF9968E1BE8F3785581F675BFC28C893729CF67345D0F7C11D6E7D6DA0BFF255BF706C986704A3B9C6FA0602C6DC108A59CCA70F624B08E4F5393E597459BEA4AAAA463A3B08DE147E10DE6B75A0D87BB79BA9A71E7F5999C8972BA992228B60912AA2D7A32703BA8BC02F774430A2B590911D48D3866396F1D71F19CA90EBD5277743A984E2156CB57DE88EBE91BCC09CCB5C687CBCD4E48E4EE110F4075A21F9A051700B0C2698FCD6A5A73372CA366A230A9ABD153E4DCAB7A33A8226F8458C5892098BC0A95619880156548F300C40BDEF81E8C1D8BD03031C690B7C3C000CE99675ADB4B94752EA22BC9E0278D0A53A2A19363A9388BB8D6C24A45B5DEDD8F7482E9C29603FF182F25856FBEEE2B41B88B352F99DB5F33D8EAB1A1A1FEDE60EA6CFB7478DB7540D3A286E88117503C4D0A2C13D32AFE3F1A31D1AF9EE60EAB8FE06248CFFFC7BB438B77D94B5644805CC276F19268DD1FFEFBAB3C796923288638DA1C15E014723A84F8C2DD9F55F7ADC2ADC13FA7CDC29BAF48CA438C882DA5F7CAA792B7CD984BB11EC4B681B332EDFD4AB4C132B08BFB688F81BAA3FEC5A079E2182C282A3EBE2AD5E4C59090BBB989E6A07D85D604F5FFDE0587ADD29A5175CE65D29FB9FDE3E8B49EDA1D88EE8DD64FA1498D33EBAF4A847EE9FEDD3376AF46C1552A150014C11DDFC5047929E2415D3F9D81186A685A1CAF2F004DE777760F0567E880866320A7B42E61CC994719DDC81E28525E50195FFE4E0467D9A9182B75EF57DFEE926D7744485A55E07D1BCD1C9B9B12A60460BFF016E9834848665F132E2FF87805E00154C7D9853DBCA43D005BB197EEDA3D2D9249A621EFC4177415BB103893C82EEB0AEEA056B40E98B5FE65527432FF33CE3E09FE1288A6E2641011721279253800ABC4B73F65B15B434BD34A573E77A94729A78C92F0E791570A416A0876DB39A8FDA8696FB12E7FA3BB11E7838054E4195164B9676DD03327810CCFF9586217AA3D50E7D3EBDB1AE1BF6889DF316047CBB278CE8C9741798452A38E48A7138E1FBA286B497FDB8B1E7BF6145C5F29ECF6D5430F8E550314DB3CF48F27897F312C6D9D6357A880B721E5148DA7F789238CE411F952695F4A878756BDE311BB4E62F10C2F9939B8530EF70D3FB431655AECA2AD36BB5DF0582A07F53F1DF8E0325E635D5A5E795C130106502A081F2FC52A9D97C5DAAF174F13D2DE1EA0F8860F08F4FD5B571E1AB1E84437F3C82BF19B96E46513C316BDCF994BC26FB8461F90594E08E6D4A032C1DA38481A1AD7BFB7D5270255BFF23CE035535CF478216E6D2E62E147AD93357D62636B1AE42C4E8433BB94CA91D0F8EC265F2793514543AA86B786D9760BE5C77AAD5A8449A7DBE92391EAAFC305C1267A68E6ACF0F044FC144D82C917992748B9232DEC4E33EC97534F2BF60B56EDBFF675F0343C9C78E8A8D0529A78E2EED9F998B360360352009F01905C1A4815A36B111CAD8E5B34688B99216171D4F57283CD669DC05995BB8D94ECBD3E7B662C4A603BD85251F2BA35FB6CA492C2B3E996FE66A1EB904CCD61B0900E7DEDCF136F50E4C3AD5FC312A2DE4B3E51F355D01763692C0722C700A544E681A316A1D261FAD727E557398E500F15DF33883ABE9D1BA645936891F5A91FF6C8A7B9B6FE5062718542DF4FC4BA50D7F513945482381ADC42D5A9D444CA211232615306D7241FC49F08912BACBAFBB056C018AD4D6021D99FD720ED6548A5A29DAEFDCE868D71A1BA72D9F998A3F89FCFE526493582C4C8AF5C1BE065EA29F6155428DBC955B745DF +pk = 44E7AFAA01466EF01BA7D58F8585FB0D552538947C39254F8BEC4203490AFEDBEEDF327D241F345298EFC3BBCD3407F8428B3995E4920AA94E58ED41A05698641326AFACA662C158E63188C1B042725AD1C54AB875338E976EFA3A4AC98D23FDC0662EEE37EDADF2DF2A026AFE3CEE69A2C734A9306252082AA5E85E7E3FF68A15285D181BDB3ECDA6E2C902CC6B6760C49CDDA5316AD3656F04C344F93CD890D72CAE9502C8DA2F63C5A45FB793CF3EA43A93045A32C6A142585EC36ABEC152BF5D5FF29A42278A6A4887DB2D951594064FDEC844F30A1AA7DE5620AF2F8C539F0806D3523797669C1A3E3EBB4927E34984CABA868456680B81DC0BB9B919263A96E6D9AB0C6620C15A9D15E053E8FC84D330544887286E68CD622363314FBEDBD74B198ACE667328EBFD2D485D7C50F6DA9F621455AC3E169B54C3341475753C86E56AFD8E7F831E0E541948231F442F28A5C8BDCB554C5D749E56B1129C7B71E59E7A73EAE86011C0F578DA8FDB727DA7A018EE67E0AC4121BF7F4C80E95859BC76522ED95CDF2FBFE42FE03B5A00886C2016A012161E3EF4E3F1212EEC3095300A67CAD914EE720F5F8C0ABEC05D657F7BDC9F29E6A731815E014CFBEF6112CEF6E437D97D7B68237734A9040B99B185B315763ECBAF900BE6F347363013D7A00E4E87A59770A7F1F1BB02C33C2A4BCA19ACB6A7EA0530435A93F679D49019FA83F8D7C6BCAF0D16FE1991F847C129CCE60A9C7CD899E293B1E1B628C27D463AF11E64A36AF45B41850D93E46433896D9B84E9BA5E8DC4360EB7EFBBF0278D1BB74CA04580EFFB7709D3D7E77799FC56D422A58D9DFDF0DD4286F2406756F832731DE2DE5F80B3810760B281DE2DC392FBDFB443A202252699FC077895695A9E47E4A850A1A56184962C04FDCD4DAB2C04DCEE8F66914B666F33F9CC4CC1EB2A0E40EE9F1F3BDB3C2C60AC13BA217485622D6C885CF61423989FBF753B0A7172BB6FB186D5A47A3B140BF8A2185C5908F3826E5AD6DDF9D80D6531EBA45D1AEA74297DC4EB16F3C717A87251C0E8050D8CC8AEC805C2B4003E901041380CF57307DCEB0607D9095F1B023BBAECA28E25D105DE8D11F9225CFAFACA16FF2AC6192E0270381F19A837872D8FB13D33CC5F0715494203B4AE054197DF6C7EEAA6C68667A5C9117FD79BB715445A5945579C637CA026AABF3AB6B202473566B7549C8E30DD0BFC0C3D70009D2102CB1B9653F99ECCC5AA4B617D06B6FF86CC1C5FCAF25F197F7D120C027B14950321BFBF9842D3D4D03BDDC6EF14FE4BBF0797BF1D1A967FC965A96DA020DF76F78BEC7AC9BA49BB59840B37335A8CD48E3A36B0013503755E4EF4FB20B64F9467E6EA8081C41EB79D32A4FAE238A94D1B33408F51780DE1864F2B498641669F1215FBF1F61D69DD5AA8C741C0664087802983EDDE2BADA6330B8E0CA63819A9F5820B8885132DB1FCBA46A68E415252F11CDF0C6AEB4BB4415D35F227AA6D45C3B74295C70B89944C2E2732532F32F43F38128EF87C0B2BE108C01043B257572610CBB58BA1E105480093D9BA6FA822D4D57CDC8CC5FCD5B8693057582340973337AB4A943428D43FFA2F7A5B0046AC62D5DFB2270EA541F358B5745C75A7D11838922581357D08E4F24B88C8CAA2AB06CBC84C9AED857CCF3DAE7E84781D313E7F2FAF3F1A21D64FA45B2956C571E8B61E6DC0D4F90BF4EA3945A4DF9578B19142B860E206B6C0F8718E01F97B29697BEF74AACF356D625C7D56CB7FD702FF3CF801A4CACEED6CFD241CCDD22829871EBA6CD1C5BEEA1A90546FEC3E6694B64214213759A558B4D74CFF3A89564462EF00138BF8DC6394B2C6B7A638622D7F2EE3CE4E603B8AA6BD1AE159DE3BFAA52D085668D819A7C9183F90843B703CE8A09557F917D6F358CBE16B4CBDEF89CF3364B52AEC23D1BD2BA1DCD8678DFCB6699F2E6B74B9260E74158A0A53B5CDB183FF84772C0A47CF6A137F0F207CACD5A21E7BB768355778E0EA9FA7B367EE822DB8363CD7156E384150F7F3C989012B9B23C519FB4E0BE8A282CC181A7079EBF7B1CD0DBDFB502406356879BB6C305889EA6AE83CED1E00861CF239AAE9AE4B6B2DBD628EB41F238EC73AEE19B9F69B51D2E27CC991E484C3B12446E4A4AD107EDFF33766F8E49FDF92FBFE321EC8D27CF313459B641F9423FD376A814717FABE51D280C0D8D68AC7F193499B3023D8676ADA6250D716D39A681EA3677D992FDA0992F8BF95E169427B5E38C7E1AB5F5C4D966621E3A87714DEE1BEAA71785B40AFB6A3689193E72553944A0387C096631C0EC484325AEFBC415D01D4D2680667AFEA2837E4B59332A5DCA06F7DC765E223D5FA7FB0F0289A8355866E7AEE6A2453DEDC2EDD17C88594461C42EE9AEF66FEB824DA77797003AD9F2D6FB927673CA72949B28326E43A74442BA17AB8E24476418708727C262866606DDEFC208D2444655C6F6454602C1886729E1934C4D65F1B7BB4F8E0267325D33C71D3FD38956B5D8D2C3EF43652B94E81538106204F8B08A3C0FA008FEF5A30DC715132EDE732BE065319CE3088C0AFEF000118250E1F1B757CD804BA3F91E3AB9D549ABD347F821AB26E0A887DC1ECAC3BEFDAC730DDE827F5BF06219FEE54C00B83059CB730E4C8FED28D8C40203A5E6FF11232E5280649F6E307D23E0204AE6B26C9256A18659280A0850AB584D7970BF3F248BBE9FB4485CE7DD88BD91DACCB9FE9087D6DC6 +sk = 44E7AFAA01466EF01BA7D58F8585FB0D552538947C39254F8BEC4203490AFEDBA8548E0A6D7B43E492D3E0B067976CA78819F090CDD220E4BD636D393D815D7D33407874401229B96546DFB1D78CCB10815258E7D30E3DC28FDA40412F9779B5145CDBA794AFF31C9CD012286152A241A6EFBC0C4AB14CFB6D4C7C17B04A6BE665067888843503205027304563626023644828615818733866374108827582477870341558607303832870623460744057543070863784102455566837023684553837234487836411100514364663583674753322153442500227153501747524466424862077474415873304813214433581656341436288473430425205720360354842865635272734157830887242722660537645560437218530242578876682167311478804831031252327026171486605052632487087887171574572303352775055128038805843576616225818051010170870721067410352351731678028787707521575823246423760742661385725447580340411163248662262734177123147047023850571058451214430583144571623356203830862877720803204724810212485744863186870206753885122405801168888175476066838130331023838188702887561537867646062804267118542215187378786604057471184706015180506866115562117513132811110770444666210606583527415633351644077216337628608670201206215034718147704118064285746042763156523845516511450274382211832366616387283308250447254167807260042865138875218812360668228647533408246032341733087661470346654580802517232071535182065110760374234526676147121314244206162023455017684636361213558281118483151045432262873434313465213625583526500017147253285121786482852136052144068517670807353883373263334344340273867806851322058670211774232880354230732473443507551420827347736651540736365371814304017161464165410826357241600722578081603375824121715444073553736781446807305623862007406323340736504516358221178352876218864612558080057726060544456436625556404405434002636548150585754034115110352636881517672727085327365864170447017305304470056351710542555008225133125552143080061434566687550256488700064460677587166513748514482530878152208056782330301834312662655274225446826885220556434657541820534646738421286666401704083846328231613652546604205672805872152470153388643665677487626438138836118642441027651217783055310566887732270171811522037784825725847321576704560248708175665000377580403257885612776883485368507103856082718727486486663774183154175308428655001585587821368320056603678363867241071122286638116842601140063366621833182446887572108172886101457344257202533625383151772470277277751766634011025454310673255014713126840145823313847255240308556534081831602115483788575517852270827317205256862016434674502163473488207355863610753321482648238775425202241804168777071878783818372770487024463053380608344236503031375845410103573862307688785477160666022727667417072017048436775078004356642540433764445386382160770627506565360412625764177636707037834275547234622530247787610522010248445444014387707050544076111764520247032467208371834535672025318435234830154666217867036238248110047081444458473845052283886686285774177643388130664337882026271734030084240830778804458710423037175070047541267002642235080362665373127108845310307706422751070703624023612265461187386046053212673648580646084530348567531460140240386408723384367771310483378265380551430108842E2DB3CFB0001A6BAD32A7C2CBDAAF019AEBABC91A139910719C036493B5CC9F545FF89548976264165F04C5EB59F619D8EC3BA7CDA12D506A9EABDCF956B896B452ECA96664180DEE6783714B125B7B96F9B9558F6CDCE6E419A3002FA2804B618EBCBF4F30692D9813A6BC2EDEA0EDB02573D996B4E6F039413958A5767EF42C33FC365409ADBA4135DE3A59147F067D1E606E186B489EDFE18313F4A7C2D2A191E46BEEA048D482BE3EA32FAFA56B060B1733D52E43FD6523A6C20BBDCCB425E244E373EBB0F6B3B1D135EF2387C0AB6E6B9135817841100BB8727AB293CE53E92DEF1C8C23DE787C4E8A79B4395148F7EE752CEF759986E62BCD9F30004926C16AB607A87B0353CF32AFB07A0A379E3EF197B03DDCA73D6BD2170F894634E8F5478D08209B0C6D11A156A8C21239F81BDDF350DE824ACA6FB06483A4A2DF08836CA623F03CDE6A2292FEE40E766F697747FD69AAAEACA16E46934E7A7D6C9C342577C23BE5E85A118B3906D75714118756BCF3C3625E903C4A58C6EF2CA3D419A16A6D1A9A7017655D4AB716385038652CE9B350351EB643122567F8AB5171E02E6F4DD06B1582CF0425A96C4516661B252C3DA518211BBA1F78BFAC3FBFAB2BE660DEE4878F96AED18B152D9DE6AE0BAA20E33AD926C8B2BC8C27C8954AA0E1C52952F4DA72279C8E45BD0327C9317F9824449DA081628D95568CAFFD6AB74793E11F3BB2B244656CF85CA39ED1E9421B41BAC495DA9C84534B6626446C780B90A776154E91928AA139542BB29EC37609DA31EB487961FD0B7FF62DE4CD45DE5ACCDAF823319A00DB1413F50A60A47F8EA9391D0BF61FDBAC7CC70FB26A15C698B589B4A4547B0BE9F7BDD2DDA417F746C117370BD8D4F8BB894C4A77A0113B611C8C689F72DC5CCA219C89D5B0ED1669D6A4349928A0912E61AA19988DF70E8EEFF68782E5955B8FB1A994926A2665DED362FA97D2F3F97664853ED9A0D44D171FF3AD2A95B711009A3A26BB4F11E5A2F217401AB23F8108148B300548AE3C31942EB1E92A7DA8506F6D4632622063DDCB719917DAE63EE8E27565B123940B2A91AB9516EA99C592F9C96A3FFBBAF5AE55E213A4E8AF9D50886C4DB4F40DBB8B2486F137790030C37AE2081D2C07AADFF44929B09BB41D7C309654F94713328E8D62616E7ED43CAA61891F6DC827F9F9D5D102F52CC8E2E3D73A6A6634F6EFD2AF45EAA1F46D1A36F20AAB1F2F23927AEC6BC9A56ABD5D64172908652F642041FA0AD1BD16FE0BC4CA8608FA277F23D19727873A9BB4EE38AE539CBF2C0CA75FAF82D045EDC62913E56080AF3F7CCC865D07498E3F77E1A7ECAC68DD3FF982CA114F32E426FB02F14070A6719D936ADFF3D16047DD9BF9DFB382206B5B43442D79E4A0EC6F1C5279E0D20186A723022CBB2A3DD5BF46EBEAA71B059C1D1818C26355F995BB5971B7B47531759E196C9E8B58EF7B4A21301B98984E326786B772B47CCC57069BE1F7F7DBA1C4317EFF8A7DF5ABDE7592032413E07FA4C33326E20C89235BC23BC4047C2689428B9F55CC7F95C7A3FF5EA2E851B49AFB347CB7770D6AAB2DD390DC02162DA01AF80915CB6A60226DF7B1C034FDBC74DB24E3664C604713FE96C821ECFFC345D29A3ECA54F1C04E058AA15903E1A4154CDA91DE09C1D39284172CBE63769FF27C164FD2AC4E00E35506602E98CA8C38223561B8F986101744D754863CF5E2CE8D9B61A75165FB8BD447932287AECB14B86425926212EF976BB741B7CDA999230D86153D2128AFA5139EFFDB48BC4D30901478753E8AF95F673A6758E24BA2775F277B4D5DE9675AF507D821904DFC774E34A79CE40D39E151581DFDADBBC92BBF560023024335A102E1A4E6B71D966EAA21B0D20E9553BB2B8C04BFD8DD282671C8904EAF5AC350EDA23357A26915FF45CF2EFE09BF875E40A780D1478ADFC415EAEE084C4EEE175D40B34D33460C768EB945333BE98B921121667821B23845C876910BEDA99F4BBD95CE231116087CBD91BE5527250C901560CB1F3D7DB0807ECFBCBD6E58CFE78EC3BBD4E1CC5682102C3DDCF0F74252184385B52E37517E966544B9A47A6DD6AB9AEF54A9A484D95C5335ED9C1C1998BBC918BA790D25919597B582A554E169A46AFC8E50D12F1CF536C9DA62C2F19A4A69858C04D98A7DBCEFAEF087EC5AA37445C88EDA36B26D6E754901F6E7406D250B823D35E3D592234422A17DBBD55B0EB0C3FEAFDC30E74FB524EFAE124D085047199C7BC25B62A75A5BD5737346B4FE6E871D8E6C960B2C8931318D6FFF5C9F170207FC07F9825B3436855DFC6D4D79DE89A2FFFF3C91F7E4542C16D038BF93994896142892E441F4F0538C2EF21640213393DB3218C28211445E0E24AAA6F15258AE5187CBF79B99821BB547D139BFFD60FD87EC9B6232137386961451082F67266283D95555FE65727B7F2624EC3F67175A7D84E243F426B51E22777BA93B0640C2BC927D368DB11A803C5911FD38A86D29D49233FFA7FE97A99122A4E8202DCCC9FD5BDE5238681AB45963A422488C0D0FA24BA88FF37FB23E549E20A0DBBA44C1D5E875043C81C6BE2137412B327CD3EA178A1AC8D6165F780ABDC8A205963ACBDB9C12888C46D66B79CD37795EF66EFE97B481D814A560131B00A97D3B7BEF2ABB942C1DDCEFD93BA4C8494B4C6AA77A83E47EB49D5F899C0BE29934D169C83DC8450606C9D0C5B54347F34B8A9FE28FE63A309D2B32A3E08C33AB12E826F0CE810BB691D6D5091352775CB1832FFA69630161FD43DEE45EA23BF6A9437BD4B9503139A1176EA7CFCCB522D840B3A9138A863477C15992148AABFCFA136C7165CBD444FF3022107D781E0BDF5F5A307679DEE2D1631F2799A593CD080699AD96DCB729ED85E00DE12DA8CEA8BDD02F12794B54447B4A5CDD5C082F6DAF7698FFC7CEC24B60D7711AC8E2986348FBF2BE5049F8CFF1C92F6FAEB5E7ED713A3238A38837CD7398F6658275955DFF618346448E5397272B9794F1594FAC0A79E2653AB08F0C64EFF6C310041CDC29C70B7427DF6BFB19760FF1F8385097A4559F7D1736F89377B0F2F536EAC74D3010D981EEEAECC829949C6428099F772B1909F01DB676B96C628399C57A8C245A5AA78BB9EBA1994199933A0A4B8E8449D21C67F253751A625E5E08CB05A5D249F43D3AB179AB4C7E8CB54A36BBB81592B35DBC6EA5891DF5D1F0C000F8EFAB44B69DDDB7F7B8C88CC722A8D2369D8885438E1647FD0F904E9A29E6A285051402EDA7C9AB03AB596919EBA5DD04CC89EFE87A09E4590A93181B8E4A77E346564FECCEA864E32ADAB40C03A41FF86C489FEC1300BBE62CB39343C1BC7577471775C9C8A0021DD4BBDED09710C2DF109B036B79AC4DF3175616069B88B591E88B1DCD7886A9670C785ABD2E89D37491071B71B7A00A238E1AA4B43C2398FFF5CB39F59D9586FB4B558D69E6A373236750493889757FBDDC0ADABB6594B78E8513FE3D7EE3D34DE60EA8D46 +smlen = 5256 +sm = 760B3E233D15B82B2B2B48A242F251AA6369553F730F8861A6C7D609B163D754561BC9D0DA847C389E4414F5B4D4BC5AD9B5E0B6DFDB47F8A8270DC471FDB1F87FDE4F9E4143A5B33C20BD24069C2A68BC2E3F281CB3810DF7375D7C394A00B33106FB761223F9BE3A7CD091A121E4FAD1D54DC4970DD5A50913B9268715933BBC02DF8FB7F32796D58DADCAD060F982C6D311E764389942B65D69F3BB9B3D399D7CD868B54AA287C3512AEBFECEB650B02147C814BAA6EBA85914FD8D26EBB75E96A5F2F9E71ECE37D3772DC8FF8E8037E573041A598429A108913DB3A427B478B575F0856BBDFDD8A10893B9DCE84E3C9775B74E56CBC8D2C650CB6B2696964EC8299AF39254CC735DCA29E0B6EFC61F7D6CEB2049EA11BDDA38CEBCAC812404DAF984A7ACE99F301004E893B412D372F0B44F16C15DDB863CEC5A94FC015CF3DEFA276CA7056E837771F9B66E4D30A85F011CF9C704275E790F72520CCF6737E9313F05C1772428591DC2A5EE27E69E2224E3C12107E043934A3963DF9A14F507F24554A91B617E64BCE9C311490887EE07ADA4515257C3EF3D6121990936F451FA32D842B1D02E6E54223377AAF1BDFEA5812A24AE549FC8C88E60E4D771B4C7615231B7C75B61297C3C7D45CD66B6F98158B467A9FFFE1FF7770F624803C2FDC3188F6466E966C16D1B3B8D4D7AB3A9F0216B1B04B35D006C4B706C2B51C3C4811E1D578859DF4D0B7D59C6C42F70FBFD95F7C57F4A8F169264BEEC5EAEBFBEFBFB4CCDA69C99DE3C28044C9373F54AFA4D4D7679B45ED3E280380245F46DC5650B5E3D9114F484333689DA179BB59210BB7AC23CD1618C2000F0C650C434E04B528078A1600B56A07D277954CD15793F5FBA679A974EAA63C86B1805B5589FFE11CB86614A7054394232954B2DC7F928E66D012256F9B701D8A3F6EAF8B9350A00A46F0AC71213FCB56560C2D746A63CDA5B8115D4070BE8B8BAEB7833861DF2856C89B175E43F3582F9B9D47E9173F2B8D712C65AF03CD07BF6F93808232D08B8052D4EC74DB4C1E207B92716422FB42472CA68ACEB51FAEF529378A0C0C34DA61963B1F3D0B2788F3E080D8627368816BD189600EAEF1898E05279F4DD26C5F9B14C8513420AB4A6C3AE2364F284F8D6C79B85FCF5B141B3F376B93F6FBE45EE30C29C319918AD1866448AB4A8FE966042AC1DB3C939BA92A57572068F639F76227B58AF19CF980E2CE39211412802B4A003E0C767932A39CEA12E223A2A637035553D0C16F5D8DABD0C29064C4FE332FA50D9B27A2845CFDA92E6B350EF82297EB1B057C877ECD1E8FA193175366217773F17F5EAF554E9286793FC6214880FC7A4C216F0707DB4FF114B30CD42FD32EBC9A91FFA009F8F701DF1DD8B635F3133B08CB0A373FDA195CE2AFBCEEF9FA7620F9303AA12394545DFA1F13EA6797703CF8897B0A5966F55E414F09E5DBCEFD656A67CA95ACFBE65B91D009F7D401F02E4943D8AEF14B4B3A760A8A4A65F46EDC5BA6F3E8ED6E6DFE0D73B91E3D56F3D5FA41676A864E5DE0726BF05F7E9DC190C407A716C58C8BD2422393E4F945C68436601977F72A3A45DF3974B04F3131B76275D095E8E97720130FCB8139C23CF534122375910983B56FEE15C112545616E4C4A2B2D74D23D9B5519F927B2DD05096D55204239414EB9AB73A454B160E2C0C02D85BA447CED1C7F3C530D558EFECBF9821067C3A4C757EEE772985859AEDBD48C1E0D9DDE755C03C7C78FC7473EA3E02BD99C0E4D52DD43E74313145EFF2024755B6474C25922741826D3C475467BD6779086F4AD40C7DE223CECE19FCEB47099D5BE0504D49FCCD851B7576B5487FB9DB8F05BE279B4E17ABBA1FA22D3B9C8F43E594440F5E4A745C5D19D33C1F5459355B4F74C0BEBBB2425C3B2F586BD8DA029D6AC091C66E1D94F04512EFD18738AEC7A4E861AA3DFEE0935C6CFCBA70ADAA7DD672C49BDFAC06F85B5D0720F9B4018B921A68571DEDFF1683E3410DB82EF7BE44CF268A8862BF872C1B8C63FD60BAD031EAF20A559B796257097B033FF3D6653E2D863B775412E3065D6FD5536F549618BC4149BD4190617D6EBDAF01793044612FEC331B34F6CAB2516F596080FD158092092961124D10317FFABA4B36733E56CD7E77053E30677DBF641A5DFEA9B5E07DDBBD870F384D556D0B9DB281CEEF3FC6B4F459F013AAC98B2A3C12023765A1BCD770B5C1949D74332891DC16A6DC3435C5D2342B3D0E7D817E9C18F457EF799841319F8A03A665822D7F63C475488DA1A33FD7112971D1533E5B6417D94B49ADE1E4D63D86AD4C900DAA7F81BDCF23234BAF9FC30B6B53DF1DAF65074FE3052D95C0C592B3295A9FD9C71CE1C728745BA05D733A9A4C37EDACFACE4B1F3494AF2FE752AF9D8EFB65021B434284229B06AF21A3F697EC2B366B8234F20B9D891B1D1CE2ACAB1018EE68B0848214E780FA940802A4E2DB07E650F6BBD404807B74A63626B8873ECC0BAF98701B48EB5C932DA75F7F8AD41B5C0C2A31A79731CAA24BE345DF834F307884C869112C166D5A898CE70F02A9133488919F564F133A1814C2AA6E4C13F29EF59868CA2F6E160C329E36B720D90526C2903B907EA3A95ED8BEC4DE86E5C9A017CD4BD9E371858F570550572E1F2FB3C0371B7BF19D8B4AB12C1DA5F213F4963FFEA8C4DC8BA81EE37F4CF4ED313DE87E26B0F5C9EFD3ADC23027A6FC193BE880FD344F6E9B6D05B923F187475C80B11F149DFC4E10F1D81CD5BD035461B2656E0F5761AA67211AFDD7DB633D72069AED07A529EEAD19E33F12B6E82DC8573E6B8AF9249ADDFB910862A3DADA36F9BF28F5AE8A8DDAD9BC0B97F5455AC232D9B850072096FD723250F9B5CC528CB608F4218E32DCFE3CD90CAF76C010F9DD67190F44FADC12763096B5807893B0FBEFE15BD765816E67E6B260735F620F0038D9B9E9B09CB825672C932B688F21211C45CA1A75ABF1AE6A15F27DEF5E512851F3E7DC4AF579575285151CF7A622D77B5DDB6765E7BDF5B1683C09ED85BF8054097B3C3BE9C4C5A8B21CC1852084CDBB3131ACAE2623A04F8CAA6A12D82204E308BCFB2E7BA17E19457F54960F64E26E560499FEB1D862C2CF169AC27E3434D997A25887F75E5102EC4B5BDD5A2C2E4A339830F3E7AA9CA1393F2BA5F36D67B6E6EE815EE1CE2667A2CFBB9F9CE62FA1516D4CC5E77DE2090F23EA9BC6436BB00E44AEB8F59104108241E2D845DD994B387B29E73CEC162AACB9DF8D8818178BC27ADA039326C15C4075E8CD30A5AF8251BB2FC1ECD7275B0C46BBC781FA764BEA589B95D4A531B77B082A0F0A92B7B6FF1EE8C782D7DFA5BD91928FB381EDC2D9F652F4B4DCB93C6342A5DDEEEE533281FB9EF901A4CB2B8E740154E0919F12D7A216597CF7ABAE7C7FB90FC0230DC170F682949C58EF6A4265CDDFD245BA6CC9109200A85570C97D2DBD8822F033E34EF62F630B19652DA714762B97F3A37675FD6A2D265FC10B0714C43BEBA075DD4CAA0A331ECF6BF4E319F823DAA5FB35F6BDA96A815E6CAB7C7D7C27B09E80C3A3711991F5DD793BC7AB7023881B3EC2DE99A0310C6A9B013D1FEFAFB0B656AACED2727CB1CB23D2D77B51B496274A057902255823E85437BA9D5BDECBB88FE66B87F03F57D87D3BC27FB3485482C8235C4D1A12B7F0950A2BFA7C682286C1227F3151ECDF5BA780B8779BB7A59AD21BC4EE633C4822DE6D80339B0ED374C31009B44523009D7C1A51CF70C6036D532295C51ABCFA27A3884E7AFA39D4534589385693A3887B5B2A7AA3BFE06790193758CC0A15FE55B32E298C2F85DC43E4E915893BB3558E6356EEB5CFCCE7EE3C0C1054F680B3D6452E67C65DA2475BBFD07B6DAA844ACEDFB443BCF4B9494D86606544F42DB90E06CED4D4C3E9EEB055CC14C8AF90BA93EBEF52A02C129D70FE685947AFF8CF8193D9C573781DFAE2505D71FA7020B2B84673B0A620F7B88D9792EA0BDDF6883AFE91F669F60F973044A6F58A145184959A76B79F875E07D2D49545C85F2C7A33636E01E9A21EA0D95B02A139715948FBFC58C9BBE90241D55675B9614134C59BDAF824613EA417AFB7E5C0F5FD13AFC5201D5A2B78F543A7A758581F86E889F8BB421F478BBB1D0086E12BCA96FC5816B87870F43C460F9A6FF9D20A9F8ECF7784DF74C54BAD6F7086351EC4091DE78432392894DF678ABA5D28191A14D5DFE25A99E25A600925F6218A2CD75DC33F7D00E088E21E0660C867D0EF74C4801ED994A98DBA9167F3CDF4619FD8FA1FB3DD8B73F76FB9A54EB0BAF82010556F7836FDFF9C6C69E9787D79984B7311B6E5EF63DB74071F8BD22183043389A532C909DBBF88E7BEBE3B226E84E5874DFC9838BF3DA8F3E53B5EEE2BB64E486B8D8CD3A04AB92AB55BD3556C65E7B92F769C15420E54F63E26EFD63CFF6A0747D1EAEA3B26442B7D1C126BE98E2E6B266802558BFCDCBAC4DF2B2E6B2DDE44EFEDFADFB45B9BF6D731483D2DBF0B94EE56193153EEC807239045398B9249CBC475375DEBFD40EF5325146604A73405EFFF31E874896B9A5D0138DB2C3D205335E82B1C5C70380A5A7DAE3FC65CEDDE5E91315240E1636A3BEE1F600000000000000000000000000000000000000000000040B12171A21437E0F77BD0E14D704BE86135119F39A0A65650C762852E2694AD9BF2EA45C7EE59DF915F5AAC128309847E944127294566FFB193D0361DD7111D32B06DBA60A12E053F424DDD70674E902E409BC6F5891CB9A76108322CDEC1491D3D89A74CEDD855BB0791DD6DA371A75AE979593B5159FBE9DDACF88506E6A184547E2A7395A46FBAAAF286EB7780B789FED86F257E5036A3555E777B909243695CE89957DF492C80050457AFD84AAD9F8918099AB00FD7AD3528A3D0AFE5B52300053575B839572D4D7CE43C255BBF5F16948D40BCC2E63714487AFD3638601ADF47A324482ECC99FB88574538809227F8C0A5FA7F20A0B2FEFDA38E6A665550E44B8D5630290A4815621A5DD74A2108CA946241C48661EB087240788808BF676B145442B2DE4C35E1A6B8CB1E97E54CB729202D8827A0D4994C6D7F3F406ED273B00B6590006AF069D69173B5EA8237B87705F362288AC3A50BBE7E70EB15DF6ED820D66290F57A87E51B2C5777C9C95C2A76ECF2E296A7C295BFE029BBE681B32A6D9F16D11C7CA2750E2F8877AF5DDB616D8A820DE998B0B2AF5B0C2C5641F498C99971932327EC2C73C0EF4058D9F33683F60553AD2962370AFC6725743C86E591D7D7C20944479DACA5E92D66A33CA0C862DC60DFEB5EC3C6E7DE356F6E43F06B1431358285398F8885176D60CBA218217DC7AFE4AD876D0890648052A56812BC3F8A9E6C49F9D70B0A032924B891A9410BBE2F214C842BBF0511EF9017744A0DBDBD500A4189B471930E25216D2588CF8BA39AAE7623966CC62D6C4ECC8B00B0613D912E60ADF613C8F55B778EFB93A513A776C64E8DC943E6272C0EAB4004B4B05CE9BCE9CE2F2B86FD8429E9A72CB16EC3DED285339EDFCD122150F4E7310F669B1DD4CD7E76D282D10314E8ABF61D53BF343F3EBF9968E1BE8F3785581F675BFC28C893729CF67345D0F7C11D6E7D6DA0BFF255BF706C986704A3B9C6FA0602C6DC108A59CCA70F624B08E4F5393E597459BEA4AAAA463A3B08DE147E10DE6B75A0D87BB79BA9A71E7F5999C8972BA992228B60912AA2D7A32703BA8BC02F774430A2B590911D48D3866396F1D71F19CA90EBD5277743A984E2156CB57DE88EBE91BCC09CCB5C687CBCD4E48E4EE110F4075A21F9A051700B0C2698FCD6A5A73372CA366A230A9ABD153E4DCAB7A33A8226F8458C5892098BC0A95619880156548F300C40BDEF81E8C1D8BD03031C690B7C3C000CE99675ADB4B94752EA22BC9E0278D0A53A2A19363A9388BB8D6C24A45B5DEDD8F7482E9C29603FF182F25856FBEEE2B41B88B352F99DB5F33D8EAB1A1A1FEDE60EA6CFB7478DB7540D3A286E88117503C4D0A2C13D32AFE3F1A31D1AF9EE60EAB8FE06248CFFFC7BB438B77D94B5644805CC276F19268DD1FFEFBAB3C796923288638DA1C15E014723A84F8C2DD9F55F7ADC2ADC13FA7CDC29BAF48CA438C882DA5F7CAA792B7CD984BB11EC4B681B332EDFD4AB4C132B08BFB688F81BAA3FEC5A079E2182C282A3EBE2AD5E4C59090BBB989E6A07D85D604F5FFDE0587ADD29A5175CE65D29FB9FDE3E8B49EDA1D88EE8DD64FA1498D33EBAF4A847EE9FEDD3376AF46C1552A150014C11DDFC5047929E2415D3F9D81186A685A1CAF2F004DE777760F0567E880866320A7B42E61CC994719DDC81E28525E50195FFE4E0467D9A9182B75EF57DFEE926D7744485A55E07D1BCD1C9B9B12A60460BFF016E9834848665F132E2FF87805E00154C7D9853DBCA43D005BB197EEDA3D2D9249A621EFC4177415BB103893C82EEB0AEEA056B40E98B5FE65527432FF33CE3E09FE1288A6E2641011721279253800ABC4B73F65B15B434BD34A573E77A94729A78C92F0E791570A416A0876DB39A8FDA8696FB12E7FA3BB11E7838054E4195164B9676DD03327810CCFF9586217AA3D50E7D3EBDB1AE1BF6889DF316047CBB278CE8C9741798452A38E48A7138E1FBA286B497FDB8B1E7BF6145C5F29ECF6D5430F8E550314DB3CF48F27897F312C6D9D6357A880B721E5148DA7F789238CE411F952695F4A878756BDE311BB4E62F10C2F9939B8530EF70D3FB431655AECA2AD36BB5DF0582A07F53F1DF8E0325E635D5A5E795C130106502A081F2FC52A9D97C5DAAF174F13D2DE1EA0F8860F08F4FD5B571E1AB1E84437F3C82BF19B96E46513C316BDCF994BC26FB8461F90594E08E6D4A032C1DA38481A1AD7BFB7D5270255BFF23CE035535CF478216E6D2E62E147AD93357D62636B1AE42C4E8433BB94CA91D0F8EC265F2793514543AA86B786D9760BE5C77AAD5A8449A7DBE92391EAAFC305C1267A68E6ACF0F044FC144D82C917992748B9232DEC4E33EC97534F2BF60B56EDBFF675F0343C9C78E8A8D0529A78E2EED9F998B360360352009F01905C1A4815A36B111CAD8E5B34688B99216171D4F57283CD669DC05995BB8D94ECBD3E7B662C4A603BD85251F2BA35FB6CA492C2B3E996FE66A1EB904CCD61B0900E7DEDCF136F50E4C3AD5FC312A2DE4B3E51F355D01763692C0722C700A544E681A316A1D261FAD727E557398E500F15DF33883ABE9D1BA645936891F5A91FF6C8A7B9B6FE5062718542DF4FC4BA50D7F513945482381ADC42D5A9D444CA211232615306D7241FC49F08912BACBAFBB056C018AD4D6021D99FD720ED6548A5A29DAEFDCE868D71A1BA72D9F998A3F89FCFE526493582C4C8AF5C1BE065EA29F6155428DBC955B745DF + +count = 59 +seed = 750A74866BE8DF4E60BC14BF36E6D83ABF6DCBB86792D125CF0980007C5435F40F87BA96498A88252D9C5C6710807652 +mlen = 1980 +msg = E4E3EDCD70C4BBED033F402CEEDC2C265DCA10B2DE0DB00D454C3AE1A0D00C97E1DC8C6804B1777ED21DDF5145B9F9348A931C128A8FB03827F653C37CD95859868DDE356ACE682F627FB69FCD97757BBE8BD5A260A293D2ACF0BFA2C0A3548FE25A2BA1A21F95123D592B40C20A927FDB615E69878E8D7C98D261DC01958A088599D3F9BB5E14002192FC7DE417B1074B3F7B52CD2A699091FD9DC3C5929E51CC0259D2255CAF0E444EC11257B759978BD4A7C8E2CE8473325B7498681102DE6FFE9764334D862E379D9F2EBF9B312FA75D7A50E08B94BD43EEF78722D423928FB8E26FDA85A345EEED0326A5D694E4729154A9997B269407B7D03818025EEB2BA96580626DFDB3BFBFCE100C508170D8150E4980D5D386761F4E8311339B47852ACC2A0A01DAD90D3978DE6536547D4F203CEFFAA652E4F2F28639BC3FF83C485C28EDC0BBE21D17B8ECAF3794D64C36FFE7F07E8A906CAB8E7FC9067CA4BF9B074C7FB01EF99A05D7C0F35D889A63AFE5FF18023BF77F8A3DA0C3CECEA0E538A6DAB5C54F3A0D83151595AD3EC4C45132EC2F22F652EA5DD930E692A7C0D7C23DE84314CAA7C017AD50D430FEF42DE557073DDBA6CAA4A787C92E6E28368943CAD0974EDAEB7ADDF991CCE20BF51C5A898CF0A2104ABB810BD4937D23E5D43490A3194B8A109B745E0A365EFA59199B43835682E996794F16C5CB874C88D9697B189AC54A1BA1F459623C1563CBA7689EBB32DC4FA0BF30E064D119D40C36301A653A4F959C97873003CFF7E8E030A137BAFE0A60AD08E4F692DC107E68AB40EDD0C384875B8525AA0A5EC3ACEAFE557EC76DB5283672F9751AFE1166D53542D216186A3DEF4DFA94E57BFFBEBD6F4AFEC3C0F3F40F651A1251A9AB39C262D42313E9F22879645589EA54FE894AC005115A43DD806B2C8BE6222DD9F02189D4221A9DDE99ECB8C3EF4171776268C12ADC37E4CA92EEF09D2D1803DB1FE917521662BA7EC0C07292C7E2130ECA4EEFFE53EE0CEAAAFF6F4CCFD42186611AFEE79BC651B1ADBAD08458592D69FBEEC708C7537925658BABBE7E9867915C6A728EAF41B0AF2EFFE55207C01652891C373F7A14409D05FE9E26C2E72D688047DE9A0954516B85ED6A3230B6B0EA9C5F086720C26EFBF8B7F5C5D14651D54C4EA181A707C562239CFC08B2E09A2941D04D587B90134D8F670F734578534138CD9CB7EC04437A768FE65FC5B3FBE818DB423A2208E485669082B422AB1257C2529CBF7BA4CB30FA27B7F702418C2EF9C3BF7CDE53661DF716449C6337C54542EADC5209A0E030AD6577DEEACC6BE1813DB24BEC035CEE6AEE93749D524222535A0277600F8E4F4BEB473093C5A00B6666CB319DFF131AE4F004EEB1BF71E5D274E3DFBFA246DADA9D6F548907091045FCCF79B363E695AD54C2F791861CE04874EE8C3375612DE820CEDE04E4472BC3DC19ABBB91C42A1C3D7B467837570E7D20A2CA6405DECCFF1AEC03E0558076E988619CB0CDA9CC87A12367BD486B676A4F71D40B88AB4E7FA750350DADD1A8F12B70864792D3CC1804BE8B7CB9DDA532182C32582015C1788B43054B7010229F46BD39000440E7F5D22E4D52EED85B204B344680426AEF51F0CE0551FEB9672DBF391A9AD363ED090837CAC1E721878E65AF9BA92A0EE7C7979925FBA9F4E452EB4FE3AF03B9EFF0526FF0A331AC0B8CD27A0C49E5019B7025C3C9870C900A7FB31FF834E04B87DB77C4D6DAE4C3FEE741E923704EE5F294D8F881833E9137158D1EE0FBFCB4637ACB814A2A5346607BBCD6BC916235F7875334F2B75A7EA7B8B8DDCDF46C0B8007C9B3A014EC6E634D4173CAFB1DD09CB9ED4A123151F4F2631D4BEE1520C10C15AFEB17198009C2B254C1FF0BECAFBF69BE8C7DBBFC7E8F3F1EF05FF6A7945FF79ED6C317609B9238670DEA26D56D481F87CA171CCFD726CC0728C965D9BC38D376D707E6979908B19FDF7E74ECD2D0671EC338FD54AD6CC5F789E96018521882588F888D7D715104D65954DBA8907C0B7CE3F2ACB802ED49DDF1416C29E8D685C5AD879464819E1D53FDAC741F71E31AC0C17B6C8932A4A00E7164CF8BBFEC36EBBD30392145B292D355FB304A88A638F991F6F89A398B09F1DE4F0B29866029BEE75A12D724A52736F2B9F49937F0E51B0F2E1BD2C1BC9325BBD1061E0F7685ACA02DA735D8FC39646E0B2453BB9690ED1C4853A757EA9DC2F4EB4B5ADBCFCBFB0CD2587F61A24B77CA0D6CFCFF47A98C7098B986D4FBD0E46EF0D1F9DF842F4473C43912AB49F4117C8214A42F3083936C7E8A38B294BA081296A393DCAADDCD0D340AC62511E47DA6591836553EEDB466DA6285359EE831A952E6C7AE3B943636124E43224D527B7D394511CF31C50EC1D3E7A20E49850905D504F1AAE477830E3BDA50430EBD47FDBB0BF537D8D479CB799B0429C3F6591328299A09F45CF9C6D30D5C1C9203B9521D807875D7FB2C2CFAA688414497122161B1B4F159B66C0834E111DA4F82D5252367FD2DBFDC079333FC51AB0D34ECEBBE786F984852A596BE620EC6CF84ED596425B90316A13B39E5EBFA19B319BF0FD1D6C812F29970FB1FFE948BC0D2E057B1DEA15445D71B5F728C72DD0C69E277C58F031F90932994AC5A177926DCC1C570AC1B4B099ED66ABF7DDE5A5D77D08EF1AD7C6FFE018F56EFB07C737F33038846247EEEE147E4A5995BDC3352B73F15FCE5140410AAE3F0AF1764E5AD996D01608C5E6C6C96A20274EA7781B41FC532B01B52134FEE28F501EFD9CF +pk = D9DBE0262A34FD4D29B60AB6FA6D34FDB2857D1722DD9F5657D84C7996353FB8FDF9E56BB4E837506C8E96A2121C58A5C01A0D2674D0C2C8B18132FFC0018F96576ED07D4F22C6D51A3F0ACCDE67C06C185816338E0677511D466BB928975E5FCA63821E3B1B2D9A6D0BED0974F3F56998D8EDF505B47F8A0D43AE636460AAD0358373398EFD3BB71EDC826D9DB0D7A173FD27A55401650686579D9CD84FF1218ADE921BC98F7CA3D967570EF6B2471F22AA25C0FF868C9922704EAF0D3B0CD5B75A547DC419B1E5A9B64CB1C44C7089C4A70C5346E598EFED7B614085BF4612811C4899C10C6D39F7E7B53088C29606E503FDCE908C8E5D0BBA8432D1AC945A739DC28FB0FFF14636E73190730A02F8A7C54D0C5C1405A05B6D7332647456C491DFF290C381D56016293AFA294995983ABC81F0BEFF8FC1CFECAC1D5B06EC1E469D5D1EA84ED647125570B623432BB8F205E8BA59C4C3F640DF19BD262B23F8E23380B4A738C2D4144A2BBE4A597B667BB6888F8271D43C580FD7F0147FFA93C924DB275BF8A88A232607E116F0576C380FBCF4920832ADF0843554659C424764637193CAB25B6167B7C7F42C1059BC2140DA49C279E464291FC74F480064040698A75080D82F96B5133D93EA5E776A152E91C0576B41F08AC67531198F5BE84532BE97B394E2371019ABFB63F17FAFB5BE0AEF3B78E9DDF3FDBDA06493BD8145CFB39EEE01E97B0498C7AE035AC62CCE6CC72F470E2D81D44B78B0B1297259439E4DCDC86302A199867CA8C0E6FBE481A20165158CC86712A6A84D6CC8B58CE09B87C666E0C6BBF8DADAE4A7A01041BBCE67195B086E4023F915DD52882C06B5E67975539E26B32C4EF64DDD4BF876C47FED4EED5EA4E03F908CB71552C690841BA2DD3454975FF0629117AFB77DDA4ED54CCE6D1868A2E5585FDB54C839401BF91ED08CC3DE9D49FC5010CF89923B9B2BB5E2C74B171FDA3890C8EB83B5A100CCA5D39318D4A2B83F85A077F56DCD6579DD684ED5EF28CF3F0CDE86D6984F4FFB3C228779730AC65F164C9C051A5B65CA1C2B13A2B23A00BE0E2CDEEFFA5BB055C3557CA01010F1F56D936CFC0AFDA8797FBCC57FB6345D39A41ABB33180801142FBB8C5677FE7AF50ED57D81548C1CBE9D67117E8B78CFA0C934868CFBD0CC33F96E24CA90AD8413800BD7C704FE801D8AC03076927A4318A80CF9A0FFAF05D3EDC9E6476E53788368856299C2FDFDA109A2DD16A8CFE1E766FECAA72B268F2BDEE0DF03F9C1DE88306F36C224C0A6F187E614EE7F3930E8230ADFA466E6623D936A1F9039661DB12D23D926E12ED4098A53638AC1F892CB618A67FF8539E8D8AB4B03DB1144E454975F5403EE799E038D5F4BB71DA5D5700223C11CE10E79A5181E1EC15E02DA8293BBC8109951F31682C117C7DB424CE1F82E5DE5707483E58F40DB2420F3E050D3381DE02BD35D5D773278B8DA8B27B3006B61E9AF488511A6C52F54F473646C886E8EFA72924F30C18793ECBA42913331F061129D81A662AC9311D8CF83359E6F5B96ABA21C994645C9CC3EAB220E60083B5EA2FAA47659D4F29881B441D78EF3741E101892A47E988A2F0F04A0A34DFE52E7E7A4471B2BF8B1AC311C54CC6AAB23499A3817E188BEB9B1A872A1FC7A172FF2CF0FA0797BFBBA21BBE0BFDFDA3D89F8BB155853478282324D60C13F34820FB29C72539E9D24B92A1AA467684BB72D02E4CC2A40EE351E3DD3D6099B92B9A53051C23D2DDF97CCB30B6DC9FF4974EC75EDBCC016F689EBCBECA2906052A634324E2EC0D7F2517AB97C66852C04C65BF6CC4F864DC9DBC4BAF5A061D0A454655148E5A9F3C4406F0C71716C4448B19FCB510C3D55F1AD031819E7CDA62373CD279D31ABEEE9CD91785F34A0483837D562FDC9B0E290CC05C0EE2C32CCD0A094052214BD7F056C2A39736F56D2F22A776C0A4B813467318A6CF6C76D8E82AC224570BCFC02BB315B8D1B803C00EFD29062AC37F7FC5363EAE1CF4022572F74EC66B1253ABDAB776BB8C94531D0EC618B4085F28697CD292F15E7E33D5812C137137027FE85A9FA0DFF1A4998A30ACFDE4FFC67F79E278F8B1D87D2FE8CA47CFF263E821A99D68B1EFB87C9D8F862BE8EDF55DFA043F3239E1282AAAC279576B8A9F387C0C97D758FE52436470495A677DE5104E7B0BC0A3EFBACE5EF4BAFA2488857F9E1A63086C2D0A0754B7E6B2FC1D518322DF5B68C6B626EA434369B2F799F2BCFC01DC0655AA1877600A81E988CE706333B8A86191953A26B523CEEE020E2853ABE35FFC92FBCF43B934B3BCD84BC7B1322CBDD0961B5F003324DCA8354284540D07935A4118D1B693D9E7697C81AE4FCAAB7FC90BFCFAF46492BC5ED361080104D9A3B999BD71FEF80F0E79E0ADF80AA3E30226192A64B96E6C6197F1B57F7CC78CEB5FC0D3640D09BA84C3659514CBD6DDDE2525C7F1F105B9DC04399902FFAC2443B5B8D980E60EDB4E2C7A1333FC29EF8A6DEE5035847F2364252AD3237E19CD50A97012AF7DEC404DDC9734E780AA400EB98DF244239D3F740AE3F750CD672B14054DB0F4E211C1460327F3BFB52D8D51287DE7B4B8BAA06B1C1B335A52B612401DFAEA02CBF976A679F622808ABA9DF4259B3CFEAD9EDECC64B8EA3A936DB73D191F303A8939FA11A612383F40A8429E60CF969C5BC694EB6F8B8BDFD2CCE7EB978DDD2825A7ABC0E67C592DCB3C8AF1883505A73BFA71BEBC1E4426B3663 +sk = D9DBE0262A34FD4D29B60AB6FA6D34FDB2857D1722DD9F5657D84C7996353FB842C3BD42827302886CC72CDEAB868DA93E8252E7201F16869ECAE6A81075C1586003501E84A2D54A1297E364617AA9585764E5640C0EDE486FF6459FCD5A1F18741F66342C57FAA847B1B1EB456D9A213D5A5A8492F829DF72731FB543E1C83354252544245210071168418544243754605724756720313766335561377485680816285822672251366274602670780447718117532365026414175046636855654662816344621700883185807705740580200655656408622571617645330824462106842460647210482334306883200672671506406337055438026177174517054784651788205257686181568556204472533134864435737846513454071828338371687220636271410784551501228551560014038510522466340227168348680240584514165266085568734786118377186322223836633585388331461720624835157088855716287608821606070875868020567838018045465470035423487078380305461663252065170315834775222214146284181811256651857528361086055202488330700313632637665146105224402351086577683481167080867105877870711444766245515287772187478278477525457554271274748048604270178648462432284084460511373230537865212878303504257365530656110016672618526544250786361267310331574651811287186315432406730065502857658127702868380032244455768141600786277558773826568641146100571660478316320202588521251352834118322426423675568706605418403765838065501223450537471386208707424757838746672417872125217785121155401067741001065555733351070016071714578448102813263284082321306444010321711827008548804241868243372305225401310180377363756482550520683520665217081218030320477506360470415238262074248557141613563510786137075502051158806385815400286536547725866441551558805355404413281258451875714216747387037562112231555350714741108033436535010651481200634501023117821561877617362541677501222313107203840587106777283486605172113361020355363540387087718233134743884527807608841526463161641083511088115830872610365440174886271004351468563051356184377777631817057010865620800408505243014020121184510821405122841646122121010640721856353418755376685515254247445663401802837533372611876451250866143624234027636513364730137540512406254464304245462717880670436675765230357461324837360580557278866324477238804181306266436832377548584688311526421321574620636646420185201510883483337344258258152071514614612641637084203431658812112340762223451401488564777270352342151217064234648527617545025218706150878868348511387558173443680616725471441060684613817767624148460206424885070351235152644437427471632084071268714761304831232456015012238770435036814754118154305754143373235687514872518611461102137755761305374114838057083842247622716042037565586682405347388837436542241811186024458135410782677462643781435884076261213255136503763257175864475431834382574301687747366232728103558766625502314801223441631727716724875413075815223434466616166472804330886647881642543440588602651705185362426851280617642585420572844416800520712265586142824104433216287778547234820808175558867735272288744020081248021848427833372524034452438710630222117555053566344666755135168206025617331283466607186206077008865254722182031378564117854670115467023702515774233046214426616243066741181023614016777685655804627155253587E660C39329600E8941420381AB990262F276931F969843DB9CEE0BDC569EB3D6B12D5F51F7A4C89B5D4A9BBB6D10F860AD854D186A99A7BC9602ECABA1288ECA5992E910800707B0F1FCBBA9219F74A603C7640891ADAD1969B2E2277B18ED0249748EEDD48BADCDBB39DCDA447888FE388423C942A22B523A2D0FBCC2ED5A74E9BA5BF3EF6F67E8C416292F40E68C64968B9770D01C1B9BB37BCAE2D385EB2ADCBC701B26D3DFB4616AA3BD74E31AC2E23375864DC748A58D5C25434EBC3A5EE976B59F9FD4659EE1CF3C3ABA896AF8B9F8882EE5AAF637A1A9F10890E884069207984BCA1C1AF98D61DD13D5D6A562B1A9A22E5A1DB5D344B00A2DC7D915CA6F64B56C8DFDAC61F48CDBE6DF79CBFF08FD9D1261C185C2B57A7476D469D27DF673A74C785700E9F0DF5C39FB5B1BBF7F8A524833CBB07698B4792618EAE9EE34777C86295E4F7DB82F8025B404C8039066EFE0361A85FB5AD35BFFF3F951024A936B1051141CED8D4B387789A48F8CAD1F87A4D050E2C88556275CE103AABB80848477DD6FC91BE66BC749187759776086D760F531B67964F12CAC140BDD392B39902F37FC66970120E5037899C870782B1F3BC59A4AAF4328B81BBE1CEBC80A5BBBB240096415CAEF42AA420EE3C627B67F4716E1C2656D81B8334600BF56930156497422DFCFC904FF6DDC26DEACA42F0106B5DD48313063343516E7EA00B11BDD81DF519ECEDBBBAA686280F5282D37FF10F9D26CC873A209FF776CDBBB0406667D5B9ADA62C562818B14D72CF11E1821DB56020C9C07A5CE9F2E738A64CCCBF3AC867B1EF7212CDDC49BFF2A9442C34D7D954142FA9AC3AD0D552F6598D8B3AFE9DFB254FA567D8611DD88B70DC6AB0081BA3ACF6FB3FE27D53C165F8F61B713EA6E68FF8C48F5E8CAA473AE328BA2E67A39437FE6F4FAFF8029FF88D5345DBBBCB9584E5C47CBB28C478F71953FA2274B274AC688F8CA8562C8A34F128A984AA057FDC9AA8E0F50637CDC21062C457D11C41C74D73A11A6DCFB8A0FD84F35450643FD8A19C069F0195DBC9B68E54E95E2CCD1D5A94A9ABC442EC2C4B99E12F0441A0609284538937FF091785C210E0A2293C34CAF4F0CD1FCF6EDEB6F468B3538958F8787BF8D41C78E8C675FE7526381E73D22BC4D54930850B3EEC642F1CFE4AFE6F67D3361AABEF1CD91DCFC7FBC5EBFAA057018395A153196D37A2AF5A70AEA6173BEEE61B0E38FD1253E58A14B4A2055F6299E52A3CBD246EC4902C85B434801C7CCE5EFC0AB23108C2DB777789390814060884A8EA5D92752EE0853E5D32431480D1D79F60FD6E0786FC8E878AF7A6578C4362AEFB8408D1EFFEC078AC64547E5DF44EC1E82E0F0CA95352B27A771630672D4E2019DDE0F072D26278332BB128CBA05C3A5C37C5378540D6ADDD5921F60F86187D21E4AC4B027956549F1E5697BDD570BBD7625463F68067F7B9E67714612BC592693BA0DF21D51C66B22E331CBB0FC99AB2536F97F197E08DBBF67F9A92EFF1053CB135EADB30C62D0A95781E8F21753F3219327DC374417261F4F4FCF1D8333B230FF724DA6DE9F3F4C20C5E55D920B35C80945CBCE57A92DF20102C80BB154AC1A979E6491D5D444F97EB85C81DD151F65A97B789F2D268B0CED8A0FEAF173104479BC04CC6F10D2FB619C132D8D6934CAC4B642F9240D6F803B96C1331CC9F5BA242D0E621332E87C4AE480D8D6850EDD64AB17E0B420A4270DA903413818F931BD6AD2B06F4F9F78C664382E884DEB7FD6FD1F2DCE04E4E23D3452D3C87994890668B011BB2F2E293A648AAF3714F8B56EAEA439F43D43DEF9D21B89B723571A37B6303CE51FF434AC12DFBFC79FECD0A2A5E01DB15C5B99FF3F70CF5BF956886D27FA670A78AFA6E7D80AFD219FC219E06398795EDD2F89CC9B063AD48A76981AAC3B6892867421777BF9BFFF3ABEE10FB50F19F2D6673082B5637C693514769FB95E40BE7F89EC6F939CE8C9187B5018CAE3FD48DAB42C3F0615FFCE7F102F01CCA18F2808FAA940D66BE4424D851FF91E7BAAB19A86C12B7D13E9CAF6B3C93D854E64759B81A806524D4710D8790E18025CD036C56ADDBF5D1BB3B8654DC70B13BCDCDB85EF2F17A4F4185DE3FDDB255F93729ED82FBDFAC898CAEC3F1B690912206A55BF3B1EF34EBD0650C7B6578E555203573A544613C880CD63920D2E2952DE932BE64A22CFF391D006F99F5C66FC2249D2F26A68F08058478CB8D5715E045C6EE40BA83AFFB3BA4888B6B20C9053B944B45CC66982BD00B9CE4620F815430ED487ACC8186D57FC5102B17C671AD799878EA6F83FDC121504EA814205EC5499DD113E85795FA8DF5011F3BBFCCCD856ABDDFA38819CE04603D177305EC83D0A3E20C1C4262C8E7AB575FC110DA6A3923257E3347CDE2C85DB5E8B80B9CA9DA5A602952121387962604ECA36556F2AAEA0F4F7E94F6F824A4942955E13A98AF8A6B81FDA7A46B6C2B4335529ACC659CA255086700EDD66D6B76F4C3791FD58E71B2A51C3AD1D8106C6868F207DE931420F1B4FFE7A34482D5AC3519FEAFA215C40E955F2E0333A8BCC739BCD078536B004A295ADCCC89865957164FAD4D74B952153B41B8CE5BF49A8BD43FA5EB1DBB2EDA0C3D8700081857E3DDC6845AED76112295095CD5B3442AF460428DECA47554BDB4607559BEA3738AD4A62ECBAC12E225BA73918A6381D1C4A54F3EF46661027E81D6EF035044D5A109D2D7B601EEA4F1F33E32BF025A7C7DA941F24F4D1B803DD4A92129719047106352577FA02B055B268B6E20C3FC039877B5277372B143A4C80F767740133EFA16DA4321DDBB999123CBA0D12C6F60EFF85741AB1C1DDF586C4380903458961E54F37942869316533B675A8CF7D4D15FC828CE1246C001A7D3CE8597365897A3F7027CBE7425CFE21EEDA56431DE2A7BAE97A84458B2E56DAEB1144394A131C80DA1E70F99816879C6F26394DA442BCDF5BB6B2A87F8EFF78668E9E06160DA61D7073495AF9C0E470DEE83AD092A4E90FECBD9316DA77AF1B669AF3C0FC139DC7611639312847799B424C7C06CF4F584ED6799D4D39CD9FFFE7C7E8268618F5798A062D95BBEDBBDAFA7FB05777DFFB3DE4E92B8857B229A0376B3E2FFED08332E6314A7CA7DDD868A62389545AAF5C50430B89E6438F310D4BAAA6711E917C3ABB2380E2D26391B97B2183C04B0FB197654A8EA1803969254B0B5C348F8EA39FD9A9BB4035C2CF0DE29348635AABDD8A7D788D3263994565CAF61C184DE00E28A841403B36ECC12EE56BD77E29C0EAEA1422CF000B4E682225796299F187B68FF06686A5175C4B6DC650DDC86A6B64E2A11969EEB90920CC150E1294F60D42E81D8C090D2DB97291845352EFB89D5133D6629771BDF19F42ECBEB41E67B9941AEF65BA0AA021C3F7CC60B345ED5FF023A5B014DB8815C52610BD2F29281B0A1BE1A81302A0D24F4BA026D0AA758C461BC97033C49F19D0F18532C1B4EC6E6200FE9D42DAC31453 +smlen = 5289 +sm = B13F797E521DE43DDBC3BB9AA5694EE0D525A24948B7777496D036E5979D31C9E775B138E9362D7BBCAC1AEBFBF12E3E8B4610204BE8D92035C522AB0E9C276355BE166911EDAD535F4FA634332155E75F076ADBEB206A1A4748EB1ED0F2784F08AFFB5AE2183E9BFC00A97269184171CFA2ED91C568EF44DD0FC8302A6081487AEB82A1787684ED683FEAE6025C429A60B7A2617C912462121E1D915A7321C5D232B9D51C087DD9509AC0AB4F6C7C4240CD77D87E7077599B8B9EE920118BD108D4C2A162BD35C1A945361EB4AD365053EFE68B2C276D9A3E4B36A447394F337AB310AF9F80AEC52CEC1B5EEA19FC806D2A292F3F30600AF9228BF7ADEBB0BA8F7DBA61605CBE72C477DA7D287F97024864B81DC3C7E90E0E20E1A4885B7486CC592859E575ADE461668541DD39D48669923C3C0B8DAE95D8928413300642A079E3B3B22962F1C291507EF39A6F15CDBE6B2AE765EFC6C8DAE663EA074DBE61C1A04F8597AFA65EC93A8B7C44B47FE661F37F4A7FB5AEEBBED6D6C34716274639C310DDE6A8D0C2C9E706275F6C805FC4022C167D809D1F60989C1C6D5EA2C8FA80199DE1D78C0BFEE67E5E43B39F047D83CEDF7DAC34484498E3AD382BFA4B4C5E51C0585BDB52EA3881D7FFFCA3B8A48905601BF17E822CE60F4C7FC266BB84E8ED16F2D84B131C8222A541A62DD3C9DFA2BDF6D97728A69CA099A0F9114CBA8C65829F03CDBCA387576B2C14995460AE12F971E6EA4CCF0A6035474677BC619AF04FF8193FB2E3BDC933771A04BDC3DFA818B32CF20916692CA8AF8D5902DAC17B220DCAF60145480A6C4468B474E421B7423998F4EC282D12BCF90A3966E610330B766C8F3C650C1373E5D3AFD30F2AF39D486AB8572002D1A2981BAC33F289EFC3030EE7D5EFECF74497E4655349AB21AA4A9CE7358EF5FAD022E12F20CA7435DD92C93F91F989657BEDD6134B62D7E13C136044FB5A0957BE26DDFDC013CC62B7F3FBDB4A2CCF2E36E169B3CE9FA154E8FB2A2DCE6C5D540710E207F14883563195718C631A7707D5119E149E632D5326DE183834EC095C6EE11286CE555DA6EFD57A8D7B0D9057704340CAD0AEB5CE587F7947DDAD253C70DE2FF4C47A71C969BBAB63EB2206F9AF0DBACF07C9C0E1DF6309F5EEC2CEF7E2264B40EC089FB9E887F45E32BFAECF053B05E0E2B4D0F03F34B540E00E5C8AC3E364D581CFE8D7903CB613434B28A01535FD2D58AEDE524AED62DF178202AF7A9F3C58DEEA5D33F80C70E17CD5C70BDBF8BB36E14835388E6FE021F5741EFC4AD5F8FF52001788CC18E307CB9296B1CC20FC7902EE007ADCD62781380AB7C10A09A732497600D1BD19238F107307E2895566968E05215EB8913CA52C079F725BA24C4696A9AD5D62A729F2CFA358DE504B8033AF684872EFD492D7724371F847CCFC4608E8592F83F1362CD00EE9DE8EA65EEA02D2514F3FB7F7E3F237AD985F2870CBFCA59A867608173DCCE51087586C49016C10F71C6B2EF3A0598E052B2AFE729D3465BB6AC2677273C4582C6941FE9C9306A478521C4167B53D28CAD30DD118ABB3E892F1DA7158E6110494871DDD2F35ECBC7ACD2A92F403A172DEF15717C292430982891F6257FFCBC3C2E390A776DD21E9982ACC2B49D28C1993D3422F5F0250CF94BC4250A5CF9C2BC1CD39FB55ED8291431CD4DCB9A2028D0839FDF449EEC096F74C97BE2881A2BFCB4A74F94FF587C6ACC6FF9BF0ACA413F04242974172BC34DAD5B374FC97E2C1800D2B84D89525F2111143A76A3B53026F5ABEC0AC2444481FBF06742E982E0BD4AB6CE926019393D63F0C9696BBE52B823C82C31FB2A251231E5EABA233148E985F96FD09D77A59A78A700489CAE4E09339637A00533684CD2E1C3D6199C108209342E1BFFA2575D8870C51D6A9FB80C0DA545C247FFDC3D5A5E002BC325F24B043DAC9B00589096B1967B495764BCA6740BA82C229EC1C065F2B9BF17237D05D87F8C29236547D2811637F93F5F818E61FD4D10AAA827104D820676BA25CBF992608EE734A9018886C757419A7C12AA7A191C99DDAA9187B28029A95389B87A0B34EEC0BEBBA830559EEBF97E14AF4276C9D7FC8CCF52CA665ECE10874BE3FCD023D922E55F1F1565BDD6537C98CBBFCE0536C26DE76E81FB52197B3132C348B182141509210CFB3CA3343C5EA2D965AD433D2808C71CA55CFAC7E0BEA8D11D748E8A93F693D0248D1CB129437DC91A28441FEDCB463465CC0EF38259EDDD8117FDC0F8C0F1319CFC0FA66808D1E942F46D0CD1F97542C80FD31D55DDF4077E38AC4C3E079647EDB1389457EE839CF1ED87159D7F336B28890C210154F4E67BB2241FEF74551D6EA41113648B385418712C3B1886F0F616BEC5B4DA600BF72D4464A66B31A234B1C476870E1F29B4A43E52C95BDD0B44F1BB4E1631D9CB018EECCC656541475D55935F78D591503333A8A27BB5D76ECD78966C2930EE28BBBDC94A174FC13C1A800B6BE2797467D1A03E2DF7AE0EB35323EA1522FA38543E4E3915270A62099A98D7C7813D9C606D15DD8700EC37D3460990D00B7A04B6EFBFE4DB63C041F5360645C464751855287ED94C7D2FC2B276F6D1DDA99218F3E50A31A0F32ED3C8CD3B97F3BC3D66A735698D841066B51C228F33A6C5FF9F9501341BDF029E07E3D2DBCF7AEBE10F5336EB7777E45C0859D160643B39137F212DD9755DE3633DD0344489172401AC3CF82529EA9AAD7FED7F224B16FEC5B6A90F7194149180151EFA25106C14DB6896E4B3CF694DE5606F2939811CC69CC0C9BEF003B805138A46496DEA0FD40239375C2340A49A8DF9849DFCAC16D4D654345A5BEB520165ED33BE0CE35D88ABCF016057FC6E8ECBB79EF712D03553A39B6AA7F6A3C7706E7F2DFA5DE479725AB797555F2993F963A6DBB1F145244367D5C73C89AC17D24F7D03BEFD9FA33134C7B5FB8D98F17D5E3F3E1F4220B9BD18E5A3E25EBB5A1CA0DCC55B2E0EAAA5A739EC48A4791AB485FD0F24BFA2266F8088560FD30D8764428E732572C19F062F05F698AE0CC1609B020E4815970F026BF4756CD68A8BAAAD845F0C0CB409387067228A07025FA6625359776B02214C275E742378E9AA9AFC3EAAFBA15F16524536DDBDAB6AA4DB38A226EF5B8F8B69DCDD3BB093B8D6EC1AE9EE5B3D1C97652E485DAA406478DF23321381D72DBDD2D0C03E337EFA707AD9691F0DB0F6EDB43E2F920510D0AB3475011ECF6ED9F116490443B91972AA04EC49F628196A4C6CA3CFDB18CD32E3C904A25D56B22B94BBCCF5364C6FDE0D8D03D5F78420EA3E03BC4F30A8DF3E311AAA8F2014DC3B1A1D176857D077A8C72F6F96B53805325F525D71D2AF7D9379E2BD6EAFBE835456D1FEE0CD841ED68D551EBF7C9B9F8FC94A7B619E87E1E231528962094C9D833908927A57432A7FB44F4089E10F61479ACFB06CD81A4C0B13A65F9CF2E620CB969BA487BAEA01653933699BB217B54A9C59B5A3AE78BBCA3ED75B8E0ECD880A9F172021B85B3C36129AD4892805E6AEC92B7CB07566987C6A8C40AA1F9C5155265C70F5D46925D80C605312F10B8191AB77876AE9E02CC0E7284712FF5482217D85985CFAD922FE365CA6DC959D65632C68C23046F9EC83FB7F72C9FB13192EA0AFCA6CA3C4A2F75A64F6DDFFC047A3B9261EA0749EAEC58CAB9CF7F70C6DF44259D02D315D3D6F8CB4A9BECA900FA60322D9FBA3371ABBE91ACEC8577C0FFFAF825D61C3937CB0ADA3D0BEC06D07EBC187378BB53029D36E4DA18E1499C589174E9D183ED87898537851BA3545DC12A5842D4E3235CB2FAC55504AABD71594150B27CD6C1B9FA9BDF7347565073A9DEC95BC2306AAD583D2B385BCD64050CE3B39C38E51CAC04BDD9B863EA5E3F508504E4195346B6C964118B6963DACCCB4E78C037CA0A01E985EA29FADBF3D67201304409CEFFAE583267B7327DA63DD0A851EF646D17BD384A229864247E1B8762DDEFE60C193502527AD1E65C62AFFAFC108A8D0B9444D11E5F1C979D7C7308801D41AC7F36A10FEA5C47CBF23A15FB9B37C5F7039289ABD785F47EF57CDED70A42FD10CBE142F30759423BA56721D34802DF82DAC5159BACC8DABFAFAA30FB461F752A61125224C451DDD82393241F46D32D98F1414A101625C2B04B1DBA9458F173C775A5B09424CB280B21B9EBFA1CE9B1162A7132A271D23F1EB7D8B9FFFCFC0482EF26C4DC1A00E2F32A59204352FA0CABC6FB7B645B39EAA24D94787066EF505A95F3C8422D84E156EB45596C410B411E8C690E54BE4AFC52EB3631915E67CA4F05E1473FD807FA2F9D73774E2F19F66A0247880C79350FCB5169A662039BF352FE74B5A968F7B166D0B780BE321B4971001815A4D2AAEF72D29C375FBFF17CFC7E040F5E57182883A87029F940B54ECB8AB44A93D39B4790FE443A1C2A9068D9609DAD60D2BA122B3B6CAA05A04FA91602BDD12622BB71D568F3342DFE39227A5508564F01B547D28D09279042A134B68562A3E64D4255390459B084D16474E10D0EE4EE7BA3B88D77676E39C99E2E0BFF291D9A6862B48833030D6180E750545664A3BBC3213D5E989BAFC1D89BDFFD295C84A9DCE7034F57000000000000000000000000000000000000000000000000040B13161C1FE4E3EDCD70C4BBED033F402CEEDC2C265DCA10B2DE0DB00D454C3AE1A0D00C97E1DC8C6804B1777ED21DDF5145B9F9348A931C128A8FB03827F653C37CD95859868DDE356ACE682F627FB69FCD97757BBE8BD5A260A293D2ACF0BFA2C0A3548FE25A2BA1A21F95123D592B40C20A927FDB615E69878E8D7C98D261DC01958A088599D3F9BB5E14002192FC7DE417B1074B3F7B52CD2A699091FD9DC3C5929E51CC0259D2255CAF0E444EC11257B759978BD4A7C8E2CE8473325B7498681102DE6FFE9764334D862E379D9F2EBF9B312FA75D7A50E08B94BD43EEF78722D423928FB8E26FDA85A345EEED0326A5D694E4729154A9997B269407B7D03818025EEB2BA96580626DFDB3BFBFCE100C508170D8150E4980D5D386761F4E8311339B47852ACC2A0A01DAD90D3978DE6536547D4F203CEFFAA652E4F2F28639BC3FF83C485C28EDC0BBE21D17B8ECAF3794D64C36FFE7F07E8A906CAB8E7FC9067CA4BF9B074C7FB01EF99A05D7C0F35D889A63AFE5FF18023BF77F8A3DA0C3CECEA0E538A6DAB5C54F3A0D83151595AD3EC4C45132EC2F22F652EA5DD930E692A7C0D7C23DE84314CAA7C017AD50D430FEF42DE557073DDBA6CAA4A787C92E6E28368943CAD0974EDAEB7ADDF991CCE20BF51C5A898CF0A2104ABB810BD4937D23E5D43490A3194B8A109B745E0A365EFA59199B43835682E996794F16C5CB874C88D9697B189AC54A1BA1F459623C1563CBA7689EBB32DC4FA0BF30E064D119D40C36301A653A4F959C97873003CFF7E8E030A137BAFE0A60AD08E4F692DC107E68AB40EDD0C384875B8525AA0A5EC3ACEAFE557EC76DB5283672F9751AFE1166D53542D216186A3DEF4DFA94E57BFFBEBD6F4AFEC3C0F3F40F651A1251A9AB39C262D42313E9F22879645589EA54FE894AC005115A43DD806B2C8BE6222DD9F02189D4221A9DDE99ECB8C3EF4171776268C12ADC37E4CA92EEF09D2D1803DB1FE917521662BA7EC0C07292C7E2130ECA4EEFFE53EE0CEAAAFF6F4CCFD42186611AFEE79BC651B1ADBAD08458592D69FBEEC708C7537925658BABBE7E9867915C6A728EAF41B0AF2EFFE55207C01652891C373F7A14409D05FE9E26C2E72D688047DE9A0954516B85ED6A3230B6B0EA9C5F086720C26EFBF8B7F5C5D14651D54C4EA181A707C562239CFC08B2E09A2941D04D587B90134D8F670F734578534138CD9CB7EC04437A768FE65FC5B3FBE818DB423A2208E485669082B422AB1257C2529CBF7BA4CB30FA27B7F702418C2EF9C3BF7CDE53661DF716449C6337C54542EADC5209A0E030AD6577DEEACC6BE1813DB24BEC035CEE6AEE93749D524222535A0277600F8E4F4BEB473093C5A00B6666CB319DFF131AE4F004EEB1BF71E5D274E3DFBFA246DADA9D6F548907091045FCCF79B363E695AD54C2F791861CE04874EE8C3375612DE820CEDE04E4472BC3DC19ABBB91C42A1C3D7B467837570E7D20A2CA6405DECCFF1AEC03E0558076E988619CB0CDA9CC87A12367BD486B676A4F71D40B88AB4E7FA750350DADD1A8F12B70864792D3CC1804BE8B7CB9DDA532182C32582015C1788B43054B7010229F46BD39000440E7F5D22E4D52EED85B204B344680426AEF51F0CE0551FEB9672DBF391A9AD363ED090837CAC1E721878E65AF9BA92A0EE7C7979925FBA9F4E452EB4FE3AF03B9EFF0526FF0A331AC0B8CD27A0C49E5019B7025C3C9870C900A7FB31FF834E04B87DB77C4D6DAE4C3FEE741E923704EE5F294D8F881833E9137158D1EE0FBFCB4637ACB814A2A5346607BBCD6BC916235F7875334F2B75A7EA7B8B8DDCDF46C0B8007C9B3A014EC6E634D4173CAFB1DD09CB9ED4A123151F4F2631D4BEE1520C10C15AFEB17198009C2B254C1FF0BECAFBF69BE8C7DBBFC7E8F3F1EF05FF6A7945FF79ED6C317609B9238670DEA26D56D481F87CA171CCFD726CC0728C965D9BC38D376D707E6979908B19FDF7E74ECD2D0671EC338FD54AD6CC5F789E96018521882588F888D7D715104D65954DBA8907C0B7CE3F2ACB802ED49DDF1416C29E8D685C5AD879464819E1D53FDAC741F71E31AC0C17B6C8932A4A00E7164CF8BBFEC36EBBD30392145B292D355FB304A88A638F991F6F89A398B09F1DE4F0B29866029BEE75A12D724A52736F2B9F49937F0E51B0F2E1BD2C1BC9325BBD1061E0F7685ACA02DA735D8FC39646E0B2453BB9690ED1C4853A757EA9DC2F4EB4B5ADBCFCBFB0CD2587F61A24B77CA0D6CFCFF47A98C7098B986D4FBD0E46EF0D1F9DF842F4473C43912AB49F4117C8214A42F3083936C7E8A38B294BA081296A393DCAADDCD0D340AC62511E47DA6591836553EEDB466DA6285359EE831A952E6C7AE3B943636124E43224D527B7D394511CF31C50EC1D3E7A20E49850905D504F1AAE477830E3BDA50430EBD47FDBB0BF537D8D479CB799B0429C3F6591328299A09F45CF9C6D30D5C1C9203B9521D807875D7FB2C2CFAA688414497122161B1B4F159B66C0834E111DA4F82D5252367FD2DBFDC079333FC51AB0D34ECEBBE786F984852A596BE620EC6CF84ED596425B90316A13B39E5EBFA19B319BF0FD1D6C812F29970FB1FFE948BC0D2E057B1DEA15445D71B5F728C72DD0C69E277C58F031F90932994AC5A177926DCC1C570AC1B4B099ED66ABF7DDE5A5D77D08EF1AD7C6FFE018F56EFB07C737F33038846247EEEE147E4A5995BDC3352B73F15FCE5140410AAE3F0AF1764E5AD996D01608C5E6C6C96A20274EA7781B41FC532B01B52134FEE28F501EFD9CF + +count = 60 +seed = A832D4AAE8076C4EFE8319A74CE315928AB765BB629075254CBC63EAAE691C220F4B5E1839E9A99D8747AACD7C2F1EE3 +mlen = 2013 +msg = 84C603D1B5549C46964FF2987A1F533B4CED94E67D576A3B0BF1C8BD87A74AC7DB640FC9F7ADE44FF79B820846EB83367153F5DDDDF9DFB7848A13D59436916EFABB82DD61291447491D2CA04166FA8680E8E0E0DC98E79344534CA1CBDDB531797A61C291606200107002091ADFA927A763CF98CBBD631CFE890B0ED257AFD34AC0C5280AA7C70BD0C945D78E6FDA284CBB7B3AB636BDF17342F2BA28D707147F14D15173D9BC0B6D65FD1663C86971BE1FA59DA8325E1F3773BACC5B8D4158EF525FDE6E96631C51AD142250252A8E5786CD621210DF3E24CC0B4B60AC2F013D76DB0C73DF40EFAA05A65383A8892276B3D69DD511937D55D914C3222A2386D1BEC0A268E683716AF4AB709D2D225B86229095E87FE70D69E6A34BB214529CA3F082C0F2709E77B86B00B4A04BCCD343C862333B7C9163857B77E30551710CCC3A803323F5CD4EB5317CD2E6A24BFB77727E1C64D0AC47BEEA1CB35E5F2FF6024C06F2F391FEE76F2E69537673FC0124E48E4E2242E84D8AFFEE6803CE6EDF3A954D2C54562B8B76A4EDD91E24A8640AFE67255605849053B60F558B43DDB9F8A04E987D15F6292962D10AD8F7B47188D12D1C9090C0FE8710DC3937C6939496884BDE0BEA979839837C61BE4DF5662C724610C7FCB4631A0A2083417BE6A20F4EED094E2145BC72A83A6E147A655C481DCC906E63ADC0244D95B6085FC096FBCCE81EEB0497F48BB5EF827C0893E331795E3B301DC9F3A91DBA9FBC838E044E2AD9859F1DC67E9BCC375442B4EB59714B5EBBA87AC9A79C99CE74F8BC75740DDCCE46C4B408B91DD7D4AD26B0FB1A4AB874F5504C40E7363838D22AEC45C10D3CC2E233124A5CD8344249EDF388E37BA43598F2C2CF56D444BCEE04A335B154DFA3CA694DB481CBAA59514098CE6E0E4138C0A543EFAFEDA4AECC022C824259A06C3D57A70EA15A5DFC822449A27F58F9EF842DCBB636CE293684E1B331CD821594A12634E5594410B6C5E2306DC8BBE62C8B0F49F2F699A59EFB14D3CAD399F74ED893E1EB43FD770FD61E0C58E5D8CBC9435F4AD0892681A30DF4885927130432186AD4BE41F6FB7CFE660E23C5E55F60789B3E97C3B622599938B36BD1C0BCF6FDB7E4EE44C92B6A86CA2470BCDB8BAB8DF6079382CA314BF3A8B3C4286518C356018FD6F6FCDD9BE9AD9C228F29135544E723A898F483E9D9EE843E75ACB3FEAC447973D12461FEE3D984F3B4F31645FAEA56852D356C96CD73A6F185E8CD56731E83FEA145A2BF0C15ADC634DD9E2FFC799B59A0712EB4D2618680C7493F50A9BBF3F7BDE1025CD44AFDAF4A8C42C9254B1B34AA8559E1CEE9BDE7B4DA0FB3CB2289418110620E505B793B91F422FCF53ADDA8F7C96D55E26244E075D9A70004642712EAC377CE18F88F2C8581694B8F621707DAB6D292179B2A95AEC5AD6E409D78253DCC05ECCDB45683DFFFB9C629AFCFB0654725D650E4A283FD98E47F37AA9309E2933CC0393625DD81D4A02F9D5082644DE02B6472D5D3AAE110747E4F756973FDFCE8EA5F997E30B11EBD50B45F6889D227D87D9184CBC6ED40E96DEF8B9236763C9999E21BFC1A74457FFE5E0DC2B16876FE04C2E0F0F47012A767A7AC18D71A7FD65F8647A7E1AE2D4D255492A18AA81D17D390E381B1722BC3C38BCCEA9D5E73231D0C6E1A96CCB47079E36C994E94AF9A318D67B6408BB602A91D8E9EC6499DEED0B51A9AE31D9774A1BEF4C1DE0E7A324545B2AF9870CD733C2195C5ECDE386D298C33D492937497EA5F0E05C377A4D755DEA9D96C61FE82CF6299EB34B857217A2C6733FED64F5DAC5F95A0EF2294ECA844B96CEB5163363A31C58C88428152663AB0A2B310B1A9E9027CA8CC0DB6DFF528F9A421FA826A86ACB4FD1D79C1AE6123C9E685BA66F5FF109FDFF2497B1A50C2E4E7B4662FA11FBAA305A960CA70FF98E5290A8C3A27B4A3CF1705C6DF4290FA64F3259FDEDE7A81CFDE4214230DFB9EFB20049E905833B5D48923C8CE2F8A104946FB3356154519D950998677C56C8B2C80471A6117B142E26C0345CDF0634E356D80C3BE12F4AB89EB41DDDCF98188EAD2FF420EED3FD9287322F24C62B21F430D5F9B8592CE1CDC946616111C91C667006E47992FE2D5A2AAD82F8DD1AF3C1B8BA5326220645885CC94E8B2B76CBFF7E161E994C0CB9E489B8A5662E9D420913AF34433F5BAB10AC72C5EEB9249F3C102E1762E862C13CC882D20BE16834E54DCC323EA89A133F451B70087A8DCDC5B518EEF087A571B570A7966F1C49BFCDC70AC05034D1DCC56EDC2C0F57D1AAF16718C67D162BA330AA61A2875F90E2935752BFF1EC28A79EAD1AC18E70A833946CA6A15D8765E1A62AEF46BED232EAE89DBEC278297B396CF611448C5FD4B36B95CDC54E3394C63B9B0969D6488FF1C700B390E7226F99A945306C6504958CD43CD3D63910A4324BB662A0E5DB1622D90CE00E50CE7112193872AAB5CEE0B8D6FD42F26C2FB87FDF99062169C0BE75C85109D4E209DC8A640FED3EC71EF3DE8878B3D1729FF118F50F8A33361C6F707F6011454C5D744989EC1BEB644FCF99CB2E7C3CD20E6F1656E07C3566C4DE68593BCBA0EE9F7BD2E272C3D47A3E03985456F18CAFBEBBC1DE74964BECABDF3E9BBB9A10B29BF3B458FD50F19D63A6231CB51CDE3DF46E4BB6318E81E10AD1674A053C8CFE1E72853FD60E6E642642CB825644D6734AFB00329839F22CED734FA1421C4334E20F2ECC8BBC2652004203B3B639FBDCF5FDA1423F08C3A1100655E4763B8D8356A151D702124D30FDD87B34EC4D34BBB3639464E44A693690E193329 +pk = 247C4A88615BD55D4E0CB9A2783C201CEE004F9801509DDBD831F5DFB776B5495B4AC0827FBDFA44345EC962C8869A49862827B90DEBD72443DB82196305A983E695658E963083C2AFF306D9B408410A37F97094ABCCBA4C2901AB94E28A1DB701FA378BB29AAF78E5BB9616798BBF1985634293A413CDE38650F5FC51CF2ABB4078EFBF51CD24A97B39DC3922778C72D6351416555E012A421D1536A6E6A47F9C5553655B214DBCBB0D90C3687F49FBA267B0A0426D65701B16ED1152629D1863F4FCF90B8E90A501AF7009A7A3E681BB870F267363D4304846927859227C718006718A0121C0D3BEBD0EB933420B8095ECDF5A50D1EA6C67A5B4F9F015F1D2C652AFEC08FA3DC9F623C830B7A8BB4502EDE9E8E945026A1C88847EEF174228BCEFB7DEBFFC81C33D1140C5F00B70714CE840B4DD12FBDA0E975B630D29347B1E8C245C34E8840B4091CA361052E565317A268829B882FE0467E5EC9917450FA3A1C7374804BD49725BE898A54F13371C3B443B6FE53EAA95FC83115E10BC2E3506D1F5948B0199E0D1E879BC6E7EB68D5762944018FE2681119EA05D9CF666D7CE7C5043CA5EA8C7812AF0C008A53187A924A1BF2268382328B6C4B2999B2E2D861143F153AF8551D626102AC5377308BDE0B8FB680F8DC3BFB9485819EC32F6EA91444D3154675AC0056EF4471242FB49BFACE4FC789B708DC3A156B268ADE7D8EDD2446A12E33A2B5ED14E3C84AE04B8F3FA5839E7199A844F5AE7F18677C390FB78EEB63F5722B8DFAB39B5394BE8A4CDB2356B2DD1F2FFD677A984AEA0C9F4D9789160594527167A7E76D299F0DF518BEF3394B6377D846B4EB784DB68B54CB55D28FFFC064116F867413811DF6A48DEF989EEBF0B87EACB34A489F9DFFA5F25375699D2189B7C485127DD304236EF94F5BAE4A4B5E037574FE6E17D53C2C787D2CCB5A23055F2076F124A2A1683DD9813CB612D3094D5EA78A93BD951E616AA4D54069A1AE8F3E6E5F041CDCE6A990F008506988C821CDAB4809C818AE0864FD2BF0E6CAA4AB264C8CAF86158C45D734348FB3E505061A8ABA6F305C6A7AC7A1CFEA10731B29E6617FE383C0BFDAB70D00832A1D959B656B336BDCBAC6A5859703CF1BF0F1A179A9F36C503BD467C8F4542A54ACC2C19D747DDEDB57D2620354E266437224291170717A61696C50DB8768E5E297B62FEAAA11DC4B11752D997BEA8BC90FEA0DDBE381F185B4327516E8CC0DC32FB761758DA34A398B379880B36BB38859F67BEC7A7CA13B444EDD7DB2AEEBE2F6222C90AAE7327B130EBEB13684ED245E3CED83E8537EF0A2F6F540FA6F08E3AE3DFE234D663F513F72551F85FC191EC8D21EF57C79236A33B6ACBA3966E63DD4B8670106F5854D46D96E5E4019E85763A07B176540F7636AC147FC82BDB4D465AE56B0DD44363232A1427337CC027B9994F7459624C6D9D92CEDB19FF50FB6148C1E7BEB43610C12B08270533CB852DBCBB28545CEF9321210FE990757FFDFB0A3DB671E7BAFD3D415D327AC09225BA1458D78D00CE5445ADCD7454F31A894BFF9F912CA3D364F8EF0BBDDB21A515CB25A76C9DDFBBF924282A468448CA902ECDBA0123CD5762BCC1492AE9A071FF1267D65DE5FCF0BD9A8DB1BEBE46D0D8E4E0BC0D2D914F7D98CA62DA6CB48770F949659F3022C151044AE042DE41C2E5D701935B4BCE71A6FF834AA8C2CC6B35E05E14F9B6D67377D05289F7876C4F00DA5E0C05AC18C1A40BEFA5BDFC909FE72CB62AAB32B08D9C2098CA73B24D0B2D4F878AC98CC46F91BC0749BB73097156DDEE26BC59192DF984A4656E964265F68F2777C858A65E63765EB8A968AD6C86929601F913FED0B7B15CC35D1616F004267ADF23BC6B1442C58463E956928E1627CF8B8CF9F4032FE97EC4EDCF0E9DDB03308BE0EEDE6898277ED2B47417A2F95C695F1D2198EA4B459BEAF87BF3144C0435CCAD713A3D954CB703283E258FE0AE2675E996A2FD8CA2372BCBAB2DB91E6C466FFCE40717ED54A8E525C0E82511D9E819117C7234CECE074AE671ECBD4ABB03DD2383C86F883DDBB5E1540C55796D25AAD444B53EA2A411E57D44BF16051E7C6A7FD1C484896A64084B5B14671D4DC12BE5BC3136CF8B7A72048B2DFB614C5A4C6CBEF0428F0255F8F030E36DDC2A298E8DBF31AE4E91A9CB99376DC0B1103A141A25E949ADB472850B22EB358C557E23E4B0E386CAFACA3F75184BF0215A663D325D5592829616FB095C57F1A151620B559A14289720477793EE26D3DBC982B4472403DDAF186214F826CCCA4CB8F8E061A81BA6B2CD6305B5D70A02DD4EE689D03E05039C088C178252B6882A940CA3B710E6B869A9DBFB121C8F82D0A13837B05831CB67FB9D49E5983C3CC7509CE245B9B4E044ED51450FFE818EFCE98C74A807F412B1F9E68B2DAD73D7B31ACB7914F8D744E8FDB9171D8A832B181B2DCACC1759EB138B113492A33A71F6A9F598A74BC2C75D3E89AD7026C241FE2CCA29C06D97169ACCD65A3455E1790657378151F205174CD9AAE5889A188F88C7141C1F3488137068A99AB5EB0534D98AD1DE35AE21514884A1AB238C3472FF871AD4A960F6A2B2E4B7D3043E124884EA39EFC7FA9C742244CB9004B4DCB46896A7B277F5A5B85802D5E8B9F9C9D3C0A54B8B8E07F59C9C3814ADE4E441A46A8D15DB23D859CA6B6F0C0739D882DCC2D9CA49A8106B03068FEFA59BB6802172BA44E84F4348499C14EF +sk = 247C4A88615BD55D4E0CB9A2783C201CEE004F9801509DDBD831F5DFB776B549420E6BC8A11FD32136A44011A16C09D31FD772B7917EE89A3DF767FBEE6BE4C1C72B41F95E22A2233D99F219BAEEBA1138AB3C127A3BA3E2B43921D2C883A408FFC42E2B1BC070BFE22272AE6797056C9E938D6D851CF4DD79F694A8A09F7F5C075603267578336430161276506808522568500882652008788354027531538306035426052276127180018731622156322081100454841081725551324440114223446134337107740828323156457442543876674628716215835846333316072206420444710043704672663308210802711264830610440878383720484681076480533318822864306062807604658424270084040173487586541248801530131751720334028883886111023510570317865235860213427042877753087740308777428846144216428753104180708141386008882088013057783117234720233324077680547844324477618067507620614833055445801316333266063073034435646088873852805433108274508632651037172221722730236626481440002115370043688187803027815070547181783462684352618336480680712573776483070100768523872532642413835076266510864501184473016686673887301568501778633283887356860446847218275375736243088562385653788034014723641730231474418713752813480730370121251373672716521802648166005020881345750884712842048020514061444631158234372200255075744008847154688083000437132740210676757418673235630380065385375314758665564521586278313118254468106408422373730268676104270315062612214871024721465807380026701437168801635038374571104861154423425605475244432278435704376228574655532331010068014757117052263446557344257121433730411048121120677784137607700006244706856125608312842451258372647686526787182553217158158834553056143522266331124548467552876803160623617202618213456823502076201677680552344124154380021170783570531646864431323227887435752763156414434001857063833734261447088051765652240452372528132531537834214064263342821545531808370350556032731066385823314146785160268440808080665623717774066213776218870221770835032853756425410037418028478820456487431384102068373185257574855737777828807041077141280335268774732737628661014303780015451108681112066154465200306666006080784677400565257273823857131563260240255681145411072541740031325478264285113848130505441468812676534310531586654382757876174665334734513574885574644616842648346265407786670013838865226885485455840022821132855422562221061003012863573133650822483514668004251853011374611722308551082185482127520604561818378070110653560438100674523478052488755012887506388660218617160160080024726330053534060788825263273480157380812056306400477248087784472301743564437728682272377713304475444180848112731583306824563317187676802157481158160748630224513771136042766514654432587687546872034008681527431117612760662156037806034560438170225887563462480372041637671281234317665378670657606714544614601200320567314137387281463425032145865541605124837266708880470675270223785588676750223477718066115342554570423456243048554483036710840258030812662721448404054112158711014006556226862347250638142671261234700481155586235188244365366472014857474476715127314653146662271816465060537764838138603184606876118412400704113386372001412153648412818030342340208646067546667273767562047360682280448414325730227034167A4ED8FEED3AC10401397D7EA051CF2EBECEACEA5D297C1265563D59A582B2A05EBD504714813CF9F8EF328362E4A5FC5874ED5B0D26F82692F118DE7ED7F51461E6110083EC0C2D64735B9372F772DAA72BD56868BDC934DC6C5D8D45677A1935D12C886A1537902AFB4E0F82A9E3AD5AA1CAB84AA1B05DE3E2E7572D4601EC196C4AA087DF82E58F994C49812D57A0259BA234A3394D7B7859445DD11A5BF759DADBBB889C1E7D3258D9BAB411056398CCE21D5817927A2B0CB6DDDA9C768DA8430F512B85AA6D67B1A282F98BCDD676618518ABB4A25DDE5990D1ADDFAFD6E1D5FD4B74ECCE01D51462214C152711A26480461C6BAB74D17E4F97F3FBF3A1C5AD0E86A8D3363771B38743AA9CFDFE777C61F6085B381F2817D840641EEE63ABB4BE79135B572C0177D98BF431971BBC7AEB88EF54F7B5FAD0254B972BB150557E2768D704E05AB6E15935AA4B616EFD5BD3AD086307465FB85C2F5054B6FBB9FCF7360D1E7122F958B38F5AC50FD91A2604BF6F22740FFD747D6C4FC9BDF5DD00E76B7C6228989790FC2CE196DD498A838077D1CACCEAC9BE6A33EF7984923CF35E95A18A5C7EB7DB7CAB519E834ACEEFA9C3A7AD3B3B3CB8327BBF755BFF1C32A65B647A66A9963C8926C0A50A2DF232936950DE9C5C5B2B3014E38A3CCCDFDD1CEB842DEA7AB0B86623DFCE0CA9C73B0E5F5AB3F2BED50E44C2E6C4664E98B065B06269CCBA6532F3C0DCC7EB68FDBAF472CA53B3A194796437790625C6FD9888FA3561769D23D88577AB37DCE650B3B6FE4EA6E6A4ACF8E63B46303DBF8F5663E17C08872BAC6507EA4F1CB8BD7F678B32174C79BF0C20991A28C4C139DA642AA138C77FE9456EDF2E5F3DC4D9A1A70CDE0282B437615EC5C4A44FA294D6F7D32648F605F50F46D6F64CE8C2DA4DF3BD78C09F3A0E7B4FCE4D189DA2C0E1C5BCC532DAE6D9248B467860C30F85565824D2A75F5409AF2F70CAA0A76B6B9042FF7F423C7D2A7902B6C27742238CB9BA8000845264885CBC1D814B9563279E251F4414C27907205268DD756737562DCDCD0611606EDAE62D66D4ABB66F5D8B46ACA2E62B2B4D00E04710E645D18FB2A76F3AA246DEF0300034612D0657DB492BCD42E640EA2A6FE875FD82185B31AD8F84F55B7A39CA0413FA83518D26D23B15B50CF07A56229F3FB33222CA8D007026E0DEE32EFA31033765569AAFC22F1B667535AC32C6F2A4917F4F771BEDF3D467E19BD7B236174EE2691AAAD9AB0D3DBB6B35D5C0A9EE160824AE56CB430A5707F87B952C61BDD0226829E79C3156E518A7A0CBE37A8EB634408E37FE9BA9D67F945E0457864A11B6063D8C493B58442681E4CB6F15F35FA8C12B07AF1E203287FDAC44E4B40E7A8B18A7DFD8DF7443872CED057D6D65E2BC6B71177D8868404956BF145D63102595DDE58AADA4F43542FD6F8E94304075F088E6C4CF4D24DD486262E1AEBB8DCB1A1ACEF58696C72EA6C98E22548D6A2E563CDACFC865255BDE23B102F9F4D3333FBB0A6AC579428938DD39B17239A00325046309359816B70552E8DACB7AC7BF1C85AD4A9D3151288A449A8A9FFEFD998AD4B003516AF6C4222245FB707CFF3C52B15210A6ADD0E0DD166796C4F3AFA7D590BACAFF8D2529224C6A9AEF771B8808DD1C9B2DC637AAFE12EAC70CE7BDDC7539C8391C7EEBFDEE64A62248C99AB42FFC827DCB56E1BE28E59BFEA60BCC9E45821A8654D188455D799D44B71A64ADA8E2F99787200870EE1C98DB35C05A990ED678FAA915C8FB3EF136E5A5E1D403BBDECB9F3B71B8955DA6A4C4BA86F1CB753911CE5D7DF1EBBB6C7FB9AE84CAB15E9ADAA4241F67BD2D77E863C8BA1312DEB01ACBF188D22D983EFA94D54281DF08ACC402D5B4166949ED37D24E3B2C405C68EE1DDF22CA4DF42F0E9CC67E02805AAA3CC3B98CF17C8C2721E74D1393DC2FA8D8F18B4729788F406EEE10C024D0C9BA88CED296A60F8B56FA4784DCFA186B0B041BD5DA3E22C589A64AD14E29611017ADEAD50C3DE9C7571804753C02628F9CAB9AB3E7B37206BF42DDE05BD8AA08DEF67720EA163BC651C83B4B37C549F32881BBCFBED66487B304FDEB06F1F892EB9899E14A63CF95C762920BB1A0D1C64B55CF4E43238AC566504ABB00145FA6E9FD1CC54A24122F00250221066BF755A40439154693498AF2EA50083D557DA44B6DB4BF1A5DAFC4F618B36447BD407749F7C7ACBBC4275D494F583C2377192132C6F00A3E028E9C9E9AECB2C91362A802C3D8F449526670FADAB49950937F037805E9A32AEF0FAED9A2137B9D46AA10781E0D3C3D4FE922AD14AE518ADB63FA95147308E44C5BD33FAC138FD73378474BD7D5F9FA3EFD4D87A14FD15F6DC12F99C3BCF60CE6DC78F5B84449D271FB7AA1951430DA58EE5DAE18E7586F2C0ADE1FC07D2D983238D4326BD82AB21241D3DD450984A2F549792A4073E0CAB8D4C7E1DF5593183F8CBD5A4D84DC73840ADAEA1FD45875CDB660580D1A581FB8B77562820A1E71F1C154E06D24F2824BB1F846766CD17A6CA8637EB787D9E9CDBFADAF8C2E2C50997E4938E4F134AE64DF7D3FF0B0BB00AF31483C56148E98A13803C117DB8FBE3A57309E529E7EED1EC34E4CB60EC5C4108DC2ADF96281B3126978E94D2B3E4F3E3D7E523612946566787F6A8E9A69E51951D6A1BBB0D87E661BAC5F88E2510E5F04C17D04FC9533315B36BDC594A8DA1DA18FA5BF3DA2AF892F7289A8EC54083E673ECA65FEA46D95E421A151F0F65DE7ADADC8B5A8E311586D10C7819A5CDDE0C39037CE262CCC14FC277581118EE5A7EDC0780EF41EB48B5D78375C4CD62E901A2EBC41570C697DC0F23FE85F1AB741D2228E12F042D518494384EC6F175BCDA06B30FABDBB619B943B6B07801AE9152D593AB8294A5564AED6186D92A5B9AD924F1531242664A60E131782BC5E227532FE571CEDCAE31720CD01B73687DA01BDFB772EE2FE189962944CFBC5DC1CE2DA6EE59457314F9813C40DBD3A762488FB86D3DFF3A6800A21C0CB8DB40D7E79714910E0BF6800C263CA2C884456A1E45FB7795BCC3B63606DAD8B5315A6062331C10B7B59A11A8327EEB25674CB5A3109CB2AD1025BFC120D47A8A9803AF023CFEDC3ED4C0706EE37388D74A899613B18BD0F2DE09BA4C87A06BCA92413815F788EFDED9248571A207B7484C92CE9EC8A0B0A59EEF4B5B83DB80840EAE34C5DB45E8AB8F8BC0ABBA8BC227F4CDD829E2CD176B5786263BAC5E9F61CC1E9D5437A199F6EF96962B623AF12909357AD43CB5405B4FE55688E6016513456FF40AC200E1B9DFF46BC9E4E5C6F1C74D52E82EC7643FC3297E66A0B199ACCFC689131932AB444C6B86749DC62A6DBE29857918CB62A0A9CF60A6A8B39C8E6562B1A7FD3491244E5D1A30AE429189ADE370A59F145677142A7B76D56BC718E70FD98AAB2F324531ACE63C7B7750A974F89C5E667942C33950B9C96D54A3E52E87CA3580E536310C242286949194F6FFC4541F2 +smlen = 5322 +sm = EABABE6667D92653931894676B864B7ADA44191362E15EE644761943C47CCBAA9FDE6FA1A669B1BCFAE34B05702BB786971B56C6E1705033DC896EA962764FB5D5D5A93EE34AF0C72625133605B442E0DC65D1FFFC8502809FA926C8A489FE6012D013507ACEF5299076E490DE97F1FBF5D6D6837E901CD37FDECD1188362BE465EC9EFBC9BC2093DA8729FD3AFB94FDF723928656B335D9FF75BB31A75EDF5A6098AE3E638FCE418E8EADBB0D3BE47F4C1CC855A008AC0DBD35EF5B8DAC1C21AE5143874E00A20B60702CE8F9568B805B40B45F03DA6B1A7CC72ADABC976E935A6E6F7B6228168C147916F440A5F89E70B89466C95E831DF4BFC438ADA9F5BF71550843C05C4DDA43FC9B19C22ACB4BCAE1411FE0F4D67A242C0EF183CD47182139B5B3AE5F96BB5222DEC91E7A08669A74D1F981872114F499C5E5BA31E13F9FC2455D9FD8785877B669078722C0B3CE9485F1BA315E99EBD0904CB0F2C41C8E25F0F9B5E72FB2C18780594D0B48092F34E36E1858868FE180F4A0E247F58098133A8229BFFE14598CE2F8B3353C7A3C674937A57130BD8C98774B1A5890C316E9BB745782C75310562648614EABAB008B33B5D5DAD44856716B500797DDCA355C1ACA6624F9A6D26D1FFB60FBCA22E8176CFF05B105FD85083D13D81B1D091D16ACEC37F373F178D35D5A19EF0B6DE9E08D4A565320D852A4E630558A2D0BD8DDB4E2D358AD09D33D866B5EAB52A78A91E19BE44EC268573AD33F5BEDEFEABF51C79F0A09AA3763CA067C40CB24C1ABED3CAA84119CDD6F028134130ADF371489C9420498FD70CA5B94DEC2D1B8E39A91774681AA26F33A204BED1A27F2CCF1EA10A9007183CA5A9DAD6CA31998A8D91A35EE73DAFCF1261702184F9CE0F31240E8BB5B32DF80F5DF37E90F9C65A449D1CB76044B097228C1279BCAE4048BC65D69547806CF9103E77F85ED1E55524DDEED269489CAB962A46929BD97A9A634709B38AE7212445400AB89D7AA648502FF308CFB07773095AD1057063AA7FEE7BDB6E2E1D356799877E9C1A991862ACE42EFDE4353B698D7D7F014871CB532D787D98C380790F6003023DB5410D9BB0ED44CEBB0D8794F1BF258DF07A3EB23CB5E0C720B04E705AF159BE7CAA69F0CD13BFAF620FEA12E9F1CD75971F2158A1C616DB9329A24B283F0B4B005D55572F463EB609AF6B6BD9012977183B32A747567A7BDB053901BCE52C372F094ECCBBD793E87BFC703F3F635D3F95A21075BA9E262D2FE8FED265D3505B4BEEFCCA2451C9480F48B917BEB4F78DCA83E2FE6D7ECE1B3F2F7F38E149C38F87C82E6FC76D7ED1B84731FE121112B319674BCD59BF2A65D1682E790B727F7AC83DB26707A596EFA0E64E4CABC9CBD970B0D95D38660E266213096F1F926A08F45103872FD6183EB1CEAE407F3D9852EF397371F1E9ED5CCEB5D143B09E78E2F9DCBE4DE757004BA8B57DCCCA1BA9049B770665997A676219C5EA9143D27587FB291117514A9DEE653E9F1C502B3910E57EF9498A12ED04A5C9D84AB2C44B739B8759B64F7327F2F4CD7398F19BE55F4FF4DB31AABF35FE1ADDDA879E195C62E4557FAC276AAF706B108C70F9F812C0B92E4C134E4C0C2F03B055A73A6AF2F86F046ACD96E0D81B45B443681886A409662D7F118B052D830BE093DADE5BD792795CB8E93FA362157421179AC54EF28E1EB869687EF90BF2C3321B99D8129F94C5D6F1DDF25625CF4991C0F8ED8C83D004504B994362800C16876E79E07D93306FD0E9CFC500F5FFEFFFD7B48E1868D01E485E8C6BE4B5D3EBAA04D59FF9F199DA9CA4D35726D3747DE2DBE66DEF1E5EFF055E3BAD682DCFB31777A2A00DE6AA1A3EA3BA9240CCBB4C341B6E47A11F2DC82441E053C7F6DAF4A01DE8003D07CB4D7363CFB0653A14937BBF49466C520FB5466C60EDE0D061A8A1F2E6383F5BF88C814176A7EFCEB41B198D4C614D825011B16435A2DB7E5490A0CA34C4A86CD1864F4B45CA966BEAB046194ACC186B792BDEC12828327328F0D6B4EBEFA42946154202AA54CC8751992D1D3396528AFD149E9F727EB53C98D9CB93A7AACE241C222EC99147BFD97A5593C7DDDF0D49152070DB3FF1407DE4ACA01728D14894CFA17795AA145DE6AF92D6BDCCB54710F5DF788B59947B9C838F3BDEA2B3E5C34329D66B8F90D312965F0A7588F603521809F5A06C6B25554CDD54FEA6E4524368AF1A7088EF0611209E3735A4A8CEB174EF7DB4E969F07F518ABE93F6AD80A1E272ADC9514FBDAE253226481843C8477694D62F96B67EF06066DDB96FB241440FC63F85F3E0CC027DC188F09931739DD47848BBCAB111BF82F7C0A0D55E7A5712D66AC5E670B783D2DA38E3C5DA2557E33CB15D902A8015598296ED72622AE3CAB520F1FFE72B8B887590757430DDF9F8C57D6B82CA2AF1DD57331A2C0BF149E0C100BBC0A0F7EC4D133CD9B9D9D72AA3D7EB6EAC27C0AECED3D7379F98B6A4057E0EB9965081B6172E4EED582769731D6926574F165CB1577CA0ED5D4936663DFE20A55565279CC773D62A7AB2253718E7399DC02543F5869AEC3CDB066B67EBD69E0650FF1E24D3D44A8662A125F5E746A2DC3068CA420026393CF4432B6CD61CA091A2775FE8F5FF9AE02E5891E2F9D2EE717324CC64B698A0F9F81B5099EA620B68F4E1EE1CBE20686C0F78CA890F4D6F90D07345DB70BEA381A2985091C7805F4E6D82950F06D8A737712E0CF2DE184EA5BC5F2502D75C101FC682C64850ED8C9109BC6D662EB60F552CFCBB6FF663FD7FC50849317FB1E9D75D734D2C5C939D7840AC99FA8920A73C07DA3C0CC01018F1EEFBB297003F34423D87BA169B5349CD100365E586C76DD076C5EBABF1757FD9A338788AA3D03680756938F81F238FDFBB90D6ACB6C72165B02A3A1FB6B191C08FC1911D7016C84720AC722286698C18D0B712EF4260B11AB135494493DF1AE5AD304052B919F830A3E7592E6959938BBFBD4E2BB757A182CD21B8C63748C26949F155C6BBC353E5BF62B65E59D028DA7766BDD2CA11B2EC65A8378A70C218930A85CAC90A754B0DD3ECE48896F9DC41E40CF0C369F6D921F6B0BB554C23427F862E1C8320FB31E8AC78439B1A8346DC06606728A646835BF5549E19F32ED56EC0C6B181AB3E98A905726E215D4A99C2CA1E9591F28BD232EF8BDFB8B162536E1A12A4E9DE94FDA86768559998821E24EA0E522B45F0380C0B99903E8B2F5E34D80A751C95F95F91F5EA2B0A9AB2A6C3964974B63B6D9B29D1172A9E07F830E0C43B3FA6F85473B1B2395DAACAAAA3E9F90CDA2B3A504124E4A3DE730A847F8F2095EB900CFBB1F135481E34C5BFBEECA5D75C66581EB6041D096DDCD04A9CECE37EC3A6EAEB07B02855333042B45E19996F42E078049A8EEAD575F90CA544CA96D1E5913B210F097F15766E0DCE4EFD1A2D87BA47DFD699909A2E1CD8BADBD9F1DB7110C9D7D8916B5CB23CF6C0374F533C5E941B1803751E3CE2CB1F0532294A56D92A1572657584728AB2C6FC927C1A685D03555460C9F1B58C7E9CF921A62C30220DD1F7F45ECA2CEBA113B9FA73F861C836B3F63CC0DF5AD18C48C020D8FD9B3500675C755896FA8CC1EE65ECFF6808EB6DC46A779515B16268C75078CBD958A07CA36044415B2C9CB9369DFEC3D349ED8D8DBB44F3A7CB937903D9C8D47B3A9DA6666653202339468876ED41891D3FEFDB9D48F7D0F0E39E8464CF5F814DA6986EA9DBD67A83D4F7337BB9CFA887DDAEC65C48C3D8577B595B95D1220D7C855CD052E5303562B23F5EF5CAA6AEDA1A3EB794C82C16C5CD6F1164BD1E5EFF3ECEE8B932BFEC942018B38FF0C809D82D028666516FD613F81DEFDF86561CAA0083C4160362EB09C845F3F3D7FF42B99EF9CFF9EDE73C828B45F63AFF7CA1D26093B298B7C319E64A5E890722D806392F7AA69910F69F41884B1146EAD3A490D59DFF63E311EB03365ED6E21B4A9AD21D7E04D18A901C4892D3C2E00FE4E8EABDE491000DBC0D56F64855B0DE077B2FF825963876994C4C849442CF88C5FF3A18481C58FFF40BA8ECF125D590BFC1874FE4D9F96B8D3D3DB59FE048F39C471C38A7AA55913676F19A3444803035B5970FA6EB7007A8940100A07CE961CF7A56FDDF9D10CCED782C8828B2364008CEB6CE496EBFEB1481CA3E3B3BB6886D8533CC79741B6683874A79F11EA51917E94B78EAF0FFFA4EEEFFF05017CA858CE69463B9CB017BC6DCF1443DECDDB5A602295CAC6DDB8B77E00B0C06185F83A7423F5906E5A0EF9BF00BE0B062551D24233E51BE7ECAEDA129ACAA4C5F04C81302B85BB3C440D9ACB10FB880DFE0D6D040A44E9DA5EFD4DF2EDAF6F85FA9224116FFAAE278F3DE0C3E5313591F44000A277C845664F0E29B96BC80CD1F6D06232384413EA996BF090407C8DDBE5C106E3C3757F28937184E90E9EBD721692F3AFED166D7BF559E6F93DE522003839634F551AD015F2B5CA335A55C9552DAE8650C401D747AA90616C2C05040391D3704540802664BE588A2A1309B8016D1A969103F62CC53E6266E2DC1BCEA885F8E72441971A43699BB4D1E3FD2D739097BFCEF6252958A4CFD6FA244961E36F9EBBE1F13E73787CE900000000000000000000000000000000000000080F161A1F2484C603D1B5549C46964FF2987A1F533B4CED94E67D576A3B0BF1C8BD87A74AC7DB640FC9F7ADE44FF79B820846EB83367153F5DDDDF9DFB7848A13D59436916EFABB82DD61291447491D2CA04166FA8680E8E0E0DC98E79344534CA1CBDDB531797A61C291606200107002091ADFA927A763CF98CBBD631CFE890B0ED257AFD34AC0C5280AA7C70BD0C945D78E6FDA284CBB7B3AB636BDF17342F2BA28D707147F14D15173D9BC0B6D65FD1663C86971BE1FA59DA8325E1F3773BACC5B8D4158EF525FDE6E96631C51AD142250252A8E5786CD621210DF3E24CC0B4B60AC2F013D76DB0C73DF40EFAA05A65383A8892276B3D69DD511937D55D914C3222A2386D1BEC0A268E683716AF4AB709D2D225B86229095E87FE70D69E6A34BB214529CA3F082C0F2709E77B86B00B4A04BCCD343C862333B7C9163857B77E30551710CCC3A803323F5CD4EB5317CD2E6A24BFB77727E1C64D0AC47BEEA1CB35E5F2FF6024C06F2F391FEE76F2E69537673FC0124E48E4E2242E84D8AFFEE6803CE6EDF3A954D2C54562B8B76A4EDD91E24A8640AFE67255605849053B60F558B43DDB9F8A04E987D15F6292962D10AD8F7B47188D12D1C9090C0FE8710DC3937C6939496884BDE0BEA979839837C61BE4DF5662C724610C7FCB4631A0A2083417BE6A20F4EED094E2145BC72A83A6E147A655C481DCC906E63ADC0244D95B6085FC096FBCCE81EEB0497F48BB5EF827C0893E331795E3B301DC9F3A91DBA9FBC838E044E2AD9859F1DC67E9BCC375442B4EB59714B5EBBA87AC9A79C99CE74F8BC75740DDCCE46C4B408B91DD7D4AD26B0FB1A4AB874F5504C40E7363838D22AEC45C10D3CC2E233124A5CD8344249EDF388E37BA43598F2C2CF56D444BCEE04A335B154DFA3CA694DB481CBAA59514098CE6E0E4138C0A543EFAFEDA4AECC022C824259A06C3D57A70EA15A5DFC822449A27F58F9EF842DCBB636CE293684E1B331CD821594A12634E5594410B6C5E2306DC8BBE62C8B0F49F2F699A59EFB14D3CAD399F74ED893E1EB43FD770FD61E0C58E5D8CBC9435F4AD0892681A30DF4885927130432186AD4BE41F6FB7CFE660E23C5E55F60789B3E97C3B622599938B36BD1C0BCF6FDB7E4EE44C92B6A86CA2470BCDB8BAB8DF6079382CA314BF3A8B3C4286518C356018FD6F6FCDD9BE9AD9C228F29135544E723A898F483E9D9EE843E75ACB3FEAC447973D12461FEE3D984F3B4F31645FAEA56852D356C96CD73A6F185E8CD56731E83FEA145A2BF0C15ADC634DD9E2FFC799B59A0712EB4D2618680C7493F50A9BBF3F7BDE1025CD44AFDAF4A8C42C9254B1B34AA8559E1CEE9BDE7B4DA0FB3CB2289418110620E505B793B91F422FCF53ADDA8F7C96D55E26244E075D9A70004642712EAC377CE18F88F2C8581694B8F621707DAB6D292179B2A95AEC5AD6E409D78253DCC05ECCDB45683DFFFB9C629AFCFB0654725D650E4A283FD98E47F37AA9309E2933CC0393625DD81D4A02F9D5082644DE02B6472D5D3AAE110747E4F756973FDFCE8EA5F997E30B11EBD50B45F6889D227D87D9184CBC6ED40E96DEF8B9236763C9999E21BFC1A74457FFE5E0DC2B16876FE04C2E0F0F47012A767A7AC18D71A7FD65F8647A7E1AE2D4D255492A18AA81D17D390E381B1722BC3C38BCCEA9D5E73231D0C6E1A96CCB47079E36C994E94AF9A318D67B6408BB602A91D8E9EC6499DEED0B51A9AE31D9774A1BEF4C1DE0E7A324545B2AF9870CD733C2195C5ECDE386D298C33D492937497EA5F0E05C377A4D755DEA9D96C61FE82CF6299EB34B857217A2C6733FED64F5DAC5F95A0EF2294ECA844B96CEB5163363A31C58C88428152663AB0A2B310B1A9E9027CA8CC0DB6DFF528F9A421FA826A86ACB4FD1D79C1AE6123C9E685BA66F5FF109FDFF2497B1A50C2E4E7B4662FA11FBAA305A960CA70FF98E5290A8C3A27B4A3CF1705C6DF4290FA64F3259FDEDE7A81CFDE4214230DFB9EFB20049E905833B5D48923C8CE2F8A104946FB3356154519D950998677C56C8B2C80471A6117B142E26C0345CDF0634E356D80C3BE12F4AB89EB41DDDCF98188EAD2FF420EED3FD9287322F24C62B21F430D5F9B8592CE1CDC946616111C91C667006E47992FE2D5A2AAD82F8DD1AF3C1B8BA5326220645885CC94E8B2B76CBFF7E161E994C0CB9E489B8A5662E9D420913AF34433F5BAB10AC72C5EEB9249F3C102E1762E862C13CC882D20BE16834E54DCC323EA89A133F451B70087A8DCDC5B518EEF087A571B570A7966F1C49BFCDC70AC05034D1DCC56EDC2C0F57D1AAF16718C67D162BA330AA61A2875F90E2935752BFF1EC28A79EAD1AC18E70A833946CA6A15D8765E1A62AEF46BED232EAE89DBEC278297B396CF611448C5FD4B36B95CDC54E3394C63B9B0969D6488FF1C700B390E7226F99A945306C6504958CD43CD3D63910A4324BB662A0E5DB1622D90CE00E50CE7112193872AAB5CEE0B8D6FD42F26C2FB87FDF99062169C0BE75C85109D4E209DC8A640FED3EC71EF3DE8878B3D1729FF118F50F8A33361C6F707F6011454C5D744989EC1BEB644FCF99CB2E7C3CD20E6F1656E07C3566C4DE68593BCBA0EE9F7BD2E272C3D47A3E03985456F18CAFBEBBC1DE74964BECABDF3E9BBB9A10B29BF3B458FD50F19D63A6231CB51CDE3DF46E4BB6318E81E10AD1674A053C8CFE1E72853FD60E6E642642CB825644D6734AFB00329839F22CED734FA1421C4334E20F2ECC8BBC2652004203B3B639FBDCF5FDA1423F08C3A1100655E4763B8D8356A151D702124D30FDD87B34EC4D34BBB3639464E44A693690E193329 + +count = 61 +seed = 09B8441F47235EFC82D71933A0037FA4F69124C3BAD4EF6A3A7178B417A3FDA874081B7EEFD7EF1BF234C752458FBBAD +mlen = 2046 +msg = 92D5FEEF68737ECE61C6E0078D77FBAE97B0B9235F40B97099C114B1586E107B5ED1308A8A2D20BE41AF129DA2E0B38EAF02FAEF733C7A1D1A387BC55EF008530ABC22697D0465AA3EB71F41EE72ADD236CEA9A25995F3689C5A451E2F03915D96ABEA10D356D549D68048977587326523CCD71C05FD57BFB3C7A853F535BEDDEADFB84118F6548860F6BA536277DDD7AB42123E93381A385FA3E6CC023C1458A9F94822D93248F36C48FDDC972B5D6494B26658440FFBC23B57363F3D82CCE69FEE4747A889E85343288D55D30FC54D2D0744744DBA9977720E8EDD2C0ACA1FC51B0C6A3C68BB9BB8DA0385DB1CA4E9CE660CF7EB2382E5E95D2AE19DEF904A8651DFAE53A4D0DC4D057AB1A506C3BD7E1D1EA3FC4623E7D7B410DCB312F037B7A5FDE5E0E604FC33270FAF1FFB6ECB3125DDFA5C49F25BBC98238C8AB1B903537CD67238995E81B814280A4CED61513D69A2178086D505F8DD1DF7E11CE66AE33D4C982F94231957031A258E0EC745672A57A5CE76D1170111B8882A9EB5388094EBBD53EE9EA1FCE4A275F9D7060C8DA79018487B452817280C63B01B05EFBF897387592E2BB3BB486FAE0AB09F46D9F2E176DE96C59992C10A14EC16EAC36102B1D15541607075E67C842A888C87B268E9809148A323C423220DC31566B62F45CCE1E2BC1B3BF43B87C998F00023890BCE517271BEC16EFAA33F11611FDE87F197852BC2E7A2B44F8C72A6F79B22F73BE0611B81EFE09253931545D2453939C46B6797CC5DC5A8F1AA3BD8456EEEB84EE76DBF2EBF32598750ED10670DF422C7D7993ACC55F657E6E1B3DFA1BD6C1CD55FAE97E69D2F8F5AF368F7DA0A63B4065EB6D8F02B19A34600252FDFFDF4ED8DE2EA9CD2E74D63A6CEF29BF02F92D346ECB9A61081EE5AC811F33AA5792F6A1AF570A8B0846F3E6EF38452346DD637B19ECA37BD1A6C42B20A5BEDE9A5DE3C9F169D04D8C6CF5376D3404F0C21DEAD53DA6C169F390EED7B5B54DBE47CCE0B2AD1179EA8FC80FDDC7281BD4FE31B9A26A00444AF0B4D40A1B72BE37501308906149DC6FC5CF02B6F60AFF82B975FC8F146961EBCCB4D126ADD524A9B33BB16F6A83C6F3727A72EFA2BAC116E493E07B2CA718A63FCAC8E9D52A1B61479B4EE52A5ED30FABCEA4D01A792A92676721286814F3B0F4E15E23CE0C5D59A0C3EB8573C0A2F66C25F2EB2FCFF787324721004979BE5EAC505DFD39F5538E2C1B2CC12D20C1C5CD87299766361AEDDBFFF743693081842378744879E6E6371B3FFA9DDF34966FBF8DEE91B7EDF6EEC3E4E2F410CB5351F847646C22AB594046DED63347D04A008FBF6EE9696C638ECE73B39A269DB239DF36443868AD44D26A5C40FC92DFFB008E436E5C18907F5B18B5E6C5900B41A9801DB070D2DB651187A4DA7E2647ED3E9B6E9781627EB576BEE8334374468760DD3B32985D42945D953D434BFD80D7F7BA537265FFCF27DB0DA1ABDAE89BBE94D98BC9CA197E41C0839728F964FE4CE30B8CC43CBDCDD9CCBE06FE99DEBC6F4024F3F00D43FEBCD62A1822A6D507337EE79D4517AA486870602D4F1C5368B0EAA1FF6C011A9A953AAE58C75BBD3DC78D263A578C75CDB1AB324D71B9A065A9AF3DAB854189585C68D499AE8DB887745E20AD9738705B9D2F5D429F12D6462E5E2EF9FFBA53CE2F4E75449D2A7DBC3C818E61DC546175A6E0C10AE631DF6B1EAE6D134C08466EBF6EB5F8257AA10EF8C6F27F4295F7EBFD450629F3EB4E0F4BE247AD7F5E80703B1247A4FC277311D69E5D62E0B0201A805CC4F1F807DE99420D563A703493AD35A56B2B2DC237112F5EC21C70BF139A9EAD8F7E921F086E001B4C449E42A0E3AFCD5BC757040A2865D0E5ADAF98E37E6F8A501FF39CEF0BC364EECDFFD03069B81F5E1978C397862FD56362835C059FCBE4D8E2A957FADD7D05BB195E21AD67B429621E1D6872DE2D8BFDC91544F9E6AE8C164A23255AD0E00BCB21456F8FA6AE018F49605736C81A5AC0945E2D965F1493ED5BEFCE512AE93AD91DAF6F5A151D6C9856DFDDD1F877945D932261DED67AC8231DC3CCD0B04DC1B02079C897601E363FFB9A3BCBBBDB0B0A375E69EE4A7135C094ABDC237FAA2E5F82D2556290ADCF82ADBA8402C4FC9D0724F15BB87CD7A75A1A7BF826896D8EF63C7A2A3C371756AF638706270652C376100EC42FA55196DF332820D377760448D3E7ADC42E9F5D8A7074BD0FA97433B0E2C501252DE6939AB948552663A17DD7FF05430FA76E29F0519D650B86FBB19FBED097143FC242573E3E6FA4BD4A2EF6D9CE6932A066B4F9FF935BA9BC26FC2E5031C20AE30A52970A2DF3504576108D5F26517F8577BE61E6AA9D192ED62CF36AA641DA0D274B1ED5EE864B549154EB4115658E6C60219CC5B2E22C49CE3BA76A85EFB549117E1207F6DF081D0761421262E352182239F1E34EDBEA4BCD8FA0027543824DD58A20324FD4CFE943AAE5E361C367B22F587E2F9BEE841E11875B026F12B9571512F72985F98F6D0C212DF36A60975429173E317F6ACF72E621F30654A6DEAEF9E9E455524BF07FFDF44642A1826F734D69F3EEF4D52F26C06376C8F71DFB65A24A4C57D74B5976950AF3A57B4248909524BEC47D858C69041EED34E0ED3B111BBC117AB112BBF947D646AB3B7172F5FB726DBC53AE37956E29F5B6B1E3C90BAF4E4FA544FF63815FDF4AC9A2A80CA0E8722383437B9A02F3AC538FEDA7A6D6C1635D3624A385D846E79E956DCE483B89C346C1287A1A7293168D8A885FEB6569EBDF3F47F8BBB50AA43941EB20001959AF1B9B358ABA13FD9BBC596EA42A9774A120AF091D544E79C50686C26B4FEA396BF1E4C25B8EE4929D75569A5FAC521C77B +pk = 6A3DC0FF5041A75E88E10871B4D438C0BB746C428F5B9DE75163624024DCB47E273811B5AA210697A1B4D1227C57239722E319A221196903887D1FF1F06485FEDD30148E0BFD1BD12A812CC8362C1BBFEF7845C745603DD58708F31171F73CC9DB657AFA582FC0043D39FA0A54DF397B0A193CB4FC4D15FA8663DE39E2695124EC55FB4ECA311ABFA615B56FB30BEFCE926A52EF51B29F9B44DD6961821737F7E4701485540AD14ECACF474AE65ABE9020F2E81DA91BA2C4C0935D357FD866D2B283EB04D169E963968F1759872425CA1B0955482ED3751396E43CEE6AAD70E3D229447CB2B5C2706FD1013F4F23F501D7B166CEAAF55CE4C4CC0C71FBED72C9A6F1E8F474913BFBA7F3246451036A10C82FD45EAC280F2919B8E57F01348925F244E454B606082C95AC412B77FE8C7678BAEA8C20369A135BA66B2A028BDDAB2CD6D3FB8E4170FB1365E91BB099353FFC8EE391DA5192DB19EED1D263F8127F51C1ED9DBDA90ADB5E71385B360B1D69FD8B85805D40C29263FEC95D3E54F2AFDE257AEADE16694970A71D1C0484AB9E03D18701F5E5DC96624E9DA4D1D951B3675B2116665ADBC1191346FFE6BCB61563F2047634970299677ACF5635D32C87AC1302E3594FCB1A0FC5EDB99A367F285EFD9D58C7ED6B9D7E93B978C86AB46F6AA7912FE616AD24D70AFB825B69EB72BD8D5D8CC21D45D461CDE6471373C63E9F5EEFDF63D41698E61CCCD427A54A95C7E738FC23F5313C05DF9D7B7AAA35E876C992E43C1F9FC7809CED752DD9B702AC32D19E2C17D3F98F35193555725F0E067EEF9399C4A14648A6E4FBE0A7F3C4F3F0E43D28740B3D7B4C503B2A1B5731240FF1ABFD91BD5BE9EA77477238505E5F4CE55274DE43D18AD2CA23EBC2868325AC19E2ACB10BCA10C27E8BE9A72014F3A3FCF60DB2A0A19C29A0E78B6FC1127B30BD34C8E91AAD6A864319D30D5F1B154E93017D9454E8421CD4E21C3A180F482B45E3B65E2452F1A90604A55014B3CE8721D9299FC1004280CEAC0AA02B1A0DD0229EDC102175CC13EADC913BF42609C7B707A5B80E13E42C031E7DBC6A055DCD7DF4C47723315DB4F93DE83D506C92A21C1A5DE52AC927F67DFA03D0D71EC6AAA6BBAA5B2E0D6B649960A60C8110358CF894785AE337248EA84685C900AD9F6862A3856E65E43492A0B4A58C5D8B46604E5E924747D322B134899D07BF6A47C0BF0FA02E26C077E983459D14AB377BB0235223A53F2514B4806A41E66EB57EC8FFC6D6919DB2EA5253712A7339F7A5879828BDE61DEBFAE39AAEE070B9ED8E831B058B615DD959E312A5DC225528BA1643BA9B673450181EC014E509E0C05EDA8DDC46D9B87C6B8C65EF2BB54DF66FB5FF0DDEE3D69F28CA16E98BB3E44EE0E99F9897E0BD8A0F1E6E8112897491B29D9907DB4AFFEA16544D57430580813C5C1FD69B935EE73E9C494AFE0095A34E5A56BE3EEC23BE770B32245F78D813D4F013C53BDE18A642B5DA5CA5C6F58B14A88F7127E9DDC0872D94F323A77B105149ECEE6173CFF4B87930B5F9A9CDF6762A12C431FDE3EF6C667801ECA1B64AAC3591A563F124109E0C06F1D87F1A7C6FEC06BEC756220088085B83834602D1FA4D452047345A2C2D006857C516323251AEF896B872DEC035891611DAC6AD19F8EBB6B1805116CA2338E09BFB6996C7AB448285B859BD8C05E0CB832AB92809CE68B503E49B254372B640C16745D5118F06AA4B7DEE4C85FB16794F62680CC4E5C8A2C6C10FE558ED8E7CD76B1F748741D15885E12AB3F357A56D4213BCF26E77DD23BF1EF34E09730B8D957F4BBCF3439D4BC262F20A062288711ECF809186F1E2F182A7C66214C5D7D0C631C5DF74A93DB1A12CB6F2ED56EC1962A93C88F23A850D52E1F201368D79B9B90A9DB2DE293E6C52FE0AC8B3B9FFA8B60AF75B5FB9E107191228402ED00BC5C005B5FEA596CF26D12F71646C65540E4822EBAD626CD6C77142A30241B9855BD6019E5D9AD75B450EC6CB4D74941146391867928DF445045594B97BA7AECB4FB9A32F534993C9DC6BDBB4881AAC86ED0167DD3A9C33B6E9434C26117D23449E6B698D87A4D7590B4C332FB8AF52AD5958A34942CAEE08FD99075A212DD43CAD2CC67B9E78E8BD740ECE44613DC060FB443B4C097C5F75F372FD80DDDA84DBBEBAF52F285FA4166AD2AFFBA138D52E49F990024B87C032B4E5357761CA9D3EDF6961FFEE6D45480A5FE4CD4BD26917254BD3911FF81E943F43BDFD69ADC2A58A0C76993927F4DF311815B0CC702186E83D184D29024D8CC8FF77151FCCEE7943544EB5D9F4556163AE583AAC8E6B8E06F94187E2A4810724AE70802A9AE56C5B3FD3CDAD7249DBDBCF9930E95476B92C272962B0EA5A96925CA4A8B1552F40C15BD7A37EDE02DCA32FA1BE31DA682B527489B3189D0CBF7985684CA6E55BF3F5CD71C974C7A317F2A8D08EE0889B213DAA4975818B2F4F8DF86AC038C1F86E9277AE97BE867C2DDB6B946EA3012AECC26B727409FA9A20F578BCDD14D5BD63E74F5D55353C4E86BC87D8DE982A484DAF5EB660104C8788A8648F850DE3A15CB10159C867D079F7417A2FA7B63E0C07156F0C8E2C996BC9501A1E0C59B78DCC409DA6FAB0DF01EE0A9CD886BC70F5905874ABD74B51E1578C0F01D22643CE62AF5D2077A81A4B22A6090F83F1791811D64102C44440165C77D55B6A7D48CDA303FA0DA559AADFD4F1185F39CF2049EDF516C37F85E7 +sk = 6A3DC0FF5041A75E88E10871B4D438C0BB746C428F5B9DE75163624024DCB47E3E58D7067211073A42604904DEE1E90028899DA04A077D044D1065EAECCF1F5F70ECFEC2E1C8A7F2AFFD203AAD1EE84A24EDFBC62085C57E4AE56A08439B4758A37FB9813B4291FE050C2547B3902065E529300F37AB68E0CF4EBD04F63CB27713862024011245745536866426836234464186603516664202772707587702514116082734052663850302527460181086637785777546661681321581031452682626000760733757555231180327444714522154357767538612512176837825633008413305684825780007372371685150424073147518235502813201314267443814281387575460877682145730810804731517411562056312607640132133072283635746540638644537530054261638784147840030455645237242553230470776822510003126138724620447334684758383765274558158101270088202121541045040016533066801084707631758102624182025072188753755387428024748140017446561374163661168720244215502877132162147370335015244287584581045314387700710108885742618617502177205758033118130540236461386348458113848731308436006377607073280025322570260154052247173886668487054073671151404066221516083621026268538611663814042533718310013373585256357320245854125033276342044067868138880142217772470866720022106524755781247824655405171272332755880224750081367786112448736138764084702080656075730651555650201025557713753000656017487850211386162154512856813674577176075345211536687586706038570802567837771411843843846880335308534640210677541653265132454113165686125760668860688253774358182246611752073780366060150757217354553721347673565782561628652234808646041167480536241365185150741656520557807544568186178601311334208064312052805273351041732762088026765838611484060036134118836701678458736885580715784714000018045621868074687813034168453180573420352554760574815147631046842463578565145126433764853710525862830657338384484168613087181880146430858376836174701265142342808853216481124216230854013504326804172148636738141152565474676213657882643064471300088061364740751574612680153337375234057622108772860677111105033756817021100845011071817786842182177247716815132225215076218225467801564225555560041147774418315202318022376200408358426325040505821440822488014051052347756443125557547183752345431601117805362385765552666212086704115725460820864462380248835007230820215028172514625013604241316388736176032253575582883178407144566472413000627715007680306555137661836768487020778364636604262808738756122436283688858378725186072478202617714066665463345240073732554136225518437856764288347011013757768361854602087656214501716502112641816251227545020401104460762480437404716217875550724017733331267324608876154107308277545250633618324865848438885478867271708781362273715881877712861214274066454176526631211883387742271702410334641482400188154056226337306123658141156848522124065142664365034841372550681350763488774827786338804071217162086214077220541882131784505145108880441134762185476004450600485174426557531718561173305863614264232856026680844676182471351420714661604871330682173222437620705887426313701858846841324338164823281847850301254508271555743185488154414141320055246136028388485778545018652047341650007717610152261171014881200037125073163354341566724625317C4C0571B50C7BC83A4F589FC5F137DF203DE000306467F9A9D8B17F138C3204F8AD81625794130D7FFF9D6172C1310CC16AA72D37C9478FEEFB5CD635454E67AF14F2F8788A610D6C3F0E14971EB1B24590D11CBA442F520A89B86C5A099FC1BC68CCCE6F78AA4018F285459FA7AF48703A577816D421B359E54045F1621C9B1653F180FCD6A9F8DB32D4A37BF8D0E7F603C1AA3FD3C3CB01D98E30B8B435A93B57E78C2827B737AE2087DFFDFDC1590E122E1CE953DB7773C12526324FF1627058B7AD49AA0C560B60ED2AC5A3DFA784F4B082B8211E2AE20C63936DF5132C6A640ADE3C4433AEE9CAA2DAECDCC7A315CF12662FFECB9EE4AC7DC645F2EA1EE8685B49D1DAECF2B9E70002CC53AF53F55F4320158B5E521F8F6FFB16F091E63395554434F2CE6362E562FC0B3633CD79DC05B404722A6525637C3CD1C24ED06BB4D7C4D2C9097A354694FFB4E1C78D644184F94CF6661857F695EDBF25F5623C0226B3BF122187ED7AEBE061BCB20CAAB1F85B7DE862644E0DC07B1A0AF0E1C0D3423F672ECB890A17B73763516760E84E60EFCA1087DF0B5288C2CEBA0DBE40547BCA886C036680072A5F4E0E155F74C439193C3EEE7ED0BE90E2834109ADD34D9AF414715A90915ED66CB3DAFBCDCFB6CEB2A130D5ACF2618EBAFAB8BE34525393726B82F80C54030EDB78CC5CFB23641F88FD792B2FFD1CBEC5E466CFA58DC25DC7C87471586256C142A3656FC7E135164AB65C9AF886CD45BEBA1A974B19E835F35024894DF1EE6419012C832BC9B499E62077DFCBFA13EF6A96700687CD2EA11C93E485C92F114EA5036F68EC5A5E407D31AEE77CA0AB1EC96737B41E88A6DD9560DEF2BF80D5345505460A21C102289428BCE5C253D6989F37E4F793B7CA369EB1815994FD4678779C4902FC6790FA4275568FF952D6C109FE86736A11E813CEDF91AA00EDF3460645AFC9BF9C8CA0D6B3C2FD8E8664B3179DEF626717DAF65D18BCDFD4B98746B07493CE8531ED5B7655865CA608E3F890B907A074723FC3FC25EEA457EFD0A3E15772ED28E9781308A429985D39B6E091DE1FDA2DCE4C26A4F41CC8C2AFA23B7B58E5AC21EC7DD818B1991571F9B043557F6B4328F45F705C96121DEC1DF0E044C9822478DC418CDEE3A783CA29D5219B93D6E5EB1322D78647E7A320B7AE7DD4EA1A89696338A1E95E814F5E5401FC7E798B6B6AE8C1D40EB659A078007254E9B817743E39CE089A2F816DB563373B3AC4AB4245DB1BBD9E41B24855C13B32C434ED7ABF5BF1C34B4CB664EB6796F4337208279B2AF49505816EC6B04BD0AD1BD34B1CA10EF79994B80001F2762B2461F9F10F7C8B5DD0047C3A5A9BEEE44957FF86F0B72EE425FB09D9D9EC1E8FA04E7DC4F479DADD317DABE6A48114E07560078E9123D553E341EC8E9FAAEB46F50B317B5270F511DD5D42250C5B4AD9CA8C99A91E0BF91F718DC783F00ECDF1320CB1D518EDC704EE488DDEC1522954E932D838585162B68840F422EE39E235717B4BA9623EC9C95710E986AABF36583A01C9ABD5E9B95E212F226F83C9A3D5FA41F0301AD89955C66FB73A552200EF6510399B905CC99E495DEEFA61DE517C5B0A907D8DCB47068C1A2C5CB03408504213333B4D2696B400558C7F3C80925B8032D66DBE5DF81F6CC5FCF1025B6E70073911031A3AA55BA61AD8EA8BCB1B0CB0568ECF3FB8A0D8775E694C99AF481B3AB8BA05BD566515A34C9FC9D0ACC7F2F5ED647A9DB79ACE6B328602E336F82B6627443D45735FE846E1F45D155AA3608FC0A82ADCE76FCD29357DF2F47F418C3A5A93D46C7D9A8CF43A509F8CA7CF3C402FFDB7CE3C4F516F74A27C994E79070171D34C03923A1147B80E8C2AC899D6D22102BCF5D9A5DD09CC950B448CB5B279DA3A113AE24833D163A5B9467BC8AA47D3F16EF32238961DB1F0581DB0A99F93581B401DAB56798A0FDE020F58EC17E9C021A3760DD38BBDC34A6E7C2BC1CA458FE53CBA693F8AAA92331368BF8C742AEB26084D0B6DDEBC3A72938F87394C977DB476D610A71AD65723FEC82A4E6F947AC530146C1D25F8AE31FE27184F99423DD253CBE8936C693B30821A2779C18655B921929883FDCAF76DCB51AE24386959FD2E9C9A7AF5567D3F237F0D125A23B8668791D4F7FCE79AF801319BE8E9ED3FDB0F9BD30084C93E82701B8B36EEB4F038CA68FB3343E0F37AAC48C79A23F7104CF8F053B78135470CB1CD7ED4ACB97F2B858852CCF613C09D42109923B47D166C250A133769D4A3690C3ECCB65BAA9FDA69BD4667F40769E9AFD785997AA333FF13BB0BEFEF545C499C9C97A34BB006C5AD28B78217DE1D3F8184B54DD161DD48D1A304129BAABA430446066CDDA18F3422B650E5B79963CE1A5471472F27221DAB1ECC612987D99374FB2DE31E273FB5DDC9120F424D0DE5E3D7822FF97FF4936904A01C55A3AB5C317416707811B827BC43B37B099FD0918C0778F6754057E570783658DFE9DB5440A710E88957C2A1E888828246CCE710ACBBAE4271C4EBD24C7E52E5802C7464EC93C463514E2711C335A0C03BABD96F2964B8DD3BF006CB8CB3B07C3D6532BFC7A32766D2E8A7825A095FE61C9AA7B3F1B6D53C96142991791CF08C0404E68AD1E359F75733C94C1FFA8E0D9307A0B08C599F1D7FC99933C19F410AC5BC66545D0045AE05FBF7577525B4CD7748BB89721B2BD8474EC2D59211B19E7C35B2A632F9B12458440BC062F78ADC5FA043B724C60B45D8229E5AB2D20AC62E9F5096A3CA2D022E02F0266FF282331959F584685B27E14D1C108EB5AA599C6B69DF36AAA04AD59C2E376FB4ADEC68B422254EF2BD60807AE03F27A02FF30C4957EB6470C24EC761171581B666B59217B867BBE02D7700F6F9560E9E166BC5C10624246C67AB5B6EB831C2D576A072592CB6450E041A60B169541D2C69D0FA4FE1DCCAC47D26B3413990DE4ED950F56841E76B725193A3E446AF33AFE6E2084EBAE4218DA8B0CCA18CB7A041F2E1E05E4EC43B422338FCCCDDBA270A2F28AFA9640B79CFDEA4A9C3CD7EEF7FA4EBEBF605EE6229D648EDDEBAA274F732C5943F786B2DCA132F30EC10FBAAAA76B80E931AF6BAA87247C0DD1DF3B782790CFE6641712883509EFE1BF019DD8BBDCC4225C323B2F25F4D6DA785C36FB84EF88DDC9DEA7B37A220F6E24837AF8526865F3E2B6ABE4542E78C1E6673D5B3AAE379B27057D6299F3D5624215A1CE75976C063CBB310F071A39F00F34A8D36408B1104E78E02AE738BA1BB5D16288E47D131D721EDEA686BE0E7371C4702F9627238608B62F125E3FB3BB417033255D0BA59A86594999CB7AD3CC4113719FFD0179646DCADD1845C5952DD926F3275E178C621714CCA3D7A48901E3EC9A131277285F220A3CD3B4E30E126DEC020AE098F9A605D43F7CFEBF87F30D7AA0050C5F16A9ECDD1B7EC36751CC53CAECED0FB47005E61601BC31FC9EAB1579E09C19FD5B26BA376552394A380D0F5991584BC9AB +smlen = 5355 +sm = C774BFA98EE31D3BDAFF782313A4432F34113E0EB8C4F6F786D253DF7408FA5B2A4DD1FFA7D1460D4421106B8427BA96262FAA061A85B8E9FC9EF85AFB92B9A4A1ADB7A69106F8DEBFC117CAB30BA6F5C64DAD26935F35B0DF47C74B9EC2154D24113638E7AA3E161A40926927BE989223BB31EAFD0E3F15216991BA17C3D25796A552BA7E23EB660A548DD18980547A6F390C493200BC7A5767CE48D3BC70FC7D2D6794A7931C58A281E2F2D9EA8A5A0542C53BB651BC066FF242754B91CCE04675D6B248975C30AA705D829384DEF4B1B3657A4817D0FE7CC51B752BE66E0C454CA04402B32C8D522D3F78064C55A1A271CCE8EE5F68BE30539D617C310E188646F1D7A44995BEA42BD7F253E843EA75B4244A6C5972451F932E12CE81A4029B347B7267E6736CE80326D665E5B00AE1EB994D830AB3C55C45A16D0F7D22170B5BFF86716D0C89F6D486B8374747E995E04D77A383B66784B7512CD5B25B0A2D4ACDA8E7CB32A930340F932129DA9473D7F64218180DB242B69A85E3D870891830A3CFCBF3AFB2C1E8AA8624D5F00E004CCB79F49F32EA24989DB3B18CE23A25893C9A481B921942FCCCBA88881C1E1A718ACA8B2A62F0659A0CC78616E3240AF8EDCB07BBDC34CBA9D176B437D17ED728707F6A708DE12186FDF1EE3A0D10A33D0E61A6D409E3D59E1604AD8649F537D2DC5E830D3E406477F27BF4A10531073E688F3A874321DAC3FC93798869999E2DE15CDC35CEDD5BE23E32CB40AE904D87E0455582845609C63A98C08509EB3EA44FFA3FCA854C9F0D73DCB373B75139A8183AEC98363CB188A2F1956EE3A28F0330EE58E5DC74E653F75E5BE442FA2575150A2B8789270549117B90434FA190C33CC78F3AB6601F2A8A2C11AFAF8473773C218E4541C378984C19E53A9D95B6038B2DFA5C7C3F4E8C690140A7BAEC2E89FAE3CC7B5A06F23F137F2736AC24C84766AB5CF15B825230FD29D5BFCF3417CF66AFD182BA36D1C1E5B245124265AE7A7576134BFA64E34C321A2BE664CE4734BBAC0E5E793C38649140439E4EAC352B83D36288520463994ED2265433070F275447C9AAC17F4A7440E189BD4E58BBECFB9055D062A0CAC7DB00F5E464DDAF502AB8C75DB8986688C58AADACC77E5DE293C65AF0CB9940C096080ED7AE7A61EE0A7E3369B03130A3F133F244A227263502FBBEC3C862A0568EF978D4FC27B74674884B85E1862B7FAD9A83580DBEE0B6B16392D99A90D7FBD091AF476C6C1B0F3416C1A0EDDA3D09B25DDC9B4EDBB7D722ECBB30FA0C4F88C7DD565DF397737DA18C5C879AAAC2969A1D295BF8BEC5474925D87A86A1B3F75493D7F3D4C9F4B4ABB8DD4101D5C381EB872CD969F2030E0069B7AAAF3CCD849DE88D76356DB0DFF76225BEF3DA7DDD946FCA98391A95FEBDE420E1A65D4F122B7FACDCEED089B3D128E1BEAA5F36DF1C77DE8BA151914DB7FF5652E73A22B9BAD3D93439EF9D3C8DF0A2498D9B864541BF8F540CE5537BA0697B325FB8F6740706D671ADDA4751FDCD028155C36D0605C987D880A5C04DE45308DE93A9AF4063FCD88D04E42F782BFF36520EFD4E0216E7860EC3CE4A629013F3615531A25BF26D6D33C69E43C666881C2874AB3843D7A9CA6FC798EB936A8A91ADA7300124E455813DF0753A13C74404A3DD2A4AC42F6EEA7DFB0107494B29F1827ABB2A393CA97D66278477791713F2B331A9877C38EC2355EF189FFFA8C9172A8F313B8D5C1539E0E01F31381D5C84ADE04533F6ADDFA1E35B3BC53E47C13338137FEDCB0DC12AB36807E08497BE063905F47887AD0A87B3FC1DF18FC487C9863B30022F5B37441A1DC21B8EB8FFE096836B7B42F14BEE3DDED490566C46FC881EA1B45ACBE0085C976E7AB5C626BC23C99002755EB4D2864F92783A70C256116916BC25E739EDB94697780BB96E672AA0491ACE558311EBAE7D8A08BE9D4E96E346547CA278678A9629515D619790C530752E0619A5C8126B7460F18B8D3AF19504C6284FCF46D67B5F489CC3E2F123CAEB6D456537E13F3AF7EFEB179507E4F04EA7B2B2DEBA07D39F19C9116D57F71DF94E5C189857F467A344ECC29E9C4A383605B3F15639E5748A62A244C1E251046A45F1827E595A598B5B3E8F6A14D1955E90ECF6F0D4DD0303821AE3B8EF8581239207E392C0DA58385176CBF4E9448E5FEEF948432246DD7184345B91899743F673494AB586B4B85F45029D99045B1291ADBC81B5908BB2E29820FCC8CB79A07D9564ECF2E0AD3963537E873E7E82D69994BF89C5FA0A07F2646D3AC6343F8A0D5A1FAD3BE0A9C3B4DF242216D782B65E602BC4118A1907F1EA68C87F3A6354364ED4CEA685101E856CA4EC2C0396CCF70640D7178ADA4376330711176592A8D2CF36DAFBCEDC15F8000FACD4FBCF912988DFA00C534A672B5609933782F2D794B7691ABB33E9682D835A102EBC4FB9CDF958CEB7F4A2332745AE730071F62E6B19408ADB5257402E688C80DADDED4E12258B5528742959E91CA77C4A812A76164C28640B0B96C38622CBDAFF71E2B9EC35427227F71C1A210832644BF1121228E826B9EBDDDB03D7B39713BC92A63D64A5D76F055FCE7354B7DB0649BFDA63E9A51C70783F69CC2C5AAF6DEACC5410814CF79EA44B7EAFEFE389868FC36611952BD3848869EA76C72A1F25A1CB19FAD4A7245F26F97E5805044F875C76C24CB663FD4F2AB86D5625B900871E0DC5F6311DF0107170EE6C53D4D167C1F33AC2F77A754EA23E33037922E995DBAA0F79DE9EDA1610013B959AA7C519883CFA062416AEE12AF5C3E452F32E4C2A43DAC4EFCD3E8AAC9CF6BDE72DB1BFFD1E8CBD9A306D6319E3469C22BFA339C8129B6586801279BFBC81736D1E69876F78917BF10D9BDB0A0E1EE95F8E2C1304DD30D33CB1F34C6492B6E4812AE5FD291FB282D4BDF110F72F208A6D8D27F4EB447544054880F928C40831D9877ED5F45D9DC7DCCE79419431501F04F87576F5C516203B347F983B0509CCF3FB0998158648D49932D42849778F45679131C2E584D74C002150FD2370BA454D9630E595B7BAE9683A8E5F817A1EA60D76E7A2B007180F95E5BB2076299D54D425C91C7654D287F05231605BC6733C886527C7A6CD85E88AA5897EAB3E1DFF02225A8F0BA459A3053ABC01D65DB12204A43B6F41E4BCC2691B7A84A0C0D28C0E36F9B7E5AFAC19A3B142592E47C45A5FC212D55AEA98E81FB11ABAA8C9B072E30BA3DE878FC4B8B49E1A5EF9489A09320F127A1F4ED768F2EEFF0B22AC89A455E0BA7CFF065183AEB0BE39F402917EFB4DBAF0980A33B313F0B7AA081FA66743B423B0A921004A1CD1DE281A62860206B42E6E58CB126EA176EFF79BCC8AAA59032D948D2672DB35E0CEB3E5A03D8BFE68EB1CB8849F7EAA50A9805A4AA538DAD9AD00472F669D601493F2068244FAF95040D5DE44AF267C0122627F77ED605AA25FC205456785C26915F7490A97DD7FD195215252EB5960F62D0B61BED957C7079AAF2B0E2D129FB35484BE132F9A32EA95BFC9AFA9EB607ECB91A728BFEB37C681CB1194EB57CEAE634FB31CBBA4CA25F98DD5E1ADAC9655A767DDF5AB6EFAF6C791FF25FA3C3F5BADE295526EB4E8DF679BCD15D0F9DFD10B7AB1189AF365D4FBCECC240D7C67695153CB951F0BFEF3C42A12AD002E2DE2CCA76A9B781DFAD858439F01B0E8C69807A182ECF12911215CFB9D8F52A6DE4CD66216C4F27DDA86783CD8E38F354FEA0A67E2E173E2CFEC8BA90F3E4E737569EEA3943552A745E8D34516561312420167BB7A1C132B9B360F26578A628E8048C098BD4F5AB36E56098E23A2BD9F9F09A45F630E8381849279FA15BF59A3EC235B78DA4EA41EB4AE04F57BA914BF607979C18C68EF52EF40AC97906C7468FCBC3055480116AE280ED54C4073C4853C9A7BC3B3B25B778D36A35073BAFD94FA7A36F0D9723F0096B1AC9EE9321F1B440490CE40645F5F2DBF15FF4D3C03E74D1391559BD66ABF81BB8296D1643BB3D7D68BBBCD01B74CB831F56A338335F564FE58F08C2A240EF607B0B56A1B0749F57E8F790763D2BDB74560AF17D554DA31591151B844BA35A8D3C64CFFB1CAB97F8D9DC42A2B07A6E6BE709A1893D571C10E70C11E197AF83A7D40B6777C2FA6F0109A957893D32608E535F6B52FECB4267C75173061E261BC05D805CB39B295C0FC55A2F2256BE9172F65EB878776A65BDF946E87808DD267421F38A265028F0685CFFA1DE882302F3851DB6631264593D16AF9EEA3F8BCB6B8381AD58C36CD3AC9EBBC3EA08DD3302F2BC4999046C79FDD3A0739E0C82BFA017EF1EADF46F728445DD9519446502D9B67FA8B616C54280E84212592877E717DDBC0B883550AE49DC90F54893BB8ED4545F93D0982DE054A28D376535BB845D39E651E7835364E3BFD47145723D6966CF1DC251D87FCC4ED4438E57498DD2671A70235BED8C1C50C807EAE3B7125C1F288C979D4C499BDBE7F6BE926210BDB80FCA3B2500E937AFBD29E262A9EEFC7F880A6B2F36AD05AD615A85F7DD2C557777FD5A9F3DE137291C73EB1BD1C9E0D003AA4B2ECFE2F4B789295989ACB8C83FB0A0FC9B8C6CBEE00000000000000000000000000000000000000000000000000000000000000060E0F11141892D5FEEF68737ECE61C6E0078D77FBAE97B0B9235F40B97099C114B1586E107B5ED1308A8A2D20BE41AF129DA2E0B38EAF02FAEF733C7A1D1A387BC55EF008530ABC22697D0465AA3EB71F41EE72ADD236CEA9A25995F3689C5A451E2F03915D96ABEA10D356D549D68048977587326523CCD71C05FD57BFB3C7A853F535BEDDEADFB84118F6548860F6BA536277DDD7AB42123E93381A385FA3E6CC023C1458A9F94822D93248F36C48FDDC972B5D6494B26658440FFBC23B57363F3D82CCE69FEE4747A889E85343288D55D30FC54D2D0744744DBA9977720E8EDD2C0ACA1FC51B0C6A3C68BB9BB8DA0385DB1CA4E9CE660CF7EB2382E5E95D2AE19DEF904A8651DFAE53A4D0DC4D057AB1A506C3BD7E1D1EA3FC4623E7D7B410DCB312F037B7A5FDE5E0E604FC33270FAF1FFB6ECB3125DDFA5C49F25BBC98238C8AB1B903537CD67238995E81B814280A4CED61513D69A2178086D505F8DD1DF7E11CE66AE33D4C982F94231957031A258E0EC745672A57A5CE76D1170111B8882A9EB5388094EBBD53EE9EA1FCE4A275F9D7060C8DA79018487B452817280C63B01B05EFBF897387592E2BB3BB486FAE0AB09F46D9F2E176DE96C59992C10A14EC16EAC36102B1D15541607075E67C842A888C87B268E9809148A323C423220DC31566B62F45CCE1E2BC1B3BF43B87C998F00023890BCE517271BEC16EFAA33F11611FDE87F197852BC2E7A2B44F8C72A6F79B22F73BE0611B81EFE09253931545D2453939C46B6797CC5DC5A8F1AA3BD8456EEEB84EE76DBF2EBF32598750ED10670DF422C7D7993ACC55F657E6E1B3DFA1BD6C1CD55FAE97E69D2F8F5AF368F7DA0A63B4065EB6D8F02B19A34600252FDFFDF4ED8DE2EA9CD2E74D63A6CEF29BF02F92D346ECB9A61081EE5AC811F33AA5792F6A1AF570A8B0846F3E6EF38452346DD637B19ECA37BD1A6C42B20A5BEDE9A5DE3C9F169D04D8C6CF5376D3404F0C21DEAD53DA6C169F390EED7B5B54DBE47CCE0B2AD1179EA8FC80FDDC7281BD4FE31B9A26A00444AF0B4D40A1B72BE37501308906149DC6FC5CF02B6F60AFF82B975FC8F146961EBCCB4D126ADD524A9B33BB16F6A83C6F3727A72EFA2BAC116E493E07B2CA718A63FCAC8E9D52A1B61479B4EE52A5ED30FABCEA4D01A792A92676721286814F3B0F4E15E23CE0C5D59A0C3EB8573C0A2F66C25F2EB2FCFF787324721004979BE5EAC505DFD39F5538E2C1B2CC12D20C1C5CD87299766361AEDDBFFF743693081842378744879E6E6371B3FFA9DDF34966FBF8DEE91B7EDF6EEC3E4E2F410CB5351F847646C22AB594046DED63347D04A008FBF6EE9696C638ECE73B39A269DB239DF36443868AD44D26A5C40FC92DFFB008E436E5C18907F5B18B5E6C5900B41A9801DB070D2DB651187A4DA7E2647ED3E9B6E9781627EB576BEE8334374468760DD3B32985D42945D953D434BFD80D7F7BA537265FFCF27DB0DA1ABDAE89BBE94D98BC9CA197E41C0839728F964FE4CE30B8CC43CBDCDD9CCBE06FE99DEBC6F4024F3F00D43FEBCD62A1822A6D507337EE79D4517AA486870602D4F1C5368B0EAA1FF6C011A9A953AAE58C75BBD3DC78D263A578C75CDB1AB324D71B9A065A9AF3DAB854189585C68D499AE8DB887745E20AD9738705B9D2F5D429F12D6462E5E2EF9FFBA53CE2F4E75449D2A7DBC3C818E61DC546175A6E0C10AE631DF6B1EAE6D134C08466EBF6EB5F8257AA10EF8C6F27F4295F7EBFD450629F3EB4E0F4BE247AD7F5E80703B1247A4FC277311D69E5D62E0B0201A805CC4F1F807DE99420D563A703493AD35A56B2B2DC237112F5EC21C70BF139A9EAD8F7E921F086E001B4C449E42A0E3AFCD5BC757040A2865D0E5ADAF98E37E6F8A501FF39CEF0BC364EECDFFD03069B81F5E1978C397862FD56362835C059FCBE4D8E2A957FADD7D05BB195E21AD67B429621E1D6872DE2D8BFDC91544F9E6AE8C164A23255AD0E00BCB21456F8FA6AE018F49605736C81A5AC0945E2D965F1493ED5BEFCE512AE93AD91DAF6F5A151D6C9856DFDDD1F877945D932261DED67AC8231DC3CCD0B04DC1B02079C897601E363FFB9A3BCBBBDB0B0A375E69EE4A7135C094ABDC237FAA2E5F82D2556290ADCF82ADBA8402C4FC9D0724F15BB87CD7A75A1A7BF826896D8EF63C7A2A3C371756AF638706270652C376100EC42FA55196DF332820D377760448D3E7ADC42E9F5D8A7074BD0FA97433B0E2C501252DE6939AB948552663A17DD7FF05430FA76E29F0519D650B86FBB19FBED097143FC242573E3E6FA4BD4A2EF6D9CE6932A066B4F9FF935BA9BC26FC2E5031C20AE30A52970A2DF3504576108D5F26517F8577BE61E6AA9D192ED62CF36AA641DA0D274B1ED5EE864B549154EB4115658E6C60219CC5B2E22C49CE3BA76A85EFB549117E1207F6DF081D0761421262E352182239F1E34EDBEA4BCD8FA0027543824DD58A20324FD4CFE943AAE5E361C367B22F587E2F9BEE841E11875B026F12B9571512F72985F98F6D0C212DF36A60975429173E317F6ACF72E621F30654A6DEAEF9E9E455524BF07FFDF44642A1826F734D69F3EEF4D52F26C06376C8F71DFB65A24A4C57D74B5976950AF3A57B4248909524BEC47D858C69041EED34E0ED3B111BBC117AB112BBF947D646AB3B7172F5FB726DBC53AE37956E29F5B6B1E3C90BAF4E4FA544FF63815FDF4AC9A2A80CA0E8722383437B9A02F3AC538FEDA7A6D6C1635D3624A385D846E79E956DCE483B89C346C1287A1A7293168D8A885FEB6569EBDF3F47F8BBB50AA43941EB20001959AF1B9B358ABA13FD9BBC596EA42A9774A120AF091D544E79C50686C26B4FEA396BF1E4C25B8EE4929D75569A5FAC521C77B + +count = 62 +seed = D2629CEEAE5C95D3C34C1FFCC2338B4A97782BDFCD39111E18540B69DB035B352D012857111F816F03550BFE5F56ABEE +mlen = 2079 +msg = 7F704CEF1C510BC2CAE9B70FD248C656226BD5686D366528F0D0BEFC0A8761EC640CD2DA7979DE5EEBDF6127F29ABB8607F8A3D3BE05BE25AACE7FEF3063DF28E22A522FFF0B6FF6A0C61F79B02A408E8E1C775AB80BE6841E9F8A9D030AE5518E3EA8A4E31E416E087D47919593598FD58122A9E601A57EF02DE183D56921811AE2253628125C24F93C84361C5EC99E7B16962BD96CA190C68F3AA9DD60CE3AA7610589813B4FB77A4688308D9BC72CBE918583E298E03AB95FC500209C14ABEB3A43BAA92DCB11CB523C4D17EB9C6697B56C8B61EDA05BF5789166F839291CFE2997B7DD462EDA69B0615F2AD82AAC0A32F4B30FE8725849C144A9C07799D6CE9D293C25D8302161757B8C8C8D07032D914EA7DAC275919A1DFA0D3348EC07FDC70266975722763EF85EC4AF9E14288C9659907526566BB3F2DD5DAFC0D422568CA3AE52486D3F2C18B667E5622BA7E52C56BF00F82AF2108CB4949A09179544F30758B7FB98C49EA160720991B14E2858D648F0585AD1BB1D08294F029BFE936154E9D328DF2E054004FC5C29070DF9EE50DCD0981D2BFB3AA7D6F637C4CE457C0C66D27E2670107A2B85D1F026BD970EF3FB7E32C60218D5E43A06D9CD26289A937B4FBAD2A831425728F3D0D30C6C602AF4B14411E9B3C7CF0B4D630614A9E03AC30BA2B024D496DA984D08854F1366012C2400A5C8268C2B126DEA5AEBA0DE7C92BE0AF08CA22E02604A753702BDCD642BBFA0CC91BD8375657A957306A76B6F139621481B6F15CB57BEE128954D30F552661F906D8AB42CF260F30F88993BB40C9679385F5C4639888973361216DF3C60C57D9B250F64B7634C94DDA3FD122713FD2405A7B71F476C263A781DCE271E7D0665E45DCB27F7293DE57312396C58C40E268F57ED856F536C8FEB4B0060488DE3C25949D2B7E64207576641B34920D04B46766AA2978D9352C2769D49F8599F3D0439C928532E0EE428A3773FA4D68E6052335C6D93368E321D750D296799FAF87B82C640A6E995D18DDA002887F141DB8ECE2584DA2FDDF848D38357D585CD619B1625A70A5D333561D6DE856ED9908D1E377EF7BE03B326594808BE58F7FB3939E939B73F11DAB3E572DBA41D43A046B8D2BB521728222D5A77DC886AC6F328D9A531118156D791D64F5DF8FF8BE8DCA32EABC3CB259B0F72B021CEB4DB36A6CD2FD149437B251F81F7588AE921456BEF1A79FE83447D80CADDBF20895667CA0E493A4731EEC901E03F66DE284400A5558922AD53D4E0FF7BC6C61640ADE0274C63D94E96BF6C642B790823109F53C3C27130A1EE38D448239187F5009373BE328AF866A9B8DD1BB735E8002296043C6FF641A432709148C707B900ECF46555D77644565D5998C096756F79B6F0E20850B8BF0528E78BF5FB4859BD655227873D289CCE47FEDA8414D09ED7E8D380FC4D580C7F44B01521E829E7B0CB2D2F345C517B65E2D476687EC9A4C160A3AC0B01CBAA588644D799B125910812790F06C1ECB1F1E64D5CCF92AE5E8147C98B0CFAD5626BAB5115844198E8C2AC1DF9A208FCD2D2891F4A29009F5B36D8E31383811A9493CF8E143B5AC8A14D48119CC16D2C6BF6826FC47D4B782FFC76B64401B8249777E32C1298606553DACF386A22809B599924A635796A1AEC3CD8568064852E54C95AD887D7AFE837F6FF676F69EE6288879F6D96193AD94A0418BBBA2EED5355876F2C3497448A5F8F3F83B136703D9A38FBB62784CC233DF448A5E88EB5F81A0BE97A16FD4CABA1D87A4BFB08E002EBA548F662D496A1478BB7C26C69CA4C100AA6872A4945D703CA812BDBA53AC86010AA1D2C53F29E46AD095936FF50DB8805DF4B08C9580AEECE3A6DDD828E7B5D4DABCAF112A6E35AB3C28A6DDC4D98AD1063C2ED72CAA50086E6B72090CC1F2AFEBEC6751F27EF51DD8557E53D928535D82A220F62BA0645E3C2618F3424EA1A339A138C9B8E26B14BC32D1736A4193C0C72CC402C3EAB58817335C1424BD6F38CFE16338611118B4100E4038D07DCA041C72E485C5290F0DDE601565DAE9CDF657A4C7839D3ADE72986AF396E767430125786E219BC5736F16FEF66B4014E5961CFB4CFEC4CB2A32205A92DBF1399E2710395BA1240D48277C120526CD9E2352F7D04D89CC2754379CE80A2CD1AC765718B8BA61EBB8BC6D0D407022E7AC672065FC8503BF5BC4138520CAE233EA997463D7C9E00BBD852F12EC17C6F1DB1914446AA21E156D210094B699B4117B31EAE6386DC0DE1F55CCEC09AA1EB38CDE4602598D452732C5EF8B07C477E3E2DD470737EAA7357E2E8B74C31A117B519BDCEF79B6B044148A10468E38B5A6B7B10D74C6130A60A268ED73DC9A25ED68AF354758FA3F57ED3558DA654CACA7150A8E4449D0EF640184A7A33D00BA765B01C442E88D9B4257B93904ACE04375679BFD8271A03073E34C4A1C0437C4009A9590CB98D0B5581DC83407F04A22C9B0246DE38E1A13F9B1191493818783950548BE562F940240CDECD4A50C94E406B1BAE04B50A3A19E7923183E3FD356238C45AE6559193E0E846DF0FC6878BE6C963AA8C3508DC31F766A4B29C78D749C89985AB8F580DBDF7993A2261CC4BBE489C3BBB38C46739BD2516D3C64A93F10CF559DB6A0EA3BAFEE8B43F696A5288C66509A57C642BBEAFB40F4CD0649B4CE25B6FB2EF5529B73556051213BB39CC4F1DC8004B1588C8DE836699C66CED567998523AD3AC303D9E13617CE6C1D2FC4C35B22A24504C51F64155F24D91D0E8785B40912B3DCEDEDE71A6933B36BB514FDD1D3D843AAACF2C1E79A5216622C20036C9C999DAC3A5A2D43FAC3B23119927806F497B4048F561A2276FDA0302423147D35579DD4411416F0F59273429AC0464AC49B230E29DC124115D18A045663D228BFDAC9F57B0C5B4 +pk = 837EEC4689B69DF4925CD36DB4923131D29AC3AC1F4B0F055C8DD6D73E3E952D43F55B1A011080D0F82716F7B8A5D36ED7BD42920BD5555B7F869DE2895A748C9CCBA995DE87A0E207EB5516B8B9C58CC24F56531992C59167AF3982F6342812E13682FFFE5DE4D4DF15765A645318440DEED22765F3185FC1E2B2435CABF5A610506D8358694933AA6CEA08605727B2DAF2C5EA73E1108967A50E864E7E87A89A4C1EE7C4FBEA5FC03E5BB9D2666D55FC3DE224FEA5961C375643B213896716D3619C27169C46F26A4FD7BBA2144326D979AEA804A8AB81848415DCFB0081EEAE50CA3501C28D87B093D9E1EF4BCE688EAE17273C058360B1F97404FE44D27D724CC68D7FBDF6F4DBA6EFB4C8CFCE66D4AD6C3D384D72A82A53323854AECB19E3230C813D7E20D4F81BBDB0201C74EE44771CBC31D89B9A9B9E87CD14ED7D93483C7CC241FF8EC222A084FB4FEBDB220CC106251DB69B3B8A454700B176F40202563CA4994469248D5CAEBC807B66D20E130758D5BB7BCC39AB1574FF45A7432A5A0B0A612BFE33FBB6B7AC2B9C25CB48EB74DB6FDAEADE54965366E5311E068C8D42E680E349D001E1C3F2046002197721F42FF4493E32FA5C1B07F4645BAE082F1AFE170E53499D1854D6A230782275D079F006148B5A4D3D86F88E7F5C87D80B727F4CF504A64421BD347963753FE8C0E1709D9E6CF74F8D967472879124BB19D56E032AA19436749F92A68C45EE50BC29A3B349BC34A62E14B9AB2FF59226B92E98F2D83F567633981C5907D0206C195CB1B0BA2935FAFC341DDFDA9A54635A3E1FE1C9041243308853683F86F201248A04A78583552E4167E11CFC4DB03D1C60A4C7339D3AC15297AA5401C757C388512AF21B0B29136AFC25B9D825731BEE987A7549DF5FADAF0C5B45D0F9A1EE515ECD6395D3C734232F9452A648E9527FE09E7E66B500109AAC3672FFC42CCC79411ADE255882B6047B43D2E7F5FBA3A246996F0E1E12AEC50096C15264DDD8E23CAEEB0E01028F6345C1F69F3DB7E95B544E7836E9BA564727071CEB7BDA6EA427702BBB5F8457B453A32E9197B48D84523EC55D138FFFC87992E0FC886819B6BEAAF5007B19C4470CDEDFC83C5BB30ABC23FEE1E5A30189BC486B1A2D8BB9460AF9483473E55236467CD6787887971E7693E3CDDE8A6579F122C8E8128AE76BD573408FBD845143045007685108988973C98DCB5C5363B321EFF92AA1D4A2493389E3605E96F4E51D0487CB1F92F289982809296A19A60E092A7012908EE175DB0ED90C9B244C85F2CB7543288C9B9CCA2EA9A58BC87982139CA2CA1816CE2CD96D010471D12C5ECFDC16E2D8D841075740C67E5FA245D4BAB927F57165D2986B87D651EC483E695D7D6B6B1C4B0EB9ECE583B29E7731F762AB29CCC33489EE8608E0EEF86CF8A2473E72F182F6ACEE44B74DF026D93823BE8184E976CA862C2AF14488BA8823AA06B146F132F799A273A00539F2ADB0CAE5FB6C25053C5E2109A24B7B189740B7C9A74D4BCB1F99A5B41F7386517EC3AC37C9A1231C17B65E61E5091AB97491669D1E36AAA01934DDA5720A6E557B9C108AC17D34B32E27C5CFD08A508F25120AF06C5C79A0F772CF38E99EF5305924B1B0F59C3640D8DF4014B07DA5B013B03524AB37A3AC0869146EF549EB9B8278F076ACA5535A6EC7365DCB6CBE276D00689C663110A0FA51F4EAF39ECB284E1387148961F550578E29E67B2CCF7D2FF63ABCAFF54A974ABF3A7FCEAA88B57B0F492F49D0167A08EB706AB0377B81843DC5E953485C0D7D2DBE617CF6CACA31590DB5F61F44D470883FC393D3F48BB94C388E086C12B3C82A8D4C0EC604A509B6BC1A5FBC19DFB0A8CDC231391AD5703F85DAD113037BE81956E94D1CC5BBBCA190FD4D6106A0952657C9238FD2FEC2EE6098F1AC63E7CFC5B77B9980C0B2CABBA783C9EE18B53FA4804433CA1F6C6BF99F35B1B4DE4409FA92E74B138564A6AE24039B8DF668E8271287B8058DAFFFE845BFA15405BC03B25D610FC751043FA7CE38EAACE3A1CFB7488C2A183E61D238A08E5F40231B4EB010EE6D3F6110E5BDF011A631CA7F7D4E87D5333F34F8E80BCCF7CE438D613878DA277596A37853C569C0BE516B4C1A99274D19F7340E79A4A05FA04AD7AD6DC1A43101F075B67D13EC33E8A2AE969C87CCD4E2A4472077DE6B56CA8D5C1EE28DF3FC39BBFBF25BE8A4C1F1D4EF0F298F594A31BA13DD540E05130E92B88CDCAC7BBD1E97C2164A5DE77D4912F5526A7794AF89054C44332E2F9ADA3649A9B12E9B92D041A6D8F798D8101C3D049AD6BCA0F88DB2BCFBA3FCB8AF297191E1028616F610C3B119FBF371F8A13748142EEDFF4DFECC34D55E3C8D11C0D44E5C5A771C64C13D0FD626FF3E474E02775FCDCE7064FD12351AF657E809699013BBE1B88B1D8A48B5CB202899BA0B5CC687862B1C016AF688A280A01B8A0CFD7EAC5AD6F13DBC0A18024B8496D92D705FC967D6A24AA34B7A12E855C529346966287F9CE7C2F1C249DFD4850AD95679A2BE1990AAE03153B2186B8904010C70C9DB3EF528875A27627EBEB7F40DE109DDCBAB627C541231BB3B162EB9B497A2E846235A708F2487FA172D6F42A61DE2FAE3AEE309DADE8BFF84146118A52695A6D9B67CEEA4E41D9B7F2F553027E50C1886E334AAC466DFA74AB04C8CFD5D7992BCD5EE0DA1F10B68E6744B7B4417FED6648EC1940A2BA8A4E7C9EE9CA9A4AB43E411 +sk = 837EEC4689B69DF4925CD36DB4923131D29AC3AC1F4B0F055C8DD6D73E3E952DC73014674D168C653CAAFF17CB31CBA9FA360F3C781BEFBC441A6927A07A2E02513A559D3BC9542930198D33F650C4B752E02113106E3C18C77D653A1E729387A83B613A60AF56D8FE38501483F504C08157A61207E7750B84473D708CD011C132847472736243450636760004620357512864143830434148623886244001146700337170164706563734687858313536716005704263634641000761603813877170421158380155034550308307610077663537027188535743362815005280084310626610033467466635458033423588825061740441208711380314163401351771716373486387183621352443450118643508215382087647060062001648533661332163268326281333563171058550242282664546215573263113855542212052751377101010138160307506242007620522530226778704688226178154072475384288476523323771867258870358368746275426548200063651642857466741605863735113153576105702152266261358227551884747335822105424686140331804706711108277547523272650228265421256410212416585642437565364846106173586322652825550644251701015350853750706614311541102604745210744240640550560577712105702243140152678312157262562404302065746838086176517017124078003456632440801848618428004086453187218377643612351456185430623016776221254526310460780702432233323420270234382047632854326367511251561250836410510655734136101640763360056285041177235234855563322740602611255178331118470713082564834031631175662470251885584754178662011452152284427717337724515111644682731638077826618548168266383826610180106775560033200383108488856160460023071104866507810101314436204843266042846274530051110856567473161108274605171755531420775660588618184702114151347376471032061208023835283173263184411457070868114678533351533412687365685102485834658400612723038310670225770132733658544624855244038518626455344506378556033215474227876628678854860633033366488600544423250121655150238407455534384205435775014447325530123337185640284302672126822045340474338661863754067360338578517356871654077366156111502027478660622540307278625358634628607266480007618047117031687008848016663552132573573851423506416371224802071478037560114664215286371563624533525881805630671405142642672236776170355540500026025180562855874817222151472015211841562788524435486504586151013154607232731808372508114323717311788144178362347522842122158467626672302678818037071577057166320320233562388800280436710387607843331725715074108847627820627755452862225175786581367318718070073740700520236222267825555757886518250478630778203161728256613062240633622328563764787622681767738743251558588078021308744211484484068577857104662854385027727246176552570423217325034756302141524262670210654875343555001445560010410050241357156282702233666848401206604013653562754514685044820424731374136351087523225657531800448542438154610504466557187372338533853614563455708783867242305333688450415426117284012545835517271077740070066586005411558646513500724815327032512608682307830636585010714701460141241864748815078625026653558431218762867517832852175530076215133118480622006054651270327314608004142127770408556234311204452702482086628707151451688480405002258260567851237835331433812203334052254438222073611614822526167483805052673128801F1015688798346EA6D435F8E361721D9E2F7CB0CD3FB68D8DD0FD74414C992D038BA3C3C64E0AA3D16C8D63B6AD7F575774F0F4C095DD886D6D21A5E0E334B9185D363EA4F1FA61689A8CBD0123BAF9A0C506DA31623BFA8DA6C41F29B0E372C782488842373D91FA3412673368818ABE526B2AD75508AEF5BB2B81E9475EB6EAADDA7E33C34E5A953F076D7F4E239555E27DF88248549C0C524EBE42134952641462E88A2C22F64983ED517F56619C9F64F75A9F03AC6E8CE443BA2C41C62AE7DE871A632FEB5984CD331FD4A33847F7FB72AE4A01CD880C4125370C208E1ABFCA52251AD066B46DBB57140E632847B71C6BE9EC17AAFCFB68BFF98E6A3E6A6D0A623244F39AB35DD0B359CC49B4B11BE6E1D8943DC5EC937913513B953DF924B6DE45E4BD42CF0B446FB272BAE35B3D2A7C8ECADC7A247FAED0A77D9E31E09EEFA2218DE0AFCA76B8BBA121047CC55BF922A1E8AE27E12236FA865A6A8B4E19CEC0BEF8F3F21569EBFFC2D5AE7BF19D753A25459094B436E5B89270EDA085D682431BA8268357B69F5C546631BBF7C7DC2F09993BCCE3A1D087E65CE3DA34939028747C399EFCD2B0E695AD2A82841EF32E15A2285605C37C29CB69903A0F50F384359EDC2A392CD62B096A5FFAB3E9D8B8C4EBCEF0537A5A61346E84D4ECEA7E28D17D70BDC3761E464EFF4731C3B480B58783F1B3739B98DE2BF28C2D7FD90372F3DB425399FBDFB5D4C531CE1D1558EA5682C2CE723A55437C8B89AF8E7DD9D33FB97B118C1D600AD18E5242108767592108B5C4A27E2768C846DCC1FDB7A112F0D4474B0A36B4F1300B8DDBCDFDCB33EFFC0DA20A6D8314D99ACF11292D04C2FC1660D195E283968F39321EB4824E4C4CF36631BB32EC40CFAB1D1779A834E511F9B57FB28568DC1D1D9134540D890770D4DB5181997CAE65DBEF58A488068704A9991BF0DF1EDE805A03CF7013E21D21EBBB7840F4415D449A0FFF94F2ED308A1DEAB295F1BF892E09C7D20E47BA779A07B24772ACE3D7A1B7B3D565B5F7AE29E4BAA5AFB6DC1613A1393945EC276EE2852E618FD49E14AF2787488DD61F8EEED58D9DE31324F96A6C914B5DF4290F9536FC62C2E18C7F400631C55C30B094DFDDF16BC497720D735CC0BED40B36810254C2506BB749532EC798D0A68DC05D571E79ADADB4A581F8576E021F230F374A21E6EA2A056E0997F64FD7087E84C505B2D19D48CA7CE327632C9CB317D27873431464E334DAF47EF0375B26173CB0B399EAA78A93B68AC9EA518EA28566A297C657F1D2FCA6111D8C524702F3CF76D06053101F0CD1D418977ED60D8457D77E1E90ED60988709FF7A5D2B1E97FB5E5C22C9260023C97EAFE6AC5BD122C918BC91EDD59A7672EB141AD832EA63F865512A9529554939897D6E50F823416EF408522B9E4AF74261F6E3C6D92388CAB9B19755C289FB228B8161F2B7F0E17EB6D2D1ABDE95FC201BF3D5F6D3CCC625810EAA5EFB4C08BB9A545B61EC5692CD7DF7413FA66279B0E3BF9593E3AA7F460C7BF04C6900DCC6585598A247346E727FEDD3DF0CB3BE49AE4A4A0BB52C9C5C6BE1723EC716E49FCE8D006D212777B3F4B3F7D9B10C8340FDE00A675A5AF3511657E0E7E4738FCFF98D9FF5590FCEE9C6B954AEDF31B3CB4C98DFAF2BB64E0AEF9479408CCD9751479B3004AD1B4BB47FEB863F100AFDE18581A848F244232551704F20C332117DD00340A5F3B9550F26189EF90EBB8B9CA11CC042E64CBA11745812C803A499E94B9D6C0BD52A624E1035066C026C7BF10EFB2E075BB797C00693EBD3A462E5901F6093BEE5D8865C5BD1C4C6D177EBFBEC6D9B2B6D853AD1CE8B0A70514C00798D5C97E49273EAB2DE8E00D00B096F35FB8E0843972506C1DEC6C429F4C731D2AD8244BAC58048BEEE8EDACE7A94C8A0689A337D6D87343D14CE4101A3F050DED0681E611B56058964D5B3A789F7BD923F2131A7A4A11DE37593ABDA41EF0184714C657C3ED29582CD2C99B5FBF0FF234C4655871644D395202B3A744476BF25514CF1BFDE04EBCB82C392167979555B600752BE0A2BF68F0470641DBFD9FDBA6C4F4FFA508C54AB3B9AD3A097EE90ADB8B4D7267C874472C2550328B4155A813C95747FE900E4B970FD128B9EBEEC7B3145C7E2A8299D09F52CFB175524CB70582B27E8E7942824D0B403637DF6CBA54CD34FDAF8ADD90C4A0864267DD280EB775737630F169B657324D23BBEE6BB843EE3CC946145F799E2DA79FA9EF4DCA88D51FC0A447D9E7C8A3929180D31E99F979947C1D609E3B062E487736C855B8B785D36CA2DCCC5674E397934D79568DA1E5DAFA1678CEFA225892E2D0B1AC7177F8DE4825A8EFCBBD828949F89EFCD55F4997BB8DE29F55B055FC18A45A954B5350FBCEC408438C374160CDE031AD623723DAC2D8072FD8E56A681CC20422CE4143F86FF7B49BCA08DC298A57827DFE3485EAEE7F897CA4487ACFD024CBF00FC767005E75AF4F9C90E74F6A87892776E26830DE2721411797AFBC97835A0D75F6A75BF227A43F7C646D6FFBC0209AA78A9C90D85852BF59A8315A6D15C95F9CF93FAADFEA4FE357F04AD3BCF798B3544D2E15D132D48CA5A4CA0EDF938AC799F8981EF3DB5AEBEE4278D387694B3354B126F351E13541A59838FB484F322C241492550D46619DC13B62FD87FA2E7E1EF7FBC2B964D85530E7A19B96538D2859551D104DC82E0BDF723C776B12DE0762E5D10D8231BBEED4D8C081BE1A71C94C8C333FA27CF34E2ABDDADF8642E0EF8D3BC76D658E701EDCC0D6E43D72A7BDF391C079370B6035131C87A40C533F335B3AAC41D7D948F9C8BBD18C8305DB842EFADAEF3E8F1BFFF3EF81FEB7CB07F9AD3840E0EEFC3D25F7CADECD97DC0903C59B974661CC3FBF1A601B15DDFF888733E4A8BDE7A909C7B3D8F4F652D9125A213F2E868891060EC7761D0A122434811BCEDDB8C724EDDE144319429217128346ABC59FEC13B4E37D32E38150E678795148D6D01EF7ED42D945DF6EBF885E1C5B97B68DB05E5F0DD7CB8AD04A831492F43C029CCDF013ABF1A9A143841F49E6B22AA4F6181420C61F81CEBCCD5C3F4D38390589B773D46D4B394D9CACC3110FBED3D0D276BC740D0474F5E9D5596D16C8604F2F0112858E6216B7F3F51059DA7E4365625BE348FA99F8F035787A048668228A26D0EF55E57AAE67EC132E807EFBD441E6504B8ADAB4D5E38A839ADBD1C81109F24E86E4AF3584E2E55A72E8B0E086344B9FC4AD271DDCC969E8EBE82205884630EF5212AB0065F497A9B226FA0BC022BCA81A7FC6B1203ABD90FFB4396EB3512643B2C790AE46A94772361B2808BB6AA88C2EDD186E259C627DA1ABD8F8F2AD1731C047314CE8731802BEA4C3BA5157A497F28C7EAAED6B3854AD9E583D3E9131197BD32688D684DB61941FDF27CA79FE790E0A8C40256ABD9587C906A3EF625FBAC5AFD03B2134A4EF062FA843B66594E5A5FA22026A0C88074BC826D20045445C409BEF +smlen = 5388 +sm = DC68938035386B29DC87B9BEA2D351CFB30D2D7814CA2914CDA89BA00B0AF13CC6948B2E95D9112A0B53B317F82F20E87B799F188DBC756FE4DA8465ABE894250D0C00FD41E3D751DDD17D2B02837CC2E8D8B673DD8C4FFF522B0301F0C2DD43B275CBA8E78BAFE72E1ED9CECF3D24CED64EF524E578548C74DEDD2D21A3CD554DE152E9CDC82DF5546040DDD83A07BB9C024EBC323096B57076658E8BAAF69F507BC9F0E1B55F4FBE6F8CB6A4F336D4E8C019C2A3424EAECA33242806A5E80595EB1E60C8BA902B286FCDEEB59E2EC1232D91C6A460CAC009CA24A2332C2B3080DB4064DAA852F80E0EF9D68D9E3C832DC0BB031EA348EEFB957C3C5C12995009A34AAF128ED460828183FFDC7DF03FA5290ED2F5CA1D40A4240A900CDCA410187C5CF9C82BAAAA924C36B391D544C4950BEFFC83AD3034F819F986A00CCA072A5302F555EABFC751A7729B029E0BB43084F9409C77A954C5022EB55F46157A441C9EC493938612BD8EDAD785C19DF94AA0411B0CAF374091DCE80AF069A00272A7B1F9E1A6A0DF88B266604AD694FB0BCCCE8A88AC466FD0E372364B65E5025D5F42AF898F6479CCF644650E6A30A876CBDBC3A1B9C606D90E1CC38C028692411F6512FBB69E2C4D8D6DF7BCC2CE1EC683A261074ADEA4D376061BC57AAF2087C90E234C86A34EC25AAB321AB76A4A628E18C4E4C07244E821B7D9E72570384037BA7F2CAD60E0E44FE5DBF339FEC6C6A8006963EA21C33D2E2F54B808BC76A521AC5A068351C87E21EB988E3324395C828C23F3ACDC9866ACE198B0E41818A55FC5215BD8F6A1D7FF50AB71D636858929F5CACA4C673F3C11C509D63CAE0F65CBD9CECED8135C53911E1FE0EBE86F65B8D8ED642F2277A898AF91ADD00DBEA5A660200B6F682AF4586690DA7FD18552440D66A0D8213D3BC37A77B9F8B9920505514CBEFDB495C5F4F99BF3AD439C446723FD64235EFC4804F3774BA8EC7BE953E5B1D1E0AF2D0D03F5DCC599DF4580E98ED24C63FF168E44EDA528008417C9B19833EE99E2EA241E76D846929FCBA01CA24D27D2898BAE001F0D003A6F2CCCEB559DB7ECA1655D17EEDAFB35B652CFAB8DF6BA7EF68684AFC0FF48D635EC6A97C636FBBD9D2BF328CFA79F50EB8EC4801CA670B53DAA61532D2A4A64E220B5DF51927599BE37FB99B544A90B7B785FB928C339BD7E24A95B09DA4EA3CD6E336DF77FA16405878C45C3C4A1435852AD96B69C7878DFDC23C08B05F93D0181148BF72AB0493179162552CE38140FCFF15B24A66469BDC7D688C2AEF6F3CD520CD8921210DE9FD51D62FA72686C7C668EB74BD16F165D968A7E671FC8948293C122A7DCE03D0B6B8013E41179F2D6723DAFC6C333FDD79D47C8E831924D76999A89603E81DFC2DD0AE9BDF3B533515C851837ED9B9D340033C7393CBEAEBDC11277F2EFDB55164D27BAF2C1CA4FD483DB55213B95B7DD1729EA0E25A368A8BDAEE3B053E6A1E73876832A53E9E9FCBA08CDEA387E056B0A7703C77514076902FF76A70DEB6984DAE123DA9C997CB8270FF64CFAE9EB3E9E6DA82B648EAEAF228ED003ACC43B7E6E37790C0703D7411F00554D66DDCB71AC34A4239FB62DB8E2533030929787BEFD32DF2A075F59760C8A91DA81C859B80DC8D5F73858CDC9DCD0AAA9525C3BF199E0A5145B0863C361CB6C25B371F7BD3E863ADC12F5148FD8A2F9EDA7445773CBBAE399CDF60F12C0FC6D86D2A05B1797520BA26502792E7E285F2CC5271DA84F73BCEB768E25162D0E8D7A7CB38B6D20E63F84F6AC504158DB520AA9BE5D03AE5E7B91BEED84D1B899DAC2FF247F1B3F31443CEF46F5399AAC0ADF1B7FFC7B4B27149F69525E89B41D3AAC9C7B0D613B705FB1FF57A11E0DA5934F0E7C2AAAFC51A598BC812F04FBB6AFA7FCF5EE16E70246EEC5F8E429F6674095F20A5C4C6C923511F2951DBE3F04E33F58A9ECE6D8786DC70E2C4DE442073021C3AE83A1D078E13B7946C663F71EE6B5D033304983802771A585AB65BA15D3AF241EDBAFD1E935735CFD8CCC6A2C2317F27275A6BF1E137D23B4EB4727C0395F813420324CCF2BDB4A8E4CEF1EF3D5FA072E0B626518760DEA7E2FF63737801B70F9A2541EB1906B75E3AB100D3DDB2C629FE0CC0CDF35424269C86DF99213E6ABD30C1D54CEC6C05F6F567E6989A190EBE9B2DF109A498FCEC9A10CAD89D229385900AFF7DCC20DBA71FB97E71B7C444D90DF6DF3A526AC66EDEBCA8706E9D7A71E62140E97DA35C7C2F5C363F90B931126B3285FD91F5D454944FC939E2758D76A91B7745C3C8392A53A8CCE68C034B183182E792150FC7CCC608A228CE98E5F712B13DC34421118860852819918EDCB15144B87F4B2F423F69EFD03389C6DD027CEC289FD2B4A9D693A7816CC72821E45BE92D670EEDD92BA155BC4C4CAF6FBB3D2004EF6B3CCE5A6ECDC0B8DACB820FA6321529FD50B2FF0B7FDF0D6CFB32E633B4B4224605403DC17A23B06C9FCAF089F08F2427F4FD8E6708795D95E175597A2929753D1A1867DC9E0B6479475037EA7C99A96A0EA1D50516A5F6E1F340CEB7A69616D9650A340E117D0AC066F05D611314A0A5E6635F12109F3D78BB519712AA61C1F3A0B070D7B6CE76BA381E09F29B82095E1A3D3F39740C3B360E077625A0A4DC3F11462E4701EFD9D29EF66BEA90DD2447A8A0AE75BF7AAB4FE2571EFBE8E6403E37652B35ED2D2CC319114D12DD8B5426DE36B919161451C6568FFE54937B384B3B9C9B5ADF76B7C52A71C36B283B89E492E723F96E068D3EAB7CC51756058CD43359E3F763D42AC5D71A62DCFF1E04727122B748817CE99A94AD005B7F4742871613D9AAC83C0E66B77725DF2383352FD80CD18278F65BF08574A17E792C911F0303CC1BB437D64B11C52490FF1C663BB4AA5ABA6E96332322411E201F78DBC104F1E82BBAA2F81B8D824473D1C017F0FA444649BC6916672B3BC89F58BC7137DF4AE2B7ACA065916BFFBEB9B92D6656D99EEA6E9004AE034FDCC0FB4EEB2D37F2D5EDD126B14D8B6E71402B088BDDFDE1B5152B1EE0213377DCAFBF0BE88B99D899025360062CAB75BE2B60362CC2E69FA8648AC5AEE19A8E05E46F4FB453420CE863803701B6CE21B564F75B876EE9AF6149CE147C0D730AAB70EFE05A3FF1FCF7A1F1B7140D5988C69105A76BDA22955B243012BD126D38CA87C8C6C8AEDA55B3C2CFA9B0EDFF3624C7B16A8B6408F7EFDCD3C2D534E3C8157447DAFAB01B14F723FDF9C955E0FCEC1C638C47527A11F0C11C555F1557FD06FE7BF680FE370E9224A2B94ADE4CD4D2018915F29C0DAD95A063A789F60124630728341F5311AF4D44F660EE81722DC963199C68E08CF60C0825EA6EB2239DDB694D690F4E07999DDB14EF1345739CFA060377E0822ED1EE287264582B62A8A9C3967E61EB3AEEBA39E74DA4421E137C28B0440A67EF946B772100C76BC0F25D468DB271D04624BCA4EC85F94366844E974044FCC42B82D036FE3ACBB184996A9875FE85DE6C0F6771CBF7C58CF52E4370E2EA0A962506495D819D79711C25B0BC26013EBC7FC3B436BA74F33459CBBEA1530EC35CE5791AF86475BEDC1677A542C19435419319AA176F314F0D21C1253FE8B3740B96BD4A5BCD314590DB9B2FD512AF17466EFA551B81DAF3F0972B6832F2E13E555AB7FA3D4ACA9B3DBDD20CB6128915E8A56884B16009BBBE10C07B5E13A08DB1AB8F164A89BA2284276568E7D985191DD23996B71DCC1787C0D5560B603DE826FD7EEF7DDBD877F82DD1299776E2415F9FE6BADFDD3DCE58BFC57443292253D3172D45BD9D9AFB0CB1170A1FCC9D722A4FA131FB1D95F2D8F3B31151F8AF7BF2985CC6277ED64F69C6319F20508694B659AFE1A0EC2CD4AD368652B8ACC4804324F592528547DA0A3E95E2957E180D64126F31C2D8812D9BDBE0D091DB4F5920D17900C38C2E562335A3E7ADF4999BCDCD8B0E82C964FF6BEED6C5BC284F9CF623C7E74138A1061413714A3188DE145B0B2B4031D9BE0C788A91C72CCAA7A09F2BCAC6CA2B652C97EDFAF3A2B2888BEBCB6E86C1636ADCEE9744E6D6A73B3974934C531FD1631DE9A1EE783130EF0C2CF23DA7695E7177BFD820749C8731F1BCA45925D731AC7FE39DA3440FEC8D290C63EE4802E43CC875D32B2445105D2319C20836EEC722883FE26FE4198AD8B7DA8B2F7053DD3DCCC2D18D0F54E727DA2E6D004BF5CB158E41B04B6D6531AAEB24EA319C0556388C3DEFA75011AB34CF92FF1D6CC6F9BCBA6353676B0E51E3E46A8BA87930B4F5B3E2B138266FD304203C75E7D98E64AA1F5E6644A33163CA48F6146DB10E203162F95A900DCFCCB09D6BEA8E250482B341CDFEE9CA13805647E400CA5779B6A4C2953148051D5F6A2CB12FBC17D64828A0DF5FDE7806A6DCDD1A515C0EE6F187A2AC1A718BEEC851407888E7D06B2D937F3917DF9247391B73AA10A1A80AE8D3F65CE890CA1132F885A894FB3B778092858719CF8F630A8DCA1AF1AB8E8A2FD28213B20F0B71EEA4349B45F50E90D0972835A140ADAA19D7B9063467E131368F96D547C929FA8B8E3082A527A818593D9263165A2AC64818FA1FA003E87BFD4EAF3F4249BAD00000000000000000000000000000000000000070F141921247F704CEF1C510BC2CAE9B70FD248C656226BD5686D366528F0D0BEFC0A8761EC640CD2DA7979DE5EEBDF6127F29ABB8607F8A3D3BE05BE25AACE7FEF3063DF28E22A522FFF0B6FF6A0C61F79B02A408E8E1C775AB80BE6841E9F8A9D030AE5518E3EA8A4E31E416E087D47919593598FD58122A9E601A57EF02DE183D56921811AE2253628125C24F93C84361C5EC99E7B16962BD96CA190C68F3AA9DD60CE3AA7610589813B4FB77A4688308D9BC72CBE918583E298E03AB95FC500209C14ABEB3A43BAA92DCB11CB523C4D17EB9C6697B56C8B61EDA05BF5789166F839291CFE2997B7DD462EDA69B0615F2AD82AAC0A32F4B30FE8725849C144A9C07799D6CE9D293C25D8302161757B8C8C8D07032D914EA7DAC275919A1DFA0D3348EC07FDC70266975722763EF85EC4AF9E14288C9659907526566BB3F2DD5DAFC0D422568CA3AE52486D3F2C18B667E5622BA7E52C56BF00F82AF2108CB4949A09179544F30758B7FB98C49EA160720991B14E2858D648F0585AD1BB1D08294F029BFE936154E9D328DF2E054004FC5C29070DF9EE50DCD0981D2BFB3AA7D6F637C4CE457C0C66D27E2670107A2B85D1F026BD970EF3FB7E32C60218D5E43A06D9CD26289A937B4FBAD2A831425728F3D0D30C6C602AF4B14411E9B3C7CF0B4D630614A9E03AC30BA2B024D496DA984D08854F1366012C2400A5C8268C2B126DEA5AEBA0DE7C92BE0AF08CA22E02604A753702BDCD642BBFA0CC91BD8375657A957306A76B6F139621481B6F15CB57BEE128954D30F552661F906D8AB42CF260F30F88993BB40C9679385F5C4639888973361216DF3C60C57D9B250F64B7634C94DDA3FD122713FD2405A7B71F476C263A781DCE271E7D0665E45DCB27F7293DE57312396C58C40E268F57ED856F536C8FEB4B0060488DE3C25949D2B7E64207576641B34920D04B46766AA2978D9352C2769D49F8599F3D0439C928532E0EE428A3773FA4D68E6052335C6D93368E321D750D296799FAF87B82C640A6E995D18DDA002887F141DB8ECE2584DA2FDDF848D38357D585CD619B1625A70A5D333561D6DE856ED9908D1E377EF7BE03B326594808BE58F7FB3939E939B73F11DAB3E572DBA41D43A046B8D2BB521728222D5A77DC886AC6F328D9A531118156D791D64F5DF8FF8BE8DCA32EABC3CB259B0F72B021CEB4DB36A6CD2FD149437B251F81F7588AE921456BEF1A79FE83447D80CADDBF20895667CA0E493A4731EEC901E03F66DE284400A5558922AD53D4E0FF7BC6C61640ADE0274C63D94E96BF6C642B790823109F53C3C27130A1EE38D448239187F5009373BE328AF866A9B8DD1BB735E8002296043C6FF641A432709148C707B900ECF46555D77644565D5998C096756F79B6F0E20850B8BF0528E78BF5FB4859BD655227873D289CCE47FEDA8414D09ED7E8D380FC4D580C7F44B01521E829E7B0CB2D2F345C517B65E2D476687EC9A4C160A3AC0B01CBAA588644D799B125910812790F06C1ECB1F1E64D5CCF92AE5E8147C98B0CFAD5626BAB5115844198E8C2AC1DF9A208FCD2D2891F4A29009F5B36D8E31383811A9493CF8E143B5AC8A14D48119CC16D2C6BF6826FC47D4B782FFC76B64401B8249777E32C1298606553DACF386A22809B599924A635796A1AEC3CD8568064852E54C95AD887D7AFE837F6FF676F69EE6288879F6D96193AD94A0418BBBA2EED5355876F2C3497448A5F8F3F83B136703D9A38FBB62784CC233DF448A5E88EB5F81A0BE97A16FD4CABA1D87A4BFB08E002EBA548F662D496A1478BB7C26C69CA4C100AA6872A4945D703CA812BDBA53AC86010AA1D2C53F29E46AD095936FF50DB8805DF4B08C9580AEECE3A6DDD828E7B5D4DABCAF112A6E35AB3C28A6DDC4D98AD1063C2ED72CAA50086E6B72090CC1F2AFEBEC6751F27EF51DD8557E53D928535D82A220F62BA0645E3C2618F3424EA1A339A138C9B8E26B14BC32D1736A4193C0C72CC402C3EAB58817335C1424BD6F38CFE16338611118B4100E4038D07DCA041C72E485C5290F0DDE601565DAE9CDF657A4C7839D3ADE72986AF396E767430125786E219BC5736F16FEF66B4014E5961CFB4CFEC4CB2A32205A92DBF1399E2710395BA1240D48277C120526CD9E2352F7D04D89CC2754379CE80A2CD1AC765718B8BA61EBB8BC6D0D407022E7AC672065FC8503BF5BC4138520CAE233EA997463D7C9E00BBD852F12EC17C6F1DB1914446AA21E156D210094B699B4117B31EAE6386DC0DE1F55CCEC09AA1EB38CDE4602598D452732C5EF8B07C477E3E2DD470737EAA7357E2E8B74C31A117B519BDCEF79B6B044148A10468E38B5A6B7B10D74C6130A60A268ED73DC9A25ED68AF354758FA3F57ED3558DA654CACA7150A8E4449D0EF640184A7A33D00BA765B01C442E88D9B4257B93904ACE04375679BFD8271A03073E34C4A1C0437C4009A9590CB98D0B5581DC83407F04A22C9B0246DE38E1A13F9B1191493818783950548BE562F940240CDECD4A50C94E406B1BAE04B50A3A19E7923183E3FD356238C45AE6559193E0E846DF0FC6878BE6C963AA8C3508DC31F766A4B29C78D749C89985AB8F580DBDF7993A2261CC4BBE489C3BBB38C46739BD2516D3C64A93F10CF559DB6A0EA3BAFEE8B43F696A5288C66509A57C642BBEAFB40F4CD0649B4CE25B6FB2EF5529B73556051213BB39CC4F1DC8004B1588C8DE836699C66CED567998523AD3AC303D9E13617CE6C1D2FC4C35B22A24504C51F64155F24D91D0E8785B40912B3DCEDEDE71A6933B36BB514FDD1D3D843AAACF2C1E79A5216622C20036C9C999DAC3A5A2D43FAC3B23119927806F497B4048F561A2276FDA0302423147D35579DD4411416F0F59273429AC0464AC49B230E29DC124115D18A045663D228BFDAC9F57B0C5B4 + +count = 63 +seed = EAA4FB8EF0290A499A1D92EE398A8D7E71CD3CBF01A36750DA4B7EFF175DA26D17AC4ECE49A84C88D1D2C2493563C26D +mlen = 2112 +msg = 2E086FA0C4582E0C6CCB020F86A6107475985160BED201760D6489CB05B8D21452C81BD5D317F8857703DABA24E968F3164C82A4A9751DD88742B72141734DC0B4A77CBE2AE1C287A396A2F5804519456CF1EAE273A5C6361F52C35EDCE5ED7388D61D01AC040676522C9FD7B02A7DEAFDCB4169867EFB69792210A7069287C5DC958D0953C36F84D9A26989DD3B726BE8B94B41DCBA1B5374123F55A6DBD6360698551C27D16BAAFBB0ECBE116B44F11425DA45D7FE8ABA91697D83B6896A06A7888C97A91406B81B3A5BC8B68A984750893114B4011B9C8BEBA6F5C2D7D9F2C7A27030555633A0F90E30753A04B1958141AF7C1B95BA208DA36F729673D20DA0A83F913BEC8049F8CD032D9F9DD94B2086C61643AB2CFFDDB2B9BE0AF996D642B7A0A31CE0EEC8C61B343ABA980FCDACE9CED7BE4C9048B356D41002EEE0433428846BA4220EFB7F493FF57B0C706282EEE448CF7DA9B17B32D0EB0016983175469AA5BBA53489EC56BA3A92A70FDA2390E3A5D8C038F496E7C3180C6971A39491EAC10D828D44B3DE2BE64569B907005783E62710B9AD8EB8C9AF4B04993D40D1EBF165EFDEC748FE9F6B334DA6A30C568BCBAD095998A47242CA16803FE1720FCAB85233AD76EBDE102A5D93AB98460494BC886BB04C05AE89E157967747F8C050B33CCA52ED5E59050965523EC5C4EAF94CF2F2EE80C35AEEDD14E65D937C92855D03FC76ABAAD57A21A42420819EBB9AEB65F031F9C4BA0AC2EA27289E941DB89669A0620797091AEA3EBFC2AC354E94D27894F444FF9E604C8BDF7D6C00DF0E7FE9827171010445E737D0A5867636E3488EAACCCFCBAC1030C0DFAB639AB45C5AC5435E2C5B8244E58C3A6BAC81EEA408020BFEC66EF55FDDC618083ED737F4DD3BB65474487CADDF3AA2720A6931FC69533B6491DFC7E6E5FABF8103D05F870BFEFDDEFA20822A68A710B517065BD2478CE080E5DEA09EFFBA3A136C1BC9D7D8088F736C363B30E2AF2A6F2395EA8161CB64079340FA642C7763E3BF0623C968A16263CDFDF1B8334E427955E20C1EBCE8C8CB136DA8D002D8A9E5DA3B1F56668C1C59E20DC3BE026A43F40910D3A2B601D9D3EA2BF6D2C2781F976BA840FC986C8AF0DF84B8B0FB291D1310039D6914F8F7CC6B26CC33AF94150253E8EB410344A64344A5A0C06E0F3AA23C68617C6F4659DF79285782C89BEA3091083A069EF8F048371CFA054DE45E32C19A44DB5D435BC8FEF5570B68D80D5BF5DC06DA13C36E3AEA341CA9FE20047AC30683AA9D862306534EC93E79EFF79FE22E3BA15E2BA3F59F7B8B9314DCE31095D3015710C2927B54BA6F46D3981975229EED16C9B17813801C7D3CB3604DE9B7A4F18C2F91B2B50C1F43E87198AFBAC718935DB9CB96D9FE048D969635CB9F4DCA659AB1612A698CE45336B8D9FF5468301BF05D04B3558D66E88DE88427FE87E65D36D3C29FA3FB126F1F294E9BB391EE427001C34126C6622905514CE153682754D7FB1C985AE4DA600AADA1593A0A214332B310620B1B4E95BCBFD6EB8A241CBE848BAB37462224994E0D2F3F4B521DCA4A9A5AB10BEE741C5919907AFD2552D4AA300ADDF67CEC2862420C8D1D8DFFF60FDBE2D4A8D03C92E23BDB3400F5390EE4B141C5843B1E2C07C9AFDBC70E3FC08E2840EBF3B0E5296E1EE44D12E68240FDF063C07BEBF01C08586E8153068C1ADC744A7B54F53B0FEC3C752DA9F6F989A1AFEA4ADF1AD6AE926CABE4E0CB2CD864412DAEE377DE559A38047F31E834A6CE56D4041BA709945F07E514F96D783F32B0EFCC8B889FAF2B6D217246BA7C07B687E028F23D2409BBC12D6EC0D94AD9697BAB6395B7070B6FEB2E907A119209C9B7D86AF953BA7D2EA63982BCD794A5BAC69407BB7CEC5E027833B17420F146AE08F4B753BEF6CA0922F3294CD2A670127F9D2A2CA78A30F62056A425CBB7074C9A55135BD06CE677ABDF33B420F66CFDBE9461BFDF385A97439B3431CD29DECD9B5E59EC3ADAAE879A4E8D5E28CA13E73FCDBA51C828DE271207A5DEAB373B1B6677A29ACB87CBB01F10CD2C090EE66D472E8DB61615A5ECB84A7FF0988DD0DF9831BF43D732A12EC8CD50A86ADD12A5A2EA765744B05F73725AB8704ECCB08BD74517F21054E58903481E7A724F7FF24C43D6CD23DE84CD69C9E464E67003903C3858A6724247EB929716E170E2D2739AAE10B88BC3FB8FFA849E385B4113E78C24DE1673FC7E7285E6E3744F3843AC7BE7EC16BF74215694CE467A2E859DD4FACAB86250FECE28E0A6A31DD529D08566A6389B85C310C28A8DABBCCA9CD6A631EF0473ABFD6846D8326561CC9CB8181C1593D0F15EFB8129AF9E838AF518477CE361640169D9731FC139881D452773F21A3E79E514DDAA513D7B9F3399C0C57D21EAA00D44A7F031B79CAC9FC304E936E75A0CF8D204A6CC3C0FA7D037DD8ACC3A33CF5718061FCD57EBD06A607FE0BB0204E687B2A17B1FF47DA357B51A753076CB89422098D4F880F831842957E648C54ADBFCC0E488A95581E709B5A5A129DA7EC5B00AC9B18B80533F2DD1BD0F475A61DB18FC0C4EA655F602B207B572234230C831B26CECB7BC3284797C4BED5A977C3BFBEAFEA3DBFC4257D4C2C5BB8689830EE157F3B5AA1EAC09CFCE0555880A074AEB86062A8ACE19ACDC1A25F8D0E454F50F119D12E707D103F3C1A502D4E358D563E53554395B5D386AD49363978AFBCA2F8B673A693ACEF70D1DB4CEAA8FA580160924D4F18119BE46C71E09FDEE45EFB14A74DB1C688E99E24CB6025E73A3E7F0F7EA9C485274D2B6CF9784CBE39E388F9CCF1E2E8DBFA6DB43355391A369DEF645F815424253ABD0B6DE9C0A0AF156D9A4EB7474A2E5937F008134DEBC9FC7E54812967FCF5BCE28FB5CD43F1AA240BA2E9CEDD6F350D556DB1658868091E6034D7E1EE5C6645D0A345D46C42E23C6821C360F5ACD13F589 +pk = 77F4DAA54D8F3B52D07FBEDBA484684BC89E2289563D34F4E9B6B4421C802F2B4976F759B449B3729D88EBE2302D9424F68CD159CA81BF3A8F1EED90C8393E8B03CA5EDEAFA122E042EFF7DD1DCF9AA145B59F5899468B4EE99683F1961C2FBF3C850E099927CF4BB0B011547541593831719FA3AF8896A57E6E137C648DDE6D5CD507012237E3478736E84CCCD852E8420EBDB8F7F9BE8690102F334E30E769DA665B0C05065A9261EF3318B1321F427291A534B841CF2F0977E682D0290448174064A50C31F83A152F4E1B9D56B7D465676D692E375745B8C44BF4945D752C33478E870F6F883F1705AF5CCE22CA5DED1BC1126F4D04112BBF61E0CD4C6BD1399A7FDA2FCEB1C28C09AC609E647DCB366399247AD0B1234A5FA35FE098D563ED6F73C7097162611B74D96EA85EE7133D1B365F716BEC803865EF1BA85B8DB7A0479212F88EBAE4F44E01C19469CDD13C7D2BE1AB0D6CA9C0E0E7BB4E25FCBC7E14050D12D17741E7264DB67ACAC0567102037AD80FDB1FE769B02043EFE2CF3292A08D89B3DB5A8B2042A686490FD36C388DB299391736EFE48CA16E4A447AF8138379CA00055E1BC157F1D05E1A540EEB42CA7BC183099AC934E6E40E7213C628EE39CFDF683D9121EC173810ECBDD2A3C25058187510321CC06D222769EF17176BEAAF4224F5A01BE56FC8B41A43A4D53D67A82F248AB002F515563F2C2D1AD4C44281E14F4A565664E3DF248DA8D6B768F8F6590DA9326D033009B0930102AB7566B7037C64A67A821DF025B6EE49F83C7F3F26BC6D83101469DA25D4C499E50887BFF121B29C45C844A0C22526BBCFB5CEDC654C1AF0BCCF596C01B2F605A1C33E0977AFCAC003B0AED79483C4BFCC7A57DD2AD3EBDF5EFD1FC1C72889C673F2F19B9BCDE554765272F34C211E9B284DB944D4A935CFE9CEA9F6ECC3E50D02EE9CCAFD0D28BF11E3E117C34C8BE14403914F0259C469DF5740339F33F94E3737362349C585E9A12B9B9003702ADC05206D0A7C3DB49278227D7BFC6A7C1FE38489363CF82CD2A3602821B29E1FCE1FF1C22E81FAB3793F86E11030AB6A3446E1DD58860932CC385398A1BF8899E91F843118AB9284917D3C2CFFB4B0B6E8BC2D64012D2BCCBEA119763E199924C30D9FE062CC30C7A357C9644907C969F41AC9AC3911762F1B145D795077106AA9EE3499427ABB67DDE39415A143923A0D899721049EE6379F78EBE3A7CBE0DE10710FED2D398729642170F7E295D066ECBEDDA0008DE9CA0E3BE802C3D3701F6BBE9DB8D88B67587D7212F756FEBD4D5959DA6D21698BE5798BBD665D7D13D7D4487D6B7ABAF22DDF5BDDDD838DF968F403FD2B23F1E7700301D10709D74165CD8EE321B6370E3FE10EEF9F5B304071399EDB96F150E38E4E1B81E70A8EC4E21E5BD01477D6751F9BA02B30AC5FB2B61DE1ECDBF0FEE0D2B8E98BC21F0D7012AF3546DBF484AC4046D724DD9230371799BAE0265FACE18F9D790005510AEA15A1071851175042018FFEC217E22D29E24A7AF5AC488E8A576301D8E651EDDE0F63C8B39523F4B59F9C428DF2E928A5F3E8EDC3703BD415F15DCAA8449FC159C62668621B477E015533D37D15CC2AD65CE3A4BCDC9B54DAA51FB5CA725ACB94C0F5F0152BB53B4D38E9477AC4A00228C635D01A2F99DBD078B5C6771D4B30ED9EF6ECC7E927D9B27598F7C207D6F2788D93FD5E8EBA05FB57800B3CF90CA21455FCBB8797EF6C95749176CA99242865DC859A1F45261C8F28F60A61885D6F323BA3DB4C704F57E39A328E0D195E43171A26597FD62DFEC97EBAD7594CDC49DC27D5446C052AAFB742AF6B32C178CB109E63752036C7C7C2FDFBE98F870BBC59D608BAEFA33DE4CDC1944D700C66CABEAF7096138ADC2A44BCC4C3D0A93FE1251647CCE77570137C43079DAC7942062F8D6DCC54010BEEF95339940D7C4F68BBD8A7E581AE07BEDFA4B655C94EB41F9BD7A8855DBB64A43DB6A7BA1772A323DF83DADD903C789F0402C4708EF3D0C98D87EA781069D869437770AB18E8BEFFCC602CA3A51B6FE56410D6555C8D8E771ECA0111439ABFA481568AC695E662F793F7E9A1256A910E5398F3509A29893837A54F7E4C5824849F4EBDEC96D687D90C2F16543DC6624D5DB3AABCDBDBD8A308C8381202878E8FE291193F1577D5EBF8C1F4ED035BD8E647209A57D7132A39C399AD9E43EFD684DDB17B2151ABC500474692E2B20F109FA228B417CA3E66C8F8529AD1E78D4CEC985B94029F5C0E13BC2EAA005BC9CA673D0232A6940D606F08576D9251015CF380C2956D57F2134A06D7F8D2EDAEAAFF70438591B0E0EE1B47A3779BF719DB0588FF92803428F89DB39E1308A9390A108BC8F41EA1CC3D1A78EBD4F55AF93D1035BB5915C18FA508E1892CF2FEA60436A980AF7398B3A537CADD6185F345DE00A1EBD346CCEE53990E8BD7A14D1C856DC13D540224889CBBB0E75028B877E3D066092C356D24C533C751857C9E0183ABAE7C250B052620B2945347483A3798D1FDF9FB74FE3F6B6429C24EBB577836B3DF42D6A59B3295F78D2F5A6687A2F10C93DB9C5C598CBD304F1900FEF991660B86BB37E69869C520AEE3363346A8AEF0E263E34A5CD91CCF8D71A03814D490813D3AA73B6B3DBF34E48E6676F758B6D550A5E7A80371302D0CC89A4717F7E6B2C77BAA316B56314D41374EDEE0E108C6BDCB7F166715BA99BB0DBA42AD053F89370A8F3D8A893971F10C +sk = 77F4DAA54D8F3B52D07FBEDBA484684BC89E2289563D34F4E9B6B4421C802F2BC957C8560D6EBFE30F9ED67154CF2A0653C2C90BD033EA0295139C34ADA3CCA6A01254E4A7D1A0125BA00CC567350593648F222701EA2D3BA925867D71759616888CA76D0F2BDCB510EDA6053BAAFFFB412D741C507D623BC1000E6FDB960E1E47740184772741226065423373077052052388746226153514375072823771587021007800537142628480865510605678764135581436250811571625164002364086608661405714517770432047777324224030474211366354010733811030282680750500642356784878538011354766427578164127487388854535152821465682235516066021478648481827516464287401051584361584147367344338314312373016581366605652454322875216231363072241031562773246105576233475854135741787588400644023616166138552176853160807774358303664533781878767461375024376870045535400631615068182208816120620233327351418065752461674682746286266400266220618010055418482241807171537117217507272224865847187346241682113562021635661152534242830163718312378006272054712581813068375406673036830002381708086802662472888630623478546318181486506706651440455023384035222274177516826800557233430732614265136244715480751503245171105351523113734311282032383052020288016354464873774045440031836803777246704470580080502874140066136576108137317356487008146540647237740076407061888178585247343260168658635708183600187110565368456484625585585117608070340313322231268563287604380305104502785284445837035581171752234435583368002150022116861145302431507282060826860162657304335112805018366263504080601442686701642527784262301420815634780156447365583346757174301200026807552874764821760707282576404745625665782545686355047275016430887016102331356751813437754842064773743085817330831581230478816752085756203172384028448050780625214371416882154445275471864572525634243561077125007055565476648574682302501276300157136812287787473215763317684000426168636081413216281734178123378282414321606466843405667107662102565178001863183866264440552526861041100505517737308226332450500250784732031082412286121254286254870741840221480002731741778263728444420510150273681617781561588284350706570348646125225426633446511163438071247176673008524838748014461816047582483268040047735160724245380876607610164848546842740373587483627558812205871622541020054622757214325200770021054477000611484305872633410847626182834387601354703733424340313125733258246257418546408552507535173535635054332532171570784132512674323216143037146526476725635831507311708647355460417635723523430213858408800645172043706066176575352700274018050244814605715884441400167728744420188445140610771580607065211780584150066611386688238818358458346738107605833656744885585657242560815827421261866853847422531263126367638643744453642754607180515580536875270462402373381120800647612052362828365341447408400647665757163453765765181443531077262867606077564553254036778748182115764068855348584485567186054237302767161144880448888763830440333721535408044702426306301804858001464544735622871482842628221415512036805578137844331531443237235763640463005036044288412720634238137676588334285264128722430834736864824264707565155387275705225121684437167733442148013422785753876034844778513525168FD2FC4C3318331309C2F75D5C38925B15411AE1C7D9F2175A95D2EA35C547A27AF7F443D998E86FF9FFAB0460D2FDBE8D3B85C2F3BC45815CA818C6658F8B7AA9AC816DAD4CC34AD3A43B5167055C4FD63A7A53D933A5D151A244CEEEBBA59848213D8786564085D9F165F68AEE03EB929AE9F2211D2838CBD43490B98F68A6FFA80945998D1AD6B8D007A655FC6D0F4D35B9880B79FDA3651D4C9F218963A210F1DAEA49BB375662569CE65B0C5CF0A8187B370FA85D59856F248AC3C7C7E1FAF2D6F87055EA1021A0098E7AF251144F478DA55A039E8BA88420E4AC4831BD03500889D6D76E37F0DBC39B5CCDE1BC8678ECFF063E140A29340B48AB3FBF3A2CC8E07E189091F7D1792A589C43B97F72888BA70D0C6F5A94BE0BF09F1DF78D12074C74E2C90EF0FED4D9D81FD3C874E2E0E4F5A4E1FE44C77979FB4BE78AC7E977DE0F1FA30023E263E6BAF8226021233EABD9114A3A86723B9849FBAA2530EFF63CF9ABE81314C3ED4731084FB66CFDDF0EE6B869C635FF9284A76EB4B8BB8F4EBC57F3638433910E5CE12061CC2F86B4A7634659BC7290B58777DBA89A38D955097818DC61E2087299D6FC2F6E5B8E1A3D9EBF570AE864603DC7392938A3188705EDE6EAB0A51745D641F1720F4060105E8C903CF554030BCBA41D9C454871A5D1B9E8C5618B77DA0BAF8211746419C14B640931E58F7092E4D6F294896B6D8BDF768E0BF578642F089297A68D44783B6F8254CC1B620071A5967FD64C7B7B3F590F72FF5533182A41D264EB72838803C489A911C952BB1F498A6D81D1C03DDDE7017411DB6A70FB5A6EAA898AFF21EE8ABFD8EB26481B96FF13545C242B61AEB051383DD0EEEAC40586989D9E04911F2F2946E54C7950AA10F071FB1201424AA611C2CD4AD45544CC72DE7BF33C0A42DB6913821BDEFA09097929C8D251A1F95F1D198E09E69BE859972E3F306BEFE2AF051EB4ED6DD2DB40AA63C9C1B8B10C1EC0402E035FE6731CE1FEC96D16E836AF8E2890B58F38FEFB39A4949ABD435989D3A4206337BADAA3A0495A8FA6227B583F02637F122BAD0A38E22EC0A7DFA6E88039BA5384037446D942B79C95EABF053DE2899EBD3339450E3DFCF17D437579D7AA5A4C252FED5C0141F4AF5E2CF3C2635FA977AEF42C251659BA3ABE74E7C8172BF46040EB31D83154CE7988F8AF3390528FE56500C24C533F22B4D642F4FF2386D41E3554A19E77C75A2F13F68BE542B2E1600DD9C92DEDAC5694B368111F4BAF2CDC9A6AECE37E939555A869F7A431A1D9B8E4D58CA9C2895AC6CCAB773A61E7535D505E179C2F131728DDB28FFFDD62D9FADBBC6982BD98F567D5B07E438DF905991B48D9BCF3CD804B163A315AB219791266FFAA9D92E330632FEAEC338CDABCE06BAEE6F94656FE1FE601C33BFEC2190ED9CCE5C78F6611871944003C822BFB04FD9CD3BCEE3749B16576D0919FB360C91F156074000FB73532DF5E37CF166DD9BF69F6211DBEEDC9E812BF647FA95CC7AC1090EE2FD1D9758AB022A2DA315C75260B0672E6CFDFA363A02300B0660664CB0E36BC4F675B66607AA13EF428C1E7C754D1245A60FF47EB62B0B9F5B0471B67C2A48E6F209ECB3AFA86F85CA181F23B58CBD5AF23B3D7688E2FC7297A9B119EEAF55DE69F0E7F6DD6130C6675752C82375020FC4BA8F72C876DE161D896FE5604ED072352F2D433E51C1C753741198D5ECEA5A24A798EB758C1A5812D75C5A003EF73FAE4393A4F1C66C93DC54B9FA0C96D0773D826708692574AEB999F15D53ECD17023A5A3F852F150B175A46DC220A7FB5A37424454C83C39F77DDF3D465C71753D7FECA1846DD863DA4EABA08F344764BE744070DAEAA62F8AB080D14D5C0DD659FAB4284E575D4B51307E9B43C5F7CC7DE264F2345FDE28DEDC1F8DE4FAF5ED6E8AA65D5B2879001EAAF9CE93F7C69B52FF9F087416CA7ED6EEF39E55FAAFDE6E221358EB986F6BF59E4CFE441653282C516592C4F0D4FF71D3AFE994BE91196A825276AB8FB2F5CFFFC7C2959577E58161AAF0E68FE63E439AFADD4A76B29FA45CB1AAF733865ADDA39E7B0535F1920D04479181BBA079D87D460FCB0AAFD145FB5598151321120264531D1F6A48E66B59BDC09BFB4C666E89B39BB279594FE4B6284838125AB95903DFE565C658E6A32946F7214BA5E3167B6C806F60E401CD4853B6C3D65430DB02389B5233DFB0FC1EBF66B1FBF682AFBE999532BA1A3A6F6B5FA2DDA57D074A1E8D39ACA2430F49D84ED35227D48D0563CCEC1CC621148F86759341F0CA44E0A5ABBA3386E87E01A37CFD31A0D8467B254B52D6A6030E8B3721834D4E5E96957AC52EC21C616AEEBC5871484400487971078FAFEC58F32EA90B0F39B65ADC8C2B23E80E719130DE0798C269B84849844933AB331327893EDF57E401B619C53DD291C797711C81EBC6F7D961E9CE8B0B936A3AFEFDF20343EC58904C8692A7AB73A2AC438D4E0B7665BBDE9313E7DC10CF8552EDA3B66B6220348138B374804A04527FEDF78F711F7F5BED662EABC11E27582D36E4EB9E981DF21C4FD8AB2790F81639923C0C8654EBE90ABF74B1ACAB76C1DDC42E96DC50838943FBC8D65C385021729BB770BDEABB8657104AD90C9E18FB12E25CD0F86E25D0934E9FA7D2386CDD1B3E84295419A07F5D860E921A4501D18F14D25FBE69F59848DCAFA8D910DBA9CAFDD1078C66E0B8024C86E44B947816401325391675A2DC07D4C3DA8390EF4C8E1E4ECD80092A3AEEB69E2F85943D1B08FD50A98557B483ECACDAA6BB4658B6FCDEF1B2180293FCA80B145F6C7F234CE6E0362E7B0AA36A1E42E9733BEFBBE258BF3551F543A416811DD5BD1517027B64C06CDC9B479D6D6293D0CC3CE470976A8860AAC36F8A1C3CF3EDEE37B27BDC5FF5FDCD2524C75F5DA8A084C68050F6F8C7950A7EB9C6AB59679058E92D9917C742599966108B92AFF2E5E084E25B956847ECA5A0498CED0490DB5867141F1C3432D5AB9E2A1704BBF9D025C8A47B27E8E1E3CAAEB40023E6486D0FDCE9DD2E61F7676E927E62F275577B53406C2B57687450C70BAE18EBCB34E7E35068CA53312EBA0E94171D15069F69A488EE8B08151E1706EEB329E1A6054819620E02FE12FDEAFCF8B93E83301628B28696EB82389A8C9749E78C99D8DE86DF060C2D39E38D42C6733B8442E22AAABC9D08C59C53AEC77C10D48D6B483E1283AC3E503EB47A592FBAEA22D80E0A622DCC1165945495B46C6CD533431750B82873468A414839CFBC1E8F7C33AE88BE26D98AAEC4EDCC82CDAEB31CF5854C08BFAAD28332C074CBB566E63A82C50930AD3DF6843E6A6C4CCA0B73E3EB8B35B256C15F88E361F9C55608BE0422920A4FD7DA99EDB11450455A9A54B8CA76CED6C78D3E0FC8D644CBDBAEC6DA3B71B095B00B6DCE10ADCD83B9839FC16F84FC12D29F6888CE4C11764F12A449C697F19919AAADE876A1B3DCF0197CE757049D84AEE32E2037D46F461AB6446E4B87F6AD +smlen = 5421 +sm = B6615B94310CAAF519A575F6D8F402E35D8E58D0E30E93E276125B8C0B73E2D0F10DFD4492732BEEF2722A84DEA3BCE379282F592E9DF3F26EA53B7E895DD2F4DED612943252E4365208394F3C1A67966E1AE81E2CEFD19444D5D1FA9CBDEC31DCC3B75DDAD5BFF3B14BA96B788839A3B8C3EC86A29087D254DD7CCF0D0072720668472CFBE0646A50DC9A2F1230D47898D126D07DE75A1CFBB340E2F474D2BCAF716FEE7AD730305B63B66A4F7F2FF08A56C867DBA957B26CAC6F641B76823AECB2AEC41929CA72FDE6E7B15304732304BD5E78EB70C8BC4937213A9C9D458C492F70106E2892D082A1A82936B168FA00FAECD5CB0537EE6DE662BE318D868AAC9FF63DC0836B1A7185891D22947EE0965F515E5762D1BE794702E3B231BB857DF2C73311BADEEB5A4192F6AECB349CB6E98BB68841B655DBF903054539A30B8D5A7A45DA8E0CE6CA062D1DA1AC67B8BC19A896E96604C0D91AA3E8B9478916266102E4DF2C341882C80C121336E032C2CD27E4C55067A38FE2337DCD988590967D8D427D0E69E5FE7FD5A75214D95D2A5A8640B0EB9A17DA665CAA64C841753D1B33F8E54BB0673B82D8C24395774864CA1BB600FCF0321CBCBFBDAC56CF84501701492315E9054DC2734C2AD81916EA83CD00F5D51902F7EA3674F3EDC361703E6ED99F5183788F9CDED566471D2BA2B0364D5856C2BE77933F7F8F104CD03050052304EA6A5CD401AC2D3A2991492CFAEF8E053EB254DBBBEA8BE0C0F1949EBF30D82D8C5F7A890005BC13ABF019C56BE7061EB98BDABC944EAE4852BD820B6328C00413748C91757F40EAE789E35B10E919A8786574774AD4308D2519D6A79B974DEBC2333F554DC167F384A349760E8CE985BC5C0B01CDF13AB87DBC6AA2AB0285DEA3E31DD4CEB407C586D91BDDD4E0BFE88B4BCFC54FB5F8922FE4E0BFD8C9231434602C21A18B12AE7C5A272DA0B234CAD894AF608564C4968383EAB60FB06B66A8E26AEC5AC5AA1800EEA72C28D786483484CEF7F6386C47F9910D1C16423ABB2C3C8EEF3C377A482B9C58E2C47036C25776C9ED5F562587051DC7BD00381D2A8C10A53234E0B766085522120C96539C32AE9145E7B89EE05230A7B8BC94A438A405B5BD9910BD8FCE08008D6F54350660EA13798B943188FFFAF23E9BC96E9538702C857CFF6A100303164A0BCC0F59FEF6F4EE21BB5CE99385F7AED405BC5E4D184A61F9E3BCDE4967D764E4FD83271604AA3B5ADA592460DB2D854A2E518A45728851B26D22B48ABB0FBD44EF3FB82AB35E71C732FA355A76D5C9537DF6E4D3936B5DD0B29119F0D61C26E4BD9F2B2238301D3366028B7347605AC7592D628A242222A708ACC5C2FFB1874B88F2BF4F9CF539F4586D5682B17C9A4BEB225B44B47C1F50963582A4437C2C74C76639033988E04ED570C6637C5DDB505040EFB919277B5A6594F17F11242D57F2E13D2D12F15B990E03BAE60D91D4ABEBDBF48F542C42C24985A004F9ACFA7CEB5299955CC9FADF3A4A60A90EFAB603F7465DAB36B7445DFAC2ACE2A9FF37A3A67B9561219F6D83DDA31199197AA90E016D3A96EBE1DCBA9EE6463F916001B441632BAF4B434ECC9220F4D870531853D13D3158E0BEF054B9F3E4C2BC20B7F3FB346B452835D17ED5BB553B96B88EBF270224E118AD2484AE56FF04B22E0464470C84DB495CFEA15A53356D819A903D91AFC46FC350EE79BE25A036D92CE36F58C08FF84A73301F68916CAC30C45048F9D8CA709EB61994D7BF5EE3D42201D5BA0D5EBE9727D5C430F52A05999C7EFCB9A7430864F4C50AA406D0F94B2C17B63EC3993B08A1497A8956FBB04761189D343F2563876427063DE58E919A91FC857DF8494A861AF38498CECD612B83F985D31AD7808F31C59A049C846CC3C4D5660E522F48EFAA796AA3CC5E9F0D54D967538B78CA81563BAB5B45E4374D03B00DFFBD6AD335B209D15317A684CD7A1808B29F6070084E988AD5B829A614A6C8AD22C7FD5963898ED4984E8D554BF9DFA372F402D62FE4F1849F7445017317FAEA8E4CA007741B4360B083CFA2799B9599D03294AB637AF5D8B4AB0A57BEC71510306D48622110A2FEB430B358E3E61D009E6F003E2895F820568CEE2191C01655A706218F4BFFE528B840B865D1FAD2BB78D1EAEB6CF474726635D1C4E898C54FAA02A1CB9777F6AECF746BB2BBC4C3C1B05DF6D543D89D9793F5C1D801EDB1A35A8140EC653F9A79F9C1F7253CA73A92B2C0EFD0EB1CFF0BD764C9378DBC53A3B48867653BE581614C5F3055707440A5DB4F9D6467DBA5C5CC96D49D644A2746146BFBA00A4391BDC7B9AEBFA6C1D13825543973CCE503EE55818230B09BCA3BFBA95B3FD719B906F94A5A2D0BCC6FC44FD48A98DC88690E709EBE45C4210E8FB00A0247A3B58D6A61011D6400683BD3E364F785501CD91F6C93B9FDB949868195604F8655AE9ED7809337CB9F968D8C6516B2BEDD67A2E68F7B45AD59A7E8065E8A196AD867F660E45154C1EC7520505F604C886B49F6A897249F0B47043ABC5E54B12AFAD8CFF17106D716F2962924A1DCE4DF544D2BA2C6FDE63545526D7C2A8B37C238ED8A75A3C9505BC7E2AC326B4CD3E7C5AFC9E173A560A77A6DC2F99248CC2912DDC333536591C1D9A097C00349EB9862A7983EE008C3F78FDC9581386BF85FC1078C701D8132F564F4C02B3E3603566EB22E192E72E14DA2C36F3A706EF871199A0F3EA0DA9AB8D3DAA3D7D4E5BC67728E65CA832964B18D5AB3783D29DEA5788F5B79CF1EF59FBD69F7A794C38CAF3F1F190D00F159D59DEC8787381015FC8C7441186A12450BE7814859A05832068580B39FD2C68EDA499A4095604FF7815492F253670A458D8865A2DD33FE8BE4F9D085AC70EA4D8119D82FFE6EDBB79FF326DC7EEB76E94F933CCE954350167B8898ED124A8745F50C12DCE8571A688A780BC3F61E53A7EF17366DC33900E533D515366705DAA7A2F6E2E1AC7C22D15ECFCEDFA7209DABAE2BC7554979D60B7A83537B7DEF72B6B0F9E0F12C179009FD7B47461574FE7C5E2BFDF5F88AAA0C1835CAE9A95C1A7CCEA83EFD6A1966BE7DA2F193DC99B8584507FF5396A23D72ADA3E0EB61BF77BD13A346DD494B41EC4A0FD82803B73E3AD40B860BB2749533B942639AC258B82F92DFD35E6C2ACDCE1D39327AAC33E146DA6007BAE8D9A832775D7988BCD6FF47FB5326D8D6A9C57B31766C93A0C5A6087D9F6E6D6D9BAAD0CECBEB29A449E6C08383DDE5D540B747F20F9C35AF09FE5BB42D7285FFA8C393E16C31ED38B464F5CFD9155FA0E2F7A39C5166E0ACC177D08768566CD4099F7E529A91839637EB0F2EA4B7EDBDF66A765CD441D82626AB18FC6FC1039B2C0D4F3272F760E9814A4EEE5C896670D9703516A8228A822D938D49B585213518F6E34F8CB763455EB4719AD1C49485E44AABAB91679455A9C5EA89BEBEBA81F7DA1A12123FE363F450F96F97CF7589B1855E80BB93638B0DF50164469E63EB06C067CF38D5F1322EEEED24990FEBB5C6006765768592EC6A5F528E66F7DA9E7EDB3C6E934AFE4F1AEF0F17B0F787841BBDA2FD486449A9795D8756415B125ACF1DF2FE1F13A30A3E99793E2449B296C5B08ACC87D951995384F9EAA9EFB0FE875456CB02C0C666A0CF714518E9BC00725338F85B186539C7A1C519038A5FC80185FC3FFC1D417FF0BAB4D67178A74765E57DA44AFAC6651B38836A1D93BB79923175F434A70ABF66EEA19F26A0A0651106288F6C5BBF4851F3DE66881FCBEDF30A95DF76EEDDA21B2A87ADF8CE9E33F5546585EDE02F5C8A8FB2C7A7028F3812D39527003D89E7FC640F3553955F866B585B87CE11B2210B46ECD4C76B2ED98B7F6DD80147559AD00D35333D48A53E07A491ACA3653F4A5051D0F59A9F9045082E9FE8FBC9E781B4BBE1DE53FBF50A87DCD86ECB3A5915B0EBB22EA14C9086E35A56C51223E01EBC645C4D9894356429614AEFB0D8290D6997071B5E65165B4F4B04CBE552A2BD3ACF80CFC6E7C7DAB6EC07083F28079C25E0D6D25740EB21BA7CE4D8C241641E8883C3565D4F88D17223894F5628DA78FCCA44D6C1F84972A168A98ECDDC23B351185EDB5E5820DD6AF9A00EE947AA41B4D68B44D16A7C08271550E90571956A501756D09C0A080814805A9A25E541678D11725EA76B0DA23B9AD132343F2345B42FB85F09049174F05EAA8AC003E02E3746FBC573E5E1D26D17930156C9FEE5A5CB58ED3C185466A84313DE6793E7E67C3B244AB0D83C0BA90FF2C67CEC7139BBB983B3F0CC39EC3FCCDC324DB706542273FF9CBBD657F7634C93C0E2925AC2B3BAA93F6DC732960A2B2D7BDC9DA1D96FE2443306B5DCB9FEE7686A018172C1BF2064F21C9E78ED2C7B0C9586041C2B5C2174069319C54D5C84C5181FD97647AAB72317532E3CC38C1D55750D4486A216455D08479ACE816D0D0D909C09486D6D1EED99878BD8679481AA8D872D69A0994B8FD5800A819CD7CA25F724840464C28DB84ACB5BD87EAE46401543EBD6660A34436185577ADE73E853557F4866572F5393E22F3412676F77DBEF29E707172F3687CD0D191C3E4E555B664DAEBC052B2F508299AAFB0000000000000000000000000000000000000000000006080E1619212E086FA0C4582E0C6CCB020F86A6107475985160BED201760D6489CB05B8D21452C81BD5D317F8857703DABA24E968F3164C82A4A9751DD88742B72141734DC0B4A77CBE2AE1C287A396A2F5804519456CF1EAE273A5C6361F52C35EDCE5ED7388D61D01AC040676522C9FD7B02A7DEAFDCB4169867EFB69792210A7069287C5DC958D0953C36F84D9A26989DD3B726BE8B94B41DCBA1B5374123F55A6DBD6360698551C27D16BAAFBB0ECBE116B44F11425DA45D7FE8ABA91697D83B6896A06A7888C97A91406B81B3A5BC8B68A984750893114B4011B9C8BEBA6F5C2D7D9F2C7A27030555633A0F90E30753A04B1958141AF7C1B95BA208DA36F729673D20DA0A83F913BEC8049F8CD032D9F9DD94B2086C61643AB2CFFDDB2B9BE0AF996D642B7A0A31CE0EEC8C61B343ABA980FCDACE9CED7BE4C9048B356D41002EEE0433428846BA4220EFB7F493FF57B0C706282EEE448CF7DA9B17B32D0EB0016983175469AA5BBA53489EC56BA3A92A70FDA2390E3A5D8C038F496E7C3180C6971A39491EAC10D828D44B3DE2BE64569B907005783E62710B9AD8EB8C9AF4B04993D40D1EBF165EFDEC748FE9F6B334DA6A30C568BCBAD095998A47242CA16803FE1720FCAB85233AD76EBDE102A5D93AB98460494BC886BB04C05AE89E157967747F8C050B33CCA52ED5E59050965523EC5C4EAF94CF2F2EE80C35AEEDD14E65D937C92855D03FC76ABAAD57A21A42420819EBB9AEB65F031F9C4BA0AC2EA27289E941DB89669A0620797091AEA3EBFC2AC354E94D27894F444FF9E604C8BDF7D6C00DF0E7FE9827171010445E737D0A5867636E3488EAACCCFCBAC1030C0DFAB639AB45C5AC5435E2C5B8244E58C3A6BAC81EEA408020BFEC66EF55FDDC618083ED737F4DD3BB65474487CADDF3AA2720A6931FC69533B6491DFC7E6E5FABF8103D05F870BFEFDDEFA20822A68A710B517065BD2478CE080E5DEA09EFFBA3A136C1BC9D7D8088F736C363B30E2AF2A6F2395EA8161CB64079340FA642C7763E3BF0623C968A16263CDFDF1B8334E427955E20C1EBCE8C8CB136DA8D002D8A9E5DA3B1F56668C1C59E20DC3BE026A43F40910D3A2B601D9D3EA2BF6D2C2781F976BA840FC986C8AF0DF84B8B0FB291D1310039D6914F8F7CC6B26CC33AF94150253E8EB410344A64344A5A0C06E0F3AA23C68617C6F4659DF79285782C89BEA3091083A069EF8F048371CFA054DE45E32C19A44DB5D435BC8FEF5570B68D80D5BF5DC06DA13C36E3AEA341CA9FE20047AC30683AA9D862306534EC93E79EFF79FE22E3BA15E2BA3F59F7B8B9314DCE31095D3015710C2927B54BA6F46D3981975229EED16C9B17813801C7D3CB3604DE9B7A4F18C2F91B2B50C1F43E87198AFBAC718935DB9CB96D9FE048D969635CB9F4DCA659AB1612A698CE45336B8D9FF5468301BF05D04B3558D66E88DE88427FE87E65D36D3C29FA3FB126F1F294E9BB391EE427001C34126C6622905514CE153682754D7FB1C985AE4DA600AADA1593A0A214332B310620B1B4E95BCBFD6EB8A241CBE848BAB37462224994E0D2F3F4B521DCA4A9A5AB10BEE741C5919907AFD2552D4AA300ADDF67CEC2862420C8D1D8DFFF60FDBE2D4A8D03C92E23BDB3400F5390EE4B141C5843B1E2C07C9AFDBC70E3FC08E2840EBF3B0E5296E1EE44D12E68240FDF063C07BEBF01C08586E8153068C1ADC744A7B54F53B0FEC3C752DA9F6F989A1AFEA4ADF1AD6AE926CABE4E0CB2CD864412DAEE377DE559A38047F31E834A6CE56D4041BA709945F07E514F96D783F32B0EFCC8B889FAF2B6D217246BA7C07B687E028F23D2409BBC12D6EC0D94AD9697BAB6395B7070B6FEB2E907A119209C9B7D86AF953BA7D2EA63982BCD794A5BAC69407BB7CEC5E027833B17420F146AE08F4B753BEF6CA0922F3294CD2A670127F9D2A2CA78A30F62056A425CBB7074C9A55135BD06CE677ABDF33B420F66CFDBE9461BFDF385A97439B3431CD29DECD9B5E59EC3ADAAE879A4E8D5E28CA13E73FCDBA51C828DE271207A5DEAB373B1B6677A29ACB87CBB01F10CD2C090EE66D472E8DB61615A5ECB84A7FF0988DD0DF9831BF43D732A12EC8CD50A86ADD12A5A2EA765744B05F73725AB8704ECCB08BD74517F21054E58903481E7A724F7FF24C43D6CD23DE84CD69C9E464E67003903C3858A6724247EB929716E170E2D2739AAE10B88BC3FB8FFA849E385B4113E78C24DE1673FC7E7285E6E3744F3843AC7BE7EC16BF74215694CE467A2E859DD4FACAB86250FECE28E0A6A31DD529D08566A6389B85C310C28A8DABBCCA9CD6A631EF0473ABFD6846D8326561CC9CB8181C1593D0F15EFB8129AF9E838AF518477CE361640169D9731FC139881D452773F21A3E79E514DDAA513D7B9F3399C0C57D21EAA00D44A7F031B79CAC9FC304E936E75A0CF8D204A6CC3C0FA7D037DD8ACC3A33CF5718061FCD57EBD06A607FE0BB0204E687B2A17B1FF47DA357B51A753076CB89422098D4F880F831842957E648C54ADBFCC0E488A95581E709B5A5A129DA7EC5B00AC9B18B80533F2DD1BD0F475A61DB18FC0C4EA655F602B207B572234230C831B26CECB7BC3284797C4BED5A977C3BFBEAFEA3DBFC4257D4C2C5BB8689830EE157F3B5AA1EAC09CFCE0555880A074AEB86062A8ACE19ACDC1A25F8D0E454F50F119D12E707D103F3C1A502D4E358D563E53554395B5D386AD49363978AFBCA2F8B673A693ACEF70D1DB4CEAA8FA580160924D4F18119BE46C71E09FDEE45EFB14A74DB1C688E99E24CB6025E73A3E7F0F7EA9C485274D2B6CF9784CBE39E388F9CCF1E2E8DBFA6DB43355391A369DEF645F815424253ABD0B6DE9C0A0AF156D9A4EB7474A2E5937F008134DEBC9FC7E54812967FCF5BCE28FB5CD43F1AA240BA2E9CEDD6F350D556DB1658868091E6034D7E1EE5C6645D0A345D46C42E23C6821C360F5ACD13F589 + +count = 64 +seed = 5909111F333F3E939105DFF8532548927EBF289F31A72F4C1B0C66816D8B68F64622F36A9BC85E63601BEE8EE7CB3DC5 +mlen = 2145 +msg = 5180B7DE9A84F651DA10D334009B3D65582F3912D329FBAD4AE39A9EEC78943338C29DB4F49EF41E3C50DABBB530E99113440383F20D5A3A8AE279A6201A0C84B003F6717C709C21AE893B6E412D87F8E0CEE5A89E60A14CE975A4D42E4F43F4710FC9FA29E9B2AFA93441EF5570123AA88AFF009E2507A3E60A79CDA25652E3AC3AC0C10A816BC04739B6FC758FF9AC467879BB67F270E4EAB43F10A633E5932B8D6DCF23814DE8643407B17B5E2A91B340F7BF6882DB694DE4DEE4C480CE037B9F9A220ACDCE84B03746F307A6026531D712C0630E7DE3ADD3A8516BA602D2463E3478008B3252B658FEA54DE41265B5C81E4E913EA0E2A63309497ABF961EC40AC374ADC0FF3C6FAE9BFAC5CC2DF475885B0BC636702828489183CDE1A2934F2D63828AD1F2B8CFAFFA53151B0FFAE6224DF54C2AC47CC8844B76222C2A3B6E132071150049B6E46AA75DEA28C13477980315FB64CE500BF0C6F633AE621D65B331BA96CFAC162DD7897B8505257E228CB621BBA9176A7AFB3A2CC20D7804DDB3AAE4B87FFAFD3C8DC541D05624DB02BD62491067EC1CDF73147014FEBCFA5B561756D5E7A13B88D1E7B2C0375E1D0DE71ED20CA9CC4E6DACDC579F1AB024AAE2A0BEC9004E5DD81C046F00A2A4CB767C4EB240D205278CB863D1A61DEF16635C6A84C2406288410FA4B73B21077D8F7A4075A1DDCA3D0D334725151E434BDA80D3E73593338B07958D27337E32CDE0010DFE5E58B99EB27A97DBD1C5E6F9A552A02726AAD5A4AA63EDC336D83E5870DBD514193367AF2274804628B4EEDFDA3B2A155694E89F5A6798C5D6E036159C1F00D8DFB03D41940E775974B11C3FE4456E07B127CCB44E6FD6B2918F57A6523D7F77F32478D9F1BB539846793D4284E2907830E5EA76054802A266C85B122A389EAF4700629036716E2869C0FC9440856D562711E903A1853BC68582A95344B612E5CBC7C5B2AEE23CCE4161A75829B2048742FBD65ABFE2397CC7D66023DE34DF4F2DF8540CCE9781ED6482D29CA4E906716C8CC9596B158EB51BAB8C2E00253D6589A99B3D20FB494834B42BBFFB80E7B0441E356B541F83877736985F6330EA459C007CE8BF18D84E78E36482D581DC7DF97528CE15F68E604B4DE62422B3AA76F3E7E5B33A49CBA9D89FCF50DEB65EE45173795393A50FD4C60CF6BECBA7E733513537D13F89FCF1C4D6437DE0EAE608FB11D68B9ADC0C3A19A3565F6D62BA81A326EC334B239B212B87320C03A75C58DC8F828C4195ED9D7ACDDCE493123E235D098E9DC60F5D3A625E1FF66F245E9977F9630A40D26E3AFB6676F5122A88CE5507BD825757D9CCD53FE574FD0E6E728DA355403AD664FFDEAAF636256FADC3283D6F15B297F79216833CF2C745C4C5E17D03260A69178F2216168BF8F00C9889E1E35540254F150C587A884CDFC9E5F7D379BE474356C06943E416EB0697A1AE989AB4872D0BDF436D9FFAAFEC1631C9939FCECB84DB2846F12CA395F506687B4A5638085BC6EF58FE8E2ABE9F8D51F272EE855E2DB84A89D348DD66950B8F43939DB897C519FA302594FD1FBD6B6E94CA8FF63A7949432DC2D35C60803A570B1DAC95EE0A60C62FD18B3319601AD29A156400D392DC9A14FF50AF6752C1F6EDC2ACB7ECCA71097B6E82227DE429F1A29C5E38ABEA1C74DE06E6788CB1790AE9F0E8AB35AFE60B001F45971D42949263AA62519B0D630281A4C5788D5591B1EF5A003C58987E8665701E5B1C6063F93533094E96820F918C354903775CEB6675C4CE9CF940C4BEB8845B4F5E1F642BF505821E5A23122E2D1ADB82A63AD18CD1E4775A96CA9EF9493D75FF784A2D4A99F54DC3F87828BDFF4B3A3D98FA5A29B62A85CAAFFBACE4592A81BFAA5B8BAE6606AD25A92A43140690A6003AA2D617FC707A53EC9D868E33596E098773942D798263F58FE5A1B23046CFA136EA35203B90BEA2C5F0AAEB5EA8C24B8B8CBA14CDEE28F45D0278F193228484BCC7E08A75D0064D605D674ACA9019A0A9AAECD6AC672CB8410FEE4192E6DCA7855FBB1C584CF288BACB40707D7E6F8BA2956F6D099F52BC7B0AD72B5A3FFC03C7B47086330244EA5D393C6B9F256FD82D5CB9436A469ACC3F8FC237146895BE148749F82D39B7BA4CE47715BB393A96AB471665529AB9E9958B12396C1BA7529DBF289184FF0F635C2BA9DF301036C869D52D993463222B70BA778E81C8DC668DE41C0356EEF5C39F1BD42398BFF30F959E115C6B386E73F0FE28A2665BD463C781DA1C46D6D4EA284B152C8C12426DC9CC467809BFDA6FBFBC0BB4793BABBF6AD564D57AE9F5E2B7F651D6ED980F8B1174A126CC58B23C32BA73F5031B3FCABFE7BC360AAE412D799CC14D8B252D9F9EC9005B7FCA04A88CC8AE9F7AEFCA94137003D5764FAA3C7C45670585C84F74C4EBD1F5AD1F97EA093595592FB90E3CAB01F98F06E114F13DE67CDC36F3FFB01C3D51EA643C25A3F6AA2C57690E42B98583D925AC7B06A349782A1D33C06BD05A82A7AA3DD679326D948D74A1861926B45DB78D36070D3087AA9C5F4F42CA57EE9CE7035BD88A85CE1107C8E07E5BA3A62ECF012BC75FBF97C4C72331B55AB9A6EFFD78869F1CD3F330526F262F7DFCFA2B084B61E90772D5FCE8F038C0F72554467192CC8A27F1F53C8714DA1864815974B00991F466648478C5F9BF036DC4083D72E8D144AB10FD32408DA7677729347FEBC79E48E7B87388D9B59AEFC84B5B3B589FD91863811A6436ED76B43E657F7EE03EB796285A4D93BE9AAAD1E1A1E81687E42EC83F3DD059B78BB7F8EC70E6C831DB5E90C6B3AA511F36507DBC8E7A77DF0F5B9EF03BFEFE9471DE7C7FBE67B9922260D3703D95A5BFCBCB62D830E20C23C6CFDDC210E47CB575957D8C3514A2ED4561C738928F210057896EAEB1499D4DDC70F44E30661E780AAF5C0A20C8553F40D7D3FF6D120511C1073510D04F2DE544121AB851E98F666906367C21302EEFB1AAA723F6A531C454EEA0BE7D50 +pk = C0DEBCA7FE579C205545BAA954D756AD0DCD766B1E1C1A19625E5C33DC942F2A714F2C21294C3EC5D9399C2436EBE9429CF59574A163F6287283E009E5510209C544719C76B8A0EA586319B625415B241BBB4807D56CA260A3E37F2B08CDD85F30FDB9C19DA0CE1013BD977AD8D099647886E40A2AE6FDB6DDE6FEF1BDF1D0292C3FBD8D0F769E6D30DD9153AC95540CC1BDB59EDD199108163AB918669DA5A97A3838CFE73F284701AE9A3DCA1C3B9A0947847A0264A6942C0FDD2A447B9FA82262B9D541151EAF0D90594F95AC55C1EE2F68996E25A827ACE9A8B14A8583E5E49794750437A1BB3F20B24CAF96111FDC05F538EA22F0759B573249A31CBBD9C833440C75086C62A63B010847A2ABB3A9CCD65A5F80D49DC1E90B61938BF272E7390FA0F9AD72B9420BC62C8404D2903550BDACAF7ECD77E15908BBED8D5B231F1FC6B7F3A38C3C1801560F7E74351FB4593C36C5407EC5741D4A224559D6130C91DF7DC202801DE8210EC11AAE2C3C1AFCE08A85F62795ED837A5D83DA038ED6CA62161B2ABD46AA544D62283A9FE70607575F06E24D1F5D43674EFCE2961361B11EB2ADED96FA6FEC53AF88780C847140DDB1542D70017CCB4214F1F5DA73AC8FDBC7D6C9229EC89BA777C92E78606A881C80DC3438ADD729CEB2BFFDF5FDE9F17265494CDF06CA71B55529B947280B412B612EAC7AFF1849FC70B7536DA837DD86FE94E342A845F5252DECBD1A5758ACFB206487C46EF08E7409FDBB39226FB1ABEC849BA89B20C89255D5221F0CEBFA3E724DC5CB06AB44D0160C18634C2385CBDF581EA2DCCB26E250D31D3BAD262824D074711D55ADC100F73BECEAC1E60AA1423B91E9D2E08850564B4064AE3B94730AAF8DC12BE825027BDDCAAE120DA3EC2CC484BF6E5741F629C07AA696A88696F2EA318B16A942918B6A1038AB207A93CC05EAD5FD77A6EEC499B7566C93C47AF8CFF291318AA29CA130C259FF53C1DDB7A9735B1DFF8D428C9580A26F4EF90393CFB505C12379FAE4C8B7B391A9AB7A8CDA7FC2A5B46CFA8CDDEDE72BEE5466E90E0EC5B0401C8B89D1287ACC8D26FF95CC0E227D18C7ADFF10264077BE6EFF451468E04DD1E5342E8B4791FB0A718339FFB5D7D6325E7B5FBA639D6AC5FF2D783A5E5EB5A80920A83E1C0F0842E37B4F2C1390ADC4AF9B17A9B0798B0317A4117841E8E708A81CDFAB846D71EA9976FCB668DB68E3AC3B623342BB548CBC2797BE515DE7137B498600E683322B0C330923FBEE74CAF8800616305689DD2B51D099F8D90C824A26F1D85E5544A4730281BC2DF4F3E36B2CC3D1C9470B97C846E5C8DBB3EF84458F6ED42DE560238DD5913464891132A760761A9B1AFCB0A1986F1E79985E741C83ED89EE6A9733C2F8F6B4B93D1E2CD775940D050213C577E28B2A642066FE5DD23F14696A81FA0FAFA36B0C308190A73A5339A1C3711C9D09C8C77A4B5F910EEC4217B44B97E7B17EA6B787DD30A31AFCE5AE11140EB349AE71692CE397B3D5A40492316AE865599D66E6BC0BBA25585A45BAE0DF014A17402F8DF890E28ACD63DB69A1F859787FE1B4CC12128E561B5933125775A90E91ED06179EC71B23846833F1850B5639D3699479A03B609132E82C13D3A851435FBA1CC05058CFC1DA7E543AA874CA13DBCAF2AA5A64777BD88574A07CBEB0B4B0B03E16DAF2A7DA2E95A63949ED180114DD864248524C7695501EACBBCCAF3ED6354F363C203330486D97AEDDEE0E0276254E47B0D8B3BD38B4B31B85D1D81CA3EA3CE1791FF989FE0289C7746BBD4F566F63012DF281E2FAFDCD016DFAB30CF1642539B72E5C2FE541181D686A933C98BF671E275090F04A6A738A67AD6898325CA8C844DF99A03E95B9F8B595D8582B2193F289941975B43878C19C633DD7D0FA5837D45C5BD761C113FBB850717144791BA53C95E09C8D9CCD0D5D15762CA53E772DDED1CD7BB766F3D5E8901E84A0DC3A9142EA4D36A420969EF29BBA883CF86994D5DD884CB7D7EAB82E39585F65D3EDA497A7A00CCF4D35EB56C7D325E2DA81F39FAA85C9F83BDE0AE015D45944A6422538F6A71F8AA30F3C448CC5B6971B54DAA7520DFB5723D9BCA2E50B151F942E228CC139B9935A57B5C1D44E2819975E8685FD6346D0FECE07625E182315708DC9498A47D0A5A933D4AE3EF8057E42A6BCB92CBCD4C312D810A38FF6BE00043D297208E6D0928A15B503B063E711AC6097F82173B0F72E35150E142AFC12E2B5F1C984D5D3582BAF137537F4B6DCA8FD2CBD43666F61740CBA2B945852C5B66DB21FB7AAA0EEC59482FE7E962621F852372ED5BABA9B102D7F64B73A03C8DB7190B5DBE98D5DFCB173A55236F53DAD660437DA98811EA9F36F32AEF240B336E69FE80935793571BE478ED3DB7B6B96EB8FA848248E10F35B34787A6D8F225318F43FAF2FB21B9B14A5B8701AF7143675626D78D65AE92FAF07A01CB5E93D5E7DC1AD2AD9BEDDAB87B858A20489402182413FF939DAB8EE43322664267698EE247B94C1FCFE5C367550C61A196082DBF2F086F078E8388EACB9FA9CD9A17EAEBC6E70CF59BA2696B58869C8AFA6942CDA99133AB8A074D1567386C76E905F04827375E27268D8C22604436E322DF4214F5A53B3EF42A04BD794326E3741A5476684ADC9322B82B4DE9B57627215C7D28BA13AFAA8B6624C66C68C671AAB56253D41D4BF3CF7F36AF73D3BACCB3566D12C41DC5D6121191A991C018E60 +sk = C0DEBCA7FE579C205545BAA954D756AD0DCD766B1E1C1A19625E5C33DC942F2A18C62FBFE98BE4EC59037F5051AECCA2A56DBA8AD31EF4EE2D865C32A125543B1E5C0572F5B0EBFAB68859DDBE66682D73AD1283ECEDEE1D8CF8C8B656E6A33DA92A1F5AB64826C8B78C31E4DB67877A86CA83DA0A047F614940703FAD6E39674283454370002555526402230811871087153841175366384671277867376660874345135702145382543501667503143400133738267648640370428021145003305040215070628677104816710766843434662326268431758550255557070777275233211381508362208168786030425622586768061322066832637885507724212143046622465381678834256570861203686222136381168082246011778003851416212446075818237650571323528885722642105785268113324384362383375658683156440788385166753875614263666230848031001881401848422877741126251004258484142402528533236465558052553450635703380743684186802703680520755021537337735346727562531443713140237501663846641831412233756741160310367686277610088505482544063560417821570275015053544842367181234648661684840116672170807680122088417505378006742125333503451177143765763273423214562782641332133614177477331184720876143067415274584451655222716105578653384121013446356686750587236763334803237800707162528007771156642283224481426163084240131675520043871482114824165821076707253213077046051471188151781210045854745122686825634001875705145161781161207476211521582158136022444078200065560867734607332182764026352471435701853451728501116578032177630338218202357557653438474467222565581480245853812301775265352475022207553558507331551224524214615603784004518013782435452534120723468108537828715335072677303608361570345127117201563878786817841344262658438431711430056648466076686083163504461583763220576663244078310626724037075751625643847345836744051581407122781568246235115014228300764512621583865486607256607526605605160465334850304213287235063757525484520745737886638371047838852888516717116278056742340014278728550221126328037218038246527736114007144466332325863043473540826037252737211758146524632045530650202641635343147776611557062320564618047002340373563814436252776485517167615667758806377422308072122136442714307022511541617104642526432540456704217547348484377440604062774127570335350516534173440514330360742623077183818030055046048081528868627155720416713132336857633765588473136721046676436780210586213560874268534301267224208863555310588134624433126283421174122862622486207253502508326707450288042500675105480113132373321776678080632072536801337155137780478385646624538185501685420456367127106410468643614850785368023033138326673615752043508864136420658361166703715858707100101515844553858627161846082343537562346227461771377880146055655174871732557032466838711664612684446475127583475265235130356778643726804124511231383641005601220126340681320648334360544847258226445065631765618362844076302086607124731716680717452877375253441031005521346143117276423576417327357880184345030864642361708501424526812103625635878372630714384037143326058016775383881857236473657255344003253163367042747710250617738016807217235305443011142356708281722754338224351745712654446321651373570177614185674853287186456573154061661776003072384785203315321415322211FA35E674728E41EB9DA7C13DB5A8F531478FFFECEEC9A044376A6765C20DC96194E723D585AD83706A1CDC89107BA0E53AD3892BD0589751345E244E6CD486648AE3D67031137DC64C9081AE1DE536A1CA6841EFA24D33AC552833153D3E49F0C875F52A1F6C41325CE33E259DB3728C2405AD7FE5016EA2E5129F96D455C85F58FC8E84A9B462F77668ACB6F53F62EBD6DDAA8A2699B6D2A2A1CAFE65E3A6022C00C8991DAFB1D1B98962982276A4C6F5C58FE4F48E8FB58251FF8C9013FDE254306ED35988849A461815A85B9E940BF490DCFF983002605845CE695F57E2D749756FC5EA79D5A64D434BC22E11215DFDC566892E990AC06A835B11103AF62A0F5FBA951AB8FBC65DE9C6394AFCB0FB1A91FD4939A3C564F716CDE8F6E564BFDCB4BB7A98289B98C1C577DF029329ABF2805901AA41AD11F2436FA0F10E1DCCA348CC21F7CAB8F2A187174EF7F290C515276ECC1B5E0267AE907763442B98F7C1551990C56C8DEBB9FC93F927C463A862AB1EF1C20597B18E758B1984B37C3937DBF8EB8A45E48CB78D30E9A1DF8229BBA19F5EC0E827AAADCE31C413FCD7E9634CB131C03FBBFC020520EC4213DF7EA9811672CF44CC147A458A015CA9675FFB322286D3596C5304DF3B8358A30DE66645F440820CBF2357723B52EF42A77DC2A92CD2D532773AF637EC1EACB954F771C134AA3F1CD58A108F8D72C478A1810EE3510057DB42A3C5CD12D453B224FC6C0BDD38A0955585D1BB740D1286DCA8D143EECFC4044334A8804BFBAE2B4BFBCE28AFD9113B85A6AF7CFAF87102BAE94FC5B070F352603D12015A0CABAEE3D1F7F638300BB26768062D0E00D3FDF115F8DF085A3CD26655105746ECDB8E341F2180E45D05A32214B8018A1996357B829BA16EF18AC33E81FB53FE03FCB7BFA4907B49B03558001F3254E7D276FB8DC4CB4DE0A7C4093BD346DB075CBA9C293C2FB2AAC499BE7F5D9088B6FA9C7F575C1DB5601F1FD72A4B8FFB9F10EAA3888651B7B0C8B8B0F7193D5AF8D06EA890E828B7DCB4C0CA8CF998A2FEACD3B93BFF4F77862B0057088B4DD51BB5AC499891D938CBE564FEF9320494DC291A7F035B4B03140C81E4BE5A37F334E7F6C1BB5B9DCE7F9FE88FF997FB615320AD555D3939EC0F1459B69013BDCE6CA0BA7125C786C51B9BBFD52D8A652AE009B5FCABF7A82C4ECBA289F00ABEF4D2905BA7B3E17ED59465128B7C9F5CF95E70A98D905C7F77243621AF86A79A266FBF0C7390B65604462596D1113827CDEA89230DA26FC946BCFCF23FFC238A9BA7390FB725758C093EE69192C02B55478F693892FB72076BB362A3B4192C73D12989B1C3358724096B36FB74F6E2B0551D9BFA89CE91572C3B5DECFF8EFDD0D4A9205851C36429A375C1262810C6A80632FB6351198F21AA1C8B24997968199C37D266F6EBEF08403E0194CEAAE7FEA6EFA854FE2B58311E6ACDC5A6CDF161EDB727E096056A68014C4820F8E214DC20958262BCD449517631614DFAEEE69D8424C686A964A7CA40A09AD5EB7463FCF0EAEC0BD2C05B15062561692584FE01F6AEA46340335626B06CE89625F4F2640ABAEA95D193E69D36664A1CA0AAB2DC3B0C2165B1EE3BFE3C6CF6A527B528CC2E4363F1C4EC6A4336095C4438996C0473817179AF41AEA069EB74E77EEACCD1CD8AFF71F09346861156BF54AB9C0BFA1E7A0C64AC7BC98657E93EACD9F27E1A6B3092297836B290C35E2844D504FEBF10BD9E59EC39B433DB7C503B0B67DA516F92759F4CAD5823BF78D4D899E883D92DD8FD8E61314EC01B19D6BDA9F6B9153091DCEDB05C31993B93BFC46FFD87B7ADC36B5D7AC900BAE97C1449B71A7471148CCC0EB1276990FAD12C31B75068E3219D58F40CCAA9CC8DBFC3C05896684EDC53D514294335AAF5998E09923FBEFEF44339342626BA791598C68BEEFEB3A8ADD8355C502FB5DD8213AA7A04612565AE64A4E03EB03179165DF232E99D745586A5ED40A36D98A72E03A9373CA7D1E00CD394F577D54A8DBF6D0AD7EB3B3A2E6EFA9F5AE208ADD6A9513C7BE2C600210EC6A45287604998856EE5C0E4CE7F9DB87ABE704900F58F544293090EC9C44F50691D25ADAD0C982858BF93414CD90B8D0303C8C55C348FDBA27873E631040DF16136EE903274B19B6BC705894D208A24EB0490B2AF4DBFE9ED12A321380586E025A6471ACB596C75CC8958B66F04199ED77CD474F81DE5E7663D528FD22DDEED8F3BFD66DC9CD0DCDA465815F5EC9A598C3EAEAFD93668E946D54E9ACC9C00D7685EB2A5B7BA6B71E2C0FFF48231B5A390998243767DE73E020E987847B19FC3E2B2E0414C5BAB904A39C52ADBB86E7130A5E145FECBF335F35189E78B859FFC571CF8DF7738F827C5B8770F219ED7E129B1465253495572D8DC170549DAE2F1100D121F002E7F60F0A67E7C1366E63F2C527D064EA52EA1B6186AF2A2F38F174EBC33A39191144FD97BEE30BA462F02ADD5B35431C11C73F7248056938834D90056EF7CFF130BA08C1AAD6550EC06DEC9E6DE7A7219FFA6CB904155D2711BEA8C5106116733253534D3A90B0269CF7A588414AA02BA48EEE507328D83AA0FFAFA4E49457158358726A2FDC8F48E07DCF398BF22E5C2ECFA45ACD7225743C441C5D4422157C5990E320ADBF893890CDD2E1D44F8BDC540832A1791E3E68AEF48E6E52540A1283F6F1F54A73B3B87CC43522582FE45F1436345516A39C389DC302EB805811DDDD65D17DC0BC7968EA3D6E28C4A62507B710CD244F9297FA171C1EA66B79C11A397BA594EE66D61B44B958209B31853AC13F2A1AF83D08B5FD5A3D043CA15D3CEBD72C847933186FB94CE99AEE5BAE39418192C5BC98A88D32786675969B23C4C83D91945DD864164EAA0F4D55B888552B70B151C450D006CADCE96B459F5BC8570803CD5E0D145472A054B1493EBB8B15C96F9A3F6A056B08672ED4E5878EB3844558A0ABE1EEFA2C84206F1384C827F51C8ED2D3CA31F5BA12CF2D6EDD52D30B8C331DDA7DE3340E02CA174FEA7E86D542DC69365FE269685758DB2CBFFD9680ED480082E556CBCDF18423D5346B978B91D8706DA54293D9742BD72F64A3D3559E06C0BA73638F0F6A15E9C6535A04E7805FC5245E9DB8C5EDC426B697852CD7206C2FC232392D0B6D6B346F2F70BD09EF1AD16DA4454F3C5BD274738F9C6BFAFD81284CBFB7C1FD71D0C14280790BCCD3F5A48ADBFF2E74E88FCE029BEEEB5E5AAD36BF818B51B1C6188CCE8616773B683453A5E5D2C67D25A5FD9D9DB9D35ED3439F9405347C129D845FCE018DA53F287CAD28298B3A35C0966616DA13B85D60EB014FB72F13FC57C96955EE8087240BAB986A7841794655EDE0547218D222294B44D8353C6A6A8759F040BC98CFD134EFACC0DB8103692D31AB6352A26BB4D314BB7038996B2BA5DFC90353A0FC1FA5D7254D94260A332791DBB31E681CB9D0E612DCA1DEF42DDD504E4AD2394905E090990016EE67EFC97DCAF939907 +smlen = 5454 +sm = 7FAA8EE5706BB3DE007A11C2352C3649E058C81109AD823F94C668907732C55B416C228CA61A70A8C49BE1E59AD80516DCA1036CEACFDE12BADCCDB9EB0D9D65B70EC210A6E80B125AC58BB70689FDB260C0A19E783AD501B850E34E028A52C8D69DD98DD7D63882C0E12970A0518EE47F8D107DEB322FB41EE641543A66BCE1EAD61FB605A303CE69FA33BDDF60B772673CCD7AD367AEE3752FE6EFF37A6E7D66E4900E58BDF99717CAD53F222CFB69F65E240E2AA29F12F773CBEDFCBBA08D529CD9C7B044923B7C1EF6EA4BA1A6F0CF8EEB343A5540E6160321EFAD49100060D0CA6DF5198DADA311BC9CF3F9389BCF6A8BA5FCCD16ABC6A6B14AB16674E9AB8F680AFD92076762444D6E3B6F24F43D3873CA98F46EB18C31B9EBE92DABED96E4E2E6B71671D77F48FA453E256C9E683ACFC3A2E475355DFE1261BFA434AB153E65203D898C1B46FB6B0561230C491914C6E4547F22D549E61ECB58F18F27980DE525C537867000FE79EF68E90512BA91DA2D04CACBAF4E3F41876B0D489F9FEB8E4865FA1F07B1373A39BD6A15CF893665973521712940E729242C93CF4B371F1C03BF3383DA70A0ECD1DEF121AF333409F7628F1CBE0F3870A62C1B0D0D09E66E14C8DE1F4DEF62C2436E0D393C49A383F866807F27E32B2EE4A5B604373BD79DEE73F6052D76A83439DE926ABD3F929E37B48F2C2C2329398E6A340C6DA03DCDBF9A02CB58508369160A0B5E47EABF9A0C993ACDF8E6DEE6F5CDE74D7D4B7C0A06D8B8B4DC04D8BD3A6191501A99E35D6F3C3FD3C904AA1A3877D81E1D3257F8676919867B102C809BCDCF32807EC10B411D6FD1521C38F212CCE351CCEE3D1BEA2FC290CF0F6EE7BD15E71411B53A5BEAB7C3D3B924E0E7FFE2AAC82D57AA59A0579032BC74D439124162B98D50E2060C6F6EF69D1A06A2575F57358E752D1A0FC6B77F7D2474B6732125018E553609CEC50E4DC2EE1E18AA2E68382D9E0919A569DE35BCBA8AAA6FC0617FF964A4E6880A356F0C7E6644BD49B34A4528B81011EF948A6B5792F9D3BFB928FBED8A6C5207EC98B825BDF3CCF44EE16342228171F8BE84AD0E2509F650F3F5F844B206895338CB3AF0191781B6DD193E9AFE77FD7AFAA79EDCCE31CC767AD1BD412E7467F584BE5056303596CA09B9DAF43E2041DA5A2AB84080411A3C2A840EB4B34D1BA6E03E112368DDBFCA21918B25C129351F97BE598DA5AB36FD7A54CB103AF882FEF0AC92CE6C4E3DFE0ED42895F39BADBAC968D671E87F5B3D2DA62DA30B43796AABF1442A2B7B42D142608A70CF60FCE2A386EAB4138A1AC7595E59549FB6EF149989F49C6B9C590070089F1AAE7087DC8606465DD8DC4FF148096150750B7F4E6BB305B1194463966086E6192E9ECD7BE540E043D00B0E600EEFF627355D97CDB343F44E086764E48CDA18C273756CBECC6A62B8701C1CEC18365E0B0E50E842749FE1D1774E87D51DA555E3607811E856B64DB4D453B01A40EC635AEBDA99A5984863CE29AFAB90FEF3F139D9B19868FF96B621DE7E041F0748C6F688BA1B1AC9AF30F132799A2A11F22FD27A0A262BDB55B8E674DBB685CDD90FBE64DCC818E2EF3C7E319AC22FE72A182DA740B09BD8A7491C66F7634561A6864D8BF2436C517B71F04A60F42195B0106AD2DD6E2BE7B6D8E2CACD8E21560EBD5E624E1380CC4696DF3CFB2BE2B12407D547F88F92EE6B53B96B008F5037FB785D78FB3B2513C9822CDF3A4604EBA1D9C0D8C4AC8CE8E42D47027F2C26828BE545F68F2202CF6E15FAD3C6F800798AB38F7B6B97BBA62EE764D037864327E6DE002EDA193F2382FDDB92EAA774160A7B61A0A2A0B9AB3089ED732B3A35A693B8C6C11AEFD9E00A83216482ED1C44827BAE16FC3B9DA915D16579D4064278F8F90147AABEA372A24610F3196035E4A3FD3E3B4BEE8CBB21C2A4845B1A7E67838DD4F58A8C3F437DF8E5ABE24A140B7B47D0C8D20F81933BB394CA09C7DC092EF57C71F2CC6EBFC3845AB83A595AB18EE4A5419E7243A14EACF0797F3A6083278F058C04A6020CE8E35E5FFEEFDD7DF6B7F1EC03DAF1488E5B1B26E51A52C1C172236FEDDCC1FB5FBDF28D46749B2DF56EC88F1442D24F77B2F2F752267E2D42AC772A54D702A366FDB0DF688C4DFC854A207E71CA8C3E66AD23A468FE783486D987973D07CBDC273FD9D1B2BB5660C33A4988C5F9EF9946D234CAA86927B85E13AB8B7303C634EDF9773A500F029EFE677CA1AE5D20E0A18CD73A817ADB831B1BD929A47521F72DAEC640B31C46C4227E018B7D15B40877F9F4C668EF7C98DCE0C9E484F2F0493EDC8C2DD1AF4CF074B557C9864D7B90CF47A4B86A1AE3BCE091396E83253D634389ECC38F3053B9A553ADA70634F72931FDBF046B01870D3E934107B0F91AFFA05EED963455402D33B786020C235DA24DD24C8AFA51231F5C07E51A74519A237978F20D5FCC0F3348343602E0F11F8038B29367AD278B96C7779CC37A6C9393F3FD3BD36E1FF12C03B28A9FF79220DC9DE9D64593ADDF3BBFD1B624973520E092653263A98946347931D0F1C11BE2C3DF9E1C5AFAB95577E8151752D85C97EB13DBAAA961C03538D1AF1ADAF6BC095BE6BC6E25BFBA0EC1B21D670737353811DA3CCFB52C142D93460F5D48AD14C4541BCE1F1669C4B9156313C35AA8CF33DB99E293C581DC5455ACC7FCB1033D959C05CC180C20DD9714C81CE355B856C298091D1A478209E9FC94CC9E87972F0BDE592EC72EA1C7C609B94454DBC9F48ABB77C8A52E947D3F7108899C12963709FAA939FB6148D9FAE80EA8CD19F8BC0951FF1ACD3FC3C1498682162A4A636D2F4CAF64F40A57C2A01B4481D4B8301BF6F0DBD860F44133CB018ACA308D3CEF03127C38D975560054247206D3807DBDC65E05063D03139CEA3BF6003EF5DB8019C3B705C6624478FDB309EA93F2128D0340C6B82C85C598B1A01404FB4C2A77F55D5D0496A0F4B1CD35FD742466F9C2E80D49765FCE22D015E06BAD74F0920CD1EF2085F975B1AFD96C7F819031E6E1F0F10FD9981E402241443B73FDEADF04F63EE04DBA8CDEE9C8890FAF13BF730230A14FD9DAEDAC9EA3C6C4D644F770987A993445EE5D218C3D78E8FFDA4A88D82CCCC83B7C84E140EADDAED190DF60BED5863F6205A4EC71687492DF3EBF8742542ECC05EFD4504CFB2C0133E336933032DA72CB59BB940990AF13C5081AA76B0984A5C50BB6963AEC56B661BED96A8441D0E5B91887147CEA3A8A8A8B1B6FE6091A7B639C500FE4B4F9E03F81A6656CCFD2B85CA0171337B2881822855CE2575F0000568F36DB852DAC37836ED0806F6D1C8E593B91FABCF66260421C48845EFD4CDCF6D01D3CD654A0C7B89BEB09C11D6E0E64464912C6A50FE6EE1EA8C93BB619FC08C5C0BE80D54FEAD29FE06FAA6445D4BD8445838F2439428E1B97C1A8819C9728E0563EEA15E980C51A90B26F489CA8930CEF4B53D2C0E5366CB672049FA841EE9063F382C3A978C70923495782409D08244C54D0861BFA5DC57D0F9667735BDCB8F348E295127D0A2A60F58180C364C64D9FB2D3445158F4EF854805285A6A0CEDF854729790D2176C1695D035075A28A66CA8EA4BA1BA4D18FB365F7A87F350007A3F270DA0CF741AF9F67475BDF890AC3340627B508CDFE5787C7D99B2751DB5A920B61964954187B79B2C8A3A999095D48FACEBE65827321A6195B3ABE2E18A255FA701724DC343D9BF0F4F22707538DBE812B2781F4458F08C0A5C1F97F98EFB41BE4BB03653EFB01CC03C8BA8A092C861B8D3666E7138EAD17F6A71A2DF24C61714B9D0146FD9AA9C0A6A8E72D156933F902D1B39BE801178192C66D469F6DCD46D821B6E3808AB7BB6358749007C8D551DD34F81639BB0BD1C330351BE7DCC5F6259373632C63565C7568B144521F1BE6CE2D800762E653B91A02C4BBCA6A1B4138E41AEEF2087345FA4328097B408A531CB75A48C59709F7BBC161570C99801AB303E06BE206F2553FE6855951DC29EA91BF6E41E139DA1BB08C4E6218B82503760ACB9DBC496090A7CDCFE8AFEC895138A8B310B2949CDB40CF1E66E9B30D49D5FF64FDBE8C0B3360B615D79628D8B9CB55AC2144D8EEECF0B131BC3A609317F792D66BA02D82E3BE432B82B7AA5656A03FB2315F6314C0967731932C6D5F8D19FD07E62C2D8E495DBCF0617C60DD6EDCAC0A1F59F9F1FE22BF9732BDA2A411D34075BBDD683370B2064041F75AD33088B89967099311CD12F2ADEC77EE0ACF86AEA3F82C73EC02D4AAED241BA6B9428A8706B93CEAD5415707A4266BA993B567A17D06FB0377E24F4075BFFD61090020E8365138F577BDBCA23092790C1952618EA3FD1B60F80F0FAF0AC63244E9DEE1F6A25F36D9F41DDBF354FC58FED57048F3EC10D3C4306401EE423DBE91A59D431BAA6B9B1F3C9DF52E7D63E32C4B364F1BFB4078809BCDA131DB1D5BD071427D952D9E264140A7F503A7EFAFEF96DBB62F50B3A5E27050CD50BFB0B601A7BE545F89977430E0FE1176814151B757862A806861F3859A489BE54F841AB4BD1F45B8D753B296076D3EF011B212D5473CFD865B3FF0C0E728187D933738FA7CEDEF60E141F436B809400000000000000000000000000000000000000050D10161D245180B7DE9A84F651DA10D334009B3D65582F3912D329FBAD4AE39A9EEC78943338C29DB4F49EF41E3C50DABBB530E99113440383F20D5A3A8AE279A6201A0C84B003F6717C709C21AE893B6E412D87F8E0CEE5A89E60A14CE975A4D42E4F43F4710FC9FA29E9B2AFA93441EF5570123AA88AFF009E2507A3E60A79CDA25652E3AC3AC0C10A816BC04739B6FC758FF9AC467879BB67F270E4EAB43F10A633E5932B8D6DCF23814DE8643407B17B5E2A91B340F7BF6882DB694DE4DEE4C480CE037B9F9A220ACDCE84B03746F307A6026531D712C0630E7DE3ADD3A8516BA602D2463E3478008B3252B658FEA54DE41265B5C81E4E913EA0E2A63309497ABF961EC40AC374ADC0FF3C6FAE9BFAC5CC2DF475885B0BC636702828489183CDE1A2934F2D63828AD1F2B8CFAFFA53151B0FFAE6224DF54C2AC47CC8844B76222C2A3B6E132071150049B6E46AA75DEA28C13477980315FB64CE500BF0C6F633AE621D65B331BA96CFAC162DD7897B8505257E228CB621BBA9176A7AFB3A2CC20D7804DDB3AAE4B87FFAFD3C8DC541D05624DB02BD62491067EC1CDF73147014FEBCFA5B561756D5E7A13B88D1E7B2C0375E1D0DE71ED20CA9CC4E6DACDC579F1AB024AAE2A0BEC9004E5DD81C046F00A2A4CB767C4EB240D205278CB863D1A61DEF16635C6A84C2406288410FA4B73B21077D8F7A4075A1DDCA3D0D334725151E434BDA80D3E73593338B07958D27337E32CDE0010DFE5E58B99EB27A97DBD1C5E6F9A552A02726AAD5A4AA63EDC336D83E5870DBD514193367AF2274804628B4EEDFDA3B2A155694E89F5A6798C5D6E036159C1F00D8DFB03D41940E775974B11C3FE4456E07B127CCB44E6FD6B2918F57A6523D7F77F32478D9F1BB539846793D4284E2907830E5EA76054802A266C85B122A389EAF4700629036716E2869C0FC9440856D562711E903A1853BC68582A95344B612E5CBC7C5B2AEE23CCE4161A75829B2048742FBD65ABFE2397CC7D66023DE34DF4F2DF8540CCE9781ED6482D29CA4E906716C8CC9596B158EB51BAB8C2E00253D6589A99B3D20FB494834B42BBFFB80E7B0441E356B541F83877736985F6330EA459C007CE8BF18D84E78E36482D581DC7DF97528CE15F68E604B4DE62422B3AA76F3E7E5B33A49CBA9D89FCF50DEB65EE45173795393A50FD4C60CF6BECBA7E733513537D13F89FCF1C4D6437DE0EAE608FB11D68B9ADC0C3A19A3565F6D62BA81A326EC334B239B212B87320C03A75C58DC8F828C4195ED9D7ACDDCE493123E235D098E9DC60F5D3A625E1FF66F245E9977F9630A40D26E3AFB6676F5122A88CE5507BD825757D9CCD53FE574FD0E6E728DA355403AD664FFDEAAF636256FADC3283D6F15B297F79216833CF2C745C4C5E17D03260A69178F2216168BF8F00C9889E1E35540254F150C587A884CDFC9E5F7D379BE474356C06943E416EB0697A1AE989AB4872D0BDF436D9FFAAFEC1631C9939FCECB84DB2846F12CA395F506687B4A5638085BC6EF58FE8E2ABE9F8D51F272EE855E2DB84A89D348DD66950B8F43939DB897C519FA302594FD1FBD6B6E94CA8FF63A7949432DC2D35C60803A570B1DAC95EE0A60C62FD18B3319601AD29A156400D392DC9A14FF50AF6752C1F6EDC2ACB7ECCA71097B6E82227DE429F1A29C5E38ABEA1C74DE06E6788CB1790AE9F0E8AB35AFE60B001F45971D42949263AA62519B0D630281A4C5788D5591B1EF5A003C58987E8665701E5B1C6063F93533094E96820F918C354903775CEB6675C4CE9CF940C4BEB8845B4F5E1F642BF505821E5A23122E2D1ADB82A63AD18CD1E4775A96CA9EF9493D75FF784A2D4A99F54DC3F87828BDFF4B3A3D98FA5A29B62A85CAAFFBACE4592A81BFAA5B8BAE6606AD25A92A43140690A6003AA2D617FC707A53EC9D868E33596E098773942D798263F58FE5A1B23046CFA136EA35203B90BEA2C5F0AAEB5EA8C24B8B8CBA14CDEE28F45D0278F193228484BCC7E08A75D0064D605D674ACA9019A0A9AAECD6AC672CB8410FEE4192E6DCA7855FBB1C584CF288BACB40707D7E6F8BA2956F6D099F52BC7B0AD72B5A3FFC03C7B47086330244EA5D393C6B9F256FD82D5CB9436A469ACC3F8FC237146895BE148749F82D39B7BA4CE47715BB393A96AB471665529AB9E9958B12396C1BA7529DBF289184FF0F635C2BA9DF301036C869D52D993463222B70BA778E81C8DC668DE41C0356EEF5C39F1BD42398BFF30F959E115C6B386E73F0FE28A2665BD463C781DA1C46D6D4EA284B152C8C12426DC9CC467809BFDA6FBFBC0BB4793BABBF6AD564D57AE9F5E2B7F651D6ED980F8B1174A126CC58B23C32BA73F5031B3FCABFE7BC360AAE412D799CC14D8B252D9F9EC9005B7FCA04A88CC8AE9F7AEFCA94137003D5764FAA3C7C45670585C84F74C4EBD1F5AD1F97EA093595592FB90E3CAB01F98F06E114F13DE67CDC36F3FFB01C3D51EA643C25A3F6AA2C57690E42B98583D925AC7B06A349782A1D33C06BD05A82A7AA3DD679326D948D74A1861926B45DB78D36070D3087AA9C5F4F42CA57EE9CE7035BD88A85CE1107C8E07E5BA3A62ECF012BC75FBF97C4C72331B55AB9A6EFFD78869F1CD3F330526F262F7DFCFA2B084B61E90772D5FCE8F038C0F72554467192CC8A27F1F53C8714DA1864815974B00991F466648478C5F9BF036DC4083D72E8D144AB10FD32408DA7677729347FEBC79E48E7B87388D9B59AEFC84B5B3B589FD91863811A6436ED76B43E657F7EE03EB796285A4D93BE9AAAD1E1A1E81687E42EC83F3DD059B78BB7F8EC70E6C831DB5E90C6B3AA511F36507DBC8E7A77DF0F5B9EF03BFEFE9471DE7C7FBE67B9922260D3703D95A5BFCBCB62D830E20C23C6CFDDC210E47CB575957D8C3514A2ED4561C738928F210057896EAEB1499D4DDC70F44E30661E780AAF5C0A20C8553F40D7D3FF6D120511C1073510D04F2DE544121AB851E98F666906367C21302EEFB1AAA723F6A531C454EEA0BE7D50 + +count = 65 +seed = 238461A224ABEECCF709AB6CACF4EDD372D45E5F4274095273A49AFE614F2BF713134ABF68B4DD058E6D7B612C3658C3 +mlen = 2178 +msg = 99B5B6FECDB52897A1958C5C3D1FC2F20B7D045F551856EA3CB441BAD9089C64CB9489DB6B63E0655AFC4C2FA73C7417FF1B80B9C7A1D659687D2C415B3A909CA30E96849D4BCEC6A9A6A4311204936BA972086B2394D86E840770D01550CAA6AD85ADC0EC851D2B3808E4A0E9830B99A70F6204ED4DBCB6759F6228126039607AD7ED8EAFEEA28D1C3E25A46BC18AF7E01F55FAD8244F15DE36F890416AA09548554338972C5F88FD9357792819E51A63D0B872B0A4D21EA3597405B52793D50C6CD70B52841D53484BCD3EAD004CEF0A6BC16CE74CB8AD0848000D8C5158DC16625112D1D85D17A3C1C8BBDAEA42C3A43E9930724655592116C4C6D0B8B223337EE4E754541A09D898F7FED71C3785B7F8721653986C525BC00F15590616437D11F9722824DFDE7E9615F1FB8488E5327E4D8BAF5F79D1FF5E808D154951AD87638910607B03FAAC3A61FE9916BA65FFD16986DEB4169BD24A72B1C8168FE569F3C81F93F3EBDD21D4E806F79FB28550912E9AFFFB52E97860C4DC0D042C56E1BB71C28B68E416874EC7043306A29BD1F4B9A3E612A6778315E2C2B850D6EAB9FF1905030FADA250CAF308735393C191134F3C493D00B5695775D82ADB9F2ABDAD17FC41FBD7A1DEFE337C2F8ADF69154CC0862FBD43035295B1A9C80B88FA8CF75B36CA08868F881966B41FB3E239EB1DB9CB51606A0A9EBCD552B2F4E819E2C30ABDECCDDE88D2D2F82F3585B5143943C929591D20CEF559CD2BAF2DC7FE03C9E4E084E8890FCE64A4AA9F13D5EB945AD7E3CC53E01FCDC192B97ADC1F98D9E773A0177E8D97405808EBF48BF17B689BFC15F4C515E38A855A9266230C9085ADC9A6DDAED93D80C3F38BC516695D202B4E89DA5B4EBC43788C848F8C4A72F79F37F857EDC105F13E4ECECFD09302711BC1993F5308B8F32AB96FB8EC3F5EA0531DAFD0AB3451F81F47E62C593C8D3E3BEEE79DB06909576BF876145856F5F716CAA436C98EAB28C5B85BC2E4D7E1653ECBB8BB6B5BD6981DC72D7F63BA06CAC8197ECCDC72C1481DB44724A3C21F7FC60661F11FDDE8122DA5D0B1D72A29952618B373423A892875E6AD24D0916109ED8E9A9A8D9A68ACEC4BB5EEB0D00EAEA72D8D5A76C2A42F18CBDB3D336B71C70AC73D39D7EB04533453779A1F210BB4FC056B4728AFDFCF46675C6AC76F750626D642E3AB117E5D6740154759A46C27D51306587650E1039054B876849882E7DFD807BD03E69021E337DD69D9B097722C6D2AEB517D773D2F7D84D69DABE1A1D6422EA1766C0FE7B8DD4D7283F2985D96D91A132B8BA03AD85F7D56095773222D0AFDC5A192D29F3BB0C2539A1C99DB4E711B6ACE3FEBD58E45E99C9F5A04CECBB309D50397F28C48BB9CC9F9CF75A52253B634EC47216A1FD6358AF26501821864569879BE1736B0AD242AB5B8ED16A7EA0989ED4CAE3567AFE1F8209A028DB46DB0270B3BC06668A9BF5E1BC1061BABBA00EC4EC37280379139D19BC6072CC6B7D260A816CB82F9BC90897BE3025475AF12191690F9F400A914789A860155EFD2D606A15895378C827F2A4FF700303962FD96DB2DCD2D213EEBB2460F0B753BC6902DA81D44C983DD027F1171D40A2039997241E09AE5B6165B4D55A8E4C79671A8B8BDEFEF2C21F81C541A5719DEB939F866B61BE250AF371CEA7B7525094C904698D412737F7781BD779365F122EE627D9CD4A68DA9D5BE1B0431998AACF824CDD864C7365C01CD5A5F480B6AC1E5FEAD8FFE40D87C1F9FCE81867157242285C5E76CF9667919C29A67CA0C0A61D7819D9EE6B792250A358F5691CCD80578F15288F3D5D6D7DD6DFA351FCF8DF0223F7D1DA1B76711FBE0E7FABD30377660ACE7B23ACF03ABC1D973248CDD0897773FB74E20481EBD3E52657C9296B980905AD29271EC128513284F1B78F38634BF84CB80791A0C5649177791CDAB87769D57B626F78A03435C758A207F52BD2A1F31E34B6A122B8701CD9FE478C57CF3535B6D51EB46CAF794BD69363D5A56ADDE6945E9788F1E1DFD045BFBD0A68834B13D6B9EC4EA9C860EEA0E9AC19C2DE14FFBD6B57E5992B08943EA0283813F3F15E4F928B8D0F13DE6863990F5C77F130C97D8BE12571EDCEC7DEEC4B6EF4835F136DA45DA70A11F9192478FD8B4846C507410FD11668365B05252E68CB2C972ACF50156E369B83BB85E62E4BD4D84C2E9FF41A5844D5D88AAAE7DED852DAA0AE5C14A5DCE64C7E236E9B7B60F5B5AD4D953A2D842A52929491BE3555AB8DF534CAD56DBBB86B28A8A86B7BD9AD1C58C87B8A089324E00FDE32F8186B2B74523A22904C18ADE02C3E965F94624F8DF57E750EA6335E3EBA705294B76CD6ADA33D90FEC1F48DE7BA9DC7D8D60A53D2563964188874810C45736C57EFBC3A3CEEE7238AEE5281882A554F2143BDF89ED4BD819C08239C187C12A8B6E763434B92C26FDD658B350F51775C60CBAB7A2CB120DB8CE8AE9AAF6AF559F8CADE84C4820209CBD27CC09230B22F013A0E4CF8041E4A789A5D20BE9914A624AB957318848ADDB39C9748C8922C54327048A2E46523BFB22487538363459035BA49858F85A469957DF1F4831BB7FFA0564C53233B99B596F5356089949306DEDD6B904433D25C4854A80590B964DF6B0703B4F9628D6B9A4D3F0A4096E9A0B46D6B32F66D563BAF688ADD18DE001DA62E33C503A4387CE0920BA5D1E8B69C38E3745B19F8D8B6CA5E1AC6DE90EDB25FC32DF04F0849D769FBED3F8169EA1D2252619A2304E055370B4443CD23E56D4934F9F3FC92F1C1EEC626657E6A89C1394E56061AF8ECE3E2A17FBAAA4D579A99A7998632A6AE2683DDFFFFD27A27C8815511855F09ADFF7BC627A7A5C95FE57FA3EF81F494FA7EA6E6CA2D14775A25BEAF1B5A3E35ECD4A306545D597E4E44301C3D1648F0A7D841F2F76FE59C6EAFA3F5B58907FC4E642ECD28D16A71EE3D295F1DE12DE1485B9CEBEB2CC6C9AC051D3D42B6A1A068533A7680A98D015B09C5B819FFC61688D441C1B7FD71180C4423E64EE940917C7DFAA19F3F51CB5B38D1B2B7C81D10E7C +pk = C5BED41F1D4524B91B8C04D0646A6FD5E53A8B08C837B62E9D94F795C1CBF62ED407E423B49CBC600491043CB2A565B5D4FE1839B695EB67F281E32C88F6BB3F31279F70DBB8E0785F5E0438A7ABF9E4E81D9E530EE227CD62BD417FDD6DD2CEBB2028840E613C2D74600F0AE5C33C830D75537C86BC5DA3CB1C8B36A9338459C642A14EA9B1C6B6B757D4EC1B8D74F9C04794A91202D3D9459F275A3B7DC0B79175F751693E3770BCB9D8C632ED23F6EC09C1C16A615D361599FF159DFA384E4A020A5EBB61CB15C6ED37410ACBB6318B22E3F381180B212A480C15CEC0E952884777E6E3091FC43141E5BE11F61AAD3E5A5F95FF3229A8F738C75A9357011C8BCDBADC11A6BAFB6933A739A2098A5FDBF93EF6452DB5474495126B0649B1A22D8793A03928DC07686071F6CB08476C2A0A040E064057976C521837F9097C9C9A5DA6535A7E766509CE16A832BBE03A02C7CE518987A7150F0A7B48BD6A93BBED91241ED7D9FE1753F941F2005059C480A76DA23DC1B751E4816232A540014045B889D618F056186445265C0FBC8D34032E421FDF8EAF5DD1CBE5F919C1958226B65A22F1E5BF3774542D8C49E3274C64A99AB0C8BE1A7E56BC1B30A22D1021E21E3253BE8DA3FB6F36A596CACA95E0A41A96BA0600C0924EB066253495D943883A438C7618A233AF8C0A6BA7B51EF15BF228383E5C247DB6672AF9D1BF922F5292FE81D0FEE62366FFD8F59D0CAFE635EAF83160D72978AB7A5D9A50AFD73B1E9BF57AD9EC91D569D19031285349BD09F8B44E0CE6BC332BD3AF4AC3A741E98EE0BCCE739C4983A68755EC9BC68811C692CE0324A1A9CDCE987FA05C580C093BD8444F784AA6FD971236757400B940DC7CAE522A91ADBE3C8A3417DE6B6B2968CA2054888A649F9ACF2674E80BC06C9365AAE5ADC4D3D04F80D13F1F202E10CFAF939B13E6449A7798A9B1AAC68DECC3A1A163819862C7547746589B5FBCB54031D49F2FE91E67B6BD4A8BB466DF470B624700FC8B46926698E315CD243DCA5F27590418C703450075B928EFAD47FD727E0A40F637B49A008FAD903505BC9663068A77D73BFDB6ECD3C94370F0F6CF92AAC5F54F9E9B3BE32CA8E864CE3EED7945478846CAF340B07CA3D00DB495F7DE51D4035FA3CAC8C189113FF4AEE626ACE74161167F025F93760FB975DF3EF8CC0E67964D36FD5982DA3361371FDFB7AAAA799307717D6D9943762521254736431D384DBAF73FA669942D66FDA9DE954588869A9416C2AF1BAA55B36F14FCF49C6CB18F0F925F8F41F45AC9E743B059BAB5EEFEA924027492BFC5333198D746BD7C6D4B6D89CDB55D7EB0D704389716B87E131FF6282A835EE191F2FF320E79DE372EE24ED03A60CF1D268E417792C28E142AA6CCEEE451E6EF7AC00062DB8226C34ADF6716366755468457E52BF1DA9D5A5FF4970B0D7C5EC2E8AAA97237541F5D214E621BBEBD2C79D376BFB2791D615459D38663672493C150FD7D2B90C21F24F70A8A68411E5F8943E680EEBF80CB256911EB35D73A5EB98626AD583B22984393D94CD511D53886335A6478402B98E0C45A799C4CB22BFADA64206272B080528059BBA1C4F1E474DA4A7FC72303C96F71AAAD34BEFD558DAA0002DEE7AB9FD63271D92E7D12B4293D22EFAAFBC90720F3D0AD312311E77349713004067334329967BBD4D9F6C01501240269AE72375073A77BA0D4385963D9081BD5B8856C4C2D9F55B68BA3BCADA7AA1A7EBD6169532572C4FB8D010784E9284C9D354D76AE0E0C75E0A9470FBA572D8313963DE213CCB1EB50F37CCE12A5E86F1BAE70A40D987B66259C487F98024A37D82F4FF942A62C2911E99CB32C9FF6AD5BA290C354445050789337AEB34DB9BB0BA43ABE0B825F84B1197B8420152424E2116400C0EF5275E3CAEDA34A91697626201E7FF376FB7C083A2A763A7CBCFCA199824787200894006F6CEA24CE5E4CA29FBCD287D1CE844CFD7001467132809E247ABC418F736BBB5CB894B662C5D48FB14FB3AF12F8C0F43978EAFCBC896255DA1A214718777FE68A9E337300E26698A7FC0D9713AF11E3A8DB713902C57BA7E4089FA90C3DE079BAE20729AFEEDCB64287BDB0C896AA0E889883BF3683E6646469FB5F243E8EFEBAA3259E319D6096FE97028F88549D476E8F8585F0DED722691649FEE9ED3B425EF263033E199410437F08CCBD9EECB270EE626736F9FA1F3E91529DCF3FA1B21CF738BAA593D7FB55011725BDFD0D12272FC8AF1A1CD19842F2791BB1F86228091323CFE9DEE8499DE663D36C295D83B3EEC68272CE8C435718FB7402A0C5677CA95AECE347B4F352DC1732CE7B8F6BE0ECA2ED359BACC544BF3DF274152D235F978045ECB77D5176FB6F904C71B4AC460E223E1D81FDD8B1A5930364BF371CEC50A9F736732D2959CE301DFA86297D17AC5EE3242631A4225C5AB021E65E6C000D4F62BB987404509FFAF799BBCB2094A77972576585DAB0C09143E688521C0D8C9088CCAE186E42A6FCC9D6079EF681BDC44132A2B54706CC68DC4692E0CAC7BE3A2C5C0EE76E1DD9160E365D91C633E9DB34E308FAA1B99CE65E4383DFBDA71922DE23EF2A9541251CFECF7E40FCB520BF89CDBD40F2BA153745F76A6EDABC65766B47307254CE96AA6E507E12B54733FB4B8271F0AA5FA01AACB6FC4BBE978DD15F9944C31227BCC7ADECC7FFF0DB80F50D6AED08EAAF3D00961F05417C2D78F0855471C6AED95E +sk = C5BED41F1D4524B91B8C04D0646A6FD5E53A8B08C837B62E9D94F795C1CBF62ED7A62E8740C3CAD25059CD0AEE71C0B955CA0799DE48CD66202820DE621516268ED4FB2D8C9AEAE9AF5E484334C7772100359F27170568CD85B2D18EB1123A126C2FD82F5F80150EC8774B0CAF743F75D3300910823D0BC11486EFB4A1A6A64555675055417325538544578504847651232785455303810758450733675647833070250508232614282816483641054445058160372371446307057011405381114602418614661775473058733118737047332684235672726337424803882577326726150288403157686217783143802654486603840873242887511018000451802482827461151406015404028703637102218134130212532675346664618817423055886304153380315480786384002301048552581385754574028861510106078145043481177270424107636248177670667821224766172650636165011856815325667562752127017572267703313145042670368231310081547143518533743250027040416307016448505706144663864830320320885746564536002273113486343147125044306552803872424558527537723834482045500803866342515338571256628834514265488871526124577832604433515205505376776657131317468152158583602251106607372570815436363837312064388724217238126135767266356362470578023240537685700362483670857478522643171101410724753014752002061873451244672005271055434010057240841136350363726324665040240186038126202762383615432734530411032856604625018773627836475382371684473142782267272765757500353765211422412172701670831024347461282164568012688123008211188273738400156187540865057114601803830053646077811021114034864225348072400647833847328802548006380288244074515557345458168225026648740222047611456327851133544156015186534727447888135324765653630172538386636568833201844368776504528014587825411618538732656574651717035207241773747173150748553485473687350023323753064430752683366705645256124465236161584788371170348450377611671404244373848736444234784042767666304605055584267641247462625663152706600615531414023477075417665313051106827051164552475008476044341142533407387615311688678105081012820210148573187337753531478775621852154285833553024085750488235014652768863688821103300841668814730387327660035741882552811065458845306008327656515320651240255014318223314545266612000177064778344341415618466524662851027004666014626738770752451660344505782258125812444180142410041421800483344221238543636447677175355543053784707082603604384327286584603710623028384325160467683337263665645242801422487202534163843345711057375818052052514670270374613677126272134835014408352102608222157100513533006488733077556570677785315667685818660827568117028686334876452707161474178686643668763528108520226878267080611855712636005301208882550545780222733713735261404330558835312343533835326487544051411334315724482367468612268437408637738543388473415038375471013272066385810370687651707087657772163366582035525410701722415234588085585175618324440735424664552371208786845537560117204885877516817251672031688720305036300055312887224720725314625030880302476045272523310408837083148602310803001826310770287466614446374442757648756008447187710552373558050426456168834876104145863183146628031485552576677534068303074763381484846747451656557275652001107703865137826854466501487231338482011853731005224653664643C43C09A1E7ED06F1E4BF4631C2D191EB024D4ADE72C430C523E9599433BE42501C42A8A1806FB181E190C8F08FA05FECAFE5621244DEA2FCC5BE7218D5040F169D8B35B7F9B2142FB79B05E1233FB2B47D17BF5F8ABDD9A32B4D77249BD7370A2328A4E9E3DFD7D08D4411540CEE8573B785E6CB1FC5E1740A52B8E139AFD8793BA10D5F1A5DCD02453C23F316ADD43150BB105969A6C95F70C698604BA4C2D47BA51CC27EFD62FFA8A3CBB2A998DA88D2BF17212C3A3372F24466F11E1C49DB9F238CE3D70BB5CAA825A79A133A39D05D417E6623347A0BA70E66393272362DB67C8DB7EA43DECA705D992CB2DFD8299DE82789A15216ED4026BFFFA8D757A3EBED070ACAEA8D19F62107F83000FD6B995D3842F56BAFEFF59A552A14A86788BDACE4B6C3A363B06196C584F28D117AD6BC54A70AA11C8FEF0C61FCE605AAD7581478BBC7FCC8ABD852FE71724ADEE15BC630216966D77F5375E1C34D8C02809CA85EB04701E207F07B14731EB01FE2345C0239A42660FBF7E17C47EE9F52339E0C6EFE9E71D7C4BF955AADA126A9802C312CF88093F94F60BCE0CC9933B9B64A3C0CC7E7D122781A7C65ED33B7991C9A4733D355E01BEE3F1420ADC07D583F70025C32D800D262FAC357791FA02251910DC019C2D58CE8C2CC3AF983C60B9EA2CDA510C7A30E4E759214F1C1D9F9CA8CE3471C87C06718AB29DD5D46C651AB654282884C53D6CAC8C98833D9355491BC10541B5252972DD735996888B2FA6278AEF8388B83A15A86A5F2DB7C62A50AAEE89E95B65041DC7FCC9ABF3EBEE18362F857FC99DCE157131C2770DE7D573526E252A271B09C9CC8AF48FAB5EA7AB945A4EF92C4D815504894055768EBF8D73BC2B4243E2DD5367B4061CEAE37610DF99468D9695EEC821D2DD9D7B267B2BAC6011A7FCC5927077341C161D55F62D1C647B032829B2031E8DB74655D28F423D7C8F11D669247DDD01DA2F1FEA5866FEF8846D341A7CE8F3AFE56B186A319404752384C3733D5F38AD5BE4E833CDDAC6816CDB25D62135FCCEA042BC8B4E4BEB48BC2D401202FDEA8EAB68F9388879D0369E219A0396ADC637B10B6608B19C0915B622E8708F1E9FC38941D7D5E907A1151CE4B566E999ED4A47A13A24719210E936E69C9FE60B67FA12719DEAC4B98ACD511536D4B8A8DB1FEDDDD7E1B4FF0B15F9CD260229780827BAACF39BF636761DEBED1C2054007726758D1A57ECFEE87C7860057BA1CEF717E0E143D7246F6AA0BC2C3052DFB3FEC06B830BED30A26AF6F021D4D7113BD0941D4D64F3EBF6DB866101629BA526D5EDA7519B4BC6333AB565182011DCEEAE67474B6535D522B0DE47095E98237E2F631181DB08A1A4A1A07F634BE550A8DFF5465A3DAAE6A464B65BA989E3621CAE9DC806D5298375CE6FE9A7BAA2DC0C5B38D2B80B04C811EF1273571632787EDFF2CE1FF2C6F16218D23A36E587D28A1575D19221B52C2E093B27C834A599814EB8D268F1296F2B80CBB651EFD8241AB8AFA8DB0647FDB927532F29014084F7C8C32D58E6A6BF5BECECAD109AC6716FB3C72E3E01DB646A4B2B201006C42FCBCA723175DD15198149B2A8751956A5D0B87F8A7DD5AA411CD8DF17665D2524AC27A1A7E1060F4ADDB2FB4D42C59DE6728FA342E010A0990039886B1991364BFE127B513181B41B7402427EB03E19606BEA36D1E00127B8C3FEAB4A399F252F3161E1C79D5A52AD0E2E310957CB96D61E7CE0E86B2AEF38035125C6B106B898EB32015AD4E1B7D6A58301A6116B7063C86C1FD9341AA7205297D3C8F815A6079FA921B92DFF809A1EB70DDDEAE8B5E8D06FFDED5259522080344F21CF93EA4C50FDE83E299052ACCC3908ACB1A393735C8BB49D86209D50B4C98C0DD1BB1C21EB906CA5EE3D4E5F9FF8EB36ED5ECD0EF3DE650807F9176294ED518F7E92405206D8192AD708C16E190061AEE4D0B62359579A21859CC31A0A33CA3FA04C66BAE517039EB7771F40CB0F21742EFCDB5CFB66A500FB93C168247C97BB988A651276AE1A6C9BC55DD758D5FC7370A2FEECD482217ACCDC23465C300B474F93CAC5C9EFA7CD49F371D1D82EF2C887942A5C887E7978D4447C62C4D800F9707B6542193DC56510BFED2E51BECA3EC9199A97FF03C9FAAFE86F929408D60BD5E0474B99EFB3B4D65E8CD9973D9E9BFC36531F59505B9210478868D431F83A10BF074935F6B7E0546EC11BA80B78A880673C2CA49F0B4C2313E12675FA91284CD19FDCFC9F08A881FE28A94ECAE9713ADC54FE351CE50E849A1EE6EE7B190FB6933CBDF41864C754D6B3D8DE693729974AD4F808938B0B6CD5AEFF5384155BDB56DDFC0627625D34AB2C62DB9131B3EE4E7B8DD7BCF060520ED9039CDA021DF23781FEDAE93F9F14494650093E1D5ECB93DD544989482387BD049ABA378EBF286C0114B9DC09AFEA6AF217996309C523432EB2A70014AD589D44864DF44C548E5D9A3F8F33D2EAC0570326B215F0C52965594D0FEFD060CAE2266507307818729F80F229FED5D0C6EA72996EE8956A2E964A03727FCD8820A12D4BE502B64E822230050EA2D74A29E5ADB776051484B417BC6E4440DCC738F6768FB0CE186E96CDD54C6F27FAE3B2E07CF09146C0CD732E4D71ADAEB132CAD5F2085D114C359A9B122720DF0E7B8ADD78154BBB159D3936719AF5848DE5F213F5D11FFE00CBD8EA00A0072421331BDBD58DCA2ACB49A486A3C3E9E155BFFD3ACC3E4B7BDF120F20165555C74FCDE579C21B09A2BEF50C1401A19202F50443D4C68AC125B991965B2BC2483E37C68FB979343ADF436954A59A0AFEF4A7F04D5D6F19397F7D8C100D8683F153AB9CDBBB22DAF6E47C018D488F8D0E0BAF9C3C7CE56BAA85606F5B700D7DFDF643179D3CDDE0D78A6901BE7FB35A954E1FBD5C285D56964EAAA2F4C2247A4DB5279800AAB87FA44AA3ABC76936505F5091B45CE10774BF862E27F83D7A20B29F54514FB374E89B71D0DC6EE769162196A2D30E42C4C6C2F2062198CDD7D89908E5A22A56F442FFE333B256EDDCA1B7504706FCA20A681F530E16139D58604A6B749B96900195AD5025A6C328354A98397F87183289421937382C46CD6E69FBC245DEA1F603E0363A75722580766364FC7D52DF9AF441470229B08D14153EBEA91364A255433BF51A127DA2F8832ABFA00CCC4009F85BD68104212F7D650C69578CEBB5002C329B2CBA388EDF2C6645D812E7E46007978549D56334577E3F2D054B25F8F0D16778AB35B5C7F1E8E2EA618DA3131E8BE5DD74AA8B00C9CE402DF05A523FAC04D54EC7D46FC90F9B3F2E208A6031A57F0BD3089651C3BD2E157BD4DC79B3BA7C430D19CD370BF4908E59BFA6CC16C99677AB77469FF6D419C8C6F8B206614D967CC9E13056B0D27565F84B6B0A45DE020DD4EBCF32F17B0BD010E32917A9FD49C1B956FCDF10A70C80549A68FBD61AD1C51A30C2121022451F76030632FE086DB06892113F78E0CA33C3B3A00822295FE1333 +smlen = 5487 +sm = 57226225E14E2B28940C57264F6C820B8B2443F23AF73BEE2DDD143AFAB463E1D0FFAB9D34B98CB57BCEEFD73A514AE1C87D832FFAFC9A0402330586B4605673CF4FC110ED08DC35FFFE6828031820F34BE60B237D29B4339633675881AC81020048C97AE27C08010B92EA3470DD3DB884F9913AD673228574C8D4EADEB832FF6F33BCF6E49C3AD5FE958D36156BA7F8A28E84C83A0D26C9B6C0A269930F67D8227CA86A7DE0B45264C431B73B19810C4B576D1D0F48E9E91C602FDC84FE24EE548502A9BD92822EB8C5AA30181DEE240F473CD20F2BC6343E77FCCDD7F111CC9B8AFE82ABCB246A718EAE667A528E882291F8CB600F8EA5E564EDB602C17881E13661062EA5CF36AD5CC3DC89FF160261E23B5A9C3140097451D18914AE0C463A49C7CEBB5B1B1BA213806D7E1EB76BF42AF2F2F951E7282B6FDD7FD34CCD08C74182090570864D53D69331BBFEFD4D9372EEFEAB4958304998D7ADDF4139E93DC6F2E67B4368AE8F493123D6CAF268C2CC1E36A11801C33316F66D9AF46DE50BE2DB9D2C40CD85B8D5986464249077CEFB31F5E91342DA36CF01FC2ACB4E8044EC690701196E59EC57B2FB9233F314B1E4FB2FB290295E19D35E2A3734FC1B6049044C629BEF5B14D9BD2CD1F1AD88D5665D8F41E1B90F2F385A4600F6A53C96F6F9EADC38C9160C7B194514859451F49DC0C5D4BD823547C1F3FBF1118CE20639F3F330C4BC953B723D8DD819EF1595FC1A64FE32EEEDF568EC339D9A8CEC56A566E15A0C3DA2C8A8D25858718EBA50628ACCD063E18F303CFEBF7E10DDEACA1F46030B0B5BC0A70168F6C40F7E6015DC7187C6DD751868A1FD6BA2432CF1BF69E5CFB87E2F7F49F3FB2D3E839F0CA19C4814162BB330CA9D7F41B4F014C8CD717BB5FBC8B99F25C31A3DD080DD30050831945140F8BEF48DC405EA5E460BD2EC91D07CC898B744042B99A7BB5EAB087DA53716CA42E40EEEEF43EAE21BE4378FCDA77A996A532ADBE26999EFF2DCDBBECAE2DA696ABD66BEF280AE624D0AEEF65E6BC029C2B80831B5FCDBD7CB01F9D2A16621D24523707FC06C2DA28D6BEB15BBFC1C85C52C711A5F2309D743454046205A4CC64EDB3AE1B7F6FFFB198A99D718C9C7426785EAB624C5B115C2977490FEDA904CF493D995E9980380700F582364443D6F6E15CC3D7A021F9303F4BDEDD2BC4BABE8D00629095C163BA5C25D72E20F69C578D6FFF07F857E194CCA2A0FB41A9BCC4D7E4DA0A77F1CEE7F23DFD782AF11C5F1198554467A1BE5916A9376C56C5F34D4C986F1AD6FF84033843CF737FBE4CE4614CB02FD9D4E619C9002F0B8E5D6774F6D7F76D0E961CEBE9B089AA3A1974FB1EA5132B64AA1976F71E85BEA5F6558E1D68E4EDCE34D2B1B365AF7851358FFF0353D99FC865FFD5D8DCB0F324688B8BAE27264F1DDFCBA8EA74B072F7866D05A48F7939DA561F19867A7FB940FE6911696389153DCDBD6AD81148B1AEA6D12BAAAAB1030A69DE43D76A79B54182E9DBF6A7A12E3651E7122A51BE5025863A288A53E36C04463A09200F5669C2F997B81FECCD70FE374E5E712C267F8B5F7C47E0F6E34156DFBEC820E59F2D9D38572F75F1CAFD63FFEBFF6797FCC6A817FFF47D3B0B77B4245C1F72ABD2E3F5DA691D0CDC441C3B2AF2BD6776E2C51F586D50B122C6F1B397F3B410731465E86CCDC974C147C63461AC9762BD1D2F43443C51B7A233EE1BE9A5AD8F36A71425A25517CA75AE31DB66EB77733220189D56CE2AA190FC416B1AA3F48DE21FA4B2B7C5A54E42F939C459B1725697C19D13AE4DB000AE4125EC4B668D51B00DAA0D4515FBDF8F81405A18E54F5194E1F5132E354D66C153DB35D31500467B64A06FEA4E81787E5606506160FB28828376AC8B9C4E48BBDADF4FFC4A6C5BD4E86576BE75E977457E195F4B8942B884EEE7D7B3FB15F14B98DFFE1A56684B60F26EAF12EBBE29AF3131ECA4C677D5BBB89E7BC4998AAB7944427F018AC47B222DF501FE2A5700C752A56A8BA209D72ADE5AACA288B3FC8B599F1F3AA1778FB69662DFD4B114B33A646A0C93B9A7B31A5CFABF7CA767C538BA28BD6A9C241DB8EC7D4853F5E5802387E9D3737E0190743C41EE2D2D92E10B4684D71EF5736226BB6EC6F8B120AD4DB6F68B030E59E271C32E8CFCE5133C97AE4111293A4FD732B00C36FF6BF9D6947E4C472B4EE389F7A3B9B3189094D423E6935ABCC7C5267AE05B609DAD3BD09A91650BC43B438A9D72A7A5C82C97FAC820C8AA894EFE431A45760C8014482203669FF106D9F4EBF779D57C216F05E0F436B0E5B40EB226DCD4DCA0406FADA0B7712496DAB47C09254255FAF534D23EAE345C3C8A278B58197CFB9C62BA3460249962ACC63838BDDA6429B058476F11AE6A584E1F9BEA98856581D2742B40C8BA8CCE0244D89D41A10ABF18424FB7EC4F95F093102191DF02EDE531D97C6373C65AB2BB181997CDA6A73B2867533D885C12FDA46ED9079B43B5E1ADCFB9CCD6C8E1E964B19E156493EC3E85918B7DAE0ADF99219F58F183EA51BA34718731DD1F251393FEEF68BA24AB1486802BCC3D0EF74A92484DCE1461D7742013E34D90648364ACBAFC82898D9FEC1C92A4295063B19D875E3FAF63B65A03D106318E3194333E2A452734626E1EA766C5A129A23896363855BCA8E48EA24644BA3830F56FFCD74E2D5FA76AD70E67EF2FA2E1B87586F6B71924E4553B5EB99C10EF5BF11FA89AA3F6E2810F97718EADAD887213596A758E91A1CBB343B2DA514102C9B702043F57851BE80CA0F7280629E970D695D8E63D32E3C4E6E98A585708A3C7E6F045D35D6A5FEDA39F481D4F8F21B11799F81238E4092551A732A4B3E118DD22FA2DF73A9D85FCAF2C64AC9BEF431AE0CAE4407C456B5F73A192D620D20FDD74D310C9B8F6A4A273D6DC859AC8CFB4A1A1A1DFFC1ED1F922B4FC26B043B6B8ACF6B569EFE61797F55655BCC230C665D86C58AFED2DEB8BDC9D1233870EF7C67D2F2A08353FA2E7D7E08CB0D282D5D5770206439FDCD5BA11C4419A424EB4B39EAC88F83CCE4596A7C38C13DDBF4E5E252C58BC4B396F7DFB89B9641A5744EB97EE6BFB2FEA9299CDC68877A5005EA0E58C5E342A38F82469C50DE202FB8E1C533C52CA3D48A37E7813489273B731D587EE79AEE541EC2FBB37ACFF8B2787F923C0593AEE57ADBD0D4154CFE8E941DE39721D785D695BA8C572535B16352AD67A1FCA4B1B2259CD3B002ADA946D21CACC35890BDEAD31D7713027B422C58221B37A63AB6808A8BDA8A37012D2C70EA5DFBAACB062C07A66AE005636B78DAC3DE424C671E257F80346884B371FA6C37D5B53759C1CDA99DC082736419318AF4019FE0FC8035B969FFC2C0B1D09CAE3264475D5B1F969D7CC70FEE1D47458162E3529C1E890E4CA4BF437C33C742E148236B4DE2318A6DB3261701206CA006E03607ED49BF9E5DD239CB253029A228AFE22112059D1EB9B1BF712400DAF8993225EC760718FDB6A5AC79CDD681808B7A0BC776BAAB4B560E17F4B4AE1BBB682779F3DE8EE1225DCCA978196EBE512AB1F3EB6C854ED5B96E49DBACDECCAAD5553D2D82652A3A529552ACE218E6A47FB4CD341487B7075C8CD52D324BD70C571C4F70FE01C1A5BA07450197A59301E97FAE2F77DEEBBBAC50968A970DF2FB07CF9CCA1BE7192E736E3D4A24BB2957364398C7C3079F1AAAD6EA03222F14F609D75209309926C5A1AB7CD58538A304537D2C6BDCD59C58B871E1C1A7AEC9ED47961998F954B0AF1F369BA94077F06321A016B93CBB5E4BE9B93CD6D075E2736821FBB216E518858AEF1A43F59112C642C684CDD6A871866B1D2BAA9B4861CF7F88BCA11E372209F82A55510C676D7C6B443289E724F48ADF509766CBED48B42DBA6EED067EC7D45E689BA925417ACA58D44D1FB2009075E91864683DD62CA1ECE1B438234B33E792E2B8528472EA97229D530300369EBB0BA28F160D6B92176FD078F4B78A3C04D65A037567AC94E5AD411F3FBC860854DB291BC5CFB03599A8ED366D7CECE9CFBB742D94BA41B71323B335E34FFCA22DC45F1553301DFF987032000D63AF0D0AE54DE4BCB195FAABFE48F9A24E628BDCE6ACF5F09A862513F41128D549472BBA0DC228157BF334B434C7D039BA8EC913D79AB27D9AA29DD04E4861B0A0455086BCAB88765C47C92CAF294B57A7E3E9BDC07C634D3EE63FAC08823DF5651FBEC1F8E08A44FE4FAF59CD4E6887275E59B96CF4BACF5806E82C1EABA92E68B006A669B32FCF01BFCFD450A1E4F8FA94BE25D5DBF8F97C2EB9757C0F751445FA78BA84B38DF9792AA7F47102558337D0665C20B09B6BCFFFBCA401AB9A4FB86E8F72962979DD321C7B7D5013D09A868CD7E178D21AF949CAD2AC08ECE4D1C7E22E8429F0E61E0B83305D0897676D6741A15A7C78FFA16DDD4CFEE70A4022D52C0C84736E2DE3B08B4FDC9AB9C856BB85917166EA467AF4682C5B5F6BCF96C4CA7C00F36B8BE2383130C65F24E2CA8A69978D9B631155A266CC3B72DCA8FF8053737CED90141EDE697820EA80BF0CE5F03C04B02E2388174A53BBC1EE65E4071A46476CA7E0F62B35377A898EA7F60102A8C3CADA179BC0C6CCD7DE000000000000000000000000000000000000060810181E2599B5B6FECDB52897A1958C5C3D1FC2F20B7D045F551856EA3CB441BAD9089C64CB9489DB6B63E0655AFC4C2FA73C7417FF1B80B9C7A1D659687D2C415B3A909CA30E96849D4BCEC6A9A6A4311204936BA972086B2394D86E840770D01550CAA6AD85ADC0EC851D2B3808E4A0E9830B99A70F6204ED4DBCB6759F6228126039607AD7ED8EAFEEA28D1C3E25A46BC18AF7E01F55FAD8244F15DE36F890416AA09548554338972C5F88FD9357792819E51A63D0B872B0A4D21EA3597405B52793D50C6CD70B52841D53484BCD3EAD004CEF0A6BC16CE74CB8AD0848000D8C5158DC16625112D1D85D17A3C1C8BBDAEA42C3A43E9930724655592116C4C6D0B8B223337EE4E754541A09D898F7FED71C3785B7F8721653986C525BC00F15590616437D11F9722824DFDE7E9615F1FB8488E5327E4D8BAF5F79D1FF5E808D154951AD87638910607B03FAAC3A61FE9916BA65FFD16986DEB4169BD24A72B1C8168FE569F3C81F93F3EBDD21D4E806F79FB28550912E9AFFFB52E97860C4DC0D042C56E1BB71C28B68E416874EC7043306A29BD1F4B9A3E612A6778315E2C2B850D6EAB9FF1905030FADA250CAF308735393C191134F3C493D00B5695775D82ADB9F2ABDAD17FC41FBD7A1DEFE337C2F8ADF69154CC0862FBD43035295B1A9C80B88FA8CF75B36CA08868F881966B41FB3E239EB1DB9CB51606A0A9EBCD552B2F4E819E2C30ABDECCDDE88D2D2F82F3585B5143943C929591D20CEF559CD2BAF2DC7FE03C9E4E084E8890FCE64A4AA9F13D5EB945AD7E3CC53E01FCDC192B97ADC1F98D9E773A0177E8D97405808EBF48BF17B689BFC15F4C515E38A855A9266230C9085ADC9A6DDAED93D80C3F38BC516695D202B4E89DA5B4EBC43788C848F8C4A72F79F37F857EDC105F13E4ECECFD09302711BC1993F5308B8F32AB96FB8EC3F5EA0531DAFD0AB3451F81F47E62C593C8D3E3BEEE79DB06909576BF876145856F5F716CAA436C98EAB28C5B85BC2E4D7E1653ECBB8BB6B5BD6981DC72D7F63BA06CAC8197ECCDC72C1481DB44724A3C21F7FC60661F11FDDE8122DA5D0B1D72A29952618B373423A892875E6AD24D0916109ED8E9A9A8D9A68ACEC4BB5EEB0D00EAEA72D8D5A76C2A42F18CBDB3D336B71C70AC73D39D7EB04533453779A1F210BB4FC056B4728AFDFCF46675C6AC76F750626D642E3AB117E5D6740154759A46C27D51306587650E1039054B876849882E7DFD807BD03E69021E337DD69D9B097722C6D2AEB517D773D2F7D84D69DABE1A1D6422EA1766C0FE7B8DD4D7283F2985D96D91A132B8BA03AD85F7D56095773222D0AFDC5A192D29F3BB0C2539A1C99DB4E711B6ACE3FEBD58E45E99C9F5A04CECBB309D50397F28C48BB9CC9F9CF75A52253B634EC47216A1FD6358AF26501821864569879BE1736B0AD242AB5B8ED16A7EA0989ED4CAE3567AFE1F8209A028DB46DB0270B3BC06668A9BF5E1BC1061BABBA00EC4EC37280379139D19BC6072CC6B7D260A816CB82F9BC90897BE3025475AF12191690F9F400A914789A860155EFD2D606A15895378C827F2A4FF700303962FD96DB2DCD2D213EEBB2460F0B753BC6902DA81D44C983DD027F1171D40A2039997241E09AE5B6165B4D55A8E4C79671A8B8BDEFEF2C21F81C541A5719DEB939F866B61BE250AF371CEA7B7525094C904698D412737F7781BD779365F122EE627D9CD4A68DA9D5BE1B0431998AACF824CDD864C7365C01CD5A5F480B6AC1E5FEAD8FFE40D87C1F9FCE81867157242285C5E76CF9667919C29A67CA0C0A61D7819D9EE6B792250A358F5691CCD80578F15288F3D5D6D7DD6DFA351FCF8DF0223F7D1DA1B76711FBE0E7FABD30377660ACE7B23ACF03ABC1D973248CDD0897773FB74E20481EBD3E52657C9296B980905AD29271EC128513284F1B78F38634BF84CB80791A0C5649177791CDAB87769D57B626F78A03435C758A207F52BD2A1F31E34B6A122B8701CD9FE478C57CF3535B6D51EB46CAF794BD69363D5A56ADDE6945E9788F1E1DFD045BFBD0A68834B13D6B9EC4EA9C860EEA0E9AC19C2DE14FFBD6B57E5992B08943EA0283813F3F15E4F928B8D0F13DE6863990F5C77F130C97D8BE12571EDCEC7DEEC4B6EF4835F136DA45DA70A11F9192478FD8B4846C507410FD11668365B05252E68CB2C972ACF50156E369B83BB85E62E4BD4D84C2E9FF41A5844D5D88AAAE7DED852DAA0AE5C14A5DCE64C7E236E9B7B60F5B5AD4D953A2D842A52929491BE3555AB8DF534CAD56DBBB86B28A8A86B7BD9AD1C58C87B8A089324E00FDE32F8186B2B74523A22904C18ADE02C3E965F94624F8DF57E750EA6335E3EBA705294B76CD6ADA33D90FEC1F48DE7BA9DC7D8D60A53D2563964188874810C45736C57EFBC3A3CEEE7238AEE5281882A554F2143BDF89ED4BD819C08239C187C12A8B6E763434B92C26FDD658B350F51775C60CBAB7A2CB120DB8CE8AE9AAF6AF559F8CADE84C4820209CBD27CC09230B22F013A0E4CF8041E4A789A5D20BE9914A624AB957318848ADDB39C9748C8922C54327048A2E46523BFB22487538363459035BA49858F85A469957DF1F4831BB7FFA0564C53233B99B596F5356089949306DEDD6B904433D25C4854A80590B964DF6B0703B4F9628D6B9A4D3F0A4096E9A0B46D6B32F66D563BAF688ADD18DE001DA62E33C503A4387CE0920BA5D1E8B69C38E3745B19F8D8B6CA5E1AC6DE90EDB25FC32DF04F0849D769FBED3F8169EA1D2252619A2304E055370B4443CD23E56D4934F9F3FC92F1C1EEC626657E6A89C1394E56061AF8ECE3E2A17FBAAA4D579A99A7998632A6AE2683DDFFFFD27A27C8815511855F09ADFF7BC627A7A5C95FE57FA3EF81F494FA7EA6E6CA2D14775A25BEAF1B5A3E35ECD4A306545D597E4E44301C3D1648F0A7D841F2F76FE59C6EAFA3F5B58907FC4E642ECD28D16A71EE3D295F1DE12DE1485B9CEBEB2CC6C9AC051D3D42B6A1A068533A7680A98D015B09C5B819FFC61688D441C1B7FD71180C4423E64EE940917C7DFAA19F3F51CB5B38D1B2B7C81D10E7C + +count = 66 +seed = 83C653708FAF3E5F6FBC9DFBE6FB5E83E572A7688645D75D2C4835B28695DEA4BD7093740D0FF43237354EAD1C978BC2 +mlen = 2211 +msg = E3B57B208352A820F622A694B7C3F6F297239EF0A069615DC664C02F1822BBA48E11E37BD9749C98FACEFFFB0FE1792A386BE10CA7B98CC874C68C36F5096D3718DC93E0734D6D6F913E3B958DC1FD1424818C9437B0FD59728ED46A79FB52C737A1D1D26F04EBAC279A7FF6A971E2B69576B712D9224EA18FB9BF4E613A8935F3B36A073B01F37BDC0B77981C8F2804E93C395419352B85C8A32DD77D41DA9BF3ECB914173E80DD1FC06E8FF5BF0E4F7424849A15EB7FAF7DE77456EBB64D10DC10FEC6254070C7DF387397137372EA3A53DFDA7DA13414AF2DF16C1E38C5C70A5F5F44F725D622049256BB15DC04A8D846A1A0DAE7E765A7F00C498F1D0B2893B8405BE4A43FB7E97881069A49134A2A847184B82EB5A690D87BAF2F579619EE19A3D7A7C7EEA72D6E3FCCF0A8092BB8D3C6B551F27E63E762A30B4A4DF2DBC4D119139AE1B135D06FF827846901577700935E0011B65461C2EF9A7B71EEA33C8CA4519C7BCFB557C5E1D42D9243F2DC34057F5E0CCB9A457FC34DCB10D9B47F6EC3B9550D3AE4FD593DFA3E28C6CCA1FF1EBC9D98DA8DB869F8C80BDBF8AD4684ACB6A779CA9D0A106F26DA17043773862681C5DD2DEB1BCA2CA48D4FBB4BB7C1F765DCA3A1D991D890B9A8751CEAFF543997FAE5B128AB2EF22B3BE94499DFD9D8E78FB4C82CA8D296B0415E84CA8B5F2024455B5DECC8B4CCDC7BC4EE06B4F0C66E6748FBD07E3A3BC5B4B6889C40DC4A97AE3EB43C3914DEF976EFE3BFD84A093BD69102D7B37C89B458A55B98A1974A13A7685D26E9D816C79585BCFC1042C2AF88534A9FE8B0A6C8C44355A6D606F902DB40D5490264BF0F352C27355633CB095268D5B8BEC985A62D84B2323FE814053F05DEDC22029D2998BD0BCB255C162C4BC03F60E3580AC3AE86C37850110E9A1BCBD75F64A0DD60B941E2F57DA9D72498B3EA8324EEA53DA3895585ED2942B9140F260895DC6A1131A4C3AD2B64028BB8C0FD67E1BE4C07F808B47DAEF306FD9578025F9C639660075837B2C95473F7F860D6EA2C53F4BA677A2345CF212C7757BB94F1A4F76D4E96625F6FE051B8246D1B7611BF6FE325FFFF8514D2F9A3453F0E77AE8B958AB5B567E541F156C6F4D315B4C3C547D59BBD0D7403E2E6A49B9E7D3FDBA338ADA41875CEB03830A846A1FB266C0F1228AAD2B76A2E3404278DBE482907206FA66487AD2C999867F870C8CB7A70B83437E14B9E893BF6B391DAD75E84588E882246D161799ADEA63ADF1AD706C0A3B76BAE595D84B21AE9DA30BBC0856987F2C2C543D977747B8CBD5A613B92804ECC5284ED23650E9DAFB4B76D63F069710897334F18EA6B0CBF99CD590A78E3B050E1BB24C86D6323A17106F0CAE3F30B01E4EB3DB1B5F3A4771A880C8AC06BCD5A82D4103D0452FD7B54834C1CF8595DD77F82D4AD9EBC1CFD0C9A8CC787E10AA4D1688474208B69FF7AD4DA6986E5F62A34AC3093E0FB1EFE8AE3A96F6AAE09B0E8F6E7A2B65C7387999CECCA43CC33F026DC19BBFD867C48127CFF579D1D71AFF0C4A0E20F9FDFD599A6169DF1B85F6051E02290DF6F5EDE4F29BB6F0C8F806D6850C6534ECDDCCD75BB8E4A097C70445585740F822E5CEBB0E19EAC82BB78EBDE2CA60A810AC6C54119FD6427DA8A0155EF48653515A919B299A306FD3C62B505A6911DB2B56CA2F296E487BA02C546ECA2783ADE8E46A8C78EB1F3D7C04BB24548F92383E475CE6E572D8DE1BFA9B3E35D9BD6C79547B592C95693750010A3D22CBB31AA5A4ABE94897831B1ED9287631F006A735C36BC84A8C87497EEA4873801A733F35B328C7D2CCBE4A41C193D22F972571BA7630B33080793498CC85E6EEA1C412914459DA175A6DB8658D0BD7A823FAB286EDC20C785C40BFD539924A24AF4E3D37BD781353677C76D4672098F5BDD17017012571D9AFDA05A40AB56998E40F5E359C43DFE32CA10A45BF08F67D128C24B1ACC03CBAC46BA6CA5A532C105E91E0C77ED59FB534AEECD68735A4978177BB5A656B9F83B202BB604D61A24574C16656E512C0A4CC6F597B3268573E10539D1BA775ED83BB680BB9115011C6AD43FBB66FB37C467249060A1586DF27B2CEFA65265CCB9051E468000CCAE24F08BA941A8180A64BB624F146C8EC562363B32C369F62997C4B1375DD7DE64725A598529244273CAF8398913C6FC01522683CF1F9F965C491ABE7A554F0019514ED98D75EB8BB8565F77C195F629F98163494B4AA2674F92A41DCB67EDD1D818A5B98993D0B1198BB6BEDABBB486BC6FDE039433E842BAC568A5B4EACC028CC2544B57D8883848DDDEE2E967EA85A6102BD0ABDDA41C3D78447BEE1D4949449ABAA9B3377E8CEDCF04A500FD1A6916E26983E64B5E96FEF87B32A060444D374409262453CB1376C349A8B5D1767B1E2991A1A6044E0F58831BD11F12159675D215D7EAA74807C995FE22017E30482DB8A4B09CA7800822C75C92FF649FC0728F5A1D44EFE7D0FF147274152D5F2F60342C8F5F951D8C95F83C1D54613A182D9DCA68F54FD55047F1F90CFECC04D733DFA82CFF2618F29A4DB4F7E1E59DEAD58CA65D07CC90C25F804A895D6A82F9375451CC55506D276FBF783F7D4D53B9BFB83DBE4A8771AFE21AC543983D68034BADC980F9434527F9EDAA2E228646FDF75B44899E749CF4C9E5B345222385A4424382603AD6EFC24C56E769028F4394F2F6220A9B390D395E412498E57A08BAD927B8BD5D76E18E8FEB457FCBD3248D218236B07783E57FBFA03C292A9F5719E6AEF2EEA3FAB2CAEED5442E89BFFB236CB13DB2CF9C35A38C338C377C475DAF45F8EA822F9AAAC13425FBD43D3DD9229367F0B3687D7E82AC5EC2FC7CDB69C99A4EB1B8E45465C6A53F16AC0C4E0C970B8C732AF515C09EAF25596F64A04AE4621037B8841FD2B1BBCB310EA23E122B0B9AB96D8F7702952D0E96E4CF79C2A30DF0091ACDA91479EE2979B0054997C48F6A0E909BC52A943459AF25553969EB31CE7685369A7FB014561B4697B8BCE220983136E5EB2303CCA4EADD4C6CC74EA2FE69D448AE6ED953A80363DDED5591B27A1EA956DF081CE99AA59DFC789D9D8FAE952B0737099D467D +pk = 6CEB15467F0C206BC58B642C4BBACDE4406959B6B8A3759A2FFC8CD486EE0FF6CC6D7FAA1A033CE830F161F33948D78F5A1F85297F13168A9C7D43669680A55BE2857CD905088484522B0F90DBFA56D2108C4367B93CDE81D7A3001091AEAE66CA125708DE518CCAA8BDEA36177D2BCBAD97656D5471193202352595B65BA385763A328D70D5F4A019446588D567E0C2574C072A465AFB3CD03EFBBD9A0049DA739AB6A0B4DE5765CD0020CC7E041C21E620A1995C866BC425AC1976EDA491E1A8252BB4A7C46ED91BC8A0101C451DB1B9AD25D89C52748F97DF8821218D31FB61CA6177751B819435FAB7B26CB8870D4359E336507079F598F5EC938540DA23315C4D2729F7765DBD5F613DD716E23F9F48122AEDBE3B3AC5D76FC077E4718ACCBAFC1FE39801D90D9140B7330FAC0A3DAF9D7D95734E596BDA2EB54FE45AEBA73001DC58B6D837154F79E9EBE674025B9FD7F3412A6793EE91D972B0717714CAB0236CA970DB50F3AC0E7524E1BA46141BBE95233FF798D9562DF008C2E2E80C1FB2C2FFF1D42A8BFA8AF9A397CB650BF17C252250138572BE2120A8632537B0B5F6188C1954358954A93AFA5EDC92D5F399B86B983759E3121443060F42B9462C47C65AF46E28D9C94612D35618F0D6650CB72B1E3132BCD52B1453CBB67573B4450F6D32CEBF7C8D9BB7E001BDEC68FCFD09BDDA6D66E9D7151FCFB27E38CBA5D2F95EA8796456C191653CABFAE65C1DB7FA09BF2CC01CF54F076FA623614CF7C87EDAD8CF4EA568C45C820699400FC8892430DB479B2CF3B6A48A55DC75D979DBF71E32A62786D577EFC04FEDF3195E7B70F8AFF1C76A5523A43B945B414F23F4001E697F6CB5BFB67C2135B19D5B3DC9051DE206C6709F3FA37DC03200F8AD383B53843DB5859200EE289B2ED259C5EA31FE431E5F8EEF365B76D2F839AED9F1685D4898485D988510D7B0CE6DEBC911FF5B1E8F5D15954A1B6086E7B6232984189A73380AA79F862BFDBA22C200258BEE22C2F2A89EAE67A2551771BDE7D833C1F0890D4B9380564A74808AB3F93DECABD10CADE4639C7DFDF2696607E95371728FEA3CBF02431386886847113CE8C2D4C60B718EEFD43A6C99B1B6024473C6313CAEE07B4DCB31390851BFA2A4793310B892A3E288BF45BC3D427AF34F130B5E5DF174938FA28D0CD344B2669DD270526EC75002C9D2F3D29EDF0F7C45E79602A68545104AD7C77158CCAE78709C20A695111DB9DCCA7A75A4852DCD01578D342500E80DA314ACD0E60FEAC757706BFA12CFB87C7B455AA989029CD05DDDA99D9C3659064F7BB5D85CE29DBADBA52BD80D7CCD4AFD2E63C1BEC78A93040FBDC61C18D01B1EA2DEBD13AF49E6E9CF3151C3AA565CF3F01AB7E8E56B68E4C1F1837EA7EE3FCFD68C37509A4F2532E9D189489677D29EFA6FE31CF84604ADB95BF4DCD55F8A41044DC17F852414FD1C295BCA9A566CE2E04084313F3BAB2CCA2232056B47E38ED42744B3968F0124BCF9C2713323538DD0AF8B3FC020C29D5C3934563B176E8234974580B69F244C7103F47F743266F359F4B7C807AEE5A0D7A4287F09A379CF3776241FC775C7B67FE9A5ABB771374CD8CDCEE139FD6F343444EB6789A75FD5D0CC69451B42DC6AF84777B8E230F3DA1E352D766E4B1908F9721AF36829125584FBA73B04F45C4B24F8D1E906D1C1CD6AD6177AE86F4D2C2C3CBAAB2AD7D7E2B242132BE5EC851FA1B9A6649C95A0DB78B3585708BAEDF3066DC1CA7B5B964F5E7867AA226CA6CE4F27F167766F0ADF3A7D9096F68E464563EF9D01A77023422CF02E291D36DDA73ABB2A099B163FAD98CF57B5498A50E024927BCB76DA7FF5CFC9C1DEDDA9364D8C2A2CE0BA75BA6C7E1DD4016871A9AA1E0812DBE7E8CB9C226A1A8D6B761183DA8F1A747B7070EED2BF3450CE0987B88178DB75EAAF8516B5B3BE3C102F69A7DD675B97444125333470D84702EDA183B31E1FAB8D9F6855AB297C8FB9993DDE2687180A45EF6E847883201E18B39F5E9472A6C22B9479292E8453505C10C45B053AD3FBF228EC77ECF43689E67FB39C0C876D97785DDB96B63D4E2305377C1E4BCFA5FBF1B2B78059175A4D204E129F17A5A68887F2910583ECEEB445EF0DE86B4362426E89A853B7C1B54EC84B78BFEB22A26412ED1BF321E7B90DA0CD34697C2C5381695E73BB9FB7AEDAE100A1109B634EC73217EAE74F0FD93E645761516511C1F20B26D56A5960DBAFF1430197F7D9621FF5995BD8BB069968AFA69D4FC66DC8C6691D131C24F4879DE70955BBB907AC82123EB5E1CD57AF8B8B226590B30723F8B455BCD2E00E339B018222D59CF2A041A365B335A07D971D402893AC9C3F9B40427C6F73DB93C5C053D0131236A915001024C13626091BFAFD5C58215AF13945C726E524875F952437B89F891A888496917697C31217D56EB80F4A72AD5B40166368D9ACC924C758F1B6C03E75353ABD5AA1679DAE737326207CD9980B59F5A0864E23AFE2C7EA53613668517911E7BF5BD8A4F94B946EF2B5ECA09FCB2191431B1AE961DF016FB3F0FFCC734DE17E9776AADFA1D9E3F312BB9EA64A6D922D02D16DFA5974BB14414B20B66CA6397A4513432869E32934A6136906CB3D66F05C15427643BB7A914039BA8B39FD7A798DB5246C16F36423D4F221CE5846D8ECD6D92E3C16E75FF5EEC3F7D5BFFEECE1662C5B0B554BC85D0CB98C167F8CF5E9128882A77D1EA3701E4E7512 +sk = 6CEB15467F0C206BC58B642C4BBACDE4406959B6B8A3759A2FFC8CD486EE0FF6639CD99A057CEB8BDCFCDB34989C60560CBDA42B21A3002200186728701D95965BA5E9B864C5CD1442CDF22F95885AC40C9070FA2A449203006E6BE5A2C347445EA99BC5C3E2808BBAE892C0D293C07CF65C5947E7A443357B051A26E2C87F1144271001676687704650038161574844713134268853477133677757240445175214624871438251282282318057675851280377386424751026417150052248357066164078612308758663244117663300816646158264727077351481464238305662553606372324150584456837761400073274730264454253180140675802771215001181357085115276454280343647571214078637531246641804622178277570532005650267018324370845546640685021476036107020246832727503104815337678032127837018882180374651456323653033624072557207310537013616526724751201427870841812738003841807756124483745444472144817252217067172636315532280116131017514047663564437347058348260576136230284215323234651515212712545667577516484365567786143641458016787115155221513573047670615407135713058870650080175864680725565651837387364236682404565477540485252112221871584471665358478485678323378533203537772422646371283543430555783275858738278410468515103780504405107367052657420153488755336256534026273160036056233155356345158562061685252228378186022320883065820568468881634645342127715026886102437505355434418632550855068726265327642520065661242147057252568701127203708365611476732751222223156471824815784533252051471283273085634627135824000620548086534854533572274384730150313535240066836271106074563334738105652510473271782135764564717011510162508306613521753632631214081226671458153704471266042608336765072661488538521270338161222805042764187053562433741818151080068674673438238240323163868211004605674676362285185310105316148161811485683282621817772607266285303504184216250101467068401165667604212151757830112068318823751454151111186003182151427034600728076656324447576400454036258774740100437102077375607631556818205726630846827746860501015568456786443252624243521636585741852354110361378444386073842178583740431388216188730568053435541034001327850544030383676857732834275684458070477545246311602066188472374313308838210113662341585384167484787208252135303155582511835021631170561271755678026223454401403364372114546561625838762208127255562381230574646552584625825812224607761620623471248342832730157566718040357787266268051441587458367715585885744887871227285205737683843578010146852403226476864682872048074153303162003422443186280607501122784526254101350085351703361673411603146681251478148307287721834120045031663265522878070714056016822714314060463875141250005020641517445800543463005835166176807863661657274016247657114076712085863636073180865255146003642645138128117761780277812761362807581436085572307808676718027385618470633727228148475867875871851027468481335458075421780012832430088841661526088071005477617647113863223607502678423442863341456737401884378883456452361627434057642046767612667422667143074700282043045648772053673774283844813367522801532187160788724612620438673477302156818252434823123665415206141138281135220201382812273281758208024133445314337002104105115453657206152120023865538247135236817FDB43D72CDE476708947C8A96CA4909648D876B386E258740C801B7399FA70010338D9D4701139AAED05AA8558BCF0746A880FB1398243323CE9EDA31CF1C7C6F898AF89F80A919CA39702F856809FBE440F0D0A7F9E3A9F4E4DFCF709B2B564F3E80087DB6067E07F2E925E657B69BD8A26BD0C2B8C76D2445F25C129242CE17C9FBA2D1E30E9AEB6A26ADD05D19CCBFE2928099E3CF418E647B180A76076B162A6A29DFE0FE324A740741ED4366117030B26CDBF0874E4D1C0F1F2FEC8899C19B41AE27707D6A7F79C1F195F473FEC887BAC5C47C6F2D1FCA71F43C6880AC7D8619E5C39B9C8646964AD9A5D0D20E9C560AFB2F19B7AD7469CF2D90653B59DC3C2CF5A2C08E19355FB0948C31F94BA51211315E43A0F1C10E8A9E20162F7A2C915952C2333EBCE3C4BA5E2608D1DC5E71EA89DFFCBF1A5AC281683298FD7DE6A1120F58D07440A23C6D8B24F78DC4580FEA7B1C11F514C8D6F61BC5CB79DF593CECDF0F4F320365D87CC852274D6DAE0E09707CC96A55DE7584ECBBA7F8C63D34E6529CE556BAD6418993E4DB074A38CD68765EAA7AE2570FF9789C0E75E7B629427A55AD65BCB0698E884F2BD6E3932A1BC6FF3B1366F5ADA461BD79A27AD2331B0DF53C516180CF4FD17068E869389BE53E7E9408D1AB4DDF0987886260931F89DDFC073D18F4B08F1F4CB6D64A9AF50B57CC786156A6FB8EF7432DF6A27A2347B0C4B0EBB9BB867F3FBCC5359BC3546BAD57523CF11EEE4B9B789A3D53455763415B46E7DDAF94E2802CEAD7F6BD63D5C30C92BF24A86CD83C4D0D1F99E3F18087D238DF8BC282FC1E2C501E01266E03E6B215D20B4418862E12AC575448BD90CDF1C2ECC249268492FB8F8BFF09BB2C1BF8584363C052F3E0903ABAC809A8B89789F3B2132C09B411696EDA4802C1E3D2F6CEDC10474913BE21FE5825A6F0E9D4EFEAD0444A52C09C49D4FA8B3C1270E50E1814601600038DAB9B8F5EE422F2D6D683A6F9B093E403FF8BB4BBEEF4BB1D7DD5A8AF596E4DBADBD7626F56753A48D4D0ABF7228996DCF093FE283721F97495DE12128E9ED59753650BFCDD7C6A85E8E4E4503E8522A1DC6B5A6C1C34BC9CF26B2E5218D4FC51FECA4639F2273251F3485382783D5D37D8111D75C83EE569D504DB75A7B0E87C451922264E0F1EF50D6842276F88A44D5BD7FA3C3F5D1A5B04EB6F9E5FC4B8D9168D904655EF98BBAE4DE8D11BFC9D97FEA05220C512EE94B6B266FAC7C39DD9DC01968315F507C254E6732DAA822B05F9982E45F1EB798A39AC9438281DF5BB2DB18F478160274164B84C1CEE7252FC6AA490A9E51337CCA5E64113E7046B7D7A2B978614E4AB568F1961E3FDBEA5F9FDA4DAE17B643890A401B30060691DE07FC31461FB29450BB7FEA0B4D16A8459C6716F54D98D425F9D81C6CE06884A47DE55044B920A3809FFA94D80AD677AED48818573B0CE83F099A02EA140CD7CA45BC76213A9C47047B2256F15AD15FFFC52270BD16FE227FA41E58EF353DD7E094E263645454C47951B28EB8FABC369E7C2FCB1195701184BADFAA0F6835EA5B8ACA07529FAEE58B632A65DD27B6514EB20C6DF6142ECE60F4031F85634FE820DE33AB3537A62BCB996475E7E77761EDECF14FDF8B57AF68190F8F5E8E03A2CAFFC59076DE867EA2B510CA500F12C76A8895932B74B0DF5807CF7951219E58F7D58808CF60DAC9714C5F3A6257FB4CA425503D5CB33AC54AE76345C7CE7316FC58D4C894A82D075E3C12C713A6EC7BCFF72D4CF64275B03DDDD5E52ACF9F59FC27ACD644FC0465A02A6B3BD0E63D34F615BE95476DB26E36E78D6446726D8267D4988133233A036EE8EBADF52544315AA2373106325374D5F454B17477F56CC7D45E9E8ED4B1D06917CB10176916B2442511D2A37393F21051CCE2E106C4A3D5122B348334B679434D92612778DB1C539FC9FBFC5027EB783AF39010371CC7B731E84A201AAECA123466DC6F8EDB4A9B820599692A359D0F65A0D5C466D2728486880B4F7632D9F0D91EC637B0A8AE165F6FB374B327BC5BF7DEA73DF652AFF362D3787FB2496CC46D80F8148BEEFEC38BD833688D74521A7C6313F40180ABE4D0CBA0E9097E31A46A9884150364CED19B60476CEA0D87E13219A04D6A49E513656FE55B3755B60D24464E528A0C782116ED919FB211F98BFB9774CAF0448A350CD0C52E0F8D8F40AD6DAD636F62B41530C1B7C589B58921CDC0798AE4AC0BD9053461C166799061DBDAA64CA84466E1186E6197878EBBB8F1E749314054522BD7CE1CA6A52B5F7F7E949CCA2728D61A53147557335307599D3A14F6870A681786F583F20F8BB22564DEFDFFD440C67379DBB9A645147D62466ED22ED14AC4ED83F9C3D09E88297F50423E14BF9129F957E207A4D0E27C0412F95E83734F43F277AFE13653C2F09B914B9AFD808308BBFAE19B4EE263779F3742F1A9AEDDA4B886795ECA31764C048CF1295CD8FCEC2BFF3966ECE1F1666677A5B3C4D880575069227E93A3C2CAC6813C0F83E098D0B281BE43016EE494BA01419D18BA58035562D5C6CFAC2AF40C4D484BD100A8E114777D8EA0AEE91DE3CBDC6B706944D945DEAB1F4ADED6B11C80E446FB512E7B802B796D950F7704401EBAE91207FC726E4D8F1E1583BA0027CB6B27A089C988E24F62ABE6A3647EE6DB02B2FE56F9600DD9A9AABC5CF3EE0878BE0B5B4F0E08BE72B3A363B2E5D679CAFD74667560E66D8440E2A772A61207A2FE47A724D04646DAFF51FDC8669D16A1577A212ED4E6F40E8DB1ED29C431FAFCA0A344AFD8D29F172E318A20AFEFF9EE9E5B96627CBBB98C9341395FA9FD1D60E31B9BF6AFB853280FD16B3AB7366948C9FC43AB53FB98C918741AB9649A0E7954BA64FE5B7F614E5821574D41496D4B8C7A74A50698A38D23E888E9E9B31A647559FDA779002B718E4AC2904914986447CF72658B282358B66D538D1579C92DA0A574365943F2D4952C9C9F710276B875AC5A2E31E95E2EFC7D5B44A1544D96DEEF46BB484E8822ADAD63FF901DA69E85D7CCB958E6C2438A0EF233CD849B47A5F2CE97200920FD0A454E342D37426F473F46CA97C86AB013D78762715A1754946E38941F87E964105AC6DC7637A4DB595ECBAAE9D1A54E072A3180724C28ABA25BAD1B71C5288251D096B61183F722B30C00C8904ED227B5BF021026EB6585F3F633881BC1ADD1DFD8AB24C7FDF0FF24E0297B53F0917D712527E993AB68D5CC3DAC833BA54E80225D39A684DC5E6382757F65834F996E423138D51CDCA326201FDCDA3204C0BB9921E1DE2BAE9BE7895325AB5DCC0FA6A035B92EBFF5BA91410506D84D6010516739C8BBA8602EC77F0FC13DA11210AD741B5AA19D1AF71D0BBE9992D73B745389D6188AE2B78FBE491E212CAE0A08ED34C89312AD1CC63DA959C7F01DB13DD1BDB840F81B908598134F600DA34AA519AEBCC83B155AC1D579472EA206155F8FBE2C8AA120611202E23ABAB7120FAF6703D5B795 +smlen = 5520 +sm = 5AC7B6673D6006A737F31211B76B7164B530DB582522F51E4EFDBF75E0ADC42271915FC01BFC8E9162428445754DACD89AFDB009D1F552F8F8D0D9770E0C5CAB55768629C023942C9A8BA67A83CF73E963C6B8A0DE123DD650190BA7A96A88AF2A0F3DE802730F46BE4B3E3A3F1224D21C3CEEE14C8BC07D4840284EE3688A8D0BA11DE5875A07F30AA0A9DA77DE37B051599E9F8CCB89BBECD25129BD897AF08AAFE0A9538B0E8B73D997A7ED4AA4A30798D1FC2E713B056D1D94257E04CE0C8030E2C54B116E9D683496DE6872ACAD4B27D8BB13F4E78F8B73C20A4735BAF17DF31E543E250C36A1DE12F197CF80E46E41A0D8B096495915A16A65C269C737F1E2B802F97271C2F732FE2827D76AD422F0B46B030F14002E7BA6171AF56570A6906E2FC309E2C29B7289DDB22088893E296DD0A0424C892E0F36AC81EC39D721A022A8E7BDF8B334FC367174605EC63F713C383B1A5653180C58FA9B0EEE4CFD08C6A7EF0C78BE9934F8E5E3656A2FCDC797AC3AE7147F1EB806BD6C465FF4091063BC557F9128E02720F0C4FD4E78624EF66BFB1B3B9A6D9A8492E8D259467473843A42B23B32232A0BFE3FC5AADE437F648765A826C1948E5C3FCD47F954CF311DF45D372E288540864DB02B9693215B7F6B7085962D6541FA69DC82CC86558C118C265BBAEA0F71B8158E71058A47141CFE3502F81988B6BAD0497A879A900CFD8F8F8A15E264C00633932FD74649F7258064F65D37F6D1DB9D3D89B195C4136A79A159ABD42420EB931FFAF76459B41D2D626B0BECB2BD6F3D204DABB358D104F30020C8EAA55809D89CC00900221AD77093B88296FA21C1BA9A8CE5282BF8891868AEE2A1923E7F515F5271D9560A7793873B271D8A3815684CC8607D13199C1E213B61A667B93D6D1117F5C225625CADEB6C82C82868273C5676EFD08CE3F1892F89DBE765306C396AA224F8AD3B0D8A8F28E8D18AB831665CB71B3E7733E3BF706D52CDCE50A83844D5F6ACB860D216A23011F5DB1B28D016DC6B060489627526C8649E22356A864519AEC8177F4C8097D341F09443E1C33492F96FAC2A9A277BD561B208E8C3F92771AFF16F9F138D86FD70C42F4A7FFFA3D5E835D0AD2E5C349D9829347CFE2C5B0B5A27201C726A6A24D3837B31D3EC9923831D2C2A31AD9E412D100CDFB88B49ADF0D49653A9EC2B6CA39AA5A0202657F70A77FD0D6190ACCB46E00733D8A963060485D2353C53865EA05D299212AAAA4DAB75834F185320CC17D62FD50DE079D3865B034C0736224B8F799253675FFE0393BA1AE492428CA257F57526E2938DF3C00B6F1BE156022FE5B8660C7539B5F60F413D170E69CE96F1AD2B1D0A67125C76939E58D6827D5359338F8327961142511BED2EF6C6CDE387E241EFD66946AC0B467EEBC4CD828F6596D5ADD95F552102E046F06DDDFD97D0906A1F13C9C11E5554A152197B35045B7D0EC4A3861A378FAA2D0A3D01000EC6F842446908C1EDCCEF6529413BDF780F2B6B7ACF6DC13CBCE914D394E387A82F50977F2D74DD01704B1E94BCB308C7D1180B7E73EB97A43D84C6086593C1557BEE4BD3D176ED86A5F894CF5971461EFA5E6520DFFA61A54142B9B584DBB2920925AF5A706E23F367CC79BAA1EBA6AD6DFDAB0E519D47BCA5F534485619E2968AD174DD220E3AA99969844DA8588035AE65D48D7DB429D429C3AF061A2F14622D0BB05A5C171A1AE4D1D012D447A10D6ACFB231959542112A772BCDE786FF3DCE9B64F47F1D04DD0420C9B283CA4B4DE618581F177569B3E51DDE358E0127E770F9E973E3534A9BE153E770D4C818CCFE8EDECDB41371F69BAA94653D0275EF160A90600E2C4111643FDA5F188280428352CE6F7FBDB0B1D8F7EB242D5D3A6475FF061527366CED5828087A5EC2A91CE52588FB7F9556A3D35201FD95C0D57DFD59EBE19156CF51A66B399B35A2CAFE42ADE9B266AAD116D2FE6734837E02E74ADE991967E2EA39AF9C1F835889DFA68B6D03FA16868045BF4137F0AAC7E1954881D8B0382967A77575999E4B3B9B3B6BD673B8A04E0C941C9B1045DE5934ED68E8E1186A748C9C328E3D2887F562F1A74492E39B93B72E441352778B0261563575BBAC7633D473B86355567EEF5A772B943326E98AB6DF808871DADA9719E14C70CB26512AE0F8ECEEAC253DDEBE7F2727716FA1AAE4CE4C3231A0561F3250898264ED9A976A5E0798E910269AA189EF60F043FB84A9FB296A8FCCC1E0B9DC842A008D00CB40FAD62B7315EB82087DA4C59F0247580703FE063E9A431F7EA45EC049CAAABFAADB5F6CA891A8487C82B6CD0E5A8371CDD16B566B6C00A0D15D3DE3DB76DBC7154E837978C2E194BF00E3236E5A4246B2B7CF3A1BA80F92523B2C19DD6B47B88AC7CB9C3B94024CE0D037FECA97AC4ABF2699376FC612307E0A859B13F7085DAEDB9AD68C06B366E9C870304EA60D0AE82BD49C5B6848C780B592B500A3BE6F258CD1266A04CFEFEFC31C61269B3A8B3CC9D51F7EA2140FCB6C95334C5F8378692146E1615E3679B4F9909353DABC5AAD0399E3A75431B1704B96953E49CF494756CA6A93E7B80FB31B355F84C8E34DC24294D00B6A5220FA25AF54143BC1EF50DCC66C14E160618B44798C658A3CA9D7AAEB5CB9C9B8C0D6504C6B32CB158377C63E6BFDE0AAFAB29A75A199994043A0BD47A72ED1BC2D123F52BA6031F6AEB711042074E3F211EE07D6C1B9FCCF95B6CDA4FB01BB1798910ADE3A07508CB1AB53C1704FBA44560273FC74207EB9DA87A77541E08E375CD2D1ACD75C5149D52D172273544339105F423C841AAC080A900C37F3D8A1FCBC84A6561E687AEF80098D329EDE38F5FEC0AD55E3F885025AA025215DCE71BA1694E52FE86C0195A33F6EDD552D6E41C75668D31BC312BF48611C2A8F96857DC703DCFDBA86B257120715D5DE5DC1A56283720ED00A16AA202587CDF92CC3467C794AB633EA672915342D202B260B2C3A56F6646794C98F53651CBC1E3489A5960EAE79A04B77F8EDDD49CC964F07A1580BA47A4EE45FB602A4B30A94D3DB8FB84CA8B1C3B74B3AC021A2E087497027382E37F0942E679F3E7CAA984292C036111DAFA639BA9620212D079A577787502AAE5B5980577CA06CE94708CCC588C0E08AB566793C3D8C8AEEF05D75748010E73E5437412B5089DDD3C2AC224B4DF05153EC7CDEC93AFA67D1BBE94A3D3F8454FCB97BE0275F2534A74C4C42405D140439E9C5A6A9BD5B45AD1A12E53DC86C4BC8FB21AD585E67F067289B75FF117C0085A4EB1AA108A0F65E85F7F1C6D7960241A20557E53AA543315DAB3C6CFD4197B240326C3540F40C88D16051A219E92D0D8864E7E73BD50689E986E3F9DD41FA43D69331D1D55C9D077470E49674E5A6E99259629D955C8ABB9E6A3BD9F0B13AAD4F97214A8637243DC13BE741834AFD0740984B94397383341C789D386878F94F1AE81C92E7C88CBEB4B4BD3916917FDF48E2B0AA0A3FADB68FB70B621B52D7C28E291EC18A0CFD03BBFFB0C6E0FBAD6993E75B272CFE20DFE98635FAB4E9C0F4F34A8ED2423586BD084A092A65810B6AB90DDF2A490B7ABB39F67B98F218AFC175EB02680EE5AB1495FFC9373BAAE066A7DB58C3E0B819996FBD1192A2A0F0627428645A6637DDAB6584F6806579DDD7426CE2BF4F6CF604E7ADC87FE2F2D518DA47CC31D885AB2A2A9E6D7734A0ACC663F8D781F9DAE2DB63ACE09AAFB8CE97131868B728BFF729B15A4A5E0A17BE337246EEADEDFF1B5F62A2D99AE53296853BBA224ECBB95AAC21DBC31912E2088BF6DB8F497162C278DC87C09165ADF8820E757A767F27CD065E352F5DE5D71476C6D8F9A7B6FEC8E40921663FF7DBC0673C14829F8F3FEAA7FC241119B2147E3E4ABE403911937CA81496668F2A49C2BACFB729E682EC2BEB16BAB341BECE456A5E7F042265FE2BD7AAADF95AE527D4D39065DBE607067DA212A633424D5E4D6642517B4E36C7D8AA67E9801F271B1DCD50FFD52B866450CFF785DE8D84BB28E3C4636E91690D302B7E2A076DDC4D39CA490C09D26620A90A2CA648BBD167F2A2ACEDCCE3BE4C5DEEFDD8EEEC7F02111FAF72FC67185BD524A025565041DEC8B4DBA49CBCFA5341541D3F4482757FD8DC9F587A6D059547BEFBDDB5D8AB0429B4653D727CD646CA89A0AC134CB82D78DF7A7FD1931BD81965821AA2F82CFDB6807E9F001A7B64FDF4871763695DDCCCC542659BD14159D68665025D5717DE7AAA76EAE1566E9219A169D11ED10A12DA29D53D74DC3FB4E2ECA1A884871F0DE0FC3CAD4E3B8922E8F6B6A461BAC649D906351DA43B300EEAA894A9F28616F9B1B8C80531F68D75A022CBFB7EC5F28B108FD79D463DE36D3A89686A229D6CB5086142268A4D0278C5C3BFC761870B0130AE7BE4A2B6E062B4927837A53E619B0C7AAC030E15784AA6FDC91E290DEC3051219CCC18088A44CBC716719F224DC8CAA2ED62E264B04A9E81EDF57C890D84A98AA0C79E7C7F2D84FEB7EDCA386FE6B3642B07BBFEEB3464F48CD5F805E961DC7D6E9ABBD0F83CBA6108200D25325562636D8C91010A2AABACBDEB061D4B5D7F92A5AFCCF8036A9DB2EA034458C01A407693B4CBD50000000000000000000000000000080F191E2229E3B57B208352A820F622A694B7C3F6F297239EF0A069615DC664C02F1822BBA48E11E37BD9749C98FACEFFFB0FE1792A386BE10CA7B98CC874C68C36F5096D3718DC93E0734D6D6F913E3B958DC1FD1424818C9437B0FD59728ED46A79FB52C737A1D1D26F04EBAC279A7FF6A971E2B69576B712D9224EA18FB9BF4E613A8935F3B36A073B01F37BDC0B77981C8F2804E93C395419352B85C8A32DD77D41DA9BF3ECB914173E80DD1FC06E8FF5BF0E4F7424849A15EB7FAF7DE77456EBB64D10DC10FEC6254070C7DF387397137372EA3A53DFDA7DA13414AF2DF16C1E38C5C70A5F5F44F725D622049256BB15DC04A8D846A1A0DAE7E765A7F00C498F1D0B2893B8405BE4A43FB7E97881069A49134A2A847184B82EB5A690D87BAF2F579619EE19A3D7A7C7EEA72D6E3FCCF0A8092BB8D3C6B551F27E63E762A30B4A4DF2DBC4D119139AE1B135D06FF827846901577700935E0011B65461C2EF9A7B71EEA33C8CA4519C7BCFB557C5E1D42D9243F2DC34057F5E0CCB9A457FC34DCB10D9B47F6EC3B9550D3AE4FD593DFA3E28C6CCA1FF1EBC9D98DA8DB869F8C80BDBF8AD4684ACB6A779CA9D0A106F26DA17043773862681C5DD2DEB1BCA2CA48D4FBB4BB7C1F765DCA3A1D991D890B9A8751CEAFF543997FAE5B128AB2EF22B3BE94499DFD9D8E78FB4C82CA8D296B0415E84CA8B5F2024455B5DECC8B4CCDC7BC4EE06B4F0C66E6748FBD07E3A3BC5B4B6889C40DC4A97AE3EB43C3914DEF976EFE3BFD84A093BD69102D7B37C89B458A55B98A1974A13A7685D26E9D816C79585BCFC1042C2AF88534A9FE8B0A6C8C44355A6D606F902DB40D5490264BF0F352C27355633CB095268D5B8BEC985A62D84B2323FE814053F05DEDC22029D2998BD0BCB255C162C4BC03F60E3580AC3AE86C37850110E9A1BCBD75F64A0DD60B941E2F57DA9D72498B3EA8324EEA53DA3895585ED2942B9140F260895DC6A1131A4C3AD2B64028BB8C0FD67E1BE4C07F808B47DAEF306FD9578025F9C639660075837B2C95473F7F860D6EA2C53F4BA677A2345CF212C7757BB94F1A4F76D4E96625F6FE051B8246D1B7611BF6FE325FFFF8514D2F9A3453F0E77AE8B958AB5B567E541F156C6F4D315B4C3C547D59BBD0D7403E2E6A49B9E7D3FDBA338ADA41875CEB03830A846A1FB266C0F1228AAD2B76A2E3404278DBE482907206FA66487AD2C999867F870C8CB7A70B83437E14B9E893BF6B391DAD75E84588E882246D161799ADEA63ADF1AD706C0A3B76BAE595D84B21AE9DA30BBC0856987F2C2C543D977747B8CBD5A613B92804ECC5284ED23650E9DAFB4B76D63F069710897334F18EA6B0CBF99CD590A78E3B050E1BB24C86D6323A17106F0CAE3F30B01E4EB3DB1B5F3A4771A880C8AC06BCD5A82D4103D0452FD7B54834C1CF8595DD77F82D4AD9EBC1CFD0C9A8CC787E10AA4D1688474208B69FF7AD4DA6986E5F62A34AC3093E0FB1EFE8AE3A96F6AAE09B0E8F6E7A2B65C7387999CECCA43CC33F026DC19BBFD867C48127CFF579D1D71AFF0C4A0E20F9FDFD599A6169DF1B85F6051E02290DF6F5EDE4F29BB6F0C8F806D6850C6534ECDDCCD75BB8E4A097C70445585740F822E5CEBB0E19EAC82BB78EBDE2CA60A810AC6C54119FD6427DA8A0155EF48653515A919B299A306FD3C62B505A6911DB2B56CA2F296E487BA02C546ECA2783ADE8E46A8C78EB1F3D7C04BB24548F92383E475CE6E572D8DE1BFA9B3E35D9BD6C79547B592C95693750010A3D22CBB31AA5A4ABE94897831B1ED9287631F006A735C36BC84A8C87497EEA4873801A733F35B328C7D2CCBE4A41C193D22F972571BA7630B33080793498CC85E6EEA1C412914459DA175A6DB8658D0BD7A823FAB286EDC20C785C40BFD539924A24AF4E3D37BD781353677C76D4672098F5BDD17017012571D9AFDA05A40AB56998E40F5E359C43DFE32CA10A45BF08F67D128C24B1ACC03CBAC46BA6CA5A532C105E91E0C77ED59FB534AEECD68735A4978177BB5A656B9F83B202BB604D61A24574C16656E512C0A4CC6F597B3268573E10539D1BA775ED83BB680BB9115011C6AD43FBB66FB37C467249060A1586DF27B2CEFA65265CCB9051E468000CCAE24F08BA941A8180A64BB624F146C8EC562363B32C369F62997C4B1375DD7DE64725A598529244273CAF8398913C6FC01522683CF1F9F965C491ABE7A554F0019514ED98D75EB8BB8565F77C195F629F98163494B4AA2674F92A41DCB67EDD1D818A5B98993D0B1198BB6BEDABBB486BC6FDE039433E842BAC568A5B4EACC028CC2544B57D8883848DDDEE2E967EA85A6102BD0ABDDA41C3D78447BEE1D4949449ABAA9B3377E8CEDCF04A500FD1A6916E26983E64B5E96FEF87B32A060444D374409262453CB1376C349A8B5D1767B1E2991A1A6044E0F58831BD11F12159675D215D7EAA74807C995FE22017E30482DB8A4B09CA7800822C75C92FF649FC0728F5A1D44EFE7D0FF147274152D5F2F60342C8F5F951D8C95F83C1D54613A182D9DCA68F54FD55047F1F90CFECC04D733DFA82CFF2618F29A4DB4F7E1E59DEAD58CA65D07CC90C25F804A895D6A82F9375451CC55506D276FBF783F7D4D53B9BFB83DBE4A8771AFE21AC543983D68034BADC980F9434527F9EDAA2E228646FDF75B44899E749CF4C9E5B345222385A4424382603AD6EFC24C56E769028F4394F2F6220A9B390D395E412498E57A08BAD927B8BD5D76E18E8FEB457FCBD3248D218236B07783E57FBFA03C292A9F5719E6AEF2EEA3FAB2CAEED5442E89BFFB236CB13DB2CF9C35A38C338C377C475DAF45F8EA822F9AAAC13425FBD43D3DD9229367F0B3687D7E82AC5EC2FC7CDB69C99A4EB1B8E45465C6A53F16AC0C4E0C970B8C732AF515C09EAF25596F64A04AE4621037B8841FD2B1BBCB310EA23E122B0B9AB96D8F7702952D0E96E4CF79C2A30DF0091ACDA91479EE2979B0054997C48F6A0E909BC52A943459AF25553969EB31CE7685369A7FB014561B4697B8BCE220983136E5EB2303CCA4EADD4C6CC74EA2FE69D448AE6ED953A80363DDED5591B27A1EA956DF081CE99AA59DFC789D9D8FAE952B0737099D467D + +count = 67 +seed = BC81485EE93AAD8B464B5199FFEF9FEFC06EA97645BDFE0B4E915B812E606A77F93917ED925E882161CBB909747AC4C8 +mlen = 2244 +msg = 89D960D04A3DF6984276A3D17D59AF9E72B25418C8797170FA701A672C5835CEAA22DC35470D038C6ACC5082D2AE329F36697C91CBB1F9E42DA59A654462BF19E04352192778CB050DB6F4A656F6AB0BD9641CA8CE6C1EF8B020A3D9FD9DFF772F38926458BDA6E6072456E506AE464785399AD7B498AFD4C211F09D0C722FBD9E20890CDDC8C6EB9EE75390E6D76D0672FA64D8B97C65CCA46DD1F542B6D6014F035D2817C4B9430AC8DC318CF8642AB34F4C8D71FC0E3B1FC961E94B6A84622876250FDC21987777360784D9A58F35E1C9B71F30561ED6854EE9B112E7B20CE064272213BD1A46D0D19E5EFAFAAC7ADDF4D7B7A519D689398EAF1E67E64ACE8E5E89756377E1FE458D04E3DF7F6680F8B69815680276ACDBEE6C8E1AA909EC56994F3EF3B65FBEFDBC29AEB0EA906274E838CAC36A0607716FBC2B8DA6150A4EF39E1CD9CCA72915007723C5D2442F7133258234D18A257DA2C13E53B47DC6ABC2D607B98E351FCECEE8BA8886821985BB3A7BD02429ECDC5A27EB04D01DADCE88A324AE44F567593FBF730C284414056FA33CE90A6D6F146DBB1635BD26B4F883D4948DA47216C70D2AA58CEB3979523C6A4F2F7EA455A97C7ADB6C43685D63BD4C51D7DDCB81A06B9BAC31A7B255B94052D686128D234BCB63CE713028451B18B981B83DA1246281FC3BD2B06C741CF71979DAEFDFA0FD06FBA3722FF7BCB2821FBA964FBE9F6467FE583C06D3889A40360A7AA03358175EE75EB8FD1D3368C30B5691776C163764DB924FBA2362CC9572F642CDD2B11B40FA2683A529EC2100DEDEDEAA70A1E639A71D6A96AD31F70A00FB63875D0FD5C21E56AE57B6E74EECD2EF34BB3E20BE5A1F9F1F54955A18B4E4E4B9119973DEB76A2A603FB6410A350667ECE5C1C147DD00B07A88A7D0E86AA2D747A867AD90BA6660C7A0432E20849EF642A20CF5A20AF7E34D139B39DD65C65B36750F17F0B9F1DB06CC6E16F10EB289F567B647454A581604F381D66371238AB785585A4DA2D00810EF6851A6009025FCADFB77FF7996BA6B091FE4130733466B29FED46554FEBC2AD291DD966BEF4D79A9E04014D3003C95696E8BC39892AD32DB6D6AD22D33E931BC87F78114BBBD97B334BCEA676F9E9DB23C0485EC06D8F37F070C143117B1BEA49F06E1A2423D98C12883D32D29103F7699646E7091D393B21A260703E17380A1BD85452702C3AF7DF73AE7856A1C066013014DE62C3C817DD74C44AA436A71490E7BDC6B8B74BF61711FDCC541AD7DC49CF4C3EC154879E048FF30DF25065B5641367CBD3BBA19606A9A27A64055D5D3B538FC88EDA66FF9F26E619DCBA696866DE54A8DC8580B5B28144F952FFC6DC543E98CC9FD7F4538135C0F4DEB4BF892266DCC48A4D1DDCF407BE4FDF2A5AFE4A0105A20CE2B3D9F48D608DE2315240875F1FED696C49CD8D4A78AD26F51B3C804949C536CE35C3963DC1D238516B3F2D297F5C9939A946A0170E185C75087F37ACF907F9E3F87A2B15CF81C7ECBF2165F0F3962D11E9C6A7845ECEF432CE9E1FBE74C77EA1057D79CB595D47A8DDC1D911C6B97AF76D91F3515081B95CED16275DECDEDCED9AC790D73739E35973834503133510DBE39201F9B5C618231184B9DBAFAA7ED6623E8BC492170812444DB62D4F01925DC4F821C0896A746B4453E93EE51844B311B0A0A51601477BFF651EB5EE331227A2E9E49F593EB2988E449E750E990A8A89906EFAB00E0955C81B6AEB160313007B481C40908130597626935389E47AFCB0A20146F0C7B29B567E95D59CED7FA8023A2D69C89443A11E7150A03D09EE6B0F74358141D48E9BCAA3EE081C7D8F8C223F4D48EFB3DF8A4E287FC5B90B4FD251CB616687ED09AB1A06C42EB9D6A578D72E99D499882D216DDB3F35B0A33D9F2D3D4A700161A5C3B5A6729F197479E78009794AA1BE3C25E0B9142613AD2EA508ACAEF5EEE33DACF60CB7A16AB38D9F3CAFD2150081B63A3A6CA0163A25FE81206A37A0874FD55FA3068B4C1B25E6325FA56646EE5F3431D33D0BC691C134AB306B0BD2D1087F4D898A529DAE08B97683FE2EB8ABC9095D67B79CFF0E77404C1F7FF316C3CECBAB77C710FBF961008047AF22805D77EFF79F815B21D142F517DA2199F6627AD9FD85AA24E9B7F40C7796207A82901C7B5A3A42369A9BCEBC24ECE13A3ED064E4E748BEE2890BB21B8E4845362BE9AEE46E25418F7CA38ED087E46E24F12012A1312BC623AABA6ED227CEF116A3C2130B4B837AC77D86F8CA3553BA0CF5AD45E9B4E4E55059F1D4675291581D7CC9E5839212AFCFA897E90CB601CB33A4D2241A5ED5925F6416BE5A43D4767FA04F701076AD5ED5ECE2D09B8DAF11B00FEDD2AA2E748CBCBE365031394EF823951EBC52B3E4C79D79234C16575910C29A35EB67C624F7504EECA3921F461D7F95EEE39638C402481DF7B59310C4554450789DFB28ED1E485C0018512EB05F14DC7A3DB5C0606F9E28420D76B8F8534D2AE31AA01E90A20E248A7FB3B72EA859031C67F7B2B043D38F7183165A42AB28C6308608C530A9CA98F82C133BBC313FDDD2109838E970DC9989EC14DF781A518F6CB56DBEDFC1E381250C64F95D0BE5F37515437673425374D44811F4406EE2B5130334BA555839E61AE623D283C77247D2EF8B22ED138A526F7E41DFD41FC69A2839B77B51C6FD96D97D3EF8359E8725BA1AFA80278FB3BA9C697F7E2BBCC5D3F0F2E61BFCF542D3160EDE02CD6295FCC55865E7890342572499347DF80EC073A91E00193BAF804B884E9CF5C43269824D4CAF7EEF49FABD8BDC5496D190263C96DBCD287681C19B90C34635FFBDFEAFE0601BBB7514FD84896A22895E9B21FAEEA372696E350F13959FC23533F3E8C34B17B595F3C935E37220AAF644F3A565114C34C7B85F1A3E465470166A62B13ADB00A2BCD5A9A3ECD59FB772F09DD6A6E2AD12FD54EC62CFACE0022F2FFE3EB62DB0F4D0F0F9D1FD6F3F11D76DA868D2C1C4124915DE19EACFFCDB31F7CA018B6976260CA1BB2C4FCD6B9958F096313B608E208D875EA5A1FA89916D0367EDC4F8890E93F1E660AFF16EA79D1E583007E693BF06C172105B3DC24117DD921FB60D3AC0D2E5C89FEF17087D885A0794E496E3CBEA333CF72A507788EFE +pk = C702C4F190D355F9C9377128FBB818E39658097E04AEE9201F7065AC5B27AE65BCABA8AC528DA2C179251672A61B0488D9B84D9A9C9C0AE99B506720AE943BBE94560D345A29B9CD2D9278CA85AE8A0B82BD126F136C4C7E7807920C4D935521AEFAB1490912EB4A1921F9B9AD03101DE17CCBD603C1B3E3931E1E7A2BE572A2A5273E901B497176129C4C11CD1F5326E7EFFED5E3F431A01DB35A9DC017CAD0EDE23AC5F79EF973F1F5CBBFE21B7CC91614BEAA50446DC7447090CBED9DB35664216E77067688B852AC95E2979F2E21252E2BF50DE6D022FD88BFE93D466AFC92699276D0C85ED09A544BECC379679BD465120CDD73F9A808F4696824498208DA5737585467B6058AE340077D86AC65D4213C3AC45385AFD064AAE637BAF350743C34832470CFBBDF2CBEF5A7964F5E778340B7D37A007997D00A6FE973712DE832142D36BC4411AA95DBAC2F8DD17A107A84236C53DED2809DAC8A035525E579F6B089338492AA3D5F370EACBC6C32CFA761D0547ADE584F21F86F2C97689250A5C6EC7CD78AF98B18E88D55A61FFF3333071676A75E6473394AFAB148E939E38461C34EBD95EFE68004E4C0EC9C88F97A0895B93EC479D6059CA5E0DC7323012FD8FBAF30E9ACB1B0C4992E60A787FBF9320A44E4A4F7106A56AA8C22551BC8C8B94D268A2725301A8FFDBA07F9DB7B1AF5578BC71F944838F177233B861AF2912C74D76B4928EA110BD75A36BC4B1FB61BD99DA495A3B26EABE1A395DB48A2DA6121129A8EA7D021412C3B9354CCE2BE2EBC16FBA2331CDBE0C45FC519261D18E5F201EB20145A5905C28F7CB43E27BAF7C1776489252CE2B36907347D50EAF40DC41344D92F22993ED9C121CD0592F78F2B8C39F24358F947A062D99A092B26840536A9E02796B0BFBD53D4B5A1671D852663373DF07C5C335D83162D264F71C4EBE6B4AF16FED8C738156832C5543FE83BFA4E3F4C8793DAFD7F8D780FDBACEEEEE85894904277511323529DC0B9F80CB779D0726DD07673F29725D574A75426DC0CDCAE402CF24B78B2F9F371FCB3CC948C87B1B8D7EE219A36D0DE1DC09D0F049B98771A3FE481AA0A350CBE6BD9451E4F91A3FB97262E516CD93275485FE84ED6797520951613287C2D768C4F0CE50F921585A7ADFA30C8485BE270CE7D50AD0DDCD9B51C5638EA6EFA2BF09E460ECC7CFFFC466C21B4A25E7DA2ECC9E5E7F98C45372B404F7108A29A3192F1B88BF00E7896075E904C93108FC794BBE1F5E2BD291A2F41E8BAE1BAB0BD6BB3D1E0AB8C206A8A7B1E474707207F32778B1002BA32C242ADB1C364B01294036A95D5FFA909C6719592ED7BDFE58772E05550594274C7324253F1A608AEFC11D43E74C632588F6DD398949A662A68461AD7087C0A05D9B2BCF611114DD85A6C8843E60375732FB8F8212876F04B941B8BFB1F2C34F7D01F385EEE305A143BA3E5CDF311227583DF3339E54AD32CF3FE924FB302C1BAB5B06633DD5E3085A8D69A0534E0ABC2938E19CC10247DB5D449D03DE497695581903F2CC9CD00564B340F4ACEBC109F208F99340B2009F023A43EB98E57C9158DBEA79F273B79B368439CE509AC2BF0D7AC084101D5A35A5B6AD8972D37B7359FBF9EDD096126465EB751179A41F02DAF30090EA6D78F542ABCE128FDCD058815267A9F7C5901E295A099E403789F2674A99B00B4BB924508753A0863571A9B2439BD7D275CC8D1E9B91D6C944931C61FBC1804C46CBCC6119FEFCC9B4C57B5AC13AD5E1AF743E4E535C239AC557186E6CB2962DE3F7042E91B1C58FB0593EBB6B72740DE4E5BE7805A816CBEF9FBDE2E3873549A513AE3B0C273ECBDFF073B54CAECDEE8677C8BB31349B175D6027DADE811328063153730459846A09A04496AD0E40F68FDD21536FD53D58CB7F42CF98CF546ED674D666F9C148F4562F585C490B2778E4DCF4F7BE42B82B852D1D3807E7AF6EEB719F5D059E10D05861D442FE2D4E6F8A8B255781E24C745A6DEC599B876FBE3E0579F5F263C1218EF51A0FB28A7E223D0088CB57FE2F18186C438AECDB9F8085274E7BF6A6D343E8EA7C5FDB9DEB78DDB00EBAF540BDE09383E956739F7B11C1FC55A842B07870D572E1642C8EFF9B12A319CFA99270BA94DA0A6090A625CC254D1EB1592239EDDCFD0AC99970FE5E7DA72F64562CF7A94271E00BD002403DF0D5AED7BA0C34E9ECF17CA950D74C31D66ACD3DD31ED480BA8BF9090ECB497B33643B6B7188F5FA94768EFB12F3E138CCA98BF098CA8B293AB5E2CAD7E0F9F4619F05B9F4CBFEB06584145FC782B406606326DB17FE89C9E3F901065332FBEED1EE5EB90C1D9C84762AC6E7B2DEC748D49BED5B202A87101FE0E7788ACF30DDC6E5B6B645B981848C4788B73587D74C0376D7DCE246F5A8554E7FD6EEE367F8F5A7373C4A58A04D643D60E842F91EF36E3186461B2033A6E4507F157B8710433D05D5E8F719FCC7C96BC8EBF70AB39D104CC9B4B116E6291F9F1B56E58B76E3006B03A453DD63335F4D228825A17E7B75667153AEBC9BD11D4750821E276F96B078B696E580398D7EAEDD6709F854A1065EAA84EE3C01A5D985564006856F79B2754954442940C47B33FA6A563DC4733946FB1F0523664FE46E4EB67F034B9B852225AE7F0CC58B5A8DA064A2DF239CDC1BCCAAC829CEDC167DA2EA2DEB0650B72D24E0B452ED000B288F46E48D7BA562D4FBD30F287921A2A407194617B22AB6D558516B7 +sk = C702C4F190D355F9C9377128FBB818E39658097E04AEE9201F7065AC5B27AE65BA3497341E9CF81E80A60F68DF3EDD22A10946680A9C64635AC8DF555BFE06D0B31C865DB35FF0785C169A60387F454B7F871FC538729BF870FEBB78A6560D1CDACFD1E58BFD33B03B2A6A6897AB9326256486879DAB0EE192B41B5B48EEB68A75582655178535754320840703408001262101067210082844158077211076553460610786063757243860474035612373410542320813525124515047703166610518520575777384871288560373875288101821638542128163365380516253186416524343645112020428834288011534225444268283024472628341450338570330046648351146456757150465660356883053787822366208855012650647577585810383365136864430755803205375652716457057052342824025081002606236208226207884614153631648535284261101325363418571146260065648740802823226331610806606188172256831265103340848325134517365431277430547670325388802723373066441556842712651508067115231323607602778004526507740351207645025684846072656724685654088452746181207215131228612270688278543174644110031660646767166884841631221470385066871472565314547061734107864858418553228147425012003105411726850304123730601624373857120518560876070633707706815356218378281406325827132730774688550082158248686400878634033854224534715421512763460058585870231666824420033542151255034056721312375351568421131428556845574775641071730473571121531536123712812561157722376445563112301157362662867817873604750702770817706723255357627064354666224423763423757668581685788226436432852258843552363573148004271748311316527202584623267260320018737823017588185688021265543127570717354613555055605372836708812502767825723747873564408166578315205744350801502720168813237838006830204222155377710820148004050437117664060070118146503503522580361186336848873627650411041043123148076132480726828004422637867788607720821706156823315472748510262657455058813173781117154028773248683377778823044250266876723681441752835152120326365868804200034581308424358361222057134182160180331232310874762638151781755805181275027031860308375761865275652257777078506871617613061300707701432871304432347476254461160476140374770317148404705464760565415034462006127257624338430624114635508205860107764662184570101162042483570717385077616434416238654267835053761881783527484851445002533367587827370843171877184652681150585502526556702616307764576851106534178553745720620426555486713201081660001418152500614867665502833276484256088280526666310178541820353782182726588861676768077400217735308455050652061754555668671144520043062604786863053246681525000104778508714486306482220604564086000353765850684744244383373725186620486354568455426780653245178506456587877676080378187552206403140516784807633635877146022210262204442663073872252346262751511363336264240603078270546247153255788472204563438046841524032327104274480457877535732236803500470161813252568188453058712484617380207751540110100810054600573015673714315407828142344010066778133815633884778125613507766457507752766174544503533560621602888176262421146565168542881835413220466640728206486077701856233718388572058527858253020511207604166755360401854228023207230012045382464520228733116622505054838113888616663056648301708003226271727570366E1CE419CE3D73B64DFE6E241487B885CB8553243BDA678D84174EEF85068083B887950AB0A16CCEA1CC1E0B8AC947751906A07100DBB7A6C7672614D2FEAA28536FFBE743AA1F6C555C73969F88D9EF959C8F422A8649949C5C4DC7EACFD0FC94EBF37920AB03E25685C8FD3C22FA12C8F5ABACF8B51ADD3786248E686E19D78B2421C0A1867981E2632C29C8E988C94A2E93AC684C0F7FF2FF9A6D78F5E160E26BB41C06D87E10CD3174566BF9B07BA24D1CAD17B52D801FBB358B97003B0F4125D8950374293B10BC6DF86F384B32B0E233BAF48599C145D8D2473EE35889DCE82DA316E9F7597EA239A0B126D407C540AD2C608AB85A9DF80C30DF82BD2A67ED57A46BD99FF77F691525CC1557281440E8CCFB821EB2102474E8DA38B9E03AE68AE8197C69A1B05B9C8C50C7BA51DA0373D59B68E095D42A94B352E77EF6F5F3D8494DEDAA3D12FAE1240ED11324F10E3B18F27838D05630D99F27116FC06D34BE0A0948AC4E3E421B250BCEF649F93D17D69ACEF9BACD6663FCAB936D862D26D585C77EB84A0FBAA5092F7A91B9C2637EC78F1BE6E0E75DC545E88D93EC5DFAE3E6AC4EC40266A4B2FC3B55D64059C16B96B030B0459805E83736C1EE5B77961F70F07D18676DA3196C0464F11BC444B0C3BA9C494969F56AF740856BC046AE7C8F9A0A903EED8F4492793B5F5210EFBE28017A7BEFD918BC69631A83B0C66A2B4C5DB7C3AA893102CF01A32FEB22668436A5C52AB28A1F1896E52FF0195F6B5487B69DDADF99D570E8FEFEDB8DB4F087554610B972907E70B01E73051DC016FA310E6929813EFA6CDF7055BDE3BFD6B8C8EB3F80DD5B9FEB094602B6177D1A08D4AAECE0C16C5268AD2EEE1A50EE5D7EE6C98D2283CFEAC39B7FB9F6F1EEEA9536309C2E7E412A0467CFC390F0C2A3110F3508B162769B477BAF0631B49D3F8502A2F8FB81D320AC9C752F7F023BE22B90793A8FD0DB7320A50B32C67CBC4F958EDFAFBFD4209FF7A7816711A80C153C2202EE4D7CCBD8E5DB7E5F18676A7F69D1D14D13163DFF75E9FCE323F3098EFED71868531ABF30B93A1A6326BCEC9E244A9EB813DCBE4F7BC2F17F81F5B38F439E3978C361B832FC00C6A05E0109CA3C93614E9D6DFCF198DF9D8D27143114401CFBEA9747009FC770A9B4FF9DFB599A72CD553E1C135D3AAEF05BB505757FC5977522278F2BF288B2FF167035C154C1470CC56E17134961BA4DB99ACFC66D8783A8C4ACF4C8F216B2B437ED34BED5BCD79E0AEEF9E742A0D45F6329E911BF026189CDFE6EE3B8A89FDE91EA23D150C1AF9EDA70951E81B1A5ACE47E1D3EBBCDE4E3B8B9147E89D9991FA95C3D245D24064ADAD3720DFD056202B617DBCC947EF6C7D6A77F5C5780668ADCC3313E95FFED2B0747CBDA8F95A2D8251AB18CA55112425C9A69C5D7C20924F2291A77FCDBDC6E869DF3076927E859366406E4CE7726C497EEA9F412CC099E2556D62B216BBD49291C0AA1F7CDF8DF6DA2F11BF1B30B541DD9B0FC565F8DE5FE3D0504E7C846978A6541C857B50768392C7065EB98820C83D638FDD667105F6813BAB133E77CC649D7429EA516530CC1DCFB475A3F52D4510C8B1595B8AA36B826698C6EE1001D5AC460DCA95C4DCB841B60F4B8E2B0BC32F455BCC9E22CF3E38C8130E5B6AB87DCA186511714A3EAB2A7082C08195EDB30EDAB285E40ACF6BEB827897576EE46B4C255AE6F07F3BD5F5A69879D348036058A3925F9AC376F2E50B8D824A6878F657A7E546891F95383563C4EEC80455BA8E7DE6D39409FE86131E593678A46701A46E7E18C30D991EBA1958B60E52C34C75D42A43BA206B334E8FFF5CB03C1D8BA3D2ADA3EBF78D8E5771BFA0394C13FC3CF88F7189E3DF5CE34D3D92122DDCB1F2F37913A483C27E94F342362DF062611CC8ADA4561957163E9C852AD9DEA1CE1F81104BE97ED24AD60B4A8F3A0E262F608C6A8284857076B7AEB884CD71EA1A5D04A3C42BAB0ED2B27C3013B2F1E4F1B183B4A7BA50B11E56FD07893AC166CC68DC24C86CFD546B23B1863407B3675503150133279BA9BC4F533CE1F57F7752E87156DACA2027A64C4149D594026B5CD77FC718F9E0C8E3C05D09F7B627D7AC663C9AF0CB31B79E1B90A1B81155B79E72D5336DC321BD4E554AC6DA9F4785937ACD1D41932E520B5E7AEF4961DF76EA5E9B89BD1A66A91520E613522D68A4B813568B9C3155634D601D93A3D346F368BF3AFDEFF9AD3C38526EDC56DA28A65E070287AFE6E6AAF89E67D8A6D85D06F44C87DC7EEFF56D6762A610B4D2E0BAB9966DC9CA7314B6A7D59AD0BF76E32041F6C8727B35D859C428013DEB7F148A59963AE5DC61855163C77ECBC6256E4442C3BFD4CF65F39292A79F318EA9A6CB86B4176DF8663C195D9F904F967CDAEFB48E9FBDBEE7B9A7764F179E59AA6CFF839EA9F6C13B62853955437C31856E4D6E8A30A52009385FD1444F126B397FAF32909D0925FCECAEA9898163A5E4B71A96D3AD7A8B5453C9B076106EA112183C7E3B364EB84F91523B4B870D66DDB8131070520B794E7CD92784C8C0E867FA9130A0EC162B0EB7FF56DEE5AE98A418F57A9F8D0FE77D317823FCBD68D6ABBF4B3CC9EFCDF0C8967021781CFBD3D0A64ADF66581CDF047AF75530F37EF5588CC2EA3FD49D80C6CB5066DDFB8AA318D2E8F0C688CCF45197D72E6BBAC11563A3BC76887AFE2546C4BD64DBE2D688E62642840F8D86FCAF0CE60EB55C1BE105426B25A398AFE4B5DE55F1F733C9D1BB714647A9E9AD7DF98CB899246C4AAC3E40CD2C709BF6D540E1D3CC486E78131A971305D4EE5465C4EFBE33FF31A18BFC895E2797A622EB6BD24889AAEA864167B0E3F4D27169C6577C81812355DDA5C63198D142701F1DE7C02AB0D52210AC395708DF5717DF782720F84F8F087E33E156489382C8E9E31AB547DB71D87071830EFDDE0D266F054A69781F8FE05A3B823BB238C444644A1731C144A6FC79B616E3B3ABB4087BC3948989E008C8A8BED62A070EEA5F0C208707ADA4307C7DADFB5D99947FFDA669FCC9826C29F809AF7AD23C0166845C71CFF1EEF2480B2E0F2DE98FD9221445CFA0D65125A155FB6A42BEDF283023F87B2B03876F22038EF55BF8F813A8D31FADFDCC048B6788F1AB5604127FCD58B654CD2879491C8904DA9DB2969ABB63290C201DA03C4CD560D10A25DBD17BCE51F8CA0BDD4124D6DA3E5CB1303F2B31E70AE3E996ABBF3A0CEC7679618CCB42DF5081E8E0255DF9887D101422231CD0ACB7F0E9D05744908F72861784208597807E60B1AF5DCB54C531F348B56F8C010969EA9CF7D2FB70F5767F77220A9A365EE49B1C33FE18D0385DB326852F752556A15E8B35593A847A7683B9ECA2652057B8AE9326462CE11F8A4DF35CF73E215623368AB64BD4470A2B5A59B0942C1CDE68D6041CCA347D5A19A46B6E4BE624338FE5803C3A7215018BFF17BF78679AF9B6319CD0373138E6ABADAF6BE816BE02DF0CD3F661354AC1 +smlen = 5553 +sm = C55E854FE705F5FA65415E068F79A271BD7E9812D492A15F3F0E84F5B8A825A4F1483B353A9C11EF11B838FE36DFB41297B71FC46EB90AE9490C79176508C09946FB42417F91A399B8CE95204F19A93E67C0C1E47FF6C6992974B21408BBB09258FBB3403FF247734D20F2CBBD2371459B000F9D19BC4462D5CC44AF226B1D42E6132CFFDEEBA4E2442C58376D5511D6DB067FC74E40FE56FC2315475AAF480E56286AE8EEFFA096BC8D1B8AAB38219E3C8A46EB07664E661B9F238B82BF94ABAD7F7118F1051F3C8690AB420D767C4A2A9C0CA63D3B4FAA54BC80275F85F5FF6F06766BF0A26D84EEFC77CF7539E2E15D47716D584D765829DD6A3DA2958FA2FF3E2C4E8D79AC02D287DF0ACAE4A89DE8602C85C3E93FA99EFF9CF54B78E9D3275A187F63B2DC85C07666B5351DB4871C86595F5A7F6491F2A041D6FF580178D6735C604DA45E35A36EA92DAB8F6EF974462DA481C837118193D699A4FBC0BDDFAEE6F41C39DB9B53D280FEFE9FE1D19BC9E208C7CE7D0F8E8A4B1A3AD77FAF362883F47A98EAA8F56723061268073107A2D2D332F61C46A5669A43D78B7216A52040B3F028EE9DCA02F1DBCB579C82ADBB14747B34021CA968CB4EF9B2FD18B57FC2FFB0A73D0CF2E766AA4F806B38E41453A369245DF3469E90FD9158FCCD3FA409462A4AE7026606947FDF9C4F2128308745DEEF0ECBE0EFCDBF948433BBB50E2C6FDA0B17F61FDAAA1BD1D1E79579D4DC172F78F83A7359D569BFAB7ABED386315BF4B195E8F29BDEE6C7F53E006CE34CB123A30CBF44B9654A3A10ACEB6942B9C474D1A0F8C908A683556A7B00E3E30CAD943D4176A06FC4F1D9A984378BF0EC0BBF7040537561E7B1C428E78CC8B1C05095344317F7A001C38F356FF6A0820CD72D7F22AE0CFD433DB27B50490079579C56CFBA8CD7FEC50FEA7BC11AEBC62ACA49E769A94C6FB2662E1099E22E6B5C815579A87E8326E90DDB66CE290AC7DE885C38E5649B2CCA732F0D31321CE267C6C3AF0BF6FF7EB0A1729075E2AA65056FC3590E460C8A3BAA262CFB9E0223FD3287F484D05F0E68CD1EF4C94E009F89CCD1101F5676201F47F7EB10E350529BAFE2B987E074E8D611DDE4458DBA2BFE6BE140C89E3CED5131E4504F2B0FD4B6733DB51E6A92E017BF83FD88D8A0E905C40A6390A2CE0B86679948AF39A64C96EA0836CCD1E8E5453D69B624C780253B1B469267251A3B2B4B8D6435F73C831A85D6AAF034036E8CAE7E00E61DAF88ABB2EB3560B63D18EC26C53D1E23CAEE02A56B16FB341036C155AF7B7BCDAD8BF29299E66ECF107DACDE470D137E9E330CC9F0FE0C18ABAA6C9921661BF7385ACA9D04A689E5C6B72482F7AEA98BFD34D6D33E5CA1BF07300E392AB1FF136A22252F9BFEE54DFD25C1E6B413BB0CF0A44F28E230227A8B2532592E56592A7A3358183F0702556C9CF246F9995059A0F97CF3366B00E310B2BE453E02AE637E07FAC0E9DF88AB4B0F147F205C63FE82783E46E51069C79058D8FA092DD7288A93F32B02BBA5D2FF03DA86E7303565D1211A0E0F1F518ACBBDA6A67E75EBD5A497F0ADF818F7A38DF453D01334BBD100C2F24A2621EB315C673465EA8E06F0C7D199B821E52C6C2623D75443E94739A185262AE6178E2C0B036309792DE803732068D06CCDF54E055CCB4FAD9D3A158EE9819159BED844A095CEE38AD8000EF6363D8BFCD33F935FC88CAD0F75CFF7F9A7CDEDA43294BC4A47C0629BCEFBEB322531DB6289450F3AE1D602AE8A07AF25337079DBB3463B8911FE2D8FBBCE50E626B16BDB2352A7250B99555652B649312545FD1B82583442516A5311CAF0BF27CE0068A4EA4F3E78D7FD09402BA5ABE56D914A4B966A1D8EC072B5E9F888FB430B75278A72A46288A1CB39BE7877963FE9CE9E24CDD627544EDF931C376A89F8C98EE485AB16AA638F94052BD216470C4AA37D70B6F53974AD5C182BB0314731CD1B58C3AF5335D79652E5F4ED6E03A694F4DB3D777D4398A51E4E30A2C504D6D86FD929702E5E9200D6E3F6BBAF84DDB1E2E06C38BFA57B507A7EA0615419E8C3C2D7FB94CAF94E347B613B453AA4A88C2A658E3428994FF669E46B107A32FC525324A2E4CCA55E35229A847F225F0173F5633A4C0BAA288EB64AAF73677F4EE3421CCE59B2EAD38911C7C0A72D2F252D92D01D1C797FD7ECA2DF0C26FE958AD3CF39EF0F7FF8458C551E2AB4795D0B9EF780F2425DF5D214835710C653AB3817DFC9C48196CA31D337DF70CC1E0C5202C8E4E47B5E2AD82E062A6DFA868ABC518CA27BD25B35A3529B7BD025E68CA1D11C010AA01AB4ECCCE3460F5C6AD279F9AB26D97C780408CC15FEFA146B117A5DF3AF42F087A5FF722EDA684159FD2E5B8D34390BFCCFB7604BCBB3A749839F9F4CF8ED383B8FD7E6E43246EC4B0162C51D6FC7CBC93A358A9D0B7C35CC8FFBFBC4126D4820985C5EAF3382328A96D6F1E87C0792EEB978E3758304BF3616E7867749E373BAD0003E18404A188D37276574EEB92F78A4FFE46596DFE768D3E2606CA775B0BDD5DE2945FA2886B011B2795B7D770CD4A022017DE512574A7D063F86A78C843D99C1A62345DF1C9448BAF984FB37DB54BF4A0E191147C0CFC62F5A056EACD286CE56B84F95767C636C4278E323BDC66B184C965F383DD4939D3AFCC7D4E51142EE39D9B8CD18C261439DB25AD782AC18EEDC77A4F49D6B1990C0ADC86135F7B763DB568D645C79E2EEAF7B3CF4F0A547AB7D71C112A69310E61E0944FC9207570893C97D1F4EA704052B428A22945ECB70B7687A1D176B4BC07A69A6922DA474F901E133A70A94F78C0105BFE550BFD1FC514CC26DCAB1B848CE2760CA28C87F847A4D72E7D67EC1509D4CA464494B337A1FC8A8529F91088A58837BAF7BF21B8E1EC687B15845AC12FE9D6A591D7A3BE66FF434F0DF65213A945B4116D65E8CC91C53AB36C0AA4A0C2CF5E90502729B61E0BAD9A426D07E7356A5060C6B7C76A3D7922E362078EFE294F3B71E79C7FB4D97980AE810EF0C87AF086330AC3CB3F0679D44F0903E887C514067559D1B3B41F045F092475A550B6D0C2A31C33615B485DAE16969EA4FE1E28902B1B7C07498ECC4B7DF5C9A0D43D62F80A00C84FD8DB252E32C887CC07C3F40BD6F55A063F44D7A9488A8ACE98DDDDF6F809BF6415DF4C0B7D633A0A794C6F7FC721E0745415F04F8CC737EC7209B7862F9D52011E0D5BEA2B1471F3B2C767F94A605EB6987F72C38355EF7895AF72937413BA22037AB0BC8CD9464FA971E0790C16037010E374A9957D8A6971C3ECF2CDF38CB0B8B50A8F4716740A3FDFF6CC73DA68F639074E4E0B2C09D1CE33A3C6A340E6600C517BE1A68737A7C52DEC0BF0CE15693ED67B18E0C185018CB4F167F6DA9BB04A9755B1BBCE9F5CA238254CA06EE844C6847878645D7D74462C871BE0167DAD46C5C9DFB7B6452D045D4C310BD2D32B5D0A43A36C358F8FAC0A30FBFC0E5AE9A5D642E42CFC15BD4BE6EBF44EB94771F370DA40FA4B3B70F7DDE84A01ED87F1411003B142A82F5F072E385AE32A92624150DD3847CD0643D3BB8541FFE2C3BFB459BD20810238BFA6816261BFA4DE77B00F345C7BECF529670C134392627B5D8F7C06C79C7E448719BDBB0C8261146B820002839F6882F0991B92D27042AEDDAF24D085279FA02B1B17217C737B85FB171A48F9B0F5711D79BB0AA3233C57B268EB59F99509DBDB3D0A7346C1B8629414B4CADB9CF7953DFE23001B15BB645540A4C232B06A8D32B5A6D362555FC964BF2DF15F929DD7ED6F771674E3EC3BD794FB668D333FFB39A921026A04B1AB56E04FD1A9E152E125DBDAC7720FEBC8F13C963E787B0EDAFAF693B46CE0D2BF056F5A61DC077B3AE04DFFFEDBC8E121FAFA731E2B2DFB4B476444A8426521B0F330561122C922E5DD14043D05FB5887D4B2F9BA92F62010EDD387D651CB535472F0D45BA51F8E42A4A503C77889B61A3356BE1954B7656C903A2E330E9DE53978CE4B51B616F1C560170FD9A626ABE761929878310EB7915B8E3D805497F5053EB4FE11F5B9C1D0A55C27EB76DFD3BF5683D278DED986D671C0B5794131C0A640A59D63F11D3268C459C5F47985F2488675CEE601AEFDE7A4B9B0BCCBF24E2250ABAAED91617F171D36204C0BCD3ED25645FF9D055915617A6AA1F80D2F216953E869074D14FCC1A917F9540B105C9EA8CBC839AA29020AFEE9EDF940F281287E6FD25CDBCDB583F63408BBDF426BB253A8BCF4D55F95E6DB099354A904C5C5D6B3B8F35F496EA2E0211B79895754C627AF74C6639C212BCB6C48ACDBE25BF6C57F82366D78D3973710A51F753EEF4B3DA1338A07FA421C37FA5EFDE2AAA25C1189EED699E4A735EF4AB9BBF01386DDA3F5BAC6A6C8A384FA48DCBDA28B52F30EB5DD85668564B37C337B58425CCF0F0CD236C607FE67E1CBE72E6EAD1292036409399DCCFE1E6AF98A00DEEDC3759595208DBD0420BB0E2BE66978026373462C6504C592F69D3E3C19B4D24CFE5539E18D9A6F71D5D364086771133D7261E8313F339AE32496B23462A484968728A9FC4EA21304DA4323C4DA1CED1034C616988234E7FB4C4CFD10A292DAFE10000000000000000000000000000000000000000080C12171E2389D960D04A3DF6984276A3D17D59AF9E72B25418C8797170FA701A672C5835CEAA22DC35470D038C6ACC5082D2AE329F36697C91CBB1F9E42DA59A654462BF19E04352192778CB050DB6F4A656F6AB0BD9641CA8CE6C1EF8B020A3D9FD9DFF772F38926458BDA6E6072456E506AE464785399AD7B498AFD4C211F09D0C722FBD9E20890CDDC8C6EB9EE75390E6D76D0672FA64D8B97C65CCA46DD1F542B6D6014F035D2817C4B9430AC8DC318CF8642AB34F4C8D71FC0E3B1FC961E94B6A84622876250FDC21987777360784D9A58F35E1C9B71F30561ED6854EE9B112E7B20CE064272213BD1A46D0D19E5EFAFAAC7ADDF4D7B7A519D689398EAF1E67E64ACE8E5E89756377E1FE458D04E3DF7F6680F8B69815680276ACDBEE6C8E1AA909EC56994F3EF3B65FBEFDBC29AEB0EA906274E838CAC36A0607716FBC2B8DA6150A4EF39E1CD9CCA72915007723C5D2442F7133258234D18A257DA2C13E53B47DC6ABC2D607B98E351FCECEE8BA8886821985BB3A7BD02429ECDC5A27EB04D01DADCE88A324AE44F567593FBF730C284414056FA33CE90A6D6F146DBB1635BD26B4F883D4948DA47216C70D2AA58CEB3979523C6A4F2F7EA455A97C7ADB6C43685D63BD4C51D7DDCB81A06B9BAC31A7B255B94052D686128D234BCB63CE713028451B18B981B83DA1246281FC3BD2B06C741CF71979DAEFDFA0FD06FBA3722FF7BCB2821FBA964FBE9F6467FE583C06D3889A40360A7AA03358175EE75EB8FD1D3368C30B5691776C163764DB924FBA2362CC9572F642CDD2B11B40FA2683A529EC2100DEDEDEAA70A1E639A71D6A96AD31F70A00FB63875D0FD5C21E56AE57B6E74EECD2EF34BB3E20BE5A1F9F1F54955A18B4E4E4B9119973DEB76A2A603FB6410A350667ECE5C1C147DD00B07A88A7D0E86AA2D747A867AD90BA6660C7A0432E20849EF642A20CF5A20AF7E34D139B39DD65C65B36750F17F0B9F1DB06CC6E16F10EB289F567B647454A581604F381D66371238AB785585A4DA2D00810EF6851A6009025FCADFB77FF7996BA6B091FE4130733466B29FED46554FEBC2AD291DD966BEF4D79A9E04014D3003C95696E8BC39892AD32DB6D6AD22D33E931BC87F78114BBBD97B334BCEA676F9E9DB23C0485EC06D8F37F070C143117B1BEA49F06E1A2423D98C12883D32D29103F7699646E7091D393B21A260703E17380A1BD85452702C3AF7DF73AE7856A1C066013014DE62C3C817DD74C44AA436A71490E7BDC6B8B74BF61711FDCC541AD7DC49CF4C3EC154879E048FF30DF25065B5641367CBD3BBA19606A9A27A64055D5D3B538FC88EDA66FF9F26E619DCBA696866DE54A8DC8580B5B28144F952FFC6DC543E98CC9FD7F4538135C0F4DEB4BF892266DCC48A4D1DDCF407BE4FDF2A5AFE4A0105A20CE2B3D9F48D608DE2315240875F1FED696C49CD8D4A78AD26F51B3C804949C536CE35C3963DC1D238516B3F2D297F5C9939A946A0170E185C75087F37ACF907F9E3F87A2B15CF81C7ECBF2165F0F3962D11E9C6A7845ECEF432CE9E1FBE74C77EA1057D79CB595D47A8DDC1D911C6B97AF76D91F3515081B95CED16275DECDEDCED9AC790D73739E35973834503133510DBE39201F9B5C618231184B9DBAFAA7ED6623E8BC492170812444DB62D4F01925DC4F821C0896A746B4453E93EE51844B311B0A0A51601477BFF651EB5EE331227A2E9E49F593EB2988E449E750E990A8A89906EFAB00E0955C81B6AEB160313007B481C40908130597626935389E47AFCB0A20146F0C7B29B567E95D59CED7FA8023A2D69C89443A11E7150A03D09EE6B0F74358141D48E9BCAA3EE081C7D8F8C223F4D48EFB3DF8A4E287FC5B90B4FD251CB616687ED09AB1A06C42EB9D6A578D72E99D499882D216DDB3F35B0A33D9F2D3D4A700161A5C3B5A6729F197479E78009794AA1BE3C25E0B9142613AD2EA508ACAEF5EEE33DACF60CB7A16AB38D9F3CAFD2150081B63A3A6CA0163A25FE81206A37A0874FD55FA3068B4C1B25E6325FA56646EE5F3431D33D0BC691C134AB306B0BD2D1087F4D898A529DAE08B97683FE2EB8ABC9095D67B79CFF0E77404C1F7FF316C3CECBAB77C710FBF961008047AF22805D77EFF79F815B21D142F517DA2199F6627AD9FD85AA24E9B7F40C7796207A82901C7B5A3A42369A9BCEBC24ECE13A3ED064E4E748BEE2890BB21B8E4845362BE9AEE46E25418F7CA38ED087E46E24F12012A1312BC623AABA6ED227CEF116A3C2130B4B837AC77D86F8CA3553BA0CF5AD45E9B4E4E55059F1D4675291581D7CC9E5839212AFCFA897E90CB601CB33A4D2241A5ED5925F6416BE5A43D4767FA04F701076AD5ED5ECE2D09B8DAF11B00FEDD2AA2E748CBCBE365031394EF823951EBC52B3E4C79D79234C16575910C29A35EB67C624F7504EECA3921F461D7F95EEE39638C402481DF7B59310C4554450789DFB28ED1E485C0018512EB05F14DC7A3DB5C0606F9E28420D76B8F8534D2AE31AA01E90A20E248A7FB3B72EA859031C67F7B2B043D38F7183165A42AB28C6308608C530A9CA98F82C133BBC313FDDD2109838E970DC9989EC14DF781A518F6CB56DBEDFC1E381250C64F95D0BE5F37515437673425374D44811F4406EE2B5130334BA555839E61AE623D283C77247D2EF8B22ED138A526F7E41DFD41FC69A2839B77B51C6FD96D97D3EF8359E8725BA1AFA80278FB3BA9C697F7E2BBCC5D3F0F2E61BFCF542D3160EDE02CD6295FCC55865E7890342572499347DF80EC073A91E00193BAF804B884E9CF5C43269824D4CAF7EEF49FABD8BDC5496D190263C96DBCD287681C19B90C34635FFBDFEAFE0601BBB7514FD84896A22895E9B21FAEEA372696E350F13959FC23533F3E8C34B17B595F3C935E37220AAF644F3A565114C34C7B85F1A3E465470166A62B13ADB00A2BCD5A9A3ECD59FB772F09DD6A6E2AD12FD54EC62CFACE0022F2FFE3EB62DB0F4D0F0F9D1FD6F3F11D76DA868D2C1C4124915DE19EACFFCDB31F7CA018B6976260CA1BB2C4FCD6B9958F096313B608E208D875EA5A1FA89916D0367EDC4F8890E93F1E660AFF16EA79D1E583007E693BF06C172105B3DC24117DD921FB60D3AC0D2E5C89FEF17087D885A0794E496E3CBEA333CF72A507788EFE + +count = 68 +seed = DE9E2742591A5AF6A6153DA85A510C39FD31A2ACD8A8511F190A9A5E5753E63D9801A8019508E67DEB1E9219CC18BA3A +mlen = 2277 +msg = 8337940EE74590EB25E52E78E8563A09CD2D45F650F48775E3E61F9E3509CC8EB7E983310D0185359F66BD80E0DA1E45A6BEB53ACEBB9030E310E81A576D0F80C64FCE1D1FD77DCA27B7C6E02B0CC26EDBF496AD2E3CE8484E988E56BB28153587D7ECB02FD8882545E7BF79CC9966A7FEDE93F7E9451BC48FDBB481673D1C4135F95D68F40F4B4F847345A320FB4D736BF5F9FD347435462DD3A238E4C799E7CEE081107E11682C7B558B19177522427F1D269FAD81B565BE538E8FF2D7193579AEE51E50974BDC0B66331B59BF496C87E4F6E143754076DB516C9C538410FB38A930CB5BA1E6610441126D01C8EB5F34E2E58424B8B218D9E68C5D8B4F5258EEF07EE0AA5475A72CCF363D47D825FA524C16C7B7587C44864DA9E4B267F738B87F7E5701147F550CD38774B17DE48E6969A0DEDF334FA67470419059C4D1607880CB12FA9C0ED23032C7E0F325169EACE7DACCDD4C2E5097FBBA859970D7EAC4522C1FEA043C9278C1C89FCCE95203033B4CEA4F9F24B55BA6B79EF88F275310C6E48189EFC1EEEDAB66B56B6BB028726BC463D93D742492841E85D5C837948978D0FADD1C172F8859C802C6BE8394A05DADA7546EE1CC5BB909D3189088F4FA6D07C573ED7263C081720E701D5D4B027AE54BE175536F3BD5E91993CC040311A7D352AA26414CAE30D10408DDB44E8C9513F4619E99EDC894F963489876B24BB0B91BDC3EE5B78AC0D4046B2E864789C0C779E5AF97F8F84F09A26FF74B8BCDE66C007970830B70C2A1122DC9845905C3AA7810B40641E8BBB398A23BBEF52BEDABEC7BB54823E64177A73786992DD67D5C007D770938402EFBCB3A60281C5706920A9EEE4C26C0B251C32B9E1936FDEC2928110959E99255508250FD5BA84B4FB314187124072D30FBF2163D36F1480ECC08F7FB8093BFAA72F1914C63533EBB3A57420DC38DC93DD6AE4D197FAB790C1EFC1B7A2234522E0B408D0648C7AE782F2F08CB70B96CD76B5089AF1EF4BA3A4C2FAAC363A4DC1C6C421F6AE1E9B67461EB02F36C25E763F1A2B73CEED4DCEDDCE619CB313D124CE6F7AC986D6BC344E630F22CB654C1286FBC0EE01C968DADD1EDAD744C8BC828CF5F316336A5883166ED000FF98D6CE2CEAE7D3E40BBC5714F71BA9E25E1506D644FB2DE2FE190D327ACCCA79D9B6D9DB505CF1853E98F30E9BA5E568ED83E2567C936A64420C5D8F07AC4F65F38C28E88DD7B5209A600AEB81A6D2AFA4FAAEFDAFD9B7FD3AD7F49462CD577204184F9D44A45E2A909373CED24EC0EE56BF2E6675C506EDA67B1E6DAB75CBF1822E20E7A8A81A7729B42A6D67A1DD457FCD19B62F048AB97B3D694254E5C051FD2DAF3D12AD627EC37C22117BDEE9EAA290D11D56BAFF0DE1037EBA908FA03E2F869FA2B27936669306E8E70A0A4910A123F202797BF1C8FE47178BB1E8E8D7AB1C01F30F5E779B2BC99902DF15185FED4C865997AB72254162D00858E0908EA95A9ACD0FCE72E571C7A381CC33E06A27FE6A5922775EE82C973CC3CA8A05717608F8703946C9A89854D627744DA475DEFC1390DC44FCC3A23C47AA8AF17240EB1A1A00A062D258D471F31333D0356243DC1CECFC559378B4395F01A970EA4074D5666B44D49EF291ED15930DADA66765B165CB8331CFE549C38CD0672F534BE60F4D9B4C125FFE747670513B5744676899B256B992E15106B99B794DB3950582816612144649210751F3D0DFD5B25CD393E724F7FDEF00756D0C8540E8891E592507599B06EDFA6EBFE543084AC81858F5EB02D8F5EB8A72184851E8589A3AC6DFE1CDCF286723FC4C1202765FA4F783EE58C627ED494C7149BCA6A4DDB420827CDCA82DC42515BEAF46CE9D9ED524BD00EBD3094F770B1E1DD09FC431E4C244D2305619DAE208E65EF385EA92F5A79F12B99AFDAEA79C9D8D319944AC6CBBE3F1290EC6B87D97785E059E6871FDF239BC404021CB52064B88EB4CB3FB6A871B0F76C12D7B8C5E8FE0A65024AB5B25F4C67B6D15C22B0005B754CF7CBEC898B49F4326F1AE4034E5F5A446A96CE08083D48525A3661E10C996DD22DC34FE570A4C8817D10D750FC5C2ED0C24C7CBCBA5CD1B2680DBAA3315FBF2BA7457ABEEDC96B5D111110D4678EA5C7851D25F258926B0B028365799E940A6E17BB03CB332FBC6D713DEA7108FC6268C8D33E7A578C94FF75BE808C15FF7884F092C0E309F1AF99B1A7314FA0F32C8D8E32B3E9D92C9C8FF6B8FBB99111529C4BE3A2A4F62884373D0903180B4DEABE613DE5CF19415DFBA7F9A46297AE2F21D7EA420B41F628FD8DEBA55207606539D11791623CB325F1E18C98AAC27283BFAB2408F4FD6CC58EC9E306643BA1C0C77D84B3930263E5A76A1CE94F3D7721F0098D54E6C990C3AFF69B6A0D82C853EA2AF2D3D2B3E96DAD59FF873171B55D16CA9A7C68DAD2E918174D264919DDCB4B9D01CE622D56C599BF60711C74315C918A7BB97B9513937AFB6A652DA68B6B0B34E316D7BE9F5C282A5E8773C892782EFF220667A6A54069C37B88EB1CE676AAECF2015E59FB7AF4D30C4625DD8DE4805F505E83C877CD61D2A0BA65B32B0DBDFBACFC88CA43E4DDF7A1A4517DCE83B7B8ACF8DCAAD28284039747935865DAF8DCFCA29FB676CE2EBA2C509CD75588FA5E58CEFD0694626C9BB31C3AFC372ED313C9BB3ADC398E89DBDB108DDA63F9380EBF9DA17B378451634682F9823E209BF10E39F884ED270413152025CDBF4875C121B1E83E12C044453FFDA6D8CA2C240AD522577C6898AB6F2ABE1FE77F860939408CD193E605F87FF2248FA163AC2FC0F39BFC38503B23F5441E0E364CAAAB890073266B3B51217661F5DF41C0BA925BB425AB3DD7B6A3675B7D60D0290131EAD53A4EAB0C66BAA83F2FB77E74C3C123ABA7731A3F62FAB8EAB2A96E8BBC911E501CD23A088E7887A469284E0B5C27B5CBC1DE2B6938CF1AF58A47FE78141306CB76E8F2B73620BC4549DB6826D2D72873885F6C5311EB5B9462BB4631D314DFB9C836C6F4D9EEC6818940C04689CC4D8D11ED9869355617861340E722B2BE78197746E2759AAA8D68D1965888E89B6B0F5BF51F94E586B2CB8708F4CDB520BF31DDCCFB7CB69E29A7AE8AAB12C11F431DE40FB9E82EB5F2B6BA1F9757F1487B63255FA69A755601C2FE17CD1892D5A6799C35D05098DC133BDD71318667D47C4671 +pk = AE58C1A3FACD6972F42739B7921602E51577B7CA885468544B000DCE43B36E972F3057959BCDFCA486590DF5A4C2F9510698E9A4507D849FC6D42D73272DD9B97EF00B993092F9450F1F6EC9D5D8AE684C5EFC7AF530EB6AEAD5597F55D5BF64F6BEB62527CF6F05E3341A74D128139C94C72A35C3198AA9C33D8A9E63BF2D5829194386C18993B64E198D6BFEBC45295BDC74E97385E51CAC8F8E8F02B1F2E49516B65805CEF76F26C035FD551F1B16A37C706FD1C010DC8BC5CF0B1160237C406A2F48D22F6F44700DD9CF1A1734F5A5BBDEABBB19076A70E04024B3B7D537EA09DC76BBE14CBA211456582EC7C445DC6AD0056562F22DB11D8A74C613294BA74C660CC8DB9E8A420DE869B1B8DC97170B2BDE5ADBD4EB4AF8396E0491D0297B00A4C40CD2CD115F46DD5CB187ABBA477BD3D40960FABCEA5E10A35B76FB4FB81171EC515368CFF791BFFEB0074610D0E30EF771AFD422054A3E9A4522F04B9D4CA2BF2EDB5F665C4C5F57934C6CFA4A1E58A0C0AF74690D7948DF0EA253C2FD76C13F6F477F56AAB939B33591F48DE4AE34951300C5636E96C0529A53D3EEBF2BB31E138838FE593E85249E4CE04141984994C3072AAA2977066DAE48A56DF20253E916754DC7D8DC47C55BB749046267BA3B019F5FED3621A9D396BA062064F4717F99DDF7DD3D268CD108713F8D7B6B2767E3A7C79789D9A3578D6F9B7D3307EB896C740D15BC9C141A00D26A008ACD7FEC3F2A40B14A0DC0307F3D49E0DBAEB8C68AB3B6CCCBD44264FE746B260E42692E964F4B9CE1779D242601F51F0D21244890DABC44AFB1261CB60C6A2E0D036B0F0D8CD6BB1D3BB23A6E56290D27B26067990508A0BDC7DDDD26F1E09FC0CE8182CA48D5C5C5F522E644D925E28989FF42255C5569A97BC7EB7F7BB24975558E295EECE2478E0F3F79B7B85E897BE98261FAA6E6A41AA77F5FBD906FB645D4FF0BE643B44369569AC356F74FF54523AC58CEA3E86368F1CB1A5154B76DC500430A7922A68B536921F8D0205029BAF74925C0FA8559DD4BF2DBD5A22CE1EA5D87C944617894CEE4B3C192255E372E678CE02E0173C1E78335712AD07C5FF03CD592CE144C4A312B3FD058B979BDB0EDB6E52F0C73D3FCEADA42249AAF3D154BA48E9DEF69C1CB40C3BDA0D073659AEE29984FD075AEBE90EE5577188C8232C865DBC32E67333F9C674460014C08CC2093374D3F92FE445999F331EC4F205CD7147542A60D4BBFBFB0251E5999B8017B9D2356697EF3E663735D4BB8CB66705C3ED8FF2EBA81BB97ECEE131E19C2D2F60154D833978809FE001296E51603E1F10FBE1593C33824ADB52A418A91E1B91BC19E90CA22C00AE42C70889EF4471F6475F04E29F1768085B2EAB8254CB31227AC64316C75C73F8707C00A09947E12600A3092DCE435FDDAE14752D02E150A67F36E758064372FFEC036EAE5C3A90F21F7A9EDAC9A1F412E9349C8824D8A4CA0AC69B1FA4D3658D28CB121CCF9EF3ED18195A18DD37164E5DDF7DD1B2F869EC9284CAD6290BB453828D0C9DF204DF2C28A57C835272A5CF140E4DD39440886544967648C7088DDFC8C9CC474C7F29B3A8E7113340227236A66018A8666DB462C9B9DC6A2AC33737BEB5022541C5049413DFF435C4B807BC2D7D3C5CB78117DE3C0E26C41B217501686D1C22C2E631F7E91D3E5FED6474DFAF8DD15CDED4DE4B6EA40577EBA46BB7EADF56D9241F292B6B43843CAC5E7600C50273DE02948A9463848A7C173D6A99CC2BAC14B0C5853BAA30D57C3C3097D344A033E33DA7103CD73105A521370A7B7A014C778F93563028B82CCA2D73661DA353B1FE465AA7F1CB313E7AE398F5D4E3FD727BF5E5AF139852F81811FAB7289E83B288D5DDE0F1FCCD06A96EDB0ED3389F6C00FE8DDB1C8912456E010D8A48C79B1045FA11F1087BF818C7334E5A8927334A5C42F147B25B5286BD012F7E1FD504E2693C997912FE8CBA493BD543C44CA93441A90BC7CF0FCA7D4BC20D1FDA52B9142FCB0FE5BE5240313FF2F517C7837E03865FED3F9B1573BFCF5363975619F10B18D0FEBE0904627D91AFC0B9FDA0808B43AA08C57355D56433C2EB9A24C1D44A5F8944B1F439E4DBA34918B13A4389834B33383F57F1BBBC72742DABA4A34C86E4C5D171D5086052C0180B03F28B30F796EC02F88744F4C2E4FCE9820278348CE97A4A382977AF26F4B08CBE0C86D9A4FA7D48FF0BC3DB4BBE8A57D3A9835F4E709DAAB2C574ACF7048A6B6E59E911382539B7B623DED33BCB5B9DDA5BFC600E1D6707A30789A994B4E2F9D952C43314D32729755C85AB8A692667F3A170B9F8E2DAAB92808C33654BB0DDAAC33AAED12ED711A246DC9B530161A0359ED53C635394185E361D3CC79E72589546E3E234D5AC71218333C9019AC1BFA8943B3E23B721E8502B2BBCE6BD0E43D591E69C6C3B2D0A1B411749614107B87E362EA5111FE407F1A0CC5F093C0234C918AAF542C02AF14B54674433CA5CF0CED016AB1E15E40064C00A681B2E0CF3C996594C046B68B01E9C0B66D65F2FB16C94009F093AEEF1A8F66EDEDEB9FA9B6B82FA8566E5B24BE2550FFC02B068440DE36E1E63F872D68C2E46048E1C9C041ED7538C9A81DC21F2B6BB59DC8E3A5F27F879053A85E706B410CE8BA4A7DC53136CB78035C4117F566D9B510BAAEF59ED6A4575EFF3BEA2FAADD62FAE6B4D97B41AA1815B2234E4E56E38ACFB57F0FEAB7BF0D103F9F4AD3 +sk = AE58C1A3FACD6972F42739B7921602E51577B7CA885468544B000DCE43B36E9700FD7ED3E099AF39BF96B0F29F32AD2141BE578C9454EF960775FDC13671049EB87E080B27B96A5DA7EE25F32BEB6A6F21169D66083E25AE0DCEC60026AE74F5E6D89F8341F145D74B5F79AF0DE2530B5C868FE0B14701E3C2FD944C7C099EE354256267644482204042662710532224667322010551587586257055430135057843868240654107284280781275066472340676876237856376846717326861713124353631584573821465720076556356651127885888515038157533243104327647560213522400334075385042365170754476121876771485864512231152226576287868175000666660624703824054555837028267011761215746213304238065716481826153033804821886401471774631075646410245441318100113361861370753110275115553468152552825680223301888453545123270506710510685357257310687480011384632042326277783523877210806561247600350402868413842160652312828713587113616610684222468284483751876521583120320505141012438374665618640362310267700075611240588013347731457147065242382476528262865762818073685352775712521232453174624682202681487276706016778558723372530753845014367561700770468055370574830245112057260713815355462706430161770835313454546606347262871125332480645072558176572454678065717572425582354272387730263617547423156344427443482824462474577231575605304632223585570404207410234227270164072223865788611028263182181637085474628230674134138470730810472267687712881725126320727278526414042688106778054037060178141886717258344750434860352201486207088821431718032637650831084233532158260808257655485686278252786272215525238128085573567548815683456873353272118506367831488880883586525645733653701371045640715844846776765277874052373344676510753257328757026861586654277265051738735423172613008425120078306544144015687710352725303240706230660732646822285325543172840515120301642108128264368834707228522186621016117335144474100481766455678664165715888833536285806654314754316128715848258617687170744652857575312704212041604841672087840738758342021828563101070816680237313763841404347446824543255580751077418660486801837085778530664101318415626005177735220365848666140185388316414410367360757583733736838601207610851104230520164758281824462275736554586772271310282502313152877374356543816153074624834132264103433065771436063287657364883560560180151711176238461332845370240645513673321136061728440221278682844637051817778104872720170053645255451164671650217311074673186474321417871362046864151800700434108451004102534584148217610125845131072187865884281543465282442701828561062020318425438310673603074476362763863851435343112714664437815718863461511157882676451455328153653150350751362052841088408424480041321135461458051515277034451463351704575354658611114220273478844202368382551280468012700406161856267113304750442313676034523226630728700868818575881511378202125526627042672855881443245626532357256717013745003011003431321657358671888837282455616148258715478280405852368807114430770778113537148048185881523013324740404326101155340174628217132336138752716850287258286164335141524146775407442472752286641503501644660381115404648186246205218606088406248313774762130212511167340551552610313528718053276068573402316151374030667EDF186DD1EFDFFF7742F5F9406BB96070357B8E39034638E2CDA403E9A590AB29A9DC584C1F4A4E751D53793BFFAF6E12372581914C87AABFF1A1B069BF4BD3154466686F82650FFFFE708CEA73AE624BFFD6ED5AE0C178B6AFC21E338A36005146EFB49BCAE1D000096F1669D6B4C528631CC68F6C4CF30D88DB0A93DAF3F10B77346D238C24341032007F37D65413F58E19097700C9747359B0EF843672E7ABD887A362823DE3700CA9D35083FA41D58C5C24EB89B9D65874D9AC537116ECC9148F3152329C6CF3F7F69A676A2DF77DC5C5A02211F1C7949F694C6B6B6DD1209FFD657D5CDC31843E23EBB31A3F0ED3D861DBB3BCEA89B7A9E8EAE610BE5AFF2EFC41E6EAF39EE5A41CFC4A211B11B6C00353EEAFE229C675517A8349023427EC52B73D5FCE6E5D4477D5EB674918848C3C45125670F3AC5018E17EF8B4F6F6FC2948674C5367639BA1737E3BD87E86CC4650F2F55C9B4CA8434633E0BAE058AB9F9442E7893198D25D1DFB9CD52D716FC501EB96C0F94D5C2E6D6DE0CEE93AAF8C2ED48AD3A1F487B19B1DE9E5365FD1218DB369D58BA1936456F448708617066AEA57D44BE5F23508B7FBD4FCEC23E8376233A888357276B83E71C3166657B56DFBF31C92FC904971B3B99943E27E0535C8B162CF2E74A2EAFDCC6E1A152B20C689C8893F4F78B683011E14363BF2E9DDB0B3E1BD389ED4217E5F9C78507FF1253F7AF7CF98BE0A3EED18E0A31114583C16EB2F3F5110AFD664AE2E81E7B311AE912153BF18FC5F40C481C1611931B3762FFEB7E9FF9FB9AD6F06C59BB9CCCD0304B14E42DFD9CF7EE4DE9846BE6988F3B78B2CF35EBAB91C631B9389B7B254694ECB0F46DDFB234025A2D43AB4A2CD26E91C3575DD145AFE5145E5C19E0297E68F3A3B8E9CA0CB2F259A45E8FA97D530A63CBF5107C92692F08DA127906C9B32E62039B09028AE879A02D9CF838C02D712D1E4987B5098EE4D2D780CC69FA6FAA9AF271F04612E11BF9C87EFD4238A32BF8BA43B4C01065807DE4564749084E2DD2B8FC44C5AA59F395AE7162FDE7DD6A0B029AAD0D60C7E3976973D5C5451DC9BB8716685806429747B1C80C68A78E2EC07AAE5A93CF33F58B011869CF45156F7FF12B870CEBC02578ACCDA9A9AB22EBDAE82B37325AEB9385193C8D30D5B4193BB847A0E73000BCABEA0D4AEEF789EC9BFF3B8B082B3DE4155A041A364C651CB5E3B70CF65A41F58B3E647B6CE067CE9451CAA1772AF915039793BE26C3264F7A569EE5A6E1F202FAE2316167383A35045FACA8DFF553BD1A2B6A8AD50B2E8673542F95F3F5A09AE66B8B444C1A2F906496B19642A3ACDF454C68B29590E62AD5359546DA8EF98D5A756A5FBBF896104EE85B31776B8C8D228CC5E8908470410364E616212119FB87AFB8E9A4F5CB32A562F1689A967C7CC807D9AD31BA85E05D985A374829BBE5000E1F271126648D84E5ECB145B41BF600C96F56CD217A471D279A68ADEB64685359B65BB9D822FE8B8A685B69BE8D7ED42CD2BF46310A3AFA510383A541793ED06AE3E4F0A974E55A6F4B95B836758050003FB850BE2A60B51BD7599A34A0BB304C3B07FFB1E84BF6570D7D8BA668C4C5E2B20BB5F28514CBCFE879C089F2EDDBF496069B6950BD0CC8A6ACB318364D8DC894D88EE7FA8523DE6C7C770B0D0B9555DFEA088A2A21EEF67684079980D39E3AF48CCFB5CEE9EC4A9B647D494E25599669F48AAC9ABCD2002E9ADBF33E5CC65DFC148CF31EE36A3B642BF65DEC0E2AF617FE98CB5D45C04EEFC10460E248D81D1AE6AE3A1665F8046DAEB37D0F81A4C7E706E17E7514DBC35CEFAB30802132B976CF174666398733AC70088006C1C1439249014B26BE09F5E1BBEB6769B0647BB1734ADF1E1DA5E4436FDDDB5ABB431BB57726047C3EFC39F370211790AF0031092253433BEA5C8ECACD4AEDDB5E547CC3AF06989472BE1A19CE98AFCC86C181DAF219551368DB0C3A8E97B32E5AA32227FDE0FF0E3B43CC5FCD715949C765F32674B901E1456D8BC7CA3316630022BAC74F32254000D8B2EB7AA581516B8563134BF14A63513BA77A2B0B11D48A8E913B7AEA08656D37CDEE766096153EB9470F69353AE81B9518DA969E66357DB96F56B47036D1FF93730960E12D72AD35211D59724700D35BD59368E798BBE19004BA95789380375EA2C9EB2CB119D1ADCD938411BADBF8E11AAECD93A72F0BD17470E6B30164302CE84FF891B5416A362009BCFDB0E2EED724B4F54193B57EDB4AF32199266AEEA90BF78121EFEF8AB144EC0196308DD0FD73DE9322A66302FE507C93FA4EA8E356A29A87D309438BADE7C1A3EC297EAB2B6FFB3460C1445593E85A297891C71589034962B0E1AACA561455E4D8945E0F9EDD7FAE46FAD30F5E847E46DBBD6CE71390B1280497EF0883800EF9671F50F506ABEE116104A1DCDCCD0C4F9BC106B1D3564CA4901206142F408CCB46A3DF93F22CE5B71DB674ABD07F14A6C7A8B7F16FFC12D2D10C7FDB2B250EA8CC43EBDB8B2C622A259CAA0ECE6529615BF550EF5FCD889E7188734DE0F9265680F8E2F462F2E108718E1F243406AC622F2BE917D296E6E1A4C7E5A03A161BE4CBF662D58C79DBAE83F891ABADB53039DB6453BF3506833BB20B077919BFF7A5F927CD1500B2DC3EC12E5FCF109764DB31F4783D414640983F7842948D97E74647732D6E91940106AD07EBDA991DDDC3C93129D84A7A67272034841780C68DA4752B488A53E6DD3C0399CBEB3CE607162D535700D23B2F20766C004FFD36D17E4BF16B8115D7913D4C64B30F06A2DB2A99586762BC35A8B6F90CB777CD55873944F712CFE77CE9D6D1A518B51379E72E5B5D703444E24FA69B6A3D0EF6F512FD02B3FB77848C31F253C772E81466D632D67538D42BFA1EA34C869A83D91B00A40CD559E85C1F02BC131586BF1757615DE45FE825F65000003D44F3412652A056A24BAB4C6487D6EA73B5D27E227825FF84402C968E8AD86F06230AC2B6483184CEAD2306139E44C127A202C5871786AB051C207A8A03C5A6751BB39120ABD5A96956DA7BB61EE9F8AC87DED06F2875F12D72FFE61D40C7BBB5FB23418576D7A0B27794DF160E6DC8A37E2D8340D3C1B84A920A59267C175E94FD63C74A9865C73AE6F082EB730729F3622951165A34BA730B09CEC446242EACBA3B4A62ACC3899C7CBDABBBC748C163A29BBC1ED0021FCFAEAD680904F5F3A018C92D8FAFB98D6604D5AD454A6B8AD094E6318B082EAFB0264CCE595752C1D49A442DA5886D4A279D3DA5DD7D18B8993DC677578B7E8A52CC264B6DC66FE39C972C6315D7080E08570F1E02B0623E611A411098C91E37406FEA220993F0CEA9201A2CFE492733BBF47CD02D7C48A7157562078B25261F60E96753FA132E7C37F11D9F06DCA513BB232DCA7D75DAB9320517B9D8A87FA608F74445793FC053C21572B8D280873166927ADAA03D5C4F5DAB47B74388ABC7098DCD585E2842CF4FC19CCD966A5D75B5 +smlen = 5586 +sm = 7DEC3C26A90FEB9899719C1B8F3933C6327582C8B88A6A4D0D2B561ADF5F55179D8F0CD198CCE7677A3319CEAF8C68C95AFE709A61760743FB6D9E47C6A5C76F4C5B6BF404AD6EC7F069B211436CE6B847ECFDF26C7449949B5C870060617432B8F0056A24488785D4489202CFFC2CDB1B1D97602BD868F8A3A8B2AB07DEE734BF657A18AD92254F73C05CCC1E3C47BEB0279B652F03C144999F4A6C71A11D7DDDC647E2F1900ACA9CF9DC6156C0791AB487D22554C0633A99CD6989DCF53D1D7A66C05921CDDA893F833ABBAA998743EF3852C692C67D55EFEE4BCB9EB145E56F09988FA942BA1AF75353E29EE6751240036E6E47CC390A55EE0D80345CEF76B0D54296B416E262AEA175275A959612AA2BEEE9DC71124051139E6F62D0BE3077404CBF99B5EC5D73C87D5F35B8300891FDA886B3664DA08E547C3601A1C56E129116D6FA3FC11DA3F3636AC00029DDFE26768FDA9746ACEDB5284E1933FBA8735B98BF524C3A9EFE9BABAE7FF7F8A70AF8D310B5A16263EDDE6B2C68494E9909036EBBD65BD4161383434392AFB46611B62FE9196283AF719E53464CB90AB91CAD11895A8F8721CA8CFB1640CC4706962F8EF934FA670A2DFDB5706883179EBFB3D6DFEDBF192BB0981647A4E09665BEC35C84857BF2CA44090F4005DF85A5D02D8D3FC7F8C3CBB32C0B2EDD4753039B6ADDF6A946CE6D8CCAAD02F3EDD1F632DD5AEAD70FFAEA5BD1CD3B3D0F9C236CD7F4B9592B747599B7F7B38427659ACD8D98F37CEFE2022BF7D00564364D37D674DCC777D0081184DF87F2A315BAE5FE8272CFF464FBDCAFBA1245FFE14FC2C43102F31BF752C966E78AF815E4E3AC3D554EF4AA975A9E6994A2E241E4D8F9D4AE0B935060A371A802C28D7A362C5D532E93699874CE056871A0C75067DAE4448D101AE753BB5CD50017B1720478549E414C9D0ED2DF076473DF211333EE055BF0323D885219940E99907C2DA00B9531CC3D32DF531641F4B14228AB3049D13D3B47DBC4CF75EC5F68D6FA8EBF23E27680B9CA73881823833963CDB2BDD42859A047E333E693FAFC49018A0931A991CA1017DFA3B38D5D3895A64DC2FBB8D3C701891B8F550AC38461A1735C9E8699AB16A87C852CB7F7D05CF29A509E5BC01BB8B486CD603A829EAD8D543E6E89D6E12D3B243BE0678112D80BB3A7D17BDF74CA8FD507D9CF3614998DED000C82E566062A8D6A897DB1233B0B0FB7C5E59DD2414771249DB1A2E8B025E19800DB486566CBB114B73CAE2C362B8320AAC02DACD3CFB4F8059853325EB1B9C6DAC388A70EF0ADE64E4F35F65EA784AC817D3481FA175C2314ABFAD814C2A34807678C4D05FF97B1DDCCB8EE29C18E1E1634931E8179C20DB388BF629A5AA528ED687876A75566C6A0F92461DB9CC876F0D4E0EABA8B976CC101C5F4A8B760EB5CADD4807FB49959125755222FB75EE69F1FFA52F7799C7DAB239ED6F50F3A5748E97A4E08CA0D7490DB225BA2156C7096CE2C37B16C8ABFBE5AD276BC9C93442869ADAF3D46FA7D30ABB6D9C8456708A64F038310A99064F1A82807EB2959C5FB46487E39CF45BFE9BCA0A182AD0C17BD8F51854F3FF14A31052E037F4F708379EA7A9E722EC987DE65B6CADC06F4BADD01E474CD943C6C97CD574B842CBFE735979C93296781A30EFFBC3F6B42722B138DB73DAB2C27DAB683DE4EA536AB46507A1ADC4664C89BE307E24BAF5669DC8A4CA2ACCDCD2AC39B04E8918D6339A737CCDB363FB222E22280AB66FDD49E3582121DC32C6490848392F8D28DC0FAE71F2D3AAA71DA742831056CE56D46B84F9E93224B6AE83127CC68CEA05587163BFC70194969CD8F93715BDDD38BCE9E994D3FC810CCFDDF05FEE3921AC955E8D50A3ECE99D7B1DC863603AE8A35C2F6B25691C108FE3C684BA28D3F19A9BF0934308419C33A67327CEA8FB5B3B679EC6C965A53036BA5C65FBD2EE3542E66EB70432067D42765FDDE7220C5A467765C205EA97124D83B78522385BFDBCB0D1D86F9A065BAAF625D2F4F63DAC1F4191C8CBFD5E1B73A87835942CDBB340C66FADC41151FB51EB0015B4EF1B38856D11530B3D3101413AD4EAA18F1202F2CA4CA43A9C830E913FA1940DED453A70014A5600C5492E73FA84B91F2195EB5BDC347E666D981B68E3F703A135AF5D8623EFE76515C3CDE897994B52DBD0F6FFA7FAC9689475E797919CFD5649D13CD8621135F8BA11E9ECA50087425059DC893568A6954EE3B141FF059B08D101BDAC906E93560D63982A0D37F4533BF8A05B0D18179D01ACABF5C4C90AEEE8A6A51819771163545AF667A7359F1008BDEE99C9649117B2CDEC816B0E00D89136E20ADA34440246153037ECF4907125DA36446FAA45F685FAF7A78AEFB361E298DEE5EFA3F1A1D172295FC8C595334B9DC3791CB7BFDDEE5EDCD9EACF96B9D54A19261F616CD50F71FADA9E98C977CB9383942C32542C22785312516DD62B821C41BD12F12047889932F77318C2F11CA9AE9EA220DDC86ECAA094AF47FBD979B4C3CD0FBFD2E237A1C6EDBDA08D0B8D66EB7792C87E4DE9A231CB70B07CDA1A83324DB4D4A5ECB60C46BB35F3E8CAF0B52556A0C354FED768790A22D8873A5BC321F979E5F6BE5E8321635E026947551FA32271F30EA39D22B71BB560F2777ECCD9056A3D78C29825FA8D4D6FB9C3ABE38AA3477154555DA09F153526AE6ED086DBB57D01DF4D2C081864E40E5FAED02D989F9355815E7434AFB304E4A089E7F6E80512F02D99210BE8A11A93BE290B0A14D8263C0C0A0B57A2C1668D65FD02304BDE0A1A2D028102A45B384EDE2CD49D24993F9B4FD23E280E990DE7A68095E1F3A049705D251261C5193EBDC75936288723DAECBF07EC16C3C9841308DF08F106362C070D853844B7C5058BBE7DB6D6C6DFD590ED92DB1C8DE1FB8873D0B30EB0A9532FFC9525143365C34FBE4D971F8FD66709EF98D317D78B61D9E00AC30A49DA502F8D0B95CEB5C3B4CFE0470D4C6F48429819E0A9AB75C64C3512CC975B649EA949582269D3C6199AE99A32CA2633618C2D0D493E7B974540A24222ED41312E08AD9FA535C2D9F3E12BB80E75CF2047A418AAF6EF688D475AAAFCED75C63D5F81529CB3C5808EBD99DD90D0E0ED9A0A3B66D36A6C1CDE0E4F527522D80A3D6D141AAC0991B2BD4AB39B7DA9A0FF1EE451F9A71BF0C294C25100438B98D729D43B01B7230248C2C35D6C1FEE82556EF9326D95FF1B3DD523590A3D42A74046DEF4D06109B28D7419FB25A201ED6AB27A5B85F5CBFD7F6D50F501E6EFD2799BEF0C9D6CAFC413D581F88C72C3A06314354A21E757A97BC968AB26652695D5F3C05E7BF90C242882DD04C432FEB27D8A0C915FDE2CC3353B13307F78436788C2759A44E0EB29FBDC4070B5775D8D5296BBCE246A79F643F2DA8B07CD74E04644698608CBE703E915BADA96A8EE6485BF23B278B112C6D9E6F0CA3BD171A80F0A14C029F1A14D02150DACBA2AEA560BB3D393D218BA8B9AB4CDC41F91F18DB124BF5B13178ECEC2A8EF117562CD3ABCA0E0DAFDE3BA0294C98ABC17F51C5AE87CD5B56033854D7C528F5C5315B6E0433FAD1B210B668FB9CBB33DC6A70CA8473B3FCC94CF0C91180C8E1E7D5EF377B506484AE96047C29478965967C5541D1786854EE611F664E58EA2AB0C3EDAC2CC250CCFA2496E00B5798146D1BBA8E1EDE1DA4ABC1BDA1CBE9FBCCC197C3895836E1BFB6B4D7E33C516B6DDC00CF0625F2D246359A0BE39CE91A8D17CD07525D1EA44CC869FD0D9BD5D292E3851E48A45B880AE36F52659E29D32DF324E759D753173FBEAC29B4FAD571C5ECC1EA9FCD064C8B115818A7D15C04ADDB1CC10B49CABE148BF1423163305EF06B5DDB5CFD631F90059E14607CFD345138ED389887A02CC5805762C21983297DD268D0FE8DE74FB658E1F1B42F7A8629F34F6ADC7A74D0EF18E5CAECA1C2062EDF7577461FE144865E91B583C56277B88B35936D5D31D25CEA3C639CB3290E8FEDBBDC033E322E8186310E71479075FD2E9BD58CA0F77CCF974C0B2459B980F05572AC0F7D2E25058348691757C5CE28A4379EB0DDDD1139EB60E430B2CA7A97651F2B1BB692E9ECB98F26F0201C622CB2A2166153A23D9ADFCDEA05099BA137FB07247E0D175C3EABCBFB334DD6BB793BB1B3E1FE03BA637772F37CABAD82EADC7000C6A896145005C5D4B7C20A50C298AA89F0BCD28D204C4448923E8A69798FE3573943E5C8289DF8DEFF34BBD1536C2F0EEA76820353662C056ACEC7D1468A6625468160E3E60046D23F6CB211FBD2E9C9FA83B0F3E250C813AEC91695DEE6D15F5E97FE209F61C7410D0E1DC067F1E0255AE8AC1AF6FCBEBAE48147DAFE076D6491F0B0A0B907416E9BBC9B91ADC5128104B3E3E273147A2CD9E8EDF142071BAAE5D17769B3601081F1E571B0D323484A5FAFF38996396EDDADB566C0F643EC324423220ADCBBD59481F54DD07673BC3884781A2CA1F149BE0DD56963077C26AFD4C6D7B630E83B04F1110B5919F77A547BFE1640F57C3E87AA856393BB4242EAD2FD4869533AB04CA177830244B5386FFD0414243C50515D7285E55F62678489B8F2C6D3FC071823292E464D5CA2C6D7E80000000000000000000000000000000000030610171A268337940EE74590EB25E52E78E8563A09CD2D45F650F48775E3E61F9E3509CC8EB7E983310D0185359F66BD80E0DA1E45A6BEB53ACEBB9030E310E81A576D0F80C64FCE1D1FD77DCA27B7C6E02B0CC26EDBF496AD2E3CE8484E988E56BB28153587D7ECB02FD8882545E7BF79CC9966A7FEDE93F7E9451BC48FDBB481673D1C4135F95D68F40F4B4F847345A320FB4D736BF5F9FD347435462DD3A238E4C799E7CEE081107E11682C7B558B19177522427F1D269FAD81B565BE538E8FF2D7193579AEE51E50974BDC0B66331B59BF496C87E4F6E143754076DB516C9C538410FB38A930CB5BA1E6610441126D01C8EB5F34E2E58424B8B218D9E68C5D8B4F5258EEF07EE0AA5475A72CCF363D47D825FA524C16C7B7587C44864DA9E4B267F738B87F7E5701147F550CD38774B17DE48E6969A0DEDF334FA67470419059C4D1607880CB12FA9C0ED23032C7E0F325169EACE7DACCDD4C2E5097FBBA859970D7EAC4522C1FEA043C9278C1C89FCCE95203033B4CEA4F9F24B55BA6B79EF88F275310C6E48189EFC1EEEDAB66B56B6BB028726BC463D93D742492841E85D5C837948978D0FADD1C172F8859C802C6BE8394A05DADA7546EE1CC5BB909D3189088F4FA6D07C573ED7263C081720E701D5D4B027AE54BE175536F3BD5E91993CC040311A7D352AA26414CAE30D10408DDB44E8C9513F4619E99EDC894F963489876B24BB0B91BDC3EE5B78AC0D4046B2E864789C0C779E5AF97F8F84F09A26FF74B8BCDE66C007970830B70C2A1122DC9845905C3AA7810B40641E8BBB398A23BBEF52BEDABEC7BB54823E64177A73786992DD67D5C007D770938402EFBCB3A60281C5706920A9EEE4C26C0B251C32B9E1936FDEC2928110959E99255508250FD5BA84B4FB314187124072D30FBF2163D36F1480ECC08F7FB8093BFAA72F1914C63533EBB3A57420DC38DC93DD6AE4D197FAB790C1EFC1B7A2234522E0B408D0648C7AE782F2F08CB70B96CD76B5089AF1EF4BA3A4C2FAAC363A4DC1C6C421F6AE1E9B67461EB02F36C25E763F1A2B73CEED4DCEDDCE619CB313D124CE6F7AC986D6BC344E630F22CB654C1286FBC0EE01C968DADD1EDAD744C8BC828CF5F316336A5883166ED000FF98D6CE2CEAE7D3E40BBC5714F71BA9E25E1506D644FB2DE2FE190D327ACCCA79D9B6D9DB505CF1853E98F30E9BA5E568ED83E2567C936A64420C5D8F07AC4F65F38C28E88DD7B5209A600AEB81A6D2AFA4FAAEFDAFD9B7FD3AD7F49462CD577204184F9D44A45E2A909373CED24EC0EE56BF2E6675C506EDA67B1E6DAB75CBF1822E20E7A8A81A7729B42A6D67A1DD457FCD19B62F048AB97B3D694254E5C051FD2DAF3D12AD627EC37C22117BDEE9EAA290D11D56BAFF0DE1037EBA908FA03E2F869FA2B27936669306E8E70A0A4910A123F202797BF1C8FE47178BB1E8E8D7AB1C01F30F5E779B2BC99902DF15185FED4C865997AB72254162D00858E0908EA95A9ACD0FCE72E571C7A381CC33E06A27FE6A5922775EE82C973CC3CA8A05717608F8703946C9A89854D627744DA475DEFC1390DC44FCC3A23C47AA8AF17240EB1A1A00A062D258D471F31333D0356243DC1CECFC559378B4395F01A970EA4074D5666B44D49EF291ED15930DADA66765B165CB8331CFE549C38CD0672F534BE60F4D9B4C125FFE747670513B5744676899B256B992E15106B99B794DB3950582816612144649210751F3D0DFD5B25CD393E724F7FDEF00756D0C8540E8891E592507599B06EDFA6EBFE543084AC81858F5EB02D8F5EB8A72184851E8589A3AC6DFE1CDCF286723FC4C1202765FA4F783EE58C627ED494C7149BCA6A4DDB420827CDCA82DC42515BEAF46CE9D9ED524BD00EBD3094F770B1E1DD09FC431E4C244D2305619DAE208E65EF385EA92F5A79F12B99AFDAEA79C9D8D319944AC6CBBE3F1290EC6B87D97785E059E6871FDF239BC404021CB52064B88EB4CB3FB6A871B0F76C12D7B8C5E8FE0A65024AB5B25F4C67B6D15C22B0005B754CF7CBEC898B49F4326F1AE4034E5F5A446A96CE08083D48525A3661E10C996DD22DC34FE570A4C8817D10D750FC5C2ED0C24C7CBCBA5CD1B2680DBAA3315FBF2BA7457ABEEDC96B5D111110D4678EA5C7851D25F258926B0B028365799E940A6E17BB03CB332FBC6D713DEA7108FC6268C8D33E7A578C94FF75BE808C15FF7884F092C0E309F1AF99B1A7314FA0F32C8D8E32B3E9D92C9C8FF6B8FBB99111529C4BE3A2A4F62884373D0903180B4DEABE613DE5CF19415DFBA7F9A46297AE2F21D7EA420B41F628FD8DEBA55207606539D11791623CB325F1E18C98AAC27283BFAB2408F4FD6CC58EC9E306643BA1C0C77D84B3930263E5A76A1CE94F3D7721F0098D54E6C990C3AFF69B6A0D82C853EA2AF2D3D2B3E96DAD59FF873171B55D16CA9A7C68DAD2E918174D264919DDCB4B9D01CE622D56C599BF60711C74315C918A7BB97B9513937AFB6A652DA68B6B0B34E316D7BE9F5C282A5E8773C892782EFF220667A6A54069C37B88EB1CE676AAECF2015E59FB7AF4D30C4625DD8DE4805F505E83C877CD61D2A0BA65B32B0DBDFBACFC88CA43E4DDF7A1A4517DCE83B7B8ACF8DCAAD28284039747935865DAF8DCFCA29FB676CE2EBA2C509CD75588FA5E58CEFD0694626C9BB31C3AFC372ED313C9BB3ADC398E89DBDB108DDA63F9380EBF9DA17B378451634682F9823E209BF10E39F884ED270413152025CDBF4875C121B1E83E12C044453FFDA6D8CA2C240AD522577C6898AB6F2ABE1FE77F860939408CD193E605F87FF2248FA163AC2FC0F39BFC38503B23F5441E0E364CAAAB890073266B3B51217661F5DF41C0BA925BB425AB3DD7B6A3675B7D60D0290131EAD53A4EAB0C66BAA83F2FB77E74C3C123ABA7731A3F62FAB8EAB2A96E8BBC911E501CD23A088E7887A469284E0B5C27B5CBC1DE2B6938CF1AF58A47FE78141306CB76E8F2B73620BC4549DB6826D2D72873885F6C5311EB5B9462BB4631D314DFB9C836C6F4D9EEC6818940C04689CC4D8D11ED9869355617861340E722B2BE78197746E2759AAA8D68D1965888E89B6B0F5BF51F94E586B2CB8708F4CDB520BF31DDCCFB7CB69E29A7AE8AAB12C11F431DE40FB9E82EB5F2B6BA1F9757F1487B63255FA69A755601C2FE17CD1892D5A6799C35D05098DC133BDD71318667D47C4671 + +count = 69 +seed = 272E459EAB6A0BDF720E4C5B79E641C95BAB66C3CEE261D0E3596BB04D232ACE0A1CE24BACCAAE9037665A962C711B08 +mlen = 2310 +msg = 62215248E1F3AFB19849F758D742F8AFAB595040C4DC520D603C9A80FA9CF2E97E4F4BD7350551FB667D606BDC31A45D88836CD376785C01F9007D47DF95C1F4D1E30A927A13525409D91C9F5145C0B86D3B44E933CA81E4ED9559AC17940C61EB85B2D26D2C47924AB80ACBAA3D9B1C8855C13EE45F5C8047C161AAA5321839A01783B21A5EE90CF91B8285C4779465B7A89DE3D74D482080F68EB2D8B47429D5475356C50A92B3ACBDEA5786F4D6C2A304AB500490F84FD1D0F21ACBEA325D62D2657F3889B6F591A7F63D8633C061CB14B8266A7FE17642DEDF1D08D9FFE369126CD780D9F99FC6262B5BEFCFEF35D33498CB2CFFE55F2F8D567EA8687DFC6E7D49A61FDBFE768C1D11BF5B3B18CA52225B096490C97CB9A0B3B2CA0762DCC36B60F7D26FCAA4E38B1F3A6279D889323010D9CB0A97FC488E09B06237E6EB0166465C2CBC2B9CD06F155759B6C93CA0CD3178845E0F3A2D20A68757AAF3C4E74545494462CCF28F6F51EC0FDFF4F1E6D98FC5B63BFF068FA7BE1764BCF14497E71E424C9389C5DCF8C5CE1DCD40B82F1D75C3C3970DA433A92A04DE958766AC5EB3645F4D21882F7071383AF8DFFD6CDD91B549F143DCF59FED6674441EEB03D5013E90ADCCBD7E3DA115535AC855DBAAB7F51D70630DC00009E726A16DEADB12047D85906CFF315C73EE7D4E24C9067E3B772F3DCC44C25C7CB8622FDD7B8ECF5E9C877838D71D500F864A662619B1478F8AB4DB2DD09A111ACC99ABE737DDBCA06E88926C4E73B5F5D21EAFC4B11938FEEEA5F8D5A4C616A342B54C9CE371817AA2409A55A3237BE85A50F05B33D35AA86A62E85A01CF34EE7DC840A26FA1B8C6B307817C062D9A2E7163A3B036874D2ABF6531A772D4031FDCD59CA79FBF442CB9155F90148DC3B723778E699C6985634185C3FFDB966ADB80A3D1308150B12964142498466506BC0742783C27BD3472A5CB45021DE066C28143FFBC82B5742BE51E93BCFDE1A61E661B730D8760E108B80C859E4B3A07D483A6A8967E5F01B03EC8B63A20C6A03755C75F419558878A5EB8BB0B2120F183E4BECD4A104EB4DB62CACF5F9964583815334A25BDB75724E549211699AC3BC9B2B5F58F1FB33429905DF81C9422F8B84E95A7C36DEC6AE9B48D4F502D8AB59B69E9D112693578D143A3F111EF00844303950F65DDEEA6E30F1286DE16546F90C4364A5C09755AF3FECB13983C418B2FE4AC17BDDA57E4D597E8BDCCBFBE4082C446FC920E5145BBAFC67FADD9799CD8C7714510DA579516ED39B3E22DE319977FC77A9CA61AE8252795D11724AAA866C1FFDBCBC1FF91AF1B8713248864A4E8B9C59DD12863245F5048110DEDE7FE31FF9836715886C37E9642DBD6C668BA7AB8C2B706CDD58586EB7227B5768C3509C1F66493468859E275700EA38BA69064179F6036D7B50BD232B61C9B9659492894C0057DBFB80329A76CDC57B2A89BBB910483301CA0BF6AEC7D5DDF86644FF52F48FF6C7CD00406CACBC09AA251708BAF3276A52BE2C7B42FB6A9036C318529CA98940769A67DCD532C0000AFB5FC63AD2303E94E09D2CB40CCBE47FAA1DD22ECF528179AD40FD4BFD43717864149243D61CA255344C52743200ED8385A7CA6CCA24CF967D23D07DC2A3F9AD5F3240F4F022A6C6CD281B6C492E8D144A2F4641957ECC65B32C9F74BB468524FF58F0F3DA2F5A56742896CC8F99088574264F857DC67CF04C4B63C6A08FC534229CA8BA616CD504F969EA6E3C98A517355F98A9E884062805B77623239074206E01AD2F3FC9FE9FF8254A5D3525C3B2F0A692803500C967A2E18511EF5B8845DC4B0DEE9338C38C4B1B8B84EE63923250EB6F9E9C272617C7895BD538A6F34D3557812BBBFAB2B8FA6EB5E95B9BCE33AD3185CD90DD536A68639022C079B5CA7748864D37D45FA6780A45AA991F28BC0D3BF371EE2FF0C913CEA6DB38E4A278A4840EA1F255F8E83B6B6C5E260A49D727AA42095A88CB8120B51DAFD764E690102F7FA07CEA2EB86AC613E7BE2F498F5767B622D04E8A6F272976FB058C3334CF8CAAD1D180E3456C210763C974E431CBC3E25EAD8B9FF9243628D5B08D92CBF1D5DF29A85B1A04D2999B3C669227B33610121D543CF4A978F8D9365C0FF8AFFA92B07FC8C8604A0F357F3C669445685B6A29898301A5AFBE10ACE8D64A47009C8741D7CE82E9900643900A3B92A26FE5F24886C06AE0918C3F2523C320699C799CBF72F0DDB08A0F1F63D6DC2F021C78A9D44503209190EE4BE654663679CFD292292D71FC4BA6233A196EF9E95CB965852773404B2622B565BD91FCA6747AAF7F4EADED7BD3BB53645381B687AE04B8D8A9BEF1095EEB39A0BEB4EA89BADB4655A1AFC7EECB7DA0D670C192297CCE0B31BBEFEBFE94C84603BA8C0B7CC73159FF59C01A037CF2C866DC40D88432CD6C2F1989351A4E41343CACF7BF2C2B395C863709D6EC1DBAB2AF514CC771DF14DF095DEA8284BE2B65097D8E6F72EF3936595384AFC0026956E819F1657C901B92644E9D6D32D0D95549729B2CB3D5EFAC9C42A5F284ABC3BF5CCA5B08161B09D9A48FFB2996C3D4383D65B8D1F7FC3248CBE84B9C05464F4A76EFA005FEC342EDD56959CD26CB0DAE1B61B0493A4B68EB3D6335BBC280508F09D84E0C5F4EF520D92CD34D69E5BAB76DF5D2B72CB41A298D370EBEEFCD6C1904B956458BDA581EFA6B3654BE402AC3A971603F23F2B543C5BEEDA5F018543B72C146CF04680BCEA31B4A238460329E2BC12F14C804FDA3494C15452223D2477C9C8A497D04EAAE7DE09D7D7A879D3A5DBA565AE1A38F15E69C18838C487C0FBAD44A068C42EFB7D3F5EF488F91C42F25AC564751F0EFE0ECE7D98BB1B3D0FC42C9756F4B8F9DAF1FD0D414391155285C8DAEAAF380BD07E43570F14E9A47A87BC733F1E676233F17BFB71AAE464AED68487392D339AE064AE27BD57F8695F493AE56CA96C0615BDA8DA37133DD13C2B21DA189A7329773FD8D51381BC118645440B28FA4F402EF84C4091D3A0BC4D206BDCF9007F5DE9AA1E6CF7F6058AC6B69FBC703E908C4221F9065147766E48F54BE4B076406E2F9ED19C1BE982E636FD02DC26267C3ED989E6AD1CCE62E7B988FA7C1831E5126111A4C3C29C38A1F96CCB3A04132175FA46F73C634AC6EC741B135645ABF1DCEA18571CF9A539F5CC935BC6D32BEB1C7B8B3B5A141146EBC12DBBCC17BB4900CF0B95EBFAA52190AFC6D8933CAFC9 +pk = AAADE0BF29948EAEEBDB3A9B5BC962A7729A4026E79929A457D5488D40985B296559845DB0AC8923CE3FA09DFBDF609B591568EBDBEE4921A39CED0F8B452260B019F1DEF389B7DE96146DF283938C0257050E6C5559DD3B6FB009FCC90AB8EA09550A1863F79B2F2662845FDEE0FF3C726C84517CC9318465C846A3532B0945686A6D685329A0752899F209AB14EA539D210AE374CCDB2553953DA7AD335C0D77BA9AFA0C46BDF8E642E081E875ED860C398351A8C00E2D53DE2E0CF43C45BEA461663687997D6D4DD99B4E465220D2B3D5DA3057659A0DBFFE1CBC0388F7F931B23FF8321CCD99ED681117F23D8569D35B72A0FB09BBD9AFCC211F29A3C8DFB4CA29D7AC3942F4B870EDB7B26E0C2CE6B71E740C1A1F4E9F740D2CD6ADF2BBBA573F42858ECA8584736008A26779D5A898433F419B5D09BA94FB1DC2950C56C4A10B862875EE631166AA001DC3E89C0455981E7077AA4EF9A80F24027DC5047612A1291D58FCD5CF6FD468447AC215B368E0BBD6881BF483F82084274F95DBC861AC72EA28C125D8B52E23AB821E7655754E37764E954FBA8D55BBAD57748645D89F434C4B2A37274702080441364E3B3B170458407E7D2C6287F6BFC025BEE186FA96942D072111A75536C9BF91BE92430A8D5A49E1E549B1946268EE1CB992CA314A04D14D1FDC7CD5A51FC89427A9F891EDF68B35A2B83D50484E53193FA94C105BE0611307C44324B5BC1BA5F3B06C1A03EC91264E1477DFF17D5BF88852FD486F2CB9978913F3A615EA642F58595A56DECBE1F46BA83F5BBC4ECEB03B5944D330F6F80B6AC3A7C40DCFBC089505233AE97CFF048F65F1AAEA4B62852AD490DBAEF330E751860D87CFF2535579CCC75E4B956251DD83083FF213CF9F3C5BFEF15BFA24C569B65EF3546C7799DB5EEE32E943F936548F42415643665EFB59E4A7DC01DC38ED5952B28FE616E657F557B9C2B97E2C0E347793F7F6AD26BE62AD9B48CA845DF5232A173E02DEE7186F6EDBC943EB1F7F3567A722AB20AD3A424EA0021E2137432199115F8934A63EBD354D8590D39C1F655A488CE422DB0FED9E93ADF9C8698230DEE9A7EA3CF91BA950BD5DB25240B9B5C7C2D870B58A053DA0AD3002B667759954140DC21876798D30B57014879B8760160B66C04697E2981AC7958F9BBB3EC12464D8C2AE32317E469BBA7AB71EFCB697A2E2829967DE1990AABC3C53732CB273D195866392D4E030DA08089CBE480F03BF722BCC18C9AAF714F62EB5E35034B236FFE63649DDAA7BC009BEE7FA31BBCA3EB23B2A1663D1FFD27D9CC35B6B9E34161442F15A64DB23AE5C38BEE38429144B5C889270210091FEDE86E4D770E771C34349BE37412F2F1C48791768DE6AFD12DA52870B122A7C7011AB195E023608D86C4AE391ED719A89E54A66CB8F9DF38FBA1B4A7830EBD4A1CCCF8FEED9AB19E1F2ED5FD7C3C28B0CFCEB4D4BFEB90B84150AE8744381868ED79EAD6364681E6A00233D03FDF6249EBA314AE28F8A9E24559E904B077732DB605A4130ED014047D092A5FC8C77D053917AD328AB84F432608F00B5E000D5D9C99B8A1BB71513B75D1599BC6C5EB897CBC0927343AF7F42AEF67E1DADC0F27C116B0996C25E0DE39A4E8E78DD59EA792B8649043BD284E9EEECB1F6309E2E5898424164F04F7AB4AC4EF1DCB03B7B411F4DF5E82497B1DE8EA9CE2AC65A02380406EEC211782513722AE62AB938EE52D0C34667AF8814E24FE39D2CCDFF9CC8220530DCFF639994CD4F421C6A9242C24AAE1E90CD9170FC24A720E374595CB996C04995F0782E1FD1077CC96B035F0346AA1E84ED9D24FA82F55613C9644692B45F03163374A286A73438DC6A64F8A62933FF790D48172034A42B0CF02C716DA4823A2DB7D4682476156CDCAEF32C3F32085F777A0721ABB79356ADABF7545D299B8726C366AE8E2224BAC4E47AB79F3759B522F3548E3A264C1C1166CC6B4A6F7ACF0065FBAA5C8B3ED28C6C0CA33E6BE99186BC95DBB44044CF22E5BC55C1850A9DD8468457D7795E1E411019B96831BF17DD0ABCB5C065CD6DBB68038EBDDD92C2B752F49B1CBAE69D0D2FF464DE2E05CC7AB1E4DEBBF738052A915A50DD5C1E8E6BDFC1E7A061BBB5082B556AE9D7C062A016B0143282292AA762A70437BCE579C65BB938E81F0093FED6212BD3414F4BAD889081CD147DCEA2120246EC6F257C3C95CD14B61083E8C90BA57E40A4C54B23B66FF1F5364862F2BD5464EA19E2122B08CDBA594E91FFF540E874016F2ED74B24657AA6125B0EB6468AE7E30A83FFEE409F75402C40B8237051DDAE88E3227F76B324F284B9656147E91EA62D9B1AF1C62BAEE586288CEB2E83AD0F4A72987B5A35E09917180CBC4936B43ED609DD4792710C367789002A64ECF0EB732A41C74AF62A380B09AAB96952A683A738E7E2ED916242168DCC5B5CC159D56F6AB6CF1E80BF736B457C101951EF0F6FDF06C474A2EFC64C3DE49D18E658A7FF391CB9E642CF67C0696BCA22E4FAD99268721256BC0C7088F8A1BDC57934A18D67383804A031210FC506177FFBC0B124E4C1FB50C95751407048B5B23AF29872C225F39D0F61AC9858738EE7BACB47A28E43ECFD34BA9942C17D884C19336E7C18519D6D5A3C42D400766373560A4AE41D495EA6B5F757AE02952716FFC0C507D9BFC258844AA96C7BD3A4A64EE50DC4B143E685346E77C1A7833DD46F5A0A44096C1BBF954B53597C74752D +sk = AAADE0BF29948EAEEBDB3A9B5BC962A7729A4026E79929A457D5488D40985B29BFA99E6C04686E68302FF2DCD426F58FA0BF0B39B28EA3C4C441B379C4A473D40AA6FBC1A2EF1BBDA94C1B48D7E04B9B6224270AAFB48E701485F3E689586A4F088F593BDC9919C40AF14B0820D614151390790027E3421DAFEFBEE2AE6FCE7B740711230275006444412317274080471480840006211520561816221803262657487140275278547122415724601331227062655522334231626050747183050510881246388607874316412645631006058063222255872557736353333415480057754115026316578676433827575048322285524107727781451836450083004633126186223288330405330725735476656022174720358325823718204853103865868287165385708828578483548880447668004382366072573588220546081312572310526570137258102237468556451180187181530471455808424585513660544584144002151016532723214686843464522107365842551004433408863606685052258245434657320571317414802434528327708728502055121040317203400412724811666653573082634130516656577344150042187213204261114406567372144634806654356007882633218553221301827375110116371181046361156824704074820381375523354718601036635817850524520223762623530536815704645411164536013276877431507337767275035645751846874347873004208348740340416044655815015862645521867065636608151223784765546520240864018116200102002605587540430440305813273723261478352766766404557007467757024412861156680665122837853054316372710118545544808212273621780132321572161663428743650340003812715860467035856076482312660234137520505414446455780441714140426208278748216274884218051014482631621476078265146044131613228836252164614010111582655613611357741854436080238085435217231510254405607701230477272631066816381237174615373338107611031578022807270751306131682478804326085502144528524880381345041810676280461614154302151501756162483424015573612834350120113727263148162323635074340207171368178284171336430524826363864134871540864601385270531386527426623467415476485578656033641371448430335031047755612555603626668404175553634282814558308422701221640482876467183372738204614814082577431121152646406512860655536276087805143351702026852830022653022820718035346584823861702417730052687804422515247732547511311627775043107388472053284852085150107540130853304677417044861688337235287586353322643775608036206272157100747141800108563644511830737318233541640645874563883170021662674211348848132187407212653614011627857230442770375285078841767585612530035020171346322335712303012081876316116754300300531556757043847661518677452300803626287267158381176030161800643805815075802820513402571666720610157381368134087505271645066864765361415266258026418056514260616041805383650246726035342846074472247384502342743703706605607366446213467016068261488745255677162574420560704783613404644664125055708288172120858736325046772205271210328036002417337067483001315144343142114314403641477713476620406278536387206670375675323074576657148381663628835545426050817804817365732657065455013286755226134635425623576155808611318813457463531407153778003765886442081873222866325137241503303617647576801711012137065074236742660021616531270483817318247622852875368456334805283241360832263582372481114111505818834426130748506806653802118247015771278324A2F496F74D29AC833973B75FDD5E12486C5BB241E4AFF2C537030BB289283896457BB2EC7B485D873069F3E2EA641E47A2B0315BBF8BA35C531216060DBD95BAEAA1F8D924B0F1E8A58E55B9A84AB3AA3D2F26FD9F9BE9B9FA77762C08BF956773A11D659A48E1F13CF04374A8F729196532179EF913CB00053D5560FA17CD0D1E3CA8AC85D2CB02115B2C9038ECB2AEB75E256A10727D123384F53897966FEE6CF4857A6261AC70C240DE517408B4EFFFE9D01F65321E43DB24DC212CDBA468D375F6D2137E9540C84B871576991BE3F27AB05060DEBD28D0DDAAE708D0370E1EAF5C75A4A635DB33641EA18C995FFA60CFD2E2CD2D5C2D4E25AE831C5162178661240249DEC5418FFDF851139A68BB872F5B1885EDE9BC39FEF5B841BA73E54416C4291B9409C87946A799E93A5FB3B71AB9148D6A546FA48E2F23EAF0E248C21D8F2D8110C02749EB8CD0B6DB2FF01541E45B449DEBD4D4C0AE70A7264BFD7CABB33DDAC550EC8B1DC0D2F934A2B8C07FD5C9B95D8852D55CAB5562A59C0702AEF3E8A79C85D331EF62EBC944E0E2775C9DFD27F041A4A634BD6C3A6E3CFB859991A4B995A8B146C62D035C913F5B630C27BDF07151949C5A2A3BEB5DC63C1289BA98896E940DBE3699E993113E4A49A4D8E42520ECEB9578588C6773B3B95C867E495678E36981BF2FF3AA381AF3A9EDDF955057E956F2C7FC0B247EF6849C16C5FC33735754FC8EB60AD5717B2C487B3E2B8F98CB01CBD9CC6600436C403513C7B2D051072DAD4ACFD556309D1FD5E9CAA5B6A68E1F9C19A4DD743E625EF51932835C364A2C46E973EC47DD5102A75C9949C820ADF07267FD24D6D2B7A6AD80DA9CF1231AFF9D0A982D4285874706099A0EE00D2E53E0F2DC558B6B59FE88E0DC1D10674FC3DBB3C7AF828690E6FD59E8464ACB44125F8FAD829F7C97B4DDDF574E56925ECF98343C600985EE8D2FCD3F03DE3D7F5DC3F30AF89184457B2427B915F6CE5CD4C1E77FECD947C4202AA5E2EE651716572D7CF93C3707400F08CB230101C6C923A950F90F180AE0FB3873F03FAA9BA47F87C0BB67F7025F587ADB5FBC258D5EDAD3D0DE8F571CE4579EC369042F18518338B955AFC972B747E54B2FAF183E20E345CB8E2B2A2299FB857F652B85EBE0CD09C79E4A30F637374EFB2D7992C613547A56D6A15737E84285A3052A10311007A291A9630F8C901B81429B9BE69DDFED372821359FEF3BAFD04AA57B951DD9B3D59FF71B42548080E628E1D9E8236111994AC10B5AA2FB896F2F38A73F018025964799F7A4CE7E36F004F8B29DADD3FA172CC884BF2F98902E0010779E534A31DB8265F5C9DF4A84944908FEDCABE6891C71580D9DE07919A5E0A565A75666A18CC079AC9D6B5BF3771C968D9ED0DD80DFF9DA0AE9036A4471A0D3F8F983EBBEE38560F2DB91EF847D8B06CCB2EF146CFBF6B770AAC899C7D83275D95D5FB72719B0DA0131908A9B2643B3B8590E7BD3082CD8D3025FC73759CCE5320B986B5827FF56D807841FCE4B95EEDDB4ABA7B4D5AE16EC33F92A89325D40298EBDA2F5B9EB4DE6505226A3EB90CDC23AA1ECFB204C0CA89D8ADA6FAAABA368304829BF18E97ECD56F315189DAEAD33144B332F223C045DB541C3BE517A723BCF44AD7813C4282432C47BBE756EDBF4E412D5965789AF38F12467A244ED9E41161DE0210EEB2AD85FDD06D3A5B89C52B44F3D76B1A8AA758712E3EEADED46820FD8B16FAC8AB8BEE869BB18418B75B2EAA8BFDB945EE16C7A297CB4A2A3422F24579C91FEB06E5E63A02CA2F00FE9BB74313C6ADE99FB4EE8147673F7DB34B9ED64E27D64E122DEBC6237364D7D449463A81987A8A1CC2D60D0BB76718030140BE2904131FC3B8DF7C4D8D63C55956218C9BF52E605D5C63FEA2AE002F6F348D0E348FFA87E133FBEE41AF8C85208793E39AE728307DDD21A856FEC5BD8880A31B46D21CDFFB6BB8F82958B5F0EC367BDAC2202C2FAA423CD79E534ED6C9EB23121BD36F141B8404251D6FF9F091B30DB151A6DD622BF17CEFBDBD0FDECBDF53B9150DAD6C861A8CC28166A305F8D4AF208E367AC49B4D339E5188F3E207767CC05B0AB98242799A61AC9AC0DD78B4C34935AE6B3305BC9182A57744FB1AA906F4676F10C9EABB0CFE586A99E85B37D9E34A443C313DC4ABDD4FD9E74979D3483723E42B51F263055592DC0B8866A29D0A43ECF63CBA33F8B90BB8AF73F9356AF4C74714C22801D015953ED070C57D356F131607F6F7D9E2A6A876322E70281C1032268ECDB8D367B3BC9F35E2F281EC4F197EF7921CBF5EE69CBE6F882126A989380B75B3BE6F8D06F637A662FA41A159A8F16463E8675297CA4EAC058E68E43DAFC118E74FC45F2208F3ADE713AFB8114EAF03B2E957DA8CBF6F4B00AB0BC2327ABDC971C0A7CD9BEB54E62E616091D780AD2BA63F4BCA194E72D7E6A22FB6C79EA8DD802325FC8E925010AF95C0809834E9907C1025251E4C2F514938D953B14F40C3B0EA33C78DE241A375FC02C7AA8A0785731ABE2E0239B60B4056673C51B1D782CFD8A976E5FDC3EB8A3E30B82C765D34587123F2C7FC2912B79A03B8C5F6383982BD171025F5483C42BC20B0E631334203BA0B0833B0BBC543766836055F42D6A07B3477400E77375FC2B88FA01E7FC1BB5AE749F01E711DC1F9FCE3D5E1763D42D1F8B63EEA5528DBB31B96F48D9D9EDB53A3D25D7C540DB20BEF8B7671BB6118C1750D27EA464DB8EB0279A98FF1FCB3DFFF9C10FB0D802C55B9B81CD73806DFEF2E1EDC2C024A4A241F7178CCE9EF1169CB454DBDEAC904CB77F529AC170A3D383034192A09A6976DB489ABDD9A5D1AEA1AE7115BC3E55CBF845613662451AEB89B40377BC7B30A7BA87A4129672A32E8B55632544C1E9CA0926D6976238DBA08355E2E08B09CF0900EC0A66565C59EEFA240A64097C0EF274DFEB79E8D9C0AB558DBE7634FE932FF71E5812E5D64E6C251E4B2D5904DF9382973AC9A9321C55B33D3322827F59A97F281147DD691014E948A2CA676924C83E21762630C04AE70C5036A3FBBB8D458DEF7810970D6927C819CBA3FC5D2FB4C35BB36580094864450FB1DF91E4F834844FA6509031CBA470BEC5419133C2956FD5520FFB6307412B0EE60CB7852FF327D16C465EE7DA25D94DA55E9E157E49B34FF57EF036F23C6B7A80BEDD8BC8D8C69033510DE395B0308EDB4F082D42A2ECA795B1CBDE2A0DF7EA8C4C6510A2CBE1FD26D48C7EE052861DAB97BA485358DF4D25E75FF1822839E0A159042440D32218410EE33270C3F99656A7F4E9DDD1D183E37787D0CAE73418B7FB24F76F82677ACF9C3982A5F2B8434798137914451D57CDD83007299F64D812591B2DE969E4B6002652084F2B7D1F70593AA09575B26A88B2974420EAE3F8FED451AB2920085458723131E63512DDFDF028B0E3625D0E2C337E39E5F78C3F29D07BA68C5D40AAB8BC183BE5DFFEF17088F7F40E835E4A657D57CBBD3C3AEFCB0A +smlen = 5619 +sm = BE8CD296B2F4F4FD9FA84F79B3B65B98EE6B1F223733CB66314F0A3D150669F39C5FEEBFD0F536F88214D47BAD83D5BF9337F3242CB943D8586F531F924C43809DE865491D2E547024F0842F597E617BAE3EB74617126DCB9EB9DC65BC39155239BF3B386C4F7EE9BD34A02084163576BB2A21FA4B80B2DC70EBC249D64A30D70273A68E815D2D6D3D4175453A99F5304B6F97A48D518D7EEAED423CACDD71DA0D7FB0AB7F04BA1999AE75A68E5BC0905114BAF416F289B36646BCDA79993A246A3682CDF55C99A870C9B48456ECEA290061E62E82C75CE2527D31082F8F0C9AC8FD54CFC002E197E510688C5ACE56631097244AED2C89631E7FB08D0B91299C2F2E940E32BA3742FC440940D11915251EB4ECABC9BD412375760EA15CEDFF2B1EA373C6D0E2A313B8E314F33B9E1F0492FD2FE5D320F896D51C5ED69DD74B1D1C5857586848A2F56ACF13337D24E4D81E6C771986047D4EBD12D3CDF25033E823A171639E5B5C42795D98FAF01FD716791D8C5D0D01A685481150E4C098B9F87BB5B644307D022CB5C017FBF3F6B607BAB8612426DD5FDF6ACFA1C28506C6139324C994173FF103FD6DB847D160CA1DE1DCFCBD57E0310EE0C2A5E76E2EECFF9D2EC81A64621019E32B606ACE3D7409BB0C3D506AD51ED37F8210217C702CCAAB5E97950533B76DA59D216902E15CFD938068D4A1BA52390CB270FAEDD52481AC0D153B0EAD665AD5BAC2BA7A8D4F5BEC5B5B414D5CE3308BE3600483C2D0282B19A29EBC9E553CA340F6E1BCC8DEB2E8F16D74C1C9E3294434228EAADF1A1350EA87F798CBEED8D09DD8C10BC7BA1611C7F9F83AD8F915CC76161D4E479AF6E1C92B874A56B503142685DB2B52145078E3CCAAD27ED25444BB18818AFDA54FDBD7F5883989EE320312E870C180CF3A7F119F6F9CFFF24C7505E817E17A7E32564053102DE2846901AE614AFB29257D2CB57AC8F48A569DDFFE256FB3B39934B0F938F729198209D3B434861C8E397DC6A8CA685A0D1E7395EA6774A3995282383A61CC60743E5E27803BAD6F5F05F4758DA5A69D65E07685BB20A6B18EABCE658CBBA0298030BAFFEAD490450EDE1792B3AE90EB5DBD1790EE624C5B650B93E1538B0D5BDAD8C0412AB9636A82BAD8B626C5BABC00357F1C66B383FA040D35C04A7B89B46EDDB7F5A1405041BB63B3F869F105EC489B2D1E0A95083E9E8196E1AC7F4041BA672D536ADB9F1F88851DC652CD6617E633B99364E6AF9E13AE3676B84B6FA69B5569D181C28F09DAC0E9758899ADFAF4811E4FD7E8F8A695F25FFBB6E4FFEBD4B42A07A578AA5E06C990A2DC1BC31282267D55CB89E7D6AEC302FA5EC871EE2E9DBBD94196E96570B950BAAAB693CA8696723D8F5D66A66E3F706DD9BB3275A844BC4D29E1EF3AD47076D95128E7E400113C30F5EA5B5DD992097CB25EA31E0DD458B692E288AB5CEC1825B8905F8A3D14BBBB41A20DFC34CBBCC786CCFD1386E880AA9CC01280EEB8A173C904268F760A499AE53B3CF07F7BEBC272F190B464D9BC3C1A69CCA4DE1722BEE6127E4A6DE86C79983BC920FFC3F2667EB1E20E576063581B537F4002A2F179708DD10B8106BA1394727BFCB5A42CB45676424ECEA653E316B5B7B00CAE17C6BA3EDF4D5429470FED41A5B0C159325DD28A7C3B6D8EE3C10A2C01DC48B652346E964F33DAE6D12DE100968ECB27B3F1D7DB078BA479F2213DD87F2896CE4E9E3F8960D0CA90F9FD76F58C5CBE771B18864C6836C6547EA754EF1C7A37E0C8CC3F39829521DCBDD0EF3BCFCCF9A019EA9BFA274DBFC745CAF6836A000334687BA296AAAD1C6AE9F06B12E02F18B4BB1A4CC81D3E5B5042EB7C6C7C718AF225DF55BCF817C8405DEEDDF5FB134076FED77A0E043682B18BB818DD39EEF8ED90E78F5DB43EB2991EFCFCDAAA0EE2492F851279B65108B705483D6E34D0FBF02A3E168030579B0F62FAAA00838882F522236BACA4D6556FEB51E74C14D46F309C7A3F34E811CA1441C5D28E5D5BCA225B7318EC0903F1F103742B372E6A5F96BF86B0D51B417E79D55ADD90B11274A664214F216B3A5A36A1430BC7F4776CA72BBAE1B86D079748437876D5C3DD09D1A9287A778B406B50BB7B23DE2F19FB097E17CD1603EA51A4222185BB523BF4CC6263970FEFBA920EC2D57B3E1F414D391A5BE8C14A00CFBA6C06C57C2E08A9FB8D53544492CA0EC5DCA390E6BD5EB15A2451D744019FBABCEDE279E92F11A3BC8EEA662ECE62A81135FC3B02E5F5B2C4D02F88B388616A09B1EB06B860F701D0035B0233C623F48D085EB7903FF27C6B45958EB5C95799D27B041EA1771B51BB70DA87F7583FF6110C9C54B28E5B5443B327A0F81DD6F98A53412CB75FBBB3003B52F5FB9B3A8B2732D84A3586C1688E1630186D073C4AFA01374F514E5AF0F16E83ADDF96AD094ED3268242DE4A5B10B6A6A6BC419084B36DE6CF4F4529203EA2FE0FBC7C309109F1C0F12FCB7BAA84173933AA436588E77A495B488CA0EE51C44A55635A796A7E99C05D398EE13A3660874E702B1528B6E66892B1E7597F84A53FF6AE147D9BBA1FC41495B90028E56DE68E5DF4E866B5393D2C66103AE698FAF0E1A996D64DEB267759F3E27F95435B59DBDEDABC3CF2693C265605E216ECE17B24CB769A9390B52B0A20834276D01C91918F0FDEF43F7D70990D026581273ACDA9B2D8461705210370CEDD650E090F81E517DD83B34F63DA9CAED5B839DE5A638504FF8A0B5D51B4197EA88F19FAE7A82279C1FDA30793E193E0006064C7025E3D92F08AA7734A4529BA853A86EA0D9187679AAB93381CF29F86046FDFAE6EB9BEA84463D4AB1BE9AD64D41E17CEAF546CF71724A5B62D19494B5C324CD953C74369A877E401F28D9D026B1A8CE1380EF9499F802415F94AAE999C50E734211DA6598688056F4CA85E22928D6A29C4566C39B3478915EE8FDE034694CCE992A6B814E3C6DC168FD30806D53A0EAA88859567277A9F24A6B764E7137C866A4987F37D88FB94D009762153E12D991F06DDABC63498B4C0CC80B5BA9AB9533DB7A00306A5BDC4118F7931DDE0CB81768B3722FD028E1DAD628F2B27809C8B0EFEC9EF8470E53C37253EF4828FB08C74B0A82D91BF7344CCD9AB8590CF559024391C1F5B8B97A5A0A51652CECE5040F597EDB0D2F82E1DD3A903600E4BE1059B5D1C63E90710946CA49A35BBF8764778ADA1B1077E654357FAF2A824878A8711565BD69810BD9310B5DBA0CD7BC5A329F015EEED8E621F627299B5F3D9671F01A2C765825CA24F7255940E05B7F57A6BB34812B3B657D35E3571719DB5B51BFA27F246F183DB0128D24D1083C50863E50D32855B7992E730ABA179C9258452D6A07383D84A7F6A9BC89A07DA3F7BDCC1AF9D0767C1F2B9A66CF6F9F4B6618B944F0AB280B092B79343CF577045C30F040630CA359004FB8036BCEF125BD3066916EFD10A106D81D52244C0555B77CE6391643817708802D27CA26B35BB24FD7883F6053BFBA6C44152A57EF967AB315CC626C581EEDF46527A23F6986C65BB4513099AAD7FF6F1FBCCF003889242107B59BB0553588FE68CCFAF88B0C739341E696722AA84B99719C9E326381A8CED313E93B85D8B4090973695B8F240F7A1CDB8FD9352C8AFAD33166EED758D24C70087D81F87B02193DADD26503A6EFCFFAA9089F5B4DCC622BB304302F6C026A8E4631BFCC9FEBE1F45F2D3FCE9299658C4486BC3D844E8438A6E9913527A43C2F3B561498D17EAC99A697F2A5FC60B0CF4349145B1DA4B88557BE9B2C8B8E7F1D68A1FECA6CC21EDE3F5AEFC31605F6167A031BBD46DA2E0E6221F2A944C17F5DB3459804947F34E2AF95D25B9578A3F4E92E9C558C37258572A80912512FF111B93E795A3A5BC1D9B834A99E06C29ABC1A99FACD2AFDC9C22C58E3CAB99C687FFC655D330B308E20D4273BE2AB7EF2194D7CE29EDDE78AB219DF2A55A85DBA58F58A56A4A80771E880D8F43066757D484B6FC52D9693ECAE51764E08C41C730FE24EC93D1D792B6896BC94A8520CC3F78DEEE0E5D33377028888784BF30EDBA295A2BE873022A324A3CE10FB195CA7816C6AD6B901A22D7B7815B8E032AE80EAC78BE3020AEC3C1126A18A99EC9041AE0E90FE19D33EC447E71DC7E0D8A5DFC8EA1FC40D85708C0AC7579CBB866ABBF509F0C387BB7FF254A0251115FD97867CC3D3CBAD49BE99427AA6E45959024B14A1C5CC136E84204EB0EC7F6BC91945E5A34D87C6485BC306EC1C6F0D5F894FA5CDC5CAC2D4A9B76B123ABC47F2835A19EE273388896CCFB4A998F1EAB097AA9ABC56A449D75B9031E2C7CA7C770518EDB93C7E33D5DD8257A05CB440A47C111CFFE78445CE85474470CB85419FF945F5285953DE5AD5F8A8FC35D809300DB796777146D9249B8E0417DBA9A0462885877935182ABE6CF2D53ED866BE5C17D73747E25F057DD4CCA36D8FCB582FC69006789D4C3F5BE0E9D8898803F72E59D8EB1E3606B4C36C3546DAD4DCF996E7964C0433204993505F96B01358907DAE60E491B96146FE3E42DC3194B757CBCD1A607210417808AA1A8BAEDFF48597DA4B3CFE5FC164371F2067AAD26A4D2B0BEF9FF000000000000000000000000000000000000000000000000091115181B1F62215248E1F3AFB19849F758D742F8AFAB595040C4DC520D603C9A80FA9CF2E97E4F4BD7350551FB667D606BDC31A45D88836CD376785C01F9007D47DF95C1F4D1E30A927A13525409D91C9F5145C0B86D3B44E933CA81E4ED9559AC17940C61EB85B2D26D2C47924AB80ACBAA3D9B1C8855C13EE45F5C8047C161AAA5321839A01783B21A5EE90CF91B8285C4779465B7A89DE3D74D482080F68EB2D8B47429D5475356C50A92B3ACBDEA5786F4D6C2A304AB500490F84FD1D0F21ACBEA325D62D2657F3889B6F591A7F63D8633C061CB14B8266A7FE17642DEDF1D08D9FFE369126CD780D9F99FC6262B5BEFCFEF35D33498CB2CFFE55F2F8D567EA8687DFC6E7D49A61FDBFE768C1D11BF5B3B18CA52225B096490C97CB9A0B3B2CA0762DCC36B60F7D26FCAA4E38B1F3A6279D889323010D9CB0A97FC488E09B06237E6EB0166465C2CBC2B9CD06F155759B6C93CA0CD3178845E0F3A2D20A68757AAF3C4E74545494462CCF28F6F51EC0FDFF4F1E6D98FC5B63BFF068FA7BE1764BCF14497E71E424C9389C5DCF8C5CE1DCD40B82F1D75C3C3970DA433A92A04DE958766AC5EB3645F4D21882F7071383AF8DFFD6CDD91B549F143DCF59FED6674441EEB03D5013E90ADCCBD7E3DA115535AC855DBAAB7F51D70630DC00009E726A16DEADB12047D85906CFF315C73EE7D4E24C9067E3B772F3DCC44C25C7CB8622FDD7B8ECF5E9C877838D71D500F864A662619B1478F8AB4DB2DD09A111ACC99ABE737DDBCA06E88926C4E73B5F5D21EAFC4B11938FEEEA5F8D5A4C616A342B54C9CE371817AA2409A55A3237BE85A50F05B33D35AA86A62E85A01CF34EE7DC840A26FA1B8C6B307817C062D9A2E7163A3B036874D2ABF6531A772D4031FDCD59CA79FBF442CB9155F90148DC3B723778E699C6985634185C3FFDB966ADB80A3D1308150B12964142498466506BC0742783C27BD3472A5CB45021DE066C28143FFBC82B5742BE51E93BCFDE1A61E661B730D8760E108B80C859E4B3A07D483A6A8967E5F01B03EC8B63A20C6A03755C75F419558878A5EB8BB0B2120F183E4BECD4A104EB4DB62CACF5F9964583815334A25BDB75724E549211699AC3BC9B2B5F58F1FB33429905DF81C9422F8B84E95A7C36DEC6AE9B48D4F502D8AB59B69E9D112693578D143A3F111EF00844303950F65DDEEA6E30F1286DE16546F90C4364A5C09755AF3FECB13983C418B2FE4AC17BDDA57E4D597E8BDCCBFBE4082C446FC920E5145BBAFC67FADD9799CD8C7714510DA579516ED39B3E22DE319977FC77A9CA61AE8252795D11724AAA866C1FFDBCBC1FF91AF1B8713248864A4E8B9C59DD12863245F5048110DEDE7FE31FF9836715886C37E9642DBD6C668BA7AB8C2B706CDD58586EB7227B5768C3509C1F66493468859E275700EA38BA69064179F6036D7B50BD232B61C9B9659492894C0057DBFB80329A76CDC57B2A89BBB910483301CA0BF6AEC7D5DDF86644FF52F48FF6C7CD00406CACBC09AA251708BAF3276A52BE2C7B42FB6A9036C318529CA98940769A67DCD532C0000AFB5FC63AD2303E94E09D2CB40CCBE47FAA1DD22ECF528179AD40FD4BFD43717864149243D61CA255344C52743200ED8385A7CA6CCA24CF967D23D07DC2A3F9AD5F3240F4F022A6C6CD281B6C492E8D144A2F4641957ECC65B32C9F74BB468524FF58F0F3DA2F5A56742896CC8F99088574264F857DC67CF04C4B63C6A08FC534229CA8BA616CD504F969EA6E3C98A517355F98A9E884062805B77623239074206E01AD2F3FC9FE9FF8254A5D3525C3B2F0A692803500C967A2E18511EF5B8845DC4B0DEE9338C38C4B1B8B84EE63923250EB6F9E9C272617C7895BD538A6F34D3557812BBBFAB2B8FA6EB5E95B9BCE33AD3185CD90DD536A68639022C079B5CA7748864D37D45FA6780A45AA991F28BC0D3BF371EE2FF0C913CEA6DB38E4A278A4840EA1F255F8E83B6B6C5E260A49D727AA42095A88CB8120B51DAFD764E690102F7FA07CEA2EB86AC613E7BE2F498F5767B622D04E8A6F272976FB058C3334CF8CAAD1D180E3456C210763C974E431CBC3E25EAD8B9FF9243628D5B08D92CBF1D5DF29A85B1A04D2999B3C669227B33610121D543CF4A978F8D9365C0FF8AFFA92B07FC8C8604A0F357F3C669445685B6A29898301A5AFBE10ACE8D64A47009C8741D7CE82E9900643900A3B92A26FE5F24886C06AE0918C3F2523C320699C799CBF72F0DDB08A0F1F63D6DC2F021C78A9D44503209190EE4BE654663679CFD292292D71FC4BA6233A196EF9E95CB965852773404B2622B565BD91FCA6747AAF7F4EADED7BD3BB53645381B687AE04B8D8A9BEF1095EEB39A0BEB4EA89BADB4655A1AFC7EECB7DA0D670C192297CCE0B31BBEFEBFE94C84603BA8C0B7CC73159FF59C01A037CF2C866DC40D88432CD6C2F1989351A4E41343CACF7BF2C2B395C863709D6EC1DBAB2AF514CC771DF14DF095DEA8284BE2B65097D8E6F72EF3936595384AFC0026956E819F1657C901B92644E9D6D32D0D95549729B2CB3D5EFAC9C42A5F284ABC3BF5CCA5B08161B09D9A48FFB2996C3D4383D65B8D1F7FC3248CBE84B9C05464F4A76EFA005FEC342EDD56959CD26CB0DAE1B61B0493A4B68EB3D6335BBC280508F09D84E0C5F4EF520D92CD34D69E5BAB76DF5D2B72CB41A298D370EBEEFCD6C1904B956458BDA581EFA6B3654BE402AC3A971603F23F2B543C5BEEDA5F018543B72C146CF04680BCEA31B4A238460329E2BC12F14C804FDA3494C15452223D2477C9C8A497D04EAAE7DE09D7D7A879D3A5DBA565AE1A38F15E69C18838C487C0FBAD44A068C42EFB7D3F5EF488F91C42F25AC564751F0EFE0ECE7D98BB1B3D0FC42C9756F4B8F9DAF1FD0D414391155285C8DAEAAF380BD07E43570F14E9A47A87BC733F1E676233F17BFB71AAE464AED68487392D339AE064AE27BD57F8695F493AE56CA96C0615BDA8DA37133DD13C2B21DA189A7329773FD8D51381BC118645440B28FA4F402EF84C4091D3A0BC4D206BDCF9007F5DE9AA1E6CF7F6058AC6B69FBC703E908C4221F9065147766E48F54BE4B076406E2F9ED19C1BE982E636FD02DC26267C3ED989E6AD1CCE62E7B988FA7C1831E5126111A4C3C29C38A1F96CCB3A04132175FA46F73C634AC6EC741B135645ABF1DCEA18571CF9A539F5CC935BC6D32BEB1C7B8B3B5A141146EBC12DBBCC17BB4900CF0B95EBFAA52190AFC6D8933CAFC9 + +count = 70 +seed = DCC58DFC13B035323ED44BE50A7096F697C9C143518FED50A59181160960203831A9904847BA20B85E99FFA63E4AB0B2 +mlen = 2343 +msg = 954511394B9D10E1BA162861802A717E24EE42A346C9ED280C88E267A41EC09D6D73B6076E7E30257BF265B71A0B6E0CF408F02BA9078811BE94D0F38559E9985463FC9671D182286CC4F18CABCAEE1A3E5ABDBC384FB27911168B54A387171C0524489FDF512E4D8D2F65050CFE7405D8DF63A79C6E42A76F4538907EFF4DC5870095241523F56FE8E389EBF1A1CC47DDB9F0188513D5259BE257BDA5BE7381F22392CDC2406E0F2448A80F3824F2670F61920C667499DE899F0F6B397381A2DE66255E061AB92CD864DE75C9DB7CBAB9FE76AC38E0AB3389530B4004055268B289B40D79B32E5EBCC74353510BD1627E2D5DD0BE7D3DFD04138F6E3EE7526133DC70490612EAA5024BE6FBEFAB24E1E83D8941A113D8B871F3DBC3011869174888CB7A265D7DE9AB99B999C19AF9B442EBDC904FEDAB52CF40B787AAB35626417C5291F2EB892F43E698A8C65CBB6442A4832F33920FB2DBFC50B8E996FB227F2FF294C385A330957D2FADA9F86839235EA79ECDE6D9D94FBE7C79A38D40B9A8F241F53B921107FF1C72624C9600EC04DFA1160F1FA9E5D986A5A363E9CE8627276DA73F5DB47E4B90328884CFE93194CFFA6FA680F77886E4A7A0FDAF13A7DDFF6984B8855E1F58235BABFD5106338FE2B075D4F10A9FB3D3C5F829B7C61B02B34E9BDE6E62CBCC3AC9F467A6CA170EB43E632EBDBF6847F781E2469B4740FDB83DA34CE34A286E3B363A72CBB13EB66CE1DE35D8FD77DBEDBF45C44DCD16E6B58A1699694D9006947C8C20810E85E3EBF8FB2C68B967743642D86556AB6958E545AB83EC24B96F2B4BB99CC8890C3C1E0FECCE26CE09B6D99000694F870AF9F642374FF0BBF61EFC7CD5AAF5667FC3FE5745DFAF7F13FED70FE070EA4C09CB1A92D8B7F0DFD4B4A4B7DCF4CA6A97043BCEF6346F1570F37B0EB48DB8D15C8A82ED69B0C7833D6C830414C111C987471E84D2CEB5BD973DCA34ACD3A65D7B1A502368941935435B78B8F2B74C2BEF127D96651247BDBE68EB7E466B9EA2A64A13C375103D7C8F7D30A13CBE184BD1EBB19F3274E645F5C7B82EFDF09233D8AD146DC0715266963FD3CCE6F8CDEC20743BF1B7F57C101AC24C64D568923203E1A6AF03A700F5A401EC4572BBA528E284C151F1D108F7563858011FAB32B3776CF2B910D7B21180DBE75742032791018258F4D1407C9A213755C5C91205352DF919B6F14BE056243DF6AC2909E52C9A79F6917440667719185F1C5F1AAF40D873BA22956FA0BBAD9C35360853333A10A0841D9D2E758A0B1BC187F6BBD31C41B74F9EEEF1F7A28BDB7AC3D52FDC6FCB3EF0383A06A61188548963E552716D2BFBD6C2DCDE496D06615E86A5CDB76A03BCA2822ABA85EC6807EBB6918AD2948D193CCF74F4BDAF7090CD4294C1785DCEDB6B55886A848284A6A4A88A496800053E84A9F2DBF6B334AACE11A5A540626716302E259A64C6316ED543806B3BBFE37563897E83BBEFA570312DF908C1786DF0FCF55069EDC336501A5AE9D4BF212D56A9CEE811038656912238AE284575EF8DE1285B763AE54ADF44F91B6DD9E309B7A7A0AB71EC2E4611831B3CE1C9DC85CF907B52DF7406B06367E7A43DECE72DCCC57D268820EA021C27056E3C6B50E7BA7A59B53539A6B7B06B35051E3151C23F3BD3C889B25D0ECE1FD0DF1AEDF657FBB096CA1C861ACB0158501EA1AEFBF6DAD11BDC325AC1CED3739A40B7A83458EF4F3453C0F6EABC1A48037809A90480DF9DC4FF07DADDC58DF2733D49A4FA53C2A41E55A4A0167C6D33BA6E752AED3A125DFD6A0322CD235254505D7B3CED7A0DEE7EB662ACFD30F8B79D1A872998CBCF15CD86E26809E0D2DA0324DDC90FD12CAF9D8E4EDA437FE4E658D47D67C95927C4B5DEE965B940CE93E6743917296E10820A7101F8F633C93069E8B569F4625AFD4EC61BFE4549FDD06C2290A91AC0FB40CB1F55DC8BC1FE695C73AF603840AC0351F5256E00555C984E79A09E58C566D1A117B7E569BEB5850FB491FD9B982442B55BDF53832AA65180DCDDC2F768B1A1361994DE8C25F3608EC853D5982E0AFD1F9FA70170FC3589DDAF958DD840B4B502F8E2697D01AD7AC2233F6A16D540EF8D232887D2B4FA727AE2F038A69AF3DAE69EDA8EF6BF1E0B67D811160B75231543EC5A4D0778B7B42FC1DD6732385AA4400450B3CAEEFDFFCF147635CFA4AAA53DE4EE3035BC40CE8670016384BB877A86A15B59F3DF0C5D624D3D2B23EC46913618C745330A96C715C6F0BD096487E89B917384CC30B3D20A332F1B4056462227E98AF9874FF1D18DF2A6BF84AE822EE737F9E34EE8C69F23EEB9BF38ED056F499545F405759355C104284A6D08A9EFAD8FE28288B2084336A6479A6D42404F3E6FF3AD1DFC63C8AAE971AF11F2699F32F57AD29188492CE07BC1A271035B4D13A686EFDE5572353283A0F3138F6DC05CC35E5E5057C5C8B9E12B0164C0915ADEDF40A6E23848FA59ADC0E65BDD2120486942F232315FC94B4676751A35AAED2828889864C4CB7DD95A662A475733C2CA8F6997A9C822C6C8B9DC95A8B4C367E613E97D3EC6D6DDC2F81022EC21B3A93244E3BC8C2737A7724A3CBD480B26819EEB2676FD383601D79FA266ED3F9BAC2A98FF0109AD7E43E33E108D88C09BA82AFCCCFE98F50F789109D99DCD0A2C61947544F3666EDC621B5D5ECB7088B2430A611BEA52BE7F5EDFC6E2649F5E81F6DF72FA9A748BFF06AF766A60D2B751B23A8AA95CBF733359F7C0CD19B1482A6E6572D1570349C688D78CF8B8C7DD37576DC47A193A2C2797D0AF7504DEE303823A8B77204AE7B6E91D431979798A7EDF435056251D0E3F26B2CA16BFE3422CEA0398D30F0A0DC06DC8A93D27D13650E5BFB6BA04C93FAF0D7D06F99FE4F1F52A059FBE808179515FDA48ECA714F0947FE9A98F02D66FB0D80952411CDFCEAEF6ABA16D92B8F1B82DB151D7DCD7FB7781EC55F4A86C86011FBB9C5570EE76897E7803036E2FE3CDC2D5EA7A613897F3C69A6EA734E3811BFD15E90D7256A0C0C88CEB54EC6AAC151B435CD2A870E4A02087C2B847C75B00B44BB3CA6D4404C3052BD308B8D5F595277592D26F6D5A2193CD4D650BF931FEFB9DEEE61032B29EC0412F38E1CBE025B2891C59574C1450D9E3D8EF27940EF712143F06F38DDB86341A7FC781E0FA8971DAD13AA7E93F1858C70A71A40164211EA9F6A41AE90D19032C2EA52C23375CE3C4E59599ECD6855213AEA83F8DFC5CC70F58A62E4DCA17C09705C0C099B29056592986C03CF5D67074735F2BEA +pk = C435BA9281752CE4731430DFA63D4C05280227A9C3432949D6EBBB7F5327E72B32C93219AD27D20789D07EA0542F8282F2B82B33ADD586D375872CC7BCF146D607FBD08A9DB5E12CE6C896D5AD7F29EAC369A92F29AF38FDB37D99EDCE4DE2F0D86143B794BB69837480EF815532FBFCDA7E48D47181D00E8FE397894DCB8280F1FA9B0AA70E0B62817A15B8A7D84EA6F5F0359AC90C10DA652718C782EC36D7FD76CC273FF5C90812438407A97EC2F3852DA0D742FAE30A3A3C365F81B0FFE52ED06C0A180679982B15AE74F1243073633593003B1B69DD9A28219BB668F1215EAB3C27E934A59D4D8366105F63F4D7C6794C5EF5849E0138DD816504B5463E3F43A9E80FBD3DD4610DF928A3DD5210760840B5F243642388300677A56C91D8655DC0F7955BB5D85D1B562FA03F5CCD9F7D5F3DF36B7BE08EA2B459CA653C3847CA0D2A9177160AB0201DDE0686C1B59C91D82AD3189ECE470DBD949FA3DCCFAC69DD4EA2E90C8BD158CA4A979BB8859ECA39D9E8384418A55AFF66379CBC31B8203627ED4AD6757EACE741977DF8271450309CA18E0718805F841A62EEA6C506350BF3F4402AE62409FE0EE4DF380C0F4EADF02D17935D5626D397AB5CABB9C40BE1C6D9811C63E06A54A77442D3B522685F3F65056440D21CDBBDD8BA0977B591BAF1BB8BB67B8406A5AA75E4C39B0B6A2FF5987989E35E0961BCB443D710A88BED26C89DBA648972F1562C310673B815BED4C2577AEDDEAE72208718ECE38460CA1C84D318BE5AE01E15071B9C022254CAED70489B23EC1ABE72EA076AB0DE343625883ECC0615186BC3125081E44AA11EC83482C5BEF68B5AA69D26C0A42280380A226737D477C9D7303C94E62E8E9B96F65BC101FD1DC185305C336C4E9E919BF733D1FF601F8E071D7D85A6097A7A8D1B07419D7AFF31C98018FAFD70E1DF5F74E1627FD95EC6FA8F81FDFDAAE631CEE77BFD9D0898C51E0FBAD33EBE84D5CB46FCBA3564FCBCEC03DC8A949E87746F3833A48F1B4721EAEF42D5F7004B48745BFA8A953D4204DBC67C374305F55AA66F0F364093ACD472906A1CC491D509238D0B62551AA59F808B89BF6DD10FB9B4B494DBF99B3FD135A13B107D798FD7D324FF6903919D1CA97D9D767D95C08AD15ACD4A87EC60A6AE30666E95F265EA0A95F306EBC9754D4CC426503CE8018C3D6798B0ED02ABBE41C9D430266D31AC77057E9147C3B41FD6B54376EEE55A4C3BD5D1697EBDFB507D6E24C57F0A75B1D0604E7FE8E9326BADE22D45EA51DCB8C2A61491F8E080939F347F487D9164EE937E6D506C7CD31C1B7BDFC97C3C778838F0AA185777FD4103EC1409D8356B4C2A045A68ECF4FC27FFB3754709066C19CA63E94C6F7C7667A948FBF72F084DC1795A69037D383096C9111FA55CA7E88C1B12595C4260BBBD475532A75D72785FC27C12AFEB153F9CA132F1231878C9A2B304F3959512AC62CF937B03E0050990329598EB394B4F0CDA49E0EDE7E5E3D642A18B256D977D41C5123B5FAC54278E67596C878F324BC5B65898CCC7988AC0129FE07EFFE786511ADAE96DD0A0158EFE52FD74B6CF29FF49D29FA728B463ADE21D33F5F484B31BE78801B42A14A90C7D25C0011A55B946DA84081D2E3AEA45358A18AFD4541B2107CC2D72D2F34973686EBAEAB198AE6F0F9774F8656CE37B6AA2C33F4FC0CD6EC0DFE8C98237321FF5AD89B6E843A903DD3F39E1B6B6537FA014BD70353A7FADD219A3B8F411A8BEDA15E3870964A16291F759296FDDDDE4B9041F00FEAA30176D3B74208F7AABD078EE62539B8A1CD788E238DD824E01CA285EF41E2D1B27ED0F0E69AAA388E9177259675AA715093B4FE1E5A6DFAC2B48673303D42E978E0B7BC3ED60BCD766B0E991F714AF412E6004D4A078FA33FDE11FAEAADBF5D7AC0004255CBF3C1072147C64774C68D814D311FE62150DC4758D2BCBA2AFA46FBFD5835F2199F5C58DCFE67DAD315D6B0CDE3352EA8D0E4D13E15504C3747FFD0A53DFBB3B29875512881170FA48F9D59282B043C62BC94BA41FB9DCC34195BC73D65E4A8D96CD4917B81C1188DDB3F6D0D95525201E23927F348368C872A3637F68BB06CA12ECFCDE53B20B7D99D1838D374404B230A6E15F5E4A121D680D715F8907283E4F290289F14117AE75E6869D30C834F4D1FF42519F722E57CCF1A4BBD8820BCA295117587CA0D6ABA97B41207FF0BF35958084C4EDE244791E08E3B774E28F0F4F3F93D89088F4E62C34DE7E740DF639416257F82B205C4F2F5E8EF9A83E690EF55B2AAC621C2E96373283B8C2EFC05722B37A278583A2C60B71060AB635AAEA874EB247CD3749CEF7CB9C06FED419F1B7C5FAD9E2661A96D25A17E77FC17BD0B1CB502B10CE019AF2AD2C2A916B0D4D123F5D91610B50036406E6DF88F6B47D413F709299CCFA231715BE9FE36A81CF65335790A981EE13B2FAF729922792A932EFD416FB8237CC50D4ECE1D69468854EA61690B01EE08ABD3F3A8A57FF076271089750AE84F67FDB561E2FE70902D4AC5C39D81FB704F6F95FBC95C55264B625A5CBEFB2072219931D2C5829436E051B379076CE733F113545FA837B1163173375CEF94CD544AD015F1B606BAD0EB1312B044C4A8FFC18EFC5C3CD55F964B4D2C7FADE0420D8113F2293AB26B39768CCEC03BD9250EF878D09072BE1814663C83CF6270FC0C45B3294BEC12E9FBC80A34A677ABC9A336BA4FE6222482BDBDAA5BBDF +sk = C435BA9281752CE4731430DFA63D4C05280227A9C3432949D6EBBB7F5327E72B23161C8B4CC5CA68A521B4EA29D56406343FE9BED5A66771DE29AA5361B5C34A608CC861BC616A7A9B3BABF7E65C59789756B5380A61E6D866E7165A1A6C75C471F9683F93C6BE0DC2E5FBF74D4739410825A8AABD32D7A4B037E87F55589AB034311686517862421885124884122456311168845234260402255364520366048884060572200566631238718140134231112244078458412123882752257773565686217657174010221373650407764523115047528213364322002730000478074235334177152828231133530401142341300378305303020108384144428576325440316014701528150085587272777145141063320241138381242006306467276325505635411128322205011745147585861640022038335270560344822834527343443242657715552541040603037360263057322000473170040341330422613335863331253111762427761568536748534136168830484151786073153068363728422337827526235823048310077883137800278148440608353526622128060082238022546483443414362315642833733465204666651378158780841411072322165600807874788647878182764042380170750412410174662517841620475357881815065777108477772456632446131266870817204360455064368275184741704053623367122831677745276760145505527303622476578260152454821031722325316750667303733760332154078328714673475411628630317631012666878181686023051870067603731747574371512407047027105877736486251774621180147663700411832216010011287373420414730556860543264334822211574472380873461701032340805706736468755333608462377134756580704516335774558617273253048014071428436866866666236405212711383531154537012554505887815270758588387470682428350405845224712383261888160048582817564566478760302548173271113015865638144156262552020705366884013782126601686475462772750427604863416440636204677164085182341556237644127224483456055553785033572677420881747265143158587568407220043204517087284784307234387445108873444844173433773714548358562525033531502115377735825064428320105583743685171662758515830172102778208658684134285528688184021832624860272157406585475526015128386020812806854814244611738544315383223104327342558222438188528088004704068188731766327754767142508256488586008545286482267465707330535877176635786101084446711657703702505035354071134356182730702501882272006888875782703240143430186835581404314114635016474721675282670050756446257481752663302610644506020321205228441108467312138247675046216277874703441373131262315457135738388565758265328735438537716460123628110305375254411516504146721674060662556663202866583428668828610204261530554641603030335452705887481461000354403683013265147166813825883635568466587316466056085218737075387216476308450177508430072573478265037404820810135264061470387038573111818754106027555724788617707814508867773355103065475747533548864115444084307107724613142073755204820437833274770545832867845610186377202104135680810538088774371141315083167235853618321288680600752373532126707821711674071233228543611267046275387745577826876324468632845260410873543350714826537652064503378104417156560868321065550036870708280423861552160555567577427877383687008820017855472771807812131464650254576420305287435788104544464868478334584251163346565876154473382728445508248263422808142515874516501612315738617883EE7CDDA4B78CC6F4DA21BA9967CF717CACA292353F34E7A18D16FFE6EAD5122CEE7D8A73B3181BD83948D1402FD933771069084A5076273AE303B184A27240FA159A063A83DA63EF70822BCE87E18B2DC10E6DC11D0260778256BEEE5941D16BC87A4473F75C394B776419E2573CDDAEE21DD4D68E57662B398D881CF588DA54DC775A013D0B4852C54E275DF70D5A2C00BCEC7415F1C16C04858B4A5EDDA558CCB8DFD53DF5FDFBB4401D5517EE68FBD0124B9D0518AE5FAF018420C53294F4CB95EEA88E04F0EAEFB1035ED33E28DBD856B244AC14BD228F2A91BA6C82FA0F07A3DDD1989046EC7D7DC3BD0E293E9786F61625AFC3604A82E3C6BABC6126C1833AF842EA5D200DCE3D3CD0BFD2492BF37C48F14145A13DCE880815F59050C7E846C1952122B520CE7B6C3D20215DE56E1AF23C6B77877CBDADAC7AB98439B85B5C143AB80BCFF130B2294B95085B23B143576A8DC5BBD1004C6BF9D56B68FE4A9513099214920D036BA536A6CC38EA9C4030C948B7339EF4E021D6D2C46D1C52FCB012207158408EBB6F414500E30B4510772CE4547AAFEC13394DEBEC2E6887C3E7B73165F2B6A392A6BBEA5BA55C8B09C9F1CD439AA528DF92A0A2545CEA519B97480FC0FAE71EB8F00F74C10F64F6DC179BEF5E35CC47B1927E47B93B6F5F7D0FB6CA849D8D92A8793F184EB034A45DC4A0AAC4F93A72412FA06238BB8DF00FDE58C773AA33DD4AB99ED93B9D27077D6690230C4E7498647899C6E4AF3EEA84D5432476F6622004A949B0522D092B2D530C29ADDDC1C42D653662C6FDB0C7D00F7A6BA4CA5C0ED4B2747FE6D3E11DFD23652CEE51962A803A2CA9B5ED279E793753BE8BF3D2C7FF3F9B81C38481DA49D1ACDE9319A61743EEBBB8985B1B2C0159D9E93960E36E0658DA9F70FF21093EE828F7DB70721800BF3D598FA5DCFD1E2DDDC734C68E486FE1193BB7F04CCFC083A4FB979C0C16FE3CE8025FC97AC09E71803E60A3D2016E4BC9533D3BD2E75F828ECB8145862D80779F4F200DB22A4EC5A56F6B66E504AAEA4B9B9FD99BF148CA39BB921BC2BCB68B05EC5C7BB0151940B3723298DCBCB528FBEE909B84E3F9AD8130AAF89C363F1A6CA485B02F37129048BEEF361FDF4EC033866DCB91E84E04B3A7FCA58E8272BD83A85195FBD1CCC8BD10C18D8E91C6EFD9768DE7F87248C39C7B8C04E7857C57F81779BEA8EAAEC3E6743D858AB222397C34E47D9D8ACD6C9D6657B48786E31D50F524D8D29FACAA0A141621187E385297FDAB8D715354D904A2B99D67C68EBE02481B8F3EB8D9DB8815305D25F1A45A1D6E18A876FA065BF1A1CE52708FBDA257CDEE442B41434D1A4D4EC4949CA51EBB37DBD70D68000D6A6F1DDB3A5867BF174FAEF6D7C289F35EC94288A381F3F3E24A13F493BF0B28AC5E354B6E50B48CDFCADA33267F6DF59F96927237F73DAE4689895B48F68C479F10F4C45198BBE6E5E140E9DF067081F65D795490502A0AA733E88782FC1BB05B66A25F46712DC3FB194792C5B92368E09C4797695C9168A072E9DFEF872E61D43EFE0603731FC14E1A28967777B2C2C0150E5997870AAFC99D21D9527B1C329CA0E8B1644C3FD0C54E3B64E1BCCA3E403486BD121126D161CDBD2492F0EF299EBB4DA7D1138904730F2509DD27366B9BBAF3387529305FF9CE7B4ABC8B4DC3A71123BD30700D22A00EE9A4B63BF3DE3F2144FB3197D026FFC2C1339B7F0F320B6C38C16D8EF32B8DD2787D260C4CE6AB732CD50696B35033C7CC7F92E6760CEEA85A063E29F69039342CFD28FEE641F0E55641754CB9BCBE0BADA6887159250C773B4A25EAF083A5A966C2D0B75C30E96CA486C53A6AADD2D55A65841B7CC2DC81A9AE257B1C71A2EAF2DD8C2B30284F45CBFB9AB61B6C830342118C1ACE147E0592D8A1279785B3B786A7D35996F85940688CE4A2C888C011A9FAE82A17ECC047825D81DC0DF65473A3D8550502CA831662788C23822D8FA687059CBD70AD5FEE48DC69FD9D1167A07D4172D06938FD61F5929BF9F71E421B535287AD5C56AC0E1EF93053A7C166CAFAF37ECB56D517BB3E59043C29423EE7759DA670F514A8463CFF4F08282B7AE8AE081D3C8A3B685F70F589847BA212D169594A8532569F866E6E003740319BEA884D465AAE0BB432EB6F3822BAA0E166D52FF49001F17191DEB0ECAF8D01BE8BE390009F1EE62C3667D8BB1365A72348EC7A5FDB5270AA460331700BC680ABE27C5A42610F9DF2E710C6FF5157F75D860AEC77A43681B2C22B53D5639682508E474FA3D6438074EA94115D3892699FAE79358EBD5EF2794057DF87717DD55B448B539CA19DA3259189B68E9F8C38AD127F83935F4B82FE3C65D551FDF1E3DD198F3156015086D38E43C64A0A54A456F5F8084EAC5A3459BC0EFA39D168635E6E036E77D46C8135F6A11E5DF6852F24640E187C740E661DAA2079C79F8D495ADCA417B978E58F05DA0DC0CFDC0426FAD01BBACD3555C8087BAC694699A8ABC946667E676582EB91877DE7621A24308D2663786D163141FCB44306CC0B0820ADC8F243EA7688EC88C1A0580E6D8BDD75487BCB8C99C11ACCA501C0697377793F421AD31AD99BD6C36018714E089913FF75084890E5D12F94D6E25660D405BBB360DD41EB8685BDA906D11069DCE52A417997A174AF9AC657D64C200C596DDBCDF4DBEB162A1AF98F65BCBE6F841593B376C17FE691E145ACA9DEBB7A75A4E97261F7655689729D8ECB3698155BA8B044F0A765B0D2845F0A266E743E39AC2B4545E87ECE64A6CFCACCE5AF23CEAFE7C0E3C24CB16AF58865E996C6087F6D70395C6E45BE82896F54813D6E51AFD34C98694DC530AB201D7E64FA787D5C7941490C68997ACD81D0C9EF9135A63E2F256883939663927632CE993C6D558389D7B44B9347B23EDDBA01D28D05A356AF88402230CF304AF5D03ECC6BA783139921B76F843C9FA8D91C76CE593221CF9EAAB855D9759CF83928125158F7E953872A6E37B422998D1E3215D0D34F276A99DFF13A28280372A45A76E47754AC1C120009862A93E1874708F5DE50B937C162D04F5E9D11E4F35357C58EC71308264C688A1819F9BA9F2E9A3177DB228D97F930F847F4717A738898B07E7BD028605A24F8C2268E6ABAACE7E8EC38CD04D72C86CE7DDE179361B5283977363E4715F479028BAD5F7909FD9762861C8B17DCC07E4A8EB735C674C90E2B2C8EE2E9B6A058D2BE4C024AD8E801DA91B99B704E4C067DD0C1382C76A9F47C2026596AB27748A1DAD8087A54CBC893BCAF7BA907A05B19D14636B298A028390087DB90E5357E37A0CDF338D182F0868063986FFDF29BA175479659AA8F9EA9EBFC4403EF8510E426D93AA339340A3919F515F396141A609D7A866E95F5140E8DAE4FAF2B81AD7FE1BE5CE96F917F83198CB7B6FDE06D4C48B56490D03F7C36EC500AE8B60610FDA2E3B61ECA2B4AF97F6445F2A4AB0E89318F04EA7F640C2C41CD3A68BBD84555576D32C8 +smlen = 5652 +sm = 075318D8450198734EBCF0BAD565077CF5E1B6A2772983D41DFFAE5ECA601C9EABE4ABC46FCEB372DDCF0CA3466848E020E39508349F65AF62EA5C61AC4F00DAEE84E789C5E4B165700AE0B0BF405A1AA04B2069EA5CEFD129BCA36C590B995EB296EFA4B342ADF3FADD3A97C523274F12BAF6FA162157216F2C2ABBCD98E43F71758FF28CBDD269B030E359CDA7CBD53B936733D8283184BAD028D418840F39078878CF8A537C330CAF9A5807AAA509B00999131A78DE713B66808B92CB0A36D29E4CCC3F73870314D77CA4FD14832CA2A4BDA94E5033EB614D2350228D2587357B7353F87B46DB30A694C35E40DF890D60F4B58165BF5A12FE16B2AE4493E66F7FFC1258C2B3F83D1BF7FEA0F9DC5550BB2CBD4ADF1A1E97351CD024C22063285E3A81A16DB464B99B024C1BFB190C9C911D547AF3843FB35FA8095E5733AF044354782B4CF0EB8D37161808BF49545A207C527C86DA5DC89D64EE7B3352A9EBBC04D4C513FB9756E0544BAA75397F57739D108A0DC65BB78751F99179722D380C34341BB637BADED9AFA23BF2765926BE6293813F9065B6F5DAC0A36A7952E5187F93485178CA1928A897DD7557D996E8AD19168AACADBFE73A1153C4C4F534F25347BAF394C96A2207B3924E80719F3C771F293EC1D7583AEDC1702A93BB5B082B6273BB6CA1C9649DA6B7DD5054751F85E9D7CDF4D53AEB75E4F89B783BC9B2A266184492FD57B680A4F8A462AC0CF543A881074A6482679EADF69B31C78F74858FCD24E5F4EAB6CB87F9F247B58BC2D719183253023DC07B310486853B39C85552228D51E4F3DAE4F4A7B32B32F68A93C26EBAE8F2D3EC1E5B21925BCBB29D9C0E3F47EE5ADD57AB33F9D1AD3AFB1F73722B062F7F0E0105ACF67C660009B5A5A7812FD4E3D56267418FE2F21BF184E2DB745AD270AA4EE0E2C54FD829A08BB5DA593191EC0CF97DFC28A1BD1756FF5B86E926A41473A03D136EF763146B861F9BC88ED0BF2FF81CA9C0EBE370EA9D8660CAA2EF1F09C1EC63FD54AD67A933E52EFFE8A4413F0D0793AD9ED70337D06289D404DBDE669AA08CC3A705A5DB6C0216632EED6E60686E9A85F124A25326CC7E600F7CA5870EA9706F9E58BAC6A37E4DA4457B93BF6186F050BE07E61BAB2856CC4A0F087EF46B0AACD188E6A509EDF72106A36B16CEC3CB05314C0131AE45EED4313E1838E0F3CA31EF3BEB14D9E3AE14D115A3C6B5712334811C27CFD9D0EC6392A7CEF25E7321B2083BE6866C05B2FB4374F9063F8BB3A42495BA575B78F5197626E633F48A3DE56BF2572402A4900F211C1FA88B936E9AF40FD592EC6F79CBDD8F83D917C31AEB12037204F0826C78CA4AE5F647535AF81BBAB8A12944465A6092BCD33FCCF2DE782BC730AB706C6CAEAB378458FE5CC9E2D542E28AE148183A88AC2760B8648F0C4584EEC31DD038E372BD6896C0DDD30AF231837BD657EAE33B1B5510484D818B4240EA97B3F8024780289A9CFF30B3C0554C455C9940194AE2E989272810E7C214723DD3A6F233A5087BB2F0063B69F6BA76EE36F2C9268CC45BBFCEE513AD944897D8B4C49CE17D2C356E823AF814ADD8F26CFA5375F72696A8C675A880F71FF24A07D9C7334BEB00348E0B9C434F0A6B46A14BC7AA2F6E2747F7B86BE0520DDB28ECA6821904F910400E7CB415B1CE51785C4D38A60D437CD1A73698AE4869DBFF3C34EFD3D62ACDB7A54E2EA535E63C3AF711DDACD11871EAE18CDAA2A5CA4BD03C1A705673F3C7CAD5748CB78DDB3EAD3D4EDC370F5A15BBD5A149799B2F5D244AFBA89366EB790DB9A61F990A56758CD4ED652D907DEEAB65878670F64848755FA90563D0DC7AB3FD59ACF0862D53EBD76DBC85375100F8FEA375542E4B55B0110F82F2A91E089D6C27F5909D6DB9801D44F2C4536145C7ADC09145CF8BA5FFD7A9E6C4E6F118451C12EAB3E50556C750FEFAE9CF088C48EB68DDF48C555EC522846A8658D03E8C8DE68098790DD3D4C3576762EA9E29F154F1546B92A0B14A9A9C0738DAB255E5433877EA6CFA4D62D2BE8EC2C70A5C2AD0108F2902009E36E22D55C9D3DD0AF1A8205373469CCE6E94905097D3DC7EE4A3EB1CCE324F173DBE6229F0DDC114421A708AE75B27D08A80C413B75837D1178B1DF1A0B7491C03B7EB272E62FE6B2742EB348A087C80919607C98B76051DFC09EFFA8587928EBFA31752921B7C8E40CCCE7528C406B9B449019CBAA28792E71B34732A034B9A47245F03264DA089AF602F8FA98FD180A3AAAF6827EA0947373AFAD6D8026F01481A2B4E5777FE6A17ECA7882E08C56B478F02667B9A705E9740C125DD1B87667B2B49AFF19FF2F0938B0B9659D8620FFEAAC03FA40D91565F56C122E8131936B773E90F1EC3CC8C81148467BCAFAE0032BDFDEDF9D2DCF688B001713C7D6FF6A743CA37858E877B3C5A0B6775CBCBBACCAC32CDDD08137FDFA4D3283E4AF86B8E36B0931D0EA090BF7CF5D98C286332A87E768F400E65DC0BEA43AA8309BAE04B0CC2E6EEF6C36B63821F636ADDF7627382B056A01D0511391963A0CF378CCB3CF640E6406890BE3FF63B7C84C4DD4E6BB6A3EEA8ED47BE8FB03ECEC8963C2248FD96CABC4CFFB6347C490AB544563AE1B67622043397C2FF89689D6EF23F72CC6ACE909B92FB7ADD3CB31622FA7233E2E381B75B24FDA0A0B67506EB271BA07527C169550F1C986B255383D8DC623567DB7B2F8F79F37499B12756ECCC4F4DD2585FCE6BFB13A30B344F7B5F7B80F35AFA4D6A3D697CB14F7B6FDAB4DC0093AB21323C2D7FF0209CE1FBD9DC79F23E941E703623BEB002F0F9AFF5D68C39AE29ECBEEC9FA8BEEC7A586AA49C6430DE906BA050D46ACC3B07E35BD2622A62D9B11CD6C5F3A341ABF2EED6CFC7D8234C29B3B7827E95CB709CE6484209552FD40331506A7EDC0ADD9C785D58420A31D3AE54436FDB0F574D34B1C156BCFC1D9A054507F06DB462220C800DBA617F82208CB04A722C865022605A003FE0D320BBBB1AFAE634C8F00C9D6D8A79EC0BC2E072CCBF39FD7BFDCEC33AE87C67C426CE0DB65D38E10B3DA77CB0AA5C15B4A53F1A1368CEA31E92303787544895ECC92FBA22F4BBDF099EA683EBE011D83EEA515E51009279C77F59B2B44035E74B5281F8F27BAC30C14165F77BA88528A76BC3CAB17BDC7B70C15227685E43574BC10F9C7A586C3D79F3DE08F1D9BE3F621E131692238FBA81310B917362CA6383AE46241B27B61ADA66B9675E76369C01AAE13834648E947B3E83ACF26BE2C751DD1F3BC6D01B903811DB1AF0248CCA25A1AC09A01404D16847267A7BC328110355A12550E27A2541B44A98229D5E30CC7B56314ABB8806E0209DB5CA8FF2A2CA6BA963AB2BB86FB970E489481BFBE0D12AA2CD58F90BFB75B4E0BD7FC00ACDA31F7F67CAE38EC896800035623A197A0FC193EFBE89BADC0000E78BD635FB68993F2E39635DB3F0161CACF01F4D9295FD1325954514697EAAF8BA943571FAABB0ABFB079B62BD5269B4609169E027777C775BCD62581E404B5EDEF14AB176EEECD370155877C4621E53DAE537CF246F8B435E5A96FBF40160D343917083DF08577A9284AADA27738FAD82C3D1FD511F9896398A1C8C4481B0359D3E6C40ED5846F5934ECF02598D50973D7167372D17F38B792BC9744D6323604015F123009619044E16FC537CD01061FC5D6E44421CD9F84B5F7937F95966E156D4D9DB4D446DBFA1047CA57CD7E221B5696B3627393004A332A42E81790767689076F24DDA0EE1CDF6401BE92ED8214C76E7D12E0A19E346B1466C444D84457A6931076121358EB2C41EA8877EDA5A012EE743DA2D0CC52C23436E0187C44D578D78A90364AD09A0DA21C7A1CD3CB7432F9658823CFA2FF96A91F379F3C5BF38BB836217AC051817FEB4D03B59A6AE9CB46F0AB61BD9B6200711F3B3F2117341D9077E55EFB97E01E17C40CDF0150F8767F175857EE9C2BA4D1DC9CF7AE036ED776F6CF341676DDF8DEA0F6A4F347A208F892988631C68D514B31CF88C9FEAC81521DB5A7A14808153585F4EDE2105C480A5294AD92F1D7CC0FAAAD627B92AB363E39FFD0C3420825846C4BD56D260BD1A89A2E9B481E3A206072F8405DCB38847AC63FFA0F56B87E13BE7FCDE97886B949E003B1696E0C762519053C11F049DCE7BC0AD1E94173C45B9B9A511C97E817A9ED2C614DB23FB4902F634475F54B5EB0C54177C30FC7D9AB500E32CCA0203A17087E768D83D2B808CAF6BCB32372E9D25CC3AB644AFC3AB54C258BEACAD61FB87C00FFB86AB739424D2549187FA48E4F9D6BCBC20C90E20B84FC2E6656DA193DE95698B684C3384617FF8843B497A963F039CD35EB4FCE32556FCC0184BF22ABCAE0E8F01FE8F25AE41807E030F958C9D5F7415105F4573D8E7A73A5458103255088E9CFC3934E183A2DA49EA226CE858D6FFAC07E679FFBE6DA6468501C11C6498ADD48A669BE6F23D209EDC8FE6D2AD5872623F05EA4CF27A0838B6C2B1CAAE0007F0F42AE46F90E5EF5A9E3BCE5D669782D944430BA931A28F6C595F5085FE48B079363E61A616244C697A922C418DBEC8E7F6556D7C950E242F3B4F7FA1F70B3C497EABC62C3D8CAEE000000000000000000000000000000000000000060D11191F24954511394B9D10E1BA162861802A717E24EE42A346C9ED280C88E267A41EC09D6D73B6076E7E30257BF265B71A0B6E0CF408F02BA9078811BE94D0F38559E9985463FC9671D182286CC4F18CABCAEE1A3E5ABDBC384FB27911168B54A387171C0524489FDF512E4D8D2F65050CFE7405D8DF63A79C6E42A76F4538907EFF4DC5870095241523F56FE8E389EBF1A1CC47DDB9F0188513D5259BE257BDA5BE7381F22392CDC2406E0F2448A80F3824F2670F61920C667499DE899F0F6B397381A2DE66255E061AB92CD864DE75C9DB7CBAB9FE76AC38E0AB3389530B4004055268B289B40D79B32E5EBCC74353510BD1627E2D5DD0BE7D3DFD04138F6E3EE7526133DC70490612EAA5024BE6FBEFAB24E1E83D8941A113D8B871F3DBC3011869174888CB7A265D7DE9AB99B999C19AF9B442EBDC904FEDAB52CF40B787AAB35626417C5291F2EB892F43E698A8C65CBB6442A4832F33920FB2DBFC50B8E996FB227F2FF294C385A330957D2FADA9F86839235EA79ECDE6D9D94FBE7C79A38D40B9A8F241F53B921107FF1C72624C9600EC04DFA1160F1FA9E5D986A5A363E9CE8627276DA73F5DB47E4B90328884CFE93194CFFA6FA680F77886E4A7A0FDAF13A7DDFF6984B8855E1F58235BABFD5106338FE2B075D4F10A9FB3D3C5F829B7C61B02B34E9BDE6E62CBCC3AC9F467A6CA170EB43E632EBDBF6847F781E2469B4740FDB83DA34CE34A286E3B363A72CBB13EB66CE1DE35D8FD77DBEDBF45C44DCD16E6B58A1699694D9006947C8C20810E85E3EBF8FB2C68B967743642D86556AB6958E545AB83EC24B96F2B4BB99CC8890C3C1E0FECCE26CE09B6D99000694F870AF9F642374FF0BBF61EFC7CD5AAF5667FC3FE5745DFAF7F13FED70FE070EA4C09CB1A92D8B7F0DFD4B4A4B7DCF4CA6A97043BCEF6346F1570F37B0EB48DB8D15C8A82ED69B0C7833D6C830414C111C987471E84D2CEB5BD973DCA34ACD3A65D7B1A502368941935435B78B8F2B74C2BEF127D96651247BDBE68EB7E466B9EA2A64A13C375103D7C8F7D30A13CBE184BD1EBB19F3274E645F5C7B82EFDF09233D8AD146DC0715266963FD3CCE6F8CDEC20743BF1B7F57C101AC24C64D568923203E1A6AF03A700F5A401EC4572BBA528E284C151F1D108F7563858011FAB32B3776CF2B910D7B21180DBE75742032791018258F4D1407C9A213755C5C91205352DF919B6F14BE056243DF6AC2909E52C9A79F6917440667719185F1C5F1AAF40D873BA22956FA0BBAD9C35360853333A10A0841D9D2E758A0B1BC187F6BBD31C41B74F9EEEF1F7A28BDB7AC3D52FDC6FCB3EF0383A06A61188548963E552716D2BFBD6C2DCDE496D06615E86A5CDB76A03BCA2822ABA85EC6807EBB6918AD2948D193CCF74F4BDAF7090CD4294C1785DCEDB6B55886A848284A6A4A88A496800053E84A9F2DBF6B334AACE11A5A540626716302E259A64C6316ED543806B3BBFE37563897E83BBEFA570312DF908C1786DF0FCF55069EDC336501A5AE9D4BF212D56A9CEE811038656912238AE284575EF8DE1285B763AE54ADF44F91B6DD9E309B7A7A0AB71EC2E4611831B3CE1C9DC85CF907B52DF7406B06367E7A43DECE72DCCC57D268820EA021C27056E3C6B50E7BA7A59B53539A6B7B06B35051E3151C23F3BD3C889B25D0ECE1FD0DF1AEDF657FBB096CA1C861ACB0158501EA1AEFBF6DAD11BDC325AC1CED3739A40B7A83458EF4F3453C0F6EABC1A48037809A90480DF9DC4FF07DADDC58DF2733D49A4FA53C2A41E55A4A0167C6D33BA6E752AED3A125DFD6A0322CD235254505D7B3CED7A0DEE7EB662ACFD30F8B79D1A872998CBCF15CD86E26809E0D2DA0324DDC90FD12CAF9D8E4EDA437FE4E658D47D67C95927C4B5DEE965B940CE93E6743917296E10820A7101F8F633C93069E8B569F4625AFD4EC61BFE4549FDD06C2290A91AC0FB40CB1F55DC8BC1FE695C73AF603840AC0351F5256E00555C984E79A09E58C566D1A117B7E569BEB5850FB491FD9B982442B55BDF53832AA65180DCDDC2F768B1A1361994DE8C25F3608EC853D5982E0AFD1F9FA70170FC3589DDAF958DD840B4B502F8E2697D01AD7AC2233F6A16D540EF8D232887D2B4FA727AE2F038A69AF3DAE69EDA8EF6BF1E0B67D811160B75231543EC5A4D0778B7B42FC1DD6732385AA4400450B3CAEEFDFFCF147635CFA4AAA53DE4EE3035BC40CE8670016384BB877A86A15B59F3DF0C5D624D3D2B23EC46913618C745330A96C715C6F0BD096487E89B917384CC30B3D20A332F1B4056462227E98AF9874FF1D18DF2A6BF84AE822EE737F9E34EE8C69F23EEB9BF38ED056F499545F405759355C104284A6D08A9EFAD8FE28288B2084336A6479A6D42404F3E6FF3AD1DFC63C8AAE971AF11F2699F32F57AD29188492CE07BC1A271035B4D13A686EFDE5572353283A0F3138F6DC05CC35E5E5057C5C8B9E12B0164C0915ADEDF40A6E23848FA59ADC0E65BDD2120486942F232315FC94B4676751A35AAED2828889864C4CB7DD95A662A475733C2CA8F6997A9C822C6C8B9DC95A8B4C367E613E97D3EC6D6DDC2F81022EC21B3A93244E3BC8C2737A7724A3CBD480B26819EEB2676FD383601D79FA266ED3F9BAC2A98FF0109AD7E43E33E108D88C09BA82AFCCCFE98F50F789109D99DCD0A2C61947544F3666EDC621B5D5ECB7088B2430A611BEA52BE7F5EDFC6E2649F5E81F6DF72FA9A748BFF06AF766A60D2B751B23A8AA95CBF733359F7C0CD19B1482A6E6572D1570349C688D78CF8B8C7DD37576DC47A193A2C2797D0AF7504DEE303823A8B77204AE7B6E91D431979798A7EDF435056251D0E3F26B2CA16BFE3422CEA0398D30F0A0DC06DC8A93D27D13650E5BFB6BA04C93FAF0D7D06F99FE4F1F52A059FBE808179515FDA48ECA714F0947FE9A98F02D66FB0D80952411CDFCEAEF6ABA16D92B8F1B82DB151D7DCD7FB7781EC55F4A86C86011FBB9C5570EE76897E7803036E2FE3CDC2D5EA7A613897F3C69A6EA734E3811BFD15E90D7256A0C0C88CEB54EC6AAC151B435CD2A870E4A02087C2B847C75B00B44BB3CA6D4404C3052BD308B8D5F595277592D26F6D5A2193CD4D650BF931FEFB9DEEE61032B29EC0412F38E1CBE025B2891C59574C1450D9E3D8EF27940EF712143F06F38DDB86341A7FC781E0FA8971DAD13AA7E93F1858C70A71A40164211EA9F6A41AE90D19032C2EA52C23375CE3C4E59599ECD6855213AEA83F8DFC5CC70F58A62E4DCA17C09705C0C099B29056592986C03CF5D67074735F2BEA + +count = 71 +seed = 270BEDAA7BCD43990FD8B4F44FFB63A3AE8E991BB2BF84DA7BC2CCD1A079C579AEBE2082ACBAB7FF286DE795F31973B4 +mlen = 2376 +msg = 326A4FE723BE9363ACFC000705A10B6CD8A7B25E99A34B4A354CBD6F50550BED30F6C4208490B4194AB79B24B093FBE132C299DF924F2FFCC2CDC6C2C9019EEDF4B72D7F0817825BD787135927102E1DA041E9A78B501B42DCE777A79ACE604E57DF11775D7B87E75E5B00ADAC90D1ADD78CC5AD348C7472EEC6E6E06F737E77115A9509A6AE6570F738DC2F21314A7CCB9D44ADD6E1434CDFE3614BC73A6B468F6691B60F4F2DB103289A90C4FB2BF5AAF87826D2BEB0880FA64E07E9BD30D4EDA00D6BDA01D1EB22BCF14EE797A859C9A0D9034E8C5316201AF91388C47E1DDF061C9F45E067A5F60B355C98F8734559B8F1B82F47BD9CEE0224A1D67D40706333523C34F3582B6C8CB47BF7D0E4FBC7D7CF3DBF21077E664FD59998338F4DD4A423C3A145EE1E994AACC1A48F81A7E9FE106008DB93A6626B8C8505043AB864D93AE3972675E69C3825304086AA3419216CCAE7F7D5117739E99D8F4A0B658148DE33FDAAEB9967EF56677D2028C3B584C5CC1C096F4DA16799408B2EE2FC3482AD2F49293CF4097A78492470099BDB90BCB4FE3B245AC8B3C53E05D7609E34770ADCC147033A8FADE81359FF63C3FB90C5A498C98B7A0E5EE9CF4D287759ACDA4BFA3965CA85E1D1C1019E7FE6D82E5E66A717F94890277E6DB1EAA6F3291FE1BCD7D437094749FF5574B8728E0DC21A143A14E382937EFB7EC1B0FB3F6F9C0F547F470E3B436DFC7986F923BEAA89583D8978C433E0CB0C4E98516AF1AC797C778662455A57FEF45BA2C7865C1DF5C502EDB01C8CC729468091BB96BE9DA9C298528187867EEE9A06141DAA15F60CF719DE2BD15010550B92A41F12D8F38B54692589AFF51A9D5E6047A0D9B707369992251DF31341A45B01B05FFED8ADEE5810824F903EA59F14FD500AEDAE797F8BAEB470C0B14C4EDA5C687E4848A85B30A8E8F59C45D4C9F0C65FCCB15F4D4209A55722C29B6CB09AECB4E53FA3AA602C56EE3BA6900CC12889E7B87D5EF283AF1586764519A30CF60833C82F0ED15E39A8BCAD5C6AEE9999E63D399C5CEA10AE1F53B04858EF7896AA29FA541451FDB685734C39470250545193CAF26C9891F7F965904AE10E8566BFF9B2F465BBE13D6EA4A79586E68844B9FA68B2F992565C8B0EF5FFDEB5878CC12A0571CA3AEA50ADD29DD06E13741A1AB215BF487BE7735D1634332F47E037253054A21E0AD8D8F011334CB5951F833D4D344D632BCAB7C373CB7DAFE8F3D79E7E13BDB1C6CFFA474A9FBB46F5736D55F3466534596EBD22B29107A8FA50C1D0E62F0533E343FEE038FC0C3040A6DF2D318BBC8420019B1B148D6D1DD2FE428C2FD617CA73F224EF9AF9BF6F83CF1006616235471B69DD4EAF9F32529EF3E1DFE6765E61E246B519C702351C9CD66C57065EC78993D793B082E3685EB06F2530B07862277D339A52813C99EBE16C06C4C8F547D9705850E770982E8FA0275A52F430FF2422A115ECE46A9202CAA0195789532B1444F1507AAB2E4303464E499989F21C7D881328F18DBC77D4B9B467CAE244A93053C0321DFBF815DA28B6EBF483EAFBE634E9947BB5383FEE3A31BC03A63FCDDA5E3E46D5D3184718C348A83975728714351DF43BAF91787CACA346DBB819602F18A4C4FE90C4CE307984BCDED89CD2E4AEB66318C10D95AFA5BE53393FEB981C21BB1411BB9C58818BCC141223D66ED5F35F90C05FD4848617220DD72F5E892292CE20AA9A0F9AD54022CBE94D2C86DAF3FC66949AC35D8E122B02E2D155E73F4CE24D7E85A5C301DCC173CA8EC090AF9DC7F443C983280DDA27ED4B9BC71F86E84F7AEE39E6A7E9BF5E43920AAC858F0F49A06216D9D3984CD2E3575C0FA6CE8A5E28B0F481CCBAAB450FABCE8A1084EF458DBE257CF09D8116136C2CF1EDFA6CCE31AED0F1F8278C1C8D9C79846886D48E3FD311C015BF2373F7CAA71AA26B011D0DF5A843AB53D7E7F0466CCF49C5D4DE872CA87B8895101EE0147A3DBD391BEED75FC16F65814D56CB29273A5F4E5400FCABF85040505C31D001DF0023726E9C1F7C29A37039FDDA73B9B99ACEC3A029F7C0DD61ADE7D5E835E1CD605AA8E583BF8DC99285E86CF91F4B4827A0E8956EFDE2B495A86F85E78B954341CF3AFEBE8DB71C26B9B1BA27B47284AA84E55B1C2AFEE733AC596A10186D9AB504F33E34A06CA931D7633462B04B9B2B0D4751B0343503BCB2A1893D944FBDB4BE63DE167348A1588E6551FD9CF2101B0B4CB61422655FBEB50D64CB9E87A23007A39821EC3ABA391485347624EFC3DFDA4A133C537D7CD8C3A549BB6BEF9A52D2EDF0A8892C6FC3EEC3EFC3C18741C85BF24CD3B36CA04EE77F654ED5595A0E4B9316CCFE4D2AA6B4A66B06F309337E363C9E39829C8838729F19811093DFBE962246473B7A19FAEDFDB0193F63EB85EF308CD3BE5831F35CED36D9448D0EA8306044F78946079210CF89FF78104BCB2964CE2AF9954D53885D7914E4FFA4AC7E9B3D103922FD1AD68C0A4592F885C5FEE51D52214E17035E8681086203B79B5EB176679EB3263B44EA7287262DD84BB98F6639B9657AC04E397D69C634A0C1181ECA485E467D62631AD2D9AFD5AC5B86ED4005FDBB7404B65BBB826F1A2334A481B9CD46E0CE9C414A162E84368089F24149D7D05EA6ADF40B25A708357AAA5A28801FF100F69252810188CFC6087507BB5BDE1CD43BF72B1B3207CE4F7E65A18E5276613D4BEDDAF21AF7B964FF69965C47CB03846F7CEDDD2C5133080FC632A4F0B3495B2D2751727CF7681F28675552DF2A0994E425A922BBFCF84189B8C9F43058D691DB3166C596F6BC480EFDE06BDAE7B9C2985A1F2F6441520620E193D7B94AB46DBA2A1ADE44E2B006734E6770F34B0E2122DD7F4EAF045164DEA8C2FECE7758630384C00A6B528A6ECF07045B2DC0281C936A540904733149BC65B0F57ACD9A5E41C2ADF83FD6A760B169BEEBF04644DB1314270ADF86D01CC2CD580C609E78BBCD9D2694A89F9CB6DD36B9AA2AA5581FF561B5417BE2B52F3EF2581E461CB0690782F33862C52590643BECE0A6141DC805D8F56C4F64C1BBC49A3ECF1E8827926796E5F9335DF47DA6D3E4C14795B547116FD1F3351FC55C28B543183FEAD8DF7DA4DFBCC38E224901FF7BD83B16631064CAC4A37FA632F53F004374AA19861FDCA515AF91E66186EF804366D5A1B3B4FAAA60A0C4B36B972A9579548B4CDACE7EB85F1F68A4E4255FD994C1786975E7F6F0BA87D0295DE72876BCE37146A09EDEBC0164B9C4911CE41EF4D48130A27651BD0DC315FD622CB6D03759D35756806332658B5B33E768860C1946569AA45130486AD49B +pk = 481790F5476E7FD342D746C51113C172751930E51FA565A304A1EEE2E2AE7F409E87693687DDB6F14E1FE7AA28CABAA776CB50354A17897DA103E9B64E9AD9FB12CDAD4B4C97FA0E63CFDED1F7CC52B1E7E77F3BEBBE7350585FC9233292791DBA596394CAA9B2E1B001EF5812D6EEA4846D6E41CFF9FB1A5955537292AA8484A4A8CFB8FAD2AF45ED76F0E5FD435AF9E0612EC19AE110528470D9A0288C54D6602758DFFEF3D7F810A65A83218AB83770338A6E4B0F557DB57437B4F7CBBCF0F5CC69544165378A4C70BB8C5F1F3ABEB19691E95204DD31E03247E79C9588F6059047B54DDAA39B93325C14DFAE4FB60C641F51013DED5E0541CF388EECED4DBA873A28104B3A8BEC77519E8D98FD49C81CE6C52971B8A46B017F5FE5FA86601519FE234172A5C75D263DB8759E4A99B2FB5F0E253C2EC1C1E352D4ADC119A439B021EF4CD48825067CA4E3DAEC2402D49D994CBA03D3D7810A99FC4CB7DFFBDD51944A89AF1896C19C0295D4B94DCE5FB2C2B96B6DB1DF5143DCE4ECA2AB30C5F96BF08A510ED9B32C1AFB2D710E0CA8BAAB66C91951C4A39E58971AF23A8CCD57A48185A05C33B58FC3715C9D598EBC10610F2D2CF6B5D1AA028F66B18C6B73CA7F8EFFA8C6F133E138113ADC56649645E7BD140F23CD3E4CF95FF0FEEF5DF974C6FBC7F18F5FC0E8CEA5D08DFD383EE57F0B7842719800F50686BC0FE35208D9A88B7313620F4322579A9FE86EEC91B89DA556809AEB8E7C5CAD785FB7D5873F24AA0663865FE30CE3BE0D5F95B942CB500A5EBB8DCEE4D3649F82113795FE4BCB9E2ED473F88908226CF1E9F92436667193735E0E6B67E77FF29C4C43F2C2146D870922D8958C7CD47AC21C2C375AC7D6B30E469ECCDA6D54CFE681F7D835B2AC26055A163B269A301DDF2893323536897C70DED4FC0694D9F7CF676D93AC73BB4717E6A225A2D3163EF01E64C109B1C7747F41D8FB68C816CC1A1110E2D7E6E33DD562B93D5BD734CC2374E31BD681458E6CCE42C1BB1E31A8CF8713AED81396EDB52AAE74CA478F00745ABB27F884FEA0343A7E541C16E0A758A0B00E8896069DC9F28DF7A7455410FBF190B96F7A63B4CA2BFB29AEAADECC8EBB1218178B52B05BEF8740E7B7D20C56581A6C6022C20941C04BFA3EB1E329C605924F02A5F193C55DCF840A325D67E8BFDAC303AED0F6F7DD5AB9DA7EA25D060BABAC10893C9A10EF85889E755118284F87809EB2818E9B8309FC15DF8E5AAD8B1D29BBAEC43868DBDE839BE2DEA9F2BE7C0901E5204E144DFBE35E4773EE9B43CBE17619E4F94B879948FC6636145EA0D943CE4B9A3DFFA5C8BAA2191DDC1516DDCA456368EB2E5FFF6E555EEE4E17B10DB9DC55FD763C0255020D7B59C2D2DFEDD7AEAC25E634FE26BFA893AC893028A45E3910FC48B7EF98B5BB6462E02BD40758B66451FC9D5EE544356EBA225EF9FAEF644BDF67AE3BFF765AE20FB72103AD7C79360FAC65F354BA92DFA91B884C2EBAA0027826B516893F854922609D1A75AEAFA2DFA07D8C31CAD271BA4ED475C628F7D9A11C03E1E6313253B13F29392E615B88F0B55E251AE3852B19DE4DC870C15A1C33BCB8F7F1B2B6DC369CDFFE1BA7DE3453FB087FEE6E04276D5511E11F8E0B2CE60AD1F4E26F046FD5C0299B9E66EBCED854193AB1B134D0A82D187306684037C694CBDDEFE5946AB2E1E6E0739CE8258B765F245C84DF6160F562333CB1026C59BB5E6BA1E4F8AF609C46654081964140947A0C5C1F5156507882D73008752DB5971C4588DFC7374732D815058C0DDE7222FAA564BF9C3ACC2E49DD5A322E8195E3B89FFF66D2AA6410BA9D9D7DA4331E4518E1A75622111889EB5DA5C23C738276282882FC8FF9DD5EFD5F67A596A8117663CE5A4DFB2EB908D2DBBC152620B798E2A5905307153FA803CAB8798EDD95163ED1D344251C6B35B73A25A1D1C58A58256EF07DB8B975E535982A3BE81EB311612742B9E72A57A2FAD2FF6CC1E78A18D6A87F147C1594D38A29AA8BBA98E693247F4537E6FEB9CCAAD19889452FB9A6594263A4528E2F24FAF1F5BD3120AF211E63EB99FE885594C6A57CC295CD21FAFF210E41F3FB7B14926F727452EAC549F3F14FAF02879301D8F54510A617671C190352C03F51B11BB351048FB270FE5CC70A083555E0251CEB6995630291906A8849C210E43C1C4D9B0E79FB81781EA0A1A760D5CB08B48FB50FB600FD5BE928B29C9C6DCCD2E6F7F726A45044FD25F05FEFA4AC31B6DC2868F45D17751E44BF3CF2D0ECF1A592B5A1EA9B6158675C1D1BEE717E14A510E307BDE37A1B248F55F4D30987B360E2CA9ABFBBA307FC5D3BCE32F8B7599478D30D36E1A6C3D2BB42656144F108C6E2663D0CFC6CD473D0B3BDC57C667EDEAB556B598B9DA8C8C0A8F453E0C0795425FA3E5BF00275746B31B265D6FC7FA849C829358371E04121A2C1527581F7C5376C930E149F6C934E6198DB2126CB28273788203564A999237772368C5F09F49E43FEE4AC5DC9BC205B1FA5CA1D21FFA2EB6B411019BD65E968597C476D621CCB543776870EA0F3E66B02732332DF819875D9000EEA798CDDFED9A6273A0B5EFBB6AA16C02BE7A0654CA04D5524E58CE879FE0D4F7005C69C1B08C90F8A2FF9F2BD7078B88A8C1A46DEB68CF128696E7B5EC5F9BBD5F6A14CB80A0E8E14FB035307AAA88FF63362CD39BFC0B9BAFCA1BE2266ED5F7665FF610CEB62A068126C6F0B051B1A4D +sk = 481790F5476E7FD342D746C51113C172751930E51FA565A304A1EEE2E2AE7F404D32212F5959A268CCFF8681372F0E601E67B73C867144BB489F6A2A8110D0462DC68CA0D2F5E9DE850FE46579134FB69B11C8754F81AE1A38F02C5F6B3BAB85DD518562F91B8E238EF2023BECD1B976688DA0880C04DFC1514AF065442DC99D02070416377041855573078665324067727221037340108665482634487256031358334515653864341602447532567132881610516086832803200258387686813555701314854240334741124888800442750613071038401026260788376172840010703822471765217881611130333263644003137375802250078884437206711057004187145125747068874627032241204111518723800283178248681380713072870508656276314665586253858130652236407268803810077426776688728488112852727325068852752706180332481182263581662430755165843573845140626188457426830375051254067483061338881317567366642815263431060324137103571417514157453167300785453431505632000231635135548438387402813017360446710033825113674707640348605843464860363063275885243765888167305251048771720647683784862684414184483431610125437218463146827848471455316286342616573576758105027660561080654672516385472542867704606106576772366181867747431060116468061487480110516361005140611264727686186313140836620512537463204024701276175018838362543644034047816380547376008156228106424277263853635148344485234838053266102361645457540015421166704616608022043361137517681876754068132250676362326351648115541717722770812623578248555173376300276636468148685755316220506063565351367582384416855686051615614486404663836785250268055743564878238728586833441555352427268582641102706012441361437650426447147165212237144025617574288343435464003833270527375253710543516335245244024856244512020468033084000572251515737747807350766137627120704751776882336137010807848226500388601318031126113235800632480235574345184071156314477218538634303500880486264525316806401388033265518600352714113828215571228315555836536831644800225332117143113708265107704840620153840113055460378155580457480338723074155653750806764283168334600602435476122436231381760478665847382704561862174772050520582020111376571015047618823701841833466614456143145387603750734506011217635526642137852126251675468148815023202708304027778027063044724742645864374804411138530048204374758413630215863718713635310816116145262505645042003488141625418842802741174822304208368058853318582261611042168381634266072373717307465405112218385732820382433665505258742315433118870284344460237072701151852104620751184768406840756200588148033266542683863621168225887618365148763163214753027618635301323535166170076115240837557573782755372847823046024821836215660815382758315478013873085470280681623310180017157174128007832351332664521306736440860434268478225263780755131352113356440625722451505558607201347173663708581207520362237327044616433184424360832364776302662752224302560276738413516834221802444176364808304520345643642457356207201760201573171361166504248064180613387431020203514068176354805127645435033218702728306667865524274614332435732744584244767152860757443873186845601178050224357001451705054655746052073737045523616211748323740378824358674662122612615537570080502554101353588826634074264305232488197F3AE059AE8F576FC2AC011B944E9FE8F5E0742DF7A1108FA972198B98DDBC170FBC213D3A2A680695E4F3FA49DD8894D6F2597EFA4B218DF15A72C3B215003A78F6BBC64DD7882C24BE5AF3F21A0C4DD667880F09AB81BD3A3E2D94DE1B141FE0BCE1BA603FD6D6D95CC65A423ED4A457B8A743B35AE6396840592E5DC90BD251E414085B94698F041E5E7A6F13B7578DC86766C2A065EAFB9C90F46A8C825F6C550396A06E33032B9281B634EEFBC838CC872240722E860224DD76C77C5DC88499F87F42F81BB22ABD1F0FF0AF4C4A1550EF953A08D168576902532534A20DFF36E5C323E1CCD5214A16C5BCB2780377575EE417632AD4C36ADBD80188B6AD6C21F94C9A7780777E2C25C3E040B79CB6104AE77130F92692F5E8BD1637C403238E14EC26D19DE3974243DF17EB2BB599CD50587E8569C1916041E87201855AFBA752AECCCB1C5D80FD7331434F4968F97C87556E81A49EF7A71606ADB0DF7C751DCE92C2E09496BB5C2C7276C31364E21480E032048F6D0ED6D65E587F6575FB128292A247BCEE8BB970F5BB8436011543A55717196913FAB77FC57FFD9453307B308B62C56628D9A9CDFC2345EA738F202446F5FE4F6FE733850473B5089C1E1EEAB8D41B5A0B4A3CDDE7CE2C086E67F605811EA907177706DC3F802E9AE52E4B1B581DB4C8674985853B7B7492D96F5AFF5E1BA2413434CDBE280985028DCB44F9453FABFFB1437C7A00CE425240EE3C450024BAEE2D3E106CEB5F1B6F97F47E7B867134504A0CD53D06A97FFFFFBB6E9AB5ABABEB255ED3F35D93C8C10DFB33F43600D644CEE6D38B310C92375A67A8BB371356BFB49EA9C319C1DCDB0F9CE29F32E1564BBF5D71897204E5E4FBD5CBB72A05EB66B6644835D701DB590A43ED6F8A9D6E91B7386DADB68C123E833BE474ADD2C34010CA5362807DEF5F087E88223FD89A36501CE4F2FBF8DA944ADF4E427640F9D10F67A566C45DABAEAF80AAF6BC43AF5FBA4002EA8E8DF91C626DE9399AE9CD7EF9BEDA35071B85780AB202B96DA09C27AC55AC68F7EB5BDE052E9C553A4B43252B8B51F160B49C1F3FB24B28CEB429C28A99D768449D4CA3B40437274A36B9AB5E8C34B4361126F6E0884EB9532F09F4600143CA33644470C915AE318020BBE2D8924E03F55DBA6E0BBAEFC411D5F7F70566602B2C3DF4D0DA949A49F3F77EF247EC4AB3554FFBFDDE25855BEF3B38C8531ED4F492CFD58AAA102E89F603A5EBBF869BEC01B86F2DF152F610880CEB3E7ADDB7DFE196CB3FCF45988058BB73F7683A88C69C86DA823279E6164ECF5E960902D1EDE706BF3840E307C0645D2F1CDCAE3332E9A0E9B40271396DC5B8C521196A5DABD1461B61DD91BC161D9F1F226D44C565DF8FA9EC0D5CC7A6FD5958AF1D28A0E87D4B867783DF60AC64FE07CA45F4B65F63F979825A1B5D82945ACDB374AA8D8847210A7213DFCE2FD57316D350AAF9BE107EE5E3A98E6E23C219E42618FA16B5869DA84B785EE873E4756BBCFD021140E012C65B0F9DB67F1D52469D8E49D382F8B5D81C5446CEDABE3E3E169E117EA089DA8A6C9BFE7AB8277904F9EABD1140F1374CF1E4BF754596A475157D1612325919FD47D1CD92BB8814559E6E762170927ACD2C92D8C13045616A3A275634858AE27E0C5A8F8A8F7E0E3ADE5036A7AE074061E48C469A5086DE903637C19A5D997EBCA3A16661E5FB691FEBD216847899CBD7881A39AB8D00C5273F7A1D1458E338317E099ADC7385E6C408A0DD342A550B8D9BA68C48E97E8A78AB47F8B0821671502BBCCB82299A7E940585ACAABD45E4F24B760CF09943F7E9AF202000C363C4165ECF34B296E538BB85160B6BC117275854BA207718E161EFAA836A4BCFD267D38D5110444ECB5DE722FCA7E571285BEFF5126EA04646E55B4A3302DC0A385C35FF89CB7094EF344A0BEEABFABD8DFF1DDF0748A14E3BFC45B317638F4D08074E68BAB252D09C12FBC1F866486E6AE7656E3685C6A4192ACD195D04FCA6A1C2E51421852A73D0FCFEA11AD9E32567274DB87196041FEFA2F9AE23F2C66B8E21238266FF22B513B71506F2D15710E631778DD65890DF7003F85A63770417BF2F5288D39C8C91D7B3E0590EB104EB4F46CB66D332575F83B2DDACC77B35AD1ADD5E202287BDF50433577CDD913948BC1549E2F1E3705A2941379573F33678A87FCB4CE45876642B5109CD0390B69F0BA58FE324CB41F3EFB37AB29DE42CB2E515ABB4682741DE9AB9522174F3995CFB58D970F62530E8931BAF633C2182CEA39FA5BF42FF20A16827A7313E41412A808A46E8A67724952CDD6CA1FAFEEF571FE835B492F8C1A2020E05E6526F5DD63F5843F882D497787BA403DC5ECA3F5ED097C38CB23A1B8BA1BBC226B2D52F03514B15F2460B284C4F63FD4B934B982C85F56E283A8482066CCF8E93CFF6A968AE51D1AC18D19CEA5731D1AF49A5E7136B630F2FC5486BA0F08D822A3B2DA426BA77D114B1895007C64032662060FEC4E61321C146603CC3908D4BEE79F390247AB2D2A9EE35DA4CED181A7A8A8EACB0E8A8DB91DFBEEEA48A42C609A08727837C8B94C3DE46625F2AC7A3AC12A13691D6D93B2F616F0CC7A44C65A066DA9E24DA721691E1C0BE8A9BEBDEF3D944FCA74DB59E05ACC611DBA2D7BC67DAAF5FDF92009E2A651BC0C45FCAAE1C308D26B44FF61683FBF406AC8201B12C059EB778DC95B532E83C77D1E22B604410BB35B9B1C7B3C18A5A174E35E4A899030F876D6E1BCE451E986854711D2C1AE58F4D4BC06300CD0A58CAFD4296E1C7689937B8B9E8D5B862886C24C2E03E9B3BB0A12B2C01248698591E631DC5DE469CFEFEAF335F3D3BC67E336B6C7AB0B180CBD6FE2BC4FD8FDE82D68C05105DC63F5E143B1EB20BB0150C0F636E7B12026A3773A605C91F7E83D22365104FA26BB530753510EE007B677C88781E65147D2E689001502F7667E58F8512E9F5637EF4CA55D48AD1A612FE20B948185D366172C108F33B41377292A4F58E494472FA4F411A72DFB413976E03BD871C81EF026E79B73130327D56A4A1C032CA3ACF6106BA7B2197BCB6E648341930177175E7FC3C1B1676544A335DD951AFA5915E3B242479A2B9265D438ABC943B5A8CD7AC42823B1923DAC1F0D088017849AFFF4A238E63C3FD1A92745317B2DD691359BBE3979EA3EBE4029C69D0786C0F15F476E13191C7569EAF8A5FCD21C7359E858BA77D01606C917E19A91B26632925DA5A3A23739AA65E0D870C9954BE40D526FA5463FC60DD7526ABCFD3012CCFD9F3B44E0C35EAD09170C001EEC71C56496F797C6F9ECBDE83D2004107FBB768F0893E01DA8AA19DD56916A495088FE428B77709C30C7FC0DA3C222315E3E7B5AA746F086901BD6F48A9946B63F6683136F82D321EAF6EC9195B52C03D2BA85F308A467A545492C87DA08675BF882A1A051DAC31D122647F92D8BE6E48CB25BC67C7606D100F1418B3F451A36F760FA91B821FAA39FE7C7558976C +smlen = 5685 +sm = 530300C770E9B652A385767E1FDBA7A2D417A4536D2CC155F6CC7EB50B2DD6254C775E953B9B354EAB8AC3295F98074787E9407302A4AA4FDBFC295E75A44A4A0C1DAEB8C08D4F14C44ABF7BE689176728DDA34983A21A47A663002EC921B6BF2E84F46399E5AE05F20E171EF811FCCD185B4AD625C683E3F406C11270835D840419F4F588B6121163285F19593AC3F01C4E59D04CA39968A8B4312AB1132B932E00AE8DC6E897BE6408962A225FC6D48F5D363A480D2CC36D2E72AD21213E4BBA225A0401F8749F47F13D1D27DC385D9B7CCC2019BC4BB331B337C1DA0AAC2AF00097ECEB2ED79E8469D0AD513CB4D8D8A244A05EB319457B47D633F3688DF56FB4A1023628A8C89CADE846E572F6A6D4FDB0A5FC1D50FAD57A81964CB0C0F7A039B457E043BAB0928C2BD5E665A9AE24EF2A3DB9EB16592B782BB18B06011B2547893BB71E48B8C955E91AFC9567E7BB97CBC3A9BAA9C9AA76747163EFADD35AE14D546E40442AAA60B979B62D915FBDDC704F7E9945739A2F5B0B9DD315975EAF9B80CC83ABCD038A13507A90FB95561311546C6970D9A49AAB2A23EEF13E117EF783355D65D40C9F8874AE1919E59C39C662D9F45FB7B7AF05D3878AE2DAA9FE8CAA7AA2AF7246E3601F1C6AB1DD560010E5083AED63704809E1DB4FDA92247BA2139D0B1992D3C54C22C8343EEF3E392C869F891FCCE6D5D967D026FDF0475C09534EDE2B8C3D1CE2887AC56DECD2ECD15AD363F73C61667E4AE17DDD38C3B92D4A7384972F638431C75EDBDA05D3C04AFD63431EE96775E3A9666FEA1421FAA0D1BA8EA1A8C13AFD418706897E5B8274D4CD7258B14A0E12308E5177CF7A5E0086F2A8D51241430C7F7B4AB248516A9FCBB47C0E245F3EC4E3C03ABA392898A3FAEEE7CFA9D7E834C20102DB978F97899C2568C69B7C216BB19CD48B2ED77C8A54777F30F9F3884C7D05875364FA01917CA8D49A6ED6BEBC265B3A4626A915BEC5125378507351D6E2F5C9135DEE7139A2F725570C2BB3A97F6C1CBB789B8FDF5686F1699B08EF19D06F443D74B2294B39BA82FFBDFDED5EA79E37912F4520C8D64C52324EA3D9D5B74A3F25D950B6CEF09C696D0797927021D9FBC0ACD52672E608C3A35D1F5E58EB0C4F649E3BB2719E8EB0A42480B1CE725748335E9FAB7E668054D4B7BDD8B21FEED26B85E472FC53328BA5CFDB8962FC75E6E42891E80BBC82C3673F7EC077B6DBCDECF978AED97B73850A5DB90EEC1A56EF3A73F356D3E2D3DD53E1EC56CFC2A14F3EDC5EE83FF037C076DD765D9A57D3D15EB271532C4E738151884D685386EDF05604CFDAB46FA4B19D692F00434E5873F4B6A930E130490AE85B7DDCD3A79518F465B4A705BC6E296889DE1113C08DC2DD4821B1BBF8701DC732AC542B0D4CB0F0478EB345203CD0DAA770450105085AF12AEBEAEA10C18E74478EA8652234234ECE821DAE1FA2C875FE7978C156EA0207D5B45D5A67849363B0A7CD954D2CDB0116CBBD7FD6FCD2A2B5D488BB6C92D758D912651B88343B53419B14D91059DED3C955B5C50546B9C57DCE22EC95D04BEF4CCAF4D22063F904E22B23A1F4F409A495F4EDAD4FDEF325ACB3CBAA1C2581790CC2D5025356B8521A865521188CF1C29A60D545E882B5FEAC3510828B117FE76A8F1F0FD69C209EDB308E088845261CBF53665E13C8AB0191AC5C8C669B27E9CD41E0D843A9B6F4C678DA11542D45C33F5A0130FA13A080B0BD8CC54ADAD08BC60D1DDDC3F9B32C2E92673B4E20BEFBCDDB1A949E1F9444BB18EC10EA9F0738ED32934B1D6116EEF7A6C501149AE2C1DA97F09CCE5C3FBE2A43371ECEB3049D7FC3DB2AEC7369AA2F84DB21055347979B94E9C5CD6F35D9546A19D3FB3BC88B2162BB2B6F04A693389D21A6D713F78E9BE1E2D5BDCD51F75F2AD9D423F7C3194B4B08D405C29DFE35AFE771C181757BE3F86F718274025DDCE86F68233EF7B98A5E005413B0223FB4FFF16BAC205F2EA371929BC30F8893F1969AA5330ACE69137AE6208ADD0B3567C56BA559916DE7AAB00705232DD75CA9EB211A2E609938141922AFFDCF1718E5DE22965D1F6B348F19233EE61D80C1098A5E18B168643E3D4A56091529EC9DFC6993EE1D1BC362EE2E9D1DBA0837B605D83B4B9AEF9B9D5ABC2E961F98749B8E138E550433B53738EA6B325CC13C8B01917C46254BA47FD53EFD1990E30C2800D32B4B7CEBA43971EF89F751417D70752B60F752E71CC9EA72B3F5609B642AB90B0BB5FF9FA67B7A1230B81FEE5F2DB5347BBDBC9F98DCC33840504C42A5E5E99A316FC395B0EE76522AF94E37505B3B8C12B01E0D3C2E5A546B9F130439CEE9FF12E4901AEE5E1B2006DC2AEC4B8DFC66B454C943585845EC6F6F906C9E984E6CDDFE0DA5530744F47A6B270FFD4F38D441F83BFA04B82776444CF15CB758F735B0FEDE49356185A6B17DEBD35DE4DD51CB465ECED3B43B38C01790127F2F4C4D19204654DF5AC319B3C0BB8DB96D6C7BA4B31BDBE7757A50FE3A02E53423581F5B32939D49876F208E990CC3D1AB9DE413DB814B2082323CEA4E639884E19C01FD38914B62DD05F11CF22ED30F18F6410ECD8D2631A0B97634B3A295E8C37295A71229FFE6116517F5BF2F9EE15D765F2E237E20B3BF87B95B0086A962066EB09EF26B9580AE99AF47775DA0CF904BA3EA6C31AAF87FBEC37689B67791843CA3D46EAB4D3B8BDCF8D405DF2C80A384E579ED9D0E156A8650096983670C8A13C8A6A4C6BF6D94FCA9017FA45DB3EF9C2946C0E3028AD0B9C7BA89F7680CFCD4503C4210733E656D812FCCBBE64BC45543B95D36EBE4109A3ABD68268FB93E0D7430D74680DB005381BC0502BED6C0245458CF0332DDB7967BC3340C59F6E654712153EB71312506058EEE6E8C2A441A68B37553B5646DA7C4846076786CAB2839C4D8A61549336455128FAA33C6D378249AC69F1E8CE83A58D5B64812BD465AEEE21CC702A5657D5DC9934D82E7873C6806A2FAF7E843605B309E0EC3248BD964649E41CD2253B54BA4D8F25EB9F3452D7B50C6608BF625004091134CD7B79D16643EA67ED89C2920844D64AB04BE95080A26EF029C762281B2D6172AE82DFC99708A8623680A071789A2368F01F00301D742FBCB32EAB19CAABA16756358C7E8DD094EB387C63337B8B22654449DBB921E95EBDEB7FF663009DB9FFBE27438AC4EA722C257CBF3A9C2D9ED5A140BD2C0FE6F8F84B4D8740696173D104CB42D33B656E55BBE3547C6CF656F1DE464821DAC97B78F135CDB06B88F117AADF3B0D85107961A29F2EA93B69E2A3C9B67D8AF57B21648B2E7657595A5940A8F41583064AB22903C44E131C6DA0A96A7A030C09A03D2E769FFC6EC47182A23CC494D1A46609872E52DBB7D13139FEE970A95B6C8A67484EA9B73F7E2E571E53568F5A1DEDFC09780005961561470CD7910DB464A56C195C28492900520BBECA826995E65570E533B8DF0242B1E1BAE53F35069A98FC1AD12A41D506404DFA238747A87397BF068A6C6C78BB528E705C5013B79EE382F749581E5B95DD04F4D8157611B55495C0167EBDE4375B8FD281FD51EC96A80E36A6C1EE6C6280026BF662671841DF20B7ACA66759BA0F6676B802B85BCAFD996A36003686A378A9705A7D32F1C21A99646F6BEACD4784708B02B187E5303A0162E54CEC575822F2C733D28A7596FAAE3261775C0C23E1E3A9D34FD8B0DAFBB0C062567EF08226B2E92A507526534F3BC6A5805544039E2C347E0B8846964D3EE1474B13D09CE48FCE0A041F2B1637A9AAB7D6CD8D2A84F00E6FE24475EA48AF3D91352F3F52F8FCB971448248D229FB209EEFBC734DDC1C02D614CDFD433DF188FC6A33BFD83F110ED41855B40F3996487676B820A6E509F699E56E5734137561E81C55FDF117AE08C640C282F00FD2EBE63715BA92966E7AF268CC5C20D34AB66E34FF9FD092F5DC7F35D9A89C368643C85C4B393EA77785BA2BAD07DB895A9F24249F3DE1EC10C4DEEC59FFEB05C3D774D885A3494A629BB3D2E6893B72894276CCF498E210DFCD6C3B0355BBD33DDAF62A504C78107EF3E5FF9B2E345446DE1B32D0A7099C66F61F28C7E8F08E59975E4748F2DBC2D618330235BC98D756A2975C84490E46E0D163499419259C5E97CFFDD39FFC441F438EF13D26B8C4F99B9F1E3FAE3DC6AF0D8472C03773FC276AAAB8324D3D6536B2425DB24FBD52965CB877AD1926C8A2CD8C967A7A7B339B5865B02CC8456F11F72F0623B1F0374C368EDFEF6A9E9A0D003E6046BD480A253584F06AE5E7B0EB6EDF9D4CEBF03BA246C20894A4BE2A26311AD000CECFBB4DC4F650EAA5913D84EA39DA04D01C2AF190763B0C4540B442A146C936135E778EF0611FBDC471681D7B3761E45A0231DB117D32AED5D7B70BDC6DB275B51195AF48704E26C8F1AC378648A4F85813EDA59DCE789AA0B29B02503628F6A8A41E5D33D5AD3951D47E5FF09113A60752C25541BFA524EEA6371A38A16271E5F4FAF61B6DA3639960E711FD2FFECD09BC324DC8837F5F391FEAE2F87DBAC8FCF5263F50395AFA3102939AE0210131981C0E5EC060F13151B6E738490EB4042484B95A8FF5155575AA3B6D84A56576FB2D0F1000000000000000000000000040C161D242B326A4FE723BE9363ACFC000705A10B6CD8A7B25E99A34B4A354CBD6F50550BED30F6C4208490B4194AB79B24B093FBE132C299DF924F2FFCC2CDC6C2C9019EEDF4B72D7F0817825BD787135927102E1DA041E9A78B501B42DCE777A79ACE604E57DF11775D7B87E75E5B00ADAC90D1ADD78CC5AD348C7472EEC6E6E06F737E77115A9509A6AE6570F738DC2F21314A7CCB9D44ADD6E1434CDFE3614BC73A6B468F6691B60F4F2DB103289A90C4FB2BF5AAF87826D2BEB0880FA64E07E9BD30D4EDA00D6BDA01D1EB22BCF14EE797A859C9A0D9034E8C5316201AF91388C47E1DDF061C9F45E067A5F60B355C98F8734559B8F1B82F47BD9CEE0224A1D67D40706333523C34F3582B6C8CB47BF7D0E4FBC7D7CF3DBF21077E664FD59998338F4DD4A423C3A145EE1E994AACC1A48F81A7E9FE106008DB93A6626B8C8505043AB864D93AE3972675E69C3825304086AA3419216CCAE7F7D5117739E99D8F4A0B658148DE33FDAAEB9967EF56677D2028C3B584C5CC1C096F4DA16799408B2EE2FC3482AD2F49293CF4097A78492470099BDB90BCB4FE3B245AC8B3C53E05D7609E34770ADCC147033A8FADE81359FF63C3FB90C5A498C98B7A0E5EE9CF4D287759ACDA4BFA3965CA85E1D1C1019E7FE6D82E5E66A717F94890277E6DB1EAA6F3291FE1BCD7D437094749FF5574B8728E0DC21A143A14E382937EFB7EC1B0FB3F6F9C0F547F470E3B436DFC7986F923BEAA89583D8978C433E0CB0C4E98516AF1AC797C778662455A57FEF45BA2C7865C1DF5C502EDB01C8CC729468091BB96BE9DA9C298528187867EEE9A06141DAA15F60CF719DE2BD15010550B92A41F12D8F38B54692589AFF51A9D5E6047A0D9B707369992251DF31341A45B01B05FFED8ADEE5810824F903EA59F14FD500AEDAE797F8BAEB470C0B14C4EDA5C687E4848A85B30A8E8F59C45D4C9F0C65FCCB15F4D4209A55722C29B6CB09AECB4E53FA3AA602C56EE3BA6900CC12889E7B87D5EF283AF1586764519A30CF60833C82F0ED15E39A8BCAD5C6AEE9999E63D399C5CEA10AE1F53B04858EF7896AA29FA541451FDB685734C39470250545193CAF26C9891F7F965904AE10E8566BFF9B2F465BBE13D6EA4A79586E68844B9FA68B2F992565C8B0EF5FFDEB5878CC12A0571CA3AEA50ADD29DD06E13741A1AB215BF487BE7735D1634332F47E037253054A21E0AD8D8F011334CB5951F833D4D344D632BCAB7C373CB7DAFE8F3D79E7E13BDB1C6CFFA474A9FBB46F5736D55F3466534596EBD22B29107A8FA50C1D0E62F0533E343FEE038FC0C3040A6DF2D318BBC8420019B1B148D6D1DD2FE428C2FD617CA73F224EF9AF9BF6F83CF1006616235471B69DD4EAF9F32529EF3E1DFE6765E61E246B519C702351C9CD66C57065EC78993D793B082E3685EB06F2530B07862277D339A52813C99EBE16C06C4C8F547D9705850E770982E8FA0275A52F430FF2422A115ECE46A9202CAA0195789532B1444F1507AAB2E4303464E499989F21C7D881328F18DBC77D4B9B467CAE244A93053C0321DFBF815DA28B6EBF483EAFBE634E9947BB5383FEE3A31BC03A63FCDDA5E3E46D5D3184718C348A83975728714351DF43BAF91787CACA346DBB819602F18A4C4FE90C4CE307984BCDED89CD2E4AEB66318C10D95AFA5BE53393FEB981C21BB1411BB9C58818BCC141223D66ED5F35F90C05FD4848617220DD72F5E892292CE20AA9A0F9AD54022CBE94D2C86DAF3FC66949AC35D8E122B02E2D155E73F4CE24D7E85A5C301DCC173CA8EC090AF9DC7F443C983280DDA27ED4B9BC71F86E84F7AEE39E6A7E9BF5E43920AAC858F0F49A06216D9D3984CD2E3575C0FA6CE8A5E28B0F481CCBAAB450FABCE8A1084EF458DBE257CF09D8116136C2CF1EDFA6CCE31AED0F1F8278C1C8D9C79846886D48E3FD311C015BF2373F7CAA71AA26B011D0DF5A843AB53D7E7F0466CCF49C5D4DE872CA87B8895101EE0147A3DBD391BEED75FC16F65814D56CB29273A5F4E5400FCABF85040505C31D001DF0023726E9C1F7C29A37039FDDA73B9B99ACEC3A029F7C0DD61ADE7D5E835E1CD605AA8E583BF8DC99285E86CF91F4B4827A0E8956EFDE2B495A86F85E78B954341CF3AFEBE8DB71C26B9B1BA27B47284AA84E55B1C2AFEE733AC596A10186D9AB504F33E34A06CA931D7633462B04B9B2B0D4751B0343503BCB2A1893D944FBDB4BE63DE167348A1588E6551FD9CF2101B0B4CB61422655FBEB50D64CB9E87A23007A39821EC3ABA391485347624EFC3DFDA4A133C537D7CD8C3A549BB6BEF9A52D2EDF0A8892C6FC3EEC3EFC3C18741C85BF24CD3B36CA04EE77F654ED5595A0E4B9316CCFE4D2AA6B4A66B06F309337E363C9E39829C8838729F19811093DFBE962246473B7A19FAEDFDB0193F63EB85EF308CD3BE5831F35CED36D9448D0EA8306044F78946079210CF89FF78104BCB2964CE2AF9954D53885D7914E4FFA4AC7E9B3D103922FD1AD68C0A4592F885C5FEE51D52214E17035E8681086203B79B5EB176679EB3263B44EA7287262DD84BB98F6639B9657AC04E397D69C634A0C1181ECA485E467D62631AD2D9AFD5AC5B86ED4005FDBB7404B65BBB826F1A2334A481B9CD46E0CE9C414A162E84368089F24149D7D05EA6ADF40B25A708357AAA5A28801FF100F69252810188CFC6087507BB5BDE1CD43BF72B1B3207CE4F7E65A18E5276613D4BEDDAF21AF7B964FF69965C47CB03846F7CEDDD2C5133080FC632A4F0B3495B2D2751727CF7681F28675552DF2A0994E425A922BBFCF84189B8C9F43058D691DB3166C596F6BC480EFDE06BDAE7B9C2985A1F2F6441520620E193D7B94AB46DBA2A1ADE44E2B006734E6770F34B0E2122DD7F4EAF045164DEA8C2FECE7758630384C00A6B528A6ECF07045B2DC0281C936A540904733149BC65B0F57ACD9A5E41C2ADF83FD6A760B169BEEBF04644DB1314270ADF86D01CC2CD580C609E78BBCD9D2694A89F9CB6DD36B9AA2AA5581FF561B5417BE2B52F3EF2581E461CB0690782F33862C52590643BECE0A6141DC805D8F56C4F64C1BBC49A3ECF1E8827926796E5F9335DF47DA6D3E4C14795B547116FD1F3351FC55C28B543183FEAD8DF7DA4DFBCC38E224901FF7BD83B16631064CAC4A37FA632F53F004374AA19861FDCA515AF91E66186EF804366D5A1B3B4FAAA60A0C4B36B972A9579548B4CDACE7EB85F1F68A4E4255FD994C1786975E7F6F0BA87D0295DE72876BCE37146A09EDEBC0164B9C4911CE41EF4D48130A27651BD0DC315FD622CB6D03759D35756806332658B5B33E768860C1946569AA45130486AD49B + +count = 72 +seed = F151196F55A9ED88F1663AF6BD24B2CB9DCAF3C9B313CD8F0A27639D3CDAE72EA90D60ED5C7C6AB697A06185E5A2E215 +mlen = 2409 +msg = EFC63DD588A7230CE08EFCFEEA534F5A0EB005480AD1D169C386E476715238526E936FEA7136E2D8AED60DE31CC91DAE4E764CE5F93624FA7F72B87562FB6AD8996B5E41FD478AF0AF8338A7FD9AA250EFD2F2D20364E8A88A8642E8E38F38583ABF8D3BE97F14C3EDE66EBF8EBC84385CAE646CDED8C5CE8F06910BA7FEC05D828446D558D6FED766FBA347DA2E84DA247C34266AA31C328804F4E3AAF6ACBB0AD50FEECCEC00D20B3610785B9F1BA06A0BADFB42A8F43DE3F7BAC36057EE0B4D2A15DB040A8903F767F7352995C8FC3E06ED1B1322587EEE5B31806192E04B09A7B433D08CB2A340942CB75C51E0F8409F907F69C5F8DC316A227942EDF7A458974FDA76C255FF4F1A85A352CD2CD2A21507E0F37451060D31D0847528B3ED5DA3E7168CBD0302F1B03842E63B3DEC6FB37357E37FC3CC26721F290726A47AB3D4DD8FD1778FE5133726C240E7B3E398F3D809C6C469680B9EFD25DBE890D6936B76A52F97AEF3F93872B76506A95685EECDCBCE203400D182252471B99B7F4C6CED4CAC8FACA7682D0DF07BC5904AAE042479855098CBC41534F0EF17F38F1BC8C272CF72C1AC4A5564DD132130EE676E7D7EC3CABB4E85AC81945C87DE08EC60CED3FA0AB3E83C18AE493A851434BFA2C4968B42ACCCF3609539C62A4E01F8BC159362E15EE91D8AA399D8BD8D67BA1E8FD646EEBB4583812293406B05BA5BE2B1DF9620E6FE3DAF8CEBD9652BB04494B899F407C7D9ED1C4E77FFADE24ABE56AD597BD438928E05B0363D6D2685D34D6B51D71012844415C46F13181B146A3AF25AE4E8853CC7C7EF6387306C45180A6EF9E97ABE1E7D5E10115752C3071B6A213367E8B1A3D1C3703CC1840735315623901D772C61D55EF8C47DB10F0EB7582D7A043018DC1363E93F315DD984B8002EA7BF5BED38D3F273276CA577CF99A635CB6ED9D6525520793405BE27C86E6EFFEABB1E5F84A0076BD151CAFC59853424DE4B3460C673B0820D76E15EE47B6505D2D5C179DB92A44042F3631C646D350EA9721B8984660A76018DCA5C6BB1223CD03CC844DC9371D32549D9D645F75D2683FDAD1DF6434BBE43200E506ED2A815FAB511172C70F99A85FA3970433E8955B2F9389F23C10141B5779A23B8671EAE8B91991B78F635FBE8E627D3E79D91FD1E6E90699640BA3AE8D7E4CF5145F1259CC76AE50B1FA150D8338A9450A5B6B90EEC9C94318BC78C9C7715A3EB215AEE6443540D211A0556813529023E5A581623CD6D19BEF0705A5F69AAD4833A57C308144E92899AC5683147CDBD279D5C3A55BBC5E8F8E26A158A3E42F8C5B858909B024B4BA4069E26DE66460FF4A7DC92BD54AC244007B6AC6CE07A31A2AF3323CB55F07B8F480D279308FE10F2DDB001DA6C4AA132B988AD03FB63E0EB06544571F5505CF377A81153D6FBD4FA2B7562074CFAF587CCF28DAC84AFA58809C0B296E0D2594D3582C28596F5AF7500E143BE7B49C63D04F49BBFBDF60B024DABA5533F945BA90659758E06984921EFEEF79604059EB808C9FE1BF9BC5351A406FBBA7F5D8FC9F891488E537DB14B216A0535C9FF7BF8D5C68A2453A8A48E58FA7BF6EB76448D6D0BD05BD4628C4B852A236A11BEC0F67118F1267CA42647F6F2303509094C9A7F3A07B2724ABD2D9B56B71FA7AC6CDDE456EC209BE76C419855A5151EC9EBF0E0CF1B86F4E8E81B8173960F8D1C8AFFED1AC7B818AF8E3BC092E2B209D693E80B11EC7DA39CA93223E1B47C6127E8AD40A78BDB0ECBFA1F39C84CB9ECDF960ABB39884627BC4105C53EE7BCA4802B92AF60241420CBB36C407F46CC2E953D7E3503CC82287A8D68D0E673E212173D80A12257ADD5256652188C00590DADCFB7DBB6B35507B853EA5FAD4F52E02230CB3D3BBDFC43EB74780583E8DBB851E0257117F4A39A6676586216220C1CA21DE16CDFE6E1CC99EA7C989916AD2FED4A8373CFCFF02207529BFFCB7B7601317450BF430BAC9CE111B0FBA8D7DE6627F863078D8E6286B2D34856426EA90FFD58705444D0DC12D4FEEAD0FFE543811E1EF306F40939922563832D06E6DEA7109087AC051A361EA9E755856FD4E51388BC7C40C63E0953C8413AB0CBFF70C466E15DE5B089D095E8EE8A64E929D26CA3B71EF0B2360AECDFA89284CCE08C666F4E0146362F0BB84B87A49FCF2324EBB96DD941F00E2586F7246436EB66B1E04AF84482D8ECD2BC8EF9955CBEC62AFDD754A7F235C7F3C41CD0B36A9024D426B7388D3C33A5A6E858846C0FB0D88BA5798C923F9B43D14A6661C65092D5C5EC0F97D84784FA336AE6EF57C7A5D04804B96D19849FF9074724A5FACA538E32C6EFAA5209317543159272CE50454FE1E7D068C8F5FF3797A66D5F87758627AB5D40EBE1FB7CE9D69287AE7A5F349A5DAABD8A8E7778BAA26DA0EB237034A3366448280237A165CBB303BE6B33C0F11C1E56C50A84384A0F6878F2A99B14CD3B6820ABD27D2011E0C37F8439BEDE65747038A5FF7F00DAEDA094331523CDB7E10F1063B64A584D3E9F0655268F89DBEF3EA3FA4C6E54FEEBF8F0046C6C811F0767CF6FCC9B3497DB05582774047A8DCFF6A0C1B5188076E64A9D5693195075F2A05E507A5A523EEE4537079F9E5E79210E4AF056D6624D45A0EBA553CA9BC92171451970102CAB57DCD89ACEBBD7025008325C61145264F42E4D14A76E5C2F1C129D4C054DA00501081617D1A27012A6E160750DBA73BECB5DC05105BFDE1F1D0CDC837355844B291B09015FD610628513C1C86EAD373730B99FCD4A552FBA07163CE9CF6A3D3AC0525593F0648256E8B33FBCF92AF58CE26D0F036E11230879DBB789507BCEEFD2960EA320236A224EA74DD2AAAC541664FA3EA9430D4FB09C878169A8AF1E7FD4BE5E7926CB0B6A352B25F452454474107286EDAA145C0A0573361522EACB618DD9C8B32BD1A8A5923F4C698CCA0139DC640C1D5D557CE889BB69CE32D85853DFBB0F34DA2CF18CC79472906B67F6BACBF287F31DE0B9E7A01A356EC9B64653CB922501EA1EDA940089BA0F293B667F482E92438805CD6851776CEA0920CDEFC4062C9B4E51F5AA1D7FF909CC2608B6F28CCF28D574BF67CE80D4DDCCE28F2ADE0162CB66894B5B2DA0EB975CD95EE7FE72FDA2736616C8B571FAC94BF8C64ACD1642D9431118F08A62328D99B2B9D90BBC915DB764C4935951A59C369C72060CD9F4273BDCA0C295294008C0AC3A149E8CA5E8BF21042F5F21C067147F3BB52B13975026A9DF7246AFB1D053670982AB316509F2850342913E1322758ED89DA02DD79126726B1C5566C1831CCB1D62B3E271875E62CDE0DF0715D404F95F580B63923F362D416F83FE5AD98EED584717FBC2CB7D1B00101200F4EB4CA5 +pk = 40A0AE510D93A5BB64F6D765F898A368792820761D76A6993D754FE4E7FB4D5E492367C0F88EB6B924B0848FBA5CCF0DA8C2D155DBF18E201772FDC28935D5C9B2F4143752415BEFFE770374E48FAE2FD4CC89F8D9D0DA78214FD822479D9352208D8E0EB8A0D79D4DA0C5411B29C65DE5AEE8D6BB5C384F3E72B38B19C09D4C7D820DFD162462008837E1ABCEC6A1227EA0BD238584A3A348C9EBCFA0177DEF4EF3705279B36AFC168F036AE327EB4B8F637153347C68A91C276178578CFD594601A1F632F4025A3F1D53231191F5C54EB79B2CD48947B350D972DEE656BE7A338C71B0821A7098BEDF38677F63A7E308A9022A8125C035967A519213A98394A79E89E8F5C324DF85760302AB23E35679995FB4C680A6DEA44C4D6948D72368FF9DB237B07EED86EAC877C3282850F325B98B930941D474C590A3F88F1F390046E37C716971C0E143F85DAF1F17050DE79405F7B682D680A1660B4CEE8FF02609FC307D1E3A5099C023E0A807E38FE2ED5EE3CE75AC57B1F45B07AAF56A03C4B0AE43C9D2D95D238860C331C57FCB2617D1888D9EE164296969562598BA8F4C77926A0BB48720A4AEDDC29F57D6E23716CB9B137DE288CF82F8B6C0A7EB5D1C27465967ACE3F7F41FDCB00D1394A89053C27816438D64AB4C6C94B38977E9A874A362448CEFE20A88A5F78A9C227AECB9ADEC993D6F8A5868CA82F993DD377A9A5D1B6CAC2109311A2E9810EDA8C3D5EDE2311E5E70AA27C673456495CF53BAB1A403709E57A8437AF08F63F4178177EE1070C7C299BE2BDF02E47F5D715445B219CB88F3BCFBBE37F07307CCCFCF59414051A0CFA9ED8B1D51A762372CC8DE0ACCA3829C8666E65762E62D367538990B21A6932B28A9E08D77C7310B1F6D3E20792A46DEA6C6DDDEA1CA59764A077D4303EDCFD19E415DF80E937FA6BE2F699CA5C8FFEACE6988056864EF2DEC6DE0E483C53BC502DC03FCE6CFCAA625F2326ED839D79BF4B85F4C0163EEC841D861F4ACC0B3ED5C838315024D6999E4D7246E976222D9F06080211B0DB52637BF1CC2012E1EA8ADDB6F452A4964B65A48FFEFC89E4B79995B4B559EE82CE4B92D4078F96316D25A3B5DFA5504BFC877E1199B9789FD639E7558E6DF900EECCBFE9613B920BB1B4DBD5FF4035E11BB3737E69736B519E1267CAF13FE8961508720AC639440FD1865B826081382085BEE8EE7F1EEA2A03F202BEEAE9292BC6B8B64848C79D0A95572B9D29452BC640A82315EF765B2F55029D2D4657D5E4209C21BAE56D8F2EAC277F60BFE3A3900B44FF338C9EC13384ED053A1AE047E0A5FCC2DE2FFDB1BB0B7E7839BFFFA1E911ADB964D9679BF84E96C9ECFB1A803972B3CBB1F17E3FF53D0650C7EA9C41A7138058EBF407EBC93CC81C842FAED07538DFF7AD63EE44ECB26B97017F924559E0E8D55A6CAB448AC579CAE6BA3E0CAC3931624B9F07C4270CC5CCA2A92B818C9ACC816E6DF9B9C557B11E6131BEAA0C52B6B0DF742B17459131AA081112304A8B607FBC7CAB93B727B195C88511F83C59B51159E52DA54B286318C1D9A6A980203C3A24A70320831075B76DE2A649B4D1B05D154760A1D49B719E0BA3D95F7D27D575CEC4AD539D423ECA5F58DBA12B943867FA41BE4E3B1ECD70A2A5BD524D8D80BC4AE89FD3646C9F1964DCEA2B771664E48F976151E0884C82797B9E5E1B5E645BC858A441664594C46941E2FA7913C840C761E0387C0A3F61B95B3E867541E19B050CF335CFC2D5479543B4F9CD01C478D64A4AB27448ED00C38CF2BDD88BCC6B69AD7BB4561602009C3DAD78C7FFAB729E1417D3336A5BFE6AE38A6B5516DE1C1FBAF0CE4C9979021ABF5828F3CE9025FB1D6A357CDDCC28E4F006DF48437C8203CC5C6728AA6B32707C238233670A4CCE54F11485FCA3B3729590B086C9F7497E4F4E6A495DC856DB31C2C118497937E14CB65BA0B251E337B28CD5ED5F4D0B23C55F16CE61599D9CA65F18AD5161A4A12EDC9ED044BEC3C1369744484248712B73025C3F307F7DC96C10B0344766519DACD630297789677811A58BEE4B18C934A3ECD6127146914BADAF2D5E1C4D1186B685C5FECB67C75E5A5F2EC17CCDA934C2B44FD7C86B735343D72A48DEB5C0052C3C4D03C77C9B2FAC2AF8DCBBDFF482398B3882E14B082CBC943482FF994756AA25C32599CA4D77D15F32C6A7E855A188E59ADBC07F2E66F9C8636FFF418C62B5D48DF8251FD3257F54F51469BE0CEDC62C30D55879FE4742457486D80CB4C9D6F5F9786048CFF8CDDB6A234DF240A5BD526F2D0907F9889FBC570F93A7DCFF54A96E77EB24AEE6E64D7C4685AFF9FA572623E9AF9B9D751ABE3EFBC151C8A8D9DC171941819C29E9DC6F49A94ECF5D47C878CE330B11395D76ED71F5CB3802A96F4D232664F504B8B5D85CA6647046B8B8E7C787F321479B2ABD0D6FC59460D2C00B6F9C5C95A12A482448EBBD244C4C336D59EA43A017A75AE4AC3C3D4273C48DD46C8FB498410B74A2A37502184E20992C48FB9F07EFA42C9991B297D468F5D5714281A05DA4628BB6CE2F1C91FD500E76BEFB16CFE3BF794B67BCC363BD53E8F06A65D13E8121F5972800E96E94160C7E34F10267FB5643F86CE3C9AF3539A823A3A194D2A8E2D71A92A52924517C5A0463FAFAC9D5BA580B273CA63CE1F2B5BD7AB1FC69614438572158DD6203D3BE862E6850589598E5743FB9DC3A62823BF435F505F5C5D8DC181D1F57EB62A +sk = 40A0AE510D93A5BB64F6D765F898A368792820761D76A6993D754FE4E7FB4D5EEBF21059AEF7D0B6E34AC718954AE51C6D29198383F23233F6E6D2C20341ABB0A2A711C91AA728C073081F39CD2E8578FBDBA6181A5E2AADDCCB7A3B0E1E14DB7C8341E6E1778CAEE1980CFE05024399B3995C43D93A8399E0FB343F5BF66CD5283203135476715363857172208437261017115655806582678527217034276704451617168514732035725364366151875553371703156802626112578074373431268165282800261074724807355622637534725403455248265320183052337408802441737581767025760148555476075853080547067143278155656122807133121417682058281553605434070082441541424168845852646332128248152083405358601765824216023322488830620307286182752202187337105337382148643026671138774380313278544763643656746648888316330806470066428008101068648555423245372555620073132251570571270065226574660547260488375731307706558406704730113312074210602113603723172668228278782685246378613877450057158744268566725030255842265147216722460061460013867728548416008725367686438483485726610606240266863463058331638601140327500462683838008551045418463738830841813245042411747380565166065133436040513360375878483426544688234365604118550711534788676708283351063378523172442057145136205527208205824323846578540517374882411160602186135020324611250364760221526115018553521766070408417036642407534145507013048457575808308256803820184265471620532171156310123312735570330357518610734502212763038581256682125210413346328153064120108080273126623530370523848160221611424240866020384270813201484658828088480184115884041554771874786818284850317824163244617448881430430608663533643115483788264388711746753406861077716805243838878804701650377714811876285703071175733881520328334860872750003674478545604262552368457770345765742714357254654371467071436462282144252442641871287557536050152083628516831121105442330413021561731045400360266511865223387438462012273032865116107477083214873812841412018031402543712487044705275261641453313711874560657372860045521457828373257888838734884106370253225567720866088382526121261213380466272318741487720748228045836632488086450647547202671524244800435572058621047702456013164047225041645417183748466785087431388046852405114042038307637488453871100767158067072782147286810180840683352225127464748416303410518262604278078421248224464068018325230118202161100538867782124806006424861538465737173623332026306257833310757513454068571614033047282887327725422441383088178654038652720641736341681712811210847268356380318681431314844607277404470776383823366555447841322586441443600446567111263836126812185427413740288801641658126103782507175435686166657871008424580867187773440435064265658670604267382770035530173775340802071444285008288755542032531555624500066755582522106352314654685471030366534355742640728614548673076114851604645474615718123216580622568503540255437701317316121850181373242465005872011658308132563384367550487677012470735770480501547455417852816843878383181484767715166016065583116441836787021017134628230637631866845255805458824180610088056467385834838632106852778011532620665606872341836572351116842440557673707483324433436402653455360764555305568776146564375558660251661147568D64A65D4B43ABF7E2E42981828651088F9EEE6B90A9B6D0802F6932BBA6192527AC78C77E9E82DE130F9A45FB4A9D962768C73FB845449BA39DEDD84F6045F26FE35C21B93A4FA6BFD33949AC282325D28DE3ACAEC05DA75C1AA7EE01FE585A7300817AE01217FFE19B2F060442758C21DC08D91E4F08B30B77181B133D9C1417B1EBA1D3B27BD3EBB9448FB88ABFD3830A31F33961480FD8997AB2F4BF58D6926D78A845E04EA3F2861748F076956329078E4900FD8E9FD6400B98F9A622CE10E61F01F4323D80F92E16D5668F920675E9E26544510A4E5E7C9574ECDF7203651372EE2DD7A94005DD035E0E994D8CAD04C1BC154D9525ABB8E31BC347887A36E42AE8468FE5F2B8080058C09468DEA73D9A8265E7BCB212DFF328051D5ED226F4E088FE2206B70E5FE5D1DE709BDEEA76205AA8D18E293E670A09212F2CCCB1E354E47F342B8A09EE34DCF847E30D82E1DA9B7A3C544D4D6709F4F5E02260682C1C5813C8E357BA92F6FB4036B0C369E2B002B87988E562A9DFFF13FD9B90B60FFBE734D0DDD54EC770C5F2F961074DD10AC6DCF443E0C64350E9DC9966FD3FF3B3ABAAF6C75745158E1F13A440612EC5E17882537B5D67BC1FFCF1F106207A697DA8BE0E279F22A6655C33C28A36EBFAF2D7CD776FCAB45E250BE5BE48B53F2BA8C6EBE11B3A34C41309BEF4C3153EFB56B09616F31F26C12E8B4F5A4D886DF27ECE51492850BD173A818462C88E1FD954EAFCD841F3EF68DFD1A0E450A5C763D35B07AC9250F37C614E5C31EC20634D998F7C4CC09B8E2100D934F89ABDBBB87AAEFB0A4A6F981FF8D20F6E437059CFDFCE45AD40AD1882E620752B051E7B73F56E6E32B39E2E6A56ECC9A39F9ABD708002C615602D6CC5C2D482299AAB7448B0C3F04F51DE1C96D277601979FB1A62FC510DDBA526563D0BF0977DC9687750078DBE00F416C2032CA9F475FE4A1DD2B0945D0378AE3FF52251D29F14A9C20D4A5156FF04A633E33D2E283459EE80F2BB6CA4F9C9DF9D769360A9E96ED8E94EA318FE05FF3163128472D1E362CD195CBCF9A50CC64018ADE756B80B43C416622FC95E3BEC7E7F4664BE282A4F8E0043486CDA8364F497DC32F62C73FE3EFFDA3B2035337A34EBEFC89B55ED54D722B7B6779C9F712AE1C90247F0022F62FB9894818E3560A8EFDFE080CE6C74E3903BA032E069E44AAE72BF8F5F78E02B6191283EF9987A57471C70CE59D6784FE3586719C15FA2FB428F4FC205D08D4D7A7146D9E4BEBA66EBD4C0C8BC89CE5E364F2F6195AD539B90B95EA6E16850B27D0DA9B987B649C527709757B1C905FCB49B84062ED1289F9F331E4EB81992FB883B155D978BD2B67D388E902A06BA2BE20585329129A4AF26988CD850A458CEF23BAF1D7EF639787F5C14F770D0BF7DED27EE49A498EEE6156879B17EAFE1E6B059AFD1618B2B6819535A82C7EE220C144C08C77374323639DE62306A8177375B9AD9A5087A9D9C5C169D8B6A9FD95715C1B896D0C471C7A01414EC0D236D7949F4905EE54886E3DB4539AAE2EF694273688F036572BA47C31AFE077F4636BBCCC6EDC4F87BD4E1B946457D141E1EC0CE2DA08FE2256E8C91D6628FEEFF6E464CDC78A400F4E66325BDE1D1AD621334183C879C4AC6B9BD402EEE6FCCB5E0A00C4F52D704B709D51E45336E0289480FE9AA184FE2BBC84888C1545587B86A6ED37204BF0CE663966D3D1AF26DA90A5CF2A901EB559E0E7800D2AD7970B6B63762EE8B02432F01D6C9C7363EA6FACE60B4DAE1856DC48C9158E97D2C038546F7B2BBB259F86BA497460F5050BC79FB51E8B5C8BC131F4BB65C022271F8462E7C5FD37A147AD438758F57D9DE1897E2DEC767C2F08586D23902BED001F7A3A361059FEFCBA2BFB988EDD5616912E05C71611420AD3FE0C97321AE6C1BE60CACC4D2DCC270DF50C7A3F3E5E35D812F4DDC7CCE6BEBFBC5CB0F904B7A69FCC8E954199D1CD3E4ECF6D174A58825FDBF5F2133BBAF08519735E28117FBBD3B079C218563BF3502C95432A7F4E166A09ADBF50370DCCC311163099FA3C7E56356D7BBF2E5B8F0CDE2A3A7183221EDFD768174E98AA25E9C155FF7C2CE68A8BEB9AB461146469A90C527E098A787A9ED1ACA944C8A0BA0C552BDF5FF5C73D27FBA30B8E5F2560B7590920004B32DF335A630FC96B8083D85B1361A2F6444016DA52336EB6A0A7D14D3E791594BB0276C9B8782A4015AA34F209E3AECB8D665FE51F056F802F900C52FA44647AD3CCA0FB3ACA2C91B5BAC6CE3CFAD4B42FCEB6B300177B4C4AA6A4CADB5B86B57D1F9631B0C140707FC515FE384F5A51AE2CF99C2F747156E5B684C9EC1D122D6A0AC6B0878301FC65281ED35A84F618875D484FB3A189E3BCC20E83F6AD009F7FFCFA35EE656AE58F2B583AFF9C3F99FD67E02535DB014914F9F6E013E7A716503F98DD7306136181B0318BCF456647DEBBC084BBC419F88950AE49BB2054B78621B2C283099FFC0883E8595BA15B068DF77A21C6774AE2BCD25722446B7307839877329C93D9EB722C4BD95F99C3DBE120F98A23B32F30D1589AF993CC4AB56B0E1BAAB2676F28DC34FD7817911D771AFF1CE11417648915558DC816E8DE76D697CBA0901A5F1D82F9C0C36C21492ACA640AD8E91D26268ABA92E8FDB1550798A9CE6D340A0778A8B867AEC01D9E3536C882B0EB31826FB084E67AC33B9C08605D616FA59E83A438E2ED475592B3FA0D8EF47BE92404C8961FAFC45017279CBB97FFCCF2B9A76EC1E81907614C8821554B66AE8153CF85E3FD0412B0E8D6EA4043A1691E512882AE879C8839018022E587B5B8BFCFEFD07D79D09EE22C577F80FA3C6152A012E569FD7BD40D45956F1AAD97B33472522D07D9834BBBD249A55B768ECA3665C7B79AEEA62A788C1EC18864EFDB975E0EA1C38B28B7D285D351804A7ABE9BA408695BAA384F72A0EC182CC7CF08C53B03F892C065BC46F3B7D7F3638AFA4C9DBA0F147662DFB9F085EA9B51E54E0B0ED5EB1BF481C2DBE8A2023C69BD4C0F026022D7E6FE3BA5BDE4BFB095D03A0FB8731F60A8E81EE3BB3AB31029429F6E794EFCAB6826DA05F10404158666ECE27024DE9A171E6CB9F57FCF6B514B99585137E70DDF77A4AE05FE36F417E4A922F3FBE3643ADBF686B2FCEAD65765B8BB87B998BAA18E576C87740CD16468BECA197372700162E00BB3D6C7959AFAFE25B798AC48B6383467AD821C5992A8CA5F812ED5A7D088ABF462E775F428D340E5D54F1BC0A1CEB1174C8D700D50CE158D1E1C3C6EB0C31DA631C5B1C0FC50F5705BC4D486552667C7FF3FEDE7722F1EBC3593D6970427EE72A186E36AF751B21519E413102025AA9C85D82A1A07A6BAB0FAE4C49BA022809E065650BDC0B47574FB5EC66BC0800FF3B01FDE027E8D8E04F3A2600866E61E53FDFBA3D9A97B9463A1D9AC9BE3D29652A9D4C49371A73F7EC64100C475EF232FC4A0F1D9AD1CAF239A2F21B29D8E62601EE44D0460F208A230F +smlen = 5718 +sm = F5E431B784DB202D69626F4A155020F4A801B80F82DDBFC648FB312ECAFF719749C15F39A39A3233EC7279E93023CB71ADD5775DE6F90DE4AFE257767E9B469A02571014CEBA6711D10A259ABB80FFDEC32A3829391319E42DC44F07726B9F00C6BD9763A9BAA17AAC0BB48E5C7D7AFDC0357A917DBF2CA2AFE56476F049BA147868E384746C8B698F2555C3FBC89F0991BAA84BCE59286E1A67B7A1BEF1142F1C1BF893C0DD986CE4023CFB725453034D4B42594D6192DC0EE479E48AF04ADA4827284C474E68B2A13E08BAA33575EFDC2FD68C3DBCAB1A4FB1BC1261D9F0C766493F1E42EA31D243257FA7A51AB761CF25A2462550E232D0C85E5A1C7A74A94F1854B7757F3F9E59353DEF1FC1F5D84FB74F45D976225376694EAB78FB29D68B870842E67658E14B2D09D01235046FDC65F99B6075C47C83534263AE5CF7577AD017C37A3404FD1C8A4ECAC359F7955F66070D8002EDAF29886D80B83BA53041673246CA83FC3473BC5607BF7056ADAA80351A069427BC4729CA1B4028763EDDCDF8319C8D29B2817CD36CFC56FF90769E2F56859EAD5790195CEC9D9F6D175BF9DEFE5932C40D13834E7083E6A3EC28C245D76CCB9AD4EC450BC5E4E5F38FCBF536960DD2DB5194A4802C9E2FB0547FBB793A48AC47A4FF387A5374FED261AD2F6B01B7A4979A858FA3C4CF890B28EAE651F234BC02E52C0524AB5D1E0B2817332B0EF25828674777A42D89D600EFA9BF11AF0E4B3F48EBA7BF0F6181FB9C7131F08C0E38ABB459B8D6E9A469D311DD0E9B803D3DC2A09F791AE92CBC71DCA4E59C2472DDDCB38F663CF4BFEFC9E592CCB6ECC1F38EC58C26932AFFD0C2DA4DB79134C86CFD8BC3E3B3B57A67172BBF1507F40E0DCF74439DC06042715A037F76BADBD28831C8F968FDDCC2A8CA6C694326EBFE53A1D2133AB1F91246A6A6AD4ADD14D2D4F497A331792F9D91C8128A56D368243075E72449643A677D195DEE3ACAED466D59A0D4B42E02B6E887CA7EB98D033C1BC56240CE0F50E6A8FE5C209CCE344EDE092A6AFFAE949A4E652C404D0B104D5A1900C383691C5C1ECC24A8D78D743A882790F9EB6367043C8FAB2A542382A751683D0C9EBCADFC9FE0D19DCC94FF0F7046D3B62482821B11CF234CEC8DB4AA45190B3CD3D904A5B9C46F2D9797AD32585129EF682DE44BF7C8B750D003416D756F79FF8CEDD58EEC9073A6191C78464B52A3A7468119481E8D9C6AD1E5868AB3A5D0CDF6940A411E124CD60613E58B7AB6A41AEAEEB0B2C541640A6AADA0661F40BE145820D024FB9C0E4B8CF2424D5419E6F49D69B5CD833CC35B7FDE6992CA562F5EDB2D5BE495B25A70CDEE614539470FAE0B81850A5C23B13673D77A3E4D9835BAD3FB2A6158DD38E78477A0B4315859B9B7A1049063240F180AFB0D539AA7A24F3DF5ADFF2C28B087E12C19AC050C8DEC44B5FB911A3622D7ABA7E4F76006E7BA712DDAC71944ED74B3BA3BE54DDAFD1AFFA2E744BC8BA86DB80D9935B01F1610F7A0B3DB9FAA607E8F9C0F3F34764C447CF7EEC580BEA528A163F39B03A8D96C7F8A34AFE69B6E18554A67C896D79E98F3AE42527A66014AB3C74E9CFB55CA687D783BB1B969BE30140A469EC5366DD927DF250A8A9B61E08E275B35FA1B67A019FFD035B38F8048FED60AD2F5119C5BD1D96EDD2CC4CF13E7A86E3DD61083D87F8B6F43A1E7BA8A9A7A38E6E98D8F396090019BCD8987F4233A87403AA5F452C98184B8623C30F1F0218D6B2C88B3C3B51E2D428FA17535A7646BC4BF5A31C7360B8271E506986B57202233F01F6382908044B7E9207AB19C13BF43308358C48D284FB5067B7254DBCDEE0DD518200EFFE56C5EE09D28468E212D3DEABED72359891A6966ACC05BF786713DBEB675D3FB2DA11CA57EB3658AFA83F234444E42A84A29249A8D92E4D22BEAF7E1C9223A95059E604B2F0A298827082E5454DAED4FAD2D7F49A0B90002BF67230D74D8156EA234421B279B27D8684FC3E4CD20CE420C3330007951B6394127ACB3CF188C00B45378BE5C3F38F6129674A1839FA4FDFC0B45D698A05AFE564A3C01FFFDC3EFCA7B9C52539EDB0853B7956A6C81955B61155FE553E159C35C0A8C714A0E14F27E0EA8E9431A5DA8072CD83A0A471F7BB1EF0C1F597AEE6D44F541B07B92ADC31536CE11C38BC40B345DD38CB622A6846C0B89EA5DBF9AF91DE9017FFFC0DFE7119AF31DAD7C1A6A6F7875B33E328660DAE2977A6B682523E1CFE80240D7B12974056A74E2AE88ED6B8CA9552CFEFE8BA96D56D6F56ECCF5D17AAA910960BD28BB38D869EABEDAA6D2E4907DC7C163A97485F9A69F55C325CF7E2B728AFF4780D3B66FF654A21C50EC726B32713DA1D5D92D671D1377BBB3929C56DE87900256D812C85B05E41E290BC1662DFFF9A74F4C87057BBC6A53844927CD9DE494A2E778AD953F3DDCADA8E5CCEFE23CDD97050027A4F33E6A0FF3AB966AEB213E88B2CC9D9BAD6B0197C28A339B8349A6D1BEAD3441C2176193E06B76CF0ADCDE75916AB9EA5C95F463F4E57BBFBB2FBA65EFD5635BAD9F1771AD97F8E98E5768922DF110996745BBA2EEB79620BCE0FACAADE97516CC27946427D7D680E90791091159266B057646F6E6B70878A60563C109AFE4421E2B5CE86CB1C8779995C0F48AD682A6D30FFCA213214BA1678642DB374674D72F61D87C267B8890548560B706799B97DD922F7875322C4C3CB233D7E259C9973E374AE50DC6B6146B95034133F785FF515D95F9C13FFECC083F74DF2AD60D61FA49314FF24C26A6BEE6ED22951B102ADDF52CB54660BCD889D2770ED217F9A7BC4448CC947A5947257970EE8C1A6CE7ED93AAF1738D01697F77EBDC5CD8B5F7BAD719C54CE3FC2DBF42A8EE449AC24D9978F6E499B635375E2AAF7F89AAFCAD1995FEB52FD77F09FB9345382F87FB602C80F3E2A7F15CA0D67638A9EB27D564B386D66F0F2442F9BD37C2E4D9D337144BBD98E73717D08A1232D9EC878B0B9FF38385E85BC819BF54B5253CF649C3BFE8B7A6FEDA579A7F18A8C070FE310E6981A8897ACF1EE2AED545A4A738985046A6D53A332348FD5F2109E2EDA3FC180BC37DC45ED923CA6385ECB59BE03FD1CC6536B76DA899478B9335A02FC9963CE8E38B92F10913445C50A4DFCB61E001EC9DAC504207154930D2021F9479A30F5D3F24532A640204DBF25A67E9A6377322333F131060E840979B9C6B7A24F8D98E5CD213EB502B57654C28537EA788A7722576B0ADDD4DB304A54E08E902FAC1198532BCECB47A2E0BD46B2A572A7CE78AC8898D60AD004FDBFE1FB72C9815C0BE1AD9240E683C18C52AFD1BF58936714E9A79A29E1266B0410BF3734FB6239B8244A2BCA0EAB68B86CAD7C5EE70C077C4501D71D1C3D474C74DF505431F6014FC4A5972704E72C4A2B8EDD6958EA59C91DCACB7B53364096AEAC54BDF7677469DACB26A04FDDA117178F03816C8575ECC75C26E9628804DFD7F956A8B57B7C02F94353634969BB938E4CEE43F8D5E1F14B07D8A5B97AE0FA9EE68990C4F5B0B7F538165EA54A5866688A64FD62EF4C192C1F269F94969D34DAC026AD4D152FDF45849D29D47CBC8302EFBE4DA26B0A39F6FF30C8D53A16FC825D33C39A0EA0438AD495612B05D244E019D5C67092B775F844E8CEA0586BC1DB4D583A03E7A9CE9252562ECDC6F8F0DD65F4F8A63A0281194CD0646C06593AD206C499E0A979AF526F4E16E13B2A3382442EAE4B8907ED42AE3381DE5E75A099DED78B0150111523826241CB9C38692625DCCD8B9DABBA1B791A1C590F5A16BCFC46CB0114114167321442C0E347366AAACC7C60B02115A3DC8FA0896F5899B192740B3A9794A46C8C539E691A17E779A549B43404BC6225B62D915280612508A0B318984A100ED1A267C74060193AF8F7461B1E51B36AAB11CD344099B6BDB6BD90183D683EC32705F156351C9FE82CD99358CE580F66C589F7E59664E7495ED04042CDF5FCEC11AFAEA8338B68BB2E45948C63FE8A86CA4496F9BEEEC70D837D4F0E62C9BA6E11FC37AC2635D528B80F81F7B1A5694641EFE2789795D2508C6F94EE3F6B83A74DECC4D5CDAB660D8D854D3E7188296B6187A34BFC76299D6FC1759CE39F03B8CE32FA9DF19C5A1AE5C195C6BA6925FD41D36E11C57E525E126870D5073DFBBAA199DC5FE03E61E9BCE90C3D43D2AD9865A50C442876293A4ED4AFEA11828FD87A09330212481F47A0F9718B6F8A90E071D6197617450100216AFB00C32C3DD3AA5B1DE80FB60FE5394A0F9C57463B11E7C617AD9C91E7821C160DA92AAF757AA2752FE2A6B4D1A75287EEA3F5BAB3A2B635BF250C171D55FF5021A93551DDEDA116A2D030180E679ACC538294A4D222A44E15FEF01C86F11C7561909D76DE4E81FDF9B6D8143A50097CC8FFAE8136F1A1E998DA65B85CEE8B9A032D5F55E203E5E7B5C1CD5CCE46697C51BA43DA4E2A272471C6060F7C40841ECB187B244789395AE55890D9AC0F63B02CA58823270589E2C2DF9D05111AEE3FEDF8A672B2F0A353E8EA5A2185715338F773DCB9543DA66665F0563F613646AC5D3DD253D3F82ABB4C4DBF60D57606BDB1C52656B7A8D9EA7D2EA137D8090A8AACF000000000000000000000000000000030912172128EFC63DD588A7230CE08EFCFEEA534F5A0EB005480AD1D169C386E476715238526E936FEA7136E2D8AED60DE31CC91DAE4E764CE5F93624FA7F72B87562FB6AD8996B5E41FD478AF0AF8338A7FD9AA250EFD2F2D20364E8A88A8642E8E38F38583ABF8D3BE97F14C3EDE66EBF8EBC84385CAE646CDED8C5CE8F06910BA7FEC05D828446D558D6FED766FBA347DA2E84DA247C34266AA31C328804F4E3AAF6ACBB0AD50FEECCEC00D20B3610785B9F1BA06A0BADFB42A8F43DE3F7BAC36057EE0B4D2A15DB040A8903F767F7352995C8FC3E06ED1B1322587EEE5B31806192E04B09A7B433D08CB2A340942CB75C51E0F8409F907F69C5F8DC316A227942EDF7A458974FDA76C255FF4F1A85A352CD2CD2A21507E0F37451060D31D0847528B3ED5DA3E7168CBD0302F1B03842E63B3DEC6FB37357E37FC3CC26721F290726A47AB3D4DD8FD1778FE5133726C240E7B3E398F3D809C6C469680B9EFD25DBE890D6936B76A52F97AEF3F93872B76506A95685EECDCBCE203400D182252471B99B7F4C6CED4CAC8FACA7682D0DF07BC5904AAE042479855098CBC41534F0EF17F38F1BC8C272CF72C1AC4A5564DD132130EE676E7D7EC3CABB4E85AC81945C87DE08EC60CED3FA0AB3E83C18AE493A851434BFA2C4968B42ACCCF3609539C62A4E01F8BC159362E15EE91D8AA399D8BD8D67BA1E8FD646EEBB4583812293406B05BA5BE2B1DF9620E6FE3DAF8CEBD9652BB04494B899F407C7D9ED1C4E77FFADE24ABE56AD597BD438928E05B0363D6D2685D34D6B51D71012844415C46F13181B146A3AF25AE4E8853CC7C7EF6387306C45180A6EF9E97ABE1E7D5E10115752C3071B6A213367E8B1A3D1C3703CC1840735315623901D772C61D55EF8C47DB10F0EB7582D7A043018DC1363E93F315DD984B8002EA7BF5BED38D3F273276CA577CF99A635CB6ED9D6525520793405BE27C86E6EFFEABB1E5F84A0076BD151CAFC59853424DE4B3460C673B0820D76E15EE47B6505D2D5C179DB92A44042F3631C646D350EA9721B8984660A76018DCA5C6BB1223CD03CC844DC9371D32549D9D645F75D2683FDAD1DF6434BBE43200E506ED2A815FAB511172C70F99A85FA3970433E8955B2F9389F23C10141B5779A23B8671EAE8B91991B78F635FBE8E627D3E79D91FD1E6E90699640BA3AE8D7E4CF5145F1259CC76AE50B1FA150D8338A9450A5B6B90EEC9C94318BC78C9C7715A3EB215AEE6443540D211A0556813529023E5A581623CD6D19BEF0705A5F69AAD4833A57C308144E92899AC5683147CDBD279D5C3A55BBC5E8F8E26A158A3E42F8C5B858909B024B4BA4069E26DE66460FF4A7DC92BD54AC244007B6AC6CE07A31A2AF3323CB55F07B8F480D279308FE10F2DDB001DA6C4AA132B988AD03FB63E0EB06544571F5505CF377A81153D6FBD4FA2B7562074CFAF587CCF28DAC84AFA58809C0B296E0D2594D3582C28596F5AF7500E143BE7B49C63D04F49BBFBDF60B024DABA5533F945BA90659758E06984921EFEEF79604059EB808C9FE1BF9BC5351A406FBBA7F5D8FC9F891488E537DB14B216A0535C9FF7BF8D5C68A2453A8A48E58FA7BF6EB76448D6D0BD05BD4628C4B852A236A11BEC0F67118F1267CA42647F6F2303509094C9A7F3A07B2724ABD2D9B56B71FA7AC6CDDE456EC209BE76C419855A5151EC9EBF0E0CF1B86F4E8E81B8173960F8D1C8AFFED1AC7B818AF8E3BC092E2B209D693E80B11EC7DA39CA93223E1B47C6127E8AD40A78BDB0ECBFA1F39C84CB9ECDF960ABB39884627BC4105C53EE7BCA4802B92AF60241420CBB36C407F46CC2E953D7E3503CC82287A8D68D0E673E212173D80A12257ADD5256652188C00590DADCFB7DBB6B35507B853EA5FAD4F52E02230CB3D3BBDFC43EB74780583E8DBB851E0257117F4A39A6676586216220C1CA21DE16CDFE6E1CC99EA7C989916AD2FED4A8373CFCFF02207529BFFCB7B7601317450BF430BAC9CE111B0FBA8D7DE6627F863078D8E6286B2D34856426EA90FFD58705444D0DC12D4FEEAD0FFE543811E1EF306F40939922563832D06E6DEA7109087AC051A361EA9E755856FD4E51388BC7C40C63E0953C8413AB0CBFF70C466E15DE5B089D095E8EE8A64E929D26CA3B71EF0B2360AECDFA89284CCE08C666F4E0146362F0BB84B87A49FCF2324EBB96DD941F00E2586F7246436EB66B1E04AF84482D8ECD2BC8EF9955CBEC62AFDD754A7F235C7F3C41CD0B36A9024D426B7388D3C33A5A6E858846C0FB0D88BA5798C923F9B43D14A6661C65092D5C5EC0F97D84784FA336AE6EF57C7A5D04804B96D19849FF9074724A5FACA538E32C6EFAA5209317543159272CE50454FE1E7D068C8F5FF3797A66D5F87758627AB5D40EBE1FB7CE9D69287AE7A5F349A5DAABD8A8E7778BAA26DA0EB237034A3366448280237A165CBB303BE6B33C0F11C1E56C50A84384A0F6878F2A99B14CD3B6820ABD27D2011E0C37F8439BEDE65747038A5FF7F00DAEDA094331523CDB7E10F1063B64A584D3E9F0655268F89DBEF3EA3FA4C6E54FEEBF8F0046C6C811F0767CF6FCC9B3497DB05582774047A8DCFF6A0C1B5188076E64A9D5693195075F2A05E507A5A523EEE4537079F9E5E79210E4AF056D6624D45A0EBA553CA9BC92171451970102CAB57DCD89ACEBBD7025008325C61145264F42E4D14A76E5C2F1C129D4C054DA00501081617D1A27012A6E160750DBA73BECB5DC05105BFDE1F1D0CDC837355844B291B09015FD610628513C1C86EAD373730B99FCD4A552FBA07163CE9CF6A3D3AC0525593F0648256E8B33FBCF92AF58CE26D0F036E11230879DBB789507BCEEFD2960EA320236A224EA74DD2AAAC541664FA3EA9430D4FB09C878169A8AF1E7FD4BE5E7926CB0B6A352B25F452454474107286EDAA145C0A0573361522EACB618DD9C8B32BD1A8A5923F4C698CCA0139DC640C1D5D557CE889BB69CE32D85853DFBB0F34DA2CF18CC79472906B67F6BACBF287F31DE0B9E7A01A356EC9B64653CB922501EA1EDA940089BA0F293B667F482E92438805CD6851776CEA0920CDEFC4062C9B4E51F5AA1D7FF909CC2608B6F28CCF28D574BF67CE80D4DDCCE28F2ADE0162CB66894B5B2DA0EB975CD95EE7FE72FDA2736616C8B571FAC94BF8C64ACD1642D9431118F08A62328D99B2B9D90BBC915DB764C4935951A59C369C72060CD9F4273BDCA0C295294008C0AC3A149E8CA5E8BF21042F5F21C067147F3BB52B13975026A9DF7246AFB1D053670982AB316509F2850342913E1322758ED89DA02DD79126726B1C5566C1831CCB1D62B3E271875E62CDE0DF0715D404F95F580B63923F362D416F83FE5AD98EED584717FBC2CB7D1B00101200F4EB4CA5 + +count = 73 +seed = C7ECD1EC1A3D83F5116C0AA4345FB3ADB4D9F81BD79896BC4932EE2F9D2D1F179BAF7A002D88F4F69071A7931E7F7FAE +mlen = 2442 +msg = ACB414EB55AE5E49107BD0AC5975544F83104F7264495AE0BF0A6D9594C422C16B99469ECCDFE8B8000875B469309891EA42586A615D146DE64FE59277A61631B2C7F7379CD52FAB3871BADE120EE9558D1479A91925634578CF14D35DF3B5672F8B5F9F956FA9F7489D6E37E207FE556017736F6B147A8CF664D0E0521D94737E18188A1B7C30296CCC9067E7B55D6E0F2FBD875F42FEFECAC49510E324968B07372DEB10A31C585457E0C48879CE44BC78898ECEFAC7BCEE90D0F8925DF2B52D5AC81692E0160F8FD5808645498428260F592E29BB90FCB07D0424EC79FB081840CB827CAA4A9D562183D10EE41D281E26CE3EC0069C83E1E446EF82E2E30DEBE3F409E0A9E6D1550E224DB15DBDDA44341E4ED6F8B8984716CA87233197528547D090058607CA141424A13145F1E896555288C5E2877AB3B51C7F9248D2D56A8521975BC4EAE3D009988CBD73C66931BADA0725FB8A3448D43E0C7364E9494FC4E295A700E79972E1FFD626D1CBE0199917851638B192EF9F5C03223F2BBD67EB59A5E8BAEC3DB40616938274201DEA1AE640F6EE7E047CC4C13F80DC65E3FCB5C62386015F4EF1BFEC561E121F9BFA9B2075BC1C4730503FDD5DEBCE8A535ECA01B9D5B021C290854B5F3D49EFFB263DDA34C4E96AEAE9E71A686C009B205994B46CFDF1F76727CA67D415B9D21D54312CDC6A8ED0AEAB96B580D0B419E2058E5D843C17C96D156549962F81C266233ED2B795FAC40B1992B626457F211F08106AD86F5702B9DEB9323A0970AD86125ECA836E0A3D6CCBC380D474049BD96EA246B8BD9542793A66E15B319AECE6BEE17ADBBA7DB337D25F8F642774030A2FF969CB5671F59901CB109E661E55FD5E75EB2A96DC37FEC76A82EB89D020B4916271CFB0CB3342494FDB62EA0D253FB8FF2E91357B33D96D41530B8B5E9550FE9B3F9F34FD5A2A1A6A8BEB93CCC322622F3B5E8487DE19AF57CBD1481ACE02779AD928B17A9B05CBEB722C783B088B5912C2D67CE5073F1801C23170DEB1EB6DDFFC4C33DD25F94F4FBE59D704E478FB49DD2142801C37ED8F539EC1782EBD2F3253BBE19C5A048B9EF41824A811119F3A6AD2A0D4B77338E001358C61A9794572B0C46EB1E0E575D4DA141A415829BA8712B791B625B1B0EA840EE745D9FFE1E99EFD782BA25859351F443654995102CBEFAD7E59D03C9A502ED7B77144D0566E4BFAC086A7DEA356CB9E5AC02DBF7E81D6CEED4A33DA8D801D61BAB5C01F259EE3A99FF7F6D7BF8F2160C4BC3F890736074B000C4C58FA4615880F93FAD43D5657C76045D7C414E6B85F63AAC91F04A616184E04FF9AAD513BA767215FB0331A369D36C0AE9B1EC1268F1D0B43C42B786DB23DD66465B3AF17FFC68C67964C2FC9E41EABC45DB68CD2C3D95B8BEC787D994BB8E9CF1DD7D4C563FCA5D80B3F1FE8E3C7BFB7D171F5B9023BFBCC0CF4371B63C856EDBDA154B4313C47983F4027F9E61E86DA1E8CD787E3E6B50E1DFC9201B9AB92059F8B6D1BF7856CD55C5B1D6C4E6EBF818D481C56F66C79444F5A6544A64A7D78EAD33EB805A6AC4310CD46A2331E707B9B0950CA12092402D68C1CC5C3F269DFDB13AB34B97EAB50B0745BE72BB0FD2D73BEA5DD37802393B635E42A0DEF8544A96E7F40A8D9D06B64E38DC406BD59AC5C4E218591D20B8DBA2125978096517EC5C03F9BC6F96CB255E216EF82D7C7C873029F9E1D98EBC0D8E1312B84B8D02E8D680AA56A506C8668B5B9C56D04CF68E37C7CB1B9377C867240CD42FC7FBDE0AC44E3DCCFD3F877C9923AE9CECE0CBDAB00CA530F434A33F1C939FB88ADEF4D12ACBD8B2B5A139A3FB776D8223A9846465C0372B8C3233FB5280E936BBE9FD49058961463A4419D939F4F1FEA705EB63114F0A3533638DC4D3EFD620147770AD877E2354299CEC6E5C18924E78DD661697ADF89A77C7365522D3E8FC0855187139F7E43E9A0629EE321B2CBD9F007B05C22EFF56FE48045686B36C5BAC2267F37A2E3D4E03E19B1E422ACEA31C2E9F3E7541976D4E2FA03119DF9C4CC2D5418F0FC7A467CD98E290695B9530B91D5DF8C626C7236A5C0FBA73578B9A47491CA0AD26A144B0F23EC23D2C5B2DAA03BF40130F14B9A427CDFF1F232C9CF02426228C570CF1FA7C00A773BC0D70858588542BBF8F581540870897BFAC8387CBBA3416A846CF9F4F5D3F9DCEDD080CC0DE9F71B93828B835430898E82896CD3F30FE2AF8349DB294FB2A8FFC0848692A0B9E8A66EBBFC0F896F8D03E3C6A0C27E0F2177B85A2F6FE31E8AAF14EA5C1FDC54E80CDE47AE27A161264680107023CFFA961E913C4E6AF96C0BE37AD859C334CDB8BBEECB5443662739D027EF1B9535A5A46E2169933E419454025623FD6779F54C622EF81AB9289B50758EA34F868EC85AEE589B08962B85CF537BC733F62AAFA95FD81A60D5C2E38D6EA0DF7D1390BC5050E2463E3E2E3A769DE2A94ABDEDFA0ED67CC0FFAFC5A05A3B0FD37BBE6967BED8DEBF02A42CDC80BDC62158E184FDB6672F7947505E2C0A6C7762B1145C4BAF30E3D32434D22707044DC99D2CF2D38F15C43ABC8632382BBBC9E0F106565906F7D4948D30FB19EDCC3748100397F71E1548E58A5A01876D0A12DCC80000224221C4ABD98A5022506D24BF4D9B9108991AD3421D4AB9CC393DCB8D744F97822F95CBB2640E73E401F044FE20253ACB8B32A75FEDA640E190454BAB695A23B14AE3EF60B00491AB22F622DAA89B6B2E6D18E735672FE0EB2DE269E4E386C926E23B865E1BA22DDA688293DE144102F7030FDE6DF653E4106C08C2467AD7C54D1DF0DC5981004876C6BAA8720F70942700A154A376C8D45DAE1BE74910148EE3F2733E591E1965FE763B58C8B28AF25E9B3C633ABD83F1C0A4F68DA2E0B85083BF97D4E919340C0437A604416C4F629B33039BBF2A1F561548321780411D2E8AC0EDAE76FC3A19F3C84C3BE902A1E84FDF69B11A12DC8B78EF257B5FBB5D923FFD548451A52C6A3AF31C70266AE8A957B2BD72A51A034A2921B8E19321108AC303B0D2E269D032C3DB13F21D558C82BA4158962F2210E1C5FDD96C98D6639AA844F34E40C1B9C909CC6AF1E97A8DC83B78C72B30B7AE400F44CA60AF37770B3D9147F7D6F5A327F34DF7CB8891E71D41D723CB18E0DD324E5CD22AE0D9F2B1D2BFCED0288B7AA73AF4FE0A8181BA1AA7EAE966D0A240E10FE5735D98326A106D16DC49F3FDB19D3A8449C56A74153655600E4C9E38D302C6D4080017D93C628388DF94860329BAA289EFA4587F079C6F03FA03C54540A0AB4B067EE46A5A346F2FBBFF6570ED0166A55C258EABD62AD90F060FADE84E8FAC799F7928285F58557A72E055B535D00BD9A4880D10C05C07CFE7A6FEADFCDED880521803E339F6EAE3FF28A0A471A003358F952320F41A0AEF9D28 +pk = 3A2793DC38CBA2F36DB066F8F55D7B6729C195AA00E988511CA354705C38E799854498F9ED75C1CB1EFED2200B6A80A1348D8EACECA22A29550457DE64D34E1814E10CCA874B7CBF50CC08824A1B201B1E569813E439987A601ED8EF3BAE527A61848D5741749D35C28702CE96ABD4D40918476D20DC507F93A331A4CD53D21B9C5DA1504F8AAE2736AB1081265248A3A35EC2258DF1A4ACEDAC3F66888AFA0E510ED5496B6848D5AAB009FEB9A56D646FCDB88BED9411459D72F872F9EBEF68CEC005896CDBD1F452D6C043B639C3576BA0B2D421BED78B32803BBBE5D0D07659685106730D08F86112222CB55992A47465E5482DB08A7947827974B0834D8529E356261A9216881918FFA79BD8D6FCE4025BE8A29F1D7D165791DEBAA06611740FB2EF2B80FF3C0C46F62FA31E6193135A8D2DDAA2C96BECF3733DDEF71E7CCD49CDA17F3D8E92C0C2FB785B593E887FB35713B22ABD19C47EE67E68C23E2D8731C4DA0BDA76717E6692437DF25BE9F89ED0027DE630BE405F58AC596EA654A49731071F4295AAD51B77EE2C331627F1FA8FBD76E81C7DECEF3BD83CE314849FA85D353CF1245A6A865B51534DDBDAD219D8D9C72ABD158316B2A5225C9F9B55128104AB16289EB1983F2005C9378FFBB630693A4E7A67089754EE20FABCD4B6B4CFE80CB18D28ECACE6830A9D9D66FA36108E3B4F4BACF81CFDA2AFAC951381964C8D6BFAE47B0539384E4D0889544EC77F1D79F85E6718427A6925D4422D41021E66C43829CA39E1C0C57C878FB076EAC241008DC26FA241C761540F0CD53C3B44B518ACD125BDCA9D7B6210765C7189D2C6D5D5976B850F4496755D209458C33871CC6B80C2C53F81C23E8B92D2B3D10A258DF5CBCD81E16A31037A8F2E098EC6E66116D9D1FB46D3067DBBB05ACA9AE783F9BD9A787D30620D35A4F0597DCD5BCD3C8867A4012EA94BE0943451A20DE99F652C11E4CB09068266C1DAA347F1A9E12D9EE44FE0F322ADEAC2B069B5A0A5049351D4849094028DEEDA0274806D816D69729A48665A13EABE7CEF3014E94D97321FEAE6AE2F72D1A47BFF8FB8261A80277CF1EC735F90C7D42CA0EF32FFB9CD6E8636DDCB3A271D16674592F447EAFBF838AF0D53473F15D6B7F5C86942D24875712A2384548A3536029102A240B35476827D6E8369AAF4260176C85D0EEAC74701CB1C489EC3D0F5C0D8A19BE8DCCEE375E961599FA8C40E915EDE7555EDF865EC877D2FF47A4FE72FFAAE2957FE4ABC924C94B39BD1C4BEC5B7EB8073C5D3E08C79895D090A2C118E78743AE65420D111B67DD91D92F62D87799321CA916A28ED5117FF8CDA3DE68E081C92E989702734F47E3A805C831C6636454CA51F0EF0704A6F3B724A01D3AF130E6E882E049692CAC16E539DF27CBBFCDA25642C1A82DE40BEF1FD22EDE60A99B5363F77E962471895667FF5378B2E49A9267EAC1F1F2208AB7B3143FD375B001E7EDE176A3AC1EF460BCDFC71EEED4AF10974E1E63F8560BB8B1627D3099AF066B7A9B7919655BCE0F82827E8954A0ABE4A0E0006EBFC0D78F693C456152F6A51AD5F92FE60C6EB2A7F59691E9B3BB5FB508D8FE61F0A6C6811AAAC52794AC22C49CC0F0080EA4C0365BDAD93539CFFF30E111851AE606023B626D58E662C14FFACE06635FD7ED6B7D2DB2335CB13C958B85E3AA71316B0E934EDF8D6795A66C3ABE8D541C734E52F88A5584CE32333511FB28468FD15C2455AE5B6EA7E3F3F40EC73790A2C79C6DECB12E8B229658C13702A9BEF5A8D660ADF65776688CF74CD685667F79DD47BD4A8A9A883B0A72053FAE98457C486F817974912BA8834BC91A29487040EC1F770EFC14E4ED834F377B9912EE173B8241627653D5668D7ED776DBF8637348ADA552B0E9F1C028CB3C9A3D60AE2068BE3A6253268C8CAF7761DB492E20A4AF37BA6D56B3C04171EEB7B3FE8D06F9B6C55A97BFB48B8B531FF94EDD379ED7E9E619D1A0B7DFDE46A971FAD8B1445D031A777B0427823FEC8F06DEF33D9990ACB0572D6A2A8FE6FD627E043CC8579E7DB9008925FE550756D8F34F24DCF2DA6638175AE4E1A08B24343319BB2753FC297A9DD74086925330EAB9C33B6F63472A7CF223C1C2F0486A11731638EC4170E7E23739EB2D6030467144302BEFD2A5311B93D43751C52724D6607DC40F5A9975C7EC32EE6914816B4740855E05E4DB4E29D61593C043EC3C2FED9C7068EC12BE18CF89E5F2DB863DA7136AD55A64438ADDC43C836EE934BEE1A1582A6A58EBFFFD1EB6A24B7FC43D97B5F8BDA889425D59742D8DEAB49C659B0DD0D61820B60EF7A19CD9B5CE5D6652C3DB81C4BB86A54F8A8B891CE99E47911C53680856A9D29FAD458EF8D4DE2BCA81BDBA9EC96663444CFF91B7049FB59F50A5C8E301A99390F9BCA6674A5B6487692E0E02D3AC04EBEF1A006D5E394DEFC15C004DD7960E70CF09781CC33CEB6A744B01478F0DF77C75E27D15E6C04B0C3FB7C48070F4360298797EA59A08B4EA4E53FDCCA61AF8F57AA0B43EF8917C7A108CD417C39A178256ACDBDE0B7E725246259830F765479384CEE8BAD2A4D9A73235F29811F506F03ED7A7C76AED681AD06A921C7F7EEAC638CA989AFA0265C3DFED548F92B0F4C8DD5F2EA8C761256D5FE5816EC89A2A12BAA7882E3C4C0C4097A3E8A88D3FCF737A669A6DECEA85B31D3D906A78808FA4B7C215F9BB8E1A50AA0D8F0923B359C73C765EA540C82C07A4F +sk = 3A2793DC38CBA2F36DB066F8F55D7B6729C195AA00E988511CA354705C38E79917235DD0CA0E28FDFBE573E197A2A71278AE7326225951314D6A408F92B8C9D7BA01455951A1A1995C90F96B5F3831516D016200FA7E95B22EBEC368BCE887F9181A2341078FAC2C662F52B640640D4AA4D84F0662620D915550F2FB923EFE3E87776876631117711261447314888582811623153275323512511760764600013624746538800536705536534818150563368677301357220777662723370654624832105340386760621555135104366124253416312248601062571127488366603678082778644707268152664442156655858656582204135056276344172485658062356671560456788683858548326866421857306822485607237587844701860621880736537226508231240113055875807516536822337625225688200676807832264348300152772572054864072546884062782056652128537626485484871355640883700556783871836246785201722450632303774771853242520572860664353746634458603287736140734605471484520287830774456137255147666447222086553782880570725480182840804878102464832488637361386751147014704077000481478520061001045522258360731612263275586517766656371106034678587628068253788633032337438516442303870176784504161042103571218343143407535011614116042240085604627866728054838442814525356733887364323015417134086711846126761286408721675062627646172813556521820060323450088755578665720631030830304028670825303070815142852785550042370752353855131285542173711414887746822818852583016014181030621704257248707862070246563234813024662574387166405233550842075101537642180346705557443361362067888533360326641621063211758325204254734203717340856777325558478837248361474446414233353260206317878085247104025588185157103832516008756682485823523027460257001360515316843767247516565466172085328162545552408660621446750688273382471630111202768485781582612601005515644315538404150631105243262334764843468754121503844466005588326781505636423573468754670205865231022873877625686731085515203301401708257664863815208582144582834777301378077200402120228578144868832622300208122587211842573512434004514670673435834587505445824068265224038321330517063725311124677347661368603671178875077726227107416784630004636754151872727413425035744811382361335821723201613168512805873084272510705827338612313442147885122085111775378887540564356702304680504356344480268503833402166583477835557216702685276400516454624601404575303141417436185763106862784130216855160251383256540377084222117635223800122862750141616227807116721011068407805833151672405547828232771822787873706461211850452887383877563681175228486523638702267030580254207185005432130388008401840435254350470531366408854465668007147117585178550564253431605610161856121147174055718464183157603664045710288120025738420772300701816143800417668230712248182037777185083381821540321181445443386676516214126858431627004718077818137052635642435342332402223233237781646858388004484467442462860657608518685823085200426058828770852360560147247068231317317161656382751122657828041134758237076487642572048543680081862404230476206154035535167401205510481536103306356453862728002581145685171048587743658206681206724087570067226846505701826831223666576352381728628768483841871243421273061375154147107545600386656842518367077681754067626247A242F0A3046735AAB5A2454BA2C817B43623E53E9F8FE4A3B3DBAD5231F73D8FCE51A5FE229BEC09B4D71409D968191837C5D0F2CE3DD7F9D923068C5BC76743067175DDE3944D3512F533FFDD871C611395A0AEB0F863FC4771B222E8B4E0A9BDAF7DDE5651467FA6BB4DD964DDEC4C44103579B0FB17EA6ECCB5A8B6C1B11759EBCA6098E6E05A61E2ECDC39A9CDB778E347404FAB7AE15B5DD32E557ABB56DF044E23F3A86E938FD5AFDCCA3E69BE236F3EC6CA1AA5CC3199D03864F56C15C6B8B516994D9AE6E78BB1B89A84F6CA1E0DA99A704C60045AB945904ECD6D8C6FAB6761D2A5251E31E76ECBD454C33489459DA6DA6AC184B299A0829BEC61B7FBB0D82F77C2093647C076229FFA3612DC77FA8EDE7C238A8FBC389B7F83513E5C30F89FB9C2CE7B06887ED606D9E45E899D4DA838D73337F83E95FB11D8273472C20E720E2DB35C40B88DF10D1505C1FCD0D476E41713287874937BB944B53E19909699F41444ECA6CE3F7DF531760373F1AF70731B872B513AE5B1A23DF73C7EAEF50E2A73D4BB3CCE072933285719B74E328D04DCDF4328C596D88A3EABB3ACBCD674D3FF60719D3C76564A0EAB457B6F704D84AC3AA7F9CDED556B0608F7F10700919D402DA8AEA62E928954504A8FDB57D9C83D4F4F0D0CE5BA8131A79D4F8FD2FB96D752DA1B05CE1F91DCE5F79EF9283219E8F193FD2E9547CF9C20CD3907686D4508348543D14BE13A0A6B741DF52A152CDFDEAD235DF747D5ABDA4899595D8F0247A2C857922A39FFDDE9FB6BF0B63EEBB2BB5219EAFF9A312797033E7FD0B7EAA520875661BBEF1E3B9774F94CDC759D28AB93F9F06C3BEA2F4F24BD5A1E92CE4FAEAD429DF6A81CBB3781F66C3F3866B3BF2528B78F9129150A25BED626B70DFDCBC9770D7E0B5EFF447434DC98707F56AB0BF4B8134C2B4FC90AC66BF337F95674528155358B7FDDEF0452FFF99CEDEF2FF6FE78F0398ED26BDC43915A512027A2B9D523037C2D2B12721404EE248DF034ED9FDB88148B537CFF537ED81A4659615A7C905AA4468CF1ADB1B994B8214DE5442D1910FE63C147D76B961285F3C089F40648E7602434284BC3C7F8BF75A57D7295F96A488E4CAA56C4F901FA156C3F9A95671BB4D8FF6366C533D9B345D8E4477A0FA4A2F38FBAD740595D3CABDF5D05AFAB3A4874AD63B4F13602A680B44C3CD5615C813E22E290AC97D945A8ED1099C6338D93427A9C91F1E2120C3B7F07949A01BDC474129B466586F770FD84458DF59598178C7BDAA20442FD0A8F0A89F37C1A19972031A74EB2540A7A70EDCFB3E51B1E844B15DB2DA83A40A0F374D04952E6D130CDD1BC2F4F5BCEDA7006D95B16FBF727D02569FCF67E62AA07C822D6A476D2846780A00AC54E623D3A4C2EDDC9F114C1FC442EBD701B4161D8F4635007F3F6710067CA2DC35EABBA7B3DA271B7F0D6C564B480C393C674710839F17369219A3B1A4F9B7CFEAB997C355A3A63A3FD66A72FED5AAB4542C2FBE2D41A10FCFFDF10A4D1A7471725C1B91AEDBE2CB1CE41CA6538AFF2745C2C376268FFBDB024F02DE86625AF31105B7363CC1D8EFA25D577316B1C28041E7BEC303CA35B29CDCA8135104D719C59BBAE17BFD9D9DAC81DEEAC962BD416B91CD9F8CA8EB754F7757C31FAD65A67026DBC74D568F7149F4D4D5ABE73BF21C1468438EC59EE891DF758FC853AEEC6D4E49C23E676E79F95E46E67E7CAFCE584451678D8AB99280F7CD64288EA9FD66C2B995568FBDCBE2F291A11F6A9A3521185E46401B1D229EE5C4F993A9CE4BCDBC6194C074BE9D83589EFC9A70B9FB267373084C5130AA0291E49918F2A487E79C263F549A80079F3C809DDCE8C9F11E2F23104B33742BA6A144A3C60110FAFF53D9CF1DAC2541183D4D9A944748C3953DCB126A93E1AD97C765D7B0828C4F0B8266E2B4158456F874F76B113C666B87E2F12943323FB4179F0E296384A56FDC347AE94EEF8EEC3395986E7BD6F230309F201C155C8E14023153742D1ED3CD060B70B46136EAC55D32FFFCE1A4FD9681C39858F30EFDE5E8159978509C92EA57F32C9E23BF208D5778620A0AC381132471C68CE1F889CBC4BAACE7504C065B3DBDED8FBD0B900D999EF5DF634FC9EA3C3C65400D88CEA2552CD7963DF76CFBB2BC7E83F56620E682C575D7A8B4C14BEF4C0F697D38EA483EB532AD293F8812E1374C27CC0C9426A0B103561A795F3C43DAB2072D7A9839704EB40E290F63F444F9249E32465EDBD64E31661B70967341F162B98CBB34A27CF83336B80252FF2841A54146559BFA89DE016F68927AEBB4056921A3EF9609980A08F524A6BA7DD9E00BF0909B90E7327D27C0C9533CE16390878E530F6C1137C7FD1F668F3C54361B72DE5A3B938D461C01A90BD646405A0DD5A5AF7B4E65B06BDA69AE4B04F360ECD279450A7A7D4E58B5284954103815BE0AFE709F3028DFE1BD8BC559D9F25CF8148877D838CC772860EDD8BB64C027D12827CCF725D2461B805A4F8946EB045C8948201E777CE2D44385D998C973C6DAD8F3921338AE87DE882461FD9DC1D4A09E3D676FF1B3854F70B1EF5D841DE42C1A81287E392E6B44DEBF660D139BB1480DBE2D2E9FCB4B5E0997D06506210207DF3F7132AA1A40AC130FC3400AB8C652A42F350656C41BDC78EBBD635AB55EE08355A54C13DE67DB1A00301DA847D1D7752B4F559F26A99B1FBD9C7A590022CD3B1B3F23A6BFD16339854CFA70FA8CDAD3ECE19BA56DF4244D5C20BB1D64F6CDF308D8CC93F8B6FFB3CE1A9989A4902F622B0DE76114E9B02DAC2965E9E45679A583857E651B4112C8CFEF2C4E964F5196DF88AABF696A177D876F7A66F228AEE0971A12E9A14D87136C4D70DEBEF187F2B4EB101FAC9482A324037AB143BECB2B0688F23E2ADBA30FE9FCCB1A38D22F97DE754FCF13FD0209B56D557EE81FEAD414479CBE92BC62760AB64DA1D678D8FD22B29C869F04B8570C0A7337A6B50522CCFAE9C1DE40A0E2F9C4DD5982BA341C91D28D670DF44A236657F28440F8D2A86720F99DC3512E3599418D0C25BB1CE04E184A4709B6A6CD7E5CF1003351365ACF9659E97D6738BAE21E3C017D8D4E578CB6D1BA4589879E6171C4B90EE42511BD6F0B1FA1E59A4315D5222E19960025E1410144AE93CEA4EC3032EB9BBEC2B9CF8C38F431B124387F11FEA742F3F71BBADB873039EBA3C984049169A43EE7EA5A98322A658B0A645DA85B7E134F6C0B5103D7CB84149FD2DA20464424EF7D815EFBD469BF85B1334A4E631609AAF5CD10EB7B753319F2ECA1327A07FFF2A96DCD0A762DE244046A7A460804ED1573DBD1116A0AC49FD6041CDAEF85828CE39B35D56752192A7B6FBB3050DB5DF00FC385F7E7AB7FC3CE6ACD5755652B2E40AE0606775D459C01B00263C9F16FB65360E74A3B4402C81DACD2CBBEFB605660A2102E82D6461AF4BFD4C0C779E641D396251FB13B8CF595424D910D934AB3808ECA834C90EC6CC851873DC6274 +smlen = 5751 +sm = 9B6F3563DBD8F40F433602A78857693FF666AE3410A4D5D9FD7CD5BC1EE41E40BB0BA3DC20778B2A258C5058296FF973354B50A02515270BE61AFBEC6E0A1704FE16028B740BF9B879F71F93D8EBA1A68970A56B8A252309429F6F577CB24A81DF3BF414C459ECA4DC42246D0BFC1F03ED3D56EBB62ECADEA22DECA6246C12345A0E469DA7CAE20AD1749D40FB1574FF86829A7E9D81B06A64C97CCEDB63D5F062BD11BBE7B03251B31D838E7422DF0C4E88D7A12C6FCD3A8C14396A5E3C06DD27AF961F6F820B62958D11A361F29FC9ADB53B1DDC18E3FAC1455367B9C649916FF6AB0B6D7478A9912FB783D88DFE590FD38E6A37671FEAEA837EFDEA8EE5D1723B80A1B937F7AA56601B74F96FE2E740B958690E2583D36C91B80FF11190914870ECC9115BE9CE5D3FD984C66F46C552A4ADE70CA2018FF3087B4BE571523C5C512246267EDA498358DC4CDD6386BECC36D0C252F5FD8ACE549BE9FB25C2F809CA8FC3646D82E9D0473C75674D9B6006D7311CF02B6DA66288D2AFF651EDBB2B479AAF673F94A81F3318751358A67EAC64C8F77BFF754867C52E0389D70CE6A0C0A3984654084B07EF43EA1C539DBA7D1664A7609ADC6F49B40E714792ECAAA0CA795A0CD7FEADE8C9A5C0B67C6DAA955DEF48D1CBCA61CE434EAAE07E2D53B9A8492948E80AB2FC5D467822B800724A9FF503C11AC1D06A3CC2C3743A5EBE896570BCFC696E52B727D3692EF1FEECC06A0B927A9A47EEA67C32A7B3AB84E344F301C8C886E33C44399A106031DB064E0D025202FCF9C011C986CBF4E4DF044103234FF36241E88E18382092FE4D34CEEEC63BEFC7F9FAD4739A70C3E5C5A9C59E9ACFF9DA06D4F25393F0A7E988DD59EF8038D05787EF94089D1256D55A15B18EAC3B0B8E5C61A0B54903EE3E44FD38A44581B86DEDCC57A8278843F839B574B8F3E4F28665842D863D3EFA4CE19216F371D34EEBC219ECE7ADC91A7496703767393F098962B1142D818B65202B72E1DEF7D1D1A1B8C8B7D5C7E500E6C649AC4764DF788BD70A187DB70F164EF291DFF7518C3F610B60546109C53D0967965030473F20816F1F5748E46B0B55124690256AD93A255DF6A101673681005E236EBBD1E2BF560DEB67BC161A637B7A96E78E79767E9A1C5AD934416420C74964B62C4C4A4F86D1EF1419407AB405B8CCB2CB67BC1B22AC6FB02668BD0F949235EFE02FE2528535DC82161AE9CC086F4744C774F8467F8F9974A64D8BADAE974CD80F3A8235252187C9E65783255BECE57A907746F644BF9DF069E502B39F8CE02FDC913D1EEED016D19B5C191A54474BC5B58F338C2CBFA78EB59E8B891A31CF4F795C0963CF5D4E30FA282B340EE22246BFECFD8718CFF48D0257AC64553FA8D9283BBCC0C4A4907C1215A167A620CA5FF45675043A8C2C0A4E16067B7F906626F63CB5B43922E0D60A1F094968F77DAB803DA9502B1E8E4A30CB507E5C63FDA075ACF0171903749B3D0C94B842697E727B34CDFE468A7221180AB0B4AC80B12F80F1B0EEB7C588C0439EE907FAF8A0D83071B270D6641D1274E26C2376678CFD88DE85B428EEA4990E69A6FFE7B4776D3305D3E599BF9A3E7AFB8C07593D9C3D3F6B5062A953AD3A535E2AAE9FE3330F7679BA3C8AA8148A7CA3903D438336005D27CE04FDD7996D8CB91CC16E0589DB83DAA8116807DF112692C7F7EB1B47AB0BD1B1AD01C2B1BFC163142E2C2201E25264F990D263D5C894A92F3EB5429B76A6A505593C6124F318E5AFEC264363D8A6A8B074EC11FC14B8D1D28A91B359098F96D13F678DE3FACE484B7F055AEC0BAB67294C4E066A8735927175017DEEEEC48279B4345FA9C54328F483F19BC4FCF041E03654864D7D8D6DD8DCF09489ED28A5558FDAA690607E617B9B89D000F3EB7630597165B6FEF520A3C0A32436020BDA3CE6D23B02F6DD03758754E825E26274F6F008C8B06CB2C73519C58A6F040B87404DEB5F870986831E44D1B02C59681F1085572BF4555A7481C9285A818591381565F789A4890473ACE39FF4B5CBE38A96A9BF080F591888E8F9120D8726AED7B074673B7652571C9DE4CB9683DC0480FF311A3EAD212DE017201AE60926F545B2FB9069A97C5A3FE8E1EDE0724851DEF601FC4F3234A2B789D408846F644D4B72DCF403762A06746E4DEC0648D9915AFDD4ED78FDB7BD6E581414CD65D61E563CFAA409708472C9F12DACD80475985DB69AB04A7D5266DFD035D258EA5E9E2BDEEBE8F8E41640048C1EFA16E2E8AFB8A9B1925309F9EB56038741C0AA6556811DAC4713D8F3BCA02D71B804A46274A1EB5552683D1D7B8D02A5BF541598031FC4FCE6BAC68F4E633A7EAC7ED95A2D98E51EE835F1B6EB651B856CBB84C653A60FC745AA4D39596A4928E52A19BE4623222FB62EA4F92592E8E4276DC263AFFECB0B1B2EFDCA013400D12274DC6628D5FD426096B7926D760DF07A9A225D88C91C2E1D0CE157092F80B02F479E25BE4380FB79F09D5453036EA6AF9888B01513916B4D57A252D25D0FBFE70798B7FC2A4787EFB43168E3807D094CCA9301D2CA260F5BBB5857E845892DCFDF352CC11FB9190E46BC6A5F11E5FF05C8715D5FFCD74DD3D32230B55D78B59AB84B05357EA13572F73DB08E0F352C420272422D7F4D7B3D6C45D834A87F27F121C52591A7993C4846CE3AA7FC3FFCBAED0F0901C2FEDA382572D454D021C9946EE106DE632E29B80DA99E68F16084C92B749EC8D488B35501F9A221A6081BDAFAB21D1CB2CBE259353A8BAEF08A0D9C5C6B813A0D54C60595D3DA67D728BC51BE65513A6236D9F6ECD0D63D921EC42E99F89B5C5880DD12947B32845202B2C1A0D1E0B67E5AC70AFE5278F352F1714106B8EEDDFA556E665E66BD5B3A1085C73FA8DB1DBD450B58FD1C54E6F5CEAF8B04CF86A3AB570FE4469AFE40888958214E1366C5C353E424544666EE75746D9BBF540BB787E7B4DACFD9F5CB4210AEFB13F198854E303FE041BB741033F7D17A5CA859B508F8F238E37A5F6CD02F54428396721A86FEAEBF52454AFD57E51A4324D7FA2BE0F4605447415872ED63E318985E8E5B579843D8A5C8F0A59D349937A7462722523008F0C0600CE1F1FC528C8002B175F9B83ADD71D5DCE81A606F06EC30932C31E0D823CB02567770335512CAE6BD623F9315F4583AD9D71952DFE009FF66191BEA6C12268D413224C8B0C845B8874031706FFFC77B63C692F4628D4BAC8A866B5ED446D9C307AC30AC9E93B3DF9990BFD3BA0FF9F169B5E9D73AD8440099B9F8D4BE7DD9B43F13FA8461BE47A53E11241F9A57ECA83286DFF1BA3E72C7ECD8271EC66F0C518B1234EEDC00A2694462154B7192AEA8D3A7882A01CCD3AE9B7AF9E0363F93DBCB4D9BAF3D84E44F396258FC18B2EB780DFFE941BF966A216F807090FE129817C9D691338E32E2B04E7F0854C46E6394F72E7B6B4B5DDAA31D02C8A4D03947FDC8DF3683E0FA83BAFACBBDAB083E8EE49076BA3034DBC1D935230DF7E36488696EBDA96D4F3DAA8E9C901FF363642F5A09FF77BEC12FA1975BE9093D50D1E8C81AD0440BF9A1ABEA276DF70523676151B034286DFCB6CF3654D2CFA9CE2DD6D831DA0591485E8DB5917B0F98ADCDE48E2E9DC659FB9D045FC0269049B56A7BE65B5E226128559CC516652F065FA5BEDFA2BFD667AEBA8C28F2A3FB31890764ACF957706B5E490DA05E7A5C965BA47A5C0C80D8243A16892B8496CBBF94CA21641179707367D250F97BF3A3697786146237D51995856A0D2A0FA0B2894E01D1902BA3222B0A32BAB432F424B947CA572DBFAAD471511CA2D33929740565FB6FB5974A3F6A0BC8B3DEEDCFB3814C8B173D3CEB1BD7B9EBB49E5550E8C572E2F58BDE79325FC31B02885F86ED4D86C7CC537A601E0795B94A83A121FDE019E09FB3E23100B983BF98C6CD2A400E7D591402397DBEF75870D475869EDB3DF542CA6C3F1C53CD8DF484C9E2A0695B214F977AD016640F1468E2E21B63A50C868920D8B42E2E947DDD1C6D6F8FA6219A9A503DF8004B128537F621643E3373A96B24E488AAE76B29837467C639F1B67B4246A95287A66E12F5CD433B2277AF52CF80BF0DA9D4146594F9074D937CA39E27440D29E500831AFE107DA8A6B8C461C0922C7F77000EF2415CCAF75C5B0959359BEC7EE9E3DE8F0CDF418D2914B4AA42CFB848109CF95147A0F10EFD8CCCB2058EF721F9229EC227D6DB6B72114A979945DED2ED5A8286111212041D05ED0FD7C9E0C50DBE4FC5456DA7054C1FDE01C8533852E37E271CBAC2F07FD0620D309AE49C18C55476D756B699718EB38DB78CA99C35BAF621B2DB7CF8A72870F8D2668C36845803EF96064140D056954EA974DF29064CDB98FE28387FAABF8EB4145FB68486BED845F6506F51A3B28FF2F514ED8859BA13F381E428E2EF3888587F707269E0E8A7F0A538F47D130661E2818EAEE75DA25A534D53A05E6462F83896A9FBF79EDB64158D4A3A739C7B4A44B13A6CEDA5D7435DFF3FDB10F12AB8B24CE8AC12A66966F68CB48DF7CA06E265148D697670AE71F4E1A244D4329AD10C1C44585C97A1474D52548A909AA4C4040E586E8A99ABB859B8BAE2EFFB088AC0C9000000000000000000000000000000000000030A131B2125ACB414EB55AE5E49107BD0AC5975544F83104F7264495AE0BF0A6D9594C422C16B99469ECCDFE8B8000875B469309891EA42586A615D146DE64FE59277A61631B2C7F7379CD52FAB3871BADE120EE9558D1479A91925634578CF14D35DF3B5672F8B5F9F956FA9F7489D6E37E207FE556017736F6B147A8CF664D0E0521D94737E18188A1B7C30296CCC9067E7B55D6E0F2FBD875F42FEFECAC49510E324968B07372DEB10A31C585457E0C48879CE44BC78898ECEFAC7BCEE90D0F8925DF2B52D5AC81692E0160F8FD5808645498428260F592E29BB90FCB07D0424EC79FB081840CB827CAA4A9D562183D10EE41D281E26CE3EC0069C83E1E446EF82E2E30DEBE3F409E0A9E6D1550E224DB15DBDDA44341E4ED6F8B8984716CA87233197528547D090058607CA141424A13145F1E896555288C5E2877AB3B51C7F9248D2D56A8521975BC4EAE3D009988CBD73C66931BADA0725FB8A3448D43E0C7364E9494FC4E295A700E79972E1FFD626D1CBE0199917851638B192EF9F5C03223F2BBD67EB59A5E8BAEC3DB40616938274201DEA1AE640F6EE7E047CC4C13F80DC65E3FCB5C62386015F4EF1BFEC561E121F9BFA9B2075BC1C4730503FDD5DEBCE8A535ECA01B9D5B021C290854B5F3D49EFFB263DDA34C4E96AEAE9E71A686C009B205994B46CFDF1F76727CA67D415B9D21D54312CDC6A8ED0AEAB96B580D0B419E2058E5D843C17C96D156549962F81C266233ED2B795FAC40B1992B626457F211F08106AD86F5702B9DEB9323A0970AD86125ECA836E0A3D6CCBC380D474049BD96EA246B8BD9542793A66E15B319AECE6BEE17ADBBA7DB337D25F8F642774030A2FF969CB5671F59901CB109E661E55FD5E75EB2A96DC37FEC76A82EB89D020B4916271CFB0CB3342494FDB62EA0D253FB8FF2E91357B33D96D41530B8B5E9550FE9B3F9F34FD5A2A1A6A8BEB93CCC322622F3B5E8487DE19AF57CBD1481ACE02779AD928B17A9B05CBEB722C783B088B5912C2D67CE5073F1801C23170DEB1EB6DDFFC4C33DD25F94F4FBE59D704E478FB49DD2142801C37ED8F539EC1782EBD2F3253BBE19C5A048B9EF41824A811119F3A6AD2A0D4B77338E001358C61A9794572B0C46EB1E0E575D4DA141A415829BA8712B791B625B1B0EA840EE745D9FFE1E99EFD782BA25859351F443654995102CBEFAD7E59D03C9A502ED7B77144D0566E4BFAC086A7DEA356CB9E5AC02DBF7E81D6CEED4A33DA8D801D61BAB5C01F259EE3A99FF7F6D7BF8F2160C4BC3F890736074B000C4C58FA4615880F93FAD43D5657C76045D7C414E6B85F63AAC91F04A616184E04FF9AAD513BA767215FB0331A369D36C0AE9B1EC1268F1D0B43C42B786DB23DD66465B3AF17FFC68C67964C2FC9E41EABC45DB68CD2C3D95B8BEC787D994BB8E9CF1DD7D4C563FCA5D80B3F1FE8E3C7BFB7D171F5B9023BFBCC0CF4371B63C856EDBDA154B4313C47983F4027F9E61E86DA1E8CD787E3E6B50E1DFC9201B9AB92059F8B6D1BF7856CD55C5B1D6C4E6EBF818D481C56F66C79444F5A6544A64A7D78EAD33EB805A6AC4310CD46A2331E707B9B0950CA12092402D68C1CC5C3F269DFDB13AB34B97EAB50B0745BE72BB0FD2D73BEA5DD37802393B635E42A0DEF8544A96E7F40A8D9D06B64E38DC406BD59AC5C4E218591D20B8DBA2125978096517EC5C03F9BC6F96CB255E216EF82D7C7C873029F9E1D98EBC0D8E1312B84B8D02E8D680AA56A506C8668B5B9C56D04CF68E37C7CB1B9377C867240CD42FC7FBDE0AC44E3DCCFD3F877C9923AE9CECE0CBDAB00CA530F434A33F1C939FB88ADEF4D12ACBD8B2B5A139A3FB776D8223A9846465C0372B8C3233FB5280E936BBE9FD49058961463A4419D939F4F1FEA705EB63114F0A3533638DC4D3EFD620147770AD877E2354299CEC6E5C18924E78DD661697ADF89A77C7365522D3E8FC0855187139F7E43E9A0629EE321B2CBD9F007B05C22EFF56FE48045686B36C5BAC2267F37A2E3D4E03E19B1E422ACEA31C2E9F3E7541976D4E2FA03119DF9C4CC2D5418F0FC7A467CD98E290695B9530B91D5DF8C626C7236A5C0FBA73578B9A47491CA0AD26A144B0F23EC23D2C5B2DAA03BF40130F14B9A427CDFF1F232C9CF02426228C570CF1FA7C00A773BC0D70858588542BBF8F581540870897BFAC8387CBBA3416A846CF9F4F5D3F9DCEDD080CC0DE9F71B93828B835430898E82896CD3F30FE2AF8349DB294FB2A8FFC0848692A0B9E8A66EBBFC0F896F8D03E3C6A0C27E0F2177B85A2F6FE31E8AAF14EA5C1FDC54E80CDE47AE27A161264680107023CFFA961E913C4E6AF96C0BE37AD859C334CDB8BBEECB5443662739D027EF1B9535A5A46E2169933E419454025623FD6779F54C622EF81AB9289B50758EA34F868EC85AEE589B08962B85CF537BC733F62AAFA95FD81A60D5C2E38D6EA0DF7D1390BC5050E2463E3E2E3A769DE2A94ABDEDFA0ED67CC0FFAFC5A05A3B0FD37BBE6967BED8DEBF02A42CDC80BDC62158E184FDB6672F7947505E2C0A6C7762B1145C4BAF30E3D32434D22707044DC99D2CF2D38F15C43ABC8632382BBBC9E0F106565906F7D4948D30FB19EDCC3748100397F71E1548E58A5A01876D0A12DCC80000224221C4ABD98A5022506D24BF4D9B9108991AD3421D4AB9CC393DCB8D744F97822F95CBB2640E73E401F044FE20253ACB8B32A75FEDA640E190454BAB695A23B14AE3EF60B00491AB22F622DAA89B6B2E6D18E735672FE0EB2DE269E4E386C926E23B865E1BA22DDA688293DE144102F7030FDE6DF653E4106C08C2467AD7C54D1DF0DC5981004876C6BAA8720F70942700A154A376C8D45DAE1BE74910148EE3F2733E591E1965FE763B58C8B28AF25E9B3C633ABD83F1C0A4F68DA2E0B85083BF97D4E919340C0437A604416C4F629B33039BBF2A1F561548321780411D2E8AC0EDAE76FC3A19F3C84C3BE902A1E84FDF69B11A12DC8B78EF257B5FBB5D923FFD548451A52C6A3AF31C70266AE8A957B2BD72A51A034A2921B8E19321108AC303B0D2E269D032C3DB13F21D558C82BA4158962F2210E1C5FDD96C98D6639AA844F34E40C1B9C909CC6AF1E97A8DC83B78C72B30B7AE400F44CA60AF37770B3D9147F7D6F5A327F34DF7CB8891E71D41D723CB18E0DD324E5CD22AE0D9F2B1D2BFCED0288B7AA73AF4FE0A8181BA1AA7EAE966D0A240E10FE5735D98326A106D16DC49F3FDB19D3A8449C56A74153655600E4C9E38D302C6D4080017D93C628388DF94860329BAA289EFA4587F079C6F03FA03C54540A0AB4B067EE46A5A346F2FBBFF6570ED0166A55C258EABD62AD90F060FADE84E8FAC799F7928285F58557A72E055B535D00BD9A4880D10C05C07CFE7A6FEADFCDED880521803E339F6EAE3FF28A0A471A003358F952320F41A0AEF9D28 + +count = 74 +seed = 5DE03CAB3CBD81B8805A17E0FFC2105C3BCDC8D782EAAB161A15AAA543FED59353C1FBE03E7F36B955FC51C9B30F0C93 +mlen = 2475 +msg = 5F7522CE6BD0CE6321C27B9EAA6F572616201F283C5EC171D0BA47662C2320897805E1551ED438F3FCBDAF9DE6F3A19DC16FE9C167A65B6E52BCF512C919561B548496A4A80AF7CE25458A62EAE92EBF677872482D8647C30C12BB1F080C6B9A56560D64FAB73DB17487BBB007C66661EA9DDA14601AB27A100EF4CF4B7447E51418651C03211F8FB884BE91F3980FE13E00EA4ECFE6D54882059A436C90BCAD80E4101CC6C0754417545F2D167629F80A3C5FFE45C00AB2BAF0494D6C065872B03A987A5EE818B3EF11E47FE1747F49E2DB6A14410F0B1F9610A2D6114395EF6EBB231FDF71D595CC1171DB9C89D6CF202E42D4FB968AB8105FDDB2AACB15FAB8014B534CF468D77ECDE2072623B7002620B7AC3E78B62AD673FEEF9F8E97E91ACDAB171FD415B2D15605DDE00D074A770E36F2218F7130F13E91FA4C88DEEA7E854BCAA01B8458D40625A33E982F0955B83080A926EC240E31F0D9BF477EE3A016E146A3909683410D4D09ECDF32EAEF580402F0D416DFC082CF1362E8B79158BD57739AEE56DC41A549E534C7CCF3620C7D7D95B92994A747D5EFB8EC43CFA8189BAA9B75FD54694E512FCA388B71A5B9EA591AE9CFA34183DE59D284AB16B2EFFA4B26A24A0E615B38B83088A9827EEB5C29B419BC061B033E0E3FC809AFDD3DE948412677E0BB5136854532639F3CCB176D54EA1961B5C527EF66F4B3286A583E86208AEEB8ED07D9E6BF1BEB33995F76CA480039A6130775895F19E3CD4873ABE3BF2FA9DE81BF0CB04575DD6AE282720B152CF0EC6A4A04016DB0F3543D8272AE56B1152B02EAF22131420CB194021F97060D5CE52EB21B57CC93964DD21344786E3888617152D2ABD829799CE47D20158AA93F7DA85CA6146C5BB94B512DA053C35BFA8840CA43F6509A1477603FD50F5E4F9A7CF8D2369156989AD638D35D345BDC859C52688211BF7EF3F4AD4944657289406BF01DCBB49D560A11840EF35DBC0C7F9C96DBEA76300CF61997A87D70F5FF8C51AECA2CF0680B6FE8C4025E1E25B62103D248CDEE335F4FCD67597103362003206C507970EA6D78CFF4B68B44244019152DBF812675CF667E5E13C8596EB6FEA3903BFB25ED08F902722A37F8E460E37A03A2D6ADBDF79DA20052DE658390484B83BBAB28D039A303D7376BF555181680B7966C798A1C6CB215257E37739DE7B9706CD1CF3AB031F68C82D6ECFA507C104115040744D74A40C49245215639D0CF4A5A7A10098E9CE3564AC3C44F0683AE9D3094784D354DB1AF439BDDF63D5CCA668D8180264EFECEEAC0BE1B8E1C6418E45F9ED6C779ECF169143B034CD9F332989D445C83A8786398C507B9171B4D95728575539CBB29C5B804268D88F2B39AF1F9572B8DAA9FEEEF69C4A77DC64BF2DBB5E57F8B33AB151769B2D00010D67A2D6F188D6D5B35E5E1873FE2B327E42AFB8885A842D26C246F7C18E6BCDD6FA49B300C65A3822121E95004928104017CBCE2AB95ACADB9802BF4BB049B8E96468353D649654C6F69D774380A5A387D6414DC3000540BAB6ECCBAA088C1068CCEF20036E5C8342FD512F55E6794BF85FE15721D99A1BFEEDC218617A940C8C25D4DFAFEC677D2A719B2CDDCD302294B7FA41AEAB5606F859CC0D638AC94B99AC3EA48C687D278EEBEB396DC5BF2D2E89E880F76B533FA54EFD30D8EE38B34DC5F8AE62C637E9A7E85D99E011F62D261AB4D3DCEB98A8972D3482CF817EFF476B873AC56963BD60183B359713385BA82F6E24BE2D6CFEA6DBB4AD2E1B5B790EE54D23F64E740502E887629B346FC8FCCC3338D0F2921131B84590B32C7CB82CBA8BB3B81EF7BC5CB12F0AA0B3C6A5B2878DC4F868057C68460C71D40D4263AC5C8B8317D2D0B63403C7549439A9EF227268372EC3A54CF8EE97714BC4B55007F92B1A32238659EC1EE27D6F2987AB06FEE84C3AFDFA73240963F076A955BF3C19410E1DA6A19B3EA3AE2DD8766082D3295D35436597783DAFDADB905465D05FC21FA8AC2737A52FA8AAEFBD2ED83F12545C1FA3198FF225D37070694C9392738E89467EDB2DA3CD1734CE398E32BCB1FEA2E4FE1260A2D9F9EDC3607A8AC8A51D5DA36E99B31903025E0CB157FD2FF5B51C9191CC16A9CCB870B4060CFB0FD900AEF62738A58C5726F5164417F084EF14FC0953E3C6036B818C21CA3476B8CC5F8EBAACE257A0315031A03E64E7F749B9DF99BB56CEEBBAA4333BC7270EDEE90FA2715BDDC38D44898A41998B2374B6EE3B8524D3A385C03868EE9479355092C4D20EC32DEB51497F4FF34AE7E7EA4828C288F46E5148DE28A8C660EE132E5B5489833DC66205EC968B60DAB96C2A4452A7019BBA9FE3D19D5829129E2A9C75C39416AC8695145F2B62EB9468198CBD48D7670DDC6AF2F99F77E7ACD01A34EA8E0E974206FBC22656867D09807B980563E06A559B0C3A7E6F43CF8DB75B18C0F90C12FF3BD43ABCE7DF75D17E631C08C974322010648FE2E2BC940E6510FB8835DF8384EFF3FE6A264687256C6BC0A5F9D2DDF208171DB55C4446B03CF27796BC77E3C68D8F1252BE21877D7C53747404420302CA5AE1AB57E43B158BE8B707360A2F59D6A473F98B816FDE2CCEDD92385202C419278E8B840DBA4C05E9BB65F68AE2A635A29110329E8C0C02F6FB5EEE41ED225051EE975F92DA52F93EB1FD7C0A098F6D1421701537298651313514AD31CB333E9C5DA719BBA95E73878BA41F9E2512862A80602AA2DE1E1D086576531330CC7BB8F0CEC38050B3CFAE5C8B1D6CB849A579F2294F8CE80FDE5405BFA3E6ECB01D5117203A4523591AC4030397DE9FF81D5CC91AF3002590F5854E852B88667638B2D052F2A7852425C8EC026E48D9EF5E73D1993D7F3FD7F704760562C36D2278C9CE131EC6AA444D7B2EACA3EE888D9B2AE122688DCB35455E7DE31562BA618F1183308B30D07A5C34020546218101AD42AC5054D4703587FF60E860A60375FAB12734912058D5B0B06430FABBFE0C0B43C22814F56DAE9E2713325A31C682C13F008B9A3D4FFA8A454F0F64A9213FF2D557A4CBC64EC6E4ECA0A976CD9F27497BA544DBAA3E2ECA0F54C2634C719B9C3A2CE37BCC8158A880BAA72780F8B1D3494F589E2AF3044B4FDD86F4DB2DF0843EBD9F3518870F55488F41E234CE94E907A69D28BD83347702750DB1AE2EB1454CDCA37A8B5FC90091F548BABF489E57C8919646E977274FC972088A522FFF9F9306D2F0ED6C01FF92CAE8440D7F3526B8C186D5B96942CB08032886051DA2A9FE77E38BEB18F4FB25F1152EDF9D61347A00A844929976A327BE46FFD3E2EE0B6AB1014294EC5D40CF7071C36B11127FF90720596C1B3065E7DE8010AEA469BB4F4AC5A6EFD20591CEFB7B94B2006D85CA475FEE556F24CC41237C631B75EB594F8342DEB4F976D73AA46563C1AA6D0B605A16152315626BA08807DAA6025CF62B29176F3A85E4BCA483EFFEA7E5939 +pk = 58AF116EEA69CE1A26E9D30B703D782FCC5F29A80EE143CB73DE30F664A8BA4ED73A3729E8E754EC4EA3EAB1D73AC01BCD783F508920A0EB53F239A35DF33D9E82B830A4A5DFA041223F9F70B1B7FD600D7B67EB3C249E67F32060E6EBAC52425C8972B71BE007515CAF63DE7155029D85E36B0C7FA878FE32CE774526D93593AA4D8907DE3241A8680AF06331543195FF37533C0F9F21B659369300F74543C9AFD2521A10A0470F5D40F17A3B21EAC5EA4F72A006D6531BAB104142D14574DE2DF75D08ACFB212A91C28B10C5A0B9A31BA6FA427AE0D4F76802E95483E786D40DE39B7B03EF635A45ABA7245C61FA0E3BD6E74E57F7D016D732AA29478AABE881390BC40B0B110E7E42AC35CCE42FFE4F4C59FDB2F3BC9F191F60FFADEFCE06BEA510A4BF65753F9CC0F8C91A49426934B1B6156BFABC8297DEEF32665E76A010CC421B70CD50FE66B8F2E49027C31869E87306EEC8A599D47BEFDEE11613EF89FFA132BD966383F9F485F5FBBA208EE0DD2622910ECF60910FB55903133C5C9D817B9DE5372AB81ECEEB9648E51D8B0329B3636AB1CFE384BC8E8F03AC2811902A45A2367C09951FE42A248AA776B33823FA0CA93DA491CF55FDC56604501D906531AF9D5D401C0644FDCC9F80E1308EA8163CF5283F01D04368668296ED69BB5CB1C4D20AC391D2A9EB9370F23FD1D13AB50EB1AA59D635524D8C97E0E38C1270FE9ED914B28A5C42F38BA5CD0532563A586125E62EECD2AEA1FA8951B50DDEFA40DF3848EF79768F3F2DEAFE77ACB281401C099FCAF80D30100C82BE60FA68C87F0970DE69F91017517E1E03A90BBFF34789688DDEDE9E25FF5CEF7E7D5F47782C7AE80C931C6BE32C60EBED0A89448F9C7E08232A3926D4D01F6E778F464F5E47307CF2F5EF7714B6BFE227A4A9010A691374872D60242E47C2CFB159B1A33775BDEBE3D4C56B55756F520EA8A69A3BF1579CB41D95F7CDCFF84E194037BD7666FAB6345A07ABB23F4D3E04D983EACBC6CDB5EBC202D36EA9E75F07D51E877CC513860B358EE1EF46237971BE44769BD075730C90791EAAB8FA90F4FB844230CAFB2B6E189D83FD89A243205C941E34788DDFBDA9AB48E1FEBE28133F37DB2F2023F6316F6C71ABB270906A965795919813A9AD178E067DCB2DBB6C9EFBDE35D94F4FFAF1625FAE94D05AED0C0D58CA907222426FB04E3A50DB95480DB47AC7C9C0A3159EE943726108C0544BA1DACA36DBF627AD755DF71BA7558584E51EA007A24EF85F0432D1642DFFA35A4CD9F1B1974617FEDAFB9BAFF413B66FDDB709FEB3831B84F936117E2EC80B45B502D6962BF28E7D93B0F80AF5BFD3E8540F8336264929B7DDAC589103D4682B34E949C7047918817F20B51D8D7AAA50220316C39435926A173721F5B806A79FCB8B57B3961E456A070FDB0917B8A0149AB9026CB8610A360A4D20B610C353A38A0A01F94E8C60A4EEB43A7CBCA8BD0D8376DD543F4D5F0869D3610075967C2D3A00B35D79FF0A00A89821275F7D86F7BE92205AE4B0DDA38BFB4B39B6DB4EA87476F0680001697F6D6B256DDF1497B678FDF5A8F7ECE061EB54183C103BC736865459C847B7B9BEDC196A2E84C86DCB98C62E66753370C9AD78C9790549F2F0A5D17D298C5A9BDA5606223CDCA35C0A57734840526B515A5B1D0DF01F816706052D5357C5629F57EB1F44D7724003176B221F73B79ECB81C0F0674A6304EA625FB1D46C4AA3AB4239C47911D36C10218D921C3E012DBD4B5C8D18137BFC05D88AFFC0AD8281658D56A415213FAE42793E2456622C8D5319AE90F6DAED6E41EE73294BE0F697FF565843B3064D199F56E8E1489C8C3F0E8CCDA122E9F7CAD0361FB2BBD86BB7E8AA9269707988D4525B73C5B1853F76B79498D6180B94D4AC4862A6AB9F38CE52E53482774E0D834C3DC219C167583EEB2B025A99641C5A0AB01483CD61C2A3DA5171ADE1A0E0B8DE2BF4BA0D474F585E87123D61750420C67B0BD7055A6CC1381ECE9174221FFAB7EC46F74D3D6E7C65D81F95FA5A11EC61252DF1FD88D08E9CC3105B80E829998CA05629755CD049CE31B65916658A724DA2625563892E0BE17DCBFD5EA67CC4E5895C6A96F5E5E6A54996D3A6E1F25A4423F8FCB217F555AC42946F2EE00EF1FB75732C00DF21E007A7903EF977731E82EF42E8651B1CA9709347B947D031AB51EF82A9540237C4D01439344467E593BF3E0CF594693EE6B48BA5C235F252F4ABA53AE44B1412499FAC65B1F09C2E9DD0036DDC06D6907E849720E62639348E7340E4F0858CA260F2D671F18E606F1649920C09AE8764479CAFBB1E7CBC81C44C11C0B46C70F22BC20AF91A6EB38E159BDBC52F7839D2D3369D6AB7E4A2981E2EFF6279B70980613BAD73C6ECAEF66B480D73720076B3B30A6132647841000165910D4993A5FCA3EC21894D905F7D0D209551A9B60751B20A5A020CB743BDEC24B5EE3B3C371A53DDBAA96107D23B24C604DAF551649FD9B849E1FC55892E3D0D01221FC4DDD218F1BB37EC0220AD5E4AC08BBBFBF5AE30A21C1124602064D7BC7276A877A2EEFA4A8D57D4A22B0679D56CF643CB8116D9F9E2DE9903A7C2E08F86696AF2AA6988A69A69040635D716720061DF241AAE3E64694BFA39FDA0A7F0137BBD9A81AD941D27F14577F7E37AB7FE4E5A5FA8A0054DA4733BB3B65969E67110D7348687CDD58C744EE2B77C1827940AD30F8285746D5C1452535017BC2AE50F +sk = 58AF116EEA69CE1A26E9D30B703D782FCC5F29A80EE143CB73DE30F664A8BA4EDF6A7E98BE7676FA67B0908317AFF58682888E7E7482EEC1955CA4441D34079FAA33117E580ED24EEFAA441A88B80D5D335EAFA3BEDDFB7E7E5E7F317C885E15D85C860D0FFBE6334088CC2CF14E10FC4FDDC9884D02FA7AA9AA440A057C3AB025101216443246260567048412414134085276777868424213785828481467141160770137761380616716586845680243145116427706848107128125104627107414225884171783241663678315302700686001100171276086266107728137677540425251701731642381484785611504582132727181315014861800365483407006665430573546584827085286813853363027161576445706535161542030437733467223557206243743471524787146845413651843344562857233346245441421657334741152642277878732503343346818636047833525542341801235280218663237873384524234062826416745027677614414711040038874610340028601117474173832663370412734070152586340400470275353382852023615073674616243746256525455076032458043533543874005460215035604313414315053013811487555575080651536407253581865220752803348224773545255116643536301643575208547163184550784041878787377326273226305457746485524756762625080070721214487612840385837024520625718486565751342522264264663545550775735370467111701285025272066715878220174162383562178568167888744872488640764865036001827106443532068853582604442484743077121008585618410488326350761054606776031671162157116062384883087181883304626771234751818347730850352788623521445323012464023438620212648543502422633443153008245735545254078246244478835365622375437748123703431570537051318855216318510087508375242025044614774131843806143400027731824814136377513485022211128803404807146776080171704801356166406257887220103834054371324450712230714853811454167510252637431205403813264016453178308457324156832227735257076462073244422340827466167627121481220510086833505306734600665620272831775827320325281413825164640558722843025703130081538532633477218628547552575508114414064883461583456226003805638820461431721156162154784713827255358778206768033587505374754873424168687247531166545012314630008856067270077163272464721865347654315013701337555325254160324224552885002442353258618180327372330440600826504060174356851888577881052326735702222770062862635131467223637655132328301276375772545650463334135326670433753601054234282754408871054322852131342766345451107605278663740651861685370571605567388137008554064718852684854034607413557705563072750713415773372804128440403101184853505266656433710445574843846070413262766752331755647551154557432116077547084724617613270524461017767640618381325712411047485005838362882205304321616303713028087234004522586140011103358673834262232121045088517737754133138672176731232246013245032414027087683755474117327324543707757138017878627848774341842616786360044273031042060013427235453624843700151780134552616123870764567244735107722858650388064117377518140765877046715720182072725816485486702678837233180878380042457433135353751122554000256883566371646722352673062248670858346606745316088888010136707306512077271736153334688586111184324771854520078862544210755204246323774821480768610421588864415078864261525654717042558464243061627218872711341067142667781336508100E60F21DDEB043D549CCA09D9F12C1B0178C768E1387906DA9BA14FB427BD59C28F5A7E4582F17C5C6269B9773A34EBFF2573880A4A37CA9804B1B2423E15D1D94DC48CC1578FF8F90B526E8D4A5E06BC39B56695DFA8B61F9C993E346BB886F0C6FD2C86B561080ACBECD990B50D91D55E021B329CB699E245275C0BB49C8AA61B3CC4C0719827B2A82B6A9C1C34931CF14C6889F2CE3EEA11E240BE027A543B45AC41E546E632D9324BF07D2727AFB66CF06AA8FE792228C8FCEF6F9CF0EBCE666655AECF9F9C64A84B56A4B275830F6FF0D6FCBF3D4442BBE95A6C5AB3B52262A9E6F9AB411FAD7DC2463085EE3BE1383644D48887017BDB11AE60DCCF84B6CD5A7AD67C520E29F161C730A3E5DD41960713A3EB29F045249A1D83F18F4FFA411E8FAD61775654669593873AB08F3DA4CFD6D4CD04F47166625E210998A230857F9614CF0852A0F85C3F949169F0DA46CCFA152B482E31F0CE9EC93BDB00BA4F76B81D0CE2DED4D868BF50DD46AF83201CEA4842AE569D6F657299321F3F5A0070D1EF5AC4DFB045474E48632B28ABE938B5EB31C2B3EEE25F88AB0AE4CCB0C1595E54836DD768D901A738984149A1396D4298C0990CC34BCE9607605482643E5612D2A8FEE6D902777753892D7342C6A894ED911B2612C9A85DC3246004132E1D08FABFC65EE7215B13E37D01A163DE0620F7F6D2147B9F9FDEE4EC72B8822D5236E8A5AE7D52FB649D2D53E10DD9A1593291780BA0DF1203C958942E284A4EA51844973DB17DB02C84D7BC03ADD2D4617AFF5ACC440068C201494FA584EE7B348A8697837930B351B421EEACDF504CB4AF1DA600238071E9961313484ABFD8AF28A8DD21D4A0038EAA0772EFE7B019037FB8D790987A6BD4B1E81BBC13A4216B7B20E50B6B9B88E5252BCA6050FD30A5135B1F81FD1DBC9760D93D14E2E9EA5792151B0673F375BB6565AE545DB8E89B80FE644018CDA916D7D3178A3A6271281F7C2A010CDCEB8AAA0F95AA4158FCCBCD579B84E80B8D86FE87D7498F562C8BDCCE296CEE757284978BC4DEE108FF4AF397FBE0518DB08E702342C97151D2286CEC8E383A7B621CA9585222DE03D85B205A14E9CC1B32BA822E4FFBF86687E9266AB2440B78BFA97E73B2AF5782A808BF9B2006F316E1500A5B48852D5F257A7435AE42319B0A08914C79AAEC868AC946FE66AF40CAA49B41DAA38A691F11EFE9B7F0175A7E1AB7E95BC753CB002B3A5B65197248CC75B7153211FC23FD0711F3A5D467D57F1413B545EF3792EC535F43F63DBC3ABB24B82EE1A717123E1EAF8F56CB743BA0F577B74B908603E3FF16F6BE1ABFC49F355D4B4D64E1A17247B79DF4A1D261FA251BE3CA9B2A1EEDFA7EE6861D3697D57DC7F73594737B502F1CCB5DF774A3988DA2425ADA7B3C2F4711A4CA31E6D90BF3C730C15FF4034650E75D30920A86FFC078336EC2DE67E8F052C56E6AB1DCD396B6A672120757BE40FAABA8CE91E922CC3BA0066BE8DA822CA36E607E8906DE5FF44B6097868815B45D78C9E27F6463DA4CFB98508CB201FD13A50EA0618FB9BD7A8F163507F7FD249C730E5A00592C338013BD0A0B3B530F99A64614D575CF340865BFC63490452722C8FA2E794CD93581CE0B3868D0EA497E3A8185A744DF9350109E02F9797C6451503CB8226CDE5FB5FAA13C150383C45F50072CDD1854BFE65AEB67A1C70522670F914EEBC98ECEBF7223DCC28DE0265CEB6B244CC3763D13AED81274B0E67F3840A7FECF7F2500F2D7646A2101D547E9E9C281856B18545FEB7E09A8D3AE07EFC384100AFBDEA2A1826AF200C93A9ECFDB9A4A1D8C9961F818F23A743800B738566BB67C63B56BE11698382CDAB2531F2EED1FAF776F5F6D2B19E487C116C121FA6ACA65C59BD32BBFFC8B67B49485249D75F6BD724C208758E8DD8A121346D7AEBDDFCCFD33BF85A88F75FF5B01A951B107BF026A1335C1E4985A2E7F110A90BD737A832DB37B7C015DE851F4346581A13373F37D0A0AEF1353C7703025F11E69946621DD511B015A2D27E715A53FEBB49E08C05C5B22431F9D168FB9F21A3A3D5F3AC6D44D1A2626BC7593455A70B0EAC14B1EA73E20E4B054CAF1148B0A671EF22ACC6DF848197843840E2296C0A11E8AD389E0FD4E8BBC7C3D706D3FD4B04DA58EF6A9642E71FB80344554D1EB5D37C71659743CC504DB95829F84CD912AB3D50D17E13827564DDAD97F2E87CDE072C31B0F33936ABA5B69F69E664A56745E0212BF4322FD547B49815AD206069FC34E95D3A47E105F253E5772E2B3945EB833E6C9EA7A252F1823A02A5FA548EF203185D40CC0A1DF959C30F2A28EC3E85BF09A02FAE1DCD9B9AB15E8D530A1BE241392F4D3F7C0219B95C05EE642C7FC06A21032FAB0B45A23FE0755E9D703097BFBD90297BBC4D360220D43344D5A1993838CE03C65528D5D248320D55918F6360EC29B858FCD26988140A9F79376B4E700F8626A7214482D55365D4BC2FC91E289EEEEEF4EE2CF100210E22477C95C3F0184DD398441B53EF50060760E38004EF16ED89A6BC466DF74DCDBBAEA7462A55D11D263E2318C33232235E01865603332D4F0E89AB9379169CEF3154E2B2C982C6495A7205CD9A99BD382C64F1247FF4A567BAD2868D0892DA52F94EB16CF17C8CFFD32884CFAE0AC062A0C19AF06AE0378B60B0DCCA37A740AD4C169B1A01924A2DC7873F71D91F0CECDE96866DA31A27FC0DD11B89F78FEAE6588CEBA99900D209429E5FEEBA335CD0928DB565465DE75E7694277C211045201812F4F667E884C176651B475B228499849CD3A15A45B3F1CEBDCDAC250C6D6B28452604EDC731139506F81EBC0FD2E63307CC4230702AB79AC61273FF3B62E4FF8E6A7135415684F3ADBE3CCC981D161E5455F0EB2DA1F4B4B0EF57928E14BAED8046CE2F68B2CA5293DBD70AA72BA7EC1E51A66B2D2A1AC438BF9B784CD19E44E65534CA69ECE840F67C04DB817B13A747B9EF484064BBB5E14232AB4718B8C0005CA364CCAFCCAF81747F13FCE2EB4C04A044723F1A82D0247F93664AD6C5C1D6673739056D5183552B8BFD4B32EA837AB15DEF47E01A6F52B57656CEE7498CAA376E34260B8C9F09A9996F743AE3748651B7BA5E46EBB399304BC0CA6382AE6E3595C2225AF4E0A3B4A73FC580EA2F94FE064477D9F41E0FFD771F4055282CD6915C72317FCB1AE4A6B5ADC0C1284761FA960A96A2EAE9389464CD67B1B5DEFC68974445E0ED0BE556F77A8B54629950848BB89AA9464FBA96F60E9347F4A1CB4A2CBEEB2158B1243DC8245FCDA3860C3DCA358B9B31BCB3E5D4D7CF65F75BAADD9399A2003564B6818F267D6B605680272C9849D1F130E4F3C1267B9E486D24626182B0A381CAAC78C6383AD632844345154AF6965E8A53FDDB68566E5800A5DCF65DA8515AB675BB217C6115932A46281C99486DD6173029B13AAB40094928E391F476EF261D512143A0782AD540E8477C19B4DD2FB488BF6A21351E4038 +smlen = 5784 +sm = F981040C217D325B5055E1920580F74A0FE22F998CA26EE2B28B550463B58A91D027F5904C80572200AA67FA6EBB277E5479C9B74526575EC8F8B32DA2FED11E9372CCBB397B869A1045E213065103C61E0187930A60EA457EA7652819ECE1F23192B43C21C22908ED93866D908D08FB50039E7188B7EE0842EC4A7C44E980CE389A2C59EE88FB6AC5B3F9C2E7AEEE33EF391BC7809DACF24B4F884369AB94FBB90BDD738B98A126C063E0AF4FB19217E3BCAEA8296A167214F3BB60ABF4C038DFD9C0BDE59C4255AAD509E46E6745BA362AC47AAA390CCABF394DC94691ABED3A3F4822F077754066B30E9F49B7A290052F1FFD3D51DD6CDBCA3E787465C75BE43067FA4852655424DFF55F954E58E283FB1963903D9B582E46C7AF8A9C12078E1D3A26364213B0E59A2D17ACA3FD5E3CFFD087BE91E1D6B11D59AEBC97442130D5B3B6BC9904720CC65333F813AED744B9B6E87B113D6F25786950878DEA85796F2C847EAE0984E7A2C0FD9274FD94C687D859173A34FD87500BBD512CEAAF41873E0EE07C99A0E23D42C28159952D9DA3E7DADC18AFE68AA95CB3F8F25EAA10B98CA359066F4520DA7F16876CE77A9EB003B5633A096FD9E54B5C784AC949B2F7AFCABEDB9519D52AF259A25E93401E00AB038135931A485BF77EE571B11025C8CE445D722BF6BB3901FD618403CB815649E7045DD8C41DDCBDD0D15D861D9B8BA30E5DBFC6EF52007741F35969D97E739C645E5B7E3A8840684BEB4D22ADDD2540D2392995CAA54DEE56C1A2F048A66075CA008BA5AC9A93C7D65C4EC55CDCF12222E08757DD4134AFFA8BD7BFC283C60D1E7D1DC08108E25B26700045B6C7D051634648AA262BC4A6026D57E7295CC20BB268720E08854F4DB6FC681D7C3E484D2E61C91805B953989B6C87363070DE5B3231863A3C13F81A37B559D48EAB9EDBCBB1366E2F3C829130692CE9414F69BB7EE838BC76B820FCF61BA37D68702F2C0064488DC5B4BC3CC3EFA89A234CCD7232787AEEB73D8EA95E3C20B1A0B879348E50B658967CF9F7062661AEAA087B66119B3E50E3722508FB86589737B33D21A67D4376D5F5BBE05566E831521D77D5C8740B9304F06901672E5D4D85E9FFF4EC6C96E7C1B2B7366E54DCC70A851089CDE3F3797DDC716105EA08482B3F5078563F2B498756F4E5B3EC0EF8236A37B6F9E043D5C3E54E97DCF0DA9F592E9F9588FB6FF74C0741A462AA126F6E1701B5A28B289D0BA32B2B1C9D1C2DF64F00FCF18AE36C81D2C54D248A8F9C2351E35806FF748D2BC24D6F49DF2DBC83837AEC44AD415E263C4CB7A2631DACECD8701997E2B1BA87B5F8A8F2AADC80D529C2C2C300DFCD5210E14CE51B297DFFDE1AD78F08016E9ED710BED8BF5569CB0845F67683C72364A7F42979A41653D3351720FA08F4CDE553CAA8AB3D84846DBFDD5B641BC7AEBEF16F16A0195E737049F8EDFD87D395D20D3DCB5159DF08F6D4FB492E405685D5B1CF09A3EE2998D6C52646E0A736B46F67189966E09B66C0E27556B8113FB98E04B54C1CB89CBDEF42461AD00554F08A441753416B7847FD920F697DED4797FFDD52ABB42771C387AFC53AE6F515181B27421D3C2DE0E317C960D5CC615759C68CA6C64B93695D22685B9346F8086F1C136A795796CA729E88E5E3D16AD45B0B956F64071C3608C890F70FC0510C42CD39049116B825461A3C1F69C43B77D634C93192EF9676FC2ED0907D798DE123226846CD8A9018DD8FAF68199D988362B887966F6C6E6228719BBFBDCA35DD9A110B658EB51D2FF22678A01BE6F8D61C57B78F1D8892BCA07F6D0A388725A676C1C8760AD05C9CC473DC9A64AA27ADCF290B9D128B26F1E994E1D05261F6956D1C05B68152D5AC44D1C69965A3FB6C6A2D161AC0C8D7212EBDFD1CE47E43E69EA50747CE63462155C02BDE1D5C09881DE79C117C7DBC0E8D96E6C34C139781B41E3573F9FDE01D7670E4D341B3C6E8881272DC99F745F519FD8E4291032A7C2266B134F25CE799F4279B30A5CA399F13BB69BEFB32DBD3D7A5898B4DEF8319089DBFA0D949DA023C655FCD69AE91EF3AD0830AAE530104BB051AC073B8234555CF02577B3708574255809519D9F87D3415068E6C2C74F15502B2E477C04FE6FA76D786938782979E83B1C6BD26BA927DF9EF1FF145C8F2A5040C9E522918121FEF338EAF5B2307D8EA9DCAE08109551BF7627BCA43A1E7DB36C233FD820DAC44E476D41656E8AFF200A4FC29243B2B123CE40B7BEDB479579B6B65A6BEE564CE788E4BA74FC74746781A8110201293CD9D2D1E38C5837D01EA09146004B5992E6080EED96A7164DFE92FB41E887E6201472807C511EB2E2A89E297F42DE1F94DF1F68216B1A8FCFF11188A5DA029C1DA07A271E61AD8819694090788396D50121024E8C6EC9282F5FC6340B21E1FC806BF6F8BBC53C0E981CC4A42E33717AE80EEF7ACE8A7AECE714A76847F3771B2C731B619A3FA8A56CCAC4707B6297485922F8040BB08C94425E113ACA2F96502C0468B52630448C7084CC8C1DCA2C7BA43B26C83CB195FC7E40EE6F9F59B79052E4A8EF50A37E72869B47867C2A14030E4F606D0A4F7DEAEB3600289C539AFD8C8325928DE027AE78AD2275E4065012B13E08278BC33102AA046BB73551E88163C1E59A0C953CC75EA255B5814E9C4095ED0B2C4E3CCB6D351F040E10CE18752D2B8533A2555B79C6C8570F5BFCBA856B115E55B675E75B103F0C26719308C13CAAF3025066AEFCC52A4B61B43B281E3700F65886CC25B4254014F15E18164D886D581E2980D1B37497C4DAEE056B3C40755194BC4070404D9737B3D399295AF356B93A723A800FFA5EE9D86BE9805EAB866369334DA129354589366D181BFE36B98D3F47B28DAD93CD8F667C2E7BE82A4F3B65EEF6C7B9BF4A5F32FE9D85B97685E0ACFCECF18F1BBF1C51FB926874AF7BA952ED75AEDD3454E44FC74D3BE3BDF9A04659FA6CE45CF2AADB586A7BB4A8F7F416343411FE281B25B12B47F2C0312CEB93B5D68114510C7E9DFA2AD085E4D65581C868A8301C911FFCFDAF905C0C151D914E79A7F32C3CA69271830D3F696F3B5FE51CBBD5B9714A713C15370B7AE7316ADD15AB0F0DBE4CB8345DB59D88A04986EAEA9D9A14559F4563DC85EC57D7DB19B01261408BB5DFD9FA36FD7B56105301312CD9E3894717462F4514944874B4832E98F0796655450AC6EAB9A80B403949AE4737C8D045B1BBFAF566DB5CD8656D974C5F435313ED7F55ADC8591E6C61E877264EFA90BAB78D2911852BCBEA8FDC400B312A0767708B7A0667EF4CCC2619EBD04B2C43E8A27C8723FB6B28F72D679B993DBD4738FD249BB6277F63EB2CF6C36DEEA1CB57A10F5B245DE978912DBBB5F3AEDFE3CF4B45C7A9B90D77285E36AAB71ADD3114026A402AB6063604152B3EEEE01B6789493C80097C08E7E3744F2213D85A3101B8CDDE2CD531BD7422C74387866ECA0DB486A66300141BE564A98C8FF9ED8769D9728FBC5223E0589860290F5A66292028492E8EF704C126F791A0CBE40CD504A8916E71630D66AD54F9E01C3AD81B1F3C0369F01DB29DD841D7FD89824E6E8F6E1676FC62D729F3F4B45AB3F8C72A85DDFBEDAE6FB48A896BF18D05218C4DEBC91F42527E4B526121496ABE71F5848796CDC1908D59135082BD4B0ED5997B57575A2F3DC28188A85357E63C46B033A539A70CF70BFD4AFB73D026B3492268DAC07061DE04D87BBE9459912250603071FF1FF1E8395F1BC7661A0B45258751D85F84C604C46B0675798CCFD04EDD379CB7B073154E4D274469768B8E7967D7C8D3F962C5AC0ADF5B35991A0C2F0ED479D4C2C9DC2FE068163684201F174D21789914227015DB3DE976B5DFE3A8F54F1352817BD68649A09558CE9BC2BFE07ECB8B731427877BA6D1F58C0C9C28FEC78F502A10F406044D629B512651DD0944CC290D45025135966A5277DCC07A8C5D026FFAB3691AD6F0336C09707AF39CC4F7877E33EAE1275E2D2BA0945EF0F8AC29632452024F3B20A471783BD5A07DE22806D951857E5F922DDFD85A272FE93F5FD049525210E8D821D56D0B49CA74E43FAA1630A384D882A0047F347E6574ABD6601909BC97DCDA63E89DB096B4882003E0AE13E4A2E9898A069B8CB8DD70F6E4093F55BC274B109E42590C30B786083B53143E0743E46DEB2EA9AE7CCBBE9548AB53F59CE4E9863D1C50C764D4E6FAF296F39C7C2E3AFA4B3EDF9BEC7338A9675FB8F88B50B816D4D5BB13D821E11981B5DC025FC11A7DCD836B241AA7A0A4FC63E762A5B469D2F6E862B60D9AA726F67B253C6D17806657E101D36CA608EDAF8E52AEEEA85DCBE7882CDFDAF4CE5954BEDB7CFDC4B65390414E7D87DC8677C4BB578E4342E5513DD1789FE2785D759D54F315F1E5C579D770100FB31B060EADED49C08A27114839DF4DADEE0E9D4D4F191A80263A52AF275BA9B6CA1A565E350F31CC682EAAF2717FB6EF7035A9F4C37FF1CD63A9E30939083815AE4E1EBFFD3B31908844758BE0768E8F79F4D0CBBC84B3C87D011C40F2246FFC99A0D88DCFF03151C263031365B9BAAB8C3DD23455575C7092D57669FAAAFB6C20E1E629B9E060D496E8BB158AAFE00000000000000000000000000000D121B2026295F7522CE6BD0CE6321C27B9EAA6F572616201F283C5EC171D0BA47662C2320897805E1551ED438F3FCBDAF9DE6F3A19DC16FE9C167A65B6E52BCF512C919561B548496A4A80AF7CE25458A62EAE92EBF677872482D8647C30C12BB1F080C6B9A56560D64FAB73DB17487BBB007C66661EA9DDA14601AB27A100EF4CF4B7447E51418651C03211F8FB884BE91F3980FE13E00EA4ECFE6D54882059A436C90BCAD80E4101CC6C0754417545F2D167629F80A3C5FFE45C00AB2BAF0494D6C065872B03A987A5EE818B3EF11E47FE1747F49E2DB6A14410F0B1F9610A2D6114395EF6EBB231FDF71D595CC1171DB9C89D6CF202E42D4FB968AB8105FDDB2AACB15FAB8014B534CF468D77ECDE2072623B7002620B7AC3E78B62AD673FEEF9F8E97E91ACDAB171FD415B2D15605DDE00D074A770E36F2218F7130F13E91FA4C88DEEA7E854BCAA01B8458D40625A33E982F0955B83080A926EC240E31F0D9BF477EE3A016E146A3909683410D4D09ECDF32EAEF580402F0D416DFC082CF1362E8B79158BD57739AEE56DC41A549E534C7CCF3620C7D7D95B92994A747D5EFB8EC43CFA8189BAA9B75FD54694E512FCA388B71A5B9EA591AE9CFA34183DE59D284AB16B2EFFA4B26A24A0E615B38B83088A9827EEB5C29B419BC061B033E0E3FC809AFDD3DE948412677E0BB5136854532639F3CCB176D54EA1961B5C527EF66F4B3286A583E86208AEEB8ED07D9E6BF1BEB33995F76CA480039A6130775895F19E3CD4873ABE3BF2FA9DE81BF0CB04575DD6AE282720B152CF0EC6A4A04016DB0F3543D8272AE56B1152B02EAF22131420CB194021F97060D5CE52EB21B57CC93964DD21344786E3888617152D2ABD829799CE47D20158AA93F7DA85CA6146C5BB94B512DA053C35BFA8840CA43F6509A1477603FD50F5E4F9A7CF8D2369156989AD638D35D345BDC859C52688211BF7EF3F4AD4944657289406BF01DCBB49D560A11840EF35DBC0C7F9C96DBEA76300CF61997A87D70F5FF8C51AECA2CF0680B6FE8C4025E1E25B62103D248CDEE335F4FCD67597103362003206C507970EA6D78CFF4B68B44244019152DBF812675CF667E5E13C8596EB6FEA3903BFB25ED08F902722A37F8E460E37A03A2D6ADBDF79DA20052DE658390484B83BBAB28D039A303D7376BF555181680B7966C798A1C6CB215257E37739DE7B9706CD1CF3AB031F68C82D6ECFA507C104115040744D74A40C49245215639D0CF4A5A7A10098E9CE3564AC3C44F0683AE9D3094784D354DB1AF439BDDF63D5CCA668D8180264EFECEEAC0BE1B8E1C6418E45F9ED6C779ECF169143B034CD9F332989D445C83A8786398C507B9171B4D95728575539CBB29C5B804268D88F2B39AF1F9572B8DAA9FEEEF69C4A77DC64BF2DBB5E57F8B33AB151769B2D00010D67A2D6F188D6D5B35E5E1873FE2B327E42AFB8885A842D26C246F7C18E6BCDD6FA49B300C65A3822121E95004928104017CBCE2AB95ACADB9802BF4BB049B8E96468353D649654C6F69D774380A5A387D6414DC3000540BAB6ECCBAA088C1068CCEF20036E5C8342FD512F55E6794BF85FE15721D99A1BFEEDC218617A940C8C25D4DFAFEC677D2A719B2CDDCD302294B7FA41AEAB5606F859CC0D638AC94B99AC3EA48C687D278EEBEB396DC5BF2D2E89E880F76B533FA54EFD30D8EE38B34DC5F8AE62C637E9A7E85D99E011F62D261AB4D3DCEB98A8972D3482CF817EFF476B873AC56963BD60183B359713385BA82F6E24BE2D6CFEA6DBB4AD2E1B5B790EE54D23F64E740502E887629B346FC8FCCC3338D0F2921131B84590B32C7CB82CBA8BB3B81EF7BC5CB12F0AA0B3C6A5B2878DC4F868057C68460C71D40D4263AC5C8B8317D2D0B63403C7549439A9EF227268372EC3A54CF8EE97714BC4B55007F92B1A32238659EC1EE27D6F2987AB06FEE84C3AFDFA73240963F076A955BF3C19410E1DA6A19B3EA3AE2DD8766082D3295D35436597783DAFDADB905465D05FC21FA8AC2737A52FA8AAEFBD2ED83F12545C1FA3198FF225D37070694C9392738E89467EDB2DA3CD1734CE398E32BCB1FEA2E4FE1260A2D9F9EDC3607A8AC8A51D5DA36E99B31903025E0CB157FD2FF5B51C9191CC16A9CCB870B4060CFB0FD900AEF62738A58C5726F5164417F084EF14FC0953E3C6036B818C21CA3476B8CC5F8EBAACE257A0315031A03E64E7F749B9DF99BB56CEEBBAA4333BC7270EDEE90FA2715BDDC38D44898A41998B2374B6EE3B8524D3A385C03868EE9479355092C4D20EC32DEB51497F4FF34AE7E7EA4828C288F46E5148DE28A8C660EE132E5B5489833DC66205EC968B60DAB96C2A4452A7019BBA9FE3D19D5829129E2A9C75C39416AC8695145F2B62EB9468198CBD48D7670DDC6AF2F99F77E7ACD01A34EA8E0E974206FBC22656867D09807B980563E06A559B0C3A7E6F43CF8DB75B18C0F90C12FF3BD43ABCE7DF75D17E631C08C974322010648FE2E2BC940E6510FB8835DF8384EFF3FE6A264687256C6BC0A5F9D2DDF208171DB55C4446B03CF27796BC77E3C68D8F1252BE21877D7C53747404420302CA5AE1AB57E43B158BE8B707360A2F59D6A473F98B816FDE2CCEDD92385202C419278E8B840DBA4C05E9BB65F68AE2A635A29110329E8C0C02F6FB5EEE41ED225051EE975F92DA52F93EB1FD7C0A098F6D1421701537298651313514AD31CB333E9C5DA719BBA95E73878BA41F9E2512862A80602AA2DE1E1D086576531330CC7BB8F0CEC38050B3CFAE5C8B1D6CB849A579F2294F8CE80FDE5405BFA3E6ECB01D5117203A4523591AC4030397DE9FF81D5CC91AF3002590F5854E852B88667638B2D052F2A7852425C8EC026E48D9EF5E73D1993D7F3FD7F704760562C36D2278C9CE131EC6AA444D7B2EACA3EE888D9B2AE122688DCB35455E7DE31562BA618F1183308B30D07A5C34020546218101AD42AC5054D4703587FF60E860A60375FAB12734912058D5B0B06430FABBFE0C0B43C22814F56DAE9E2713325A31C682C13F008B9A3D4FFA8A454F0F64A9213FF2D557A4CBC64EC6E4ECA0A976CD9F27497BA544DBAA3E2ECA0F54C2634C719B9C3A2CE37BCC8158A880BAA72780F8B1D3494F589E2AF3044B4FDD86F4DB2DF0843EBD9F3518870F55488F41E234CE94E907A69D28BD83347702750DB1AE2EB1454CDCA37A8B5FC90091F548BABF489E57C8919646E977274FC972088A522FFF9F9306D2F0ED6C01FF92CAE8440D7F3526B8C186D5B96942CB08032886051DA2A9FE77E38BEB18F4FB25F1152EDF9D61347A00A844929976A327BE46FFD3E2EE0B6AB1014294EC5D40CF7071C36B11127FF90720596C1B3065E7DE8010AEA469BB4F4AC5A6EFD20591CEFB7B94B2006D85CA475FEE556F24CC41237C631B75EB594F8342DEB4F976D73AA46563C1AA6D0B605A16152315626BA08807DAA6025CF62B29176F3A85E4BCA483EFFEA7E5939 + +count = 75 +seed = 63742CEFAE9868C3C0B31DDE0F9D378FD5D71BE7CC3F0B6ECD393DB55FB043CF00264852C45D1836CC12B9C872A20251 +mlen = 2508 +msg = 9FFA507328B2129C9F05A22B81A597FD1B8C27D554B36FD3EB150BC5FA0C6ED967EC5BE6F1E52D3BED1508DC3C841360020CFC2CA1B0713076251F2935EFA8500573CB4634C78A1D0F87D994E8E2B0BD265A877023B54D9A33282C12397DC74CAAB07AC2EFD140DF907651BCD1B37CAB2D03F77CC28872291F1CB28FD4BBB5331C2A18E02120BFD2D9EC0C8938A6D43681DC03527FC2BF59703B5160D8E25D08534EB5AA5CC9C10572257D9E4DB29235683BFE1776A2D9EDACFBA1ADAF66587BC451D32C524C7934556F94776F91CDDA96D2E5CAF91A39503D3A742DC5A0EFEF7C1A13666E200C5E3FD7652D200ADEF51FC5136281570B7832E0C6E7552972E43291F202E6F916C916DC3FA48858F3D92B1B7EFD42DE140D43648AEDD7C7379D7A4B71751A3348B6BBA3B0DB71B4C99C41E085E5536A3F0D2BDDAA88069249E21E2D9906191BBB5C8B45353DE72E00270431847AEB4FF6230CEBD1969A0FB68D6E302B78DA39ADF6C0E681117C8432E24820B9EBF38838545E95CF7AEFCF1E9436CF48E87B6C5181CB418132C7BC050B9498720D7D534792E0585F05DA2735B7E68FE35DEC358DA1BF1681F7F62329BEDFEA3D12BFB26AD9403F3AC1DB96D828050F39DCE4017B45C5DAE4D7DE9E9F687A9D7FAD1AE0E7197184142F6818A63D5617BE9D8D82334A12E68F2EEF88A0DA3A915DE63629550D8A64DF591EECDBD1B89EB40AE9F9D65815271693C85F2CA41BF45E4FA16EF8B17D945EC61E757C6C609D8AFAEE32B3CA628842DB255B619F6562E656F6125FB27195EC82FBEB9C14330DAB649CDB74F523F5A98244194581503356B5B7EC51E2B35AE889452D3457EAD713C0715AA7382DCC510B16E771B3A5A91949FAF5E29223C8F1F861BC3B4E77E095BB61ABA00EB29C065D6F9DA9B4413D61B2202547FB6E34671930EBCDCE4C541B3E2DC90073867A47197E08C96F74ED81DE5F10C37C062E8D82364D67EB185CD098CAC1BC3C522E4FABDF2FBEFB66B9EC6E848F732A737FA7B935EF2848C29B1FB94044996EEF006E251BCEB5BE356F286F0FC85E5CBA627B67398CBFD6C0F520C6F896353FE75BA323D8ECD9D3ED2997580E7E1E49EECD91982C5DA650D6B128068B8D3D72C1EC4BF1FBF121BA96E1CF5F247F9FDA7018CB609329B1C95E59E112C393C45EF7138905902227CD21A39CE30397FF017495BC98A968FB497E03DE5843E64923683F2E402DA63CC25AD0BA13B85E3E379B08DEB39542C06A268BBF44990447190A1F8ADF0D3ED9ED9917886210864CAD84E7C4D1282C4D3BFF9DC23E4FA68EF6B0480E76459D1B5E0A7CC0CFC17F59531C4C1CB1D416B7D009AB50173F706289DBB68201C305E39FEFAD87929EF933006598CE0F0242A2C60955AE487115B4C367A7E49488491A6F044FA8B7AFD81F6DA09D29D4BEFE1B3C9EAFDA4F17D22EAAE0B2D1646906D1CEE65614640B53479E23831C56EBE12B92997D5FEA725D78CA75F4509EEBD3DF4F741D6B2770521BE2AE63CA365FE1518CFDCD5088D58CDFB8D3DBA76731F74760A47C9D619A31B7E318E957194AC5ACC6867CF8C9C235043D5C09240F346FEA840AE0BB16094883FC801DA0BEFAC64A021F6F871413249E9C7F5CCA92F4EAB5713B0F2CD6C950F34BA6FB1CFAAD541BD5FAEA45EA5FB37258301A49D7BC4657E3E986D707213C0F836B030C21593F11518EAE3A8A95A2EFC8B9839E79CD8CB0E6DE59D5A43FF8F81FD35392F0C0659B7679542136782D559897FBCC0129C22F43A30CFB27E899A8CA52453F5459A281D0CC21F902403A596C7F69CBF9A64D97B935AB384FBEA5851D831E8420066826D7E11E34047D18CF08283BE8F29A8A79B0F477C27BC41B8EA4AA010ECF8ECE0D37389FF13E235A4526070F96F415D41AF2E053FD4440DDFFD69799456E7335CC6D9F4370008803F7BABB6C58B6996DC5A52649E25463B5267C188E2DC39B3258636ED8689E5C02E00574988B3AF881D30E9EB38AC51C1E00E1C0A411ECF37E314276221D7D8713F7A449E38371854EA26520ADDB58082287FAA1F77FC04095499A3C3A331A38852A287B24040C1CCC054086964FB1EE2B328F3DE21A986507CD20B4DE4898DFD15045324B93FDF85E5392DE0F32C3BADD04784012E97CB9BA19472B0C20EB0A71C89149EBB601ABAA4A853F2C75DD2622235AC30D97B9D7B1216089B9CC8E879660E40EBCD15203404A8DECADC42114715F4D8A6A10511BACC4DDC23520445A95FA3945BC95878BFF18728E64DE8B7767CFBBAA21F3EF2D92F3D7DFDA792BBE4E5B3381077658BFBEF8DB95B64F9F2A44917B38DF6F9391118978544369C882B218E7A7A31AFC3EB9A75A28095C4478DC81F9CFA127BB749CC53898409365170823D65A0B46BCFBA0E47CC0C5F6ECBEE09131F134EDD254F4F58B50C486DADA13195B1A35739420A45BE6558401F64C3B6AC94B73397925C20545621C7ECDC7DA9F71A755F84D27F2C6D8415D37F2BF1966A76845216E41764AB96DC2E14C12DF3684F7683FDAF5EC771DB7050F81A4B3E516C7D5C955201A18F436962476C1284531764A9397E0EDBFFA8C3699929DAEAF968B4524BD98EE62F9A0DB9CBF99FDA80CC6C57A5EE1099B1EB29799A5B5BF5593CDA26CE2C66DEA3D40545465C1D21F5B9373556B9ED0AE30E90B836003CA83F78E29BD8D49550286DC2DE6407860E9A9CC5EAF3E1B1C73FC2D248B81B1CC8F59DABFB5DAADE6F2A0B38E76D9E6D0125955D08DE7F334A56A8F362CC5D883D56BF7BABAE6D9E425376D34A05AB863A0D9ADF7C6FDA574FA8DC60965E021532C25ED4D568412D4143FBF2C4EC2F230D08337A4E546E01F7C1BFF4C97F2F27AF400CAA57BCF398AA5BFFE155B0F29A085D5053DFBEDC3423818DE8FC597EEAB2C1663D8C81C71CB876F73AC854286063A2E8BD8614D06B80F3BF56381179342143F4C89B8CEFE9168B6A96F416DC617B9F544F9DF65CA6F4F7A84A327909666B70CFFE889C86ACA706A0A1365E248D6B341A004A27D4EE344F03CE6E85D3573E272D48210DF7C3178EFB7BFBEF7765D24754673C9EEC14C7513FD8DE6386B0829EF0980B826EC9C77C81D1E3B8CAA65992DB9C2F8DD691C520FA6F233AFAAEDBF287A57A9A66D2330F4636F02EA3148C4BCD2C8B114D48A1027FB3BD5008D732C427ADEDEC9969AEAD451E166954FDC207C1A4EC409CAC60E42383385187AF44F136F91A8461E62EAFE6FCADD1E491162E46CFBBADDDB72E5B54B7C655CB9489E7F4F7E55C93D3AD50CF84E1F47A706FEDF818A5246BC755D6D18EF18702F5A90CE51812A67227C5E5A051133576E9EBC18AFA18C1B05C854D343727B25BB10E3B9A3645D789287858FA43734D66AD831E8646FE604286544238DC99ACFE3C8285230FC784BB73360F72ED34795B1C46EDBE32A346BFA7F534B500C6C9D3EC26AD7ED20D1500E3DEDF141DF3C2F92E981472F0010A48F25429329AE92CBBB918246F5A53212703C75DFA15D014801A830DEB75BAA36 +pk = 10FE2116FEE80D6D9639F61B4CCB8263C939FF238347A69D1A4F258E822F858A051BB54DABFB2C2FDF923C6FCFBE9ABE78DC03DB405745E51FE48AA39C9476A9736E52050FAD2A7958C0E2AB419A2A1FA7F872F52019E7DB26B8D4515EF7A6120A942326ABB97B5C0C4EE834E9505D36180B7009D8740B1408C703ADE94AA1B283DD282C5492AA8822E52991CF05B3E9516B540E8D3D241C4F07D7E3DABFCBB21AE50FE1188C7FA4988C1A704D657C84D849279D5D6C25BCECF7FC263294F750D87F81BBAF93255253F04DD3DC58780A647FC5650CF8D43C428ACC426FEAFFAE8F15DCC47D50CB55BF645D564A30E256AA2806F55AE2FAD5D8307D34F999F26C842E31FBDDA3BFFD7D9ECAF17E5FE6E34FB8496A6DA7262E12F419B9FB039DC61B5BAA86A39D47C6AD61A8A8000CDE0FB10760BA279909BA8867FBAA158C10476BC60D17BAE6AD37693EFEC12E2593C87E378DBD7E7FC9CA6700B9E4AB2AE5034C7169BEFF70EE41BFA146199EF29BECE3806275B2FFF63483E9F2E3F75ECB04FD816EA30C2498DDBC08355529E8C28C82AA6A00FAB7F08E24F21B7DFA68FE626D0E61C0B5786FCF305123CBCA6BC29FAF84ADCF0BA667E297B80D65226C69E3D068A26281B8393F50BFAFF64E8D3920EA966BBA77C4664E031CE5CDD6A85AF227F294B9D4640132C28027FB9199ABD773E9102A4728D006BED57B1F63AC42A122C7861A121B7E6023F849E6204E5D5F5AAC005DB27478E369E073D4C5C3FFAEE286FAA5224EEAE51802D57C1A74F33FFB2805938B69856FD411F325ADCAF51B1895277BBD0B0483AFBB80664DE7DB0A17E6749A7628D0DE5FF6C9991DD2365C7B4E3492784BB64C359FE5961587D1B20446469C089CEB5E244C567C379F2252998F286B717CE39BA8B1B6374EC573FE1AC688C4EC30DEC09B83ABC87418268867CF6374C9BD764678EBD40A7B3AE1DEA9C11E9B40774D7829F996DF955B876E946D52AC562B504059AA92112F9FF136905AAD707B931A23E9913B7966666C33020A01842A1F77F5A30F313AAB4F11EAEB794A0FE4037D0DE8B79887BBECAF03D7262EEBAD58255D5D836A8E0A999616781F99384A1A0E3408CE9215A5CF6B7B045C0ABDE99F0CE6949925FD5EE3CC8182BF8BEE59CCDD9A784C42B08FC8390C8A067F5C31C17D98D3ADB00065BDBD1AD5F33D43C3406D20584C29A4864B8982E876FA5C6B9ADD7DA67252ACC2B41D9242CE5A5DEA535DD0C60D55EA65FCF182AA1F109656EC7199C251B951A5EE93A87BBB7F2C32BD96B7FD9655B66C69D82E75537D7D33CCC3458C218ECE1CCB888B95266317AA5F2AEDA79406091BDB25565D4FDE5F6E54D55D10BFDF7B0FCA3D69781EA28D007933042E95B4E71408FDA4C760A20D21257E4CE5C0B2881FCBC01E9E6B6C9139E66BCFF485EB563946F1275EA5011F53EABC76B370AB6F00E3C9908100755B9B5AA551AB06E88622EF45B9C63E10F551B729EB2F9A4E3396ED884FBEA9B75C05FB90AE633703510B0FB9195C5B03F59A10C36721854D9BC3FB290AB45AE9FB6150C7E9D9BEF6EAC3D82EEA51272FDF419620D675B415A0AB3DF4AAB0808CBEB07CC4B5FAFD205186A204C39E9A3026D07F16BEB500F6C655FDE7A15CA9CC461DDF0C791BF2CB9FABA2DA4CBD5240BDA1D6586AB1FCB61AA9D372926B25F2C75362F6D0F4DFC002BC11FDEBD5C12E4F528E1FD109AB388610154888FF06B4A0789889323E667FBFD83FD88123D937672D3324F5E07CAE231A4F1CC40AA3FA510BFA2A2558B73007D15DD7AFC2ECD2058E30A2D554C349DAF1CB82B92325B20409969021BA4B61F5736658021515A3A7C5E64E27FDE85CE008828684A2B53C65D06CC5E9832F83512D25BC7C930EA11E6A9DA9CCB18DB200C33FE51A804974FB35660423809C0E5E23E52B0C916EC247F2A77BDA91E89663CF02BB7245D136CD08AF81E1F89B9328087B06EABADF3EDFF73C003FDCA52BD7104C77CA74CB928FF666BDB849A9D09C9955AE73DC79E503A776C3E09510C63573DA919D779B1FD3233825A3EB4D15D658382686A925852E51C03E15E57FB9728543249B3434E6222ACBA551B8218FE53BE3852C7E57E5BF95AEFDCFF55FECC30537398645ECAF1B07B35F1D85CF226958F644C31C608BD0F7EF419A955562BB68577E7007BCE1D1A7D13A47C07BA420551703E122F7B84E8C1AAEE540A1E71225CC07C4528B5E5285F6519F11003B6EDDE1EC920482F89F4C78F7F2F1D6306A31A3A90AC87AA70DFF4CF76F4DE0CD7C1F644C06B47EB5BFD4FE87184D7DE3A7BB4FC592BE63B3DF5DF79C70693FE46F548FDB7C0E328761070B1BBEF71317E24A7CB240334D388A31297DD668503664C92D91ECA545A7EA15454145C4821793B1CCC81C0C32F709B3AEC1B82E8DD4D5D4413F74DD12A12490ED4F53F4B03AECDB619150D39881571B0BAF0611F80C714E3AE0FED615F8C28BB0A84C83F497E96699751748330582431283AD36D508AFF423CE497101C12AB0099EDFA27B506ECB376F2E06CDE15C262ED4092780E8176A819DEFA2F42802332DA79542AB7F355FBC4617BF3DFD51ACAC49E857F430099979544906C058599278D7FE8F12C86B770934CBA643CD139C45866BC554D9B612ECA65E0BAC2320AC2FE291AEB71322981334C1D3648D89B2FF5B8EEFF4A2E1B496033C4184470F6648B927E4A2899B15E0E8F5627F74378DAD6A188ACA80EBBF6ADBE3 +sk = 10FE2116FEE80D6D9639F61B4CCB8263C939FF238347A69D1A4F258E822F858AD36F066BCC83D9A02A1CFCA11F191E8A6040FA5F5479757C57AA10DDC45D16C45B1D453814E140537827ED18ED5B2B7ECD59D71222CC4CA494D95212BD733400CF1A94E90AEDF49B071B0C1897EC2525A49715A8295256673906EC1C9E87396E073718345613724581058807137034614366600840872548565180537277286864123721484008674032016672656667426130704182346356330252318033021535202120212017882463056462368016504883412732117153037642318365817583057646452664814354177260037877783764814504287415105113428023235001471026327045233681134508702565068828543104602550424426674610885581052763117260228580812640732026287382058282800284306501280555718685378478522006147104233208513177650355807151285850245423618628040362823233564210776276733417862542265208102411838284141032113864123244030481425844834455010772673762025217111641466184145634373434007155753527266852614378410328613864218110231876870805247062750152502635857320657174537521056503526808878723224140135083877058127613358761773188544467822266111231216431148786303050482055105454861426047706168325068582245603505688323110815863770082415573663312484000372448051878081008017126237241515480471703012831476775314141884840842454553010587586133363158327582837052325478033122330154562837215576670764463134340686145371411560806607306064411438057453326704200684000186577265235555041817057461706210738442853183462710462511155846308514454813108487665275760505628675731361622311262104225237806348488002765746822860381171220838266552540583183866347250140268624653867732074443581214577683766081070685212423855708610560114778258555805150833427327778420423740747676861175841561203047643582070445634113260870852750128036011035438175221162320852013886233610360038873786001565007544250764334523670163222858735568566142030135625264854031074116034064816243317212208704056435343375421587648032605532742148751660033206853486815320834762887117543832126224228011882711313703261746110534305870528876841456108461727238676340514623483811258413844247547255211626302872463507335248130767548541171034270027157617321147016630583007066471724228477486181234113032283126746746115477110144607014720458473076034124037146242007080742166160466114864045782632830655837270578150132051504184432487573271581326576402773267024571817281461462482442363576325638211280267841420244172605165057426520407552270532485710314408238247445654855856603748377246854635286144445373722650260131314057704701634360573777007783655754572753075751357000405886036484387208631701084715661725247836130614140331844143783064308044666027760445375348430468155358643705631112701010315834574100574186402450621154450326503415373185010831078330548634847560464241547566810207341626052022325573662140521516874677187151146346052522458536662543017333308774600204880672402020735788051802850137717207142515265608222641254357852036404411170033831178445513302124643575708172815485472750081604113012504130050186817363356206374071421502542811050043082374146202366187702084606263235638448035273040282176468884704357861422751643565452427872070714172437304255665888530825067101574310444386638677853060458193E3C10126DB8560D44CB54FD835FEE16319C543358CD4B2584A976FA647954EB0ED9CAC4A6037167980F2E8729C4CB11EEF5CF7AE8839BF35D2622B2679A5C31FF6F1CFC9F1AA38F2B05BF796E9605C4A4C8BC598308DE15BAC435022E45FE67ECAFF36534C976F15E7E4B848EB4264365057D2D0AD7A270682085B93442CA6E9697FCD836629B1756B3ED86A896F926A8276AA62164D183F081DD23C3FA92AD63E66B5D779B39F6A3B3900D341F7CB7CC84EFEEBC6DD55AA8332F6C6DC24535D15DD0E77C2EF56759BAA148A99FB5FABBD48ECB14C6C22E8924C4ECE30ADBB4A3A680D73CD234910C818A72A826F07295F271D37A0DAEBE62FC7F9C64886D55ECA1A41256595644F1F93340ED0668BFE9215BB51F6A29920ECC29E4AE2DDDC0A373DD712EB28ECEAC8281BBA953C44592C4A8A1DF35453F5504801B23993F190E48433DB072985ACCAD01DCFDC6CCFCA5EEDAE787FAC0804638603CB420D34F62A30BFB72B3CD0C8644A4772835F98854F151E22BBB95A92A55390F266708CF857ECF0361180B90DAC34128F8F52A20C94E7E4895F52970424D1E55A9A8448F7E307201622A418F7E947E9DF8C1B06ED1805F34394D8D584851C3AF7FB48EE535B91226C733C68793275E7E7166F8621EAFFA5D4484BC0ED8F84038379B04177D2969E0355F1DD322AD49C188153988F54FCF737C15A924F5A6DF965ED6FFD9770493CF7C6B5BB1F0700598A20B5A87365158E4A7AA7B8A3883A2690C73E8FA122C651B59C2055EEFEAC131B67874EA70F5D6B84827096493FE283203D7521D93BCC251938FC99DC9D53ED056C0183DF45AF80DCAEBCC2E9ABCE5266DFEEC67018F693A985948C95442C7CE3802A732CC428B210F45319CBBF76669EB6CAA4E73C39B07D6610068B0CCA669576EBE9424250AE4FDEA6A9AD02CBF636E28834E608907EC5797D2025AFFC6D9D4A5D8AA9C7A527E5347B4FACF55FD471CB6087CC2036A1E6A2716C13EDAE80D954D86006327B260299954F096129D4B28E89F17326BA021EEE744A75F34F10C7360B174EEC182A4E4B47A5EB4CA33E64A49ADE056724C178CFF2D90B2EDF149C3B75E69F198B6BF4C73C2DCBC41898D06E47F6BD5AD0FE3312C9DA7A926FC865380E7673DCB398FEF80B79FC16E2095E31F650F275FB1C60C30DD49BE963DC342BF9E7DE14177AF6AD317A3212E7B4A8FEAE781B1F5BD041F34E5D8BD5ACBECE5E4320A7614BBE15E40DB9CFF724E86DFCAF16271BA14341014A1AA35C4FA332690A9138ED86C43226627AFCD76B385D7F93CFC40B0EF8BD01D6ED8E792B1D7EC40045B58D1D7CFA405747477CCF835B682085A4F02A64509C8070BCB00B86E034A111AC92543C7D6A2D6F186AE35C9D1C521E85C933C9B4E0EA1F11271E075A2570703CDCA419C0D964D2E85B3A5C5E8396BFC184D9983384D3D4409DC38AE1C883445C8980E8EC3B778636013DC9895CD558170F48DF6624450630D1E495677346DBFF8EDF29DFA182FB22E44BDD2858F011F9A0C57BD91899F1FC0CD56E61F8187D6A6B8D2D76C81616BE84DF1E557C9C62625A4F66450F0FE696213545349D8066D5EA76853DE71F0DF02DE6FD060228F21D9B8818DA86F4CF7A5EED07682F5F34C175AA74725545839F348E9054B5280EBD36404AC11F104A09F6E103AFDF4B6BC8ADF42C80A1DE64EC4FB3D57F0E9C5D66D94F4FEF156337A1D4EBC3462211BEACE362686EC27D7BC353DBB0FD6FFAD99D6D0EC5CD1C888A4A9D17D9E20E3537C9647C8EAB90159440B7D9C14136330B37840ADB229AD59E881F0F0E39D4EC233DA6424AE607E04FAA2C9428A82ECF1D85AE2EA6A639111C6A18BAC9F96A2388FC96B677B5673CD05C7AEBBBC480A3B12F6EB483DF49DA5A577E7FF5B6D2E27FB338350CD64CB1A5CA5AB2E73CE51592612706FBD5569A6F328883AC5B8C4D9A68D9DA3D14A67DCD2DE004A22294BF6E9E2D287D6BAE94FE7B4A69C6EA00D03D2216C03429830DB0CFC67E5618D5A7A3AB372797320F3E1412A337A78F04F3CE466B2E81B63AD347FBCE957E8147A4AB4C96AC30A82C735C8A7A9B6D9388D46854C48EE262B379C0B25659A3DD4CC3AB940A59A204109D14B032F790DC487A5463A2A2473939E919EB3ED3204559D2DD182D19E7AABF1F1BC39105C5223C4FA15D3E8430480981C1DCA84DFEAB51B393A65B492D7A7EB7A4BC4D16063936B53B7483A48531FF7E5C9F26CCE5A66DA8FE8AB2ABE8ECF4993E6FC384666641E8085572A67121C4332BB2A4E633330CEDC84734A1DECB34458ED310D41BE2C689EA0B74ED1384490D12008748E34802075D39C5F149726F3B89390313009B1B4E6017B147CD2541B7827E1A14267BA486A733419D4DBFDACD685F1B841F980168C6A35783A62163D591FA24F81A272C401BA548F5C054DE5F702E47A5E5E31F1B3CDCEA69DE90FCCFDF343FFED51B77008E06CAC30A3B2F93ACB7A5E861CFE58765A155F0687C5E75AF93FF31BE29D48EA620D340473C52A50F6F9D209573D35BA9AAFE88E6FBA1461C4EDF70C61A966173C0A968B8B20EBDEAF8AE6EF31565D5ECF127D3DE3E907C0BA3CF95200EE0CCC8BCD39D2CD6D9B98B034A0D0AA7E9C95BCAA8A26551643F94612CC51DDEC7F7FA8D5B3E3680AB20E0AC570A5B5F87D4498EDED2641EFEF6EAC5B2F58B376D554EB7CE2F538FB3114148F4DBDE8978035DD50D2540C9FB2B3286141E80F8AD92F5EE62F62BCC34C1E567D6A1B7E8C73DAFCF9DC0DFC237FD19B7E13F847985BAF9C7641EF69E10801CE202BA8B1649BC7E5755C2496FBBE59892613A72C82D04F7E12E2FAE13DF61FD2D5F731BEEAA65AE83F77FA93639184C9307526F04452A51F604044FA6E166B0B733A69A6D15B5C6B1681424766B739DF11E3E867CF774366ADF4EFEA58461A3BCC8A4AB536515A199BCAAFDBBA9D9DF5312369296857D58998254BB235D004CC4E9F4C13FD16DDE83224611BC7EA80122D753238B33A9A7B4903193F1F11FFE68E08D709BE982B0034D85648E24E6E98F82847C10625FCFBB655B7B3BA5E544309FF9601E724A23FE21585207F87AA79EE9CCD080A2077B97542E6B307C4A3C6C37A52955C4312B8B65FCF3FB01BEB932702948030D9A01953C6028C669166CB0265B67B7D4200B1BEDAA50BED809DDC139BD71B219F65F8CC62021BDD3E0F5C16BDCF0DA0B85CF8EB8CA27B29E4A54157FC5DB88E3D566F8AF6A9FA791BE6D693C03539E336740D4D3DCD0E9445EFC6EC4E3AAF10910D4C87616290C70521951A0EC149C78503562ACB6F5C0A7DEB4140F0B0440A864E531936F69497B174E089AC23B100E4889BF54D000F1916BEF3817E5B9B90CD747E334CAB8B4013D947FD17BFC79FAC9E095BA77168AF9A23212F43B408062FC824565BD32502B2CD13A0CD24F7E7564A76D2AFF2C2C27C4BEA28362AD16F2BC2F0663AF9A54E636389FD43232899169E6BA3EBD5F172E6783C755023719F3FB +smlen = 5817 +sm = 32CD07117FC75401C7763ECA58F67D4D690B59A0337A0FC27D79F4B1E19A59C7C40C8D33A7BFD80978342434F18DAB1BC93B4607430A54BA619D8611BC2F3B18B203800CF5481721F7CBE74AAD76F406976BDD1CA4318BAF17D0CFDD54C547D5266CB8E77786780CEB7074A6828581F3DC8EA7B32C1C396A4C736FBFB68E23B3ADAA1001F8FE49F2F34976CB31EE50DFC7CFEA1B84824E03297496CCB396202A2CFE01311DD868473C435D73EFFD43FDC4FE712C8F71281114224BA5E0B0807AE0350BC44E5FDB04895894F744D49F1594EDD07F11097890F6E2DD7C9614B7B5746CDE555589E7BAC9AC44EEFF106FC6C71B91E7DEA33010C98393343DAF48EC6921B9D320FC12DCAA403D11F8D6536FD2AF48EA22F690054251B93F074E4474AC7DE7F89972428BD9E8D361DB042C9A97264690F3A40308AC8029FA91733D6CFE8BC4C793B2B5A8E86BD24FF96F3CF6441DF7C4BB544665CC85F212BE8403225700ACC1743A1F6F32255CF154F4E2E199D1E903E72DB764F76C7531F1EFE5F31C2C4F9EFD2CA51B1ABB93DD601DE5C8DF1258BF2A338EAD99F48B3EFF935A0E2D098DEEC92387611ADBFBCFFF50716F74F02C18764AD4F3BAEFFFEC26DF87CD5A6F23B211CC5D962CBAEB2CF3EDCDDE5CBCC7A5310A41C73F879137C21D7FA3410839F2A5C1E56E6E34F089C753887165852D0311654D7DEC1C61EE3D4814F233D9E4CA266E4D9511C5933A4999962280A980214CDB285739FEB50E52BC62BF16210BFA172EE1946377434D4FAD69013847C48706E53027214EC4EBD5EE0020CFF3CB4C4DE7CF5E7A3C49D8A8326CEFFA3259C91B7BB133D1678650A53CE785FF69BB4B336A601FBA81C6C01AA6BDB4367FD5C81157F54E2144DA9E21AC82ED800914439B4D47002B9BA36A7EB390B11E080D8C0E9C60428E13EA41D6B3AD0E4F97465C250927151EA62E0F71513229C6AF2D6864B571D4B5B77177DB7D6D4D316E3EF618D3E4714B79DA2B2CD4B37420D6EC837EE892A92A0B994414AC9A217EA4656D430705060D300ACFE3D726AC867CD9A8F624F5C19DE7583E7BDDB8B0C84A536E0D8E9CBDA909A127BC6DF844CCD231C5A8E629DDE11866CB3D37E07FB4324C735D3286D9046C4E90F2E93D0BBB332DBCD55B14E6CE5AA6F8AC010EA4D7189C9B8ED68C66FFB53E755456D655EBBD498723D5960CABC2DC11960617EC5F2461580BE928DDF25000BA4EA92858DF1593BF564430CB2408DC11E02D00AA68A6EAA689FA2CF26EF67930E6817345B78DC2D9390C1257A0119B42FF3B560BA2E3CD421EDB3E046BD8A2E31F55316946EDA906264325D6323A6C2FE703CE44DFB62BFC5F7FE0FDD361D06DD0A5F11C76DC9F4AD03E6A504681E2B1EC940468B968782194B1902F8E796D34D59B1B46C9D7D413414A274F4578ED0978942F2962599FD27CC2C42EF433ECD76605FA7B4E3B3B6F1492E0EA281E86723C164A446A50521A51F6B7258DCB9A8D416AC1C33C0C5A9F9657B8F272A3409BD78B7225859838249EA67ED7DAE17BFD2B733460591A02C7E486FBC92790684ADE7F4A18D9957281DFD1BAE7D90B7A1144ED6C521C0943CAA5A1FD905F42602BA56A4590ED6DAB462A1ABE189E06F8FED1292779543CCAA35DFA17AC30CA61DE1085F0083B64C8F8AD3ED5C427784FB76B5C227A03C1DBEEB95247B3275941A18BE8C132E21331A7ECEB0FE25CEE6D1DB3EEC0DB8EFE5D22E1CB7F7E01C10BC00175F8359F8E62FA102715EE2D096EBC659E35064C32A7F8DB5E2C7F96193E2734B04DE524F642D765CB6C98C76BBF1F27F4C321E5602811B6D55EFB3059F38D351A3DAE2FBB238586F0806F494B700F496771B28F012FF50CF8B189C95B0FEB2C0CD1C520328155D6461F5C847FF432D68FD96F7AB743C65DF90B33F72832910C64D7BD05CDE719229C1B762DBE41621599FCBDD8B57A04320D5B6765C9B8A9C5FAD5E620E491237878819736E735F851B373E112214DA12C53906C9E48DACAA351A7CA013FE1D0E10A3F0F20C3ED4246535B94E08724D50287ED192D370736A9EC52098AAC89D1F8CE46239C71C358CC62F673BF5C5269AF6491521541C95ADE7879372CCDEB11D4EA6761B540FEC3BDB34C4BDD32669764195C6389D0C845171DE244B086219BFD8034992D4856B12AECDB10A71C145FD0316C5A999C4FE5E3C0CA7B8D281023877B9ECD7672DF8A48AB0C4A291D66BE88B0D1CC7DE4EAC453E734AD6FC2C0EC9DB548045EFB468F2E1E3FE6DC2179D0E504B402BC5B5302F94A99F584DDB78131E10D190129FF6154559EEE7919E1A27ACB8571868EDC330F8A83D595C5697FF4D5E27153F3D068202EF967FEBA09E20F1438DE730A4DCCDBC77731CB08C2E7DBD85D7E743B1FDD9F79033C1D27EB6802AE6557A212E6566D899F8954806725B7C0F450A57F0FD8805AB6A5362ED52FBF5FEB28823F6C765BB16706E072D373625D6BEB59394E6A0EFB4D453D42353DDB05446F2A893B38C4803298B7E19AD31A0B1655AE37F64A4FDE6F13FEF1873501441D7F66F862B8BFCF5009575EB07E581AE9EF22636326C9092A39B6F1875DAB5F3D96A44394156B7D1276EC479A849DBB882D02C10D60CD5D8C4ABEEEBF08C3B846B2CE3DFC447783DDB0C2960767AE82570244C93F2681CAF8D65B3BC40B9BA9926FA85345B09B53E318CAC89107FD17DF5300E4B42A7EDE0181C30CFE6FA88C21868CC9B959501B77B324BBD6EE8589961BFE44980C6233878EED665CBCF26C953CB980E0D08F57836CE6D0D6E012DB7DF816A3697FCC633205404A53E27D1B055B7493BF5004A0CAB8791F4932F4FEB96895003F50BA19E56A1552CF90AFB55D803A02399DC211BB941D53AD0D3AB99B458BDB99C4523588B5536E06676A3590BC5C5798A2DDA94DDFFB6CD987490FC2AB0E48368B571C8A01782C7F87B86A48AC93091D7C694A1816428FB51FEDB6797979AFDDDCC3B64C269C93CB7B30E2692C571C4C197B43ACFCDD83133536338A11840FB7AA9E7E581E29D701C2C3F0A057984D2AD99B0A022E071C3B7A99E86CD60C18C4DA82D7E11D4EFFAB3085C8460E6432A4AB3DE6C0CB7CB9FEAF021FF855A2CB16C8F27F9ACEA5B9F02C8E016DD12B74DD82F2147CFD30B47B525B83330584FBDB6CD48F06F7B79FC6BDDFF55D5AB9F8644C5EB2B572A4CFBF6C9273DEDFCB8AD2DFD2EA270AFB020A9AD4E8470DBA431CA7DA131C9E944F2FF7EA1BB1FDB37EC49B644EC764E60087374ECD2138F321B8AA966138720F0E96C38CEF736D567650337A9F042DA56BCAA0F33FEA009AF03B39DA08194ED24DD823DC55F42D6A8030FE83ADEFBE8642B308196CD4C783871BA0DCDC23EF582949D70670974031C78CEE03FD581130BC824185F8DDF32E877120806EB575A6F92F0F81B938FF56AB23840747903BF8CDB6452C66AD5C377FD9598AB326C7EE6790973913B5B30908AD7C5D21B94E2CE5BA6AD556FEB3C2CCCCF042421855070C14214D2FA2E05F532856D12BA4D88973366AC2930A7625B2DBA1F8C98B0D5285B6021F8F767CF3456F644571AEC5A6772B7E2CE2898D10B8E3FD581FCBE0C7796CAAC22CB43DFEDE5FF323B01CA8275E2DE67B452C6C6A16C9B1504A6505CD786CED18BB7802E565BFDCD6C5EDEE797778341EC5A8DC8C2C3EBAB0E435D92D4558D84DD1B3F14AAF8489E31184DB255274DDC6482C1C7213E1B0DD8E4D3C9D092705297B99857FD3078606580880178DE8429EEC84141D307D7A4B4DFD725FE041D8564B5A0BAE73236010246F3794B9397654EDD5369C5510331BE306E564344E3E1FF3D92AF1BF20235A463C1A7ABFF9BFE09DE530F6D06FA21749C55DD255E7F6A50274B0CAAACD13FD9C01E1C113557E273C854B723CDD5CCF4BAD515E6A16B8719A5980D5E50AF69FE0798659606828A2498338C8CA224213CF417C9945BFF9547CFF924FEB9C8530E3417C3AD46E2DFA318050C5B80AAB9A42C23833763F130D0BE3F66AC5528CABD182BEAD7A70834B8E5379E17E4FEBEA949BAEFC10D1B90A00AFB36DF1FB84123A9DBC66DCD685A730A79843137C9F277520170BA38C3C5EDA3C3425E5906413341A967B909C554AE6004170B5A94E72C33487D8225DAB1991406998A302CE0F273EF8665CB112FCD5404160A0463EC99ECE3F914AF7B5455A1993AE97DC7E7B5D6F02D38A9319E5E0DFD3EE9B3FF5066713859C64B65F719336A8C5FF32222774EFFCB1F446C0E269C4F0EBCA2773902D91276C208FC3C42C2FEE090FCDB2490E2131EE4A78B8BBB185EF771CCC63DD057BF886707C6E8C4A86CD7E34EBB06573A207A43909EC6AD2249DEAFCC23DB04921BE4CD8360BF0999BA45D008CBE4BFF82C7AC3A3B79680F95AB1F689997C2C8DF93635C76F4891CAB5BB07498B0FC6DEC48D194685B185F9561A399127AA6FF5847FEEF0C380FCCAEB342CCC55178FA600C98D12900D36CBB9B662B420024EAE920185DC5EC24FFCB788B378983F3B5004565B648C9849ECF62DED4926DFA9D5869D48658F5F644EDCBFF0DBFA4C8B52692122F0548BCC1E6131D2F435B62868D95F96291ABED012F32415560A7AEF901373B626DB9D6E8F200000000000000000000000000000000020711151E279FFA507328B2129C9F05A22B81A597FD1B8C27D554B36FD3EB150BC5FA0C6ED967EC5BE6F1E52D3BED1508DC3C841360020CFC2CA1B0713076251F2935EFA8500573CB4634C78A1D0F87D994E8E2B0BD265A877023B54D9A33282C12397DC74CAAB07AC2EFD140DF907651BCD1B37CAB2D03F77CC28872291F1CB28FD4BBB5331C2A18E02120BFD2D9EC0C8938A6D43681DC03527FC2BF59703B5160D8E25D08534EB5AA5CC9C10572257D9E4DB29235683BFE1776A2D9EDACFBA1ADAF66587BC451D32C524C7934556F94776F91CDDA96D2E5CAF91A39503D3A742DC5A0EFEF7C1A13666E200C5E3FD7652D200ADEF51FC5136281570B7832E0C6E7552972E43291F202E6F916C916DC3FA48858F3D92B1B7EFD42DE140D43648AEDD7C7379D7A4B71751A3348B6BBA3B0DB71B4C99C41E085E5536A3F0D2BDDAA88069249E21E2D9906191BBB5C8B45353DE72E00270431847AEB4FF6230CEBD1969A0FB68D6E302B78DA39ADF6C0E681117C8432E24820B9EBF38838545E95CF7AEFCF1E9436CF48E87B6C5181CB418132C7BC050B9498720D7D534792E0585F05DA2735B7E68FE35DEC358DA1BF1681F7F62329BEDFEA3D12BFB26AD9403F3AC1DB96D828050F39DCE4017B45C5DAE4D7DE9E9F687A9D7FAD1AE0E7197184142F6818A63D5617BE9D8D82334A12E68F2EEF88A0DA3A915DE63629550D8A64DF591EECDBD1B89EB40AE9F9D65815271693C85F2CA41BF45E4FA16EF8B17D945EC61E757C6C609D8AFAEE32B3CA628842DB255B619F6562E656F6125FB27195EC82FBEB9C14330DAB649CDB74F523F5A98244194581503356B5B7EC51E2B35AE889452D3457EAD713C0715AA7382DCC510B16E771B3A5A91949FAF5E29223C8F1F861BC3B4E77E095BB61ABA00EB29C065D6F9DA9B4413D61B2202547FB6E34671930EBCDCE4C541B3E2DC90073867A47197E08C96F74ED81DE5F10C37C062E8D82364D67EB185CD098CAC1BC3C522E4FABDF2FBEFB66B9EC6E848F732A737FA7B935EF2848C29B1FB94044996EEF006E251BCEB5BE356F286F0FC85E5CBA627B67398CBFD6C0F520C6F896353FE75BA323D8ECD9D3ED2997580E7E1E49EECD91982C5DA650D6B128068B8D3D72C1EC4BF1FBF121BA96E1CF5F247F9FDA7018CB609329B1C95E59E112C393C45EF7138905902227CD21A39CE30397FF017495BC98A968FB497E03DE5843E64923683F2E402DA63CC25AD0BA13B85E3E379B08DEB39542C06A268BBF44990447190A1F8ADF0D3ED9ED9917886210864CAD84E7C4D1282C4D3BFF9DC23E4FA68EF6B0480E76459D1B5E0A7CC0CFC17F59531C4C1CB1D416B7D009AB50173F706289DBB68201C305E39FEFAD87929EF933006598CE0F0242A2C60955AE487115B4C367A7E49488491A6F044FA8B7AFD81F6DA09D29D4BEFE1B3C9EAFDA4F17D22EAAE0B2D1646906D1CEE65614640B53479E23831C56EBE12B92997D5FEA725D78CA75F4509EEBD3DF4F741D6B2770521BE2AE63CA365FE1518CFDCD5088D58CDFB8D3DBA76731F74760A47C9D619A31B7E318E957194AC5ACC6867CF8C9C235043D5C09240F346FEA840AE0BB16094883FC801DA0BEFAC64A021F6F871413249E9C7F5CCA92F4EAB5713B0F2CD6C950F34BA6FB1CFAAD541BD5FAEA45EA5FB37258301A49D7BC4657E3E986D707213C0F836B030C21593F11518EAE3A8A95A2EFC8B9839E79CD8CB0E6DE59D5A43FF8F81FD35392F0C0659B7679542136782D559897FBCC0129C22F43A30CFB27E899A8CA52453F5459A281D0CC21F902403A596C7F69CBF9A64D97B935AB384FBEA5851D831E8420066826D7E11E34047D18CF08283BE8F29A8A79B0F477C27BC41B8EA4AA010ECF8ECE0D37389FF13E235A4526070F96F415D41AF2E053FD4440DDFFD69799456E7335CC6D9F4370008803F7BABB6C58B6996DC5A52649E25463B5267C188E2DC39B3258636ED8689E5C02E00574988B3AF881D30E9EB38AC51C1E00E1C0A411ECF37E314276221D7D8713F7A449E38371854EA26520ADDB58082287FAA1F77FC04095499A3C3A331A38852A287B24040C1CCC054086964FB1EE2B328F3DE21A986507CD20B4DE4898DFD15045324B93FDF85E5392DE0F32C3BADD04784012E97CB9BA19472B0C20EB0A71C89149EBB601ABAA4A853F2C75DD2622235AC30D97B9D7B1216089B9CC8E879660E40EBCD15203404A8DECADC42114715F4D8A6A10511BACC4DDC23520445A95FA3945BC95878BFF18728E64DE8B7767CFBBAA21F3EF2D92F3D7DFDA792BBE4E5B3381077658BFBEF8DB95B64F9F2A44917B38DF6F9391118978544369C882B218E7A7A31AFC3EB9A75A28095C4478DC81F9CFA127BB749CC53898409365170823D65A0B46BCFBA0E47CC0C5F6ECBEE09131F134EDD254F4F58B50C486DADA13195B1A35739420A45BE6558401F64C3B6AC94B73397925C20545621C7ECDC7DA9F71A755F84D27F2C6D8415D37F2BF1966A76845216E41764AB96DC2E14C12DF3684F7683FDAF5EC771DB7050F81A4B3E516C7D5C955201A18F436962476C1284531764A9397E0EDBFFA8C3699929DAEAF968B4524BD98EE62F9A0DB9CBF99FDA80CC6C57A5EE1099B1EB29799A5B5BF5593CDA26CE2C66DEA3D40545465C1D21F5B9373556B9ED0AE30E90B836003CA83F78E29BD8D49550286DC2DE6407860E9A9CC5EAF3E1B1C73FC2D248B81B1CC8F59DABFB5DAADE6F2A0B38E76D9E6D0125955D08DE7F334A56A8F362CC5D883D56BF7BABAE6D9E425376D34A05AB863A0D9ADF7C6FDA574FA8DC60965E021532C25ED4D568412D4143FBF2C4EC2F230D08337A4E546E01F7C1BFF4C97F2F27AF400CAA57BCF398AA5BFFE155B0F29A085D5053DFBEDC3423818DE8FC597EEAB2C1663D8C81C71CB876F73AC854286063A2E8BD8614D06B80F3BF56381179342143F4C89B8CEFE9168B6A96F416DC617B9F544F9DF65CA6F4F7A84A327909666B70CFFE889C86ACA706A0A1365E248D6B341A004A27D4EE344F03CE6E85D3573E272D48210DF7C3178EFB7BFBEF7765D24754673C9EEC14C7513FD8DE6386B0829EF0980B826EC9C77C81D1E3B8CAA65992DB9C2F8DD691C520FA6F233AFAAEDBF287A57A9A66D2330F4636F02EA3148C4BCD2C8B114D48A1027FB3BD5008D732C427ADEDEC9969AEAD451E166954FDC207C1A4EC409CAC60E42383385187AF44F136F91A8461E62EAFE6FCADD1E491162E46CFBBADDDB72E5B54B7C655CB9489E7F4F7E55C93D3AD50CF84E1F47A706FEDF818A5246BC755D6D18EF18702F5A90CE51812A67227C5E5A051133576E9EBC18AFA18C1B05C854D343727B25BB10E3B9A3645D789287858FA43734D66AD831E8646FE604286544238DC99ACFE3C8285230FC784BB73360F72ED34795B1C46EDBE32A346BFA7F534B500C6C9D3EC26AD7ED20D1500E3DEDF141DF3C2F92E981472F0010A48F25429329AE92CBBB918246F5A53212703C75DFA15D014801A830DEB75BAA36 + +count = 76 +seed = B887F07DB5358C3FDC2402947BBC87ABD064B02A859FE8DB37B5BCBB916020443DABA5534A0778FD0B1C05EF3ABE6269 +mlen = 2541 +msg = E7E845902E852B331EF9923416E492C1641236E4E72408D800FD70774BA32B6B4BE04B6E82237A247D26F9A33AFC4745C16CE0554774C68B33CFC6E67AE34E42038FC6C324972642338DAEA75982C71720F1EC9542DF94B38434DA34A2003FABD9DAEA1950B7751DA6C81AFF7D03390F5D63455D417F5D12A510337A16197EBAF921B6A7A9A9A58F9696418ECED6B27CB8EFC8ECBD9B68714F721561AF8553A0D84E30E009A8985D011CB994EEAAF88C76F7F3261B47FC174155C138DB2EADB09A06073B211FC0D27113E8FEA0DA56E181CF532BA8207F5D80D6A30D8BACBA540D49A81A0763A0467DBA7883766ED6358E809261AA3D8B757C839B532F272C5767671A3A8BF3391B14F5E97BF2668A4E98847F1ABFA21E2370870DDF24504F89B3DB71E210C46D66EA7296D65C926E2C955D899AC830CD9D06808A68E9B3722B86E878CF21A5E5D41D7F3CD95D23A6344C259859735AE1A953ADE13CA103692B33AF90ED0345C7B038D938F8F494D90CBD3933B2A80FEDC2BE57960DB23AD018BAC63017A04FCC510553226CD86C74AB90E13C72A1BE12E4D751DC670A98EC4F81E9F8954A693FC7175BA7E50D340FF7F15D568D0ABDED0BB1FC557B1E55971B4C4CE8CC1B4D9E239C73B1133C9E1672DEE36A2D9527F315C21764648643D866B0E2AB6D2DEE61D838BC5DAC183FC511C4501B6E535ECC54F3EDAD6E8EDBF0DE7CB70BEE861B2BFF0D41BB87FFC0EBCAEE9A6DFB98D31D35CFB6DC0442FC285AD0879E7B218B6E66453FE04207FE814C5F72E49406B48FCB1DB145753DC2A2D3E9793594F7EF1A1A6339619E1040CDE605648234A51B2F6774B31C7F9A77C2CE3B98819132BB725D288C65901F7001E05FE5326B6F701C337D41C8CF8748FF9C276ECD398C725C36C11857605F58C0B154DD9F3C1B4649AE677533EB0338B7475254E273B786C2FE7DB4C13468CAF0AA2AECD55DC1A5F868C8EDFFD8BE8DEEC20A9FAA621C4680F3EEF4DFE4A79794FCBC5F8C56EEDCC3E1963569A36525D4F6A5BDBBA5D12966FD8A0FCC70783FD9F61613842F80D000C9281CBDF28C01C6F6AEAC10DF1DDCD0322E00C4E3CC801EF091D9C1B01E84DCE725D57C800D38990251AA1D1206AD93A7DDA40F27726D6A03D973150F7A88703724E314C0953D56DA6EAC442A70C2A08BC66BFA2B0EE11E185131E352D10DD714DDE502097AF0AD155AEEEC2A6B93B149B75DBB898B2B3A7C5FEF2F48D9B12A580F54C4EEF3FF83A4F13F2F194AF551D4800AE86AAD6EFC82CE460D325CBCFEE3400AE939431AB4070D7A7CC005F270896051E32B1051E58941530E250F05AF19FF416E65CE40655FDA31D2E7A6158E07DA08FA61AFD5319B682DE44AFAE146129A8B769C1708A5D3479B6C910B2FF0FC872A4A41AA8BF3EE16F80011D163B599D18501335A2BE10CF117DDA094FE01596C404C14580A7075D04CEEF68BD8F813D7DE6599F478F3DE9CE60B294CB7CE5284A61E078939D08F3D4FD998ADD3B92532AA54E0C31087CF14BF4EC964EBAAD53BD15D04E37948E94917DDE181EE3BB2346335FFB403B000F5669019C5281D88A0E771176E49DD0BA22E719C0B731EC2AAE9C898E74B2967BCBDCE0D7D73057E004BD62269F4E7F3823DCC18CD6C551104B9B896B0AD138DDE7C3D761138641BD3EFF3DF1552659FD97BDADFC59A05CBC622A4492A1B22CFF72AC197D61A4C5A949AA9AC09D4C1112F4C1B1CAE353C70278A21663E11F27E9EC66ECD4AD56F2179A3FCEC37AC3A3F4B33C06BBBD4C8CE8E74825BBDA3E58A2E2D928C2C6E6D886274BC0E2175AB03D8721C664FBD6455DB2960E3AEF0BB25AFD3CB0BAFB71A2BD18A89ADAEE00AADBC7E4AE70ED4B534AEEAB88559194755F9656B43BC83E3952000D9E2295BF3391904218A015C786DE0144868EE4AED203B261FE743B7168788A0680F7484792A3F64782B2B1ED9217B09AE9845DD71ED363F18E8AAECD51A4F5913AAB33FEA3FC5F1E37E0CD6333D2A8347CF45EB7C4AD967FE6FCFFF3565743435EF09A646E75C7E968ECF4202A9B2C23AA8118A1683219B1155C2CABC95C696704F5B270C6D213332649363AE13EC811E9A1090D1603EFF745E2FA83379DFC6DA5EFECED556E46A8A5FF1F2A5C0D911B95C20EC2465AD0C96AE7E16FC36143762BBC0734CF4D6134DCB0D739F7822470E0ABF66A0AB15CE0D6096D3ABBA2CA4C81C1C68BDC252A8A4BA609B7C05CCD913EA56126F418FC0B06DE8F76EF651F8085604C16E5910F3B8651AB78296B56B78326E41AC15774E442017FE5B291E5227EF5A4B78CCFA96D6921C8542A8A984BC87E2678903869C52C2568FEE4E23EF3CC466CE270614E6472244A4294B31F9438F7E43437FC9C9C5F3EFB0F4F0AF2110A613661DC24A1C7F7A7F8CD14A943821F16F94BD874F1A32E305DB4776CDF6633446724CCBB2488B1B06F0177819D53885127E6EB717C0D6718366A8B8A089AA6AB17CB2581A75EC748123B7D0383F3900EFCFF77D2E022E90AA41491117758221A0B149C8EBC23CC01C17B9FD39118DAD413A391CFA0A5C614208060A61646C7CF1DFAD4ABC3A9CC5CD566DB2AC8FAF392C9D8E7DA0F84B941D792A8493FBEBAD30D0DAA0D683DCC1583F0C9019622EB6C92FBC475BABC8B626319BE2264ED873AC063F84B7F83688AC99D732A1E3FC12281BFB1E1E63D48BFBFCA619BF4B95F899C50AD0F5FE4673347DF2BBF2CA21BEF49C7F8440D95A83299960F1E42B457ADDCCCE236946DE80FD4862BAF36387E041DEAAC3C9751AE345512BB1F423A3B4CA8D3A5E3796D289641D3424FF22670A46552EC68D7D095E8636441D777DBE2E9DBF6B5FEDE5318516C3886B943F6ADF17D8B7CD40B20A48233C9FD981145B45A5CB8F6A88EAA36C270E93E1D876D7781BB92A1FD99727D8E0AE34C73398AB8781BB342F5AACF4081459EA5EC20C30CBB6122344C457F92B20448F78E1A2A291202003781EBDA1747061C6CE1F8BF882FEA4FB50BFE638685CD638EEC15BC24252567025FC5C16ED1F5D98DD90C76E720EF7B4E25A20D262E339C5E5BB5A9CF051BF5FD1F63E93452A179277B57956821CDD901F1C01E634AE18485708A6ED8F592AE2EF3A9D54C9734FFBADC6F0B86D0398AECE9374F9ACAFEF38D4B97BE9B932B9852F97AEEC435311A67AE344AC1985738C72F52B3D8B71F64A916240477FDDC5FAF02F8224EB35D310FEA03FD2C5933047355A438676D92EADF70DF662D97C2F5E00CB293053699D51D302B78145C77AB03F34EAF170EDA5215436FAF0238A4B0D41D29F36052A5278C7D8AF9A6FFC6E2B6FFC4C5D524F7640A7170957F3DE2451AC75589CE328B61EA7179FD990DA1698F5C73BB8639A4DA2AD67D364DB04771CA118C4055C25F1120A0643158C07CD22B375D5C1DFA26FFCDA44921F41D4A504B2279DFF03421CAD19960F87C6B6DD8C29981CB66C9731F931E43B0D97C6AC9862E2CF711DF0DED8E4D06F3957FFF9085A95D9FCC95610FDE22856B229A3121D8B81EE83DEE4A6A9FA3FE8C75351574CB000BF7F3746CA1CC5414AEB23A2 +pk = 02F802E0EE8A8855D1EFA29D37A529E5B02BB1D225AFD42FC3C9006A63B4A4A3EFD443308CDE35676B64706D4A967D75461B7DFD94D2E8B7804114B5B41303C1FF3A27508528DF79AC823C81EEBAADF65BFF5A83ABEC0EC4CA85C91BDD6ACFC33FAC36D89C145A91DAB768ED568C40236B2477D5C6B3F7D6BB162DFD41813CBDB99D2EC3E4C076C91A4C1F2CBA2C3379BB26A77912E43034B85EB561990CB78AE6F228349C8785E768B7B11E53A5E808282847700D41C251B27C9C3AB8D2D0D59107A0B08B2AA1F1D3BD07C037459D4AA4DA0C4EF3AF316F8ABCE6F673EE26B8A43226E064D0F701CFA5CCDB617FDE42066A8BDFC1A08EC32CCA1B4B953329D09865E20DA148B3F0D52C97D9768875940A35888E9D99441B29439ED6F40DF8F53FC48479AD158CAA31D534A37271BCDD16552362F524BE98EBA56387B74DF8EB7E72C5C49798E52A55563A85FDCAE063EAC33341B3E0E076098A3F9194664DE43AD5FBE8C0261C7A9856E778CB3B2BB8594712720280DF58C0F63203A2636F49C2238042CC2E5EA24A8AA30B5DAE120726A67CFA2D0A39DA63C7B33C74E8858452C9CB0FAC00CE400B1CAC1D1FD8BD2A07B9D70168A14F2F5B9472A35448BF6F3FBF0C8DB05DE39957F1C378CDE09F7C57B861E005D7E781884BEA8592AD3DD747DA30DA7F7413C79B9ADAEDD68C03F3534B60BCF92CD4FAE1615D04396F8C784C20512EF38867F11252D966F14AADEF82A3415F6C923AF10D14BB44855B5A3D70EF0F0986C674AE052F991C6D0DA5A53443E64522FF499AA390E7B2AF50AF97AB3ABF051CE488825C93993832DBF6380D40DC2D77961410E5DF87E71154601ACDD30611113C422267EDABBB53E251BBA1664C2F002510D9F7E930F97F5E7CB9A20353617AF40C74B1BA4E7E5C68317577AC30DD019A81A4C4E564960A96071FE88FBFE33BA371EF2D81B86A5B97AF7002FE1B60A14652DA3FBAD57A449419EADF3D179FC516F89958713E17C9069B3460C69F6268C23E7ADC4DB6582AE113673EA72594F4F358C53C5A002C61D2A81B2AE3696829EBC55261E61A8A00890F893B50ED1338AD325E80115C9F8908C2EE53F2830C6F533EA311B1483BEB777D858E97BC4FAE782F9B8D16C18A293645F3DBA5EB087DC6D585931717C89E3D13089FEBF92B6EFDA43794C62876FC8B44FD4382446EE22B77C9AEDF9026CF069098E85805AB9A2C74341A117A386FAD36CC214BF3A3D2E5D47A15F324041B8C130F0A327FF1DD2C5BD98A7AC1B837843B683F37BC1EC09DA28144109F2F4EBAC3EB196C732444739BDFA9A200291E8286B3B14AB12E4E8584025861D0686D3C51CE81A07C5E9954FB22BA5B27EB83EF6A8C24DA415B74808534EA355A15B152DB499C5F13BD7A4265A51272F8F89A373A56A953990B5A8CD16A21DBA6C1A71D1BAE7DB291BDE49FF5816791D21ED1A2FADF48014EC6256F3A0507E5F222A47DFF064A4DF68E264A9C822F54976693D19DB82EAA9F3626BFE0988A3E3D51A568081EDF912F1D9AA3CE1F5DA9F986D50AE7D3F6C8200481019465DFAE863887EC860FDC863DBCE49A30041B41B0C79789318A63D8662442C4CA5F34F6DC39955B340A49E3F049F2D6DB290AA8047418EDB0AC837527C16E8300CDCD40A570DA5E3803C943821CF2AF6FCE2013F0DA335C70637CF4B8F21F0ABE3C61094C6A690087E824E3A2D12E26F3227FB295510800AFAB4D5C75B754F8B9E02A55DD4CB490EF8465C4FDDA15950DA416042A0C1800E30D259414BBF809E72280A50DC3EBF476623A5AF96C2441DD20A7A3394BE7C8C8D1FD9CE8608E2D80609322B7B42523640379CFD5E4AFD20F59E70BEE440EE5ECB4BB98C07150F68018C507C185D70B4CFC1D87670A4D875D16CBA0D1EEA73C6B7F47F27334651FC228E330B1701A1FEBDBA537E66D5F78B75302571997F0A8C9EF2850A45832F090A0F7AC4F9983A928516AA2A6A50C4B9A9A04CFD10373DF2E50C1441F0D3ADCB4CC5691C84FDA92E7A461B039D45D0F62E800BB35CC764533A137DDD187CA454997F9450ECFAB03349B6871B4690FD14A5505EC02CDFD5E45D45A79071084FBACBD209698E4A440581AF479D34B6F529A57A1AF2F25DE58EEA7A3A4E3CA698A6A8BC34A66C72353E46E227E80E128969F057914C75E7275D330A905ED882E211D04EF990BE1CC38209CD58A2BD7D4F545D4F179C4A2583729E0EB347AA37963861554E5BA721BCB185FF64B3B870BD0E6E8A255C063479B55963543F8A7138A259A2CD6635EB4C69A361012CF2BAFC1A1CAA6C05B6CC4DE804E9CF8DFAF94976AECF3431CF772F4AE051903FC1885863F8D9EFD3CD7A12AEB766AB5F27E13D0D4B81955A1F41A1FDD19336398F329F2958A8AFBFF4F3E9B9B2EF62012B7C7975AD18FF6B606B9A1035E1FA7ABD611AED4AA3F896EDBBCCB37528DAB6EFB4F508BA5EF04492FC3C77B4FE11ACF74D3647AD3B4A501F15E60FCB459A7CB017B6F3F0D35BDC318CC10EB4889CC796EB5B94693C1D9C0ECF2B9545D0BF512F813FA1334A6F31B3438E01D57A8FFB690FA433ED94B8F081A763C1DEE54E37EEAD915438E36558AFCA8446F983A419646FD48BDBFE75BB1795E102D323F2EB8CC11C3BEBC79483FE12287BAD14E228B6EA530693998E6483B74982BEDD4FB93B3F581A697536E9CD280998F5F1EF94700BE6E69167FA9DC5E6F213B66228B59245B008B65F33B95FDBBE442F0 +sk = 02F802E0EE8A8855D1EFA29D37A529E5B02BB1D225AFD42FC3C9006A63B4A4A30D1928CD22618964A63AD3E6F6023AB467D37BFD799A1F11341359B3FA25FDBEB9C53F31351930784809E094A4E79E31C11FC0750F0F291BC8D482DBF6079FD94AF52FE20807042CE8B2DADFA41DFBA7C1DD6CBDEDE8FF6ABBCDE9EDC1FBDD857188122076266860576154805840336382016472425527273042432834478818106480431131707713328756808336000052884224553254285804037204404162057285243137027403420664711874676040611622555544521221450073784814607363341123434412266603764557157841376645281646807030408257147758650012500276777356524050831402836062472101318111863666654884731761333831805850465125326516475346614660648703738487026225565781273276305615163237077661777647048168684780180284821718101808572264441502345324666721878046521123572675602832470725472538873873248010102312765175785215374303126513301530424167120042851268521420528035316744331837668150138121000550535346616442577631543285181838455202217575046148475665162464244351140848754020305328062870855466233526461265587653746007527822708166203165658265331362300056224554586578531121368251762622012082763714536883602155285150375780143754064581220803024817187110263645211231136626707558854586584356327286335882552224881685168511642358771071857425312803575260724408200275203560862604438288176405683371783068646368554300026126258568403344750005818427574282218764824745006627857348725463143620637072510723355375430537331374828383413516470734163751365062502077885781007540738256148773644647444712608641243412653748088105148648747635168236158667720658787005516223708207054452211408543455528588115287547763401335805373153318111863012803628267185850671630267626342341372347282828648404375645672278010010161106341688808057145354035102658217886088311741568440676867064728278202473326055031018783136228305708585575588557241461772860445762705111406516717720328860671653078034254382347517672621754170816436202610782421637830567703501434151473307844323661305622370304281646776576883060730801072321833243482133562550518340627360740755410860661425454601381060143728456715512505314273784288063205250310063440664305640786534625647405784325688784565130831655248562461747475884065503363626172758430278437431666618207250676826321174821136135231642248822626507242047257036716854328302410072016326520586565783083858223104258782354607356460783136378127786145444212548864642652586116550815700633371700206575374250000157243602806828423418323354258142870034021530222387230384074722314133772628520005723628404675084688064311184606218817014308512070682521625684121051747070280313010060204701800645324242271645161844041471400317138063881040743062045573654551080584226322801736862036200442408311752276144582657030370358423260533847115567075326064817332104101037434662238484428438351707368781104752048317844873351577171858875052064527628677387657176506237766855740848774568821800507302507011433785044168708258100414102827246742246687824622166326785264208328840130065821831176202607174073338734865382767337004032066080852384717346313710881560786454266232403106171707550347341251241256367708616471103712288857814043257203268114300215346618576071E6264B0A95A86E37F49FD0843FA934B6D76F992592DE9236D8C31B1BE61B30DF8D6DF4D113257AB9696AE3CABC4C7F963A1EF0FA115F355ACD8559ACF87F5344CFA8EAA80E74FAA26DAC583097067FCDB10872FA97BA851C9E59FDB79F2EE7A1839A796464814183014BDB23272F671586BAAAC5B2621BA27103AB0E9D56ACAB8260814662F2C1EA542401392A671032A3166687B0C08613D21BE5E23B2A5412C27B5D6F0D194730A0AFDEDC0056041BFE94B4C3244A8C826B7EBD984D9662A43578C603889FAA390EE13DEA652E69390D0920296C3EC80FC8E55C8458249B939348F80F5BDA7ADE01312986949F1555721FCB5AEFBD51EACE6F51088FB4513E0DB8F51C9782D7CA4C8DB4D9146E74F664123BC1245D83A51132AB142D4F04A008F4116EA37D14C09FCB35DA7E28F375FC89447E2C136CAC15B4980F6E88F0CE8AB990D419CFA468E0D58288A13A318327632D7C14313B7D9FAADFF37937C1CCDB73586D0DDB5D00840C6F1492CB5C739D3389C8A6E7DE402810CFA00404ABFAF7541244A8F980CD826BE031E4022E8E787A83781FA47D5D551D14F472FE66465E7981B081F38E2DB3BE3A0EDBE0225132D4788A74CF6AFE0CA89B8F387CA23D50FA989889D967D2C4DD645723596AEF48C857DEAAE342DC1091184C6C92C61C660B23E35CF62528D7F5F2B3DD3FB0111F81AF98EED25599C69E82C74A792AF5FFA6D7ABA6FBF8B9EE3614B62AF296AECC53E7B3B039D161E23DD14F40194455A8E1182DD2AD3263447113872E2A64C4C27A56425CC7E35E5295ED2CBF2F261777F09CA95D138A93A05512047857062835CB22F8FC77F0B24FDC18095C0D59C00E71316B8376E1C0EE392CACC37A09FE86DBD803F541996E3497D1A0FC9199F4AABD563416389E74C8517396EFF905750360470D9D1093B32FE1AD1B68E3DBFF2C2D1115B5A49EF533E5152A822A4173702E3A08B10133FB834644884DD1F6D187F96884E8AC27E00B536906B850E0DDE0C3969D152E82F30CD4CE0FE9B97CDE2994ACEB52C7A4250FF3B2A3077E2BB2D9D58FD50FB027F6A906362D337AE1E790E3628175B112704CF01A9850A5E1B5DEA92C9FB4C1AA42CEF919D1028B480BB46F524A79C4200972F737A8A1EDB4F6D13148D90A14B616B2E05DA4C4E6CE242B27EC8C869C85EF3528B0E130B01586A4F1C99A270E314C7539DF17944ABE037FF3C7C75AEA3E047FF9FFDD155D9FD8B379DF77755CEAD7DA459AC7CBDA29075A77FBB69A6E1B1A3FDDC6EF38C963036C147A8DBF56023513245FBC39DEF2390D509AD863A6D1DD799420231F4CD034072B16CA3F5F38E11B6436FADCD22FD6C8BBB46775533696613729B70AB80B6F8234B8DFB9EB372920D8E11C79B617617E9B54BF6BB9AF9B5108167190DF4C376D5BFD3EADB0E82E10A6E5A3CB37D16EF0CFE62B7ABE9523879308123981DF72B4BD43B9868AF8E036890ABAB2B8237E43A0829200E2ED34B2B9962D2606256FF7BB91DE926C905C28271EA7C9E1F80C42B6DE28B239FB84BFAFA451AA61B019663141B5DADE218492A5525CED7D478FC4517D4E5EAF856A629FD0DEDE57C990776206E408ACE28B42D75F71ECE4C4D1C07C9552A5EF310CA9295D475B18A481457B498A0AADBE4D0909B3344722D0353CDAFEF3AE7F230482A535707AB29F3AC21F8D6B18CACCCFEFF82824BB09CB0C15DFCDED881D0F22D0B345A55E0043B396867CAB50543F580B98A9A3B582A41EB6EBC15A7CEABD81EA907CD4C8533E6B7F8A4D1C7CDD1577F06BF90C2B454AE36D04823B066AED85D96ECBE47898C6C9FC0B625AFFBDDDDE72316B80B1BA1ECD5AC1AF62D93633CCBF9D8CBE7AAAEDCCD93B59358561FBF7D056804C18A6EB1C6B29A74B7F0BA233426241B548CA8D18F759FB2D3E1E1D19AADF6F9359F2CAFB38E90682DBDB92B166903B20A3E38CBD905513EC0E8F53151FF9CDA3D66B748DFCA39A5FE3B29F81D4586A18AC6E822FB2CCAE02A06F3169A3C7E694A39D3CADE233F668FD285AE06C73EDDD5E9E4D6EC9ED7265B2F05B116C80CBEA8ACD4D832743D2C0344966EC21942BBC14A280DA70488506BA5D4E36462335C1F615F0B000B68391433564244C1EED7A9CE07EB60246E7A7433DB60F3480BA1505C0CDE4258343E3B5EC1E74F047F28D071134CE70A9F011E2D495ED95679C91BB24D3BF85A156DB5DB87ECB19E52CABE289F03493D50DD01F331C37F22DA86296089D05379AAEAD5A99F0EFE22BEE5C6431B29F9ED459C01A040D8BF63290073604D93EF94400147BD86EB00E9F670421F4CC15B4B9B17F1A9496F892E3070891E12F41B6C6F8777761F11EF9E9F026210650D3B20719C8CC7AF03B39AAC76E63EC5219EA07F4901B2345B6F40ACC94AB3F84B5FE1BDF465A4EAC8426F3E4E97A6FB40C9C3AE63EF4FAA97C442F0B2965114DCC7E70375D4E6315A945B793C1DD1C54C146D446608AAF7D5A9F74D3BEA423B133A79636DABBAFA9C41B705BB4609FDE5A27AC621837713378B7F53017D5D25AEF2CE6EF35CA54A3278D9A316E5A5A7734848D321BE3501BE59CB40F4E8E06DE8D9410AB066990034303D1A99763A4AA621EEFADF0D0542AABB81B6AF440128D773BC39BB7559F8D199CE1553928113F392B1487897925C852112B0FEE9F32DD86C572DCF46CED6B1BFB15C0A3898939671C4207D43E406821BEC6537E21DF416ACDF1408DB1A1B460DB6EA9C56CDEC15295260F84A9953FB474EC38F81736BFD0004B2D8CF962F463390DBBEECEDA9024C919AB984B22CBCC970C5D35D5C17DF5827941968AE8F3F5F716183FCDEA1482840BC04654B44021653217444794FCDE99AE5FD232F5781D150C972A28350CDA9E29CEA5DE2AFB9ABDE712B77B5A6451DA89B9EDFB66B3BDFFCE29B7740B6C8D08FA871E2043EF31D6D6AEF89B50F44DAE836DA40C4A19766366361101FFBA272CB25F4D2D86E6F09316B9BF73E8A3BC93A1811299E953D04A21FF5D97AB5E18E834AB60EC8A2A4433C91C6B48120FD122041301962C84AF012672067B4FC4251A056CA267DBD552AA47391CD56C8E6343D1F29D2F02AB715AD52DED7A16EF9164767AE0B539A62CA14F80733C44933F39A8C5994BD1C42D204FB385AE7D8C94BB0A7FC9245D90D0447C59C6AC191E5FA28CFC13695D03F8DF0EA7392C209712744159BD33F00EE3C4EEB13170039A622CF835E1E7978FD5ACB335C1B5C2EC9368296E4AC30900063659C9FEF8FABB22D8E1ED926DDEA5356B94F39E43FCE724EBCBCA4491F6F4E6FAC984D5C4CFF99A0A555345FFD41E38CAE600DA4F1679DA493B41180C6774C890AD7C760B764ECBB8C2246C5C70486798917176484F02C8358984788472FA222622A42F04EE9E789F1FCF87D2AA9945471CA9BDF59077DF071CA5B048F3D727D23B7A4360C7247A9ADCDB29C3194802405C058470589BA631023853BC0B9D3D5A943FD83419D57DFD68668F0C86FD4D456EB653667547 +smlen = 5850 +sm = 844F0880C9F032A6C8103B2AF46E8EB3CBF7DEBDDF0AC53B697B06DD2B53C7912D9B79B3D36D062F2908BAD3CF22BD20FA785B38285B332CE1E57E0D04F5144AABAD3B22E531D4BF607F475D2DC2A06A7FB2C885052B34EAE5FFACE67A583D7C5F4C0B0E3A07B2CE3C47B3B1914F43693002755FCFECAE3F22DF53D8F9A73A85C93A7978C6B93E265C63B52E523D71C2A74C8C4D67E97A137824A8903D7474F091816236CA34B7B1C0E4FDDB6C556A11871A4618AA7F9A8FC5AB335CFC40F4D6D96E2991F872BF2238157F9B3134AB7485DCD83B91B6DFED8FBF40CAA5F442FC4CAB39C53E99CF7188DA2D395314DBE884EF836E3968D15AF817AAB35DC64FADD218B8842209D5BDA7ACFBCA0A1DDC9245CBFE73A307934C20ABD0FA8B1AF5EC3C956DFD0551237D8AE1543D87679627D537F8B5356C72DE46B0795ACE530EB9F348AA5585F9DAD4D6B6004F6CE9AE9DEC067664B243C7F056BF04A1B1F17B125F0D500D6F91CA709B5C5FC41815C6FC2A834FA3BD92A6E6DB3D83DB0820136DCA2F76A3A75A73EF6F883140C2F7CDF81302F6AA2CF2D04F7C06C21224339144AAE399B0EF453B94D76E916D4A6992BC3F8AC7C8F60657A14CD214C98DE499AAE0CF57B628C640CB6FE8428871C24F22DB4C345D0B27E5146EA1FA495133A9A3D339C2D842FAA1391CA343BB50E275D8C632DD1E0BB2ED72224CB6FB6F039A3702CFA86A2688DB65041C859D5DEF85509D6CA57CA446BAC95FFECA20DEAF766FEFE51ABA01E3F112553D3BA4E9DB47A1A827EC0A1319BE5ACAC9C853D7529DDFE776B5C03849BD2F619ABEFF0FF4C4A13C98583EA53AEC8A86ED23B95065CC2692DA973895F70340684EB48C3DBD8E958A0000750507A224214EAC198F147B007FD374E38EBF23C43D7D5C8EE0DFCD1D9282AF146AA309A10E231B0415DFD658159B69FA9D72020992775DA5E9DD97DD6665043A298F067284542A8DE0E71DA139BAAAB67CCF6AD91A360CA16825D7FC29329ED092077C35670F0ACFB17C53678B816E0962B98BD6DBCB41DF687A7D325387A981060265ADD025FBDB4A9292945B75ACCD472AEA58BF8817DD1163F194A075C5AAAC431B1740E9807854FFEE8F6EABA214F703A12FBE37256AC19AFBF30A35B66C09B25447F9E6D95953CF970A46B5797DDB56F20C4391CBF4B3476ACFC118C4A8D4DB3E6241F2D39BD16EA2D79961D7B10780098096BFC51E2FD68F01101F621076DB11E8A8E5A7C0D2376CCB6D88631A6F8B296C169C1C6AEBC7C7BED1EB58F5D44959E24FCA84E7C5E0E426CAF7C9D17A2660FE5206A62FB027B7636B233EACEE93E370CBD0F5DE9D0836F0E90CD8428608C6A53E4D419FDB32E6900A0F5FB6D8DDB53C5C2943D6D52EBB31669BB0ACB3582A491B6C319F61CB5403F25E66FFEB38B0C74964908EA5A312E3A3EC7D8A9795C11CE1C6A537AE5F70FDF94AD7DC2806D4834E2FA38BD3644BF642BFD4A175CAA0694F1F9E45CEB44FE12684421FDCDD6E44DCD51706802A8606FEF853849AB6B2ED04E6EFE1D7EA2BB0013053471F24BFB1F6708AB7E3DC9CF704BCDC8F6ECF6549F8704E1DF093B1C4B3A7BC675090C9E2F795B910C054746DE8DC15F057A8B4BB9BC2CCA20D214D32199E9DCD2D2CD5730885E7BD221CD5ED2D8274BE12F7EDF422F2506683D70731EE5496DB64D51F0AA2CFF6706592968DD8B086C48DCFE146B17CC93069834E914EB5EA138D709C7EAD34543FFCD10E1930EBD3C630372AE46F7A4DA9A3C4890EDE06282C236D70856D96B77FF9122DE2E52F822E3D0A76022917A43F56026360273D366F2D27B2C093AEC1B01453390689B0D61AE8A4C105A94F7AD37482B088B6BE494FE212375A5F1B605AD3BB4CD14579DBCD3FD34CA61B6030EFF1A6FAB413ADC97AE50EF2BC453C151CBC33A45FDA703BDE8977B90AA35E8DC3BB64FFDB8C6C54EADC117E334684BDFEB6E2F5F24E0CDCDEAAB283F6759F305E2B97DBDAC4155061E21DBA262BC0985299FC046604FD33C85ED2B8024B50C77E1C40E02793D3D7CF4E25EDE1B19B866BAF6CB2662915B5D921691E26ACFB560028BA0AEA90D866EB03126B228D879882E58652FCF45B20241EFB84EB6C204D0E9C3355F18C628027DD642783BC5045AFC647BCAD1AF0170584D2A576D2668836C579D232EA8435A198103510EA4A500360C7B98ECEA2D1B947B7C4646AC857D5C8CB1F538F2DFB9E09853AE08FF904A209B71E18F1DCAF4A8A24FBC383259107AABE0C3B65E428CB9FDA72583D998C1B373990465FC6EBF0A91EDA3B9F14C4B6343DEBE1908A5107A7ED5E827B4A96C1BDF3E123F02A34A58A238F74FA7511DE75CD92274848F85260F6525CF50CEEA0CFC5C5ADC635C7A9F3FEB5A684386E2A9C8532E8AE9CDE3659D20579255E71B95D770D06BF8072C4DA3DC40796C103E18031198E8039ED19E7B11B7CF3DF8A3C5E0CAF98AEEB6212CAB704E2D9CC1BB6C6B9C3CC42380102D32EBDD8F379FA8037F9C76A1D92E9FC456362D64D123D87724148F20D6B8DE343DE0DD0C9F67D436FB0EDC02AE345EBF213B23C94594821991BB24BC2283BDE5736666E7CFC2D36654E9D49F925781D3307E2094649536BD6AF3AA5C179EE72187E7D3B0844C5E040B79CC40F185CB52A8998CFFAEC5E85A2646773D73CC7A99ABA030AA5DE7F49A350B5DD864FD5203A37678C51A2BB074F910732900D5F38905EBB14D6FDB1572B53EA0183B9BD32D6A568F3A88C1FDEDBA11B96D953061474A1583C3AC363B39D78BC04DACF25D82ED378AE34AA30DCF17BFCAC97C8B03059DBEC05A4C1C578BEB523DF02BD5FA8B01E8837DDCC5B46FB75EF16FD4046D2A1FD461125B36D2C408088435079D562B4D721F68DC57043C78F14AED8C0048C8B2CD1EBE8AA28CCE6739CA455B3EC138E1951E4AA2A7160EF0093F6C25A29EDBC19BEBDCA58D7821412A42458A4A8D8C55A21F86B4431A8EC7A732CC4A6B6DB293B21A372EF3F3C2C49B1156B6F3A4665771931AE190A28C60C5300BBD30641BF4E036F0BE478BCCA7502D9ABA83DE90DB2243B733641080A3AD0DCAC4B37D2987FC3E9BBD1767B5F7500E7C553B9808644D1619BB5FC52BCD7814E0085DB018FCCD4DEE03F6CD3EA91A054FC5AC6AB3F1D689E824373DF153B22759C11319329743CB1B5409C22CC9BA96429F6007B14CF9BE9E91759D79CE6A0BA47253F14D9DF2F7DBC5D04FDAAE3A25FFB6E2997FCF2C1BE177356BAC6EE8E70FE97C82499812845E324242799757CCC3D33D84DED251B646243410F8ACB855A5B4ED1DFA9DC0D315506606696A6FC36F1F86F50E94A6425C0917F67720D49FBBBEDF1D4C8C97EFDF866B0C32002AFCE639A9C99E463343F86F421460CAAC1CF2C5D6C9F49C96860AEBC58A10CFDF1EDF363A10F7D0A2DFC2FE97B32A85B1C536A96677D7EC220AC06C8178D339205CE7C86EB0EE55B801E3D00FC62ED4B339567683D0C53FEFCFE2689E23ADD5BD6593AE8AC7B07FB1DD2EAD51781B5C0A62DA46157BD90B147F428EFDCF9507953C2250A86994076BF90A795500187D4628A4A4B219673680D9BDB25F8E91380DBF776F5A99104B39810A10E8F4CB1BF3DABC6209EEBA65AFCF484C0E9A9B5CAF93F5E6D0923BA392AC67993586879DCA0BC925253A6CBCC178AB49B49B7583B33EF92DCD1A7D9E7C5529FAAE68A938F7EBF991A9903617AB41C61D94B755791087F22775F01BD062C4B333879D5B3A762384EEED090B7F0BB42E0CD10AC9896BB97858B4583C7AC3935925E2D7FDD0F825B93887C8C39DDA6CDE17998DBF358987DD09180EC728778463205B8C4798B266B3AA3AC92C3DE304AA6D9CB4E2AEDD9C1F9979336C83DF5F8EE3723972D0DE5E18D8E0B2F275B55425FA8D4CD6CA8B2F9D494E0196F9AB11728C10C36CF56BAAEC481E45642692421E0948AA731F2C21CB6AFCDA9507723AD22F6925AC84C1A7EC0D03CA6CD8829F6993AEFA3C88D1658A783C08362916DD2BC80A4243848151AF705379208F39A9164C6A5822144A78E6B8317ACB163B4943096930E477AC53C54843848036E2425C4206FC3E53548623228D581B093A91F29FE6E03FE138968959F016E1BD976BECBAB87EAF556F14BC4F4521165D78BB9FD95D365B258F292CC494B384824EB40842BE827AEEB4F35A9FF4C3E1341866C2C3033754F5D59E7DE73FE63592E664AD655D2CB8FE1C00A875F40C1EA9BD960312E5835FF93A06911A636CFC3E3D6060119A0EA10E769414B6D35BC7E77F22CB4C2ADDBBD3F7F2D2FDF36E5B6CAB7A71806BE75A0DD309FD9570F4704653F3C92A58C776CAFDE45E9D50118BD6B2304AD693F526358029D8A9268ED0198CC1D295A75A354176348762AE3F93CA117F21F63EAE544D7987F1437A9841366D382566FC79C29059B0D780760C04FFA627E0D1044053049DB4C9B062870B0AC8191634C9CEFA94935A5B1C0F798CEBB94212E95555C65A07C8978611C585B77966606CB6A61BD3D5C4F8F6ED4FC1121916D0AFC40D02EDE10A458D3B7FBB1E93928524C0BA9055FF179172951C5CDD4EC0C2F3869C5FB184C50616D77F0F23294DC2E3B949ED42D394B565B98C000000000000000000000000000000000000000070D15181D24E7E845902E852B331EF9923416E492C1641236E4E72408D800FD70774BA32B6B4BE04B6E82237A247D26F9A33AFC4745C16CE0554774C68B33CFC6E67AE34E42038FC6C324972642338DAEA75982C71720F1EC9542DF94B38434DA34A2003FABD9DAEA1950B7751DA6C81AFF7D03390F5D63455D417F5D12A510337A16197EBAF921B6A7A9A9A58F9696418ECED6B27CB8EFC8ECBD9B68714F721561AF8553A0D84E30E009A8985D011CB994EEAAF88C76F7F3261B47FC174155C138DB2EADB09A06073B211FC0D27113E8FEA0DA56E181CF532BA8207F5D80D6A30D8BACBA540D49A81A0763A0467DBA7883766ED6358E809261AA3D8B757C839B532F272C5767671A3A8BF3391B14F5E97BF2668A4E98847F1ABFA21E2370870DDF24504F89B3DB71E210C46D66EA7296D65C926E2C955D899AC830CD9D06808A68E9B3722B86E878CF21A5E5D41D7F3CD95D23A6344C259859735AE1A953ADE13CA103692B33AF90ED0345C7B038D938F8F494D90CBD3933B2A80FEDC2BE57960DB23AD018BAC63017A04FCC510553226CD86C74AB90E13C72A1BE12E4D751DC670A98EC4F81E9F8954A693FC7175BA7E50D340FF7F15D568D0ABDED0BB1FC557B1E55971B4C4CE8CC1B4D9E239C73B1133C9E1672DEE36A2D9527F315C21764648643D866B0E2AB6D2DEE61D838BC5DAC183FC511C4501B6E535ECC54F3EDAD6E8EDBF0DE7CB70BEE861B2BFF0D41BB87FFC0EBCAEE9A6DFB98D31D35CFB6DC0442FC285AD0879E7B218B6E66453FE04207FE814C5F72E49406B48FCB1DB145753DC2A2D3E9793594F7EF1A1A6339619E1040CDE605648234A51B2F6774B31C7F9A77C2CE3B98819132BB725D288C65901F7001E05FE5326B6F701C337D41C8CF8748FF9C276ECD398C725C36C11857605F58C0B154DD9F3C1B4649AE677533EB0338B7475254E273B786C2FE7DB4C13468CAF0AA2AECD55DC1A5F868C8EDFFD8BE8DEEC20A9FAA621C4680F3EEF4DFE4A79794FCBC5F8C56EEDCC3E1963569A36525D4F6A5BDBBA5D12966FD8A0FCC70783FD9F61613842F80D000C9281CBDF28C01C6F6AEAC10DF1DDCD0322E00C4E3CC801EF091D9C1B01E84DCE725D57C800D38990251AA1D1206AD93A7DDA40F27726D6A03D973150F7A88703724E314C0953D56DA6EAC442A70C2A08BC66BFA2B0EE11E185131E352D10DD714DDE502097AF0AD155AEEEC2A6B93B149B75DBB898B2B3A7C5FEF2F48D9B12A580F54C4EEF3FF83A4F13F2F194AF551D4800AE86AAD6EFC82CE460D325CBCFEE3400AE939431AB4070D7A7CC005F270896051E32B1051E58941530E250F05AF19FF416E65CE40655FDA31D2E7A6158E07DA08FA61AFD5319B682DE44AFAE146129A8B769C1708A5D3479B6C910B2FF0FC872A4A41AA8BF3EE16F80011D163B599D18501335A2BE10CF117DDA094FE01596C404C14580A7075D04CEEF68BD8F813D7DE6599F478F3DE9CE60B294CB7CE5284A61E078939D08F3D4FD998ADD3B92532AA54E0C31087CF14BF4EC964EBAAD53BD15D04E37948E94917DDE181EE3BB2346335FFB403B000F5669019C5281D88A0E771176E49DD0BA22E719C0B731EC2AAE9C898E74B2967BCBDCE0D7D73057E004BD62269F4E7F3823DCC18CD6C551104B9B896B0AD138DDE7C3D761138641BD3EFF3DF1552659FD97BDADFC59A05CBC622A4492A1B22CFF72AC197D61A4C5A949AA9AC09D4C1112F4C1B1CAE353C70278A21663E11F27E9EC66ECD4AD56F2179A3FCEC37AC3A3F4B33C06BBBD4C8CE8E74825BBDA3E58A2E2D928C2C6E6D886274BC0E2175AB03D8721C664FBD6455DB2960E3AEF0BB25AFD3CB0BAFB71A2BD18A89ADAEE00AADBC7E4AE70ED4B534AEEAB88559194755F9656B43BC83E3952000D9E2295BF3391904218A015C786DE0144868EE4AED203B261FE743B7168788A0680F7484792A3F64782B2B1ED9217B09AE9845DD71ED363F18E8AAECD51A4F5913AAB33FEA3FC5F1E37E0CD6333D2A8347CF45EB7C4AD967FE6FCFFF3565743435EF09A646E75C7E968ECF4202A9B2C23AA8118A1683219B1155C2CABC95C696704F5B270C6D213332649363AE13EC811E9A1090D1603EFF745E2FA83379DFC6DA5EFECED556E46A8A5FF1F2A5C0D911B95C20EC2465AD0C96AE7E16FC36143762BBC0734CF4D6134DCB0D739F7822470E0ABF66A0AB15CE0D6096D3ABBA2CA4C81C1C68BDC252A8A4BA609B7C05CCD913EA56126F418FC0B06DE8F76EF651F8085604C16E5910F3B8651AB78296B56B78326E41AC15774E442017FE5B291E5227EF5A4B78CCFA96D6921C8542A8A984BC87E2678903869C52C2568FEE4E23EF3CC466CE270614E6472244A4294B31F9438F7E43437FC9C9C5F3EFB0F4F0AF2110A613661DC24A1C7F7A7F8CD14A943821F16F94BD874F1A32E305DB4776CDF6633446724CCBB2488B1B06F0177819D53885127E6EB717C0D6718366A8B8A089AA6AB17CB2581A75EC748123B7D0383F3900EFCFF77D2E022E90AA41491117758221A0B149C8EBC23CC01C17B9FD39118DAD413A391CFA0A5C614208060A61646C7CF1DFAD4ABC3A9CC5CD566DB2AC8FAF392C9D8E7DA0F84B941D792A8493FBEBAD30D0DAA0D683DCC1583F0C9019622EB6C92FBC475BABC8B626319BE2264ED873AC063F84B7F83688AC99D732A1E3FC12281BFB1E1E63D48BFBFCA619BF4B95F899C50AD0F5FE4673347DF2BBF2CA21BEF49C7F8440D95A83299960F1E42B457ADDCCCE236946DE80FD4862BAF36387E041DEAAC3C9751AE345512BB1F423A3B4CA8D3A5E3796D289641D3424FF22670A46552EC68D7D095E8636441D777DBE2E9DBF6B5FEDE5318516C3886B943F6ADF17D8B7CD40B20A48233C9FD981145B45A5CB8F6A88EAA36C270E93E1D876D7781BB92A1FD99727D8E0AE34C73398AB8781BB342F5AACF4081459EA5EC20C30CBB6122344C457F92B20448F78E1A2A291202003781EBDA1747061C6CE1F8BF882FEA4FB50BFE638685CD638EEC15BC24252567025FC5C16ED1F5D98DD90C76E720EF7B4E25A20D262E339C5E5BB5A9CF051BF5FD1F63E93452A179277B57956821CDD901F1C01E634AE18485708A6ED8F592AE2EF3A9D54C9734FFBADC6F0B86D0398AECE9374F9ACAFEF38D4B97BE9B932B9852F97AEEC435311A67AE344AC1985738C72F52B3D8B71F64A916240477FDDC5FAF02F8224EB35D310FEA03FD2C5933047355A438676D92EADF70DF662D97C2F5E00CB293053699D51D302B78145C77AB03F34EAF170EDA5215436FAF0238A4B0D41D29F36052A5278C7D8AF9A6FFC6E2B6FFC4C5D524F7640A7170957F3DE2451AC75589CE328B61EA7179FD990DA1698F5C73BB8639A4DA2AD67D364DB04771CA118C4055C25F1120A0643158C07CD22B375D5C1DFA26FFCDA44921F41D4A504B2279DFF03421CAD19960F87C6B6DD8C29981CB66C9731F931E43B0D97C6AC9862E2CF711DF0DED8E4D06F3957FFF9085A95D9FCC95610FDE22856B229A3121D8B81EE83DEE4A6A9FA3FE8C75351574CB000BF7F3746CA1CC5414AEB23A2 + +count = 77 +seed = D08A139CC7147ECAF4B1D1E434EB2EFA2B2607B0033D8BA989133E496DC9F3654944C7AF91CBB79866443E8C4E8217ED +mlen = 2574 +msg = 34FCF4626248B979A7A8D306CB9ED69C4CCB5CC3729D2692E0BA679D5C2FEAAC54A4E06D4EFCEDF78E19357DAE263E1B5D107FB09618A9C34F54F19A738A66B95E6F88E20E01F879F53E8F4C371B571E1438FF70E0A8CD00D608976E24501B2DDD323EFE6C1302A318CAD821C6FFE641672BB80AC62286C69FCFFD93422911C46D43DC9A1F00A73E19EBE6CC09A9801F2A1DA708F0F1F98E7F1A18529010823230279F487911CEF1E784A229D9E311BCE5E2D368E6D613F791DDD617D0F37F604B786CA2BAB754E8BC4BD3DA37E66A54DF1D3B268A5A80379A30A52B1532E8CFABE24168D83CBFD61E2346F901C361F771E0BE3E03DAE8CC30614C10FB8DCCDCAA5B9A25DDD8D61E61F60F22308E12ADC137D3D8C53CF7B31984CB813758BAA19AC178F2F0CD2155ED674A7509A3CFA7FF66D2D9B1E60BE50FE7FB79591C500F66BB1D35EDB80263F4B696A3DDA0B9B2911D01E76E9070D99DB93D1D0C3874CFFA776BA24424A6B453526F7C44EAFABE13C0750F9DF33E82105930139E70B5CF1B09DC3913D6BF4A4859F67FE814FF038F0FDAB93522A35E7F81002A395989D68B8B7E4235A09837CC6402A5338DA08E7C73DC63C43BAC42054C694F4931B80140D6B104EDEC995CEBCC5629F85D09DED8257626F9FA4079ADEF81D044C18BF2277DAAA41931B62A6028F89F95F06D8A8FDEB95EB2EB1E90C0D8523E0B476B158E3040F212390AB2503021E8D6FC0733B963CC6188FB2532829925B59C8255D89F10B657053D0FA1D8E76C84826A4609284503D3A101EBFE7AF93EDC423EF5303CD946C8B570511E38EB04BEE0060E678D03E4134F84F279A570AAD0332417FB2099E3F1F279CE7D6DDB080C5D83064D107BB560B21183AE165CBB54CC75313DE72D40D1CF5173455AA55C5C356D7C40A2A7023DD95D3F89B515D7598F800DCB7BF68B707978ECAF55B794A17559BD1E913F4472B1830783BBBAB5F23A760C78C46157FD1B429C445494CDF92FEC8BF9FC217D3CE2697BB6C671BAA793CD0C1C84F579F0DAEC400BEADA799A9F417FE4744145F21C6F8559AFA7A514A0E951F03E5E68C17A8E5816F3FCF41774D26BE2EDC11FC3A42CFCF00F817C3D0FBF474FD7F30C9C3C6BE7F74FCC79FA6AB07CAB037EEA7D83866673A74C087B5F7542804071D53CE348D2E836749E35AF0FB884D5D53ABB195AE1EE6E9AE35DC91BE359BCD510A7801FC243C07DEE92373918AA4F8A89EDA3895A52456F7244D1FF007CC7B1A52CBEF4C1ADE1C2C0AC189AB24B3F260475E1D08E7C5BFA30A1CDD71DE5ACE80D5FBD1D0F17198B79C8EEA0365D139F2AE73CAB6FBC9A79786896DE0CE7FC747D68FA4ABAB662A09E0E409F7E652153352BB92F5DA1836B0E92B0B644C821B2DD2BD0AF193AC0F8CF5B8D88432F0248DAB09B46FBEF2EF1899B5981E9B33DE4E9927AE50890FEFC35F681E075D8B0169A2E16FEDA6392AB9858DB87ED18ACBA25575AFD1FEDA9FB3FD01ECAC13C245DF6972F65087513F505187C4E8EA54B6433FA092B6CD3AF13F4718693904435C55D273060FBB5FDA76074691269493E86F287922D074E54EFF04209B2FDD3417D8436D1395E638D57DB75D68F4F819141B6DAF4D13A9A18629CF5F84B0CD02E7A397715DDE5476BDC467218D11AACD6CE399D9D54645BB27CA43076B7E4E57FB4F7C4F4B8D0AA949719D731C3A927FDEF1533D773CF1BB562D5EA43817A5ACEFE9EB7E51029DEA143E8A1D5F76F9BFD74A26C6D38F54194319A1AAABC4DAF45EFBAE770B9E9D834C09FE45C15D4BBC0251D3DF2F2F23387DCABCE6CA7A59625E18FD997770D164C338D0692AF97C749FB746C0D3944CA4B2DA6D3AD7B8C3AA922FC029CF9AC5580CFEAFF50CB2E9044211EA522BB5769BEB7A7BBA0743F345FEEA9AA9DA6EC5F0579CF7A5AA4DEDC832FE3F65185A31FD49C0D259E3B7F8FA96E110D130F588CDEC30D0FD4860CA6673C46D961FC68A4020FB03AE24B1AE12967EC1ED19ABEC0808A7EF89521152033F70F406A7005819D28DFC556C79DE18584088F40BE40A555EAEFA78E3FA3D9360A7CEBD963555CF208DC408A07CCC1369F98BD840F5C940721064E6C7CB241ED0697AF0FACF36F05632A504870ABF90134A01AF00D340F7A5D548A8078C2049600EE454D15EB8CE58C26B3C8185CF9DFCDCA7D4B6DCDEB82230F993D51E701D8387B06BD45B4B61DC9DA6D3B4356F50C1D4AD2B467D36AC092442FA90D1DEB014475AC7CE90C974063459DC951DECFA30D2DE4C70FBA39A8B6931217D0924FFA783C8C3DAF048908E4AAEAAA3B7C98846278AFDD1753252F39CAED7D334D8575CE3ECFB2EDEC31AFEB2BBE67FA929A267376293C2B2F295CD8DBD66106E1D9518BE1798949F3315E0454D018C2B706FE836FB37AB908D9D698AF495BD285A74E4CFC7612D42121F43FDAA7DCF44DA82897B820514D66B92983A3EC819D2CE208D688B6F0AACADC0CDD619D815CD231AD8DD9B6DBAD9C47E16FAC098D0F4279AB52055D2FF765AF6E3618C4509FAE6AB00FA23980EFB19A26E0A6EA4C9A7DC699121388748449C429B28AD2779F5642F05FF58B68BA3E289F90EB27CE06392616C080D659338CAF274D46A90D58F2BFED25E8D4A8C62030A5E89F6B1A5F6112A38661E2F2B5A37BCBF050812DCDCE9C0A939ADF929C921E7DA0C30815DA318EB2F350F286441CC92060C970077623EEE68B8C6FEC9FFFE780A6FC85FD7AF90172951337AF57339E98049132A4CF58874A7418FB7ABA0628B6192BB2C43102EE6B1D7E824725D9C75D34A8B69DF4A6BCB1F96B57767046C99EC6352751E2FE1075BB4092672379B3518DDC884FEAD5BD062B0336EA88BCBE0D22E066566347FEB617A322BEC561E9AA9D2177EEF0DFEEAF6231AD56D0CD9E300709C9317B3D334D8D2AC97F96CF2F45B8582C4128D95DA8CA207AE34D3DAACCDB128C11694EEE6D3E8E6AB767B6886B1F7235D85A4D9C7C831C5DB8AD8323F63927A638E19497CFB308285A03CA2C1FE2AC4D919AD11511ECC6F28E7D0E0A614FE21B57BCCDF83535C7E2C40840BA0014247190C580378454751EB3F2361D7193E160B9516F7EE1D683B336B873C8BA22E97480A61F002A73844C78309C0A3B31BE30A192A62BDCC3D33A7A5BA1F6AE0404A8558740CAE46E5FD15971B41C0BC39665A9B92EEB3328C328B073ED5B3720D37A1C097AF8A6FDDC3B2B067680E6CAA760368B0E1C052E804E9F80F26B52596202FF2E0AF7215999EAF7D3EE3E8916744E40AA1154322DD068AA15960DC38671A4F5889FBE709CE1DECCFA80B9D33AD2FD963FE0581A2ED7718A27CA62819D05BAA3212EC7CC1C5472BCF579AD52D5E1B2BEE637D9827851C419A4CB91DB57B2A6CB4433C1BD209648F1FE170ABB964B272BCF0A263CE28CFA3A9D1449CFFDF643E37AD97182F0031CB334A1EEAD23D63A5C2D0A675D0ED000F37FD2153E1AFC4AC01692701014927601203ED2B8A477CCEC45C1F43190E4FBAF2295E32A9383FC7915AA76950A301ABE47BFFAA9C294292126934CCFC173115A6CA96F3945FD5F924A5017125AD5AAC705106EB852EF3190A24420196ECD37F7C67B57162CBEB97DFA +pk = 1FB1FEB1D4F63AF9AE4003EEBC906B58D4238954FA98139927CFB5419A3115A8297684AAB279FB321B81C6FDC118323E0C128A1ECDA2FA10C8D9DAEDDF6172F4E9B1EF8B4A79E52D6D5B52111F99E58F83AF6478C5FCA35A407E51D252257CF87D2503F6C48F01AB754BB822F4222EB96980C3FB3BFE88946525A052E945F62410548ACE20A14382240AED23C452601ACF314731E10A07C4DD5BD3A8ED43C8A73BB2E637498B05FF975A28D7C4C40330A4E72C7F9FE469C8DA6F93337FC054AEEF1F90886DEAEE69BD3667DAD710FEF17196C1BA937C33BEEAE5497728949479DB733D3C2DFB41C192FDA2B082488709D2548B1C9C38EDA82AC00AE163107C239ECB88C114E4477E24A20580D0F14A3A110537FEF321B879109C4032E8F39928E47C23BBDE685CE590CA9E22562CC6F8A13F26842A8035F0D9E8E8806FBF7A91DB9BFD4948C1D8BA58425467AA8BF95D483D11914B0AD7A59BD7AD2B71E7645B3918D9475697295E743A5E1B6071CF845BF00F3422CDB560AA86CBCE71C56118194F8BAF13675D1782778A03C82FF3F280660743550CDA0334DB8836DC1CB79490479F736A91B1D3590B7DAA64A17F329DB6EAFD0527998B64E86CC77B7BB860D81477C511296B01D69FCE6DBE22F9BB11AFED0C831EE9F608C8E8B683D4371D2C87A063F2BBAC116A821CA1CE444BB79B697B10D08923DB6B0A10A1AADFD5BDBDDEB27A2C275FB3B46F33626C7DDD77AE6EA5EEF47D82EA6A31FAF1CC4BBD9075106D4108231F5872F86B6E6A323F6CB712C2AEE0396A54DFFA11EA4283300CC899B49B1EFE667C59B4F92F7245868915238906FFDE2FBF08A0AC5882D78D62BEF40C97DD9671E5CF91D3E1DC5001B77DEA61FB26066C62643C46855ED615A1C361A2624CC001CAE384D845C49C2F29F04451E7149B5B8B995B04827B7D093719EA0549C8D4D3CBCD663B714964C8EB1336B817AEAAAB7F5AA19F4AD3896E73FF78E2D1CDC386094A72ECF1E6F786AEDB653E56F31519E300ACD59FA56B294717B18A45A60F0F36863886F4CABB5CB39478378BE0593F1E73F7A485E84D06283D3462B898DDAF29C69B82759675D1A5F5DEA59451C17D755D137F3B34E22EB589C973467774417F525F6EE038EA89CE2BAFF77D22C49B17B8C2260ABB118DC5CCFD34BF2C51E979D89B09114989A3F8311C58EC39971D488016FF6991F9E151A6DD085BB3FB79A03B2D48ED25CEEED9E94AEED94FF7E9F37204798C2DD284F7CEB543BD3F4BC8EA5C8FE0598908814238A3F235D465B0CE0E24491FAB2584E4376BEA78A7A0F31DA5710BB1682A26921F266E28504C48639C00C4A4A9544BF169DB83110CE389D02BEC3D0BD1B80C9C93145BE9722F95674F6D506074F72855EC627A7361CFB3C94FC666A0C7A8DF499F0321B15DCA04E2DF53C498ED304A7CD8630760B22D6A58C5F421E72D8D21F3D62C7A9C6FEF1169E48A6493D87012AA1D7474D5E501F258EE981313C70F9DF9F55DF6C1D6751B127EF0036C588867490430946F148A4A4A9D66ECBA97C3B670A1255A1E2FD39897049AD120A115D9956A1DE9368CC98A8628733816895F207FCEA16FCB28BA50B35B7170EBB8D39D14EAE8136221AAB4551EE6160CB8CF866B16446A1F53C4CF6EACA93EAF28B6E8BF9839FE356C9C270267E1A7B8641EAE2D4018186C859AE45BF92E8B68B0B5BD02999BD0FD512A0C189906DA236D3A2522DD5D4B49DAFF701A2B61EE135A860822CCBEB188C36C31903A04D426CD3E74A52B8C5CE19263F7B5DAFAAF0FDF06CAEDE75F6224F136C24DB2C9EA08FC55D65B56E036098C014B57C8956A4C1D9A71C993DF939EEDDECD0E45325950D4357C582F10620AE8E9646EA72B6CA6D1FCCB787D8574732EFB00E0403B0B6D619E2EDCF1C45C29C072D92186206C91C7EB398990B1025036ECD6B253C338E611A97D655E49BE7A7A1DCAEA3A2C08A59C618EF7E6B15B501D73DBEF8A452773C923B9CD9B90565CF48C1B84B5D40338A58BE1C711209E69EE9665106AC8F25BF38842C06C20E329815D5E2B29DBC15A79846FD81C3B84F63CA2758A58AC7C8F22C603A14FD7964DF3D0BDD437445E46C07A8C93EF4BA71650A940D5110BE09BC6061F175B333CF762B6A98956B6E7C342C8251F051A10B383320B9662D9FAF568ABA9B2A64C966891F1030E8A73DE329EFF1070EE6B892CD24C5CAEE7993573F20E3D42D6C518B9BE688FE8574EDB79E92E8016890404435A48F2877FF988DA13D1ACE88AD9F89BD3C75255B5BD67438DB507BFC79078565753994B6BFE944D3BBF1E8DCD225D52435DF512FA97069C92968A99D54F6A185CD8F6B557D648E0BEC808EC5713EA32AF1EC702D13ACAD2D61DAB55C00E1B845A79C4C8BF269BBD6FD2D84190D60937CDCF7916ECFBEA9814E3F7ADBD3C1EB5CC73A9E2EF7D7238017D9AE7A1672B72B151B2E31AD2F97224FA6187DEDE908BCCC037B1B702FFAE4CDC9FFA424F74026D12F0AA05741ECC0158F8E2FEFAEFDD652D2F16D18614ECFE998C1AD42517276273E6BA3222CA8CA711A6061201DB160CE3DC983EBF09B77206ED3A4E52355686AEDDAD1DDA71CCD61A7896EF367C21301096ECB5400BEA3B8A7A1E5CDE4FD219E97F97BC23B9EBFACD46421829799632A09D208A30719889A69310996061C583545A037EE5D95F387CDC514D7FB75994C0A35527EFF0987943DC2530A18DBD67DADE2B2F580DC981640C98 +sk = 1FB1FEB1D4F63AF9AE4003EEBC906B58D4238954FA98139927CFB5419A3115A85A08C93F3D3CAF930FC3C84A3E3907F727894E6CB0311888FB4C28A80A4361FE3B0DE7568B6117F6660A1BC34C05707D5414022EA72F3DEDD049F7DEADAAC269DA304A5B7E785BE43721D7A83F832E67BF1F780422C5BB6AB5FC01B4E500F72081835202818258015204153674424344202424027707228000568627204870110840583507811345158505741302766820384837270374503518577276582404826475448668783118788545711857818288083838558172186133367822366252533207373263452020044330142548004732614557316137642857826776108420577683827227325547302354256020574065874545265518136208253500462015618405353256475107337856756841547738142407701113431042543215373310724563364388274546577002870264450545123647387521204470237138720411376052211828058276366271770602273400584386173106353068468223573643456070172582306607335333806246772688665511850647332016003650252881348142772661023211668871000351784481073017141463018602644306521564865245168034353571075806573141133744185461044238225251526522367886655345247701005853870307165721842352611171228424313082816581145031547841153411324718027222543063384057774237428758244065414234300158616264840648406173733441548608108704232132475754232787365562562652182602331558142058176326541211500030682488612124581765118005658134070224106268448857235470277821456477215856841166047866882328632247577457267154507844126125587354688356101007233286114320061437700154777647480156876216372118876435083817588485086018367786441887526824875203582213351554860424048072871653227688032225157668155234710484162007506514504035022048401410657626758671826764623286415805060877135433081073132047284701845211802153202888441067634828516427330681406046782702673361405388442577667804013235157043660763188368585767206638050681861273148603725666361408877603556273065738472617314874538121573645337351183274111030628270777371843886006102886137583721653540871078614040614632160012406632686736581538381107785514347476338732116578560354731064503033037418382575340657048756264834344433521577648151722342023832047368661612413827802683633541610568654322020205162752880202046086176700785165443383511028343268038716856627123680477875717853115501607361058538758575627616601315243610102357666107341670873010123073070064432568013523653518363415353438283065703867631855714705124085008060380611026207038775764568535017883664720410026777310368748102446887104143324862588076228300217374481361302723062078214638014107647442726340133201260304660200280141384862772268850260566806487080710000636652161664664535551665580153054781815366867448350585358815185822252637081588366350214516863265455554237251363112262482426063044767838486218731007723785152276087282026323154028087623628550740104285374078657211242183701827650527440474210562081004872514671343534507643212216434746107004640855084816183353055700358113717626814015735878483620158213855100526667207075153502443111168484452727452135551724252152741458108535857165047804576066428302433511586067757232755445867537051522802641146570618708864628535286552882105855637254487358610078302341138234421871762875126015350416875802377776351263571888701414565376365BAC6B8D7F69E228E12B7C8398E0C96A3DDB207C0AF70BC4BCC88125A341C288CB79DF3AFB02B54282B420BB0D4D6906A937313CE9000134AA68308E97672B9D5EBB54B96E08ABD5163D1BCD0923BAFB3E07F283C50DE0735682571D593423FFAF38651A51F9E7A0BDEF682876265A6EDF77737D14889DD336E871CDFDDFC9537BA60DBB700B66888709F1A582B3C32903D458F5912AC04B7ABF218130AE9F88CA8DFAE535B79D56B46DF574C208636B4859338F2A0EB8448C995C0F48139713BB882F0F48B62407F9C831AFCDD7BD8701F589708F7C0A906A96989889763E9D86B52F4EECB1C5396804088E96B968E247895AA4CA3C035A782C60B9FB81D8C7C425A10B45A0FC49E059E0CCF5EC32C3515F79810EE4DAB580DCE629DDBFBFA1E7E089479507001A72C934C750C8FDA560503263B56B10D83AD0C3626AB1513685F8DFFD4860F4312F6C001B91C9263074F51B792CDA2A0A2475EAC1B67F93DA96DF6E14EAEACA7856D51ACDF467C30BF830D5A5499FBA8428ACD0A0B8E76BA09DF9A6FABC8C4DF3AAEDC887EA662BF5D22180C24922D57D78BC2851987BC7920BC389780663F2B2A2F275D7AB418B7990A1753F2910A18313C06C9006F7B2A558AA7DAA61A1AA580C9DCAA2D76D38DC409FA6DD82D4B257E2D9BB63B6B44DFCFBE397F0829DC592273FDBDDABFCB43BC51F68349431BBD53CC31A0C236E5E2521AE1278EEBEE901DBBDB8C58B03E21BDB0BEB33D03D0E6F8A629CEC477CD7AEF0F7A71FB3D94AA063B2827548B0249DACD7F45BFB230A961EEC1300E778676ABA2722AC6C8377C4B7F2BF3B9B7AF8EBF288602D723692D052042DFC6392DA4C21D2C37187E670B436CA5EECB3084832DC496FDAE4D1EEECA52B6DA45987E9EFA57FA51E5F81DD0B91EC0E00D518C4372237A6F5CC93780E2EC0DF2CD1312CBAE901783CA5369E356E7A272794AA273B6C62DA07FC188088325117F4F40E545266B73BF044E843135E014A6FD5FCF130E17328B377F5DDD8D77CC82B0D7DE7BD408639231A667C7AAE91A0810B9C96B9B66DA0A9B98AE1826CC5503B19F4294C4D3228C0C11C29BB207C21DF02946DB9834E958C229B7A0D0E45B3AC4C83F65BC87878A4A18526758AC676C9DCC972D4BFA537D6B5E018C27A0B48A3D6FA8DEBE21E40D06A53975A354127EE00DC1215F6825F11C77604EC8C3FF0074CA5161810AEF401EC64EDE174D12E5B9E69659462C06246BFFD813404E89DBFE2C6677FA0628EBAC45DF22201C5CCFBD069E5DE5F75A8CE43C932123517926C869144AAAA64F7B65D43B5548FC612A2D3C8CF6F48D8D7EB6E239023003ED212B278D5A6619A2276A7E0EC337666E26C9E96009D28765669001954520765BBE9AAB856488557777D10261F9E714AED314FC36E41A9FC259C29F8F6D45CABB21236C526A308D8247F76BCE3CAD8EE78FCD30E63F95DC06C5A5D37658CC1BD03152E3573AFC754ECA1E69D4EA783F36FF8EA5E6930CC2BE5C02C76287C0A68051B67608458FE4E8DF2303D102989770D2D0A3684337185D5FEEF31A2EFC9713CC2887E792B577F19667082F2C2B1D2823E790374C950CDB674828839CC33B5CE4512E931DC3C6DB1E512C583CF25C7019F100CD5D48E38EEBBBCF9DB16B874171C0B43FDB134AC56BE39924D6EFCD125658A62B6BC66C4F81B7888FFBD29ED3DC84B20DEE4E5F854891D443011562A41235A320301489B755F1C8EC46991816036F038AC1E36F2AA6A6AFE4966BE8C14CA2E5B7A3033B2259B61BBDE12DB9732F18FA64225C046170C18DF76CC832F8DB7F41864BF881358DFB2BC713BF51CD49B7EA5118E05C42326C3883A24C438A26F220F751677A690D9A6CFB52A4B407D8801A6408A69C11417378185D613563AF84C3D714202AC16693315819B489707BD10BE62CAAA425D267BDA2F899D3E2D5D33C74918EA53E5B0B58B69F5CCB0AC3DB43D3417C2C23ED0697C906E4EAB8FC75D00CF9660C51D02BFADBB6291110FDBB28974ABB44F907932F364C93116DDA9833CFA2225872195D922331EDF5EBC247AA7BD4F55503BD438D523097454A1015FEB6D1BDBAFD831BFAE96674CB34C2636206B39E75AB0E9231CB85FA60A51213E4EA9C75B8EF398EE33799A103CF8C923BA67936248217EF77C889A3D71BC83AA812F0E9532E65222A7E4141119C4C57EFC17BBFE816F3A78E277255A72379331366E1C062F1E43894159EB198DE3E6097A9723E95D33177E5E49D892F71B3758BCF1671F4A8731FEBEB76D49626F2B69BC96BCD110A14F2C83B780F9FA3FD438E595AD84888FF612E2EFE9F0C5288207F37019EC406DCCE15872613C822FCC61503FB2076BCD164464CE99C3E55823DBFD0F5B3A83B7890F35B906ED19D855F24606DE806E3401D6BAF0A53F19526654319ADE93946637384DD07FC93D6DB382BAE0F3D8E59916B08D58DD72B0420CB46EEEA09180AE4571CCB5D4BA4236479B76C4FC4312602693A7A7E1008C12F001195EA51BE5DA66713A0EDC99F85523D3EEE126BC897DE689A4DE504F1774BAAA546C1BB5D002080E5A98FC7AED0A174A8A819CFA92364A0D160C879B2D8EBB1F8C226AF0CE9AA55DFAA425AE5156CA684106FE16F25DAB7DB67139E6D52DB9EC55AF9B552EF7F4AC2564C33D640A3F2150836C65AA0378B3C816636159536E47EAE6D27E8A2DCBF820ACC24330CDB7FC1DA8D7DB5AE6DE31C7265DD5B85F6F29F60E1B243CC4FD6B358DE114F2D11CE75BC0BD8BEEB057849EDFB2E72576E44FA894C62987D955562F19333C17354DD3155B9F55EB83DEB17FE764D5A0A7E93F6520AF56DD910C9152E6BEE72947920E3F3B301A2C7ED3F5B55A03D3468201179524074FCB1658BAFD67D5B0A9E358FD7BAB17EC8BA146D0B7AD6E4F5BC6EE3F00F56330032FDF47EDECB82D37F5F6D7DE5712FF9C9AB20501C570B0F54E149D6E963FB10EC51F907ED94B1AB092C7B262B5AB45BC1F67481B856C7C9086895C5CB1EE28C28778A50F15EB7CF3386CB44F3D913F5ED8FDB952F60E67326FC0A6F6D274CB9B6EEC01E782EBFA8B3481ED42B264F2400F9013C93C67FA08FB78112BBCF37F257506A1BF2D6ABC57447A2CF19C1DA20228DA8071FB8B388D5AE82B2A17DD2E9FA80C55F60B51152F940C5AF510C98735EFD8528FBA9C0322EDA21C80230ABC107921F2F2F546A46CC3AF499C6EAFC31378474DD66E460AEA407FDD3F418F1EDA5DCCB1A0D82D0CF9F9AF9CD13D46A9CE1502879168251144E1721BAD9A4244DB5F306FEAD42A3DF483BF897C7F46C86CA9AE118914BF88EA66C4FB00E833DA852EA3752F70D4FA9CC626F60F8B2BCE37AAD739214B3EAF73D261B2BA3BB02017A51BD8D701606EBE31FB62D7FFE9E1B3AC97CC5EAB5C39E45E97E524857B0642B8A7C32B91E0BCC0B294051271BFB0BFD7C57A9B763D29CE9D5DDBD1CCED582B46FAEF9AF98CE96692545798A082EA3B2CB203A562FCA36BC0A59F40667E6 +smlen = 5883 +sm = A515A8DAA48CB56BC4E92BA9A85DF5CE0779AA79CFB87AA5DDE6D291EDEA06D8C34CCEE78160BC7416AFB405F78F92BCB165DE8B9DCA003A51F24DD67742159E9CF3145BE2694045C4D89D16FCD3D506E5293E680A8B7DBE3611C7065F6787D054443E7DF212F10758E9769699A2E08305EC08D5BF662A30A30BA25114C4DDD67F7C8513C7CAAFD648BE40986B932A4FC5CC2D5EE439FA54343BCE3BDEBD343661939EC13B544C2140EBDDCFE355BAB5DC8ED3AA565F1475BE7862CB56FDD942ABF7428B1D26659E930232E06437BE6F27A00F594DCB29A6E1BBA01C93CB112D60B63D9591B3B5DF9E3B36E23AB2B8B2466FE5F617604BFBC3C1585C5BA0D3E4ABE80B753174FE3438AA5C0406F9479464AA97405617E8AA4C8BF923ECC991D025E976C02230E35E62728AC7912EDDBF5F145333171B9953CE995E0D6E6D8A92F1EF8D593B0416563BB409BC87C0E34E32D004E22D22E2A6606FCF23CC8218958E578B6876E3B4E05BC16A3E499F80973A7EAF672D841CE2CFA4FC9F41190FFACA5F37CFFD4882D3C9A372DE2FABFF5BAFBEF4237176CDAB855B02E43AF4D2FAC85AE628B9B94CFC1A87EB360622DE8EBA88AF2DE13759BF30E9993BCE3D65A35FCC35D036E9E9CCDF0A592186519E3608C5825DB6908E424483EED22D1C884BE6A0FBBCB51713AA57E5F948B9705F3EE33DC7C54882C20FEFC43E9865902AD6D42A40A8B3B6EAFAB36A684739B778FFC5DDFBE901F167A9F751C40AD8EB9371631A66EBCA5758409E8CD13E0997A0A496596F128074EA02D86745FCF0D7821CA596B37370785423B35C42003574758AA96BC87CB6F1D3FCA34C3B3FB3652BAFBF6A1011E6B0B721653A706CCD106F9BE4BB9AA647E1D88A38EB488D0BBDC5325C9C2B9FC600A6D14DB66A332BB35A00DC9AD182267A8E9F9E1CA172AE34EDC21154B2FB0B0FDB3D85A364BE0608B8760BE7A6133E89C67777316B7D8466BA222631E6A50AF75B0FC8C4DC601AA7393358E1FF5C6A842C35DDAD9F96CD075FB3B686FFA77033A1D6F401B3410C3A160130AD6372207A3EEB09D3DABED863FE3D103CDB540CBC8D38652304F07F29CE3F5CA593102A0A6F8541005D45AD9824795C1641DFC56555D0B86775118CDB17057333E049F8B69F3B57BCE386EBD881B7D2AD37030F17CCE4ACB7CEB8AB6D1063CCE717EBC0E74FC1F6FD6186541C2B9F27B9715EA6DD486B666F3279336E86ABABC6DA032C6FFB8D3A885E2558E5B5508365FEBED8524A0FF3B8F8E9067CACF676255BB978ED304872A943C30687A9819FDE8AB349C447EEBD9C6903E4869C90A8B6E38E89759C17B5A540E57F3E898C7B03C31F5F8EA0008AA785734B5AD391905DB3F570182221333F7FA63FE3A9BF8B037CF944ADBBADA7EF053FA5B856374AF4748D9533CF7E2937FCA66B72FF3ABAA9F7AD5465F6B39AD0477C468DE1B1652D050751DC797E3418BF9ACB33388782849A33388BB046A15CFCB7F5BC7584F50F0F518A7134727B94169B369BF7E5D0C821C8864B3C711310A3859506E4D0E4CB832EAD81AFFBEEAAD8F241094A34450FA576DEB2E3BF5F7C160C9E22A05A055C3036D37EA2EB59F45A1AECD1D8313B47993F3B4A2FA417611F832351E5B93AA9C444FB2756A008E6617124FD875CD313F8DCE6AA410973068B7B71CEB49B39B293342FE06906FC7F7959A3CFD0BF0873D8D6E4447FF80A98AE609E6D12D66D6A141778240C07F8C0C9A6956426ECF41529B2D4EC59928282CDDEED0EFC108728F3E96E34E0C5C4C037747879E6F36B1275412B5C0834C578AA1ED279C8A7C0D81B7EFF72BD87E826500434D46228756494A972746383D3CB06464A6A3C43777021DB0F558CEEFFC0ED0C70E345CE95306B1F866D4686419CD40FAD5C13BA2CA3797EAE41DB1CC32D4052021FDF1690EC6D74AF447A7BB7C9DAE438D1FE3C594AFA8798ACF62923D5E1AA2EE515885AC0F3D876FD29B0B5405C4D00D4AC9B4ECE7222D7BDD5EBBF78F101484FEFC5F46FEB8CD397165DBC3490F0510598D83AAD995715995743366000CBC5886B416BA4FE686E0978CB289A51F87F4723DA84F07E15B89F5A7C451A48753CB88AD71FFC92964BE88A361ECF58F9599D5FF8E6D065E4B730F17AEB15F7E55C86D8BAD1C97D1F2AB4B884CC8739E7B4D1E5224AD8B252853EE572D2C407EDDFE193D2D6DF2393492E992EEE7DA5AE2C42E2621574934685B9AB5197AEED0866D73506F9827300C99BB237B55A8B2AF7B085664C78DEDC9BB4189BD810B6046FCC0B110FF14F21EA9A80B2BB582A724C4FE8E2D3D65B7115C422EACF86192F676AF338D3341E41B1451C899BD7244371F09F738A4557BA076A67F8B3D086877D0B40A18077C8BB16CBA59214ED433E418F8A5168F9BB8CFADE8CAA170CBF900EA978831FE15FE18A230188990B31A2AC30D9882368E81C10D9BAD687CFAEDBD205D5276F2EC4268BCE77703A30CF0A1A477FC737891D4005042B2BBBFC1DB99440BFE347CBF6EFD0647DC51E386D9610B8C3BD47289A7601EDFBCF803CCD19147F604C8DE5D32887C0CB516EA3A4F13755C0D1E5A48172585571AE328FD0F6445F795BC5C69DFE04E0F153242D94B911E7D5EA56C2387006A61D806E9309180FBA8F614E5259C91ADA55689CC177A14453F3415A4F74336BC6AAF3E4A5CD15029BCE7883431B1A499E50B98CC83E2759EA06BAC01ADB2D6DCF1CFCB640B62D3EBAB6BFFB48B35B90B6B13E413DDFAE0924EEE5E306E610043E91A13C57BA28ACDED63DB37FCAA7D3AE025A38855E8DDBC6545E7AA926B94D6CE332D4BA165922A5AD3B8D9B04B46E55A1BD5D4B4B004BD475D58888230D901CFD323492941CA0803579C4DCD6525F9CE30FF2DB406E8492B06919EFC8B63275FE587DB555B2E5B5D23B644D93ECAC3C53039ACA9A37CF111B9DE5661B15F728B1BB4BE0B49F9E7C25D36C97B022198B56B721843D4F62FA9934244E7B72D8CC050E55F3B09D9E9FB38CEC444226A160FF39C7A70CF4155A5C62EF28ED1A02880B7AA381A26A716FA6E95E59AC18BCA92E3266E8FB07480B6B1B1162E4E87B400FB4C003963D345754CEED55A048D1CF4289D98DB4893BB1059FE8861429B98C309BA6D696A38EFAE4159FDC87A39E907D76BC9471CAE7E0F9FE9FF0715DB0FCC163069D2FBCE78BE7FFFBC5CDD296911810B9726A4F4E7D1DE0BF3DDC06C78E1D90DA8EFC682146F7B4B41A0EC8E42B3E2D0B1765A5704684C2626B8E4325233E2FCEF779ABCFDFE10F97BAB2F93F763DBACABC13860409518789EC38681DCF736BBAE87D72D2A4A88E2AA6C1E45CD27CD54075759FD071C04DF7B03E6F96E850F1AE497638BF27CD0E88E3EF3D266CB33E0F94166122D591EF61B0F3E4EA3A9A7758CB8D90384867E3A51A47B0DEBCE6846B36B2C052C67945B00F2E0A6B715DFE71B120AAAFFF2828400D848E7E22766D2959D5D165A01D2B9DE0A185B07D18FAD9E847E70102A37FF2B496F569876749A6B2934BEEE1D1230590D2E03C764EC606D79F20F9B381459167E82E363012D333CA2303E08ED6FB32965FA92CDED3FE87C4CA6D1D48BA5E82B95B2A1411DC3CB07275B812815B455D59D25847B08505A50E9728B844A58D9C92A33A1C2C168CC3FEEA63BE7AA6043AF794259BAC4689E383E2A67845E49F882DD6D5DDFD17F6C6D2F79169A4A66643A3C366EC4C22E576AA517707BE6B6A841B46C02BE6FC5ED20E721A8BC2EF3BB0C87D53C710682CE34F2A2E770DAE3B54A338464F29E1297A1C5065D96AF3D09664CAEAA5AF67B3FB4BBBABDB22C8DCBDFDC042D287EC8C161E69E6E751B33F47016C377C823628512144D2F39F68D8CCCD9347B729170C359F841565CAF1E3DCDB7C2D8C17819A20666D54284E20EF08AF16115FECC33E272226BDC230F3A7F2A4271055FCD97BFD50E743261C077D41E350E9351B75FCB6CE6515DB83078D1E8794BDF08435F470E4E74856E61FBE376A3BBF500B0B6CD7B76BC2CAC7B2AF368CD9332572B62ED564D8BE5C9F747DB7D6B50816A0E776DB690DC1FFE44BF55AC3C6989C33FE0CF254D4DFE2386CAD6C906397CB1EA0B79D21205F15CB421B7230BA14DBB314D2992AB7EF6ED1D218D9833117A3750BDAC878CF9F5D3EC6CD6E201ECDF6B51D2B10B099CB1540E8FCDA08D53C38C0824EC054D31A5F8F5144033E144DE4042B55287B00A54CD97CFC5A21DB7488D1976428DFDE2681084AC6BF4B7C0D39D05DDCF71483858464340538C561CBD03D87CF529548D30BB92B1AC616672052BA0D2836E0A7E673097ACA49006C7E4FEFDF3FD44BD096CEED17E4DFFBC46630F28FFBF848089A940047065B9B36D0ADD6EAA229A2CC91B6FC616B4EB1BADBD1984FB143E753BAB88C2B025636909DFA385EC96820D8892715FEF5EB3BD66AC4529D71D9949F71CBD2926247A3DA4600085B8B5BD3BEC3A1AEDD77ADA0AA2394AF86DDD61E3381FD4B905B934363740D0613BF56A4F98F98DDD47A56054307B98DEBAEB3D251C16C34755373BB85D27C751C6AFD824CEB94F8649A819AACE5F656B9E21138394A6FACF21D6D7A7F89B3C5CEDEED2B7678FE46707375CED8FB0000000000000000000000000000000000000005080F191D2434FCF4626248B979A7A8D306CB9ED69C4CCB5CC3729D2692E0BA679D5C2FEAAC54A4E06D4EFCEDF78E19357DAE263E1B5D107FB09618A9C34F54F19A738A66B95E6F88E20E01F879F53E8F4C371B571E1438FF70E0A8CD00D608976E24501B2DDD323EFE6C1302A318CAD821C6FFE641672BB80AC62286C69FCFFD93422911C46D43DC9A1F00A73E19EBE6CC09A9801F2A1DA708F0F1F98E7F1A18529010823230279F487911CEF1E784A229D9E311BCE5E2D368E6D613F791DDD617D0F37F604B786CA2BAB754E8BC4BD3DA37E66A54DF1D3B268A5A80379A30A52B1532E8CFABE24168D83CBFD61E2346F901C361F771E0BE3E03DAE8CC30614C10FB8DCCDCAA5B9A25DDD8D61E61F60F22308E12ADC137D3D8C53CF7B31984CB813758BAA19AC178F2F0CD2155ED674A7509A3CFA7FF66D2D9B1E60BE50FE7FB79591C500F66BB1D35EDB80263F4B696A3DDA0B9B2911D01E76E9070D99DB93D1D0C3874CFFA776BA24424A6B453526F7C44EAFABE13C0750F9DF33E82105930139E70B5CF1B09DC3913D6BF4A4859F67FE814FF038F0FDAB93522A35E7F81002A395989D68B8B7E4235A09837CC6402A5338DA08E7C73DC63C43BAC42054C694F4931B80140D6B104EDEC995CEBCC5629F85D09DED8257626F9FA4079ADEF81D044C18BF2277DAAA41931B62A6028F89F95F06D8A8FDEB95EB2EB1E90C0D8523E0B476B158E3040F212390AB2503021E8D6FC0733B963CC6188FB2532829925B59C8255D89F10B657053D0FA1D8E76C84826A4609284503D3A101EBFE7AF93EDC423EF5303CD946C8B570511E38EB04BEE0060E678D03E4134F84F279A570AAD0332417FB2099E3F1F279CE7D6DDB080C5D83064D107BB560B21183AE165CBB54CC75313DE72D40D1CF5173455AA55C5C356D7C40A2A7023DD95D3F89B515D7598F800DCB7BF68B707978ECAF55B794A17559BD1E913F4472B1830783BBBAB5F23A760C78C46157FD1B429C445494CDF92FEC8BF9FC217D3CE2697BB6C671BAA793CD0C1C84F579F0DAEC400BEADA799A9F417FE4744145F21C6F8559AFA7A514A0E951F03E5E68C17A8E5816F3FCF41774D26BE2EDC11FC3A42CFCF00F817C3D0FBF474FD7F30C9C3C6BE7F74FCC79FA6AB07CAB037EEA7D83866673A74C087B5F7542804071D53CE348D2E836749E35AF0FB884D5D53ABB195AE1EE6E9AE35DC91BE359BCD510A7801FC243C07DEE92373918AA4F8A89EDA3895A52456F7244D1FF007CC7B1A52CBEF4C1ADE1C2C0AC189AB24B3F260475E1D08E7C5BFA30A1CDD71DE5ACE80D5FBD1D0F17198B79C8EEA0365D139F2AE73CAB6FBC9A79786896DE0CE7FC747D68FA4ABAB662A09E0E409F7E652153352BB92F5DA1836B0E92B0B644C821B2DD2BD0AF193AC0F8CF5B8D88432F0248DAB09B46FBEF2EF1899B5981E9B33DE4E9927AE50890FEFC35F681E075D8B0169A2E16FEDA6392AB9858DB87ED18ACBA25575AFD1FEDA9FB3FD01ECAC13C245DF6972F65087513F505187C4E8EA54B6433FA092B6CD3AF13F4718693904435C55D273060FBB5FDA76074691269493E86F287922D074E54EFF04209B2FDD3417D8436D1395E638D57DB75D68F4F819141B6DAF4D13A9A18629CF5F84B0CD02E7A397715DDE5476BDC467218D11AACD6CE399D9D54645BB27CA43076B7E4E57FB4F7C4F4B8D0AA949719D731C3A927FDEF1533D773CF1BB562D5EA43817A5ACEFE9EB7E51029DEA143E8A1D5F76F9BFD74A26C6D38F54194319A1AAABC4DAF45EFBAE770B9E9D834C09FE45C15D4BBC0251D3DF2F2F23387DCABCE6CA7A59625E18FD997770D164C338D0692AF97C749FB746C0D3944CA4B2DA6D3AD7B8C3AA922FC029CF9AC5580CFEAFF50CB2E9044211EA522BB5769BEB7A7BBA0743F345FEEA9AA9DA6EC5F0579CF7A5AA4DEDC832FE3F65185A31FD49C0D259E3B7F8FA96E110D130F588CDEC30D0FD4860CA6673C46D961FC68A4020FB03AE24B1AE12967EC1ED19ABEC0808A7EF89521152033F70F406A7005819D28DFC556C79DE18584088F40BE40A555EAEFA78E3FA3D9360A7CEBD963555CF208DC408A07CCC1369F98BD840F5C940721064E6C7CB241ED0697AF0FACF36F05632A504870ABF90134A01AF00D340F7A5D548A8078C2049600EE454D15EB8CE58C26B3C8185CF9DFCDCA7D4B6DCDEB82230F993D51E701D8387B06BD45B4B61DC9DA6D3B4356F50C1D4AD2B467D36AC092442FA90D1DEB014475AC7CE90C974063459DC951DECFA30D2DE4C70FBA39A8B6931217D0924FFA783C8C3DAF048908E4AAEAAA3B7C98846278AFDD1753252F39CAED7D334D8575CE3ECFB2EDEC31AFEB2BBE67FA929A267376293C2B2F295CD8DBD66106E1D9518BE1798949F3315E0454D018C2B706FE836FB37AB908D9D698AF495BD285A74E4CFC7612D42121F43FDAA7DCF44DA82897B820514D66B92983A3EC819D2CE208D688B6F0AACADC0CDD619D815CD231AD8DD9B6DBAD9C47E16FAC098D0F4279AB52055D2FF765AF6E3618C4509FAE6AB00FA23980EFB19A26E0A6EA4C9A7DC699121388748449C429B28AD2779F5642F05FF58B68BA3E289F90EB27CE06392616C080D659338CAF274D46A90D58F2BFED25E8D4A8C62030A5E89F6B1A5F6112A38661E2F2B5A37BCBF050812DCDCE9C0A939ADF929C921E7DA0C30815DA318EB2F350F286441CC92060C970077623EEE68B8C6FEC9FFFE780A6FC85FD7AF90172951337AF57339E98049132A4CF58874A7418FB7ABA0628B6192BB2C43102EE6B1D7E824725D9C75D34A8B69DF4A6BCB1F96B57767046C99EC6352751E2FE1075BB4092672379B3518DDC884FEAD5BD062B0336EA88BCBE0D22E066566347FEB617A322BEC561E9AA9D2177EEF0DFEEAF6231AD56D0CD9E300709C9317B3D334D8D2AC97F96CF2F45B8582C4128D95DA8CA207AE34D3DAACCDB128C11694EEE6D3E8E6AB767B6886B1F7235D85A4D9C7C831C5DB8AD8323F63927A638E19497CFB308285A03CA2C1FE2AC4D919AD11511ECC6F28E7D0E0A614FE21B57BCCDF83535C7E2C40840BA0014247190C580378454751EB3F2361D7193E160B9516F7EE1D683B336B873C8BA22E97480A61F002A73844C78309C0A3B31BE30A192A62BDCC3D33A7A5BA1F6AE0404A8558740CAE46E5FD15971B41C0BC39665A9B92EEB3328C328B073ED5B3720D37A1C097AF8A6FDDC3B2B067680E6CAA760368B0E1C052E804E9F80F26B52596202FF2E0AF7215999EAF7D3EE3E8916744E40AA1154322DD068AA15960DC38671A4F5889FBE709CE1DECCFA80B9D33AD2FD963FE0581A2ED7718A27CA62819D05BAA3212EC7CC1C5472BCF579AD52D5E1B2BEE637D9827851C419A4CB91DB57B2A6CB4433C1BD209648F1FE170ABB964B272BCF0A263CE28CFA3A9D1449CFFDF643E37AD97182F0031CB334A1EEAD23D63A5C2D0A675D0ED000F37FD2153E1AFC4AC01692701014927601203ED2B8A477CCEC45C1F43190E4FBAF2295E32A9383FC7915AA76950A301ABE47BFFAA9C294292126934CCFC173115A6CA96F3945FD5F924A5017125AD5AAC705106EB852EF3190A24420196ECD37F7C67B57162CBEB97DFA + +count = 78 +seed = A315BCF0E6835892ADFA07C034BFCD39F80B62925A95490B20170BD29378E11559C7F1CD296377FF1E01284EC727FFCD +mlen = 2607 +msg = 96AD5FAEF409B8A4C21ACB1ACB596BADF387D26656BE3EB17987AF59737E324B7BF8412A306B0E706AEF73D79AF753D9B0064BA9CED8DCEA966543FE748E2611709ECD1CE6E4DD8FA812D485E91809A225936675369574B0D104A258E3353EE0E021683615CA5C7C531FB29A5025CC7F7323860443DC19C9858F741EB9D24A9F6F04FC839B67153214116E8B7FA982F338445830F915F7C85C88C23BA2A3CE8E2020A9D8DD7B18EFE95563E3924D2A341826AF51A8584CD026B1C433EF0221145BA8BDC8F73A467B33A9EB3E8CD2A4D671C17D7C28AAA539D1C5BF2F4138639AFB89CE791DAF0EF0281D52598F4C13D210974CFA1F099A0FC70B1DC120E5C00C33A2BD360BED57CCE069060D6380BE2204852D8BCFFF4918BA0B70B0BD1E1D55DC1D68DB1D20AE713B0093EAEFA1E33D40D9BD95CFF17568393E9BBF5CC1287325D2668F65DFCF44ACE2F6C6CEBB62F1433E69CD19E6C6532EA93682B22C4C4A62C6ABCFAED08EE64F32723E56205222E4AE0831AB8FCA8C265FEA0CFC66AAB1E367201752AEC11F752B963792C071E42A8A1AB80658A0C6960147ED740CD07F307CF6A644A98E1D2E56C625ACF458D0BDF6216A4F1B9C78EC3F14850C803A4207C894E61A8AA88840A27F2B439FA7CBAABBC789102A95323E06E2C324859DB92C6CEAEFDCA389F677082180FE3D6202FF60DAB9F87E3B84841C0A4EB5974D893333F7F1513E54EA4AE0731EC409F69B77089FAFB121300042880EA59B7927E9435EABFDCC1019A96E145D5D157998D620E7BC6945DBD6CD78E94C2D89589F8DC8A01CF1B295A26B091847F034937F764ADFD811F52B3AA187F3F49273EAE5949FF34B64BC86FF11EEFE378825D526509483E7191B33333E5465FFB025B269F898CE1F83EA549F1864B556C729F510118921B69594F67B8C229236AD3AEE55BD7082E027B5D342C976A549E01618288944DE0B2C77473A25201B61034B334968178AFAB7F8CD1FEB6A25CF8DCE3586FFAAA861471E2EE7F0C22538FB3C95D2145965C4673E6489764AE24B4F048DED77FE3487AE175F6D4898F69F9FFF276470A93DAF986A75F685919D98C9C609C795D4785AE941C782B551EF382F47209AADEA19066AE5D3EBA7BBD99E91943F1E62754A42FFC8048F7B87F128CCF6C96BD760B45F07F740E94491874B06CC3450AAF55BC664B407C57369CABD2708A9C478DFF64D292D96AB71EB997F8B71CDD6BA02F52C5035EC26E8111EBF8268CB00DF9ECD63BC0D557E2D2E77A6363B00DAF25237E77DAD03F929E5E9B39447A70D4E5F4B90958F312C80D594E1B1F3D0D23F2B0D9753BF3544061CF0C0F841C440319E74F9B9D15B91EBA1E680ED6AAB7D63A97B48C0A4AAF314E8E77E2EA6BE9DCFC7B5557FEC1B996A37C86CF6941325EC356EE75671726BCED7D2157BE8D4C62CF4BD0420BAF2C4223597C0EF75F7A7C9533D14BE0D21C37F06FAA53ED5EE0DDB025862417F98D2F188895395CF2FE72185ACBEA952F55CAD7EC2D684A5AB94B1257D7ABB565B8C07B88C6335FFB9D2FC6F6779CC24FC3CDF92BB3B12EC54360A7CF3579632A2A65C518E57015DF1C616C857F83F5F1AAFF693ACFF210DD1E95CE04CCA9A0BF385ED6EA2AED894E79D5133799393469B666209371E708D4D279E1AC5ACE28985D0DB2765D547C2902B715BAED5A4FA3E7AA42645F3BBE1E9F3CDB87B1DD8DBB5AAB08626591921CB49E552F8EBAFCBCF428470719AE40B9CA847F31848F39E4D42049C5D40B0BFF036E5409A6A12E7924148E60B64BB83386079B54486FFC8187302893B8BF826578D9CA03A1291983F21DE7F6E65458F8942DC1B135C6C8C1FEF4F3863A58DB17112419590AE57B9425592FF22E596191E5BA7C513EC315EC3476C95A149F6A5EC1CF24870400FDF46217A23F42E0B61157C3CEE23E7916B4475A94B96B917C171B1A34DB13AD98833E457343F94A76EE226FA5B9F3066C2FD69F14D3AAED1B31F5114780442EBBC88D0DE5F689CD910E7464D73423B9D4E03718C5C51871250D11E27E28DF1268166E3AF328A80D9D335F2D27D2E91DC61CDDC7F733E345D56C11B6130875D93D527F93542FB352407185E7AC07051AF7F642E34FA06B1376BA15A35D837C1BFE090BA67A89FC1E307DFF3F02A988ECD48FD229733F641F2609EC8DB14B1A5AC170B104F03C2509D2EE6844C716766D06A6A25D957530FD68A8DE6F1753F83EC19EA2DEB1A4F9C7986F20FF60A7508DED6547A85BABA70577062E8144BA0496777A5218595E021937FEBAD4BFDECAC29E3FFF2EFE7D598FCB86F93A734E4C573E1496A6282A3B40E817DD3C9D631939AAB350ADC703899EE3BCB1B5EAF6EA8420DD6EB2D4F64A1818AAFA97B73C75610B6005F1EDC1EC7D8F8DB1E5D3E9666C1292515105037D26F2C8D83FEE1F4EF5DEEB287CD7C1E11960218C1B8BB50453488BAB019435065AEDFECD8D218BD1E751FE736442E8D09CE7176A71C06415A30B070693A68BDAA5CDF62351AE665F37FEFDA9481E62EC181ED24F0D0649AD01C89AC422F1B7E27895E55DCC2FD817346D361FA559094B37894C0B478C68A1D7564D089D9D4417D5C7372A33BA475A81FC129F3259C5407BC7435825B415782CC84D85E69D9B44B32D78FA255A895CFD55319DAE677FF89D93A3884CE9401775563FF1788CF3AC11CF96DAA199E7F4579A0264378A323FDA64FAD2349C09465FB23BA09069C7FBC79E7288A82F9165268F6842E0AFF0E250C21BBAEEFB4347D4EF1CD51161DFD29BFAFFBEDF71DEC93F4157A5C18995379ADE8D15DB59EC4A8B308C2EADE1B7DDAB55CE2220F3B3AE8CBA7C8211CCCB3846A225B438F4B37DF54363A987C5C4E6B9D20EC3C0096317D11F982184B75D8EFFD168B7B41317D40F903A23A2649999DB36CAAE31BA5D91998A684D30AAADBD3B1EC154BB6C92513BFC0C47C673254F42B1FA36B995CB737668CBDC2A0D1BA838E74E0E50B22FC22DD048F48B6D1E89E1CCCE5A226F63AC7B8E6E9E8CE27050BF3DCD7D0F35F47BBEC1CAABD4D619CD77302AB4FF6F56DFBE9F5821AFF2D72EE6A628DAAAE4440EDCC070473BDAA54CCD775331AC2812FC5B9884915DA582EB36F85C7923F06D961594753802EFC5883CA484FC64FACE42DE6C3105E23CB90663A3B381D0C6A7265B740BFF0A1A017058F06E39A74BB07B63F883CF914FE675E7E5AD5AD44C9F90DDBE23A125D9BE02264EDC13972FF22BA48ECE8890A223EC13ADDBE055A8B4E03882677FC0D94C9053DA6CED34E132FD83810A793350446D60AE5DD0D174B534A3B6F5BC1B497F9406B5CDD414401B6DD881CEABAB12CC51425E88A81BD9E14BDA18273583CCE0849AA48DBA1CFC49CDF29242C73C99C87F063B8B739AA787570459C098405DCCEF78D6D97C21545F2959DF9CD62F9C38AD9A849507C23A51714565642DD76C9103154327985F7DCC701B795A7AF8625F06367ADC11A7FD7B6ABBDA5B2FF6A825DD43B64A48EDE4EFF8603A82159A6011F9E626171E4593C0E963595A6E068AD05FEB12378C71AE515A82C293EB7D2B01B333CBC7991B44685AA7513B3A58342BA5D094B773E6A27F8582F3DABF54DEF59974CB8A2499369B5B64C7AC08D32D75FE37371C578073DC83B82A828DFC325976FF282D3F6 +pk = 9C8D58F80F7E14FB50E5ECFBFBA742F1E29FD7DA1040CB12E07F2EC235E6D92EFA44DCA4468821E4661E5479A1ACC3085ECBBD8991B8BF97D97FF4F479F6737CEA768803B8EEF254633BF29BAD8D6F4E7C48E561FDCF1EC5A70682E60072587DF8669E6A79AD0FBBE80E291CCBD7CE1A7BE93A156E24B93001241FCD05ED7AF964ECEF00C1AAB1E7246A7F5931D70906862895B558B1A91A37479F61C0BF35C233F02C9470E9F818808DA9951A5FED4FB9B490FCA5775E3B4994FD9987EC09CA315D4C8929EBAF19AB09FFD3A206272273089F4E6E345BF8E7C1B9CD1CB61425AAF9BFAFC6D6C2894C4DDFFB5FADFFF4ED92B999FAFB8C6C9FF671366CCDFF28C159EDB2535CEFA2A411B59371FB158C4D1E1D71ABCB5529CDA05E8F19CD1EF43AE47EE210C2076488F9A70B74E5EF7491D70AB12AA9F234DBD16566E92561A45E616A11E699E33397A4B5E9EE97B6A136D4F0E8FC4D6E0607DDEE81BFD8F9F9F9E639790BB217200CE35EE9376176D80AED85E90C21C6F0636318D12AD628C94F9B08B8285948E87A3C86639A5DC72BDB9989D743533048CB5B3CEB17D91597B3494FA208BE67211350316F53407C983EFC8E9469E7D6D175E449403FD94A3F3C1A5A3D8CC48501F3A4D6D0C57D011A5B40BD7A50920EE425B02FD54253B48BE3ADFD8DDDB9C9E73A028BD379A432590A044E3F0014DD8D9D3E006DA5511F46CAC4611E1AB279BC0F32A180FEC15D9C7A82EF9A135DE9891011DF7D4CA3A05074CC753EB47FB345D1C145343FC16CB687B80D09E061660E9747FA50CBA4AEA1D1EED1C3E4C149CEBF03812DCB5052F2EEF1DD6D071342D2C80A7656B5628BEECDD2427691A9C9286279CC2C23D16EC61CFCF376F0A0A98799C3534B2DE25B0F321FD3F63AD23A04E303B4ADDF3CA6DC4CD8451EF9995B2BB78255ED775578119E1C3FB8F7E60992EFB6F062CED7C0D6066FDCB86320EE3D2084096F4131642FA9F7A0BEAFB80FBA07A49D5407820804D6B09EBFF47ECB2A031F56FBE71F2CA5E15BFA688D11B2E07A9F8F840EAEB2B7CB2531771DB264A98B502555361714B86DDD9D06E82DB5ADA6486B180D2C052BE10AB021611AD7AD9C326FED718964A014BBD964788A1AF5A334E4D1716074F2D80643485AF6BD659F4B934BF4E136B21824DDCB9500A5F6103EE83EB824067734884BE2541D81899455828BCA33D42267D4216804ACAC7E788FC4DF2366700538E0566D5CEAAE4BBA4A254A5A7D2681E66A6CBBF0C8B347BA54C201E335BEEEBA2F7A182620DA85A0D140E68B14164475DA4170A4162D0586750FB030AABAA68AB980E6378065E5498FAE55858CDA9D45BDBFA7B2B7190E276EA623427AC91D44CBF0E378CBD5F82B62A0D75D6102E982950AB8F83C08F5F5436C87FE93BEDAEA13F29B94862E07ED40A53A30297DE7132A0BAD4BE2F680EB01544AFB17E902489BFE86556F8C216EC87FBC3ACDA43C666C9FE091F3F02482E2DF3D5AC2BF769EE9E2AFDD2F4E1BAFF02375F04B22CE330EEDFDD3DCAE504970F5C4E3BE35A27F642750B37720DC54B5C959691649DB943AB84CBE452F38F692B83732BEFB02FBE46228E8B8EB019794ED67D9E62D3166916B9D75EBC7501232028634ACC0043DDE0FD3C000BFA34F9850DCC7686D49BF2B149FD1D430B167DCCB3DD8A76A86A6BA0ABCF7F17402600C10716864EF5B5557EA4C2CEA0E642F1BD5E8116AD52C7D338D0E48CFA4BE3C85DF0A78EB3EB0CF17BDB3B9508EFA7CBAE61BA21E43AA03764DC417C6FA2A2E24CD513A9CFAA62C760CFF7989F370D558BCD602A68AF9CF4C43AB7FEB3D6C0D14C60BAAC3A13865459874540C1C543DB71C0750DE1B538F10A7BDA71D013DC8867F3D82619E0FB2FB1F52332592A1213045E21287548A589E1C4411E1D4B070ABFEE1843C042EEFD1DEE5AC9B0AEB74BACB01E4B74DE7D3C58406A63099FE8C360C77E0BD13C95C9DDF273536168F4B095C36F965FCF090870D6D56045B61F3E7B4E0EBDA3309F077C3DC70471EB8C98362B5A3A82BD75425C16FC3F80BAABCFF8F7A4FA3F8516E5E647BC85E918CECCEC02D6505E45D08EB6E1519C4A1AFC5F77C98AD8ECECAEAFC29003E7260A81288878152907DA2C7BDA771CC9BAED8E21047142CAAF3FA918F804BFC023C2F621E7767781BE63393B909CFF293F857FB9B793924A99E287C3EA5DD6DD9517AF5E00D289EBA21D7A5D84CA7E8C6D571DBEAB70ED06E6D29908F21207B060D886EBBDB41D1154CAA85A38A2AFBDF735DD93E90E6ABE4584DA2B0A7302DBACD9ABE94D93AB97C656BD5B9CFE595799E9ACE3F8F438BE0032530BAB635251C6C616BD40264818271A054C87E1A5586C295680A795E339876B0E078B8856D00C4950D2A7E23F16FED3281B4709F9DEC7C7A2063FD9274A7B6EE4554DE0F7904F0D8C8CC51BAB2F0EE9A5C909CE69CD7FDA94AC254E4990BD3F71AE3FF3695C663A8AB16E424F19552EBD8831E263A8AADDF27ADCC19D33F585AC6AFA925379F0150DDBDEB092BFD6576A06419793440AD01FFB5B6C16F704FE82DA30013AC75D5A0502E030F6CD2160991E40AF2AC3BD01AF9EFE6F65E44FF42806C00C33D66AB4631AB9AB76DFFA6B86779E91C539C3D9F89F359AE45CB7E40C2EEBBB09A15767ECFCA2DBB21850955025B36859B028BAF72A646BB41650D14C4A9DB34EDD2AE70639AD29A011A47E656A1B15DCB79BBDEDB47AD83902798B7 +sk = 9C8D58F80F7E14FB50E5ECFBFBA742F1E29FD7DA1040CB12E07F2EC235E6D92E8A39BA55420173EEC22E8829B700B6C6AC2FE27414291DBD9F8C9B8F71D0945E5F8A34467CF7B1824959690E4861A052137F0354BFAEC91C49AA863F49C1CF4C28D764F86442BF3BB249A987E346CA208F5A2CC1AB11D1C37F9D4061B4E63566031262306252265476164747601538446321858265380761372002852840185035741658376484771746688114086844248081444158165705135466786167180062777281306346324407546648687374388022112128653813310355345034548877466371625110353667826877033514434478057661724076453034140460430280451150627211800201584125350324656821238120634610673046837280623754403673480302737262645075236711041481771140187660401847330078053602631033010612748332607015601455510621066166108521740177616437146263224028412844215168020657750661846355234214687073688775704157201078317527148631030405346127583306406323075001130616862222413820631818675665476138621050111022618521561838877631610475464586486820563378438021805626683461708581672763852871457211656211502325836063222132585136755575562273823853375203207108666558857452162155685203672014428231870117332530652552136685174084144576757173486087505110182044241163302103270084034030146461500181245178212276520818607381350042206104448354841235434414154653371043717481127138345102665116085537623242177363208248514671333031267215562230207358565617641271154128246170278801325085262622070226670383745723732857444447637101566837111125605445558348740444436504224883172007613285306166734240732084047563612653065452864428400588802030010180256083517672003032057432283457613612134677602485073887316226558753586008358047112286650736811215474177170375844843625557164256744531137314681260783166511168225753271866777430677263185734033145140776724885658818512472042164055672110523878822643440278276245225253004570032424768133278256116513882112787020710634185216064866186271588042074061133863036423016388778140538017444520483764626364666022520235115742188776847068636270785443601133877546436202567415440733818787774741317061306283378064785173187658076783050365245483013888475183401262238168205404227678770527006310124306662654664508773215673844383580163405441353762752723270154002617067711465367754243544074874407722403566282888062448325784104857702700571628725233076130882504066486546337081556817860656081643470240851073723166575082871171755713446268324863820468570350543025506468768172746662877522563753875464124088300008104620504845223141741883608680884311487854185318715563178706012543803735440771182176256557321826813808018578680822260400260258262123156185100418026780462845182656087538312385587842006582155350423216855608724730134428642524404413644413433774131387750862651606746437831387752773216883233108321188555675431461178120451621846806627765587380661004561600714142860674422661014857208543808710603147502025673872022273308603345371186502645621708127657475568753216056254830146054486764740224055203136125757567367672367125643633180570228074647683621603130627770383053628335278718414588251814114837455186765216105465051270522741180501311512438827304524863382442178735258235063870080057430370135726876468705527255554314345754DA1523C5C7134324528F2AF0D8F555C90FFA43C13F8511989518E4DB3CD58DA1BCD30EA6C79B5994829317651521DD8EDFC145A2478A10EC5B11F8886A4C5488EDB8C21E0CA65C9932284390B2E99E28659DFD2A5E21FF73F8619F227DC2195E74D808E5F836259F9E2899CB5507E6730732FDF6E7C663A99B5CB14950336527ABED559C47598F9703309C536FA9E8EB8EE6E5085BF6F4568E7F6964DCA009A16E3328C39D8895952CA9D69D056CB76CD8A6764B96CE1BF06926FBD5E0D8679E8BDE0809C813D41C0CFF01C8B4ABA8EB15EE8770E74C7E1BA6156C2A466BDAB8147BF79AA6BAF57A854C1CC0AFE7615D6AA4B33BFA6BB31753C4B6F423577CC5B99E86CE375C722509C0170C44EBEC513DE9542348D8650AE247AD81B617560854F86C83D59A57DB879A0C2ED76F6928722AEC33D78A8E571E326EC0547BD726A07B85041A0888F5C70EF3C3CC2B27CFDA480C823C5282E9CC56248A9427F26A7DEE9A433FB443456604BF80C31937E645D192EA5258221A0FE5454871E52971569C4D798CC8623909DA4D0AE9B8642176146B1F8F9ADC7B8739739C6976AFFC560B93AE058183AF8FD6DDB850FD4B65B50D9E94210C7B2A5A5F26F616C0AEB03CBE5994D99C298C024C553927283BAA0782EC9B1D965F493BD10A0F6DD1B2D4CF02EDE5A69EA7FF51EBD8EFFB1A33C19DDA8B46A5D3744F4021BFC16A63C74B972945BB3365A926CF9EFF13DF8F6BD3DD5D56991FDE907A598918CD98C9304BF07FA37478251FF5302525A0858709123611BAA5464C2D626C32D62F8DCE54945E5BC3E6E6ADB80C95D4791BDB4423220815BBE79B69EEA3EA55B9BAC3D553F72B2AA4DEBDF951ACCC512D0E947E74348CB5A617D79FA4CFEFE37E4FF74DE6A820612AD9E933FDE262539F11F18DC5E566A5931116F62368BD2974FF43433B5EBD2197997DBCEAD734D2727C4DF33BB5A52CC9CF906BF3A03830CA1E3F403F722A197116A391BAC7AB596222635E5AC523D4CACE762FD32ED6D8761863F28584B00628B7ECDD389DC952FEC3404FD251E5DD5A3C10EFFA9DEC878249C3F8581BD8C36A51DE682ADCD121AAA6D1AB0116F7191E184C47AFD6115500E35620C2ADD62CA3E07506CD898BDB6526037C61382C2D1127BC1574A4000EBDE67815E82171A68F291F66C772391DD1E583E6F2DAE8FF78E61DE3596CCDC6AEA28CE36CFB91A84923F36905ECB036F5505573B34C65F271A8C0DFF23CA633D3D954E799B0B36CA31C1C4D4643778428AAE0D2F8FC662D69322FB33583EBF6BF2EE7431C25EC2884ED0EE89F2EFCA1D7FE6290F691663B694B54F4ADA2B1D57AC2EEEEBD2AAAEC5D581A557BCD1B5364D42E6280CC643E3A58DD6F4DAFDED055D7F8B67159CE65FF28033C7169900E05EF9616E7C0F8B494127B4FFCB84DB69F856F616F8D1E2E6F8D0AC11C992726CEAD8A5875A9B63A6227AD3E5088EB8FB92407E94517866EA35ADD37E1217D78B89268C871458E23213BE2101C63613C4F2F5D247DA368737FA1962D740C426940172F3A8FA55311598A8AFB188CA303D9E0D777C88D6345C4E5E7EF573EC3EC87E9E7D128D0ABE699177E4A0EEDD5C15EF97AE93C482B1429836507A2544DE7692C78C1E70F54C974F42B950429C07B6E775B6ECB6E7FBFF6BD92909AC1A41921B7FC8841B01B727E50FD61495942DB0E66398823950EAD98D988E9D6ED6ABC078DD59E0B26F7FC198148482DE8A0C96541768B0289DCC9F33EA25268D3B2F2072F234D4CB77B7EE828481F123A14A214A42BEA067A8F3D2E8856A36646A1EADDAEFA191C6CDDAC1A90B2A6402DD377F1690B5F0CDDA6F845E00062D121922AAB221458B6A1C0C040603408D2B32EEF40EB30C5231581BB9199E20633F570D2DDC6969A2A5A949E7B7E4E637CD7C012E9DC80DF493F24225E0D73EF96739A0A3F89D6F5B0937D258CA1BCFFF08D5F13069086B122944D09597D9B411A5038014EB7FEEF4248A1CB896EA98E4D413ABA1F41722EBFE9132A880AB47EB7E5649327BEB3D8BE31DDA8EC63D01359702717C1AED74BB164EA95E7DFAB2CDA65D3C33EF715A4C42A6298081C867FB2E7389FA34273C0370D8EC461A3FABDFBDB96BBABBB86A0DF14BF9CEEDB4F1F99D8BAB6B1735A33D1AC8DFED9BCAF2725F572AA0EA73F81E3F99B63C7F31CCDECD4EBFA7FE2D1854C6388AE519AB2F325EEDA686EB5CBAB1CF07EE8186895ED1CD1441F4E47F518E81FEE7A3B217D2E81713EB155B6FF2F78CBD66366F59E1E30AB1F6D44B11552AD4AF981F9C186DFDDC4DDBEC51645E72DA30F76296FD947CF241615E9E9076A6ED79DD94BD53874C0C3E11F784326E09C904F96EAD91E52D8AEEDE87F1544C5F4CDABD8DA5621131531FED3348F24DB28A3CFFB6565F1379A5228A9860A0AC993818D4013BAEC8BB74438FD807716C144985E5B869B0543791CA192658E0028AC30017A46568AB65DAE1278014F184DE9D0C2FF2A675E1A39F0AB3DC43CABF407C64C5C4AAD4ABA3326AB86E082A6699D5E63BFF77C8CFCD2808BBC1D67EEBF88A5349263796D9DD2EF581A71B06B17D01D60CEC3AF00DEC37D7EFF6A74EEC6BE7CFEDCAFF91DEF320BDDB9272B79451E3B2661A357094318B8A0FE2EDEAEDC6CAAB52C48ACD5B7B232621F8D92E045BA9666DA74B9E2CC4B65FA87DE2B21C7C3D13CB7A9F76611C6755A6C20F6EFC297D8711343217AD6E9232C3678D8CBEA5D9177315154F2617D38C9AF469DE1BE5072E888B2643ADB968D56D16ECC18E70947C58EF81468596B16F8B2900DE29759A6C87D6A01765A7DC00062713093C81C638521D84C474A616D2569E35E5BBD6294B0552B4916A1EA620E8B4EF9C068A7CB4D0C99B583B971D0D4ABF31E27871E2E755512430D718CB3014CC7D8ACB4306B45323381F7F1250B1AADFA8B4DD2CA46424EDB1D6299486C1830FE1A85393BB5FE56C088BAEB75A807C0BB58C5D1B96B70A7AEC61A7D7F8A1ACD5DCE9E4BDC6B3478DA3B2D061F2118E07C4611159C71B4AF955D393D8782E2293D5C9F35A9ABCE7DC1FFA2DA0D72B6407DCC40AFD04DC5A3CE4573ADF35510A8D47D7F5ABD685DD5956A33F6AE1387D79C6BFF69F29E9969402B669CF624CE3FB05FC68BD99D98D2CF86EA281C3ADDFBC0EEE8CB18985B2F361B139D4B704B806BDB90E4536435B1A440A4EEF500F45F397B571C96A03E5506150F701C208C68526AE507A8B7068E902499AD3CC305F677E5E4F15EA56399ACCAD93EEDFC739DE1135CB60AFA865616837F35945B5A4FE4A0B29AC3D5AD80DB28211F192B0EBE7CAC89EDCB40A1A71E8D8E79061599656E236F1C14C5CE9C27C9913642A06E0E46F83E0823AD1851EB16BD614708DDA32E084F8F08696E1652C97AA0CA59A2B5B526CBEC6109D99FD27F2952C3C3C7780B4F6ADF83D284E4FC86F3A7AA6586FAB78E0949A0D406B7615658F338698B7083D294123DBE42C87C00A11F8EF2D24BC0664F27A4B +smlen = 5916 +sm = 8DB328582113310B369635B46A5C7235998EF95D85688F83FAEE5A7AC23788C4B8A94BC2338206A086C5C360E9AF404D8F5D4A5215407F850F221675825DB791669955FDA37BFFF655DBCC89CE8D44785D15A2DA8F024C0A27ECF56A6B8109282E1187545C22AAC5625E809F067B5351AE13C0C2682F11970990AC2F89E00DF14DC3772D4465C94A9D1F2F7A453C06F4CE8B6C2E866D5DBF4675056F9A9BBF93F51D5BF75C6F11AD469464D266C11EEA98FCA2EAFEB825F92D0997C271FF0CDD1B6179E02D3A936B994BCDE039A3BE7FC7233F74A0C77AD1E75D7717AFA030DFF784A8F6A1FE31FE88437549A6933C197C8EB6DF36B6CD9EBCB260A032F64F7567E63C63832FD8F610B1BAD24010807BFA2564747A579894D250C644192494B79B89FC44819774F8419EEA9C0D9DA18BF47F0B634DBFA8EBC50DFB57C60721D093945811CE68BCBAB6458BF47E410B1EBFFB1C712E32304FD3FDB5E2C89D74D0277728DA8918ED8AFB682AD751EE7F2E4A531AFC494E17BC9CCF7FD886C05E9CA77E09AE850F964EA49AE87AFE51F0CDCD17E3BDE43D1A2BDA1EEB99B564088D51990F9EB7410336B14D43C916D2661133161B36DDC9AC43FD8CCE7C9B02AF39E0639C683CB655E3E28C510DC519933324BC1879C3A28DA0E9C5BC7F97BEE69FAFB679DCB4BF6CA9570228BCCA8874FCEB47200E7E4AFEEF0CD14D91B2AA4ADF06C301E8D83F58D162CAEE7B55311DB061A35BC362770FF6B34DBEE8B2C618164CB3EC3185012C62DC33118FB13DF500EC1BFBEE9B8CA3C6310761F98AA4428EDAFDF81C8FFC3F7195449DD9B69CE848791DD6E54CF6504C5D360CDCF3DF79E68A92D3AB0884EB35313EFF07142F8DD6037F0E9AEBBFBC7A5BFE1D15CDFDB3D4E7914F57D12C73E229E01C3B0CC999278F046E1FB0C76F32516559013D09C04D1EB559CF1FB37598D1982F2D347AC19DD2E483D2313FAE83184E2575729EF21C31B1620F1271B924F41ACF57031529DD42E8B3A463F9910209745273C1296863860E8C1ACABAC6AD17BEA37E4FF038CE85CC776DDB44031A91CBEF1441C450C3CFA3BB7C16E086366CCA7218D47DCE4A2B99E4DB285060F8CA67AAF41B6FA22BDEEA9EC5DCAC17689CFAD82EA43CD60A0290AABD9978FF89FEC0FBCC1089E83A82691342D9BBDD68D34E759F10584C9924FC94052DF55FD7AE5C7D00C4634E2FC7EC57812992FC8668E52F474FEEBD1ECBB7214C26AB1A0DA7A23C2A089B884E83B30764FDA3704BE8CB0B5F314E8EF4DABB3C4DB336E35B3B3A228AD5D2CA6024322301FE1A46321430E4D1C3797961A08F92FCC6478E2DABB08D192E69D2E71E0D9E8A6EA6887F046A568E00B2256E236913DCF20DD6428E202152750A4EDD471D8D250D55BA005A007B17777EE5A41B9F015FF4DDB1C9ACF05D1C76F153B4EAE75C766BEB1C20485CFD51DE3B91DFD6BB039D6379BD9192CC1B9B305D5D8F97FB7D1FD5519B0E8DB258A03AFE0208549886F71F047D5B8468802012D90F5017AFE68378496F4A2E9FA0B21500C3C238AF46BD7948C8707145ABB50E2B6001FFC26A36A2D4E071BD4BAF1F98EA6756378BABD25541E8F02F9C737B10DF5598761ED8F8AC20EB92EE862C594BF9DB61F1381A27332E18D32D98FA571A53EA3E393B90D5E3E2E3851E020C140D79C1598EEFC537D94AF9AE09D8BD9E443E2933368310DDB514F85C6F496341864C224F119329498CDB18DE78F747C0211A397FE277734040C4BFACAB2205AE951B9A58D0D1B1CE241DDCBD9B94E87EA01585AFBF9D3128E31137A8D15FD4E2996799DBE91AF3D74B77579B431065519C5573E8C364C930ADDB66DFB044E3DA5EA7D20404BFBC2C747F1C05CBD484F5FABF39132608A53039841723E73FEEF144F0016F958D4D5877DD2B9F07EAE6D6E773F6749ECA091FA2145FAA37315C04DC5EEEA58C94DE8325DF6EBF0A9E4ECBF3D627D04E1341CDF991DD87A581306A1226C8D033C214154C99F2F6299718282512DFD5000EB0CB9BE354406D39AE5F6B327B131665867F513814F486B53E91A21D9DB8CD984E40B96DCC3E08EE3A2E7512F2FBE20FACF2D69D99355BA7B08966A290A0E5495AD160582CE6E5F40D77E965F67719FD3B7FCCB006203466D83A6F357AE2A35A29EAE0DF2F8FEB6A0D7D7E5A832D8AE048C630B7DDFB21016F4931F1DBDEF5D81ACD61D09A08EEC3040E75222E43558698940B7C4C5C027D52C9786EDDFB9C612045A2CB66E99E6BB0D7E11BE03E08DDC23C88EDD936F7C6CECA9C384B97755E20E8F200B1C6DFC70F123513B444B5CB87C00A22BB554DC319E0FF9BD338698450AB298CC78AC07ED7DD33A709DEE83B39247BCC602921FAE6C831BB9AFACA712B5EE442933ADC3F271151AD37B5EEA8DE5FBD906F28860A081A4B2E140A2BFFF3057CD6ED34F52E1921064B5CB7E21E5F545849BD51719C6DC7AAE846E7C645B74FB7321F2F44D5FDFB9D3B9604777AFB862AC7595497E1AFF8EA422E986AD13B309C185A199B378484E8FCBD7FBED0E6FEE17E2CA4DAA1B5BE7C85E465A118114AAC865B21F20B262D164AAA8A74C6B3C849940D7C991F9AF776A08D99276135D5B881A4100B4C62E7966D6EEF7531C307A3A538043DD4FE796133BF207E036D89B1F1F6C1452A2023BBA4B521F8D04F2F14821DE10D6E49F6363C7CB6D4E06E4D1A4E698ABF0DD93FFAEE782907F08937F21AB4A4CDFFC5E90B11FE9B814DABAE2EF4C7D363AE15FBC02CA34F69E8F7B40B36BC76605602DA6A9D035DAB119A46849E2093A458FB2EA81B8AB7EDFE118FCB72BD0915D376C12B3773609E4BD4571BA49551E64F2227C5BBB507E930DAEFAC30448BF6632BC6F3BB617669788DF60C5F29A2798BE84DC5A296CAD490FBC3B38F9AE02EA1C67A74D986F29A485C8D4FF22BAE1560391B1C606E080E6D5982229660B7D21BCBB6E03E456A8A60CB8472A7E7B17305C7E3BFBBCF2F7EBE16D457F7EA1A99789F5516A9560AA5F43CBFC92856CB0E36D7890450855A4F3A5950D226F67B40E78C5ABF5F547C4386006A42E4C33C3CD3ED72E50E740EFD186C1B4E52D79E72CD6C32AC2FC1FC6A3492EB88C38BA05400865138A4ADCC03E2ADCE82A77F9017479323F153A9322AF7F016E95A6F95D860FF42638284AD6CD57D13D8F775E08E1293D91E512208F85DCCC8B95995B2114EA6BF19E8A81C4506426ABC82404E2ACEBB7CFDAF46D0D984999978F1745ABA34CF7228EF664174DCBE49EAF83435D1425F0C954A39D256FE3FCF7D634D03026B87F3421F7DCEF9BDD515B87391DB8576F4243DA04283B697EB0283F63FEF64C7264F2F0A2A35723ACFE59595D60AD57A33943107A7313CD8938E3EE6D81549BBACA555E28042BF25D6A72034DB70E7E7981E11D558BC4A691821EB0674E9DBF6CCF5E28124CB44D8D508EC2998180C1119B0A840A8FB622F5359F84CD98F75D9CD12D40D8663A7175CB91671D4C5BEB4ADCDB523451ECABADB2F7BA4B17D87CCFA6417C41A09D7A9CA2F77FD2026A52A2D615ACD6812DECA72C164DF0987685A0E715EF9BA418AE44BC19238F049D3CD6700C741683094822282F943587974DB7F539F7D705B2329126E5B5F24DC845FE7C634D0076CCE142460965CE07AC0C031492B743973806C56FF2D4B56F0079DC3756A1EE77F4D82732D5293FEEA0B905C685A283177C8815F4BFE8E4A3AAD1A9D3DCB70E9B85C9549ED3BF485AEE4F97EFFB04DF5616DDE1B189F917DD577687476D58316636C5A4975079688771693E683A301725A5702370DB5F1C383E47F320AEB2F54F82C9998790ECCD5163983096FB86B42112A2F04FD1C30B5D2383D90D74EBF9D2E4B16321498D74400B4ECF0AC19EC5446530FF684C5A5B4245EF9315FF2609272481299C41F4DB56420959663ABDDEF23ADD00109659505F012C982AC0D714DAE8A5E8D92578618F6549677E35DA430EE195CC075D760A20D191C0565EF9B2258318D9E0205399943BF7C18F56F7502E6EAECDA1F6E7B7697BE66B6220937524D2F59BE92920F3A98476300903ECB9A53FF9F2589CAC5DA57D0ACA1A9ABF4E778ED30DA62FD13BBC98FEC02A191C920F91C3E3897A8F88A4BC1BB497624AA369B2560195BB2D422753E63FC18130BABF35940CA591206F6DF71024E8A3D655996552D8BBC4E911A2A4B672F9116EB6C0DD63A9F67D3D50F9ABD9145812D5A803E9FBA983C567614842CC21BDD00A84FB99E8F5D575EFE246595AFE36188CE89505DC6D07CB7DBF6DD58A26DDD6179B41FF8DCD77888770EE455960C84B0B964EB0AF1AAC45909E19D492909A5AB79BC226187B1091459B07DE36DF19C4A98E4CB7EDBC7CDB31EC3D1D19E96DC0C32C81CA444FFBA6AC115AD5073E3F2E6E33F10C52DD1874CEC1B2BBDEAC62CDDA5EDE1D0D7073E3591858F9C934FD5AC0B1819EDC6023AF2C1B3F7D20DF13BA8524FD04DEA3E75CE788457DB98D3261D09734C96CB60BFA1EA4E53AFBECF03F2DD4F8BA67EC6F043B3B5F86DE4B8E0716ECABE945BC19414302595340BCEE300F1C65B488188C1EAF0335162DB0038567BFE3B434647A8D5ED0679CCD8E8E9050F70939AB6B8C3FF000000000000000000000000000000000000060A0F161C2596AD5FAEF409B8A4C21ACB1ACB596BADF387D26656BE3EB17987AF59737E324B7BF8412A306B0E706AEF73D79AF753D9B0064BA9CED8DCEA966543FE748E2611709ECD1CE6E4DD8FA812D485E91809A225936675369574B0D104A258E3353EE0E021683615CA5C7C531FB29A5025CC7F7323860443DC19C9858F741EB9D24A9F6F04FC839B67153214116E8B7FA982F338445830F915F7C85C88C23BA2A3CE8E2020A9D8DD7B18EFE95563E3924D2A341826AF51A8584CD026B1C433EF0221145BA8BDC8F73A467B33A9EB3E8CD2A4D671C17D7C28AAA539D1C5BF2F4138639AFB89CE791DAF0EF0281D52598F4C13D210974CFA1F099A0FC70B1DC120E5C00C33A2BD360BED57CCE069060D6380BE2204852D8BCFFF4918BA0B70B0BD1E1D55DC1D68DB1D20AE713B0093EAEFA1E33D40D9BD95CFF17568393E9BBF5CC1287325D2668F65DFCF44ACE2F6C6CEBB62F1433E69CD19E6C6532EA93682B22C4C4A62C6ABCFAED08EE64F32723E56205222E4AE0831AB8FCA8C265FEA0CFC66AAB1E367201752AEC11F752B963792C071E42A8A1AB80658A0C6960147ED740CD07F307CF6A644A98E1D2E56C625ACF458D0BDF6216A4F1B9C78EC3F14850C803A4207C894E61A8AA88840A27F2B439FA7CBAABBC789102A95323E06E2C324859DB92C6CEAEFDCA389F677082180FE3D6202FF60DAB9F87E3B84841C0A4EB5974D893333F7F1513E54EA4AE0731EC409F69B77089FAFB121300042880EA59B7927E9435EABFDCC1019A96E145D5D157998D620E7BC6945DBD6CD78E94C2D89589F8DC8A01CF1B295A26B091847F034937F764ADFD811F52B3AA187F3F49273EAE5949FF34B64BC86FF11EEFE378825D526509483E7191B33333E5465FFB025B269F898CE1F83EA549F1864B556C729F510118921B69594F67B8C229236AD3AEE55BD7082E027B5D342C976A549E01618288944DE0B2C77473A25201B61034B334968178AFAB7F8CD1FEB6A25CF8DCE3586FFAAA861471E2EE7F0C22538FB3C95D2145965C4673E6489764AE24B4F048DED77FE3487AE175F6D4898F69F9FFF276470A93DAF986A75F685919D98C9C609C795D4785AE941C782B551EF382F47209AADEA19066AE5D3EBA7BBD99E91943F1E62754A42FFC8048F7B87F128CCF6C96BD760B45F07F740E94491874B06CC3450AAF55BC664B407C57369CABD2708A9C478DFF64D292D96AB71EB997F8B71CDD6BA02F52C5035EC26E8111EBF8268CB00DF9ECD63BC0D557E2D2E77A6363B00DAF25237E77DAD03F929E5E9B39447A70D4E5F4B90958F312C80D594E1B1F3D0D23F2B0D9753BF3544061CF0C0F841C440319E74F9B9D15B91EBA1E680ED6AAB7D63A97B48C0A4AAF314E8E77E2EA6BE9DCFC7B5557FEC1B996A37C86CF6941325EC356EE75671726BCED7D2157BE8D4C62CF4BD0420BAF2C4223597C0EF75F7A7C9533D14BE0D21C37F06FAA53ED5EE0DDB025862417F98D2F188895395CF2FE72185ACBEA952F55CAD7EC2D684A5AB94B1257D7ABB565B8C07B88C6335FFB9D2FC6F6779CC24FC3CDF92BB3B12EC54360A7CF3579632A2A65C518E57015DF1C616C857F83F5F1AAFF693ACFF210DD1E95CE04CCA9A0BF385ED6EA2AED894E79D5133799393469B666209371E708D4D279E1AC5ACE28985D0DB2765D547C2902B715BAED5A4FA3E7AA42645F3BBE1E9F3CDB87B1DD8DBB5AAB08626591921CB49E552F8EBAFCBCF428470719AE40B9CA847F31848F39E4D42049C5D40B0BFF036E5409A6A12E7924148E60B64BB83386079B54486FFC8187302893B8BF826578D9CA03A1291983F21DE7F6E65458F8942DC1B135C6C8C1FEF4F3863A58DB17112419590AE57B9425592FF22E596191E5BA7C513EC315EC3476C95A149F6A5EC1CF24870400FDF46217A23F42E0B61157C3CEE23E7916B4475A94B96B917C171B1A34DB13AD98833E457343F94A76EE226FA5B9F3066C2FD69F14D3AAED1B31F5114780442EBBC88D0DE5F689CD910E7464D73423B9D4E03718C5C51871250D11E27E28DF1268166E3AF328A80D9D335F2D27D2E91DC61CDDC7F733E345D56C11B6130875D93D527F93542FB352407185E7AC07051AF7F642E34FA06B1376BA15A35D837C1BFE090BA67A89FC1E307DFF3F02A988ECD48FD229733F641F2609EC8DB14B1A5AC170B104F03C2509D2EE6844C716766D06A6A25D957530FD68A8DE6F1753F83EC19EA2DEB1A4F9C7986F20FF60A7508DED6547A85BABA70577062E8144BA0496777A5218595E021937FEBAD4BFDECAC29E3FFF2EFE7D598FCB86F93A734E4C573E1496A6282A3B40E817DD3C9D631939AAB350ADC703899EE3BCB1B5EAF6EA8420DD6EB2D4F64A1818AAFA97B73C75610B6005F1EDC1EC7D8F8DB1E5D3E9666C1292515105037D26F2C8D83FEE1F4EF5DEEB287CD7C1E11960218C1B8BB50453488BAB019435065AEDFECD8D218BD1E751FE736442E8D09CE7176A71C06415A30B070693A68BDAA5CDF62351AE665F37FEFDA9481E62EC181ED24F0D0649AD01C89AC422F1B7E27895E55DCC2FD817346D361FA559094B37894C0B478C68A1D7564D089D9D4417D5C7372A33BA475A81FC129F3259C5407BC7435825B415782CC84D85E69D9B44B32D78FA255A895CFD55319DAE677FF89D93A3884CE9401775563FF1788CF3AC11CF96DAA199E7F4579A0264378A323FDA64FAD2349C09465FB23BA09069C7FBC79E7288A82F9165268F6842E0AFF0E250C21BBAEEFB4347D4EF1CD51161DFD29BFAFFBEDF71DEC93F4157A5C18995379ADE8D15DB59EC4A8B308C2EADE1B7DDAB55CE2220F3B3AE8CBA7C8211CCCB3846A225B438F4B37DF54363A987C5C4E6B9D20EC3C0096317D11F982184B75D8EFFD168B7B41317D40F903A23A2649999DB36CAAE31BA5D91998A684D30AAADBD3B1EC154BB6C92513BFC0C47C673254F42B1FA36B995CB737668CBDC2A0D1BA838E74E0E50B22FC22DD048F48B6D1E89E1CCCE5A226F63AC7B8E6E9E8CE27050BF3DCD7D0F35F47BBEC1CAABD4D619CD77302AB4FF6F56DFBE9F5821AFF2D72EE6A628DAAAE4440EDCC070473BDAA54CCD775331AC2812FC5B9884915DA582EB36F85C7923F06D961594753802EFC5883CA484FC64FACE42DE6C3105E23CB90663A3B381D0C6A7265B740BFF0A1A017058F06E39A74BB07B63F883CF914FE675E7E5AD5AD44C9F90DDBE23A125D9BE02264EDC13972FF22BA48ECE8890A223EC13ADDBE055A8B4E03882677FC0D94C9053DA6CED34E132FD83810A793350446D60AE5DD0D174B534A3B6F5BC1B497F9406B5CDD414401B6DD881CEABAB12CC51425E88A81BD9E14BDA18273583CCE0849AA48DBA1CFC49CDF29242C73C99C87F063B8B739AA787570459C098405DCCEF78D6D97C21545F2959DF9CD62F9C38AD9A849507C23A51714565642DD76C9103154327985F7DCC701B795A7AF8625F06367ADC11A7FD7B6ABBDA5B2FF6A825DD43B64A48EDE4EFF8603A82159A6011F9E626171E4593C0E963595A6E068AD05FEB12378C71AE515A82C293EB7D2B01B333CBC7991B44685AA7513B3A58342BA5D094B773E6A27F8582F3DABF54DEF59974CB8A2499369B5B64C7AC08D32D75FE37371C578073DC83B82A828DFC325976FF282D3F6 + +count = 79 +seed = 8B47E0EBE786914C9A52D547106CEB4A3D3DE938B3244E02E5F9660954C4C95A23F2476FCCB487673AAD0513820905DF +mlen = 2640 +msg = 2447D338BF1A375B66B77FB96CBE7742508B57DFF4D33A368EBB8451C2C67B980D3576E6588D8678B285EF288A8B5C9C2726C4A550E764E47FFFA2A128533A7653E480288447509E10013AE1944FFFAFBD9E2BACA0B3C7069C07A4186C056FD3857CADDADD5F891512DAEEB26865F5C89FFA63A64C85A08E41EBE7BD8786A8ADD571A4267D5A9E426840A0B988E197A09F3770B5B0D80D65515CD4D8390AF40E6150062DC4B8661A8238F232692C152C97B8CD5BFE7B5AD863DC92D99744D769087B3EDD81D2E475F5CF0224B10CDE6FAE8DFC3519EFDBE66805AD4468D84D3DD93430363677360DA8F56CB58A6B775FF6417C1F324380B15C9BA668EB0F25FC2A690B483E856F3327B2D79FA6259E30D7F76199CFD21152B7C6FFC3FC113F70D3930C08B3C1EB1BF25C100C5A930EEC2C52664F092B89614943D9D85ED86A2EF666A94F9826C3D116A2BBE49443E2C11748C977716381D9463DA8D09612B80A6760E5A6FC5F59425EAAAD6C8342C1EA4BEEDD5D73151CE213C0B155286FF22CD28E3BB88E0CEE39CB859900D1E0FC19F6A7237BDA8E51476F4844A316752FB347492A928EEB07AA39ABDCC0164D1921B61352ED4AC94B82C410A56505633BAD53A3E649ACAF64C43C1ACFCD4715FC594AF6FB9E85B0B7DDD6E8621BD12A2BEE48223A97EC8502C16B550B03087B6E87C1A860D36322064F8FEBC52F2B7C31DAE7430870259BDAA5889852E3AE6F61013F5AD0D38727CF9D90C67BD7BB3B82D303C6C35383ED86FD5B7DDEC824EA198EF780BE830A1F2679D24EA6E2FEEFB979563F511D188F409F0CFD0050FD418414D01E46DB3D23B3A90B24F4E96EDD4F863BFB333D6A826D29EED167738BBE22C516C59FDF81B032BB55473A5EA2A1DEFE71C95A1EEB5C028435AD0379896CBBC76877501B054CF1FD2F6D7A9DECCD70D0C07111147EF568DCE514DE96EED61600029C8D103B31C8B344A700DE630276BA2C5633419C59E66577659538A6381E45584C7E1D6ED978AB0AF89067AC83BB70DEB6F2C58E339A5A66176A54D985DA6E02002948C62BE6F12314240FE18B09AACBCE82EA462586B8316C3E0AEA00F9998922F8D956120E53B4178223F4D2934A20976FD5A72027C8F4CB33E9BBCC0ABD15395151266B6CD5B4A9E2FC1725D8E9AB2CBDA47B507BB25AC995EDD51EBDA5FD19CAF68FAD8EAC57CB5EF0C6FC861A73E64648EE3255DB4C3394438F49377CC4AC2FCE1B6BC812E5D282F122678713C6C6D452A33C632C0AA47686588752D72B0586FE5EC2464A6DB40662FD2106A19F67DCCC45692FCA03685251D512642B0CEE436C78D94C6F5F25BBCB41FC7E5B1AECD52B846A0B70EAC93579603E9870F942AD4C1CFC9D49B1132777C6F1C184C1537178E5029067257A2DA2827A2EC44D323D13DC6E4E1B9EDF5949D4324228687FD54F02CCC3C4DDA635FA546A5A6783959B1C48AA9D9C9F6381EBCCD979253460857D3CB1C70893EE6F04709E35923883EE3C71C7F33B8CC28B9136B3EBE5F52B9A76817F2F74FDC2F12B459DFF32D5A295BE374B3FE507A0995BCACF1E7B24F4501B29F1E8B4F2A8CB394B3E459A4296F6439BA59EC88305AB045FF40B1DAB4F672F878DE1F9E46B9326CB3E2F3457B83EAD8DEC28DD079AF0E984A69ED882E1CF21036578485DFC2DEBC9CFE82FCE0383B4039D147C4C7E31E315FB57B9093DAA811F4EE4568E32E5625ABE76C5A1AE42A03441DBE766D0EF4DF607406F7D489275E8C5D4470866F9049A4AD5C428B843DEC3702E86E177E4B60181D2B5F099BEBCB25F04C93D087C72436E87A9B3AFCE78FA31E2B892400B5C1071F8AE0F78EF6F7D71859A97C17EC0912D5EA27AFEACE739FCF66F489EC6355A3318F79649881CD6C7E96A881ECC4FF6934C3D10D99F1DFD00592CB037749B025BD4BC2832E206C1407E600FC2170C0BB57E5C7AF0756830C2A6913E2B9C60575CD4A394F2A65C50E40A43CF5EBCA6A8A32335707DDF4633BAC7375DD53E24DF20AF30203B514D3793392E38FA8429B050F58B28CAD0146F385809CC7FAEFF8B71B2BC93D2C6F72E31AE2D07CBB3CB7F43540894E01654EDC71CCF4F361A847EC5B1D23C2D4680E29F0E1F992EDA3AC41ECFE614FC010A2EED1BAD87A7D17468D6FA5356EDB25E9008A9BB328225F85202246816E1A542E1DD746A5FD3E064FAA1248579D31CD3D65F8FFF36F782622402DB328C7850D82D8D8A52B897353A2F8B95624D2D958FC1C3AE6466EACCA2A6A5E6ADD4A582D27E07633CCF697FA02E243A4FBB3DC727B718B5AC0FA6AAB217E241627E69CA46F05ED6B496A739A29EDAEEF76992A507130715BE555C68A7EEAD6E8FF3A378D8F4B7BAFDEE3EDB9EC094440E31BBA717A9C82A117D05EDCA2370003DFABFB2EFB29510466F74E76CECCFC41709FAC4CD8EAA998357170A7A293209EB0BB83DFE5E2F6D73C28D5409C55E95068D647BEC42DB8098F0089EF8A5FC5976BAC421C37DDA6C4227BC1AE5AE229F067515CEA3D794C8D85564AF208AE0FCF836B6C0AF41477F99C8773D9DD1923C5C07E1FD508C7436EA93383797F372EF3103546A5278A4F59614A5D182344F0431D065C35620D63D4D001D7F626993241362E67D1BF41419858EECC2626537D44E2E23619381E96CFA91B3D8054681D298509D9B99E7AA99CF8742E37637B24136F8E1B487E9571E4C24AE5DF307E4C7C62E55C47132AE404B33E5367C6F24D6680BE32D20BC58370145486FD5EACBCF98EB7E7FB6293044067AF11879E91444025FE52E24617269BE192BB71BD9F95356EDBED9DF352AB56A854F9F531889A88689D3F161FE6155C6C1E8011D60A46F59C7D08C477FA652B559A80567076B4EAC29A85D54C66B35D6960DFF75A696CDB17EC9A7B74DC6C3652DAE866E8758170D055C4BF60FA1238448CC9E29160DF50160C4B0DFB36BCA40AF0BC5F7D490E7DBCA49535742EECB90098A0A0FBBBBC7AF25C0CA9BC039DFB555DD8431AF188F7C1D0FF786D627C058A0B9A15F26B58AA2A5992BC8FC5AA14025FF95F294203B45EA081E28F094D0D4AD671C885E67B2E9E800F10048158698D56648F67BFA8CC73DD5AFA15C1E48936B2596DEE34459B484336C20CD77E58BF682479F9AEF2FCDA86E4F3A2FED7046E5A3828A9B3C0DBFFC25FE699F25629A2045A51242E310CB369B730A5E81167758D7FE843261A598E4541B02D0DB4BF5616BA07A440665F7FEA6213114B6B1B38BC033D70E845445DCD18E23D34D3D6F4A52F5F904AC5D8FECA5AF1123658D09613209EE19954174A1AC7A8C7F9EA288BBE5A0705F3CE38F30ED5EE69CF5208D461EFAD51C456507C3729EB338CE15C4C253BE21E81F082B0847C6871CA0FC8B3E80115FE2BB8CD8AFAE69A3C1429D21F149B7446888BB4DCB639819EFEE665B6D6F69E61452B9328B4887A7C04E9949390980A2609A667267035B11BF862C1131533DDAFA518221627E0EE7E4009CD48E4AA9D0753A9AE82AA0257B69D569B4C53F05A75A521B327322C60398DB0947D205D2A33AE51CF2CEA8C9162DD604F8EDBE91F5199D19EFBF9896A46389E7BCBA54B4AA57CBA0D4F9DA117F288133AD01A9A9B2A824D54F74D4172BE2B1E5F0D3DE60C13AA5B668EE6A45397C2E39573EBFABAABA48D1DDB2AB6453FBBAC8DCC05349404889C7DE23A16EAFAC8D5E541457C32CDCE80CBC +pk = E7E5F228A0C97EFA8F5FF1D0189161280844372F9463C61A791746584EF00ABF773193CD9E4C2DD69D7FA8B598758C421332DC58A5C32E07397A21583593EED901211FA4FF0FDB0026AD158BD6D306F385D9F52A830363DD06934DD8ECE41BE2957DC294421A4209A3D5727E077D22B779FC2EABFC60C336D4A18604CC68CC81CE7453FFC9B500523E73622002C2EE45CE4EBF619A95499B66F3BED43B65F4B7DEE04F76CD3516378C50B38677B18151DD5F89D2DDEB577CBA481156964D44FA7044B23E84E6D4020E71748CAFC9A6D35E9DFCA032AED7BEAC3FEEC4509572552B74116459256B2CC1DC5BFAD8245EC49A299C99167643D90BDD8DEEF7CAAF0B65307F0E0B8DF36EE7E7557E3C4FE661F90D3D2DCA7D58A5E48750BA614B6204F2ABE9153BCC1D0487F0118400D9CE44FD21F3F98937B49562B3DB90813166E1ED457E851762D2C485E50A7CCBC6644B7B845FB324A224184F49B4B2964A719B1B650072ED6CE65B8D236BF4F7829C4F1F74001D4A03FB85E10B2175DD4A914078A731AAD7044D7FB5B6CD2022A42670640DE4F62D1301DEF2775FC092A5FDF86ADB36831601D38701ACC1C96706F967E464FAC00D7107F725E6D1040DE97874178BAE0BA837B5010D4CE8BD3BC11D6CAABA646E89188406DF3FA79B0060B49C83EE6D711AE198B8D41337697E1342729B06ACFDC42286BE992BC55C35C7313A020CC1CCA4D10F419E92451CBAD480B2034156B385FFCD61D1CF0904EE89D5D9358596C09B3B24B77B327E208A10BD18E32349055D8BA98D338AA826C4C9EFE964758AB18F91F14B877CB744E053938121D83722B5823825CF9E942F49DAED56DB57C52D692D0D3F8498C93BB97826D32ABB451018BCC0505413CEB6FBBE86AAB394667EC1DB49ABCBC2125E7CB88389216863003AD16E36A27A49C72093CD11CDC9ABDF4D1F5B5E9E2A17702A5D990A0536FE2011586B3564975C020DCE674BC8301088ED62046E9A0FAC899B13220597675809ED0B7AE16F0B6B2293FD239051A34AB6097BCA01DB2293D0A200DE835316E9BEC21F25886A9898BF7EABF4D71ED4C4B282EBC236AB4146E28BF2F1C2C7A0A65137C1D8ECEBC1F66F38D27D4DD23E920BF6E813CA05971FD6D936E1C97A94315D1AF21340748F66378ED842CF43D772D2B74DC895C8E922001F08B31FE57507F070229D9C7958B85A213120A150738D6CAB4AA1D89381046839CFAFE02A988F8C7D23A312F7F38A90F75D2F89752DD7C2B1334191D3DBA73255476F7879879831A09C7F3C329DFEB83DDF8C32C9780BA69377A433FB5DA4754E079744D86DC5CDFC1D4A0D31AED9101BC302ABA03702139F64EB8687742F7768301D2D1D0F1E079AA3DDAD5CDF1EB6D36DF922C6A3389C2440C7F7878A5613397790667A06EA3D3AB4FE0216571D988D185757CBC88A5ECD6934469963AAC9D340ED708CFD241CA5ADF26D2D97970D8458428852AF7573B64ADEB412CC3CAE3CF8F552420A548932964C32659D78E2FFB27DC3850780CAD25CCDB7D43D1C2FAD3E222E17052DBF78C445BBD2BFB0F8A4A5B5E6608AB1D3EFDF94709F10E43F5C5CB2DFDD23F82B3E429D552C97B6A4C5CBB9CC3190B009777644B3EF03F74189600EBFDF7DA95DC761E8D4BCE2B8125A3568AF0491CB1CF7CA711E41F9399E61620EA27B367DF03FF45F3F692F8DFCF4B75D1D09AA1608B91F7F05EC44326F0A0615D45F6574FF26634670F49E89BDFD7B8AA3F510290107463B62A457275510638BC0ADC1A5CE841367F95E6C5AAFD60F0A3656E7040A04AD881777AE7BD9B0B326A55F8CE784FF2DFE3CB8D8869718C58C5F49B6C17A62F9BB2DE855B377D9DA3FA2132B0B417DCCDB3F9DDCF88F749054C2E683465D906806346B58F7C5D14F738E03B72A180B896AF64E7FE42CDD0EC37C558F55FA9492D5D33CA12009CC572CF8E1C8AF6FFBBA77B01A77C09565DCEFE6CBE790844BB699AFBFA379B1F64087662A2FCE87EE979412A2468F460395F7E1021D1BC798F495670419FC4484833B1546F66ECCA531EA35EA193B163A4AB3B231E9E92681FCA43A6D59E21EB29C5652A4DCA46998389E6C4583A1D80A590E2A884F219AC2FE033750FC630D8090FDBB70818C1A1E10A140D7A43CDD64ED53E12F4C44942637E015C413B804C11BB287A00717A5A5B6D59EC9E61E38DCF4CC165C628C64052FF2C493BD303C37309DF44C7CBB65D84CCA5D68C8CAF69E6CD994793987786AE7649D081A7F711E286CA8FB1F783F09A23D82270F081A3DE9D1188FF4F5BBF7CB0D2FF9B83BA21B3F59F56968E80E9C40E8D59A7C0463CBBDF187BB7F8E49DE9EF0BD564EDAFA6BF4488ED6C7524BB6BA7762C408AAB5B944AA65C50225BF88DEFBCA40D491956C14DE4411D0DA435ADF33F5649857247B88EBBA86FD02BD96317D9D32DB0BB0D5D4CC844F248B5BCCC65A9CB879AA5DBDF52F57103F636865D77F674DD2D857C42C296A247E0A777635D60AE24E957C6140FFE8E9DB1B807CBF586BCA849271A359565F2506EE38C4557E74931C1DD37705703F44A062F2C21CE86F8A0B32DF43F1EE95AE51E0035D349DF9F488427B674523824B2C00CF23C6E2E5D77B74D3176762DA6E084F8C2B52C49C243E31385AD990BCE93AF73E2566162BE6C47531DD60EEC02236A4CA255E28C62270C7F536F7FB12D68E1391B5E1CDC6FB2EF415E639CF515567120CFF7351AAED29FCA3E24613B8 +sk = E7E5F228A0C97EFA8F5FF1D0189161280844372F9463C61A791746584EF00ABF77969868262073274A98683BDA2F0E3FE6BBC814D380FE9D945CFFA5E6496428DC5C1BB6C51610C6B975D7D49E32172130A80AAD222260B15B8EC0FE62B5523A536AD077A1844176551C18208D18E2D87D3DB1881482997C3D51D897C02EF6FC44236888313545553411156060610600770537343268526616652151876083267358445153437818466817454325381500763361530127350823877068212003223324767172682554865337832540353583448007318320278784831632646727568111726414552745277387886782267244045236173007345550840713463526008067602713210655668744144224074063340115764504188582444106307864873765162041701533186500658776632455665136121163034248843164433835610368212413456662328462260153845451367545030074463036842040227300761267874118820187176558354374571848683870457351618041164304368830571114647820788622832374641833008760011214433463323332484761671115165853410026857476001412664837501344675713710733610132366525052065835567468804833715041182841045537063584637642257443311542335102822834737188088230274450541052325224346484851386503310573023258768315201142354128316060587624800160405461004153804418222251364034603380116276083631126246220734365301240262881868300334035424318067558543031873325344573317375388507550210208638301800540312148857273275554577838573116038354572068773118812303185658222684232306751084243585282077300375063537472522007182007647666446313877683020767200653213767023081158712248818650713778682415052072530143112046786618661735202626246880628526708775176640537235812000372717010134814766338362475530068577012883720174662055712251410752503008543841178306670517307106122473074885107401163808786234036535082621111535438376613750006706528827553715664613061222525123088848157728438383867650560140724572868265024816843061021775534855463502386545460271426622381876018702862851605041545245173360461267646505036803004044843148536864443331462104833017862568241203086727600088544231830438138140545106400318057284172250844844846438655626725651823407872662254543055146757713467222167257432214776465460202411280032386582115217625828255188640708127455688410536024204348615002512458058610867586814553742833321730504053730524725030162007161156835306168152834330406074071625271138173651655007668330762618411075464657287113320828683224652375434153727386622407111267858258057071660375823853052734818177300003477167575461680217821451355717778862822774847748340364378806656534514467015724103756811456878168718015322105234232028466706762615381033228507853438174635723284080265016441743611788375681606761276180023160750873155628774423130105848684400556431647376867272656780826238516033828053627843010763673232675552158073260788041034272544464007383211803052823200648031273343445054460350150188434681231560400485012425085875740381300413217588278011144387237037008558172216302607227881363801750570486624525618010070843133427023742083276488107106032136218208701275260253852602401318631315700056588813587618301821654060018676128765516040454848452555050514787410036634633475480783161214832272843770134551362606688000643543087050115126605016326012223777064621447223086055845251822474121483946D10645944656F705C729D09624CEF90DEC7232311C6A42763F96A288D2FA3375D95C499B520C1013AAF5F22FCB8EB2263AECCF7287DD4BEF52A1BB9ABE6BD9F20095BDE8070D33A12F95D870EC0AB946F3974A6DACAF8868C7B60436DD24F144CF788222A1EC7E67FE89044E01167F7541255C2EA8BA1A2767C515C3A42CC8836EA65110E81CB862C182B14F14D9436C15B829DD8D2E0234B42266D7BF269A6F8453F72E07733047BFC32B3A25D698B276A59DBAC29FCA012F94F3B0A356338A79F73BA9F25E17EBB0B8DAA63105C2EC17C2E0E4A712B9670D475E153867AD36E7300EAFED932AC2B8D800BF07FFBF5DF8718F1248F356AD21F9AF0D372EC19E10388E5EFC4DAE88117C749245451BC487FB3CE9C11CF00048A2E5ED6D737254F5A7FC600579B937EB241517182B9938503B8A3BC506DF421880530C6F1FBCF30E7628A944B8E5A98091555C0E06C90440A128DFA2DFAC05F9978F22017E28B62B334BA38A77DA3689A7FA0AD4ABB16699CDED1EBB49346C8E06F0F56A09EEE30C24D59399BDF7A5C1E317811D1DB601201FB47F1A4C7A26B0B685A760CC11532A0C71D3026F3E861CC63671906FB45E6848DE94C495E65C49B662F358A090B0A3366D7BD88F5D5D0F24265684BB9DAAE1CF493DE9CFDBF1FE1EEDA9C8ED23A7D0C8942F5CA666BC6DFDD79B6D35E56911EB0D7D3B7A7AC1FB6F9A648BDF3F1A49BE75871B0BCD1BA294B746A4ADCB56CAC166A1712F28D5B27EDA4E4541D17853BF2AA00B5B74C3EB63E9450FD6642F0F905A7F054D409BAB564FF11E9754F7EFADF832EAB1A4BFECD3730369E2A6A82FB08AA9A0B48E3EF9F3465947F3174C768E8B2E46F20B5DEC94190DF7CA0FE93CF5E25BBFBE91DE7E14BD814809F4CFED88129C9C100DB69BC7EC999C3CC20459D6FCBD6BA3C6850AE3471C18EBEC62454AF6985F40FD4373B4C46D01B8C1E7115841E7E70B9EC77929D7D1E8F0B3E7EE1D63204BFC1669F004840EDC931C0890ED4D5CF0D601B3555BEB40869F77F0C00A5D0593824BCAAF24D3274131E2F028CA6398F4B1FC21A27116C76014768DA9FEB4EB8355EE2B64B2BAC9F8C7A12AFD8079B11CAE0C3F0E9A97A4944B8B73244E17520C88F9CBCED4E5EE5531F0128376B89B791189200F0FF761FBC39DEDA12B5A337E0968044CC9CCB83FDEAD0754B340E0EC51DFF3DF0DA5B26C3B72DF8866E76F525B986CCE74DDFE4DA3D5AA3C8B9D96C00A88F5F2EF34AC60C1C092F7E822C135CA88B02B19896BAB6CC4D692CD54DEF9BEECEFCF4CA8D24FD7D065A29DA4264A99C498C76849E48FB38F67F3923908167C29593D3F6DA82B608CF9B1C79265D57045FC716D892E5EFECA419C6FFC5B4882B3706D753AEBB19EBA21B853022076998DF39FAC0F012A968B5D76D79DA16386A75BC5206330631B384910EADFA072750E2B59EEC62191D9E056B441E9715B42D1A41F04305D58175DEAC7D862996F989FDF2217761BC0AC5C69F4A44D208A6386747082AE74722032D73A6A4EEA9FC219340086E74AE22A1861B64657334EF81832BDB9D0EF24A7BB001780D3FC575DD6017530D57E2DDC1FD9B84D751A16B43ED464099CDC7A31FE7B3231B542D119FD74B9C4997C1524EDA8DAEA519892B6327A0C352FEFD068F9EFE0F8ED883E2AE2237943AC3C6CBFF96D4863924E34582AA78C597186658E253E0AF03BCB965F323C2D9036BE6AF51E384F38A24E9B26C9B52462B143F044F624A477C1C8816264A7289D4B7763FABDB75FDF939935D852EEAEE5D644B7A0B534AA4C0DF576FA7C944C94C96E56CE66210189656A7036255A2DC64F63C4D6E60AF841817C185D4692AF2A0661E72E74EFB033AFC19E0A47A16108E7B6A6562C63452398014F339891F6BC1CE6E2895089E2557102436E8443812128D61FE3953C52DF6381DFF59F38BD25A2ACDB998936D9B851A58779639F92657DDD5C9AB8625BBF90E93100AB0569E087BC6CCD2177F85E1BF378AB058C6056AB1354662B42B97BFFA4E0BA01291C5AD16333D7E86D382CB6C6598C5BD18CFFA82BFB83387B802B3058B6678C7A80728F3C5D9F6943452E751053E6F7706B6684BE1D0BF1220FCAEA45633BA68F9E4DF6D719269558A069D5F67B2D8461F713430A51839931D2E91EFC6E6E2C33421096C7DC4F6165E1A7E52B15C756414A6091CC0ECCF3B40BA0388BCE1CBA3162FA16768CD1C5F1C35558F2DF1D17073CDF96D1FA34DAA1A7D4BA8BAC079CE1BA9957738E39224C0F266CAF8B9EEB2CAD1576FD4144FF325D1CB7AF1523F095F99E67B7A540FCC3FDCD1C8EFDB56AC4993F27AB2CEC28ACCDF754C03406F8E9D641854AFC5D43BC2323923BE22083501A073A38DC19EFECC94CB87B044E6E70BCB8337F1BC45B88AA08A7DAA86007097B4DFB2832F6A41CA15FEDEA8B34F9DB32F14D92AB397F5D16AA20F9CBC954BD4F5788AAA0B9DA3C6BDCA001675DCF8E25980E1BE53DA6A464C9C41611A5F842EE8B6104D87D6FD2E79B36481282558C1D3AAFB250D7B5E6FA70661E3B74B60F6B9A62E85335772590EEB75A970D30257584EA9C5CC19FE2DFECB70D6DF5064A60971066E79C62FDD769F6148C4E7FD6873DDFC76D56715B6C62FB6771F4C71B4A67F8EE3EC77F926E06396DFD8BEE157658CCC142F3CE2233C8C6FA9A4A48601774FD33EADC380B121AF28900504B411BA043212E65C0EA37872374D57E728D257073C73E04F33067EA35E72086DE4D2480FD3DBF80D3A35A254A6B5D55EFB2AE0C9F4D801F43CA2A01B4B2DE089F98B967D635D6927D0F3213BCF8F2C6D9C17D74CC12803FFAA9770B3544FA0E234B4DDFA696AC49086376FA8051BDD0048A985F756DEBE0727319A7337986DB161C49D87F3B26E0992DED51CE3037D6122AC2E2D5CB7B4C352C3EB847646B4F5ECD57642C0446FF946425A87608487BB706C3BC05B5DA67B5011A6F193150BEBB924ED5E7C4DECD6514C249E6EC8246958CDA4EE1D06F11281E01D901E4710082CA111B6B9340F8AA0A86F133B92B515B801B500C3CB20A0703CC50D2C7B35BA408E5B69DAFD7C2F9D7F4DC0E7D90B2F267573AE7DEDA29D6F75B57BF6ECCB8BFF47E3422AC510533C59D865C8D7D988F14188FB13E6AA12FD5FB612F59C0C509D84D49C454BAE3B077FC512AC77C5CEFB61214A941DB9869B5B079C2F79E78024C11BBDEA4A4746229FD1F8EB7917B09052C39F62FC5F9163705303510A3FAFF6134130539E18B86EE00A0727A50B59E325B3A52D63B1054416B4ACB8B52429F002E819AFD596C2DA77E70F5E8E40E56BFCBB0A58FB7E71525B3136E6F7AF9704E8987A1597E66ECEFDB7D066EBD42CA0C0AF3A0707DDC5D266262E4C6B77A560A556A2CF2F491F61F6B6A12CD6588E99D69820EFE5A7A63FA4FAE38948E3A6A88A04123C9FCDEF6C0569D574BE9CCE63CAE99F8C04F6EC1B1C42FF58B604549E4098679162C8187BE80BD000D9806E26B5C52FEF96EB18 +smlen = 5949 +sm = 4AFD3CE39CDD2A16064DBB6A514D914BCB3133E373549A8B4EF8CA9C827292C65EC872662F87DCB9680B3E88930C05BF6EAE5EC30E7B4E31180C0F7489759C3D4650247AC4B7026C39F20BB1CA6A014955DE6DC6A18101C2CCF351E58C953B2F7D6E780FBA8145C5DB0FB3F4D969C65B605439925081FC8E75E067EE226478C86C2B666C5DF00AC87A754262E4FC50978FC4608E2690DFC778DEFD10567542E0BB94A75F9F033601157E89E51AEB397C7EE60408D14E55E3951CCF3A51E338345E6F72AA6D3EAFD27AF0054F0BD180891CF0F96CD9F59EEADFB0458A1CC0A90D11A70358D35D82FD32EF7D5F7F240AE39244039F554A8E34A7B3F71471538883B76A961E0DADBAAA21517B1F528B22F2612A221687CEE4B0EE067CCA1A1D585BFF0FB75F46C3F827A5F4546896BDBC650311C31567F071E061F0D33BD0A561B226359AACCDBB0B12D4617FB82EA6190837BA9E4C136B88384742AA74738458EB89DCCA535518CC82D4BA17D18AF6736DFD5D9715B761C5602E162904C824198D363E1B0C4CE51B30B98273F2DF044A6BCC3945647C937ADC52FFF69E1BCE18B25F8F7FBC9ED4518B27C96299BFCD832A2FBE36C8345994B01E4957E31DDCF09BED8C61822CF21AF50BA8EADA4FDB20620DE62106C0CFF0A329AD527279D3466A5E2508D04393D8302F959A9932FE0A10FB1D434E6B8C9B8975DE9BFC964149F3832CDECE372F0972C3813E62B9922509287649AEE4A1771540389E7CBB77E5DD979FD0AD36A2D6DF70265AFE931512CAD87BE171D7429F7F0707A4E15441CD9EA1EE9C62778526A2C56B2DB684DE57F8522A5948E41A09BF52C5FE3D57E1E04F18AAF461477BF8593614D9FB27B42B7BB3EAE08024B0F1A8EDF92387B86DB468E31D86E453AF50480D76429C184CD4ECA3A44B418D529178EE50A837D2AC0E48BE5F12BDA7F6ACFC97C13518F9C5DD99795187181CEF5BDA7ECE718D494A2EB3C841F5624BE3D812BDAD6386ADDE90E3B31B015C2382943FB159DE0AB3A7B105207063322DEFE77451D81FE22DCB1EBAACB6FB1766122A6F56C0976F4E48AB3CF8A5BE5197DD51EE655A88368A61A3C160359111CA0BD1DEEBF2AAD7283C0C3EB35A5479F389BF39F7BE7569D99938B7DA28D493CD545A57A50572B685554AD0ADE4A22C9DD647FFC8EF32E619E93EF75B46FA9271D2AF8D1497F36FDDC8122C85A5C853562543DB36F3AB2C1D32808185D99DA61E8AF18925967AB4F0A36F9972538A1B2DAD6A1AD42412453B21E28E61D2CD1B99D943C8E156D03262949A48746327CECCFC313E1B5EBDB972EA6184D297C3FEF358015D2C98022950AB48294555CBBC61BA81EF48D16BD856693B0652774E8F28548CDB1C18466D64F6A57FB84E90A99518B0E2D510A8AB10ECD13DF890DDAAA82EB92F6E743666654DD79A07986DFDDE3BDC809AD68947B97F5D49BB67286550820B79825EE55952ED4DE158689FDE2AB3669CB287FE7AE695905BC54B62CF1ED174D7D1DE0BF1F3CC71A6EFC418614E192D4CF4D298C9F2EF445C792EBA8002C248B636CA6E23EB7769D8117977B41F60D0D02B2481A9023ED7688B89CBAC077FDC912169C9F4C8326F2755545247913F5DD75BD476FB550CF9C0916DCC3175B6452A79D980E3C2F2B8CA30E4272892C1ECBBD23B0EC3CB95ACDD9B3962389798BEA8B2820F5D4617D4F13E7A40BD2A97B894CD865EFDC474FAA262F0D0244CF26B47250C27A846BF52692A4907130923E8FB5A42A1B3E077FD1040E6272894DD434945CBCB1D48A1DEB8DCCEC93C9B49FB312D1DDBFC30E06E6E29D9BCD1FB6F8F6D4FC4970303A96BF29D5414A685E1BF7FEE6D33DBD145003AE469DF9478B67C6998DF6A0A101322844AAB9B0F26600065BE590C2F5CB5DABCF86BB041C6ABECC9474431F7CCD278B10F3256167BA47D8CA9F69EF2B9A84973E17A58DD9B4C0B045FA75F8948FE670FC2AA8DC155B88D40408057E2D8C7F84A574A1EE1A1AABC144A4BEF8045CC5463A3AE85314462620321AEDDEEF011FA0BEE04BC176684F086F74E66AA128F8C8BF9671B48748C8A39AC68558A69D40558954A2704CFA46712F869CABE74B18E00C6FE57BCCA08A436722FBB142BA66DB99B4BC0D9AA2C630715416A7C829640DF4E9BAB95C760FFDC25DF32BD8E558AC950B8DDF73C7504F78FAE50D9BC468FEC83520C69BA28AE0D605B32A276FDE20C98D761355E37136EBDBEDE4EA251A1E2EF4674A54FAB6F308FD3C6B2959F8C038D59FD5BBFB98746EAD0427D1C98437593B18E776AD1C0AA40BC3C662998F9F869CE8F0C97D7604B57402751190375280194167C5BF73455676143E0F391F2AD0E01BF7690F6C47EE445CC455E8BCCFE4E73495B6A41AE20431EA0201F8C7D9338DABCD8AEC261E5138DC67BBECA74FCB34724DCEDCF2412B0B4488FC673CF8FFD3DF1EA90D3B38839F70523B9DF4E0F16E51B4A5646DC33CA7CC1601241E3A92FEFC6F19B31EEE55E6BE20C81C9890B6F216CFD72F69A66E8A0B6B67756BA72C6D7B825AD70CF83607CB29F6C8BA298883A3580133751267C5585CDEAF56328FD6B5A86DAF899DB1A405EF43D4A471C5F044FF517E97D43BD9E4E8CE56367594DA4A618B35D849A27FE425FB928BE2E97CBFF9F5A7465A742EEE325D8D97631FED79582F2122F386765D622B5040031C9E34E50FF62F47F1B0548E58B2DF20D1BCAFD6F766893ADC4AC70C5DA43FDDD351C9D4D81F879936BE1FAEA1610DC65E9C2AD5A9D66879EB446D5F70C64B6A18D67091E464B04BCEF9817263D357CC3E945FAF19E9A52578249A62B68D17D6804454435DC6DAB31916E30AC8448A24AE924126C9C23E98D2FE3B826A42F0CBE3C3CF34E16A97E4F21F6C9DBC20C1FA85F347970ABA2ACFB3C019AF6D92BC50E4957580578070C08F062FB981D94FBEAFC9E499D62B89B8DA709CD04D411DA1F635B9E1F948B36F3FD1F81B7F7359644D6E5AE380D6214CD1AFE8F4C62C5783B892919BE3A9EA4EB22243B9BEFAD571A833C972FDC6B6D71319995D9A33E89C5C3911F47DBFB83DBBD9B4E2CE36D161A9F8377B66E27B9F2B39303C0EFC85D58647D51AEFCDA5BA4A94A15C3A0A87F2FC9C4157F1956A70E663BD0FB1A447E1847174E5D8F2DB70DE8CC732439795688FC7388C921D9191DAB53CD04EA91CAA9C5FF0CC43CB7B17FE07F02D246B341A264174BD9257CF4ECA2E055E11FDC1B5EC4E4A68A3A3734B86C3C6348E22D5F4D029B6DB830E06892AF86BA3DA56839B07529D4B11BC73481D1060563A4BFEF737961584983361F014ED396003B3AFA08E5882AF63D3A06975D57F218348F3A12DCAAA24A8154BD1029965217FCB2D1D95AF166CFC0F8E0ECABA43D23CCE15266D273AE5A7C5DD765B737519B757127FDC915D52570B81E060DE8A3F2FAFA4E71F5D09DC96F1747AE2BCA12ECD578438E6026AB945DF4FDDE2C6DB6B82AF79CE901456EA3A17F01F87320D61D3D442471D80B2EADED68161C8ED7464C59AEAD7D274DD25628FFD77D057908D71F7601846E1C9B353B29EB0148BD44E900D1BFA89415836492BEB01B41173461140F9DC9713D9F6C8388CFE93437EC1722F1410C665B6C6AF9B83ED2DEDF9CB998B95248E085BD1EE74CA8230F16ECADC7881E7B818A620687B3D31EBFF07714F203D6C9B07C74D5F92D99264D3B9C3DC457DD282B65EE18B86CB6761953CD889FD2DC799AA183CCF429D21FCDF3D76BD297DC0692D5CAD7C04D50A8F7ADCCAF9EDB6DA432591EC5085DCF8FBDA17E0E77E1D87E43C501A61434A48DCB62841EE61BB9B1875056544B821943AAA0459450BFA9F5A2334A4AEE06FA3A0792D3BA67F0D3F26313BC4F076BF31EB1DCC43D90BB7D9C380E28F0CE08D32B768549501F0D980D91E56D47DE75AB139B31E54492018620ABE1A4B01DF664C5BE09F4173EC441C3D25278E9DE702568BCD1168193AF42EF61977E723D0742396FEFE9A151947050F010186392BA24F5B39259EB658067C6977C6AF2518B45C5E6503AEA18010B8A67CA4CB535FBAB7AF1D0FAF798E8FA486EB6D1CF533ADDE91A146EAB3F767FCE2F5C22E399E6D25CAEA34C1CA2FA379E9128B8328EFFC8A3B5E756B6DCF41FFCC8F8CCEEA843BCBA66D5EF621817DABB786AF49731E6FCE3AEABB5F0CC063C952136877B047A5565840F5D1DCF1DB988CD8DE92F2DEC807D059BE06D495EA7428053E3A4BAF58F2EBB0844E4C07B77B361BB4B9FC601FAC8E82F175A324EB4ADDC46D74F867C728211ABF2ED78C4D45FA86E7D8E2055241E60BE97E67D3DF31330A6753046F90E7B59F426967F2FEE0B8E89CE9605B1A10359376956CABEB00F537FD521BC8404EED884CBAE19D5CB650E4F3590193552A28AB081BD674FE30833447103C766CD9FF74E7FD63BD6565B64A7286D10B46B000410C9820F13AB65D2A75EDB2D264C925366992F11D2DADBE276ECF4A012629E7AA4E84FB3B3DC66D5FC364EF18AEA29BF120D3E0CD586BA19F404FBB2CB9B387E959539E3134844B7597D46607BEE048D2C91194208829E8CBABDD7384E6783B909284456617789E8039CDC151D223C56A2C30000000000000000000000000000000000000000000000000000000001040911141B2447D338BF1A375B66B77FB96CBE7742508B57DFF4D33A368EBB8451C2C67B980D3576E6588D8678B285EF288A8B5C9C2726C4A550E764E47FFFA2A128533A7653E480288447509E10013AE1944FFFAFBD9E2BACA0B3C7069C07A4186C056FD3857CADDADD5F891512DAEEB26865F5C89FFA63A64C85A08E41EBE7BD8786A8ADD571A4267D5A9E426840A0B988E197A09F3770B5B0D80D65515CD4D8390AF40E6150062DC4B8661A8238F232692C152C97B8CD5BFE7B5AD863DC92D99744D769087B3EDD81D2E475F5CF0224B10CDE6FAE8DFC3519EFDBE66805AD4468D84D3DD93430363677360DA8F56CB58A6B775FF6417C1F324380B15C9BA668EB0F25FC2A690B483E856F3327B2D79FA6259E30D7F76199CFD21152B7C6FFC3FC113F70D3930C08B3C1EB1BF25C100C5A930EEC2C52664F092B89614943D9D85ED86A2EF666A94F9826C3D116A2BBE49443E2C11748C977716381D9463DA8D09612B80A6760E5A6FC5F59425EAAAD6C8342C1EA4BEEDD5D73151CE213C0B155286FF22CD28E3BB88E0CEE39CB859900D1E0FC19F6A7237BDA8E51476F4844A316752FB347492A928EEB07AA39ABDCC0164D1921B61352ED4AC94B82C410A56505633BAD53A3E649ACAF64C43C1ACFCD4715FC594AF6FB9E85B0B7DDD6E8621BD12A2BEE48223A97EC8502C16B550B03087B6E87C1A860D36322064F8FEBC52F2B7C31DAE7430870259BDAA5889852E3AE6F61013F5AD0D38727CF9D90C67BD7BB3B82D303C6C35383ED86FD5B7DDEC824EA198EF780BE830A1F2679D24EA6E2FEEFB979563F511D188F409F0CFD0050FD418414D01E46DB3D23B3A90B24F4E96EDD4F863BFB333D6A826D29EED167738BBE22C516C59FDF81B032BB55473A5EA2A1DEFE71C95A1EEB5C028435AD0379896CBBC76877501B054CF1FD2F6D7A9DECCD70D0C07111147EF568DCE514DE96EED61600029C8D103B31C8B344A700DE630276BA2C5633419C59E66577659538A6381E45584C7E1D6ED978AB0AF89067AC83BB70DEB6F2C58E339A5A66176A54D985DA6E02002948C62BE6F12314240FE18B09AACBCE82EA462586B8316C3E0AEA00F9998922F8D956120E53B4178223F4D2934A20976FD5A72027C8F4CB33E9BBCC0ABD15395151266B6CD5B4A9E2FC1725D8E9AB2CBDA47B507BB25AC995EDD51EBDA5FD19CAF68FAD8EAC57CB5EF0C6FC861A73E64648EE3255DB4C3394438F49377CC4AC2FCE1B6BC812E5D282F122678713C6C6D452A33C632C0AA47686588752D72B0586FE5EC2464A6DB40662FD2106A19F67DCCC45692FCA03685251D512642B0CEE436C78D94C6F5F25BBCB41FC7E5B1AECD52B846A0B70EAC93579603E9870F942AD4C1CFC9D49B1132777C6F1C184C1537178E5029067257A2DA2827A2EC44D323D13DC6E4E1B9EDF5949D4324228687FD54F02CCC3C4DDA635FA546A5A6783959B1C48AA9D9C9F6381EBCCD979253460857D3CB1C70893EE6F04709E35923883EE3C71C7F33B8CC28B9136B3EBE5F52B9A76817F2F74FDC2F12B459DFF32D5A295BE374B3FE507A0995BCACF1E7B24F4501B29F1E8B4F2A8CB394B3E459A4296F6439BA59EC88305AB045FF40B1DAB4F672F878DE1F9E46B9326CB3E2F3457B83EAD8DEC28DD079AF0E984A69ED882E1CF21036578485DFC2DEBC9CFE82FCE0383B4039D147C4C7E31E315FB57B9093DAA811F4EE4568E32E5625ABE76C5A1AE42A03441DBE766D0EF4DF607406F7D489275E8C5D4470866F9049A4AD5C428B843DEC3702E86E177E4B60181D2B5F099BEBCB25F04C93D087C72436E87A9B3AFCE78FA31E2B892400B5C1071F8AE0F78EF6F7D71859A97C17EC0912D5EA27AFEACE739FCF66F489EC6355A3318F79649881CD6C7E96A881ECC4FF6934C3D10D99F1DFD00592CB037749B025BD4BC2832E206C1407E600FC2170C0BB57E5C7AF0756830C2A6913E2B9C60575CD4A394F2A65C50E40A43CF5EBCA6A8A32335707DDF4633BAC7375DD53E24DF20AF30203B514D3793392E38FA8429B050F58B28CAD0146F385809CC7FAEFF8B71B2BC93D2C6F72E31AE2D07CBB3CB7F43540894E01654EDC71CCF4F361A847EC5B1D23C2D4680E29F0E1F992EDA3AC41ECFE614FC010A2EED1BAD87A7D17468D6FA5356EDB25E9008A9BB328225F85202246816E1A542E1DD746A5FD3E064FAA1248579D31CD3D65F8FFF36F782622402DB328C7850D82D8D8A52B897353A2F8B95624D2D958FC1C3AE6466EACCA2A6A5E6ADD4A582D27E07633CCF697FA02E243A4FBB3DC727B718B5AC0FA6AAB217E241627E69CA46F05ED6B496A739A29EDAEEF76992A507130715BE555C68A7EEAD6E8FF3A378D8F4B7BAFDEE3EDB9EC094440E31BBA717A9C82A117D05EDCA2370003DFABFB2EFB29510466F74E76CECCFC41709FAC4CD8EAA998357170A7A293209EB0BB83DFE5E2F6D73C28D5409C55E95068D647BEC42DB8098F0089EF8A5FC5976BAC421C37DDA6C4227BC1AE5AE229F067515CEA3D794C8D85564AF208AE0FCF836B6C0AF41477F99C8773D9DD1923C5C07E1FD508C7436EA93383797F372EF3103546A5278A4F59614A5D182344F0431D065C35620D63D4D001D7F626993241362E67D1BF41419858EECC2626537D44E2E23619381E96CFA91B3D8054681D298509D9B99E7AA99CF8742E37637B24136F8E1B487E9571E4C24AE5DF307E4C7C62E55C47132AE404B33E5367C6F24D6680BE32D20BC58370145486FD5EACBCF98EB7E7FB6293044067AF11879E91444025FE52E24617269BE192BB71BD9F95356EDBED9DF352AB56A854F9F531889A88689D3F161FE6155C6C1E8011D60A46F59C7D08C477FA652B559A80567076B4EAC29A85D54C66B35D6960DFF75A696CDB17EC9A7B74DC6C3652DAE866E8758170D055C4BF60FA1238448CC9E29160DF50160C4B0DFB36BCA40AF0BC5F7D490E7DBCA49535742EECB90098A0A0FBBBBC7AF25C0CA9BC039DFB555DD8431AF188F7C1D0FF786D627C058A0B9A15F26B58AA2A5992BC8FC5AA14025FF95F294203B45EA081E28F094D0D4AD671C885E67B2E9E800F10048158698D56648F67BFA8CC73DD5AFA15C1E48936B2596DEE34459B484336C20CD77E58BF682479F9AEF2FCDA86E4F3A2FED7046E5A3828A9B3C0DBFFC25FE699F25629A2045A51242E310CB369B730A5E81167758D7FE843261A598E4541B02D0DB4BF5616BA07A440665F7FEA6213114B6B1B38BC033D70E845445DCD18E23D34D3D6F4A52F5F904AC5D8FECA5AF1123658D09613209EE19954174A1AC7A8C7F9EA288BBE5A0705F3CE38F30ED5EE69CF5208D461EFAD51C456507C3729EB338CE15C4C253BE21E81F082B0847C6871CA0FC8B3E80115FE2BB8CD8AFAE69A3C1429D21F149B7446888BB4DCB639819EFEE665B6D6F69E61452B9328B4887A7C04E9949390980A2609A667267035B11BF862C1131533DDAFA518221627E0EE7E4009CD48E4AA9D0753A9AE82AA0257B69D569B4C53F05A75A521B327322C60398DB0947D205D2A33AE51CF2CEA8C9162DD604F8EDBE91F5199D19EFBF9896A46389E7BCBA54B4AA57CBA0D4F9DA117F288133AD01A9A9B2A824D54F74D4172BE2B1E5F0D3DE60C13AA5B668EE6A45397C2E39573EBFABAABA48D1DDB2AB6453FBBAC8DCC05349404889C7DE23A16EAFAC8D5E541457C32CDCE80CBC + +count = 80 +seed = 07CD8F8AB7CD12EA7CC94103B8623D6F0FEA2BAFD2325BF6089DF5351BDBB9A94525C3C6B72D3820F2E4D5F9E7C849F8 +mlen = 2673 +msg = AAFA792BFF719A3B794B2F8198EBD1556889C8C61EE6A51470AC9B274CB162AF44A26E2BA5EA7663C4C78B4B66B322ECACA8F2EBB6A610B51D7C4399F4A64A870C038797CAC80F709CA5C3C9FAFF7D797963E60983B584130C1B99328AADB2D261217CB95A535B8518A78A6D2F6CB8400C2AAA2DAF451391F7B8AB0277A3AF88E1CE6F1D3DBC386CBAFF15308F073D29838692E645F566D4B3DB4186C259BC84606855EA88938CEC4F7211BC9B461E39DFBB9E44CBC273E02D4314A037E0A26D60985EF5A35F069D8B51F86E9B6801CA067AB75565D73581EBBBBD98ECB5AF47509C8729D82EA0B35F0A376EBE6D90108CD61FBD0CEC966C17264F6A87864457F41162FF7210049E6CE2B5354F8F19161E0866D6BC3935815D9267C600DC529521FD092B126EC440D49B8E3A166587657B52AE9E2923644F72876EE94A61D2DB0EF4DAB33ABEC0C47A6A725D4CDABD06D4F6A30BD7C90DB3778C17B7D8CE82A5123B798D8B47C7F3E968C9E9F82A6EB3C2BDD8FC06D282F5CBF3050F6FF71E2EDF7A109F23AB47F427BD75163162C37722BF70A6BBEBEBE8FD9C39152AFEB78C37D718014F739F20BAAD1597B1F9C4E0B59FD82B834D83DAFFC935DE4A3272D7C2454508C07502943E90FDB56128D6E6009ED09CE80A9B60D51AA2E4E162F7F0C362F6886BBCABE29EF6C7F38B742000B9D152FF709082FAFE809C5DC9BCBC6F300B0A7840D0D36F39567D14D8227E7145F7CA670EFE917E0F18B0570DA3E05DDE56883FF12BC0C76C2A1E9FEFFBB728D991769B7D0B0D34853C76FC0655AE200501C28755F57934BB9F46A3C6AB1DD8E0161C698133F4F2D7CAF3392576B4BD2B6F8735D80BCF60656E132442BB7FCFDAE160A2DFE3F3FB8209B5C933201785A7E8206096B84A222A68E62501846273F6A9145820F87F450D12C64FF79A843E897C8394AD54AAF4F3B886FB00A6C37B2EFD0F6D4DD639C9989E7CA30E4F12EEF440946B61D7A28904E1D74009B6D1AEDF2FDA8B5991CB37795A8EE51BBDAAEA34A4C7040944761B9B4B4C12F455C536992A0852F7F07A9AEDA8E522591CB4831B0C79FA977AB6BC49C9730186855986035D2C6E5A6D93DA43E8825753721978AAEB433CE2F2A7D67C1FFEBFEA6F6059474D3022817A7329D9DD0E4A292302E4A57174B9C5346E4B6D75D65882CA7339A48C6E7AF776A8515014A20E4390F6B4F4A19990FA725F5A69B9C3BD4E8BBAEAE49979AC19600A3CEC6DE154985E236C3D0684269974BFC82301AC7196675F618182D7CF15EE5CE3B7ABEE0DEEA5C72F54CAFEF203D556B31327089A0C0DE94F74458CFECB481ADFE3CBB5DA422BD3626B00C4572B4C2BD7584ACD9129A76C616AAE51F944BECC4682AACAFB8E3BB1A42A6A8E5FE7BDEB43305A34A98308EF2D49EDE4F41361446A9AE4DFC1EE13D12821BE0B01E55B865B563633E5A19DFB6425CB60159C147B18A6419F5085C5D0882656ED533EEDF97674D0BABB6CF32F696DEC0F9921CB3DC9E6021FA198D554B1D83C42A0BF214FE4C0431547384F45AED9190CBCF98ED8278E8A03D551FA284C8A26218F0B0B58D99879DB98449CC99B6B399DDDAD9924E6A7EB20A0F1FDAD2F8138BDC7B445BC01503C509066B1603CDA76FE41727AB5E027DCB15032E8F66BFA84544D22C501AA6F62B02C0F8764387163CCADBF1ED7238E7F16C80E6C37AFEC2E10FFB95AB0A39784F9FCCD8AE263758ABE392727E9AD442A44738D77CB61A6B1540ADE751130489015AE5917C927232EED27BBF88481F3CA0C5ED2C31DFA943B2EAD4A8C80B4946E3C138A61BAF43A72C7A25E16874CBAE254D3F14C154F7C60CCF665B566799A01E0F769B60F73C17C840E0018C6FBC10EEDA3E35A77586B3A5936B363B2D5CB25C78A3E3AABBB84F1E64DF47F97AE1645650FE1751A724EA9BF80744D0F33DA6F313A3CC17D8F261585B62A75C167126D899219A26210DC55AB6DB2B94E6993849B4986F988EFB07478D6621CBF4B8ED772E61B0246A5582242FA20339B2D6CB89BA1B9210A318EB4697FD21EFCFD230DE9680514A442A13B29D8CB2627A6970BB97BF09C79C6ED7A27247662B25F39C8D675B0747F1A6D9EBBF7CFA7BC51A7EA3A7307EA4FA2A463BF53A645FE701FBF26628731CBC18636567AE633A49E59F6F049447803FA3D4F1F79F38026DE9B07D8610C9F01BEFB7054AA46E523E001C1EC3A4E7084DE0CCE596DC63D9C1F1DC03F35F9B1918E62ACB2640102E1D520E900969D53E83D2DBDDC80D1DC54BEE99531FAA5A8D2DBF8346C7ED123587353DD63823453DE350545C176446845BB3522A862F5D675419DA901CF7D2D1F7050ABFA3237D42753203BE251B0364379232D2D9D8642D52A60F6F4CB09EF29FA1E6069F97A1175F8447FE98A813CC182E33FFD8B8CAD93BF32A60F1A9E63A79A7F7FB9162783B89BB57F3E73155CED1D0084D5BA967F76C89C61C1A3E944F3B6F78D6CD3D1139A315C5276493481F3FFF9B6A6B40C920EEED9EFC74108C6BBA5A15DA736680A23DB5672C5A32ABDA24B49F2011F44FA8FF9C73609EC195025F0456D753C848DC6296920FC32DDE2174D37BFBCB86CF618AA0D486EE46C5E1EA14A3BAE4952AF5D4837F9B8122A19D1E59B909ACEBA6C849C8B452CD6CEF877A65FD83E6D0C6EE35886688F1D877612CB8E671D83216A1F76693D6A4D6A2EC13EB6CA2005328B3C91F51B352A707EF8180F320D6E1685C1EF4D87E3CB77FA549BC12727E59C11BDF8A9631CC272998253028CECEE8A2914182B90F586D80E7ECE370979BDE683F37123090012AB9243A4C145D6349C2791DC44E54956C5E9B59FAD017D3EA27D85B48A896671A0AC14A73B5AB9145D8BA6AEBF9EA25AC2E8E2C4D16C5009A83D0E84CEB80E95DF2CEC4CBEFC7F5B90A84D408E8C4855F9AA2987D9FC9D8A451F32B367BB1DE5271ED35EA153B5D400A6D8050EE82F519BD930245A96C9727FD24D8B94DC53D4B4F00D03172CD6B7F2BE163B6D16FD6247B01988A6EE6CE7BFEAFF78E983B8DDFBA4242730E52B57876E3719D1F9F6CBCC81620F848D23C31E3FFF7EBF2AFE5011E6466B1889E7EF6281FAF8B18A012CEB96796FCA9B28E78335DFCB85BBEAFAEBB0FA75EE2D0D391CA97E05F0FE43475135B13613206A0D88438F17EC8E604B007AFDCB9FA1378B7CB96675E0B19DC6FB02508E05A7FDAAF09297A3884AA051B6389A52F921F8FF31970FB082DF554226C2613B80CC1ADFF770024D6BF011C0F028A012597AE56F36EB6B3E864D79639810B8BA7258B18192B5CAA80DEA4B140D3C6F1D707ACD2256D676AE90980BA80E10B44109211ABA830EE96E1BBD248315C804D391A86AB7D4B3A4A37FED90D9867DA4B93FC32E79403E5D78AE99AF1CD2ACCE65D4F3384D9CEAB71B1E93B99704C64CAF17B999234361E378B9362D14BE3FD9E6C268013CB1FA2EA8361749D635C0429F796EB15A685E31DFE7A76AE870EBA120331AC830F8C486F6C0C4F07B658EBB9274A463E0EEA101481DD6B58835A303ACE802AE79EBEF51ADD98A67B7FF7968815ACF4504B9D360F7C0120A00ABA1FC558E6CBD8324EC35E0985294563A8D7ECCCCD9E3D1557A09885770836ECCC7AEE0F18B81E30F85D695440B5BCE29945CBF60FF402B281942D38EA33A4B03E9FCBBBEFAAC2C455E8A03FF3F35154132C538EA16F0605EFB788C3CA8435F6D595F776433585094ABC75BA581EC59AF701F66DD6091623E4676D167 +pk = 730EBCA946D05B5680714D3DE5C2F7E09F4B29F5929B38798F7C1DB79EC0D9179BFCE214B6BB95F84E6DBFEEF61495FCA01990BD4E58B3DC5AFFC21F621A797E9DE9FA542D7FEAB478F5A59ED1C10798394AA8A3FAAECCAC61DEE61F526FBB6C478E2C8DC0FFCD6CF1FCB5A4C716E8998AF30572AF286BDC973391BA6E0E9157970F0F43CE34A917A8F8FB7032C3AFF39C67E6E20BECE4D41135B3A14E135811BB5616EE3FD6BDDE9CFDEF65F44D2B3A79E6FF202A2C16C05814CE8B05BF4A92F461B4967E6437EE0FF54CCD40871F3E96C8E39F419D0BA8183936EDBA70596320B178C1EFA56B44B082EFD51CBA177855499811187CEDF94C96F8879F1D8E3F218B9BF01CA0BE5243B6D801263B700917E095DA443C63F285701CC9B60EB01D8D8601EA6170627AC9DCAA897F2FC1BA55C94066DF258ABC75CB47E3543A985172F7BC81E150872914B1CFB15E0C61DCBD8D045FDFB564EF40845517A8A46C74162F8A59D2084E2605B3D2B9DE0FB9367E1C2275DE0F9D0409EADAD9DCF3FFFF6B3C4E5FDC5AE5D6A688137548953EB247F8975436EA6D4677FFB08019DB4164216B5887C5303A376D55BBA1F82748895262EB7056173FAF991EF25079A2E47188AE230E2A16E54A328AD26FE5DA0D868589C5026B257510899390EB250422E79268359ADDAB4FA8D659891564A9C915E5D0B75CF6F67B5753FBB4828CC38EF749CDFABF504DA98E5C2658E28F4829227107DA6B0FF4FE361B89A39F3757E32407A26F530EADC429FA39526643E2C5FA444C444548CCAB269F814EBE06FE3107BA399CEFDA9CB10E8E607DFB30ED0085F73D6D2D36B3857DE64139FDCBD8052891C9A09D9587BCC97E5CDB4408D617446041EEE074A0A7E91703B3845878641BBBBD6191ECC5DD8BE919E4D5790435F2A01E117329B2EB0531D31339877C3CB7E70F93E29BD49EAB3444BEF856858DAE99CF0E0857CF5F3E6A932C01F4AECB27DF83CFDC6D38EC0E173C553CD0C0452D25A5A0A06DB21A874D9A3158705595235D395A9AB7707E559C6EC9F76A1A1A538EC730871FE3FBDFA8C3293102FA77CED67F4D90102681EAC268FE3D1FE637B611507AE080B0468A527B59B9827DC3AD97A137EF129021967C383B27A3C8623D0341E19E965A55BCECB26F6EC425D9EF7A979DDFEF5C496D1AC4791A8F566B66F6E04D76924D797494A40BD3E09A6106108D11E0120D149272387738D34E5865AF45FABA5F4DD2CED2EBCC66310BD75C65493E16F6FAD9BCF15120DC3EE408BCBA5B6708CDAD6C38A9E2FA834DE4932BAA37257D8E5C683C6F0D7F11DA1A09D7349CADE02CA42229177C6E803A22A8FF296FAF0D1B09B9716D4D37911E443E5339759CC93E1B2E7573BB15401885B3A3496420C39CFEC1F63B00E630B35769A48EB88B102195025A6B4839C83C31A47D2915BE3B673F394689945CA5D0AC93016824DE2FF3672BF8DDAA02EA75A1DAC188FE5DCEB341885450AB87D63A7654721D4F1A0EAFDC122D3203EF256542B72111B823E6BFA9F0E7EC8E54F94DCAD13D5F0B0FF1C081B275FFD9BF725B18F93C4DBA4038EFC3BB8488FCCB988C9E48FA47B5E0CB6E90F0FA6C1FCC6782D23EFB27191837489798546758E8F7859BF452E1482D1EFD716DF0E1CCF8033281D957DD5EEBED4CC2F55B10A9BE25A4AD4EDBADFADCDC69D31FBB9282F775A8C5E269A2BF9FEEABB8AE23DBF0D4A20CA05A725D0A68C26A2B37F8F420A7305D71AEE6765294AFC8AB6B768BF40A08349BBB44A3DEE469864E4E0E5149A026B014462FD843CF401B916D3390966EDE854373C7B8DC64EE691DDBE16FED08264F994CE5B55D26FA13013EA93FC99A58AE5623BADC730811B210DCDEB437B779C2B294C3E9151AC658162912E5A05C1944527BB503030BCAA6831E27EB0E7AFA757D97E83ADA027136D164485820ED2E84525CF32E8453AFB989EA8C74BD08C4149252FDB57C0A694AC3ACCDCEDD8983E5EE25ADFAE9F24E0E6F320513E8A898DBFFF0CB8835508780BBFF87571E67F0842DC1E67B7A5AAF9FDB1CE2E5DD7276052A5B4F0EDC264AB467B8CF73C6D1CD63FDBE5A2C8922E834FADAFD8DD1F17E802781B9430E891D8BA75E6EC9AABBB2EFEF14361960431045D84919FCD1E3C41CA763214409AC0B47132DA150F75D1F8F0B96487FDE7A06AA9397668FAA500C0CCD88600B3720BA7E793D3CC82D9F34887BA6D0A6115DFC3480E8D32A279E91A0E74EB149E7180125A6E735870E0B69833EF319FB7E2F2909E5EE10B39C25DE78E22739CD9BE19A94835101E45FADC3297F6EBC397F768BBFD509998BC8F86A30AD7F79A6E00D09B358B4AE616736684DC1E601063434BD8BE78EC26F5D37EF483890F97F5536268AF2A423546A6D16C5923B5FB22D7239D2976D9C593DBF3DF3B9D29BAA1C70058DA40432D01B8544A974B93AEE726C1791F06CB372B6A4EFEFD99511BDE115657FC4231588BE7E0E517C0CD10103650D2A670303C1657BF1DA1C73169C31EC42A5743CF9EA7A8CF317167F3E8EB381B32BD8C34848C241A3B4BBCD2DCB4DFA6A6BE27685E7A5A505E9B4A992C23D064F64691C821C53101B962786CF0A3C98D2375A8DC27A30727B0FFD2119653E2DD7CD49CF1CB143C4337C13282BC6334ACDC36D8E37A06A976BD060BEC361D011B24579D833DA4F0E637AFF31640FF058E470FFEAA1C4FA256C06FEC4C23D549B699154EC7DD922615E8C483A98 +sk = 730EBCA946D05B5680714D3DE5C2F7E09F4B29F5929B38798F7C1DB79EC0D917EEF757C2F12251A2C3FC2A99D5E29BC8460FD5C69CA2C2CE2CA2FAD0A0E87A4A3380F9A1E27BCB5A428C783BD09AD76BFD7660F5B911D1EA6EAF92020590A5538A516D3189DDC91F2B961455EE372ED20FC11AE89ED9F58E7E4F25467CCECD61151085312113053157814453315284587851413202558477483348385014624503003774531733212514525820536087847458871221728254613648343006885280747541143253852340047564352472558143225268720337317237118888801538033671002142320263466040782756623476604102124507418546827116058154082101063433466148512750361380353113173684245443082514735610468041575425756141223527037306343600801752007185278341207284585431732806246402027238036063770023635005818375325256537824023814830358451045261058162458741381244247745038131627368512403453650340161214773418646724574208254738882647036042407212167520768631583781852353630501054710382281782040414138737730376050285576167676211175625425733445255610748524138163044640055215337361656664552071574545050417111741532420263787676586210376534667316185227532164041112446125015282034546877523182567625376301076752805058630220274522502454351457056501556652380875005545558182568205066832530008168850568861828110681236583183437607031737442822501840821842425706173362064043028377756032677572637603336672534835883620656772318053646316381628400244006384188544627510377836174530643761204110177538646176516143458314522867177542786704028614331716160512085632886842237838302842035037147173488125048220772375882017335708376642173406417275365860830048212214222511704180337854860647106448424158715867012635878277215746331641268340148851685211311142352441766873834706625061582584846088516558413880711771861147131746105435528030332462314751682238643602860032885241407758335160645046487560642607131821712460458170781620400603437300438245746068624781607554155625578606862264538442615083547326038256271000332241224367222713104133573205573126805310130881148685811864884870844334155573265665641332002531380880073831210648272184065465806361587247054012800413708470667867118470174788585443268152134766835662664824353060888848847337355384733455778440174680607304078030241650748834230637500611233374372281517805667081260624652506278855028543547668622387601341016516020155857480415040642826603338208748332687525071044518745210238731748548254420303875761724875705855028488066115771516552267247341682621145805625031514585385003061781876587751178441078710727111168841748061480304688407607628477160372073368287122107725635738045234363316862726152648011327447672222368508324130562062322875342018123027822583535006337721616228835776782826671587738060234001510443335702548286353620371884156262045342571327415127522578326650615870714845184585058613874850355542423745710588736507265086526744454536778044425087023546407275038666156150542823820273374845734248686888258570463622032241565516428237558158281127782538823368748866575446717775302555344522104436746815122046130528865888425347753261675564717124206570736722556611585075874610715021312536174531256455113226552408727680381142603711744888555172482345145660855125161008404007316540020572539588EB584DD59A13C7C234D3BA0BA81B4ADAE1ABF9E06DDBD9B9B1E6EFD9F98F11A553059D4C7E923BE1B0D4703CCFA5FA0CAA60BD7E6A7AA62612BA4DA9BAD8C1503882335E5CE4AFF3BA44C50B7348B1BB1C8A9BBC2C66E295B7C4F13C537DB5F003AF8F0D111E0FBC431F4D53285A554ABFAF500CBB300B7B6CADA515BC9F937C34C1F2F3C551FA784A6ACD46B6AD7E047C185BC1750299FC857FBA8D9DFE87293B4EB039F36F390149A89E93CA7571B590C1D80AD886FAE9F9065EC6D5FE5EDC7D6B0C1D481B768D0D8F1C0620B757004422CE1B81855B3DCA5E7A5F190924F256F1F5783BFDFE8B2BA86CF0BF7941E18A9FAADC0CEBCDA7A77EE6FD49A043C6F376E9C47027475DEF9DFB3B8DE7EE36E3E138637F807D39ACCEC7FE13500530FE912F0B7156E3626F7CE7DE02E4438E2B73B1CD49095A9617D483F7B649997B8A808FBC585A9FB4FA3002EB00CB8E8A49D2DD31E76E5E57CCE1A54B63DC98C8953B9A3C87FE9D255B910689CA3BC6BEA67804C595D97C4FC3599BC220F38D0AB93871424EB0A25BC807DC88D692EE9F43B320F36828064B2B4010FA3713FE6CE520A8F813EAF2CCAA7A0C45AC5849A0216E7CBB20423CF1FE57B221FEF2EC9CBDF7C78412D4F6D1F0D481C5EFB92C53F409384AC45B9DD88B0910F64151F6BA63932F648B494632F66A4278A31855F8A047B0D618B8F043A83A20910A7E43B25C15C1D038E242F734B9A83E31FCDEC0858FA13B6F887D3AD29C8711B68FD7815585379B7E21D4A0509F71906DC038C287B3FB609A77B4F1447D1DD321A51ABED41709383E73110A87E0A21CF89872A062E67F036AB9D9D9E07A1C8D34E10B0632EF1B2A66AEED471F0F9C2CDE5EF30EB832605DB164FB79F732058C40B725BCD83BBA4A4370FDE64919AA7E62F0DE6EE92231288FE74CDC38126854B044795C9B9DCFDF2A2A48EC6FCADAF51B03D1BEFA975F65E0F9A014D6C3EB394CA552B7F2CA0A2839D316673CAFEDBF89030D3E30EDD722B3BBC40CCE8BBA37D5CDF926D4A3CEEDDBCDEEEDE817CE406D80C9918E81006F5138A3FCC654AD21372806B59F136BF30FEC6A4FF218554FE2D1259A963F0210CDB12B3E3E62A2FB1F12D12FCD2AD3667FF19A82DC2FBBE83CD30F851B26AAA346D5E2BDEB6CD8CED66215A7D04DE9B1298F2F69B4F979899C95FCE4CD3EAF8F47746F75939E5119D1CD5C58210E16197A5B10A20960BEF05FB184EAA60E4BD8CEA8C705F1A1D73D1B5EB8BDA569AA83AC1EFB4F43AF96FD9C9E13A9E63DEB3BBFC905EE1600DC254E4810AA6FDC44C9958482E3356BD91FDF0AEAC9736D2F7F1DF40572B3C9A506904313D1D9655739158225037B42F15B766BDF9FB3B74430B8D861396DEC8051A9453B5DCE39336C2EFBDAC8745039429383AB6D824A575ADB70331771D12599B9E6C55A4393D522B9DB0201AFCC7C4011178EFBA8F1DB7BB487ABD12D2FEE4F5487247CA92459625B271255DBCE7ADADF1E9994F8C60F3C9E03D2DB2F8056E023A6FD2CC6F2C560D39CE00CB4F59594EF25EDB09A708FE5494D9325C1B68061C026A42A2E9F9BCB6F2A42F46A75716B07B7C10DE53592D9E9F3FD483739275A9CE87A30842DD5E2C17CCCBD08DAE88372786EF14290DEBE1B2276FAEC120E2F3E635F9CE190D56B622302056C624780263569EE19F7AD5192870ACD193B1AF0370404B73E3BCE88525750831346096ECA8157470C596494AF12F8B6354EF7AD503C38D35C478697C4F3089C04C6599F3C97A943B7E0AF0A48085C6A08450E42137C25A76CCE463DF7ABB37A79D7732C57D7DA6088FD292452A30C704E20E4124DDAF857C1F4585ECC58AAF7BC01AF024434E06525DFEF04589E1444E437F47B51EEA649A9470B42665D650A79C3385E610505C354C5F298449D06872D44BA772C57A71BBD744BF6A2A431AAD3CE66CE1A358DDD8C492B2D5737B67274CCE5A613FF90373525E227998E3B4107D6578DD96ED7B611020C85C1445D019FAB97E7BA6C9D2DE7290A7EA75C0CCA4140C01815D8D13EE20CA23CB8EF05F74FA937B54374B9707A4ECACE2EF15B771C0BCE9CF6D569F80C8B8A1DFC442821CD75C3F829DD1AAB61B3A4D2C6274DF398169E14ABAED4946E4588A44D941B017E596FB7BE4EE55D1D65045E51102B23A9567AE61BAEE7511D9166324EDC995E81D8BA56BF1D0790E6EEE737AA75F607FDE01C92DD76BF0C8E5869D1D9C9CD8A99055C890CAF54F80044446157EC6F29CE2CC4FFBE7B9D30339718B972132462D9F7E2DD39128D76A26A41E5313767DE3B38D11362FBADCBFA34F946C986D6132922E2DA71236328265FB51CFEC1EE6C34505FF795357953277F54BB6B5B95A21ADADADF5279E5A3D294E6B6AADF19A66955DFB4A2E34FBD2C3D82C87E7260890BB11697D5499DD49C8347D1FC794F9F74B3FE6EA0A6ED6B54694F1A2C364FC7B29B35953292D107F19DEEC2842A3E45FAE06632ADD0828D9423F4708656157B43B9854AD89E1681DD99497EF7B6CD91481CE905D3C9B7D7F4CCD47F60D1F8D3D849AE2C3E403AC97C21CFF83C3DF9C978E3DBFB55C5890A35C1B6CB4FECE50FE05646ED3CA55C5EA95AE61803B18E7DC94E5CA86A7CCD1EFE43D62C86589346DE97FBBEDCA1F3EB58B83489F2E5345B600A9BEFCD6F04DCF92BADA9CABA076685CEDDA50132529D5222FA51FFE72C6CA11771F1912F1027FBFB1F3B618BA97EE73723A84FF605E556566B87DD388CAAB96ABBD21BA5641014EE13CFCD63F58019D08D7623FDA07C01FDC7065A529DB1429C43C710898EAFA1B024E008DCD1E851725A7DDCDFBC1442CF9DE89D8F9626A3EE7F0D324CF067C5E889A7430C5A11A06C8953EAC89B4766ECA39773774A2A752C28E38474E9D4393694319FAB6B23886D0A4BB9FE38201BDD5F200B7C16EFF6AB3CAA67F6C078CCBE63B3511C93EB1A8852FE4D7DA795FECDEF856D74DA140DDDEBE808B2E7EA19B305E8F8E1F65EDCA858E8B1ED5F334FDCA21D6BC528A1FEA31D20824D64565B132AA667365F4382D8A6F436CEDF8B4DC79189E4D0CA4E7E90AB6FB13739E833CEB3FFC8B6A7C810FAD7E1FB0C3DC18508E46073B01FF5989F9D5D501C4B0AB7047412D4F05B371CD23B6EC1B04E5F64AFD32C68BCDC4795B4A32AB68E7432F58992C878151F04A9AE554DF9FA1527E67149E221E22A4054A5F7738A7A0C20709DC693C2F9A518188FF36FA73BEC75D7A75847A0A7BA7278D513C77D440F9DA6A7E102231117150025CDBFEB3F0945D0D303724104072695AF01D146EE23889CA6FEEDD92A30C0EF4C8F351C177450C3A742F9035EE3A7283694C7ED3AA6ECBBFC89CDBE38D0E3C0EE98D1AAB7DECBB8EBC98163ADD7B1375433FA12C740A76C96CDA0370BD6399A66470E65E44E01125C8434CBFEB2BDCA8B91C904387DE570455576A7C4B5CCB505A96AB63D759E621CA0A4AFE8A717921A08984EF71D056B7922FAE6A5C4E369874817EED9 +smlen = 5982 +sm = EC69EC6529F28691311DD117DAC2219CD281330BC2E8A01A51C9916B63E51BEF30D1B328F50DC0C92659563951E735E4C1000B14552AEE4D9C473AD6929EBD61908E3CD2C349D99B0ABFCF4C19FF5794E355D49077BBB80B2A4BF548687596E4A45A6CC25DD3ED78A78D33AB76851E7A48AA3B602347FC26CE62ADF4D026F2B6004F4B02227370E2E1F3DFB6077369A4D8BE450E904383D0EBD0090676C0068815DD4EAC9B261784B3C0B29D8E08A982072C56CF99A65750D5FD1896428AF953BE7EDA84D7DB8C00F3D52917D6B6EAEAFB4E330AE929503C3ABDF5BC0073AF05C0645BC9F455921DF3C87325D85BFADCFCA1C2B50DBC5C7F3984CE92EFCB3A80F62218C7C84ED9E71678E3A48F8586A3C4C05F0F954D013F4397C384DFA82FC80B50F5CB4F943B61DE44EBF52E893EA59F2FC1A91F699FE3FFA591F55FA0EF7165A7EA3769A611C9707284D86682DACF2DBC6AC2B0110158639956E1955A5DDEF151137D90D19A80F11B776BDEA40AB391DF1B5FBB181B8562FA5C327E02F7F3BA280CC391E69804B7FED21EC146973FDDEBA6051F863165BA3D3955CD1E9D611246AC467FC1D03FF13FEB1E037FB9443A81DA147341778EFB3790D50DB78D47C15E934A4D846136D1C6BAD3D3AF693191BFB982048ABCF5D4B697B8E3630A49FF5922608CD74BB0D3CD91CFD4D090825CBAF9A1469AA1F63E8A2EDA6B78A735740A44642267DC036B2F26620255316EA2655E6FB9B30E848F2FF2FBF21E81CBE3C592EC6AA44DBD19C5018A13FA79B526FD55FE2CD4D71A3A158BCD55FB71D106699E103ACAA37DF1F53DAC0D51406DE058D7851E44F8CA0B3A8011BE6DC92E60C06BE0CA6861B8063E80C40703B49048B5EDE4AF98F9541073B3D52C75E7FD81EE635549855C97D365D982A2955A9286B24A70BC1126F6D76C3472C1A2B57826C8638557673246D1CBD94E745CE23E7BAA64780EDB8BB501D3D3FDA6FC98D2CCD5BA742C290A67D41C96FC7BDA8BFEEC1A92DFF09029846E1CE5739BDE34B5BEE04902E5EFABDEF120E9A962A506AA86B0F173299178ADB08325373591AF109CF61575FAD67D1B0CB55942390FD5E2B8ECD65B0AC0A1DF96DEF57C43EFDBC7D5C96FCE63CBD4ED028ACE7B102180501B293861AF858F39D75363105B16934C03679B96365353C4F86789D8D63CC0A6EE9760EB782DB10F5301063B90B03F8A2D9E004066A31C3018298986AF6B3AACEF2044DF984A58B72DA8625E7D0160A0ACC4C20C8304909F58C4AFE5F005833E8EB76689392D60305F81DE9903B12C95078AC81A96C452E9D57C38D499DBEDF7D8B63D505AD56BBB4E5FE22A748D1506FF84098E0CAD55051B17CAFA8E8ED3FB44C7B9FD97881428E1456D2F52A56292F6ED294552FDDF4F7F2BC584D2228B5424DE7ECDABEAEAB5E1ECBCF2EE3F6E3514499FD072C06BD7ADDDAA774571EAA69080EE368242871AFF504A7FD87C90C694F03C24EDC25527423BF8487FD1C9D79A409D3B720357B65055A7D5678C77872E62E9B19272F240C7EE96FBE21208665D1DD21E7AB81670EF67FF6C1488BF478E6C8E01CAEC6B6241223B245BF80BB208363D93E69EB028DCB14E6277252DCB685EA073DBCA715E6BECF80D5DAD190A16FBC9C2695B1600CFB04790C242AFA31271C056CF259FFC9E683EFB1E9C3BFD1F04E17D7303B5A52313CA45E289F97B049AA40DA68F507EA5B58D04AC1B2B605B97E31F232BDA340FB34ED0AC6D29F4FD3D307609D2D2B88E343B0BFB642259051773E1AE6988847728E04950B2B8AE548CE2B60AE336F6A8E0D764FBC13E1E68B6646C73FD82574EF81111E77F6957EB23D5DFAA52947AB966EB28BAF7F39BD5954E9A74EB598EA9443C34FBA45BA5CDDEA4FAD6FA2F768639FBCC6D6FF662A46CDB30364636302D8E6389E36BC9C89E549D8C3E407E907C3D8152CB28984B3FB83513C46AD1F50F9643A1B5CF749AD6A7938EEE5133CB3112914A579D1CBB53AD90125048664E44378D26EBC4EAB141A2E914F7A1A7B340BE804F30F2FEEB2BB4730DD59372A316853176A3E0CCC22E06A4E91646AFCF90522EB43CECADD4AF2BD60BE8AC985D1539F93E8CB30AB41426D43930369468E381126FFA12E6A7FFFB6A990DA44E1E83BA219C2914EB5BB90B94DC6CF30D3381EC84B6D7A878FD13AE5130F68C79CA74DF2893EDE94031170785004F1E1171C199F3D62F6C7D562FCB00427767610092E756103A4EAFE8C6F623368B737E0B0D9C3846AFC24146528E23249738B451374A1D63CC4195135395F908B9DBA88D05D33C459C60327776641C213418F56D731DE06421AAAEF7470F6A0EB65B2660693CE34D63FCBCCC2DC0C4C5A66E4D7E140E0B7F36E44DD6331AB933432BC2A50D6F7F35E56A045E7A2818E70D13740A5C09286CAC568222BB5F3EE0D56052BD632BC57FBE315A94199BD74BAABBD844781B49FAF4B9CC438FF935D601EBB27DE88F6FAF8055542E9A7F331A05B6A13B6EE8ACDFC330C1F7A7A6C4E48313EB3D5294C62F5BE111343EAE7EF571CCBECE92DC0F5FC486E3DE3E029D1425AF97A58BA5358D747E91A105AF0E0DFBD0525AC3CEBBE9C2A41B972B44A366E492069AD8F5B33DBB3C4D466D607A8D49A0BE7B355657EE13988452A2BA90EE2AD6D6ACEBD395B1B3E0E2C7B4633AB4E9C1EF378E6DBC8EF9D9EA2D012B89CC9F62CBC575BCB5FA973CF85634000214A1D1D297858DD127351082B67F9C4CEE7465D1FE4A3CA1BC15127867167E08E779807193C4068DC747148A37F964A50022F7F680990DF284D7AED8C3DE97DFBDB9C8E148736B77F2C448579697FCFDAB117B5896353C9EF449740C929F0879E671492E7D8CE4B541292759AEDFE659A66B40E215A70216E46FD903DAB608C9811207C7BE4DFDE9BC357D7592590DDFB86998A74AECABD25E370C649E845844B1A8CBE70679AC765B95D777A1CE35221E32CE43C32CD0D947171181967370F266B686007460399FACA8F3FEF4778FC6E04CC3F3C0A6EDCFA41091A3019B909D8C1BADF8EB871B6C998E29C4849A3AC4148BF12D9602007C94B6E6E0112B3368BBD5FBD72A0F353F6007C94FA2460C527DAE1480F816224A1E47248272FA0E0F560D47FD9753F2E503ACE6AF55875022B873997162F7E48FF0C60CA73AE12D0683FDF6C49753CAD5A409FEEBD9267C75379CF266B2FC038BAA206D11EF3D9ECCB1A84821FFAE232DE4BE422BCFECBB6821907358166FF4EC258F275A1C71B269D6F8130627509425E658F3475501E5E75D5778EEC3D470E590A955A2151408FF5DDF73F0D0D11FED43B407D6452DAFC52E8F07A6631934C1A971CC1CC9F980FD40C76A9551D92FB6F2CA73656479047FAA9C1B46ABA05921A53A2D0D465E71A8BFCE8DA040EA78DF82E8F544569CEB940A57EC17740D4DDF6DEBF9BE37B22A4333387CF5BDD23945E47F82DD8F4B36A52C30356A30F6C988AD32959E95CC2857EA7E8AE27DFB574E309FD00B7610C86335512BCE26872DD79D37B1CCED351A2F8A41ADD72854E12B5C1074C1D1021A932CE9C01C8AE3080E7A8BE63C9968603CE2591B9B4601A9D77128E1C2A706DDA037473C0C2D8F54B3C16B0CD5A09881C5D452A3DE10858FED083341522D344B3BB7A0416E7C5E787F002152B04EB76FD3517EA85B23B8C09E848E5F8A987F0CAE8D3107B475DAD9BFB149A7F93354BF07E05F89D0594EADA75A21C08DE666D0145528F570E7701B5AD961B3599282B9802AEC2E4E30B5E60571A1D638BB4D22FBA16F60339AB52593729853F06171CCBA2F3362712DD8F4EED951EDBEC69B250F3F237427411046B6DE45442B2CCEC1D37ECFA643A239D08F058ED894C4828F3130E6FDD5D29E4D65690DCBEBAEA8AD592491DC1F37F0415F353058E78D9610350BF428DC5BD77248EF3EBE1ED4472CBB9F7574D3159A4D2CF98E6969AF6AF0896CD32BB7CAD8870998344DC3BD9EDCD0F8E0954AAA2061218C7727B1A59E47FF578C8955F88F20F9DE7D75BA6B29597DA9823F022A3A253570D71FC815CE39DF288F4ACAD185450DB489D3F92EFF2E9079F78908B260CE023D8285C4D39C67D0042C721F3D7AFA6CB8100BC7A030E446D92B306F6CE617611E4D9B9EC8C704E50EA16050C6EABE9A48C8DD7F99A40AA962F720AA5BA5951E3106F1A54CB86FFBA609E5F8C7965EA3D69B48CB74F7F7B7428680ED6B4BF116950E621F9AC0045DC79852F5DC75AE2AA5E5EABD799969A92DFD1F1D3D6DCCE63F24C399318501F2F4D827F9F4F28D738586C98104A585C93CB81394456677F519A3A0BD0527A870D72B63713F069BB1494E5D20B90CCC6D990BB6057B215276E4DFC6F530AF14734F62A1ED605076433287998F98B2594C140B36C523217B3F666DC0B9196E5A293B1CB55AC4870BEFA7F5EDBFC11B5F0F9AF4F7C27C9F8A7CAEBF6E2FFC99448DBCC58E1CB364CCB7CCDA44B9FAB49CF3468E90303B6F8CEA99EFF4046038EDB5CA7726A474FC3C9AEDE8DF9EE3F577E9D33B001411B85ACB3CF00E389BE99046483DAFE0E7273D0B3C9CFA69840E347EB4F3F60D1D39B9F80954A61F45596AC9F7108286CBD4DAEC050B142D32849BADDCDEEE0000000000000000000000000000000000060B0E141B26AAFA792BFF719A3B794B2F8198EBD1556889C8C61EE6A51470AC9B274CB162AF44A26E2BA5EA7663C4C78B4B66B322ECACA8F2EBB6A610B51D7C4399F4A64A870C038797CAC80F709CA5C3C9FAFF7D797963E60983B584130C1B99328AADB2D261217CB95A535B8518A78A6D2F6CB8400C2AAA2DAF451391F7B8AB0277A3AF88E1CE6F1D3DBC386CBAFF15308F073D29838692E645F566D4B3DB4186C259BC84606855EA88938CEC4F7211BC9B461E39DFBB9E44CBC273E02D4314A037E0A26D60985EF5A35F069D8B51F86E9B6801CA067AB75565D73581EBBBBD98ECB5AF47509C8729D82EA0B35F0A376EBE6D90108CD61FBD0CEC966C17264F6A87864457F41162FF7210049E6CE2B5354F8F19161E0866D6BC3935815D9267C600DC529521FD092B126EC440D49B8E3A166587657B52AE9E2923644F72876EE94A61D2DB0EF4DAB33ABEC0C47A6A725D4CDABD06D4F6A30BD7C90DB3778C17B7D8CE82A5123B798D8B47C7F3E968C9E9F82A6EB3C2BDD8FC06D282F5CBF3050F6FF71E2EDF7A109F23AB47F427BD75163162C37722BF70A6BBEBEBE8FD9C39152AFEB78C37D718014F739F20BAAD1597B1F9C4E0B59FD82B834D83DAFFC935DE4A3272D7C2454508C07502943E90FDB56128D6E6009ED09CE80A9B60D51AA2E4E162F7F0C362F6886BBCABE29EF6C7F38B742000B9D152FF709082FAFE809C5DC9BCBC6F300B0A7840D0D36F39567D14D8227E7145F7CA670EFE917E0F18B0570DA3E05DDE56883FF12BC0C76C2A1E9FEFFBB728D991769B7D0B0D34853C76FC0655AE200501C28755F57934BB9F46A3C6AB1DD8E0161C698133F4F2D7CAF3392576B4BD2B6F8735D80BCF60656E132442BB7FCFDAE160A2DFE3F3FB8209B5C933201785A7E8206096B84A222A68E62501846273F6A9145820F87F450D12C64FF79A843E897C8394AD54AAF4F3B886FB00A6C37B2EFD0F6D4DD639C9989E7CA30E4F12EEF440946B61D7A28904E1D74009B6D1AEDF2FDA8B5991CB37795A8EE51BBDAAEA34A4C7040944761B9B4B4C12F455C536992A0852F7F07A9AEDA8E522591CB4831B0C79FA977AB6BC49C9730186855986035D2C6E5A6D93DA43E8825753721978AAEB433CE2F2A7D67C1FFEBFEA6F6059474D3022817A7329D9DD0E4A292302E4A57174B9C5346E4B6D75D65882CA7339A48C6E7AF776A8515014A20E4390F6B4F4A19990FA725F5A69B9C3BD4E8BBAEAE49979AC19600A3CEC6DE154985E236C3D0684269974BFC82301AC7196675F618182D7CF15EE5CE3B7ABEE0DEEA5C72F54CAFEF203D556B31327089A0C0DE94F74458CFECB481ADFE3CBB5DA422BD3626B00C4572B4C2BD7584ACD9129A76C616AAE51F944BECC4682AACAFB8E3BB1A42A6A8E5FE7BDEB43305A34A98308EF2D49EDE4F41361446A9AE4DFC1EE13D12821BE0B01E55B865B563633E5A19DFB6425CB60159C147B18A6419F5085C5D0882656ED533EEDF97674D0BABB6CF32F696DEC0F9921CB3DC9E6021FA198D554B1D83C42A0BF214FE4C0431547384F45AED9190CBCF98ED8278E8A03D551FA284C8A26218F0B0B58D99879DB98449CC99B6B399DDDAD9924E6A7EB20A0F1FDAD2F8138BDC7B445BC01503C509066B1603CDA76FE41727AB5E027DCB15032E8F66BFA84544D22C501AA6F62B02C0F8764387163CCADBF1ED7238E7F16C80E6C37AFEC2E10FFB95AB0A39784F9FCCD8AE263758ABE392727E9AD442A44738D77CB61A6B1540ADE751130489015AE5917C927232EED27BBF88481F3CA0C5ED2C31DFA943B2EAD4A8C80B4946E3C138A61BAF43A72C7A25E16874CBAE254D3F14C154F7C60CCF665B566799A01E0F769B60F73C17C840E0018C6FBC10EEDA3E35A77586B3A5936B363B2D5CB25C78A3E3AABBB84F1E64DF47F97AE1645650FE1751A724EA9BF80744D0F33DA6F313A3CC17D8F261585B62A75C167126D899219A26210DC55AB6DB2B94E6993849B4986F988EFB07478D6621CBF4B8ED772E61B0246A5582242FA20339B2D6CB89BA1B9210A318EB4697FD21EFCFD230DE9680514A442A13B29D8CB2627A6970BB97BF09C79C6ED7A27247662B25F39C8D675B0747F1A6D9EBBF7CFA7BC51A7EA3A7307EA4FA2A463BF53A645FE701FBF26628731CBC18636567AE633A49E59F6F049447803FA3D4F1F79F38026DE9B07D8610C9F01BEFB7054AA46E523E001C1EC3A4E7084DE0CCE596DC63D9C1F1DC03F35F9B1918E62ACB2640102E1D520E900969D53E83D2DBDDC80D1DC54BEE99531FAA5A8D2DBF8346C7ED123587353DD63823453DE350545C176446845BB3522A862F5D675419DA901CF7D2D1F7050ABFA3237D42753203BE251B0364379232D2D9D8642D52A60F6F4CB09EF29FA1E6069F97A1175F8447FE98A813CC182E33FFD8B8CAD93BF32A60F1A9E63A79A7F7FB9162783B89BB57F3E73155CED1D0084D5BA967F76C89C61C1A3E944F3B6F78D6CD3D1139A315C5276493481F3FFF9B6A6B40C920EEED9EFC74108C6BBA5A15DA736680A23DB5672C5A32ABDA24B49F2011F44FA8FF9C73609EC195025F0456D753C848DC6296920FC32DDE2174D37BFBCB86CF618AA0D486EE46C5E1EA14A3BAE4952AF5D4837F9B8122A19D1E59B909ACEBA6C849C8B452CD6CEF877A65FD83E6D0C6EE35886688F1D877612CB8E671D83216A1F76693D6A4D6A2EC13EB6CA2005328B3C91F51B352A707EF8180F320D6E1685C1EF4D87E3CB77FA549BC12727E59C11BDF8A9631CC272998253028CECEE8A2914182B90F586D80E7ECE370979BDE683F37123090012AB9243A4C145D6349C2791DC44E54956C5E9B59FAD017D3EA27D85B48A896671A0AC14A73B5AB9145D8BA6AEBF9EA25AC2E8E2C4D16C5009A83D0E84CEB80E95DF2CEC4CBEFC7F5B90A84D408E8C4855F9AA2987D9FC9D8A451F32B367BB1DE5271ED35EA153B5D400A6D8050EE82F519BD930245A96C9727FD24D8B94DC53D4B4F00D03172CD6B7F2BE163B6D16FD6247B01988A6EE6CE7BFEAFF78E983B8DDFBA4242730E52B57876E3719D1F9F6CBCC81620F848D23C31E3FFF7EBF2AFE5011E6466B1889E7EF6281FAF8B18A012CEB96796FCA9B28E78335DFCB85BBEAFAEBB0FA75EE2D0D391CA97E05F0FE43475135B13613206A0D88438F17EC8E604B007AFDCB9FA1378B7CB96675E0B19DC6FB02508E05A7FDAAF09297A3884AA051B6389A52F921F8FF31970FB082DF554226C2613B80CC1ADFF770024D6BF011C0F028A012597AE56F36EB6B3E864D79639810B8BA7258B18192B5CAA80DEA4B140D3C6F1D707ACD2256D676AE90980BA80E10B44109211ABA830EE96E1BBD248315C804D391A86AB7D4B3A4A37FED90D9867DA4B93FC32E79403E5D78AE99AF1CD2ACCE65D4F3384D9CEAB71B1E93B99704C64CAF17B999234361E378B9362D14BE3FD9E6C268013CB1FA2EA8361749D635C0429F796EB15A685E31DFE7A76AE870EBA120331AC830F8C486F6C0C4F07B658EBB9274A463E0EEA101481DD6B58835A303ACE802AE79EBEF51ADD98A67B7FF7968815ACF4504B9D360F7C0120A00ABA1FC558E6CBD8324EC35E0985294563A8D7ECCCCD9E3D1557A09885770836ECCC7AEE0F18B81E30F85D695440B5BCE29945CBF60FF402B281942D38EA33A4B03E9FCBBBEFAAC2C455E8A03FF3F35154132C538EA16F0605EFB788C3CA8435F6D595F776433585094ABC75BA581EC59AF701F66DD6091623E4676D167 + +count = 81 +seed = 3D598F7C498D8A1095C40945975380554BEF6142578638A7627E2C0A21C59C579F8E8CDA309348FC54C764C899FB93E9 +mlen = 2706 +msg = 63EC08B711DDF5C66036A13F574BB7BE76445A1D1F83C7732B9F4C25FB9E799D4AFA55817BCB39B974AF92F3730767CE7D863B6A3406450DCBC5E0145D10B7D532DA6E80196157C38D1B6D3C173F74D67AD8DF24ECAD4D9B59921418863A38270B982C4392225EDD1845AED2199E2C38B36C7E0E5D2F3CC7F6803926D977C59ECDAC67CA290658E72BAD633358FCDDE2A4B9C40169A0C7CCCFDD93E4DA3C3838E9308533BD468A9128C5A141C4842840E45BC8E4610A7C5E7535834C5EC73312A50197C76AE984B3521883F549BE04E27D97580E6D85D0EE84CD0B8C65BFB1AA005C607DE82DA70021F8F90B7912C67DC5657E1882CFA6DA3DE1BA4ED823789C052649DEBC9085C74528162243133A6AE5C1C6BCA3F730525B167D816485E40C208AFFA8706E3D74631EB4413032730A7647548B77579323EB03D36C2EC37D2389D4A17305F607C78F3073A2F4B4395BBC94AF163ACBE3C990306BA3F89AF9AFFE785C3F6D102FB2BD55F0C1044034D6A871293B31A1B38E383CB926BAF3AB4B5F79A47E9FA7B77BCD58AA35A7F16DDD11FF642069A8A327DFA800049BABAAB4AFBEEC9FA98ADB9796FBEE925BB70EE9E96540436E1473E3AE4C56D7099D8DBDDE755A7E101BCCEB596B9415F52374C8A3A73EC66B229DFD8CD7EE7D2CF1C5E7F490C7D9381D9321B15F84F640017851ECED1DC80D32DA3A0A57ADC3EF37E021031866E278C7D51FF5CA8E9ECEA1082423B41D772C5ADC61A8C71C3D4CAAAA3433928D7931EE715875BDE2BFACAA0A7F799B45241C21BD2ECE4A5944FB6890BF24908DE58DD3C76173373254A36B0B2AC7D67926948CC0136DD9A5079D776C297FB6A585C290D5DAE1C45E91153299EEDB731E527F0F62E83C1E93C75FC74F9C7E63311562B0A55459A0D41E034C3AF637EB29BC789E5920DAADF265F42F2707DD1AD490B5F8A8D24A9968BFF11A0C364A779EC385A9A33EDB9CFC7DBC672BA60CE5F421B40634270B982D619F8E7960D32E1B8A76CECD13A3B0214DD34214CB5BB7FD530058D5DE1FB9E4E88ADCA05926CE1F5597100F55DCBF64D47FC177FF87C4BD9F6ED7670FA7B7D339EDCCE6FC1EAE069E0C303138689DDFD23396C145B79AFCF68125989C8477BFC318CDBD69D1AA6D3EE41F4B1F9BE4BE9FA58A072412078CB9196556EE56FB7B2A2761DD04120FCD9AE9736F599C8B96BF8F964B305530A6DF1F94874F36F07962F87ACC0B285EDA64D2E4857E26BED40E9A5DC0327F1D91259292C608D6C6D59804DC23A34D1F9F1B69331D68771E41542FC5D669CBC3CD7F8310F87E8FE8F6201E57B475DE2318EA6EF9F7D32A728A44334CC9DF28DF77038C37CBA62EA8CC5EE80E571879AD111F35B6A154FDF8D40FC93360D547D02F0743A37EBC4AF178C6CE36C92CE6B80B6350202D2978621684A19AFE1474155BB962014587B1F5A477092F42BC446D7811C0EB439A6829E538077ABBBF03F515F1E6AC018EFB05AF79069C2569D2CD7140C4B1B47886064DAC695D59FDE2D8FDDB35318D33EDAD94AD4FD988095B1156FD59551F0658EE666186369BFA84E30672E4659BFBF7963C377F0039E08DE2C2D9803FC12D97B5E67CE9536AF12DAEB3B9903D8D95F336FF53286284BFE8D7AD13EC21C2A9BA93C9A97BD7F6148DE7C8CB41CA75A9ECC8F9CC68D888FAF6B3E75376B5B16F41E7E6B76A686EB365365E2074FB1D7EFB1B285A2357B020FD3E47B89943FBC1596F3FA8289AD844386A691F33DAED4B7A6A6729526160F2D32BA7F68AE6678564FCA05BD811F208A8FA62F6731F23D46027008246FD4BF3C454A39EE225245E74DA5910E7937B36661548A55A2270A9D27114DDC94DD9B9D4122289DF0A5700222A977F15FD8E36AFA1C4870BD3CE9B658E2D83882AAC5F3DB814346240FF8C8FBA3F36E52AC9B441C76B6F104A0931BC45E202ADDCACCFB93A486A7734A6D82B9F6CA911448F988626846D413D987C5AC860FCC0D5F734269AEF88D41A055794DCE832BABB7E306F622E5EAEFDBE1CF195E320A1ACEB4834B3E70061EC2D624C12EB35B16E5AAE73053A3290D4BB1F51FFDF48C1A7218D365DB7FEC15BF0F710954CDEC54917600014BDE3A901DAB1DEC0844D7FF148EDED9788CC85C0CFF26E5895D91C56BA6950C0BA8FC6C773AB4A6091A5DE3AC335DDC2110EB0144FD89B3D815EF4A26F718C1ACB5723AF1DA5515442A03CFB9D90623FB21D78DAF441000E285E9E7C235C0F31E258E6B3FEAC048DB652B83E07848D2E9357649372B1A55975B2EC7FCFED19D0B6613BFDBB4B5B01A9AA3128AE137BDC1D8FFC3A38B597578042CF183BA8383C289C3D92F6B70AA9B3364E9FC5D43F3CD3F310D229912E91D5806C2A11E0BDD208A2AF438BE77B43680E2DE67918FD414338A763910E1316965BF96BBF7DF639266D075E90EE9C073011F6783750764FBE4906ECDD94EE9FB7E4AEDB23EE88EBFB018C44FC8BAFC66E6B454A3D0E332C7A6B34C2E8D1D26416FF43D768CC36CA9D3168355F1A281A6B2EAAEAC7B64AABBAD2156A1D781A78A896248C56F3491A5DDA8C22C231AA7AE14BD558F66E6280FA65F20B246D815BFF1D3C6CEE6DF9B4AA7F750307A7BF73850E6BCD22CA0AD74B4AFC13CD4AA2FB7E7B588ADB3A46A23EC88A34F13214B261A283AE8FBCE8007C6EF6BE255C33218AEBECD3EC27EDAFD252994B70BD67407620D26E8567F4C7F6D636803B6A27EACC3B853706A8D57ADBF7F7E142FF149C35119A6172D5884EDE7C71E6C34D1B485A684DD56C9D670576B75CACB870A68EA7FF2BB461D9E2FDBF500B2F200110265A3CF24370A3F480DA66F98FB5327B4CD796EAF0E559A5519F3C643B59E3B89D05D2A9F9DA6732CDC2996408B7FAB5A734310FCD73FA3FA5CACAF31AB04EC0B9734407C6DC575350212239AC9092DA5812137BFC40F7735BFDF9827F768FC0363FC8C5739C7DF828075EA2BBE6321D5A8EA2EB7E397C3D58A953C7F0BAA69A96AC8110B125EE2E9701F43EEB87FDF58A6E6266BE1136437599E26E8E6E853DBB6ED9DF3931C5F402FD09B7E203AB36EAA6EEAE72E908BD2B9CFD379BC9B407F0C882807BBD2E91F920EB24137002A48F1AAA0CBDF89FDE5C51079F1D8CF7A014207F1B40773321AD952D77CE18EC7B48F2CA054E65420C1132AB67C832EE22FFD8672803CCE3DE7E9FD0690E55FA1AF5F11611E3E2C71CED55E3E347F4CBEB9C93BEC2B98E48495585392471AF0AE589257ED8D01792112C798BCA5107030F207CE567594B8433490D8FF1811F21B03A42AD0678927183321355E3D6908DC1125CDCE038CD0469D72458B6CC5E67EB0D78C20819C6F3C4518B15CC63754FF8679915E329DD46FEAEFDA5249ED7E754E7BD55C75CB764B6CC36BC06267B2479CAFBB3F0BAE32A93558190B65C85DCDC080CD56D51D4105C5B0717691D4DB1893EF8AD550F55855B4123A38D18FD67B588A3A4C2A6604E874D721359352B235C17AB1DA2758712AF8179FF433211B93078735F909F985F557D0DE52CB9203DDC67BF9DC8632ACD8D4F90196AF6BD2E79834371C5E9FDF5992ADB04AEA186AF36F56271F763ACFFBF94DF4B0512CA6B7CA8FF486504E565BDA367E044FCD0F25FBC2A6C720867F95BFD92109780D2E6DD60CE90A4CA8EEB8C4CAB289DCF99E687B017B37695C3B99B4FE97D7E5D52BB9813C04D03C9AD71770FE0986C7F3A3FFD3A261AC771DE88C7ACDEF253E5CE2B50BC5C576D132B68CCC694BA883770B80F5ED7D527CEE816527F69CA2C101747A0088879C3663037DB5B +pk = 7B2BA93A78F89A116AB7AD274A78F9B0C809EA0938B510709A192348CD50572CAE403EE3BC85C470E617B62EB360341D18C5494FF1306E81495EA8E2E1F0C8A178A5AA2F6C71F3AB4B8C8FD9138394D92CC74AC03AFD23888D3B9011287A6217E54564DCBC1FDB92E27C990ABD92E50FEFD92971DF65368E8F759F8F173ADD74D60406C3933EBB82DD722265793F5DF860BD2116C63F613E23BA352ABA5C4AAFE5404351DE2FB894E7AB7731A509EA73AB9C4C5D84DFC00D025F635C9CCA489399281AA64EFD9C76514B9E841F7DCBB17687A7016820456C3A6F957C34E81802E121DD1071CE900400A9D1083453B0208D77D94D7CC891C5AB2E4300AEFF9944DCAB93B78D55E3C5BE0D1E7E51231F33EA350EC9219CF2A4448C37DF5996DB6ABDC36D5F961706670292513DD08182E13CBC8E548FA8D3232E53670FFECBE65FB6BEFC71F240183A6C81EC0DF74836567B402A6F929A82AE28868224C5C30C4B6E51A91597023117D72D27D5E634EA1278EAC260EB9FDA1BB0A4718966A591B0D832BB3773143019829A020D8D0F1379527B144FD3B3507C9A5E4B358C286D2C88ACB7081B373378A4B78084372C58ADD5C66D8207FE2EAD7483A39054CB5BDD2B1C57A6E9139A670AF88ABD26D9A99E1DD46891445B875163194205433D66A34D0B869211037574FBC6F74B26CA54DA7C0B1D3D76C1425BF8A321D22B4CAAF8F96299730E8AA261BB8556CD578381745457245101655D46E0DCBA6D606042AE4A73515843E16AE01E9CBCA6504383DB63445C3A41D20032E7152C379AB4B69EB61E5C584A9D53B3442A69CC8F853608AC8A8CBC83F68D2C5DC0600975ED236565466B8A0675D7EA4FCCD8718FFA7044A8219773799068E102A979F04ABD35A98A73B21298ED97A6C274FD90E753301A8A155833713315D3464C19FBF7EA5672878D3CCBEFA3628462FC1584AE0AB00FD05417546A0D917FBF4E65558F6B15953726CA1FF32DDA53BF2E794147367512D2F062818B8B19353DA7F53B632B08E7223DD358588626F18C6977DEB4A1A942700BF953A37E5CA20766ED1054EBCF343804993A9375B5431379F4C04A70D7C7EC847A2103A9C47BE5DB4211D89163FCD5EADAC7D8E8471022A97415AC69A15BC5EA82B250F4824149E5631C4F05D067F6EE2A089DAB8FA1AEA7377CA50A28BE6F8FC562F50B7E5D62AC077854BA3258CA4225C4F2A4C6DF027BD885051535ED55C54586FF638417367230A4B3A3968BC4B2CBA125D2C69CA8FED7B508A618B8C92F936C491F15154707ACFC670A55E9BFF75C3743305C5D6B278BDABF9BEFA3092AA3ED91B65A23F4369A43597867FFDDAE258FDCA93F21163CA7FDA370BEC30BF02AF33943AECB315240BEA14BAD7DA6C9EA4AA395E5DC7BA79DC1F5A38B402B07E802BD18C93511E46413BC8478CAB21CD34DDDE6735B19FA2D753C6E8B2BDC39534452202AC649E9332D3A2A0AB0587BD2A91E27CABE8A82A4CCDA67AB9D9CF3EEEB893396AFE9348BE581AB65AA3952DFD49EF010109BA24683AA31F295727467FE552BC389B34C28884893B4157D823403BA339082BDAB27E7317AF6260A4B792EDEEB4EC4A79241A2D89BEEAD64105BF312FE9F111C3CCB3FBADF70554FF0793CAEB36509CC942EB6860FF692B7CF19770EE63E10C95C5BE779B37C86170C088566552142129E9BF37EB2EDEAB31165102CC95266BCF735E6161B65DAC30E6342537B5E1629FCAB32B303138E78D0711FC13B447DB9C034AFB541E691CE900CEE4289198C97E17BA7EAB01C0461837C2005080ED664BA344EB836B2D460FF504E559432DFD088F1B8C4392C953B517EAEE01A8C12825DDF1BBBE53CAE49643A0052A5174404306E5CBE6CD8AE32706DD0BDA559B2106BFDB67F7C577B90CF6F7837C98AB0E3EB50958C98553247D475393C2E5C8F34AE5FC48CE65CABA4993755426D647B0C812D55B68B7FCF716D5A77D663505BFC7A0B85002A14D7CD700E14DBF7C344B8D6AE743758C7AB984A12DB27233C1A94DDC1EB7BE78BC471A68C1520611FF8185C9FAB06782D9757FE0C55DD61817A29F7A49A97890BAE3E4C449D7B5F74A65C8A5A434A7FE04AAB86C730586DBC387ECF9CE3C990C8C4BE561C63C09E41F684D7485011D696E0D6E573676373CC4A9C689CF25124D767AF2C0D8593B66BED08F65FEDA14A3BCE7EE06F6E9B399B84646F424F1F304807E62009DBFB3258F5B4D409CB8BA6747EFEDE39E6DD49D163773447AFAB30FCAFD05A530E98CE0604323E3AFC5700E815E7CD358462DEDE4A59FE55583324232B094214B441C2CECF83D3DAAA3192DE15045E94425CE53A48CA690547C98B579628AC0A19417F3AF9918965866605F1D2E6A340BF2574997870EEBBAFCC5EAC4DB567A3E7EC11850CF2CC23553E49A47FBD386B57E062BBEF1571F80447C87020ABB55CA54BBBA6E611E322C72BD20B59860A41A2A484B5E75A4E9C4A0317C713113C6231C707C50A185C0FACBCC664A73790DD4D80E18481C1A86AE689B8ABF771482A1AAED3F78F12C6BEBA7AAEE20773757EBBDC14411824A2EAA6C5189A63EF83747BD692D67AAA43F41CF38AFB6C1309E80D6A86C2DA6C4D03D6D60C205B1AE5C37BD043F8E16EA98889C6B3E5E45F28F5BEE5B846651635ABC1A8E8EC415091D56F35AB257451D3922DF28BD73C07774033F4799ABDE36BB78A2284087329DB762495DCAC04B852661A2A359E3A +sk = 7B2BA93A78F89A116AB7AD274A78F9B0C809EA0938B510709A192348CD50572CE09327CA8353708C40FD9A3A9ECB172DA81C4ACB82E8C232FA99FBC1FD3E181F0CB32A18B6FC3825FB838C142630072F3C667C7303CA362AAE3172813F0BF6CA596625894114C9A46864FFD3CFB1DBC0BDD3F4904A3F2E0EE75D6AA069D14E5143487625121216446261721740748041758073553774300543736018506407148243841077370032227824688478234011126375727285152535276107111076105525472246640384873818251730340251013751626276000454612116341538362207116664352873852221322171703687581124486462721081086201872245601343208802411184865504355374313854311534472348454366610413481306106702806540540065102236350673362678270680155546556237635328210718784528281257370546585261343435667312800000111828457627183425411282156548126250764120436151233522848205780236112227768073411284148553102572568181846884210023286076410153228106071224834215783266511530174584757742050440737088262680462222475176613713843026548482064423708083274627218011853023813687056341835332361853534017801744562535323753163550125374820147781623827704811641083846007171723647054832713012840038604181140577508362175036272525401708183436103262312324136004384184845175041756164157248615260365763388607655377383585737366482543643503534425220106363803708861482634716726187675407022336343765846801608648580305584572168488352668643771522120187455878711623416202835407306087781352071827078755715810481678776571417376511510623158043416143404764527455810461213087864123235617302856245837366131233760660388650067053655727802278484556075082811640870546463473478441465110417480006543610621116522556444736277660617212614653326586516620860010183035550837644518866888714580200865311785557610365214684403236027516808656317276525471733218616725756072046533218764503454105118620650235640608351177732133213708824560146840838528071063542673300345118371074717054580150528541722051026254543000222313236614303284436144484541443871874773384545447817287817713183287043160655156047106311367386327000684667270843621858278823177638345244111606068047784032632277782734608462657366386071516374640431637128150737141774512633263511285866471121566531137678064835103088445842204634584226888654887164615842602177328382621164413735548780753685363470460025624172623860882555468273582287256143575013673453077042636162705615682817886505255246742217636617643764783784800037347732240202880602122038681778077402873843218623281372335313114581714411043056340447287076473021667725336110704532048566330387864441847408146187671657562631058302231358158362153416586406748085376375754872048560712706576253880660185161253513448625052741622601840381700245468826032008256164880102200263734200872067007713031124742787121457323532072865778182450122448750622305060753264310365767770624318464562370775743533840081218883161275023232652358780006435856861303786658243517622884703525837818573806335585872638678035813750454403511467516644834138311886616365506313083410858170124518808143840377602387837213743076156881618300075031854104527117386584456183228384228767561201578436466553252147443280770780852077838483856422437475732368207701255032103038775650482476551263364750FD5165ECD4EDF37D7A14ACD034EC57FBE098F16B5CC60B120E0659FD871A96F3111CE939F795151A29277C6C9927A7DF9ABC584F7A766E66CA1F7078E173298A8175DAD54D98045A4EE9D5EE69BF82A87B14169349BF4D14B51F03CE4189CDB9792AC148CFE88122A1A18FE86626C6F3EFAA9B8F6A29F5F832023783BDEA046B0F367199BEC4D017D053C29EFD0D698FA713B69E1C60F19815745AD267255D1C5F1B4B4C0DD324F9EB90F38F349A1B65C83AB0386D93A0314CAAF850A63F2B9F2CB7F234DA8F6C5A067655BEB81C2E656FDDD5AE8E47BB72EDE316AB76623BDEB326EFC7093333767F13D749BCEFE346A864AC5D7CABFFB9AD8706F95294F673F976853E746B2E3451AC25110A23A0DB82AA1795CA13797E06970515E8E9587C73B6F1864231392ABB7E0F98D271D6B5418E90DBDBE88AE3DC5B07B3AB045D96B601CD408AA77FFCA35788B734834DDBA2910D801C810D83F458EE5F696608C8B925A89503053E1720740964652522462E376DEF8A097790E7A3B83DA95BDC8A4ADDF24345CB4251F1443176D99BD11EE5921B1BE97A6E7579B4A621298366FC4107134E6593176C9DAD6AA3F31976FD59CD53DE0A119F2C5CA32F26257F708C5132735F3239206796E696C6FFFF6665C950B5A60431DF8425E27A3F67563A4B04873C8735E75C18093E2815C8A32B30150A39D1584B06077C06D38A47B39872263E2C9ECD5EFEA01667EE073FB8D716026DD357A6257507FD1D5BC48667808037053A9AE3E7BA8DCD1373192EA36A09DC47C7E403C61E7178DD3C61B7A3AE03A4A0604C4D7B9BB45B11E98D19E259A667D8F0274556C606ACD3624E7A5A7F03000A31E4F24208871CD9009CF1C55CBB933FA4ADD724ABD70A97BE315A0822CE4611D468B65708CE50ED0F92955C6DF8DA8B1CC45D4AFEB93FA0C2057B97919472819DBA09D7B67420C3C05CF0E4F7FB998A00F49EF2A4484198A7DC2D5B814B6838CC39195B283A82685DEB977A2BC4AD01C1AED80A752DE4729DE1BAD83FD8B183BE9BAA21ADAFE8E712D62A5FF5940BD5BD8A634C23ECC508B5711F6E3DA4C51B6126EEAB4D6868C4CDDAC6ADD488C5B0A59E22EE83740B702312FA840608FB73D39718584FE761B8F5F5761BED56A28F0555FDD3F8A8EDA77ED0D46E320E12B4D72E35CB809E8CE1F6328342295334FA68768DBD28C5B5AB394A2EAD080CC264E53B597A41988A1BD609883E70919780ED45A41711FE4AF33F12A29A70411E77194C28CA95397F87004BDDE9371A0C40FE22CC80DE36B1051FB4214215A93A9E0E1D603A22116ABCFAE20A5BA3E795CD227C20BEDD8958961292FFE5729F24F52588F1458243408E822B63094DB6A1AD7DFAB3AA8147D292B9D92BA11A1F7045C7BCA0438B225978CDD1BBBDA0AB7BEC88D638E925AB9C37F01152E38C4DF4EE82AD21DCBA3A51A7ADFD866132FB0E99938F1ADCB7EC2CEE3A0FEAB4F938EE065BDD2F0907A860A5F8331841795CA88F2CAAA1E8B867F8E53BAA6999C0411F41FC33CA63C20C7B1E6583354D46076F7E9D87457C3FA8DC3EEDFD46BF9A0545ED7BE16B297D43667FDBC03D6510BEA0F85109D982A708AA29FFFB02F32954D50832A8690052F1A74DC7B43CDA7CE774A2427B30789DA5816B35C5FE71774281091DEB8A8C44EE41F16677300034861779FD9CC195D97BCEC98C3E366FD78DF262CD77199515881B6EEDDF00B77C9D6EDB2276EFCAD0DC8FD280DC3BA56CA1DC209F7B398E90125BF92D24B43920AA768A8F5F18DF679AECD846BF3230054AD7AF1808CC8F23A96CCEAD09082A0095963F9A51A2D37D4D28DBDA48BCE3CABFEB09FA50E2DB22FBFBAFEA3CCB46450D0F344383080385A8D7995EDC954005062FFA0667647FBF79DD991C7CAD42E4193B9C05ED15176E959626DC55246ED173BACC6429CDE18D08DE141CC9FAC57EF4981D2353ADB53B3F663D36FCCD12D440043FED34D87F907537A9D41140CFDB96885FD57295885D3C6FC42874792E1BA13F021EA8CAB489953492BDD076A3ABE3DDE0ADD06444103B1E70E8575447D96BC04A9B8ED86D032B737C67ABB7E20BD873A664BFD657AC637E332C051C5152FEB97A47153E0E216B03CBA2F361BB6D688EFC24AFB7F3C84E96FF87E268729611675C56DDBC11FDEBD1317CCD810460E4EC2BB504D70E0B43A8AAD0D61871B9A8C830073FD9BCE12DD6111739BB69228662C0B48AC3E662062034A7E73F6FCD059E8F3A76613F50C3D753167C06E9FC7AB5C186B248DC77626CB7615851C2AB82B55C079C90F64939D523E106B434AFDDF018F55CC9000ED6B453F312EF5E6C16EFC5633A2F0A3EDFDCB8877BE092BA51A34F816EAC0663A0D9330DEF8AE2626533B3CB8EEAB57927A62819CFFC67C451DE50161CF7DEFCCE6F4CC6F1B404ADFA19CBDC338DE394C6D12438C8FC10E5E9EE51D265D6DB30C32D3A71FB5826977E866C2496DC4E9E18BBDAA7F7E5E5F9394BCCB0F34D5C5CA3291DB004630A0A05B630B0D8F11C64423D3E6CFBC66627725D2E7B5D9C04E4853DE8699C4DEB1EB5062A0F2A21DAD742FACFD5AA1A3E1C8FB1C1FE183E9682CF68A1FFB1E0A720E775B6B4627E4DD051A25AF0DE7C968B184AE66FE0150B82BA7F1533DEA81FC5BB5FEEA0929754E8E4BBAB80C203E5B652E453D709FA7B9B331A43E47D55E143212639C009936A453E79055A982E3A4FAD025AE952327D5139D2FF09861EE7438BF098D57186B0F09D6038BC2EBAB89265FEE60414E91EBA908182B72F87C64AD2341F7D61849E64B9F78D411526985EC39E4ADE07CDB9CAA3EE126B8061E73A7F4D2DD44559423A07D27007799002DAF1EE7E0AF8166D74D3EBCD0AD0E3BAA9EC55A2AE32C57CE7BAAEDD8E95C6C40D2A07D243E0E90A5C8E19716072CCF24688EE99D46A36DFFD6CF82B806E7C118AE99D11F203179F5CF6BBE8D4A02C214CECACC7279DADD6A4989BCCB9A469864A63436F78F17541C98E432B6DCEF89AC420455096EB319ED22677BAA538AF31BBD36DE1C150BA19271D44A9DBBAE7FABE08523394C765C5E17EE43A31220C55999E435A7FF8B11AF09FB4AD8EE908775C09D64267C1E3697D59B237AB4D7E4B07EBFCB671205BDE5B56809FCEED5F2C6A8F2E07100C396593615BBBF9C66CAC23E1C1E742837AE797911F848C8E9447EF5F7FE7600DDC8C53C0D60D16BCC57989A418A8A85D1102DEB527C21B52AE5FE4E0DC81B5FA74947B508842F4D1FFD4A75007DF12F9DA12B17B1342654A26696A86BB10B2A18204A8B4F8BF076A8975C964E70A67742D670430358C0296F2A7E9AD7ED3FA9F5F143DE95E840093A29FE32EEFB5455D0AA36FD8CC9D82A27DB8ED84C014B8DDC194F15BB1573B33EAA37D337EFED327F5529067716C7237F14B1AFC336D9B40F1578D5749D683B27E43DA644134EDA5035A52812C0C93E7EB4F28CAFAE1BA10A07269040759E93657DAC27D2723E02B2E24DFA22CAB0949270E4612 +smlen = 6015 +sm = AB94E447D36E0F7C9485EDE2795EBF854667736B387290FE05D2282875901555BCD872B7A58D9ACA938ECF959CAE86C66FECAF7A8113A34E696CFBAAD8725D4E9AEE24E612E60451EBAC8A7B2A0611238D29305C07FBDD86A67AFE27C233DDD62DFAD49CD485E951946597B879464EB124805F0A5644303F8861EE03E5EEEFA886C6A138CDCC83C0FC14CC785B6F385B2865D83FCBB13E71CABCAA01434461B3CDD18F8B651C0628DC8D2735A6BCE9E10CC8D79DDC66F031127A0DA7BD55734459359CF784C85A9E366E14CF208D2ED7956674502A2F0E4E9CC8E847F89FC9A1E73CBE9DB17372699AAB109366547B40E56B16069F4163C633DE244EE9B920B3BA642D8EC458D3F4A868AFD7212F60054DEB05D293B98521FFA2D10777C11A28BE5494ADF106B99DCAFC3AAEDA17C999326627838125592D6D7D259EC113B0FA71D4F2A5E556C0C333697790E690FB0570B98BDF20C22C857DB141113117FEEB74071C93D9A6CB1F1EE6E095AD91A1ADB513C7779D741BC7A59E7478D45AEFDB947235712F9FDFC1CCE8A94ADF18D908F1DAFC75E7CC50469746390AF421ECC6322DD65CC58D46A29835919EE78AF76B85AD4F576E050FE44C8F2FE84BCAB2DC5050B58139A75933EEAAF371A292FC5898D4700E612DDA5D6E91308EC7009AF7846BE8EA6215614D1CB7F1A69580B8AD01133F6A3B7E970D8B80F36756CBAE0CE2E15817456EE0A2B9082F512DFD6AC925D3815D1BA126C069E38FD630B1F93583BED36A88107899E84367E5CE8C6C3ACF0031CD9FC96812EE7B9173E833794571F95683CEEC5E1479736CA7E6B1CE6A1592F61A4436BD952C8E60AB1FC840482671AA7226CF0EA8AF56738DF05E044EB0FA4FFB1ED8CD229EB337551FE393100917518D8BCC6DD7BBD7AFF0256451EDD6C290647494CB6E15F5BAEF374A8134473297AF6AB48D249CE126AC4826A5C788F1B8D18099E9119B5087C9AC4CFC569FAFAB24414B4EA1CC9DFB1EC2F4246FBF363BF17D84B8A180DD987F69C22C05542C92976A1E6FB393804913FFDBD2C0C0DCBA937EFFFFEB4C1BC3CA4EA74757E44A03213CCC442750C126382A62BC16B0ED8C46B98E5DDB7B21CE3E75C9F1BDC4C617195D2F1E2ED5AA59378A295361AF27EF54A5D3A2119AD4583299A55C07EDD79FC568B703E6FAFA0A533A6282EACEEBF6D22A76DF87D67BC2C4E785E9B096E3CC941C42D748B9A9779A23E23FDB30482F0D553D8CEE876869B5C29C3C851B64F4D29A8425E15E70ABD0847A2BFE40F522DDE9E1E475A74BD4E59862F42BF29D8507F3B05E263D01E5467347AF7870B3CD6BDB5BA4166103BD64F08F92ABF49FB5538B548470FC687CB4C7B51B89B2E6FC590CC05D152E4C6752EE9FEC8607AC0587371F752A3306263C67F1FE52CEAD6BDBF3F11B50640ACDAAFB1FEA259B381C3664C75DED571C23E5B9E30CD30AE58A574539BE7C82788FD00A2D6206B08EA0EC6242252C0DE7D9E43D1925002085EA136DD8D0946210AB10DAAEC5C3BC17CCD0D96089FD1BA01127A94E79646F0411475A9D1EDE9D86E9B0C1999E7CFAAA6779FDB378D884716E79E2532EC48A507B38D43BBEADF3F0179E447F20314E144941A2E7C66C0285CD5C37D18CE4EE5A674D7A7EDFD1C2C2180077FAEEAC7C10244EF5017EE568D9D4E3920BF8F500FE62095DD54AFDC7A93B3BBF0C3AE57E236A3AA5B691B368FB20C51EFF40095BC325FF5A00BD0B1D80F6DFDA1F2585BF046EC11C444EA553C33840F4CA65FF58F3D7709BC30FEC6841524524264023AE35968F0FE7A0EE01854DAFE5DA4BF277B19053986052998C5F6E5965B6E17A21BF45562B641C88FD39C6CAF87D12888F96BC80ABF40BD6EFD8993DA3F82E3B4C09628BB1A6B31E13517958447B475EF103E402697D42ED93EC0922C66BF27210BA50B0AC0F3796CD50D8DCB5CF3C6355F140909E80ED35CB856B8BF7060E78AA6BC4593906094CF2E113D88C994DBADB42518015C789B95A288BC65E32329D5082A94CBC4D0864510C07BFAC013CD7E6072A8BBFFB795C1ECC4C9B3E284FAA2FE183E1D3A775390647D8BB790262811923B6614E626F50423524F0CC0C90B6DD7503DF95F52F8E2B173E3E0E8E6A4774ED90710B6C9A341175F96EA68E432D03946B90C1BF01255555E8573DF0FD699E8A53B84B1B33AC76AAD4ADF9B6A98AACD0280249881D9D680C2B098800F1B8B6A96F9271B1DADFCEBE01062EB86EF16CFE5B39EEDBF2E1FE37D87D444912F340C20DF8A35B00E7E9061D087C46D0637871232657DDB5EEE1DD5D68D691AC8AC6CDFB6BC542C86CB06A7F3F5DA002B850A8505AE4274D11E0F03CB18268FD7ED45790A9CE129C7C8FF165537871DE3FBB2EB7751049773B7530A69E101D5592F5D10747090B067F45C084240BDE2ECC909DC658E731A9C94BD91F4C22B2E0604F6E4121DF6D2D1F2D208252F9C78B6EB637D15C0B1E977ECC433FAA055406DC9D4DDB1B42DCA2733E21B9AC504E9CB10F18A8B40977FE553FD0E1D85CC3EF6D4FC4053F7DCC6FE9DD156D92ADE6789622D3EAA6347FE3AEB404061DA5B77B3031DA058475C5A7E94493AC57FEB6BE7BF515570A7776E16AECCA53CE8FEC873B92E3D895E6F688DEA3BF85F1FFAA9757C7324E34FCC2F5479197ECE367031E986044B643FE3E164C402C23C8CF3D81E55CA63D561299BCE2524CF1FCC99A84BE49B198CC523D25832DD292BED9611734CAC16747B15649789A097D1958918BDB5551CB82E8F3129F717F0943F719A25D9DBCA37EE1A38571BB3619852DE14F8DD687127C38980AD882501A0090893EC4E9797CC33241EFC4E1196140D726E0B1F85693C52052E1D70FB6299D481859F8080A18078F04AE63C144FC75F8093533FB10B114503EFF1FBA1A94173581D1F28E19A35515932699842D9C170F50BF62FAF8A28F42FA5412197D1659409103A8E4410E4B54AD9EB776721DD6F8D0A0CF5386EFD86174979945D9806BDA608746321691B4E2846AD77E53B1512898DDB5BC3C8735172D86582F63734989F89F0C716E025FD39B76D7374F1B847DE7489753D7B042E18C6133E8B358BEB3B5254FFF75D5B13A7B149E581C8A1ACDAB90748DB0E43944F6171FD3593FBD37E635E451DA55509CD60B330A97D696F69897E14A2D5179F469906D8B70197D656628D997FE2D8C3FC23EFC83AA7684E18121996C55139BEDE88CF84FBC9EBC51A3A9697AEEEA5EDD5DF3C92EF58472EB9EF4ED9AF8F560834CD6B54C33A8575A912F41A0C5C125DF69DF3FB8F8944EA3307A63BB5BF40E3FB6F280A87D80FC2CC3D7148B28267EDA64211628BB71C250B4194FCFACA0CEC198ADF45C537DD9A794E2D61FA64821450BEE3E4A727FA208AF3AF72E8BA6DBDA9F5F02445FF20EE556CE0F505C4659E47DDA83D49A3D7B53B66151A1EAE8A61C70653976C475AA8DAB174F4F084CC50E6ADD2E7BDB680B51EDAEE13BCC219DB8C723286D81132CD4E5601FF6A1CAFD93018DF6D3ECB2CD3DBBDDD15201B75BDBF2466353431F7B9A9A8749D4AEC49D6BA8BC5BE961A40FF141B49FEFF14B16E4855278BE9819F0A956A79969A666F053EF356BE831035F12DDF35B82CFA4197E2A03720921EC953613BBEF7656E25BDC2A04AEE74D5B72D3BA892CBF2F4517BA96B055AD0A03583831597BEADDF26D1A84901968F8B1782CBF274EF6EC8E0A7EBDCED619E727A75771D6CA477B1419C15FA7BC5B066C366859935C7CA4B009185D6B66157C7FE924E159B9AEEE435D2553F51FF7623634A0BDC52BF7A80BE696AE3D6E148E2BA5EACDF12FD03E1151FD87C3F2311048F38F6E1445FDBF6064905EFDDF5D3006E163A6BC73BDD83027103E41562643C9F0290C61A47FC1CA1E28001592D4B345756970847CFD63369EDCB4CEDBD078C0ABF09FC39DBB641845FF7AE59FE355DED89F5F3142F18E3B58010565CFE3EDA22D1B3BA10E5AA9C2A7B2219247C4B9F42E2A05BD721EF87B0356A20500EFCFBB9FE2A7E37117666C0666F463DC8FFFF710EDABCCE842759AEED445BBD58D9398C2FA07D5E340549A10EE759EA82DF148EFAB0A422216AE1D94C1732B629E60809DDB271B3193BCF66A709FA83F533A3FDFD43193A4F988D9BB4760D5484C005C4F21A5C8FB037529814BAD19EDDB24D024E9F83ADCBC44EF2F6EAA6EAC5717EFE793F220B929830EC2369B05602E6B6B164213656B0479063C93D7C0A7F3A2D6321E12408ECCB2B501913AFC753CE9B9EE901A7198A8880642300D655A7F579ADD2A040A760FF632DCC38544813B0ACEBB603EBA1D12CEEC33EC77228645EC8E99059A5E58003862FA18C25D779A8FE365D96F47CD5CA0879804EE116F1BBE7521F0DE28EA204EAFA1105557BAC4B46B936FFCCF3FD57117DB2C97534D13E9733FC65E1250AD3300DCBC67CD6E2458DA0A0D9CC8E2FE470BF35A9746B154286C51FF61A23840AE2CD727AAED90B10CE29E7FC148A9E0E412C2EF1D72AF2DDB4F1D27EC4ABF6AEA12702B84767E6D0F1425451FA552DDB8410A9D8E61331B102965608301CA27888992B9BBBED8F81F7678858D273B5867A2CD5D6CB5D4DBED2A393B627290A9D8DDEAF40E6469C50000000000000000000000000000090E141A252963EC08B711DDF5C66036A13F574BB7BE76445A1D1F83C7732B9F4C25FB9E799D4AFA55817BCB39B974AF92F3730767CE7D863B6A3406450DCBC5E0145D10B7D532DA6E80196157C38D1B6D3C173F74D67AD8DF24ECAD4D9B59921418863A38270B982C4392225EDD1845AED2199E2C38B36C7E0E5D2F3CC7F6803926D977C59ECDAC67CA290658E72BAD633358FCDDE2A4B9C40169A0C7CCCFDD93E4DA3C3838E9308533BD468A9128C5A141C4842840E45BC8E4610A7C5E7535834C5EC73312A50197C76AE984B3521883F549BE04E27D97580E6D85D0EE84CD0B8C65BFB1AA005C607DE82DA70021F8F90B7912C67DC5657E1882CFA6DA3DE1BA4ED823789C052649DEBC9085C74528162243133A6AE5C1C6BCA3F730525B167D816485E40C208AFFA8706E3D74631EB4413032730A7647548B77579323EB03D36C2EC37D2389D4A17305F607C78F3073A2F4B4395BBC94AF163ACBE3C990306BA3F89AF9AFFE785C3F6D102FB2BD55F0C1044034D6A871293B31A1B38E383CB926BAF3AB4B5F79A47E9FA7B77BCD58AA35A7F16DDD11FF642069A8A327DFA800049BABAAB4AFBEEC9FA98ADB9796FBEE925BB70EE9E96540436E1473E3AE4C56D7099D8DBDDE755A7E101BCCEB596B9415F52374C8A3A73EC66B229DFD8CD7EE7D2CF1C5E7F490C7D9381D9321B15F84F640017851ECED1DC80D32DA3A0A57ADC3EF37E021031866E278C7D51FF5CA8E9ECEA1082423B41D772C5ADC61A8C71C3D4CAAAA3433928D7931EE715875BDE2BFACAA0A7F799B45241C21BD2ECE4A5944FB6890BF24908DE58DD3C76173373254A36B0B2AC7D67926948CC0136DD9A5079D776C297FB6A585C290D5DAE1C45E91153299EEDB731E527F0F62E83C1E93C75FC74F9C7E63311562B0A55459A0D41E034C3AF637EB29BC789E5920DAADF265F42F2707DD1AD490B5F8A8D24A9968BFF11A0C364A779EC385A9A33EDB9CFC7DBC672BA60CE5F421B40634270B982D619F8E7960D32E1B8A76CECD13A3B0214DD34214CB5BB7FD530058D5DE1FB9E4E88ADCA05926CE1F5597100F55DCBF64D47FC177FF87C4BD9F6ED7670FA7B7D339EDCCE6FC1EAE069E0C303138689DDFD23396C145B79AFCF68125989C8477BFC318CDBD69D1AA6D3EE41F4B1F9BE4BE9FA58A072412078CB9196556EE56FB7B2A2761DD04120FCD9AE9736F599C8B96BF8F964B305530A6DF1F94874F36F07962F87ACC0B285EDA64D2E4857E26BED40E9A5DC0327F1D91259292C608D6C6D59804DC23A34D1F9F1B69331D68771E41542FC5D669CBC3CD7F8310F87E8FE8F6201E57B475DE2318EA6EF9F7D32A728A44334CC9DF28DF77038C37CBA62EA8CC5EE80E571879AD111F35B6A154FDF8D40FC93360D547D02F0743A37EBC4AF178C6CE36C92CE6B80B6350202D2978621684A19AFE1474155BB962014587B1F5A477092F42BC446D7811C0EB439A6829E538077ABBBF03F515F1E6AC018EFB05AF79069C2569D2CD7140C4B1B47886064DAC695D59FDE2D8FDDB35318D33EDAD94AD4FD988095B1156FD59551F0658EE666186369BFA84E30672E4659BFBF7963C377F0039E08DE2C2D9803FC12D97B5E67CE9536AF12DAEB3B9903D8D95F336FF53286284BFE8D7AD13EC21C2A9BA93C9A97BD7F6148DE7C8CB41CA75A9ECC8F9CC68D888FAF6B3E75376B5B16F41E7E6B76A686EB365365E2074FB1D7EFB1B285A2357B020FD3E47B89943FBC1596F3FA8289AD844386A691F33DAED4B7A6A6729526160F2D32BA7F68AE6678564FCA05BD811F208A8FA62F6731F23D46027008246FD4BF3C454A39EE225245E74DA5910E7937B36661548A55A2270A9D27114DDC94DD9B9D4122289DF0A5700222A977F15FD8E36AFA1C4870BD3CE9B658E2D83882AAC5F3DB814346240FF8C8FBA3F36E52AC9B441C76B6F104A0931BC45E202ADDCACCFB93A486A7734A6D82B9F6CA911448F988626846D413D987C5AC860FCC0D5F734269AEF88D41A055794DCE832BABB7E306F622E5EAEFDBE1CF195E320A1ACEB4834B3E70061EC2D624C12EB35B16E5AAE73053A3290D4BB1F51FFDF48C1A7218D365DB7FEC15BF0F710954CDEC54917600014BDE3A901DAB1DEC0844D7FF148EDED9788CC85C0CFF26E5895D91C56BA6950C0BA8FC6C773AB4A6091A5DE3AC335DDC2110EB0144FD89B3D815EF4A26F718C1ACB5723AF1DA5515442A03CFB9D90623FB21D78DAF441000E285E9E7C235C0F31E258E6B3FEAC048DB652B83E07848D2E9357649372B1A55975B2EC7FCFED19D0B6613BFDBB4B5B01A9AA3128AE137BDC1D8FFC3A38B597578042CF183BA8383C289C3D92F6B70AA9B3364E9FC5D43F3CD3F310D229912E91D5806C2A11E0BDD208A2AF438BE77B43680E2DE67918FD414338A763910E1316965BF96BBF7DF639266D075E90EE9C073011F6783750764FBE4906ECDD94EE9FB7E4AEDB23EE88EBFB018C44FC8BAFC66E6B454A3D0E332C7A6B34C2E8D1D26416FF43D768CC36CA9D3168355F1A281A6B2EAAEAC7B64AABBAD2156A1D781A78A896248C56F3491A5DDA8C22C231AA7AE14BD558F66E6280FA65F20B246D815BFF1D3C6CEE6DF9B4AA7F750307A7BF73850E6BCD22CA0AD74B4AFC13CD4AA2FB7E7B588ADB3A46A23EC88A34F13214B261A283AE8FBCE8007C6EF6BE255C33218AEBECD3EC27EDAFD252994B70BD67407620D26E8567F4C7F6D636803B6A27EACC3B853706A8D57ADBF7F7E142FF149C35119A6172D5884EDE7C71E6C34D1B485A684DD56C9D670576B75CACB870A68EA7FF2BB461D9E2FDBF500B2F200110265A3CF24370A3F480DA66F98FB5327B4CD796EAF0E559A5519F3C643B59E3B89D05D2A9F9DA6732CDC2996408B7FAB5A734310FCD73FA3FA5CACAF31AB04EC0B9734407C6DC575350212239AC9092DA5812137BFC40F7735BFDF9827F768FC0363FC8C5739C7DF828075EA2BBE6321D5A8EA2EB7E397C3D58A953C7F0BAA69A96AC8110B125EE2E9701F43EEB87FDF58A6E6266BE1136437599E26E8E6E853DBB6ED9DF3931C5F402FD09B7E203AB36EAA6EEAE72E908BD2B9CFD379BC9B407F0C882807BBD2E91F920EB24137002A48F1AAA0CBDF89FDE5C51079F1D8CF7A014207F1B40773321AD952D77CE18EC7B48F2CA054E65420C1132AB67C832EE22FFD8672803CCE3DE7E9FD0690E55FA1AF5F11611E3E2C71CED55E3E347F4CBEB9C93BEC2B98E48495585392471AF0AE589257ED8D01792112C798BCA5107030F207CE567594B8433490D8FF1811F21B03A42AD0678927183321355E3D6908DC1125CDCE038CD0469D72458B6CC5E67EB0D78C20819C6F3C4518B15CC63754FF8679915E329DD46FEAEFDA5249ED7E754E7BD55C75CB764B6CC36BC06267B2479CAFBB3F0BAE32A93558190B65C85DCDC080CD56D51D4105C5B0717691D4DB1893EF8AD550F55855B4123A38D18FD67B588A3A4C2A6604E874D721359352B235C17AB1DA2758712AF8179FF433211B93078735F909F985F557D0DE52CB9203DDC67BF9DC8632ACD8D4F90196AF6BD2E79834371C5E9FDF5992ADB04AEA186AF36F56271F763ACFFBF94DF4B0512CA6B7CA8FF486504E565BDA367E044FCD0F25FBC2A6C720867F95BFD92109780D2E6DD60CE90A4CA8EEB8C4CAB289DCF99E687B017B37695C3B99B4FE97D7E5D52BB9813C04D03C9AD71770FE0986C7F3A3FFD3A261AC771DE88C7ACDEF253E5CE2B50BC5C576D132B68CCC694BA883770B80F5ED7D527CEE816527F69CA2C101747A0088879C3663037DB5B + +count = 82 +seed = 6CDB757AD36DF99E52F535C2680431D5FF36C812D8EA19399F666F2FDD66D3A842A7A5AE1038359AB618FA58A0A6E840 +mlen = 2739 +msg = 7785A08A3892C97D5EBFE52475298BA444674086D63E17E1FAEC96F6B10723447FC1B8CC758D1724A33E26518798183A4B3C99A7DA54038B86473DFAB8E626EB3BF54DE5581E04450B2821F5020C466505990B173DB9F030CFCFA505AA04B37CF0A063876843A042F17AEB1728787187428F8D1010D532C94C7AB2E1193994BFF0CB56415FCD2A96BE7F7FC2C57C8313E795367A22B6A17CE3B803083A74FDBCF030D91C957128099D6199686F2BEA618CEE111AA9D55A6F9E8966C102D849ADE596A1B576924DE0E92DD91FBB01CD93E24AA71EEF219A78430D84965672FE6AF091D46DCFA9AB906F6240913C1286EE0A152666ECFE2C154CD3FB14DC0F9C173E30FC9958A75AA6DD74822AF7ACAD243FDFB743E47E48280990C2870904EF1C902261D0BD6BCFDA91412BDEE9A28C628F218E7648AA0027D918B48EF30A9B18390331805C6739BF6A2CB69A0DE8766A7B3A448910D181F6449565A363430BA1C0FA8B11E1A151F6CEFA3870C3B1D8CD800983EBD41B48C5624269EFB440DF23FF9BCB31A4B02F6505DC862B2103F76137FC6560F893577BC3FCE92ADA27F291305F2345AC82A846854F172131B042735D4B76C6AB2DCFD32BB6258B23AC790AF2AF7624451172FA7A29E0C5FDB3DC3B719B274B2838FF7A8B25F272AC8EA90FA3C8010AC7F65633EB43FF7A0A95CE99717F35D3C416B0E0DA30470B5AA20EB9E2B66315B9407A4753DF8BF505B8066C5D57EC4CCDD2236B9C58BD7337925191ED7B75B92C9CEE626F13EADDECB07173C8160540FB9F6A4D43A1E9AB263B300C08966C247514647DFAB3B420202529E963A51F8D23BD0F689BBC4D67D5A603B876E8CD3EC0770F0D9694DFC30083991CF3989DB1812B4AC5452358075534190F012F7C0E47734C3BA748E04910783C0B845484461DCEA67A1EC731354B902557486B484F67183FC711D10F906C68CD01F46481D040F084271DD784E5B958AE05B65BF5D207EFBB5FDEB25366D6FF4161CA3A1CB71B2B9F90F86A315D800935AC0086D85D907A036C4333EA347000A0755550B68FE3DD7686E416483781B563680146697D6FAE8333C24ADC8A2436852DDADF6061E2B16FD3829C0B55C2E9C2C89F64CB8DA02A6706498CF0330742083E9AC4593A1762D32DC4E6CC2D9F4310014FB15DEBBEA324EBC2EA1E1660782559B9B39FBCF34C85FDA9AD350D195AD7587AAB621EF7FFB63277CE35AB43B01977C9F8DD6C2AE7B34FA7B35D5FA37D8B3719E736F18734CB3A2468BE9CA0832DDE0B958925A377FE6751C4EB8FF1AD295355302F0A5ED4E8F8C33FD5162542B8ED7CD985DBE3C84401830F6A7EB9D955EC74C7F98B02388B4E1353317CDB5EADAAC9025038CC01F8655C7FB9AEE940FC4B282748B39D277A7FEF462038833A9A8EB50A8719F68B3E858825911F294A80FAEDE9D4C1815844C2632DD20387950003DAB80B1A58E541A5E6658AF7D4CDD91FD1C08735B584F5C69C5CA94F6B7F97A4761B127DB394AC72E902DB9EB4B3E0B884C448FF2763FF9ADD530753263688CF92BB746181C17294BFFC2A0B3969A7BBA429A481C425B24745CEAD66286F5DF04F1E4421C56ACAA668E87BA58E3B07A062D1DA60CC6B411667BDE6F466B72C9169965BC7781DA78A818F779A9B3D7A577F71A1DF49AAC865A0D6F2668CFD2C77CFA8D306A14DBBDE4D3A3818B07DC89D5F51E117F7BFD007D60F32BB1B6BB01E76862398371FB91E0A3D4B39FD9146C47F627A066618CF83C32E5C82592B418BD2F5DCD8D42234625974F988A6F729C60BA5EAF18C77B611DFB187A581E3A10268A965F650FE242CE2FE08AA71515B59A6EDFC9CBDAE22DF3AEB22E773CC2EB373619E9CDA23C236CA3F7845C2136E93849D9F6AA1477F4513358CD8CB4E21444C9E5709818801EADFCA23F2C23DDFD5B4EBB6089DAEDD14A21EBF3F7A8C1C80BBF7D37973BD156AC5C4462D29DCCB7EEFFA22A8B6CE433B600532F33999ADC39196F01230614767285089FB262D8469DC66D24AE0B77FD05C3EC02FBC5EE328319409B8E2D7B0AC6801C1C8BA86F793C2037C71E2A25F114E9EE0EDB3B83076EABFDAFEDEFA0548DAE91E62CB7C29C03413235B8C6EB9F46BE29DE8F5D30E8D97DB6F45687DC4719B1024E48B7DFFD0D2B474B2032B4E69B6382E603D4777F3450E2E467C6D9AB2782C0AE266C320D36BF67BD6B86EA9721B22741684D9C0CCC774335430071A5410C1E34B4BC1A823A93A38F5AB4781CC593B13A593867FB634C0C705107CD278C6CCEE6D842748BFBD2FFD205C6BDFB3AC87F693C25C832C86D96B00BBA0AF88DCFBC8CA4328765DE27FBF1389C4EDE28317BD0EE447F030990E957D223A5EC66CED9D16400AF6DA8663C4E4111B4584F8F0066CDF8258D90C5D7B439503E3AB3FCC55FDF933E06D704416187AAF86E6C39695DEA8B8189EC1299670BE03B6A636889CB7F10F04CCD67278E77886CF3F6E2A05BA8D25AB8664EA817642ACF5DB4D9B3EF80E169463EDB6BFDF67172E88D233609B091BBD085B970DB8AE0DAA5048CA42D6A54042F42445BAB03F9BF1ACCEF341B7349109BA0073D3715A9073AD9BED258268AEE9DD5202E0EDFA5720A317EA5CB41706C0D235465BECDC8E3FF0D628EE5EEA6AAF1BBD3E18FE9217516893DF115E979C4CFFEC494988B6F9B86026610898C44AB1547C5F8ED5CBF3C3A837DDB6A444BD3E803E1824E6AB931310FE86B36587F1B34B0B48D358F4B97E9774213DE7D92571380BE2199E703119C5B9836DADFC826B71D588250AC37DE0EC05C5823573C102BCE44C9F044507671C4E1723950A3C0E14968CBABBFEEB049EB723DB9B23CDF0273525C29CC5165530A1F1CF830D3551DD6BDED53954947D5C334DC9C71907CDBFA109EBC52D6305477C14159257AF8C51C6F09D76FC0085C3D969EC60FB09145E66A8A7489611DB3FDEFC35202B8AAE82D3CDF666034BEFF49FE49A45C5EC438F4118F338545532CED916DE78E3BF82B4E55907474386B9C172F393EFE895334F7323CBB2AA7CE7718BEF5E7A23AF734BD4963FBC7889AA5C50F3955B904B5E577D71B21A293D766865E3F8C212DE5EA084A9D22748A8009A7D1858328A1BDF7BA0F4E3B83BE9707629252B3339CEF796696855A574B4A4896CA68C3D6A6824E3F593069EC0A571E61282F8A29BEB8BD788F7B351A8939CDAD9E257587A77804F2704F49DB3305514B85B449AEE56EE40CB2A75D51690194284AACD0855B02893F8DCD3091629DC548705A1085E5CC33DE7726A0F521C149003DF380ABDAE96BCDA55C44BF9BFA1103150F049563E848A8750625DCFDD9BFE02E1E57489B5B3AA28BEAA80F4DAA562DEABB4BB6A27125369415885020D237A92CCC3A23593FE2183225BFA2FF39B0BEF9CB0425375E256BCD572175483F713BD38F937F2B3D4C1F686C5AF60061E0B05CC3EBAAB0AE8BA21E47A8318BEE4A01516046363D152936A1344E17A65E08030522EC667233145A56001B8D065DC2FED0D2A9F02C981A8962F984916314805DAB644A5112CAA1564895121D8B1FD046F547BE282CF979752883EC79AF70CF59A88D960F3336F0AE61357877AAAA34699A876144B65CA5B77A684D850D09B3D42CDBFC4539EA103F8377CFE5F9E5432403FAB416662C4C83226191EEB7F82B01E0819C081FC40E7B978669C7856067E8B582832DD0B92588103C2616BA2C7774C46840318CA2B1A3798FF7ED9FEC087F01798EA2445B92E67E2446126A7406E82FF8D3711311BE16E9171531A95C966E6BEFEA34938E6F5FA660F7C7CB533A119377F1D26AE6AE51D805AB96A64C8B80D6EE137F634B384C2E377 +pk = C9FB8933F769E24C73D4F2D8BE98B79C05DB7E9213B039B175E540225397169E52338E6A0267E7816603EF011E89F69E47132CF01F39FC99D3CEE43FF0D3E976AEAB0BC030441BD2359A62D8CD8D2AC33CC5DBA91268806E641BB5D4465CD466848434E621AE8C8448B863C94AD2D0B5428D1BDC5158EFC1713694929FC82774AB9D143CB63175DF217567BEF7EC55A6C2ABB669AA8CCECEFE6893FEFE2BFFF5E4751152260FB6F4D55C23A72585978CE90B084FE737AA1C501658B33FAB136700F7E20013FBC401742B63DE68422164F6A5CEC869C6FBE1712B1762553B0FD878CA1E4DC6BB63E8B05CE6603DF749386A5C07FFA981E6E75B48D9215FFE504CEE7F70925C69C62AD5085869073AA4879EB7E229C860C9AA1E9C06DE1413B42E4BE8D07CEF28E60A14B7A520DE0394E6962658B24406FED2202BFE42C9613A43F6308F1C984D82E1EA8D659884D5A7DC6325AF27ABB988DD335D8788F7085BDA65684C2F67A9B4F869A1E70CE63D9E72F71AB794F242C33D2818606895F30087BD3B9B696670E92ED47E5C9CF519611DB02D091295F4B5CA61012E683711BCB6199AD19E9607D7963478D668E81D9ECAA01AA8E99B97F787B757D15425F9CB46C9ED66FA5CCAA99B3412398C2C6D3B735657A1ABF9CEA32B37B418851AD255AABF091A8D05544D749F64EF94E52148DA2E1CBC258B1676B89888C7B81892EAAF0E74877628995594AEB8742D4DDEBA9AFB16DDD15F1B8740770B171B5D8368B77EB818DA1B3956E75F9B38DC5D094ECB5381BD5489BA393C832D9A0C29099B5F1DE6F35CE919C4150E54C2D3CA57BD661F7435782DD38575C8E6CD20D14C033AB5DB769B177CE73A124FE1F04640DA5F639566CDDD0A8A780593544E7E7CB46DDFBADC95577F067781D906AD5C47ED0CB601BF4E9711D6464CFB9E4391665C8928CB61477C7776D519E62E63A3DD2A547D733382D0C493FC474E38FF464BD30DED1395104B63693FE82160AA0C3294D14C1BFC47ABE2AC02B0C2C26FC91BAE071A9F41ACDB971DD8D41ABE1A4C2F26FD0C74706296384A9247CF7C8A5BFE201E0CED60F57E3E4F9A30B545CB3F1CCCC521ADABE4C9D6D8CF7B4D8FEF71B189BEFCBE7542AC0E10A5C3B7F32D1C677A4691B78A5476B439BC530D3E6EB9AD9F60B847F9C9624F1B467C3C535152BA4A8BBE91826FAB64819487E9C295255085B0E9F41DD4F0111A9D6F9C4AB4065B4D0A54EC3F6481E84C78E742EC47252AE68D5B3D5CC0CC738BA2AAE2698FBFD396C56C2E4EBB522F7E85F4CA6D14FF8B2969A5655EEA2118D9E9F37995E1155EEC58421687896D158AECCA328C0CB42935D78D4CA192619ECB264B66AFDE35C4F3DCD290A50E811D2D0AEE056E2671D6F400665A67EE94EBF976CC99EDC726CBE5EC741A096F37A23EEE89E8DEE5D014EA708BC204AF9438481C3A06D1736A083DF184F33D35B793F5D18C4A5FEB8D126A6F91B235E7F88A12108DBAE57973A2A1E325FCFA47A6E5119B16A2058F0529DE202E379C3810930B17AE5891B44B357772C6B983BC55DC58357CD07E7F07ECF948ED9D826AC5FF12C396C8A2E769C7A86B277E43AB35BAD34CC064071CCCEC9EF5A464C0FFA7774FFB7EDCDFB280464041E841F223F33DB50F59DADAC83EB6A90D507622AA01C87812480727EF60EB708E7B3245E7E59EA69576407F1F403C2F08D498BBF2982872764F6839A7F098F4CD32E1A1CFED4888E1DC2AFB82AB44B17037ADE779E5AEC5E7443A1259C98953CBBEA62499F391EF7B82E33C473D08FBA362BB9507B44B3C58DA2FFC6FF806601A6653E6A228375579DA5B665BC08C15EBE5A0D57A562DB94C7305F5CF3DDDC2D78E5245BB56293B22E4808987B637AEDC8D3482AAB468D98A7978C3AEA23A2C4F58CA2E43526B0B845FD7EA3BB76352999304B67F14D62CD1D20273DD5D764A8C12B8CCF8909A65622FC3B3A756ECD0E1F96193CDC56F34F5CF1E0512D1C8A90BEAA29657D05DCBEDBC9C3DC9B8409D109BC437507C81064D086C9B6463001A8A0275C7D997ECD8BC2B7DAD0879FC15AEFC84E6FE41A11ADD60B14E748AB6262D266B689C37B1B73BA2B26A04844C491262A6627B5A99924A4B513BFD6B5A79FDA9B11E6B714F50F94849BBD57476E00A2869CB03979ABDF05083D97F69DAD5B52AC82149BA4DCE6CC69CE3FA9C1353DA55F4F94F14D898C476F181116B95D02C0FDA75FBE48B7D751C5D305A90BDA986FAD24FEC5A1A07D0E4CCFEFDE555911B312CC0FF4AC1A3F853438FA6E29E4C01C592DB6F84CDC56040EF27F0943D3611073EC279135BB3811D58F6CD1222FB787E2CD1047DBB8A6A2275C85595EC1A3162300544F9C6773C0C0256AD717A3B0DE7614AB53038CAB6E623B7C281ACEE494FBF9F2EB758DFB08B82FE06155642B12B66B1B68DFA54BF4FE6A3B7FA861C9B48D5D07C9A1BC053AB046FDA2E00498293569B2079F6F554A1EB16CAEF5657381658911B28AE0EC0DA48A79B6CCD6D95EC541B6ED1518BBCB5C09C401C50E63A28C0DA9618B93A92B2F3418E54FCBCBD68DB24D81E2236578D5A9091AC50E58E96D7A16A08B64773DD6349A1EDE4CEB52B9D8287AEC15FCC6188A6485E47FFD54B5F098AC958E92C9FE10F04271B24A3F4571504ED908F4019FDD1D06F2D0A91653E99AC7FD79CA50C4008EBC74FDE56BCCA9E903D6AE5392B26F97AB32AEA3AEF656CC24054052EE72AE4FF09C1E81C +sk = C9FB8933F769E24C73D4F2D8BE98B79C05DB7E9213B039B175E540225397169E887B56F5D5DC779AEE62700A7157B9880CA978703FA1EFC3FF8B4EF16851940076857A9D72228749EBF952933466EB5AFF20B1BFFB9588F2A1BCA7A14A2C48563CA98290920A2B1024532DE08CCBDC5DC9786366CAC068AE1B8ED91629756012268577375484377333152335007216311767015218814662780406751026517535317158802384543650666441606053450525731837083241455144524678131740307332065775483653720452073805558722425634235325888480871442170001537822577656214336802443188417185323012320325116848316113730171121351050475355422877538060823012613503800675437660664421550302103486217001145505002770882562432520438471446538117422018586013067260528074073325270730846442302521528242606810150652600117061882131242250881074771125038784605207030363625281325040052243641407803072687837475546800535268352622733646017212511256626434634712437844680455783211765614181528504364885808617823404877607421460204276762806360246814235202412213508706553883134312714801721706732181512218727748711838582878648067800625208615768615732113514868254436533372210036334516351851624486255151180268284305751662077036087573660272786248236382722802382045244162387105015544435042842321853423874087033238286870761387855652327252335243875513051334635842637204004841332006132043007421615482702303506808605533757024523161018003664840175575082771682373722770651718357744172642147124850630017024144281737677586402375702104784364481486268305753145045536082816562073577678884103728102404045020488627770682612074485218748526458346588002633112620144057615505872500821376514773643833126431740334673022185815120226538177407146650284680157235517821472217833512843800386847401651866246112803054685347774754357443710310527458632011247320661106476321242188506480133445324138630777412307085676028532620808376167184253273663328418367133753588450645525308227123373552881383748362736877435373517088614724152278540655388761535781551825672212884473665838238061431687704635423752526325510444336437583776457712180526758566565584470408655128152131176755158268262875638048331451265047642606088135316810447517364747641101057704421876612468862642638006700058750011355105487375255325112057383158265254348251270668804751208214302738086685086278656074822115166247387618604765338062232644062172867628421627868305161221252702150450668377270084081182531541562212672478244244572731141608873435427601165276351470305675846708281304260872028744086077177808478563088501342571628708632455408818155134054430273584874788758780413102825461435164512013017270267727786162243138673411463366473676048447561526235328648830016082582242310653663657062250681483512207513312286704117258070165006287674170405012121455448001270208722033517373643684320216365611440315758388718353440053450154076578435850357128751843200811040746505603648082185617141561588623211717702436024015654713342221232304655406725273542071774886580178061822867670818286473651516170613774246314337581525335560186604037831811340880237150700101317158466247561108636502565316635852404083204126307336845035756124658147447115321536748048750582463764605170487244778737052301706810527614755EA5926759D123948D97A475BB8E946F8E74F0B7908348AFE1A55472E14F6A921B9950A02A9970262853409D50BE412E1274B46850CF8EE66FA7B7EA18FF20CF45666212AFA18A582104F2A5FCD21299A4B9044A11704A6999AB0AD97690D7A55143DF1F5B656BBC7D9F455059FE977635B3D256B21CC64A2CFB9AE541A367F17335BCCDE802E66CC6B4EDD8C6466937E735C7D59100BB59E87812745838837ED0717BB2FCF59BDF785340FE5333CB9BA4853894627D609AFABEE27F436A0C54DECF89A99B8557789F7550DA88A098DE31144FEEA6C8780A70F8C634547B110539D89D0FC85C952010777AE8ACA7B9F912F7E284C2AE7509F02D4B6A2D0758C5D9B89D0AE56F1418D74B5266CBF59AC0D48923F8D8BBB04D42DD752427A9A69053133E86EE0FA25110EE5B3A96B4F56A854C9FDE0693CA17A1CA545334B33789F3D6659EBFBE6D45D1A18922549EF5705DA4214D0D80328A7F07C8C741F9A4FFE25140516832138267D2FD98B7C32E135F0138C86F400A49DC5FC39BF8D519C56D0363695412492445A64185A52AF900B720370983B7F610D74691DB0FD555C967830AF8FF3B440331FA9656EF0B6A9DDC7D252D3037067AD73D29BDFD858E1F923111221CDAE314D3CB0E979AF6249DC02AECD650BC8BF204DE02031FDD27145FFEDA22B3F77102B5F7644B7686E47CDC39855886EB0CCF9B5719E551D1842E9FDFDBFB9016D1BD0828E6447AAFEFF75BBC31A6EB3D5FFDF612819D02EAD7C0F44E27624A9C43263D02175B2EFB9C24509048C4832CBC5F4E66FA78E59D780A94D104D609D3757DD6111F3FFC1D11316BFE42F2B8BEB04F34F1021B4BB0BA39AA05758E8D5A7EA1520357AE846B2D96FED4E5360910BBAF9DA3F2A355E381607C42EACC1FF423F272267BFDE79EAF594081E06CD93F159D571722062A310DF347FE4A59DD030E65B17738BDC1B4D6101D2D95F2BC4960AD6E99FD845F6AB54AA0FBC808C5C0AD6E73345CF98D00D4E029F34851D2A515729D6AE3A489C1B62353FD2D33067D2E60B887447CBE33E6C8198FF9FC8A953146DC6C39E4AD7BB17A2B457FED23AEB3439FA4124E02A6D9F4BC9D9DFAAB558811C465182DA1EB81F559169CCFFD6D2DDF885C67000952E17EA2A4687CAC34F6130F94803D2549302233174F4CBBC2C1F51869FB74EF60C5AAF9D9FD60D7864FA395A9A91211DCC9992A20D4EEA95392C188E68EC29B4C0CEBF84FB3816DB935C62469FA6F286464262870AA79935D2AB562145975EE411D9C5D0DBBF852FD27945DA8572A930122D1F2DF9588860F1D15BB769E2B8273C265F88573B624B184FE618E21D943BF43DCF9EBF0AFCEC799E7FE642BE848BB33133F4B3022D531D0B0D6077B7283490319A7BFF3C461042D576B6E2EDF3871B676A8D6DFD538CA1504EF7A4F266953BE54977019FEB54A21E4E8297F426B463297D54C70149B9066C52ED616E053FA979E6BB53E75FD57B02D0D59663FC726B0713B12A30EF7E85CA0F7960C4CCA13B85D211464149926944E197433BC846D5BD048E568A6B73F50760A8EF0C00A30007B5E6BCE4B7173284AB3780707DFC1258AAF158C9EFA72D8448CFAD7C684E6A8D5864559017E9438931124DAF792E423F34E94CBAB506BC883455493FB5AD50B5718A9BA9240F832DAC739F29192B838F28D762B260DE60B83074A11C65CC6455D883918AE63D330DB7D3ED395E7C96BD289A036CBA40C8F8A3FE8092799C849E1704E35A4D3B0EED876B62E5CC17365C1F749BC46503939DF631AB9921D56623BB45249A6137D1A19B11A2853DDD23BA88F4C8F3B3D739A18EB668320DE9A6D7332BE9A659E99DB291A59F0317DE689336887FA3F02A0B4ED5C1F1C1D963C42CDE5ADB8CAD035C337535B14A6A2EB3B23396AE8A0555782E014D73CEC246816A745BD3B6C890A4A8677F85D35A72669ECE2AF4B8CB94354F52F9DFAC43E97A92654B60D2A200B06ED50FC934F5CE20F213FC86655A431D6EC7828214098BCD8C228D9AD51D29DE0F258CE05AFB853C62AA75678587D992699E1909903FAB1B866087D98F41BDB0D49C36D077BAE44167BF510F91D40E1B0FF28D3B50049B3B3264A79A122B7A89EC2E25A51B4F1E13BBA32B18CFFD2DBC65A83210E9AE846A595EFBDBAFCD7C80FE8E5424877AA59C545ADB40E8E7B5D549B0A33E69F57A58AE28EA28C6ECA98E65D44B9C78C9602A22D16673BCD71D6C1CC25489D8F58CF9EA8687423B9774A3B8503335F75A58363AE096FA6CB86BA059C7571F8733172718318B4023A91FA56C0BDC2F6479716730D533073C1D0A668152B61B82A0A6853D1D2F04E77E1AB7450835DF62A2F452910A57C642BA26473F0928E92B8D4306B95807F78DC4C30C4AB1632CE076D3F182921FEBD8CE7E66A0EA612D2D57767EAB2E2F2A56AF9737948D1650515C23DE9D265F8A75FD3B479F2ABBA09AAF21523BEA39EF5E2090B87C2AB1D233A86D5B6A89C3C0A302CA878DE2DAF89C728DB3B06EE561BCFC8333F5F40399BE6E45DDFFF540678F9F225C08B66CA4885B8CECF2CE74A767FB61835E8282594D3667221DC3A34CCC2E8195CA837426890A5E75EEE630E45D0E31284AAD0E79C6F170D8B11AC5D4CB39AA4C238436A0D75E7BF9D4D2FE3D61F786AE5879736621667EB07AB45C359EFD8C4D1138D9FC7E09F4EFF1D6317DBDE103E84E04B896060DC10B56CEB7C4BDF547557FCFBB989F15DB6CA0A5520FAED7C5D8DE08AA31AB5A7045CF216D25C0E5575A7791BE5758058C65961922B2079D95B9FB1B949A6D7F0B754F75321962A8868CA191019DE861E6B140AE94E2F55D244541921C3C2C45F68F9EA44BADBB782757B233235131010CAC52F3A4630AA55E6DFF31B590AF69A1446EF80C41FE59C321F3DA746F28D50E1A262CD0E6DDF422D89C04365FC50653E075099C3BC12D889A7CC0FC63836064F240E8E2CA6F035A87C14D9C6004BE80A6F85BB1D8B6F176C08432C8BB40673F651E0B7F4F50171791D219BA886BEA2E038E19A0DBA1750175297B6450BDB59F2E0E6ED10F71E4556443552D431371519DE9A4F791E00A60CF572217D5840D3F6148713A4068DE80693B1A3ECE6BD702A62B96CA88E96A577DA2F5FC18BDD8B71994EF2D52C7DEF5194F6B5F0990967F2022E50E4B1D9A4537744F378C8DB219CD9E604A9AB9BCDD22CBB46A9B289BD1B922797613AE1C0B927A44E1538BBE049A79BAAABA250F4AEFAC537FB529C9387048E04C259AD10B667027F80627FA232DE1EC839A66925C6BA4281134691FD0815D3DD82D7849F462B1517A2C51B350EEB60942B8FB2E0C5E4CAD2A731F5BA9044F983C83CA52D986BB57D7B72B26379081123BE83D4F26BE432A7C82041233692A048297B1E3322CE446A4B6671F5799AA2F0E0B569B0F4AB9F3A0AED4D785EB4220723F84BB1CA7AC5DD49A417E3557B923BC920A272CAD8B49F92DE4D5CF7A8FFF8DFB7D9C70175135EBB88BE04998833 +smlen = 6048 +sm = 7C6887EA7C5AC675687A9785A558423E314C48AAFC635D3F1B17C01C5FED7791DC50E2FB2BF9729587C0B5F1ADAB46479700822D197358C11A2A258A58611E0E615809F356F8A94433ADBC7A06080DE4E9BE38A20BFF0BAE61D7FEDC2579D8F18C7FAF8D607B96BA83C772DC31EC7DA227005C70BFAAF86DDCC54BE3FFE99E7CC58FEF06D8E6D6F6005289A6204D4D24A65B16CE097DE187C81DF2A93E5F2612C6850CB90A95D3581CF82D6DC0F66EBD17C79100631423D0BF88F93819A2BF9141441CFEC2676EDED4C7FAD2D80893B9EAC651ACF372C9C780483CA13CFAF0C850A6B0070BD12C64EA77825B807CE94A858E69CB991C7A8E40E7033CB1FAAC32E94A36008C85DB9071CE87823F57556D71F4DC0B742A8254B01CBF3B864A49464F66D072EFBE02AE859274BB49D93BAE64CB602645F5AD686B89B49A87A236FD1B9CCDC3AE4FB705993F334993F65906425EE3B5F8945AC4BD7105CF48C1EDC31B0BCCBC1BEB896D6A50A48ED76630AF909AB6A967D2917F26941EF2394ED78EEF05842E838D18170B8316DC7A9AA9FEE72B9F37DE5E08E3314F21391E395F9B09FF90521B19D38FA33D6CDAAF544A99216B6B322F17365844090288EA036366DB886E86C46A649DC91E0E4FAC120B0D819332A88BFC48504975C9F34587941B872A7E13A362103C1EE2DD4C2C3360C1211DA3316143418A42A5F1F723E61931671383E22784C05B501F25949CBA4F45888A14862E704C1E756022327029B4F024D362792340CAFC6E7F42BEA471FB790D508375249E49D01E6C5E4491F07D003BFDF3B3354E9AB761DCCF9B69C47D4D1318A8D2C4A9F4919B9A814E4757FE3DD2A65861DACA674731CC80EA45A90A55840CDCE73AE798D208107A894EADBFC147BC6892B309AE92DF50A31549F55E54335FCF7CAC45BAD1ADC9079139C48FE3695492E40718E5E9454729804EE2D1F7DDFDBBCEEEA886722F8BD3A36B8FACC20DE82097F123CD616B1F51B1C63627A6D6D23198CA533D90593BF9DA90634AF96C7D92EB768E34707011C7E878D4DC64463BE38138B8FB9E00486A5245B25299F163A0BEFA341566C7EEBEC13272E7D0B512032CDF19EBAEC7EF31D0D3418E66BC4C894A2CBF8943A1E987C878B6D33AC7474BE337C5684807022DA1562CCB86A240DDBEBE925E5CDF95ACC34F0C6C2D7C089FBD9B040AF9392222E362AF55243E8BEE6A1EA47E1C3776CE96DA4E21CF5CA17729D6112A3C8C55251004D97ECE1AB0AEC3B173513C54204E290A892DF37D5729F0CDCD1EDA2A2A6AA6E3E8B06EEC648F09A4D6356A19A760D68BE67AC231674FC64E66ECAAE5F9B8AB8DB4A876FB298700917A3065449705D22A7AAA4067B27A180A3F8B11F25B4A3941E531175DEDDAC588D4EADF988C6CB7C4826C99F3DA91CCFECD2E74F895253A377EC62D96D676A9022BB04F6909F81476202E7123CDC32755D33BE64739FE86E0FDB2D3D476D2B67173DCE5D4E5747040D52B00A44A95F69760A2B7E751CF5E5244CCA62A9F8AB3D7A4888929B75F5952CBE1579529CB6BCBA793C8B07B1ACCC01B4A42DA5EB3590A9443F8F7D71A989922F981FB45A501B5CCE3929F15C2CF5157ACF66156806BB6142EB245BCA140D68203FDDEB7207E8DE18FF4341ECC0F4B24E50CB200C997D288A02D00E28137ADA5643C69C6009D3A85B88C7B680B436F033B3A4115DDEB0554F3F197F6625300B8A592A3A82FCF9E2830BC00E736557059B9B148067DFB8562E70EBA16402DBA7785901389EFB919A8AB20ABD501F2E9009DE3C6EBAF285972B0A00429F3833BF038338E0FBFB3696D190647B482EDD95B750B0C5F57A1C3E75CFBF1A70779A558E4C25EA8496F8B37503173A3D6832923A101FCE09A4839F6246C4BFA7BAD2C054D75B4F884447240C9549CB2B6F30581826B925058CFB8231560B9FC70B94713045F9A48DA4B7EC4D6B92F8F86CD220568440B92EC4E813AFA3F4F450339272F1AE6773D4E908714E40BCB4A5A83C88DA07F9EBE24F44DCF446390F363C1A9420817DA32EE5C686E9E7C509B0819589D5C4854A52D5BE7882060079B39F055994C5F494A750E040930A93B91180521431F7E92B9D5FF7CDCF03F09178A573338253E823C24CA268FF30EA81763A731D6228417FF3A4F3A6578CA27E29D4604E69C6E50FAFE2607333400F4828B9BB1FF186D9C51A63DE7E7B88D5B05E98AFAD72639F7FF7A98755DD724935279AD92D725C31308B95510C527D02DE0F2DFBC88A8D8C8DCDF38F6C56761DF770B2B7CC2E95A6443F85F998E915B34A321ADD2811873865438A6585DE41740D083DF65BB513BCBDED5FA28D87C648DB646D0A290204758D4B1FCA3E14A75EA7FF3357C18E0C656E1003898E023E568849541FAE7C93474FC443038626A534BD3B4BE5684846B51870570D5FCBE553D0BB095460868675A3944C7AF0A6B8B21B78E36DB6F0E329BA81258AC218D8E7F4C8586D3358E7AFDB295C00F4BA8C7627EC4493CBFD19436830D0553A7DEA3883BA67D87EA669D30590602EAD2AA248A733015F4704329E699D0A3801711F0F67F1917DBD93B8DFAF53AEC640B9BB66379DEF2A6E052CB3B75BDBE63D8241CDF499D8ED2B058DDDF2300C5D018F029087292FDCFB6506A4B10EF7B275155166BC9A57FBAAB3F9AE78BB5641346053E80406DE4CC8C534A8B46A9AAB880AF5C899995A65B19A74ABBCB37B7C7A9EECAB86ECB4C3C9FCAD3E4990BAAF6805C4D5DBAEE734EC2B33434F7F5D9AF3FA30D6CA2817C570C3A506036F0DDAFB0EAB033AFD3B026D6447203F2CD39D29FE3308610787D0F6AC05FF9E13A512EAEADD0F03927B96F2B6E451A60B53AAFFA8617E3C5C64BFB75EBFC97A058E1B197DEB44838E29E15A20D9EC71141B0595EBC2FC00BEC45738D758422A050F7E938A7D08FCA9F8572229CB00DE842F24C9901660F4DE09D65286CA6C0C399B94DEB100009D16906D4F1B19D6CE4E8D7C03145C1B4D39851E4CDE88F62AF20CE468ADDB723AEAF8DD82CDAE17418E2849EF96B2DF3910C1357D6DA3BD55B58FF190D9A7C16F822EBEE67906ADA132B7A9519D285BCAB6B36B7F179C2F34759FCE3F91D8DDCC1A64C84D8D2A7D7F818DE12610CF16741246CC9D6CD9C0F3037B5104739EFA158592887576547396D9626763D6AF62B7A3503D7A99D45CDA703E1AE3CC00FB608436A29450E787E002DCCD3A7DD3783F64FFCCC43C0CF5642152EAE169097DFE845545DDFA2BCCE845E52AD2235D90A50A01F7F5E1803B14499D9CEEA2C8DD1D18C36CED73E3D53D15C5F7C7D5D2BB16DA3E85DF186E2C8A9D0EA4A9CF8168B326CEE1F42E28260EE97EFA38A4806F8596E02A7704420CD7EEFC8A8D101DEA38A78C50C01753B50D92AFB4E0C795AD6B927FD1C93C5AEDE27DD07B926F743C881DA0A900A3034C619F5DF0C3CE7EC9E5A8279738EFD2D87A11260CCEAEA4F0478C9737136C1398052A7223A6BD067648A7AC6075BFD2EB432B545D3738DC173E20ED5E74E7326627F1AF69C63D6677022DC4BF3C5053CFB98FF2D6CACEB12E150D8435DAF9322D3A5BCC8F8C8BFDFA7D0B863AFE89F8C4B5CC25E945EEFC96EC45B9474F2AE0259142CD5D4E8A0DF39D96BBF28FECA5FBB815D8F666A04B469EAC360CB3613BF48BA6D85D0B4A8155CEC28654F2FA0CB9649967D63A88B5E1DB6721F6140689BD09BE9E5A97BF013AD4B0536ECF31138FD4814AE8269F72760B82C5C83E777EC688327FE2E2B25681F83240AE65E00E48E42290AEC214FC0F8C68F3FB8817BD41E69FD860C98152E8D2E036B915C2E0CF3CABB027C4FABEC8A39BF0182FAABA300CA6D20A92325A717BCA1BA8D586BE19F1EBA1AAE93AD01CD75D5E2BA71AB0358D0A9771A75488298B0B9820435AF4BF574B777CB4F85882FB4BDEAB9C3574328CDE428865D82048D6FEE9CAA4B40BE71645FFE82F06F27DABD9906BE1B488A1140EC214CBC0F3395BDB4CD23D29033E2D6A703161A82A418A1E89962FABD06AC014A1DFB9007983422F3CCCACECF1FEC676D6690D739DD87419DFE28F0E3B8734FCA63674119DDADD0068B1747AE2306A80E4D559255C7F00C47A51512B4B1227F2906ACB9FB15861059C77C1BAF0B141DB5E854E3C4989BD0225B6B1F06F2B7707DE0F7583914263BB10025133101D69066A5DAE476B6E3C4CAE6C282790609F359A5C7B5596BB68A63C1F61AE629C6227D98130A257D73ECD565CC235A97EC2CD744D1D47BC8A3C28F1D878E38BB01FF08EF9E4D3469D45616C99F53192A286A2271EDF8BF5A04C441908550B9E597123E6A333ACA0434E68476FEE4DEFA8090C08C7FCBD8C78B714656F5A2F409CCA534F90F330939A55DEBDDFCDBF326B12B93FAB95D380E14797002290467653B839B871E754C71310A148502F12CC8560887854FD7A07D9CD4C129864D9BD6A9FBE6938FE4014B0139B88719629400AE08ADAAB86499F8B5E6A75AAD925B4B2F0FF6B2C3F604CB15B235BAA7336C3858FF8E389ACB63DFEE1302B42FA52781EC066627BBE227B29672CF7F552754191F889295D2F7FD0F515557646D99C2F728296184E21C1E2F70C2D8DBF1F98B8D96E1303E425D99B4ED00000000000000000000000000000710151E22297785A08A3892C97D5EBFE52475298BA444674086D63E17E1FAEC96F6B10723447FC1B8CC758D1724A33E26518798183A4B3C99A7DA54038B86473DFAB8E626EB3BF54DE5581E04450B2821F5020C466505990B173DB9F030CFCFA505AA04B37CF0A063876843A042F17AEB1728787187428F8D1010D532C94C7AB2E1193994BFF0CB56415FCD2A96BE7F7FC2C57C8313E795367A22B6A17CE3B803083A74FDBCF030D91C957128099D6199686F2BEA618CEE111AA9D55A6F9E8966C102D849ADE596A1B576924DE0E92DD91FBB01CD93E24AA71EEF219A78430D84965672FE6AF091D46DCFA9AB906F6240913C1286EE0A152666ECFE2C154CD3FB14DC0F9C173E30FC9958A75AA6DD74822AF7ACAD243FDFB743E47E48280990C2870904EF1C902261D0BD6BCFDA91412BDEE9A28C628F218E7648AA0027D918B48EF30A9B18390331805C6739BF6A2CB69A0DE8766A7B3A448910D181F6449565A363430BA1C0FA8B11E1A151F6CEFA3870C3B1D8CD800983EBD41B48C5624269EFB440DF23FF9BCB31A4B02F6505DC862B2103F76137FC6560F893577BC3FCE92ADA27F291305F2345AC82A846854F172131B042735D4B76C6AB2DCFD32BB6258B23AC790AF2AF7624451172FA7A29E0C5FDB3DC3B719B274B2838FF7A8B25F272AC8EA90FA3C8010AC7F65633EB43FF7A0A95CE99717F35D3C416B0E0DA30470B5AA20EB9E2B66315B9407A4753DF8BF505B8066C5D57EC4CCDD2236B9C58BD7337925191ED7B75B92C9CEE626F13EADDECB07173C8160540FB9F6A4D43A1E9AB263B300C08966C247514647DFAB3B420202529E963A51F8D23BD0F689BBC4D67D5A603B876E8CD3EC0770F0D9694DFC30083991CF3989DB1812B4AC5452358075534190F012F7C0E47734C3BA748E04910783C0B845484461DCEA67A1EC731354B902557486B484F67183FC711D10F906C68CD01F46481D040F084271DD784E5B958AE05B65BF5D207EFBB5FDEB25366D6FF4161CA3A1CB71B2B9F90F86A315D800935AC0086D85D907A036C4333EA347000A0755550B68FE3DD7686E416483781B563680146697D6FAE8333C24ADC8A2436852DDADF6061E2B16FD3829C0B55C2E9C2C89F64CB8DA02A6706498CF0330742083E9AC4593A1762D32DC4E6CC2D9F4310014FB15DEBBEA324EBC2EA1E1660782559B9B39FBCF34C85FDA9AD350D195AD7587AAB621EF7FFB63277CE35AB43B01977C9F8DD6C2AE7B34FA7B35D5FA37D8B3719E736F18734CB3A2468BE9CA0832DDE0B958925A377FE6751C4EB8FF1AD295355302F0A5ED4E8F8C33FD5162542B8ED7CD985DBE3C84401830F6A7EB9D955EC74C7F98B02388B4E1353317CDB5EADAAC9025038CC01F8655C7FB9AEE940FC4B282748B39D277A7FEF462038833A9A8EB50A8719F68B3E858825911F294A80FAEDE9D4C1815844C2632DD20387950003DAB80B1A58E541A5E6658AF7D4CDD91FD1C08735B584F5C69C5CA94F6B7F97A4761B127DB394AC72E902DB9EB4B3E0B884C448FF2763FF9ADD530753263688CF92BB746181C17294BFFC2A0B3969A7BBA429A481C425B24745CEAD66286F5DF04F1E4421C56ACAA668E87BA58E3B07A062D1DA60CC6B411667BDE6F466B72C9169965BC7781DA78A818F779A9B3D7A577F71A1DF49AAC865A0D6F2668CFD2C77CFA8D306A14DBBDE4D3A3818B07DC89D5F51E117F7BFD007D60F32BB1B6BB01E76862398371FB91E0A3D4B39FD9146C47F627A066618CF83C32E5C82592B418BD2F5DCD8D42234625974F988A6F729C60BA5EAF18C77B611DFB187A581E3A10268A965F650FE242CE2FE08AA71515B59A6EDFC9CBDAE22DF3AEB22E773CC2EB373619E9CDA23C236CA3F7845C2136E93849D9F6AA1477F4513358CD8CB4E21444C9E5709818801EADFCA23F2C23DDFD5B4EBB6089DAEDD14A21EBF3F7A8C1C80BBF7D37973BD156AC5C4462D29DCCB7EEFFA22A8B6CE433B600532F33999ADC39196F01230614767285089FB262D8469DC66D24AE0B77FD05C3EC02FBC5EE328319409B8E2D7B0AC6801C1C8BA86F793C2037C71E2A25F114E9EE0EDB3B83076EABFDAFEDEFA0548DAE91E62CB7C29C03413235B8C6EB9F46BE29DE8F5D30E8D97DB6F45687DC4719B1024E48B7DFFD0D2B474B2032B4E69B6382E603D4777F3450E2E467C6D9AB2782C0AE266C320D36BF67BD6B86EA9721B22741684D9C0CCC774335430071A5410C1E34B4BC1A823A93A38F5AB4781CC593B13A593867FB634C0C705107CD278C6CCEE6D842748BFBD2FFD205C6BDFB3AC87F693C25C832C86D96B00BBA0AF88DCFBC8CA4328765DE27FBF1389C4EDE28317BD0EE447F030990E957D223A5EC66CED9D16400AF6DA8663C4E4111B4584F8F0066CDF8258D90C5D7B439503E3AB3FCC55FDF933E06D704416187AAF86E6C39695DEA8B8189EC1299670BE03B6A636889CB7F10F04CCD67278E77886CF3F6E2A05BA8D25AB8664EA817642ACF5DB4D9B3EF80E169463EDB6BFDF67172E88D233609B091BBD085B970DB8AE0DAA5048CA42D6A54042F42445BAB03F9BF1ACCEF341B7349109BA0073D3715A9073AD9BED258268AEE9DD5202E0EDFA5720A317EA5CB41706C0D235465BECDC8E3FF0D628EE5EEA6AAF1BBD3E18FE9217516893DF115E979C4CFFEC494988B6F9B86026610898C44AB1547C5F8ED5CBF3C3A837DDB6A444BD3E803E1824E6AB931310FE86B36587F1B34B0B48D358F4B97E9774213DE7D92571380BE2199E703119C5B9836DADFC826B71D588250AC37DE0EC05C5823573C102BCE44C9F044507671C4E1723950A3C0E14968CBABBFEEB049EB723DB9B23CDF0273525C29CC5165530A1F1CF830D3551DD6BDED53954947D5C334DC9C71907CDBFA109EBC52D6305477C14159257AF8C51C6F09D76FC0085C3D969EC60FB09145E66A8A7489611DB3FDEFC35202B8AAE82D3CDF666034BEFF49FE49A45C5EC438F4118F338545532CED916DE78E3BF82B4E55907474386B9C172F393EFE895334F7323CBB2AA7CE7718BEF5E7A23AF734BD4963FBC7889AA5C50F3955B904B5E577D71B21A293D766865E3F8C212DE5EA084A9D22748A8009A7D1858328A1BDF7BA0F4E3B83BE9707629252B3339CEF796696855A574B4A4896CA68C3D6A6824E3F593069EC0A571E61282F8A29BEB8BD788F7B351A8939CDAD9E257587A77804F2704F49DB3305514B85B449AEE56EE40CB2A75D51690194284AACD0855B02893F8DCD3091629DC548705A1085E5CC33DE7726A0F521C149003DF380ABDAE96BCDA55C44BF9BFA1103150F049563E848A8750625DCFDD9BFE02E1E57489B5B3AA28BEAA80F4DAA562DEABB4BB6A27125369415885020D237A92CCC3A23593FE2183225BFA2FF39B0BEF9CB0425375E256BCD572175483F713BD38F937F2B3D4C1F686C5AF60061E0B05CC3EBAAB0AE8BA21E47A8318BEE4A01516046363D152936A1344E17A65E08030522EC667233145A56001B8D065DC2FED0D2A9F02C981A8962F984916314805DAB644A5112CAA1564895121D8B1FD046F547BE282CF979752883EC79AF70CF59A88D960F3336F0AE61357877AAAA34699A876144B65CA5B77A684D850D09B3D42CDBFC4539EA103F8377CFE5F9E5432403FAB416662C4C83226191EEB7F82B01E0819C081FC40E7B978669C7856067E8B582832DD0B92588103C2616BA2C7774C46840318CA2B1A3798FF7ED9FEC087F01798EA2445B92E67E2446126A7406E82FF8D3711311BE16E9171531A95C966E6BEFEA34938E6F5FA660F7C7CB533A119377F1D26AE6AE51D805AB96A64C8B80D6EE137F634B384C2E377 + +count = 83 +seed = A97269579EB70D268C58D94FF744329B197F722A8A407B788510DDCACA34C8CD4C72FFC14B76300C86AEA1E4CFA66BA4 +mlen = 2772 +msg = AE3DDE9E33719040345DF8EA7E4C0B5E2CBC5CB80B34FDDB959E2DA1D67D74D2FBE5AAB07C6357A9F3E5F6EF5379B4C75008E9077A1EB025F9023FE32FCD9076C8D2B291D0BECF2DC624F9E752B1EEA2CF0755FC9D4B2E4320DFD042C68577D58E61DAD075BC1C3931ABA78B473C0726ED495150D6A11A81DBBD1C840F5F1FAACD54E3470E0D994DEACA7E6E324A9FB4E581AB447A4EA026DA3DC3C7E6AD55E88CB841E069ECA63404CACE0E3D4C8B9CEC33BFF6AA6341AA1EB69AD799C6CCE358CA94555287D01B0192B1B49EB6F705E54FBC86465C4BA70134AFC9A53C1C3A732E21B010002B49B7CC6F5237B794BC1D1F1E30A7F1EB95D195D5F26B46A704F77F80B092117EDE1C340622FF32302DCA7E7E43C2A4D8852CB508403B1AA8ACA27A86936350264811550DFEF05D72542C74D6243AB9D259202295A63F54C836CBF610E40EB85E9704041A51BF68578B10F7985C752DC35788E7B7754358082AFEC9E4B271D36974EB90A46F7D703B0CCE941C3CD072A88F931A4FFD098634BE0921D089E46637F88F9625B7DF900A276B4BB75FC75921C8A8B6668DF9946290E11FCE4565A76D39D8FA55F324253FFBBF81536581621DEE664A9E9E4F4FCD3A9765706B8EA833125A825B1CB30314B7C6C78B301638EAD4311932FD4611D78572180EE441648F8BFAB869874611C153FEEFF88A45F7A98206D0B2D97CB7EC2144F045225AF5A9925AE7FD3DB017E37259B7A2FF6C66820DDAAC5651B2EC2E5767DDBBE18256B1D0D0F96CF5EE04266B8ADB29B0AC5D55B73E1ECA8FE724EE174B76EA1C0A54896E2BB565075F1669D3CCA171657B66F343A634F4250287F853B52182B9BE50DF29021673DB1841ACA45E7263DCE653F0DD84338E49FF5C6E3BB42F1A3C7164704A2A000149114D36BB9231606EDA06C712A904C1E323C4AA3EEE0BCE6062A9CB956E004407014ADB58EEABF486B38570955C30F2B5C28179F86CD5FFD603CD441A1FB06519368886BFF9C2C127ABD079346D762E51C311F196D5F825B45EDDD4A48C7C2123E10A3D369D772750987EDB96968C59441FB2F47F8E33FA4CED3006766C06BB6B339ED94B8FE57B20D96F1A27A61966289D8FF5072FD11D7EE53DEFE0014A11667D0A6C988BD16629FB53F269130B22A13AABA2E9F70DCC93D3BF6E611EFB006BA585FB8E8720357E25DF69C6DF388FAC792F87CCE801FA49A8CBEAD1698C11B82C4F85FDB4D52A2A808483DCA7334295BB3B2658AAC18857878730831622124F5A254A464DE459F3528C5194220E5BB1779C8F5E3866B0D60931A1A47502D99E2B186785658DEF57ABA676626F9CCAAAF449609B07AF7B57C78FA5BD06B2AD2927AB491EE461A94AC37A079D9BFA02203B09F7EF180C1C1C430518FF2D3F2A3582EAEB6668060A2B544E973E8A2B88733A902A0A80F8E4F30AC5D0223C1076482EB2CA5AE67039597514A4866061D5FBDD99694A060D0D0EE43A1B7290FFD7D796A9F1A2142DB6E0F154ABA8720396B6DE939E668447C81CC828FF9D2A014FE001CA718C1D6ACF4C08BC7796D344A29FD8913E4CE71E986C46BB66C2610FA797C9E1639DF423C338D7192638F621D83A6802E72E38BEE3AAB064FB606962329997FE908597E7407CEF098D4591E5E6011CACA701994E4ACF572F7C91057D3DA06058A7DFFD3248EE3333208BFF27473E6F1EA3914C5B2056AECD7AEE07F8DD26B3C2B8B9656EA4260D38E8D5F23C925A4476754240D0702C5859AEC2329E1CC3E426BD7665B2A4EE2E75B41B561FCE79690F64D1068DD35A294A8E8CB43A6AAA901109F0E09D985B6E323C30A017E75BF01D0AAA739102C1A6667ED48E60DD4499EAB862851558DFD17229878F5BEF0CC29FD19F59835579F3CDD4F85684E0D46D9618A205DE3B29B0BFA5FBB36745B989211E2BA711527D32CBB5E35830DF4549FEA652377EBBAC6D52787F9EBC3CB687EBB641BF51D3E22E98FCA48F99584FB1F3BED3F97F33EBF656C5795055268F49985CEA00819A07B8F4B0ECD7BEDA95EAF11E3498FA7AA414C54C38A08A841B012AE91763BE911DAEF803E2CA385C9D4CDC642A0B343DB6534C10D9E1755B7B2DE543AFE1D3C90981A7BD907E9CB14367243D9FDCAA8776AEE5F65ED6DC02F633BCF9F57DAE39E8E8261DC10029DF7B7124BEB67DD753B36892481EA7CC54DDC3A60EF8D4DCEC4D5796DDE0E7453BBF0FD93FCACE97CE5048D75ED1F34B69A392E1734E262B2B2A1E246331A373B5CF1FEE7BB46096C76349B0F19BE63FE539DCD33A8450BE894C2DC21BEFF0DE6A841A533F4C9949289037D161BB97DCE31CDFF4C1E0AE36B4192594DEC3B021E8F3D5B500C244CB122974F8CADF125DE0CF832A920DEC3A6F7150585D0209651B0FAAE0F74A36FC8779115B96136805DDD4F6F3A69C06AF472F369F481359FF834A0FD2F9AE899EA36B9B061B63D07C1D4ED7A373ACC40EAD808564B05FB0C6E656A80FA3865AABE483848D14D1DFD66D7AB1F353642EE3417869DA21622F6AF551659D07E6C827C18EA36E2C5E806A9571A7B05BBC1BA283A8984BFABC555AACAEAB2453573F782A4087F0F903AF34596E83282A2E54773AC33543BD353A3F855BC46810930C3635A9B70BA7FFBEEA95A129CCF9E9538EB11E119A072F806130D831AF7E57D332AC889D7D9E6BBD1C65D64E089722F6954F126E64EA939D98084D434EE74B55C549BED21D11264F8B5E023277DB52B03D7B8A8E75B12B11D62052E474E435707272D72D00D92288CEDDCD1ABF8E63A8A9963A48B54F492487B309F69CD90C9FF54B9C5A55CD2BAD4A2E0A6B00B188FD6C527A8184BB63670BF626A995815810CC0F280131F5F652EC20609C7D3B910E4168FE273626BF0E2CBF05BC9CCD178AD91BC25CDF178B387DFF0B6B40A46FDB6C975349B6CD8AD103CDC5DAB8D09D9A5B55622E74564C1E789C5C185CAC04FA0ED6065B9CCADB1D5DC80E90AB244CE1AAC516B346ADAEBAF7A030D66FB90FD070ED062A41E0B70BEE3B07F1C03887DE5F79D70F9955B25B8C8201602784EF8A60147260D1BDE8E152E8D3F992CB8255ADACE9D5DD2E9C856C47537742094190AA867459D20989DB11841AE44824979C0A2093D7EDCAA13C9DE25E6EECBC5124055F17466467E123E39034502BA966CEA873997EE25E52DE2DBBA874DC9AC222B49967B7BEDB5C81BE09827CAB782F458795B2903D72AB16F4423964F82DC69C138EEFA3273BC10376939E544964150D9DF09E14BE08CFCA06C10BB2C315B1B676C40762F8209C0EF13CFE5FAD76CFC17FE462D8330F78BAB072C5465F7A26D047FEC4BD3B918C9C761B91B02D820ED7EF345E79A66FBA61AE13D3050A27488CBDBE693B800F1E76C188EBD8118C9432EB9E7124D35A1A038D237918F1DB83304D10AB5DEDF58C6951A92AAB1A1A40E180254E730EB43B566A83CC71FB6B9749BFCD3A90B964966CAE90FAD7406A8A89B1E48C885BFE2DB41C1996F20DC9A8DFCBA1A6F2F307EF8FBA5EEAE9631C2D6328D90F17679DD9E8E9660D6BD4C8A1D79C47A5FD46BD2ACCACA2D5C6407B0F7F31D093CEEF0342C67DDE3F1BA5067ED1500DC45161B8636255924BF007C4C870990C5DCE098C5A26386AD84D0F0CE4860349A147A4E7AB80151FA63882590B91C6AD3E70A68E6FEC1A2CF65881A6DC38048FC14DE71C702C934C5D3C4CF4C474F906C3400364BC400A7DA087F94F1ACCB68439A9A6FFA8C6439B2CC5C0B17A7D649033798429F211D9DE12B24D117583E1C425C2C0348C625CC44E9B976D319E72D4E09D5D6F36EE243F5FBCB190E84DE56EB680DEC8566F5A2C7D5F595116C628CA09401D561BD78356C634419225FB01CB637C46A627F6026D39EC1C62E9A3E85FAE +pk = 3E867517B847ABA29E8EFC7C33F89A353C2F953A7C043FD3656E1877FCA932A261448C78DFE2786254DD4B0753D6E5300C73847676515C30DCCAAC9FE0BAD8112CC460BB65F6297D9C0F49685AECCF2B0E58B2D7326D37FDB9E718B1F28665780AAEEBF900CC6C0878AC6C916002CD08655CCFA64EC8CFED208D43C57089011CBAF117E63E5EEEAB2CD001AA23197D091C121F365FAD24BD293F120B1AAFF3B1DFFCCAC294EEDAEA85775A431EA7FBB7627628C29A4DA72BC52EB39D18CA1A3B495C646E39E2D60C0180474E47F9765C1AFD2542050EF825994D844CAE5B9258C3238B5BA0AB7839051B10D7382EE42399226F44139119E9348DA4B62B09105FE432EE33AD8057375C63FF046DC33FD6D72F5B1AFC65A501141396B7004B9C0EB71528F87112F6FB2914660649459DFCF4E39525A8BA207B62EAACC3E4A31F9F9CFC85F88DE7602E1B48DA297D8941B46BEE63DFA75E86A8CA9A05B6636FE02DCE1C4FB30427AD4BF8FBC8EC42A69688DF6012B7884B3FD0048125CEDC708429D5E341585EDF825B3170964D69E0AA7CF129048150EB0A50D919BEDDB76D30A279BB84AC900FCFE2CB10F64AEE6C02EF3C1CDACA542C904397D6B44650425C3C3D32463C01A5C7E2AE8D83F896B7546BDAFE5C3187E22C98C0C6C44C303BBE40037A4A1ABC044A52DD94DC058213D8F72FFD058752F674894B72FF429EF0916164F09C851F6B09D07708BBEEDDD3048897AFA485D07453E568BD6E95DDE2AAD38DAA3368E3E2A8F79A317991CFD281A363CBA3568567EF79CAEEBB058045A459CBB29D7A1D9968FD90736BFEB3B1B34C8F7E836795D29459E148B268C6E5A55561214BBE078671586ABD8E9EA7C7E9D10016686BBDDB8DBEE46B39E559562A70A4FD4C2164B6F920FA4559CF9842788AFDC3641A3EFBB96A54DF9EE43005D6BC3D76CB924FC90F22B2A6A1275D197E2B6F532550259F4B2EC66C369CE141ABC0825BB65591693C0FD4D5EFBD95B3404BF8F34D605A91FCB059DA9C5DA79EAD95708F1A5D12C3B4BF43F52528CBBC243E6974EA6961AD9F45887E17EC0807C89CBA931E0AD412D915B91E83495E48D3798483AFFB625739C92D5F8E2DE1237F5D2B203F21B0551353F42226CC4F1DF6DA49F354D463923DBDB27061A169E3587682423039FB0B8EB9ED877313DB290F80BEADD46DDED5828AEA267C06E43E12F127E9C732F7529BBEFDB584F3D99D807EE548CE9A0B2A9FE13586EBF7C81B9CB635583437C9D8A63717AFAA95E4AFA368EDDB528DA95BABD40F79C157ED034DF7304376C30100B0AFC79FD316BCF4B3F82CB01527B3B38067215C35AF53D3722E52696EDB5F3178641004BFFD1A3D2016D729D7A0283EB32C7D915A7EE4C66594DAC519BC7F2767E35DDC13704C69950821EF492D73E113482429F208FBD1CA7919727353BCC272CF1FCB7950A2E016F5A39A87A2C948D188E847822F4FC861910F8FD5C10370FEE89E16A3C645FE87220F8C49B5A3C971BF3435240CF9C78AE912B5281245C5CAF6F08C426E64242790EC385FD991921907A7A4C54868D3FB22539F783C64903F2325B5CA2FC313A5982C2A85B856F9F6F2051996A95EB9D0BC42D8581F64AFD5A8A27D1C7B657E7F88517C2F66B9B0D807DE16C9766B2F9F7315F83F9AB99AA405EE148259D767ACE23349A75564C8EF4653E3B434B0C77B953E8B5462DEF7344373C490B5CC9A78F0FB90279E7127761590C3E376E08DFA875448EBCB7292F69154AF34E7240F4495448B99CE7B53E261352A67C468E2E97ECBB95CEDEFF8DC2291146A3BEFF06485EBDE769A5D1D9E026A215C3DCB8447A76F157366DEFCF599A9BED347864A440A98FB528FACBC56F1AB6D1EF2701FF68B359DEEB049FDCC9CF7FD3213AA2460EBF8FAA0E7165449DC2102AA3F25E1EBDDDC4F8D310B23B268C762F4C73445AE997D22AF60BA3768B5691651B015F192709507B2AA3762E4468721DA71C56845A40497C6176C7DD07D6D8CB9E4F85B852FF30E563987DE8EB4C5DDFD729A9F96A5C287E663090F151B7A9B816CEF6BB09FD55EFA0C6C0B13956BDB6B7996921A2D708A6A62208EFE9345138178394216990914779C9DC9ABAC05267A75AE1F9A26CA7BC01D60CC4E9078D9B07DF40FA628DC617421EFE3AF68F62E8DFD1544A8F0AC83E2F743A59DD6D1D62A851D55E91DA04EC960799DB896D03355CDBFEFDF377122EA8140569E36B9F617D7827C4887457D54A02A56E19D949D904F41EA77638F582B4AEC53D4F4A218CCADFD2B4848F704C93FF2568A362E5BCF8A55167F4A02DD7AF403FB5A9FC11330838449302BC58337DC5BD3F2465A6D18C39DCB28F1AC89FA93E503E91105A5F009CF9F4F4014FD6053A35F070BB93D0CC015CA5304355B951BE04416B83E1D91646B8DB9751897241E0E7AA7810724F70F81AE147677DE235BD9E5C74908A90E252AED60FE5C10F407169219A62663D33B9429D9DD7EBF503366A7AA6F9F45CED944DDFB197C42837A914BAC4CEDD11644EA149123A81C8704C5369BF0EDA8C7D41A39F30E2E4C84DA68533A959C9288CF6CBE64B2938A4C07D6C9A4A7165ACD91FCB282F23CFE760B09D132C6B702BCA4B85F86A066773817C23F2D2D94D85BF57D27933C6600C6BD12A9E24FB1E5B5DBC871BA3A89E7130BB2400D53C5178C2121A805BF5F3189FD1D97679A1EAC8118640741F5CE9B9726DCB6DBCA29265DD0BC06570F +sk = 3E867517B847ABA29E8EFC7C33F89A353C2F953A7C043FD3656E1877FCA932A265957A813D816B7DCF5339A808B21254C0B22A8BAB1C652065D9B7773B907FE7B8134BEA01712C3FE2ADF75E030B4EACB5D58890251A17A3273447E8A25F6AD296D485581BD17BABF622BF5C8EA100CAFD928B05146B8480473AD0BE4649FBFC763186435844110308673782843252063515106802545335554318720671835180886772517517256388283753486623452668852512070634408485832436110675121264353326746481085763615732848113424008433076603801463533552164128280122641200154016410450135711311104888841853701523474130453543832180047868583476022668122168032833812305005137370586847361877046131535643153772163056516432666022760527584344444821402411773828283765006207753868628640256425148316466165154878345162444645878035388758757072635834678020580405808268366066062110015363355485074463681253422300021152073236832422530335274463583857754543640512618178434380067431513105145620653348463827411651382502313888170658441262146606147105636111242882487032751300882338173736115640623463253086118361871852024274168538851558177045157286724337446476164681212073672358151778716002607864441837235388062711122402088538045527076020221080850776671044871538041448620247287460077831713854272655611846285182675757612546600880667884588505631367681762078722436368823582114425564400123217072766517757474617104805612281673846540475163428048225535074453318203151115476448161216550537368026856227661780763578222087505177880544113520847332263710288524662623182484055116337225533043305364737843013147046364875343034224031508884076865245081387264412805273405211236880614117403710402011205463017665164521172458481740313226030172045167763041686266432243886720527705428520252230240533452301614033032378221288586244077163601866211730586517702606413242734643780173211401171424710041136708317547286483807876101386320550336487567483787556840383578024388426786844455276124112714464880472228338711485168441716825311385418360606226340403111484345180600384321070232502006132871880622808257381736884770176541626361660466318862138107022102801371405730341352681651167603430215832240675532643408734302101528884772728780331757005383102462633025444022562570324583306124557505350750662844035010451200251047808414403156263060077110768702354473838758406544736840063517310014523027113653812054081178303110410038621531422675555654834107872247514077373345325327212086701474851661806862831575326222453672521502685185323033458300706064758540674581434131587551175554123864258284650733370426542100025266421423678811231668362345223417715568470141311056250578041524780315560576820011831827671662088841356764438007174820543705166212440023877664468000655175836583686785661547467052260076507516468305022525246665617838474821577558316826277301106872646662512264184870185632642245563121300737752370744488632123006884454424013556703334047231207703108826046113102103810444204802527767167087471371878680111515514462044740337822775556260243585230044860648581100205200753264247467767576257336411381441278141172565672547630258586316227087744102245754065037604880573880216427158221384138203202457405868815681111852320471883426003816867763576505008E1FA87138ADB412223241F651411CBE7B0C1CA244D7966449FA3497553EB350B3FBE853104B5AD59E21C09873FB3B98416F9AF07913243154553D794B6F0524C877AD1F61A66D0FC048F01A92079E30F6D6A68E8B02EFA364F7C7E400BF562C0318D37C12E4283500154F91A497463D70CA61ABA6B8510195426FDDDE6DAB61C6E79F9B9336EF932C7EB92E5C739BE270510FF2C19A2407D8D7EA1F39587658E3E28C511C88C38CB02BE382AF01E56061493739F8C8AA1A5CD24C09933C37C16495B4F70A63409C630D3D7B81AD95853FD057FA9A761C5078B3ED786C9CFAE3EE68E1402E242027FE5DCE9AA2306A8F293B61B27EEA770653693610ED05C54AC66E8730E341138460055190B4B4A2FEAB0B80D12AFCD4B5FE847B993249E204682CEFB2263779B8997C9367E56449F667017DFC6890F6CC849C5D09BC6B980538C8747622913EFFE88ED53EDA68A9B77179C622393A4E01DA61BB6FA1DE86CF7E34380BF67ABECC929A9A160DC6ABDAFA31A8974DD18A18CEA46A0BD6894098CBFB374C2E350BECD4F0DCFA2696555CE8E9610122A80B57F8B48573E96E0419B7BC849618162C41F6533C926A74EFAB3842861D100FD0DC691AB727A900465E787FFCAA74BADBDE536D5BB4289CAFF80564B4C8AB53DD185EE6084DAB4D400BC73AB0EBA4C89C72DDB4C7FA2DB96B8F42E6040D56AFFB4008E5A097963696199914B91AD6590EEFB24F476DDFE08FC21D6F2916521C11EB5989ED972FCB6DDFA3FDB09C6F775F317DE06FA6049CC85441BFF3A514469DCF3EC46D2080AF5BB7B849109537A32A82899C78C2C3E4030705B61FCECF45333EFD8B4D958CEC8A5C1392F1C9C26FCF9792163AF71A8BA8B800C658C73FFE19FCBBE5DE86C0C86CB4ECDA064EADE3BE877843FB4920D275436C0379034E188B99EEE595512BF58A59E689F2A421C883563E27842D2A27CB09B3DC83A7208D32F324732EBAEB7EE6511CE5602B9B9546D23D01BABA563D2FC7D4A0C7B3163E241459CB01C80D631F2E597FA510F52432504EE8E4DF3EDC5B9565B589C566E5DB6F683BB361633893DEDF8BE1E36C9BE636374D096246C31789F9D67001918957561F18A4EFF0A92A043EA68E2A265A4AA08F51EBCABB324809605A39B2245A37C09806590E5D1A6DE212AF9234EAB0C529AD9B1EC92A57431CCBB949832DEC5E35A5ACB2B3E7CD12C38F492AC34BABBB9B85B044C0D64451DDD42E38D55356499E8C9FA993FD20C63C81F1467C4811AC6E1442E207BA69FC3DB50C2C13146431A1B8F39EB0F4C08551F5AA118F4E284A8C28DAD77E1BDFAF1DAF73DA18174D0D85771B1B0EE4408D2FFE6A8C655D903B2FAAA0F925E13C6F5B25E21307C9995DFFCBADDCE5D80CA60CBD37594EA4EB04A3A11291BC751B839A0ED25832380DAEAB080AAE4DC996667D06E31897A5CC3C36D5A22ACE76217C7E4A0B72DCB5983DF16CEF5D7B9A4B4CB0232C92A68F8CDE707D1B07C93DC1202475531A2270FE7E44872E70F896702FE55C59C0493FA21E2C5399CD7B66D6B754789D11EE62BB7B856353BC884F2DCEC5616E9BA729A7D1A4FD915EA7B4DC65A472B249359ED13952BE43F76C3C40AF2A391DFEE1903795C341154BEFE77C7F303CE5117587E4263C93F66C1BCBFFD1BA5187633BD99309409DD1E8BE69DE4A44E9A1E53222A9A36B72269B91AEF427092E3198744F4673F5F92CEAA347FA504FEA31F44F1D86A53A5334EF26D61229F7570A7B2D5E3F083536CB87A17572A63C724DAE1BF3FEC92820EBBBAD3F703ACFF7A89096F1218A06A14E5BEAC52289D172715FA17D41E2529DBF1049CCB027022D2DC99844A3477A8F67F7DEAC08507BEC0266AEB941920E6917BBD4ED39C3D25465A5CAA0F841E4FCE0D141B2A5EF4D74E9F46767287EF680098A2E9DDCD732AC4B04270E31DAB74DEDA6D146C7D5C697D064BF6E1CDEDDC0DDD321E6C121A98D641797BA62C47CD8446AD8F8C75C26DC4911909B76CDA03A5EB2C4ADFE0CFC720AE72CCD1A15949B7A33EBC2A422327DDB443744E476D7BFC42DF6B8F267DBD5755A7BB79A57F6229A3506DFC4C3E38465FB274A12CD84D2F58CC0D88240A1159410E930062B322520A3279A28954577FBD6975233E64313AD8F2AD900735CBC3F589E8686253975E540FBCF727B974C0339E17E9B59078E3ACBA17FADED18BE8D51C94729270417C6D0B1CB50B94D289E2C0B747F63D8624D3D94E6ED843E306D913834D1C1F43664EFB60C8214B118DAF668737858B6FB0E7EACAAF996E8F21E9B65FB394266FD793CD506285267BE63E80C7905C47B4117EFF1D12109ACD963B64A9DADE04A69DFB499E829D251F06A3471190D8C54DB68A021CBD651534D9C33012CC8BD81EEDAC76E91EC3F97E6A00C40AF7C0BCB0D06CEF9D98D8B746163F3CE0667FF5B3D69BDC7933DFD7F99765E3FEEC076FE9149E9084E6C62A09796A3A2332C352FB2AF4AEEB0C5282D76B633FB5F661EB5B7DA0B93B12A98A97F650B83A75D0B4E4D49E8ED7B2EF632FB2F8490812A5919E8F18C8596B9C68D4817B5BB86CFA39F14B3EFFEF18A5E559AA9443D33040B35672024C98E975A755602D008B8AA11AF16712E3552015E1ACB90E738D9C305FC9E437909C752957FA6E69E99A1058C8CF8B22D4E7B454BB40CA9DB5D9122C0E06DF60F1408E7E217B5F98A882ED9B58D8B7393EC7996E0BD9762A703B2485DE279E97FA4932D7D0307CCD1739C0BDF04D539FB5E115925E7C366D9FCC7A6BD0B954128A4F5D37F02D5759FB66F81EC8D8F5FC21C168FD3902F9D9E6F8851A7354E6B34D79479ED6CABD2A8FE8DB6B5D676AE5253333FEA26CBFCDF70073284DF464D0464CF781705B34A6D0DF3D0B0B2B16E65D994279FD25B4915996B5F8E2E52092E4E2DA470239FC70300F31523EEAA48638598FAE388B0934DDA7F425D0CAC2C40A10B08D643C244F04F6FE8EDC54D73575F46E51689B171F6E2B8510A65408435713D3E0277923BF898CFFB07A631B25CD15F5A3724FE43DE15042567693E8FA69AFB67635F14DD095F3A16DE6C90AE6E3A3CE7AACD7DFB7C0C40A9D97E65429B954BAEED49BC0C3E7D03C1C3C4CDE6D122D4814DCD9BCBD51E162712D49FA3071E9CF880DCD361E2BB0A346C8FFB2ACF4E49F39F02016C89DAF732F6A6CF3E51B12EB5780C48A9A606B839098CF0267916AABF53A649AEE8D8DAE243053560AD1B5BAB3C19C0A304E04C45753A10CCFDABFF1DF6406352EF71124820288660DC1F6C5FDC82304740497327DEDF1F049B29A47DAA085904DBD079D352069A1E078A91399F9D8DFC844F6E6BBAC15B1C7BBB83E0C8DAF74507CA7CDBA61AEAE01134C7DF18990EC02913E877582B8BAB136F78E15377EF4C51924BF4C0B61F2E8DD5438D58814ADEAC856504A44323B7967CE051070DC84A4FE21CC69496582CFC95AA5794A4775F485D18AF4090369E76A0B13438764AB8B3F189085637CFEAA5E9BB04BC65 +smlen = 6081 +sm = D4995A593592A50140E515BDB9D67DA8EC73FE06E512C0F09D7C1A15AB970C6D1F04FB7E53718C02DE283C0366E2D0BBF608173B0D431ADFB09BBE3FA4E0E08C26869275DD341CED23A79E7E9DB8851A91D44C87C2F4776A4C7FC38F46DA7D61BCBE0EF63CDA1F95F645F0A888951A196FF00050377E8DB25A6019E98963B2435E888E93BE50B4C68671BBBEF054EF993C781C1F1B68AF45584558792153194938FF5B76472F50C3A06F637418B47877ED35C4BD5509147073EF4AC87A4B45B22B85E77123C98B428788828DF7D0FB361BC7D93B39ADDC6EE8A3579D28569430902BEEA7923AD8A54CD092C37A2921D17AAB0FD2F035BF3438E70C24533DF0B7E282D6BD42D753265F5DA5127F00E2DB2738CCE5D778D602144D19765798F9F7BA9F2D7717306EF7289A03CD48CAAB55CC36D9145BB898AC1C36E66B09C9ACC3684720C28CC02C1E54B19146B28FAE1AA5C3B17723DF87CF454C290C41DAA4D4DB6375F737EE129025BC6B07036C8DFAE9B07725F6C1B899915D2A03E0AC0D1616C88A100A5DCD2C9D27B616EE9D36D3C186792C4C8ED18518C8B1ED1A451308958E38194881BEA4BF63EAB6A174F310C23C9EAE9AA4C593F0998AC04EF5CE0BA6A09D0DBD3A7AEC7FC1014A67855BFE1E05B0CABE30164B4A405867B255CD91800FCC5E829B3A8CC26E6BE7246D271EA06C83240F44951EC20AFF82F55DA40009111A351DCE6EB0384E72BF6C0865BB6BB9025222F37D6B1F5F93B15A4C16CE5F317E41F218BAE8CCF442D409D5F79583D4B57536F788160FC8930D7B27A7727EDC679499FA5BFADCB4393A53C9E17DA3143A79FA0E56DE1E8EE35A36B1D825E4C84EA2085F3D06B64997E5C71959024C07492B7E2B3B77501427D6A17EEC1449E0E98E56E29893FBE79856804A3A6A261D1C747486F264B08DA7646ED30CC81A43B83C9FF39D770227E209F8C0DE363937D82102A4492D461D1FFFB6E10CF7D3E569B13EAE28818404B93FF6F43084AD9391B4D0FAAF65DFB2877584A5E85E7907FD44354F437B2DFAB345FC660D2F4191DB4626C3C2DB57B5006C0676FD9F14E6B7E7495E3DFFB746E4699E30F12F2DC4077F83CFBC3ED13BE83C4F3173D52654C6DAB3E5BA0537E884C571B1111FFD9EA36CD082295E18FB51D3842218F202AE1084EA01751AADD4D4F817ECBF5E9BEA9824D38DCB6A7CD06970199F9C21CCD3331C0F58A3AF674F717590FF21D2AF544B18BF9CCE73066B6F265D89518AB0449286AD1402FB7BCBE31EF1355083C8EAE51C785D4745851CFFA0943384587624985EC8B298F6F51F54A738881966286A8EE112D2A749EC946792CAD5E26957F8F0BA123A53F2C4812B6CFAB432ECFEE01F61DA95C19AD75D3C927C786CD012CFD4848BC87165BA82FF35030EC61DC5A721E438C1C2F835DF9879171A78BA5280AD8D1CB9AD8044E2915458A1BE23C2E80029875D9276892EE4DFE8C3B10FD740FCD123E52C52C066B8A8859BC94D105821D593A586F8039655F9945674570DDE3BD78CEC4D35D873E80605DEA55FBF24BBDF31AF1C8CC434DFF08EA18427EF41AE73E709D2E714DB2E43EF78D3BF61F5F741371CBEB7DB5A67F327CC1196808D5EACAA932B52C8ADBDD056732A41CDFB033B4192F82151B46D0A25C09413AE178CD26D74133B45353F018D3520822D153AD389DBA7F3ABE98980D94C09E4B5DB0AA64DA29AF3316C28144FBB85C27B10370997FE021BA53672A35467EB065B2A533D95E21E7DADB0527DDC715D68B80F0D1F7DCA9B221293D1DBF119BB03041119941D5052D111902730AEBF1D08684DE068FFBDB8FD145A2B647BA76A52C229D0931A3B7AFFE01E39EF44295D7D3AF31B9481690D773DC2E407FF340B41CC938F398C79E665901352DA0C314C43B5B31227398020E8ACA62C4F3AE9E3FDAB99837BE84D89146B738773282D5C799F90C4E7418E12E9F1E857B967F601D43FA8C5CC4B0059941FF2B3C9AE343E1E3C19927924169503DE9341362CE474614BA611E838F8A5213FD6C2F9C43E1FFF3F88275FF8EEB6DBA985960EA3144378F581D9A23189EE0F4EA1B62ABA31B246B0F051517255669A2CECCB771F964854E693996B220D9D5B4BE138937EED979C1A6E09CF86B9738C50181156DBDC92B22C38D9B84EECC3304FB922660198CC45CA4470A909B7B9FAA8D558CA7C27A055D4BC7A804AD68AC8BE17BDA189451C56568FEC6B0590CD0FA45F260CA5C3B604D1F3831E36DBD7A5536EA44CE3B260A8484E3E4320A592A8A7A3B4939CBF7F85867E2E303E30379D4DAFF663BA448B07FE42F1C475C93C7FA77528CA25D7E0B5223CC2669A5B2BA59EB6233224A195B7E47C1F4673E2DBCE3F98044B12406F7D49369AF52963BC72EA607E80F445F00124CE953436B6EBB09B3458CA5CCE16A091CCB565587A5C4166D255B716EA347B8995EF22BA5261655B3EF3CAE4BB25466312C77A1957B6AE975564BF7B8B121FB18F518C12EA88CAB953AA1352F172634537F330FB2F8A478C25891A94193404C7B2617C670841986847FD9DD46DED0A40C12A76CB6230B0A7325BC06203E41E2569C9FBBA6808B7EF060690051F2DC0D5E41A0F08EA7538D866C210AD54513825D518D7BEC01C2560D4D99C560DC5DBA5A406F1AF9904A742FC875E24685B1FFE12AA60CB52C8F0EBD201C298C02C9D61D9C9DE6938A724323D243A53A0FDF1D2D43159322A0E96A8EF97CCFA39F42326E754E7EC2F7AD799848EC7CBAE4ED2FE062B743481B5B1DE82C781E5036CAB864A295958ED7AEE6ED3FD530CA75E7ADAE7B9C4157FA839EC0119A268B8237298B98EFBC8C56A95E8AE37F994C6D0EF5BFB0F27CAE6133B19E8BE25799D100FB1609A9EDC05AF63FFDF665DC2A59BC38EE7DC981524901019F38A98564CB74D5FA7C8883E5C2D3B556710BF10E8AD3D5FDB291704ED61B89656A6EE1B98C55298DA6CE63F4A7D8C8633EA1012365B95C3EF2BB992F2FD115B1F78ED23449CCCF15AB45055AF2085DB6125F53AB1DDACE9ED0987365D0509E24DCFFE044C30EA8A1F2ACDA936709F59AA52394739045D000359AEB5613B8BA6843942234B79F7BA3C00A02D7E73B87D8DDC2602B14C47DB006BA1FB2006C8D64BC8E2FF2DBAC1CAAC93D6E2FE0D979B5C50B8C11F27565C5852BA658AA8340AAD25BA6C3C352C0896C4B8050AEBC3BA4ECECBD5B394A54E98059E8FE840325E4FB9EDAB2D40BA23CA3C08FF1D830558809D63A3857C931CDD099CF3D2B65BD6294F338B5EC0E239DB1C8242C285177A99C24C5C8192B452B1F91802E90B1AEFF549C12CC3AEA6E0B9F96A9815B7BFAEB782F9447CE205FF6B5241F0C5E3C14F8C094A191DAAC9553E7D77B3E3E03491162FB461EAD70B9F83836B624A4915787BF52D25C259E6E0B9843F282B7CEBC55B2F997531DFCC26124F073CB91B056F6A04FE701ACB7BA5C8D60AB090545514D295CCC8EAEFE916FF5316FCFD814052612996FFEE08D88331F4490AD51CF276F76B9C12D8816431BEB9B5B8CD500875EB05BFAA2A02CF53AE478573CC4DBA1FADEEE3B48120CAC909046F2CDEA68B5A44EABB660B8A7E241C200FD4951802588D13C354104043CB9D8686B4DF714A02561A6168E0DC0BCD714E5F054B536E42C18F2BB9D1995D067756E45D04B0766B72815EF72D8228A7D44B5853BD6E3C390A929E19726AD326E7ED6576C8D49426B90E9FDDF13E204F876878BB064F862FB0DB1D00CCDA8EB6EDDD14274563A1F9E0313226697018F7760167A01A74297D1FB94F1A621ABB2A4A245CE41DCCFFC132A6259FE79B5E8F3C987724DB65C56EDFB7DEB0AE426A9F20E7EA675F25E3A758251B869BB57FA655C76AE9A349D51406AA14C6DFE81D4272F4EBE602DE3C3DF63DAB36E5A5E77E3C3A19F92E135D410BCCFC40284CB3BBFD1EF335B9E59B05C1582098415E8AF3049447EF1932997774524D311A8B5F469979F653E473743F68596C7C70EA8C5DF2DAA3E17974452EE0463FAE152EF46A1D74DE812B8F53FB057F524C6206BDDE1583D4D36AEAF1A81E6224EBCE1DA7B850C18B492C8CEE21C63EB9A737F885C352A1826C8157B6D9682465D06779EDC936873CC331A0980A639581AF697C6095FC54D522A1F85D7F475309ECC849FCF59FC3279BD77F88CC74EF07B74558FACA3AE40B8D8D6232ECC090540FF8DF19290AAFAE8FB891E59C574C59A85450F464403C278D03505D5C24B1C9D82650AC58B4D3E474BF918279486143DA36C69CCD7B17E85A4B36B8FA11B23C1C80D3B9107BBF096853BB696689E17E075366176ABAC9A303F6B93FF7BB0FD184D83C756FB4F94DA4ECB9F03DB1D893FBD77AD8A064D77323BFAF5FD65E524B9EB18B870C5DEEB65CD27C437B8F9F1DF74AC3BC0B46F3638B0AA005528F4E8ED25F719CFC80401146DFDDCEFD6BBAB330B0896DC703EEF02F19A0D55503789ADE9FF56009F49AFB2236AF0EC0EBBEA343047E25D241B00C9D998A856FA452F2A5509D2C7DF8D7104EFBBA5B20C757DF299B2226DD873BE6FEDD97A06350914101021E6A13A3080B6ED2DC55090A11808FB0B2C9F20243600D407D8FB9E0F30000000000000000000000000000000000000000000000000000000002070811141BAE3DDE9E33719040345DF8EA7E4C0B5E2CBC5CB80B34FDDB959E2DA1D67D74D2FBE5AAB07C6357A9F3E5F6EF5379B4C75008E9077A1EB025F9023FE32FCD9076C8D2B291D0BECF2DC624F9E752B1EEA2CF0755FC9D4B2E4320DFD042C68577D58E61DAD075BC1C3931ABA78B473C0726ED495150D6A11A81DBBD1C840F5F1FAACD54E3470E0D994DEACA7E6E324A9FB4E581AB447A4EA026DA3DC3C7E6AD55E88CB841E069ECA63404CACE0E3D4C8B9CEC33BFF6AA6341AA1EB69AD799C6CCE358CA94555287D01B0192B1B49EB6F705E54FBC86465C4BA70134AFC9A53C1C3A732E21B010002B49B7CC6F5237B794BC1D1F1E30A7F1EB95D195D5F26B46A704F77F80B092117EDE1C340622FF32302DCA7E7E43C2A4D8852CB508403B1AA8ACA27A86936350264811550DFEF05D72542C74D6243AB9D259202295A63F54C836CBF610E40EB85E9704041A51BF68578B10F7985C752DC35788E7B7754358082AFEC9E4B271D36974EB90A46F7D703B0CCE941C3CD072A88F931A4FFD098634BE0921D089E46637F88F9625B7DF900A276B4BB75FC75921C8A8B6668DF9946290E11FCE4565A76D39D8FA55F324253FFBBF81536581621DEE664A9E9E4F4FCD3A9765706B8EA833125A825B1CB30314B7C6C78B301638EAD4311932FD4611D78572180EE441648F8BFAB869874611C153FEEFF88A45F7A98206D0B2D97CB7EC2144F045225AF5A9925AE7FD3DB017E37259B7A2FF6C66820DDAAC5651B2EC2E5767DDBBE18256B1D0D0F96CF5EE04266B8ADB29B0AC5D55B73E1ECA8FE724EE174B76EA1C0A54896E2BB565075F1669D3CCA171657B66F343A634F4250287F853B52182B9BE50DF29021673DB1841ACA45E7263DCE653F0DD84338E49FF5C6E3BB42F1A3C7164704A2A000149114D36BB9231606EDA06C712A904C1E323C4AA3EEE0BCE6062A9CB956E004407014ADB58EEABF486B38570955C30F2B5C28179F86CD5FFD603CD441A1FB06519368886BFF9C2C127ABD079346D762E51C311F196D5F825B45EDDD4A48C7C2123E10A3D369D772750987EDB96968C59441FB2F47F8E33FA4CED3006766C06BB6B339ED94B8FE57B20D96F1A27A61966289D8FF5072FD11D7EE53DEFE0014A11667D0A6C988BD16629FB53F269130B22A13AABA2E9F70DCC93D3BF6E611EFB006BA585FB8E8720357E25DF69C6DF388FAC792F87CCE801FA49A8CBEAD1698C11B82C4F85FDB4D52A2A808483DCA7334295BB3B2658AAC18857878730831622124F5A254A464DE459F3528C5194220E5BB1779C8F5E3866B0D60931A1A47502D99E2B186785658DEF57ABA676626F9CCAAAF449609B07AF7B57C78FA5BD06B2AD2927AB491EE461A94AC37A079D9BFA02203B09F7EF180C1C1C430518FF2D3F2A3582EAEB6668060A2B544E973E8A2B88733A902A0A80F8E4F30AC5D0223C1076482EB2CA5AE67039597514A4866061D5FBDD99694A060D0D0EE43A1B7290FFD7D796A9F1A2142DB6E0F154ABA8720396B6DE939E668447C81CC828FF9D2A014FE001CA718C1D6ACF4C08BC7796D344A29FD8913E4CE71E986C46BB66C2610FA797C9E1639DF423C338D7192638F621D83A6802E72E38BEE3AAB064FB606962329997FE908597E7407CEF098D4591E5E6011CACA701994E4ACF572F7C91057D3DA06058A7DFFD3248EE3333208BFF27473E6F1EA3914C5B2056AECD7AEE07F8DD26B3C2B8B9656EA4260D38E8D5F23C925A4476754240D0702C5859AEC2329E1CC3E426BD7665B2A4EE2E75B41B561FCE79690F64D1068DD35A294A8E8CB43A6AAA901109F0E09D985B6E323C30A017E75BF01D0AAA739102C1A6667ED48E60DD4499EAB862851558DFD17229878F5BEF0CC29FD19F59835579F3CDD4F85684E0D46D9618A205DE3B29B0BFA5FBB36745B989211E2BA711527D32CBB5E35830DF4549FEA652377EBBAC6D52787F9EBC3CB687EBB641BF51D3E22E98FCA48F99584FB1F3BED3F97F33EBF656C5795055268F49985CEA00819A07B8F4B0ECD7BEDA95EAF11E3498FA7AA414C54C38A08A841B012AE91763BE911DAEF803E2CA385C9D4CDC642A0B343DB6534C10D9E1755B7B2DE543AFE1D3C90981A7BD907E9CB14367243D9FDCAA8776AEE5F65ED6DC02F633BCF9F57DAE39E8E8261DC10029DF7B7124BEB67DD753B36892481EA7CC54DDC3A60EF8D4DCEC4D5796DDE0E7453BBF0FD93FCACE97CE5048D75ED1F34B69A392E1734E262B2B2A1E246331A373B5CF1FEE7BB46096C76349B0F19BE63FE539DCD33A8450BE894C2DC21BEFF0DE6A841A533F4C9949289037D161BB97DCE31CDFF4C1E0AE36B4192594DEC3B021E8F3D5B500C244CB122974F8CADF125DE0CF832A920DEC3A6F7150585D0209651B0FAAE0F74A36FC8779115B96136805DDD4F6F3A69C06AF472F369F481359FF834A0FD2F9AE899EA36B9B061B63D07C1D4ED7A373ACC40EAD808564B05FB0C6E656A80FA3865AABE483848D14D1DFD66D7AB1F353642EE3417869DA21622F6AF551659D07E6C827C18EA36E2C5E806A9571A7B05BBC1BA283A8984BFABC555AACAEAB2453573F782A4087F0F903AF34596E83282A2E54773AC33543BD353A3F855BC46810930C3635A9B70BA7FFBEEA95A129CCF9E9538EB11E119A072F806130D831AF7E57D332AC889D7D9E6BBD1C65D64E089722F6954F126E64EA939D98084D434EE74B55C549BED21D11264F8B5E023277DB52B03D7B8A8E75B12B11D62052E474E435707272D72D00D92288CEDDCD1ABF8E63A8A9963A48B54F492487B309F69CD90C9FF54B9C5A55CD2BAD4A2E0A6B00B188FD6C527A8184BB63670BF626A995815810CC0F280131F5F652EC20609C7D3B910E4168FE273626BF0E2CBF05BC9CCD178AD91BC25CDF178B387DFF0B6B40A46FDB6C975349B6CD8AD103CDC5DAB8D09D9A5B55622E74564C1E789C5C185CAC04FA0ED6065B9CCADB1D5DC80E90AB244CE1AAC516B346ADAEBAF7A030D66FB90FD070ED062A41E0B70BEE3B07F1C03887DE5F79D70F9955B25B8C8201602784EF8A60147260D1BDE8E152E8D3F992CB8255ADACE9D5DD2E9C856C47537742094190AA867459D20989DB11841AE44824979C0A2093D7EDCAA13C9DE25E6EECBC5124055F17466467E123E39034502BA966CEA873997EE25E52DE2DBBA874DC9AC222B49967B7BEDB5C81BE09827CAB782F458795B2903D72AB16F4423964F82DC69C138EEFA3273BC10376939E544964150D9DF09E14BE08CFCA06C10BB2C315B1B676C40762F8209C0EF13CFE5FAD76CFC17FE462D8330F78BAB072C5465F7A26D047FEC4BD3B918C9C761B91B02D820ED7EF345E79A66FBA61AE13D3050A27488CBDBE693B800F1E76C188EBD8118C9432EB9E7124D35A1A038D237918F1DB83304D10AB5DEDF58C6951A92AAB1A1A40E180254E730EB43B566A83CC71FB6B9749BFCD3A90B964966CAE90FAD7406A8A89B1E48C885BFE2DB41C1996F20DC9A8DFCBA1A6F2F307EF8FBA5EEAE9631C2D6328D90F17679DD9E8E9660D6BD4C8A1D79C47A5FD46BD2ACCACA2D5C6407B0F7F31D093CEEF0342C67DDE3F1BA5067ED1500DC45161B8636255924BF007C4C870990C5DCE098C5A26386AD84D0F0CE4860349A147A4E7AB80151FA63882590B91C6AD3E70A68E6FEC1A2CF65881A6DC38048FC14DE71C702C934C5D3C4CF4C474F906C3400364BC400A7DA087F94F1ACCB68439A9A6FFA8C6439B2CC5C0B17A7D649033798429F211D9DE12B24D117583E1C425C2C0348C625CC44E9B976D319E72D4E09D5D6F36EE243F5FBCB190E84DE56EB680DEC8566F5A2C7D5F595116C628CA09401D561BD78356C634419225FB01CB637C46A627F6026D39EC1C62E9A3E85FAE + +count = 84 +seed = 483A81716F91A43ACA6764C4BD2A57C9156B762E9174EA49730A6BEB9CB19A0B3755E37BA47EC524BBE2FA25B9FEF687 +mlen = 2805 +msg = A7E941D3C14E2DDB4F971C9955868ACA753A73E8EC6845ED6E9D3B444C826480F03AC771F92E94380BCA7E50303FB79CBA608E351A1A67BF217B9816E2AF9F89BE8A79F661470CA16BFB2C99EFDE97859AD1D217848289EAF543005F5C231599FF74299EC2A7C737FF94B7465DE11F80E17D4FDA264DE568D8767CE822B3AB9642D95BC89533CE05FB331B86E3C5A296E4EA4C637EA458BCED1F89355C0270D083D4920E72112CA1ED486191748B4F730ED52F9803D05A0F2F065BE03B2603D6CDB154DD7765847D656B919B08969E41B23F9D376135BD5D924529410392ACEB004849550E6CF2903181C9A395FD469B7DE2C5060ED22922AA4D7C782A33330714A0AF206B29B4FCBE0F12C18948F6634FFD7F2710138020E273CB0DFA735BDCDE9BD6CEC898C5E564EC71AA7880D97CC711412F28603DE293CD5E904E9156D4F6BFE2BE15347B9FF7848EB51CD0785D6A649EA3514E02695C7E3C4F021A9992D67BEA1D68E5B17DB2E0DC061CCB5ABABA49D110055467F9DEE61ABA8F3E5C713E94A8A96C3A8AFB698887C1FA4ABC5157CED33A834DBF0F5AF9EECBB5F2AD7B63B4C2CA94A117C2B92F3D51900926E26B101FBE6207AB0884CBFCB15F9F98F95B0D08E29390977F4D3DC710EEA3AE7433D5EA87A5F710F1FCEAB26D516FC19FD272F6B0F01EE167F06E6C33273481F280CA64FDA0549C8DB884FDD467B93998360766D4CAC4C8DE783752FB6C6D7B1E47DF23CEECA572F2AD3E2B628E31984B9054448ED1D90658BC658A9CAEC0485512CE084A535E7C8196B8BBCA5D26C105C41E083F8D56F1530A8C1B36A7F3E41FCCBAC7F342B2D026064B304444192D4873FC57978E44151896EA6C0F13D017F683B203BA1DE677ED00F2B737C4C69E53ECF16AB918939E120E9FE14B2243EFF0116B24C6654BE09C582F1E62E75EFD8593E62E45AC36F717815B854B47A4DDCFC91FC533FA85BCECB6E560CF11E46D2F334B396D68B275E7404A70F2A805A64CD458A8E5F114A89124BA1866F917749FF32E59EE71948BD97F2D4128BEAB8BB0B6B06D84C6D466BFA30FD8100E48D951D0B3E787EF9611A56FFD64D970DBACFB1B4DF064B1CB5DA9918F5C58A10F0903B64286B1C1AE5CBD00EB8B363BDD7A7AAF2111C0C6E86E15ABF6C1E761FBF027425968CDC19522B44FF3F56335C59760FAE6D9028E76B284330F7510F2B55B6F46ADF90311CC785D35C2BB49272BE514CFBBD7A2B7B2E8C0B6DC28CB683D3D581F547F83BBD3B8C7B76925E44E6DA89D5EEF17AB0BF4213EF9C05B7B473901D483C647F416B98478C7100919C28515B617A27321841BAA174C1A2D3494395294CEBD48EEA14BC3106CA9C69D9F6485D6ABF1C2B1111A8BC602454685CA61AB4EE4DB9F413CAF8F0F204F04D40CD36FA5DAB629CB53876DB3E16372E626B6BC892C63C6B6C503C9D22EFE113927395206BDAA4B83D4FEF4FEB42FA7A71F7CE2197FE282A02D0FE50F96B1F917A67E50EB79CD3FFEF064542F7BEB51AB05B56AFD7AEA5F4164CC9BA37D8FDB35A3DEACF0CFB555161E7E41EB798160798BE9D01E3DE0C4288E0BAB19AE398E94353ADBE9A43524ACE35830B82FCFD4B1DC2800CA4C38A56B7CD28BC3E2F69A0AC4655CD79B5789A2B72EAF93B018D4D6F4C983D08932B22C85AF6FB07DF0A786D98820E1B06BC17F62D6E39739790A13049252F1B9102DC692CEB20C270FFE9B902AB7EC5A4EAAF47F7E2D31B2195F5F48AD18D099C33384141DA14E151BA57F6B1BB97901457202CDB83B5C713BD8A13F6E3E276C7D6C130AE287CA8931D9EECE06AB7CCA124D6D02D497D55EA9151A95E8A4DCCDA72D3F51A7DB3F2879918753683B01BA1B154DA83E6D84DDC9492F2DD8C128A30C75174ED1A6B8D93D08645270BDE247782E882418EA158B2A2153B2D8F75C09932F324EC199D26E9F3C4C4CECD807367E3981E137858B98BD1268D2C894541EC99BBBAD19A6856EA16A1E56B7B193BAF79AB89D4E76327405658C4ECB5A8626302B3A4618AEAC7E11A1199C4BB08C60AD78FEA4827B59CC883B2CA7038D7845106DE9174B2B8C17267273D23418AF560265000543ED9886884912B4160FBD372FCDF706EF642CF1829493884B6CFE946ECF6140106DCBE11B3746E33FBD4B5852B732230B9047004F4FAFA0D4BD7043C7D6595ACCD1B2771AAA76FE05A0C80B7B221DBEF79950FC69147816CAD0E52C05E72CECCF55FB4DABD81ECDB476417DBFDAF3B555CC90573CBED9474266C89FC55FF0BCC55602A51A1B5F91E425A1A58DCD4ABD09BBC63933FB4279B9E21298F9FE0CF1A93C4A19695240E8978D604047ABC7239F5053EA650D781307C50DEC4D5E2360ADEB9AA02C0F6FEC5784784A271169CE456E1C32BF984C3323656CCC588C97E0ECE5A40FC7B4DDBDDDB764EDC512DE63270F07891BD160F78B8ECD3A4D11EC4C68EA0A0FBD0F23AF9AB261A110F431F926C4995B05462E0DABF29D9660ABBC660C9A675628270CEA7EC5AE9B6F298B17B2392263700B8EAD9C845AD29CCF109A2ED66ED5BAF9C935754AAA1B84BE2B5339F9BF3CF5E80AF16967863FA8DCA64F5FE873DA4A6D33E39A592749B721FEC203C0CAC527CA96DE7A96CE9A540F5DA1902C97F960A05EBF0C32934F9B81244C945A60FD3F176DD8C261690D8EC98D19607129A50EDD51135FFBAEBC04A0961ACC5A32FD058FFDF2C6866BF90A3E177787E7061BD2011EC08EC118EF0451CAD010B53C68D0BDDC701D10920D697EA3439B1A0F96E6256B7712F59C746D1C74C20B17D461C3DF635EEC83E3B8E098034F119B9D9A79ADA735158EAC3F434E805444D5EA2EC85CC8ED8F5BCCAB7DBB6ECFC2E385781579AF1263D9FD32BEE32E01DB94703B5C756B894DEF19783B12BCE2A1A8D29D96F329CB0791D697BE7E0F05DD5C9DADA52E1B8C1E5F75A0FC90ED8C05BDFF86644B1EE61989CAAA271061D4222818C894AE9ECA2DA7326E5C24CA1EEEBE3720D2127BA997B0C572AE30615F8BC4278057F4762D46A39B934DDB2A0903FE1568C1BCC6C37E1F7C145EB7CB20A6A4B3466A7ABA58B48BE94F7E14CD20C87B2768358D06E3F607FE5E9DD1AAA8477975660F1E379B9EA26CC00CEA8CFD6420F2FDC7EE6393AA17CEF88645B821F8F42FC7DD97B0E16C04631F86ECF1CB76A6502FD1C13917CEB26A83596B117D5336387DDBEA56162E8A5BF2FA35E697245BC7210CEC13BFA694AE884582924168BF8EE2F61A734E37876F363225E5AE19B7C65CA6AFC31C8B37BCCB308A9C27F3E9902DE365E288E6CC46E329E78BE914B85EB980C0BAD932C164671ED395D5D8317C133E2E000A10E0D20D0F408019B33D9A87ED7725EA4C5ABAD67E0CAFBFF31DD236E59DEFAB7FF2CB40F479B56B261A32656F016DECA5302A336CA15D10E0AFCD168A4B922B79C11CB21881220374492D64DF21453B41346A85174A0A4A3C1E973845C856CA70D6D25BB854D0C6BD3C75CD73998C7F64E35A58DCF593C85C2440A6ABA4E470F87E6F9B4ABE127B30F8992D8AAD0BE38F008D9D937582EB3AAFC68F516D5AAF2503ACC96E59A151D2D4B072AB6B38C54928D6656441C709F1C1B770CE6EFCECE11F8B3602EAB63E0C629BBD8A79A96BE4CDB072780F3D287B091FC94FF2C0D347FE280BBAC308644BDB15A3C653863EDD945AF0AE725507507B82C283DC9909CCACBCF357D7A19703401B6E4474B94A6CBAE575B942501A281B8166FDC70E6B4B60C2F57A4D66FE1197D301D0E0C7BEC12CEDF9496BCA2183D04632711A79C8374B6DE35C2EECB0239391C2019C720894BC7A635DF18FCEEB9AAE16B3CE92717E2C56903D20D0712EF80131B8C48635163E97EFB1FABD1500D061C93AD935BE9A65A45A92E4A4E885268E712EFBE5337214701BAAD4C73E81E73BFF19AF131F0ABA105BAABE849F +pk = 1F73B63C95E6BBF1D454748BDD4DEC6D3E9153758979FD12163B3AAC929DC114CC79423C77935855FD3A71A808B8CC2AFE45338B6C5179A3286717C9B88CACF21470FC86D9136CF53ECD24FD67460399DED86356C628CD720AAB42E1A8B268F64051FA4E7EC446F84FC36847F638353DE47CD938A524799D6889FA154826C9C5A50567B0D8681CBF4CDB07D08F43585575443DD37B5E488584BC50A904ABB189FD53E3D454A7D4891B31BC205B93C1D867AEB13EDC8B0A0737E22309EF223313BDEF2708591C7B0292B6357D4C152AF209BBBE72C0064441B8367DC87D84A2C58A2390C258A4AC33D4E9B0FBE20D9CEFA76193085A6B8B63F516BAD01AD955868BCC216A53C544E8BEBAE9243FC1DBBDEAA17135E58A3D8053922DE3C901173457A4CDA905D95EFD6A47F0B4695AB0A02C2918044C56DD4D0CCB9E9E33301AE523E5A033F6096847D6ECCA7EABFA30261512D9961540B62168F0488490FD8B0AA5FEA3C22C4F6EE1E1CA15582F2AD755FC0EF7361A95EEF762F40847F1627D43FBC5E888BDC9B590B71E32EF30462BAF6695DADC28F0C6F3102681248CAA866D9F154A0B1387708F4337BDBF013013DAA6CDBE73A0AE4BAE63BC3488589AA859E2913012509A52453FF4DB5B42FCB1AD3C09E9EEB3013F27F0F0E6FD6506B434BF16ABCD4D2CC0DE8F81BC9844A26A02A332B857E77F16F29FC64FD750FE3A34BED1939CF3BC09B249F37969EF9B9D190FB80EB0491C6DB70B427887AFF1F608E8689588D7178435172B648DA42C14FB15DEDB4AEE8307980E5B9A4370796C93B7C9B05544F5E90B226D4A1FC69464189F2549380529B12BBB873946106AA45DE7D9A5DA02C9624855497DED024D9CDC60A4F593CDA53C0B4A4F9AC81F467555A2F2334CAF909FB277D15A66C57D2C06D709F8DBB4162B50A15DA88145A42FAEBD18F43389954523806E36558A29CE4869748033ACEB4D5CDD41B11599C32D5AAF97D741FB520447530B5E00A81A60E5C370364FA3DBC20F48269D3B04B4E20F89A3A09DD38A2477158A906258A3CD5F8ED7650630162A5DD4C50FD0582D984F13494076C0D4F9277E2EF62D49C9220265408AC5BD52827365AB1FEDBB37D06A4ED97AAFC068BE91CF2AD43656CC94DB44DDD6151EB1C00019F7CF7A21AABFE227A67B69AD101E80366F3B60AA38E7644DD55BCB85F97405B569612BFED61A2D605408E115D6961A5643EA175296E4680FF6D3A984090CA1C9A66EBFBD28D48DF81B66C9C8AEE29BF9ABD448E5DC6653750F80C5D6D765A5234822766BBD2FA6198D0F733199CE7D36C6C01D2C858B1F80A99E31737626AA1F4C1DCFC344BC8350B5024EC23FE46B0425727335E6DEFA307CD490C06C28A7F357E8F8DCD12F1DBA407065B686B3FDCBB4CE37925A85DAA8D9027C32E8AE1600B7CA856AA57832D17935095A5DA6A23952CC43546500832E4F46F321B4876D2051021CD9C07F9065EBBD8EBF2452E49B29B6BBA10FC33C1EAE5511D6BD934161965C82EA247EACC108BF04A8917E17ED33BD296F69AB5D3369AA8FAC2E88ECC2B0E151AFC52D23830C6D16297A170FE35E960E974806F2BAA9A77E41DD139C482EC8B0646F0F85274E4F4012B938568445453807CC062744C2D6F1885CB48C73BDCFCB1CD7CB62BE4AD65EB6E44FDF901FBE1A7E0EE60AFC7857D5B10562561DBE767BCDBF036FC295A1425F8783A01D7B56C8ED2872BD0B3E4DEB4D42E2EA9A97DD9C9A9C13F190D6C074E48D1C8328B9B7FC8C283D03C79CF781F0D3FDB0D3DB51F71CDC2A36380ED41ACF0D6F04A638201BC27E2AAE30A44EA5F7915177318A04812DEB932AA4720F73950E18AA84FF347262F206106679A3FE3C72F283527D12765DDA659FF7416342F4AD24A67858801B0886F8F875FB109C57D73B666FDC0E5135DB5E292CF4B58F39F51F96044D63CA4E593E98A34330D184412D43A6DA39A8893E66BFF94D1CD4195CAE276AA8025749761E66BD152FA38F1266A450676A1CF9260F62D33BC232EF85F2C93781AC486A7395D739107F6F62F749AC7BDFABA33540F9B132C298633A7D6D5A27E6FCED9B97173DAE6EF1056348006C4DA93E348CB82B03CB47EDE59114E64E96E569A36D6EFC56EEADB5B7251110BF2CCEFD8A4B92162DE25AA424F5241F7E40DE3EFBD5DF95AC845C7D988245542A5BD4DBF0B977369893E929AF4979D05A252999C5484CAA5E1C0C2A7C840AA6C2E3A6BFA94982F15444A81BC80385EC9B348E300252F0107A65A1343FEF6C7901B4EE96B4901197618C13A08A211A62C8035F9148C52FA5D9CCC54D2AB819B69395D6CCE6D121609F273F7439DBFC2AEEE83CF81CA403EE21D3BAE1CFE5CEDA0C2E985F88B3A6C7DF4E84B77839091B113018CE231FFA0F82B8953CE263629EACFCD97C3F758DC8F1509B848466A2C0BF20750367EE7643A1586FCC4711F5D54C553BBDB3711C50155D043B23363AD7DB5407372A57655B3A212D46FCF7E2BA60FDBA0DAAD6F685274B04BAD98CBA120CAC84DBDDB5BE1BCDD73B3CD66D57FCD764070E3632E43A9C91FF341FA5E00F6138DED5770430CB6FA5EC86768EF382C170E12DB798DC0EC981A2314BE7AC46EAF2AAAC7A4BB79764F913188328C8AEEAF0BE26DF00AC971C97D8ED205AB5BECAB366BF7ADB5310DE7B54758E9E08BB4A6608B31B9E81D5704513062BA3E1DC382A39D21EE8C03660BA32DB1DA5F29D41DBBC6646DA79D5C8 +sk = 1F73B63C95E6BBF1D454748BDD4DEC6D3E9153758979FD12163B3AAC929DC114D4D28FEAAA989347F97ADCC29D585A8583FD6AF03A5FD954F0E036D13FAB71C9BBC7609DFA1807788AF3D80CABAA2075198140F86BE63E5B54C652E4A5FD24A62E2440BB3F9CA301EBBAF6D980F42D42C9D19125792E9E9F7BAB37B0E2C76DCE586655267083623667162532088076822513784464225862205337147675553121454277738848403535087634474514065053537776202110433054750362516210357581631730574781014256474752487388217536223025011608882372108158151767600265520520220431703270143542567464627156283223611535248357714303564217511480464067653842285287624331730425471363015427575281526122354012340138405683202261410411435667566866200565867821012122135036518865617740676025846067654031475275566612580304883476013652244118430153435748804623076422277836477414200808523550484506143647101665647741753338317341875363748415442600613451283486288148088360184182308722112177501563853167038303350461217274764200366371752558588564487338166343865670755143355624848534162781804260751757023808546127735210354413111874436841417201030157221657683684767360482445155661844183453008806241074121171834004063264503502456253532036140087630862864372463786171754772320860115524465157245615868727202208750723622364355342731461612403743110882022806485353124713321835884506112186648581527453547657721868686851160227842683104460180331701536006140382058183248003452213177136602130611570373520054456456375256015504887478583308558046431736746311640427635213801763163343755360864836202121105220868750853806335350612463647077481361421337600384406044712007061215457532107636734307063087651330728830253670068315316885332572048813532404525383006704847565501526811854141253332676865057750388724542800026783738431225402315768675515714747753856632114007530568657003508241833530888757153782365306282633275416826165153513560534274041804110770515708287353683728514651055807734372415730364828826608465486202550584580311216761741635712010012440500431314708548471660250228452754048273138227234513742712481487537223140311540188574261354738401107060876870207546736557870168885540284762050382012827674440227020863243470876263250671884181002324428473110315063171188211807634514556571440463475275401155806715647651742241620217437613264783428707102017761228557834345864702534864866881882661380050718835102717162500608544134523673384585352548385611773028257614373433308066207235800753845348332108808140216633714241562641807380082573204206831635106822868782072887405337883743810666288322721204485717637041480270015535618440356380154066031721054187014771330563270884218584143621806084257850016787651667411520875046534624837764147761134886737714146204133485086607541501525540513205325068703776855153347764765837772882865423606146387006506462654677126334856555254113886087677424338688254818802866806616687733351764014227083421402444405064661426558388588637785115154242162051032180161371481163078734173774405570764242570001224217357717366140684530568857465417815678440300172626318313783280824312338235610470065842822657540733760772280001767374401675030538570144248161327380675066855542163543368112200256571725237368535854750435AA244B082A10A42BC5DCE64924C3681ACA8B111A007F1CB598001654ACA9D7F5B8D92AC30FC2A354B7DBE8114E198B51F7CFFE20718BB9BEB5431E3CA20D21B11A6E462DA5302C299A66C656E88A07DE94C566F49F59A99A0EBC0F43E7AAE64458C8F6B53594022A5A2AF9A517C62D108E80201341CB16823832E3AD79B25D0E3F000534ADA8449512E447D146C85220806730A402AA14541D271B3FFEC6ECB294A0415EF9E0ECE5D3F213DACC37168F70A92DF6E7710E5C8973F90E4A2C7C9906052889F9AD99BB46616C58E18B102655C6DEDCAAE79F376E0A19A5EFB6DD27D4B1FD5A6FAB60DEC3DA3ADD768896DF8D2459BC7C8269ECA4B5300E5075791BB82689C58787309033881D76A7B4E515335890442292D5E3BCCA8436331B1619305F416B6ECB60A46C17AE782FFBB94FFE37E2217E63149D5D99229E1F8147182E7B3464EF8F0A2411A7EA314AEE36DF87E2F534E03E65147BF2ADED0A52BF5E4AB6A75C5383FAD908259C82A81D64B6A682308178DE3770929520B3879E0CA51AC7C432F25C8B0E49243E89A73272F4B4A12F0153A581DA3DECF90098A4B824186F3572EF822D04DFD5EACA73532ABD8B2C34A47BA88CE45885481A454276414DF520C2862B527949C19068CDDAAF7A1B845EB78FC78EF791D12CEFDC9E550C35513159EE15D642977FA209855FBD210AEB694E42C60507C27A56D101702EF3B20BC374CD0ECE3286438F71F45F7EDEE174A30E936833043FD8A451D6B058E52863CB7CE3BEC9772BD3C531ABA351F8B2714B04009FA0AD7D5545C99AB6E9B1F16CED99CDC2998FCD7F448012302358175E528AEDACE254BE69671F349DC46AF822F93A617D675320FE4F5F1EE81015874C68027A0C112C6DB175A48DB14814023097A7D07CF542875B42D03D73E60BF7659DC5FB1FD594CC31B65D50A0603CA7092DAE6F9C6F4D66FC052039AF4B196E268718F069CFAE8F1704C2E2C4CDF23364D2EDDA2EA1ABB6359CD73C4A97032E2132D9B1375B6322DA478B24C5DA478A43E1ED7E7DE5E8136E0261D2BFC87F3456065D7CDF9FADA35F48AB4451B95A7C1C595AD12F5AF9F1E6041B039C868701D57D64F1E42A6BA7663EE423964141D073F5580CD0DFB2ACE7956B6E8915337C3AF9E8B968B88E919183015D23F5F2F16EF6B71828066679783D8BB9AE71FB2A08791CF2DC4299562C453AC0999C73DA46D41154F22514BEAE0886426E9B5B3651F0CE0637B2D9B37148784C49F6E7F9C8BC2FE9F63722B447E54B0AD572AA235634C55326E4362FFBE0E8CC97DA7414FCB7259F994B9E73B7C5D052A04884266EBF6DF619C259C544CD7693C381A4D0156F57A36EF08352116E8B017839CB8FE91BFDF90A6826D0079B9ACC2C96778470EE7B765CEAC77FE775AF7B28E436D07058531760B9DCBDFE0A08F1B046E0CBF016586213E636B79DE6781101DF2906D31EDBDC50657884DC1537548617C2BA8F4A4829ACA744A8A50072BD952197188B41D2AC12FB07BFC7E18FBE78FBA6EF40D26CA3F00F08A64DBD38D87794BFB0A1EB85E2ED8CDA2AE131428D3EB3C47B6FF106E6B357F62A7BF4632726DC5E99AA949AC9BAA0387BEB3866CB418EFA8116BEDF9907960B9E84F46B5EF03C5479F04A2A3DCF34555B1E39FEE21B3B1720E44C11C41149D6D7428005FF1A6468BC3ACDB8963E36D574F2343F76B1CAC98E11225D7F8E18BF54ADCAFB15DD582EE9547D3D1B7F7CA92E8D180E941148B291AEB48AA8A1597076F5DDD7ECCAFC8C44E9EC32BD5F74FCA39656874EFD820E4544F421154C8E495EB4D60275F9B0BDD78C6CB01D24F5971264BC99C9F61BA92C7F25A45DD1F681B665ED816F607A381789BCAB05F53FCA075E807C9EE217214225E31B991208D7BCCAEAFCFDF2E1EE1D0CB68FE23DFEFBC756C786611F1BE0E750A4EA5F03BF4C1BA333AD51F59E72CB106360481F4D05872753695EE30B42BA9824070C7274DE3EDDC36CA4E91073EAFCDDBDACF3BCCBF1EABD1C3F56A209503657469AF59D92A90ABB7AF7B2B6E21FA3F2A4231E621E0D61E57FF0E22A8B5B2EE930729482FF6A894E2DEA0CF1B7D04D395025A80BDD86825849F402026A8AD0B4E883599441DE1750CF711C443DAC9E72F1B932036A257BA1EAB807BBA440D84A2CDE8729CF5F2CE42C56A5FAFC6DC0650FECA40C7814ECA89DEBDF9A4EEE886BB478E44E069F537B7E1DCAA3A16DDB337A38D457C28AEB30845570D1FBDCBB91D4B76876C77DC1433923C64773C9630222176D0CB6FC2674A53C39C637F1A4FF9715A449F7EA2C679D3F5DB08A976B6D008F59AC703C63F066A500373CB54BC25E852F75F4E63F9F60EEE1FC62333332B528A37D79E9277F50C814E48E8BB8DAED1E07140C321D77DE9B5208456F3F845327CB5B8119146D28924489EE0A7059B7534C2627E85753399E555351AF11A4248C6570EA20C956B367D80BC5C4C1125E04A6B2C226B98235A5433A97B2ABEFA0BA6933A872F16E479E9D0BCCA8E5731A87C53AA1F8ED3ECFE932DE63C23FA995452AC924F3B43BCAE165BB9798E1CDD15EBB6DAF7A4768494A91A16B1271363BBEF90731D8B3C0B5E326650E9D4942BBE695ADFBEC4D8A2554CE4E2A6A8D31D046EF2D0522A4779129C9A7F190AA02C93949AF66B8420702119023E85E238FBC3485532991D65A52BB95839BE404F13FAAB941276F41F4E0AFD63BCFF83E774005EA95A3C922277EA6C0189D54B8812257F0A17129538B52992B44D40BBB3A25F880DB6B489F592C3D88CF22DF7E50D545A8228A29FDA47341D7AD232E01E8162E2D71981C2705945AA21EC2B51B94317BEE6861D40C7EA292840BF15AA80F435701ED313A7A840C562BC134FBAEE97623D800E282F948042D3553866C03E681A05E8352D3F2847E05A1D46ECF302A4544004855F8BFCF59035F8A2D3654A73FC9052439670DFB8C88AE6AFF960E974712D5A473EA4D596689C3866119279FC2D913FAF793402CEF758FF262175B0B40420063F49D47F1DEFC2AAAEE6106B62086309145706BA68D142805AEC1F14CF92172FD947FCCC3F6606FD96513A0B21E824CA3BB4B107E542A36DF0E20A1EF1909F4E9991219B39C0762AAA6148E08F334CE021E7A7DB711536A872CEC5B01A8E758F03530EA072D77C8669C2A512E6E0F10CCF61B5DF7F7B2EB231ED70C2661152ED22C0DE82F272D4865A0D8D5FDEBF1C561C3DDB6B952949DC85978CAA87913D9CA3782E31B10C65821BCA25E448B01F8D3784BFBF0166F1C42CF3D3750AF6B874ECA4F0B270A7E7B4796786EEE6B8FFCAA1FE72447416C1E9D8C9058ADA62D5F0EE780D02B24DD2C2A0DD4E8B595A39C184F9F1356897CABA7821FA3E475E0D525F6775FCB96BE4208C68262A6A91CA4E16C671AD5BF1419EF33B752D3D2B6D9C6C178C8F9F928B95EC9971B34864F5873A9B99C7CFE1FF20D4B35E056319B41D91E26BEE7F9CDF83169D3D40A2325AC33EF3608F7BBE9CBF02 +smlen = 6114 +sm = 711384F16BF01CFC202C2EEFA054E2B0AA20B8409F956A98C5D415A39E1F94D112992F48DA1FECCE1B5C768C0DC676B2B19C89BF1034275F5CF692AC6CFE2627764FE2577BFA2C9B3DD4D82959083077E580723065566D9E1EC7F4C1F72C6E4F49A7DF2E9022A17F613F5431BCDCB5772AB59D8797A1267649AB4E121E629E425CC70143B3F9E3D683C25C75786060338DE7E169BF5670CED46ADC3021F5A61CAFEDDA875B390E32813105846056B37ECDFEBF20F4EFC2BE72F544A93319026A6DF54848A71ECF8D40DEEDD5FE3C60C1DD4E597C6BAF9AE829E1858BC1C306D2BAB63D2D452D231B91D1A767767B86B76B15ECD40CB3E3D626D0D7DE9543CBCB68F1A28D1A9C91EF4F2474C3BED67A3D64209268F114394D7DC3366C7F23AC0FEEC4018BD1D22F312307488D9893DBF5C4C9F96F6205C3F6A548E476172A7C8E143DE00636D7D783A18AEF0E0461F9729E5836B58E6A2D35692DCCDB0E83BEA7F8C5542D0C1B5889CA1E327CECC056EEA2AE0E0551C34BFA273380C23B1FA88C082DF6587B742B94AFE8A9709CFBF494CD87447A9259381CB82A64C4935AE5DE6AC99F2B798A5EB0B579114D235E8963D66D90B1CAE511C7A246A59796D776F7335589E138DE3A69682B945F69166482335100AC4D07CA47EE69E67676E568AA8A74C093A5706BE51F14EEE551943751C6F4E5B90AA9B0FC8206C5B9AE6D8ECF1F01B177F614ACD4846E71BB1A3A75BD5CDC65C64A25CE1691C2BB31943C4F8E9137A33CFDAF1A2C15BD3DDD4DE6AE15F5D1A8446287211D8A05434E3C5283B085A9EA5B82FED184B40D00B6B61D5A5E97E694E37ACF995694ACEA01005F3CB56A4253A73538E6C11A4A58FB967836888A7F73A51491F33AC339A619E57530B82FD572D9A639E201C822F2D851FA09C94148DCE4299EE988F1CD4C5E22EF888720328F762369A54C3A6D77DF9DAE3D32315EFF83D73AAB07065B8AA5013F5A87BD09EC06FD79F2A82804C8B2812DB4E56C975B57DF8F7F20B2039DA3C6356A474E624C6C6D89E534235C8EDBE8FE1AC5164C32E16FE65E91E3DF8BAFE6888A0415FB3B5C2FEBCF7F7E4576CF9996893960A4A6028522C59385D5C2820623239B50409F85A1F922024C40832B415AB4AD5DB4B7CC82A1DF04DBF6E76ABC60DD77E55CBBB5296D24FB29628433594E41D75D920585A7ED8C46DE916815DF201C5413726AA5FEB0F10B0A4249BB5E93F7E0A9CB94E663CCF9BC78C594B7423289E4EDDAE5FAA49FBB74A17B11111FE3B2608DF276C208FAAF8BBCFE701C11F93876B5C9429340F0EED3D68BD1CFC85B268CBBB12576D55245BEDEC328F14C3D876DC8BD2398BA1CBC3C02A0F0841CDD654931F571EFC5B6E74D8292A5824A411BE200646E0E966237651AD474185C2778EF92B7E91D407C52648C6E950F76D5A5C6F96E47218AE0C097B04E7E4FC308149920EFD9C6A0DF8B4D14C2BFE2D242F6B59BB69B556F3A61B9BEAD93B43A672DB8364C411E9A312DCAEDFCEF261841DC4238797A341CD0C71ECC9D2536692AB54F58B6BFCF236F789F77062CDFE3B226B19CFFE2755CC1ACB967C5708CDD0EC067E12CACEE24B7952259CC4D5A45870129A4704E62B0F4186739CF4C9D64A774D84A9717AF0C046686CAF159B644AC2715BAFDB240EF6C6B2EC0F0DBA1C61809FED1976577A3C204387CBC0162D2B566C22562017E8C1623321D552BB89420F5AEE32202562B5AE771402057B4C40F0CFBA2106D27B19D8566434C549851AF91DCF0EC6D4D0718D0FBABF094C6D83EB357418FB79749BA1A6157882F36745EDA7B4174BD15270BD16FA604692820C1A8D4F5C45D42F530AD89E5AE3706AC56B03D00216B4C94A0A75DA45A504DD4079990B22E708612AE53E56CDE5F4B67D35201696F4E490629A95549DC660A50599298FB0E0EFB5A5E8A12044B1F5AA7AB7D94BF10DF2BBDAF365246F5457BE6ADCFC52D2EDA8A43E819255F7AEF088EEE0FA884D9F36767D319B4DA02D5FB45AFB8850341CC6A47C53DF1AAC5662D740DB539C06A3F81B3E3CA1B4D2AA907EA98717DBF39B371C6DBF1942DC1C2FD923F4416B00E2DE0E1A6FD1AAFC11C2EBD9FDA17932D4F915374BBAF459030E98C510FE710CB9C26D2D76A560B383C64EBA1F2DCD7AF11A819B79A98C2214DB02F3022349FCA6A32E69F7F125F1592A9BF71DC3BCE0156332D4638E1344002E739500E59EAB0FECF3C53891B98CF12C524A8FCEBD7868F06CCCEADD529518E36E9107C75F3F90598A9A01ACC1FCE602A8575E5B0FB5C65D23B9C74D49CF37F757455CEC8E006E3A7132611F088847C4DBA644C577B79B67F8F7D856D6AA7570D4644B24D184AD6E917F5CC574338EEFB7F33D120FDFAA73D92070B785CF2AD29B67F5085453E18AD1048130FF7842FC8D0F2541CF6A5BB23705F2F0FA55C2CAFDABF4FDA2E92244E02B91F9C1B7F4B86618641E78D834C99258CA9E75D547CAA84C22BA5C40C5A59D86EAFB84570C51B31853E78128B19CD6EC39616EEE277B5E9E41062EAE0A4212D4E297F68CC54C25B974FD511E9C815DFB072B6BD5CC495AA3D435B4EBADD7C0EE767DF94D22B0DBA4C2D492F7ED2E37C18F344C7EEC0CA8D67B45942C742B2FB13959A8B9ACE279562F34AC86835738689C27C3A364F6A444A44FB3E25BEA4BC130CABAFD6287F4476D8908F60E4D4F3F686E403B3A60084E6FD5C4B0BEE01189DDFCA74764F9DE42D77043FACC46A740398B99FA18F9E85044CDDA7F98DBB673A6F683823EA2C9C613E4369A11F82A6A8FDB840778EC796CA37CD43B29F3EA074CABCB71EBE812CAA77FADCC21511A016449B9AD0FBA818CA43FEC7DA664CFEC239E6BFB185276A89ACDC1C73E5FEACB7D697E7443C1485B9C1FFD5CBE34B74018852E20F695D5B341E3988EE848C9CB72722BD9EF24E5D02A7FD101A1AA1F15E862739A0A25C0A08E536A2A4F592379867998A2F7BE729F500AD648C1E1D989D7A8EEAFBA7C67D4969573D9E9D94485ED7B162F531C10EF91A35BCA0C93A77A17E7A0C82412BFF0E63AFA75307391DA0A6B0D06D93EEF47636E313606E41C1425677F943D1EE223BEA2885F65336BAF4E0338D172B221A9E8CBCE7A8EE209D599413D2A2DAF1535E97D00B5E25506DAED619F2647747D4C138B765826D5CFB8315651B4118454DDF8119577FE843B365259364FBC4AE20997D4EC88600479C8F25FF031769D127B4FF9022A2459AD26137AA39E28F716DCAC4370679D67A45B4922CC8FCD7100877937A4E4F86B18BED6C99859AF0BF7AFFF47ACEEDE8F53F8C9D53BB4F0463F3D18A9E3267C71C34861B16C5BD02E55CA42856EC2B46495B64E9981E064C360D9208AFFF20662371A4C7063F840573517DF05AD30673937CFFDD0B8C3F78CF69B792F7729B29764F871148E987290C52BC8DB97DE416711D5328A1006405BA5EADA1848D354ECF5FE7D279A0921E37868CE5A1CBA952AE7E62C2B10A5147A5A888EFA281E91BA60523ACB19F71E942DBBFDE40EF9F5E81142B3634A947C68EACF56D6FF6D6176F7C12D730F08DD587F5D6F361F1E5174C68D98E6F4F6058B1F26B8BE8D170E2379FC1E2816F7853A645C80B8D268263553A050E9B1D71AA3725EDC473A2DA6B1360127759DA0A410C92CD5DC682324319C317677DD29AACE0A04B4C73D7956926D402AD06C6A32C67E1BC5DCAA2060CD3BC510704D329688B2564567ED3562D962D05C5D37FBB62BD801F28CF00CBF348D9CAC96162A756A22B070DA16AB14DC97DEA228C7A6D32160A26956444B9158E1B0AA4C43D7DEC2D30A1D3E0C53C8A00BDF5D52274B083EE9236341889E5FE63796C2CC5BF55EE913ED232527DCF6BFF4BB88036EFFEF535D7E668186E498AB98721654ECCB62E49FFB61B07C7B2F77720AD44037B1872B1FC0B73373DEDBDDB21D7176F0E3078604B485567B4EB39985D1366B42B4DB3DAC7EAEA223D84509E19C90D8FBBC8847D09ECF190375BAA834BFFBF61478F828DB9DB3FE72702CDCCC1530E14421B1579CBA743BADFBD9EF6F2394AB71DF1E7779C93E1FF3B82F4D859E37FF4A0A403A9326ACC87A57ED8D723FA6996F7349836C3E61C77D7DC855807A17FC0011939FC912ACC74561AE1CEC808E57A0E1640C601E3CDE145D012293188583830FB3B13C0E161C4D6CAE976195CEDD5A61F334C666D54637D58EBA0BAC833D2E0ECA3FF83F1CBC0FEA01CCA29899F2E3FC009D62FFFEB8F46421E6673C1D922ABCA3254DA1B25F14F734BE0B4C254B0A2A011B71E9E525C9D90816385102584E829B729083B338D98B16CD30483A5BED5430261DC628C213A59C8ED2C08B8F2D9C1D6E7A3586A3F1042702A42E56B4B6842C835DAA957466662B85665F028C0AD3698B884CF38E4AD7B67C878DC9CAAA17602A3F6A4EDD08D8DDFA0538070F0AE1EE8D9B8E1C08ADD3EB4F05579E9C86160BB0F191B8058CBCF3AE3F3EE777595C1439F18258D9307D5315D4A8C9F67AC52BA1831412C7996378C5BC71533CEEC6446B83A4EC458A41B0E0C973BBA43D6FCC833C6CCD99C1730333F42959C24507779A8C7D52D378AC2CBD5DCE6166787A3F40B254147D34344D20000000000000000000000000000000000000000070E161B2023A7E941D3C14E2DDB4F971C9955868ACA753A73E8EC6845ED6E9D3B444C826480F03AC771F92E94380BCA7E50303FB79CBA608E351A1A67BF217B9816E2AF9F89BE8A79F661470CA16BFB2C99EFDE97859AD1D217848289EAF543005F5C231599FF74299EC2A7C737FF94B7465DE11F80E17D4FDA264DE568D8767CE822B3AB9642D95BC89533CE05FB331B86E3C5A296E4EA4C637EA458BCED1F89355C0270D083D4920E72112CA1ED486191748B4F730ED52F9803D05A0F2F065BE03B2603D6CDB154DD7765847D656B919B08969E41B23F9D376135BD5D924529410392ACEB004849550E6CF2903181C9A395FD469B7DE2C5060ED22922AA4D7C782A33330714A0AF206B29B4FCBE0F12C18948F6634FFD7F2710138020E273CB0DFA735BDCDE9BD6CEC898C5E564EC71AA7880D97CC711412F28603DE293CD5E904E9156D4F6BFE2BE15347B9FF7848EB51CD0785D6A649EA3514E02695C7E3C4F021A9992D67BEA1D68E5B17DB2E0DC061CCB5ABABA49D110055467F9DEE61ABA8F3E5C713E94A8A96C3A8AFB698887C1FA4ABC5157CED33A834DBF0F5AF9EECBB5F2AD7B63B4C2CA94A117C2B92F3D51900926E26B101FBE6207AB0884CBFCB15F9F98F95B0D08E29390977F4D3DC710EEA3AE7433D5EA87A5F710F1FCEAB26D516FC19FD272F6B0F01EE167F06E6C33273481F280CA64FDA0549C8DB884FDD467B93998360766D4CAC4C8DE783752FB6C6D7B1E47DF23CEECA572F2AD3E2B628E31984B9054448ED1D90658BC658A9CAEC0485512CE084A535E7C8196B8BBCA5D26C105C41E083F8D56F1530A8C1B36A7F3E41FCCBAC7F342B2D026064B304444192D4873FC57978E44151896EA6C0F13D017F683B203BA1DE677ED00F2B737C4C69E53ECF16AB918939E120E9FE14B2243EFF0116B24C6654BE09C582F1E62E75EFD8593E62E45AC36F717815B854B47A4DDCFC91FC533FA85BCECB6E560CF11E46D2F334B396D68B275E7404A70F2A805A64CD458A8E5F114A89124BA1866F917749FF32E59EE71948BD97F2D4128BEAB8BB0B6B06D84C6D466BFA30FD8100E48D951D0B3E787EF9611A56FFD64D970DBACFB1B4DF064B1CB5DA9918F5C58A10F0903B64286B1C1AE5CBD00EB8B363BDD7A7AAF2111C0C6E86E15ABF6C1E761FBF027425968CDC19522B44FF3F56335C59760FAE6D9028E76B284330F7510F2B55B6F46ADF90311CC785D35C2BB49272BE514CFBBD7A2B7B2E8C0B6DC28CB683D3D581F547F83BBD3B8C7B76925E44E6DA89D5EEF17AB0BF4213EF9C05B7B473901D483C647F416B98478C7100919C28515B617A27321841BAA174C1A2D3494395294CEBD48EEA14BC3106CA9C69D9F6485D6ABF1C2B1111A8BC602454685CA61AB4EE4DB9F413CAF8F0F204F04D40CD36FA5DAB629CB53876DB3E16372E626B6BC892C63C6B6C503C9D22EFE113927395206BDAA4B83D4FEF4FEB42FA7A71F7CE2197FE282A02D0FE50F96B1F917A67E50EB79CD3FFEF064542F7BEB51AB05B56AFD7AEA5F4164CC9BA37D8FDB35A3DEACF0CFB555161E7E41EB798160798BE9D01E3DE0C4288E0BAB19AE398E94353ADBE9A43524ACE35830B82FCFD4B1DC2800CA4C38A56B7CD28BC3E2F69A0AC4655CD79B5789A2B72EAF93B018D4D6F4C983D08932B22C85AF6FB07DF0A786D98820E1B06BC17F62D6E39739790A13049252F1B9102DC692CEB20C270FFE9B902AB7EC5A4EAAF47F7E2D31B2195F5F48AD18D099C33384141DA14E151BA57F6B1BB97901457202CDB83B5C713BD8A13F6E3E276C7D6C130AE287CA8931D9EECE06AB7CCA124D6D02D497D55EA9151A95E8A4DCCDA72D3F51A7DB3F2879918753683B01BA1B154DA83E6D84DDC9492F2DD8C128A30C75174ED1A6B8D93D08645270BDE247782E882418EA158B2A2153B2D8F75C09932F324EC199D26E9F3C4C4CECD807367E3981E137858B98BD1268D2C894541EC99BBBAD19A6856EA16A1E56B7B193BAF79AB89D4E76327405658C4ECB5A8626302B3A4618AEAC7E11A1199C4BB08C60AD78FEA4827B59CC883B2CA7038D7845106DE9174B2B8C17267273D23418AF560265000543ED9886884912B4160FBD372FCDF706EF642CF1829493884B6CFE946ECF6140106DCBE11B3746E33FBD4B5852B732230B9047004F4FAFA0D4BD7043C7D6595ACCD1B2771AAA76FE05A0C80B7B221DBEF79950FC69147816CAD0E52C05E72CECCF55FB4DABD81ECDB476417DBFDAF3B555CC90573CBED9474266C89FC55FF0BCC55602A51A1B5F91E425A1A58DCD4ABD09BBC63933FB4279B9E21298F9FE0CF1A93C4A19695240E8978D604047ABC7239F5053EA650D781307C50DEC4D5E2360ADEB9AA02C0F6FEC5784784A271169CE456E1C32BF984C3323656CCC588C97E0ECE5A40FC7B4DDBDDDB764EDC512DE63270F07891BD160F78B8ECD3A4D11EC4C68EA0A0FBD0F23AF9AB261A110F431F926C4995B05462E0DABF29D9660ABBC660C9A675628270CEA7EC5AE9B6F298B17B2392263700B8EAD9C845AD29CCF109A2ED66ED5BAF9C935754AAA1B84BE2B5339F9BF3CF5E80AF16967863FA8DCA64F5FE873DA4A6D33E39A592749B721FEC203C0CAC527CA96DE7A96CE9A540F5DA1902C97F960A05EBF0C32934F9B81244C945A60FD3F176DD8C261690D8EC98D19607129A50EDD51135FFBAEBC04A0961ACC5A32FD058FFDF2C6866BF90A3E177787E7061BD2011EC08EC118EF0451CAD010B53C68D0BDDC701D10920D697EA3439B1A0F96E6256B7712F59C746D1C74C20B17D461C3DF635EEC83E3B8E098034F119B9D9A79ADA735158EAC3F434E805444D5EA2EC85CC8ED8F5BCCAB7DBB6ECFC2E385781579AF1263D9FD32BEE32E01DB94703B5C756B894DEF19783B12BCE2A1A8D29D96F329CB0791D697BE7E0F05DD5C9DADA52E1B8C1E5F75A0FC90ED8C05BDFF86644B1EE61989CAAA271061D4222818C894AE9ECA2DA7326E5C24CA1EEEBE3720D2127BA997B0C572AE30615F8BC4278057F4762D46A39B934DDB2A0903FE1568C1BCC6C37E1F7C145EB7CB20A6A4B3466A7ABA58B48BE94F7E14CD20C87B2768358D06E3F607FE5E9DD1AAA8477975660F1E379B9EA26CC00CEA8CFD6420F2FDC7EE6393AA17CEF88645B821F8F42FC7DD97B0E16C04631F86ECF1CB76A6502FD1C13917CEB26A83596B117D5336387DDBEA56162E8A5BF2FA35E697245BC7210CEC13BFA694AE884582924168BF8EE2F61A734E37876F363225E5AE19B7C65CA6AFC31C8B37BCCB308A9C27F3E9902DE365E288E6CC46E329E78BE914B85EB980C0BAD932C164671ED395D5D8317C133E2E000A10E0D20D0F408019B33D9A87ED7725EA4C5ABAD67E0CAFBFF31DD236E59DEFAB7FF2CB40F479B56B261A32656F016DECA5302A336CA15D10E0AFCD168A4B922B79C11CB21881220374492D64DF21453B41346A85174A0A4A3C1E973845C856CA70D6D25BB854D0C6BD3C75CD73998C7F64E35A58DCF593C85C2440A6ABA4E470F87E6F9B4ABE127B30F8992D8AAD0BE38F008D9D937582EB3AAFC68F516D5AAF2503ACC96E59A151D2D4B072AB6B38C54928D6656441C709F1C1B770CE6EFCECE11F8B3602EAB63E0C629BBD8A79A96BE4CDB072780F3D287B091FC94FF2C0D347FE280BBAC308644BDB15A3C653863EDD945AF0AE725507507B82C283DC9909CCACBCF357D7A19703401B6E4474B94A6CBAE575B942501A281B8166FDC70E6B4B60C2F57A4D66FE1197D301D0E0C7BEC12CEDF9496BCA2183D04632711A79C8374B6DE35C2EECB0239391C2019C720894BC7A635DF18FCEEB9AAE16B3CE92717E2C56903D20D0712EF80131B8C48635163E97EFB1FABD1500D061C93AD935BE9A65A45A92E4A4E885268E712EFBE5337214701BAAD4C73E81E73BFF19AF131F0ABA105BAABE849F + +count = 85 +seed = 30F0E117513AAF27AB2516BCEADD1188B4BBDE76E57DFAF43CBF2D70723D941E8F875C5EBF02BD7D67AE81ABCC54440A +mlen = 2838 +msg = E43EEBE157E43D9F54130C668A153907D65BB19856A1B7C2FD5E2C770FD6BACB13BAEF951EB758485C128ECE4F3E9377A58A45EBA1C3A9CA5C94B50714088700D6FDA933ECE3A6989EE77A824A9E99674748A90B7F227B589250C9E156A8E50B74A7F49DE036FCED86CA0D4C02E217EEFCAEF7234F651CE4380B86389D7331C7657AC283F58C781F904405ACBB68661310EC6921C1FB7483E74116378086D4A0C9A52AF9847BB3CE0FE97F5A7C2CF588DB3B6FD725CA83391656CB38FCB6D79531E56F5D42FC0CC20D04AD7BBF57001BF2F8E6B335CC57CA2DB23C247EF9B75BBBA3159030975D65B9AA7C10E0FA4F615F77126D5271129D8839A3F8DA30C79174373C4BA643E4C4F0CB26BD5B8B9F7EA56DE459EDA15037D8772478FD9F7F7E06F3B422DF0B425DBF1E91D3893CE20F78CDF1910C5D4674EFADF122F41D6C7D6290DF59FA029BD82E792E758AD4388F9D352E9D2FBE3E58810C380D1CC5768865D24BDD92145DBD1EE0D4724C769EF5CEE12DB2AE2708B4C8C7865E70CA31386388D991D46C4DC4DAFC5CE66CB24D455BEE01488A7C764A308C7054572FCA0CC74A01A2B1F191C54146FB1AAF55B834F998B50909F3D003271E6504985DC836B5C44655B938769639799F2575BCFA92F13D32B283A5BDA11177CE1F66D6B30788415BEF598773E87B4C8C41F0CE6633B6C945A3B4C46B74F30945EFD99CF3709FDAFAEB4BD4C6BF605F89C7A9B4EEA1A6599F0A32CE3F2C58587EA8BB3FE6495D92F2FEEC52BEA3DE2047F5EEA7EA1453C762201FF1291AFA87923107F7FF586E00D07824EE021649ABD2D6E9EF11A1D31726EA9277134341EC57D790949590A963D25D6FADFA9CA21E43ACB7E5ED4CB6E8BB36377C2618997943CD100A927D395376871ACB9619BDE9B1FFD5E48E271952613875FA3ACD3E1F2E872F1D672AAE6E2A575A4FDC4FAE2DC6A7196E7EBA94AE5B49BE41E7295433ADF49A6D2D945F43699D444A726423CD9164B9E28B0AA4485B0C767A9398DF5DC5F23D27889C14B1ABE98880E7BD5DF9AB3D1321D5493A0A8B91EA4827627A9B59308CB0104CD8DA7D9DEF2D47B27074BA007401415E900DF03F251C8AA425F0FA59D74C41BA7A9288C8E280141CAAF6C6932DDC4184F81F5C33F0FDA005BF3FB6A0A9169A709875AE475302D57CE96D3DB332188202597FF29D1F9EBAD2B0FFA27C14CE9CCA58C923283BA10E9FA1689D6C2B8804225D706E09FF97AE9CEDC27D256E8736DAA54382040648F2F6BFBECD6C3A9BFAF5D1ED23EAD00EAB351F1E0BB4C719AE6A1F5D12E7F09ECEA62A2F554B18397FE1400DA1EB6694635D7C9C626E0FC82CF8DF6AA4CA88B69F78CD065C53F929BAA58507FD3E3D8124C4BF287D452AF47AF9F4D926DFDB529A8ABB8BB57C5C7611A97053A0CB0B01C754CB479C6CD3A3E867BAC33E45EA0BB6BF77E0B2EC2F136DAC0E259FA309FB5F6D8E7005E1696CE203C5D054E5927A87A1B4E81E73F22FAFE61D7D64CBFBE519D39E716BDCBB37657E71B9390FF04B3C01C6F6842684115CD7F5AAC208EEA48906890248E58D1615634CC1263CD3ADC14B67F1A1A8ED2626E7237AF5488F5D269973F11458E3E4FC2EE35A4BF49C2F5F2361939FA243FA8F33B54EEEBA9B0453701E367A7BF4D698C62DA64732652C68C20A956522826F8E29A764BA93DBC98FCC87E59A1423886694057E131333C5DCDFF3BE7A1F0D344A2DEBB90051721E0226178DEED353A136F69481F83651BE3281C562D6127914CD24C38FFB327786086B08EBE89D03A33BF7B5DCCF90DE9C4D907D308E08A616C5343C116A098786383009DC70787AAFB4529CD27CF85F946B8B238AD2F00DF109FC84CDB48BB52B73E1DE066636176E8C6C76216105486C553511DF1F0664EC1E04EE0B0BD74A08070207486B7F326C3EE73188AB5BB7F8F5643093916491D62F0DB18675BA4CE90B2AB310BBA4705B65A581FBC5E76842A99D4926AE5BF7B8EABCE5FA30CB98C1BCF0E0708DA970096234D47BFE23A4F9ADE29BE5A8B6BBB748EA1C13D00388AC90B65EE10BE6A9AC422EBDDAF5482422AECE19E702F6D26ED954D4E489CC48B2E39A6F168E98E11C1DFCB4A843354F1AFD447962E5090CCF51DDF6643CE0AFAFCF3E4363187E69C31AB796132EEB04F2D4976A576B9BC8D9B1D491B74613C1AF32E3D2DEF408ABEBCC27E4A915C983E10B6090FB2DE6FF9E60C96CF4F940B09AEC048E7A174711798FD76DB15DCAE0E570BE3AC147E2F8777A522555B0898BCD7B04ABBF060FA72B04604C9A583FEFD02B2AF9FA035F97DE4DAA4EE777F9D6985149DB6C2F0A33EE1A1436B38DFDFF87F831E83399C6A884273E612433EE3958F37C99A748DF151E3EA011F4DF5F0050597685E0230DA1B1C7095E1203EA7099BA5C43E58AB0EDA60AF65291C3CC9A07257D71CA6C9EAB93CEF41294853A67A5B11F9192C96A36C701F142DC36B046218BEBAD9904FB765550598F8E2F49F5F0AD2608117196751E7E4C5CC4C3EF425A921C1EE15F37A1F80DF1E24163CA145EDB0FC4D988B8C7167ACF9CD94F919AC96E5469859FDAEC54E1970007EB9699342A9AA044A8EE478A3ECF8B59B0109EA7640C218ECC1E8CBC5E2FB61A1748B7C038EFDADC2D096BC29D95B1BE770D097AFD8B0FE02173A1B3D7110F80D6C849F1AFD1B01A60894B16140F9B34D96071A753545159C4FFA4DBAA938BDEC287C6B83751C5E699724AB355D1FA0E081DB286EC83343877C520E856C4ADC65322AEB39CD87B7D8E4FF9222E085ED84C58B7FF513AD77F8A9EFF2760A03F69AE5DD14DD92DD3F2D3D98E97B1987086B3EEF2F2E822C851B7ADD83903786C050F30C4A4F4BA9361E49ACAD503E2A07EA119752E12D4FA09DC83F7A48EE3DCC1F09475960B6839CA736E498A128F78E58279063D839ABA88AC9E5BC24BC07BBD2DE1CF2E1CCC5987E63F83780D0ECF07EAE21C8C752529735B37C980EB320DC949468C69B17DA8AD612825A84D0529EB97FF8C4CD225FDFD1563BB6C5360ABDCB3339434A298DDCF5F36188F3AB501E505828E8D2FD6DDA062AD415C56414FD7557170F0F57BC5A401FA648699F3C7F7FD8F1F058849B817FADDDC24726DF851D3644414F55CADE30A5764914675D574EAD4D4DB8725866A6C51BF0EB23B12FBA1E101A6F3BDB98A2884D0F2B8DEB3F279E9C38EBD0209DD05C0FCC6EA715257355D0D6BE2C8BC7835187CDAEA43A8EF9C59E88AF6AA667A697A3DF8BDE250EAF4341A835B5EF93CFF97656133B49E13213949A3F368D985E0D6C793319F4284DFADA383137DC5B000B7FDD85F27865DC633562949BBE4FBFF75417AB109F03015BD0F67728969435EFAE791AC72C6AEF99A385A3E8B4C35F58380149C653FD78391A7C3B26A3550D37F9639164979288BEEE99E36AC6F44D0FCBAF0D210839D563A6249059A30CE6F047F5D541FC8A90A18610A8BEFB9493C5AC804D34D40881CA82E673788870705BCD585044B11F1D9BBD6B17D8B82B7CCC0554D1E3AA7F2762FE01385571C9FA7A103D07C1A209504876189DE4B3C5910C26C5F33EA725A7D57CC30A6EC8F3EECF2409F1234A094556C0F7941CFB30FE86F208FEB73C8E8EA8623640AFBDB1CC589768A714CF945731DEBF4519B70870FB3A50F1FB368ADA3FB217704A5D46D879CEFF9BB72667ACC673CB196AFAA0DB1160CC2CD7B260DEB791A94D0988ED54B7E45F33E7CDBA0FA105F3AF3CB1521EA382B1266DF304C900BF53E195CED03871A22C50DA166BB9441CEC83607083195D6CFA17297B678ABB5E03950160130B47E25713B0829F64D2552EFCF404F65798A86D5899B72150A91BA00F7DFBFFE82531497B60C31C28992377A2DFD5FAC8A9C16C835CE4DC24D0389277E6355C655C8A33C89BD48F55C13EDE24B9BB348DEC89612F0905719743C95C0E8B5653855676CE171F812ECA405B6F96F2212D1A5369A11379282AC0C5AC41D +pk = 164CA5EAD1412FD79E3167B7F7BFE18190C810316F37C3E75AF638A0240EE1B1E05C496203E777A0C192FC84FD5E442A975CEDA54F934C9CC595B2C18CE7DFD259F1DDAA8BFF4C51C8F32FBEB0CF117D243094F79FD11A0518BB7418EA252C1FA92CE21DBACF0D3D63AEE303B3B17342BDBEFFA836D64C439B28DF4FA882E4E5CB117D9F523C79292481FB079FCD427298A64D09C80A091EB965C7E4775426181A3270471C23BC042F0022B4A058573F2ACE90C2D09E4D55A30F5E91FF4099EF3CF53F344B8B8766EF4B2279113654E5E9D5D3E4AB4A7A223554F8A7207E77B89CB0CA1BE9B630D0040E89E25A269D008A291C4C6B6C200DC527E01722A8395856808982FBC54911153035C09B5E200401E7FF8BB99D3AEEE41A0FEA1C2E095E3673246FB5B3D41F1E9AA71A45B2EB8688E1F1041E8DAD8601B9C78F0BC04C5F3180297C03080B0A4FCC412448C86EB286C312F15D273CBDAB742076AA263136FDDBE58139F0867F3ABF62FFFD04EB883501648C241F6B207FE9D9FE3A09656EBB715F2A5874465DC35DAA4C293E9C53CF2A82098B580A367F8402FB8AA6C33E1EAE18A04FE6C35537C2C2881F34EF7587C30EC265FC1FBB057D43C851B384C5E30D226DFF54343A9D5E5C61DA4A1B64175BD92D0EFE7CAAD908777451B26380106D5503163D5221B7E6731667DA600DCC30E9468A0E33C8CBB0C3C7453893586E942C7C71F968040506DDAE1A48A4B27058C7AB63AC6573DF03BEC6B276FC6D26AB8E94AA2A070ED7308BB5CAFA874909CDF0FA996DAF85BD0CE5978BC2FE892F4A23CF92FAA06C6640D76638DD5B49159D33EA0B4DD433D2ABF55D82341702BF077F0E685337136F305BAA58C0D9671C0FAF4A5E0D34C1B56EEA6B7AF811BC5F92B4B3B688A9BF2372AE419E376F1B228C0BC8257CE2AB31E961D306C9D28297B2C3BD9E89B351F9596A3A87B1F26B875632CC4DB0B7E6608C6C66D1041812BF06B913BE35F76645DB9C5FAAB048859868381C59B5FFC0E1F1DE4A56F03DE1733EC543BFF12369534F9D7D0ED7CEBB7183DAB8BFAAF08D712A30FA1BA52AF3882B0EDFEAD9355E8B475AA3BA31D6E691812B2BADBFD9935B5EEB31C935237751545DF2F4E23CADE50EE22107B70A4DAB7C3A62217D9CAD9290569CAA1F1EA6BB463D233EAA8F27361230DE425BAF05DAF8BB3A2281FE8C7D93097E08CDEDAF03640DF621328F22FCE8446A6B7D082D3C6E66E67C4F30B540FEBC436DAE00FFF889B9A3871880062EAFBF06B4959B523ED74B568F0527EB89CA3839E28F3947A613DC3D54F2BC1A61273991EC0E6F9225F878C824A9F187AE764E34ED3B8DEDB7B1F3AF36D7FA27BECE6DDEA57A4722CC005668B631846161F736C89BD577E91B132B3C6DB8965E5A8DB4610446C1652468C38855869EDD6CDDBC13DBB4C0CD8B8213F88848F6DEDE44075ADB7E61C57C2F6A75362198E347CA0F1DD9A01DB8A5FBE0594C135644E00660E7A6B81F405E3A6E09DEE1FE9C11CBDB06E92A333416C73D8E03A74784B520F67E31C4F1133AD991702B6161F7242C138BFC1A621E9A206FC3F56EC31FB9C05D2A548D7AE8590DC1CC73E88C6FF53C52DB93317A4FE2E908AECB3A7A1FC487B643F7FC3C63495813D03595713B2F4F1618716F6079B0947E774F911BB24DA33098F2EFD5993103AC21769325AC92657AC234DC6408EED9D5AFDE65D6C410CD80A7D51B948AD985B8D57BE0A20B06D6D7F520C335ABF989E714948A189BAC9DE06B3C8EC9CCC030932B755331317A1EE3E092FECC17512263EC8D5C51F72BDB8A5CEFD9D5BD7463099C25937DDD1DBFE06E7C2C953881275A00C93DC11165CD0D89206B1C0B566B45CEF605107573D78B4035023A208C22A40F7795C465E244696789D96F75E1F34E2233A66CF2D70108C8546726AC71F5E00FEA3005EF9AC0F7BB4A8950C59FE214135F0BF482D1BFC81E6FA741A75648CB86D006B8A15834BF40DD553CC4252EB1B63E29716EF109EAFEB2F367690226680D6303D92077FBCB2387674425736A026CF28455B222C6F7EC56674C0012C53127B825B1C9010F473E72C18F9A95224AE909C2CD412805F1EDA0F1C22FA37CB77CF4CBBAD2EEA7648AD788747C9F0E1208244C13C3719BFCE5B49EF891800731DF68037B09E2AFE79483C856152F64EF81AE7F570AA983070147CBC6DD3252CA3EE0CAC8B78EE5C778F739B74DE3B2B01C71FA65607B1C3402996F62F4404D45B2CAE3AD88CE564D42C1054E7E7FB647A182678C869302CE6C5BAA06CD062ED8342EE1335896C799C4B55F7AC9C2F5F7381F2ECF9D3E5CF6C187EE8B09DE4B974CE6B79EFAA6C21F337CED15484A2BD13F7A2E98A128A246A3C41240E45E42BEB2850D8E7287537EB81253902E685DB4E1E8EFF801C7737188DD76E7EEB2E4A3BD2B16443F1FF23A4263C594CF4A402F288216DD95DBA4CC9823C9D05C5CA0450780DCEFD9AC9503D6D8A2A1C3F5814AFEBFFC5CFF491A955668C0957780A2A0BFC6EC905A9AD8817871C22D3C8EC9C22FB75F0D1F6F37D4BF1E519CC8D0AEA4ECF4ECF7FC396BCF8424B118A18416C62CF208B76BC7FAD6AAD608E1F3DCE943A7B4CE1E6D8E169F89F66E6BB4C932DB92DE3DF4305EAEA7CF72A20CEE9B171802EB1F5AA2CA9A71B7123C00E76C157DBC36077C0DC7396FF6A75AD3760F4D33FFDB7500DA9CAE34A322E455B55443C63C7AECC80F6DD2DDB08CCBE9D6 +sk = 164CA5EAD1412FD79E3167B7F7BFE18190C810316F37C3E75AF638A0240EE1B1BD900C3A49B078346175AD1A2BF23F8ECBF09E751664D0B1819F016DD2299DC9CB1754D5095F3472FE3A06B55BE997A462B1FBD1E8CF8B00F52622B538ABD4E128B0E8BE82616242289ECACF24E674BDA9C4C7264888C1114CBF830A4672DEBB158516441124545754827608122247034727681165162811178274815862430046805634746652071715320117385485260331848665410601752856660437523871370356766572845620584705570825727607577573540315504210328448846073114632243842672454845343424657840815700538171886225023788484218358867187361678762275763021671100634720607115271765847525332585374167348803857860215215187225877352480587148020327025164324138545656420423877780376612264667380618863026872821668748266747722005573175017823022712471001460014755732203852545712038601311055081082756542371422674642530446380135482772851114235578720343188284007513658878210426770435255010506016577026078331538822265738261753681437166831204470620171176325688831720512775247062561755384117402863757430582780120345082102655011541367044215268360664663417527750573276815744425685284378581641533253871702268677765085463245157336266500511103342701067110515311542233354022707607564004148070047052406600234528234422461171253200640868727782023044542265368261261100766463084584820786432185758232602600413382560683103415574523221430422001264443153174003226112104530665323623312614721741873162472757620516612150264336745652804376863115715582030226663150443766378255452804623785137720852748164504136582065423310687683165620554384547675082338734420826333606018851530155657740505664310852311001048810847342474475387745010355503850120127668300523582541306485888607283654817103800378540647132517145065300882447304407261832341612210514617078110285605408261102874516283143054250816727647757870418041307850004474826314832851212362187164736630286518631114166135862556846281751511422254718872575036208762268326330865415853631318177182143211607730783021250504585655105877243756120030155032821324603542005285700714737601681373023261003461380764680234053381058464478785311438586882282621382173200135036778634044561104136251034583256284156308562231111038636420243473106288217140607307473436205817238826603555104441742124120612560418678105686778580038270407600500058476447265171324421052352060616761751037188023055401677414632480511812082471380573360263013833850246033018307555220020337887138067851304807715438820004018073808776541116385147137280151272663823722503075130154072334347444588020068680001641121601846577808856020777604672861536801561361023437046802052347376887715616101371585157428787565350573121365624116530608740352200345474682036014184367858125256140184443756081064587221377021536631616535000046081778470626462413060583626486231724175186435271616315638425264532635033315747276180056872465410242727873324664383100550324603025638675333448772060041316178657601674582687230186530600227646055410767642448164445383447703148157331720570447078808217548551156704318400180658745813880011577756035402265166703641204875577646762808371510773643556558372363637406573583287828333447741531583844161352028043167648510704423767D7166A615617AA1DA19EF5FB571A2411E834A46E186ABA11E683C503BFAF224C69CECF51AD2D28DA674289E4E8761C1EF79EBFDA2E57C9F84C8FB97B8C710AA4D5F220F43CA88096FC7657681A99914E57739CBC9FAC33917466A9E7C01B356759B8F5CEEF1D6E914E8981BBD859FF1F5882571289AA34CD9EF0D4005AF999836B1ED902A3F501D66FC463EF4E8515A1006BD87D88E3154A64B77437AC534A0D6F84E4BADCC1838BEBC6258DF8411101546D77D47D0263FDADDC9737C113C0AED8A787011EBA205773DDE3B239728C3808DD2F4F8DA79DBC61903A8B1C0E9208B01E67B0F1F20B58114135251BF6C808E166DFF7B4DA2DF03247FB15620C23A04C21C4EACD0FF6269E11CB6A159CDC5CBB90D434120F98DDDF86B0AC392C77FE52EF46FCB4B333242FEFFF9FEBC997F90F72BE713BCF487C26351C7C5C1679E301734C6978E05DE087073D47E9B9C9CBB7A49605560897F62AEFC655B6E997CC5FCFED60B7C5AFE40E08A41A932C41D6551C28C207E0F798FCB8BC76179417FF24E38D765DC6106A6C78547A0C3E89DCFD249DBF687734BA361D01F28CBFFB0E4F0EC73D4E543F900633425B55B08DDE6D3B89CCA826624491F291AADA947FE719C830CA6EFA3F52F5CD387E99A2BEE115BC2F214CA3EDD3680FAAFE94542F819C346DDD6370AFBD089736ED8AA8492DE3E1BC8AEF79A06D8E3022B034C5904D1EE2D5A3B7860C4059D4C505EC836EDE5CD559D1C5E0DAE3296D9349303FED6A73490A8B4BA8716B9611C44C3C612035A14A14B206A419263B825A7BA9C6E34D99D6C7FAF43FF5E5CE260DD5AF1CBA6CFC5945D1D233F886FC58E53333B0BE531CDF072D06AB450F2A171AEADA215F7E0BF2A69728016532D1870B26F2561D0ED3A713E36833BD5634009731B1FE9B5910863986C2DBCA57AC5CE1185E49509B57B9DF372CC306964D736DEA92E977B4F0AD2FF2CF9F169281A774CEEBF9985B9EFDA767F6DDA9C371F80241AF7B841A93E9B9800FDF44D1FF8454A00A9DF563C5B08FB87104166A593C9CE11C78CCD7B8BA9B2D5895E5655BFB35D8834EC28E97FFA8210E37AB66F921725AB40C96C1DB01B2C164E651EFD4572B4AE36CFF1697D5ED236D9D2DE1E4E2AD7B9356EAEF35765250A2B8406DD97ECF92F4A6E25377545D70B1BC02A5618D7F7CF20A07F712C273CE99DCB9427D36FC98FD2FE1D25DC283A2253DD53F5578A878813061AFD6AB0C7D118540D1BB15A1C47D607C1419C56ABB75A839B6B0784F26A6DF486F30C05B0B28326152DD410C17FA64245469E116C91EF04DC34E68B2C48B251ECA546A1759323742B6FE77A7E41C793B36768755B77E14C88F1C2A930AA839E2D5FC21D449DFCC094A206931BDC64CBFAEA3668B8D294F1C7D223B023B64702E668F6F5BA6E2CA8DF4D7EE7F38FCB6EE2C41CD35DD858A3E7AE0FF4C33153D9AF47E0679E0695477105C0E76040A9E24B236A94A2E2CE7838AC4C1A35194C5B20785D5645061C9A081C6F3DA2A3973C4F1E3238592F443F38FD763863EC5A7C2C8E20BA70640777070F624B71BAB0C7181D456E024401F40F4289373F292ADC426FFD84DD13D1E0B5942A677F3946AD8E8A4B223961F9F2CAC93BDF81202C3AD9D1FAC62A260C91FA1B14287CDD78D25153BD4D0D903665D346F97389D613A7D393E14F15F506669A083A5CCA62E55F33E3AB7BCE58067D4AFF524D1B2CB7089F26CD121DE2AE046A559A5E1BEF62490360CE12F0E72461D26570818F1895BEECB3F0388DD421AB4BE453E83D54B1280157B7FC73B49A020E56DBFAC99B9B20EAF7C360C637555ABF0183F444F2688397646D8E9E6B25B6A8176DA659FD7123041A3A07CB1A9FC426CE8692EABE164E7A6EA8A692889BC752BF12CC5EDB3162B7132D668DEA0ACD13D7BB48EF3AA2C44F1FEDC2B934AD5F91C490D6BCB16C875DC34371039076E736214A6BE14B311CAA05895BC8EEC558D3228F72F96BFAE61F552328F5F1EB52AD1608D0C7049EEE5B0D241369D702EAA030DD468AFECEB6F1C8B84213F62671DD099F6CD2AB88851FBDFF802D16E9C6057439AA71969EE6AB9B519ECAD1B3115BD6CA24A0FC2D1204836B82956AC883CC92A743AFB62A0F9512A26A2771C1314D63EB0CD6AE0F229EE8C433C2DABD2C295D918331C79A36F6F36EB2A393B1AB939FAE0C4E8286D1C596E53E14424C209A8EBF36FB59EEB983338719F50E00C27A41183C690EBA62396D2BF0A276D21B9E19E48E0F6B339410885F5D3B950F6B43891A6740D629E4AA718D7A116B08BA09DBDC104511B8F2B866ADF2154408C9A765AFBF5BEDC934E89089A9199DFD854699B543D71888CC415BE25A0CD8FA6ADB75F51B8601B1F28773D56F2D85BDE75E32DFC2CBB747FE110D682848C4A21E07865EB4B318E18ACC909743105EF0BC439EBA8A38D808DC5A64282F730A707E42F2D3EA8994A0029AEDCF62EB57D80CF935B92BA2768A8A6AF0E1D82BB4E5391F9B6D01AFB12D84A01D467366E7D1C572617B903596F1D2C0FC4A51771D2CB05428543B0EC9861EB95E8AB547A1CF74A11973B825F3C88433B1DE6D03778D5D0CA9B0B3AF2B1EF7B1D225E45A0CEA108E38F0264A7C2E7264688CBA09B85BF8377FBC00499BF73BF68ECE122AE1D1A6359DCEA01204FD1A7DB0B7A74886E01CFF49F9DB72434637C8E2B1311D9DDFF6A40EDE8BA4534DD1667939C382CABA1BC69BBB93D4B33A93869703E7C652737B3140DCE9423275C5C4B653FE19710478CDFFC435A24AAB0A0D12416DCD9EACC7782524B5A9B0E9B9F9B5241AF6C0C3C03365458233CB2558F8DC18B4A5FCA54BE6F5FBD8301E1F86C097EC4B3359527C0EF7664338B4402325EA18BB22B9C7D74483E1D8EE0455EEB3E0C6C09F5C53236653789B4715B1946FAC241DC411B95250ED8D37B46FC9C9DF6A0458471E9636A39A86D7667E2E94AA9D8B26B539825ED1AEAD283725F89E399EDB6C23305DF2AEF4C54472A2BEB6DD4789AC83D9D382188E118C415FF24B307F8242A7AB7F3C9D1AA4F7E03F890C1844489C63AFD2D38F8D17F5EF8A5CD57E74596EA8495825CF3FA4207AAF3C37806ED487498875DCE2B7B7DB576B2D4F24016E236CDF855B2A16A438A32DF30C4D58BDE2AAD777A6B2A6D046876810A4352BBFB2305B00874E6A7584B3B67E1D659BB4B322796564CDE91EE93116CE10520058C0D6BA310C4842DA9DDE51BE0B7648238F62029EF9F926D99D3912883D26122A06DD34B59058BD2AC6C1D4B70DE6ECE40024684E90791C74D891DC92E0AB8488C3C66C2F0540656DF8707D156881037FAA97B2A6A5A86280D589C69594238784B7487B2A593C7DDCF4846134884C6FD6F890E57BA3AA5F5BCA59E2AC97880EC853B53F1DB8E965622A56A461BA188017E6BCC44F09B89929DA90B5338E6C4EC214398F4FD8CCA8F430C35AA8AE355540F230D2C0C2AB94361191DC7CB4060EC5483CB6F64B16A2482CD1BDBB5445 +smlen = 6147 +sm = 6CDA94E0F41FFCD9AA8E8748AB6EB1E3C7D99EC63494C26D1EA3749636078AA806D1C3F86ADDF3846B9323693E54CEC4A1A540206BC374EFE1B84AE5369D0E60C23C85F43454729DAEF86D9F64A978ABB01A1D4551DA83C48A2A86844C0D7995DF885DDC001E9F3677BBBF81D5748C692794F03DF4D59040D2E3A1D9B75356D959F9F5E6F1DE7A6E4F49935232C3581927EE870F49C63267B28E3F13962B0040B1BE93B847447F5537275C65918F5146357DE081ECF41EFE945C3C3FDCCF538F682A6E0C1076A63FFC31611C95BF1534F13444145F6F67A06F48C951768C6240B3D1353DC5AAA8CBDA8CCB7F7AC4F623E5983C7600AF099189D14F805496940DD75E7DBF1AFAE473A74D7943D31880092F8030C501D88F2DCB7406EE21E3B19B4F2D943C30B1D0E8782AFE4EA3C3028CD130FD2F276EAB6E529AFCA8C7DC257580BBAC5D6C2A8B20277FF4BE2BC55128414E83A310BF79FF0D43E18E41E056C37D1CA2952B6536376CD15C55BCF0E6E80653ED0993371A7D1C3908A163B3FC7E757B0FFC45E73FE30412837EEEBA3757FFADB4B3C225D57BCBE3FEA95BCC88DA59929912FC50E12C1C4FB0B95164EB10E8A64DEA21452FDCC3F8D60FC017CA3055924127EAB0729CC294F8B424927F3C7E7A2DDD334BB66E165E45EF574803E4F7F24C2C7670EB58A1A3D68C83723AA39CE741DBD3D4FB065C256578985DC3741CDB47AA532D461744F115DF1A818482A063E78B2294116642F6BABF6E9D119B9245E8072D7CFB089E17BD8D5F1036074C62E08BD780915FBC4AC45EADEB1BB64E909FEE2382DD23C383A595E2D6CB4F961C18A9748351DDDE869EEDD7C45126C54F8D6A4735F88DA437960FBA7725B8655A168C87F0A69583ED87588723DD9155FBC94F29CEC69ABB5D5034D16DA8CE6151B887AD6A36B8B46AEA63254FD7A7A969FE451A6238908611B7CF68F9A8B45AEF690A4D6917FC72FC1B45CB7BAC6391BFEAB16BF92830F33AA648F4FCA284B2E854939B4D3A248308387057E3C3271DB9145B005983C1B83E0CABE4B197B7A2F3A18A0E09DF5DE1B188782DF2808D13AFE531624E3BF64B5DD8AD707449AE864D3CBAECC475667CEBA1EFBB419442CC9EB17CCBB259DB2581DB2961EC2C5F6511E84431D111F5AC6F2CB8C0721DE81FD416A5639C8665E03C55978AE6CDA34DF3D7C9D80F1C7BC97F40999A7211252D1227ACED77A9E61DBC0A57EED8B32F3A5214B3A304A3D8CB3C741904D508FDD405EC8952F65D0F77922840032F58D69D19489344C0E31BF04EB1446F2EA24DF7206D48744188C63E5326CFB6B18020FE5EB68BA3CF1AA98750916063B6572DBC14C5C6D160CDB5C7E2D6D58E6D0568CF80777DF29F1968F8F5D00AFA0B07901C6DF23E3015F4F1496CC123A8164F307048011D7152D4A1C63378D5F99704AB3FEE6E08CA165E5B67B854C248A124F28EA2DB2E9C4473C7FBD62F773777458A36B8A60AE92F83B0556B500F1601ABC6840BA1C59E1B74353774ACF5C60D201654BEACDDC094310A344C24C3E3EEE15C27C1C1223167C9D13386CC73B311C378272367A3F003E35FD9FD12167911404AFB8DF9BD823CAF0EE98F5B39E3C453FBE8AC2C0E378FAA284E6A2A262B30029D76E68BC06C167547A82CB23CB5E9C6BB996B23604618DD64C6C47298B90B42DB76EB893FCC4DE930E06F9E1843483D861FD98E4039FDA154A2ADDBC131BE7491BF0D3CFB8029B4A05CD5B0CC83E503B53A2C6664275DB82C0A7D2D221E82538B2E47868ECDBD1DD13808495D7AC596436661525249F0340170109951A8DEB59DD84EFDD7AC31295C3436BB4C722DDF8A382B5DD6BA1D266067D80AD5EE7EA402A560204836CFA304201C115CCDF2733D6B833291AFDBFA060A22AD8ACE2DF279602357F601D09F0EC90B8C932AA6350194C56A7DA35E5978D79A76008CD30A77D5280A8517A5F9807AD353B6E62A649BF7672410D0B94461185BA9BBDBDCFDDA59557EA61A4415EA1F406B43732901487D4A7EB8CED63B8BCF50530415F49901E6E93F15B762CB92715DD373F6EE92CE870E50E6CF55EFABCD47AF02F1DB129AF01EB0D52DB6505048F704E027F00F73EF8D2F8149413B15D74D4A850605AABB04F34A050B91817D84B400DA815E03ACB08F30A2155432026FEDCB853B0792E947A0A6D8325E9BEFEA8880DD1E4B7D24BFC2F63717B9D37B29760DFCAB9239F6A9F293BE2EB951C1D0A706D5E3241E711166E4B74F0A01AF6266B323CBDEACA4FF5DD9B7C813D9904410909095F6D9A96120FF3A58E7A4B4AC173ABEE0849619B5E5E9AEFAC01F380087C58E6A3C2320F135884335DFEC2B25259FBB65CC58995BC89F4F49BB145C340DA0C254AA3729B91E8BFA8F45D88C6586059EDD05121B53071DE0397C74965C3B8C6B2A87A830F1393945426B45B4D4ADACB79CBD6617807DF1F1B17E50E787031F6D32D2517C46A252EED729EEB8D9C330F6A2AC68AA3F240EACC40F36BBEA1D8357DE60FD5F93077EF195D8E1B38AF1E416381104C47BF9B76746D0F07C4ECE4BD30F3D24FF15CE30124FFC6699E8D8ABFEE745B4076C04CF0D2B039C8A2EDEBF90A742950AFA56C0801C6BFEF85FCCD94138573064EAAFA770CA07A5B694D74536AD598B3A1AB4D27D59125EFC680D4C1153A417C5AC957E67AEECE506B0FB91919B7CFDADED50E2BE746E694A46D5E605F61EE3CCB18D4340D9DAAC9F7B729657FA9B9C8219935C69E8195D5E0D66807B5D226F798F983FF49E7A914BFDBE186A2BB730C6B19BF577583D042421A9AB652ABA81CDD2B643DF60728F429052447447678EA54745032C2A33B8B8068C8F95903F88E23894DA6D96832D3E798E34D4931FCE4AC60F5E6C936E19483604AE4C2646EA4F312D50E5217C1B71B574E75B629038C02371081D86038D5A2110819834FA64183206E9B062918411B0498B12EBF473338E59ADBD25775952C5A81069E5E6C9852FC814202BC8653A41464D1E6EC3D91CFAA63A3BC29F350DFAD93914AA1D0DAA63F62112C426D02DE46F444D7F8D24BE40BC1DB3788ABC096F745877854D08A15D90A0E7615A34C8C1077D3C15E1FC679534D0FDBAD3DA60AD6C6A7F757555587988ECEBADABDE27155F5AB50EBDEFB3D9ACA99571EA3A3700DD8AA97EFD2759E0CDC9BCED1BE88B187A2535C633E64084B5BFBDFCD17619BA24DFF0D4A7B3F53044EA7D968BC9B586BEF57B4F5F752E97433CC043024B72EF7141F77C05AD0DB10081962393CC0C2CBA594A0484BAE747282D0B9FA949E3717C1CC2F3AA37CCB38C132FDF874D75822305CEAD7DCB648A4AB49AE7DF040190B7C3CC4B9632B592B97250EDF2BCC4E2BF5817A218766095B060D2B7DC6027FE4FB2D1FA95FC597C87855CC1B358EC88D08819AA17E301C42928B2255FE38238167D3B7998F606410C167814F58D1578212CD0F1D8485915CF51E050F50C7E5A87CF3E0ECC60B9D59D2A6EBC0804A0C28565B2C0AE5DEF919CE246F71F69BB6135E97789F32A4F1526BCA4FEB9A6414B5E20DB815E26D46EE26F40C96EE5749A97A666C7B3B86617ADD4FB9F9BFBD805C1CA2A47A56EE9400B59EB31A716370CA957046799E8273C415F6F43C5719DC1AC6848D74E521F7EB07324885599461262D7E1D764482746FB8DB347B54CAD0DDDA45A8A53D7684E61B9078657D2E5788DA26E23E77DF879C66A82591B873C82B7A9F5F8EA0F14CFA66C9FB6FB389E34BD2B9CC10B18BF196A3B55D8C247399E4FDF183AF8898064004CB919E396916552C2CE7623C6C59223B0B7E4F50F5EC944A415B16EBF479E75C2C3251D4EA12BCFCA3143AE64E4782FBFA741DFA008FDE87041F222A861523A949C7AB0D420171F9062D9675BE6E5722AEB12BF3D6C4906F06EDFE205257748D686C677213A07BE38AF6B5C47A3123C619968A567924E103419D6444A27816C715EE80E6DD5698395CE84EAC37E8526A89A01D3490B41A9B617DFE4FDE6735694EBDA606F1522B72B5A473A6323B9942D2FACD65D23F355F5055D5B077D7C50B116831FCCED6EED42C21BCA3209F62012E1FC87B1D53AB5C77605E7A4377D3D2A05B136DB0097E5C431E18E3A87823594409816EF3A3745FA8B18923B261ADA7DBD27100DE1391D959792B52FD64418CEC584BE3562EBA07C05F735B42E5E1B81F399B65A52B2612FEBB592B5AEAFDF818A069DFFA79D277649E1E60F5A5BF8D697AA30D135CCC919A4FDDF20042FBDC8FD99456EE10044D15ED8DFFCB49A96996690441FD69C4C646FFA33D5D88565139642C55C832CDCE9889FC71A3BBDD00D874B70268013C7BC5906F91450F168A5D03E60DD60F59B3C11C41D00C151DA6EF5FD6DB5B0D4057C6CC7154B3D591B527106F81013077CBD9C321BF11306B5D77E7534C1E6C0CC3E3F5A782584AB8612CCCDDAAFB5742EF845CF4241B1E52C29F5170DC2D1BE01B8EF166EB9483B5BD2362968324D9A8E7DC3E8F94DAE05B2CF76CED8AF6A419EC07410192AB692EE5DB38B44813A176CADBEC44E7938379C8EA73536452D94958C8E20B625DE080D328CC5CAE62036373E94AEB9C0DEE21A465A74DA1A5A9CB2D1E1F643668AAAE436C0CB0000000000000000000000000000000000000711161D2225E43EEBE157E43D9F54130C668A153907D65BB19856A1B7C2FD5E2C770FD6BACB13BAEF951EB758485C128ECE4F3E9377A58A45EBA1C3A9CA5C94B50714088700D6FDA933ECE3A6989EE77A824A9E99674748A90B7F227B589250C9E156A8E50B74A7F49DE036FCED86CA0D4C02E217EEFCAEF7234F651CE4380B86389D7331C7657AC283F58C781F904405ACBB68661310EC6921C1FB7483E74116378086D4A0C9A52AF9847BB3CE0FE97F5A7C2CF588DB3B6FD725CA83391656CB38FCB6D79531E56F5D42FC0CC20D04AD7BBF57001BF2F8E6B335CC57CA2DB23C247EF9B75BBBA3159030975D65B9AA7C10E0FA4F615F77126D5271129D8839A3F8DA30C79174373C4BA643E4C4F0CB26BD5B8B9F7EA56DE459EDA15037D8772478FD9F7F7E06F3B422DF0B425DBF1E91D3893CE20F78CDF1910C5D4674EFADF122F41D6C7D6290DF59FA029BD82E792E758AD4388F9D352E9D2FBE3E58810C380D1CC5768865D24BDD92145DBD1EE0D4724C769EF5CEE12DB2AE2708B4C8C7865E70CA31386388D991D46C4DC4DAFC5CE66CB24D455BEE01488A7C764A308C7054572FCA0CC74A01A2B1F191C54146FB1AAF55B834F998B50909F3D003271E6504985DC836B5C44655B938769639799F2575BCFA92F13D32B283A5BDA11177CE1F66D6B30788415BEF598773E87B4C8C41F0CE6633B6C945A3B4C46B74F30945EFD99CF3709FDAFAEB4BD4C6BF605F89C7A9B4EEA1A6599F0A32CE3F2C58587EA8BB3FE6495D92F2FEEC52BEA3DE2047F5EEA7EA1453C762201FF1291AFA87923107F7FF586E00D07824EE021649ABD2D6E9EF11A1D31726EA9277134341EC57D790949590A963D25D6FADFA9CA21E43ACB7E5ED4CB6E8BB36377C2618997943CD100A927D395376871ACB9619BDE9B1FFD5E48E271952613875FA3ACD3E1F2E872F1D672AAE6E2A575A4FDC4FAE2DC6A7196E7EBA94AE5B49BE41E7295433ADF49A6D2D945F43699D444A726423CD9164B9E28B0AA4485B0C767A9398DF5DC5F23D27889C14B1ABE98880E7BD5DF9AB3D1321D5493A0A8B91EA4827627A9B59308CB0104CD8DA7D9DEF2D47B27074BA007401415E900DF03F251C8AA425F0FA59D74C41BA7A9288C8E280141CAAF6C6932DDC4184F81F5C33F0FDA005BF3FB6A0A9169A709875AE475302D57CE96D3DB332188202597FF29D1F9EBAD2B0FFA27C14CE9CCA58C923283BA10E9FA1689D6C2B8804225D706E09FF97AE9CEDC27D256E8736DAA54382040648F2F6BFBECD6C3A9BFAF5D1ED23EAD00EAB351F1E0BB4C719AE6A1F5D12E7F09ECEA62A2F554B18397FE1400DA1EB6694635D7C9C626E0FC82CF8DF6AA4CA88B69F78CD065C53F929BAA58507FD3E3D8124C4BF287D452AF47AF9F4D926DFDB529A8ABB8BB57C5C7611A97053A0CB0B01C754CB479C6CD3A3E867BAC33E45EA0BB6BF77E0B2EC2F136DAC0E259FA309FB5F6D8E7005E1696CE203C5D054E5927A87A1B4E81E73F22FAFE61D7D64CBFBE519D39E716BDCBB37657E71B9390FF04B3C01C6F6842684115CD7F5AAC208EEA48906890248E58D1615634CC1263CD3ADC14B67F1A1A8ED2626E7237AF5488F5D269973F11458E3E4FC2EE35A4BF49C2F5F2361939FA243FA8F33B54EEEBA9B0453701E367A7BF4D698C62DA64732652C68C20A956522826F8E29A764BA93DBC98FCC87E59A1423886694057E131333C5DCDFF3BE7A1F0D344A2DEBB90051721E0226178DEED353A136F69481F83651BE3281C562D6127914CD24C38FFB327786086B08EBE89D03A33BF7B5DCCF90DE9C4D907D308E08A616C5343C116A098786383009DC70787AAFB4529CD27CF85F946B8B238AD2F00DF109FC84CDB48BB52B73E1DE066636176E8C6C76216105486C553511DF1F0664EC1E04EE0B0BD74A08070207486B7F326C3EE73188AB5BB7F8F5643093916491D62F0DB18675BA4CE90B2AB310BBA4705B65A581FBC5E76842A99D4926AE5BF7B8EABCE5FA30CB98C1BCF0E0708DA970096234D47BFE23A4F9ADE29BE5A8B6BBB748EA1C13D00388AC90B65EE10BE6A9AC422EBDDAF5482422AECE19E702F6D26ED954D4E489CC48B2E39A6F168E98E11C1DFCB4A843354F1AFD447962E5090CCF51DDF6643CE0AFAFCF3E4363187E69C31AB796132EEB04F2D4976A576B9BC8D9B1D491B74613C1AF32E3D2DEF408ABEBCC27E4A915C983E10B6090FB2DE6FF9E60C96CF4F940B09AEC048E7A174711798FD76DB15DCAE0E570BE3AC147E2F8777A522555B0898BCD7B04ABBF060FA72B04604C9A583FEFD02B2AF9FA035F97DE4DAA4EE777F9D6985149DB6C2F0A33EE1A1436B38DFDFF87F831E83399C6A884273E612433EE3958F37C99A748DF151E3EA011F4DF5F0050597685E0230DA1B1C7095E1203EA7099BA5C43E58AB0EDA60AF65291C3CC9A07257D71CA6C9EAB93CEF41294853A67A5B11F9192C96A36C701F142DC36B046218BEBAD9904FB765550598F8E2F49F5F0AD2608117196751E7E4C5CC4C3EF425A921C1EE15F37A1F80DF1E24163CA145EDB0FC4D988B8C7167ACF9CD94F919AC96E5469859FDAEC54E1970007EB9699342A9AA044A8EE478A3ECF8B59B0109EA7640C218ECC1E8CBC5E2FB61A1748B7C038EFDADC2D096BC29D95B1BE770D097AFD8B0FE02173A1B3D7110F80D6C849F1AFD1B01A60894B16140F9B34D96071A753545159C4FFA4DBAA938BDEC287C6B83751C5E699724AB355D1FA0E081DB286EC83343877C520E856C4ADC65322AEB39CD87B7D8E4FF9222E085ED84C58B7FF513AD77F8A9EFF2760A03F69AE5DD14DD92DD3F2D3D98E97B1987086B3EEF2F2E822C851B7ADD83903786C050F30C4A4F4BA9361E49ACAD503E2A07EA119752E12D4FA09DC83F7A48EE3DCC1F09475960B6839CA736E498A128F78E58279063D839ABA88AC9E5BC24BC07BBD2DE1CF2E1CCC5987E63F83780D0ECF07EAE21C8C752529735B37C980EB320DC949468C69B17DA8AD612825A84D0529EB97FF8C4CD225FDFD1563BB6C5360ABDCB3339434A298DDCF5F36188F3AB501E505828E8D2FD6DDA062AD415C56414FD7557170F0F57BC5A401FA648699F3C7F7FD8F1F058849B817FADDDC24726DF851D3644414F55CADE30A5764914675D574EAD4D4DB8725866A6C51BF0EB23B12FBA1E101A6F3BDB98A2884D0F2B8DEB3F279E9C38EBD0209DD05C0FCC6EA715257355D0D6BE2C8BC7835187CDAEA43A8EF9C59E88AF6AA667A697A3DF8BDE250EAF4341A835B5EF93CFF97656133B49E13213949A3F368D985E0D6C793319F4284DFADA383137DC5B000B7FDD85F27865DC633562949BBE4FBFF75417AB109F03015BD0F67728969435EFAE791AC72C6AEF99A385A3E8B4C35F58380149C653FD78391A7C3B26A3550D37F9639164979288BEEE99E36AC6F44D0FCBAF0D210839D563A6249059A30CE6F047F5D541FC8A90A18610A8BEFB9493C5AC804D34D40881CA82E673788870705BCD585044B11F1D9BBD6B17D8B82B7CCC0554D1E3AA7F2762FE01385571C9FA7A103D07C1A209504876189DE4B3C5910C26C5F33EA725A7D57CC30A6EC8F3EECF2409F1234A094556C0F7941CFB30FE86F208FEB73C8E8EA8623640AFBDB1CC589768A714CF945731DEBF4519B70870FB3A50F1FB368ADA3FB217704A5D46D879CEFF9BB72667ACC673CB196AFAA0DB1160CC2CD7B260DEB791A94D0988ED54B7E45F33E7CDBA0FA105F3AF3CB1521EA382B1266DF304C900BF53E195CED03871A22C50DA166BB9441CEC83607083195D6CFA17297B678ABB5E03950160130B47E25713B0829F64D2552EFCF404F65798A86D5899B72150A91BA00F7DFBFFE82531497B60C31C28992377A2DFD5FAC8A9C16C835CE4DC24D0389277E6355C655C8A33C89BD48F55C13EDE24B9BB348DEC89612F0905719743C95C0E8B5653855676CE171F812ECA405B6F96F2212D1A5369A11379282AC0C5AC41D + +count = 86 +seed = 070FFB907EE8AB7152A9D380DEA2C4C4796780FCFD80906C5E489B917A45D5E7EDFE6F37C4420E5480E8BB599FE36451 +mlen = 2871 +msg = C07185E0343DF2A4201649AD5DE4CFFA20BAF5DD43F5E4A6C81CD5143FE72865A7C036A2DFD617D96626995C12EFAD019FF44E0EDD7028F29E3657EE3C0D02E9CE83EF0A648FD7CF183A7BF7C15095E0F9278B14FDF6C983CDCF2987DD0CC085400906DCD0D14ABA60124F4B7494ADBBAE3A8D6052122575F99792F7240EB17864DC6D231721140E43F1110E73EB2E3C05049783B33AAC4E4CA0A248775BAF81FDB03D114508928BEC3169A810296B5A4DAC27E7C7F8D01CF5943CF4D8CF6EE6F9042BB300E50EEA3224D35C9628E38C368EC3B42393FC820371DB6557216A2C2D5A230FE3A7C6BCBDD89A2BE5CDBE7F783BA379B6A4237DB051E6256DCE14DCF641190A956E8E85EB2638736B899ED045636DDB7A351F5A4F4108D9D6E0413F92B9D392495299128A5F4ACCE8C7747C675EFE05ED7182DB51C515B345029440AB61A904D2A390122680C951ED4575515144C5CA80D6F14D1CFDBB5373B78E09D04D0544151CFA1240790CD31165048D1484DC4D11D05057071DB3433DF071B367E00FD38C386DAB689E4DFF6FB421B2A95FF54DC29375C9D1C18A76C79ACAE3D3F35D4CFC385199A4CCAF6C9F0421BCF58D296EC7E0D1B95A6C4BCBAC1271F94E438360A71A6440275591E41389B30CAF2626A865B9E59552CB198A1D4453EBA6D0F6FC491A8A7783B4A8BAEB81E54F9189CE493EFC1C5D830A4F637F2BF43CD86B91637611415C95685FE79966174312FDFBF33A646625F97521B5CB1F008135B824F1D6D8373006C7158E62B1F794AE34548A0C6DAC8B60C559D81580AC0D84034A501516EE36CB4082732918365A5AB787FACE591AB02BE6957AE4BB96B58E2B173DA019D3E0CABEBEBA0AF775779F14BFBA8F595697731522DF3C80CBDEC16F6ACC32659CF5DAF193178307887EF1BE1B48B5806D0FA9868A7FB853708B26873857786B974709C687D6597BCF6C7E476C1E47CAFDBF30B6311ED434C0F998C4065399C59073C1F2BAB1D46104E74EA6C976D416E58BDFD24CCD957CB431870DE5DA8763992EF68BB18075926B0E4E826095EB3B8CAE086FB1759C94B873A1F4DF477E0EE9EED8DFD7C77508B3F0C67F69BE04355ABA9344960639F6DD6B3A956DCD66370338617A365579C5993986B4F748CB7C990344B209785E22A40FDCF8F83061D37C9F1351B4473D6C74ABE6B3EB2A7D62CA0F0C88A0AA8A46973F781DF0126E8D55D3E9C41C2E3884F84FB0A06C484CFA0C9A0DFB8CFD573749C711C7C236B0F2F144E1BA4DB2525C093DEED29434FE43CB3040C5A374CFEF33214FDD2D660398E91BF070A4F5F9746C2F08C41256FD5E955891146FFD38B155987E6A0FC47AC2A5950509B9E2C86B9DD9929378F43EF3935F1562672498C5640A22315BE15B001D4B01418DF8EB41DFE5C570E850582D8916C2E7FC2B728048E24BB9D1E8283615E039C16A2FC61011631BBD8F2BEB24ADF9552CF5797CE05D9D1A7E7F3F5455017B127D9BACD32BAD0CDBD3991BBCAEA5FC988EE7AEC0B1003732F25489EDB0A1F9897247CBC40E60F1DD276259CE19DECCB90067F7293A68B683FB5232ACD2217B8929859109D6852A43892098630A67D72B1CF4BD5D58E20C5C18B85D69DF74EE8CC69BAAC7DA48EB71A160F03B68C6BE87A4919736F14363F004EA3F41DD37FD8E621BF433BCA71E17565E060F3C0F889515D0A8C17FE0D6D734FF756256B0A62058B95422257780DE000557DF289F47910CC272A14BEC737C0715F204C49F03150082DC904A5D170F7383F04F1E355F50F80D5461CBA53490BB2E9484806D369D61FD00ED1EE5BE518D04A24503B1C4C08C7CA084902A3942C04143807203287A985EB3FCAE3C5309410CD9B9A548F54DED44321CE8C2A04679841DAEF7FBB6AA11091D240AFBB467D9969C31C1CBF6B24F8CBFA20CB4CFA404B1310400271664763E9C1CD1B6FE5FF2A0FAE22AB14EFC016CCBB19C5DD5D047750DB4ADDEA3E7A193128A5F4D7BB6358F21B39A44259695904DE3440BB28CF9466B562065C387189EAC2F7522C9385DC2A607F6F9335FF8ADD47C7BA932659AFF69B1F26EC8655BEE4F97FBC846E48111CBE25524873D1DB2F2282D0472A2AAA3CF491C26DDC5E1BE77866A3B692E417E6717A4F4454C56F97F063B9E598865B6F71136D65DDB0F3CDEC57DECD5A57366BA96E4315A88B4EA3479321468FFFF508D23B0701A62CE0CBC0FA37C91CFF5C5A0433FD61AE11A922575F5BAA714DE46A58D6EFC79BDB10C9AF7E9950A61D44B3E17E3B5298501146485B562B1570FF5798B47641D67091CDF90902B2D762E3EFE94C540DE4A28269CC416EDBDDD4D43AC2FA82D638DD9BF11F3BF22FD81CC4BD4759D7D864EEA0E8E8AB71796254B278CF9B650D1FEF38B8437362B2D69ED84C54498331C6899E20C596FEE7CAD9ED8D83D86774AFA6E56A4ED34B0B0842B21CCB67035406DEDFF0CECB0CD089929ED5FFA0CE210822444808BAD99AF603082BFE5C98EE4653349F8A43DB64CF90190C96B0446CC9CD23E0D75B47F54A731E8BCB0A4C67401DEE87876011033D2A526067FB73786FBC1CE696130FCE5D5379CDAC6788875D27C04783B1E2EF41063D57E3D6560D1FF48882C39131C95BAE5A9C9392DAB6CD17EEFBCF61C464A4DBC08447443CBBF3FA80481F3BC1A5806042C07F7A7AD435875DDB1001565EB6B7B872CC6C853F771C1DD5D9C16BC27ACEB3C7690125C1907C7CE904852108CAFE76351269A3D3EA8812FAE4FAE35F0DAEC8E8B186F760005524998BB5DE475E4DF85209DA915BDC972218AE7DB7E2EFA05A7D752AE61CF2F3DC26CA2D282C8E32B4838524BE460971E077348290FA0043FB7616D821A71DDA3A5FB76BFCE0DC84AAEA432DF32B05133A26B46165297EBC45024777A868B8B1B0DD6F97658BE799BD366CFDF99861E916F7CF06C034E4F79594F1BB6ECD9B7347911488928E1E473C4B8C73297F7ED845B9EC59020373EDA57A436C1C9D1459C6114BB6258543D8F4F97B10AAEF5A2E082EA173EE69702D83711FEE6AEE8F6B260D03AB74C3B5D8FDDB81B208E16458511270DD1DA295F25CDE7E44A8349B60BF0C59D4B425C1FBA60D2BCBA47B906D2830D8D5C091DBA756E61620D78B2DFF28407FDC9DA9113CBE82219BB2CC05E11C70D040BDE821AA17B3E981558961CA571E5D5041F7DE047A1727D9C904DEEBE561DC6DBD8876BC77C27322F512D6171BC03871EB0FDECE70F119BACB41D1852220CFF26110EB0EB78E39AA1B2A4C2E78679F53683520C5A57FEA71A8E96E0AED33118DC4BDD035FD88F535B011D9C7DEB6F406A072AE6C091016ED10A5A4EE9827882EE27C535262D1D745AA5231736F2DEEC8A6017BF0DA36B416C98AB71C6824A6EEFF3564665007C9E850FD02A1F5E201B534627B92D21A493DF293DB9F24DE70C7B49A6E07ACF2DB6C90B448681666DCDA318C08AAD08D3E257AF7E774C75DEBE3B3C07AF683735E87F205B0FDE07351849C5AFD07D5722C6AA17B6AC2CC3551C305E6AC31E3601A236961F6618CD3A0F7DCF6F65B8EC82E27E44C8518CDC16ECF79374F796A3DAABE2D5005B25576B35B021497C5A8F9B98DA68D80E56A1CC1044C04DFB11D36CB147EABFDAAFBA0A93FCED8675D7D6A9F999785C0E7346F4C68EB17C0A2409E2F5BD4AC5551FF66A9857C66F642F2A385131377B6372884C417E01BFBBE1CA748AC8969BF2C0BD8944767746D1D57D862795E8ECF9E8A5CA122D0259FFBA822588C5ECCD14CC6FF4B7354CB572F5BD695ED9D85DE131FDD97DD5D6CE7844DDF9F3D112028B5125AE7A77A4AEB2EBB554682A26F457C43FE96D67C90BE7E49FF443478E82D3A48680D737D1260B8210BBE962EFAE6505E496B1B6D4F1042A7B971605E2DC50BE3BDFECC3010B9F5618D3A1B2C1F48888B859E4D6B63CA9D29990B6D502FC22B738B203A83D597B48D73C41860E4E99C57181F5B02F108CA193451025F3B368CF2741244F42B27CB9E57260D2E127CA166B32E0B9C927B247B31619B1D4 +pk = 92D8682363C4BD6F42A49D69D2437251D8A26AF1225D8F3B32E7F8BFADB035BA633F898D7B50B6FD1D130C74CCBF1A094DD861D4C87F8C26B7FDE7627AC4158181886EF58A8EF95EED13DE335C1A3F4F4BB40C01ED76B6391374B279990A8C5A9A8E33005DB3DB93EDF1B344C0B9F28034E325E6BB983194BA2A4F5A7111D030A120801FE49BA8B7A90F1B00E07D77B2AF0D50BACEF98C1F394AC9F490486ADDC4EBCFE2E04F9517A2FC251F75E5CC4C9FA74D3FD88B9B9E0EF0F15611A00A081F0CE209AE09F834744AACF049D1F65EA8F3F4E29BD92CCCF22C70E5F26ED1617214A6D6B19CFCB285F232D495A4C007B2D2E69F96E5C620136078BBEA7E04487B559D32BC1E46CD62B4564577F3E4561E240E01A0C0870D13D98B8C302C5F06B7D3DCCA6604FAC8979C47CE30613E1458E874CDD47C0099B07F058CEC4F3241BF199AD9854CCED11D73E8823FD73AE8CC719709BCED786B006D38242DC85F8349B5BEC835C80372E79004B84919A6AAB26D8ECC8D837BE73F959097817FAFBC5F28E71C49A49C5344AC641E6B69A7E06EA03F1BDF2590346F565CBD142F54E90EAA1C036E68FADF72C9BBB88F476003200FCBA859C91002D80AA70AAD1AD628541A6A204B99DD701DB652E2C5BFB35D18E78E2C6C8856471CAABF901F9D3368CF707453A20F68455B8409B6CF88340AA4E4FB86750F575E03F894A4F02ACF399E22307F7CCE8EE1CA87D9CE3EAA33E6AAEDC7E1CC7590825BBDDAAF7414D0B5215D39FB552000A85E24A965B65A8F7C3A31EEECE1A830165DCEFB01882E5EE1B2F50871AD14F5B1B818F575F0D38CBD8C5CAE24350F9974745F1B5EFF9F6E21F93943D2E404966E44052141FBB29FF062FF47C6ABA72D90A65594F58ECDEE07A99AFDE8D73F6FB036EC4F63E15B86010B9EE5E86F64F8C8395F0A1E7E0FA7996C03CDDABF1419E3C71EB259D86C1977B9164A8CBA8F8DBC4C1DE6AA625641A100D6B0E25F2F4DD0F3FA87BC34946026C79644F93BD1E41D61408F4392D6CF9B1C02D3CB2A51153A6A7C80B1B7BAE6ABBA256B8936562D9279F6EB87A80296C82400BAB3455F51AC3B3826F99F05EC4B476F8BF849674C4C8DC2600FB3A9E9B4AE841024EB536A6DD4C2F35CCD444E79A0A057EEBCEB8481FAFA3BACA090147A7BD7731DB9667C17DBA3F5D00F0FD1EED7E8117A9EF908C8DA45C5B76919088158D0BF25DBB5DA5E1D50DA7578F8750ECDF1F38E5C154C8377AA6B4FB07F68F29DC7B61DC0A60609507C7C1A84592E59FF346A5678525A4049D561FCE185CD9DB6DD4515D862E82AE5DC39F4096C873961E136FED1A58ED195F7F44CF1F527C199D084385BFED25B9ABDDB034F93A59E60AA419F089812535190BDD06A28BDD399C05E0D0C72C1C5DE5A464ABAFD2CC373E9FD481C7557271473571AE8CDB14F96CB63D1A8EB4EC8A790B00758D926A5E8B7CFE3823DD0A33E63D60859824861E7EF627F0C0C31499F9EDEDE81C62BBAEEEC7458DD57B6C2A133238FC51189DF718DF6D65869D6EDE9F1B7EBCDDA024EF8D1B43A5DB565EAD05159CBBF131A12D9DC95048DFB6B663323FF74888D84A176BAC3241D09F4F09D7C73A4ABE53C7612C5845E1F344B3E12E65E9BA819CD8F791A46D1AE5C47C7E981E8A19A246099741102EA86FA7679625FD8FED08993C5E81EC44234CEDDA919E6193A681C632E584721E3B4C53341C5E0006E7D2278BF40F3BAE0BC4F9510DD345F35860B86C2A4615C9BB03460D7AD1D8B1020B9810B9832F22B8185F8A40F80612122B06F791E0DEAEBFB089F2F989437B0E30F73A48FA3C46F68FF508557ACF4DD949255570D7CF45411591B626330D20C1722789364AE1BC5C66D84F72962EA556DB3C50430D4083A9F6491BD93F550AE05834A080BB98F60B71CAF303C58B55C3F2BBBF64335B47B5033F492574D1F366D9431E7E94CEAB0E91AA89469777EDB34E16A1757B1FCD78EB890999D61AB91472EE473541FF8173D8ECF50B5A3149EADA939B0D7632D375EF1078DE16F395F2204E62A98CDABCBC6B6D16463F603B9BBA507CC9D5BF2ADAF4AA2675E47A7AF36B11F57E8CC3C1710370C1EFC02AE20C35E6DE92D1CB1441AEBF4C948A42E2F9BB15B2BE520E9EC66B6AE0CB1455AF0AD9ABB6EA361A6DCCC43E7C08C0C99FC0F9C102928BE8A80EA74D04EAE7D274C901FB747608201765E223051F8A874BE18B1268EF82F884C3DDF1EBB9E9C75605B6ED554A1DE63DA47C175F487B8E3C90FB6DD5AD0C2A9C0F1B064F96357E8106E1666C7BB21617F509C94A8676348ED8CBA2389903327EDC07D1B2181B1E278349EB05D2D317656CF1C1588C51073470B8722B78A0FB272E0454992F258CDAB4C4B0E553B2C6532670024FC4BEA8DED556C9136FB9D66342F7143E4A7265F382F68DC92A38DFD00BB89645000CF94A0281F0631ACC72328D16BF06B5FC223DB58BE92A9D365456BEE3EA75E4BD460173AD9C78A7D549A87E3EB1A4206ADE0C4280D6E240CBC5151FF5ECFE717041003E4DB0C44BB09E701CB9D406EE6D823904186962B7DD1FD8BE81AFA42F31AC5A2A6D1B1429DF0BF1713B7C66278B645E7088B6F278070BB8827763EAC10C8BEA7B68E7685ACF760E5B2E36E6DBC05BC0B18C7C80EFD7AAEAD94AF6D9E522933D959C310F8DDF37A5A79ECBE6F0A02554BF4D1EFDF0BDAC2536768EC27BD85BDD492FE90527AC62B407F5144C393A196C0C12BB443 +sk = 92D8682363C4BD6F42A49D69D2437251D8A26AF1225D8F3B32E7F8BFADB035BAEC80A9F22CC597B5939DA33D7D6D36D710FD65401F6E92A34F1CAA7E59CFE11D9010283FD161CD1EF81573752A253F3E3D08EB520E778B7738FEB1883DE54A0E3C7D7A9FAC48E94BF2887945FCE50BB04E03682B2C09BD42A89812339BF7C33733601280147032540742027767366126370207378403328267460782586561874247785602366660272184435024441311105154641751141578021363816403376768114128705864051268157647572070856228003301755627085026085057871078328206603086828680188057362127226083880413803640830805214161307761834803131604047202425737775683480013035220282875850012137776041810715666230210356185573812832377423116815404851402580316406722503231644174745650845051385816075584040284575103024013785017561233565240345282656454070040088485686401755432323864683566282581024647360203668112275843671816716803371232583881381343270227755480183368325554887606755074168033585325230745225080637876214241640207061660356083238284281372723520535061681475142362380017142013515180886704448460301441223202477255387683872561670403572465862423748404003122803381627161212788788205832886521433851202581542117367484353764764268208326446502572071874467338368166365027846521300102130807125850500587821514078583437224167458114203523838765457301632324615786400572515674211072545076324072182764058216874448476782028314552217427183884070488156528123228661678358402371188721447885822407424163156363286218382314504111602217558020015284641164363454382465874213112143228244618631035886756638018716326640555367143303206745217746566677176503643100600737274844134711716112048338383114010765036662443526232656275034403780138745120650140456622267875211485478055276576278248348785176312183236107078785018027013423830875244124104765388230058746304371201408533121678774563522558154102646465274043648241787162278588535158427250001224185435780346832748464535557227203706613728662861666444026347581163623270120883041113627455840666574311001333232165103205206063765840805876604144788650584105865558466662105816317725164728516017521124736674106011607860046564488445058138837062620030247755515524766626142010625507475558674636526323305131870708283372852424714274468565573738565823820743568002775237513510185681575275866050783803582770540221804421777442436880536287158161736205102756548534414108865705456614788720682271532044877527625822615037173452107530072683337772758057224811752306284858468611257223805016047223776234546821858688468180331600536302701043626243751345426745383325653084353045082464514542273843701573570482405023582011736402368228868464828616851548782025380360708232537368285546036421376441040720656350240806855308111745512025038660811638177663855114745427440216453457618614652480531568221631722727152114784575715223753522288312570877308350320262635688656244187704085516212888057346463037280558547716675127876818145378044426683044503051430528715574411622453648176368023667880381056042671555630734415001740514450508712305144021388127206038144684667082854142702084207627277154463333834010275158851446388402150028530055577385818250138246710271454503216512852853652663284586330824510638788712830313AA603C8EA7F0BE866C6093BDE391934AEF217DCF7353EC582685FE7CF25EA03DBC6A5906A13A8E87D3E605FB3C8B020EB89313EC25954F23B162A160E70935F0B631782E61148FDE36117B5989E221E7C3B5495BA8FABC13DB197F930F10F78C5428430976FB8B40E649C905BD4138507B6008FFBBDEB81B5393988BE099DDD216956E2D990083B08FD6AED837AD4BD5838EED06C5EF78C23F126DE13AADA1695040F1A4459A823188FB71C20EA68CD648C04B8FB24F5410FEDC80D38D3111A658C24293C3B8C895657EA0522CF165D48F5715C259EA23EB0360A33D0919B9385D538F719ECF89B0AFE37553EBB34AE3D7529106D8BA4D4FD5AFBA56695FA4284CFB9D76A66FD3A25F32DD6C752E38D0862CCCFC09899F743D7CE173FB4C99E15ED9E06046C1900BD62AED0766FBDE3D60FE4D9886D72959E5193960B790D99BEB66CD9BA2BBF39FC73F46F048D3CD99F8DA7703987DE9E883A40EBEADA0D61486B20AABD34082CC881BEFD11531871A2912D5B49CBAC834D36CB5722C1B46A5E311652F3113463C7F95830B234C022645BAAEAE26E98AB58B623FB72A837BE3689D1E50EE6B17965B08ECE9861E687CE4188065AC274E5B7E240C12AB5169ACB895FB82E5D62D38F3864E326BA673463D3724EA0A76D50DA9CB739974DAFF2D91A8766CD1CC91C1C267F3927AFDAEF7B80FE3EEBE9E96F2DA8F28803CD992CABB8D66B185A2148751C1AC7093FA32AE33A5CCE75E7B976EA5D3988587A7BBF16347549840694257F1985241D08215A410F7BA492A94FE62856DB426059008EA76570B4500D86B26C6CE81EEB62C3BA7249FB3592BC51760FD97C67E4866779944BCF0D5965CFA7728B5FCB9ED88576C3C199AD3C1503DE52747485CAFFFF049502E1178CDE65273E81202CFBDE031AAEC362C0E79C2C417E017B256F68BBFAF27FE51CB040F8E58E9050DF24F423380CDACCF6EF68AC3539327C60152B09B028591347E994562E9280A2FA4524ACB5495D41A20D53069F6A4E4A8753A57800555358AA4A79F7C88B952BB03947E7715FEEFCFDD61B626F27143383067AF907E479D36F1348F285C03D1414FCD9A425584B560DE36CB238B0D524821BCB403828832DB6514AA8776149E942AB70411F48C9DA47351FD4E986FD8B29ED5E348F37814E1E0D3D62CBE065EA1E1098F5E6A6B5DD1A36017EE36F259FE3A256F1A0946D45972D6EA1C590565A30FF3B516CBFFD6FBA231F6595DA394C09581B01762F712A7E289785F81A61D7BA5D41FB56DE4C2D1283A353E6238CF76BDB78F37F0AE729176B2C90E19BA98E5DF2134B45F1EED0F70F107D2FF445FB90A3CF586DC30493B202522D612F643E7AF9258C5BE00E9C59FCE0ADFE47BE55864DBBE708C09FA24A6663D577EBC8AF30884C374C8320C92CD644AD01FDA1530642455D549D385A926749B2DA1E4EBC9924743AD5C9FE9A70FECC9025290B9F0EFB159AAA6C8DAA2BB0FA424EFDC7C33FF536B1DA2DE73991AC16A712E507FA8B3D750E80D9A7CB08EF36360E48D7322004CE8B10B132308CA80FC223B4CDC2B1CE64673BCC0202F73C77662306C135CE716C57BDD479F9C08AD374E70D3B3932856982454E6CFE3541FE729518934351F3EC461B81F665EFC428FFD94EDD92F02585D184FFD74C1B612F15982B974AC41DBF57C1F1954127177277CAC7EDBCE2231119B6120010A3358F0F2C9C25E847133AB351B698D1923F5CC09825E3401B119A3A08D5595DCC3F27846840FFACD1EDD1CBAD6955DB879D671A5DCFC2E654A5FAF52E4901DF16C9621229E4639614441635C714B1ED2AF938472984FA232D7C4ECEEE0BE532BD965610A51856CC339427A5B10EA8BA5A55117F2B98BE288861472FF0AA9EAF3A49FC2C89F1DDF07A08857177F95F056417DBB2698D99593D01C7BF5AF0F7A12EEE172588E2F941B521D3F0C486115E57CE83F8238842E99C791DC37EF0128CCF22C1807259F24AB4E78AD458B56D80F27F60412DAABB383AC42C9DADA2E4952B048CDCBFDD5D853C37EE9E37D2924EE3D3F885FF7451D4FC02D5FF8BD27378325A1539A0192C9F7ACBA8DF524AF25727353EA272958C64D2C526EAC61D5B6709BB1CFBE9049BF830F025F93905384C2CA3A34243DB45B7230ED357F681B22C718DBE9E7EAD5F837BE492DDBE9A76F024D7E38557F6F703D1A1C7D676C840C1F655996121F315D8F987C3036679315C7D6DE78468B1191FF185C87FEF1DA621830C3B58948E0E569C75E1F7F4929BA2A7739CD6CBDF6D83C4FC80A64E686051EB20F7481023BF42885C938217315ED7AA08E98727C32CDF82F7BF3BAD76644A2EAD27E80E0D93294998ECB1C0322C0E9370F6E8ED9E4763374538E2DBC002C8B4B84DFCE35155902545E39058BBD38DFED491A5CF69F4777AFBB2C40389BBC4171C4082792D86820C26103748E4313DD34406B126B8E2E170C4625E85AE4ED709B01ABD7A8CC77166DFB1BA445CE796033BC4F27DA86078C269B2D69909B920220661ABEA5E0EF7CA368F9717D89A4038FE0E02C2072BCBE3A904B0C44ACA49A7A6B639C21318CCE22AF47CF355135B7ACA50B2CB8535F5B199E32B05DD59C5BBE8D59C809B4B3F0DFD52A5A2FF0C0B9125298D5516E71FE9E7230FB75A399D70F6A2B37971AEF1DB1BF086CC5CEC935757FCFD268C5C9EC8555FD769EBC0B83479A6C874B0D3C9FAE8BFA8007A131E13B9BD25C189C2AB9605D08AFEDD6299BDFB9B7554C0B31030C148AC080F9EE49035ACB1197542E8D062E5E758181789B6F2795B438FAB75BA8AAB65ABB5CCF589657841E0ADC297703E2C4678242FFB0CDF1A664D6516A7D4A518BE116DA4335EAF06AD46F3D6F41EA6A9AC596EE70365AA1EDC7F6FB8E8E35953C445BE0D9691CFA1C0A3F37B93539F1FE341AC24022CD0CB2EB8AE33E63FDE8FB86256D3FA9B1D130BEEA7BB282C011C14191C6E82F2EA112F273920E2ABAA0C8798E31CE37C4FFA68FE22D3FFCC189200FD3F9625DCF2333319DA17325628E18F34A791769CFC01B3E62C6DD34278426E2E51544E78A46ADFFEE5F9474A7B68C8EEB338681D03AEE9CA92DB27CAC346C5A9749FFFCC70E6845B4A451F52805FC21EDBBAEB89B59E4D0C3432C3BBDD8F05CF815A538F0624DB2005785F824EFEEFD7B18EBDD5E29024704E9CD7AD6240820803445D444CAE3ACC99AF9D8E6BF3CCCC1160864594204491DCC03AEAB39F3CB0061199E7CA74E165A67DD274A0DEC18137EE926EDE087879F0898089CD4C8200C65C1B1A91E4E894AC9667D570B0813A10728A505C11C294AF74C14F233CC153201E6A57430898774B09BD88FD4478DB74639838F354E5B2EB3209C296EC93AE59EA0F1F190730D63D7025292D18181A9A18BBBB232E092373F3C635084FE359D978687F9F554584E33D356C0E12EC59FB5D1BC0A1F8308D004BB241D5BEFF54DC73670FB0339BE341B395C22FC76A7E9DB64ADEC8D444AA6DF13EB7D767B7081 +smlen = 6180 +sm = 0DD51096FC26B81E35F34D5153998E9CDB1A4C398ECA4B5CE51F731CE64B2B876F476DFD1AE164BFB8CA785A60891FA17B79BDD4EAEDA148D98F2A4B1339117669DC11810D289B0BEC6E5C92D9FA8A1432E03F515DB3EAD0799DF1599C8C39442B3BCE17098DCE0B46CC52D6DA621D9058C0857FA7363AB6CEEEA13D57C4B07C9C92C77740921A0AAF013E111D7D90AB2552B6ACD7E7C484791E4E28BE5FEB300A744018E9CB2705EC9F0FADF7505D2B4034C94E8DD21E2CDBDE27B8BAC281D0F9E145C0C5C0E52641F897024A17F2CA056F14FE967AC2439AA38CEBDA2323F3F8C040BC70ED9BF7A407ED6A1D8107DEC9978234880AE8F74E52E1D15FA8B83A8DE746D83A1C191A9640F1FC22A0E8A099A2D3E482E305C692198B19A0C779EEC6079FE2A5E29E2FEA89FB4A1256EF22C121EDB8CA1A99A7F1D851D4D26C860A49685B1B21810442521E5A7AA2ADD54997834CABADA7305E569DFF82A2AA26F3221B9823759C7A1C438AB8682D2227E6466D8A34FFB79BBB1438CD507A305D7010D3E978E55E3CAC2551815DBD1A5FB2DDAFB3EED0F5A03A51AB10B1E78284E592AA254BFE879FC4F18C38CAA641464D0075373BAB751A2AE0D82AD00C4A6AFA59E3359D4CD84ED21A29A128847FBCDD74B359CFF02F407819615884FFF181150A6D599ED6339C381FF5DC639DF9D6269BCAB4112FCA8248DD9D50E02851F8CF727B72FEE18F4E3EB495C1C52A8C8F6F81731279CE1EF89A2823F82AA72C334E6B52F7551715FA859F9244ECDC16844CCAE52B0247ACF90D8C0E56C990E99179E0B854B2769FDDDFB7B758FA6DB850C12994C22FB30754ABC4C4B5043EB59B8BCFEEEE9D31A912ED3579E1BA1795A78230B4E99057D1DC8F86604904A3ED715A3F2C5CEB98FB3C02F9A1E7F67E4710CDE28AFD0F12AD7DE8456E9548E697975EC0E0480FA9A01BDA910AAD4F580668EE38B42B4AEAB01883334FB8C64815FA60797182209DE0FC98BFC10762A02119D0CDC85B70EC7A141651B00C1A759B8C9C9FCEB396CA430CA4657CEC49C0A0474ED4081C24F6919185E84B185F56E0555E03D5A43624464157C49CC39BAF194B29387A0E58F0D48B03DC53C99EF9571001D25164060B2233E6ADEC4897567AC09C7B3036B671FBB04E758445011A92B9E78074D168403007D7AD620C714913AD5C519DA94669620E6DF2942D89BCAE4DE9E988323152C814D7F95BC147D42CB1779221573AA244BE23BA3F8C15E5F14DC0844BB968DF04DED21BCEC91F3F157A0D457394F2B9E65A8E79E3E55A23CC3D7A182BE115440B9988954776CCB3C16D8A0CB098EFD668597BEFC19D2D678EA933CDC528BDD4EE10D2D607BC160BA8A1B3FD33BE978E00AC9BE552FA54B380DF8875A79FF006635133F2AAF9CA146068E51A47BAA9DC6459402E33C23D15BD3BC1BD02BA6A9784A8B97E3748CEFFAF7F1DAF1550FDCD1964EE7A0C4D483D2AB206543D6D5E09352565B660633FB74A7EACC9EE49A78F075EA629CBB54F4189F212036BD572DC4924D45554466D50984B10711D85B672E6951C404DC2F7854BAD29B04E3630DD5E4FA231D96D440CC550305662536FC1F18966BDF918EB2614074EE95D99686465C274470AF7DECE9B0C51FF35236F4978DE513A0FE487872B89C06B16D86EB005119FB5BD8616BFFFC0C777E7E81ED460BD3D7BDD235E4C7783AAB82C1F34809765D9264E2E28DC2E9FD31B2CDF20D28EF983C7DA2248FE0CEFEC68CBF605B52DFF03D9EB9C23D35019BB1BB0CB6CF16347B1B4FF80D2677A46ADD8AC7FFAD0F9DED59F96FA0201B8A0DDF193A21ED2B35A7248C216EA5616AB49BB65A09BF46D52B2248F3AB2392FA5FF6D9F3E05D523EB14810698389C1E9F03FE87BD6463B7E19E5A61A6281ED52608544BE092C81B07B3912EFF0A8253BEBF6DA18556880CAE839775F874A17D8ADE2EACE845B9B482EA60874F3C3078735991348F3248D960774C133F1D84C2F604FAB698607209B99E235890158B934AE16D1A74BD2C59EC15555817722BA6A23EAD959659812606BCCB3FB2833189EAFC119B04E65C0F18C036C84427DDF2A50A469FCF51D83FBE7E873FE130AB7AC988A00605E6656A261C586464CF03A96A6DF60AF2C60847F7D3566AD99E90325DBF6F4D804A59428E1981C511557C62D3D5C5841C3677B57799844DA7CC369F3D00222B895A864878E568D76ADB3E06072BCF8BD00C9CDA7D426EB9118009AFF8008ADFEEC5BD5B4DCBFCD05859D70C7C401EF25A5FB754F1FE2264587CCB81B1D11170726AEA0292CAB9F770926F7E975B36113911744FDE93B794003D0F0A92D783DBD35A2101CDECAA343FE053D5B655A76EF2AE6542EBEF965F9904A8A4C43E7DAB38EE77561203AEFA99409DDDD9A185D145AD5C55E91C0B46FB5325F2ED7F73C3480A251BA81ED4AE0B18DA68E49B51E7C050FEEE3AE11BC827A1E765F0FE409AF68C4955AD3B3E4EC71D9BE238C2BA6FCB3AD395474023F9B515843CAAC9B7C97CC2D3705BF278FF451EA1A2481C044FC22AC41231C82A11DD037FF6854949826C11794D1F70514C6788898B2835D16B7987AC05A6F80FAE53035A32FFD26C4B6E39297AF08CFD431CBB567B16E5CBE6763255436AED4BBE3A9949258D406A9B163F1F58CDD522A86525782DDA1CF94EA4033D251E7B33CF05AAFB5B9851F1374F98AD0B3CCBE474FFFEA2431A3997E8B3EE2F1579B3562F894AAB766CF1F0FE4AF692ED691B7A7D2A4CCB0A4140E214956A936F775C783B7D481B91C5857F6AE6E18DC4E671C97E3E58513D0D5B013FFE9FCEFDDF0ED2F508E19E3C2C120318F6F027EF21FAC93C07B6196F362C5B606D137FA0A10E1C2B793509E8A4EDF7600B666AF4A3EBD029FE72DCE015FB9C69653AF742B41B0A38133EEFF3E8146E4676DAFC03DE1ECFE226E456907ADF06F0C9048BEACE70695EB906E495485000C61F386CCCA9C8177A10B3CCB776E92D4F9C84FFF7CA991F53E56814B7B3FEC03522EA12360772F5D8A26F4A1D7AFA5ED7D5E5A4C2D2CD843BC74C36D8B219236DEC656AB55A9D2C52A1BD7437217CFE9D2C603194FA5F09E2E5DCDCD1927F53CF13877876E496BDA3D162AAD5B749465D9069ABDAF524611E88B784680A3421C83E7152905BED96999A33E8658EA08AD2804187A84B930154008039EA3296EF5475051C7B0702C5145E6F7A2A19EA037801B35C4F4949FE57E16FAA744A019CEA0641C953D0065323A9952D33DFC36D04AF51FC5114D2278C7A20281DC94400330D865DD97FFA086371727F805CA83AD8C15C3DC0296C9DC2DFE6F3CFFD0B8F444A16F601AF6137D0917B6611E0367FFE9F2494D4FFC2961691E953FBC6B49F5163A1C9CDAA2F7B92D1A37AC0E4BC5FC1147F697DE982BFDEE3A7A0FBF0F52E4519AEE0F7B4469A460696EB2E750338AECB27E98AAB776E6D0492893C9745E9175D74532CA3001009933EE422A7F1B229251B28C1C635F92F03ECCE5F8D916EFAF3E1D916AFAFA4DA8C90D10E5179D688DD3B732AAD662F96B86B917377DDE9F12B164E39245A8792909A3959EE86B8A74A2EA2DF2C8F914BE014C2031E824A56D4622249D4ED59BCD31052040C93CDB9FFAC89F042F79A21AB16F848A547EE19DB696E4AC92C5CB1D0E389A4E450A6A394988204DC4BC1CDF0F9191729E21AE12F3803C47552A70F04AF4436AFACACCEADB3978816236B2658DBDDD83E0D8DD3F48D243EB7255C13B0E80EBA710D12A001748A01DF3674248996AA7DFA3FE86AB4D8651115C3366CC12F66A50B3CD87DC2A69554EAFE0CCB859C98E6DC6C790BCB100912E043D50E0E0138B9115F0F7BDCF4CA4153226FBFCF5CCF9BBF22178ED04A783D510870E463F893178CEA568B1E8AEAD78284658D3306D4933CE471E991F2E81B93854E02FD9DF5E003BFC92CF5F259B4E3F91F2B2B89B423B62C097CBFFDF73EB6AB1A0F23F966CCCF8EEEFCCBF39F7E4DA1A849623CF6B2AF1CC44312CAA1F51BE7FF66AE6CC7B683286C478293388C6AF9A2EED0D659F9E0A4DC12FC8F69192C8487A66ADE62DA1C7B6225DF97047CD0077042AFF4BB5F3CA5C5F6D0DFBD61756BA484755761259FED96583231036929A35266CD5FBB6A9421077AB516858705DBF056A2A7D99B36BC74A4538DC129604FFADD190CF307350FD8F87A92582AEB360CC90905AB2EEB218ACA4FDD228A44B187A2CCAE3E6A9E98C5C13F93BB28F890ECC7BCE7D2DF1376D65EF7A9D472D2B1D239F0D34AC3ABD99107D8D58444054EE5414FAD6E66CA19FFCF4D798C9CF7BE7A2AAC2AF1E0D972E25F2A1AC972E60BDC04BF316DA04E50783C5CAC547FFC474CB7E8444D88B5B04B556BEEB108C27333CF16AB18B4F4F51F7966A27E9C92DF1451DAF52694A4F55F58F77B96346B050888BA01DC390C0788C8E53ADFFD26978FB23C89FD9492785437B420FE0185CB8A0B284862E5CAAF56F2419371ACFDA37BE5BD8E331DFDE73EB0B86AC29B240746507DCC6B38DDCCCDC339E79E17434A0E99BF0F1DBBC238930C26359745864D05DE7EC7DAA30780A8C3CDECF8FE192DC4E6FB1967C3D4F804062C51A1A9098E97B5C2084057728FFB00000000000000000000000000000000000000000000060B10161B21C07185E0343DF2A4201649AD5DE4CFFA20BAF5DD43F5E4A6C81CD5143FE72865A7C036A2DFD617D96626995C12EFAD019FF44E0EDD7028F29E3657EE3C0D02E9CE83EF0A648FD7CF183A7BF7C15095E0F9278B14FDF6C983CDCF2987DD0CC085400906DCD0D14ABA60124F4B7494ADBBAE3A8D6052122575F99792F7240EB17864DC6D231721140E43F1110E73EB2E3C05049783B33AAC4E4CA0A248775BAF81FDB03D114508928BEC3169A810296B5A4DAC27E7C7F8D01CF5943CF4D8CF6EE6F9042BB300E50EEA3224D35C9628E38C368EC3B42393FC820371DB6557216A2C2D5A230FE3A7C6BCBDD89A2BE5CDBE7F783BA379B6A4237DB051E6256DCE14DCF641190A956E8E85EB2638736B899ED045636DDB7A351F5A4F4108D9D6E0413F92B9D392495299128A5F4ACCE8C7747C675EFE05ED7182DB51C515B345029440AB61A904D2A390122680C951ED4575515144C5CA80D6F14D1CFDBB5373B78E09D04D0544151CFA1240790CD31165048D1484DC4D11D05057071DB3433DF071B367E00FD38C386DAB689E4DFF6FB421B2A95FF54DC29375C9D1C18A76C79ACAE3D3F35D4CFC385199A4CCAF6C9F0421BCF58D296EC7E0D1B95A6C4BCBAC1271F94E438360A71A6440275591E41389B30CAF2626A865B9E59552CB198A1D4453EBA6D0F6FC491A8A7783B4A8BAEB81E54F9189CE493EFC1C5D830A4F637F2BF43CD86B91637611415C95685FE79966174312FDFBF33A646625F97521B5CB1F008135B824F1D6D8373006C7158E62B1F794AE34548A0C6DAC8B60C559D81580AC0D84034A501516EE36CB4082732918365A5AB787FACE591AB02BE6957AE4BB96B58E2B173DA019D3E0CABEBEBA0AF775779F14BFBA8F595697731522DF3C80CBDEC16F6ACC32659CF5DAF193178307887EF1BE1B48B5806D0FA9868A7FB853708B26873857786B974709C687D6597BCF6C7E476C1E47CAFDBF30B6311ED434C0F998C4065399C59073C1F2BAB1D46104E74EA6C976D416E58BDFD24CCD957CB431870DE5DA8763992EF68BB18075926B0E4E826095EB3B8CAE086FB1759C94B873A1F4DF477E0EE9EED8DFD7C77508B3F0C67F69BE04355ABA9344960639F6DD6B3A956DCD66370338617A365579C5993986B4F748CB7C990344B209785E22A40FDCF8F83061D37C9F1351B4473D6C74ABE6B3EB2A7D62CA0F0C88A0AA8A46973F781DF0126E8D55D3E9C41C2E3884F84FB0A06C484CFA0C9A0DFB8CFD573749C711C7C236B0F2F144E1BA4DB2525C093DEED29434FE43CB3040C5A374CFEF33214FDD2D660398E91BF070A4F5F9746C2F08C41256FD5E955891146FFD38B155987E6A0FC47AC2A5950509B9E2C86B9DD9929378F43EF3935F1562672498C5640A22315BE15B001D4B01418DF8EB41DFE5C570E850582D8916C2E7FC2B728048E24BB9D1E8283615E039C16A2FC61011631BBD8F2BEB24ADF9552CF5797CE05D9D1A7E7F3F5455017B127D9BACD32BAD0CDBD3991BBCAEA5FC988EE7AEC0B1003732F25489EDB0A1F9897247CBC40E60F1DD276259CE19DECCB90067F7293A68B683FB5232ACD2217B8929859109D6852A43892098630A67D72B1CF4BD5D58E20C5C18B85D69DF74EE8CC69BAAC7DA48EB71A160F03B68C6BE87A4919736F14363F004EA3F41DD37FD8E621BF433BCA71E17565E060F3C0F889515D0A8C17FE0D6D734FF756256B0A62058B95422257780DE000557DF289F47910CC272A14BEC737C0715F204C49F03150082DC904A5D170F7383F04F1E355F50F80D5461CBA53490BB2E9484806D369D61FD00ED1EE5BE518D04A24503B1C4C08C7CA084902A3942C04143807203287A985EB3FCAE3C5309410CD9B9A548F54DED44321CE8C2A04679841DAEF7FBB6AA11091D240AFBB467D9969C31C1CBF6B24F8CBFA20CB4CFA404B1310400271664763E9C1CD1B6FE5FF2A0FAE22AB14EFC016CCBB19C5DD5D047750DB4ADDEA3E7A193128A5F4D7BB6358F21B39A44259695904DE3440BB28CF9466B562065C387189EAC2F7522C9385DC2A607F6F9335FF8ADD47C7BA932659AFF69B1F26EC8655BEE4F97FBC846E48111CBE25524873D1DB2F2282D0472A2AAA3CF491C26DDC5E1BE77866A3B692E417E6717A4F4454C56F97F063B9E598865B6F71136D65DDB0F3CDEC57DECD5A57366BA96E4315A88B4EA3479321468FFFF508D23B0701A62CE0CBC0FA37C91CFF5C5A0433FD61AE11A922575F5BAA714DE46A58D6EFC79BDB10C9AF7E9950A61D44B3E17E3B5298501146485B562B1570FF5798B47641D67091CDF90902B2D762E3EFE94C540DE4A28269CC416EDBDDD4D43AC2FA82D638DD9BF11F3BF22FD81CC4BD4759D7D864EEA0E8E8AB71796254B278CF9B650D1FEF38B8437362B2D69ED84C54498331C6899E20C596FEE7CAD9ED8D83D86774AFA6E56A4ED34B0B0842B21CCB67035406DEDFF0CECB0CD089929ED5FFA0CE210822444808BAD99AF603082BFE5C98EE4653349F8A43DB64CF90190C96B0446CC9CD23E0D75B47F54A731E8BCB0A4C67401DEE87876011033D2A526067FB73786FBC1CE696130FCE5D5379CDAC6788875D27C04783B1E2EF41063D57E3D6560D1FF48882C39131C95BAE5A9C9392DAB6CD17EEFBCF61C464A4DBC08447443CBBF3FA80481F3BC1A5806042C07F7A7AD435875DDB1001565EB6B7B872CC6C853F771C1DD5D9C16BC27ACEB3C7690125C1907C7CE904852108CAFE76351269A3D3EA8812FAE4FAE35F0DAEC8E8B186F760005524998BB5DE475E4DF85209DA915BDC972218AE7DB7E2EFA05A7D752AE61CF2F3DC26CA2D282C8E32B4838524BE460971E077348290FA0043FB7616D821A71DDA3A5FB76BFCE0DC84AAEA432DF32B05133A26B46165297EBC45024777A868B8B1B0DD6F97658BE799BD366CFDF99861E916F7CF06C034E4F79594F1BB6ECD9B7347911488928E1E473C4B8C73297F7ED845B9EC59020373EDA57A436C1C9D1459C6114BB6258543D8F4F97B10AAEF5A2E082EA173EE69702D83711FEE6AEE8F6B260D03AB74C3B5D8FDDB81B208E16458511270DD1DA295F25CDE7E44A8349B60BF0C59D4B425C1FBA60D2BCBA47B906D2830D8D5C091DBA756E61620D78B2DFF28407FDC9DA9113CBE82219BB2CC05E11C70D040BDE821AA17B3E981558961CA571E5D5041F7DE047A1727D9C904DEEBE561DC6DBD8876BC77C27322F512D6171BC03871EB0FDECE70F119BACB41D1852220CFF26110EB0EB78E39AA1B2A4C2E78679F53683520C5A57FEA71A8E96E0AED33118DC4BDD035FD88F535B011D9C7DEB6F406A072AE6C091016ED10A5A4EE9827882EE27C535262D1D745AA5231736F2DEEC8A6017BF0DA36B416C98AB71C6824A6EEFF3564665007C9E850FD02A1F5E201B534627B92D21A493DF293DB9F24DE70C7B49A6E07ACF2DB6C90B448681666DCDA318C08AAD08D3E257AF7E774C75DEBE3B3C07AF683735E87F205B0FDE07351849C5AFD07D5722C6AA17B6AC2CC3551C305E6AC31E3601A236961F6618CD3A0F7DCF6F65B8EC82E27E44C8518CDC16ECF79374F796A3DAABE2D5005B25576B35B021497C5A8F9B98DA68D80E56A1CC1044C04DFB11D36CB147EABFDAAFBA0A93FCED8675D7D6A9F999785C0E7346F4C68EB17C0A2409E2F5BD4AC5551FF66A9857C66F642F2A385131377B6372884C417E01BFBBE1CA748AC8969BF2C0BD8944767746D1D57D862795E8ECF9E8A5CA122D0259FFBA822588C5ECCD14CC6FF4B7354CB572F5BD695ED9D85DE131FDD97DD5D6CE7844DDF9F3D112028B5125AE7A77A4AEB2EBB554682A26F457C43FE96D67C90BE7E49FF443478E82D3A48680D737D1260B8210BBE962EFAE6505E496B1B6D4F1042A7B971605E2DC50BE3BDFECC3010B9F5618D3A1B2C1F48888B859E4D6B63CA9D29990B6D502FC22B738B203A83D597B48D73C41860E4E99C57181F5B02F108CA193451025F3B368CF2741244F42B27CB9E57260D2E127CA166B32E0B9C927B247B31619B1D4 + +count = 87 +seed = EDBCC4F6AD0F30066947D678A368B960CCD164889D77730516B444ED2DF10B49C101902F5FA227377C3163A0045B34E4 +mlen = 2904 +msg = 836254422C7D13F1120012FB9CC7CDAA1D8B72F6FA3943AA7DE75263D3DF814BBF2E80C3A204BC0F9AE33E4FA82CE893D35C57E41C7147602BE12455B00B7949A3195264A3281CECC3FDE34802B28C6E1F2B505AB6087D453BD6AA067B2370124840BCAC4605EE4F14EDFC4B4FF19A4D7A828E60156B49B4027AC18DCCD20294F89CCF03D0CF47BB2F22D3749EEE69EE17AB5D8E4DFCCF36824D23E3F95E959D0494FFBC712CE3975E3A661B3F9E149A0234F691C2D820000DE97CC016C43EFE958DA469F740610FD22B64D4BD2E30075E22BCFD4AB41D952D2394FC629F016EE1CD61AAB4581F62A7B8648F8F8CF02462C81023CBE2755C91195A5917FE5A8B5058ECB8DAFF91DD3F73FE38665666DBF79CF6F203FAF94A5CA3F3AFFAA2C2BD5F5DBC011DAF46FD7CEB74B5875E4B5D80B6EDB9817106B91865267E78731662218C8EDE73E588256FB1AD57232AA5533D25BFC54452612F0C2AECAE6DE19355E1D508B888D18FF9F6D7D68199755CF5C210172F65342269ED96C77D80AF8A244B43A99DEB49B97A6F358AADFCFF6AFF72AB39540D375165185F31E0F1A6F97722EE365620BC5D642F8CDC59F7E84FD8615F4A336ED340BE6ED8451997D87B7904C1B9A3A0BD1F8A01AFD6A2D9F5B995E3FD0D44DF8FBC8389B6CBB5537816C91F0EFC3D2349F15EEE747B254C5BBF9418BB979294423DD6DE4D13484408362582A86D082350CC79EBCDCC05B70110A038736034CE4F3DC1D17E5D11C9C7620D40730B61437906933193D1272F7C89C701D495ED682F1335B7E1C42C994E090A67D932A8E825F4B9EDA8F2A94B9A1F11F10E91396908A9D436DD01BAE1D1DE2C6ACF458C0880E3F81ADC2240A99E6083C9C188982713DB243028AB07DF407218CA6B3C4C93989AC96D92375834B915B724F2A105D6240E52B9D7003C67FF76F7A325D84ABBC229266BB40D1DC8784CE1A4A6BD17972CDB26C274B06337D525F61B5BF952D23FA13757460B7B8A3B99EB023831F4FBEF72D62931348622041FFD12634947579BC6E16BD1EAA8E8B2DFD54D74EFCED79EF4FF31AD42036DEBD0FDA3B7F3F8E7A3F45955F82936A67122CD42E38AF646CF565E294F422FAC1E7D274185896F58E9D0FA1FCD3F4D379ECF5B566586246216556939BDF86D6A417C3BF77C64F95D7DE8197EE25B44EEF00209D33159710DF001372C3E3D09F24B9B08B8938C522690674A7588933E1CA37D2C14DF50777806EF6FD2285771A44F6DE90475C6CC314DF140C3962DD9D70C54E58CC5FA3302D69C80C6511D9D42A51B7CB7FD7FEA8D8BD65A66FDB2AC80D945FB7EC72E138F5566CEB570968D84B60068DF20C6CDA2AD48372DC97424793FEA8D2136923070C25F47C3D10839D1747B613B93530968D5E97A3FC0F563BFFCDE7B42C839EFE66C3A8655D0CEB5AF7A37D23DBBB52D05CF6FCBFFA7C7491703349819AD94CE218912557D6C87937B2E7B0473856EC78713C29A02CF7B2B38E0DFE16804AF6C2BA8607026892138011E06B4AF179D63DBD97CB917B6507B798E58D74F485D3F063C044211E428FBFFD5AF2D7941900299602D3B15D5D600B435D9A21948B8D87A35205A3AF9AA9BA491D56573A93C35AF6683655E04A7A17F1B9709ED83E70D82A3DF59A2FB7C051ABE508601F322FFEC089C49DC666BA04366C038AD59D397022F0F6344255F4D98BBB17120441CC75107005A74DB35459C63770547A4AFE59F2703894DEB67612448BA7C4F6FEADC1717F6ACE410C6BE62AC319CD33AF285D17D55F500E364A0ABE71D357AE0802AF464B6D2732F3FB94BDB3BAA497F2E44727BDCCA5A4B65AE9DF189FF1AC640940FF4D479A8072D34ECC523DC8FC7C87FC89A540485AE7BB3F29B041446CA427C0B48CA7515A1E31788E8B53E1122D372B6557F8D2A97CDE893B20E60283954E2934AF340A358A4376DD0CFCBFE305A2CE7B72DCFE2DE105CF44833F548D1BCE88D34B60BD29B69309DD87F4B91DE10EBDD7D7F87D6231307D0AC784E0496DB725AB97656C34E60B34B230F37E30FE326296C4E1BB88C0BAC261DF0E5F45E6E126103EED6B1CA146D58140A8893D847E92D9F3A0A883E8BF830147CEDBDC7DD42C1A58A826A8A827F9AB26ECCF64F68E9CA6B68261260B659B47E0DEDBF5B077982B24ED9B36E8466DCB21EE69B5E2BCCC49A163B4860EC2CCBD65032776DAE601E18ECDAB8E35C2760D5758592F6CC074298A97FC5E82E7DA84036FD10E0725A0E4E58CC4DB30499ABEC0C7D95D88BAC2C58EB093312779BC1B8619FF2762FD1FF009273456D829394664C31FF6D7848B27174B36E59FB65D6BEF6D974D5038A28F49AD465B28857CC12BAAFFABF3652C2E22B46B040E579FB040A0FB4B1DAF0C157D35407C0B78E305CEEB232E7B7426C95639B1CF7B079E80521FAA538E51E69255576650C3A16E143D0F815D2CC89EB00AA13AF20394AA23CC6AA99A9F297D886AB9AF2655D53816E066A02CF21C277DADDEF3D7D0825D094FD8FBD5386139757EFD0B7F8501829725A4B70FF1DABF2958E07ED21DB76266A88483EE7C51A7D215E1B41D2464911ABBB1DC71F9613ED5446E4B0C97BDD47F22B372FB7662956FDCF3B108E0107F74301A054FB004925B041AF354C04C20FD370CE1A014EBEBD8311F3265A2F78B48124521A4AAE240D3BA9F94FD33CA4A92D24A029E0754831869B58F670435A44DCDD7BF75ED9FF06DBA52980DCE49C1C26BA0965DE3623F459E36127AC6AFAD4D5598FC45A95173D039CBBE2CDC7DAB2865FB6BC0FA8DFD33C4A826CFC77BB7F45CB5AA73377A27271AE41630DD3D4E2722581537FCFB233E5AF8F04CA824012B5C429EA498F4AD44AFC249DE2229FD7266FE84173A5CE44632B3650D6E1F278625D564B374C10C1AFA3F17432CBE4B65327C6B6E0CD2F99B68AB043C5C6C99D7FE7FCF940F4887D309D7BC0FFAA5DC4B90C79266514F46CA2D5477F2B84B04E30DCAFD0224170FA6D4BA9AD2A6DFA8ED73DFF9D5D40D43F02610032719A7C5646CCD453CEF409B4325F3FB6D9B9201FB115E4DFAA0B4D29959A44518774E94B2D4D6D06C7F065973BECD203F5CF6CB59F869340EC6BAF0121049DB3E1146234CEE4657C1B821AF817DA27BD4C9B1103C81F5B5161E6A9329D83D6E4DAE1F3299858CD201222D34A85E2991BDCF32E9771F3E701897F647D62729C9805CBF118C9FA727B056A7271A23181B92F033DE1EF113A856A884AD527B8DEB92085AF3DB509FDB0265FBA3376B31BF753DFA477DD5E247D939109F31CD430A692BCEC4D9FC7C5B4630CAB90C64B75496BC7CA54D5621FE3315AD03EBF1AFD6D436BD2DBCBE707B35F916CFC147BBB5B8AD2E80ABD692834E42E0724C8B901F5924212C4129F7451B9DD860A85855D1AC59F0B6B87A66B6A395DD81990AA3DEBF64C91CEA6862B5793BAFFF81677FA2928E950D94A6333B0E77A15AE461E710BE70AFCB9FE6E0C21C5AD188E439A6E5138A2C5AD17126E759D48491E3F3F93F81EEB77B7B3A6ADD96917CF0BEEA202EEA5ADB3D5593A3DC9FF1F8F05DBF5A2707EDBB6640EFF5B65A0003CCED2EB480942A13C1F1CCDF9994F1D11DBEF0D3BA7C3801AA508C17BCF287A928B635F475195D88ADF9F4C1CA7D3D1462DFD0F6939B89E5ED95F177BBB12253391876492BC01AFF1C1DAAF0A1C7821C2A4E33F52BADF51987E010B391FC984328E020206EE98E9C8E6763120055F99725E48356FD800E11CE973D00C800C353A5DF8B028E1E42F817C7433084C440E47532FC639172533DF35F0FF43257841C3E4EC7DD7F601EAA81E9886FA3253844C195A62F89FA5D292536BE8CACD80C94BBCD1A83C985936353C9233E512431A8863D7D8340E89307547BD10B16BF2C7E0BB01AB8093C70E4F4C8FD30608FA14FF072D81048391C07DDD82475A280D4EDF81F739AD1A13BC6483C3C37BF52ED52CE8D568AA81864ACABE225BC6467C79FBF43781F29B0C508E6825D4E56D25E45A8C0C6298765069FDCC66B2C5492FDDFFF69D6F5975FCD81041F30FFD7813BA3219B3139583EB588DDC57851E581FBD5E20127EBD +pk = 0EA33FC56DB7715252BCAEC8D0E77739D4CE3C6845D741467849B38CA852A1957224142CA1C7FC5C5E5EB82F415D59A1C8EC8A03D27E33648F611680F52D1F9D979428605A1D7F02A3BD9A905D65BB76DB520964D6C34563A39AD9C2A7FBDC559DB9451B8A8747E8ED67875B850939E4B2E189FB3A9760D35A85304735406DFEDBE49A4ECE0BB17AD929A1880514487F27AE5E4B5546C3535278A937B5C6D483175FFB6ABA3E757ADCA33EE1A43AFA02793664CEEEA71055C2678DC3DD53E15E0CC69BDFE8FF7ACED618DA438BCC252ACF5F6913ADF0B84260FAFF8B0DAEFD7CF3D366A5C11D749EEE0BAAF597E2B8E8A46B461B3B36CDA232218951D3EF5200D49C3C4EE9B5311CB7BD9B2EF6D159382257601DCED8A53BC3679AE2DDB0E73E1CEC32F488167204EA0EA66739AFB25BECAC901BD2AF2CC5A988543F26A57DBBB199B9E071E796E6A79C1B0B7C574CA786D090A5F5F6E600554085067BD7E8FCC1E66B6CD16CD0D29921241BC02613D72D0322BB5575C5DB985092465A3B9834AB2FF915E8A415C1EA14F68EFD665D7D654DA13615CEB845E9E7208AC4EBCB3AA0437DFC479D8570D3A3BBFF5D0B4645848C05CDFE4CFD70B8B3BA0D72C722E68FBD810E4B4A40C84CB1861EC0B21989A81A2AD808A8E43A387362EF7DF7867B452C1DAA85D324508EB369BD7E69BA38FA2891A28C8265DA000788FD2C678073ACA0A43C91995BFDAAFEAC90A26AB25EBA70B1C974D22F5ED07A8D432AA9C6967A99221B1D54AA78DE8DBAED987E17A37E02BE0D8CC46ED32F50E78D0006F10CE060490D6F4BA6C3CA6A2EA7893B8251CAE0D8551EC724B0882712B96C99F4B95E9FA12389DA901556462E3CB3BF7522A206DA72A7FB3AF54C8A0694483E62D4FA51209E98FDB9B0296CF91C35D23524E671BF79931A45746FA4565571E8506C88FDD1F02EDFE9F47168439491717FFB6B52B0CAF009E4C22A0F1A958AD61300EF11FA78B3C5AC75520795DB2CA086994E077BA264A0571DADEB2481D441EAF5EDB38F58C401EDCD0795AF4647DF340D62F13A9CE6F79EC89458519E5BE080C98D3E733175D3172DC64BC5EAC12D8D384E39CDCD266FE78F5C27AAD044ABD8A6DEDA66044DE659AB0A2A752C28CBA812B229016AE7E28952C41DD96A8DE34530FC2637AB3BE9642104D149275AC52A4FB57408270A07B5784D44E12A3EA1DA07205283F829C6EBACA392623C92CB6321A7B180C99401147D0214FE7A3104595231D1B128FC6469E82C1A9C84709AC3740B5A3294A757E0C72437F4A6E401A47DFA85EFB23334186D5612B87F2099F492C86E882C744A272ED777F65D5A2D146A50C5B94DDAF665888309A388A6408F8422EABE05BE55765A0EC61554BAFCB8501452718E53917898451EBEAD4D185F2E9E1E4C6645F9789212A1CB5919E76A237257B5857A6623B24905564CF9A59BABA2BD8B706B1EF557E95DD621CFE8DAE641E13DB6928C364BEF5A329816012C68DA25BD00BC8C5523CB91096C4BADF52D51921D4F2D64663E9DA35D41CA5F053021F00F5A89611D6DA4F374649337FE34D9EF73F90AE5FBCFF7867787EA1F7DC24FBCAAD8A995F2DBD68526760CCCA6CF9FF48D695A494AD3207B29564E9FBD49C368C909685E14C7F0A9E025823135FBAFAD48A17A33EEFC53EBB9CFAA65270C6A5806EF423A26522FA46A104CFC9009863D4FC67B30376B15A7A0C28DB87B81BEA33D344A398F9602E3B40E9B20C73978D6731D98E0494584F20BCFBAD2816CA978B7703740849CA59C8A7446E4AEA8F0CE303F5AE0E50E12CD7DCB6985C3946490A2448571E95B03839C29B37AA6E4AF62171FC2CFED72DC86005A331F69DEB09D7E74EC6F8E831FBD322A4ABD45209DAE3A01468A40A497FE6CAFE2B25AB7727DA8D37EB2E82E8E0F35ACCC8FB6FD898A3FDD422CD2483A08414437EA6C5ED1A0A229FAB3DFAB0D4503F841454C4FF9F2638394DD6EF108518CF3FA098D559ED34FD1CCA7083BCC8E421CBBD39491D8925F771E966B102AE5C4FE7B7D850B8C719F7906DBE06316B169D8734C0636C0D31372C3D7F2E299624004F037A1611A8ECCB309843EDE51E2A20A31DB3F0B2220D7386F816D7A1F314E23A35A4D63CEE314EE744C38F236D3EAC7E9A8D4827A47337E4E274C14B5E0A872117964C1653C96DDD820345730EED85686E848F99716D29FFD2B9FBE4D6964C6DE0B35E04E600C9B986A23C0E6B01F9EA719A5ACB493E1FA9A9F5EC0D9095686C591634B3C96929D1E9E47B74FBC06EA49AC8F8BB2CC773EDDC06CBF7FF41EE941DEC987BF4D1F5E259843911A6A4E2091DFF7EC6D2A62F251012ACB80B24DAA7D29AF25BBC5FAD3CA8FF13DF3E858FF146D050DE0986AD3E461695541D5882A8D93478D648026AA762AFF81C4CB9EA0F45C1E4F153272145CF559AAEAB989E05F4ECF1B60DEE1873EBDD8A0DAD6208409B94BE3DF104E15BC5AFF65CAA51BF155C5B45FB3A2D593C7A169963CD37FB6EA9F483050E26550508C032E6A63F1673D207EA4C68A0A8AEC9D2B03779483E91764E48A6D0541ED3D7EC91F40D2058FFB87D30C2997BAF116732F048CD99115F37C335A62DC82F16EFF5B4DB5D78372DEE16CCFBAD2328DD90BAD67EEFB9328201AB3EF5BD56D84E714C30B36DAB849C53FA6DC051330662A19B652FA0DF6F0EB1EFA4FE6E0805AF998DF1C5F0C6CC8F3A96EACAA461757A40C730F9A7A13F74A601205 +sk = 0EA33FC56DB7715252BCAEC8D0E77739D4CE3C6845D741467849B38CA852A195DB8952ADADE90EFA939577B1F306F1BA66EA5A3BEF5D1689ACCAF2E0C75E3C3A6CF00BC4FFD481D21487D374C0AC1CA7D72D0586179B96420A3260FA67BB507F4F8D8331B55BF1184AA9E53C0A368D9F3E79007B1786D68049BFC11B29DC9D64704303414807468781645405718582206408312438107305334211501677336454380276015108110685878017111256803560073318745187145521214675515756043464663425477713656440760031747810252133176755485242353447044881724178314026242660730182500134447625331048675481670686474727035360156341705526823286652748882516565004587663766404547602002883437423654608601556630313378436510113551016012366701714316250543300648257225308112842365834734561426316357482447321735226145272106107733673010385528182554075571456308487678211087352306374703838645808824401115167771128716678352217734825661452012362768582635016877805241412127568060547511886523546863413282673013118082035502823068513357502853864212072006144108225230121157144736374261115548571218750674800487772254063837770780284768035166146271301426587323766211144805028457207608682621353754070361574142181616277634678054236627316218273835581242237852886324744403873312116010023845378466300656853033652054523814306651135203607374161242344863372667824428028825034353742521144235165270647577365010825231534441557181832862577564181423420400032175737046045428424372546140421238874756247227253475346040070341617042088133574061458635353715777210040855773644101683420266340037086013514831532354140070565080201403651605741536205241161385047475223356812086368352125100487500352614681060575376635037013072723406080641280682731304236310132823612278362057475301056134302735562770776560587007768282385100185747423822888757327776112688646852103377541517064678753718881816541075214316680421215873343753658713064045524446327662775136644013457226077600135723026180137725207683066154887853845567318018421168166563564510740013664242815106702087634356312641302055863775531617804632178243155610531410044187612707025857342387462281165857114368011750433312303520165606421304470778523640100180474015730328344061885414732311784734346841577147378713667753812102436884351304165405624324583206371051746813347064014433283102871234678521473064002264206136670523383071607734746812036518215172523212428524738425071242241656800657388115861114666715483365131610350656537605441862176101000851437428454046471202080836841238127407417051388856726571812781046722258400304203083625678310858471866200051861805213803454805417712551711265251871217651427430140034185617171821673724253564716544616732721102741415067777644872711148877088240064773828864471875882663510041165304133482676412868437658022871484520432167204138320568571602714487235514420220856400241130170223522745503105143431112065253770505502344208070355760148524625560150846330151630663434385577657338041510346417011478800011063275085826607416562184608846843146448707718681443443648685152528012613312385771465580546008704462412707182144541631554726036116315532832461085664080822543571847788642822633170243538634105875361841005808077443413726741143746137833738221317875844884407448DA7A649899CE209A2B734669526EB721402F59F17F66C02E678D4FEC968B81EB08795C814CAAE833497AF7EBAB21F40CAC159DCF4EFEC0FD49367733B98147C2EFE669396E67564F6588DB8BD5121929073FE1E281EB0578F296B3055CE240B968E8A7119A1F5B4BDD9AA5CDAD565B0E686FB7EC9D8EF597A817D7782987EAFF7A295C9AFE66508B8C4E19D61958806B7095A630FA6766EF75F52658D8CBD042533A67938497282CDB9EB8B561F54C783230EEFF9D894206C342DF4E072A6C44D5CA9AD46802A5A06C8D9582BFEC61E458DB4BF56A9C5FE385C0EA42F17CF3C417E2BBE4EE9F4F20555C00EEFCB06979D1ADF348D6D52D2A2BBD42D361A4F1EA3989BF4CF74E85A568141B8D0A787A38FEE525559CD4FB4407BCDC20F47619E5BC2A14A56775A0AA218ED1A92CBCBD71A88A22F98AC05F37AD4622A660C8F532B2E6AEC79EB28D15BA07193AD4340E867DBA81A13D9973369465ABF96948DAA4A6AA97752E3915B7511B9F4371EA04D47BC6983C7B899374927B415D040F73615B0FE5B039C143F8C35613EB06474094DF72CCC4732379355D0D74EB67677FD5B24740E1219135A0AC2B827E7133A0A76E965A99EAD494D290EF718EF894B855152DEABC7F533D0F1A0876B75CC27A83E77D989BF8CF1EFF6FBFF86C8A6D670F6BEB8E2BF48478474E74EDC146B55B846E0A4CD2403D975079C38E82EDC5CD4D74F993E2CBD3DA5E14D03453780779B908A346CC908799E9B5C8BEB6706C760B382A7CADBE1DB10547CC996BBED74C9368BA930A450645C42C9625631074790E75C28A8C5376BEC2C488B12119E13C42CF85F211284AF8D38DED0ABA3DA01F70228D2CE5EA88444A41BCBBACDD725D9C1A928D360C8DB9F80E958534BC87A78E30D4E3A8CC94B714FBA3D0A865CBA97BF074EDF2551A713441A2B227A143124938AD18E5614311224A4CB81320F53D7C7FB1E53446A1C876F1343D36B8D9F4FFE1ECF3DFEC8CD75DE6ACE93F19CECB8DCBCA246E8E34843D3DC839BC92C6E146E8F11A7498E8AFBFFD6A69C76983450195EA31CDFBF9B4C4C46EAEE4AB900840FBE1D6A69241D37CD3E6B468C0862F6719CA9AE2C2391868F023CCD6C63F51286FCF9CA761ACF9D5496FD35747C732874810C92EDF41A1DB1A482D0E4FD21F489C6DF592EC664C8BD3708F86CE3D588148EB2071B17705053244F28C3B73DFE35F8CDF049A8419B5688A162D0BDBF70E64214C876F8E1CF32D2C155D93657C5699C8A958917F270CF7F9567D4A7A95D8002DAA8C91E8B6397AE07FFA4ED0207207064AE20419802001337AEE10838F0B48E6C6A0FBD5007C4008FD5EBFAE7A65A07AF9376AAF55B65AD2A21CE58E0BBC7B1A52013165B480ADABD5866178835B944D58D0DDB7992179ECFF2D705805E0D09CF07390E416D0C5EA53A63E337E04A70C02A3CA255D64267493AB7B3A81F8EDCFB386CD9BF43B7CF6A9E27109D2C5BA23BA11D8166015F9468BFB6467C76BB597804A9ED1BE43CFB766581B7DB828F34A14B10D6E16BE40E0BB9617F46291EF9637F6E0130BE537864E83BC059E24780BEF763F3E2F329DBCB63692E8DF6E8749C5E43A1FB23289CCC930FC483E60CA4129BFD97BBF9435D0282F225A7D1D12C0CAF1E2576F3451A1D87A99AA39696AE05F6A5AB3C3D116572D61C33C82537A54AC4A352CB3CA85479AD019205D3608539D147A3F830ACD3FEC34B30E55C8802DEC576CAB54FEF2DE7F8A5714931FAD8BDAF62FD1ADC785DDF61DA69F72D561BC72919B3D3517A21F191C54F4C0B216166AFE6637A430CA0352D3CA1C24D45270FAA018544F76A2D9E395A1267F986C622A4CA4338A3811C14AE0747EFB82165E66CCE4782DE8DEF1BF9256B5180F77D1E3197E365AB51A0EB542CD0CFEDBA9C205C64E34EAF7FA1F2FFD3EB90C55EE3DE60A114991AE1E2074A37BB048C0ED0280ED11F674DB3B8E37B08CBBB235CF48729E1BA7D4D8BAB71EDEA4BAC4FB71AB82DDFB18EF20F87DD743D2CEE010913FAA5B46C2CED3D960F456980C84FE585504BD93A061AEA9F1F5A8767AB649D2D77C85618C5727B1C3E6E83681900A5C35E254DE73587B0E8D55E4042DCECD8174E3384EF67A4A536B6603AC5D57CA942DABF7DF9B44A74DBD26B1175D65AB69615907590868ACD8E4E94B4859F06FDFE1A2E09FEB1540B985E64C5F6B02A0D79D5D81650C39FF869A0C1F29DA2E4C742B16D6C9CAFBA6368CC3228442CE1F463BEE167464B8427E7445FFFDDC192EBBCC2046D30DB47AF359A21C62749261B0220502449AE4C39343D42415CC6ED747B7543705E78CB4F7E2EF7B2394AB688C4B5C776CB47EA0085CD54E8AD701FDD9D8FD37124BEA2402FDD7E7E90D1BCA9FF708E6B0EF1DC903EB9A42BC04AC9559887BB54C32A86C87B8FE8848224BBFD09B01626DEC9FD4DD06F66F28ED839113FB270FBAF2D7DD71A097A465DFA124197F8DFF569271219B1DD9AA0DF6C448A11C18CB3E288E6961A2173700E05E52D5BA894B961C3D0D06738B7E25B92C745BD5A67685EA28A7970C5723AE7A2A54A0972A2077F5AD93355BF62CFC6769167082E85A0E5F898E6DB0458AD8DF3D4E4CA3429A07C7E35387FF14516705652042AFCCD4EF1BEC8B7BA0F9A6C7DF4DE13E89758DEB3F34A9F23D8C71741E47DD616A7C19A4543A4F3C75BB4EAA8414629D3405AE16B8F008EA97EEF0815C95B094B2BEA85E601AE249AC2600AE7A1CF98A884C2DCA5751E3D2AE997620A46E79D63529089F38CEE1C61CAF414252011F1E5C326AFD9FE5F02C7DD0E25157EF5F90DE56AC84C2A0EE2E73F2FA6B58732600A870C959374419D1C2C856F3621325A6CF0EF942E8F59F838D236B30316ACA30201CAC4BBECF6660FEECE037255C8EFAB415A766B924D11641C5A15E2EC9C3846192724638D5553BE8E708A25423AB0B1D48087664D0F602E8A5DD07FA420F26ED197EB3E2E248ADFCA1703768C51F0B6EC7FCE1EA8AA5D46E393429BDD760E5ADE9AA597389754FCE83414FC0A2E986679B02911D21C8F1C730A2DAFADAD95C3D2C57CA526BEE22770CEE22ABAD9A57FC90DF56C8FF68B2822CB84D50C7CC8664F818685A93FFDB385524A05BD50E0E93F62798FAB4E87C1C162C8720E29AF17511598612431A00325ECE7556EBA53784FC1E752FDEF591B5FDF2013707EEB40EB69FA2B07266B38CF759A48CD6608F4FE2FEF385EAC36802D8C6F0E546EA7385DE19C5907F94F21DA9DDE533D8E378818D341008AB52205B87F9530DF1830653EF9C3CD6263DF979AFB5CBA7573A9C669FB219088CDF68AA766399AEC6244BD2924F4E6BD2BB498F2AE5993BEE6BF5FFDF7404FF898A3891AE7BEEE4D6652B32654451A2EE03C957CBD815A62BAB475EAFF1CFC830DC3C741D803BCCB87E69B796091EA167679A4195BC6433AC854F4FA13C810C9BEC50D3C0BA2EBA98BD91ACC1FD72AE1006BDF9C347817D547F3DC761E04425FFE8CDCF1B3EDDC0 +smlen = 6213 +sm = 7128A5C46526B1F0E5183256ABDE10763AE82EDD6B6F03284F43AED72C0A0394A52AD9B7E9E9362BAEF5449C050B47540B6A383FBBAE11A8EEEF674CDB3B337DD471DD59638AA2BCC18716DD03EFADD3EA14480A7267E2D10C7A843C8CCAFD10BB71C3C23838CEAB79DBD6FCD2B792DEA5068E10DA00B10FD5869086A6C65AD49021F538775E215EEA71831BFB88119263198BD9AFDD62E64196E0ADB9098A773CC36F0084380851E6A206F2743A7DD242953D28EA08A18BD6587D5CD5069F668F1222D71DEFBED1D9266B74B1B2FACD3C757E4E2514E0BB773406C63403D082156E4E51E0306AB48ED6C1CDD4A978BEE6DB386FE0B961B753BE16F8A190C8D537D78D7FC9316CE0D4AB8D57E799344508CA5609393E0672259C03D42AC19F3BC8B3FED6DFAE1C852B4D3E07DCDEE0FF6F882BC61135EC072D9A6340FE6CE313F05871ED7A2D3CD078DED09F9D0A0CCC52565E2C987FD7D5D176CD950FF8E83DA529249A71F9FBCE9EBF4266E45239AA8BDBBCBD8A39C29F823C22EA16774FE1B1AE9AC625A9BEBFC1AFA177F51D371115CAC54F7CD7C2DF125BEAC0FDCE98883C62B530D905F657EB86E346580FAC78CAF7C80FCE325201C26F95E6585FEBDA2F08C55BD44EA041953CEA401A291A6342049C279D51CDF5AFE51A73543AEF07A29923F54F4325B5DE28DB92467BCC8F965631EAF9F1696F4476D1FCC447513A306FBF77F053938A1F7C05713E829FB5CDE828C21BE49EE4968979B09A2037B4ED36526378B8A4FE309BEF68BC8CF2936DC1E99F1E5C2EAF64199630B00466CA8BD2286421393408D0E452B059DA30FC922DCE290DCA99D582EC5D7F04EA35FE984B3142ED3AB0018E7BED1161A0405838480AA05E01525994EEA2FD5C866B00BFCBE65B83FD0B383B66ABB7B0B864BF06E49BFC4D524F621FD01A840B65A0A2030ED2F1992A28F64C321D007FFD49BF0626E53BC3C047EE09C0BEBED54646AE9E5C0B9C87E230F77694CF2F0607B0E441B1E0BCD75998033B94E9F960F7DA334257A53E17A1EA391207B1BB65237AA4F60E77508C499FCF40CF4E3A1AB3AF482666E5B1F7F57B4A1400716C2CB5D30CA8C2766306C7505731DE59AC5A62525B1B3A272013CF3DCA21CEF0B4AF1E4B5A38D3365145C0662C85C12B6E4C650D6A06E00AB0D941CBD230461F369F6C2D0C1D95E2B9F7AED4995DA127E85D230AB9199EA4EDD8BC05D117DB6486C1EFB0F55C2A163C17E8ABF9FD2A39C3D9F39E266BE9C75B1B170CD1570C18F661CABF7D5E51C4795EBC6972CBEC739369C7315A18C2944E5B85FF4A3C2FB14402C338037EB1D98C9721FED05BC9E302904F7E186D9ACDF2A20BE6464D2C1D8106501A37A5B0A3F5CB8A4138B5B1B1BF2EB6B465762F378235DC04B294299F53EFE48FEB2C8E450096C296A07A38B6CCEE111F500B44F294C3FB7DFF37E4C61E417AFA87C87D7657AF3BFA70ACB41232990146EEADF2AFCE7679AFDD4ED6779959A3D660EFF85B0C22D84D8EF3D3A9BAE0C9F74AE783ECDE9B8128DEC2900FF89411D7145E21224485B74EBF189831AE95A4D9530D2A8A2715B4E337D9C6C1CA216ED9564685B446681B26EEDCF592DEF9E681E17A5B921B14F7DBCF61E89CABC4A3734C3FE824A31EDC43726FCA99F55199F886007AF39134EC5EAE3DF7C027FF3D8A4DE10553FA2E46510E10987C7E2BE7D89453054E4F031E15459F637E211D029829EA286C9DBB74FB2F34243DE1A5536F90DF775ABE1DAD099371A7F65F4428AF18FB338C278E04A72917EC9FBC1FA1785B324D03BA2A0EF9B20E5EE6B6CB451536E29649787253DDD46B736D88FC301541FF80893F1FA661CBC305373CFE308A718F8C46C959C36E97C49F2615428B698C9A19E3E0E046177ACDF69F6A2A0E043B6C74480502A59C03DBF9A8036D9FD14AD33CAA9216E3A1E3658C261709F964DF42F2B23B7C881755AF0057F29D56EFDCB181792B159EBE63F7C5ACE0BFF7E7E56018003E4E4ED4DFD9286AD8EFB30DFDEF9B6E1BC49C706370EE600F468A02D784A31C4C2BE7461E00880314F054DF91FB9D3F2A58BB35AC19218D3F02F39254417A69214AEDCADF39A3B08654A8BB7B8D01712DD3F5AEF88BBB8E590E45505D9A812A35F4C6F9222199CAB6B3F8BADD8AF097CEC20271D43307B60545CBE0A663B82C65CF994177CF78ABE43DDBDFEA7AADCB6799C5D1F46D1AB55E30635433007E0292850F1A08F69C5241BBA2D6D70D5FA6F620DA57DD71678C60526D1FA1C8F50626B5987DE1F45E84052BA599DA2B8B71037495DDAAEACF97940B1D32F9B45716F4038D1B5D953499A49A1B4017E9A0CA600B4C95BA152200139CE808AA193EA92B0B825BEBB3DC151AA831AD884665CEBF61CFDCE44FD3FCD7101A79DF1B4C59C3814C7A4F03550F6A71DC57C8C6FE49D6D8FAC2692938537CC37EA53B4339AD02E01715EB84EFD3A0DD4A18D59393197055825F0402CFA7CC0446F1D21435DEB9A5708195608C7E9D894BC8569C9F87B4C12272F087C6661DE736600219A9A819AD3FCFEE6460BA3E70A1E79D6BE6A71B0E581EB2D920A3BFFBF15AD0B7CEFC6B1B0E8664DAE341522A062C7C9AFC18BA2B90C09CEE922DBBF3606805129C5F10CA4BDBDD9139227E766AAF225F30CB834C3D527F35D132A362402B628D271722ACFC36988A4F8A6D6F2C25516CA92CD4E3CD7B3A898E644721F8384E3F13B0B4EED54B18ED2F61D5B01F9CF07A51D4FE3FE0838E9278F45E56CB6F9D28220B2EEB54ABD53CC916F87F6460453015277A68209B12D7CFDC6B19CB9FF151018E7ACD9E2D21CA61462752508E513390A319DFA4C7C16DC0898B96D2BDD371B8BA8A65EDC87AEB39BBAD0FA5234B4D2E4CDBCEA74ACED80D5CB70E7920BAE94B7F71DD458B08CE9C7408A75A1CA93712C2A0FC683458C064C2D066FF1202C771B515276E9C1E4531B3FDAD12CFE0EE4222170B52D61AB09331BF91CD86F1C9B0DB9CD46FC6A13AE0C44EB1EE71DC34274957F443922025A04A550E38AF065019D6B64DEEE5CE97BFABF7DCF7C657F228C3B48FD8A35A0870A58528C4A00EDF7019485F83AD8D3521925157A468B1C47201D0B54EE18AD472E62C5B8C66A71122482CB8BFACCCB997D22BF151D88576C3BD26AEA267FD25AF8107CA027A6D6978AFADD95DABBCA28B82D151282ED398510A49A7BD10D48B8D112DB389C04BFBC52BAE884C612C52E2D899D6F4C63CEF0C4F6541BB23734727F982D5FDCE6D95BB44D8009E764F950B4AA04A4C4B92FF156656B89E06B8C434409A60331C5DD951D57BCDDCCF26DA790E4A8371D7E43D8E9A5440EB7B7F6B3EC8FD65A030B7C4B69F2C02DEFB2A8BDC7E6B8D01533E47CC474C02E082130822C3971D2CC55441ADE5D8CE25AA51E7332976E9874312C27694B6B6FF0548351BF840C210076F08FB841714ED4D7194F1BBF5DFBD55F765B89B8082D0D4C1ACA0F5C4D9A3F8ACA797FA200C4E410E419F0DDF9F62E92E22B30C87C399EB7DF746B68A64FFE898B055FCEC5FE3B9745F01B3622A5734D2B78D54A903FC9DC193D7458E5958E1C3E117ECC0FDE98D6C1549009D99B068085FA3A7406728B342C700128FD08CB6DCA09AAD70FBFAC07ABBC4B8EC06258150A6B64844E013F0A6EF1D732C7E4073402E5CD5233EDCCB407C9AE5FB96459310B4ECE0193D9D3E72B3739FFC44F7553D5A5BF5B6D9AE414F992483B93447830588C2FC64729457B6262E6CD9ACF82A3CE3E165E1CB4F7D5C06D23490DB3E897DE3A194CBC35441490BFD8BA9A9427D83210E6C74E82DC500BDB8A41E2162152CA73815DDEA602D1BFC3342A01D518AC4D641164760FE7C418D4A7A40C0160E6B5675B1511FC44ED9BA572BE135278AA1B554A3CB5E153686A1E949A1FB395A83CFF149B8BBB1856B14CFAB2776C50C62394DDF09509CDB11763514E33DD72E66F9A2881F0DA23C81B355CE668157BE8379524CC3DC161C463146996B2A8DECFA1756989FAFFA1C0552D95446E965E1951963BAC65249BDC9FF54EFF5369174FA10855087604D0EC25A0B8DEC2B33E4AAAA9CE53CBB66335360C2063DD05838068E4241465669EB14A563FE68D3D2FF56B419F5E2DDAA0C232BDE7A069EC7F42F291328054B7D6467619088A94EDC687BD21995287F0255AF9A6528435B0724E6B41B1FAF4D9E1898F74BF27DD46E5F696D8656B1FE29156C857B39C58C7DF05AA85517259789628D143B6C98F759E51D4AFB8674664F9363B4C9C0DA6C9B03ED12A4E03AB0008FB9E01A396EA90D63A4D8635FE5E8BE16998C1EDE08E4114ADB9B9BCDBF3F3AA734CE8752644DF3BF8D59F6F2EDDC58B9B0D616C17B211375825845DD3800E14552A6FD86DB31A44F05C32D0CA68446233C0ECEE142DAF25D8F2533BD3D9474BE0C57AE07B5594C2FA1B4F11E8A4C0ACF0A33B52C461302FDE1EEC8938EE15A3880BF028CA3B3CB31FEE55E46F4EA61546F5451844E915D513D8BFA89A88B409948399F61A95AB9A71577C4EB1F76B122E33CCAAE7648937B5D3BB9A3437F7A69BA2C152D71C87CB1343777AADDE01C4DAFCF0634959CDB17314B355B7488ACBC286ABACBF300000000000000000000000000000000000000000000000000000005090E11171C836254422C7D13F1120012FB9CC7CDAA1D8B72F6FA3943AA7DE75263D3DF814BBF2E80C3A204BC0F9AE33E4FA82CE893D35C57E41C7147602BE12455B00B7949A3195264A3281CECC3FDE34802B28C6E1F2B505AB6087D453BD6AA067B2370124840BCAC4605EE4F14EDFC4B4FF19A4D7A828E60156B49B4027AC18DCCD20294F89CCF03D0CF47BB2F22D3749EEE69EE17AB5D8E4DFCCF36824D23E3F95E959D0494FFBC712CE3975E3A661B3F9E149A0234F691C2D820000DE97CC016C43EFE958DA469F740610FD22B64D4BD2E30075E22BCFD4AB41D952D2394FC629F016EE1CD61AAB4581F62A7B8648F8F8CF02462C81023CBE2755C91195A5917FE5A8B5058ECB8DAFF91DD3F73FE38665666DBF79CF6F203FAF94A5CA3F3AFFAA2C2BD5F5DBC011DAF46FD7CEB74B5875E4B5D80B6EDB9817106B91865267E78731662218C8EDE73E588256FB1AD57232AA5533D25BFC54452612F0C2AECAE6DE19355E1D508B888D18FF9F6D7D68199755CF5C210172F65342269ED96C77D80AF8A244B43A99DEB49B97A6F358AADFCFF6AFF72AB39540D375165185F31E0F1A6F97722EE365620BC5D642F8CDC59F7E84FD8615F4A336ED340BE6ED8451997D87B7904C1B9A3A0BD1F8A01AFD6A2D9F5B995E3FD0D44DF8FBC8389B6CBB5537816C91F0EFC3D2349F15EEE747B254C5BBF9418BB979294423DD6DE4D13484408362582A86D082350CC79EBCDCC05B70110A038736034CE4F3DC1D17E5D11C9C7620D40730B61437906933193D1272F7C89C701D495ED682F1335B7E1C42C994E090A67D932A8E825F4B9EDA8F2A94B9A1F11F10E91396908A9D436DD01BAE1D1DE2C6ACF458C0880E3F81ADC2240A99E6083C9C188982713DB243028AB07DF407218CA6B3C4C93989AC96D92375834B915B724F2A105D6240E52B9D7003C67FF76F7A325D84ABBC229266BB40D1DC8784CE1A4A6BD17972CDB26C274B06337D525F61B5BF952D23FA13757460B7B8A3B99EB023831F4FBEF72D62931348622041FFD12634947579BC6E16BD1EAA8E8B2DFD54D74EFCED79EF4FF31AD42036DEBD0FDA3B7F3F8E7A3F45955F82936A67122CD42E38AF646CF565E294F422FAC1E7D274185896F58E9D0FA1FCD3F4D379ECF5B566586246216556939BDF86D6A417C3BF77C64F95D7DE8197EE25B44EEF00209D33159710DF001372C3E3D09F24B9B08B8938C522690674A7588933E1CA37D2C14DF50777806EF6FD2285771A44F6DE90475C6CC314DF140C3962DD9D70C54E58CC5FA3302D69C80C6511D9D42A51B7CB7FD7FEA8D8BD65A66FDB2AC80D945FB7EC72E138F5566CEB570968D84B60068DF20C6CDA2AD48372DC97424793FEA8D2136923070C25F47C3D10839D1747B613B93530968D5E97A3FC0F563BFFCDE7B42C839EFE66C3A8655D0CEB5AF7A37D23DBBB52D05CF6FCBFFA7C7491703349819AD94CE218912557D6C87937B2E7B0473856EC78713C29A02CF7B2B38E0DFE16804AF6C2BA8607026892138011E06B4AF179D63DBD97CB917B6507B798E58D74F485D3F063C044211E428FBFFD5AF2D7941900299602D3B15D5D600B435D9A21948B8D87A35205A3AF9AA9BA491D56573A93C35AF6683655E04A7A17F1B9709ED83E70D82A3DF59A2FB7C051ABE508601F322FFEC089C49DC666BA04366C038AD59D397022F0F6344255F4D98BBB17120441CC75107005A74DB35459C63770547A4AFE59F2703894DEB67612448BA7C4F6FEADC1717F6ACE410C6BE62AC319CD33AF285D17D55F500E364A0ABE71D357AE0802AF464B6D2732F3FB94BDB3BAA497F2E44727BDCCA5A4B65AE9DF189FF1AC640940FF4D479A8072D34ECC523DC8FC7C87FC89A540485AE7BB3F29B041446CA427C0B48CA7515A1E31788E8B53E1122D372B6557F8D2A97CDE893B20E60283954E2934AF340A358A4376DD0CFCBFE305A2CE7B72DCFE2DE105CF44833F548D1BCE88D34B60BD29B69309DD87F4B91DE10EBDD7D7F87D6231307D0AC784E0496DB725AB97656C34E60B34B230F37E30FE326296C4E1BB88C0BAC261DF0E5F45E6E126103EED6B1CA146D58140A8893D847E92D9F3A0A883E8BF830147CEDBDC7DD42C1A58A826A8A827F9AB26ECCF64F68E9CA6B68261260B659B47E0DEDBF5B077982B24ED9B36E8466DCB21EE69B5E2BCCC49A163B4860EC2CCBD65032776DAE601E18ECDAB8E35C2760D5758592F6CC074298A97FC5E82E7DA84036FD10E0725A0E4E58CC4DB30499ABEC0C7D95D88BAC2C58EB093312779BC1B8619FF2762FD1FF009273456D829394664C31FF6D7848B27174B36E59FB65D6BEF6D974D5038A28F49AD465B28857CC12BAAFFABF3652C2E22B46B040E579FB040A0FB4B1DAF0C157D35407C0B78E305CEEB232E7B7426C95639B1CF7B079E80521FAA538E51E69255576650C3A16E143D0F815D2CC89EB00AA13AF20394AA23CC6AA99A9F297D886AB9AF2655D53816E066A02CF21C277DADDEF3D7D0825D094FD8FBD5386139757EFD0B7F8501829725A4B70FF1DABF2958E07ED21DB76266A88483EE7C51A7D215E1B41D2464911ABBB1DC71F9613ED5446E4B0C97BDD47F22B372FB7662956FDCF3B108E0107F74301A054FB004925B041AF354C04C20FD370CE1A014EBEBD8311F3265A2F78B48124521A4AAE240D3BA9F94FD33CA4A92D24A029E0754831869B58F670435A44DCDD7BF75ED9FF06DBA52980DCE49C1C26BA0965DE3623F459E36127AC6AFAD4D5598FC45A95173D039CBBE2CDC7DAB2865FB6BC0FA8DFD33C4A826CFC77BB7F45CB5AA73377A27271AE41630DD3D4E2722581537FCFB233E5AF8F04CA824012B5C429EA498F4AD44AFC249DE2229FD7266FE84173A5CE44632B3650D6E1F278625D564B374C10C1AFA3F17432CBE4B65327C6B6E0CD2F99B68AB043C5C6C99D7FE7FCF940F4887D309D7BC0FFAA5DC4B90C79266514F46CA2D5477F2B84B04E30DCAFD0224170FA6D4BA9AD2A6DFA8ED73DFF9D5D40D43F02610032719A7C5646CCD453CEF409B4325F3FB6D9B9201FB115E4DFAA0B4D29959A44518774E94B2D4D6D06C7F065973BECD203F5CF6CB59F869340EC6BAF0121049DB3E1146234CEE4657C1B821AF817DA27BD4C9B1103C81F5B5161E6A9329D83D6E4DAE1F3299858CD201222D34A85E2991BDCF32E9771F3E701897F647D62729C9805CBF118C9FA727B056A7271A23181B92F033DE1EF113A856A884AD527B8DEB92085AF3DB509FDB0265FBA3376B31BF753DFA477DD5E247D939109F31CD430A692BCEC4D9FC7C5B4630CAB90C64B75496BC7CA54D5621FE3315AD03EBF1AFD6D436BD2DBCBE707B35F916CFC147BBB5B8AD2E80ABD692834E42E0724C8B901F5924212C4129F7451B9DD860A85855D1AC59F0B6B87A66B6A395DD81990AA3DEBF64C91CEA6862B5793BAFFF81677FA2928E950D94A6333B0E77A15AE461E710BE70AFCB9FE6E0C21C5AD188E439A6E5138A2C5AD17126E759D48491E3F3F93F81EEB77B7B3A6ADD96917CF0BEEA202EEA5ADB3D5593A3DC9FF1F8F05DBF5A2707EDBB6640EFF5B65A0003CCED2EB480942A13C1F1CCDF9994F1D11DBEF0D3BA7C3801AA508C17BCF287A928B635F475195D88ADF9F4C1CA7D3D1462DFD0F6939B89E5ED95F177BBB12253391876492BC01AFF1C1DAAF0A1C7821C2A4E33F52BADF51987E010B391FC984328E020206EE98E9C8E6763120055F99725E48356FD800E11CE973D00C800C353A5DF8B028E1E42F817C7433084C440E47532FC639172533DF35F0FF43257841C3E4EC7DD7F601EAA81E9886FA3253844C195A62F89FA5D292536BE8CACD80C94BBCD1A83C985936353C9233E512431A8863D7D8340E89307547BD10B16BF2C7E0BB01AB8093C70E4F4C8FD30608FA14FF072D81048391C07DDD82475A280D4EDF81F739AD1A13BC6483C3C37BF52ED52CE8D568AA81864ACABE225BC6467C79FBF43781F29B0C508E6825D4E56D25E45A8C0C6298765069FDCC66B2C5492FDDFFF69D6F5975FCD81041F30FFD7813BA3219B3139583EB588DDC57851E581FBD5E20127EBD + +count = 88 +seed = DEEE61A2FAC04E4D6B7A250124DFD91518D9B90A71FA02665E3088760BF69CB3CD7B6977F860A7026819D178623C9676 +mlen = 2937 +msg = BD2B4058218A15C008A4BBBA29592079583F684FEAD3E6B3F09ABFF0DBCA23670AE4496077D47945E5F1AC3CD4ADD5763581285D80DFB43BBA9C0730858293FF6A15915AB203FBE65C118B87EA37DFA1E06CBC0F24EBA3F43A8BE17FF1DAF4277CDA2CAE8AA924E852C9D60524B98306927746C4EB26DC9475E8A0D0F920F33E1AFF9D07EA5561E70865B2D8161B86FDD7638E7A72345DD72EE95BAE1EBD2C24D2A5510ABE3FC2CED397A067D215F6088D63FA63F2247427917E5C4FBA14F0A22A04FD0AC1D948507751F3523BE2B0A0CF2F96DC61F8187ADF646D6914667759D49A6DF9A327830EFFC9470CEC6C82EA127A8B0C6510203879FAAC4323145931E146D962846BB1A6E84CB2C31BC686E388C853413EA7D3EBF7C752C6AEC774637EE01F2817A5AF133928AF35F23FC3541FE7FA749A863A048EFED2F8CC2BA86520B97FDE0324C68D1DDDE1E430C30DED0B25664EA676AAC6B1F22925A40B319CAA37DD5DEDB99DE4D963630A6FB0E8B00AD8F2A2B9BCC497A00099A70A9DC190A2AB2A058930E63FD6DF342A625E9A095EE79137CAEB8885117C7A9FB8DF7A35D5A300D6F7EEE40578A7507EDC38A0D6522474E672F156FEDE7E1690C3BBDFF40342F1F3AD3C34325BCDBFF0A68249858C777551683A9F3AF225163C9323A4AD5E666E0A9F44C6496269038AAC5DC2767966C1560C5A09207406F3C47157D2FE5909346D8ACBFDDF3E3D19FE48B7C60E1C8CFB2EAAB19E736B2595D33A0AA034726CB6146A01EBF5CC72EB1182B9A4BCEF90A1AAF74079862CD775F8F773BCC490F6015B4D5469EE0BD95C1A32A1FBF283FCE1FBF6F8CDCFC1884F4D2A899F3E7A95414DE419D56462F502EE703CDBA007C3BB78F20243C35B882C90CB7DE3CAE3F0468079C546645977347BC183FB0A6CD24481391CBDF9372E2D6765B6CAF8EB0145BB269A47A1B4E2CDF9901D6AA284D919BA57163AB9929E715341BACD81F35BDBFF36D59A1EDABFF3CAD2C122386A6335348A3170337B94E4336B2B74E791981656CB5234A6F84DB4142D3F323000FA98BE61527F7548DAB6E83928E9DD2E461F08A5BB52F241BB42254E5746FCCE0F3620ABC69A6E275B5E06A333360F9B809562ED116AA6CC2334694AAA4169310ED6AF695678DE22D3E551DAF61C0A6C5F6C0F36FD3469A3B977F6D295E75ABB804A43E1E7AC4708208A94E8368DCA40856F1D43C9865D98F69F1C0BA9C8B33AC9CCD18D400D2559B1CDD82A0C875B5E136B97C02126C81A81EB5D1E421221564100450531DBD97BDA77C1B0186527ECF526CE6BCD0ADD5668382D984AF9277A21D40C06EB4BBBB0CCD6F64E90272FD632D47A388D301377EE745FBC9CB4C02E1F096DDF303BCA4E1FB4B6DF867676080CDFA6A29CEDD15003EE636DB8C74E7E293A087B1A5F62334585369D12D9876ED0F334C6711146643FD598F0D69BB3475D219D1F89066644897A9CC5630BC84C0CB5844087216038C8FB6750D0968D3D3E2D29D93639486C76DC045900AE1A13529E74BECEB3338684402BBC3EB36870E0B37584E9F309BFB0DD9B966F0BE1298DFE55D1A94A6767CAE5EB3120133B7D7B71C9F2A538A97F8548FB176B0E8923B14AF28AE26306214F1D392AE63C3736B9F9374CA10EBE93370C11BEBEB45D066477F374866C8A7208CE6DCEC404194BB1F833DE0AA4700CA29681FA0F72D98679DC3E1E142852347B01DAA08E5CBBFD242F7223600804E066FB5C98C8358370F5D390898FA44023A30F824F1C6A95B8E23308B4BE474D03E34CF72BE65F90D698DFE0D2828A797BBF8397EC87AB9EE00C76A1C7B3CED0100D3A1030136CAB9A69F05CBE58A4A56A9C700BC591B87783DE59369F2E62D5B885DA09F25835A6DC06F954C19B347724244FDA69E3356A4EF60F6A41CFF3BB7CB22ECB128415CD1B89A9AEC12B66F1EC23B14E7D7FD601EF7B000A0C96F386216F75710EB2C12817DABA1D1295E7535331CB90A9B0D8F7542E73DE2D93FE554063F57274DF27BFB39BC4B78B72A88473408086D8DF531E53B5BE018E076032D1F8EF86D7AFB8E8867B9D7728A25ACFB6856D83592CADA4494977678A9F4D134F49A8598A8E0F23D3B7A09B5308243410CA6F47E0BF8C43871600817460BDEB74E7D32C2FF7C40EA4BF924E795516FF7C7BC8E5FD5D64CC489F1894C6BCF0E9C312B1EE7E2BC68739372E7402E6AA2ECDCA39C18D7441F0FF373946559C475E37D4ADA64B98283E5A64BE7BC2D1A1C148D2CDB4EDA35F591D3A7E7CE15162F50FF1B025F87CBB82289FBE7F9C32DB8F23012CCCB87ACA7D758D42019B9A8C15F508CAC9284928F46F0DC1C1B6C6B4DA030DB9286FF8D3762EA4A83D096AE04F98E9416D3DAC59E04F9E4E4359AD76926BBD9570A3D5811F69A1C4345B646BD946D0168ED62A7A431D920D707D8CC7E840BB9CF13D8ABAE8196D9177E8C28CE0DD9EF647EAAF0D3C97E52CB31B560EA7067B45AEFB5EC2B7C7BDFA3996D1C7E467636BFA1BBE11D1CCF86B64ADE9FAF9287A23502E9FF711CA97D6CC09DE814A67BA6123A8E4E67CF6E8CB6F7B36621BC6192ECEE94D61860703AC8411B16E19644A6AB01813402629AF52301C9D76A94CEE22B1DCA49F13B130028991C8AB383C8461433383DA92AB34F1EBB4124B24C6C391EA44EE6E736BBC7A2D4660A878A600AE39B7DCCAA51ADBE90BD705EA51AD13C05E611749D43DE336D396352CB0673ABCE7473DECB0FC708EF28DCBE18C85EE0068FEF64685ACC3A7D0DA9A21DD0AFB10B95D81F6AE437022218B6094CE35D01248EA85A9EC6FB56A7A2A8453EB03E6CCBEA0F2EADB015D8BE3D09739EAC07AD9E3F17D13E5F71CADFA220ECAE90EA50BEA87B19CA6FC5DF31874D51723BECC80C8845C9EA718454D2817EF8AFD99B63090CBA6C8089AFA78770222FADEE3B3B829CF36A8153EFAF2CF28DC4651FF37A8921E402EF81A0F457FC1802AB06A759BF4071F082BFDC100AB612A4584B5AE19354854101AB0173D7D6A5A0637CCB58AE58978A8BEFD5A2C51D3D53150C336C0C0C2A27B442E2BCE120C4CCF8D97EA4584434A6F48C0245B63B2255BC52ADAD4EDA9279412D70BE457F7DCAC492FE53C06EDEED766B46EBC3419E6DA2A2847251F75C62A5FE7AE74F0DD5AF50A447DA6356DCC828C5F1A2C0C873E57041EB1158296C038B91F2E13D3D4B2887B284384A9ECB8BB378BB311F4ABB19E1B90EB3A399C03BFB4CCB29AAD80C55C1636559FC79A6C894B5BAD8D529BF680631541A45EB0E57BA5B458A05F456C60FBB593DAE90AE549416AF96642A486F10843482AFC3989BBD1E8E4DDF0791204F4B720ABD2D8995C87C8A388ECB14860CF83B7A4406FB6C8C9393475082D24E516C5F1AF91CEBA444D8E460D0695746BE057EA8D76F8C0C80358F3DB2AE5B996272737516EF5E4EF5A1FE5967304CB6D00090C9623D29F0D4BCE8CA3CBD54A30F9597E01E5845C1CDD8777E18C5D5D86492FDD0606F623D11A28DD9F02032E3A378C71B757B52021DCE6CEEC63792CEA24D6DD7150AC8FCFCA6554F7B08A5529D59628D0F35122504DD1542F6291BEDBEE09F81AA744A0F6C6DFCA6207FBFAB6B9E17E8A4040741F6508471E72D227D0FDC50C13F444310245AD17BF819FFBBC4E0485FA68CF1F0A4423F251538F25DA989ABCD008C803D368F626438432569F12D1612370E4C6C971079371081B37D8DF7EE709198AAA2FCBD443B96732AAA4E6924A461B60CA4F4CB13E88D539AAD709A3DB84D2D6D26671A9F3877125B7A358389BBEEA846A32E949DB9A7853DBC7D5ADD92729CE1B5C00680974F3DDC6A8235C7319B6CD1CE5E0B66FE7C2F1115206C42B4C02990D79EFA8BE94927543C19EE93D0EC8811F9330693696C878CFADAA2D56E877D42A3680AB2F6A576FDA7BF7957F781655CC664A0A4A0D16CE34D04D7C98A9E0C93D2E6D42870FE66864660B564ED4F881693D466BD68B6470AF03A5A6E703DBB40515AF5DCA7142C4C8D79F5BE4BB01A1B56BE9D0936396A7EED9A84DA86A4F00DCF676B4942D5DF6E1378EA26D9118A54E17FC623B83AADB417EC82F9AFCACEABBDCFE2F0B6AD4BC1601B4E24F547D61D1C1737ADBCB46D98287372C +pk = E9D1258056C50241C5BBCD8E50894957D9BC2BC57AAB3CBFE624AEFFB4F7A0115B5A8C1AD354C8957C3DE55F0A470F3B2D5AC10A0EB7D6E7ED6754FEB5E23222C3EA3B9652279DD70A20C1FC37ABB4785AE3A2E217577E6E0F8BBB6838A9DB71D68796516F6A0C0A54D775236180CB19911E0727E4ED977C000406E3935D98AE2D2B4C3005A55473894D6C94DC5C13D00B240A4FB57091EACA7C5DD4BCBC632B8CB1DA2B9B23924F13954F1457D18AB3CFD18F51C28C8AD65CF96F9AF5465D596E94E657339A3FE4C0D568554AB2F14324584E4A0225E1C47AD9A135517E67C7377987AFE4AEAC36C103FBE6B7D0D299FC4FC50E343DDC0B8688DCCF2632497AB56164055A51AB02C81F22ADB5C6CD53C8F7AE420AAF9D006B106FDF814715865BDC51040BC52033930A8748D679F0A9A314E9201E9BA03062B042185C84064BB137FBB21B4A713F3CDE9DC32C86956E6A763CAF17AFFA1D840EE6C05EF680258873F2D2CF134436AF997F88E006C68FBADBB69F3D18709F20D41B4EC51482242F78A36D9DB9E5EB0673CC6E1E2C1AF50929D37047067D5009627DA65768A5D6A244097AF535355D73CA6295D5B02DACAD014A8D38732859E9FF6B6888A46168D1CA4780388FEABB34CB909C94A8FD0AFBF83CC5A86503B603D191AD62A8E6CB4F28C577B01604DCE6BC9D196BADF872CE6452A0D7E513CEE0A42A2AA8AC091062D02E970BB2254BAB4398DEBEF8C52788FAA7FE619000E8D22A46CB7E1CBED9B02096525CD44144A79A5220DDE2A3AB32A75CC691C8770D10574272757ED904A02B2C439B7DEA42552FA561134933ED2131DC5B4B5EF9704022BC72B65E2CFCD6AFA16C11327CF8F3754EF53B074007EAE604735232CC61CAB268499F99FC8F18D9918B14BF26AB6474802C8BF769B78B4980946BE85880993C4F7088FF331FAA1448DD13175052C50A39B037EB76F53DFAEB54017E4981578A78D81FF667A1DF4881504BDBB6B941C7E8048E4984A2A07E37D08AB05D92F392B4B7182F353481250CEA817671C98CABF48CE2350C55C9479110CCD04C6FA4809B3A928537CE4153E95CB6DDE3437A177144769634C7563CC69E2AD98E6E44A4324FE0A6E43D573DF9621720CFE80196D715A996A62ED1AAD055F1570AD9473655674359DDA6BC4149A1B7F844C9392DAA5A5D6A7C5FCABA4D456FB264B9F1FB0AAE2FC1EF5217507CAE77FE4D4ED5C0DF758097BA4562854C7FC509C9904A452C8990D885BBE00A3EA7F16BD6C05FA79DBE2C9181339FCA0B96F5492609176337EBAA61F1DB321AAAA161A567017745C9EFA8865E5B41BFF73D93D137D29CBC53624BFF56DA908CF988645ABF78F23485411CA5EDD55AA31A16B29213B9E451FF5900B3408AF7FF3409FC9E41177B0E00E9567694C59BDA1D569ED67A1688217794BAEE05BDBF8352F73ADA80A33FB7C6D5743E9A0AFFA6930E59941A948626D362137ECD4595480FCB9BD5D1AECEA6CCEAAFA5EB9991D57C51F5BE852F0DF854DF619CEECAB33647AEAA59C930F6D113E857D2E8A71BBA2C2F28D300ADDB3AC0465BBA39818E5C0A4B6D4581CE19420CFFCF82CF8315D1C71721DB1230D8F5EF5E885DB8C640D9A6EF625C600EFB13FAA18D26C73DECAACC91C6022DA61A9A613F77A14DC8090709CD38A47399AFD28D0F7BDC532DC3E49B6310DB7BFD07344F0D2639F0D97C1631009E8AE3B696E93F8AB4CD00AD9235A124B4E08AA0234E3EF54B9365AA8072518DB439C701ECA46D98FA7D6B11E236C873E57C971F78D785213821DC13860987AA9415AD29BCC601B1C272AD7D10A45E29591C486C9383A3CC7267F1A2AADF26254EC7F5897253473B15CB5FA778EA93436E6CE114800815BD0595072B205BAFF0FFEC5EF5F670D32ED1EAAE8EE598CE53A6B5530DDF20A9481432374D1D4158517DA3DA291E74DB9A7C5D226D8AB0A711D5D45C40E8FA1E6828F23966EAE37375DCCE058779B6E5B86B33DF919C10BC6BA2BC8FCB20AC0B237372BC83BF3593918B62D04BCDCB1A123165802A8E1CDBA71BF52C6FCB00DC228E46DB41035FA4F6AEF4619B0D1E4171AD4BDD64C22D9AC8669791DF4A7AB5F7194AAA8DBE620A703CC3A24F404751FF122050BAC9FBCB0A4AB2C1540E2DB7F9D73EEA419BEA7508EF4C9F09C893B3C13C29E2DE938271DCDF7F4EC070C83BFF2174BE564CB86C7A1E7ABF2E5A5530F729BE0F82C5E3A1B7206127EC9FDC2B47B01D9BB220BC0BAB75384923D37D1DD0F7E85EC6324FC4BC8CDDEB45AB413754636A8FDB4967FC70E967DA03172D6B35756BA995D468B8D858D13B9D32AF0453301EB9F523FC6B78F0B408FF11E1C1622A258A6C315B51D266C589E9CD976E50EC540E4AF2835E69FC8560CF0D2E19C356244EBC9005B6B16692D90B12095232FD3089016640A53352A8B1F5C2E10D00909C2175FB30630E74EE5129984D89FDDCA055B27A3C333237F8E359A39659703E3561B8CC88EA9A23C4F9EE0F6248E2290041505E4D81DD6251ABBC70DBF8C602E382EFBE78022A450501AE77AF62E8443A41EDA06DCB8AF6E5D205AF38066B75A72C64E9C6E3811D7967812A645C893E090568527E33C26AFEEEEFDD68E5B698D6483C8015737B8EFDB5094C8CCF8BD826CC78F5BD7E0FF4CD06AA849088231963FCF6F9E90088CCEE95B7EE07800318341167A5ED1D6DB72A11EE6C69AEB7F2D113E8F2D310DDCE516E56728A61FCAD5B2F9F +sk = E9D1258056C50241C5BBCD8E50894957D9BC2BC57AAB3CBFE624AEFFB4F7A01143882EF9499262B4D00D5AC9ED46BF8E0ECBB0B7E1203FD5FCAFAC5105292921608C5E7446F4A30F01ED5402C1A81A2E98D2F395526BA1A590C28BB8808C4F3E245FED7BE712962E8D9D9C620BB5520F8CCBE159E96F70645D157530AB9E87CB8442140332543751325573687811112660130118465517555584870384630422407575340572300781252176317530184106428455614372142742626513516161268335572206426447030143702375568281102280803345046086548620280670350677300335277320220085420273504331056186175828134404425118807453664737642475060118475178561150261315667230418011476546516461310016618455166430304770530830105526062114471830476148864366078634362308886218775028686151318121402751864862220673631487641127037474186888001711126451311040506436835438711848810758588674348742006823300813686741780876104865255072383063145277686747313510732764041041347705588245475068311412634673773645463118654361185373336688508047048224448441121608333543300015541851211228805700043846275381756771232241564812028382406506627867558382013600838217645833320380754188284814172631686108010024708343431604316345381624581451217414103211126220721202280287874128178814020214140888235436654288654711275365872882470235233347568180212410182245186434271738768630415680778045378441833504146737657510726887365421358374765618845056134250868021508518051585377181673628644747417515440078140252335027446200752370635143738630008180883363602122366573655534538718206161755145332114564515004658843742618740785217178834665334082057760224728334477758262885542314566872424153757508740031808183033306444434013242127407378410117086307357160843772150725174621165778370353448322384333138100355282765707463430406060415547836313007013811830107113268348823166018871463230512078404544551528278715211032380247820180410670856174016721403278352338374836115020141772200688635056075787443762646021788407688418270146031807455344058404477572373030113818084814548778611556120883322253812404632645603561256072140506702785607777285571063461602520800761460346623876365580585717785075268884653410333558615064674808151625854484545252211443444714102051753843028577013754552853056534213835521580606400646666507656200313201107718124847788856678244820325144445328704505841761308785757220131155122047047503844041705578022736427503712078326064416257485808035330627058278840165277743420201557042343624686783533870551525105177347661866206301264234731238331573041031525287877616747808334846875602158452366101884075166528874204152878415114173440650655178482251451280647136220353055608757071013336325265681202708228063710166373610072702112310386485765387314173335502176387043255877183278881276258461614486258366716673241215100481247108665321142016145317081383564316757300776056588307100554775760220855866860730351723703734052157810226088505272767026371272704612301624337731577434738884141458440715533622757585753403204533404652533610233627437807337872506235763850580876034261850356254567446505855215658684230603404641488578057264238405754262246565584532057051780716554557413210126066185020800723787236681306633147134683108772878505037761553186788011328881E217BBB639215D8AB97B5572D0A55405FAB448009751B31493A0CC504D357DB549A5B0CC6B48240D0D436937DB497524B1BD5022C35F8E79F2BBCF28469E676C6478B0EBBDB8B926B821A269CF30C1DFCDF579A8E8A43D30D5463B877922014B08A31B2633D326EA5CA50DED5F4E9F8161B6B176FEC5DF6E5612DA4A7FF6294F381EC4529B3B537693A5802A3CDF48FDA0CCD269E2BC3220F38EE00091ED1CA51E8A0CC7CA8F656A7BAE8BA0957D8C97EF3D20EE65831B5E11468982F12A076EDC6D0F63A2BA59C28D23A191E6CBD705B3CDF0E0840E763A628A8D388A6B79C2972BFB04969631D2006C463CAE328E39FFF8A0ED0016BAA8493F887BD49C3D6F9B6934085C6148ECD1B190C54176A440568EA16E5D96D3C9E5C0A2DECEA724957EFBD86BB6177B52E305CBD3AD2109BFCC7C1540A5BEAF1C50E51275D647AB530382B218AA975E9BF86045C6C41440A0941327C3311A3B093B87028BF0005269DF2B8B9BF1BD48DA2973288112A4A5BF4140A3B666D1281E3C665154751268681BF23CF5F7E2A634D14E9D6C7387AF9EAF2FA5C2F005A27A9E7F1E17FF60140EBF99D19CFEAFB3E63E11BD400E5092D4BFBF60C46F5F6D0EB5738FB6BB9C59CE2CFE52ECC9F7F77392F61CB5D1E935CE24F2849FB75F11ECBC4208EBE8518F7730B83E1712F237FA96665227328D8D8BAB1F96C52E6198930B987EC36C6B8A531619CAF8BB65E81318EDFF225EADE11F8BA472FA5FF91CF5355B58D73D24207671FB83056BDA73260D7760BE7DBA02711332AE79E132A561A2014C2D61FD2F9CA8F009D10C0ECE3DB758B9FBDFD445146AAB893FF2F78CB8A7FFB743BB029D5CDF5979150099F4C0E419C0E91969C17801C69E6260A009D2AC3694A05D23E37A492DF0390F8C524672A903AD7F09AAD70655AD546886CBB3182CFD8D9FBFC8BB2E0DF969B3F4FB8A174CEAE356EA20DF040C705BA8D063839D2251462198C02E8AE1AF775198C7384296D5C18E7B1EC9B689D227D944A0B2DA02E1D84A2B1E11DEB277DFE35813321CA72BB045E97D6974B9BAA1A443FF1B4031096C11E5D6306FB100D753D738A29119FBDCC629C791F19741D3EE0EE9D5D7E239B118BBDCE8552CD8AC0BA0A8A5314B6154FF1E73DFA0307D6553B0B2302AA195B4FCEC31C550724730D0AC73953F6458B39C7BFB22BE5C314D6DF324BC0CB7AB4A239A643916F16D78E2D8EF53516A6BCF44208DDFCFD755FEBD15ED227FDD843465A9CA7D02CC7B62F19C227E21BEC6AE2073004008B37108823B42FE26C14EFF7EF2C06D20AE8030E07B730B37B3163D048A5048A7783460CCEF85AA5FE0C3B8D15A0E82D56A0D37486F2E6C0E90D27A4B1EFBB07F7F7D41B51861D45EB5C7755978FA50A540F6BC6D5D1596099BCEF8B35420A48EC340A8F385A117E20AD115016BD586F71824E86CD01078BFEADA57FFBE6B228FBBE8C8ABC211EE709F6D3E59B055239B6CEA204A909E3AE65DBA6857561DAA8B3DF2A31A26961E08D6F7F13CCEC2F3D18C90DF96F45713151FF587AB69AB89A829B9165186EE5F839FD5878142A55094E571F773218CCB291DA19953B65E71D4F0BEA4D8ACB386A244AA67C6CF5C40BA9D0F2E32A9ECEF8C8D21B2089F1FC10577200A0776E436EDB1F68836D033D0554B99A0428531DE1DBB5DEBDD43A6B202452ACE08D6F970365E35C04C2241E86813C6178EB5AF0550DAC2259E709C88399C9731E66D5A24E03FE156963C75C702F3A9AA49E6462835422A0750EE803DBCD0398D2F46D5A0D83F77DF5EB77EE1AFB7548B68C98054572319890EC8DCC7A3586588DC0378A654B34F9A69E7282AACA3A744CD3D457DE1196194055396FD5FAA120C330738E41FAC2814B9B741F4D7E2FC93355E1653C87D22CAF72936DC37064F27F0F9B6DF41234256536AE31BB35FC16C6302D5A686478FD77451CEB5394D5DA295DBF0FA9F78FC6D959E07AF476230D15D54EF8D921F5ACB21D53FB5E8BD8FCE6BFF9D44D8D3E97ECC4CCCEBAF8DD86AF9256C045AAE545473E62C8F1D253C74264D76D22F055F329F678D878ED8B5406B032133A6BE3ABB69611B3E09883E69F813646A5919D668550C7F90465BDB4C0BD1F3382883E7005D3F52CFBDA94F2D2E075A31C3E1DF13C8BAA8E8EE529EB5452455CCBB3C347BD18E0B3E5A2E97A43F1CBA1A081C7F6924CDF88B381ACA5780EE24887291A4C34911E21C4FC0B1204DA4E53ACF4D41BBE9594BE832D4DB2123B32ABA770CD252BE24947E3463755A0C267CA834C22DF32C68A136CAEA064AED4FE577BFAFD10A9913B81DCE7C16F1BF1B2E4BF9EE47DB14B2B13FE83A039F72FCEDFA1D8CB49DB687974E417F634051DFBC414CA352BC04EBC59D6F2029E3D6904936DC99C48389332BCCD79F7FF1C8C4FEE14867F56E4D424D2286A66B3D55C5DF553BBCB0A233AED0D51289639BDBD6ADE8215F9FF64ED03ED261CDF8AB6C243F6246730E462BC55417C6935B80C67D9A66DEE6F3F64EBC848A84922361ABB33C0AFE647E54057045A8A1EEBD891EDD5041F0EF068C708176BBB99BF0DBF3CD755E1B7EE457784FA4C8EE4DC7DDCDF36DDFCF2441FF37DC8DC821DC4DF1F00AC622F00E8A51D51ADCF9226BEDA6AA9E717EC28ECCCEFF463933D228070D602B5BE5CE260594BCEF95F2D35FEFEC206944FCE0E6546274C98F24CDEE7527BB1AD1FEF88B6CF8B749F4E01219391F26673DEF3DE3F535668B0AEB156AFE43190B1FB03C48B5432440A461D9879C09156C76F3D197A5D2DEAFF7B36B721EE2227EE88DEF94B5B376240068279C275C0F8EEA43235266FFA7FE4F6F3AAB088EF48DD48BFC8908E8E69F16EEC5348AAE1B2ECF8F6BB80393C00A48B9E0563547C4CD7D3B27CB0F57235F01D195FF2E552C9A6AB4CAB325CA6DC9C600A1C62EDD002E55357DD6BFF901CA1357172818A88B205F45EF3416007D3CFE9670634ECA444F6DBA662FDDF2A0B6FBED747B7D166232FA94B634A6EE6FE1EAB1C87A91E9EF5A48F36DE07A1390588B4F0EE1667CEFBE49A488F1BE1B96B2E826C7B9518D9D1FFF027E6214FE6AA7023C564B472D1557CFFE625592851EE445D03FCAD928F430306A32E34B6CC8B4C0D4BE318A9EC39D01C2EF7F7C76396BE2F6D415B24A478437075C6F02B2E56791C0E5C0FC2408FFF75DD9CFF502F4DC752FE7A59926D817C111C60AF00206A8321C27EAA7B1650EFACF15491701761334C692AAD1E0C97B2588ECB0C8DE4D821460B6B92F4D28D61FEBA41A5960D0C8EEA280FB0D6846468823EF47ECF1E6A6FA092E7EFCA804100DFA52FFADFD3987970A5DAD817AE2DA555BF1E07CAAF97939B5A0C57593A84891806A95C3FDDEA82D59A8016BC8A1C216B7536B1096921DC81419227FBEC5FC9D7B94F6AD1B1563AB255F4C293D8A4F793052C8B83450BE42AE30A7C1BA1FD5973A30FE06AF08037F4D9FFA7A39FDE170B955ACD00E94764F084CF2BE722AE02D9A2F073F38DF3A96 +smlen = 6246 +sm = 4B2703E30898037F7AD1EB50ED253B0FD0570A26038480C1299BFAD50F945F4B7A13FD3704FC65F83C9E859B6EA6445D50C32640DFEB9FDEA94CE1D3B7918D697795E4312129191B0F523CE7CCFFAFA3FD5CAF19FADA13FFEEACFA6AFD9A806CF6D0E2BAC7D0ED645FAEBB3DDBE97946618BF20F51B227CF44DFD5A3F8688F9BD18B8D2853C11B1119B0C89B2265236254FA00D6E777679486B7D8B7677317D69C8290178B5A3B190CDD4AB11A3F391560DA6A6E77C61E42926BDD1DC628F1EE39FAEE3A38382D6366B605B282EE86DE8ED6F312E1796F9AEACCEB191D0ADD3A64AE2C6E5678FC033A33A7A9D042091AAF6F62726BCC41CF1611884348F8DEE3BC32FFA3CC2DD1F9E2EC34319AB99734490DE61CCD049A701E81ECE73D476C4C322ABA830790BB5080AAD3500653A1FDD769A9CD9FBEA0ECF8DEDCF2E07F9FAE4E40E58F2E28BB302F9596494AE7A04F8038767A06D96829F0DB7126A80FF7D8FF6B232C0D9FE101CC822E0516A4342053A0F959824290D66616A125577E7AD572EC8329A3C0E4E5F9A76EBC555ACBE901A23686CA9EAC69524E0BD7E7DEB6C78F24844377FB34A4AC18B2BDAEF697400C80DA14D39AF02881CBC41BF9D3F606BB0D90F15C5C2A21817A00A167383FC7EB5A931EB283441C34360BE9B848E1E4A80F51DC1A3FCF08CDBFB1F124FF3C79387041F7E7BBF7006CAEC634B2D5C295D18651F5CD40239CC32FDCB29442BE67FA257D4018923FCC1849FD8F454031343438C4E95C627EA362E273D77A8C2C4D746A2FF478D346E295442E5265C402C43B21927A932C142991C2ADE4F61D2CC8E5D78923B98437A6AA2B407D462429904D6EE0760A3E7AC4FCA8219FDF95C57FD9B913954992356ED83E201258D41EB77CED3379D51C4962A17247D80915AA4F1DD467456FF315E1BB23387685366ECAF616A7FD1EF99D49D8379C346BA8701D926C6EF0844D020947934ABB7B501022BF5BCAB0A0387F33AB13BA7B3B02DA6F3AFEB17EE12484F0861A7B1F1766A713663A40DAEB2DF2BBD51E87131A4ADD6F4756C4B6C12B2294F64FED670A69F9BA6A55727714DE5E0B64EFE982C81E9E0118915B051D0DBAC539B67E5307482DE73E6AFB4CE13F8ED62E4FD88EE33710673DE97B337798569DFBECAAEE6FE5929E6ED9B4EF9279646AC847419FDB4A5F79A1C5667DC80E553DCD6C14A4E0EE3671BCE9C28497FFFA5A8B1B4C0514AD465412C8C1045D0B2516DF558A1A2AD42E0E7884BEF0537EABF75968ED6AE3540D7EF3822BD0CF68A5308FBFE39804AF12AB56EA3C32BEEC2CE8378B60D80FE0AA66C8A0104D82CFCD476D8092899155EB25C58C3342BC1DC24E0C84EECF0D1F1DD8E92BE0601C2BB47C4E91485720D3D25647EB87981908D7D2B7F683F96F007C730C0541F85A218E15E774414EEF7ED8577FD40F65A2B125AB8E18341EE549CD8E2CA0A54505E96EE79D41F97BC3959B47990897C20904A8F6924F307D6766B54BE09B68BC410A1E4EE1E61B9AFC56BCB3FE94DBF0BB2AA726C3DEFA7FC3E89DD61033F246016017D6EFDB08A2001ED15E3435A94AFBDA8CC8F3950239C2608995E1279269BBF388FE86572015B8F64E275CF16D674385967C7D70B13C10EE5E3F3F55AB54DB7874031EE97428EEA9A3806467AEE0D4872FFA31E4AEE7062FD35032961511B7DC08F90325E4DDD763438BEE84672E58C07D93802B60AAD7AA5779C2B6687381C3CCB68F3D7A847ACEC43D3EDCA11EC3D65E4336EA057128498E89E6E46FF753E4B8FD1FF75807CE0F37F4E20B1E3194E1FB03A1AF650C4B64641826782B5D481A41D2A192544253EA4E4BE8DAB0D4AB2CC22AFBBCAFCFEAF7F6C5252068D427EF2B398606C8289E047B064FA9B972283D819AD128D845E40C8776BB3694B468030EB2F81A18C1A9864D21BD34EDF9B2EC3143A0922516099CF40D2A094A7B7A61AE62AF8CF22E12DAC1F24F5C5AD46BCFB831ED260155C53ED58F641B143D01FF6D430EAEAB3FD3D4FA93985FF8F1C2A13250C618256930DB227EE9B3AB88313563C5BAAE2E395D9E5C99EB3EDE1C6AE591B6A5096C12B33B28BFAA319B8A8083732338729AFC727C407FA93575433E1FB3D4825AE0A0EAFF79858559D5C1B3A40B9EEEA3DC71C001B1B27C731A906AF137A6533E8354D197E00904E21E8C0B28C68596A3AEBF1B1142EB8441146A262CF7CF006B296B2D5F6E88740262E2E4703FC615A50185B206FBF7AA9C7431FE841EAFF8597F642974A9B9F9B4B5ECF832640C5E0F4F040D6E78BEAB0E9B45342BA9EBD6F3D0CB72BC7BD92B0703B4E44C0188AD43299F377D66D86968795C96960C9C6D34ACFD55E5DD735B32FB51DF7FF5A3EB268332BB97FF962E889C58C9F988A0649F3D180EED2AD3A25E9DF3DD5ABD1F96FF6E2EA593D7201647629D63695578F5161168378C73B810A4737B087723037974E11FDCBFA130E495A3F1379A8E238BB54DE8249992D86D20CA1A1F79A48CFE944661212287FC88F6DE1617F5A0754670321584939D264FC8D7B314ED9A035FF039C07D42E470D673B8FB48158D20B473E9214B338A6D93F59C7EE24DE843A6919853791874115225FDBC12B1A681A9B834FCFF52AB69FE64DCDB8ECEF0B0A15140A362FD528C9C8E3BA2574AEB7747BEE6A8C32D2D156AF812ED41D7F104E24AE7AE8B93DAA118BD2044C5E5D4DFA410C5F77BC2A516794825E3251B23782496C1C11ECE772AB1BE6877AE8F189BFEB82134651AFA95D0D5E5585F606EA0B5C48B96B5103D4E1AF4DC35BAEF1FC95450A578242A470E1953512DA95B1BBB77B298E21A7AED062FB426D5276705BE3B4ECAEB0ACCAF75DE5BDEA5CB70DAC38F364BE12C097CF7A9B0B1F724E3263D3465BCBAB57E737D5E65BFF88AA030FC550E49C575A9E03DB294FE09975BC084856E14F22D8231076D47D0C9877BF09FDD2E29661C9EE8917624986AD32B9D080EB9D14A1A63671DD49A974F97E059819E67CA06B82DDDFB482271676C40067D09C368C7F354D8F46864F88404B72540EFB963AFB603FDA156EA30832B4F9E29CE28D53055EE354D1ACC40B9237141DED7DF49E0D23D578570F752B3B51DB08D8DE99CC5C526A6E4F28A4D61737C9F4851EA565CB6C668E2A85C486179D1D1960A8DDB46FCA5C676CB88BF548A24D4B6E03A61A38D55638EFB76120587CEE8F06EB39223B17BFE5BF3F0027C16414497DAD38A394985099DB7010A5DB7C8A6CBF7F393DBAB5629713E53149583065FF97E058BED59BBC4BA85C56537FA25DBF1E8D595C103C1F4BB27314DC20F0FDB115F7783324FDDDC78CC8B2423FD0F1B2B28CA633AEB9DB83FC11A8E617D0B0BA1A2DFCAD7FE37ACF501C37338D5F450F8FE9BAAF4992DBBB06212E43AA333988ED3D2855E6C40AD90E037CF98BBABE6BCCF37143CDB2F51C2FFB9D221554696EE126C047806871D1B9A8C2A076B0AB33D41B4DDC1041D609DC7F5BD2841114B8A1245A92C022B7557B0A185930D68E8DCC25C5A2E096155CA7C681C6973D7E344BA88FA078570445A2BDE5777105C67DEE22B33DD6DC51AA669D878B412A68DFC82CA3D69E1DB1D2B337E273655110ACBC68A3ACEB05CE5C0EDF5EBA689DF5E33C3D936E62A2B2F1ED017DE880C0FBDE22B0C1B6FE6E3279FE7F21A78E8BA6D69802307E409D12EF5B6A9329CCCE3292009B103CB6294CF918DF97EC9C6B63938298E018720BF785279B8886573BE6D90CD2AEACEE9E202BCFCE2855BF98D83F97F6F86A0CA0512EC4701CECEC39B4B24D528B85020B2DDDA7160B2B7BE2ABD8FACE0A0459CDE2B69DE0E8F4284AC7B22B9102E9586F4C200211B32EFC7EE61DFD9774E1019290D00209F6663BFEBC1EA4E81C98B16557D68AC24C80880537C9A0D7F51A6B432C65A69A156E820434CF1C929AAA5E008EAF43918EF4D4002A3F8BDBED8F3A616317DCB1BEC83BAF0956B029EAEE4885FD81F27D714D98949C5F062AB3CAB659AB0A231FF3B7F942D95E30A8107099B6FEC4E75F87F9AD43B820961F4F10213245771E4DB499BF8675EDD8B4C7A235B3CDAB1A15583094296FCC639E086BCCCBBFD6321D004B69A222A3792BF44BDC8B0CFB5E106D7C337AFE19DD36AD7D2BD46C57B92FCB998703B503E6C6B9CA6E509FBAB80F02641BE13E1ACE91951F3594762957CF2412EEA72FDCB8C9D0F79975A4CB529B6038A9663BF6F030ECB4EADD584D74669EE857A1452CC7764C6797A02541D91DB79FC408968575C5076F78CB826CE7190B513BA02F670C61BD6946D11D858BACC3B61A5AAF78B446BE76321C12C41916EDB2946B1DCE840919AF50B5AA12F3BAA745D4B80CD2CEFD2808ABDC135F2658E4897F729A4A13BF381723A04832A0620FC2729DBA047C856C78AF0D0F9B232A9A5235EE1289D86BBAFB5BCC9BC8BC6FD9258A998A2726D7E9F37B35F8F85E74A363D4870506ADA580EEE1066129123AD56DB64FD70D87B18DEBD406907734623F73365CC50E78ABDDE8F627EA12CF42D5884F8F7DC8F3E6FE22F79B8AB688B22E712CF8A343FB0935C024C70BDDB080966ABFC1C619DA7EA0F275E768D98BFD0E70990C9CC3E467394F4FB1928757BA8E70000000000000000000000000000000000000000050A13171D23BD2B4058218A15C008A4BBBA29592079583F684FEAD3E6B3F09ABFF0DBCA23670AE4496077D47945E5F1AC3CD4ADD5763581285D80DFB43BBA9C0730858293FF6A15915AB203FBE65C118B87EA37DFA1E06CBC0F24EBA3F43A8BE17FF1DAF4277CDA2CAE8AA924E852C9D60524B98306927746C4EB26DC9475E8A0D0F920F33E1AFF9D07EA5561E70865B2D8161B86FDD7638E7A72345DD72EE95BAE1EBD2C24D2A5510ABE3FC2CED397A067D215F6088D63FA63F2247427917E5C4FBA14F0A22A04FD0AC1D948507751F3523BE2B0A0CF2F96DC61F8187ADF646D6914667759D49A6DF9A327830EFFC9470CEC6C82EA127A8B0C6510203879FAAC4323145931E146D962846BB1A6E84CB2C31BC686E388C853413EA7D3EBF7C752C6AEC774637EE01F2817A5AF133928AF35F23FC3541FE7FA749A863A048EFED2F8CC2BA86520B97FDE0324C68D1DDDE1E430C30DED0B25664EA676AAC6B1F22925A40B319CAA37DD5DEDB99DE4D963630A6FB0E8B00AD8F2A2B9BCC497A00099A70A9DC190A2AB2A058930E63FD6DF342A625E9A095EE79137CAEB8885117C7A9FB8DF7A35D5A300D6F7EEE40578A7507EDC38A0D6522474E672F156FEDE7E1690C3BBDFF40342F1F3AD3C34325BCDBFF0A68249858C777551683A9F3AF225163C9323A4AD5E666E0A9F44C6496269038AAC5DC2767966C1560C5A09207406F3C47157D2FE5909346D8ACBFDDF3E3D19FE48B7C60E1C8CFB2EAAB19E736B2595D33A0AA034726CB6146A01EBF5CC72EB1182B9A4BCEF90A1AAF74079862CD775F8F773BCC490F6015B4D5469EE0BD95C1A32A1FBF283FCE1FBF6F8CDCFC1884F4D2A899F3E7A95414DE419D56462F502EE703CDBA007C3BB78F20243C35B882C90CB7DE3CAE3F0468079C546645977347BC183FB0A6CD24481391CBDF9372E2D6765B6CAF8EB0145BB269A47A1B4E2CDF9901D6AA284D919BA57163AB9929E715341BACD81F35BDBFF36D59A1EDABFF3CAD2C122386A6335348A3170337B94E4336B2B74E791981656CB5234A6F84DB4142D3F323000FA98BE61527F7548DAB6E83928E9DD2E461F08A5BB52F241BB42254E5746FCCE0F3620ABC69A6E275B5E06A333360F9B809562ED116AA6CC2334694AAA4169310ED6AF695678DE22D3E551DAF61C0A6C5F6C0F36FD3469A3B977F6D295E75ABB804A43E1E7AC4708208A94E8368DCA40856F1D43C9865D98F69F1C0BA9C8B33AC9CCD18D400D2559B1CDD82A0C875B5E136B97C02126C81A81EB5D1E421221564100450531DBD97BDA77C1B0186527ECF526CE6BCD0ADD5668382D984AF9277A21D40C06EB4BBBB0CCD6F64E90272FD632D47A388D301377EE745FBC9CB4C02E1F096DDF303BCA4E1FB4B6DF867676080CDFA6A29CEDD15003EE636DB8C74E7E293A087B1A5F62334585369D12D9876ED0F334C6711146643FD598F0D69BB3475D219D1F89066644897A9CC5630BC84C0CB5844087216038C8FB6750D0968D3D3E2D29D93639486C76DC045900AE1A13529E74BECEB3338684402BBC3EB36870E0B37584E9F309BFB0DD9B966F0BE1298DFE55D1A94A6767CAE5EB3120133B7D7B71C9F2A538A97F8548FB176B0E8923B14AF28AE26306214F1D392AE63C3736B9F9374CA10EBE93370C11BEBEB45D066477F374866C8A7208CE6DCEC404194BB1F833DE0AA4700CA29681FA0F72D98679DC3E1E142852347B01DAA08E5CBBFD242F7223600804E066FB5C98C8358370F5D390898FA44023A30F824F1C6A95B8E23308B4BE474D03E34CF72BE65F90D698DFE0D2828A797BBF8397EC87AB9EE00C76A1C7B3CED0100D3A1030136CAB9A69F05CBE58A4A56A9C700BC591B87783DE59369F2E62D5B885DA09F25835A6DC06F954C19B347724244FDA69E3356A4EF60F6A41CFF3BB7CB22ECB128415CD1B89A9AEC12B66F1EC23B14E7D7FD601EF7B000A0C96F386216F75710EB2C12817DABA1D1295E7535331CB90A9B0D8F7542E73DE2D93FE554063F57274DF27BFB39BC4B78B72A88473408086D8DF531E53B5BE018E076032D1F8EF86D7AFB8E8867B9D7728A25ACFB6856D83592CADA4494977678A9F4D134F49A8598A8E0F23D3B7A09B5308243410CA6F47E0BF8C43871600817460BDEB74E7D32C2FF7C40EA4BF924E795516FF7C7BC8E5FD5D64CC489F1894C6BCF0E9C312B1EE7E2BC68739372E7402E6AA2ECDCA39C18D7441F0FF373946559C475E37D4ADA64B98283E5A64BE7BC2D1A1C148D2CDB4EDA35F591D3A7E7CE15162F50FF1B025F87CBB82289FBE7F9C32DB8F23012CCCB87ACA7D758D42019B9A8C15F508CAC9284928F46F0DC1C1B6C6B4DA030DB9286FF8D3762EA4A83D096AE04F98E9416D3DAC59E04F9E4E4359AD76926BBD9570A3D5811F69A1C4345B646BD946D0168ED62A7A431D920D707D8CC7E840BB9CF13D8ABAE8196D9177E8C28CE0DD9EF647EAAF0D3C97E52CB31B560EA7067B45AEFB5EC2B7C7BDFA3996D1C7E467636BFA1BBE11D1CCF86B64ADE9FAF9287A23502E9FF711CA97D6CC09DE814A67BA6123A8E4E67CF6E8CB6F7B36621BC6192ECEE94D61860703AC8411B16E19644A6AB01813402629AF52301C9D76A94CEE22B1DCA49F13B130028991C8AB383C8461433383DA92AB34F1EBB4124B24C6C391EA44EE6E736BBC7A2D4660A878A600AE39B7DCCAA51ADBE90BD705EA51AD13C05E611749D43DE336D396352CB0673ABCE7473DECB0FC708EF28DCBE18C85EE0068FEF64685ACC3A7D0DA9A21DD0AFB10B95D81F6AE437022218B6094CE35D01248EA85A9EC6FB56A7A2A8453EB03E6CCBEA0F2EADB015D8BE3D09739EAC07AD9E3F17D13E5F71CADFA220ECAE90EA50BEA87B19CA6FC5DF31874D51723BECC80C8845C9EA718454D2817EF8AFD99B63090CBA6C8089AFA78770222FADEE3B3B829CF36A8153EFAF2CF28DC4651FF37A8921E402EF81A0F457FC1802AB06A759BF4071F082BFDC100AB612A4584B5AE19354854101AB0173D7D6A5A0637CCB58AE58978A8BEFD5A2C51D3D53150C336C0C0C2A27B442E2BCE120C4CCF8D97EA4584434A6F48C0245B63B2255BC52ADAD4EDA9279412D70BE457F7DCAC492FE53C06EDEED766B46EBC3419E6DA2A2847251F75C62A5FE7AE74F0DD5AF50A447DA6356DCC828C5F1A2C0C873E57041EB1158296C038B91F2E13D3D4B2887B284384A9ECB8BB378BB311F4ABB19E1B90EB3A399C03BFB4CCB29AAD80C55C1636559FC79A6C894B5BAD8D529BF680631541A45EB0E57BA5B458A05F456C60FBB593DAE90AE549416AF96642A486F10843482AFC3989BBD1E8E4DDF0791204F4B720ABD2D8995C87C8A388ECB14860CF83B7A4406FB6C8C9393475082D24E516C5F1AF91CEBA444D8E460D0695746BE057EA8D76F8C0C80358F3DB2AE5B996272737516EF5E4EF5A1FE5967304CB6D00090C9623D29F0D4BCE8CA3CBD54A30F9597E01E5845C1CDD8777E18C5D5D86492FDD0606F623D11A28DD9F02032E3A378C71B757B52021DCE6CEEC63792CEA24D6DD7150AC8FCFCA6554F7B08A5529D59628D0F35122504DD1542F6291BEDBEE09F81AA744A0F6C6DFCA6207FBFAB6B9E17E8A4040741F6508471E72D227D0FDC50C13F444310245AD17BF819FFBBC4E0485FA68CF1F0A4423F251538F25DA989ABCD008C803D368F626438432569F12D1612370E4C6C971079371081B37D8DF7EE709198AAA2FCBD443B96732AAA4E6924A461B60CA4F4CB13E88D539AAD709A3DB84D2D6D26671A9F3877125B7A358389BBEEA846A32E949DB9A7853DBC7D5ADD92729CE1B5C00680974F3DDC6A8235C7319B6CD1CE5E0B66FE7C2F1115206C42B4C02990D79EFA8BE94927543C19EE93D0EC8811F9330693696C878CFADAA2D56E877D42A3680AB2F6A576FDA7BF7957F781655CC664A0A4A0D16CE34D04D7C98A9E0C93D2E6D42870FE66864660B564ED4F881693D466BD68B6470AF03A5A6E703DBB40515AF5DCA7142C4C8D79F5BE4BB01A1B56BE9D0936396A7EED9A84DA86A4F00DCF676B4942D5DF6E1378EA26D9118A54E17FC623B83AADB417EC82F9AFCACEABBDCFE2F0B6AD4BC1601B4E24F547D61D1C1737ADBCB46D98287372C + +count = 89 +seed = DAB6C05E29342106CC34769BF419ADCC88010C05B57E673A503E63AE7A4EE55B72AB2CA86C4EF57FC8C02D2E0C8694A1 +mlen = 2970 +msg = 4D83349DD620DC2CC0E9ADA524B9BE9B195973A839A042F4342D69E6B38918507A9747FCDD8B751D7C75ABCE2B482B3313D4C74EA4E7A4A91F2E08A059536B651508307B7F4C3AFF5CF1579F90F32BA1E847778673E3956713C14661AFA2D11CCF61FD8F9BC914D4B6E6D09C52AFF7FEFAE325C180147153C9AE1924C9A2B8DE4900BFBBC6797558B000C5ADB9A8DC4CAFB458AD328F19A2C55D5434BBFA7BE5057E56511529709992BD6527E913B46ABE38DBFF90D4AB3C024A66FC0F8FB34AFB96E22535A0EA8F313A087AA65355D7D5989C486E103FD526A7A6D812C0E4D8C081BCCE4DCFBC64B68436739451BE0C4B67BFCA71BE955BA9F9A23C223C7D0FFB1B2196C9C9845B6AF341A363951E2008BDC4F3296DD0E1E3F480F2E4B0EC77A002ECCFDABCC58D24CB0BAA26EACE96DECAA0F6BF1CDE0175AFA65AD5C23C5E71B50DF778208EDBE426AA6E876C12440D7C4FCCB42D039A14509092784BAAD37D9B8EDF186CD4FCB3D9F8B0397E951777D602B8AF613060FDAB6B358302B3FD28437A06694F36CE12A035F09D677E48D077CEFD1676D8FE51541BC19E3A6D6A5D879C4F9EB4713B7C0F3A652F3A05D74DABFF79A302FDAF147531FDD57924F49E52B298219B03D6DF166B481F232FC85C7CF52838969CED2DCFC18DD8C95891C498FB49289D1A982922A0FC02C849AC3BB7FA92CF43A64464D5BD919F75ADA287FE657BF61DC07B3808C0FD0D71EA24DE5353268B2C17C989C29465BA49111CC479F51A8CC623CFB6FF68149E52C77A7D85B5ECCE66C05900AB9957BC7ED39E03649A103B5B6BFEEB168B7C1F30DCA84AEA509FEC2B215DD95558A2708839396552F517A8FDA28C3ED61F84E1B2E0DCDFA708DE50D44BFC65BD4E70260C437C8B5B7158EC7E2301D9C7AAA68E0ADEF89FDB601711AD2998379145B29CE3681B513DC3BA9B2EB668C1B53697833670466E21E767361C0A4362E5B8DDC38EE6A9C4DC5205EB808B93C72FFAFB635B4254E4F4496BACC753C8ED0BCAA88DB683CE77C8165E8DDDE665392CCCD57BC07573D83CB3AA10648281EFB08F92AACD8AB6F9B5D7FC66D29526BD57E421220FFE375B26C61A0DDBD9807022EB3B4B681A43E7719F5EC255C1E19AE6C542D6DEEF3B94B6960C18D0D7C8110B88F995826073B874042FAF97F1FF034B8257418CA269F5CA588223393B0179F9817E08E7212D0D410EA259EA66BC4A00E7FB1190A732BFDBF7ADEA0E4550BE90C3E37BF33BAF436955742A2632AEDE259235702EA2E079D99A22C9755ED34C1E3CCBE746E728A932B1852F692B103112B303033AD3CE1172AA066860DF570D21EBBA51FAB72D5AFC4AE8995F532AE384CCCC3C4A295AF76A803FE076CCC920A80D82A9B614760EC43208579EF5DEE164356D62EA33953E55195EEE9B2E2018E6FD9D19A9F49258702DBAF6EDBFD093919917B1B6734F012E2BEB4F758DD481FB8A8D7796E755C6647501E28862B9F5B16FFA1C5D80DCB07141806FC348881A5A8891BB632A4AE4292A102D71504D0FC12C79D15BCD0799D30C7B9E72625A7DF7DBC7ECF9EACC627CA9AE5D71E264F2F2A9D5DB8593F3A90F3915CE480ADF800C99FC2C8692F2B57B492BF9D84171F8C29AF8D5549F82D3730927096CA18FF0B0C0C0B8B800508C44D5749B92D7D48F7FBD5C86E408ECE0EAE639AF475073DF5CA2CD5083BC4FF8852DDF5C399946A6B21B0841D137F583E0DDA3A6046F082872B783ECA3E14B21A2AF61BB150847026F2371812B1A2BE72024226F4613DA860AC2FFC578DCB171DC27B896EEFE49F885F9BE4CC8766F37038E01CF20DBB661F507B2ECF2B023203A6259B0A018FC00B2CA9B3107B605F04388D5493AE7CC4BDD093CE761A92847C2A167739E0750B427B2ACEB3ABC5FF751A5F32D36B589787D4DA509C85EAD751353AB2C68A9C14B8B2C8166AEB6F27C7F101221C306AAC74AAB6B4E795525FE12038725D7AF3D2A6D60E1EA85F2B94EA24F1B72FED9DDAD4C8E5DA484E80A2150DE22E6ADEF41153D7B4331E8F011A3CD48DAB02876B067312D0DC736E465F99AC3C9C56321507E79ACCF652E3857C749AD92DAD15350A6B4B67229A3905DB18AB2053E2D4F92F156A1D76D0AA891364002C991E632B53FA217AAC1709F37F3402F43B0753361EB2F595F9FAE3D7D96FF050DCA0B9657F4C3AB49EBDBFE8816051C4E0AFF32C5137749D53B062CB61F7201171B5DD716E9CCB38D00E50955596845DFF602200B30D375A854CA4E9A7276CA1A1D9EE92A04BCD78854BE251F7080ABA6D8325D40B37054596AD80211A50AFCC1DBC177600A70E648D8BEB4FCB8919214894CDDAA6D63B6F6C445469A6866721D4BF1117F25DFF9D65FC8FBE5B0ACC8B9039C7F94B2A5CC6068A0489E2E13A731DBE1094FA8558A601ADDB9E4DAB04FA744CD5B95A9D57C52C8124AD950A5944DEE2C55E5C8540DBEE5823DAA624F57FD5BE994BAB3AD4E74EA9443F8B6024BD6B49ADF3972442D88E61E04FE8478FF28916584CCB65FB15686991D5781CB7EDA067745258EA671E0A2665F94FEA1B5490669D1EE8711518BB911094957586C8075E3BBEDC47BE059053A7658ADFA0ACEABDD46E0DD9647B34EBA32E56B6305653ED386C50E79E15084F00F003B1D12504FDD8E47D03D9F7572276047BD22B82B8E81F87C86E6F20D2A756B16F291179A97B010F993C0F839C9A1238CFC9BDE8074405CF1B35DF423C7566CE965681F21C969E4F3F8FDCA72A18D5DAA80287F53B5F8429FEA81612CF63CCF1B7A13512DB4D1DD2678FE1189398032EAEB4368332972C728AD726B7290302C3C5ACAB6E73432E825B9046F846ADCA9D93780A36095AA5C51E354CC6E9A910CABBE59130E98F4ACB3CB6D4EFDA9E2F78748ED58465937FC81C548AD038FDC32AEC46B078CC5A7207658A9706F1C9653359DE6C4457DBFA71D300F98F9BC5DAA14DBDD5EF20DCEDE7E9D3F7DA5C932AC3338BA40E46B17D89FE38F725129991983D4A81321B394F2D7B20D66E3DEAAEB6FEFC8CFF0B68A766E27CCFBA66DEDDB1F541DEB3C1892ED2AD5D073162F0DD06B82E8878477BC96E03101C9B5D9D0ADA10EC060B45E144B31E6B4DE283FD43538B47178398FDD15B01ED421EE2C65847F7A4E9AECE2F1D13971FFC0157040782AD4B591DEA0906370820DDE1000490AB1C27C03D02A0F4B4BFAB0E56D7257288441CEA63175CD6BD11382E6C873154332E627CE82E37C63889EFBD8537AC35C21AD7A09C986CFEBF13B19D5677C1104B373F3B55198D075AAC608145FF9D0C4C12C83BB41036AB32227629EEB4922F172281A66C23C35B8A3E92DE0A10D5E8C18B9A54D6C30230F3A8263986AC535B6BF63EDDAF6A02C9100B712EC4BD49851A22AF0E647F259C2E19B9ACAEB6147C476C90745A353F6252ADE8212A9F7C215C0B3053BF2B4E0AD225E8B344EC14C1B839877349C3743E8337D9C1EB128B06939C5A08F60A46FA700723EB6652FC26440D9BDA3C99C10AD0742C2F039BE6B66749B77E14F8223509365053E87ED870FE3906A16DA6C62945DD2112C96A23942B1E14431AECA7DFCE3FD4D6633E0B661FB34B0BF05C4D21E689CAC9B6ABD9F507F08E4AAB94BBEF1C629C0E1CF344E66D3A3E100B615BF762DFF0CEFC5E4CCE0DD908F46C94E7411A151E713FE0C18ED33C4C03E55E12C0AC366DA5C757C7090E0F94E2C34D93EA3B226ADB2979D23E071F18C2EFF33BCF41BAAF52F4B44E38675DDDEC89C7BFE858BFD1AE70D96D0487972D70F8D8681982656FF734BB6323AA91EA14C6330C71783D235D9F094CB111ABC4990319BBF163891535AA5F870164DA65FFF395DB68B390084D4F2448B98CD56103E49CAAEB6CD040C3ABA8290284E9B2BC423117F4104D89B1B1607C6D34AC30AA9E79D8753B97CAE90ECADA6CAFC6100D3D6D91E20393E0DC95B981FE0EDBCF88E046F74184A96705AC226FD26089468E432D525643293BDA781B64BACBDFD6C7301AC42AED7DBBCE7ABB9D67AF315BCC3509CF03523FC887E27EDCBD7C74DADFD0F126CDB49E28ECAD38080F18A775E6D824C18359935D921744EA72FE293F299B530D9DC9285EF174EE60E2DDFFCCFFE89960BABA90D955CD2C96672513C758142D29A1AD79CA9291BC6782B64717F11A71E6D65A1A71D +pk = 617FFE99C53B1267451A9D4E20A9564E19CA7080BE14E622E51E9A62C9885A6A8203F7DAFDE4F4973B3117711F3F7C08E6FD00CCCE63EFD65A17829C1784EE27BF1FD0595DA60D1EFFB8A657654CB8BE682D086160E43B6738200177D114A20CF6970B6B5DC9A113B4D9B5529F63E08F391FE00615CF50E889BFD9090ACCC729234697C9F0FFCA36A3ED084989ADB54DD96E299F129A4819BD9B096C09CBFC0021CC7A723F5D8FE33880B6EC79EA90A14A5CAFD68FDA384F4D39A1913D9DD80E0B51978FBD1D8221E2D690CE46DF2EDA4C25AACE7FFB6998E04E16012B2C4D086E2EA975D91D408791966170711BFF3CB18AA2B4027E1DE7B280705B89649ECD9968CA315C6D35981AB698D0CAB89333CB89F5501C4F3F480448B334F2F2FA9A4CC396293D5E5821471B315D5E94CCAB65F41246488D341E47196E79DCC2C6AE9DEFCE8ADE91287776538DBF65E75438CB3FB687F17703ACB5A6DDA87ABF5C5D7DE85CCAD1AAC269619BA0B9F1905E1E92C1C2B0E4B829B940C6204E229A11EC731B4937641E606FAC2719A71A28FAB9B56478B25ED0C074337806B02BCDD600F2DE4DDD9DA88B96F43051AA1DAF9D971A91084D6FD2AAB4D1F6D242511CE7AF80A50DF20D2076313AC28956BA771C25BE4E66DDE8A58538449244EA3C6E66869CDEA1D0AF9FE0ADBE25F31998748269B34FCA3A09BD7F1919720D6A12A572DDFDDF5E0F1B076A0D4EF91FD62BFE7703D99D153A98D4F40E6C547739BF7EAC5C0B39FD5E60AFAE0147E9C9BE92BDE81F13BD696A4A2183B1428BB17B54156E72D69EBF2263E572D5322C36586723416855AD889E16ABF82BC0B831B89FAAB3FE46ED0E0680739A38C95ADDDD7F3C18A2D67D0743A41FD6858490160536C0D98757590F4DF3B8E1954F7C81769D5058D5A32BF543C8F1F884E1652AABDCF56AF36AA2A72BFD25F3ED4C3AA3555F2D3E7941C438A8B3EDFCA7ACA960C34EDF886F764FFED5CD5B2F4C5C75A59F7447F12951F35422FCCAEC88F476E8A0D93E312DF93E8B6E929BA1F8E8E8576E2C4EFA2933B4B764F0C3F93524A93698E8CEA2C1A0A806D96203B2BCB99EF8FB35488A8F9F38C6103989F5B374B739ED3400859E29A5E1656ADDE500977E7C5AE5F506F7913B7985519507ED276C0BCE7B6342313DF5911C6BD8666F8ED087F3C2D12517B11E68D08688DF8E2492E5B25DC9842A98A387B3044607E043661EE271029005BE7237C52FA94AA0588331320C2E72B89D7F0177630967B8921E1ACDF337537AD2182434F04B1276B5157B82ACCE144AE86674D6426597A7B6BC56DAF08A4860D9F34641CC20652FCF3F1FCF941AF96BB0A37E61B274733580919F18ACC869A13E58BAF9C99CA5897AF918E2A0F045FA16FBC03A86A16066453930672BAB079649D093E73E9ED33D3E1517736B06AA7095FF8B0328A051859B57BCC6F421136FF44A5B8D266D322454222AFC57989B810763D8201963B3BE268911247639C5D3CE322EFDB93F34855CCAF43C50CA93DC7FBBCA2F7D3F0018A8C3BAB7394A551EDC33447327DD54B180287AA851B42C7E3BE6AE999E159BF1D372ED13C19E311397234EB08F079D6BAE1F3762C2192C5E7213B3259A24C700F656D942E336BCB5D994FE33AFB49FBFD2416090C0F5E38F7CEEAFC2DAED83BCE22D78CEF00FA724FC9E3719F022DE770A17F121687E399132CDC0A12A42CFEB093A784800F712C19E9F0B6429FFE57F01D62812C4671E8A24CC2CA254E89D6BD739CE23DC586C53358F94A455F0EAC4FC9A527393396A199E3D349E46A2BA2A99D4F6A9EF670DA6CD8D17943F84B38CB9845642F0BBC236415CD62598D2C64FBAF6FCAF767AA06DC7D7821F73C2089FE73D45586A9684B12611339BAE8E090A3E8DC8E87744DC9CD00B3DF510FB3DDA537BE930301C3A1D9383366147BAED9BC0111C030245BCEFE09B1287F4D50D0B325B5A0426050F91500DEB1FC1EFF304E49801D96E5BFDC9943EF21387327C62F1CF7A090A0C140BE8BCDE79534D746BFEB1A49005C2B0220115E6C361856B648AA389D575D02F4E0CD9AB799A5129B3F507242D2CD6F8CAC1D92863C0C518CECB3BBFF3483E4E915177E643B1CF5EAD0448A389E44B697FAAC9B8AAEB88AC1CD6A69BBF5B59BE8875F0DEB18DDD7BC59B1EEA402C4C1E12740253AF9ECBFAA401597197BD92A6B6AE354B4210A5EC9572D5D0636355D9A0F745514C97D1F86DE639424442C47C10E0922532DE39969C3FB736A0DC2113FBFEB9DAE197E811DC4CA634C9798628B0F91CC37E549553C35453F8B3E7D5060334D20B29575653617117464B836BB62BB8CD6B20E21D3264A39A83E1C403567CF7CB5533B29B449F36B1CA8792895FC1031299B9690F47EC46501ABB51049BAC116F860EA810EFAB814397BFC53DD5E85DE6C5C72D84EE9BC5B081B82CC0F73C94F99A94226B5E895447404756EDE4A5A09C7B49BA053DC0413A4AE0E04480E21B94588911CDA695C400CE2AC5A39402552401BADD3CC9C10631BFBEAAD9EAF35A27C08EF3720F10359CC0E3899FF928662EA1C4B86D0413969719B42D39FB62B65E27082AF5F1E922EF1A4196B4F8BC28AB5EC4ED725FB12F046F6B0C9494CC1BA987D45F25F9B6BC47B891E2D10A4378289CFD0A223BA09D01E7DBDAEA77412C05B22A1B8969F29E19BA3DC16854BCFFA741A10DB250E88E88AE819F1BB5E3DB04C7FFC7B39255C17D1C5CC0765272 +sk = 617FFE99C53B1267451A9D4E20A9564E19CA7080BE14E622E51E9A62C9885A6AE1D969737229E74AD7837903C72745E3D81BA8E5E53DA89BBCE80A802E3FE15E5A7CB2EB71927E81C6C8CCA3DFA44BE9B82A9D392412A381E8398CBA85A32004264AD58DD738DFD12F427D9148BEDB01094F1681DFD48BB02DD179F65690E637838563213878417003307285836607244420454351120861331401722782638752500007232483425173301807155557244378647286837530523651632121806645848676115172271413707403577487387343585877407028431721231484373644642582452730575621400648254284311817261370102465884611174365226788440767501652285743380116600156150146076002232103656173106554571740136642604302170025637647161780573242176810355610424300584076102226204200852726501658340713261102365601650750542627075160818611160033842774344883228240866240073737625431067300500618106662450112748511070476037317765823555583457875000827116274342128364850270042103020451041205286263144228271084614482230813883185601064582084488477454052477132444008727306547727135167462281683874370440248825400042532345517845041777485171875013201005160868280458544338461211118077177645724047274735201125052037735117016615457537575767262705647447624254644142630226708278106300732260735565238230736544784818614615364203456634435721125213438402120830301055448127443060561486511620408688515823803632564530270513842761354750670014605631180244546880716146831537631651404335688186872431443162662874236557257473780634243433123331244355730818462735540305030513516781606551305818465314175265815404111081712162555340536711415601687046420044772282230148888485601166871208603053211235044434612106644428415431221586075731217256313583268304370525358605386855126476370205468270878744633305822548830157756617626601720326638688085761655450125584374726845270428603602056513605032021416638160358652430765800485574684408763652141507543557140236741815341185477633148125835456488316004423817815027250550837681037742103346685636805026658875172660253877740385166426241560628548846353673407407350627532822315648452340664565076712675752306310511260577515737122775146802020436008778688452527282705086065754387238376155801224272136463430661547608835763103074710780175631605526153466536618066163477201850053564834826230675550067582158254724626125860375088552482172656818380148172813361151560570778104526626463163560481353275581182421325155623803570153380635012280128361657152075412406188268868005638640140282774820200712328241580337685507275181417728362807320068168375637725405813086512334711800646063013202768735055424740347755782154580158017215827335108134507065653177255478634567861710273852105254142728670681621303471466804548148814156810102535511858315442148188304753018826567887148726273414075000620452630153503245677018811642403833243814231136601685433281870212420473354767018747326721855407643838270616722306804087314036267637662458833515023570022830630408525713516367008225446084307035070134102560238767540410352046387752842541045146688262355106818720207685363884074550288187452504467767136351851768465461234466253411772763727148171864670136782156310173406522332012073500541004478648754637866373308581373574832636871163356063437F822AB93AFCF626CE1B83834D9732CA46017F25410645366C73ABE2CCFE0C27185CAC1BEA64A7F94192F6BAA47DD8F905700545A1F521F3BD03EFE6C7F6E4B4641024F6B86BAC2605EC3A6F8734818A8E4EE7489332290F786774314FCE55BEE78A49C86FC1E23AF317C70CEFDC7F0F0D1FF056F674F194D422884AF949F82E24C190C9E38DAB3AD8D399FEF97D7A9202F3BF2732DA484B28C79636A2D105F626BC7E2535A4049860A1CBE65146F7FABD1BC5422F2CC49E3D0D4EF3B8F39DE4579FC72FF46EBF3CE0D361577925CAC788E2CCA4A9CF7D42C1B74E0714613298F393E37F317AF719BD6E767843FD81AA0E7277D32589909358967FFF13675C6D04DD60E36F37A59CC1C42E25D714FCC716DE804F8ADD36E529E029B9371948173105387B25F245449EAF21422464E6B3713E3335D954F9CE66291FA1D676A985D03C5D82A810DE1C9D72A8CC32B17255E6394C0FB7C6D52929F0E75C8B1DC3956070BF8726FF211AD806F794FD80059207E3D0AB2FAA3CE7DFC60DD88A5C9D8C54F24910730C7E606E0B7521FD7BE4BC72C7EBB4773A22D8CDFC80A9416350DD6D11AF742958C9234EC8C6CC70242EAD1E94DC8A91EB9D422432963FE96B6458E901E1FE8162D64E8804DEB55C4D00415AA527954771BB12DF3FC37D8EF774BEFB9C4989B8644029AE2D3BBDD9A90713888CB1E55972608B2BF4E6C17AAF6BD8AE36115611BB62CBA2BB81933CBF65FA49F5CD3037070519E9D47079A0367163E6ED0EAA4051A9D3D46085CA1C1A6F1A4A911445E9FD333270358A391C9604573BEBF24A7B364DDBEEDB98127848629CBD0816216D89E15D91D3221E53E438C076CEB58CBFA2532284C7CC53F722647542797971BB6D36601A4764AD832E48D7ABA7C0456DACE9739A3ED8ED0F12AC9F4950B85357F782CCCDD4241026CA78470DDCAFCE3F682064905373F595302355518412622A5AC3332F70914F21F71F0B665C1DC2F8B7FC5E92868479CFA97A7E4EF2E88A298E301144961132B5ED7EBE00D3EDEB794D0E496687BBA5A3F72443CEA86A8AFAAFFECCB99AE1871EEF0EAD7E113A86DC9F699F8F99531C8645215F6E0A6EFF094E8B86E03E089F41EE94C2A47494132F52E34641B0DCB2C1E07D89004438F8AE040897263708DF50C2A5D79CAFB032CD395C0902BA7A9203DDF464FCC3CF99C8E953DAB8A537DE24247F002D46184CD254B0342A2575E885953F809965E52FB3EDBE361FE41357F836443C3A965B5E5164EE137E9D5AAB405E42BD90248289A994DD2815C2A4B295368B7A1E40C163554F1BF4A93B2BE3878AE7E09556E312001FE63B6361EF57B1A417FC465E19DDF210BBF77049D70625100EDA18266F6DBE3F9F619ED2F985407A2A6C15F64A5C2B2AAD13933EE4C9265E1F4692335606009CB309888B927D13171A4CA4118AD3137985D289721A87AD570C2B0B4518F00C420DBBFA52594108BD8DC4F12D0D57AAB287434A5B3B61B5CE75CC29072AC73B0B181267EB2600E28948DCD3D0583206249FBDA5098F3644710B412FE866A4CB28B7B2F14CB31E28C79D6660AF269BA180A8B8244A2308A5BB11D4903F484929F725EBFD5F0EC3A7933B844FBA861C8C5DF3B0AEC643A396C3BF7DA4E03FC1FF46ADB2D7496200734FA3B3629FCB2D931C4DA6E7BE3551C1C08D34FFFC501869673CCCF34A6DE1CEC24DCCAFDAFA74EC4D2BC150DAF644407B55E8C6F4CCC2DF096C8CD4C686C940D3B3C635F932D15EEE67AABD5C98DE1EAC8A3053F807325840C0B6FDBDDD88CD608A2588AD395599F36383A61ABE24855584A7072F68BC5E6F8DF9489EF0D62FE6E4374051C12B68D0E33F9A2FF2075D6227BA58B948990E0BF0F028133B6C4CDE2C6CAD203BC93FA480E03BE48FC7E15AF8693CD00BCFCDD7A38E341BFA9564A48282CA933B2C2A20D8B0D850E99DB7D79765E92FFCCF1840DF8616770730149C86F4EB526720F195A9A12D6DDF81A6E621C1ECB1FC1172F8BA00C599DC1389516BEC8231BCF226FDE33AAEA19B89670175109E232347340A24170CAAB907552A38C211329141E7B03FB3F8AC25DF115798A9518397C13143CF92227136BE78509AA8F40D17650299D15DA480FA7E7A3BBF7DE4213E80B14AF721F82DC221658891B88E7E2A8339C751DA34A1D740812BA6B1BC62167A26FC430FD7A867F8CBF98A4FB86EBCCACA52116C248C9FB4908E5BB4794A516BBA527096362734C0B73179141275628013EE12D67EE14411F07767CA1195FBA8F3D417207E6F833DDE535A1FA1230D94E5C972FB7998FA2EEC2E80565F21ADDB35FD76500A3443C5C0BD808B1D66AAF6C22DBC5F67E83533E0641BA7D637318EB19F802A2EC2B1EB17EF3337013824E7A5AB8321E6949617FC3B8D6A63E9671F441FC8DB0A72333431B5E51A5F2022BC19AD96F38066F7D3B889C2CDE9B5D7E32C06CAD567E6C0F9991B2874AF21FEFBBFD05FDDBD8BED5A7D6DF44866756746A28B93CCC7D69CB275F8AD76CCE85D83A365B27D22F91263AA9C1772D2BFBA8CE37098C090432C5C74996B274396B6ACAFEE141972530FB2C2E6973A2A328EAC75CBAF91F53052FA2B8C78082F31E2AE240922635BA91CD49EACC30077E4F4EA28A0C1C95145548EE0A94728D8648C89576A5DFC252890170EDDEA4DA1BC117423F1E056003E8ECD01118EC7FE5F6D541D9F59BF4033E29421D363A2DDD3BAD83A286728137F6A249C47D42E0225488C7E580A225CCA6ADF5ED85D21F8D902AEBDA3A287AC43F1E80F6FE3D9752F5AA9A0BB37D92FB7FF44B7661FED745F55860FDB4F13195039B7399577F70D9D34FA565E416EDA3CF6805DDE81AAB085875BE0AC198E78ABB736C00A5808A47F72BB2E6ED46A15DAF45BE5A958BC397D509971627A028D64635A1462E59572EAAF8A674F61B7442D5516787341FB4169725035CA3A83205950489466A32C32ADF30F1DAC00DC1DF0D9AEFDDA5113C3BCBA4D391E32E60710CBA625A6BD8B0047F93DF3B87D09CD8A643622FB21EC493A73A16B9436902024CDA42A6C62FD442AE8C9E5BBF3F42C9F2F8A6C85876A6E872FF9FBB04BC4591693056D98948C153A0A3E4C71B327045471038BEA8F1850988CE42A1A33C7B394521F00A891A2C9EC109761CEA4D85BF155E9EF27F4E53AF8715C69AE48439076C7A9EC07AC93E2D37D764700D50DF2C73E9BC52A3634CCD7675A044E6170496987E5CDF780BEEA00D989A23D1E917C16EF1A42F5B200729CE1D47B43A7602BF91E63BF672E9F5B448912C27DB39E3C60C50BAB7C425EE6CB5BB391D871AC35A849CD0C17883E58463A8E2EE5693D7272846DD68306C1836AC0863E9BE9FD1582B9757E16EE7E665343E19CB87CF3299583DD98A68618033AA9AA0D6EB385FC0A03397958885E7EFABF75DBAE98F5A2FA0F54407C3586FF7C6ABC6AF4D2225D2C81895E7DEC95FC3EA647CBC99639887245F30783E891882E7CDE164507625620A421748EA397 +smlen = 6279 +sm = 5D1DBC10690471F3FA95AE0148C089835079DEB4561BC9F99D2C11DEB370C340721D5B05C45796AB333E4AFACE3412C8EC9D28996EB3A616242CCF33DF498B4B2F06E429EEC699CD755845B226161ABBE65BFDC86E95529B0A30739835037027AFBD013737DE52B5DEC387EAF57BBC224F7EEFFBEC12B6B70A1F360A12914250DB145C24F6049E6FACB33DA1BE4EC46518302A74197A4ED8F494C800AF1FAA27CF267E5DA0DD4F6D998448C8E3C97F3281A6DD3ACFFC0C5FB41EFC6B945C0FA721684F3CE6F53E11E9C9D4110ED324DCDC687FA2E620969B821E92D00C9DC10C77B4AE78F84DFAEFC9C80627EBFC9D3737BB56622F27050C18DD4FC6A219962C5A7E6D97482D7182133337DD67BA629105928F2B34C32ED586692A6E0F83955579B37F3C54BB30898FB9167D0D754ED64B21D1482662F24D68A5274165027D4C8FFDFC7D52B2920110A3E96A8C9DB8714814D5964091C89CE4D9BA8C9D5B2F546242A6B8F09D8C34B28AF30EC05395311AFEB0F3BE55C25B453BF157B3AADB0F26973D74BF2C993EC6110A967A148750FA1EC3C1D07713D7F01A9531D233116E13052A849E4FDC7FDA59E40163CD6163920A92D94DEADB161102CB86D0366302805EDC79AD0EDA44802F6FB1CA2EF8F2144E3BA49E2CBB2044C4C4200F205A032179E27CD215F4875CFA768FC579A8FE94B0DD2329A653F7883094E8C85B135CFA5B21C952F346D362E0A057AFA3E3D42E6C2A02914C8F30D3A8586F326F208DFF6C792125D224A2A5579FDE57EE956AA3435FA605B9A6824454E4F5FC8472B232D4D0430103BEE77E105A4B6C88A22E071BDA627DB1275376CC79970578DB66F7DBEE8C98DBC30050D989BED83BB0167A91CEC80B7B0F4924A632941D117FC1663C8FC80D46FDCEB12B6FF5B7C5B9D140B920513D1EE86ACB81F0B572B500294FCFF7D393F6E1DE89491FCB737C253DD16EE78A9586B54DB282D8600AC5D3F1F04F561A64847060065E65E970520A70263A0AEE78059EC029E31FB7E889FE62DD17591E2F3EBFE86F5926CC72331F7CD493CAF832E6C76CD7E5F08D718F1D6056CD5D348A95AA9FFFE2CCC202AA7425D3A55E9558AD112A56B4B0E8DB6479CABB36AC4753A097A1AB9F2273C9BF4D9795840193D370ED759D6484273A01E513A5DBC76CD95ED4FC3D4E63F492D9650B7541E3938D0D978CAAE10A5FB57E210C501349A056A8C4F5F78F945DC8BA683AFCC0114F8952CDE289D2FAB9A9BB122CC0AB16D253421E754028275B0DEC02A38B8645DAE027ACF8DA62B3B578A149B1079B66B50DF194EE2A02B0B24463F8F51976392CE1A03DA3660D5E1E2DCCD8ED1E0560ED4519E00CE347F32BB618C4F66138A50CB8A6602F8C5501DE21EF3939CD476D0D573E8619E7FE20DE1AD55AA4F9F8D128FFBB7FE2AA2AC89B715F317EB39BE6D464A59ED51C636A5A04B95CBFD0599C1C05AEA2E8679DB14E40E2EC956DAD8181A66DDF149B70720BE0ED966AFE067B292BFCD6716CC37498C23BF9F377AF11C6D3015FA198A0BBCF76C86031FF818653A42D82EB2EB610A64D55D8C1CDDD3F66C0537A20DDB5F65FF07F331B4CF9A56AC033A2B42275004D2111DE9E620EEDF2DF57F76ED1C6B84C50A72820CF06E5B50E63B3EF85FF633BFF72518E078301EE7F45AAC4F786E2D983FF11EACAD41F99E78E98B2BA77823689CD1D2E7900470A589B3B30432BCACE0C3D2F38C1B8796B19DD9E3CFC03824E7B42729961251E4B7176848C72FA84507EEC24AAA9D7391878874E64B3F0FCDC46ADB36A5CED360C8852A62F8B7482EF252D5296C3C2819EF0B7FEB9CB5B927D810736F7EEE0DE3F8BF3A91BA425EA10FEC811C41C307330120A7B8C1D5FB0C92C5A603E4DDE41690D36EDCC35CFB3902FA365A309C476F2ACDB8EB571F522E4A819523A567FEC3B849F145C3D209E36FFE54C256E5621595DEC3E3320A207BA0584E0028A10931DBF4D97FBFEE5B91F92B72A2D13894F8280DB06E9BA01180561DA1343E9E50AE3663863A1DF35732B135F22BC2769FF5FF6974FEAD618A782FA62823A4DAFD28EE1879732F42F1DAA518EEF7D05662FFFC875008517B8B18A20D3EC2F6507FC5A36599B427F2742EA905A5A3FBC60C29A424B3F82031EC8DF85F43663FBAAE27B49F1E1E1D2169404B4ED83A3C62A3B1A9B9AE2A145B08D424FB1337F55263DE03EAB03DC3A52C6FA81357E67369EAD8CCC232994F792586C4249935611B259430DAA6D53B332CB96535F992F4A7E81D10CA4ED3D60DF5EBEC5A049AF632163521A0B9C95AE98D69A334042D8352E1A015E9794F6FC236C45F3E2CFC5699718F6D09F643E875D7A506F7DD43CABE0EA3FF7E8788933DB8AABE4E0F9D32BF0AC9E1B660CA2BE4B6968D5CF096166ED5F6B146310D51EBA7F1739294D09817ECC71454B486A35BE8D1653838B0363317BADC34C36194F7DDE464DB6E6A15685D00DD2FABCA0B21B65C6ADAEDE582CD414C5B8E73207B3B4E999A76ED4168B65450B79282A39A7A0B3FFC29707C205199F87954F37DA83E6EEBC94F160EED1C7F9796946CB8A4A3D498C579D941CA422D7C9CD4F034213FA2208EFD4016054F6DBC7D9F2E3123CBCF12EC23F1E0EA5DC1092CF21435100C03DF1B01CA7340E7FFE53987050BCE9F2FEE9E734EA84DE6A6DBC42A0CA82DE6D578F86EDCB264CD2CC446DA40D2EB8A16CC6177D6D28E7F47860FD2FACAEBB9D8629C5D26863858037DEFD4A26D7146CE5D46186C2A744ED9A49CD930383F00CA7540867856192427140C2835ED78CD2BE2F470E1178A7E3842FA8014A549B11BCF7251C5F20B61CB69C7223498FFDC72C74F6398B9230E86DCCC449919AFF98E573A44CF520821B296C1F0424C9316B7D7BED270355450760F66B58A9A5E4890C001BD263A88674915DDCDECF2079112015174BD5B1085A0C47D2222E1AECC0C086C3BBF0D0EC742E86AAF0A40C3DCBE5E3F3D928AFE74CB23B5B83EA35A909E26A68D099162049EE505125C49F76B731B87107B4516C5B0E9E2FCE14DFAA82C72B72ECC8B826924A99464F0631461E855BCEA6EA141DD7ADBB2BCB05F19ED3FCB9D79031E8D3009E68CF3DD224CEEB0C23296008DBD2D06D5E48D682C1773B5F92C6B94EFCD9E63EE5A84E4050423DF2CCBD7BC0A44A980F7229FD60908E13B1830564D3328DB7CC8062230732E58785D1E5E11D49F798483303233493B52988CB7CFFDCDA35CE7E1FD9B9C503B3F9AD574F8FB1DBA4C1552796C71136F8D63FDC679538455BFEF1A0FF2735CD7AF9C38CE8C116FD14D1450DD32BD45B698BFDE9958C085DEA727E5CBDD632B2EF493E8B91ADEB62B97919BB698CE9DDD6B7F48847C8F5B881EF9425B215D02F14895E1E067FE22B267C5DDD8B36DF33B5EEF3F19AE2D5611EC590EC07C1874766C80EF4785A7FD1AE235DBE8AFC2898933CA99D6F8DAB92CC92986A9666C4405A0B77E91037C3A0584E7D76FAFC1B6AB74038DAD832E2E1F07FF37AD6BCCB36AA6A8976D0D7D6FEDDD845CE1D591E59ADD468F7E858B7F1DFBD831389F4D3C0602D195314370CE63FC57E0178EB5D5B0D98525DCD4B042FE5414C38C52D96D132A4A4747B5E1A3FFEEF381C66783CFFE5F1D18343E31196FE807F9DC237726ED51B48256C73F46FF0247CCB7B57E1DAEC1CBA526481AE06EF379A2A0DE1DDF5BF7A6F218D7907640D2E258E37E35C1B2CC17BF274C885D897339AE0E52F755AFAECC541B7BE90A2B1BEA102C5137B9992A7CEC89D3370EEA0D23BC91A871CD7CA2938ED5FFCFE50C08C3E4AF7A33A16F8A64C642AB65DF98FBAA699DC211CB6A5DF0ABDF8A1680570EC502080262111174B1B5BA7D3749D786CDC80144B35E251EEE4A2802EF94380393234E5FE4C03C60D17E24F5964B5E252A5504D340DBF50F0C381D7CB658FAA5A3F70AACF1DF286777FDBE1BB86FBC96E6F38EB43CCB3D16BFCA9388C8D9DBD8D14F531532F9C21E9284AAB2C2A3E4A985F8AB45A41976B508D3872568A73D2B7714D708B49C368606E7B8430DE74CD10A4093A09853354A77796427ECE1C5B5440909DC91BCF8338C48EF1BD04B66467E5C57D6A4FBE8BF50A43DFEC7F24767BA1B95B5202F46CFEB3607609A7D599F340BA403E92AF48BFC8C8DBD60366ACA536B8D3E8D78CE603C6D7924E1583EA8A9BA663C128CE8D595729AE81FC8188AFF33206B22DEEB5F7637ED7C499A038B94998F2D21023F7CE77B81B59387F1661E3CE7DA3AE2000DFADFAA9DEE8D5AC7983FB367CC3C1010177A9CEDF9587E6FA8B6F05853474B8E93DCA42AF20EAD7A576732FCC92FD8517BB2E045B18B4546E8CF0062B0A00EE6F217F231C0265876EC53BDCDABD6460A11377BAC57E3189B66B94333440F39BA486B411FCE0992FD762E88A9EB556DE332889A2D003194246FB3C1104B04D9CC7EB905E40229091E8481B59F5B541E18CD3CBF82CC52A7316174E226E0F1FEA70D44D3647125929188398C07DED3CCE2F6B586A3F54E3BDCB3A9E71E8D250275F6A744EFB53FAF2021662721E60A793B1C5D2422533E064F2262C434A4FAAB6F62774C1F65066909AB4C3CCF53D4145777BE9FD1D264A5068828800000000000000000000000000000000000000020A0E161D244D83349DD620DC2CC0E9ADA524B9BE9B195973A839A042F4342D69E6B38918507A9747FCDD8B751D7C75ABCE2B482B3313D4C74EA4E7A4A91F2E08A059536B651508307B7F4C3AFF5CF1579F90F32BA1E847778673E3956713C14661AFA2D11CCF61FD8F9BC914D4B6E6D09C52AFF7FEFAE325C180147153C9AE1924C9A2B8DE4900BFBBC6797558B000C5ADB9A8DC4CAFB458AD328F19A2C55D5434BBFA7BE5057E56511529709992BD6527E913B46ABE38DBFF90D4AB3C024A66FC0F8FB34AFB96E22535A0EA8F313A087AA65355D7D5989C486E103FD526A7A6D812C0E4D8C081BCCE4DCFBC64B68436739451BE0C4B67BFCA71BE955BA9F9A23C223C7D0FFB1B2196C9C9845B6AF341A363951E2008BDC4F3296DD0E1E3F480F2E4B0EC77A002ECCFDABCC58D24CB0BAA26EACE96DECAA0F6BF1CDE0175AFA65AD5C23C5E71B50DF778208EDBE426AA6E876C12440D7C4FCCB42D039A14509092784BAAD37D9B8EDF186CD4FCB3D9F8B0397E951777D602B8AF613060FDAB6B358302B3FD28437A06694F36CE12A035F09D677E48D077CEFD1676D8FE51541BC19E3A6D6A5D879C4F9EB4713B7C0F3A652F3A05D74DABFF79A302FDAF147531FDD57924F49E52B298219B03D6DF166B481F232FC85C7CF52838969CED2DCFC18DD8C95891C498FB49289D1A982922A0FC02C849AC3BB7FA92CF43A64464D5BD919F75ADA287FE657BF61DC07B3808C0FD0D71EA24DE5353268B2C17C989C29465BA49111CC479F51A8CC623CFB6FF68149E52C77A7D85B5ECCE66C05900AB9957BC7ED39E03649A103B5B6BFEEB168B7C1F30DCA84AEA509FEC2B215DD95558A2708839396552F517A8FDA28C3ED61F84E1B2E0DCDFA708DE50D44BFC65BD4E70260C437C8B5B7158EC7E2301D9C7AAA68E0ADEF89FDB601711AD2998379145B29CE3681B513DC3BA9B2EB668C1B53697833670466E21E767361C0A4362E5B8DDC38EE6A9C4DC5205EB808B93C72FFAFB635B4254E4F4496BACC753C8ED0BCAA88DB683CE77C8165E8DDDE665392CCCD57BC07573D83CB3AA10648281EFB08F92AACD8AB6F9B5D7FC66D29526BD57E421220FFE375B26C61A0DDBD9807022EB3B4B681A43E7719F5EC255C1E19AE6C542D6DEEF3B94B6960C18D0D7C8110B88F995826073B874042FAF97F1FF034B8257418CA269F5CA588223393B0179F9817E08E7212D0D410EA259EA66BC4A00E7FB1190A732BFDBF7ADEA0E4550BE90C3E37BF33BAF436955742A2632AEDE259235702EA2E079D99A22C9755ED34C1E3CCBE746E728A932B1852F692B103112B303033AD3CE1172AA066860DF570D21EBBA51FAB72D5AFC4AE8995F532AE384CCCC3C4A295AF76A803FE076CCC920A80D82A9B614760EC43208579EF5DEE164356D62EA33953E55195EEE9B2E2018E6FD9D19A9F49258702DBAF6EDBFD093919917B1B6734F012E2BEB4F758DD481FB8A8D7796E755C6647501E28862B9F5B16FFA1C5D80DCB07141806FC348881A5A8891BB632A4AE4292A102D71504D0FC12C79D15BCD0799D30C7B9E72625A7DF7DBC7ECF9EACC627CA9AE5D71E264F2F2A9D5DB8593F3A90F3915CE480ADF800C99FC2C8692F2B57B492BF9D84171F8C29AF8D5549F82D3730927096CA18FF0B0C0C0B8B800508C44D5749B92D7D48F7FBD5C86E408ECE0EAE639AF475073DF5CA2CD5083BC4FF8852DDF5C399946A6B21B0841D137F583E0DDA3A6046F082872B783ECA3E14B21A2AF61BB150847026F2371812B1A2BE72024226F4613DA860AC2FFC578DCB171DC27B896EEFE49F885F9BE4CC8766F37038E01CF20DBB661F507B2ECF2B023203A6259B0A018FC00B2CA9B3107B605F04388D5493AE7CC4BDD093CE761A92847C2A167739E0750B427B2ACEB3ABC5FF751A5F32D36B589787D4DA509C85EAD751353AB2C68A9C14B8B2C8166AEB6F27C7F101221C306AAC74AAB6B4E795525FE12038725D7AF3D2A6D60E1EA85F2B94EA24F1B72FED9DDAD4C8E5DA484E80A2150DE22E6ADEF41153D7B4331E8F011A3CD48DAB02876B067312D0DC736E465F99AC3C9C56321507E79ACCF652E3857C749AD92DAD15350A6B4B67229A3905DB18AB2053E2D4F92F156A1D76D0AA891364002C991E632B53FA217AAC1709F37F3402F43B0753361EB2F595F9FAE3D7D96FF050DCA0B9657F4C3AB49EBDBFE8816051C4E0AFF32C5137749D53B062CB61F7201171B5DD716E9CCB38D00E50955596845DFF602200B30D375A854CA4E9A7276CA1A1D9EE92A04BCD78854BE251F7080ABA6D8325D40B37054596AD80211A50AFCC1DBC177600A70E648D8BEB4FCB8919214894CDDAA6D63B6F6C445469A6866721D4BF1117F25DFF9D65FC8FBE5B0ACC8B9039C7F94B2A5CC6068A0489E2E13A731DBE1094FA8558A601ADDB9E4DAB04FA744CD5B95A9D57C52C8124AD950A5944DEE2C55E5C8540DBEE5823DAA624F57FD5BE994BAB3AD4E74EA9443F8B6024BD6B49ADF3972442D88E61E04FE8478FF28916584CCB65FB15686991D5781CB7EDA067745258EA671E0A2665F94FEA1B5490669D1EE8711518BB911094957586C8075E3BBEDC47BE059053A7658ADFA0ACEABDD46E0DD9647B34EBA32E56B6305653ED386C50E79E15084F00F003B1D12504FDD8E47D03D9F7572276047BD22B82B8E81F87C86E6F20D2A756B16F291179A97B010F993C0F839C9A1238CFC9BDE8074405CF1B35DF423C7566CE965681F21C969E4F3F8FDCA72A18D5DAA80287F53B5F8429FEA81612CF63CCF1B7A13512DB4D1DD2678FE1189398032EAEB4368332972C728AD726B7290302C3C5ACAB6E73432E825B9046F846ADCA9D93780A36095AA5C51E354CC6E9A910CABBE59130E98F4ACB3CB6D4EFDA9E2F78748ED58465937FC81C548AD038FDC32AEC46B078CC5A7207658A9706F1C9653359DE6C4457DBFA71D300F98F9BC5DAA14DBDD5EF20DCEDE7E9D3F7DA5C932AC3338BA40E46B17D89FE38F725129991983D4A81321B394F2D7B20D66E3DEAAEB6FEFC8CFF0B68A766E27CCFBA66DEDDB1F541DEB3C1892ED2AD5D073162F0DD06B82E8878477BC96E03101C9B5D9D0ADA10EC060B45E144B31E6B4DE283FD43538B47178398FDD15B01ED421EE2C65847F7A4E9AECE2F1D13971FFC0157040782AD4B591DEA0906370820DDE1000490AB1C27C03D02A0F4B4BFAB0E56D7257288441CEA63175CD6BD11382E6C873154332E627CE82E37C63889EFBD8537AC35C21AD7A09C986CFEBF13B19D5677C1104B373F3B55198D075AAC608145FF9D0C4C12C83BB41036AB32227629EEB4922F172281A66C23C35B8A3E92DE0A10D5E8C18B9A54D6C30230F3A8263986AC535B6BF63EDDAF6A02C9100B712EC4BD49851A22AF0E647F259C2E19B9ACAEB6147C476C90745A353F6252ADE8212A9F7C215C0B3053BF2B4E0AD225E8B344EC14C1B839877349C3743E8337D9C1EB128B06939C5A08F60A46FA700723EB6652FC26440D9BDA3C99C10AD0742C2F039BE6B66749B77E14F8223509365053E87ED870FE3906A16DA6C62945DD2112C96A23942B1E14431AECA7DFCE3FD4D6633E0B661FB34B0BF05C4D21E689CAC9B6ABD9F507F08E4AAB94BBEF1C629C0E1CF344E66D3A3E100B615BF762DFF0CEFC5E4CCE0DD908F46C94E7411A151E713FE0C18ED33C4C03E55E12C0AC366DA5C757C7090E0F94E2C34D93EA3B226ADB2979D23E071F18C2EFF33BCF41BAAF52F4B44E38675DDDEC89C7BFE858BFD1AE70D96D0487972D70F8D8681982656FF734BB6323AA91EA14C6330C71783D235D9F094CB111ABC4990319BBF163891535AA5F870164DA65FFF395DB68B390084D4F2448B98CD56103E49CAAEB6CD040C3ABA8290284E9B2BC423117F4104D89B1B1607C6D34AC30AA9E79D8753B97CAE90ECADA6CAFC6100D3D6D91E20393E0DC95B981FE0EDBCF88E046F74184A96705AC226FD26089468E432D525643293BDA781B64BACBDFD6C7301AC42AED7DBBCE7ABB9D67AF315BCC3509CF03523FC887E27EDCBD7C74DADFD0F126CDB49E28ECAD38080F18A775E6D824C18359935D921744EA72FE293F299B530D9DC9285EF174EE60E2DDFFCCFFE89960BABA90D955CD2C96672513C758142D29A1AD79CA9291BC6782B64717F11A71E6D65A1A71D + +count = 90 +seed = 0CAF47BD9AABD7D09FFAD404449BBAB2E1D48E80AC78550831A365BED8765420DBBE9A566EFDF20D4E5233D7848582E4 +mlen = 3003 +msg = E0F434DFA04EC225FF6B6DB802A047E221BC064E5BE89A5FC13937AE9D3F22B4439BB1C1BBA01547A64AB3E810BBB09706D01959E2E906A69FFDDF0C56726BDB58FB039D66AC5D77C7F0E9A8617B0C69176770DA328D38171F39B5220279186250139922C0DD0F7C3F96D48615FC66DB7568810931D257B230258FFE9CB35F87859E08139EBF7432E948EE3F962BB9015CACB8499BC69597ABAE4B841B606657E2E3C51FF5A8961AD42177A9E73950E3FA150439E2063B6555624A6D8E3AF4FD5710FBE722B8C6267BA5DF56846A085C56444573D692D5412CB70E443761751E58C41953BB9FAA3CE1F4564C825A02F0E1339CD659AB1480804DD2E90E3086AAA292DB39C6E2AAF1B001B47A21CC721C0C502C46EF0479BB7D8CBDF8E9C136397FEBC2D83C0FDBB3ED4FA6868068477206A26D2B7E0D20507AECB2756B888FCF5B446217DE14EE6A20CF7E7B732FAB22CA3ABBE81B2BE18463ACAA3132773ACD7476460536111CDCAC98B1CC9B2C36AEB3FB318340F7397B4B4AD6AA87EAC94AB7D98CC12EA5606162877465FA2CAD276CBB5D36C40A0B014C53D2D3A96825E237342DFEFAA6B9456B5FF1DCA859C5976F77C3D3CBC9DF355237EE9B4B4C90A9DD941294431DB76DBB539DC48669E7AAD21808332C8A4FE98B8F043FB756B526890452FA3C3527FCD584CD33E38FF9FF783538D39A184B7B3EB649E1C04C289FB65998F6CF5D5BBB0609FC3403D85C6DF269017032CD24AC540E1B294BDD3C3A0C7117CAB02B1A0063A174FF26FCDA687433A667322320C0DEC1EA3963F3B14375882B3478AED43C2C74DEBFE3A734F8B1A5CF92007F8FB627CC3AAD5C6AE4C31846B72E7573041270FF40E762C0F8DBCEB7512D44DC260A97D5CA7D60699981ED8476D8651C35C8ED498FC2961D1E38AF46F3653630773209A63838A9222B813C23DB0CF4196D6654126BA2B1840A7180E653B3D6E10C4C7AC3CEE93B0399D918A52E59F0215B09A119E634E6E8A9886C877F157BF7B7DD827ADEDBAF03C718AE037C0B262588171839E952721DE72180F8EED00B01F53E098B82165199C53129576036FC753A3D33AEC92060DD19AA078A496A2B214B1BFBB747A1EC64071B0A078D74D0212E6203C9698C7449326A42BCBBE8D9501DB916C64307D5F1083BCC36C0FFA18C0E4410B0B17D443481C3673D17BBD7A366A5FD1C3C5B3391A02EDA7596B4F869A91A32B5A02A05611371231BE035EDC716F534724B5225E1A72A2B2CD357F4C326F1DEE963FAB680721D40DD70B750A019E70885515F43946A0DD3DD042969139F61ECA0E9EE3107D3D28AC606AD53F236303E1FE986C38825318B7C4597B14E1A83B81295FEF49FD0F2C1E14A0B146540D853DB9706CD224B376343317BF7330B0C2721A409B856304FFFE60C24C441D5E2797D4696C0FE046D305AEE93CC6A2D89A81EB19643636A8B424B310034612105DF16516CE9607CC0A2BAC5835642C6FF9572191BC45E44D9B40DA36B607F570AE8C39D490342786F31CE6764F3F7A764665B6CB93E54922C6D89DB566F494E0EE069811AC82E8132F2F388D68490CB1C2172D2979FCE3659D7076B4F457232EB839172963F8C342E2CD18969F086F451D33BB774F3D00E6FA2BE02292F2E5CAD3ADF5DEC28932BD784801E69364962BF39E25455303E1F289052D2F0CD4964E0FFCDE29E7C074E5D57E43739DFA42AAD636C352D363E3A23BDD134BAABC7CD1621CA638DED7DB7051F0456641CA872ECDB4D3C2603DDBBCE16637010E782C4BD5230992E2EE7DD904F8A83EBAA7B4C3CEE15B10794ACE894118304BCDA9E9B1376331D2248B802557AABCF913E95F783715BB5E90A4436E4BDE7D651397A70A24257C39E0516BB1F548DA36C1F1F92A416DC1114107CD863F3BFCB360286E774B21296259756EA6040CB61738EEFE29A67895AC69797C640E03F0E9E731647C2DA93373920341FDFBD50EB6B737BB0D9FDA8EC8784920407D4F41486D8FC616430768D6431CCD789DEFF332B239FFD1900800CEDD9661A55D6D96089007E9089A117F03D7858EB4C3FE2D07E91D8CAB88D2BA5421846069FA6D4E5C9161A140CC3A288100BFBE61C3B0F0E820AB12D8FC54B054A0F4C777052495B45A7D1A883E67663DCF50C2230CA5319AB31CD76435DAE41CE1EE25ECD3FA0C7E83B0168852B2CAB674127CD7BC9DDF9DD4B57EB40128988C7C8994DC6A5FC939FF957F06C70A4056E63331F9AAD254EBF2B8FCCD580285BEA486D91A0C2DBD5823AC8F6846DDABCDE25A2252F8DA1AEB32E6969276BD2A7F94CD7DD3143F3181489272B1589FD385BA844F90E35982B53141DAEAED413054CDB935F3412E31D99C1147079CB487FEEE85E3906DAED18106B8C407BBCB7716EF9D4D34E2FF04709C7457997AD6FADC55A8FA70BC907815805578A11A012C521A1325754CAE2E3F7C9E1FFFDBD4BE31DC534961C318D1A894838E0C33806735DD11E408E500995B86B6ECD20D325347F792A3381D2A45587D9B6AE0AA27533732A6C421CA621AAC42335848D9C0DD89F14EADF2F92EC532756CD5697AD752B6260C598EC9F0E9976A950B22DAEA8B74FCC87F28B5E9ED83C0339E566259ECF06E5CE209065DE87FEEE5D1E9C466004B34583D6AE89B590EAD6A96CD2951705AC764F329E28C996AD6DB05F6C69AD2A39D3EE230F6501F1760AA41FFD936C9DBF20DE3996917322D32B946062A3C27D8BF35ECDA22403AB684CDC680DD166562D018D943369CAEFB9133A4BC4515CD5F9C08E7C22D153F0A7733EB4EB2CD8A74A4C85E40DADEF6858C5927B6EEB2B01E9B7AB02F7048C8869991068B00FC19B9545AB42181DD5CB5488222A402E827F60A8D87B09ECC88350032F998E3C10A88D4733227334812EC97C5E5FA85FAEE1A1E28A58641531B139AA58BEF49780DCEAA408986CF3C40E226C60531945A20F91E5DC31EC86C9F9A0545E5FCB79A13B9AFE9B133867BA7A38152ABC6D9F8EE10090BB71E6ADC6A6C2513B066F2565138BADA60B0BD339F9BE1AADDFC90DD272B4146D0F5830C6A53E295C849C15D001176E7774FCD7619D6EF1A30BA93CFE278AB4806BBF25CE4A4E94163F614E81DFF7EFCB015997F5138E22B80B2B00AD7579CD84DB5D1C7FB16E9E8C5D9A5BA0AD0E0A7DE79C18839D673632F3D2C7DA2062EAE844FACCAF23590B2FBF1861405AC347EB9D723ECBDE54CC96BC4D8EE2178F353310E5D69230C5DB2841D2A06A3A4E03E054D99DEFC6004A6E405FA89B198A901EA1AE9F3112A29F3AEC5698A42794E04D74D761E4AA5AD23DE271969BAF124450F4796DA1EB1C01480436AB0F5D0B1B2E6717DD87EEBF137420961F978896077E40B2D2EBB5664FD8AD89BB9333FDF46C33EF3BED21BCB5B4697451BDACF364F85462F5CB9F546657B4744EDF757DAAA4D3A9A2A6F281184C3576B1DB0B540F3B36310020BC6AC0C6454A7CC8EC1182422B17BDA202729C270194CD6044210D2B98731565812339EDFE5A0DAD79BA826D8C566C7D25DEA9BFF0BADF1E4E5DA2B884966E03FADC51C6D9BCFE877511157201DAB48AED1AB038999E5CC3FE58CCD37D40050DEE92E0BD5332413A7F0118724084EE5545FB51942DF1EF399F734FB9592555B5F32290C53D7E5017EFA2B61E29FDCE90CC3E7C1B0E545425B1D3E1ACB9089DAA786CB0122DB3FF27EA0367751A5462230F0F248147EBCCBA2E16D214E9A0BAEBE989BBA020F95B623CB14ACAF2BE6F157DFDB1E32627133F0D26C7B65A189F39955EE31D9B507B43126B06B9E4524732C8621D2274438DB7ECAF736AB7257CED950EB68BB868581649232793EC83379A16F40781E76F5CC57C48C3F5C2989BEA803E1B63768436D39AD19BB77DB46AAE6E8473ED5DFEC983F49E4B8E7CA6BF476AB2F0272C0C2DBEF1BCB064D7400BFE1B9ECCE13578A20B1D5B48133A74C5C59CAE0115BC3B50574580BFA99D58BCAD336EE2CCA5B7994C784BB90CC8F1B9A0E21B39D5EBA464DE34D46AC0BBE436C2F419D60D8AB13786F9A841B52710D1B49BEC290DE317B66B6855ABE156C07619A4B998CC582E3F54A7F457F1D2839BC3EBAC937AD3EBC6A9E6E845379CF1D66D7C59000E3F6CF6823B005728A95BFB0ACD044EB35D5ADBE8933A3637887CF91EE74BB910FDCBE797B0C6B1B056500542BD39781BDF13EBFBFE949D7BA0B7F31102E63BFC6E22693F97 +pk = 4CC5044A6B9D88D0620723799C69C9E1118C571330B37E27F390D38311163A5B18CE16CE5149C19CAAAC0CA3F56B9DB187D2E9A5E164C1C4C538FC8534A02465F056297DD7EC5303783BA1BF5247BD28222933BDD89890127AB69753E00A191227E2EFF7E01B63F885ABF925ED611DA70EA2519E37936D05FB4FF892BBFE7DFBF527ADC39BC05DDB8B6CE237E6131800D06308EE92485C645F846BA7B674BAD0C124B3A451D954E4F9D7632D3BC942E16ADA468EB5372FC8D55DFFA142DBEB941772ACDEE1BC3E23A77A72742BBDC4E724274B2D3AABBEE89DF913F4EBFDDE47201428D620ACA26A616EEC31583DA2ABE995384A7B2DC990B3F76DE137AA92D7AED8B4EC80A59BEE8336A798619EE1AFF23910A6E5A8AB5765A2A71634834EDE75B7D90F88755DD2643E746961D0C229C42A8EBBB37A96DDE0671156D8E336D59A7BA7CD4464F3445B07BBCD7EDAC157CE096537745B96243897305600F384A18BF71C822FBE155085C9F0B92B801D0A3546A339F7E709BC684ADACB92A249ACD0C7B13DD7AA27A6BAC10D829B91DA9EAE5B59C2996C8318FF9565813C870BC4414804409F1B9C02514D2BA296F450BF3394E92194E0AC5D62FDCBC10762230618EA4D7C1BDCFE85DC737A202AD59E5EDDD2D05A69C042950D99424E40AEF02FDB44710DB73E411B6A0252BF9F3213B9E0EF3314FB3B3C643C4A2F6AE9391FDB946CE5DB13A2F2F02E4A4C45D9251497E4726353926D4BD7665F21FF2721B2712DA96E0777DD929E398BDFA85133C1A6842E019C2F4438EDD3F46C604F7100D45B7FB011FA40DBE467C0B608274D7DB211648A74782C158397190BAB2205CC383DD679E1E62512C189E7ED2242DBBC5E57E427928ECA50517BF22897CDB9D5330015949E17A19A2E54FEA97846C6B9E8EE866177601C398CEABDF3CC34ABB090A8A0ED0D58CA9E19DF4FA5A3F27757E4F76A125E13996F811D38ADED81299680586753343450F42952419D0B4F6FDCBB75C7C7362A7676056A20A69D41CFA8855367BFFD9BDF1E5DAA83666C6CB54E8630B95252A90F904B58DE40B09A90081F9BC3E3E7CAB7B891CED0A9F000AC9B47910758C0E0945F5199844CBE18A79A887EEFC7F0314C06FD2DBE3B858A8E95DFE3CF9ABFA0F73F7C80A187C8BCD72DE83DD14017754F0FBE6B59B76C8350F9A7124F0606DFCC865D327BD6999B512F3FC098E7FF18C13FA3DBFD8666603A323F23221CC739E9C875E50A99D1B23BBAC39151CB71D0D903B0DA4E7DC04F031D4E7B6EDCAC06F6B2AC332CB85F502E662ED54979518C3ACDF747D5A50CF6A786398388AA8A3B8C31099F18D87623CEE1B8A7E4B7FEF795CE244BF834CEB56DC04DA518C4876E62B7653EC9A8FC7042AB585B656ED38551BEB57E91716FD26DC73DCF3855CB141F0C7F4E25AAD73D42EECBEBD2F26B81794AC13AE796B2DC8D1E25BB66C37BC90AFF2FC29452DA46EFABF9CAE13A2D80B2A0F18053B4B84A5C82F653285BEB78122FB9AF2332538F8C026477B59BA6B50E993D04FF3AD0DAAD43A2165D5BEC49DFD1DA4D547AC7C897D751BEA126AF1D746E47CFFC84E807E6826E0B5B50F6CD9C683793DA26DE99BC985DD4CB0DF8BC33EF2B2CDAFE4DAA02A3BD5BB461E00BD4B38147FC7DFA203B9733C8D9638A69B7A4E59E4A18F50A930268E5F1AE4CC9E258B8512CBF40C36E7860194CECF0C6DCB3A0691BDA4CE502D06B1E3104D93EF6B41BF1AC0209EB49EA9EB917CAF2713FE6D10B2CF09B9B3CE0CCFDC96CE223D300D4D86C3007CBCBAA830FA0AA17AFEE41979D903536149943B3798EA56F2356044F126273DA49CC869C2394B907A526A1FBA27ACB479D68BD7600C98BAFCAB4292291DBF47FB557682471C67297FDFE0E89CAE64F5F0B0E7D81B092A7D8FC977B8E4A39E621B37F85E459CF67A6B8C42045D4771B58F05C27653EC28723A91B197B4CD766D2DB7A1DB7BC0AFE78DF552F232981B3D65D7390E06281220C0360FE982432C92CB759F1541C6BE1EC0241D2967EF520B80ABDCBFEEB414B5D17E5BCAB8B44801130B0531F680B5A1A81550CA1061CE466C9E01F666E411274322C8FDA4A48A1A2C8B3165F118E35E6E1B910D1E836A4FF58A22B334662E9EF77F6A2330EC66CEEC4EC03C58DA8E8A23AA62AEF75542016680E7B8A125C921A1C776E7FFE7EE2789454D80580E1B63C8D65F38482EB9BC2AEE06E0B9662DEDB3586A577E8442DCC94256431E5AFC841451428DC44AA4ED412DA996F92789305B986C814A0FB1A0A48F512B733688A5B89535450BA767E7455E8D7C70382FB19E4E957C99456C49467C68EFF00DC831BB6C45D88408458C2E3BB83BE97059CC1DE73B36596A64C9C990D0F57641123150A31B3B7B61C665B657C2E77E768F399219776E648AEEFA600771A96542A3E2327BF9E439E9B58A5F0D4562D8E297CBE0CE24E85E7C1CE616993F1DAD6394DE3093C1587AC8469C527C131ED7B4C639B5EF66D6C01020564F214F895438AFF5B998881DE75E9C958C6F4484FB47AA7ACF756686601F62E71843C1ABF2181FF5C43BBFB53059AFC6D1DAEC9EA1349D99ED187B918FA32F89F6E9820740B461FCC06E7CD81EC6177E0E0771259195B7DA2BDD77FD060C7654D31F80F875058652720DF06B739CB5C56E0A76BFF93F24A63823937FA6DAB4E0CA9E78060AE1FCD12284F011D8D681B8CEB8CACC251AC53745BD5CC914B4E50572A910A6E +sk = 4CC5044A6B9D88D0620723799C69C9E1118C571330B37E27F390D38311163A5B0FCF00B3F52DD082245659156C72194F89D322FFBBB22E6C7CD16610CC76644E7A82EFD386CF78F9E84984CB95B0A8DE03E88C52BFDF46610B2A75DCE6277030FE9A88DF9AD7C796664D15A735565E37091E466B0ADC5D11A63F99A22EF58E0251461306216878388503650365675055874105708834300805424002575520086380632444664673225305105326466334182382685113207372272751467038326832868200041383835218162280576277725511645371466141784785450867101047570056401562584575771433415751448872403115375347735878865652041013614462175115328430215816761667513256363637101457657477510204388320346246238438064547315425200474162232622276343857210128440015788758520732223511604884206237612001322757870577730644053243127823387022230861135841377056432810182553566677376508842202383210635873123471246283835446817175475205757230168841727102815726846322082416511147850111404137381553588720837602034874482084725207846781376547668187521725730625570431034276065675311628167182537637540061353424001018725466285680810128641228303473473783115188257647027554710658083422640336246626682217263528080615345162507728031446587380210822844862433502545725404451413733104553568586270673756807417416711484732374065702110265642645603411574355227772617743213283488775214005535688753512730635563458830861088365653734386027424760354513720018337052867727743872317161312035343156353018182523078653005740456107551566302637148055253617143015545003330247451041071822077184824773821237837557534803088468356485178277278655558864426205477365243651187747664370216656027862567815380263661128680764362407512731116433541422633861067226037106122431513167407460833243284636480182164160465340505440867275880477580354413750188158232344630533527546082582475346446252871860557500382152735711435386210674336068648242820635164680785070286852713048225565878220084011017174126063580387271862711857577156561523254836123400815458237835365580084820863724863071506734118385303368457580788687326002887125862730514030253208665716787035073381181153841365206260555607004301635163483657657033306388857674312010461680606107783018311681528566554810338280180207421737138423453741663437660025332603354554442665076256127761410560034673428601207853752355150820288312376735171728815213381168638374004203404827770482232484546082481271153106873058253855000724757828414543751153204500672654726565874145336785551716126185300234400737176548278560542323434008270736317810666568456355857081638842117372135812754507862288561407633045782210182826701105070141772006172278104617181238145663236504132482883447100056545306478775027338442028526088231507423216516830478441518167835456426482421178522781585558330312816167015776574767477720278777023718722236871608120514340701573208777255258408300043630864410715278336360133385883627700517234721356064710750580028787576570508782554680637476433538646516743146250507476113754133070414556272632787508050487325352174280288811302782588225680828560022473356330115658126558507533000141810873808164282112142307031511543831785211451877822206762855860342431038044425510363821258037111020724218860805332042847545153647010697A6C40A4CB7215431CD6449273CC6E74E8073513BBD04161CBBE80074C6C4AD3C0D087B635E1B3EF2882F34DF785E694611E3552D92B29D67637A36A5D5128A7D99AC6CF6FA775312B664CF147D2FF6D50BF617A794E698F386A6C8F88FD8551E2E2008ACFB03B37E20A26B0611B2B22FE7C7B44BC4F0FD57D1B61AAF18C790C4EF62C13262A50BE3D7518E5F240A680A54CF2D14B1791EFA369F3BA1525B5B1A86F7C69F707C70C0D63E87DFF330935E0898E2201AE196D4B260FBDE384C766760C5EEECDB37920FAD1F1564E77013FCBC4DA811FE65F38B5A8137F95785D365BB397B0CA6CD78A9293CC10D7451D1FD75032C04100D47839A2818E0B450087915BF15B12A58FE8A8DF315AE9DF228A8372DE78F662FC922AE02476429C48CDC2AC5DC4986828489D0F6AB1122F6DCF18AEE9DDB92E1BD1C090ED00B22B316944F660FDD7BC49AC29EA7582B6A2DBF7AB660ECF87E637EC1C0022EAB8A5875B59F0E9A80EC8F904C0DF6332DC2866D0AB5751E6AEB937AB3DCA4B8C4D72B95B0E222B258A44983CE170EC9D283FA3093E48632470B7F07153F45DB0E0A85242E765BB3AABD9AA12C14CCC97A48B7AEE95FA80E6858F3170C20C0E92EADA176810E8D0FDF6363E89EC406CE6B10683A13C0F8E209BEB05F8B572696252366A4457E7378B1D5712E5D2D2BDD5169333F10720627122E494A7B7664BB2E6CB710E4677DC1222069312520A7519F7AFE1FDE1714C96AB833996A4CC89EBB321AB0E6E4F61B83096E3042D5EA2002F7D4508DE3E8A2DE91A3EF2781E0626B91BDA4EAD796E84161C17A11492FA5E3F0803E532A3EFF575945C245095D1EBA7612CB8DF0E79C074E908C6236D3D73C7A91002B68AF5C071CE7AAA45EC9DC5132ECDAA0376F4BE37CF9402969E703BDDE301DC7BB11997DC299C04FBC4B3FBAED602385EDCA3350EB515F60723D1FC628E971A29CF02CDCB1E19FF5658B06B3F38F7587EC32E7CBDAFDE20A8291CC79B1B356BAF3755FA6690DA1DB4003B38156A38006256C44B7FCACEF35CE4ABEE0439A74FFD9785342B22DF488A59EA242B527271870686DE67465097F91581A7E2B10ED609E9CF603AE0CF5BDF4618E3BB87C8CE6B4F0854D2A1E6B61EDD9DD6D779884906C551DAE3724C5D29F78852DF1F971947608C43D0F776A7C2078E98FDF06B80C7A8AC4103319D9981664F26100877B4CAFC829632727B82D55E02F1E8BE198C08E87D147C9829955755F230805B79DC61F220DD6A6389C7A6439969BD24D22F60AD68FE35D4F848167B027FFB6DBE31662F7A95EB08476B065712BB23EA4348ECA5C01AEEDB0AB0D49CF084E97E1B69EC8154A130F509F23F0C439D427069A2CE73176CCE24CE76376C0D361ED8C7C02C44612A4368EAB097447D4AC0AC8821BACACADDE18238A957B16C9583B1E04865E532E595ED37D809AF664DAA089E14FE14DA69468A7B1FC69C782D899E6BFDFCE5DF9F3549C55B0B62462000543280DB5BD3A82C9DEBB3E97B35399CC23DE5DC283D9FF88894A590449F762DBECB979A8DA65955E84F5476DAB0F2765706D86DB35889387923D3BDE2B241933C95192D1A3EA5BB71003BC159F140ADB4956C94B1CE6BAEB89DF7CC12726888FCC59AFE605796216213D5D1157D452166E068C3EE2E69A760C8C86666E1F5FA28DA6A404E4F3F7AA2B5A2B2B683846158C469D07547A79958607C0D36D500DBC26B2B746ACE1B7C0684191E1FF8C0640A849A87A997B34EE44A2440BC935DF1F38BAB84AC5F0C563BF1BE70F40BCAE4D4F49CB2C43BBA0A17950C8A7152D4BC1830E74CC050140DF347C1C5B42CDA572FA457E2BABC3B227DCFE8448E55CD2C5BB6D31C8ACEB1FEE1ECC34329A474DD7B0351190FB678813C12B6599C4E43974CEE2C745BF876B38B8132E9B4566ACA2DD00DDB867CA2C84A21219468143A452B4C661E546DCDD54598F1A0CB2ACCB8D90A7A4AC2E2D59D6A2E89C1307E54E25BC30E20DA9DF6D16B5C0363FB90ABEF36E4A4E56C6299BEC9CD2544BCFD1C89AA94386555D02320D16278C50A35CB6D29CF9B9B118BDE83CB797561F74D0C150FD1FBD90C9DFF8FAA1567FDD544EB1206761AEDB73CDFAD1F6BE384150D5D3289C42DFF6709CC514EB63CA97BA0F2EF385E04494D647308E0DBE8C32378B72A6A6217D84D1D2F2D71801E566C4090553A5A9A2764F4140FA19BDF36D1CA3B3C2500820C151D838D1C05395A939A1E2DBB1322557AE7B86A8441D3533752B2228919A54CA524B0132B328A12E8ADC1E23181A3991361C9887E025256F93985C1059F4FDB91C5513B053A63A9FA72AE06227828129E701058DA136EE8B56A58C61E3125368106D1C6FA50C7540E8E163BEDF16D7F86E8163A488539E3A1BFC15B7C3A8A16A9990DF8FEEC8DA18DBD87AA4D042537D2E4F3FFD73A5B9C6DDAEB5869BBCCA8BE6D226812CC0E850821F07766B94B81D935B93CB8A76540E4BBEC405F224EE7689840C93E01DFC2A7EAEC91202808E3F98CDC8D0F32840CC90F5DE75543FD4602FE4E2EF5E8054228CFFA860BE37A9797673C7B3DFDA5A169A171D7C5763B7AB289AD87D7F2440B7BCFF3ACF036EE13D98E734CDA5A19546CFF13763BE0638433CB93F153FB1F1D8076408ACC85CCE5F857388673C0D3D34650786EE884A1E87DB017832F078C3B93BD7581EC223BB458BA5AF436FA12713FC21F1484FC935E51992BC55105DA43E7ED959BBC831CA0C0F1C6F1478DC8091F54205C5DEDC572FB9C0401123FE62C0E210F0E9A641567D3D3E73656E0273012FDBF56C4889056BE4422A0CD5E99FC01F42C91CB08EDBF1CC716E90BA20ECD9557AD1B29B59D064C1C679AB65CCF91F5FBC0B4D4B1809BBF940E28AB60B4B3170C91010AA9B6084740602FA86FFB58FC008D247D05B4DCB6F353755BC33FEF6D4ECC64152106E6BF0BC255F5B3874985B052D2A16E2E245AED0104715179EC053E9769481B0BAD411979FAF2DC21A196401876AB69880890B488ACF64345032F81BAF5FFB84D51A08DA5CE6EA135393E50DB45367B3CFA736CC65093EDA32C0CF8138C19346C2EAAEA3F5EC98034A2245484D420BB79739CE09F1C00A310DC8D04BBCDBFCD96A288B673170192737450E528113CA5DE7B0B7BC629CCB2CEDBDBDD7DDECE8B8F04ADDAD801C336158A5FD9C9DE2FB8736576D72C82EEB3311DE778561DADE14A17A68F63827564D0A03F98E38BCFD7E7D5E915A284C850E67B1CC392965AEDC3D71C9D795C0847EABDB56B7C5FC86465260A273577AD2C19B885DA6C27AE0674A74DCCC2CF575EC8FAB046316B2DD230C7D98529DB795358EF44EA71FA2513F07005DA893803A4F00B14D6C0B824537B989DC8C64BC4842680F92EA6BA59BAE316CFDACD5F531656A09F1A70AE2A1FD4B30938780063EE9660AD730BCB1426A1AF9EA5E1A34A3077DC510754F2F91E0A18985D7DB9B0513E6042D36BBD49201D098611C198ECCFC4E592DCCB9492DF +smlen = 6312 +sm = A66072E6BE2091DED86DCF852D0B2FC53A35E53CE4060D82FB0D15B8F31F8064E2AC2EF1FCE6FCE1AEC24BAD2426D07DC8577288EC4671847E5959DA9D4516E981BC840A7B4D00E39DFF6785D9A991F028EAA20A8DBEF024FB5EBCAFE9CDAA91CD7920A08D792AF7A2E270BBF7979ED6F5B895CB799F13223E7746FCA7499936C7FAEE555FD979F0350160DC74E76F342A76A5BCD60B9E59B455D609187FB810F36877A0789DC727535443926529FCAC279CABEAFAAC905CB4B8A0ECA90D3DFC2C4BB0C55977706718B866A1A8B5851CC40921C57D748D012A7C5F8BC8431BE5D90040E207295DA4CCFA428F19AD70ECD7AD1EED31EFB733F45A00413650EA94C9839BE016AA81D665890BC6E13BC9D095374D3588289F0C21758753C7E1F6538E96812345644046C24645BD6F4CEC4FD7C109A3EAD21B1CFA6BE6957CB2E31D1E72C7CF66F080440B5874678AB2DFE8F91D198B90D01DE426C750088711457C9B862075C9DFC37942246D740A9E285B1044A70A63D3F7B11F5A7D49CAC97998E99B917D64464372B723ABDFBF933A6BF03325CC2A8B5CFCC1FB6EAF66B3B018F6697326DDEA734992118FB171A395EE2DF725A158AB72F1E8093A278A812EFF67A804413284160BDE462E65C9782AB8FB05366269F726DB0900A4AB29D9DC89779A5FE38A80A936A27AC88ECCDCE4E1492ED01DA55EC3F8D60CD831FD1B08E2C47CC96BDDEFC401F4408DCF3760208DB8CD91FE410AEDA4AA9504711EB7C35B79611AB32C1C4401FD88121D54271B825B3851284255B8A6156A4CFC8BB66A5D5F6B06BC1E14126A552C86806EBC58F071848425BD27088669729EFFFACC33D83E30B1E5719BF3EF0EBE5E1490C609E3D12B76FF0C69E9F51AF1292E4EFCB4B537E0D790BB8CBD7A4EA5464F61513BA5104868D34BF183AE0F9485337D77ED192FA21486032BBADA142169032160DE1EE7B372B1D0C67992EF67E9E330DFB521F7EC72B933DE00D8B29BAFA12BC16FC57839F746AA338DB01AE1892FA30FCFAC38EC8A66BA95F61BFBFCE3523C8904D8DB81E03F25508205275796810249F23C899FB95D853559D5D26892DEE22A1F99E89855E26E7C35336322CEAB453DDC25A866061EEE43E3681FA4B87605B44EBC241392F22522E08B1086682755DBA8E4803FFDF39E46878CD16376666B1178A45878D81EF47985AF9CC76275406EF9692DB6E4FE3CA51601614C1F9555C0B3D5F8CC0E907639DE2A517142DD1C0E3D575BC6583D5DFF185D3AF7F36FB9ECEACA44A6B1091D5AC540DE3BE2A837ABDDFF782202646D6DEC31A4701C803069D4E580A6B0448B69A1FF49E68B5DE7C38A64163FF46A0205DC63937BC1B89EAECFE8C987492D6F685389E6A4358D5037C15F4E46EEA5E4A17373DCF8F65499E701D3DB2CD8C4E1EBDAB28150C9452A5FD13FE3D2FEB36B1FA1B011B6BF44999EBAF4D3A5B5EDA03A0C14E26B05E4AD39CD702AC0DDD5DD5B138344D7BB0C77DD2605A6E84B1AFA30660E8CFAA6097EC54B42B5A2A7500F95AA4210CA31FEC041AB5BE9A5F7D7185115263F7CE59C7D4CFB58F0CFE119136D3C929E79DB6AAE1D2673CFD548D91432FE0BF2292A36723F1E354C5B9AF1882AB0FC4432A29B074E75088DCE5E20712CC172D28A53A18CB9789A9B4D28BB73A4CEE8A3B53BBAFBDC04712AEA1443DD592DA757250264D77BABA098CCB104800034E85765E0DA2204F08328C370FD4782A73ECC58C438DF5C8CAFF2E3553C1EB29E4C48FABCB80D0A9876EE76AED81151AA7228FB7232C28E8092C45EB100DC51143D057037B91E254B79E07339A007C978FD46382CE3AE79C62209D13191A4C4959FAAFC3FA42BF5363752861C686DE2F5BA666909F0E308A87385A07EFB3BE77D929D7EDBC45F329C913B4770CADD18050EE8BB26E49FEDDE96D675931118D0813E4A682D644D92C5BAE42A906EEB6659289268EB42BE286266FF46934D7995744AEC679706FBC17F83ECA7A6AE399ED0ABAC5634893253D518B18AB18113A86558BE0BCB0A92E8F4EEB41376B976821F216D54D9E061477C9C7DD89730D6ECFE5220B6421062A24A6354177411FD27C363EB9EAAAC7012D973E6F0F7E0E3F626BFD71C47BA4BACCFF888375C19639729D3C92F067C7DA4E6E25B7C319FBE33B763EAC576AB12AD0AA341EA2A398E2C47C538A6CDBC21397A0B90A2230DDE8C198940410778F462B62563F907FE7A449EF9C804F20E2E9C91EFE2A4173541C637E01271A5500D1E87B4F88511217368AC3C6FF0F06D7B0EDBD1A035C005774BA4F7062BCB70CA12D1730693BBED2621BF7AF55E2E100E45150835F330C8F9C9B3278E2A83E9B64B3FDCDEF40FB725C854CEBEB453BF4E1DC84B92836114A6095323C423CBECD02CFFBA0E464B3441CB37CAD409A97B473DDCAB45CB74133BD9B1F19CC40DB2E5A3ACAA28344C3B3F9B67553C77F983B5FEBB95F5A37956B903552B49D06DD6FA2A5F667FAC6FC01FD3FBA027B8F9934A49D1AA8AD3D659D35CC79A69004C05561252653A04959874480457C2FC2119C878FED96CF54CD37805C270248BA4081C243F013A7105FA9188119387089099FEADC19FEE3F4703EC9EC7879F21BD881AC1209A8FD22EB3F55F4DF436175877421A546F19A3677C09265358E9DA4CC4185AB16DC1EAB838ACF5E8FFBE0CCD2B05759B48B9D24C2582054DDF0AE7D31FC6BBBEC49986065605AFF148E522770ED96A50AEE8E7BD28A516C2027602D108F1C86A2866FF732AFA760D53F4988C2E608324E9781F94E001AED89E254274E7C5024E7ECCECAEF75D37E201EDFAEB501EF44A404CDA02DE86B3038E9781033F26DA03E74CA7E4CA4C56101811BB24D27A40A5ED200D484494870F54A67961B2651B5E6CCF3CDFB3F2FAC04D4F1CB274D2BD35C20039608DD6297DAD2D6DD2DF22FFCDC6EFBDFE150212255B04FE4F42A3D91CD20B6DE18C8E95013723BFAE859557787962975D15E1E0CC1BF94C740E2522F1BA4FC67647FC0485F4B80DBD4928DD9AD0F8279C30341ECB26DB10EC9F91E8F5AEDE093663BE394A241466F78B67EED7CC22502B25D0453246E11E2097532C1C3839FD2A6B712274778EDA3B973AA14F2C78ECD2626D29850BC6F07FCAB6C4656058896ED807D37477E2A57DF9A70C65C7732585EBF5EEA705ACA3C4BDE04164D5B39F0E1EDCF6DA5D29CB284A1031C514290409F703B88540ED51F46EB430EA5714ECBA6BFC5E7CE3DAA20EBF40A22A752E829AD648AB9B822F7A0AEB385DC33D8B60715E9C25EFC0A98DE62A52F0DEAF26B4A9E06FDCE5DB765321DE655B6C33B83A3A98BD8EE4A951D1AB1447DB0FF7B7651C22520784F1B2DFE9140011FA2DC0160411E34BC5B45F2D63EC3508305FCD035AF070219860D4A9D9A244CD0E5B05CA85EBFC397677583C74EFAB470E036B95555135D3BF6E2BE9316899588ECD8EDCEE80E779295457D24D49B6E399B5DAA08AA48B7AEE8DB59939CF702B95D5105C94A82A78D9A16FA0174FE82C5AA08DA8ACC1301C3636A682AEFE4F3265BAA43BB7967D5DCA04FEA76AB979D66E8F4E3A03B57876F3B5A5767DE79BC7E687529FEBA296595AD0F13D5946195303BC248A2D2736BD1DC2DEFEFBD6E567F1A546A837D7AE2DA9E33D2FE7C945BCAAE733890247024DB965A8E3A6543D1B3B41B70237954669F779163CC641E42FDF6201477DB08E112DDB5C8912150E22DC81079434F3D4A1FF30809E876B549655668CE6F2AB0AC4C16CE6616E74CA7044F49E8C6A355D2A8241D2100E2FF6C67CA30467BF3BAD82CE73E3AE2F327407E09FD258508B8F291E7908EA33DA5A7516B015EE44F9ED45F02A69158BDE19EFA0BF594A36CC902095F9F5307D5620E5522AF16AC668914AE6A567C4E361A60DE7C7C4AB35D3FF8F0EDDD9AF938F2D917EE8D7B696CB90EB12E87DD21E9458FBB3347043D85B38FCA5885D65BD626AC60B185858F0179F5FF14411BE8285331927273AAFEA625E740AC6E834A0CD3261F139781A77A2690556BFC3567EFD8F2F440E8386866B72F87BC62A9F0C7C46605F76F81F1EF3C044F010FC8FBA90052777BFB6E05FA63DD700930ADE5A6C66E53F15891B3BA4014D284CB5F1014D4BB14190DD2731B0D5F78145EDAB09F60E63216C2817910904A7895B6997E998E2D9BF05933B6217EDA48C9401723A3D9378CD1E5A377E4AB6009B2EDEE121914D81475EC4F431022B32F978F202F08CD11A5523CD0AA396BCFBDA0732B98CB7965B44CB34C198CC8700C30B89ADFD3A1EF2CD817D127095B9DDC76F27F0A8F390C34C2A8D5A94C8AEBF215BBC0D9D59B86FEEFD69E68FE9EEE09B7CA8510C8379A9DA8656EE240F1BCFBBF2F8FB97918B7B3793B111608F19B954048F8BCC1EED3D366582AAB8E260D173B67AB699D4E23751923ED0AF1F7173BD7D10497062DDEFD78F8D5110052279DA517FE6698A967E8F3E71C2C14D18ABE3C13785537CC28F464B0071270EC64354114EF26831D18D1C71588BFD02364CBAD83C9E7A5CE0F985E3A86617F975437918A9A352B68B80D9DE01042151597382A5D60E9A33445AADB8BBC0D308121D21F11015191E365974818789C7181D92C2D9DD0000000000000000000000000000090B13182329E0F434DFA04EC225FF6B6DB802A047E221BC064E5BE89A5FC13937AE9D3F22B4439BB1C1BBA01547A64AB3E810BBB09706D01959E2E906A69FFDDF0C56726BDB58FB039D66AC5D77C7F0E9A8617B0C69176770DA328D38171F39B5220279186250139922C0DD0F7C3F96D48615FC66DB7568810931D257B230258FFE9CB35F87859E08139EBF7432E948EE3F962BB9015CACB8499BC69597ABAE4B841B606657E2E3C51FF5A8961AD42177A9E73950E3FA150439E2063B6555624A6D8E3AF4FD5710FBE722B8C6267BA5DF56846A085C56444573D692D5412CB70E443761751E58C41953BB9FAA3CE1F4564C825A02F0E1339CD659AB1480804DD2E90E3086AAA292DB39C6E2AAF1B001B47A21CC721C0C502C46EF0479BB7D8CBDF8E9C136397FEBC2D83C0FDBB3ED4FA6868068477206A26D2B7E0D20507AECB2756B888FCF5B446217DE14EE6A20CF7E7B732FAB22CA3ABBE81B2BE18463ACAA3132773ACD7476460536111CDCAC98B1CC9B2C36AEB3FB318340F7397B4B4AD6AA87EAC94AB7D98CC12EA5606162877465FA2CAD276CBB5D36C40A0B014C53D2D3A96825E237342DFEFAA6B9456B5FF1DCA859C5976F77C3D3CBC9DF355237EE9B4B4C90A9DD941294431DB76DBB539DC48669E7AAD21808332C8A4FE98B8F043FB756B526890452FA3C3527FCD584CD33E38FF9FF783538D39A184B7B3EB649E1C04C289FB65998F6CF5D5BBB0609FC3403D85C6DF269017032CD24AC540E1B294BDD3C3A0C7117CAB02B1A0063A174FF26FCDA687433A667322320C0DEC1EA3963F3B14375882B3478AED43C2C74DEBFE3A734F8B1A5CF92007F8FB627CC3AAD5C6AE4C31846B72E7573041270FF40E762C0F8DBCEB7512D44DC260A97D5CA7D60699981ED8476D8651C35C8ED498FC2961D1E38AF46F3653630773209A63838A9222B813C23DB0CF4196D6654126BA2B1840A7180E653B3D6E10C4C7AC3CEE93B0399D918A52E59F0215B09A119E634E6E8A9886C877F157BF7B7DD827ADEDBAF03C718AE037C0B262588171839E952721DE72180F8EED00B01F53E098B82165199C53129576036FC753A3D33AEC92060DD19AA078A496A2B214B1BFBB747A1EC64071B0A078D74D0212E6203C9698C7449326A42BCBBE8D9501DB916C64307D5F1083BCC36C0FFA18C0E4410B0B17D443481C3673D17BBD7A366A5FD1C3C5B3391A02EDA7596B4F869A91A32B5A02A05611371231BE035EDC716F534724B5225E1A72A2B2CD357F4C326F1DEE963FAB680721D40DD70B750A019E70885515F43946A0DD3DD042969139F61ECA0E9EE3107D3D28AC606AD53F236303E1FE986C38825318B7C4597B14E1A83B81295FEF49FD0F2C1E14A0B146540D853DB9706CD224B376343317BF7330B0C2721A409B856304FFFE60C24C441D5E2797D4696C0FE046D305AEE93CC6A2D89A81EB19643636A8B424B310034612105DF16516CE9607CC0A2BAC5835642C6FF9572191BC45E44D9B40DA36B607F570AE8C39D490342786F31CE6764F3F7A764665B6CB93E54922C6D89DB566F494E0EE069811AC82E8132F2F388D68490CB1C2172D2979FCE3659D7076B4F457232EB839172963F8C342E2CD18969F086F451D33BB774F3D00E6FA2BE02292F2E5CAD3ADF5DEC28932BD784801E69364962BF39E25455303E1F289052D2F0CD4964E0FFCDE29E7C074E5D57E43739DFA42AAD636C352D363E3A23BDD134BAABC7CD1621CA638DED7DB7051F0456641CA872ECDB4D3C2603DDBBCE16637010E782C4BD5230992E2EE7DD904F8A83EBAA7B4C3CEE15B10794ACE894118304BCDA9E9B1376331D2248B802557AABCF913E95F783715BB5E90A4436E4BDE7D651397A70A24257C39E0516BB1F548DA36C1F1F92A416DC1114107CD863F3BFCB360286E774B21296259756EA6040CB61738EEFE29A67895AC69797C640E03F0E9E731647C2DA93373920341FDFBD50EB6B737BB0D9FDA8EC8784920407D4F41486D8FC616430768D6431CCD789DEFF332B239FFD1900800CEDD9661A55D6D96089007E9089A117F03D7858EB4C3FE2D07E91D8CAB88D2BA5421846069FA6D4E5C9161A140CC3A288100BFBE61C3B0F0E820AB12D8FC54B054A0F4C777052495B45A7D1A883E67663DCF50C2230CA5319AB31CD76435DAE41CE1EE25ECD3FA0C7E83B0168852B2CAB674127CD7BC9DDF9DD4B57EB40128988C7C8994DC6A5FC939FF957F06C70A4056E63331F9AAD254EBF2B8FCCD580285BEA486D91A0C2DBD5823AC8F6846DDABCDE25A2252F8DA1AEB32E6969276BD2A7F94CD7DD3143F3181489272B1589FD385BA844F90E35982B53141DAEAED413054CDB935F3412E31D99C1147079CB487FEEE85E3906DAED18106B8C407BBCB7716EF9D4D34E2FF04709C7457997AD6FADC55A8FA70BC907815805578A11A012C521A1325754CAE2E3F7C9E1FFFDBD4BE31DC534961C318D1A894838E0C33806735DD11E408E500995B86B6ECD20D325347F792A3381D2A45587D9B6AE0AA27533732A6C421CA621AAC42335848D9C0DD89F14EADF2F92EC532756CD5697AD752B6260C598EC9F0E9976A950B22DAEA8B74FCC87F28B5E9ED83C0339E566259ECF06E5CE209065DE87FEEE5D1E9C466004B34583D6AE89B590EAD6A96CD2951705AC764F329E28C996AD6DB05F6C69AD2A39D3EE230F6501F1760AA41FFD936C9DBF20DE3996917322D32B946062A3C27D8BF35ECDA22403AB684CDC680DD166562D018D943369CAEFB9133A4BC4515CD5F9C08E7C22D153F0A7733EB4EB2CD8A74A4C85E40DADEF6858C5927B6EEB2B01E9B7AB02F7048C8869991068B00FC19B9545AB42181DD5CB5488222A402E827F60A8D87B09ECC88350032F998E3C10A88D4733227334812EC97C5E5FA85FAEE1A1E28A58641531B139AA58BEF49780DCEAA408986CF3C40E226C60531945A20F91E5DC31EC86C9F9A0545E5FCB79A13B9AFE9B133867BA7A38152ABC6D9F8EE10090BB71E6ADC6A6C2513B066F2565138BADA60B0BD339F9BE1AADDFC90DD272B4146D0F5830C6A53E295C849C15D001176E7774FCD7619D6EF1A30BA93CFE278AB4806BBF25CE4A4E94163F614E81DFF7EFCB015997F5138E22B80B2B00AD7579CD84DB5D1C7FB16E9E8C5D9A5BA0AD0E0A7DE79C18839D673632F3D2C7DA2062EAE844FACCAF23590B2FBF1861405AC347EB9D723ECBDE54CC96BC4D8EE2178F353310E5D69230C5DB2841D2A06A3A4E03E054D99DEFC6004A6E405FA89B198A901EA1AE9F3112A29F3AEC5698A42794E04D74D761E4AA5AD23DE271969BAF124450F4796DA1EB1C01480436AB0F5D0B1B2E6717DD87EEBF137420961F978896077E40B2D2EBB5664FD8AD89BB9333FDF46C33EF3BED21BCB5B4697451BDACF364F85462F5CB9F546657B4744EDF757DAAA4D3A9A2A6F281184C3576B1DB0B540F3B36310020BC6AC0C6454A7CC8EC1182422B17BDA202729C270194CD6044210D2B98731565812339EDFE5A0DAD79BA826D8C566C7D25DEA9BFF0BADF1E4E5DA2B884966E03FADC51C6D9BCFE877511157201DAB48AED1AB038999E5CC3FE58CCD37D40050DEE92E0BD5332413A7F0118724084EE5545FB51942DF1EF399F734FB9592555B5F32290C53D7E5017EFA2B61E29FDCE90CC3E7C1B0E545425B1D3E1ACB9089DAA786CB0122DB3FF27EA0367751A5462230F0F248147EBCCBA2E16D214E9A0BAEBE989BBA020F95B623CB14ACAF2BE6F157DFDB1E32627133F0D26C7B65A189F39955EE31D9B507B43126B06B9E4524732C8621D2274438DB7ECAF736AB7257CED950EB68BB868581649232793EC83379A16F40781E76F5CC57C48C3F5C2989BEA803E1B63768436D39AD19BB77DB46AAE6E8473ED5DFEC983F49E4B8E7CA6BF476AB2F0272C0C2DBEF1BCB064D7400BFE1B9ECCE13578A20B1D5B48133A74C5C59CAE0115BC3B50574580BFA99D58BCAD336EE2CCA5B7994C784BB90CC8F1B9A0E21B39D5EBA464DE34D46AC0BBE436C2F419D60D8AB13786F9A841B52710D1B49BEC290DE317B66B6855ABE156C07619A4B998CC582E3F54A7F457F1D2839BC3EBAC937AD3EBC6A9E6E845379CF1D66D7C59000E3F6CF6823B005728A95BFB0ACD044EB35D5ADBE8933A3637887CF91EE74BB910FDCBE797B0C6B1B056500542BD39781BDF13EBFBFE949D7BA0B7F31102E63BFC6E22693F97 + +count = 91 +seed = 9564E88F336C091EAD50C893F3EAA8351FA388682F433F7A72A34731020B9C96DFCF75EF5EAE47E12684AFA51EFB49B7 +mlen = 3036 +msg = 2601A39B6D7D91DE539EF11C3B67AE3EB1607716F587BAD5F60D311A9F4FE7F04350CA085EDA6D41C4BB6C6E13E376BF8A314DDF791AE18BE2EC0544AFD3CC27BDF270C4550E9E78D497B92349AC07755BF9167B2958BDE919123439D6F49C3408E8D88021E668A0A5FB6799330188E35EC5939B77097E3737C4F664D01D85FAAD0F583B3E95EDE125587E2A79991750D5CF804325C72DC8DDF3471EE8FDE02519D2D0CA7EDD651EEE30B3BE335CCF7FB02059BC3A47EE3C056D4929EAD4FCD82C8CF49625D5DA460DAA299718556BF0F77CC5CBADB99B64C8EAD4474601FD5C79309D4E63AAC392853072619EFD7B958F0EBDE5CBD40ACD57DF269A8810776D6DFF2E637EA57ADBFAA08DF8D2581C38CB262DBB4D1F3C65A4FA068539D2056E08DCF03BAFF006EDC688023A20728B227A99FED3B8F2BCBED2E3E6ECD8B8665A2E4D233B78D7C33F6E3BD9D0A24D13C8EACCCB53A21DDA9E7A34F9A0F031091E65F749C9EBCCF3DDC4097A121D8C68EB7883405EE34F6A8B0208EA8D5A3FAB53FE2CAD1110BFA6E094F78D5314880BB67BFDFBC2DF8AA250F1D7200FF9A3247C4976DBD1BBE99DF02A3F246E5D466F85ED2F68E0B2DE06B0F2448A7B98FBCBF5872BCAE71BF0DB4E70105B020FF130141E8DE86DBE05B7D2A234CE2EA83A38E23A262E46FFBC837E8A71F657E443052E9A49DEA4E344D497DD2DE2AFB4009D681F232BFF4FEEB173546CBCC4C80C9F85B1CE125BE678E5EC62EF04433D55D4B8829B01AC165A440FCD6594F2C0CB456C8A47444AB05A0F0717B8185930D9738E885D24DAB98E11ECFF7D7A48A4527F94FC4C9D1B9D71F5E6BB39CF92B1A6D0509FFFD42E77AC9AD6F50F8FC649B96B8AC08673F78AE8D0BA2B7243452B33AAC44B06A2B9BE1AD6A12583D3590A3F9AF0E0DC35DA88A257170D315F32F3A889601D6729433B7ADE0F719386723EB2A008634749F5253CB7D9B2FC99A1AE1BBBE7F00A536CD38F8A7237D3992C3897DF412F5B1D45E1EF5B5DC974D49CF8DBF785160BC527543458FD9378B3D4D3124214AE5676185794209AD0EE73B063CBD5B7830D00F817CA0D5CBB597C44D28E4885D935B7BF426C1339C500DAF4F2033FA6A27A4196F233256650472F205D2C5E00E7087FB73027B0C6C9AC5C1D928CCD190B8A6BB33F512CA8E2369DAE6111156DE47A24469683F4721A25652FF87474DFD92A028B3EC5BCFC244CE442752A7DA1DA6C33FC22573BF0B13E371CA9FCC86C76FCF7A1654EEF4442E47399835A06336E62952770C6E61C573CFD07B3AB631B8831FE3F5DD2C6DF68EBF2F8E02EC9F6B90A371ED5E62C8463780AC453AB6F72D38C8F5212C8B650F63B98E3C0886B6A85AE8E7256C1EFB30969532CDBF72184AECBDE2A17B9811DD4222D080049C5D36C532CC0E910779D64AF93D750EE96BDA87562EBD3830FEAD07A3960CD6DE7146603199563693392D3CCE1332DF35C2C8A2C251911D38E95815CE5A4CE5596E2D77711D87CDD54D22E8F0AB431BF8B24CE9C7BD6D077E436543C70B02F338841AF0FB86B5EA4B6A47E27C1D83E1AB06801044F546ADADA437F3CE7D788A1C92A74BA540664658E70D4F2711979153FF1589792859C3BF122628479C7C35EEE951DAB8CDB0D4D150C2DA338346988D34F8C5E589B231B5E00849611BA09711BD3A0516FD515E6C4AE1E8A3657C282C8120C97AA7A2E3BAA22B6EABB8D8212A9A48E7759A9DAAA51B538F662A05FB897067B7CF9D2CEB47A1897214CCFC225CE47CD60E86F7DEA49E220F7DDD6894B30B66460DECBBCB2E42B31F4ADF0AACDDE544B9124EA5ECB04B03C448B17E8094D489F516D23164D2317D3A1332E0500F1423136C8535D69065E880AF34CF7E36DB5FF2C18122E41880585B4D188411E86B370A024BD6E28143EA2EAE52EB46BE334A21A02E21C6755C0182B9A055A7D4C7B056E4930CE63EDC79C9FB4E2FBFFC58F776086F3487F02F8D1E7C8519C7F452E75CE5686A037B3642B95D7526ACD4A81A47112CF96A8DA7548016A22E9359198E871DBCC5852FBE14EECF3CCC5EB2FB5EC31D10474DF7D63482A03E11F4AAA2EAEDB714786E21D03AF1CD644D06BB05FF7B3959601580BF50E5F7F82FF42E9CF2FFCA0C67FFC52CEDC53C7A5C9EFB6C21092DDA374D1CCCBC78BBD9F5EE0FDF6DA6AC60C95F7C2E96F17E3C379A52D5DBD1A92DD76D1F5DFA19EA0408E0E7F7867445445CFA60BCEFC016E68872FBAC9098FD6A8E84731C285570B1BEACCA6F4728958E7924F7A7B7730B9BDC9AAEBD9E045F464071843C650D06C96D487CF8397286F81D93D0CC2008A62EE32421E5231998140909474F6D98541D899EA53714AEFE652A3D792E4C72533332C3133707A49293E3B2E06AE18F2F81D601AADDAF2FD09EC59350E0979A5AE2B721771682A1BFB5748D000F9736031CA971288F34993DF10FC06A16A6DBEED8CDAAA8127F3B71432E723558F0281459820A0F4A75A3B2716F976BDEB88BE9C73F31623050D7C1A96C84988B01D847309E1B6D7B815883F83C9BDB7FCDAEFA8BA69E25B824812B7D54530A3ECC96611897661158DAE1B4AAC112E9AC13D07FDC03DC7D5AF23C08C5E4BBFF737238FD3F1C06F94215BF2351DCE9CAE14B4DD4745AC0CD626054469C6A5286FF821BA192706D47CCEBC443DD67FDDB76797A8B78DD0DAF850CB5D181C82298616E1D3A92F7FC82FD256857915773C7AD97CBB9710373299AE8516B8A1D647A13C7BE848E0269ED6C8A91DC50D0CAD21430A3BC9E718A13D1966A0182D9A24FFF7ECBC7876C868AF2BAF2D8B782172C6719CF140E8CB877FE6D78779E1BB31C70C6C9A6A77529C51CF78A5E4FBD7FF6153B5195817F80603E5C5810C38CF43CA812ECA52F73F045E33DF4E3D04EC8C5F8B4A7399F6CBBF0D39DC951C476B9BCC002720CE89F09C3885673BBA9C90D20DCCCA4A82CE5BEB38BCD60AFE2BA65FCFB01C8793B7ECC0F0B17A9DA74F2E0FEF4C90B5132FD6BAF8C010FCB5E8E7FAEAD7F2E0DB29BFDD1811072623CEE274EF2EFB0F7D4191F332AAF20CF36FF89A2EDF15F7B284CABBBEF46901271D8C1B180F736125C8A44FE164AC7E687E9A58C3B1775238BF1A11F99BCB583D0E3C44BF4F76DCF9496A06F80CA52E24D55B54AB849D3040B4798BF5292B0574672E9F844016A52A4D4E4DAD2053207BC97215BCC1BB93271C03C9AD2DFC7485EE2ED399236AA06CF9A12972E21AFDC587A6334CD1D71A7539362D714BA26214664E3B4BC39CDB1DB847583DB8E002A2AAB451B4E5BD6FE200730BFB2745D03C82B640F4CCF58701708F724EFFDF98CB04C78DF36B7A866CFD596BF5EA18445EEA0E34ED514D0DC2625039049A0CC82711DBBEDCE339C77F9FA1DC60EDDD8D58C8F144B0F3D00227AFD8710BDC66D29809728D7FBE85F08AA38AEBE5605DA29A09CC0526FEE84691EAA54DC3744BF5A95275037FA2F600B1F91E502D5D81AF48F8EC4C1834FE625FCDF2364067048727559047E07062B4D8A7D3851853BF28BE9D2C511451E5FDD9459270328A2612DBFF42E1DD34005A3DA1226A023162F454923C0337E6C74B44BB27A3B1AC82DFD68B0A6DAF93473D97A9E4591EC01A51CB6B47E2C7A85C1FFA73C35E5CE3003BC4534A2D9B16EBF9FED6464CB1E0CC665A451616A62B6A8481E4506A73883198C144A06331224D358196C815C811B103959EDCA35B26BCF86F41D9C7638547496787885EE62B14AF431CAB2AD4E0224D33476C58B8B0833BF13B50BE2B1D682CA7DD194B793AD2C6E4EE25AAF95459302F0B4DAED907A317BCC6A5F8D76CA9AA0D799F8EA39F330D6244BFB9F35E6223A0F665A65F55EAB9BCBAB446D7FCD424DCE87F234864D2C27EE84600ED9193AFEFB6E7681BC94F514FE0748EB32D32262CAB880D79CD4FE5CC963A4F688D448F2DB2DCC5B0CA87AC26DD8506512C100273B8D4D902FC054D48D8BF9EE818AD9619F68A8904B613256DB78C881CEA3373F0CBBAC336A78CD91AD9D60126E05CB8C16E9AA8482CF1B806B2F9C57BC8D63BF008AB2E49EDE8E788BF96B9F1DB2918DC5063F3F1D5B9B1C0327141ACC0B4B248FFDCB8BCC127050D27C805E154A4825DEE6BE9C8D4E42B1F5EFC1EECC6A45DBC119AFB15CCAD19789EAAFA8B1715111AE32E2ACED2278803B60E2FD63A43317498244A7CF7342342B60462510E19D83240DFF5D58E762C093DF326EA503FD347D2A92A5A4680D5E13B305671C729179FA21BE83B0D83144E63 +pk = 58EEF138A2D2EF190F6F732CDD4C6D40D3652970DD174BA03782269C97418919ED68D7EC873951ACFBD5EE5C41BE4722435A3BB1963574D770CC45540B07994A422EE0275FB80DF4A1DADE9947AC0868AA81A7F1407760A005D9F4E1F6FDD4776A28EA5E4DF9F44BDD33B4E1EDF4D827551485C650E7A215B75A8A1D97047034151E92E8CA0FFBC2B6E2469295BAA6192CEE1A716586257B8590B28693A78F5AC82FEEFF2ECD9BC5964ED798ACF9449A820074D67F7BF76C74C2BE1109C59A1ECC742F572A1082859FBD066BE6552ACD5270E8CFB31AAC0401FF93251C797ADCD7C8AAA114A394C763395A548434156A969B0E7FF44CA32EC19A46F1A2B9D0B990B73E3114FC6B314C8264101EF82B837873A4230D6C1FCB7549361704C2848F2C6595DC74097B0AA1A9B3B4365AEADC968FC2A8C5FA5B16D35B93E88ACC7D4FB598632D232D8E1A0B6A220CF0A0407CD83FDB67F1F5BD3D1F7AD4F2653FCE51D3F7DB08C87409A2BC0DAE52523232BBF43157B3FB1F3E3A03F3CC0793215A2F39C95ACAEAA8A37446EF8D288BF9DDA1A73ABC680696265A5F1E7E5AB18FA39FE5175C9341DFB2D044720C2F7672BFBA5C1384175CEE97F461B37C15CE442796BE95DD8BBC4CC956872F6A8FFF6729BD4E4DEC9E30DD7AFA5450EE1F7BE120561FA64564EFDF125D3832D700178919F18707EBA1DB2F155AACF64B005FA59C27077EC80B2C12738C72F07E208EBD4FCDF0F4AEFE88857D635444B1EB0F6961CDF23E6D381E2609582F93795085A76358791D8C416AF476BB587953B55C305F677F61F672EAA8F70BB766AF331AF1759CCF8DFF0D89D5F422DFE7AD3B5964B70E6F03380FB1B592195CD046A753D1EFA9E12D04D016D1CB6248B636A05FF7A90042BB9A19A5AE7DF394FA82184A115FD203DBC8F0E50FCC8E9F2B38D6DD9C0C107B006C7504139508C9CFED840EA33819E05A5F790CCE6AF0A2AA0DB00F7F002BD93E56FE23CB3E1BD1808421F9AEC6A48C352DA3A6F8EEBA29E45BED2F34598068FB7C5A29F202B523549FC34D67E7E8E04DE9FD6A60BA99D0E918AC91AEACF59962681BF530B1BA0FBFAD2AD4C676F503FE0ABA0D33215398603C5B094B16E031037547436C985DD92155950721B793AF049B139AECEB4F7477B59EB1982A463F902D7D5A310B86DDC6A7FBD183FF505CB9A97E4A624ADC67B4E95678B65AB7EA82A660DA73019B2C4DE5B9CB1712440AC4ACBAE49E0832C801680F5FD7E7912E9DCA33779768CC1D38E9BA120BA67B51796EA6372CCD418588B3B345C9EFD27595360FB94FF4C382722E0D682C86BE657507A760E9542004BE23257134840A42AA8237E8F6F6C1C9BD0FF8012EF068AD643C58735CB7BA9618FA63FE20CE7DA5435B99E1B66E48F09E92AAB5BD4B73EDC7471E6770F864763788B0153328E6CC266648DD29697A7A91C4FAE52E7CE55ADDDE566029AD8183F48EBAF3A577977FF4AD6BB5E79F4456860D04DA87491619DA725433114FA815587F24E4BE8805180F47692A6D884BA6544EF89CFFF523E38C3FB82D68AEDEDF83D8A142378130F43A444FEDBD891A12EBDCEB3ED083F3B1F4BDE23549936E339B09A103F58CE8CDA064336054DEBC1267E9605B54928BAAC9C8BB410962AF27B8599A8BFFC88FB2CA14FD5CEA13D39D8F77A232C4B6D38EB6275B4C212FA08FB0FD5BE3E368707A652E729BB99BF5EE110700BC4B4A718E4141C9E42D6E34467AFC993E77DFC7162ABF8FD07196B99F1A73FA55B8294220E1C3A4C086A9FF7754DCAA6693E83A2A6F396B7376B684EC2A215421799BBF54D656711522E067E2D75BEF945FAA8A048FA512D861757168C079CA51438AAB0BA5290FAD82397361C72FDF4BC5BDA5FDB7334CC43358F8E96DD38C8FA5B88C1B1ABFEBEC66412F5768E64B6CFA457CFD0F9209AF07CFA0DDC605B8BAECD150D5B5412134C64E3858219AB07A5A8D996A6E6BBB590B61885737EC791E655282A76D7CF18ECA5D9212D8269ADF68F039F9AE64E10A4E57F32735D516157B53337ADAD33CF99493574EBF62A54DCC7EBAA9B843EC95C2932F2E2535C7CF343AF88A4A1C32B0F8230BFC1675B003832E6E08C7FBC9AFCC85F88B164E2A622AD23C81A2736DC5D8D66724D6446815822D341963516E53DBB96550F81608C4AE3CAD8EB588B32F2D7B04D16FBAA674FB7B1C3ADF76A6CF778D0FD14C055B8B916FCF9CF9B597CD67FA53896CDA69F3F643896DDA4DD41930A7760340B0377F79D8042F0D8834FC034940D92F9C1AE7B77474A4B762DBC8B2E7F9ED9FF2F133133961A4F44D9429D17FC2803BEC556666FCFEC7BC301AA3CA7E9DBD48A08A8CFD784D76BFB49265B63F7436B2610963CFA27AF6BF47D917239157F4E5AD52BCBD07F6297B62E9E7EBE95B197F5D26331C0E4C4EFAAA567FC668A4FCB4678A39BD27FCEDF52470720C59214F2DC48FC77212D6BB28092E7AD48ACFB9AFABC8A7B2195DA4426F90CB241248E396449903C232DEAFD9E82B3FF10FA4170FFB8879B9E994BAEA0A0E171AA56B211B5687A2713FF98EF1F8C1C40E0522D30C488472477CC13EBA7CC82D8368311B5E58D30B3633CFF8E5225FED382B9C0555D4261B55AD2C147FFF21AAF01F34A71FB00001A3C643EC8A98EBA40B9D6C735E135C6017B4C35BF8647B2C4FC6251C08977B531BD37EA16B70D1F8E5BFC53362D19BF8476C8E8A7A043769369A22C081591DF1471039 +sk = 58EEF138A2D2EF190F6F732CDD4C6D40D3652970DD174BA03782269C97418919C2AE6077B4971E095B437465FCC2E7640B4515278547AFCCC9A375CC23F2E9187A72245C27A16D05DF478F4B57BB65CDAD2758AF393D76923407BFA7F7A2C67A5AB74B7F01D673DFD293B8ED38D48D862D8F534DEEAE2ABFDDED4E571F4408A4625572045622104587375146087276546875831474742505315876758057288668574462015505264522253683381075261164316542550170572727451772467676778770420615286440542611331537466307440810548307015674041248313822766225308765482710133136820023441686176021555251843342422168285507005315001235366506731662228122401505356238574046353742025536775102768023310515884276744380728043828563622345875465521641572855408360421201266542510600467884417510435551162542333247816400141770224105700142212506253408686712264037548171344358608346638800566804827158837117252185666340752212783116224763506643366405668462005357184303131257187406084586857004081170253334555012503484458018351426308853443218136224127025871521011655027203104306825076664812607467884521700562757603423803162268134631733056504221206158478136228362716868357054502626680357107263047713650813538558335130303674420660426303070424604312774737101317221516228872181160220546637522726084884483676215378805520303885488447235276424401035076640866428322461264668600703857147801101823230478720385505221544420732644638415433388716352565177203627510108710532806804330747186684257735515170872204321276017785411336602514656464645070614757177666734274880705577227633467376684322143884017524466608760137727136531810363131302247350745872131647657560464840788831166068007748437778556801585458887340086848753243703237305250354115467272565601056311100444345012880363128585780153377414286366320868620435014784712832545356808641411211021183105680310878828445645847046668526646842605610737331228634658662105576387763860253177883487848208046388478514213102274581475406886070732488200658437777881544176441026230162004362468027527300565224463761317468860705577526544523851436717513867754813278177773764743438786655064815378727782304057357316223361245723824237063476360813421858676466038785507465372573381123153766746101712781461513365453318148378002706273333324803456671713851543417847522104554146644471500680312723752278208752231240164280832740312465483432380572188168760177485642513112332821765377505434348586003473646105402122372878256815387011786110254670780414308183084311182454440751177515681146724720486645078547787483185647333110408137314718078213461400420638073058731118225706465057747681503402574831662566611388635633256358710364417475346030266212084205868764307816305007874022234777517871076011470566531660208280865618510583358815352320510508387441348738661403077075411534573001012077843285241661375862866712462536422133082655154078165626585452265372866031838042445357830875038774430538581786672320823167246404514714405227624116823708635088512448150755755411876030748123082845147501283725078317286070651255251815753265346640433465366250501507861676806644817702061763068117117067342644711500311182342667523544670522572764347275414711651473378820670223288602805204447815277444486237565424128200139D8EF54F5FBC6F212D0EF10F25FE5F23BFE555FD82589F4B35B78577F4E382F4BDEFEA7C45CCBBA900C614753E2176E1F07E26E91DB086B196F412AC80A86D721A1EDEAC46576D560F9C43F8A430F812D5DB615E2EA79ADEFC382107498AA7904E1CC53363C8518AA0ABEB5AB3F530CF96FBC74953FBB51DE56D5AC33787A1C18D7327B2001F220F8825912EC1CC8B919AB37169819CA5BD00118DB55CEF25D930C6A392D3EE0826550CEBD40CCA030DFBAC1A701696BAD2058F3D7394F8B0B69167FAEC0609FCF12DCAAE2F642C444ABE4CC9BDF963579865021A63D8BF0B960F80C0561FD378E955AE8917AA1492E1DEF19744B6DA2CCB05B53A16E01FB37E1E30075629FB8DE402213D67ECEB9ED5524741C6010D33D8653A2737FCC95B905FCE390F480EBB5702C2CDD03F0B1057DA772ED2D3B3775DB217C8C725E53B40DADF620670126FBA722108B9C746ED51DCA6D2C05BD383E83F1D4A618899565072BA4934D9F5723CD79A7A59330FA233F4CE2E0C10E62BE070070E39BA5F748A9E2FC3DCC316171A90A9D5876272B3DECFDCDDD6FB09C402D8BB1E73FFA92F827234FA6DEA81108ABD9BA773987A89A06021D07BEC786EA9C43C13EE03B03FDDD715FB94FB119E0F5CAACDBB2A7D51FCA14D92B8475E8834CCE65152FBD05180E3D453DF7DB3C072D34399B65382806A0552BB24F2F2AB570DF2E9D0D6658B57E7A39CA48EE5EB1C846B1727E1A9A08FA3A95803310C32BA686A535451DD4714390F21CE87613B1A8177570D991A4793C36E2ACC0233A4C7F92E3D1E8BC1FA5042ADB78FB5AF277EE0F24C9907CE855BF89CB6C8A30772064B76367B96F8A7F1613475C20A6AB825D7C7596330521716DFD69770E7960B65FB616D660EEDC46594A9C4A3FED93F19FC836DC9B758B1A741AF0D9C565BB761338312FC0B973A5FF7266FCE39FB869EF9BC862BD050AC1AA8CA7F61E3E6C32C6F1DCAD7B41E191756809FF8DFED0D3FBE94916BF6EBB3977D5BAB5EDC82D41872BD3ECEFA0FB5000316978EEB3D9B46A5366B37A38BF715613628A8183ADD8B999DE42049FEC89941A2842F3DAFB4DEFDE79C9B169D7485F0F0A007B559FF8A0311E31A71E31F9DA15BE8BFA8528FFCB345F601BAF98E67863979CBA501D6EA36A427C1FE997D62FFD5C52C7D699580282805F7510F9933E42122D2BF4CFFCF5E8FDA567B105DB0BF26409ACDB588D91FF868E5AF6CC28BECFEA78ECC337D33360A6D719C472F48146B12728CD63A2B5542BABF8F263AEFF9281EB922BF9C5B1267A2794908EE74FB444525C42D8AF711F5944113665162E6B9F39310A5C9F00AB95C2409C74D0D468C2CCDF27162B88C669A4655015E3DC57027AB967F71494E636B7DF40E00AEB30FA864D4650D2330FDD508EC62CCE5508B313DF5307CAABE9ABCF334B9E63936E1269917FB32E151FD999ABCEA32ABB5CD639CDFE6847C93DE154F0534265B76DA0E69716429A267079A3ADC3FA87D6362A369E451E4B197FF44036FEDE8F591B0CC31C0383EB12C74FC0ED60CE36B75EFE5811D6A52BAFED6CE01D1E137B7C2DD163EA05C589A79DD953B780472DAED35487ADDB5B192E297D6BEFB299CC93686558850E27EBD972E8CBC14B2C4551F5A3963363275C20E57F6968CA1EF7561EB95CFB5E686A7400E4F70C8A1AD97F48E09CE2B6E0740721AC312D857F86F82F788A10DD689B2BEAAD9F7DB79D58899D16555BF946B25483F955567BC84D61774E577B5EF43A652F154CA1B2AE11487023A6D1577D969DE021ADA938A4433DF7D5B9774638B68DDEE324B0B66ACC9B30C81772D58F90F1A0D2B3414B24D1522C0F2DB9A3D57A80CC3464D48CA19D14A1E47C110B0DDAC2C6A6BA476F27F911BFBC289B48816EFC61E0CEDA702B4DAE57657D8682EED71D73D2BC15EA45910018E9DF5714F466461057BFC80A89641F5EB18E77E00A846FB5DD8871EDCE49F29CF2AD3AB0E9CD683672D087925D54660FB09F47BDBA40B4FC911D0521720CC519B09A9AD30571FFB99C8F4A798AF73FC0C27370D16D0B2C514EBB53511E694E31E9DF531CA99F7F863F29AD30DB411040F39E06B420A1803C840ABBADB841F5BE28B0C23099358CA08758714A9E13D0CD6BBC1D702F249BB352978D8F470CEA1F5C5E1B56C4247FEF4E962271C56C3C4B33BB63DD19C93C8713ED4B574F89BF666B09229A26B731756847E993AB1ADE3B5520C81211BD962B74387E47F1B0FA65981F1B2250FFE247C50DC9C309FB24E3897F097AB463CAC7A3C64312B569BAE7BDC1B69B4EF1C039CDB70F9095920A717846E1BD855285A17F5A5BDED47B2DA74D58C69B1C885E0C004A14E0CB4E1A72CA9581F2A81B9D6913B41489FB3ECB4B92C8635261D78127585C32FB6A6405285384982B0189932B8D49E4BA79AC93DE78A36513E8DA7B8515F8CE9C25BA0B43D59FF93C8A169ADB52AB59729F1C15113CE48471580FD53765632E3098DA33DDA8639D31EC2602A0B36516D30DA5E4209B816341D6D370052B82639FF8F1C3805B20CA998F3D22B752D1030381BB4793EA03549FD2E6365FE1124B4E01DFE0F59D5DBF0559DFDCC9E43573FBCCBCEF81948EDDF91E79C439B233760103F9109381055DDA51D088827732B8958663E80DF345F306C293E6C01F527245D385CAD3C5CB44EAE3770DD11674BFF6F653008756B0EF268D94B48BCF8938A68FF8A4B048CA793ADAE882EAB439A28EF359677CB4434A58DBA5D521E6CADC2CA65C8BE5AF279A91F329E4FD3CD04865D2F926EBC46B5516517B8A8FBE4004AB89A1D4461AEBE8DAC2D6ED504170BD1B22862A25A82626333DD178746CF5CD5667B7E2B173B7804F2AB505B6761685A6E33B03BB45CEFC4A581ABC036BFDF76AD60FD27A1274CBA25C7C2706BB065CF5C22752447A7DDE35325E8162D88641C0FF3FE01221F6C87147DDBEE5322278C3C070A7D8B7501634B95ECE00D29956C476C15CA3ED1B9F38EDF344667D602F1F131DED4F56AF6D5F9D2419AEDB7921710318698DD1B67B9226E94FF23CAF75CE223CD2F980BC19B6B80F1933C217ECBC67F17E4523C2005773A05083CB3768B8EFE24329702A1418EE75F615FB0666C0B93B3594B1238F1576A76820E40034E3486F1E663CA1F649F193BA434F520727615CAA18041A4AEE5316ECC66C9A3A60DBBC44369420405CFFEC06CE673C0D05850A8AB483D022C202F6C3F99F5208AB28BDE8BB9D4059763AA90D95E9966CEF662085AFFA91FE116BD3E7974F91167695E0BFFDFA6A89DAD8DE863C7C65755795DD0FEBE89F197C61DFE143B14B1721509919B61DCC2842F557D9380AC2F416DE067368A09E1500AF6EA5EA2FE3F91BE27BF140505A25C0B9365F55C37CA2E5FCF96705E08964A47CB0C808949DD44418F3A949AEFB38ACF492B925C2D4655D0E1A364321320479D8F394D9A89AF5E8190C5F28929939876BD3B00C4C5C522D07660A3805A8D1905275F9A767E5AA8623033 +smlen = 6345 +sm = 3B027AFD28C48C8EE32132CB8A024B3CC6DE0C3016893D17A148C698D949FAEAFA7AEF4587F90E63B00BD24AF53E2EB8D276FB40AB77A6228D545F5B65065D6EDF1235866FDE2816849E1495AB128CCD302FD469FB0B1700AC958B576FCC8A67944595940255A973E7DF781C2ABDBBA79A9098521F2B51A3B08CB152C20C23DCA2302D8D55C0CBB9824D4B703A5BBC17D37CCAA162901AA9CDB3D5590C96A6DEAFEB67AE9F8D2F33C78019E9DFE95ECAA70159D2911D1C5C8842714F8FF7CB960D0B083520D795DD664D8AC731FB6949CB436C54A4C287607D5F697DF4939798749BD7D526B37F4C9432CE6EBDA4D0ADD18784FE72133AB11473BC3DDF8708AA436C73840A8DA6E77A4CAC507CB97BFFF90B6D2DBA4488B95163F11B71CDA15A0FCC510F348E87250E889978E3C703551926BEBEE3ECF2F7C6985813A27BA0CB60772130F9C850C0B5030BFAB3997680E02137E2953B050D00EBD19E39771BE680D21632D87E4AB5FB0AD35A25BAE7B1BE6184019547EBADC0D5DFB0BC5144C5A99D5EE1C7783FC2E81FB9B87DA5D21415319BDFAAAF3B3F77350C7EA150936D952CAE957563127B837355669E1F439DDAAEAE932ABD343246BCE82C5B4411F76A057153754242960A273FB23584B9635DD7392B5F8697CE7DB95DDE4162ADC8A80032BF0284E358CA07F44D7708DC0A17937A3EA58797E2CDA4CE436DE9B1302B024110A0EFB6F65F3593A14B0050D3B07E78EBD273508497E336145BA427A165AA1790CC4782EA7E5B9EED19902447B9A4E6396732C3FD3BE2C8354F69873495AAB09C6021C44709DEB759C22A52F84A08FEBE2A080B14E8EF87B6EFF079BC3E175D09B0AD0EAC719034EBB88553AE0259BB4495991A2F0A38D6F6E53EE60C2202A33C2FA384BDCA4F15FC5647814AA5B04B9EF628C35B6EE9E5F37138FF3D5317C8AA2BF4CFFEE1DB58AE926955B62D5865742882EFFEB54778F78390C6EFB8873E7BC2E9826F0729433D52137FED90CF539B581283695CC9D4EA24158A493EE9B3B507FA055F6F3CAF7AAE47F710E816DBFF1E5B78A9FE6EE95F13DF4359862B288CA192D8EB9ACA9E7FA9486324282AC791D682A08FE8246B862C792C190C63C5BEADF19FB0F07158B5B04DE7641357FD7604A8698AAE3B72C3064F00C55ED44D50A05F0DEBB489D645BA3C17B4F771005FA86338925C2B6B3043E30A0A0789E02C70AF7243B2A03937F8131558A016270B999A95EFABE44949ABF033A3FAD5E23E66846CFDDE67840325968F0539AAFC6A808ABD1836DB772AABD91B7ED2C204DF4FE40BD656055EF397CD96C59880C1E1AD279874FAF7A3085CD1C43E41680B920C8EC466C85561EB2DC359DDA9B7D92EE7D155BB963EB9EF2EDAC179EAB710421F9789A6B018466244D7F3DBAC9587A4E53A40716BE52CF8434F888ACB74007F191B5C594F79434074DCC6E98334E84FFD07A57827EA74DD5912F7CE6610EF862801707CD3D45122B1B35EF15E11655E1353AF4D51CE88892095E6AF0EDB166844EC90418B8B67F5511EFF1D59504130AE509292F3B258FA3A9FBA8FE3F9164FC6C810175D4D0E2C5B1A6590E47B9235E12AA3E59D05314FA46AF632B9B7E0640D789CA4DE7E7184C63FBD6310887C6BE2B014C907BB6A0199667C02D6E8DFD13280AEE4099A92D76336011D857FF91FA18FBD321711B79920FD55BEB5DE988CAD0E7A7556B525158C2EF46240A875492B31CA6194ED5DBCDFF14DA44BFDB06CCADAEBD0DBFDA2AE69883E17EB6F9904F64797903A8696B9A5178E51A45005C61C26DEE25A7B457D384BF22F3011B3AF56C25BB1FB0FAD9CA43C9B2213226C68092B12FBB8AF57D91B7A81EFC69C40B8AD471C6C2F838492101C773D4A7EF807559EAE01F9AE457A0182D14A1A40751E01716111420F7EA9AA30A3697B5A5C24E73037C8B7C32AF6B42EAB00E3367BDA97CFDED6A8364C06BEE6360D4FEA1C1D67A3C4152DD7DE7483504ABD8A3EDAE30716ADCF329B5D34140C2CA0DFBAF79BC3C7C14207ABCDA7D602A9AEF507FED300261E13166C91162C9FB7A61D091707E932BC650B24AF8C5A2444E133944526F8E42402EF8E854E60778EE19F734A1A2240562D56D3D80633C111452C3C90869F0EA582BCD4EDA1B07A36FACD03669E4963CB89A33A0E2170C3146136A30869DDD87030E2CC9E9C4C06945C2EE6889F120DB1267BD6543B7143B42039BFC370995A1CF68BACFBD60B99DC606D5B4AD5E5865282E5251995C8B7F78A4DDD72F5671831241DF939C461B91B88CB7F708E6EF7AC5034BA9F8331B8E0CC445F7EEE3F4127C61DF64C4BB96DFB0E8BB87E915DE988169CF8550E57DDF9E18B29779D08EF2E824E1D008A761688200FDCFA46555A8E597689B01BDDFD9AAB2CAA0BCEE864A484F06DDB2C4F59441686EF0EEC6212E84200A4C1CE571823030A0B1D51046C3E7B4AB246B36BC8FAAB8E7D543CF5EB8C66363DBDA6482C1FD1FEA8ADF91922F6658BFEC9C0FFF5EBA6E4807ED57DCC76E7D44F9079AF22A56E3523CA90A0701BD0F3FE0CF36167AE18ABBCEA09926707B15FADFC6F49AF91C890E25AF32FA405B1190D8B6ED3685B1A56573969C7F6B45859F0A239E092BE8411EAA4579B660DB905F469CCAD63A170959955C2C2EB1C56028E5A34EFA273EF1E90CDB3F330017C0EF804A86BF9815B60A153285C07C3C779F0A2F377B1076F1929C90730DF2437CAD6C91AC1189263AFC224ADD8D474C774ED1130000A3129C6A0EB544F5115276B78913D4184539ACFC567CB4DFE994A89B2AE2578F160CF32323F8D5B5EAC14858201F727C85D6A3D5BEE08F23328DECDC7A7F3A2A7EC0394694E76F5B41E49686B71B3C979ACCD61409E5AA430EC9F7EF2C2BE46C880208909BEE3D4A397D1F879322AF0DD5569D6E2E58DAEF44B8E42374C52526A859A8D9F14052EC6AF0CC1AEFDBB0DBFAA628A36E437E1DC36233BD3BD75EA3D4228B8CF774DAC1A495BD512C6716F77D68A892EEC1230227A3360799BED8858945766F2DADD4630DE447CCEF61B71F55CCEC241346056493CF4BE6C367AB03439F1A363767F35ED0CCD97E1CE8AA24DF3A9D27635367215A95D1C886EE046AF2C8A1A732BDFB9EE0AAE840538F38B9088C85C1AEA161F4EEAEF1F07E2B4F1D67A151D628DC100F4297C3EFC8954AAE41FA19BB5F96DE833CD61BFA8476E3985037BE0CD372647EDD299FFBBA7F7EA809D1493A5E6A4B702432ACF643AD39932815AE7729D93CD3D634DFB6A394059D647F0B3CA5A1B3F6189FF195EB6749FBE98F0F035753DFE1E32A68D1DD3E8C808A9205A919A4386EF678CC594C4AB05023D71ED4F5A9488C0AACBC11EA346DE9528AE14D381F10008BD987BEC00AE8B09758B4CFDAB28FD82CD5E221D3761E92231FAD02B10A7B502E26F6860EDE70CFBF837BE883BF2DBFCDD474EFB9319E3AF72A84E589C519BC5109689F210D3F2288C2D453F762CD5B0A4145145C8A8E9DD10B278071A37AB68E0B554D73A09996BE736F61F1AE1E8E171D160BD92F6C4FD273FDFFEA514E6DC215502AFBED1A7183ADFE3104181813FB1791F6D7EA90C57EE92F59D4EBF6F3B347BDF198CD3DA082F6420F78110AFAD309A05E0FC93B5E82C8A16F5633DCA88ECC914AC897FE1891B3E37721E50C845EA2319B598B1668F8CD5238232B1F03CABC45D45769B6D2CC698DB95912574A222D105898C8949DA0331562ED15016171F5E800100907D964DEEEA385BA694E4A9229B4381C01EC730F4C313E677FD53117E4B66DF7E328AE1C61D349E775EE242205F5726B7A4982AE1774CB1E68197F95A811C5AF3823D1DA606E28ECA0E45EAC382FD885FB07670319E0296D05E9D03AD5F23315C25F85CF244061B16A4B3BBE3BC0E61B5BCE2E7F0C90A650A0F43F78E5B982FF56894F0283400B51ED325159F412FC4195D81577790659EDABEED1A7CAE2B0236C944FB3B9D5E001DE28ABB2DDF3D36E087776D22614DAC99487D5DDA34002CD993D6E3BE084E00DAE31E42370A23DD7905731531259A48758B633C7783745B6C98C82B6C51F2B52B0AAEA28FA3E7E29E170A3027E56DE166F962615DB813C4D196C7A8CC17BD8EA82343DF334868E02A45943EB0705943D20B90895BB7BF540947CC9C12D1E828B527AC90FDB897682A3D4EC58602A6F18DFBE4BF2B9F6B8481DDB76ED7A1E5E5D9DB64CE21AC4CFC09EC7A7FBE6E0A7E66B673D8E3EF8C34AC4349912E6091DF534C362FCFC1F9040E867596761FA648416AC750ECD6214759FC721966811C4E067F719B7F44B16073F5B6F94974259489B1B38C7C6E147AC6F2DD46721A71592847F2F7F226054B4543B205EAE0953EE463B767C87231F5033AF16CA3BF0969CC35E4D594BBF3459936A98D016A93275DA962511423534BB59B159E8CF7CB4B5A35B240A4D96D1230F95D921966C48AD9B8E72BA6A4FDD583A8385AE1F1E7E6E8AD5795E24209F900EA1B5980A2C9147F833DABA44AE5FEB4EC6566402EFA28816ED1BCAF115F6C205A320A388B55D35CC0AF07AE330EFD6F8C08C0D8061D7BC2CCE3FA096A95F2F8656D75950E65AAD8F42A363F536EA1AEB8CFE900154A5AB8C8DADD00000000000000000000000000000000070C10151F272601A39B6D7D91DE539EF11C3B67AE3EB1607716F587BAD5F60D311A9F4FE7F04350CA085EDA6D41C4BB6C6E13E376BF8A314DDF791AE18BE2EC0544AFD3CC27BDF270C4550E9E78D497B92349AC07755BF9167B2958BDE919123439D6F49C3408E8D88021E668A0A5FB6799330188E35EC5939B77097E3737C4F664D01D85FAAD0F583B3E95EDE125587E2A79991750D5CF804325C72DC8DDF3471EE8FDE02519D2D0CA7EDD651EEE30B3BE335CCF7FB02059BC3A47EE3C056D4929EAD4FCD82C8CF49625D5DA460DAA299718556BF0F77CC5CBADB99B64C8EAD4474601FD5C79309D4E63AAC392853072619EFD7B958F0EBDE5CBD40ACD57DF269A8810776D6DFF2E637EA57ADBFAA08DF8D2581C38CB262DBB4D1F3C65A4FA068539D2056E08DCF03BAFF006EDC688023A20728B227A99FED3B8F2BCBED2E3E6ECD8B8665A2E4D233B78D7C33F6E3BD9D0A24D13C8EACCCB53A21DDA9E7A34F9A0F031091E65F749C9EBCCF3DDC4097A121D8C68EB7883405EE34F6A8B0208EA8D5A3FAB53FE2CAD1110BFA6E094F78D5314880BB67BFDFBC2DF8AA250F1D7200FF9A3247C4976DBD1BBE99DF02A3F246E5D466F85ED2F68E0B2DE06B0F2448A7B98FBCBF5872BCAE71BF0DB4E70105B020FF130141E8DE86DBE05B7D2A234CE2EA83A38E23A262E46FFBC837E8A71F657E443052E9A49DEA4E344D497DD2DE2AFB4009D681F232BFF4FEEB173546CBCC4C80C9F85B1CE125BE678E5EC62EF04433D55D4B8829B01AC165A440FCD6594F2C0CB456C8A47444AB05A0F0717B8185930D9738E885D24DAB98E11ECFF7D7A48A4527F94FC4C9D1B9D71F5E6BB39CF92B1A6D0509FFFD42E77AC9AD6F50F8FC649B96B8AC08673F78AE8D0BA2B7243452B33AAC44B06A2B9BE1AD6A12583D3590A3F9AF0E0DC35DA88A257170D315F32F3A889601D6729433B7ADE0F719386723EB2A008634749F5253CB7D9B2FC99A1AE1BBBE7F00A536CD38F8A7237D3992C3897DF412F5B1D45E1EF5B5DC974D49CF8DBF785160BC527543458FD9378B3D4D3124214AE5676185794209AD0EE73B063CBD5B7830D00F817CA0D5CBB597C44D28E4885D935B7BF426C1339C500DAF4F2033FA6A27A4196F233256650472F205D2C5E00E7087FB73027B0C6C9AC5C1D928CCD190B8A6BB33F512CA8E2369DAE6111156DE47A24469683F4721A25652FF87474DFD92A028B3EC5BCFC244CE442752A7DA1DA6C33FC22573BF0B13E371CA9FCC86C76FCF7A1654EEF4442E47399835A06336E62952770C6E61C573CFD07B3AB631B8831FE3F5DD2C6DF68EBF2F8E02EC9F6B90A371ED5E62C8463780AC453AB6F72D38C8F5212C8B650F63B98E3C0886B6A85AE8E7256C1EFB30969532CDBF72184AECBDE2A17B9811DD4222D080049C5D36C532CC0E910779D64AF93D750EE96BDA87562EBD3830FEAD07A3960CD6DE7146603199563693392D3CCE1332DF35C2C8A2C251911D38E95815CE5A4CE5596E2D77711D87CDD54D22E8F0AB431BF8B24CE9C7BD6D077E436543C70B02F338841AF0FB86B5EA4B6A47E27C1D83E1AB06801044F546ADADA437F3CE7D788A1C92A74BA540664658E70D4F2711979153FF1589792859C3BF122628479C7C35EEE951DAB8CDB0D4D150C2DA338346988D34F8C5E589B231B5E00849611BA09711BD3A0516FD515E6C4AE1E8A3657C282C8120C97AA7A2E3BAA22B6EABB8D8212A9A48E7759A9DAAA51B538F662A05FB897067B7CF9D2CEB47A1897214CCFC225CE47CD60E86F7DEA49E220F7DDD6894B30B66460DECBBCB2E42B31F4ADF0AACDDE544B9124EA5ECB04B03C448B17E8094D489F516D23164D2317D3A1332E0500F1423136C8535D69065E880AF34CF7E36DB5FF2C18122E41880585B4D188411E86B370A024BD6E28143EA2EAE52EB46BE334A21A02E21C6755C0182B9A055A7D4C7B056E4930CE63EDC79C9FB4E2FBFFC58F776086F3487F02F8D1E7C8519C7F452E75CE5686A037B3642B95D7526ACD4A81A47112CF96A8DA7548016A22E9359198E871DBCC5852FBE14EECF3CCC5EB2FB5EC31D10474DF7D63482A03E11F4AAA2EAEDB714786E21D03AF1CD644D06BB05FF7B3959601580BF50E5F7F82FF42E9CF2FFCA0C67FFC52CEDC53C7A5C9EFB6C21092DDA374D1CCCBC78BBD9F5EE0FDF6DA6AC60C95F7C2E96F17E3C379A52D5DBD1A92DD76D1F5DFA19EA0408E0E7F7867445445CFA60BCEFC016E68872FBAC9098FD6A8E84731C285570B1BEACCA6F4728958E7924F7A7B7730B9BDC9AAEBD9E045F464071843C650D06C96D487CF8397286F81D93D0CC2008A62EE32421E5231998140909474F6D98541D899EA53714AEFE652A3D792E4C72533332C3133707A49293E3B2E06AE18F2F81D601AADDAF2FD09EC59350E0979A5AE2B721771682A1BFB5748D000F9736031CA971288F34993DF10FC06A16A6DBEED8CDAAA8127F3B71432E723558F0281459820A0F4A75A3B2716F976BDEB88BE9C73F31623050D7C1A96C84988B01D847309E1B6D7B815883F83C9BDB7FCDAEFA8BA69E25B824812B7D54530A3ECC96611897661158DAE1B4AAC112E9AC13D07FDC03DC7D5AF23C08C5E4BBFF737238FD3F1C06F94215BF2351DCE9CAE14B4DD4745AC0CD626054469C6A5286FF821BA192706D47CCEBC443DD67FDDB76797A8B78DD0DAF850CB5D181C82298616E1D3A92F7FC82FD256857915773C7AD97CBB9710373299AE8516B8A1D647A13C7BE848E0269ED6C8A91DC50D0CAD21430A3BC9E718A13D1966A0182D9A24FFF7ECBC7876C868AF2BAF2D8B782172C6719CF140E8CB877FE6D78779E1BB31C70C6C9A6A77529C51CF78A5E4FBD7FF6153B5195817F80603E5C5810C38CF43CA812ECA52F73F045E33DF4E3D04EC8C5F8B4A7399F6CBBF0D39DC951C476B9BCC002720CE89F09C3885673BBA9C90D20DCCCA4A82CE5BEB38BCD60AFE2BA65FCFB01C8793B7ECC0F0B17A9DA74F2E0FEF4C90B5132FD6BAF8C010FCB5E8E7FAEAD7F2E0DB29BFDD1811072623CEE274EF2EFB0F7D4191F332AAF20CF36FF89A2EDF15F7B284CABBBEF46901271D8C1B180F736125C8A44FE164AC7E687E9A58C3B1775238BF1A11F99BCB583D0E3C44BF4F76DCF9496A06F80CA52E24D55B54AB849D3040B4798BF5292B0574672E9F844016A52A4D4E4DAD2053207BC97215BCC1BB93271C03C9AD2DFC7485EE2ED399236AA06CF9A12972E21AFDC587A6334CD1D71A7539362D714BA26214664E3B4BC39CDB1DB847583DB8E002A2AAB451B4E5BD6FE200730BFB2745D03C82B640F4CCF58701708F724EFFDF98CB04C78DF36B7A866CFD596BF5EA18445EEA0E34ED514D0DC2625039049A0CC82711DBBEDCE339C77F9FA1DC60EDDD8D58C8F144B0F3D00227AFD8710BDC66D29809728D7FBE85F08AA38AEBE5605DA29A09CC0526FEE84691EAA54DC3744BF5A95275037FA2F600B1F91E502D5D81AF48F8EC4C1834FE625FCDF2364067048727559047E07062B4D8A7D3851853BF28BE9D2C511451E5FDD9459270328A2612DBFF42E1DD34005A3DA1226A023162F454923C0337E6C74B44BB27A3B1AC82DFD68B0A6DAF93473D97A9E4591EC01A51CB6B47E2C7A85C1FFA73C35E5CE3003BC4534A2D9B16EBF9FED6464CB1E0CC665A451616A62B6A8481E4506A73883198C144A06331224D358196C815C811B103959EDCA35B26BCF86F41D9C7638547496787885EE62B14AF431CAB2AD4E0224D33476C58B8B0833BF13B50BE2B1D682CA7DD194B793AD2C6E4EE25AAF95459302F0B4DAED907A317BCC6A5F8D76CA9AA0D799F8EA39F330D6244BFB9F35E6223A0F665A65F55EAB9BCBAB446D7FCD424DCE87F234864D2C27EE84600ED9193AFEFB6E7681BC94F514FE0748EB32D32262CAB880D79CD4FE5CC963A4F688D448F2DB2DCC5B0CA87AC26DD8506512C100273B8D4D902FC054D48D8BF9EE818AD9619F68A8904B613256DB78C881CEA3373F0CBBAC336A78CD91AD9D60126E05CB8C16E9AA8482CF1B806B2F9C57BC8D63BF008AB2E49EDE8E788BF96B9F1DB2918DC5063F3F1D5B9B1C0327141ACC0B4B248FFDCB8BCC127050D27C805E154A4825DEE6BE9C8D4E42B1F5EFC1EECC6A45DBC119AFB15CCAD19789EAAFA8B1715111AE32E2ACED2278803B60E2FD63A43317498244A7CF7342342B60462510E19D83240DFF5D58E762C093DF326EA503FD347D2A92A5A4680D5E13B305671C729179FA21BE83B0D83144E63 + +count = 92 +seed = 4D0788DE958A707899D5DCC02F756A10DEA2EFE0214F5E01B3281DF4E013CA75523ECEC64723D6C8BEC0B92C4F821D8F +mlen = 3069 +msg = 9163116C86E64D90D35CB216FED71BDBE6A0797A48CB915F5A40FC8D31AD340767058B28CFF0C240720327E12E653C1F98B5755D8000BC01324DB2820781B94C4434FDA76223845E0613E2526A95F28FB4A768B1487AA34DADB28CBE8DF4FDB510DFFE672FF004F37C7AC32072A24C0F12A050BB396AD56346F4E0BA75C0EFAC162288A7EE8A63255DBA5CF451A0932FD56B05E40EDD491293E045A6081F6586BDCA10B41A6970D8F9A7B3B6B58AA772EEFA9ED22C9A24A384D6947770862BE4FE45C5E0E56FA4D116B79699ACE41E5D9F2E4C245059CD798DD986A3763F527E0C9D5A88A09C4D76D447348509FA7D9BFBF3DEA59EA57711A3B1A9352123D4A74DF273FA24A89BCAB42A6D455B5FE3C503F1FF638280F87C740B9E4C5FF20133CBDFB8D08CAEB7DE9F26811D437E6EC8C3143C0419C2F5135D25C7F40C7908C03F295FD26F1A03FBC7285196BE40ADC6FBDDDC912B3BC94B0BCE08DBC2185EE3CB766325068DB55C31FFEBE4B1F6848AD4FC201A5FD056916A397ABE6A66FF9BB03B037B50AC509E46CA441ED45812E3334FD7036D190A7991E55CB817EC2A63CD800F293277E7D15F086618B55AD395C614D168FCEDFB274FDF4FCD50CB976F68A266C5365E02A1ED0221BA4E13E70304824F94251249CA23C089B4D54E02EA03FB7C9841DD30404428AAB2519D68CF564D75D18530C7D062496C120A8F5305AAB23AE52255EC919EB0CD875422B144BF47F7472349558E746B0EB5493F1FC40ABDADD2ED84A8B31221A485052369FD0B552972C9FAEB1A78E826BA4DFB9E91E301DB589E9D7C256E7051692C48534C6A5E2BF0F45B78ACA66D5F53E549827E15D64E2F294F93D43B9F36BEDCE6CEBC05E56CED3F846635AE3C384C3FD55B969CA31E8C625103C2B24E7EE45E92984CA23A331C5B14281B20116069C619D82D6080C6FE35C3A3FB2E73B695CAD9C5D3300814FD65738DCC3EAFCEFCD24361AAD13A25B3570D2D509FA449612BDB5B49E0605D7EB78449D1DB40660AF0F3D8BCD4869B6F175CD28AD72FE2668C3DFC1D4963D0EAB309DD50B74B9D2947F86FBE9864AE5D0DC69B55B182AC1D914B11F631193F5F1F897CE52CEE97D7AE95631FC2F2A1AE9B672165432EB2E5633B55185AFA5E883268D8503AEC10774D25D39C800B74405414FB06C55B8C48835577884D6B4F2F128246563066F8F34D76213E0720E899FC1F11A3B0A591885D82C688E40D6B44B54D6C7C6973156E2DD50C40A28D2EBBA60F5117D64646CAEF72974F4B8362E4820EC04F2F373DA8D883AF27518567688146F16BF4E10969E70BE8ACE5D2FF6A135DB1DD738907EA355FB6D243904F6427D11592672060DA14443B55A9089167FC9D5EFB2C64B0069795C341F90DAFF684E566611EA87BC40A4C45F22C23AB6888A754B89E4C95BB54629CE74EC999889C82714B5AEC703DE7BC080B0D2E622ED53B645688CE164ECDFF4ED66C86049B2F9077F2A94CD685294F8EA9CBC1DE29A48D39F6B308288DFDB47731E39644B576A298646752F5C53D7943A5D0F7DBBC9604902B61B8EDEFEB5AB7E5BFDBC1E6723E6047894547E440E918038CC13B47424CCFE1A207E08A40524B553C750683F5F6C960F05836FB9B28C59E1B471FD5331F1811DDF3EAFF73798B7FFD6C9714978988C440CA906B4782A410372D70EE65A0A803061708003688F576E2D3A22580B706149A24B93A162BE9F1B546680A1DB2A8E54A576C28B4772C50A55161B2994514369C2192B2C90017CC8282F41D28099F38B2F1F0D2C0E46B444417A2078755591F00F01DF0CE72B1D1BD255A14D2BF67AB3E630F95A5DA9BD9E10F08EFBF6FE722CF000C32460FA3271F18B39EAA4487C1DDF828B6BEDF4523837BB3425BA1C1606E8D5D1E6182AA6A74F068F3E90B42641347CA755779216AFBC99603391FCEF4E8E5AA202BDCA24B83FF42F4F01232D3F2831CDA2DB76FB93A4CF6E9EFB71B5438A4B74C3190A8901D73566C50727559BA9BF6317D116E8F5536BACF064D3F86282E0F88DD40B63E75519C6A8E5664AF8E1029FAE87930F523E4DC7C2DD6DC3296A42A59F178D438866D929A70951BED05533EB1D818B7C7C595971C26B1D436D26897D6A6EB036A13511AC4A3BD724F2CA57FEF07D2C0730800D35683D745125F4237ADD64B538B7DAB0D0F258DAF7DE1A74F74A2FD010CDEE810F514FCF6045F0CC84E2054B5F4EC2772718FFB4CCA9C9BE77F8F007333860180D60EE4DD8CE976E63FF49AA11DD42FE6946515E59DA3E602B1861BD3F63C89362BCFE8438BC71959A617D8D63331A3D903BC5734B777FB14F7A2B063D79EA8637AC52C758EF88DF217B95FA8FDF1009AB28D8A4F318F78772568CC7AA9E3B3E001C0111B1751B698EF1B66383D6B3CA942FE4F66FC97613CFBBC03EEC9D0B7E08F80939D9A2EA1F72BDA7B0D655AC3A94B4C699D3EB1BBD6076E63EF5C1FE9CE258B55D21164CA7EE03BB53D8BA4306F695E648093542D769DA95A35FF3A2C071DD8ABD5A82E217D82317065D50A87B689AE3A2EC7887957BB243373CF986490961220EA61EBE12AC0287B185070E124FC518C300620B4B6D4F29402B18C2462A7985C00E2A87691053B1FDECB7AA264F33E27C6B201CA6065EF79E5266513AEA92E8D3E646453C089B5EBA66D14BC45844D0240D2E7737C16668FD53E38A93D6003146019777C03644C300D06927EF6994AC794914EFC5BE0CA81680CA8C9752908FBD2D56D7FD1FC1C76EED755408F1D7802F0D3D0F347D82B162EE6F0A2A890E083C20B822FA6C4AD627F4AB5D1526D83D897C244D6ED4A427B23B4A0C19F4E8889257C1373764AB7063B5DB8ED9C2443CB012381A2B3365EB568649D7CCD52271F25FD22FDC397E4C9C536EBB452CD2CD10DC5010BF433F88CB58D2B9EDF2BCBFA83B782FFD4388F1BCE3F8F9AF5AE6BE590BDCECB1BFEA846D2F0199ECCDB0C7E4D419F69B6A428EAEB462B67AA40340417BDFEBB6039AAB8242E39F6C11EC136D73FB315CF71414A2A1203AF08FDEE34ED0072C27462395815F7779012A41EC526BE53DA954E1F7A7EBBB68FEB15CBAEA8ADD6CD0F2FE3D3615991AB54F4C7884E8A80A9535F13BE2ED944B3BB315DE8AF2A70439294CD53F041F41D3562BE840C78EFCB08661B1731FEEC46A9091ECEDE3A9FBC2DAE42C72EBDD84308E95644373595DB62157DBA7DBF124BB45DE6C2837B0066673BFD215FF915A8D41637EEB029C345E444251ECBBCDF79E246A80AA4591976A00DA06C759C6160ED1986F8E15A562417DA55109174628E7B11D49586882851205755B4F99A875AB3599FDCC094E4A2164E1764D24DE805FD7B20EFEF2A8E23FEA4E206DFA1FD9C31D90C1FECF745D3EB886190827D952703AA6A99B5000D8EE9D51DE94A82DD053B6AA89CD7E94E92D4AA93A9224D3F688B5C834A53F2993638166A3DE78ABA7CB930CC5845F9915E6523683715A187E940FA2A978B5CA4C3B80DB62E96A600F1864BF0B1AAC23B1330B13EADD3A2F07CE7181D0A9497C455D228278E5CC3E4C00A2EA3EB8E5B9CE2799256302B0F8F1F829D3A3AE8AA7CC4EA229C5AF476C01B8D48A9F6987DF57C3469B6EF6DFCB488A3D5B91FE17B5798FE154AB8399A2E75F0D15B2A6AA91302056266B22A38A604EDC374E2D2155ABCA119C11DC6827A47E3CEE7032F6E0F59708DFACE221E47041CFFC59CE0334D9B7C5E91C2C320A70EC2F32906624128363C893909F47BD970DF652D5E6C2324033F32B1653A039F8C051D9DC8F839C50F5696E9E08F7F1CDAC4750B429AF03176FF6E643ECA1D8FC710C6CDB0D26074D85316F4C9084D5F453F6D36C1CEA0E389F3462E1478E2503C1DB99FC46F3F0627F173672C21F3CC3B483998192E81EFA689819D0007762ADBD141A058587E030A3568E412D25662C40ACDAFC3C6EE30C10CC23E3DDEDB6C73085C90C89B1218D67A328F06C3637A786D4715CB9F9D8B0B22D920B68B0557CC80A56FCE0B6E2D6627DE576E308757A8F37821898E96785AE323E413D3572205B0A5710143A2621C258C76C7C3FF7100A2FCAE99C84D1AB1CECF7FC5B1E4698BFA3BA2A0856A65F2D4F291A4A164C0381D70D1213F7E40FC4BA42C43EA8E70043E27C5AB0827559B7CF7F2587D0D2F93C6382CF54E92764D815280D68C554E5B6FBB351BD18635786299DDE39FCAF3EFA708A3F18701EDA1579BFB0BEE4FA1F1ED6E09D450D427E4B91F4552F87F31F06F109E74AF4BF301481452AAFA2146F6375DA467EA008BAFC3C8408AADD61B07C28C55249EC0C8BFDB00EA +pk = E3B5A2F2EE49231383C023707B5EA5CD6682CFE4B65C0A8452ED137C33CF2B52457B600177CD51C1469F03B8E478563661953E9132FDE7214277C1AB005D8DBB80E082E572198F2590982BB5FAF4495BB8EECD49B2DEC1FE37BD51F607D7081296228413FD040F74E9A94BE42CE62FECAD05AC809B9B064A6CFA6843A2A9075DE13AFAAA598F059AEC6532F6B1BCFA12BCBC2DE5963E5A5CA71CED2DA16FA92DC389940FC7E0234C1DC4A2BBC65F202FEC3AAADA1BA405A2E294CFA56D7E2176CD395903445320716FEE13650862FF8FBD819BEF018B4280843A7AAF6828FB2CFCE00C0C260D76B2F38BCB193C3569D00A834D4D024B6DD289BC4EC3F8808BB79004456389EEC90549CEF813DF3F06C2E3BCE3EE62211A2D3E9C427B1D6A8C7FC25F5B674518BA6939A230C72DDECBB9E27C33F021411937B68970033D5BC1CD2F2A5043759A179817A6CFB21E2CB061D447086EEDA58CE1CEE9D9A431AB9265BB6AA908BE2C67230C7B31C8BFA4E7DAA8FCA7D703764C990CB72F6C63F99CDC719C35FB07D1BF452B637751E0F8C1ED83FEA68C27B1DDF37651797A3721B1B18FA183B5BD0CCEA42F4727CF3EDE3AA2CE53AD7E9F395F9E34831C14677B9E9574993FBE1EFA2A3B0290E50DF8FDF98F35F6BC5D87E51CD45F157879E11E14969B790005CDF8BA102940CCEADCE11D620870B94F13CAD55A8508BE99F1EABE8B76928E24EBB358C0F5D014ACA33AC5E5CADBDF2BB0BBB94F5997322A6795BD4959797D9FA26D6E9EBBB6E58507498EDF435068BC0587904C65EC8403553B2AA7B226F0DE6ECC1C8B6E2BB188DE701C222AAD88E244AF36E26D7F506DDF0A41D0A71ED36085382A403BC5E279CF130C9E10EA0EDA9207337A467D3AA735180A3A1110EF9E1548DDE2904DC8166CF5C51CB884D97658021C12CDB8E0A0DC3B68A2AF967FB0C2DCD2D1AF2254FE191298752D8FEA43F0BE79FE10D2AFE8860546697D85C2F7CB4E6035BABD79DABA1EF04E3BE15FBF571A1ED8C57206BEE1EAF36E4E3DAD3F5E1B5DF2F21D552FDDEA337FDFB2931736019D89765F3C98372C38BECF195427E42BED619927B111D92903F9ADE6EE2903FC3EA82E025A4BD8BD14B5C35AE68EEA52298EDBC5DB79B1BEEC13EB4FFC11A99786B80952651C342B953810204033B8E92EE325482ED56F852CA333192A0F543E8EF5BCA7AF3AB6AABFAD7B0229C542BC90135AA5F1DA7C291080755570B20CCBC014327DA6930736271FEFD0F7FAF3F7E36DC470CB2EB68A0FC7318A90860C668E8912F81E9A6F28BBF59042A2521510951B31C451069FF28C58BF699EAD8A93FE24003D9533A4734B907AA0C7894BE8AB27A1F710B867ED2B02B9B26C04C50425A41D98BA0D2C1DE18898E9B28AEE4A74419EF630F0D03F0833AEE2F706948CC563923CF7BCEB9AA6BD532FA67D8DB99287D59110F4E6754E466792B227888FA861A7D757E9CC77E30360C8C933255319E265EE361C54365FF116A34C038CB921E0B36C83D7F63854236DBC69A663C38F72DCD3FD465043802B579C2398A96D6EAB1484A2CD3FEF20F172BC5142D3819BD729AB1DAAD8F20AAF831909F62DBD8E3A4D8E9980B5E363A09F2B2ED1AFCBBAA21B71A3080BD658F0DA07A39BF110C84FEC575C32831B3F107C21FC745FD78249D149412751EDE92C7B94A6524F9F03F186A8F96887263DAE4EB177024433B6EC45B4B04FF7BDEE57C37582714E476FE8D569A7DD7E7F83055A0FD33B855181168D924B897D68CC8B184921A5EB26D324205504B1C67BAE60B6F31F4AB203EDFED8D578711DD78280B33AE802282F7A2004816EABA1E409FF98DA0122C86E907957AEC6584CC5AC9FC7ADF9655A962C87FDDC06D838B343400E3D701DA55F6F81668EC83090A722280218FB55DC1A0DBD9EBCB759824FA57CC25130277A7638392D1104D089D4905CA330BA70D8D5E36B3BD11FB00B7DDA46E8D1F797B29E8D85EC32AB45059EB85D3079AA0698A3566E21AFE25BDADE40C810CB18DA4F7B8C7C97A0A62D485FEEFF04B5114A26FD147DDF6622CF50E9BBA637B7DC3077502449F28D67D8A6B7B55EAC889A7FB305026A3B3E9A7367B0DC3E19C23B99505E28993983EFA4AE6730BF8F9DE2A9BCDDB2469D5FA0AFB48FE4219C0DDBE355C30427D4DCE611A88913E43EEA0A02146468A87B0A5818CEC6DD4488397895B875F3354F3502A5E160E16CBADFC2A12E024439A89552E8B06629E6DDE852081BF3A248F363FF5F498BD00887EE4B1354AD3CD71CCB13DC4B7C583E9994183DEB56C5AA2E2EA76B6D9A1F3F189746961B3474B844E5BD862F6CD693C9FD0B683155E3FAC38998592BDAD2A1B1EA384443197C01757D65F4DEB5ED3A8F7294370AE0615D750FAC5A3AD7D4D7372059B6B52C111207C066BF70F9E86A9CF4A5952789422C14B296973E76986DA3BBD6EA93D7AF24AB132C7414AE2A6F4110307461F27E0BEBCBA05E72A6DF3D7511D7CE9100FB178BD3B19D34F1451EBA03FFC03B2AFBCF560BB0A5BF1D62CDB6704A0AF6CB4C1233B0441688F002F4C453B4054EA1881BC2DB1D9D91AC4957ABB721166A2DFB27DB34B08CA466473825E42D0CC1D354F0466FA1BF09A4A016EB90C76C4E31646439DD343F609825E11B9089BC7C375F70BB1168C063558648E3E25B3BCA9FB869234A83532C4F4F86A94063393AFC54138930B58C7D939E2538CB0D875D7896E4563E79319426E837 +sk = E3B5A2F2EE49231383C023707B5EA5CD6682CFE4B65C0A8452ED137C33CF2B522E62778812AD06B08EE0896E9FBCA0B1DEE5C2DF75FCF0B640C1922CD84EFE3151351B16416E480A9C99003236092CAE78FFCF85BC862470859CA0C1C4E89BC10B53DACB00D42E8B13C836C99D03C45A4E91BEFEEB1D1555103433D3C79DB03D740763064257350761262623105272611737854471235142220535400440281203315538521432346886024056814736088261181321607775174437470546774104605113472515313030511636557515181012155620548675153743012430603634263388741473715012183537554365301660345735274228101111715740055061675450841017662570824320748701655072231610408703511060887425146480014822231848268527288432883338113234428542562068768211501602363104051345544837348072003654131382451362436701180236725682014330585057772241620034000174684144156181685711633558877356546757400612343728640478241338333042362078157012037860884685415760321654166420750334500405360618145442148444875152172185615454444101654367146456655751222182615020674230133276771802030561851206821846431312122252140667664048443457548606327074801670672818680848707200665134748877557516660625362678245182560381620517888751861305727113078523374774213828654643076640715701201845433328606101151126364636767168315167540834682825201741152025450011771233438361617647334554531512220546773878041730665837451624288874571237126123065873460302860864778440415033200522133620018521752148166012873507547032414241844630366338162525123334128173872637505640084188001731501235076688876627563504335080312002245625337327485073818842150664186558625456630653253276874382126413526754704211086583274704580465756136320054821180583205132723688846033433820652566548057555534350330841132654207637868103822353247654736653202356813031442003112414275427365021603613606651308658840546054352204767387434137832475858826461505548073275702342172374222350145813520538856004538540762472483784714131182373110534726311135436018114413374472644800004682332243435780577067817071165046158811250302525553454148285630383808225684577562177746123117224863818834571614566845122812551743644663083667458021031507006887880066638178721886766146132503837438057282667286430701842573862288017885368472558442846356348101316003484502561743300165411617474362718353756183282135878736814877030386076872405414271078622033042313715472753352120768262530634523703446131463157150133776422600232202205631112007862133136285180328763514846854453161522821248617307312060411326303738065116202617568783001081738718280784477701250370563232553676248875222833016875156051325646700181117301867461360574560560333574671157467001525483316153201141248778036606562814867414784456211443158008670011653418434425053664646020486648216178632785263674267875347064658326416285188468876267233776511814351713255404432525508373824504348453271385350026047518372872005657102181778664845546151607478662344485320712735118670312070228823513355131317108214082347258587360524334414740067227214650655882357660437184317347637454406310620262277655834371558723853113330584623485455601500115650658041065635233141144106631510216126353518012341020803608882830221273426660472455868513885016282808253672277327047643750298EFEFB71639E6A73A33824D43B830D36B742801A9CBA2E6AAA4070CA68693D3FEC7DFCBD310F6F5F18D257F1EF3DB24DFD97B959F87F2DD979E780327733E26DF1683C37ACED3715EF7A7F9426F72CF22015E21EF0E4B718EAD02DBD678B70D66706CE9B4B8915EF8CD893C411C20595303A3B4FF39412C9DF99BAAC394290B9E2BB43173F9368135A3748DB49593C820D0403FB15BE283B86D6064F2ACE1A278D511A074A537327393B0FC5628C27BDF05D0745941ABD0A6B10A3D2FD1BDE804AF5F51EA797D188DFEB7A77015FE8E2F2EFD07A39BC9AB52968BD54CB5070DFAD035EA405E92A56655B8C997F4DFE2DE48AF22CBADCACE0A8F2CC7B8A6EAA133B6720A1F4A158C9FCBC5E096DCCD319D803927CC24435FF793A1B589A14373F6DC5ACAE672087732194E33ED82070424DC7C50D1B69F0EC02E1414B169ACC932F9B7E737E090F85578DF2E17D62C526121546E24BB67A4384609441E2EA08AD96C87962F35B5D73DB0DB6BE67D48E8810D359B0269CE7F7597FE7E1371BD2D44C6741836B2E7E430F31E1204233C95492234E23D1780DF2AE71C239758348F47ECD0A71F1206CCB51D57AA242EC2D2E8087A2718E2D106B5A6FDDFD2D3320C1AEF7E331B28ED03CC260D4C177050A02C31B6D5BE8413127A94FD9A864A5F7C1760AD5FD01E7FCBD369B5B70DFBC70D0C3240CBDBA9D94CF4FE32D6204A38FD7E807F5AEE806578ABE373FD2443E86C012F00FE5DEBB5DB914E7FE91D16814F68F8316016A17DE61F627BDCFB039F43D7CB79D57701476BD6823D66076047888C2DAE458D92E9053A3581A759FC2039CDD400A0A329C1500DFBBA2D9E60711B1C76D909A5FA66535658F57EF8F6CA9E9972B529CABA80EB9AE2A4F1B8E26316141C73DE4BD677AEA3824606218395FCD321D9486EFEAFFD35752C4CFC3DF82EB78984F54163528231A5A49CA6D8EA6CBA13E1B885B79739CD7802E5EDC0D8350B3114EB5C55683F733B771861EDB26FE2BF1426E2B315310C4FD858AAFBC1D6327EF7D8BB7D09D7EECDD903435562D61429DE96722782F1D10C425ECC322F0A63CBB0E1BE3D82FB69E10242B41293C2170A57C26FD6B9B9AB60AF2BD5678ED9E9F9B25B97426BED3EC08C92065669DB8E1D33A7075C51FA779BC72315D96E36087746B486ACF27CF34DF5A6391ED97B8C6C6B709D3E033BACD977CDCE1AD841110A6A1C0641EB45E62432478A8F454C01175851DF2D6F79B462B0984157CE0886650A74FBB361E9DD67D3D6EE835DEECE5077082A39E14CECB5364EFDB1541F2F6B8DC35FB2542847E77F0A0DBE6934E8C7044FFC6D0DD32086D458D5953441C91C9E20BD496AD313079F9E780C4E85FCCD06CE0B9A57A0A39987779174D36275D806ED76BFFB7931576823B091AA29426CDC561CB274C7E5A4DEE391E194A685ADD0C9B478B67133C99C085DE7F344F5E448E956CDD8D23D888C50C04C0D803FC73E71C13BB6397799BF016D06B74C671F081A9EA8944CD38658BF19436525E5630243E3883D0250D34D833A6DD1388EF2B0951302C2D7EDBF362A19130FA5EEF70F701BD466FFA36A86BD59AEB3F0980BD0527337C32001B5D0BC6C881C7FD6E17EFE091614FED74A36748C2DBEB84BEF33DB269E54EFF1C9FCD03919E77F2387DB627914601321187E0E2714AC1FCFAEFE0BF4AD49099E466E41425A6DE4A4FF9B25F1DF4AFE393FDCF27F6623E0A5F565288D053F34A7D2A919EBA4B2DC079ED3F1FC430B92AAE57E6634B046849293F393AD18A122F3ED023737AE5A37A41184A96F2A365AEE638B4FE947ECDBEA2CD2EA1AD599DFAD053A4F7CE1902CD1E046C8D928D3BB63C227C9037784A20C171CAEF5C9C94EF4829E798845D2CA2DEAC9735183B227E5A5B08B992C7BEA0C7CC94C62A7296F45F9BA753252D4397D2516FD0270B89088E2D447A6646F6FD25B3497792F7AA6084F0746F7569A156B38556F5AC0D6B3476A30FBAD7B1A93FC4E3439EE02DCE9455CE42C7BE4372F6C974D55769F53B4DD93EAEA880D919C4158A85B1F434986A95435A0C1AB5048A38C51951D9B07D0538F1280353DD85B8774FD27FE6E9ED1F0465691C03047D4D98ACE1583DC166D1BDC282E9004908FF233A22C2CF08A9148343FBFF006AE20DE2F5B507B1029F18020687F4FDEC7A360AE2DB603007BFB863398CF5CD41DED34057D52732782B9079F6506B902976C79846167042B56B3973A28062590E8330FF5D02D18FA5C9B116869433F26C8183A4B9E5EC35BB829DF7DD0C103B575292176784FFE1DD4C317CA2FBFDEE6BBA9F6B6B664F06FC2D5FBEDFCA497101C6AC78F7A05DA68138182720050CE2CDE36967C7BDBD4EAFE5FA693E4FEEF441C069A8A80283E19E05449B4205C43C066688B647A099FA06E01B16D34597A4915B1D017CFF34672F4ED0DAF9C85930405DE68A446F91E81D22B42354A2EB1611B4CE6FDA212F52FB926494C5D42C60D5CDAFBD9D558CA4039E5BD4B1B1D02C1782C55E94DB0AE0AD4CC75750E14AD237FF80DBC40FD2A35FC68E3D367AC7B358FCAA9B311CCE9708E98E571AD086800AAD2431105AEC0DDD5DA723C65BD21169D3AF837512F9461D52524BD0E86D394760E94FA26F1E902C1C85700BA7FEC6D3F7D838B8626C3EDAF551E64A1AA8F6EDF545C0B6AE2AECC3690E72C7B5380CAAC63AB2E16652B7DC7F8C367E43E95AE3653E18486DB72E629C4D0AAD91A1B441F21A69FC21E34D6AF5A1EC7F4B836F7ADC03F26F40156B1961B8D0D7FC876E234256C5BD3CF768647E84679A282E6C37C3F90432DD7E8D758B3CCC11DE974EB4328349DEB33C9636152CD5A02D1EECE3ED8482C5F0BFEC12FE44EA17A7E05CFA8AEDD1FC42882B841E551A7F037EC0AD014FCBFBBF47375E6B3E9AE41DACBB9AB8A767269B4BADE752929389D040F66DAF58676D983EB6F8D031D8F96F493531B2E5D125818C452D1AFE6EC193AEE251318B4512FBC16AB40E602B03D48708BBA17EE314A9F8D87FE94A707473963F7E489E2D32FF87EB2EE80A923CA4C69CF55018929EE1E6CF0415E286BCA2ECABCE5756AE52FE9A374F95BD2DBB24D75302959C0A71DEA4E14A74A0971A4402D0677036B31DF7E19EECEA974AB1B3A84DBB45069BFD7C4AD8916E7AC995BBE73783FD89552387D32900AC720120C425FF0543E3503A549DC45020210B1DA83B19B5F0A07D3999F322AEC5C498382DD09DFB8A8A983CB2372C1AD0DA9F06BFC47D65E51D7753D388E02BE67C641910DD99234E7676D5DD603ACAB44D01120F2013B90EC0226D6AB93C9E5164C7BB94D29BD3062B1497B2086D0B946A28E54E34248A23E0D9077EACE72687891854217228EE7F629D996A8B360D0441509F939A67563BB566929C66AC22F35495495981BA2598FAD9955A397D8E2283E62DD71B48EAD9B110BC45DC7598998A0B5B45FA21586FCCA42A37D0480E80F74FB3999D059775BFB2B7E7BE039D331A7D1F5B97B3A1A +smlen = 6378 +sm = 36291C1D9B388B74431EF94B42090A6251FBAED51AA5B7050CDFB4DABC9188183A6BAD8991BBF4D3A2A6E6928BABC10A9E8DD8CC1967A17C5A3270C4FCE0C299A78A05F9D3F66952F2DC17E2D63338F9F3F7E6E10B8C3772A970D1EF257EE801DB4BAFD476E495287C998237CBE136A58834ABC6D74560E1733C4C4BABE80CF4D853DA282D861F1688316DD55FFCDBB11880F83DAC981D3A6CF55DD4600A6FE94C3F208E3AD9C5CA033E7E72A67B086EAF959F2029E45A9C97B61CEB3FBBBCC7F8A8EE9BB9C57BB6A909E5BBF5E4A9449A46B6D43D4AB016AB4A92C04CC9A10747574EB3E53DF7D66D48ACFAA0F588910B0933F3AE55B5C48870870BF090BF5150B136FB5E86A79B221AB8F11B28615D84621F2BE50EE0A1BBA71EB900693D64D7C71A82988706453AC1A67A3468F280ACCEC8031B59A795A8C67888E70072ED58F769434B85726B51919F1BDF6F55DFDA4FAA1EAFE2338BD17595E02D3303936C11F06AF30B2382B0C02973032D1933302985792FAFA962AE1C0A17A755E5F29DE6F944F294CC4E152AD3F874385E26C6D14EF5B9C363325BA07B96C75F6EE387104A331FFD35EDA65BA6F6CCA4A1397017FC7E4F09D09C4155D46A9AF073FF0449572EE013EB3F8C99720714B4466B50C862BCDBCCDE15BE7CE432B07F2E4F0D73768C0439FBAA6067D468F243D6B8078D307D9405116E627B939C5E7CC92440FF479AC336D0E606C96DE29D53054F3B29E14939AD452C28C74975791D3495E9CCFDA53290655DF67BC093DC4F79C2E1CA929BB6739BDEC00F1A58F63C2F34B909A9FE066E24583EA813F40A306F1F9B2904EDFD68C2A52923C04EC2267347079A6E1D039E692221A349185DA6F845ED6869F0832A1BE0AC91503F05C8D02348F4579A81C0EBB8BF849B2573CAA9229B5A726EA65E39A32F4F2A413361E5C9C4D9FB0F668AB08703EEF4934ABCE2BBDFEC2E319FF5A10FD62CF5645E104A269AF48B7AA701885418E17443812A2C3BAF78FFD7391A3526E6858AC3444899F607748702AAA9F18F3FD8D2EEF0510944EBD6EB471B752D123D1ADD5720E236C4FFA37266B04CEC484D2F7FA72CBB557336B57A39EF69F678701A9412CD63356A26B742DA96C097AB1E7F1A825A39C70D65FF2EFE8F2AD8AB2B6542849AC9405D1A20975D20F854F5770C1BFEC5021B5D9E9C20020A4AD9730A2C86F1F8AA269239917BA9E4480D4913608D09D1AAC6B5F6F22521A460C9BF9D67595CF7506707E1EC7E0975616BBC5CE0098CED9E407EB8F59148D3266B493FA9D9537859B217FA16B2C84DEB22CE735C3F51C14201D902933A3A9B1EE14258DAC84809798614C494EE677325C173CF1B01F76DE22826ADA4CFEEABE27D47B33889C4D47A7C5E666839EE0D34B1708CB66CC89137F1A548CA8A304A3811DE609F591653EBDDA4D28B5A709241BA6353127E22414C428B1B06E1F3F52F7056E18731FA404F9910FED0DEA9B0C93392DDCE761D887E0723F6D0158078762FDE698800B7DBAD24E522966D296290AA29AEB8E67CD18F88C3569B94AFA986775CF122C72CC98FD8CDD12BBDF0F9C9D0FAB5309FAB37AF1CA49A84276E050AA3C4647B88B2DF0DC45B3CDE040C10AF2B73D8C2341BB2695E168BBA895BAE35D20E8AE4DF0EC9E9CC20CA7C00A32B4F12FA8A38B0B231B6EC85F1308161578137CDFB44C23F2D98685D4589B38CAD2D1DCE59CD4E1844B12BC7C3E3B696CAF502799C797BD91EC68F7F28A74D85FA82ABCD32A79832C4944A23AE7DE2B2E68398A9CAB0505C3E9BE4E4306F56C9637F568CAF58598A1EB156ABCEB2DCD5BC128789C063137C36472B6438509A4AC29CAAF96FB13E8AB038B10E31649BB12FF5BE512E77C9F0D837ABD499C6FE2CE80E94823040F8E40239655A5D3F4B00A552590FA28DB2B41E2DFED1CAD0BF3BA9C544A93F234DC7C35D9638A3C7761E26B40837BF5FA362BFCD7F429A3EDEE5CA4DECCBE08021286FFA2D9F0AB326335E3D7F419E29F4C08C86932A5C0DFE7442D5B8B3C4830FEDBD9669B9678E688547FE18D0301169BFFC437570A27FA053B16286C0272D97D2A283244FBE5D945A0317535C37C77DD18DCACE7713DB96988BD85A3BAD520C37323E4781C23128F117715A6C0C23CEE8C41F056E08BF6C07025C84B0404471B9455FC59E58B98665645EEEA215EBAEC397BB53BBE2B3149DDC85D3C206FF487B4F0816B8609D3EA92423C99A2C9BC4301CA35F7E53079F20D418C28E82C8D5416F0F1FDDD723B58DDD5ED50BBF7D73265FE1893AFC895C26040CB1E3BC12871A2E15B684F914E5809ECE6D6C9B8137154C7ED6178D44C52A467E70D6D3A3760D95676EB0C812EB1D810B526F45DB13CA782234947C00A441A8E2704C2FCFF35FC0F8155C23D1CAD3A6ED315B29994EBEAE458C42027B0BEBB3EDB503E7622B370911DF64EB393A8266481872A644AB8EAB2757CF35FDFD35E476DF8FAFB1D3D645C0C003EAF009AE2C38A3C0CA98EC083FA8689A941864314454EE8C452B88F8F6FEF0964656B06063F7D31215277AF69AF1CD8A5B92041C89A17A484C5D778015D4459D0E734BB0B70514EF0E9637A5D11087E7AA2DC087896432ED57D3975D04BE736BD3D6A8E43DE56414DEF5E4A9B64B9870C32E73DE0E1E76B24483BEE8161177B49A811E57CA836FCBC1B25C980C5C9D975539B70133EA77848AFDF3C82B6CA6CE9473E1A9EAAE80088E1AEF211ECDB5724D99D181B385E44B87F2F4D08331883065B700BD362EFDFBADD0175F9D93B96EDFFC50EAEFFFFC9E79D83BA42679F4D63ED6E5F8BA9C633E6F0E911575310EF6EED39B61C94527915485D93C9AB28EE76DCC351D2AE50A477F6FF042B40656F90611DB66A64925A54DA31EC51D039E4C6DEA97E9E08AEA43C955C8BF1B7CC1C1158036F7D973DD59C353757F5A8395774A4FB15D91B0DA6093B2C913251B23C051929605D7C8F64C2B98036DED1B32E3854A01929F684C696821B9FBA21BFE98C96EF09C484AF5DE8A897E9779FF87421764F3C8BFE53E1D5334D8B26299DE8951B0C54AEAE71141851DD3E3D327E2C5A655F449B9BC01587EB4AF3E7C101E316D210E139FFD36DF62AEF47D3800A18A0F39D13EFEEDE45287B414AF0221E017F0F0E4F18D121835A93A477BA8C11C1CA7D4450BD4579845E10029161A460FC12BE86290196B108D0C9C0EE2EC75D0099931A5BB339E75CF937D1B02C20676BEEA57095250508D36AFFC875B4AF735FF2084ABCB3B20A541FD2DBB56C5AC60497643476B44ADC4E6CD3CEE0C159CACA6A11A1400F27E3843C119DEA78470FC4452783A4B384F5DE972B2F5DDCF138B6C5464522051BFBE75BB11C5FC91B66CC45B3D416C4235C2E196953D4077A7F7362F98D6BE61E82222BB901C1529476290AEC4698F3C8753687F3AD8BC29A46F4F06C866B170DAE92657ECBE278CC333E30E0D611BA48F810843907066C135B685961934B6EEEE110DEE3E6B64EAF58918259D2787612C772F3D52C520011D6BB7B82B0D2447F66FBB6A2A8DE50C45E8DCD2B00824013F19787173D4A55A4BB2444A8937E1709E8D048446779AEC4C1321E387EACBBB9A2F5725B40443B1C94E64DDD938261F762ED84D0C73AF518409EA0DEA4F9FE5632693CB15CAD92AFCD5922CAB4757624503C9A5FC77A3A85D8A35BDA43E79F308C6EC85DF24165521FE2B17F2D28695F00717732CAF01C71E9F5C54DEF429CF048C242786B8E1BD09094C41A7C3B6C1E6F22A9EF20F57F2E28D05F157EA743D580C2D7D2BF18A2593575163B9966585800819DB3553ADDA7D628D30C290D5F0B97810F2CCF95431EF35BCF504AFE89C364CCDBDFB19A24BF5F802ABD86D38ECD873DC1694E0685D8452C55317E2AF8A4EED44C521973458E7FCF94F21CB5C6F81481107D099D16CC47AE2FE46C4A88A47D574CEB0F82AB1CEAF4EC4B4B53CC6FB812B54F6390946EFD35850EED897CA44368D6BDC2584F22DFABDF288847D50419ECB49D07F384089E8FDCC85D282C34EB2BD5BF9FCEC18D53B30FD28E81D05E3E09F4E41532E58CAFBB87697FC8B7FCF1764A10D85BC7121F3D37744F1B66F515FD16FFA73F8400F8FB5A49416D21149E9588AFF277BE596D1034AC77F5FD0BA873E9BBAE09A00796637684FF854DAC39B129F85B38B189CA836E412E49FF8D2067E944FE15986032926FF1A7757A023DA499B2C083DB4C5E8793660D1EEBDC24513C6B887FEA531DCF43421729FCB4DD181B97A2C0DAEE7432BE8732640C2C17F03280C3B7BE6AFAE1713ADC7A34780788E0B57CC56FFE6DCE7467061D2438C11B7E0240D3FC20CEAD022DF2F4120E3C639C89CDC93D4B10DD33D9C568AE01FB3A1132C76E941326EBEF3A2FA259DDF0C3DA1813FA3C4CF97A44BA1559DD803BA1C350766B30A939701936C12F8A3493B4F9770DBE54205272A5C4700C085C63CE4D4722CD1C3B2442BDBEF81D8B2804C0B7ABD40195B646F52F6FF60DD3FC44776B50E9BA312286B07AD51DD40C17A865173E3E9F947A4FCC835D79AABB825C7AAF7ED68E1B7D2CFBA4C60626FA4A50E2438586B777BD1DAF0555E8186686B82AEE1FE253E545785C4F3053D477EC3F0000000000000000000000000000000000610141A21279163116C86E64D90D35CB216FED71BDBE6A0797A48CB915F5A40FC8D31AD340767058B28CFF0C240720327E12E653C1F98B5755D8000BC01324DB2820781B94C4434FDA76223845E0613E2526A95F28FB4A768B1487AA34DADB28CBE8DF4FDB510DFFE672FF004F37C7AC32072A24C0F12A050BB396AD56346F4E0BA75C0EFAC162288A7EE8A63255DBA5CF451A0932FD56B05E40EDD491293E045A6081F6586BDCA10B41A6970D8F9A7B3B6B58AA772EEFA9ED22C9A24A384D6947770862BE4FE45C5E0E56FA4D116B79699ACE41E5D9F2E4C245059CD798DD986A3763F527E0C9D5A88A09C4D76D447348509FA7D9BFBF3DEA59EA57711A3B1A9352123D4A74DF273FA24A89BCAB42A6D455B5FE3C503F1FF638280F87C740B9E4C5FF20133CBDFB8D08CAEB7DE9F26811D437E6EC8C3143C0419C2F5135D25C7F40C7908C03F295FD26F1A03FBC7285196BE40ADC6FBDDDC912B3BC94B0BCE08DBC2185EE3CB766325068DB55C31FFEBE4B1F6848AD4FC201A5FD056916A397ABE6A66FF9BB03B037B50AC509E46CA441ED45812E3334FD7036D190A7991E55CB817EC2A63CD800F293277E7D15F086618B55AD395C614D168FCEDFB274FDF4FCD50CB976F68A266C5365E02A1ED0221BA4E13E70304824F94251249CA23C089B4D54E02EA03FB7C9841DD30404428AAB2519D68CF564D75D18530C7D062496C120A8F5305AAB23AE52255EC919EB0CD875422B144BF47F7472349558E746B0EB5493F1FC40ABDADD2ED84A8B31221A485052369FD0B552972C9FAEB1A78E826BA4DFB9E91E301DB589E9D7C256E7051692C48534C6A5E2BF0F45B78ACA66D5F53E549827E15D64E2F294F93D43B9F36BEDCE6CEBC05E56CED3F846635AE3C384C3FD55B969CA31E8C625103C2B24E7EE45E92984CA23A331C5B14281B20116069C619D82D6080C6FE35C3A3FB2E73B695CAD9C5D3300814FD65738DCC3EAFCEFCD24361AAD13A25B3570D2D509FA449612BDB5B49E0605D7EB78449D1DB40660AF0F3D8BCD4869B6F175CD28AD72FE2668C3DFC1D4963D0EAB309DD50B74B9D2947F86FBE9864AE5D0DC69B55B182AC1D914B11F631193F5F1F897CE52CEE97D7AE95631FC2F2A1AE9B672165432EB2E5633B55185AFA5E883268D8503AEC10774D25D39C800B74405414FB06C55B8C48835577884D6B4F2F128246563066F8F34D76213E0720E899FC1F11A3B0A591885D82C688E40D6B44B54D6C7C6973156E2DD50C40A28D2EBBA60F5117D64646CAEF72974F4B8362E4820EC04F2F373DA8D883AF27518567688146F16BF4E10969E70BE8ACE5D2FF6A135DB1DD738907EA355FB6D243904F6427D11592672060DA14443B55A9089167FC9D5EFB2C64B0069795C341F90DAFF684E566611EA87BC40A4C45F22C23AB6888A754B89E4C95BB54629CE74EC999889C82714B5AEC703DE7BC080B0D2E622ED53B645688CE164ECDFF4ED66C86049B2F9077F2A94CD685294F8EA9CBC1DE29A48D39F6B308288DFDB47731E39644B576A298646752F5C53D7943A5D0F7DBBC9604902B61B8EDEFEB5AB7E5BFDBC1E6723E6047894547E440E918038CC13B47424CCFE1A207E08A40524B553C750683F5F6C960F05836FB9B28C59E1B471FD5331F1811DDF3EAFF73798B7FFD6C9714978988C440CA906B4782A410372D70EE65A0A803061708003688F576E2D3A22580B706149A24B93A162BE9F1B546680A1DB2A8E54A576C28B4772C50A55161B2994514369C2192B2C90017CC8282F41D28099F38B2F1F0D2C0E46B444417A2078755591F00F01DF0CE72B1D1BD255A14D2BF67AB3E630F95A5DA9BD9E10F08EFBF6FE722CF000C32460FA3271F18B39EAA4487C1DDF828B6BEDF4523837BB3425BA1C1606E8D5D1E6182AA6A74F068F3E90B42641347CA755779216AFBC99603391FCEF4E8E5AA202BDCA24B83FF42F4F01232D3F2831CDA2DB76FB93A4CF6E9EFB71B5438A4B74C3190A8901D73566C50727559BA9BF6317D116E8F5536BACF064D3F86282E0F88DD40B63E75519C6A8E5664AF8E1029FAE87930F523E4DC7C2DD6DC3296A42A59F178D438866D929A70951BED05533EB1D818B7C7C595971C26B1D436D26897D6A6EB036A13511AC4A3BD724F2CA57FEF07D2C0730800D35683D745125F4237ADD64B538B7DAB0D0F258DAF7DE1A74F74A2FD010CDEE810F514FCF6045F0CC84E2054B5F4EC2772718FFB4CCA9C9BE77F8F007333860180D60EE4DD8CE976E63FF49AA11DD42FE6946515E59DA3E602B1861BD3F63C89362BCFE8438BC71959A617D8D63331A3D903BC5734B777FB14F7A2B063D79EA8637AC52C758EF88DF217B95FA8FDF1009AB28D8A4F318F78772568CC7AA9E3B3E001C0111B1751B698EF1B66383D6B3CA942FE4F66FC97613CFBBC03EEC9D0B7E08F80939D9A2EA1F72BDA7B0D655AC3A94B4C699D3EB1BBD6076E63EF5C1FE9CE258B55D21164CA7EE03BB53D8BA4306F695E648093542D769DA95A35FF3A2C071DD8ABD5A82E217D82317065D50A87B689AE3A2EC7887957BB243373CF986490961220EA61EBE12AC0287B185070E124FC518C300620B4B6D4F29402B18C2462A7985C00E2A87691053B1FDECB7AA264F33E27C6B201CA6065EF79E5266513AEA92E8D3E646453C089B5EBA66D14BC45844D0240D2E7737C16668FD53E38A93D6003146019777C03644C300D06927EF6994AC794914EFC5BE0CA81680CA8C9752908FBD2D56D7FD1FC1C76EED755408F1D7802F0D3D0F347D82B162EE6F0A2A890E083C20B822FA6C4AD627F4AB5D1526D83D897C244D6ED4A427B23B4A0C19F4E8889257C1373764AB7063B5DB8ED9C2443CB012381A2B3365EB568649D7CCD52271F25FD22FDC397E4C9C536EBB452CD2CD10DC5010BF433F88CB58D2B9EDF2BCBFA83B782FFD4388F1BCE3F8F9AF5AE6BE590BDCECB1BFEA846D2F0199ECCDB0C7E4D419F69B6A428EAEB462B67AA40340417BDFEBB6039AAB8242E39F6C11EC136D73FB315CF71414A2A1203AF08FDEE34ED0072C27462395815F7779012A41EC526BE53DA954E1F7A7EBBB68FEB15CBAEA8ADD6CD0F2FE3D3615991AB54F4C7884E8A80A9535F13BE2ED944B3BB315DE8AF2A70439294CD53F041F41D3562BE840C78EFCB08661B1731FEEC46A9091ECEDE3A9FBC2DAE42C72EBDD84308E95644373595DB62157DBA7DBF124BB45DE6C2837B0066673BFD215FF915A8D41637EEB029C345E444251ECBBCDF79E246A80AA4591976A00DA06C759C6160ED1986F8E15A562417DA55109174628E7B11D49586882851205755B4F99A875AB3599FDCC094E4A2164E1764D24DE805FD7B20EFEF2A8E23FEA4E206DFA1FD9C31D90C1FECF745D3EB886190827D952703AA6A99B5000D8EE9D51DE94A82DD053B6AA89CD7E94E92D4AA93A9224D3F688B5C834A53F2993638166A3DE78ABA7CB930CC5845F9915E6523683715A187E940FA2A978B5CA4C3B80DB62E96A600F1864BF0B1AAC23B1330B13EADD3A2F07CE7181D0A9497C455D228278E5CC3E4C00A2EA3EB8E5B9CE2799256302B0F8F1F829D3A3AE8AA7CC4EA229C5AF476C01B8D48A9F6987DF57C3469B6EF6DFCB488A3D5B91FE17B5798FE154AB8399A2E75F0D15B2A6AA91302056266B22A38A604EDC374E2D2155ABCA119C11DC6827A47E3CEE7032F6E0F59708DFACE221E47041CFFC59CE0334D9B7C5E91C2C320A70EC2F32906624128363C893909F47BD970DF652D5E6C2324033F32B1653A039F8C051D9DC8F839C50F5696E9E08F7F1CDAC4750B429AF03176FF6E643ECA1D8FC710C6CDB0D26074D85316F4C9084D5F453F6D36C1CEA0E389F3462E1478E2503C1DB99FC46F3F0627F173672C21F3CC3B483998192E81EFA689819D0007762ADBD141A058587E030A3568E412D25662C40ACDAFC3C6EE30C10CC23E3DDEDB6C73085C90C89B1218D67A328F06C3637A786D4715CB9F9D8B0B22D920B68B0557CC80A56FCE0B6E2D6627DE576E308757A8F37821898E96785AE323E413D3572205B0A5710143A2621C258C76C7C3FF7100A2FCAE99C84D1AB1CECF7FC5B1E4698BFA3BA2A0856A65F2D4F291A4A164C0381D70D1213F7E40FC4BA42C43EA8E70043E27C5AB0827559B7CF7F2587D0D2F93C6382CF54E92764D815280D68C554E5B6FBB351BD18635786299DDE39FCAF3EFA708A3F18701EDA1579BFB0BEE4FA1F1ED6E09D450D427E4B91F4552F87F31F06F109E74AF4BF301481452AAFA2146F6375DA467EA008BAFC3C8408AADD61B07C28C55249EC0C8BFDB00EA + +count = 93 +seed = 55A9C7A0B49706090BC0702ECFC070AB060427FFC820C3FE05B499B59AEB125F2DB4787A5910B88C6F8FAF0A69BE0AE5 +mlen = 3102 +msg = 02C7C4451DA90503C43FDED1CCB3DEE468A6A8D9E56670CD8F6A58E7941F1BC5EFA6E2AFDC0141A2F7E8F781D79E70B4813263A9DBC8D8A67F89371CFBD90977EC96461B28BEE4C644F2C91E96257B1909B84ECB25CF438A3FD6B835E20D5CDA56A1FB7995FCAA0EE1B5327FB1288E3C57CBEF0554CA5AD6FCD1F1865C6AEC6CBDB24495700AB5AAF078D8516CA4FA3A231A97C77BD150B127CDBFB42C03702C9027B2A5F6594B022EF55B63BF3EEC27EB0E9529ECCDC82BC6AD1F011F167D602EF1F175DA5DB4028BF08A053AF2C728ADE93B37EDC2A75B7B6C6CF38CD1C07F359C73B131B13DF76139DEE6795F1D85B47F29AE97D0E40CF5DBB67360044F78940A1E80D9D99FD5AB0185210D8769911BC471650DF0FCB9C3AF038F7882F677790E146E612FCDD6FB89F90B7E5E46CD648F4BF8F736D69F8A91E4806346B4366FD48D1481C0B47ADD82003310B0A99B779D63EDE1771F50221651B2D8AF40F48B92EE1327C85A1D2EF2D86378076BEB58556FCAEC6029649A0EA5FDE517A85D87704210E071FCB6F63317AEAC3EB3E9746018E1028C50C790A45B1BEDA6EEA2D646DCE401AD5D7850A5F69CD85301920DE77AB0D01B1361EFA3E70AC05881BC02190720ACC75A691D6064F9D24C79DC72476309E58CDDF5FB2A253D857A79C8E898AB6ADC300EAAF208820CB02F5F2CD317F4052D40DE28E52C55A0349DD855D64E8DA8296D4F572281E221A3D27EF76FEE67FBE5484E6460C99950763B801FCE828E93D2A633A1CA5D7EC582D7C463DA5A9AA8056BB2173306F3820BD0A3273742789B61AF89CCC42B81CC68745800D2A59231D5D28E832F443A871DE5B6B10B58A8AA7CC9816014D7F3545DDF1F481B7F0C9DD41B4D96E5DB767B74776C2253FA230DF65F3E0B944B95ECD4138E2847418B084D9F9E0798CB5247238EC12B88C10A5C0C645E1D09D09059C72E33C28A472FDD8B88EAA93C63BE7D980A12195C2EC3105DF2BB81CC9C3009F7771B6B813CD12303E3A9961D6731AF55ECFE5127BAC68D06F835DD5F2D584FC0E648C3A4256E2A3D4B81966010964657F33D1FE0400724C488D5AACF9F2C0B802CD812C8452E5B8E2B17FF4A1289D33FC405F5DB4ECAB4A73FCA3634756DFBF9012C413B6F64788FD0F68F8AB7620477ACD3C14009377F3DD54B9EAF2784433D63341323F54D113FD63D7456AFEF885F13C13172A37A5DC82336B9515F8F7F4903EF6DBE9CB34930743B6ED11265CF94AAF406DEA9802D17BCB369AD0D9964792F74D338DAFE47EE88B3B74EBA8E70774EDC1F16FA876FD62B0BFF880CE252EE4435B1DEBF36F0A06A4FB406F01D618C135E6103E2A39F4C9CF41EC93702BA76BA753AB49B5836C20F67D05943EDDDF47AB8C5B81F4BC22D773305076F7E5B697A7B25B016190072F756F19F397884E0521595326CA591672684A3BE17C9F5CC8E8F4848F7136762178FBDCC7BC6A6C6A31345FEE687B0505F72BF1AB7EB87BFE5F896CFD42DD67A239C70648B39BC0C84DA33CA17838FB4213C38B68F22914FEC3DC50194E883720719E9B5F8D037DEBB726DBD899ABD97853C54B0BC347A322BFAF961C6CD6209C98AA81B8E2595FC151B1375BF4FCA2DFF49DF40A3D1C694EDFF6E9687E73EF62DD42AD7A05195A7F206F097196AA0E4D68F8132D4A00CEDED940C4F6AE02E6D3763073462C7A4BB11778290E744471EC554A05917E52C5263FF02C07BEE055234EEE10B79175DC164AB2051B03598DF1D4311E87ACF4AEC45C55B1A58B0F05EBDABE248A27C0187643CB8F9529D31FE0AC4A28D780196DA00DACFF5F2DD64FB04E7C159DBBCDD3343BCB7AE188DE15D923D2AC0AF232C5389DC9C949FCE554F7A0425D4F9B28DF2EE4B81740C2B5A5B93F0F7AB75EBD360CBC78B11C28608B5BAFC970CF3D4455A20A198392D876EDCF89E2639B50CD84AE21BD50FB077050EBFFB210BE711D8EA807CA66493650E909911FD3CAD99AB94B2AB2EDFF192D9D75257818272E147A9C54E06C53210FC091BF4175F2F44423669716FD9A6C4F96A0C4BE17839769A806453E55D7357FBFB3D7A458E70957D524C0E896398E135BFA68A0CC136FB93EE7D30AD463E32E152FC32CB8E7F0B05A30EB13C0DF98BC187EC0A54856D2EFCDA10A82B89DC8CD21C67D9B6DF3D7005EF3B2BC9DCD5D55B64DB40B74FD322CDF9D9911A00B5A02E1AD5CA9BF65D90DB709FC1E5FC84BE97574B09C83B49963A51228A667BBD84BFD8E0D90EC161FE5CA73BCB8D95FD7AFD982AB7EBAB51BD2B24CD6D356EB850D2C65593313D8EBB97E7DFA450AE982918582F86A356F538EB05AFD460566D79F040D36C93D3C645B636560007D51B121DE3FAFB3ED70B475AFF9617DA4B52937C628678B109C3B76BC15BD02B766A394893D8EC966DFD8033D12A8D98AC5BE201134325E32CB6786F4FAECD7DCD05AEF5F3739122B817824A672E71DEB312CB7DD6A77116B30715076384297B1962EFDFEE6D6D2B2ED2EA4DD802F4784872D825DB828557D4D927B7232682AD91CEC3E508854F529853A8797B7BF7BFF8E3C180980DDF4081E96A12A495ACDE0C73282AC78617C68A55A94573E5A37B859858D1E19ADC82821B316B9D346ECFC6DBFFB3779F692A62D20D1BC4E730FDE2AEE826E76638ADE3DFAA11057B0BC8A80E8905B15E41D9A4105109F18E7E1362149AE9C568D1D642D65B94253BE2B13E7230F8BCF34DC87241D1DE72A65BBA111C111CBF5BD618CD02E0A06E37F60B3736631073A6BE004C1AD5F0091A82C87B276F7C5AAF6938C886A6039DF23482E2064F6AF05636B4C6BA6B24A29AAF2174AF4BD959177203AE9B160F81CA6764948AFCDACF6BEC0B987C6DBE178DCF47C137C64809483019C5F2072D0301C19C500C60B5CA913C24A8F28F50E1578D806FF9F9B810CA14BF5F2268FA18DEC67D973EB1D975AAF871ABC980D06222493D900CEBD8811FA20D5DB8F8036430F8BD7F9554F7CB47F9EBF389F66C3CCF9F42DB57AFFEE074FFEE4EB3E11612FD8A8FE02CC4E9D2F8BB36C505CECE9DC87512AEB5D8EBE33328C5217CCAF2E1AF1E38BFA84C0035DECD8D8C250FB4D964E8F0AE448AAB740D9EE9D794390686FE9A95183F0D5166D479C51014F1F29D8FEC616E1A4E7A9C86E2AF790BC7BD7BB6F746A2266332E04AFFBE6B9512E6620681C3317DC846E4FD7974E8AE87E370ECF9DFED574E339CD7E8A663ECD1A7BF5842391913D98686F7F2145BBC420F2F58B89131D5F3BE41C85752E13504BCC549A8F690CD2B0E1E29E4DFA3CC76BD398BBF28F33A00C3915DD719F7CB985E9A0A7CC8190BFFC8BF47310C71418D7A6C629C491EB8E455148BD4438BA6B7014608B0CE6A1BC5B035BC174C9BFFD966D8305FE9E5619BCA3FE4B39E6732DC652531819AC828F86EA11360678E786EAA741382D713AE26A608D582A3E4583D45744ACEDD32670B5AD4A1310301B28A174DC9858A55F0C1B7486CD66CB0635083B0C63016E40DFC533AB80C9CFAF1378D00769DCBAD56B09DA3A4E6CDBFD8F3FCB951680020DCA58647665462E42F42DC14E7B20F262D3CEB0B1A2BA807B98D66232AD7D3839C298564BC36A134CC2447B1B9FE69271960459C0A6F897C1878140690DA7D41FD8AAA05A679FDC3037EB2885AD3C82374F4BB991745351292DFD8E54F565E0093776B7EA65DDCD500BEB4D15AF6029F2630A0062F2D4FB331B47B6A5E139D385016E1FA490EAA209636B1383B7D7DC1148F07ED2CC2C03FA7FEE09305F34C57B3CE899C18462B4F1EF88C1AC5259440AAB48C5849652AAD9D3CF3D31F36C7F64F918868182D36345BA5BB7A4EE088D8B081EB78FE977F5A5295177AA427215BB26D1DE33AD4B2D610A47F8C672EEDA703A04D0FAE4C5961F13AD6FCA81863D8A394135565D8B27904A511FD0621A532F84A47CCF4FCC2114D4C369B7A76822959F8CAA25A6495081CA9EC3AC3348A981618592C090B6439CDA2FBC932C8697B3709323E3388AF8EFA1B9CDBD65A65C8F0C302330DDBD10E0235F8030562452EDE447EE5A5A9A636AF6F615B1210AA7CBE69572B3467B643BC5F5EC3F9AD15B3AD918993355E209ACBD0F1393076DA3B0950803295B6571E476ACAA04D48A4627367CB7FAA83796C4178CA9071DCCB8D3EA70381B61F0C56D515E0A765E266DACB13056317AD8737A1AD541AACCEA1641946E331229F19BB54C20BD51E63D63BFFA13110A552FD0A95AB984EF53BD639EFA0568C6875B2798E3A0578C940C0C4197D3587BCB1CC45A99F5D37B1612DC1A4178A3E288FBD79DDACD049159D6A5416F9EF3F38C74449BFB2E6A894566C5C17B4555E154F29A93241463690 +pk = 0AEFCFB338D198C54B14E3BA71ACDC4F9ADE5C95E02862F68E724329EA220B21CDC9F29D5BE2C00D6E67D37171B18CB2B367A2643C2B45A7378620F1ECC855DD0BE6A123FBB2DAEC8980A748B4DB3EF289176D38A5BAF4C3B704DEB66A5E6993CA08C07B9FCACC65FFDD6C5FDE3541EFB8AD68E9AECE28F0B09D47D8DCA00C61E1BFD7939FC7605A3FF627E5079C45E96066CEF63B2482DBEF73FBD072BD3D7ECB8796B3067E887084A558BDC5ED067928D149DC8CB6E05FACA5191FFEFEC9A9DE63A2E6AA2C28D40CBE8BC77C6455AA3F7E941C9919F92A4581A063CA2F802AF6E8F248B5A832581F7FB9F51802BD16D6581E7F40A669BF7A5FC6F1DA502D8BCE84EEF7EE969FC7BD92F2436EA66CA4B63F60C98D6AC8386BC35D1AD35CEEFB694E0FEEC33207E72EA875BFE0D69091FBF99FF52E66BED1EC4002C66917AD19846B79ED0CC2CAF2B7A0FCB1BD805522876517F01D27F9AF0CD15FA803FDB2599914BD96ACDF055930ABE1ABDAD11990C4124E25F6A0BF680BC8EC168906516E9935FF76880751A4569D7B07B7B38EC4FD1D9A95378E8035F2544B0BC390522A4D4122FDC50A73B522034449B5F33FEDC214777DED26FFB324D58C5AA42FFB46AE560B6D08D8212CAFC6D672706E0A3D66807697CC4738A7A0E62872FBCC2F654C28E971B5EC8F0D3BFD392040357CD59497320B1A0E9364446A161FBC984840F97A8AA201994BD8B53BF633623E5DBD2AF093388D7AFC94636008C1E89369C4AC820A6BE12F018C16BF5B31296340A09158742B66DD60809B19E328D57F9DCEBE0BBD3E7D38B39D971E388B3405B4D0D943C12ACEE17CC4D56F1C2FA19D72C2BCDA60D74B6299B780975BBC36367517F86F4548DEC083E3EB6C33AEB4C7E031C5C466C06FEE00DE4895F75581576C839DB501867BD8B4BC000571DEB036E4DEDEE971C43318A68FB4772B2072CE322B6FF259035B73260A307761BB7B7AC7F361950C4DE0D46DA629E07B41BA84DD85493D526650F2164AA44B78794CFEE0BFD0719F62C7D2759EB9145685C2933857E4A5479F2DD4A6B4B120E8AECED42A623B96C2B4BFAFBC7C138D88116765272B9C71E1937C1054FDA4A1917545450233563B514EAF1F49F8278FEE37A350E1FC26DA57DADB7FCECE45182643351C1E82031807AFC1528FC23249D658C9CC2E29EA883A6FE57BD9ED8B17ADB90620AD74A53DA0330E838E92A4277AAE3CB6A27EB38BFBCC195C59755F6DE846E101D5BC2B36880BC63B12F5331A920258F924D947BBB5B83F88025A6548F0CB64889E7CDF2D4E6B7C2682CC84F12BBC7DAA2D39518614A020B19EC6037C176110A3BB5D8A6A16B1AA50708C6AC023427385184CEBB451262DA083064C8E7F7B7A2DE0C4C3E1A789EE0EAD68468E15AF156D38A9841B202B78DA1431416C326A813E807C00AC8D703E07062D1EC445AFB24C5DDF7F79DC8AB1CA02DF4B2915DB9B670A200C7A089E5EDC5A17C6F7E369D4C0F2B0E8ACA9885566A06F1E6AD02BF7AD94CA247F1339A45DCC2EE15C6EC9477979424699E6BF3AE5C938E62A3B991C901189C044FE2F8B27056DEE28747784FBF4C80406380ABA0EDA53EFB8D20A668267075EC852CFE67E2E098E8CA272F1E0C1DB9A619C6C281D282A37612B6D22ECE9BA7ABAEF001CB48F660F7EF6AF7048077697C319D3DF90D889CAD3086D36F46EAAB521A90A9811AE897B48814052467CBA881A54242D952DC06650E72ED2ABC47F03DC63BE01B041F3478BE9C64DC37CA7A005BDC7BD1B569C8B53012435946A7546BB4BFBD827655BA4D0A9CEA52DC7F030CF512083BD42AA6CAA8CE9D8B246BA3D7057ABCC1AD4E77D7439C5A69D6F74D45EBCD86F3E69B56E6EE6D76A84B25206652EB1509A56F8F8CCD981D465C565F5157448E6246ADA9591B05E8C250926D966A0507A1B6C92FF11AE1BB9A4476787B7C31E1C36A4206EC0C59C4093534CD4135931C9540150FB5A43CE6755C64369438010D9913C634AFE2F56E6CB4AAE3DAC03DE96D4D5395AE5ECB75DD157727C7EC4828B1421C18A30DA69445BFE3F4F8C2B4731F507A2D905ABE670E5E1B12001619E69708A1C8940B2B7E2C697316FC6DA506D52AFF6D2CD77E3BB4C39D67EB43B416EC5B5437D225739E051B18023388A5EFED4DBD62C3858DED7538F087AC27E48A6FE90C185CEA6B866506095BB826CF5F66B477218E8602E1E25EB22EC7D4B9ABFEFEC6AED2152AECC61C790D0E3EB1F61D270F1E0772747E3B66DB6B039AC05085CCE4201F7493BB7A0B1CD237616E1FDE511587718A09FD6EBF36B90850ACAA503BDB9EAEA90FEF36E50E921ED6C470098CD71C650DC902C8C004AD00C0DDD4FEED2FD5686DDEF19FB020E0D0E362FFAF5166FCA64DFE619DC094BF533D18CA42E7E0E14E49A2D151A15B9682824681FBDEF0BDB091C1B911013FAD7EE2CEB9FE3605AF91506B571FFA033DF12060616F33E1C8BD05087EAA48257904FEAA19A879D22CB1406573817DDAE4007D1AF1D4E6738689ACD31445FFB5718F8176B032FCC26ABFE2D0E95CB9A978C6516CEAE481A0C3128B4D3C868E8167A80609DAB3745FB4DC241E5D1C5B9B4A22BBCCB3A1047BEC9D25C3DD057680E866EFBCB64F317EC1DE480E69EA78DA07FB5E683170AFB7CBBC7223C9E147F2E3C037EE49B029FFAD064D1F3243A48FF46117A4571A905F7A41E8ED638C719C5E71F01FCEDC81B1B238574F2B072264C +sk = 0AEFCFB338D198C54B14E3BA71ACDC4F9ADE5C95E02862F68E724329EA220B21A8659D00CD2F9CC76CF11D1B2A22CE7A3AAAA73E529FA72717F3B7BCE0A7C222E209E8B17D38D472070D5504A0771EE7F68D95A141922D02D416E69FBDF07D9B065DEAE4F4D14D2063FFF5A988A5AE956CD2CC413CB41E9986AA5E1E64326CDA32606476543786111044681371343107852526155834142268361401485152150735441615312612105711344601872418840801403585254422848115883733847527063524077647307187524640724275573215404105454346874500648824785602442122268545254152386682370755720441887306882378821531667244113086257271416502601302471223342353062662832478106821325063465042214763748123633487815576755111067850582041686034814530767411783287507682666378104604478110420514656152633382537483552234005473018442346407260816612522344258822570710255651767233417706256708836444718185683402415574250611078271258644117553652122884123144208511616223082656613410864206783527362055146872256176441718302271347421426522247225207008661031656564173085001770523663076488052385027247280104024214404760080070573881762408283208824262750421628651145554888054524441521356731675663740808640034287022341042663803184373863282144835316756445583170330506053452364770063646168075300237708177373100784381630684201682581411813561852421666512010314728775773174866300568233760678565472305011714345487486373063515673765501527025083065135573136174146887566077741326163285871761564358408108354076830803813755006747358252735555338086078527077644881546548460104043544047320856823042252042542417466457754704503830021201062372362861317121503238111007122053178636866288675752520047804643862410523653556314128625125703230537687028548414267351820156737213417357012853784877342567444474542381377847138181720605275157131706644072836616688752156063050060707660410364011036701323546512442432555510818708246423125802501547321150014253631080037240803278108316562161864871328125282278014451065410571303284404274624474222013788070720457003355165754733865213560005636134586450281024050463664738838618022148758553638334814261178134783875602708715141832640648635248306185602413157461252066834444103411400647262035400066085425537478812588563248723483443016780586140533120665170725171067047328075150758137412061625607033587177665756815571344625261268104676022617624383310017882435771516353324008202758802358312282461842548244083031746372214757801314212371051123826802826372488588656155223174710434528025127777642788167821584465312337280868326486482787412034765011347281141020201176208253810544712362082122005074815513218175372601431326567372188675636464717042045488140131087208126012477162875485265831803105268261835154082610457722378204457780844587861268565465735777675478804314567044053520360427344604330684284173068041428460140887156436277315282782161267522188333128666325222224827152662828360862368558428763223807685566204266577806246725232386011575670537253383630132745150220071577011555100766804228408620714527432237272615476754165716680772175325486630513666102537821721027823700461482601503641771082207711808836506624710775015756406135471435158242600854065553542206014536833426358452847701622546086247327670453586EB832D745E68076B61C096DE646783994E21142B668D1233803B88856840B6BC362243ED22FA757BA871EBFBF499E86330D0EEE3CB4A303654DC8D9114B9E7EE70427269D02B9D54C1D1FD1152D36D130AF0571B3F6A3C4EDC0B8CB13564FD7D35C48355061CC78D5472DED055A90CF26522D6C38B3829DDE3FD7A06693089F054B86495442A0EB64EB869B7AE462E58ED7D64E04ABAFB9FB2CE4F9AE55DF80384286D95AD764D51339D7BB5CFE14274D7EE4657E690F0F225E71179139C3D7376B908F9B329E51C20DB69B2C53C0F756FEF8F8562CB9A24E2B414D6D7149E6524610D5E47D1AC9B973E09CF88D4B2C9E5D010B547656230DE6293266089080C4777BE3EC199D037B12ACF0A06A75B0E3C19053512F0C9E358F915171310DC09027AE46E99684F4F0C84104866B7AEA39FD4E9D439E19E33822FC3BC31286338C8C4A55A8D7A4913334C7ABDBAA0E42A325943003194A460107529543C7417DF25FD2F02FC2A3BC1BA575E46E7DC30E86550902DA799970EE2639B12CC95344DF3AE2F14455FF31005490AE0C9883D64C9F9890E448727E58A946126E698B223D8DEF69361CC2AB16C3FDD30C5582116AD1A20813BCD1894A23B416A917EF2D99E26D6C8F8B0966372EC49BDF62953E1D8CF5784DEDB7FE5E8E37FB84FFF74AF299BD4EDDF79D0BABD710D76841A08B1D2713B605A150EEF8DCEA6C67610273C097E639A825A6747A97AF48D7ABDD54F507FB6119A986033169E2DCE1FC37500C9B3EEE8FA0F086BBC62270AE8D924F12195A72713A592442B9C63BB3FF372B64C7681E9673F0EBB2A30F9F80E1DCC8E9BA5B0FCF5CB9E1DB1418F9BFCBFA4EA6C7385808489A098B90C18D92AD1B55EFD8E24FC113106415CE38F97267F6941F285BDA149DD821B0792AB82B35DADAF1F65DAD4045D7B98EF177D0E1D67EE954C82F6A51CF66AB9597E56C59A719F398A557FC5F96FBEC1DB03A4CB04AE4916093F349DD872591AA81AB3C508BDCA5CE7A1A39E22474382FDD12AE990E28B2C5B493A39F4D33E0F2741389F051ADCBA6DA34D5F079851760881326F2F3FACEC6D037C85F2EE313E78BE3707D5735E685F868DFE2F1EE5CA6E49E21205727F20A2F2DC91A4A9B97FBF03F943ED69675F42B86816E715C7B979D0C536BE7A5F7A93E814057024FD9B77BC682B3D923758E6C7D8BCBC0FF5D737840260F6B123CC090C270D6E562DF516926795952E2B52F28E7A8D67857FB2C3714F59E18E2F4C0D38385B32299FC103D8389CEB4152D9E42251FDEA97CB012AEE14DFF2EBA408DFCB6C5AC189269BBBD37F0BF0484B0462DC849EC360D5DF1136AE71B822BCB644B993FD557FBD093CFB2161414834B715E2370180EEBDFC744772CC96DB90DF1133BF034C4C9162BB4114D407EC780D4E8B5D69035E812D05BAE4BC7F2BF46C20B6CE36453DA76B4E5615020E8440F1F3BD1D995AF91AC95AC3E868C7A9655509AC0E8A6093155A21025DAC235C9923E4AAF70EFD53583E838C8D61AC4DDFA03B3AE20FCBB273E6C51B5F8B37EFAC35032CE1864651EB32812625738FFF6CAF01C6F8CAE49D32B962485A62540A22E2B74DF3112B2FABFF7A461D15D18B7450E51639EF66CD7AB59DEAFD0089B507A5E990F3BC92F3AA2A35D650A125DBBC4866951BB16D69E08D487D206663126CECE3995D364CABC00C679FC87F64092398CC36383CEC856421287CC5284B28E0250EC19B5D72F4C49B208DC9253BE9CF1E16126EE9102EE9A5E6FA8D25CC5717AD5A03DBF76FE37A72ADC18BDAF7A32BDC3B983E5B9889D47FEE3DAC984ACB595F51A3AA8471B032A20E13BCF8C268E4C7C621C665E6346E8894B7A79A4DFD758C756D71EBCA009F488D4CE1CFB16AE627A8A4B3676A063D184AA0FA63487B811EEB83DB3707E6AC5F63F91E74007FF9B8E09BA8F03285E1D0C99AFCBEE8D81ECDE81284137991A19683411F9E26EDFF61A41F8E94AFD1BC72255477ADC8C80478AC92C8F7A5794A7C7DFEEA1053DF71FB3EC8B30CF395020B637BFFE37FF91E5168EF366917860964C61697D0437DFDEC98CEAFD5FBB5BF5A85A80A20A26B83D3F5A8FA257955E61CB1774BDB7F2D06CEE9B6ACC6B28E4956B38A6D345DB6EB03B1B9CCE762E5DE597461DB5FECF6C7DA3141F84DEDFE0452FA2E7A90EA7483F9A87E5E44B4603AACF03EEC79F210F8BBFADA995D3D0EA042AE16CD57D302EB8A7E0D75F7B25104AB56959D179CC02390F97E2EC5F7DCB76B26DB957677D584539204BF7D3D05F3DF675121DDF21ACBFC65EC43FE7A04BD1F300FF41C0142AAB9EED014DB422F8607B3DF33AAC0ADD245E3E0D80E50319FCDDCE360FF82B52998EF038F472559241494CE5184484FAF86A5F6861C57B5A5B9AEAAB72AD493A73FCE13956979545CE09E8D486A2DA2625817DB84D0504EBEB9FA872F5B7806E7CA68188B799F35FE499011CA1F2B101DE8C5B24C557C4440F6E3992EBCA59F713AACE16CD3B32AA6712889692635EA52B7BED5CFFD6F2896D349C14D18A47DD9098C6391446D438153B50548FD93D888B7749327461777C27032C25746D249FCD62E7EF0E3905F2351B6297449A9C090E10FC92612C83C078F2464C0AD908E72AF7FD96F4F54616644C9A22BE8E6429EE82B0FB550CC207D7CCE7FC43C034F50A370D8DBB245BFD6C9E412C85AC784B6557B6110780AD0453B5DC4D06348853B0E3ED3BE5159FA34FB252C896395DC803103BEFA589B90876BA183A57EA6752DF39B3E81C35552FD264CA0A26C6C5E50D5EDEFE75DF134F03401C3F12EC94FAEFB1FAC25571468F7EBCC8DB5EBAE195317226BD796B8FA3EA62DACEC2381F7BB2EF05060A3F4E19611041DA50CDC4A31E587871C8BC5D2F8B090F9A26A7B15726C50FDBEF3B417A72ABB6C5DFCA9F4C0D02C647B31B60278567DBA1EFE9203305E844933916DF647C2CC35F0243DA3ECE09CA16DE56B71EC65FE4E17EDDCA60AD97D423D7AB7C12C6159DAADC34CCFBDE355BD921AC9B76C62E49EA270294F0DA0A2C34370C1C04B75DCA8914033B75B04211F314F3A68BA392256B139723DDBAB2EC6F6C5A4EE84B501B1CBA866D79E396533672A76A62B5BD4968C45E6232BC6C2866B2819815D0306173DAF0ACB1FC9190EDAF4306838F8A2FA7714770CEA8D7156DC0D65E2327CB7C2048B55D9382F2E628CBD72712E1C63CD728F037098926586053B22E76E04D69FB666FE3EEE465F3CB77CE0ECD8F48FF2576E53F5829CF7C0961A578BCBC6EB86932FB9807E31FE212D438D59100A594CD498536ECFF77BDB3D88E6AAAC55C25F464958C4EE066835B63B24A5A5C500F7D31D9F58AB801FEFE12A3539E618581F7EE0FEB2B4CE34FF1A0DA28132252AA4D8A8FE5711EB601E1F88255D2A669EE845D161CA3FCDEEF16702BFD79F125B149CD31A86BE46DC769AF4E6D729096D9EF1CF0FE5125E8E6D989DD749C8E0348A647F6CBC6C20FFAA83149710B6F2CD7B6DC4E6D1CB66 +smlen = 6411 +sm = A24A37D2A861A1BE66AD1454F2D56E4E24D7B520178C010342F4CAA66A28D502C9AEC02E4E96F233AF7B52E215A7C142B31836D5136D38F3DF7589242E446D1B835A9FD49388AAA43B36BA5AE5B48CE903DA5EE0385FFE0AABFA718774E44C35C223DBE4FE487EB899D86F49788BFB8683E36C58B70184F64F74B7FB7C0D2281B2A252FB889CFED13A9F6A70D04F669499C41320C42EF898EE6EA108E200190763BBFEA1159E791E7D85B50AA546C02A11AC09C02E9C404EF048AD37924EDC47EEF3424D4FDEC30AA544F3FAF16D34D713A269414A81A6EC019BD1093C659C163A7703A3FE1D728E6E689E426B2100527DA9A532F9E8AD8AE895CBD24B7240FFE32A2619B6C7B79C7A74E302E0E1198265BFA5D7EB5B0D23A65904E8B5D2D32CE3B18E760C5A8E8EB052430D18EB49E8377A6E0C76A6FE6F0DA715804AE7EF78240FA15E9D15B70BA8FD14B07946606FEDB2E1EF07EE4F9EBB4CF45270AF6FF421820E453CE5B5D3C8D15B2895C178EB8FB83EC6B2804DEDCD782511A80EBA7805F236CBA268108DB247DB7F6204095BEA70D8A9D3E96ED0D1DEE8566FCB598DFAE7D5ED95BB5AE901C86116A150FA48D53F91E0C601B7AEF6E358F1E6BD2F041D4A0AFCD01062F2C0E081CD0D98FA1CA91CFDA75C8DE72A0AEA81BDD02C0120C83B21C9935673C35885320762EF6F275E92CF502A7B3A7EEB29A4C0C756266740BBA1858CA7FB5E3B454F159EE0B76008C320E94FB6E5FA874159E1782EB9323FB389082ECF2876B8A529AE1D1CD9095A44C8DF94B212A5A1B4218E03F5A84D3C385F1E726DA3760469F874792D7B79C2D5AF12D99FD887793891EC56A6F2A04CB73984A4E384D2349A9D185DECBB381E4AD51D8A2CB3E39F2D06761AFD816506791F3975DE74678DCDB6A8CB4A5793AA00EEB3E77FB0775FFF655F62B302E2D18557FE3A69C3EEF9F7F4AD704BEAB3AE6A86409E3E001A7EFBF21FC39DE7A2160E14BD6575679307AB37B1D68A731F4A23756B104B1C3C614972E4C89F2C830F85BC996EAC85F4B1486CBE955A067F04EE98DE4A4296437FE276E53FA83D7A268E7169797045DB86B13389C1E4221AB856BFF2B756E0AC7A4FB3F1AEF6F64AFEE6430E66FB4FF852A512448A1E01740E7A3581E5FF9C57C6EB20643549B15E93A16B5B9272D225D44090E5B26CCBFC4685FD38CB6E86AC06318CABAC03D065DC7467BB58DBEE96084B4333F65F6DE06CD6642294BB4BABBCE0E2BDD765CD8196CCD6CC51CDB108B738BB6A4ABB0EF54CDBF1E0E8828518657AE307330A89EBA162C750DE2DEB696A5CA5E20E68B9E7E6335D2E33A5F3B18F4F8AEE2A9EC8791F22321979199CE2896A7E5709C09DF173313FABB19CF86BD2B7CDE1918253ED82ABE26859D23FC66B461F8F6C4867CB0E688DF3AF857B95475D542A6D08816F6DFA0B134443B325B9AFE807BE6D72854C897EFDEEA8CA4BF381767DB0D2EDDDCF3BEBF0BDF997E363050191047C7D5334F40484A7C3D8AE93786071F8A20B0C3A36AD0376C45288A85DC8F4D75A87E654DC32EFE53C597744FD53190F4B8995DAD57D15AE71B524E57B5BD08236382A1F2AE161193FD78EED8DE7A0A8CC27D3DEACC732AABE51BC2D244F8ADAAD076292E84752824E695432DDBD8BDA83F78112F369ED2FA079ADC9489F593BF47005890A7CE3E2309E724A318F0B05B91C8B43E1344516D8D1785A93DB28698C6A499DF07533B620F3F6B82730F33090AD9233490989AD5D850409CD35D2E68CF55F6AE8BAD9036178511B57A10E10BC0EEB64530804491BDEF73951577193707C25EF98539B1BB655D01CED209D0D4C068E1FC7F2F7E6F08A9BCC82F1F8EC6FBAED6F340B2811D54C76B94A793D0B2A1262B11738F88597416A6A2F50289049768BE478D1AE65ED921A459A648C53385743C3FA52E5293C82289F67F0D6A41A19611CFE02C55F4986981033A9A92490911C3C4ADB0ACC15DC05012CD7EDF0EA7D307F83354FE4BC97F5892AE7FEEB8F8FFA3E41C9B0713224962AA1959AB374AC957708D077563F40361E619FAB86E3159F64DE8229EC1F4D01393FFA24AD3309DE00FC8F900807CFA9C3A9943B35549E56BEAABABAC6F87E73E2CB4D1817124816CBAB820059F5066BFCBEF7C1072BA42AAF6BDA8EC4E2D842849F17277423704DDAB6C1AAC924DAA78B76C1EC249E5D634580A017C924A3A3A779583B0A7B263B3559FC38C7C6B57A458AF57DAC311FBE616A21F4D726ACF1CD816D3E3D3835D889BF01F2BD26B18D77A5CD538E8F2BAF4241238DD9493F7784D47D47A039E698942FD14A4A8B411538F33EAF7FF299906C16DF7ECA53601850202BE74AE7F26918A37FA700C944A5772CA400416C670C1B6527D1DD4BACFA430D0517AFD1599F202210FCCD907516DE2A720C8AC4F1995CB5AE323BCDFACAA1343FA405AFF333B23CAB3798B16A06619AC25C1BDDAEC61AD0CADCC183BB105EE192A785C5DBC623AAA95BC1354464A3ADFD8B1B0FE66D776CB3A49F019059C00619ACC9B14B6D1C0DB6D4A14FC0C0DB70A8062D08F73B62A600E4BA01D59AC8B38440A63AE52E2DE44C197CC1304AA2461A7BD2E66C1D39099E165A37EABE78703C3BD0D10148BB97F905F9563ABF72CC6951ED809BD03A7BFF7275707F240CD19D57323CE7580156F8568D42EB7CC76D8E06BE7C2EC6AC6472F7047C34151E1421232EA61EF3CD27E8C6CB26B788CB9F8A561CBD5614144BD69B0ED1A934607A8FFB76F4EBE8D2C14E4D7F471975214F0A1CE3CFA17AB7588D2AB451728FCC47A6B35DCF71D17CEA0E04B78127DA52673F66B21EC60F99397D1DA2E308A1244E1ED132E67D243CF1776DB533711FB746DDD5A605EA0EA9077C940116E898BECC4E73464A249547C265BF62AEABA8B41906437A0E6A6A21114B753C7AD13F9095F895CDCA087DA389FBFCE5E15AEE85E66249D104AC4D59C063173E9B3E6BD895ABAA9169BF33DAF0EF8FA5F46F4FE8A07CF80EDBE3AF1E9DD10EC7BC908731388B522CC1C483D792518C012152BE44666E2FEDD4ADD6511DE6F9EA8624BAC2611149E1823095D0AA30554AE823D6A6809C52C3AC020D812A8880233AD83011CAC4DD9A5C491A40481E1D9D91957C915BDEB8F2F94826916A7FD054CFC639D1636EE49223100511AEA95E08463F7D86496FE2B56D81D859D8B00EB1B54197463B9579A2506DA36225A8852CB1E94C90F439245E85779D1BDDCAFD61561EE962A9DE8B7F691E552E5D30A8FDF0A80FEC12C34417C1ADB837DAD7AB509508FB80AC99CBE2FF253708F2550774CE4F412B3BCBA91EE51B876C445A450B7CEE083B6558B4B264CE141BF56994AB2F0F6891216974A0201015076B4283125E7D1108B86956C4AFA44299C51B6232CA46272DBB1C866303524D40234938703B1EE64242E076F27FD3EF12BFEF87FB44D858C4C116B07D3D62256DBC2023DC6F87F02A95BE746B6550F3FDB0CB19419A276085F122A6F8F8F3FDE94AF223577C94E8CBF4E0968A1AC3DB5111965468633B491B7E59305A489E5F684003411D66FFFDE463F4BF652DFF828C4B2606139E96486565C2C3E675036204FCC42E7CDD351A548E8A44D96DCECC8950D441C0A3B04543093B62A86F807B9D123D404FDB63962C6D2C0A6590C4CC17ECE6DDA9A529B8CD7728324983868C12005AF6C7194DA605EC93C731D253A7FCF68219DC1685703721911E36FBCA8E6E5EB27F49D8EEF27F8DCC9D86D01D8647719370CF6DFCD02DC7B5B29EB68129B01221E6917E013F03AEC30F1B60FA989078654B71D8F97CC8DD4144D0309CE7F4A417F3D23731F5893C39178D5D16BFC329B03A58E7C35CF7E1C28AAE36C99EDD28DB4F330FA1DDA76D61626F6472451494F70C2FA7E4A647327D6A561DC96B74FBA2326719CFE7017F2AA0B7F86E8BF6312CD106E399F47EEE28F53B978E732B149AABCCBFC1D1AC46FAF44A83E18A41414758F2FFE40A4206174C0ADEFD885E535BCFB87FDA887DE7EDECC0FC1FDE912DAF57840CBF86DC67F7E754E91FA7053937808A9AD2154624E0EC5AA9EE90CCA6AC1FF6B2CDD26FC99EB55469F0D262D7E272128FA8BA162E21F7CCA05AF6358B7C9E2ED444A40418ECD2650C31AABDBCB2F8D3DFF023686BF8E9D85C83DA82CB53740E94A317AE28DCC8DE0985C4612298E5A0DA9894ABF63AAA0E113BC7D2E6983EB38F709771AE55B8A88B3C8E98C3061355549D3C3C360C3922C2E0B93D58EFA0490168D0F30E915B5BCD7A3408E6D0D3B7A149B993E0E121AA2DE3C626AD035756616DF71B670194CB2A5AC1F5524F7999398197C5F5506A03199963EB0B943D4E69BFAFE9D9892C23DFB158D89B809736DDC978BC5A2641AD7915F12A94AB02FB41D719B38A10D19700D855A79D7F8A24741BEA75E59F8AF8F13623380F6C34606F3DAD524C91EA4305EFBCB5C5752F3D3D126E7F41DD184BFB0852484DD5A3115BA714BED4F9905A16408223C7DAC9A9B253F4A5C48C531FDDE18081B1328CD58754A22186E135EF9096AE12E7BF6337B5EDFB4BFEA1CE2714E79B486A9FCFD1EEF64D79A9AAB5D3254DBEE6F8535B6C6D7D8CFFB6E800000000000000000000000000000000000000000000000000000000070D1218191B02C7C4451DA90503C43FDED1CCB3DEE468A6A8D9E56670CD8F6A58E7941F1BC5EFA6E2AFDC0141A2F7E8F781D79E70B4813263A9DBC8D8A67F89371CFBD90977EC96461B28BEE4C644F2C91E96257B1909B84ECB25CF438A3FD6B835E20D5CDA56A1FB7995FCAA0EE1B5327FB1288E3C57CBEF0554CA5AD6FCD1F1865C6AEC6CBDB24495700AB5AAF078D8516CA4FA3A231A97C77BD150B127CDBFB42C03702C9027B2A5F6594B022EF55B63BF3EEC27EB0E9529ECCDC82BC6AD1F011F167D602EF1F175DA5DB4028BF08A053AF2C728ADE93B37EDC2A75B7B6C6CF38CD1C07F359C73B131B13DF76139DEE6795F1D85B47F29AE97D0E40CF5DBB67360044F78940A1E80D9D99FD5AB0185210D8769911BC471650DF0FCB9C3AF038F7882F677790E146E612FCDD6FB89F90B7E5E46CD648F4BF8F736D69F8A91E4806346B4366FD48D1481C0B47ADD82003310B0A99B779D63EDE1771F50221651B2D8AF40F48B92EE1327C85A1D2EF2D86378076BEB58556FCAEC6029649A0EA5FDE517A85D87704210E071FCB6F63317AEAC3EB3E9746018E1028C50C790A45B1BEDA6EEA2D646DCE401AD5D7850A5F69CD85301920DE77AB0D01B1361EFA3E70AC05881BC02190720ACC75A691D6064F9D24C79DC72476309E58CDDF5FB2A253D857A79C8E898AB6ADC300EAAF208820CB02F5F2CD317F4052D40DE28E52C55A0349DD855D64E8DA8296D4F572281E221A3D27EF76FEE67FBE5484E6460C99950763B801FCE828E93D2A633A1CA5D7EC582D7C463DA5A9AA8056BB2173306F3820BD0A3273742789B61AF89CCC42B81CC68745800D2A59231D5D28E832F443A871DE5B6B10B58A8AA7CC9816014D7F3545DDF1F481B7F0C9DD41B4D96E5DB767B74776C2253FA230DF65F3E0B944B95ECD4138E2847418B084D9F9E0798CB5247238EC12B88C10A5C0C645E1D09D09059C72E33C28A472FDD8B88EAA93C63BE7D980A12195C2EC3105DF2BB81CC9C3009F7771B6B813CD12303E3A9961D6731AF55ECFE5127BAC68D06F835DD5F2D584FC0E648C3A4256E2A3D4B81966010964657F33D1FE0400724C488D5AACF9F2C0B802CD812C8452E5B8E2B17FF4A1289D33FC405F5DB4ECAB4A73FCA3634756DFBF9012C413B6F64788FD0F68F8AB7620477ACD3C14009377F3DD54B9EAF2784433D63341323F54D113FD63D7456AFEF885F13C13172A37A5DC82336B9515F8F7F4903EF6DBE9CB34930743B6ED11265CF94AAF406DEA9802D17BCB369AD0D9964792F74D338DAFE47EE88B3B74EBA8E70774EDC1F16FA876FD62B0BFF880CE252EE4435B1DEBF36F0A06A4FB406F01D618C135E6103E2A39F4C9CF41EC93702BA76BA753AB49B5836C20F67D05943EDDDF47AB8C5B81F4BC22D773305076F7E5B697A7B25B016190072F756F19F397884E0521595326CA591672684A3BE17C9F5CC8E8F4848F7136762178FBDCC7BC6A6C6A31345FEE687B0505F72BF1AB7EB87BFE5F896CFD42DD67A239C70648B39BC0C84DA33CA17838FB4213C38B68F22914FEC3DC50194E883720719E9B5F8D037DEBB726DBD899ABD97853C54B0BC347A322BFAF961C6CD6209C98AA81B8E2595FC151B1375BF4FCA2DFF49DF40A3D1C694EDFF6E9687E73EF62DD42AD7A05195A7F206F097196AA0E4D68F8132D4A00CEDED940C4F6AE02E6D3763073462C7A4BB11778290E744471EC554A05917E52C5263FF02C07BEE055234EEE10B79175DC164AB2051B03598DF1D4311E87ACF4AEC45C55B1A58B0F05EBDABE248A27C0187643CB8F9529D31FE0AC4A28D780196DA00DACFF5F2DD64FB04E7C159DBBCDD3343BCB7AE188DE15D923D2AC0AF232C5389DC9C949FCE554F7A0425D4F9B28DF2EE4B81740C2B5A5B93F0F7AB75EBD360CBC78B11C28608B5BAFC970CF3D4455A20A198392D876EDCF89E2639B50CD84AE21BD50FB077050EBFFB210BE711D8EA807CA66493650E909911FD3CAD99AB94B2AB2EDFF192D9D75257818272E147A9C54E06C53210FC091BF4175F2F44423669716FD9A6C4F96A0C4BE17839769A806453E55D7357FBFB3D7A458E70957D524C0E896398E135BFA68A0CC136FB93EE7D30AD463E32E152FC32CB8E7F0B05A30EB13C0DF98BC187EC0A54856D2EFCDA10A82B89DC8CD21C67D9B6DF3D7005EF3B2BC9DCD5D55B64DB40B74FD322CDF9D9911A00B5A02E1AD5CA9BF65D90DB709FC1E5FC84BE97574B09C83B49963A51228A667BBD84BFD8E0D90EC161FE5CA73BCB8D95FD7AFD982AB7EBAB51BD2B24CD6D356EB850D2C65593313D8EBB97E7DFA450AE982918582F86A356F538EB05AFD460566D79F040D36C93D3C645B636560007D51B121DE3FAFB3ED70B475AFF9617DA4B52937C628678B109C3B76BC15BD02B766A394893D8EC966DFD8033D12A8D98AC5BE201134325E32CB6786F4FAECD7DCD05AEF5F3739122B817824A672E71DEB312CB7DD6A77116B30715076384297B1962EFDFEE6D6D2B2ED2EA4DD802F4784872D825DB828557D4D927B7232682AD91CEC3E508854F529853A8797B7BF7BFF8E3C180980DDF4081E96A12A495ACDE0C73282AC78617C68A55A94573E5A37B859858D1E19ADC82821B316B9D346ECFC6DBFFB3779F692A62D20D1BC4E730FDE2AEE826E76638ADE3DFAA11057B0BC8A80E8905B15E41D9A4105109F18E7E1362149AE9C568D1D642D65B94253BE2B13E7230F8BCF34DC87241D1DE72A65BBA111C111CBF5BD618CD02E0A06E37F60B3736631073A6BE004C1AD5F0091A82C87B276F7C5AAF6938C886A6039DF23482E2064F6AF05636B4C6BA6B24A29AAF2174AF4BD959177203AE9B160F81CA6764948AFCDACF6BEC0B987C6DBE178DCF47C137C64809483019C5F2072D0301C19C500C60B5CA913C24A8F28F50E1578D806FF9F9B810CA14BF5F2268FA18DEC67D973EB1D975AAF871ABC980D06222493D900CEBD8811FA20D5DB8F8036430F8BD7F9554F7CB47F9EBF389F66C3CCF9F42DB57AFFEE074FFEE4EB3E11612FD8A8FE02CC4E9D2F8BB36C505CECE9DC87512AEB5D8EBE33328C5217CCAF2E1AF1E38BFA84C0035DECD8D8C250FB4D964E8F0AE448AAB740D9EE9D794390686FE9A95183F0D5166D479C51014F1F29D8FEC616E1A4E7A9C86E2AF790BC7BD7BB6F746A2266332E04AFFBE6B9512E6620681C3317DC846E4FD7974E8AE87E370ECF9DFED574E339CD7E8A663ECD1A7BF5842391913D98686F7F2145BBC420F2F58B89131D5F3BE41C85752E13504BCC549A8F690CD2B0E1E29E4DFA3CC76BD398BBF28F33A00C3915DD719F7CB985E9A0A7CC8190BFFC8BF47310C71418D7A6C629C491EB8E455148BD4438BA6B7014608B0CE6A1BC5B035BC174C9BFFD966D8305FE9E5619BCA3FE4B39E6732DC652531819AC828F86EA11360678E786EAA741382D713AE26A608D582A3E4583D45744ACEDD32670B5AD4A1310301B28A174DC9858A55F0C1B7486CD66CB0635083B0C63016E40DFC533AB80C9CFAF1378D00769DCBAD56B09DA3A4E6CDBFD8F3FCB951680020DCA58647665462E42F42DC14E7B20F262D3CEB0B1A2BA807B98D66232AD7D3839C298564BC36A134CC2447B1B9FE69271960459C0A6F897C1878140690DA7D41FD8AAA05A679FDC3037EB2885AD3C82374F4BB991745351292DFD8E54F565E0093776B7EA65DDCD500BEB4D15AF6029F2630A0062F2D4FB331B47B6A5E139D385016E1FA490EAA209636B1383B7D7DC1148F07ED2CC2C03FA7FEE09305F34C57B3CE899C18462B4F1EF88C1AC5259440AAB48C5849652AAD9D3CF3D31F36C7F64F918868182D36345BA5BB7A4EE088D8B081EB78FE977F5A5295177AA427215BB26D1DE33AD4B2D610A47F8C672EEDA703A04D0FAE4C5961F13AD6FCA81863D8A394135565D8B27904A511FD0621A532F84A47CCF4FCC2114D4C369B7A76822959F8CAA25A6495081CA9EC3AC3348A981618592C090B6439CDA2FBC932C8697B3709323E3388AF8EFA1B9CDBD65A65C8F0C302330DDBD10E0235F8030562452EDE447EE5A5A9A636AF6F615B1210AA7CBE69572B3467B643BC5F5EC3F9AD15B3AD918993355E209ACBD0F1393076DA3B0950803295B6571E476ACAA04D48A4627367CB7FAA83796C4178CA9071DCCB8D3EA70381B61F0C56D515E0A765E266DACB13056317AD8737A1AD541AACCEA1641946E331229F19BB54C20BD51E63D63BFFA13110A552FD0A95AB984EF53BD639EFA0568C6875B2798E3A0578C940C0C4197D3587BCB1CC45A99F5D37B1612DC1A4178A3E288FBD79DDACD049159D6A5416F9EF3F38C74449BFB2E6A894566C5C17B4555E154F29A93241463690 + +count = 94 +seed = CEECCCD3F7BB922650E3F6E8F20C47AF17C1C1053EA8FE08226F167D67C3B0781BD774C4C7AAD23C6AB0B9F3E3F96F97 +mlen = 3135 +msg = E13692E3CC06EBE8FF9A292D890F0A34DFE9A4F968F196B475AC4DF553A30E2FD5DF008DF4D7508302AAF6389B6A5A9135E9BC8A5ACCD2BD2DF98FF662B763101D31E24E8F182FA50840BE27F76BA5ED645BB4D3F7F2F6CE25179A47FD7B6441A9B3A28783CEEDB425B2912734A75D7D03811172188253BD8F0F52EAEE84A9FB025F95EA1B566C53297A6A090F7FD8B21639523E073ADAA750D63DA61631F933FEDFFB2819E0EB3074E9E11E10B102AC88E2C8D6CF408FD241AD301F9B8E18A88B74CB4B0DAC76347635DFBB3EECFDF84229BABCC003C6E4EFB7394E25667DD7FA47D36E027559F53E98789E6E732E6AA23A71607677FB975C2852367C5BA5E3D10B3017AD26F9A38CE803929D08A43646FFBC3980B359D8BC2E9615636D4E5DE8DE6FB2465A983EB1696E98DD33FAEB7AF8C2D30506B22390D7F9FC21C7A016FDF22D21ED2EA4175FE9F5F44598EC26452700DC9A495675431E1236865F2F4AA5BC9C9A10EEE9E29B1FC4FEFCF8F24BF94342FC7E19AA6534C3B771D910AA419EA2BF70E2C1915891CC630A3397551E4F34BD2192B70EB210EA67CF152A35A3F5D0878E153579B42AFAFE5068B2BE2B48127FFB54553B7A9B6F845E7D72C43938AE42BC03E33B836AB212909510AAE7DBE8EE6D0EB8AD84D60832F3151273A1E09C514C3AA4CACD15564643F4255F36059022B91BA4137ECD97B34BE3308D40EF06BCF4F45EC625B54C7347F52A21815508199C8B7A6212779CD171894DA9FC3DE2A6EF5D76BFE03B8199ED1DC92B2A403E4DA009CBC0FB597C5952BE32579EB8E781EB12D935848C051029C528CBB68CBC1DE0102B42561E21F48E72E028C2CD8816A9027914571B49D2F94C9189E1A7F18D7D3D0A09B3A36EDB8A084ACE5FCCC77E3E42EDA0FBAB8C81EAF170103CA757981839C9448362BCAAAA3F20C8DC653AEF36953559F3597E1915F02A8D33D0E46201FC794EE055E6D9955B91FC7ABA1F136C280367404725CB355FC2F129413581401F98236D2A6F8BED7FDD7EA99060DABE3F0E8CE20B0E98EA80994D1673E8CCC6A0BA4A9D544F3D31BD95C9D3847527A978C1F155EFD84B6A7BECFB749628CE82E80285FC7272EA05F953404E437AD557F38FD9BBF77A69B81E4441605B23F2AAEDB00C7519D8E9CB4CAE5F8C3FA74FAABF6C12595BA045F647ABA7168C65C8A6006733D1341435495C7088C3361B50C43787EC24C24F57323466B5C088E8097B44666453010DA38AD65B426E72140AF78A5448B2F93DF3820F013FB9DCAC49604C86F2B2E4EA565463917285F148E8BFA9E11943AD3B86B14ED59A190CAE097DB26DAF8FD2A642676A37DD90C23B52C82CE028B80A805D9BA05457F7B6CBAECBA4094822E16C14D6E2291B731D581B12FB16802653360AAA6A7989D61C80DEBFCCE81A36D9ECC84039C4F086A5579D36FF5D0CBE61292E4FC3D14277AF380A9C1DBF36C2D61F59CFC0D62524E042710BFF5BA719E56BA367FFE849D660B9F7F3B638E113BF2E1A4DB1B8F65A0FD680BB2A168A4FD5B4E0EDF3208AD47F1FF4AFBAA726E38763CB5C84C03DA3D1E32CBA873B9A0C750922CD3D0A10A4877EAFEF602F5C875FBF0EE2F4F0AF7F308EF934F7E8E74FDA62A860BB594FD061D1B2BB32BA613339042FD90E749ACEF450D204072ACF58B18C365E4F4B815F1E837453C4255D53BB68D50F3677E7173FCC23D2B592149A9F3DD615868AF91F705387547862D34553FD45B8DF643F596DFDB7ABA47BD5D91445826C86FD4D30365A2F9A3CC0913DE19707D072F27A09EAB906304008875B5BE3526210D6B8BC8663975A1F78EAB9CD7F7305CDD4C00D6277622E50606E1CADD639730101D088BC2BAB295AD86BA8E26F5EBCB3E9C7C543E533A7B3C20F0F89001775F714825DC8547BAB06F5B99C5305EF18372A184569323FE269D45B669B9A222C9DEFBB0B2C84F42A57EF343A5C12F5712EEC33985DF8F0C566D471A9403FC103A3EEED42829D8E3E5C517BDE29447841CE96C8AC587DF3E4B6227FAB386140DB0112ED0D2846355C4A45E94F3A0718CEEC13FD3CAAEEFDF0B7F89F502AACF8C9D96D01B5549157B7DF2BE65BC30C889E69971700286C561DF91C8CB923001E5F0E21D2C7A3DFE8D1AF07FECE1EDA20C031B29A4389F265D2C7BE64EC37B2884849EF30FC8A82D2F766ACE68C72F0A4B72F3B50884749814387893DB2370A3410F794C64CD24BF0D13E44AD500BA9816F9BAED72F7593F758592C2E974D1207A664B869130BAA1FA71DBC55875134E7CFA276E36568F79483886099A1070C14C6E4EB87523E04C0154A2250624261211723453CFAD185298DE06D08CC25FA18BC58B34ECDF5D9DBB02541BAB4A2AF110AE09130E12439F1CECC34F9AB5D7BE36C827A6F2F6708B543D4AD2E424805E2A74895742B0A5DA30CABE4AB45F40CBFCCBEEBDAB9B8EB8F78781168B5BC79E04EFFE1757AB0547B9BD0D2625673CE528D2B4874D46DF0E09C24FC413EF9AB4C3D2E803C1E316D77FF5DE3368BB925B2B1F6FFC340525663931F5595C8AAAF9FB0DCCDFA4793519A66D4FDE38BD2044C60FD1DE15D60BA878FDA570E7AEF6DB69D2527A1F1481A9D05FF2F6F621238939ACF5D2C37B2BC3A194A9E65E7441764A5EE37B1FEF3B8C9C425BE1B5FF0D05BCB6A3B91876EC04ED89A31749FD443C2B85F8F388E7070D77DEE37E2B666628CC9A961236DD24AF2769C1F613B4E77F8E82D1F410ED59F63F1DF19BC53A448106DE4F8EFB8CC37E40144B0F658A4135E25A3CF36D8692DEF2677E4BEA3A9770F19E44D55080625421D5BADEBEF3B39BE71C08650B5718A9B2FCEFC4BECB26C4B63C43F6557DD66517D103907F82F9C2B965B7C5E36059D2159183F5ACB8B5FF5E6B92E94D53AB25AE955424E80EDEC4650BE293E836DA6148392C500FF4B7672932E90E068569B81AE335B2E5013CCC95F571948D58127EB1269A08D6E897D2D9B60F3E49847C05D0B3AC230A67EB6D38FFDBD4B8D82D7B9EC803429C701F080BE86FAA165C0111131712DB4957FD84A8936AB55558C69D33D5890CADD08D7F0D4962CF9E2F69C7517E79DB14B76E6E188F5ED95169A2A7E4C0EBC2175EC2DD44ABCF239CEB3E22F955ED25DA41768CA5FD9A9AE15FAAAFEB431958A679249AB8BF879185E8FBF9986B96A92972153B4CD0D1BE001E5AFAE3AD1F0B1191F1483738E728D4AD240538E5EF7BC9BA4D5903929D74CB64241306FDBAAAE17B1C3134AED2CC394D3EF9653CC62A29C4B0B9BE04E95E072EC98F7A80A7B575DED4A1993AA884C1EDFFE056EC475D934B4EB0EBF418975728C6E9CB3919B2B67D2C71228A4DF1FE2C8388E3A2BDD75549417FE795F1947F857B1C0C9CA021515FD4D79E691493B988080943C394BF29E4190082A94F224AFDE5853323EA51C06B41547EEC0DA5CC202A048D77C7B91E794C51E72B02EA7C14578C11D9DF48E099465783E496029EBB6D42D9CAA52902A4694355DB01DD7F5D7C113AE06E3F712FA577E937CD4FB817659F93964E194FE7D509A81C258C69C3415A8F11D35B414339FD1CC1D4F50665D9111592D1C3A3D69FCF6A971C285A94F5FFBFE8D2FD2746DCEB3B218D970D670D10135126E479D92000D41EABDEEA4C04D1748A4908DD39C60A52AA5FE29C8ACED50DC1295B5C2C4A98E3C62EE4F370F4D3E500FE27B66F65BAE604FD558D66B7F09CE36C36C8B5B4FED193EF56D1D8DF0FE6FE0031466A1C633203966FE83D6BFF843657DC0AF176AA8D5CB7312CB4E072BCFF24D5F3828E29B2037E8D1FB63537C70C27011E9A97E3F04895F4E84AC69C55D450B46D5792A5D790557BE64F765FA243AFA98527B976783E7ACDF76A7E1DCBDA72431FC30D7B05197478D8D74077626FF7409F95B24A1F1BB6B803B9F1B9AD5B06883FAE6C4B587C309A63F3B2FC9619032157B98C1DA9608107E87F4FEE0DAE995AB86AC9869446CDE92441F0B9F8240E6F7F7AA9189D92B7FAA3280FA749BA8C7729F8974049C5CBCB8C6650CF1C16B8194C7AE1A82B40B8B04488FCC69E674362FE4821D4C1846CD9BC49234BCC464013F5F9A082FB83D63098C331D4B1C9129F52259CCAF4A9237F8EC5BCCF06F230C08DDAF1D0C21C5930F55D3D5F60CBFC447E7FCBC75CD199733F8D17BD043B67B0C138CB0C9C8F2E477728F27DEE573796F71B013689B537AEAD4991E67F2F5EB94BFAD9509D7C235C9E55F68F26B9CE8AA90834D170F8B700A40AE9A817D5D17B1644D25BCF1172A5CF0C755A6EC04FAFC39DB06AAA05F5988E187B9E110EEDEA9C84B99AD29A4B31950F2C870A1F91DAA6A5817FAEAE516FA42660FCF56000F7365D8C6CC11D4784C6FC02E4D0C727806E9D43B957BBA124C980C31F81FACC6D46F6C38D227EEF8F0 +pk = E9D58C0EE0B2DB275BE53870CE3349A856D50594873EEF947B394B1828D11C82601E593CA79F0BA49D1F727F70D318EDF7D50BC264419DBB4DA4CAA49B98A24D4860ED9DEF4E5D4C50270AE06E080939BCE855165DF6156820934FAAB57C6844DCEAFF7EA5E0EE56B636AE1D6A8DC25330984206EF7B32C624E3BEEDA6A8863CA9ED0AB128B6206484CE16A8D3AFD2D0B67B4901D9203EF130857426CF75D6D7A65DB436C5B5AAC89033CDE66E62FAD0D99324C6BA12197EF022FB5F5E50AC19F37782EB1FDF65F2C82C8DF621BD107A1E3F9DAB86C1FD044B6F7B82A31037A9F108F9AB589E25A6AB5E7C90755E09D4A1C1388DFABAB587443E7922924F39B534F784DD22E1FC389497555B377CBFB36978BBB4165C8199E9067F8CA45743FC86222DC957BCF288422C9DF85AA2F15579F6229FB7DF31683A3D51A7DD837B877BE3D4B4DAD72CB77921F36CAFA5B6ADD4BE048ED547A163550BEA0F201E56AD76B9B0DF86AE60C4EEA56551A912DC2D5848F625B8BCCF3AD3E96772B95BC276D002D6E046182045B36A2AA79DE1A94012180CAE4BBECB432AFE119FBAED653FC969943BB96C8236F8BA578294CC498CFC41B7B62AD9471A5E613ACCAA8DDE9CE36AEFBF817C4E7110015A213D678C7318478DC23275403738A4E458B415FD30E9D43D654797C262ADCA2CCC09658695180E642914A654C8AD8B15AAAA7B6AE87B36845526F961FA8EEB0A9BC956C41DD92FD1EDC665E5523C3234172EE78B7B39F2E9562E0A334CABE4D78E764FC27882464932EC0F4E722617F2C5157A0E2C611BF852DD58E49108386D273A5E79D5194D4DE737B8CA4C292F99F30807DA63EBFD865E04568DC7076841CEC474B3A2C8A0E5759E8EF5106FA237D9970A4287511F473188E259434A2553FB1D8C9AFCE1128BCB9CAEDC3BC5E5F4ADEDD536F617374C37E7BA60BC5649DFBE1B1E45F7478B3B789EB0164CF29451EF0137B77FC86B8937B76FAA84B68E980C1B2E02DE41ADA8A22A06DB66DFCBD6ACCA9B36ECFC0996A2538599B5F5705F482505AAF87ADAD3C3E39B7562FADC623DE6C091A7EE046E6433822C1124A1450EAE23EE80EBD26B8555B466EB29C9965BBD7C19EF91BA28A601A81CB5B04C4FB38F748EC2D3D025D586746D5B4B36BC5C642DEBCB07C156AFA32642F7EDB6B7C1E55050DA5E3BDB5A93D58DFAA717BDEBBE4BBCD2F9C65F1B06CE82FA6A0129A2259C43F25F4E66B6C7BFC6693FEFE737D131F88848FCF71239DF46A9077F3033EE44C6B8A4907EC3ADC95F631003C1EBB5EC112B63E292329B9AE71F5015A109BEC1BADAC0100E909E16582CA8D0168A7B13B7935EF95866917B8520411A04E36424A93B72F25D09B9BEFC3CBDB2248B515E93874FE65585EC7C9D35BF1E5968A71EFFC011BE882F4B1524194C4641B74B14AE8C9B72FE371F394DD5BE488518B23716BD7462C06425A757EA875147D28544477B2DE427735A4AA8E8EF69BB054ACF9EF40B3563C458D6547CB301918A4D4F9DF928D16EE2E53D975C72EF7B302102EBEF4EAB1AB17552373B56BC1E963ACCC4AFF584BBF06F6511E0937513CFD2F6C7CF47722177D01C1A77817F0B039C87A1BD593D65AC0F4235299B16F54503F601DCAE7D8FE73AF4E6FAE81F3CDA40072D2EE97F8FA7C8B87ED5FDEAC80F5CA84E2BAACB4D8A12471B0DFA0D84F5FB4C7E47ED1224F4667C3D05EB3470364BD23AF752C5557B104746885D385B6756E54C2A21F22433EF6A5E60D5997DB10234FDE9DA062D9A6F63EBDC76AC947FF8FDEDB5B8F83B009BCF7DA9A35CE27E5AFB2A02A5B7C7D2A8B6EF97914176DD4A1C66FE4C841E7B9591ACD980B9E485AA67A0852D0538625A6D47926F72E89DF0CD788A599A39DB4122E47DC12E5F28BD3A70206BABE34AF30C952A9401B8301349668ED0B0A63433A96AA8701785D58F5F9518FB3AF215A3C49E224EB8B502895B95B6F53188EC987409C0B868B5161191C315016423D673766D851C4775E66105E65F9305CDCF6D964505E2416C85931C80822F965959EEC2A1D2CFCF317BB560EAF26B43297608972B1CCEC4BEB8BA96C180FC07CB1F244983D6AE7D1172FE74F23D75DD34A9023A6962153B39D04868DEFEE39B6AEA6B56880FA1E4A45C3D003774ED2F8D69DDADDCF0BA6D58AF00BCE58C88CCF7D0AB2E5D89C204A5BBFDAA0525833F4DE247AD758C306A49A0C29FAE1D212D8B8F59A8D341E096D33261366A92507843498B879F77770A1E504D59BA39610618FB6EA15BE2A444F45E4575A6AEBF6E51A9BB1D6C0CA4A5A64114DE6E2DC52714C1F811B86BA2F4A11F483883893997EFB0FB412B1CDD2B910734F91E1994EAE996DFFA7481B58F77467320391D8AA99E6048437709B4516B76793B52CD2155DD0B600E372FA824F459806F978DFEAEF9D81C4B96F9D673A7D6232A4A5DA36E57322EAAE8FBDEA27427A24EC02DBCEFA5ACA716B15E716601A41DF8128EA3EF483CEA99D89C5EFF97262A09A158A93FFD92A988DA686CB2FA351941B10AD8D6A4BE714EA538259F03EC01D109E699BFF853F6215F929BFDF37EA7D0CAECD101A528C9808F94EE9B6163460E7F9CCC1A7F5CF8092F62982128AADEAF637D1D83DF7E6624878F0C05CF3160EAA880FF95AED4B2381A435F4AC29301E50E82516BE0C467E13488A13BF14BC706BD66D0225F6DD059FC6A151C487051EAD81F175507C71E945EAFE0B7021922C9A786 +sk = E9D58C0EE0B2DB275BE53870CE3349A856D50594873EEF947B394B1828D11C82B8D9CFCE89CBE8036AA98A85E108301FD4994C292B8AFC7C21EDF03F02EA74D5B568CCD7A26DA583FE09579F247E0954FF0015AC848C4F6D521C4FD7A5358DD8203B89B4BB612478AD28144257C245AE1901B39B7DE81CF670F8DEE0EE16162025347406062828336624841734637704736858664204400003342358188888315343343561617246864345173633488526580868340075612740580203167505352746326334148117717267074560555885152875736120872434347837254181387302836076328741340557653711202244182143312281574122353137507833045733547734722734680040770244812216683104836474254052073156468322883615411511585812581630464646447034082218262348214360253742163055558123866688546280654878543783047780545483240340023412454038656032250633135750683885132440787723640846113713388074656030011508368008636028607680548007227013244427478433752867438185665331843122003872202585038331255876778186171434753858428244446083622320081427075283247164534236214188350567060780217856413680314084713412261133774464772243010257380613226686668111785561030153034788065716172647353060731865828813046215221571082836616003461552232246746114541667775645147341183036224403357814004467562827646060150345438740171780645514338432441447014375083551561642635417547814205815650765512116336246100746085170370335351678841145244614251240311716131043418326124403733248364234766551651686655141722650506457457056636777734542215144284264327023700002756636268033557161768612185284852723822275071765551112741746162773228532732485000015401385216786335182151682502146838501771358372113250384830121573730105466448802662134615408244245400671447724640820015868880877485283242241786610170152715785226875485017681711042350583816052723785036771845556506380251418672155428324228866221712682454343608482568047354823864567488246250888380333021882741084125221067680365233512514548388267561433724887341166318154081623205251284600111380006166852688315745055362712131886735456487360432077707258672712622060470482205351551244722672417535137724002351845102171840822828424717080304310243728500237863045531746824423050656825678676648177301772316236010348577167166616366512104265287568850747581705165575107310027564208510743443337001125271383654567428476100052500772336220157846672705322616407175745034700361716402087647836667451838033215107214680287824501761587586384338372420845615261641180326012725785656253320176520422513787076175030207515087338028806828275421384644376678636541106578354740852645575251071313782542602512113227788083335425487080083633377862856418048466103130381027004860106484851653700742244054824316117317374657761551414145751344126843825345288780702653025105380446663728227451472323086461546423548377107487581370200450865104870812256052771700460005665747100838678740868512810776885486378853524520631221238467635410761408053581646804100823520461011488874464037730180356640032778747465677448886044822304510517204883140473137083115726287437804412878287284662713652724237232165507364474582276740563723785312264272060122418411412606536177480177074707740257710703574706644861208311218817803184326632676265073508440487852780333610881373CB05455AA172A4B305849DA1E3619DB9ACE8BAED1D7FC6C7EC3F68D8DB6C7BB9B53EAD5C932E524B539D97F8B4507212F73745A3C8545D281429433AEF110E718E13D03771D4CD3642AB4E5A0B088E432EA757C2AD3381381548ABE0738D89ABE051E5D4765E3732451529E24B3DFAF6561428970CB2D5334498E27408726843A1FC66FCA2FD16DE7ABD7507756DE271EC6D03183A69414B7BA16A7E8B918768620E1D4EBDE6B792029A8FCC854ADD208D826D07BCF5EF867161B68AE7D3451EBA3B3831A5A28B723B00CA1CFC7D8A3122558271D9FA2AA9FDEC35380F098DE01F4C0EA1E8358AD1E3588994C164FB6F5E41B3ACC7D56922262F048F00E40896975251513005FC126255544A0324F826C27A876850DD298B000A37C20F66D9758788E5EAEBA249B89F4E31B9FA49EA27903E7ACCCF08AA841D40471D546323FEB9B009F8884AE640B7C089A868B6C6022DD2ABE57E6B100E625751EA34A69C8A29C0151936BAF92D322EB947D17526ACB90ED6271A7899A1FD3703D4C9F45495606E3D1F6D4177E219CB7F710B9729AE46BD6B6585A3847185D99AB2F276798A740962DE0C237DF894A86AE135077CE0DC407949EC9E75121DAA8C5161E06ACC1BC0D1C2084D993C36B8A9C9321E5877D5EB400FE221060FD3D8006A79C05117322FC71662B00531B267E9605BBD82743DB852307EFAE9390DB9497BB7F714BC999876F5557D0FAE18875CE1A19406E0A06C1604550AEE744093A2F6DB82680A7ABF0CBDE1EA826A89B74F1E59E561897A9D94EAA596FB4DA0EE446F84A175BD8EA9E755C74DCD120339BC2A230A0ADCDF5BABDE9CAA9E9911BFAE83CB1A76B8C7B601CBCD7366FB5C5B52319416491EA517FD68ECC1BB114F41D0B53CDCE1F6BD6C7D0CF9D888D125747B87BDD494C096B6E13A00FA56FC9E135DEF54B08CC2DABD7218646B40207A603498C2545788F10B52B553D51230C1478C8C23C416AC67D817096628FCB3DF902237311C1443FCC0C6954D5D2D41088B180DCE981E134E2158EE3C65FF05D454BA60A1061D7B077A0C43866D870B346870D68A07FD601D24FF1B2B076242DDA7C75B6F69377228A4895FA9E850DC452BDD8B94B0CE163A2E63EF8D151EBF7F71B1EB0C0F6B8C8F185A472AF5E85F8A7220AE18605D6E0DA4BCCFBC8B3F8B7EF9222FE962D4567FE5BDC5DF1BB0C8017591B81E7420131D4051B487ECA164F52C607AFCB79F6D603B0A589C30599B006932DF1F26C61C92A520412872989FF28A620A01CC16735B0D2D97C47C1FF8670F3878E76900B5920F4C2A43612810BE49016F4F0420D67EDF693B90F66BCC943C9CE31128C12DB0C7E5A309A8683D1BD2052863AE98348C00B640B3EB1DA87D83B46098F2A9B50CC3DE6722B1EAD2CE752567A716709FE7C0070D4DABD2C329EABB2184A799CF2B01BAD3F6D966F81C0CBD3EC24C650600361B429E13B4683FD674C11508D09792C200857EE68032013EBAD03866E016AE10D3D3CC83C2E7E24EE8EFE26A052DFDB67C3DAECA74F4F97193A4CDA328E5E1EE1953FB071E96241B176B4E54FE7616660722F19A627229EBEE25C81303B83B8FD31DC4AA6F51A510CCFDDDC5FF8F8FBE24CB19AE0E049773B1EF63FCB3FC38B6328C04890DCB4D75F14E215F9489949AA41F2B56E1D356CFDB78CAE6B5CE343D32A79C023B7FF544762676EC8B4865F03D6CC58097D057E16E253759B133E10755680327CF786EB1A809ED142078BFB07C518C4D2F360B8CD96322077DC64CCB3EF9041209F2F25EF69F5D7E0C7D714D9B01EE47EB30C8F758F383439AC8EFF38C52D3C15D5AB81C49B8518D1D94A1D7064D100ECAED3C5B1F2B3647BF3D26A0787409A7B65E5A5583BD607C8AD7CD5B1B89CA3731FE328B2F04054E21F54F8C27894836DC10940A6BE60B43D34CB07385A10853687ABAAFB8BD3B704803E7920F9639193459E1815EEAECA36A0DAFAAE555794DC8BB3D2FA1957A817A563BABB2F38BC3DD76F32F3C0A7A72B58CE31ED38B477143632F82CBB47472C47D4D68DDE0C5E1C55B2A52109360DA85048E924FD1D1DD4F952B31E13D14E47FCD37BAE0075F1288DB9AE416FF5D319D34E6217A8740BB9B4F0A1EA8A9EDEB2E11A3B88558E718D0B837EFA0BD4E0CBA1B4FC5C1D975EBE03260B8220F27DB730E4A4659C342A95048090F11FD332C98728C12297954FF5A3F99BE88A438F2A26D406320C3C403C24443F08E36C7CCAB1E4139463AD8501FE6214601932F8F613A6F89FB46AC84D3B29C060BEEDB3D67FA3150668EED38AF17DE71F8E42217542ED21C8F5B86EC5DC71F2C3016E9797E02C9D69D01B8E343A419EF9F9C132E16E0DB7DB186373E20AC7963EE8371F04A7E461F7723648C5AE95C38AC9C37CCE8BC531747D767E2977864E3C8C89556902C44373A01FF4E4724125B399AC766305502B39C50AEBF85549B3181908F618D29E68CF09678D71ECFF416008450FDDBBFF348AAE9554569A88E29D423CE0A958A8F889A1ADFA99E17999BB584F06D4B84DE5345E01A520DF2D375197FDF263AA4C2E659E33BA51BD4006E2BC8DF6DE9AD564EC235288D58AA6159BB4348A19C8AC25F05FC4C8A008B8D7CD1416E69C15253EB83C0A1B854BA4AD2CA8F78FB6A251C0A6190719CAB066F6DFB75609CB560DBECAC7CE0745945341B8B42CB172F0941362FAA067C08818FF6FBA8E9CE44DD94E6D43F123B99E46DB31C719A43035DED8E79254AEC1B46A3C580CF85C97F14D248C856649BE3EEE817ADDE45B27F60E475A3720AE3AD04CFE48E97A1D8F7CC46E46A95EDCA82BBAD0499FE614482C4D64669AA58A9DE8D61A09BAE68648087DD54FB6269567FF64654E3CF93712708BBC15F7E15604C1B2CBD4E5BBA0DCBA08F2E1C640F716C16729BAD42595AC64FB145A4990320AB14FDC5870623C6D075BE6D42BEDBBA83BC659CF38ADCC1CC052D0FE788D2914212467D86FA0403796E362E016F836D35CB0BF115A9DBFEF0B0DAC927969B43FC04AF11979BF0918EC538D853ADCEF8D5122831E4CDC3F5954F89586D36A575152C2F19649F22054D1E775507EA86B1E4D4B8528BE2DA5A2BC6C1E81781899C0F719CDED0549F22912A43F1D9827D3A12BF0EA81A27EDBE8484FAB19C8D610EB504B41532CC87773A6C034802CE679BC7981B996EF5A4DC33E800E2939CFB976CCF980F39448D2B1A526585ACB231782B25E4E4D9CF007FD36281D25F8D2161F5077059D8C7BEF0B68D0D2C655063113DCFBFA8DC555860E5769AA5938C05BA074A8840DA8E48E19D848924616980476180C80DD460D793C3657A67E5693004A43E4DEC0E504709F07E3FAB7DC2233B8E7261EE05CC11454DC69F875EACBF7BF6E52F1C49C1A2DA726A3063A51156C6309D9602E54A05F31C75942788F1EFAD37AA3E86E4F33C7261C616AF0EDAAA3DCBF2A2EE6205E83CAC2652F2BF8DB4F2EE5BA034521FDCACF69851DEC59636869013557DC078E06C7171 +smlen = 6444 +sm = DEC46343C74FDC165FFFBC98C0B3F5B284F9FD4DA5D25E81C237E7A8BE3EA45D7B38591EAC5E6DE86DC4F1459764C52E1EE806591BEEA46BDDFCCD122217D8592C58B9684C29293F77FD73DDD017C665E3FF1EA1A7C13A431A8D0206669207F6574D1EA9BDFB6AB352A0363922B1E88D1BCD2DFEC54EBCE12C7E993220B7274866FA8CC419B1F873A7D7271E8C8FF484FE6BDBBEC0D92A5C9FE80C08AB2C73C06FC947B7EC77EC922BE5EA7D164B231D6C46CF0D81AF454CD4EAE1BA66BF6A5542607613473C20F41D6C1D243B622FC6FEFE720FDEAD0785885279088EA009FC35A4830A1D25102D23FC1260E3B4FE63668C4DF7136B5870BABD52DFE9A0C0B736DB8735FA03FA9A9D5FDD4A53CAF5259C68A74578E316933D3B89D73D2E2B662E1B25E59A2C7F8C0CA3225EFCD1A06AC790AB85BD29D9085D9E6A2109F1CAA43235ECE039C67CF520BF082F0C10D50B3F0D0295A8374EF487BFEDE86D74649613FBF383420243CB81FB355822A3AB206317FDE24353A9A51602915E775C220405CA7BF873FA9619B564C11DA694D4118B006D275516A0C968DDE061494C06CFC954DDBA9D43E6D11DE7C7B3F4B36A60702A2419B4CE8887B27083FC5C6EA4776C9A4CBFB9E622035BA3C7993ABEABA2BE931AEE11FADED95C6B3C70FE873CBB2C5C8C3BB36A4C50BA017BB2ABEC43FDA28AB613B787838FADC703FC97AC5E5E389102AE8024D2E294990AAAFF9CACC355EECB47E505A587CCF0425E5983BF39FE4DDF3327AD3346A29C50507FDACFB0D808BF0A6D1D1E9BD2D3C791CB2902FC57D4FC818FF2079A36DFFEAB9172442EBCA08807C8DA27AD1880576E419D75A5B0C951DED638A4620C9ACCFC5AA881BEA53BF9A4E26769FF5D59960096F81668B4C4B7BF25395E203F4668E4AA4EF6EF254A9B7AA4579EE912BA65C807DB62936D8E62D330D59CADE8FFB325DBD30E4D2BD2EECBAE89F413063D9B7659EBD39B4CC1EDFC4856CD4E117C022B759DB409B1AE23255FE867759D63DCCF418B9EE8BA2AD33156B5F0E58F0740664A05435FBA96B9432D20A9E4C2EB0010E59404532B82A29706C2CB850A546385F6D31D154757698DFD94823DDC84D401CBFBA55AFE0A43F0626EC1E43495BCBCE938942E23CC6B53E8803FE9B21FBF66285B15EF6FB0577A7213ED0D04AB6F864CF8C72C4DBA9296F49D58FD2DD2998E1DCE8BD0B92B4C44FE164E4507B81BDA2DE8DD366489FEBB55AA7F436190B3C448686AD0540DAEB4FA7467062765C3675B0227319AB05CCE3E5F99A3B035770B6FF53D594B0FA404BA4285EEB655B95C9E0D274BEE877D3F5EEE2EDC7D02BA0A2A5355797C72559DA1F98B07151A7EBD2FACCCA8FD5D2B8D88E3404D1E001B8432FF44442E161F71159716BF7E1E7BCF13646A02BAAF3845034E24D5E14E8741F02099DD490CBBE20694BE6797851F3D5C868F69FFA06D5D124EAC84E8DD230D98003F374C40BE2650870D4AB29C1CF50BB619A297A02561C00C1CBB23AF7727E2F915F363B34EF15277D070CB942E167E77BB5ACA8A0436E9777CEBC7CC547ADF7DE4E950317FE121A74953EC09FF6FFBF442E50B756F7E052A2FD23D73F4853DA2B4E4B84924EB85BBD786B4DB323C932348E123A01AC9DD11E302A02B78AB494C9D38B1818DB5B636EFECDAFC12C3B5DCAC327426FE2FED9CB946148A3A770A753DF06B2723D7B9AFCCD15A66C463B633D46970267C929A0532565DB59424B921721705ED03FB5D0A181A22D23BF0E227428E2B26993F9ADAF37B72AC49EC61D19AAD77484198AF72FE9004E514A07804996E2D040AD82CF8BB7EAA9D47C74987A346CC889536911296F233AECF00EACED7F70751DE7DFBFC9CE08C3F38B6A728D319A589536DBF779E807CA3F3CD4D9E220193528EE4D37C674F1E0BE819FF85313DDE866D56B7BEE076AE88DF00DCB7E86A91F90A79EF2DE0E560DBA0BE17A3719F07FD88867F399FBCE894770FD632E38B466A81274BCE3227EB5CAC4044B72659F57E1E802F0E8D41206F6C8C67A75374B1351F8CBF9BCA66B5F4CF7AAA972A31EEBF3D5759C01067B9BC44978848125D306C0410D3946CCAB4EF612A5864D86C97199123208005D6CB7AC5D9C2D12060B14649E5112806104EE58CD885EFE1FBEEA91EA5B52D5D8BA33901C20874445065006C87C0B66B25B358CE9C8112471251F6717A66D5C5C135B55A28EAF1FA55A1A5180D2FE7D7C2173E81B6B2C5AD7330E09A35029D540666085CC5F4E0B2DFF6ACC5981C870FC5D643A9B036924C6FF238D0872215E4578250EDB2DED461A88F12580D29C0A06B7A8DD6344BE1F3FCB6EB9D88CC6D34DDD8CA6553A21526CD7629CC585B5102F61D2C12AE1A35B32A2FE1A6794D8D82043CA1C9510B79A31EEBF6DD0FBAA1F3DA119425EED723E88B1CE73FCAF6ECD33F6F3FFA8856B701991EE751C9FB824CE1B8FE361898E94B517DA04375AD692136F7745E98B79FA1CB51F6FB4A666D53991E710EEBD4745C693A9724D73C376160C84ED49FA1B69BADE2A288CB529FF53CA30CB99171E128588E46F34BF86B598B0B29E854CFFB20DB53266E513068081A5F40AFF52F06B52FF88401A66E2C62A2E12DBB34853519DFD93C95DFE31DA8FA0E3B6F99B57A44D10BE0BF4C249F8BF23AF9AEE4024BA7AC2007FCC2045F335734D2599459FCDCF3D3E6F7C0DDD8417B9ABC0212B817F196B57FF7B2F8D73BE0E79C0D52E333F86A350E4963B7F2C449AE6CE185734ECA234A15AFDC0B0647F71F5FA9E5D0B82CE7B9A07C3026A9F3B936B3DB5BCB684D5BA55B87D76B091D6B8B73FA2BC0B373B366BDEBE6F4228D5BCCB47EC1E50857EC8E605E32C72E817828B533C382301DAE4DA052F41D134680EF0BB16EE2EE576A2F495A8C9287155462A12D53AEB77E16A2991EC863603634D4A0C22C582C23828C26A81F70ED6B9C771EDE33543C788F9562B7D42BC009DE0A17D7672CA636A75E292F0751745015BBE545A683C272FD72F0B486331D9F60159847CF83C33B1CD4D1E84D996A034DD7B5129EDACEAE91C899F6495AA4FAE54B291409E28A2E40923907F29F5FF5ECA76BD4A250F7065A9BB037A5B96A6C103A3783E5B58E15C5EF91884D9DC917F855CEDA0DF9A3C2DAB4D16C3A8FA400746CF69A35CC3C2E0232B2B787F518E08CDB50AFA2A41D44628E3B43691410618EFFA6B45FA9F7185D5373528A95DE97CB5862CB432244CF38448DF21D18F5EABA7C414BCBAEF40907FBD84580EB75261661120C0FB6E49476DD6ADCA95EC8BE831486475FD0B21E3AD7BE2E950F4865E582AD8ADD3AAEC129809C831518997AC5BA29E43014DD8A6C7438B89789716D73387936BD7DEA478B0D92260DB6E727419F9775E2E7B92478413D517EA1E6F52F185B0B4D2A4E59DD216949CB049374A5860D61E283ED95635093CC92D60DC8998F27BEEF8808732062EC0EFFFC77E8F75EDB4F03979175281FB7B1300ECB2E34497B46A352CA0153EB5B46FF5C7928A3EC9BE314AA1D498845D51CEAC99A1B464C7C553633383340B558FB9BBFF66BBB1D96BB8EA6B75E9DD2493A2ED94225B034629716381F0EFDB79ED173A1B4B49A38210AB5A6814E4297316C9A69F41CDE4FAEBFDEF07E1E97F8627E58B675CD5CB51F6B2B2A728BD5CB775256E2ABE6A3FFF62BE59561B518C9CD9837288CA222F0D9C2014ED34D6D517BE0ECBDE6DF201F058B940681F887E91BED24F74108B0101FB57C5BE1F43DDD3A3FB9200892873C43FEDC7A3AFDB30539EF8A7A6B9051E7A7A1E53391B04C21605F3B63397AA5FDA93F7E319FB7446039E3A2950546D848B7A28FD1B380EF8F8DFDC2520D7DB5F5E785522C67B5FCA7883E6C7070D6FFFDDBE3D2A85990BB98D6AA388C0ECB08E03CEE3E891FA0A498CB7512F83FC37140CD42E9818070F6639D2DAFC637B9E9BDF7881D65D5AD004D2F685B504B3F351E2603ACCF2D20E6E577C2414F477E79771437D35CB816DB14821F40369992EBAC025CF1F50D00BBDCE7BD039BB40AED890AA7507D3E4F352658512999117FABCB74FFCC58C45B0B4AFBD38B787619A33C7A06518A0B11BF956ACC24AED5AB32060750278D28ABD4DA6057779373AAB77CE81C1D89D1627735FD86E15FDBAFC69C6D786CF4666C783569D244ED137A7C1784704C6EA616FCF188F83AB8BA032947869FE5DC6A0ACBF481C9D460613DF41C8872225019B1ED05AEBDB98D9CC0EE0CD3C4B053077D48CF39828F88998535B1756F4A26A28FEAC338A07926F40FA311E1A45B2333C13491F999C93752EF9794C5263696E6CF31504179D4B7AC5D4B9C908E52529FC841F98A99C78BD6FBBCFFD89CF7A8B789E54DA2260C81C4ED71CD4C0C37814D1325DA152A768C4F52C27FBAA62B18C043F8F9205414D4606073D38C26935A44180550130655ED209E0EAFCAEC786D52D61E8FDA000AEF12017158B92C549F19FCB2EDB950A02B070994FF3086D71303CE44F0B2D3A2D43DC68A6153DC46399882D658DE0263A3B38210CEAFED204ADB6FE4EDBA37315BCA3EBE756A13271717ECB90109388C982C6E809AB9C7C81C356B3671A4CAF34756607F8B99BECAD16888000000000000000000000000000000000000000000000000050C0F141D1FE13692E3CC06EBE8FF9A292D890F0A34DFE9A4F968F196B475AC4DF553A30E2FD5DF008DF4D7508302AAF6389B6A5A9135E9BC8A5ACCD2BD2DF98FF662B763101D31E24E8F182FA50840BE27F76BA5ED645BB4D3F7F2F6CE25179A47FD7B6441A9B3A28783CEEDB425B2912734A75D7D03811172188253BD8F0F52EAEE84A9FB025F95EA1B566C53297A6A090F7FD8B21639523E073ADAA750D63DA61631F933FEDFFB2819E0EB3074E9E11E10B102AC88E2C8D6CF408FD241AD301F9B8E18A88B74CB4B0DAC76347635DFBB3EECFDF84229BABCC003C6E4EFB7394E25667DD7FA47D36E027559F53E98789E6E732E6AA23A71607677FB975C2852367C5BA5E3D10B3017AD26F9A38CE803929D08A43646FFBC3980B359D8BC2E9615636D4E5DE8DE6FB2465A983EB1696E98DD33FAEB7AF8C2D30506B22390D7F9FC21C7A016FDF22D21ED2EA4175FE9F5F44598EC26452700DC9A495675431E1236865F2F4AA5BC9C9A10EEE9E29B1FC4FEFCF8F24BF94342FC7E19AA6534C3B771D910AA419EA2BF70E2C1915891CC630A3397551E4F34BD2192B70EB210EA67CF152A35A3F5D0878E153579B42AFAFE5068B2BE2B48127FFB54553B7A9B6F845E7D72C43938AE42BC03E33B836AB212909510AAE7DBE8EE6D0EB8AD84D60832F3151273A1E09C514C3AA4CACD15564643F4255F36059022B91BA4137ECD97B34BE3308D40EF06BCF4F45EC625B54C7347F52A21815508199C8B7A6212779CD171894DA9FC3DE2A6EF5D76BFE03B8199ED1DC92B2A403E4DA009CBC0FB597C5952BE32579EB8E781EB12D935848C051029C528CBB68CBC1DE0102B42561E21F48E72E028C2CD8816A9027914571B49D2F94C9189E1A7F18D7D3D0A09B3A36EDB8A084ACE5FCCC77E3E42EDA0FBAB8C81EAF170103CA757981839C9448362BCAAAA3F20C8DC653AEF36953559F3597E1915F02A8D33D0E46201FC794EE055E6D9955B91FC7ABA1F136C280367404725CB355FC2F129413581401F98236D2A6F8BED7FDD7EA99060DABE3F0E8CE20B0E98EA80994D1673E8CCC6A0BA4A9D544F3D31BD95C9D3847527A978C1F155EFD84B6A7BECFB749628CE82E80285FC7272EA05F953404E437AD557F38FD9BBF77A69B81E4441605B23F2AAEDB00C7519D8E9CB4CAE5F8C3FA74FAABF6C12595BA045F647ABA7168C65C8A6006733D1341435495C7088C3361B50C43787EC24C24F57323466B5C088E8097B44666453010DA38AD65B426E72140AF78A5448B2F93DF3820F013FB9DCAC49604C86F2B2E4EA565463917285F148E8BFA9E11943AD3B86B14ED59A190CAE097DB26DAF8FD2A642676A37DD90C23B52C82CE028B80A805D9BA05457F7B6CBAECBA4094822E16C14D6E2291B731D581B12FB16802653360AAA6A7989D61C80DEBFCCE81A36D9ECC84039C4F086A5579D36FF5D0CBE61292E4FC3D14277AF380A9C1DBF36C2D61F59CFC0D62524E042710BFF5BA719E56BA367FFE849D660B9F7F3B638E113BF2E1A4DB1B8F65A0FD680BB2A168A4FD5B4E0EDF3208AD47F1FF4AFBAA726E38763CB5C84C03DA3D1E32CBA873B9A0C750922CD3D0A10A4877EAFEF602F5C875FBF0EE2F4F0AF7F308EF934F7E8E74FDA62A860BB594FD061D1B2BB32BA613339042FD90E749ACEF450D204072ACF58B18C365E4F4B815F1E837453C4255D53BB68D50F3677E7173FCC23D2B592149A9F3DD615868AF91F705387547862D34553FD45B8DF643F596DFDB7ABA47BD5D91445826C86FD4D30365A2F9A3CC0913DE19707D072F27A09EAB906304008875B5BE3526210D6B8BC8663975A1F78EAB9CD7F7305CDD4C00D6277622E50606E1CADD639730101D088BC2BAB295AD86BA8E26F5EBCB3E9C7C543E533A7B3C20F0F89001775F714825DC8547BAB06F5B99C5305EF18372A184569323FE269D45B669B9A222C9DEFBB0B2C84F42A57EF343A5C12F5712EEC33985DF8F0C566D471A9403FC103A3EEED42829D8E3E5C517BDE29447841CE96C8AC587DF3E4B6227FAB386140DB0112ED0D2846355C4A45E94F3A0718CEEC13FD3CAAEEFDF0B7F89F502AACF8C9D96D01B5549157B7DF2BE65BC30C889E69971700286C561DF91C8CB923001E5F0E21D2C7A3DFE8D1AF07FECE1EDA20C031B29A4389F265D2C7BE64EC37B2884849EF30FC8A82D2F766ACE68C72F0A4B72F3B50884749814387893DB2370A3410F794C64CD24BF0D13E44AD500BA9816F9BAED72F7593F758592C2E974D1207A664B869130BAA1FA71DBC55875134E7CFA276E36568F79483886099A1070C14C6E4EB87523E04C0154A2250624261211723453CFAD185298DE06D08CC25FA18BC58B34ECDF5D9DBB02541BAB4A2AF110AE09130E12439F1CECC34F9AB5D7BE36C827A6F2F6708B543D4AD2E424805E2A74895742B0A5DA30CABE4AB45F40CBFCCBEEBDAB9B8EB8F78781168B5BC79E04EFFE1757AB0547B9BD0D2625673CE528D2B4874D46DF0E09C24FC413EF9AB4C3D2E803C1E316D77FF5DE3368BB925B2B1F6FFC340525663931F5595C8AAAF9FB0DCCDFA4793519A66D4FDE38BD2044C60FD1DE15D60BA878FDA570E7AEF6DB69D2527A1F1481A9D05FF2F6F621238939ACF5D2C37B2BC3A194A9E65E7441764A5EE37B1FEF3B8C9C425BE1B5FF0D05BCB6A3B91876EC04ED89A31749FD443C2B85F8F388E7070D77DEE37E2B666628CC9A961236DD24AF2769C1F613B4E77F8E82D1F410ED59F63F1DF19BC53A448106DE4F8EFB8CC37E40144B0F658A4135E25A3CF36D8692DEF2677E4BEA3A9770F19E44D55080625421D5BADEBEF3B39BE71C08650B5718A9B2FCEFC4BECB26C4B63C43F6557DD66517D103907F82F9C2B965B7C5E36059D2159183F5ACB8B5FF5E6B92E94D53AB25AE955424E80EDEC4650BE293E836DA6148392C500FF4B7672932E90E068569B81AE335B2E5013CCC95F571948D58127EB1269A08D6E897D2D9B60F3E49847C05D0B3AC230A67EB6D38FFDBD4B8D82D7B9EC803429C701F080BE86FAA165C0111131712DB4957FD84A8936AB55558C69D33D5890CADD08D7F0D4962CF9E2F69C7517E79DB14B76E6E188F5ED95169A2A7E4C0EBC2175EC2DD44ABCF239CEB3E22F955ED25DA41768CA5FD9A9AE15FAAAFEB431958A679249AB8BF879185E8FBF9986B96A92972153B4CD0D1BE001E5AFAE3AD1F0B1191F1483738E728D4AD240538E5EF7BC9BA4D5903929D74CB64241306FDBAAAE17B1C3134AED2CC394D3EF9653CC62A29C4B0B9BE04E95E072EC98F7A80A7B575DED4A1993AA884C1EDFFE056EC475D934B4EB0EBF418975728C6E9CB3919B2B67D2C71228A4DF1FE2C8388E3A2BDD75549417FE795F1947F857B1C0C9CA021515FD4D79E691493B988080943C394BF29E4190082A94F224AFDE5853323EA51C06B41547EEC0DA5CC202A048D77C7B91E794C51E72B02EA7C14578C11D9DF48E099465783E496029EBB6D42D9CAA52902A4694355DB01DD7F5D7C113AE06E3F712FA577E937CD4FB817659F93964E194FE7D509A81C258C69C3415A8F11D35B414339FD1CC1D4F50665D9111592D1C3A3D69FCF6A971C285A94F5FFBFE8D2FD2746DCEB3B218D970D670D10135126E479D92000D41EABDEEA4C04D1748A4908DD39C60A52AA5FE29C8ACED50DC1295B5C2C4A98E3C62EE4F370F4D3E500FE27B66F65BAE604FD558D66B7F09CE36C36C8B5B4FED193EF56D1D8DF0FE6FE0031466A1C633203966FE83D6BFF843657DC0AF176AA8D5CB7312CB4E072BCFF24D5F3828E29B2037E8D1FB63537C70C27011E9A97E3F04895F4E84AC69C55D450B46D5792A5D790557BE64F765FA243AFA98527B976783E7ACDF76A7E1DCBDA72431FC30D7B05197478D8D74077626FF7409F95B24A1F1BB6B803B9F1B9AD5B06883FAE6C4B587C309A63F3B2FC9619032157B98C1DA9608107E87F4FEE0DAE995AB86AC9869446CDE92441F0B9F8240E6F7F7AA9189D92B7FAA3280FA749BA8C7729F8974049C5CBCB8C6650CF1C16B8194C7AE1A82B40B8B04488FCC69E674362FE4821D4C1846CD9BC49234BCC464013F5F9A082FB83D63098C331D4B1C9129F52259CCAF4A9237F8EC5BCCF06F230C08DDAF1D0C21C5930F55D3D5F60CBFC447E7FCBC75CD199733F8D17BD043B67B0C138CB0C9C8F2E477728F27DEE573796F71B013689B537AEAD4991E67F2F5EB94BFAD9509D7C235C9E55F68F26B9CE8AA90834D170F8B700A40AE9A817D5D17B1644D25BCF1172A5CF0C755A6EC04FAFC39DB06AAA05F5988E187B9E110EEDEA9C84B99AD29A4B31950F2C870A1F91DAA6A5817FAEAE516FA42660FCF56000F7365D8C6CC11D4784C6FC02E4D0C727806E9D43B957BBA124C980C31F81FACC6D46F6C38D227EEF8F0 + +count = 95 +seed = 2489C04BA57D149A60F446670C13C29998B52F3BAD548A751D7134B694DB25ABFA034FB4BA45E105AE27D575CBD02B99 +mlen = 3168 +msg = 1F7AB96E8C14D1A5094672D7034FA8F81703A2CC18983C972CC66736CD98B031AC8A479CED21A1F634938DF85F3E83161646DB81B9AC3EA22F80980B8E2EBA4E9975714E5A98985817F426C41F3968349686B69AF917564A2648401B8FA127FC3200DC16A9E663D1D345EA83131E21229DD39E70D7270DE7577A7E9635602FD2C30EFAF204A9234F0A73D21375658B0B0B04927E67F3F5534614EDF5137BADFED914A49AA301000092DA93B3FA4A0FF592CC3A53F4A75B54FEE775EFA421EEFCD6E0D32FB5CDC096886076DA940B26C6E07F12F6E08FA7B3E2DC42055308E5607A2732717AE592A6909C6E084252A5B08685FE8C6C1DA387B0AA9800B67CDB3EE2FB21B9BE5E6B79AB545563068441C0C9C1E68CEF6028A5CEDF27D3CA47D95094C9E1E68B8449758BE3FF8FDE148ABC420295DC76E3EBA8E11433217FDC3136551A5A41C1C7E7D6EF43601946897FDA54842D8F73FAA7EB7ED0DE544FEF2A95C6FECB13C8C0F14B5B22493F54374184B73D5BD47383BBC5DD7BC1BEAC0CB8E66D2F413A9DCEB7E1D0EE2D63B9EB28DB232C33A95B792AE67D2591F5AF59DDC45771A0E7195C4D25E7F4079359597678B0C0A87DF3D66A686A9215DD566D4722C212AD05A23E1377E37E18A6AB3AB8BF5CD47BF1BAF06EB05E4C150CA67D7E52BD297A08CFC97B575752E686B83575F425F3A450BB0F596A60E41F7183F463007FD019EE255BDEF1D98B7A0A12EC33B3E2BC9BF0CC8F4860DEBCFBBD5E40B2ADC2CD10EC35A341BE7A49F8D204FDAE86921B7DE5BA700A61E2B041A8EA7040ACEE844892E5CF025FFEC5322FF6D765BFF1107C967A12ECCB0489F64F8C13BD7057DF76485446641AA7A560C7E73008C46572628E1A225A8D3F6D68DDC9759A952FC07CD43DE4434BD3391089E900275E9EBC92563AC1403BB7DFDD182092130E3E6AEB7B666F4BA66C38BBE1F726F40A07DF6C42079A6054399519E26D765CA065F4DDFD27A29CBA292699CD826FA9D3E7EE31B0D76813879DB5EC5C7F454095DC3BD27323DABD2DFF949AC760D6137334507816330FA67D886021661ADC69AEBD882A07E01B4B6E5492399ECDEA99222EE785C810B30409DFAF2A3CE5A05D699C2368249C9588D86FEAA778B4860D6DD442088A21D2D9D0B49B15EC579776812AF8AD582F1C44BB6432D7472300B5440A382ED87AB64B20373A0ABDBCE391D0BFFC9C543EC686449FCA9D04B7141836A416720BDFF250A06D7651A1F98EABE4B340B2303591D0847AED6FFE423B6DD8C0C03459C381DB506F531343F82C116323899DF1E5D8DB8997BEC12EB70103F0BF2B3D53C4D4694052606EE32BE4F5B35450358D7D85062DCF7F0BDB51364700BAF92CD6ACE4E2C10E6CD9A332716F5F4BF7598466A99238357798A499C9B8BE77690635C57E7D87A904B3F2278C0B1B23E5860B0532F152E1626C86FD855F656B5D070BC81CE4634A87C8EA6D6A433C02DD2E6D6561B25968B149A6F3BBA40B749F188B84314B5778A000CAE91A53D59860EE6F7DF38CA0935CD64C08A34BF19981C17951B9C39A847D0637441452E38CE5E1D9B99BED51B86705CEBB8D3244C40BB8D70F846936A2BE29C21604A7E6BD3E655022B929954F6C9A5743F5FC2127B49956D80128DD582CEAA06FC174813E5F5E6A0A4D7D26756FB28A6588E9410722591CCE2A6C6ED0976B98E1FB0C642D5DF8F08E96BAE1FE10375FA1D7C70806101570FEF1EBC8F58664281E2B61DF2081B655013AEF54616308504F5F4A1E8F156680163489D3FE7BB0A514F1D2D57EE6302853D7D03C767C7BDFB79E2B8C80403F26F6EDBDD6A890A0A0B9B76D334E0F729FF9C47BFE960A1C3FAF77E81B9AC156367423DBB4D766A1F3B1E67595EFFD76287F22BC37DA4F0204633E804002EB7C1AD0836FA4D01E2FCDEAB8457DFC3D8B7F1151BEF3574F8F4653AA3780003787B8891901ABC8250A974C15F2DDDF9E1BE6798647EED710D06CC3FB4C276BFFA585680FC632D8EFD1614745BC3C72B82C53FEAE935EA5014E2B321F69BADF570FAD878C9590FD20FB7BF1B31E373DA93D1A8C63EA45E698CE060FE70ABA0FA84F37E836F2AD2998F07101D3FC7CA2B08B1398E1687ED5A8CE860EF9B4889FF436B74D13281D1F6A7EDF1DBE8989BFAEEFE6A475E65217643E757006871E664099F5B3846553603CD9EEF8FC195807361FBFDEB8DEE6A0B79F009C10DF397FFB865F4EBD0473D458D553358029C6B5A95D6FFEE9B645311D10A8F479B7E5249AA87E3DED08311B4DDF3A458FE61AE294A22643861826ACBBC9B0EA8B73157CE15D1FF35098AE67159B07CA7499398C26776DD9884B5D3786C87D48E864D8BBE2B73E2890F217E135BFDFC4DC5E805D9CEFEF5268E33DB611ABA6A5D57EC82B7246A63DCF3EAF3A51CF503D65C206D2362421DE774158AEAFFEE45A6B5AD5CC0B1DE0E2EA74E97913729A69E9C00A309DDCEB7738BAF4757EA9CC96E055BBDF692B12D8B01B92CE5ECF3D52187402CB7FD961A2672DC1875B6EA22AD7F5F42B1B52BA2D780F2E6C5B25FC7E30B1B663E3A09C8FF0B5C302E0E7F984DDCC62DDA65FD996E17DA72F02A16C354BBDAD44C5B5044759BD53789B98BC58CC25FCDF10A9CBBF0FD6ABD58A4CEDD92C5D85EF22B3C5EE5D9440CE42995517D2F7352CE997F51A36B9FA5703B4C6491AD01F406FD1B5BF85321026D28B51354DADEDF057B37743499A986469F908A01F3C1B74DEF5D8E2F57ED25A80720B540333109A0A65E7984B557F65429F3D3BD7EC3732A10D7AF36DD5D2414A09949A0F57F37BD9021D2C482E61437CC15E9DFDD92D4C212C4FC6C22C54591E5AFD48210FDC88040135E433F50E45874E0D5EE2BBC857F2C80E2FA4FC7ACFEC8EEC0CAB351F677C790787C715945C21BF923EDC0A58878AE09ACF5FB5A003C9C0B6E30A450CE6DAD4B626108B88E89F1E6A7BB3843E1EC8AEE35AF69E81773CFF71190F819CCF24142D60AC51B80B61019EC7ED2EFB6C5F18B499FC9727BED2E3324F8B94A522092E0A98241E29F8F14C6561DF3FEA0824F9CB0FE10BB497E427EE62085E7AABB2900FA47BF27C1638BD116C5555C076DEEFE9754E8ED333D72CE9423E27EF640FD5199C0CAFBCF2DA1C5C34121A69E7E0DEB3C268FE60C6797056383DA43E6F472D225116F63124498271D3D43AADCC5871F2349CE040BE068D72EB57B7827A7D9AA01405BA0AB07E684B91EF05418948F6713AEF1F4948399E0E6130740CAE3E481A6366295422BE3EE2E892AA9FEE86A6E23E2EBCBE654989FD93D1C4E7D62910E1223BD66B7C54F8DD7D373986E5D4141BF0BDE98DD13AAB7D598D698660F11FA4BFB0AD09D5C27B65386C8673E6C4AE9E8E30F8DD1A5A3FE557A3C29DCF99A7C376200AB595C49445E740E3DAEC07BC047FD6EA4FC6CFDC23D7449F9D1170FE635CA36D3DE5B57F1CFB182DE240CD4C1E480600C449D1A8596D8315906A53954201929E7665DD2E27D590D481DD394CF2E8AE19217F1FF0CB511DEF7460DC9E49C21607247857BA744B1384344B4C2D8CE987512376F66F1A279509281242A7A2A58ED500395418138ABDB9C5572A258D157F4D3E88ED216BBE9CEE3BD054FE61F94C59A4AD19AA62E456B86CADE61622A6FEA877575EEAEA20C76AE8A89E7B44396BAE0EEEAB1C23F221A3DF2B2CC683256A4E5C8207EDA0B235562AD3B510F9D3FBE0B51CD8F238A0ABD2EC182681606C8FD111D8CE1EC1CDA6DB4572303DDEB925AC1FFFD75E321468266790DEE6BC0E85070CEE749D9E46795936324DD1388E1B11AA617500534B8DAF2DE12B035F73111B770F5F56F5C6A4152C45CE0E112E650FAA9F3C7E59E3410745C29FA59CAE5CC37FE4C6594990E50DF1576B69B2B292AFC58A804743F49DD7C98C1768FD19AB4213AE4FB197492AF5BF7FBC6C8B507673539D8515DD527FAFDD8CA3EFF629CAA720AA11E65922678447AD4DDF5FF943873DF5203AFEA4130CA5F633E104AB083EC690CF092D208A98006E91BC7E33731D18E592869E564E6D3FF8BBBBB9837FFC1F1B92DE0F5DD4A029C51E3F64592CAC3DE1B4CA5414F894B7B0B7D73D6BF1DA4B908ACEAB47771DA56A8B0536301FC5FD270CAA55CE171332F7DB2EB4619C4B2C1971EBC0AB8B0B11FD54C24285DA8428AB9E0150D8897216B133ED554DE8CEE532024DF8B8D9314D7C9A3EC60464F9C7BCA8C3D4FBA23A7B543AC111ABA8C8F1BD54A243D565DC062F84CCCEDB0A03375FDFBCEF8AD8CAFC440D3E6F988DC607ECB947673DEC4AD48724C91A6BE22A0027E42AF6D94D26D188D0B7B3A5AF012880FC0105DD2F11171742321DD41A0401415C58AD4DC445642A2CBB466788F54D270BD8DF25602B298B62B6D0FA3ADA97008A99B73A807092F8957F17EEAD9D53B1128FBEF1DEFCBC607EA92AFBD353E95F52D33AB7C1EBE2 +pk = A7F3412319B06D3511FDDD81EB9C479E1C6CA8E33ACDF53964BE7957CB853D9F6E197ED19219F9D051D470F8706D8C52E215A81B30389879F94BAF652C87B23648AB559C9CFF83806E2CE8E8DA1A66D3F0BE547C01F35E594CD86530E4CA47F0E03D9B4A36E082FD3D1BA24309A29BDCC56C5E5A39DECDE34962C5F6C7E88E5F3E456895BE3162B62D088038E7A22BE83845CED7DB2E3F52D6B2569D915BB6431CE7F7481A13A87B7FEFB9C3055EF4A462C1070FFC1A6A87662EA05374E0BB39BC3DE81213964DE17B1CF2BEC5E4D77F98B7A494C7028CDA69C149583C79F28BED92BC3D9E52ADACB82E931526E5053338B4166970A3DDC9340DD0E4DC84009767D63057C57D31A1217368668AD2D2F918D3CB6C754CF69B7A659326D7B0C0D086D2E43E65BC0CBA1157B78152DE1C8A0BC3960511579B76722ECB3F2AF149792336D5FE4880208CA912645F5E9120D37C381F28628A03EBC39D414EE892EE8BCE2C9192E2E8FA3C197CCB30E9875A7CF69EE5DC2087D5911848AA4497743A4E94F03CD2D8B242512477567D0679337B3AA6E1AB44FB15CCFCF413F95FCA6E82306376446F10DD7F67A5FC88E4A1CD8E9D26693734D3C84C2261EB538DFFACFD23BB00E38BDCAB4D9C2DD61D8EC91175546D3DA250A391C24EBE48AF84D653F6C706E592C2A8C5FAD8BBDCF0B0D256FA807D3C0DAB73424470BD14CA26A1E6591E3B7EEBA65243BDB2B9B5E08EC0B768B23371CBB67A8A5D3673DAB71776989CCA823A4ED3593D76992848D54162D8EF52A0484D7A2AA6C5FA8AB45DADF72B7E3E5F5DCF0377AAD46C26F1CE00F0ED62BA83C6A08B7B5675A2921E81C96EC06098BAA81EA93D1AC71B96802DB79CE14C8DA72CA4E90A51774E7F534755D50B05974A9B5CE9E0F8E14F129EC49905534F4A8641368DF8D2E237E30BD7593DE165875462A87F22EA0102F8FEF624FDCA74E76AA485AC2C304F65F88BD282A718C7F31D12D82660CBC08F6AF7ED18A721CFEC3AD341EBE6D8CB9241A5A4400838BF0EC55604BD241EBB5DE37AEC15D753A69338506770F7B3B311ED4C07E8C4E3AA8AFBABFA46DB4A179268F0B792B5A408A0E54C7B7243C7980F6E0EF195D83AEF2D85CCDC037340F22850967BBF42F7D59F50542DD5C469EB4C4B2332B9DFDE7DBDC882F06CE02B0155439A3BDC9593BFF47291883BA1D26DE13222B4C65E24F157C594F8159D8DBA4FB6D527AF797BB2F884E68E53ACF481DE420E4F5B1FDF7849314E34063E9FB0FDCAB2BB1F81B5CADDA4F2DA1B0D92DD673CAD37AA9B98E84C96A0C2A8A02D117941443B4CA3769505389A31D80712CE4BDE2529D07451CC20BFCBBBFCC728F9B7FCAAB928EA1A287B213785CF6F731AA7F2A5843FC4067750F29503EB104B1572F85E9029E888AD0868F1F44D84A057B4682CD97D19083703CA56CC733BE8CA8816613B875FEFA96716157B2DA4CA6D838338AC6F99ACD54DE5F771F130D9DFA0A0025772B9AEC7C8B663E4F4FDA7870E5081581565C9C29AA921B83FD0F68DFC1D511EF3AD6F5995A8D0215461D5A1B0A9F3CCEBF7660E54283A1B1079C387228EBA3C3DEFDFF2E7648C7E5FC5B755AAB1E2748E31E9959C0839706092748A75D4E3074E21EB9D4F726746FEBEFCB9D8CADEB999C84A1589F5ECFEE52C6E541A28EED829723563EE63BD9E9164833AE8623224596D85183A5CA759ECCC41433360D33B84287AFBA8E50159066EBBB68D42F6B31751B38C10355F6C5F0CD3C848FB2C9992975EF3209D38FA6371B4FCEA5AF0A38FCA8C5978B58B9034EB857844F43463DF0156179179C7C209CA1F436E8B0C7ED23D0D6EAF42F5587DBFFF9AF2BC048F67A759F49C5CD8DC99582F394353CE0B08F1326A46253F144D2A8F15CAB10F139C013FDAD0ED80BB040C0E20BEFF68711D2529A9BA848937A87677B13FEEAC826ED80E24656A0A903B6943B5DE54B1AE7DD24C9B1EEE1A22DB5D2BFC43D9646B87240DF8CAB7B74B6823CB6E0888586A958D9F156B2FF621E8174ED65FB60D8A7C14E094C960DCD23404D875C41B9B6F2651725C495B6058104134B3A6F668181CE4570B7A9A4988E38BA5046412C749DE28E168C7B23F18596DAF76D0312A014351009E2B6BC6E88DD57D6C2773C317BA7CFA9A42339A056F68B13AF483BB31B1B32C1FDB9D6420F6769122A49F6EC2E8AE9674BAE0F3309E64F2EF674804AFBF9A8C6452DABB84710B06F2C5BE9F7A9FBA617E4B76C55CD6F01B7F1C8325528A23D3EA6D3C318CB45675B898F42E3903CB24F6CC9C167FFD4DEE8114D8C3E2B6B518DC84D4CE1A4D17042415A0512E5D4B55643ABCF631F8963760C1536B0B675893D409F7B54A98D2ED4178489194117CA1E680BF4DC58B899D73664AFC00D1918F6AB294281FD9C9E30AD2586423D367FC47975BB58D6FF524ADF23A6EC1A2A7896754ECEBFCF007D028A6E93DC76DE8D02CD4B646D8CA8BB76FDFA6DE6742337DD77D11A03520FF916B55495CC615130DF44741F5C6EC1762D2A11B2FB7553EF6B7A6463D07E0D4C0B25B751399993571331AFB73FD1E60B7A91920C475BDEF3DA8103E117FF41D1189350BEA75F75099D3FB4CA64DD13F4E6A8B78093CDB092EEE3C3D282C080CE1CB3DB24E3CEDE3ED69787B0A51A451CFC5B5E61B298D9D088A33ED1B1EB622A27AA3862D5EF941DDF4A82CA1216F09EA1C586FFACB6D4538882E27DDB7780AAB53A0B7437A17AFF41F +sk = A7F3412319B06D3511FDDD81EB9C479E1C6CA8E33ACDF53964BE7957CB853D9F5FBE5C733917D5424198450FBACBDF1A36C6943ED646F87A8E8356C55488ACC88D7CFE0F68F364B1F4950A403429DE62AF9710298D1B855D3E87287E3334BF0D8C222DFBD8932180C6CDB05FDC7BCC94C4ADD1259FAEDD88A53B4BE4A71BEBCF83488416074431478678006532708304883401512236323508825780488728575817667332570884471253161768313544585614573547268708115662872214318538105552543701423106644617767045758764770551004164105818153742757077541244637732685137080505338622402381646473460156377827675874662031335651126877764208751072261747868726360457584668721067042675510507034484055526050341478635125513512444108232241558640441812360323550241765662436302554463734572475500682427124033112821386617550401362341417017265820836806206260763603856642035115741280026386500561487210542668873236663313640003574001561627252144870661320256611783735577040374407475338374147768428865107571647863776464066403085238724276072445002211284271871206115037186353425486872608252651257484321866156060181178180406672627231085340623040366262712805710860545702634857741033838601667037363654173353182783016218111301515540115311768426857844373507558253201555052163481512372164237300742768773844130251865853074283431867586451757881418453548068480803756257401876557253116155136413541610546752272010771262753421447013630576287460280542270673488142760570106844666383706171287325103871288634840311408018302853073126277327587486064331401412576208125516663101500543650180627110084435871054831166262480744850813107074131201683808463410467835676077354000240387700788448441447116823674500476058237625854711474676333525285876215108024527455465430332885777481377750856407144383632427650361578748328604436842255334501644657317431585370465377517080684813401708435002788528252311051888117834415137387785148075082711686161145185418776532442803550650001833564703516458536723745632008784556060736403805157668000640825462275350855556152152730588508126583503312371711423103420275563842051513307057818686002051785103710146440456772513043013646347448416241373646147362046745066401823226535625478638472562881764332031211015301268537674236107466372426506111001515823204724155578481805376410707413303063615001376883767464810076850016687718865161143375045804264088808015325832084161130362042541482071217365773663563344875332303134245250547076663207826768210711476320582555472447264086458741053205634516663785354288307355414036150675762133577480485373755242715155240470235040715556808221126773455020886771760300608883680720146335063817212715880403412782708483603453200563515247453448021037076208882376758412586650671877482801722343124440156684082135386081503637623001562211888456355037828272324584711265054711123258632372166205005850185550367864183837667344385531004787786546743146527286515281476628241231141630585111354644065068848635582150637130542436206160330556185210382465706121157421652625056506673511567054663853710206047344842240404347086881152872387752626320550276521523474004820770521226101373515466250077385420606555736523555570313226526115601417421153830524180513635372484800558047460037805637283410DA92F99B78E942BE29C65190EC108922E9F7C4A23E47A5C233ECF8769E6E6CC099F393C9163452F801D4AC3D840F1BFE493C300D3041CB9698B47CBE1E4C4E8BD2F8274900F1671AFB750F3263913D3EF74E359A3D4A6BE57308466DD979416DF4096E69CAF27C492500FFB6F6314E6283C34CC1B1A7E5E6ED56F7504E07AFA3434BF1CD9C9B792672FD6C0D093896901179E785BB24EF60B8A286333FD1012BD8EE4D9E4CFEE72A81948B6C05831CC3098355846B0D7C1F400706354517C177DAB9965219C39AE82938605745DE80C58D7EAE644DC852FC2B850563A11440FCA037E097BE7388EA0B6A6C6C678CB4C520382926D22CC94829944F52FE7791979F32E9B3315DA54126326035E0AA497FAAA3B56616941624E60C1E6D5D30C2A0B1EB8456BB285B9C8CBF888BFC4601A93442AAB122009C766E4986CA0C53E3343A6D16B34C2E5E6368633E616C1F64DA982B0EDFE9B267FC49F2B1CC196193119A5F2546DB7E2614CB576960717FDA4E95963D73CFCBD33E5EBAF0DD0D2E6A150EA093D582343E504E94DF88A6F725DB480B60E0B4A3A1B489FA1CB35D416D54C0886A8349504221A4FFE085C674788B3B553ED3CF65DFB7FBA32A7D945B51DA6C02016DCAAC2D60A8CEDF5973103DB800F548585DFB2F68C96CE72D17819E19A62E8FE237B5D63CB9C39BF850A7FE0E812EADB726202EDCD24A90688D237B7EADC20BC54133C7C3605918BC3D29DCAD1CB6DFB274CE816B7C50EDD43076A9306E82F582AD9D179157582ECB4F37998F4209FAF9F8F49325BFBAB6959175BD570AE0D7B09535C014128C71FB394C930295CFA95F0BDBF04DBEAEA6DA4A8909747CDC0F2DBE7623AB3086CD29F4F21F9E74A2D68E64DF4D3B057F5F11A58FD11EA4B227EA95458D15CBACD3F0181930A1196318C66564E57080F7EEFF5EE5171BA5FCE5DEDE3E2B50F2B6EFDB93585167C337F7E44E00928EEBD6622EBECCDDFEEE8AF75FAA50E47D5E5D04684A31C6B750527E39D02AFB77E8206734D328BB686FC396821999776FBE8DFEB40F0219504DD8BB817ADFB32C1DD6A9ABDE09E1C9BD09FCD7D0B2C3FAF3E801BD30902BD50ABF0B252E356C8F01FD2812E85CEC75A94988E71A8FFB86242FBA088C76A8BBF27D40B48AA499D9DCFD680E398A654EC793B13FEDFBD432A5B0778F4EFC5A742FF0E85F81E7572CEE3CD835D2A7F761B7F3B965B8931335A2AE3126082CD121F83B2CD1E3FCBE472C7C325925B799FF96942765F6AF11FC39A5E589371BEE85AC20EF9E6065E0F1D4BA9525EE751F48397AFB9A3BCFC563A562E49EEC60D116E66976E7275A453D026DE393F2852D088CB20230969B0DA4C11BFB24347A414AC4B2211940389D8AC40EB6D06F51950C6FC6D47C3FC133299CC5AC2DEB7067AA6EBC6F562E7C5B5CE365F955E29E4BA26E27BF4A6EB3E47D2B51B2E6E94361EFB4A207088FC442897D224D3136BD7195117B168A5C97CF36DF9090085512C1E616A2208FFA84B7DAC16AD390BA87A94BEF74086E410122B0631CFA12CBA0020237A29814F97D9D3057FD7216E4E55939C7909D455F8D99C4FECC67D2E235476A61338FB0CDA250C8412ACE493EA306C31230A8F3239E5BA4CA0C7E8E2B96F7BF61741F2B05F6B7C970ACFD6B98CFBCE4BE09CF83BD4821DB23A907934A2915854AA4FA0A234536FB24688C94B800498CF28B3CF0251BCC54D294BF5E9113F7BB7B0CE53B41770237697760213E91BC457C987BFEF35A4E927436CDCE0BF34D557AD7435B86B0087EC43F4374F17394C01308720895AC0E2C1CC14656A373D14223BE7A98C0D60CEA887DD15F6C9C8E4BD2DC92DBBCC63FB7AC9EF319DD51C7D7B0DA99C7D099DF6A829F3B1B1B6F78C6302F313268F7436E986D37DA3AE7B54BC24B0E57D9F8934F3D3FF374897934D1EC2D0DC41D4C4FC64D098F46EBAEAC80069AD8E32C07B52FB940CEA12B9BE4D8F2D33C340566E9D9C0757F75C1B837C3AE3A37A1C76EAD4590D0A23EAC689EC5FC48153D93DC6DDCD69206FDC646AB23EC87BC5EDD00E158E73FB67D42B5783891E7822B1FB703B94137848857FD6A7A9706216773764D0D72E9D3CD7DF9F33104516E9603B28E871B6E70E7782CAE9824C18EFEBE0905B0685444C9BEEEB5E6D766DCC48885C20579E2468E8A5F58CCF76C34287B1528B7BD6D1BBA9D282A0D21C89192662DBD2B0A34672EB7619E97043524AC2AE9A5AF49F8D0D6F9090AA94DEAE2A2BE007E4325A3CD87C2CA2654CBFFE6CFE9C6B1A57E97B978341BA1439454112B49C66A14F84DF087B0F04E11F4AEA2E992F1B4076E6D6BB8FB8DDBA1160D469A3CC7EB1CEA7A663030CC3C53C107DC64D706D2E20B6867029B7002AC93E76164ACD83A5BCD40525FFE475A0D3ABFD22565BE8CFAD1956E81486F4016811B5B44977E3E1F528258C869429C274BDA21FF10060BB01A30CFA184578E4B9A798BEFDFA81CDAE4C46C8E727AE633ED55C859CD5B9E52C1B920D821C8609B399D9554239AB2255278768583C504BCBE39EEE775652AF5B7570D34468068BD31AE2B86F00EA45619CF037F4C1C4655B6CFD8F7623693130331B4502C05C2857E4254E089305021A0C101C0B6E73D698839C33E168D6D8BA4C0979FE6346AAFEA1E5053FB30704BE8536CFD960CA73542DA65CA02353C66EAFAB0795FC2DB211B18F310BFADC120957C9BD7044035B67D0C3CD68BCCC17250C560C4D1EB8EE9DAACFDD05EEC917844822D91147AC877C722A374D30FB45971FEADA4276F60CDD4F5F048C0B14C6D785181DCF7E244E82DBA15492120B90C9E166F02B92E97C54C6AC062511EF3CB6F7AC373B2941F7B938CC8D7ABC8171EA6BB2E2C357B1E3DDF796E00F7C182139553AE75D4B0FD5359024A22D3FB21C65DBF7B64D6356932A0631F7E75B315F7B1FA30A2CFDB8F6A91F39873FE005784B9B99C60DA50F63F01E30AA3AE0051B4F615E7FA656A5A4E13CAA2F7DED3B20C718EDF663BCF8C2EFC3B8B5F12E37EE5390116BBE0A4BB86A0624E134E1E629D8DC148527967099C89AEFEB01607BFBFD1FACE8ADEE98D69E0AE85B4795411B09DC40627A3986BA784AA4EE4D55D36B39C8662F6FA5D12B2C72A8351454584E035C03201CCBB748F2D51604E23B1B25013596AA6589BF3CAF89A92F5B5DF09FD0C57A38A832612A7BC22253D0063269233869AC9EDEE16328863E88810B5FFDED6AD14C18DACC26BE22C1C07EFED6AB4E57D30C2AE3EDB93A4F922E7E33FA6A89751947D226AD493F85ED64C3436E01B9710BE48598F8C3727CF1821C538D1D5DD3B600F4B486BC06F25E6517AC58F91F343CF13FEDE9B4AC2EBB3EFA86D159A97136F6D5D7F16781EA42A3838A5EB4F8A5521EBB33423A77850B1F4FA9548829DACD45063FA749E4306663623656170F9E856FF63A788059A2BB0ECFC61A97321DB68869E1573B06E418C37D8485CCCFDABEB553F76EE809B88B8DEC5E7D889718EA0D75E3F679A +smlen = 6477 +sm = 0B6056435A2A76415C87E752A78230AC36F276B9D3019CCF136CE625CEC1C26C3C8FC45014C934388E35224AE29C2DD0206BD56B3ACCE60CE819CCB4C4966227E698DA01A71099DB598769CA072005B0F98EB75612BCB30AA48BB2CF622C9370FB88AAE13B2146536A2779D3BFD9028D1D5680C491ECD7683DDC834BC9E8A2BBA8CACDF573745D6582F5DFC02C6F45450AAA05294A4601DB4FF3B0672B8BCC89D577AC3F6AED56989ADF631504A5A8DF7095D9E98EFB15AB1A91BFBE4C6BD31CB3D8C4806D14E099D36C845918C623C077AB0C27AA67B48D64D3FE552DB2FB13999FF8F8FFA2030D265E2E761D4246FE312A6004CE3A37A519F1224DE792D9AB5177B66A70F0BE2B78D2BDEE4B6DA123E14E9F06EB03E6F1BBD430F6A3186634AD05E5C285F8D6CC0DFB38CEB5BDF8E3386389EB377A14E9C7EED6F6FA0D72C05B41C12892FDAAB519A352F0CC0CC33D89058D97AD9E2E5CF1ACAC4F6C6CD74414FAADB7D41D8892721A6DA449961350C5E127EBB1C6F4086D45F95E07758B2138AA47145101F13C57754D4ED11CBACC27EC6F13E3CC0E47AF330C03D56147D4D7FB04DC29DB1E5D45A9241247F74B1C3EB9233E473A043670E5647C5AC30C516E133896DD73F1FD378CC86DDADDDB3A99B55E7977EDAF0F1FF06003CF84AC513D80E865CDDA10896D73E1740A9775EB23E74793423285EFE34B67F7BB0C89A8EF0BA1C479ADDA89D5208259BFD9B2F8736F78FDE4CB8162DABBC6387C4087C0DC7A911C36325A245BFEEA484144571E92678B8ECEAAD1B11D032ABE48242CA84D02DABAC8A6CBED81F55AD7206EAED4909D935523F1BD055C6E57CF92D8B1ED00F632BF850F3213B16A81386532638288C8E105ACF0A3F7115D2264ABC38735FD4856233AB64B1DD3FB99CECE542F9B3E6F2643AE6249BFA6E3FA91E8ED08FF0C3220AC7823CE4E5481BA882F2878C0D52D73A44698D53993015F3690CE5D65FF9613A403D0C5F68780F8A8ABF845628291339F45AF9530A29BFAC7DCAD9631ECFED7722B39E2571EF6C3ED28FC6117954D45A6963F7B348C3AD7D18473408CB1A5553E54EFAE42BA110915A1ABF7D66EB7EEF41438A150958875F69C57BBDF31AD07A4E7A8AB0E1364521D24145D69F6BE37A8E73417D77B8F00383D95E7E76C669EE60002BDCC01A9205F775414FBF2ED1A623517E966F1E7F9F5B1826EDC4CC59223BC908C13AF20F4AB5ADAA7A1A52F3E96E3180FDB6E50DBFB31B5EA7A0FA959E75974804B311B24C12FB24B898B8A27CA85C8EB6E97986607B6537D7EE65F698A4EFFCB40EEE1E408B6189F08C98E759B436874CEF8FEAF326DB47471D5ADC32193D72F50A0F05D8C89199DBB4B4E57A4F6C5C0093990A39D6B1D433DC5A7AD752FC328523568D7EF5F30FD5C33564284AFFF1BFB2162244D7C55C114917C74717B38C1D084ADA945656A257FFAC53B3C638C4012B0423C67FA4B0E76FBCD7ED08C5A911D415D9F0BA641530F6C65FA85F4257D2330E5BCE918609351D2DC8DA90CDC39155DE4D748545D43462D26471FBA519587CBBE239AAE52AC74014F98E32854FDC36645275437258ABFE9432FE851DAB464A4022FEA3EF90DD200FE09C2E3011FF0FEB21D44544CA22E1AFC4453C6C5D8EE81F154E7A44EB03655B3610AAF034504771D0F01E1F43589C960878105DE07A31F0E10E6597BBA7E4534681FBAD6E40CB620E2CCC59D8B59339ADF7B91679A0B05446CD9AE8204D763D7CA49806A69C43ABD49B14FF884B38A02227D3EF85912039C60C36CD6691CF7F5C1199CC678A377DE336CBC78C3549405C6A7577C748972A4D2559318D9445499ECCC3CFF89D13187B959F8472ACAEFB38E2DE6C0385E77F5581F36C592C842C4C9ECAE7DB479CAB62FFEFA5A477D55DDB85A86206342BC45ED61365FA3E5BDB8C36934BB7AF6B24BBA56BEB2390760E412CBA0EAA4F3CEC23757A6ACB4E89CABB180388EB2B1AC7D8638FAD328A1518CD5844DE92109C02C1E76E8D4BCD746BE2E6C31115344D7C08030B6EC61A39136D9919B19EFFB00A8B6DE4B9F62C2E2499AB5212A69776B58ACA79B43EC7A0D896399650520C5A1A931912BBB42F7A27A280D1BEB690EB555B8AAE51BF236593059B377446EEB402A50DE8DC74F07213D5DA994EA3B09A3A9FDEDAECA56E69046C2A83F56DB54271DBC76114A6D13BF396FC93D2D84C6515D810796B642D970DF122AB84115D047EA7A732098B7257FAE237FEA609A7846FAF648DD4041664EA0351DF45DDF287BD18409662F45ACD45C8F990804034BE876E0D4465D5E745876B4231B4ADB319051A75D4273211E1D32877E08DDE0D107ACD234519D6B0AA2729CC71F456555BD763ABF9E8CF7F159673922AC6A29E6CFE7628758B7C14D5098A6F182FD7126FD0857F29881354AADC60762AA62B4C40ACEFF8DF80ED028CA92AA7B318D6AC7AE0D0A8EBAFF2B980FCA672C5B8D60A2CCD4C6C44372F309153CE254A04F0F3D06CF411C363A01409D0BE6FDB3E3D3E8D897467A3B8E51402BC49085C9362F060081A01F59078135F8D77CF05DE554309D9D996EF567E695A753CE4451F806DBE29A0763AA494F61CCC8957EF60E1648A6AE7D60D6A12BA51BD19F4828FAAEF30C1C88178F2D5AF8231AAD1E288AE8A58563F5C351284C3D92ECDC2C539EED6A0EE9F5D3633EC31BE6E749ABA1402B7E2AA5EBBE9CDD8B864B3B14F7425908B476E5641BAE26C954770ED14A32C9AB4F424D9B346920D93D25353AF37C475B8330900DECF25D78D36DA1096AD292A4D9941527C80A7C65FACFDDE59889231004C3C35090B58D2A1270D5EB4F7E05F727B673A141478CAD30977874CE08A8AF4A163A1D64977ABF3FD71353A33FBF2483F4772AAC2FB636CE63137108FAD6E5D497F1190F476C18BE807D20915213EDD6AFD269E105488AED35EA535E9B76EA38093E09438746A629E908486C165EC6FF41DDE6BEDB934BAA17BED26268D51E856F54750477E4C2C20DB932B93464B936990BC7B95BB469CB929242BCAFD6747973534142AB05B19EF37A786267A15E2756F2723EA261A0A81FC9985D517385C284D3FE8D20C4C00D91267545AF5CD97B06943662C04741731B9B5CABFF305FC103A6871ACF71D4F2DF5C8B50941959758B8205500C8ACD6D3B6ED5FB627AE0760851FCA8EA254E4EABBDB7744432076242F2F1EC9AC89AD08A3E74FB768A1650E57687EF983FAA15659AC7C578A470F9F516380913557BB19728E665F0D7E8B970CA94D83E3B47F05E32E70D75DF8A6535D028C6C113F407FEE1AA7EAF929A9C39D477F316C8ABFE2E1C89125D6446B362F43C6E571E3A504D0621E0F3075AA69C0F9A516CB0C2364E93365B974FE2F90BAE31523E79C88F381F58A833434AF5101986EB0D8D1843C4FDFFE2E56F08C83DF7339900489E7A6E25AABBD88E6EF1BD68437AFB9991DE5EA65FE97014D65BFC173C27A38C70789F48631BA5AEC28150A1C0DBC00C5B2DA597695F488F0E06589C53DF2619A1B080823967F62DB1A136A5F396F884B4E26AE0E3872131E11AB90005653BF5A1E12290F77DCD6B3FE810BCE595D250C8614A03C613BE84BF13EEB412766CFCD7A370F3DEF3CBD3CC9C09BD46BF8307BD154BF3AA522140D0BDF5999E3D203699A5414108D48A7DADE4635B387118656BB05B7EFF46C04BD1836205AF5A199FB5465F221D400F062E2C2233FD78ABFBD1F39FA30E0A29981B0381F50BBE1CBC21EE15AEA0D6054FB67CA49C88ABF6197C157FCB2F4979DE3FC4E4D8F3A2B11BA3AC8C068F2BD9E5D4E391D50D50B651C1DF97CEBFBD2603EA8979C55C4B4E8C2A6515EAB1E4D693C340AFDE90C1AC7376F02E820D502C5931C1DED8D1B9BB8DF2433642E8AD03E2C004C1B97D9A5A20DA3EEAC0645D7BE48C1A22CA6161191760C9B458D23AE547ED2F78981F07B25C0B71005D0B06AC0890941BA435F80D9F28C5C2CD3E5710328566202BB67B73F46CF9F475DB3CCF110142E668DFE99A217F16CFECDC959AC28F6EBC2BF0AA4C89610C2005D6187040A4100ACD1CFC3755E4F559627084953723B2D7DAC5F535F7F6576D1935FE9B5100ECC799EC1547001FC52F725925F798ECFF4D950C580050F8595EE02F7679C2C7C9F22F7E30CC300297F79F62AAB03C4998FD1357BE7CDC9401D8CBC33F9DC7164B114E605CE057D7C4DCCB7103407888DDBB9F30D409FB13D5DD67E6DBE999D0326F2C6DC7D54940E9A50538B90903FA71B02E7C3BA65521E48355D7A9723FB19E161388BC00188283497A4DB8CB479BFD6695510E251726124243E123D023F4D379EF4D19597C1B3A420462578376FBDEB3C350A972301B6847CEAC13BFC3A341FAC12FA2BEF52E0EC0E3CE0CA3FD8D545791E3DE5D66E6CC02FD4FCA045A3CB30BAE773B5FDBF2D66B084F67A26727B71C849A9456BB8F944BCF83D1348A9DB1D8E4E8D26F4B6187772431C46F8AB79DAAFCA882A3304F83F87717D0CB2B33AE1DBA1A2302ED46573D9049699390A1BF25527431188C52642B48ABF9020C31D58F3520DC005668492E4C526B7182E417292A2D6A9BD4FE285859899FB6D3E1E61229357B85AF2C35518F26365A747FDEE00000000000000000000000000000070F181E22291F7AB96E8C14D1A5094672D7034FA8F81703A2CC18983C972CC66736CD98B031AC8A479CED21A1F634938DF85F3E83161646DB81B9AC3EA22F80980B8E2EBA4E9975714E5A98985817F426C41F3968349686B69AF917564A2648401B8FA127FC3200DC16A9E663D1D345EA83131E21229DD39E70D7270DE7577A7E9635602FD2C30EFAF204A9234F0A73D21375658B0B0B04927E67F3F5534614EDF5137BADFED914A49AA301000092DA93B3FA4A0FF592CC3A53F4A75B54FEE775EFA421EEFCD6E0D32FB5CDC096886076DA940B26C6E07F12F6E08FA7B3E2DC42055308E5607A2732717AE592A6909C6E084252A5B08685FE8C6C1DA387B0AA9800B67CDB3EE2FB21B9BE5E6B79AB545563068441C0C9C1E68CEF6028A5CEDF27D3CA47D95094C9E1E68B8449758BE3FF8FDE148ABC420295DC76E3EBA8E11433217FDC3136551A5A41C1C7E7D6EF43601946897FDA54842D8F73FAA7EB7ED0DE544FEF2A95C6FECB13C8C0F14B5B22493F54374184B73D5BD47383BBC5DD7BC1BEAC0CB8E66D2F413A9DCEB7E1D0EE2D63B9EB28DB232C33A95B792AE67D2591F5AF59DDC45771A0E7195C4D25E7F4079359597678B0C0A87DF3D66A686A9215DD566D4722C212AD05A23E1377E37E18A6AB3AB8BF5CD47BF1BAF06EB05E4C150CA67D7E52BD297A08CFC97B575752E686B83575F425F3A450BB0F596A60E41F7183F463007FD019EE255BDEF1D98B7A0A12EC33B3E2BC9BF0CC8F4860DEBCFBBD5E40B2ADC2CD10EC35A341BE7A49F8D204FDAE86921B7DE5BA700A61E2B041A8EA7040ACEE844892E5CF025FFEC5322FF6D765BFF1107C967A12ECCB0489F64F8C13BD7057DF76485446641AA7A560C7E73008C46572628E1A225A8D3F6D68DDC9759A952FC07CD43DE4434BD3391089E900275E9EBC92563AC1403BB7DFDD182092130E3E6AEB7B666F4BA66C38BBE1F726F40A07DF6C42079A6054399519E26D765CA065F4DDFD27A29CBA292699CD826FA9D3E7EE31B0D76813879DB5EC5C7F454095DC3BD27323DABD2DFF949AC760D6137334507816330FA67D886021661ADC69AEBD882A07E01B4B6E5492399ECDEA99222EE785C810B30409DFAF2A3CE5A05D699C2368249C9588D86FEAA778B4860D6DD442088A21D2D9D0B49B15EC579776812AF8AD582F1C44BB6432D7472300B5440A382ED87AB64B20373A0ABDBCE391D0BFFC9C543EC686449FCA9D04B7141836A416720BDFF250A06D7651A1F98EABE4B340B2303591D0847AED6FFE423B6DD8C0C03459C381DB506F531343F82C116323899DF1E5D8DB8997BEC12EB70103F0BF2B3D53C4D4694052606EE32BE4F5B35450358D7D85062DCF7F0BDB51364700BAF92CD6ACE4E2C10E6CD9A332716F5F4BF7598466A99238357798A499C9B8BE77690635C57E7D87A904B3F2278C0B1B23E5860B0532F152E1626C86FD855F656B5D070BC81CE4634A87C8EA6D6A433C02DD2E6D6561B25968B149A6F3BBA40B749F188B84314B5778A000CAE91A53D59860EE6F7DF38CA0935CD64C08A34BF19981C17951B9C39A847D0637441452E38CE5E1D9B99BED51B86705CEBB8D3244C40BB8D70F846936A2BE29C21604A7E6BD3E655022B929954F6C9A5743F5FC2127B49956D80128DD582CEAA06FC174813E5F5E6A0A4D7D26756FB28A6588E9410722591CCE2A6C6ED0976B98E1FB0C642D5DF8F08E96BAE1FE10375FA1D7C70806101570FEF1EBC8F58664281E2B61DF2081B655013AEF54616308504F5F4A1E8F156680163489D3FE7BB0A514F1D2D57EE6302853D7D03C767C7BDFB79E2B8C80403F26F6EDBDD6A890A0A0B9B76D334E0F729FF9C47BFE960A1C3FAF77E81B9AC156367423DBB4D766A1F3B1E67595EFFD76287F22BC37DA4F0204633E804002EB7C1AD0836FA4D01E2FCDEAB8457DFC3D8B7F1151BEF3574F8F4653AA3780003787B8891901ABC8250A974C15F2DDDF9E1BE6798647EED710D06CC3FB4C276BFFA585680FC632D8EFD1614745BC3C72B82C53FEAE935EA5014E2B321F69BADF570FAD878C9590FD20FB7BF1B31E373DA93D1A8C63EA45E698CE060FE70ABA0FA84F37E836F2AD2998F07101D3FC7CA2B08B1398E1687ED5A8CE860EF9B4889FF436B74D13281D1F6A7EDF1DBE8989BFAEEFE6A475E65217643E757006871E664099F5B3846553603CD9EEF8FC195807361FBFDEB8DEE6A0B79F009C10DF397FFB865F4EBD0473D458D553358029C6B5A95D6FFEE9B645311D10A8F479B7E5249AA87E3DED08311B4DDF3A458FE61AE294A22643861826ACBBC9B0EA8B73157CE15D1FF35098AE67159B07CA7499398C26776DD9884B5D3786C87D48E864D8BBE2B73E2890F217E135BFDFC4DC5E805D9CEFEF5268E33DB611ABA6A5D57EC82B7246A63DCF3EAF3A51CF503D65C206D2362421DE774158AEAFFEE45A6B5AD5CC0B1DE0E2EA74E97913729A69E9C00A309DDCEB7738BAF4757EA9CC96E055BBDF692B12D8B01B92CE5ECF3D52187402CB7FD961A2672DC1875B6EA22AD7F5F42B1B52BA2D780F2E6C5B25FC7E30B1B663E3A09C8FF0B5C302E0E7F984DDCC62DDA65FD996E17DA72F02A16C354BBDAD44C5B5044759BD53789B98BC58CC25FCDF10A9CBBF0FD6ABD58A4CEDD92C5D85EF22B3C5EE5D9440CE42995517D2F7352CE997F51A36B9FA5703B4C6491AD01F406FD1B5BF85321026D28B51354DADEDF057B37743499A986469F908A01F3C1B74DEF5D8E2F57ED25A80720B540333109A0A65E7984B557F65429F3D3BD7EC3732A10D7AF36DD5D2414A09949A0F57F37BD9021D2C482E61437CC15E9DFDD92D4C212C4FC6C22C54591E5AFD48210FDC88040135E433F50E45874E0D5EE2BBC857F2C80E2FA4FC7ACFEC8EEC0CAB351F677C790787C715945C21BF923EDC0A58878AE09ACF5FB5A003C9C0B6E30A450CE6DAD4B626108B88E89F1E6A7BB3843E1EC8AEE35AF69E81773CFF71190F819CCF24142D60AC51B80B61019EC7ED2EFB6C5F18B499FC9727BED2E3324F8B94A522092E0A98241E29F8F14C6561DF3FEA0824F9CB0FE10BB497E427EE62085E7AABB2900FA47BF27C1638BD116C5555C076DEEFE9754E8ED333D72CE9423E27EF640FD5199C0CAFBCF2DA1C5C34121A69E7E0DEB3C268FE60C6797056383DA43E6F472D225116F63124498271D3D43AADCC5871F2349CE040BE068D72EB57B7827A7D9AA01405BA0AB07E684B91EF05418948F6713AEF1F4948399E0E6130740CAE3E481A6366295422BE3EE2E892AA9FEE86A6E23E2EBCBE654989FD93D1C4E7D62910E1223BD66B7C54F8DD7D373986E5D4141BF0BDE98DD13AAB7D598D698660F11FA4BFB0AD09D5C27B65386C8673E6C4AE9E8E30F8DD1A5A3FE557A3C29DCF99A7C376200AB595C49445E740E3DAEC07BC047FD6EA4FC6CFDC23D7449F9D1170FE635CA36D3DE5B57F1CFB182DE240CD4C1E480600C449D1A8596D8315906A53954201929E7665DD2E27D590D481DD394CF2E8AE19217F1FF0CB511DEF7460DC9E49C21607247857BA744B1384344B4C2D8CE987512376F66F1A279509281242A7A2A58ED500395418138ABDB9C5572A258D157F4D3E88ED216BBE9CEE3BD054FE61F94C59A4AD19AA62E456B86CADE61622A6FEA877575EEAEA20C76AE8A89E7B44396BAE0EEEAB1C23F221A3DF2B2CC683256A4E5C8207EDA0B235562AD3B510F9D3FBE0B51CD8F238A0ABD2EC182681606C8FD111D8CE1EC1CDA6DB4572303DDEB925AC1FFFD75E321468266790DEE6BC0E85070CEE749D9E46795936324DD1388E1B11AA617500534B8DAF2DE12B035F73111B770F5F56F5C6A4152C45CE0E112E650FAA9F3C7E59E3410745C29FA59CAE5CC37FE4C6594990E50DF1576B69B2B292AFC58A804743F49DD7C98C1768FD19AB4213AE4FB197492AF5BF7FBC6C8B507673539D8515DD527FAFDD8CA3EFF629CAA720AA11E65922678447AD4DDF5FF943873DF5203AFEA4130CA5F633E104AB083EC690CF092D208A98006E91BC7E33731D18E592869E564E6D3FF8BBBBB9837FFC1F1B92DE0F5DD4A029C51E3F64592CAC3DE1B4CA5414F894B7B0B7D73D6BF1DA4B908ACEAB47771DA56A8B0536301FC5FD270CAA55CE171332F7DB2EB4619C4B2C1971EBC0AB8B0B11FD54C24285DA8428AB9E0150D8897216B133ED554DE8CEE532024DF8B8D9314D7C9A3EC60464F9C7BCA8C3D4FBA23A7B543AC111ABA8C8F1BD54A243D565DC062F84CCCEDB0A03375FDFBCEF8AD8CAFC440D3E6F988DC607ECB947673DEC4AD48724C91A6BE22A0027E42AF6D94D26D188D0B7B3A5AF012880FC0105DD2F11171742321DD41A0401415C58AD4DC445642A2CBB466788F54D270BD8DF25602B298B62B6D0FA3ADA97008A99B73A807092F8957F17EEAD9D53B1128FBEF1DEFCBC607EA92AFBD353E95F52D33AB7C1EBE2 + +count = 96 +seed = 26CF860726D4DFA38AE07399838BB336F1BEE59E9F23AE4C81E73D49964997EF21CB5F5412F9A70A1EC39FC6228C36CA +mlen = 3201 +msg = DE897F02AE7292ABAFA6A0CAD52929113410F2BA972B4184E894C4D31081420751560956F49CE2B772635625AFC3CA6698FBFDE4D0A05EF243DF190BA1CE780EB572590E01E6E283E1963F2B0722B0CEB365552F65BD405F1A284DDBED07BA61C4453D30CC28C83E41590E09D7BB6932D231285205D61332FA9263B8A2D3D7F7FA20F521CA4B49F249896780E08C2DC41669BF0777278F87BB1F72CDDF4B998062B1642791F81AD474D6D8F963DCB4458CE11108544C41CDF19145B77038C7E8ADCD6501508C53B25BE6E787313018620D1BA647CCA4A5A8399E11815EAECEC6AE66DBC576699BB0AB44DE111AB6F252256389EFDC0546E641DE87FD6A3A724716257A9174F39542539A593864441EB79D499FCDF2F1D053CEBB3A1FCC09419D2C553C2265B3DC3943E0341BB49130E9981EC59945FA0B23E9DBDBF352ABA0D925C4333F2EE1F2C83C847EFA78BB13263B893D7CAE029BF08CEA2A5D1B5B997E403A489C6D9A124FB8386FE58C2476894E7754B8E5A162102A119482B5E59F8D89C8B1DEA70B6C80641C77BFD12D45C5B3CE0021EE500A1665ABCF740794E0D3E7E8CB5804A1E0D0C81A107DEE80BF63BFF8CE2EE2DD602DF279DE39C579B417A758356D2B48B41E83495DEE9ADFE4506E03F19DD096E81405264D408B2FBCDBF41DB5CED6FBDC2645DBEFE5BD038382993970C7686DBA3FEDC24E1F91BA4B6CF70B2E832B97BE24B6393273A519DB0B4446E98D77E86CCACFBECCB18939013C66F7A29B10DE2E88FCFAEF656B858B7DFACC4F21EF5F328C0EF604FEDD993510BA40530B79525FE8D336DEF0E5C303539E664A9360EDAD7268F70DF4DE199AB3F70EB2BA65E2752BF5FDB1E853E6F4EFCAFBB31D8CC23155413BE31082DA958B01682894A9057CAB66D4D64A6F3B1D81C5B75815A3E0CAF6486B17339174276A84E11C117B060302DC2EE06A03C0E15395C0DD32661638F059A385578C1B792349A41C511D12AC7185B060A831EE296E6626459C2750FAF3AFB579F6F6836D566C00C979B5130E8E50431E914834CBB3D26F6E5BA50BCF05D50F699FAF10767AA2831C3557A53AF14BFD9F23C00F76C2680C7DBF4A9B2A425E34C943228C3EBE55A0960ACC757D7878F7943E2E8A1CBC8C0D2139A6A6459D3492A1A7757F71E90A58A78E0FF9B04D059C5D131F6E3C30742FDE5506AE7860045A4C903DE96DC43AC6A69273BF8EDAB7E7FAFBAAD9EFA8FA609961502EFACCDE63A6D98D8D017075487C608FF701A7E3381D7A2ACB134B198950ECC6970A75AF5625FAA4EAF968CCE48FFB673F4F365802A984C609C33BA312140A60A6F0924E945D11BAACFCD643C874D352A90367EA4C59B63665364832B1A9A9A01EDA92C64F393C357158973FA7C6047B8B5E27EEDB28E26359402B63032F8B230F5AA968272819CA486A8BAFD3D66799AE951CABF04EA81E1E7E4632B915D4E8387C7D1F4FAFE1C1FC8666FE0318403EA0027487E947D844A7FA28C0523A64EBD95D2A8ABF6A71FEFB5BC059B2CBEECD4375F3A3F109DEAD98539244DDCFEE9E42DB3ABDAF943C445712EBF19508A1FFA6133C5078C1DA69A32CBE729A8876C4C73CB232024A87D87FD5F9456D3D4A936CB4CE2E00EF415406D66D344000A4A95CC9651425A16021336C4BEFF310210324C754BBE13CD0066C507413671C80CF492B4655D898A18A2F4DB5A393400C6AD821580B0712D6C919C62E87FE212260EAEF6876C409FCA1047A67B223E0766144F3F676F051FBE912C4CE4A9F7B85459DA031EC47C621F6EF06CD1621421FA52B047B51C944DFA94807083B4ED40D533B19813477193D1E4E96C8D76A5AF3100FA44A985A6513060B08A7F3848159B3CC551D43370B223037753B824A099A7C7DF59305BE09E2E79618C83818BD542F39380126A927190EA5536DFA63B664AA7601C6D82CDDF4CE4006E1AF2601EC453971828CD09C29D2F3EA6392B58D38BCF40BF6B6497F6B848CB853B187610CD23880CB09787C76087356C66565C0399BE746A81753442E4AAA54E84F1D8C2CCB2D00A551E960203D61E71A72E131ED1967DD06E72C99264EF2EE5BD156FC869B5031BA23A6D354D7CEC58F339F6BC2DD1C547F07AA733994860197DCE5BCE6024A74668ED89A2C9CAFE1F78B31638C3225D96009C260FBD28C1F0423E75C9C01A0F9E62B7F265FA3817F441F56AE79BA54A0C107FD7946A2DDDA60D0EAE428715FE2B4FF93BEF83CD10E5E17760FE028F1AAC8084A43EDCC12BFD3265D13FA94D9704809A50881D48F0080A976C5BF31B353B9043C0F0B69AE6F2B8BADD056752F2FC9E90C4B35850C2D45B9F354B41ED7826B976528875547A0C389B83725E26C006CC8240E380E3EB554DBF2133A131743539B1D174CCA6B135C59F81D499631BDA4CF90DED836E8C24C074A0BCD83271309FFEF320791C9030FC2B1F53FD2DE870E54EBA20CE9930C279B48B39CB481737F012F65933650374BA39E2222191B0E3C7DB9632CE9CB077322CEF97ED832DDD8AAEE53C52C03D2AAF8EB5597D8D6467A406BF428E2F16462E0C0D486A1C1C7348CBBF92633EC4FFA75945025A3C92095317E32290D4CBAA6CA40F3F201975F3FC8B733D1467C094E075E8415352E3AE51A6C5169A4AA430BCD66FF39B184F5B7174042DFCC6840EEF60CCDCAC12D012AE4F24F7184A038D8D9964AB405366740600B98CFE2E4737C8D846FD4E9B22B5047110D85B37BDB9E7E3BAF5298BBDC1050AA20F14E34DEC283830F5FA9C570C22CA659C1276BE8FFBC0AC3551DB8488855AE7EC21E239E88A0F68227D17DD87FFA3B3D0535F9E57807755DE56A65C0DE9F4A79F8746B20908BF9416A86F62EE2C2545BCA2D55CD4D45DCDF06DC879E1B6270A80778D0274AA658395D800EAEF367DF4F4D838EEE0A66093E0F419B9EDC5F003E31CF0EB7E1CEE9ACCDA7A2DFC920A4B5222389DBF12AD17392850C434A9B3C260159B0F52E78E7A66D28DD5B3C77662CFED2CB3DD5BC3CC26A34293EBF1FB3A9BC59BB0C104C5A9387F3893A65D145D424CE741A375F9C65E733A024E78FE274B29FF4B0EB6F21FAFC31453EAF7E48FABEC5711D3898B876F59952C73123281A8E85148CEF5A166BF45DF36053D57AE6F29D3E334BB2395FA236D4DAA8A4FDF99D80A9BCDBED36154BF4FA3D463D51974032D7B88B2504317E14165B1C3FE3D8FE366FC8284321D80F9CF512F418C63F73B7C29C07870332387BBD1A870AC39485F64086006CFD68C8299347615A423736C01FAEF2DA56CFB6FC966948649324E22D4551B9F50654EE505547F7D0B8481ADF6AAC3977F49D7E6AE5C4248DF7B43BDA7F082AACFCDCF1C1BC04F2D45F5E028498ECBCA47EC4D1DDEB03A2AB27BE9E4B80585145676F8AE7A5017BC5EFA317A576ED6E423D5A0495B8DC619712A2C3E6162B04B9BBC7DE4BE6532F6C1C019E702C014C60189A2612594BCB18317804C630264D07B7396DB562777BC305B885E00706FF6D0208737BD229BC7AEEFF5FB770A4C057B347601F1F6C16F60D4A53A0B32631AD2D41FA307F6630228E1807D22475D5E331A50A680896DC606F3941AC08F8BA46DE5A49F5ED6A94965334FDFD69C4A6C7973D9615B3FE576B15AACB9B98D9E498D2A3A89B4F8EEE715ED5F29F13DDE7629BB386F7CC800F16F3B5BA8BD0E14CD8D9BB0F0AA615BE9D7557F6EFD00F7BBEF9989E7F463279408E6AD77E100AE4457D57424F2B1CAEF43052C5B25C896BAA1C2FE67D1D6F669311F17D39460F0B176A7727F53257A36FAACBF3DFE623D8F882F8EE41BA1CE387E1D1860F4BABE26ED678395B9979D84DEA5C7B38905D4C7FD867ED7722D066BFF3A833D3282BB40D1CD310DC8DAC9270A49B65B5181EB30F166CAF0832A8DC56B9D135550B506D98D036BE7876836AAE669507990DE6D03E78A38139CF64F65FB410F192E30B045C93FE259C10E0C5B56A2B5F0605DA0851104C4BEEB4E3B30135CAE5A6C68403C63121B0993832834A3B5EBDD345C41B26DD219560B624024B8B945A10D385B3CE4E0BD54E10A64ACA59D283302028A9592120D142CCEB1CC30E1F96AD041F1E17BCDC3C68C2EA2E0D65D6BA3696166CB365CC461ABC4D67D504E8290EB452ECB77F6D5FAA5053D01317646242384C5C510BD43C5780BBD01EBC3AF33D29D8A09EF39AC85E70398D2A64DFFA72B3EFD8D6D57AA2F9DAC0CC6EEAB27B69FDF2403A5FEDE0BFAF441619BE03FDE44C49FF0A34E9C37D2B9AEB726D56EB646A67BF349323F397DB056D71DE72A2597D780942554C8F8273E307DBA6BD02E944E0559509E1F28B511BD709D03EA2451EF234DF6F077E06AA01E2806D5BDF89DF29F1B3D8C6D8014496AD83857F7465F1072E88709D0194733E1FC8C9F092DF5B9802FD2DDDA8B142217B9532D8604E2F32D06F6400025930DA2BE9B25529788E6BF4EB7F84C272DF455CE2ADA291CFDB5FE815129E4AED59625C879E99B3E3C1B6C5D7 +pk = AE987BED1D3E6A9B3243D65958EF6F6BED0C865DFBCA7867D300A7F900BDCB0433100B928B4707FC6A0BBD057C4BEFB8605EF2AAD618720AD54D4FF59A9B1AB67E471B0C125A1BC0BBDCDBAEF6F2A77992987E6529852369B9EADA27AE895C1CBD678045172B079BFC6187F5600772120E0AC66FFC8595EC04F9F4D595760243AF7CFB6E547B112877F82154120B89B21D4A46CBD67DEE7ACD56D4B20775B8350ABB59F57BC7F14A5641DBF99348FABC851473131A7EE149AA1EEDB02A9647244668011B4BF9D7FFABF7712FF088A689CF576AFF8BEF70EBB5FAE87A81C1767686CC838ABB4F3912FA3215C3264EAF92D689F2D33432046E06EC95D4FF75DC65830344AAF858C2F08E6C1C983A5987F9FD5ACBB3BE294508165AB0E20512A0E8251DCBD404223C066C703FED35B622A3A54EE09322994450EA21FA911638CAE00B8D1A57BD34A2C63B023D82D2FC8994BC83BCDAB4C040672F2F95F489CC372EB222869FCF3B4CCDFEA9A6DFC5EBCBA71AFE5B991DEC2F881D57952B1795A4B6A9DFF0AAA4F8C18AFCC582B52EB2C5643F3F532907AC1A5B1D7C233FF1139099CC87D42A304C6AAE8215593ED309462EF7B2198BBA5B53E762BA7C4BDF4FAD8D7B96AC3D8D295DA9BC1CFD2638ED1FCD5CF8D82119BEACCD5CEA6960949349067DE713D260E1F5F612681661EA7F7AFDA85B88AAB3174165840DF608FED32474183B24138857A01A3996B5675230B2153273D695CD6E3E2A5195144E1AACD86758B201A8A7B59A1768E569D751F0D11E8FEC7DE0E3CD74E70B4E11D697269B12E13AB1A1E45383B1BD0C06CC50730401D0CC4BCF8A67CC73ED306DA4E87465678F9B9767E7098933F73267D51CA8F5522D2BD93BE2C1A4567334233A870BFA9756920B734376568407F8EEAB7801A2AA676D6A6FAA863ED166641CFA33AC8A77855D4B9DBC729AAAE65AE665F523F812DFCAF69B0ACB7D2DD6D75A42CB60D7A7D2163FBEEC0045EF6944008C6B619103C90ECD6BD868843C2BB188DED13923D1B3868993A4C210D5041DA7F81B1D8EA27418E03F37357E894230450705793214CC0D98BFEFE52F7347BC7B818458E33B15FF75725993F9D3816BA03BB090222B8891852631C8B2894D6BA1EC405BFAE5B80C964A0F539292D30F84F9B51338D48131D0EB572DAEED8D3A8253A5ACC0676AA1ED32EAE33ABC342BE4F1C86C4AE064B3EF17FF4FE872A2C3B141F79BFE1A282B25D0037697B55EB82B97D4E269DA6EE92C8247A094C249FEAAD6EAFBA1B9C39CDDC6550E931A355372F7244BFB7E85D34A1B38B2E8272EDEAE8A96318103347F897A24A85AFD34672F94C68E55A0428CBC08EE964F1C85228CD3245DDE24BAF4D200307F02662650FB36D641A44D7577E7E3BD546FEF540DA77CE717CDD95DB76EF05A469A825BA335645B13279C79030BE66710FCA8C7C5C5FEA32BE23C4AC13B6564CDA170C9A11CDBAD9D0FFA595064BD5CB23FF2F8ABBC1A76541ACD714D820A7EA60E658EF93ECFDDB43F173E9EA9B340E6536CAD152D852C55DD44E4323A42781DF81D02F8ED0FFB19685E541CA9A588AF67099B8E4CD887B0F39E377EDCA6E943F4815FA61E887897C13233DB0F447BDC7ADD42788A9039F6B61FC365A7F763324EE51D742177F0CF42BAB6A9F34AF3FF759EF61111F48C2CF0DCDC25BBB8AB9B88CD2F39CC35C090B8843D02F66EB6F8E6FBC17302C1106706F40C1B4AD405C6601B2799EFBC133292A347474ABD1B470F4AFDEC95E46C0C0C0E700CEFC5D6ED87B6DAA48A1AD16989B3AC28877196A5A10DC3F6D83C40D6F2868128D30BCAC03EBF7A32B0AF4C6AE61E569F6BE7EC04DBF81074F4AA45AEE955317313CB6CC067915468CD87868C841AF0B64ED01F64C0C39F6FECF5672A36EF003FE30E653B3EFA338435A12E6A6C2413AB57ED1CA245EEE77BB38841D83EBD9A134D13B408F47B0AAE076A640566207D31728959F5BCD9C4E5A31D5C8F26EC0002981DFA6446DD8EC703DBEE5D22347A61FC1B67E96035F972BB0F10B55FCC6787B5DF20CF5906C866EF150E1ED615124781D6E5476156A3CBA945FDF500717511B17E8DD619452A84AD4B5E4CA34D278387AF143C91886E289CC5161339852E93CA91BEACB6717E72FEBCF8D3DDE00343179E5D9EAD5A9ACAFBF60743912ED79F3F7D8A89F80AFF59EC3D6197BB6A96AFC3FFEC467072FF2B5CFA5179F942E78E60E0E75B0C8C1F75EF59BFDB39CD64942A9EDC9BFA4C1F5D3F8739DBE765A6C6CB210E56178A270E6F9EAB1B0A7E705483D0117E587BD51D64053D8656887D940BDB21B77B8348C088C1834DFE5D250FAF8CFF79E0CCA7D9A62CCF0179FFAB65072D5DB16B75691F9ECE99E7593A2C1AF52F75C20D4D854A0CA9C36F236126AF384FBC91FC81A3D88EF746C23358F97174871A788D1ED6010EDD87CECFC09672B45CE357D616299776F8F5F15AB4D3B9741C43D3CFD997C289F8D014D59CC538957661F66804BC6CCB1D0AE86F752C7BF8F5C94D89809559283D86DA98C866E56DA12A91420951600F8239CF384D0C161D6D79EF854B458EB9468180134AFBB8887CE49656779FEC7EBC94071F700174043D5A794C28D029C7BE5684165E7ACC939B927A3BAF28FC8379BADCB237EEF16F288084BCB9CDB441E69C0F73C8D733420451C682FA0D4E70DDFCBBD7E47E5CB73F18401D1FD757FDB7CAC3B442F7B007BC73F59A90FE61C8B25F076175 +sk = AE987BED1D3E6A9B3243D65958EF6F6BED0C865DFBCA7867D300A7F900BDCB04006290C1BF419782C3148EDC761731F318DE066CB97FC90C3494A2728C626DC546932EA23DDDE7BA728CA3E0D72B9222EE46F32B611C78D52FE2781B41ACD594C33FB2FA537F9A602F3898A74613FF6227A8F785A49B49F20998595D4ED96FE90456202022861333108824462251277510035228683017851446462482011211553784181300776175262161137423237148460230675042112316223010863036066763781150617416163367574530023123788576531726841435012431525068041405613145210182336366033076734705313264660430157185760855564167271676830106308337405518410663673640011705320255601351824168186611601133107714708728033884060385427260867756810128855670440812530345615480383228344462387257145718573760025654142853746345440811286648450566403227228155226022858564565186003386142334520888776177144070448764452264407821580061556516001451384812655203538675538415487110552410041743713448530288137572041361885037003012731031882884805554143226704771706663776160727564757546552462618137652722418714123465163331538765131104622225665882200525313621400558571154122724370140735315537720012063182115241644214354568461837376037236210208553074836014377534370572262680630403287473887560055113171674077205173020042520071410231551610484110250308355606785760774541057566316534870241544441513830468531275524523660758731434831443822837555266142171141270572056475446374814017143641714778044516522252114167242717687263575104754282275105436548801234434126246325286780340722862460151866212355632688230042216887864366644684430473818566715080108028157253475022016260451827437874535128446717606138427626624155175581136725153150361455014004731283752566373650720823167520436201877063113462334242668724027677665025415260017120136880363775548457115064165402680285071348082064852376115305883230815821763312701063764178821088151452772208354716858630550421828110643071330741702824063408712476063107866074467847258328678734614800632364708615320675811784424647811212514053375753260134344415341348346212338761868060081727453021102185518536077411382331045723610161614111138456804067110072465444767705816656585365767483527643485666128040760867707266724851420647577077382240705611313455646858523221756143413323871437352008655736842187484331674658360415037766153542523755873526465756204416000143374521523321626134638527008736720707365684520045762754565438248568048206262204662172423855770060146271882184122810083057562308545618864046176175455786714723322683617846805346441441082808710050171005473200445722882813786005631326815767163208667381745501663488751240211105782485688118510563684377053153435765747575424073867050066513231574673624832118252215731146438456657541314868038470412825280882848603407234286472127323133772764518356501541172442454814460868776130336522251832876408020168286804111128544563075173305681177066327850623064744405805125867342737105831876287768320050172555706756572173220723005845767656470822186746306418001406227361476382478575720286568271271822804254037723675757747401275616703503143601875202515515804566534413046346408621782643657776311834602823436225418328075335714258270184654621202611357430764515035144734EC154B245ED922EBF0BA651789533C26E3D23941500E8BF4676D8392C9A680C21659380E58CC55C2D49691E3778E6325F5CA7F21AE2394006CFFB32B594C191DF00A71362554BF88B4026CCC7BDFC1E5C3F06A380E25C5CB0096E9AC7CC1A1FE6E6917FF08C52FF4C3841709D36C3584D5E4C9B7B6148310757D1203D401AE82C6E08EB35174E355ED98351D9CEE55864AE317D500C5514BFEB6907A1A136F057F03688F8D6834CF68F9667F76AE9D6BC4AE1FE2DC5327FE11D288C1384241CA24D23CAEC12256E4AA7CABDB6AC38A80FD10F51C4F25799B888AB3879400094E21D22C1EEE4F6CE2900D716650DB5A2059C85C2DD89ED5C9F96A306AB36ACED09E9971DD799A42485A692075CA59B2B824420269CD53EA5E2B895D6E8574CE2034A8BE8FBA55793329C45F073295B2611DEE747313B32C155C951A7224566D1FEDB22304A286515E827B81F48BDE3ABA16B0862CAF87340652902667C05E546E1222692CB57E247961A4E88E38380AE02E5110F9CE76FB4C20D1DEC68B40A70B7007DE86F886C58D6648118F03C6F94EF2972647491EAC65BA8CD24BBEFD337DBA55937B4875B4068EB66585C4D137FED834D67C282B91DD639332FCE4F9CB02C49C96D645EAE4B4D75FE503504F0B88EB6272EF9F146057DC9CB7F092FA01A85CC940869040073C79B9AB4EEE59706241D2470B414C061CCA09D6ED723DEA814426C16D849823D4F1B0543BF79C424FB65924B6A1046450F950D9C030A2C9FB417BB8CF415076DB3693B62BC25F656B29B3D9372CFF407417BB0DB56B712FCD8DB3B666F54AED4A57E8F4CD07DA3AD99EF26DDF69BE3335A2EA4F1CFC9BB2AFDE655FF6EB029021573ADB052174DBF95678754DE1BF897BF9BED6AB3A353FD060759A048E928F4DAD0387FCD3C4DF4B74FFB3F2A52287658F580E105246A94FE18F52E73CA9383211FEA215A3D1AD14C5A8209B20E5E93E46575922E5D2DE534370081AC6C32B1811FE462C4B134A87BA10FE6201D43B041A22C925E82B785CF48EC6A18E539967E97A5DF98915D69862A0E7D04E0A35C987E7F1039767B72A50C6823488F4C612B6D3D91B681BCB53D9DFC4D2419178AF45E39BF77671BB37FB2750692F918F3DC200ED9265FA0A337EA44CAAAC33E5CC8CFDE9A9CEE10B13778B7586791D97D972DD2ED85C48B4CE17C5330E03CDAD095B56165437E21F899F5C2907B5AE8B09646E4326B8CCF5F8CE0B269AE486BCEAB1C826FF6CDD0BBCCFBCC9B52BACBBB25AE610E3DD7231B7D3287C18A1E91D8C8C444E7D1669A6D5946FAED4F1A02F59D6D3B48730443E760465D30F0A5DD82AFBC71DE44DA00E1531C7819484464FBB9436FC097C72968DBA2EC48AED99C43A972830C2D26C45AD0BA87DC49469D243003361CA0C2186A2CE82A185CF1023FA859136105E8879A5EA6A0070514BB102D05756DA97004BB63DB7A9D63A7B2C0ED058DB52CFE91787820ED2B01D5AD09460BCBAEB5ECF860A0642F803463322E8264D3B71C92636150BBCADEA00B10FACE4A0ADD9FACC58EC75785309F4073944664FF7AFE72F4BF17872AFA63C35DC83C2D3EB95A423188A4FF2987CBB2DF3A8A98C610DD8842781A10458704872CA5ADD75545E95886B1AFB6076340B150C3D4FDC7C86548B5029AE618B3455BB6F9541F711E618D10F1FB7D36FF24D985EF1FC285C19B4820142A562D154681364955F58AFD6D68AFF9D78E16C0170BEDF2520A71F1A5352E9A4B3DFC56A7B11E3A0D10FAD5B262382DA9C766AD731A9229AA139D74261C9DAB16DC6F2FFB682C9D9B8761533AFDF455327B651CFC894B53B3983A35BFBD2996104557BA9230774A1AD70DA9C63585645F1D09D0CB6B672047AD6543BD061FE00726C7CF889C7479EC42385AF68E8D15BDB1FA997F94FA11BA79D3B636CEE05FAD1B297F20FCA38C8355EA270722A56B1E4EC37F0593AD92396A89AB58BAFEB762DD1C75AC3620A837556A953F4F1C9EDBD79FAB90C45A53B268EC6F7F32C6F7CBC709E686322EFDF00EACCE0744D3AF4ECF0EE92FA206238CB0ECDB62C2CE49C1470DC6125436337D725170994812473401AE612F8E00904076067295B22DDB00A0ED777FC3147D98F002E1AAA87C2A0C10B62DE26BA9E17AB80F86A78D4641C5799CADE9856BE8E449E363D4B473B051FF41CDF3B7FA18B695A25B739EE81E7B20D6AB53F7E8727C9CFAEC7A5B595DE50DB4063A53DA0CC2712F6602A91CB919EE857DF8AEBA8EDE881A3BFD16062A1CA1A38D1A4E7CABB27EBB4BE83167EDD2EC2A0D5693CBBA969320B406A29692DA38A331C0E521077F9DC3EF67B18A8792505D151A96C7B343424A31695897B5604B38BDFE46515013CCFE3A00DF4A23E7BE9C0DD3D64F881E7300AD563A97201358D5840447445DF2FFD516FF2F687BE7C48880589AE0B0F47A6558CB08A5FB488F58D7004F825DF459C502501DD36F951301BF824B7517190066CE7DAFA7506E8BACF8993221C3BB3B7D9E56CE0CEC653DFB504F85C4DF39E65CD1DFC44EAB490C1252945AE8797B4ADBB8B2F5565531E0D3CA4F52973AEBFEA06250F6393B6FB7D0AC46D5368E8A688AC8C23F35A1A69218760C645693373239DFC9CDB7949E03464B696823AA904A8A94F1DC1742164C3B32377F5F11B3145333CC63B0D18FE81D60C70B58C0509112DA6166A9160268ED85C76CA1BE9F60FC2D070E413B99BB6621C39B26D2ED8BCCC621237FFA82C093075BB230867B335C40F9184E6CE31A45869EE0DAB81C16D16488A39A9ECD12E310E78E5603F394DDB1FD9F3B9AE9F78FDF0EE4300212CAFB5F1CEEF54E169CB8BCC4725299CE94E3FEF9F9A09CE7BF3B55693A876D45F5B5018F389BD07943E4D1A8652E0A3545F3F3B4987509D47B97C5A43B60A54179F296BE68F643E1BBA23AD621D27F207DD2379EAEA5EABAEB466C6E2121DC22B1697EA113C656ACB97253E50884CF524CEB7B9F5B301C6DABB4DF8B16A8D83265C6D4EBCB49DBF176DCAB29B1E829C53D0F81603DA49195E7455EBE728E318415B24FE4C0B0D5F04DF203DE01693E2E92A396932C6468F227C3F464694792A35DBB967E9450D6A7D3DDF2075CBD61A273C8E25DC041E906D02232D935BCA099EEA9A076FD50DD340C241884F385A24099F8B4D9A6640A7B3AD3594795939753BA62230AABFFDE2E59F32C4376FC2E2426E37C08DB4E666CA459A30546092F04374B20F113BFACA6C5A737E8E3476231BB3206CFA10590B5AA5C7EBE85FE42CD37D4D394A0F42A8548D291331D54A072443B5273FCBBB357FF75084EDACFD163EF98BF4217A17A5EAA9BCBAFA8E27460DC7BC4BE685E09E6C50BE45D128253C14532EE7789EA93BD0211B06CC232FC21C15D34814E5FBD5B403003F9CCD2E8501816F5AB7DC9CC7F6F1577E45FB8AA44967B18776294F0FF36D171364B0CEA3ECEB0E1A9EFAB10B0124500228E77D5BA08C9942DF4696C0AD7DEF8CECE61B6584FAFB4713D +smlen = 6510 +sm = 19A407BD0E415E078CF00719FD047991595E74E23C5D20F36810C0376EE9AFACAA582D35F39C0A0E24856D1B6D0A3B065F2FCE0DEBB37E209DD44F61183E1E3BBE7F3E68A035B94B35BCD89D3372BA5B957B6E16B67D72DCA6AA27B749083363432FAFA9B8D41AE22260DA711FC9EC019996CE4B3BEE5A4D4F8FEB44A1D23DE2D817F9BCD47766F3EFA92618EFEB88F7238FAB5AE736C2A0B8C9456291FC0B3AC532159AE444714A88AEDE2B19715AA7929DFEA282E8E45D174CC4FEC52818F083A6A232780A7CAD9E8CB48E69117C07DD11AC77AF132DF4EFBE980D0FFD76143D3C16BD30908151BE8233FE6BC2F97A78EA98C63DE76F6931949D4F8C7AEA71ACC418C58265C6A14E45C7C065483000DB7EC4A905BA1579472509E163F1D9B5876567B49BCA7B9A73BB42FF4B4A1AF22A8DDB2A0DBF1006227AACC4FD743234BC6E20F15980008FAFAE560107EC9685D1B092C1AE1B5EE2EA6CCB8AE4D41E662868338DFCDF34310F9483E1299A40E677661E5B8629C814C6F45F70F6AFD42BC112FFCBC5A903E22A9AD423E1E260A8DBCFB77471443B737052AE849621BBE8CD9AA2C0620629EF7D73BC86D7301644D90B5BCFD22AEA907247A18813B293C6D09F5347E3215C85091AE9701447606019CD169B5F042448FDC90F698DD13E96579B24B711E3AEFB98EAA584589F02623571D6B30024BC182E60975F3AD3A1CDDABC9D3C6359E2F5D05D161D43A2F232CF914FDB5C73B4E6BEF980FE820BBC4239A8FAD759FB82941DCAE4D0C37461F060D75B052B11E1FAE4D8EC2392DF5721CF727BBA007DBF68CBADE3E6D7DD3967EF89CA7FAEF79E1954CECF5637F01B58D36F0823BD899A0C56243BD9DCFC002283AE8FBDAE632645986571A2C2FED41D48D7E05282416BD08716FE2827A02B3A5A40EE4778CBE5CB811185E4D39407B9550D9984BEB34B3D0F280644FB9B4E0EC65F41306E216615B484F675B25A8E7A3108AAD7E1E3501A4BDA43EEFA34427F27D683E005EA4DFBA15F4D30D06B75A8FE3BF73E6B099999ADC488BB7C51DE58076EB1360F5933CDB1CE9D3DECC1D38E98F21D54209904560C652D857AF30D6A03D9B89BBE0E91E380BB4623E24AE30B347AD64710F80FE7C604F23162681B85848AEEE61E2F94526F0587420449B5E3EF92DDE5DCA0E582DDE328C132E8AC2A8F0B09FC6551798E2A0C6D93251A810D2ECE3948031B9A91A27B4BF440A7F3D6367EF89AED1F41A8D0D23363D00344A66DE146650D3F2C915CC93897F81C5DC8F24A341344847FAC8825D0BF3861D260BE83AF8E996F7FA7731D8A6E095F451DA4FC16DA94F74C71C6AE1C39C49773F17587AACBFB9B38C6934E300AA3F5331B8E9259370A83239964E0279B84B6698A6A3C6BB6E4C21353741BEE5B5CE19DADA104C61DA252F66975DC69AF333DE3DDA26BEBCEE8A53DC8C627ADCDAAB30CCFD06CCC3229DFD5A34F307B0EF1E77CFA86360F6E42E2A09B589996F8A55BD088D237CFD486C2172DCA0439A6BFE4249052F68C713C792B91E31AFE964B6F4112BD7385B20524220A8BB86D5FF83963B708254A2DC7A4D997F37745B9EE462B9ADC55F55D1EAAD0E9A914F501DA8E1BAB8039C4C6138167A475AD222788E76D8B82C9AF70B30DB8B77A30218504553031FE7F6B14CA88669D817D3A557663EF7E741C6F01542A6707C3346D10B0BE04ECE3D4C4B97652A94558E2330E912DDA223B7DEF06BCA8992B3E57D8FCBAB9EAC57886863D5097E4F43B552CBBB80E232688423E56A05A6DE1991F82F0FAAFE0ECFE8DDB1156FF528F96E3AB7255B67D35BDD712C1DABB8BE442E35A5E83446D15741914831A6D9E141FD5EF2CCD6AAD5AF3E9C2600F4CB327AC571BD7E73F65D4D00C89472AABE1327B0235BFBC9F73C982BD6E383960604CEBADBE711B39CF84DDE24342EC01FA619D3DBC8E6CD6BE475625FE9751E5D55B982E2A35FDB685EAC92422D878599317A7C3B3C5D42302AEE9F0E76CF506C41447EB2E0EE59149880BDBD56FF73D86033C0DDB1763455A2B532596DA1409E27330CC71A4325E2D80EC15E1EC5ED11C305205BAE1E2908BE9B3D15890D5497FCA9004F10094E97BA8C85DF05BCBE8E104BE88D313CC53443C75F8BCED327D34693F00B300926307E39DF37FE59952FDE4B89B94C05FB6EE0C83D68BDDC4CF92C849938ED6678289B0EC3D45B21AF65755133C4F6FF1060969E3CD22D6844286167A3243D25A81E85E4589DAEF0697A11ED3054CCE8B23E94650FE08C355D3B309D702D6274E8E1A416A5222B9853EDFD66FA09A7B01BF7FC4A8D310FBA5EA1FA53B1502DE90B7F1352D2A05BAC23DC1891CCB291577ADF3A69164B377597022BBB98806084CB9B393416B2BEF5CBE5E901F04FC1284046081E7D4D0A6A57894C3EC36E97DB046896E392D335E78DC3FC62B8C98064587E37B2453A4FA83BC9EFEBA962E38B94E70B8BCBEC667FFB30BEC10A097E7B233EF69F3EEA0B08925628E097047EB7F39C9E1A77E50B5B753DFBD5A8FA8347BB93C546A31EDB7CB71CF9D8569AF9A3EAAD4237CC92F8A8FE078C002A601776D91A0BBD5FCC031DF203195980B03C133362798864DBB187F1A3DF77103646545BC042F03E6FFCBFCA8B16B130B1051F65C9FAE88457E3E7450080AC06B92A14AF1672C3374BB71F1781AFA00C75F67F4789C651CB32D5AC849BCB7F021D608378D65E7B2383C012FD28A979FA8400432C0C2E361A68D6F7C015AC2E9691F67ADC2386722FBA62FC1B551F8CCDBBA61B1C35DBE3C3DD30FB4786BC7632DF27FB3FDA06A3713B9EF826B6EBD293A5187B426D61E66A14F7A0B605BFE0BB89A4403FFAC2F487F44063339F12EB39D051D5BB64CC8449019166DEAD34201C08F9DAFB01A07DA25904880858616CCCF0DD3CD41C9EDD674083AE9AF8FD7A765FDF7916A0D1BC2F71384B09E64A45395618AE440DCF30E00684DF1E311F6D11C2C355808B7ADD83C8A3CC9FF9F3F2DCD5A81861A6A13C33BF03D0358C911CD5DC23DBBBBCFA9E6FD3E214B9C835533742B6AEC2FB35FB3DCD5DA85C7200DC643D4B1D887BBC461AC159C22684C76F607B42585A1104FB6B6103C3860E42253569D1B138B68CEF7994D9FE3D885C9D3FEAC7770A115880CBE0A24B825B8C0811EA60F42D09BCF9B0C63DC1BD0766DDA86D1DD5A31C26B902501F12609A7137AED86C015F1F823A1E58AE5B2E8BF695ED3789BB272CBDCFEAE6E96B919D8C6B35B066AEFAEAD4BA54E886D89EDAC51EF5A9517C96885B9BB96942B63F04E5271C4C458C76F56248A42EE7A35DCFA57B0DAABBA42983793B051ECA89459FEA74B28C809991236A2505E6DDD6599F6DAF3C6C3E1C4E605B90EA7F0C0C86BF9AB823E5653637EC60C5E23DEDBA0339B57AF06F4B3C3018FE6695DE59B99F427FA1682825D6507817AA2BE02500F0F0072112E6CFAB185C9DFA3CD03B3AF7477BFBD3CFD53AAC76F61F3E70365BDA63C88882729650B2047A052B2F91C0F76B6153E7F42A54F1D845E3EB019D6105FB8406ACF46EF79AE8C8361C86BEF13C5504C5E150CA6857C78042DCC78807F29921DD4781805FD42BD793AB31ECF83C7881E0B879E0EC3F4E9765999FBBB5FCF256694875B3F649512EC7D54BFD003755C9167644C2EE926C15D0D8F3AC70FD0B91F48466871384F203893E25B5E5CF024B37BB69596FDBCC65EAAC8A18CF643DFF9F2E40DC144388F51F30F8875EB48F7E7D60BD1E6BE94C6169146D99D1E51C157D03FE327BD8E04EC8233235FF05E1C9116625469E97FB40746184C613701500DAA045017B3E7B404DECC4081A7DD179123CB0E630A47F0E2E7F5CF5C26693B531B24B24FF1F878C38F45695763592C866B92AFD2EAE1A02AA308A6E94EFA784AC1041B3F751BBD4CC65BA7BB78EB272ABB0C5CC7388C25A776C7D725E9AF8A8B07A6F881D2A6A9ECB20CCC3636A44FF4393DC7B61C4ECA82F8BDDC34389D22ACCB105DEF0CE121362A25137535F99ACB02BCFF573189A7FBA7072F24A5C035CC43FAF11C1EEEEDE3B076B209B30CD298F4C183506F7AE1463A19F095B7C995395B410281A4879AB8A8B36BC944A212703ECDFBDF55F2050384ED1FFA8787C42CF0E12E49AE2554D6F56FE7B1094DB5A67340D87762BAC9E73A0857843F3CFAA703E9BCE8E1220D392DDB9989BA224CC2C13EFE00BA32891BCA479B9918C56E3B5FD8076C5F0E4327C016F9BCA2544C3D4E716E03CD980BCE83997490D74241A6D44ACBB2B150132923360ACFC269AF9BC91131DA575F2AE68B10B2384C27754CB7A0FEB175A11002E4A337BF92AE4C3051116976487BA9A624A76037A3D0D08C918F4ED146C6A6DD880C23C30EFFFC516C06150883DAB9FAFB5B2AE3917B2741123F2B3D9A1C396A49A088A29C9AEC2DAB654C590B7BA3DD7D629021BFB90E0491B34253DDB95077E0A39A28643A6D2D81A1699B746516BC5E085C15AF7DD92794ECAE7E5A087357AE92BD2A26A7272A6BE069E9A0B8845E94FFDB9859B0E91BD6B8474BC50C6A6E2704D1748B9ABF629D8409A59D76F271012E9496C000418599AAC1F8FF1719336FA6AFF4060C7890F21D8AB3C3FC292A477A9EE2E4000000000000000000000000000000000000050D14191E25DE897F02AE7292ABAFA6A0CAD52929113410F2BA972B4184E894C4D31081420751560956F49CE2B772635625AFC3CA6698FBFDE4D0A05EF243DF190BA1CE780EB572590E01E6E283E1963F2B0722B0CEB365552F65BD405F1A284DDBED07BA61C4453D30CC28C83E41590E09D7BB6932D231285205D61332FA9263B8A2D3D7F7FA20F521CA4B49F249896780E08C2DC41669BF0777278F87BB1F72CDDF4B998062B1642791F81AD474D6D8F963DCB4458CE11108544C41CDF19145B77038C7E8ADCD6501508C53B25BE6E787313018620D1BA647CCA4A5A8399E11815EAECEC6AE66DBC576699BB0AB44DE111AB6F252256389EFDC0546E641DE87FD6A3A724716257A9174F39542539A593864441EB79D499FCDF2F1D053CEBB3A1FCC09419D2C553C2265B3DC3943E0341BB49130E9981EC59945FA0B23E9DBDBF352ABA0D925C4333F2EE1F2C83C847EFA78BB13263B893D7CAE029BF08CEA2A5D1B5B997E403A489C6D9A124FB8386FE58C2476894E7754B8E5A162102A119482B5E59F8D89C8B1DEA70B6C80641C77BFD12D45C5B3CE0021EE500A1665ABCF740794E0D3E7E8CB5804A1E0D0C81A107DEE80BF63BFF8CE2EE2DD602DF279DE39C579B417A758356D2B48B41E83495DEE9ADFE4506E03F19DD096E81405264D408B2FBCDBF41DB5CED6FBDC2645DBEFE5BD038382993970C7686DBA3FEDC24E1F91BA4B6CF70B2E832B97BE24B6393273A519DB0B4446E98D77E86CCACFBECCB18939013C66F7A29B10DE2E88FCFAEF656B858B7DFACC4F21EF5F328C0EF604FEDD993510BA40530B79525FE8D336DEF0E5C303539E664A9360EDAD7268F70DF4DE199AB3F70EB2BA65E2752BF5FDB1E853E6F4EFCAFBB31D8CC23155413BE31082DA958B01682894A9057CAB66D4D64A6F3B1D81C5B75815A3E0CAF6486B17339174276A84E11C117B060302DC2EE06A03C0E15395C0DD32661638F059A385578C1B792349A41C511D12AC7185B060A831EE296E6626459C2750FAF3AFB579F6F6836D566C00C979B5130E8E50431E914834CBB3D26F6E5BA50BCF05D50F699FAF10767AA2831C3557A53AF14BFD9F23C00F76C2680C7DBF4A9B2A425E34C943228C3EBE55A0960ACC757D7878F7943E2E8A1CBC8C0D2139A6A6459D3492A1A7757F71E90A58A78E0FF9B04D059C5D131F6E3C30742FDE5506AE7860045A4C903DE96DC43AC6A69273BF8EDAB7E7FAFBAAD9EFA8FA609961502EFACCDE63A6D98D8D017075487C608FF701A7E3381D7A2ACB134B198950ECC6970A75AF5625FAA4EAF968CCE48FFB673F4F365802A984C609C33BA312140A60A6F0924E945D11BAACFCD643C874D352A90367EA4C59B63665364832B1A9A9A01EDA92C64F393C357158973FA7C6047B8B5E27EEDB28E26359402B63032F8B230F5AA968272819CA486A8BAFD3D66799AE951CABF04EA81E1E7E4632B915D4E8387C7D1F4FAFE1C1FC8666FE0318403EA0027487E947D844A7FA28C0523A64EBD95D2A8ABF6A71FEFB5BC059B2CBEECD4375F3A3F109DEAD98539244DDCFEE9E42DB3ABDAF943C445712EBF19508A1FFA6133C5078C1DA69A32CBE729A8876C4C73CB232024A87D87FD5F9456D3D4A936CB4CE2E00EF415406D66D344000A4A95CC9651425A16021336C4BEFF310210324C754BBE13CD0066C507413671C80CF492B4655D898A18A2F4DB5A393400C6AD821580B0712D6C919C62E87FE212260EAEF6876C409FCA1047A67B223E0766144F3F676F051FBE912C4CE4A9F7B85459DA031EC47C621F6EF06CD1621421FA52B047B51C944DFA94807083B4ED40D533B19813477193D1E4E96C8D76A5AF3100FA44A985A6513060B08A7F3848159B3CC551D43370B223037753B824A099A7C7DF59305BE09E2E79618C83818BD542F39380126A927190EA5536DFA63B664AA7601C6D82CDDF4CE4006E1AF2601EC453971828CD09C29D2F3EA6392B58D38BCF40BF6B6497F6B848CB853B187610CD23880CB09787C76087356C66565C0399BE746A81753442E4AAA54E84F1D8C2CCB2D00A551E960203D61E71A72E131ED1967DD06E72C99264EF2EE5BD156FC869B5031BA23A6D354D7CEC58F339F6BC2DD1C547F07AA733994860197DCE5BCE6024A74668ED89A2C9CAFE1F78B31638C3225D96009C260FBD28C1F0423E75C9C01A0F9E62B7F265FA3817F441F56AE79BA54A0C107FD7946A2DDDA60D0EAE428715FE2B4FF93BEF83CD10E5E17760FE028F1AAC8084A43EDCC12BFD3265D13FA94D9704809A50881D48F0080A976C5BF31B353B9043C0F0B69AE6F2B8BADD056752F2FC9E90C4B35850C2D45B9F354B41ED7826B976528875547A0C389B83725E26C006CC8240E380E3EB554DBF2133A131743539B1D174CCA6B135C59F81D499631BDA4CF90DED836E8C24C074A0BCD83271309FFEF320791C9030FC2B1F53FD2DE870E54EBA20CE9930C279B48B39CB481737F012F65933650374BA39E2222191B0E3C7DB9632CE9CB077322CEF97ED832DDD8AAEE53C52C03D2AAF8EB5597D8D6467A406BF428E2F16462E0C0D486A1C1C7348CBBF92633EC4FFA75945025A3C92095317E32290D4CBAA6CA40F3F201975F3FC8B733D1467C094E075E8415352E3AE51A6C5169A4AA430BCD66FF39B184F5B7174042DFCC6840EEF60CCDCAC12D012AE4F24F7184A038D8D9964AB405366740600B98CFE2E4737C8D846FD4E9B22B5047110D85B37BDB9E7E3BAF5298BBDC1050AA20F14E34DEC283830F5FA9C570C22CA659C1276BE8FFBC0AC3551DB8488855AE7EC21E239E88A0F68227D17DD87FFA3B3D0535F9E57807755DE56A65C0DE9F4A79F8746B20908BF9416A86F62EE2C2545BCA2D55CD4D45DCDF06DC879E1B6270A80778D0274AA658395D800EAEF367DF4F4D838EEE0A66093E0F419B9EDC5F003E31CF0EB7E1CEE9ACCDA7A2DFC920A4B5222389DBF12AD17392850C434A9B3C260159B0F52E78E7A66D28DD5B3C77662CFED2CB3DD5BC3CC26A34293EBF1FB3A9BC59BB0C104C5A9387F3893A65D145D424CE741A375F9C65E733A024E78FE274B29FF4B0EB6F21FAFC31453EAF7E48FABEC5711D3898B876F59952C73123281A8E85148CEF5A166BF45DF36053D57AE6F29D3E334BB2395FA236D4DAA8A4FDF99D80A9BCDBED36154BF4FA3D463D51974032D7B88B2504317E14165B1C3FE3D8FE366FC8284321D80F9CF512F418C63F73B7C29C07870332387BBD1A870AC39485F64086006CFD68C8299347615A423736C01FAEF2DA56CFB6FC966948649324E22D4551B9F50654EE505547F7D0B8481ADF6AAC3977F49D7E6AE5C4248DF7B43BDA7F082AACFCDCF1C1BC04F2D45F5E028498ECBCA47EC4D1DDEB03A2AB27BE9E4B80585145676F8AE7A5017BC5EFA317A576ED6E423D5A0495B8DC619712A2C3E6162B04B9BBC7DE4BE6532F6C1C019E702C014C60189A2612594BCB18317804C630264D07B7396DB562777BC305B885E00706FF6D0208737BD229BC7AEEFF5FB770A4C057B347601F1F6C16F60D4A53A0B32631AD2D41FA307F6630228E1807D22475D5E331A50A680896DC606F3941AC08F8BA46DE5A49F5ED6A94965334FDFD69C4A6C7973D9615B3FE576B15AACB9B98D9E498D2A3A89B4F8EEE715ED5F29F13DDE7629BB386F7CC800F16F3B5BA8BD0E14CD8D9BB0F0AA615BE9D7557F6EFD00F7BBEF9989E7F463279408E6AD77E100AE4457D57424F2B1CAEF43052C5B25C896BAA1C2FE67D1D6F669311F17D39460F0B176A7727F53257A36FAACBF3DFE623D8F882F8EE41BA1CE387E1D1860F4BABE26ED678395B9979D84DEA5C7B38905D4C7FD867ED7722D066BFF3A833D3282BB40D1CD310DC8DAC9270A49B65B5181EB30F166CAF0832A8DC56B9D135550B506D98D036BE7876836AAE669507990DE6D03E78A38139CF64F65FB410F192E30B045C93FE259C10E0C5B56A2B5F0605DA0851104C4BEEB4E3B30135CAE5A6C68403C63121B0993832834A3B5EBDD345C41B26DD219560B624024B8B945A10D385B3CE4E0BD54E10A64ACA59D283302028A9592120D142CCEB1CC30E1F96AD041F1E17BCDC3C68C2EA2E0D65D6BA3696166CB365CC461ABC4D67D504E8290EB452ECB77F6D5FAA5053D01317646242384C5C510BD43C5780BBD01EBC3AF33D29D8A09EF39AC85E70398D2A64DFFA72B3EFD8D6D57AA2F9DAC0CC6EEAB27B69FDF2403A5FEDE0BFAF441619BE03FDE44C49FF0A34E9C37D2B9AEB726D56EB646A67BF349323F397DB056D71DE72A2597D780942554C8F8273E307DBA6BD02E944E0559509E1F28B511BD709D03EA2451EF234DF6F077E06AA01E2806D5BDF89DF29F1B3D8C6D8014496AD83857F7465F1072E88709D0194733E1FC8C9F092DF5B9802FD2DDDA8B142217B9532D8604E2F32D06F6400025930DA2BE9B25529788E6BF4EB7F84C272DF455CE2ADA291CFDB5FE815129E4AED59625C879E99B3E3C1B6C5D7 + +count = 97 +seed = 13F1F446D9AA5AC853278BF74C9E6447A6CE4294C037867F43DF554370EE261D05C7260EEBF46D6694D0850B8343FBE5 +mlen = 3234 +msg = 525E8B98C55864849FFC71EBC953F7A0ECA6298F6AA15A83BF6923BD5921B1C86DBBFC544A39C364EF6D9281481E946C994F96829D6639727A5345560D8641E9A510F913F7FE5592C2A40CB278F5AFD8D4504B5387C20945654F08168247A98F56A43A5020955F882D2D93781F4A83676B08F50341E953A5D1B67DE7F6D1BE3D78D5D060AA85B5EE4271763C437CCD595890DBC8FCFAF2754AE9349BA2FDF89847A15188716C0EC672887A4B9A15176AE0C5138819CA232D012BE1DCFFD29F677442083087C127CBD80B0D9CC0962BC8318E734910D1E2653BBF700C84BB0919E12DF331CCDC7128B41F0666F6419AFBADAF673BE16C9177D3CF113C6488504DE088149BFB83EACBBC400309B7AD753F7B2F5AA89F070C9D14C084C32DF91C5F7CB6A7D869D64F4A05AF80A98BE7517ED784C17B0D7DF96B9987B7EA7A398CE018AE6E13E1C0F7AA040AC3FFD273BB9687AD6FEFDB211061A6228967E9DFEF69BCC1C5D02EE56D49A93C8AAD46D08322A2CA246AE8C3EDC071D063AD605A97B8AE94D58E897A4A6310BCBF55B0CAE1AA81769D30B46F883EAF29D4B5FEA32F2DBDE49360CB6235754BDC305ABB5E5395360097378656E2BACE675448889B0149D6086C51E9C3AF07A76563164864F131CF9C0CD475CD4A58726AD237CFB76ACA68032351FB24711DA635871386B4BFC94B0DB6D35F07D0196F75CEDB92EFBE7D653E0FF9326A596F9166FF6CAB73125DAD27F361D6122CA531D86910187E75F849EDB52DB26C96FDF05925DCCA232480D3F979EAB07CCA68FC9069965D12BB666A180989AD1FBEE3FE65E746C5A8F64DAB2E370F0487D001121EDD0D0D760531AF46DA65C75DE11688EBF31DD2AC95C188BCFA07EA798609F3EA8E6364A43742A2825144FAFC05ABD17476480812EB2483734B13D075B3EE3AD510B67CF7057014351B2CE5357E3F12F43BA74CED614BE3A9AC0E26763E9AC596F87AE98F72ABE0DE213A81A9A03E2B82F2312C1A186DFCFC3DB346FEB132931C793ECF837F57D8E326101F59705B77A3083E712CE347C2C29C23468B0C5857EFA410197833987C61ECBC2A855EF78B3D7B1B697AB9844AAD07C4B8EF666BD80DABA5FCAC900C5D358A11676FFC89DFF4F36F29F14D9F9B854DCED41FFC4B36381449D22801C19BF8E8BA1F07A1B38FFB527A34D009C4064A1E606FF2AB90AB2E05C156150EC14D7DC792578A16F46650D0ABB61175D1817E2C38F109EBC01A3ABB358673561691185DA32EEEF566C1BA1C72C1F08CD1B427B552425501B8783116F2EB0CFF73C5D2DEF18D291C106980135821A77428FAB20A935AC8B6DD8EDD1A936225344EB103DE0D5879CCA09359B5B882291C0FB1FCCF167C30DBECFC324AC315713CD10F35B72F0D4871A7CBAA2B4CC2BC2598F23DA607C94A063C9E2013B0EDA5F3BD5AADB2C429177A4BFD7B6181ED5F9A55C1F043DA8155C9E7BEBDA7EA07DEA49938FE07743DF2295C220EB53348310842B1000B7A02AC025C3A94FA82D46ED7E2712DE71B149742731EBE62E225D21A7F29D5F3A8A62B71FE16258570DA412C07CECF82B2064AB5D98761C69FC5E899A8E174875B3179DEAA0BF4A0261DA9BF39148440DCBEB0C887E41FDF751505DE79AA1F8593F45482B659F5B5F4CC3E7BFEE59DEF49458DB195A1A692B8AF4AA44CCFB00B753AC761181B8AAB39DB82385AE776CFC585F7873613B62DE55BB10A6B2F27E631CE41436C3FE390163E6F4EBD6B501519C96C06FADCAC8F75920FE1435542FDF535EAD6C0E3F41345996063B95A208DEFB6F110CC861580979BF4422ED395CA218CFC3B22C0BA8B31CB9EEEB51C3DF35FECE92795CAFB8440F522B44E21B3A18D5CDBC296B887A4B927F36715E4AC2CAB043D8B69A8704D6BE24C725B0C2E814BCA7B040C27FE8F4C14911051039AF13F44E0485EB767F5404CFB6FD19DA24D82FE24B53033C83DD8634E2E28AA330A81F14BAC1C57DEAD7FFE39994D9D094383E14322E146A3DF27A776E2F09A11EC9014C809F8E543594D6B4814918A129B36FD25015A044E04D3F081D4D201DF86A0FCAFBBFC695088170B8246776B6A28E59449C646D1E706CEA96B12683CD3A7C60459D42989CA46694B0089CF88E9AEC5E110F69FE0E3FE20D18309D1BA72A83A34813B771484505B08548FE5D376AAA0C414260EA4BCE5EB81F6545CD5203026264938905BE1E252574F4B4E71C6E12F99F6EFD35EFFD64183CD0665FE89D6A357B1908E083511DCE2CDF792A608044C31418C433F86719E156AF3FF98D0F54EBEB9F9FBF24588A5557D310EF9D7CF5DD8A68512D8CB15114773C69D7B40C927858AFC049F7C6A89841020E1C313C5C38B988EF505EBE6C15FC1D6CCD8B472F90ED64DA895D06AC01BB99F455A195A670D22DBD5E3F03AC84A08831E9842A566E9785A0FD4C460C5CAC154D705DCE1E7FD1C45BAEB23976AF881CF5628F3CD92AB19BAE8D45A03A859518E4A1E558FAC2B48A432E46CF274E6496B63874CA4E4571132568AA43EEC3D2A3948F40D327976A6D28CD816CFBEAF8FE126913384061D219F51179F679081503371EA0B6BD7E9524B0ECE2573304ECB4A16EB471CA0817C0C6EDE751F283ACEEC5A60C2796C6261FFC6226E4813241619F465DCE67B38E1D5A647B079503144907307C7D6EB6E6EC1936B5C94FCC08A882B4555B19B33A9BF22384DB38473A313966D157DAF8AAD41EF67D3A5FE723559096AB1768FF69773EB9D5C88D6F35F00DFA4473DF71C7E9E35393638DED05D05C105CBF37711D38E3EEE35E8CC0029B3761241FD1E56969E09E949690D4FE25735D774E777A2CA17FE058E14AE6806F611FB1E9FCD516E20499A704B67990716703A4287B50AB45D155D40EDC0AAF97F5B87551C236CEBE9CADD562B27957EAD251F79CAAC6433F228B50167FB1A753306FFF08B53A8A3CECC226857A321700EBE23AB4D6C35415CA79B682D6CFEF6B1341E7CE00CB9870F432B63A2D9A9A43C87D28A95C514582812DA37738BDA6CC76142E08F69EBAA5ACD0403100C2343E2FA088441E9A55C720BB509BC3600C27C1D39157E049650D1749751EFE55A72349E2A5B714556CE2188CE972287BE2152C7E58D3FCAD43A214A4095DE55CAE9F627D8B9018DAA01547842FA1AD14D67327CD47EB9B90CD94AFDF5244DE57E527F17894A410FB4210E06632E88A398400B0AA48CB3FEB9A90ACC668615D193D5A98158092FBB59AD2D6D4FFEE433A2A6A971A228685AE5BBAFB3AB28242C630AF4656C5071C545618A0A765FCE41B19970C2152D44C349D0CDFB29673D1A42FFEC139D1C9958B0962F7B57F80CB8FE6331553B0DF93DA9BFC722B1C001F48FF9C0FEF032610A1118AC9EBAF9202DFFEA605272A50A90768F031C72D570C0AA5B0D4FEE4AD568895274388104C0BF88D03FADC3159D6CF28AC6A7E3E5CF6FE5C6658128CBF81456DB8C29A76F9C75230F3837F1A94CB83C3AAABDF4B29C9045B45AB9552BBB6C0844BF2926267C0D74D3337249D5C9610E0F6FFD0278F12F39C48650C048D61A3FDB8E1A2E08CCCA68803A55B39BD39160B0420CBEAC7D8A55F571F490F694A7AA8B725BA84238EE1E711864AA1F74AFF252C088E36B79B09C80278DD442EAEA8C7D5833CD1BAA18BDD866689E663EADD0EAA6E0C78A3E09DFFE5F6F1F4003DE24336586B25DC5EE45D56F31D8BB2DE31B24E87172F3F1B26D400B08D50FF624E456183F269CBF06B3707260383174FDA152E4D0C528A90C54114C4F278D0FB35B74DD3ECDA14EE89D38E3227A7E18B068F134B22154348867A61719C926EA3320D1BE0B9ED78466B2DED728CA04C15AC144185FB2F5084511A38CFD765659351AC1AC3E5F327D9F3DE9B2B003758DA78DFD08FAEF3625CEDD87C8A55A3CD0257AA71B3788FD2449EFD1F48948CB304468E3CA07EA7044FA185A2B91F9761C6532B9273DB74C66B2DE95AB19E5102CB90C719EC85671E2829B182BB6D09323248D6584F0CA67D422BCDA65A0146D8DF27AB4AE651706D5FA33B5BB88ADC2A1A95105D55CCA8439A5060D110760DEE8B855D0839053BE595278EAE66542736D25C93D8544C6E55ED51AD6E7029C2E6D32CFA8844BC14972809E31754AF84BB479C504EE77CB65CEDDB6BDA613FEAA2AE6598D1F4975D0FCF9D9DC787EEB5C03F8B0BF438E83C38E2195EF1D35D40F5A14E194BC1BCC64D02CA722E7DA28334E91FB6654D708C5B07946CDF58747086EB3CA59D095EB27F1B7E6806D3A35335B2265031A1120F28EED8B4C5D9AF268502727C5D23152149C98E6970D4DCC4B9D0FECFA6A79FEF82CB233E71FC8AA999DF66EBF5A1DB2ED1583C65803FA8958F49890D13BC05C6A991F26C31766BDEF9BAC601A47C8C3C5E395FD8F47E56F04439E9BC8E9B1901A529395F2D57495D70D0712881D298A60E3E013326CD56BF9F1319EA8D6A6511EEFF373F081478A51E14F0AA4A33C6C5EA7816380C8984F7A5DA45B0C4B6B550644E65A5B2DF059ED050936FE6F073B4E8056ACCD3EB65A0B +pk = F9CD5D926A9E205F1ECE49E62A71ECA70B60A94F6EA76C322121533FBEE293A43C71067B19AE4266D2161DCEF3AA3F334E1782202AF5155720C6DEDE7948ED029EC0B961171306CE354FFD3E52482758658DEBDDDCAFCD75CDA4B8EECD1C1620C2B08825A2EC98A45453625B597D677E84EE4CC97E3B220B5074A3183DDCEA5527B0334974C0209F6DE4DF3249ABFEADE3BA70B8EEF6A7E2AD7C3F30980E899D9040B728F90AE935C397DE75094F9A1DD7B58A0CAD48143B65036F7E9291A39193699A31E3DA6072D8EC3A4F531D21EBDD939B2DE92B2594ED3194011178ED6F8462141FF5630681EF937A21624AADDB1BA1F14675FD92E3B42673DBCE1E120C19A93EEDD2D9AF67E8F0293E8180528527702758489D66A25D8270C21B574FE4BC651B9F40DCE5C097882FB7822851F7A22E9577D71335BF42AAC9DDCF92E697206B2F81AC2E1152127808985F231CFC9C8AA99AE9509DDFF5C7127D14F2945E28836A30F2C9DD67A1A950777C0C26F658E538F84E941539854850C8C361E76C8F1A7FAFE0EB7500956C3606FFB3B24A94392DAB1E3C40C52C0ED4BC73769902FCD186425F0EE25B5AF419B673E6421E474B65AF3DD2D5186AACAE81E169C05980BB13668F436C0B05C0BD6A074911DB9E28F459BEBBFDEA05602FF69FFBB08FFEB288BC121A3055C99680A913CCBDD69A85A7C65C50C520A7AEFA915D8EE407C49872F082EEAD6A7C8C98EC5AD045EC77E1636A46E44A8066C2C60FBBF4AC9273CF3D3F2DEBD4F54151A87C7D90EEA7A04B351D2FAE60B26FA6298380D6D6F5AC7404003A830905DA731A0D4BD3F422FE1C6A7A9563E482E2EFFFE921169B22CEC1934C6218A61B82651B7DCA9105371AAA5A954A9FD8E16B950C9F55096C6BC1A10E6875A268D5FBEDF0859ABC3A2ED363B9C555141E45505013CDFD0CD1C51FD1B4F98AF77F1D89BBD635EBB5CB28D43387297097D3C5D91AC5B098801C8F88569D95A196CC71000B3A188F61313176AB191A8F872FC8F7D4CF522646ABF54E2CB4BBB327E9A1C99F4700338641305C3EE6A92AD4D4B9BBDAB057A23BF896711C4C7D9F63A21C0BADAFD2CE058E7AF439230E604FA728B5365D145D970AC64DFF27BF428E60C1229DF8200EB7E4865270442E21A7C25558AD2F82373CE1ACEA52C49C2C5BC8E32F32C1F6AB88861010888890BC37F839F0F3A1B00E4AA16F4F3091C218868D7CFA5DE7488B46F262BF2F8B9E0EF4AF8638EE4C46B5582CC1FE91A1C239384AE4E495E7CCF4354DCCFA01A38E7AD4D6CAD3632BAF3CCC23950AC974F4A4C125A9D8EE5EF4D4D871AD627743AD00D3F5296444132E6F7CDDEE2BAA1E7405BD147B266DCEEC28E97DF149D83A32F0405CEC6D83DC9EBB386607F4F49C39FE66185AEF949C608BCED451F0E7B4EF61A4D45FD2A7504A0972274564338779663EBDCEC91695B963C04495E07CB81AC4284A918341F19BFFF13FCA939BC4A8140992C7C4AF8BE440677C574DF3D3F67B5E8E3B75121DDF9A614A820FE05227F4BE4097E2134C33345446E0F55EEADB87F8665ECD133A321295F0E4FCA67FBF31E184B7EB99E76EAE0BE11FE0A94096B6CC33D09B02680D0FA279529BCD99FE900EDCB494D1716D2E0749B507D69883076F590183856D8A90D2DDAC653C3F7C290ADDEFE380ED71A1D5346D94FE8AFEF670BBF6F1938067724F5E2AE9C087948E6730C4F1F9FE43B83A7E26890ACC411AA8B1C35F2903ACFB447D16106D2081BDA50D8F27151D6892AE037022F1349A2DEC9F0A3D13A4FEEB57781F3C50610628E631C4C537A99ECF68470FF8301147F83B5E2FEC77CE4C921CFC451B38AD106C8EB0D466D7E4BCB13A4FB0C429668420A30D6732D669DAC0F75AC59483FC1E7158AC24A42B8DDF209C981131D499B7DF54C0ACFF2E862DD3FF5D8AE805E2BE8D9C6A6F5F08276ADE1561781AC3143C292B6DC3AC279BA0281656784D400FBFDBE422E03A6E867170302584F707399CC4FF82BCB566BC74AEA5E939C4FC0B5A2FE5CEB777E716EE29808921F7CD2C83801B2B28E021467A0E30EAFCF3E713C09D825BFB89C5C16AC724ECDB28D5D42511C2462D75DFAD8B1BB9500BDE1D1CFEED0C710ACCFC98E48A44CC71B1297193FC61564A2A0A13944846EA9C724617653B6611EEA34FCAE48F35AF7FC9C66CC832F4B112FDFC03000B69056E62E14132581907D9BFA5949B5C1E0A9E1ED216A2A43E94EB0C698388ADEACEBE066A5FEEB0BD5DF88EEF071470F8C79E0984982DAEFEF6934ACEB6C0177E276D67952B4FBC73A7EA97C8B08C3C290774111C7A9CFE6CA05EAAB9C21A5A2AE06C8F984813526D0774069B33A2F1BD9DB0509CD2ADCE665A51CF47E252A6304F513072D730BE732E5A3CB9FF3DAFDD7AD312D7C5B91C470111683EE886DCBD41C90720F653E012F3468556C20BA7AD86FC294736512E8935D082930D47F915757ABCED50B78B5980CCFF939CBB7CF518C69AB7A9AAAAFD9F5078B3F4AD4521C7A73595FD78421E6015A778D7EA3B92C5A9F09C47AA6353D64EE2FF80C965BFEBF23449DA86316EFC0B00F37E15A3917544BA000EEE42C9451DF101B75CD39AB4339ADFECAE881158F9CA60C5CE64B69BD6294EC09B4E1385FC2C50BAB83E9ECB8E8FB80E4126A8581CBB91391DB5446E23D2B7158500A69EAD47E9FC57747E0B40A3E4E0C1FFD636342E741CFB79DFF78CB7A0DBA3145415480FE1FDB15BFCC781 +sk = F9CD5D926A9E205F1ECE49E62A71ECA70B60A94F6EA76C322121533FBEE293A473DD5EA80733C180A686F4A953355B30DAE6C10BC0A9AD3764DE372E5D827E3319BFAC2D31DFE07740AFE4520E06F14AF8D29280960E5C937B0C617F24BCBB7FF08E6F078577B8012800D66FF71DA28E039AADE7EB653EBED35A8C296390C10533501866462785211014016614302067143840183012324552121473003521618438576250138722563587256028341563608670228654250615402684441152477067768276013356083068567486834187843443652635057705517515142388028834341427020583424687613622102271167374325515862584367504451660272106347104156767005511083043767278177634770273161026580648705537125750085175665416474880020363544254415310037503070260277415024524384571605038570170347347217360655845416882404216187104668603048313442001306741028437418543170751265557320527677727444485227057243126052321812070871834860257186302714186700113052216343323383751547686002215162036581858355244637660878281067485542452212746262750020236680442113673888080244413074511823852021475518412116526646515213135757062823471278345826547582553128530547542138635828182873370587280048882170875052088476762728741638836310558518177068531865608777072713752713343660477504820835372803352188360521613824328638475082102714020573530553272874772753414687724147644710664238844125204031705220225237845476756808752688383833087864273883042156700005611344718547678711730827061340131537477355667274541851813153037635652155518685184135356232887726140123201382081216834150004643183204474645734278462154322838083013226213032343115661704646631177630246503378641687700805147380236010633210221714833708246430703424547450123745744812544280862640104165435580564715672155844768736368857005221502123326458474121540824082525736532826340715657453200575431673808458430003684734372780673566041875171508867733856856340163606512485786842405325315548567675111441067842802155851681252080545382830626503760423161364826756476214854685668114775405263204716422752361001846024068208206042680123842276871378664502502033006818727001204707103201306412642104767300641880311603861044165577850100685460453530646448435371745435702016107315365862645664058024340461005512855572103240365503806515210774274025481805237270005857335805023044286860405605683142360201813646638535781116082780584838120666664066104311211274025653301800721421333035077515402532630163700267025061463344538736662847428835653615627804012634715875181603741034232621670850503878382445868807588451537518784042601568456440167068434701833006088203110848276740883507476133416110308740508371444438643328572513816620481561377672533846808657377477583781520266755857244173512672563544666672682770702731502188138786117313324208336602221885534254227183600754143415172256675504415624284455000616181826811881765527465231664378628408004882715060612363785830026384148014281253802815280227272002533162366647636666230504620422287023120066517472475581441804488850581750486123112031571803470526341508551345518433270276676375023122470215517660315186676322378561807223780881356357855848260142105271222486578452227765851552726882071410300570172266201155158782235020206858115680813254848573257331853221343877DFA2A9C7CB2A1DEBDEAC3D1A36B185432DF22C6D062982147E0F8723894BF273FEF3F82EFED51E29C2561F821E6CC5FD0A6D0A493C4EDBD3BD7CB9AF7A6EC5F2548FC0CE1438075ACE4FBD8A557843E03D3BE1AD0C33EED50B514F21A48A67551432AC7560502AACA58F515BB28C4617D0E0D24DF09C6362EF7C1F2D1A3333C6E9F41DEAFCB1C0504FC271692FB1A3BD2C3F06FE8ACEFAC7AE78FB1E61E21CB47A5B178D9A2F4CAE10667F081FFE373418CA08426805243661235A384E36C39A540D3478FDBE05FC306A6A61B964872969A0A916E6F39A7AE0406B770E1BCF96B5EDF92657DF13FA805DBF921C6DA8A0EA354EB281E65B814D47E947E0EDC397828F85185AC38AD7DAE7A30097D7C44B3287B9DFB40FA6FBF8E24BA418A85F8075DF421961AEF7CD2A77D41137105B6425A0EFC76B63A89C03B94C62D4C71052E193487F8DB66DEC0CC11C1CC1647381DF5512F24CBAABD7FA17C9FD669488BA67D6C24A8CBB9EB26491F7DAEDCD1388D4C640A544BFB5DE1719DEC78DBA865CEB3C4E0B7506E24D5992B76CD2418EB34F8D001DAFAC533644F8E12C3F032CB283D9EC64AFC55286943F3CE8D8725B463F503E68883ACF963C6637C525E71EB092E1E6A3DA835A5511F33CF18A2AF1581DAABC09CA4679BBB9907B12BED81B10F944C4BC765398BAE2094F6D3107CF1AD4759F2F21FB95AB4BF0189CA2424FE032128668A0A76EAC90DA94FE9A69E158B6FCCF50C71C4BDD22388EE990DA801C3F3FBA79A024D43A51CEBB2F09FBB730D448782C1E77C1B3B523BA4513F2BD1780CDFFDF818326A969BCD607DDB1CB8AF105E809CDED670344BAA40F93EF4EE1880AB962DF50A7502092D3D9FE21A0D2CDEEFCFF1938A4E1040727BCFEE1DD95BCC265584C87F4280DE66C1CD9D4A591EB0AC5FE8F4EBB5D6F49010B498D0E77C5DE3995412D837721A6A464D849F565D9960579BF4390D8C814CA2168D587F64248EB10069E1CA75AC77F3E16E81EBBED116E3AC862ED2F4EC64FD7C9053CFE869C419C963B9E8C33054FF7D17E95D46E648F4D3DF8F22E268A8A6B8E7A8DAC8153F4939C28A6571A7B92999EF28057F9A66A0533051635941A9C82B255AD0EF5C4C349CAF450752C27D16C7B366A00294346AB4A061A02351D6CD64E1DF5ACACD0C032DD99937A44990BA5D909D08EDFD04B9911F583578492988568610D42B986A2454ED55C86FBF79AC99DCFF72F6C0CB9328AD21235D3B7D8025575A36A58660A504FFCBC7A45F680B344645981353FEF1075ACDECA15D86589814EF071DBC19F18CF286F3AC38FE7FF4287FC4456B9C0D1CABB5081D017EEDF1E4BC6D1D817A148CAADE31BFDDDF7F951927FAD6F36BE57ECA5681FA0EF7D244DB0C5C8E5A3BD21E9E0C3ABFE32DF75041110CA930ABFD4FCB670A8A99FF4B278ABE84E62843EEB19D579EA5EF09F5822B1097ADD3B97FD3B941557404A91016A7C8618BE102231ECE2AD9A3B383FD310307EC011588B69EDEAC37B6E639BFF03BD68AB0C6F1FF5BE793AB150315E883EC1477F12AB7E10698C5AEDE88AE4B01C794A0DAD297F1C6E8DF8EB90B640DE4168E719AFF666CB117FFD657FED5A523967AA023BF903B27F05A07677817316D6F48E47AB6D0C48523D6F6B13366C7F73985B3E33FB865E17277612A3002B2BE12B7170315DC7CD418A18EEFD587517B4F547328A083FA020E1EA3EACEF4BB70471FB59DFBE7E7C64E8D0D8FF42C407CC8408744A911ABEC52A14FBE3A897A1746F18E01A0B6073F8DAFE200DA962DE28B959B1BC25372EE0CE011047D849D0893640282CBAAF8578D7DCE5C3610998DF27F8E6E8A2E7FF21CBB2B1E8D4A5207E0EFCED8101D7F955A8B5F0993020FC13086B94EF9AACE8DD5E75314DC7A6B0AA9F34BEC108D65C5A5B75D1A395B637ABAB0CFC69E5FA67414AE6D70855910AEBBBC0368DC832C202B36992A17ABB4401371BAE09D12C00B0D892E21E6CC11077DB1CDB99BDE5787615853165EB44783FC9E8193F1E64488F67564CC367CC4149ACAEFF9B6EAF7CB0CF04B50F18CDCB5976DD267EB62F8CFA17A10BE1D07A78E619C74026BC0A261DE043FEB7CD62A9D4E3E3E033793DDF32FF743F895C0EBDAA16E4C1517FB4C52A197773081B66F511F0767B38EA519FE4A61212FA11C4C898CD97C7D9E94B71F5BB1344C2DEC1CE78E58F2B858BAC1D57B8592F68A05FA9BBB0525AD05885760237712251A127FACA6BCBC2D05B2635784FFFF0EC1E15EEDD6FF6D8A16FF35292E93DD93C5B636B0B7CC78560D1CF3BDD5143F6FB3B08DC7C482B31ABA9383D09BA040AE09B231A314D74AC39BBEA6465C3318675BF15639701E5E6CBF94D7C1F97A7D24544E9129F4D68D659BE0C88FF961512FD83EDFEA26AF99EF17D06292A2D5742534BB4649D0AC6D758CCD0FB84AF94C17C82BA3A1A969710DDC5ACFDD93E0BE9497A67A6AB20748DE817151014FB2E5E7317966B4647BB4D22A2BDE8F0578702C3DEA8DEB5A0DC5A118A0772EA7C05C8F4F2E61BDEA612F6DF40ADF39D2EAFF0ACCD9538C180DBA22703FABF0E74FEB31E60D02E78C9C9C5EC3FF3BF5FBBA2DB6761DB39FA79CBF144678B31ECAA7A3157C045162AD0276BE3653E78527BB65A3755D3C3EAF74830864D5827DC49350FC519E7DB895CA771C4518F68A08C013110B65C7D38DEF8CBB3E11BD81024A8C26553C2EFC5CB1B69FD854766AB13D47C7117447856AD2D06E88F65718E346550509AA79FCE02516BD86D0B5E6CB379721EEE70E2BF1AEE2DF2F576B7582079CA51B0C54515941F2063308E1C0E7E3BD771C17DD4ED177F05FB9287EE98899A8C795B37CCF391E0BD727AE9958B069F5ED86223F724F61819A6126146C2233C886C756983E407707FC096C0192DA22B1366229B4DC43140A50B4F1EC9DB9543F0C32A704BDFA68B655A863C76C9CDBBE59FD0EB1232F7B310330F04B6B6D7639C55476529780ECB08982FED6EA21FC0DE17D77E028F6DF4E680F15691D761E36E206FCFA08FE3978E868E21D47E77589973B580F3D5A291D6A66FDABD3C7CAD5AE6587992BC925734677862EFB52EAB23E5278E3CC83D4C51D552FA4A6F88A9AC24C453F560B0866726BF58C8DFD2569168EB07B914D455F5457CEA1A7A61A6E8474A0E8E6DCB1F2DE81A32148F6B729D314F40A49CBD99904C5E25053F2BFBF205F644F1046361D8A1900FD343C7B4B97E0939FCD7E4FECD55EC7CCB8034AECE5743D4210D11CAFF92FCA3EE627C5607BC37D55F5E4A5FB4F5D74B8B3354416A5076E6E469F43AA39BFE6D69E8D06E726EA6E5DE94B7788A3B22D2AEC900F7D02FD0F06514C39C6ABF1CC757111FCA68A3459421ADD3A0FE530D2AA65F8DE63EE70DE827CE902AD799B8A072F2F53AA7923236623AA106EF099C7E58BAB92BA6D24D0EDDEC48BCBFA23E26ECC077B3B61750742B486C4B7EEF5E3E9819535E0C3DF8327739EF8D5D80E275A03EE17A948827E0CEA095BFF5 +smlen = 6543 +sm = 8064ECF7E8B7C1A3E8DF068D3557218C2E988916CD0416D44C0C5C21BAA705BA7FE068DDA40F8E431EFA4EBB6E7263D23B0770F17C77F3DA5CCD6D9FDD5EE7D686266786C6040299C198AF661708EDAAD11FE534C7E3484BDBF15DBF160CB160BBFF0862415CE973CBA26700245C990AEC9B49C8763A3DED6C7845A647E8E0217F2399A57E15A94F0D281F2E86B393D460BCDB775FA198DF7B4AA3E42E0A0353AC88A372878888C9C328415A4219BCB5AA118997FCDC2034813B019E586590834A83D9D1427B7B26E82B23610CC6D2C70394037DD6DCCDA379A9A0C6BE4811846FC42C4C617E4FB38AD14FADB81D7850278BE901DA60A3C97A1697E03CECCF98AEB49732B783FB21DB785EC1B3E16562B8C555AFA7CE453B278D34D59297B28D0A2519D3AB07BD7C63528B5BBB3D8FDE49AF166ECB44EAFE7B14F789D40EF8AC2DF564111DF47FE291CA3B3128FB1A756F95AC50079CA7AD2C00137046FEF8F47FD15B9E4E920F8127B5B44B38DB506E42182CFEF1F79CC8DF5E15CBA1C7D464D1F7AFE0819B1EE41A3CD5AFFD784CAB1A6DEE327FEBCCC69DE75248091BC0263CA19E8F905DF2A47500DDC165A074DBFDCBF479611D74EFE0BB709B474A1BC9E12624A177B376D6293D6080FFAB5C413B382EE4AA6023388853AE0978353365DE490E9F4CD9411F7F345A05EE575EFC1667F67B9ED84B60AB5A72DFC94B09756C84C272A289E09F5C19137EEF2362E758F7D4AB5DD4BBBABF63D420A9827BE04028BB6311344C67BD37D8BB033C4AC5BB9DFE35B10F6B6EF6E249537D045946858EB1D608BC02EF9021E3A1FA272609FF21F72F5CE277579A7CFF7B3A05AD553530A3F6B8FFFC4670862C28F573C8A91471793E6B21AB3F1BA54E099A802D4649D4D4CDE9F9178848EEA900B0518548895C6A4F9CA70CCE4A57FB8CCDD11EF411235882738E6B608CA1433B9036A88C43191AAB02EB1D5501EA49E39ACC183A71658AB03A7EAAAC91D976CF1CD14D010CA151A708F75AE9FE5B4A3CE9C93379827CD7FC3F3B9D9DCE77D19DFBCA65B906DA99F8D6631188DE92F2628CF310F363D1EC2821270EDA5A4816CD3BEF0E913759ACEF55EF4499BBEF566B27BB82C91EA7EB3CA5E0BA3F6F2788CCFDED96296F959BEC3CEFAE53F064890A20B0E5A0E58D42E73653506AA391C83DAC3D3E9EB66C6DB11650F306B18B9D62CAC5CB490BDCB1918C6129B07840F2480CB76AACE56109DA7268EF953DCC0B5B389C3113DEAC51A1313CD8A58DA76DDBC98202238EA8C124578D949D48898D587016268867EA4A7E9BFF778A83C3A0826B5DDAC6CA42712503B0F811D4D16DB9C0954832E38F02D35F2EF13A5B43615064FB3580ADD2403A99B814B6ACF517F33E2A55EDD783ACBD26AB85BD1CF946D393B002BD7947A725696AA734AA141743DF676A9EA1320ED7E7A0E427A256027AF324709E6B1D047BF90DB8C5F38DB573C27DE34214B32976D4F2A1AF2A178CE8B853CCC1B02A659E97CAE482939365BE07BA8799C853A322D466676CCF4B888FE7341525D78AF6D42EE792E10CEE5769DA9604571126DF6703FBB4CADC3C0C723A5C9F14F963CF10A31118C935954220F7B5E22A3BAB81A410D960D49C83425751D09AD20E47380BCFCB20A9503EDA33937E7AB09C53B017D5B75984235CC10525C7B9F7A313A92F8A911488683A2B0595AFBDFD6EF7CBDA8F0E33093B0290D42AC32BF455CB914B68608CDD7FD9BC520CE19A041B9112857B9D45708995AE385A0168A42A53A8E1862C146C2D9DA505C8D3BC4B32E3A1D875373635E787735BE1FE79F8A0BB2AE812795D76E2FAB7ED819E6DC8E834187152C9A276C96B684EBBA279D7D0740BE5F52D19CD8A41CD7DA57061804CC5E6F2949488E9C0D09F7A7C68678A5942A3B5E316741BA99A2446DCF4DB746A65C521CAA6714ECE93B2CF4C734EBD5018027E2EA4948D2E7849DC5348F8EF668FA09FA72F88391BC11A4282838E5F549F0F9644684FE68FBF487010F4F2DAC698E517B965922697A2EC2872C357D739CE9F27B9B64160D429B6A9B2B7D0EFC421FE42D04909A475105351252A5A762949C805D50AF2012C076051E64107C8EB81D8E57DB3BF4F73B32B02EB93A1D0FCB6B61B646367FA042597A05D573EF5B1905B0B60B2986208D26F5F77E40AC4E7C85459E4D800DB71DDA6B6067D459C7750E7D52D98D42AE58D2201E081F226C3199744F4AE74E1907F685D5094C31A114179604966F418E0579B385B4FD64776F224445C854ED919E814A3B7C8AFA22022AB23567E79B36F6AEEB148BA1D68287B9EE3CF1BB7583D83E3B1B9F8BCFE500AC881AD6380FA415F26BA940E21FC8D99EAA5F3BF7122551AC11EEFD827B1114AE556E1D137F433E70BA9ECCA79EF98061555A8A7B91270AF59E32E46D0E48E303DABA6D0CE1287B4459B0103E385EAA8666692560FB349B0857B36BAA57A36593C823C68F814ED3266200C1BB92C2702D1B9D1444FB86FEB0B9AFA10DFE1E1D332B6660A97A0A9E731062094696EDA826E2BD90ACE62DFBF059DB3CE63A2B976C533333DA26024718943B6B37088F1AE6A730762E2CDDE1CB18C632B88118DA8AE542645D837CFC0630DDA3279D609119C795E14347B70B3033A004C7FE07BBBD23F71BADC71F5DB3322C35EFB9F5329FC79D667B32362CBE405E2E21CA2832EF1FD78D42AAEA28A636205301A8B9C68383EFDB658CA7CA625656E667DC04B483AA4F83A628C269F64DFFF363CBDA7219B491827CAEAC1E78648F2C1A2B3C02197B0420BFF6ECB777A35E075A8BAC4D9E3B2055A13D2FCD2503FF08BAF2CD2CA37F9AC88FE1240A48FD598CAC3AFE31E5469F2950B049D0187E4ADB2560AA8B5C2F1A674384F30A2B290B4721530888532DED171419AE849102FA2312FDE977A0F594EE9CE0F08192F0BE8CCDC034CBBA891CF1EA16F1F3D657739DB5C5701C9E2BEFAFCD916E4D28C98B36D74324D0F7A9282B54C71EC046A09A5373E65D43D5D8CBDA247D0C92C23365440B9393F8EE697D963AC3DD6CA5EBCF6A04EFB2704037134D16011F6A9686765BF42B871914D8F0CD831ED6E456BAECCAEC983FE1CFD2F1C16808A3DDB339E0FB6B5074E979758625F9A64080B1EAC3B9782B145D2A723A11C450A69E43A7E3ECF36E63FD85608D53F4DE246E8B0D4425A31B2075877F889EF9ED5E86BC21551FFF516CE6BB99358CD84CFF03E8193844D510B010E56C8DABE6D4A8EEC6B2B6B5ECA7350668B73EAFF0C1F5E0B8287B2DF2F5666CFD581800F2627056BC6835E617AEFA7D66B5BA9C74B857C4ADC92230CCC01FCE507202DEA4FFB8EF0507815B5EB56F4B505031CF600EE8389A4D2FEFDA036681EEA24AC5DF8634D19BF5DA9A9BEF7BF3913971AF8B336A9EA6484B419EDB103E322531FBCB5F9C64233F20BCE3AF93F74B448514E0CDFDBA29A070E64217B3719B9F5D8BE1235385AB4A3986D209B1952591B7A36DDB2C803E8E90608D4DF6BAD4F3F1025F9A1CEE11E0C4558B77D437AF91546B425DA94A3F289F144446A13E67888D1569904AE20FA377C6E878EB768BB42511B9DDE2378E75E20A21EE8835E63AA16B2ED684EA3FF733FA7CA1FD4153224B1D8C13A7C9FF5B961DEFA384E9B31C48DDC228013E2EA82D83ECA7FFCC9744E241AB254A6F7442D4F32863268D7930634B1A63703F5C4EA6707750E99B848B2635CDF5678A9B8AFE405B2CFFD344319F3E42E115290C010908FA31EB6C909AABF651CB31D185647174ABBCF2C714B049ED1CD2511035EFDE7D175E8175C5466D54937FC27CF7A0A68CFE37A051A87D2742DB695C7D0A038701C9C6BCEA94E17D834781629864E662A5D318ABACCD64F8650B6D4741D15D7B0BF622F0C3CD7DEAD8B1BEA88558114DA33CA5A7F207E7B60E21A86DA1BD98C19CCCA411284977AA0EB87737076BAB976C7FED1654DC463F29B3EC7D01887AEEE8675080B6F86AF67ED8EC93037EAADB2C1F993DBBC99F7C6F4D2A94917E4749BD69742278084FD745FD2B0FA43A9CBA9FC4205DE79F99F5E05E2E2E8E3BD17FD82398B29A79603D46BDC9CBB19AC7F917687783C48F8A47B2CFAE54343F4426BD64688D231BBB11F460F7E753118D41C659C02FA2A7CA3D279C1FA24E8822AAA41B3A04C529DEEBD81C35F9F281551CA454FF89A1B226862FC05060AB7AF4383387289D11232D474DAD85EB8543FB6BE73BB9FFDE942B74F7C02D620FC3773DF1099E138BB9B1F72436085C44DF9E81B3CB340F242C7E938E85EF680C158B7A8233FFAEC935B7B3EBE63E2FCB1051FF7BFCFF7988F61D1D0209BDC37F6BEE3D5BE07E925B0AD759F5E265B05159ED84596CC34DA4D45C75041DE23AE596A990EA6820C04F479BD21687D637D02AFABE73A5745CD79AC1A2650DE10756220618A834DEC6EAFC791B80BB52764FF4367E28B699840029C920CC8220FB071BF4EA23F35679FC003D12C5B21DC89B85885B7C01D4FFC2D7507881757A638BD5B03A0690C201C730163116B54588D2B7F93D31FE848673BAF500C09D4295841ABE3012320A42249A7CDDDEBFD3889ABC0E034565A83AEBFCDD90A3E8288B5E451777F9FDAF8F951000000000000000000000000000000000000000000070C141A2122525E8B98C55864849FFC71EBC953F7A0ECA6298F6AA15A83BF6923BD5921B1C86DBBFC544A39C364EF6D9281481E946C994F96829D6639727A5345560D8641E9A510F913F7FE5592C2A40CB278F5AFD8D4504B5387C20945654F08168247A98F56A43A5020955F882D2D93781F4A83676B08F50341E953A5D1B67DE7F6D1BE3D78D5D060AA85B5EE4271763C437CCD595890DBC8FCFAF2754AE9349BA2FDF89847A15188716C0EC672887A4B9A15176AE0C5138819CA232D012BE1DCFFD29F677442083087C127CBD80B0D9CC0962BC8318E734910D1E2653BBF700C84BB0919E12DF331CCDC7128B41F0666F6419AFBADAF673BE16C9177D3CF113C6488504DE088149BFB83EACBBC400309B7AD753F7B2F5AA89F070C9D14C084C32DF91C5F7CB6A7D869D64F4A05AF80A98BE7517ED784C17B0D7DF96B9987B7EA7A398CE018AE6E13E1C0F7AA040AC3FFD273BB9687AD6FEFDB211061A6228967E9DFEF69BCC1C5D02EE56D49A93C8AAD46D08322A2CA246AE8C3EDC071D063AD605A97B8AE94D58E897A4A6310BCBF55B0CAE1AA81769D30B46F883EAF29D4B5FEA32F2DBDE49360CB6235754BDC305ABB5E5395360097378656E2BACE675448889B0149D6086C51E9C3AF07A76563164864F131CF9C0CD475CD4A58726AD237CFB76ACA68032351FB24711DA635871386B4BFC94B0DB6D35F07D0196F75CEDB92EFBE7D653E0FF9326A596F9166FF6CAB73125DAD27F361D6122CA531D86910187E75F849EDB52DB26C96FDF05925DCCA232480D3F979EAB07CCA68FC9069965D12BB666A180989AD1FBEE3FE65E746C5A8F64DAB2E370F0487D001121EDD0D0D760531AF46DA65C75DE11688EBF31DD2AC95C188BCFA07EA798609F3EA8E6364A43742A2825144FAFC05ABD17476480812EB2483734B13D075B3EE3AD510B67CF7057014351B2CE5357E3F12F43BA74CED614BE3A9AC0E26763E9AC596F87AE98F72ABE0DE213A81A9A03E2B82F2312C1A186DFCFC3DB346FEB132931C793ECF837F57D8E326101F59705B77A3083E712CE347C2C29C23468B0C5857EFA410197833987C61ECBC2A855EF78B3D7B1B697AB9844AAD07C4B8EF666BD80DABA5FCAC900C5D358A11676FFC89DFF4F36F29F14D9F9B854DCED41FFC4B36381449D22801C19BF8E8BA1F07A1B38FFB527A34D009C4064A1E606FF2AB90AB2E05C156150EC14D7DC792578A16F46650D0ABB61175D1817E2C38F109EBC01A3ABB358673561691185DA32EEEF566C1BA1C72C1F08CD1B427B552425501B8783116F2EB0CFF73C5D2DEF18D291C106980135821A77428FAB20A935AC8B6DD8EDD1A936225344EB103DE0D5879CCA09359B5B882291C0FB1FCCF167C30DBECFC324AC315713CD10F35B72F0D4871A7CBAA2B4CC2BC2598F23DA607C94A063C9E2013B0EDA5F3BD5AADB2C429177A4BFD7B6181ED5F9A55C1F043DA8155C9E7BEBDA7EA07DEA49938FE07743DF2295C220EB53348310842B1000B7A02AC025C3A94FA82D46ED7E2712DE71B149742731EBE62E225D21A7F29D5F3A8A62B71FE16258570DA412C07CECF82B2064AB5D98761C69FC5E899A8E174875B3179DEAA0BF4A0261DA9BF39148440DCBEB0C887E41FDF751505DE79AA1F8593F45482B659F5B5F4CC3E7BFEE59DEF49458DB195A1A692B8AF4AA44CCFB00B753AC761181B8AAB39DB82385AE776CFC585F7873613B62DE55BB10A6B2F27E631CE41436C3FE390163E6F4EBD6B501519C96C06FADCAC8F75920FE1435542FDF535EAD6C0E3F41345996063B95A208DEFB6F110CC861580979BF4422ED395CA218CFC3B22C0BA8B31CB9EEEB51C3DF35FECE92795CAFB8440F522B44E21B3A18D5CDBC296B887A4B927F36715E4AC2CAB043D8B69A8704D6BE24C725B0C2E814BCA7B040C27FE8F4C14911051039AF13F44E0485EB767F5404CFB6FD19DA24D82FE24B53033C83DD8634E2E28AA330A81F14BAC1C57DEAD7FFE39994D9D094383E14322E146A3DF27A776E2F09A11EC9014C809F8E543594D6B4814918A129B36FD25015A044E04D3F081D4D201DF86A0FCAFBBFC695088170B8246776B6A28E59449C646D1E706CEA96B12683CD3A7C60459D42989CA46694B0089CF88E9AEC5E110F69FE0E3FE20D18309D1BA72A83A34813B771484505B08548FE5D376AAA0C414260EA4BCE5EB81F6545CD5203026264938905BE1E252574F4B4E71C6E12F99F6EFD35EFFD64183CD0665FE89D6A357B1908E083511DCE2CDF792A608044C31418C433F86719E156AF3FF98D0F54EBEB9F9FBF24588A5557D310EF9D7CF5DD8A68512D8CB15114773C69D7B40C927858AFC049F7C6A89841020E1C313C5C38B988EF505EBE6C15FC1D6CCD8B472F90ED64DA895D06AC01BB99F455A195A670D22DBD5E3F03AC84A08831E9842A566E9785A0FD4C460C5CAC154D705DCE1E7FD1C45BAEB23976AF881CF5628F3CD92AB19BAE8D45A03A859518E4A1E558FAC2B48A432E46CF274E6496B63874CA4E4571132568AA43EEC3D2A3948F40D327976A6D28CD816CFBEAF8FE126913384061D219F51179F679081503371EA0B6BD7E9524B0ECE2573304ECB4A16EB471CA0817C0C6EDE751F283ACEEC5A60C2796C6261FFC6226E4813241619F465DCE67B38E1D5A647B079503144907307C7D6EB6E6EC1936B5C94FCC08A882B4555B19B33A9BF22384DB38473A313966D157DAF8AAD41EF67D3A5FE723559096AB1768FF69773EB9D5C88D6F35F00DFA4473DF71C7E9E35393638DED05D05C105CBF37711D38E3EEE35E8CC0029B3761241FD1E56969E09E949690D4FE25735D774E777A2CA17FE058E14AE6806F611FB1E9FCD516E20499A704B67990716703A4287B50AB45D155D40EDC0AAF97F5B87551C236CEBE9CADD562B27957EAD251F79CAAC6433F228B50167FB1A753306FFF08B53A8A3CECC226857A321700EBE23AB4D6C35415CA79B682D6CFEF6B1341E7CE00CB9870F432B63A2D9A9A43C87D28A95C514582812DA37738BDA6CC76142E08F69EBAA5ACD0403100C2343E2FA088441E9A55C720BB509BC3600C27C1D39157E049650D1749751EFE55A72349E2A5B714556CE2188CE972287BE2152C7E58D3FCAD43A214A4095DE55CAE9F627D8B9018DAA01547842FA1AD14D67327CD47EB9B90CD94AFDF5244DE57E527F17894A410FB4210E06632E88A398400B0AA48CB3FEB9A90ACC668615D193D5A98158092FBB59AD2D6D4FFEE433A2A6A971A228685AE5BBAFB3AB28242C630AF4656C5071C545618A0A765FCE41B19970C2152D44C349D0CDFB29673D1A42FFEC139D1C9958B0962F7B57F80CB8FE6331553B0DF93DA9BFC722B1C001F48FF9C0FEF032610A1118AC9EBAF9202DFFEA605272A50A90768F031C72D570C0AA5B0D4FEE4AD568895274388104C0BF88D03FADC3159D6CF28AC6A7E3E5CF6FE5C6658128CBF81456DB8C29A76F9C75230F3837F1A94CB83C3AAABDF4B29C9045B45AB9552BBB6C0844BF2926267C0D74D3337249D5C9610E0F6FFD0278F12F39C48650C048D61A3FDB8E1A2E08CCCA68803A55B39BD39160B0420CBEAC7D8A55F571F490F694A7AA8B725BA84238EE1E711864AA1F74AFF252C088E36B79B09C80278DD442EAEA8C7D5833CD1BAA18BDD866689E663EADD0EAA6E0C78A3E09DFFE5F6F1F4003DE24336586B25DC5EE45D56F31D8BB2DE31B24E87172F3F1B26D400B08D50FF624E456183F269CBF06B3707260383174FDA152E4D0C528A90C54114C4F278D0FB35B74DD3ECDA14EE89D38E3227A7E18B068F134B22154348867A61719C926EA3320D1BE0B9ED78466B2DED728CA04C15AC144185FB2F5084511A38CFD765659351AC1AC3E5F327D9F3DE9B2B003758DA78DFD08FAEF3625CEDD87C8A55A3CD0257AA71B3788FD2449EFD1F48948CB304468E3CA07EA7044FA185A2B91F9761C6532B9273DB74C66B2DE95AB19E5102CB90C719EC85671E2829B182BB6D09323248D6584F0CA67D422BCDA65A0146D8DF27AB4AE651706D5FA33B5BB88ADC2A1A95105D55CCA8439A5060D110760DEE8B855D0839053BE595278EAE66542736D25C93D8544C6E55ED51AD6E7029C2E6D32CFA8844BC14972809E31754AF84BB479C504EE77CB65CEDDB6BDA613FEAA2AE6598D1F4975D0FCF9D9DC787EEB5C03F8B0BF438E83C38E2195EF1D35D40F5A14E194BC1BCC64D02CA722E7DA28334E91FB6654D708C5B07946CDF58747086EB3CA59D095EB27F1B7E6806D3A35335B2265031A1120F28EED8B4C5D9AF268502727C5D23152149C98E6970D4DCC4B9D0FECFA6A79FEF82CB233E71FC8AA999DF66EBF5A1DB2ED1583C65803FA8958F49890D13BC05C6A991F26C31766BDEF9BAC601A47C8C3C5E395FD8F47E56F04439E9BC8E9B1901A529395F2D57495D70D0712881D298A60E3E013326CD56BF9F1319EA8D6A6511EEFF373F081478A51E14F0AA4A33C6C5EA7816380C8984F7A5DA45B0C4B6B550644E65A5B2DF059ED050936FE6F073B4E8056ACCD3EB65A0B + +count = 98 +seed = 6F6E47E8336ADEE99B2C52CF2DC8D461E0A54C3DF2F08199A9F0816AF8455381054CE47A7766726D3AFC2E2F2BEAF8E8 +mlen = 3267 +msg = 00769683FE7BFD74B3ACD21AF3898B74CA73DD126C8315538937CAC4EF0AD4588765A26DCCE1C90C559CE691E7EB3E0A497D357E1AB583C761439C0A66D1164518F01B6894067925753CC2866A91552FCD0EF029C2284C620CAF364DE6C56EB41EE0E4431D9BE22B76451D132A3F9AD91A53449BE820A7ACF56F6ADBC7107C7C729EC8A64FFF6A24B4CF83FF4E945DEF336DBFEA6067FCCBD1CD6B5698ADB1AD6DF03FD0A553457B8E9FEB4A1243FEEFC2DF7F66AE3ECA5BF169F7891ADAEA8D5C59012C7AA00A5A86B0A33D0006F8AD5A01C60ABBDA6D249D3FAC7EBFB85103A3A747A45D0ADB7DEF52ED3A5F1A620EE383A9C0CCE1900E413FC74A7A97646111D54783928B15BCA783D01EFC67F49CE6F781E82D25D3F30561F507E3831CB4EA5B4A08D5489830017270B63D8298BEEBF48EB56BDA5685D5E1E06404EB9A6C3790E9B29C99168B10BADF8FDB03F3C568672773EEC96428149CA272EA5A8083F8208BDCE361E7D40BC4DA75029D4A18B0B6AD615DBF849935D4755CFFD270A52FA290811CD55BDCA38ED89F0066ADB9BA7F58366379FFE1CAF3A9127E147C3AF3DC27279391E0C09537E81E20E7B9FE4FE3DA970FE50BFC96555233CC9E61D3C356AAA8EED5A8AEA2327D7036EE03E7EE40AA35E9DA4544B121514C261EC1CB0B2D75B1D5CE129E47F89825F69BA8254163179FC1331A917AE9C5A18556A10C5F983871B1258CB6FC8AD207F97A220C5598860B6C56F1EFF09DE6000241E901A89E107FEEC15833D34D6EB12DB6B188FAA0B858A5B9E32F84F783B43B6F8A3B2E4B044CFF8902E1EB0C527BB4E29C92ACC9DC7E0D9AC6B3A021415768B21DD9695983EE89C871C0EADE0BCE4FB72E682DFB5A2BB7498BF4D2C01240F67D1B62BAA4E587069C16E3032114B14A1C4288FEBAEBB4C75C3C05924A358C4BB7DF95ECF81D67147FAE3F605EDE61B7BA164EBA1AB36ECE97DB0ECB32A673E899B24557D8987AF3ADC57A9DA609914C9B2D6D8AC58E5954E0DB5AA9E75B444700B8F704E15A6A7BBA81809FA8801C6CEB5747A44CEB8F99CFE6D8A2A03C03451E5F3D392725207F3DD28B2C00004425B7AE05FA3769183AB60857B27AB08BCC4321D293C93D1D850D4E7A81B14564D7B15AC0E3BC1BFE0561622C6AA06923EEFE163629EDE8BA1732DBFCAD52D3BAA6E11E569EA790B36A8472B2CA37BD5C0EDD37D8F164B874952D00D592FB705C6B3110A12B03829C157191D33C579593E7828CDA5C24A284BA2F5A42F0BFA601A8F6D3DB1CA6D703ECBD261629C9F96EBC0458737B9951219E5B1F86192E2A85B47D80610A0ACC8B1A70DB2916F89CDB2C7F8943471DDBABD2A3536C5DC8A73CDEDDEAAEDC86FA148D2EE479F8465558852FCBEA0DD8017F1B976281A5014319C2C3CACCBF571D9550215B24134F6DAEF32716802E7945CB3F97AFC1AB1DA17D0C41B545A750EF345A6F88AD5FF52D512AFA6558335B5EB8979D8E6DC1DA562BB997E7D152D9FA3EAA09119C3474E11218230D8A56C19AD87FDE483FBD6DDDE9ACBA813BEBC8505A323C601E5B5251650DAE9334562E3DCC38A28BD7DED6942D0CC2014235C1B66CF4A57BA3010B83CC7050309F57A27207512D195D070DB3D10FFCBACDB47E4231142BAE588F92C5B0A71ABD67CA9390C2E05FD2CF7A1FABB14C5A7AE3773C66DB1F055214479E388B5E6ABF0DF8FD1B0E4F90828ACC397643CBC274143FB4331262A20634877BE4C7489C1AE9EAF90BB2A177A6B5AC15CBDA27DA0616E5F87461554F5686A7BD6D047AD0B98C8CDEA3DB78DD2970C78FB861F2A92DDC277876791C4A30F525659557831F4377065D19ACB384CC68340152A6DE6D84CDB58F433923D1FB8CC6B10BACD95B9AB1B45563998620D192032269FA8301C09A29C4B5B20CA0A3D63A4F5984B7DB0F5B17417DC7B939B9B177BF423E2F3D57DFF296E6E4FF0FB1744B13731206EAD54EF0AA1DA09BEA8B0AC0EF71B73D009D30531DE9FDE90D86BF5F20D8E5A9E324E657A98F8C0031ADAC4385157BA4E28B48AED957A5B36C3B49057F8ECA7F56808F794014DAD170601070607010E004F42D01CC63B2A1761126BA045F1165E25FDD05901FAC6B76E777FAAAEE6F5ED94302E2DA28046B4BC60228E1B9E194F364E377F84681B3011583554B76FBF8D7456DBDEA665ADAD6AA0556C8CC714F217A518A98615C4C1CFC8ADBBD4D12C5BC23AD7A0F849E32FE2005334B55D7BCB43D1C95D4793E7C3882740CDE8DD24B367294496A3E2F3251A66CDAECE9E0A73D853F8D4E3A4637836DED68CB28BA4FCAB02D61FB5CFA581792E636217F3238D78912EA0863816FFB2F388823174B19433C2B14BAB69E12C3B791FE683744D4519455A52555AF0D7E12749F6094AFDBA00FC6A609C7578C531FC4C3C3065EBF78414F112014726EC2230F9BCD9C15E36283144CCBE0D1785B65CF49BA8FEFE92EB6907C0330BC98AC172EA9E8DD4DF8974DD6B6772BBC6CA8E8562C5EC0B6592DE7440AC915C35E0AC8087F22EBA110CA3037B469B1D5BC92636D81881E38D8BBED01A29B3EBCF0C19EB95BF999EB848022592AEAAB649CE19824ED9D3A32D75FBA556EE07606A306D1FCEC2E24B38274C361B7BC96CE37B7F4FE434EBA17AC2A097051A92E4EC32E4C678F7762E8B96EBFD2600C0F224B04B2CD7E9F4AD327D53603828015E9CF45969800F02FA5E0BA26B8C844BA1FDFFDE44303AD0389C1B31D582877CA6BFAD4973BA35FBB90ECDD95F430078BC39AA89434130A5FB8321E51F9624090D0277A9F112EE8FF65D3DBA999C7C08727D0F08DCF00CE22F62C955D6A822F247C8065AB94AC442E1CB5F31254816794CC2556891A523B8AEF09D3B9E07AA8B67B3B87567ADEBDBDFB93BA9A082F72052572C97E73AF16CFC42D2A51A3683F84748A338AAB56264753BA4083D356A27C71F47221ED8340C50AFD46CD207C4F9634AB5A44888A4234770C46232C35EFF83FA950B0A6879137DCE209D5A1F26809B411F046F51FF084F15BFE03292EE845D3044235ADBC299925235462E67F803DAA1426F0E116B93F4532DD2784F7F87AE360281CE21F70D230C242E1A98DE8FE1D6147AD71EDEC89E24A5980C45FD91E23516758AF71DF8E0DD96929D4DA61A3BAEABB96C9378986DEB4C9101175E3AF1E102B52A8DA27D916EE4A28263CA485CFE87EE5436249C1A2F933669F6E3274E9BD93092F4A798AE85D6592EBB54DC65C28BA08582E275972B0A12C22A7792CCFD4A398E504C6FB2CF5EF1F9C268540B4FD7D07D59C49A559D86A56A009C4C18A3FCECA109FC7A45C6E842ABC22053E84878C4805D96AC96BA00FA40FC3B50407141105845055447CA94BD27F234183C2B8BF37F5CD249ED0705AFAEAE59C8BE8F6B38069D67FB23F74284E8185C176B58B482900A3E09774383C7ECACF4FE5E580DF99DB102AD4018DB73C73A635D3FCDC833B000C948D846AACC92ED54FFB3ACAE1BFE205D6B2312658F15DECFA085D13BC3757C754C5704D8089563E0CCF52B04A49DF293CAFBBC2FED5D9551B5A3897EC7BEAA56A4034BEDCEB4840A9BDFBB8BF47D66DD3A4E3EB1666372C6B2C39A48D52761BD36403CB130A087685E2EABB8711C11005EA09F90AC49665415C56CAB6FD2719C45B6800DF914F8FF327EED29D9B9A5BBD6B80B8BB31AD1522803B2C8D89166D5C6B2ED47BC5BBBC4ABE6709D46B856AB81DDF15F098A9AB76A8257E7E5C2E7DAE53FBD691736F0D6BAFE0BB939172614E99C7D7E37754AF6C3C637D076A43DBD70E5EAE910C8170CECFF1621E382D2977635B67F4FAC555419F8A0BB76CCAEAEF4C7385D293C9595AE10E5201C4A31B4C3ECB9F3B304EFB1886F9C58A4EF04E73341B95D9BDB85D706B2A8D3FDD153743A8BB7B3289D0FE79F6A3B9E0FE160DD6700FD64FC87D9AC96858A6D395FEF6F3D2193EBAE7C3A92E18746A7F12B244FBC5B1DF0086CC7045036519D9D7BF8E92B850EA0D3D1E775DEA362362462DEA2D3501D39203E2879070D1F7AC92FA1576F6D12886D5B979E3C788C09A769EF4EE45E14CD8E7553EBEEFCD31FF3D43D4988DB08F6630BA8AE8C7250AC42A3D78EDB967D59310A4A224567D8797C42370CBD2302A3F49ABEAF85FAD9455F98B61EF2B5E34A5C552583872145E191BBFFCAA526F5E38E497A1A1E1220A0F283A935ECD366A9069D5A2A80BABA3A22FA85A2557DB72D7E29EB4E33E8ED8BB4EC2EC7C2E9CEDEF46EA955834ACF8C9AB23B78052446FD73C9D61683D7FA0088DB97D07CC350AF0B6B2AD7E66A493AF814C11F8C0F2FDF0DF40AAFD0D218C00319C367E98D7F10C74EA06D31276F3F216E1CB2F12033915008CC83B00AC60FC9C2FB7F97D6E8CD79650D0F9D82BFD9CAFEF668021D3D165F3FE84221998BC8C29AEA0B5B7E0F1F25A0D7447E806CC3FC39E6038BE3DF9AC01F46222D3A609F8A026744AB4F58A734E3782BEC301EA91F2D8E2242D04A11E82474002143223F29656B1A7675AA5AD181004C4F1381DF6A0F95A0186E82C04B4DE881209E9CCCA3EE5B1DEF0B02353738D92A07314403A1A2721C256121FBA8B8CE9B460 +pk = 781BC0A1602EC531D0040E8491BE5D75AFA8F4ECB0092818D990CC08F6FCC40A4657E9CD8954285E847074F2A26619CDE88F2CCC66821D6DB32A0A613AA1A026506D95BED78CE81C352A12006803B2C26CE6750E367E0328404C177619C8FCEAE613C6004B064B612C245216BFE3E76A8A7AE195EF16FB710FF29585F1C69CB7A51FE411FEAEAFDF0FA13AF42E8EE438505B76B29BC759027442D4C004EE98F039F80DBEB7D783912F6916C8C0D0D1181B13DB29FC50F71AF27CA8875FACB3435F1C67DBAA58B6CD2C9C5EF58EFC3AF55AFB63042F4CD5F9E8164F22038B4D3BD66FC5C10537D68623F43D6BAD6D70A474883A72233659F0E58C49D4F0467BF8183D086B2D45E333A7FB3E5C716FE537A784272875F6DA27F0D66279FA78FCA07FCF137B6A9F659E625B2E18AC1121AB37ED130E5710173D3B898B9D1865E0A639C27DCABA62565BACA7CDB835C0F9D464FC708B98E271FE18BC208B4B68DDB69FAF9371030FF9E2CE585668BF523183F6B62466456A44B8DFDC9B3CCF5558A1207ABD5A1791B469BFB7162F1A3987E4D2625E8DC99A3C1CEC4D763FCB35860D12AB9669B5F87D970D9338F29963CFC5E1ED4517AA6816D2AAE8426A5D3B1627467F5E9AB7D03244BA757138BCC03276423F16DF060C5925061F7D700C85899A4B802124E292DEAA54AC5405D0293DFE1B14A3624EDB107E3970CD31D35E0A96DA99AF97216EDF344E1B7839A902601A91DD3EC4C928033C21F9A44FFFF29261F67EEA35560A4DB6D5FDD15C8302E12B14860D2176FF0E69E12B21B6439B7017837D5BC0E7CCFDFDA1A076C0CE7F07496ABFD3E601EEF130C74FBA0CAE88B449F3A766F275E351B4F8390C4F8C3D4D0553D977429F7EC607B895F5C9AD93864C7375A0D7F3C3BB1EDD113B6BD4E9319C85508A985D84705C812ABDC06AF6BBF74C3E008B2C271CA53695563FE3F98772409B1CAE1C22B922AF9C84FA75A97D28386DE754844E05C2481BF6388012832A06F770963794A090757621415E4463308F2FDE6CA8F7749DF60B95CE238EC683BD8A34C8545150A27FB8981A310695B449D3BCC3E4B7227B95F262D03D0B36B84472E0825A3B2D407CC7E9F975BF2B387C66F018CBE8277EE07E4B9ED14DCC441ED633475350B68DA5009D335AFA5753F4DA28133AF182206D74CDA07D72956B8BC3F44F906824DEB776F41AB502153156F62165C7F6949F284FBA069D41819F1465CEAC826174ECADB8309F3F03177C121994FC73326E0BB8D17198C6A527B2A9008EA56D4BF8504214DEEE9918754964EC86F5D50252C285B9636E58DAEADBE2C4BF69EB71DA5BED0F74148EFB20AC83B4D7A71FD6DF5C44D33DCADA9096B1C10B7CFEC910E697D1E76414C34FEA9227582D0A182701BAA2C4D8CE82DDF6FACA924D6F29FACD4B956B1A5B9C59F1DC3332571E47C6980331E711400701FE4275742905CFB7C48A8EC825FA64E48E6B2DB2EBD7CAB4912508D021C4F070957BB85D887015050DBFD9B086847A132E9FA3A892ED88E025AE137AE9E8261BABA6641572068AF9DD79B9E4BBBC0F7A264998F33AF26D7FFA7D6C4CCC857E5A548B7BDA06DA21637FCDAC7B281D263AC4456C1A1A7D6527325E43573A8B87C453102B01B4EE530C8E2C9380F1BDC3B76FCFFCE03865D4B34ED2FC6AAA4210E1F4294D0B9DEE9369CA0F4C18A7FF387D20D5A9AA108E39F774608456BFB4A64D2860D2388F6870B76CA4FE48F763106269E629D9D7B8BE044FE3DE82E62EEB4D7ECFE012DE49620EF4ECA253B6B46DA015A760A6F75BF21E4057AE26EEBA267CC7E16127A3C91C314FEEB85879289423636CEEE16EDBF00168E098B251018E76C062610ED764FAEDF5FBCBE915E481B4475BE4C301CF2830E4E561E18AAAD629E2617BACA5C4D5C3AE8E9C50F870719E6050A851119E3078122AD72CA8D1291B4F0AE236A0C542904B54984E52D2EA255AC85BDD19A1065D4BC28CF15A12EF1DC61C5AEA4743B76A64E1FC0C1483884A2B5547D1B40E0A7309416D5D13CAE7F46153B49AD2F707026A7FBAF6C412E633E8AF269122189F9BEA08D101AAF6BB42799A41AE9F920519320E3F000C92BD9629B7D259B8280C515FDE194944AD92725CB7515396E174426C06FA45FA8A135AFC55DB73B1C94D3F2E0D2E3F113E220FDE08C2BE6EAE1A6ED73CA3949624E7B31D1801F6C84D52D559E23EBA9C9033DB48EF4EE003E628C7C57AA00E8A8D549D15C6EE099A2B4381889254C9D1D8B2DEF893FB52675D3830914BDDBCEBC19E66E08F588FFDE848436C36E5FDA3222258E3DE7ABD1A5B72DD74C70D0576D93DD94275949D6F835A599F2690B21623AA7040597751A29264315679D5DE3839215AF6CB7AC3B5A52625327C30A044223CB02FCF4D439F429333E3D8E7A07CD1B74B9A8DA7E0668A620689AE4CD5A0D4DE878E05C5495E55FDCC7446E83DA0357C52A455D1DEA62988ECDA9C12BB8B3B04D56B1C2A0446EC6830B94C8FBCFEB220E03B53891B528935EE0A84249C6B8028F196BC952FF11AD90119596CB42EE6E33846DAFB9E90E0C0A73F1D37003BF6714B80E25A51D8BC4F94F276E06ED016A4DFBF6779D145F685E4FD2EDC1664A5CC472E0E59EF59BF0B3A20BEB1EF86E5DA2B802B205A42218E5BD8B48CCC33885FC1FF764FCAB46183950B4FDF71A9F72145AAF178CB6E5593738D7BA276C35539102DAE57BDA6505AA1EB588F05515EAAA13710 +sk = 781BC0A1602EC531D0040E8491BE5D75AFA8F4ECB0092818D990CC08F6FCC40A537B05AB029DA74CFBB1CA710B5478A1B9399BD002D7C66957762F7B2420B4F3D972F5192198CC3D7DEF713CFA616003D4CF29F5612108591371EC041AABB499F892B05C60133E64BC1F977C1F2FC3286FCEDA91D25709CD701FD5218D6C3D8A75808882078718742674505261380205062063641162714466788834447641451754260087813822655366811227253765680542680636584804478003845455232170451317455786326107455362204282521562475767835745207554171010650702170071757534068313888430240435604001157281505465657776472112144841855263326522553735255414777371802112167037151406522128157623224648675388530158623635185348554258265018228434183302063150376086251504810665461370031454322853838875051451010704020541677486203244661188317080811616820543081584807754503637012508032270284713211734036457200281667342525384313440516770130036655214557380582515444663153367754008120723533053215837005183075220538481783226276435882462032552147517423023653835751353408173141752157824844704424882611327513860310623028381252030234657873662380845588281115575736231623537444557530251266277637202145763723633680865056051168557055057721437172757780436485711501610471157037203036602103532252650286262637182111123545443382452807252477112532872404318683024656405540257186320822624585605001322011102053551550037548338811242505606073513872561580614631052520651306846853265288817116630840816536730480024652341887508853853140081221307017320817202120825800425750832884227351224781662117488407172786310786242405343487568233783587217556060507317454158045042886320284681608462137463403670032752477601476304516406302664710634833717881702216148474230557882188326388218878778525323425328086167463635220674061422585367146126123646760607887077427464650633025107713485073846310423708071524205608701853753127307748701380324332772535752485813114564474367663083788140470702684044284725461145861341065554245846451457848678144600558876732414745486180311527504862800084127105233760374668547623310584146612387741842071116804860370664770440758738672035632350752145028702655276033801218388741838458243448305263466104648761646787547755148522638660462682615705102585724785660537845448308216877538850635187366873641768528150821385081117684100886371156414471736264051175663803647163857313803836714562040487178375187666858065281061862500556465336528437117100336358734650340472542751404736165042856566437782171737251223440171506175517545535470386253466475738024485711065004772425345145045884823742316271884238248385537364733384302380475715530034105727242058803778062758113288264014736510285853102076478556588660348101577347434075217486733312731678030817518028560075152241832453837308521736115000772356651304072086640743320116213646376507734832267375737133672658387260556484446210808253752342447325147582700368846034841521704688204164388326750124632647578673537043246344266743208550268414747680683866035623674367503162883731484367228380175322065506448618248515755086751086338008821107881124574645348340083871413080278246481745377808415204150157255738145346380705355667310768644862201675543446545776486711101430767125123175454052874450E28C614A95FFAEB13E789994AE734D1BA2FE3DA0361F1C7DDB09693BFC347A02D026C9C6EC46B92C0C1BC96BF3E9C7C5A8EC3E51834B9A8AF6D7AF0F48FAEE70034FB56BE3A506CD4EFA81FA4D32E1C40BC2C3A636B2BA52A520CAA5CE38A5B4979B13C888A7FEB7842710DDBE31750C6A0C6F40272C37FC8869199B66B40632762D2EA72AFF846F845A098FD90A313DB63D53A49B67BB6995EB8F23372BC76831EADE712D2B6FA061D750299464280945F1C9156639357B16D2AD2F72A1C56403E0C7DA8636B0C0226CEEFB41D2766447193372AE8549976056546E67981BAA831E3A3157CF3742EEA3FDF9BCC61436ECCBB9CDEE8A56CBF971FF1C1423AC40179676D8F0AA07B0521EB852388F1A164E42F98A9910B9D6A3F3FA4C0F042BB60651725A85D209F5927FCA29B8C7C31BC940457FD2CCF9EE31D7EE79EA59CC93CFBFA8F4C078B32C1E414FEE1ED3A07327BC89E54E81C12D6C0E73313A0A5C7A7DBE190C99A948466E33BA416C145B76F12F39D679D4FCCE71EAB9BBC97159F3B9A222416E6F8CB4231C4B057032C42DF08853807F730F861B54294EA1742DF4BA461E7E11E9B6BF342EA31F52C9F450977FFDC73940829B8CEA2ED73549E5BE3D872BA3B9AF3747E51B3B72C22DC9C673BEC6055C1BA7633594749467E094ED4143A49FDC5B5C60B2DE874B26D249B9E96EA6CF9FDAD8C2EB19CD6AE9FC2C6C5C85C86222BE1317463E79AAC00BE5C67564578E2CD6F1FA723AEC01DB9BF26BE8705619157B300423AA2F16968A81D251F4DA2C310FFF5B8E009360C0889D13397B2942F59A5DE9D11C67AE16778B3645DA89749C227320C741B7943F6FA3D5F3A5229BF3CFAB50F05EA0130B03848A7FAB05040B1844CBD1B747C769C3381DC31681C131AAC49657B13A6929A85DC7049B2F80712F6433113DCDD2CD83AE334A1DF067CC8D22D07B823B7B7251C482483143A76EC815BE2EDE856DCED96E9B63FAF913C2C6DDF23134ED20000DE100AA91581B1AEB0387F7DFA07A38ED4C18F7E5D3E96B3C7AB221AC1ED96EF6CCBD04C64BCA0E69E58F8A4E41FA850BBF396C931780B1E2792AD5837FCD9D07E8D46C61D6D6CA4FEE0066DA62A68BDB1EC2D141961BB99EADCD71EEEDD5D49EE03CFFCC5037D9C9BC8F66317C7EC99916469EAAA12C126ECB4204F8C6FF724E307959926B1C2741A9A65AE96EFDCDC527CCF0247E4E950B92F0EC91357BAE90C63066C2955298C37A5F3E47261A6C3BBE749FF5DC2F5E33352986F423BF75FE34133C5520A52F3AA1E605AC9754E03AFC4578BF84D5017BEB3CD1C22D32B3F1748F57C8A87B6B98098EDB91C6A9148644733E0FDCF8F4BE3016E2FAE6F99D02C79DBDEA9418A1FD22313F6F1B63E76E6A5812FCBE6A1293CC1F393904E50CA486346BAB4DCCCF878BFA7FE77631132F777E0FA900219B53BCA325E0B02E1A2FA55B96E9C7BC97E9FF120F9BCEE39765DE048B2ECCBB8B2A5C2D42A025C3162FAB609C05AA99412185DAE3B699E4207B90718BA6F71588E67D0D53777C7F1A2B20F35B9DF95E0BEDB566E578170752EDA04491B6FF6F3202FBE139DB56D0A8E0E010704A456A776C8E0662E65BD8F7646F090DE6759F6F084FD16B9EF66A2524A2BEF9EBA26556963C9A4463C69A1BA8A09AC076713C92100B3B0E7A6B0D11C42B977068A2852A8D6AEFAB64404C18DF26413BED9AF9E0710B2B2197E78C9279FA1688F12778B0C596EFA80E1C8772F71C0F16FD57FB545CDA5C6603A5E50BED085B2FB5D557F551919BE061DA754161FE70D50A067A06D21BA65A21036967C1E94CCD023FC34DF69CB8E711FCD9F6E1D7D5582BB2609203D5F406521730263D6F4A36AB65BBD5CECD89B187517685ABB8E387889E957AB89C89AEB2AC478482E74A8958EEF47366A2F86E65814C1E70BF45574D7CE31A6B69B0F355F35793DE9EEB30CE2069D3202877659DDFD612361FFA9DB578A8FF7BF7DD6579371858D0A6FCF3DB109402EBC036C968EB39E542FB121AA73E9C62EC3B292B76B293E305F6D5BB87914335D9A55AA3D1BC679D0927B85069422EEBDDA3C1E39409B942A1B8E7D3A8C6C4A20628E2E222CF8ABA169CD155996A70ED885A98806895216663F725E9E9832E2407C2CD2210B1A7031E02CF4A85382F81ABD162F6F085F6DBDBDE164023BE6E6D0A72909E02A133E4BD6DB02E36C338A56811E608D79A8E752A5D13E93FE7463B8BDFAA2CEFE37CFA8BA38020A04622E3B5F65E5935EADD69F91F9E521A59F170E54FED271D73C8E06B30DA3CB3715B25012FDEBAF61ACFDBC38710BE435175782DA81081B56A3AD2F6D076E4F341DA8996D54E5829D08008F548CA12FBBB31CBEFEB0A4322C6355ED17D28F03F7B66257AD233B5C1105E4FB46AA3B102BFB2E13DB4EC878437EDF6B0261D261B677C39814636BF3A9EF53C98AFEB685C08516F5C25F258E16907F2FA426C5B509E2927D4823F5C5AC7C76CA675A59FF9B2F8FBD1A1AA8C528933028886AB00437F4B274AD3C97B3E2B84D41C4FA9FCB9EB02F5CAD7D379F6A365B3BE969D5DBEFC6921071DA702375864A6F1EE2A6E21B53E934346A6605E1EDDABA1CC49EC83CF849095041C5816840A7765AE792E0F30A112B87BF6AC429540E6041D9762535F912766401ACBB3F12ADBDA2B7510F6EEBF05B36D49DB1E4BF4ABB88986C821E163BE014648F252C4C5EBC7CB76B1B7A11849E1389164FDF52F2CD5F3CE8816C2C5F9DC16762301DF4B998336B8F484C6CFA24690B72A87CB851C6C2FCB9C504C0CA09A73D39559A2514B87B96EDAC20CC9F8C915CD9B383722C469D0C861CF935505F9FA6C914BAB265A23E48D6495E4BFC4880DCA2140792E2830ED49C0352381B7DC7C3CC94FE40D65BB2BD4524E059E21695C13EA06CF4002AEDD22208FEB5E8D7A1CE28E119AFC8642D967419179F6AFDF73A9E65BC3FA053EAC952C8D68BA65B95DFF541A07A978A6D0302FBF92335BE76072D29624FAF3B5C588221FED9A3CE031CE2387C97A8DB0E5BFBB0B13C58F464E188B080AEE3572C32D0605562EBA2E67B6D0E657B21A03A93603C3FE1B7CBE21FCFB32295D74D2798B0ED641CF88B70372124DCF1672D8C4A86430CB1423C52952546125E3B2B0ED25A796BCBED68194892B1F4A072C050AD58FFCA48905F9D843CAD02368F03895A6E126EEE75C927C5DD8E230C9D0C674F0C1071DE4447DE30CA48DBC576FB2903F8EDE86215839545EEA09BFCBB4DBD20C4D0125F117CBBB7227037AD667B224847F653073E7F860E078EE77C54B0952C8395713D4736C5071194A8831EB80AC72392AAD815CB16196B035D1FE4A1BB41F9240B5CED3FF3A28570C6FE4CD9DA9C7CB9CD8954EC6FB5B349D9B852D8C62D8169F2F776479E51CA14513286C046E60260959DB15286B16166213355BD93C3C4F39655F6569637A336DC794C1DF7FA224969EFDBED9E190CD1C672E8A5C62013063FDFEAD5836574817921AD953C32E +smlen = 6576 +sm = 4ED53C0AA58F21322E7117308619E6B0C4C91248B8D3DFF9F654FA3EF4D44737322DFB9BAB85BEB8566F4A14BFBFA727AF534201AD2BC4AAA8B05EA04A7A190FE4F7753D5F35B47EB3B0CAC31A762BD4D229E5C34A8D052DE0774CB84A2B0CE4FBD47A72C79F881ECAAD584BA1239FE37861EDBE06CEBCA37F1EB74C85FA0D41287E6B899A86546D5264AA950CD8562B6DA1C31CF52BE72B204CE44E036D6260856759BC57E3E57FFA82046FFBC44585CB807B7474B7245BB74E4881070DE3C7DC513950C2BC051731C128D16D4DDBF85944972F39319E8A35E719087A550201154CBDAF353BC9249721920A9191BA689207A3CC288FCEF317C4AACD5681F6BF5D503E0D6AE3DA0F5ABF6CF5B9C1A1F54155364D6E85F11FFBE91A45CAAC61CED92722452FD0B0D2E8FE7B520962DB334B4D5D5FD4C6E466BB84FB8F3176A2BFCFBC17C1292ECC9947B4664FCEC684F5123C050AC9A58E028246004D988B30BD76568DFBE2B5847BEB3E71521CD2B9774C6467B6C75CA71816E7C33269F3BC145D583779B400736949CA42356C06C6C8947BE09224CD68EA8CC01B59EC4A6B34E05FBB259CBA4D25446FB77E000A2923E82BA7409F7BBB17D8CF777F30ADE7789DF5E2AB2ACD09310FEC191A65A81C382F0E64C2A123178D922B23875F1D2D87D339B24DD01FB6BAA63823E28FDFB556314CE4C6D366C68DACE136BD66AECD5303A35E519A7175FF0300670ECC087C0E17DB557B965E066A3E4275757AEDF3D186F789F37B3634D237A6B7C3A686D57F706C87450A62E5E44008802055F9D33FC14F8762CEEBCEC5D57DFFC94F55EDB969D92881937AE3AC26B39D8560E327837961CEDE7165EEFB84B583F6060FCA59AF4E0842A2EAB26F1F01978A09F53BB8C509EB5659B7C0D6D53D6D8C9BB2DD02A31FA900BAFD8FF1F5A9224028425698F578BD8116B0243BC2CC59B2B9B7AD2042090A2FA2BEB1B7C2DBCA9CEC2380A98DEEB9552EB9B7D361CD234684B0555187AAD5D812B7AB95BEDEA407E9BE427B47328A7545D3682AD5925FA8ECC8BA55BF4CD0AA1C7029FF6CA855B2D7E93A6EB4603F037E9BCDA5D8AAEF6125DDDD5ECBA3C9D2AED7FA04D9C97CE9E1564791026CBE610E63FB37DDEA914AF847CBA02D431A3FA2D2C7E2614B56D8E5B9DC4C5BD99A452BFAC939F236D195B2CC56FBC9E4172C713D108FE6397D431388C6F66D0B1582684D88C4A93C3A9B6E26BFB9092DD467859ADBB4E3A051AB2A2CE696FB4C6711F47937FA6E255049BB0A1C9971930DD024FB21A38132D6B91B4173C56CAAE18FD973C95ED39FCEB609854A0F0F2D7C3EC861C778F62893688B42A57BEA19D99E71B19901ACA44BE70D48D0AFE2471FA916B5BB903B0603286BAB04A32755553AEDAF140BEDBF15BC9F8C913F1D1C3740DE1F2A8993D8D80841F438C491C7FF9FC8E721DB5A6B9B090AE94DE9BBB361C35161204E250ACC5DD5F85A2EEFB7E381A690A64FE9BC363E6236C16241DE4552686C176A2EEFADF684A949CEC6AFDC3381934BBDD4AD4A71272948D2A976A7F66509EB928388E3EB92F175C2906161DE8C12569385DC7131E06B6094A8B5795E1288051EA780BDC13361E9CF38C39D64A47220B9DF1A7924BFA217D2BBB203FF8ED2BFE5EE49E35DC4C984DE86F911D40902A763760577C1DA91A3B8019304D0CAB5C66FBF4BBDC0C6D62476B5F20352B9B7C2E6C37E30871F83E86EE86E9D5C2CD9020850B64DBA38D561300DA5D76CF41D730C5CE7369715EEB7703A3608C62F02019D348096E5E6412E3DBCF95A1395F4AB23518BE773D16329768A9CFCA348253288828B29D24B52181365A8D3676FED1A131E0A0BB6D2B02C59D7EB48B474B8F7DBD5884104424E1A11A633FE45023BC5C2F85A1BD7BCA8CE9971D2B4B60415DE9E286DA096BB59E2C464B64422485416D03E5EF2066B151C70C9258F66BC0FE820571C41A351C0AC12EF70606B6BA8D947CA4E6E683BC6E6DC4C1D12A2B87A1EB9558BF74BCAB8BD3EC80780983BBA52B4E3922C02327A9495152FE93318C19E97DDF3AB32048EC81C923A48FA9FF439872A9BC3CEAAD4F851AD2E23E853D156820499C6088DD38259515D1D2B452D3A6A07F1CFFF15F4B15AE7E6B59AD7EEEF91B5A2CD00C082588D6C235ADE97905FE071A8887969F7D80FDA307693C5D3296110266D62D3C9C783BD824145B6A892AA69A8A8BABA9F912EE6DFBEA0C75B6A8F495155A92D82D2DCA879B348B4B03B56AA227F1AFD968A46BBBED523F0B1A623F3554503CA2537938EF5A9B7A5C2C0A460BD873D0D35A665625E35DE28BE978C082A32787A6549496403D3C792E3C0CA67ABC1F2057CA366E2A6995E4C19B5B480DCE0BEEDDF84C6FC8F5697D45D797DE7B46FAF8734834C463196FB13100A85037BB7A4EB34F2D4B800B4B33FACB4E7790B9E9196F10694F2FE2337AE1C10DA8FF20D16195DDAE552C23E4FDC5B083AE104246817EF9E490761C456BCD0AA39DC0B5DB508EF6986F6041F8CCBDA87FF002A09BC839D8B1050C3152DA28533995F6F330C1B3E3BBD8319656738D2C0F6D9AE74AF296E9E902D2322C702C16CCCD400E4EA630E795EB7F8102ACE6B8C58DD06C808173577DCDCF26F3E945681177A31D0518D7CA8FAC255A29FCDBEA204FE0DBF3044B46D42B61F9A5045BD4F278CA02EE53860D9948D22987E303BAAB18C757ECA81368BE2FCAB029C500E45C3B54B9BEFBD50059B3F4553C5E50CDA2FAB24077CBED1B72A4F6B24DF43214B0262BF17A4F791DD772AE7B1FBF5900C3143F7CE0F6BBC99FE60093529DDE56E2D72C926DE94AC155B7E5064D503A2B3E17415C1031BA3936D50D43CE9F7864EE2329CF91881C91B1E8F40EED3B06D695ED174F747961453606A181693A4372BF2793218C7F935EBD8556CAEDE1EFBEA2FFE34CEE299D9CF16FB5B62EAC47D0A4680E180AF69B5BF9A0FDAF3F140B9EE43660D9DD8EA3C9A0E6EDB8F7A55E7F245CFB12793B8046AABB1390F60E6E4C48EE42FA3353D816B147E49A13D2337EFC0E1A40A82CA76D4C5A07A24FCAA8EA0AB880A29FC9F262422317EF2FDFD1A0ABE3475278068617A0A62473A85E1FF58EE0284F99E3FFB370E6B0FBF2F575AF1C3877C14EA6C0FC961980974714B8CC4094305D74D3A4190B8F80DFFE2417514A132291E63B6EF7DCCE6353E1CF0E5A4718E57B8393683B378C0D072FF7ECBFABEEA64C7BA4557CB516A3CE9848995DCB6F2BA68988D04FC676A301A989929F26FAA413783DEFE9F51FED8C9939AC49560A2AA840E04CD8CAC72EF22DC038548575FF36CCA454D60DF5BF0EAB863E9A4E59A1915953189062EDFCEB7E6A1B3E985F6D03F1A9D4E24E0F392A13A6E64241FB468DB188328B36E09784382156011E858D6623B2EA3ABA863A84877BE933C1E63940894CEDB045EEC01D23F286D481B0FFCD46A1DB539987D30B1F8F40D159265FD6D4C21399907A81B8AC9A0FD80DCC9A35D4D3E978494EF8B9AD2F497B8B935B5226D4DD339C90AF5FE9FE2E659D0AEE7090AE9F24F05D5D9169BA02F6DCA795352B2EA9DC0CF782F668FC166E3C7603844728D62F8CD5FB150EE02E906DEB85492817CD5E31CD5BACD71AE61B71E522B053E56D1D7949D02DA0E6F31B7BCEFBEC19D3C9B0E81E8F7B1D4DC2E677283AA5600528F2CCA1E0D621AE272580AAA5D2DDF5163FB07A9ED856A24901DBD26B2D8F1B912135D558C57AB58CC2BB49B89C33291A87E779D0F2124C7B031CE4F937D27697384E81089FAFA6E492D9E4629FAA0515CA873213B657557D940CC4867D4ABE21B419AEF2301415B3F864D69D24FE6CD936B2AFDABCD12463771DF1ACF265A29DAA02EED0292B6396EC842476ABF907F24E6BB07BFBAE50FE8ED7627885BCD60C6E3ECBB063CBC7A7ACBA9066B0F8BC7031D490C10560BE15FF0BA51038B959BA1DE73B83F834EE2A285DA8054C70FAB901E02C30485D7EF3FC2FC5B614C590D54EB0B057D4586E5EF0AD07013BB7ABE03C8C0CDD702EE967E3D775D759B4AD61946E6EC404712003B0339CC43680D294416215517B4D922563576364F35502C2DB5DBD142F97D84A659A52FBC7E2C5B613435FE3D104801489F0560FEA6E86C4CE2B123F4FF146678C11A4DE155C19C4991F5F1EAD31C3E7A9C4338AB6B1047211363C04642842159A71CD554BE003D792A13182BCCC92CBB6F48D652E12BCEEE66DD8FB60697A822A00B4B2941690C05AF7A9FD9BF69D54C4E11280AA032483E6D02E114894D88B82A850C9E388FF70CB99411F64ADA0E3B41182ACD5EF03492C887D99FDFEFDC3BC62D1C07E4D6A94EB1A622DD028BFB280D933157DAEBA5773ABF73FE48F3A88AC4962A5C413533713E81C10F1D87647D3E60C99856EC0CD8F3E8C3F0FC76C28E666BAC0162DEAD4DAE1968EF8E8DAD077D5589BE44C985F0B0F3017ECB13E43F35FE9CA77A2D113D488F6940D4EC98A15174E8989B56BCF591B6F849404C1D254D1F8B121D1ED8499C912D10D66551972B260FAE6A4CECDF46F65CD93E6299548E9026A391030D7B6BB4448CADB1D0DDE617202A6B021F565D6F8BAAD62D587D9496B4B61D79A7B4BFC0D0D5F7304296D8DC000000000000000000000000000000070B131A232800769683FE7BFD74B3ACD21AF3898B74CA73DD126C8315538937CAC4EF0AD4588765A26DCCE1C90C559CE691E7EB3E0A497D357E1AB583C761439C0A66D1164518F01B6894067925753CC2866A91552FCD0EF029C2284C620CAF364DE6C56EB41EE0E4431D9BE22B76451D132A3F9AD91A53449BE820A7ACF56F6ADBC7107C7C729EC8A64FFF6A24B4CF83FF4E945DEF336DBFEA6067FCCBD1CD6B5698ADB1AD6DF03FD0A553457B8E9FEB4A1243FEEFC2DF7F66AE3ECA5BF169F7891ADAEA8D5C59012C7AA00A5A86B0A33D0006F8AD5A01C60ABBDA6D249D3FAC7EBFB85103A3A747A45D0ADB7DEF52ED3A5F1A620EE383A9C0CCE1900E413FC74A7A97646111D54783928B15BCA783D01EFC67F49CE6F781E82D25D3F30561F507E3831CB4EA5B4A08D5489830017270B63D8298BEEBF48EB56BDA5685D5E1E06404EB9A6C3790E9B29C99168B10BADF8FDB03F3C568672773EEC96428149CA272EA5A8083F8208BDCE361E7D40BC4DA75029D4A18B0B6AD615DBF849935D4755CFFD270A52FA290811CD55BDCA38ED89F0066ADB9BA7F58366379FFE1CAF3A9127E147C3AF3DC27279391E0C09537E81E20E7B9FE4FE3DA970FE50BFC96555233CC9E61D3C356AAA8EED5A8AEA2327D7036EE03E7EE40AA35E9DA4544B121514C261EC1CB0B2D75B1D5CE129E47F89825F69BA8254163179FC1331A917AE9C5A18556A10C5F983871B1258CB6FC8AD207F97A220C5598860B6C56F1EFF09DE6000241E901A89E107FEEC15833D34D6EB12DB6B188FAA0B858A5B9E32F84F783B43B6F8A3B2E4B044CFF8902E1EB0C527BB4E29C92ACC9DC7E0D9AC6B3A021415768B21DD9695983EE89C871C0EADE0BCE4FB72E682DFB5A2BB7498BF4D2C01240F67D1B62BAA4E587069C16E3032114B14A1C4288FEBAEBB4C75C3C05924A358C4BB7DF95ECF81D67147FAE3F605EDE61B7BA164EBA1AB36ECE97DB0ECB32A673E899B24557D8987AF3ADC57A9DA609914C9B2D6D8AC58E5954E0DB5AA9E75B444700B8F704E15A6A7BBA81809FA8801C6CEB5747A44CEB8F99CFE6D8A2A03C03451E5F3D392725207F3DD28B2C00004425B7AE05FA3769183AB60857B27AB08BCC4321D293C93D1D850D4E7A81B14564D7B15AC0E3BC1BFE0561622C6AA06923EEFE163629EDE8BA1732DBFCAD52D3BAA6E11E569EA790B36A8472B2CA37BD5C0EDD37D8F164B874952D00D592FB705C6B3110A12B03829C157191D33C579593E7828CDA5C24A284BA2F5A42F0BFA601A8F6D3DB1CA6D703ECBD261629C9F96EBC0458737B9951219E5B1F86192E2A85B47D80610A0ACC8B1A70DB2916F89CDB2C7F8943471DDBABD2A3536C5DC8A73CDEDDEAAEDC86FA148D2EE479F8465558852FCBEA0DD8017F1B976281A5014319C2C3CACCBF571D9550215B24134F6DAEF32716802E7945CB3F97AFC1AB1DA17D0C41B545A750EF345A6F88AD5FF52D512AFA6558335B5EB8979D8E6DC1DA562BB997E7D152D9FA3EAA09119C3474E11218230D8A56C19AD87FDE483FBD6DDDE9ACBA813BEBC8505A323C601E5B5251650DAE9334562E3DCC38A28BD7DED6942D0CC2014235C1B66CF4A57BA3010B83CC7050309F57A27207512D195D070DB3D10FFCBACDB47E4231142BAE588F92C5B0A71ABD67CA9390C2E05FD2CF7A1FABB14C5A7AE3773C66DB1F055214479E388B5E6ABF0DF8FD1B0E4F90828ACC397643CBC274143FB4331262A20634877BE4C7489C1AE9EAF90BB2A177A6B5AC15CBDA27DA0616E5F87461554F5686A7BD6D047AD0B98C8CDEA3DB78DD2970C78FB861F2A92DDC277876791C4A30F525659557831F4377065D19ACB384CC68340152A6DE6D84CDB58F433923D1FB8CC6B10BACD95B9AB1B45563998620D192032269FA8301C09A29C4B5B20CA0A3D63A4F5984B7DB0F5B17417DC7B939B9B177BF423E2F3D57DFF296E6E4FF0FB1744B13731206EAD54EF0AA1DA09BEA8B0AC0EF71B73D009D30531DE9FDE90D86BF5F20D8E5A9E324E657A98F8C0031ADAC4385157BA4E28B48AED957A5B36C3B49057F8ECA7F56808F794014DAD170601070607010E004F42D01CC63B2A1761126BA045F1165E25FDD05901FAC6B76E777FAAAEE6F5ED94302E2DA28046B4BC60228E1B9E194F364E377F84681B3011583554B76FBF8D7456DBDEA665ADAD6AA0556C8CC714F217A518A98615C4C1CFC8ADBBD4D12C5BC23AD7A0F849E32FE2005334B55D7BCB43D1C95D4793E7C3882740CDE8DD24B367294496A3E2F3251A66CDAECE9E0A73D853F8D4E3A4637836DED68CB28BA4FCAB02D61FB5CFA581792E636217F3238D78912EA0863816FFB2F388823174B19433C2B14BAB69E12C3B791FE683744D4519455A52555AF0D7E12749F6094AFDBA00FC6A609C7578C531FC4C3C3065EBF78414F112014726EC2230F9BCD9C15E36283144CCBE0D1785B65CF49BA8FEFE92EB6907C0330BC98AC172EA9E8DD4DF8974DD6B6772BBC6CA8E8562C5EC0B6592DE7440AC915C35E0AC8087F22EBA110CA3037B469B1D5BC92636D81881E38D8BBED01A29B3EBCF0C19EB95BF999EB848022592AEAAB649CE19824ED9D3A32D75FBA556EE07606A306D1FCEC2E24B38274C361B7BC96CE37B7F4FE434EBA17AC2A097051A92E4EC32E4C678F7762E8B96EBFD2600C0F224B04B2CD7E9F4AD327D53603828015E9CF45969800F02FA5E0BA26B8C844BA1FDFFDE44303AD0389C1B31D582877CA6BFAD4973BA35FBB90ECDD95F430078BC39AA89434130A5FB8321E51F9624090D0277A9F112EE8FF65D3DBA999C7C08727D0F08DCF00CE22F62C955D6A822F247C8065AB94AC442E1CB5F31254816794CC2556891A523B8AEF09D3B9E07AA8B67B3B87567ADEBDBDFB93BA9A082F72052572C97E73AF16CFC42D2A51A3683F84748A338AAB56264753BA4083D356A27C71F47221ED8340C50AFD46CD207C4F9634AB5A44888A4234770C46232C35EFF83FA950B0A6879137DCE209D5A1F26809B411F046F51FF084F15BFE03292EE845D3044235ADBC299925235462E67F803DAA1426F0E116B93F4532DD2784F7F87AE360281CE21F70D230C242E1A98DE8FE1D6147AD71EDEC89E24A5980C45FD91E23516758AF71DF8E0DD96929D4DA61A3BAEABB96C9378986DEB4C9101175E3AF1E102B52A8DA27D916EE4A28263CA485CFE87EE5436249C1A2F933669F6E3274E9BD93092F4A798AE85D6592EBB54DC65C28BA08582E275972B0A12C22A7792CCFD4A398E504C6FB2CF5EF1F9C268540B4FD7D07D59C49A559D86A56A009C4C18A3FCECA109FC7A45C6E842ABC22053E84878C4805D96AC96BA00FA40FC3B50407141105845055447CA94BD27F234183C2B8BF37F5CD249ED0705AFAEAE59C8BE8F6B38069D67FB23F74284E8185C176B58B482900A3E09774383C7ECACF4FE5E580DF99DB102AD4018DB73C73A635D3FCDC833B000C948D846AACC92ED54FFB3ACAE1BFE205D6B2312658F15DECFA085D13BC3757C754C5704D8089563E0CCF52B04A49DF293CAFBBC2FED5D9551B5A3897EC7BEAA56A4034BEDCEB4840A9BDFBB8BF47D66DD3A4E3EB1666372C6B2C39A48D52761BD36403CB130A087685E2EABB8711C11005EA09F90AC49665415C56CAB6FD2719C45B6800DF914F8FF327EED29D9B9A5BBD6B80B8BB31AD1522803B2C8D89166D5C6B2ED47BC5BBBC4ABE6709D46B856AB81DDF15F098A9AB76A8257E7E5C2E7DAE53FBD691736F0D6BAFE0BB939172614E99C7D7E37754AF6C3C637D076A43DBD70E5EAE910C8170CECFF1621E382D2977635B67F4FAC555419F8A0BB76CCAEAEF4C7385D293C9595AE10E5201C4A31B4C3ECB9F3B304EFB1886F9C58A4EF04E73341B95D9BDB85D706B2A8D3FDD153743A8BB7B3289D0FE79F6A3B9E0FE160DD6700FD64FC87D9AC96858A6D395FEF6F3D2193EBAE7C3A92E18746A7F12B244FBC5B1DF0086CC7045036519D9D7BF8E92B850EA0D3D1E775DEA362362462DEA2D3501D39203E2879070D1F7AC92FA1576F6D12886D5B979E3C788C09A769EF4EE45E14CD8E7553EBEEFCD31FF3D43D4988DB08F6630BA8AE8C7250AC42A3D78EDB967D59310A4A224567D8797C42370CBD2302A3F49ABEAF85FAD9455F98B61EF2B5E34A5C552583872145E191BBFFCAA526F5E38E497A1A1E1220A0F283A935ECD366A9069D5A2A80BABA3A22FA85A2557DB72D7E29EB4E33E8ED8BB4EC2EC7C2E9CEDEF46EA955834ACF8C9AB23B78052446FD73C9D61683D7FA0088DB97D07CC350AF0B6B2AD7E66A493AF814C11F8C0F2FDF0DF40AAFD0D218C00319C367E98D7F10C74EA06D31276F3F216E1CB2F12033915008CC83B00AC60FC9C2FB7F97D6E8CD79650D0F9D82BFD9CAFEF668021D3D165F3FE84221998BC8C29AEA0B5B7E0F1F25A0D7447E806CC3FC39E6038BE3DF9AC01F46222D3A609F8A026744AB4F58A734E3782BEC301EA91F2D8E2242D04A11E82474002143223F29656B1A7675AA5AD181004C4F1381DF6A0F95A0186E82C04B4DE881209E9CCCA3EE5B1DEF0B02353738D92A07314403A1A2721C256121FBA8B8CE9B460 + +count = 99 +seed = CB2E6226615393FC3BD4AB3A412AAA030AAD40E8648EE6B56D2C1591D8B97915D88F2D22F7221377B4B04CF2AE9ECC4E +mlen = 3300 +msg = D21A6BB3A2356805E678673C45FB055FC5266E3F692AF9935AEA307F14A5C41B979966A5DFE42EBFED1487E4822B74AB5AF28995E085EC8007ECA4977C63EE5299FEC63DCCBC42EEACAB488E574249E9D856146750AD97C8A443485EC1C5820BEB0964640010F6407140791E74684DBB91052E2D8BEF7BDCD78B2EC03C97A53295D683BDBE32A70DC19A2F75B8613AEA9616AE0E280179492820F73FB7FA4121E673FB5C328F41B67FF8FFA7AEE6564ADABA046D6E1D6AA13FB24965390F829246DFA8763851405075F76CF94C66FFC3308214DF0960C649AAEDC22926CE9357D3875F8B71D68D75999AA3663C30A9EDF07228BF7DFF49EC1E6C7A33D2053597003B82392E826EBD701B4C981AAAC9951C79E08F592C2C0637C8E5A7F9DCDA599E859C317D4888B4098992E0E2D979E41C703686D577E5BA6001EC4F587140711293D664963632F87EA0461E0E0C5E9D8D292FB409F9F9AB172EE17FC8AFABAD06E42B437CE22924EB5DBD3A80A06962F3B37946259F9C75A233CB2B4ABDC5CD1B648FAEB1BE8630DB40D151B8FBA693DF2C5BDCAA14DC4783F450B6BC407515CEEBC5C9A47BD1A141384F0B596CAB1135C075651CBA989C190F3171DC1D72330EDAA01656813C4B7811715060B023FC426745C301B2A91E0D08ED3BDED438C4CE6799C35F3981C882A0BDE4A2FEEB1A52CAFA47B0C48558FC43F98FE08F03A71128362BB6FB9DA6A22249F4D4352AE7D3DAE85DE497E2411EADCFE5BF1A3C075C45811E0097ECEA255FE15BD8321FE8B546A8CACFB899EECF5419DB363C7567C2FE7360B36DE14674F500A31D3EEC71451A7C0D5576A8939C0F6D4D9F2F03F3C516CE25CE73ABB35C73AA94F6AEFAE6AD87052D6B195FA43586817F5BB974AAE7F1B8608922411AA5B0D7D574016CBD3DED13395623470A108FA0E1D3F9FAA7E1E5031843F2A23DBCE8B196315290DEA5795E4115D53DC570A444064CFA3C9457DBF3EE323B1966ECD2270C32910F8F430522471258A1F1955A6E1DD8C84ED9A566499BF85628615351ABE84B401421DA2CFAF575E2644C9304C075ECFC374066CEC713FA4C0D89043689FBC59FF54B8F97EE0A3B0989BC5E4EF83CC9833E75BC8B67BB5EE3C06EA156611CDA95A6702416807530EA206ED89835D20805EA988B1958569CDF7F809996214DADAB4E20BD44917E3410EC6BEAC98FEA07F764E85B66AED5E17CF675D2ED8E63DB728FE75158CB31779E31379648B43D68CCFF3780854CF03535C57122019456E73CF06769BF1FBF558542241CE665BD10F921828553585E0CF664CDC6160F9C47FA5330591B74194F4716056CA83993EFEC4A52DB9A1FBD3B2F504AC19667325167407375B6D7DE739F07947B511C8D475744E5C29D6E286A37F1FF8317BD0178F0E306A38FA6E75F4A80427FEB2C91235D3E7F20D8101CFC03BB73F44EF59AF3526E9AFC580027A1DADE37654238B8EC7AF0105248FE30784A88B72E11FC1BD807E47A349BD29075BEFBB29730EF8E85E3ABD5105559BACEE74AA27D90D360A8D629DBEC95EB34C7F7CA20096FF7B521E40D3944A975436896F372EEAB6B8615EB91697965BBF955779DD3047F7E3BF029E3509A5780247445D6223D085AFB4291D976EFADC41E42DC2C0728D18F6155654A332FEC72EB6AEF8B92C1D177E3DC28C31971BCAFF76DDEBFD9588BC244B116D409E58DC5ADA1648663D603C47FAEB814AAA7EB9B6264356F926C18B9357BF426B89DDC8EB9177ECEB5C6CDC64DD8FEB7B326BC1BA89BD9035235DA0E644EF959C58DD97B88D5C749B36931AC2694C67151DB0894652E99254222D37CEFE9E27B3DD663A152DBE29A3639AFE42F4578937076180563AAD6AD739255EA012A17D2A56627D84C44FBAB261D392A966CFE19278799CF1634D42384323C496190D4B9FB662694E3887EA66AB9E8B195488C8DCA47C8BC0424247759137CFBF86DEDC3641904CB6FACBB30A9FA84ACF69A67B4AFDF4C2AA420FC0D90CEFA0DFBBCD3072D9F772FD6058E2BF0E251BE93B00DC43765B53DB51B22F12D3ED0CC5655E4AEBD9D923F99A43E4461DCF5992030E66A1CDC3A65558D9BB3A39788D92328387D144850DD3706FD7A079E3D2398F542F91A8AAABF0C5068DBAF1FCC5160398ABECF74884BEB04F3A3EA38BBB80D798F5981B3F2DB6C7B33F867B7DC06A4417E30F94CDB4F523AEEA0BE12BD75AAED57520DB0D4B4F013BE3A1DC7AE5C58FD1DE9637F7D82F697B7E92DA427A78FEEC6A5C0255EB57A43DEA6CEBC8805BC04E04FE789E222B1E2642D26EDC14FB36ECC6092B3060E45EED6C5B35DE8741F72933930ECBD7338CF39474122357365700CB50C5EB176FB92814FA7F4032570CCEE6B859236AD5DA5F1730129EDC7BE218BA9874620F6F0EBC45E0BD622F8FD1AE6974994AF95C6519EC1C46650C073D194FA6EBC62F405F63A3416782A47872C7D77D648D0A1C802FFDFDE5FDC112C94CFC68F401889EFC522FE488FDB5384C0D93147AB6587659D936F98ECFBCDCFBF8B352D605F18C855E2559743ED97991C5D50DF44A7B929303835654A3955ABC5BEE6327400A7CCCE460B318D8B5ECE5B12F606ADB3D7B5ED59563B8E675E78029AABC234442C2463256FE02B04F556DA35C4615D14A9F4EFF17DB0DB81DE4BDD894F6628A120BE2D4CF3E1F46D53817899657035A76137E23C0B0E8DDD29465D7F15628FD435E6CAACA4194FDBF85FDCC31D5DAFCB52568B7C0CFBE713BC85FA424BA3ABE149E4035FC86807A8B876D2163B447CAD5EC0E6EF38A1D591AFB46267F9DBF142CAB1CAC1F73BEBA212992FC6D4647EC17848D1ADBB1901277A5078DD72D9C9184E893C0806E9B4AFF0A824670D438620F2A7E8D2965B619D291E5824C014FC888A36FBBE17356431F0039038F9B497902AED969F9C488390B7087763638E976801127BAF1F53803C4DC9649F0EE85D67B239E2BDAFB2BD75F1D1DA22A56FB3AF10A9DDE7AD306C4AF8681029316C0E1949228E6BF5ADF942F1C0EF92B2BCBC0C70D49E5808851444240A78B14D21B54F66271482F49B85F5180B268050327368496CFA8B54ECB97EE6D28EB74A3742F68583DA046809002C22F7B31FBC0566969F9A15CDCA892C4BEB101A2AC3526C76E9D30982C9B4893450FDEC4001D2431828D24D8B1A67DF80E2E10ED2EA8D723227055C48006665F7DA8E032EFDC70BC7EEB2B369B551FAC542AD6DF1A23107E2B3C0E3CCACC25F26404C085CBF56E52D35D7948DB9FDA6DFC24709994719D8CED41A2CC9B3C4B2BEF0967CB71861CF0E6AEA9BEC9395726AA0E2F1A7247ED0F6038E3DF4BF566786073590DCF97F8F0A99658D8F630A2D130C46CF4D26C669360D0F70B75F904C9F923AB285D5DB129F6C25AD21F9E26AC844D07A8EED86C4E224EBFC5B3F720D6F94B0A01B1433C46B40CF84E80F7A6AFA7BB8F9ACF818AD3CAB2DDD6904C067BEA4F1FE79B83CB0AA8FC75B6B096BAD6FE94ABFD48F8EFC0F2B9A02EBDA8FDBDBE1C77F1854EDBA18AAE7F31CED9CD34C1B355108DF18A8953932F7554AF05B203A96A9BB93E0EFF51D7F93B56E351562CF85A2D35EAE2C2427B89A8662A1C723D4F14E6EAFDBD636C2BB7ADE29C1A6BC8A463734C808BEC68B1E9A31AF6E29B412F1CB8C90A9911AC5C3EA71E46113D2D7B1AE2D8802B06A770FD0E9E4652895E42181AD09BB541E9493F258711BB7BEDD3E7CA8B8CE875669CF80A6880ECA3F13800DE7011EA67F443E505C4FB455608AE586F922B3C83FD33B306BDEDB86223C33E3AA65EDC93CBCF3A03ADAF9F328997951D59A9200C0BA2618E3596AF176B43122CEDC52B1E006EA6D12DC236A6FCD7CC46825F2EF7ED71683A731D746FFF2FE54E0B392A8CBFA38873196BB2B835DCA7CB7C3ED9A004C7A329B9734A111744BDACDB669E69E9DF1E52F07C513E3752A0CCD81D7DDC4A64868B7BB2BBBD2095373480522BE10615248A179DCB61DAC90F7FA5FA9B84F190A9C62B5FF9CD473A940F03E7107157D7EB60AF1E3E384FFE8A67DCB2389B3B0FAB7C789CF100CA95CD6A85442CB9A2C243FB9D454B20BAE5762D72B8FE79B4DF81163D61DE4578CF976992D8B9989FC68089F811F53DB1E1092B60220552876B818BEA981571898CD6AB7B5F13C46B0A076526E3241D65014F855EFD7BDE08AD91F259DCB64E94EC3DAD97811EB024EE1D341521DC92AE5E93C73422088976F2D27D64E1D193B955E6736AD2BCCF3C1A53D590576434ACBC0B687F27F255FEF354E68ACA47160EFA7126F908E08E4548C11546D9C412D685FA84D2EB4DCB2BDFC48E2FA8023548198EBB072A48044F4391143E3BEF4FF9066A4B0D03ADC826819D67588BA84F99DA27424103652ACC039DDD3B567851CD78E4117A8B93AFE01FC8EEBDAA1ACB8BA9D095789E76B9D5AB9EE177A15D666EF171FE1D4BDCCFE2E58CE669B561F63028C6CE26DB5C8182FE048680B175C7AB407215FF3A7801C950D509867AB1B0BEF89B3E38A387915225EDE76F91AAD15A85D8C46EFD588BB3BAACBC52C036211512473420F3F061F5F53E9353DE0780425745A76439B3811511C86CA503251F24113384E1A24A9367536E796CE08B896F572489A2339E82A856C +pk = 0BE5FF5F64E309B8BD4D60D6302B5A9669979515352E32EB57BB8868FB19FEE331A6FCFFA9182234BEF6A6EFF8E6C0FE1B61A98154792AB62128417644231096B994C08BBAAD53D6609EEB59A38AD48B222A87A39EE49B10F8DC7071A9B33B6D833A885CEF1AA7CBDEF93F3B4F5C0E63F62F6E4C5A1DD9951CE2ACED5026AFC9650921CCA4E83437A0D157C82A49384F0CB0E4E5EC9C0BBB812C374090DFF3BCCBD106E58F136124EC62535B55D59EC9A2CE943713752BDDCD7B1FB9A8822BF81CAC626AB3659EDCAC0592CDDB49937024E37C0048B982F3743F1039C56D6DFEF551B8607C6FCBBE7F6EB9465BE42A679433E21970E80CF7557281CE2F19C07BA46CEA9065086963A9D93E12D2F5BA3663F7184B54EC4368AE93C17F8763D56D245DC31B9051CC0D8DF86ECFD79F2CDFA90EE9B0043DB6900A9E6B20B25C79CEC11B9BFFD02528143A87ED9427AA6E303107D37916049F9C58DAE49F89C1275DF99FFAE9932C2FD25B9E6FC61B72122BFD023A6B365E8B2251615FDF3279B7BD0A3488066427C1A28E5FDDCD0272712396A6C83D08DC41382536146CF413678601FA18BEF86806D6D9A44E6EFEB2EC0B418D69DD7F1B1D6D3DE44783A98275D18980037F8458E3DD707F426366440C74B0A38064DE307C95AD1C12696902E08FC66B68936DB380464ACC092577E335DE7FC337E74C36DF4DDCF5832EC5E2B0347659AE97A9359F4498EE4FAC68D6B22BD83752F822C9ACA87BB3916117B027828C95E304A2FA56BA61DEFB014830D852F092917837770F8A1A5EEF5D67E9852D09B42FEE23CA9AED30F8BBA0F184C37214E3F7A09564F69FF66746023313065FEF22A3C842C1D1843F2815863968A66C98A41DB57652D4BFF79FFCC879043EA7FC737439A0A14AFA5861D4F92B4AF986FC7D6B0B8424983E21EC48140F0C9911C46FB50B3E1AD40B21441030665322F784FF284D8FDF33FCCE366A1F615982112DFCC3475B298EC5385750EE9807BB3C7D842B820C5722B25479BFC064520E5A3892896C8E2631D56DA05E1E8646C13886D7DE9E6BE3615EFBA120826F1A3396BF2E13B3B11EF9ABD190E5E2D64C9D34597DF2C2AFD096DBBE437B4971AEE0842658BE19D13C54E0D61FA0DA697F8F80BE51A4D1DFE406B4A15FFF03558858B4B8528A01F5195C6D5E8CA94EAAAEC00998AF44AC1D0F175DDB8BB918DB52A266EEC4351E5998EAE4C8CD25D5818D772DACA90D4C29B717F033D6846B4324E752062880440A4CFE59E8014017C483AFD79BA8A986B71651EC7AC5FD44BA43E93F021D8DAEEDC078CAFE7780C3EF30E75D79AC9F0B3E62A1367BABAB8C0DDC3B109816C87BD351D5FEA04DA6962882E2DCD4771CDF9BDB0D3D8E2CB6A8893AB465E8B822A80DCDA6504E83682F423D3B38D5512EB0485034188189AAFA39EA0D52AF2B18612E3F63B538A95C3057C47A593B8E9ACE8A9AAA312EAE001AA31335B8110DFF950226B9CE1EF0F6DCDB7AAA77F728655FA3AA909596501111C34E3B6151BEA33D5DD379D137328C578E475476E6E45983130DB9D243796B6BFE756698046FF158DE1564A77478E602CA8E683E762E4E290DEE813FD9E680012F80715225968A841C5E501839569FCF1FAD8C47E5CDA9D0852F08CD556B88C8D3BC99CF18929CBADDA7F65EDB6791ECE7BA60EB58553FEF9D8886D9E0E419E8C3D9C2012C67831FA4630BDC2A500C4656CCD73FFD7F4EE47BE3B1D4A92126A303946505B274C986B9CEC77FBB990DEA38D64F496ED0FDEA336F5F0ED614C32DB929BADEBF97A5ED440A2AAD6DAD3743A000E8A207CED390C3AFE896615E723351A033AD566754C4CDE33BB0C31E1E5F90E9E8C64CF9C955AC4B4CE86BA77589F3E87D4ACF5D88FC4EAD1A3F8539A4AF9E784641ABEA417BB0E77FA86E22ADBFAE47E7A64A8EA07FF9A8E8B98188F587EE429A1573C143954F32B8AF778EA1D6A1C31D8016D4AD50890351E838E8E1251B84C1B9913CC197F7F376C7C034F826B6F7539C30BD78219A642A711E9C30BCE766CF9CD795BC02C81D765225EC23CEF75EE6F2FFAA4189D99DC83B89DF767F9DB036722D3865FC3A1776E02CA600CC15B461AB11E668DBE76373EDA7F2C0BCFBFB618F061AAC4AA12D7D07E2EA5C8F2ED0550EB660A56592C3C142E71872CE6CD2549C8B4D3B9F1F4D04F7C0D2EAEF74F6AA82BCF92005282B12C11C8E1146F7DBCEA2D7F30FC571DDB24763476C79CF4867E4E66319C5AB769EAFF3669EA7B3A974C4C3A45B43F8E236A4E32CABE4B2E03326A8D3248A8AD38916DB6422C0121FA269A99850D4C0AB4154F897EE40E1491DD3DABCFA39D83E23914A2CEC51C8AB00269D6C420D49258989F47E8E3172FC415922443295AEB2FCEC999792370840C11E8378DFFF571E23217F699717076C972DB7C881CF8A822253E9D4DCA2B2D4DF75592346B2DE49EE6A66FAE8791152E7E62699E87CEBE9A74F27CC8E31925DF018F5565E6F4516A8A777261CF33A1B3047A24433EF97C9B673973F65D1E5E14BC44D738AC10856E5D59A3650D6FE5E8B62BFD1D9075C0B1D3B288A7079E4B88A75D848F3A3EF5492B56804DB710AA2F08B88C07B006A597595CD8A14F9F7ADC63ABE2537A1E3A187824009EB02BA449D1537ADA23E2CFC97781FC418AA27040928167295A3918D97975D2FFD26EC2259023344F2994B73D828BB38BFC21AD42EDAFF57069B90412D90BDB08387C1D35B27 +sk = 0BE5FF5F64E309B8BD4D60D6302B5A9669979515352E32EB57BB8868FB19FEE35F130B34EC33E8A395F7FA574912DD2221CC4225114D6E1AB37A3203395934696E07E9A642B4A2CFC5442B267A1D2E93A8171C61D06428F2190407B8E9F17257939A803C9C0379EB57ABA6451C0224159BC9F1A768B2ED2EBD9CD9D61C9AA11264257116772717487108067542060764347718272031273140774024527521307444635624456643167144022016222875816760261705407244272471507122637386173473623616663268856227603638615758773452666632450437031211024675563277564588082183404471076161504684683247322734234678645132066338386276232866364540203677222208180521514342043730130304112180078214578872773001334360174103025040432806425000436161471426803665634864564035265617283557473538686678081871726813751873703264761870253300748734824406482345203388851225874828725057265237637771808575108787176555462507740207415162728535834481847554224623037221164462518067780244555436878788134685842818154403174124248708301771014876786116537647565566075150612310504241146242874838530058756756016214622051535223174613030501174374514282042420266470881527851120542186050777482746545683256688618147344671376361345060423564443134208362216317136788860727327234161486886068104286324847303205764176061610624850872068384512421830286838352712781140647302073823613788460808122182660503562616263102630135400875358823186541037148747705240036320286586023884033446518673123428334318614245542221731405337313663005876117547776407717514040884458370386143804151045100776641863668023212206083173302706038180304003668273277442108203262880727278074526347315207070136301647814418161450532173561870201466520052067380241782756574548150417228052408344534183643386614227318228165340006221855834352264553375654280513375232821883756607801606475873855360281042201162251887443654215732552648622483622728308514204583756286386054877032162544488028674341501315666235636882761427771504288234146357565052336786823817210130373638034243111173717588387806246601873650741426306857332173532367544110532745382584256337110885184557508363648784558346846708388635635867717171751223112283507884417707453683878268005508386025580524443352027727877614080054755731242812803247122163873401480728018153536874758314030443076434347722086780831410057556422487152820818585331828117503884182778588380743260650253244800862318843451764542688003706250474153776302102707162052607158156544608018343134014061024255148873716386757533412653312467171318673512326416008618761736883332822000843060630348521615030473374862880470178815262886313340312244834858034268024310821754651588084071112645427830513023115253828167847827507432263830777047703035676073863156575112658422087563188522278027652822378835728727158086373787681301115485868271377536626720841506572304622045845735150837132828278677886443742366087248082425571547877575828867727626224438605881720276471675042763803774552812688562406840323534350178262232050180225176314163067848581747672177838060730774026808075105261865530400175803047280345661707216625854106456070821221286483842764381280228384676635306432804575321160161381567830721570548536166552462611121087032784800276183426054035602706323367268235430B21D3D7F0F0411D63A751587CF20FA57F6140FDF473A9EA0D21D1AD229DD090055CD31FCE38BDC1EACE286101FC01749B587B0D967A1784B15ED8965DFED7014B70B94B7F7A1993AA760F9B706AFDC8C7AF45A165340D39A403CF17879EB16DAE6DEB99D3E65809A227730668D6E875497800169C1A9A7A841021B68D7EF3B8F1156FA9154BA7020A12F0C405EFBFA4FC470F86D8D30624231922CF6CA270129134B4BAF5814A6AE14A8DC89F5CD50700988DC40E1CDF1D47D0C3727BC7C1881D9CA9787C465968397614F3DB7878A9F9C92085214303A02459556C08FCDC0D0A9063E6A41713A0D322E8286343924ECAA864872FBF01B6564508A05C39393E51EC3B57A1B2E2EC6E5A410FACA9E8E9D61C06EAF367253AFB51C491B70CFDEEB7FA2B0C34D6E561308468F75F5534F5D5E73EF2D9FF508AA99AA3AB323689C414AC6BA38BB3FEA737437D4FA8270E18F87B7097C933C1C28BBAC8B70D3F50B574937B5CA45548CB4AABBB6E52BB8B42B47F2CDC4ED06D2040A136CF3D8BA63E878120588C8D2F6972A259C2493241879A4A10B5BCD0FDBEB7BF78888DCE0B1AB58CF97D8FBE5423F853BB93804B7B73CE2C5BE1D9D5B5C3CF5EF9F479EC90AFACE0A192DD5CD7B3341545642DB5C0EABC087FB2A4002CBCF1A060187317B4FB51DC9A2CB2AF6EC050C05AF1CC108CD0777749DF9653258C284DE90AE6073BE43B07F18AA184251528D8A6271982221D66302A29FA0E47219522733B82384ED1F25618CE5B7C0C27B989596A9AD7A3CB80DBA628567E89A181800D868240B6E2CD8D1EFE836073D4B8CD1592D887A894843594C93E4F954630963EB625B3CB6F5F9CC3F5344587A48043E343E4BBBB7FB12FD0459B1C4504BD5888C7B47B445899A52245D4194EBC15F11466954B762B67D146D5AFE3A398249EA5BF025C8B2093C268E257054AB967DDD9805FFDB9D580046FFFA5CE5A241D844504E13F8F73A96954E9F1AE39A7C18FF2AA8C4A5E5F39745A85AE100BED2A2EBB6515DCDC5E8FBC3F31DD840929AB83784C43523BDCB5AC446C6C14156E53B7CF7F02EDAA6E925A0E3CE8CD05B6F6B3EEA7CE269DB08964EBE6B6C09E921C4430592B370A040E32E21CFD505557AD5EC5F24C1C49667BFEB55A45ABAB3FEE36A87A1365039874D72499B270BED728D20B4E755245D14865E6728E6DF45F872EF0DF82B348231C63CDBD1532A242DC9EA9200CA6C52793D9AD7592FAD95CE0854661CA99FDDC05049DCF16F459356194D9596199B3297014E474F12BC3AC1B1B0C62E52CA00175F76E7CC2FD188F5FC8E6E551C64E98528A36221C31B2759110623FF393877F3B51983C386E550A1519C70543D733962EF3891730EBF70A1E56C57FFA81BF6E4EF1E9D00E8C62ED1BEEEBD0E3673B9BF25CB29BB910D51090804FCEED75F38116E4EB636A65525E1BB8EEAAE955A6BFD6D90B42A484BC332D2AB095E57EB37AAAD1FE2787F312DFD98B18F5DC8361EFACFC979C30BFE73BDFF894361C50653DF3D5E37D1CCC1A545C7B900652F5D20703D77E968CBF5431F5A002C64A363D5EFFF2C44686EC1D36CD531E2DD57B65A132C2714ED71354571BAB3757E7F0ED2A9F7E523A65762E45BAC528B1E60E43B536DE4F7C69BC253A6EB096AF65DED3CE726EE33CF6FEC17C75BA02ABC8187E25CCF8B4EDA4FA556EB7FF8D3C1BEDFF29D2AD3581EAFEAA4AFF50812BB13D136AFF9C2C10F8D84CC26FEA8DDDE767FCCFFFDE0D15CD15D37F3D2D390670EBE7A7FE79B4176007B4C05BCDBD44CD8D50A85246FF2518F94722062343D3C65892C1F6A20772373E495E4D8C12F87DE137C9A65CDD46BEF9F7F9D92D1479780FBD39ECEFBBBFD4D0ED9A252B893FFCB1C88EA5A1D100DC9795769D74A7F0009422CBA88D960106EB5D36EA719C5D7AEF446A950E159B10B8CBB58AAEF037545623838449A7DFDB3B82FD1C8D8187A7911706DD51DAC09990160D5040B2732B8A542F326ACEA73AA00934EB8B8CD6543B82AD6E53A6CEB1149A15C9978ED36E5FF7139C9B39D721686C7B9D1798BAEE92849CED26C366B8C6644ADBD2F980CFF7AAFA57A0032825FDC1F3FDF0AA1B6A0184579C7D12700B73EEFDEE1C2FA459ACEA7CCEC534A449701E2972BD56B79FBBEF32B53C886009874C6CA21C65AB1AD0541DF2BE78BDEDB5662D6140562F1C030FC799B233766C94FBA494D26F1574BE28E6B9614CBE60521CF0B24D89735CDAB8DA1F37072077E70A35A6CB27AAC8BCEF86E67D80E3D9A6182B87F99E1241FBD4445CAD4D89BBA4998ADB82A68CD22D665D6603C24E6CE8D6B034959EE4C8B71774E679D324ECB6D4D607D7E028019732A39EB0AE39201B57D58E5A46E1E521D194810011999F052765CD1E2664B88B2676ED0FF601032E3D8CC5AD0EBF16E688E354E822EAEF9EF75F82039C1E121038BCE902A26FC846B58C54E686411C4B36B356E4E570BBB210A5B0AEC58D83E2465BE86B53C67AEAEC14F6A6D500E38CC4BED63A8B5F42FC8F8D9830D59EFF6D47354D1DE1438B4B78C40113A37D40D029E1830E6204DBFB645FAAD4FD1A96A1EF05B67A9BAE61A195FEBA4467679B71A187E60A827BEF455706843130119DAACC827DFC1D91185A6B5D77E6E6D5CE08CFB24ED0030265F0FD4A94E1FEC1C18C7B291C3F9F18B35055DE503C7E0ECA0750E4B9F2962A6E7D86DE27AA10429F2CF3EB6F207591E8E9AA242A8090BFB03FACE3E1602382F6FC3CABAB00D3B75EB31B9E33DA90CD1A99AF9D47A42AF168E37AAB83CBD1C7C26BF9AE6FA38FD645DA007040763FB0786065EB23EB29295A1C243B1FDF6574D9A726E0BBE39AD4709B4D156E37F7C52E5319AA30CFCBEF9998ED1D4FF9F138D5BFA1BBF5A8423DF4CF8DE22D022AB5B17F329C36A57FAB79A2B33014D07FF50D5883B482E61409CCE624B4DA4A9DB5285F944CE0B5D373760F765FE8BA82D716CA55CC6DD8F170A5BA3AF529DD9FAE99E8CAFEE482C85F9D534FA6053129A2786B79C563850DA03D97A443A53B872DB257BF9BD350581A15BA3FBAD6288A12F628B22D5F730033B0AE4B3202FC19491E635B44D7FE699CA403460F5F621B6682B271CA5BFEF87673BD5D6EAA59F52C3FF61DABE6BF00AAEFD4962D8546E03B85C1DDC2C8714476FAC4019887D6558FF7C9775F76DB44D69C96EFDD4C9B802BED3A956602860C8285901E0013515503DA82E358BEAF05E5BBE681C6B624E4996ADC948426DD0165106218509ABD11470AAA4F01DE8482615A57551EFCAC76C69C484B2F54329CE244AC098D803DD78D01C134D21F10D93A4D65ECEEDEF614B8A0543E088F212E81805A0448BEB3B7AD580CE20AF6B913527B9443E54201D9679806F759B3F4405FD5C4AB7816A923EC094B1EA8A4A04EC6D935D3DB09AE39F77F57DCC486870E338BD4447A2BEAED5AB60D317C676B86FFF7C2925470090EB6647EB432F7C100BD7DA172CB5180BCAC5A27197A9C0C4739CCEAE3 +smlen = 6609 +sm = E9821E1EBB6CF047A7E9919852165E30934F31C5A4B3DA3420455B24FB1697D912B80CC56045DF3832C03D3D5C290A9DF1EC80111BDD74A5E5A7269F103AAD13767E2215B538C7E23AE238DCB986FEDBDFB7BE23D8872CE276FA988BFA7785E6A9A4B4A5302D490FC2459A1869C518C641BE32EFE05E70A148FF7B895A5865C1FE65F2E9FB4BDB2F9003BCF46645EAE0810F599643E69A6C80457770B4E8E7F01AAA6C92950366889C59465A160E295A7EA017BE2D66112BF6327F04F52F351131E98CF8093462666764B9248C4AFDF272A46B41F438643CFB9E27F6E811BC39FB66F2BCF1280CAA0418BAD218598C4AC45D28840D2B4AAAA6142C7E3EE3E7304CFFA0070721935407DA5E3D6BB5FEEEA8D476CAC532B2F389A34CAEAA39DE91D8324E59B07C256D28FF220F8A98CECDAD4F96F2E8632F7226456FE6C063DA1128027BDECA3A79C71A5F98223BE91898910432E7D941F04855AEB09EEDEDA06D61B44177F99AF40C4862998F0D9D40FDA68A9679E9C0D71E574AEAF1E953A5E2A454A0439457D06B52EE3C95A2931EC9A93822B75AB6F1D7B65C56DC0F9117492577EFA52418D4FC3D1F3CF2A45522F36896E56F67F7C9D418791590CC838E59F335BCAD2E1A9288919192CC4D8B3B441638741CF6632505982FE9A3DA2BD1B1B7572D38F39918D97753AD8E3D04A19ECFD5DC06F3FD9503AE1F5674C5DA5F2836BE464D1E50F957906140A0EB801B74223F3EB2652E90DD0C21D9B948CC02A73B3A4EA58A0C409537648D8954CB971D3017926120442933171C473458A38B83A373CB2ADC6AF1413F0453AE2BAA00D12232A3EA2FDA821904B48BCA3501F77CF94F7216E6C1037BB55727C821389CFD9F63951E709B84D22C1F1CDAA493154F1C7AB9427AA69EB8A864B127DFBBF70A37AE3E1B09B8DED6BF9FF09CC063324BDA75FA6BEB288FDB482B71ADA6F9A1A80AFF0DFF242473458C5BD0793EA91CD645A9BE6BE9F77EB4330D3A68A7064FD8BDD63CE92DB97FBACC04493F2FF168D239DBA906A61B9A13FF504920AEF8B98F8EFBAD891CB9B89D74FB6D6BF9229FBF4F44CE8E41863F43984295ED77BB89341910A69B6D49D6EEBEA1E29FE495A8ABE32118380BC0E64F5345CE6C877E232F805F35B607E8A5A46A6603259206A1C40ACD31A3208612FC9B1F0CCF1D4659D3791484EA8F8E1830A0CA05EA80ED4497CFB1720E69D36024B77DFA9289AF7085C7AE0C7F5EE6530AF391BA2F849A1124CC2556EBA941635D90811E685BC2B0E54AFDD11CC5E7F78BD32E8B37F7CCCEF449AE098F7B34D78E42C9DA2C40E53CBC87DC1C2554B041B54F88322FD3744DD39F7CE848EA68AEAA631116B9746EC85E1F3647D1A3EC1B10F00B3B5C60B54B133D755F953CABBB88D3D0BF6F2DC7FEF4C7218ED2502A5E5B6F27C052BC07C4B794B8C97D7EF77468E211192DFF546387CCBB47228D5C99996034296773FD8A3A1B4E349C109A86F76A93BB3181DA59803675063658A1737658E6C9BC40064161908F24BF57391656387B94812D89AE8EBF679A9E6040AD549F85030D11DE610F73B6290768E17EB62F7210975B9FE047A0B02EB68F58734095078862DD9D35E100B5008BCFD01A1A28594461B8935444470F89E9DA3534BD11672E417B82A6BEBEEA76BA64923FADCBBF7CFB2C382CFEF157B2D3970CF7FDBA854A1BC41BC70EA083AEC2EBC14D7BA65C3B220B5E3F1908D2C63B42DF2B6D43BC1D222753EB39DE63709EBFAC42327718F096CA7C2DB300DECC5C56DB1F554C8018D7E674A06E8596B9903A6FBD41E7142EBF71479C9CD2670C03E2FD02BBAC4DFA2FF559B8F19D2C5F063292F9493B3357A83959D406C6E5FF06DD9FE00C89A5422562F82347A5ABD9AA1B5ED4DC427327F7D9D605C8D34073E1690FBF6AA58DE9AA34F8B126670B223A6A0FE0EA1A7B1B15A00D28880F18CAF624C30A7C908270C267885002D7382B61C575729F574FDA3E9EF2D1528674B7D23DF8E392128EEE346D67D4D7D3C4DD4A8B95FC0FCE7A1BBD4A6017840FDE3BD0F04D6D9A892BC975BD54FD4DFD9FA06D9719B6DFB224470D18FD81B1CE3D562169C5B6FF14AE7F23212A94798A69B106B041D5A4513813D305D72A8D0C1F2B8E0929CBC0E10705E7CAD1399012A7EC3CFCE1930400D4B053552FFC5792047054B877A02129FC3C4CFDF77E7EE2EABB769E8E925F2850413007BA5B1B54F7E3611776C649E9D581F378B589E9E8350BD3DB0F732C0D9B1ADC422F53F1CFCD1669BC0302E0ADF624B284B95520484C5633EFF23CF817B3BF14BB97053ECE0EB7092531ED3EE56662A2FC57240CEA5032F24E9068764F3B7D47F8E6717EFE0EEE2421CE5E3C277D4B20004595B7AB79165BB9CB3A66F0682AB26999E3D3A10D025A0B0A69440ED45116CFD989FAB45453AC54529776830B6B721C35B812D29315E67BABA3538FBE4A9270A7B19175CB250E820CDE7256469028F9221338EC6359A72B3BA94DEE7D652D878B17E9F48DAA1B43295451A38E8EF689088A73AEC19C0A013E9CF4E55B606E6554A7F1158B65C44A788C0D2EA833EEB21EB535A00CC8E8D375D1E32C571A7BC3A3E0344AF2654A356ED2AC63DE44EE4160ABCB8B956D40B7EF8084F539FC568C79F03BE21832AAAE0CFCA41363E639460B433BB2695BCFAE481E2D1C97572A0C69D9D84DCD98DBEF893D20D4A56891FF5186B15E6A086DFF93BC3D7422EA72075F446E527207C9F29C84CEFF034AC701C77F1262BC57E342237F1C8E2A8DD29B42E258E0D9D5BEB541466289AB606876678077741209590DE8736A9B4C1265471ACAF2F2D11DAD96E0E57D4707228F86D5D271D64378676E1C09E343EB9E5BF4676A0012F796AA9E12BDD0D9B1D1970383A3C6A0C345BB096FE24841AA91895DDC3DDB2D0E59AC8A0AF7A0B46318D9F9012BE253E9CBB1028C5EE52813BC7118B982B3EAF090CADF0FAC9266740BD6B346EFAF3C34084C4566B607308E9DE8EDA8D65BE7D6820473A23D7F717C5DAA9395456B2A6837E31601F7E26750D89B2690206229637C9C117F4F69D3DFD2639959C0AFA38C9090C394CE481B73921F8AA65B2C85ACB0EFDABDE29399068D4A6D15CAB86CAFF50F236D23652137C8CBA2FF7B37929A23752EE6220B0DF6197028CFC7B6296FFAD95A7EC03568E8288C5DFB85D4FB09710E7B28A4C926DA50B7C3FA29A540CFCE9B51DE65299A83684628C115C362DEDFDA49E008011B78298B2292D2943BB4E66FF8A08717EC6C1E21B6803B9103622C2048DCAA11E6A3991CCBACBB2B70557FCD46A3B0E094F329306F12BCF0F3034203B070A6F285811DF322EE4DCA54A215E06481145769242F80EAD907FBD9B4BB44F5FBBDB4FFD940F230B12743EAEC82E6B86EE6A2210938EEA8FE938F48F6B82C64ADDAEEF68D70B8B65DAAF219414488F553B0683B7ADF79DDB06C9C59E2FFB507945E278367E476C7621D066977ED1A26BEA9B6E92200F5557D7CEAE076774E9F37AE19822B8617B3886361776C77683F7251CD6B52EF221CB349D808FBD98A703E7C06415C615D04FE0A3B7BFCE69FBE204D8A69D7DE1CB3CD6BBF661D332DA321678FBC2D12A2008053A40766ECC16F39AE37D8138CBC4648FDE81831043D04470C1831CA7A35D7867653E2428530251CD2B966A5CCEAB264E62B4BA107A17AE7E37AFE7074318E456053970A89B3F10F05243D8EE5B71EF84272A2E2342075BD5474D2E96D264E7D8AA98CC53BE8EA718992F6630AD8BC05585202852A653E7B5381ED152CD38E8D05BCF22133C763B001F0C0AEB99D77DE7567B6C429C3B67514A9D19A8953E490ECF9AE5BAFFBEEDF71199BC8423EDC46EF782A3523BC71C527EDAEA6544F325035785ED12C0974E8CE1C8A98F72556E578E36FB30DE6A6E50EA43C8C73CB0B5140FF6B56C90871D852011E9A154DD9087A65687E5845161585A91D3E375A6927A5CA9369FAC9844852C490DBE3960727C64C5DBB4735BA5AE730DE1ACDA4B495706A04FD7986F834418D9C7BFBAD918692A2E5A3AAD83D3A706DF3141E5164F50C77B5AE7FFF71551B81F9A0FE180497333EC1B1DEC3A67910DAFCDF264B5D79892CD87AAC25B0450A4354302350873A28B310A87FE4A94FCC6BC561350AF39F2FF3F8EF5A8BEC775BC2E275656F9579A6757F9AB14808337713A12B45CFB6AB0FC933DABF409DDEACF463D57F6F5799451FBDA1C38B50C58574D6E36218F6BCCEC992313B9D816B0EB7CF7A135ED5DE1EB60A92B3CDB1734846A87231EF4BD57410C6D48050D4EA4ABCDB4067F3EE1A019B61527C2B9264E1AB662F85A77D5F6C76DB92C8F2E2F1F6921B4C4D057C64748D665B54539182D648B8CA418F103885AA2F7FB32C1F26F2CC2F44E1D301A541758D0080AB945C035187A97E9FF355C828E1C1A78348DC6707D37DB7AA58C06297CC441F35C95E6236D786CBE872D2F3CB34A94BB11E50C0EBCCDFC554F36BEBA4046A9EBAB31172AFFBDFAD184CD32E26D25B7188E518DED332EF95D592826A70A45E266654728F41C01E2B86B4DA958602031E65B0BF222D369B3D6879CCDD1D246E768397BD060B0D1B1F2B414C607CCEDC112839517B8EBAC4C9000000000000000000000000060A0F16222BD21A6BB3A2356805E678673C45FB055FC5266E3F692AF9935AEA307F14A5C41B979966A5DFE42EBFED1487E4822B74AB5AF28995E085EC8007ECA4977C63EE5299FEC63DCCBC42EEACAB488E574249E9D856146750AD97C8A443485EC1C5820BEB0964640010F6407140791E74684DBB91052E2D8BEF7BDCD78B2EC03C97A53295D683BDBE32A70DC19A2F75B8613AEA9616AE0E280179492820F73FB7FA4121E673FB5C328F41B67FF8FFA7AEE6564ADABA046D6E1D6AA13FB24965390F829246DFA8763851405075F76CF94C66FFC3308214DF0960C649AAEDC22926CE9357D3875F8B71D68D75999AA3663C30A9EDF07228BF7DFF49EC1E6C7A33D2053597003B82392E826EBD701B4C981AAAC9951C79E08F592C2C0637C8E5A7F9DCDA599E859C317D4888B4098992E0E2D979E41C703686D577E5BA6001EC4F587140711293D664963632F87EA0461E0E0C5E9D8D292FB409F9F9AB172EE17FC8AFABAD06E42B437CE22924EB5DBD3A80A06962F3B37946259F9C75A233CB2B4ABDC5CD1B648FAEB1BE8630DB40D151B8FBA693DF2C5BDCAA14DC4783F450B6BC407515CEEBC5C9A47BD1A141384F0B596CAB1135C075651CBA989C190F3171DC1D72330EDAA01656813C4B7811715060B023FC426745C301B2A91E0D08ED3BDED438C4CE6799C35F3981C882A0BDE4A2FEEB1A52CAFA47B0C48558FC43F98FE08F03A71128362BB6FB9DA6A22249F4D4352AE7D3DAE85DE497E2411EADCFE5BF1A3C075C45811E0097ECEA255FE15BD8321FE8B546A8CACFB899EECF5419DB363C7567C2FE7360B36DE14674F500A31D3EEC71451A7C0D5576A8939C0F6D4D9F2F03F3C516CE25CE73ABB35C73AA94F6AEFAE6AD87052D6B195FA43586817F5BB974AAE7F1B8608922411AA5B0D7D574016CBD3DED13395623470A108FA0E1D3F9FAA7E1E5031843F2A23DBCE8B196315290DEA5795E4115D53DC570A444064CFA3C9457DBF3EE323B1966ECD2270C32910F8F430522471258A1F1955A6E1DD8C84ED9A566499BF85628615351ABE84B401421DA2CFAF575E2644C9304C075ECFC374066CEC713FA4C0D89043689FBC59FF54B8F97EE0A3B0989BC5E4EF83CC9833E75BC8B67BB5EE3C06EA156611CDA95A6702416807530EA206ED89835D20805EA988B1958569CDF7F809996214DADAB4E20BD44917E3410EC6BEAC98FEA07F764E85B66AED5E17CF675D2ED8E63DB728FE75158CB31779E31379648B43D68CCFF3780854CF03535C57122019456E73CF06769BF1FBF558542241CE665BD10F921828553585E0CF664CDC6160F9C47FA5330591B74194F4716056CA83993EFEC4A52DB9A1FBD3B2F504AC19667325167407375B6D7DE739F07947B511C8D475744E5C29D6E286A37F1FF8317BD0178F0E306A38FA6E75F4A80427FEB2C91235D3E7F20D8101CFC03BB73F44EF59AF3526E9AFC580027A1DADE37654238B8EC7AF0105248FE30784A88B72E11FC1BD807E47A349BD29075BEFBB29730EF8E85E3ABD5105559BACEE74AA27D90D360A8D629DBEC95EB34C7F7CA20096FF7B521E40D3944A975436896F372EEAB6B8615EB91697965BBF955779DD3047F7E3BF029E3509A5780247445D6223D085AFB4291D976EFADC41E42DC2C0728D18F6155654A332FEC72EB6AEF8B92C1D177E3DC28C31971BCAFF76DDEBFD9588BC244B116D409E58DC5ADA1648663D603C47FAEB814AAA7EB9B6264356F926C18B9357BF426B89DDC8EB9177ECEB5C6CDC64DD8FEB7B326BC1BA89BD9035235DA0E644EF959C58DD97B88D5C749B36931AC2694C67151DB0894652E99254222D37CEFE9E27B3DD663A152DBE29A3639AFE42F4578937076180563AAD6AD739255EA012A17D2A56627D84C44FBAB261D392A966CFE19278799CF1634D42384323C496190D4B9FB662694E3887EA66AB9E8B195488C8DCA47C8BC0424247759137CFBF86DEDC3641904CB6FACBB30A9FA84ACF69A67B4AFDF4C2AA420FC0D90CEFA0DFBBCD3072D9F772FD6058E2BF0E251BE93B00DC43765B53DB51B22F12D3ED0CC5655E4AEBD9D923F99A43E4461DCF5992030E66A1CDC3A65558D9BB3A39788D92328387D144850DD3706FD7A079E3D2398F542F91A8AAABF0C5068DBAF1FCC5160398ABECF74884BEB04F3A3EA38BBB80D798F5981B3F2DB6C7B33F867B7DC06A4417E30F94CDB4F523AEEA0BE12BD75AAED57520DB0D4B4F013BE3A1DC7AE5C58FD1DE9637F7D82F697B7E92DA427A78FEEC6A5C0255EB57A43DEA6CEBC8805BC04E04FE789E222B1E2642D26EDC14FB36ECC6092B3060E45EED6C5B35DE8741F72933930ECBD7338CF39474122357365700CB50C5EB176FB92814FA7F4032570CCEE6B859236AD5DA5F1730129EDC7BE218BA9874620F6F0EBC45E0BD622F8FD1AE6974994AF95C6519EC1C46650C073D194FA6EBC62F405F63A3416782A47872C7D77D648D0A1C802FFDFDE5FDC112C94CFC68F401889EFC522FE488FDB5384C0D93147AB6587659D936F98ECFBCDCFBF8B352D605F18C855E2559743ED97991C5D50DF44A7B929303835654A3955ABC5BEE6327400A7CCCE460B318D8B5ECE5B12F606ADB3D7B5ED59563B8E675E78029AABC234442C2463256FE02B04F556DA35C4615D14A9F4EFF17DB0DB81DE4BDD894F6628A120BE2D4CF3E1F46D53817899657035A76137E23C0B0E8DDD29465D7F15628FD435E6CAACA4194FDBF85FDCC31D5DAFCB52568B7C0CFBE713BC85FA424BA3ABE149E4035FC86807A8B876D2163B447CAD5EC0E6EF38A1D591AFB46267F9DBF142CAB1CAC1F73BEBA212992FC6D4647EC17848D1ADBB1901277A5078DD72D9C9184E893C0806E9B4AFF0A824670D438620F2A7E8D2965B619D291E5824C014FC888A36FBBE17356431F0039038F9B497902AED969F9C488390B7087763638E976801127BAF1F53803C4DC9649F0EE85D67B239E2BDAFB2BD75F1D1DA22A56FB3AF10A9DDE7AD306C4AF8681029316C0E1949228E6BF5ADF942F1C0EF92B2BCBC0C70D49E5808851444240A78B14D21B54F66271482F49B85F5180B268050327368496CFA8B54ECB97EE6D28EB74A3742F68583DA046809002C22F7B31FBC0566969F9A15CDCA892C4BEB101A2AC3526C76E9D30982C9B4893450FDEC4001D2431828D24D8B1A67DF80E2E10ED2EA8D723227055C48006665F7DA8E032EFDC70BC7EEB2B369B551FAC542AD6DF1A23107E2B3C0E3CCACC25F26404C085CBF56E52D35D7948DB9FDA6DFC24709994719D8CED41A2CC9B3C4B2BEF0967CB71861CF0E6AEA9BEC9395726AA0E2F1A7247ED0F6038E3DF4BF566786073590DCF97F8F0A99658D8F630A2D130C46CF4D26C669360D0F70B75F904C9F923AB285D5DB129F6C25AD21F9E26AC844D07A8EED86C4E224EBFC5B3F720D6F94B0A01B1433C46B40CF84E80F7A6AFA7BB8F9ACF818AD3CAB2DDD6904C067BEA4F1FE79B83CB0AA8FC75B6B096BAD6FE94ABFD48F8EFC0F2B9A02EBDA8FDBDBE1C77F1854EDBA18AAE7F31CED9CD34C1B355108DF18A8953932F7554AF05B203A96A9BB93E0EFF51D7F93B56E351562CF85A2D35EAE2C2427B89A8662A1C723D4F14E6EAFDBD636C2BB7ADE29C1A6BC8A463734C808BEC68B1E9A31AF6E29B412F1CB8C90A9911AC5C3EA71E46113D2D7B1AE2D8802B06A770FD0E9E4652895E42181AD09BB541E9493F258711BB7BEDD3E7CA8B8CE875669CF80A6880ECA3F13800DE7011EA67F443E505C4FB455608AE586F922B3C83FD33B306BDEDB86223C33E3AA65EDC93CBCF3A03ADAF9F328997951D59A9200C0BA2618E3596AF176B43122CEDC52B1E006EA6D12DC236A6FCD7CC46825F2EF7ED71683A731D746FFF2FE54E0B392A8CBFA38873196BB2B835DCA7CB7C3ED9A004C7A329B9734A111744BDACDB669E69E9DF1E52F07C513E3752A0CCD81D7DDC4A64868B7BB2BBBD2095373480522BE10615248A179DCB61DAC90F7FA5FA9B84F190A9C62B5FF9CD473A940F03E7107157D7EB60AF1E3E384FFE8A67DCB2389B3B0FAB7C789CF100CA95CD6A85442CB9A2C243FB9D454B20BAE5762D72B8FE79B4DF81163D61DE4578CF976992D8B9989FC68089F811F53DB1E1092B60220552876B818BEA981571898CD6AB7B5F13C46B0A076526E3241D65014F855EFD7BDE08AD91F259DCB64E94EC3DAD97811EB024EE1D341521DC92AE5E93C73422088976F2D27D64E1D193B955E6736AD2BCCF3C1A53D590576434ACBC0B687F27F255FEF354E68ACA47160EFA7126F908E08E4548C11546D9C412D685FA84D2EB4DCB2BDFC48E2FA8023548198EBB072A48044F4391143E3BEF4FF9066A4B0D03ADC826819D67588BA84F99DA27424103652ACC039DDD3B567851CD78E4117A8B93AFE01FC8EEBDAA1ACB8BA9D095789E76B9D5AB9EE177A15D666EF171FE1D4BDCCFE2E58CE669B561F63028C6CE26DB5C8182FE048680B175C7AB407215FF3A7801C950D509867AB1B0BEF89B3E38A387915225EDE76F91AAD15A85D8C46EFD588BB3BAACBC52C036211512473420F3F061F5F53E9353DE0780425745A76439B3811511C86CA503251F24113384E1A24A9367536E796CE08B896F572489A2339E82A856C + diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/edge_cases_draft_dilithium3_sign.txt b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/edge_cases_draft_dilithium3_sign.txt new file mode 100644 index 0000000000..baeabf2b30 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/edge_cases_draft_dilithium3_sign.txt @@ -0,0 +1,512 @@ +description = baseline +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = short private key +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D6090581 +valid = false +smlen = 0 +sm = + +description = long private key +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D60905813200 +valid = false +smlen = 0 +sm = + +description = private key with s1 vector out of range +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A36401C37F701D3534F2B12BB1CF025D76C2E28CF618C0DFE01EAEB99E89244BD9ADDFB0EA382BE7FD5B84FC7A542DA6DF8018393C1CB4447CD8A57A2A4010EF668C892162120262656660577537620858306877288262032550153645008243057054217885086730253027718543115827673734834021026655848872507780160307120610653807615026121011654045584742242028050076212304644622036857780160574258268153175682380507728864805110378511663401100281288612604554431023467464318607638564716220174250501806756485253788101817760728110332166223400053388866140755703256378713651266251025143727143862156512628830358881868827351366230442135233067730826283313276701663806868606378477354802251542518664580001676813105243524037547434312857600076111675044534078713415665851221862481576565288714147773755146042124737138577158807552174524665527655475711031167755773405268058885826085172715016873355756131635087773263680176517822621475634868037374581758202262826405358827453764185573441285177646637046482664734215076273628557418472536417670624837714315770036225287425417545552835381262180632774576104156422128657852728607634888226030104476341211350275417301320538568576126854705873358535286252876730066607400671077451488287474673781057376755636736300351584316776077034760530472112026628657855477551476720662364873460023778603037564413774656371300714764330504086315152870325575220164151244123320758775702584254563302118684674181206428565763726336522613252227150246387837431861718613367336681068173381155570303618371877421018621034688423711364265326872170560016737288183135386051588605005575601562300482072351276338850813627300827045360182475734107841807172823405464035682762454727085134112788152668335867881603747747886438728275143456437138372534838423544772560485420373145867133245230318456430385001513766856401740560506632507806758013070578760882087560664118431087766457301152570784374156607668135523235127006508001844765168205625675515522851306463808170330288717426340542061017182525753272483381887050415385621873518551456220162640581837416542202384673046227788087360284411017141668004300724058448772845202481185421185106346558106858851458334352156853014853775434371558770778756562750800618155783837362317541122253861613131105617835532140332273154670126080050054821553732466882528661165754206308744168278778886451752026474481361880682130111255183607483727825030054507078150465157304487813686635646518564474314147540677352760104147038338840886546367137471653273322815730234801515416268273212123372142508026803610111663547542260815761245004581623328122653811435308228387031216118038527465681043658728857732880011211842720148824782314800256806645741246087368061875721027666682312103868210735466403846013883051130172662338686665824445442680428744316636068502645333342510762032110182576265825132061332306783484382753165436032405062768011781085432483762467688218557682520377778334416064410850584515378203731655448168158187085814234183301526115577255068758827451712316307151624186053783455822606128666687000188750627024377333667F9EA90A30BF9214EA584EA87D0DCF45FE8C7D03D54E169A64CBB64533F801D4563E1718D439E86F91E421B90B02F63A4D8BD005575DD0BADBA5388C48E8E3167D1BD314810FC2C529C220C89EF3D1BB549EF3410719E6CCB2E2C359296F20D9B717704B98EC5861D0B74786BE357E3368EC11FD0783034ABE1D432AE30FA38EA10775686453B73450BAC84F76F2B525E6A9B937BAE8A593BB3E1D8FA3F33A55C20864923A2274BF766C405E785113E5EFB2D572369148BE39E03835A05C904866719106C11ECEAEB08EB553CDA18BE3F685A30223A16B09F4516FF5A3A28AABBCADF48A7ED7916227AA6B04CA899E157FD2FB1219671134ED555B9D8C63CF769D5B2277C43689E215DC1886440D25B0D51E42FE94CB5AF18B316F7373251598DBBAA2C828FE8F90C3892B65F159B495C7B11C3A315EB1908DF603F7264B41281A6F2C7ABE75B76C45B9E9DCD563D0215C022A7870BA9A77C2756CF4B9AC44BE1E89B8D58108211A89B33CE610ABEEAB2603A136A2CEC9F4A2E3ABF1200BAEDAA33C5CE3C68004A2C9E49399239FA73CA36F9F7C38AA3F5C774E5EBFD38A416411FBF9D6DC424F1D35CC36ACA3AB5E57723CED977A4C36F6F2D52F2CDFBBBB60F8E8CBD875047159B83B997837B4BA6914EE408F5C63EA8168D8386CE4BE6D58A52C0DCF7E36CE356D0493E79F13832CCFDA167E87339881F22D5C04EF3180ABB68BF385FD85A91F2BAD501F8C11D18B111967F151E75B645FE6C6E9132EA9EBFB96BC015865DEDCC03A80B689DD9884CA2B03B9C3C139765B085764290E77B6F98424677315E92F9FB581CB6322AD0A6104F5B99E646E43F40115DCF43304FA3AC29E4AB019DFB5F95B1D15AC6DC7285A77066FFEB17308E8D630FE0C66D63E7FA641DE17C0F18814940E4D46855F421894BE71BFB4688C74BDE7C96748D412B3DD77F702216847CF997B9A6F25ED951B17C4D4939C30B6E1D703A74201BC7A962900DECE72A038D69E0679016AA4D198615F37E484C953E773C2D813E74D73DA6F291CB7A079C297F240F779EBD15A53E62CAB45C98B2645B956E20549504C1EDF3B96FD3E2DD50B69E0D8A6AF3E286FD8DF55F4623B9C5560A7E93E7341262DE6C09F1EE74101F5AB2949254CAA89F43A268E86A790941E90BA460FEF076E7CFB16F33EC06D5FBE61BB8D407F7A14EDC7EF1BB61D9130D51559B484F7214018C97A875E87D76F96879D48486193B94553F6386EE0F0581F0E8D4F894B66F7E859F7857E089A76BCC3C7CCFC1C623C9F552579AFAD69BD87D050A38B860C4D8A5DD9DBEB9DCF2E2A0A21051DBDD3EE12DE710CD6AB69AC26C4D97DDF5C503A7F2358995DA75953841630E70ACE374E03371CB1987259EB2D9FB19E28C5A46BC0E247103F9DED74FC99171A732DCC9836040389B7DB854BAD92C95E64D383C53324B32287F7DFD582854D218C261F49FB32AA6338D590ABE900BD5F75B9DB18624AE6B725BB1567226C85F5CBE59663D46E6CEC63E1E11DB91FECAE53CBBA9E45EC3F5B1B7750CDDB93C41F86EAE0F30D760E07980BC7E25F8C333B9153D510E5C1B92B6468A6BA76202E87C73087660ADF1145F99DD5742639E034C63F235375F12A07283E2B0547AE90199EAE17333C58F5AF5E03E9F2E34D3752E763B618045ECA78B845253A31005FB886872B30FB1C3949DB436853A55753F8E427227FAE92E30C3C6BA8C061DA52B63410C880AE255DF765742821E0236E7C5B582BF922DEB404C5F7961557B150EEF668B04BAF50C3A2D3E21F7B942D4BF9DAE3C25BD81A9AE3A0D76FE1CE0998C310CD936597AE1E178F99DF6ADB7B46C08A909DC51919D12DC2CDE5A7D55EBB442F1F58EA53BF92A92A2E13E9917447EC09DA24FC7499C5A140754D443E947338D7723C2E89C620A55650C630E63EF3D732B68B79DEBFCE10DB8A52D9F325E2C6DF03E9BA4604BF928F01ECE3F26CE8BCA0E152C33172F065869918FDC70866823809A228993CA4282D05CFC1DC40ADB514F68E5645FA7AB51109EAA2A16B60097C83BEB377B5366FC564EF77FF33DAA536D9BF0BDBC8F4C8EB31F1F241ED65A5EC257D0AAA689B7B7DC2B3145381165BA0E3E13860CFEEFFBB295F0BE75536D2A9D60AB9DDF9C2759D49DE5A518C23F43F8FCDAA0E861E3F1BD0EE0FA8B4993516D111B7DA0ACAC70FCBCBB5EDD6944CFCC320F7371545EF4F79732BD215FF8DB228BBD801609AF01CD2AEC750E13D573B6941A0DC41EB11AA9C8CC3F734C28738C7337E13754E3A3D5A378918B308FA305719B89632623DAAA38C44D740D22E7F3B943ACF23A7D9E416BFE75C865A363CBAD9066F2B364CABCCD7D25D1D4F05474594C5730918E23F2F7DF47F04C5AB2A21830EF70D4340399E46DEED555B0F1362FC4200EDE6CD6B15C4C951BDFA98F3BC69867D884F44D70D2C8C333DBBDE59208D29937603777B2FB97D0A9117202F972CB03D0752EF69FC72A4A63D63B889E83D47A190889EC5A2B543FFE04B0F51E232EBC8CD1C42A8412E1E468D9DB1C80D69CD41132DBC1AE272CE5F2A53AF70836025EEBB061DB84D10B5700959E1D79FBBCF94E95B82B7F652D8A785B0C347D0DFC74D78ACFCB97352DBB69E8E02B2034D3566BD3088D782B01B980C8DA9166CAFFDB68DC0A4EA0B67187BA124058236FF727A4F15B16361168A3816A9B084114443DA01AC1FF83E754047A025F42861ED697A799DB164D32748B74A3BC5112E7B14C7A7FBA184278A4DAF17982CA8B30F6325B69F7D6E9B191B6C54766825FDC50D03218C9A00F89C6BB9E0FBEE658A68FB40F60A88CF673303326F92909E23672E8AABA8670D16C498CDAC10CB7F1942DF44890E4EC29BE4EE7D1E8D87D42639239A6CC9CEF7C70C0AED3057D9204795B3AACD78699422C69B10E77285A51C0241F37EA3CC251BCF8C2C3478344714A6862E2CFD5A16127F2A14B92788FA6F3D9E64525C8AFAE9D383C09D286BE154A4B9D533FE7CEA43E7BFF797D7247A8CBF9345F1B25FDCD9567363D23B1D4E49D10A228E5F0FB1C4750B406DF731DAAEEB5B6A02C795E6D9FFF553271031ECBDC2C4849FEE22EC26FA2CBC5DCF354E7938824949FFD01D5AC45FC71FA7C75DE411D023060E79725CD46E6064B5D27056D45687632952A6CF9FFE773559ACAF265C9FB92F7FD348CDD21B0334493E5AA92B1012E2067760B6BEEE9BD3922A436AA2C218F2EAB0992B1A654663BEFBB0559FDB9D6750121128D5CACC8E8BFD6E99D37CB1944F578CFE516A10C584F5833AF9A6F895E77A433B5A7C997BB4ACA1D5E8FA5ABA5F876C49BE22E2A200B0EF206655D3A0D440874D117ADB20FBEA3C4880682480E6EC0EC0DF50B64F1222FE0E80524861BD03FE1990A8A014FFA43FD6CD1C0E046FD7BE1EB981F9312FA72E3A3259DBE4E71C66318A6573AE1BCEA28A37FD2EA38542078150937A2371EFC3AAB7A7B75D7AD6902F30C5F36E3C271935E96825261AE9340DF4F3D2C36C743D08406A +valid = false +smlen = 0 +sm = + +description = private key with s2 vector out of range +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733698106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CF5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = false +smlen = 0 +sm = + +description = signature that takes 1 iteration(s) +mlen = 32 +msg = 0300000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 35390D83E9B544E464339524412D01BE38C19E0A91B4BF2373A59ADDDEE17E5FA0C6437F27A97E16B05C916EF7671962F362C3B11A422D60D07FE9667EF4225C3376BC7844238D9D80D289AE111A82EA08CF2901FEF205BDE7E2F76EF3DD75FAC6EB6CC93BC493646C393AFC11EA0EE022BB03244950D3277293FFED1B950C15F710163DAD25723E551D01E4EE838A8BA5C815A4937572539629354D6CCFFFC516D9E3F0F5FEC67D7A8A6C7EC169B3E4F8985293DFA7C2F8F6060EAA81322683B6DC50F21116481B2FA172FFA76E535EE37C408ECB7C826BB38E05F3908815FA7F4009CE0F6C75B6279BE48F578BA400FED352634123796244974B5C978F7FC6A51346C21F56143415044411D1F7640CE49572FA8B8A8BA0322599DD4CF7E8E12B96709133810692983E69F27FED2EAD33F38690A49668FCD10B343890C38A8974D72A3952E1D6DA7B7EAFF59FAC010F821620CC784A8858D04D1241E16A0C2A656D68760EFF84B63E6F60B3FB98DE3980D9D90BA34892202CABDD5CDB1BE1A98C7FD66A127EC3FA6FD5B68B1B5BFFBF91562486DE3DC30294F63F81AA5E58D8108F813853F26472A801426D2B0B148BF908EE954AB9D64531D2BE46D43BF1CA6CF00A2644DAD4BD63B79ECA088A7356C4C0844B986EE05B867DD8E50AF832302EBFC8BB1D9C2B700E8D153D4D2F220386DE68F2605DDEECE2A449CF2C92D002841308B0806C901C2DC3908CD086993C2C5922B218F33FF8A4ED4676E2C95373BA9C3A3290CD399A3E2E82F4E3B7D94204C432DAA4E9DF6659DECEF06588C0550ED995E078A9CF6DF555127D58333386FF5B62D094985AF06DB92C83BB6FA88372DE1E255EC18C56E100DCFD13519064F87A6957798E1EB9D992850FD335EDCAF98328E253A02CCDC4EE7C6F031CDEC6875EC6577FB6E1DB278EFA20DAD69475925452C4931FE701F5710F1338C0DDE065F78CA7C31480ABEFADD2706AB4454F21EC0FC3818EF0472481D30820C910C50CAFF4D1C0743C2B3C331CA2E32632DF7AC797B12C360C982109994A987025D0DD57F96E9150B6FE1061B84543FF05EAAFE9FCC3CF4A211FB5187BCB381013B26BC444A18EC3702FB42A0BBBAC7F19A60748506E22896F091B5696C4562454345EEB4E80C44888B514449AC32C50049703E8ADE88C5584FC94B7EC766A40B8A9BD92766F31B1C35ED646CB0A012C12FEA5CE1A7DDA4062754A21C1BBE641B180EF277C7FA7CD01B2533A7DDE8573D9B89BB332DFDA4DE383698E57F3A4D01D7A0425F64F635D8D345913241D8521DF09A38F8B1447582BA401D4E68F5D0EC96E283CA4DC33B228A8A233D3841B463E041CC44F08A5BF6DC176E7534CB209617A4226BF78C124B6D9B22AA27536F63DCB44853ADA78966BDA53F07A74A20C6961815786B09F4CBFC99FF499163447DAF8290BBA869978CE0799C7BD7A803F91D7B18C7F7A82D1E019DF788083C9DF9DFBB1CBAC0BEA8937A7019111213D8CA12CA85FDE3AAECC805E235BC4B038CAA02FE1FA6D5211CB44A03B18A7566171A9527B902FB95290529B0D6E967F38950706E5FF29692CDB8E6641E29BAD6D5A6BC143CC0E2DBF74A1B076D84CA23CB1E90D1B4A42FE208B81A569B085F55468E3D4F5535AA74DD8756C5411885AAEA260A4C47738176F6391B6E34126F50F19B5E1957A6BEC7010E42974A49172E7E51E6FD0457A3494877F76961997953FD2A1264E28C6624D70CC633B3E5C3BEDE1602D2F2497EF5DC9637D56864E0A07AE62619A7041F90FDF667EE326BC4AFC1BC844BCA948E1B5F6436B150C2B9CA9803E36B3B00D24E00CC91FFC4CDB73B2B689D9A1144243B7EF99D46BFD47E70DF5FC130A19B85CAABD31267BE6B1C293032EA0019D1B34F6F9ABB221A5ABC99D8229E8C0F95313562ABC358E19349DD44F56924CF40DCA534B5343558D445FED929BF50BAAC983888F88F913021A2D17A25DC5F1182C6271720FF64AF77DE6EB059BE9B68B80B87CF3CB8E859B3730F838AC1FD533F6710EE8D54A740095A7C95AAFC8756232988F32FB135811747A60823F68310F1F0B046A1EAEDC9A705B3D725663B9A5810DA797E37DEB4C42FFF7E770F85456B53245B84C9366C69018D7AA40BF3CE643A86A5EB3EB0DB337C8FBD64FFE9FBC4990F97B3574E8113287D2305FAA6378FC914B57027350BA8078D145864F8827F445896CF9AAEA17E529E92225E9C71CCCCD46FA516E9E79E433DC219EFA398603D38C14B4D61B4E20ED8346474D0B15231392AE0486FA22BF438EEDB9E5E57840DFFF4AF51DC4A60DFB5E87E984381B3AAC96A2091AE4E884EAFFB423D56412981B1296838E86AA4C6B441518DBBF438D2C2673B9D7237AC2070D4066245F77D2AFEF2E0878E57CFCF3D50DDC478354C7A581AD82330259A8A0E45DF110C341B1202983F64C388568AECA38E1F1D8ED4FAE542D6FD17A81F7E9C27BDDF34FFD09F5846110B7B142CE7392D17AFE27F3306FF59B502ACE62989FD351D38E599C6D7B1FBE5A742579FAE6CDC9CAF6CB6086ACE48194432C9F5A5C17FE107291409EEDCC89277C1901693CAF014560427E6276CA572E45325CA861170D5FDA4FC4317E1C566FBB504C1918BAEDFD8C2D1D216BB3F58DE8AE306AEF3041AE92628A32EAC2BD610B2826C474C212ACA3F2D92B97A5DABC1233F3148AEADD53B601F57413B27AD0DD861C44923B6A8A61BED0E8CF5F060EC8002DFB59CE0648F595FD60E98AEA4AE82602FFC2DAC37D129A57B9CEDE8E4911A1F36E87EF6D9111D31AE78D3766AA40913D7B87135F1A19857CF2436B38A9993D518DF444A23B98BE28C1F17C2B8FFBE954BB149307450C317378B5FBB9A86BE299D92E8F0AE52459A8B281AE9E991C8039762A072C78926E7B5B1BD2F032BE517A8B37896F3D5D2AD4C1EBB9BB893FDCC509BAFC2B83BB7226A90C7050C893549127B1DF0126887A3D155837EA27EE188D6C86D973AEC3F027F150E268A8D2BA593E998F43EB29402A1F912047194E4E8FE4346AF0AA003E522FAB92037CC16BB1F7E1878D744F6FF765693E54600C312769C0B4B2D5E12727D3052A73114D2AB5DF5E276A425D941B3068E4EDE76E7F88C38397C9CA93CEF4F34B694C2CCFCF0E2C887B8D3C2E2F01D9F3649F9D453A5E52780855A6D6C439B6975594BDA5C25CEC6A6A75E536EBC8E836D5761B5D2CD1085EBFCAC2B0C49558CDDE0C18B8AD46700941BF64F810418AD7364A9672051D20C8EDDC39164F2DFA20A9552A3132995A247F43C01E835297535A55568E95D6AB2A4B3BE1442A0C8F5F07447FD5D285360B10A044014B1CF4A1410838996A57DAC7AB8C34960F568EE9A858E99A4B498AB235DF57BA37215D0DB48C94388A731AB285A987442139254487DB2D244B350E6F84A27545FB0FFAE19AD93EA658ED01187647DF0908EA644C3591E31F096BE30DA4E6063FA201FD725BD9E17C945C4E1FE4142F4377E4C866FEB2839D82E8252C27119BF498F6F0489DB684646F44CF83FDD9242434BD35A65BDF9D809E53A43077598AA8C45BA86DA107414D2E46136DB6DA185CD3DC8DD216B17440FEFA541222B52C6348D6EB0FDE53826890083498F5D22BC87ED487ADBEB3A55A8F3CE68AB614E43F053A26431255ACE3DA8B066C3BB322FCC6D1BA99FBB7C116EFC5A31836C59B57659258755FF5067534DCB875FF1BB38178A146C2FB0B569116EF80730DE85C111946690E0F3D8F48DEA6B1F34713C73A5BE7AF868CB2510269C450CE1EB2AFA586F725FE9FF0F595A6F12E32025A96D71072BF735169591DAC9934DD07E18DB0FF580662FF0700E5711E08E58E406DB8668BF471480E65B23706B13866C150B3291D042871F8F2C0F424DD0009989E395C11EF2B5D33650CFC05EBE52AF1D27A038CE34CB83947659393D3DA9A2DCF4A63EC3C022734841DDE0CB8EF21DF6F7258E01E7A2DB59FC67DD7368ABB0B1041D7971DBB9077EDD3107F9D310C435AE2D126F0D5E14CE8957FA0DD3BCF8B5FA42FE16A3DD2AE0BFDC3ED778968B367AF3B788D4A2874CB56329FAA49DD84B4FB60E8B256C76FB416F18FBB3BF5B8D3DBE94DD1AB3E82B745766244A5BE8EE2D2ED932D95CFF0B396C8BC6F6827BA0E1926FDBBCE0DF0CE6A0DF631DB8DAA72146E2E8CFBE1C0B573D00E5AAF755F7E9A1454CDD0D165F8E077A3E5EE7DEF1C59666F8179FDE6E2CCA97CCE9C696EAF1BA66DCBCD3D5EBBBEDFF43658C20DBB182A48BBDA59B3C0F40AC4C75289759EABAC31E6AC40D008F135F4B18610EC21FC229AF0750CEB7C52ED25BF1642D4E823232A6479E30C4CC431741474208483650D264CB0AC88DA48CB9878845D88CD4364621B34E0CCFBC17EC9BB13AB04F298EC8C2172222CFCE5E0514958E61E75235C0C45D171FAEDDAB4B80CC5BF863E8E05EC00443318FED599BA7CF66A6EB330D461ED40AF9BF0ADF600DF2645EC7DED8CE816F3EADFE38F1B4A63722895DE304810218AEECA1E4A7300718F2515C7B1BFDAC62E1DF2E686BA579901456C43D419C165479E34E85C5F902DEFE7FAF34E386368BDDFEA1A49528894B4C0CB0929363A98A64A56D5D81F67CDFC0941486A869D9FA5AEBDCCF8000000000000000000000000000000060E14181C280300000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 2 iteration(s) +mlen = 32 +msg = 0A00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 06E1477F032B417F6F1FB468D213ACC90AE675672E2108780599A0C778AFCF50B763DE4B13DF5C81A0EE78D66A1C0AF7956A1C1654EE03773D4AE23039FA749EB8E824212B137D4CDB270F790988990E0B24DA0B14E14B48C38B96B4A2916F7A8ABE3E0F3847069A4497CE70828DB8E0B7A143268732324F6516F160ED54D2B1E7B5EA31FED71365B7D7BCF9D50D17F9417B0AF1F6B5DB7AF8C7063AED32C21AF3A71027504DED80FE1828FAE33675D5D1E47BF45DC4E1102313DDC0D9C3348E5378B68CF29B6AA3E80EF854DAD0CE1C5E7CC5EBFA145E51CBA874696F4A62EE4CF0591E1F78CD5ECE9AB042956F9997EBD609096B81F95DFE461A04172772A3EEA62B5553C751E039FD2D8D8283E745FDDE2B7320C06016DF6D260760542D5D433EC9594E88918C7A16D64AE484EFE5C7A4BAA4F038E5C777215B3C84DF89C67D57A766E7A51CEC76F4E14507B5FE3818F6C91F43DA897D1A97E100AAC0265F46770B6813642F6E6FA9611B982A8E1F8D79B51A0ACA523CF5C0B2C5E2D6A9D5BD4E166A60491DF2C777CC1D3BF4B0316964B066BF79833B324E15BC2C862D524D5C77F563F3B7D6A027895B69F6C69ED0E74FFDB3F3F708D386D07A13B1F649E428ABA12DB6CE5AF1AAA28588DE91154B1FF0B0FE1CF78A0E087FB03E0146E18451B7FD992A1EE7E1FA25DD925EE77BBC8F8CF1080B862378D0923524240BD3A696712A3A9F7F8C088461FF3627FADC6237356CE0F3EE9756F4E0A7AE1042AC2608DE536DD2C3028AFD1C250E42F9DDA6D8DEA8727B186566FEB5E1F9E0860742C802476B115346D47C732126540AFA947A297FF963DAFCB7D67FA1C1BF877003D987A151D7A9C5961C92CFA403A6288863FDCE1EE59730AD62204A73E0D5E6D92EB309AA115CACEF5F3270AAEC3375904D348861FB5A3CA1FA509C56352E185B5CD817D037A0E64BDFB80358A0410DCFCD16946260FDAE9DD9164510951C333BD1118E0043970CA01B2469062CF4AC39285A01B554BB45459C999F379226EEEF754639E8129F6DCAA695CB9AF4026A86C2C32CBC4A7A528F2D2C162C9D78B4976D60F03A68037552139094B9DCF6CA1DF2882D0B13CE681D38C271FB119D8C0FED6D962DB8E0FF56DC528DC099D24CD023EA86FFA85BA2F1B1A3EEA854497FF0E3274083981478F7EA090F7E6DDB1588C0FC47F19D6C4E55D51E78C026010F9BCB021D7AF31E8BC9688810F8127A79DB03ABB6A1977A6115F89AF9698CC9AD2A1F52AF5F485AB1BB77E36C946AC5FF4FA22B8159EEB3569FDF6D9B8CBA45DD5232B6CF5088EB08EFFFCBE8256DA673E198F692A332AA6C2D61596FC714AF5D74193DB856B135945ACF3BC48F162495DF092BBEA85866A99EF710EC7B814B04435320CF1CDDC37A641E73FBDBA77576B64D6C0F26A3B7BC43F890CBAD92E92D5AFAE9FAD7E008C2E524AE4948819EFECEFA253372F70868F0BDB705981DA77C6A134EAA18E093D8E0612AD5E0939920063BA299B3FA7B67EB3B309F2D3B6ECE9BD7043D7A69C23090361C5D78877B573141EA470B600D55A8135C2F2C88DB871109AF0C8629FB3FB7014339911AC78396B05CDD8DD994559F671A1DF9ABDD0E351416E99AE6831A2178B3BDD669ED2B0E36FA7FF6E0D003FE748DE3E465D513397BE9DCE3FD7808B598D824ACCBF614D9C3BF37FA202BFCB39419B617DCC1BFD1DA298DA213D75FD72ED5FBC96FF692E250EE1168E5562E943697ADD071DE60D275F97DAAFAC026F4F330D0EBDF78CCF4F5FFB5D393BCCA0A4DAF9E5857AD6C568306C0DFFE7D4B25E27B5709D80F4883F2F4F2D0E8A74B92EC438046C47B4ACC70D74E45A802D44196251F0DEF2736668CF5DEA20849D102108BD7C1A3B7062DC8C27F08C6E9E58BDF80BE8AD297E0A345D5FEC9C56E2DD682E6E8F83C906D96B535D1E46996BC48BEBEFA31A994A8364CAAECD14359BE24C1FA429113E7138670F4B0B83450441E41575CCE13BFDE72F649DB05B252D8DB708C1EA907208679AFD5F4F6AAA47AE67303547A2795D7FC6D640968377E36452EE667B1FC95E4E00D850D35187B2A5BF6A14D7B1CDCA7444A15D6746522F25B505CE5DBEE34C3C90DDB5D14EC017286FB433A8939E626B9AAAE6A00362AEC1D644EF01D45CD6CE39CCA54125B80E0AAF7236CFAADA69DF1213CDE47BF7C66E2A685C477DCFEB051BA25D815010B414708703757EC2ADF8FF68BF6994D53852D9AF571D0324B82EDAAE973467B8BDF45ABDA2C76E716E16403D953C2BCE331E03948D6B27FA81C841D23F2BBCD60178DB3B8EF769CC7A7C35667D5EB5129AAEBCD792F8474B4B54628E64AD7CD14CB1F26763257C90E2FE223E122882CBD6B4667688EF98E357988650B70597B014AC487D5B95FB7DCFD1FEAB4A875E76BD17074917A7EF1D5A1B1BBF44650A49BF976FE21AD72D31D91BD628890AE0AB6B8062D111D441DE4E7BAC80346850891DEDDD0E437D6D8F110ED16A535C9C1873186A68B13B0F10A5DAD3DBA0C14B3BEB544306F57F4F302A732B46BD30E8F95943FED534D2EC8C93BCA12A8E49384E236B63090AF902E1B291806A0A595723B32E2BC84A94DBA2F767EF2E9F7C808D7457888041FFB6C56EEBC22671F2EEEF5F865C69908932A21B9E39BDE4195029ABCB2669C41317B1A86AD43F0F6B88730EE6A6A34EDAB5F21E415E33EA6851589855A1D9CD7598E320F9CF2D3D4296C51324248B99BD83A5EAA7216791195CE88E598DCC9E77302B4EA690A056D9BF1C6C148049B86BDEABDCFCE75790D5781405C5DACCDC08AC560B294F5F1FF08A321CAC157391C6C4B05656FE3E8FBE0328F03541BE0A7423E3943DAD132C513725C470F4EF03C6C3436606B4292E9A3387A8439E572EE08CF6601A6390A3A8321B6AAC0A3798BC02E59CD13DB4D21FD24B7976DB3A76122F80D28247E0E3D91420531A58C935385947BE95AEC39837D3CD15B95C849E4033C9CF01992463793F4519E802EE7FF94188AE04341F77B9FF4D02ED489CA4F3D6692BE73423AEA0FE07711BDA9DD212FBE0C1D36F3E5180EF5CA3D5E236D7079F0DF29BF01EFCED2895059C59E69F89D2557090F41C7625BD570749992D8C1516D0370A8EA089D10DF7FCBC46BA9B1AFE8F83D044089951F48E020B72633993A8BE6CD138506F4122339CD61E8FFFB67E1556431503A2B609469F80ECEA17E8B06279E71AEDF7BD40542DA1B78B040AA9AD84A47FE0057856D656FE6077AE9C15AF10B05F5F7E2E7E158F7FD519B4B15B616D8CD5604A59A30D9CF6523EC5F75F1381E038F29EC5D62A40B7C84818C8AEEDADC39C7AAE6E2A354BFD71712E81C9E8122E8D11BCFDF6DF8B3BE5493F8C24AA0A2BBEECE07D8E22869B55F9B2052064E4B2B6C10D578E5207764CCB3FD7A22475C89A95DF8FCEAC1C17554FC74485C6DAFF0D1BDFF7C0AE17CAE3661628DAA1F4AC3F28236473BDD036CD1BC23DC3615D88B29DA279C8932BADF7B46014CF7AD68032DBF5AA74CC74919BD52833C027DAB146E0D3C1064EDE6DDB9780957EDD044B27915D15DF7AA497A7351328C91559853FB9C9784E7307CE676B54FF2338473D06A13186E1A943C50155D726C3458B87764519667471965AD94B44273977C30156DB0C52CF0A2294418F83A29CF88A8401AD54FE75D2BDEF85F8B3E1D26B73B6F58EBA6639FD57E11E35063F8D445B55855D59C83E798D18E47D5A58BBF01F894E862D2FC7AB1A5C7E9BB59DE924182E239F4CB443BB3E7B5A4BD42803032BFB857BEBF21029C7DD8126113BC8D3D72D18DAC0ECB80A1D65F8997870050FDAC159915588C3CE74D84B4508B5A85CC8BAAF19A8CB7C110AFE83882EF4E11EFA9F7DB7B70F770DC695EBF6302A9D2573B5E72D7D14E44B62FC762E0E58B0E6B442464AF9996B01E6436A43E2D07B3972F27AE7043D4539E66D23A352C43D9E41FB297C2205D100806F00A5AA814F9D83BD28014AF96AA7396D8F6B01693605A2CF1E4D9EE35334ED1DB913869F4657454B98B6C18FBB1042CA875C117AA64F30B16FC25501FB32AAC607EC6800629C8DAB7BF8E87A6B21B051B8CC9972845E63D785FB95FDC150AF9DCEDB4ABEE97A4BE07ABACD1453E607A3D97343E499263F7949A23DF69A2E5A373749BCDFA8260E6FC527B06AC347B73DF75902B7ABB28FF73A5A6C5CC7D3A75474E1BFD8A306F57867B5D929DFAD5F1256D16B79ED5620C5A6011D14124E4220B5385AC38D66C6A799379B2F88EBB582135584171431E70B84334591D8B5D640E4DB39BCDAC0D6BDDB2A4C8F2D7C348E8EB04DE5335C29A36CE8A94D61CB3D2C885AFD64F7D62E13B1337AA915E503C2B0F1F75C106B92669C0378BB7EA27CFA7E0C5C6A68DC8394EDD4C1D807CE69715796401211E58623E469532D529D0590105BF7B65FBFA126762B9FA80F0AB0434085721B996619017C33DF28637324C0CE95F1637171B792EEE9E21D460D0E3525E78E11B00BBC59DA44489C14AC50489D85B2EB1802C9744054630D1896B25A56AF459296CF4054E9C029677E41C7B719CBFEADBA4B35D222A374E542E788296AFC487BDCDD4E3EB092A3191AFE0E313243A54BC3D6B000000000000000000000000000000000000000000000000050B11181D1F0A00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 3 iteration(s) +mlen = 32 +msg = 1700000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 933370D9DBA15CAE6BB2E5BD527AAE89AAB84158416EDAE3EC8B082123C613727C19A5D36A429CCA70E084AACBE5814D43C86F6576372413458FF12FA0FD9A971C0C9599160348FFBE5A4EB36CDC471B1FDEE78FD2C9FF27850CCA7DCBE1FDC7952685AA1DEA344233972A5E98DC38AC5FEC50D6010BD62602B326E8D25F4F96EC746AC95DAE223FCA61F87E374643AEB1763DA40F25619C1B759A68851B23C124C669D8E40B8178435D1C759A4D76ED85B0D689DF4123A28221EAE8AAE39C9BE30AD50A9DCB5DAD392A487DFABDA8F00406229B89A7A2CA5BDE33076343D26F7F804FD5EEC4425562938850AC8424632D0152F4A3C2333C784016998AA5D1670137C470D2703B963E8D1D75AAB8ADAFC95B611A6C798C5FD989512ED5C663E4B5E4A75EF651C9CCED827632EBC92F87854FDADF891D61B6166A0E60A8C43212566B5923FB58CCF77449FDA7A26ADC43070FDFE51F169BDEA03B375B9EEB9003FEE45D4A35B94CD05C2AFF37D73FC3DFCBB3C0730DDDBEBC8FFBE931C00553B951F3F43721FBC9A35B6A66CA1CFC7F3C3156174E392BC0365561EECEBE498F17738EFDA8FB3A84B1C0372BDEF2F2123FA4F2C3BEA41F68FBA80987086DF098D5B723D323EF4118F82DA49141E7A0F3482DD73B09A6A4A4AE7AFEED28F4B2A17FA2013256E4DCF58AAE656A5A5AB7329CFEB73D90EA6F3A119260D812B6FB18BBFDA9C23C96F1D2E35C2D847A9108E626A8F1A186DA2531045B2138A0366286C87B789357133A838928B943684C3696AF815A427343ADD25C51D1826FC48A6B9B1083060279AF15BD4121574439AEA39B97E20B52E90BF9BC39F1CD306B89C014A276B76D0D46DBE9262E020CB75F7BF9C03B1BD1AEC2374B3CF8963D620AC70695F210B95D401D61C3823A9E486C5DB3B5A7BE095915BC0CE03FEE3E555F76C7BC8179C5C7088E0DCB4D2B9EBFB9CD4D44E94A9C13E5EA33E0F8F644021B16BB124AD74A3F4B974516CBC123294D554A6C3D619DCA00A62D2229FE47D56E97FA63AEBEB84F96DCFA272B224983D54190F50DA0759DBDD4168216D0B17CD29D717DD111BB2DE1038F09B52B996D875DE39D393247B58F6AF81F228FEE3598A4B111110C125B71072C483DE8B42AAC1B32570C3B703CF380EB718F37572BB0B402EA427FA711649B193E708DFF17A369CE430033461B5746C887D7B0D885535EE4701F3177947E66272C5B76C9DC1BD927D5441FA3BCB06ACB2463017DABC1DE7BAE9A73262FC5EC075B1E31E7D7891D336BB67B2B28767920BD35CD2C81082114291D1E0AEE7A285FE0AA6E033124876F5F0526611F46F99DD9CCE92DC67A5116348020F02890AB1824781C434FBF222247042953F86C639B90BFFE8F22B6AF5E219031AD3A093171F88B1E285B9AA37FD2FE901DED5853EC762892477A53989BE6B56D68668CA30E3DE42477DABEFC134DA18BF4AEEF27E5BFBF01C9A26E03EAB7F77275FDC9A7A762373297F71A522EAFFCE5E5774CB46BF270EADCE581E95DCF59878AFBB0D357B5777AA1B9605868273C2405BFBC342FB15FE6E24184C98A47142E4858A2E05FE2F6D7C1CD3D24587A743E5B56E4A74BE19E8A1B3651012A4EC6CFE3AA79F008CAE2C72E130EB21969BADBD1046A7982F53080AE1D05944BD7AAFEB0A8EBA906B8A6BFD282FA84C60F8091BCF683526A7EBF458A8E38F31AAFA2330E93187EDB8EEAB52A41923596BF1E4B17D3FB258BE9714D73F8ACFD6160C3D3EC5088A717F8F95AE17DDB97A62D8EACB41DAFC8935704E4503EF6C2711BCDFD7AF7F84689655018D805752774A38480AA44E8BCA3C63CAAAD21E999185B11A25FF91CC5F0EE469B5A793C11CC57D39EC4D990A1065400BD4D7B1A8256771EEC57307DDAEFF11EF1ED288E4A1846085E45D54EAE002FCF6D977B0ADB8999D3D6F80D549C49BBA7F4B444539A7D6CC35F045809EB8689D70AB8C3E237113F12674F57DFDD17DEB72FB6E387C8BC633610903A77DD57816CC0A6E280A4E2F33A0AF1ABA75332FAC152FADD4665E7610753B7085144AC0800BCF188EA0C19F1D4C27B5CCEEB603F4F7C88EC89361821E0F226516D19384B1AD1C416484B0716AEA2BDCE885D36990CF6524F21615229FC002D2FDB242363CF8114662A1D1AD17BB1B6E72432C2E7E137BA7C93EA9F273CC80BAA30326CE14E17DF0BA54EF2CE11E2F34EB44927D3A14397A04A3B6FD5DD1E73A73002F7F1D9D1428F6224A11A8D36B0BD0034B5ABFBF02DFEB655F08F3E0476E6E6D6D9EC947E2E67AA4F6E745365EA91C025D1AEC010FE1E7E938835C89A5258A9E0EC5101A60BC70C3D0A72FAE0958BDB67FF5422271061670247BB6DAC5C8B677492676B57652EDAB72C41B09C27BE11EBDED986A1AAA642E6AC8C7FF7BACAFA6F8C46F4FD89B4F0A01C70A7A6E7E9282CC6B54E22648E1B65207B8D7004B1CF5F939FDD8FF53DE649BDC90A252C7482CEB3CCC6ADE3E87D6AAFE6B8B8C06D66A4463AE93600D530DA0322586D01E12F5C74FAB208CBDA52F921EB30C62F55FADF53F4CEDEB7D30CB6CE9645B0B5DFF6A016817DC1A0B9A12154B313DA604A1782E264A7CDA600464E14F08122B89C70BB254A3AFD805DF6AF925B80B90DAC6E966ED6CC7A98E394E9DB81C61F193E548DCA9744FF2C8C81DA5D5BC0AD30A35E1684D9138C2A6D8E1F8B14E2CCA3BB71FB8DA85C236F454BFE35EDCE1862A11C69FF1F14C186F6C2F63C1FAF7797321AAB3777EDA7A7EAF43174C232DCEDDBC5E7EEC0C0310D3A4B47B0F058197283D24BEAE7A235DB0EC16BB48FC8EC970E3B7FAA4D21959F4460D0E69959B86D134D60D0AF83D660234F9A33818A12BA69CF9D26CBCB7919E58CC9B6F3AE8949FE0B3EAAD07FAAF72C192DCCB6C8F3A402CD9C7C79957FD02B97F49BB77C3136462DBAEF60E9E49EFD9B4CCDB85BB674B956F02DEB3714FA157AD108925BB171AF703780EC937AA00059052274AAF49239EDD76293B358B9A8D12F31F6936EFBC56D0C337CDBBE53E9849952C114A58EE46FB8F3E77606E33BD6B504A578AF9251A6F0CE4E2CFFFC2BC5A635C53742453C61ED0B3769CEBAEFAFA6A9C96EA7BA451792ECEF7F42C72B25E51403705119C704DAB75D5DAAC4B21315999615A1961D471DFE01149216985B70F02E132D25A2255BE21991F4B2805AE4AC23DF53331B00F8D04CDAF4C1524F66B24E4DE46923BF497B0DC5DF968599FD5DC785DB98A3C4F331CB143AE77DA7C56E8149469D97D11BB82E27B0F724B1D897540C60095947C5890F5AE59CF47454FDA7E5239DEC35C43E70CB852812CD8513EFAE586A59ECDB5DEAF12BDE5E64CD81F2786C1B28AB8CD81D5934157A72D84B7E819FAEED9490893FA0D57C8E2BE60FCCD08B6469F286EE86B1FF9B1F01AB12644E583DCF7ABB82D63C7F747B7BD6E92C3184C0B21A6B2485EC16E3CF56B8990A1F270CDA4A7B3AE107787EDEECCEBD2926A0A9BA57E25DFE80F926D6D144AE981F1F22BB1CEC9F5FB74A2D85D54AD0A36F89FDF74B529DA55C77E983C88675DCFEE789C2C61EF987E63C92B86610FB5145DDE6D4E8807A2345ED9E6B52891E4E44A527A91AD9FB737E821B7E4F5A43BC5D93308F87872E920D94D738783D8D6797FC89B7796472C74087E890330CFDD1DEB3FDE357B5B7C7352DEE21CED6565292F744D836CC10920F9BE5978A8D697F0E2C75BEED6D0A9EC750966E58DDD9600575FB4339804CFE7EA08BD193CBBDF30133EC8AE5BC6E17EE93890274420B0C641063B2C5F5932F805681691B445054A2F8B09AC6EA4CC3B5E70431B5CD65D2842D5772A6BE0CE1432A646E5856F3890E2E412C18D780D61BFBD6AB2A32C945B01BC326C01C6B53FC56778F871E306A501951D795AE5E70CEBB2D8229F31D71CAC228CECB77B7C1AE57806151A891D758043AFEEF3D57950CBDA51B46A57924930238E2C820A0B325AB02D3C7085CD63F080A4EE5E16DDB191BB3874DA801F5F14F37A734A943A73EC3B8C7D6CE0FE4AA1A4E33FFE069897658912E9CE9665EFCBB9E63BB6F019CDE82DE80AAB64FD3F0105898392C096CF7C88C2E757CD758A327ED6C524BE0B150F80AD1E6C5E098F6AD82BAA82862790EF3CD000B0D6001864474ED836A8A79BECC1D280D9B10C5693C8E0A35C2A475249F2D9829E17A302A191B210B21B72BCA020351FE64034082AD615DCED25ECDDCCBADBB997E4AC3F1E6EADD8BAA206101952BA02941526C4D41DE8142BE857BAF927F9006BDFE952E51630B19438BDCE494AB8A56FB2D32BD7C0B4FF7A258285A4DF89CFAA3D437A99CF0FF4FCA0D7E07E972B593E00FD56F5023697B3012EC2B79091B3850F48754A5CA1D643DFA20CB5542BE4CC0C88FACEFABA58D040154922EE6007EA84D022E31E58F9657C1CA5C5FAB27F30446E7538255842F3ABF57388DB45278323CC8C191642F8D1B5E97C0B173AC7DE5F2CCA4E8ACEE200981C2F5009968893A5820663C41F75FD5842F56B6657C60A44320D01877F5808703839A42A439A14D04B6E559E1CCA6D4713AC0A6B101368A87264582A9092544555AFF5FBACCFB1B1C4849525C90A5ED566C7F9DD2E6F1F47987ECEDF800000000000000000000000000000000000000040A0E171F241700000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 4 iteration(s) +mlen = 32 +msg = 0600000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 7C4DFF99F029BC8A43BFF5483F53E3D5233E2AE3358C21BCED17C6463459952F95C5D288E283382E9315EA212A2D6F8E809ABAE806404307BB784E1A9D40B9B42EB75DEDFE370D78FAEF47A77684FBB35DAF64E9CB154A8253B7A3249DF68687BEBB1EB5DD45FFFE3A2E05DCA8F315A3AA6AA1D2D9E7F2ADAA2A92A5DAD67EAC8F37CA3FA2F9C64C97222D786735CD06DDB9787A7DC7FD4026EF4C984186C7F695461AFA65F11CE018023155DA1B3D7C13EEB2DF0EBC697690295CB70B5C08D3AE431062337AD205CAB5FA85531639A0CD3D3DD03E503D36563638228375960E125168AC95870F9F40F4CF620E97FDAD9590935CF3ACB818E6C194829E6AA80AA19791DFB83F9F84B1AA98676B352E8105A425F2606ECA2B23FAF20231C00222C3DB547123C16F0C4E72EB1CB8BB3F411B882B2F552DA45C957805AAA752AD9DC24984214B527E398E088F729E1690FB7F6385455E3DA14E5939E85AD2A33225223972DB3303E1FD2EE5BF1E344688620F76319631A7CEC70A14AE8B41684F227D9D242C339584E3ED547414404E4A9EEE931C1FAFA16DC570A1A7C0B400B592AFE14511DA4F0CCA1F474333DD4F48B8A663450748571325956EECF5C6CFE984377055E39352F07D4A3A95A3A41AA5A220CC39283066FD4BB2696CDF1B71FE837B200CACBFBFFB06BCAD747619E6E5823D8683E7EF5F42C40B8FFF87D5F3D8882D595C192E7E941390CF0FFB1F5EA864CE27558229076BE5159067CA7BC6E46AF17F5270E79ADE6F615C5B25C8ACC461A26C7C6E30361654319FD54094F35EFC6F50F7A9D9CCEABF4260917EE95A191C0B95B3CC53317F60F57D151F8C767FBBF9358B3956734A1CE14463FF88255E5C735778ACA422A1E0266CC5A111611539E699A928AD2C67A53CED4635DC866F1921D4F15D40FFFCC599F2EEDEA3CCA120D7920BA4EA1D0F96FFB5C802497F020552446D319DE1D3B07FB396FCCAD4F24E1D602E2316F3EF658F0A8C465B8BEAAF7F8471CD3282A5D3D8AC8DB08193685F37706C43888C8F22B0A182B3B8297AA22ED5A9F464DA6195FB380861E40B837FD2DFA64D7AFFD8B61719921FEA3C883CFB9A8363D1374F19616AFDB36A94509486CFBE7566BF22D017B97FFC76671930B17C04F92869AC903EAF3F291D85B8460D612EE7B6078A09B958EE53017EDB9F14A8692BFD40E53C455D3295EF7D09231D0FA50CA6174E5C89497BBF3B3599C038A89DF8A9828A166ED3218F916B0B036F540CFA9AC4CCF7DE613F706060877A5EFC33F7C28F63F5782C582495BF7BC02C639B23F9279C695CB738670D9CC6381486C0428047FCFF70DF16389D8E50E15831713DBFDE8F87CCBB008DF71D3D883A1EA7B6A16DB49536F9B95373B93DD6636CBA0305FFF8217EABE9450C4E2098DFE09D5CB70FD9E9CB911D2DBE51B86B3ED4857821B5203DF5FE28D86056F152BC56F5FF8316A211E5CBC05C4B70DC68220E1BD8522404F1402571DC20B97808C707A0F88A582A18BDB3D29321291D3127D5D889E7ACD44FDF8DF4CDC503A974CADAED6A6129302359BE31CA7138D06BE2B36D0F7985B1E165E4FC92456E5BEA6F4422B918AC61F83416EEDFA88EA1D623654140265F9E8CD08FAB25A278231AC361A1F2E41C31FD99FA304E4EDD83752C424AA0FD0AAD2056CB1A5D8F323A75BF799B22C0AA2100A8A22C63B367AFE21BFB47FE09B8282B5D8B3200588E94318CA9ADBEFD1CCAD3E1B51B3D8136D8919B5DAF30D9A1C26B7F404877328D3BC75EB04F5086B1ADDFCC6FCA576D2F294C9AF5321032A40962B38D09483ACB1A297DA896C3B262E9FE2E1A01E4339BD9302A9E18B9C9738B5F6ED919890C019B71C88B00162EFF4E4BC0CC42202D20D7498013D1999B498537A06FAF3BFCE5F495B3B85B2CA59C3F308BCE13ED20080EC8FDE5051A0EDEE329A95EFA552D94AA93FD40B688974BE5AB661E9828CC9E98786C9CD2C93A65CA4F0BEB69893BF4195088C560A869038A060CAD4B2E75D459C984D73E7CC6286B00AA4CD3009BE25DA507D10FF6A2D9A8D9DA74D71A1070842DBE468E488B3CBD25C965ED5F3E8B8B4299B172B2A3759DC0E4B7298C4E410DB2C91FC459B3024967B1FF9419643580BE1C2A5265288A930DA874F67A93D34083489A440D28E461D5169B81B0C186E727B7BDDB008A9043322BF8E148407E52BFD3271489F687F81726E624744C3FDBF23E74362BE766E57C91B6884B3026B2715ED8B0409602CF7D41B0B193FA607231DC2475973B76BF7BAFFA103BB4D3202EA689DB064BD77E466167E3F8C44C82631A94CE7EC090D8BD7984DBC365549AF68331D5786C042DEFC40119C13709D93C08A146A1D53F967FF9AECD47B0873126DCEF4C9DDD7BD4413086C3AE64DAA9553119A0B0736D686E9B5462834094A7E74B49016B387BC189F2166AED154A646E59EA02ECB8D396B3DEDFC75236177AF79C943E81C8C2FE4891C2359D519F1F0A1BC6C28DF47C1765C5880CCEE8C46B2CC5FBA64E1714F0CEE54FB1F82CE5222CFE6A65F1220C70BC02383576644EAF94BA74BB0F2783FF3AFD6FB689B9B4A495B5F12701B70A86426F76C49F8378A7875308E0D3C929CA4A9AF40FCD75852BAF760529D232D38B4159EA276884CA06451C9A8A3B1FF64E72CD0FD170A1DF82B344DEC3B1D81F62BE5FF16E346F7707FD46032D0C39519C1EEC878293D2745C0198D25323B3A0F3420BAF2BA7F13D770430356230DCE3150A5BE083C95CB62D291153B15779B92B1E7DD2168D6D75743516E737B2DF6C6DCAF298631B437A99E040B79821816B7E7760B6744494EF192626D4143AED607194D62849950685454A3E802D4C1EBD70343CBF7250EB55F5C7DE9095A5A7265654CC9692FA914187D933DB141A6EB2CB8C3A74FC3A882F65F8E2684D0A280CF68A8B8B4BC09B30D0E83A45B8BD1B1039D145FA994730175D53711F99F8D28F833FA53E01E6613FB831763B10A393FA05856C07CC5500BDFD3A4385FD993B36060D11EAA5D0802513080A4268114FE21599AC1A484A69BAE1365D278608784DF96A0F6F0F2A3DAC459958118FFB80E2CE2D2E59DC0CC8826396444279E031B8A37F3B3B57E67207688D68D45E1D344B64172F66801407F1CF16190B359BA1B65987B726F752DA5378B28E6262ECDCAFE786FC9D73D9620111C20187BCCE5550DA1F82333333B8678D877E07367DBFB461FBE14B6C631EFAE7AAC1F930C6E19F9A24565D5C121157F999CC61261FBFEFA3875E9F7C7828552A9C816B293A93B44C4FC8BA4235523CF92EFEA01EFB6F71121A8D8AB051300268A5A15EE6CC8F67AF72FD033838C7316C7534521EB1FBF028EC0C5FC41D5F0347971ED1752FC9F2E8CCDE1E7249DF9A7386872A9B391969AA1A7E175AC0E2D67A8DD244A01EE5C1A9E28DBCBF93A0C570E3143D8FE42AD4958AD7C3F676ABA3629F57C3D73C96702D8D85A7E158D078E83A18FAE5E0A641AC36F83114BDFC4E3DEFD42F95F21402191BA0BC8264D3EABBD6C098368253D7B72B5939A3186B1CBE84184A69C3977D9E772EE1515FD39C70EC58E79033D457D04E18C61F660B35F869809C4334D8ECB524D1A5958AEC2330F3EA03FA9A40BA38195FDB7C87E41B36F3C1208103588155B51DA98B04D77A17AD6A4A34B9470030B4BA17B4D68E5766B10879327C1FCFB7B2C3AAE17C2E9E4EC4591FAC2C4EC655D57670B9D03999C39C003C94D888A33087DF8743DFF45FA6BD17816F08D6928903A0BECA9681C5B9B2DBC0B86C77A350438561B8089A5B89DB7323C680F167541DA4388B3032825AA01FE6B313FF3EA1EB950F3AE61DB339477BFFF17B02EDC3758281C21EF56EB0F119F9F766FAD84F00EEAD21481CD2CFFDDA423B6EF36DDA929E8BC202D83A26F7F2210523FAE9801449549E1A5408E4E67F71C5E4BA649AB92CA80E7405B374CFF399552BD67CB2E23AF1A523C82D1B59CC216F4FC145A7D37E3E93005F1E80F20DC6F1C28083EB9DF92C419691BF409127779AEB5EFF0BA751ECBC87A2E01A28BA7BE40518DA2CCB9BD64D7C1F4998246CE0FB821155ADD716CB735E85036D4C891A8387B0A6D4075D0931B4321E823393C69C66BAB4B7ECFC0B0BE3ACA9B9838DD104E6012EAACEC40295BCFD4BF014FA4B30C4E609138DE329A4AA6DB6C8FC8274DA94E2D4F120E4EB349ACB075337C07264465B0491EA1EF1D530EE93816253ABC0132500B573713C4399C8E3FDD7386CC736A2CA4E8ECF903EA13A2AE0929072CE3894F54103F1C1BD7F700E184AD61E2054F43BC18EAD24D1EE3DFC7D7D4B901B692107102115ED5AF19C94B5024A0BE4187B479D7A704D0EB6CEBCAAC1B4D9405D464AEC3147C0159E852EE41CF82887261D1DF5953EE611066A574FFC61F6B03601202C678ADAB494483CCB6694A26619B0AD7FDF3DE777D21E56CA9F00AAE7FB2E2045C9C2E7EE23787CC3FC6D08822B34224F77D5AB5AFA1226A18570827EAD6DCCB028974C33A5785CC3F611188FAF233B89FEBFACA4D7EB5AFDE7B5EEE064CD3B99F865392F6FBD6AF39B1A943F4B7094B3D7D9E5F61B4D9CACD9A5B2B438618192BA0724C8D4D7FE00000000000000000000000000000000000000000000000000020B1013181E0600000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 5 iteration(s) +mlen = 32 +msg = 0C00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 5957630F7C1E2CF91EB85656AFF138A7D6627D1C59392D5C516219D3D2FD910E226BA8FC718B148905489D47413B3BDF6972A2395CA215A37D384B4DDF51F394C53FBDF10D8BEE17811D6E43A2B8D4030D402A7A10B5CCE9843C4814D6FEE3CC9F8914C532C8BC5866D0F16EFC8E521C367DC8AF5F7196A933325D5220972B5C2B466D87010B85F38EA29DBAB50689149EF09E90BD5E0F988F965770F75C27D075AC980B0D8B1381131E536F76182AB9B755622D176C365647E2FBD71707BD286BE33EC48E340632539CB5D318B2E40C2A941D4738A40BDC5D2743A8FAB723F464E49B601D76413187429DA0430910FB7668F1C79FD0C02BEA63040507B5A497A65B654820C1E647AC708F4AC8CDA1ADFA5EE28A944BAD5A992A79C737086EC03DCD66AFB04E622E0EFAF59141BF4D5E626E437C429E843CDE7A287222A02647C1856AEC463996D28EC95697C5461728A1B06FC7743917D7219C04C6D8B0F8B8AAA1B02A82350DA7E1F2958E0B5C0B096F459A55F37C6EBD412B5CB08E6ECE7AE3467BDC142CAE85FE3D065D2BBDFECB5191966457D02BB1DEF1A7E373C36696D28421FB769CE29858E329F1F66C4B130A31CA8BA94EA145DCEAD22C2C56E9F7E4106EA977B532E1A7A9D55D43E9C5208EF3EAF170E63905BC6D030298771AAEF8529C672FBBD68702F6C1BCC7B37C884615E4394D05E38D34E885EB12176C6C33AF56FE89C8EA75A50CB343C35EB0EACBF759A973B0F65A054488DE0A73F6DB2D1E1CF0AE9C6F8EE44D7416E5A42EA6F582927B91A8510CA7C3E0044B4E9E665423C1FA079076780CE663AA8AD8419C3CC2D7951AEB4A4658D6E74D16543BA82DC86346469736344A512E304A54ED6A026933AC95E2CAAD31DE54E196F21B9A7CE8572CC9F35EFCBD678AB7F3E9DB9BF505B798331464CA6DC6302B41C8C0B757AEF052EACC2646F0FF0DCFA6D915B3D066A14BB1E439DD7A68A7BA0980924666ABE8E95D4153015627C5637EFC81F97CB527FAD1EB65EC623A713266E655CE24F5625A5CEAE8004887A4EF127832BB89A6E95A8A8489EF56AED8FE51777D46C883A1CBDD2D45AC6751F410217D511D9C96851199B4F1075BF836EC3751AA13478562FFB8369176F14B7507D6BAC3DC81378D9E94A861D19805C09E7D95401503566EAB2487E69C3F9852298403A92D4C1522FB08E2C972918BA5E319F8D1E7FDAB7B76380148E902138BD99866BABC15F81EBFE5C11A2B8CBF306FAEDE35D02D7553588AD37168AEA5A046FE59AE78EC8523E2BE594D9C7D5B4605B23B58617AB691E7ACAC66F27DA0D17524FF04D7B533634F68290F83F35EB15ACE70BFF19B347F7DCE405AB39EBDBA8022DEEB66C4FB10D16C551FD0F8FF9AFF94CDC1DD9E1D282C2E2427DA2BD1BCCE7E0A7BAE958A69E9490AAF7C88313A67424AC98D59377856F6AB8EC7E397616E8F51E86F852AE88E9915A0C5B0AD5E57E778DB7FDE223ED85E53743AC644D39C726BF8466472CC2C900D130A8D0B46B6C400AF2446046E83651C0F86CDB8B96A8ECE9BEF26184D920B35179A033C40F94A00977B24A37CE2FEA80EA4679D975F44C918470EC9A742414905E34B49487753F04E66589955B6EFC660D91D3525AC72F750EB4E0C0EAA841830EA20B9EBA7F43AFCCE8DE1A82C37846FE08657875A612D00B9F6F58F1C07B5253D86F83966517CF2DCE9CCF4D1CE3FC0B9AEAFBC73D92E7EE4EB92517CD65820116B2DE4BA4ED54E117E635CA80C68984CC8C6A8D5FD2E4F588F5ABEAE6227D3DC0B1355838788306C71DA6CE90021DEB333CD37B51BD4D0328DE175B3850D6F33DF7DFCE1CD15BB0FE5BB251BD92FC3018CDCF86E9A2827DBA1D45CFD2DFAA210916485E5C2662FDF801FE8489FEE76ADE3B0CE6BE6414F5AC89B64BC797902C344BC5AB09EEF3CBF92504F361EA3AA2BDF1D9D1CC694DA990AE1F4FD961333FB5D6AD724C712BB6F216D337BA6130F40FC8AF64C43E51F4674A7750BE251D48D54E14B81322D655D47D9A60DC14B0B4D5FEFEBBCC3FD54EA6EDC89CC05112ACE53E0CF7762CF58134CFBC02E288468379106954A7F427ADE2230CF80EE385D304AC6991D63443CECA1A957C6CD1CDA5B65F4538D0418F054128B446C54FBF549A8AB2989AD8BD4A2274D08E155BC179BA90E75960DF884A01CBE8F52D95625B31AD4FE7EB09C552CDE89913E16F1524B1E2CD071EDEB6318FCB145F08F68BD5A8B7E270BE7D036109418C605AE7DA18832E7224926D41ED282146DDADB38E11483E9919BA9930564F96676ABC213DA990F30F46158C101A89114DDF43C1844F39B674866C824BAA440DD4857BEE3FACEEC67BD0A62A12CE10161C0D4F2D7A900D33DAD9EE0287ECE2485664B96A83B96B61C1FA2699C603660DE49A34F2DBD7C4C01E83CF4B0E1990221D6E242BF3B8971D4B0E04182585295F7521463C335DF24A6DCEC3456F721D44261A86B082EC1FD8232AE7A6510E086684EA01A8A6A0CFBC6DEEFAC67F45E8A6B6F2DE045B2FA4498884462ADC991E40755F6D845EAE3523B218513E4BF0E071308FC78043ABAD2F357BDC75F7E551A403E39987DF2AC1F8668A0B75220C3D55763B08F968A06456641430F13559EFF3AEDC6FCFED436B9F85C799E8F94D7C90DBB5403A660B2C830B630876EAEEF80BBCF81CDF769CB9024D0E4657308D806C10F8A1BEC1DA5C74799EB7BD31BA732F0788684EF66882461200EA5454A0E5A564150355A468F2CCC6FB67BB948ED4540709A0C79562AF61BBB88C79A54E5001C168BEFF2F34CCAF684E46FCAD2B434F55A60BD0BBA8AE2A894FA8111D6469B6EFBE8FA7537AA29D8907CA23E06FF5BCFC29958B288556932FC820F91DE7E7A8A5D5A3A2C1E4254B647A82FC17661688DDBB7A518BB3774B777AAE991E72DD60CD47885CDDBD944D14BE13BEEB5C714CBF57347A224AF71E95C26552159EE9D1A04EF09D167EE33564A4764ED53A08D05FD40AB57039C9BC2A3A6E1511811B7C2020755E1D889F552A5912162B729D5617C6ACFD6A5CA7BFAA336E727C13ECA15D5ABEDBA1FAFA451C5AF1747409EC8E6CD2FD4C7E4CFEC6235170CFE181262E1922D23AA2413B51C2BC848434D47955AD1BF19B58F7B27E2D38231928C72DDE3F79420289060E48D988C96DD410455E4EDC60A5CF78D57DD4769469FBFDE9713A7DED6D1B735AC8161555BF97A671DC350FDED988731487EA9C13ABBCDB0D22F9BF15D543F4B7C1F72DB9FDFB4ED2ED414DE9349EDDA54D478EA1DA24649C919424612002DD983105D9B7870F0B250964122051F0028229BD6F0877AF38FC73A27E8E876B1A758612EEE3BF94FAAEEFAB2247F1ABACE705A3C587A260BBA88B66A3ED189D089638EF0F55B81D34680A0620293B39C53228D8D80F4B184B628EFFBCC3E4E602037984D266D6767BE2CCE6709751642A2821B86F57FCD9EC3C0CB5DBD15ADB43A48C5F5EFD8419AC6F2606E836E39CC3D99E07562332EBEA08D869FA7289D490590DB83E22C5D3D36FCB8DBF6352A799661E358728359CE5C8E1C580FCF24A91FE91E48DE5555CF7B13AA9FEF7A3748225A545F17072B1739E33EDAF4971A320E13056EC1DF53E1F14A9180CAC5A0CA827C8B140B20BE51A6CC1D5907C5D2E579E97C8DC38653987BCD69440C6A5D4ED53E21154E03DA52AF3E1C377D1BF32B0CC45C96C96C3D6DDD4472F237C576BF63943E9BC365FB30CC2D5D0556DCCB8EAC3335284F514BE897E62FD78D1C9ED301AFAF026D1F257BCED72E52946A76B5C5BA8231E13E34DC598E26D3366B73D11550DF1E5F78B45B250443F4FC38230F5883E19241C761C1B371A45E0D010906BD8925FB3A62E80BF9618CD0D0D1B5E2F9B75470B2D7C3819BDE2AD4CBC796CB97DD90E5145F20E6524E0FC68A23A7488E86D9730A0A95FDD73559B15C0106DD6692B85834ABF5ADE250B994F74F5C789F329F8BEF8808DCEF76D11AC5ACEC3A26BA7BAC871198668186E333EF2B3194662BB40056925E756C9C15DBD80FD7089AA43BC91D90ADAAE64C2E23854878E7BBBCA12F870B9A72461FE331DCC5423588BE2FCF5DF20BCDFD9B771AD3DBACB3119C28E67D461C7E1543572F22F285AE3BBC2131732D2949512E622E688C6FB6224D0E358124FF6B6E2280501180903425F17EB2891BB6D63441D23EA433DED94E0929CB3B9C9B601A7C409A36D97862B545903C7CD6752B3D0CBC578042673E4B52510D040509A6F06AEA689FB624EBCF0CB13E8854E024B82F8AA624A161F6A697D11E159334EB46058D591832BA9E7CA4695523CE4026D560B86A06DF6960EC0821F428709CD4062BDF81BCFDC5AA0E49671E741EE9E032886C2180DE9B5723F08E5EF343E4A76F86C8096CF0D73C166EF584DB07DCF3BFF8C8F68CCF4188B80ED2B4F8127525B260F86B8B3E8518276055604F754B51B6D7C01CEE266FF32D2136772BDDD8AEA1EDA2AC41252F728B6121572F8F2178D09FE0D651489696DF53954C291A8324E704A5BCD74AC0B29004242F4E2270E408D6251011B7FC3F03C8680CF633A798AE3B7898DADF1A425A6D8EB1E3F7469294F601072761868FA1B7C7131F23374DAED4364E86A7CAF2F5000000000000000000000000000000050D111A21280C00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 6 iteration(s) +mlen = 32 +msg = 0100000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = E1412C0A8930EBD5BE73CFF29B68C3AD7426551E499553D7CAB9B65A984CDA37D793CFA5011EF4470DC57BF0C7D1C25449CD23C82868180997EF617A42D425CC5E1DCB6127D3B60E017A9AE1AC7DFE980DEBB098F6099D4A5D497B0EA1A063F863D484A697F9E4B87652249301455276EAEAAE6E5B9C32991BB3A247F5EB6A64049C317A2E262BC9FBEBAA53E1203D780AACDF8D8C1DF9D104DB25002257CFE39C49E88EE0ADAC298199EE0285AAB5966C4DECCCDD64FF86A76DA9FCB17765C10CE7EE8272595B0DECCC58C8D89D11B78E56A4CC63B19D7D787988256A277B53BA7D99C1930BBF1CD550ACF5C97F6F1B1BBDC6A9CD0C3BE66672724E9ACD89240987B0B17F9BB38B8B323E21B7DF3A056B85CC41288D34707DDC050B8484598EDE78EA295774222EF491F0D621509C9361B7C8537A4904E2E5ED1640968FA6DFCD828C8BA6E771F970ACA894F0D57CD03CE325F4C3176B818F42F29C8646948B58796542DA63FFC905171129418A349C0783EBF5AE14B3FEE69492293AD3894345F07EDDAC036C40AD5215D4827DE6A0EA0B4BD2DD86826C7F5C340FD2D62062A41C075259A9ECB3ACE3722D3768D5A7D355373E3DE4D6F87A408E5BDE672F414826A2C6714A706198723D6E41FEB39302B155F775BDD01B7CB4925B75AA1D0A0D533A2FBDABF68D03592DE2B24A39D2D093FEA87CA57E16622E59B46988D7057540A511506C1E7C819D8697564E161FB221DE02DB05B8715D7E8CB81B96BF41B257FE6C5DBD8AB7E4B6CDE8A7E15077B3318C7D6B7C301C0EF33CF1F1C65668CE0106A259A599A4034010F5809FA7E781665D866DEC4A5BE77E8CD090A324FBD25CC07929B773CD8358D666ED767DB22D540829F4BC09C3A60448A23EE40E09EC699C784649331563EB114EC47C8F1731DB50761DDD7C972553E9819DB31148FB97D3B4C9FBB89AF7E87033536455F9FEFDF8566B6EB0100040ECD080287DA76A7791CB90AF6253E701D9705AF96B3597596AA58B9B0FDD7689ECA35A7AA7C21B71BD80C3921449D3C5C8D9A26BD386B5C4002C8050B6C7F2489BEE49B18BA85652D4B528BEB21F35C4C9AB1F5E7F5FA4098B2D470BE2CDA7087C61C4F40E771AC04193DED1C45B0AD787BE20ACF7C9393671C354DD70E93618BCF89F684C9FB7C8FCBD004B737A65350E912A1945FA6F6F082406526F8B8B4603E171B754A3F571B7933E07BC9971ED2C299C4BBB4293B3282E34FC1244AD5C4C985ACD31D4F2EB5B82E5B5E1F00C9BE628E0A317885AB6E26AA7667C73C12F541CDF463CD72798CB1F7908D2945A131CA8AC4BA6343BC4FCF7DCA98F30B0FEADE3F0841EE280DA51D9501B5CEAFCCDB8319F9B32DF23E74A12B4B61C44B3005EE58160C85302C141DBD6FE0D598B2886824B1BDADC874C530DF612FE5260E996C6D289A2A5F3F811F2B50CAC599477F9D8400298981654013858E4ADF2B6A67DAF24A5099E9A44F5DFC37B2DAFC4AA738D4690F9650F019583EAAEDDF32BA74C3468863CFD565D06FB26601EA919B68985F5B7F036B2EF1B7B0F6A738E292BE4B263D30EA5D9784221C09DD6BD77F26DAA6996BCE002783305E478CC1CAC235DA49057DA7F9CF7B8E25AE6FB02A46AD93EBC5D9440BDD07018AE26DE5C51C87556AD561F3C7E130A24685F3FB9E39518C1E9D26C5BE936CF3F9F08C464FD0A32502604A349C8956541D94CC0F11BD5A0733737FD75ECF57678264E63CE8B5323A0630A40CD6032D62ED84951427A5162AC1685F8682EE7D31621F6A77ADE12ACDE5634BC44B21A2E1CAFE4A689E0D30AC3D03A6903F75393BE77FED6BE1F970A4BD7F2E666721E271E155223C03C7068E4D9B348159ED8B09D14DF65F4D86AE612CE3A931FC4A66C60DA424D5C2CDA9FBD7115B771E3262AC7788C70F6C0241DED2B9DC0D936E613C795F69D65539FE00AE8E7EFDF07BC068EA4BB9BD83F5A64E970BAE105036435BCFB23934DC13027ECFE3DFB7A1E9D3F7B2B07DBA844598D4CF53D39FCE8C0485B8EEE92671CE8ED10B262E63944A1EE4889494917FA81E01B145B17FCBBD079E8574DF474362FEF1F48EAC5B8A443973B75E72330EB03E15DECFB18F69D10343F2DAF0CCECA3436C20612091E3BA0940DD3A5D5489338578E0E90F3795A7380D577A67E52ADF7358F2E7AAACC75BBB81537134A12771C1539AD42307BB2C1A5277C123F10B74216CCE836E78D24DC3AD7E794BFDBA4D0306A519CB122E3B2D5A6769EF54636F4398E87BD42B0E6229DD7F430F5C6BD610F9C67C68F1F7A687B98C2E5A61CE50C9989A8DE3F53C975BB75B97CCDEB3E0FB7C26F368B29DF709F18193B9BE27FEC820136D8BBB9A037C13B03E8FFE2484D948A284D505916EE424414C5DAF57514FDE0A84665B2C31E2D4C8FDE45BFDB2CA08E9974EA9449C5F332CDDCAA46140F08DEEB3F0B4BDA7BE04446239C7AF4949FAB33B40DBA8FEED31D45F85507FC232FDAD3C85595643B4A7F2503C4BFC4B3C55D969AF6AC80A3C02AF1F5BEBD23A66700733B36F133951193A1FCE5D429B6200FDAF383798A1D11F3CD6536D3F9D27B58A5388482279F925A8EC2850DB90F5F70650B0045B4002B952C36B460A5B566FD3BA2BF5BCDBA0378C54AC9C12CCB46C7FE110AA99DBAE10D5CEFAB484A3ABBD517DB89C71D60ED26FEE9D55E73BD4CE16D898BA426A683B842885B514370F6D854321E599E24EDEC6C3A0DB6F73C60BB36433EC58E162D6FFE8BBF2D345421341EC22E1D25FC740EC4D3D78B79484387A9207B9B48EC8585FB9F6BB4F776BF71FE7834D95BF4C6312D430EB79877FC71EA67EC4080C359D4C4901596E93EDF71C6B3AE2EDD5D491DEA03186BD3FB24527E7F99C708FBA19D606CC44EC5E1FFAA33CD2710CEBF4D4B5869230B151CA8472D35A49CDA5367098CF3AD4DDAF1838E77476108EAD4C399938FF0CBDCD226B6F06D5323C3D885FF1B043E6A32CDE2E052C7D5C273B5354EB020A81D4F9BBA9FD29A5148359750EC9CEB6AA9906047F1FE4191D07A0B018DF93BFCD96FF4AF3BEEC9C5E5EB5884B32BC84F66570B9B57F506443FF634056B504871E4B75CC1BEA1EBC8A9D5D07C9EA587B70EEA92B93F65C3194B343CBFDC28D1A76DAF95303C9C4EC0034FCA333628720BDDA7A3373D676E2928C08684E9D24EED7D9382AAE547CAD5837D6E1BE3E7245E947053EE2219D39E33218D9AE52F6B5EB487B0E5B16AC35FFFC45AC1D832DF711CB11B2A887647BC2C3713945F92103F3EE2A52AD946B0D38BC0BD92E701C7E7D4AEA25E6AA4FF2A42CCBF5DA9BB99F88351076AF1FB4E7CAA65DC23A78372E1C2FA09BA8D46152CDA3ECC8A9288598BED37E4D11507E6B5E239F377D1DC5AFAC7FB38FFBB7B2D4ABC6BD74771923AE17CDE020B34151D2555FDC1C09848196DAAB35745D88B80A79CE2BC86BFE7397EDBD9F16188A133B2900FEDB915629B3104DD6F00CD1403F8A62F71756D614C0224276594D4FB74891D1A2F93F43157B0A6A4135DD65FE25D227BE62AFE953667147FE7D3D486BC6D5436B218FB9AD0C6DF31CE8FCAFE01B81561E02AD5D34A0B669345A74AE16F651FAE91365960DC687B5738D98817B10EA8197FB807C59A47EB187BCD2E4E873BACCE97E70DDCBA6B4189A57FDF7D6F8B62A0FF3D81348DB2B8B35AD55D9CF67F668BB89D448A751B02071D1CF812027EDE8658D51BECAC34BE3EEA1DBF31E6177509C81F5E3A373FE9E2AF88282EC5BAB7D00C1325C6A305BB0E2B47989EF26AA3CEFE6A3F6E7CE5873F215DABF22C17E5E6FB210DA4F5B5F576B0800AE1D282A5D897B6164D3A32C5D0AA176DF03A6C1D2850CEBD40F5D97EE707EC307B13538FC3A0C83A95FF0EA2E5470E1B682ED12F9E65F366C45775A9365BF74729DAFF7FC0E9BB4C05A53BFCCE1B14CFAD49647ADFAFAA0059707D4D72C133E5EC878E9887B41656CBEBF749F9E19C3E9C4F464A67354A6212F43D15AF01A762D8C7445F7FF27CF835E1CE11C844E488036838FD7254AA6C2CDB858B7FEDF7852A90A8AC7FE2504DFDC1EEA60F64A671DEE39E72332E407637033A9146CE243950D4C3D07C17BFE22D9A191FF01315FD51653CDBB316E833C823EB459987AAC7E3D6FB50BDEE54652AB253CB9DF0A661BE1B5AE2A7E9EA429D7E8A5BBFE7683A2DF259CF2F0221CE0C2FEB06C117002D101921FB54E06CCADD05DE9353E5874C2B67B45571A83E2967BE45E77AD2336B076088B33F33F024185979EB36D57ABBE493D84C7F7DAEE3B10E039339CFF06CF36DDBB04ABD0FB8C8DDDEF0F7E86F9724644D6654D4FFFACA74F21F242A9722ADBEF84B44C9A1B7B815EA0317DC5CF688F57896C57AF47F44B1AED5C92853A7EB1138A125C026C9E73770D982A0A25785CD91A4F315D03DEFCA59A2D3CB3C015DE5DF285B53A455087D46109582854BEDFC301B9EA9D87D4A04A2F9650B8D9A83B6885FC52CD32EEEE85E740873330E29885C8BE8BC9D657E612A87EB3969CD24950C9A8945844BFFA33396876B885550860721DECE6AFB92F1D87707BBEF2A34915657168C8FA2E3050F1029355F7E969FABD2EC252694A5BED8E0E6FA4E8B91D7294666737D80D3E2F51B1C65B8E5000000000000000000000005111A1E272C0100000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 7 iteration(s) +mlen = 32 +msg = 1600000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 4F7C826C9AC53F6D972C7CABE6749F3E045F1A718C31F1D860283A9CA33F12A2CD9255E55228C637FAC5B89F39226C235956825C853E63A0370B5B6A1E531479D190F7F122D070142A664C1A14B7E7498E413ACF0F1215A64F629E67ABC94F76EC3687EDA08A1B1F3140227C6DC3EC0A83DA6D409B37618B04C961C22446EC81660F6F15DD2AD86B47B0AA3652E58CA9EF362FEED608343178337F20E4DEE23620C99E3ED4D8DF087462DB45A2845CA1FA4B732D17345A8BEB9DAC372F0DC399398D4C40FCB898FABB85D0DCF3CDD24E8A222B5D4DB8945774DD061DD479F4FA143A524A6554A4253B5801F7C4BADA4A50E5F71BF436277BC3E039C6A17F6AA4BC2B24CF84976438E5DEE8BEA760D13CE70F1B9299483E10509C9B4944011EF0A60EE29C6222399CEC1AC30F5A75C14FA654BAD1FE8B9D554F912F8B8B4A7CDD5D01B5CAEB95D5816A7E4DAFA42B9FA5CF1806E6FD8330A04ACFB88EA8D1244365F4EAE72585A17D06EEF04DC7B0A9CF75FDD251BF72445250D94DDDCD6C2890C4783D3DBE6CE5F062638B260F1777C46EED801C9FC5B9ED8C152D858707520E0FD4C7930A3CC6DF555C6495671FDB0E27AB1C414272F6C10107146F5D8244237A4AD939F72957F1311483838CF443C1DE48EE754BE77A267995C2EEE3EE8CC46A75723B9F8BE0A16BF8A78F097196E094F8FD9E06506DCB82E10A03E8CA0EC6F363816C3F095E7ABFA64043C6944E03F58CD478A65865BD706D4F3CFCC5D221822E728FF9C4180541AF9E1BEC0ED5803EFF2AB27C008A22AE991B1FA6413B6B6AD0F2AC94975FAD9D406CA77575FF3C02CA6916F13092BE92B43088CA1D808606FE44E7DB9F7151F83C423DD3C172F15BC635B44952C7573B592B2AFC3E59F837BADFACDFBB7DF61F784AA6142CD9118BE1347680DB435213BD9CFAEA1A128FE546E19E022C25CFDE56793B3EFF610783926B3EC2871CA1542784518C0056041FC18F604ADE4B0B56EDF2FD0652CB3577949EBF9CD02017F05730FDC741F267A8D03FFB41C02280A7DDC1DA0C0C0B85F47F6968627BBB9A7ADBEB36620F52F00BA2C772F256E20311643FEE4C32CA079C81B46CF4E61B3E9766758CA0A87FAA3F55328314006961DFB1A02773C363982EE84937668B98D98841C4DA6B4935A6CA15003716F7C372A8AE78C29BD79AF078E4CE9A18C9CDC19F313470DD6CD2E0EE931B29422C5A2A4654AAD8879E35FC1F2BCD9811E128661F7C40E7784DBD3AE2A80772519A3A30C40852C7864A4E79D4861C6B5E27F09319970DC24211EC9B4C8E16C0A90E3EFBB8A6105EC20761995592D85641C09EAE0F98318A30B47E2A91DBE8F506A3D0B4BD8700462F92AF214E0255AD7C85359D9EA046991057A5974311E94E0C5756344819743D40C91510BA540C7DFE2256EF8ED316C928D7E817ADA81B0F798FEC0B47E53776C46A1D58B56D95402F10CFEC2A741B9EEAE635898C8B2AC60F9660BBBA2E02377B294E0E7DE4426E402D5C8DE978A11B42AA123EEF24D6E5A98F82B49733EEFD74CA677D15FB6A1B7206F1D8597B1F2A692FEB244D7ECCAB6A9700A70CD8511704D1C469C6725B59417A8C25D90906222712461E9CD0E9A274AA609C511F6D6265C3AEC5CFFEC419266DED863B9A596934F8787E950810C648341374A33BBF2B16809597ABE0D99283F16BEDC855A95111BCB7DDB2899DA912DBB35248B567292ADC76CDC9EA09C44134A98ED555271D24798AE270B91265687D37275D5F400A3329DF5D5491FAAF7A9232C74A06D065D0F7B3FA3BDFF51E0A1A3FA8F2EF2E689A8AD260722D0ECAD61DFE6AB3E8BB8A810CB81ABC3E4AAA2D85E67FE5E7BF8AB1A2A0F70B1CCD50908A8E87017989CF8B4B928BF2E9F2686B05C1562C0F762A6DCEB3C72584823CCFDA18F42F9997E6C1758B5B3061FB757B4EFCD6DF14DCC469F4A1A0BEBC7456DEBE613A732D578420F0EACEC760B56A37AC7A2E7E7AD2DDCEC761A13812D3D688CA4D0CFBECCCA16BC0B01E6D348D42C10E834ADD48B53E910BE11E16E4A40CD6CD15E663C6433F699E060ECB7FFB17CECD8CE20E8EC4C216305470ADFBB4EC88710E6C051A3AF5FF75354BE0F8A192CF22E212446F561DB3A3FEEA12A70291283E42C15978CD919335EC2E07EB2F716855D7BB78ECB4EA0A655F66C16BB92447AF488BABA080259E68EF8A3EDDCB81BDE0473CAC96EFC887BE27017825852ADC1475CE4D17A51F50F74D2876134722679FFD5C59AFBED5FE43417A86F09A1BDD87331CC5B7A9B96A2395C66B5BF3FF17E6B9FDFDECE2A8A1A465C726FC9043153110B3CF6A3C9048081783E62C1BC6D3F8FE5AFA3908F9007A0DB29B539A4E5E83F811AA2B13BACD1612C0EFBA98935698A727843A618B13A08E275F2A1F4502A0EEA7F4BD369390304FBC5009ACFD6141631102E8401048431F6B6EE078A9A750A29821AC41EF6267581DAB60533E443B0444D87425B7E2F0DB338D5C1D21391068D7C32A0B5C9F93FA6B138DBB47623FE8A1063DBA1E7E993A6D8A097B4644FD394FE36E58D2715456974619872A1B4FA9EAEA4823FE7A456AEA64411554A1923B2BF9FCCC6BDBD1E07D469E24771740D79C5BFE17565C281D5725EE7AB587D1181FC2AAA4CE62A018A61274737A2C0E59FEFAA7FC32F1AE9CF40C82CE75C1EE88A4238ADE693E7CBE902A575F8E0A12D5239331863103FE09906C2E80E744A8B2DF74DDF78E745410786920A2F349F62346EA86BCF663123B16846526B9081718B422502653894E04EB13967444665D3B0424CEFB7D6D30DB4E84CB887CCA1C8251C01314EFF24687E10001DB87F37E19C8112BFD31BCF77A38D846BD11A869383D32F87FBD18877AD7B47B557C213075B7B66BB55460423E0219D14AFFC639D7032C51F1EDF8AD7559F817716971CADF47362734169E35F1D899A4DEAF03132E8408179F0657E31734C92D6447DDC740B5B55C4D1C5D354A80FD6234F049268341552AA79F6F37DA01745BF9CDFC8B28192BC0D0BAB1D722AD325B6C2FA52CF1A01713BEF7E7C428449F0AC7F258870CAC215BC471448B47DB93759A53124AFCD92A0BB9B48B86FD65B1C575221137000608620C4DB6A0812B7D9E632849E554446BB1794DFE1259E6688EBF02E4470F0E818B21F1FB6646F4CF2A3107089BBE231BD59F8322ABB0045CF3D0F558BC91A07C91CF77C917140E0FDD926C22A85A3487180D7B3CCDC43A58CCAD777E72BCD7DA338B6A486D0853A305A0DFE027C8E98BB7421CC3F84D50BFB0FCA0496BC012EC95D06661D548B97B47741BA9C6B66866E00FBE15DB52D5CF968163066A54733E1C62859969CE33AC9606CE6E6C2CC38405A75AF34EECE3EEA4874D7FFB42B55635FFE3CB5C383E6C3CF9E1BF30ED5BD4FB16DCD77EAA08CD5F34B0403BC97F3CCE09AD04FE0D5DD5A033CF008BA1111744AB06D941D177FB3C24D8A86104DB2E06D5FD85772C083BF6B838F6AD63D1F1025C4DEB2ECB931928D66FD82C970F5692854D87B9DE5A82D3FD726E300B95ABD03D466E55080CD97A5CB12FF69C2B7764FA1CCB48A35D1DA8BB18AE4FDA44E43555ED3DF57F30796EB4A13C1842BFFF6CAF9498B2E423FC743CF16C9F7C6E19AFCE9D3A2DD634900A51A06FC2EADD8FB6E816F74FFF53246624A28111EF764DA214CE1ED7A1FDF356C7E319296A0FE1DB5A4A16CAAFF06755FA5CCD5A669311545A946028806A75DCA6346028C5AA2A6A10E5FDCD7532E84BA3B5935EFE175837249A35CAB8C0E3284DAF987D1CB68383DC1D4F58875EE1709054859A7FA46DDA6BD0F04F35A0E4820760EDADC69FBCECAC8E449B0D9DAF4519D957D5595B3E7D824AF80A3488F6DE3FCC757E68937FEDF4F4DC267A6F0E3237F254C6A62FEC3759F4A08A0509FCA56768FC80550A798A55104C9B0AD9371595A4A5C5B00E13274828946EA4CF47F146DF6161FB961C1B9DC5ADBC66B993C0B436CDCB2BB98D6B3BA56CDC2E4E7FFD18AE54C42063EFFBEC222F40AD313619D4FA2464F99EEDBEDB5FD7EED24BB655AD997E4052C2C5656691C85701FD4E66C40ADFE4C9AB502DA176193060330010B0A2FC558F645593CA792EADEF21560A19BA0609FA27F1278CB6C9556392CC1322003269972ABB48E3D3F13EDF75ED2D27D696AFD56C6910C55F1E103B20B3A1EAF7E8B34A3CD6179EC003F6D243253AFF072DA6992E755D17C1F8F85306F18780EB66C17A280B290B420C18498A1F8227FA8909909FE98DB84FF9E6066728F90D08A0ECDE373F7A10CAC1911014420EF787FE1C6672A6C44AC3C67A55AD64E702DEC536102FB26586F13A6F2C7B26F53AA7E1B67EE8218B7131B738521C53BB9E32B513768B5073E50C450AB839649369FC1354AFE13DA4EEBB0E30FFCB622BC837AE21FCA627E7546755C9034F1DC4B5221A229738AD5EE45128AF12EEBB3B28A22C0ADD29A46B07ADD683BD299D542EC6B9B45632C73D07799EE4569250E1DA500A45AAF6F92F06C2CE245F2D77F4B0680DD69562A44FAD935EC7AF5F642D6C8534CC5031310A5361BC8210486D71899CD60382E92577BDBE293D484C50607895B6D40235E5F1F2378C9CD0DCE90000000000000000000000000000000000000000000005080C161B211600000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 8 iteration(s) +mlen = 32 +msg = 0800000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 464A36DE67F458E0BFB24C3988B420700B2FC79C11EBCD8DC15F3AE7C4BD88D939C4D450C2E69B8CDE439DD8F31023472F95BF20077DCF6CD357361162917C73D6756D22FAA92BD22DE95E303D089C5F5BEBDB35EC518338824C46D9421FF69FFD586B99AC3EFD76A9F92B4AFE3330AD81F04D2AA3E335488D1516B4F8588786FF9B47EA3C43082A67EAA7338DBA529CA69A3C2CC9D039FB9C7AB2356D7D47912AEFA904557BE7AD21DCC2C5D5EC1B7DC6FE29C3B466997E9082FF5B76C758F677A71802816CCAE8CF422D5E26C3EA5FAB1AFCC7721AC5F36DFC1E918945FFBF8590AC4FDA8CB7BAC27F42BD75960A8BE558AFF04362700BC13EC5A14165C1E2FD1E935ABC7634BE683A1FA006B161C489DACB3B87304C8E16C6BC3B198D178AEF455E5B3D94B1B1C8D1574E4369C7587DD811EA19456D4FF8C3525F4109093A028C94242F7888F1D0F37EDA92FD4324AB20221171E2F092E6351790349B6757AC3190992018A4B3B82B65282AEE78A8956EFC70B99DAAA2F7CBE58ECC1BD9DFFFE966AC7B1C0F2EE072187C0F55306BC40E46C2890DCEDEAE6F7916043F048CEAFCCD28032E3F8D687D20198BBA7D3744473B3AFCA295284BABF1AE006BD143AEB7212A425228CAEB19F87D7BBE235212EAF0690D536D30F4D5BD1216187A2FD812EBEB888A15A5E8B772F7F22020A086B3108679BD7041C7CBA5FE5BE8920578A9A4EF06E3D63A382A1A089AC66F39E715A7CF68B03538A45433F61546FB5F3B3D329F6891D2449D74C7601B988C4053B70E5D2C6432FCB60319DEAEDF0CABD72489940ABAF67886D90C8C5E22B2C2B0FFFFD043775BB91CCF9381C8C1915F48AADE11606FB5E6E6F102FA10C2243292BB9567C1F0FB8496140F72B7D8A3BB30C10666298B7AE8384ED079BE583C012FF54E6A1BD22EA8F528005612AA176FCEEA77BFFAA3443E7ACC537666574922078B5BD3227763B9CEB295D7024E95518590F566129773BFA8371825CE68ACA58D76BAA364DBE51C184681D7A6450C4442DA1D5F943E97332F74031B7326C6E52ED8DE535DA46F6E33D2B456AE9F6B24C94892AF7650C3C4193C11D82D3B859ED87FA188896E3C4E90DE4534D21D04ED5968BE5C8966674F42E6DBDAECBEDB0D3AFAAD6ECFA97A30CEA4C09EEEEAEFC069D8D54816F1BC57A9E109978336B4F6718E49432062DD137A928770055BC2766A745AC511D949EFB31C2F2FA2436B4BF1F98D6F0C82C5FCC88365F0DE5E99F99125284534FD8900223E40EE63F1301E4FF886B6CF972543A385931AE5DFA14CD6D6AB7FD93CEAE766E35DBC22E09866D5A125BDBC107C8D8C14A9E405EDA8F04F764289B8E37C1EA7F5CA0550F79BA16D65544041982903FCF614DF600DC788D908DB234ACFF7DAC63335BEC95CAF2673E772B8798199CF0199F80BCD50767C0462DE2B44E9B83AA02CFF70925A9A7242598F78726E5E4A0563DFD3C847B198CC74C25F10F14AC3C9AC7B57D007BDAB39BD12F18A80B6B1B6A091851C7B161205218E8DA921569B1D1E197FBA831663905E58DE88BC4B90295104332818BCD70F066FC8BDA0E46AE858B05AC4AF73EE90C90604BE8B9BB4AA78CF0387229FDBDB6DAA96554CB85BD95FA9E5B6EA277F058A6379C39EE2E94BCF5F4CC3EF936C80201FE22EE4B42F5F752A273DE0DBD7698964167721B0AF0430D53A69B9ADE587AA8E2F8A659E917EF377C08E1C80E9AE51FABD2BF48D393F806A4D1AAC149424CC8CCDBF947450C32D2E35522094643991CEA2FCD62AA3F827B1A17869FEDF099EFBA80016B916A9447B200C18842C0C0B8E21512DF0D55CFA369052A7481A461F133A56E5DE09DF57047D61F2DF2ED4A6D93CF21B2E9F5B220BD0438B4A1F7BD773B994D1F4C0B205DC6FDD50BD6051C526F63C91C0F8F316CC688714775961E114F3F23395525D8A44640032576C92A46E82B9C1B00157ADAF4E3483A49F3246E98B1042D1D23995BA8429E751B03F6F386F42BFCBBC02C59BEFAFEB5DFD7DE2BF4B60971B261F3EE2A2DE7191A520D0830335B14AFBF37ACA3998AC027CD2FCAA10B8F1E2068F110B751ABF3EC913C721AB1C8CAB31D1CF29CBFEFDDABF5617CB04EA123700D4A6C6AABFB8AEFAB3EE22F33C6C98D92C4A50E0F27D1FBC9EF06FD31F0C7D0526B10DB0D88627A4AC927CAB03F087C498BFABFB2C6600F73E6E83ECAC32D555ECF87991A8FE7F83FB3817EB5E88B398F5498D0D0E62858D30F2278C9A7427ABCC67E5D8A377BE81A0A93C262B462EA1497A05DF1983C34DA6AAA3A8B11C9AF92089C9556F56B6C91295C74EFA1624AAF4C0C3C7BC404E0023C8244CB8616D5352E61E63673D3920D41E2B7925B961F409FE522F692F405658A56395915F9979D28F6620FA0FA759F57C5D04EF8D69B86494E86F243D778E123B86ED787128853CD4C7121610C6A660FD7B7E3DED7B405E90D4AFF1B60B6149BD636D1F3A1F382516D8EA8DFF9981B0242CB0EBFD4FAFA63155F192CD2483BCF5B6A06A0C7B7B2DF5137E5B1E0691FF2FB95D065E115E6AB4C7B087170D2116275F0640063AEA5330B0648D17B3B7870259E6E8D87DAA68543034CA23E42FF9D78B38AE8C9D690747986554378F233B6E8E45B4FD40E0EBDC1DC6B9F221E9207668DA6881780D96079DDD6FD7B9E79A79F54E48B11845610E19CF659CF11774ECB092A6A092A58C3FFA54DF3046808D6CAA3BE698B215754606ED1A0FBB1B9C688D93AA6A51C8E70B4F220A11E953FD3DE404CDE7901B21A85FA2F27E38EDA37A11518E70E0BE97C2305D8815ADD3C5DA2F2C698B03CA930D473BE7F3FD5916624DF59168BF5B2CB2B7370DCAECE0433A06A5BFF3E3A64FE5A096A22124BF0D37F2510AFAABC93A94B4FEFCE8B963A03C9A89DDEEADDEB330EFF6060A8466350B56447453781B6E236412C1498980B9CF7E527ECD6AA1E19C1D6316EE8C1BE442BF4CF4BA1BA9FB5883A2A3105DADC1B43A9D758B6FA8DDB565C8318C73C0271C6259A88F0CE41FF5378B970854A0D3B9CCD65DC31F89E88C4A6DD121E12BC82442DAB16236B98DCFE81AF616F3039DCFB1F7F8F09A8248790A9DA50E80A2144B605F75BACB5554492BD4D18CDD49CB0A6BBFA194C1727947E91352EA439DF58ABBC285741D863B66AC49654F9406B9BE2D5DE8DC94EA0EE7E17C0ABF2F1384B90E521502922339532E001E3781CCA33F09A6EA0AC5BA91422ABDB0668A339B8F8C6AF7A4C8A44B2C91D30DCB355D3687BFC8B48A10813C8E5354ADFD011149973A73699814DFC7811BF6B35ABC9A9033915F48D0FCAFFE2D43D84AE399C39D404A71FCDE8D375974203C6DF99CF2ADAB52E765DA9E3E829CC5B18E96F86BC5F6466E0DB75ACC0004DE2D2A6564840479C493A52558A1110A334B5C3FE3ED5B1ABAD114D2EE451352853C7F766841CA5BB885B0BDD523385C228A261BA2369F8365082C594B295A9499AB3B95836D6764B4D8FCA839FBC06BF81B384A1A27136786E7FFBD362D9B9026B2CA42AA0E4816CBE2142E3C96F2FBBFD1824889F1BEDD40DF2BCDC9E85930140A99A6D294CC358ACCB1A6E736B69B15360C8687002AFB54B716C2A7E6A894990BE8E974C842F554CF3FF5C9B83D5F399BF7B08BC176BC55CBF49CA0965D29FD71DE9BA2C516D82C6A5D3E71774919A173C15E47E54A5E073973C10F0FDFA044C0027AFF7F0A4A06A0A48C6506FDD1158DC1D63072F13E2F16736EC9E5BE9FCE68B5FB129A1EF4ACF1AF3C66372958FFF0AC9EA86E1502E37441B7CEFC3D5F208E1C6FB4B293EF6964DCD1D80CD95AE905B780DDC8B24AE516385BC8E8A3EAA3FBE3FAF252C2D766416E84DD38329393B79BE37388314CA1B70206440EF266991BD855B1EB59869E2C96EE29BD14D8FB72CC2C9828979F0807B3038702B9235B627D93D7712C87D00F0E580F57A07685A949E228D5A808F91C20E371AD2A7C7DC47CB04D3827117560377C2BA11BA522CC5FD604E11E67C0B411FA82FC7581F6B3BD23857BC37230AAE8F2C16F914D2488E23C34F12D148549F9C066D95A7193186352F1280BCF63B4DF0D0486510FAC5CF8B03ABF45F35AA652FB5FD4BABBA7FB618EF680A1E87731EE117AA79AB9CC482A7FD11989E3891F266E15D3DC71770024436561460113FEF8D4EA7A9590CA908186CA41DABEAF35E9C2E2D515EE9C5CFD618163DDBC47CA922C657FB7C959C54842CC6019FA40E3AC2C2BAC9262A7C8AB79F3CB8C8AE6CA39D7A1ADEDD0AA70798D45AEB6D347749552260ADB3872EDBB2006B8B650D6E5DE76D78934A42A85039583994093B98F705A86CEB559D8922ACA6ABD456AE7011296F0875CE052E419E395B4F9B67F59AB578851BC7A3A29342115C362F2E19AF0251A6729981F9E4DCAEE9E6628A19A0DB9D12A014A5CC81A13100D25B9138E6B9DD2D6A807DEBF391B6A56DC18CE8D844EFE8E8FF1E03D4EB03AF85F9465B660125D8DA022E4928000FA7CC629B7C2706123CCBC2DABFB7B1B9D526C450AFB567FCC5A762D7D034564D744E52035E6B34E8BBAE827C252E50032743A4B719CA0ADC4435B7C7E8498A6CE10353A6C82A3A84A6576838ADCF62F32616E73B0BFC413F6FF000000000000000000000000000000070F161D25280800000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 9 iteration(s) +mlen = 32 +msg = 0D00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = E68878508E16F608560D18E3AD67A4AF53640FB64937E39AD0B7B636361262C54B9DF9F721DA48A3B3E1CD6E66DC6D5200949D8938D0BE6019C72362866C6EBDF3800620C512ADE29F5B31C43CFD8DB916E4B070EFB06B8E1534D92FC2EC4CB83747185EED0039A1832789E565E94EC8F01C3F57CE619E9656A389A1C8142324558D8B8F143BD6652C77FE42A773651931FA4857BB8C76B6328036CDA7FB2F32DA164B69984D709DC270A9F91D2EC31E5222A38FAD92E04CF3DCB99B1CC6FE106885CC334FBB4F896AE07D8CE2BDE81F346A28AD373438B6DEB6938FF7BD6988395182A47FCEFF6CC11AA44D1CFFF7A3E51AE1194E983BD64D6524DB77F366512DD156FB4C2E7719F8A9B711E0A1703676EBE182A4445FFD1F3F05FCEB6D0B7D2CB757B989127E23585B3A81DFBEFC4590FFCA2CD68208A390D99806F9126986B02757CAEC6FA6408C2AE1BC71D352BAAE3DED8185B7EE2DCB9A5F66E5DA2598C4710F4D1DF226B787A4BF620D18C3B2AA4E01D4A1BCCDBEC97BEE2BFF7A062329F8C59A4FC72ADD75472E0B9B9A0BC7E69ED0321045F0CBB1BFFCDC2FB1D6782203741AB9C8CB043C07B3672A523E806ECAC52713F9CF24733C9694F84BD1844FB272D2DECD083F9779D583FB6591BFAB6EE5C1D300C99CEB94957EBB96BD1EFCC0C44B46FEB54C16AC8C78BCBD30AA3D27BA0FFF2E6A4E175B42066C0DAC8D7740B769EB24FCAD8F0CD90DB5840B3BB36359E8CA30F3CB12D0538E741A9D8F536BF4CDC888DD2881E2CDB022AEDCE462C26CD1F2F81CDA5D3AB3A76213BD8FB75753236523CDDB436B9180A5CCF403154B93B57BA5B24E7335506C2287BDE4319D8CE48B9D10DA5672C07A23736F89944FF56BAE2EB49C2BF485F1D8D6718265A5DF4E632F840929AA1B508F91FC9797471614D93D2C171FC512D99917E32A37CB24EED04DC4FAD9BDAC904A076F927A14562C81CD027B6FA32B027BC2B60E1B7B50694533D3BC08FA6A5617D36AF278199D52F566B1A770840AE26274357470DCEC5FE52279D3D342A118EE44A85A017941E1259FF070F2CE566FDD8EFB99FC81523740A9128448ED728276B6E22F29564E6471599D109EC52EE6EC45C284B71073A157F57225B29E3BF1DE26204CA82FFFE2BF526E77020E37446EC5581E63A246B76EE9DD86D00B490E2F2CA258FCB5676D95E79335F2039B9FFEFAF59D7785BBD82CDAFF931F147AD3838F8EC26B6B4029D5CE230B6F2EACC4107CBB339E69B117C64BFBA217F4A89224DEEAB637A6D28CAA0963C730FB0D15860336E740466ABC7F5145ABA081FD592A54327200E481A19A9A91DF105DD9F064666C2130B63AAC8652815FD4318E6F06593BC00CFA193D37D4BE276886790DABCA1A3B94F0DB5878B03E7296EC874AF7D909087EF9E9DAA06D5111076A9E2672D7833E14CB858D2EC3DEC31645481D36295966D1BF8D8C2B18342F36EB77CCF904CBF6F5C2B5A52B7C0EDF23827356EC7DF716F7E3231132C01292F2D088B2F2CADA8B88BC4038D955E3C70A64E047CA5A6B73C73F97BFE36B0BCADDD403C70C03DBD51492C76FD0BC87364669DF42ED1D6CDFD1A96F51F2357CDE949B173CE9FAF474C2EEA3565A3CCB6532815AFD469B3DB6E01A239B263BD70A6EF147CA3F471AD065452CB8D3DED26D0589F2598A072FC5799C16A75FF4A1648D1A1DF4FB6BAAE1EB92A1D2CBDD588E3935E56A90D8CB53A92CDEC9EDC6E80D66C15656CEEC21CE75CAEC72AF9B5B7883223DBDBB71CCA72ED008F49941055E71EAAE4D858D5DC3EEA06D76C3F9F92F3DDC26C1A824FA1B36A84E1011B0E51C37E1CA84B678C54701B24C72D809BB49A78857CF84DEC8A79886719C66E32983098C80590B817209A71D115F11F8CCED1B684251BB25D3FCB3DC9107D3C8E4FC551EB6CFF7C9AC7A5C03E86650D7AC7119DF3B73A52083CB520683E1C784BF47C9428126BC4298F7B926423AEB67FFB0D51B4DE97DA92A690FA0CDF7818717E0C3DBBBE26CB8CE6DA26732D7125BD31C4B454AE9308A668C19BB7C29CB8A5BF9751AAA65C7BB5D3B33CBB3F9D49BA36640D16C32EF88136DC464C60E54307DAEF9ED8C52679CAB4E48793D0D2E812C88D5928A7F6B378332AA1593E28D070DCA8E744505CE03FEAEE21562B90C59323E88CEF4AAF9C7802C504D552B6A5EAEE2C49007FA5930B12513F1898222EAE1C2E08C1C0BDCCBBF8B73DB580DBFF060491F8434712329E5A10378D7E891502E45288F886036544DB76274694E7C45B8A1E009408DB5B1DE8E5E4B53E5C98C3AF2EB8CF3ECDA76C14BE58A9BB1E2EF961D3DE593157FD67D08FF93973281690504CFF3A55D86E9370199BC464ACA85EFB5B0BACF233A58E0DAB930478D79CCF5FC2513AE5624204BDA96C512327E165DACC79C35083AF569B39706996A0D699E3EE9AAAAB2E02CCD4ABF6B763330789C7A4113728DC4DFD9FAD065D2DF51107EDCDBB1D32EE9F563972668BAA1DF20E77C09FD96B538AD2705C58B2A87CBE0A532427432A8436E671F4965E05F0F10081CA49C538BEBF0E98BB4CCD72B0E21AD5961F93D9897953B27FD539B7DED7BC981D34C313ED267A244CF76C4FD54DB755D3C114CCB9EEE6C4709E0475F919A49DF41CB3B76C7989A15E2AFC8781E394976D142A14DE5ABB1A984CA1E9C5131A5ED2DA4BF69A3777585291C782655BD9696456967D420A03E27E9FB6F3D217031670360247E14DE3AC4A2267B2CBCD1BE7445C35E3726AC90E74873D373B58C522A85FC4EED6176D6C4D1FA26F6DC644868E2EE04118A35C51A921215C36A04407FC967DD4BD41FBE43B609A0842C4231AD11F94D7C18A7D65179E4280065CF55DEB6C7BFD65A24530F92EEA71586C51A17F964E9587E71B7D6249B96CA8307305133E2AA2E8CFB400EDD8D3D5E6DE5DFF6DE3DCB4382AE53EB30A3CDA97CE83E61C4621F2163B2F7A22009123DF09D10D534A313D9F3B6A882FF22DC6D4D56AA517EE23609EE1DB6B45AC4B196CA8699A132A8A01882E382F2A89FDAE0E259332FBE6D65B3987A5B2F1D077DFA5C1ED8D461130592669002150247ACA0C7094C9E831F4303EE9398D54AC247A252ACC1749CCFBA7DFE02F468541F0F76A697F90E5C1E7737F00FA6279ABCEAF9C4B19E476A2C7DDE6763BB3CA9D75264564C878FB8827C3CA7CEE86E8CD6E9070E09B61B60D14E5F21600FF547F0A8C894A0E6D03E1BD779102596FD54E2D5DA6B93F901B5F482DC0223C6B977DB029EF1D5B3EE9BEABD505079D27B72D06C9F12967DB41B1BC6F3E806A16E82DF9C7DF95E9C3C69C40C1329BA98E845717813A04AE816BD98131899F54F7D2673680BAB5325CED6DD33B4AF8B6D727FC19362EAEB74589B3A81F3C2E37626DAB4F2FF9EF42FDED16C81FE7D3D38B55468139B0D874FB21E0A977AED92B00E23C5E0A7EBC9B4DA764D865D0C8A74C5029FC38E0715095FF6DA6DF4AEF21D13851BFFA2D98790E84CD456820D3FF56000BA61113EF5FA278FFCFE962AE4AB674510E3B4C409A78452A356AD705DB0001C78C4ED36EC95FDAFD6C65BA8E01474F0E0DED11E565AED7AF85D42E50C242467DACFAD3F07CAEF2CCD80CE0254D19280F98B20F535E7528B9BF14C4D182A11F235B3EB2FECB680FB384EDF7C8E1D0497AC298E8CB16F8038BFFADF7B6FFD898E46B71E8B5C3D45A1C83ED3B44C7F870FED1502D86952C77A41C2401AA7B48FA61C19E1869A7371905F89CD9670F3BCA59B9313C77C41A20493060712CD3E63189ED5D3A7B372AC4A8AA4BD351670D0F5BAB0F5956EFAD2BAEEB7EF8F9540CC8BF4A166C4BDBA16E8DBD76989210B9B5F066F9332101B0F8906BBF75AD060FABA2A0D59B7A721937F82CF8D24606CD894D2F097B1CDDB32725EF9C1923B4AA3E0014F19F955F873CCB1582F4EA6631C43BF4D28E9EA9F98A79BA798A6D130CC91AC5259B0CB5149FFD2859864D962790B1346918B47829C53EAEE487BE3AFF644F402EBB0797A8BBB04AB375AB2C008300CF5EB28EF4F43E3A6FBADEF515285B8780914C10238AF19AE80AC6FEA959566620B7E489EC3DFFD255A871AE06BD6DDEC26B340F7983E184A2E1DD25D1DB9566ACDF0E6534C73E894C88EB52E85D8921B1AAB25A4BBFCE665AC2DFD5D03BD8FE4BEB8B42CF93ED9418E494009A4AD4A9F7C3CA516A09C55F0B62A4BC4431D8B75E651998C40007CCDD658EF51FCEF5851FEAF148145DDC460F26E264AC6CEC355DF1E9F19A3B47AAF23E8BB5EFE2DCF4C12CDF76A5200C4522708DD911BF287EE56ED5288A092A3724A79885857C6B759B04E9E956CCCC3A0C087C78F787468E4A52C72971AE7FA8100EA015C662405853A14D1E9F4734591E96B111B301C2E68FDA861D4FF4085A46DE15DE8ED123DBB77DC7CD286EBA809E45D6064169DA469AC17AB32D57FF3F9A1B79C3FB487973A10CAF5F19BEAD7E29BE0E4D61C385D04402E03F7FD47915DA98745A1A8CAF5AE2FE05CC4D8C6C95645798CF453D42DB1B189AFAAF957E91BBD924AD2F6740EE6EC2234BE5B08676710145BB92F488B9495A860F1F42D439DC1FE2A40436896DA353C4B526F7F8C95D2D3E3F20F104476BFF0F800000000000000000000000000000000000004070C121E250D00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 10 iteration(s) +mlen = 32 +msg = 0200000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 282F0F7272B8B9F6CCE50D748F0D3F9761F610D4F636BF25BF2EC47B2CF033AD91C0C60ABC1C11CFFD5F9BDD41468454372CCC204A83D613C8C1DC3C5A2AD9083B9AB3406AFC430206E7595736BAA97123FEDC02B36AE5D0ECE70B26890E93F8E9919112DA1915BCE6441767A9252D90A9671ACF056AC1896AA6642936A0578D1E84CCC95522D2D49611D6B67A28163A02F777D5ADF1FEF167431B1D143F08B1A908914C64B40D6A3BC259B7F850BF32F14D9BC0E8E61E3BF789C4FC059BB45D48C1E58B786486AC35BACAE36C51BC0137D28810BC288223F2126D94E0BF36CBFEADE622585B37C80407E777006EFF850990604DE7836590E81BA14E067317B889D33413D71F2C38F6F3D19DE662E61DA54CFFE96C9AD5518876A842907CFAAE3C83A5C9393C8705D451BABB59C306036A0EBC7EEEAAB2AC9E61A5F58691F9CDB5DA907FAAA055094515491EFE40D924D9F50CBEA000300D83B20CEB99912FE8B1BC8108C216420C3D52AB28031413DE2B55221175C3C60D83FD2E06138DA00A76B77F916A7C9B97C145D83E03AC8433BFEF3EF4937D29CD0E7E75EBAC78A8F4514860374AE97CEE2D3A62C44F1A3CA9A1B80CEAE734EF1220ADD08C96B6DB12CF28D39D8583AB8D932B03E0D0D6873C7C2428405150A7F3664DE648749B92FCE22E56AB2EB422F26B00CE50ADF5C6016E92BF5C58E917FFBBC86C70EA35A37FFBA3046DF32D24A50E3B42CE2070C36F7E2A6F6E6D85F5DDE6ED6C9E0B0FE6D5627DFDCC9BA00B0E400157ADB5107E392ECA42CE4F4C42556A0AD16C1D36B6146BE7EE747A005857C8059F8854642A623AA94132CCE088EAD46F0CB534A9BFA82B1ECB6C00083207C7049468B0432FEA8BFB75DB58DACF174D85D10F9DC3A98240CCF841385F4220363E5E3D40F4B4C6E51A14080DDA0BDB3F97D37BF151EB6BB802000D87BC522436583FA3950F6FB7FFD5333E7F732E23C0ED85A1C3545B1C771AFF5E6332717ECDDE23CB6B64A350970379D4F218F865245F8483102FE8C65CB3BBB28EC6DD8973B388F8C4DDDBBC7D979EFDEE2FC32B6762207AB568B192AE3D7404E2CB6F158E61475549CB325FC0585702BDD5AEDD4707216C78EB748082A441B12B4D9C0E79FE0189AA088D39A26380C5498E08F0A38712AF2E0AFE3246B0F99969721D4D2AD2FC4BAF09CEE10D2CD2E93ED41406968140123D21850418299EBD5FBA68AE153573CC616E667FB8698431BF76E9FA2B0E1CE0F3A2A4DB5DDF4033A6A51082EFB64C52C8E25280CECC45EC378149A608660402754873CD5072330582D2B6F38722C2B31CD98713AA06EFF1A59E1256A6D5BCD4916CA6C0A017E8823D2F98967E64132471A6AD8E7F157A8224AC5DC219B57C929CFBAE11A37E742EAA1A8EBB7F799CBBCE4DC13F003CF988048AEBBD72C39F8A8D257BE7DFCD959B72854102B92C3F17938A8FA60BDE930537865EA8CABEF0216007B841D2C3B6A1DA1903B35A3226D6634E474EC83DC6D2EB3CC6C0ACD7905C5AFCBC01A255B4926A5AD781681FC5DB7A0A73F49A8A5B55D313CC197AE9EAFBC8FC9DB13FE79447812CE4E4F0CE2FDDCA7DB04C4FEE7ED282E311528A00410DBF0A43FB311C4109A35264AE7B17A7FE64F4E9E0F1A579224226A04D5A94F86B9120ED208BD0736833B20DE004FB46B41D07D04C1A4CA786A49A45034F1815BB49FF032BE4F48D6FF2904D989B6F6EE9CF52ED5A5B83C93CA9688CFD0679C40B828E1BE7885F42C14716674C733B7D51E9794CA1A35A92639BAD80A8E05323989848E848FB3C4FFF60BEE96AC9E1F665DA9648F728950D0B0DF3339D26838F618D6FE228B5CC0416F9DA3CCE99DA0A1A453C975E4172EFBE4E4636293B64BC188D0DA318EF428B6EF17325B136FEF140BC45CA8D998DBDD65CB28F935A28A60AB12B502E95164DA6704A5C9667708294BB45D8D8508E4CEBAD5A82B4AC75B0803876AA1F3D4CF7749609C726AF0337B84ABBAF620952D8803526718F56FA341EA7D89A2D08BB81C4D4C85CF4A828B443A0B29DD247E7C0E31490130B987C0B391C1FA59CA4F7AEEC89A9AEA1F744419A08821DDEA90122989C186023D179E51456BA066AA6449452770734971AD90A67640CE95D10EF6C8415FB34188E052D5FFEFDF8D97DA4F67BF59945E0B1B94463960230862747F847CA3F294759B131BC586C7630A64C69DE7E6345F8C8C018DFF3D386BA99C3BEBD3D79896CF41F516F007006B1F9FB948A3476B1D4F47B95D890E99E8E4E3D301181EC263291C1D9381240F450D636976F8A4D88B00E505D5DD008AFB36A058ED3192D3A36755006BFFA0C14AE06DF23D73756BA918B0672A3972DD3BC09B12C272E136464763DDA07C98E9C81B9D93F987B786D92AC9254B63DF4AE200A3CB8A77950736B56C5CE5FB4255DBA095EF0C2ACB965377F57600C6ED20C532C77756E3E5771D4685A0E90D7EB553AD85233D61282F71ADF5B4B9A49B1F77247CF77435D043E43FA6EC17DEABAAB8952360F0798292C8F63C3AE4694C237406644AB820B33C9119DA8BACD0ED930B5FC1197FBBD6218CF493E86BEF3ED4DB1E1B1BBF692CE8DF4758FFA08A782567C2379DD563774425547DD0B7976BD17198465125743AB65171EEA74E8B55D06F3D6593B5B769784CC39879BD3F775F1D33B11A12FF67945AA943D0772336D862257C933C283972D20D18D6FC793CBD7F9643A9CCEDA691F7203FACD650A98E9F8BC9E86671847298CCB0C3A2CF4BBD58552F81628FA82B4D4863D025F0F4438C2F31411A2B20633D24D0B90C606043D386C4190DF5225EF3428D0D9176445AFD7F70D3D0D27EBCA9EB517C4BDE3B0BF528CFA1BF7A1A688C6ED6E672FC09F93396E4A0227700627E9837CC8E6C653551B021071A7D347DC8FCF77F51B80FC43906E7B021A61F51EBA9E89ED78A630F8E1CD1863E4031EEB6E6497C493B47CF245575E6543ED138B9CE06C8188F0E6DE18F2CBD9C9F74915A0260E4A3D4F9EDC1B68330B9DD2E61394CF9D9E193B1B1D3B2E10A0EE23B4146FD5CB261BE5E48FFB2349BF31346688B6517F4E84C9E32592782DEE40854DA7AF0CB67D80B59F08D7DD9D410360E89DFDAF52B786BEC57DC09B2EA7B9F5A6765DE586B1A40024187BC538C5E71B19BF54C692F687DAD5DA709963F208F45702C6AE500BC0BE672680249CA271CF915F239433FEE9676E6B007B04E5C1687E4549184B0B3D65643467FED567D229A2133CF1697EABFD45F58022373AA4331454EA041EED9CF612CD1B1ED5327B80C24AD2807001DC827164FB3CF8B8B57D61DDF1AC5B4F1D9DB78F08BB72E347E7A0AFEB9477FB6D7F6613355FC24BE06CFD6CCF6278B4BEBA566EC53AF541C2A43A33C6D749BA9CCAA3A5F92B3487151FC1A027FDEDC6C4EA81458E01DCDEFB7114F3B7AA48153E3BE3B37B7AC55A37EB90D0AC4CD52F3C5BC744C3CB83B8F4EFE62D23535A9B1127B707B99D1438360C78E3D748B49B8CA75A2AE6AD9EE0F61B396CC5AF8F75EA007E6C0134CC145527BA4C2EF30EB0FC8BCD9E5976A60DA49909EBF2A8EFDB7FE6FB285C97BEA6188BCB6B9893DA5AF769BD36C5BB273551D7AA8CB9486193647278FABF78DF3C50AE48C419BC83E11C18D840E7345BFEF2739278FC106C6C21E109D5C0D4E385E0D72A3D0B1F4CE5CFEEC3CB6A205C57381A1B1E77F3D42B0D21BA1D358E217D3C5405B1D8FAE81DD2C3DB63B8A8B1E316F84D6A98878D0BA8DEE9833A75CE240493E43826430144AECE8E6D1A465CA08B8AAB43200094E81120E9C650DE002BFCD0EDBCB5EA44F4C32E2361374B2FC4FE6352A7193302ACAB5750565FB6858EFEC3DD5AF2DFF33DE712DD4ED2E21EF646066B9FC8B3D0BB5CDA6F751BC8327BEA3BDE750DD6F4E4F8A7CCB19A96BE6D0899B68233ECA525E488A1919D11D8F2CD63533FF048AF696F601A83D15259B9CF12C403BBC1F1E033029847399ECF60FE4271D973C79B8F6C7F454CDF34D27FB69F37F9735C69B5978C30C3C53400EC70C484776128E36F0A87DB358880F33671A5B3ABE4658E283048D6AA76BE8BF6B824040399D0FD8242D9D72BA0E1CABF5C2AAE2C8AC6494C33098E2AE1EFD82F3E2950D2D66173A2AC2393AA3CCEECDD55436C0E1F0BA29B46E89FB709D3DCCAB024A26479B71CED06939458E15D85BAB7885D628E05C570CBDFDAAA81F35AE30982EAFAFC1DBCF612932B9AEA1573AF1C43E335340151AA43EA07DD8DD1119CCDCFD90107FFB8ED2AA11D945A9B271F40C5D1FC9571165A5AA45B1836117198E6CB2AD915631C0C7C71DAD998167E7B57D771015BABCB0E1CAF9141FD4B6FA2C9A3530B8724B955BC06C53609B89FDCC942DD5738C2B83A3C5724508B70BA96EE1392B45C2AFD2224FD580642BB59B7B350216750A8850A92A7B12BE20E644E38E86EA8A9595BB821032A07C60C7BCE0023B173ED26C51A6A4661EC072C042CE7EA9260B4488D8E63E99DB7697D9BB2770548753319E74C72730312C49CF1B4A4C5CD25A3EE93C3A7DD2D2C5EF1851AECBE0748C4A68E84DDDBDAB500001A575D77C3CDD3183ED9DDE8EAADCF0F1542BDC2CB350F1A3F404A6F7C7D828C9396A3A4000000000000000000000000000000000000080E101617250200000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 11 iteration(s) +mlen = 32 +msg = 3700000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = C637BB0B0FBE6404058B0C96283165CE84645A9D97507C6734778E42809B8D2FE0A78798D8286B11CDAFC239ACCF515F80C6A6AAD43BB304315BFE6F294697D41FC557A68770F74157C4B6703C154C19C3FA39A7EB85FCF62D4D9C8B9F7B06EB1BA9BCDC2970369BCD6D0F42FC0776F5403497F3D419676EE4DB3A2858D7DA648CF48773524C12BED8703FC73336DF29583F8A25DD7951147F09EBE5DF6D1D77CF53A2098B1B2CF2ADA0C307F190061E3F71AE4139B3125693E8E0FE1E91AA4971502E1300B1FE5486F160B4556B519F82B5647689110F559137879A7EAEF84C7E661028ED16EB70FE9A83F8F6BCF719E03EC0FDC0E816ECE340B1EC8A7653C80584C9AD51CBB6AEBE63EC59D3D31F747CEED6BECC4B69F112BC102E29D938CB690314A6ADA4A46241222007DAF6B25E57E851B861DD51192E154158E6D2D12060E14189885E536DBC2503CB26D05E4D72766A2EEBB24F9AAC8FD2684DE33B822D419085878338ED6EF87C3716C3CA1B3F538BE659426545BFEC8815AE56DC3A013F4D19859CEE5ABE44048A3303E0F8E09E3361B3C957EA5A99057F365A4CB68F03AEF58F016E026BC733140E8DDC77C6FA049F5A5A2E510F03EFD45B08E145D8F29A8519D92520A6DA04C8CE472C1A6735698B35EE4CD6C3B645D67CAB42E30D9A47CEA4CD292EC8067F7CD357F87176236C30777AD9D01FD12963DF2686C0060B11A8DA4F06415FF2C4DACEF91FC9C6D06FE85FAEE9834C57F5D7FB77F79B52D65BA4F999817EC5CCBC4C63B596AAF4F83F4F25B40C96815DA4B80965818E7C9635500157D5BF9D000EA265B53B9C7BB6BEC81028BFC35D76D3156CD29C7E4AAA27301169F11025FFE1AC35616497AF59EE9829053D96F1FB4C8CC28EC9BD86E7FB493E3C7D8BB9E2D968B2209058DFFF5426AEACA97A6D4AD94D0F737B2944AF849190CABFB5670F9F26E0DD1628077B12C2062FA6E4D2F901A69A8C830B3C14E491FBA4D975083357C7B1A74FF51005E34CC7601672907873BC6D83CF678F2ADE44E4F28768CC07EC00F58378457FB1F714292D331008DFF4555FF8C621FF88B40A25324F4651C09640747752E3DCA6D4A3B0B9D08C513DA50D071B967E6E8610273F7F9AAD3ADD836B15D0783C3239B736768F8A3B39D21B6382939123118BC6A798AF8C9266C0006E3DC1A105D0CCFD43FDA88949F5C8E6F6E022E985E8E36D63D6F80F923D9647BBE1E8F6BAD41E873CC8F19CDB3ED4B1A8B9D8BD2372C3A2251478449ABCED3C64548F697B388BC888281DC72CC67F046A116959B7CFD7A3C50ED74E1C7B3F9B4A5CE66BF862FA97E35634A35EE95B14ADA6316D0EC6356A37F53BCA72277F33275FDE43107D468B09F997800AA039FE5515012F9A0B01341FE15D883A34E8A2E11F05012527DBA32AA0F07F25035B128C50DB9BD5E498C0A31165FF0C41AE58776854DDA4937EF6591316A5BA687B358EE1DE8228F3EB7D654F1CDFB7EFE7D90F7B8D0A8C06E680611CEE19426C84FD68E7AFF1E8BEB95F4A6414046795BD04611760582FEB963320008F68C9759EFE9CE7AEA81BDDC7A97EF18996813DE741F872D4B51C2A0D2C2292262B6476C4160666E652BD89201B8393C26AD19580D5840C2EAF88320D343D6174774CBF06E3DFECA6E5C1FF39CDFEA6A708A24C80F8FE3D5BD74AF0D6D2C8BFEF71C4DBB2B1323BD5C2E6BC9EA5F839D2AAC40BD29D25F81D30E801A05B40A62A5166573CCE6059138A119112420958FAA76493EBA44B47D011053D1935533AE2F3F6EBD4BAEF7A64111CBE7AB7734E4B41418335C93963BE0534D723F4E1AE699E341955CE80A4F5506DD48E28C673E74A1DE2D572A94842B2B50BEC040F39B374A6D639F0A747C49F12244BC173708DFB0D2762D7C0A9A8C0BFCC7D3C6F5E3B0FB1E23FE0DD0898E0A1C40D8CB4BB6971D716AF1D4BE087010B2C3259EA03DEAD8DF5FD6513268352DD8B5AA447B7139104105D6E25312CAE63DA6369973637381794E2762C3D70D6AAB7C243FFEECC08C1E4E4EB1657FE0007888C1FDBB83D76612F8457DC0FDB6845C9DEBEF1D25C1FAC8C2BF37FB064A509D55639DAEC683DFA66F117D6AA6440F2ABC3A0A806657E4972BA01B326DF686A885D9845C94B799AFC83D9A57F238089A9E201004691681FEAD57BE7DDE96B23E56A5A590ACC6FBED77509C8C966EFB321C444C04E17C14764DB8859BF98F19D7932E648C077CA905BC481033E35B64E5840D467E84FD0107FB1D84489C9B92632C0AD494A6CF942AB41ACAF27369370069C08BED93DD22BD20E26B0D6B41787EFBCF2B02950E5C68C9AF44FB1764D3886C15859BC2F8A650BCF162814A86B7796ED3F4F292A025F39C239CDD4BDFD02BD37070C06673AB9EB3009C38CB1CA428DD9FFB08776AA2ACD91AC7294985F99590863EB0EC7AE4A0FFDA1CC6366D50F412ECE784C85BF98197B18EB489C5EBD6369E15BD696879144950265A1CEAE8DD0F1DD35A350A8D21F5C9F421C98912EE8323D0C68527EA634973EE63B4343960523658E32C2999ECCDEBC6041988F21B0874F0AA0F13EF8D5742D1BB9D30FEB8211C10B16D3804BFE3D9EECD6FED832FD42F596E50BB045FF058FB410798F62D0E88A853C22509BA6D46ACFF213AD9BD066F231DB82BADBFD4A530BC671839F4529794C6AA3DFFE9A9C4F6A496E0ECD7021FA048F60094C7CD3F49707CE114EFB99185A7022B1C35BE8A6BA6413CD6B7E4C8C2351CE6CBAB76F2A37943315258625BACF8AD6C177284952BA4ABA33FCADF26A9EDDCCFFEE13AFAD56481513DE9CE872DE6BB602B10F831000817A0722E663C372F4A955713ACB201698D0ABF1F4BCFC20A1B78D1391A72A335253E7EC6B623319FBF37A2E18ECE8E8EBB2B57D04E71D723B4ADBD6A61BAB8F7AEA926ECA495343DE90F7929AF9F7FC8372D16DE32140825D7E26618FA67E9DC97E305C1750C7B01067FCB7EA337172B70CCE793364977A6EAD1CAA844C6B9270E454DCA244B46E0579375F8137FE0D4713143BB54CA9B25CA665292872062D02770064231A0D059541D8B27724B1F72C95674030D712516564A6287EB0006EA73496182E318E0BDDE3BBD5B4BEB70B2479D82894DBEAD03A69ED50CD9FC67F9F10D9A3D4E53489D75CAA1138435942C19E88291CE5E35386215AF3ED866CF9B4B1B13D04A159A1C6716E9DA6FC8A311A711DBA23A8ED8FEE81A609C9F21AB6D6DFD0487A36B529B77D3A974FF8E1DCA74B445496430EA3A5FC9F6FACC2C571B3862310CCB01F9E8C54BBA587C387AEF2053A7EC5FC2A28C295E5130C69BFA30FAB41C4A28C1220F1CE76C38231BA2DD5465095EBC8EFEFC8D2F7EB45563B0CBC526DEEE42B6B0E4BDC1842D4DBCB4CCD882AFFF6F13DEE4CE935B21F2A954A54B1A99171945FAA72E5608006C89CC1B93133B64DBFE0DAEEE95521038083B00983713ED865EC20A47DEB8EFEC70AF398B095E01969A4FC6DFBB3EE6DF653EB40610D8CEA3B5923A1B98771BB11BBD8EA11A7F9AC23885D183A91512AF88CFA306C33CFB09271EBE615698B6E92663B0D374C70459971A0A961D5F417B662FF12836E03C63EFEB34AEC10A9336D2238E94674BBF6201FB92628F167221A071DD80BE91B10FD1B7964866F47FAA29DA3303F116B742A73AE122121E109896C2AF6D263A494B827556755BA89EE64C6FD9868E0CCB7B5AF645F013847BB4147A4DDD2423934C752C966312C0D3901B0029250EFBD4176C01B98A3D5542B14C19016DF3F5EEF6CB4BE5CB2BEE7856515F3A703BA445EB5D83E1312C0B94DC4DDFAADA7998E769093F1E8CDCBF3DAD82CD643CA63DF02BBA13164D036D2B38352DC7B8EE7ECC316106080ADF2393CFBD956A3CBF1CD723E5D6BF0D7DB0332ED647DAC93386E4F452ED75F8EDF6FEA39BACBB36F64CDDE2E085A6D45B6AD6681B8CF5B277102052CCBB382CEB8673A5818A12887D3B7F2F9C74337254B6269174C342365E0C5B5A1CE5533BF915A3461FDD2E97160500F78806F08B84D195851A20AB33B83AE5D0AC71A8505547AF363A4E7E9ED1D1153D19BD6BE44CA86D3C3A9B12C547E5397332905AA08E59874F296962A8CD8F448FB797F29DC4CB1691F130725E9B82C5EC5BBF880088A42D4AF080AB83467DF4DC0C52499863093C7213096AF405BDDE5AA53AA45C1588A8867D9C0521A7EA920DFEA82A39600CE1D8314C292430FD82FF036C14E80494E7F6FD50DA981C2C8ABEB7E1D78C40DA1ECB65D9B1AB6044802F7054889F719CFC13DB6BE8DAE3DC66DD5D3F832F55A3EB8C4E38100ECAD3D0CE469E05125DEE3F6A5EB671CCF55FC62E39A4D6C5074D60677A40E738B042A00A6D5FFACFE65E263659160C5C003F3997F9863A46AD77A9D22BA6D1EFF1DBE5348EAD1642EBFC114F422D67F73C80147FE9B6D8BC19A2DDA566DE07F64E52D0EB8A0326BD1A9D4D61E107802D83DD7DCE7575734610EF3377618731104B3425DA03077C8299E8E66148109624125AA477BDA68EEE54C86F5AFA56460BCFED063F847BC2D5ECB5EEECAA7C9D050648F1819292D5B669CB1CBCDCEF02F89AFE22B40CC1E1F2B414A71D6DC374068E90000000000000000000000000000000000000000000000000C10131B1F1F3700000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 12 iteration(s) +mlen = 32 +msg = 5A00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 329D197DAFCB5775B679FD04F0545CBE06B5EA670A0CA24C294FF6BF179A101A990C5C1D0CD955BBF66B8AACD6753E3B73A5D60318E508F18EDF02C1642F4BAE773BEF697226C2D2D32A124C33230A610E9726CCBBF7810BC35880F110BC5B943EC08B5D48E69C7E517EB4C6E3A09223EF092778792D5C0F1C6146A250F385729105DA422680B375EB90AB9CC5375A6252DDC1A8C9FD43673ED24A1BC9B29C33DE1910E73D7ED01447C9AC5478B23E2101A41334D8C5E168A4CAB4A8A6A9686288287181E3775A072210F5F7748BAF6DAFD3A5A08D623A780528BBFB7AECF47A7127A53FB97214C1D0B15FB2C07BA054BFAB2C051FA8323E8D790731CC146AF1EE8D14EE1AE533DC2E8DEB327B04723593489A0C06E7C6AB483FE0D1B95B46433BB75DC308B300CA38F25877597C30B94B6C6D0E6BC596BA0A1F46588E0CF2DCA60574B484B29592C9453FB79E2D26539F384F5C01C8B3881A95CB0D23D9C8715A837D2C6C4025A80A5D9F889C1497561718F621ECF740F7B8D5F0BEC6FB68D3343434208F193F1A3784FBA2BDEDF35F42BBA4A292F40937E09FE5F83EDC8E9140D9A0ACDC872AC7E989A86A8402971A7254D59EAB5DEE25682B4EA56BDA9A30DD5DE53C6186E94F8D434F61329445F4F573684F3746CFFE66520F864751C22E51A2C1711B47B562E383F7A4273DFCD8C661AEB6EE8C2671DCD98AE3B4B4E8E896D33B45FDFCA4307AA7BD34577966976943B69236EDC5899F57B859990A81C1D646F9154BEB9E6536910363A5BD4BC6384CA69414B3637DB541FEFC75C7B8F7ED04A9A29918C3BBD8439BE6836E81C3628E0F281719DD362DC3F6709A3FA90D71E8F0BDED396B2F4B42F160A614494E50F3098B1F15730E59DCC01927D3ADDFB9C8A6F2FB9467FA526803656033F7961EB1F97352F76607FF76FAB9737EF795D033168AD31D3C2E2A50113E8460B8A05A5D2894E187DCBB7B1BBEC8CD3985A862EE115F43EB9BAF4E3432C4E7AD2AD5B14C1330C5BEFFB08B9A1F735EA76FACC8315C30C0DCF4EF34CE2B41E4382F39C20A1D556C559055F9286D3C91408DA01BCCF91ED532AB6B7C4B7F9E26F188FE7783E1BF8F0ACEE41C801C1085FB4DB8E0124145EBAF5B6FE1C067241A60BEDFCA3A60604149B008C544DF6C5532A6BEE7DDE9D7970BA89B392B164EDDAB4A82B92E2F16C317BB21AB83E461DC7351743715781C74DEDD09492FC36428D5E31BD04FAD10F18BE8C70C5F38607630EAD73D36A3CC93B440CBD4B7DC5D880ECB155181B4D5E0C982047380B88872845C9203062C37DCFDF3F70DBE812399D696025A3AAB6A337F71D8025F5FB2F76F440AB6D950A0D405348AFA6309CC359E5B8A30C55AA6F6C8A3CE9019746D8E89F350BBA91CC64EE3E9B129DE50D855C8DCF0830CF9EA44D0A481A2A44254CA61B443FC7812F913367F136700B3EC7EFB0050E4817036A411F0EF1AD51BDC2232FAA0FB85DC27B675BC0C3FA929524D52ED760088D310BEA8B3DAEBBDEB019DB49533D34DFFBC8B7341BD68428E5F3494C1D27F9AD4D3A337AD0271E8243AD82FC54606B48872AABBD3DBE31A670B0B2F1851FBFEFE7C9711F6F03713EAE031A9A7BC44E7F8B08B9FE9AC5CE6FFD19D49202AEE7194A982089B348FCBDB98A722EE916237EE11B6DD81B53778662EB0DD6E890321D638D283B22AA64705293A6D26ACF72E44C4A229E073EBC33E76717D1F6DF90B583578C5D0806FA224024F7F3CBBD6701FEB91EDA28C483C0D99AE20EEFEC8E045A82E6085FE87C6F0543D5917CA8B289B4314222102128ED1CECF8858E4DAF4275A3EFED28A7FDCA3182D741687660EB0E4C30A0489BAD636BE6752A66425C2094B58B8A52096A0D41ABED69AFDFD0C536F23F1E0455956A444ED84BBA3567F3BFE18AAA315D88815F6E79A95DB84516213F89B19496B511A60079322E2CB40550409711046ACB5F25BDF7AF252AA7CEB45211F8474D02F488FC7DAF82C5B99EA803F509BD07F31A967D53A9BA872EE29D39255911A7FBB3FCFD3B51501A8CB7231EEB09581EF1373714772B15A3D752EE35C5F5C64CD7D104D625810307A946E2211CF8BE6AF39A0D9B12C64F1E03FCA1CD8EB10F3CB96E4F1100952FF7CF5A71CF4C2AB867B94C7E73C5585314E680D33686340AA1CB26EC5B6A9B2BE75C7D8FBD6439B1199421A68661057331291E5175BE09D38FAB7C11DEA9C38A7380C62AD4CD3B9567353084B56DEFE4740E503B38DFE1B522B3B9D04C1FD9413A8AB2A318DCF3C1DA81CF88D0559D3E5AE1E2568B3A3264257B740819D0B5DEAB9192A3DDBBD0C55B8B2092DE9BAF1B9A98BB26866242D94389D8BB7DF073D851B086EA341F52D36D1C62DF7DC351529584E2DA55E059A8995C75C2CADA3750FF15656EDFB46593449566C35A4BCB2CA17269404AC1FB52B8312D43F24036C4A69DE33BF09119982A9B59921F99EBB22CD5DA19ED1A9CF22BA1BF19A1815A4266139F5CB2BF78B4F506C571D3D93FF4A2C19F8F705953FEA214B0FDE0272AEFE59F26EEF138808349A9805A47EF01C76A5D236160A7D950520B0E1E3066D3CFD78601A9828C9FBBC78EE4A115083AF5DBC57DFBAE21893F6FD84C4D78C8502B8FE21902B78B785215FF8C7928780220FD6837288472A904922CBF3A05195455744BC7BEA6E086F8FD41D63C26FA411C0E528AE03EAAD592F5CF2454CD8AF3DBDD914DBED2A7CE827E49F90420F65763E7DF627750240DE5D288F83D39ACC89F2FEDA0F15860119D472FCA64D75E16A5F62ED79FA96FD69B7C1358B5F1E97688518260154E4ACBB7A54C3BE252A9E7258F05DF3511B97E5AA66B42A66F481F7B4608BAA3CA922F24E8D9CD13DF6B8A015898738CFB9C9FC3205D16D3EC40463CDB4CCD46717F15AECB61A2722171F7B8E55003E2E1795EF0CE373283C1DC0582892C0390232EF6F9B95470B36235BC1150B9BC469BBACA81ED54EA12E47C176E57B99F2A544FF64ABD7BA68A3BA2ECA34944E44D7D103E73505F09B26C42FF5B70400410EF69F8D8FCF7ED4B69B568E8A5A53FE6893C2B1FF756B7BCC23ED98C3E9C7B6BACE134D4BE35E70EF761521CE673B174DE2FB9416875C66DC6CA2ADDB810B0B2C85E1EC9EC36345A8971A69DECD0DB973D90ED8B9DE3B4511C0C16010ACC43C2CAA47B9D8F4574C0F1A40EAE91EFC590745844EEC43B159B76FDAE4DBE2FA4EB50F62DF085077FFA1ED648B7ECE8993B8A9B3C8163279C0695FDF287DF677F21B0B9A2582F2CF8A7BD402BC9D2D2C447A3EFA95F774254900BB5BB307741F28C6B9F88B8D168D2392C81CEBE15B2A1A25DE950BBA9BD9F9DFBB51CBAFF1D141C61F3014B98144135D9E032555441FD89E063D8B9BA43C92471FDFC00BC61A45A569E862B23BAD2150351E5268EF01A490A933A3CA894E6F69336C7F3BA6758F1AFDB45640F0CFFB1F5C917DE1477941DDAD6483F42018688CCC4A6095256BA3F36C7537113529735AC6251545DF9B80B0B7098339911DE42DBD0A92F6307185077862D338240CA63EF8808232AEB84E914508E4C50627E6B67905948ACCCA40CC8EC9AEC4D080ACABD6955C51F468AC9F11962CB7FF70FB86DBF3BD4D7D0AF9C1B03C26453DA1C8BE775D649F9DA1027FD27B6330B432E862672A24F3AA208A2922BF66509440AD278754640E25BCEA025AADA0ED67159D9307234C4F2A9A56FFFB6AD53B395F95C819DF975BFEDCB8201EA39E08176A9BB83662D2D617DE735A1469D08F2A4B4941F378411062B3E4E9E006347734A13FCB80920C87FBBE57719B63D3028C52206C5F621047EE786CCFFB16581718E41DB86CFE419FE498D998CE63D10F8A90AF1B283C28C1253EB8BAB75F8DED541964202C4ED2C85448E4E1B184A87E5E6F57FA15F881010479590C181EC4A7183E21DB1C8B8B588023E4CB272C55071AAD4E651174535E3F678B675125C27DA909ECFB6F63E5704549DF56A0086DB2A0F8E2157D5AAAC663430B8F27DBB7B972F1550A409B68142B280799671BF00BEC11CD7899E42E4AE7C42BF4201023D1AACE65116CDE7744E2F48505DF146CE94DD9EE993C38B603EF96365E28ABC9B9449AE4E46DB9967A9D2C414585E3A0AE9CCD59176F46BC8BA7361D2DBEDC615EF78534C860D279AC4C0D0DF9F7EE1085EA26A7DB76525B79E0169F9545E4F67AF5A3BC804FC7701DFDA5EEDC6E0F9AD05245CF1B9462489E71BA7DC8721234BFF9E439D07CCF92550DE55FA1FCEF637851F2CDAC6C8F46A6C565FFFFBC5FC0205A948848850D22ED9F4F26AE014E568BFB52A24555E68C30592B24ACCF4A56EE3DD6268A3A8A03B77414DB823B0C169B4179E210AAA40952B5F3607AB1712F0BFF61BF27C95B2E1D1346E85B760E636BFA01495DA92CECC4C9F89FDFA410DFE51D548FB9B1170156C77C7CE23AF4EA42BA296F01C71C0FEE4368E0E80761381520E5D276E819369385B13F06250B3531BF81D14A8CC015AFA9BBB1C3AF8DCB7F09666D48AAD985DF0A3BC079B28BE331D1A37C7980D0DC3EFE276445245256A8026755FEFCE0B9FB06666875B0D3E3E6EE282AC4DEF345C5ED19539CA8E40B1037505864727CA3E5E9FD295C87CA0000000000000000000000000000000000090E111622265A00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 13 iteration(s) +mlen = 32 +msg = 3000000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = ACA955FB8AFFE2BB0CB8E1B0C4618D56D56C9699A62E2BF4362CC2D493D4A2265C5DC0071CBF9F2FE921AD693F471C54D6CC650859229F19CAB5A00FF7C1414942DB1FE91DA60B617D7B54C31F740AB920827CB8FEDA78E929CB9912E3FF4B62D73828B43406B8EE8E68BD77E9CEDC71BB36F177A9C4F0859E8DF215D75BAFD2AB9F8CD5CE7A5180A2E0E47678417AE2DD0A4356F616CA5733F753362139E6D27A1C51094F9119224F66131A4EE8901B23D5631FFC35D3FE6F034DE35EB70FC3BB1835EC0EE49B900B5F459FD151846DAC8D7DE188937C21F35D11C92BD0C390DCDBB03E3431BD91974E985574A5D08731C65AD59FAAAB7A5905A8E8156ACE76CFEFE7F0DFE083AE0D229319BE4A987695D75B93E467FC169B8E4E0DDC23F5C940BD9A8A50E0ED2829FCE480AA1B1EACA14CCDBB1DB5EB39DCEBE1EC234014B14F55ADE7A6ABA06ED980E4A0004C0E439BEC8AF9EF6C0D711DD323F73FAFE047E87F364164931162585BB7E559CA3D1B7CBF0383ECBB50D3FA2B9F6CD776E923CC6277F11B9A68008B01FEAC6A9B594480AAD9C178F8F8793A4D49BE97855B914E8495B46E9914DB8D5F92F3CDFD59183FBAC84C43B5F37494DE9E27EA72F20DCD33411E17E38BE40B02D1D9603BBDFD1427725A4E6EE8286861A601EC630E4F6A3820CC5FEE5E92D125E1C1E230E5F24A51A5DD756B21645EA52454FCEF53D4C45480510D3C5AAC9C46991177276D993E584EDEC16C9F0E61BBAACAC5EFB72D3DD6F66761F6FE555F389F791A189F74F17DBF19270EABC7B89BF72708E98DCED911C9F3BAAECADAE4C1AAE77F082D64154A5F15F1AD0967C94A0590DB7415F457A81C613EB792EA31FF54851B8066F25CBCA4D48669DE4913B14A877C50CBABE803E6DCB0ED70073EC5874709D92BB5E14E1E4E5CD6CA6193F89A61A3AE3B7E255EDCCFFBBEF97B9D891D5DC311CCEC4E59775F4FC671F9D6263308BDE1A0D8B920509DF922561932E6F422AE8B92C92035E3FB5885EA32FC64CEB7D448BEECCEB5A9EF651DB0469EDAA36702B0210C5C8BEDDBF036115B44D704063B1904BE41D596F8086BF84498B114B299B7C6DC519D4B023E6A0E22231903D0185630504826F0895C7C405C55F192518F04F56F8DD15872E9CE583DC24D95515FE32C82E5578299B00A8DB6B2DA48B90FD8B1E758390558A09449BC594C38C04B7D11806B297E41E78933757050FC1004F20E8E0AA1AA332B84C72337FFDEB5A092F6C05948C5C49AD7097481A6EFB785159634F9FDBAA8AAB2967BE2D864BD1CDBCF648A94AFFB8CC156F8B76E6081BE81D18247E28DE5E003A05FD67AD947D4F07223439E160E3D54DFA5323D48BFABCD4A4EBCCA482C8E88ECD571AA45F25504434B6DDAD9609F7313FD89A64923A79FE3D12A68CB323D429CDC22B12565F6D971365F8DE3EE01D0926CF0A711EDFAE2BDA639D0328A58E32547B64589DCF1EB26556577E0E7C3CACA3B421EAF53FF109B46FBE323E570FB822E4CBFA881814BE4B8E7075F3434825CE1B58C3CD0BB429814E52BCE0E02CEB1B7EF383FE264DE2F6EEE06FF18B02A7C2CAF546D74F8113D10FE7287E1CA0570745BADBAF2EBEEBE5DDB071214E831B885D7C3746DA4248298B8F5C74093DFDBAF00966DB348246A2B9A3C3140EF3D64975367873D985172383D46A3A790054E671BBD0184EC74FD2FC17767326DF3D71C15C3FCD4DF2A388AFDF7ACCF97C08872CE0C1A2C733DD5B48449FDC9FD62BAB34CDF48A258DF60CA2EF20A9DCBB56589B47C3B3975A6A8D28D9D66409EB2FCD1CD4608FDB2C327BC47A75094BEE98173A6B5E22070705D7E6AAE0EF2DE45021DD5BFEA084B299137B3D941AEDFAEC158A3D025521D266DFEEE8C41E4D1C425120639144E76CC0FC68DBF64B84D16B09FBE83B7A9B19E74BACAE9ECBEF8B713964262C3BEB333E5BBF0CF96E9A767DB226357B54BD51F94581906885BB96E20197AE2F24B8A14DADF3DD0A531F3C855F7D2F06E0BA8887F9441456290E3AA60EF6EA6B52AA048178F16079B2D22070CA23A43E7C5709B3CE2F571C2FAA7FE433D6441C32E006B9B250F184269433B13DDF59772E9C52FB971D236FCC8EB71F70564954BD06F8C2667A1D918BB64C23C5637E8F411386A97C1ECD68F7BE593B3AB09483A93B92664F87F4B91FA0E3E24DD0F1F082D28DA5F13E5BCE6FACAE211D690F55431574C55F9F40D0308D059B0A8D5D49CD6E938621B0DE48AFA2DD46BE95B1A7B77357881CC0DF2334B2F90E43E8D78621B5501D447E53E2408D7C4398D59CAE5A1EDF930218DAA72088F8EC2E1C64A5051400C58F8DE5306326C1BBE0E821C6BD7628F32930CF459F20566EFFD455D6072EDF25B062452BD84CB465507B79CBF3532F726B1CB1BC6CD1BFA58D518BA2D395B27B4385EE693A58A32052FD4F6967D1F4E187F22526DA8D1C3FC0E5C208516DE0DF96558061ED41619B4B1CFCC3C72BC6059DDFD8D611161621A42DFFDA395FF8D9A5DA32C39F929D38D7E2F3BA50EC9879C7FD641B93957AD7491277907140A33FD771F40AAAEF04003769083F0183FB191C66612A53B68E54DFEB6E247C8CAEA47C6CF846AED2BBFB2703C73B810F8786F92247D0CD8DC3CBF30DEAB5A0751D66E6F222E2A40D4CE37A385B4E869F1B27A1107EFE0DA464C7F8A377DB6FCA17B68130717DDDA1661D770136EEE43FF12D9146BB13090D80DEF8BA21C5953BBB4B780DC34E5E0A0ACB450A44A0903D18735C39E386C88C3A49CC085096404A347BE7FE2E51C11FB82B1ED0E6C8B7B7935A8DDD99F090221493CA46A38D3447A40DB20FE2E2076499937606AC5E31047B8AA2E9EA44D19B8A990298AD07B78DAB6E3C7767796A7BA6AAA96A072C68FB610A3863E07A8BAE57CAB674862972B5FD41190D0EF7524329C311DB6DDEAED868DB7CC949849FCBCEC4D5E78CD52FB881C6AE8646E3FC1D4C58B65E888A6CB7F1A9905AACFC7EF63C5E007E6DEE38DECBD69919D1C0252B296EE2A212D3862C2A6B63E1920270CA2D287D79E6C3A0506BD4D16D5DE0937C7D2BC8D0E9210A0F14157383D8D5DE764F9E8AC6014BBD50728C051F817663EFC7CD89F2751BF9C0CBF15A005CD0FCEDA09DEC15B0777D781C064FA4FDD56ABE26A67EC75ED6EA3F6EF42971C2BBE732FB8622D8D006C03CCBD2148281259EA19F61902A949568E2A73F42B46FD0E097A04CDCFAE9DB2827CA86BFFD0FABD2832575476CAB43AC8F7A6E458DB6D89E13A042D8397CA365EE81E47C190563A9E2A2E5835B0B76A54598F2A82F34317102F763B4E4DD035F605F2FA1BFDF124D4CE1457C78368D2CC3A09E947951198EF6D1A90E0CFBBC115B45C5A39B8C575AC7EA57D57FCC0C757D5DC65AFA33AF81A4316A859E6F63E7463E0C506B86DF8B898223AB590E05B8149ED7DC4640FB1BA9BF0CD3D9423FF0B77ACAD57F5C8377A032441DDDEB770920E17F6535FF5B213F59910F6D2CE723294788DB3A1EC15D9753FBED0413A154E3559C7782F4B1B1D85E911F9FD53A0477B38E2CF3DC357D3274C887615946C536666FD9ED2AC02D0409BD71CB050605B6D72B5B86837D9C1834CF56B18BE49AAEE4272F45BAE61204D101123E64952C1EB8C9BDF827B2872F237F58277450B704158F4A1D8836C2B5D943D76DCAF3332407D104295254D0567A3897E2675454C4CC8711D3EB974E80C7A08586C058DE444991BF6D35AA9C0C001EBFDA40FED69D9AD63057A6089B46C4157735AAA1474229D2BB4C0DE4DB11E363E24DD97E23F41CFF4A902E2A22F4D273A1319209325CE275F898100C1A8644B6F6182E9C264206A361DE85B3BE510F0884722A34D070123BC59A5B704DE7C1C5C7BC335BFD47A1524C97FD42529CA45339473051875012B06116CBB6B6DDD5A9CCCCAF1F02FDED20D7613A5567D07AAC42BF78BD2BB1522A30CC3B3689A2DC08C18130DCE4D13135D14946C68B8E4CCEF451C3FD2E5A9A24B6847AF0CB1D94D4E156008B5284DED4A465C3657D8102A5B8A1099FF518532D7E23A5B61711CEF14E99F24C3D4454D06439105335BC522C54A3CEC4DF7376120AC34DCECEF775DB37666467AD58DE5FBBC38F0A8D2D3BCEC651B3FF4404B20FCBA8314EABF4CB02976FA827D5F11DF895BA518DA951E62B8CFC1C4DDEFE9A9C123FBF54351B9084AA5BF7C0D63BF142AC0F401BDA28CA60888CE3FD93740EB6C96AF730764175CB3A017AC52496C453465FB63E474FF9EFE76F855F6C3DE5C54BD93A1D00FEB6C9706EF8344732102E0C9B1246D8D86563E5D4DA036C3DA3F15C325605E00614B1E7595DFB15F69DF83EC567281A89CDC77C58D0103EF36A6F6A66044A52CFC97D0399161EA07FCE9545BC2DC81F71AA69EF3CFC5F3FBE2CD00A41CE9CE9BC4F4F53EDB4BB4515C1C224B5BABB24E8164098034AC0EEBCD4271BC3E03D78A10FACD8D44C28081CEEAD3419E009898D93CD80D950CC2B73096012D4FE3FAC6A99F960C1690F2404F08D28CD9E6236C4A62E7C158C00DAEF24780F36313FDE6D0BE73CC250788807D7C6EA2BCCC364575889BED00031D6D81859BC3FC0F353A5480E3F7387475828FA9F400000000000000000000000000000000000000000000000002081118191F3000000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 14 iteration(s) +mlen = 32 +msg = 0700000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 4C20D4756EBB87C04E2B12BC10E946DEFBD6887C1E1E59235CDE3E54F82E24A7BC40986CA2C136250474A24A6A4359E6AB24C0DD5F888E6FF4C3811165FDBF6BBD65F4C343A934C50CBB617AD05F611D70AAD50C3EE1E82031599C8420A14F2249F9702AF294DF6D357A26E3D3BBEB73BEE1920451E08600A48375690269EAD2ED434A4B07DEC198BB71440A6F1D3833207D592F41227EA3B80BEE740B167699B1D1B62A8C0D380096FE20550A35621C91AD0B8B4591EECC06E968A7A0F42936F00BC1260B59BB8E998FBA8369E6C0E4AB59D584E5D2FB6D3BE236D6DDABF760E43613F9621BCE0926008164FEACA03FA415BEAED6E229EFF38AADB3BCE226D4CBC14590ABDF5DFE3671D01CF73E3B7DF85649D4FD4A8DC4A0610943612BF8826811F014E1561F4D73D27C2D047ABC03DE8479C16E9C200209B74B5D5AF065C379C815CA3DE9479C4C796C05FFB1425273A33E44C508B90FAF68D21F71DB621BCDEAC2DE596EA8E2DDBCF8D83C40F212335CEE03E5534033716D9E48187C5E6AED2B2F3159B05B7D26E664ED55ECA7A020333390B5D75F2FD339B7D9110E9FD43213715EFCE49C058FE3CA8E9AE0819F59DA0972875B6ACC22D26BDE3EAFD0EB771B63CD750E2FAF94849B624BC8380A7273357040DA6D8DCAF17340952E61475F15569AC7FDBE96174AFBE82F18154F152B828A1FBC3E0FB30360B0F71662425B226833EE355B692B4AC28BD76043CDE5614A30573690D0491AF1EC2357FC92CEF92185701772C027B462859BD88A2606D0E762CD166B2EBE1C941499E001477BE199D116CC10782E2FB2F93764860915CE744CC1C9DFEB5004A5F94C1035B7053E5063DA3151835E7CBCC6C03BB6C245B29A1B53B5C60BF1131A6C9875B67F70D0E09B24AF743C0669F55218B715F768EA00374C546157877C5F8DA88506DF17D08CB6B43616A52AFE7FFB1E9573DC4748016811E362A0CE050DB3FE521AD275872B2574DCA118357DD8C54ADC327E1C3F279165FDD6DA2AEFDE314C8BF25C0ADF2DE1C3E999CD37EA9440CCAE029A0A18A71FA49E3025A3534B4F5EA84146D4761837C6ECD6494F65E413705D407735151F63325FB0AECB6A08622F7D47B78DBDE33F928C25BD7552BD5EFC383954905E5081787DFF7A99C9EAD9C1A22E93C5611EADC2110BC61B8CDA5849257EF3B364D714D3D8121123E53C17612DAC8854ACE6EE3724FEA1ACA65ECD78144BF636D381B04A8569F08044D48010D4F9DC82332384FEC13FDF75A19B658CEE93BEB3FAE83AED20A67E5B5222D2622057268BBADB06C867BC9FC5DA9BE0BE1D5A80AC9254EA676DF534499DC9D316245AC914744DD8EF39BB7F87E75E4C50180DBF2AF70182DF9FA9FA6D68F8F01118F1D62A92F753272B9608B52222BBB4850D76AAE9F8BF3A34738B3B0C85AB34755CEA1A2F8DFE3E59EE3F48DF02FB26434A3C1E1B0C07E0F0DA24E810F0B4190AAB290CE081E7BB407642FC2A7C3A209D2C2AF367217EF57B39C19285020A6AF5BF367EA819E272B3C4988035FE23CAB7BDBA868C73C1673CFFD537222572B68303A2C71AFF1700B1C1054C38DAF29029D5B80D17C571F6B3A370A155851A44D3F1F0EBA7996589A25A011F706EBCA54408BA0858C32692912675F8982C6FCC5B46FBF56D036AB51D23C1F5DB1412E95E35F5B023F11F05BCB7D4A2339499BFF3C517BD0EBF28000C41FB6CF513973CB06A0434F2B1E7D488C752C3F0CF88EB139610E1C6ED7B19D808B78A1068851D182CCF706CFF29D07F1FD11D7DBDD0E5975CEF2B8797C12D8F229E16309355EEF3BB68C904605AB078B3B3C6A5230A79A01018ABC653991272EB69377ED306D0FB21079CC11558F4AFA644CC505B1EB93714C99D5D9F24E1ADD89C493F62D837E53E9C29D5874E7D2CC5ED570935C98F64B582813D09B9BBE0122A97F4A186E40E1D9E5871AE879E8898C4DBDFE8E7430F714FC9887D90C4FD25D7A45401E113C3697ECFBD72CBBD838D9F4C92A20529F5DFAB9A7E45815C1E6A786CCDC1060F54E00072F9CAF8746D54189ED53ABAE4583F1B12F5CF068DE12F91A5A18C3FFC2E34F4C93C92BC32D5744B9EE3176E3D096BAFB22D0F05DC7A2AB450B4FFA996FD34C52215AE4232461EBEA39EE8036995B3A8F79A6038380046A6F8C4DA731AD6D0ED8EF3EB18CE10E42295FF1429A362F5B487740F36DCDF5AE8147B1DFF375929810ADDC6DFC5EAD0653FD2F41A8B052EE356CFDFBD907FFF2F50FCA7C7FE315DD7421C45D7A5D44D059D8F043BE9023DEB6AD063BF7631A0BB268B718D10556562C0B7AE71FD7598B677B4AFC2CBDE1B3BB2FED29BC423CFB25FC50A6E2BCF7F72A69AFD44C7A7E6CE90EFE9869B9C3BC4842A8D5DD285B30E00ED00F9C04F8A319F56630A7588CFA05AC0215C90FE6304B0ACF5D9012D9414F7DB8355D62CD01421A0033F06BB82F3FFA5ABA7D461EF0486F9C712232D62D7D1261AD3DA6A050ED40DAFAB46F0D5625AEDEDDDAF365C1BD36E6C06086EBEE512ADF26FE51AE7ADEB2825C416332170BA8C98BBD0FD61103D03444B09F3574966F908CBBC685FD521D8A7FBEAEAFF70D3EB009335D8D6C36CADAE7C0BEBECED3CFF06F08F5EEB55AFD6428C1B09D3F87170A739E1EEFF3726F7C8FC5FE40E6F748691B71D9A025C7F2516DF9ADBCA126D0AE88F5D89311FB262413BB4822FFDEB00D36251D95E2B61CEFDC45DF8AA513FA1278D370FBC84E49317F71BFFF01B54C44BDFBB4041191D99A2C38A08E7BA7A7F1D28CF4FD60C64A8E7E9EE943EC4B59DD1DE214CF2E4F1E572DB03780C80BAC53CB78BE8ADF305EA2DD37CD298E09DF98DE9F214036642BDC622292A96673DFCC937904D98A7D5C22978825C0FF8AF8128A28738D555FA8D0CF28CF90DC9D876AA28AC055AE4E18F52F526A1EAB58E32C1D07BB62477BF3643FA0078DFE9FB1689B4B86E74CEA57B182E044B192695DA7D39097E74C8FCBAD5BCA84FAFF8B9E5D4C3FEE68BE456D906D3D6B33F8D623742BEAE927890717D06779AF30D64656F0416ACBFC36E0BA5479B92BFBCEDA0F502225FFB560FCE92A0633A201A020AE7BD2E6C8AB100D2A103CFFAD4653A35B1DE6AD2EAFEB887DB92BFCC1147A8CED56C31AED1043E3FFE28BD9E3A303FE54EB5D4E6F397050C45EF0CC3215E684C30DEC801E7951B2F430C578D65945FC920C76468682EE7A5A9ED7A94C86F1FFDE250F6BBF32EA7C6A164617BDB34B5F8F78A4BF863AEF2DDD54FB67796C99BA3A30C908B74E291A1E3999187CC5E848DCBD4237771CA92CAC386CDE11A6ECAC522140CBE2D2477A173D635CCEEED3F4E677BEA60F801D6B6D029542FEE50051351C54F9D17156F54AB3C20F97212A442CA6CCD0763BD052E84D8501CF1E29949F6A065DB8087B094DFCEE63E5D3474F413AEE22725DFFEEBB516A814C05C95D5E8A0C2437E83549E5B3C7E8B79F0A661DDA431355D1AF06012818D7FFEA732ED983EB519CFCA79913F4717875BC1147F0FABB622B5DD46C91AFE56A0D5A1A890B85963C1A5E69573C51F80BD3B2C533299ACE8A5741E8F463E939D8FF25BAC06F56EA9FA497E8B445BDE706071144EDF446654DDC813CFBD79DEF406D88F1EABC13AFC668939CA8EBB6857DC6507AD57598A20E37D3976065100BF691EDB2E07E4AF41DA2E71B811A69EE30C9CEB2D7193F90DF8D76CD844AFD1663A919FC8BB2A9A2F5004432BB292D355FFC94709B3D56A0D2B6851F50B82CCE36B0F9F5D0F9CE65AAFEC0226E6CD3C13CC175B23FDBDE4F2DC727A316DEEFC49C36CE5E121D68C9904F6F8F8A77B771D35AAC6C071B880A05A4D0BEDDF969F77EBC6BA7CC7CFE328CDD15978C5E19D14493439B1D26054C5546FBF726BFA5E7FCD0F79F936B392C32FD817AC69613C9113EFA1A6C4FBDF7C0208D5C3244C4C3634B30AA3D427CAABCBF6916E0C0B4D210798025CD079D99C7DF73D36F9DCD015D6EB42C97607897EC0F325D63ED27F6E8F6F54933885E12FE331C27383081E54F4EE37FCE9C80D45DBB240AF499212026E3820E8FDC918278BC28D8C5B5720C99FDD2E7AF558BC21E98B619EC466C6267CE57AFF3364BD96136B33CD1A786C58A15BB1BB8B59AE76536B1486E9094E1BBD9C02ECDA2163A091F089C68C9E322D58892F043F6AAAF40796A8A057B254C4B286DB85B19A310830DBEF3A9363F1F75CF216DB0E7D9BEB09CA3C34331BF46F6F7ED8DC5C492EA0A38CDD71F0BF308310DA8CC9BA54CE737B14E6920D559789AF7BB6F1D2D24C49F699CDA760E2D359A2025B6B5FE8DE7A3FAEE2B8D80049A37545A30DAD4ADEDCB75B0D2259ADF75D5FE6D8A25E79302C06DCD755B4C248071903C2DB57506DE14C2BD505FB8A22B1E7A89D4CB742B4EA08065B5A49AC1EBC9636979F2C3BD1975531549FA054D607403087637A299CCCBBB22868CAEB689B5A07BA9E4DB8CE0096FF94343D1A5F3D81E2F4BFCB21F52BA0E03F2ACEEE92329D8B86DB09907376E1BF0975896CB7D7C93F0871624BBE901DC44D21158525788012BC0914AF7CCBCD50DD5918323540899EB4CED6D9252F728F9AC7EB1F4BD1F7051A393E535C6398A4D2DE033B5E9DF0444C5B6CA7000000000000000000000000000A111520252A0700000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 15 iteration(s) +mlen = 32 +msg = 5901000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 0AE96FF29DB27475FB79C14C425C0EA4ED3A6F5ACA3E03341C0915072A3E0E42A286C52FC6EAE4942ACFD1702BF89091301E0148CE84E6FF37324C910E879F5462BF79B2B694F816FC7ADD718BCEAC778C5AEDE41DC8FED0B36E389B578F2C2A9CE275106A43CE324E1F8AB3D90E2B74962C5312E0DA28E7A2EABE551C7CDBF5570CE51B0A6375D485D60870E7D33CCAF6F38E83DDFAE219FA43C3A628F906092D52436831A2BFEBCC8CCC3D4C37AF51145B7426796AF475328E4F13AF5277A61C6439FB4ABD3E16E7926762AB654B43ECB35AD2B55D50124713F40B61D65286C1F6A22098688A54927A9C0809B4592FE84E6716B3FCB9E9578922A32552D0240CE23BC33EA207E7F0E454C4A1E8D04F1984412CC43FBD6190DA1D7B27BA81710FC9357312E6A378A190C233C7A318317A18F8572AF09790E9FC6533A75B8FCF50A98A2B4F812A6551DDBBB42B852515579D8F494180E88970D66249D6FCDD043D8D4A28F7DA88BEFCACEACA48D5995CA175446E683CCB819604C22DB1E64A00CAAA9922FB47AA4B593E9FF1CDDAC56460D4D10A7EDCC2F4EB55E656AC34360E59E2229F001E1B97359D6B34ACA5ABBE7E2F61A1544B55AED0AC5CD5EC8ECAC54AB2DD60D2D388F30A58821A2DDF783D406F5661539522B08B2B75ABF69B3846B812CDBE7F7F9703DEDEF8E44624DFAE277D73D0A48DBB204367E42B5745E6D1B39E341FEB9B277624D098C95074F9AEF2A0EC6D19E814D6293505E522FEB5FE8A307CED98C2AC121F2FB28766EBE91EEAE3ED492E42B1E6D96766CA36F088E6BE95A5C905239BC710BE4453FA4C6E4A94B813299935A72AEEB28E82E2A5F75418473B1C6DB746D9D5FB6FF8F3CF12AC89DD5D07981200A88DDB68D6B4163D33462641E6D864CFEA94E4C3F1005C72842786ADA132A5C208D78AA264178C27EB78FFD96C657822E87E644F04FB488B1475BA38E257D7502DB05B3AA6D2BD7CB3624F8871CA02365F72B21A700A09C5A2AC8768AA9C2EEA057A8B3044E57BC4522C54140FE3E56F1106F40372A4966FD7E2F49C0F50739C3DEB57E55496680DE407833B4572D0B8F2645C42C4E9E532EAF834751437D456BD8E7227F784E97024EEF48A3C28DE24BA3ABA2E3AE0AB9115D8BC42C8046B112973FB5235050393000BCC9E9E7F5A1908DA1E6D754BB6677E84B8B19AC59DF7C04896D5EFCEBA588CFCA5A47FF525F3E3A03F23E1FC2C568D13F6703FE6BE6D45DE6108A5A779A1588E5ADA196BF57E6A80F172CE2EFE45A4CD02341A63FF68F9A220F54E98C0456C48232AEF29B3CF7A0EE7476E53074DBE6F6D6B5CC6C7DB09281D8D18556ACF4389F980A4D3F31E7B68A6D185020D3FB3E7EDC1F6146537AC6B53E2EB051A993741BF7178B135DF37697A53DA4416FA3A532B70B07ACD25AA201D4D331FE2C99C8B909F537332167F16219D612E3B52C31391D88A1864C00F280933985E25EDBF1275F1640C4C96D1A207DC9838DC2A79BB758E0492CFD82266D33A8010C9B7969A9C2CDD11AFCC76806C8B313991371CA7628F4F6125AA8D6F93E54508EDC4563ED98D95FE5599CAE63E07CDFDB3296B702C6565719380C974191CD8AA3809FF70FA6A9549115C9F636F7CC013861290BEB1ACF259EF43D48E51D210EF9A15F01AA156C68B9426981657B40A9BCB1E24C59E0739852B9661372A93DCD5E15FF5DAB707451DA37B19A815A1C1E42E649A785941FADA03FD49FE4350C52C0BCCD5A3F37C9AD996B0D1E46F84E3C52A3CBDD034187BBCBA24605AED2ADDF7A386CAD0041E20D8332704B00FB4D7F7B5E41B51D22849B347479DE81C1FFA4B60E550039D8CCC48C71DD700AFC79A8A2DB036A025001F14A29E8C1F6C262E766C9E60BD1DEF02BDF7FFAC598D0BDFB7404FC80C0937D0CD390BB1CBA5DBEA4AD5917948ECE345ABA23475DAB8DA835E921885EE1CFFBED132E3F8122429443DF96BCF07B0AF8D1D6268BC2D33AD91C873AA81FE95F10D76B7391B996F5A589483FFAEC7DEB9EE75DC674ACBA960E0A173686D7C8ADE2CC8A3758C86DB5406880D43E03A5FF2F32A304553877AEC6AAFD3DDE8AD73E9221937C74785479267512802429AACAEF9AF27602DE45D973D6CFF72CF3C17305FA4DC896520CAA84B91D644E0B50D1E92F909EC9FEC83D5FAB3B82814C3DC8EF17B122CD2AB487B07E926EA2A17A399E107C44414DB3F61B7B81E9AB51FCD6DEAF4BDE305B678AC30EDC62101C57AA347FF1E7787F40698C85AEC1A8B8572798EC99D434E0670C4613DBE89C5E63DBC8A4A780A063ED1EACB7C3BB967938BBB9CCBDCC0C22D6D77B12F6D1DB4B511EAE4EE5B1412160CAB2148CE81D2877D71D37EE9A32A12B866A9CE34E6B2693C126F96857AE921F6A4070230A1435ED8047AFEF81B82C0F99AC25E7C9585A3B5984BF1902C27AEE5F7CEB3DCA49FF573D87AA3EE9E0104E9409C8323E035C3D518BAB3D92BEEEF73A36D5D7DD5A2947B361859A0734766754A5CAA3247F75F56C123D60AB6A8552C2600FC5C38A841392AB5CCB833227FD0027162A9B3DC819BAF21C4DEB72C30E2A5432164A5084585257F404A786DE69FA63E73CD1FA34C5C5A643E7751C8D641F46BE9E9380672B88598BBCBACC68CD1B34B2AC484C76D6663ED17ABDF56E8FD8E3A6D66A5E795C4D622B5EE22B9142150A42217E89F2636A8FA8030E797341BB453CDB400EDCDA2D76DE0FCFDFDFD3C621AF0F848013BD24D9165D0B16FD0FEF369696CD617B8A971F4DB1CA9E8DE7D4AF39212124C592DDFFAE21419B427AA3B8AC121011E93C37B603A1644A2853B1CC96DDB8950B7FC3DCD38E2500A9E44D7F9C5AF0628258F0E4FEF27645F5781A99CBE4CB15D27E1BA9B18C0DABE7FC00B61129DCC1EF9CED8E9284FEC24800C2F4428E43CBEBF84B6B5C9573FCDA463DFA81490370A9D6F3DA6756A0553F3C23B2BEDA638FB570BFFD75C38F0A0567A71F290C818540CA440184C6254DBB5E26F1D31A82A4426179AC7C50168C2A64FB380FF31E3352D1DBB888D4DA49880E55C53FE2E13731A6E69C281938779F3E85D7E2C481C24AE181A571267A4E6F756BEBAFAD1F8CF77350A6B27B538F6E7C501D0C69B3BD00119EE8FAC8581AE95241CB518446C1C525CF09D55B7C5370F09BB3BBD672192DA98234EB96F66489C64427B6B16CE282001C3945CB77ECE4A0404E2F769542D30B60DA603A44E8107A821FAEBD42374EC1A7A4A956D7CE236F11AB39F849599A1B91C307D2CE38905E1632917E0B128E289823F55A750ABA510EE2E9D53E6FEE309B27B4FD9456C14413E84CEEED549A408955D82C97D0A706DDEF7A4413E8D4C83E2CDA09E92EF48AEFE31904A9A223303C40F8B81AA59C32539F082AED85AFB7D54365979BD78A3EA69BD79334270FE0960377114BD0F7F9AF961C32B256878DDC6CA11BAA6CF2248290C85E3ECE829B6E95C584090B4B77DE2135AC7507B97B7EDE41DB85C6C102046D353EDAE7F11CDEAD09413292DD8D68674BC21500FC704234EF36850220FA8944BA6AB04DB5CAEC44ED0DF6194160F4F7FC681206A2F4A83F2647CDE571B7B2F71BC870800E80E5BB9EEB60177337D86FE0D6D50CA53F42BBC72D327451129508482E5A3B004960CAED4B37CC2BC04A81173D164614780936C28FED286A68A9D6CD71720C55F8C7ABBB13451F052EEB535AB9D155393DADB2E595F292978D14D126110010E6F7399259E54ED999ED8FE47109AD43D6905F0A3FE025D12EFAE1BE7F812F09C0C61BB3031C0246971606BB4C3B230B8280B402E7DCDD7A57CA13F63A93CB621863207688841001CDBB5D1FB59C836E08C332577B906FE2933588052BA9D0AE97362DE13F0ED1A508F98E20BA58DE8E35F125819E4B75018C6DEE49933932D8268AC2FED69B48A6FF22C4E841D3456E5476B1D834C2458034BBBCE869195A5A8B046C8E80160EADB70B82655F7EE48F12F82AD8CD42625FE1C162B3FD5EAB61ED00CCFA6CE908350F53AF8A8A5842B1BAABAA4FDFC7DC0D2DFCDC06B2BD3FB786C96667947B3837EB064DB0477C16BA63012D28B479D6B11F49704A39DF7B992B41EEBE13E2F7EB5B021DF2BE37C2467C901325A33256EFF193A89171B7B50C30E3081916689E0C95761A5EA1CECB5990ADBF00934150CE12DD7F15FFA23C904B28CC8BD2441B2928716538DFDC9DA600ECB962213E4CDA73988E22B30D34A94003F3778792159246E206B2FA02989D4632B4D2E251ACDBA79F741635165CC0E9A589D6A263345F5ED3608AA5F235755774820E37175F03356A1641C73FB59F9EB34E169420A53EDD8C7265F618AD42A1BFDAC5BBC367AE366D3A765E39E5E426B688C68D649A82898130D462809550748D140F77177460962E76AB257BF605EA3E1CC34D3C77C78F416457F34998AC0693BD45033AFA5E77E26C148BCE33C2634238410A25C99CBBC47C0F0C892626F9EEA3AF77CFDD6BC410976C4EB02DE3681A5A2F84C0B9430BC6F75A8C1387520AFE25F0305D1715882F07029EBD05119DF7BF01821FF73D422B04B8E833E16672C6A707BE7F5FF1A535F647A858FEDF84A4B88AFB1BB2E36434D738EB8BD1D7B8C9956A0B70000000000000000000000000000000000000710161E22255901000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 16 iteration(s) +mlen = 32 +msg = BC00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = F56C83A96B8A6EC436284C14CFF08FB09B6F95428C11DE44BD37BFDFB07274ABFFAA07CCA07C2DFDAD0AF4A255E0288F84FE3E570CC5D50866F65B5734D32A9A64F67378CD9F68834DCA02D0CA6AD618412AE1DE64BB73E485A26A410535F37C11C29BC6EC709C7A0CD9F4DB11705FE354C9E9C599894FE465EC19CFA6A648D200AE8B4AEB44E599607AE8CC5357687AA5AA4E16A1BE0D3FFA9D8183F37E7057664E1A4AF44BD95684A270376B045D659EC580447A712D7FA9F341CC5083A5723786F53B3BEE31ED1340C70C56C6A0E4BA62B78ED2D138CB5F1BBF788A378742040CF1054148C77549D2411AB91C443BBABD71BF18A3682B91BF94FE16978A01139486A1AC69F8D5715E6BFECA102DA3089477D4A7FF66E2A9E6C6D63EC5D2CF6D456C355FF6EB8D2CB8FA711401F2A977FE507A53A835A5B41C555943AF8402532F214A84FEB45DF54FCC9941E85D7AF3202F98258F55D85A6A2D0C3C3E9204C4E58A590AB3D7D10DF85714B4B51ECC0EB462F0534F9C8851FD9FE01C5658A9B4456E377EE6AA65695A055AADEF8A34AD67A3220D80815E9506846D00A74FA406FC0EE4E0066D9867C108A65C4E78AA52440B6D2229467F3A1DCD3327ACCD6ED34FB3284B3535B10514D6634A7B56350E1F0E7A5A99FB67223D5582456566E1FA843BC48A290EE82EF40F40681DA92F2FAAB8BDB56B3A0F3B2D4263384C7B42672EE60A41A70AF454EF462E05B6DECE1B461184934ED7ED061DD8B624A57F266B4BD15CD50F0792C1A5511AA1FCA0E25DB6C85F67EB6D54D6D32517136ABD776EC7CAB1393AF5C3BA071B2E8EB0F00F8793565122212587D2C3A3E881D8EACD3C3C5575448128402AEAD38E9F4203ABC7C35139E88A7CC0B99D85CFDC542AF4A6187FEDA485AFCE7600BC7E36D0BB9EF1F177E13AE25CC303B9245AD9C17E24D17B7201E38B94EF42730F04F583C6B26A8DBAE3A2CC35C77E0F0FD93EF33C2C26AB83F9C87EBABD79DA5F622053599F6865C94B0629A1D4865301B680890437A084F970997628A74F85683D0169111620DAE9CE55B9869905ADAB7C12683B31884DD9C3E2CEB085462496164CD61B09673D0238CE57E039D8B049C5A6F8FB11125AA9BB2FAACFF9A48437E50C5FC263EF43C1FE418A39A5E70AA23D1592E26A0CFC355A8550DCEDE2690F6AC4743CBAD17860BB13B2555A7F5661FDB02795ACD5DDB66A02D9D08973E1571F4D1EAFCEC5089C3232CCCADEED7AC4B354994C7D6CFA847E535F081BB2B8B72EAE05484DB1420466A2D729A020BA0DE466C035670611304373BF03A34C98FDEFB3BBDDF878F5409BFB657FC1FCD2487B17E24C1A73A55E029263221BEF495E94EF52E81F5E4F07DA04996C7B9DF0FCED48E70C302BC25AE322C71EA12C7FCE267D52E90D3C70E41473099BBFB49D88C9E16156FC01E231AC82CACAC30BD6C5C452B8DADA6B4FDD3821A5961C0DAF8F373A125892069539DBB289BB26D6C255F5A72AA36088DA358922BE9BA030D367ED89601BAC858A16829D8DF676390F0B62C50BE1DD189825454D1EF43E7BD29F646665877850411DA7C5C317DE8CE72E0A2B0AE6168C63FD33DBEF65C21F0DAE2B6724A52DD24B9958F0A4E8617FF5A7BA75952B360EFFC280ACE26415211D215B6A6259DC66523A11DCE0141696FE01DDB34CAA4FB336F9A25E0F528EB00EAF20D6CBC11D7F6AEA7D9C666F3DB8F1962BC20D11DD6344BD26C98621B47D129039AA6114AE2E91919F9C01DCC70E79ED1F37ACFFA067EB3637317239A09A08D9E517C5F2CC7C20F9C060622144A1BE49AFAB8CFF13CE7AABC17FBE73E58A15EBBE63A094F052DF71358F4AA217363842955D7E8B603E3CAE644A52ABA5FF069BD3395336049BDCB0B47E6D742C7C74861BA372D3CF071316B381032CAA26F7ED20670761E63587EE9B873110B6A8F88DA8BE924103BBDDFEC35A685AD91A93EB3AECD202AF975DF233CD8A00C419A3B6D7B3FEDA4EBAAB112417118B7B4A8D587C78830CF3C4BB3FB575B48FAFCBF45A919DFB4D4AFC55D8460FA276FCF5D13ACB5411372018CD363898D7C57208F5D511E00295B8D45D053FA3D196DE14C101AB072027D8B713EA59CDD6280AFFC59A98024A3C65586EBCF11AC9BF11D543C0905CEE0F34BF1D28A04049AEA9373AF12DA85627CA230DB9242BEB057C33281103E8D4C4130766312284E87626A2C502409D4009BC24E31E5C04C840363632F914EFDF1E137269981D87BBE007FC3E7BB501FA6707CE784CEBB58AE0BCCD57EB0040B066E4229B2B4CD3A5BC6A3B8FC21F18CBBAAD51DB1A949E4859CB581418CBC4C4C9AA91B3A4EEF7A87FE92464F066395DEDE537ECFAB55F846ED9F858870E913D543A6F01DDBE4874A89BF05FF1C1278419DD98AE0DE4A0647165AEB1EEBB06CA7E54BA6B1EA8048A080E4976549BBBD6F543350FFBF2F2D33ED9FBC9918FC30A0CC60EE12552930A2096FA8748DB1D55114FF8342E36DACF794FCD34063D0DEB54A9845474045DDFC20E65DCE65DDDDB7DCC1F6F03AB11B87E4B60404EEFAE8412C464223D4F271277E8D54330C056A88B338E7B36CBD8EDA0482C4247B6D2D5B45CB8DF73751E4A4B116EB8DB46A99F9197CD8C64638731F5CEDFF83C197CE3F0FEBFA5C9E074007010A5ACA4488E2FC835D3548FF082914A34E4A2362A7FDEA03349C720D49D40A6BDC9D583128DF97A4B445B07D6E00EA75CD0F97E763B35BCB30D8E15A4A45CCA248847CFFE4F269DD54E7105AF70F6CB32DC60E21C8DDD20A5E7C1E3DAF6A2A2B5B71985AD74CAD6BB68F38481248DD433AE360DE8CD6347FA43D965954730BAC0C51AA87D4BA1D40FE55C0B93C0502DCB99AD707D45B0D0112CEA70B675B8ABA2173BDE78BAF48585BAA7787C67D5EF45612C873E785577404C585D1CBEE8421D6C47A743E82865674815C1E541EB4DDF021F875FA87BFE12CA61AB4F03F31AAF32993C9E02C51E910C668F9C5199701269A1D97877546F9534D58E037D444223AF8631EBBBDAEE7783ABEB30EA0E1F1AAA820B440462E02685CF61B1176DEB8F22EC17F805A2F5D72DA968BD697DA1AD56B65F2D2AAE0D6BDEDD231E9D645101154CC797260BC88142A760933163EEF09E5B5555449B8303493571E553F8F9299D235EBD8566F17F6C77C7A9F122A1A918F9361F47462816E29C66CF888D8E48292370AE1167D077435E9B21843DDBEAB0F4FC57326408C382D7D83A8B6760F2A6CAFB05BF6A8BDC0EA1B1DF470C8E6C66AC3482D6180E00FF65738928E461BA88B836C3AE5BD8EC84507AFB1B9BC7FDCC703E833C203D2D7BD3579C2F5C1619C36E93BAF0AFBCBEE2DCB94EE5DE10ADDAD0935F22C41DE878A9205BB61E23CFF1D88CB9E1A84B731E0EF55144784380FA6A5A5E7B956827959EF5C26542807B2E4B906343B47F3B6F1CD63E81553239E18EE5FD2595170C529EDE26D34B4B2E73A3FED14C4675C26F4BEAC5B312385A38742AD3BA96F5E55356586BA397A7BF719FBB28E8019FE0D4BA91EC1CA7B5D2B9677F9D95A785C034F284783EA1C52CB195D53490D655585E792FF4ED31895767B0289423DD5897F5276E595CE9B5D9FBA87A633D6B51FC7EE604D2738D390C22BDADEBC43C28C7DC8521C05FA49CFDEAD53A32E1F9B941E17512D95D22EDFC7ACA816F222ECF8D29DA55628B1542F4CA7F8CF0A0582C172C2EE62597BDF36F590B68FD1EB4F5E565A1756788A54B43FDC67F78426FD7BEE3414620AA8BE0B1BDE563E2F176173CE62F7916973BA949DBE29CC2F88D1FB30CB545E21AECD96EE7F66E69188292F6C31846B775634DCE449FB96DF1A066A1EA83DFCA60D837B20B389AABF2A0D994D626630CA861122A85A9476FDD50D736CA657ADB0BA60A21325E97D185337BE6D7E85E98A2CD20E1DD7F8A909251724C6F18CE8D437DC0B3764C6052DB81D0AC49AEDDC37BA627EFADC260C2CF6FAF796B57ADF3C7EFC2DF9C09E7818E4FA69B27CE38AE8D954A04CC528017EB184018ADCA03BD956C3F509715467670E842EF6B2EE8899D6DB2AFAE79CCC8A5EFA14D88BBACA7B9DFAF4B7836E7FE8C06F5A5A6532678E0EEA2EFE4AE5807B51770ACBC09EBD48179F5DD48D4D19D1EDB4BE201E416532E8267B73C5CC28041DF981FD6AD43B22882567B742C8F0F47B935C0A8F45CF3252A4CA2DE4D466F78355D052894783B1C30A454FD3789074866268C1E281043A727438E8F1776CBFB61FF9B59EA1280483BB018EF58B58DB7C6EDCA4268573ADAFFCFE35F1634C997BDAEFBFCDD8A3D61F2A2B88F771E5FD865AFECBE43305A66E801A16200C3FDBC003F6DB0B864C6097918BB70F7E4D9A10050B79105A88886F63C1BDAFE1ED99A112B48B931D1F006D0C6192A5F6DE1051DA3EFCE2AB68614F437A4737C3D422AC6785C58BB2E19ADD4DE22E0C97CC39E580053E312CF1D6AAD53B4AEE11B928CA79B6015A397FDA8C44C22FEEF97AFBD5B4FB3F31EF9C92EB1C52B0BD77E1F5F17C944FC0624490097D0F842C7F96D7529604303A432617C7E1BA9771A2AFF3C1DAFC64C7CC9092A5892A5B1E6F8036299C1C8D1F01C2A2F4B6FA3B0EE265184858CA7B0C7DAF6155DD800000000000000000000000000000000030B121A2427BC00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 17 iteration(s) +mlen = 32 +msg = 1000000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = AF93C0F7A8FDDCC796B60F67B473A00A34E99978489FDBB9988F9007954A44C7007D0ED719C29A9D81353F3E44B8C7E549CCBE338424C443E538C7B5CE544267F657803FA59637EFD266055C8BAD73D233ED5CFDC8F412FA1A046CD1F677D12AEF276A68CDAB8A2588FAA74852A54BAC330B1F7A4365498522013BEEBA215D4C783D181AD15984F7D0030FF757B8C0A50A7C1851A55CB4DDFDD69E0382C00508A727AADB019A9520E9EBB88E0995D76411C2518A930226048FEE6B01DBD420C463A5334E164E41ACE2542FC7640BDB200991344DAEF326D620C8CCDB8277173DFAB2D7254BCB4A5546A0DF28CDC4291755FD564245A8BE0C23E7EF8C7674FBB3A6C81569E39D412F58BA8564291EE7C655328CB6449F38672011CC88B848F3A108CD33B92709EFFE3DC0801CA685ABEC737F74DCD13082E2EAB3F9BCAB9F8EE3B8B0725B42D78D01C547005819A63B9C7C24A252E6CE020904A45D1611641C744ACE8C8BAAE5D2FBC33F586E89FE6F2FF01AA8737A5D41F79D967AD06220204C63F620BFC9FA0E1B881181F60CA9B291EEA0C765B549E5F7CED9FD7EAD3A9A127E73F7A361EE26613B12F678F61A336CB5965AABD48FC60801928667764B0E832B0D087D424CA3105552A8D46DA5E43DEC762B65F78B6AFDE136F30F807D355218E22E03516BBC681605BA55FBDED8971A0A5F4D6C4D44D63B854A5CC21FE0110AE313FA9894D6F57F646B01A83E1A7EE41DF6BB63BF72BCA424F9449F6B260428AC001AAC7B7B97D3645E38443626FC4831D235DA29966EDDB8E2E30F1415A1712097B7DC669D3CAC46EF333674D85211E9A94D825FB49E7B8AE54EECB9FCAEBAB8EDFE66B2433FCAB5D4B9DDEC943F3416DC47463C32EF40E9F7A68FF2415B6BC936C3C4CC83EBE5AFCCDB2AF55CFE47EF5614B67DEDEB13E57C846A3CC6852879B370CF8BF5E1F7346751C337A751BE6C83E1865345CA8DF92E516686D997022641AE6585F25DC807244A04F881E5B3274C8C7A70707D7FB5C5BF1D1096038D76CA31C35B451347EAE7A5B2BD376B77A3C63876A7841A398E506963454DA61DCF27BBCFB378EE04CC9507AFF13BE16DB5ED64FFD3E1F23F5C6B06B519A3FAA7F1260E205E9B1ED7C8F5B755DAA51B8478E8F92E86F031BE253EC3A20C36AE8C4A5202CAADBF21AA3F465206CFFE2CD6B380EA9E35DE58A95F6490B71BA32E04D69A2C536F297EF1C7BDD44F0BDB961A3723A1A7E96255E6876F922FCC955376CA117418D54158433AF5298352BB23B84DD3148C880E5C23EA49716F2623BBFC33F86A35CDC16C6F73E900EF2AD5BDE1F8EDB0ECBD712CE18086992A98AB2599AC44A51547FC0FF29EE444161E1620A7E2B529C38378340EB9377714CF1C5D8E73DCD81DEDC847533316C07600523FB3DDB021757E46C0C2239CF13AE3011EBDA4EEA6A97B6686A07239DD556CC78EE20F9D65BB30BF67141BACA8DFF02DE6E7563966C13B954B5B73FC9A0FFA8F1C46207BA024B64AF5AD45A4F706DD3DC42EB7EE9D73ACB5FA6BBB0820471AE23830A0AB3DC0E1D8B3125282A790D366D6823D9A5E05B7B2F5BA5D0B6EB3DA3150CB72A33B4BFD157B4D567CE44D43DDED029B4B43EE2DE531F5A7ABF86E2D9ECC4A3BDF4F274E0A8A055B26730E74B8DE1138ADE92D7FCE4BBE21A3AF06490059F3F0716369AB12E2DD6F25EE5B73A75D2C31AFB0A5F8D7792A4027731475909C755CE7232812B981A9FE347D3686059C6CBFAD3DFF337C1FFBB18435A36E0AF9431FEC93BEE8CF3503C0D86549A2E8F53B6CA6A0EF9A8D815D53667873BBF0AB80DBF8CF8AED5D3D6743B8EC867C08A6B9DCF32E6BB398AC8C4659646C88ED4E44141A8A15369A8C9265B8E0C1CC0A340EE30ECF4AF0D5A44EA6935B08D132FDC33E21DAFFEBC19F4D8DF0EE0CFF37EA4336A9D74E41AC59EA998ED84F1173D2B9F1F5D925F2870E6CF674CF5DDE76C0847AA4606130F04A265F2A10F260AE932C6887F148A622B158DDC2DE6C53132FB13741A2D91FCF6D8850C9215524632F6D2343AF02B41EADA24D3E8C5D29260ED4D16DBC48942EDCBD34BB9B077627A9C143CD6EE2DC383D7B8222A7B7C91C7609E076E9D59111095BA654273166AB6FA705028167CA5DE6E2E71861D3C6E9DF0770FA686F732DFD932B13C19B13C94B19A98BAD4CEDDA7C62538CE80269B21F852607BC4E98117AA23D544673563E75B6C719883EE844014E1E95C62D55C0C7CAC26B64038ED78DA5D953DADB17F51B5E93D513C79D2734F61270E8F9EFDB68B77A8C32636CB6556F7BD6A1823E80BAFDCFC155D13C7DF59DA43A36F172DDB748A0DA0316F9A545523F325DC69A42972AFA1C5FDB7F5381D8C965210149C6FFB333D21085FE711D8F7FA2A89BB26E10391FA30931E95DB7E3D594E97551C4D8D39CEF7598FE8A81A5D9FADA9483588E137A314BBB9E95118DC3BA4C0EF42FB4615FF6302A0D36D54225AFA09D810691962E61A11703F8469624AFC54079E03003441949672FB86EE1CF3F792674F38D73B905AA37FC4902CB21D2E6F9D4BFD70D0BBA049FA75DAC673CC489EEAB5F8F14DC948CFC9F2240CA4754A9592CB01188D19551F22742A961DED4F75516EB6F40519BC7ACF9AF731C435A417DDD8B0E0556220382E0277D27B71885A2D717C479F8B5AFDEE48BBEA908C4BEF0C28F1B49B97CD48B67583BA769EDDDE8367D9B674829253AE61EE24FFB20152E42C58D0ABC0DEA43518776701D9FA82C2B08985949DCABB80515E6064D0E5D914B8710905827A94729467201A4C8C1E4EFA72EC531B730BDDC188E8424290530BE45F5DB0FB1A63A0DB4AF22EA3609C9D06DDF5253BC2065C2DCC5FEA4657C8D0165113B16C186C25ADFA47CF7B363D9B9437B7F7BA32D33F8D45706B4051C39FD0C18675E340202FAA9D6E0CB94B6C29D88D187709C39C65BC2A78DBDB1D21B7371F8ED0FD134E826CAC83C80E9EC08FBD0E2B8FAE270E948BAA82E65A2D3A6D96E0F36E9CE1FE36AF1D358FDADB0CCF3ECC3303F05EF51E9A6EC6437A13C1285AAEAD9FC8FB2A17FA8DB08AE17090C06EA9ED4A392F01E5AE8CF06C76FFCA51B9D9CB2ADB9D98AC920A325B5DBD8A6C2F9CE33DA8C2A08AA304B2457CCCC71D39A7D7C6945180F221429672587DFCD2E1474CD860443CF669FBCFAAD471A2EDA300B662184A150941D0E126F8054470E927D353BAA3CCCC3CD255081A52648199E73D0D86D0054707859464C2A249913D01A1ED17026FCA43FDA575B3597B0770A6E931C8D4343131276D1AC598D2816A5E492DA8C8EF5BF88BB6941898A223E3C274F9729D7109A3917F63115834E4C3ACCAE2044CEFE2D8810B41FDA638F2904D55C4B42B280F5717600E282699C1860BFB7B6427ABEEED8A261D1F6A1F1EC969EBEE1D2A0236A6D9219DB4F14D4342A1720C53FDE54202FADCB8F44978E526650BC4C858BA7EC06DAA021990F659D971C8529A8E8138024A1A54BA4BF5DE975EDA5FE450F72D3E5A10281CD582149E56136076C2342D64D5418BDAA21981FAA2D5E79570E4D9B40D67F987C1EEF79CE7C43CF7ED1B5F9B7302EACDBB644D1610459524E0092942EDCFB2D89DEC927D15589998C8DC051EC4ADA88A39E40020A9AEAA89035CCA9A2E12BEBFB0A7911B163309374EA53B363715A09051EC6D372CA111CBB1C4B9C303BF267C8CDC503A7A2065DD21AD33862627598EC7C8B036ABCEF446832203A4091E299C47E148CEB0425EAD34CA79980C994B96E8FA9A74EB00A3A95A7BC2CF82AAD377820F608EDDA04D608442CA44BEF07622C67BB6F18ED4461A5629A91951DACC068B1406DB22C2185B855FFA9DBA1CAEDD0EF747CB2101CE27D86CD6012969875355E292CAEF22B22BFBFD36B7E1731E5D1884939245CFC30583E7D6C1A9F97D6152F4F634FAA69A9FA355C3E0287152ED7711B89D832875BC216C98DC140C5389453C4B7AD3796FECE24535CD3010DA842D0A57DBD35F8BFA26DC268B9303CC64A257DB4CA8A999DE7E2A7CE25DD94635A95DE6985CB2368A8D0488D8CAF976AFAAB06D76512C2EAE9F8F7F7227C3688314B13D123C32257918FA39F13079007F10981F118622E1654A5771EA7B98939E03065C1C74C2736D373D55BBD61F2738B17A12E6D48918C515E64B52B729C4E25DB55A4A1D8549AAABA3818174486E9BB5057C02BF5900CF3B3526C2A2A96DD9D4F9AC35C08A33060CD7A57F6CD8AACC2E30A58D6FDF8546F730FA3AE4A0297CF41A4A8B4B3C0F768F861FD7D1DD7A836AD5B102A4A433001E71C6D36F046926FA2557126AA478E605D9C66C020A4322ABFE9CC1FED99551C12576275F8033D4C8850CADC9EAAA2229DAC35C363EE21600C90DDD7CFBF171F333C3F0F4A3D0E7FDA4523A9950DFD758619159C38AFDCE35E21065EE587747D21311B90E0766DF0D94527C07CC187B439C8B38D5979C8AAA87714EB31AB0B0A37E860E5D7C87B22A209ECED96A08F8C4C6D10ACAA1E3FFD3E805546F42851114A950199B5E2A1ED7FB5036A0D670ABC0D211B276236ED948FC3C747212E424F858B91BEBFF5363C64747B9BB60A2240586AD1D311A9B1BFF45167B6BABFC0CFE44BAE00000000000000000000000000000000000910171C24261000000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 18 iteration(s) +mlen = 32 +msg = 7200000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 89E3FCCCB519E7A1C60E5F252131C30DD25D9A20B32CF6B2F0E281E2D5B6B99044F77DE936046D11D13D89670F1578491A329A7C9CEDB7611ADD5DC3FBB4DF1B491E33ED7C40B851275F296D77F2C1A8A64E98353B95C332FE2AEFE674AE9288C8334822FB6C42A58465F1EA2989ED51E462123188B529ADDEDAF07B5F45236B86E0643CD3295A5391D085FCDD49ED6A1172ACC80FBB094C5B492B61AB1B3DBFA0E095394A5A3831E267FF606BA17950BEE38192C02C7E56FFEBB85C4AAEA630893B41938CF9640FC150ECCFF4E487311B3AC97A9CBC51121BD3EED73365052E38BF47192F9EC21219430895EE224D467EF2EC36CBED2E3056BCEF987130CD5C3C7D8C66A7B06E635D81E482C8EA1C7CAE12BADBD6BD1E9617B04DE30A76353F30EBC2683F9DD64FE9981F1E8D25B5AAA294C93A1EB5AFAFB477717ABDC9677F1B4190EE2CE8F1A9815CA23F799EE73A1DCB32682CAFE18375832FF1D02A1AF90124A3CD307FD712E6184D2ADF2BCB6A55607C56EEDAD38390B0DE19B65589D765EC43A8B9A0830A825D26FBDF22B70A11586A301DB6B94CF45CB3264B6E370AA6B346E0AE0D0DB54CAE4CBA079456732106789D879284E1F0DDEBDB7896F70F23B25F984FF2F0415A96CB7422FAFB88767A28886FF8096F15E8761541A17986CB47938CCDED129A6B30509BC3B6161F8E0C3783024CA65C4FE4179C0D4B701C6ABDE8A27423D3BDB5EEB6B693AE5D357F5740E3051A3697CC56E18501D1944FBB36E728A1C6A25CD7A6C463B9CA935691871F3733FC2E9841BBF6900C24A08E09FD28D43FEAD0A5AD656B2279895231B3F7A760C976F34D05E9FBEA5E34C8D5477126DBB5FED21B5F30C415772DD2051149C3F68FC8FD8D1952127C74B3F394F57E323353B4BA41817A3B98A9C862D09BD709C1A58E97B4DACAF6AC977DDCAFC5E9AE8142D63429078DEE03B61A096C9539F7217144179286F61B18C6B4462D592CC40922D5B4D645F2967B5259B6629741B521DEC58394435C37CDCBA169D92BEF5DA32BC4E910E907B65961BF07BA3A0E99B699A0D051FA5FA961EE605F2F67C4AC5EB8A794215DF11E666D89AA1E91C1088D7C80CC516045B793A0E516E8C55F0B08B8D85DB1F2C7651333B9C9AE00AAE0F2EF406CC55472A20DE3C0BD0D53651D54C4609B4997E6C20F8BF7CAB11D1875362F84697438C09059D9C690B998DEC9797A2BCD730110B52A3618B911C535D3E75608825E3E51FBF0ECC49A4565D506C4AC0CA40699081F4CF7E9641B811B7E9DB7B99E07479067B82A421F114BD72B87B48A362EAF90FA33D0B064E5351811E722DCD6044AB2153435B373A3891E05C15A74D8350E215155E9481E4E3E187E6F7EE87BB43C34668A27A044AFE988A2486CA1299AAF0811F7A7638F9DEBD17B77B6A7062794F6FAC860C319E5C3127890BA6A9A783F01F81D1AA757FDDDCF9D2307B8F2D9A0540AF771D00F6DCC36FD7279A0BA94C280F4BEA00D43B181EE7674CD09A5C2E0A369BCD7F7166AE1F9BD0E92C3265E62C72308C9C358157B0C7A2B4B9C62927648799293265CF1981A67B8D46148BC5E619C0EADD3675C83753B3294865654FF0A7236773436E0C271DCE2C35C61CC8DB3A97683E14C2D5CEE1FE08635252A16F3AA80D9F7E80CFB535C79FBA5B52153E96C884A0D085BC02C31FDEDD1B70CE9E4312E7AB12893F55EC3BA29EBF4D8923FE5396E7DAAA5A9B2F310180390771D36D85B733BEBB56D03DF990AC69F7D371FD5BEF121811A166C1E0BF4710768B004EA019FA8A52C970C492006137C864AE8ECF9E1A1BBB97E513146D4D21A58E0E739AD75AF2167739E92912C59790E3F296236548BD13C05436695D3C1911A523AB833F4F28BCAFE633E8567327F3112F664F3F63209E55F3EE488AF6D7D281FBF15FA73D2BEBD0124A71309B41D47BEE8920F498B961A7702971AFDF90E37D5C46F46D02F5DEDD54638F5B169358F1AC9E58A5EE745CE6C342C33C76E3288DAE0FB5B4C9FEC740B3B141E492388F7E3F274767A8AFB4794646858ABFE976597906AA8B4B958F118EEAAFF7D94C2950156456984D8F4FEE7CB60EBB41550150E1B3B9519FEFA00CFB20FC66BC44F87C9CDD018363DB42FA9EF81A7679D37CC1DE7480B3F6F78B92B5A09A1314BB0D90C8DFC8302ABBFAEB9008F604A1FFC600514C5C676E414A9B2BDF07769DCBA9C34F37F1E7EB3E0A5AAB946C633BD46877BB84B4D742617E72AA90D89F58D1E4DF6C4C550E4EC5C99F7B0E093DF5EA492B3AF72B6A7A41042B9CE896C8122F6E35D1E8C6F0F52150891B43C19CEA1BC255118C824BD1760FE9D9D5FDDC70146592547BD87EB077B4E8E81AFDE392D885DE9B73A5BB02E7B7C68581C02B1B5E38B68443536DE2F77B694E7E74B933A9CD8B76D8DFDDCCADEA4410A2B94C26F8E948E92A7BF5469E75D426F1F6F85B1D6CE46E8820CF0649A26B1AE5C4A7423D304BB2C2ECE2C84AA805203427DF2F0FC0057EA5C702A6BD67B187E131017FFFB93D5782A7E11625F6B8A41D3B53F3AC1ED2598423A5AC0F084D6BBD92A41F6BD2DD4764E4B865371F240E9BDA5D68C3BE3F224D9236C3ADA888105CE0B053F604A48AFE7A02927BC6B67B2F79E5F73B4521235C395754BDEB691BFC1DF3740F1201AF277047A5907ADF4EB26BFB55CCF75BBBFC81C58CA59B5A2D2A53DAB03341898AE908F64A237FBBEEFB126882EC3974C1E9F97880AFADC572A60D0A568C78254075C7CC7B1782C41856EDFDC27D45F8B30FC47D9E68523C62F8D3558AE0EE252F5F12F9D8D607E584D8B9111C6F7F812A42667ED21B56F0228E4A28EFAC770D015E88CBF8B9D9EA380867E61902E6CAFFF7EAD38AE60BA104F83BA6ED775589A7F782B2BF3A44C5321F217B030FB716094DC39E0D7626FCDF24EBF6C53284DBF54C97E8A4F305210FB142FF9EAC36EE75E9577A989836954662645B0B06D05E2AF26F209C67149D3A8CB4B87A040991BB619F9459E3F6A809CBF8C3E8439245755B27BE0FD0F344EF6C13C579B72B3B7DC995985CF834ED07E146280C8AFCCB8DCEC81D92FFA57C8B3A571E77D05D757DD6043CE3ECE5C51E6BCE0A9B704A57422943E333D20B8870DD492441094C6EAB058BDAC1A9F746F34E6233DD40BC87217A2D88DA0361239883631460477320213131BA05F9C431DF8BE629051E6B13FC11A733AE1CCC71BE9D00FDEFC788C7F76CE0FA0D084BB12B5AD57B5E9E1C566F5C899FE8EC9CA04051E9A8C36F5FBDD7A2D8824D601812DACF94A33FF121A853B97F0973945F4C09190ABD545361B9C80D98D47A7B8EF225E19DEBDE3FF5364290B416B09C1F59EAAB0237B1CAF199CBA737737AA3630C73ED1B81B787CD5B7EBA372A6049882C9D8EC64D467F301267361E23BB1E56174CB0513981269D02EAB2D2A896EEC2464880199CE2E1848363045D65C7B63222B4BB7C1BFFC76B371326F7AC2882389F58FEE8CD2096DCAD410A3FA1C7EE2A74AEA61148E7B09A1F8065F20C627F9B42A10EA8FB23EFD4A723A580619472F81A07A543917BAA847C92F7BF106D6201CCBF577061F10A904DA600EA23C986AC2101CD615B5492739D876BB301B41D92113402B55D06EF6663205FFFED61B0492A2C02895FE023768837B6798EF7130A4C24403ECE37D88F25E966A12BC9E33F359C5D0EC0BADBBF3C1CEF1D8C3C81B57F4BA30403A8A89D0CA671A19D768CF8A056EA75A3769A840D6A99FAA8C7CC160F784BC055FBAEE457AFD7295D3C42F0E0C455198BC5CDD5683670F2FA0D544978D58CF7EAC45F4E2DDE9FDC0AB3B66B3B94148D0B9BE9968101D35B8FE1C651287DD8BD5192CC85EAC1FED8FA56BD1EE425036C2B494D934FA458C45B014C7AE2C849A79247833B222805C98EFC232CDA590ADE0124610441615ACFBCC43E2ACA3DA8F7A33C0285DCC8484344274E4D743540F5A59D22B8A64046B2656E5E814988BAA234C2688A7A9D2DF51E5AEF0D77ED17B29246377360AB1471BA0975EF38F26E975D4B5CCA86144AA4A32C41F69999D6CE1EAAA3C12F9C32CD86E0D18C715653725380E2B9A05E13CB9872F6080103F4D4150D454230AED7CE84E26B3F9093B3CD616A9F94FFED023E498562B1C85EDA02C88961A752EEB654F0588D0DA952AA2F46C580FC07D83984200CBA01BFA6C604A429E1412B6A319B05789AB51E4732EF0A04B3F48B5014419D9094941C1A56647C6C41DE617543266357255CFCA5E6561364A7A4688096336FD9DAE450249350AB57C5FDB895E1C263683B4F0F5EF93FAA11D3AB3A936DD7AE7B2266A3458B6C61AD4223D190E874A25CB789E9A9D19F0C3C864BAE17AC7D5C24613FCE2CC010C2B07CB489012D0CD214AD0BF2278EAB207AC4160021468B4A1BC4B2A31D322BAF1A59CD71C79662D030FD6FECF6F1590C86564C064BF10D1EF3A876F65273928DC0F06A01586F856BA9DF0AA5FB852F15D33FEC277A3A33A79F5FA6CBFC3055F28FF741DE987AC9A3BD1122AA7E1B1CCB349B45075943F661CF013FD211CF24565175C87D860EEB422C09ABD386A6C2D50DFE606151C3176A8D0D90E1017519AA2AFDBE7E906094C821C4987ADC800000000000000000000000000000000000000000003070F191D227200000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 19 iteration(s) +mlen = 32 +msg = 5000000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = D195B3100A492FD1F03970367C4D07E1284C8A322712615C275D637C9B96DAD2EF21121F912E61B7CD334775443CD28EA75A5FC9BD34FCC95147DA63ACB8D624CEC3318B1EE120B993223D41274D674D890D19BEFC0F7D36C8AB3B652D0D998806798CC679914C61F6C1CE9D673F77E050FAE67EA3BD4F39D7ECD599D206BFD07D3ABC228921300CCF5B09DAC8953E2683DCFF870B14CE3D11249DDD92697B129A78A662A064F70326E3DE7DC138C31E4384B5A6337028943E1027C2C775B424AFF4F19501267E25A6B29B71909299D0054C9081F62130BC741BC3C26460AE76F6DDC59B16612F965509EC9E1821090194720BF788172D0088AD9641C56AE26B34AFF89937FB35085A213957EE177DA345C391D968255C399E769522233E914B164010A66BEAF2925BC54921979C3BAABCAF5E8E0011B4DF4713AD14FBE0E83E13B1EE808C17924A2BBADF06A6164B2EFA23A43CBBAACFC7B573A21ADE3E62362A09118F63588EC9ECC5A496B293E5DEC027DE91BE7AAA8465623ED9451614CDCF9A2758639B410FC5A17515E84B0AEF28401D26D27ACE64DE1E4C593F3D9324E1FE96AFB7D5253BD4E0DD6038EF476B9E113B098D3CB28CA5DB8A1FC347A21B47411CB46FA0D0D25EBAAFB8F484F4D74710D2FDE2C689BDE16019A14E7226B4D1511A8586FB1CCE623584F16B4532A3877003C0EC9E067A4031E2919D94426C4A1DA9B126E64A5547884019E1556662FE591AA19BDD487AF5D4D60BCAA80D156140EBD9D028F01BD8EB526B5EC1314FBB72C945DDF1D37A154D923B13F4E9C0D082B9F1568F2EA1F3C63B5BF1E8A8E53FF879CB9012C2ED3D9E3CC03A4C4DF80C376AA20140B31EC67026049DDC3CAA0A346370915641039D80876C4C9BA492D7E53184D75DD91A27B6F4D6998AC2D1AC678A01BDB31291E7E2D54A0EC5CD43E9B345AF3667B1E7572099A907256C7D24D8779988B0074BC5DC7ABE47A19F8B55E71D97EBF88A79DDB2E31459DA9551B9A3DAA3A4B5C2F880AE6F5A1281FECF9FC551BC4E7F28DD2106C03CBBD9C2B2E431849A74FFBD4EF436B89709EF99F56D5E0DA522B244B1DD9E6D7F40F2F406427D3BB56FC0F104CCC4B0D4399072D46BE4FE8E3571EC282609E5BAA75EBB176E3FCB1801F12484FF84A19E420F562B0AC5BD50C4C00A2807DE8AC33DF85BB8696BDDB44915E3F9857B375328D9AF4D1493633FBF0249014117823B2328B7EEA84FC9A44E77E3A407C3C247CC339ED63E5DF93E59212B57D36C631F8ED932DB4AA4D0D1201B9EC5FB645165E4B3C331C67693EA81C1877A96CF9452CD384ECC8054B067382F9BAB4523F494292A112EBC63CD768DF87D89088F7A2034BED8B3BCFB08BA36D08CB5CF935C00DF9B84691AE61A8398102DC1724F1BC67AD07C4E595BEA160E282849C087580F6128A4737252E6B9652F7B5ABDA7417199017099D30EA76514CC169B199FFBC48345E29F13961405670DA7294AC9DE9F0DA0FD13A47F254A1C5CF8090FF391CA8558034B624E4508A9744A1DFFB92F42D02787FC34B2FDA548BD426BDC657F901EE220E7A5729EB0B889CBB851AA1773F99C51176604D8F287D3BE31FC91FF6737B6305FBDAA3E80C4B8DD9796AE2DEA6DBD2D9E97FAD0E6A8952EA8E5DEE06C2CCFA2AB7CA9FAEF5A1BA3BCE786B5B1D62266AF8EA4ED35A885D445C9C0D3B979282147130CC9B0818F1535A979D9A3849ABA98807774EF7445288ED5CB8C3124EDE54D7D9A34C35ED593A32B15FDF288BA498DF82F6A348BA28FF3978D7AE36334B63EF873A2C638BD6CF921FA4E1688FF425D352EBB8C1794E512C8A96BDB0A50BD3268FAB4F12E10C099F4871947E1583B847281760E497B8D8152B9D83CE418CC67F21C465042B70F63098B3F5858B0B64EDD5F4AEE6E121A4B1F3CF0F079764D716664CEEC17960B1F4FFD9AAD45E1C0399AC204F858045E8F6D436CD4AFA788DB43B26DF5BCB8D7BF5C2A78BF59E1ADDA41D7B3D2FB6774C9E46FF83B7993A708F75855C8748AA9F121FDA369F2565E4F7DB8DF3568A8ADAA743BBC01F919A7567EC675EC0326A73E930090E0EC168B8FD8F0AED26EB23216EAE57F8081502AA2368D74252874782BDFED800568C8327480AB6EA3223FE82903CB17BFE43FC301476C7F49D23417D08AF26EA61F106FEE4C7D49A4B18AF0307C77334947B6014C29385E0613A85D618814D40806BDF0B8E4F4D8CDA6399483BEB0DF880DBDEBA74BD81170CB340FCCDAF6E3B862DFBF89753F57B1D6A5384633A15F33B83D368AAD4D0B21E850909530F1AE483896BA28544822F9134C58C7A13C75EB2CCCA3D1B5E645ADD5E4AA696358DD486FA42FBBFF23D73AA4C27F24AE001E314A969F349F3650BB2B53567061CB9276A22E568228629106088E4AEE0885FE5AE5B4D54BE6680218BC1B63FFDEC229160EA32F62F2A7F36FD37049ACF0C9E42F13A601B014236292A9E8F22C02D564BAEB71BCB9F57B91F0F455F98ABF4BFF9F57F5C390FB3F4687170A7E1AD49A40B5A61EFF0306862B762F43359C247EBE045FC6ABE3FC21159FF533A038C6ECDE4AC32637B27028E285333ACC7635D751A24D01834E0E142D8EA32455CE08D03C8FC180BE64CCA4E17FE347919BE46B51D83233C6D651C6061BF43FD1605B38AB4CC215188C822C899354451E8F90683CA97D0EC3C8244939389981B689F33569645102ECFDE89BD714F7CC4269C218FF56DDADF455A377B04F375A1716069F79F5F72E5AC8737D754934B25C1D175DA27D0443561B3B593EAC1E3ABDAE794E47DCB8CFDD77CD94479794CB08A346AAD446B7F0AD121B281F69486029160E3A0B2E267B0D35FF920DCF16AAC60AC453B6CE7B51D8D469C15C28EE409165379DD0DAE461C440A22F18C644B6444296C2A1CB8442AD1B21CB67BEC20949057B799D3F5D38A7A06382D70A728E25EBF46120333232DCF2C89B288F38A47AA4AB9D599954E7F39B8863AA16E34FA38B45195389A5F396E4E35F635F9939CA24FB6F1739114286D4BF46EC439F3EDA4F126B144B6442B5D64D0A8CF96D22F876B1B2219CA966B87546DE684ED6317CBD6EF324DE398EEF3C39FDFB8FFC2FF06707F24A659F9E544DE6BBACBCD2E84F59C240D1BF852C59A8CDECF61CE5D630DA04987F72EFC58B6B90703235CEE579A2EADAED963F7617FDD088CC256469D8ADE4197B6EA019B0E114EFB98B0F78C4FF836F7DFAA8DBDC2C3B7FED9C4A4CB350B62591ADE1BB881256DC746D72B7B345482A704F52745AB80B12A55EFB83E9EE8F7E50F19672C2AAF58B7504079590A447D4EA9ADEBF13720FB366840F9E41F0C128789C1AB41F2E736A954AADF87AA93702C82C541895780C41285E5D5A42CB5252AF85AB70889694A153850900D9E7B696C39A6026BA3AA18EF304E7B99EA209456959F7857DA264BA4D707CB2FAC183545BCAF89844EE448554EC1F124540C907EABEFA6E7BAF56D7ABAC473E433F949780B2D31B41C8C7DC597E6F58A1FB67F8D99CA1565622A4495E484384615EFA8A1A3BD26D1328447791895CF82D14B7E9AA490559854C1E7175CFFDF93C959896C74EF2B25C1E4DCAC32BEEDD50FCB92481C255DEF447A0C0984E3A8F7839542BC8E5465CBACE449D3AB75E03A39F59C8DEBC8F5F27782D425732FFF5A3993A45BB0B26D8D929A7451DD2C1837EB3969168DDEE0FA9B3EE1664B9F6A4CE5971D02EE990B58896195A844A740EEC9BB76F90733B78A5E6C65848669E5899F049DF2DF8B7F6B1B88BE4357D5555B4B7B7CFCEA19CE5E48AAAD6D1680E8FCA41833DEBCE5BD8734773EEA6B237E9A31906EF4D7B29F832FBA2F14F23E7ADE4D2C3EBF7050F8633FA01E9C0E260FAADE6B980A7309E4F0B16886BF5BBF1C4044602736A754D459966B747F511A7A20C52BCC57AC4586FC3528DEB0897C37BC9CF52E71B9206A5DA2F1C594F4FAF1983BD9966CFBC2507C601883D57DFD23E87B86D75B7D37213D0141B06539B2D6E422527437092913F423341437C683B8E5054BCE2140765D4919E9D1E9C492D7CD56176302CABD608B52AD78A2E83EA21500769E1B16B29717BB0808E27BCBFB2C31DCC442912A43F3BDB4B9FB0D929D6E271B67620233C731F5835C12615C01574951EFEDA8C75618C79DCD957B9C72380557E9B9DB7D8F85C64BE2B70AEDF19363BCE90EF5015CD20ADAB909A8D155D9AD1AA0EE714953EF4DE0D705EF616549A1F78F36F3601253984CA67880F5F2F1263CF4A91506ABF6D1D82D1963E2571B458265A1487E1FE3C9BD2BFE9FE7580462282C23A15E0EC1765205D074E3C90A0B541E11871E932E054815415E74CCA00BE74194C80E66E99D754FE39DF2CD73907251E1E9A80BB80CE076D889416A9A04D6279D3C2F8D289E0645356BCB41AA0ECF3A3FB70FE4DF4FB4E8C42AC6683F5B81FE346F9A9CBE2F420F12D67777A2BC1FA17F85ED62A805F7A629880DBAFFFC15C9B7C28EDA4BCC6CB988C3CB10815A2BC991E7FDFEB08665D0DA9CD66A7A8EF8EB5FAD7F879075397AB60A01C0E5D2B9490C38A8F9A9506030E1127A9B5E5E83279BECDF6072541535B62A2B6CBE93C65666A73B1D1DEDFE2E3EAF8018093CBE1EB1E314970BCDD00000000000000080D17242A305000000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 20 iteration(s) +mlen = 32 +msg = 3A00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = D5D4C237111DE3D767EDA7B22CC454DF422BCF03257B0C6F426F9B6E2105862D63652590CC4B1E32C6A257EE0F6B0CFE50571154C5623C73C73E1BC93EE850D43E14C34F1D3011001B014D9A4AFD32ABEAC0352FC6D15471125B6EA5040ED939D354A7A37826B3DC623C58F18A61C426D24060521ADD20FD76B9D97D79734A4A5A32AEECDAAD09D8BA0D941EF82D62A0C6DD6CF9D07FF00D547607CAA5EAFE45CC4E8AF67A1E40356FF0C1681B791325C1887C5EF56EC8B0CC7F5B881C6D4D0BDF6B8B589E75E5CE3629B565D5332C291755C8095907830388D5CE3C6519BA5161039655D00A73501ADB9E25B56A7F37A1211BDBCF3F6D1ACDAD3D9F9131E43B3EFD9914A8E822757A2C30A92867D1C333A9728F01C1AC931710D86E05A85A9B635B8B4E8E8A4C15A981E1907BBFE333F7FA686493C366ECD0EC101910E1F0003815B6F7A9336D5C6BA98F250D7760503727FE0D51826AB9CDE573A99673A3154356F7FF7E2786958072DF8C68607FA2DD1A15892887D39C4170EFF34D0C4A4CC13BEB561C5386909D734B8811CE42A44D3FD90C64D8DCF5BFBA0DCC1E30EC5D2CF73DB17E7903C6C1AAEA40FD74BADF28BA195FE12591EA57F424346F2FDEFF968AAA9B458AB9FB01B3D6966FF6309058F498A213F733404AD82697F8B012963BF5A478F71F926FC82D0F5ED8E9C1D6274EBA18B68F63508227B4D85E16D6577B8F16E0D218286D4DD23D7D4BF931E83EB825FCB27FA3FD8CCCEE8643915885FD35E57859C6EB50683746324CC25BCB6AB260E06247F99BBF3FE679B84B594A7C992685A0E4E78EE927B1C7845206A2C47561B8F8B5D3449F866D24287C1E7F8ECB3099F890DFBF481780100A0D8405FBAFC4A93A74E2BA2BDCCC2962F1CC33E453401880398975231173C0F0D476DB5508E6DE861AF42B48C7BD3F6B685EA1290B7B559E02CA5D97A24588E3C93830F7858D2C3A9A58BF7388C30392BF665BBFFF7995FC3015E58EE8AB7C169B681516886E30002BEB3BD37D7CC46A41E756F321BB9E5126E41EA9E7052E50BE777DB79876CEB71C49E9EC8BFCA0CB061C50E7930D4BC345765145EF81567F13BB7F5BF50E3F8944E92415166FDB8F1848C8CA5BD4817D5B85C9FF97D54FA3CD9D5767E3A33D6D7749C26C4AC63F84A7927BB952A16C4ED7B05FC5F648A15443CE3BF36730EA9C44740948BDD7803D99C2D00DDD11FE682424FC767EB9A2B99B1BB1234D2C8DFAB6D2EB132C10D5F5E56938707784BD89BAF9E4BAA281F3EA7BED42E4E4B859EDED26B3B7E5C6953EC9C9D8D7ECEB3108C720C898BD639A754B5B9076DA4B827BBE2177D807044C805780D87E7C0029885777F0438D177F761D19900ECA270FB7F3A5BD603963A1F3E247EF56D120D2909A14B1414B1809AFB632ADA9291989CC84D53689A588A67A9A7CCB293C9209DD8C06BB5B9458F655E95978A5BC3DBF65AE84CF6B556D7EB52119C9F7ED1E1A9FD72432CA2F372976366C00BDDEF0F10316210AA1331D6133A81A929EFCB7A10045F597215257CDC4C1BDFAE9C05FDDEA982CEA4423059D3BF9C657923B571CFCE925A051E7DDFA5C021E1A05D109F41B1A390E1F3D4DF8BC428AD3C948A1483888F3944D3C512D68D0F250A9203FE6F240FF3ADEA30343864D5A70CAC82E00A292A1496E0CEE1BB4B54F459570AE0F1E578CA2B9809182371FA90AADD4A1511301F1121E07064AC334D59F566B3326FDE27B8954DFB1E0C3FFCCDB0B17277353102DCD0B4A66FD22FC9D0DA0E31FE58382D036BE2F373E504145BFD343D8C4CA31D6B18C7144083A0DE8944261637CE323213AF02048400F68B6BDAC8B0BD38075330BC452D33B64B574ECBADB28E7A0E5BCEA64148C37D4E53F6BD70B74AD1152D5F0288E1D02246EBEDA700524C64A53C9270AD5A203ABD3684795EA83E0E46F377C2C3539E267EDD0531B52567A4C6B22A9F267586DE28563F46FBCE127414F69DF2992378CA7221A4D3EC40E336A99EBAFF2EC9E0AE500DA2944DD3EFEE4E3DF1C9AF4461BF2BE79A400E0CD8AA9437817BD4FE0919F99A8ADAD6CCCB02D9ED32355D539387A1EBDCF47DD542CCEB56A0D3638498173FF7B279A842A96D61B1B09B3CC9FBA0BBB3DC97F3CC439D065AA81C56C94BB80F61CA96DF571E74FB2ACBB123348CE8B8885882AEF8A59D1ED4C1F4002BE0F338336B7DF6A0E60C8F693C751265DE66EA247181398592A274318AD749E4B4239F5BF0C386F7110FA6C3AB0BAEEEE05468C56FC81F97BE4FEE082D6F93D9BD615C4ABBF3DBACA1B8DDB3862521016BEAFC9924D92DAAC52BFEADF6DCFF838A7304ECFD4C7960B6F87C0ED22C958DBCE8498C601E18FFFB839F2FFFD2B0C7F76F9BF109324109EF59735500838188BD09439149845080E37BDD032DB9B54D0AA6912CC84C75F5E6A2970CF93EAA0277722D4DE868869E2C9B4A6B257DD07DA582ACB32E51336F204FF1A8A95DA1F519583B63D16D8FF89F127177D31AE34D669AFF049D1314EE62443FF81BF1A9817A7EE6CCB23ED801A2C029C90042D6138F8955110149CC15A6375246882E041952E3735F087D1BB78380EBEB3FD785C8D3EF5E58CC6B5C356BDEB1983632607928EBD6763B77DC5A42D6B5A145BE0B59E5F178AB83869CCB335B189ED35323CA4BF8E8573581308DB432D40D10AD5D2D1DF72C35C06B4CF78B2345AC9F9CE5BD648370E42ECBC899ECE3D647090F05D0AA07487F77D8BEFF80A694FB491084619B7A147F3AA900B1877674873B9409A6224D7BC70558084FAAB2DC7C22C880A1A41892F342F36D121B8957F33A9032605F226961F254D751CF45B2E74E8C853313BE3268C03978B4E95EB100E846E9E37B932A4F6A4F29366858856C52BDAE4339E4FFD2715DD3D11E03472BE3145C97AA1B04277FF7E236A90DD6F989C5F571801C1AEB191CDEDB744357D984DDDE14B32748AD80365A6C05AE217EE7D166E1C47E1501C4989678B35DCFEC700F9CC86DB534F503216EA70CAB8E14F3D4463651DED4BDA83FC7E06B1288E36B35BA85CE6368E2CEB82DC63FE092B35D236A9333E980272E6350C78DFCD36CFCCCD5E4F84848F95C559F36E921B75A8E34D9D190542AF7FC129AD36067287AF55001FAAA2FF47348379CDF4DCB9D223B7BEE63DC504C0B08B6AB6870C721CE320191E20F5391000F0588913A6363CC770A106DAF8DC981E153A8914F230AD0DC2CCC93085BAE61879D7B82B0BE5904E0E5207116FCFA8A4EEA9B744CE63BA82DE2CA6443FD76BB9E933760C3613EDB04C0A57B587937BE3C70FFDAE744CFC763C0B83A298D8FDABABD26FF1D5F5059E74D48132C029D6766139E579333B97632B7DE40BC25E83B9109E2BFAC810029B3E0CAC37A616965C81F473E3180866EBF6D7C646581C8D857F5AA0D43CD379179C9F52C18DD7207E6A95E47B99CE7FA8346433C630C5EDB827E0D8F909B99FCB7C0DF8E40C29548CB66459068F58EF431F8CD5EAD9813958F06F9C8162184FEF9C546290EE0EDF0085387F0FACEBA71F5DB046476BA8824F2FB4F8C162B5527BC8E3CE372331057C37CB1D054E0800440E184D126B45B5A55120E9A3C524F8E34869C3140E1D77CC17C34819D392032595C445F99AB002A8481971A148EC34850B9850D69BFF5344135FC85D412A8AE5F5ED663CA237E8222889E9343F6C53DFB9C85013ADE360BBD67AA546E69E6D9E9C5D0976C02C5E072E91DC82AD16447373B0E5B0D5B07BE4FBADEF9541286C964BB210A7BFE8B8F942AD9748D6763873435E97B8B9D18CEEC2CE397222D45FD4BD75512E3A4E67A2860F64EDE81FF013E1A563A4253C228CE8D894F216AF05C63405538BFB4FB3074606ACC8CC4ED5A12BEBAAD8D54767903661DAA206B29461F4565CBB453FCCBC9559DF583FAFA3128022C8C30D5086CE446532E2B448A75CD95C449A7159BC3D7475DAF6C5B72F1320CA85B9E4F1A8BD0D95D8BA2B66B1A23F6F83C1C34E0E32FB56F0FCBA0A0D790CEF1DE3543392C93688895FD0147F3949F1F93DD69C08CC282DD71F2F93148EF7A4E1A83FA8BF0E83041C3822DA6CD6B8E66915AD2074FC5430247938223C0368FD367C2FB19B6BB3E59EBDF17F5F6B9F0DA025BC3A1BD237ABBAA1970CBE524271008A6E8B0F86FB8AB57832B1549BF060DB8CA4BDDCD587131E61D01214B2DBA739290B410A49EEBA87075AE899EB7AB7D0B22A7677FD18C205C48C2D0EFC5250D3B64E777688E1DF8F8F251FF73C7B73D01E06A1DEDB8E44ECCE22E5F23686F54EA59D3E398D6F38D9453FE571F9CD88AC21A5E8AE089FC74D93A02360B9267668D285F8B81153470634F3BB938C5975C62781D2D70A4B5540CEC4E4AD8EEA549953545CC98F761C35853971BBFDD1104DF872C4A76CB7C72A9273B75E48828D9EDC7950819435FF5148AB9A1069F429E6EEC43733CD5A33F9DB1C19F3BB54F6B4C7E1E1CE90E60BC1B9AEF5FB65C3D3A041FBA21D7E36284EA4CEB0CCFF7480A22966B3F7D1A41B0DE85D6DCB03E244628E56938EA4A2A933F460A1007D6DD3974F95EE1849A546539ACDE1E441456A919A9BA00F20257813B4DE1F4E8891B3BBFE4564858B92C1F4000000000000000000000000000000000000000000060D11141B223A00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 21 iteration(s) +mlen = 32 +msg = 0301000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = BC69835D4DC26784A0325B8049D40E922955C61B21148C20D8FE679E4167F21A10E880F6C75C0FBAAC2994FFE766613C65683672413C55A0EA88C3DDB91D53E1EA8312D8A7781E611C7355945B8EFF528A8623BAC8B3EEFE0EC5628155CFF355CC6DAAF158D459AE496CD3648F8749D08B8AB5359B8B62ED52CB6DA031819D60F2E9EAEE9A90A354EDD6715ADCFEA9703D240BCB4C9390C68C4DA321E7C06304B7162F6A87F0AAC352E2CF4875EDA31353BA980D1BF7A4516166C2C4CFD0FC0B7F5C00BBD520786B969AB57FBE151071D0AF22F5CA50F6BA63005A04E0B2C8578C694BF7D5E7E5AC6C51F02C242623CFACE4D85EF1B3EE20A5A1D29642A47362F3709E0500D5C62D1CF155C97A3470C49332147B9060D7E3FAA7AC06EB71946D23FA8D25AC0E6A314471679AD27867D4F19A17FE3C4A60ECEAD04B1F706BD74562E04210282220F268ED1EC33F4E5EDCC72BFE09B3927358678F0654539503B3CE71346E0BEB86DD74D8FAD3710794ACDA646F639ED99BC38D5916EE939C7A230CBDE69AFF3BBFF6DA1A3E867F9AD8EC1F02E529A34DEF407A4567E055E65D17CF9B4DF1C67844163CC4F0422FCF1879B96192CA6BCC6EE361CEED8472AABDFF98A68E3E7C8E3015B36A323502EAA643626563FD9FCBDCA779214086084A829EE6E3FBA9072CAF18C69F1442DAB9FA5FACF0970825E7EE57F2DD372E93D9CC921D97C4741D8315CC8DF4D1E67115A6DBFBDDA45A2235C1334422F2B9AE523270A8D4189C3A57B5E3BE8F42E1CB1FD2BFDC56658290F737A72DD088A894CB2C3723DE2EC448FCD05B20AAF1F6F27464260E5B406B987D1249AD9499EF56B4B7C42FB224336C5EBC13EE060CF1C81A63A3FC79AACBA7E5527DC940765199B5F586EDA057106732FE6D38D75B3676F2E1CD1D607382F943C30744DCC903FEF904AEE1C7A48CB53FED2B7EFE5F886F7FC4CB37E6A14B540953C2FC4CAC05F03E8F88CD27A4A174089C713A673BD46A77D05EB781150062DD1144A37FC66B9EAE3E4FDBE4BBBC53A639B55C5BEFDA2F6DCEB39ED5ACD9D613B3EB340E31555AB945BC878D44C80BC48E58412614277DEF3CA1F41823622F7C7E14A75C7D1370D7A5FDDBEC7438962888B14A84897D6831780D6E5C7B120011F8CC6C4761E1D7706D6ABDC95DAC0627D7C00504630CCCBEFCCFCE7292CC274326E9203FAA904C3D99957DA57AEBCF0EFE62230A1AFF267446A6FA67CFA3912C395E49A25D9365D4B9E9AD0E30276DFA497CA24F25E7139C2389CE28D750342371AB6E2A1DFAE9CBBFCC5AA5EDB1350C799B36DFEA285EF252B4161A8C5EA08AB8893B41E4EBF7A220358EFB3235BFC74EC1E4846BA2D2A176CD214A52BCF0777FCBC9A0EB3EF5AAD7F8F2E40681A170BEC00A25FEAE9AA60EF29D14864D6DF9A82073176F42022E8142E59DEC8C583944E97FF8CEA6E4D6BEE0C31CA86C8F1F4A45F2E01A37C80FFA85EFEFA18B68C4E5819EC5529DDDC39EC9B160DC2F2C20A7F6F483E74E3540D55A22052DA34337B0E15A2F53BA3D3DBD74D7179D979C32DF25E0992B4EB5E71D1853CD476BE0FB6581E93C44A25C51B5B0B2D0DE536D42966BC8757A98337E331CDBD7374E8E9A1E55C140720F995D6E59FD9321477911B14DA22182E3CCDB52A1C2299956FD27CD22D4FF35167B09873CC28045F1754A4D2EE5631A3A2A848CD1A5E14C2639D949169C05260025AA6003EF2804D69D92F96AF7DD405A95AB798BC695C990A301A4CE0321CEDA4026300883385B6356433FA0EB81425E53040C78D75A2D28CAA62C2180BD2CAAA543295C67C55F3675BC1BA4E4E660B60B41F3CD9DAD43885C5FA760957D826DD3E1C88FD2C5C0C61BE9C4FF918D0F994246E370981D7E944D62AF48DA8B4E9D6E9CF526C12754C92E8D58F7CFC3FF3458AD469D89476A4081ED1A71E15814CFEC977F9904EF570E933C19F0D87F28CB009D8959FB8FAFA3FA26583B11E6AEDAE855D49B5EE0E71B9AB3F88C7342BAAD7A59397DCBF615A2AF3547CC09DB685F2A13BE97CE8E1D18E129EC654899F4BCF2B871FEBD64B163EC52C0FD17FFCA6BCB7EFA6AD0FBDA1F02FD26F6208658C0B4BFB5091196474A4DA16A40319EA36203C3836A8C1B3A173AA5B6EE3774DD6F63FC246C4D41997FA72492D5A05D6C3DFF9F84166D20284AFA4A645DF34F46B7368297305EAB04E78C3E3A955F1C3ADF7226CD93B21AE252E2EFA9819475D1B39CCA27438C16305FBE167B69EF443E0939D558CD1D9BDBA4EA289605B15FF7A941A3A259406F3ADBD28C15DC9F920D80819D0341368E7393B8FC0644F7FA96ACADAE97E935890429B24470E191CCA79CD78BA248EB59A881B85B5F7B85CB9F13613322579419AF8236EEC6A0BF16ADCCD126A5FF4A56D741A5545BDE822912130C79FDCE1D6BAEFC8E235B1077DF528EC1DE808B5B190BEB056B233C05CDCA7466566E2E546C539E1FC92F4441F4E30C5B4E05552A6A0F7087C77A0B79B7CA04EE02675A92FCFC5BE63A1902B8B53F052A87DCD6DB0C79CF77EF7497EEF42E34A095A9F33798D2A1B9BE69035D29DBD8334D7499F62E4A5A92223F1ECB325634E399459FF1CDAF77F61C5AED1D5F46D605D87B091D494133815FAC2EA307BFD8E6E4EC1F6B9CE4AA192BD94F69D37435B797CF00A275893F884C4CE08C26BB4575548C3C9F139FDFB165A02BA5A594492A2A9E8412D1A97F6EA8DC62DDA903BCAD8913AB3FFD96B2E03DC1CC3268F5A7B7298B212816C09EC8C4C3BF5CF6D1F343087463C84CE07F10EBCD6E97168E61A840D2215C62F39ACE7D03605AEFC6D456B816DCBE6D7CC3D77172136CD9121B4F05D433DEC531A677298D268B9B25EFA208BC772E5DD4CF7870410C765D70A4BF2594D6B2037EE2AFD2E73B32590CB2C7F56E135859132F04C7DBF590DBE569AF2B8529A051EA21E00727898AEC481AB55D0D96960999DA91DB356615847EE91147AA9A907183CE995FB7834F37BAAA15EDB3122632CE9458C3DB90BCA7EDDCE97BB73AE7A5F8AC139734F761F64556A9A8F066C664D5774F8D2F28A5543C69C637C504191FE1D00FE9A88DF5071C3D41760E9468040F4E108DF4E3EE7274C6CCCCB8EC08C085F9262E5E7CA3ACAB76CC8AE082B678219B0595C0B4AAD6C6989474AF5FFAF9753FD36987AA2EAE9CAE5714D913E166471BB8E2CC2DEB6096AE16B66857DDFB5215643CD37B6B442A57E886AA9BB966877819AD5E5787730F08C6DDEDE8C7C52195B023C9D8655BD39E7EB3490D492FBBCC465BFAFB903069454B97FF73ED90BC8BE7265DB1E93C62FEAFA8392B65E4FFA521A382EF8A32B58A1DBA2EFF98050BFD251B7099E32ED9F6CD768F0FCFE86250B160CFD8121E808EAD63BC018105D4783702BF7363E767F224EBA5B8698717FEAF2C660FA772C73C0F4304F4A0345BC114CBF0F49D002DF610C410867A7117B60FB5F8C2794E5BCD07A4B7FE849141CBB5E5D6532F08FE4A11B1523332349AB6EC7109E9E837DAB5D224D00B58FBA22E3910AC7158531A5B0A2CA26EAE2B7E36188F7A309D560889C912F92826175F473DF0D3943D37BF96DC91726BEDC3A6173E0BBF035A0A2E61263C92385D27A04CDA5C0325A652DFCA9ADF5F74B3F6C028CD590E9EDF6EB1669876C0E449F16030252C85EB04D9A4B2D3D71ECD277EDDE659B0D11C930713830DACD452D2F5AF5EA7A1B09E50E709983ED6CF1028898E13782980209EF72F8F61D07949962749B5FBD2C09D1F26DF7D2A19AFF854ED5FF0440756354FAE6614C9F2E3B5917C748DA5360DDA149F4228B3F35F0BF77BD3E61456E377D94017BA1C8AB154CADBBDABDF533AC15D1ED9CB0DEC3FFD79FC8CC295CC47EE8734E4773541DCB0EE9B746741376553175E98CA8753C1D66BDACFFD717B0D11C3CB4E04EC4F85BD16342ABD4A8F15442E46ECBABF3E8BE618ED752842C5D77D1B0C63A293C5422B847DDCA0B105EC8F185AD1E891EB2C01DE98437E91093F2AD1CBE1B69C6383C4B092076E39DB92F4ACA72DD8A1BA9C4B4749A0AF3019A77EC711929732E5A018DCC6A53DB20CA478B013A7169BFB46FF4B1B27D9C0596061F4D3C9D92D5065B872AF4F54850473BD72C772FCA1A7CBC1611B7FCC2BDA37B244AE24898A1B714C7E0E7A83A1303FF2CC34D3A9BDF6DAC9D70CEF8EBFC28FD35BC04F5AD34BC583846CE7791799BCD09AD0B49E8BD8F7315C344DFDD432A0FE23287ADA28C28F8E1655A9B85A78EF281920D648B8E6780E23C388262AD283FC606B90A5CC8ECBC2824BB84C37B9CF392C7C9E9A478CEA9D416F14F1D4A6153ED0C9367BDD1F3664C8308F56C237BFF64B9E38C79CAB7EB3463656DE506C9E4CB0EE0EE53A576E0AFEDEF1A0D4EFCB8C83DD1359D725CE1AE0F94B4C12F569FAA59C14D658D9383F6E8F26AF7858609F4CA2704BA02098A09D194AA61BF4A644E67EBF205C96E40596F0DBB5B5AFB2618A212A087BA23792E191D4B323C0CC6F6AA028A6F1393CE19BEBE5D6077ED6A4C74AE1F02EA251C08DB9298A895BAC0BD271FDA390DA6C73001B3C67D62B353651224863656CB4D9ED062E4D7BABAFB4BBE1F428970E3F8CFC000000000000000000000000000000000000000000000509111B1D210301000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 22 iteration(s) +mlen = 32 +msg = DF00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 5904D8B360F2977A93D146BC85535F57D7C537459777B51BCCF37747F50874A489D0C9F3B0CB4399568B420C8E6C36C2ECBB1D256EE4C33BB3274108568A5CA2C55236558DB61F7F7B786021D948CEC21D7DACF722D97A51E01922CAB79FA56056DAFA7D4DF250ACDED7AFF8403BADEAF5D2B6B7679D34C1EDC9DA353EC106E855A496D6BB3D76728F2EF85E3A7AE7AE5006B05E6577868B0FD45050482A21F7B657FE25B263F93CD77F64802E164176C4D6E8BCE5EDA052A5810526C87AF7FD8BC9754FD36184DFE017BAE8B3C932F57E1FBFD6D7AFCB92BFB8E366F5EDA8CF034A93B93C7B9CB5BA4A9D89F3FBFAA624BFC3862428432B8C2860783620E7589D850C4BC59A98617FD466E20C68EA5739650CAC8E1A4018C1B7D96F1C6D14CA3C6619D2025F09453FF93CBE6A6C9F3C27DEA7B17F1BC96BADB70B4B222D1EA14C632B1F15131A0E7ECD840BA27701BC35D7B24765546D4AEF40FC5ED45F8C9A685649063891F71C6BFCDBE7FA5758B823BBA2B5C385C3CFB9A99267B71E4D9732F83AA748CDC0E0F90D450F1BEEFA0634D380930902FF547EDE10C0FD13E1713D4A2A20DA85F36402F9A18972D5B1AA87B4DA9BA202F1B73CE69B09D9009D3C181CAE983A3FE952E41E6157DFEF51E2DF112514251197FB6A9CAD72E2952DE6DFA464541261C2C2D358F99E249BEAEA4DCA80B5563BEC8A0062BE7634EFA283EE943DB470FE3FE3DB4BB27AD6683F7B95F404372A90E8CDF9D796389F25084AB6625DA15CF5EFB9B6912B289541BC91FFDBBBC6B190F3C2F49B2BD12F948642B67162DAFD5EF906EF5D963CA9F335A89083728020BAF7C8638D1184FF3851FADA92BDA217BB848CFDDE8CD0F2C923B4BC274E2B83F19A1AE53A168598070E128FD7219CFF20F25AFAD63F6B5BD5151DF0F12A72699E7D7F7FA3B667FD8621039265F98AD229B8CD90650E1511AA805D3A3E2F1DA3931F39B227495E92B8BAEE558259C4E11CB30324660E659C19CFA6FFEECA971EE29912F73D56E752C6872B1D098EB37DB5BCFB71CE6F5A2E464EBF6189225501099E623245FF3859C42FD3047CB8C039C4B9F0A348A579B5227B6FBAD1F6300C441278AF252B3154ECE53E8EB01291E6B6033997CDEB058CDBEB2FA9892A526CC6BA4FF9EB7781488C368BA88369951E64DEAAFBA8E97BDA1FEA3A466D1BB2E50DFDD775EA9FE776175203E27A5B4925E606F7ED87460ABBEFC572E07A058BA412908B89AE1C16BD1499F2E3D314B42B191E4250145097E392A7983915BAFF0894837229F6AF94DA23299A2F0D1448B3832E2C9ADC76F3CA53192CEB68937B45A8EDE43A21ADBD171B2540B53E28F30C2E5D1D4B2DB0ABB1F91C028C044C76A77AF64274E07D5990F68DFEDAD5D652271F4538BAFAADAE1307085E3219503125779854E1848A236916814DFD9283F30EB81D434320F7063F9E05BC8DDBB9DE572580840269952103C4EACC9E57C99EC29D68FE66A733231B788B4F5B60CE0725D9F903A8A734B8784306FB76CBDBE990F7D4244757DF91623FC062E18D6A9DD45BA6EBF904DF58498330BA893BEEBD66539AACD43A18961ED901932DF3D2F02D826B81E06894D3E42BBAFEB9FCB9E31F863D41BA577E3B70089480B4853E1A290943C9668CDC040D5962E1922FA81C9E33746C5BE5E7043EE74D8A03559C5CAD68C66E73ECCB7837096F0F9BF0158886A94A6AE42D7BF49F3C5490180292D1777ED2CDD253C2502E66A1B3F6896B7F69CAEDF92A77F5572E68E17F6F6055E1C7171695238E9A56C8A7D57153B72F2A2CE4B29394F88341E58293D8C8ADC483F2E6932A7D6118C10162AC26DC925A78E3F8B7ED3EE5474FE1DDEA69B99BC8C49A091DD9BE7914432AF0ABD1CCF935A158256923CBB17DDA32024B548C7544A0A1F00EBA0727F96CC429F6574249DA35B77F231380CC37C48D1CC65CDF8A13EA655C3FF90B0D61E97B3CB0126FCC9C8EBA23528C166B6EEFD7FF8711844480830768A2FE4C661D562EB0771788E6DE01E951209EAFFCAC5CBC96A91B16044A50987030B360DF5AEAC87998EF534637148CF3B8A0580221A892227E2F312B7C348A1BA5DCB86126DFBCB9B7E556D1A1C3F200CFA79F7BABD06BD5805513458D0C6CDDADC5A82948BEE265F27DE58F2003A5BBF632A44850838BDC809B50D15EAC428A1733FC1CCD6978DC68AC6ED92EFC12226ACFFF102431523DFB279B2B54A2B586383CDE777FDF3A4F509A12FD02D2339B940D04F30B3C2422B2A0B0D5C913E2C36D452C299D864A39FA6A424133A3F31D62EA38A1D42A49F8D1A56948963B3BEC3619807B6548478E8BB9A2B7DF274A93154CB159E6E138D21ECD4EBC07F3781A4E0C4DE90BEAFFF5495F5FE8124D8586C5A25D7DBE22F19D700720F57A27EF65C30B69CF81656370063031B75ECF3D6B5F796B364D30B18A39386051D95C2F3921313A18286A6887B66F1FF3F501102EF75C51119AFC50BCE788187752B1003B94FCCBC16ECEB52DCA1886C7202F8087F08AD3DAE91C3285A0B6C5F9D311C54A166F42B29F3D2B506237BA0D61C5F9A082C9A481F91E585C90FED220FD71140D983A8B817087B0975FAA7F4BF8D2035495D5BDD76E008D3402F146E43735B6D21F5888538E678B1309A8377232C47ABA73E7C2925B8E8631FD53E54CB17CCBDD253003B98067EF266C68FAEBEACFD11434885D47A63E80E948BDC7B91210174B0013B7FF192BC7851672C9B327850D3F9302E099D07EBEE2AF73D0BAF2530D91FA93BAC589881615C7DD13142BB3914A1A801847A1A362215B51DC3854141043933D0033568ED96063411B0E37512F110541D686F59DE11A24CF4C83C6157A4E916E237665B3C8AF75FB4984ABC0725F08ECFC05A1D140E2D6606259EFDC4167DE8585CB3FA90D61A7DADF514F76FD73A2DB81A10F2BF1142EE8937AE1C2070DCE77F3CFE8D04DE6BFFD977B7775C85C97B3042230A5947367F8DD266D0415BE08E37833B4B37A446EACEB12AC8D5A7361687226DB529A2EEBD3BB84E6E89C7B325FEDCCF6B1F5875FF921ACCD9A362FA8BCAA0181B84A1E97F8C5D2C10C49BEA940CAEFE9FB6E1C1DA54018A6C6DF186769F18C97F32A5D98975CDFA7B29B4E3A0ADB06FC3271AFB9C1E85DDCA82ADB5628888D709CF9CC15C68385BC5BB898D8319F5D66FE962FF4AD9323BCEE5F39846BF4A5010493FFA52E7BD8F4867283F537E64D76F44587E56086CFAB70BCF2D1EAE7731E47159E3AA87FA226701726B8AEEE6FB07D1547366C1B3AA2DD3E6634926BC371DA7A63C9D9E8B6833AE061E75A415B62B9F673E59710C6C07FD9954ACC32AA04091E78DB933845E65514105111EAE207C7DA2BFA6BDB85FC2346FC835B82121A91F1BC2A220BEF3EA8137BAFC9FB5AD6E0FCA7041E0241136C694C624CD086065025882ADB335426613D087F008F3D4056B7A4491DFAE0D879528C1CBD163862222D2892EE47304DC30CA014849FC264E01209F1924758717F6F8ECD796CDBC411A3878FE55B3647BC4056F80A2F29A0FB027FB434F34111B8BAFE5662C0DCD05D90F30DBF499DE9A8AC7E14C8DABBD4598C0459117B4F9939AEC74087C1271658CF9DBA93044431893E52400BF75C1ADBF4FD98C99CE921497F086796C115E212904FC0863F168BEB6CF913F38B67DD03A3FC4FB6A8C85A9E5E4DBA52FC1D37FEFE5C221C4592C0BE1F01A553E29C562C5D90C3E15751305EE1946810119C733A6C12F4C1C936E18C667F1332B2E209485C448547B0EE2F92915FC4794C06D4A0FDBA012C02B4D10C226BE3F3916569133C0F1DABFDBDD720B56FCEC60A6188E43010209EE460FEDA5EAC9920624B697C6DA7B6E7B1B7AC528AF533BCFB459FE9677F3717775111EB60802594F380986B52E33E1020410DEFC5F417EC536D23069E0BF5912D4DC5D6401020616EF046411AB8A690FBF6A93D44C980066B612E9166F944400A9B175D32E8B5B71620A7B5615EB177B331C59DD115F082D0DFE374C6F622445C6643F95683ECE9ACBA27885937237E4A8C7C6E9BAB86AFACD12F12234C20C8870F0E592B748E4AA7897ADCA0C2036270713B4BC246CD7E4FA1B95BEE3BF8CE0D660E384F45DCB0F168E23DFA2F440F8A1C9BA3DFC0374106E65F4B881C498F39867D57C7F05FD645C555E94BF1F7F08DFE1B49778184519D52637CFC4485CCAAC8902340412C39F656839C9F6EA675EC08A556EC3CBEFADCA81E8729DB5282070136838402AEDB2E782D657AE2AFBFD99AFA12024F7900EBF115B1FD8D2C0E8E2DD9B3F35C3874A58F8E4407110AF69D487BE28E84CB85558802D1930B64763BEFBFC5E60595204B90C8BACDAD1C7A17A78D97C521EC6A97FF7A6D234DD02965E1BE1E724A98DED88C0131F8C45E866A3D7D0A9C02A3DBA178F6BEFA170C4634262BF4A1BBEBDC2FDA75C5989C17E38325AB1195A2AE2BC7628A282A9078906E7A731E39567DE1B4A5739F63635C8E41F49EF50EE89AAFD842DE9830A7BD3E96E91AA15DE76E3F0D3121347BD00879B6AD9A7E4B0EF5684E3C32D08E65929E3188CDFD0D214A4E53626C858EBCD1E6F9193394A6DBE4FCFE3D5B5C76B7BEEA333F577A7C8EE95E707B8DAFC0CDD8DAE9F60000000000041119202732DF00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 23 iteration(s) +mlen = 32 +msg = 6600000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = F1D8A6B653571C99122842C7CA222606E74D6814EB27F05F2EF8DBED54201882859D0F809903A7777A3236DA3BC18CC879283B6BD925A20C2B35A9F0C4917A46CFC0EBBC7E34B792F1577CCEE1047E207E1C7EEB4EB6AEEBB18C7E21D3FB28575AC2CDA9E9A75580C5268AF20917165E5DCB735A5615CAF0CB4B001FE08B65454C2C65338BF5777A260D550456F8616AAEEFF235A9DED33140DE0712CAFC0E729213514764F56E0AA4A852D5582135DC900BC4858CFA77FC098171A980CA338CFFB8C0C9AFF0A60AABE27D25CE0A329EEB802752E17E0D4C10D5EFC2B83ED0D0654F5810A8585E3460655F0DC6057A2CCFE847A79509C919D0A3D81E1E05BDFB1CAB826B5B3B76C19468F1E19DB7D02E4657A40B724F8B966A873711E9305DB43613A96BF1FDC0FF0E548BC22D56079A18B19CC4BE342AAC9FD83BAC171118D5E25961FFCDCEC1F55DC8A096B61883B3FC7EB4EB6FE40CC7E24875E39A907108E522E2BC8A7A0C4CBEB2315A8300278542C60CDD30EBD7EEA0D5A5E9D26DF5D3A37E7E7E62011700C74FB905F49671473AC6B63E9AB64DDFB1CF6ACD419D7CC7049BB2D00B6D170FFC62B286DCC989A8F418162F36B149B5FCEFF5000537EA0F39F7DA20597AE00849C6D9EC633592AF60F30DD1A98C8A2E99F6194D527176CFBB587EA4772D17A387D7171C3602964CD4A150285F27278AB956778C4880839ABE9C5EF4B4F9229A71B81239D1EB3A9D10D1CAF62B9FB031221129C7B595069656836813D2672D93EC963FBA56B8BCA5615010AA9AB8875C10A23F6FDF87F852199CD91CB0E84D2F31FB8DE5FF59E2DB2D234C61A5175AC7F0390AEE454544BB1D5D036D9A0BA4980E942ED17BFCA4C50BC4F452075B6BC093FCBD4076265F3E926B73AE6690CA5C084F66FA8890EF01BC234563339953BD0F11B43AEDE7E9E1A505EFFBD3751EBE40B3C6126DE59C5AA703A90E09BBB62DDEEF444088BAE807EFF6CE95A047AB36DB714EAB5631991208215B0D1A6DC557E93F397961B1269A423D398C411A0329425949623087D299CC27525BAE1977B972323F40E04BD48350B4E03AFE61B3024CBCEF5D0B66718D7CCE18D6657D262C2BD253357B1EA077039865698D491D2C6D71C33227F1E484BD8EB31312142F9DD785242C722F61218E03922AF3AFC8507D5E9087F9E2B2D4194555E9EFA7C01181186671B469D4596AC8B2726A1B973F94B67BD866FFCAD0424A57A97E712E96576438B81A9A6A92C88E0CB7D26115A5CC96CDF4C7E01E06FC22AA4EDDE06D99F2694FA6E0EE0C50B6681D22E79DEAD0084BCDFD9E70315603D8E06DD315FA069AB4E635A9CCFBEC07EE23690F5F8C3C6C585B71705835C7FB8D251C0173C28C3C1B3CD1EE410F2ACBBDB18DFDCF33D6530C781CE00B7559B7A2AD1A37B9EC1A29306C60C6659982DA1E0ABD78F5167F202419AB0226A3E5393D9154A32CB428F1857866E6535FDA4E79644D2D9811AC0639FEBFD926F07AB45266F3EE9CBF5B5DC13E3301849DE423ABFD112A18EB3EA7181012A17AC0F2D3647C38B7E8EF511A6BF7C39A7A8D2B15D8FF995527D768014076BD3C04ED5309F81A03363479A7C4A704C38D6282522D9CB5CECF6485C0A3BE5E25FC9C66D5856E9946B02EA2FB3CD04B1B138880ACEDAD31698B4EA78A1848FE9A88FD43A9223A5A3C238BCF118F7105FCD0F7A32194FBA1A5FAB339C88646C28FE340A3960A5E743E48E9959272B4C5FE3ECCCC0A8424FA556A75326ECAD32EA7EAE8FC28A221EFB38818478F09020510B8EE10545C1928D34B57386C04ED7B57CBC327A08ED010B8EC5161A27D3938A1F51B8ABCC4CA53FFA110FEFA4D1A9C0D1791FD08FF93CC703BA46BC863975D4133E96389F6EAE6CC5947368E9755C1D4249DF67DF0DB2692EBFE547F44D70A857057BC402DAE21E8DE324B4723C9AB3B9E5348DB4F136AE5606D17D2F0385DB013DF81FEC26A6185A2A97127EA253CBEF907B4B1BFFA72C84AD848C3E628E14E6D07C6D28BD3C3727CD6E77FBD4EEB587426BA98C0EFB8B66D6FE0EDD88CE487478D89018FF7A8CFF9DED5ABFF5848C5F6BB702F595F5806D2833382E997C1D8104463D76CFB2A7D12B5DCA8AC2161DC674041787E5BBC1D21B42FE86A8B6FE4B4945AFCF1088BB16620C8C8BC9542F0950169EE13AA7B2D409188DECEB87D9A95B49522CF96291C185F4E7BFA29DF3CA7291CD8D876CBB017C96E7D621943D477442359BCCF913E498F34E8EFB6114D96928772CC00B091E9619CD7F869E25356FDE75529F5AEE0FC32CEA46A5DF2C0E5C2EAAEE54DC94A5879DDA8C653694F071D08377365569EBF8762D6D030DA0C12D69050103912D9D779F6409A91FE0EFAAF62017E7018D8A9A5B9EC25CAE60AFE000A36CE9C81CD8DBEF732DB13A09D5E5A65D763CC48C30941702321924C40736C0D1F7F4006476BBCA04A1E0D20522A50A5A809B9C1A1A9B03D59E4461C5B9BCBC3E4C3650136804AEA8AA55C1B2B1435D2D0469B5D6F010CB51725B864DDCE08ED2B874CB5E4242058DBE3D79503590FABE53AB2247949C13F10ADEEB02C059AF1DC4B74278B3735C29DE6C9E8A96AB4550BEBC238C9F9B76F94BC70CCD7B7A006F6F8474DE941730F699BB12F7AC129F64F9E0EE993AEDE6F127F124C117ED7C9F4EB0F1B32A30FAD5AA52DF671B43BB3D9C571443A968456A8A512E1E55F4F5CFCF7CA12B0E5840598BFCF739D573BFEBCC12CE756BF4C18B8FF3F214F26B5A8560F8946E064C0C6BFEA565B5E03196C1B88AB460F689AFE860D5F209D6DCA51547CD5A0546E44627FF6059979805B7E7F135392D1817AB9A71AA1328D3B3CE62B65BEDE368F4B94F96ACC923DDC8456707A092AA5A861B15B577F3B357C7A05BC95E0617E754208DA2C5BD733EECE2E2AE36043DAE2129E84358D8818F0913D175E8D747B977C26E6223D9272F02A4219316050134E548CD0AAAC2A40CD4A18CF4C59653575FE7BC5F9105AA0588BEE9642697D948F66692D954B941620B1C75E38BB8215492DAE2F3F0B8785736D7E36C1A4C0623E8BAF7299148927453B69C6BFD29554471E9C7110011E0CB03EAA86CB425A13F56886F4664BD315E433E23BBB3950F47A20BE0953CCB1B061B5AE357D89695C5EB2678AADA47E85D50DB2CCA2FCFC25D1B0B8AEF77F8807826B787DAAD98E65FE04F405E58BF9A3190C15239E413E3756818794D1A5150F7A01753A1838DDD591FC1B7693F9E509E0488439290C1B8CFDCA32AEACD3D1C523F79D71DC2970F31D09FB2FCEC1710A533ECBBAFB1B14780A8DE4AA96CC098EA3BBB627C7B1BE410B6102C46FDA68AD79F4200E89651B5D3BF420430940DA84FD1E44F3BEA4F32C373FA789FD149CB188D05BF45E87E4FF686BC7D174BC1BEBABDF86084503101D8E2DE84D976A96C803FD9FD0E4835FDD621D33B9B38A71AE8F4967D29B7318B042C500052BAFC46506DD861825BB0324BBA1111D8F7FA9F405D023AC6F73DA056E8C569278C69C3DA0873132C987A77E9DC0CBC78C18C7A7A31F4DDC0BA4D3D292D09724C77D86DA709D5C76F6CA64FE82DC3302F421AA076E03006D482205186DD5F2CC559F97AFA7B24ED4AEC51D0FF3B5D96847462464929E0B9C2017A91CADC5F5811B5CFCC4621794926BCB6CD08E68C8A2BE7112220A0E3444FA2B745A984BD504EC05B352C3FC105AFC554B59954237075FC0E9F36783DB0F9BDB0487FEDEC2B9B20BDB788A0E7B2A6197E459E6C767649FA8671454F1BFD4C968A332C0D37FF139F9AFE431ACD4189C113963542777EDF8F2137F9255A3A7A1CC959F7E5A2370A6CC027556B58BAFB7DFD7F19205D2162BC8E3F934C99245A22774FA43118BC96F61B17D4E5ACD3217AA6B79E7D17ABC2F62B96D6389568FED71B0D4EDF86D0CCAA06717A113BF8CD124043A1AD9F41E0A9E0B0B1ABC01585459B9C28B0269C0822605ACC2B6259A3B64214B3EF035F7EC3F59204E39A2B408F14C6F1BF6E34CF1B4A6BFFA4577CB85C3CE3994B1019D4F3FE54B21798EBD137284E6D403C304B86A941CA4428C75E5A522915F4E2E829EC58B3044BBA877CC7BFE1D28216C9720872CCAC70B44CBED4858490EA5EAA7DB5DDCB736229E360FC6F708AD4C862A2C7E9AE28BD8C19A97ED5759D83C7A89127361C941B54F214818E8713E156090F28B2ADBBBA31EF3BF22416B732A2E41D3977BA59FDF4594D407140AF0122A74E01BCA4C428ED7C5A430812C2F83B7A5C4BB3BC7467D9300EDF2E4411E4E1681A54F80C606FC48CD5B224C98FAE366967E8971A0496D022878942B65DA37315E4E25E154B9ABD2CC9F7D861F5BBBE416A917EBCC62398A9FC5C9C1F11276F1926EB6A975F1E529D3AE1E3C5B8284B27C5A82D82F580EE5CEE542596DA0D1C4862A29693C6FC60C50CA268BAB10BB5119B79A2E8335935FCDB8DDEBDC51969BE025DAE7C0FAAE34D2ACE2869FCC9F531FF5215FAF1F278CD01DDDD49653B6D6B005415354E76D911E57202718FC1D42CED82AC768B81C40F7991ABC3AB3EDC186F62A0FE81DFC58E17E81BAC4E1EB0C1A394451596B82AAC9F0F5151EFF313C63A9F634385868B9E02D3A4089D8ED00000000000000000000000000000000000612151A20266600000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 24 iteration(s) +mlen = 32 +msg = 3800000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = B17BADD5AA9343D1A5AD764F7AAE6B7A20D588E4A075849ACD08A3F52E41C305895BA94E249654A9EB6D5D1BABB83D2DC0B6C7B65E8A0CABD2E3460C81C4AAF118BDBE28054C2A3201CBE2F2FD432C02A73224AD9E35DCA777022D6B4108A9A78F3C5D8CD21443D618EEB319751359745E241073E20BFFEBDAD3C52485A1DADD6451F203A54B13AE35A962E287EA763DAA336623832298ED56C0C48CC16229D4B801F399DF149BA78AE9035B16713771C616439519067316B1CD14780D58CCAD2D71EA075DE02AA0C3D68E02036548FFA0AB142A12D6E1F269754EB0CDF508575BB86843422E69C216545170FFEAF015FF177330B8AD9BEE5C482F8FD333CC05D21DBFA7F4106AAF48C8094D956FBFD84BF3672A663EB2351F8E242930BB7FF29558DF029C1CDF7AFF3185BE194EFA1EB96074F57E0B0636FAAC04596A8FF28BFA4E698635A53ADCAE85C76BB4C25C9A1886D09C1708B43B765C296BBE0121177CE33D5DA85B3F41A2C21275898866C05CBA0854334C7F1F8C75102176CB886CFA461EC6A4C55BFB2D685EB9E604CB3ABBBFE3237B6D724EB3EBF050769BBE6F3D50D28626E3DBF4C009BCE530214C84E49477ACA9BF49C6D7C53302BB5DD6E72F1EE26ED64FBC07693D240B729026EA719742A4F903C0CA0106ED79951FCFA382C4B0C7D07BF4FABC99803260E82FB728F1B0F4612D6D8CB21A14AE77BBFE299615181D9EC1275D0022FB583BCFEAF81DF6E1624BAA703389E65A3EA3BAAB0BDA5462FEBDEB110B0473CDA2A4A9FCA096F4A68EE8FBE76136048176F8721AE6106BDB0F3AE310459D71ADD85A2444EB9479AF450CA4864E1EAF0D5BA04C872BEA6749560F570C67814884B1DBE5A87C505CE9B93F465F75C3E0A1AE3044D6F4E6CEFE05904AB90E5B9AFC485228DE76B6F3415DB1C311A41A55B13F0F0783ADD6BE3EA5EE68AB27FF34E2A1006B5DDB8938F5C08D05946CAC2EFD3EBCCFA654211D69A825773126E600693337A91A4A8777229E80F654F9F9A0F21E69D9A979890F8F3DE93CEADB0E4890C7D19701FD7C2F957DC7DA88910F31CC8D500AD68865477A66984C2CAF86B08C13B7CA3DE0B7545D41191F221C0C0DE6E176BE90690E2862DB31886B8B25503529FEB62593AA3D0C074271CBB8CE2385AA834294DE61209EA793FB766862CB12E12C6464385761209811A78960542DF923C5089FA3A103B2C0E2BF2EB3DE0D05A57A514B02A1EF539EA4C35FBA7FEC65888832088BAA38D5F1D7AE58DCEFEAAA24DE9D83C8D8ED481363BAFFFB1788DD36114A11377A7C871BDA3B5813B9D6632F289145906C335359BB3876A127D4DDB8C3883E022C3AC1C869815D13F06E195D246C2CB95DF4245E49A09C617B6088ECE00177C30E7A962D9ED55D38BE7E1880455F14913759597ACBE866770C7D28C704CAD764C547A750BEFAE3DD88910DA22D942B99503E0753053C95BC8B44843B556C396F9BA60CCCF48E4A3CD692BC4C5F989725D0F89924C63CCBE7702BB98DA76D442060A7946D00D195001428D30299CFCF807C7340A8681000D35DA9E2D74446A83C89B158770B31158CFB99391EBC79521AF25CDD2943D46D17A81A9D886AB68AFD3E2825BCD1E7FF30A788C9DB45D865AC8EA7AC65B5143C8910DD10380FA47CC2EA4114B4807E9860798E19C27CA856BA41D4866D393BF30AD5F40D9AAA712E8259315E4334940447E795EB293237781FC1D1E3AD79A21FAD18F2DBEE6F71FFBDCFCD1DB77C2C8D1A3868E8F36094F51864DE305783D39349B01CC26A0645B78809E2A59E761512635F455CD34C3A3CB0C416981FE2F85FB7E7A810138C9221371B126D85B63B6C96A5A5055E3AD48D54A85FA9D916478958543D114229568EEA61E57B67FE644C27355BC5CB5D8AF0A15727764751A6F13740F5181A8C134CF67B958EF7CDA612C40A1CDADA48C887587AF26D2D47D57C6B772A89F6312336E646894F20B1820FC6B217C8B9E08ED4FD9E104C3C7E10A9CADBFCC1FBA58A3E7FC84BAB6756685E17F37B7205716699479F403009C36A12ED48EED461EC83B45E94D48E50BE83231E16C4C9AA47A8EDAFCE1E39DFFFAB382922C42646F4B83B81CBF2FB84AFCA7A2756038CE1D4691E8FB062DCD8123F3FA358A5076C74F5FBDA1595E2F29C9167A42438F61290A12326D8D7CF9256DB109D5509A4FFA9F06A98D6F89CD77EE04A10BAF28933F31FF404673476F7759654E33083235B0B9E15022F2D7DBE40BB8C79C76DD60B9720C78A03D1CEA71FED43F4A207DC32594940D00A19594DACB610C0678FA9AE8CB5D99C55311AF7D121E017D960CE6D7450F0253217FF9CE9CA93EC2FC167BA4752CDA6DD5B7F00286EBDD4B02E17BA40962D03F9F1F6F1D5C0513B8E768CFB0A55DF7BAF0352D63933C99ECF5479A38E66E9748734A6D69BC6C62EEB8C0199877631EFEBCD0E82F36A50664104A2ACEAF10F99E73924B52E903CC9C8DF8870696A4894F44DB890C2DC5FB9CEB858D3424A6FF9FBA82847807A6E11914D500B1224DF23DCEF2AAECE0A6B44B0ADB6EDF276CCE4EBE77E96F705C03993A411D98C45F25A6DD793A4B630C1617AE4319926F00ED248B4C3889977F9FE83FCFBD587FDF07C75A3EE3880FB26EB6DD4BB01966F74B6B6212311779F5F11627CF98889E104967AB4B18CACF4CD202E5EC46508F0D8DF188EDD20DB49421B2B348684F336917A40B09EA1D6C4D931EDFA4E28908A61E8C367B221AD2D4814B0D85AFC99DE3967F3D6C90E9A975715E2CF403AFFF1EA9F0C207CEB40D3629067E79C7344053A08A69460ECAF5BE667AECC01BC045BE25AFE85416FA1E6B47FD6BE17DAF0A01004B0972420A3163B24A4FBBFA1B61F34380C1131B7C03382642A7030D7C17B845989C39DBEC16175740023F8969FEEC059CE37FE0B5652259BD4DF5526334A2E856CE57CEA75319CAD0A958C9D0B33E45920BD4D23427C44986FFF3045A51E2559D990190B82BB7321A1C3D1A0973E51C7ED50FC2B9D31E727DA677A0B29EAD8B81596D6417C6D62C79FD30E838FD08729323A35766839DCAC3597C76CCDF3E67D7835E7EA9184DC7BE8526E7D014AA26955757762EBD75C3BAB998B76DADAB816EBAC4B961C7084BB5B0D39DB09BCD46C8BD7D2CFD85D69786E14B7CA62D50B2CCB9E322E38D1F90D556B51DFBFD145346A664638DD30F48DB058F0843412ED47779169CF42BEA4656E5D4DCF9C4984476BD677AA6CDAEC9F4973E0933181C5EC98101259AFEADFC65D55805DE0B57E76FB38DAC3EF3544B776926637E8DDA46846FEDC0CF55C19645759CEA07B793D70A428BB654A9683E7DF56FE23B1F4C52494677EEE25B7FD9D0DA1CE33D39E58DA056B99E2A9265335498A80A873BE748658FC8C37841B45CC70E3A46B8335CF5DA9B0E51550355F42CD6AA1CAA3A55EF21ACD1C8143B8E0BFA68F81B06438EF9C24AA6005A77B4D9457A0B599C0F71EEA26B40AEBA5265EADD8A2BE1FCDDB318559DF9BBA95537D012DAA14356E3FCDBB7CF41870B96CA9EFBEFC758BFFC172DEDEFA450DD0E586C98783529DC44EA0778EFE30F8E5E4B349F6FC0417B7D1AB53E592C627B93C2E26A6C607A0F899BCAAD7761530BD1FF0D4997AA003A06AE940AD2994A2CDD9FBDB51B015BBE122BD333E54E1120C7BE813AD75D2504E61C75F4931CF5A725545DEA045A5FB768DC39CB9FD08D4658C31DAEADD27765D2FD47CADD1B8BC1C51969E1F140DE354708D69585E985047C73B139B79C2D1B646354FD9D7F94A0B791E429274CDCDC74FC1BF2B8EE29FAFDC54241AF82CF34BD471736FB8C3DB0819CE586DE4CBBF86C5BE138CCADAE85B20DE30AEC8219512061FC1C7688A78102D97DC9D7EEE91EF52F6024E475A02BE913ADC96106A0BFD503112B17C80F60D506A70F4589BD5172475941B36305905A51D340A7B49D884D4531E83277B2FB865DDF727A8E17453CBF785101A2DDD3818D12CCB709518B3D1534A980720162DDDD0703EA37111C67F81FEEDB854E8BB924158752E66D8213B24A7F37862F57737C0AB14E72A70B8E4AC673C15EF6D483B6ED1A70F265B8316B0E431971B7F2DF7CA94723F7FF874D153BEF275A72F26986353FD9405E6DAC84B4726C137CC0FD2BC03BEC0677EFC299A4862D9AEEF7103D1A19196A173AD9292198AD8D5C4335144156F17DB54FC30C230965428A556A7DDF2A6CC4FF960224E01A38A59F526741E3036A040249F58D6633509E4161C73629D1A749A534C444424A11B9205569AC69BBC1600D11062529B48A1140AA2088F914F428B390952490FE59B2C561088D364F01C8B3F7C1AD896330B117176AA1829FBE8FE82D9327A5D9B67FE81F3AF4D734EAAC7BCC2649E99139D9B32EF4713C0DE9FA3BDD2B4099EF3AC9DFC04D7E254E2F76E20D392AC638AF5721ABC161A9C28EDA6E9B63AEBA4A6B06F62E6CFF70B87A38B23885E38426E322EDA05166C3AB9659281AF5DD25D3763610E3B3FA37130453ECF73305F4A34CF29215A40D106B9C652D10E665C5175C3115F19E573D68383CA003712D0821E2429315A62707798E4113F5DAFB2031F394557787BB2BFE52668ABDDE5FE21313E8D61A8D1FF000000000000000000000000000000000A0F191F23273800000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 25 iteration(s) +mlen = 32 +msg = 2A01000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = BA8E0A490B8289BF91C6AD96670FF09AECC7C4FBC1063A0DA6E2C679B03DE134F67FD1106AB8147565657E569A4F90E8A5BFAF65792937778E3B177BEFF1F6337E8732DA0F5D6E68750311B8AFA490588A2C71344344D887EEC1B5828DAFB88020C91477E6B7AF11510E5431F4532365E4ABC72897C34D781F014E17DEAB35A4DE9138D8B1F8A374552C93988926EDDFC0D3251A7ED2F89E832F732871416BA82B6D8F94EAA946FF0B9F9D26603E50EE9415516240797E7690095F536CA54F7E320ACD8D4AE98C65F6EAF4DDF5A3C5F8BA25D1FC2ACA577BF2B9ADB6726F4C8FF84DA5340A5291B563484E402068E6D41F2A472B60F33E5EE1A13473C6CC829433F5FE344D6E8ED513445062F54175366BC245FD34E1A1F772EDA590EC392BE722CCA26C71593CEE8B65B181BF25547F6418D05ACCFC9C545FAC1FEC115B3790A99C99E02028DF2A5EB0457CC440EE925AC9C3E101E098A41F602A3B0F546E12CD16E0FCDF4DB9CF70C9016A209DEFFEF9A7ACA0A2531D3481614B11FB73BE650E5E98BC1FBF3F6797DC0EC864669E1E4B072F34B800F1AF615C1D64CF8DE2A3D0F634F6177C7E837911087C2D0E45A1A01F7F67066CC1B34B384EE1D6EDD22E63B45121A73E29FE66DDDFD2C24F5AF1F7AAB6CEA8EE81A8FEDAE51F12C11BFEE57BF20F3F4604F31220FB447D48D6C2919018318CE995C731DAA55B960721A58C88700608C37627872C764A1C9D1F310AFC72AA9C18E5C67C806B561ECE7D6C8BC888999DE43FE5E4D8B01AA40C66961CEC612AFA66B60B770C0F92CF9389A7ABC4B7E4055CCDA9D049EA4A9E7E203C866A360011DBA8DEA95242E1C81DB5E69B5A012AD44AF1D9D8554E12A6FD5490128FA45982EB3798909BAEE62451E0AE02B37BBB064302FA6B3058D99968E94058078EE8FC6B3EF89A0674AFECAEB14C219F9F30749D90D7E89EAA9EB3F96B8574B5B7AF292E5CC4CEFD7A7B3D9079A4E67E9FD5622C4FDFE065E88A1F31A0A189AE699CEC7349E7BFD4A9408E4854BA4C0AD7BA47A1D93C33E6ED2ED0C12BFCA59EACFF9BE53A1B7903E1372357ABCACB013BE6EB47F8FAEDAF1605280FDC91C170F3DCA54F38990F12BB9687ADD8B6C5FE5901FEDCA5568A37E5E7AF1061743A9182A04BC37513EE5B2D55A014A6F9E3B2CB62D298B9D5E726DE13B904EDE0ADC5ED335ABC95362C6975E868A64F5AAEACEF406C46896EFED331A93052FF3634EA438D2A91749BAEEF6F063E0464DD3EA3A48B0014F8361259B7A2E33B157DBAAC76DE53691FA602F03FB25AB9331AC0AC449A428F551374590E86BF9048FE36F8A37AEC825239DF432EFA544D294756B4B9937F202B8C25569F9BFD3CF43C95859E31237DDF39E7C0008C43262CE4CA1BFDFEA4F95AD8536D0F0C108815CF8BD516F3A1388C236F4D3DEC7E7E99CC8783E908FCA0048DA7D15CB2CF618A6074B936BF95BFB028B9C2278D70104D3A5126F09DAB4102A3E26101770C1BFB0D534165C611B25291830033764C9E0BEA382C1848FC5672D5B390CF439A7172295E4ECF786ED75A0F93093F80ECEAC98F6FF26D1C9AA64470AEC649A0658C03096B666E5DE22A9E5182DAAB4270E9593457AB62FF230F86BA093A66DD737EC1BA473C06E1D4DC533A6E8B33C1FACE7CB08114ABE9E2217CF738BCFA1E263D6486F89274BD7F3FD6281A91A1DFB1B99E29D4998A354FE92CA8ACDC5B354E7C3EBA062998F98E23FF2675C5BAC64E296E583B7484F7D9400A8C6667A26D1D597A451D3760FA91F298B490852AB9B1D26E16AAD64F366CDD36079B528CA18B213CE11798AAB5E054798E405D20B05AC450592AF93F82BE6C3B106266A0E2F98D31B09EB86851E1647A19165F1A3F57E1AF2D64AE70C16A37409443298F3F9E170D32599212E7365E7970E34DA4EAA5E77FA644D76E806A4C2523D547D18A90E147E403BD168D021C952904DD2E4391D9B19AA07268F202B8E69D440748ED3A6DEDFB1E5B61E2FE121D980508E3C64CC97F2FEC9FA2F39F4BC3BA08878A081E6E36471454A3EE2CA778DF0D06EB5CFD045A3FCC15795C09CD38143C08E8138F590D05D442C36314FC39B2DCE2AD003B56258A19872994A4D0D810D9DC5C0BCC1BEB1C5F2B6AE9C72E6D6C196D5CEBEBAD71DE697689F7DEDC9F3AF16BFD543B049AB8997FA73E6626E865263A28CDC8C9E3B475682434B19D0A13A491E4918E7BF8656FFEB8DB4D6ACA3E4C7B5289458670655EB1360B5440FF0736A2F58BC3363A37E50A0CEED384D0C0A55A440939818241C026775F5870F1EDC5CA2A0DA998200B7BE15ACC27433013D5A128CCEF8838662704079F63BFE547DF67FFBE209A3E6AF2DA62C80E771B863F992FBE15DFFF1EA5267CB37CA71F7629A618179327941CA4A864B4DFD7B4627690066A7152C0FEF3F500F433A4C54D411BC59CFAC9F1380A4806B04D524C7BB6B7B055F06E2751675D6FD1C3DBB520FF10DCC938F6AD19D577554B656C3643718DF6B72C96B998750EB9102979C58AC4C8A8D23265B8AB8E1BFB2EE40434216DDA64E539B6FB5CC349ED522EE02D393604BF04BF123192EBF131537A6CC1452DDD38F788AD8052FA5A2DA6D5D9C58D44241F403C617AA688E024C50A296189CBA610E031B45A1D6AEB0CC7C23854831B7632FCE1BF7AF1609AFD72800BE217EEC043E8BEAE8956A6FCC99160EE2F0A04403D59A056AF9127D5A8DEBA03723BBE6E14328704FC25630A147B687966FFEC6095D1169DB8F13A39D67A14A7CA574A6CD18F09632076CA53EF71110B818480AF18DBC9DCAEE1851CFB3FBB9D817D314A91DF1EDB4BAE5F36EF05DE9BCC049E672DC2920B392552C4AF73FB5C2DDB0715FA4D46E269931574ECE6C8B92FD5CCD4C33F6B128D34D8BB6D476D9A9E19576127822A0F9BDC2C2065563FC9567272D8BD1E5707AFF183C090ECA58FAEBB6162D04981AAAA6DAEEE847AEE541D04B1794AADDD68DA59A38882E29978FE8F3833D2EBB3E35CC0967C834EDC53689282BC9A7E74CA45EE044B2638690EBFF103CBC9810970E244F0AD42F0BA4A559D80F22957D246A2A6502DCD7E574D54E6C99C866BCF87F18133D0AEE33BF9FB4D851F4E65A6D278ECC89E8342CBA737BCDBF09BFB98500282DF602A99000A37DA8595B8950543D94EAD49E895436C3C5458EB4AC5D75F12079A4FDC7695497D8ABBF36F111919F395E99FC32D9E63B71D275AFE40FB39A88D9D2609C73BB75E9F0F5ECF209FC06F8C6233EB083A88358B4D84F97C75D15089D510384B5B31AC26DE5AD4D20464D36D085CAB2785FFC13186021890C8A9C003DCAF4F456A46D10A06C7B95821C12D96E797C686ED6E7484EF96AEE5A0BCF402FF7D59FED7CB621BB93620AD010E7ADF7CAE3582C8025E6C9F43A7D05DC8F0B165F54CCB2B9E0FAEE33DC008D5AB56E05DB1358E52EB21E5E04484962F2FDF56AA75DD7DEF24300A5F9649497FF9F2AF1AA15194B5B7B86AEF3AC88614329FF4CD249365A3D284E387066427F71F100BB2C58204C236C4D122FD6042DD3AAD7C56B3F48D263584EC2FFB6655560C50A0F1ED396213D85ADEA87CE1F5FF273746DF024C73A449DEFDA41F66BA1ABA7F14F5E2042637DD9EBB18A976D5565D1A5299513933A114C42BC440F5523FA066205D6674E99F14842F2FD552866565081E3F630002EAE82B8103575211BDB74A122AF28E061910261EB6D23256C132B32223970B63D71B8A8C975D9973B2B5CC9B5F27830C4F0C42BF05A3560541AE7C8D6674CDF31CE2660290F279169BCF2EB652C51705FBB27123CD14095DD10B2B966EC0B44B6E729957FAA7EBA3AF0D3BAADDAE47E48155238B0782A45EF4DC8EBE88F3BBE1BA2A7B2DC8E25BF285A808927FA1A7A4A7CCDEA5CEFB350E68D6107D9E2EB20D1B393DCC883F4D5247F36C124B072C42DCE7F455CCE4EB1DA17DE0DA3A801728B32429BB8207F59F46C8D0EE0E6D303E9E6F285A16F0DEBD408B2C29F90C668A412964D2722DE11349B04DAF131DA3E821BC9F0F294D1284B8EE097232449E147008B7A592140D148CB08C6DDE3B13AA3EE738BB1F2D9163EE36CD36E52EA81A339BA09FB6F5CD4B889F89854123AC5E11286676F4B98D159D15BEDF207A70408DA9443B8AA8CB7DD6241CF8CDB3F6EDC801F3A585692EDD0543683F82B1371308143B825121EBD6DC531F18A50E5CCDA7DDAC2F429553E0375A27F20C333FE0C401BA379950EA359617E4CC4A1CC0A2A2A6A0B2215012B4C9A4060FCD1CB2913D70B03B61C4C3B140FA143EEE9741558A7D7E94C4900FB04A746762C3A29A897C2F04DFA5608CD8FCF8A2052A994129485A575ABFF95E6E172CAC945A282E662B3F08CE81CCE600A30FAF8521856B4B73488413C87F684866B4F9D47C95C3B1DBCBD4191C98CA7751358349D21955D76172B855BE70D8E9884A086A2862417A5FD956818406B4EB89665C3859B806BEAE14642953D4AA708C4CE70D17B3D6294BDA94A262DA01AD271F0A51FBF4FB30D8DF2ED047A869266A97BBD27F1DB40AB40A85AC34F770CF62249E8A335866727F80C0D3DBF91B3F8F94B8BC098BC0C5C9E34973A7DCE1131F65699CC91D435991A0BD000000000000000000000000000000000A10161B21272A01000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 26 iteration(s) +mlen = 32 +msg = 6005000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = E2E3002901D6AE3DB8DC9D4E90095433BBC07465D4A3A5FEB1CF53753419B2C48CA1D58B6FCD6E92D98DAEB4674450D9B41D277BCA9B8035EBD230AF965B010F0AAA4093D336335C7840F480799F1CA5EC49E43E603506FB617CCFAF4F1D49F2BE15F524543351B672CADEA14C0FEE4F6E3CB1CB22E78DDA69420717C33711A01C2001F66BCAE1E453F24E15023E8055BF7422F59F7B9347B866E004131B8BBB48572BA22354AB24B4D210C57705F918DF669BAFA3453AB34C60AAAF4CC4FCE0E918A0C604A3938EF09D49903CD97D724A09F6B32615C7B50147384089685BED5BDAC66DFDCF5A9E50F04B4CCF7D15421DA6B3A63758FABF83EC088EDA2FE7C4C3BBA40CDB9AF7153369C3F679DCFAAAA36DF17BEF61591E73947EB5E20D53037B1131C9760AE2949153F78FE92C81269E323222F6259671E506176794963BF2EBD339372BADAC72952DB6F7682B4FFC48DE396A4F2E86880654CD7C896295CAD52BBB6F0E618FD18341D68B6136C9DBD384398A9FE189A71A030C1D933BC568FC4A1B39DC9450555A4A73C69CA1BC58FF64088675D0930B1ED616BF0CB0A3D1315F1F1B713BD9A96840468E43BFE87DBFE958A141BD307E16A91DAF0B8D7AB7232D42B937CB9AF60252AE21CBB4AAF67772AD7E9F3DD9F35FDBA81D4B23767E24FB5A47CCC22FFEE3711CE6F07BC5B2948321FA4C358D266078DA461C0088D8DC4E43ADFD37AE20C29C7BDD02D38DD215C55722DBB877C66F7E487E640402213248AA479B21A9AC1FCBCBC16DAA6DE93908B5CEC812FBCDE9A67735396285EDDAD434BEE205876AC352CB3D62983D8A0FDDFEA53673247FB35D6E0E38FFBFFC2BCB847CB6CAB648080901F95349A8B08A2F327041E8755FE9EE5545D1C7B780192088135ADE6614522CB5B761275C27B4614E1365CB4945A0D2D1C2A4F08275FDD3170E76E37FDF3C687B9F90CE3C4730A35C0BAB0E5969B57FD4700230CB5FF64C5D9F82B2368995680C1C11D078F645A5C169B568E123C2CEFB3813BB21CFEA05616E865A7190304643EF6B9FC0658645E46AB145C1E16EA1C1D18956A081162ECC2194A7D6708963AD838AFF77C735DAE24F9C5AC1B2B0E3918137153B4F62BC94A4D3C0783E83055DF250B88AF533D92216017F218720404D5DB528A9D7836DE0C5B6EA675BCE62634DDD5200F158B63144CAE98EE39FCFC9AA1AED5CD1E406EF5A137D70D1E78A76D184DD554C5FB692880F75BB5FC12125A95EE2FA55A711589BFFCD9E9D374A6E28A344E329D745BC897FEA71EC99BF0A31A1B829BE924794CD7E7593B87F1BC690FEC324ED5A8A9E1CEF5898932F9CF1FF448BBA8ADBE39D05CDC8F7A490FE4297ECB05D56581E74295C3DC34688DE4B35C2D8060A759E662819CF45E59DF5F020D3AC66A673F0E6CC8EC84B981D580CC83BEC3FD4831547E86B190D8D629C3A0A8E9F8D0B9BC49FA799664973C3E1F95EBE9B5563306488DF4F31921E7B9BB104A41B7BB07E6B4400EBF1C84B7EA14B3B4D46A07154F86C62B16967DD15B5008EBE9D9BC2EF4BA5E5CC36999DFB97277FF29053F323337201D16A943FE1941AB54AED4F553BF125D98DE6A9716ECDF140162EEC485C02DA4A0C46674821C557E1C447E513C0B2676E2D3957BF8682041D6B6C2A02C79ECF12D54E3314631F4CC43403B0151C7EAFCC95C1DC140215A8B1FB27FCFE6FF46E5D83697F825D0F052E2B3A78188B84EB1E286DCE32572C95CC35C6945DDBE266815BFFB85FA38B0AF0F4819A34F2DF093698FD99089C5B3867E4B5EA50B880F440C31D8AD04D39C410804572995AE993233FDB00A655B5E55A1299C4A09858D88C617BF2B96D4E2323753996FF05A03848BE0DC382A99EC92C5F6EEBEDCADA9F8AC1A24AA2123B14E2886F1BAE57630FCF89E25C3CABE32A0A5C04D2DAA13CEF7BA846D5F2673E0D4046CE0A764C44DE186C7CC8428C78F40F2E92D5BA339F70F6F1FB77FD4138E97291AA97DD73DEB714FFA54A149AE3CA1099221D0C4BCA018038EECEBF0B609D3A6EACF85C662424F8326B82A2CE40FABAB9B53BE8BA87B2AD87AE9D0D38E1345D8AECE7896503DE334437C9B813E7513E0BD3E09FB6CDCC884330E0A63CE8B1061588DBE1D8EC2D164EB4C1B558070F592952E5671B99767FC86F5A4D9B56690DA5AE97237DCB738C8601865D0701314B24F4566470B0DC28C2451E1FF6414EBDA864BFA8EDA434AB37FF1691A4EC593CF3C3E38877402FA7204C03961407F9307B0A94264E4FF6751BF0736BF0E32D4B1547C8A099B9155CEABC3F0F27FB51D9CFFF842ACFAFE98051ECA7B681A4AAC7FEC3B97C5FA2C92F13AA3E22118605C45691F81ACB1835C8ABC3E89C551248219E5AAC51C43260DEEF89272A3C35ED3DC484F3A5484ED323DC7A41B45FFA2174905DB7C9030729B27E92DF220F42497A5D409A6FED0CDACFED7DE66CBDB2E0DD65D0D89C452D14521F4AEE4E17AB30DCD8F5183E0F1BB2203EB5FC0F45073520E1B06DA4428E57FA91FA44583D70BA6718B0CF576C4BE5EB6181A2A84FFA5D7DB9056BCFF5125E6B64FABDD5BAB30AE6FFE546B62C93CE61960D49BAD02DC65CEE28E931D856E3F24B04ED0A434B9379314CF396EB10CDFB5FEF9CDB779CC1AC4A947A150514AA65EE6BF7C4ABC7D042AE8E1899B5891F80B219460D59D35BDC0A380C86AD868D6FCDA6AB267027DCB567D6215A100B74C9D77F05FC21C27CB98266421E6D8827624E7132B7EF54F78075AD8D54167C59D139D547ABD5A5BA0475F078DFC42A6942D28A9B3804866943DE2049E62406B6A754CFA87C5E4BDD75BFBA1C1DFE1AD116C8A5810C69450EA3FBC294D90C7759FC9723BE5CF62E90B971221E43B098C3F0C9DDB0549C75CBC9BE13140FC65989DDAEC1CE71F00B2C76522DB6D90A98B2921139C8D280B669C9481BB685D78ECA1FCA02CB98DD895859FF114B14A0B35D772ABB59B6F6634BBE0E8D7B578C35FCE04ED628F4CBC1B529A4A374900B7E3BAECED01361AC933AC3532E803B5C85E7FD5852041C026D48B753D35B429916670F27511A855F0312C3A156B80B7FA428AA7FEFD0D10EEF31EAD00447B1312DC107DA80208C9EF5BC49A469984B74EA7FD1BAD7404F3D5170166E74E3D5B1D5E6FD5CBA1D0E0D5170976F9DDDF4E8500E48AA267C1E5D53D2798DE27C6A2C1DF31FCCFB509C4540467B527031046E0BC000B3C65E371795CDF17928BF5A7D062B9F6B8DCD65ACBA1F0AB86E29B95E0A12B372E101582534C7E98842BFB446FEE6470E365A0350B949874B3D345C966E256F8A1AEAAF25DDE3A83390B3C52DE1829067BCC12CE9D962DCCE6D12E8D1350963D852D7A14ABB03E0AB0827FDEDC7F309B3E29CCE3B9F67A5402559D67561E6CF32FC6AB7406DB5E89EEE6FE75F41514DB151B71BBCE51B5B5665B374493D006DBD72F836B17D1C521631876392E516A53881CCE14B589D9A533035D5BFA515BA087FA30FB45696E73923F54B0CC7C44EA75E80DE04594A3F8727001658EA12718375B343423F6DAA62492C74925FF0481D6A8E1B525E8C00C3B63C54BF744F7817FFF2F9F18DB82321FC972E307BF7FC6FEF3D2BE42EE3FB4F8C92571DF5E15CBAD49A32A306CFCC7A70D929BFC3D2C46D9EF87C6B4156B6CA9E91F439D8F2157DF563064268C1FE032E12878A2CFCD232A0BFBA1AE9FE14A8038483B9473D21CB0C846AF238CB7AF51BF7D3B6CA841C3F3F28B322022CAE10C3466C88C3D188FA97357D69F0220D90BB6C3BB9EF624F6777F4067F5E207038ACB7FE72C9098BEDD7E08655C1919B509764D3B8839A928F9D3B93AAF3B422E00F79A5D027D6ECCD69423D49613C06027158EDE2FF7992F45C0CDBF67CE5FA4A64884D2C1E8797AE34DB79BBC1F27285EB15BD0D667F6A76D5E8B777DE699644646C3CB402537C44AA8B039391A0C4CFDCA2D7F9BB64F4C02516D31FFAC03008CCB55CE12E87D3D6FE363BEABA87566249AF79B4652C6D5123E081B0B44129EB790CC27837B193192EDCBA872D9C5A7F3CA134FF916DA058C90F3EFEBC6BD59C11B9BA3473276323949F55E5A3406471C12CE1FF2A105C22C5D2F12B8789A871827FD8B9628BC59B2320F9143CB13C9C2AC6620A1BE6F1E314374AA4A58C810C7FB292898B27FB5C7521C222C3B461092F8CCCCA1C930569035C0FC6A01A618AA9249E9317E1B1306F980170FC95458DB571779AEAAADD1A534F53658484791D17FEE5414C515912CE290D4E4F074B0A2C524C6AC4F095C7BFCFD30C8F17C4368E7E374AE30EE1D104B86438CE15B39A6DAA670C7380E5FC9EEA3A1CFA8213452BC1AD3924C4E44A8C9A5613CF116E646DC605BB8EB8179DCC0E4BF3C81AC3E43D35FDA25E97E9C5967264C6A55910EC9D2666AF2B347D77F87562B095B46BA0764AEB768A45947B9387B1D39490004AA5950D95E035C45C4C05B43AD9AD05F2CE64EFB5B75FFCA0AC868799171C8B2F9D6499700F194B4F800E97E449966DCA97173B9DD632EB254AFDA45AA6C0D1E7FC81CC39AF9DD16439AE9BBCC978F158CC9E850F1D1E6675A2CBDCF8496FECF40C292A6295CDCFFF0559639AEDF90C3A3D5A5F90B7BAD9F4FD203A576B70A6EA00000000000000000000090D151B262D6005000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 27 iteration(s) +mlen = 32 +msg = 0003000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 0DB5C5DD7972E157C32CD30DC3086C9DCB52A7B4BDFC1393ED1BBC9BC1B1BEADE5E981EC4CBCA547797438F0A25019DA9977EA631507AE1C92EF040B35245CBBDCC4299A7623B7434CF1C35C8E59CC8852523BEFC428B2FD42BEA79D19B1395F2A774A877CB7D388D4B83889A65A535001862FED286834D52887B42A4FA2926F5FDCDFD13C24B3373E65D1411EF71C7DE408B035D52FE8E8ED13A2094D006510794642A1591E08678FDF9DF4B82B406AF5A1C506E74D5FDCB8380497576258D176A7779E167A770FFF44566AB3EC828B61464302C66B5C0A9EE6D481F03A0CA64EAEEE11341EEC7AADC936759B835B55C18DE6EB66DDBBCAB480F7F3EABD7017327A28C17990B60E9B3743080A562A4C5DE191969003D8C6B9A30DB7938CA477085CA1E4361C3BC630A9FBDA7926E4D36DD9C15A170EA75CBCB62428EFA955DCE62B93DD026BF728231D2CE00C1C50457C4E06B726D7415619C2C12031EB9AFE95DA2C24FC65A7C1FCC6DF3F810B29BD3F709107D665FBEAE4C62FBF35EE38EBA3B8BAD38597FED3D69DE52C6D01C412F239015C7BB3A6DA5B9B22306FB33FAB50B07B186B31ADC79F4BB16110530653B86A498CE09A199DB2E3AEF76CC19F224DF606D20F5986CE46C88690474B4BCCEF3E1224508E48791E03311DCE6230DB6E8BABAA8FA12BF1090AEA9CAE50A43BB230C4712F5CAE06E21E7798BE877F13D6047C1E3FE1B3BB988E2A5888E79F3C08DA35E328C832D7C72A0DB3176FC7842CB5B41BC37CCEFC21F6121BA0692FD39EDB1ECB92427A0FE89EF8FC8829B1C29545D5ED0BAEAADE19CDC24B19BBC11AC4599AA4A28AA215AAC5806882ABFBDB72CBA5BA01C0F1B83B868A87FBC7594C14B9E2653FC8D0585C857B41EDBB9D306D2CFA368E01DA1E78EBC9ADA2FF235D90CE220EA489D6C088694437FD5907BF2EB4E0CB8EE0F4ABD86ED7E7E0C5DB3BF37487504CAC0562A8E23638F4346075848E8C1A8BE89B680BA84C03FE602CE3133B02BEFD0CDC524D271A4FE7C51AB3DD1318D12B3C4A73B748E9AE37ACC98C95DAF59A56263593E7F9D350CEAF82E3562977C503F8CD551AFF52AE4FE71D8922256384C0FB9F56FF3148CB34E984090AFC4D716DA8ED5AE77ADC21EC9DEAD3315ACD6D5AC20A930E1B7E6A79C3EE09FA8293A7FF1EDB125C138E3582F974E74E5189473A33E855AA48FBCB32E90C7E9438C6E7D9EFEB77F6C9AB2AE564B833C51A9C61A56599D041E55C3DBA4DA5464E7642101A7752C8B81BA2C531FF730A998D603A0044D6C2A632B741CD456EBE4E9B0AAECC0AC4C99E46CE29957ADA554E87F5E7E65E17007F3D976431B3AD5738BA5E535C8F6890CEF767A46F7256EC89C96AD432E1986DD7F81D98F11E88C4FA43BD2EBA95375D3E974429FC117B62A015AE28C1EF92C79F43E1E2E7E49A6F60EA80D9D24A7DFCC8252ED2A75029D07296CCB52C38AC66A83F7231DEDA2E0CFA143FF4384AE57E649700973064FDF5B127AF39B3810B3382F4D81A233C1AC4E4FF39FC8109377E73D3916F06CC66682551618CDA452B50029393C636031ACB12FEF3C903428EAFEE03A83A6F72FA2FBBC078FA99F910E4220B08554EC1918D946E62E6645B1BC155CC759CB8862BC3555700576D9292EFF47E04A5BAB53709FF24CA8C81093377C07816A7097207F4B8F0F7966AF0B89DEC150649648CD108C00A18621CF5488D3F3256BFA22CC23C49BE059DF96FF66D4C5756B6F79AA6375B718F2B2CFB794F108DB01F9EAE4B21CF6F4F9A997FD2BB62797FF8F449C484EAFC62DA8D6B00753B614AEF05FF5448D6111FBA45EB13435FE9AA1698D8A8DA391950C0CBCC3D6C3E966F2C132B8030BA274D22F5601D324CAFD1F9A6EF87059D9F7B3D0208041B27681ABFC309C1D0113BB1B2DAD16EE01522BEA4FCF271A4BEF428A7C66E237116A4A4310313403CD6596F7C8F94AC1818C3492428B1B0DC1EF747281BC9293D1EDDB357668D27673B7AEF728DA7E4DAADF21951C1D07430D672023414FCAF456DA7A39F594B773D5C7EA66A4F94595CA97EE3334D5825BE975B38BA856EC9526D911232D5638F493A393ABF42282827E67806D6CCBA59E3B7AC6880D077B3382032E51169A56081D90A24D85F5381FC76ABC3E520D5CD99650AA844347E0156B5F7F8D417CEE990C631C0EE587531B7399B73B328538FA226CDB3C35E8386B26C99E764F4D42C654B255CCDE7CB311C01DFEBECF018D459447577A8C5A3F9C4840CA26BA185B78209FB3FB51F237406406E005A4C419C76A5311C4F3646A214E19DEB1F07DFFDB653CA926EC3AFB27751F9665DDB1E152CDDBAC663406B4DC5552DAC580148835C6C8DBBE656F2B519603B19C7E79A69416544B4F99A6CA265150A1FB94D23E4F0CE270BF19E7B7829A90C80553CFED44650417F6CF91F038F9072E61554079031F706409E66139845CDD75E554B349EEC294A92CABA1BA6245623518F470D2D4424A967803238547DA575AF48AC4F5078D28A6611AFB29884D542DBD228EA97BB7C38F5F328829BE6BD24190DD8D80AAB57652E34D530B5771001C45807D17EF5C2C6F14BEDCC0116C942A98CC3BA5B5A57BBA8FE644B76725B945057330AE4C68A574E9AB3BD7A78476D3712745371FDDAA1871FB9756595E935BDBB6DF34F5A0D12803422191AF94EB54A6D0653D59437339389BAC5D4F8283B8997D6136C16659AB4FED4D2B484F2B6E7E64DB28EA40977CAE8E8BC3B2C009B55E6065E96B5BFC696875B9C3D7F3979CEF03E23ECD3067154AFBF04AC711C58A02CE1700155971DD8E86565070C04B1BDF2399D7180BE36C8A8BBF34B5F6AC1E9BF62FFFB52192D73295BF55FACAC86CA7CE7D3EECC32EEBCB71C29A19F53AB69D1B448A304958195AB32C8D7952455A4E1C25DE3BA91EA06E44AC83872C775F345F9AD3E691C1AFCDAC7CB0A077C7292AD5B4C010109644FA2515F9E501851EB250F69F5445BAA9D1C063A7CF6697978CE2C71AB8E6325EF2E70ACC2CE6DDE0B388F1D03A0AF212CD177BED9DCD00FD381559444F563AF6705A0FD42E40A969298B8D52271852E57A5545B410FFC4BC9AF5E518780056D329CFAA31B1AFA41199D76FDC4E44B98F9FB2FDA61ECA42D7741A163D30298040F9D27899DC8771B020827E31D60814C8B4D544F77BF67CBAF21E79A3C95070D1A57B622C56380AE8B6FD5CB5148BA9B495F96689A508554E2BB4986C185482FFB9EE590CAA69F4E41E68E542F7BA0AC15C9C5173533083715A60A72FD46288BBC5EBA4E4BF9EE8BDCBFEB5CD493A6B995F4F6B99A5432CE7BE0F3940D27C49604FB9CFC52FD706E0B777A7049BDC719E42E4FBF3ACBD934BC62D7F8980539D4D08EA99F1ECC876FCD7484607A95013458C6D5BF14BF3EE6E833870A044BBE004BA20833A7941316AFEEABD4715F34FAB6BC66BDC1079FCF98819EAACA614CAF43507BC94A3FA63CB002938C68D98E898F8CF244CCA23D703AEDE9A6E6D183C43A13FC677CB647956CA775ED2C38FAA629D04E4E5774FE2752FA4E9EE2B257D665E1C1E968304EBA5AE3D0A87B466A069C8D4D46C2FFFD76AFC2E8BB60C0AFCD232C4AC56F43738B3DA46578287D970C7F8959A0F820ECDECB6A38637E415B00F002868593061043D58A8FA42A237B61E3351BB24942C7039769A8B7F8193BB98342B621AAEAA00DCEC721FAE25C9D1C5D4AD57A4D2E473DFA21170E38A969792AB4C1FCAD4B2E5D52269EE988941923B1A8DB3D190B7CF2AA92F5E5AC3DBED2369913B3EFFD225841EDD269A06DF4F73C3E85E56C69E54B125E8BD2FD79191A6F43C6D9238F3A5D9A36BEF70EE38E016A36FC3CC07A94A63110086EC0143A8DEB67438E4D16242AD8D6133D01F6962E6C2F84AFBA07D51DC2E65D6BBB6205E0871751A2204611986F4740B2931EE47C1AA8AA20C1CCAE2F5566F87F89C12A18D4D74BD5A06B98973E4434489D48C7E2B8996C40D5CC63B3BAE199E8E3FDD30C3C68092FDEFAAB10FC1D028453B77ECC529484F61D6F5A141A1E5710FACA6E1DA5BA60FB98EC8371831FB846DFE7D52AF0A60B185E27048E7DFF00B7AFA61C710A7C33B6663952399EEC31D4BBA9A15709CFEA40C2DFD6A100884EBAC62BAEF2016AFD1BC22ADFA6213AE54BD0CA929350D36EC46474AA524187A34578C60F1E7752CB29F3F4EF42EDBB15C78AFC63CEF839DC5B44695206A8AB6D54288E998316FFB13C8D41A1259188844B3DD5BEF5EB0AE641B9868216F65DC2A64747EEA9005B7BC07BCF98DA6B5F93588A5F9B609404EB9BF2712412F112EA7ACA8A6FF40BC3EEDBD350050483C1331006EA15F35CFCE2E153C1DC4AAA5093D9813D4461C72F27C3F3490B49190CEDF04DDE769D111B18B49D688093354EFDC7A5EB3CEB10458E766788D379903AF5FC321A7F6D777C694D41F1E3BCD7BA1DAA4AB25E4A66EC3843B08196E36C27DFA03F4CDDDC6A0E8114C1A5D4C44100B829817D770DF24C4F10EBF53C21410B0C33008D907B795ECDC38B308943A4D3F93D5DE38024D09E446D8B75B35F110BCCF066E363A7B90119212C44526011163D898FAACE013E99B3B9BBD5D7DC27324E687EDD282A3F80AAC0D0F5000000000000000000000000000000030A111A20280003000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 28 iteration(s) +mlen = 32 +msg = 8303000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 1BC9C862B16DF16D48180EBB9AFD2ED72A1A420BA312090039F5DA0D4FF270596D4C762F8D3DCE5D949DCED4CFA18F548937167D4D69D5B13BC4F7706B5E15A87B389E44CBACDCC955190AC44465DAE66DE9379AAE42AB771592E5270A0723B7AE57235ED09AF780C861B0B440EE5B88E396FE3BEA23F76FC714F9DEA39160610DC75414158299D59B52A10ACA0431FE1F322FE46492087C0235F3BC4863A7B83C2A4A72AA0FCF2A1221D4DF1169FCED3C75D7699ABE3287ACA2686539D705BDD7A0A4CA4391AD5C68C5D17B417DB850329C7A00973E0D46478309895762C8B829023153DCAAF7FA4F04D696C6946C991C21D9A1BFC00B96998049EA15D9ACEC52BF416E54F6FC28B1E9A3B5ADD96AA52431F1D361ABA4AEC723303BC351CEE44830AE4C16D7EDA53F418D868E59534CFFD23B88A982F53CE90380B4F9063D04AE820D1D10A57B523A62C023EDA78894785D3F462AF9A3A28222B99552519B64337FEF4067444D3520F088813A13089CCDF1E44A8A57F88D76B414351961402BAA4D717BF0F992384FE1683DF9C3DF07D53ECBE76A21C4FE175E25902739637F4CD16727405493976A4C196DA0FD1E469ADB8CD0C3DE4E3F9A47653BA8436448F62EA2F2356E0A9857CBB748FCEB355AE43C6B9B2A27B5798E86A0EF51924EB1FF2AC7158594D7D2983955FA2B613458A18B957E7D6617381C03D2C20047A781379C0C0B6061AF041E1F55B3963B7FB76D83142A9BC4CEB6131CD232EA0B173CD9141A36C1B8956D4AA2574B3815E35E2D8970D495C66A599F347AEF6139C6AF132BE62D2F8EB4574CA209CA18E9072A3C988748F4D39405D1FB617613F665D15CE0B744AFA4093D2C6D3AC6AB7F5F520E29B0B6817D7C7A76BEBBB7577A48D2405AFE79334A56772B88560667D46D0698EAC1F0483DF4671AA236876A58D15D2E14A17B65E07E5ED03E9496CD5492B08BBB5699558908120AE9204B2E3DEDB83F9BE70EE102EE84AD42A0352DDF68E86BB44343E6B6D2185A7A4DDB3744C2FB5DE2AD7ADE6414C85B684F1486C3854834B34ABB1EE199DEAEBFB9314F69ED1A2BCEA581998F474E315259F62502D54C2AEA54F4ECE5A8D8F298BFE609E7D5CFC082BA187DDEABFAE7A58D83A240E49068D02DC36EC4D76340866B617EBFA1B85DDADAE12D08D0A6BF905D3CE11F172EC74FD755B37C2DBE13DA614C6A732F44C24404B1C9ABEC1000956E1A630CD3389372D8A76616DF2714FAEE5D5AD754143A530B02C7A26DB883683B13E847AC2CCC99C7F8BF383AF93EF7B92FE780E1EBD4B1CAE4740C20FE7C5760727436946A0F91E72585819D988735945B19DC925BDE22F52DD32B882E71052DCA1EB39C8C4E9C169B58D4BBDF5CDE68581087F1CEB128C15618EF43F6BC4011C17892F35A10A78139B1B988D4B526EE4513356E280E390921A093DA926D9C742AC710A6FEDD23D616BCAEDED70BF84151CB66A69F09E6834621E78AB217E2EFFE52D6708EF7F1B4343B6C76263967D7BABCBF7A6850673237243E4D83C5DF43007D184F7CE4AF6498E0EA73BD32E2EEC046CE175B0062653A8EC704A5991FE2BCF8EFA6898099135814D813844CA2D6140A98AB4C95AE9D6A5121E252014FD9C9E887FE251774EDDAEDB8CE3681669ADDA972BD7A1D16A52AD6AD19E4FF02D486E386E0C2CA3157A3A666BFB4D407008C03F52219E2649D962EB7C15346B0ABA2815CD67CA360A4D168E5ED9BCD2EE60498928A9D00D7CDE750D85844C82926AF0F50808CE3EA5E80DCC6823DE71F05C171030BF13D93A04F1C156E66CA8D22B5DBBE8B44DDCAAB9CCBF826231F55ADE99412AB6ED7AAA35CB12A944536E1BD36C10D8181FC89D09F84BFDA2D8DE32C935FAA02E267A3FBB6E8C3A44A5CA166EEB2788F691E63518198DB0B4D030F85A2E38EC7F4E8D7D9A0D1B7EED1139FA8EAAD17AD2AD00F15CCC09C715AA7EE5A703291276EECC0F4209077AA32EB970B73AC3C615DEFEF689FEEE8895912DFAC4611D6B834A96B3B9BFF1538E07D88936723B6F4A39CE7C4A679078D634C92B8E9F349F203711940A576FCE501C3870A3DD4FAC09E5C8BA03A114EBD09651D5096A20AE52F0BDCED915D6C8F7C7A23B8C2D4F79FC38B5A78DEA3B628C40889A4B065E38387F260311F36F4B1FEFDCBDFF02CAD18CAE8995B3094BBC51A96F51F638AF9C299BD79AC084A13B307FAF13D68F3140140C6C3A9C8CEEC7B65EA92A9A5E5B7B8D5D3D1F5CF48D7F42C022AC7CFD77DEF0F0998BC46EFFB4FD69A1BAA6ABADAE10567E9A4B685778DA34EA1EDE2529984EF8F6336CC07ACF730B05014054856799540D0269A2E8270465137000A47981F92A07FC202807DB5F3983136777B6B61D3AED5BB093A2A6E18A7B4C64F9F0FB9D920B3F7558E4C09D62AE690435732B244104DD0E713621A4F001D2DF4B1323A1C826B469E3DEBAF80CF753A7163C069AA4FF1837E33925B4C9AE10D8B19BA9A807E8CF6050B0F3F9AB2959F576235704622131ACCCAD1B607FBDE6DCFA840E6B0656D6EB62151719E082A3204E76B11B0F583D07CB784710F654E9FDD8E9A0ED42884ED99B7CE601FB19795AD3ADFE936941D14952624AD6E75D675A1343A2D4F0EF56EA19291F6308DB666FF5AD0BB73701442F1863FE7E82A29FC670DE6019B93CB233E7D744DE7571D02E85BD5C50304B2760840F6A4838DC0D0780725988FD52657769E22769188236269BDCD6C89FC3916AEE8B04435799F5E74FE7E986CF31CB263A77C2B69DDB452BF3C697E0CFE9756E7BFADBAD40E99B7420C07B7540CD1B48036ED3096715EEBB356E0EB59DF6A9340780068A269ED91FBAD22F204DE5C9F2EF819EEBE6FBBD4BB2BB6C77AE1219DECD680D933DD15720481E76E38695C0A1A93B17F90F32D53A1A89124EBB7B686C0A96B7176B913D39F374987B8BEC493D80B75909788BFA389A9E5B546F46BF921CA4CDD91ADFEC87A91AB66D71F92FAE2644876AF07DF0EC3A5CAC2C4D62D97DE6F9B584F6F8A889B0EE4E2A2143A4566126C9A25E3E4C5B4B4B92C8F38E7B20F26AC5FB0ADDDF50FD597A9202DDE1CD8B8DBF1FCF3DFB6CFB3B7FBA249E94FA6DD61D7C03D5F8D010E897AE69307E3382E275698C6A9D8D728DE78FE754C5771E25E92997D4EEDEC79B7BEB3C0FA871E5A2EB6F0729E33C724F4BABF5782D42033C75959CB9F4C37099D1CAD2560C1A4ED049AB586CDC43C368CB45CB73E504F491B0EE3646FCDA7B210CEB531FB426BED577E4D468D4D18BE91C6F0FA2B1D13427EE6BA551E77930FAB959643C3A4E195E61893A8098658B16D549859CE4233C699A6B18021B33237712795696D78ABD6C3F180F6A476DED3720158B4EF011D33E2601D458769CEFB14C36EFF46C32C5E47DAE1967C46BC82BAE8AE6EABEB831CF7569344E3ADB76715FDE48084581BBCF6CC736277B28BF258B8EB7E431F972F5B299108B3CD74249D97D6B95DDE7F94CC9280FF1689E2905696301B81799BD721670C88497B0140EA8AAD1A853780341F2936CDC3D39375567866D9C255EDF95A3A935475EE0C35E81DCB138B996F33F5295CEC3BC9B94AF55852BB70330ED6545C3C6A6382AADF25BFE8A34D117C5F655C1DA99A87D21B131AC3A909D80C63922EFBD0ED2B72E8FD2E9150415C6D054AA609F45C1033A37528B64A5993F749651370C631A429E96FA141EE220ED3E7A70665ADA077C3DCB8C1B302AD671A2A67FBFB350B8CE3517C64B90C6D434923CB33F9C5C7A18436A41BDC9BD792BDDCEC9EE1D27CE4F20B4841A01486224C8C8EEB0AE875DF92896F82A67A584F6BA1A4C71000EB549C00206D41415C16479740D18089E910A14281B435A0D014C7CFEACECB8499543B4D5709C6EFFB16C0F947206D1E06DFFD344E98A3BE9133CA6462DC7CFA364DEFF631E9169CBEE3B79859F4951C3E2267C6DE922C1EF4BA4EB3491B4493397DF97B1A9B89384E492E542DE2511096DA0930B360B92CD7B62142BFBA4F8D7B6E7EB3B234BF50A2760545EDE546CAA7B5A020AA92BCA66C909D819385F98AFB19D56946C6BAE17BD9DC2D1D9AA51C1CF1ACC9F03E04790BE9E0C1585D75BFF0AE21B917CADFBC33FD5AACE13A49572DE0A9CC50C6BC2D7FEB28DB6AE4B362B3A23277D6A01575A9646A48FBD18CCB190C0490CB6B038638FB962B3C159A542BBB6ECE365365B93516D0B5F5970D82DE06C397E22001F41E96260A389BB1ED2D8D76C9851A7CC1A3FA3D4D98EABBBB679CD952D94770BFA76F283170110BFC719872C32D79C18BCB7457CF85E880C5BEF6CB0356F7FB2C5F190982FFE0BF6C5CD92861F3FD8175620B232C084AF4EA68D40C18408BECA2DC96CC02B11B07C5123215FDB152C1801D5532069BBD3898D2181BC00F0517995F4D5EE6CCD4376C346C6D6DF6C3B9C3A8EDE9459F24A5680DFFA2399EB279A366034EB0C7CF6F551B0E37BDD5D3F3595B9012F685BD2F67AA490665C81DFA5EA3B7E340D55CA7C4102AFE9D12BBE8EE075B8DBA97C9CD30FB8455000E98BFDB83F7FDF96C3A9DB7B23C4FD7F83E490C0F5B5E77ECF9166075DCF92E3950578EB024528C93959D9EB1BFDBE8025D6E94A0A2AACAE8EEF1071A21305E606D7478CDE0E3F30000070C121D28358303000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 29 iteration(s) +mlen = 32 +msg = F501000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 8C253CDEBB1BA5796F440D3D2AB09CB0498B8EF4BCE107D8662022FCF322ABF787D74530CEAC9E7B0D923CF8396F6154DA88C9E566EFDB82BF5C65E73E0D663022B737130269347938878E233DB8A375232AE2C335DFC9AA8D1176A02D61CDB8574952FD5358F9628F03AFC9FDF6AE1C80E80ADAE06F5E8E327891F984C1C657306FC4890356861D69F07E06DDE87D05FCF9603F83DEBB6071687931F168CF34EE9CF0A4098B2A267D7B221C87AB8A39B5A1A624006BB96EEBC8D4D1244F9FF9E3CDCEF6745206D52524DBD6AFDF90BA7987CE8DA6322644380BB4C7F226E53DAE556683A43C2FAAD7D4A37074FEF5BF7D9466DC56ECBA6647468ECF92DF324C8B1FADE1240D39B9098A06FB33C4D201D7B501C82F5C4B29C17A3882EF2B10A3BDA10DCA0B0A7797A00E72B50822A3020DC1CA4458D1D80997D3BFE31CB4D3D6B20A17FA901BE64602AA79B0773070C57A2B263C11153FCBD3AAC5B12931D307C9FD9431566D7D07AE6FACDF8565E4EEF6FFC3B03A4C27A3C807C9653846029BFB6F3A99E08B5DFBABBF3A170F5236E8E7A76971A27C462B4CE370BD8E0FD33645304BED23C7DA17EF045F587BB90373218A767A7B5189A121DAA38EB1F45140957F7F6B90102AAB9031AA0F2CBF58F5C9E19160A2D52F93B0901C715B29DFFFBBC8C4FA8787A28DD0D90B35D87A022F3686486ACE972AE6E0E686478C7F6E96F250D60EA023329140A4CBBD2C79BF1DE5CAC656A2F1DB70D3A9FF56C84959AB72BB0F228C42328B08933771F7B5CA46C3195B70F86BF702EEFF671736973403E50A17B10E1598C8A53869B81D1102973030251D6D339474D579969D44A33044CDBA3D99CDD8287A6FD9DE987BD233CD056B4E214CF5EB893024FD75E4402D97AC80F753A127E67E1EEE717E3F0940763CBEFFBED94D8065B65755C2BF2C17ED323CDAEE4678E8D188AFA18FC17CDF12C82772FB6BE3032A47B156AB4281EE0F7C8604B6F53C8936BE92D09399F43369944E9113A435B351A4F9649EBF5BF42634413FC8135D0C0D21A2C2869280CE9CCA7A7E13B387A0D9CC9B60C622994A02BEF55C4DCF0F3583388B7D84ACC7E75D208B1886772296FDC6E03E538B48D7750518557E1BD161AACADB98A702DB7C91FEF6FFCA244DDE2957DFE1E35FCB8D0604C953A9C4FD6B4870121EF58D2F98C66EC1DBD608C46B6E38D6535750DC6AF9CE628EAD48A53F64C5F9A6AB9F9D92E922DDADBE58C5BA6E3A57527514ADFCEF0C60F125CCEA8B5DF9229AC325328BD761E03D03FA541913846962C50CC801731EF4EA39A1E730DE15C7E10C9B03D8ADF15EEA6E54D179CC90D090F04A665E8DDD67F29FF265784C61D98A2FB74C0B5916A00DA89FDE2250A44C6065A270634B259F40A240E857487D4B976E953364D614B4A32DCAF907E69303F0DB3B3DA6F958F6336FE0D70F49DDFF907D2C6F2306BBBD26BF8C1D0EE8512CD671D1D9313C75DD1827157B9797D2836F6C89AC85683FA6B321CDBF5DFCD5F5F5F3C2C191002BD07F1DBB6C502CC97554D44DBEC0BC0615059477B6679A03DF31C8636399BE38E068DF1387B9E8A36101E3B2CA1438E0DB16B7541241832AEAC355B00C70A47413A0CF10572DC69E809D0B5D1960B3CE789D94396A2B91CEAC18D1296EFB98A7872A95656123B4CB94B106FF602C371FABC57CD99A2D76B75EE1FE813BE4DFB099894B9E01D824AAD6491495DC12FCD6C63D73CDDFE8CF89CA3BB45745EE697F69CB0696E2CE96DD71CEE0060518A55772B93C8D3B9F430276477280E72EF2CD29780C706AE7577439DB3BBE329CDA8F4699EBD1D60448AE1D60B6F473B94B341188016CA5B59DA8A0BADD45626754635B65602291A70E25900BEB414487C2B73F591D2E55AA4F8D498747523AFBDA08AA146611C6260D1CE595B97FF7FE4D36440DDA592EE5785399799B1D1A1F1EC6F62B9BBE5C862F03B6D30A03D3B291031FEAC23CC92AE7F2F3C683E702891F5A1850EF566324CD340D7F48FE748DDC234FD0232B9258E55AE80E16ACE20A8E02112CBBA0C1DA90CAD25B13B3DE3459ABAF495C6E547B67E5B93DA9A538F19759BEC1A32AFAC1362EC437324B65D0DC2584749183C0707C83CCF840263F75D0FA27BCFC88AD905E480878DC64B1DAFD0DFDE7826C824F8AF0DA8B6A86E2EF465F04039A54694CD12C2F9B741B8D560EC0B9F3543EDD978778888FCD0A2F4299F7444C9D7CA48A41BD170AE0BB468A9B2ABE7F50688ED04CCFB4E382A7E287893309B9CEA35EB198BB5898D8A28E63B39151715749E4CE70F07BC1B19995676BA357B0BF5716038CF7195E50FF7FD6B6F0D9B2779C250B5FE7FCC64664E410D5ABEE8240D8C4541D01863AFA7317B617E293292A3BBB4ED6E7BEB5638A84156AC6E99C0D46FC05A261695AA7640CD8521AD7899AF6B58BD45CCDF21B1083EDFE8573495E866DEE9EA454301FB920D54E8FDC71248CA41F23C2923EA7E88C21C2F5407FA1632ED1B6D6DD708363718C1F0246B33E822A41E54E255627F8C25AB671E90264B9179D217BB2A3FB00A985CFD7EBA959BCA17F68900AF1316A16ABC929FF5B9FF30B0D4BF32672A04B1671B2191571CC57665050E3D37602D161A7C830DB43A4A244C5FC9929D3B55815E25D2B53F46E56109A0C3545D156DA8C6959B610B028E62F89AB57F0BD6CC71023F7D5311FD688BD08185F6A21985785C7CADE83B64703DD2167B6C31795A37BD306F0F8D964C004034A6F7F5631364E0684371FEFB6C4DC93857E68CB9A07F0039C1CDEB76264CA83D716B5F6B169863B6F4FE89DE74371D117C0766D5733BF6D9B8CFE923ECB9CAA8B6875C34AA48CFC67E9B19CF88C8904F4B99396D3772268EE88FA0C4A5EC855E196E977B6299ED1BA98AF54F6FE5209595DFF4111EE880F4EB623399E0F8BD5C795BAF558699CAE469AF914DECD453DEF58DBC5FB25D701E7724E26F441C884B215949FC909F9B082EAA85221B85707EDEE7C013F08A8F734A78AFEDA72E76C43F79DE08543B2EC20940604F3FB8C909D1468843E3E725D3F9AA29A8066D827CEB5D9ECB395D73894C8A339C6C3B6C767D50FCEEEF8B86C0EE5539DE7F1FFAB4FA24D24F133026A48E97128FBD133E1267552382F81416EACBBF4336856D01464118EC7624DFE21D3D4C2909A0EAB355D91F87F6FC1296C47DF1D57DBEC8E0DB94386429D0B0F9D59D01CA6EE187C9BA564EFF5BB599FA587D5978CBFF76A172A19CCCCD6A2967C67153E2CF9C15D3E56DA95BB71E6EFB0083DB1E1A6BDB566B06BBC3022D0CC6308161D8A5E2F81D3B883ABA02804106412BB7CE257532654220496E6DD8AA2F8101E8BE2DC64225E54D30083AF043BC7085782EA0B1E99EB7128A453B9D1BFC4D4BD78091FBCEA849CF2E2B0B7C5909ED7BD94524A58B8D56FE87207CAE9817039A4681C429B19EAEFF4DCF8D6D75CB7C058687CE6E27A9631D39C4D5DFA73119871D8B91E59C677102C25A55C6349F6165593945C51101A1F939E6975F77C89853B6074CFAD9BC7AF620E9D1D2B869502DEF1E697988425DD079727BF160307F5E04551D5E97B291A345C3E3AB0AA7EBA4483A43B35F34A9F3AFC41D525F83C5387FD78AE8B629C4923674860C74DA16DC10123B2A44BF339187F389A89FD75418DC5624E1A4AB48FDCF1F389C8A5A9B7B52CD987BDFD9C7596AC3123889577AD6BF4318987F65A41AD8AF55EC5DDCC5E1CF5DE31BC94BC3BF214D2CCAD36042EC2E36FE79218D4DBDFBE6A6A4FBC6693319BD7FAB023D22EDF401D297D2676D134894B68B970ABD4F0C9105A31A4F8375359950D2AB59B018BAB399994537BE6545CC79B2EC9FAE0084CDF47D0E08D7E5BCDB35C78A63AF8D92FBFD760CE8979CCD7BB7A0A70A1E4DD77656DD7D3EF1E77EDD2E17E0992AFC5E4894295F3CC2C19C5058A95FCF33894710BD8A891F637CB55885EEFB0CBD6B3224D23CD5766E054D7DC87B50797A9F6A8E018E8EFAB48D5B7B70C73A5EE62EFAFC2E2EC2D9A5019AD54188F5C3579BB882B60C738CC149D743D6CDF0320BBEBABD420F50D894904E0FF55813838AE5F5D46743A61A64ABF1B4349A72892E245A6E744D8B4DC3E9C13A1C5C14BF0C6FDEC64E8F372F570B038C4B321BE6AB1FDEEC3FBED0105F77D13450EAF4BAFBEA36FDFFCBC18AC309D4467CE56FF7B0D49810865C95BBE564F16DA1EF783196C541A89396F44E09F5574264271CA5A1306BC1B46BEAC94F05E6C0E1446657849B8402BA61D1473BE762C4414517181944336F240C0963FC41538F9791ECDDB0CA90A862DC71F215B1B1898FD4B4D26F66BDB1D47E9AF059A2CDCF03FD6218422E2F143BF6B69DC5B4C9D1C313C30993D9EFA1C9FE23D9DEB38851605D062656F21DC39B95E8752C054A54F0E43DC9F0D44AA195F3408DF5F33B62FFA3A305B272EE4E72D29B9AD0F3C09481B208DFB3265218223A5A13F71C64E661233A0052839AE36A3402167D0553728B3BE519A043D16D3BC54AD1C0775CD1C290C593A7D31D938C1FAC92B45ABDF1EAE7B0BCD55B6FF0554E79941A808223B516C757C87888DA8C4D2DAEF2663D2D3D6DEEDF64DA1AFB4E505326166A11A3A475C7896B1BDD5D9F4FB167BACFD0000000000000F171C212D31F501000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 30 iteration(s) +mlen = 32 +msg = 1710000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 2C85FCDBFAC8E5ADC031CF1EB284833D0359C84BFAE3996C50FD75D3C2CDC4BC57C7BF72C2D23FE22B41DEC00949E828824F7B9725D473FE934BD374CFB1B27A790D21647EFDF916D65E90BB6F8371050005D23C3F2C31DA7B14A3BE22457686594AD526E0B09B8F92DE2B1A00C0A4FE4A7217680821C7ADC0F62FA3AF98B3278A1E0CF7EA351332F891E57FDD51965663F20D6D96AD7D8053CCE022DFF296346442D19359CB24C726BA6C6A61E36231FEDEF753980861A11270AE043713C0865683516D854D5F375D694B147A23767A14CA4C57FA3E66F29578410D104C5DEC4AC0F55D0928B435565481ECFC12DE265AA89910AFA4C7C265E32FA3EB9783B01904F71D3C3B9405F70A794E04077A3C94301BB75FCE0FA263098BA425E0223AB1B74FF1B1360D744316036DEC6531D29C1448176EA8102389704AF4C496DD85FC9205687DA8F65B3F4596B79BE1D8816BDD059F353A94F6D35EFC1B8D3E3D57A6BA56D6B872F3A6C082F5633885577448003FBF56C1F19DC84ABB9B292E45FD8F291B37947411ABEB9DF1D7804F964538CA438D5B3BF27FF6BD9F3D9237DB5F0EC1855F7AE6666BAC62E6171DDEC86C1AFB4B90F0BF897C0F244BFD4E08B4AC11A911871D94879C4D8DF68EC52E01DE4896FB0F7B88DAE0DD257281CB9DB2C78DE846207EF1DFEBD66A8140E1E5C8D7279CD3B18BB89E0FC7DF4BA54D84B73795298F41403C177707771877078E13B1DB8C1EE9C36AB3F3713B52C1DB0ED49F59FFBA264D33701A088FCD69C6B35AFDDE9E9F74DCE5A01488CCEEC00481DC6FDEB3FC2E353A98F9231654057CD815EACBD92FA1A40AEAA54F868C493EB5649A13EE296B2D3300C850ECFE78A26BE1F7772FBD9C3C21FDFEB02ECC93AC12ADAFA23EC51ECA46D1DA11F6190D0591B6A618D225E8904E0C3E3B041AF3DB8A94AA52EC9F0167A013128857E7181C2E719AF102A6C6E1290FD3F69115FB1337D8C5FAB380E759D26120439E49FD89346E4838D0BDB48D7BD6D109BE98460D355638DEA4876A4D2A5AD4C9CA7F72C1C9AF8F35EB8765E4EE9A7C1EF5F615599E183F734D8E76AA9BA37998AEF053F2CB5DAA80650266DF03DDE03830679611F365336C93F98A3709177B6F97DF307D9984637A930B7BCD2CFA265474DF1183EC28800A30ADE5C6BC6CF176015AA43215C984AE7F255F7ED7F62C02D40AD1A705AED97AF97E1F3F23CD234FB24100C5DC659309F1E51B973DD89D695FD1341E3CE9983DBC165C46774FD4F66995221A81AE2A583D0E978CBA226946BF4D132DCABF647E8D1D2094B06E9AFB6A5BF1BE91403B0BC0E1188BA2FEE9D4271E7690CF3A95096D7515C98CF9189346C5F21E72DB09DC11EE2645D8E16742E68F47937858FB59A4E114E866D23CECC681353F61D22FA0D9B0D8B464A8F8ECF9E8F46EEBAF37AA3EA60E125B2CCE00FECD2A24A543075D4969CC7E1544142B8E46495D8B38ED2873666277B8B869514F756F97C42A762105F3CA6DCE3EAB4E3E552F4D49585BDFFDA46DD7A54FE772FC877AF3015859E23051DAADE007D23FDDDC883478FADC400F109F34E72B8E1A513DCB938889C045F34CD69D837DD4D40B77132C07C99FBBA68AA5F327A562495A683928F38EA43112E1CF5FB2B66C0350193BD67B968A31B07CF42A6568A91F325696B386739F6634876DF32685F0C6BFD4CD16802C8C8E559BB7A631EDEC8AADFB60522CDC7D6A2F67F88AB7701DCB61AC74E06E39FD4BB853F008B15056F8ABF7469F5A0332D85575A6944AC0B746352424F9DE67D0F7F292F3F02E93A152491EF0F401F56DDFA825902559C38CFCB2FF0BD63CFD87B1D7C4899FF1DBD0B40761B85194D9DF1874CF7FF52A1F849D1F79AFF5ABD489F862585F27614B8F944AB091D18DBBB7DEB5E84F62C59E5E904F98B5BB0415E3A2576132679754E0730DFA3465B537E160C85C8F1D30198FD5449BB02D3043B8084C93E29594AF010CB2A9A293EB29E282C88821FCD302852453BC79B2902E1C786A64F4933292D99572F8700CB936DBACC3930FADE53977937F28053885052743813B6C80C4DD8CB27224B1CD8CB36ED517D0D8D52D06C6E5033471DD98AA09C8517F5D0666901E80B36590B65EE57CA83BD730DAF45518D0A37E66141B6397CEDC4F6B0366F8C589C85C3BC05A6C92920A950390F32D2A0B8DED5FEFF23AE71A24DA3DAFCCFB18921E96B5333E708C266A15372A1F8F4D62D7F42FE34A169B76BB0CC8357BE8C855183EAB2434DE7FD97B8DF8FC4E2361BE6C8395A910EFC0B44F1D03E6056D48B108AB470308D62FAF31415C90F1CF9F5AEFB1928A2EFDF1429F798C66EF8DFF4732791D3C440AE493234FCE1D9F2E35AF6BDC5E1709A3678AC317C8BBF644165A096F9B2835F86F23B14FB0B1EFDCEA57ABD97DB6CD9E07566A82DFDFD2E790CC48BBEAD0E2232B7AEFB84A614893C22A0F0AEE3F648A70AD7A2FAE3B44B5FD45547ED6DE7191375D9917449B536BF40856743EB44DBFDAF675DD6B493A0FED774A2FB89D4F383CA4771A6816409BD15AFA7641FDD9A4FF0408DCE586D9F0124E53886B54FBAE0A771D6C94C382D0281CE0E51FC844F1175960C92886B793123DF29712C6C142521BE06B7D129E7034746206484DDBD743F7969186F8CBD1F5E14BB079CE36FF7A46D588DCF96FE3FA635F96E99034F053BE26E80CE7CF1AC6431B22D4778D4B7EC970C2C7908854C3A13B21BC26A8B5B4399546290CCB98C1F62E5D5CA99C0106405E1A8A576B01613AD5D028C8B090D750718C159C7BEE7248055F655C5C4D38E89EF58A2FF24B5136C7503C08E2211F534582187CA30DC8E1245F261D25CCCE7B60AA5EBFAB491E94D612EB1359E078583844577359F533ADA0994FC3B107A3C7C3EE6296B5E5A2854DF74DD942BE779D7BA2D6AD6A42F2A059E57457BB972DA0C2B3CA996DF11EFB6184DAF4EA146DF4B8A3BACCB4D9CB05EBCE23D752A194B7AFFC3FE62E28C7992841D8D441B91CE7761CE8B056DD3B93EF97AEC940D518ACE392F436FC2653E63EE24D4C9AF568BA456F13F441350672206143F40E420AEB561B79A66A3DB803DA4B7394A43EC7982EEE2FF86169065330FD4802E167BC38ADBFD099F56475E1FFB4AE48EB8407F6EC4434F7A8A1CDAD4E278F16F240FD54A8CB1BFE1055B34A58A5FCD6087D3E051CB44708E47E878461C21E4229C515202B6EC100C492192D2FB51A0121607D51E322B818A1588AC4E1B2FF94D1E8CD26A974CC222339D7A203DB87F7F18E1556CD0C8477CD7CC9F8AF4265F9BA29E6934A2C2AD8047F4756FAB53653C5A4CBBE75A65D4A31C2FDEACBBC71CEB394792FACDC1C79D497D9664AA3A759121F741DC9659BE8CBC76B273CF2A5980752D15E0C9EAE46A4780CB17E74F45A4F79197563B5DB4CBC104B6C5E2135491C33D1ECFC95D7A4013AEB6E33AA81EF9E3FCCD7511AB11B5C88F4D580C1E1F6F406DF964B2A05ED4D8CAAEF82BAC1A45BF235309A8CFB688C0C1211A08FE26E5E808609B2EA2DFBD0AF98DCE934AA57E659D78C71239F9CF6E3E5B0248EAE03020DFB52CE99A91BADD6146AED77E1A879D5F87A964B05C871CF291C5AFE49759AE857FCE382E5643DD687BAEA86776FACE56DD08C7AB062DBF68D43AF4FBE3FB65912251E6A65655CA2A4F0C3BACD2DA37DFE5EE3EB7CD959F56AC98A8C70785BE7F08A2085FB7058F8836CD5540927DB3C94393C9C67C0CF750C982788B41BFCD19B281EDE811762D560DE5B96F353647EB81C3FE572F1B819749727CA56CCCC621B35CDDBBC99989357D7FD6F5C3EBE20F3BFFFF6C990A3549499A8A5B31B1BBA9B98EDE4565BA3E7373AD85C1CBB18C29DD1B39CAFBC8B96DFEA6A1478EA6B939EFF130F9A98E02A56CAD1025B097C50C37B8D38E31871E69ECD60E02827796EFC8B465B4BAF8CD9A9DC04ADD8A18C98CEE625E8EB82A798DD9F95586EA39E4C3BD52BB2061322947424EAA78211B9295E8EAF833D54EE8FBB633772F3F815EDE5CAD63E64ECF3A280C012BD05D4C855BF70909CB9D58A7A5CF5C88188084289FEFCA5B8946C082B192F7463172FC4E58E7807D1629834188C5C2D2E71D992DD4441AD2D9B9FA17F61A98CE106F26F5B3E668A2298ADAFC9E23829605E75BE02CE82F3F39CE214696080E879DEA08427D45990274799C5D852DC6E1D4D728EBD862899A9FE5E66137F769BE684B587F01F0876E2763A9D478241EF15A807978B150444AD94E9BA007FFC0FCCE70855E940AEA38E9BAA16C180296F5842ACDA8FB1458168A419172CEEE5A85694E3A7B639B6137929ABC9FE6C074C4FDC448178A4CC64D754956F3EFB65A857687A30AA9BAE4BD8CD9D59E473D95F98346E34500FC9F4DAA931EA21553DFEF45E6EFA1B6AC6BBC1FB8ED7C440F404F3BE0A7826E84C902B1BFB8F61D907331EA076EC028B1CE07A847B552C0391D769A13F614CCA41F87A23204BDCAA6D429B0AC56A7878D363E5F58855F5FE9CF19D4BF9C327C67B21E7E3EE596DE190301D719B33CB2186C1C861C0A44D26AD6AE9E6FA2612AA33606885CAFA32353E75BE06313E739CAAABC5E90D316F7087049EB5EEF70C103900000000000000000000000000000000000000000000060B14191E211710000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 31 iteration(s) +mlen = 32 +msg = 5100000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 01EAC4DB3D5AF8020D86FA01FFAE47CF84BBEDB7D6A54031FFC015BE4D2648994182C9DE061737191F16DAA359C2A134606B3C2816848A84DD0C60246CF17453005D4C0A6256A6A31DD52C7B09D0BAAF3791A22EAD92D8F11ED0B7938A481E9C2C9E383E13AF8FD06C3D85A50C865453453885DD62986E33AA42C6AE9B3B83402C6957ACED4A8B673828BABA64309835F0AEF2E74F67D0CFF227F71005CD43CCBED8CFCA53033BDE00152868EC79AE5C83F3B7B3FE4F954B0BFBD74C956C66E8FC31689B47AAA3E227428588F072BE6579BC2829A36E143A4DE51DA03A35752BF6C1FFAE7C6A5DBF951D634CDC81F7D661D29027AA5FB5AED7EC725AF758EBD7075618905C05278BF913A3F126C374382558859C8BF375F8DA8FAEFF00E59189678BA0EB29A5F557A23B51E1D560A982CC9B2A7134534086FC2E5B28DBB6FF1043B560FDFB4F4B9DA4420B7F7D283A3DD8DA2D6F9194C5D43E6CEF26AD05FD58EAD718E22FEDDB2816B455C50BDD5F776E8982F7C27EC7F38E07126B86E6105CECCD2357D1F459B8DA652C6F79326F20AA658E15654C95F73417885F61FD1C2BFA9B7C50BE0B113661B2B8AFC9D942F16D1AB0BB0E3EAB64126730A4B5D2FCE426B4C911E0421898398BD18679AC1890A82829146C5B5D0EF7EE58003CBA9EB5A8DE86AF08051A69D5B4D0CA70CB2A1623364E51AF673F7F540463FD4260EE73E6B12D518E68CF40F1532165AAB88E1BCBB9DA41F385C2E601E511533AF7B43E82CF67D47C72FB9AD3617F89017C825D3F0D7AF95B69F55F73B3D699852201D70F4ECA4A1EC59A59C1F4CEFD1739CAB4DB6DE0AFCB15A8B87BEC532646F3824F8DE6FC716639BCB887A70B2468E0740F970720B1F571DBC5594E5106897C8F514C9307FE41D6E9F7F04E09C3C5478D55EA213D84D27745FE11A7514AAAB5339661C8A1449A27D66EBDF1C1E7E95649BDBA7A382DF339A188494460B97174DD9BCEA52C0BC69A812457475845426B1A26D9CDA478FA600F25F09F8217C4DBC1A9D9A028A51259E9654D115F7889A6875952CC1E8162436DE0360828D63C2DECD077BA290B9C4992957189EC6385063A3B6CABCE3581C5F909435B5F3EB373756B5D33C29F2ABD530C03829FDDAAEFCD65EEF2FF143D5F4A74AB8C6B862647BA6925550E4D0B7E16D357DDF2B30D79E931199D2EB0B771FDD15CA7AD3D5ACB7808E550353B678C4F98A70CF2AF0F5D9CEAFDF70D736AA7FD755FEF92DBEBEC9E9E78471775A8A7953CCA04C021518BE6B3EC8AF2E65986359F0956D2745F6B4A5E0D3C7BD7DC3865BE5B8DA9FFB0CF77DD1A31A9624DA0B8C9F9B385BEC629EFC9DFF5A782ED90FC7C595ADC65C46E4E3CCB155BAFC102B861A8BE3E01BB26811FD7575ED3CB98593A40E30BCCEFA56C648A0B17B6DE9B7E67163F106A861C90FF9568EEB3C807DB49EAAA5A2BE38EF546AFB69DAFC42A1EB7A7B9AAC9E5C9E081852773DE237522327FAC04F76A64883C9CD158099F223D901153BE517F58DC82423B0B0AA9A6848B13B2E07D887ABB96E083943C0F619448A90932ABB31B276C65454C0DC65DBB014EA2CD0BE91C855DFF43B0637AD99E5C45F4450BCD2F968727E59FF86B50BDCB2C30AE347FA4BB8E4E35FED1FB33EF825B09D01BA2B736D080A6EB66DAD7EBED7A353FDD1F821FE8F3113B820CDAE08E04B1D031F3CAB521B6B6E2B371D67ACB911E63008FFCD206936D76E0DE45B056617FCE9A0AE0932D6F1C815ECE53A2071D7827FF2DB130E0B249A0A7B52A0CBF92D2D67062945C0DD2B12D3E2CEB302D2E33B711798082355E7839E4CE9173D78645991DDCC1DDFCBC566E24B79628F917D8B75A62721CF878F77A441298F306B99207DBEF11F5FFB39A651A48CDBEF63C539A63C8ADA3BC269BCCFE392802AB4C0ACC4ABCBB10022A57AE7DB6AAB779264D5DE066D74939E1EA03B815FA14130B94FB3A633BF300AD00B5FF8CB13D896C1269F6C5A587AB4BCC4641961EC507A900E9609537AAE477B6D64181C28D3F3FE44C6B07BC50407E7D77105633E994846E7D009784A3C7A2DF07933F69447838DCC8A531C9075C80D34B9C13A0A5C6412DA213F3A845C1E2BC38B0A99C0D10CC4EBAC342C137FAB6458DAD3CE12AE18D074FCD91B6772804D8C80C1300D14B6F383A0768311E02D355DB6DA654715A523F8776E1BF03B51D256E8EEBFAF9FB926BDA55FB38D25410429158B2EF6E789F633D6DFAB82483668594FD95652812E7E80FEC788DF5B3F3E4F1246C4C70F7C33EBAD179DA0E9E9485C0A1C070CA35CC0DAF43C4513FD2C6062273A54D3C779D876E251B6A064252541744840387695D4757E9B4D6D7C600CD635F8D2ED5A76EDA12F771D6164731F517599933471E34A9BFDC8B3E3361BCC2A6AFA4AF277583A7125B7E4CB9BB24EBD9EDBED2558533647F32F6590C396DBBAD1B7046129A86E3720347505A9EFEB23459378A1A8B54B4E7960355EBA1CB84F2E761AE08BFDCC52EFD9E4FA3F579365A4519EAC13F0BBF872C02AC7401AC2600FEEBC218F930F7DCA793647A7F7940D29884ED6A7FBCB41633552FF7DE28D4ADB21FFF2334CDCFFC33DB0D3A5CD42FA921D3387F20B87EA59D6871A3EB24C71B8296E3BE9ED57E3CBB69D62B1FCF19DB8F07732B0D6AEC22F29719214D27132E1303AF5AD5EE328E75B7B347052B2AEB4A98322E703EAD7FBB27D7159BC128CDDB06944115766D944647F644C8ECF45C71BE4641536A40661E473F7AA9C70D2B61B61CCE8F2E35B3E6E793EA1D103677C5E76EF2DB62353AB1931DE31BBE67FC2FEB6E817D3E534C5F29A9AEF5AC4969A532F9D01FF9E434ED135BF26C031A3BE3CFB990B55700954A0D280161CED882AAF181B0A43E92B7EAA986598853150C102F70B231DF612BF1AC58542AFCC0E003F4DA9C3BB86A2966E8746CE1F4A75C5984DFA45B6D84E1EF9DBA9DAECB9214BC14AB7D44C0B7FBEE350C4C74B51025D207545FFC6C53C05A8C1E5919994F46F596CB990F11F33BFD70C3C8452EEE7EAC2E4413C6FAEA3393CEF45E259BAF7E3405CB6F694DC28A905932FEC271A81F8BFF02AEB47DAB2575317BC3AD0DAD3A83CE81EFCEC0D6C319380004CF03B0267F775888127507E396AB6B6E3AB20C4EEC1B507DA32F5314D5CBF8790C3AE3171D76A8E3833ED9A236621B9C5E91BDD77D7A2F06EF59607AFFC2AFAADF55BE88F6C8D742B6F479E38FDAA0FA130CC6F835A67ABEC845C137F3A644B0E96179DCE4EB10504E30EC07869D04250311DB87A72773DE260C63F90E31CD3F059C4BD56CFF67B3DD4F45EF41687342669CFF023A4241A576B9D57FC74EB6376C90300E6418A730398A8EA54D759260DCF1B19D6BC59157159FE1AF193EA02F58DA51559F5E1EFF3C4222F45CA00ECA2DC9B2D7AFBDB600FD97CE14AC231701C4EFDE8ED052C68FC763BE4FB52019B9E6B6EA7AB85535E94425513E18423B2F7E0905E0535C7DDCF2F4AFBC1B8ECE7E7361D3EFD3A412A090AB999A2010ECA0A2664D121E7975688778FC2401A6076254BDD0995CB21B7C82D94D51F0AF2A4D89EAA35B5259A134C0856F791DB0A632FA6F9BDB3F902F4ECE52B1B323B1F14509C1CEEBA25756F43AACBD878E7A733F98E6B6E62221CC6799ECB2556F5A6BCF8F92EF8CFB44F45B89C6DD6525577E6ADCE1DD49438E90F12A880B0F85417E35A5369ADB315D9A2BF2F2A098848998EDDB6C0F5A8CDD3D331E0E8EA3AC796F7031CBEBEA2952974FC0038E511D01EF56A8AF181EF281BF2380151898DBFCC33081B5976DD5FA93A89140F51DEF740A69519846C7EF29CCE77D578A54DA19CCD259D7A2F255AC0371468EC0DBDADB228F3C0A418B86BFA44827D232C162CB0C3C48ECCA98331D4F2F40B6A66EC54B14585F112E5003A596645CE7F2B2D73E988B39E8EB2B12039A2CAC4D78325D8A06F8500E7CE1898D3CCE1DE236518F88006ED12EEB65EA7B5244F446F3F21FEBD9E7CE0C5670D17D88CC618981A679F415FC25B82695B622D6CC49DAF2CDBE96FC6F44C04367FFEF73B071A5A481CF1EDC9C96D6B4E44F5591C7C26B28A6F80D630C2503451FF6F051963EED1774B62772AECB4C0C5A54DDE4DCE004FC29473A71B5588DB929141E28A9ADFAFC1F2243F5C984BD1EBDF187B5137C07A2BCE7BBBBE72D9C847858668B7EB044AE04FADF395499F09DCF9937D4AD40D5914179BAE8E337D325CD65661D16F7483A68257036A129047C59BAE8F14A053C177E54C57F069C7D50E1FC87186D67CAEE5BF7E9E58D7EB4134E60F4337779F80BDD171FAF8380E87B9928D360D600E7671D227A0BA10C5EE01507B951A9793956E247D09F50B2BECD9EBE1A9BE34EF7EB5868A1E5F7B9600048947FD8607A6FED0A5AEDAC7D2925674D74B16F462A360965E6EF756E442EE17D1C80114C1BB93CFCEA183964032A14D0C2BFAC98EC0678B1C2A90DD130FA9EAFA717886BBF0E095FC29214983D2131E69FC9E63182867D4D59CFF725C909090F5F000C12BB0AEC5EF663DDB0DA69A12809E89590ADA3B19B4E2262E9AD04797D7F8E9EA4B13E5ADFFE212834464D50A4C64BA2AFD1E0E8044B5F6F85BE14426D6F87BCC5CF000000000000000000000000000000080C141A20285100000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 32 iteration(s) +mlen = 32 +msg = 8B0D000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = F8DD8FBBC21EBA0D0353DE9A97DE9336945958E82AF93C8CC5061B00A1247283888887C38034709D4C56288DE3175F1537C41D2DD3F0045CC0613C5E0408AA522170BE1CE10A79CBCB18B7E4C2120B15B6CC47909AF9D3B12E160D8000B2DCBAFBE4A587757C07CDD1CDE88466B31D8B425455964A1B3399A4BF222CA4F031A4E5BE6C9F921B078EA61F063EDEF5C841F7788992B231252B74261F764548F930DF5ED83736E50F97F8BED8B52A227561242B158BBA244C29EBD49C44C61EFFCDDE24AD5F2DA561EB7A47071192299A0FD4AFC27937D9E653150D31E7C13F66819F09D317E894ABBD0A2D61B820552A8E816F3BA8E20695B187EADFC86B0445FCEA20B9B2250EC38C368FEF7F7DB9C8EC0816C07835E8E61809F8324A5F3B5D7B3EA992EFCAC693CC4DB79D45884211DD4777C4E9C5EBE688EA263020300D100115692A7C5704BA393DC218A89D568A2AB5744BF37F294BF2A6C522E8117EF58FC447DBF5478850F2030C14C7EB459E39787A30E585C047C33677D03CAE36BFBF8866171CD7D26E4D31DBA33F956C51B12B26461AEF886FD82232A012CFE047CDA97ED3EB47C8130B9DCB4FCB12979BE1E067A5166C3BB1647B05BAD6C582E015C569B490956E109CB642E5EAE01668CD1975CB9C657B7D527710A10F0ED595AFAB34FA805B740DFDC6310C003A556DAF244D0EAA42DACBC258A4978A231B9446EB01CAD717F0AE6944E6DAEA99B9F08C0977CF7BFD188A1C997690979E8FF8D987D8A0417EAF643CDE62406795620E5462875E77512F0229D2B12D3FBD39E4E34E007EDE5C76E434AEA73F6BF104C62A7A2E7276402455D4F0E179F14E6B17B90F4CA5A4ED34D8D4552CE4654F409396E3A3532BF52BBE93F0533260640A76BD64894000A27BDACB6D243757E464676E57E4D0F629C3D10085215651D94D75225500B1AC7F5921F86ABC504443486B26C401A5917C855E0BFE548EC1D1543488A8F9560C387D14A41274286019449655935795AE37FCA42F6428649006A873DD71D292B8486E12B6EC3DCB8E440E9ADC2651F50756F44BD5CAD087779AF008F928962DBBC65AEB1B0AC916F32802EB41947821B3783874F94FFD66A066872A0F6BDEE21766BAA0E9D2F246B9C48FD65079EFE3F120FE81D8BFFBF36F07FA425FF4C1717D759A972A2B4E4121AEEF340BDE147EE50B9152EDCFAF191D4BD83D4C089A80D8EE1F9FF56C32D22EBD176ECD1AD78BBA09E575F0F8C6EB7A9B5B19D335C9B6E7543B1131130B40F928AF9A20D3CD399CF5F221093459ACBD060E9251CB80E52DAB9ED531DDB5F9281616314D17AC99A51F492C7176CEF2C49427ED767C8DDD6175FD92213FC3E6A99FC598D731CA01077D8537C724DFAFFACB565548E0CAA34755650294031F98EC246139F58E889419D0B75A4C319219E3B49927F72B3C19CD86F5F25FD58641A83C5583076B0B4F360999C6465E31B38E1E7E931AE182FA59FD37E3506E5D187DFBA45D54CAEFC1C9991ED5426334ACFC818A07E3BEE7F8DCF07CE81F824299A84A45007B42D318C12BB5792F45A02EE011506619156C05B3400D33731584C72DBD49C3E6B09CA9C1AA51C0CC6481BF6325B1CB77DFF6A7F6940CA80B974E12013E18E71971120A68322EC4BE3122A5F8BDCD3C7A7E7A385CAC585AD473C490873CE997E8CF52F8FF8AF9C2EF23E4404C9B22A5D0B806A063BA2112382F0A11B2D805A6AA8DA8F2ACA0F976A9D0F1A0A251D4FB0C5194675C369A025087EF70ADBEDE6191BE31E918061AC2304C1D2241482FD9C150F09E4357423F72F533913E34A975F71B69B3CE42BF52A38E35949CA10D623333498304CA2E8EF9641C5B283B1D1CCFD5345A279F90E87101543632C2D3F61F3BCA81362620439B8D4F1C131A34CC2C772C0AE04518416539C7BBA5E072E15F081DDD9950DC2B222D3814B126F8CBFB6FECA845B128D4D09A53717C944791DD37ED615A22363C4F2A2E8F842D4A3514E841865112F74D1ABA767C92C1F9D378FECE9375249D2BE01C95BF6A395231230F935B02955F94C11495E9CA79C5389679AD71159057E7367E6BAEDA9EED697767ECE1072DF2CC25AC5190FE92BEF5D7D56C135A4FD2741EE76481F72D522473E5F5B6A6DB1FA1FF9CCC07CDEFACC6EB9FC533279D56FE3B5BF046A1ECBD993554E38A8AC94FB09B05FEFA4FCEBD89AB8BAFAA76FCC16122F3A7BF4B97EB76FC6B6FE315C141FC5A1F63308C584C9B895EE0BDCFA139EAEA016FA292EEADAA1D2DBD72C1247FB409041A27BD74A4091FB9FA6244B4F8D637767B6456FD87B8BCEF882696A83E91554AF325DA9B481521660E98C3E3D553DAB5984770A5E22539D32D6CEDCD786DFD917524E7564196992522FC3CDD355AFFB285DE717355519C34EBF5209C176AC9534BD6FAA23BACB2FE87BA34FC92746E2F82A2BBB70551682C748A522695ED6930C6423FC5D222A3856A5B3D106C0B096E496327FFEC72D26EC67986686BC6E8F27B12A3460350E6772AD320358578C8949D14808067973F5BAAE5257D2452A4C9FC6249FC4FC13AB9568E6884A13F9D6EC6E5828D62C43AB3AD819664FB66E5758849AFD25BECA344B92D5F24A567B9323915B9B7803CE76BAAFBEE01DEC333EB63B236F64446501CDAF265145AE6E1A1CCFBC77C04DEC25680BCEDEA1FEB79862D4B02EBCEA0FC58B90909D75FD33F6FA940DD75DBC3A99E1EA62A47E6049BF6D16E913D98F1AE7AF115A1D19D598016D870C51D0C1456B4AC4C500020D4EDA7840BDE8D1216150D2CA7915877023339196EF35325AA05F1360F2E8E00B81177AF4F142F67EFB126367234BA0F62271B28BD65539C5D7642983791F61074E98BFEC5E6C15E59A346D26CDFC699365D711E65E13E4E2B2608DC79F4908ABCF5934F8EFBC78195B74A1E766FD9CF2F5EE89C8153655C6A7744768FCC978FB36D1860C2167B85C89F3A1947B2FCE55A4E14A8C3189580EFC1F52E0CD768FF0B579509E003DE240BC1F6AC0CAC3F0F8448C586F737244A4886D01F08A36510156982ED74852B52E3126BC52FF96B421A0A9C3D1D6B136F1104B62C4D691F645DDAF2A6A1E02F91AB23FEBE5189781BC266B66B963D20A25070F0C354566FA16AFEEF5DF705148BD73DC4D67BAD8464100FACF6A073C4647E9355A7224922590BA3BF1E3520658B675CCB0520C50C5D2E156014961CE4B3571CD0B7D5A40A23945B0A336DEA45C5498FD859CDD942A89C180134E5E324647BEBD50131A964A91CE1483347F2BFFB60BDD4C6669B19F5D019400E4CD5373CEB4C612DEA80F0B0ABD4EE6A9A9B849051F600808C018972064C0EF98998D56D7DF50ED36598606E7D10A4C16F3A376BCA8B6006BF7E1DA576064B0C37555D902C1BCCFC96D82F37F7CFB5CC15856C3B456BC1E25D02EC4CE469123C4E80D3E8F763E0345E7363D97D7F643287CDAAACADB79F815F8C857DAD8BAAD445B91388BCC43C1C0E9A22B993BD48EBE1D2D80BDB990440E0EEEE61C6122CB628C694E626AC74597D2E46149EAAAF29F97226E06A3BC78FE27CE64F7373F282F9F8FFD546FD4F42EB4EFA91483111E88E39F9B05013BD1D40AC2B9728ACCE4F6FEEA748BBE79191569411055DBBE998A39CFA496BC9F7F6503AB9CA01BE10127FEE2BF4FFB420962ECEE559870BA7BA0E0E70618838309DC8D61E7ABEDF50FBF9445755CCC5A3330F9BAA15E52C05A91CECB76D5B4E864BE1CB1DB91C37A6646C6BAB89FB5F0127CB551600FF910E6F2936B44890909D1DD34D4D67EDDFC0B7ACC5B2A7EA1308A90C02BC24AED97C651EE41BD77639777D66E4161178B0BB93D09AD01868029556F686BFF810DEE136E4235D6E32CC160AF3CE0A7F1F648C6169D3B7DF5FA5011C16FF21A6F5739260F7CD319FAA66B7286B91DA26853F556CB4DEDA3DD34D132851B45E4A811637279CF937B8C5F9E71B72CBD229118E68F5C714E16C9025D65DF8194E561F2B4B347A966091507A0705E142F88BCA45B16A00FA9E9444F1F1FEA22EE0109273B7F514F66F3D05B7F8577F21732E98FF8558DE75E0DD335B543BA8CAC44E1C58B9BBD2BC5CCC554035780A7A86AD5AC9E5AD2887DF3DF50E1D51F2041741C93C35F21646AFDFB12646E2916762FB2A82158E5817E6102DBA4B9377C108A55A35F0E1A67E606C1EC12684B0A9435F386A0C176320EA6443F6370EDD0D83076287C97DBE7828E470B876FCC25FE86B58F50804A2644121AC3AB19ADD97DE8806CF40BD1EAAAF36F03EF289DFE74C318D0692CCE63CE7958BC2F821338AA0B0C433B825825B401287494319AB10897AA49DDE720022128E18EB4F7A42B7EECC3A6F13DCD536BC307183E0D0104C037DAF4AD2302A057DA4A0E8967CD9A04F133A7F2CDB1CC838C024D7056EAAAEDB66963ADF559F347970A74C29AC62410EE9D36840F37C7FA1BE5B118FA1B95E3459F48CDAE7AC78D03A62A732A99FED3485D9CAF7943B6A2C9A94FF4C7A050CEC9160646827A874B10E891FC82DE2EDC0D9DB0E8A9E1FD16EF2A9D0C95C6B0B6FEB390E6BB6B733959718953A494B899C9EAEB7EA93F616178FA8BEE9F6F749525D6C969DBDE1F7F8686B7A9FC4F6102F658600000000000000000000000000000000090B131D23278B0D000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 34 iteration(s) +mlen = 32 +msg = 6014000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 99893D22371304A26A3DB4219BE60F59E72FAE2E331AF713086816E2CB99878730191E2C9B66DFD0AEE2FED1F1EE019D583FCAADA86DCE30FFBFAB7492FE8CAA777A0B67EBE537911AFCF39315334952F6F03E9EDB15BA5571B99C2B61CDEEB166FA36B07CFBE9BBC7186EED33064E3C8AE36E9AFA0028FD6D5C6E06DEE48783FFB7FA79C60FB8528CD5F9F2C7913769FD9AA23FC6E13E4ACF9A9B1DF92C986FFA594AC2E2986880E62446BAE4EFCCCC2211479E7F63EFFF126E430F7B3E9284A802445BCE8A82CCE56255B960559B667075DB347A4AE9D45BEACB94E205429AFAEB1823E8B9F160892398319D74F4EC57F75EFDEA595DAE514E08FB0FA22445806FABEC1DFCD05D80FF2834FFB81D462E4335564E7E642651D0C7423173A862E0C82A690E7269A62FB4684E3A3E3C9C0A99EA32525ECE6B157972E52846CE4F92B12A5AC7733C1963F99537FFDFCC3E3254B87B1F297FD69AFCEB4EA5C58FD3DC389C6E0EB5C81954BCB8E14564F1627B59FC768797420D663EA275802CD1ECC606C57CE04903FC3644A8DB03C26837B594E48346328ADCFFE0B8E50518997B62B5D25BED7B2180672DC403411320DFA3867777544555EA0AFF222D159C3E8C2A0670533AFAD440238F326445FB48ACE5E680E15B85A76A7F6F06D9EA1513A6F46DC6A43D85AC0AB1EB58BFA480647E34FEC219DBE0E760D0843162D886C082E986A35AE4584F00CCED01FD93026D29CE92D7F9F0A47EE337A7D395888C0E7BF87520BCCDAF4D71208FA03065ADBD6F9CD59A71B9F2A34227CA0B7D8CD4468FA8AD4DAB11777CD6C4220EC64B9BEBB3FC36B8867700B79AB1F5BF39218F9E596E292C6CE77FA06A2A8B760F6149691861A4A42E8A93DBDF490BC307F548A760D45C1B469B2C20D2187685F5FD5189AFE2FD4A84E88119B732C5D384D54610307F0339913CF766ACC2E7B697308D91669371CFE1B2EF4F5E6FE4B80F0451D0A363CD2B3A6331ECB5F7027BC9D013FFB85347797A2E47D02EC6146A8C2C8AD7EDE90FC0F44C93CB41F0FD22C65A431037FD02E51D5908FA1B3537A3D925622B04A2218BBF052DE349D15999E7AA731D0596E2CAC1014523ACA43CC5A26B2E3945F06BDC12F854D485D7D83FEFA433F800559E192CC357996DD99604304FBA475289435EC4E57CDA06442A3BAEAE4C90AC3457047A25377777D13E4C8D367D0E2FAE1B2CA117B952BB91AD9AEF010C911D79FB4B8EBFA6D3B3D083CB5210A24D2DE2360B75171B42908E9A698FD680DA715C8CE151903F945A1E226EC2510410846FB36537411EC9D11E06CEBF69265860775DFB96E7804F496EA0A86DAAA7D7CFED679B895A856B097AA27CE79E056757B2666D6ACB3DCBB33B184B85785D025AED348A400FD29747AA7DC33366336FAE0FA371FA27A24D75B36FFF6AD373A58C41387A5218054AF533F7E78B288D02C3C4A01954EE56D5AC0009E8429499079D4313722CBFE79AF1FE6601934F6301E2D2C958AD5AFA6AF2CD7A2CCE652032B9D4E266625322980740A0F70035B4182D69B03D7F5E85DE2499658CB7CA7DEF9D67156F148C314F5AA943D620F5B925B016942B97E73CEB690205954511974161550522A17B48AD64E49A450E269CBCBF1CE27D8BDADC137976AAA11632FCBBE0E6AF086F3DFC302ACE4EEE7B2DD48511BC010C30BB0B8FA4108CC38242769DAEFF64663B3C90793B12DC689007B8491F42C32F16EC884FF660FB9C300B39E33CA52DDE1365B91828EA9B5F52765112C4622CA10F14021BA33E606E4247182775C5A045E995375F96623E046693F4436B90060958D7AD70B91414FD53A9FFA06D6F589BBA6F2FA2AEF973CE1728EFD15B307DD8883CBCCD53483BDE7CB6C36E84B25401F9C77BEE2BBB92A65A53C9522D05331D35C05FEC36F11F3AD2F9A4C11C7DAAECD0143AE9D4839BE50DE35951B639FEE01126BA7B3225E90A4F31FEE99E29D21F58C36F8E88890A5E835ABEDB635FBAB82CA66991FEF7550FE1CE7728FE5D5D096182905E534EF4497217C3B6E494883941BD6C12395842837EA302502C31D35D33CCB0CC78A57720598BB37121B3AC734A707FFD7A3CDF9CEC64B96762518D944C370C10EA2BE59A691318B822BC06DE27D7F67FF726A709ED5EAEFD576B443A269E73EF4735A9AF5671824FC5E9E589910F405D42F9A4759B31128FD49F3BECC42E4A0E083B8BB618F57DF5E7F9EE64F6107C67DFAEC01546922CF3B0B90D88F5315976EA17378B22B58ACCCEFE558BE949A296D0756C882381152AECBD96E88A3FF4683AB7D678D572917321858E3CA66B9B87783C40341B35A5CDB04B1B384880C4DF13623017D7B3F6B089941E96AEC8F878CCEA7D4EEF9A95CDD9B3CC8758C2A9679D788989D18067BFE806F467C4A34CEAD74C5AEC3703D86F575A9F4159F0FFD1BB05458159571E559DA812B2033BBDE0238C36BAA6C8C0D979F5F5F231B5F94BC67B0FA129FE104C8B76592A5355A00A6472CCB95D4EF8D07E895D103502D816B5501F5B259B86925FFFDBE30029BF8C002DEE7597DEFBEC850CC18A0ACCBD7D08E30B6FD2F9F3D2E7C9D6CB77A97690F15ED0BC6ED158B0A27A18FE7596E308BBBB01BB1411BA31D7F2B49CF7E6AF5AD1837DECA57E285C9084525F859D72E1381FB39C6525D46976AC5EF54B541E4B36CF50B92977E1170B0B04C6222E213DB34B8A48D111627B905CE65821A73482CF439709851A26FBB82B381B84E076D807CC35DE298AA3FF38EAE9C9EEBB52D339F62B6DE3CF7BF934CF1F206AE4D9CBC6C2E5CF403732EDA34DF16A6E04B3A89EDC0EF3C7DE55E7946909B6C5ACD1C51A5E505C62E0DF81B0DBF94381B657DACA9647B89CE5E75336C735382750C90ED21F611B2607EE7D4BBD97DAF6B40572619A335D9344E459FAF5672DF500A9541E8113363BD4AB65724F6D086860630ABA2B858CA21E3D491215D2E52D1FDD9AAF9B22E97B02D0B3CC653485929D6A7585A9701A45704B6BA175D916DC7DCE0A75918F8C8DB61528FB39AC509928A2A8498C07083136D14E28E1094DB7CFD4C5CB401D55FCC4089C1FB1C18216AC7C007119858F2761F81AE717A5BE42202B2064BD1FE51227AB82C30BB6378D3C9D514639278C25DE38C99E70B8AEEECEECAA23E672975B8B9EFB50F4B6E946B4FA00CB2A88F48F1BFC33909E93AA87FC056E67F7F81AF4800178CE77E752E80A649A667D389CB03B13CBEC353ACE08674FB6C612B831500D01690E254779F23EC655804D53B10264B542A28897E3E0F041FC94AFF3B3AB22B5E5AB3F4CF6551AD064A9C96FA2232FD9D1A2676E40358F49E38072A62CD223E6F00909CFDE7C549B340E4A01ED71B866E2A6F898B5E61040D2E93904E4BAFD5E5E34DEB37481C50CDA70E32D1A60F7B4ADF786C7471E0F59E1B0EAAA793329AE660365530869EEA6E5E770C11FA56861D69602DEB0CB9C4F5181D010C43A36B118D481735E77A1B0170C206865F90F2FB5309593E2DC0DCF49488798B7618B11BD218F256335250012337F245EF45AD4CB615216F01AC27938095490A18DF687DB9B5002DAF85AAA3CE939053CB5E84080D4F689BA7965E2034DA99EA05D50B96A552816D938100F22CB2ABF8FDCFB80D73C78C77FAB1D1FA81FFC4E3EC48A116065B6E313154EA2281E5A4D6A98DF5FE439DF530DE835FE169533B5A1F06FAF13534E8E40E5F30C5DFA2F522F42682CDB1BDE0FED6F23EECE1C2707492F8B002442860609A24F2F4580A2138055C4311BA248E4D5ADBD442972C54D41527DE59DC9070ADF8A299583EA0DDE372303911FC97E94EEFDA2D4A05F30D225A7E506656A38529A45A8C3029D5235071F78E1F487B38CF6DF4A6339BA55E99EB25754B18D9CA0AB26B3191277C9502A037254B742659DC410419C1C07E600533307D93F0B7E64262CF1C39D4EB4371E6AF881052359F2239F7CD8824672D24B93A1B8CB9A8D8FD7081E24E29B4E48F813CC8C5E8D1A1FB335A76CECE90A8032E06FF7669C28F5194D5ED88ED671C6B3BC2A3F47770386DF323B00F4B3CA0CBA3AFA5CFD1F0050CB12EF36BF402917D808B179FA9361F34BB7AB6EEE3BC25779528AC770FF5BB6DE8AF65891D3CC58A9424A2D178365E5FFC04BA513E98586D3B3E0AC5B5449DCDC7FC2C20EA95C12D2D8F6E1CE5A6594ED6090BE82D6335E9FA9C8A7B147747C1726C302930DE4B17BAA609A4121CD29F3424C9831958F885C6DFC9C7496ED3C48E41A3C477711F67A7058C1F1BE29AABAE0A28F4CBF566DC33741DFB24ED4F434C831BE69E23CEC724B2838D6201AA8609C6C173015E01C821EDACCCA1780FBE149900F6ED2E5B855E8A6F7BDDC2B28628942F3BFF63A13F89B8CC26C3C19603A899812A7953C95D1446BF3023C691EB369062B5056FFF2B6660B8A0EC98D8A4504AF94DC24FF1FFB10537A89DD25B8A3C35007C1396D9FAD096246832A7657984DE550E36E868169EE27DD6632EE57A80F612C082C80D2CBECCE6E2C0B7F7B4315F24151C20A80C4367FB53C308184463FAA5591D276411AD6176E8436253D5491C3C90E0F2442474F5B758A9AE2E6F24C6FA610396089ADBCF0143F58A8A9F6141C1D394F808DA5BDC2E50000000000000000000613161D232E6014000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 39 iteration(s) +mlen = 32 +msg = 7515000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = C3304E029959E6B7BA4E9EF5BFEC78BB36D08A2BECBC4FE162D90926F2CFBEEB79EED7B76501A926D95293E35D3331C30C399330FAC466A6C8499289B4633DB15DE3FF90C04ED672A4B913C96BB3D86C77DCD8C47391927A37E95AD26A6E8F04A87E384671F1821EE21171E3505DBD359B603521A216C467019508B591EB7E3E00B192AF3E569ADD7E67F827F0FE056C53A23FCDB3D927E2F1FB7B3C3E360B634ECDC124F34A52DB96DC3A3AC9238355D65F8A6F6650AE0ED2447009A3F940D37BA4C269045E98B26FCEFB7039FC71A05F2CCA90D5A9616F37427997F299A1E4DD9AB8BD9C1EB6433A3FE3A58662F37CBCFB4537ADFE9C330B256991C55AF4035EDAC7B298F8CFA821A0F21D4DC10023C12BAFD86BB61A65BD9F7FEE332D372CF227A67C8EDEEFAAB8BB1ECF58740CF9C5062DB241458403A344852B201298BCC816B0197EE92EB4489CB60CA20B1B6182C492995329AAD2C3A5EBB1A003BA0D2D4674C019F974A329AE0328A44BBA4B959509780016B71F89CC9FC48B30B11AF86A6BBEF213C1182729BB9E1C78372C5B85B898BDA52A9260A9AEC8C616650E1817B593CD0B82433CF2C4AB09BAF9756AF271ABF4305E976FA97CF15749A316DCC24EB3087C447CBF975BE71F29BEF82ADE63C40AFFED1109ACC66D5E2126268A8C0490DBE3073E8D6E1D9427159B3E62122686538FDE5B6712850FB89AFAF222B9EE881026F21E86FA4209137427FB53BD70FBE58BF1B3E1347C0996FA4F21941BC691D981880D1EA39EA26BF6F2DCA7E034475DF70B88BF94318DF9678A1FD0F1686950ED80CCA56B7F511A68C0A5B374E5BFF80E0084EB7E356D26BCA683826C8A1C5C494A8AEFDF814858CB055711CDCE3EE41A000B6AEE2D5D17C7D58C99EA1A11B7F7AC20CE4663B5E57E95EE72F8114D8E842DF0537EF08D5598EA34BE1FED1C8991B9A3A1481286402076DB898987213B3DD8735D180CFEB0530E9A4C469EB8ECD049C5F0D8CA6B38AB37EF0F1A201BED54C3E5727D7360ADECCCD8522BB80E74B2228C0E538A36481E43F24A9DBBC7B06420983F9058254870D0CE6FAD673A62E168165467B3C899896315FE62DDCB5CC5E82942D27AC0D6475977B4F37F765F85C2E7626F7F348260152EFBE49F9521B88D41164EDCD41E004C7C101AC5467D59947AF5CB4F080FC528DC209D900E920A85262A2EE830D33C8E7AF3A444850BB20E5ACCFE3513215EE9EED19D7B404DC0807414CD59B7365CF95A16FA1391D3025176738B40D0465063C05C572DAE80FA1AE804DD6EA3BA13716E89E8984E247389D47CA043A761C0883DC68AF4EC8D9CB01E8D2ECEA6FCE936C7C28A7DBD1F351BE8E0B9FCE5ACA185CC9777AA08CFF21F5008B68B7AADD983A856E5D9485C81BF86F08F7EA35ACF7C0AFDA1D44D8EC411110AD4814CB0DFD86661C542C560CDF911C6829688F9F305B60B3DE3BC22EEDBD7836CF79ABDA8639FFE93F203E799B07B02297AAB3031ADDDAF06C205286C247E44453B7D983323EE1F397EF8E6023FB7FAF4BF511AB83ECC976A5DC8B6AB1A6D798CD6E4CC2223694EF74E439C935E27E23DE4CACD6869B70EBCE81787DF8E1063D9A0082AA48461F0D2B3F5FCAC025A1F6B1023E9F13DDF79696E601E4F26D288720986AD9EA3598B0651E12769689B6171F16AB65EC27AF2D041B09AB1F19884E2C5866650EC1F4B7033090F564E2B1E660ECB1B3853E12247EC964B469C9222FE851BE10CDDC3B5E1D17B63019E696BA002FEDE98D7BAEAA5D14360EA01515D49065CC0037F67924EC5ABD5D0FC2F8D70F9C92B4C02DAE4E298DADC923123A1234FB7F2D6B16E745D01C69B8D05CFA49980D44069550EFB4AE4813A91AABA49779BF99D00CD1AABC03B023DDEA283B62437A9EB984956611F5553CBA5A1F0A47F6287129551951820AF360A536DE32A462B85EABADBFF05B062BC73ECBA0A5259AACAD8A0D014A6A741E44E8654AB51EEB6ED295AB7D2B533DB65309D393BE413BEFEFE0E3905EA28CD62D0D1C9A4503173F52079AE739227D6B1038680333C71A36AEB46E7FE63CC565DA2B5EA862A40533A8708B6CAABE549AACB9B03B95384F5CD1BA19A8E05930BC4BE52E81ED37F6FDB0AAA683F16B8180439F7F23B8C9C2FC63806CA7317A533CAE23C626D18C1858442BAABD3766F29F0864330D6DB45CE1B11FE5A647D7D36D305E3A1C2B1EDBD69EEF733287037970788F5B39300619986A34B25CBAC2F715A144B77CF87B15D2869672CD14997D474D3997DE266A7972B6E097BCD0557C8C73843BCAEC6779F1574272370A0CC97C6159CDC35C55AF1FCA49C04B1F0A4081D35EFCFA430D167072E2103BF1B74017E888E289305FE9B60DF191243621FEAD191BAD5BF198C3CFBDC8E101E1F6295F0F68E99878BF5B52E52E32D521D24909F7C6F2CA546EA88AE037F28F4447CD1E15DBB3AFFDDCC64B5FB050467E8AC5FD5DDFE5225F82A29C74333EC6F3EE7BC7266B899A5609D0DC7A71B668D0F6EE47CD47EB1CFAE4E3435BE1288E5AB9CA9BD92A447FC8B7A7583435CC04F668ED4BBBC9DA9D34D91E92FF222AB616AB26956DABBAA5366E3DAB272ACF75851803C183B165023D1761F017E0A1A8E3E99E29EE8CF50361A03A5146AE92EB29FAD6BD6F457B54FCF48115F91FB2A0760C9B2F8AF77C622B18C0ABA4714DC37ACA5A269621396105F8C4975C3AB7C0F80AA90F4510109AE250600C2B1A6F3274A6EEE451E19FBCE34F371F8DFF7FFEC59238F87436253BA145DD163AF8EDD0C8F8E97DD4A2E93F11A300F81B7D3EB1C86F6E41445901AB8EFAE10C2396598060992BAB0FC2AEF0A1D0DBECF33C387B77369D8EDFCE5475131465C5D014D871600E45A414EC63425CF44432E67D86282577355910FE2B3F1BD24D52289623E4A97F59980AD7DBBAD95FB803627978E01E9D7061FDBBF00608F802690AC593442E989948B267601BC218F04EA3EA35B20DC910738818078295B26D1DAC60382266A64DBD1C6F7E8DE50BDB11E6F7DA99FE22C231DA3DC52139DF05B15E4AE12C274FB2AA2FA4F00236A732124ECCF699D9DF4E88BE06E2B1FA57151F361BC3F899DD0BDB35DC36E8EDDBF6B10B6EDBABDFEFE968E362A1EE44C40784FBABE2BF3101A44756C0AAAF45A87705AC5290F1FADFCF8A8D8544014587A88AAC922882FEF8556DB2D587CE3F9C6A48CBCFFEB682F3FDD8B9E6EAF45E0251964D0355C67882942CD6F9D0FA95C97AD53B401BF348630D484FA4A38A3CD647C80BA4FF99B782CAF1A132024B3613930C8002A0372AF979CA367B47D0CE33821ABFD12990D1ADBC124B08DE1C535E5039D87CDDA29433593DD6697A4D33C812D96A8B502B2321BC5E045B0E91567E8E42E97BE10CDE96817C4C17F0DD255FEA6A4DE09B359D68E535599C71208FFC429A4507D32B8D5427ABCF4E1069DCD8FBD89FC8C97B993B0AF1DB772A5620D01C81FB01F900B2774DBDEB288A1541A614BD5E0C1D04F0245258DAD5F4546F319AD695FC0B9CD08B74922B648541C0457947E52A794BFFC640572130C0262369C16AEE59B5408023AD015F747A8251F667B84885563114DCC1CBA1F2BC772F24EA86E6A6AA38B2AF886D81A9CDD5CE3422FF238E6AC6F07C8B96B6EE9645BE431BAAEE72969922F2193C085EF04DCE50D6BA7054C5C2EEC4E8AD6DCF8A95555A2DBB73020EC31A8E091B1CCC86267825BE7C916248BDE7CDF0CD7EF07C926B5CBA9516A1A6F0B7224CFAE79389957827A4C380E081716AC4AA27B2F81F4AA8426BFEF404535E86EBA668FF51F4C5B478B8DC3AB71A6349A8E3C2E28ECDBEB275EB07D671678179FC4F5002C83DBD8CA8BEE9E04CE6ABBE505398F58599481243552B3B54BFAFCA32ABAEB05DD5DF26F124B13A430E16E1EB41F20AC5981842DDC8D218FF65D69A7C5E4D2B34D130F0CC6A9CE4720FF52D2E4C3BB3ABAB6554BCB1938494B080CB164151D746182C27FA4015195F68F7A6FF536534537712CEAA98854F1BE88FB902B1EE9388405B467BAF960AD9A7115F61E71EC8666807F4521D5A436B7B4A2F6BF22711E253633D0B293775EF550B4D0FB084C36220067891EC7DE5E16D0106BD10CC7C9AB8CFA46316C426EBDA58AE11BA7D7E37396C2037F42664E09E4F95158A59E463900A55BE6157288B3C87934F26278BBA364014E3E74427EBA15274CF832049DA4B58D280BDE1FF84A7DCD5593FC48F4661DE021B1B727DFAF1783CD1B83FFEAEB1B53DDC34F51ADB4697F48DF2B7F0AC8DF45E6E72A38A2030583877AA9871D282CDEE2C88CCD162BBE1F90562403938D55ACB8DF04AABC1B3B45B98EA17FBB795B6156F8D0CD9DD02F887CB28ED04464FA2CC5560BFB9F0843EEDFBBC2FE1FEF61317C3B422B105FB07FC8A916818987920406DB2D2D993BA3F56E51DDB7218813183D4FF202D6CDFC92F6E3ACC2AF6BDD3BC75D070EF1F2898A54AA5D467CE831F2AF74E2075FE543B89E96FD546BB03A06D6BB7ECE0670B391127BDBB41F96C0B1839DA212D8BC3BB7FF6D9C22DE0D4BF07650000078B0E40005527D848A92BB07A0F20E11316C72B8C6C7CBDB1348719607232DB3D1FBFD214151575E7D87ACB6DBE400000000000000000000000000070A14181F2A7515000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 40 iteration(s) +mlen = 32 +msg = 0B23000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 3D0F7F815DF664C39FD42E0B8409B60187D3D7E0B32F7132EB739AA56184482A67D2834185BB705068F6B525676AFF87445BFA3B53862B716EE41B95A565B5EEED7A7E07C873B22D48111A525D46E08338F877B5AC39A52B92437D378045ACD64C52DE02158015A57CA60754D5A0AC7FFAD026D90B3C7ED8A2B05F4250842C7D6263ED1813C8FF92BEBDF9A8A799BECA22C1DCC19530CD3BC4E7C9B562A093987A0B663B0D75E6713CC512D7568DD84035B5E3A2CDB2D81F796CE832A8360939E3F642E0B605DF54C5D521BF282902E593CF6FDE287D4549A3A7B958B6CCE8EE6095DB422584DF359FBB243C1025C4159CEC357712224F66A74344ACF0415198B91E66C0E6D765D2A203B33837A95DEB4FCBAC755C442D4FB7D56C819FE000D3B1928C97B18BCDEE4AF3A261804C317FB20E926DABD9C4A28DECBD264D70A4A37C1E68473C16A34AE3B708F23C9B927451F9E6CEB565D5B3EC25408ECE9DBD0CAD318F7774E691067D353D01A5974AB3531C1B3D2E5957B50DACB3415AE10784B56DB2247538490D46521CE0C442833F08A8BE8D8785C4CC10FD32F81C1F15BBE9B5AEF3B6474AA9351FED8F452480322016B757CE348D3D64B50BCAF3CC7E279801B6200526BE95B2EE11308CC831E1A6E2B06ED7585062184699774D3D7D4ED0D69196450B0F07D13D042A2C985CFDE48692B01606FEA78DAFF716F1264858DB1A0D495837048EE4BF8C0E341DFE340D3D854DBE61E77AAA974FFE8D75A716B0E6D9008A7213CDA37DAD64111A970CA999A257022275929A85A5AB04AD922E1A7D80BDFD683225133B0E575DDD139D9B6C792D4AA72F6E387A34EF8334F48ADE8CF6700CD875490B9242DF1C27D5A18473B5C60F1D3FA643DFF98BA934FBD03E01BF06737D85D691448CBBCAE356B9ED57737279A03F00CF1899082677900DEF4FEDB0FA3A9BFAE9C3589A116AB4CA4B8D14374C6EA7B9D61E7FE5124FA0B21C9ED26BB080BEE74949BE011D7B743EB21639D5EFF564721FE64B10F00795E854E2D35BB99C810AA748F1ACBAC759DCEAF5684580C9E6302E2C7BE0C03404DA2B273948DB1F31C69BC91EFC14285491F817A7CA71145C1EBD8CB27A21F323F834B2F536070CC410C47D98AD817D5D53088F124540417CD279FA43FF2F5EAEE6991250ADF0B1A70CB5C450DDADF4591EB9C22BC2A8445C44CCF8A9F314D667813B8D399B975FC19C61A05E1BFF417C799F745203351A274A0515A5CD72FB1DC3174A17C459643FD29024C457ABEC8F947A447B2A55A144C59AF4431343F803E75A57ECCB7EC3D165BE526A5DE953E9E13CDD3E552F572737D232CE13F3A20A2517B2CB33A50ECECBFCFDD54CE8C14A3EF29A9A917BE8409A31EC33EF31040A5D18E720A399E6B7F078841534E1304880C9FB9A466F10A6F3FE71E45C3E6A87FAF9331A39B995A096CE7E8BE9211AF6AFDC9D7267C9ACA5CF3DBA5B984E78E2F009C161D483385609B50EEA31FEC821DA6D51852BEC1CF0A3431C09CF9FE9EC7EC1520B64CADA3530B0F26DB7DC7AE59F02D18CF60D851B5EB812BDC0B2BE9F4DB821A4F6E5B6B0A53EA779BA26137E81124BD441F50AA0DCE7F25662D5FCBA158D2402A7C1525241E178C73E28DAD146743F2DFCF6ACD97DA4DCD81232E90A9178AF64E89872CD3EC31E0C49676366355EB516F1744FCA4291EF6D0D4C061C2AC3CB34401B3A9604B6AA939B0F2D2BBE443DF962FE61E350EFD0FFEEA025460E2D4F5377C24F8DB8ADDDD5D5DE73888AFA636411CB5AAB098787CA786F73858E2602FC7446AEE613823DDBF46D83CB13FAA41D12BD41C2A6FE4FE4F5872F15FAC2DA8DEEB7B54C0833CEE0F3958CDA91522A42110B5CD77AA77AD6E34D2A51BC1E109AE8AC0E63800B5B0CF477ACEC5AC787D8FF91AA9F73322B6C94D486F3E94BF4A9DC8EB1EBFF80DEF0AA86F119F3E37C61C4BCF7B483E8B35773397425A6F4186B9F32F32BD37C63635F1E49A8DA3EE5B12114DFC2B1A9788D3BB5AB07210E3D5455196D02202813C48303648BF6961A2CFA0F7004CD6173BC2B90FC0277122DAA026B94A492874A95E5C4DECE947EC8835BC9A7828B9615BC6DE0636126770D0BE74A8FAED95BF9DA614DAFC58D3E4D214EC7F62D2F11C944DDF3CAFD3274AAFECB366B85CB5B8EB56AB12EEBD16280DEB70805E740034A280071EFAECAADBFD32198CCABEB3A3C5EC15FAB6EB9AB01DE390AE0D76AAED650BD4E865A006744633CB10078F643B02152B9FBDB6334BDCC6DC2083D624AB9694224918C1AB275CF817D1204BDB3FB2D73E43602E6E02B1A3F1E7A31BB9447AA4F35F769603B47C32CB34778E1C13695F28959CA25489C08A5452FDCF56A685FF1CA77F25F8689FCD9CF6C7A2287F04F0895149F1CD9B8E2963B14C136403DF7618612105D43E2224851555C4AA55D2DBAC5FF0FCE0AF0BE2B637B41F625F3DE9944FAD33E30463D3861017C2996A814C18B257F8D947AB09740605AB40B2764D7A82C368BBD4D9457EBA6778F3CF0A63B8D3B94DF91DEA7809B8573CF00A6E96AF1754FC7F0CCCEE04ED64230F0DB9CCCBF2BAD09AF509B74FC6DB81BB30377BF11B35C42CE9F3ED2F95C487BA6D88A31CE77668F5E9720C497153024C92DFDED2AE4E967B1A5C8DC1B05A8F9EFE9CB646D5B0BFA4047DD3F120C7ADB5C4496824E68B34138E0ECCB2B1EB72B32D72F7F8F83BD95BA384BD9A8B267037EF62532687C10A0316D657895C2A1350C0AF9DB0773760E36CF5EC22D98B0ABE4C528DEB3C6EA8F661A909AEE5190B9006E4F34FD26D92D4F4315CEA2D6A908E4E597CCA6A4930FE28BBAA8DBAB549C12516707552BA07612000B99D5266FFA583709F531FF2031D1B93B5264A5D0B0869E1DE7A19A4A0A0F8B883B382888488133A10C4EF5877013E76609E2B4E243256A2DDA313437B7B054DAB73CD15F8072D0EBEB61BC4AC5EB1968F23FCEE84C69300AF0A36BDC65D99F5A044A3AC7997926DE34A099B8FFE4FD7E0D2D0966AC7434E44D31127667BF1B65A9392741B1F6BC71FEADD1827EFB08841E519BA46067DA7FF47BB368748CD05DC48635EC4D4032C954683665B11D32EF4C732163EECA2A257FB0C7D372D255BBBBE017044F08FEE9EC7F6A9A85F994FC3E111DB886B29FF23E78512E9874F5F1DFADA017377EA16843C15C199F0D0F70A24641F14DA173319DCEDE7C6BA1046F614BC912AAD8D42550408162698583E5103EF8E7AA121967540138E88683ECF16D1FAB8F5725175DFCA5A9601C9AAF9482C99A14FFAC9013D06B0E24B5206B4155715519D8B5866051CDBC9B0364D84A07B9A615AA7E875A4CDFCE594B33E1CD851D3EB8C925133999FF6546DE4E0EAF9E92F7864237D07C021EBF4A80A979C3A5E667B6CA2671158E94071320E6CFF5A778B3874AF5C3B806D13C34FC3CD4E4DA97DF15D129647C14B717C437485168FFA4B11C7667DCC6BAC22DBEA8DF1945F5F8692AAB1A976810868AC5244958F2FAA92F0C652330B0DC9C0B6A480DF2C69CA2454EC86EFA4C2D2C6BB3E4C604CC895FD44DA5D61067F032CB72CAB9174DCBC833B724E1051A7B2E258A2E4401B5BE4F35625AB16E8D00F3C422865A1ED70DE89085AF53FA53B06262A1D0891213CBAFD3E1BE081EBC55C2CC501F0076DC0B0B64B543743747DD7465FD07E822346D5A08ED2CB6CEC8AE67261DCDB6E34BDADCA60385A8DDA1FA71619BEDE51A87891B8984C62F9B20D0469BFDB1E29D5B248D67108F98F45208D6E9EBD56694D3C049F97A753D2389D2CB021699D597D5A786753DC6E5E5997F644C2842337E523AF9D66F5B916B858A472978AD8DF14D05E3843E15C8C400DE938D9D6070C2ADE1CCCBA39E581EB349B8B04F252C6AFEA402FA3E88CF32F46CA7AF2FEAA71DA329749E389FD7C1FDD08E021C2C5C32EC1B3763454A63F4D9951EC32425B0A53A3D719CF9122C4B71AFBA1E4AEAE273915A67C9938241B6FEAB4076B5CC16527E4A8D5902A11329CD725EB67264416F227EFB5BB20FA59619354274E26208334C3A378E4A13165E67B559FA8400AADF09C334CBE808124D45ADBCABB41049C64E4C211320CC41EC9E9129FF5BE9F815FF9323D9924B79E691C801F626544FAB47C223D2B82B42BFCC82197CBA3F5BF013A06DCC7E1011DBD1E89BB68098311C8F6E998F48EDA82CC24AFB1CDCBF1D6538823C92F25F45D8919BD1FB8C4A5FEE7109AC8BB2CAE76B35A9F6429E165292B5A0F0D3DB6BA60015CAB94A49A781A2EBFCE784341172F9EA256785DC233E6EC90BA756784C6D52688415586BF77456D8F45CEAE5902D41A7CFBBBAF24E88D4DAACD8BE703113AA6B5597F41C46A2EF85024AE62098A88CE3014D13B9026815A18EC38AE1BF78F6B8ABB6C2556CCD83A9C3B0500B13174F5D52F663ACFCE4892111A245A46EFFF636E8552F634148E7D1865B070072A9E9EF986C7D5710599D850F463533B7079104DFF25ABEF2E13FBDA6C2EA5746DEB9E5C4EC50325F50A19362D7FC3D9335C367E096623A40E5E873AC05651086F802317AB818CA04455F7B85A6CBDC2B41A2D6F23536B0B90119616E989CB9192D479CD2F1414E578EE8000000000000000000000000000000000000000000070C10171D220B23000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 41 iteration(s) +mlen = 32 +msg = 7504000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = FE05190307B3C178FE84A59F36CE2FB27F95131D923BE19A14049AB595B7893A79CFF8E1FCE183AD1EFA99FEFFCA7BF8F441AE4C8FBEFA803A0B6513D81E4D82DD1C44E5B5FE911B5F09B47D9F6E5CD37E22D6EB7F8FDAB3591C714A68829678B4EB25B50BFC012C93E4B553EC942B43165C82E64874C312A29E870644285FC66C7B52C7A9AC9CB583895DF9D33A2E4D61F4CDDF75E735F4F406FCDCD9A916ECB9042D2CC52BD1849A09C042AF6AAF7339B9ED6768DF14E59A719939B2B3168B112A590E48773412FB4CF26C1FAB25F36E29F21D82AA1632A7D610FC34DDED48DC589FDD5FB3967E5A691C9941F4A4A9E2E9B5FED4A93DCA60599626D7DF865C3BC980B9FB4CB4F81BE8AD600871518401D82575EA9E976AF0AE28232F6783ED09DFD2ADAF75D335FFD402378C20C91D60B8146E9D605217945580E501D2EDFE626B094066DF77F325E6BA5A54E19DE6BB45A6DB689A08CA3D4B28A2FCC454527F4BB8CB89507B72D42CBE45BB72977A734DB9E7BC49B87FD185471A30A858D4B7E291029D7911854E9509298671378B6757B76D896BF844AAF11AE2CB6B090E012E1063CBDEE969C63D49E70E776C8C72C192BD0656633AE83772363F9439EEC8B1F72A31873DF3D46CF03B202CAB1360598886542EE06585225B21F3489130640532421C989CBCAB92108F0844BB34A59DE145AC8651862202033050EFC553A9335BA15858A51B7585CF345D8518CD547F8739FF3C95B16130A5473B6F4B32EDC1F673154981E95D439519B90DD96E64B22F710B5A502D8DAC2ADDE2F168C7A4FFB51DC950250CC207ABE4CFE6EFCABDDD5B074DC0491ABA4C8FBF8F85E62AC4CE181E782CEB0664D1F10776678C74CB00FF742E91279FAA64FE6AE22855A06E3A3A278B04F5EA28367A84AFD818891C00909838DBD482ED6611F9031E071A25B5E7227106EFDC53F5E524141B71BC3DFFEB069349F7C1D3A0A39F7C345D17F2B5C7A7A5645475E2057E1F551DFFFE0E43BA63F2503532BBEBA746DE9A071A581CFE19FF9CE1907FE2539EC33AC7C9E7713A714DDC3EECFD9A68DFE81BD7A16E05FC99F7D641F8ADC1BC896C42210E049BCACBDFF65E15A302CC57918490204C683F0BBEFC0D09DD1A7289213F39B3AA07FC4B5C9C6094859E5F1E658B85F58859A1C58417D39D1815DBBFA8CBC03339AA474767506D1DC9D3FAEC1B5257485FE836F0F8C05CCDA7BC71BD126D3DE6DD4C24FAA1BFC118B3E7971C1AE05CED4AE210BD7F61D1996735C56D6FB1189BF7A4A85C2C75A3FD8D726A31692F6C57574332D9723A23DD7AA83836B4143FBA5E5BB415695A5F77B981BB9E0F50F3A07935BF316E3EC51E476610BAD5C31BC68F26500BACA63FFC93A924453BCEC94C2E1AE503210C2108624D97C47E922A27DCC680C0723E43D275F357A691357FF7C192987B198DBA4ED82F74AAC3B340E73E1D887FB71755A97CE72FFB38D3C204A2FC227DFA6FEBB305951B6A7C84017B5AC827C06ACD5A11653DF27AD927B539AF41E38AC97452C877F2945DD7624BB37CF59F2CA2C4295C6683C5BD8BE3DFEDB3DC71267E6C823106AB00195160E8C9DB811550A807B531D8E31D0F4E13AE0936A3C02312E334FA5246F9EAFAF79C2782C502FF562A8C2DBF1B32C62D904FC62171EAC3F394E365F7E00278F96DC59E6F6FF8CBE6E74643AB5A5E554FBEBBB6AF3115D914D6FFCA0619F1C870040F8C9FADD4EFF4455DE64957317888E0ACA04D452CC8506D0AC26DFE538DF76A1761CC48ACB103181F42CDE489F424E4BF2F5AA86E5D0B7192F559D4AFB0886FF3E1E3306E234F80AF57A067252F7E89689A9416EE9F7B0C4392E86AEDDEFCF0E06F6F35D068EBC15D6A8F56E1B80169FD2184B8CA574719C0A155CFEC2AA38C9F8CDFB339C24D9A525639B4C4B895E84794C148D5BE82AE59B6CCAC97EA157E96F03E573FBF826273167CCE27BE7FC8B921DE850BC53FCDC35219223AC3B03B1F434C5BA11A20DEAA1164781C7D14FB0D6DFFF909AD97DF4DA16A648DCA7F8D0C5B954600B027DF9FCA9051A26884513799DCD7A3EA1ECAD9E2F0080A26DCD3E9A5531BE456BD6CE40A9753C607EBC3CC22BC9871AE7588CF8AAB7760E5E21A8F4E98E87544FC85525EE130BAB060C02F6262474E4A05C50B660BFFCE5BCBA156391CD2C1321D17605E32F7333182D9D31835B2F9EF2E0B064F9CD678D32A998912BE023A102216FD29AFCC9722EB827C38FAE1742D10E6EB7939E85988DE6C4A2C7A39EEBE16647E59970ACD67BB7C7F42DD003B18E131CDD18940F9220B3E8EC7B6191612E5EB2D5F191B13F68094EE204BAB57CEC4B9E8CABE35993BF48600751D08782B0CA58E4F2832F66DC45C922EB2765185F4656B2E06304F26281F60AEF0281A44919BBB32015CDB573C20BDEC136CBA26EDAB9B4E5BD1C19A06AE460F67C1D32AD90D4516B0AC6307A50030615231449DF1384124C9CAD8466B01E899CB65EAAC027FD4A22A0BFCB70E47DD9E01F24F41D09FCC8E2CE9D7C79ECCD8B8992D050147A26439CDB3F746A4F3C8CB51E3FF6E8C2BBC5A26CB797265B8693EC47135F006C08CE63B8596B2CE5F7B51B7B997DC3BFF82213213347889CC0BCDC47D8D311030F5C8B7B55FAB5DEDEDDEC8E7DEC50A3AFE32F8974A2CEB204ACC1E2C3D9BDB61FC90262B88904491331BD63845CAF90ECB9A2CF5477C782BBB213328242C27ED9EF3A5C4E561643AE4084E31C3DF1A418BF3F5481A8C7448EBE5AB51DD0F3BA00F71F59A59B531B000D8FB1C372E01991524079DE326746615F5F3451D483903E20A3BBB70D255B85C004120C68AA8969D911C825399F9DF2C7BA467FB7B08C182034C160E393FDC5648F44FBCA6F0F10CC3361776F35C4F89F61A2C8243F957307E21D9B3CBE628C91F82F119E16C4239D858A667B6D4DF1ADB6C500B94543441441ADC0616400AC9F312D1997EFCF40885D0E0A6AD7832D1624580D94BAC2A4680498C92159657D7606FF04195D69EAE06CDA609080BA16CB0EB1E38262BAD5024AABD87A732D5C665356DE842A1039E9B4C215BE45A39BCE4BA01204C47C7D72B09823C87BEC9AB0324855261B17EFEB231B87011010ED84F49A33432DF5C247321F70EE93A84DBBFE7425B4D8978376C9A79A96DBCB16DCB52B05F6B5E9F41C0BC97F39A2B2EDE586A6EB9115B1A08D88BC665FB37667BBCA06239D36C5311D1F0F3EFC5497AF69CFF6209EA92C1EE400667A6AE3AE471ADEDBABB2629C5589305AFB2574F323C575720096DB40B407884E89DEDFEF229DA31501FCD6F3FD81403C00FF9116F2C9018C688E9F87F8CFC6C91CA556D2B7AD20970B66E150F7363DA22B4A8B7B374C6952CCEF30FB5062576AA7FF39370066B1EF847445791EFEEB39B1763E8F385D7C8DCAD9BFEA58CCC19CEF8E64FA40602D209A6A7B9D65B013F481139C6CF5EEFCB90EBC0BE487A024A4BF48116A29F213EBDA7C4741FA228A6AA8FDC3D4C78586643C20C7332C926594BD10D238D7EEEB9A09281F87740ED00909A8426B5A7B57C77EDA274DC4CB408C0A16FF2521CB6D59DC0AEB8BC74DC677D31DB123E4DF6913865625B2D2E40FC31BF34690CE41DD561532199094B94482E5853091F8FD78337F72DC50B9959F3D875C030367F6CC7A8EE449383A8E525BC653C31878F57A69225DFD0919CC8D347787DB8AB7A76288DE3ED78A466750A8391EF7DAFBF6CFCA8BB644DEE21EE576D9B1A0F6916F537D2920690EED8B959497B3441BF6E9A05D935A3592BE0195156085AC204909619A570964B90AD9EE4AFE604E19C1277AA21AA9BB6A0738763B0B220E636455ED73D4DA20C137FF7F10692DB51E8D3FBB07DA60BF658BFF6CEB0907CC1EFAC9177702E09B694A1317003FC848B4914AC20BCC701FB2CD1F58709C275F1B3C839C2019FB564A610489D4EF2F833E70957AEE616FA316D0217BB1CADA518A5F4AD8D86803141AE180358CC16D3B63EA165F1578B07236B026734791B690645DE7EF29DF5AE81D5254BC24213A6A26799CA6E5C571B690FC50EDE7C79A547D7A2B615B6C6A24B377E10D4B45F8827FA54F4B40A27B1EBA16385E4D6332C29B24D3412780C117E49BC8675376FD4D6E389AE29F30425DFC6F1C744A1EDEFBCCA35F4F0B4630ED1CD887F1348C38DD8F8D71441AB63BDB1FB9D6379D7622AF23489C1E35E726592EA44B80194AD1D929D39C7951D071E3A5841075F830F9E5B9C38A8E7379D036AEC2B7730DB766AB9B3EB2294B0A2647915EC9C8BDC142E47EF22A7953B80D61188B9B71D720E03B313E97F835C69B78D8F37B0DB67D02FB2B0AA322C04375EEF24BA6277AF79AAC4A597D44905C736C2E7D57F89DC791150F0CAE240D8270F9A421FEEC641A24D8EBB8AD06663867C0EA93FB5DC653C27A7298B8B814110F3BAE23DB3598251BA1B3A91BEE607C889A9E455AB04C0CD84D84F642AE809CB09088A6C9EAB192B51EA5765F669082800321E82CA2FC9A1BA3D592A357B143D29D5DCA9E9903DACE7E3699375D21D7260768CE5D6F351090CFD2FCE2659788C9AE2F7FB0215222F3E6985ACEAF40D575DA7BBDA24434D565BA3D7447FB0D5DC36515259FE0000000000000000000000000000000711171E23287504000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 42 iteration(s) +mlen = 32 +msg = F105000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 1217E9D5818E6F067BE5D3F7E86622C2118C2A5CC0C45B58BF5F8E62A834E60A52EFC3C922F9FBF25ED3AC7FE1565F1D62F2562B39554205615A19F809040D25565919F28F8C0EF319B4DC89049CBD69EB54099ACAD2167F396ED1CF31F2D87A0141807883644211889C571C4F55DED7C5D8654EB069E5B05DBFD3317A433632523117C3F2E35A1638633BC47704C6C640F1980CAB109F2DCF5E6A9B0FD509C296560A17A4B4431566A4F04E58B8CFA7BC221973CB90EBF7DF86A8DC273DBBA0BED62BA36320198B75F18779002EBB5ED5C44EF722F850FDB656E5B4565234694A45C2BF65510905950DE82145F4E1CAC5B01C6A03017AC4C21A068D6F4462B6E2AAB754CE231DDE7E21D06DAACD2CD9D54C225C877235E81CCC85B9649FCF241FCB9CA4294EE852F52812661C23EE796A28414D0846EFD3E88A0250DB787EC04368381D5A769C364EF51FD55FEAC6D51EE0A9048E4076BBC57851AFDAD4368E3B1A90DB660D908084EE45F98CDEAC8B321A99CD2CD7538CBC3A364ECA4FB6003BF6AA681B93E207D252EEEA027C9C14199CB15B4CC0E4BC6E59547B6673AE37E02794B8CA1AA16CB9501175B02154B45083F6C34E39CDF47C1548D303550D9E7B0AE083132B67708D228F7174F67561BDF230063BDBF3AF4A11BF0330E90A0EF2D0E6C1410E8197CA8A5E892AAC94B78DA6C33DD220A3BC6752729C564D3670A9C127B88018D46E58062C9317982ED91F53DFCE78F958508CA11515B5072526751A4B8A5E8066A86A4E97F540721372F1960B1D3E25E89D54E75EE14BFC2F1B9501195CF8F20D6ADD1A32D0C936F1FC351487AFEC12501C0BC1BFC7500076A9D50C2B1C4129B8D0438CB8334144906039DC1C5D97C88117C456E6E8F66DD13E9F0D4FA3C5DB1F0E529071AE4D1C4C5053548B43D60BD6D7EABC2EF866E26BB809908BD90C359812EF913CD92EBA8A09380D447C54594CA768FFEF320FEE5C7D2695585AE26423EC09D3421CF46B51170D7D64EEA5C668613D5739BAA160ECB26A8502422DE2B10A9BF1D51526CAEB8791195D8BBB45A498E1D5B3CE38F12841F1F47028C95BE9ADA9AEAE76F3ED2E3F82F96BEB319FF41BBAFCA29E553977C10D422006981DEA385E6189A9C63168116F97FCD88A78E13BAC20CDEF4E3C5FEACAE81A43DF02CE7AB2EE1A8EFFDBC524BC55CCBA3192F6F0A794A3B8AB1D0EAC8640EE4A8A9CDE0110EE9557815EA16F20DCC515F919EB3ED722C8245783ED374A91B57C4825E7D0887B63AAA39688014E929A46619A0C5C2E413F2950467B6398072D3CF70A636B62439E80E8ED04D24AEF6C8C8EC3E3AEF68BDE6869614BF30125DF0889B1A903C9E930665E314917C416CA3AC2FC9BF060419F690E97843BEB7F6B27D02D43D3C9427F0697892AB2B820D2EF0A9C319990EF6BBE7F1D0F3C4CD0C827699B37C14F6F28426340E6D79BC7783AAB36084BDAAFB536D1AE4EDC8F9D1D0188EEBD0C3DAB59F8C897CE73C8F3E165C2809DBD45972483984270ED76A6539BB08630FD5E8B2532051AAB0C9C74E728A52AF4E888ADF151556B90D6D1DE6A65434A650D21085E0A49A7B9BCDB9E7D4D17071F6D06CC9B3B394B799F2BEBEAE8E1359EAD7A9B565EA5161D77DDB95A682D500784A961CA50857467D3281AFF2D40E9EF10C4FDB21A2EBCA52DCF46F5FB14BC808D0A0E8F4D308774355FD9FA31F4E5318B6DDD92445EFD54FA93641A99D452A6BB6D1D403EA5C37C912DBD74A58590D39168B2F21A9070FF57C408EDB188E224660F5C8DFF11805E2414257AA6130A90987CD065A3B3BF16671E2D21629F7FEB8346ED350521F09CF44576136903E0B07C81CFF80550240D5CACBBEFAC2B67742623C9D3FE822CB4363D38EBD9D59614B08A8736F8236701A107C19E0DE8080004B722246578E794929C823C1AD79F2D5A428B6F5AEAB8703857A98E1C354EBD797268F88F1C77F17AAE27A438E21B25D9580A0D634CBA30C5C3EBE31A2692CF1FBAB42B3660474DAA29A37C357FD2D79DBD0E22AA0946DE5BA5335E0DEEF7B0A4D5AC23EB3538C327E835B2DAF74ED77005088AC75B0A08D27609DE4C77AD66BBD9958C6B9CD4251CE9D414DF8DD111A6BF35AB015CD436D860913A5253896A803B9BD1D2504DF18D7224071DC223C506F1EDCC96E26F22619ACD8616443DB41283ADB9D1E54B1774EE0300068BB7C959F46A36BA718FE716B3B3945CBE65CF1526CF66A52AEAB76B02FF993301CB883E5654FFE3E3BF7763E5B8AAF64F764D10873A6087BC59F9B76741A7C441611272E3244A39C74B8A7FCABAA0B61A387E668F2A99CA35DF13F68D77C959B6C607D7E5C9B7D4926DE0EFDBA42864CD4949BE8DFA87118CB8821F6236F5E9585226400A6A636086D77DBC71F6856BC715B83CD93E628438E1867F67163FFAC23CDE81A74DFA8B1E265E562DCA1B5A881C85C45A21AB90533732A4606C405C8A04EE00088F000F4E9F33E2912C3D9142A71D2300654467E1BE688EC5792EFBA01BF087BD36D15855DD96C417BA652F0386633C9151E4CF33209D93202F7D71DCDB51CB76A708FA5E23B070F95BCDEB99100555E8A64A6B84DC6D51504BD7EA24593A32223A4F1268D5D986A12BFFA3AC548B7854CA02262871F7D20E0708D29AD7A7635C537A6F5569DE2BD4A9BF41DB3B357A181FC8F3D4277C05C4A2A98D8A0A40EAED01AA4A84E00208BEE78C70B13EA5DF61DD9DD63CD2AB8899879636EC575A7668BDB35E15CC2F24F8B646FC54049DF718288C8C414F3CC1588786F40C0A5D6DE7CFBFCF02414055035D6ADBC30C3AC0D85FA572B604475EE6FFA09B20DDF23847658C9DD44F29D7E143E4A23E4C4F1751FC74107BDEBF45BA1180880EB036C14E71CB2EB71260F3DAD56D1CAD348616446E01B7E66D64491034BFCD447C1A8570458929CEEEFBCA84571126691D3DBA67994BA84E61FB4FD6B66122BB61A6510E7FA8EB284D1AF65D25D5ED756A92DD5EEED49A7E19F9210C783008EB193A24A7D7258F0A89C7391912CD81545233666FE675C51907BABE9D24C5D6524F307AB6188BFE5451F23AAC9387ED87DFED2348DFE60B3C6D620D0632828CADB5C2F69A4A81855088EDC9843FE34841C2C01696B183731F88002F4D0C466AFEA52B749F317CABD628A74C869E96E1DA039F732CB7D15773B71C4D2A1F2178FE7E4F64E007288C5C5E3DB21DA4517613270E950B21E8D8062384BEA6C1F092FB9D0AEE11888BDF7065B154A343EEFCC94736E5E375D3EAD8A1409F41ABF4C1C08DCCF3B4CBCAD8DBC31B593009DB4CD25016F90CE177A5E9B96E7CD972E55B2C4E34A08CD75123465A58FC4C34870C787941C5A7F619848A2B0D90F2D55BE371F4F47B706322909B45BACFADC6C290F17EE4DF30305E04315063A02D5F76F5458B6A22EC1409D634AE43ACDCFAA5C3A241A67C4E938B436640815E8C529BD6606EBF282482AA5C384DE807C04F0BE2668A6816868E28BC5863DAD6FF0421B84D35578702D3CAD09CFF953BB421D260A2C98EEC86BBA870F545B3D160643463700ACF522D665AE38498E57CD399560B41D923F5C2A564067FE85D9EAEF21CC0133E91607BBD0FA83DD54404847D82443CE36EFDE619DE2882ADC72A79C2A65798F55DC2EF5F67A4EDCB871E9D5F2642F36693BFF3D694817E308857428E06B42F3681AE08ADB354BFD104FA3BC2AA87173A1883AA0F28256EF146D4E1A5FB44ECA834CD652D0E42AD8A681CBF24BD0DE427B03093F1C0A7B3CF57359D5BFB8CE15E8EC8AAECDFE1B26AB5C78A6A523F2D9A576F4CA43F8365E412664A3D4511A42737A60D7708ED3B11E3BDCD731C07002525B13E0F19A78365BC6CD33E8CDF190A5BCA4268E0142FFBB3DED4D3D49D385498B05E4CEC7F3B7703307DAD2C77FFBF10169CD0E5ED0FBC029B3C3455A94661B9E8138E20C262FF3682BABE6A8D97476C01CAC2E46FCA1D788F6381E0561D3C8BA3DA8EA09DEF32D0BD6262040F4143E82122417801E88D693425B7B243BA19049D275C747EEB96F63FEE8D3B62900352FBEEE3C367DD9EB1F97386174084C3E7AC78C1204B6032189E5AE1A4635D59A4197E6955139FF9E3B4520FA30B397EDFE36F4C947BCEBA45C8ED8FA289186FA7C7B381C1C9AEA249302B5E07C4FDDAE7270F45188A8193C0917B694BE541CF17CF63DFAF99E1DFD98318405BC7909865F941E26CC9C0B70553A49F9B4A41C97A3D09FB49116180564724985B554751526F89A3C931A18FD1355F68F3F23FE9D04A965015F1385F78CD68EC5A91B7FBB2AE85038B3458ED91E82DD966CCC80B8E85243E390A2FB12907110A3F6B02FC851758F32DD82424EAF9621B02D9AFD391AA6BEEAFF717E051F68139EFA1D36461F577307B23C885BFF1433A4107B184457A6560466183154C02A06EF149DA5603363A4FB6F3BCC6A652CD6B6115B83E89299CD853ABBD58AB459F487E8ED27A3896D41E47BAAFE0B497D07888123FC03B54C9090DED58970DA8D0B4DD3F5BC9379D78B251ABF5F1A02FE0109908533A11AA1AD15BEFF490AC7F5B666CA5DB777D7EF24B71ECFC1D566C999BB0FE535B6BD4D9FE496F96C6E4EDFBFD00000000000000000000000000000000000000000005090D141A22F105000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 51 iteration(s) +mlen = 32 +msg = 5F24000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 9CCA8ADF0460CC52697CE7610C5CE0D876060DEDFE1EC0B2CC26B90039987757809CFDCD227828A160C27F96C0B5B395AC34B6184A828A0971DD2C218163558E6E7FB6C0AEF05FCE80EDA92BFD740AAB1376CB01595CDEEAAD7FA757C0AD9D603295C3FC1B5814E2A8BD33B4FF31425CF46C832D4E1BFEE3D02A9FE8804E662AE91EF43A27DDC105E1BC4A279F82B7DA4FFA37BAC496ED62E6AFCEC0AAD0FAB378C5A266B6885EB06F506B7E44A2CC0AD60CEB9A103164757ADA2AE9DC50E2A3A5713A7EDC673368004C81A98AE72C51374456546198785D61D1D99552A4F942289508C16F61E70D732627238A7DC19C0AF92B87C256AC229C1073DA067EF8594D0BBAD6A5488B1085D4892A64460D32AE6BB3F7D33D15087C6AD9215764E89442E303D3FE68397F958ED67B0C2FCBBFE6CCA89FBC5D600CB8C30C32F8299B0D24439F11DB2BC8A77B78E010FE3A3FC8E7C9DDF28D20EB922C5498CD4E8AA96C5B9B1F01F79FB2DD03819C7A30D74B7A2FBE43D60A88A7B531B251D2DD675C6F95A76996714756B0B44E87612F19C2F211D16635B6471028672E4B8C570C548A5E80C7685FED950A6EDDE8EF2DB0178DEF727EA4113749BFEB58CBD085CE897D0F650BE44EDD3B56AFB334335B18BA896A86A13123849AB7DED4FFB7FD33CDB036928882216F399D1E6B778BA6F922AA7536E4AE870230B0BEFA0C4647B32B44C644A3B7A0ADC003211838516C86EDC1A91029AF654B395ADB354BDA3FA43A52AEDAFAD8065FB75BFC0D033370E30991E19C1797A75614100CA37B432421B954ADC635E489DBE75B7C6C8C55CDCE65CBFAD6DBA32A8313464C43415181327B9921F4375CA72C433F749E55B072A05B831F75C6CC412A773376A4B12F4FE6F09D10387A0A3B77780ED8DF0C1F2D74F040D22CFDCB71DDADC6F0C00CECCC2A08A8708389E0F3EAE60B6743FED338475ACC5F95CA0B437F3A8080897C0D199E17C1A19B98CB3080C0EDC38E0E6C469273804D156065DC4538715215F829C771EF039F4ACBE0AF43B6085E8525E130215F049CE3EEE9C753A2FB739874A8A28B45D67A301FE5504DAFF4C940CBC06CF6BE222317E44D1099BDD0016A939CC6FD19F0E9B7F4F55B94B21CAFB9FAA5212CDB78B4713F5AB58322ADE42695C75B06B74659B54632CC43BAB1B7F4DB55E32E5A3F8B0C68E733A0F6426D2D49BA03B5AFA121429DB31090153BB262F2407E8D5A2B212374D05F05B95C9D8F29566582F3D202D7C24954C7E98FC586B00EC8F242226835D5C0B6DDB1693142AA49E277B94BD126C9D1DDCF73AD37E9360EE71CD5E19F30CAA9BFB0B237F4A5E30CEA16A00E68878B6F8D1EF1E0C6D829B73D01C9BACA3F146E55C470EE867B5BCB0C161BA873A0FD9A4D9B5C0986C95BA8E6E3C6C8645410542F1CADD83439DD38C94FC792FDCC18512AAAD09CDCC50A531F145A29BF40B7A817170A7C1A2AFF774F32440C2B8C91182EA1A6AB2B548F068F5032C28629EF241D743D45A690420184C58E17F2ACEFE355B38A14ED30849862573AFB010FB13FBEE7DBADD8E0DB68C327F0F6F77F323F06E6B6F7F9088A872A1AB151FB6B5C7EF54E2C5EEE8D094ACA7AD38C9301B3C1E38066C7C7E12CEC49688F7209735A5498B1A390A2FB36FDC59408F8E843462874592B8750E15845FED34663B443501235028108C08EFF7860DA995BA221A39370DABA9EE5528ECA9930842F042C7907F3B0C8C50D9427E9256E9BF56DE25D3CDADDC7475D297C1FD7DE6B4E18C7393956871FAAC45467CA9EF5BAE49BB2DB203B994A344C2231854D05F053F29A0718DDADF9FC2C4CE38053517888C3A3E58A1258D6019CF4903640400555AA09E6F3D979CA764F64CB75A74B6C12F54AB2E6CC1F6A744636034FF7AC31CC7B2DD8A9DDD521F5C3828DB0F74F123160332CC555B285DF68BBA0BF76BAD472E157217184AA6D7D3C4947408F7E71A0C7AABCC5519EF8ABFA56B18CF194CB69E38EBF57AFA6C776AD12325CDCEB1F5D96B2862D403C30174ABBFF700A107E6AAC6ECC80A554C29BE4F311A984039723BFC60EFDDD16D6EF3D2040882D8033C03465D0659787CEAA8D5C2338F437F7C9CF97C902882A5B178DC40ACB9934CECDCEC16E2A5A4A3992A932E45F577A7DC4CC204655C07374DF197A1B93C7942A476C56A9295E123FB2E3DE30D8ECC309D58486180C3BF4B9D889FB32A960447797D232BA3A201B013C6D625C61131B528DF2499540410BBED33BC761DEC3C9BDB01F2BACD119A14886098734A184F558D88344B91E480B456D46E81348EBC5578EA0AC20811B667106015729C9F4809399DCC46D480E89D0F7B253DE8B5DE6C2E024FA79352F21820CEEA66497396EEAB80993D4A0CE62B056F8C7C7C7AB938B7FE84427274A298E07F38A4743CB02861F9306AB36CF63686CF22220B179BCB1192B0391DB03370B8D79DEE6290C0DFA1179BE1431678BA31ADE9A1FE07B2FE77D1AE47218BD462A23C3457EACF619C07327D9263848146B4C5E3CEF0C7FDC9443874F79883EE39C23E432C08695BF30D05BACD7C66CA8FE722FAB18C074245D8FBA614CF4781F7CA3ED046614006A393FCF509D8632ADADEB099FCDB87A316BE1E01F08AB6EC485E26EA20187256C31DAD0DFEC3043ED27A416EF7D21C592005A1C938A4C76D17B58D16001730AD951BCFBE1C761C268CC7618D13CED5445A3F5F1C114030F96BB618CDF3F97CB7A86BC2384945C4B66ACF1481B0E280487CDBB7187D6D70035BA4C8235F638823EDFBA8770D3B587AFBCC7D5523E0730B62BD703A762138764DB6061829C40CD02B64E6FE74FF8248CF3D9380837358C185A8CD23FE69D2035C37263002B4B25182D68DE82665BE120329C483EEFFA90083E266932666BE519833C0088065B905B65FA87087B71F0E7686FAF90AC320C02858D3DB6E229D7F422B8816980037D9B2B1A19F7FAA771FD43403F98D1E423DC3E5AC63E90D7A03CBEE04851FA61025B017F6FC65AA319D6311C5CE65BCB5EA49C1345A7286E447351601FEB400CE9252789BA8C86C84D98B53FB9FC9A784E71252FD7C979FEE27EFAA21C1180D287DDA8FEC742E89ED164CDEBA7E049D7CFF09729A2CE51C678404E7EF88784E1B90959D58D9AEDBDF77C27DAA7E6DD64216A4D1A5FB0FD816C6777F1432285E34E400294A21B1DF767BF8DE430D66A4462617CD4268DFE401812C65259BE4B1F100BE09860479BC056F2FE2276B8981B6178BE861DE3BADF6297E76872FF7CBB35108C89037702DF1966BAD37CCE6BF82141D918453526921D518D4C6BF2491CE2ECEFB139D712ABBD1D90DE52E17B486A20815DC146732173E583FA1A185A447329E340004DAB67AF10FC2E9A85C349FB37CF5BB5719C550BDF2E06C471EA784EE06396B2C9E1253A6A6D83280ABF9EBC7CEFB1BC4DED49881B293CC34FD09B67DE7C2B25E2EC16591DEE608CCC7D79411399BFF9FB8608CEF0B87D2709475254EB63751A63852167414CC51F2410AD7FD848158C90C82FF7173142F6056EA432D6EB4A91E119933DBFCA056F5636B035038992498B66EE9653D37BD49403DB5CD7DACA18D1D3515E9381F9EDEA67DDE2717A5B07137D50593DC0B94ECBB91C1F21926CAF33E1AF87FB8061188408D85337548CFD4CB08BFB8E24802A61C43C0263B1271AB3C02360E16C19C23A641A59DF3BA92E6E24139BD4CBD4F342C2638EE7ADA58B42677DEC2EF4F57CAB94BD95862DFACF65FB9028AC2223DCFDF148556951372B4D6F8D38D8D831676C95843394ADB32D7990559B7412EB2A72E333519F295BD8A5252310F3E7A42998B2D6D31D44BB072A4F3EED3BC7F4665892396F1C563CC9AA35C7E4ED3BED0892076907020DF57838404E162EB3B28956767D71B7FC7377C00882E18925BC57440A367038850E7417F5C7BC4E42AF7BAA0FC55086A1E3213D188F40D54A8296460DECDFDDD341CC713BEAB8A3D7C7752EF45C8BA7ADDA0A511FB3C28BCF8BE5D01B31D72F2C8DC0214B3E25B1702B329D7FA96D1EA15BA669F21756D5BBC36576A93C37AA94EB5A8CEB86FC17F2FDC1522F5B6CA074BF3AEA170EDE6E74E89F4D444CEE9A44CE03C5F2993989AF10ED2EF9A7CD40E3EB8A01D20068F65F9766002C7202CE105B0DACEE1658F4EE2F0E8E91FE4CA41135136A849E67F998DF5BBF9897F8C1818C8F36A79045B17EDF5BAC1AE0D1C6EB2D73E185BEC0D4CC7CEBD61F61BE28D41178A13AD0B85D653D1A49E9877745D2E0024035B6E2F54EEEC23FE5888732695D417AECEB0C4967DE64ACE7D3DB409090FA92FCD0A91C5A695D68980A7E52BF77C932AD2676D193C723AE0185287D249621174EFC7AD8FEA0E7DAE70C7ECE2B74A4871407AA2A4DECD8084B4DF3B2A2FF1D49E9091A2E080C605696DC3B156D603C62B480A03D43FBBE97C00B8534E19B11C6A67D1E66DDAE7CBDDF2D89077F53FF5A3592B7B114D8E3D4C9957DC0B8197B97AF45EF3C3F990A342844089E6224B96F5036233FB1499F458291D7FEF706AD9A46C4D47205BEF94D3C9723CD7F2A3033607084E30D3D6FC60C112A718B1476B8E21B398D98CED3DFE906174B526975959EDE00000000000000000000000000000000000000060A0F131B245F24000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 54 iteration(s) +mlen = 32 +msg = 9F03000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 751F8773A0E4EB9A2913518DF24D5D2A1A35D8BD92B6E2171FB43820F034D08E87DF2D10FB8B86DA69230E6231FFA2419DA923FE0D06339558C3E69BD332BD1706B8CB0F662EB8EC576400F2AF0091D3411091C0EE4AFD6B7E2070925009BD76DC574940D83621F664F107519A59A77971B08CA011798EFEEBC363B41450BB8C8819E4FE784002AE579867814E6A6392C7FA4964639570B9716A7242F57AC9EE59F3B99E31BFBE2B513DB90EEBE87B114171903817BFEA16D4B5073F4D880821F3A45DA7F206A6B7A004992B912EC5D5D13628690B76C19EE3182DC2B74FD7F620AAAFF3A028380AFEA0C92D7280D4B16A652E7753454E781382B559DCC95D05485A11CE45B0FD7390E280FFE9450E61D3C9CAD6F63652B769DACE89F3D9DF3B02C5E1460C7DF059B6B1F651324CC38F983DDA8EF1789DCCD8FB3045969AEAD0F6CF97E9C55E2172B53F8B43D1C6A4C576AE5B2832CE2B373260D9EAD91943B6F437A64C826BC0C0F518226688C734CE088D5DA62E8D6D7ECD1674597DCAF2BD52EEDDE7E6750BC7FB8EE5A784023AEBD6CA1C5D627C54AD50A361D0F21AAB46A83C8703F823E32E9EB5AF3082554172F2B3F9DAFDB01B42AA15BBB9F6F0B369B1FA6C703AFFFFF0DB8559DE5B8D54F9C9B0FDD16103AE5C71900D6869530658C9AE227756F1B9FF4354B10141A18292F9E9C527E8EA6E0DB395AF07CA104922361F36C7C56B297B5F175A701D3FAA988D4281244AC4CF6B54C54EDDD896F6EA9340BB8A30E2B1462A231FD3958141B3D946D9D46C035D4A6614209D941273702AA0FC97E4DAE314FAD58497FB6BB858174C08300A225293C75E8C4ACE84345D53D6D90D15DC1780E0B9730F7623A35090409D28DD9AAB33E7E87BFC64E8996176FAD4F16370BA2FCA0D666DA4E210EC6384394797004FBC82027171384A82A7034FBF41AF22AE0EEB349F41C624F1C51AEC6AFDA131785B368091CE5AF0776F469B2AFDEBD3667FC5E372C17CE14D67CEA6610462A74C6FED92B10677026039075AA1AC80003016F0654E5370B16F69486E7D7AC6CCCC54527B02B9912A083F40AAAC76C61F6A617255E4271C132573CC21417CB86AEC5753D67323187A2E115D591DBFDC6C7FC1B13E7D4AC594157090912605EE74614E59F8BFAED0AA3716B15B53CFD83DBA8B2A9C5F071E3FFAFC9B46C82352B4DCA4789AD6D188E372274672E3922BB7389477B9B4C854EA5A4B7B20DDA6254C7681F2ABF55F9CBF648663623B77D7C6844E5D98AE4DE396E0AA8320B2E911398BC90BF7227D0B243179A9BCB887F61B184520175B6E1A0760A2ACBB3DB79D66055DD015D17D5B1CA2FF7D859A30385DD47456A0790D11570A83A74AE778A8C9A087B3F5B73984E5C5E5BC1AB11A24F1E3F425993228B4D06D61C87E117CAA4D3DE0E9BB506F3BBDD18B648A850F6FDF2F5E008FBE6368579B186514D4CCEB0F73512C936D226A8CEF99C763AB74EC87F38E47EBAC830F57B79901100ABB8B8E54CE99419E523834FBE8B8EC098C616E14ECCC1812BF347EF2BCF17EE1CBD3102795AB27B18A01C1F3E8FE9CBFE053EC55FAAAA59364DC757EFAE2B2744FC2C8F392464FB83493EC9B4D4960FCAA6DD9420D77C7A4C4B0275FE9FD215B328D057948F533D0CFBEFDE1A80096B477F27886B7F80D37E4A270AA6EF9432C5FAA1B44D5B2431F925D8865A288FE11B915BAE46F2D13AA29CAAFEAE8D0499E32FC21B43E7E6FFFAF5CAB0322D21E6052023721E851B2E7F2107847E6C4EDECEC99C4E10DC951C94B17C8C48CDF79B4AD4EC8F78E205D2784553B0EE2A73D1AC7C8889F92C973C90A29A6CC11D356BEE150390030AEA7908FDD173E7700F01A8F4322FBB03B75852007E671536990B302ADD831F0D1ABCC94B424AC08CBB197ACE78315C5648E8DADC90F6071EE21E5A5323C9D0B7320E834A53F34F183E6C467C5999E7133DCCD6F623051F5B98ABF20B7B6356A0E9D2608B2F00B774468EF17B784173301B5E3866D07B1D9C34A71F11FFB0DC7131722E0CCF153D821F4BC54F5D8CAA57F2DCF46552EDADD2B9902EB664A668616C08558171E0CF53DF6E202CDB96103FAE6978ADDF84D4988F05AF52B89CB387A5515C07C5B3BF716B84FD3C533C12BC850975EBD660C47463FCCF823FD9EECEFE180F5162B6A3059B8684E5278800138A728C4142A1CE6CD0E329AAF3C68C55DB00582E7E195B19D88826EEFB3EFDF03D930E0A28686A92A13A6F77EA30409045DF3546B85633B5C10935AA0D35C9FC5001B639A35104F79A4C384A7A57656D1B7CCBCD06F004092EF0584102CA0252806DF91188716A01797496348893BA73BB4FA61CD9A699B9C001F6FC1EB04DE9343357608CD12AE103434AE6DD30FAF45A6528D96F24CEABF34F06DD37B96C71F2D5D75FD3F07881C0D62BBF9CB079152FFF4179854DAB85B0D051F1F3A09CF376DA879647AECF5A30D534A3DD90E6FC1D2A409D58C96101024ADF72D6A514F5274D92951CAC1238F56A7D6629BA302EA8910925EB79B1C1F3A405D0AB8CC643D0FE28399E7EA5C40C99D2E6E1AA3BFCB4A9AA6518C4C59A792F5E238E2F3E3CC1DB3BC7024A91A7168C8FEA4D7C7100E8E2A52E2C7F37CF8043C4A1801D2744F1D106E850DDEEC17DC1DD02C20D59573C5A064693BBEA39BC454DACED714E014A5277D3234685D73BE268AE211C1E7414DA84B75113D6D45164F3EB39E39ABCD24961E048F3FA5CAC9D6B759248159970CFC0A4B6C199597774F0EC058C8EF6B6A33F3E94DC25EEFD66D7F7080280F90052986E7C3FC09ED5CF9564F84CCF9A60A210C3227F4C3AB98CC6C3AAA8494C9C0C6424B6D1A1F0A5C4A12347F3A6C976273C2ED32E148043068B1A791D21FE5C89CB3F920C3E88F78BF3378170E9FFF636E2F5E1FFD6A6EC59F1029E7C14BA5735618E5D2A7AAC442FD0FC3A9BAF78BBC299F5CA22EB3FC58CB7C6C4076EA543A06B95CD56B560911BF8D072D0E59E22C56875CC5303B0919E4946EA1307F2DE14D31A75E72E54FEB569E85A40E3B3D391CB5C91A11A6C7585EFC08BD32FD2FED0E2760435691E89EE7D330E058BB0C1C0F09561E15B9C21004EED9AB3C0C75174559CC3957D08E6F20467339508056F9C66B73C170F91B9CBBF69AD73BECFCE77360BA7753AF3CC9E7A853BE4D1C0881454548D5FC7B451A6955D5C2BE4D20650BD7F84431B6BB65FD1F4750897AD99C966928B8C6E5BCC53FD7572AC92860496502E35AA164B4D53F733255873C0D6379C5451D08F008AA2A65D43AA0721EA86AD968DD3C8F4F3E4D0F1B6191630F2123A2E8FE137950C253B0CF01B9739423B9FFEB12D4FFD0597A8752D5CE83B4C64F78961DE2885658AAD82120871D4A44CC25C815F61B50F6418F9FE3BED595A5CDDF333CCB98F9A15C1A7913C0C4057DF3425F6E19C6CD23F7F37CBC9E5E4DC98098BCD9758BA78DA394EC21D4EA9B9E9D5711EB0B19E1AC611B273299447BCBC9AB0DFC1BAD528E739265D616F709EC328C42630CE1EA22FC4C5DC3CDB78C632F370E18B83E747D955035B5139D2576917F558EDAEB208120973F4D090E2B9E91C7FADEAD96B493A78BBC9E787E89200EE925BF24BCEFCA795F137ECDD2B6D4470262ACB42ED7EB5B527BD4BD700CA30462F13C4A9BDAA11BB59A6AA79C969D7DE9AB00898935712BF0F84DEF5249168C4C7941FA98EC4D3165A547402DF49178E78E92B5B41EE037487847620A7E938A7428E973EB664DD3F01FA25BF7BFD0930440B349C3ADB06640590EC2B8093AA5306DC8B5BB60D89D0806E93F1A35ED0661F1E69B68B8F644911756A95115571524EDD5804EFDA23601D0C63B065631FCCA6271835CF54A1A1350683D4D195E222289E16C16CC30B1BE5890EC1D2FD0E03FDA62968BC8ABD12648D7CAE4126ED5D2120EF810BFCEBF5D3A937F7C8FDCF142B757636BFAFDD178EFC30B4965D011D3EE00122C1A77C1620230E37C0A507B2BB28EC5C41EE648A18743D75666A9E7039655A8BE4F2945AE0D303BED68C040B8438251C79DD2E6C18C9C667B82BB36DF86ABF342C2838FAAA4FF32F1893F2AF2C629D0EE7FD33A338F50EA21C2011B2AE7C42D5B11764025EC36A0C81B8A001AD8D94F48E6F7E1AB19C6A23848D9BF9EEFFF4949E117DA687D6AA8B74ECC7E5740D7E28520EC2530A1B2947B64A6EE661904D1277A1AA2AE63AC4D00DB200838101CCFC03172A5B7BA594AD042F68D0144E429DA335E54A662FB21EDA9C4E961AD9755BBED869C57484FF45BCC4B419C9EF0DD463447379C9F9D4FDA38AFFABBF5FF0AA61FBF29716849E8426A90CFCD707158C07C2C04C27F9E04356C9D1CCFF97C264335770B974746C940E9A9D820F48BF09EFFAC52C0E4B1640B627534624B84AE4E95367ACA8D2ED30D05040DE8565F81AADAD237C182F4B6BC30BCF56736DEAB0B794347979CFC363C92694B873A27DF3EF2921E913FD02D336D66F3DB23BF44EDC92E6BC3B5D2CA8BC90F5CDCC9CCBB111346E1E360C8AD030CB318BFEE4FE5158330DDD775278496B77B742CAD30EE6C6D6EE3114C566467707F9196B7BAC5F71974779AACD1F4F5F83E4898B922396CE5EAEE0E282E353845B8DF0000000000000000000000000310191D232B9F03000000000000000000000000000000000000000000000000000000000000 + +description = sample_in_ball requires 1 SHAKE blocks +mlen = 32 +msg = 0100000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = E1412C0A8930EBD5BE73CFF29B68C3AD7426551E499553D7CAB9B65A984CDA37D793CFA5011EF4470DC57BF0C7D1C25449CD23C82868180997EF617A42D425CC5E1DCB6127D3B60E017A9AE1AC7DFE980DEBB098F6099D4A5D497B0EA1A063F863D484A697F9E4B87652249301455276EAEAAE6E5B9C32991BB3A247F5EB6A64049C317A2E262BC9FBEBAA53E1203D780AACDF8D8C1DF9D104DB25002257CFE39C49E88EE0ADAC298199EE0285AAB5966C4DECCCDD64FF86A76DA9FCB17765C10CE7EE8272595B0DECCC58C8D89D11B78E56A4CC63B19D7D787988256A277B53BA7D99C1930BBF1CD550ACF5C97F6F1B1BBDC6A9CD0C3BE66672724E9ACD89240987B0B17F9BB38B8B323E21B7DF3A056B85CC41288D34707DDC050B8484598EDE78EA295774222EF491F0D621509C9361B7C8537A4904E2E5ED1640968FA6DFCD828C8BA6E771F970ACA894F0D57CD03CE325F4C3176B818F42F29C8646948B58796542DA63FFC905171129418A349C0783EBF5AE14B3FEE69492293AD3894345F07EDDAC036C40AD5215D4827DE6A0EA0B4BD2DD86826C7F5C340FD2D62062A41C075259A9ECB3ACE3722D3768D5A7D355373E3DE4D6F87A408E5BDE672F414826A2C6714A706198723D6E41FEB39302B155F775BDD01B7CB4925B75AA1D0A0D533A2FBDABF68D03592DE2B24A39D2D093FEA87CA57E16622E59B46988D7057540A511506C1E7C819D8697564E161FB221DE02DB05B8715D7E8CB81B96BF41B257FE6C5DBD8AB7E4B6CDE8A7E15077B3318C7D6B7C301C0EF33CF1F1C65668CE0106A259A599A4034010F5809FA7E781665D866DEC4A5BE77E8CD090A324FBD25CC07929B773CD8358D666ED767DB22D540829F4BC09C3A60448A23EE40E09EC699C784649331563EB114EC47C8F1731DB50761DDD7C972553E9819DB31148FB97D3B4C9FBB89AF7E87033536455F9FEFDF8566B6EB0100040ECD080287DA76A7791CB90AF6253E701D9705AF96B3597596AA58B9B0FDD7689ECA35A7AA7C21B71BD80C3921449D3C5C8D9A26BD386B5C4002C8050B6C7F2489BEE49B18BA85652D4B528BEB21F35C4C9AB1F5E7F5FA4098B2D470BE2CDA7087C61C4F40E771AC04193DED1C45B0AD787BE20ACF7C9393671C354DD70E93618BCF89F684C9FB7C8FCBD004B737A65350E912A1945FA6F6F082406526F8B8B4603E171B754A3F571B7933E07BC9971ED2C299C4BBB4293B3282E34FC1244AD5C4C985ACD31D4F2EB5B82E5B5E1F00C9BE628E0A317885AB6E26AA7667C73C12F541CDF463CD72798CB1F7908D2945A131CA8AC4BA6343BC4FCF7DCA98F30B0FEADE3F0841EE280DA51D9501B5CEAFCCDB8319F9B32DF23E74A12B4B61C44B3005EE58160C85302C141DBD6FE0D598B2886824B1BDADC874C530DF612FE5260E996C6D289A2A5F3F811F2B50CAC599477F9D8400298981654013858E4ADF2B6A67DAF24A5099E9A44F5DFC37B2DAFC4AA738D4690F9650F019583EAAEDDF32BA74C3468863CFD565D06FB26601EA919B68985F5B7F036B2EF1B7B0F6A738E292BE4B263D30EA5D9784221C09DD6BD77F26DAA6996BCE002783305E478CC1CAC235DA49057DA7F9CF7B8E25AE6FB02A46AD93EBC5D9440BDD07018AE26DE5C51C87556AD561F3C7E130A24685F3FB9E39518C1E9D26C5BE936CF3F9F08C464FD0A32502604A349C8956541D94CC0F11BD5A0733737FD75ECF57678264E63CE8B5323A0630A40CD6032D62ED84951427A5162AC1685F8682EE7D31621F6A77ADE12ACDE5634BC44B21A2E1CAFE4A689E0D30AC3D03A6903F75393BE77FED6BE1F970A4BD7F2E666721E271E155223C03C7068E4D9B348159ED8B09D14DF65F4D86AE612CE3A931FC4A66C60DA424D5C2CDA9FBD7115B771E3262AC7788C70F6C0241DED2B9DC0D936E613C795F69D65539FE00AE8E7EFDF07BC068EA4BB9BD83F5A64E970BAE105036435BCFB23934DC13027ECFE3DFB7A1E9D3F7B2B07DBA844598D4CF53D39FCE8C0485B8EEE92671CE8ED10B262E63944A1EE4889494917FA81E01B145B17FCBBD079E8574DF474362FEF1F48EAC5B8A443973B75E72330EB03E15DECFB18F69D10343F2DAF0CCECA3436C20612091E3BA0940DD3A5D5489338578E0E90F3795A7380D577A67E52ADF7358F2E7AAACC75BBB81537134A12771C1539AD42307BB2C1A5277C123F10B74216CCE836E78D24DC3AD7E794BFDBA4D0306A519CB122E3B2D5A6769EF54636F4398E87BD42B0E6229DD7F430F5C6BD610F9C67C68F1F7A687B98C2E5A61CE50C9989A8DE3F53C975BB75B97CCDEB3E0FB7C26F368B29DF709F18193B9BE27FEC820136D8BBB9A037C13B03E8FFE2484D948A284D505916EE424414C5DAF57514FDE0A84665B2C31E2D4C8FDE45BFDB2CA08E9974EA9449C5F332CDDCAA46140F08DEEB3F0B4BDA7BE04446239C7AF4949FAB33B40DBA8FEED31D45F85507FC232FDAD3C85595643B4A7F2503C4BFC4B3C55D969AF6AC80A3C02AF1F5BEBD23A66700733B36F133951193A1FCE5D429B6200FDAF383798A1D11F3CD6536D3F9D27B58A5388482279F925A8EC2850DB90F5F70650B0045B4002B952C36B460A5B566FD3BA2BF5BCDBA0378C54AC9C12CCB46C7FE110AA99DBAE10D5CEFAB484A3ABBD517DB89C71D60ED26FEE9D55E73BD4CE16D898BA426A683B842885B514370F6D854321E599E24EDEC6C3A0DB6F73C60BB36433EC58E162D6FFE8BBF2D345421341EC22E1D25FC740EC4D3D78B79484387A9207B9B48EC8585FB9F6BB4F776BF71FE7834D95BF4C6312D430EB79877FC71EA67EC4080C359D4C4901596E93EDF71C6B3AE2EDD5D491DEA03186BD3FB24527E7F99C708FBA19D606CC44EC5E1FFAA33CD2710CEBF4D4B5869230B151CA8472D35A49CDA5367098CF3AD4DDAF1838E77476108EAD4C399938FF0CBDCD226B6F06D5323C3D885FF1B043E6A32CDE2E052C7D5C273B5354EB020A81D4F9BBA9FD29A5148359750EC9CEB6AA9906047F1FE4191D07A0B018DF93BFCD96FF4AF3BEEC9C5E5EB5884B32BC84F66570B9B57F506443FF634056B504871E4B75CC1BEA1EBC8A9D5D07C9EA587B70EEA92B93F65C3194B343CBFDC28D1A76DAF95303C9C4EC0034FCA333628720BDDA7A3373D676E2928C08684E9D24EED7D9382AAE547CAD5837D6E1BE3E7245E947053EE2219D39E33218D9AE52F6B5EB487B0E5B16AC35FFFC45AC1D832DF711CB11B2A887647BC2C3713945F92103F3EE2A52AD946B0D38BC0BD92E701C7E7D4AEA25E6AA4FF2A42CCBF5DA9BB99F88351076AF1FB4E7CAA65DC23A78372E1C2FA09BA8D46152CDA3ECC8A9288598BED37E4D11507E6B5E239F377D1DC5AFAC7FB38FFBB7B2D4ABC6BD74771923AE17CDE020B34151D2555FDC1C09848196DAAB35745D88B80A79CE2BC86BFE7397EDBD9F16188A133B2900FEDB915629B3104DD6F00CD1403F8A62F71756D614C0224276594D4FB74891D1A2F93F43157B0A6A4135DD65FE25D227BE62AFE953667147FE7D3D486BC6D5436B218FB9AD0C6DF31CE8FCAFE01B81561E02AD5D34A0B669345A74AE16F651FAE91365960DC687B5738D98817B10EA8197FB807C59A47EB187BCD2E4E873BACCE97E70DDCBA6B4189A57FDF7D6F8B62A0FF3D81348DB2B8B35AD55D9CF67F668BB89D448A751B02071D1CF812027EDE8658D51BECAC34BE3EEA1DBF31E6177509C81F5E3A373FE9E2AF88282EC5BAB7D00C1325C6A305BB0E2B47989EF26AA3CEFE6A3F6E7CE5873F215DABF22C17E5E6FB210DA4F5B5F576B0800AE1D282A5D897B6164D3A32C5D0AA176DF03A6C1D2850CEBD40F5D97EE707EC307B13538FC3A0C83A95FF0EA2E5470E1B682ED12F9E65F366C45775A9365BF74729DAFF7FC0E9BB4C05A53BFCCE1B14CFAD49647ADFAFAA0059707D4D72C133E5EC878E9887B41656CBEBF749F9E19C3E9C4F464A67354A6212F43D15AF01A762D8C7445F7FF27CF835E1CE11C844E488036838FD7254AA6C2CDB858B7FEDF7852A90A8AC7FE2504DFDC1EEA60F64A671DEE39E72332E407637033A9146CE243950D4C3D07C17BFE22D9A191FF01315FD51653CDBB316E833C823EB459987AAC7E3D6FB50BDEE54652AB253CB9DF0A661BE1B5AE2A7E9EA429D7E8A5BBFE7683A2DF259CF2F0221CE0C2FEB06C117002D101921FB54E06CCADD05DE9353E5874C2B67B45571A83E2967BE45E77AD2336B076088B33F33F024185979EB36D57ABBE493D84C7F7DAEE3B10E039339CFF06CF36DDBB04ABD0FB8C8DDDEF0F7E86F9724644D6654D4FFFACA74F21F242A9722ADBEF84B44C9A1B7B815EA0317DC5CF688F57896C57AF47F44B1AED5C92853A7EB1138A125C026C9E73770D982A0A25785CD91A4F315D03DEFCA59A2D3CB3C015DE5DF285B53A455087D46109582854BEDFC301B9EA9D87D4A04A2F9650B8D9A83B6885FC52CD32EEEE85E740873330E29885C8BE8BC9D657E612A87EB3969CD24950C9A8945844BFFA33396876B885550860721DECE6AFB92F1D87707BBEF2A34915657168C8FA2E3050F1029355F7E969FABD2EC252694A5BED8E0E6FA4E8B91D7294666737D80D3E2F51B1C65B8E5000000000000000000000005111A1E272C0100000000000000000000000000000000000000000000000000000000000000 + +description = sample_in_ball requires 76 SHAKE bytes +mlen = 32 +msg = 5F07000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 97A77DDE48BAADA6090588B72E6B7AD2C44282DBA1BD1DB01FD9BD96A5CAAA90EB975FEF65599DEC159367797FA9149747F1375653B74E6C973DC328651B27F8EA6CE9DEEAAF67341E25E9421A0AAD84A2C1085F56DDD002B2CD556FE7A555D4D03C41A5AB28857F2456D2F8E495DFE4B9F9E78FC9B84B1BB4238C2EFE049C55CB8ED97A390626C184311B5125D5E6811B96EE45D98F5FA997972040FA7267981C407B45681CF7DD4C5A0A3DF0B0098234E7EA01653B593EAB1E671D9C792BFE734CFAFA0EDAFE2B2FAB7D386512E9CAA29EACA22F5F3E13FAD9005E8BAC32EBB3676D247A3B53B4821AEB517A7DEA13C1720365E40BCAA5D89E38521402E835D872EF62CA068FA570FF9CE8EEB16EA6A2B735FA3B80E8367626DAC125059A83CFB964EAC39A42729D238A3DC7486F6DEE92A17E10DF17857E37186700B0653FDCE6C072FFB5F783281C659213AA09FB978A2095F1EC35FA420C421F085335F7685F77C5527E2B5017431E7D5418F07E27F529DBDBE8C66493B0BFBABDE53AFBE8B0C220692BB2BF1C3850603E7D0D469840BB9A79E183D41DECF124BFF1294E42469025687BBB1B496BB8F9B3A0D0F4C598014ACDA45636DB287FF71DF6F500C9E48C3D028A64AD0D085F1B2EF4B5307F357537BC9CC36C76E42DD0AA016EEC7F80F20DBFA39D9AF638B6C97639E6EB3D14AEADE1C114DB1BF1C17AB478B3F273891027B6490404E05E54FD97608EB4F4AFB8389589D0A33469EFC0FA00EFE5B6197CBFAEFA377F1EE13B7C4A2BAF06C2A7696C28C32C5A6C717E487FCB5FA9CFABEF0DE5B867BDC8A9C9DAC8B565C532FB667436D8DE2B264C14543DA221A527E05129092B9DC2071E0D414C807E70E13ADB5E678900206F0D5A6AB82C14599A9F1F074C557F17B1A2A516CD26C9AA70D073833415823BA89D4153C4277F01E44086C8EFADBF051109A829AB5508525DF5562F5D19BA4E177E4DB0D6A713DFC23D218C7AB13C9B3F53C29ECB3AD3B30FD136B34A6006AA30A4972A244132BABD2A3C9DA498A6A9E1567EE208E83686104E59F90DD2A3741301E586CD2FD86D9954AB1980F0CD513A0A6D34656EA31E87E09B1E10E18FE28E789103A08E79DB9C8BF85F14E733F206EF2441AA45771D3AA1B5BC8B1E73149B43244784E98B6DFD7CBB4E1531FC71EEBBCB277565CF1B528E529E7FC935DB09945691B4BC77EC0DE114AAA5696401FF7A6248BB785DCCD11E819CDDF857E039DEA72043DE5B36A6E8DD3BBED56BB47C3F2E37B0674084F8978332297F299095A8659AF4AA916ED967EFEFC3C5B3F103BD19839D5D8D355FA06AE926D7EFE47EBC914E7DBC4E14809F021C134A043C135B96800C5AB1E93D767ED0A2861884D70792EE93EE00D16236673924748EC88925C29CE2F9A2063647FEB81C95123FCD0DED64912604602495207AB98A032CB81644A4F5E63FBE9E036BE65B0147B4A81FB1E2BF5AE35D127A3579E30841CB6740C7E831170D83C02BA10D642B1D9E8D686394FBB00C06D6F8AF6C1F001CBC352987C26C22EC239C68E00BC2BA2D3E4A2BF8B6FF803638C0D0366B6BEEF33F8A7D043DE545ACBF521F0F09C306AC960EB980D795BCB399DA18258AA347B4B23DAC64C1794961931086B1D8B7CF842B06422B1E052DF65ECC6CE10785F656E35D633B3C18A5ACB0FAED33BAB0022091926FEE9ECD5BC683401922C94C901238F602FD2BD199C49F20A66089D85538517B32D6E19BAD80180575FCA04B18DC207B4A831C96EB0A67AEFCF1A7540C6E6206A2D4B5561C169DB7199DDE498F7D2A966C432627D0EBCAED74FB04D1BCF8922BAB0C5BDD688FF8D9EF9D2F181D0C7D411C0080E01E2846149F00910EFA3E9E24DB672E583CF1F25161CF8822E18B347AFE6A75936CE7F2308C5A7401EB0342F89E48BC9A9E38AB993B5FBBBCC05C21F35FBBAE3BDE103AA84964CA4EA6F8BF3FF3EC19922206E0641834FC2093B36713B2DFE1021AD44CEB7CBFFC70A656B7024586BB9AF351AE55BBF3AFB51C388881403D2350799683C074EF1C1EF54AE68FC9D28B85DE1DD5F3EDCB9ECE5C867628130B5D2B2382B92A62909F108092EB035FA0010B0930A7DBB959200A8DD3EE88E5DDA7723C2FF9773667852C30740E84D62162449E3DCD1BC1506ACA37F14B43E9168A86531FE6AB919BCA8ED4E4C3F45DA0FC1D4082560B49A0FEF0C466E4EE955832DE16846B6772A57ACC4FDE0BD320E672363313F8B73D6F27F61BD0BAD64FBC9A44A4C39B25BFFDCD4A2617D16E73FE00972286D7D39335956CCEC3644443B9072A3EC59A8F4D2090EAD36E9C8CB654C1ECE75803E0C1CB308C621E2E4EFA1D6833BD38C4DBD60D402A780AF1D491D228F6A4B31EB5CD1D76E570A7CABF028FA6492554615B46522324932B41D31A5AA22B8E074D88D1F18C02CDC244AFC99BB2525A9471624C6CB0E9A4E2C3F6AB074004EAD6D50C16CC5D09BB7547959714EC9D25DDC7ED2ED9EFA26FD5E5C4B66B874847B6E6E5ED1B79C13697CD808AF3897E4CC6E9E9FF0BE373A6CC38D5056421B0F5D0C854807ED5E7F639DF89C8E04FE33C6D442A593488472165A5F36DE93BA4597286DE3C79C84B855AAA9C78987B055FB239EC51036374A97A2052B23588343BC9042B014C8641E4D83BE7CA343E3042A73E62A9B694AC17D6231B7066FB985B3F27A13FDD8CA021378AA9A5224F3F8774A891411C922EACBA8F1E017416477B7166EF989CF649B1852CEF35B67DADEF3F709D0EF6AEA11F66A006B38967C896360C79E0FD20B0C86B46468C14F6BD9311A1BDF99ECF835F5218CDFFC9E98BF86D70DD381EC61F6BA4D17F06F434F5986F95FC16F2298BAFA7DFF786F90D6277193CAFF8E8AA31D4E23C1F41F407B181803A61F5B187CDDC0A54E638AEA5A950D681387888B4D50BF8006AFA7051AA901E6ADD60769D22F0127F3C8913C23DD71D897F6649E2FB75BDAA76E838E6C2164222209F3544F2063EA79A1EA1A231AA4B0B253334A0065AEB382FAB31DDE9532A2664D9A28E33DDD896F517C7D3E50E0027FA10B4B47BDF36333DE0B388CEE8B18FC1E92D959CF6F440129DE88397F9BF2C46FAE78CAAAEE9EA5BF1A15A9912E8F61208E665690FCBCF2732CE6032092282B53DCA14AD722E3DB814748B5004E143CB605196D32693467144CC10EBB837673DC7EBB4BAFA449961A578EA4C3856410EA200B37D9E6609EF19E9DA63DB7AAF7E2E54B132A4E2D7D9C2F926AEF761581D532EC205EDC6227B2CDE95B30515A89B79B6908DCF6846440F87266715C9AF73CE37F383438E44A4839A30CE8D1E3F1844F006B9B698D4DC52BB11F71B6C51B2338E85EC83E6DA2B60D0D5C2F3E411609EACE960D0A6F460612A4F0D6BBAC27D202D4185E36BDB1C89C64BFD5FB4F3E3EBAF34A8E1ED0CF24B10DC24DC54A06562F5FD9DFF7AB277682447F97A26203ED91925226074360D251B9D26BC7D2AF105EE865B1CD2D59A964B5F3C02A3EF33C9C9ACECD74D92E5EA48578D45A5292B91D221F872B77879BF2DFDDF2FB9198FD8CCB6CB0DE9EB15E610E1E4AE4D4938B1FF28304D1859066EE45664D849B9BD977BDC16F41E64B0AC60EB4AC518206383808CB59BCEADA3D87CDD6373A5F49E90DD5B7E71B389FB6E36F7BD7089A34698FC5195245F3CE76FB3B17EC71FEF9B160D7E7514D271CC3BFE9281C1CFCCE62BCC1C0D4B9C801BC84ABD9DFEF83E7DB8E9EDB02AADD8FD0A4D8C0954D1BBA04552F049F346E8209D4702A5D0EBDE2C199F73485EB11899EE2070CCE593983C8705E14BFFD69ABDD6C9F27B9FF474CA6E938B20654EDEE807006A53F4AEF62C897C23B5A160F43AE6E9D3B9A577DEB17ABE291A12BFF1D1FCBE98AE9406EAEBB27A8233B3D52AF2A91CCC240C2B9DEB50DB5C42DE42CBF56AF5860E522F45CB3C696606A3BB5346A1F18BA2970815577DD72D9CBAE732013101983720C29E897A2ADB9E36C8D77F39FFC59092532938E83D8E80A7DADB71AEC0AB7694BF8E5D67F71FA6BB7B185300D3AADFF3F024214964D47DC9ED0DDA55EEE3591B7C20145065910751D96741C2AB8D2D4C9B8925019923AD11189DA9F226B63D9656FDCC50D2466DADEFCC8BC2BE6FC07A5D99438E6CF3A164D30A342FCACF2D96982A5DB6E6DC6AED591D02896940DF04CE6B57B09341373A3E7D52D9B41941393D4E2BFEDB54DBE1E68481E3AD51160B41C92817F7EA5B95D759467F7AD978B099FE692C1131ADE3162314BC62C95462378CC895C5E4EE1FF383A39CB2EA495B83009547C974B9E82F380FAA431504689BBA67ED2F2D7DCFC9E0498398D9AF1E76A5AF5BF6A6EBC0C1DE791C38DE7505B65541A79B9AF4DAC303B9563FD8F5AF6E3B88AD40BBE143A4376D5C9DAD22A0EB6D66ECE160533D80ECC8124C186F93DB5826DFDB9800D253165BCB17699957CC1F0535DEAC0809E0F79AAE8793D0090EC09428DB8E5220C53D457D2BB8A730A668F35AE750944ED0C414888927EA329C71D1488B072CD9FE880A5C82C9B9CF915CD0B3B8A15688003D6B5E272EA61D3C8F38395864698B9CA4CCDAED1A1B40666996EF313A5B67C3DDE9304041556A6C6E7BED0E1C3775839AA5C0CEF42A6AAA00000000000000000B1219222C2F5F07000000000000000000000000000000000000000000000000000000000000 + +description = z_max below the limit +mlen = 32 +msg = 4B00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 88190ECD3E1BBA698BDE9C7175B2B855E3297F2C87F066EB0A4D3192B1E15E2A5539BC8A0DB56CE7B9387C13B82170EA91A38E195F432493716E923A20511F8D32F7AA4F83E420EB76B6D61101351AFC5E1EB1C317AD09795F08AEB9E05E5122C07E94C29E3D1C822C7329AE0F7969B6E525DF66956318EA7660E1210BE60ACA014B4D7C3CAED17D7DEAF39DCBAABAA4F862D2FD55BF310F66737AC2C35BC7EF8915CF9CAB73218AFE38A155DC49AE81F0C3C58D656AB3631CA535770CBB1D158FF35051D94174F86C3B7D3F41D3EC7D1A1F9355AE373BCC4518070733C4993FC03F2F03145B5A1D0E1398A4A425924D3DA2EFD00BAB3BC4151081A04E4E3D38DDF67E4740FA6CBABF3B0CBBCD411025B60B6896DB7A13CD9D533601B564FE57F974DD29AA828508E19A6ECD084188A2C615026380F4075F6F5A16F67D49674002DF963D628B3A964DC47D61DCEF2A42D72BEC1A4ADEF0ACBADF7AB0AC0C25FCDD3777EA1ED00F649A216574AA198C2CA1A6964D3CE1442074F5FA857150E0B2D1F1DC750348AC4A196E259D6B80FDA3E94EEBB05E3FA80F75EFA9557889629BE2C66D5442F917F4E4A9DDFA3F3B75B76D725D2B690F98BBCBB48B9C9D7864DC274E9DC21DA79BC6055810009EEF2AA6BB98CD7D6E51FBBDB37EA404D3C33D6A31DA87FF1C7CAEA51FDF9E5DC714961D1F82D1E6D4510E6E14983F2C3D045B4FCD0303B0B5215B2A9F952C7E5A7E411CF4D55447F78F7A60DA2E8D07AFDA18EA491723A2C5C46FEBDD342D823CF079D6BDD258B354BB46B2A5AA6F0CD2CE24CB91E011C061C72541A10ADA83FC668EADA549B20BD407660DED336CB72277B9EBE4A609124EF196407C7ABFA5D945148E6D735C9BE5873E8DEC42D61805863B937BA3D80EB60374C9B250A84AA2362421EED71CBE94DCA23FC4F9B31B8E6B716EF115750B0E8790F3C6A38E7703607A4C0CAE5BC3D69BCF74742F7087FB5C3F8AC91106CFF31A1C00E4F27A08EBBE7B06798ED269B23BEAE0F21273626B5FF61448179EDE64E4560BC8C0BAC582DA6FBF1856718D500A2548E0E7BB35A3D05679472E8F8D1F9331CFDB11F1A0CC117E8AA993CE5B05C605B74928197D16D18CE0E88C89FBDBB823744303D3432E898923DA5D159B161B9D406D3AC6CFFCE16B6B054AD2BD9C7A9E13F0511875135911363ADEC3D2EDE6C613B0D6B239BE3DD632272768268927B18CA4E25A3E5962E733D4F5A8D3A8724C414A00092884833F63990FD854A97319D04001CF3585769D1568663BAC855D6AD3780114C130D0E57784D7F7F7C042FEA6C03F7E5010B1AD08244AE6DB605355D657AD6DBDA61FD920FB74B531265E91DA21F3EED324DDB44C999AF8A718D964C3D62CBD0190E5FFB8D02CFCA43F2AECE92263960BE08B6042F76D320B572125D10A66A8FAE11A8AF4F50E7EB03BD872F34960EFED71A0CDAE54658FA50BFC7BEC9637FFCD2673B093A942F81D432DFAD0DE68B893926E9024394D1DAC5F6BEC2DFB4229ACB34E7E800FB2E3F1FEE759AD157E79C8D14985448011F5D216CD68BD7E9CB2B48354FCACF0E7798D3E380EE39895F1F766ED9356C2B422764C06E7525F1646A699E22618DABBCF2F6098B2147219B9265161D7F5BC5CFE28167748EEB34F56816367156EE9335CE64A0A468403C38F748A3BF93FF2C2AE10B84221D99A9435C7715F23A1FDABD334714907C2AEB22F8C7FB438E391A32B2022760D8F714A5DB12FF793E81114AB7B8CFA2DF6131ABE0605641E54D986C469DC6E112ABFFDF13231A34B8B0D204C27A871162EE794C66AA3A0441ABEC9942392CE162E6CF14601B65828E3D56C12EE3DF93FBB6B8905268D6AB93B02EB828A586820DABA8EFBE0D979E8AD8B8AA1DD3B8C78BD85286E4C7798FB2AEA13D28C3368E72FCB9D65AE692B96DAE8CF47EA9D0DD16BBE9C2129FF02B69A2477296D21C2878CB13CC0C9AA9E982C52D824AF6B9573339F1F15F468DD3FB9EC891B2479E1ACD663481483CCDDE9C793139474DE2A9C413C62DADC069E197D864E420E3FA1EC4AA81FDEEC8A0C356E58445D01099D8B12E60D66D7AB2FE41683E2980E48B6F6F5235A059490FBA0067488A01E6439801B2E490683C4CFD79F086223DDDA53EE4B66F132865DA58471AD5D01148EA0B141B311CD7C928F12E3DB20C766F13C22C43785AE80C6AA4AB8F13BC4F5C2E17E0C563C02FEABA052B47674FF148B020FF289018A70C453F05C211B8DDE962E71E9E6EEF85C0200B9B6FBF73FA4F1D8AA7D4572E28AC8C470D215F83BE9EBAAC740989F10A7D9E174A1BD1EC371930D0A543807328BB336EC3ED05C976FF70500449503825253D22C8AE30082FDC631F31A736B234B7F1DAB5A52CEB3C81682B57B2AD51797C4E68E59AAE137B191396B6DCC5EA6728E07B6359550A4C904D247C3D106D1ED3DBC97B5FCA6780DEC1DC8F37C1BE937AEC53F5802C64C73711D6C1D119AFC99B0C50E4F656B58256A2B780463916D89A9F7A3D3107DFC43D90B64B068711B6DAB9431A5535E4736E546B6875CC9135DACB816A56836A821307874D03BB56702310B6F2A813416AFCD87C25EC45C25CCEDC438A3626822FC85FC6B6FD12756510537CD9F20C0963BBEF088BD4560B1B722DD21A502493C68ACD6B84C7EE7F9908BC663E91990CA6629D8644C4A97E552A2FCBF4195FF8E0B265E27BD84580784CDA47C7F251B8FE4526238B11AAD3DCFD48E3626F10EC2B30EFDC57486C4D0CF1BD4F6407E7D62E7F680CC95F18847C207C895D22E778A4F8BEB7D8AC671213E7763D6F35DAE42C18D7E848BD1E808B4E7E57E782298AC52F02DC2FCF0BF5C8E2285F22595A8CEF6A3A22E90EB545553FB9A765443021599F85647CD1CD0DE00EA224B2FB77C3FEC0BE778F46A1190B83C1EA28BEDD22EBC38D8BC3B747926840C3CD658FFBAE54E98FD2AE1D2D01420DC323A67948B63D00721E14CD8FD5F6E964AA3A975C1DB1F54AAD4F8234A82F7E694D3EA036F3B61D031B53BC6CEFB42AFD0847CD1F1282E152F66F3A3CC005A9D3B0566827BED0BD0D5F5059C8BD13D689783BED285BEEE05AB104B50DC594FAAFCE045B532D31E7A3371D6F1C9B90EDBAB8D7C71DE038FAB4A7498886E002AF08DC0E099BEA3046912F2157AD57ED1D2C2684DA30C7FEA95152A96E5CFE8B9CA916D1D0F3A8CE144E99441071443FB3FA2B5338136EE6BF087615EDC1F6C12C070FA4AD223A2B718F350D41C221C7B5F2048073C99FB9C153D3AD259ADB01331D66F3C5C910F44AB501C1D92A533999B7AC0BF10ACE75E6EB4867513540594DF4A6C0E8A4B776349AAD80BBA90B20B87BF740E46BBD6964EEE91E54F7F698C57AB52F3CFC248F06CDFC67F06D9400881AB3F330343F528A024F282D9BFCD2C5077B2873E31808A3E375CC116B454EE48FD5C43905BDB71A91B0EAB7A13BD642BF0F36FA46545065AEBFBC26533684503923F0D840E8F9661C1B11B01149B396AB647839128DAC9A39EAA0F4F927B2140C8A2FBAB407D1BAA72E863AB8874DD056406E857660001B1994DBDF4C63BC7DEE46E26C98B823298A5572FECCC994D73028FB6AC2900195FA49968AFD0860C92E547BAC193B240526FB135F0A9A979F37ADC34D56C10A8AE2557F1FC238787CA6C76683E916957876AB71D5FEF0062536EEA8823EE8A17A07182E366545C6CB130DA906CD14AEFD564D9CFA987DA4B6833B2D6E91400904B73305721CDD929D6CD640FD4462C312E1F2811F93B47B650086599FC32145A1C94AB3B0A67C7DF23427C0F845084A0E163BB3DDEF3BFFFB5B420B908B7BBAD931EEB5481007AD1B07A4E0947E34B36A3DDD26571E6AEBBCD0B94CCE0154F2AABF8BA23CE0F35F8C5D82419BC23A6051FF1007935F4C38703919F829B9971456C7C51169EFC61A3155960E778BFEC49642DC11551AF2379036F9C9F5B1A2AE37AAC45519F83FAB4E14F41964E480E0F750FBB3F4A34EFF0674C8233E0D444028C658D99929D50EB95BBBEB5B16F90B4BE4ACADC4C7E384AB2C6AD2829B97038FB297804A4DB959B1C4588E789F9E35460A16450A3E1B4832D5CA66C69588AE4973DAE90432C7F97BAB95CC0C9E821D1E42564D10619006CCB9725BD059E19D1C09F65342B27436115E5FD6FAC5D560074BAA5AB9A8BEFC83234A99FD6210F038EACDDDEBD1484E5386C32FF1EA833888AF8DD38196F76A110DFD330DFDBEF1A1AFF2844AFF291C507F3D703ECB36817C41E6613AB500BDAB75B5A712467E3A7AAC1C22910F7D6154C48CD7D57EB8A04EE581809B6D35E0B6395B712FB1145A7C4CF5FC3184F50D0838D9A2F7ADA094BEBF21DA3E9FF593668811236A43F3E3446ECE18EB9D45DA90CB75E4BEBA18371C1D5FEBC262FEE5AD84638CE9FABAA60A0137C1232039F2718864F1D57AA0B5C0C0053EA10DF2BEFC31BD53E22A5D3F7D27C2C5FF923DF8C0A7505F09F5475F1E1595BD8728033A77F97754D81D6B0C43F45FD9DCB102B5389329EB27C7D199A34B06AB8B8E132305059429D424734E775CD8BB3B0697C031EF8C6B2143266769AC6DCEFF6FB494C5F7787A0D4E1F90F294E5386D8256063767C82CEFD182146475A636A828692C3CBD5F6FF07375E6E0000000A13192130344B00000000000000000000000000000000000000000000000000000000000000 + +description = z_max above the limit +mlen = 32 +msg = 2C01000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 1B96AE9E6D51A0B5FB3DC41DBE9A83A1B91D850588E9F6D433C42CF0C71AD03630FE02B43A41F3C617AF827AF60F5FD54BFD8C62BEA265344AD94270BB54FCBFA04C9D700CF009B74F90D66012F96AD265F7C59D71BA564281B39AE12F3F9BFA3D3DD88A93B5D7F34E51F0689125CF87418F350223CD4957219C0221F8C86CAD528A609BC9CAE35194BE6D761A31B315C1F011F0671BBC16F1D2525EE5908C5DBCC2BF227F6B1A02186721AFAF6168C5EABFEB477967FA75ED9D9E66A201D32C3EC5D476C05C2ADA966B0B32FBFE1320ED3E4CC10EA3A78BB4C9E74E76DEA0298F3138685FD93076C69A515728C6D0C950BCD6F9FB76F5DABB60E4555A3FCC5A020B84DDF4E51DCBE8F58666AAFB56C5ACB5DD4A62F475CFA66BB806F1792D80EA7D03AF243C9D603AA1D37AA9B18FAE107E7B3C13F25FD18916E04234939E8E14488257C79776AE04173CB91439B05EE00022CA590FADA75EDB0F34C4D300919C18E9EFDBEC7400C48777D1A4C73D23FA71C1FE773272AD90A7FA1F593784755C01960233708F45E10FE366A0276CE79F6AEC1D2E042D2E13CD4CB5009A9211DD43C8CE4D82F70AC207D52D57C6B6F53F03B8DA1AED029134DF00DFFD18C9DEEDA050513000242ECA8E4586D2FFBE31E7DC13A637EF298AA6E23F5C199CB68A84D54AD618500F66B180E1F8B147965721754351D06051B78B8BAB456AD986EBA18C920FE2D4426E6A665899311B0AC30A4DFD8306F1B9C98AAC0BD697280C6786A085A83CD2AF2EB1F4B127AB82B7AE876F4B012CD201686546C44A6801B1760A66665AC730A4C89DBA7757A229044905A05DC1312039B416C385398EA5197D4AFA1598FD5925E82DF7E124AB65CBA6CE965307D0670D2331E28B24442F185C8D176FDF24C29EACE23E1195E4CC1D71E7E1CB1ECBC144615959F2BB4815567085623590FDDB56E3F3A0E9C7B3140494648DC8537E683F0995FC4DB554A840CE0C8D9365638714DCBA28893B2251E59055DB75B7EB7E92D4597B5E611E353FE6373AEACA7735E5B781FF719F0933D9975E9A245EDCEEDF77BB5A7C2741E3EFD1A12B5C5C18AE425D53AA49EB26E3CD80E5A16A67F54FF7B4BFB588EA015E32281B82BD0E839BD05A3976EF6DEE6A6A123E7C743D1BA04262F73CC960765DBB7C117AC035D1444C754969C0CC614D800DCE6720C08C78E46AF8AEAD49AF596BD2596838BCADC863721ECFAE26E29B1111295CBAC3F8AEB76551A7DCE55226DAAF41EAB266A3D4CFC229DC48338348B91F389E33536392FB6E27D03B28FA88FBBCD34B449E514D720916D9C98C60266730470D19F8CB7453DF136FF7B0F61EA916E5477E5B8238AB9D02610A2CEE6CBBCF84A9A2C86A19439AAC921F14D710C25C297F1419B4F4E9824F56C0249EE0F5B9ECA355805A03DF22EBE1FBC8B93707ED1BD60A12046246186D9A816497E2ED7205E8F4359B6263EDD23AD2F4F308191270902D37845910B4B97FF1EDDEAB3B5A94D290E5110A0CE5DD76E78EDCA4C56E47EF8A498C5CEBFE3757A2A5A108A22BEEEB9E1A06B843A0B24DACE33B61EB3407B8A9547B08B079AB2C7075A709434EB3722AA91A5CA5CB3D8CA92D3C6041ED45C68D5EBC928000E948E6CD7A21A3B4FE05D4CF0D0DF772F8B7F52A453DFA6CE44D0D52E27E069556250FD069532055A619B84E4A22D70ED558766E946E351AB49009BBA1EE4A4655AD260773C2E046F4F1BBB5DFEABA6ED8C6B0373294C683C07589697CEFF68D9CA47DEC9ED8A2487FEFDD10F2DD788475B794E7E08654A111E478C88C8C6C1C6424B8C8FEF5EB489C098A45F33D74A6916B82020ABD4DF285EF5A5DCE8B08F2318299FB387CB517420316E47928A13B06CD34750881628B210CE93C15FEA4F16D0069C3476F9B4B257BC7FB46A9F7BC556A6214FD45AA98E3EF9E8EA89E9E4324184F152992BED351209F6E821BD9D0D0DEEB743605DB1AD840B02BDBE76E91A8266220276455F6BA16642E53B312778851E09D52E2CB848C6E91DBB551699CFD6203D9862C67773BC505D76A4BF784A77F95DDDEFF7B0F28CF61415DE003B79F198DA701797388EB5F1B56EC168FC1088EAD14B4796D47FF8ADF2A5A418C48328E474DEB90312C00A8A350C07CCC468EE49D194EF657007262B2F907EA6C72C7F9716F443FC02F77E8E8420AEA85B24E866262EB03DA49C11F59A5E47062BE56CE288D4C8D1258E6A6348562845628F278AE4C9DCDDF629C4DC553C7BD32B4F7B81A26B766D0FB13A6D9C2E34589F56B5A0C014C61B402B521D0792443E7042D2F9A621CE9F25266B9B0F5A16444A7D15E6270D4BB2F0C2E8E480C7E12823AD2ED7828B6EBC96158746D5B3C3107EF928E6F0516EB3C5F707E142ECBB3BF9C889247E80E3F7559B92FCD4EF941BA992580E436A814243BF6540CD692BC2C33720D78B8976D3618FE505EF0D93B4D0B91ECEADC785EE865B48B530316AF6D294890B518B92AB490BAC1B0D57F94CD9DA765B791EB6B573CC7E36E8C203867089B55D0A3DE1D1458A5E101F7748A620246EB3623AF6BBE847B2F895C9DFFD2916E072868EB1BE05CDDB9F6FD74B5C863503D16D8C3E50A329867883B382A9EF62B2B270C42AF262587E31DEE4D5829254FBBC019B3D237ACFB1B173DA3779451DA5D3373FA18551E45614E14891566ECD89B2945DBE72944E98A081995D28D40212768248A2CE002F473ECE8189F8803B7C8B9DBFB3CF6E203C59D07DE99D012DDEEFE35453D0B9E39ED880599AD2D28888FEAE66F664F0CA01CCDB3EE8085CC8A576382B9DBFD98A39F848D8D3348219D90C57675C20F24EB6C5BC8CABA25E7C935156B42D530F4C826BCB5A0CE30CBB408DF49DA6C06B1142824410FB01EDF247136536508EA9E7D77C5EBED0C42D4E398CF998196C47256ECF85E17070A609D1DF95112CF1A1E843C0426084F36746C0FE04AC0C75B23F30E766B6AD71076F4E9AB412A247043C47F0E0D77DF41BD7895D7BA08176A130E9EFD1C7F03B3C409F92A5098A8AFE9063F40A4A7719FC2498D2261EFFCFA3623EF1D0B96F39E7B934E0C58FC26B271695DD7184CD9A6ED4DDA919723E05A46E06E357C6187B00A485FE0808637CA0B5303F38934E45F377694EA67CC2FD2D024B6CE724A8A50EB440EE759A4EF5A26014393F7E8FB8BEE31531221409ED50F9FE199CD066DE33ED0A6ED63E38018F6E1B721AB494A8FC5498381592752CA136E16B6BD9323D7D52B9144882C70DBFB4913121FD1C53BEAF3D462147D17B0639B9CA109EA25574D2582235D5F993AA6126675D884339D9C445D5B783F5D63163652CF090E5513F0A5C12223D03A24C8EF2D4F90107D5D9BB16E472EF561B1D7284FD7AF3B57F28002BDCF3A4F6792150D03294C2DA159FC19577CBEBD9F1F6F6BB373731B5F993EAD2E4A7AC90B3DAB651A12E85AD82DD12D7989EA0F04A782BF85A7919EC603507427E40A2E543AE1633C8E6A6C696E89C9A53C4D0452D2AD350714FBA30B9C7C2C9E66AD86782719593796608FD3BE225CCF213FA17529BD0460A861211462316EA58BBD0966D46883E4FC2DB545BA09BAB14E75C6A801A68813D7163E3307E0CD8D1042E08DD1EC26E891CDD9E03571CA271C0490781105FD2818511DF86FF5FC045864CC10FF743506F3F7BA078ACC72518911D68541C9660DFE9A631E90E3A326FE3658B172EB9D17D20D2A282A76A3BB248375B331FD9713A1616D3D478EBA1842204824BD8DB871F3D7A20910250C1D05B928D3DFF0E869CDAA4CF16D4C853C7323C78D2C2BFB6188C8515B8A1A880C8EEF9736145D7963FED6C214508666D15AD62F3C58845C31B25C6940914020D3A0BB87A0304B49757D5854034D90A5A6531CE45DA4FC9FBB4CB333C734640D4089827805A3D7E6F6CC193615D4E1D9B6506AE3403F6C1EBF6F944B3528735647CEA4E820C36408478ECAAC229D4AE0D1877759F5E86E36A02384DC5D11958F9602040DF6FB79F47DEB7AA462F2E3E341EE98E85B023D379D5D06341BC7A32A95FDE0A5AC5065B4BCB275A074A3A9B85D818D1E1A0A58A95CD06E508D521DBC0D6593AAC784F59E350424594690974FD3034BE2311B3E1DA598039B25D5DEE8DBDED6793C50696CAAD8B9DD61F44CCB014D2E35A08915AE9BA304384A624DF50A9C2AD809B44B0F4A2EEE8A1FD7D10D9021C61BDF65FB09E35C5314F87506B19550E50BF19D5D37C079B642C5ED7B43AC2BDFE92F38CA2A17C8A3A58CD9E227647A1BE6F6E733C4BEBCC46BAB048AED53B15088063D67ECF9BF007AE533FB32C606EFB72B093F93E27CE1B3BD9F5279FF2D1B837D95B93B8B8A2371288DCCE0B9A55D600761B1263B017BD3013A4CEDA0E53169D4BE8CD9311E5CEC0D5AEF037E859419FF20DC8F413143E30DEF0E36EF1629FF6C3300DE11CFF5184F2A512B72C6E92F8233BED60626400300CBFA800D74E10FB2AF47B95887DC51BEF0C770252895E7279E63C4E2FB72BB28C661644517014AF3C5114700385DDBA3E245B6233CFDC5BAA0D479E6713B57F47413C762C626114F2248042E515C6F949AA0D0DA599EAFEAEC0E2329474F666B7D8ADAE10420548E6E74759BB1B7BDCDDF25289FD7DA00000000000000000000000A0F1A1E272C2C01000000000000000000000000000000000000000000000000000000000000 + +description = r0_max below the limit +mlen = 32 +msg = 1B02000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = D0F3650BE15A65FC38721C970E700FF8DA63AD4BD68EBA40374F0E1C303F703768BEB02DA4CD729D6F2A5E3DDBE90D72FCF3E32BC7AFC5CFEED6920F93508AE3688D0046D4D04737919FD404D790A90DD4816C0C80D8C3147CA5EF171FC266CE0990D973173D2CD9E04E598E47AFC7FFA7FA8ADB9F32A8AB47F13D1CD7DE14B9E3BA63A4AF1F391E7AC29773533CAC14C722D9F2D1FD2177876BC6FA0E906F855F9D41E979A546EBC5AEBA50E1EF0B8259B7FB5E0241E4A6D65E258C5B68F2F7CBF70FCDEC29C4CCCA614ADB534955D678493A4F27753568798DEA62E852EDD0AAA52DE0496D7CF65233E92F2A07168F1788C9892EFB1B0B1520237A02F43E51B04CBA756ABB46D23B89930885E21AEDC7FED54E46A47620BB8FBBBCA05F2385A5F8FE600694EB5A286D8B6F4173DF997FB08446FCBD686CA03CCB3DF8E5181357B632B48BF88DA86447752B9E04D02D0247BC23405667206EDA3A3231C3011B435F6E6B859E36952FBEEC26D676D0D6DC0B5F3662E9ECF11385A4D23E4FC8CFCE61BFBDBB9BF5AD4CCBEABF0F714027B3A7A3D5E0DCD5F0EA3A75EA29F4DA7EB60E39052972066F7F1B42A7109003C4DE3E075FDF92B42D2588304050016B32152DA99D8DE0CD898013D6AC918FF6B77ADD6B22B2CC4C1F8B75E0D1EC069E8F9954A2504AF914742B3F1D914AB5FA6DCE9D3FEB798C617D6230373E43D916D14340F30CF7BEC1DC2847BF71D77BDD6B2310FB4AAB6894E092B87ABE9B02CE96626EC2D27E1FF3F402DAC0436A6AFF6CF55439CB8E3117475F45DB47E95456331652C921439B8E6AD6F39171A0FDA50230E72EEE8434B5433F21D78F87839FEAC320CBA94BAE247DC70C456596C5AF329022F8D226045A89BB6FA01EF875F81EC2E53F48D1C8B252BE7ACEA1F51B9772E14D7E42B924B4C3B22CEFD3295CE1F753877EDDAC4930130400D9378A4F433D2941006FCABFC3B7160A2D4A53A5898C6F590579FB61DA92637D5EA1C84ED85B16D7EC4CB0772BB1BEB94C4DBF9DD5AB41D34FB25120D5E6B2ACB1B1EFA411E30B5A9169110A5BC7D13A5AD92E6829C324BB7897FCA65C290FE9B461F9E54756B81DBDCE7B4666251D7941F7BE7F83194AD814B202CF0E51DC3E3700EDA636DEDE2F3DA337ED6CB83E3590C71152BE67A836A97D81ED78201C1CB89292BBC90AF10130F6058A3343FE4A0EF296FDF045D8C9B9A2C922ED4FE7E9D8368C3167E0D5622C540EFC91619A466CA2ADDBDB5E0DDCB403C4AE70417B993F66D41032D65042FC79B4D4EB802F9E8DE55F6BF895AFCE5B8C3A2DA3961A54BCC5D2091123A00570941A7AE51A5E91ED1C549B8E23F6B8479F705CD24A295B91300F35EB82C9659B28B269C6C21D56599696A15C2F038B363B4AF9039B579D8590DACE080E805E70AC7B9F13F570F9DC04FCEA3D37A14230C04259A831450B8D8623B486AB03E9A9E6BA7ADEFB13D37F29DD1FD620F73BB8236625EC2B25A680D1FC0ED7C3097D709BB43702D6BE1A4DE7D8399FF02A3D5452CFB7D7CEB82C2239CAA23A159FA8121DCED581A0B966D36B0D4AAF26BE88B73A3BF3C47444C6E4610B802B729B56E7417473BBCA142E682EA46928E602E39487BF4B20E03DFD0DFEBD04B890D731376E4A773B96F84B024BB1DDE46DAE63FDC9187944447F2F3D59461E7AB691D364C0A47C64417BEBFD93FDE12FFFD5A6D747440C7FF458662989D5343BD8E7C154A3C7F6B661AF5FDEE60C7DE49E86F0D10E42DF9193CF75F07C1FBCCF6298972F373769EFAD0B479C21FCAD942702ADBF21D52D0ADEA893BEA5DBE0FE1C6360FDEE0F98E3E878346CCA5A09A83A1F8ACD046CD8F42439758D201EF18D532ED74E0C453D64F3D19464C532EAC1F7587457ADF9D5943B35E27CBE877EFF8DD52BC19A1537D0A6208531D6D5D8AB57A721BA399E7E73932219DFEEEF1DA9EFB01CC7B42800C8A4D0880773DDA3B4720E793D116DD18D201232C1ED7DE2F6A5854F5170E6DF3D848D382BDE975A41FCB2CDED3B4E40694A627F8A7D01AD71A88299160D5781316BC1022CA95D2314850243DBAF3AC054EB2796303B86C5DB224F8F95E6805288A8A832B0AC6B853A36146C808E2D5C0BFDA0AA1AC70AF90F5380391A954AA04594A2D9B62EC1E0CBEC2BFE73FB3DBAF79E3FB40FCDFE06AE96920E1C80240DFEA7B490F440319C23D80489ED9AF9D6B677CEA2D3073E46BDF2C5163588508DA085FC32D4CFBADEDCDC714FDDEAA5DFE7EC5F2A024224819539C685E76D0982481522DE0ECE718575EA5BB3F70BE7E9D93904F3B40B0F43460ECBF95CC269EFA6DAAB55CCCA5C2D91534AC60040772DA27604B08F68A84F3A4D977BA5D690DDBD8EFD4BD5838C8BB2F5DA599B4A5AE240C5B0256444C38CEC1378576FEE88C5AB6E7DD801F83B7836707FB3B22C1509A29640B721D8302AC2897CB10D98323157B6614BA2C3D5DF3F2BC6927853CCB1F39CF275C5A0729A3CF50FA91A79C3C7326DFF047666317C6D4E719662FFB25C40ED171508E0F938B8FBFA101B40B2B4A256D97532F801B21F3DBD65E693EF481FA36F92C3BF611C006E8491019EC087D6BC01549B6B7C3381C919E9DC2D1464849DA2F1A92C6D8ED1FB864EB13192B4F09E6B03017094C1A4E10B8DFE788F6617B9886FCAB092C8629AEBBBED6182DC58D7EEDAF2A5C8425BC087173AA79E570D24DCBC295CFB0495E3F1536B7C5BFD6C548FE7E37ADBF73755A3EFDD976E196F2FBE4087F3FAB78946CC70F3328255EDA772FCD627C7D07E36E2BB0BA4E04C7350872BFAFAA25218E944FD537AEFC8AA19AD321010F802C35846B7037F2FA362740A20096C22D79D0805833B79E946A7FA60D1C1C66F6E69FC5A37ED8D7A2D48D06560C8E8341AB8693BE2CE14E120D1DAD5868D48143116AA9E06F28AF876879FCF38B3B695CA7B2B64620097535FBCD449B69DEAF8CEF75C73EE09E160B0DD347BAAED60A5B1F5899D68DDD1D9915F8CC18B316C2A0712D7C459FE1D1BC2CCFBBBAEF417FE1DDB3813206BFA0748167447B124B7F2C1A43D317FED1BDB079CC05101CB710A01BDC23E2B83DD33E6004A618EF89DB5B3A0CCCCFC810B5DFE3B86166E3E3DA99A9FE6800F46CE69D3D8E0C9D3C64E404C07F8B835386B7002C90B915EF689BD35F1AF85D060AA18E6BF8A6CC3A5820B150F32855433381683E34B31D39AFF0907F10913C38BE3C3E98037C09D59E5A4ECAFA683FAE16B72132C9300C1077DC9D786D7059D349D3BEF11FDF31CFCCE052AC6FCAB6BD7B148ACC88D0CD0C9771043B9F8612AF19C25647AFDA5C28A9CBD9FCE57765643258331584D3703721206FCFBC8BD70CB9693D2C758BC0E89385FB5A748087796FBE061127997267499EE685ED49C8EE0EF64E8A0136810AC3B75955DB31E0FBBAEBC171D2D05A62F8DA64ADABCA6BC21F459608EF6BCF39C16AC8068EC98A729555687E9123018D4E2C5E2DF32BCCD32C630741B3BD06369BA39EDFA64A73884E596DDBE2AFA6A36D2BA073F36B9D5EDCEB1E62700F1F0B7A78B8E2931645BC9CFBAE8F139735202F1BFA82CB34E006CD501C619A68E852C2BF7FA1EB653140A0E2DBD81A78DD57AA0B415F9A031F6DC1F2B07380FBBA28B6454E9027108F407206E1EC8A5133ADB37D8393B45D89632D5B529D1CC67F9C68AC1597ECC6B7AC1165012C2BBE3A72AC98DFCBD66212CED459C7D3F8E3367F3E6AFC6C7C0EB6591D6FD090A9EB93B0719311D534DB26827067283F9DE8CEAA32CA3C910A79F0EA2F08F2B5FEF210B4134648CA1543A23091DD6BC586B530B6E48D13828C16CF2F048CDD27A641FE0DD3004FA1C53D0569D5DB776D6AECA58AB5CA4C7A57A305FF6E71DB71852AFDC0FC936987BF9B6745AF2504392F64C752F9A234E29962BD5B12F27685815A36D9BD488C2A892FAA4254C50454224AE3CE9D1295C860990B1E467B659F45606A7C08017B7CFBCD68E2D0D739D9ECCF793A04271ADB79A9FA9BC1D1A5A96633024462D0A95878CCD50938511F375EBD07F0F94F6151A6C1B8F787CF9F84B44C4B2CD30329B96B854E0A3154A21DFB000EB187567B815FD35BD533D61BFF2365A11139661D41E68D22EDD2796E86369DFF96AA458BE212FA6FD8295D543E7217DFA5963A0AE6DC1175F13341EBA2910F60742A778152DA38F22A09EB7D1227F8B8C3A33ED5208FDC1F1B9C0290850820A4E6C874675430356340998F6D96C9D7BAC6C0B12EE232836840F4D8520B4685B0C2C1C9EB7DB8685F0A39358C8D08E292844EA6F25F07280EF453DBB3D9A2C5DAD2D8AA379F910D9581AF4914339A7B51A0E09AA240DDFE1C25409FC87E6A98B2640349C56E4387DB5DF820321C986DCCE30D7D7F56E125878F4439F53BC44B8C8696EEF0FF1727A7A6493907B5A19B6AFAA1A62D9319B79E8EA969BFA2B00DAB99CB574EEF7EA781C7CCA5DE961A8E2C806703F2675162C7A3E0D92534590E9CC1179DF6CDD7BF086E55772B7D6D5174EA4791A596E8A6811888FAC1DE5C9533C43ECE84BF374F8B9E2155C85EF4950EA2479FDFB5FF112364041ACF153549FB602363C48666CC4D7E0E8EBF69AB6BCC0C5DAF2F755647884E51E2E387EA3E4F800000000000000000000000000060A161E232A1B02000000000000000000000000000000000000000000000000000000000000 + +description = r0_max above the limit +mlen = 32 +msg = 1A00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 911A02631BFE7FBA22BC9A785646A089C74FC26BD86516BBB9388554C2817FDBC717F08A0971450EB8092E862D92FA4D60D566FCA3C0BA99BF43434E8D12580B9F09D78D4C045C618435469EA5A43686144A858EB1DB217049FFB036CE98C07D0EEF1AD02EE7FC430562A695D94E7B7F742C0D1F0AECF9D7A21E1DBE912B800FE894735EE371F0EBE9762F86E4F0E8E5302E306F428B56B1399806102BAC34535D3B4A37857B75F44E8209B2B33661EAF9F0015AA2596F24B21E9547BB468CA55F8D0983493F8D136C8C3D5E763D98D74A819C1B37511357B6552F82C60AD7DF91EB8A38762B3B39CB04AE30102F655DEE62A4A5EAD07AD0EEF62D395A29029867E3B7AA4B58A0F0C34C33E3827CAC3394E423996AE78FF8DCD5A399B8B29EBBE57453F5EEC3F540F00A2A9FE4810C83DFC99F1D35C3CB7606C4610FE91655EEDCF4A0B2AA7B4328B715268BACFB139909433B014CD32EC22050365279ED0613CB98A4B9A335F0DB3D66195ED2BC7F4F9C7AD545350A939B242F13CDFC1D271E3C45DB87E0C21D0B97FFACB0BB3DC5CCED8ED47D3891CCF94071CA38F62A96EFB0B23B849071E5BB01E8D5E891A5AEBD749DDD37BE5566B99AC4E242610AA15E3537490ABBD4628205924AF7B6300EBB9DF52367B0A2614D78471788A4E6E1AD9A2CD4D9AB0C589C42633D84D49CA1257A99D34BD90D14900D556487170095DEE45CEED8D5000A2A4C08D3E557B143D6E30E540354C513450828EDC7485787BDAAC462F608FE056FEE8D9EEABA663B609A2A48D1E9C79982DA006BF9F7AD63D64BC01F4A4E43F5C7EBB7C745C3C2315F080037EDB501F601788042B865786FFED5EA00FECC0156B6C2B4546F6ED1B91D700C12B222F7E26B3A296FEE0EE16644EF037CE46B30EC1B26A99430CDF27CBC6F4307A3A786A87EF98F80775D1D57D22C70D53AED30F91EC0F8EF83CE6D6F13A1A96021A739D69A1A1B6828502910D1A56D2716F8FCB6C3F5286A59740FE966B0D87E804880545DB932E87199009884236E1165A7A3E40B5006438EDEF71C90DF275EB2E43F27376A84189FF3B9FFF14DEC8FEBCE31398CD656D1E10CFA7AD88673C61413870F92851ABB5BE17035C9A4431B3F2E0D9B9A9C97EA5FE7B165F4A2A79C964DF0CA6AE3191820ABABF197DEBADACC455F1277C9E4401F3A7EE4BE9A6A0C69D3C8A3ED2E69DF31F947622F6E606126E03732021DFEAA8B03FB3CCC2F90AE0E8A00F0A5214EB50CE6AF2296901784C5853BF28A9DF062CBFE8022709ED68478004B774A85ECD71D2CCA96D00C6BB9C35ABFADDB5C23A4CDB0B8DAC66A4AA5F00064ACB2953226B41B2A470DD74051D405DA3014A5A892A3A0836263AB68EE7258EDC65F6C59F15408957A7B2740741C75B84E3BB9491294C6CC943D85EFE43CB4DAECF60F6DE6D6470DB27F83CA29486FD322F4DC42D88147E529E24C3813540EB1C66D64840F144C438CC2F553592AC178394BF6D08307904D512B8C9714BDB96A2C5500A7309ECEA8C5EC107C7B4BE4E3A0731FC551398F008C5F22B97B5E7423A86A5FFF31C3A91B24CD609B51F5918E74B1ED696B9D782A50E378C11BE38B3E5F5FE7365299AEDE89D6865C7CCB173FF6EF223EF7664D978DCDCA1658E92C263CF446C9E3932EC225885A866361B251BDD6699C7BA5F6AF7534B6E91CDBFF438A320C43CE8EE4F69A860703FE8517331B23105D00A78DB06B61D9982B89D12436ED042B7A9C596069ADF5CA1C9D32734D8748D34A0DABD8DE8DBF90D1224FC794D07709F390C845E4F26822F9C428D27C39A1442AAF794FBD2835C6F35643E50C5113FDD0C75ED2CABFE9E7E630A5FB1AD6C2B342267378ED7E0762B914A93A9A010725008485F2D9A02F7AF776B3E53A4BC7DBBB45089644F71D447C3A310AB40C631A7748933991F40060FC13834C5DDA483D625DFD8E231AC958664FEC34A8365D4B2D798732009395ECB38F9B9B82EA832590C484E16BDA281E82835BA9EFCD738DB10DE95F5AD9F93E8F6DCEF28FF930174D23CA3D7DA2C4950C2F4658BE1845792BE94978B2B25A9AAAA0FFD31DD7E7F015284BEC91BFF7CB404AFB447A73CA72AA4D05A15FD485EA257C32DA5DC6E102CA7A98212882DA4B57DBD3E8A7A1775DF3402B242F3BE9B6E717687D5D3F3A1F55F1C683E7DF7795F871433DF3702B5EF2CAE52858D18123F3573A95C1876FE0C6D0BC7599FD8A2E992057EA308EC29592F422A2EDA074FC1A1BD4F9C6DA2652FC217DA21B5242141F0326A4E0072ADCB5FBE7AD82FD2B1E3A97ABDFE72ABA34628B78116C01A45B331763393DF589C178CEE3B7162F488163C81FD44424A2A3A6707CEBF1F5F87F2C150D61AE6CC8AF0C708A854677D3DE0381ED987EA4D7F69FAE772A1EEDFB7852915BA084FFC0D057E0456F36EA22E6E4234E44968ADF8BFEEE3692C5DE12776B819E2AAEFFB425698F802607110358FC9A5F1538ED93394C86C25312F6DD7AE5C9D5E1AD4B2CD9D32E7CE2095CB564F7E3446F6D5DA0F57A5BBC3D5D427AF30C9E1E7CDFF8FF631BC94CEDA2FF6EC746CC283FA10AF1BEAFAAC6BD43E5E9A1B63622A33D5F7A7B7D3A741329DDA5663CDF9E52C195065615039B9BF96CC1093AE5B6778BA58171454374953F2C5D50721CF943C28825317AC76F2F5BFEB55D10E590E437B3CD46E7D464CB76A8612B9D836C22877AC89F4C4716FB330BE2DF6875E074A61147E16EB02EF627A54BA8641148DD6B556B442572FB9C14F1EC5730376DE535178C3DC92DCEC68016B8CF3C28D561F393BB2C6A90E18B04C9FB06ED926A69FE73875B3E353944BA0CB329F4B8F1A527AAEBAB4411638E725F5F8D837343A8FA2E6D1C48E8110A51BA71BE5545D066ED06CA3EA83CED79B7D6FC8BAC02B53F3BDA4D2D38A52686FE51A72E8C1635C230BF3DA64B378B673AC6E7B40FA1B22FDF14AF2CAABC8515C145AF6C054779BEB47B4749C1FE40AC47EBC1AF9F4F73D8808AE5AC9E6B85DD571C19A3AE2D5030B8D8413B9C2508594DC5F99E879EF8A7B7A4572CA8DE9B5D7C3C6B3C09BB437408E2DA58DCBB37DB0F36FC67EE74207FAD89FFFB9E6B2E1446DA2422E23C339999EF2B946B6758F5D61E70C53D48B8D2CCC5BFB8065684D36630F82AC806A2A395F570D9034E443DD10BC200C1E818F67DC86401457B9B0B82F6D7E6FE2590B4FC0A380867A099B3F5D8B51BBD2DC3D9333C73CD86C6B16FC7C703221C67A6E86A9D7413FF6FFA010F7351782597BB84CD26ADF1D92F47613DF428ABE3B9514ABB15A00667CF14C9EA0C676FBEC0F7427D9B0ADDDA30DA7A2B895C291CBD017FE8135580B3C9CD69FE02E08E9F140A0674311C6B7D3ACD4AEF8F5E356A2458D7D4DEC8B7364BAEC737A93E5F9829D247F9C88CF200BD42F439DFA55AD6367FE010777D2E127CB191A57C969D1B579A69474EB8AE222E1B6CA9D174C1A35BF9811AAA9FF1594ACD0A41442031BA47AAF1ED9F94C4B4877F5D9AB810C2BCDEDBCC35F2195385D0F41DF6D81433418A8DB56AAC9C24832067DBB7A8D56211F7208E6399C25DF41422ED734D5FC475D43B8D17497005D2F629ABBD6C3838691DAFA7570A2F9AF8EBC90C515C844DE8849D137D1D5A89AF65E504E09CBB43BD3E73219E6EA7C980A80364BA999AB38A3E9AC2432B582D8DF787459A9330B926DCC7B4B358EC127F45450B14092A43B53C35CE034353602386FB6F74FBE48F56257487F0584F10C8762750FC26326861D68C997D5B37CE77CA40647C82C445A9000CAA64685967D4B55C99D21EE59EF22B5E33B4637400559666B6D250863AEF8E8F9AA467BDD36CE406616218472AFD59F562273CC08671D1DBDBB48667DD685B4C55C0C202D544112814E4E460C72DEED53C9D1FBDF6DCE5980D89693BBA5F6BCB0CFB60FCE0C922C7EBBC0D25401892C7BD8F3008ADE1BD1580BB6200CBD07582A5127396438E229B50F237D84D116F47401E42E499B4CA139171AA4AA4C903E22A72821AC9858AC764CEAD0D967365E7DBAAEE5F366BBD66D628C67C870B884D58519C6B731ACD4C857E2D5F3FA6E1139042BEDFC3E4D56AC41769E6309824E54120218CF6A77648CD7859854287E8DAAFF5557921EF3880DE6CC58E860A43038AE89FE74C47EE81F87B8DFBA55B6779E43F1D064698143136B1181FFC0FB4182DAD52DED814C8E10D4F502F1940689CC5BCC29B0B9D88374542F93692229D9F3BE6ACAB3CD82A93B4EDE5EF5BB013208BF886E171D43485D9E5C2F214BA633D5134014D111E836A23B2953204AE34F26403EB61622DF0B2F5B76DA164F9F9DB6758C645E1C06EF88D8C277BBCD739C75A6C9A2DDA7542EACD13D16F38C6532AF09CA060FF0E526B6118FEBF5744296E9D2EAA93F1A4EF49F586E37E7DEC4EB719BCDD338EAEE83223480970F0BE08BCAF1F79F83673DACE99972E4210D54B6BE0D9211B5E98414CB160CF2711C9CD58B185FC9AC4C3C74DD78548A40120C5089E485C9142090E9DF898D1C2CBCC04A38322FCB54ECCCF301E15A5DBB568C4AB748DA773FD9BADD9200AAB0305494E54A2A9B7F113383D3F6C7785949DA1C7D2E3E4FBFC21283453779EA2050C62DEE1ECFE2426275A283159829395DF0000000000091920272B321A00000000000000000000000000000000000000000000000000000000000000 + +description = h_ones below the limit +mlen = 32 +msg = 6F01000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 2A7F2F6E8C77BACB79932ABE5708AA889E16891BF04EB42941428CDBE5B2A02694D658D104F6CA51CE8E87EB3FB20E0634E4239B26D0D6E08FBE9C8BA7624043EDA4D7606A3F18063B28C203298DE764B4083578E36B73751D6DF5D0B2563DAB5E40F30AD99078DE98B14176DC57547F06C466359C30D5E0B953D3BF9D31442D7E006CC29730D9F069E487E2830C21C2E191D2AF81EFA3F0EB620EFC0512A99EFD5EF8D7EFE658F070399CDDBE383EAF46301224BBA1326C86B260F8701F616D1908F8A9FEE8B42646B2B1EB5735F1A62962395013EC05DC549BFCAC77795DA42B103730FF65843DAA455D3D4F516A3A0A0F89CB30A3647BB2AFE8A03E359E1D7380AFCC316095290D731BE3631A57F1F2FFBA3BC24BCCB32DF16030FC5957267F1C082ED8966F3DCB14F6A209CBEFB8E24FC6B65DE21422DFDBF1ACBFAE731971E522308B856B69A0B0EB041668C5F966379AE1D3A6AFF00E726C9BC73DD70ADF67C98B933098E471AC6EB740074C834D429F8C026932E9103EB40B8B1C2842754FCA9EF28E6A4EC9C7B878241AC720834C854E551D0222CC1D8C7C2E4718A9107C4F56668D30E40628FD60272FEF34C6AD1CE3F34F91B1BED2E4E588220ABDB7CBFC497699574B1931E4824F4673C42A37BC6DBCAFA408B31FA067895919461FCCF5E1CC364244ECEBEA76B3BB89A92315CE8A954693C1B27E619977B7606AA81E1EB41278E88169C4F51DC9F08010BB85E4C63924C2F36045E2D9FA8C1D8A339D1555428E5D43C2DE4B156997A3189FFE356A4221B18B74DFAEFDE39C619322FB080DE0F9C4299C75B81D54E3EEE6CEF65D4B075D032D66F461D0923F717066834D439F50C865D01A874D9E4DBEA8A187BF28228C9B557A854AFC6D68B83CD3670F49247DD6457E4813CE430A2E16847C2AA0943133E30F3A4DDADA690830CB4921895052B9E4FE7CB28B95965F3659570CCFCB819C238767450FC25A823EEAD30273B5BF955F5D0548506125F2D835BCB807B63097A7C3D704C693B6D5043DC3C9679E0702BC729210F1A546A3890231E92CF40888837D8E9B63A5A58B8596AC5D06C97FB232EC836F3DFCE3B512E67BD628A188084E3E7D90048F1A9348928B56314D33191E8FE6A9764A6CD8EE75F6518705B7CECBD2DB4A2FEF5103236A0E896912277D1504074D8A3D3073DEFF2ACF5C5E06BD6F470E714D0955958CAECC552C72E29697A8D84611A7DD5D73AEADAE523FBEA696EB59D160607FB62FE7D8ADF8DF1AAF5D7C5156E8D96E0E4A9F903DBECA6F2E81A8E2771309F14C761A4CA30277F9F2DF8F46D30423E8084CE69D0FF8EB8A97895FB193B8DFB6344AEF653AC818C54D0CEC13D40C8A8D81650D90DDCE05C5D941A0E036A326B8D13020254AF23B06EAB878BA9589AF355D45BEDA5E1BD8F6AC80D313AE12F0B3EDDF25FA01B4DAD3F06EFC918B6E7997F16A8907E1E61C8135CB4CB1E8D73BCE5DC35279D4435D4B66DE97649B6A11498B33F229014E9DE1366369186D99D03200BB30D2EE6EE6464A05ABBEF217F3AD6A9E686CB2DD792A25266BC768CE17B3C32942C92A9A90D905500FB95EB65425A04AE954C4EAE92F6CB6D0BAB3CD722DEEA1C79C37826A7AAC4311D31F3572565DF5562D2C89E8FCD895B61B8C24A9D69EBE46630BDD7C3CF47C98453BED0C82CEDC409F44E92258FEBC72F8F137CD1C09604669C0A1070B25C09CC6CEA05620E87643800B5E0B6A45BDB5CAEF0D969688F560856F332B2095F764ABB9340985AC232A800AE1C9291AB052A0B5AB0F18CF76E75C60F400A11EEFC5531222439E01127983F3C98CCF418474A937173DD1D0C9D43CACA7903A04BB5AE633176E5B059C1176FE804F91F7506314B0AFDBA5CB7ADEEAD68257BA8B2CC07286834DC8C0D5E50F18C6EA45F73FD500222C949D4B57331F82A39F6D43434A852F5C2CA8DA7A91F7BD78FDD451A7A8ED6799A3DFB3CBCE3E12B8E0F0699B0BF98B20561CFF0950E6CA6BBEA5D714A52240DB59AF0BBE806A043611CC17FE310DF8531F4C609804C5382800DD2B701D38FB9DDB42C698D9A324E636EE26BB39A81EF8A840E7C0602CCBE31DA2FE6D816DB1F713225F0E95E35CD4A3232237199735BD83453BF63DB456FBDB06D0F7CC7B47B2EE2A8213D221A364DA2B66865F54876EFF1BF16AAEEE396A8D7EFB722BE2351CB93B28461A475AECEE021A4CB3C8C64AFA243FAB6111A986F45AC566DAD078DD36D440441B02B5CB5B69E39A911253B969BA536D9F455F1E0A7FB1E5AEB4B816A14F2E07F951C82AD47E95F3FE4556C3C13640F29E1B0287A71531B6976E34DCC475B2200C1AC90373A52590D65C24DD2D6FAB4A77CBD3F4CFECFC52DA0DA146BFD120D8C8D73FF1AE819F940F14219A1914646AD0B20EE103C5392283CA98E7C942C54EE77F4C46D7129502756645AF792FB995981AE4E9607453D6EA8C63B64E7FA10DDC1B8D5B8533FBF6655F0C7A6351307201909128DF0B90C70287BD8E2BDE06E2BDAB02C3BD319AE8B422FC3F5FB9BADD45255BA572241DB8F7789C108C8071067BBB0432ADD83159437592B6F58EDBD7FF57275EFE185FFAFFB6629DB28C28737EFDCCE06809B6320902C154689624004CB4A8FCAA65D336498BBD41E464559ABE17E3A25A29E824EF2D9CB5F900FE0250625078C468BDED27C11454A84E727A3873F5CE9AC68DF451B4C055BD4EE12DEA4FDC49D1E1840D46B87A0C8B5F398C10DCB249332E027D1E6F3FCBE33B1C0F26B816742099C74EB1608E16CE31A18629715941F6BA7190610C1BE71371DF6AFB0A0471762AD86DA0D00466BBD181975E6C410AD259EA6CC5C72FEFB5E185CC612E33951522DB41FED4AA84B9B35767E78A3C3598361669C82D1B6E99DEF54ADFD1D09F88BAA00C413B18FADEDC1D92FAFE9E286E3C0130C83491CE4084543AC52B115A96244CDC68E8F309E5EF041DF076EF0FA23B8DB04070A12861C8CF0913A8C11837D716FAE090C4E3905E15C4E3F6E1B3ECB8AFFB0FCE86232B85626F30EAEA00A53319C32DB6023C63E799668F30B060B5E883C4F15807831C6AC003A08DE6B6BCF1A758E37BEB99C6B3C1E486A0324DA04521D0446DD960300B3EF8FEECCDDEA79CD0143ECF516B0AC37FAEE1096C5403752A550192907358536934B1D8BED3D1AEF9FA56BBE3CA0529D64BCC9A6596091EA9DFC0BB5B5392459947F1025EE5555B56E083C97331135400BD25D7F30D919647BC94A0577EC8963FA261C02E4E619F74E7CC803B0D2976395BE4A37941E810E310B4CB04296210AB167AF312082EA73157F0160F24126D2BBA3B70218CB78A3C91CD573966BEFDB9DA5B384D8D0F6D4FBA384FB502800E3784F432CD2AB14D200D45705746622F659EAD3D297945380236515EEB97C90033D5E2ACC2FAB9A71F386930F9238FABC4063038ACE5427E1526390CBA00F6EAF0F13FD3D96228B988D758A64E8D9105977D1B5933D9071F6D7FF26537D730BD00F871ABEB94620EF4B10A152C0585A3DB26D12AAFD3AC9364D3BBA9E69FC83E1864587A1E1D4F4FB62EFCC92373CE2D53473CB567FEB7CAF022842E5C3285C9827BCB4B2013A834A42C36309DAABFFE52A9F8D2D8BF309C764CC1D62CD5FBCC07AAB6E4D006E5A4935F347B45D7BBD1AEB46D1EBAF0D32F442DDA1A19122AAD3690F324770D6F867D0AD24CE0B590252D1D6F915FB96391FEC04E1F4184D82DAED46FAED7AC87864875B720523AB1F3E176A207975E6EEBAA4CED0798570519D0689EF6B45D9573EA3A00812594F35591FAD9E5888C91CAAF8BC5461E717EA5A77FE95E336E6201AC7AE3550300590C44C46F28318367F8B88288F10580C2A2D71DC4DB6DC07192CB9D21EFDFDF85B93E9C0C2E37E52F16320CA17B6A64848993A12A152DE79C486BE1E06282FCA9AD4102909E9EFFA4E3ADC7BD2BE958799A6A8C9CD9EC22B853364EF6F76CCBD1ED6469EC65113EB78433FBAB87ECCFECF1836F829A51C7B9B3F710D8F90B7506117087679015A4D51C93F59607ABF953C75439C1879BA1E31A3A4CC4F878839898C08E333556D9A7D499F133AEBCC7D98B3576A557F52A88E6D5AD099E0597B8B1834BB00D9752258BAC6E2D91502A91916837BE2BE4AAC02A474A0A776DC81AF8C6898F0E856FCD646C2D4D71F0EC913194DC59DAAEE548D41174750063EEBA775EA83986C2EFDB987EEADBC6D5DC36A9FD870F1973981D8CB3668C792F7B156DCC832654F4EF08890679DAE49A7513AF040DADC0B08563F95A03221194A02D0BC2B41F24D7F194D86D45961657DF90737A8571312D407C8D6FFD68CF74DE9FAFDE864BC5DF2456714F812692B8ECA59ACAD89BCE4D4E853845B2DF5570226F1D04DFBD6136C633D9018DD4F8171A10C9839E4C777B0D9F6A43DB8B82E8DC9FC367D8AFF643EDD08E5C3895FE40CE4F53F72453A77B8B816F9969BDF19B3BED5C7C8F129BA24150D7C355F50D6A500F6D6AE4592EE3616966BB0FBFCCC751E3F631AAE9F92CCDE3AEB6C9A98B832E035FECB23764CD82BBC23DE3F52C82C060B2A6B70B1151799B9DA1B3D0E30C5357A1AAACB3B6C3FD0F11196283ADB0B9C1C4CDD9DCE17689D0D1F6081F4B94A8B9BCCF0430394E5F749ED10A1422272F376F01000000000000000000000000000000000000000000000000000000000000 + +description = h_ones above the limit +mlen = 32 +msg = A301000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 8AF63ACAB69436B2C1244E45C8E6F6E75DD5F7EFCD93D132CC613A0DEFE5361548B9354DBB2EC4A674CA4E4495583EA51BBC3A9506BA941B305D4483FC09699FF6D95D55F12AF96122C71CA8732AEA69CBB3C21405572677EC926C06EE40B0A14A39EEF44FCE23743F0285E9FD3836657DE1AC89006D100A189C4A44668D1A96A519580DCEE29E2B4993BAFE768D9CE84DA1C274399C306D0CA24B3863E021E5FC1A7361362DC1E63B765A546F940259910A5CA341622F3A0E261090B4A30AD4624B2F6C166FC8CBAE6366B19689F5A33DBA664403CE6A5639645EE46D9C49B6CA1F0FA6BCD9F62336FE4BBE0EA5A571C116252A6EA763680CC12A7B25C4726ABEE6C6F46CD7EEACA9D33F820A13114C0D5B8793B911B26A3F43C29C3F87706694A77925BB7D67321D56DA25975ED08C04D20B713B49B6D6E6FA1CC76F7FA63027E4D9AFA19690BD4A356DBF5CE1D2D65A84EA803122DFC6877998A9F1226FFB1543AC4ECE57338BB87C02E182714C904416A10AE8742E6B8205686D5FCE8530BC1C9BB4CE3D7E1C1C56793D60814D4878E7F5176E09A40870FCA693705E2BDDB831D74A366A2BD668DE5BD759340276E59CE846E14DF866A091A7FA689C71DA1594AFFD600FC1A202A8A6F9ACE2820AEECD152D470D040E921760E48311D3C6A6E8DB2ECC948BD8B0BE6731E0C0966EB2598091413B331DFAE46DFAF7F0B59107FCF0806FE2B6B551A20826C01D04F6547186C2E87514236E904842B2BA5A20BB6621DEA873057EA2592EC1DE4A5FA9B84DAFD92A864D1EEF8422A9E3320D913CDDCC55D56739248F1BD61489AF13AFE4EBC6F7D3A6651113B613F5229C8BB78238BB680DA85DCA417BA4AA03339621B35180EC4D2075A2F0BFB23B810BD792823B85978A46E659A258D00FFBFE5423CDD2CD5D123BDF98FDB61DA4CB926F9B3654A3479F55AAFDD87831704D3606D8645B1CDBEE5593D69C2ACB0769E7C4820B0EFC378E7EE56F5EEC9C4EE0076677A9F9B89F08921BCB880D830F2337EF7465C774DDABA7236C3082117C40DF45AD54695D2158992F77A3A5DE49F3B0815B30A1B3DEE31426F05513504CCF31BF88B20F0F247FDCD783257EB899A0362CC0C9119B683E3231D3DC653F271BD9C80E0E50B766C609E7F49B1479E766D0603F9A3D978B21FE88265ED6A610D56B9EBFADAD6D3939CC5F85FD733EBB631FDE924663D1F02CC1A190D53CB17D5BA519B3E041D03B01EF85D0C1C4D86A869683B782BA8847896F92D38FB54346CA9AB7A3AF3577AA4DF727E97D070F5044CF3E693CACCF4F04877ED36A940298AB54B6DE65BF9C7397550AA68E0BDC4D1C362643A6B24C655956FDB80B07E19EE941B1148FAB8AB90163A029689F168323AD9D3E27264ABEF2C4F7DCF1E84C29B9655445AF8CC195FF48B3E22788D30C42322C22191D02DCA1EBADD062D937C9C852FFDC665312EDE8A4D4468A32371F7FBD2962836478F26E34F1C04CA2278F13F7819C095324C027E8F702BA0DA42EF814DDDAAEBAC7FDF7B1A0DF56E9D3B0EE05159681B7AD30A8BDCD44BE7965D2A3101DE8808B98D9FD992F4042ABD1B55B26EB2BC7DD314DBF64BE5800588500A418108ED417136AB924A544578ECC56B58DB53E7A8952D350E1E98AD6D15A9BDABBEE835C689019F607BFECE26B1B0A8F90463316AC213B40F5D88E56C5659D626290CCA99C7BEB1D9774038D7BE471CF9FF5F799D8D1710DFD6E4B4DB9BAE982A231CD0AC9DF41F47DCB92574DD0CF68E25396837AEE63DFCDA9B393F2A2277AD2DFD7EDDB8A50BCDB335A8BD44A6BD0CB3551D1BBEB19DB1474C6BC6AD6316FF0EDC21516B67DC906CBB4A4D2EF018C3821186E3A323A878FB502384CAF49E154F0CE43CB53A584357BF20720FC0044BE73EAEC90EAFC4A7BDC55D78FD7153EE37D24992E5C846557211AABC4661A79596C1CF226AA758E0FF776711A99640B3AFFF33DAD0A6055E8D6C51AC69B125C916A0CA520FF9F697FC395837F43414380C520958D84B9BD670BD81D81FF456C5AF9190ABC2498A5DE0F08C982CFD79AA8652A0DC9AD70F1472A939885972BDD4E699546815C950FB26B5EC8691C6DDD3AA53BF55581226606A5630232E4E4EDBEBA6DB684522348E8228B9DCE09B63C3F95029C7CB4DC90BB8B4156AC4CB4627E3D2E12F2197CF8C74C2840B91BE255C3F02BCCB427B2741DF2EAF7B2B9C8B9ADBA98E74EC42E95C0DDA2652180DD44FCDB008B1ACE527E1F240DAB90D4BC80238342CDE0A92122C55F158566E0FB9E0DB9391046CB20CB083610485BE2E700126F20FD7745A0C877251C10E1773FF453230973E794DD11F3478562F1E2984E4EFE2EC780877329CEC171E4F6686B8B8E05AC68FF1296D066A2391A700E6C59B78F374E397F1E02516FA6D4BFE312A075AC4D4A5CDC062C7A6227DEE0B95714C633447A557DD401F52EA7BB5909A47A37A3ED7A87EBC7FA8C703D48A2A0F80966541BA441F9AE50930F160D9C03B7742E7BEF9A427636789BB4DAE10E13FF552367D6A8F897A2BDC02AEC3902D8EB387157456C4367A181222C4837DE8305739F62DF370D6CB19E8BDAD686C049080C045B3C40253756E2073D35845F7F216F2AD3F82F7822F24C1390DAF57CB003D5CB1910B668360E15E2483D8CF0F0EFF239EFEC41FDE5952FB4A8C5CB13A28AD4BC9B684AA9195768D5EED75DDC877AFAD68C4CB0DCC25812E8A8DB3C5602B6EC4FF0BECDA3B2E6FD8B1A64957F207418CCDF31ED2B25FF185A3A1B48F2E7A72DDAF18A3F6C795D048ECB3CFD83E3C823A6A6AB94FEC10232A1231126BC4F72E9BAFBA9A509587D72B3C05C1204D602608BDB4088E15FF4FE87E6CC40207597D578DECB455FA30F0FE78C1A393EE55452B6BF704BD0BDB09B0EDD65C025F1CD3ABAEFD8D3B2995FEC922510DD94BF520C552780A438E61B1850CC00F99D67775EE8E5053D1B20117EBAE042AD833DFC0D8703B8D1EB839D0D2CA19906BD60AC515C93357C1484875CA134C7DCEE07CCB0B2CB2A143BC6965FF224518887B39AB348CCCD82C64B0340B05E83DC951CD419DEA37F5E98AAEBA9E7F4A420CEB34A1C9DA57670DF45D3DD32FEB4192CF0490494E47BA70107CD213E4E36D8650204116AB3FAF000196EF870DD8A5A6860893D60E0F22A6AE6804EC687E3729D45F5323B86E4BC1B6E30F336471D958C23520D44DA5B75453AA412A2685114C8239C7D73B3AE310D20D75BCDB2DC9A23D2BD9B9B27BB41115694FC98A7AD79BB2793A1AD04CE0131AAF8A74D627654B0D0FF74CE320EE98A1ABC5AAE2229D65D95A34EC37605FAC9D353AE0330209C9A4C8752AF1B32751CE01DC9197522A8B2641E9817A5873F6CF678DE8684F386743671B8651EA5EB3F123DAEAABE237A8C10B58BCE7634C7B65CBA61230EAC412B32C4CE326B105FFB3D283270CA5DF72D8F4E36F444DBF4CF050B468016F10BF77F92C24E02879291B6240D534461D5866ED6D2BC525C4F9049B2A1A7DC7DEC180D33FF1F3AE0D8D59B40840DAC21E87E1A896CC9FA14933ECDD82ED6E53FD10E3508466557FD762A642707DF1C14D6274CB101A8BD83F5DD3DA100B5689F4739621234D78BE9CA691834F022369EE6A0300B26E6C8EDFF09D8B5856FCCDCA837F6691E12BE1BAC1A70CE0D29570C5EDEC8808DDDD069DD50A67C758189BCA72568EAFBAD11FAA11B63262684FF1B4E24914B5E75E511CD1065F2CFFA7A392F153392D470F097662C65CE59042ADED66061F36AB84AD192C81228E1BF708ED79E4C6759F9526B4DCA768D674ABDE8C985593F525985989FF2466D954C5A3CBCBFF04FD9C7F227D6D1F044465A10621D1BCD8C37CE3EEF7BE3D7B6EF7C4C105D35E17FE3EE49C2B4900D8C8D431CD394AC3C66B9DC42B69490DB87412FBBF94940FA7DF64074820603BC4D49C022BA0697D7DD25E1A6FD822A8BF1D48053DF1F5AD07A63CCB459492EA946EBF31E3EB7EE96267DA62DB8754CDCCF03A77E335154D9FA8B8A4124196CA96E5E343EFE7C952778F128FD1A2C2B66EF49679E7FCAC002F69F1E884E8761B5AACF11B222A6EFB51DB75AFA498EB4DCED56C3FE0E44D80602D802550AFA5A6108157C6D14C87809706FDDC242D7205A4A3D3D4853EFB68466E4FCF44743A342CF4A8E26B82F7B286947B124D8BECB17BD366EE4520710DF72194F339D21BFF18B155ACC353B2CF249D18D227D2315CC30E7DD6614FE940C23F4458DE305EF37C2BB763594CB6DCBADB65C4349B9F4DE4A43E084E778EDFEC85A384167DCCDF0339A70FE83565B30E71F1B4AFBBF0B4A3BBF19B49447D5E431E90A1DF83678B575401833DDA828D9B14AA20276874373E7177D700806A0242298AD056BEC878CACA1E8A550C326C3DB38C2032E3CEA380A53E09811AAF3C84B92F20FD7122A86A2076178C40F34E07F8EA7914E98FC4223C8A9A4F7FB2C2C9F07F73372AFC727F5AD1565AD25027D4F227CF8A744290A04E350676981E415E172ABF6848357B598DB96C4CC870EDBA8175D88B9F7E859F78ABFE2FEFF5423E8D670A49A3356ACCD0E0F225837C1DAFD050626568999CC11234F6FC6D8DB88CBD4F2F800000000000000000000000000000000000000000000000004080C131A1FA301000000000000000000000000000000000000000000000000000000000000 + +description = high_bits called on the edge case +mlen = 32 +msg = B906000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = A8AE8CDD7601A1C6584A0046AC0CFB3C4E3BC3ABA16E4519B1B4ED50A546DA059987DD058F3A4508EDEF4DD7DE054AFA64AED0DFDC4C9F9558562696A4ABD959E924570037741D10FC9CF0459822B57BD5A84F3AE7539B475C60D95E4E3B2D9376B0A84B4D3031D200E279A3B778B4D43542AF4262C6E5AD39B962918366B0C3EB63B35BD3DA14F084E1F92DA6B229082CCC52D9176694476C10A294B98A890AE0DCE28214AD6D127245DBC778C1E1927579350A3F361DCE464594C3C1DA42BEDB2A081F62FC6C6296BC60718D8DEEAF5A3B6DF4D6CF48ADE47837A95B8013CC3C92E03F94E932EEB4AD008D41D0B8053503FEF97FFA71AFB208DBD0E2981A519493D6DE40C08B458A28FD5BAEF5FC24111657C20F953C36AC3CED9B0CBF3D48EA7AD7C2FE6813975C07F83BF7B7D85EE22C5A9AEF62B328FD4B60833F377ADCFAD8EB6FFF9E8E5034182517928DB6EAD56082D7F9E1DCF31E21ACEE55CBCFC6B180DF3F140677C39299F96DC8101C11CEACB613784F8B75D7FA12EE0B38E7E86159D3B4379543725C305B48081888A44FB084C8C97911BA6C2D58C9184D3EF3ECF262FEAB0C9BD7A7347D3154F0ECEF8C53DE747DA07E913E3F42C54C19E6C876D226DE5E790DEA94684F3031348CC5E66E8E6DB22B154942CF779BEBC8C2A762C60858C13C2CCDC5A6A7AB8BE884E60B3C730BDEE15311BADA52403AE2733CA9E728EE224D919476BAC87DA7AE384DEC6E47FA838A1D40DF75B04FFF35D5820622CD307609036493CE0530F7E2E59225C63703582ABD8F2CB622A325A1155DBA9F7B6474FA57DBCD2BDC526DA41C7FDACBF8772ADA912B95B6FD34FD709A292BB0D92360A6F55383836E967CEE3FD13773E23E015CAAB30E250961496CE64B7EEB3A9120B0ED6BF90529B121F74923948EF1205C95BCA03E98C9642404AEDDA7ACE200D2A7AEBDF854A350EF3C520D745746A76008293EC508B745F159BA493527C55E2ECDF67FDBC3426CED84CC9451AC7D42EA08F5C026A2E28544B1EAA65D12033518CB8F87ADF6CE87A72B9B7B3D3505F2719C47D2670DBC13D76BF61FDAB4B4A58AF5DDBF79CBC449565A4712DF8F10F4D58C2FD0F33F6074A0CBDE6C18BB4D988DA12263F58B5224924C79972ED39D0391D557EFE9974A686A385F80F3B5C9C7E1ED4A1CD79186D24E38A2899AF567886B36EB2A8B4F87A173094863E9E6CA77C99BCFBC93139D5C53272C1B7978DE0908F55BFE90ED18B0612003473AAF252FADFEAAD36DE9F00AB6175D3C8A0D88A1CFABC21D6A70C53DCD3655EF13589C97D88B8B9499FCCF1E0EB70B6FDA164AA039ADD3ACCE52303E1E7EDF17493DD6FFADA104404AEE7097695FC804D41BAE02EF74BC9030FABBFDF269F027741A4B27E4B6D8CE636F605CE467802A286D73AA748468BC8E35B7D3F705AD650CF06BA9C8D2057633ADD59D5D92DF71539AB957AF1850C2A98790D003BBE6A38BB0A21E3521BE83C94F77C57ACB61BEB013BCEC2820A3DDA5F9290965B8DB9565F08507AE9BA11411869294620385D04E5A3015CF08633EE8A876755B6C76A722E557B4E289CA0F675F55363AFF3F2D1013C64E72764122C75A4E527A7C19EA457817725F19B56F7FC05E22BAA9BE29825413ACC19FA55600A95E842A7EF9BD0E7951725B3E396616983E234534305A4E05DEB017C82D14D9D717D11316DC425DE109C4574EE934A9EF4F629394FABE3953E9ED9CD30A5CEC6C2AAF7F2AB02A85A7089CD903226306D30D29775067D2B3D60CDE82A5DDEAF600146B5269908D3AA020344D992BE7E5DC63042755E25F702025733C5F80A9B3C463326052C77FD4B5B97CDC2BDC505D8B30BCB4DB7BA449438FA016509D9005C3A90A65AF42B939CAF7BAB8520040BE9730484F3DB2D32CD144FD45ADBE35D241C1FA3F80C9862939B335FE5509454CFE6836E9B0F2834C12476471DB627E168D6D09C015C59E90C6A7AE21926342365BFF7FD23D45D2D0A3D0277D6DEE0F18A776FE5FA5F14637BBD09C246199EBE1583966CD133DC092FD7777E0476E9F4ED1B5313F9CFF5CC270A5EB79B9F2BAAE0739F24968D553D420F76DB16B8D4414567E17A9C41C3B4E49B8268129AC37CA356F0A5F052510C2F3134CBF3A5B95B1514858CB93AFAA3A36BFBFA9BF51926B790485AC73BA738104ECAD51AEEADB11443829F4AE6B0E6E2484B826E8F77A61EFA1C96B5AA5ADE23C7672872325EA63C4789BD7B612B1C6CDAC1171BF318EBB00CBF28994D1694C810769D8FC07E5FAE3FBAFEE192CEC26C52535758A279A05295EC0AB14BA25B61B1770981D3CBFC7E990E1420D0DBD7922ADC048D48074549EE7EE09E6568238A6B7BE3E8E12A032A5B0CFC9BD43F8A075EA28816626F9CFB1618AE12B360804C9D640CCFF5649BB150A8DDA0B1B643412BAC11ACCD304F6EC5894B3A7D92751B454FD50F1B0F49902169C6CB0065F37F660301612C59C632D7F84CC8955EFD86C7373A9E729857E2E6E4A6A094BF98F0E9FAB159094979557B0F31A4EC8A7C22957D0BF3DD31C058638FBE8F57469E3789D67DDC4F0CFDAE459D54345A603D2CE79C633FFD9369A59FC45E3CC2F2AA5C5E5B7ED3338523EE2C8249D25DEEBFFFEB9359E6D9074BF33DEEBD997559D21F0B664F029E536C5EE56096DA4C7531C9E2E116D109011F86903CDFB4117FADA57A01F178C71D4F9FC0367864769C9ABC75540B920F0136179098F02FC5F808840AD1680981BED9731EE7A2997FCBBD8E80B00A8D85526898EDBD6DBD60C478090B49AE0863F961654D3E7BA10F03A94CB4973EDF27BE2085085F799A5D5007D256EB0987A52ADEC876CD0D036622FBB0B53DE0ECBFAC30B1C4884A4248FE1340B6123519722CBCCD712136642AF9C13507A003DEDC647BE782E1766256C6FF9CCBF487919827DF78A87D337049A7856618025A464FBFAC986434B1AE21C1D0A7382E7E0781A457E4E0241CDD410706F4713D15F6D61929C3A519CE05524272C0A333A39CF6F437F1BE0C86E0B531BA6AEFA5BFE1C12B95C5E8F5CF62649B30D99EEB2CFEFF4DA6728C1EA3454A3FD5A63C2EDAAD7C7F7EF0526E085071630AA4674315917DF3F0C1B94E19289C76ACDE2012A060259793574EFF3534DAA0966F7B33C616ECF7CEF24EFF84A207085C1DFCCABF6D236B8D3888FB647B5DED9683CD8276807AFA3E5E88AA5EB5A5CEFA026EB7B8F6D7457BBC79E72DE4CD4D92A51A38127376F01D2C386D2D67FE3B0D837C69D4D7E7F7F7088C0136C6CD68440F906E0B34F86392A9C1217AE98DE0373F9519DF555BAC28411939FEFFBD5B6DEA5E8FB0F9F87FC2F9678F520533DD4C1EB1B0981E540E355BA4EBD489A2672FF10D2380FBD956CFAF3BF315583F11313A3E34BF4156D7525788B7B7A8D17D14F975A695A22745DAB8601FAC6B3CE7F4BEC9E298858E702D136D7EF683DDB367BD9DCE2F54D5C54D4F160DA32FE78BE2DCE9FB7BCE3D079CCE887399DB28C759152C16CD112B1C67A2020D46589D0879EFF71E1F60C05077B52E4A752A03238E697B5829826C5C7E5F67B14885654266325C2D08A51C061EF88ED081A5636FEBB510A8DC56319221AD23107DEEE4BE080EE9C39EE3DE0ADF59157DFA36E403FE55BCEBC4C4011A3D638C078A716D11D75ED96E860F39C30D4929DCA6C7C61EF5592AD0AB218E54EC0D617F4F1FE0CC35C70FC08BC95D758F8117D02D3C57DBDE6B3C78DC5F2644544D059699FB78F808CCA390F0B65E9C5D3FEBF6BC83224CCE78F602F2D289605C1F9513358C5188A649FBBE3744E3E27A40F59C0184EBF4B7FCDCE3978B25D333706ACEECB07A4A57A0E6536276505949FAC58FE1534DB31B2E68C327FD30BA76B4CB8522284BB9010155F45FAC65B544BF28AA6552CE1AD878C6703054F499288627CC2FD5B2D7F62DDD12FCBB9064A8CD8B2E52D1B11C33BBEE9E31570C53794262D974CB03BCB05A6DA95D90467A6378271D3FE59CCFC5F0607E69C8A2DD542147C7449A82AC8887DE89C0C6683D74C76023782FC40BFEB565C8B554821CB27FC528893EC77BF4CEAF128CC6888E54340DF30C2439EDE07BA9ECD30AD0AE498AF1BC71480FB8BF8DCD1DC79BAAE421D17790F5D5331744E555E7A6FC0AD02CF5D6680318E1439FF535CA6B26DB71BB57B66116F5C8EBED986F209296E474AEAEF97CA694C0FF22D97D022C573D7274A20FE61464C994EEB478047BA7194F55BF7A98614D1FE6C668076FF36181EF2BD1447FAB111BD439F658A982269532D51B677D87A7B21B6AD43445AC367566E46B423DBD531514AAE2AE399985461552630037358278060EEA1550C1629512314E8115B2C9218078DFBA77D552541F0E2A84D1164A4ECAEF7CE265941376C2755AD08254545E1D067D03FCE227A43C3898A525699B1DED34BC0125E9208A16ACEF7F24676AC1CBD506D8978990D6CB8BC2E4A2AD024046D2049C587BE4C8838A8EA95A0B09D7C49CFDD6DB6EFE5B79BFFB9D0029160A6ED5C6EBED0FE13C385E90E91C235D0515374001DB3158882D4889729872CEDFBDC384A6DA8E02B4306454685B8BF08212E73A7C1FD0C0F7ECAF8122187A8E20000000000000000000000000000000000000000000000000005070D14191EB906000000000000000000000000000000000000000000000000000000000000 + +description = low_bits called on the edge case +mlen = 32 +msg = DB00000000000000000000000000000000000000000000000000000000000000 +sk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F271D69371FB6D0D47FFF2C2A3E14EFDD968B5F906525510164DC0922789DE9A364BEF2114DB20C23E2612E09FF08803F1370DFEC0FE7BAF7CAA0B136307C4C5E28D66131588FD95EF62F045CE5F9FC97FB325A615633CD8B3750E0A59AF4EE68B585216212026265666057753762085830687728826203255015364500824305705421788508673025302771854311582767373483402102665584887250778016030712061065380761502612101165404558474224202805007621230464462203685778016057425826815317568238050772886480511037851166340110028128861260455443102346746431860763856471622017425050180675648525378810181776072811033216622340005338886614075570325637871365126625102514372714386215651262883035888186882735136623044213523306773082628331327670166380686860637847735480225154251866458000167681310524352403754743431285760007611167504453407871341566585122186248157656528871414777375514604212473713857715880755217452466552765547571103116775577340526805888582608517271501687335575613163508777326368017651782262147563486803737458175820226282640535882745376418557344128517764663704648266473421507627362855741847253641767062483771431577003622528742541754555283538126218063277457610415642212865785272860763488822603010447634121135027541730132053856857612685470587335853528625287673006660740067107745148828747467378105737675563673630035158431677607703476053047211202662865785547755147672066236487346002377860303756441377465637130071476433050408631515287032557522016415124412332075877570258425456330211868467418120642856576372633652261325222715024638783743186171861336733668106817338115557030361837187742101862103468842371136426532687217056001673728818313538605158860500557560156230048207235127633885081362730082704536018247573410784180717282340546403568276245472708513411278815266833586788160374774788643872827514345643713837253483842354477256048542037314586713324523031845643038500151376685640174056050663250780675801307057876088208756066411843108776645730115257078437415660766813552323512700650800184476516820562567551552285130646380817033028871742634054206101718252575327248338188705041538562187351855145622016264058183741654220238467304622778808736028441101714166800430072405844877284520248118542118510634655810685885145833435215685301485377543437155877077875656275080061815578383736231754112225386161313110561783553214033227315467012608005005482155373246688252866116575420630874416827877888645175202647448136188068213011125518360748372782503005450707815046515730448781368663564651856447431414754067735276010414703833884088654636713747165327332281573023480151541626827321212337214250802680361011166354754226081576124500458162332812265381143530822838703121611803852746568104365872885773288001121184272014882478231480025680664574124608736806187572102766668231210386821073546640384601388305113017266233868666582444544268042874431663606850264533334251076203211018257626582513206133230678348438275316543603240506276801178108543248376246768821855768252037777833441606441085058451537820373165544816815818708581423418330152611557725506875882745171231630715162418605378345582260612866668700018875062702437733366CC5B335379C2528DE2DB3C7486BEE132F92E34B325EB2B474E238581051D098EB8130998A5D0CE7E8ED551A204EB0DEC3E53A53025FAE317C1D973A27609D5BFC3FDBE6360BD155F107108C4A5971D913A3615B28CAA60B7DDC27135A14608D2F43646126402F3F591E175EE4C34F142D7C2332C6ADE52FFC31095A5B4E23ED5B63DC4DC9D05496C4BF49B308F526B447E5601D98A3A111C62D349AF190CC96275FA4665F1AA379AC393CCAB3F5FF0D05AD217BB0A8F69EEBC1AEDD7DC219668F9742E1E8A2862E620BC60B06EC7700FA9060655A892F183E70F29F6D188D8B1AABC090B8C4EF967D6EA350D65FC02EF4D6F062C3C0421794EC261F42D93D6F12EAC55F5803518DEF6B936C27E1516E547BBED41E86CB23708BD941F0C75D272A1B4C8D09164C99E3330142170C403164419B916F956E80928990FF35B52C5B09F4CB1635D212D912126592F2F73770C759B93BEBF89B65D0EFCEDE2D29324C9170A716B93EF99536714B7F5CDA111499DBAFAFD5412EFEB291F874F0401F52616FD6EB04AB7D4DF4B69322CCDEF1A0A5A35CB365D5B0B02D1E5C78A9E1FCF1C02426ADD4BEA769EAB6F5AD19358EBE3E6C45603FB5D056FFB4474984B7942EF2C03B3E2B2FD000556FFD1CCFDD874F5628809BD39E396E172B3B1316F77B7E11290A0C584A148EF9575E7DE4547A680808A0F09E604B7231E4D627995BE092D61141B874FD03DA36A8933CE3A1262099097806FE9B9A0FBA7B16A0343F3E76E69AE9D91F68963C4B48F9C7BAC411600CE4DBF87B295DE39BD819DC632FA45E3943810CC231A4B285101797F2B6D4F08CCB33DAA67EB92D632EAE427C63426664226DED96652D32C9B18C25C421DB3B0984AEBD8289E248DEDC4903297DF22783366DE4B71CEC53C308E394225042017B7F92688204ED6BC8B0C5F34011AE3335079EEA47F617563498BE1205166BD3A1C7BD8110D9E6503A0DC72FD550DE1ACF401DCFA212DDB3790BC61F04E4DF9FA0112D977779F6DEA4333A19749E17BB70EC8A7A18EF4373EF131D89B3F77182FDA0C9F98B7A614967A0708938F2288FEAFD89D19A1F542606874F2EBA5A0B7582B5506EC9D907B50DCBE0EDF55F32A22AC3A62DC906976ED327D530C67103B5AAE417A1D9DBD4538772DAEC64891B90E913BBA087F7B1CFB8DAB9A0CB95A19BAD82AE6C34102CFB34F783DCB78308509325FCAD64D301B59A50F7EB1337B279FD39FBF2062A314D56B1AC8D809997DBC094201A0BA7E46D2C79EFEF3B2F738C534083EDD16C41D2D0FEC673C1F15E9C3F996E830EC248F9F27049CB276C59920BF690CAA54A8CA5D012A004E1AA12EE181B9DF54A2688AEB38A7194B64C4BE3ADF2392B7AB5FC3DE1A29576DC9C70060BBB633D4AF5E890C6C6F7567C6CB17CFE14F75D8EAF1A303393B68520D88705B6797A78E991D01735C715D5B93F5231D04B662CD949677385415E210FAE274F454CDEC9081222CEF1DEFB7818FFD1640D55CFAB872718786F26FDE1D00FF1192060E5D67769246693EAF49D88F75A9910A83888B40CA630FB3AF98D1C1C268DD5E16F7B8E501BFB2FAB98129E09439EB3FE7A6356C1C1C3019568A0DD341125536D8006A23003F1557FA1CBEDE1A78C046BB91B00E3F350019B7995864734C0DBDECA44DE7AFC847102E270D880B6EA6D01E5903228E7C7CE66CA0E1D94B6CCCAB8DC3C90CA168AB8A131CD9160B515382F9A667B54365CEFD27006F0EDB52B8DFC61237CEC28E31E3E8AA8E2A1882C13D3910EF0FE61511FF5D230EFF4BB990ED7F471CB5351E88D780D74686097C1C32EB8E918FB07242AAFBD52F3C584A7F669FBB6D71E01AE12D5F21824BB5FD1E4812D7CB93519F62FB9BB3D7DC2EED33BC85107EDB0618FB01BC38FF89F3DE70D39A602B2B21413BBB55F1541EB9D4B6A997E10EFF77C759E5565353DFBAEDC2942053AB72C64C9BCDF22CC3F99D5130FB4B55EADA0FE8B69368AF8D83282F3BD2A9686B18D0682184B48EE0A0A76B1464A31B37ACF8DDE3A295A3AB293907FB4DD5A6703C765926E23FC58BEDD769D427C1B73E0A6E5D9F21A5DF54292187B9D32A2EAD8B9F91540EFB7E98A390F76C1EF40E9FDF9253193D5318E1092D104A7312CCAD9E2FD5C9C5214EA4626D429C389DFC931333181B931E5EA723E34034A0282174FF89130533C1E6284A99F6A01E376CBB79A136CBAE3BCBA43FDF94616AC206A4DEB4EDE69A2C126854CF9A7DD351C5290951893CE6BDDD3A97FAA51F0807693FFAA6AB7C7A1AF39883D78B8600651D2709F9C01C73D62750D7D8729FC5B410FECFA3147CD06E8A8E453929E22A1B4E6C3B5909BDB605D1B52A107812F37B0AD7F875162C403600F19F6C9181977D2E1670E7364B8184C5C61508F5C6903925BFFE36B605300584E251383C859A72908260CA1A78F611364A80FAD6387AA3B71ECFE175A2BB9EB8C4C801EEA2A82D90F4A5483E0ABE46F541042DCD4157E94E2865993B9FC45F257CFFBCFA6228FEE327463ADAB4299143E6B175065CB93CBC21B2BA4EFE06DCBA5477D4DE623B221B435ED0D5100526393E0CD1D1C6B200277CE8F7F020F79E5119F85643D4089217DB311D76ED9BB3576B6AC21F118AF5C9C5BDEB9487014B5FCEF89A14B5F85C3E9416A5D333E7A501199C55F388B157BB89ADDA91A5BC39D212B3526AF5C5E7115C2419D6A92DB81B5C8811B16FBB66FF09F52879B4F96AA412D768A53FC11D9651844F5E7CE16BEF00DA7C2D8A1EC61FA3DAFFEED9B4D0EC314CACE4F38CA12911E9C71F63F4ECB877BED1B95DDC57872EA136D786414038834D9D00929F9C40F0E74273E2FD55D331F1B61370D8A0EF0DD212525158FCD4E0B7E6D8C3F1B367CD6395337C751D35E8D528908D7F92CB7BAF384577E9902EBA8B2D1C50C440DC18135E6CEAF16093E810725437C8C118C2EA9D09BED3F71A38C95F7BAA0822B25F662D0709783ED0E725BDB9CCF936BF66C4A660EE6EF5F9C1A0E0227582A1A304070B286806BA772C8F1FCE8EC5EB7A8735E8D15B8261D8852EC913816CFD739475D1412FEF0E5A85756385A9626FEE1F4927AA227AC930DB6ADE1DA75B6752C1191ED766FE9CEE652C0D34F96A5CD596B96DA30A841177307D32CF375066C0F56478A3CD87653D13C010793F6912ABBA2C2BD53C547FB5992EA521F4C59DFE955545AEC832833E6A4B51F745B1D6677947BB6492E991A2BA411D74A5E67FAAC65D8E9F451374987D21F17FE15F99856173760EC4692D52BB1BD51FBEB29302BC09009279272BEC9141AA2444AD020FFA416FA35943C423C00261D54770074F78DFD640CADE82F9E7280B9C4EC3F8BCBC63A2286B5EDE8E21A06B1C251B525D1F41FEBC0DCE86225B0EDD6DE59D768DF541127649759DE213D1A84DD0B03EEC32006758B069C1E0A21121A15C706263FB3E53D6F37D04C77E35C9FD70541B2D5AD0DCC826C143FCD1076319108007A9DAB1D6BE5E0ECD59D609058132 +valid = true +smlen = 3341 +sm = 76432E6AB59EAC46A20DCA4E4E47E611229522C99E1CE6FC194463AE709D93AB730C8140EF2672FA15C236DA36C2C60E0464C076BBFF7AE1AE2D720AD13905F269286EC74E8267DCD7A88FF4F04C3AE636481A55C781839EA1AC36062F031D137165E996FF75D4C065A98BB8EB707BD84545CEEBE4DA24D8A2EFE41662335A474531FFB8C14238DF52B18557836A0EAB930EF7DF9E64EF74BD9648BC42416BA401A521518D564C52AF2D92CD0048D2228FF9157405F3D163F951A63E51525378C55A23AF9F2CB52609EA6FB83DE7538A40CC14374CE9CCCBE760DE69CE8F9D86F83B74DADF11B521210E13DD5AA12CD85B1D77E7EF38B25151C2D8009EFD358278FE5C71AD2F2CFD8AD6A6EBF03E43A03897C269F229193E5C36E3B897326F9009F72B0DA4C727C8E3503195BD1C82E783A19B0F81143BE7BAF57D92D290332CBA51E4B3A4AF66440D1D6939B02C3903667A7E0A2FB50BBE23164A31C3AD4B4C9F2402AEB00D60D16FF32D57667B3FB681205A422576F01D75D5218B560222296247647D060366C68417F2C388A8B004102DFF8D13AE83FD34B1ECDD81C2F5AD807A3492D75B397AF2E081DFCBBC3E8C8EFF3BE20DD7F482D2CC52492F8E7083C132A5C0FD4D4635362EF960E48D6E35EFA51076B6EA32DD63179800F505E8E47099A3B861E537333950434273BD8383D0164A2C4AAA911E7E8CD0351D2E6BE1E2980387B67081BFFDB76ED80AE821E05454ABDB12758B3DE37BAFA765EE5AB16648F4DA5C2CB7A489212A743D37BAFA06F58ED6A6BC6F20E6B0E8A1FA9AD07AA56548F93E23858619E67C83BF4DCA2EC6516EEC1C9E115AA34220C59255B3AE1D5B4F8E091C17FA55275FBC8230D217330B67473738B3362DE17BAEB131F7D4A9832443AEA256B4A5E3889830ABFB4F324E22698E827733AEEB16E34A33B0023B9551E3B81DD78BCCBD2468A13CAD54918D10EA69029C9FFD797E968253229D6EB410FF827A9D2CD6BF152E5EACFEBA68E1D778B1E89F6B71FD040AC712F36C13D70969D025FAAB59338983EDB26116D0561E066BDF5C7AAF24EAB47A68D15EC19ED074F3D4E9026DCC8E33DC6D46010955E9BE675F2B863AF88ECF29E4C7AD7FF639E04DA36EA15E8FDAABACB4F69967C12C36B33AEFCE2D9F3608531545D210BBBAB46EA27DBB3A9E80CC844A18B1D1D9AC101EC131DC54143DC081B988A482BB46A84FBDD791E742E4B38088E8538AB8F2544D8F9A5F4F9C0EB83D37F856C4CBE64688447C7F052EE375B3EDFAB105A464D937923166833F3EEBD302E30FD472343E75B661389A049E497DF2D7150B9681DDD66D87A276A1A43A18EDB7EA77D2F2EB23A722A4FAE1A68FA2363F29B2D67381E7B70D359DC86A06EF2BD9FD0E791440906062E9AD715EE41ABEE8262EAB49C3B7F9B11826684F735BDDB21C3DCB681B12223AB13D38CB230E0CCEB4D23E6AF1FB184270E90AA00B311F8C2452688B8734C8D62C22AE08D8592479E8EAFF64B2AF23FD68F88576A66BE58E085BBB85B022A5C6F460444C0287E7D25F4480C429EE9E5AA5D455743B38F91CA4445196672E360DC894571F978D29F72B3634682A5263B13FC4CEB9A1BCD71520973F8DF457D61ABF1FAEC612AD6C86305B65D9CBB7BCE5035B8F644B716313F684EDDC6909893DC958813E6E3341DDA8A332C364A97BCC9B6472E6B9CC570716ECB625F4E8994DA9B1F6DEE8561CA4D2F6C691703022EAE2235DAD9D5C5CEDEA751974E8D602841E71AD1DF6ABC92F4F0337BF7237A65A17E010162C46DEADE485A04F46214FE7BEF32DB3C311661E43C0C2E9EDD963908A1F8C1F6DCDFA45CC100DA0DBB89B30D70E801D0688F377F6E908829DEFB4A17D78717EAF2E2D5744F11586BDE49FB4C8EE40F36611DA3C97BBC5CB69A3C94671122BA097BB01572CB883A6F9180C3977875A1A5581DBFC57851A5ECE82E40E297679433D2A7CF18BAB87D7F05E04C832299FD2A650BCC6BFE288DB08D12653CADF12F768EF212C63C95714A4641A12962CCA3CAD694032D531307715F64AC64D259F835E316688965529E513E56677FC4855B8C4C9542795204A08C58DD0CD741655446865CC14A7181DFCA296E47096729665A2CC9B340A26EAE144197BB69B43E3C062E5408B8A15C6C7ED9E08A9D5A58B6A1CBDF8F7888AFD4DDB9110848EAE2A741D0BC3D745DF8787FAE2521124F3211C34B8EBBA39F2034A9E1341DB3C49FBEABACF949D3BBE4A89AE66B2CBF10F883FCF5783E419D947CFCEB12D33619DB27A970FFA82D368163A8D9DB2A9C40F38DD69AE09D21E842794349040A6471D884D524EB009C6E182C36449F7B609B543551F6C3196F1F7CD4F311C277B5C6A1A99979607B246E0937D066DC6014EAE9CC6232EAC1426E954F70E881869E80D435BCFEE437405FB528E179A68E28336085C9CADED83B771A39BE93E660B4EF5066FF8A5EA8DF0C2FCE41A2FBD7A9EA0ABFFD5A3832F1BA3CB114F975630DE4B8583275F48FE7EE4EC19E84B23FC41FB4542AE0D569F417044216A61A3F7A5F7E340A028D7A035743CF71F7074A1A4B51DA6748FC290F29BD42969DCAB0282B6AB6711539C2D55B93A575AB062CFEF43027C82DD57866A0133DB184849C480BF014470BB72DF543BEDD1E5F80573929A7F101C1065090FDE89EA5CB81C0CC2937493CB0028C4C57D74E141DE27662DC744E15F6EC98796F01EEC26209945533D789CEE8F1126AA430AFED7156DDCD0501C632B1F83837D157C3EEFBC55A64D1E0BA4EEBF25F157AD169A438D979F5D81C7C37F1312ACBFFFBCC267C084E098737E172026B4BFBB53D7C5F515B3D7005A120FBA41EEC124F22394EE0C735651E4EC5749A16847DE77312B07399BCFF4B3D1C5732AD0E9B88AE5BDEC072EF63B0E2EFB30309DF310171E24A8242309100A173E62C53ACB781F87831AC589DE9E07CB461C5F455DEDEB8084C39739DD33BF34CE6E0AD134B53351E9F14E3343EB1D7925EE463ED8D66AB2E45B7BFD6429B4A2CCFC868F78B603F4413E2EC432B299CBA4B1F017704A41AC31F7027B0628A3C9C7DC43146690DA24D7C51218F10F72465C176F84EEE1F0364163A31EB761E33273EC07C806DE809656AE57F86EDE4B82845C3ED6AD075478EC179B3738A329D9627410127BF5CF193BE7E021131518534B2813DD25CC7784B3A203139BA232C9EFC1DD538563C970F2DC6141CFFFC1E880CBF3BBF81B21B948F160A40CFCC83F71F652DF1BF23E14943ED3346DC97441730E162BA39F3BAA187206E22A7888CC5315EBC08D08B188CDCB76CDC24CAD462303A0B0AD1CFFA6ABD013B1FCE7FD78A6272B3A8E79EB0D171B4B48D63722C7524D0A367D60793259B53FF34EF2F295EF1728C57B1DADABD44272C94DA9E2F8DDC8EDB6A8148BC5A5BD4252CCE3742C8D635D4A590682D7EB92D52836D55D8B5B985A7E0E9F941598436F8470B39E84795853A3DACCF65B1ECA82C8EB92FF5035932E4BE8D34B1A441C47FC0FA515A3AE9DF6782A041C751AF1E825CC1551EAE4B98BDF47293A485F7DFE59EB639D23B5D0DEB0E19CF832A0A7659CEC0FD7AD6DAD928D762E2F5AB572AF3F67EF51667F8503DC1FD8D73C70CEB08FA184EB7601242BE1A7BD7813276F9B4E5F7A3180F6A773F1ECBC48BC4D917F417734601C05C9130C4169BB8E7EBAC241F359BB63104DC97E2F4D11A1666E5BD6FE1C267EDDE2E1B4DE17A5123DEFDA1DC62231B7EF65352D8B319B9CF1277CC46B20064232AB378FF3D908446A61AD6223D9CBA2D1C770EA8A8580725E6E945A04365729DA77F39397A398725985388AD6BBBBFE28CB756AAA8AFCEF1CBA634876187B497671A8F79180E37EC94751887C33814B33217FFD1A84D19E05314DAA554581CA88260CF23278C0C1459B3D5308159A5349679959E06CBE727D26B399A37247BC6BA526531D10853C62703EDB910CD4F1CA64BF7842A907AA1A00B3C78EA696A342D70019C6A32B81A278E6296DA3F7111E5ABC1E982DE9CAAFD5CB65E690DC33E1EDA512C29824ED0F085CC7F8CBDC012E5D9E7988A281ED3F8BF87C8CDD643E6B5E1F766983417B38B9B421A7C7193B9F5FF4FF54D71818CDB1A5407BE5244B7E90CFC9E95262873DC6E8F69DD05FA0C61DA32940B06A6999284A1348C8E54BD7A87A4D318E42E2B38F89A5F9BFCDE2185C438BBCBA42115CB986E2066CBC68B901FBE8E1CFB2E96B3DF0563A1B121E8B1BDAE6F49333ED55CEAD1A27C23C23382EA0FE81856599DF39265BD68284E402E3C3CEF38B50C7580F1DCE8EEB8B93E9E41AE8C23DFAE117973C39F45EC30674485445C232B13ACB7960016503C5D28F338CBB5F167988EB2F0BC8228F607D9130A5B8A4AF4114E203894BF0A522054BC8E3E40E4898E8AEF82598C49227B6B992988450AA6BD7A72FAD964F27D1C75009C6F8B1B1AB09BD03CA83AFC0D63ED18CE114692EC801839DE1D60BBE145DEE09EB4A452744F9AEE34DD7431B9692A8F1FFC57CFB9ED48000194931ADCBC974E01F685F78523C7B1AA7F3BF990EC83226B3C8A62B182037476B77A5ECFA1F293591A1C2FE01424855BCD0EEF3F70B0D24468E95A4CAD00889969FEE2433445889AAD300000000000000000009101922272EDB00000000000000000000000000000000000000000000000000000000000000 + +description = rej_ntt_poly (sample_uniform) requires 5 SHAKE blocks +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = D83F3FE5BFD9895F3FCA5D0B6AC999618C311772D3A9DD13D5F1DCEAE0F8DFC7D86C63CA8CF54C480EDD1537E2482258FDACB27328F58BD2CD8055EA13BE3BAD08AE1092DE5D43108EF9642495C5A1463317CB454B80EF2FD81072D92F9E93D0E1E248D4C3814AC62669EDE39F05F36164FD1610A6D26A9C187A12B8AEE8DC0905621382285870471134125485250844255442123244784880547268512633727337770546561634253401607317387373742276857434176786134680186282884138162341105032436114487587361614825265003743542077044014637717428071888830204235344735508768473564714131046021657546183437443841062682803813641721071641738886054301466850256112063147100271616112814876368374624345134475841516088333868260155187475272062267325526227164340561274317808608624583371163012362731844370315218218703456715385734028664401747415606705217177385721370841154338772368705305700366467755113257144784814107026041348176141846745605700208022665246682525357374470882022853834707235706003418167606203413810262242710038838515881260083746451866384576425368001252282184658214332207073243133063206883185703636721603305267885742482436774833663108244410401254378680257606056281870032600013063722605263501436121438003306361400508175316861102253221683218426130107101450502624712016188178186885835618468151764383132002037426788822462646334456356104540230845360853145887824037071870705675517356836081240754656548301034233465413055705723647885442818784714123443476032275268274876620684731506332320184028454826018261270602471163214452745182584768011750066462420700408022112167677443276264156261662023583717551060603843481054118602503815716171554167363010661616165167307551743386401312023444051676765067364257247535444588130760686223782827331225678674532658123324441733000440127534267225820268711001483113416170508235700844388865058645541582400322402110133286110841735642872267677424708812784620218651436842641625586204716611776715541243122626300857516266566575406181600656633746426427040605248250814184223183868381603572064646067671475635152314438574544776205366182711080774078413276800342258617867501040788344271327372368886311210384160413345532177278017235752255086055667483067020882626877754538633433610233037006837832875054285273046050270417512484138780231500015818806027560653625865250433881547683047881880107842300167356087786388071382464445747866870200455708020147304005565832022870614374417263724112308765014277366533272036781370007584236072114552752755743576678045868207804821738217614116160722788741078526756837256317877724156821547533556363455742148231173145636847706163820163557457033127117182584521450602880243106888286010613575007157860517226586582705687428708665653823450014840785434500752408618777432238387857187502588473051573712674068323728600406155714330434483248332330035516883840215848020046204481537332073007356386635524346023801146656667768025831438633264340053115116313045485428633701788422713850435022406083313738304232273718188161503856155348228057625214887361652151217027260546461061712338632841330437535648850681540536383778545061224304564384802318180034548402028602350344712554244542231280227008737078052016877458367121011466105126076452407543240056255056BD4136C3776FCC902BB88A602A6C3AC24950586A22102399A7C56CA5E061112887A23B60AE33131E73A72B4D26E3779F7440C1E053E024C0C8E250A481B252197389BCD4EC35972134E4BA9141440D07C835FF488A883E66CD2774B90033802460569D0988B231CC18C6831726FC8E1375CC220A7EE37E22945A237494389F40E1C618466E79AEF7FFB059066031ED6B7E30114127B843A6FCEC5876074D1D70E44048F29AF7E070E5CD50FABC06FAFAC325D072BD20A56A2FB087D126BA3132B06417DDF9BBFE24E2244751FF244DDEB9CAD99E5E22EA438C0AF0AE2F90F9B395C9D8BEC9190455AD64A536FE932F98EEF9562E72230F7CF3A6BEAFCD90D47FE71D7FC5FABFBB240E32D2C4B00FF6280B5838DE87CF1983F05327941A768632576061B012A0C54CCC3E75ECF9B8012807A74AC0033E50065E02D8C9F5F4899DCCFDBEE9FBF5DA27F96DA155C8DD4E8F82B6D8B0888D6001E1423E6354C828BB2D1471FD0D303A440B6625F660FA86796FBB76A8DB811A82ACB597E021D6EEDDF3A5ABA50481B54D02506C86E452F0D1E761E2269C39961F5D8FB3395E7920479013AD76D755549A28474A5DD3193F10EA67B2111F81DC797CE4CFE2137A0BD46B0755236577B793BD85E70DB87733E70026C8CFAD9C44EE49E0FE6169BA3AA1C6A537BDDA3AC68426634FD54B06E644024351BB34DD6E6C45ACE2EC75F8A0BF9B7D1E6D6D188B5F1219D0C53AD2CFEE59B74B57EA4F76E26C519B94D7A7D252D22F92AABDD0762481192BD75A7FF374EAE81FA9A32AA173BBB50B6389C24AF000C1D148452B17F79A54FE34B6A1D610B7FEAE05BCC550CA49C7E490A51486A3D0F54150B5FF9F0D410B800B5D5DA757A86350DE63B9BFF23C4B63AEFD63126FC05B1AF10EA098E380D5F3E42326EAF7EED02EF3AD26A8148B632E5859A0D3C3574DF1C8C689F9977BF6D54AF7D548290CDB4A11B25E902FB7FA1D2545DC2B884675C0E62F3F777BF021A36737DA086A92D5E7E2931A41657A461221034261E3AA80D223A43854257D871BE334B668C5D29A3F72B9322D4295D5E30B59BC8DF6011BF4C660A06AD6E84B1523097A147EDC22E5577767B4C468717141193B2A0AD609ABDC84924D556B6CB69756B571825B490EB70E7B605A900D48BCCACC01E7BA9A593C4C6517E1614A971D64F155D22EE51BFF473E33772EAA85928C8D234003ECB833ED82309E854489C22A176ED157EF93A0802660C873B36F2D56EF76E015608D1C2FD778CE9DA2D3A8C677D508416CF03249AD45743BF246C03CF26EB5524620CE3D452D7BC01C9BD01E15C926A2872B61EAAD907A2970BEC14A003BDFE6C5F5F206F2AA06C0C9FEFEB516C0913B22328C266F80988F8315C0C371E199A43428A281517B7070BD4134B3EC9F7A3E944CFE6FA7ED219BFC942290B428E5DBB3502C9B3BD161AAC14E200897DE8DD6E83751B951D9BA1727E4E8CF83A73B05DCBBB0DCC9C968E157BA940810226D9E9A55351FC089925DF790983FC215F570D5E5C9F46DD2D76AC4F2C3E35A686320FF863ECE3D6FE027D184D180C3CFF1CFE70895E3649C5644A16E4A7DA3F2DBCDB0C89802A72799D2F62DDE05F4ABD93000911A1606673CD57C016AF4C58D9EE0EE596770DC23633B73D7DCC44D7AE9752AEF7C3589C4EE6565A2F911286845BE1DBAD3309E84896D8444A41CEBFA57CA89085107B227F10C161FA3F6C6A809B4ACE3243A4FCCB1F24637D9D80ED201BC7F56CBB78078820A958E580B31A29A59AABD1A7B01A90C7287A66E5FCC367488DE7EE06ED2176DA817510A16568B3F5146AEA6ECEBD11E73CE48AE783765946367997E5F2EC3B619C99CA7E44BF1CBB35F400F891ECD0BD4D57F67F46A767D74FC3C615B85830611BDED11D8FD0951698F9E14C7D01408AF2735291BBE2CB2D6E189A4BA273A2867E00F9DC47DE76CE306D08D702E09A61C022230862F38E9D434E1F652FA8644E523B704C4A4D224DF227AF52508AC86F2C9ACB2CD8B73632026D8A235D448E0E58BCC1012BFA8C3FAE888FEE75F7575C82E2119B2A1A03090B234C7BC3ED51E83B7EFAA1E8061D38110145A2447EFB04C56FFD6405CE3A6831CD23BCC67E3A8BD01230C3F21056296364CD5F89DB3B7C906F069A1D7AE5DFC347FF602BDE1DBACF0976E18D256F7CCBC7BB7E3081EAD70095BBB0F69593D845EAA64A751BDD42F8D82CDA14EDC7C533626F49803C702E13FFC39683944A673F2C3B27A715EF92708A63A573522F8B6F5A1B048F3868967B38AB48DE71F10006115B5444F26FC22E401DC4DC51D3EBC4A26DD9753BF74A7B1353DD295C77D11B8E402F72E1209F1E62DC654183F8F7E473D8E42712C108EBBA819FD58703A2DED0EFA29F8E7C35FAB62180E09B3F32AE23D7EE757AF0FEF6D46CA0FE87AE88F064F074E860216C038AB79E7342D95F222290D5BF75466FD88C00C41DB0CFF0702DAF4E4657736ED1FED2CD3736B1CAE65A62B649AB0CDE2B67E16E20AC8A8F494DC81995163D1963089CD0DFFFB52DF2E897D47F4394485801423BC01FD4A3F8C476425C72576EF3CB21B313D104457FB455652BAA5FBED435B223F68D591A662674C443186B26CDDCD4088CD9CAB68FF8AE68F5DA1C1B6DB149B325D01678E1F5F4ECD1967CEF392197C1774BFD1853C1BD6C08E03DD9D47143C694C4AF7D67C5F0A400EAC989A9F05FA27C024661120847E7DB8160A20B32E9F254BC99DF8C4C65E9D76A88CE3B2FEDC463645DD6AD44D80D5075F29358EADB1FA2018D4129ED7A7FE1EE6DB69FEA19804EA11E9B410A42C01E89F1D7343F021AA15C1C4F8AD04C56189BF336AACB4629EDE86B3F4BCA1EED91C26D50AAE129F6DA7E9CFA1B477B2023A4D5B05E9898F69DDF43209A50E8352C4A40A5482B642E9639566F3EB7DA60E5C4AE6E73D9B84C1795D6DB56DA68AAC9FA54F5A52DA7ABBF3AB2BD59FFB4C9BD6A2B8F42F75B21527BA77D3F8B285E624900827B4716B5DF3361CD65BEA88F5922E9791FE91C7A2F579BE1AA4E3E1A500EBA20C203F734FEE8A0707E28B058B707A1C4081E71CA09E3AA0F3A277296798FB3F40B7B8629F77FC18CA9721EB1EA8D5E1D4E647FACCF666A501540E9E255CCE8AAE3F6D450FDAF18FFC23467B7A628BDE5FDC566088FF2A730772AD2ED93A1852C3B1039AD47AF727FF762995B53FCC65D00A8191E44A1641B8CC830FA66146FF710EA12F036146DC87C71BA1518ED51C10EC882514043936C93A0CD483FCBAA5B697733A21000FD0D9B1F40FD1D103160FF9207F9FC4C7F6E30B9CF56F37EABA63735F91E0686C95EF2CEE963D4585381B93E069CB3B9F59CFEA501744885969F02ADC0B997F014A4A28A586F158145DDF0158DB06103652D37000C4C4FE692435915A9042B81D7C519BC59A1EABEAADA5618BBC8F21700C00EB8C28A32A7AFD6D9515F9E711DCC346D65509690C10F0F40623770834CE30F17A9A464543488571DB36C92CE732F2 +valid = true +smlen = 3320 +sm = 16B336256C51560D99C97D15FF467360F5F563FB555932F56351ACD1E53906F1C05C87F8544A821BCB05D0E3952A84C4D9DE460BECDC5EF5138C9729E905A3FD4117D32CB0957C5BAD8E84ED7C4170BE74D63E9B8D813C4EF7F534C5605A5E4F6BA4E06F6D800AF82809016EAE3E6FD4BEEF0F045304A4C17222BE7F8C5E71A294ED8485C956865896457119A39BA4ABC44BDB4D019493147D0B5E619BFE0A5F4ED1938E48E71B88EC8FBF267D1EA5DC8F63C67D98A1EBE9FE4757195C04A8202CF012133181892A4221CDAF79BCF240D005E80E8C68DA8F0FDFAF8754F21EBC42D2A5900CFF1CED847EE80E875C27100BF230F613B0758C3E4CCAE5064111E71F0C13447A25FFCA32669E53CCFA855B997236887F6AEFA3BAA2FE264686B879D1389D72C5967030D99915A9915182F97AC2375C93E5DAFAE6575DDDC16908BD2BC865891D85E70FA998BDAA18246F73DB0D69CA58BA813E33C90A3E6B2A2C2F8C97166C9B474C60FAB1F3C7841B96C2AF1349A37C443FD86291FACB657A049E175A69443BB3662E252213A868E8241188D8941FD524EF6017633D2E3B47C9A1AC1BCB119722F54C514E62DE40B5F2DB38A1281E220A14E31E46442D31C71489DF94F02811E53806C5EF65377433222B8510FB7E4F53AD31CBA34456779563028DD1FE7EF3752F0121EFBBCD28DCF09F045CACFFA2F09F343CD4184820DFCFA3E0746AA7CA2DEFD2BC165DEA6E3A07AF3B4A8E9BA1C18C32B44EC37069D65013AA2A88AFA691DAD1A07EA87FDF8C7B187FE9572EAE4F296BAC40F3F729EC4C9EA4378AAA60B70F4FEBC3FF3A7561E2E22A7B8A23770AF7BCA50540236419762F1F42D9CBA0B1285E83809EA02C4F0F9AF086D506967168653B1A54754B629D769479EEEF76EB8171B127B724040F0E7BB815577A4998FF01662D2968DDEE9CAAD22212C3196F60D9212B5E1FD92F0367D5780D3C42C92332E305B6E15BDB3EED70643A26892BA2BA9C6E575A77EA82EEF3F425DFB971C7F6E74520889A1869CFE4DDDF2819445E8BAF658668A9E0D3C65F263C208C4442D38E644F8CA193C5F463C4DCC2217DC337D37A0FFB61688A2C67A2223E41D24D07CA4984C35C5B33CF142F443E9A0EE0F631173399D714D41131E84F9B0C9BE290DAC2CE4716843CBCCDD3851CDE789E8D03A7133F08B6234DD78F63E17D29A7B93E992EC7C80D6BEF2E7EFACEACEA917FFE1B23B8A37F438CF97C42551CA8E37B1831EEFD5F4FA495D934AD6B7DC249BE12BAF8010F55552C87E04C79762E717A8647C427E9A9D41200438187475B8C51A990B1D268FBD1CB741059622BBE0B74D1C40C539D1719232A31023E7A0AF41034A64F65F96347F7BD9B1501812FB48BC771B72DD3487485765BF4A769B8CEDB355F425F49FB27DA1375B5183196ACA9009E4E638A0C5A07E424D2A9A6D828706DE3E36D5C579704E30D3980511C3F95786FD6CDDE178BD9B246929BAB9BB6E55176F83A25252D4DC97E70239A24EDE49A93CBBA3EF31A637DE8F254AB965C6D8824B31F28A9FC4C32BECCDE5299ECF43F488E9B8E037B848491DB03F6DEDA7BE882A5669DCD87B26D57856EA3F2D3BED6D5394B7A06C498FE8568F62ACBF63197D21D1059B55516D08496608CCD6B0CAC9A49B2A9B9B7436C1BD7F0673C2D66EA6CC6D20BDD975CAD6D32C11436333454C7CBC67A9EFF002B29F3B5AC34255FE7351888A5872862CC7F745AB7116BCDAB0D76BCD187D4318B65EE3044D3E342B88BF231838B93B3328DC787B3340FFF90931C392A1283F897F9A9091DF52B7CD2AE885118D4FAD2D595A76555071DA39436675AD6C083E9160B3A964A6B020F65AEE5A2CB3BE2453C0157904E7283802F243C5CB40943ED48A91B48FED455648C576EF7AD7FF6DF274723899B2977E13BF8E803FAECF2EA7FB78F63A78975512C962E375BD6AA37BD0132B0A9232E35743620D1785A55BDF36620888B2A578141E29E197735BF388491FC40DA63F423CCDF76E2947B53D975975840257FF2CB2B5075803305954941F49C7DAC218E081FE269DC2A5506F4CC2A751BBA6070D9EE0F8A801A90895AD3C1EB756475BCC3C6E0DF907C49B4A3494DBB7066744EF693A5EAB0EDFD00BF41B90002713F08B35CEAE0B19338D604DD47E55527FDD815408A20C575AC6388240E0F9B3FDD66C9E100E512FF6F73E1285C4DDA646F6E667C1E358F166DE2688E64E38FE47F0D44410A5CD284ADADDC6B444A08BB44A3FA3DFDDAB4245D99AE058F019362EB5E89F56B41DB5D885F038A31539545863809D094CD15FD23B77BB5C652D54ED422790532FAD71FF5AFD2EC1BE5F0BB1456F09FD9B37D9DA01FB9C103DBB277AED288EB4B5B28A2820EC7B717CEBC4D9F0EEBE5FFBFCBF722B0FAC299C4EC37C03EB1A066147A18AA47752F21877111F5DA3EA36B8D4A11D06126E90E59535B3A760D882BD694E5CF9E0DCA9B73AB6984F50472782F9B105BB3A7FA7AA7B697F831D3A9A94ABCEF8F7B6295EE73A873D67A930B4B830D770AF621E2DB52C5AC7DD221C8CE33C2F2D5147AE5EF89EE1F370A90DF218F69D3937ED20F2AC484D79CB5FB22C5C1BD477FB005A05414865AD6430233997053F1C4AAF7182AF075D196058C97F871CF7951585F90360504841AEBF6DA4BA1E721AA97F681989704F04E13B1843FA2678254C536844A0CAC2391D229F2C1382819F4E15CEF9655C1C667F45449CC7D3BDBA48C86E112E9BE49C2CF45B65934304883EED0C97A0ED53E660D7019DCFD94773D4209058D8E131B0E8DD0DF041A5AF4DCB7FFA810757EA253204510C69D08D4FD77FCD971D4D9C5E0FEB00B8672F525C13DCAD6734B40B98893A74836DBDDFD401C9BFE873DA4D1ACF4EB1028CBED94D48079B46643652AF0A877091D28CDE82585602B6003B47F19671D42BE1660F0CFAA289268CF1300C2273038831C57BCBAA2C88934484565CD2952AFB8214F76BC911D0C942D4B260293630BE3C0C44358D16AFC38BBCEA3AD073179487BB17D0AF4EE8884F30BF7AC5F7A8B469B7A82FD83C68A5531D2987338B2D760DC6718997DFB433CCBEECAD89EF7B79690CDFF544E93572468E0B044221304077C8D506DCED5FD7A3AB0449771ED71CD5790DFC43B1BBBF22A519583BCBF5B4E836D6A59870D25ABBE4BF8AE2A7723BBB98E3C763A9DFF1809D0AF5EA183EB1C983F06FC95735A64390876394ED3A98CA2DC5D4D6BC4F5004C7A4BACEAD5DAE0ADF46139FCC77E7C3D74B000E08BA87AF82F1669A8CC41855430E1C3A1B42ED1790D127D0861058BDD401F59BD80836E81CB019A923BB4DBEAE1CE5D8C9BDDA06CA80A407CF057448618332C75F2E61050C4D9E20B34EF1BB5D00008D152D77F220AE4ED705973E704A20C170BD9CC1F00D2C7B09A6B00A010BC987E0743E2F3005C7A802B73F76D1831E0FDC39D7F5B881B551116BED6FA9B7878D1E34CD9BCEF3E7F75C448EAEF8520EE560846636009AA7C6352D3C9BF4471DA268E00C9BD08D620A172E96CDF2D286D0433DB1E00FCA409DF3355ED471053A4B061E07D7CEBD0967C2840E3EE35AE99948F4AB0FC4875E8FDB847F6447E429D1261A961D0F54A6466BD1751313EEDA7C7F1EB197C31E3EA96D207DCB30AFA834A7923E9D482B7DA24B2FAD6F64908301335FEB45F68B4257E08AB4B51297842661818EB1532DBD1FA152177118A119EBB89FF9693506C7EA51392A009745CBC5BEB359BF6067958EC19A59F1CCF114DD379DC363663E284B182C7BEFFA1270330C009377C764D4C72A6A8C739430FAA1AD5E6315C61BDFD1FD573AFAAFF096BAC889C8195C07FD7F9203142C2BBF76764F948B92D8AB2B8E876A071F9C7626CD1F8F88885AA5F1BD2CD06161FEAE0949F7F45F6E1124FEB6211AE8CA38A0B2F5810EDB79DBB9F3EDA2242E61CAD3F75D8E030DE89042D8041A2F6D4260D2EFFC31818D0BD34F57BAD846B70D61B85EAE3DBEEEC6E7A1EA64E7BD691C4FD07AF4292DDA572B7D8D13E0FEDE3E3563CD86EF4C823B1CF96B639C13A988A6EF4389813296FB9D37070B5C17B4374681B8D46FC9BA4F53C63DECB76EB907CB49A23F43FB788E22086EE2C269E25A0C45B5FEBC15D1F02198BA7E8D4DE8134AF6C10591A28EAEF7F39F9B54D845107589F15087AEB2ACA0C84E475497D25BAE0353CF2D036CBA5FC06A7A0B19DBAC1AA464880DDA5584EEE02F306EB486FCEE0D3B58BCC5555E8FED38C7BEC8779CA1B47EC5B9F1BA01DD18A0C3A90FF771EDE19F6B107F8DBFBB3AF3904E4F45389B002DE434E29425FA9473F751DA9E0A44E8ECC3B09127E011A343D2022B18B953DCA32938FB2D94D2FAD4295C1AC9BCAB0AD6941C950DD14FF5973239C7853DD5E80FB1DB007A923AD0CBD26973C9885DB7FFFDD09DD896EB6E83CCBA97A2AB7018A6339EC33E7AEB84D0F3323509E81AD2ED32E9F749011FEF2F9FE7281C5E204E6A9E3107F9901B0E3A7A55A3CA54714C53CE2BC79C4AE2652D3D5B701C31EA92513C102A4077ED8F76708758B24F3083D620F2EAD66EA3CE3D8341A0D4D8C99AAB5D1265770A7ADB8CF1C226A7D979899304B5F92999AB6B9BFCA1460A2A3B4B6B8C92E459597B8D1D300000000000000000000060D141E262D48656C6C6F20776F726C64 + +description = expand_a requires 150 SHAKE blocks +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = D83F3FE5BFD9895F3FCA5D0B6AC999618C311772D3A9DD13D5F1DCEAE0F8DFC7D86C63CA8CF54C480EDD1537E2482258FDACB27328F58BD2CD8055EA13BE3BAD08AE1092DE5D43108EF9642495C5A1463317CB454B80EF2FD81072D92F9E93D0E1E248D4C3814AC62669EDE39F05F36164FD1610A6D26A9C187A12B8AEE8DC0905621382285870471134125485250844255442123244784880547268512633727337770546561634253401607317387373742276857434176786134680186282884138162341105032436114487587361614825265003743542077044014637717428071888830204235344735508768473564714131046021657546183437443841062682803813641721071641738886054301466850256112063147100271616112814876368374624345134475841516088333868260155187475272062267325526227164340561274317808608624583371163012362731844370315218218703456715385734028664401747415606705217177385721370841154338772368705305700366467755113257144784814107026041348176141846745605700208022665246682525357374470882022853834707235706003418167606203413810262242710038838515881260083746451866384576425368001252282184658214332207073243133063206883185703636721603305267885742482436774833663108244410401254378680257606056281870032600013063722605263501436121438003306361400508175316861102253221683218426130107101450502624712016188178186885835618468151764383132002037426788822462646334456356104540230845360853145887824037071870705675517356836081240754656548301034233465413055705723647885442818784714123443476032275268274876620684731506332320184028454826018261270602471163214452745182584768011750066462420700408022112167677443276264156261662023583717551060603843481054118602503815716171554167363010661616165167307551743386401312023444051676765067364257247535444588130760686223782827331225678674532658123324441733000440127534267225820268711001483113416170508235700844388865058645541582400322402110133286110841735642872267677424708812784620218651436842641625586204716611776715541243122626300857516266566575406181600656633746426427040605248250814184223183868381603572064646067671475635152314438574544776205366182711080774078413276800342258617867501040788344271327372368886311210384160413345532177278017235752255086055667483067020882626877754538633433610233037006837832875054285273046050270417512484138780231500015818806027560653625865250433881547683047881880107842300167356087786388071382464445747866870200455708020147304005565832022870614374417263724112308765014277366533272036781370007584236072114552752755743576678045868207804821738217614116160722788741078526756837256317877724156821547533556363455742148231173145636847706163820163557457033127117182584521450602880243106888286010613575007157860517226586582705687428708665653823450014840785434500752408618777432238387857187502588473051573712674068323728600406155714330434483248332330035516883840215848020046204481537332073007356386635524346023801146656667768025831438633264340053115116313045485428633701788422713850435022406083313738304232273718188161503856155348228057625214887361652151217027260546461061712338632841330437535648850681540536383778545061224304564384802318180034548402028602350344712554244542231280227008737078052016877458367121011466105126076452407543240056255056BD4136C3776FCC902BB88A602A6C3AC24950586A22102399A7C56CA5E061112887A23B60AE33131E73A72B4D26E3779F7440C1E053E024C0C8E250A481B252197389BCD4EC35972134E4BA9141440D07C835FF488A883E66CD2774B90033802460569D0988B231CC18C6831726FC8E1375CC220A7EE37E22945A237494389F40E1C618466E79AEF7FFB059066031ED6B7E30114127B843A6FCEC5876074D1D70E44048F29AF7E070E5CD50FABC06FAFAC325D072BD20A56A2FB087D126BA3132B06417DDF9BBFE24E2244751FF244DDEB9CAD99E5E22EA438C0AF0AE2F90F9B395C9D8BEC9190455AD64A536FE932F98EEF9562E72230F7CF3A6BEAFCD90D47FE71D7FC5FABFBB240E32D2C4B00FF6280B5838DE87CF1983F05327941A768632576061B012A0C54CCC3E75ECF9B8012807A74AC0033E50065E02D8C9F5F4899DCCFDBEE9FBF5DA27F96DA155C8DD4E8F82B6D8B0888D6001E1423E6354C828BB2D1471FD0D303A440B6625F660FA86796FBB76A8DB811A82ACB597E021D6EEDDF3A5ABA50481B54D02506C86E452F0D1E761E2269C39961F5D8FB3395E7920479013AD76D755549A28474A5DD3193F10EA67B2111F81DC797CE4CFE2137A0BD46B0755236577B793BD85E70DB87733E70026C8CFAD9C44EE49E0FE6169BA3AA1C6A537BDDA3AC68426634FD54B06E644024351BB34DD6E6C45ACE2EC75F8A0BF9B7D1E6D6D188B5F1219D0C53AD2CFEE59B74B57EA4F76E26C519B94D7A7D252D22F92AABDD0762481192BD75A7FF374EAE81FA9A32AA173BBB50B6389C24AF000C1D148452B17F79A54FE34B6A1D610B7FEAE05BCC550CA49C7E490A51486A3D0F54150B5FF9F0D410B800B5D5DA757A86350DE63B9BFF23C4B63AEFD63126FC05B1AF10EA098E380D5F3E42326EAF7EED02EF3AD26A8148B632E5859A0D3C3574DF1C8C689F9977BF6D54AF7D548290CDB4A11B25E902FB7FA1D2545DC2B884675C0E62F3F777BF021A36737DA086A92D5E7E2931A41657A461221034261E3AA80D223A43854257D871BE334B668C5D29A3F72B9322D4295D5E30B59BC8DF6011BF4C660A06AD6E84B1523097A147EDC22E5577767B4C468717141193B2A0AD609ABDC84924D556B6CB69756B571825B490EB70E7B605A900D48BCCACC01E7BA9A593C4C6517E1614A971D64F155D22EE51BFF473E33772EAA85928C8D234003ECB833ED82309E854489C22A176ED157EF93A0802660C873B36F2D56EF76E015608D1C2FD778CE9DA2D3A8C677D508416CF03249AD45743BF246C03CF26EB5524620CE3D452D7BC01C9BD01E15C926A2872B61EAAD907A2970BEC14A003BDFE6C5F5F206F2AA06C0C9FEFEB516C0913B22328C266F80988F8315C0C371E199A43428A281517B7070BD4134B3EC9F7A3E944CFE6FA7ED219BFC942290B428E5DBB3502C9B3BD161AAC14E200897DE8DD6E83751B951D9BA1727E4E8CF83A73B05DCBBB0DCC9C968E157BA940810226D9E9A55351FC089925DF790983FC215F570D5E5C9F46DD2D76AC4F2C3E35A686320FF863ECE3D6FE027D184D180C3CFF1CFE70895E3649C5644A16E4A7DA3F2DBCDB0C89802A72799D2F62DDE05F4ABD93000911A1606673CD57C016AF4C58D9EE0EE596770DC23633B73D7DCC44D7AE9752AEF7C3589C4EE6565A2F911286845BE1DBAD3309E84896D8444A41CEBFA57CA89085107B227F10C161FA3F6C6A809B4ACE3243A4FCCB1F24637D9D80ED201BC7F56CBB78078820A958E580B31A29A59AABD1A7B01A90C7287A66E5FCC367488DE7EE06ED2176DA817510A16568B3F5146AEA6ECEBD11E73CE48AE783765946367997E5F2EC3B619C99CA7E44BF1CBB35F400F891ECD0BD4D57F67F46A767D74FC3C615B85830611BDED11D8FD0951698F9E14C7D01408AF2735291BBE2CB2D6E189A4BA273A2867E00F9DC47DE76CE306D08D702E09A61C022230862F38E9D434E1F652FA8644E523B704C4A4D224DF227AF52508AC86F2C9ACB2CD8B73632026D8A235D448E0E58BCC1012BFA8C3FAE888FEE75F7575C82E2119B2A1A03090B234C7BC3ED51E83B7EFAA1E8061D38110145A2447EFB04C56FFD6405CE3A6831CD23BCC67E3A8BD01230C3F21056296364CD5F89DB3B7C906F069A1D7AE5DFC347FF602BDE1DBACF0976E18D256F7CCBC7BB7E3081EAD70095BBB0F69593D845EAA64A751BDD42F8D82CDA14EDC7C533626F49803C702E13FFC39683944A673F2C3B27A715EF92708A63A573522F8B6F5A1B048F3868967B38AB48DE71F10006115B5444F26FC22E401DC4DC51D3EBC4A26DD9753BF74A7B1353DD295C77D11B8E402F72E1209F1E62DC654183F8F7E473D8E42712C108EBBA819FD58703A2DED0EFA29F8E7C35FAB62180E09B3F32AE23D7EE757AF0FEF6D46CA0FE87AE88F064F074E860216C038AB79E7342D95F222290D5BF75466FD88C00C41DB0CFF0702DAF4E4657736ED1FED2CD3736B1CAE65A62B649AB0CDE2B67E16E20AC8A8F494DC81995163D1963089CD0DFFFB52DF2E897D47F4394485801423BC01FD4A3F8C476425C72576EF3CB21B313D104457FB455652BAA5FBED435B223F68D591A662674C443186B26CDDCD4088CD9CAB68FF8AE68F5DA1C1B6DB149B325D01678E1F5F4ECD1967CEF392197C1774BFD1853C1BD6C08E03DD9D47143C694C4AF7D67C5F0A400EAC989A9F05FA27C024661120847E7DB8160A20B32E9F254BC99DF8C4C65E9D76A88CE3B2FEDC463645DD6AD44D80D5075F29358EADB1FA2018D4129ED7A7FE1EE6DB69FEA19804EA11E9B410A42C01E89F1D7343F021AA15C1C4F8AD04C56189BF336AACB4629EDE86B3F4BCA1EED91C26D50AAE129F6DA7E9CFA1B477B2023A4D5B05E9898F69DDF43209A50E8352C4A40A5482B642E9639566F3EB7DA60E5C4AE6E73D9B84C1795D6DB56DA68AAC9FA54F5A52DA7ABBF3AB2BD59FFB4C9BD6A2B8F42F75B21527BA77D3F8B285E624900827B4716B5DF3361CD65BEA88F5922E9791FE91C7A2F579BE1AA4E3E1A500EBA20C203F734FEE8A0707E28B058B707A1C4081E71CA09E3AA0F3A277296798FB3F40B7B8629F77FC18CA9721EB1EA8D5E1D4E647FACCF666A501540E9E255CCE8AAE3F6D450FDAF18FFC23467B7A628BDE5FDC566088FF2A730772AD2ED93A1852C3B1039AD47AF727FF762995B53FCC65D00A8191E44A1641B8CC830FA66146FF710EA12F036146DC87C71BA1518ED51C10EC882514043936C93A0CD483FCBAA5B697733A21000FD0D9B1F40FD1D103160FF9207F9FC4C7F6E30B9CF56F37EABA63735F91E0686C95EF2CEE963D4585381B93E069CB3B9F59CFEA501744885969F02ADC0B997F014A4A28A586F158145DDF0158DB06103652D37000C4C4FE692435915A9042B81D7C519BC59A1EABEAADA5618BBC8F21700C00EB8C28A32A7AFD6D9515F9E711DCC346D65509690C10F0F40623770834CE30F17A9A464543488571DB36C92CE732F2 +valid = true +smlen = 3320 +sm = 16B336256C51560D99C97D15FF467360F5F563FB555932F56351ACD1E53906F1C05C87F8544A821BCB05D0E3952A84C4D9DE460BECDC5EF5138C9729E905A3FD4117D32CB0957C5BAD8E84ED7C4170BE74D63E9B8D813C4EF7F534C5605A5E4F6BA4E06F6D800AF82809016EAE3E6FD4BEEF0F045304A4C17222BE7F8C5E71A294ED8485C956865896457119A39BA4ABC44BDB4D019493147D0B5E619BFE0A5F4ED1938E48E71B88EC8FBF267D1EA5DC8F63C67D98A1EBE9FE4757195C04A8202CF012133181892A4221CDAF79BCF240D005E80E8C68DA8F0FDFAF8754F21EBC42D2A5900CFF1CED847EE80E875C27100BF230F613B0758C3E4CCAE5064111E71F0C13447A25FFCA32669E53CCFA855B997236887F6AEFA3BAA2FE264686B879D1389D72C5967030D99915A9915182F97AC2375C93E5DAFAE6575DDDC16908BD2BC865891D85E70FA998BDAA18246F73DB0D69CA58BA813E33C90A3E6B2A2C2F8C97166C9B474C60FAB1F3C7841B96C2AF1349A37C443FD86291FACB657A049E175A69443BB3662E252213A868E8241188D8941FD524EF6017633D2E3B47C9A1AC1BCB119722F54C514E62DE40B5F2DB38A1281E220A14E31E46442D31C71489DF94F02811E53806C5EF65377433222B8510FB7E4F53AD31CBA34456779563028DD1FE7EF3752F0121EFBBCD28DCF09F045CACFFA2F09F343CD4184820DFCFA3E0746AA7CA2DEFD2BC165DEA6E3A07AF3B4A8E9BA1C18C32B44EC37069D65013AA2A88AFA691DAD1A07EA87FDF8C7B187FE9572EAE4F296BAC40F3F729EC4C9EA4378AAA60B70F4FEBC3FF3A7561E2E22A7B8A23770AF7BCA50540236419762F1F42D9CBA0B1285E83809EA02C4F0F9AF086D506967168653B1A54754B629D769479EEEF76EB8171B127B724040F0E7BB815577A4998FF01662D2968DDEE9CAAD22212C3196F60D9212B5E1FD92F0367D5780D3C42C92332E305B6E15BDB3EED70643A26892BA2BA9C6E575A77EA82EEF3F425DFB971C7F6E74520889A1869CFE4DDDF2819445E8BAF658668A9E0D3C65F263C208C4442D38E644F8CA193C5F463C4DCC2217DC337D37A0FFB61688A2C67A2223E41D24D07CA4984C35C5B33CF142F443E9A0EE0F631173399D714D41131E84F9B0C9BE290DAC2CE4716843CBCCDD3851CDE789E8D03A7133F08B6234DD78F63E17D29A7B93E992EC7C80D6BEF2E7EFACEACEA917FFE1B23B8A37F438CF97C42551CA8E37B1831EEFD5F4FA495D934AD6B7DC249BE12BAF8010F55552C87E04C79762E717A8647C427E9A9D41200438187475B8C51A990B1D268FBD1CB741059622BBE0B74D1C40C539D1719232A31023E7A0AF41034A64F65F96347F7BD9B1501812FB48BC771B72DD3487485765BF4A769B8CEDB355F425F49FB27DA1375B5183196ACA9009E4E638A0C5A07E424D2A9A6D828706DE3E36D5C579704E30D3980511C3F95786FD6CDDE178BD9B246929BAB9BB6E55176F83A25252D4DC97E70239A24EDE49A93CBBA3EF31A637DE8F254AB965C6D8824B31F28A9FC4C32BECCDE5299ECF43F488E9B8E037B848491DB03F6DEDA7BE882A5669DCD87B26D57856EA3F2D3BED6D5394B7A06C498FE8568F62ACBF63197D21D1059B55516D08496608CCD6B0CAC9A49B2A9B9B7436C1BD7F0673C2D66EA6CC6D20BDD975CAD6D32C11436333454C7CBC67A9EFF002B29F3B5AC34255FE7351888A5872862CC7F745AB7116BCDAB0D76BCD187D4318B65EE3044D3E342B88BF231838B93B3328DC787B3340FFF90931C392A1283F897F9A9091DF52B7CD2AE885118D4FAD2D595A76555071DA39436675AD6C083E9160B3A964A6B020F65AEE5A2CB3BE2453C0157904E7283802F243C5CB40943ED48A91B48FED455648C576EF7AD7FF6DF274723899B2977E13BF8E803FAECF2EA7FB78F63A78975512C962E375BD6AA37BD0132B0A9232E35743620D1785A55BDF36620888B2A578141E29E197735BF388491FC40DA63F423CCDF76E2947B53D975975840257FF2CB2B5075803305954941F49C7DAC218E081FE269DC2A5506F4CC2A751BBA6070D9EE0F8A801A90895AD3C1EB756475BCC3C6E0DF907C49B4A3494DBB7066744EF693A5EAB0EDFD00BF41B90002713F08B35CEAE0B19338D604DD47E55527FDD815408A20C575AC6388240E0F9B3FDD66C9E100E512FF6F73E1285C4DDA646F6E667C1E358F166DE2688E64E38FE47F0D44410A5CD284ADADDC6B444A08BB44A3FA3DFDDAB4245D99AE058F019362EB5E89F56B41DB5D885F038A31539545863809D094CD15FD23B77BB5C652D54ED422790532FAD71FF5AFD2EC1BE5F0BB1456F09FD9B37D9DA01FB9C103DBB277AED288EB4B5B28A2820EC7B717CEBC4D9F0EEBE5FFBFCBF722B0FAC299C4EC37C03EB1A066147A18AA47752F21877111F5DA3EA36B8D4A11D06126E90E59535B3A760D882BD694E5CF9E0DCA9B73AB6984F50472782F9B105BB3A7FA7AA7B697F831D3A9A94ABCEF8F7B6295EE73A873D67A930B4B830D770AF621E2DB52C5AC7DD221C8CE33C2F2D5147AE5EF89EE1F370A90DF218F69D3937ED20F2AC484D79CB5FB22C5C1BD477FB005A05414865AD6430233997053F1C4AAF7182AF075D196058C97F871CF7951585F90360504841AEBF6DA4BA1E721AA97F681989704F04E13B1843FA2678254C536844A0CAC2391D229F2C1382819F4E15CEF9655C1C667F45449CC7D3BDBA48C86E112E9BE49C2CF45B65934304883EED0C97A0ED53E660D7019DCFD94773D4209058D8E131B0E8DD0DF041A5AF4DCB7FFA810757EA253204510C69D08D4FD77FCD971D4D9C5E0FEB00B8672F525C13DCAD6734B40B98893A74836DBDDFD401C9BFE873DA4D1ACF4EB1028CBED94D48079B46643652AF0A877091D28CDE82585602B6003B47F19671D42BE1660F0CFAA289268CF1300C2273038831C57BCBAA2C88934484565CD2952AFB8214F76BC911D0C942D4B260293630BE3C0C44358D16AFC38BBCEA3AD073179487BB17D0AF4EE8884F30BF7AC5F7A8B469B7A82FD83C68A5531D2987338B2D760DC6718997DFB433CCBEECAD89EF7B79690CDFF544E93572468E0B044221304077C8D506DCED5FD7A3AB0449771ED71CD5790DFC43B1BBBF22A519583BCBF5B4E836D6A59870D25ABBE4BF8AE2A7723BBB98E3C763A9DFF1809D0AF5EA183EB1C983F06FC95735A64390876394ED3A98CA2DC5D4D6BC4F5004C7A4BACEAD5DAE0ADF46139FCC77E7C3D74B000E08BA87AF82F1669A8CC41855430E1C3A1B42ED1790D127D0861058BDD401F59BD80836E81CB019A923BB4DBEAE1CE5D8C9BDDA06CA80A407CF057448618332C75F2E61050C4D9E20B34EF1BB5D00008D152D77F220AE4ED705973E704A20C170BD9CC1F00D2C7B09A6B00A010BC987E0743E2F3005C7A802B73F76D1831E0FDC39D7F5B881B551116BED6FA9B7878D1E34CD9BCEF3E7F75C448EAEF8520EE560846636009AA7C6352D3C9BF4471DA268E00C9BD08D620A172E96CDF2D286D0433DB1E00FCA409DF3355ED471053A4B061E07D7CEBD0967C2840E3EE35AE99948F4AB0FC4875E8FDB847F6447E429D1261A961D0F54A6466BD1751313EEDA7C7F1EB197C31E3EA96D207DCB30AFA834A7923E9D482B7DA24B2FAD6F64908301335FEB45F68B4257E08AB4B51297842661818EB1532DBD1FA152177118A119EBB89FF9693506C7EA51392A009745CBC5BEB359BF6067958EC19A59F1CCF114DD379DC363663E284B182C7BEFFA1270330C009377C764D4C72A6A8C739430FAA1AD5E6315C61BDFD1FD573AFAAFF096BAC889C8195C07FD7F9203142C2BBF76764F948B92D8AB2B8E876A071F9C7626CD1F8F88885AA5F1BD2CD06161FEAE0949F7F45F6E1124FEB6211AE8CA38A0B2F5810EDB79DBB9F3EDA2242E61CAD3F75D8E030DE89042D8041A2F6D4260D2EFFC31818D0BD34F57BAD846B70D61B85EAE3DBEEEC6E7A1EA64E7BD691C4FD07AF4292DDA572B7D8D13E0FEDE3E3563CD86EF4C823B1CF96B639C13A988A6EF4389813296FB9D37070B5C17B4374681B8D46FC9BA4F53C63DECB76EB907CB49A23F43FB788E22086EE2C269E25A0C45B5FEBC15D1F02198BA7E8D4DE8134AF6C10591A28EAEF7F39F9B54D845107589F15087AEB2ACA0C84E475497D25BAE0353CF2D036CBA5FC06A7A0B19DBAC1AA464880DDA5584EEE02F306EB486FCEE0D3B58BCC5555E8FED38C7BEC8779CA1B47EC5B9F1BA01DD18A0C3A90FF771EDE19F6B107F8DBFBB3AF3904E4F45389B002DE434E29425FA9473F751DA9E0A44E8ECC3B09127E011A343D2022B18B953DCA32938FB2D94D2FAD4295C1AC9BCAB0AD6941C950DD14FF5973239C7853DD5E80FB1DB007A923AD0CBD26973C9885DB7FFFDD09DD896EB6E83CCBA97A2AB7018A6339EC33E7AEB84D0F3323509E81AD2ED32E9F749011FEF2F9FE7281C5E204E6A9E3107F9901B0E3A7A55A3CA54714C53CE2BC79C4AE2652D3D5B701C31EA92513C102A4077ED8F76708758B24F3083D620F2EAD66EA3CE3D8341A0D4D8C99AAB5D1265770A7ADB8CF1C226A7D979899304B5F92999AB6B9BFCA1460A2A3B4B6B8C92E459597B8D1D300000000000000000000060D141E262D48656C6C6F20776F726C64 + +description = rej_ntt_poly (sample_uniform) requires 783 SHAKE bytes +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = DA2593AC1DDDC220922B9B1972A2549AACA212F972786A5A5D7C2E00ABC407A14C3BDFEC8156039E1DA4334D82B03E6F05A91A5D07E6781CB8E5F864F700ED75DBE1DA863A798BE5B8F3AE8578A8FE444465F3FFAAC17AD93756E2FCC020CFAD625092C61E4DC425D5E0A22C767B14CF110B3CA30E5FFF93170F8A929468437733240242771602371624281748881635455404240851716735204245036517314217660477141247651752202318835871263122834465622518458561780077570860257211388202828424008014443514083316467565616425053801127375637763428303217364610105374586512036253874800726837230162716148822164327068506803332315418054083547225706812304078461352086308710530384081037277854166504830426243572414407408807067584563753143818505264202624535777016578550230362345472415216650431401217458300408665544784324722748332322278777664586356034414654757657262504247556500211401345401633632741015515507171327888844234052648183330470851507147642405011866458485633820262788642782878068572673764871060611175567457021424002753343444086888376536447420702267251221218146408501871634878388454550872582658835214562682244426224475466035676608602843155263580626230150842033248603648045111465125166150463405382800002130416240806315850553846481530573430675344031702350257584774586310886740422471750257872037045052462248458052528310612653318074267532471381843037180462020573145748487714165878431675412705266272883888522812737706187220141562472444608108751574284107500551523613755517205820802554537456472286135021874748137217128706016733830887854258265828367300270303688338615155720044524266136303075024644836528707042470381300746328842652066778278360422851101372253223058104244141813851508547177371185144321751212267126011721730140741157833213735215450754734241507573286055156700385456280846738617521217123054445074451325688276346468707312574862207552642663548548006064707771678722151222408424131676603022358014116704218102765763220018254127460208100760178570451172847165177018721533544777204435777016163523672650735463502720238108316666455643220017356565343428200835360837373844180544144352881713204857857475283554064001504530445706362647323837262767542470713007783072813357666324626452082513155822315431771831533353774735457021432081815828511167247735257252207870833776828767812535771064485036603077422461118011787676222326187572812047703517384221243253372787888484247837613713745444303744714023057142788518300475325804728133127280300837257426767222163200074467704616626445262164854074466715868706312213461252075860557076740331725532473364424816665372457837782646305451803381218164544633135260215368500311410018803458480043617560274602523857205160615303773138882578846268136350868032875856830550881618585006705173072806163276643010734884562004778601413036154804022584203461258326073168381752728371217553553072852062614530162028308602407870450875047041736371067424124246880624651802834462053710506787152280328350525218258780431783325044038233126036707436687026446108813622227012560541130112833734768030554033032652400333425772416241614235203647050010158470101686540263860467711728648476401612215730561313346286742687105744030513126763260341562750403722707670821811162538571202BB6601A2C57C94BDCB201A3D2BF2EBA46770D436F29F6120121745259E43E68FDAA00A599E862E6CB6B251DFD9248F68DB07632534062BBA7D82D7B59CE53ADD88ADED324352DA2E85D0F60779B7BCC5C97BCCD7F7853BFFA225876F3DA5CAD225EE4CFA67A0EA26AD2CB37F044CCCF2E40CD2216396924624D4D63EA47BDBC3A22D910C07F4A5788C74F6C72F901BEEF1CD4F309D2D2F1EDAB870969DDA414129FFE834DC6641C9E91C2C3282D983BFE19F2E39225FCBFF429E1A6EE4304914F36489D4167785AB7C8D34A122E6789ABCE8E2ECF978DA0F9703FD81B79EF438A9EEA48F9F7D8BCB155B18638EDA7275569D3FC26DFC5A513062721B72238896AC1CB0BBE88CAE8612A94875B76BF70596D498A85641D90E232B40631A6459E89876297736BDD89405236CA9055054E7F0C844257311EEED1325B90F833ACA583413658B46DB07A7ABB4548354D10E72C3B38CA1DDB2ABC9819C1B7F24360066FAF28EF5D3A694A142463B63E13790F517F130FF7C6A93253E8BCE723E1842A5829A1CC301FD6DD5B2B08DFAC76ED4B8ED9B1A66C5475D7DEB3B17989630FF26F9197977FEFD993033098BCEF68D6D9F2DA859CD772D800CABFDF02A7737E048A66419F117C6F3EEDFE33BF8007506755D9D338054206CC10861980AB82F979A85C727A5ED1CE39B8F36AB449051460BEFBFF33AE33EA9B4DB373805DDFA04135B0522CEB824C5D6D1B0CF840F0E018D41FD1B4B5FB7907C8212F534A91D79AFA3AD6F95AB903D89F6E58C36A20F805C9B73A393FD6E54A2E5C27CF090BC2600BF81D7E658F22152D48964644580E1E5B29BBCBE3E72CF4C2973B438094B3484AC8FC1E2348E9FDA2F4C02F0D6B01395CA9110421CE33FF49FD5C70B51B516E9CDDF8BD74F4342CE04106C4D0C51FEA11C79EC0FF946AE087D4A02D8F5356588BE470E5DC034ED9161EB7899776527A6D5348702AAFCDDAFDB4D07CCAD4E1715CBB2F8AA9AC5F5CDE4D31AAE06EB47508891BB21E97A08567937D70B81CB862A68C136E0FCB965D139B281AE2E7C396EF085E2F69FE95611B313BEE0EC65C028A4A7AD7C00A06FCC03A9220FB607A10FD60308F8DF3DFC8C606C13B8892A88A57F13DB9E13BF0D75C00EEDD42EE212BF51C4B389C34A12C3F58005A9CE4F4EFABAF93BB8CE18EDB72E74A578CB5B8907AAD9F95EA310E9FDD49D567320263D1137D6E95DB30C60F88D7E3C00757C593280F4CF718CE514C4DFA5881E822F6CF019DA816AB50BA6EBC4A376FD13809279EC94E54194B9396E0BA47207EB0EA5F0A3C5554423B3121FD9886322F2A8C83F4B98D9B07BFFD556E9347F25B435F8B2FE0951750AC7E71FE9CEEB71F1603700BBA0D11D8D343976A1D8661BA117A94EC39C4A5587B5E436CD779AC939A7950C816A0E28BA61EA18885F00AC0F4B8963A3C5E2885176F23CF59EEFD169B45595598D7C3F7EB042978E1C62FF7F7E88CDEFAB52322B1F0D15141AA322BF8C2E75792B9A7FB78ED2BB24AEFAEC4ED407A20D56CD220FC814DDB868649B59DEA7CBCCCBF64124214A1524FD6E31F143D7C3538BE0B6B338BF605760D20FC651694B62B8995EF493BCA2EE57472698607EDC3A3A4261DE6FE9E0BFD9B93515682B313B4DD8C49E656B8BF6F667F6AF72B80E96EA0A9ED76288DF4F53CD984E9DEF5F9968CD430480BF4A8418F3A4A7FD6246E279102C0A8328B1DEDBD1FE4955B1F3109DE39B2574C6BC9F8FD4EBDCE25D185564EC35E3C8DBF49F25D92EA0F122C102206591D39637B4E9F760D33296D0253C962299A2E21F05C8B85F754022D91CEDE63603BD66FD67FD420274CA2E1FDE081FD3DBEB70F282C7930109030117F4A5E0F9807FC5D7307E7FD8800D362A4BB8292631B868BC63ADA8CC163CF7AF1FF3AA10544C88EB6D00E2AAE0799DEEE71EE271AC3F62D796271C2DD613976214E944B33453FD48EEB9A3553293B3644ACEC58A4ED56445F223538E357A2D7E3104A6D4B5F709FCEC2022B2222AC772ACCAA9E12B1B33E0C5071513FBD02BC64FE6D350C8F9525629350D24829F3C7824EAFEB898148B8F923C81C2B04D9EA4A627B4C554B258D0E176D87083D0E20903E9FB41D7D937472B022B79F4EFD3C0A988E3F637FC62D973682CE891B5AAB1B3371E61755FAF20476D7FE3B622AE983A418B022F0669F89DDF60BC249465043142B45AC97F214CC8D2BBE6A41E35BD8055F10D9178BFE7A8E8DECE2DE0A8AB965EE1D3005684E2B7BFBC974DCCD181DFD18733857F99A383E452AFE7B8B6DA94E37EB7E0BDB1F289419E61CB10E4F839E36A17F5C3263B0AED6AD74397C55029508CA38E6D61A55C63532AB2BFA90EFF64046AAA278BDA1E25576B15D7DED96C24E850351D074842ED54AFB0EA76C50612B28CD467B2C26ECBCFBB1CA9B704AE9E089C315710BA1AAC9232E8827E3B33479CCC51D7191B4C00E4E8ED21DAA612E00BC1BD57E8D8AF9C150319E54D06645C27D742F35CD7D5BA40BBABDC755280E496E8FBA6DBBA127D0484AC0B12182B640F8E9EC1AD7E3618F76FE63D6EA5543473277F49107830D29548921763C53946726B19DBC0B8358B29AF7E81A5234E468BA32B02597529E4A79EAF716B4BC7729D4DF03232B3A56D393B55AEAE6A5C28D0B37080B66CEE42BD2BC1F0367A2BCE60CEB70BDD9EE6ACDAD8FE4246498B0D35CB26E5A4F31C9F301F9B1AFF29835D7C0ED8D5964F820B8F7C44B5D1D337329560A7FBFC665B3E3F0255F55C64896C704B907D54C4F0470E30DFFB7132DF233732505E2BA1C42142390A1D7CA00EC36EAF6C558F83C813E3E65FFA4B93D302F15D72BD0C116ED6BAE9E8AD690FB3C35F4262F08C384D426F6FA460C3CC7F4BBEE0374F58B3F323D9C0BDC2431800B2913BE73FABA07308CD135A016D8316D6571567E7A1D879DE51E13F1BC24AC0F36E84F6255D1D70138E2DA0FCEBC3C8B5DC43F5C5B65475F2D793F5A48FBA33FD975F8AFDDCDB9AB72F413B04F9D790215817ACBB30817ED563B87F049C7079FC857F9CE51AD2FE061F0B564DC0B7C991D2AA3E1936973CFD9C9457433AF11AC3F88565A49F4D09A92F080E4A89ED896E5B30DC84526EE46F70B1C2BE115A9BA0DA900E73EAF8E987755D5265811A54C47731D83B381445C97E35D03538ED31FFEEED0E896F394552600FCD21F71D9724E6B418CB99963DC5915C20B89137E0217623927C4FD46713AC1F68B3F455053129C5BCE36E305CADA071B17DBDE422C139419159FEB11787486ECA3F053449DE5010E17EEB6CA850800281C41082120F6FA45CBF92F40239E4D85A760A82C6F08B642880FC8AB71E47266DAA313878DCD805D901778AB1EBE265FBFFFB44622B979E7606A5C4E14E1A6F40380FC4FD0B251DE3311F7ACB698F7CE0C27AA89DDE3BA0B2B1678B2EBC6BCE52940492BA8A0FCE96F3BBBD7052936F522FA4BD0935B6C38190981E723F55DE51CC6B7113A8BF648ABB54795EDE77945030FCC4DB +valid = true +smlen = 3320 +sm = 1873DF7BD504C772B508A823F78C4C0E859D16A7BC477575E700AD4A5E862F74D2537CADF3B3AD288ECBFA3FB6ACB3A8DDCAD7E1225CEC57DABC09444F900A7C922DD7AC0901A2527A71E32DCD3B6C71FF446EA8B8D404E61D59D24439171F1BD2D809136B9E71DB3ECECCACB25DDC3C84B318EC60327563B30CB9F29EB59B21B214E45FC14139CCE27A424CD804F869D69B5757CAED6CC254D3CAAC256BC4A3D8A95FD3A68E27A8CD88600C143DCB6F1559E83DE3B50127B75233E79C09C0FC9BA447971931BAB365B3675289D8A97CFC58305AEB4B81D9D9D221E21DA52150AAA9D1C655C8586CFA705AD67B793F2F96E545892B02144927C3BEACE27BEADB7E1B696557CD8E4A745B6101D4B05A8C999D05831C568367B0E71FC3FB682C22D9A52654835F06AAC19FF5DC5E4C1EFF1C49846571565D60458A337C44C6484884ECE36197BD5A759FA54348D4433058D1CE34505A79672D2E13BB01E810708739E5B4E86B5010E21F56D6035FE66ACFF867061294FECF203E528D71BC84DF0D46B63EE9EBB0806C3D346CB9787DB32D667B059A42FADE5DA9E88167C74056380E1E35004E59277E90FD4A835032442AB773D52A2A60DA388F0CAC93BBF26DBFE11B9C5F16BBA1D4877B6382B5F98B1E279DE8C06FC569EBAB6442F247CC321C38AFE012A003E5454F5A3389AFA18DC958B4BD99A93B5A1ED6D4497C75B0209D0D7669BD6A4F2D21FC61873A31C1B617CB90AEC8AC7FD16B12860BA0834AAC4E60F66108C0F8B17ED43E306E52E76C4D1F572E12D986ABAC77CB79D265271CC876E46BA3CD58BF650326AE1BD91FDB92A337D884C230F625235C403EA6BF1CF601834B7E0E6145D23CF386514F957B9CAF959D5E420964E2B07FD2E7E7541BDB8252103871A48B5BAB5B13707C872FF4B08989BFE71142346E2953028F26E1DF451BF67A7F1D71DAFEC0D64828CDD535F44BE1FD8E9C69A113BDDB421676E07027851B073053A9E319D3F2C5EF128476D78D44DF98D1C72494D1581B7ADE65A2DBCF7B0C9135AA42169DAEFD63124DFEF3DEAB5D93029D3ACF418C99AB58F39B49D32FD0525017D4DDE93495CA4F812152A74047EB93C3E63C0BEA2AF63194D8287779742D7F5A1B0C48FB299A1A1B773A331C221755BE407866695F00AFAA33E4B458037A0030F3609B3B0A16F7E68920D0013CF5943C076B3E20BA19C8DA95C18F69526FE271301CCF45FBF248FDB8A5CBABB191D6355F1F87DA4B9E0D11B417F5BD1AA8603E10D9A082DCE8F29A1B10E814D5E5B1532A209A636EC0C1854746087666C2F030221324DC62B24A2EF2E30D519EBCA2908A84C384735A322F1931597635DBAB254A1AE28305883C1BEFF6CE068FE7766E92D7977DFE4A315C09D0E39920E6FBD2A3A9139FB0B8D6CDBF44DDCE7AF4CAF616D0FD9AD62C41F48E3FE81235D79259CDB48EC0412C08219F60728E935F3C059198B5EC99168FC3503230A50536165AC05583DDE40A99A950639B0EEE5650341DEE03E84FDD4F5BFF58C9E90D8CB2740BEFF0BD05951B107A7ED5C0CC8B987AA753EDFD1CC3E5A57668B7C6F6B46979500A63608BA2A438E4093F8226845AED1F8DCEF6906C9B590D0343EA442F20416E199F9A0EF1E35BA075832D1FB1FEADF5AF89F84DF428CBFE7ADC07129E2C4381E0EE4AAF48C3E83567796D4DF6A0F77BF524EADB07450FB026112B1EA538DAE20F494ACBC9E020E6311B7FF4B325261FAD7784E5728D1E22033F28B95773DA2D9230C48E82DAF126882178BCFC58DF7ADC163B2D41E105027BFD9824CEDE1D5EDA485062D9DFBE197F25D7B0F7A1742E9EE705B5213DF8BDCF3EC012FAD069F13DCA7EB025C6586222CD754E7488135EC0A38569E45D7364ED9400E4A9D5DCAA7BB1ECE595973912B4BA3BE885C6684243A3C856E054A342235B53F217EA2FB6280DAA54A31027C9BA72AAB802501F355ADC9604E799FE3276655657068D1DB6A699CBD6CEC2F3BC5C9C502D43FCE11AE3F8B2B07A85FBE0D244FD81C9F92495459A782FCA7A2591B43DD420DBC860C8645DBD55FD191CCFC99226EAACE268D6BE92A09F29AAA1E61B53642180956AFF65B59D93C21302CEFA86E85CDF7D926933809977416649F853A3EBAD040D952FF34EBD5D6B2A3C8F9BA32B15E3921B70BA47C505EC1233044D3F349F49DB4D262EAAFC04AC0BCA4317A6863F3FC88D98A311F80EB41BFC5C611312538C4D92043E7A96B567937B1A3EB166081D0DAC70AB5865D6409B3310FA3FB55BCCD8EF6B6B79FD677EA89C9117BA9BEF2C0F282E2765CF100570E1FDD58323D4926648E8C9E4F3CB3E74AE5E3EF0CB53DDF48F7A082D346798566FD508E1A81BDD8FAA0F9AA23ABDC25A7080EE24AC4D147097976E6A350C23C5B9FB70F0068C272CF79756E25B2708F74D7D73D4976E6EDBD48214AA276F823B535F1EA6B1004612D965B6B43B17C66EC24B222E6A50C119157BEE10ABEA8FC902F66EDCDD9D10CE822B186C9AA837F2DFB0E0D612B358CF057BECC23106DFBB8511BBC14DBAFDCC1C44F140A6234B915E297D967EF905373C9579CA1C135C695B25A57CF8E7280BD32D20880A2155AA2E6F37CCE95EC487BF57F387BD19D398AD6495A8D6C3E34225F02912D204B110E92085DB5958BA740EBE55E14D37AB874E52884D30BDED1BF58065049FE9D495AD0095FF765615D2D192AD35C2E5CE12368A47BD53C94956E4BBB13B5F43FC2DAF2A82D1168E76E0BFB70F55A636DD68120936E888C79A2CE18FB1D8307BE5518C8831F8122EDE516DB4F1BBE06E22C9E683769E3FA0D42455DCF53B099535D7B2DD023C79947B2269AC8C4EDED0CE16D6666E738743FA61F05CB1AFB685D5DA51550AB115465C5047044DCCA58A3A47C9A42A03FFBA31174FE3DABECDD1B887ECD3BAB1A1AFD6BC61CB527B5C71208D797151A05B806209B454D62AC2AFABDB4023E8D215B6D8DE761852EA366E4DEA97EB3D54010767D2154B3B72B6A3599F624098AA9BDBB9D0D9242F7DC823A71AA89277F75ABE825D6D5240C5590439F1084952625466A1676F778FF117D3E344E66ADCF06F2F78935E723D86C0BB8CBB9D90238F963F8C63F94C5FA8A946D6A925CDC77F6CA2AEC141E8F16DE1D46236EB81C57CE682D973F2CB3AC12E3CF9E0290E4ED555EA1A57AD3B49D872DD6BA99FB89B91C8E6B25DFE38F8DF7D91023BAE4EB2DC7CB0A585A3BAA9422AB93F349167578DD3936197E8DAA71128083F7F783C67532FAC42AE9B88B94BE99FD9B62EA0D6E8C53EB4BA21B726644438649D0E19F379EB77594F1D5CAB77E97D61440C8F0AB0BED326B54FE5ACCDD7AC69ADEB946C855E32AFE33B6C75F00FC992F53FFF91546317C70CA6102052EFBE00407CA20FD276CC5E0C2984AF9A442787798673877DD990F6D49FB774FA6A6969D73E37D7AFE31B9546125C9F1C12280AD11ABD8866A0C13A210B8342390367ADE2772B2A6FA98ED4C373D2407A7060F5ABB6B0D8046C7A6392835B1B5BFE69B8973135B5B4DCB4DA252AF6706B3D813B4023574201B087BD7EBA6F7BA4C2E32F94DB3DA7CABBDB04728EFCCA581373FD34E9C518C3E8A388E46626CF240A5D30E18448B5B0058A5F5A65F0C8F3D5C42FB02F8F391C8AD68A8F05385B86D3E816F604BD75B7ED5F27589E4196A0A15E376261F56A89958AD737448226700BFC9BD2FC05A09C23E86B85304BE0FED7B4BEE40F106FF3357E40107055F26189E59126DE22DE0C50C20CE74C2D30FBA2F8290C969508321BE117AB8AA6270961A9DA3C451B3A4910EFADF20D2CB52B07A57700A11AB4D5449CD370789057C1E66B1CCD6412B4461B0208C87863A068C4A2DC52E1D6CB77103DBC6993C26E77D8DF0E847BFE649AA9D111F9F3718D5ED949F6688339DE0D7A02931C5C2FB34EC6E5BFAE039208A10C3EDD34DB3292AAE4B1CC2DE238914DA4E0B605E5BA988674176541FAECEDBDEDFE8F954D86972C9F187DE5D4EC61D9DBE89C3DF927E245B14A8A4B7CBA2264C1646E632E07DC59B4C6C0578AE7266E312174CAECD94A57A50E5D87A82DC94AACAF6A3E87928BF5ED7B4A939C5A2D445BEB9E7929C1ED4901B38CA28FFFCBA1F9C859962698DBE4460A694D99FD47BCB91B391EC8F4E50500466617FF2A0123DA15798E9CC4992043B34C759B63B6A3B8D2B6EDEEF00F6B8C5A2B3F0225C315B6CD6A744151CD5AB9CACF0445BD62586B7469C0C4E6D466FFCBDBB165DFA42BA888D64E9F7D22D1AE22E1A361F4DDD5C059FF273928A47EAA229B409E20E48570CCD7191067869940F661385B0E57C04F936C72AA36C0FA1DE1CF3A18EA4B2E889F7AB3300D223E2F73200266AD8FF854E7276EF9420539DFF1422296D22188D519A5F7E8FABCF04B4E85BE6271A07E26AC654D93D31C1BC674F5799A84474FD347C44A9BEB5523F6E89D8993C35BD6E5DB1996225EF5A6C7A92C0B2C57F1B19EC26C75D5A9125BB4FAF7C0EA29063CA6708DFE044D5C8B23F03E376A4765A2E1A127A82E51A7C9353112D05E841245D1D2C3F254E4C6B0EEB4BB53818769E10610254044636AA5C93A678BA0AB1A1B41434E7B899DDA0F70959DA80275DD00000000000000000000000000000000000000000000020B10191E2148656C6C6F20776F726C64 + +description = expand_a requires 23103 SHAKE bytes +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = A65C0585D2EF17634953ECFFD89A4CE8459CF96FE59D2F9F59170D5796E90F535413AFE11D1A0CA3836E0D2C20D592B3E2B30E82A0671C1B7ED5D35C8BA49B67E09AC3EE366ED99C1CA60E5F36AA0E78CA6D2E7607FE7763156A1616C29368AA745314C893F5C08FAC6FD11ABAD39B2A1E830E2748C6B73BFFE9BAB748FB9A2E28803823122456206453855788175133716500411187104307286261026560502276812271470016274682378081051078477760471788355034715262832450543584782475087405654320272043531536847377115776627727860873852105773035732813101351077852848385363142078211177447687250018588057661617208152684668736778235370622835174116464801511730173062288114768142132876460670374143345577773826000045227372736571148288708040183586352562333517837331817745028303240586403576114053066560710702257210756523743211726361424371032147682127500550825747848502418085063207545453313656443256232646141857353613204133843418035544067888681122272844478801600062564840286175178208362573661304742345871508625477747322316032063844720421725827782840748457260383178004701058333436144083501188757383513822741182362708418182852151765458332117485622464531660501037717830388612310167121564436655088655580744281322717253177831136660170480574035408883326257721574028754586428217608652561424438141334413064315518355444417543220016455615864566823058774187310573807710175105527003145650180157787728750600247538322166521584723315123440882885466086786856351436173732516343262566085503372167281773674582008866772060830441534407767833356227567270004501087672031411500661783352872523310182873635673662512038105134773586117812335312570266610625722125340813251638778137244180737408284564016464041845164346255744716012381221667445872068848404067760018632171848852708557638268542587005211035148571375664600414263105403275782165013331372041415288885416686184851430758434005232385506258845256035475747721865025877463810348877355178034016111540727086730648166603777551635052723151845735830847287563074565842682504835725268864063667602021012605240728285584158237252518303676840605075414085568428615102260231726022004810427264601241074310367856717545583103728506572540201828346564666774027734375847122137870252073112730664821413326403604136742067254434075666126815786075354270451174033207611078056555442647184881585217005584242777568473272130613457713676703657358871417720770321004500306107521861072718033003550086182702205505544046548131166402121018064215383764452210735674377766486604372216170112344087784222435604210544388333468321450714373686305858404845430553733256074103817433152252414544045147441614020028266876880382575183847773375040127206307543411284330013672775477383526288753504882118781556208456374552411775046420266050850888602622431002416836135636080303178717344020082347562764404506175760367060712405824378725225252681168328208688460384047473776787057018800122848375573147448782613146373883500678702510552243874527428633830283650230563225106284504548454775738508148010664668277637080287082715278376873366616877452842355420873382111244885452752528538885654267050617150128367460516664385627081857143800868422658317015370770168663532238726437051187010222000628348578847340441768212CFAE340D43837AA29E4C20EDCBD89D2221E74E251B8D6CD86941AF979D4435385CEB3996BE1B4A0942A685F30851E608DACFA80FA609C9D8A038BC23AFB58E2AC5551F9840BFEE19256590AC44AB268A6771F7B24573194B095B5A5549F741E241521561FCFCCFBC30638B4A111868301E73A0A3E886B230DBCCAB01EC669E2A4227A68FCAAB2FA33FF72D5BDB3C49D7CC30BEDD70F3FDB4B3040B30A144DD3BD7F85DD25A4F06B0E044DEB2BDC66326A43182517FF7D6C121EF4439959C5593558636A8CECC76C7EEE4377F12C450B882033B01EBF67D3A02B6F5BD783ACA9FB6AD18BE2021D84C0CD55EAF862083AFC0AF458137A2ED648464F99DC43BF852C97A98FE502E31C22BDA8CAD497DACA11640B4BC0B70FC8CE3AE3D2EC60A5112B399E38BBA55E6E5A1575F0F21A3AFD43D3729180914003382A5EC06A719F8A47BB768E227F87A88B67A4299D003F0E12F0DA6628F9F02135AB15BADEEF6DEABA2DAEC3355CBBAB2E73944EF32C1F2511B631E083274CD4752C2FA1309E905960BD4BF10E9370DB5342850FBE92415C0E2470AD7B51A598250E8BE474DBD5770FE2002D260DFAFCC8668161EEA1B1DB31E5DDC90D31559CFB3F6A8E6CE068612827E3A9AF6631CBABFF514FEAB89A05E2383F542916B8B077B5901E68DC979D6B39334C1394D3073254737150ACDB20993876A736AA9C504744D8E3E3584F3329D8909E0D6A35FFF7C02F67C5E9B8389818545E75D051EAC1D7917008E0E9B1153851F1D755A7DE509DE21069EDC846E0CD8DCC545BD8F07C45B72FE2F523AD5CCA6E059BC1F0B835F28D6D33F8D77F744FCB095E3E1C7076EE1279926FC0DD36D17AB41C685C4EBB1AA3231F50A9B5A4F2812BBF6B08014D37A7A2BC70272032CEB83629109AF2B37549616E9D29DF0B0075A7A9A750BE5964E6D500E4780EA753C5F60A98EA0CDCE8E61F08FA87F57D08EFEF9011C44B27A62864FE6BB05FBC1C9755152B6DFDAEF254B76CDD574B1F013E2BECA4F4EBDAE17D7302440AD40B5BFF57A84E1013F152EF03DCD568DC2488268279F1C1517E357918AB795071040C02633FF68E42610530E2A7621705983E11832ED238C92740B17D78DB86073C708053177D143A2B1E30B05D66A19F9A3DAD723B9610EC72A042CAD021DDAC3C056594EE8078155128D0F2F14C4EAFD3EE977CBD2FCC0EA3EAB4B405DB899EABE19F722C166D2C7ED4961983A34E2CBFD00F13AD7B4927DD45D9321A0CBF520B727ABEECB40D37BB704013C701E8635BE5D4E2445542C527EA078EC5201E45B68948D41074DAE91C7A725B364F41C0BECE31CAC2EAE25F0549D510CD1F12D75BFA872A311DAA8FDCB4B98DA74D249DA40BD6E4B5CC7B18274FE4ED4A3BFBEDA23D02BC92BCF75D265B5095335269329396DD7C2B8A141315E412583340563C803650791A5A58FCBC46034D883F4D76285AF08E4C6CB612A4C9A3F8B8A4378DA426E23305D860BED794DCC296163C43928147E578DB19604F33464FDE6B09B82569873EF0974DC8BC7AA8FBB1EB3C72A2FD3DC544C8F0B89853D3BE0600C992F071734BA3BA9FA1E6100E3DDBCA2B7316AFD5615364D8063798131821327941C61868B8FD02A921FCB897B3B967034532EA501C974370C66BF060E69B70824D5E3A8C6A248861ADA7F891E7390A210CBA7BA7E9A36ABBDC25077CA8AFC4C78BC7A755660AB8D22A91624EFC24AC00CE3A90AD23FD6E81B2D5772D457A86A35ED874D053C75484A2A1CB4F7268B7CB29894310AEBC8999B68EC35C5AB792A238E1A11D058047A1E1621B7011D5AA87B4801D854DBD3F93931F2AB21AA6580ABE50CA317D36F112EED1B9D45B2C2308BD3F7A0211B143EDF875958A5E0C5984BFE1982F03F67A47DC39B1B466387B1EDF073689EBF69D81A357294FE062C494C6AB35F7A77F61ADF74E0C95E9FA9A9FB3A9C480322E8D7E6E16AAD503378D497BCDA82ACA132D351DC5DE8093A91E4ABD523F70B75C0D48BFFA4D6ECDD8F78E13C7F0027B960E5D1053D51E73F6F8E2768894D54620BF38FF1D860CE2E53680DB698DFF64924E7ED0905E1013814FCAE5F2E81AE2810990A4B57010FFC1663062C58437B7CB45536D08B1516ED48F67E607EEDC730201541CA8666E965F01D13DC239BA5CD90C055D45508BD8530268335FA0DAEAF8ED5143039406BECE8FBE2A88CDA782BA1AF015DFF428C4E80147802F55C96DC1AC26A3600CB540DC62E2D7F0B46504D88472BBCC47F54517083240F4F87F3E13C1D1B4494CCD7AB34F7417B7F72767712911BFB39980E71BC02A19D710B61F6F0E067BE9F6CC9EFFBA0E70D180B36FF051377273D969F061EFADD4ADE9D99E100086592990FABE22BFBCB8DE0F1C28F3964489F95AF12B127DA60DBDF1453A051BC4EB084F7AE8660F4338EC1BD352846CA75C274E415C1E199BA6F8E2475F105750CE13A83BB797CF361D340C0BDB3B9CF3EC418FC87393DA998EF8900DFD90CF25D887AACC3AEBC55BCA907673D20DBA2F36F3940105D625CE13086F8D5CEDEAF7F89A062D6E3F3E6778DD33A11BD73CE79A49FCA1CDFD163155241E975B2D81C49E8505B721F3189B291248FA1C90A06E59670D6015AAB5EB9A7D5599AF27B274BF7569E25D4DF6A833F2275C7003C53A35D60B499E14CDD6CE1BEADD85F415D62E9DD1195BBB5B71145B94878D287F28E8CD81A035DFED190EB2BFC57A9300269901356CA7AE0C74AAE3D5C81CA88F4D26DC4FC14C4BE6125ECF27896EEF347D1A4CC3FB2FCD4A68D2860A7DF8CD724F7A67D8F0823C48A2A9D9C62CB1A573F0CEC4D658FA9DA5D28FA97AAF5CB07D92068D88F7E12C2E3A8A3481F38520AC182D5A9DBA02726E9E43AB21E438DFEA02D71955A0C20916649F57932ED6AA86637A03D9CC5B2030835A9102EBD392F5CCC367742C1B7FDCF08D36DA1A0522DB09CA34128233A556E3B0C8A60D0732C8962E7BC5D493512A205F9F5367D9F5192E471CFF71C97DD8E850B19A2BA1E6B0D26604A3E28D0D9C9753273F0155264A3FF43131FD7BD6F635F43343BD69C178F3A80B8396B1D4D3B2DE1006FA32E54C33C2B63F3C2C81B63FAD3B98022F499C1FC0118304ED20F2DCB593431405C5F93AFC27C77023F564FFCB2BE50DF68E1BE774CAE88FE6C042D87F9D91AE084CAFCC37A9281B3CEBDA45AC9F409B0CA0B9E600BB9E024B28A63F9A9145B182E7EC6A5A5B9B3DEDC5F14F7D301CD53B18450D91DBB6FD86B34462503BDDC273B3511C414661309D18D8E69CA2C14D0A3EEB6DAA539431DBC7C9CD67EADF3AFA1A19DAFC969664216386DE2ACFC4096CB00E3E3941DFC856C3C1790BD2C97AD0F0BF76A24BFC480C9543F23113F749818AD8B97F9603873287BBFDF3AA6F570D176178FBB7B0C537ECA21EA04518B3440E4A7DE0D8CC83FF62B5D91A8BD3D45AF74EECEC1D01FFAA4ABAA283CCDB7D50A7CFEA9D7CD98A8A657A3BB003ED1C6BAE25A961DC31DB5850822E871 +valid = true +smlen = 3320 +sm = 5C713BB1755F4A31C900FFAC7AD74AC8ADCC218DDC7B7F2A7655A89CD348461AC84BEDD66DE6D3F9D2D78E6441B2756E31345B4BBC5DBCD8491DAA61080ABE2C108E7EA92D02C5064DAA8447CB982326C83BEF10EBD654C0846A572BF1AADDDAD8AC66DB63E6875150242CB8299433D5DDACD8E9DFF829AD3AF5635795D90E932B05C499B3BDB6A5BEBD3D5B276993606D82855FDDC31CD3233B255A92B6A6BFB78FC673D057D44F555B15B87CB15B16A2B50354237C1DE8BF2CD45CF4D808448B7FA6B554AEB422C4F4666C53BF6CEFD9E57D752509C0D278815116EE858F07D1B924608F76824981FB3D50E43973CB3AE375A337AFCADFEA2F4081C7BE3CB6F89388D2DE94A2565F7ED22BF296916D26B7298E2FD86B993720BC220B827EFB0D3017A8B73A4768E21E2AC437FE462518C199361E141D28F1CFC2117CFEB5E10BCBF402427A6DD1572CFB296D2B145588B82FDF547EC3A08876A9AE7D7980A97671BEBF5A0464B22D49737C677D7B65717A2F368D3E95C8EBFD58EB0412EC7D55AA49DC38DFE6EDD15A814A620A0EFACC6EC38E96F342A8590EAA1B25531FE3E82F85E4F5E46302140D1EE4AEAEEC02CF0274DC7519E3C95AC09C77D5D8BF5821FA9EA276FDD26434B57F838F8DAB472250EEDED38C7D5DCDE7D4850C56C6AEEB9D0690E127E3D530DE6CF11B934E55085E8F89CD72988C93C6B2E9650650D90C561A208BB9ADA1A58F9AE0029B492BFE1A44C99B54DE4226CA44A47C7BB4AB2BBBC0658E9484B6A51FA46E54E7CBF8DD0EFEE828815AAA1986034B78FDDCB51FB41E2BB232E623841350318A427FF8BBEEF53B7B4B51C6F3FF16B7E7D7A5DFE574632AE42785B07027B3E5F9591064EC287D07092EBFE406731AEE43FA17D363564D5078AF8A59A791FB8E3625FA6581BEC1A7DF4F6B36BABEC24ED58878F1AC431CEB7BD690996162642B60860FD8F43E6698A8B9911E7532839827122C5244E0252646F32235DFF933C04AAA92590448254B9E529ADCBB22982DE869BEA2A0035A33F10FE559BA90758F491C2BE1D5D8F1FDCBCCCE193D40658C8FF753700B73ADB2AFA7AC7C38D02D9CBCA3BB6E797FB8C7FE428F0B0B267B2D40A7329C902D90AD4C5D00542C0681DB02A39DBDAC0259E0A36C9ABD6318E709C2ECAC66819F93C6E424ABAB8C58FF53F5251066F8FD9F8B4AF9ADFABCE77CEB0C7D9485FC593C1309D160A5B06896EE147336DB19D8303545537AD166203214C72BB76DF59B4387A6287AE1390DF354E9EB4F8212F7EAEF0EAF486DF611775BEDF64E579CDAC9E982EE9F3FED430A464E513C3BBB40322B786D39E8172D553AE9C1FEFAF85C7032B7EEA351CE428C25A7A77E194415D75F421C0EB37A366E5CFDFD876BF24AA48FCF2F7E194CD79F4E433A5A33EDA08E2C7780E86EAFE3D3A2B37B275CBA8355FB196A5B4FB6C92130C99AE0230EA69A64138A54DAF9E4B7B3C06D898E0C8EDCB0CD47446E587CBE1351E38C18E8F8C913C116DC0A532870012B795F7D8EA90D5B45ECB399B79F10960D46F0E38BBD2AEAA3FE7DC1F0A4A3AF34D93C0A4790D0CAD37CA1B2E8BDD5E19CF95DBDA815171A93371D2FB9F3FA682CA5955EB83EA1AF89A9BE5D1F898EE779BFEBA43D497CD9BF434CA423C6F7EE856133FEF62E88F68FA9C8A3F6919A4DD39A1FBC1755229FC376232630082157273CDE5E44F1ED90268D52271FFE9917026D4E7E435C502C027DBCAD78009F25350F69626E2B367AE951CD9BE2549C865DF0E96876A860567C61F7E9F93D379A78FD0F21BE36BC87BF4111B7E362341AEB39D08E0EBD93F19B9CEE674C3AAA3303B5CCF3EE9A17852A7B2F8F2A2ED4264A418122CB8EC18579A9205838548689ADF6714ED73332ACC7BED58CB4125AF069805553BF17B4624711781466E3D16888FD88B1A207ED140A3D741A0B014556904C24F6CE9BBD5491803131235056AD10EA16F68E5311AD81C3D10DBB10BD15D0437FF942C12DC4F9B0206371820F5669065FCCEFEC40E98C65D58C7283178EB6E03EE178DF912BD2F9BF1DDEF5D0E8BB7C21027AC835A6F4AC405B67C2E00974B183B3B69F4A21E2FB5577CD3FA80A922DBBB2EF9CCC1460FDF886286F98092D1DDCCCDCC1A92FCC2F3C9AA95346E5A8E7F9EE66312A8D6D79B92AFD56E7528D821F9FFA0B2B0105C0946ED8FA93882862A8540E193402F6579A377B5D6BD341D010438D0C8FB181388FFB65E0B2CDCF32155C0B4D6F126EF8A1179EA3541A38EDDE3F1F8E11C09CF92903987B1BCFC0F99C58623DA618A5E92414E714CD545D3DDF46E084596B6FF8FAF0973BE86EF48C8CA973F0A1FC3871A6DD67A691BD3E0DDF1A423B9BEF6181024D0DA29C69E969D43A45512AC0869533041A300C1750A4681A93DDE85C2A7D1ECE439C0CD3965376038269548EB760374909BEB0C46AAC289613C1A8B53AE0698EF0AD4D286CB7637ECB07D20D286EC5187A91F812CB4F99B6DA9B74819A384C04F295DFD4008FE11976FBCC83D53ADABCD6EC5737C1634E704C1B68381788B4BA28DAD170C0AD2A4BC871762F07FD0FFD1D37DEE0F2152672BDC97FB69ACBBE7A0A85FF88019FA51DE355F47DCA0A74EA528E8FB0B29BC04CF70BB18590A03F2B2B725D451B8F5F37CB1A7FF237698194351583217055BAC197FF529B9D8F8B7EA0F78CB12F0BA2BFD9A7DC5BA469AAF8421B01F3242848E801B01CEC65DA9EBC1C1618106F0858F44FB4A81E7C07CD098ED4ACA64FFB0A181B1DBD83F7D3E82C86F02AA805BF888F999D5CCADD1C6DD25B58820F9AFD8B9A53AA93CB32938FE8E0D1B1F04C84D923BB2F76A7EF0CB5F501D5BEEAD7B2D8E84722DBE50084CC715813EDBACEB17AB046C9075F21AAAD399402A9D3606B664D58E992A117E3E92389AC87F39A83EB035A4DF9569F4F171577A67224ECEED4AB6F4C897AAB269DC3FCAA2C36FEEA43587A0BEFC5C2C9EBAE65C103F04B92DC2E0F6A793CE8A13BB5FC14D99F0650806D617CAF9DFD894B036F83B6E01804DE1FF9ADA1B12E0DAC5EF9F95D6468BE6D28B04640EC3BECCEFF1436D7AAF96DA77428D3582AE13D61EEFDA18E3AF9256BCAE31FBAC6DC6C2C8BCA8A1316F9972A82830D2D1A840329DFD4404AF13B99C1FA2528E8B180C9402A79794F5249384166BBD69B703FD4A122A275D415A178A69408A99E1A011C8F820695D955142AAE70549588181573E9096BA3DB75C0F5EF8296C226C9BA3783EBB93CB1FDB09E36B98B67991F583D2F41204823A64CBB18C005A96642E90409229F65C67CE69F4C062604AC8AD1F60DDEEC981D9E0911E1F5E897AB2B94F35487114382C3B71A09A27717A08EB9F87329657C14DA835A4523E7B5D2951031AB26EAA90D3473A850760EA2E2261CF2564531EDE5D4ED3023EA73AB9D98D842492E0E560E01BEFC685277A4B5A53CB4210A5131223B205F7033AA51A6B0546C3D9731A4D6574E612509946D55F47A0F207F956378CA1F4AF2AE9BDA14CEA65EF74D58302136C29659AF7CC753986AECD52563D1CCF9D11EFADF5B5FC108263C2ED24A935A8BF48FE3269F552A9A9659813F94F6EAAFA76AB20F5AF37576409AD6BE15AAEBFEDF66DF5AEC89A98D0E7D549D6BD1C73CABB6C16F6CD1166F517316CBFFE91E5D63371875D6923CDFCDEAFC5A12D7402264FE51ECA38AD1FC0815B688F3FF9D1C42C703EED9F8DF1D4CED289DC635776E3409DF2635930DE118FCC33C3A112C458478D565367643D376248B27569187450ACE30502CB9A85CD55F6D40737B6535278631468D200E08DFBB0D6DC82E420DF310D331D5D3C95CA36AF71FA9871B265464CEB092D427945F94DD13106BB3E2D5B395BA2DC08DD3CC1E1D718A390930E7D078A388DBFC82A84C1AE17BF776F524930A5AAC14FABD97BD8816D2E118DE666864669FDA008D9EF5FC5B321496DA23188CF659C9C51CE39AEFA9906C2A00269BAA823BA9390E3978E5A26C451AADE8974638B4D35C6B781F9E0F4E9D20FC4CE491C9B007CCA5F047AD7158E66A7C43554A5FF02FB8A704751C769264DDAC792BAC252DFC8DC8AE9F7C06578015E8E11C7C94D1BA277F9D2657168B2F3D2BE2FE3DCA8D5C7DD639EEFFD04F94EF21ADE4DE04B845BBB7258DD65CDB99989803CAF5B65127079AEDCDD0B1063CAC8688307FEB4302EA2AC43617F8CC44CBF3274EF928063DBA017D0C9310DBE912A0FFECA7F3B212DEB90DEF7DA2B219426CF68EDD169FCD27321819E0FF163BF467FD53B1F21AAA1C98C13F1751E2D2A0F32A26352C6C7734441AA45BECA811F5D44746C9B3B23C4C3A438E7261A65B5499DC339E2D545E6BD39E7E56CCA44A6B17CCF19876AAEB1BB41E416E755B59F9AC67E65D7ED6D4143837E1CBD32185A8D638F9BED16B49C645DCE9B21D4BC9380ED95C940B4101AB59C7B261BAA867F3A7278758F3E01298B6F08DB2802EC178FA2EEDAE79D4E37A68D9FFD92A8320ED59A8E14C5F32E7837F90D9A142EBC681BA1EE4ACAF2F37C92E80335880D025DDB8D3F8B2D07F2D3C79C5EBBB42229295460DFD2F682A3E497E879BBED50B17274144617486A1D3FA1241467B8A15193B61949DC7496781949EA5A8C40B1141424DCFEE0000000000000000000813181F272E48656C6C6F20776F726C64 + +description = rej_bounded_poly (sample_uniform_eta) requires 3 SHAKE blocks +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 15E04BF6D4209B8C4CFE8AFC2BBE6F9DA39072DB9496502939931B5FA7088ABE7DC282E4E0EFF44CC33246ABA043AE58F5580DC29C245EFABB45931559DFDFA1A07A3BEDFF273A6E47F64D1AC7BA44829494610F96EAAC1F23372C021D743AC1818DD93C7A14D184262239B09BAC038F72DB6972D9569215564F8999ABF3FD1E10532724231011337456217036651077730508052880818760806160751806170164663433355545615283765085350508078377035004151744503252773505805358154735886776704316047452278002678847701405625061721302633630605222112541361513112675864588705573387633224061814414671303134081657868544138322028276384547783275413756702872815400677568001214202382375456844814303101682851070534268540571581148163622044326614713241637578885886688076042150712647888272016447631217734854758706461010102132010432200727240772745010572302410884572815837320233756111343254514166240434577501066220065324845107553075545377005061712315368747721883757147641151826688505572565666738470360700843280884212780241532331107083428008227356265427521111870423565387340043132150503670487182576310665147254247211881342422584452637420407245147372335772840610140835601378568632028445714113182316404243153003634664828555522310627707505836555635567068522055610882231720335571501637870542374813375860826285711778260712664213386600821806047601271701047853517641072285287384574175360828558418302386737766144004173187862802765583086034507322125875850455442624101866863735425067248804547080868362557417160555525363864835873214323638281571522811654242756610601404833175620162368434323240241760340406676662886635261348541564677564767134347333470767883726274868380017331024712582284556055237124305642244743257138887670003742801306036847154153114675437183648505435007528267683453658650852811048417462432337661661375763565056365241780266050387832165651352222571753131486130836850786545355205136833050015157500834722027636561411463025112866261775454665432443068808524023617165344341136130223754366544818018001343845644340522285747182822058742865222674504745137258226160600765466072223318580156368825672771457033343076140880132411186504716000317478847588277168174450437172577880704742002762548507637725135434428731087777884458068582737487178841862785621361663446152340357804006076240324043588184334267526623653547661543221151011367088665308242538635565130125763604378531306611567187036333563846250178870025736642224674342651553430701017761680741423128566050602372512367615727052717441425334046516826113215100452505816581380524441357000406166838682106158821566127226124603083712207388660786721345252340813554546152123500662137500560882778341382084701880670088705108537811203815322225014026064082218866548713232168455686538071862224232266547703654183348330832565518507071868454606436323184778381776211715364782153030587630247811772053211877652166382213612772616075643328111771810731202355883085102132273505526328864443457265846132836137217448686255471417403828411743763451816160662054017700261054811206825807336066367836578746365523872472344048608140551775425681273542677214442075461163541306017276038654506130141817072482646314726228871607758763523228237848337324324301481318756373102431168FDDE3121A2CE8B9F908343221274C3A5780AF7DA8A606BCDE7E3FD50CA079B08991F4D78E3CF1A0C4B20D599003B6930F7E2A93D5AC38E179BFB234471056C9842C59006F9E5531372DD21FF8F3CA81B5B5CDB5BD50B2BA286484F23E7A373E354F21005F7A22EA1DB7CEAC84BF7EAB93955F6F327DCAB2BCB7CAD9D7E16B91314FAB94E9FB67242363CDEBC4095AD6B0DF05BAD4338EE0BE6F214CA0308621CC028E2BFB91B9EC910EDB4FB1761903C4B99DF04C7ADA3DAD8615B1403C58F3E30602088C74C4C08734F6B87B9C1F321F3307BC1CB561BB55E1063B3D76CB82C314E2C87BD27D888EFD6704F106AA68392B7FB6F725FD7D6CA1DA9571609694ADC70E996FF07AD9B9F581CB902F8054D49532ECA9B67337D81FC8C1A903A4CE8D4566D0C66CDA5B6DB030B7E132901B0F7ED4F86585B67370D79D0B399B69A64EE975F610D8EDE730802B42CAAAC63D2F2F575C2A5BC6E6C92084825295322FC73E54D56312964B3B21747E0995E1B778709A5ED4992E3991D805CFD0329295B680EE003E06A17C374B852246F2800B83CD9226EF275AFBC3F4C6CAFD1DC768E439FD05B768A87B095F864AE9BBF7137832DE3267311C27E3AF6C6834ED3C351C4F0078B66A859D38C0C81138C3FA136D70D1EE7B56B938A30C1E39B4DFA5EC11453A13B8CEB3B40DC8BA90BBA993BF53CE4CE870C94A5429FC6021F35898339D1D5A39D3FD24E2E8B1E8242B4EEC35DC61435972FD47C6618BD725DBD7986D56071466448C96506542E48C6406DA3F624A7C063C09D9137A1ECD7AC8B5B1FD7160C69B52D5207A0E3551D0DDF9F18F61C147595E64D8B6FCD5D63289F5B2B4A4259CB7ACC3E00BC31F17C5D9BC7765F31F6DFDD11F125BAE25CE496FDEC9358DD336D7C58394982113215EB11A461096523990802DD281A4BD5DDF286734D92ECA02E26936C0D83AC4D1A22F6477E9DD132ED558F7FA8E1730F1FD9D2E7D23E395CBAAE84DEC2FE0380CD7C2B55B89FF333006C4916F0C5E5F7970601F1ECB79024BD16A82169992047870C2B1A0C4E98065BF9F6DD3142DC941DB338B65E2A917E7006C8A1B80E08C490EF19BEF13A523ED0E49930069F896CAFDA87A52BABC37081148F0213C702B6D84A550A18658957BDC1231A097A7FF5C6B6D1FE4D656231E862D40257DCD8F1789E670DEE04E43B721CD45F43BEA66036D1BA9A2AD594DA042C4C6D0E41477C566D51C358BED1848ECAFD34436EFFAEDF22880957EBAAA882B52FDAC499E9838BE416F1A119DB4082B1DB0C792BADAF50B8370CDD8972D7AB35452F66BA6FD7C0EA74787993B1FD8FB674A2F89772476F272A128658579E5A72469C09589ABB4F896CE2C894D0A5C2A23955D98F2E6620C4BB2B852DBE7BECBD3700DB42A98849E05602B01707E27F0A1E0EAFAED579D6F5195D5D28D48CAF839E3E07A3512B8432ECA403D16B6AE1BBE6599C1F9945CED437F2A1B59E209E242C8005350270BC3DBE7ACDD0EC5B4E596716B8A4366AD46AA33FA521A051F78715EC593DCA870C69D0391C0D6A0DC3BD881C57B6DA009B8B4CA2A4D3161A9121899B4B602E13CEC5DE361440C25F91213D2194475BAC036D7AD82E48E5319F14271EA5B7580D55020CF0F978F824D0D8CF9F723F3BCC48519F594663644F2A1E1ADD9BC665FFE92E841666BF1414C3F06E35DC895B825E944A3C397FC8AADB7BE46E36F3A1C3D6DF6271E4C71ABA786970DEAE48F1C5BF48E2DE014BCBF78C2DDD8B32886AD3284F0E106AB19550B3404F5B8D5D54D85E28EB231D3DB947FA09E3BBDB40315C7B6FF8B9A3E7373744E4B656F29D741D72A2700A2CBB135B2B69440399258E0D61418ABCAFBABDBC5EC01AB321F0C675E234D9B2F1BC1C4A00CFC085CBA1AFA87D42626D5DB4577FF26435EEBFB9D4F31B33453D28028BAE26B5936F30B9149F2EF68B129A0B03885CD3D756CFAF03614ACC1096016DD8D738B76A813EB37E8C4100AF4BF0248C7B4929EDFAA6121F6B7E10CD25248709E8F0D17C20649095051FFDE01C49C42C1D34CA0E406F26ED67D1812463DF2CDAC5160F98F09CFDB917FCCEFEF409D4C2BEA9BF166CC43CDA18C14834273EE057052E5B47973ED8F2AD7EE25A2609B8DCD4B95A7F0E55ECE59CCEE4863EDC434942847F813F85F620379FFED7835E845A3E6F6986DF0B6F0A08FD789AE711FE20959714BCAB4ED1B5B610508AF507234B143ADC6BE34E4B4737042CEB3E21FF9D5A336DF1E60278566A7706E7A12F604ACB66C06C3FF43DE33384BA106BB304913816FEC66A51EBAB43EB0167CA37A0D5657398314628937D2E942994E6C1783A43D127258261A905B04144ACD6A196B5E22FDEA526FFC63535D6194EFCC2D4E10647BE22CA36A8D3F7FC1E897E9C8444D06953DA8D6179E3662AC0B2E6495222E7F64751A9D178397DDA874C2B0FD30FDDD92A48171FE2697214723CAFC21CCCF314F0F4C24795854560807AD9AE4C873A4BF85B5AED6B711950C726CCBD1A972CF7D931BC50C5D60C9DC48E6B5721B31C1309C562C18DDD494575D023E99E0BE15DB11905262209F72D747690372191AD742D56D09B9CB48F7CB2A47C0E39AF54EF94F875CB9F7FF352BA89831BB248670B267098A27888BA6E594E56EF860D3FFF472032354E8A5B77A5AC3C804DAD988CFE0F60C9FE8915AA2454893E35B8001D5E8E3BBCC3F018DFA31DC73187FDC623A11ACEB969539A6CA0132C8311A047E21CB924F24D469F1C8B6319A8B4CEABFDE66409B8B140B3A4E01F02683FEB9BF74C5A3BEB86401E8EF4CCC37DDF7D44D5C71296B72351D7857A15D7424190C972FE69053389EF39F3FA5D91FCFD4118FAE269167CEFDF260932731EC8ACC81414ACDEA52FC926C6635BE4EED57ACB95047EB0DD30C82F3428023B72AFF6CF99338C1F8873F122C52C2DA7051AA2A306A778C361AC98AADFD73BBA2B9AC06125F18F6E64FE99DCC195E02085F9EFBC12E064F296AEFE6A81988B07C68E0903484437CCB45960CEDF23302BCF3524EBC89D47E6E797D738D62BEECACD4022312B3973612DC31DA40626867604F00733FA781B435ADC2E8DF5CAC855DF761C4C620616B895915CFB98074390D2E813362770C7C3EE14AECB979333580257AB1BB44B2DCB9D1D3C003E71C29DB1D45E5ED80706AA3B3AD49BA918B15E79DEB544D9920E70D0982594EA0AFEA60514D18A5101BF50386E6C2E96DA7C7E0E71FD498A3E9828245CAF0C9992642F3D85D1C1A530FDF83887E8234AC4E338C4640C1B77C773CEA2A39849D7A2B7874184AE65A073C583436F17AA85980D1D6497DA62229F6FA8914302CE450B56E58AAC3B585CCDEF36FEE8467D71B65C597CAC0F5AA21CE36735E1AC2EC9327132D988939B90CAE7E2CD67D9D80D7E899189688E6D9C5760A19543DE2085C269102534498536A6C6B4568FCCD18991DC035742415D16B27DEE0A3DD5F845153A6820B456AE74527D43D27F817506BAB9D7A912E7 +valid = true +smlen = 3320 +sm = 0C75BEB55DB356144146BDC41A5FCDB1EE2FD32FEB0F4A37458617B6B02CF5363B96B58166AED22162D54823970D25ADE5E22205AF1D387F455A30429E53A1186B03D5568785893DFE81FA7FB28AD50F8B547BE838D4E57B1D6AEC98CA75161F3DD8AB552B417BC573495F1E59B3AB692EAA7F4D30C6F3A02474A1D01D156F3A0CAA81C2CA9B2C65D1619C148B226463428085F7EAF1BBCD491F1BE100C93AD8A9C33E57EBB76F8B57BB603534D1930C1BCB17D2036D44E7C37D88FE3CB0D285E0F8D275D8BB44827D7CFD23EA6468CB4AB3C53B19DDAA2E4E688A33A4303E6A57E1DB745F3DB0DA5E3301C4290B4AB8CB42A0F8B3E1CB63C29FF943CC4DFAC41C8A9C2ED987D8F3012CC4550E19CE99366F0700341B86103A1FC81EA1FC0F49C66EA638319F1BBDBBAEE13175E06954CE060870055C5E861BFFCA5F706424891627B43E92C92815CC4A093BF794BF528024DFA927998AE93898CADF1F2D680A4F26E77E749DB84231EE587F3EB82A6EEE42498FBA367BDA88C7A066E25C47453E1269DE4EA56ABAEDC0D2E7040636F8207FCB7E6273F2F43F557CB56680214CA86B1D5F6E774D699E9B7E85D32B7C0CBE31F2E8B4188B7C8BFBBDA09F1C70018F3BD73EF365F8BBBA82B461B78CADB3D0CBF9CA4B418472CC424860DC81DD2549D3503BF93E293929F7F83C2D576709CCD291A8BD4C7D9B4A9A5F64A8F2F20413582611888FEAFD5757F851609B5C7B00E9AD93A4BEAE2E21B1F65519C7D068A29F4B2DB0B2A61E676ED721B153E2A7818BDD624978D6F71C582E04EA2BB81C23047B463C808E3F3220F5DE8E161E6B37336BE5E635F0FCF31777C341C7F46C5144E1097B90E44BC8EE6672CBEF59924D841D7FAF0E0495122C98A1AD1004165AB89462137D9D35330239C438FA864EEF96467B6F3B17DE011BB72B57C38482EB527DEB3EDAE42DCBBAE0F2202793C76E0458B60DDF7A59E0438CEE78736C4649C3AA96D798A4103471AE967E93DC657848BEB0F22D997E9E6F97CE3C42BBA7DA71F3BC7C95EFB98B6739F5E88B37BFFEA5E6CCF39AF2A97223249F89655BB0DF36C1A6C88B613C1E3768C1087D2ED5662E12D4CEE9D95F1F5296902CA56EBE44E37B74E9782637E4DB29B300CC217E9E2258C57E8FCC4DAA69F39BE21F6E0FED143CA5E7AAE26057CD622C14AE735F020833C75B9DF4DAB14A5C75B1E1DABF4D3075E0AF0CCE8A7D85E0B32E1E4F361D9653BA38DB3469D01A957716C851D70EB39BBC5747E7A5A45FFF6C6E3B0B8B9D76126FDE2F65E956339ECA35FABB8F28F905C81510DC1D63F3364FFE9B0588F37DDAC2630B3700CD627B48B747364BC96DDEAB281AB27D5D591D5CF240FD7D5B49B66C8E48072A816D5A218359B1C030160CA0BFFD77CACC7C583E4363EBD2C3BD6BF0F8ECE2B2B5651B718567E36D5D5266CC38D85C453D169AAF0EA1830EF7B944F5997B0FF94E6444CEEDF5B5D5288DFB75CBCFFB789CA8613268D659320F449E3E4D75B03A1AD31305C08AA319E8845A05C21D8A20B4E84A46AC75A83674C2421D02D9FC2F0808D42A46A247D84DAEA362079EFBF7830C4C3CBE8FE47D31524704417590631FC67E93264E5855D8CD3344E65DE204A5EAD08148AE674F8423D2468707BA27B4BD14CE3CB51E60BB5C35016BAEFFFEC2ED017C2517DD18675A5B8D9E0055C2E9DF3EFFD128ECF88A2EA1A302154B2B7E3268068501334B0245FBE10651A2EC76917B82D5DCE274E9570902F42A76277DCE44793191BF15D2A3AEA4CD7B403AEE4C0FEEFC7D8121C686398E46ECBAF55248085FFEFA3D9A8E96AB48A7DFCDB7BD9CBA7AF25278A449562AC1CB5084CF79C42376D68268FF53EB377C7207CFEA631376CFDCFCD207A2B10A3CCF2A6DFDA0CE55E15479A50730BA664EA4A09B412B3FBE6BD6E3D0E81AF22080D8E94D685225F2F69B39B0AFED4099702A602771CCEAF6DF0AE8C7E7EC972F883AF6AA711DE81AE0E83E5494B6926BC26C8AAC103BC030749BBE655BC85D85B39135A0D3D5AF23026357E5E4D30103D012CA37E59C0920278F9E3D84021011E0C3AD7FF90A677905FFD78817E4CDD36D20DA46E15CB48351CF468C138C6F16EBDCAD4A91692285659A99D468949E3B53FA0CBEED3BB148ED404DD6D1BD65CBAB046F16A633CA0EDED57A3B66FD8B36297ABE19916CB604F1FB08589434C8ECA083877AD3A1F799C41D4E187148548C7414469EB48E0623363EEFA18EF0160A71EAA3534C81FD171BFB0F604FBEB14BFD178F640C4FB79B79093EB8BD11E81DD6E3ADCF0E7B2EF540A8C14C310849FD065CBF97D027880AB6E81709C4594E6965079EC77F823F22C1F41BA5D46EAB14E11E7931AEB2DBDBC631F0C764A3A84D8D9A32809A1F18386CD583C2F86BF644C912A969656E6B215F0C8584695C2FD559D60289C12C9642B6F9B9E92E3BF5707321C8D8125680A026757FD487058AAEA659DB79AA3AA0A8BD4DE34A5C412FB534B0C9FEEC86A49E9A2942C3F4F6A2E006DBEC02BBBB7231FE9104D170B7A6DEFC30EC60BAF66E8DF7FC2725AF9CF347871DA7ACE0084D13F98A6F42E6FEB6F7DDBE30FEBC3C8518FA81E0D233AB4A5EE54D90E64C4CC0D82E6903253AD3500DEF856B50E46FD59E3AF48BB3D0FB9AEFDFD8BF4B588A1137205855BF16DEEEEABD1005A9FFE0BC1E59612EED56A544A0E5ABB3480E066FD551A273F2B04BE332F3DD1096F73D7C0D4992DACA9CD3EEB256F7C9729D1344978978701B307402AC9974257A2603A77DCF6E0AA186B7AE11BDAB8B5E85196922739DDB109E7E0DCC80305599F19B90F5D0C0BDEF9FC8B443E46260A8EBFC3C8633DACEA35CB51C02E1CE6E87C788744FF47F2BA48FE8C73A3DF66A9B7752CC041D2A0B89DF7306CD85AC666A71CE8F38ADEE5E9EDD9DF90639432BC2EF67664FB02E388B88E95AEE0549578F7398A18296AB9B3DF35A9B497C9A41D0042B5B66C593E353C94E3D8DDF031B3A3D071409F92498651F86047F1656665FE076730B3465AD551F7026CD30B938EDE716DAF4F85AA3FE6AC76EA240861E4E222FA034B18AB54CE04C476ACFFCC4ED9B79304516E37F2A1EEB5116FE4A81A73268254EF02E85A82C6F921C73064011A421F3310389DA4A05E28AA87D3EE9D2ED5551BE90D1BD58935CB38FDEF9EBECEED1ECCE29D20D2CFEDD85F4AFE0DB902C615EFCFCF180098839CD6EB7ACD8927B397EB0F0D70B19D0D4CFCDA80AB4A5DEB950101E7724C9D848374EBFC97EC72D5C30C6ACD158CC864F5168E1AFD4C99CED7F8343719454357A33C3A519001D76055F5D95F13365E1F7FB97674094CA62986DE4A0D87BFA4BEE1E655C3E72736A899576262EBD782485EB7BC4834822E004379A971D54665CD498F1F599E7FA4E7041392D243940698957A31DF79CE06E2B6DF3D5D37E6B94D81B056C129C35CCAEF3438C5104E1154C6BC976936EE6622CBA189496CC62F00B4B087ECC6256F125C840DD54C364530A159FFFAB8DFBA9874DF3EEFFB1943489101DB83DF904B7E2E3DA5AEB29A9714453D36568646BA43D102189BFD90D473CE5E5E213B5C6118CC22AFAF826EAF6536AF5E861B6C832553C3A7FB1522CAA688792B3E47FB5E9E1CB762D5113B5FB8726D166E3A7C7EAC734E23BB44754FDDB0487BEE9312E738E415BC66DA00276D3E3C48606D733F2216BB322C5BD28F90A35A41B0F3C56F20F53C923E86ED7629740B6EF27CD51477F140E1507C9162C508AC4DE2CD6543E6E68EADDCBE026FA177CDEFBD91ECF8D782B480E52B8C180349654E495BFFB2284573A1DFCC21FF7046448D6D7E5AD3743D7C98E4C56655E88DAF7BD293961277A5283620ACC979C39EBCD8B59E9683A8D84D361A904DDAB46BC06C64D03B48CE4356A494AD4786C9859551B52EF99229C846B8F9DDB12C0130198CE92468F103C8660A3FDC504C749E89B7247C9C0F8D8CA4CE188D1E03CF3C3BA8444D96C84006AB4572C45896D5F521447610C0A12EE91AEC667368E3CF88883E9F4DDF456812AB0589EBDA1D8FAED0CE6E3CE7389C7559993D3192ECB2E6E3D17E900E2CD1C9129440294467036C82D1261296FB479441CBDE0BA2EC5C4390E72BABA6B88A349FA5A13F5AB49241A8DB7C0BFB12DCFDA0346CC3414041DC78D50D44118523BC34C07B3E2AD92A918B96F294E8AA212C65638A3D3A869EB90F334AE7FCD387034F00CF5F6FCEEC7C9A0F5DF4028DC63A1AC408D4570656AFB0BE4321BA047B998F24177BE997B0E47C2010656BE55C84B685729AE5A3230ECEF2C92CB660383A989CBC9DF9B6EEB8DC2577D12FE6A3D0989E3A60B88422D42BD75F1A7AC8391D57B5268BB41B9ED5C4B0CB9EDF76454693FD604B1F4B2F6425A71A1C8A587F18691ECF2DA6A6EE366D50E05239655D02A4CF110571EC706F9E6A6F059472C39DD2D53EA9F311A89D735E1B8B19953849E0689E2880EA5D94E3D97FAE414DB347ED1B26EEED05DF3C7D8FBA6AF4316E79F890654CCC61D6549524A51783F2412E8EF0E37DB33D6B1B2BC9ADC84227866AE18AD9F987FF8010717395389BC163072A1A2E8082D3B5372758911477DB0DDFE254867A9B417186CE3E400000000000000000000000000000000000000070D141A1F2448656C6C6F20776F726C64 + +description = expand_s requires 23 SHAKE blocks +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 15E04BF6D4209B8C4CFE8AFC2BBE6F9DA39072DB9496502939931B5FA7088ABE7DC282E4E0EFF44CC33246ABA043AE58F5580DC29C245EFABB45931559DFDFA1A07A3BEDFF273A6E47F64D1AC7BA44829494610F96EAAC1F23372C021D743AC1818DD93C7A14D184262239B09BAC038F72DB6972D9569215564F8999ABF3FD1E10532724231011337456217036651077730508052880818760806160751806170164663433355545615283765085350508078377035004151744503252773505805358154735886776704316047452278002678847701405625061721302633630605222112541361513112675864588705573387633224061814414671303134081657868544138322028276384547783275413756702872815400677568001214202382375456844814303101682851070534268540571581148163622044326614713241637578885886688076042150712647888272016447631217734854758706461010102132010432200727240772745010572302410884572815837320233756111343254514166240434577501066220065324845107553075545377005061712315368747721883757147641151826688505572565666738470360700843280884212780241532331107083428008227356265427521111870423565387340043132150503670487182576310665147254247211881342422584452637420407245147372335772840610140835601378568632028445714113182316404243153003634664828555522310627707505836555635567068522055610882231720335571501637870542374813375860826285711778260712664213386600821806047601271701047853517641072285287384574175360828558418302386737766144004173187862802765583086034507322125875850455442624101866863735425067248804547080868362557417160555525363864835873214323638281571522811654242756610601404833175620162368434323240241760340406676662886635261348541564677564767134347333470767883726274868380017331024712582284556055237124305642244743257138887670003742801306036847154153114675437183648505435007528267683453658650852811048417462432337661661375763565056365241780266050387832165651352222571753131486130836850786545355205136833050015157500834722027636561411463025112866261775454665432443068808524023617165344341136130223754366544818018001343845644340522285747182822058742865222674504745137258226160600765466072223318580156368825672771457033343076140880132411186504716000317478847588277168174450437172577880704742002762548507637725135434428731087777884458068582737487178841862785621361663446152340357804006076240324043588184334267526623653547661543221151011367088665308242538635565130125763604378531306611567187036333563846250178870025736642224674342651553430701017761680741423128566050602372512367615727052717441425334046516826113215100452505816581380524441357000406166838682106158821566127226124603083712207388660786721345252340813554546152123500662137500560882778341382084701880670088705108537811203815322225014026064082218866548713232168455686538071862224232266547703654183348330832565518507071868454606436323184778381776211715364782153030587630247811772053211877652166382213612772616075643328111771810731202355883085102132273505526328864443457265846132836137217448686255471417403828411743763451816160662054017700261054811206825807336066367836578746365523872472344048608140551775425681273542677214442075461163541306017276038654506130141817072482646314726228871607758763523228237848337324324301481318756373102431168FDDE3121A2CE8B9F908343221274C3A5780AF7DA8A606BCDE7E3FD50CA079B08991F4D78E3CF1A0C4B20D599003B6930F7E2A93D5AC38E179BFB234471056C9842C59006F9E5531372DD21FF8F3CA81B5B5CDB5BD50B2BA286484F23E7A373E354F21005F7A22EA1DB7CEAC84BF7EAB93955F6F327DCAB2BCB7CAD9D7E16B91314FAB94E9FB67242363CDEBC4095AD6B0DF05BAD4338EE0BE6F214CA0308621CC028E2BFB91B9EC910EDB4FB1761903C4B99DF04C7ADA3DAD8615B1403C58F3E30602088C74C4C08734F6B87B9C1F321F3307BC1CB561BB55E1063B3D76CB82C314E2C87BD27D888EFD6704F106AA68392B7FB6F725FD7D6CA1DA9571609694ADC70E996FF07AD9B9F581CB902F8054D49532ECA9B67337D81FC8C1A903A4CE8D4566D0C66CDA5B6DB030B7E132901B0F7ED4F86585B67370D79D0B399B69A64EE975F610D8EDE730802B42CAAAC63D2F2F575C2A5BC6E6C92084825295322FC73E54D56312964B3B21747E0995E1B778709A5ED4992E3991D805CFD0329295B680EE003E06A17C374B852246F2800B83CD9226EF275AFBC3F4C6CAFD1DC768E439FD05B768A87B095F864AE9BBF7137832DE3267311C27E3AF6C6834ED3C351C4F0078B66A859D38C0C81138C3FA136D70D1EE7B56B938A30C1E39B4DFA5EC11453A13B8CEB3B40DC8BA90BBA993BF53CE4CE870C94A5429FC6021F35898339D1D5A39D3FD24E2E8B1E8242B4EEC35DC61435972FD47C6618BD725DBD7986D56071466448C96506542E48C6406DA3F624A7C063C09D9137A1ECD7AC8B5B1FD7160C69B52D5207A0E3551D0DDF9F18F61C147595E64D8B6FCD5D63289F5B2B4A4259CB7ACC3E00BC31F17C5D9BC7765F31F6DFDD11F125BAE25CE496FDEC9358DD336D7C58394982113215EB11A461096523990802DD281A4BD5DDF286734D92ECA02E26936C0D83AC4D1A22F6477E9DD132ED558F7FA8E1730F1FD9D2E7D23E395CBAAE84DEC2FE0380CD7C2B55B89FF333006C4916F0C5E5F7970601F1ECB79024BD16A82169992047870C2B1A0C4E98065BF9F6DD3142DC941DB338B65E2A917E7006C8A1B80E08C490EF19BEF13A523ED0E49930069F896CAFDA87A52BABC37081148F0213C702B6D84A550A18658957BDC1231A097A7FF5C6B6D1FE4D656231E862D40257DCD8F1789E670DEE04E43B721CD45F43BEA66036D1BA9A2AD594DA042C4C6D0E41477C566D51C358BED1848ECAFD34436EFFAEDF22880957EBAAA882B52FDAC499E9838BE416F1A119DB4082B1DB0C792BADAF50B8370CDD8972D7AB35452F66BA6FD7C0EA74787993B1FD8FB674A2F89772476F272A128658579E5A72469C09589ABB4F896CE2C894D0A5C2A23955D98F2E6620C4BB2B852DBE7BECBD3700DB42A98849E05602B01707E27F0A1E0EAFAED579D6F5195D5D28D48CAF839E3E07A3512B8432ECA403D16B6AE1BBE6599C1F9945CED437F2A1B59E209E242C8005350270BC3DBE7ACDD0EC5B4E596716B8A4366AD46AA33FA521A051F78715EC593DCA870C69D0391C0D6A0DC3BD881C57B6DA009B8B4CA2A4D3161A9121899B4B602E13CEC5DE361440C25F91213D2194475BAC036D7AD82E48E5319F14271EA5B7580D55020CF0F978F824D0D8CF9F723F3BCC48519F594663644F2A1E1ADD9BC665FFE92E841666BF1414C3F06E35DC895B825E944A3C397FC8AADB7BE46E36F3A1C3D6DF6271E4C71ABA786970DEAE48F1C5BF48E2DE014BCBF78C2DDD8B32886AD3284F0E106AB19550B3404F5B8D5D54D85E28EB231D3DB947FA09E3BBDB40315C7B6FF8B9A3E7373744E4B656F29D741D72A2700A2CBB135B2B69440399258E0D61418ABCAFBABDBC5EC01AB321F0C675E234D9B2F1BC1C4A00CFC085CBA1AFA87D42626D5DB4577FF26435EEBFB9D4F31B33453D28028BAE26B5936F30B9149F2EF68B129A0B03885CD3D756CFAF03614ACC1096016DD8D738B76A813EB37E8C4100AF4BF0248C7B4929EDFAA6121F6B7E10CD25248709E8F0D17C20649095051FFDE01C49C42C1D34CA0E406F26ED67D1812463DF2CDAC5160F98F09CFDB917FCCEFEF409D4C2BEA9BF166CC43CDA18C14834273EE057052E5B47973ED8F2AD7EE25A2609B8DCD4B95A7F0E55ECE59CCEE4863EDC434942847F813F85F620379FFED7835E845A3E6F6986DF0B6F0A08FD789AE711FE20959714BCAB4ED1B5B610508AF507234B143ADC6BE34E4B4737042CEB3E21FF9D5A336DF1E60278566A7706E7A12F604ACB66C06C3FF43DE33384BA106BB304913816FEC66A51EBAB43EB0167CA37A0D5657398314628937D2E942994E6C1783A43D127258261A905B04144ACD6A196B5E22FDEA526FFC63535D6194EFCC2D4E10647BE22CA36A8D3F7FC1E897E9C8444D06953DA8D6179E3662AC0B2E6495222E7F64751A9D178397DDA874C2B0FD30FDDD92A48171FE2697214723CAFC21CCCF314F0F4C24795854560807AD9AE4C873A4BF85B5AED6B711950C726CCBD1A972CF7D931BC50C5D60C9DC48E6B5721B31C1309C562C18DDD494575D023E99E0BE15DB11905262209F72D747690372191AD742D56D09B9CB48F7CB2A47C0E39AF54EF94F875CB9F7FF352BA89831BB248670B267098A27888BA6E594E56EF860D3FFF472032354E8A5B77A5AC3C804DAD988CFE0F60C9FE8915AA2454893E35B8001D5E8E3BBCC3F018DFA31DC73187FDC623A11ACEB969539A6CA0132C8311A047E21CB924F24D469F1C8B6319A8B4CEABFDE66409B8B140B3A4E01F02683FEB9BF74C5A3BEB86401E8EF4CCC37DDF7D44D5C71296B72351D7857A15D7424190C972FE69053389EF39F3FA5D91FCFD4118FAE269167CEFDF260932731EC8ACC81414ACDEA52FC926C6635BE4EED57ACB95047EB0DD30C82F3428023B72AFF6CF99338C1F8873F122C52C2DA7051AA2A306A778C361AC98AADFD73BBA2B9AC06125F18F6E64FE99DCC195E02085F9EFBC12E064F296AEFE6A81988B07C68E0903484437CCB45960CEDF23302BCF3524EBC89D47E6E797D738D62BEECACD4022312B3973612DC31DA40626867604F00733FA781B435ADC2E8DF5CAC855DF761C4C620616B895915CFB98074390D2E813362770C7C3EE14AECB979333580257AB1BB44B2DCB9D1D3C003E71C29DB1D45E5ED80706AA3B3AD49BA918B15E79DEB544D9920E70D0982594EA0AFEA60514D18A5101BF50386E6C2E96DA7C7E0E71FD498A3E9828245CAF0C9992642F3D85D1C1A530FDF83887E8234AC4E338C4640C1B77C773CEA2A39849D7A2B7874184AE65A073C583436F17AA85980D1D6497DA62229F6FA8914302CE450B56E58AAC3B585CCDEF36FEE8467D71B65C597CAC0F5AA21CE36735E1AC2EC9327132D988939B90CAE7E2CD67D9D80D7E899189688E6D9C5760A19543DE2085C269102534498536A6C6B4568FCCD18991DC035742415D16B27DEE0A3DD5F845153A6820B456AE74527D43D27F817506BAB9D7A912E7 +valid = true +smlen = 3320 +sm = 0C75BEB55DB356144146BDC41A5FCDB1EE2FD32FEB0F4A37458617B6B02CF5363B96B58166AED22162D54823970D25ADE5E22205AF1D387F455A30429E53A1186B03D5568785893DFE81FA7FB28AD50F8B547BE838D4E57B1D6AEC98CA75161F3DD8AB552B417BC573495F1E59B3AB692EAA7F4D30C6F3A02474A1D01D156F3A0CAA81C2CA9B2C65D1619C148B226463428085F7EAF1BBCD491F1BE100C93AD8A9C33E57EBB76F8B57BB603534D1930C1BCB17D2036D44E7C37D88FE3CB0D285E0F8D275D8BB44827D7CFD23EA6468CB4AB3C53B19DDAA2E4E688A33A4303E6A57E1DB745F3DB0DA5E3301C4290B4AB8CB42A0F8B3E1CB63C29FF943CC4DFAC41C8A9C2ED987D8F3012CC4550E19CE99366F0700341B86103A1FC81EA1FC0F49C66EA638319F1BBDBBAEE13175E06954CE060870055C5E861BFFCA5F706424891627B43E92C92815CC4A093BF794BF528024DFA927998AE93898CADF1F2D680A4F26E77E749DB84231EE587F3EB82A6EEE42498FBA367BDA88C7A066E25C47453E1269DE4EA56ABAEDC0D2E7040636F8207FCB7E6273F2F43F557CB56680214CA86B1D5F6E774D699E9B7E85D32B7C0CBE31F2E8B4188B7C8BFBBDA09F1C70018F3BD73EF365F8BBBA82B461B78CADB3D0CBF9CA4B418472CC424860DC81DD2549D3503BF93E293929F7F83C2D576709CCD291A8BD4C7D9B4A9A5F64A8F2F20413582611888FEAFD5757F851609B5C7B00E9AD93A4BEAE2E21B1F65519C7D068A29F4B2DB0B2A61E676ED721B153E2A7818BDD624978D6F71C582E04EA2BB81C23047B463C808E3F3220F5DE8E161E6B37336BE5E635F0FCF31777C341C7F46C5144E1097B90E44BC8EE6672CBEF59924D841D7FAF0E0495122C98A1AD1004165AB89462137D9D35330239C438FA864EEF96467B6F3B17DE011BB72B57C38482EB527DEB3EDAE42DCBBAE0F2202793C76E0458B60DDF7A59E0438CEE78736C4649C3AA96D798A4103471AE967E93DC657848BEB0F22D997E9E6F97CE3C42BBA7DA71F3BC7C95EFB98B6739F5E88B37BFFEA5E6CCF39AF2A97223249F89655BB0DF36C1A6C88B613C1E3768C1087D2ED5662E12D4CEE9D95F1F5296902CA56EBE44E37B74E9782637E4DB29B300CC217E9E2258C57E8FCC4DAA69F39BE21F6E0FED143CA5E7AAE26057CD622C14AE735F020833C75B9DF4DAB14A5C75B1E1DABF4D3075E0AF0CCE8A7D85E0B32E1E4F361D9653BA38DB3469D01A957716C851D70EB39BBC5747E7A5A45FFF6C6E3B0B8B9D76126FDE2F65E956339ECA35FABB8F28F905C81510DC1D63F3364FFE9B0588F37DDAC2630B3700CD627B48B747364BC96DDEAB281AB27D5D591D5CF240FD7D5B49B66C8E48072A816D5A218359B1C030160CA0BFFD77CACC7C583E4363EBD2C3BD6BF0F8ECE2B2B5651B718567E36D5D5266CC38D85C453D169AAF0EA1830EF7B944F5997B0FF94E6444CEEDF5B5D5288DFB75CBCFFB789CA8613268D659320F449E3E4D75B03A1AD31305C08AA319E8845A05C21D8A20B4E84A46AC75A83674C2421D02D9FC2F0808D42A46A247D84DAEA362079EFBF7830C4C3CBE8FE47D31524704417590631FC67E93264E5855D8CD3344E65DE204A5EAD08148AE674F8423D2468707BA27B4BD14CE3CB51E60BB5C35016BAEFFFEC2ED017C2517DD18675A5B8D9E0055C2E9DF3EFFD128ECF88A2EA1A302154B2B7E3268068501334B0245FBE10651A2EC76917B82D5DCE274E9570902F42A76277DCE44793191BF15D2A3AEA4CD7B403AEE4C0FEEFC7D8121C686398E46ECBAF55248085FFEFA3D9A8E96AB48A7DFCDB7BD9CBA7AF25278A449562AC1CB5084CF79C42376D68268FF53EB377C7207CFEA631376CFDCFCD207A2B10A3CCF2A6DFDA0CE55E15479A50730BA664EA4A09B412B3FBE6BD6E3D0E81AF22080D8E94D685225F2F69B39B0AFED4099702A602771CCEAF6DF0AE8C7E7EC972F883AF6AA711DE81AE0E83E5494B6926BC26C8AAC103BC030749BBE655BC85D85B39135A0D3D5AF23026357E5E4D30103D012CA37E59C0920278F9E3D84021011E0C3AD7FF90A677905FFD78817E4CDD36D20DA46E15CB48351CF468C138C6F16EBDCAD4A91692285659A99D468949E3B53FA0CBEED3BB148ED404DD6D1BD65CBAB046F16A633CA0EDED57A3B66FD8B36297ABE19916CB604F1FB08589434C8ECA083877AD3A1F799C41D4E187148548C7414469EB48E0623363EEFA18EF0160A71EAA3534C81FD171BFB0F604FBEB14BFD178F640C4FB79B79093EB8BD11E81DD6E3ADCF0E7B2EF540A8C14C310849FD065CBF97D027880AB6E81709C4594E6965079EC77F823F22C1F41BA5D46EAB14E11E7931AEB2DBDBC631F0C764A3A84D8D9A32809A1F18386CD583C2F86BF644C912A969656E6B215F0C8584695C2FD559D60289C12C9642B6F9B9E92E3BF5707321C8D8125680A026757FD487058AAEA659DB79AA3AA0A8BD4DE34A5C412FB534B0C9FEEC86A49E9A2942C3F4F6A2E006DBEC02BBBB7231FE9104D170B7A6DEFC30EC60BAF66E8DF7FC2725AF9CF347871DA7ACE0084D13F98A6F42E6FEB6F7DDBE30FEBC3C8518FA81E0D233AB4A5EE54D90E64C4CC0D82E6903253AD3500DEF856B50E46FD59E3AF48BB3D0FB9AEFDFD8BF4B588A1137205855BF16DEEEEABD1005A9FFE0BC1E59612EED56A544A0E5ABB3480E066FD551A273F2B04BE332F3DD1096F73D7C0D4992DACA9CD3EEB256F7C9729D1344978978701B307402AC9974257A2603A77DCF6E0AA186B7AE11BDAB8B5E85196922739DDB109E7E0DCC80305599F19B90F5D0C0BDEF9FC8B443E46260A8EBFC3C8633DACEA35CB51C02E1CE6E87C788744FF47F2BA48FE8C73A3DF66A9B7752CC041D2A0B89DF7306CD85AC666A71CE8F38ADEE5E9EDD9DF90639432BC2EF67664FB02E388B88E95AEE0549578F7398A18296AB9B3DF35A9B497C9A41D0042B5B66C593E353C94E3D8DDF031B3A3D071409F92498651F86047F1656665FE076730B3465AD551F7026CD30B938EDE716DAF4F85AA3FE6AC76EA240861E4E222FA034B18AB54CE04C476ACFFCC4ED9B79304516E37F2A1EEB5116FE4A81A73268254EF02E85A82C6F921C73064011A421F3310389DA4A05E28AA87D3EE9D2ED5551BE90D1BD58935CB38FDEF9EBECEED1ECCE29D20D2CFEDD85F4AFE0DB902C615EFCFCF180098839CD6EB7ACD8927B397EB0F0D70B19D0D4CFCDA80AB4A5DEB950101E7724C9D848374EBFC97EC72D5C30C6ACD158CC864F5168E1AFD4C99CED7F8343719454357A33C3A519001D76055F5D95F13365E1F7FB97674094CA62986DE4A0D87BFA4BEE1E655C3E72736A899576262EBD782485EB7BC4834822E004379A971D54665CD498F1F599E7FA4E7041392D243940698957A31DF79CE06E2B6DF3D5D37E6B94D81B056C129C35CCAEF3438C5104E1154C6BC976936EE6622CBA189496CC62F00B4B087ECC6256F125C840DD54C364530A159FFFAB8DFBA9874DF3EEFFB1943489101DB83DF904B7E2E3DA5AEB29A9714453D36568646BA43D102189BFD90D473CE5E5E213B5C6118CC22AFAF826EAF6536AF5E861B6C832553C3A7FB1522CAA688792B3E47FB5E9E1CB762D5113B5FB8726D166E3A7C7EAC734E23BB44754FDDB0487BEE9312E738E415BC66DA00276D3E3C48606D733F2216BB322C5BD28F90A35A41B0F3C56F20F53C923E86ED7629740B6EF27CD51477F140E1507C9162C508AC4DE2CD6543E6E68EADDCBE026FA177CDEFBD91ECF8D782B480E52B8C180349654E495BFFB2284573A1DFCC21FF7046448D6D7E5AD3743D7C98E4C56655E88DAF7BD293961277A5283620ACC979C39EBCD8B59E9683A8D84D361A904DDAB46BC06C64D03B48CE4356A494AD4786C9859551B52EF99229C846B8F9DDB12C0130198CE92468F103C8660A3FDC504C749E89B7247C9C0F8D8CA4CE188D1E03CF3C3BA8444D96C84006AB4572C45896D5F521447610C0A12EE91AEC667368E3CF88883E9F4DDF456812AB0589EBDA1D8FAED0CE6E3CE7389C7559993D3192ECB2E6E3D17E900E2CD1C9129440294467036C82D1261296FB479441CBDE0BA2EC5C4390E72BABA6B88A349FA5A13F5AB49241A8DB7C0BFB12DCFDA0346CC3414041DC78D50D44118523BC34C07B3E2AD92A918B96F294E8AA212C65638A3D3A869EB90F334AE7FCD387034F00CF5F6FCEEC7C9A0F5DF4028DC63A1AC408D4570656AFB0BE4321BA047B998F24177BE997B0E47C2010656BE55C84B685729AE5A3230ECEF2C92CB660383A989CBC9DF9B6EEB8DC2577D12FE6A3D0989E3A60B88422D42BD75F1A7AC8391D57B5268BB41B9ED5C4B0CB9EDF76454693FD604B1F4B2F6425A71A1C8A587F18691ECF2DA6A6EE366D50E05239655D02A4CF110571EC706F9E6A6F059472C39DD2D53EA9F311A89D735E1B8B19953849E0689E2880EA5D94E3D97FAE414DB347ED1B26EEED05DF3C7D8FBA6AF4316E79F890654CCC61D6549524A51783F2412E8EF0E37DB33D6B1B2BC9ADC84227866AE18AD9F987FF8010717395389BC163072A1A2E8082D3B5372758911477DB0DDFE254867A9B417186CE3E400000000000000000000000000000000000000070D141A1F2448656C6C6F20776F726C64 + +description = rej_bounded_poly (sample_uniform_eta) requires 277 SHAKE bytes +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 9EE65680CE782748DB4F70D31A92D596ACF4E42765B63397FC0F9A3A7BD14A464E9B4ABDE70FE0F411233C3A5C2A0E4F137510F47A7526A7B13D3B0E6720BFC17B49F66B7579C8417FD7F22D49FF0BCEB7D00CBF7857E2833ED9FC4D8494E220556007C689CA04F9BB81676689A8E9CCA8800A72A94C58AC60D9A9D79B5C8240811372256641568808647784702482241460868268526201550403827252455601678435284820150830567721248762612834321302086367250887152770434221660510838753215561014566286015827522152368333112244860040211084204822552305182514208014878312131078760188816743853857354847285161161018814180425644732051481084803442543338246032065270747234533255510585508217316557045882103778475366203264334837558368472827262552032761000662032050241258204747682513008075110767867554545506432417500066272385364860478208077752344624062825285224505047606873375807824340087188543217236572402602107383548151860165266335253812470860353657317261137627118248058228510737718571460547707828670044256367626641785031338370231632702840507411582803743371003632346682785702600070454202180087360153264663354186317118344512245382437531667340842435867235244724874640820515765106512101273448236504853631674814153610804801256615007104720200506018852513781335635270120431134238468567826284825855676622045587475773424475263846702022153326348030835873536361348071160413631476754137787123766738388158563777744740403266086615527774127256865336072311316586561200404474116417866763017877777603723662216624773574825412437472107856837122162275131537365740575227872700462131624022731310250270731680678685507683845307310038073677466120303605112401776200565853645458855123357526081587748450863278785378470585428556131820342327513250037508524767726165166011808414087622736856602721525064557224280072473544631327216688220733216153435740584451676631585550482405630550868054174482655344211738815563288036788030701342488157438816586211504443241817625361221540063308170453832305686748748440257814278071628525840876320406517161101531532768165715882274776247748823574001256367534066447526412860044700647260843250731417231120743174870302132700713475617402160375705151316752638408856788242883076382512108636415443230802481110714731854381405317642637008831535325325221337727355362740228082703430564570362316370382664845203684358165266804021441178657417654123101831668357562316408721627068745070668062268423768543208780575075437777081838772107153654755243302043568141647278835854021801345746057745046620504611132143763307327305383775152826586705023428244174336436085631213618057400848277112400358478023631112165431288730828374778001072011845283284220061542242260142105848581450544862436452174120478310050337258837218717441127444350412335121814067252260607768808876346172116227303155366782222802181212868128764518045488524171470047073175163615477467648103825128878737382205808145664627787703675186184764508138504556105524137436471315460471471234175451433086108125415281350722216344167516340067552620427858710260708133702016551504482511368547360272713253776782433307647021652503475547725325775583513687143208105011478748846214151744557771604131125677866210726038283636672008866536215078564573648883C0199BD226946E884A38A70DEC6EA918299D8A2CF2246CC941273373B9D286529381C0FFDFD6B04C8CD5B4E78F5B46A132AFB33F7D654D1CFEB38507772CF5E081BC6E84595B64DF4CD7EDCFE0E8A2FF0F0F2DB70DB9B5DD6EB123219B24939E97C68839AA014E84A04907158732F4DE57D9401DCD57DDE6286B0DDD8D0CE277A99198E2E5D301BB706FA5E7428F2C0E9DF8DB3409ADF23143B1853594A11685EF3E842C5E7045A80307745FB6866FD6212D136682D29886178467AF8956B1E980FD3E83A4BC5F2CDE789C28FD46682995DE409AFC535483B5973729E83ED2572DBA455E844E64332DDC95FA97CCE72A5A23A25F7C6DE540D3669D83B40BC74F65CA015DCC7091C5F6EECC56CC89AA81AF4470EFB27C9E4D6D0735770951EEC2BE4F2B441FC65EECC43DF4B9EFA76E54B2EBD8356E02E2F76D776E1F1564BFF0651022294D8BAFA0D936B22D216D115E2F681FA24B46137E8710A9E22BA8F068E76653C6AA1F06A905B895AF81E12EDD6F383BF311BC2F711C430A3355C55BFDFC1B19084D9531F628DB40BC2E78FAFCE4B1663792FC4E48127ABC8911EC206F30BBECB56A62385C45FEA73E3B30B3FBD57A60D6ABB27C1DE57858F63393B04EDAE302551642CFA8A242FA056AE1084C802B1D884DAE8C862A851A3B0AD273FDD6E92B4476AD50CFE7C525CDE5FD19B2CBFF1E4C1D714371BDC486540462A1DBFC3FFEEA4A4E95CAA6F192AD317D83EA0B9F1C1E02B04046A0BB391CB78ADB18E1A006A803381FE5024B47BB98D840134D81CF819F82637B025B2FAC2F3A060A1101E54BF0DACBBFEEE0E82DA966886CAAC47BA9E445346EB8EC3F748933CCB3DC33CC159DC646CF809FA635466BF8A7ADDA56D11CF4AAF72326B3189101A04E14BB75ED9C9C9AD41668E627364E33002FE56A286DCE60E36529EC0644F4E9EB8FE830AF783E46EF401EF01F304F080DD1FBF512335B25E9E3934685633B0DA0C16263F5861249628401259681283012E417B18398EB4B8D3B6A279B70D4DC7873D4ACB45FC19D50DC120F0E945DE4F56CB94A012DC1687614DEB1984F1482F31741EDA9836133BEC19AAC5200251A1DFF621E78612FF8643E1D37B764A0BD57C422118C076085AED3618FFCEDB490CF56EBCA112B29A5DCA9A0E5B45C3049A26BE2CFB7441FAF39094BB4487818212A59D75C10EEA36953A79ED133FE34BB669B65CA16F46BFC9DD1FD897D2DE92CAFEDCFD19D629C733DC5E8D11D886FD6180E95B9AE561D6E620039B30F4389F0A6938E1AEF75E2B971781904A0EF5F032C58DCDC91E485C3F06D4D303DD6D2B0D1B73B1C4A17979134365F3A0591F5B8C241323E0444AF4E520B49DA0CD24AD54436F231712B1466ADCB2A63821352E68A4D1DF3BE3DBE272049DEE81401F67FA66410A1DFF6181DC483A0F46EEC8823780352BB5E44892982E5D16D8F9483392F5166177D51B520C7BA847450DE21EFF50A51CCF6C6BD1449BD50AEB95985C8A31B14F44D96A50A8F6B630B0FC29F3F51D29A04F88DF29DD745D31EF4826C12A18296D4BD8F3A442262DE978BB381075E3B0606F83F5B99B8028D0B49D36F946FDB8CA3B9ABBE2CB9D6EA387BF00E119AE3A9827B8B3A7DFCD0AEFA1D89BF02FE8DC49E43A30B42AB024CA431C91F5567214B4FBD313B4D9D39AD65B54E6AFE37DFD389156D96E516E98215B2514300446F3DA43A734113D525D5FF9C5E4DB4D63032419483E1BD827250951E065C16F052A1D0938C249D6E6F2F313D12E32ABFE4C7783E7AC3C14445EF665BF36C9D0E25E75471528C23A953B1838CEE041EC4A476D7923DC65964EC32FBCFF9514E7B76251CAD4361A7B5244C1E8EA3D2D41596FD4BBD49A5C57843135DFE0D30D9420414C822E19B8DDF4CE9A35FE8FB9C5AD8C19F9DC0122255F5EDC328FE60452214701577BFD87EA8A019106B48FFC1F2184B0A88F6B2A597CEC184FFF1D4D74EAB2CEB197785D5A0EA25F6CCE727D6FE3CBEF37DD8984CC9B473BE7A85C58ED72F013545951D5428109806686D277009BAA87DBEC470AC1A3ED4E9A206573875F7C591F095633583E83A22ED5010934F3780EB5A7393B622F80B6786899712398E75005CF31D0B25FF14E506478136F7266DC9BF318F6CB3478EA1FF9B78AF6EFAB129B483B657B45FEE12CCDFF819DA54280C91442E5E1EA76E4DD3E436B7B33B3C7741E872D14440632C563B41CE550154F556412F577E5D5AFC020B0D011FC377D3FB94A6DE0797255DC5D1B51448041E99A3C0F4999EE970659BAED2F9D64C107ADBD72B6E2DBF3C4911D5EF754FA9022714574ADD0B1BF6F5FEDF8A9CEA5FB64A1390EB9978303A88C91B308201A5BF1947426D35A6148D31BEB3269270FDCD926B1AEFD5ACF3954CD105A6FED3FBEBAACF72583CCE38222BE0976D7C42B752F5CD74F5675ED13637E9BAB7A54221D6BBA9412993C9E93764C6F35672265018815D0BA9BAFC15ADBC02EA9A09AEC8FFA96D0E6A9F027F2A1AFF405D8B90ADC8A755BC4CEA631A08488681D44F174D4BEC2FCFF5F2427D5471BB6FC4B3AE45707ED7EF21F340E92D309DA7FEA5B97B5FE033B52D11685AE2F42D590F1A70B718338E88FA8658B6D3DEFCB3C60F4105197D1195D561D78947E4619BB9910F4F0787C7502D0188F3CCF5DA6E737F7FB94CDB4948181AEF4A4EECA0D57DF5CEED47E04405BEAAC87EF378BBC96D62CDC9B6D330A351C99B0307554055E1550CDEE3F1D78A51E7C09BE2B85C02303051AC1E1F1A3A08FB4DBE83C1A1591BD29E064C8B11A32502E0C6D9775BA5EBBCBED8E5C562A2725F419912797DAE2050844FA3359113513024EF056ED9E3521A0A5F05CED47F01FC3A3242214B8E9634AFEB69EF38C9DF483B4CE256CDFFCA8F1838D10232B8E7476E905CB9951B5EE47E1861024A5DE8693113AF41657F1F2BAB04DCE3CD4B4C16CD438436268558DC08858EB0D2A1CB6830FB3E1F28277ECC8586F9EB29F138A00E5BE34EEDDF35326195CD1B230143E46DF890A619A922FF88A146DB3605A31FB7A076C0F9ADE9D593D5E1199C3CA25B3BFA0B808620EE910CC9B8E89F56AF786C43C70348447F358DD58F234A62C10D5903C74EB1728CFC499B75939EFA1DA90EF8F536A5AE8E5BF513676CF87128F4D8BA823D972447B56D00A7737A7F63020B4302EF41BDC5084709C90AF75B10DE041A21A6C788CD48796C6C6618AE5EE24C756160CF561CC6BC60D13424F39144862B977CEDF7498F233E84D25E1345254ABF8C7CBCE9A1601201ED581939EECDDD1362ED509653B32D93C56B14864FDA9812510C2F198D83B3D16F060BEE47C9FD34FD046B920C21EAA9562F5293DA5213E4599AAB6A000354CB77DCA26DD0D4B0B36D68FF0854E713DAE256CE4A51219AA659FB7DD17D2639ACCDEAD35D81FE52D86187E12B89E8CF08FC32A7A8AE4E1B65E9236BACC1EDFE4F7E29C79E4318AC124DD62C3DC82348127DF899FBE5E15B698A2D4DDBCD3C9 +valid = true +smlen = 3320 +sm = EBC6B035EE412836992FD32CB31EDEC14A0901EDF47B682F79EE0EE00AB31F56B150E3C0AD7CDB295C635F1DBD6271B11B17710308DAAC7EA40878561153C9573F09D21DBC3A2481B377F8F34118053568285FBCF5B1D6481FF12E52E5574A62B70368396A0036D053E8C43A30B51085D0204F8B80ECEDF6A4B663647BA18753CACC8401EB046B05B5899E547438E9A303DF6DE686C9DC1FBF9697985BA1014A86F3F3351813341C7B52D7B1A92E01A4C11FA279B20E1972B0463B33098610ECA011B1CDA8461FA20923FAF42487EB36350F3D52CE71FE48F52FDD5161886FD76FB49426C1B9F8E2A364533F74BE1062E26AE641F29735389BE8EBE31E6B0F59AC5BC20462ACB3DC24E85A1A0F1F8C322465CD904CAB50549896BFE500E2C57444297EBB8C569BF5BC9EF6F78773B2349F50893619C4879D0DFC0CAD871FC7CE0F63ABEE084426ED70B0E4A3A163985FD210DD4EE1DB20AFABD1DA9D87164DE031D46A4662934B3617D729368C52C8ED7ABF9101929B210227B8189E02C018C3B2B699C25055F8E47831893CA0E86C154B2F62005CCB49D886C874C5AF3F6FE1126ED41D53AA258B7E8268A699609A7EC1F0E439F379B69A00940B1AD63A735AA34942B97214150B55D74311C0C5BEEADC5A28571B7B9B8BB685C6E42173DD71315DC0E864E6B967177AD9EFA00C2C89B9D27A1F5776317A8647388798DC1977E4EEEF5C80920F12F12245DCEBB74A5096485359F47331A352E2B7050775F6122FF7F4883E09791648084D91CF15682060733AF18F10F872C22DBE55ACABD0B4EEC5CB6285C5F009FFB354AF539B5B3E64011CB752FEA88A1A868ABF72FC26CFD65F99BD1205DF61F377C95BE80257D10704D6D12EA41E6BD8C11E3E07E78D3BA113085C0B71639E08E1D9193F5A21B992484B5A4851D0E568F9BAA3AF9D23FDF389885F1F65CAE6E1C1138BCBC1F2E9518004790C2F5DF8B7B90034503D436C3385B1653498A78F5E7F5BE8B181FD8A99F93BB6BA4647BF9856D37322D1333CF5E977A3ECD2926ACF280C26CDB2D998A283FCBF587A8ABC5006D5055474DD8644F90413DC7CF6D1B2EF6925342DC26ACA81F8439824705E400F42ABF61D1C505EE79941FFA48AE45A472AB9E2C01BA12D0638570B7B4919D413AE11F7E0EBC11E718289DFF4F4195A3E12D92A477D59DE56F0FF61E09596942BC1678E18AF15337C5945096A5ECCA247BC03F4B649F570AC6FE66318CE0FAFD080FEB92B4414DB54E8A1F1914094484251DEBA8D407C3A81BBDDCEEE08832F6140D54F04C3917A5B7200239B92D84211D2E551FBF4DE38D1B6C12BD1131F08A3D1BE59C1828E6873B51F91B3C14CF30E3C4DDB7C009A1830ED1957BF2B7241D6EE1B1E5A4A4996949392AE2A847132C64AA166DCFA8FE231A2357321E3106E44C3A2333334B53240FFCA65BEDF30952C7F81D85B3F8F4299F86FF9993CFC21E66B3B96387BB2E52F948E6D5DC25F1B83168C45092C5496B229317535B8B3C9B0C6DB6E667EF941B8C0CDD042479E1A9ED31A91CB6CEB4A34D31F0216082DF33D1057E6EB97AA28B911EBDB9E7A557D3C7F1C14460F134DF2C49E4458450908CEB277DD0483B7DE858BD035B339A9E68D9585AA695DE7A59B806AC7392F81B68F960CB71FDB0E7ACFEE27DAA350591C9DDFF5A4D6B93817A9EBA93FF228DFF9A8148C90C0D54FA5BD9F4F844B829611C83A0D1695B05428D430E5A42B94103F2EFA2782692B77C6F1532C334C5609323CF173481EB3C3C8A7AFCE8B87CE68A17DC88C4DFAC633FD2C3D68BC383B272D8292FBC239DB7AE454A84F1306BEDEB5F93200EB9A9C0897A47E40EA2C3AF500F30DD9CFFB4FAFF594DBD23F1CE23E19AA38FD85BCF1FDF354FD7AAB1ED82FCC908E5F275DD7A74738348C3A1B037C19C787D31F9DB1655F4F069C7B26A0D00C507E5AEDF078B7D33FF326737D25F0174BA6383C4A95EE7DD524D8CC7789C77113819E4686CF8EF5980A8B2C83E0EF141AE07D2C9AD4DDA887DB56B8066D4F8F138C9519AB30F662833AEE8B91809ACE2CFC1B8076A37A80AC966E994ACEC0F1986F563E28F68EF3C2783FE3E892BA8060285BEBBDCE7FFB661A210531788D5838B6619A789F0688AA3B5F68E646791A1C1793EEB0D06F3782995D3AE731B185D29A7A6EBFB0556B959268E48E71BC8C726874F3127F4B53B80891445604202529F62898DE839C0BE7E7EFB669C5E53F64996750F754A26E95F3826AF92B03D55BC0BF4F30AC4E4725A8A9959BD815A68EE67BD624E8122586A8365346E224BB38B1C917BC1868153D14CC85D1573DE9BE3CFE03BE5A0BCE13B82048AB49A46AB507DF9AECD843A2374FC8E074A6152039A0F39A6766F2CED16FFB143A8169DBD680AD7FA95A831293D60AC41E1A7501D6EE7B42549190BCDBEF70C29BD48C9FDBC57A77D29425C90A5E9EEB55C24FD458228F637AB06FB334DDDDEF6A530D3322A66CFDA77B32DED21802F1D904048E1C4F76AB23BF0A2B5E650A9DA8C04FA763C63353ACF60D56A08B1E6F27971AFF5370F1D91F0AA8798009B39D06CAD8717BE03B9C729EBA35424C053D18792EE5CDBA4BD3EF6AF1F75E4F1887C194E9B0EFB2E8DB3F27CF1C48E66A70E4940CD82C2E0F774417923F611D541A8FEEDF8553A9F3F18135C6BAB6A671D2C7F788FA3D73541CE884358C7651122647F59C5B2B4DCB0183F7F5C0A30F231B6406B006409B2496BAEEF47095F63159D145D0913E89C5D2BDDDDA4410D25ACD6D068622D7E4E235A5140207C385B95D01188B948657D4DF0198C79FABD5731464E958EB458FD4F1C75CB51FA7B01008AF6F485D31FD34F9B994393F99C48507C0125B7D2D056875A5B1568E92DB318CD5CC61526C28A3592AF6F33B8747D0B442BB3A6FCE1E6652616F090A714F00213C2E025A8DDC0EDB29C1F3B75867033B4989D6B36D5637D2E3DB0ED6C214ACB196C4150E94F8AEB45E2B404F1DAE338C73CE087181A8A3D919610A71AAEE2ED7733547B15B6495F47E796037E77D44960F962A84557BA68F8E6B2150104FA5AC800E6BBFD18C519BBD037C64C0175ABC1D6C2100F9F0A8E2BC707BE87398BF47025F715226F03E85B93694CB9753252207B974984A6BE79DBD800C16B5F652B9CE2D84954C292A9D3FD0CA5AA18A15EE6BFBC06DA1404096B65260C39018AB259C06B3A638E27ABB901F2A19D8A7A3257DCF3226BA94B24668BC9CF82D95FAE945A4D055BF5948F0F1E85526CC8D6F92B1C2985E1689B8339D5C1E5860F14810B9FD5FD78AA4BBEBF7540E74E01EE36822A6EBD810A102B86BC49DEBB37AD99D45DCA9C12E062E8CDC3CEA19CB6C62DFB8F04041BDE1C063D0E7596E73B47A0BE7A4FF4C7C5B1196EE34999A32887663BB3728FF133037FD90A319F3C640C3E59AB9DD6FD9E344A3E98E13351E28B6650AB6457C54BE6DA4B50B3E4CDD1566FFE834927C32BF2B31B08D53618C3AF25124D6323BE3B8D3E656FF8E0DA14E654E969BA8F34023723514C29E5EA179E6B78C582CD2A852CE2B46E2FA29F30A2912DEDBABBE2C8B6AA5E2CB147CDA3CE25532044A4F5A5BE463CD26C7624C2858E18AD9562A6AB120C1A567F4B2082E15D95CBC430F825F931319F039188E127BE8D62C270EECD9306D070FC564973E424D38E9FAAACD12B131E0A223E70F44AE2D7E9B7518358ADBF93CE34AD05F7B84B7399F3E7AD5958066C79816773C6E35F654FFFEBCEBDC0D73EBFD9253C45D2EC350442007B2C1F8A6D24BF4641F083178474FC0CF6BFD27455F8A71C20AF9B21AC1F2CA02927408ECB3862AF0E82FA003693251B503D85950A28A4A820C95D524F00D797AF7066166BF86FC28175665E85E7E0E193D1793D572F9FD778E481620DB91E1F8E5F4A686CC3D11584202AC6F336C272C342E119BD23542C03E17924C0C54A518850F77DA9EB7CCC6E352E99ABF6079D1E5114922F597F08C63D1B2BFE812FD356901366BEC1E162D064549853D1DE25AD6153E2CBB3CC96E6611A9FAD92506963C25B2176DB560763B1DF0D34DB177CE99A789E6A413E50695C16EBD8F44CB3BCD592A977C87E9C6935E05650C121F5E5FCC656EFE6F8E2369AB7564392442F7D3C2DD30B9A5BCDDD769EE25E0278EBDE0279188768755CA50F7A0E06D05ABC880272D19012B411211DDA63F8FA4A971F9ACCD4E6374F17B7ADFBE90D2C8F671AEF7BA05567DFB39BB016F5654C7956334F89B9480E6905F3841042EBD0B60A1C7969C31D82D49046FD12FF1B74AD397C7824155A819BB667BDAD9EBE44C691D1D171F0BD494BA140CD8AAAE9C3EE0629D459DEA0CD76559FA79FD94808D804610C18CBF139CCA39EDEB86CB4A958387662C50F7CF1A4D3BD057AD259C89A713F2AA767325684C022C5E7FA20B1143A967B191B19247DF804945FA7012B078DF47A01D65C0322DD2AD521389A80DDE3CFDE5C2454A2E08E23F2FFDA6075C55683FD02CE235DEEE69041257350AC56A70BD3F35B3C1BF83DEC2AC7A3A8FEE847ED82F22E229A573A9FEDED6DFD697F3144823804A9FBB4B0F2C565ECADAE5040A123B4C637586D1D64B4C6081A4CA0D2F88B9C6CADC14767A8B9FF2FD4A4B5E6E6F707A898DBACFE2F800000000000711171E253248656C6C6F20776F726C64 + +description = expand_s requires 2649 SHAKE bytes +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 8F6FB031D69B3B782B7F523D787AC54D7850596BAB67E61A2714D525ABC9A79F176E959225D16646233DE658A5ACA6D0DD5075C980DCC16B38E0A62EF89FE5173C22419881148BA2D1C4D1E8FF56D28347A90686294E2D1BC4E9C897F78664620B383273F476F948DD833E26650950003D0F1AAC192C1662F34E0CB8E73D48764778414017680776242812250638008357333285020234236483581182366612106274542547410400035011752518644854678377407082810445004604061876522045886714651344437511752652167153085385430728725682662614372515462228286225400848261525411383173776734580521477636036800732132422356624660026028466036145076645660825516702153673624483231816666805687774140612002480856670362514516776684431320850610804750183886683143513723758070184618610386168082277530515486533488100457080440718860008285344461260614076102175477315162407244803825861736635128804266423108830803120203067233365240340283651662361750452324877104808118613767017171632882725547162605201512604114115423880108851478263427527166380102040856521463101876662245036365588534770031824603803262535586618525244238612443234752724248440150152450741681058863671504577770776636451856523573415182545167881657002111372064554180286008848780002872865533351364501187077113858057643834336312476818400308382241136484145114264584416146114180661008271721123486415705685640436204156548221126373846805331703355503735401426124651123510583577386475007655687742783263654675165634571171843121826410313470414334437112173325345832508650461562204863407081471043085361880554155081723886504851661756230517254161104027032355520620732344424778661361233588472184806576214234566246534530214513047562421372583012020570554256654112221562615166564753745054065564811134780073482547212222885882276242876068171712640853204081265873884135641023215853861411228037004035504887442715024230385885164202203747441036502438358545481744248057118744866163613405012378616218070474763333267274624778703143000505841006132760220460280244511060882144880777487751730874053007530178450108648451353527674436530802808115751536714635588553385802258250470207370211318564587864567887002465027642648738230325548223674025258730024686136371373542854327512240657638031402020814006523821430008322082813864583451460738043266212127530185605511488001872528708153004870562374663017836311830133540850135461085643214330686747725454637737744328013084464708735614037526614215152748712475727377652438478647854416121626260845483587724306634211708220158450874873263280672727726858006683436374523582537464353771714262722232852615470512527220624725067617115267424158867015263385846835037614224105116026142125300576727488862507011641521577067713861410672638261875713417265140237271286127858485752335036411806028233584020802788047462688836573084440632056154252016737458134725342718412278214780456518562722238668724636705067378352835386217111701784454620426556135232600754535718078362414455508861188014426401064454265644380107651602714130364085342244833780372511561305630766083431053185545574732624860164210763131754251763541716106383517620517588748757308161543664066721213165522538283888467110316021560225080353238031625702413641563738423650600563280750216261758A825F76BDA3D8C0CCA9A2BA53F80F3B84C756523C17E7AA83311CFF43E32FDBE39F9342D66D3667B4D4FBC51DFC6BAFC98F7E7EF3425DE5F2FB245C9B6579DADC2A5DF690A82180FD7BBE9F315E62E914F93041E95D037F4D0E67F623DBB529DA51DCD89858C213C915F708F82F04040139BCA144CA7FB915D29305EF4DDF9844E8B9B9F0108AE7D0F599C68C1A7C5E8B6C41893DBAF261F1CC621A5F1342C228D79A85DF1A706686C9828C4D0F9E08C367A47F25FF56A519FC5B368A1FABD2F17C6E96B0B330A67A0F700019FE86AF32074753EE44FF20600E36583F9E8D9AE894787EE15251EFDF31D973B48BC98B864402BB848C7213E426B561CD62606D8DA271453313D2AA7AF255301F04ED55A7E0B013F6E7380A6D58FB2C777FE962BD575C223CB64DCE0CD9B164578006BED04D4697C3374697DD0A0C42911C22270F2C3BA57E2079ED58B8E0C7E8A4CAD661DEB0258F8382719513E9EC174DE3877599747375A38FD4A68B91AB4A9CF4EE4B3A5F8D55DCA5CB8EC289ED1AB64F68382917196BC0F22640DF84680CD321D08B250A66787E1D2B13D78844F9943BB2707686194071A1ABA1426E38C4D0042DC342CDC08D5043A6831D065F4D39AE681E25BB8E2E7D7F78B4538D109CB4B1D615303568356D5CC19ED57C1BB62E303532AB5FECF68E8B261BD483AB0342A47DC7E5BB71463CA88F17009DEF789B3AF57A0AF1ABC543EE622324102507555BB0D1F25127700F523DB1ACFE738678AAA657D7181D97BE22D68ED70175C0C66B1EE9ACF907363897051BE277D29258ED68A185647F00B8F7DB7C6C3078D89695574B8B954377F6AD40172A8C9A1267EA2A9321FDB180DC96A1FB5907016CAAFC7F8EB20858B6C6FE30BE6E847F531B5B55B1152736CF5B8BA7CC7B0A204AE643D5E6EAF46B8BA435F44AAAF77A32C575E632DF7BC51F7F782B0869825F44B489AAE492268F53BA1D5E5A491E9FBDDFA7316EA5ECDAF2036E9E308C0F834348328E5F10E55BDC3499A7434A25DAA7760B1E4214EBBD66C6F10023A53AAD7F2253E0CBECE786913157AFF83211832B4645A8A62992830EA176FEC70865901632536178F5935401F68873782B29D62A128BD9BAF6FF436D9A3685B2113B9290C76024C87DB08C1E61ABB22B88AD326338A7FC01C411208B05DCD7CF6D53611351072576FE1A41265A0E87C16EF9F1B2AA068FB1520B2A960DD46C81F58E63C76A42A45C8465815920E2A0F02648C9B4B103713D2AF1A00BADD0E7329E3AF919B3160E8A75CCDB558088868F2FFFEA718134D85FBE328B72FAC93CD842ADD2EF9B5B3D5D1027B91F78D09B471A1E384EE4773F7E2BE0184B4C776A752FA74D85B653A65DA018BE0CE64128AD582EA4A589256957EB93989A04160627FC55141554A6D0E3D77D2A4772596B8E30DA22FB1D474FDEF5D0A4213FB3CE760DA0C94A30DE1DDA07E60C5E89A5AF01FE390B18A5EDBBF0646D7C07D7CF07C3CAA35F8BF8F80F00435F6045AFE2AEBE2867351FDE58E3CCD6D8A327153A69C700E9C09CD94F6B45BC19C9BB889D9E9610D3DDC37720649264DA6DA8598C089C5332E4BE0D65B930D71CEADF4A85D64ACAF416DF0145D2A37CCB370878980B28D302F48F39283D155A5DC5FEAD2975D055754F1AE3B6B1F5FF8CCDC77B457097EB707F36078EF8E324C2D368F4563E284949EFCA4D52E3C973273B06D37D01E528552DD97F5C0A9AF15D5AD839AF71A77B37BD0742C90E8CEF1EEB25C98C6A43C403B467A8657D9105B5BD1254D8720B1B2BC4BD0BE780219ED085431EB8670389422738E3327194BE1A22419E271B3498943C83592CDEA8C66D178EEB9C6AB4D836591B1C4D50E0FA2F74F0A77EE11791FA0BE48BCAAF909555EA39131EE24F22545E37BC7F9485E6C2785F044C9EFD4CD231E7B4D86645F2E6228D0EBFB3707D2BFBF1EA809190991FD0AF9566D148EE620D1B272D3010125D05971A55C7DB3612A2EAE0E98C4F0355441E96DB448051BCD0E20CB896941FF2D29C7EF9E9725BDEA272CB015225FC94967773B9284182C3DA4EAFC930F6846F0216F4664A125CDFA5BF4A2D5B91F0CB58DDCBD10C164BF693D4901975C04DBD40A32A8BF8F90F6F22DEDBC0B3E7B12EDFF0822248C41CD05CB963B783AB2FCCBD10BD24688423A05D4AC2631C520A2BB736DF5188291257BF51CCF4174D7C2A34310958FF4870BA868058E2BCE44493B6F34156F8D1065075FA30630E1348EB780D8C1F199A803E67617D12FEC5650F92752FF3EC6855D1D1A1C70C6A9DCEEF715ED416058F9FDC20E4EB0F78D593981655BC9B13741C5D31B47FC7D0CCA14BC20D8835C8BAE83D05E80FA05E1172518A76EDBFADF608416E8A93EE25170C59D7CB82B52AC8E7A533A3B1E8914D5A180170F95A904CE77A5EB42D8D396ED301AC6858595D58EC5BF57E75E148C85AD81986D2DC652DB8EFE1F11280DD8525C4008E032A46D72F627D6A9E55D004004F0993A70F865E1327E04717201C01FC9EBF5EB4D5123B202CA872A373C61BCC31FC87425E8F922C7B4E5835293C692175E45C1750F668F2F68064CC9FAF851149119826A6353A76C6F12E7DD12A00395D09BD17008D4B4F8A3CE9D4FEEE2A6D4CA292CA7D36D94BF06976C6549D9F92D760DB601561004AA1CDD59A24B2F413513832C15C49963E34748B2CD692CF9FCAEF936470C4B96F226AF2B3B9AA1DABC133C023D303BEBE1DF787329B3A1B4979F52C5C07C18725EC3CE34CCCD005AA0CBE964B7195EBBA2191312F8440979FB877B506CD665E365CAAE7EA0576B5080AAE8BD5C78C6CBE2EA19D657C516E8F93A4100D601EFEEC2DDEA9CC48A5BD73014FC6272231C929EF92B2B0B13B54A1D9E61B812C2A803CCBE856BF93F397F8DE5BA5C2155017DA15B38B77A981B92B84B43169D9B29F376D7EF3C042B13B070FD7F42FD6154FD648164C425A753833C81E44DB89E9B208719D36C9B1D075B51FF47B3529D56210EEBC34CB1A002616E6D2DA9C2D7EE96D54D4046863CC9D978AF3A55F588525A908306631338DB805B2566E5308509ABB77E38A9F99DE6EF0237A75BB9A9747B3A924FA6A2BAB9E47C4105057500DBC3C2003A026B50CCBAEB236119656E4FA81E2BFEF204372329D53583DFE392EA89277F4F014165FD141E28BB7981A37170BFB7DBABE79DC158F49FD178B3EE02DCD607B96B65E3E815B4FFA5514F9A635B23E51F8A48FE0AA2FF0A674A7D2B9A60E0364AAFFFA872150F9438FB748114C83011E3F8221E8F1957B99294D47C0AD3F7C54FCCD5F129FC4915F486DBC0018AB1CDE3DED5F3C28F45F539A30B163FDF95F74633D061B63505F9CE97B152670DBC26379F64E9BD90E0BA980608540306F80F6B3B227019A8690D48A86BE78E8F0831BAC02F53620D5128EA6AD7DA067A4D14B730E1F173B6F46B9A926FF48A8FBEC1D6B4EAF992D7E071AE64A7318D4D3E02D4EE5E02EEAF53C4932BC0DE18EDE20DE401A5E8 +valid = true +smlen = 3320 +sm = B55EF66F65C4AF861C0C4A9404422784FF219DFCF4B1565989FAB2EB5F9E89779A8C88471849A4A0653BEB072B9BE59123F3D5C3D200F1B1E43AE3CD2CB7C46BC55DDF877E8F12602647F369F6F3EA297B44D1E5B3ADF136769D588E1299360EFE3E52A21970BE043C29578B8D996B2A4F80947282E463269F629347199708EC4A71747CD0E25A996E8C1C41F55F1DA52703EB155E413340B9B04A2A7596B50EE2E5885A197D7165B396EC6203122FE7029DF1097BBEF4C79846DFB99901E70E6C11B46F7288A4EE98ADAA1FAFAD60987DCBB2A586A504D03813C0268ABB240B4CB3CB3C3866E8392B57A8AA600DA00DB1A0CF30F9090D324FD5EEC1B4E8A6BE500576C9057D344D83A9A94AEA2EE10319E91273ED91E24C4D41783AA5D03B79C426FC922A914C59C62CCE192E5CDFC096C6B229561A03D21B409FC862C18D55752B3D8C8B79B9C0C1FCA00589809039CA4F83208F22C415B9EC2059E21D099C1A5149EFECD815500CF80C03221D9A30165FA6B6B52955F970C9FF5BEC404A6E99848C56F5C8EF653663995FE3C9E7835D25CE4465555FEB1CBB42AE6AC58A172D16C22CBC34C6170FDE45906C2BC93CD8535FCF1C00DA91DCE35EFA0DA3957261EFD4B4E4B7837DB93D243934254107F2B7B6A2DEA16A1EB2446811597CB8569EF0477EF87632E496042F175F4B0E82F7D1A1E62A5000EC62639002A429088F89287F1825525AA25FA4F21D82BE9EAFFEDB3217044BA1F605988C7C2FC1C5A5BEF3EA1F358170B4A5482D267C74D2BA7AB4011CA431E81F871990371FBFC6353DCD2C8B78319A865BFC6AF081FDBB20F85646D03E25C388AEA77EEB7880F2BC3C0C3A75AC5476CE9ED84A456B668EC930509CED087C1AF7EDCC0FE233E86BA914ACF800C68E9DD4F82645ED6338B824B12EB0950D07CDB86301EDB64F245EB93363681DC5D40CDCB9E1777F4B852398AB92374C40B890F1EBD0A60CA7765A8D76DF7F9E2D7E0C5168E591B293B87FC9E8DDE9ACD9A0D29EDAACABB904436C8052FF90ECA628F5A41A8E5B51738C58A719DD7EA5F7DD3B4724057086073FACB58D674BB004F6CC7617A972D348AEF1707A411A1A12C1375FD7584CD601F9D7B9AE9B9C6F209A7F83A2076AC5C29FE0E4021C2222176C10E926D3AD7FC7CE50E47480C621496AB04BABBF643180900565BE9FB3594EF994E96279DEFD17AD104989DB8897C93729AA0381084D50F1ED218EB245285A04942688EBF7DAC914FFAC4B382C68AD076CF03246E7793AE10DA30347705C878C34EA191CE95A5690284552CAE5759598D7E98A232810641B86B36DD79EA28B597B66E623C74EA9A838C48A8584D9B883D24A11D46E3FEF10AE82F30FF5D30B7C25CC731EC19286159312DEF6A5567856FF7F3B33808A6DC09EC05521A252A9D794658B4397891FAA3E7C3E45FA8DA4B190BBD2CDD094C2A00A9B5D2492F1BAE28C7642F3E082D86347C3944811D597A284A3CDCDAD2DEDBEBE491E583B48D5ADF8A841B5ED4A0DAD472EDF3815BC41F729E4F8E8B365A6E4764A350CCD8B737BFD7A434B2A24BEF1A438E0CCE806A1ED6834AF4EE5CC0D115070B2348080DF0CAE01AF9A2EFB2095CCE7845566FDC25255F55245293CA83BEE29F9A51D9123262CB2944036B88A0C9CD6F46DDF7D0F9C6A26FA0024611FCDE29C09C0EC779902D23E3B1770A4530772918054776DCCC59FCE9BD9EE253062E1BB689D349B4FB9F72C469EE8A555AEA259F948A0344EB931C3E1F94B6D7A70925E880804240D2BF23E0174810972953EBE3161AF39FCEA82041BEFE007BD66392DE0FC0A03FB1FB35FA307DFCE0329B77AA8134D5A8671156D61CE28EAA845824CB87D62AD2F57819A396D18592A7EEE75DC91BA3FE23FE79BB1AA4C424066B90FF8C747565B9185D4F112FB66DD0020C92245A18CED444125127FCC97F7CD862CA82CFCA9609DF97AD48023784610E2E5D61B41BC8973467672E9D55D3532129CAD9CC9710A83AEA3E50909FFE7C6D537928877E694833F42FF8A1B2EF0B0F2321B87848B8E7E86ACC1E0A9844DA116CDAC7BA502F1A24B4A81FCE236D2BAE5C5DD905F2CDFDCC276E3E2F8A79E1E18E53A80A3810C684054274DC140C713699C131085BFCF24ED67366C7A13CA20EF736A6B6E81C3E01198D7A62CFE1A3301701E68CD2916AC3F0992C71A67D123E90DA45B3E46C2DFBA24EF2D20AC03F739D27A102905C78523139E9420908D041255C03F0FD62BFCB5BFA0373CB7B8D4B83B20EE721F9C299C4BC2AAAB248F2BA0C03838C9C01645B9EB24DEB906E16DEB9F29FF4AAE14012F473DAFA7C6F067BB7DDA25AA8EC375270D6B3942E254655DF3DE4E924BC03BB6195015AA2647BD94AE885BCD6C5DB820F8AB1688F6957DBC2BE06CA28FD54F1CAA566233F4C90DB5B34EF865BF6C0D8CED9C4D9CF4C7A275580586B8D93F56255051FFF05C1CC4537240BAB98CEC70C879F4703A95DC269348E7142A2FD7D33A705E5B38113D5AE7F089DE10EC88F62DE0A1C8243ACD0424C9C2CFEACECBBD19B34CE3A35270AB3536D6BE36ED17A1B1F5219181DECFC266F301E71775E0FFF5A4E3AE8B3326F495ADE1C1CC77EB30C9FE8DDEB65AB5FD02C5FCF749C76672D48FC75A41FF510AC17A79BF536761B6534F8C86B3AF005D3DAB70C62B13826BCD06AF0FBD09AFD05978B3882BE006F8E7DED0B7AF37C54F93552390655B6D24F1DF1938201BAEFA2492BA2CA9885D9475DC6F1CDEBCA90EA78B56AE945BF89AF3067624A1038CF7B51C0008EC7654346C50EDE20CAB0AF90C93C53A3C83D10FC227FA89528C8BD244630F7389E7C6705DE3494604D87E9884BEA2809CD48D9A2E151E6865F6EE2891DBD9257B47EA6E96B4CA0F800F2CC1C7DFB9423E6E106B8BD14C1E846DA036163C22E2A8F94966D790CBFC81CAEA81C59D78E1C64B8DAC60BD22E9FF6C772FB801B9EBFFF2F03EC2D9303E752A30C8256F9BE65B04213D5D948025F5099DA506EA202F94B2D6722A7D52612933B0D97978534930E2876A9F4CE21CDFB15F1D53D879CF23014F0972E1F13B5545B955DA450D39895D95283B98BEFCC8FB3E4F344CFD18DCF6B1480C282E91EAABC81A5EFF80952DF44045E2578FCF465412176714C5380F744BAF5A797D422C837363F620BEC51D2983C476398EEF3BE3FDE3497431F3F2BAF9EA0CC05ABDAF8527816097E6F6B34324674FD5240ED293DA43B561687B83D2B4C1B020509AC978A8EE23BDC2210A7B7066EDCD79459ADEB3BB88EDC016D504B06E7E16EB64B7EDB443922BFFF0FC0A8AFCACD0B9FE37AAB251F78BCC119C92B2D5B8CA3D2FD7E676389D65C66719D59CF4946F9D6826042A1DD603D6222F30A6D4140A1A1D7854B0E99F48DB73CB980DBE2324A25BF4B2963ADF37B2B1A643A794C5E256337F6DF9517C205AA380720808CC7941121DBDA09D26746E6F0335F9727F2673D849A87DD8B15ED24CF9BBACDB934AABE991A6B26629C3A16243FB5CFA6BBB883672975947AC90E5FCBCA684C460B1D84AB98E34E789EA6349DA807C027F78A9C4846E0301B0497AD11F9EA087BD3E16096420C7B662AF11A4EF16682F32B473CA87127F263550690E89E2B4435116945FC50ACF8215239A5FFE902CCE7CA78FFA35A0EDDF0C32EBBAE8AE46864C179410698B4474FC0556DB384870C7C5557F5670F7FF0BE583FAEB9D78A990CC62DCBFC98AD933F671369F180AFEFD794651CDDB20F951B4FD6D4CA8BD8AB9193CE30A50DC4AF87D04C4CA5D0D85B35DB92C22122BEF14E3105E347CB882404DA9754BB30B61CE3240C60C97C080EC9BEFCD4A94CFE4A585409E415406D0A83C702480AEBA1C5EFEF64DE1EEF32B285E812ACBCD13F2A6880812C37F8F7A082F9DC130EB332450ACD9B4A56C5F64E65166EE94291A78734754506943EE6B872040CE76718C25BCB07E0BF9DACA73FA42886FB0067773DDA68DCE7B33E45BDD13FD68F3704B3105E79DD9F7D8A3761707F59309AAF78642091C9A3BCC3ACE81B1EAD9BAA5915C95F9C2F6DD79079A065A6DE158004B13A23775997B6C9278C25975BF5799943BE53B81FF49CC060A7E0B53E4B6E89E137E086CA8BF8AFE4A3B6B1C1E2658B42638D7E8746DA4697E749C3FE1AE3770FC5FA6F2B5A747EDE6A5CA8DEAD6B65DC4C44198F827446029592E80C8E895C2AD72E2792B21DCE1CEC77838AF238D2F1E7C413DC2C916E7DD431AF3CBD666AFA2A0A1EE08C7421F69E6188DFB3D358FD34C49D37F56D8A1786BCDB104B3FD22BE6615013F034145C8AE39C8707388414340D5770AC70452EB3A99F264B2CF6D926A6641677B7FE41A42CB3C9F260646775FCD653AB2C3C651E217A71179F379AE9F2181B66FB72E0DCD4CA5B75BBFDEBE497AE66F69F9AB09E80B3282B893ED057909460D1C073D9E885352FEB51D367E71AB7EB237A3DC05063FC5DA78276B27D32A22B6B0C858637FF0B8436D56BEBB511590F810AA9B6DBD5047C67714C12736C24A98F7E9550988FEEE669C39BD7FF95097A8E938EBAEEED34890B995AF165EB230204378B5CDDD5DCDF71B44557180909FEAF902162C38608AB0BCC4CBCDE3FC343B44C2CAEA11586A7179000000000000000000000000000609121F252A48656C6C6F20776F726C64 + +description = power_2_round returns a remainder of 4096 +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 2C3C585610631E4701AE30F2FA3DF0DA7B607281A51396D7165AAE1D3310295E1C8746F0F3A769952A7D563630B10A5C6305B86AFE0BA7561A00FF86CE5D25E5D8999D12447FF5FCCAA6494A7D61C6C9821477C5147B0B02A9C6218413E5E8071B7B1826EB179771F3B62BFF71F7378034867C5543B645E03FCF7B4662523E5C1604127204064276700542763035473345630064522335721055031526058045630574676140056421116366348274104327731228017724100836361037207200650805235710036867535072630813360230535438206851805466378166186421512041556678521045440876217501360510482316745724203144384731833282068664186364456444326328716170417080333753525342230563158170033177532752262731027163557275765257447024613726486150620514314140622242677046131014680630246055787752253238148624425636722211312343545481621814524810015180085623248762522478248853823485368581372828433063738223220075730516052188530550514413615855836025084856362316852437236047085070368763512834586862163002715678586655745237735778571372076054376673638006407738088856804516161536424710237763714612401676023802157006726748536178350054275700334606448243673615601363163367534712476831672513300034674430126178430088301876066646555582371486880487240537011306072684122201346857851375364801058118430355124240571612633531618104728483858653410800713362777850856556034821328052183074183456872046343700123782645808416062413086767132444324256702185332548430208407224050361348546067758122868387345648742542142524734384063470735248137373271063625046525276063768607656472018672632634343403473165457534364463736803418870635724006430063082108443642180466638042163283412358540780615835120801486762307888384722623242651682382036718185454515207720310531817282634565500512833054018826546667363071425455387788767277645670034228061581771847712750364834550660185621284468754710156052083526681327876713703573275411457050422535250418870670736148330767606060410688271528613457060235848538772043326624417166857308816130765311044885611114121115470801534447755025076056204642711662646311041403228633562557882845548251541627238141218433525662622405520352517615121545403357853545512021053558601473705488212423735223040406574152507836453736255665243466661724117536505766054672274283310246263662013844253763776808065401037710101366843667537252147764655885513140876471862545803362337520222843676106672641216300662800447246632375765250638705063152717450164248788646166177121328413277563255614438402153136610066407781473138042336184360685281420808086047814315278546717307544870304810442768885120725770350217626134454157653326460317773663678017840606163401005831548734654406202500441884161716826060117306774405251850136364261322253087475606404416057886475646675101602362425223183675441134046744626328457273822424602240504307856627664260638232055286431074147582415560670701886310285682103603648000444881651375483776230741111662525641427540486142223160451307323401864517280350108643258754426064213678126353018002282575605018618463770116060844460558406638476372867870154152752684667401735301278753066642215560335321623503262145035877478761271158322550153455863524854685105244615701808058726328880286850424216237628372567433660257546585132303484179D62FCB67B53CAAF584F3E443354450991C02AB1DBE73A6BA8E8B6FCF38F3B90BB8ADC0DD8EEC84122CBBA3C6686326CF59EAE772E6E664796C58DBE2A324BE7AB5DC18FC880C09CFB75878DF8A1F63034C3900292C1A923359366C173A134FB0FE9F46BCF33C3D376DC2EF797F4251ECD8E7C476FC92C25B7456118729EEB14ED82FD7F7C69FA95E244ED573DF0D039C5E9918F25FA88E7E02FBB29291441FA33B57518F53BD3C3306DAEB0D6236E7D4DCC83F6424E635C14A4F5896C149C62A1394E4C27E65C33A8945A347408AF364131FC0FF8FDE65EAE46567292C956798D92134DB1A48E475751B249B0D8BF4B3755F7B694423226677692E9DB0D7E680661DB12E91E699E7D61057DE5B66D4BDB020F5A4159C2576D6F63083757F119CC3665E946CFD04E9104320C90D367F265F178FA405ACF31D1115EB1E520B2F8CD2158909243E85D27E673085C8B7CB9F7A10B24AC41FF3400E12FC7C36BBBA191C9D5662C2CE0A288CAA8F1D9AEB68F3192202E338B1B86C444041BDA16CEE7B43DAAACF2F2DC695275364ABF1D5ABF279EA09112EC123441A00C3282B580A0046674BBF038646653ED0B639C725AA970A7EBC2DCD9B922DF356034A3AD7A43263B6D6A0AA9EE01347EA0BF35C5F7F32C216D2AFEE20A29390D505338B52537EF20AC87CE6A177CEA00547612DC7AF04C45FD31EEE09B4C2C2A6D906D9B11C022991878C4E821943813C53683E851D3FDA37C43DA799610DBDB7C44E124DDEC38A86226DDA921E619BC30F530273C5773472FE4AE27DB232EA155BB255C7E14429FCDD62B77CF3CEDCA8525E4E46985C731C7BDF581E09A964FED04E91F12757A525464C0CFBDAACCA7D68150AEA76127E6D04149FCE8BC7859AEBFAC950F4B0973E2D118DB62704071CA6F4799D45A2493D292A4E0C6BDE38FCE2EBC167BF533AD8A60D76C97DBC19A1F45B979A7583CC9AD5BE21ACCD713E8EFD0A5C25B0A12BFDC4985BAEEA3F506E90B3D03851F8DC5140E52EF53C997ECD9DC79EEC6940B896E2425EAB36CDE668E3AB506AAAF4E59F455509322B1F704EFB3E332F8F9C74CE88047568C921B3352167D6C4BE708F4A90CC27162862052004CAAD837DDD6737384666E98F9E25B1A77B5057B857C9D587C25D7D7A76D20E9629F1C5AC72BC1F2D93A8DDBF415686D49C6C7FC59011F751736052825B1754CAB85044489BC9363FDE7129D57210B877F663E55A54473A09F7F8EC644B2E0A2E66C30B2D070FDF5849AC0C5D3732181E91AEF1DEF619542CFADD394CB4B3A7B4FBB6AE2ABC0A975108CF064219C232F269EAA1CA9B6B6DB48EA7C3C528D0D92D5FFB8DEBEE25D0060CB57F51616639C98E9A262AD29313589B208DAA2996E4FBB2846360C13D0D6E6D3DDB79AA7D85FE963A5DDD9A59A40A6906CD31BE0AC96463D9C5E5829C22868A1FBFC86E148F9231E4C2E5BEC76F0956CCA381E67FA8AACD89EBE4DB0FBE53115737B1642608C9F2A788A513CEFAA6960DE22632D36A37F41860534E031674158F64F500681F774F8E5E22EBB0CA84EFCAFA82D8A5F05A797AB22C770A48926C8EC99C13DFA1938FD502D6957D1EFB57EB624D5FEC6F9464A3AC52E582FB6223709DEC26855DB91D0308AC13DE1832D41031818D602932E960C18B0B4E41EBB249E783AB7B5BBBC8AEB5EA5284A24D825C9CF9291965362C4BD4397DDE15DDD8D7431AB030F5A2A9CE1CF3A04652700E36B7C48C64A3E5E880B9A3C333BF03A90E2F89522F22BCD030577DB0876E246F500F6329B2781EFB894AECF52F834F95A6416686E86704DD07013D90F39C48338F4B556C363B0A9A6E09A28E8FC179CF2C2213BB505F86B21BD3EB7971BB6755CA0155A62154281EE4F0CF42CAA439AB2B75CBAC4A868BA20D72C67F3639258E68855FD1DCB9480BC879D3762029A1C5339DF049E1D3880E7D8413BEB6A83EB13D81DCD0C91E5A44D905093BDC00F89C9A5AF8741EC5F05EC391E30929A6E48DE8B7B186BD0C6B01498EF0EEFA5F516A59518FC12019298A2C7F654F1484EF6503A1D278745ECB8D7362D2529DD5A4512AFAF1659FFDD924D1B2A2DBAE7208A5AB2E124ED58464615E4E343AAE7FB99F4680F830BE68D2139CC6E091381534433EB482C5044B9847CE6104828835DE04908985778A13DACE38C1D390F28A715B895075AD32173BF23FEF12F6E533D8D3744EECD67F9E740B13530F8509DA3AF364D3595685952D3B0E578FA36126736C69D628842400DA5486D6F6C9845847C57B2D7AF12E8B455996327DD5A01AFF3EEB51218E16D0DD9147576A367A29786385E6DCE4AF04934505F65FAB9E54F2A5B6FBFD1BA592BD09D98D02B2E50A046D2AF660140F0B871A14535491B278EB01888554A7D60C06120473387F4BA619F51C4415885B1FD1899AE7BE6DA70B75D50E2426B9247CA55F448BD2A5F9688D60E41A57CA3BA7BBFA5139BA68A66095399C389FA5B234CEEF865A9446B72BD740C534C2F0B8ECCDA5A1101D25176238BD687950ADD41FBCF7DFD7BBA9419C1458AC0CBB7CE85D41DCCB84A616C309FE4555E22587F6EB656A690F8643EDAD05448FAB9A71C530D0DE3AECC7DBBA0499A247E79EA77E99B35ABD10E300470945D567B191FAD0E1B3E383F34EB6728F0281C26D3FA9FF0AB6CE297968071BA8971DECF703F1D21C3F5D10FAC7B405826EF458F9AD11821865A1ECF542A0A27A485DDA5863659DD1CB662CB884EAD304DB16D2745DF0CCA49FCB6CD06121B1EC3E461B6EAC352DC77E67406007E4AD8C4C720FFEE9A5511C2000C707B7B3ECCAF786183E5291B43F846D55BEF9DFA3712F8F438D0E25D8C1EB6A2DED79251B4B4B9AD3D3212113CF3A69A0D6DCCA6127227D8EA355FFE9E9499CE2874C5723685E17FDC77DFAFAB51B2C55703EC270659DEFCCB19378333360FCDFF57DA49F823FAFFFBA6E39DF50AD973484BEA5D4884876AEB2A95CA16111AC02A3365A590B176D2302715C35203D32D3560F88D29CFF6273B24D1D0D51A989D951CDEB2AD316751CAB1B962E5804EBEA323FDDA77F06233E47B0BC182A2010885F955C36911C08D566A1D840649FF48BE98052BD2EBDB11D4A01CC7A18DC932DFA6F7386BE67A5AB1FA50EDCEF70CD624F7B2CFA9C4A729FEE36D4D9206B5BCBFBDDC54C61BEAEC4A71EAD1BDCC6EB8E0461F44EF5924A614DB25418912A89440F8B6171DD0BB5FC218023507BE113E6BD889CAFF54070C095E336BE4C2E28F784904C505164D7DA86D8F725DC496AC257F35B5206C3304FF8DB507169D11D48D6D58676E52A9CC03E7ECB0FAA40774B55F15886595607EE773AB306ACB12B6A56519A02E4C595E5733FA80F6C9FEAA27006E9DC7433FF415C48B9C7FFB0DF2D86BEA275D615D6D3F3E9733D3FC7BB3FE67E586883E2CFD70B853F8E5E771CBC1B2C53DB75CB88FB1F259B46BD13E57CC0AD9DABDDE2D857218C96709102D3D1025AB814360D26D52B7778FCAA5 +valid = true +smlen = 3320 +sm = 3252C634B9EE85C05FB1916F7C3685A1C663A34C1A64DAFEB3B97B21F069FDF838F9851F17CB09AD664B4DBFE549430B0FB07D22F1D2FE8129DE85C2E29004A4BBAF382966EEF89122FA342CF7677FA2C2672726E3329154F9291BBE472E5A49A8F3DDA70764A1AC81EC6BFEB2799EBFE86B0973ADAFA63E5875CA368E8F654F636798C68814606A9B19051666EA9824CC60FD6ED13FF68C5B93B805826643409BA223EB0F932BC6FF5C75BC25099FBD1C6E12B512E97AF21EA0C610D9C00C090D5B1160B1FFABBF02CFEAE290274E95BB75E6A7F8CC73D6A3E511786652142085BBF0665E3DC4AC940E3A0D49FEBDEAC7F6A35D6BFD93551669EBEF0EAE26A212BA8050DAEB06C47A96E22EA48993A702EFCB3FB292D5A2F2B20B5B2B2B6167F5BB7645CA1D8AF8747B207319F48D42A54D3D267396844272ACE71E6431D013C6A308B900C5CFDACF40DA532865DF57BC8626B15285A1911C75C6B7F44621A4A40EF5B4F79C3C9B5D7C26AB76E5EAE17754766819B7D9630C4D973AB85CB721EA7CF88CFC5157D025626AD2A3D58579466FB68D585A048CD311CD87CBECB83079CB71BFF87E38EA69BBAA6883BE0CD47730643E52EA3E21EE8518935D6D79D764B7EE2AE3F68E3334EFE45A3306014A22CD88A660D83980939A1AFF7CB49073EE2073F95AB783669D849219F5B7F2D862EFCAF43B45AF00AEAB14ED06C96FAE0232E4573ACD74751BDB207A23C5FA4A55AD3C28A1914F839E47202E499AF7D443D760B8A08344BBD92080A9218AA7D24B534C71BB6699D3FFB1C61B64E5012778517D4EBE01B6B089D51E702F1EE0CE02D22FAF14EC630E5DB698C0F366BFA8649BADF678BB01AB7073EA50A9DD62F1432EF809760801C6CD8145036526DA0DA5B817B2B066565ECCA455251C0F56B2BCDFD09DE20915524F12D3E0E7E1C532F39BAAA7544221264D9766C49B6F99C597A0773C7C37FB91AAFBD6C261C7EF3A26923254996314DA7133C704C446A8023928300FBCD8BFA1D8C5718B4AB4CD5C3F7A0AEB1CA5F955825CF53D897EB1C4A8EAEDE421A38A79ADB5BF5251F452F9ECCD1C1185BD9EB45F0BDA34EE948B6E060935FD677C7252D64B60DC1B167CB1FB8A1D1C4F31D5947D73E67D436F4653717E330D37A72727B9178B0976A0F8BA25C21CE6B33352FEDBAF605C10C68BDAFD38C7AAB7B8AF606A7C16770B2A3E8B21D56CA2862178E4FAA98F0FD341FA99AFA2039FE69AE1E1A6D5A0F2BBB262136CECD7CE36926EE09FAF17A36F08388A922DC7A565F2E049BAB08D05E9841734578EFAC0D0A8EC8072B30A3CE18A7F6F9E57FD3A857CFD94A5155706714926EA98FF97402322FF1A436AE7E5C5933CDBE1616B2B229BF338F8FA500EE02F584F3762E35362B7C2B5FF101EBBBF4388609604AB32255D3E66FF29413BF9561AFA6B3CCC87FF1133A4D1F678A708C8090140F55B9D25BCA9F5A12F0B5D027FA53D97107E2835F1879B0C9823839EE51643346BCCCAF31DDD7B2D21E7C1DD1AA7B2F2A23D31DB5B20647F908F27E85041E5F442437B18E70E1CCA8FDD6B6B305DF8EFE9BA83D7BC19309BF699808391D0C2FA7E89A9C88F72667118BCA4413483F1951D6C2EAC994A0ED825B23A501DFDDDE2C449063940A48AC25CD36CC1E9B8324B8A42AF3DF49C64E9DAF2EADDE511CA44E8FCF3DC710F85D060D9EEF51A52CFA0F080383D77B3A3B5879F0AD387243B78B434EC5244A7185FEBBB60A981187C54CC479F7ACE7D61E1069776E4EB85BA8E2B42B6B64D74298EB63362E542929DF6A8FB4468D68DCA27892B6280B8231B5098B01546E375571295E86CD5A16753FC8394D22895C12AFDF891E11B867FFEA49372BAED8E820496A7CDE8A1BC4EC545A01E56DD2C639B9EFA3537D1C4FB79A7F03FE8AA44F708350A979B5195EDC49C0E1A12C2AEAB77302371C394A2435F54A3CD2011FDEF514A6E037AE3807C7167161278ED46581C52360BFA14B88CD3A7D737D3EB00447CC8D0F46A2FCFE80FEC05AD9464CC3B3C48975DCA9764DD16067713F2CCC72E29A526F1CA33C1F54FB4CAA2300B8614C229BBB632A905D75760AA8FADE939E8A33857C57FFE5178C3BF1318D082931A18596F5A666866B956D7385737C8731C4CC26215398C6432F47A9AB9F48CDC827E5579354CF7ECD7F2ED6533C1D771FEBD34D25BC0E71DD30483FB9425CEC7F8ACC23CCCB8D08FA543125C8DFF14C6097E06ADD4709D7892921B1F69905661F9020F35267ACA4D99DFBCB3BE28810D4EA53B8283DECED4B221DE1046096AEB85179AED35BCADFD342F993DBA2393FA13AC2FBED9F361D5BF54874552C68FCD3D96650D28F6F07F427876C434A71D72B245D37D4BA7EA7DB2C69CC6198DF0EDF7330F805C10BB70F17D22BB0F456EBBFDFB126FB172A0522D0553B9C85E1BFE41C8083D03DCE5F4095AE837A3AF5F1921AF474544F68AA628F74B203B744A36F0CAFA5B99747EC09BCA01F8134B7062E6B8D2A949CFD21013AFC82093EA42AE917F2843DDE2ADC1140CC4A981BBFB8CD690EF3E9B5AD79DFCB48B441BCF8AEA715EBC3B42BC90FA98EC08CB7A4C9054350E915734E31A768BE190CFA7216F4CA36C3D387BCC30F6544540289D4749164EA19D152F5CA77D5B303BAAC1476060B97681B0E35A1E9FA4AD3B230C8226666A24D4A54CD97B4528A0DF6C4070D7CA1B43F9AD213E94A8523812F663D7EA802837CC757BADE7D35619314F97E232F029CAD77C4B8A53B9770BED9BC7B87A0D0D53B3E3B7170653AC832E73021082FBF15CA74DD1069F0EC08BB50BC0FAEE60AD220119433E80D4AD0E962B548DD7691CBFA5CE76FE47DA08A5D0D3197D7BB4E133AC0BB74C59F3E167FC65BEB5FDAF07939991D48C596EEFC78B1A52F69A39E11BDEBBE056B10C5FCF2E86AF6FFB87708CB8C0315DBE641D7F295BEA6A9DC83A8C8B704832C383C9BB70847F3C1227EA907B12B9AFD0DC6F4D2326C25F238C1728E69878847F6CB590BEB592F24ADE9120230CEECF9E1C05D474CAB335A3FE04C6B30792B91F8DAAB5651E58FCBB5F79AD69411C27468B63A0398E26D0913CD8F5EDDA187EE2077B3201215D96D7F628B207E2DA29557F0B81F21EE66E331EB06BFA6B5C78C19B0FC8F6FC2CFF999AB25C18BFD7D63E3918AAA4C3DC16203F706EBD63281CA69B7F2964A24E7DD946BB213C1408CB14F9DE7B4D74C3BEF3A3E571BB4B5F59C7C7D2AC404A45BE0EE191DD45FAC05402FE4D238385EF6CFA3F19D9F48B990356E8C5A4491FE339DDD120B2804C8B51AF093CFD66917C2D1F56CAC546DA1B195261E9C54F988878AC76B64D4E13259A61C1D45B6F8A7943C40A57CA2C4E3A48B3056F9BF8BB30B9AAA3493E4C73150D14A0DDB97449C77259CA370CC889A82F4E74AB04579A5D515FE2BED5689A56DBCCD3EEC1304E554E7AC13F6F95A88716B27A1C8A9F4FE148DB5BC4C3F74C9148803B0AEF6002CD0F4D6740FE7C2394EEB888AA33BB03CE580417D55F7C6D7405685CAE1AB111ADBE13572BA9DC5A4BCF618435E61E13B056EE47D601D39FF2ED9094C5AA558CF4805E90593E16138025590CCCA86E57C1F983807D391AF9F3A5B7F3D2DC25726A0F39E5DF5AA8D0A763359AD4827AA2FD511D3409008665347610954734E367193EEF3BAA492D0928686D944EF2158B6966C39A131B06D091781F4A2242B8BECD7E1DD4EBC30F06A773954154D6104D68970CCEBEC727D4D157EAF456CA7F1AFCA87FA14DD07B4DC510E800898ECD5E250151BC82B97C821CF3AAA98D677FAF56DE996D042FDF0CD8E8EB44A10CAC17B3789F32BE8846F2D034D435390E921618166C995B917734B9F096987BBA505AA1AAA722CD8D217A5D23050CCF786FB3A7744B555B243547018B3C162AC81A996689AAEE7A1AC6CDFCA62C906DDDAE7F162BDC125E4B920607C0E43C80C5B59C23FF9F762A265463B87967C027D43FAA65584A592ACEF698188B019FF2DBEB552028FB1D67404ECF940827E5C4AB63F4DC0B3B49B23F50CA74E08F204F218EF490DF434CA51B57A5F0127343FBC393DFB66AA0D83F4BBB929A3C98DDEE8FF0299FDCAB059D4ED9382E098DF497457D9B25784A53E779C4C73D7ECB2ED3639522CD8BFA958811740E8D7695D084AB0E597A2DEA8085C536094623A395E1DBD25A246DDC73EAB1C759417530731BBDFD4DD94367DCCB9AC3FA758C35B7B30C62E7620DB96E2FCEA2A91144A6876BDD0471044271B9C625097EAA4C4268547E7D66D1A1B4F998F23763890CD4A01BA45E99CD6174756AF676F27DA6FE6B1F0FF648845714F46C02A917716E150B3812B2CDC64FD59E11C3FE2BDC2327E8B34DCA44BD19A65B74B2AC65B7D1A16844B8CDD87D6A2C4972CBB8115E05FC71B68ECB7FEAC54CE4AF5A8B40CEB26DD97C066E7004CC1D7549D6E1200CE2DD133A25AB175857BF7359BF84494392A9BA4C1C9923F7884AEF54512D5F4C9D5E07F0D9FB564611DF44A2988950E8D3FD999462892A66D63578FCA06DD06A8F1955CFF3ADA5EF22417FECF4523D6616D27842E23D94A2E31F81A9ABE9FF072E507A95BE04618AB3C3CE1A41498CE72B3B4F7C96C3D2E70000000000000000000000000000000000000000040A10161B2348656C6C6F20776F726C64 + +description = power_2_round returns a remainder of -4095 +mlen = 11 +msg = 48656C6C6F20776F726C64 +sk = 2C3C585610631E4701AE30F2FA3DF0DA7B607281A51396D7165AAE1D3310295E1C8746F0F3A769952A7D563630B10A5C6305B86AFE0BA7561A00FF86CE5D25E5D8999D12447FF5FCCAA6494A7D61C6C9821477C5147B0B02A9C6218413E5E8071B7B1826EB179771F3B62BFF71F7378034867C5543B645E03FCF7B4662523E5C1604127204064276700542763035473345630064522335721055031526058045630574676140056421116366348274104327731228017724100836361037207200650805235710036867535072630813360230535438206851805466378166186421512041556678521045440876217501360510482316745724203144384731833282068664186364456444326328716170417080333753525342230563158170033177532752262731027163557275765257447024613726486150620514314140622242677046131014680630246055787752253238148624425636722211312343545481621814524810015180085623248762522478248853823485368581372828433063738223220075730516052188530550514413615855836025084856362316852437236047085070368763512834586862163002715678586655745237735778571372076054376673638006407738088856804516161536424710237763714612401676023802157006726748536178350054275700334606448243673615601363163367534712476831672513300034674430126178430088301876066646555582371486880487240537011306072684122201346857851375364801058118430355124240571612633531618104728483858653410800713362777850856556034821328052183074183456872046343700123782645808416062413086767132444324256702185332548430208407224050361348546067758122868387345648742542142524734384063470735248137373271063625046525276063768607656472018672632634343403473165457534364463736803418870635724006430063082108443642180466638042163283412358540780615835120801486762307888384722623242651682382036718185454515207720310531817282634565500512833054018826546667363071425455387788767277645670034228061581771847712750364834550660185621284468754710156052083526681327876713703573275411457050422535250418870670736148330767606060410688271528613457060235848538772043326624417166857308816130765311044885611114121115470801534447755025076056204642711662646311041403228633562557882845548251541627238141218433525662622405520352517615121545403357853545512021053558601473705488212423735223040406574152507836453736255665243466661724117536505766054672274283310246263662013844253763776808065401037710101366843667537252147764655885513140876471862545803362337520222843676106672641216300662800447246632375765250638705063152717450164248788646166177121328413277563255614438402153136610066407781473138042336184360685281420808086047814315278546717307544870304810442768885120725770350217626134454157653326460317773663678017840606163401005831548734654406202500441884161716826060117306774405251850136364261322253087475606404416057886475646675101602362425223183675441134046744626328457273822424602240504307856627664260638232055286431074147582415560670701886310285682103603648000444881651375483776230741111662525641427540486142223160451307323401864517280350108643258754426064213678126353018002282575605018618463770116060844460558406638476372867870154152752684667401735301278753066642215560335321623503262145035877478761271158322550153455863524854685105244615701808058726328880286850424216237628372567433660257546585132303484179D62FCB67B53CAAF584F3E443354450991C02AB1DBE73A6BA8E8B6FCF38F3B90BB8ADC0DD8EEC84122CBBA3C6686326CF59EAE772E6E664796C58DBE2A324BE7AB5DC18FC880C09CFB75878DF8A1F63034C3900292C1A923359366C173A134FB0FE9F46BCF33C3D376DC2EF797F4251ECD8E7C476FC92C25B7456118729EEB14ED82FD7F7C69FA95E244ED573DF0D039C5E9918F25FA88E7E02FBB29291441FA33B57518F53BD3C3306DAEB0D6236E7D4DCC83F6424E635C14A4F5896C149C62A1394E4C27E65C33A8945A347408AF364131FC0FF8FDE65EAE46567292C956798D92134DB1A48E475751B249B0D8BF4B3755F7B694423226677692E9DB0D7E680661DB12E91E699E7D61057DE5B66D4BDB020F5A4159C2576D6F63083757F119CC3665E946CFD04E9104320C90D367F265F178FA405ACF31D1115EB1E520B2F8CD2158909243E85D27E673085C8B7CB9F7A10B24AC41FF3400E12FC7C36BBBA191C9D5662C2CE0A288CAA8F1D9AEB68F3192202E338B1B86C444041BDA16CEE7B43DAAACF2F2DC695275364ABF1D5ABF279EA09112EC123441A00C3282B580A0046674BBF038646653ED0B639C725AA970A7EBC2DCD9B922DF356034A3AD7A43263B6D6A0AA9EE01347EA0BF35C5F7F32C216D2AFEE20A29390D505338B52537EF20AC87CE6A177CEA00547612DC7AF04C45FD31EEE09B4C2C2A6D906D9B11C022991878C4E821943813C53683E851D3FDA37C43DA799610DBDB7C44E124DDEC38A86226DDA921E619BC30F530273C5773472FE4AE27DB232EA155BB255C7E14429FCDD62B77CF3CEDCA8525E4E46985C731C7BDF581E09A964FED04E91F12757A525464C0CFBDAACCA7D68150AEA76127E6D04149FCE8BC7859AEBFAC950F4B0973E2D118DB62704071CA6F4799D45A2493D292A4E0C6BDE38FCE2EBC167BF533AD8A60D76C97DBC19A1F45B979A7583CC9AD5BE21ACCD713E8EFD0A5C25B0A12BFDC4985BAEEA3F506E90B3D03851F8DC5140E52EF53C997ECD9DC79EEC6940B896E2425EAB36CDE668E3AB506AAAF4E59F455509322B1F704EFB3E332F8F9C74CE88047568C921B3352167D6C4BE708F4A90CC27162862052004CAAD837DDD6737384666E98F9E25B1A77B5057B857C9D587C25D7D7A76D20E9629F1C5AC72BC1F2D93A8DDBF415686D49C6C7FC59011F751736052825B1754CAB85044489BC9363FDE7129D57210B877F663E55A54473A09F7F8EC644B2E0A2E66C30B2D070FDF5849AC0C5D3732181E91AEF1DEF619542CFADD394CB4B3A7B4FBB6AE2ABC0A975108CF064219C232F269EAA1CA9B6B6DB48EA7C3C528D0D92D5FFB8DEBEE25D0060CB57F51616639C98E9A262AD29313589B208DAA2996E4FBB2846360C13D0D6E6D3DDB79AA7D85FE963A5DDD9A59A40A6906CD31BE0AC96463D9C5E5829C22868A1FBFC86E148F9231E4C2E5BEC76F0956CCA381E67FA8AACD89EBE4DB0FBE53115737B1642608C9F2A788A513CEFAA6960DE22632D36A37F41860534E031674158F64F500681F774F8E5E22EBB0CA84EFCAFA82D8A5F05A797AB22C770A48926C8EC99C13DFA1938FD502D6957D1EFB57EB624D5FEC6F9464A3AC52E582FB6223709DEC26855DB91D0308AC13DE1832D41031818D602932E960C18B0B4E41EBB249E783AB7B5BBBC8AEB5EA5284A24D825C9CF9291965362C4BD4397DDE15DDD8D7431AB030F5A2A9CE1CF3A04652700E36B7C48C64A3E5E880B9A3C333BF03A90E2F89522F22BCD030577DB0876E246F500F6329B2781EFB894AECF52F834F95A6416686E86704DD07013D90F39C48338F4B556C363B0A9A6E09A28E8FC179CF2C2213BB505F86B21BD3EB7971BB6755CA0155A62154281EE4F0CF42CAA439AB2B75CBAC4A868BA20D72C67F3639258E68855FD1DCB9480BC879D3762029A1C5339DF049E1D3880E7D8413BEB6A83EB13D81DCD0C91E5A44D905093BDC00F89C9A5AF8741EC5F05EC391E30929A6E48DE8B7B186BD0C6B01498EF0EEFA5F516A59518FC12019298A2C7F654F1484EF6503A1D278745ECB8D7362D2529DD5A4512AFAF1659FFDD924D1B2A2DBAE7208A5AB2E124ED58464615E4E343AAE7FB99F4680F830BE68D2139CC6E091381534433EB482C5044B9847CE6104828835DE04908985778A13DACE38C1D390F28A715B895075AD32173BF23FEF12F6E533D8D3744EECD67F9E740B13530F8509DA3AF364D3595685952D3B0E578FA36126736C69D628842400DA5486D6F6C9845847C57B2D7AF12E8B455996327DD5A01AFF3EEB51218E16D0DD9147576A367A29786385E6DCE4AF04934505F65FAB9E54F2A5B6FBFD1BA592BD09D98D02B2E50A046D2AF660140F0B871A14535491B278EB01888554A7D60C06120473387F4BA619F51C4415885B1FD1899AE7BE6DA70B75D50E2426B9247CA55F448BD2A5F9688D60E41A57CA3BA7BBFA5139BA68A66095399C389FA5B234CEEF865A9446B72BD740C534C2F0B8ECCDA5A1101D25176238BD687950ADD41FBCF7DFD7BBA9419C1458AC0CBB7CE85D41DCCB84A616C309FE4555E22587F6EB656A690F8643EDAD05448FAB9A71C530D0DE3AECC7DBBA0499A247E79EA77E99B35ABD10E300470945D567B191FAD0E1B3E383F34EB6728F0281C26D3FA9FF0AB6CE297968071BA8971DECF703F1D21C3F5D10FAC7B405826EF458F9AD11821865A1ECF542A0A27A485DDA5863659DD1CB662CB884EAD304DB16D2745DF0CCA49FCB6CD06121B1EC3E461B6EAC352DC77E67406007E4AD8C4C720FFEE9A5511C2000C707B7B3ECCAF786183E5291B43F846D55BEF9DFA3712F8F438D0E25D8C1EB6A2DED79251B4B4B9AD3D3212113CF3A69A0D6DCCA6127227D8EA355FFE9E9499CE2874C5723685E17FDC77DFAFAB51B2C55703EC270659DEFCCB19378333360FCDFF57DA49F823FAFFFBA6E39DF50AD973484BEA5D4884876AEB2A95CA16111AC02A3365A590B176D2302715C35203D32D3560F88D29CFF6273B24D1D0D51A989D951CDEB2AD316751CAB1B962E5804EBEA323FDDA77F06233E47B0BC182A2010885F955C36911C08D566A1D840649FF48BE98052BD2EBDB11D4A01CC7A18DC932DFA6F7386BE67A5AB1FA50EDCEF70CD624F7B2CFA9C4A729FEE36D4D9206B5BCBFBDDC54C61BEAEC4A71EAD1BDCC6EB8E0461F44EF5924A614DB25418912A89440F8B6171DD0BB5FC218023507BE113E6BD889CAFF54070C095E336BE4C2E28F784904C505164D7DA86D8F725DC496AC257F35B5206C3304FF8DB507169D11D48D6D58676E52A9CC03E7ECB0FAA40774B55F15886595607EE773AB306ACB12B6A56519A02E4C595E5733FA80F6C9FEAA27006E9DC7433FF415C48B9C7FFB0DF2D86BEA275D615D6D3F3E9733D3FC7BB3FE67E586883E2CFD70B853F8E5E771CBC1B2C53DB75CB88FB1F259B46BD13E57CC0AD9DABDDE2D857218C96709102D3D1025AB814360D26D52B7778FCAA5 +valid = true +smlen = 3320 +sm = 3252C634B9EE85C05FB1916F7C3685A1C663A34C1A64DAFEB3B97B21F069FDF838F9851F17CB09AD664B4DBFE549430B0FB07D22F1D2FE8129DE85C2E29004A4BBAF382966EEF89122FA342CF7677FA2C2672726E3329154F9291BBE472E5A49A8F3DDA70764A1AC81EC6BFEB2799EBFE86B0973ADAFA63E5875CA368E8F654F636798C68814606A9B19051666EA9824CC60FD6ED13FF68C5B93B805826643409BA223EB0F932BC6FF5C75BC25099FBD1C6E12B512E97AF21EA0C610D9C00C090D5B1160B1FFABBF02CFEAE290274E95BB75E6A7F8CC73D6A3E511786652142085BBF0665E3DC4AC940E3A0D49FEBDEAC7F6A35D6BFD93551669EBEF0EAE26A212BA8050DAEB06C47A96E22EA48993A702EFCB3FB292D5A2F2B20B5B2B2B6167F5BB7645CA1D8AF8747B207319F48D42A54D3D267396844272ACE71E6431D013C6A308B900C5CFDACF40DA532865DF57BC8626B15285A1911C75C6B7F44621A4A40EF5B4F79C3C9B5D7C26AB76E5EAE17754766819B7D9630C4D973AB85CB721EA7CF88CFC5157D025626AD2A3D58579466FB68D585A048CD311CD87CBECB83079CB71BFF87E38EA69BBAA6883BE0CD47730643E52EA3E21EE8518935D6D79D764B7EE2AE3F68E3334EFE45A3306014A22CD88A660D83980939A1AFF7CB49073EE2073F95AB783669D849219F5B7F2D862EFCAF43B45AF00AEAB14ED06C96FAE0232E4573ACD74751BDB207A23C5FA4A55AD3C28A1914F839E47202E499AF7D443D760B8A08344BBD92080A9218AA7D24B534C71BB6699D3FFB1C61B64E5012778517D4EBE01B6B089D51E702F1EE0CE02D22FAF14EC630E5DB698C0F366BFA8649BADF678BB01AB7073EA50A9DD62F1432EF809760801C6CD8145036526DA0DA5B817B2B066565ECCA455251C0F56B2BCDFD09DE20915524F12D3E0E7E1C532F39BAAA7544221264D9766C49B6F99C597A0773C7C37FB91AAFBD6C261C7EF3A26923254996314DA7133C704C446A8023928300FBCD8BFA1D8C5718B4AB4CD5C3F7A0AEB1CA5F955825CF53D897EB1C4A8EAEDE421A38A79ADB5BF5251F452F9ECCD1C1185BD9EB45F0BDA34EE948B6E060935FD677C7252D64B60DC1B167CB1FB8A1D1C4F31D5947D73E67D436F4653717E330D37A72727B9178B0976A0F8BA25C21CE6B33352FEDBAF605C10C68BDAFD38C7AAB7B8AF606A7C16770B2A3E8B21D56CA2862178E4FAA98F0FD341FA99AFA2039FE69AE1E1A6D5A0F2BBB262136CECD7CE36926EE09FAF17A36F08388A922DC7A565F2E049BAB08D05E9841734578EFAC0D0A8EC8072B30A3CE18A7F6F9E57FD3A857CFD94A5155706714926EA98FF97402322FF1A436AE7E5C5933CDBE1616B2B229BF338F8FA500EE02F584F3762E35362B7C2B5FF101EBBBF4388609604AB32255D3E66FF29413BF9561AFA6B3CCC87FF1133A4D1F678A708C8090140F55B9D25BCA9F5A12F0B5D027FA53D97107E2835F1879B0C9823839EE51643346BCCCAF31DDD7B2D21E7C1DD1AA7B2F2A23D31DB5B20647F908F27E85041E5F442437B18E70E1CCA8FDD6B6B305DF8EFE9BA83D7BC19309BF699808391D0C2FA7E89A9C88F72667118BCA4413483F1951D6C2EAC994A0ED825B23A501DFDDDE2C449063940A48AC25CD36CC1E9B8324B8A42AF3DF49C64E9DAF2EADDE511CA44E8FCF3DC710F85D060D9EEF51A52CFA0F080383D77B3A3B5879F0AD387243B78B434EC5244A7185FEBBB60A981187C54CC479F7ACE7D61E1069776E4EB85BA8E2B42B6B64D74298EB63362E542929DF6A8FB4468D68DCA27892B6280B8231B5098B01546E375571295E86CD5A16753FC8394D22895C12AFDF891E11B867FFEA49372BAED8E820496A7CDE8A1BC4EC545A01E56DD2C639B9EFA3537D1C4FB79A7F03FE8AA44F708350A979B5195EDC49C0E1A12C2AEAB77302371C394A2435F54A3CD2011FDEF514A6E037AE3807C7167161278ED46581C52360BFA14B88CD3A7D737D3EB00447CC8D0F46A2FCFE80FEC05AD9464CC3B3C48975DCA9764DD16067713F2CCC72E29A526F1CA33C1F54FB4CAA2300B8614C229BBB632A905D75760AA8FADE939E8A33857C57FFE5178C3BF1318D082931A18596F5A666866B956D7385737C8731C4CC26215398C6432F47A9AB9F48CDC827E5579354CF7ECD7F2ED6533C1D771FEBD34D25BC0E71DD30483FB9425CEC7F8ACC23CCCB8D08FA543125C8DFF14C6097E06ADD4709D7892921B1F69905661F9020F35267ACA4D99DFBCB3BE28810D4EA53B8283DECED4B221DE1046096AEB85179AED35BCADFD342F993DBA2393FA13AC2FBED9F361D5BF54874552C68FCD3D96650D28F6F07F427876C434A71D72B245D37D4BA7EA7DB2C69CC6198DF0EDF7330F805C10BB70F17D22BB0F456EBBFDFB126FB172A0522D0553B9C85E1BFE41C8083D03DCE5F4095AE837A3AF5F1921AF474544F68AA628F74B203B744A36F0CAFA5B99747EC09BCA01F8134B7062E6B8D2A949CFD21013AFC82093EA42AE917F2843DDE2ADC1140CC4A981BBFB8CD690EF3E9B5AD79DFCB48B441BCF8AEA715EBC3B42BC90FA98EC08CB7A4C9054350E915734E31A768BE190CFA7216F4CA36C3D387BCC30F6544540289D4749164EA19D152F5CA77D5B303BAAC1476060B97681B0E35A1E9FA4AD3B230C8226666A24D4A54CD97B4528A0DF6C4070D7CA1B43F9AD213E94A8523812F663D7EA802837CC757BADE7D35619314F97E232F029CAD77C4B8A53B9770BED9BC7B87A0D0D53B3E3B7170653AC832E73021082FBF15CA74DD1069F0EC08BB50BC0FAEE60AD220119433E80D4AD0E962B548DD7691CBFA5CE76FE47DA08A5D0D3197D7BB4E133AC0BB74C59F3E167FC65BEB5FDAF07939991D48C596EEFC78B1A52F69A39E11BDEBBE056B10C5FCF2E86AF6FFB87708CB8C0315DBE641D7F295BEA6A9DC83A8C8B704832C383C9BB70847F3C1227EA907B12B9AFD0DC6F4D2326C25F238C1728E69878847F6CB590BEB592F24ADE9120230CEECF9E1C05D474CAB335A3FE04C6B30792B91F8DAAB5651E58FCBB5F79AD69411C27468B63A0398E26D0913CD8F5EDDA187EE2077B3201215D96D7F628B207E2DA29557F0B81F21EE66E331EB06BFA6B5C78C19B0FC8F6FC2CFF999AB25C18BFD7D63E3918AAA4C3DC16203F706EBD63281CA69B7F2964A24E7DD946BB213C1408CB14F9DE7B4D74C3BEF3A3E571BB4B5F59C7C7D2AC404A45BE0EE191DD45FAC05402FE4D238385EF6CFA3F19D9F48B990356E8C5A4491FE339DDD120B2804C8B51AF093CFD66917C2D1F56CAC546DA1B195261E9C54F988878AC76B64D4E13259A61C1D45B6F8A7943C40A57CA2C4E3A48B3056F9BF8BB30B9AAA3493E4C73150D14A0DDB97449C77259CA370CC889A82F4E74AB04579A5D515FE2BED5689A56DBCCD3EEC1304E554E7AC13F6F95A88716B27A1C8A9F4FE148DB5BC4C3F74C9148803B0AEF6002CD0F4D6740FE7C2394EEB888AA33BB03CE580417D55F7C6D7405685CAE1AB111ADBE13572BA9DC5A4BCF618435E61E13B056EE47D601D39FF2ED9094C5AA558CF4805E90593E16138025590CCCA86E57C1F983807D391AF9F3A5B7F3D2DC25726A0F39E5DF5AA8D0A763359AD4827AA2FD511D3409008665347610954734E367193EEF3BAA492D0928686D944EF2158B6966C39A131B06D091781F4A2242B8BECD7E1DD4EBC30F06A773954154D6104D68970CCEBEC727D4D157EAF456CA7F1AFCA87FA14DD07B4DC510E800898ECD5E250151BC82B97C821CF3AAA98D677FAF56DE996D042FDF0CD8E8EB44A10CAC17B3789F32BE8846F2D034D435390E921618166C995B917734B9F096987BBA505AA1AAA722CD8D217A5D23050CCF786FB3A7744B555B243547018B3C162AC81A996689AAEE7A1AC6CDFCA62C906DDDAE7F162BDC125E4B920607C0E43C80C5B59C23FF9F762A265463B87967C027D43FAA65584A592ACEF698188B019FF2DBEB552028FB1D67404ECF940827E5C4AB63F4DC0B3B49B23F50CA74E08F204F218EF490DF434CA51B57A5F0127343FBC393DFB66AA0D83F4BBB929A3C98DDEE8FF0299FDCAB059D4ED9382E098DF497457D9B25784A53E779C4C73D7ECB2ED3639522CD8BFA958811740E8D7695D084AB0E597A2DEA8085C536094623A395E1DBD25A246DDC73EAB1C759417530731BBDFD4DD94367DCCB9AC3FA758C35B7B30C62E7620DB96E2FCEA2A91144A6876BDD0471044271B9C625097EAA4C4268547E7D66D1A1B4F998F23763890CD4A01BA45E99CD6174756AF676F27DA6FE6B1F0FF648845714F46C02A917716E150B3812B2CDC64FD59E11C3FE2BDC2327E8B34DCA44BD19A65B74B2AC65B7D1A16844B8CDD87D6A2C4972CBB8115E05FC71B68ECB7FEAC54CE4AF5A8B40CEB26DD97C066E7004CC1D7549D6E1200CE2DD133A25AB175857BF7359BF84494392A9BA4C1C9923F7884AEF54512D5F4C9D5E07F0D9FB564611DF44A2988950E8D3FD999462892A66D63578FCA06DD06A8F1955CFF3ADA5EF22417FECF4523D6616D27842E23D94A2E31F81A9ABE9FF072E507A95BE04618AB3C3CE1A41498CE72B3B4F7C96C3D2E70000000000000000000000000000000000000000040A10161B2348656C6C6F20776F726C64 + diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/edge_cases_draft_dilithium3_verify.txt b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/edge_cases_draft_dilithium3_verify.txt new file mode 100644 index 0000000000..231cdd2563 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/edge_cases_draft_dilithium3_verify.txt @@ -0,0 +1,640 @@ +description = baseline +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = short public key +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB93 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = long public key +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB938000 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = short signature +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3319 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F48656C6C6F20776F726C64 + +description = long signature +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3321 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F240048656C6C6F20776F726C64 + +description = signature with a bit flip in c_tilde +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3320 +sm = 6489E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = signature with a bit flip in z[0] +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B38B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = signature with a bit flip in z[1] +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435C08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = signature with a bit flip in z[2] +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAFC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = signature with a bit flip in z[3] +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119CC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = signature with a bit flip in z[4] +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9FE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = signature with a bit flip in hints +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4072B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = signature with a bit flip in the last byte +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2548656C6C6F20776F726C64 + +description = signature with hints in reverse order +mlen = 32 +msg = 0100000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3341 +sm = E1412C0A8930EBD5BE73CFF29B68C3AD7426551E499553D7CAB9B65A984CDA37D793CFA5011EF4470DC57BF0C7D1C25449CD23C82868180997EF617A42D425CC5E1DCB6127D3B60E017A9AE1AC7DFE980DEBB098F6099D4A5D497B0EA1A063F863D484A697F9E4B87652249301455276EAEAAE6E5B9C32991BB3A247F5EB6A64049C317A2E262BC9FBEBAA53E1203D780AACDF8D8C1DF9D104DB25002257CFE39C49E88EE0ADAC298199EE0285AAB5966C4DECCCDD64FF86A76DA9FCB17765C10CE7EE8272595B0DECCC58C8D89D11B78E56A4CC63B19D7D787988256A277B53BA7D99C1930BBF1CD550ACF5C97F6F1B1BBDC6A9CD0C3BE66672724E9ACD89240987B0B17F9BB38B8B323E21B7DF3A056B85CC41288D34707DDC050B8484598EDE78EA295774222EF491F0D621509C9361B7C8537A4904E2E5ED1640968FA6DFCD828C8BA6E771F970ACA894F0D57CD03CE325F4C3176B818F42F29C8646948B58796542DA63FFC905171129418A349C0783EBF5AE14B3FEE69492293AD3894345F07EDDAC036C40AD5215D4827DE6A0EA0B4BD2DD86826C7F5C340FD2D62062A41C075259A9ECB3ACE3722D3768D5A7D355373E3DE4D6F87A408E5BDE672F414826A2C6714A706198723D6E41FEB39302B155F775BDD01B7CB4925B75AA1D0A0D533A2FBDABF68D03592DE2B24A39D2D093FEA87CA57E16622E59B46988D7057540A511506C1E7C819D8697564E161FB221DE02DB05B8715D7E8CB81B96BF41B257FE6C5DBD8AB7E4B6CDE8A7E15077B3318C7D6B7C301C0EF33CF1F1C65668CE0106A259A599A4034010F5809FA7E781665D866DEC4A5BE77E8CD090A324FBD25CC07929B773CD8358D666ED767DB22D540829F4BC09C3A60448A23EE40E09EC699C784649331563EB114EC47C8F1731DB50761DDD7C972553E9819DB31148FB97D3B4C9FBB89AF7E87033536455F9FEFDF8566B6EB0100040ECD080287DA76A7791CB90AF6253E701D9705AF96B3597596AA58B9B0FDD7689ECA35A7AA7C21B71BD80C3921449D3C5C8D9A26BD386B5C4002C8050B6C7F2489BEE49B18BA85652D4B528BEB21F35C4C9AB1F5E7F5FA4098B2D470BE2CDA7087C61C4F40E771AC04193DED1C45B0AD787BE20ACF7C9393671C354DD70E93618BCF89F684C9FB7C8FCBD004B737A65350E912A1945FA6F6F082406526F8B8B4603E171B754A3F571B7933E07BC9971ED2C299C4BBB4293B3282E34FC1244AD5C4C985ACD31D4F2EB5B82E5B5E1F00C9BE628E0A317885AB6E26AA7667C73C12F541CDF463CD72798CB1F7908D2945A131CA8AC4BA6343BC4FCF7DCA98F30B0FEADE3F0841EE280DA51D9501B5CEAFCCDB8319F9B32DF23E74A12B4B61C44B3005EE58160C85302C141DBD6FE0D598B2886824B1BDADC874C530DF612FE5260E996C6D289A2A5F3F811F2B50CAC599477F9D8400298981654013858E4ADF2B6A67DAF24A5099E9A44F5DFC37B2DAFC4AA738D4690F9650F019583EAAEDDF32BA74C3468863CFD565D06FB26601EA919B68985F5B7F036B2EF1B7B0F6A738E292BE4B263D30EA5D9784221C09DD6BD77F26DAA6996BCE002783305E478CC1CAC235DA49057DA7F9CF7B8E25AE6FB02A46AD93EBC5D9440BDD07018AE26DE5C51C87556AD561F3C7E130A24685F3FB9E39518C1E9D26C5BE936CF3F9F08C464FD0A32502604A349C8956541D94CC0F11BD5A0733737FD75ECF57678264E63CE8B5323A0630A40CD6032D62ED84951427A5162AC1685F8682EE7D31621F6A77ADE12ACDE5634BC44B21A2E1CAFE4A689E0D30AC3D03A6903F75393BE77FED6BE1F970A4BD7F2E666721E271E155223C03C7068E4D9B348159ED8B09D14DF65F4D86AE612CE3A931FC4A66C60DA424D5C2CDA9FBD7115B771E3262AC7788C70F6C0241DED2B9DC0D936E613C795F69D65539FE00AE8E7EFDF07BC068EA4BB9BD83F5A64E970BAE105036435BCFB23934DC13027ECFE3DFB7A1E9D3F7B2B07DBA844598D4CF53D39FCE8C0485B8EEE92671CE8ED10B262E63944A1EE4889494917FA81E01B145B17FCBBD079E8574DF474362FEF1F48EAC5B8A443973B75E72330EB03E15DECFB18F69D10343F2DAF0CCECA3436C20612091E3BA0940DD3A5D5489338578E0E90F3795A7380D577A67E52ADF7358F2E7AAACC75BBB81537134A12771C1539AD42307BB2C1A5277C123F10B74216CCE836E78D24DC3AD7E794BFDBA4D0306A519CB122E3B2D5A6769EF54636F4398E87BD42B0E6229DD7F430F5C6BD610F9C67C68F1F7A687B98C2E5A61CE50C9989A8DE3F53C975BB75B97CCDEB3E0FB7C26F368B29DF709F18193B9BE27FEC820136D8BBB9A037C13B03E8FFE2484D948A284D505916EE424414C5DAF57514FDE0A84665B2C31E2D4C8FDE45BFDB2CA08E9974EA9449C5F332CDDCAA46140F08DEEB3F0B4BDA7BE04446239C7AF4949FAB33B40DBA8FEED31D45F85507FC232FDAD3C85595643B4A7F2503C4BFC4B3C55D969AF6AC80A3C02AF1F5BEBD23A66700733B36F133951193A1FCE5D429B6200FDAF383798A1D11F3CD6536D3F9D27B58A5388482279F925A8EC2850DB90F5F70650B0045B4002B952C36B460A5B566FD3BA2BF5BCDBA0378C54AC9C12CCB46C7FE110AA99DBAE10D5CEFAB484A3ABBD517DB89C71D60ED26FEE9D55E73BD4CE16D898BA426A683B842885B514370F6D854321E599E24EDEC6C3A0DB6F73C60BB36433EC58E162D6FFE8BBF2D345421341EC22E1D25FC740EC4D3D78B79484387A9207B9B48EC8585FB9F6BB4F776BF71FE7834D95BF4C6312D430EB79877FC71EA67EC4080C359D4C4901596E93EDF71C6B3AE2EDD5D491DEA03186BD3FB24527E7F99C708FBA19D606CC44EC5E1FFAA33CD2710CEBF4D4B5869230B151CA8472D35A49CDA5367098CF3AD4DDAF1838E77476108EAD4C399938FF0CBDCD226B6F06D5323C3D885FF1B043E6A32CDE2E052C7D5C273B5354EB020A81D4F9BBA9FD29A5148359750EC9CEB6AA9906047F1FE4191D07A0B018DF93BFCD96FF4AF3BEEC9C5E5EB5884B32BC84F66570B9B57F506443FF634056B504871E4B75CC1BEA1EBC8A9D5D07C9EA587B70EEA92B93F65C3194B343CBFDC28D1A76DAF95303C9C4EC0034FCA333628720BDDA7A3373D676E2928C08684E9D24EED7D9382AAE547CAD5837D6E1BE3E7245E947053EE2219D39E33218D9AE52F6B5EB487B0E5B16AC35FFFC45AC1D832DF711CB11B2A887647BC2C3713945F92103F3EE2A52AD946B0D38BC0BD92E701C7E7D4AEA25E6AA4FF2A42CCBF5DA9BB99F88351076AF1FB4E7CAA65DC23A78372E1C2FA09BA8D46152CDA3ECC8A9288598BED37E4D11507E6B5E239F377D1DC5AFAC7FB38FFBB7B2D4ABC6BD74771923AE17CDE020B34151D2555FDC1C09848196DAAB35745D88B80A79CE2BC86BFE7397EDBD9F16188A133B2900FEDB915629B3104DD6F00CD1403F8A62F71756D614C0224276594D4FB74891D1A2F93F43157B0A6A4135DD65FE25D227BE62AFE953667147FE7D3D486BC6D5436B218FB9AD0C6DF31CE8FCAFE01B81561E02AD5D34A0B669345A74AE16F651FAE91365960DC687B5738D98817B10EA8197FB807C59A47EB187BCD2E4E873BACCE97E70DDCBA6B4189A57FDF7D6F8B62A0FF3D81348DB2B8B35AD55D9CF67F668BB89D448A751B02071D1CF812027EDE8658D51BECAC34BE3EEA1DBF31E6177509C81F5E3A373FE9E2AF88282EC5BAB7D00C1325C6A305BB0E2B47989EF26AA3CEFE6A3F6E7CE5873F215DABF22C17E5E6FB210DA4F5B5F576B0800AE1D282A5D897B6164D3A32C5D0AA176DF03A6C1D2850CEBD40F5D97EE707EC307B13538FC3A0C83A95FF0EA2E5470E1B682ED12F9E65F366C45775A9365BF74729DAFF7FC0E9BB4C05A53BFCCE1B14CFAD49647ADFAFAA0059707D4D72C133E5EC878E9887B41656CBEBF749F9E19C3E9C4F464A67354A6212F43D15AF01A762D8C7445F7FF27CF835E1CE11C844E488036838FD7254AA6C2CDB858B7FEDF7852A90A8AC7FE2504DFDC1EEA60F64A671DEE39E72332E407637033A9146CE243950D4C3D07C17BFE22D9A191FF01315FD51653CDBB316E833C823EB459987AAC7E3D6FB50BDEE54652AB253CB9DF0A661BE1B5AE2A7E9EA429D7E8A5BBFE7683A2DF259CF2F0221CE0C2FEB06C117002D101921FB54E06CCADD05DE9353E5874C2B67B45571A83E2967BE45E77AD2336B076088B33F33F024185979EB36D57ABBE493D84C7F7DAEE3B10E039339CFF06CF36DDBB04ABD0FB8C8DDDEF0F7E86F9724644D6654D4FFFACA74F21F242A9722ADBEF84B44C9A1B7B815EA0317DC5CF688F57896C57AF47F44B1AED5C92853A7EB1138A125C026C9E73770D982A0A25785CD91A4F315D03DEFCA59A2D3CB3C015DE5DF285B53A455087D46109582854BEDFC301B9EA9D87D4A04A2F9650B8D9A83B6885FC52CD32EEEE85E740873330E29885C8BE8BC9D657E612A87EB3969CD24950C9A8945844BFFA33396876B885550860721DECE6AFB92F1D87707BBEF2A34915657E3A28F8C16ECD2AB9F967E5F3529100F05FAE6E0D8BEA5942625D7918B4EF5E2D3807D73664629E5B8651C1B000000000000000000000005111A1E272C0100000000000000000000000000000000000000000000000000000000000000 + +description = signature with too many hints (causing a buffer overflow) +mlen = 32 +msg = 0100000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3341 +sm = E1412C0A8930EBD5BE73CFF29B68C3AD7426551E499553D7CAB9B65A984CDA37D793CFA5011EF4470DC57BF0C7D1C25449CD23C82868180997EF617A42D425CC5E1DCB6127D3B60E017A9AE1AC7DFE980DEBB098F6099D4A5D497B0EA1A063F863D484A697F9E4B87652249301455276EAEAAE6E5B9C32991BB3A247F5EB6A64049C317A2E262BC9FBEBAA53E1203D780AACDF8D8C1DF9D104DB25002257CFE39C49E88EE0ADAC298199EE0285AAB5966C4DECCCDD64FF86A76DA9FCB17765C10CE7EE8272595B0DECCC58C8D89D11B78E56A4CC63B19D7D787988256A277B53BA7D99C1930BBF1CD550ACF5C97F6F1B1BBDC6A9CD0C3BE66672724E9ACD89240987B0B17F9BB38B8B323E21B7DF3A056B85CC41288D34707DDC050B8484598EDE78EA295774222EF491F0D621509C9361B7C8537A4904E2E5ED1640968FA6DFCD828C8BA6E771F970ACA894F0D57CD03CE325F4C3176B818F42F29C8646948B58796542DA63FFC905171129418A349C0783EBF5AE14B3FEE69492293AD3894345F07EDDAC036C40AD5215D4827DE6A0EA0B4BD2DD86826C7F5C340FD2D62062A41C075259A9ECB3ACE3722D3768D5A7D355373E3DE4D6F87A408E5BDE672F414826A2C6714A706198723D6E41FEB39302B155F775BDD01B7CB4925B75AA1D0A0D533A2FBDABF68D03592DE2B24A39D2D093FEA87CA57E16622E59B46988D7057540A511506C1E7C819D8697564E161FB221DE02DB05B8715D7E8CB81B96BF41B257FE6C5DBD8AB7E4B6CDE8A7E15077B3318C7D6B7C301C0EF33CF1F1C65668CE0106A259A599A4034010F5809FA7E781665D866DEC4A5BE77E8CD090A324FBD25CC07929B773CD8358D666ED767DB22D540829F4BC09C3A60448A23EE40E09EC699C784649331563EB114EC47C8F1731DB50761DDD7C972553E9819DB31148FB97D3B4C9FBB89AF7E87033536455F9FEFDF8566B6EB0100040ECD080287DA76A7791CB90AF6253E701D9705AF96B3597596AA58B9B0FDD7689ECA35A7AA7C21B71BD80C3921449D3C5C8D9A26BD386B5C4002C8050B6C7F2489BEE49B18BA85652D4B528BEB21F35C4C9AB1F5E7F5FA4098B2D470BE2CDA7087C61C4F40E771AC04193DED1C45B0AD787BE20ACF7C9393671C354DD70E93618BCF89F684C9FB7C8FCBD004B737A65350E912A1945FA6F6F082406526F8B8B4603E171B754A3F571B7933E07BC9971ED2C299C4BBB4293B3282E34FC1244AD5C4C985ACD31D4F2EB5B82E5B5E1F00C9BE628E0A317885AB6E26AA7667C73C12F541CDF463CD72798CB1F7908D2945A131CA8AC4BA6343BC4FCF7DCA98F30B0FEADE3F0841EE280DA51D9501B5CEAFCCDB8319F9B32DF23E74A12B4B61C44B3005EE58160C85302C141DBD6FE0D598B2886824B1BDADC874C530DF612FE5260E996C6D289A2A5F3F811F2B50CAC599477F9D8400298981654013858E4ADF2B6A67DAF24A5099E9A44F5DFC37B2DAFC4AA738D4690F9650F019583EAAEDDF32BA74C3468863CFD565D06FB26601EA919B68985F5B7F036B2EF1B7B0F6A738E292BE4B263D30EA5D9784221C09DD6BD77F26DAA6996BCE002783305E478CC1CAC235DA49057DA7F9CF7B8E25AE6FB02A46AD93EBC5D9440BDD07018AE26DE5C51C87556AD561F3C7E130A24685F3FB9E39518C1E9D26C5BE936CF3F9F08C464FD0A32502604A349C8956541D94CC0F11BD5A0733737FD75ECF57678264E63CE8B5323A0630A40CD6032D62ED84951427A5162AC1685F8682EE7D31621F6A77ADE12ACDE5634BC44B21A2E1CAFE4A689E0D30AC3D03A6903F75393BE77FED6BE1F970A4BD7F2E666721E271E155223C03C7068E4D9B348159ED8B09D14DF65F4D86AE612CE3A931FC4A66C60DA424D5C2CDA9FBD7115B771E3262AC7788C70F6C0241DED2B9DC0D936E613C795F69D65539FE00AE8E7EFDF07BC068EA4BB9BD83F5A64E970BAE105036435BCFB23934DC13027ECFE3DFB7A1E9D3F7B2B07DBA844598D4CF53D39FCE8C0485B8EEE92671CE8ED10B262E63944A1EE4889494917FA81E01B145B17FCBBD079E8574DF474362FEF1F48EAC5B8A443973B75E72330EB03E15DECFB18F69D10343F2DAF0CCECA3436C20612091E3BA0940DD3A5D5489338578E0E90F3795A7380D577A67E52ADF7358F2E7AAACC75BBB81537134A12771C1539AD42307BB2C1A5277C123F10B74216CCE836E78D24DC3AD7E794BFDBA4D0306A519CB122E3B2D5A6769EF54636F4398E87BD42B0E6229DD7F430F5C6BD610F9C67C68F1F7A687B98C2E5A61CE50C9989A8DE3F53C975BB75B97CCDEB3E0FB7C26F368B29DF709F18193B9BE27FEC820136D8BBB9A037C13B03E8FFE2484D948A284D505916EE424414C5DAF57514FDE0A84665B2C31E2D4C8FDE45BFDB2CA08E9974EA9449C5F332CDDCAA46140F08DEEB3F0B4BDA7BE04446239C7AF4949FAB33B40DBA8FEED31D45F85507FC232FDAD3C85595643B4A7F2503C4BFC4B3C55D969AF6AC80A3C02AF1F5BEBD23A66700733B36F133951193A1FCE5D429B6200FDAF383798A1D11F3CD6536D3F9D27B58A5388482279F925A8EC2850DB90F5F70650B0045B4002B952C36B460A5B566FD3BA2BF5BCDBA0378C54AC9C12CCB46C7FE110AA99DBAE10D5CEFAB484A3ABBD517DB89C71D60ED26FEE9D55E73BD4CE16D898BA426A683B842885B514370F6D854321E599E24EDEC6C3A0DB6F73C60BB36433EC58E162D6FFE8BBF2D345421341EC22E1D25FC740EC4D3D78B79484387A9207B9B48EC8585FB9F6BB4F776BF71FE7834D95BF4C6312D430EB79877FC71EA67EC4080C359D4C4901596E93EDF71C6B3AE2EDD5D491DEA03186BD3FB24527E7F99C708FBA19D606CC44EC5E1FFAA33CD2710CEBF4D4B5869230B151CA8472D35A49CDA5367098CF3AD4DDAF1838E77476108EAD4C399938FF0CBDCD226B6F06D5323C3D885FF1B043E6A32CDE2E052C7D5C273B5354EB020A81D4F9BBA9FD29A5148359750EC9CEB6AA9906047F1FE4191D07A0B018DF93BFCD96FF4AF3BEEC9C5E5EB5884B32BC84F66570B9B57F506443FF634056B504871E4B75CC1BEA1EBC8A9D5D07C9EA587B70EEA92B93F65C3194B343CBFDC28D1A76DAF95303C9C4EC0034FCA333628720BDDA7A3373D676E2928C08684E9D24EED7D9382AAE547CAD5837D6E1BE3E7245E947053EE2219D39E33218D9AE52F6B5EB487B0E5B16AC35FFFC45AC1D832DF711CB11B2A887647BC2C3713945F92103F3EE2A52AD946B0D38BC0BD92E701C7E7D4AEA25E6AA4FF2A42CCBF5DA9BB99F88351076AF1FB4E7CAA65DC23A78372E1C2FA09BA8D46152CDA3ECC8A9288598BED37E4D11507E6B5E239F377D1DC5AFAC7FB38FFBB7B2D4ABC6BD74771923AE17CDE020B34151D2555FDC1C09848196DAAB35745D88B80A79CE2BC86BFE7397EDBD9F16188A133B2900FEDB915629B3104DD6F00CD1403F8A62F71756D614C0224276594D4FB74891D1A2F93F43157B0A6A4135DD65FE25D227BE62AFE953667147FE7D3D486BC6D5436B218FB9AD0C6DF31CE8FCAFE01B81561E02AD5D34A0B669345A74AE16F651FAE91365960DC687B5738D98817B10EA8197FB807C59A47EB187BCD2E4E873BACCE97E70DDCBA6B4189A57FDF7D6F8B62A0FF3D81348DB2B8B35AD55D9CF67F668BB89D448A751B02071D1CF812027EDE8658D51BECAC34BE3EEA1DBF31E6177509C81F5E3A373FE9E2AF88282EC5BAB7D00C1325C6A305BB0E2B47989EF26AA3CEFE6A3F6E7CE5873F215DABF22C17E5E6FB210DA4F5B5F576B0800AE1D282A5D897B6164D3A32C5D0AA176DF03A6C1D2850CEBD40F5D97EE707EC307B13538FC3A0C83A95FF0EA2E5470E1B682ED12F9E65F366C45775A9365BF74729DAFF7FC0E9BB4C05A53BFCCE1B14CFAD49647ADFAFAA0059707D4D72C133E5EC878E9887B41656CBEBF749F9E19C3E9C4F464A67354A6212F43D15AF01A762D8C7445F7FF27CF835E1CE11C844E488036838FD7254AA6C2CDB858B7FEDF7852A90A8AC7FE2504DFDC1EEA60F64A671DEE39E72332E407637033A9146CE243950D4C3D07C17BFE22D9A191FF01315FD51653CDBB316E833C823EB459987AAC7E3D6FB50BDEE54652AB253CB9DF0A661BE1B5AE2A7E9EA429D7E8A5BBFE7683A2DF259CF2F0221CE0C2FEB06C117002D101921FB54E06CCADD05DE9353E5874C2B67B45571A83E2967BE45E77AD2336B076088B33F33F024185979EB36D57ABBE493D84C7F7DAEE3B10E039339CFF06CF36DDBB04ABD0FB8C8DDDEF0F7E86F9724644D6654D4FFFACA74F21F242A9722ADBEF84B44C9A1B7B815EA0317DC5CF688F57896C57AF47F44B1AED5C92853A7EB1138A125C026C9E73770D982A0A25785CD91A4F315D03DEFCA59A2D3CB3C015DE5DF285B53A455087D46109582854BEDFC301B9EA9D87D4A04A2F9650B8D9A83B6885FC52CD32EEEE85E740873330E29885C8BE8BC9D657E612A87EB3969CD24950C9A8945844BFFA33396876B885550860721DECE6AFB92F1D87707BBEF2A34915657168C8FA2E3050F1029355F7E969FABD2EC252694A5BED8E0E6FA4E8B91D7294666737D80D3E2F51B1C65B8E5000000000000000000000005111A1E27FF0100000000000000000000000000000000000000000000000000000000000000 + +description = signature with non-zero padding in hints +mlen = 32 +msg = 0100000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3341 +sm = E1412C0A8930EBD5BE73CFF29B68C3AD7426551E499553D7CAB9B65A984CDA37D793CFA5011EF4470DC57BF0C7D1C25449CD23C82868180997EF617A42D425CC5E1DCB6127D3B60E017A9AE1AC7DFE980DEBB098F6099D4A5D497B0EA1A063F863D484A697F9E4B87652249301455276EAEAAE6E5B9C32991BB3A247F5EB6A64049C317A2E262BC9FBEBAA53E1203D780AACDF8D8C1DF9D104DB25002257CFE39C49E88EE0ADAC298199EE0285AAB5966C4DECCCDD64FF86A76DA9FCB17765C10CE7EE8272595B0DECCC58C8D89D11B78E56A4CC63B19D7D787988256A277B53BA7D99C1930BBF1CD550ACF5C97F6F1B1BBDC6A9CD0C3BE66672724E9ACD89240987B0B17F9BB38B8B323E21B7DF3A056B85CC41288D34707DDC050B8484598EDE78EA295774222EF491F0D621509C9361B7C8537A4904E2E5ED1640968FA6DFCD828C8BA6E771F970ACA894F0D57CD03CE325F4C3176B818F42F29C8646948B58796542DA63FFC905171129418A349C0783EBF5AE14B3FEE69492293AD3894345F07EDDAC036C40AD5215D4827DE6A0EA0B4BD2DD86826C7F5C340FD2D62062A41C075259A9ECB3ACE3722D3768D5A7D355373E3DE4D6F87A408E5BDE672F414826A2C6714A706198723D6E41FEB39302B155F775BDD01B7CB4925B75AA1D0A0D533A2FBDABF68D03592DE2B24A39D2D093FEA87CA57E16622E59B46988D7057540A511506C1E7C819D8697564E161FB221DE02DB05B8715D7E8CB81B96BF41B257FE6C5DBD8AB7E4B6CDE8A7E15077B3318C7D6B7C301C0EF33CF1F1C65668CE0106A259A599A4034010F5809FA7E781665D866DEC4A5BE77E8CD090A324FBD25CC07929B773CD8358D666ED767DB22D540829F4BC09C3A60448A23EE40E09EC699C784649331563EB114EC47C8F1731DB50761DDD7C972553E9819DB31148FB97D3B4C9FBB89AF7E87033536455F9FEFDF8566B6EB0100040ECD080287DA76A7791CB90AF6253E701D9705AF96B3597596AA58B9B0FDD7689ECA35A7AA7C21B71BD80C3921449D3C5C8D9A26BD386B5C4002C8050B6C7F2489BEE49B18BA85652D4B528BEB21F35C4C9AB1F5E7F5FA4098B2D470BE2CDA7087C61C4F40E771AC04193DED1C45B0AD787BE20ACF7C9393671C354DD70E93618BCF89F684C9FB7C8FCBD004B737A65350E912A1945FA6F6F082406526F8B8B4603E171B754A3F571B7933E07BC9971ED2C299C4BBB4293B3282E34FC1244AD5C4C985ACD31D4F2EB5B82E5B5E1F00C9BE628E0A317885AB6E26AA7667C73C12F541CDF463CD72798CB1F7908D2945A131CA8AC4BA6343BC4FCF7DCA98F30B0FEADE3F0841EE280DA51D9501B5CEAFCCDB8319F9B32DF23E74A12B4B61C44B3005EE58160C85302C141DBD6FE0D598B2886824B1BDADC874C530DF612FE5260E996C6D289A2A5F3F811F2B50CAC599477F9D8400298981654013858E4ADF2B6A67DAF24A5099E9A44F5DFC37B2DAFC4AA738D4690F9650F019583EAAEDDF32BA74C3468863CFD565D06FB26601EA919B68985F5B7F036B2EF1B7B0F6A738E292BE4B263D30EA5D9784221C09DD6BD77F26DAA6996BCE002783305E478CC1CAC235DA49057DA7F9CF7B8E25AE6FB02A46AD93EBC5D9440BDD07018AE26DE5C51C87556AD561F3C7E130A24685F3FB9E39518C1E9D26C5BE936CF3F9F08C464FD0A32502604A349C8956541D94CC0F11BD5A0733737FD75ECF57678264E63CE8B5323A0630A40CD6032D62ED84951427A5162AC1685F8682EE7D31621F6A77ADE12ACDE5634BC44B21A2E1CAFE4A689E0D30AC3D03A6903F75393BE77FED6BE1F970A4BD7F2E666721E271E155223C03C7068E4D9B348159ED8B09D14DF65F4D86AE612CE3A931FC4A66C60DA424D5C2CDA9FBD7115B771E3262AC7788C70F6C0241DED2B9DC0D936E613C795F69D65539FE00AE8E7EFDF07BC068EA4BB9BD83F5A64E970BAE105036435BCFB23934DC13027ECFE3DFB7A1E9D3F7B2B07DBA844598D4CF53D39FCE8C0485B8EEE92671CE8ED10B262E63944A1EE4889494917FA81E01B145B17FCBBD079E8574DF474362FEF1F48EAC5B8A443973B75E72330EB03E15DECFB18F69D10343F2DAF0CCECA3436C20612091E3BA0940DD3A5D5489338578E0E90F3795A7380D577A67E52ADF7358F2E7AAACC75BBB81537134A12771C1539AD42307BB2C1A5277C123F10B74216CCE836E78D24DC3AD7E794BFDBA4D0306A519CB122E3B2D5A6769EF54636F4398E87BD42B0E6229DD7F430F5C6BD610F9C67C68F1F7A687B98C2E5A61CE50C9989A8DE3F53C975BB75B97CCDEB3E0FB7C26F368B29DF709F18193B9BE27FEC820136D8BBB9A037C13B03E8FFE2484D948A284D505916EE424414C5DAF57514FDE0A84665B2C31E2D4C8FDE45BFDB2CA08E9974EA9449C5F332CDDCAA46140F08DEEB3F0B4BDA7BE04446239C7AF4949FAB33B40DBA8FEED31D45F85507FC232FDAD3C85595643B4A7F2503C4BFC4B3C55D969AF6AC80A3C02AF1F5BEBD23A66700733B36F133951193A1FCE5D429B6200FDAF383798A1D11F3CD6536D3F9D27B58A5388482279F925A8EC2850DB90F5F70650B0045B4002B952C36B460A5B566FD3BA2BF5BCDBA0378C54AC9C12CCB46C7FE110AA99DBAE10D5CEFAB484A3ABBD517DB89C71D60ED26FEE9D55E73BD4CE16D898BA426A683B842885B514370F6D854321E599E24EDEC6C3A0DB6F73C60BB36433EC58E162D6FFE8BBF2D345421341EC22E1D25FC740EC4D3D78B79484387A9207B9B48EC8585FB9F6BB4F776BF71FE7834D95BF4C6312D430EB79877FC71EA67EC4080C359D4C4901596E93EDF71C6B3AE2EDD5D491DEA03186BD3FB24527E7F99C708FBA19D606CC44EC5E1FFAA33CD2710CEBF4D4B5869230B151CA8472D35A49CDA5367098CF3AD4DDAF1838E77476108EAD4C399938FF0CBDCD226B6F06D5323C3D885FF1B043E6A32CDE2E052C7D5C273B5354EB020A81D4F9BBA9FD29A5148359750EC9CEB6AA9906047F1FE4191D07A0B018DF93BFCD96FF4AF3BEEC9C5E5EB5884B32BC84F66570B9B57F506443FF634056B504871E4B75CC1BEA1EBC8A9D5D07C9EA587B70EEA92B93F65C3194B343CBFDC28D1A76DAF95303C9C4EC0034FCA333628720BDDA7A3373D676E2928C08684E9D24EED7D9382AAE547CAD5837D6E1BE3E7245E947053EE2219D39E33218D9AE52F6B5EB487B0E5B16AC35FFFC45AC1D832DF711CB11B2A887647BC2C3713945F92103F3EE2A52AD946B0D38BC0BD92E701C7E7D4AEA25E6AA4FF2A42CCBF5DA9BB99F88351076AF1FB4E7CAA65DC23A78372E1C2FA09BA8D46152CDA3ECC8A9288598BED37E4D11507E6B5E239F377D1DC5AFAC7FB38FFBB7B2D4ABC6BD74771923AE17CDE020B34151D2555FDC1C09848196DAAB35745D88B80A79CE2BC86BFE7397EDBD9F16188A133B2900FEDB915629B3104DD6F00CD1403F8A62F71756D614C0224276594D4FB74891D1A2F93F43157B0A6A4135DD65FE25D227BE62AFE953667147FE7D3D486BC6D5436B218FB9AD0C6DF31CE8FCAFE01B81561E02AD5D34A0B669345A74AE16F651FAE91365960DC687B5738D98817B10EA8197FB807C59A47EB187BCD2E4E873BACCE97E70DDCBA6B4189A57FDF7D6F8B62A0FF3D81348DB2B8B35AD55D9CF67F668BB89D448A751B02071D1CF812027EDE8658D51BECAC34BE3EEA1DBF31E6177509C81F5E3A373FE9E2AF88282EC5BAB7D00C1325C6A305BB0E2B47989EF26AA3CEFE6A3F6E7CE5873F215DABF22C17E5E6FB210DA4F5B5F576B0800AE1D282A5D897B6164D3A32C5D0AA176DF03A6C1D2850CEBD40F5D97EE707EC307B13538FC3A0C83A95FF0EA2E5470E1B682ED12F9E65F366C45775A9365BF74729DAFF7FC0E9BB4C05A53BFCCE1B14CFAD49647ADFAFAA0059707D4D72C133E5EC878E9887B41656CBEBF749F9E19C3E9C4F464A67354A6212F43D15AF01A762D8C7445F7FF27CF835E1CE11C844E488036838FD7254AA6C2CDB858B7FEDF7852A90A8AC7FE2504DFDC1EEA60F64A671DEE39E72332E407637033A9146CE243950D4C3D07C17BFE22D9A191FF01315FD51653CDBB316E833C823EB459987AAC7E3D6FB50BDEE54652AB253CB9DF0A661BE1B5AE2A7E9EA429D7E8A5BBFE7683A2DF259CF2F0221CE0C2FEB06C117002D101921FB54E06CCADD05DE9353E5874C2B67B45571A83E2967BE45E77AD2336B076088B33F33F024185979EB36D57ABBE493D84C7F7DAEE3B10E039339CFF06CF36DDBB04ABD0FB8C8DDDEF0F7E86F9724644D6654D4FFFACA74F21F242A9722ADBEF84B44C9A1B7B815EA0317DC5CF688F57896C57AF47F44B1AED5C92853A7EB1138A125C026C9E73770D982A0A25785CD91A4F315D03DEFCA59A2D3CB3C015DE5DF285B53A455087D46109582854BEDFC301B9EA9D87D4A04A2F9650B8D9A83B6885FC52CD32EEEE85E740873330E29885C8BE8BC9D657E612A87EB3969CD24950C9A8945844BFFA33396876B885550860721DECE6AFB92F1D87707BBEF2A34915657168C8FA2E3050F1029355F7E969FABD2EC252694A5BED8E0E6FA4E8B91D7294666737D80D3E2F51B1C65B8E52A2A2A2A2A2A2A2A2A2A2A05111A1E272C0100000000000000000000000000000000000000000000000000000000000000 + +description = signature with a repeated hint +mlen = 32 +msg = 0100000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3341 +sm = E1412C0A8930EBD5BE73CFF29B68C3AD7426551E499553D7CAB9B65A984CDA37D793CFA5011EF4470DC57BF0C7D1C25449CD23C82868180997EF617A42D425CC5E1DCB6127D3B60E017A9AE1AC7DFE980DEBB098F6099D4A5D497B0EA1A063F863D484A697F9E4B87652249301455276EAEAAE6E5B9C32991BB3A247F5EB6A64049C317A2E262BC9FBEBAA53E1203D780AACDF8D8C1DF9D104DB25002257CFE39C49E88EE0ADAC298199EE0285AAB5966C4DECCCDD64FF86A76DA9FCB17765C10CE7EE8272595B0DECCC58C8D89D11B78E56A4CC63B19D7D787988256A277B53BA7D99C1930BBF1CD550ACF5C97F6F1B1BBDC6A9CD0C3BE66672724E9ACD89240987B0B17F9BB38B8B323E21B7DF3A056B85CC41288D34707DDC050B8484598EDE78EA295774222EF491F0D621509C9361B7C8537A4904E2E5ED1640968FA6DFCD828C8BA6E771F970ACA894F0D57CD03CE325F4C3176B818F42F29C8646948B58796542DA63FFC905171129418A349C0783EBF5AE14B3FEE69492293AD3894345F07EDDAC036C40AD5215D4827DE6A0EA0B4BD2DD86826C7F5C340FD2D62062A41C075259A9ECB3ACE3722D3768D5A7D355373E3DE4D6F87A408E5BDE672F414826A2C6714A706198723D6E41FEB39302B155F775BDD01B7CB4925B75AA1D0A0D533A2FBDABF68D03592DE2B24A39D2D093FEA87CA57E16622E59B46988D7057540A511506C1E7C819D8697564E161FB221DE02DB05B8715D7E8CB81B96BF41B257FE6C5DBD8AB7E4B6CDE8A7E15077B3318C7D6B7C301C0EF33CF1F1C65668CE0106A259A599A4034010F5809FA7E781665D866DEC4A5BE77E8CD090A324FBD25CC07929B773CD8358D666ED767DB22D540829F4BC09C3A60448A23EE40E09EC699C784649331563EB114EC47C8F1731DB50761DDD7C972553E9819DB31148FB97D3B4C9FBB89AF7E87033536455F9FEFDF8566B6EB0100040ECD080287DA76A7791CB90AF6253E701D9705AF96B3597596AA58B9B0FDD7689ECA35A7AA7C21B71BD80C3921449D3C5C8D9A26BD386B5C4002C8050B6C7F2489BEE49B18BA85652D4B528BEB21F35C4C9AB1F5E7F5FA4098B2D470BE2CDA7087C61C4F40E771AC04193DED1C45B0AD787BE20ACF7C9393671C354DD70E93618BCF89F684C9FB7C8FCBD004B737A65350E912A1945FA6F6F082406526F8B8B4603E171B754A3F571B7933E07BC9971ED2C299C4BBB4293B3282E34FC1244AD5C4C985ACD31D4F2EB5B82E5B5E1F00C9BE628E0A317885AB6E26AA7667C73C12F541CDF463CD72798CB1F7908D2945A131CA8AC4BA6343BC4FCF7DCA98F30B0FEADE3F0841EE280DA51D9501B5CEAFCCDB8319F9B32DF23E74A12B4B61C44B3005EE58160C85302C141DBD6FE0D598B2886824B1BDADC874C530DF612FE5260E996C6D289A2A5F3F811F2B50CAC599477F9D8400298981654013858E4ADF2B6A67DAF24A5099E9A44F5DFC37B2DAFC4AA738D4690F9650F019583EAAEDDF32BA74C3468863CFD565D06FB26601EA919B68985F5B7F036B2EF1B7B0F6A738E292BE4B263D30EA5D9784221C09DD6BD77F26DAA6996BCE002783305E478CC1CAC235DA49057DA7F9CF7B8E25AE6FB02A46AD93EBC5D9440BDD07018AE26DE5C51C87556AD561F3C7E130A24685F3FB9E39518C1E9D26C5BE936CF3F9F08C464FD0A32502604A349C8956541D94CC0F11BD5A0733737FD75ECF57678264E63CE8B5323A0630A40CD6032D62ED84951427A5162AC1685F8682EE7D31621F6A77ADE12ACDE5634BC44B21A2E1CAFE4A689E0D30AC3D03A6903F75393BE77FED6BE1F970A4BD7F2E666721E271E155223C03C7068E4D9B348159ED8B09D14DF65F4D86AE612CE3A931FC4A66C60DA424D5C2CDA9FBD7115B771E3262AC7788C70F6C0241DED2B9DC0D936E613C795F69D65539FE00AE8E7EFDF07BC068EA4BB9BD83F5A64E970BAE105036435BCFB23934DC13027ECFE3DFB7A1E9D3F7B2B07DBA844598D4CF53D39FCE8C0485B8EEE92671CE8ED10B262E63944A1EE4889494917FA81E01B145B17FCBBD079E8574DF474362FEF1F48EAC5B8A443973B75E72330EB03E15DECFB18F69D10343F2DAF0CCECA3436C20612091E3BA0940DD3A5D5489338578E0E90F3795A7380D577A67E52ADF7358F2E7AAACC75BBB81537134A12771C1539AD42307BB2C1A5277C123F10B74216CCE836E78D24DC3AD7E794BFDBA4D0306A519CB122E3B2D5A6769EF54636F4398E87BD42B0E6229DD7F430F5C6BD610F9C67C68F1F7A687B98C2E5A61CE50C9989A8DE3F53C975BB75B97CCDEB3E0FB7C26F368B29DF709F18193B9BE27FEC820136D8BBB9A037C13B03E8FFE2484D948A284D505916EE424414C5DAF57514FDE0A84665B2C31E2D4C8FDE45BFDB2CA08E9974EA9449C5F332CDDCAA46140F08DEEB3F0B4BDA7BE04446239C7AF4949FAB33B40DBA8FEED31D45F85507FC232FDAD3C85595643B4A7F2503C4BFC4B3C55D969AF6AC80A3C02AF1F5BEBD23A66700733B36F133951193A1FCE5D429B6200FDAF383798A1D11F3CD6536D3F9D27B58A5388482279F925A8EC2850DB90F5F70650B0045B4002B952C36B460A5B566FD3BA2BF5BCDBA0378C54AC9C12CCB46C7FE110AA99DBAE10D5CEFAB484A3ABBD517DB89C71D60ED26FEE9D55E73BD4CE16D898BA426A683B842885B514370F6D854321E599E24EDEC6C3A0DB6F73C60BB36433EC58E162D6FFE8BBF2D345421341EC22E1D25FC740EC4D3D78B79484387A9207B9B48EC8585FB9F6BB4F776BF71FE7834D95BF4C6312D430EB79877FC71EA67EC4080C359D4C4901596E93EDF71C6B3AE2EDD5D491DEA03186BD3FB24527E7F99C708FBA19D606CC44EC5E1FFAA33CD2710CEBF4D4B5869230B151CA8472D35A49CDA5367098CF3AD4DDAF1838E77476108EAD4C399938FF0CBDCD226B6F06D5323C3D885FF1B043E6A32CDE2E052C7D5C273B5354EB020A81D4F9BBA9FD29A5148359750EC9CEB6AA9906047F1FE4191D07A0B018DF93BFCD96FF4AF3BEEC9C5E5EB5884B32BC84F66570B9B57F506443FF634056B504871E4B75CC1BEA1EBC8A9D5D07C9EA587B70EEA92B93F65C3194B343CBFDC28D1A76DAF95303C9C4EC0034FCA333628720BDDA7A3373D676E2928C08684E9D24EED7D9382AAE547CAD5837D6E1BE3E7245E947053EE2219D39E33218D9AE52F6B5EB487B0E5B16AC35FFFC45AC1D832DF711CB11B2A887647BC2C3713945F92103F3EE2A52AD946B0D38BC0BD92E701C7E7D4AEA25E6AA4FF2A42CCBF5DA9BB99F88351076AF1FB4E7CAA65DC23A78372E1C2FA09BA8D46152CDA3ECC8A9288598BED37E4D11507E6B5E239F377D1DC5AFAC7FB38FFBB7B2D4ABC6BD74771923AE17CDE020B34151D2555FDC1C09848196DAAB35745D88B80A79CE2BC86BFE7397EDBD9F16188A133B2900FEDB915629B3104DD6F00CD1403F8A62F71756D614C0224276594D4FB74891D1A2F93F43157B0A6A4135DD65FE25D227BE62AFE953667147FE7D3D486BC6D5436B218FB9AD0C6DF31CE8FCAFE01B81561E02AD5D34A0B669345A74AE16F651FAE91365960DC687B5738D98817B10EA8197FB807C59A47EB187BCD2E4E873BACCE97E70DDCBA6B4189A57FDF7D6F8B62A0FF3D81348DB2B8B35AD55D9CF67F668BB89D448A751B02071D1CF812027EDE8658D51BECAC34BE3EEA1DBF31E6177509C81F5E3A373FE9E2AF88282EC5BAB7D00C1325C6A305BB0E2B47989EF26AA3CEFE6A3F6E7CE5873F215DABF22C17E5E6FB210DA4F5B5F576B0800AE1D282A5D897B6164D3A32C5D0AA176DF03A6C1D2850CEBD40F5D97EE707EC307B13538FC3A0C83A95FF0EA2E5470E1B682ED12F9E65F366C45775A9365BF74729DAFF7FC0E9BB4C05A53BFCCE1B14CFAD49647ADFAFAA0059707D4D72C133E5EC878E9887B41656CBEBF749F9E19C3E9C4F464A67354A6212F43D15AF01A762D8C7445F7FF27CF835E1CE11C844E488036838FD7254AA6C2CDB858B7FEDF7852A90A8AC7FE2504DFDC1EEA60F64A671DEE39E72332E407637033A9146CE243950D4C3D07C17BFE22D9A191FF01315FD51653CDBB316E833C823EB459987AAC7E3D6FB50BDEE54652AB253CB9DF0A661BE1B5AE2A7E9EA429D7E8A5BBFE7683A2DF259CF2F0221CE0C2FEB06C117002D101921FB54E06CCADD05DE9353E5874C2B67B45571A83E2967BE45E77AD2336B076088B33F33F024185979EB36D57ABBE493D84C7F7DAEE3B10E039339CFF06CF36DDBB04ABD0FB8C8DDDEF0F7E86F9724644D6654D4FFFACA74F21F242A9722ADBEF84B44C9A1B7B815EA0317DC5CF688F57896C57AF47F44B1AED5C92853A7EB1138A125C026C9E73770D982A0A25785CD91A4F315D03DEFCA59A2D3CB3C015DE5DF285B53A455087D46109582854BEDFC301B9EA9D87D4A04A2F9650B8D9A83B6885FC52CD32EEEE85E740873330E29885C8BE8BC9D657E612A87EB3969CD24950C9A8945844BFFA33396876B885550860721DECE6AFB92F1D87707BBEF2A3491565716168C8FA2E3050F1029355F7E969FABD2EC252694A5BED8E0E6FA4E8B91D7294666737D80D3E2F51B1C65B8E50000000000000000000006121B1F282D0100000000000000000000000000000000000000000000000000000000000000 + +description = signature with omega+1 hints (causing a buffer overflow) +mlen = 32 +msg = DB1F000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = false +smlen = 3341 +sm = 9CF706BEAE50213E5C02CD17012AC726C80594FA32E3A2EC1978667CDE026DEDAC5433D4D01B148C06A31E367E564FD8590DE2587B5AD8E7DEED72AE20F575C3FF672A23A8E9BB33F17850DF016402A6B0997B63C8A3AD5EFC9076E9506BFBBAD7A92761290A99389AD4222CF08A71F2BED7AAD06D60F09FED22F7FFF8765FBF021E40FEAFF0F7DDBC7977E8E2C013E66CF0640B12EC365FE756A72382A9C029E48921E63B68EE207EC61384A72944B205E614B65444005550065C882224EE77C2BF92C0B6AE4640133AFDEB5DEA948CBCE800961B243B6E2F1CDB9738811FE0F95E4609042FEE953C3191D001491A08A97DFDC72F72860AF4586B9EF497DFF7766C03A36A94AA946AC762EA6010875B20CAEC650E2BA8D2AF07F17AE6BC3F0B56F054DA131FCB8B4AA19B7FD6D3B067F846E43920070046F1E796B669410FD938DBB172A327EBAD362D036D0B3EA3E31723CE0C1037E9E293E3015BC71EA99DDAB259CFB852F2D3B2A274E3BB353B16D664FDF0D29D5A88B4FEA4CB1C70BA7B34F8A6EC8DA7753D168E0B1D88BC039FCD9C4D0B3261056C8D2C8909CE2E3F6BAD2E15CE870653107993FD17198818A65648EC7B1AF1737A0045BC8310F15824C1C63279F680847F2D746021F7882188D4A4D7E54A55E39461AFDB9A4101C47CEB3D371CD2B0E7A5F3215136FCFC03627BEBD80BA2BBEA12BB6E7EA48D37AB859ED78B6E724AE7C6AE4082317155DCB470DEAAA9BAB61AED7EC35CF7054C81BEE3C8BAAAA587E9CFF23C66702FB3D65BB842889278CE853B9FC112B3047A1B80D1FA3075066EF76A54A84C0E47920CEAF93A165770B65275D1DA2E0B46564F505B586D7C76FAD7829C9D46555E67D2D5F2BDF77F68029435CAD95C5B705AB9B305567882F2FBAE8CB8C68EB26635231CAF4C10E7667FF122C7F5DB40B6C45C1F181336944BFFC3093F8AA6A35B52471D4D9C5986E243AB13407B049E11E5F2FC45A679B697B86F750F4A67EE8B47E1CE54E8E23502053FEA980306521885DD5E0B8C3C9F5EF0F4F7F0DA83B5F8C62C3389ECE67722A9CF65C0C735E9A2C09873F20FAA1A62B8C18CADC47A2B45865C95B6489FA171DA61D8278F136B05C7DF3A186B146DE48BFF6F5E2C05EA2B1034D2B580C6D5129B663140C78E267C2C4153B40338BFE032C06ADB91ECCFF8539E014CE5D309462417326643E6BB67D464583F082506E072AF9C3E63D9DC663E0EE5F660A567C18D86A87B47BB7E9F4DB8522C1B5255490263003E7CB30F7D5428BFEDEF7EF0AAD4A85F1995B64598D5299BD8ACEB64B88CC8CD0F97AA40F171A80ABF33F3EB4B62A4E478107532122C8B837DA7DE0800C6DCC963DDF97138E693D1D5BECA694F83FAF310A05AD07C63106634938FDD129BB881E24A764A0F754D6116FD2A629E13BAA85519AB380A1445470FB34ECBA2FAEDDAC739BB1FDDF9B47A136333EF548E964E3D7D06C5A7E4D71D5248B7CDBF9E9F7F40AD77150DE0CF13D1DC594D8E5A24E432279AC25F758A29DDF56F3F27A8A63DF9F6D22B37807D02E1619A58D048B8451E5512BAA8EC9A175589F174186CF07EC2E0BF3F3D69812FFB39C0B9C6CA07715F9129BA8ADA1DABAD9036065D5FCE97435C53687A4AA1F9F216C3E9986547EE71805975B21B99FFE0378ADBF6AA5F9401744226007F11CCC91D39D827BC2B95B2AECC3CF82A54537FD685256F4AF35DD785FDB981CEE388D3991F13BCA1B5176EB1B385A5E6729FDC5247BAEC55D31B0778BB00ED9FB9794F2F5344D4612EF57C0BCB1A94BF7102E222C8C1148BF4AEE31FAD93EBA32BEF2A86691D9759C0A6B0AD3BFE74511394768C3B393B899A89F8C056F1C20E7BCC15D192EAEF9A77BF9A00717936D4ED3BF9B85F806A7E61E021685D981D079188120C836CBD5B4278EB833550E6A9B62BD2B7CE34E6F99A6F9C4D87DEA8745783B2302E5F0833922911F49E79B8C9B71A78ABF53BE3696DC6F2AD716CAE5299D47D72C79E2892329AB5A2C4E2C4A6C50F37671DD596A7836DCA1EBDBCE9E05B217C073BA87BA3C242C610A162BC6150DD101C187A2C6076ADF7F2EC82CEC56595958CA36CFE6620BF5C4F98B8EB73F954D64F03FB8E44F0CDCEDC70F5BE7939283954C4F0A60137BD6940C417E132425591A19720695E0158FBCC9C24562B68A6C1D88CAFA1C38DFD2EF08339A96DF49455C89F3982FFAE5A559474CC4E9AFFDB925AD7974CF081606104DB3555509724AD3B274F132B7AC902463A56CD9451CC168D311BC16D6E9102A7EF78D2D0B10E7A527CC91AA33F841EDCF96711CC10A72CB3A3B5E945877A7651BA8CE235905AC2C0A821CF0D539132CED57BFC51C47EA5332D28524AE902ED8FE0A8BDCDE7D0A1E18D7519D97D43D44F6DBBB510F0EDE9532A7DA4D5B209A8C4836668D4854E872B89E49A62CEFF48A3BD34692666CDF85B42D05708E6624CE945FF1A05271355BE0887E4CD054D3E9D7AFFCD249EB608E9A71C4588BF393CFBC34ED349998D719DAC5A95CBA59D3809423F6E626975697FC9A533C633BCBEFD25E02ED3D1D4040DFE7B0F7F72D3937539E1CB3472F0CA5F383F70519166A4CB19BADAE8D1941936EF0AA6513E54F718092F2101981FB6BA5324226923D6772367BF23960CFC1E3576F3E489AF826BACB1E4DA43AE37F664D5E0F45B7C72CF271B1FFD216A406CE4ADE7578144B341932293B8ED22E41F6BF002D5FC788EA9B4A6ED407E0277DA5B9CB4A969CBC4EB06FE37BE7B15875B34E4A0AB3ECADFB3469EA3651A323A1280FDB8504FA8640FFE545F942240F79C07C74832A43CCF8D23B6723EC95A0FA28F7B8D605DB2B58E6B7B0CEBF8EA5DEA74128173DA04433D23763F0FFC0F54EE8E0648CABEAFD66C5D919B820FA1A161992E876D0CA000AF2EECAF66F33EFFC8D9BBFD77523AF48AABB443D03EFB417DF3E5C8E424D2C3645D3506B4EEE80786D8320C1FBE22A1073B68C888CFC94AD64E485284D10F1FA74AF07581F2AEEA11CC4225A877CB5B346D920CBF302E33FDFC336CC6A0951338E3E1EC9C37C5D709FCA28B8027699E8734500BAFAEF2491CE33C5BB4C8564BDA969D498C55884154F6A7701804135D42048D2E9F39AC1556585A3F201A3689E281DF5885BE17D411BEE984890CB123CB76AFE52DBCFD21881FE7A3E6735F892BBF984BB6D21791098776D44B9BDA94428391726B38B9C7A48CDDE8685BD307B691118EF415D74DA5AAA487CAD61586A7C9302A946DD431A101D5387163BDBCC262114A35212596A537DC11B425B0260E6D0A3E3E10AF22487DEDCFCBB1F5DED611D1FD63B09DEED301774A5543E8ED515C5216AF3E2B39ADC313F4D5C7848751DC92995E9FD01468F96E15823513A20C6D90449FFB0D68568F5348392872F3738E5861A1C6E4750A41F7163716627CA385CA890C7239EE1697BC547B9AACC6E429CD504B1F7F36E3F56670FB2528C5A6AAAF8A2166B00F13F863F0FA47915AEA2AA5F93555FFED16461A3ABAD4D718CF6E414DAF438064DEE139A30F163BA53183D1A882A7E16466F99B23C29C49F7E7083511A8BD13934E9D5A2566B6A6F07F551BDEBD059AB848E2DC016F1121B08262AB847BC198232739ED99E70F426449D1B85DD8A57836093E140FFD27B0A892B13652563136BC490057A6CCBC5819478C8CA7B515E1FABBF6F14CD8E86F5385A4F6585111026E2F1AFF431097A23BEF594A90346CA79EE6D5D568AF6545F6DD485C25FA1B65CE615D00291CB4D6D1073589BFCD56B63972C0F73E77A49665662110F655386DD6B6D7831D80E2AB482F6F4985985C30AFE7F47AA55FD7B8B48E25AC8E104723D89D4ACBD9A87BD5956B930845A04DC775D8E19EBF69A2F220CA9DEC09B2D91917BA9248666209A1BA4D162B9E7289CF18C2D53B16C1B576539EBC787CC078282AC7F80B062845D67F6F207B9F2A403680FF0B0BA01115D8AE0185734BE8870992EEA91191233D12590E98C6365A8AF19237B76F45EB0CDC945930D2F99963242EC63661D884886750BA2EB68A7A15F15D9AEE5D48F30A6A9495F7A3DE22E9D0FFF18D2AE799FDD8CA742A5B74F64080F1A7CDC359F3820C2E223DEFFD2B2C53DF7F0C96C7B3528DE9A0EFFB8969D16A2A4C9DD35010974B75B8BD7A5C1659B743284C1C89CD9F1142152546609FEEDCA278828E35E6FB8F8802BC0FD4A3FB072E8AF233CAF8A197B55356CABFE3F3D188718584AEDC60E61EEABEC6EFD01BC7B9628B63854322BA1905840AE41C269456588180DB609D9437E80554C3309E32E4D985E2F8C4D196E0EED76E226E287540983E88D456F90D50F01F46355A6F49AF7DB15E1A3F2EB525D1BF61CBB340339C6CEDE8CA662F73206A8F83CC320720F81169092C84EBFC961BEDC5FCA847ACE1460F68A1549A2E18DA57FCD3EA858DD471DF43DEE62078E201E3185B3AC8A115096FF31FF85ADC0C584F282D2BEAAB6E0BAF33791EA886B539EDB40D7585BA9A95ABF5273E820C7F510C5C04C8B52631F51E4F37C0B2359B2372A0D2E1E66B8BA309B74152AAF8CFEE96F3E73A6571DD0111131C31335C759FCED7F70E182E9EB0B1B5B6C0CFF205516A6E82A5A8AED7E6F5619CDE3595A3B4DCE418404751658D93ACE2E6F1FC0C1722252B37DB1F000000000000000000000000000000000000000000000000000000000000 + +description = private key with s1 vector out of range +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27CD931F803C2103D181EE5228549E4F2BB5CB4BFCFFCCA966F1EDE24A9958AD53842A15DB226ADF91810A689F440EF71184A2C6B4F40E5F133BDE58FE9331DEFA1AABB9819ABDF9CBAC8CC564ECB89D648CB5D66A09453DA4DBA410784FBC41DB6216E19856DE2BED90F6C30F3975A9B7BB47C2CB63E0B3DF09331DBFBBC23C15A45844ECE88226FDA9071185FABC073A8E832E7A940877972734CA3BC6BD66BCC84A61B683A3E59C9453BB1AE493EA1F0988C30E05DBD65E8824E73D7B335465E119F7B5CB640725121565C5610F7470AB86FDCC18BB005EAB35929DF14652A9771A496EC4D44AB84688F9481BDBBF79614E8C4FC611E1086BF2D4C798174039DD9686AA9F43E4CBAF94F9EC0533465D327E758F99637600455F5A51E9CF4220E8CADA21DC8A5C650CFB00D964C49575306862C7FA4128E6C65503F93CD3D2C079B7CE193DA9C9577CD7DEEDA0F66C087180ECB7D561309CC1A2A9E9DA2093FF5CF1F8BC15F1D1D91F6462EAE7A9122234E660B1739B7DB3043B09A1BFE0AF241EB0249EFD1F3255D7BDA8749BC0FA6C193B52CB8B1D3E1B4EED21D7D7BD6F024C680AADADACF51B5F0BCCB09735594F176242CC95FA4F61CE884B73F0878DBED24062E219FFEF82A912435B55F954E58728C79BE21CEC1BD74B0BD80F5FD0A5CC418C8C936F2BE63BCDD3902A0A4BBDE4325478FD58BFAE7B5DD977139FB7DDA993ADC68DAD65208BEF03FB2A20F18AE37344A2A858DFB47B2DB4C24488650D19F4AAABB43FA8B98F1BEE7A4D7FC38363BC9711D63C691FEABCF95336C67E2CCCA3F927641AB8D9B97F709E96553EC1A4948503B4783054C9D827756BF7CB8CB74B1DD5077330B2C2CA7460DE521A591BBB8DAD8575278E62B9129ADD32F30165CAF72C05788773CFD4D7FC6042A72DF403C396D496B17893A9694E0A067BB4D625E409AD5F0E818A81F314694E6C3EB63F0C7F468511462497EB40FA7A09D0D60E5D4BCA7904DE88A3B9B3DF40FD4854142302481FA7458D59DBC295DB173E1BEC6E7C9FC6F1C46A4C469B63B286DEFBD30E1AF010AE36C9CB50BA5E201D7FC5CC5386EAEFCA0D81C22F49A7AD8ECC272141E58E90D6E88C228C9C0D3C0947E13DAFFD477A055F4777761D060FE2505C8DE34CCC96A3147619D424650D6230840C3BDB1A86DB1D0969E1F5DB8B98A8A328C9C2FFC0C90732845AC67EFD45E29D7F5335637683A019C67B323E0ECB627333568A6611CD193EED5D12EFF8528ED26A37FE8F0EA7ED3B65F434D69D4AEC0B1F4A2CE9D44FC111D9E5A6C99F346379BEEA4BA3B5223EAB08DDA2841086D6974E1C638B82D5FEA7BC85C0EB697C76265D147637E919725BC00ECBC66163A8C589D07D26A61C781EEB47189B993D5FC31876242C79B2943A4AAD36933D576C21AD62596941FC9BD4FDDF223F646858A726D489A0D89AC38F609092660FCB9BBA8B00BFECE9A1C2FD7D5CFCB3ED46B75A7D5F5F89694C76EF76443E37D0CF4E1BC34F18D8FAACFAE991F2D10E06CF46CA7FB40EBC4F849B1C6C7D9F33CCDBE9171C59B48B6BE2C18923BBF33AD0101ED73AF20150885DFFC2F7607B1039D4A020A597ACB7EBDFF1B591EF32C213D8B5C67C593E91E6C123F82BD3F55C5FAC30ED7C01BBD137ADF7A1DD49C4338235DA356EB6F4A4138626A832D2BDF590A15A98258DC283BDE285D12C1BB96E4C664C720F8B04A21F70B70C6DDA30402B8995DF99F72D987B7725AB4426DD9A04473C7079AADA56547E9B275626744EF69C2F867752E0A9FD18DC6DDBC6BE74BC42E23235E8D12A66DE855046C6DFCD4E89B34DCD0D1EB1B0836B74431E8C7154B14F6077DC6BAF602F86AFBDC0DBE1C1FAF81EFD83B7361FFA9D46449B2A10A040B1857CDDD5F274DE67559006FAB88536365F63FF9109994D395BABA2410E613548528311BA3B300B20EA1B29A333AE40C6E77F30D2E0B2CBC47FFD849028189489C580ABA2F2BB9ADD957A4B3257E3740E81515930419B28AA91DF5FFAC928857830E20A3AE970DDFC8B277F656D117CEF643DEA29AD1479C1D9D5F5296011AA5CEE51DD4440A770306A561927B52FAD013801252A9714706E3D7AA198119467BD5F0F4FC1A76A5A727B0DAB83DE31B4581858BE975072809CB1F7E56BBA1DDE4AF1122B5A28162BF29FAB7D4A864352AF1699F3456F4D7BD72752D477EF16FE44BCA379259F6562FDB8821E8BED4772B3870397474929F5354C360B06741A9E2FF7F62E3765A1AC1EB69507CA0682282562744650769798B91B92F7B7B6E251C1D590AEB4C69154F262D3BBBF32653CC1EE51274EF7137D87C5D71A7CB4DB570B1FC0F98627AA025A3CAE57756FFEB5E2CA0DFC2CEBEE981E395166470EC1FEB9705A78CCAAEE282D3BA43073F9F4AA8026B581C2555F2A77467E0F4D9D25ED02D59E1E2D6968442BB737EAD64E377CADC229DC70303D5D0E30BCC620DD22736F4674444B54CE16658058419BBBDD2B75937DF077B2BB131EC9CACECB6720B97AFF8907785D50D48D6896C54B262FC114D34421D3E210E4A393A357011EECB39A877FB2B65DA40638BE4CC434A35B3B215E3FB673A302656C96A49D6D007C1708FCDA4C2D1E1699969835D8427C1B34B14660C2549DF232246D729BD75327458895DF9395F06D6C8F817F9B6FF38C48DF0C0378C035CDC3A3CC9A8DF239597359 +valid = true +smlen = 3320 +sm = 001536C68F6D411A61684379CCCE641D8D321311EC0AF3760645BCC4BCEC457C5D16593C830803146E10C484646E75EC5D0EB8B744CCBE1A0DB8C852D4DCE5FF8BCF2029418FB884FD93E859CC93A2658009BA6DBB1FC26E52F3E3E10D147B746BBD5D072E32B7DB49894EC8BEA11E95FE44725ED9CDE9FC5F0C6D0DE0573148B104AA34636A3DD7E177A903C32F34EDD3CE1EE17E12509146839833FC36633CD1031ED0DA14ABCAB55AA7B33CA7496F6D4F679C684BB788C572F815F495CE895D775DBE3220ACAE830FB332C69FE49BB89FF84E2F9CF252659C888759994BBC1EB7842B17F6E4807DDCCED8108E0C6A5E3315395979F2455A8E0C1E2A15CF352FE90C03E28D55A44807081D0136C70E57B3EA3E57A2F0BC1DA74309CCA31D16EF7C4B0AA0029839D6E517F766CD74E8F98378C69A4F540B5778F89C401530E36CD72CD00F99F2194AF91F1DF6977FB2BA45649690E8F67679DB29EB8DEE15C21EA512E3B01794B65D64B0C4785D87CCE2E6F91C4803652FADDCC623389D0C3729D153A548144396E54DB4533A8F7C8A40188A2FFD81C17A9BA70D5E9C982F451830542DD45DD5701A0354AD1E805752B2CF7A6482DAB42655F0CA011D97CE8E934330F80B9546FF781BC18E82EBC89E5A69F045D6EAEFB6CAE8C5138C65EF89378E7F5C5D80D3C1C891D3167E13DEFCA609257F63386EB0C52256B0FE6B5151BE099AD783AEA7E2D7D7C4A78048747487DB8CEC2244C06566B73B49C9F1693DB4FAA60349C9633A758AB6A372755132743AB22ED8EB36E766286AFC21408DFA556BCAB43FB2CDD886CF53C1F50993C93780FB594A5E63DD89D5E29756917ECCA24A276146188BF4B3D53806571EF5F1E949DCCCED66D5656FD80E0DA59DD73A84EAF9505EB04F5A3D9EBE15E96B2539F17DB286E4C5545A8DEB815D03524743A40CE265FD2D3BD3C6C0B281DD33B64E9A2C2E0D638476AE181B2572D58DB7C0F989510017A919CF5B82F973C255245A01FA567D8C307FA77BE4C6F51F1507416BFDE78060F11EE687F95DDEE6990F6B2B4034AB09A7B3F6D2D7A121F47ED669A36524501F833D26D8B73D8205BF1606508BA9CCD40FBE6BC64B6D784C5FCC0535B63C2D2F4E619A69982DC4922F26181A559387338A34413E8737598286814AC89FA0C9207BDB4AA91062601ACD988CEB88F6F79F726AE055A484E23DA021B9A9A90EA5B05DA9EC8CA1F0C5CD74BA84D6A0D11CB3CE0FCA89F54D030E3227CE6E55EDEE7F0D7A78082A1E14500AC97AC31FECA4B227B76A8066A539F6655FCBBDE001533F564A5DC22C6CCE282BFF9DAFEFE07E65D7F9422A621B15B966D0171F2C94C28D3D91DB87868F190E926E598205695A7516D0B374D35383421127FAF67872F88784382666672A9861747DC46D3AF69BF8763C98AA8E32AC9F57EE9BB87D022D2DAE340181E903F32C03FAE1FD5B996DDA6C9AE8D2FF645ECE493959D97EE2EBADC87005AA88BA797B2ABF5D29892E24837CD311D61F5674508CAA3BD9B9AE6D421A051C2855A200C6BBD4C2D1EC43C25224B55AE9867A971F6BC663044EF3E6A50467BD5028023297F4CDDBEB52BE7D9E32112001B54905825B0965C679F75513F28AA9281102CF364B87DE95E76458339072265FC31F41EBB342FBA2B51609C60FC37DB24B53C44680AAE030A61F2C7611E0D43AFC45F6654FE1B920DB4716D5ACD5C556F60113C0EE898D7575E97B65FA849207B29D0AC649C0D5E6860BC63A04E837415D3A9420BD97856B499F0E839E130D9B8BC189C37A63071A01D79CCBEE4E97EF76060731A629CD188A562BFEDE98C131C8CFE5D419FAC0A0BD3EB8B9E06D1A306F0DFFB863903005DC08115F22E12C57C7DCD4B2624A1FE7511637C26338FF67B40A97CBB65F7E401C75243D17ADA8F11B199487C75F3AB265B3692B7EA1240E1DC4DA62BBE1442E06A99BD9A25EBC5A267B5360556DC6DAAA44E166C65B59AE6EE5376DD46333916DF9D715D13B480768145D9CA08C37DC162DDB12D06237D2841EF3EC473F1792950D9ADBCEEBE8CA6152807768FD7696B12B2FCAE571C58B33BF9B17041959D0C9CD4F0AD40A971A15DC89F70F752B2CFCC8B402C4C0B8C1601E1D9D977EC233418BD8A54D81F179E9F5B1134861F6B26719C7E2FB7FA6982CAE090CA03C338F6BCA56DABAB39A9F4D2784DFA5C8E5FBCE5A405ABC1BDEB62F612CDA83C0B4728605D59137412CCC59FED5C9112112D1CF59BA6776E7DB331EFC3CF83C7B28A0616C10EEF7A57BC9A08924F344A3C2947787909547533094963922B1896D92D48412B45D91BEC4211EB684F29474EBBCA69B82C6B76EFDB7B9FD6E758858747AF359F6789D9CC197C3E7B39242EA789708D0237715B8288F8315609C0C23F3C932FBF6F3A16580D360C48F5E3EFB70AE07F6F7E4A1812BA25E5209EAE05F14C3586B8E440B6A72C60FEB3D718740768A5011F6156D7AF28CDF07BA2779179E1E897D3C40AE1C18ACA5B35A5C447D98F2D1B6710243E0B4CEA1DCEBFF9AF4CB5DF31FECC88B729DD6DA8987D4BF80208ED4B3BC3B4F17497B167A43341B51976925093B8B41FD5D8F3EFBB273382F83A64C3F05DCF6A70E6A6F5800B62D535D48CBA37F2D24DEC8F1134E1960781154CEF5528C6B3F08F563EBF4EEED86761061DBF8D089B2A06CD2AFEE86616EF347D35BF5987A238EF5CEE695B1438671B5B6CBF6BBEF83DDD48EB3B2264FD45FDD115BA0BC4D289A803F71DD9524228E673A1F1C2AF3EF2A979F98F7F4BCAFC5995C3F3B80551481186BCF2B7D399E21CE3791BA4A36E2884DD0498DCCE82B8B6D3CE54BA2745CE76EF1B4ECAA769A23104ACE1F99E217257545E2347BF12C0A28C7BBE6D3A7DFC72119D9603231A9D20D34FCEFE2B60BEF5598CB1085CB36A6FE9618167A512FA504E3AF78AE9A7DE9D2220A7BEBFC42F90268C9992C1F91CA51DD6F1C3E4B29BB156AC115C43A7A52C5CB3CB94C9DBE695A865322E96A3BFCDD549418802B02DC08791AAB60124669606C3AA15225E263111A22DE1895DA83578B880E6E6509132CB6954558A8D5A01B4EA8994691E53E896C2EEDBEDB6F477E76F3716DDF41C10317C2862714D50AAD161F55A68B43571BEB34D0E50C0F23FA61A73B7F85159E4A519B452C682633E2892A02F1AF51599462A0BBF4F51BA1D37ED62FD6DD6C35BAFDEFCB09E3C5560B46D6D5486687DC356B8CB2029CA7614C58540169E85961FE60724B37FE35E631E328B334E3B06559CD4513BC9BE7CDB27A48A013AB02E5CA6DD32E52246107F25CDD7F2B2C7AE7338763CB062F1B5139014DFDAEB310A97CBC06AE44C22C9D874498DDF0962B1D5C32F1DEEDA67EB35B79663394EDA3737A432C5D16E7B6D2F1E58B8477BD94BB222D340835DF44F8449E644717F55BDD3276633637ECCC9020C27082CAE35730E35E8993FA23781E516675FF36455C7C97A46170B4378615A39D257A63BCD77816C9A0D9C1CF756C0F9B524E242F3B93655750C6054114DDC18DC61B7C9DB7DAFA9DC865F628B6B42216674F7047A2E2DC6977091A57D46D968DEA38F77598B9403B816D66CF12681A3F2C7FC782364BC1198F9BC68E552394BF70E7AF301DD00CE37632621ADF8F4281302CC3E27D9F016E0F7FDDCAACB6C9BF1692656C918024520A49DD3DB8B282806B85BF23E06101ABA2FDE0AA1776F074DC1AD30BCB0F1591A7BE9BD0EA7F02265DA62A43B498B53ADE79A449D8E6F0236B9F0C544D831B25C637583861A93A5839109A1CBC512685D1897CE0C3D4A1AAE722A4E2C26A54357ED7F88B2AE6A11D86E230132DD0BFD05372F8CE595D5BA28B13310B7CD49E48AB1A41E444D5C49471B091EEFC11C598B9B0CFC330B003E1A36F0556D52EB6AE4BAB963FE1C4531699E422D38E90D3E4F4C4CB5F456A70890ED8CE2A88EC878F0D0A24CE30D21ED0C7D8DDF31D0EDB72FFAE692FF13456636748A9F101607F95E3CA0B6B5D334002E96A158D616750597457179EFEB38829DDF2F18117BAFDE6825E9EEEC4358C8052E613AAC57A947463AAC827040150A41537C2E93AA468A952EB1663839525DF68AB86559DB169EF6569E132B5DEC205835EE06300BC9C45C33CD647522BA0D04B28F08BBEF431C81D0DED805B9050A4EFF24CAF48504B35F1CE64FA254442AF37F2AC6CCF48E09DDB61FE01DF8A05AFE6FD914E748D9DE966D5D926B28B90B4DE94ACADDB8936CE47E5DD2CB879A756C8863C62CD919817E2BD0A3749F5585A89F3E374B0E64639D9DE75C9946FBAEB6834C699490D59830874AF84C239C7003A4AF24E61A3A43504CDD5A68534B3C8F68C38A3662ADD4FF024E944D52D6C609AA68420ECD274CE3F33A3486174893BA640CEF7CB42292BBC166CCA7B11018441D55117C59982A0BD10989077481E6F878B93E479BFD7BF799C84C38436530C10AA2C442644381FE549C201F47489E15B42A9D4FB2ED9244836899BE26F0FCA4F9282DAFA5957972101A2234E4154913A36F489DDF4C2CD663DACDB13BA1FFAF497B8230E82B4AE50D8D4F8226E9411164B5196C3E8F6FD164D7A85C8CE2D33CAFA027EB6C2C7D0EDEE1955F3348FB0D2000000000000000000000000000000000000000000090F131B1E2248656C6C6F20776F726C64 + +description = private key with s2 vector out of range +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3320 +sm = 6589E14A5FB859884747DFD23755C73B7C934678879769EEDC8B0B9EF592EB521F597B6F02978BC8F2C652267412078B39B728D6B026AD3770A26F4EE4CE6A0330828352E5258FC136DE7B62A425C24C6D03E05FEA6FA88BA5DAF9FEF26E8A761E59AF74C6583FA2CD70815E97BC2F7FBE63F4C9048877AD637D6EB4F6AE89D2C7C927CDBEAF31F46C6F3F3988F890C53326BE3E124D0712A3142EEC3A341709D711457126F1F6C0029C3FED6AAEA45A323E5DF23DE97E1584160C26219B64DE00382A41F5AD633E7617E4724C0024D38ED1028CA117656AF0B15FEBE5368CE38892A63ADEF0E93D13E98E03D4A7F85DBBDF9A36C072381929B566659576CD87D5F7C577EACC7C267218C95050D06668296ACE945BF61C49E8FD82D6DE18FE2E724F964F022292E4D4CFB8C7DCC3D28F1846E71830F2EB7FB64A8171B1FB8E1B3CB501E3DA0F855E502F81C90E90657A239AF07CBE2C7A66815952E6A83D26A600E36F6207F90741576101736BFCEE82DE016AE9380DE38C1150A8469CE7613E360BF223B7653774CB2F81992D629CD0A39C9870B9542C72E38C4DCF10A798FB0B8B122F45DBDF311FB278E6E43A6EFB95508E9926AC9B3576F9476F78E509586653A57303B06A75CED648332F87FCBE59F7BEBF1F20424D4F30E06F4641B32638DA7DEA7F21CC4826B6F9991FD92DC6ACE1E3E33D7BBD2DAF35F4B8E4D984E773793ABB06439EF71041D0FF74CE992B2EBFD0BF3B94574BAEDB529A654BD5A522D7AC80FB5D80D848FFD0D9D3C323C101B998BEECE494F6C27718EF1557BB90F0D6778AD3B8B48F4BDF641B60CF3839A8CB982493885A774AE75225657014A11FE03A4695118A6FBE3DF1DD1454B1B075707F1C79FFE586F173BBBBEA4A96EA21C99ED68974E4B711FCA1B4974FBCB062BF0AC75F290F32C785F7C4F2106C58ACA146A926AE912E7C0D95DBCD93D8435D08A984D9DC6D3A8AD6E6F09634DBA641C1E3C519DD38F25A4CBBBC4B49887AAC12ADAE7D0085B50CF3B3F4A38319367E62D192EDF98C4EB4DD15D8F34283C6DA0BF6FAD423011A968F94EC44732E292B62D96739162A6E813CCF978639FBA8929698002551F1E834C4B350044FF44693EF6A028EB224999B127B800248D085C3609B84A821A82591D16C0860BBC3EE853DD815FDF5C8695299AF6BC979E8902DAA96BA75F87435C97CE7E5DC2CF5B0638F5EFCC2349D464FF60594FAB1FF03BA5E90415A813693905E20A3F07CAA5731A7B69BB9B7028F493BA65825826709AEC686496A0CBFB2EC9224838278A7FF0068712EEEF0A1788847CEA1732A1FBF48ECF6628B809E9B8CDF85683B2F0957A3E3A78911A08A4C8528DBEA43E7D2C26AF405832CE6D0199EFDDD208EB077D99AF735FFDA60F4CAF7CC9E5C6D96F77D354C262C7F6AB36DC57C841DC5695CA3EB6430DA473830A966AC9C730577588F384EDF35E00C77BFC4ADF70CBF039F75A8F524A72A6C3D91B9C0F7ECC18BC97CD9E86CC4B077F28F5C81469CD3CDDC1273146B819FB1345F83E2E389D4D82D67F8145230365CA68F517896121A4C335FEC698A6998C90AA1D120AB54715EF1935924D298B2541A4B815969B20A657AA0289A4EE98B2584CF9485DFF02EE1C823C1878A11A3276AE719A9B44B31E607F3BA82CB3F89A36EA64C82343E108CA357F461721E6512EF823D15A6F50BCAB489962344BC5FB7B6D32AA7E177530AD7D2CED8D4FB4EEE07BF6B9137D62F1FF1E8D196145B805D037D4D922D97D315EA37B6DB5D78786DD651D520FCFCD83D35C61C9459DD1ABDEC5C7FDFDA068F9FCB6A0D8697A5EC1968A2364DE2C87979AF280DD6A113900B6D71A1C667F8F9163FDAAEC41E12E234CCE2A22C06D03F96D3EB95F40C8B2AA886CB0F27B9AE33B3FEAC414CB00F184B64F684E91E1C672020E849013F13ABF3CA9DBE10B12FC68F61B76FF48E4823E699699BCA18EF394110110671BD336CA7013B0B694A1DC5198958A6F33469F2153AA9855809B2CE9D40CB9A1ABE3FBB5F29BE6A16C7BBD0FEA398B214429109F11DB96D2757F3AFA6A4291386840923640D89DA6EF249270A5E779B5B37D301156018BC64EB3EA49368802DFB372F7BB208642186609C7BA264F7E0EFF71CEE5FA7E04CDDBF5B4269D11A9EC8D7ADA95DC65FA1CB262EA0902980E7AD0CBFFABFC50BEE60D83368864698F64787B7F62084D847BAD84C1882B45DC13AF9AC33FE7F185D699CF902F01BBF20F3A7BE7BD4F489E87B0CE4E50EE0AC7D1EAA2410D8B3FDF00D2EC2005D654E239D4148055BD3F071A6F121A2A38C6BAD34B0183BA826E7363C74AEF4A5F460CFB890C152524D0C3A50E44029C2DD323E08C989BCA6F86951389626C4E05EE5DEDB141ED465BC8E2ABE8A7B05A3627BA30ACBF79D12ECE568D61DDB836C1D581F3DE127A9888471546C8AE5E9AD7DC7D1E5AB477B735931B7091BFDAA69B0AB8976E2861BC178108A40E726225D79BDD4643873A251C87D8146BD45B4FE97573A4946B51632D55AA8D4C24BDBC3ED8E6BAFC39A503AA25DECE834467B3485ADFBEC2FBE7AE2D6385FB2ADEF081595F7B67C887ACD14F1A97FD493F1363B5CDCBECDFA69CCFB02C03A7B0795560A69911A2DE0E8F6EFA29DB0E4103763930835266ABFCFCBF338040A8EF38B0401A4A98690CACAFFAD195BDA13DE62185788C2043A2900844497CC3706D5D13F700052D16D71D74BE385F9A6AF2ECFF497E21C518FA61473B9F0DC36DA3D322F24B6119DC6C5E1D93FB83FEC7FFE91FD32D230342D2BF4F80765FD3C0ACBD85043867C4A14CAA2FF20DA4D731EB102C24BC9C6012966467F790585F0FCF4F9B60BDB2F7334DB4FAE55808C999F072AE4E995AD4BC078E4206954758F2DCDE2072F76A5958BA63C3A49868EB3FEF5A49E042D07180979BA79D732B2675C702AEF3041D3A6699AB2D1A6DC76D4B0044536329A40BEE29021899F2EB024EE29B96DF86FB6CBC129539E1FB964B56C2D14E08B9A793C59D43C5839FC977BFE938BA2B512A76FE450EFE166D9DAA5AC670C875DAA626E664381A6670D1671D439F763CB4221C7E89F298E04590FBC315E214CDD96E50C6CE5972C9AA649DD6ECFA32E454E81880794074572469D5A44CFAC07998616815F2A1D2397FF5D7B4C10D24F250E0EDD05EF3C462251C81103AF606705EBA22A7A4F5129840872309BB7E2BFEC94CA8EE00FB41407E3D80FEF6F03DA8499A86D2AB5CE65EC6B745A02A072ED0907CA728C2CB16D050393BCECF72706608038CCBAC194AB4BA306CC2FE44E7A69E713F8556CF29660CD20C7912138BFEB4FB3E42EAF740A8C4592E2A79601F7E6432F297F6856A04F38C05DB3F9DE1A23170315257F38CA0CC2C1C1961A851AFB342AA7263D34231E3279E3790C6B46E6B60137CE361A9B7F9CD3BCD06FC2512C4CA4FB1B498F88F3AD0A45EB9F7F281E4D2F8A8DC7F003BB6945685FEFB80B738E94EA4AC18ED149A7162FAE53BD658FC29AE467865509F9DAF3CDFDCDF489BEC5EDC5A8ABCBFC43C032CD10A4DD010225EA88E2625B19A2C019CD5CAF883EE2BD8F1DE21B2A884A8D6EBF4A156B8B600C98670401E23D34C6BCAB2CF9F81193DE2AA5A8E49744CBC0E5980E64CABDD4919831B4A532B01722F54C20B4A5481A62CB9EE7ADBF01F1137E9D4AC33BB775345A8A465E9026C80FFA25EA68F067076DFC5A338EB3CC5C2187BC3028B3F45BEBD26BE52734A8D71D0DCE4F28BAC2BFB43390B793316B731580498EE651869099D40045135D94656A6DC0455E778535BC2A40D232FE14A5E6F5EB056731DC70CAE835372EF463430A15A991B287500C5241D40997B8BC9BA99B4C7D87B1B18492F02A6CD769A87C1F1475A3DE27FC549F030DD2956E3BF01D6FEF9E63F5EA844E1EDB3699DF080AAA3E44C9664948A27FAE173C4442E37CC31A992764121D3329E30297A9412E0C8216D15EB836C26A9BC3A3B7C7D9B09DD20A3A1E2C9588D7A2736F8E05A3F98D2D37D868A9A88050988A4C8F8D3D17D9D92C269BBB42709C083C6B30BDBFCF94E8B5F932F4AB8272BD81C3714381D8C3A968BFF5C6CFBAC90852D1E54DF7CAE73A92A0ADF97F698FCEF7C861053CF02BE42EA4F02415C3A5A8326B70A6EEB9AFBF17D728FE1F6CB5774574D68F4EC6C511E11A4657BB7313DEE5DF1AFA4EAF0E6DD009F30C24AC1BB10D52701A056578C5E0E82A1DD4CEF83A143A8AAC3CF9BF1639D3D7B1FBC5268F9A313F14140B5AB458B8FAA95F242850795129295AAC8160C85E38B2431DA00A6800D836E36982A9A378E4354E00FDB50ED0EBBBD17764EEE2FE1E0FD4495BF7B53819993891C8F68D510E2566B0F87BB88734D83ADC531352F494FB99520EB72D06D908922E5D2B9AE6527F81C6CAC254851A3BD733066D69E45C13D76376427BDD4AC92D5CBE41013E09D6B0B84AC2A6E41C81A3994CD929175774877198AF8A3263BEB51C5C1479EF80F6F1B0AAB54118249B7111B8C49186BD0C7AF66F5A0D865B1E10C26D19AABF546C979444E96EF3D506562F57D06B4FF55B8345A9C76B4172B0E25089AFB7B9BCE3E52798B6E7102230407D87B4CCECFA7999D5D7EA6A8EA7D6D900000000000000000000000000000000000000040C101A1F2448656C6C6F20776F726C64 + +description = public key with t1 component set to zero +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +valid = true +smlen = 3320 +sm = F90C671A8259C85BEBCB01FF120F55A3B2BF0AED40C18AF7382B4AD29CA238C4A62AB8CF3BC2CB8A0DF1D5B74FA4D7E500000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000080080000008008000000800800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000048656C6C6F20776F726C64 + +description = signature that takes 1 iteration(s) +mlen = 32 +msg = 0300000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 35390D83E9B544E464339524412D01BE38C19E0A91B4BF2373A59ADDDEE17E5FA0C6437F27A97E16B05C916EF7671962F362C3B11A422D60D07FE9667EF4225C3376BC7844238D9D80D289AE111A82EA08CF2901FEF205BDE7E2F76EF3DD75FAC6EB6CC93BC493646C393AFC11EA0EE022BB03244950D3277293FFED1B950C15F710163DAD25723E551D01E4EE838A8BA5C815A4937572539629354D6CCFFFC516D9E3F0F5FEC67D7A8A6C7EC169B3E4F8985293DFA7C2F8F6060EAA81322683B6DC50F21116481B2FA172FFA76E535EE37C408ECB7C826BB38E05F3908815FA7F4009CE0F6C75B6279BE48F578BA400FED352634123796244974B5C978F7FC6A51346C21F56143415044411D1F7640CE49572FA8B8A8BA0322599DD4CF7E8E12B96709133810692983E69F27FED2EAD33F38690A49668FCD10B343890C38A8974D72A3952E1D6DA7B7EAFF59FAC010F821620CC784A8858D04D1241E16A0C2A656D68760EFF84B63E6F60B3FB98DE3980D9D90BA34892202CABDD5CDB1BE1A98C7FD66A127EC3FA6FD5B68B1B5BFFBF91562486DE3DC30294F63F81AA5E58D8108F813853F26472A801426D2B0B148BF908EE954AB9D64531D2BE46D43BF1CA6CF00A2644DAD4BD63B79ECA088A7356C4C0844B986EE05B867DD8E50AF832302EBFC8BB1D9C2B700E8D153D4D2F220386DE68F2605DDEECE2A449CF2C92D002841308B0806C901C2DC3908CD086993C2C5922B218F33FF8A4ED4676E2C95373BA9C3A3290CD399A3E2E82F4E3B7D94204C432DAA4E9DF6659DECEF06588C0550ED995E078A9CF6DF555127D58333386FF5B62D094985AF06DB92C83BB6FA88372DE1E255EC18C56E100DCFD13519064F87A6957798E1EB9D992850FD335EDCAF98328E253A02CCDC4EE7C6F031CDEC6875EC6577FB6E1DB278EFA20DAD69475925452C4931FE701F5710F1338C0DDE065F78CA7C31480ABEFADD2706AB4454F21EC0FC3818EF0472481D30820C910C50CAFF4D1C0743C2B3C331CA2E32632DF7AC797B12C360C982109994A987025D0DD57F96E9150B6FE1061B84543FF05EAAFE9FCC3CF4A211FB5187BCB381013B26BC444A18EC3702FB42A0BBBAC7F19A60748506E22896F091B5696C4562454345EEB4E80C44888B514449AC32C50049703E8ADE88C5584FC94B7EC766A40B8A9BD92766F31B1C35ED646CB0A012C12FEA5CE1A7DDA4062754A21C1BBE641B180EF277C7FA7CD01B2533A7DDE8573D9B89BB332DFDA4DE383698E57F3A4D01D7A0425F64F635D8D345913241D8521DF09A38F8B1447582BA401D4E68F5D0EC96E283CA4DC33B228A8A233D3841B463E041CC44F08A5BF6DC176E7534CB209617A4226BF78C124B6D9B22AA27536F63DCB44853ADA78966BDA53F07A74A20C6961815786B09F4CBFC99FF499163447DAF8290BBA869978CE0799C7BD7A803F91D7B18C7F7A82D1E019DF788083C9DF9DFBB1CBAC0BEA8937A7019111213D8CA12CA85FDE3AAECC805E235BC4B038CAA02FE1FA6D5211CB44A03B18A7566171A9527B902FB95290529B0D6E967F38950706E5FF29692CDB8E6641E29BAD6D5A6BC143CC0E2DBF74A1B076D84CA23CB1E90D1B4A42FE208B81A569B085F55468E3D4F5535AA74DD8756C5411885AAEA260A4C47738176F6391B6E34126F50F19B5E1957A6BEC7010E42974A49172E7E51E6FD0457A3494877F76961997953FD2A1264E28C6624D70CC633B3E5C3BEDE1602D2F2497EF5DC9637D56864E0A07AE62619A7041F90FDF667EE326BC4AFC1BC844BCA948E1B5F6436B150C2B9CA9803E36B3B00D24E00CC91FFC4CDB73B2B689D9A1144243B7EF99D46BFD47E70DF5FC130A19B85CAABD31267BE6B1C293032EA0019D1B34F6F9ABB221A5ABC99D8229E8C0F95313562ABC358E19349DD44F56924CF40DCA534B5343558D445FED929BF50BAAC983888F88F913021A2D17A25DC5F1182C6271720FF64AF77DE6EB059BE9B68B80B87CF3CB8E859B3730F838AC1FD533F6710EE8D54A740095A7C95AAFC8756232988F32FB135811747A60823F68310F1F0B046A1EAEDC9A705B3D725663B9A5810DA797E37DEB4C42FFF7E770F85456B53245B84C9366C69018D7AA40BF3CE643A86A5EB3EB0DB337C8FBD64FFE9FBC4990F97B3574E8113287D2305FAA6378FC914B57027350BA8078D145864F8827F445896CF9AAEA17E529E92225E9C71CCCCD46FA516E9E79E433DC219EFA398603D38C14B4D61B4E20ED8346474D0B15231392AE0486FA22BF438EEDB9E5E57840DFFF4AF51DC4A60DFB5E87E984381B3AAC96A2091AE4E884EAFFB423D56412981B1296838E86AA4C6B441518DBBF438D2C2673B9D7237AC2070D4066245F77D2AFEF2E0878E57CFCF3D50DDC478354C7A581AD82330259A8A0E45DF110C341B1202983F64C388568AECA38E1F1D8ED4FAE542D6FD17A81F7E9C27BDDF34FFD09F5846110B7B142CE7392D17AFE27F3306FF59B502ACE62989FD351D38E599C6D7B1FBE5A742579FAE6CDC9CAF6CB6086ACE48194432C9F5A5C17FE107291409EEDCC89277C1901693CAF014560427E6276CA572E45325CA861170D5FDA4FC4317E1C566FBB504C1918BAEDFD8C2D1D216BB3F58DE8AE306AEF3041AE92628A32EAC2BD610B2826C474C212ACA3F2D92B97A5DABC1233F3148AEADD53B601F57413B27AD0DD861C44923B6A8A61BED0E8CF5F060EC8002DFB59CE0648F595FD60E98AEA4AE82602FFC2DAC37D129A57B9CEDE8E4911A1F36E87EF6D9111D31AE78D3766AA40913D7B87135F1A19857CF2436B38A9993D518DF444A23B98BE28C1F17C2B8FFBE954BB149307450C317378B5FBB9A86BE299D92E8F0AE52459A8B281AE9E991C8039762A072C78926E7B5B1BD2F032BE517A8B37896F3D5D2AD4C1EBB9BB893FDCC509BAFC2B83BB7226A90C7050C893549127B1DF0126887A3D155837EA27EE188D6C86D973AEC3F027F150E268A8D2BA593E998F43EB29402A1F912047194E4E8FE4346AF0AA003E522FAB92037CC16BB1F7E1878D744F6FF765693E54600C312769C0B4B2D5E12727D3052A73114D2AB5DF5E276A425D941B3068E4EDE76E7F88C38397C9CA93CEF4F34B694C2CCFCF0E2C887B8D3C2E2F01D9F3649F9D453A5E52780855A6D6C439B6975594BDA5C25CEC6A6A75E536EBC8E836D5761B5D2CD1085EBFCAC2B0C49558CDDE0C18B8AD46700941BF64F810418AD7364A9672051D20C8EDDC39164F2DFA20A9552A3132995A247F43C01E835297535A55568E95D6AB2A4B3BE1442A0C8F5F07447FD5D285360B10A044014B1CF4A1410838996A57DAC7AB8C34960F568EE9A858E99A4B498AB235DF57BA37215D0DB48C94388A731AB285A987442139254487DB2D244B350E6F84A27545FB0FFAE19AD93EA658ED01187647DF0908EA644C3591E31F096BE30DA4E6063FA201FD725BD9E17C945C4E1FE4142F4377E4C866FEB2839D82E8252C27119BF498F6F0489DB684646F44CF83FDD9242434BD35A65BDF9D809E53A43077598AA8C45BA86DA107414D2E46136DB6DA185CD3DC8DD216B17440FEFA541222B52C6348D6EB0FDE53826890083498F5D22BC87ED487ADBEB3A55A8F3CE68AB614E43F053A26431255ACE3DA8B066C3BB322FCC6D1BA99FBB7C116EFC5A31836C59B57659258755FF5067534DCB875FF1BB38178A146C2FB0B569116EF80730DE85C111946690E0F3D8F48DEA6B1F34713C73A5BE7AF868CB2510269C450CE1EB2AFA586F725FE9FF0F595A6F12E32025A96D71072BF735169591DAC9934DD07E18DB0FF580662FF0700E5711E08E58E406DB8668BF471480E65B23706B13866C150B3291D042871F8F2C0F424DD0009989E395C11EF2B5D33650CFC05EBE52AF1D27A038CE34CB83947659393D3DA9A2DCF4A63EC3C022734841DDE0CB8EF21DF6F7258E01E7A2DB59FC67DD7368ABB0B1041D7971DBB9077EDD3107F9D310C435AE2D126F0D5E14CE8957FA0DD3BCF8B5FA42FE16A3DD2AE0BFDC3ED778968B367AF3B788D4A2874CB56329FAA49DD84B4FB60E8B256C76FB416F18FBB3BF5B8D3DBE94DD1AB3E82B745766244A5BE8EE2D2ED932D95CFF0B396C8BC6F6827BA0E1926FDBBCE0DF0CE6A0DF631DB8DAA72146E2E8CFBE1C0B573D00E5AAF755F7E9A1454CDD0D165F8E077A3E5EE7DEF1C59666F8179FDE6E2CCA97CCE9C696EAF1BA66DCBCD3D5EBBBEDFF43658C20DBB182A48BBDA59B3C0F40AC4C75289759EABAC31E6AC40D008F135F4B18610EC21FC229AF0750CEB7C52ED25BF1642D4E823232A6479E30C4CC431741474208483650D264CB0AC88DA48CB9878845D88CD4364621B34E0CCFBC17EC9BB13AB04F298EC8C2172222CFCE5E0514958E61E75235C0C45D171FAEDDAB4B80CC5BF863E8E05EC00443318FED599BA7CF66A6EB330D461ED40AF9BF0ADF600DF2645EC7DED8CE816F3EADFE38F1B4A63722895DE304810218AEECA1E4A7300718F2515C7B1BFDAC62E1DF2E686BA579901456C43D419C165479E34E85C5F902DEFE7FAF34E386368BDDFEA1A49528894B4C0CB0929363A98A64A56D5D81F67CDFC0941486A869D9FA5AEBDCCF8000000000000000000000000000000060E14181C280300000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 2 iteration(s) +mlen = 32 +msg = 0A00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 06E1477F032B417F6F1FB468D213ACC90AE675672E2108780599A0C778AFCF50B763DE4B13DF5C81A0EE78D66A1C0AF7956A1C1654EE03773D4AE23039FA749EB8E824212B137D4CDB270F790988990E0B24DA0B14E14B48C38B96B4A2916F7A8ABE3E0F3847069A4497CE70828DB8E0B7A143268732324F6516F160ED54D2B1E7B5EA31FED71365B7D7BCF9D50D17F9417B0AF1F6B5DB7AF8C7063AED32C21AF3A71027504DED80FE1828FAE33675D5D1E47BF45DC4E1102313DDC0D9C3348E5378B68CF29B6AA3E80EF854DAD0CE1C5E7CC5EBFA145E51CBA874696F4A62EE4CF0591E1F78CD5ECE9AB042956F9997EBD609096B81F95DFE461A04172772A3EEA62B5553C751E039FD2D8D8283E745FDDE2B7320C06016DF6D260760542D5D433EC9594E88918C7A16D64AE484EFE5C7A4BAA4F038E5C777215B3C84DF89C67D57A766E7A51CEC76F4E14507B5FE3818F6C91F43DA897D1A97E100AAC0265F46770B6813642F6E6FA9611B982A8E1F8D79B51A0ACA523CF5C0B2C5E2D6A9D5BD4E166A60491DF2C777CC1D3BF4B0316964B066BF79833B324E15BC2C862D524D5C77F563F3B7D6A027895B69F6C69ED0E74FFDB3F3F708D386D07A13B1F649E428ABA12DB6CE5AF1AAA28588DE91154B1FF0B0FE1CF78A0E087FB03E0146E18451B7FD992A1EE7E1FA25DD925EE77BBC8F8CF1080B862378D0923524240BD3A696712A3A9F7F8C088461FF3627FADC6237356CE0F3EE9756F4E0A7AE1042AC2608DE536DD2C3028AFD1C250E42F9DDA6D8DEA8727B186566FEB5E1F9E0860742C802476B115346D47C732126540AFA947A297FF963DAFCB7D67FA1C1BF877003D987A151D7A9C5961C92CFA403A6288863FDCE1EE59730AD62204A73E0D5E6D92EB309AA115CACEF5F3270AAEC3375904D348861FB5A3CA1FA509C56352E185B5CD817D037A0E64BDFB80358A0410DCFCD16946260FDAE9DD9164510951C333BD1118E0043970CA01B2469062CF4AC39285A01B554BB45459C999F379226EEEF754639E8129F6DCAA695CB9AF4026A86C2C32CBC4A7A528F2D2C162C9D78B4976D60F03A68037552139094B9DCF6CA1DF2882D0B13CE681D38C271FB119D8C0FED6D962DB8E0FF56DC528DC099D24CD023EA86FFA85BA2F1B1A3EEA854497FF0E3274083981478F7EA090F7E6DDB1588C0FC47F19D6C4E55D51E78C026010F9BCB021D7AF31E8BC9688810F8127A79DB03ABB6A1977A6115F89AF9698CC9AD2A1F52AF5F485AB1BB77E36C946AC5FF4FA22B8159EEB3569FDF6D9B8CBA45DD5232B6CF5088EB08EFFFCBE8256DA673E198F692A332AA6C2D61596FC714AF5D74193DB856B135945ACF3BC48F162495DF092BBEA85866A99EF710EC7B814B04435320CF1CDDC37A641E73FBDBA77576B64D6C0F26A3B7BC43F890CBAD92E92D5AFAE9FAD7E008C2E524AE4948819EFECEFA253372F70868F0BDB705981DA77C6A134EAA18E093D8E0612AD5E0939920063BA299B3FA7B67EB3B309F2D3B6ECE9BD7043D7A69C23090361C5D78877B573141EA470B600D55A8135C2F2C88DB871109AF0C8629FB3FB7014339911AC78396B05CDD8DD994559F671A1DF9ABDD0E351416E99AE6831A2178B3BDD669ED2B0E36FA7FF6E0D003FE748DE3E465D513397BE9DCE3FD7808B598D824ACCBF614D9C3BF37FA202BFCB39419B617DCC1BFD1DA298DA213D75FD72ED5FBC96FF692E250EE1168E5562E943697ADD071DE60D275F97DAAFAC026F4F330D0EBDF78CCF4F5FFB5D393BCCA0A4DAF9E5857AD6C568306C0DFFE7D4B25E27B5709D80F4883F2F4F2D0E8A74B92EC438046C47B4ACC70D74E45A802D44196251F0DEF2736668CF5DEA20849D102108BD7C1A3B7062DC8C27F08C6E9E58BDF80BE8AD297E0A345D5FEC9C56E2DD682E6E8F83C906D96B535D1E46996BC48BEBEFA31A994A8364CAAECD14359BE24C1FA429113E7138670F4B0B83450441E41575CCE13BFDE72F649DB05B252D8DB708C1EA907208679AFD5F4F6AAA47AE67303547A2795D7FC6D640968377E36452EE667B1FC95E4E00D850D35187B2A5BF6A14D7B1CDCA7444A15D6746522F25B505CE5DBEE34C3C90DDB5D14EC017286FB433A8939E626B9AAAE6A00362AEC1D644EF01D45CD6CE39CCA54125B80E0AAF7236CFAADA69DF1213CDE47BF7C66E2A685C477DCFEB051BA25D815010B414708703757EC2ADF8FF68BF6994D53852D9AF571D0324B82EDAAE973467B8BDF45ABDA2C76E716E16403D953C2BCE331E03948D6B27FA81C841D23F2BBCD60178DB3B8EF769CC7A7C35667D5EB5129AAEBCD792F8474B4B54628E64AD7CD14CB1F26763257C90E2FE223E122882CBD6B4667688EF98E357988650B70597B014AC487D5B95FB7DCFD1FEAB4A875E76BD17074917A7EF1D5A1B1BBF44650A49BF976FE21AD72D31D91BD628890AE0AB6B8062D111D441DE4E7BAC80346850891DEDDD0E437D6D8F110ED16A535C9C1873186A68B13B0F10A5DAD3DBA0C14B3BEB544306F57F4F302A732B46BD30E8F95943FED534D2EC8C93BCA12A8E49384E236B63090AF902E1B291806A0A595723B32E2BC84A94DBA2F767EF2E9F7C808D7457888041FFB6C56EEBC22671F2EEEF5F865C69908932A21B9E39BDE4195029ABCB2669C41317B1A86AD43F0F6B88730EE6A6A34EDAB5F21E415E33EA6851589855A1D9CD7598E320F9CF2D3D4296C51324248B99BD83A5EAA7216791195CE88E598DCC9E77302B4EA690A056D9BF1C6C148049B86BDEABDCFCE75790D5781405C5DACCDC08AC560B294F5F1FF08A321CAC157391C6C4B05656FE3E8FBE0328F03541BE0A7423E3943DAD132C513725C470F4EF03C6C3436606B4292E9A3387A8439E572EE08CF6601A6390A3A8321B6AAC0A3798BC02E59CD13DB4D21FD24B7976DB3A76122F80D28247E0E3D91420531A58C935385947BE95AEC39837D3CD15B95C849E4033C9CF01992463793F4519E802EE7FF94188AE04341F77B9FF4D02ED489CA4F3D6692BE73423AEA0FE07711BDA9DD212FBE0C1D36F3E5180EF5CA3D5E236D7079F0DF29BF01EFCED2895059C59E69F89D2557090F41C7625BD570749992D8C1516D0370A8EA089D10DF7FCBC46BA9B1AFE8F83D044089951F48E020B72633993A8BE6CD138506F4122339CD61E8FFFB67E1556431503A2B609469F80ECEA17E8B06279E71AEDF7BD40542DA1B78B040AA9AD84A47FE0057856D656FE6077AE9C15AF10B05F5F7E2E7E158F7FD519B4B15B616D8CD5604A59A30D9CF6523EC5F75F1381E038F29EC5D62A40B7C84818C8AEEDADC39C7AAE6E2A354BFD71712E81C9E8122E8D11BCFDF6DF8B3BE5493F8C24AA0A2BBEECE07D8E22869B55F9B2052064E4B2B6C10D578E5207764CCB3FD7A22475C89A95DF8FCEAC1C17554FC74485C6DAFF0D1BDFF7C0AE17CAE3661628DAA1F4AC3F28236473BDD036CD1BC23DC3615D88B29DA279C8932BADF7B46014CF7AD68032DBF5AA74CC74919BD52833C027DAB146E0D3C1064EDE6DDB9780957EDD044B27915D15DF7AA497A7351328C91559853FB9C9784E7307CE676B54FF2338473D06A13186E1A943C50155D726C3458B87764519667471965AD94B44273977C30156DB0C52CF0A2294418F83A29CF88A8401AD54FE75D2BDEF85F8B3E1D26B73B6F58EBA6639FD57E11E35063F8D445B55855D59C83E798D18E47D5A58BBF01F894E862D2FC7AB1A5C7E9BB59DE924182E239F4CB443BB3E7B5A4BD42803032BFB857BEBF21029C7DD8126113BC8D3D72D18DAC0ECB80A1D65F8997870050FDAC159915588C3CE74D84B4508B5A85CC8BAAF19A8CB7C110AFE83882EF4E11EFA9F7DB7B70F770DC695EBF6302A9D2573B5E72D7D14E44B62FC762E0E58B0E6B442464AF9996B01E6436A43E2D07B3972F27AE7043D4539E66D23A352C43D9E41FB297C2205D100806F00A5AA814F9D83BD28014AF96AA7396D8F6B01693605A2CF1E4D9EE35334ED1DB913869F4657454B98B6C18FBB1042CA875C117AA64F30B16FC25501FB32AAC607EC6800629C8DAB7BF8E87A6B21B051B8CC9972845E63D785FB95FDC150AF9DCEDB4ABEE97A4BE07ABACD1453E607A3D97343E499263F7949A23DF69A2E5A373749BCDFA8260E6FC527B06AC347B73DF75902B7ABB28FF73A5A6C5CC7D3A75474E1BFD8A306F57867B5D929DFAD5F1256D16B79ED5620C5A6011D14124E4220B5385AC38D66C6A799379B2F88EBB582135584171431E70B84334591D8B5D640E4DB39BCDAC0D6BDDB2A4C8F2D7C348E8EB04DE5335C29A36CE8A94D61CB3D2C885AFD64F7D62E13B1337AA915E503C2B0F1F75C106B92669C0378BB7EA27CFA7E0C5C6A68DC8394EDD4C1D807CE69715796401211E58623E469532D529D0590105BF7B65FBFA126762B9FA80F0AB0434085721B996619017C33DF28637324C0CE95F1637171B792EEE9E21D460D0E3525E78E11B00BBC59DA44489C14AC50489D85B2EB1802C9744054630D1896B25A56AF459296CF4054E9C029677E41C7B719CBFEADBA4B35D222A374E542E788296AFC487BDCDD4E3EB092A3191AFE0E313243A54BC3D6B000000000000000000000000000000000000000000000000050B11181D1F0A00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 3 iteration(s) +mlen = 32 +msg = 1700000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 933370D9DBA15CAE6BB2E5BD527AAE89AAB84158416EDAE3EC8B082123C613727C19A5D36A429CCA70E084AACBE5814D43C86F6576372413458FF12FA0FD9A971C0C9599160348FFBE5A4EB36CDC471B1FDEE78FD2C9FF27850CCA7DCBE1FDC7952685AA1DEA344233972A5E98DC38AC5FEC50D6010BD62602B326E8D25F4F96EC746AC95DAE223FCA61F87E374643AEB1763DA40F25619C1B759A68851B23C124C669D8E40B8178435D1C759A4D76ED85B0D689DF4123A28221EAE8AAE39C9BE30AD50A9DCB5DAD392A487DFABDA8F00406229B89A7A2CA5BDE33076343D26F7F804FD5EEC4425562938850AC8424632D0152F4A3C2333C784016998AA5D1670137C470D2703B963E8D1D75AAB8ADAFC95B611A6C798C5FD989512ED5C663E4B5E4A75EF651C9CCED827632EBC92F87854FDADF891D61B6166A0E60A8C43212566B5923FB58CCF77449FDA7A26ADC43070FDFE51F169BDEA03B375B9EEB9003FEE45D4A35B94CD05C2AFF37D73FC3DFCBB3C0730DDDBEBC8FFBE931C00553B951F3F43721FBC9A35B6A66CA1CFC7F3C3156174E392BC0365561EECEBE498F17738EFDA8FB3A84B1C0372BDEF2F2123FA4F2C3BEA41F68FBA80987086DF098D5B723D323EF4118F82DA49141E7A0F3482DD73B09A6A4A4AE7AFEED28F4B2A17FA2013256E4DCF58AAE656A5A5AB7329CFEB73D90EA6F3A119260D812B6FB18BBFDA9C23C96F1D2E35C2D847A9108E626A8F1A186DA2531045B2138A0366286C87B789357133A838928B943684C3696AF815A427343ADD25C51D1826FC48A6B9B1083060279AF15BD4121574439AEA39B97E20B52E90BF9BC39F1CD306B89C014A276B76D0D46DBE9262E020CB75F7BF9C03B1BD1AEC2374B3CF8963D620AC70695F210B95D401D61C3823A9E486C5DB3B5A7BE095915BC0CE03FEE3E555F76C7BC8179C5C7088E0DCB4D2B9EBFB9CD4D44E94A9C13E5EA33E0F8F644021B16BB124AD74A3F4B974516CBC123294D554A6C3D619DCA00A62D2229FE47D56E97FA63AEBEB84F96DCFA272B224983D54190F50DA0759DBDD4168216D0B17CD29D717DD111BB2DE1038F09B52B996D875DE39D393247B58F6AF81F228FEE3598A4B111110C125B71072C483DE8B42AAC1B32570C3B703CF380EB718F37572BB0B402EA427FA711649B193E708DFF17A369CE430033461B5746C887D7B0D885535EE4701F3177947E66272C5B76C9DC1BD927D5441FA3BCB06ACB2463017DABC1DE7BAE9A73262FC5EC075B1E31E7D7891D336BB67B2B28767920BD35CD2C81082114291D1E0AEE7A285FE0AA6E033124876F5F0526611F46F99DD9CCE92DC67A5116348020F02890AB1824781C434FBF222247042953F86C639B90BFFE8F22B6AF5E219031AD3A093171F88B1E285B9AA37FD2FE901DED5853EC762892477A53989BE6B56D68668CA30E3DE42477DABEFC134DA18BF4AEEF27E5BFBF01C9A26E03EAB7F77275FDC9A7A762373297F71A522EAFFCE5E5774CB46BF270EADCE581E95DCF59878AFBB0D357B5777AA1B9605868273C2405BFBC342FB15FE6E24184C98A47142E4858A2E05FE2F6D7C1CD3D24587A743E5B56E4A74BE19E8A1B3651012A4EC6CFE3AA79F008CAE2C72E130EB21969BADBD1046A7982F53080AE1D05944BD7AAFEB0A8EBA906B8A6BFD282FA84C60F8091BCF683526A7EBF458A8E38F31AAFA2330E93187EDB8EEAB52A41923596BF1E4B17D3FB258BE9714D73F8ACFD6160C3D3EC5088A717F8F95AE17DDB97A62D8EACB41DAFC8935704E4503EF6C2711BCDFD7AF7F84689655018D805752774A38480AA44E8BCA3C63CAAAD21E999185B11A25FF91CC5F0EE469B5A793C11CC57D39EC4D990A1065400BD4D7B1A8256771EEC57307DDAEFF11EF1ED288E4A1846085E45D54EAE002FCF6D977B0ADB8999D3D6F80D549C49BBA7F4B444539A7D6CC35F045809EB8689D70AB8C3E237113F12674F57DFDD17DEB72FB6E387C8BC633610903A77DD57816CC0A6E280A4E2F33A0AF1ABA75332FAC152FADD4665E7610753B7085144AC0800BCF188EA0C19F1D4C27B5CCEEB603F4F7C88EC89361821E0F226516D19384B1AD1C416484B0716AEA2BDCE885D36990CF6524F21615229FC002D2FDB242363CF8114662A1D1AD17BB1B6E72432C2E7E137BA7C93EA9F273CC80BAA30326CE14E17DF0BA54EF2CE11E2F34EB44927D3A14397A04A3B6FD5DD1E73A73002F7F1D9D1428F6224A11A8D36B0BD0034B5ABFBF02DFEB655F08F3E0476E6E6D6D9EC947E2E67AA4F6E745365EA91C025D1AEC010FE1E7E938835C89A5258A9E0EC5101A60BC70C3D0A72FAE0958BDB67FF5422271061670247BB6DAC5C8B677492676B57652EDAB72C41B09C27BE11EBDED986A1AAA642E6AC8C7FF7BACAFA6F8C46F4FD89B4F0A01C70A7A6E7E9282CC6B54E22648E1B65207B8D7004B1CF5F939FDD8FF53DE649BDC90A252C7482CEB3CCC6ADE3E87D6AAFE6B8B8C06D66A4463AE93600D530DA0322586D01E12F5C74FAB208CBDA52F921EB30C62F55FADF53F4CEDEB7D30CB6CE9645B0B5DFF6A016817DC1A0B9A12154B313DA604A1782E264A7CDA600464E14F08122B89C70BB254A3AFD805DF6AF925B80B90DAC6E966ED6CC7A98E394E9DB81C61F193E548DCA9744FF2C8C81DA5D5BC0AD30A35E1684D9138C2A6D8E1F8B14E2CCA3BB71FB8DA85C236F454BFE35EDCE1862A11C69FF1F14C186F6C2F63C1FAF7797321AAB3777EDA7A7EAF43174C232DCEDDBC5E7EEC0C0310D3A4B47B0F058197283D24BEAE7A235DB0EC16BB48FC8EC970E3B7FAA4D21959F4460D0E69959B86D134D60D0AF83D660234F9A33818A12BA69CF9D26CBCB7919E58CC9B6F3AE8949FE0B3EAAD07FAAF72C192DCCB6C8F3A402CD9C7C79957FD02B97F49BB77C3136462DBAEF60E9E49EFD9B4CCDB85BB674B956F02DEB3714FA157AD108925BB171AF703780EC937AA00059052274AAF49239EDD76293B358B9A8D12F31F6936EFBC56D0C337CDBBE53E9849952C114A58EE46FB8F3E77606E33BD6B504A578AF9251A6F0CE4E2CFFFC2BC5A635C53742453C61ED0B3769CEBAEFAFA6A9C96EA7BA451792ECEF7F42C72B25E51403705119C704DAB75D5DAAC4B21315999615A1961D471DFE01149216985B70F02E132D25A2255BE21991F4B2805AE4AC23DF53331B00F8D04CDAF4C1524F66B24E4DE46923BF497B0DC5DF968599FD5DC785DB98A3C4F331CB143AE77DA7C56E8149469D97D11BB82E27B0F724B1D897540C60095947C5890F5AE59CF47454FDA7E5239DEC35C43E70CB852812CD8513EFAE586A59ECDB5DEAF12BDE5E64CD81F2786C1B28AB8CD81D5934157A72D84B7E819FAEED9490893FA0D57C8E2BE60FCCD08B6469F286EE86B1FF9B1F01AB12644E583DCF7ABB82D63C7F747B7BD6E92C3184C0B21A6B2485EC16E3CF56B8990A1F270CDA4A7B3AE107787EDEECCEBD2926A0A9BA57E25DFE80F926D6D144AE981F1F22BB1CEC9F5FB74A2D85D54AD0A36F89FDF74B529DA55C77E983C88675DCFEE789C2C61EF987E63C92B86610FB5145DDE6D4E8807A2345ED9E6B52891E4E44A527A91AD9FB737E821B7E4F5A43BC5D93308F87872E920D94D738783D8D6797FC89B7796472C74087E890330CFDD1DEB3FDE357B5B7C7352DEE21CED6565292F744D836CC10920F9BE5978A8D697F0E2C75BEED6D0A9EC750966E58DDD9600575FB4339804CFE7EA08BD193CBBDF30133EC8AE5BC6E17EE93890274420B0C641063B2C5F5932F805681691B445054A2F8B09AC6EA4CC3B5E70431B5CD65D2842D5772A6BE0CE1432A646E5856F3890E2E412C18D780D61BFBD6AB2A32C945B01BC326C01C6B53FC56778F871E306A501951D795AE5E70CEBB2D8229F31D71CAC228CECB77B7C1AE57806151A891D758043AFEEF3D57950CBDA51B46A57924930238E2C820A0B325AB02D3C7085CD63F080A4EE5E16DDB191BB3874DA801F5F14F37A734A943A73EC3B8C7D6CE0FE4AA1A4E33FFE069897658912E9CE9665EFCBB9E63BB6F019CDE82DE80AAB64FD3F0105898392C096CF7C88C2E757CD758A327ED6C524BE0B150F80AD1E6C5E098F6AD82BAA82862790EF3CD000B0D6001864474ED836A8A79BECC1D280D9B10C5693C8E0A35C2A475249F2D9829E17A302A191B210B21B72BCA020351FE64034082AD615DCED25ECDDCCBADBB997E4AC3F1E6EADD8BAA206101952BA02941526C4D41DE8142BE857BAF927F9006BDFE952E51630B19438BDCE494AB8A56FB2D32BD7C0B4FF7A258285A4DF89CFAA3D437A99CF0FF4FCA0D7E07E972B593E00FD56F5023697B3012EC2B79091B3850F48754A5CA1D643DFA20CB5542BE4CC0C88FACEFABA58D040154922EE6007EA84D022E31E58F9657C1CA5C5FAB27F30446E7538255842F3ABF57388DB45278323CC8C191642F8D1B5E97C0B173AC7DE5F2CCA4E8ACEE200981C2F5009968893A5820663C41F75FD5842F56B6657C60A44320D01877F5808703839A42A439A14D04B6E559E1CCA6D4713AC0A6B101368A87264582A9092544555AFF5FBACCFB1B1C4849525C90A5ED566C7F9DD2E6F1F47987ECEDF800000000000000000000000000000000000000040A0E171F241700000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 4 iteration(s) +mlen = 32 +msg = 0600000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 7C4DFF99F029BC8A43BFF5483F53E3D5233E2AE3358C21BCED17C6463459952F95C5D288E283382E9315EA212A2D6F8E809ABAE806404307BB784E1A9D40B9B42EB75DEDFE370D78FAEF47A77684FBB35DAF64E9CB154A8253B7A3249DF68687BEBB1EB5DD45FFFE3A2E05DCA8F315A3AA6AA1D2D9E7F2ADAA2A92A5DAD67EAC8F37CA3FA2F9C64C97222D786735CD06DDB9787A7DC7FD4026EF4C984186C7F695461AFA65F11CE018023155DA1B3D7C13EEB2DF0EBC697690295CB70B5C08D3AE431062337AD205CAB5FA85531639A0CD3D3DD03E503D36563638228375960E125168AC95870F9F40F4CF620E97FDAD9590935CF3ACB818E6C194829E6AA80AA19791DFB83F9F84B1AA98676B352E8105A425F2606ECA2B23FAF20231C00222C3DB547123C16F0C4E72EB1CB8BB3F411B882B2F552DA45C957805AAA752AD9DC24984214B527E398E088F729E1690FB7F6385455E3DA14E5939E85AD2A33225223972DB3303E1FD2EE5BF1E344688620F76319631A7CEC70A14AE8B41684F227D9D242C339584E3ED547414404E4A9EEE931C1FAFA16DC570A1A7C0B400B592AFE14511DA4F0CCA1F474333DD4F48B8A663450748571325956EECF5C6CFE984377055E39352F07D4A3A95A3A41AA5A220CC39283066FD4BB2696CDF1B71FE837B200CACBFBFFB06BCAD747619E6E5823D8683E7EF5F42C40B8FFF87D5F3D8882D595C192E7E941390CF0FFB1F5EA864CE27558229076BE5159067CA7BC6E46AF17F5270E79ADE6F615C5B25C8ACC461A26C7C6E30361654319FD54094F35EFC6F50F7A9D9CCEABF4260917EE95A191C0B95B3CC53317F60F57D151F8C767FBBF9358B3956734A1CE14463FF88255E5C735778ACA422A1E0266CC5A111611539E699A928AD2C67A53CED4635DC866F1921D4F15D40FFFCC599F2EEDEA3CCA120D7920BA4EA1D0F96FFB5C802497F020552446D319DE1D3B07FB396FCCAD4F24E1D602E2316F3EF658F0A8C465B8BEAAF7F8471CD3282A5D3D8AC8DB08193685F37706C43888C8F22B0A182B3B8297AA22ED5A9F464DA6195FB380861E40B837FD2DFA64D7AFFD8B61719921FEA3C883CFB9A8363D1374F19616AFDB36A94509486CFBE7566BF22D017B97FFC76671930B17C04F92869AC903EAF3F291D85B8460D612EE7B6078A09B958EE53017EDB9F14A8692BFD40E53C455D3295EF7D09231D0FA50CA6174E5C89497BBF3B3599C038A89DF8A9828A166ED3218F916B0B036F540CFA9AC4CCF7DE613F706060877A5EFC33F7C28F63F5782C582495BF7BC02C639B23F9279C695CB738670D9CC6381486C0428047FCFF70DF16389D8E50E15831713DBFDE8F87CCBB008DF71D3D883A1EA7B6A16DB49536F9B95373B93DD6636CBA0305FFF8217EABE9450C4E2098DFE09D5CB70FD9E9CB911D2DBE51B86B3ED4857821B5203DF5FE28D86056F152BC56F5FF8316A211E5CBC05C4B70DC68220E1BD8522404F1402571DC20B97808C707A0F88A582A18BDB3D29321291D3127D5D889E7ACD44FDF8DF4CDC503A974CADAED6A6129302359BE31CA7138D06BE2B36D0F7985B1E165E4FC92456E5BEA6F4422B918AC61F83416EEDFA88EA1D623654140265F9E8CD08FAB25A278231AC361A1F2E41C31FD99FA304E4EDD83752C424AA0FD0AAD2056CB1A5D8F323A75BF799B22C0AA2100A8A22C63B367AFE21BFB47FE09B8282B5D8B3200588E94318CA9ADBEFD1CCAD3E1B51B3D8136D8919B5DAF30D9A1C26B7F404877328D3BC75EB04F5086B1ADDFCC6FCA576D2F294C9AF5321032A40962B38D09483ACB1A297DA896C3B262E9FE2E1A01E4339BD9302A9E18B9C9738B5F6ED919890C019B71C88B00162EFF4E4BC0CC42202D20D7498013D1999B498537A06FAF3BFCE5F495B3B85B2CA59C3F308BCE13ED20080EC8FDE5051A0EDEE329A95EFA552D94AA93FD40B688974BE5AB661E9828CC9E98786C9CD2C93A65CA4F0BEB69893BF4195088C560A869038A060CAD4B2E75D459C984D73E7CC6286B00AA4CD3009BE25DA507D10FF6A2D9A8D9DA74D71A1070842DBE468E488B3CBD25C965ED5F3E8B8B4299B172B2A3759DC0E4B7298C4E410DB2C91FC459B3024967B1FF9419643580BE1C2A5265288A930DA874F67A93D34083489A440D28E461D5169B81B0C186E727B7BDDB008A9043322BF8E148407E52BFD3271489F687F81726E624744C3FDBF23E74362BE766E57C91B6884B3026B2715ED8B0409602CF7D41B0B193FA607231DC2475973B76BF7BAFFA103BB4D3202EA689DB064BD77E466167E3F8C44C82631A94CE7EC090D8BD7984DBC365549AF68331D5786C042DEFC40119C13709D93C08A146A1D53F967FF9AECD47B0873126DCEF4C9DDD7BD4413086C3AE64DAA9553119A0B0736D686E9B5462834094A7E74B49016B387BC189F2166AED154A646E59EA02ECB8D396B3DEDFC75236177AF79C943E81C8C2FE4891C2359D519F1F0A1BC6C28DF47C1765C5880CCEE8C46B2CC5FBA64E1714F0CEE54FB1F82CE5222CFE6A65F1220C70BC02383576644EAF94BA74BB0F2783FF3AFD6FB689B9B4A495B5F12701B70A86426F76C49F8378A7875308E0D3C929CA4A9AF40FCD75852BAF760529D232D38B4159EA276884CA06451C9A8A3B1FF64E72CD0FD170A1DF82B344DEC3B1D81F62BE5FF16E346F7707FD46032D0C39519C1EEC878293D2745C0198D25323B3A0F3420BAF2BA7F13D770430356230DCE3150A5BE083C95CB62D291153B15779B92B1E7DD2168D6D75743516E737B2DF6C6DCAF298631B437A99E040B79821816B7E7760B6744494EF192626D4143AED607194D62849950685454A3E802D4C1EBD70343CBF7250EB55F5C7DE9095A5A7265654CC9692FA914187D933DB141A6EB2CB8C3A74FC3A882F65F8E2684D0A280CF68A8B8B4BC09B30D0E83A45B8BD1B1039D145FA994730175D53711F99F8D28F833FA53E01E6613FB831763B10A393FA05856C07CC5500BDFD3A4385FD993B36060D11EAA5D0802513080A4268114FE21599AC1A484A69BAE1365D278608784DF96A0F6F0F2A3DAC459958118FFB80E2CE2D2E59DC0CC8826396444279E031B8A37F3B3B57E67207688D68D45E1D344B64172F66801407F1CF16190B359BA1B65987B726F752DA5378B28E6262ECDCAFE786FC9D73D9620111C20187BCCE5550DA1F82333333B8678D877E07367DBFB461FBE14B6C631EFAE7AAC1F930C6E19F9A24565D5C121157F999CC61261FBFEFA3875E9F7C7828552A9C816B293A93B44C4FC8BA4235523CF92EFEA01EFB6F71121A8D8AB051300268A5A15EE6CC8F67AF72FD033838C7316C7534521EB1FBF028EC0C5FC41D5F0347971ED1752FC9F2E8CCDE1E7249DF9A7386872A9B391969AA1A7E175AC0E2D67A8DD244A01EE5C1A9E28DBCBF93A0C570E3143D8FE42AD4958AD7C3F676ABA3629F57C3D73C96702D8D85A7E158D078E83A18FAE5E0A641AC36F83114BDFC4E3DEFD42F95F21402191BA0BC8264D3EABBD6C098368253D7B72B5939A3186B1CBE84184A69C3977D9E772EE1515FD39C70EC58E79033D457D04E18C61F660B35F869809C4334D8ECB524D1A5958AEC2330F3EA03FA9A40BA38195FDB7C87E41B36F3C1208103588155B51DA98B04D77A17AD6A4A34B9470030B4BA17B4D68E5766B10879327C1FCFB7B2C3AAE17C2E9E4EC4591FAC2C4EC655D57670B9D03999C39C003C94D888A33087DF8743DFF45FA6BD17816F08D6928903A0BECA9681C5B9B2DBC0B86C77A350438561B8089A5B89DB7323C680F167541DA4388B3032825AA01FE6B313FF3EA1EB950F3AE61DB339477BFFF17B02EDC3758281C21EF56EB0F119F9F766FAD84F00EEAD21481CD2CFFDDA423B6EF36DDA929E8BC202D83A26F7F2210523FAE9801449549E1A5408E4E67F71C5E4BA649AB92CA80E7405B374CFF399552BD67CB2E23AF1A523C82D1B59CC216F4FC145A7D37E3E93005F1E80F20DC6F1C28083EB9DF92C419691BF409127779AEB5EFF0BA751ECBC87A2E01A28BA7BE40518DA2CCB9BD64D7C1F4998246CE0FB821155ADD716CB735E85036D4C891A8387B0A6D4075D0931B4321E823393C69C66BAB4B7ECFC0B0BE3ACA9B9838DD104E6012EAACEC40295BCFD4BF014FA4B30C4E609138DE329A4AA6DB6C8FC8274DA94E2D4F120E4EB349ACB075337C07264465B0491EA1EF1D530EE93816253ABC0132500B573713C4399C8E3FDD7386CC736A2CA4E8ECF903EA13A2AE0929072CE3894F54103F1C1BD7F700E184AD61E2054F43BC18EAD24D1EE3DFC7D7D4B901B692107102115ED5AF19C94B5024A0BE4187B479D7A704D0EB6CEBCAAC1B4D9405D464AEC3147C0159E852EE41CF82887261D1DF5953EE611066A574FFC61F6B03601202C678ADAB494483CCB6694A26619B0AD7FDF3DE777D21E56CA9F00AAE7FB2E2045C9C2E7EE23787CC3FC6D08822B34224F77D5AB5AFA1226A18570827EAD6DCCB028974C33A5785CC3F611188FAF233B89FEBFACA4D7EB5AFDE7B5EEE064CD3B99F865392F6FBD6AF39B1A943F4B7094B3D7D9E5F61B4D9CACD9A5B2B438618192BA0724C8D4D7FE00000000000000000000000000000000000000000000000000020B1013181E0600000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 5 iteration(s) +mlen = 32 +msg = 0C00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 5957630F7C1E2CF91EB85656AFF138A7D6627D1C59392D5C516219D3D2FD910E226BA8FC718B148905489D47413B3BDF6972A2395CA215A37D384B4DDF51F394C53FBDF10D8BEE17811D6E43A2B8D4030D402A7A10B5CCE9843C4814D6FEE3CC9F8914C532C8BC5866D0F16EFC8E521C367DC8AF5F7196A933325D5220972B5C2B466D87010B85F38EA29DBAB50689149EF09E90BD5E0F988F965770F75C27D075AC980B0D8B1381131E536F76182AB9B755622D176C365647E2FBD71707BD286BE33EC48E340632539CB5D318B2E40C2A941D4738A40BDC5D2743A8FAB723F464E49B601D76413187429DA0430910FB7668F1C79FD0C02BEA63040507B5A497A65B654820C1E647AC708F4AC8CDA1ADFA5EE28A944BAD5A992A79C737086EC03DCD66AFB04E622E0EFAF59141BF4D5E626E437C429E843CDE7A287222A02647C1856AEC463996D28EC95697C5461728A1B06FC7743917D7219C04C6D8B0F8B8AAA1B02A82350DA7E1F2958E0B5C0B096F459A55F37C6EBD412B5CB08E6ECE7AE3467BDC142CAE85FE3D065D2BBDFECB5191966457D02BB1DEF1A7E373C36696D28421FB769CE29858E329F1F66C4B130A31CA8BA94EA145DCEAD22C2C56E9F7E4106EA977B532E1A7A9D55D43E9C5208EF3EAF170E63905BC6D030298771AAEF8529C672FBBD68702F6C1BCC7B37C884615E4394D05E38D34E885EB12176C6C33AF56FE89C8EA75A50CB343C35EB0EACBF759A973B0F65A054488DE0A73F6DB2D1E1CF0AE9C6F8EE44D7416E5A42EA6F582927B91A8510CA7C3E0044B4E9E665423C1FA079076780CE663AA8AD8419C3CC2D7951AEB4A4658D6E74D16543BA82DC86346469736344A512E304A54ED6A026933AC95E2CAAD31DE54E196F21B9A7CE8572CC9F35EFCBD678AB7F3E9DB9BF505B798331464CA6DC6302B41C8C0B757AEF052EACC2646F0FF0DCFA6D915B3D066A14BB1E439DD7A68A7BA0980924666ABE8E95D4153015627C5637EFC81F97CB527FAD1EB65EC623A713266E655CE24F5625A5CEAE8004887A4EF127832BB89A6E95A8A8489EF56AED8FE51777D46C883A1CBDD2D45AC6751F410217D511D9C96851199B4F1075BF836EC3751AA13478562FFB8369176F14B7507D6BAC3DC81378D9E94A861D19805C09E7D95401503566EAB2487E69C3F9852298403A92D4C1522FB08E2C972918BA5E319F8D1E7FDAB7B76380148E902138BD99866BABC15F81EBFE5C11A2B8CBF306FAEDE35D02D7553588AD37168AEA5A046FE59AE78EC8523E2BE594D9C7D5B4605B23B58617AB691E7ACAC66F27DA0D17524FF04D7B533634F68290F83F35EB15ACE70BFF19B347F7DCE405AB39EBDBA8022DEEB66C4FB10D16C551FD0F8FF9AFF94CDC1DD9E1D282C2E2427DA2BD1BCCE7E0A7BAE958A69E9490AAF7C88313A67424AC98D59377856F6AB8EC7E397616E8F51E86F852AE88E9915A0C5B0AD5E57E778DB7FDE223ED85E53743AC644D39C726BF8466472CC2C900D130A8D0B46B6C400AF2446046E83651C0F86CDB8B96A8ECE9BEF26184D920B35179A033C40F94A00977B24A37CE2FEA80EA4679D975F44C918470EC9A742414905E34B49487753F04E66589955B6EFC660D91D3525AC72F750EB4E0C0EAA841830EA20B9EBA7F43AFCCE8DE1A82C37846FE08657875A612D00B9F6F58F1C07B5253D86F83966517CF2DCE9CCF4D1CE3FC0B9AEAFBC73D92E7EE4EB92517CD65820116B2DE4BA4ED54E117E635CA80C68984CC8C6A8D5FD2E4F588F5ABEAE6227D3DC0B1355838788306C71DA6CE90021DEB333CD37B51BD4D0328DE175B3850D6F33DF7DFCE1CD15BB0FE5BB251BD92FC3018CDCF86E9A2827DBA1D45CFD2DFAA210916485E5C2662FDF801FE8489FEE76ADE3B0CE6BE6414F5AC89B64BC797902C344BC5AB09EEF3CBF92504F361EA3AA2BDF1D9D1CC694DA990AE1F4FD961333FB5D6AD724C712BB6F216D337BA6130F40FC8AF64C43E51F4674A7750BE251D48D54E14B81322D655D47D9A60DC14B0B4D5FEFEBBCC3FD54EA6EDC89CC05112ACE53E0CF7762CF58134CFBC02E288468379106954A7F427ADE2230CF80EE385D304AC6991D63443CECA1A957C6CD1CDA5B65F4538D0418F054128B446C54FBF549A8AB2989AD8BD4A2274D08E155BC179BA90E75960DF884A01CBE8F52D95625B31AD4FE7EB09C552CDE89913E16F1524B1E2CD071EDEB6318FCB145F08F68BD5A8B7E270BE7D036109418C605AE7DA18832E7224926D41ED282146DDADB38E11483E9919BA9930564F96676ABC213DA990F30F46158C101A89114DDF43C1844F39B674866C824BAA440DD4857BEE3FACEEC67BD0A62A12CE10161C0D4F2D7A900D33DAD9EE0287ECE2485664B96A83B96B61C1FA2699C603660DE49A34F2DBD7C4C01E83CF4B0E1990221D6E242BF3B8971D4B0E04182585295F7521463C335DF24A6DCEC3456F721D44261A86B082EC1FD8232AE7A6510E086684EA01A8A6A0CFBC6DEEFAC67F45E8A6B6F2DE045B2FA4498884462ADC991E40755F6D845EAE3523B218513E4BF0E071308FC78043ABAD2F357BDC75F7E551A403E39987DF2AC1F8668A0B75220C3D55763B08F968A06456641430F13559EFF3AEDC6FCFED436B9F85C799E8F94D7C90DBB5403A660B2C830B630876EAEEF80BBCF81CDF769CB9024D0E4657308D806C10F8A1BEC1DA5C74799EB7BD31BA732F0788684EF66882461200EA5454A0E5A564150355A468F2CCC6FB67BB948ED4540709A0C79562AF61BBB88C79A54E5001C168BEFF2F34CCAF684E46FCAD2B434F55A60BD0BBA8AE2A894FA8111D6469B6EFBE8FA7537AA29D8907CA23E06FF5BCFC29958B288556932FC820F91DE7E7A8A5D5A3A2C1E4254B647A82FC17661688DDBB7A518BB3774B777AAE991E72DD60CD47885CDDBD944D14BE13BEEB5C714CBF57347A224AF71E95C26552159EE9D1A04EF09D167EE33564A4764ED53A08D05FD40AB57039C9BC2A3A6E1511811B7C2020755E1D889F552A5912162B729D5617C6ACFD6A5CA7BFAA336E727C13ECA15D5ABEDBA1FAFA451C5AF1747409EC8E6CD2FD4C7E4CFEC6235170CFE181262E1922D23AA2413B51C2BC848434D47955AD1BF19B58F7B27E2D38231928C72DDE3F79420289060E48D988C96DD410455E4EDC60A5CF78D57DD4769469FBFDE9713A7DED6D1B735AC8161555BF97A671DC350FDED988731487EA9C13ABBCDB0D22F9BF15D543F4B7C1F72DB9FDFB4ED2ED414DE9349EDDA54D478EA1DA24649C919424612002DD983105D9B7870F0B250964122051F0028229BD6F0877AF38FC73A27E8E876B1A758612EEE3BF94FAAEEFAB2247F1ABACE705A3C587A260BBA88B66A3ED189D089638EF0F55B81D34680A0620293B39C53228D8D80F4B184B628EFFBCC3E4E602037984D266D6767BE2CCE6709751642A2821B86F57FCD9EC3C0CB5DBD15ADB43A48C5F5EFD8419AC6F2606E836E39CC3D99E07562332EBEA08D869FA7289D490590DB83E22C5D3D36FCB8DBF6352A799661E358728359CE5C8E1C580FCF24A91FE91E48DE5555CF7B13AA9FEF7A3748225A545F17072B1739E33EDAF4971A320E13056EC1DF53E1F14A9180CAC5A0CA827C8B140B20BE51A6CC1D5907C5D2E579E97C8DC38653987BCD69440C6A5D4ED53E21154E03DA52AF3E1C377D1BF32B0CC45C96C96C3D6DDD4472F237C576BF63943E9BC365FB30CC2D5D0556DCCB8EAC3335284F514BE897E62FD78D1C9ED301AFAF026D1F257BCED72E52946A76B5C5BA8231E13E34DC598E26D3366B73D11550DF1E5F78B45B250443F4FC38230F5883E19241C761C1B371A45E0D010906BD8925FB3A62E80BF9618CD0D0D1B5E2F9B75470B2D7C3819BDE2AD4CBC796CB97DD90E5145F20E6524E0FC68A23A7488E86D9730A0A95FDD73559B15C0106DD6692B85834ABF5ADE250B994F74F5C789F329F8BEF8808DCEF76D11AC5ACEC3A26BA7BAC871198668186E333EF2B3194662BB40056925E756C9C15DBD80FD7089AA43BC91D90ADAAE64C2E23854878E7BBBCA12F870B9A72461FE331DCC5423588BE2FCF5DF20BCDFD9B771AD3DBACB3119C28E67D461C7E1543572F22F285AE3BBC2131732D2949512E622E688C6FB6224D0E358124FF6B6E2280501180903425F17EB2891BB6D63441D23EA433DED94E0929CB3B9C9B601A7C409A36D97862B545903C7CD6752B3D0CBC578042673E4B52510D040509A6F06AEA689FB624EBCF0CB13E8854E024B82F8AA624A161F6A697D11E159334EB46058D591832BA9E7CA4695523CE4026D560B86A06DF6960EC0821F428709CD4062BDF81BCFDC5AA0E49671E741EE9E032886C2180DE9B5723F08E5EF343E4A76F86C8096CF0D73C166EF584DB07DCF3BFF8C8F68CCF4188B80ED2B4F8127525B260F86B8B3E8518276055604F754B51B6D7C01CEE266FF32D2136772BDDD8AEA1EDA2AC41252F728B6121572F8F2178D09FE0D651489696DF53954C291A8324E704A5BCD74AC0B29004242F4E2270E408D6251011B7FC3F03C8680CF633A798AE3B7898DADF1A425A6D8EB1E3F7469294F601072761868FA1B7C7131F23374DAED4364E86A7CAF2F5000000000000000000000000000000050D111A21280C00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 6 iteration(s) +mlen = 32 +msg = 0100000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = E1412C0A8930EBD5BE73CFF29B68C3AD7426551E499553D7CAB9B65A984CDA37D793CFA5011EF4470DC57BF0C7D1C25449CD23C82868180997EF617A42D425CC5E1DCB6127D3B60E017A9AE1AC7DFE980DEBB098F6099D4A5D497B0EA1A063F863D484A697F9E4B87652249301455276EAEAAE6E5B9C32991BB3A247F5EB6A64049C317A2E262BC9FBEBAA53E1203D780AACDF8D8C1DF9D104DB25002257CFE39C49E88EE0ADAC298199EE0285AAB5966C4DECCCDD64FF86A76DA9FCB17765C10CE7EE8272595B0DECCC58C8D89D11B78E56A4CC63B19D7D787988256A277B53BA7D99C1930BBF1CD550ACF5C97F6F1B1BBDC6A9CD0C3BE66672724E9ACD89240987B0B17F9BB38B8B323E21B7DF3A056B85CC41288D34707DDC050B8484598EDE78EA295774222EF491F0D621509C9361B7C8537A4904E2E5ED1640968FA6DFCD828C8BA6E771F970ACA894F0D57CD03CE325F4C3176B818F42F29C8646948B58796542DA63FFC905171129418A349C0783EBF5AE14B3FEE69492293AD3894345F07EDDAC036C40AD5215D4827DE6A0EA0B4BD2DD86826C7F5C340FD2D62062A41C075259A9ECB3ACE3722D3768D5A7D355373E3DE4D6F87A408E5BDE672F414826A2C6714A706198723D6E41FEB39302B155F775BDD01B7CB4925B75AA1D0A0D533A2FBDABF68D03592DE2B24A39D2D093FEA87CA57E16622E59B46988D7057540A511506C1E7C819D8697564E161FB221DE02DB05B8715D7E8CB81B96BF41B257FE6C5DBD8AB7E4B6CDE8A7E15077B3318C7D6B7C301C0EF33CF1F1C65668CE0106A259A599A4034010F5809FA7E781665D866DEC4A5BE77E8CD090A324FBD25CC07929B773CD8358D666ED767DB22D540829F4BC09C3A60448A23EE40E09EC699C784649331563EB114EC47C8F1731DB50761DDD7C972553E9819DB31148FB97D3B4C9FBB89AF7E87033536455F9FEFDF8566B6EB0100040ECD080287DA76A7791CB90AF6253E701D9705AF96B3597596AA58B9B0FDD7689ECA35A7AA7C21B71BD80C3921449D3C5C8D9A26BD386B5C4002C8050B6C7F2489BEE49B18BA85652D4B528BEB21F35C4C9AB1F5E7F5FA4098B2D470BE2CDA7087C61C4F40E771AC04193DED1C45B0AD787BE20ACF7C9393671C354DD70E93618BCF89F684C9FB7C8FCBD004B737A65350E912A1945FA6F6F082406526F8B8B4603E171B754A3F571B7933E07BC9971ED2C299C4BBB4293B3282E34FC1244AD5C4C985ACD31D4F2EB5B82E5B5E1F00C9BE628E0A317885AB6E26AA7667C73C12F541CDF463CD72798CB1F7908D2945A131CA8AC4BA6343BC4FCF7DCA98F30B0FEADE3F0841EE280DA51D9501B5CEAFCCDB8319F9B32DF23E74A12B4B61C44B3005EE58160C85302C141DBD6FE0D598B2886824B1BDADC874C530DF612FE5260E996C6D289A2A5F3F811F2B50CAC599477F9D8400298981654013858E4ADF2B6A67DAF24A5099E9A44F5DFC37B2DAFC4AA738D4690F9650F019583EAAEDDF32BA74C3468863CFD565D06FB26601EA919B68985F5B7F036B2EF1B7B0F6A738E292BE4B263D30EA5D9784221C09DD6BD77F26DAA6996BCE002783305E478CC1CAC235DA49057DA7F9CF7B8E25AE6FB02A46AD93EBC5D9440BDD07018AE26DE5C51C87556AD561F3C7E130A24685F3FB9E39518C1E9D26C5BE936CF3F9F08C464FD0A32502604A349C8956541D94CC0F11BD5A0733737FD75ECF57678264E63CE8B5323A0630A40CD6032D62ED84951427A5162AC1685F8682EE7D31621F6A77ADE12ACDE5634BC44B21A2E1CAFE4A689E0D30AC3D03A6903F75393BE77FED6BE1F970A4BD7F2E666721E271E155223C03C7068E4D9B348159ED8B09D14DF65F4D86AE612CE3A931FC4A66C60DA424D5C2CDA9FBD7115B771E3262AC7788C70F6C0241DED2B9DC0D936E613C795F69D65539FE00AE8E7EFDF07BC068EA4BB9BD83F5A64E970BAE105036435BCFB23934DC13027ECFE3DFB7A1E9D3F7B2B07DBA844598D4CF53D39FCE8C0485B8EEE92671CE8ED10B262E63944A1EE4889494917FA81E01B145B17FCBBD079E8574DF474362FEF1F48EAC5B8A443973B75E72330EB03E15DECFB18F69D10343F2DAF0CCECA3436C20612091E3BA0940DD3A5D5489338578E0E90F3795A7380D577A67E52ADF7358F2E7AAACC75BBB81537134A12771C1539AD42307BB2C1A5277C123F10B74216CCE836E78D24DC3AD7E794BFDBA4D0306A519CB122E3B2D5A6769EF54636F4398E87BD42B0E6229DD7F430F5C6BD610F9C67C68F1F7A687B98C2E5A61CE50C9989A8DE3F53C975BB75B97CCDEB3E0FB7C26F368B29DF709F18193B9BE27FEC820136D8BBB9A037C13B03E8FFE2484D948A284D505916EE424414C5DAF57514FDE0A84665B2C31E2D4C8FDE45BFDB2CA08E9974EA9449C5F332CDDCAA46140F08DEEB3F0B4BDA7BE04446239C7AF4949FAB33B40DBA8FEED31D45F85507FC232FDAD3C85595643B4A7F2503C4BFC4B3C55D969AF6AC80A3C02AF1F5BEBD23A66700733B36F133951193A1FCE5D429B6200FDAF383798A1D11F3CD6536D3F9D27B58A5388482279F925A8EC2850DB90F5F70650B0045B4002B952C36B460A5B566FD3BA2BF5BCDBA0378C54AC9C12CCB46C7FE110AA99DBAE10D5CEFAB484A3ABBD517DB89C71D60ED26FEE9D55E73BD4CE16D898BA426A683B842885B514370F6D854321E599E24EDEC6C3A0DB6F73C60BB36433EC58E162D6FFE8BBF2D345421341EC22E1D25FC740EC4D3D78B79484387A9207B9B48EC8585FB9F6BB4F776BF71FE7834D95BF4C6312D430EB79877FC71EA67EC4080C359D4C4901596E93EDF71C6B3AE2EDD5D491DEA03186BD3FB24527E7F99C708FBA19D606CC44EC5E1FFAA33CD2710CEBF4D4B5869230B151CA8472D35A49CDA5367098CF3AD4DDAF1838E77476108EAD4C399938FF0CBDCD226B6F06D5323C3D885FF1B043E6A32CDE2E052C7D5C273B5354EB020A81D4F9BBA9FD29A5148359750EC9CEB6AA9906047F1FE4191D07A0B018DF93BFCD96FF4AF3BEEC9C5E5EB5884B32BC84F66570B9B57F506443FF634056B504871E4B75CC1BEA1EBC8A9D5D07C9EA587B70EEA92B93F65C3194B343CBFDC28D1A76DAF95303C9C4EC0034FCA333628720BDDA7A3373D676E2928C08684E9D24EED7D9382AAE547CAD5837D6E1BE3E7245E947053EE2219D39E33218D9AE52F6B5EB487B0E5B16AC35FFFC45AC1D832DF711CB11B2A887647BC2C3713945F92103F3EE2A52AD946B0D38BC0BD92E701C7E7D4AEA25E6AA4FF2A42CCBF5DA9BB99F88351076AF1FB4E7CAA65DC23A78372E1C2FA09BA8D46152CDA3ECC8A9288598BED37E4D11507E6B5E239F377D1DC5AFAC7FB38FFBB7B2D4ABC6BD74771923AE17CDE020B34151D2555FDC1C09848196DAAB35745D88B80A79CE2BC86BFE7397EDBD9F16188A133B2900FEDB915629B3104DD6F00CD1403F8A62F71756D614C0224276594D4FB74891D1A2F93F43157B0A6A4135DD65FE25D227BE62AFE953667147FE7D3D486BC6D5436B218FB9AD0C6DF31CE8FCAFE01B81561E02AD5D34A0B669345A74AE16F651FAE91365960DC687B5738D98817B10EA8197FB807C59A47EB187BCD2E4E873BACCE97E70DDCBA6B4189A57FDF7D6F8B62A0FF3D81348DB2B8B35AD55D9CF67F668BB89D448A751B02071D1CF812027EDE8658D51BECAC34BE3EEA1DBF31E6177509C81F5E3A373FE9E2AF88282EC5BAB7D00C1325C6A305BB0E2B47989EF26AA3CEFE6A3F6E7CE5873F215DABF22C17E5E6FB210DA4F5B5F576B0800AE1D282A5D897B6164D3A32C5D0AA176DF03A6C1D2850CEBD40F5D97EE707EC307B13538FC3A0C83A95FF0EA2E5470E1B682ED12F9E65F366C45775A9365BF74729DAFF7FC0E9BB4C05A53BFCCE1B14CFAD49647ADFAFAA0059707D4D72C133E5EC878E9887B41656CBEBF749F9E19C3E9C4F464A67354A6212F43D15AF01A762D8C7445F7FF27CF835E1CE11C844E488036838FD7254AA6C2CDB858B7FEDF7852A90A8AC7FE2504DFDC1EEA60F64A671DEE39E72332E407637033A9146CE243950D4C3D07C17BFE22D9A191FF01315FD51653CDBB316E833C823EB459987AAC7E3D6FB50BDEE54652AB253CB9DF0A661BE1B5AE2A7E9EA429D7E8A5BBFE7683A2DF259CF2F0221CE0C2FEB06C117002D101921FB54E06CCADD05DE9353E5874C2B67B45571A83E2967BE45E77AD2336B076088B33F33F024185979EB36D57ABBE493D84C7F7DAEE3B10E039339CFF06CF36DDBB04ABD0FB8C8DDDEF0F7E86F9724644D6654D4FFFACA74F21F242A9722ADBEF84B44C9A1B7B815EA0317DC5CF688F57896C57AF47F44B1AED5C92853A7EB1138A125C026C9E73770D982A0A25785CD91A4F315D03DEFCA59A2D3CB3C015DE5DF285B53A455087D46109582854BEDFC301B9EA9D87D4A04A2F9650B8D9A83B6885FC52CD32EEEE85E740873330E29885C8BE8BC9D657E612A87EB3969CD24950C9A8945844BFFA33396876B885550860721DECE6AFB92F1D87707BBEF2A34915657168C8FA2E3050F1029355F7E969FABD2EC252694A5BED8E0E6FA4E8B91D7294666737D80D3E2F51B1C65B8E5000000000000000000000005111A1E272C0100000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 7 iteration(s) +mlen = 32 +msg = 1600000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 4F7C826C9AC53F6D972C7CABE6749F3E045F1A718C31F1D860283A9CA33F12A2CD9255E55228C637FAC5B89F39226C235956825C853E63A0370B5B6A1E531479D190F7F122D070142A664C1A14B7E7498E413ACF0F1215A64F629E67ABC94F76EC3687EDA08A1B1F3140227C6DC3EC0A83DA6D409B37618B04C961C22446EC81660F6F15DD2AD86B47B0AA3652E58CA9EF362FEED608343178337F20E4DEE23620C99E3ED4D8DF087462DB45A2845CA1FA4B732D17345A8BEB9DAC372F0DC399398D4C40FCB898FABB85D0DCF3CDD24E8A222B5D4DB8945774DD061DD479F4FA143A524A6554A4253B5801F7C4BADA4A50E5F71BF436277BC3E039C6A17F6AA4BC2B24CF84976438E5DEE8BEA760D13CE70F1B9299483E10509C9B4944011EF0A60EE29C6222399CEC1AC30F5A75C14FA654BAD1FE8B9D554F912F8B8B4A7CDD5D01B5CAEB95D5816A7E4DAFA42B9FA5CF1806E6FD8330A04ACFB88EA8D1244365F4EAE72585A17D06EEF04DC7B0A9CF75FDD251BF72445250D94DDDCD6C2890C4783D3DBE6CE5F062638B260F1777C46EED801C9FC5B9ED8C152D858707520E0FD4C7930A3CC6DF555C6495671FDB0E27AB1C414272F6C10107146F5D8244237A4AD939F72957F1311483838CF443C1DE48EE754BE77A267995C2EEE3EE8CC46A75723B9F8BE0A16BF8A78F097196E094F8FD9E06506DCB82E10A03E8CA0EC6F363816C3F095E7ABFA64043C6944E03F58CD478A65865BD706D4F3CFCC5D221822E728FF9C4180541AF9E1BEC0ED5803EFF2AB27C008A22AE991B1FA6413B6B6AD0F2AC94975FAD9D406CA77575FF3C02CA6916F13092BE92B43088CA1D808606FE44E7DB9F7151F83C423DD3C172F15BC635B44952C7573B592B2AFC3E59F837BADFACDFBB7DF61F784AA6142CD9118BE1347680DB435213BD9CFAEA1A128FE546E19E022C25CFDE56793B3EFF610783926B3EC2871CA1542784518C0056041FC18F604ADE4B0B56EDF2FD0652CB3577949EBF9CD02017F05730FDC741F267A8D03FFB41C02280A7DDC1DA0C0C0B85F47F6968627BBB9A7ADBEB36620F52F00BA2C772F256E20311643FEE4C32CA079C81B46CF4E61B3E9766758CA0A87FAA3F55328314006961DFB1A02773C363982EE84937668B98D98841C4DA6B4935A6CA15003716F7C372A8AE78C29BD79AF078E4CE9A18C9CDC19F313470DD6CD2E0EE931B29422C5A2A4654AAD8879E35FC1F2BCD9811E128661F7C40E7784DBD3AE2A80772519A3A30C40852C7864A4E79D4861C6B5E27F09319970DC24211EC9B4C8E16C0A90E3EFBB8A6105EC20761995592D85641C09EAE0F98318A30B47E2A91DBE8F506A3D0B4BD8700462F92AF214E0255AD7C85359D9EA046991057A5974311E94E0C5756344819743D40C91510BA540C7DFE2256EF8ED316C928D7E817ADA81B0F798FEC0B47E53776C46A1D58B56D95402F10CFEC2A741B9EEAE635898C8B2AC60F9660BBBA2E02377B294E0E7DE4426E402D5C8DE978A11B42AA123EEF24D6E5A98F82B49733EEFD74CA677D15FB6A1B7206F1D8597B1F2A692FEB244D7ECCAB6A9700A70CD8511704D1C469C6725B59417A8C25D90906222712461E9CD0E9A274AA609C511F6D6265C3AEC5CFFEC419266DED863B9A596934F8787E950810C648341374A33BBF2B16809597ABE0D99283F16BEDC855A95111BCB7DDB2899DA912DBB35248B567292ADC76CDC9EA09C44134A98ED555271D24798AE270B91265687D37275D5F400A3329DF5D5491FAAF7A9232C74A06D065D0F7B3FA3BDFF51E0A1A3FA8F2EF2E689A8AD260722D0ECAD61DFE6AB3E8BB8A810CB81ABC3E4AAA2D85E67FE5E7BF8AB1A2A0F70B1CCD50908A8E87017989CF8B4B928BF2E9F2686B05C1562C0F762A6DCEB3C72584823CCFDA18F42F9997E6C1758B5B3061FB757B4EFCD6DF14DCC469F4A1A0BEBC7456DEBE613A732D578420F0EACEC760B56A37AC7A2E7E7AD2DDCEC761A13812D3D688CA4D0CFBECCCA16BC0B01E6D348D42C10E834ADD48B53E910BE11E16E4A40CD6CD15E663C6433F699E060ECB7FFB17CECD8CE20E8EC4C216305470ADFBB4EC88710E6C051A3AF5FF75354BE0F8A192CF22E212446F561DB3A3FEEA12A70291283E42C15978CD919335EC2E07EB2F716855D7BB78ECB4EA0A655F66C16BB92447AF488BABA080259E68EF8A3EDDCB81BDE0473CAC96EFC887BE27017825852ADC1475CE4D17A51F50F74D2876134722679FFD5C59AFBED5FE43417A86F09A1BDD87331CC5B7A9B96A2395C66B5BF3FF17E6B9FDFDECE2A8A1A465C726FC9043153110B3CF6A3C9048081783E62C1BC6D3F8FE5AFA3908F9007A0DB29B539A4E5E83F811AA2B13BACD1612C0EFBA98935698A727843A618B13A08E275F2A1F4502A0EEA7F4BD369390304FBC5009ACFD6141631102E8401048431F6B6EE078A9A750A29821AC41EF6267581DAB60533E443B0444D87425B7E2F0DB338D5C1D21391068D7C32A0B5C9F93FA6B138DBB47623FE8A1063DBA1E7E993A6D8A097B4644FD394FE36E58D2715456974619872A1B4FA9EAEA4823FE7A456AEA64411554A1923B2BF9FCCC6BDBD1E07D469E24771740D79C5BFE17565C281D5725EE7AB587D1181FC2AAA4CE62A018A61274737A2C0E59FEFAA7FC32F1AE9CF40C82CE75C1EE88A4238ADE693E7CBE902A575F8E0A12D5239331863103FE09906C2E80E744A8B2DF74DDF78E745410786920A2F349F62346EA86BCF663123B16846526B9081718B422502653894E04EB13967444665D3B0424CEFB7D6D30DB4E84CB887CCA1C8251C01314EFF24687E10001DB87F37E19C8112BFD31BCF77A38D846BD11A869383D32F87FBD18877AD7B47B557C213075B7B66BB55460423E0219D14AFFC639D7032C51F1EDF8AD7559F817716971CADF47362734169E35F1D899A4DEAF03132E8408179F0657E31734C92D6447DDC740B5B55C4D1C5D354A80FD6234F049268341552AA79F6F37DA01745BF9CDFC8B28192BC0D0BAB1D722AD325B6C2FA52CF1A01713BEF7E7C428449F0AC7F258870CAC215BC471448B47DB93759A53124AFCD92A0BB9B48B86FD65B1C575221137000608620C4DB6A0812B7D9E632849E554446BB1794DFE1259E6688EBF02E4470F0E818B21F1FB6646F4CF2A3107089BBE231BD59F8322ABB0045CF3D0F558BC91A07C91CF77C917140E0FDD926C22A85A3487180D7B3CCDC43A58CCAD777E72BCD7DA338B6A486D0853A305A0DFE027C8E98BB7421CC3F84D50BFB0FCA0496BC012EC95D06661D548B97B47741BA9C6B66866E00FBE15DB52D5CF968163066A54733E1C62859969CE33AC9606CE6E6C2CC38405A75AF34EECE3EEA4874D7FFB42B55635FFE3CB5C383E6C3CF9E1BF30ED5BD4FB16DCD77EAA08CD5F34B0403BC97F3CCE09AD04FE0D5DD5A033CF008BA1111744AB06D941D177FB3C24D8A86104DB2E06D5FD85772C083BF6B838F6AD63D1F1025C4DEB2ECB931928D66FD82C970F5692854D87B9DE5A82D3FD726E300B95ABD03D466E55080CD97A5CB12FF69C2B7764FA1CCB48A35D1DA8BB18AE4FDA44E43555ED3DF57F30796EB4A13C1842BFFF6CAF9498B2E423FC743CF16C9F7C6E19AFCE9D3A2DD634900A51A06FC2EADD8FB6E816F74FFF53246624A28111EF764DA214CE1ED7A1FDF356C7E319296A0FE1DB5A4A16CAAFF06755FA5CCD5A669311545A946028806A75DCA6346028C5AA2A6A10E5FDCD7532E84BA3B5935EFE175837249A35CAB8C0E3284DAF987D1CB68383DC1D4F58875EE1709054859A7FA46DDA6BD0F04F35A0E4820760EDADC69FBCECAC8E449B0D9DAF4519D957D5595B3E7D824AF80A3488F6DE3FCC757E68937FEDF4F4DC267A6F0E3237F254C6A62FEC3759F4A08A0509FCA56768FC80550A798A55104C9B0AD9371595A4A5C5B00E13274828946EA4CF47F146DF6161FB961C1B9DC5ADBC66B993C0B436CDCB2BB98D6B3BA56CDC2E4E7FFD18AE54C42063EFFBEC222F40AD313619D4FA2464F99EEDBEDB5FD7EED24BB655AD997E4052C2C5656691C85701FD4E66C40ADFE4C9AB502DA176193060330010B0A2FC558F645593CA792EADEF21560A19BA0609FA27F1278CB6C9556392CC1322003269972ABB48E3D3F13EDF75ED2D27D696AFD56C6910C55F1E103B20B3A1EAF7E8B34A3CD6179EC003F6D243253AFF072DA6992E755D17C1F8F85306F18780EB66C17A280B290B420C18498A1F8227FA8909909FE98DB84FF9E6066728F90D08A0ECDE373F7A10CAC1911014420EF787FE1C6672A6C44AC3C67A55AD64E702DEC536102FB26586F13A6F2C7B26F53AA7E1B67EE8218B7131B738521C53BB9E32B513768B5073E50C450AB839649369FC1354AFE13DA4EEBB0E30FFCB622BC837AE21FCA627E7546755C9034F1DC4B5221A229738AD5EE45128AF12EEBB3B28A22C0ADD29A46B07ADD683BD299D542EC6B9B45632C73D07799EE4569250E1DA500A45AAF6F92F06C2CE245F2D77F4B0680DD69562A44FAD935EC7AF5F642D6C8534CC5031310A5361BC8210486D71899CD60382E92577BDBE293D484C50607895B6D40235E5F1F2378C9CD0DCE90000000000000000000000000000000000000000000005080C161B211600000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 8 iteration(s) +mlen = 32 +msg = 0800000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 464A36DE67F458E0BFB24C3988B420700B2FC79C11EBCD8DC15F3AE7C4BD88D939C4D450C2E69B8CDE439DD8F31023472F95BF20077DCF6CD357361162917C73D6756D22FAA92BD22DE95E303D089C5F5BEBDB35EC518338824C46D9421FF69FFD586B99AC3EFD76A9F92B4AFE3330AD81F04D2AA3E335488D1516B4F8588786FF9B47EA3C43082A67EAA7338DBA529CA69A3C2CC9D039FB9C7AB2356D7D47912AEFA904557BE7AD21DCC2C5D5EC1B7DC6FE29C3B466997E9082FF5B76C758F677A71802816CCAE8CF422D5E26C3EA5FAB1AFCC7721AC5F36DFC1E918945FFBF8590AC4FDA8CB7BAC27F42BD75960A8BE558AFF04362700BC13EC5A14165C1E2FD1E935ABC7634BE683A1FA006B161C489DACB3B87304C8E16C6BC3B198D178AEF455E5B3D94B1B1C8D1574E4369C7587DD811EA19456D4FF8C3525F4109093A028C94242F7888F1D0F37EDA92FD4324AB20221171E2F092E6351790349B6757AC3190992018A4B3B82B65282AEE78A8956EFC70B99DAAA2F7CBE58ECC1BD9DFFFE966AC7B1C0F2EE072187C0F55306BC40E46C2890DCEDEAE6F7916043F048CEAFCCD28032E3F8D687D20198BBA7D3744473B3AFCA295284BABF1AE006BD143AEB7212A425228CAEB19F87D7BBE235212EAF0690D536D30F4D5BD1216187A2FD812EBEB888A15A5E8B772F7F22020A086B3108679BD7041C7CBA5FE5BE8920578A9A4EF06E3D63A382A1A089AC66F39E715A7CF68B03538A45433F61546FB5F3B3D329F6891D2449D74C7601B988C4053B70E5D2C6432FCB60319DEAEDF0CABD72489940ABAF67886D90C8C5E22B2C2B0FFFFD043775BB91CCF9381C8C1915F48AADE11606FB5E6E6F102FA10C2243292BB9567C1F0FB8496140F72B7D8A3BB30C10666298B7AE8384ED079BE583C012FF54E6A1BD22EA8F528005612AA176FCEEA77BFFAA3443E7ACC537666574922078B5BD3227763B9CEB295D7024E95518590F566129773BFA8371825CE68ACA58D76BAA364DBE51C184681D7A6450C4442DA1D5F943E97332F74031B7326C6E52ED8DE535DA46F6E33D2B456AE9F6B24C94892AF7650C3C4193C11D82D3B859ED87FA188896E3C4E90DE4534D21D04ED5968BE5C8966674F42E6DBDAECBEDB0D3AFAAD6ECFA97A30CEA4C09EEEEAEFC069D8D54816F1BC57A9E109978336B4F6718E49432062DD137A928770055BC2766A745AC511D949EFB31C2F2FA2436B4BF1F98D6F0C82C5FCC88365F0DE5E99F99125284534FD8900223E40EE63F1301E4FF886B6CF972543A385931AE5DFA14CD6D6AB7FD93CEAE766E35DBC22E09866D5A125BDBC107C8D8C14A9E405EDA8F04F764289B8E37C1EA7F5CA0550F79BA16D65544041982903FCF614DF600DC788D908DB234ACFF7DAC63335BEC95CAF2673E772B8798199CF0199F80BCD50767C0462DE2B44E9B83AA02CFF70925A9A7242598F78726E5E4A0563DFD3C847B198CC74C25F10F14AC3C9AC7B57D007BDAB39BD12F18A80B6B1B6A091851C7B161205218E8DA921569B1D1E197FBA831663905E58DE88BC4B90295104332818BCD70F066FC8BDA0E46AE858B05AC4AF73EE90C90604BE8B9BB4AA78CF0387229FDBDB6DAA96554CB85BD95FA9E5B6EA277F058A6379C39EE2E94BCF5F4CC3EF936C80201FE22EE4B42F5F752A273DE0DBD7698964167721B0AF0430D53A69B9ADE587AA8E2F8A659E917EF377C08E1C80E9AE51FABD2BF48D393F806A4D1AAC149424CC8CCDBF947450C32D2E35522094643991CEA2FCD62AA3F827B1A17869FEDF099EFBA80016B916A9447B200C18842C0C0B8E21512DF0D55CFA369052A7481A461F133A56E5DE09DF57047D61F2DF2ED4A6D93CF21B2E9F5B220BD0438B4A1F7BD773B994D1F4C0B205DC6FDD50BD6051C526F63C91C0F8F316CC688714775961E114F3F23395525D8A44640032576C92A46E82B9C1B00157ADAF4E3483A49F3246E98B1042D1D23995BA8429E751B03F6F386F42BFCBBC02C59BEFAFEB5DFD7DE2BF4B60971B261F3EE2A2DE7191A520D0830335B14AFBF37ACA3998AC027CD2FCAA10B8F1E2068F110B751ABF3EC913C721AB1C8CAB31D1CF29CBFEFDDABF5617CB04EA123700D4A6C6AABFB8AEFAB3EE22F33C6C98D92C4A50E0F27D1FBC9EF06FD31F0C7D0526B10DB0D88627A4AC927CAB03F087C498BFABFB2C6600F73E6E83ECAC32D555ECF87991A8FE7F83FB3817EB5E88B398F5498D0D0E62858D30F2278C9A7427ABCC67E5D8A377BE81A0A93C262B462EA1497A05DF1983C34DA6AAA3A8B11C9AF92089C9556F56B6C91295C74EFA1624AAF4C0C3C7BC404E0023C8244CB8616D5352E61E63673D3920D41E2B7925B961F409FE522F692F405658A56395915F9979D28F6620FA0FA759F57C5D04EF8D69B86494E86F243D778E123B86ED787128853CD4C7121610C6A660FD7B7E3DED7B405E90D4AFF1B60B6149BD636D1F3A1F382516D8EA8DFF9981B0242CB0EBFD4FAFA63155F192CD2483BCF5B6A06A0C7B7B2DF5137E5B1E0691FF2FB95D065E115E6AB4C7B087170D2116275F0640063AEA5330B0648D17B3B7870259E6E8D87DAA68543034CA23E42FF9D78B38AE8C9D690747986554378F233B6E8E45B4FD40E0EBDC1DC6B9F221E9207668DA6881780D96079DDD6FD7B9E79A79F54E48B11845610E19CF659CF11774ECB092A6A092A58C3FFA54DF3046808D6CAA3BE698B215754606ED1A0FBB1B9C688D93AA6A51C8E70B4F220A11E953FD3DE404CDE7901B21A85FA2F27E38EDA37A11518E70E0BE97C2305D8815ADD3C5DA2F2C698B03CA930D473BE7F3FD5916624DF59168BF5B2CB2B7370DCAECE0433A06A5BFF3E3A64FE5A096A22124BF0D37F2510AFAABC93A94B4FEFCE8B963A03C9A89DDEEADDEB330EFF6060A8466350B56447453781B6E236412C1498980B9CF7E527ECD6AA1E19C1D6316EE8C1BE442BF4CF4BA1BA9FB5883A2A3105DADC1B43A9D758B6FA8DDB565C8318C73C0271C6259A88F0CE41FF5378B970854A0D3B9CCD65DC31F89E88C4A6DD121E12BC82442DAB16236B98DCFE81AF616F3039DCFB1F7F8F09A8248790A9DA50E80A2144B605F75BACB5554492BD4D18CDD49CB0A6BBFA194C1727947E91352EA439DF58ABBC285741D863B66AC49654F9406B9BE2D5DE8DC94EA0EE7E17C0ABF2F1384B90E521502922339532E001E3781CCA33F09A6EA0AC5BA91422ABDB0668A339B8F8C6AF7A4C8A44B2C91D30DCB355D3687BFC8B48A10813C8E5354ADFD011149973A73699814DFC7811BF6B35ABC9A9033915F48D0FCAFFE2D43D84AE399C39D404A71FCDE8D375974203C6DF99CF2ADAB52E765DA9E3E829CC5B18E96F86BC5F6466E0DB75ACC0004DE2D2A6564840479C493A52558A1110A334B5C3FE3ED5B1ABAD114D2EE451352853C7F766841CA5BB885B0BDD523385C228A261BA2369F8365082C594B295A9499AB3B95836D6764B4D8FCA839FBC06BF81B384A1A27136786E7FFBD362D9B9026B2CA42AA0E4816CBE2142E3C96F2FBBFD1824889F1BEDD40DF2BCDC9E85930140A99A6D294CC358ACCB1A6E736B69B15360C8687002AFB54B716C2A7E6A894990BE8E974C842F554CF3FF5C9B83D5F399BF7B08BC176BC55CBF49CA0965D29FD71DE9BA2C516D82C6A5D3E71774919A173C15E47E54A5E073973C10F0FDFA044C0027AFF7F0A4A06A0A48C6506FDD1158DC1D63072F13E2F16736EC9E5BE9FCE68B5FB129A1EF4ACF1AF3C66372958FFF0AC9EA86E1502E37441B7CEFC3D5F208E1C6FB4B293EF6964DCD1D80CD95AE905B780DDC8B24AE516385BC8E8A3EAA3FBE3FAF252C2D766416E84DD38329393B79BE37388314CA1B70206440EF266991BD855B1EB59869E2C96EE29BD14D8FB72CC2C9828979F0807B3038702B9235B627D93D7712C87D00F0E580F57A07685A949E228D5A808F91C20E371AD2A7C7DC47CB04D3827117560377C2BA11BA522CC5FD604E11E67C0B411FA82FC7581F6B3BD23857BC37230AAE8F2C16F914D2488E23C34F12D148549F9C066D95A7193186352F1280BCF63B4DF0D0486510FAC5CF8B03ABF45F35AA652FB5FD4BABBA7FB618EF680A1E87731EE117AA79AB9CC482A7FD11989E3891F266E15D3DC71770024436561460113FEF8D4EA7A9590CA908186CA41DABEAF35E9C2E2D515EE9C5CFD618163DDBC47CA922C657FB7C959C54842CC6019FA40E3AC2C2BAC9262A7C8AB79F3CB8C8AE6CA39D7A1ADEDD0AA70798D45AEB6D347749552260ADB3872EDBB2006B8B650D6E5DE76D78934A42A85039583994093B98F705A86CEB559D8922ACA6ABD456AE7011296F0875CE052E419E395B4F9B67F59AB578851BC7A3A29342115C362F2E19AF0251A6729981F9E4DCAEE9E6628A19A0DB9D12A014A5CC81A13100D25B9138E6B9DD2D6A807DEBF391B6A56DC18CE8D844EFE8E8FF1E03D4EB03AF85F9465B660125D8DA022E4928000FA7CC629B7C2706123CCBC2DABFB7B1B9D526C450AFB567FCC5A762D7D034564D744E52035E6B34E8BBAE827C252E50032743A4B719CA0ADC4435B7C7E8498A6CE10353A6C82A3A84A6576838ADCF62F32616E73B0BFC413F6FF000000000000000000000000000000070F161D25280800000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 9 iteration(s) +mlen = 32 +msg = 0D00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = E68878508E16F608560D18E3AD67A4AF53640FB64937E39AD0B7B636361262C54B9DF9F721DA48A3B3E1CD6E66DC6D5200949D8938D0BE6019C72362866C6EBDF3800620C512ADE29F5B31C43CFD8DB916E4B070EFB06B8E1534D92FC2EC4CB83747185EED0039A1832789E565E94EC8F01C3F57CE619E9656A389A1C8142324558D8B8F143BD6652C77FE42A773651931FA4857BB8C76B6328036CDA7FB2F32DA164B69984D709DC270A9F91D2EC31E5222A38FAD92E04CF3DCB99B1CC6FE106885CC334FBB4F896AE07D8CE2BDE81F346A28AD373438B6DEB6938FF7BD6988395182A47FCEFF6CC11AA44D1CFFF7A3E51AE1194E983BD64D6524DB77F366512DD156FB4C2E7719F8A9B711E0A1703676EBE182A4445FFD1F3F05FCEB6D0B7D2CB757B989127E23585B3A81DFBEFC4590FFCA2CD68208A390D99806F9126986B02757CAEC6FA6408C2AE1BC71D352BAAE3DED8185B7EE2DCB9A5F66E5DA2598C4710F4D1DF226B787A4BF620D18C3B2AA4E01D4A1BCCDBEC97BEE2BFF7A062329F8C59A4FC72ADD75472E0B9B9A0BC7E69ED0321045F0CBB1BFFCDC2FB1D6782203741AB9C8CB043C07B3672A523E806ECAC52713F9CF24733C9694F84BD1844FB272D2DECD083F9779D583FB6591BFAB6EE5C1D300C99CEB94957EBB96BD1EFCC0C44B46FEB54C16AC8C78BCBD30AA3D27BA0FFF2E6A4E175B42066C0DAC8D7740B769EB24FCAD8F0CD90DB5840B3BB36359E8CA30F3CB12D0538E741A9D8F536BF4CDC888DD2881E2CDB022AEDCE462C26CD1F2F81CDA5D3AB3A76213BD8FB75753236523CDDB436B9180A5CCF403154B93B57BA5B24E7335506C2287BDE4319D8CE48B9D10DA5672C07A23736F89944FF56BAE2EB49C2BF485F1D8D6718265A5DF4E632F840929AA1B508F91FC9797471614D93D2C171FC512D99917E32A37CB24EED04DC4FAD9BDAC904A076F927A14562C81CD027B6FA32B027BC2B60E1B7B50694533D3BC08FA6A5617D36AF278199D52F566B1A770840AE26274357470DCEC5FE52279D3D342A118EE44A85A017941E1259FF070F2CE566FDD8EFB99FC81523740A9128448ED728276B6E22F29564E6471599D109EC52EE6EC45C284B71073A157F57225B29E3BF1DE26204CA82FFFE2BF526E77020E37446EC5581E63A246B76EE9DD86D00B490E2F2CA258FCB5676D95E79335F2039B9FFEFAF59D7785BBD82CDAFF931F147AD3838F8EC26B6B4029D5CE230B6F2EACC4107CBB339E69B117C64BFBA217F4A89224DEEAB637A6D28CAA0963C730FB0D15860336E740466ABC7F5145ABA081FD592A54327200E481A19A9A91DF105DD9F064666C2130B63AAC8652815FD4318E6F06593BC00CFA193D37D4BE276886790DABCA1A3B94F0DB5878B03E7296EC874AF7D909087EF9E9DAA06D5111076A9E2672D7833E14CB858D2EC3DEC31645481D36295966D1BF8D8C2B18342F36EB77CCF904CBF6F5C2B5A52B7C0EDF23827356EC7DF716F7E3231132C01292F2D088B2F2CADA8B88BC4038D955E3C70A64E047CA5A6B73C73F97BFE36B0BCADDD403C70C03DBD51492C76FD0BC87364669DF42ED1D6CDFD1A96F51F2357CDE949B173CE9FAF474C2EEA3565A3CCB6532815AFD469B3DB6E01A239B263BD70A6EF147CA3F471AD065452CB8D3DED26D0589F2598A072FC5799C16A75FF4A1648D1A1DF4FB6BAAE1EB92A1D2CBDD588E3935E56A90D8CB53A92CDEC9EDC6E80D66C15656CEEC21CE75CAEC72AF9B5B7883223DBDBB71CCA72ED008F49941055E71EAAE4D858D5DC3EEA06D76C3F9F92F3DDC26C1A824FA1B36A84E1011B0E51C37E1CA84B678C54701B24C72D809BB49A78857CF84DEC8A79886719C66E32983098C80590B817209A71D115F11F8CCED1B684251BB25D3FCB3DC9107D3C8E4FC551EB6CFF7C9AC7A5C03E86650D7AC7119DF3B73A52083CB520683E1C784BF47C9428126BC4298F7B926423AEB67FFB0D51B4DE97DA92A690FA0CDF7818717E0C3DBBBE26CB8CE6DA26732D7125BD31C4B454AE9308A668C19BB7C29CB8A5BF9751AAA65C7BB5D3B33CBB3F9D49BA36640D16C32EF88136DC464C60E54307DAEF9ED8C52679CAB4E48793D0D2E812C88D5928A7F6B378332AA1593E28D070DCA8E744505CE03FEAEE21562B90C59323E88CEF4AAF9C7802C504D552B6A5EAEE2C49007FA5930B12513F1898222EAE1C2E08C1C0BDCCBBF8B73DB580DBFF060491F8434712329E5A10378D7E891502E45288F886036544DB76274694E7C45B8A1E009408DB5B1DE8E5E4B53E5C98C3AF2EB8CF3ECDA76C14BE58A9BB1E2EF961D3DE593157FD67D08FF93973281690504CFF3A55D86E9370199BC464ACA85EFB5B0BACF233A58E0DAB930478D79CCF5FC2513AE5624204BDA96C512327E165DACC79C35083AF569B39706996A0D699E3EE9AAAAB2E02CCD4ABF6B763330789C7A4113728DC4DFD9FAD065D2DF51107EDCDBB1D32EE9F563972668BAA1DF20E77C09FD96B538AD2705C58B2A87CBE0A532427432A8436E671F4965E05F0F10081CA49C538BEBF0E98BB4CCD72B0E21AD5961F93D9897953B27FD539B7DED7BC981D34C313ED267A244CF76C4FD54DB755D3C114CCB9EEE6C4709E0475F919A49DF41CB3B76C7989A15E2AFC8781E394976D142A14DE5ABB1A984CA1E9C5131A5ED2DA4BF69A3777585291C782655BD9696456967D420A03E27E9FB6F3D217031670360247E14DE3AC4A2267B2CBCD1BE7445C35E3726AC90E74873D373B58C522A85FC4EED6176D6C4D1FA26F6DC644868E2EE04118A35C51A921215C36A04407FC967DD4BD41FBE43B609A0842C4231AD11F94D7C18A7D65179E4280065CF55DEB6C7BFD65A24530F92EEA71586C51A17F964E9587E71B7D6249B96CA8307305133E2AA2E8CFB400EDD8D3D5E6DE5DFF6DE3DCB4382AE53EB30A3CDA97CE83E61C4621F2163B2F7A22009123DF09D10D534A313D9F3B6A882FF22DC6D4D56AA517EE23609EE1DB6B45AC4B196CA8699A132A8A01882E382F2A89FDAE0E259332FBE6D65B3987A5B2F1D077DFA5C1ED8D461130592669002150247ACA0C7094C9E831F4303EE9398D54AC247A252ACC1749CCFBA7DFE02F468541F0F76A697F90E5C1E7737F00FA6279ABCEAF9C4B19E476A2C7DDE6763BB3CA9D75264564C878FB8827C3CA7CEE86E8CD6E9070E09B61B60D14E5F21600FF547F0A8C894A0E6D03E1BD779102596FD54E2D5DA6B93F901B5F482DC0223C6B977DB029EF1D5B3EE9BEABD505079D27B72D06C9F12967DB41B1BC6F3E806A16E82DF9C7DF95E9C3C69C40C1329BA98E845717813A04AE816BD98131899F54F7D2673680BAB5325CED6DD33B4AF8B6D727FC19362EAEB74589B3A81F3C2E37626DAB4F2FF9EF42FDED16C81FE7D3D38B55468139B0D874FB21E0A977AED92B00E23C5E0A7EBC9B4DA764D865D0C8A74C5029FC38E0715095FF6DA6DF4AEF21D13851BFFA2D98790E84CD456820D3FF56000BA61113EF5FA278FFCFE962AE4AB674510E3B4C409A78452A356AD705DB0001C78C4ED36EC95FDAFD6C65BA8E01474F0E0DED11E565AED7AF85D42E50C242467DACFAD3F07CAEF2CCD80CE0254D19280F98B20F535E7528B9BF14C4D182A11F235B3EB2FECB680FB384EDF7C8E1D0497AC298E8CB16F8038BFFADF7B6FFD898E46B71E8B5C3D45A1C83ED3B44C7F870FED1502D86952C77A41C2401AA7B48FA61C19E1869A7371905F89CD9670F3BCA59B9313C77C41A20493060712CD3E63189ED5D3A7B372AC4A8AA4BD351670D0F5BAB0F5956EFAD2BAEEB7EF8F9540CC8BF4A166C4BDBA16E8DBD76989210B9B5F066F9332101B0F8906BBF75AD060FABA2A0D59B7A721937F82CF8D24606CD894D2F097B1CDDB32725EF9C1923B4AA3E0014F19F955F873CCB1582F4EA6631C43BF4D28E9EA9F98A79BA798A6D130CC91AC5259B0CB5149FFD2859864D962790B1346918B47829C53EAEE487BE3AFF644F402EBB0797A8BBB04AB375AB2C008300CF5EB28EF4F43E3A6FBADEF515285B8780914C10238AF19AE80AC6FEA959566620B7E489EC3DFFD255A871AE06BD6DDEC26B340F7983E184A2E1DD25D1DB9566ACDF0E6534C73E894C88EB52E85D8921B1AAB25A4BBFCE665AC2DFD5D03BD8FE4BEB8B42CF93ED9418E494009A4AD4A9F7C3CA516A09C55F0B62A4BC4431D8B75E651998C40007CCDD658EF51FCEF5851FEAF148145DDC460F26E264AC6CEC355DF1E9F19A3B47AAF23E8BB5EFE2DCF4C12CDF76A5200C4522708DD911BF287EE56ED5288A092A3724A79885857C6B759B04E9E956CCCC3A0C087C78F787468E4A52C72971AE7FA8100EA015C662405853A14D1E9F4734591E96B111B301C2E68FDA861D4FF4085A46DE15DE8ED123DBB77DC7CD286EBA809E45D6064169DA469AC17AB32D57FF3F9A1B79C3FB487973A10CAF5F19BEAD7E29BE0E4D61C385D04402E03F7FD47915DA98745A1A8CAF5AE2FE05CC4D8C6C95645798CF453D42DB1B189AFAAF957E91BBD924AD2F6740EE6EC2234BE5B08676710145BB92F488B9495A860F1F42D439DC1FE2A40436896DA353C4B526F7F8C95D2D3E3F20F104476BFF0F800000000000000000000000000000000000004070C121E250D00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 10 iteration(s) +mlen = 32 +msg = 0200000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 282F0F7272B8B9F6CCE50D748F0D3F9761F610D4F636BF25BF2EC47B2CF033AD91C0C60ABC1C11CFFD5F9BDD41468454372CCC204A83D613C8C1DC3C5A2AD9083B9AB3406AFC430206E7595736BAA97123FEDC02B36AE5D0ECE70B26890E93F8E9919112DA1915BCE6441767A9252D90A9671ACF056AC1896AA6642936A0578D1E84CCC95522D2D49611D6B67A28163A02F777D5ADF1FEF167431B1D143F08B1A908914C64B40D6A3BC259B7F850BF32F14D9BC0E8E61E3BF789C4FC059BB45D48C1E58B786486AC35BACAE36C51BC0137D28810BC288223F2126D94E0BF36CBFEADE622585B37C80407E777006EFF850990604DE7836590E81BA14E067317B889D33413D71F2C38F6F3D19DE662E61DA54CFFE96C9AD5518876A842907CFAAE3C83A5C9393C8705D451BABB59C306036A0EBC7EEEAAB2AC9E61A5F58691F9CDB5DA907FAAA055094515491EFE40D924D9F50CBEA000300D83B20CEB99912FE8B1BC8108C216420C3D52AB28031413DE2B55221175C3C60D83FD2E06138DA00A76B77F916A7C9B97C145D83E03AC8433BFEF3EF4937D29CD0E7E75EBAC78A8F4514860374AE97CEE2D3A62C44F1A3CA9A1B80CEAE734EF1220ADD08C96B6DB12CF28D39D8583AB8D932B03E0D0D6873C7C2428405150A7F3664DE648749B92FCE22E56AB2EB422F26B00CE50ADF5C6016E92BF5C58E917FFBBC86C70EA35A37FFBA3046DF32D24A50E3B42CE2070C36F7E2A6F6E6D85F5DDE6ED6C9E0B0FE6D5627DFDCC9BA00B0E400157ADB5107E392ECA42CE4F4C42556A0AD16C1D36B6146BE7EE747A005857C8059F8854642A623AA94132CCE088EAD46F0CB534A9BFA82B1ECB6C00083207C7049468B0432FEA8BFB75DB58DACF174D85D10F9DC3A98240CCF841385F4220363E5E3D40F4B4C6E51A14080DDA0BDB3F97D37BF151EB6BB802000D87BC522436583FA3950F6FB7FFD5333E7F732E23C0ED85A1C3545B1C771AFF5E6332717ECDDE23CB6B64A350970379D4F218F865245F8483102FE8C65CB3BBB28EC6DD8973B388F8C4DDDBBC7D979EFDEE2FC32B6762207AB568B192AE3D7404E2CB6F158E61475549CB325FC0585702BDD5AEDD4707216C78EB748082A441B12B4D9C0E79FE0189AA088D39A26380C5498E08F0A38712AF2E0AFE3246B0F99969721D4D2AD2FC4BAF09CEE10D2CD2E93ED41406968140123D21850418299EBD5FBA68AE153573CC616E667FB8698431BF76E9FA2B0E1CE0F3A2A4DB5DDF4033A6A51082EFB64C52C8E25280CECC45EC378149A608660402754873CD5072330582D2B6F38722C2B31CD98713AA06EFF1A59E1256A6D5BCD4916CA6C0A017E8823D2F98967E64132471A6AD8E7F157A8224AC5DC219B57C929CFBAE11A37E742EAA1A8EBB7F799CBBCE4DC13F003CF988048AEBBD72C39F8A8D257BE7DFCD959B72854102B92C3F17938A8FA60BDE930537865EA8CABEF0216007B841D2C3B6A1DA1903B35A3226D6634E474EC83DC6D2EB3CC6C0ACD7905C5AFCBC01A255B4926A5AD781681FC5DB7A0A73F49A8A5B55D313CC197AE9EAFBC8FC9DB13FE79447812CE4E4F0CE2FDDCA7DB04C4FEE7ED282E311528A00410DBF0A43FB311C4109A35264AE7B17A7FE64F4E9E0F1A579224226A04D5A94F86B9120ED208BD0736833B20DE004FB46B41D07D04C1A4CA786A49A45034F1815BB49FF032BE4F48D6FF2904D989B6F6EE9CF52ED5A5B83C93CA9688CFD0679C40B828E1BE7885F42C14716674C733B7D51E9794CA1A35A92639BAD80A8E05323989848E848FB3C4FFF60BEE96AC9E1F665DA9648F728950D0B0DF3339D26838F618D6FE228B5CC0416F9DA3CCE99DA0A1A453C975E4172EFBE4E4636293B64BC188D0DA318EF428B6EF17325B136FEF140BC45CA8D998DBDD65CB28F935A28A60AB12B502E95164DA6704A5C9667708294BB45D8D8508E4CEBAD5A82B4AC75B0803876AA1F3D4CF7749609C726AF0337B84ABBAF620952D8803526718F56FA341EA7D89A2D08BB81C4D4C85CF4A828B443A0B29DD247E7C0E31490130B987C0B391C1FA59CA4F7AEEC89A9AEA1F744419A08821DDEA90122989C186023D179E51456BA066AA6449452770734971AD90A67640CE95D10EF6C8415FB34188E052D5FFEFDF8D97DA4F67BF59945E0B1B94463960230862747F847CA3F294759B131BC586C7630A64C69DE7E6345F8C8C018DFF3D386BA99C3BEBD3D79896CF41F516F007006B1F9FB948A3476B1D4F47B95D890E99E8E4E3D301181EC263291C1D9381240F450D636976F8A4D88B00E505D5DD008AFB36A058ED3192D3A36755006BFFA0C14AE06DF23D73756BA918B0672A3972DD3BC09B12C272E136464763DDA07C98E9C81B9D93F987B786D92AC9254B63DF4AE200A3CB8A77950736B56C5CE5FB4255DBA095EF0C2ACB965377F57600C6ED20C532C77756E3E5771D4685A0E90D7EB553AD85233D61282F71ADF5B4B9A49B1F77247CF77435D043E43FA6EC17DEABAAB8952360F0798292C8F63C3AE4694C237406644AB820B33C9119DA8BACD0ED930B5FC1197FBBD6218CF493E86BEF3ED4DB1E1B1BBF692CE8DF4758FFA08A782567C2379DD563774425547DD0B7976BD17198465125743AB65171EEA74E8B55D06F3D6593B5B769784CC39879BD3F775F1D33B11A12FF67945AA943D0772336D862257C933C283972D20D18D6FC793CBD7F9643A9CCEDA691F7203FACD650A98E9F8BC9E86671847298CCB0C3A2CF4BBD58552F81628FA82B4D4863D025F0F4438C2F31411A2B20633D24D0B90C606043D386C4190DF5225EF3428D0D9176445AFD7F70D3D0D27EBCA9EB517C4BDE3B0BF528CFA1BF7A1A688C6ED6E672FC09F93396E4A0227700627E9837CC8E6C653551B021071A7D347DC8FCF77F51B80FC43906E7B021A61F51EBA9E89ED78A630F8E1CD1863E4031EEB6E6497C493B47CF245575E6543ED138B9CE06C8188F0E6DE18F2CBD9C9F74915A0260E4A3D4F9EDC1B68330B9DD2E61394CF9D9E193B1B1D3B2E10A0EE23B4146FD5CB261BE5E48FFB2349BF31346688B6517F4E84C9E32592782DEE40854DA7AF0CB67D80B59F08D7DD9D410360E89DFDAF52B786BEC57DC09B2EA7B9F5A6765DE586B1A40024187BC538C5E71B19BF54C692F687DAD5DA709963F208F45702C6AE500BC0BE672680249CA271CF915F239433FEE9676E6B007B04E5C1687E4549184B0B3D65643467FED567D229A2133CF1697EABFD45F58022373AA4331454EA041EED9CF612CD1B1ED5327B80C24AD2807001DC827164FB3CF8B8B57D61DDF1AC5B4F1D9DB78F08BB72E347E7A0AFEB9477FB6D7F6613355FC24BE06CFD6CCF6278B4BEBA566EC53AF541C2A43A33C6D749BA9CCAA3A5F92B3487151FC1A027FDEDC6C4EA81458E01DCDEFB7114F3B7AA48153E3BE3B37B7AC55A37EB90D0AC4CD52F3C5BC744C3CB83B8F4EFE62D23535A9B1127B707B99D1438360C78E3D748B49B8CA75A2AE6AD9EE0F61B396CC5AF8F75EA007E6C0134CC145527BA4C2EF30EB0FC8BCD9E5976A60DA49909EBF2A8EFDB7FE6FB285C97BEA6188BCB6B9893DA5AF769BD36C5BB273551D7AA8CB9486193647278FABF78DF3C50AE48C419BC83E11C18D840E7345BFEF2739278FC106C6C21E109D5C0D4E385E0D72A3D0B1F4CE5CFEEC3CB6A205C57381A1B1E77F3D42B0D21BA1D358E217D3C5405B1D8FAE81DD2C3DB63B8A8B1E316F84D6A98878D0BA8DEE9833A75CE240493E43826430144AECE8E6D1A465CA08B8AAB43200094E81120E9C650DE002BFCD0EDBCB5EA44F4C32E2361374B2FC4FE6352A7193302ACAB5750565FB6858EFEC3DD5AF2DFF33DE712DD4ED2E21EF646066B9FC8B3D0BB5CDA6F751BC8327BEA3BDE750DD6F4E4F8A7CCB19A96BE6D0899B68233ECA525E488A1919D11D8F2CD63533FF048AF696F601A83D15259B9CF12C403BBC1F1E033029847399ECF60FE4271D973C79B8F6C7F454CDF34D27FB69F37F9735C69B5978C30C3C53400EC70C484776128E36F0A87DB358880F33671A5B3ABE4658E283048D6AA76BE8BF6B824040399D0FD8242D9D72BA0E1CABF5C2AAE2C8AC6494C33098E2AE1EFD82F3E2950D2D66173A2AC2393AA3CCEECDD55436C0E1F0BA29B46E89FB709D3DCCAB024A26479B71CED06939458E15D85BAB7885D628E05C570CBDFDAAA81F35AE30982EAFAFC1DBCF612932B9AEA1573AF1C43E335340151AA43EA07DD8DD1119CCDCFD90107FFB8ED2AA11D945A9B271F40C5D1FC9571165A5AA45B1836117198E6CB2AD915631C0C7C71DAD998167E7B57D771015BABCB0E1CAF9141FD4B6FA2C9A3530B8724B955BC06C53609B89FDCC942DD5738C2B83A3C5724508B70BA96EE1392B45C2AFD2224FD580642BB59B7B350216750A8850A92A7B12BE20E644E38E86EA8A9595BB821032A07C60C7BCE0023B173ED26C51A6A4661EC072C042CE7EA9260B4488D8E63E99DB7697D9BB2770548753319E74C72730312C49CF1B4A4C5CD25A3EE93C3A7DD2D2C5EF1851AECBE0748C4A68E84DDDBDAB500001A575D77C3CDD3183ED9DDE8EAADCF0F1542BDC2CB350F1A3F404A6F7C7D828C9396A3A4000000000000000000000000000000000000080E101617250200000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 11 iteration(s) +mlen = 32 +msg = 3700000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = C637BB0B0FBE6404058B0C96283165CE84645A9D97507C6734778E42809B8D2FE0A78798D8286B11CDAFC239ACCF515F80C6A6AAD43BB304315BFE6F294697D41FC557A68770F74157C4B6703C154C19C3FA39A7EB85FCF62D4D9C8B9F7B06EB1BA9BCDC2970369BCD6D0F42FC0776F5403497F3D419676EE4DB3A2858D7DA648CF48773524C12BED8703FC73336DF29583F8A25DD7951147F09EBE5DF6D1D77CF53A2098B1B2CF2ADA0C307F190061E3F71AE4139B3125693E8E0FE1E91AA4971502E1300B1FE5486F160B4556B519F82B5647689110F559137879A7EAEF84C7E661028ED16EB70FE9A83F8F6BCF719E03EC0FDC0E816ECE340B1EC8A7653C80584C9AD51CBB6AEBE63EC59D3D31F747CEED6BECC4B69F112BC102E29D938CB690314A6ADA4A46241222007DAF6B25E57E851B861DD51192E154158E6D2D12060E14189885E536DBC2503CB26D05E4D72766A2EEBB24F9AAC8FD2684DE33B822D419085878338ED6EF87C3716C3CA1B3F538BE659426545BFEC8815AE56DC3A013F4D19859CEE5ABE44048A3303E0F8E09E3361B3C957EA5A99057F365A4CB68F03AEF58F016E026BC733140E8DDC77C6FA049F5A5A2E510F03EFD45B08E145D8F29A8519D92520A6DA04C8CE472C1A6735698B35EE4CD6C3B645D67CAB42E30D9A47CEA4CD292EC8067F7CD357F87176236C30777AD9D01FD12963DF2686C0060B11A8DA4F06415FF2C4DACEF91FC9C6D06FE85FAEE9834C57F5D7FB77F79B52D65BA4F999817EC5CCBC4C63B596AAF4F83F4F25B40C96815DA4B80965818E7C9635500157D5BF9D000EA265B53B9C7BB6BEC81028BFC35D76D3156CD29C7E4AAA27301169F11025FFE1AC35616497AF59EE9829053D96F1FB4C8CC28EC9BD86E7FB493E3C7D8BB9E2D968B2209058DFFF5426AEACA97A6D4AD94D0F737B2944AF849190CABFB5670F9F26E0DD1628077B12C2062FA6E4D2F901A69A8C830B3C14E491FBA4D975083357C7B1A74FF51005E34CC7601672907873BC6D83CF678F2ADE44E4F28768CC07EC00F58378457FB1F714292D331008DFF4555FF8C621FF88B40A25324F4651C09640747752E3DCA6D4A3B0B9D08C513DA50D071B967E6E8610273F7F9AAD3ADD836B15D0783C3239B736768F8A3B39D21B6382939123118BC6A798AF8C9266C0006E3DC1A105D0CCFD43FDA88949F5C8E6F6E022E985E8E36D63D6F80F923D9647BBE1E8F6BAD41E873CC8F19CDB3ED4B1A8B9D8BD2372C3A2251478449ABCED3C64548F697B388BC888281DC72CC67F046A116959B7CFD7A3C50ED74E1C7B3F9B4A5CE66BF862FA97E35634A35EE95B14ADA6316D0EC6356A37F53BCA72277F33275FDE43107D468B09F997800AA039FE5515012F9A0B01341FE15D883A34E8A2E11F05012527DBA32AA0F07F25035B128C50DB9BD5E498C0A31165FF0C41AE58776854DDA4937EF6591316A5BA687B358EE1DE8228F3EB7D654F1CDFB7EFE7D90F7B8D0A8C06E680611CEE19426C84FD68E7AFF1E8BEB95F4A6414046795BD04611760582FEB963320008F68C9759EFE9CE7AEA81BDDC7A97EF18996813DE741F872D4B51C2A0D2C2292262B6476C4160666E652BD89201B8393C26AD19580D5840C2EAF88320D343D6174774CBF06E3DFECA6E5C1FF39CDFEA6A708A24C80F8FE3D5BD74AF0D6D2C8BFEF71C4DBB2B1323BD5C2E6BC9EA5F839D2AAC40BD29D25F81D30E801A05B40A62A5166573CCE6059138A119112420958FAA76493EBA44B47D011053D1935533AE2F3F6EBD4BAEF7A64111CBE7AB7734E4B41418335C93963BE0534D723F4E1AE699E341955CE80A4F5506DD48E28C673E74A1DE2D572A94842B2B50BEC040F39B374A6D639F0A747C49F12244BC173708DFB0D2762D7C0A9A8C0BFCC7D3C6F5E3B0FB1E23FE0DD0898E0A1C40D8CB4BB6971D716AF1D4BE087010B2C3259EA03DEAD8DF5FD6513268352DD8B5AA447B7139104105D6E25312CAE63DA6369973637381794E2762C3D70D6AAB7C243FFEECC08C1E4E4EB1657FE0007888C1FDBB83D76612F8457DC0FDB6845C9DEBEF1D25C1FAC8C2BF37FB064A509D55639DAEC683DFA66F117D6AA6440F2ABC3A0A806657E4972BA01B326DF686A885D9845C94B799AFC83D9A57F238089A9E201004691681FEAD57BE7DDE96B23E56A5A590ACC6FBED77509C8C966EFB321C444C04E17C14764DB8859BF98F19D7932E648C077CA905BC481033E35B64E5840D467E84FD0107FB1D84489C9B92632C0AD494A6CF942AB41ACAF27369370069C08BED93DD22BD20E26B0D6B41787EFBCF2B02950E5C68C9AF44FB1764D3886C15859BC2F8A650BCF162814A86B7796ED3F4F292A025F39C239CDD4BDFD02BD37070C06673AB9EB3009C38CB1CA428DD9FFB08776AA2ACD91AC7294985F99590863EB0EC7AE4A0FFDA1CC6366D50F412ECE784C85BF98197B18EB489C5EBD6369E15BD696879144950265A1CEAE8DD0F1DD35A350A8D21F5C9F421C98912EE8323D0C68527EA634973EE63B4343960523658E32C2999ECCDEBC6041988F21B0874F0AA0F13EF8D5742D1BB9D30FEB8211C10B16D3804BFE3D9EECD6FED832FD42F596E50BB045FF058FB410798F62D0E88A853C22509BA6D46ACFF213AD9BD066F231DB82BADBFD4A530BC671839F4529794C6AA3DFFE9A9C4F6A496E0ECD7021FA048F60094C7CD3F49707CE114EFB99185A7022B1C35BE8A6BA6413CD6B7E4C8C2351CE6CBAB76F2A37943315258625BACF8AD6C177284952BA4ABA33FCADF26A9EDDCCFFEE13AFAD56481513DE9CE872DE6BB602B10F831000817A0722E663C372F4A955713ACB201698D0ABF1F4BCFC20A1B78D1391A72A335253E7EC6B623319FBF37A2E18ECE8E8EBB2B57D04E71D723B4ADBD6A61BAB8F7AEA926ECA495343DE90F7929AF9F7FC8372D16DE32140825D7E26618FA67E9DC97E305C1750C7B01067FCB7EA337172B70CCE793364977A6EAD1CAA844C6B9270E454DCA244B46E0579375F8137FE0D4713143BB54CA9B25CA665292872062D02770064231A0D059541D8B27724B1F72C95674030D712516564A6287EB0006EA73496182E318E0BDDE3BBD5B4BEB70B2479D82894DBEAD03A69ED50CD9FC67F9F10D9A3D4E53489D75CAA1138435942C19E88291CE5E35386215AF3ED866CF9B4B1B13D04A159A1C6716E9DA6FC8A311A711DBA23A8ED8FEE81A609C9F21AB6D6DFD0487A36B529B77D3A974FF8E1DCA74B445496430EA3A5FC9F6FACC2C571B3862310CCB01F9E8C54BBA587C387AEF2053A7EC5FC2A28C295E5130C69BFA30FAB41C4A28C1220F1CE76C38231BA2DD5465095EBC8EFEFC8D2F7EB45563B0CBC526DEEE42B6B0E4BDC1842D4DBCB4CCD882AFFF6F13DEE4CE935B21F2A954A54B1A99171945FAA72E5608006C89CC1B93133B64DBFE0DAEEE95521038083B00983713ED865EC20A47DEB8EFEC70AF398B095E01969A4FC6DFBB3EE6DF653EB40610D8CEA3B5923A1B98771BB11BBD8EA11A7F9AC23885D183A91512AF88CFA306C33CFB09271EBE615698B6E92663B0D374C70459971A0A961D5F417B662FF12836E03C63EFEB34AEC10A9336D2238E94674BBF6201FB92628F167221A071DD80BE91B10FD1B7964866F47FAA29DA3303F116B742A73AE122121E109896C2AF6D263A494B827556755BA89EE64C6FD9868E0CCB7B5AF645F013847BB4147A4DDD2423934C752C966312C0D3901B0029250EFBD4176C01B98A3D5542B14C19016DF3F5EEF6CB4BE5CB2BEE7856515F3A703BA445EB5D83E1312C0B94DC4DDFAADA7998E769093F1E8CDCBF3DAD82CD643CA63DF02BBA13164D036D2B38352DC7B8EE7ECC316106080ADF2393CFBD956A3CBF1CD723E5D6BF0D7DB0332ED647DAC93386E4F452ED75F8EDF6FEA39BACBB36F64CDDE2E085A6D45B6AD6681B8CF5B277102052CCBB382CEB8673A5818A12887D3B7F2F9C74337254B6269174C342365E0C5B5A1CE5533BF915A3461FDD2E97160500F78806F08B84D195851A20AB33B83AE5D0AC71A8505547AF363A4E7E9ED1D1153D19BD6BE44CA86D3C3A9B12C547E5397332905AA08E59874F296962A8CD8F448FB797F29DC4CB1691F130725E9B82C5EC5BBF880088A42D4AF080AB83467DF4DC0C52499863093C7213096AF405BDDE5AA53AA45C1588A8867D9C0521A7EA920DFEA82A39600CE1D8314C292430FD82FF036C14E80494E7F6FD50DA981C2C8ABEB7E1D78C40DA1ECB65D9B1AB6044802F7054889F719CFC13DB6BE8DAE3DC66DD5D3F832F55A3EB8C4E38100ECAD3D0CE469E05125DEE3F6A5EB671CCF55FC62E39A4D6C5074D60677A40E738B042A00A6D5FFACFE65E263659160C5C003F3997F9863A46AD77A9D22BA6D1EFF1DBE5348EAD1642EBFC114F422D67F73C80147FE9B6D8BC19A2DDA566DE07F64E52D0EB8A0326BD1A9D4D61E107802D83DD7DCE7575734610EF3377618731104B3425DA03077C8299E8E66148109624125AA477BDA68EEE54C86F5AFA56460BCFED063F847BC2D5ECB5EEECAA7C9D050648F1819292D5B669CB1CBCDCEF02F89AFE22B40CC1E1F2B414A71D6DC374068E90000000000000000000000000000000000000000000000000C10131B1F1F3700000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 12 iteration(s) +mlen = 32 +msg = 5A00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 329D197DAFCB5775B679FD04F0545CBE06B5EA670A0CA24C294FF6BF179A101A990C5C1D0CD955BBF66B8AACD6753E3B73A5D60318E508F18EDF02C1642F4BAE773BEF697226C2D2D32A124C33230A610E9726CCBBF7810BC35880F110BC5B943EC08B5D48E69C7E517EB4C6E3A09223EF092778792D5C0F1C6146A250F385729105DA422680B375EB90AB9CC5375A6252DDC1A8C9FD43673ED24A1BC9B29C33DE1910E73D7ED01447C9AC5478B23E2101A41334D8C5E168A4CAB4A8A6A9686288287181E3775A072210F5F7748BAF6DAFD3A5A08D623A780528BBFB7AECF47A7127A53FB97214C1D0B15FB2C07BA054BFAB2C051FA8323E8D790731CC146AF1EE8D14EE1AE533DC2E8DEB327B04723593489A0C06E7C6AB483FE0D1B95B46433BB75DC308B300CA38F25877597C30B94B6C6D0E6BC596BA0A1F46588E0CF2DCA60574B484B29592C9453FB79E2D26539F384F5C01C8B3881A95CB0D23D9C8715A837D2C6C4025A80A5D9F889C1497561718F621ECF740F7B8D5F0BEC6FB68D3343434208F193F1A3784FBA2BDEDF35F42BBA4A292F40937E09FE5F83EDC8E9140D9A0ACDC872AC7E989A86A8402971A7254D59EAB5DEE25682B4EA56BDA9A30DD5DE53C6186E94F8D434F61329445F4F573684F3746CFFE66520F864751C22E51A2C1711B47B562E383F7A4273DFCD8C661AEB6EE8C2671DCD98AE3B4B4E8E896D33B45FDFCA4307AA7BD34577966976943B69236EDC5899F57B859990A81C1D646F9154BEB9E6536910363A5BD4BC6384CA69414B3637DB541FEFC75C7B8F7ED04A9A29918C3BBD8439BE6836E81C3628E0F281719DD362DC3F6709A3FA90D71E8F0BDED396B2F4B42F160A614494E50F3098B1F15730E59DCC01927D3ADDFB9C8A6F2FB9467FA526803656033F7961EB1F97352F76607FF76FAB9737EF795D033168AD31D3C2E2A50113E8460B8A05A5D2894E187DCBB7B1BBEC8CD3985A862EE115F43EB9BAF4E3432C4E7AD2AD5B14C1330C5BEFFB08B9A1F735EA76FACC8315C30C0DCF4EF34CE2B41E4382F39C20A1D556C559055F9286D3C91408DA01BCCF91ED532AB6B7C4B7F9E26F188FE7783E1BF8F0ACEE41C801C1085FB4DB8E0124145EBAF5B6FE1C067241A60BEDFCA3A60604149B008C544DF6C5532A6BEE7DDE9D7970BA89B392B164EDDAB4A82B92E2F16C317BB21AB83E461DC7351743715781C74DEDD09492FC36428D5E31BD04FAD10F18BE8C70C5F38607630EAD73D36A3CC93B440CBD4B7DC5D880ECB155181B4D5E0C982047380B88872845C9203062C37DCFDF3F70DBE812399D696025A3AAB6A337F71D8025F5FB2F76F440AB6D950A0D405348AFA6309CC359E5B8A30C55AA6F6C8A3CE9019746D8E89F350BBA91CC64EE3E9B129DE50D855C8DCF0830CF9EA44D0A481A2A44254CA61B443FC7812F913367F136700B3EC7EFB0050E4817036A411F0EF1AD51BDC2232FAA0FB85DC27B675BC0C3FA929524D52ED760088D310BEA8B3DAEBBDEB019DB49533D34DFFBC8B7341BD68428E5F3494C1D27F9AD4D3A337AD0271E8243AD82FC54606B48872AABBD3DBE31A670B0B2F1851FBFEFE7C9711F6F03713EAE031A9A7BC44E7F8B08B9FE9AC5CE6FFD19D49202AEE7194A982089B348FCBDB98A722EE916237EE11B6DD81B53778662EB0DD6E890321D638D283B22AA64705293A6D26ACF72E44C4A229E073EBC33E76717D1F6DF90B583578C5D0806FA224024F7F3CBBD6701FEB91EDA28C483C0D99AE20EEFEC8E045A82E6085FE87C6F0543D5917CA8B289B4314222102128ED1CECF8858E4DAF4275A3EFED28A7FDCA3182D741687660EB0E4C30A0489BAD636BE6752A66425C2094B58B8A52096A0D41ABED69AFDFD0C536F23F1E0455956A444ED84BBA3567F3BFE18AAA315D88815F6E79A95DB84516213F89B19496B511A60079322E2CB40550409711046ACB5F25BDF7AF252AA7CEB45211F8474D02F488FC7DAF82C5B99EA803F509BD07F31A967D53A9BA872EE29D39255911A7FBB3FCFD3B51501A8CB7231EEB09581EF1373714772B15A3D752EE35C5F5C64CD7D104D625810307A946E2211CF8BE6AF39A0D9B12C64F1E03FCA1CD8EB10F3CB96E4F1100952FF7CF5A71CF4C2AB867B94C7E73C5585314E680D33686340AA1CB26EC5B6A9B2BE75C7D8FBD6439B1199421A68661057331291E5175BE09D38FAB7C11DEA9C38A7380C62AD4CD3B9567353084B56DEFE4740E503B38DFE1B522B3B9D04C1FD9413A8AB2A318DCF3C1DA81CF88D0559D3E5AE1E2568B3A3264257B740819D0B5DEAB9192A3DDBBD0C55B8B2092DE9BAF1B9A98BB26866242D94389D8BB7DF073D851B086EA341F52D36D1C62DF7DC351529584E2DA55E059A8995C75C2CADA3750FF15656EDFB46593449566C35A4BCB2CA17269404AC1FB52B8312D43F24036C4A69DE33BF09119982A9B59921F99EBB22CD5DA19ED1A9CF22BA1BF19A1815A4266139F5CB2BF78B4F506C571D3D93FF4A2C19F8F705953FEA214B0FDE0272AEFE59F26EEF138808349A9805A47EF01C76A5D236160A7D950520B0E1E3066D3CFD78601A9828C9FBBC78EE4A115083AF5DBC57DFBAE21893F6FD84C4D78C8502B8FE21902B78B785215FF8C7928780220FD6837288472A904922CBF3A05195455744BC7BEA6E086F8FD41D63C26FA411C0E528AE03EAAD592F5CF2454CD8AF3DBDD914DBED2A7CE827E49F90420F65763E7DF627750240DE5D288F83D39ACC89F2FEDA0F15860119D472FCA64D75E16A5F62ED79FA96FD69B7C1358B5F1E97688518260154E4ACBB7A54C3BE252A9E7258F05DF3511B97E5AA66B42A66F481F7B4608BAA3CA922F24E8D9CD13DF6B8A015898738CFB9C9FC3205D16D3EC40463CDB4CCD46717F15AECB61A2722171F7B8E55003E2E1795EF0CE373283C1DC0582892C0390232EF6F9B95470B36235BC1150B9BC469BBACA81ED54EA12E47C176E57B99F2A544FF64ABD7BA68A3BA2ECA34944E44D7D103E73505F09B26C42FF5B70400410EF69F8D8FCF7ED4B69B568E8A5A53FE6893C2B1FF756B7BCC23ED98C3E9C7B6BACE134D4BE35E70EF761521CE673B174DE2FB9416875C66DC6CA2ADDB810B0B2C85E1EC9EC36345A8971A69DECD0DB973D90ED8B9DE3B4511C0C16010ACC43C2CAA47B9D8F4574C0F1A40EAE91EFC590745844EEC43B159B76FDAE4DBE2FA4EB50F62DF085077FFA1ED648B7ECE8993B8A9B3C8163279C0695FDF287DF677F21B0B9A2582F2CF8A7BD402BC9D2D2C447A3EFA95F774254900BB5BB307741F28C6B9F88B8D168D2392C81CEBE15B2A1A25DE950BBA9BD9F9DFBB51CBAFF1D141C61F3014B98144135D9E032555441FD89E063D8B9BA43C92471FDFC00BC61A45A569E862B23BAD2150351E5268EF01A490A933A3CA894E6F69336C7F3BA6758F1AFDB45640F0CFFB1F5C917DE1477941DDAD6483F42018688CCC4A6095256BA3F36C7537113529735AC6251545DF9B80B0B7098339911DE42DBD0A92F6307185077862D338240CA63EF8808232AEB84E914508E4C50627E6B67905948ACCCA40CC8EC9AEC4D080ACABD6955C51F468AC9F11962CB7FF70FB86DBF3BD4D7D0AF9C1B03C26453DA1C8BE775D649F9DA1027FD27B6330B432E862672A24F3AA208A2922BF66509440AD278754640E25BCEA025AADA0ED67159D9307234C4F2A9A56FFFB6AD53B395F95C819DF975BFEDCB8201EA39E08176A9BB83662D2D617DE735A1469D08F2A4B4941F378411062B3E4E9E006347734A13FCB80920C87FBBE57719B63D3028C52206C5F621047EE786CCFFB16581718E41DB86CFE419FE498D998CE63D10F8A90AF1B283C28C1253EB8BAB75F8DED541964202C4ED2C85448E4E1B184A87E5E6F57FA15F881010479590C181EC4A7183E21DB1C8B8B588023E4CB272C55071AAD4E651174535E3F678B675125C27DA909ECFB6F63E5704549DF56A0086DB2A0F8E2157D5AAAC663430B8F27DBB7B972F1550A409B68142B280799671BF00BEC11CD7899E42E4AE7C42BF4201023D1AACE65116CDE7744E2F48505DF146CE94DD9EE993C38B603EF96365E28ABC9B9449AE4E46DB9967A9D2C414585E3A0AE9CCD59176F46BC8BA7361D2DBEDC615EF78534C860D279AC4C0D0DF9F7EE1085EA26A7DB76525B79E0169F9545E4F67AF5A3BC804FC7701DFDA5EEDC6E0F9AD05245CF1B9462489E71BA7DC8721234BFF9E439D07CCF92550DE55FA1FCEF637851F2CDAC6C8F46A6C565FFFFBC5FC0205A948848850D22ED9F4F26AE014E568BFB52A24555E68C30592B24ACCF4A56EE3DD6268A3A8A03B77414DB823B0C169B4179E210AAA40952B5F3607AB1712F0BFF61BF27C95B2E1D1346E85B760E636BFA01495DA92CECC4C9F89FDFA410DFE51D548FB9B1170156C77C7CE23AF4EA42BA296F01C71C0FEE4368E0E80761381520E5D276E819369385B13F06250B3531BF81D14A8CC015AFA9BBB1C3AF8DCB7F09666D48AAD985DF0A3BC079B28BE331D1A37C7980D0DC3EFE276445245256A8026755FEFCE0B9FB06666875B0D3E3E6EE282AC4DEF345C5ED19539CA8E40B1037505864727CA3E5E9FD295C87CA0000000000000000000000000000000000090E111622265A00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 13 iteration(s) +mlen = 32 +msg = 3000000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = ACA955FB8AFFE2BB0CB8E1B0C4618D56D56C9699A62E2BF4362CC2D493D4A2265C5DC0071CBF9F2FE921AD693F471C54D6CC650859229F19CAB5A00FF7C1414942DB1FE91DA60B617D7B54C31F740AB920827CB8FEDA78E929CB9912E3FF4B62D73828B43406B8EE8E68BD77E9CEDC71BB36F177A9C4F0859E8DF215D75BAFD2AB9F8CD5CE7A5180A2E0E47678417AE2DD0A4356F616CA5733F753362139E6D27A1C51094F9119224F66131A4EE8901B23D5631FFC35D3FE6F034DE35EB70FC3BB1835EC0EE49B900B5F459FD151846DAC8D7DE188937C21F35D11C92BD0C390DCDBB03E3431BD91974E985574A5D08731C65AD59FAAAB7A5905A8E8156ACE76CFEFE7F0DFE083AE0D229319BE4A987695D75B93E467FC169B8E4E0DDC23F5C940BD9A8A50E0ED2829FCE480AA1B1EACA14CCDBB1DB5EB39DCEBE1EC234014B14F55ADE7A6ABA06ED980E4A0004C0E439BEC8AF9EF6C0D711DD323F73FAFE047E87F364164931162585BB7E559CA3D1B7CBF0383ECBB50D3FA2B9F6CD776E923CC6277F11B9A68008B01FEAC6A9B594480AAD9C178F8F8793A4D49BE97855B914E8495B46E9914DB8D5F92F3CDFD59183FBAC84C43B5F37494DE9E27EA72F20DCD33411E17E38BE40B02D1D9603BBDFD1427725A4E6EE8286861A601EC630E4F6A3820CC5FEE5E92D125E1C1E230E5F24A51A5DD756B21645EA52454FCEF53D4C45480510D3C5AAC9C46991177276D993E584EDEC16C9F0E61BBAACAC5EFB72D3DD6F66761F6FE555F389F791A189F74F17DBF19270EABC7B89BF72708E98DCED911C9F3BAAECADAE4C1AAE77F082D64154A5F15F1AD0967C94A0590DB7415F457A81C613EB792EA31FF54851B8066F25CBCA4D48669DE4913B14A877C50CBABE803E6DCB0ED70073EC5874709D92BB5E14E1E4E5CD6CA6193F89A61A3AE3B7E255EDCCFFBBEF97B9D891D5DC311CCEC4E59775F4FC671F9D6263308BDE1A0D8B920509DF922561932E6F422AE8B92C92035E3FB5885EA32FC64CEB7D448BEECCEB5A9EF651DB0469EDAA36702B0210C5C8BEDDBF036115B44D704063B1904BE41D596F8086BF84498B114B299B7C6DC519D4B023E6A0E22231903D0185630504826F0895C7C405C55F192518F04F56F8DD15872E9CE583DC24D95515FE32C82E5578299B00A8DB6B2DA48B90FD8B1E758390558A09449BC594C38C04B7D11806B297E41E78933757050FC1004F20E8E0AA1AA332B84C72337FFDEB5A092F6C05948C5C49AD7097481A6EFB785159634F9FDBAA8AAB2967BE2D864BD1CDBCF648A94AFFB8CC156F8B76E6081BE81D18247E28DE5E003A05FD67AD947D4F07223439E160E3D54DFA5323D48BFABCD4A4EBCCA482C8E88ECD571AA45F25504434B6DDAD9609F7313FD89A64923A79FE3D12A68CB323D429CDC22B12565F6D971365F8DE3EE01D0926CF0A711EDFAE2BDA639D0328A58E32547B64589DCF1EB26556577E0E7C3CACA3B421EAF53FF109B46FBE323E570FB822E4CBFA881814BE4B8E7075F3434825CE1B58C3CD0BB429814E52BCE0E02CEB1B7EF383FE264DE2F6EEE06FF18B02A7C2CAF546D74F8113D10FE7287E1CA0570745BADBAF2EBEEBE5DDB071214E831B885D7C3746DA4248298B8F5C74093DFDBAF00966DB348246A2B9A3C3140EF3D64975367873D985172383D46A3A790054E671BBD0184EC74FD2FC17767326DF3D71C15C3FCD4DF2A388AFDF7ACCF97C08872CE0C1A2C733DD5B48449FDC9FD62BAB34CDF48A258DF60CA2EF20A9DCBB56589B47C3B3975A6A8D28D9D66409EB2FCD1CD4608FDB2C327BC47A75094BEE98173A6B5E22070705D7E6AAE0EF2DE45021DD5BFEA084B299137B3D941AEDFAEC158A3D025521D266DFEEE8C41E4D1C425120639144E76CC0FC68DBF64B84D16B09FBE83B7A9B19E74BACAE9ECBEF8B713964262C3BEB333E5BBF0CF96E9A767DB226357B54BD51F94581906885BB96E20197AE2F24B8A14DADF3DD0A531F3C855F7D2F06E0BA8887F9441456290E3AA60EF6EA6B52AA048178F16079B2D22070CA23A43E7C5709B3CE2F571C2FAA7FE433D6441C32E006B9B250F184269433B13DDF59772E9C52FB971D236FCC8EB71F70564954BD06F8C2667A1D918BB64C23C5637E8F411386A97C1ECD68F7BE593B3AB09483A93B92664F87F4B91FA0E3E24DD0F1F082D28DA5F13E5BCE6FACAE211D690F55431574C55F9F40D0308D059B0A8D5D49CD6E938621B0DE48AFA2DD46BE95B1A7B77357881CC0DF2334B2F90E43E8D78621B5501D447E53E2408D7C4398D59CAE5A1EDF930218DAA72088F8EC2E1C64A5051400C58F8DE5306326C1BBE0E821C6BD7628F32930CF459F20566EFFD455D6072EDF25B062452BD84CB465507B79CBF3532F726B1CB1BC6CD1BFA58D518BA2D395B27B4385EE693A58A32052FD4F6967D1F4E187F22526DA8D1C3FC0E5C208516DE0DF96558061ED41619B4B1CFCC3C72BC6059DDFD8D611161621A42DFFDA395FF8D9A5DA32C39F929D38D7E2F3BA50EC9879C7FD641B93957AD7491277907140A33FD771F40AAAEF04003769083F0183FB191C66612A53B68E54DFEB6E247C8CAEA47C6CF846AED2BBFB2703C73B810F8786F92247D0CD8DC3CBF30DEAB5A0751D66E6F222E2A40D4CE37A385B4E869F1B27A1107EFE0DA464C7F8A377DB6FCA17B68130717DDDA1661D770136EEE43FF12D9146BB13090D80DEF8BA21C5953BBB4B780DC34E5E0A0ACB450A44A0903D18735C39E386C88C3A49CC085096404A347BE7FE2E51C11FB82B1ED0E6C8B7B7935A8DDD99F090221493CA46A38D3447A40DB20FE2E2076499937606AC5E31047B8AA2E9EA44D19B8A990298AD07B78DAB6E3C7767796A7BA6AAA96A072C68FB610A3863E07A8BAE57CAB674862972B5FD41190D0EF7524329C311DB6DDEAED868DB7CC949849FCBCEC4D5E78CD52FB881C6AE8646E3FC1D4C58B65E888A6CB7F1A9905AACFC7EF63C5E007E6DEE38DECBD69919D1C0252B296EE2A212D3862C2A6B63E1920270CA2D287D79E6C3A0506BD4D16D5DE0937C7D2BC8D0E9210A0F14157383D8D5DE764F9E8AC6014BBD50728C051F817663EFC7CD89F2751BF9C0CBF15A005CD0FCEDA09DEC15B0777D781C064FA4FDD56ABE26A67EC75ED6EA3F6EF42971C2BBE732FB8622D8D006C03CCBD2148281259EA19F61902A949568E2A73F42B46FD0E097A04CDCFAE9DB2827CA86BFFD0FABD2832575476CAB43AC8F7A6E458DB6D89E13A042D8397CA365EE81E47C190563A9E2A2E5835B0B76A54598F2A82F34317102F763B4E4DD035F605F2FA1BFDF124D4CE1457C78368D2CC3A09E947951198EF6D1A90E0CFBBC115B45C5A39B8C575AC7EA57D57FCC0C757D5DC65AFA33AF81A4316A859E6F63E7463E0C506B86DF8B898223AB590E05B8149ED7DC4640FB1BA9BF0CD3D9423FF0B77ACAD57F5C8377A032441DDDEB770920E17F6535FF5B213F59910F6D2CE723294788DB3A1EC15D9753FBED0413A154E3559C7782F4B1B1D85E911F9FD53A0477B38E2CF3DC357D3274C887615946C536666FD9ED2AC02D0409BD71CB050605B6D72B5B86837D9C1834CF56B18BE49AAEE4272F45BAE61204D101123E64952C1EB8C9BDF827B2872F237F58277450B704158F4A1D8836C2B5D943D76DCAF3332407D104295254D0567A3897E2675454C4CC8711D3EB974E80C7A08586C058DE444991BF6D35AA9C0C001EBFDA40FED69D9AD63057A6089B46C4157735AAA1474229D2BB4C0DE4DB11E363E24DD97E23F41CFF4A902E2A22F4D273A1319209325CE275F898100C1A8644B6F6182E9C264206A361DE85B3BE510F0884722A34D070123BC59A5B704DE7C1C5C7BC335BFD47A1524C97FD42529CA45339473051875012B06116CBB6B6DDD5A9CCCCAF1F02FDED20D7613A5567D07AAC42BF78BD2BB1522A30CC3B3689A2DC08C18130DCE4D13135D14946C68B8E4CCEF451C3FD2E5A9A24B6847AF0CB1D94D4E156008B5284DED4A465C3657D8102A5B8A1099FF518532D7E23A5B61711CEF14E99F24C3D4454D06439105335BC522C54A3CEC4DF7376120AC34DCECEF775DB37666467AD58DE5FBBC38F0A8D2D3BCEC651B3FF4404B20FCBA8314EABF4CB02976FA827D5F11DF895BA518DA951E62B8CFC1C4DDEFE9A9C123FBF54351B9084AA5BF7C0D63BF142AC0F401BDA28CA60888CE3FD93740EB6C96AF730764175CB3A017AC52496C453465FB63E474FF9EFE76F855F6C3DE5C54BD93A1D00FEB6C9706EF8344732102E0C9B1246D8D86563E5D4DA036C3DA3F15C325605E00614B1E7595DFB15F69DF83EC567281A89CDC77C58D0103EF36A6F6A66044A52CFC97D0399161EA07FCE9545BC2DC81F71AA69EF3CFC5F3FBE2CD00A41CE9CE9BC4F4F53EDB4BB4515C1C224B5BABB24E8164098034AC0EEBCD4271BC3E03D78A10FACD8D44C28081CEEAD3419E009898D93CD80D950CC2B73096012D4FE3FAC6A99F960C1690F2404F08D28CD9E6236C4A62E7C158C00DAEF24780F36313FDE6D0BE73CC250788807D7C6EA2BCCC364575889BED00031D6D81859BC3FC0F353A5480E3F7387475828FA9F400000000000000000000000000000000000000000000000002081118191F3000000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 14 iteration(s) +mlen = 32 +msg = 0700000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 4C20D4756EBB87C04E2B12BC10E946DEFBD6887C1E1E59235CDE3E54F82E24A7BC40986CA2C136250474A24A6A4359E6AB24C0DD5F888E6FF4C3811165FDBF6BBD65F4C343A934C50CBB617AD05F611D70AAD50C3EE1E82031599C8420A14F2249F9702AF294DF6D357A26E3D3BBEB73BEE1920451E08600A48375690269EAD2ED434A4B07DEC198BB71440A6F1D3833207D592F41227EA3B80BEE740B167699B1D1B62A8C0D380096FE20550A35621C91AD0B8B4591EECC06E968A7A0F42936F00BC1260B59BB8E998FBA8369E6C0E4AB59D584E5D2FB6D3BE236D6DDABF760E43613F9621BCE0926008164FEACA03FA415BEAED6E229EFF38AADB3BCE226D4CBC14590ABDF5DFE3671D01CF73E3B7DF85649D4FD4A8DC4A0610943612BF8826811F014E1561F4D73D27C2D047ABC03DE8479C16E9C200209B74B5D5AF065C379C815CA3DE9479C4C796C05FFB1425273A33E44C508B90FAF68D21F71DB621BCDEAC2DE596EA8E2DDBCF8D83C40F212335CEE03E5534033716D9E48187C5E6AED2B2F3159B05B7D26E664ED55ECA7A020333390B5D75F2FD339B7D9110E9FD43213715EFCE49C058FE3CA8E9AE0819F59DA0972875B6ACC22D26BDE3EAFD0EB771B63CD750E2FAF94849B624BC8380A7273357040DA6D8DCAF17340952E61475F15569AC7FDBE96174AFBE82F18154F152B828A1FBC3E0FB30360B0F71662425B226833EE355B692B4AC28BD76043CDE5614A30573690D0491AF1EC2357FC92CEF92185701772C027B462859BD88A2606D0E762CD166B2EBE1C941499E001477BE199D116CC10782E2FB2F93764860915CE744CC1C9DFEB5004A5F94C1035B7053E5063DA3151835E7CBCC6C03BB6C245B29A1B53B5C60BF1131A6C9875B67F70D0E09B24AF743C0669F55218B715F768EA00374C546157877C5F8DA88506DF17D08CB6B43616A52AFE7FFB1E9573DC4748016811E362A0CE050DB3FE521AD275872B2574DCA118357DD8C54ADC327E1C3F279165FDD6DA2AEFDE314C8BF25C0ADF2DE1C3E999CD37EA9440CCAE029A0A18A71FA49E3025A3534B4F5EA84146D4761837C6ECD6494F65E413705D407735151F63325FB0AECB6A08622F7D47B78DBDE33F928C25BD7552BD5EFC383954905E5081787DFF7A99C9EAD9C1A22E93C5611EADC2110BC61B8CDA5849257EF3B364D714D3D8121123E53C17612DAC8854ACE6EE3724FEA1ACA65ECD78144BF636D381B04A8569F08044D48010D4F9DC82332384FEC13FDF75A19B658CEE93BEB3FAE83AED20A67E5B5222D2622057268BBADB06C867BC9FC5DA9BE0BE1D5A80AC9254EA676DF534499DC9D316245AC914744DD8EF39BB7F87E75E4C50180DBF2AF70182DF9FA9FA6D68F8F01118F1D62A92F753272B9608B52222BBB4850D76AAE9F8BF3A34738B3B0C85AB34755CEA1A2F8DFE3E59EE3F48DF02FB26434A3C1E1B0C07E0F0DA24E810F0B4190AAB290CE081E7BB407642FC2A7C3A209D2C2AF367217EF57B39C19285020A6AF5BF367EA819E272B3C4988035FE23CAB7BDBA868C73C1673CFFD537222572B68303A2C71AFF1700B1C1054C38DAF29029D5B80D17C571F6B3A370A155851A44D3F1F0EBA7996589A25A011F706EBCA54408BA0858C32692912675F8982C6FCC5B46FBF56D036AB51D23C1F5DB1412E95E35F5B023F11F05BCB7D4A2339499BFF3C517BD0EBF28000C41FB6CF513973CB06A0434F2B1E7D488C752C3F0CF88EB139610E1C6ED7B19D808B78A1068851D182CCF706CFF29D07F1FD11D7DBDD0E5975CEF2B8797C12D8F229E16309355EEF3BB68C904605AB078B3B3C6A5230A79A01018ABC653991272EB69377ED306D0FB21079CC11558F4AFA644CC505B1EB93714C99D5D9F24E1ADD89C493F62D837E53E9C29D5874E7D2CC5ED570935C98F64B582813D09B9BBE0122A97F4A186E40E1D9E5871AE879E8898C4DBDFE8E7430F714FC9887D90C4FD25D7A45401E113C3697ECFBD72CBBD838D9F4C92A20529F5DFAB9A7E45815C1E6A786CCDC1060F54E00072F9CAF8746D54189ED53ABAE4583F1B12F5CF068DE12F91A5A18C3FFC2E34F4C93C92BC32D5744B9EE3176E3D096BAFB22D0F05DC7A2AB450B4FFA996FD34C52215AE4232461EBEA39EE8036995B3A8F79A6038380046A6F8C4DA731AD6D0ED8EF3EB18CE10E42295FF1429A362F5B487740F36DCDF5AE8147B1DFF375929810ADDC6DFC5EAD0653FD2F41A8B052EE356CFDFBD907FFF2F50FCA7C7FE315DD7421C45D7A5D44D059D8F043BE9023DEB6AD063BF7631A0BB268B718D10556562C0B7AE71FD7598B677B4AFC2CBDE1B3BB2FED29BC423CFB25FC50A6E2BCF7F72A69AFD44C7A7E6CE90EFE9869B9C3BC4842A8D5DD285B30E00ED00F9C04F8A319F56630A7588CFA05AC0215C90FE6304B0ACF5D9012D9414F7DB8355D62CD01421A0033F06BB82F3FFA5ABA7D461EF0486F9C712232D62D7D1261AD3DA6A050ED40DAFAB46F0D5625AEDEDDDAF365C1BD36E6C06086EBEE512ADF26FE51AE7ADEB2825C416332170BA8C98BBD0FD61103D03444B09F3574966F908CBBC685FD521D8A7FBEAEAFF70D3EB009335D8D6C36CADAE7C0BEBECED3CFF06F08F5EEB55AFD6428C1B09D3F87170A739E1EEFF3726F7C8FC5FE40E6F748691B71D9A025C7F2516DF9ADBCA126D0AE88F5D89311FB262413BB4822FFDEB00D36251D95E2B61CEFDC45DF8AA513FA1278D370FBC84E49317F71BFFF01B54C44BDFBB4041191D99A2C38A08E7BA7A7F1D28CF4FD60C64A8E7E9EE943EC4B59DD1DE214CF2E4F1E572DB03780C80BAC53CB78BE8ADF305EA2DD37CD298E09DF98DE9F214036642BDC622292A96673DFCC937904D98A7D5C22978825C0FF8AF8128A28738D555FA8D0CF28CF90DC9D876AA28AC055AE4E18F52F526A1EAB58E32C1D07BB62477BF3643FA0078DFE9FB1689B4B86E74CEA57B182E044B192695DA7D39097E74C8FCBAD5BCA84FAFF8B9E5D4C3FEE68BE456D906D3D6B33F8D623742BEAE927890717D06779AF30D64656F0416ACBFC36E0BA5479B92BFBCEDA0F502225FFB560FCE92A0633A201A020AE7BD2E6C8AB100D2A103CFFAD4653A35B1DE6AD2EAFEB887DB92BFCC1147A8CED56C31AED1043E3FFE28BD9E3A303FE54EB5D4E6F397050C45EF0CC3215E684C30DEC801E7951B2F430C578D65945FC920C76468682EE7A5A9ED7A94C86F1FFDE250F6BBF32EA7C6A164617BDB34B5F8F78A4BF863AEF2DDD54FB67796C99BA3A30C908B74E291A1E3999187CC5E848DCBD4237771CA92CAC386CDE11A6ECAC522140CBE2D2477A173D635CCEEED3F4E677BEA60F801D6B6D029542FEE50051351C54F9D17156F54AB3C20F97212A442CA6CCD0763BD052E84D8501CF1E29949F6A065DB8087B094DFCEE63E5D3474F413AEE22725DFFEEBB516A814C05C95D5E8A0C2437E83549E5B3C7E8B79F0A661DDA431355D1AF06012818D7FFEA732ED983EB519CFCA79913F4717875BC1147F0FABB622B5DD46C91AFE56A0D5A1A890B85963C1A5E69573C51F80BD3B2C533299ACE8A5741E8F463E939D8FF25BAC06F56EA9FA497E8B445BDE706071144EDF446654DDC813CFBD79DEF406D88F1EABC13AFC668939CA8EBB6857DC6507AD57598A20E37D3976065100BF691EDB2E07E4AF41DA2E71B811A69EE30C9CEB2D7193F90DF8D76CD844AFD1663A919FC8BB2A9A2F5004432BB292D355FFC94709B3D56A0D2B6851F50B82CCE36B0F9F5D0F9CE65AAFEC0226E6CD3C13CC175B23FDBDE4F2DC727A316DEEFC49C36CE5E121D68C9904F6F8F8A77B771D35AAC6C071B880A05A4D0BEDDF969F77EBC6BA7CC7CFE328CDD15978C5E19D14493439B1D26054C5546FBF726BFA5E7FCD0F79F936B392C32FD817AC69613C9113EFA1A6C4FBDF7C0208D5C3244C4C3634B30AA3D427CAABCBF6916E0C0B4D210798025CD079D99C7DF73D36F9DCD015D6EB42C97607897EC0F325D63ED27F6E8F6F54933885E12FE331C27383081E54F4EE37FCE9C80D45DBB240AF499212026E3820E8FDC918278BC28D8C5B5720C99FDD2E7AF558BC21E98B619EC466C6267CE57AFF3364BD96136B33CD1A786C58A15BB1BB8B59AE76536B1486E9094E1BBD9C02ECDA2163A091F089C68C9E322D58892F043F6AAAF40796A8A057B254C4B286DB85B19A310830DBEF3A9363F1F75CF216DB0E7D9BEB09CA3C34331BF46F6F7ED8DC5C492EA0A38CDD71F0BF308310DA8CC9BA54CE737B14E6920D559789AF7BB6F1D2D24C49F699CDA760E2D359A2025B6B5FE8DE7A3FAEE2B8D80049A37545A30DAD4ADEDCB75B0D2259ADF75D5FE6D8A25E79302C06DCD755B4C248071903C2DB57506DE14C2BD505FB8A22B1E7A89D4CB742B4EA08065B5A49AC1EBC9636979F2C3BD1975531549FA054D607403087637A299CCCBBB22868CAEB689B5A07BA9E4DB8CE0096FF94343D1A5F3D81E2F4BFCB21F52BA0E03F2ACEEE92329D8B86DB09907376E1BF0975896CB7D7C93F0871624BBE901DC44D21158525788012BC0914AF7CCBCD50DD5918323540899EB4CED6D9252F728F9AC7EB1F4BD1F7051A393E535C6398A4D2DE033B5E9DF0444C5B6CA7000000000000000000000000000A111520252A0700000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 15 iteration(s) +mlen = 32 +msg = 5901000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 0AE96FF29DB27475FB79C14C425C0EA4ED3A6F5ACA3E03341C0915072A3E0E42A286C52FC6EAE4942ACFD1702BF89091301E0148CE84E6FF37324C910E879F5462BF79B2B694F816FC7ADD718BCEAC778C5AEDE41DC8FED0B36E389B578F2C2A9CE275106A43CE324E1F8AB3D90E2B74962C5312E0DA28E7A2EABE551C7CDBF5570CE51B0A6375D485D60870E7D33CCAF6F38E83DDFAE219FA43C3A628F906092D52436831A2BFEBCC8CCC3D4C37AF51145B7426796AF475328E4F13AF5277A61C6439FB4ABD3E16E7926762AB654B43ECB35AD2B55D50124713F40B61D65286C1F6A22098688A54927A9C0809B4592FE84E6716B3FCB9E9578922A32552D0240CE23BC33EA207E7F0E454C4A1E8D04F1984412CC43FBD6190DA1D7B27BA81710FC9357312E6A378A190C233C7A318317A18F8572AF09790E9FC6533A75B8FCF50A98A2B4F812A6551DDBBB42B852515579D8F494180E88970D66249D6FCDD043D8D4A28F7DA88BEFCACEACA48D5995CA175446E683CCB819604C22DB1E64A00CAAA9922FB47AA4B593E9FF1CDDAC56460D4D10A7EDCC2F4EB55E656AC34360E59E2229F001E1B97359D6B34ACA5ABBE7E2F61A1544B55AED0AC5CD5EC8ECAC54AB2DD60D2D388F30A58821A2DDF783D406F5661539522B08B2B75ABF69B3846B812CDBE7F7F9703DEDEF8E44624DFAE277D73D0A48DBB204367E42B5745E6D1B39E341FEB9B277624D098C95074F9AEF2A0EC6D19E814D6293505E522FEB5FE8A307CED98C2AC121F2FB28766EBE91EEAE3ED492E42B1E6D96766CA36F088E6BE95A5C905239BC710BE4453FA4C6E4A94B813299935A72AEEB28E82E2A5F75418473B1C6DB746D9D5FB6FF8F3CF12AC89DD5D07981200A88DDB68D6B4163D33462641E6D864CFEA94E4C3F1005C72842786ADA132A5C208D78AA264178C27EB78FFD96C657822E87E644F04FB488B1475BA38E257D7502DB05B3AA6D2BD7CB3624F8871CA02365F72B21A700A09C5A2AC8768AA9C2EEA057A8B3044E57BC4522C54140FE3E56F1106F40372A4966FD7E2F49C0F50739C3DEB57E55496680DE407833B4572D0B8F2645C42C4E9E532EAF834751437D456BD8E7227F784E97024EEF48A3C28DE24BA3ABA2E3AE0AB9115D8BC42C8046B112973FB5235050393000BCC9E9E7F5A1908DA1E6D754BB6677E84B8B19AC59DF7C04896D5EFCEBA588CFCA5A47FF525F3E3A03F23E1FC2C568D13F6703FE6BE6D45DE6108A5A779A1588E5ADA196BF57E6A80F172CE2EFE45A4CD02341A63FF68F9A220F54E98C0456C48232AEF29B3CF7A0EE7476E53074DBE6F6D6B5CC6C7DB09281D8D18556ACF4389F980A4D3F31E7B68A6D185020D3FB3E7EDC1F6146537AC6B53E2EB051A993741BF7178B135DF37697A53DA4416FA3A532B70B07ACD25AA201D4D331FE2C99C8B909F537332167F16219D612E3B52C31391D88A1864C00F280933985E25EDBF1275F1640C4C96D1A207DC9838DC2A79BB758E0492CFD82266D33A8010C9B7969A9C2CDD11AFCC76806C8B313991371CA7628F4F6125AA8D6F93E54508EDC4563ED98D95FE5599CAE63E07CDFDB3296B702C6565719380C974191CD8AA3809FF70FA6A9549115C9F636F7CC013861290BEB1ACF259EF43D48E51D210EF9A15F01AA156C68B9426981657B40A9BCB1E24C59E0739852B9661372A93DCD5E15FF5DAB707451DA37B19A815A1C1E42E649A785941FADA03FD49FE4350C52C0BCCD5A3F37C9AD996B0D1E46F84E3C52A3CBDD034187BBCBA24605AED2ADDF7A386CAD0041E20D8332704B00FB4D7F7B5E41B51D22849B347479DE81C1FFA4B60E550039D8CCC48C71DD700AFC79A8A2DB036A025001F14A29E8C1F6C262E766C9E60BD1DEF02BDF7FFAC598D0BDFB7404FC80C0937D0CD390BB1CBA5DBEA4AD5917948ECE345ABA23475DAB8DA835E921885EE1CFFBED132E3F8122429443DF96BCF07B0AF8D1D6268BC2D33AD91C873AA81FE95F10D76B7391B996F5A589483FFAEC7DEB9EE75DC674ACBA960E0A173686D7C8ADE2CC8A3758C86DB5406880D43E03A5FF2F32A304553877AEC6AAFD3DDE8AD73E9221937C74785479267512802429AACAEF9AF27602DE45D973D6CFF72CF3C17305FA4DC896520CAA84B91D644E0B50D1E92F909EC9FEC83D5FAB3B82814C3DC8EF17B122CD2AB487B07E926EA2A17A399E107C44414DB3F61B7B81E9AB51FCD6DEAF4BDE305B678AC30EDC62101C57AA347FF1E7787F40698C85AEC1A8B8572798EC99D434E0670C4613DBE89C5E63DBC8A4A780A063ED1EACB7C3BB967938BBB9CCBDCC0C22D6D77B12F6D1DB4B511EAE4EE5B1412160CAB2148CE81D2877D71D37EE9A32A12B866A9CE34E6B2693C126F96857AE921F6A4070230A1435ED8047AFEF81B82C0F99AC25E7C9585A3B5984BF1902C27AEE5F7CEB3DCA49FF573D87AA3EE9E0104E9409C8323E035C3D518BAB3D92BEEEF73A36D5D7DD5A2947B361859A0734766754A5CAA3247F75F56C123D60AB6A8552C2600FC5C38A841392AB5CCB833227FD0027162A9B3DC819BAF21C4DEB72C30E2A5432164A5084585257F404A786DE69FA63E73CD1FA34C5C5A643E7751C8D641F46BE9E9380672B88598BBCBACC68CD1B34B2AC484C76D6663ED17ABDF56E8FD8E3A6D66A5E795C4D622B5EE22B9142150A42217E89F2636A8FA8030E797341BB453CDB400EDCDA2D76DE0FCFDFDFD3C621AF0F848013BD24D9165D0B16FD0FEF369696CD617B8A971F4DB1CA9E8DE7D4AF39212124C592DDFFAE21419B427AA3B8AC121011E93C37B603A1644A2853B1CC96DDB8950B7FC3DCD38E2500A9E44D7F9C5AF0628258F0E4FEF27645F5781A99CBE4CB15D27E1BA9B18C0DABE7FC00B61129DCC1EF9CED8E9284FEC24800C2F4428E43CBEBF84B6B5C9573FCDA463DFA81490370A9D6F3DA6756A0553F3C23B2BEDA638FB570BFFD75C38F0A0567A71F290C818540CA440184C6254DBB5E26F1D31A82A4426179AC7C50168C2A64FB380FF31E3352D1DBB888D4DA49880E55C53FE2E13731A6E69C281938779F3E85D7E2C481C24AE181A571267A4E6F756BEBAFAD1F8CF77350A6B27B538F6E7C501D0C69B3BD00119EE8FAC8581AE95241CB518446C1C525CF09D55B7C5370F09BB3BBD672192DA98234EB96F66489C64427B6B16CE282001C3945CB77ECE4A0404E2F769542D30B60DA603A44E8107A821FAEBD42374EC1A7A4A956D7CE236F11AB39F849599A1B91C307D2CE38905E1632917E0B128E289823F55A750ABA510EE2E9D53E6FEE309B27B4FD9456C14413E84CEEED549A408955D82C97D0A706DDEF7A4413E8D4C83E2CDA09E92EF48AEFE31904A9A223303C40F8B81AA59C32539F082AED85AFB7D54365979BD78A3EA69BD79334270FE0960377114BD0F7F9AF961C32B256878DDC6CA11BAA6CF2248290C85E3ECE829B6E95C584090B4B77DE2135AC7507B97B7EDE41DB85C6C102046D353EDAE7F11CDEAD09413292DD8D68674BC21500FC704234EF36850220FA8944BA6AB04DB5CAEC44ED0DF6194160F4F7FC681206A2F4A83F2647CDE571B7B2F71BC870800E80E5BB9EEB60177337D86FE0D6D50CA53F42BBC72D327451129508482E5A3B004960CAED4B37CC2BC04A81173D164614780936C28FED286A68A9D6CD71720C55F8C7ABBB13451F052EEB535AB9D155393DADB2E595F292978D14D126110010E6F7399259E54ED999ED8FE47109AD43D6905F0A3FE025D12EFAE1BE7F812F09C0C61BB3031C0246971606BB4C3B230B8280B402E7DCDD7A57CA13F63A93CB621863207688841001CDBB5D1FB59C836E08C332577B906FE2933588052BA9D0AE97362DE13F0ED1A508F98E20BA58DE8E35F125819E4B75018C6DEE49933932D8268AC2FED69B48A6FF22C4E841D3456E5476B1D834C2458034BBBCE869195A5A8B046C8E80160EADB70B82655F7EE48F12F82AD8CD42625FE1C162B3FD5EAB61ED00CCFA6CE908350F53AF8A8A5842B1BAABAA4FDFC7DC0D2DFCDC06B2BD3FB786C96667947B3837EB064DB0477C16BA63012D28B479D6B11F49704A39DF7B992B41EEBE13E2F7EB5B021DF2BE37C2467C901325A33256EFF193A89171B7B50C30E3081916689E0C95761A5EA1CECB5990ADBF00934150CE12DD7F15FFA23C904B28CC8BD2441B2928716538DFDC9DA600ECB962213E4CDA73988E22B30D34A94003F3778792159246E206B2FA02989D4632B4D2E251ACDBA79F741635165CC0E9A589D6A263345F5ED3608AA5F235755774820E37175F03356A1641C73FB59F9EB34E169420A53EDD8C7265F618AD42A1BFDAC5BBC367AE366D3A765E39E5E426B688C68D649A82898130D462809550748D140F77177460962E76AB257BF605EA3E1CC34D3C77C78F416457F34998AC0693BD45033AFA5E77E26C148BCE33C2634238410A25C99CBBC47C0F0C892626F9EEA3AF77CFDD6BC410976C4EB02DE3681A5A2F84C0B9430BC6F75A8C1387520AFE25F0305D1715882F07029EBD05119DF7BF01821FF73D422B04B8E833E16672C6A707BE7F5FF1A535F647A858FEDF84A4B88AFB1BB2E36434D738EB8BD1D7B8C9956A0B70000000000000000000000000000000000000710161E22255901000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 16 iteration(s) +mlen = 32 +msg = BC00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = F56C83A96B8A6EC436284C14CFF08FB09B6F95428C11DE44BD37BFDFB07274ABFFAA07CCA07C2DFDAD0AF4A255E0288F84FE3E570CC5D50866F65B5734D32A9A64F67378CD9F68834DCA02D0CA6AD618412AE1DE64BB73E485A26A410535F37C11C29BC6EC709C7A0CD9F4DB11705FE354C9E9C599894FE465EC19CFA6A648D200AE8B4AEB44E599607AE8CC5357687AA5AA4E16A1BE0D3FFA9D8183F37E7057664E1A4AF44BD95684A270376B045D659EC580447A712D7FA9F341CC5083A5723786F53B3BEE31ED1340C70C56C6A0E4BA62B78ED2D138CB5F1BBF788A378742040CF1054148C77549D2411AB91C443BBABD71BF18A3682B91BF94FE16978A01139486A1AC69F8D5715E6BFECA102DA3089477D4A7FF66E2A9E6C6D63EC5D2CF6D456C355FF6EB8D2CB8FA711401F2A977FE507A53A835A5B41C555943AF8402532F214A84FEB45DF54FCC9941E85D7AF3202F98258F55D85A6A2D0C3C3E9204C4E58A590AB3D7D10DF85714B4B51ECC0EB462F0534F9C8851FD9FE01C5658A9B4456E377EE6AA65695A055AADEF8A34AD67A3220D80815E9506846D00A74FA406FC0EE4E0066D9867C108A65C4E78AA52440B6D2229467F3A1DCD3327ACCD6ED34FB3284B3535B10514D6634A7B56350E1F0E7A5A99FB67223D5582456566E1FA843BC48A290EE82EF40F40681DA92F2FAAB8BDB56B3A0F3B2D4263384C7B42672EE60A41A70AF454EF462E05B6DECE1B461184934ED7ED061DD8B624A57F266B4BD15CD50F0792C1A5511AA1FCA0E25DB6C85F67EB6D54D6D32517136ABD776EC7CAB1393AF5C3BA071B2E8EB0F00F8793565122212587D2C3A3E881D8EACD3C3C5575448128402AEAD38E9F4203ABC7C35139E88A7CC0B99D85CFDC542AF4A6187FEDA485AFCE7600BC7E36D0BB9EF1F177E13AE25CC303B9245AD9C17E24D17B7201E38B94EF42730F04F583C6B26A8DBAE3A2CC35C77E0F0FD93EF33C2C26AB83F9C87EBABD79DA5F622053599F6865C94B0629A1D4865301B680890437A084F970997628A74F85683D0169111620DAE9CE55B9869905ADAB7C12683B31884DD9C3E2CEB085462496164CD61B09673D0238CE57E039D8B049C5A6F8FB11125AA9BB2FAACFF9A48437E50C5FC263EF43C1FE418A39A5E70AA23D1592E26A0CFC355A8550DCEDE2690F6AC4743CBAD17860BB13B2555A7F5661FDB02795ACD5DDB66A02D9D08973E1571F4D1EAFCEC5089C3232CCCADEED7AC4B354994C7D6CFA847E535F081BB2B8B72EAE05484DB1420466A2D729A020BA0DE466C035670611304373BF03A34C98FDEFB3BBDDF878F5409BFB657FC1FCD2487B17E24C1A73A55E029263221BEF495E94EF52E81F5E4F07DA04996C7B9DF0FCED48E70C302BC25AE322C71EA12C7FCE267D52E90D3C70E41473099BBFB49D88C9E16156FC01E231AC82CACAC30BD6C5C452B8DADA6B4FDD3821A5961C0DAF8F373A125892069539DBB289BB26D6C255F5A72AA36088DA358922BE9BA030D367ED89601BAC858A16829D8DF676390F0B62C50BE1DD189825454D1EF43E7BD29F646665877850411DA7C5C317DE8CE72E0A2B0AE6168C63FD33DBEF65C21F0DAE2B6724A52DD24B9958F0A4E8617FF5A7BA75952B360EFFC280ACE26415211D215B6A6259DC66523A11DCE0141696FE01DDB34CAA4FB336F9A25E0F528EB00EAF20D6CBC11D7F6AEA7D9C666F3DB8F1962BC20D11DD6344BD26C98621B47D129039AA6114AE2E91919F9C01DCC70E79ED1F37ACFFA067EB3637317239A09A08D9E517C5F2CC7C20F9C060622144A1BE49AFAB8CFF13CE7AABC17FBE73E58A15EBBE63A094F052DF71358F4AA217363842955D7E8B603E3CAE644A52ABA5FF069BD3395336049BDCB0B47E6D742C7C74861BA372D3CF071316B381032CAA26F7ED20670761E63587EE9B873110B6A8F88DA8BE924103BBDDFEC35A685AD91A93EB3AECD202AF975DF233CD8A00C419A3B6D7B3FEDA4EBAAB112417118B7B4A8D587C78830CF3C4BB3FB575B48FAFCBF45A919DFB4D4AFC55D8460FA276FCF5D13ACB5411372018CD363898D7C57208F5D511E00295B8D45D053FA3D196DE14C101AB072027D8B713EA59CDD6280AFFC59A98024A3C65586EBCF11AC9BF11D543C0905CEE0F34BF1D28A04049AEA9373AF12DA85627CA230DB9242BEB057C33281103E8D4C4130766312284E87626A2C502409D4009BC24E31E5C04C840363632F914EFDF1E137269981D87BBE007FC3E7BB501FA6707CE784CEBB58AE0BCCD57EB0040B066E4229B2B4CD3A5BC6A3B8FC21F18CBBAAD51DB1A949E4859CB581418CBC4C4C9AA91B3A4EEF7A87FE92464F066395DEDE537ECFAB55F846ED9F858870E913D543A6F01DDBE4874A89BF05FF1C1278419DD98AE0DE4A0647165AEB1EEBB06CA7E54BA6B1EA8048A080E4976549BBBD6F543350FFBF2F2D33ED9FBC9918FC30A0CC60EE12552930A2096FA8748DB1D55114FF8342E36DACF794FCD34063D0DEB54A9845474045DDFC20E65DCE65DDDDB7DCC1F6F03AB11B87E4B60404EEFAE8412C464223D4F271277E8D54330C056A88B338E7B36CBD8EDA0482C4247B6D2D5B45CB8DF73751E4A4B116EB8DB46A99F9197CD8C64638731F5CEDFF83C197CE3F0FEBFA5C9E074007010A5ACA4488E2FC835D3548FF082914A34E4A2362A7FDEA03349C720D49D40A6BDC9D583128DF97A4B445B07D6E00EA75CD0F97E763B35BCB30D8E15A4A45CCA248847CFFE4F269DD54E7105AF70F6CB32DC60E21C8DDD20A5E7C1E3DAF6A2A2B5B71985AD74CAD6BB68F38481248DD433AE360DE8CD6347FA43D965954730BAC0C51AA87D4BA1D40FE55C0B93C0502DCB99AD707D45B0D0112CEA70B675B8ABA2173BDE78BAF48585BAA7787C67D5EF45612C873E785577404C585D1CBEE8421D6C47A743E82865674815C1E541EB4DDF021F875FA87BFE12CA61AB4F03F31AAF32993C9E02C51E910C668F9C5199701269A1D97877546F9534D58E037D444223AF8631EBBBDAEE7783ABEB30EA0E1F1AAA820B440462E02685CF61B1176DEB8F22EC17F805A2F5D72DA968BD697DA1AD56B65F2D2AAE0D6BDEDD231E9D645101154CC797260BC88142A760933163EEF09E5B5555449B8303493571E553F8F9299D235EBD8566F17F6C77C7A9F122A1A918F9361F47462816E29C66CF888D8E48292370AE1167D077435E9B21843DDBEAB0F4FC57326408C382D7D83A8B6760F2A6CAFB05BF6A8BDC0EA1B1DF470C8E6C66AC3482D6180E00FF65738928E461BA88B836C3AE5BD8EC84507AFB1B9BC7FDCC703E833C203D2D7BD3579C2F5C1619C36E93BAF0AFBCBEE2DCB94EE5DE10ADDAD0935F22C41DE878A9205BB61E23CFF1D88CB9E1A84B731E0EF55144784380FA6A5A5E7B956827959EF5C26542807B2E4B906343B47F3B6F1CD63E81553239E18EE5FD2595170C529EDE26D34B4B2E73A3FED14C4675C26F4BEAC5B312385A38742AD3BA96F5E55356586BA397A7BF719FBB28E8019FE0D4BA91EC1CA7B5D2B9677F9D95A785C034F284783EA1C52CB195D53490D655585E792FF4ED31895767B0289423DD5897F5276E595CE9B5D9FBA87A633D6B51FC7EE604D2738D390C22BDADEBC43C28C7DC8521C05FA49CFDEAD53A32E1F9B941E17512D95D22EDFC7ACA816F222ECF8D29DA55628B1542F4CA7F8CF0A0582C172C2EE62597BDF36F590B68FD1EB4F5E565A1756788A54B43FDC67F78426FD7BEE3414620AA8BE0B1BDE563E2F176173CE62F7916973BA949DBE29CC2F88D1FB30CB545E21AECD96EE7F66E69188292F6C31846B775634DCE449FB96DF1A066A1EA83DFCA60D837B20B389AABF2A0D994D626630CA861122A85A9476FDD50D736CA657ADB0BA60A21325E97D185337BE6D7E85E98A2CD20E1DD7F8A909251724C6F18CE8D437DC0B3764C6052DB81D0AC49AEDDC37BA627EFADC260C2CF6FAF796B57ADF3C7EFC2DF9C09E7818E4FA69B27CE38AE8D954A04CC528017EB184018ADCA03BD956C3F509715467670E842EF6B2EE8899D6DB2AFAE79CCC8A5EFA14D88BBACA7B9DFAF4B7836E7FE8C06F5A5A6532678E0EEA2EFE4AE5807B51770ACBC09EBD48179F5DD48D4D19D1EDB4BE201E416532E8267B73C5CC28041DF981FD6AD43B22882567B742C8F0F47B935C0A8F45CF3252A4CA2DE4D466F78355D052894783B1C30A454FD3789074866268C1E281043A727438E8F1776CBFB61FF9B59EA1280483BB018EF58B58DB7C6EDCA4268573ADAFFCFE35F1634C997BDAEFBFCDD8A3D61F2A2B88F771E5FD865AFECBE43305A66E801A16200C3FDBC003F6DB0B864C6097918BB70F7E4D9A10050B79105A88886F63C1BDAFE1ED99A112B48B931D1F006D0C6192A5F6DE1051DA3EFCE2AB68614F437A4737C3D422AC6785C58BB2E19ADD4DE22E0C97CC39E580053E312CF1D6AAD53B4AEE11B928CA79B6015A397FDA8C44C22FEEF97AFBD5B4FB3F31EF9C92EB1C52B0BD77E1F5F17C944FC0624490097D0F842C7F96D7529604303A432617C7E1BA9771A2AFF3C1DAFC64C7CC9092A5892A5B1E6F8036299C1C8D1F01C2A2F4B6FA3B0EE265184858CA7B0C7DAF6155DD800000000000000000000000000000000030B121A2427BC00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 17 iteration(s) +mlen = 32 +msg = 1000000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = AF93C0F7A8FDDCC796B60F67B473A00A34E99978489FDBB9988F9007954A44C7007D0ED719C29A9D81353F3E44B8C7E549CCBE338424C443E538C7B5CE544267F657803FA59637EFD266055C8BAD73D233ED5CFDC8F412FA1A046CD1F677D12AEF276A68CDAB8A2588FAA74852A54BAC330B1F7A4365498522013BEEBA215D4C783D181AD15984F7D0030FF757B8C0A50A7C1851A55CB4DDFDD69E0382C00508A727AADB019A9520E9EBB88E0995D76411C2518A930226048FEE6B01DBD420C463A5334E164E41ACE2542FC7640BDB200991344DAEF326D620C8CCDB8277173DFAB2D7254BCB4A5546A0DF28CDC4291755FD564245A8BE0C23E7EF8C7674FBB3A6C81569E39D412F58BA8564291EE7C655328CB6449F38672011CC88B848F3A108CD33B92709EFFE3DC0801CA685ABEC737F74DCD13082E2EAB3F9BCAB9F8EE3B8B0725B42D78D01C547005819A63B9C7C24A252E6CE020904A45D1611641C744ACE8C8BAAE5D2FBC33F586E89FE6F2FF01AA8737A5D41F79D967AD06220204C63F620BFC9FA0E1B881181F60CA9B291EEA0C765B549E5F7CED9FD7EAD3A9A127E73F7A361EE26613B12F678F61A336CB5965AABD48FC60801928667764B0E832B0D087D424CA3105552A8D46DA5E43DEC762B65F78B6AFDE136F30F807D355218E22E03516BBC681605BA55FBDED8971A0A5F4D6C4D44D63B854A5CC21FE0110AE313FA9894D6F57F646B01A83E1A7EE41DF6BB63BF72BCA424F9449F6B260428AC001AAC7B7B97D3645E38443626FC4831D235DA29966EDDB8E2E30F1415A1712097B7DC669D3CAC46EF333674D85211E9A94D825FB49E7B8AE54EECB9FCAEBAB8EDFE66B2433FCAB5D4B9DDEC943F3416DC47463C32EF40E9F7A68FF2415B6BC936C3C4CC83EBE5AFCCDB2AF55CFE47EF5614B67DEDEB13E57C846A3CC6852879B370CF8BF5E1F7346751C337A751BE6C83E1865345CA8DF92E516686D997022641AE6585F25DC807244A04F881E5B3274C8C7A70707D7FB5C5BF1D1096038D76CA31C35B451347EAE7A5B2BD376B77A3C63876A7841A398E506963454DA61DCF27BBCFB378EE04CC9507AFF13BE16DB5ED64FFD3E1F23F5C6B06B519A3FAA7F1260E205E9B1ED7C8F5B755DAA51B8478E8F92E86F031BE253EC3A20C36AE8C4A5202CAADBF21AA3F465206CFFE2CD6B380EA9E35DE58A95F6490B71BA32E04D69A2C536F297EF1C7BDD44F0BDB961A3723A1A7E96255E6876F922FCC955376CA117418D54158433AF5298352BB23B84DD3148C880E5C23EA49716F2623BBFC33F86A35CDC16C6F73E900EF2AD5BDE1F8EDB0ECBD712CE18086992A98AB2599AC44A51547FC0FF29EE444161E1620A7E2B529C38378340EB9377714CF1C5D8E73DCD81DEDC847533316C07600523FB3DDB021757E46C0C2239CF13AE3011EBDA4EEA6A97B6686A07239DD556CC78EE20F9D65BB30BF67141BACA8DFF02DE6E7563966C13B954B5B73FC9A0FFA8F1C46207BA024B64AF5AD45A4F706DD3DC42EB7EE9D73ACB5FA6BBB0820471AE23830A0AB3DC0E1D8B3125282A790D366D6823D9A5E05B7B2F5BA5D0B6EB3DA3150CB72A33B4BFD157B4D567CE44D43DDED029B4B43EE2DE531F5A7ABF86E2D9ECC4A3BDF4F274E0A8A055B26730E74B8DE1138ADE92D7FCE4BBE21A3AF06490059F3F0716369AB12E2DD6F25EE5B73A75D2C31AFB0A5F8D7792A4027731475909C755CE7232812B981A9FE347D3686059C6CBFAD3DFF337C1FFBB18435A36E0AF9431FEC93BEE8CF3503C0D86549A2E8F53B6CA6A0EF9A8D815D53667873BBF0AB80DBF8CF8AED5D3D6743B8EC867C08A6B9DCF32E6BB398AC8C4659646C88ED4E44141A8A15369A8C9265B8E0C1CC0A340EE30ECF4AF0D5A44EA6935B08D132FDC33E21DAFFEBC19F4D8DF0EE0CFF37EA4336A9D74E41AC59EA998ED84F1173D2B9F1F5D925F2870E6CF674CF5DDE76C0847AA4606130F04A265F2A10F260AE932C6887F148A622B158DDC2DE6C53132FB13741A2D91FCF6D8850C9215524632F6D2343AF02B41EADA24D3E8C5D29260ED4D16DBC48942EDCBD34BB9B077627A9C143CD6EE2DC383D7B8222A7B7C91C7609E076E9D59111095BA654273166AB6FA705028167CA5DE6E2E71861D3C6E9DF0770FA686F732DFD932B13C19B13C94B19A98BAD4CEDDA7C62538CE80269B21F852607BC4E98117AA23D544673563E75B6C719883EE844014E1E95C62D55C0C7CAC26B64038ED78DA5D953DADB17F51B5E93D513C79D2734F61270E8F9EFDB68B77A8C32636CB6556F7BD6A1823E80BAFDCFC155D13C7DF59DA43A36F172DDB748A0DA0316F9A545523F325DC69A42972AFA1C5FDB7F5381D8C965210149C6FFB333D21085FE711D8F7FA2A89BB26E10391FA30931E95DB7E3D594E97551C4D8D39CEF7598FE8A81A5D9FADA9483588E137A314BBB9E95118DC3BA4C0EF42FB4615FF6302A0D36D54225AFA09D810691962E61A11703F8469624AFC54079E03003441949672FB86EE1CF3F792674F38D73B905AA37FC4902CB21D2E6F9D4BFD70D0BBA049FA75DAC673CC489EEAB5F8F14DC948CFC9F2240CA4754A9592CB01188D19551F22742A961DED4F75516EB6F40519BC7ACF9AF731C435A417DDD8B0E0556220382E0277D27B71885A2D717C479F8B5AFDEE48BBEA908C4BEF0C28F1B49B97CD48B67583BA769EDDDE8367D9B674829253AE61EE24FFB20152E42C58D0ABC0DEA43518776701D9FA82C2B08985949DCABB80515E6064D0E5D914B8710905827A94729467201A4C8C1E4EFA72EC531B730BDDC188E8424290530BE45F5DB0FB1A63A0DB4AF22EA3609C9D06DDF5253BC2065C2DCC5FEA4657C8D0165113B16C186C25ADFA47CF7B363D9B9437B7F7BA32D33F8D45706B4051C39FD0C18675E340202FAA9D6E0CB94B6C29D88D187709C39C65BC2A78DBDB1D21B7371F8ED0FD134E826CAC83C80E9EC08FBD0E2B8FAE270E948BAA82E65A2D3A6D96E0F36E9CE1FE36AF1D358FDADB0CCF3ECC3303F05EF51E9A6EC6437A13C1285AAEAD9FC8FB2A17FA8DB08AE17090C06EA9ED4A392F01E5AE8CF06C76FFCA51B9D9CB2ADB9D98AC920A325B5DBD8A6C2F9CE33DA8C2A08AA304B2457CCCC71D39A7D7C6945180F221429672587DFCD2E1474CD860443CF669FBCFAAD471A2EDA300B662184A150941D0E126F8054470E927D353BAA3CCCC3CD255081A52648199E73D0D86D0054707859464C2A249913D01A1ED17026FCA43FDA575B3597B0770A6E931C8D4343131276D1AC598D2816A5E492DA8C8EF5BF88BB6941898A223E3C274F9729D7109A3917F63115834E4C3ACCAE2044CEFE2D8810B41FDA638F2904D55C4B42B280F5717600E282699C1860BFB7B6427ABEEED8A261D1F6A1F1EC969EBEE1D2A0236A6D9219DB4F14D4342A1720C53FDE54202FADCB8F44978E526650BC4C858BA7EC06DAA021990F659D971C8529A8E8138024A1A54BA4BF5DE975EDA5FE450F72D3E5A10281CD582149E56136076C2342D64D5418BDAA21981FAA2D5E79570E4D9B40D67F987C1EEF79CE7C43CF7ED1B5F9B7302EACDBB644D1610459524E0092942EDCFB2D89DEC927D15589998C8DC051EC4ADA88A39E40020A9AEAA89035CCA9A2E12BEBFB0A7911B163309374EA53B363715A09051EC6D372CA111CBB1C4B9C303BF267C8CDC503A7A2065DD21AD33862627598EC7C8B036ABCEF446832203A4091E299C47E148CEB0425EAD34CA79980C994B96E8FA9A74EB00A3A95A7BC2CF82AAD377820F608EDDA04D608442CA44BEF07622C67BB6F18ED4461A5629A91951DACC068B1406DB22C2185B855FFA9DBA1CAEDD0EF747CB2101CE27D86CD6012969875355E292CAEF22B22BFBFD36B7E1731E5D1884939245CFC30583E7D6C1A9F97D6152F4F634FAA69A9FA355C3E0287152ED7711B89D832875BC216C98DC140C5389453C4B7AD3796FECE24535CD3010DA842D0A57DBD35F8BFA26DC268B9303CC64A257DB4CA8A999DE7E2A7CE25DD94635A95DE6985CB2368A8D0488D8CAF976AFAAB06D76512C2EAE9F8F7F7227C3688314B13D123C32257918FA39F13079007F10981F118622E1654A5771EA7B98939E03065C1C74C2736D373D55BBD61F2738B17A12E6D48918C515E64B52B729C4E25DB55A4A1D8549AAABA3818174486E9BB5057C02BF5900CF3B3526C2A2A96DD9D4F9AC35C08A33060CD7A57F6CD8AACC2E30A58D6FDF8546F730FA3AE4A0297CF41A4A8B4B3C0F768F861FD7D1DD7A836AD5B102A4A433001E71C6D36F046926FA2557126AA478E605D9C66C020A4322ABFE9CC1FED99551C12576275F8033D4C8850CADC9EAAA2229DAC35C363EE21600C90DDD7CFBF171F333C3F0F4A3D0E7FDA4523A9950DFD758619159C38AFDCE35E21065EE587747D21311B90E0766DF0D94527C07CC187B439C8B38D5979C8AAA87714EB31AB0B0A37E860E5D7C87B22A209ECED96A08F8C4C6D10ACAA1E3FFD3E805546F42851114A950199B5E2A1ED7FB5036A0D670ABC0D211B276236ED948FC3C747212E424F858B91BEBFF5363C64747B9BB60A2240586AD1D311A9B1BFF45167B6BABFC0CFE44BAE00000000000000000000000000000000000910171C24261000000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 18 iteration(s) +mlen = 32 +msg = 7200000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 89E3FCCCB519E7A1C60E5F252131C30DD25D9A20B32CF6B2F0E281E2D5B6B99044F77DE936046D11D13D89670F1578491A329A7C9CEDB7611ADD5DC3FBB4DF1B491E33ED7C40B851275F296D77F2C1A8A64E98353B95C332FE2AEFE674AE9288C8334822FB6C42A58465F1EA2989ED51E462123188B529ADDEDAF07B5F45236B86E0643CD3295A5391D085FCDD49ED6A1172ACC80FBB094C5B492B61AB1B3DBFA0E095394A5A3831E267FF606BA17950BEE38192C02C7E56FFEBB85C4AAEA630893B41938CF9640FC150ECCFF4E487311B3AC97A9CBC51121BD3EED73365052E38BF47192F9EC21219430895EE224D467EF2EC36CBED2E3056BCEF987130CD5C3C7D8C66A7B06E635D81E482C8EA1C7CAE12BADBD6BD1E9617B04DE30A76353F30EBC2683F9DD64FE9981F1E8D25B5AAA294C93A1EB5AFAFB477717ABDC9677F1B4190EE2CE8F1A9815CA23F799EE73A1DCB32682CAFE18375832FF1D02A1AF90124A3CD307FD712E6184D2ADF2BCB6A55607C56EEDAD38390B0DE19B65589D765EC43A8B9A0830A825D26FBDF22B70A11586A301DB6B94CF45CB3264B6E370AA6B346E0AE0D0DB54CAE4CBA079456732106789D879284E1F0DDEBDB7896F70F23B25F984FF2F0415A96CB7422FAFB88767A28886FF8096F15E8761541A17986CB47938CCDED129A6B30509BC3B6161F8E0C3783024CA65C4FE4179C0D4B701C6ABDE8A27423D3BDB5EEB6B693AE5D357F5740E3051A3697CC56E18501D1944FBB36E728A1C6A25CD7A6C463B9CA935691871F3733FC2E9841BBF6900C24A08E09FD28D43FEAD0A5AD656B2279895231B3F7A760C976F34D05E9FBEA5E34C8D5477126DBB5FED21B5F30C415772DD2051149C3F68FC8FD8D1952127C74B3F394F57E323353B4BA41817A3B98A9C862D09BD709C1A58E97B4DACAF6AC977DDCAFC5E9AE8142D63429078DEE03B61A096C9539F7217144179286F61B18C6B4462D592CC40922D5B4D645F2967B5259B6629741B521DEC58394435C37CDCBA169D92BEF5DA32BC4E910E907B65961BF07BA3A0E99B699A0D051FA5FA961EE605F2F67C4AC5EB8A794215DF11E666D89AA1E91C1088D7C80CC516045B793A0E516E8C55F0B08B8D85DB1F2C7651333B9C9AE00AAE0F2EF406CC55472A20DE3C0BD0D53651D54C4609B4997E6C20F8BF7CAB11D1875362F84697438C09059D9C690B998DEC9797A2BCD730110B52A3618B911C535D3E75608825E3E51FBF0ECC49A4565D506C4AC0CA40699081F4CF7E9641B811B7E9DB7B99E07479067B82A421F114BD72B87B48A362EAF90FA33D0B064E5351811E722DCD6044AB2153435B373A3891E05C15A74D8350E215155E9481E4E3E187E6F7EE87BB43C34668A27A044AFE988A2486CA1299AAF0811F7A7638F9DEBD17B77B6A7062794F6FAC860C319E5C3127890BA6A9A783F01F81D1AA757FDDDCF9D2307B8F2D9A0540AF771D00F6DCC36FD7279A0BA94C280F4BEA00D43B181EE7674CD09A5C2E0A369BCD7F7166AE1F9BD0E92C3265E62C72308C9C358157B0C7A2B4B9C62927648799293265CF1981A67B8D46148BC5E619C0EADD3675C83753B3294865654FF0A7236773436E0C271DCE2C35C61CC8DB3A97683E14C2D5CEE1FE08635252A16F3AA80D9F7E80CFB535C79FBA5B52153E96C884A0D085BC02C31FDEDD1B70CE9E4312E7AB12893F55EC3BA29EBF4D8923FE5396E7DAAA5A9B2F310180390771D36D85B733BEBB56D03DF990AC69F7D371FD5BEF121811A166C1E0BF4710768B004EA019FA8A52C970C492006137C864AE8ECF9E1A1BBB97E513146D4D21A58E0E739AD75AF2167739E92912C59790E3F296236548BD13C05436695D3C1911A523AB833F4F28BCAFE633E8567327F3112F664F3F63209E55F3EE488AF6D7D281FBF15FA73D2BEBD0124A71309B41D47BEE8920F498B961A7702971AFDF90E37D5C46F46D02F5DEDD54638F5B169358F1AC9E58A5EE745CE6C342C33C76E3288DAE0FB5B4C9FEC740B3B141E492388F7E3F274767A8AFB4794646858ABFE976597906AA8B4B958F118EEAAFF7D94C2950156456984D8F4FEE7CB60EBB41550150E1B3B9519FEFA00CFB20FC66BC44F87C9CDD018363DB42FA9EF81A7679D37CC1DE7480B3F6F78B92B5A09A1314BB0D90C8DFC8302ABBFAEB9008F604A1FFC600514C5C676E414A9B2BDF07769DCBA9C34F37F1E7EB3E0A5AAB946C633BD46877BB84B4D742617E72AA90D89F58D1E4DF6C4C550E4EC5C99F7B0E093DF5EA492B3AF72B6A7A41042B9CE896C8122F6E35D1E8C6F0F52150891B43C19CEA1BC255118C824BD1760FE9D9D5FDDC70146592547BD87EB077B4E8E81AFDE392D885DE9B73A5BB02E7B7C68581C02B1B5E38B68443536DE2F77B694E7E74B933A9CD8B76D8DFDDCCADEA4410A2B94C26F8E948E92A7BF5469E75D426F1F6F85B1D6CE46E8820CF0649A26B1AE5C4A7423D304BB2C2ECE2C84AA805203427DF2F0FC0057EA5C702A6BD67B187E131017FFFB93D5782A7E11625F6B8A41D3B53F3AC1ED2598423A5AC0F084D6BBD92A41F6BD2DD4764E4B865371F240E9BDA5D68C3BE3F224D9236C3ADA888105CE0B053F604A48AFE7A02927BC6B67B2F79E5F73B4521235C395754BDEB691BFC1DF3740F1201AF277047A5907ADF4EB26BFB55CCF75BBBFC81C58CA59B5A2D2A53DAB03341898AE908F64A237FBBEEFB126882EC3974C1E9F97880AFADC572A60D0A568C78254075C7CC7B1782C41856EDFDC27D45F8B30FC47D9E68523C62F8D3558AE0EE252F5F12F9D8D607E584D8B9111C6F7F812A42667ED21B56F0228E4A28EFAC770D015E88CBF8B9D9EA380867E61902E6CAFFF7EAD38AE60BA104F83BA6ED775589A7F782B2BF3A44C5321F217B030FB716094DC39E0D7626FCDF24EBF6C53284DBF54C97E8A4F305210FB142FF9EAC36EE75E9577A989836954662645B0B06D05E2AF26F209C67149D3A8CB4B87A040991BB619F9459E3F6A809CBF8C3E8439245755B27BE0FD0F344EF6C13C579B72B3B7DC995985CF834ED07E146280C8AFCCB8DCEC81D92FFA57C8B3A571E77D05D757DD6043CE3ECE5C51E6BCE0A9B704A57422943E333D20B8870DD492441094C6EAB058BDAC1A9F746F34E6233DD40BC87217A2D88DA0361239883631460477320213131BA05F9C431DF8BE629051E6B13FC11A733AE1CCC71BE9D00FDEFC788C7F76CE0FA0D084BB12B5AD57B5E9E1C566F5C899FE8EC9CA04051E9A8C36F5FBDD7A2D8824D601812DACF94A33FF121A853B97F0973945F4C09190ABD545361B9C80D98D47A7B8EF225E19DEBDE3FF5364290B416B09C1F59EAAB0237B1CAF199CBA737737AA3630C73ED1B81B787CD5B7EBA372A6049882C9D8EC64D467F301267361E23BB1E56174CB0513981269D02EAB2D2A896EEC2464880199CE2E1848363045D65C7B63222B4BB7C1BFFC76B371326F7AC2882389F58FEE8CD2096DCAD410A3FA1C7EE2A74AEA61148E7B09A1F8065F20C627F9B42A10EA8FB23EFD4A723A580619472F81A07A543917BAA847C92F7BF106D6201CCBF577061F10A904DA600EA23C986AC2101CD615B5492739D876BB301B41D92113402B55D06EF6663205FFFED61B0492A2C02895FE023768837B6798EF7130A4C24403ECE37D88F25E966A12BC9E33F359C5D0EC0BADBBF3C1CEF1D8C3C81B57F4BA30403A8A89D0CA671A19D768CF8A056EA75A3769A840D6A99FAA8C7CC160F784BC055FBAEE457AFD7295D3C42F0E0C455198BC5CDD5683670F2FA0D544978D58CF7EAC45F4E2DDE9FDC0AB3B66B3B94148D0B9BE9968101D35B8FE1C651287DD8BD5192CC85EAC1FED8FA56BD1EE425036C2B494D934FA458C45B014C7AE2C849A79247833B222805C98EFC232CDA590ADE0124610441615ACFBCC43E2ACA3DA8F7A33C0285DCC8484344274E4D743540F5A59D22B8A64046B2656E5E814988BAA234C2688A7A9D2DF51E5AEF0D77ED17B29246377360AB1471BA0975EF38F26E975D4B5CCA86144AA4A32C41F69999D6CE1EAAA3C12F9C32CD86E0D18C715653725380E2B9A05E13CB9872F6080103F4D4150D454230AED7CE84E26B3F9093B3CD616A9F94FFED023E498562B1C85EDA02C88961A752EEB654F0588D0DA952AA2F46C580FC07D83984200CBA01BFA6C604A429E1412B6A319B05789AB51E4732EF0A04B3F48B5014419D9094941C1A56647C6C41DE617543266357255CFCA5E6561364A7A4688096336FD9DAE450249350AB57C5FDB895E1C263683B4F0F5EF93FAA11D3AB3A936DD7AE7B2266A3458B6C61AD4223D190E874A25CB789E9A9D19F0C3C864BAE17AC7D5C24613FCE2CC010C2B07CB489012D0CD214AD0BF2278EAB207AC4160021468B4A1BC4B2A31D322BAF1A59CD71C79662D030FD6FECF6F1590C86564C064BF10D1EF3A876F65273928DC0F06A01586F856BA9DF0AA5FB852F15D33FEC277A3A33A79F5FA6CBFC3055F28FF741DE987AC9A3BD1122AA7E1B1CCB349B45075943F661CF013FD211CF24565175C87D860EEB422C09ABD386A6C2D50DFE606151C3176A8D0D90E1017519AA2AFDBE7E906094C821C4987ADC800000000000000000000000000000000000000000003070F191D227200000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 19 iteration(s) +mlen = 32 +msg = 5000000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = D195B3100A492FD1F03970367C4D07E1284C8A322712615C275D637C9B96DAD2EF21121F912E61B7CD334775443CD28EA75A5FC9BD34FCC95147DA63ACB8D624CEC3318B1EE120B993223D41274D674D890D19BEFC0F7D36C8AB3B652D0D998806798CC679914C61F6C1CE9D673F77E050FAE67EA3BD4F39D7ECD599D206BFD07D3ABC228921300CCF5B09DAC8953E2683DCFF870B14CE3D11249DDD92697B129A78A662A064F70326E3DE7DC138C31E4384B5A6337028943E1027C2C775B424AFF4F19501267E25A6B29B71909299D0054C9081F62130BC741BC3C26460AE76F6DDC59B16612F965509EC9E1821090194720BF788172D0088AD9641C56AE26B34AFF89937FB35085A213957EE177DA345C391D968255C399E769522233E914B164010A66BEAF2925BC54921979C3BAABCAF5E8E0011B4DF4713AD14FBE0E83E13B1EE808C17924A2BBADF06A6164B2EFA23A43CBBAACFC7B573A21ADE3E62362A09118F63588EC9ECC5A496B293E5DEC027DE91BE7AAA8465623ED9451614CDCF9A2758639B410FC5A17515E84B0AEF28401D26D27ACE64DE1E4C593F3D9324E1FE96AFB7D5253BD4E0DD6038EF476B9E113B098D3CB28CA5DB8A1FC347A21B47411CB46FA0D0D25EBAAFB8F484F4D74710D2FDE2C689BDE16019A14E7226B4D1511A8586FB1CCE623584F16B4532A3877003C0EC9E067A4031E2919D94426C4A1DA9B126E64A5547884019E1556662FE591AA19BDD487AF5D4D60BCAA80D156140EBD9D028F01BD8EB526B5EC1314FBB72C945DDF1D37A154D923B13F4E9C0D082B9F1568F2EA1F3C63B5BF1E8A8E53FF879CB9012C2ED3D9E3CC03A4C4DF80C376AA20140B31EC67026049DDC3CAA0A346370915641039D80876C4C9BA492D7E53184D75DD91A27B6F4D6998AC2D1AC678A01BDB31291E7E2D54A0EC5CD43E9B345AF3667B1E7572099A907256C7D24D8779988B0074BC5DC7ABE47A19F8B55E71D97EBF88A79DDB2E31459DA9551B9A3DAA3A4B5C2F880AE6F5A1281FECF9FC551BC4E7F28DD2106C03CBBD9C2B2E431849A74FFBD4EF436B89709EF99F56D5E0DA522B244B1DD9E6D7F40F2F406427D3BB56FC0F104CCC4B0D4399072D46BE4FE8E3571EC282609E5BAA75EBB176E3FCB1801F12484FF84A19E420F562B0AC5BD50C4C00A2807DE8AC33DF85BB8696BDDB44915E3F9857B375328D9AF4D1493633FBF0249014117823B2328B7EEA84FC9A44E77E3A407C3C247CC339ED63E5DF93E59212B57D36C631F8ED932DB4AA4D0D1201B9EC5FB645165E4B3C331C67693EA81C1877A96CF9452CD384ECC8054B067382F9BAB4523F494292A112EBC63CD768DF87D89088F7A2034BED8B3BCFB08BA36D08CB5CF935C00DF9B84691AE61A8398102DC1724F1BC67AD07C4E595BEA160E282849C087580F6128A4737252E6B9652F7B5ABDA7417199017099D30EA76514CC169B199FFBC48345E29F13961405670DA7294AC9DE9F0DA0FD13A47F254A1C5CF8090FF391CA8558034B624E4508A9744A1DFFB92F42D02787FC34B2FDA548BD426BDC657F901EE220E7A5729EB0B889CBB851AA1773F99C51176604D8F287D3BE31FC91FF6737B6305FBDAA3E80C4B8DD9796AE2DEA6DBD2D9E97FAD0E6A8952EA8E5DEE06C2CCFA2AB7CA9FAEF5A1BA3BCE786B5B1D62266AF8EA4ED35A885D445C9C0D3B979282147130CC9B0818F1535A979D9A3849ABA98807774EF7445288ED5CB8C3124EDE54D7D9A34C35ED593A32B15FDF288BA498DF82F6A348BA28FF3978D7AE36334B63EF873A2C638BD6CF921FA4E1688FF425D352EBB8C1794E512C8A96BDB0A50BD3268FAB4F12E10C099F4871947E1583B847281760E497B8D8152B9D83CE418CC67F21C465042B70F63098B3F5858B0B64EDD5F4AEE6E121A4B1F3CF0F079764D716664CEEC17960B1F4FFD9AAD45E1C0399AC204F858045E8F6D436CD4AFA788DB43B26DF5BCB8D7BF5C2A78BF59E1ADDA41D7B3D2FB6774C9E46FF83B7993A708F75855C8748AA9F121FDA369F2565E4F7DB8DF3568A8ADAA743BBC01F919A7567EC675EC0326A73E930090E0EC168B8FD8F0AED26EB23216EAE57F8081502AA2368D74252874782BDFED800568C8327480AB6EA3223FE82903CB17BFE43FC301476C7F49D23417D08AF26EA61F106FEE4C7D49A4B18AF0307C77334947B6014C29385E0613A85D618814D40806BDF0B8E4F4D8CDA6399483BEB0DF880DBDEBA74BD81170CB340FCCDAF6E3B862DFBF89753F57B1D6A5384633A15F33B83D368AAD4D0B21E850909530F1AE483896BA28544822F9134C58C7A13C75EB2CCCA3D1B5E645ADD5E4AA696358DD486FA42FBBFF23D73AA4C27F24AE001E314A969F349F3650BB2B53567061CB9276A22E568228629106088E4AEE0885FE5AE5B4D54BE6680218BC1B63FFDEC229160EA32F62F2A7F36FD37049ACF0C9E42F13A601B014236292A9E8F22C02D564BAEB71BCB9F57B91F0F455F98ABF4BFF9F57F5C390FB3F4687170A7E1AD49A40B5A61EFF0306862B762F43359C247EBE045FC6ABE3FC21159FF533A038C6ECDE4AC32637B27028E285333ACC7635D751A24D01834E0E142D8EA32455CE08D03C8FC180BE64CCA4E17FE347919BE46B51D83233C6D651C6061BF43FD1605B38AB4CC215188C822C899354451E8F90683CA97D0EC3C8244939389981B689F33569645102ECFDE89BD714F7CC4269C218FF56DDADF455A377B04F375A1716069F79F5F72E5AC8737D754934B25C1D175DA27D0443561B3B593EAC1E3ABDAE794E47DCB8CFDD77CD94479794CB08A346AAD446B7F0AD121B281F69486029160E3A0B2E267B0D35FF920DCF16AAC60AC453B6CE7B51D8D469C15C28EE409165379DD0DAE461C440A22F18C644B6444296C2A1CB8442AD1B21CB67BEC20949057B799D3F5D38A7A06382D70A728E25EBF46120333232DCF2C89B288F38A47AA4AB9D599954E7F39B8863AA16E34FA38B45195389A5F396E4E35F635F9939CA24FB6F1739114286D4BF46EC439F3EDA4F126B144B6442B5D64D0A8CF96D22F876B1B2219CA966B87546DE684ED6317CBD6EF324DE398EEF3C39FDFB8FFC2FF06707F24A659F9E544DE6BBACBCD2E84F59C240D1BF852C59A8CDECF61CE5D630DA04987F72EFC58B6B90703235CEE579A2EADAED963F7617FDD088CC256469D8ADE4197B6EA019B0E114EFB98B0F78C4FF836F7DFAA8DBDC2C3B7FED9C4A4CB350B62591ADE1BB881256DC746D72B7B345482A704F52745AB80B12A55EFB83E9EE8F7E50F19672C2AAF58B7504079590A447D4EA9ADEBF13720FB366840F9E41F0C128789C1AB41F2E736A954AADF87AA93702C82C541895780C41285E5D5A42CB5252AF85AB70889694A153850900D9E7B696C39A6026BA3AA18EF304E7B99EA209456959F7857DA264BA4D707CB2FAC183545BCAF89844EE448554EC1F124540C907EABEFA6E7BAF56D7ABAC473E433F949780B2D31B41C8C7DC597E6F58A1FB67F8D99CA1565622A4495E484384615EFA8A1A3BD26D1328447791895CF82D14B7E9AA490559854C1E7175CFFDF93C959896C74EF2B25C1E4DCAC32BEEDD50FCB92481C255DEF447A0C0984E3A8F7839542BC8E5465CBACE449D3AB75E03A39F59C8DEBC8F5F27782D425732FFF5A3993A45BB0B26D8D929A7451DD2C1837EB3969168DDEE0FA9B3EE1664B9F6A4CE5971D02EE990B58896195A844A740EEC9BB76F90733B78A5E6C65848669E5899F049DF2DF8B7F6B1B88BE4357D5555B4B7B7CFCEA19CE5E48AAAD6D1680E8FCA41833DEBCE5BD8734773EEA6B237E9A31906EF4D7B29F832FBA2F14F23E7ADE4D2C3EBF7050F8633FA01E9C0E260FAADE6B980A7309E4F0B16886BF5BBF1C4044602736A754D459966B747F511A7A20C52BCC57AC4586FC3528DEB0897C37BC9CF52E71B9206A5DA2F1C594F4FAF1983BD9966CFBC2507C601883D57DFD23E87B86D75B7D37213D0141B06539B2D6E422527437092913F423341437C683B8E5054BCE2140765D4919E9D1E9C492D7CD56176302CABD608B52AD78A2E83EA21500769E1B16B29717BB0808E27BCBFB2C31DCC442912A43F3BDB4B9FB0D929D6E271B67620233C731F5835C12615C01574951EFEDA8C75618C79DCD957B9C72380557E9B9DB7D8F85C64BE2B70AEDF19363BCE90EF5015CD20ADAB909A8D155D9AD1AA0EE714953EF4DE0D705EF616549A1F78F36F3601253984CA67880F5F2F1263CF4A91506ABF6D1D82D1963E2571B458265A1487E1FE3C9BD2BFE9FE7580462282C23A15E0EC1765205D074E3C90A0B541E11871E932E054815415E74CCA00BE74194C80E66E99D754FE39DF2CD73907251E1E9A80BB80CE076D889416A9A04D6279D3C2F8D289E0645356BCB41AA0ECF3A3FB70FE4DF4FB4E8C42AC6683F5B81FE346F9A9CBE2F420F12D67777A2BC1FA17F85ED62A805F7A629880DBAFFFC15C9B7C28EDA4BCC6CB988C3CB10815A2BC991E7FDFEB08665D0DA9CD66A7A8EF8EB5FAD7F879075397AB60A01C0E5D2B9490C38A8F9A9506030E1127A9B5E5E83279BECDF6072541535B62A2B6CBE93C65666A73B1D1DEDFE2E3EAF8018093CBE1EB1E314970BCDD00000000000000080D17242A305000000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 20 iteration(s) +mlen = 32 +msg = 3A00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = D5D4C237111DE3D767EDA7B22CC454DF422BCF03257B0C6F426F9B6E2105862D63652590CC4B1E32C6A257EE0F6B0CFE50571154C5623C73C73E1BC93EE850D43E14C34F1D3011001B014D9A4AFD32ABEAC0352FC6D15471125B6EA5040ED939D354A7A37826B3DC623C58F18A61C426D24060521ADD20FD76B9D97D79734A4A5A32AEECDAAD09D8BA0D941EF82D62A0C6DD6CF9D07FF00D547607CAA5EAFE45CC4E8AF67A1E40356FF0C1681B791325C1887C5EF56EC8B0CC7F5B881C6D4D0BDF6B8B589E75E5CE3629B565D5332C291755C8095907830388D5CE3C6519BA5161039655D00A73501ADB9E25B56A7F37A1211BDBCF3F6D1ACDAD3D9F9131E43B3EFD9914A8E822757A2C30A92867D1C333A9728F01C1AC931710D86E05A85A9B635B8B4E8E8A4C15A981E1907BBFE333F7FA686493C366ECD0EC101910E1F0003815B6F7A9336D5C6BA98F250D7760503727FE0D51826AB9CDE573A99673A3154356F7FF7E2786958072DF8C68607FA2DD1A15892887D39C4170EFF34D0C4A4CC13BEB561C5386909D734B8811CE42A44D3FD90C64D8DCF5BFBA0DCC1E30EC5D2CF73DB17E7903C6C1AAEA40FD74BADF28BA195FE12591EA57F424346F2FDEFF968AAA9B458AB9FB01B3D6966FF6309058F498A213F733404AD82697F8B012963BF5A478F71F926FC82D0F5ED8E9C1D6274EBA18B68F63508227B4D85E16D6577B8F16E0D218286D4DD23D7D4BF931E83EB825FCB27FA3FD8CCCEE8643915885FD35E57859C6EB50683746324CC25BCB6AB260E06247F99BBF3FE679B84B594A7C992685A0E4E78EE927B1C7845206A2C47561B8F8B5D3449F866D24287C1E7F8ECB3099F890DFBF481780100A0D8405FBAFC4A93A74E2BA2BDCCC2962F1CC33E453401880398975231173C0F0D476DB5508E6DE861AF42B48C7BD3F6B685EA1290B7B559E02CA5D97A24588E3C93830F7858D2C3A9A58BF7388C30392BF665BBFFF7995FC3015E58EE8AB7C169B681516886E30002BEB3BD37D7CC46A41E756F321BB9E5126E41EA9E7052E50BE777DB79876CEB71C49E9EC8BFCA0CB061C50E7930D4BC345765145EF81567F13BB7F5BF50E3F8944E92415166FDB8F1848C8CA5BD4817D5B85C9FF97D54FA3CD9D5767E3A33D6D7749C26C4AC63F84A7927BB952A16C4ED7B05FC5F648A15443CE3BF36730EA9C44740948BDD7803D99C2D00DDD11FE682424FC767EB9A2B99B1BB1234D2C8DFAB6D2EB132C10D5F5E56938707784BD89BAF9E4BAA281F3EA7BED42E4E4B859EDED26B3B7E5C6953EC9C9D8D7ECEB3108C720C898BD639A754B5B9076DA4B827BBE2177D807044C805780D87E7C0029885777F0438D177F761D19900ECA270FB7F3A5BD603963A1F3E247EF56D120D2909A14B1414B1809AFB632ADA9291989CC84D53689A588A67A9A7CCB293C9209DD8C06BB5B9458F655E95978A5BC3DBF65AE84CF6B556D7EB52119C9F7ED1E1A9FD72432CA2F372976366C00BDDEF0F10316210AA1331D6133A81A929EFCB7A10045F597215257CDC4C1BDFAE9C05FDDEA982CEA4423059D3BF9C657923B571CFCE925A051E7DDFA5C021E1A05D109F41B1A390E1F3D4DF8BC428AD3C948A1483888F3944D3C512D68D0F250A9203FE6F240FF3ADEA30343864D5A70CAC82E00A292A1496E0CEE1BB4B54F459570AE0F1E578CA2B9809182371FA90AADD4A1511301F1121E07064AC334D59F566B3326FDE27B8954DFB1E0C3FFCCDB0B17277353102DCD0B4A66FD22FC9D0DA0E31FE58382D036BE2F373E504145BFD343D8C4CA31D6B18C7144083A0DE8944261637CE323213AF02048400F68B6BDAC8B0BD38075330BC452D33B64B574ECBADB28E7A0E5BCEA64148C37D4E53F6BD70B74AD1152D5F0288E1D02246EBEDA700524C64A53C9270AD5A203ABD3684795EA83E0E46F377C2C3539E267EDD0531B52567A4C6B22A9F267586DE28563F46FBCE127414F69DF2992378CA7221A4D3EC40E336A99EBAFF2EC9E0AE500DA2944DD3EFEE4E3DF1C9AF4461BF2BE79A400E0CD8AA9437817BD4FE0919F99A8ADAD6CCCB02D9ED32355D539387A1EBDCF47DD542CCEB56A0D3638498173FF7B279A842A96D61B1B09B3CC9FBA0BBB3DC97F3CC439D065AA81C56C94BB80F61CA96DF571E74FB2ACBB123348CE8B8885882AEF8A59D1ED4C1F4002BE0F338336B7DF6A0E60C8F693C751265DE66EA247181398592A274318AD749E4B4239F5BF0C386F7110FA6C3AB0BAEEEE05468C56FC81F97BE4FEE082D6F93D9BD615C4ABBF3DBACA1B8DDB3862521016BEAFC9924D92DAAC52BFEADF6DCFF838A7304ECFD4C7960B6F87C0ED22C958DBCE8498C601E18FFFB839F2FFFD2B0C7F76F9BF109324109EF59735500838188BD09439149845080E37BDD032DB9B54D0AA6912CC84C75F5E6A2970CF93EAA0277722D4DE868869E2C9B4A6B257DD07DA582ACB32E51336F204FF1A8A95DA1F519583B63D16D8FF89F127177D31AE34D669AFF049D1314EE62443FF81BF1A9817A7EE6CCB23ED801A2C029C90042D6138F8955110149CC15A6375246882E041952E3735F087D1BB78380EBEB3FD785C8D3EF5E58CC6B5C356BDEB1983632607928EBD6763B77DC5A42D6B5A145BE0B59E5F178AB83869CCB335B189ED35323CA4BF8E8573581308DB432D40D10AD5D2D1DF72C35C06B4CF78B2345AC9F9CE5BD648370E42ECBC899ECE3D647090F05D0AA07487F77D8BEFF80A694FB491084619B7A147F3AA900B1877674873B9409A6224D7BC70558084FAAB2DC7C22C880A1A41892F342F36D121B8957F33A9032605F226961F254D751CF45B2E74E8C853313BE3268C03978B4E95EB100E846E9E37B932A4F6A4F29366858856C52BDAE4339E4FFD2715DD3D11E03472BE3145C97AA1B04277FF7E236A90DD6F989C5F571801C1AEB191CDEDB744357D984DDDE14B32748AD80365A6C05AE217EE7D166E1C47E1501C4989678B35DCFEC700F9CC86DB534F503216EA70CAB8E14F3D4463651DED4BDA83FC7E06B1288E36B35BA85CE6368E2CEB82DC63FE092B35D236A9333E980272E6350C78DFCD36CFCCCD5E4F84848F95C559F36E921B75A8E34D9D190542AF7FC129AD36067287AF55001FAAA2FF47348379CDF4DCB9D223B7BEE63DC504C0B08B6AB6870C721CE320191E20F5391000F0588913A6363CC770A106DAF8DC981E153A8914F230AD0DC2CCC93085BAE61879D7B82B0BE5904E0E5207116FCFA8A4EEA9B744CE63BA82DE2CA6443FD76BB9E933760C3613EDB04C0A57B587937BE3C70FFDAE744CFC763C0B83A298D8FDABABD26FF1D5F5059E74D48132C029D6766139E579333B97632B7DE40BC25E83B9109E2BFAC810029B3E0CAC37A616965C81F473E3180866EBF6D7C646581C8D857F5AA0D43CD379179C9F52C18DD7207E6A95E47B99CE7FA8346433C630C5EDB827E0D8F909B99FCB7C0DF8E40C29548CB66459068F58EF431F8CD5EAD9813958F06F9C8162184FEF9C546290EE0EDF0085387F0FACEBA71F5DB046476BA8824F2FB4F8C162B5527BC8E3CE372331057C37CB1D054E0800440E184D126B45B5A55120E9A3C524F8E34869C3140E1D77CC17C34819D392032595C445F99AB002A8481971A148EC34850B9850D69BFF5344135FC85D412A8AE5F5ED663CA237E8222889E9343F6C53DFB9C85013ADE360BBD67AA546E69E6D9E9C5D0976C02C5E072E91DC82AD16447373B0E5B0D5B07BE4FBADEF9541286C964BB210A7BFE8B8F942AD9748D6763873435E97B8B9D18CEEC2CE397222D45FD4BD75512E3A4E67A2860F64EDE81FF013E1A563A4253C228CE8D894F216AF05C63405538BFB4FB3074606ACC8CC4ED5A12BEBAAD8D54767903661DAA206B29461F4565CBB453FCCBC9559DF583FAFA3128022C8C30D5086CE446532E2B448A75CD95C449A7159BC3D7475DAF6C5B72F1320CA85B9E4F1A8BD0D95D8BA2B66B1A23F6F83C1C34E0E32FB56F0FCBA0A0D790CEF1DE3543392C93688895FD0147F3949F1F93DD69C08CC282DD71F2F93148EF7A4E1A83FA8BF0E83041C3822DA6CD6B8E66915AD2074FC5430247938223C0368FD367C2FB19B6BB3E59EBDF17F5F6B9F0DA025BC3A1BD237ABBAA1970CBE524271008A6E8B0F86FB8AB57832B1549BF060DB8CA4BDDCD587131E61D01214B2DBA739290B410A49EEBA87075AE899EB7AB7D0B22A7677FD18C205C48C2D0EFC5250D3B64E777688E1DF8F8F251FF73C7B73D01E06A1DEDB8E44ECCE22E5F23686F54EA59D3E398D6F38D9453FE571F9CD88AC21A5E8AE089FC74D93A02360B9267668D285F8B81153470634F3BB938C5975C62781D2D70A4B5540CEC4E4AD8EEA549953545CC98F761C35853971BBFDD1104DF872C4A76CB7C72A9273B75E48828D9EDC7950819435FF5148AB9A1069F429E6EEC43733CD5A33F9DB1C19F3BB54F6B4C7E1E1CE90E60BC1B9AEF5FB65C3D3A041FBA21D7E36284EA4CEB0CCFF7480A22966B3F7D1A41B0DE85D6DCB03E244628E56938EA4A2A933F460A1007D6DD3974F95EE1849A546539ACDE1E441456A919A9BA00F20257813B4DE1F4E8891B3BBFE4564858B92C1F4000000000000000000000000000000000000000000060D11141B223A00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 21 iteration(s) +mlen = 32 +msg = 0301000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = BC69835D4DC26784A0325B8049D40E922955C61B21148C20D8FE679E4167F21A10E880F6C75C0FBAAC2994FFE766613C65683672413C55A0EA88C3DDB91D53E1EA8312D8A7781E611C7355945B8EFF528A8623BAC8B3EEFE0EC5628155CFF355CC6DAAF158D459AE496CD3648F8749D08B8AB5359B8B62ED52CB6DA031819D60F2E9EAEE9A90A354EDD6715ADCFEA9703D240BCB4C9390C68C4DA321E7C06304B7162F6A87F0AAC352E2CF4875EDA31353BA980D1BF7A4516166C2C4CFD0FC0B7F5C00BBD520786B969AB57FBE151071D0AF22F5CA50F6BA63005A04E0B2C8578C694BF7D5E7E5AC6C51F02C242623CFACE4D85EF1B3EE20A5A1D29642A47362F3709E0500D5C62D1CF155C97A3470C49332147B9060D7E3FAA7AC06EB71946D23FA8D25AC0E6A314471679AD27867D4F19A17FE3C4A60ECEAD04B1F706BD74562E04210282220F268ED1EC33F4E5EDCC72BFE09B3927358678F0654539503B3CE71346E0BEB86DD74D8FAD3710794ACDA646F639ED99BC38D5916EE939C7A230CBDE69AFF3BBFF6DA1A3E867F9AD8EC1F02E529A34DEF407A4567E055E65D17CF9B4DF1C67844163CC4F0422FCF1879B96192CA6BCC6EE361CEED8472AABDFF98A68E3E7C8E3015B36A323502EAA643626563FD9FCBDCA779214086084A829EE6E3FBA9072CAF18C69F1442DAB9FA5FACF0970825E7EE57F2DD372E93D9CC921D97C4741D8315CC8DF4D1E67115A6DBFBDDA45A2235C1334422F2B9AE523270A8D4189C3A57B5E3BE8F42E1CB1FD2BFDC56658290F737A72DD088A894CB2C3723DE2EC448FCD05B20AAF1F6F27464260E5B406B987D1249AD9499EF56B4B7C42FB224336C5EBC13EE060CF1C81A63A3FC79AACBA7E5527DC940765199B5F586EDA057106732FE6D38D75B3676F2E1CD1D607382F943C30744DCC903FEF904AEE1C7A48CB53FED2B7EFE5F886F7FC4CB37E6A14B540953C2FC4CAC05F03E8F88CD27A4A174089C713A673BD46A77D05EB781150062DD1144A37FC66B9EAE3E4FDBE4BBBC53A639B55C5BEFDA2F6DCEB39ED5ACD9D613B3EB340E31555AB945BC878D44C80BC48E58412614277DEF3CA1F41823622F7C7E14A75C7D1370D7A5FDDBEC7438962888B14A84897D6831780D6E5C7B120011F8CC6C4761E1D7706D6ABDC95DAC0627D7C00504630CCCBEFCCFCE7292CC274326E9203FAA904C3D99957DA57AEBCF0EFE62230A1AFF267446A6FA67CFA3912C395E49A25D9365D4B9E9AD0E30276DFA497CA24F25E7139C2389CE28D750342371AB6E2A1DFAE9CBBFCC5AA5EDB1350C799B36DFEA285EF252B4161A8C5EA08AB8893B41E4EBF7A220358EFB3235BFC74EC1E4846BA2D2A176CD214A52BCF0777FCBC9A0EB3EF5AAD7F8F2E40681A170BEC00A25FEAE9AA60EF29D14864D6DF9A82073176F42022E8142E59DEC8C583944E97FF8CEA6E4D6BEE0C31CA86C8F1F4A45F2E01A37C80FFA85EFEFA18B68C4E5819EC5529DDDC39EC9B160DC2F2C20A7F6F483E74E3540D55A22052DA34337B0E15A2F53BA3D3DBD74D7179D979C32DF25E0992B4EB5E71D1853CD476BE0FB6581E93C44A25C51B5B0B2D0DE536D42966BC8757A98337E331CDBD7374E8E9A1E55C140720F995D6E59FD9321477911B14DA22182E3CCDB52A1C2299956FD27CD22D4FF35167B09873CC28045F1754A4D2EE5631A3A2A848CD1A5E14C2639D949169C05260025AA6003EF2804D69D92F96AF7DD405A95AB798BC695C990A301A4CE0321CEDA4026300883385B6356433FA0EB81425E53040C78D75A2D28CAA62C2180BD2CAAA543295C67C55F3675BC1BA4E4E660B60B41F3CD9DAD43885C5FA760957D826DD3E1C88FD2C5C0C61BE9C4FF918D0F994246E370981D7E944D62AF48DA8B4E9D6E9CF526C12754C92E8D58F7CFC3FF3458AD469D89476A4081ED1A71E15814CFEC977F9904EF570E933C19F0D87F28CB009D8959FB8FAFA3FA26583B11E6AEDAE855D49B5EE0E71B9AB3F88C7342BAAD7A59397DCBF615A2AF3547CC09DB685F2A13BE97CE8E1D18E129EC654899F4BCF2B871FEBD64B163EC52C0FD17FFCA6BCB7EFA6AD0FBDA1F02FD26F6208658C0B4BFB5091196474A4DA16A40319EA36203C3836A8C1B3A173AA5B6EE3774DD6F63FC246C4D41997FA72492D5A05D6C3DFF9F84166D20284AFA4A645DF34F46B7368297305EAB04E78C3E3A955F1C3ADF7226CD93B21AE252E2EFA9819475D1B39CCA27438C16305FBE167B69EF443E0939D558CD1D9BDBA4EA289605B15FF7A941A3A259406F3ADBD28C15DC9F920D80819D0341368E7393B8FC0644F7FA96ACADAE97E935890429B24470E191CCA79CD78BA248EB59A881B85B5F7B85CB9F13613322579419AF8236EEC6A0BF16ADCCD126A5FF4A56D741A5545BDE822912130C79FDCE1D6BAEFC8E235B1077DF528EC1DE808B5B190BEB056B233C05CDCA7466566E2E546C539E1FC92F4441F4E30C5B4E05552A6A0F7087C77A0B79B7CA04EE02675A92FCFC5BE63A1902B8B53F052A87DCD6DB0C79CF77EF7497EEF42E34A095A9F33798D2A1B9BE69035D29DBD8334D7499F62E4A5A92223F1ECB325634E399459FF1CDAF77F61C5AED1D5F46D605D87B091D494133815FAC2EA307BFD8E6E4EC1F6B9CE4AA192BD94F69D37435B797CF00A275893F884C4CE08C26BB4575548C3C9F139FDFB165A02BA5A594492A2A9E8412D1A97F6EA8DC62DDA903BCAD8913AB3FFD96B2E03DC1CC3268F5A7B7298B212816C09EC8C4C3BF5CF6D1F343087463C84CE07F10EBCD6E97168E61A840D2215C62F39ACE7D03605AEFC6D456B816DCBE6D7CC3D77172136CD9121B4F05D433DEC531A677298D268B9B25EFA208BC772E5DD4CF7870410C765D70A4BF2594D6B2037EE2AFD2E73B32590CB2C7F56E135859132F04C7DBF590DBE569AF2B8529A051EA21E00727898AEC481AB55D0D96960999DA91DB356615847EE91147AA9A907183CE995FB7834F37BAAA15EDB3122632CE9458C3DB90BCA7EDDCE97BB73AE7A5F8AC139734F761F64556A9A8F066C664D5774F8D2F28A5543C69C637C504191FE1D00FE9A88DF5071C3D41760E9468040F4E108DF4E3EE7274C6CCCCB8EC08C085F9262E5E7CA3ACAB76CC8AE082B678219B0595C0B4AAD6C6989474AF5FFAF9753FD36987AA2EAE9CAE5714D913E166471BB8E2CC2DEB6096AE16B66857DDFB5215643CD37B6B442A57E886AA9BB966877819AD5E5787730F08C6DDEDE8C7C52195B023C9D8655BD39E7EB3490D492FBBCC465BFAFB903069454B97FF73ED90BC8BE7265DB1E93C62FEAFA8392B65E4FFA521A382EF8A32B58A1DBA2EFF98050BFD251B7099E32ED9F6CD768F0FCFE86250B160CFD8121E808EAD63BC018105D4783702BF7363E767F224EBA5B8698717FEAF2C660FA772C73C0F4304F4A0345BC114CBF0F49D002DF610C410867A7117B60FB5F8C2794E5BCD07A4B7FE849141CBB5E5D6532F08FE4A11B1523332349AB6EC7109E9E837DAB5D224D00B58FBA22E3910AC7158531A5B0A2CA26EAE2B7E36188F7A309D560889C912F92826175F473DF0D3943D37BF96DC91726BEDC3A6173E0BBF035A0A2E61263C92385D27A04CDA5C0325A652DFCA9ADF5F74B3F6C028CD590E9EDF6EB1669876C0E449F16030252C85EB04D9A4B2D3D71ECD277EDDE659B0D11C930713830DACD452D2F5AF5EA7A1B09E50E709983ED6CF1028898E13782980209EF72F8F61D07949962749B5FBD2C09D1F26DF7D2A19AFF854ED5FF0440756354FAE6614C9F2E3B5917C748DA5360DDA149F4228B3F35F0BF77BD3E61456E377D94017BA1C8AB154CADBBDABDF533AC15D1ED9CB0DEC3FFD79FC8CC295CC47EE8734E4773541DCB0EE9B746741376553175E98CA8753C1D66BDACFFD717B0D11C3CB4E04EC4F85BD16342ABD4A8F15442E46ECBABF3E8BE618ED752842C5D77D1B0C63A293C5422B847DDCA0B105EC8F185AD1E891EB2C01DE98437E91093F2AD1CBE1B69C6383C4B092076E39DB92F4ACA72DD8A1BA9C4B4749A0AF3019A77EC711929732E5A018DCC6A53DB20CA478B013A7169BFB46FF4B1B27D9C0596061F4D3C9D92D5065B872AF4F54850473BD72C772FCA1A7CBC1611B7FCC2BDA37B244AE24898A1B714C7E0E7A83A1303FF2CC34D3A9BDF6DAC9D70CEF8EBFC28FD35BC04F5AD34BC583846CE7791799BCD09AD0B49E8BD8F7315C344DFDD432A0FE23287ADA28C28F8E1655A9B85A78EF281920D648B8E6780E23C388262AD283FC606B90A5CC8ECBC2824BB84C37B9CF392C7C9E9A478CEA9D416F14F1D4A6153ED0C9367BDD1F3664C8308F56C237BFF64B9E38C79CAB7EB3463656DE506C9E4CB0EE0EE53A576E0AFEDEF1A0D4EFCB8C83DD1359D725CE1AE0F94B4C12F569FAA59C14D658D9383F6E8F26AF7858609F4CA2704BA02098A09D194AA61BF4A644E67EBF205C96E40596F0DBB5B5AFB2618A212A087BA23792E191D4B323C0CC6F6AA028A6F1393CE19BEBE5D6077ED6A4C74AE1F02EA251C08DB9298A895BAC0BD271FDA390DA6C73001B3C67D62B353651224863656CB4D9ED062E4D7BABAFB4BBE1F428970E3F8CFC000000000000000000000000000000000000000000000509111B1D210301000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 22 iteration(s) +mlen = 32 +msg = DF00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 5904D8B360F2977A93D146BC85535F57D7C537459777B51BCCF37747F50874A489D0C9F3B0CB4399568B420C8E6C36C2ECBB1D256EE4C33BB3274108568A5CA2C55236558DB61F7F7B786021D948CEC21D7DACF722D97A51E01922CAB79FA56056DAFA7D4DF250ACDED7AFF8403BADEAF5D2B6B7679D34C1EDC9DA353EC106E855A496D6BB3D76728F2EF85E3A7AE7AE5006B05E6577868B0FD45050482A21F7B657FE25B263F93CD77F64802E164176C4D6E8BCE5EDA052A5810526C87AF7FD8BC9754FD36184DFE017BAE8B3C932F57E1FBFD6D7AFCB92BFB8E366F5EDA8CF034A93B93C7B9CB5BA4A9D89F3FBFAA624BFC3862428432B8C2860783620E7589D850C4BC59A98617FD466E20C68EA5739650CAC8E1A4018C1B7D96F1C6D14CA3C6619D2025F09453FF93CBE6A6C9F3C27DEA7B17F1BC96BADB70B4B222D1EA14C632B1F15131A0E7ECD840BA27701BC35D7B24765546D4AEF40FC5ED45F8C9A685649063891F71C6BFCDBE7FA5758B823BBA2B5C385C3CFB9A99267B71E4D9732F83AA748CDC0E0F90D450F1BEEFA0634D380930902FF547EDE10C0FD13E1713D4A2A20DA85F36402F9A18972D5B1AA87B4DA9BA202F1B73CE69B09D9009D3C181CAE983A3FE952E41E6157DFEF51E2DF112514251197FB6A9CAD72E2952DE6DFA464541261C2C2D358F99E249BEAEA4DCA80B5563BEC8A0062BE7634EFA283EE943DB470FE3FE3DB4BB27AD6683F7B95F404372A90E8CDF9D796389F25084AB6625DA15CF5EFB9B6912B289541BC91FFDBBBC6B190F3C2F49B2BD12F948642B67162DAFD5EF906EF5D963CA9F335A89083728020BAF7C8638D1184FF3851FADA92BDA217BB848CFDDE8CD0F2C923B4BC274E2B83F19A1AE53A168598070E128FD7219CFF20F25AFAD63F6B5BD5151DF0F12A72699E7D7F7FA3B667FD8621039265F98AD229B8CD90650E1511AA805D3A3E2F1DA3931F39B227495E92B8BAEE558259C4E11CB30324660E659C19CFA6FFEECA971EE29912F73D56E752C6872B1D098EB37DB5BCFB71CE6F5A2E464EBF6189225501099E623245FF3859C42FD3047CB8C039C4B9F0A348A579B5227B6FBAD1F6300C441278AF252B3154ECE53E8EB01291E6B6033997CDEB058CDBEB2FA9892A526CC6BA4FF9EB7781488C368BA88369951E64DEAAFBA8E97BDA1FEA3A466D1BB2E50DFDD775EA9FE776175203E27A5B4925E606F7ED87460ABBEFC572E07A058BA412908B89AE1C16BD1499F2E3D314B42B191E4250145097E392A7983915BAFF0894837229F6AF94DA23299A2F0D1448B3832E2C9ADC76F3CA53192CEB68937B45A8EDE43A21ADBD171B2540B53E28F30C2E5D1D4B2DB0ABB1F91C028C044C76A77AF64274E07D5990F68DFEDAD5D652271F4538BAFAADAE1307085E3219503125779854E1848A236916814DFD9283F30EB81D434320F7063F9E05BC8DDBB9DE572580840269952103C4EACC9E57C99EC29D68FE66A733231B788B4F5B60CE0725D9F903A8A734B8784306FB76CBDBE990F7D4244757DF91623FC062E18D6A9DD45BA6EBF904DF58498330BA893BEEBD66539AACD43A18961ED901932DF3D2F02D826B81E06894D3E42BBAFEB9FCB9E31F863D41BA577E3B70089480B4853E1A290943C9668CDC040D5962E1922FA81C9E33746C5BE5E7043EE74D8A03559C5CAD68C66E73ECCB7837096F0F9BF0158886A94A6AE42D7BF49F3C5490180292D1777ED2CDD253C2502E66A1B3F6896B7F69CAEDF92A77F5572E68E17F6F6055E1C7171695238E9A56C8A7D57153B72F2A2CE4B29394F88341E58293D8C8ADC483F2E6932A7D6118C10162AC26DC925A78E3F8B7ED3EE5474FE1DDEA69B99BC8C49A091DD9BE7914432AF0ABD1CCF935A158256923CBB17DDA32024B548C7544A0A1F00EBA0727F96CC429F6574249DA35B77F231380CC37C48D1CC65CDF8A13EA655C3FF90B0D61E97B3CB0126FCC9C8EBA23528C166B6EEFD7FF8711844480830768A2FE4C661D562EB0771788E6DE01E951209EAFFCAC5CBC96A91B16044A50987030B360DF5AEAC87998EF534637148CF3B8A0580221A892227E2F312B7C348A1BA5DCB86126DFBCB9B7E556D1A1C3F200CFA79F7BABD06BD5805513458D0C6CDDADC5A82948BEE265F27DE58F2003A5BBF632A44850838BDC809B50D15EAC428A1733FC1CCD6978DC68AC6ED92EFC12226ACFFF102431523DFB279B2B54A2B586383CDE777FDF3A4F509A12FD02D2339B940D04F30B3C2422B2A0B0D5C913E2C36D452C299D864A39FA6A424133A3F31D62EA38A1D42A49F8D1A56948963B3BEC3619807B6548478E8BB9A2B7DF274A93154CB159E6E138D21ECD4EBC07F3781A4E0C4DE90BEAFFF5495F5FE8124D8586C5A25D7DBE22F19D700720F57A27EF65C30B69CF81656370063031B75ECF3D6B5F796B364D30B18A39386051D95C2F3921313A18286A6887B66F1FF3F501102EF75C51119AFC50BCE788187752B1003B94FCCBC16ECEB52DCA1886C7202F8087F08AD3DAE91C3285A0B6C5F9D311C54A166F42B29F3D2B506237BA0D61C5F9A082C9A481F91E585C90FED220FD71140D983A8B817087B0975FAA7F4BF8D2035495D5BDD76E008D3402F146E43735B6D21F5888538E678B1309A8377232C47ABA73E7C2925B8E8631FD53E54CB17CCBDD253003B98067EF266C68FAEBEACFD11434885D47A63E80E948BDC7B91210174B0013B7FF192BC7851672C9B327850D3F9302E099D07EBEE2AF73D0BAF2530D91FA93BAC589881615C7DD13142BB3914A1A801847A1A362215B51DC3854141043933D0033568ED96063411B0E37512F110541D686F59DE11A24CF4C83C6157A4E916E237665B3C8AF75FB4984ABC0725F08ECFC05A1D140E2D6606259EFDC4167DE8585CB3FA90D61A7DADF514F76FD73A2DB81A10F2BF1142EE8937AE1C2070DCE77F3CFE8D04DE6BFFD977B7775C85C97B3042230A5947367F8DD266D0415BE08E37833B4B37A446EACEB12AC8D5A7361687226DB529A2EEBD3BB84E6E89C7B325FEDCCF6B1F5875FF921ACCD9A362FA8BCAA0181B84A1E97F8C5D2C10C49BEA940CAEFE9FB6E1C1DA54018A6C6DF186769F18C97F32A5D98975CDFA7B29B4E3A0ADB06FC3271AFB9C1E85DDCA82ADB5628888D709CF9CC15C68385BC5BB898D8319F5D66FE962FF4AD9323BCEE5F39846BF4A5010493FFA52E7BD8F4867283F537E64D76F44587E56086CFAB70BCF2D1EAE7731E47159E3AA87FA226701726B8AEEE6FB07D1547366C1B3AA2DD3E6634926BC371DA7A63C9D9E8B6833AE061E75A415B62B9F673E59710C6C07FD9954ACC32AA04091E78DB933845E65514105111EAE207C7DA2BFA6BDB85FC2346FC835B82121A91F1BC2A220BEF3EA8137BAFC9FB5AD6E0FCA7041E0241136C694C624CD086065025882ADB335426613D087F008F3D4056B7A4491DFAE0D879528C1CBD163862222D2892EE47304DC30CA014849FC264E01209F1924758717F6F8ECD796CDBC411A3878FE55B3647BC4056F80A2F29A0FB027FB434F34111B8BAFE5662C0DCD05D90F30DBF499DE9A8AC7E14C8DABBD4598C0459117B4F9939AEC74087C1271658CF9DBA93044431893E52400BF75C1ADBF4FD98C99CE921497F086796C115E212904FC0863F168BEB6CF913F38B67DD03A3FC4FB6A8C85A9E5E4DBA52FC1D37FEFE5C221C4592C0BE1F01A553E29C562C5D90C3E15751305EE1946810119C733A6C12F4C1C936E18C667F1332B2E209485C448547B0EE2F92915FC4794C06D4A0FDBA012C02B4D10C226BE3F3916569133C0F1DABFDBDD720B56FCEC60A6188E43010209EE460FEDA5EAC9920624B697C6DA7B6E7B1B7AC528AF533BCFB459FE9677F3717775111EB60802594F380986B52E33E1020410DEFC5F417EC536D23069E0BF5912D4DC5D6401020616EF046411AB8A690FBF6A93D44C980066B612E9166F944400A9B175D32E8B5B71620A7B5615EB177B331C59DD115F082D0DFE374C6F622445C6643F95683ECE9ACBA27885937237E4A8C7C6E9BAB86AFACD12F12234C20C8870F0E592B748E4AA7897ADCA0C2036270713B4BC246CD7E4FA1B95BEE3BF8CE0D660E384F45DCB0F168E23DFA2F440F8A1C9BA3DFC0374106E65F4B881C498F39867D57C7F05FD645C555E94BF1F7F08DFE1B49778184519D52637CFC4485CCAAC8902340412C39F656839C9F6EA675EC08A556EC3CBEFADCA81E8729DB5282070136838402AEDB2E782D657AE2AFBFD99AFA12024F7900EBF115B1FD8D2C0E8E2DD9B3F35C3874A58F8E4407110AF69D487BE28E84CB85558802D1930B64763BEFBFC5E60595204B90C8BACDAD1C7A17A78D97C521EC6A97FF7A6D234DD02965E1BE1E724A98DED88C0131F8C45E866A3D7D0A9C02A3DBA178F6BEFA170C4634262BF4A1BBEBDC2FDA75C5989C17E38325AB1195A2AE2BC7628A282A9078906E7A731E39567DE1B4A5739F63635C8E41F49EF50EE89AAFD842DE9830A7BD3E96E91AA15DE76E3F0D3121347BD00879B6AD9A7E4B0EF5684E3C32D08E65929E3188CDFD0D214A4E53626C858EBCD1E6F9193394A6DBE4FCFE3D5B5C76B7BEEA333F577A7C8EE95E707B8DAFC0CDD8DAE9F60000000000041119202732DF00000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 23 iteration(s) +mlen = 32 +msg = 6600000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = F1D8A6B653571C99122842C7CA222606E74D6814EB27F05F2EF8DBED54201882859D0F809903A7777A3236DA3BC18CC879283B6BD925A20C2B35A9F0C4917A46CFC0EBBC7E34B792F1577CCEE1047E207E1C7EEB4EB6AEEBB18C7E21D3FB28575AC2CDA9E9A75580C5268AF20917165E5DCB735A5615CAF0CB4B001FE08B65454C2C65338BF5777A260D550456F8616AAEEFF235A9DED33140DE0712CAFC0E729213514764F56E0AA4A852D5582135DC900BC4858CFA77FC098171A980CA338CFFB8C0C9AFF0A60AABE27D25CE0A329EEB802752E17E0D4C10D5EFC2B83ED0D0654F5810A8585E3460655F0DC6057A2CCFE847A79509C919D0A3D81E1E05BDFB1CAB826B5B3B76C19468F1E19DB7D02E4657A40B724F8B966A873711E9305DB43613A96BF1FDC0FF0E548BC22D56079A18B19CC4BE342AAC9FD83BAC171118D5E25961FFCDCEC1F55DC8A096B61883B3FC7EB4EB6FE40CC7E24875E39A907108E522E2BC8A7A0C4CBEB2315A8300278542C60CDD30EBD7EEA0D5A5E9D26DF5D3A37E7E7E62011700C74FB905F49671473AC6B63E9AB64DDFB1CF6ACD419D7CC7049BB2D00B6D170FFC62B286DCC989A8F418162F36B149B5FCEFF5000537EA0F39F7DA20597AE00849C6D9EC633592AF60F30DD1A98C8A2E99F6194D527176CFBB587EA4772D17A387D7171C3602964CD4A150285F27278AB956778C4880839ABE9C5EF4B4F9229A71B81239D1EB3A9D10D1CAF62B9FB031221129C7B595069656836813D2672D93EC963FBA56B8BCA5615010AA9AB8875C10A23F6FDF87F852199CD91CB0E84D2F31FB8DE5FF59E2DB2D234C61A5175AC7F0390AEE454544BB1D5D036D9A0BA4980E942ED17BFCA4C50BC4F452075B6BC093FCBD4076265F3E926B73AE6690CA5C084F66FA8890EF01BC234563339953BD0F11B43AEDE7E9E1A505EFFBD3751EBE40B3C6126DE59C5AA703A90E09BBB62DDEEF444088BAE807EFF6CE95A047AB36DB714EAB5631991208215B0D1A6DC557E93F397961B1269A423D398C411A0329425949623087D299CC27525BAE1977B972323F40E04BD48350B4E03AFE61B3024CBCEF5D0B66718D7CCE18D6657D262C2BD253357B1EA077039865698D491D2C6D71C33227F1E484BD8EB31312142F9DD785242C722F61218E03922AF3AFC8507D5E9087F9E2B2D4194555E9EFA7C01181186671B469D4596AC8B2726A1B973F94B67BD866FFCAD0424A57A97E712E96576438B81A9A6A92C88E0CB7D26115A5CC96CDF4C7E01E06FC22AA4EDDE06D99F2694FA6E0EE0C50B6681D22E79DEAD0084BCDFD9E70315603D8E06DD315FA069AB4E635A9CCFBEC07EE23690F5F8C3C6C585B71705835C7FB8D251C0173C28C3C1B3CD1EE410F2ACBBDB18DFDCF33D6530C781CE00B7559B7A2AD1A37B9EC1A29306C60C6659982DA1E0ABD78F5167F202419AB0226A3E5393D9154A32CB428F1857866E6535FDA4E79644D2D9811AC0639FEBFD926F07AB45266F3EE9CBF5B5DC13E3301849DE423ABFD112A18EB3EA7181012A17AC0F2D3647C38B7E8EF511A6BF7C39A7A8D2B15D8FF995527D768014076BD3C04ED5309F81A03363479A7C4A704C38D6282522D9CB5CECF6485C0A3BE5E25FC9C66D5856E9946B02EA2FB3CD04B1B138880ACEDAD31698B4EA78A1848FE9A88FD43A9223A5A3C238BCF118F7105FCD0F7A32194FBA1A5FAB339C88646C28FE340A3960A5E743E48E9959272B4C5FE3ECCCC0A8424FA556A75326ECAD32EA7EAE8FC28A221EFB38818478F09020510B8EE10545C1928D34B57386C04ED7B57CBC327A08ED010B8EC5161A27D3938A1F51B8ABCC4CA53FFA110FEFA4D1A9C0D1791FD08FF93CC703BA46BC863975D4133E96389F6EAE6CC5947368E9755C1D4249DF67DF0DB2692EBFE547F44D70A857057BC402DAE21E8DE324B4723C9AB3B9E5348DB4F136AE5606D17D2F0385DB013DF81FEC26A6185A2A97127EA253CBEF907B4B1BFFA72C84AD848C3E628E14E6D07C6D28BD3C3727CD6E77FBD4EEB587426BA98C0EFB8B66D6FE0EDD88CE487478D89018FF7A8CFF9DED5ABFF5848C5F6BB702F595F5806D2833382E997C1D8104463D76CFB2A7D12B5DCA8AC2161DC674041787E5BBC1D21B42FE86A8B6FE4B4945AFCF1088BB16620C8C8BC9542F0950169EE13AA7B2D409188DECEB87D9A95B49522CF96291C185F4E7BFA29DF3CA7291CD8D876CBB017C96E7D621943D477442359BCCF913E498F34E8EFB6114D96928772CC00B091E9619CD7F869E25356FDE75529F5AEE0FC32CEA46A5DF2C0E5C2EAAEE54DC94A5879DDA8C653694F071D08377365569EBF8762D6D030DA0C12D69050103912D9D779F6409A91FE0EFAAF62017E7018D8A9A5B9EC25CAE60AFE000A36CE9C81CD8DBEF732DB13A09D5E5A65D763CC48C30941702321924C40736C0D1F7F4006476BBCA04A1E0D20522A50A5A809B9C1A1A9B03D59E4461C5B9BCBC3E4C3650136804AEA8AA55C1B2B1435D2D0469B5D6F010CB51725B864DDCE08ED2B874CB5E4242058DBE3D79503590FABE53AB2247949C13F10ADEEB02C059AF1DC4B74278B3735C29DE6C9E8A96AB4550BEBC238C9F9B76F94BC70CCD7B7A006F6F8474DE941730F699BB12F7AC129F64F9E0EE993AEDE6F127F124C117ED7C9F4EB0F1B32A30FAD5AA52DF671B43BB3D9C571443A968456A8A512E1E55F4F5CFCF7CA12B0E5840598BFCF739D573BFEBCC12CE756BF4C18B8FF3F214F26B5A8560F8946E064C0C6BFEA565B5E03196C1B88AB460F689AFE860D5F209D6DCA51547CD5A0546E44627FF6059979805B7E7F135392D1817AB9A71AA1328D3B3CE62B65BEDE368F4B94F96ACC923DDC8456707A092AA5A861B15B577F3B357C7A05BC95E0617E754208DA2C5BD733EECE2E2AE36043DAE2129E84358D8818F0913D175E8D747B977C26E6223D9272F02A4219316050134E548CD0AAAC2A40CD4A18CF4C59653575FE7BC5F9105AA0588BEE9642697D948F66692D954B941620B1C75E38BB8215492DAE2F3F0B8785736D7E36C1A4C0623E8BAF7299148927453B69C6BFD29554471E9C7110011E0CB03EAA86CB425A13F56886F4664BD315E433E23BBB3950F47A20BE0953CCB1B061B5AE357D89695C5EB2678AADA47E85D50DB2CCA2FCFC25D1B0B8AEF77F8807826B787DAAD98E65FE04F405E58BF9A3190C15239E413E3756818794D1A5150F7A01753A1838DDD591FC1B7693F9E509E0488439290C1B8CFDCA32AEACD3D1C523F79D71DC2970F31D09FB2FCEC1710A533ECBBAFB1B14780A8DE4AA96CC098EA3BBB627C7B1BE410B6102C46FDA68AD79F4200E89651B5D3BF420430940DA84FD1E44F3BEA4F32C373FA789FD149CB188D05BF45E87E4FF686BC7D174BC1BEBABDF86084503101D8E2DE84D976A96C803FD9FD0E4835FDD621D33B9B38A71AE8F4967D29B7318B042C500052BAFC46506DD861825BB0324BBA1111D8F7FA9F405D023AC6F73DA056E8C569278C69C3DA0873132C987A77E9DC0CBC78C18C7A7A31F4DDC0BA4D3D292D09724C77D86DA709D5C76F6CA64FE82DC3302F421AA076E03006D482205186DD5F2CC559F97AFA7B24ED4AEC51D0FF3B5D96847462464929E0B9C2017A91CADC5F5811B5CFCC4621794926BCB6CD08E68C8A2BE7112220A0E3444FA2B745A984BD504EC05B352C3FC105AFC554B59954237075FC0E9F36783DB0F9BDB0487FEDEC2B9B20BDB788A0E7B2A6197E459E6C767649FA8671454F1BFD4C968A332C0D37FF139F9AFE431ACD4189C113963542777EDF8F2137F9255A3A7A1CC959F7E5A2370A6CC027556B58BAFB7DFD7F19205D2162BC8E3F934C99245A22774FA43118BC96F61B17D4E5ACD3217AA6B79E7D17ABC2F62B96D6389568FED71B0D4EDF86D0CCAA06717A113BF8CD124043A1AD9F41E0A9E0B0B1ABC01585459B9C28B0269C0822605ACC2B6259A3B64214B3EF035F7EC3F59204E39A2B408F14C6F1BF6E34CF1B4A6BFFA4577CB85C3CE3994B1019D4F3FE54B21798EBD137284E6D403C304B86A941CA4428C75E5A522915F4E2E829EC58B3044BBA877CC7BFE1D28216C9720872CCAC70B44CBED4858490EA5EAA7DB5DDCB736229E360FC6F708AD4C862A2C7E9AE28BD8C19A97ED5759D83C7A89127361C941B54F214818E8713E156090F28B2ADBBBA31EF3BF22416B732A2E41D3977BA59FDF4594D407140AF0122A74E01BCA4C428ED7C5A430812C2F83B7A5C4BB3BC7467D9300EDF2E4411E4E1681A54F80C606FC48CD5B224C98FAE366967E8971A0496D022878942B65DA37315E4E25E154B9ABD2CC9F7D861F5BBBE416A917EBCC62398A9FC5C9C1F11276F1926EB6A975F1E529D3AE1E3C5B8284B27C5A82D82F580EE5CEE542596DA0D1C4862A29693C6FC60C50CA268BAB10BB5119B79A2E8335935FCDB8DDEBDC51969BE025DAE7C0FAAE34D2ACE2869FCC9F531FF5215FAF1F278CD01DDDD49653B6D6B005415354E76D911E57202718FC1D42CED82AC768B81C40F7991ABC3AB3EDC186F62A0FE81DFC58E17E81BAC4E1EB0C1A394451596B82AAC9F0F5151EFF313C63A9F634385868B9E02D3A4089D8ED00000000000000000000000000000000000612151A20266600000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 24 iteration(s) +mlen = 32 +msg = 3800000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = B17BADD5AA9343D1A5AD764F7AAE6B7A20D588E4A075849ACD08A3F52E41C305895BA94E249654A9EB6D5D1BABB83D2DC0B6C7B65E8A0CABD2E3460C81C4AAF118BDBE28054C2A3201CBE2F2FD432C02A73224AD9E35DCA777022D6B4108A9A78F3C5D8CD21443D618EEB319751359745E241073E20BFFEBDAD3C52485A1DADD6451F203A54B13AE35A962E287EA763DAA336623832298ED56C0C48CC16229D4B801F399DF149BA78AE9035B16713771C616439519067316B1CD14780D58CCAD2D71EA075DE02AA0C3D68E02036548FFA0AB142A12D6E1F269754EB0CDF508575BB86843422E69C216545170FFEAF015FF177330B8AD9BEE5C482F8FD333CC05D21DBFA7F4106AAF48C8094D956FBFD84BF3672A663EB2351F8E242930BB7FF29558DF029C1CDF7AFF3185BE194EFA1EB96074F57E0B0636FAAC04596A8FF28BFA4E698635A53ADCAE85C76BB4C25C9A1886D09C1708B43B765C296BBE0121177CE33D5DA85B3F41A2C21275898866C05CBA0854334C7F1F8C75102176CB886CFA461EC6A4C55BFB2D685EB9E604CB3ABBBFE3237B6D724EB3EBF050769BBE6F3D50D28626E3DBF4C009BCE530214C84E49477ACA9BF49C6D7C53302BB5DD6E72F1EE26ED64FBC07693D240B729026EA719742A4F903C0CA0106ED79951FCFA382C4B0C7D07BF4FABC99803260E82FB728F1B0F4612D6D8CB21A14AE77BBFE299615181D9EC1275D0022FB583BCFEAF81DF6E1624BAA703389E65A3EA3BAAB0BDA5462FEBDEB110B0473CDA2A4A9FCA096F4A68EE8FBE76136048176F8721AE6106BDB0F3AE310459D71ADD85A2444EB9479AF450CA4864E1EAF0D5BA04C872BEA6749560F570C67814884B1DBE5A87C505CE9B93F465F75C3E0A1AE3044D6F4E6CEFE05904AB90E5B9AFC485228DE76B6F3415DB1C311A41A55B13F0F0783ADD6BE3EA5EE68AB27FF34E2A1006B5DDB8938F5C08D05946CAC2EFD3EBCCFA654211D69A825773126E600693337A91A4A8777229E80F654F9F9A0F21E69D9A979890F8F3DE93CEADB0E4890C7D19701FD7C2F957DC7DA88910F31CC8D500AD68865477A66984C2CAF86B08C13B7CA3DE0B7545D41191F221C0C0DE6E176BE90690E2862DB31886B8B25503529FEB62593AA3D0C074271CBB8CE2385AA834294DE61209EA793FB766862CB12E12C6464385761209811A78960542DF923C5089FA3A103B2C0E2BF2EB3DE0D05A57A514B02A1EF539EA4C35FBA7FEC65888832088BAA38D5F1D7AE58DCEFEAAA24DE9D83C8D8ED481363BAFFFB1788DD36114A11377A7C871BDA3B5813B9D6632F289145906C335359BB3876A127D4DDB8C3883E022C3AC1C869815D13F06E195D246C2CB95DF4245E49A09C617B6088ECE00177C30E7A962D9ED55D38BE7E1880455F14913759597ACBE866770C7D28C704CAD764C547A750BEFAE3DD88910DA22D942B99503E0753053C95BC8B44843B556C396F9BA60CCCF48E4A3CD692BC4C5F989725D0F89924C63CCBE7702BB98DA76D442060A7946D00D195001428D30299CFCF807C7340A8681000D35DA9E2D74446A83C89B158770B31158CFB99391EBC79521AF25CDD2943D46D17A81A9D886AB68AFD3E2825BCD1E7FF30A788C9DB45D865AC8EA7AC65B5143C8910DD10380FA47CC2EA4114B4807E9860798E19C27CA856BA41D4866D393BF30AD5F40D9AAA712E8259315E4334940447E795EB293237781FC1D1E3AD79A21FAD18F2DBEE6F71FFBDCFCD1DB77C2C8D1A3868E8F36094F51864DE305783D39349B01CC26A0645B78809E2A59E761512635F455CD34C3A3CB0C416981FE2F85FB7E7A810138C9221371B126D85B63B6C96A5A5055E3AD48D54A85FA9D916478958543D114229568EEA61E57B67FE644C27355BC5CB5D8AF0A15727764751A6F13740F5181A8C134CF67B958EF7CDA612C40A1CDADA48C887587AF26D2D47D57C6B772A89F6312336E646894F20B1820FC6B217C8B9E08ED4FD9E104C3C7E10A9CADBFCC1FBA58A3E7FC84BAB6756685E17F37B7205716699479F403009C36A12ED48EED461EC83B45E94D48E50BE83231E16C4C9AA47A8EDAFCE1E39DFFFAB382922C42646F4B83B81CBF2FB84AFCA7A2756038CE1D4691E8FB062DCD8123F3FA358A5076C74F5FBDA1595E2F29C9167A42438F61290A12326D8D7CF9256DB109D5509A4FFA9F06A98D6F89CD77EE04A10BAF28933F31FF404673476F7759654E33083235B0B9E15022F2D7DBE40BB8C79C76DD60B9720C78A03D1CEA71FED43F4A207DC32594940D00A19594DACB610C0678FA9AE8CB5D99C55311AF7D121E017D960CE6D7450F0253217FF9CE9CA93EC2FC167BA4752CDA6DD5B7F00286EBDD4B02E17BA40962D03F9F1F6F1D5C0513B8E768CFB0A55DF7BAF0352D63933C99ECF5479A38E66E9748734A6D69BC6C62EEB8C0199877631EFEBCD0E82F36A50664104A2ACEAF10F99E73924B52E903CC9C8DF8870696A4894F44DB890C2DC5FB9CEB858D3424A6FF9FBA82847807A6E11914D500B1224DF23DCEF2AAECE0A6B44B0ADB6EDF276CCE4EBE77E96F705C03993A411D98C45F25A6DD793A4B630C1617AE4319926F00ED248B4C3889977F9FE83FCFBD587FDF07C75A3EE3880FB26EB6DD4BB01966F74B6B6212311779F5F11627CF98889E104967AB4B18CACF4CD202E5EC46508F0D8DF188EDD20DB49421B2B348684F336917A40B09EA1D6C4D931EDFA4E28908A61E8C367B221AD2D4814B0D85AFC99DE3967F3D6C90E9A975715E2CF403AFFF1EA9F0C207CEB40D3629067E79C7344053A08A69460ECAF5BE667AECC01BC045BE25AFE85416FA1E6B47FD6BE17DAF0A01004B0972420A3163B24A4FBBFA1B61F34380C1131B7C03382642A7030D7C17B845989C39DBEC16175740023F8969FEEC059CE37FE0B5652259BD4DF5526334A2E856CE57CEA75319CAD0A958C9D0B33E45920BD4D23427C44986FFF3045A51E2559D990190B82BB7321A1C3D1A0973E51C7ED50FC2B9D31E727DA677A0B29EAD8B81596D6417C6D62C79FD30E838FD08729323A35766839DCAC3597C76CCDF3E67D7835E7EA9184DC7BE8526E7D014AA26955757762EBD75C3BAB998B76DADAB816EBAC4B961C7084BB5B0D39DB09BCD46C8BD7D2CFD85D69786E14B7CA62D50B2CCB9E322E38D1F90D556B51DFBFD145346A664638DD30F48DB058F0843412ED47779169CF42BEA4656E5D4DCF9C4984476BD677AA6CDAEC9F4973E0933181C5EC98101259AFEADFC65D55805DE0B57E76FB38DAC3EF3544B776926637E8DDA46846FEDC0CF55C19645759CEA07B793D70A428BB654A9683E7DF56FE23B1F4C52494677EEE25B7FD9D0DA1CE33D39E58DA056B99E2A9265335498A80A873BE748658FC8C37841B45CC70E3A46B8335CF5DA9B0E51550355F42CD6AA1CAA3A55EF21ACD1C8143B8E0BFA68F81B06438EF9C24AA6005A77B4D9457A0B599C0F71EEA26B40AEBA5265EADD8A2BE1FCDDB318559DF9BBA95537D012DAA14356E3FCDBB7CF41870B96CA9EFBEFC758BFFC172DEDEFA450DD0E586C98783529DC44EA0778EFE30F8E5E4B349F6FC0417B7D1AB53E592C627B93C2E26A6C607A0F899BCAAD7761530BD1FF0D4997AA003A06AE940AD2994A2CDD9FBDB51B015BBE122BD333E54E1120C7BE813AD75D2504E61C75F4931CF5A725545DEA045A5FB768DC39CB9FD08D4658C31DAEADD27765D2FD47CADD1B8BC1C51969E1F140DE354708D69585E985047C73B139B79C2D1B646354FD9D7F94A0B791E429274CDCDC74FC1BF2B8EE29FAFDC54241AF82CF34BD471736FB8C3DB0819CE586DE4CBBF86C5BE138CCADAE85B20DE30AEC8219512061FC1C7688A78102D97DC9D7EEE91EF52F6024E475A02BE913ADC96106A0BFD503112B17C80F60D506A70F4589BD5172475941B36305905A51D340A7B49D884D4531E83277B2FB865DDF727A8E17453CBF785101A2DDD3818D12CCB709518B3D1534A980720162DDDD0703EA37111C67F81FEEDB854E8BB924158752E66D8213B24A7F37862F57737C0AB14E72A70B8E4AC673C15EF6D483B6ED1A70F265B8316B0E431971B7F2DF7CA94723F7FF874D153BEF275A72F26986353FD9405E6DAC84B4726C137CC0FD2BC03BEC0677EFC299A4862D9AEEF7103D1A19196A173AD9292198AD8D5C4335144156F17DB54FC30C230965428A556A7DDF2A6CC4FF960224E01A38A59F526741E3036A040249F58D6633509E4161C73629D1A749A534C444424A11B9205569AC69BBC1600D11062529B48A1140AA2088F914F428B390952490FE59B2C561088D364F01C8B3F7C1AD896330B117176AA1829FBE8FE82D9327A5D9B67FE81F3AF4D734EAAC7BCC2649E99139D9B32EF4713C0DE9FA3BDD2B4099EF3AC9DFC04D7E254E2F76E20D392AC638AF5721ABC161A9C28EDA6E9B63AEBA4A6B06F62E6CFF70B87A38B23885E38426E322EDA05166C3AB9659281AF5DD25D3763610E3B3FA37130453ECF73305F4A34CF29215A40D106B9C652D10E665C5175C3115F19E573D68383CA003712D0821E2429315A62707798E4113F5DAFB2031F394557787BB2BFE52668ABDDE5FE21313E8D61A8D1FF000000000000000000000000000000000A0F191F23273800000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 25 iteration(s) +mlen = 32 +msg = 2A01000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = BA8E0A490B8289BF91C6AD96670FF09AECC7C4FBC1063A0DA6E2C679B03DE134F67FD1106AB8147565657E569A4F90E8A5BFAF65792937778E3B177BEFF1F6337E8732DA0F5D6E68750311B8AFA490588A2C71344344D887EEC1B5828DAFB88020C91477E6B7AF11510E5431F4532365E4ABC72897C34D781F014E17DEAB35A4DE9138D8B1F8A374552C93988926EDDFC0D3251A7ED2F89E832F732871416BA82B6D8F94EAA946FF0B9F9D26603E50EE9415516240797E7690095F536CA54F7E320ACD8D4AE98C65F6EAF4DDF5A3C5F8BA25D1FC2ACA577BF2B9ADB6726F4C8FF84DA5340A5291B563484E402068E6D41F2A472B60F33E5EE1A13473C6CC829433F5FE344D6E8ED513445062F54175366BC245FD34E1A1F772EDA590EC392BE722CCA26C71593CEE8B65B181BF25547F6418D05ACCFC9C545FAC1FEC115B3790A99C99E02028DF2A5EB0457CC440EE925AC9C3E101E098A41F602A3B0F546E12CD16E0FCDF4DB9CF70C9016A209DEFFEF9A7ACA0A2531D3481614B11FB73BE650E5E98BC1FBF3F6797DC0EC864669E1E4B072F34B800F1AF615C1D64CF8DE2A3D0F634F6177C7E837911087C2D0E45A1A01F7F67066CC1B34B384EE1D6EDD22E63B45121A73E29FE66DDDFD2C24F5AF1F7AAB6CEA8EE81A8FEDAE51F12C11BFEE57BF20F3F4604F31220FB447D48D6C2919018318CE995C731DAA55B960721A58C88700608C37627872C764A1C9D1F310AFC72AA9C18E5C67C806B561ECE7D6C8BC888999DE43FE5E4D8B01AA40C66961CEC612AFA66B60B770C0F92CF9389A7ABC4B7E4055CCDA9D049EA4A9E7E203C866A360011DBA8DEA95242E1C81DB5E69B5A012AD44AF1D9D8554E12A6FD5490128FA45982EB3798909BAEE62451E0AE02B37BBB064302FA6B3058D99968E94058078EE8FC6B3EF89A0674AFECAEB14C219F9F30749D90D7E89EAA9EB3F96B8574B5B7AF292E5CC4CEFD7A7B3D9079A4E67E9FD5622C4FDFE065E88A1F31A0A189AE699CEC7349E7BFD4A9408E4854BA4C0AD7BA47A1D93C33E6ED2ED0C12BFCA59EACFF9BE53A1B7903E1372357ABCACB013BE6EB47F8FAEDAF1605280FDC91C170F3DCA54F38990F12BB9687ADD8B6C5FE5901FEDCA5568A37E5E7AF1061743A9182A04BC37513EE5B2D55A014A6F9E3B2CB62D298B9D5E726DE13B904EDE0ADC5ED335ABC95362C6975E868A64F5AAEACEF406C46896EFED331A93052FF3634EA438D2A91749BAEEF6F063E0464DD3EA3A48B0014F8361259B7A2E33B157DBAAC76DE53691FA602F03FB25AB9331AC0AC449A428F551374590E86BF9048FE36F8A37AEC825239DF432EFA544D294756B4B9937F202B8C25569F9BFD3CF43C95859E31237DDF39E7C0008C43262CE4CA1BFDFEA4F95AD8536D0F0C108815CF8BD516F3A1388C236F4D3DEC7E7E99CC8783E908FCA0048DA7D15CB2CF618A6074B936BF95BFB028B9C2278D70104D3A5126F09DAB4102A3E26101770C1BFB0D534165C611B25291830033764C9E0BEA382C1848FC5672D5B390CF439A7172295E4ECF786ED75A0F93093F80ECEAC98F6FF26D1C9AA64470AEC649A0658C03096B666E5DE22A9E5182DAAB4270E9593457AB62FF230F86BA093A66DD737EC1BA473C06E1D4DC533A6E8B33C1FACE7CB08114ABE9E2217CF738BCFA1E263D6486F89274BD7F3FD6281A91A1DFB1B99E29D4998A354FE92CA8ACDC5B354E7C3EBA062998F98E23FF2675C5BAC64E296E583B7484F7D9400A8C6667A26D1D597A451D3760FA91F298B490852AB9B1D26E16AAD64F366CDD36079B528CA18B213CE11798AAB5E054798E405D20B05AC450592AF93F82BE6C3B106266A0E2F98D31B09EB86851E1647A19165F1A3F57E1AF2D64AE70C16A37409443298F3F9E170D32599212E7365E7970E34DA4EAA5E77FA644D76E806A4C2523D547D18A90E147E403BD168D021C952904DD2E4391D9B19AA07268F202B8E69D440748ED3A6DEDFB1E5B61E2FE121D980508E3C64CC97F2FEC9FA2F39F4BC3BA08878A081E6E36471454A3EE2CA778DF0D06EB5CFD045A3FCC15795C09CD38143C08E8138F590D05D442C36314FC39B2DCE2AD003B56258A19872994A4D0D810D9DC5C0BCC1BEB1C5F2B6AE9C72E6D6C196D5CEBEBAD71DE697689F7DEDC9F3AF16BFD543B049AB8997FA73E6626E865263A28CDC8C9E3B475682434B19D0A13A491E4918E7BF8656FFEB8DB4D6ACA3E4C7B5289458670655EB1360B5440FF0736A2F58BC3363A37E50A0CEED384D0C0A55A440939818241C026775F5870F1EDC5CA2A0DA998200B7BE15ACC27433013D5A128CCEF8838662704079F63BFE547DF67FFBE209A3E6AF2DA62C80E771B863F992FBE15DFFF1EA5267CB37CA71F7629A618179327941CA4A864B4DFD7B4627690066A7152C0FEF3F500F433A4C54D411BC59CFAC9F1380A4806B04D524C7BB6B7B055F06E2751675D6FD1C3DBB520FF10DCC938F6AD19D577554B656C3643718DF6B72C96B998750EB9102979C58AC4C8A8D23265B8AB8E1BFB2EE40434216DDA64E539B6FB5CC349ED522EE02D393604BF04BF123192EBF131537A6CC1452DDD38F788AD8052FA5A2DA6D5D9C58D44241F403C617AA688E024C50A296189CBA610E031B45A1D6AEB0CC7C23854831B7632FCE1BF7AF1609AFD72800BE217EEC043E8BEAE8956A6FCC99160EE2F0A04403D59A056AF9127D5A8DEBA03723BBE6E14328704FC25630A147B687966FFEC6095D1169DB8F13A39D67A14A7CA574A6CD18F09632076CA53EF71110B818480AF18DBC9DCAEE1851CFB3FBB9D817D314A91DF1EDB4BAE5F36EF05DE9BCC049E672DC2920B392552C4AF73FB5C2DDB0715FA4D46E269931574ECE6C8B92FD5CCD4C33F6B128D34D8BB6D476D9A9E19576127822A0F9BDC2C2065563FC9567272D8BD1E5707AFF183C090ECA58FAEBB6162D04981AAAA6DAEEE847AEE541D04B1794AADDD68DA59A38882E29978FE8F3833D2EBB3E35CC0967C834EDC53689282BC9A7E74CA45EE044B2638690EBFF103CBC9810970E244F0AD42F0BA4A559D80F22957D246A2A6502DCD7E574D54E6C99C866BCF87F18133D0AEE33BF9FB4D851F4E65A6D278ECC89E8342CBA737BCDBF09BFB98500282DF602A99000A37DA8595B8950543D94EAD49E895436C3C5458EB4AC5D75F12079A4FDC7695497D8ABBF36F111919F395E99FC32D9E63B71D275AFE40FB39A88D9D2609C73BB75E9F0F5ECF209FC06F8C6233EB083A88358B4D84F97C75D15089D510384B5B31AC26DE5AD4D20464D36D085CAB2785FFC13186021890C8A9C003DCAF4F456A46D10A06C7B95821C12D96E797C686ED6E7484EF96AEE5A0BCF402FF7D59FED7CB621BB93620AD010E7ADF7CAE3582C8025E6C9F43A7D05DC8F0B165F54CCB2B9E0FAEE33DC008D5AB56E05DB1358E52EB21E5E04484962F2FDF56AA75DD7DEF24300A5F9649497FF9F2AF1AA15194B5B7B86AEF3AC88614329FF4CD249365A3D284E387066427F71F100BB2C58204C236C4D122FD6042DD3AAD7C56B3F48D263584EC2FFB6655560C50A0F1ED396213D85ADEA87CE1F5FF273746DF024C73A449DEFDA41F66BA1ABA7F14F5E2042637DD9EBB18A976D5565D1A5299513933A114C42BC440F5523FA066205D6674E99F14842F2FD552866565081E3F630002EAE82B8103575211BDB74A122AF28E061910261EB6D23256C132B32223970B63D71B8A8C975D9973B2B5CC9B5F27830C4F0C42BF05A3560541AE7C8D6674CDF31CE2660290F279169BCF2EB652C51705FBB27123CD14095DD10B2B966EC0B44B6E729957FAA7EBA3AF0D3BAADDAE47E48155238B0782A45EF4DC8EBE88F3BBE1BA2A7B2DC8E25BF285A808927FA1A7A4A7CCDEA5CEFB350E68D6107D9E2EB20D1B393DCC883F4D5247F36C124B072C42DCE7F455CCE4EB1DA17DE0DA3A801728B32429BB8207F59F46C8D0EE0E6D303E9E6F285A16F0DEBD408B2C29F90C668A412964D2722DE11349B04DAF131DA3E821BC9F0F294D1284B8EE097232449E147008B7A592140D148CB08C6DDE3B13AA3EE738BB1F2D9163EE36CD36E52EA81A339BA09FB6F5CD4B889F89854123AC5E11286676F4B98D159D15BEDF207A70408DA9443B8AA8CB7DD6241CF8CDB3F6EDC801F3A585692EDD0543683F82B1371308143B825121EBD6DC531F18A50E5CCDA7DDAC2F429553E0375A27F20C333FE0C401BA379950EA359617E4CC4A1CC0A2A2A6A0B2215012B4C9A4060FCD1CB2913D70B03B61C4C3B140FA143EEE9741558A7D7E94C4900FB04A746762C3A29A897C2F04DFA5608CD8FCF8A2052A994129485A575ABFF95E6E172CAC945A282E662B3F08CE81CCE600A30FAF8521856B4B73488413C87F684866B4F9D47C95C3B1DBCBD4191C98CA7751358349D21955D76172B855BE70D8E9884A086A2862417A5FD956818406B4EB89665C3859B806BEAE14642953D4AA708C4CE70D17B3D6294BDA94A262DA01AD271F0A51FBF4FB30D8DF2ED047A869266A97BBD27F1DB40AB40A85AC34F770CF62249E8A335866727F80C0D3DBF91B3F8F94B8BC098BC0C5C9E34973A7DCE1131F65699CC91D435991A0BD000000000000000000000000000000000A10161B21272A01000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 26 iteration(s) +mlen = 32 +msg = 6005000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = E2E3002901D6AE3DB8DC9D4E90095433BBC07465D4A3A5FEB1CF53753419B2C48CA1D58B6FCD6E92D98DAEB4674450D9B41D277BCA9B8035EBD230AF965B010F0AAA4093D336335C7840F480799F1CA5EC49E43E603506FB617CCFAF4F1D49F2BE15F524543351B672CADEA14C0FEE4F6E3CB1CB22E78DDA69420717C33711A01C2001F66BCAE1E453F24E15023E8055BF7422F59F7B9347B866E004131B8BBB48572BA22354AB24B4D210C57705F918DF669BAFA3453AB34C60AAAF4CC4FCE0E918A0C604A3938EF09D49903CD97D724A09F6B32615C7B50147384089685BED5BDAC66DFDCF5A9E50F04B4CCF7D15421DA6B3A63758FABF83EC088EDA2FE7C4C3BBA40CDB9AF7153369C3F679DCFAAAA36DF17BEF61591E73947EB5E20D53037B1131C9760AE2949153F78FE92C81269E323222F6259671E506176794963BF2EBD339372BADAC72952DB6F7682B4FFC48DE396A4F2E86880654CD7C896295CAD52BBB6F0E618FD18341D68B6136C9DBD384398A9FE189A71A030C1D933BC568FC4A1B39DC9450555A4A73C69CA1BC58FF64088675D0930B1ED616BF0CB0A3D1315F1F1B713BD9A96840468E43BFE87DBFE958A141BD307E16A91DAF0B8D7AB7232D42B937CB9AF60252AE21CBB4AAF67772AD7E9F3DD9F35FDBA81D4B23767E24FB5A47CCC22FFEE3711CE6F07BC5B2948321FA4C358D266078DA461C0088D8DC4E43ADFD37AE20C29C7BDD02D38DD215C55722DBB877C66F7E487E640402213248AA479B21A9AC1FCBCBC16DAA6DE93908B5CEC812FBCDE9A67735396285EDDAD434BEE205876AC352CB3D62983D8A0FDDFEA53673247FB35D6E0E38FFBFFC2BCB847CB6CAB648080901F95349A8B08A2F327041E8755FE9EE5545D1C7B780192088135ADE6614522CB5B761275C27B4614E1365CB4945A0D2D1C2A4F08275FDD3170E76E37FDF3C687B9F90CE3C4730A35C0BAB0E5969B57FD4700230CB5FF64C5D9F82B2368995680C1C11D078F645A5C169B568E123C2CEFB3813BB21CFEA05616E865A7190304643EF6B9FC0658645E46AB145C1E16EA1C1D18956A081162ECC2194A7D6708963AD838AFF77C735DAE24F9C5AC1B2B0E3918137153B4F62BC94A4D3C0783E83055DF250B88AF533D92216017F218720404D5DB528A9D7836DE0C5B6EA675BCE62634DDD5200F158B63144CAE98EE39FCFC9AA1AED5CD1E406EF5A137D70D1E78A76D184DD554C5FB692880F75BB5FC12125A95EE2FA55A711589BFFCD9E9D374A6E28A344E329D745BC897FEA71EC99BF0A31A1B829BE924794CD7E7593B87F1BC690FEC324ED5A8A9E1CEF5898932F9CF1FF448BBA8ADBE39D05CDC8F7A490FE4297ECB05D56581E74295C3DC34688DE4B35C2D8060A759E662819CF45E59DF5F020D3AC66A673F0E6CC8EC84B981D580CC83BEC3FD4831547E86B190D8D629C3A0A8E9F8D0B9BC49FA799664973C3E1F95EBE9B5563306488DF4F31921E7B9BB104A41B7BB07E6B4400EBF1C84B7EA14B3B4D46A07154F86C62B16967DD15B5008EBE9D9BC2EF4BA5E5CC36999DFB97277FF29053F323337201D16A943FE1941AB54AED4F553BF125D98DE6A9716ECDF140162EEC485C02DA4A0C46674821C557E1C447E513C0B2676E2D3957BF8682041D6B6C2A02C79ECF12D54E3314631F4CC43403B0151C7EAFCC95C1DC140215A8B1FB27FCFE6FF46E5D83697F825D0F052E2B3A78188B84EB1E286DCE32572C95CC35C6945DDBE266815BFFB85FA38B0AF0F4819A34F2DF093698FD99089C5B3867E4B5EA50B880F440C31D8AD04D39C410804572995AE993233FDB00A655B5E55A1299C4A09858D88C617BF2B96D4E2323753996FF05A03848BE0DC382A99EC92C5F6EEBEDCADA9F8AC1A24AA2123B14E2886F1BAE57630FCF89E25C3CABE32A0A5C04D2DAA13CEF7BA846D5F2673E0D4046CE0A764C44DE186C7CC8428C78F40F2E92D5BA339F70F6F1FB77FD4138E97291AA97DD73DEB714FFA54A149AE3CA1099221D0C4BCA018038EECEBF0B609D3A6EACF85C662424F8326B82A2CE40FABAB9B53BE8BA87B2AD87AE9D0D38E1345D8AECE7896503DE334437C9B813E7513E0BD3E09FB6CDCC884330E0A63CE8B1061588DBE1D8EC2D164EB4C1B558070F592952E5671B99767FC86F5A4D9B56690DA5AE97237DCB738C8601865D0701314B24F4566470B0DC28C2451E1FF6414EBDA864BFA8EDA434AB37FF1691A4EC593CF3C3E38877402FA7204C03961407F9307B0A94264E4FF6751BF0736BF0E32D4B1547C8A099B9155CEABC3F0F27FB51D9CFFF842ACFAFE98051ECA7B681A4AAC7FEC3B97C5FA2C92F13AA3E22118605C45691F81ACB1835C8ABC3E89C551248219E5AAC51C43260DEEF89272A3C35ED3DC484F3A5484ED323DC7A41B45FFA2174905DB7C9030729B27E92DF220F42497A5D409A6FED0CDACFED7DE66CBDB2E0DD65D0D89C452D14521F4AEE4E17AB30DCD8F5183E0F1BB2203EB5FC0F45073520E1B06DA4428E57FA91FA44583D70BA6718B0CF576C4BE5EB6181A2A84FFA5D7DB9056BCFF5125E6B64FABDD5BAB30AE6FFE546B62C93CE61960D49BAD02DC65CEE28E931D856E3F24B04ED0A434B9379314CF396EB10CDFB5FEF9CDB779CC1AC4A947A150514AA65EE6BF7C4ABC7D042AE8E1899B5891F80B219460D59D35BDC0A380C86AD868D6FCDA6AB267027DCB567D6215A100B74C9D77F05FC21C27CB98266421E6D8827624E7132B7EF54F78075AD8D54167C59D139D547ABD5A5BA0475F078DFC42A6942D28A9B3804866943DE2049E62406B6A754CFA87C5E4BDD75BFBA1C1DFE1AD116C8A5810C69450EA3FBC294D90C7759FC9723BE5CF62E90B971221E43B098C3F0C9DDB0549C75CBC9BE13140FC65989DDAEC1CE71F00B2C76522DB6D90A98B2921139C8D280B669C9481BB685D78ECA1FCA02CB98DD895859FF114B14A0B35D772ABB59B6F6634BBE0E8D7B578C35FCE04ED628F4CBC1B529A4A374900B7E3BAECED01361AC933AC3532E803B5C85E7FD5852041C026D48B753D35B429916670F27511A855F0312C3A156B80B7FA428AA7FEFD0D10EEF31EAD00447B1312DC107DA80208C9EF5BC49A469984B74EA7FD1BAD7404F3D5170166E74E3D5B1D5E6FD5CBA1D0E0D5170976F9DDDF4E8500E48AA267C1E5D53D2798DE27C6A2C1DF31FCCFB509C4540467B527031046E0BC000B3C65E371795CDF17928BF5A7D062B9F6B8DCD65ACBA1F0AB86E29B95E0A12B372E101582534C7E98842BFB446FEE6470E365A0350B949874B3D345C966E256F8A1AEAAF25DDE3A83390B3C52DE1829067BCC12CE9D962DCCE6D12E8D1350963D852D7A14ABB03E0AB0827FDEDC7F309B3E29CCE3B9F67A5402559D67561E6CF32FC6AB7406DB5E89EEE6FE75F41514DB151B71BBCE51B5B5665B374493D006DBD72F836B17D1C521631876392E516A53881CCE14B589D9A533035D5BFA515BA087FA30FB45696E73923F54B0CC7C44EA75E80DE04594A3F8727001658EA12718375B343423F6DAA62492C74925FF0481D6A8E1B525E8C00C3B63C54BF744F7817FFF2F9F18DB82321FC972E307BF7FC6FEF3D2BE42EE3FB4F8C92571DF5E15CBAD49A32A306CFCC7A70D929BFC3D2C46D9EF87C6B4156B6CA9E91F439D8F2157DF563064268C1FE032E12878A2CFCD232A0BFBA1AE9FE14A8038483B9473D21CB0C846AF238CB7AF51BF7D3B6CA841C3F3F28B322022CAE10C3466C88C3D188FA97357D69F0220D90BB6C3BB9EF624F6777F4067F5E207038ACB7FE72C9098BEDD7E08655C1919B509764D3B8839A928F9D3B93AAF3B422E00F79A5D027D6ECCD69423D49613C06027158EDE2FF7992F45C0CDBF67CE5FA4A64884D2C1E8797AE34DB79BBC1F27285EB15BD0D667F6A76D5E8B777DE699644646C3CB402537C44AA8B039391A0C4CFDCA2D7F9BB64F4C02516D31FFAC03008CCB55CE12E87D3D6FE363BEABA87566249AF79B4652C6D5123E081B0B44129EB790CC27837B193192EDCBA872D9C5A7F3CA134FF916DA058C90F3EFEBC6BD59C11B9BA3473276323949F55E5A3406471C12CE1FF2A105C22C5D2F12B8789A871827FD8B9628BC59B2320F9143CB13C9C2AC6620A1BE6F1E314374AA4A58C810C7FB292898B27FB5C7521C222C3B461092F8CCCCA1C930569035C0FC6A01A618AA9249E9317E1B1306F980170FC95458DB571779AEAAADD1A534F53658484791D17FEE5414C515912CE290D4E4F074B0A2C524C6AC4F095C7BFCFD30C8F17C4368E7E374AE30EE1D104B86438CE15B39A6DAA670C7380E5FC9EEA3A1CFA8213452BC1AD3924C4E44A8C9A5613CF116E646DC605BB8EB8179DCC0E4BF3C81AC3E43D35FDA25E97E9C5967264C6A55910EC9D2666AF2B347D77F87562B095B46BA0764AEB768A45947B9387B1D39490004AA5950D95E035C45C4C05B43AD9AD05F2CE64EFB5B75FFCA0AC868799171C8B2F9D6499700F194B4F800E97E449966DCA97173B9DD632EB254AFDA45AA6C0D1E7FC81CC39AF9DD16439AE9BBCC978F158CC9E850F1D1E6675A2CBDCF8496FECF40C292A6295CDCFFF0559639AEDF90C3A3D5A5F90B7BAD9F4FD203A576B70A6EA00000000000000000000090D151B262D6005000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 27 iteration(s) +mlen = 32 +msg = 0003000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 0DB5C5DD7972E157C32CD30DC3086C9DCB52A7B4BDFC1393ED1BBC9BC1B1BEADE5E981EC4CBCA547797438F0A25019DA9977EA631507AE1C92EF040B35245CBBDCC4299A7623B7434CF1C35C8E59CC8852523BEFC428B2FD42BEA79D19B1395F2A774A877CB7D388D4B83889A65A535001862FED286834D52887B42A4FA2926F5FDCDFD13C24B3373E65D1411EF71C7DE408B035D52FE8E8ED13A2094D006510794642A1591E08678FDF9DF4B82B406AF5A1C506E74D5FDCB8380497576258D176A7779E167A770FFF44566AB3EC828B61464302C66B5C0A9EE6D481F03A0CA64EAEEE11341EEC7AADC936759B835B55C18DE6EB66DDBBCAB480F7F3EABD7017327A28C17990B60E9B3743080A562A4C5DE191969003D8C6B9A30DB7938CA477085CA1E4361C3BC630A9FBDA7926E4D36DD9C15A170EA75CBCB62428EFA955DCE62B93DD026BF728231D2CE00C1C50457C4E06B726D7415619C2C12031EB9AFE95DA2C24FC65A7C1FCC6DF3F810B29BD3F709107D665FBEAE4C62FBF35EE38EBA3B8BAD38597FED3D69DE52C6D01C412F239015C7BB3A6DA5B9B22306FB33FAB50B07B186B31ADC79F4BB16110530653B86A498CE09A199DB2E3AEF76CC19F224DF606D20F5986CE46C88690474B4BCCEF3E1224508E48791E03311DCE6230DB6E8BABAA8FA12BF1090AEA9CAE50A43BB230C4712F5CAE06E21E7798BE877F13D6047C1E3FE1B3BB988E2A5888E79F3C08DA35E328C832D7C72A0DB3176FC7842CB5B41BC37CCEFC21F6121BA0692FD39EDB1ECB92427A0FE89EF8FC8829B1C29545D5ED0BAEAADE19CDC24B19BBC11AC4599AA4A28AA215AAC5806882ABFBDB72CBA5BA01C0F1B83B868A87FBC7594C14B9E2653FC8D0585C857B41EDBB9D306D2CFA368E01DA1E78EBC9ADA2FF235D90CE220EA489D6C088694437FD5907BF2EB4E0CB8EE0F4ABD86ED7E7E0C5DB3BF37487504CAC0562A8E23638F4346075848E8C1A8BE89B680BA84C03FE602CE3133B02BEFD0CDC524D271A4FE7C51AB3DD1318D12B3C4A73B748E9AE37ACC98C95DAF59A56263593E7F9D350CEAF82E3562977C503F8CD551AFF52AE4FE71D8922256384C0FB9F56FF3148CB34E984090AFC4D716DA8ED5AE77ADC21EC9DEAD3315ACD6D5AC20A930E1B7E6A79C3EE09FA8293A7FF1EDB125C138E3582F974E74E5189473A33E855AA48FBCB32E90C7E9438C6E7D9EFEB77F6C9AB2AE564B833C51A9C61A56599D041E55C3DBA4DA5464E7642101A7752C8B81BA2C531FF730A998D603A0044D6C2A632B741CD456EBE4E9B0AAECC0AC4C99E46CE29957ADA554E87F5E7E65E17007F3D976431B3AD5738BA5E535C8F6890CEF767A46F7256EC89C96AD432E1986DD7F81D98F11E88C4FA43BD2EBA95375D3E974429FC117B62A015AE28C1EF92C79F43E1E2E7E49A6F60EA80D9D24A7DFCC8252ED2A75029D07296CCB52C38AC66A83F7231DEDA2E0CFA143FF4384AE57E649700973064FDF5B127AF39B3810B3382F4D81A233C1AC4E4FF39FC8109377E73D3916F06CC66682551618CDA452B50029393C636031ACB12FEF3C903428EAFEE03A83A6F72FA2FBBC078FA99F910E4220B08554EC1918D946E62E6645B1BC155CC759CB8862BC3555700576D9292EFF47E04A5BAB53709FF24CA8C81093377C07816A7097207F4B8F0F7966AF0B89DEC150649648CD108C00A18621CF5488D3F3256BFA22CC23C49BE059DF96FF66D4C5756B6F79AA6375B718F2B2CFB794F108DB01F9EAE4B21CF6F4F9A997FD2BB62797FF8F449C484EAFC62DA8D6B00753B614AEF05FF5448D6111FBA45EB13435FE9AA1698D8A8DA391950C0CBCC3D6C3E966F2C132B8030BA274D22F5601D324CAFD1F9A6EF87059D9F7B3D0208041B27681ABFC309C1D0113BB1B2DAD16EE01522BEA4FCF271A4BEF428A7C66E237116A4A4310313403CD6596F7C8F94AC1818C3492428B1B0DC1EF747281BC9293D1EDDB357668D27673B7AEF728DA7E4DAADF21951C1D07430D672023414FCAF456DA7A39F594B773D5C7EA66A4F94595CA97EE3334D5825BE975B38BA856EC9526D911232D5638F493A393ABF42282827E67806D6CCBA59E3B7AC6880D077B3382032E51169A56081D90A24D85F5381FC76ABC3E520D5CD99650AA844347E0156B5F7F8D417CEE990C631C0EE587531B7399B73B328538FA226CDB3C35E8386B26C99E764F4D42C654B255CCDE7CB311C01DFEBECF018D459447577A8C5A3F9C4840CA26BA185B78209FB3FB51F237406406E005A4C419C76A5311C4F3646A214E19DEB1F07DFFDB653CA926EC3AFB27751F9665DDB1E152CDDBAC663406B4DC5552DAC580148835C6C8DBBE656F2B519603B19C7E79A69416544B4F99A6CA265150A1FB94D23E4F0CE270BF19E7B7829A90C80553CFED44650417F6CF91F038F9072E61554079031F706409E66139845CDD75E554B349EEC294A92CABA1BA6245623518F470D2D4424A967803238547DA575AF48AC4F5078D28A6611AFB29884D542DBD228EA97BB7C38F5F328829BE6BD24190DD8D80AAB57652E34D530B5771001C45807D17EF5C2C6F14BEDCC0116C942A98CC3BA5B5A57BBA8FE644B76725B945057330AE4C68A574E9AB3BD7A78476D3712745371FDDAA1871FB9756595E935BDBB6DF34F5A0D12803422191AF94EB54A6D0653D59437339389BAC5D4F8283B8997D6136C16659AB4FED4D2B484F2B6E7E64DB28EA40977CAE8E8BC3B2C009B55E6065E96B5BFC696875B9C3D7F3979CEF03E23ECD3067154AFBF04AC711C58A02CE1700155971DD8E86565070C04B1BDF2399D7180BE36C8A8BBF34B5F6AC1E9BF62FFFB52192D73295BF55FACAC86CA7CE7D3EECC32EEBCB71C29A19F53AB69D1B448A304958195AB32C8D7952455A4E1C25DE3BA91EA06E44AC83872C775F345F9AD3E691C1AFCDAC7CB0A077C7292AD5B4C010109644FA2515F9E501851EB250F69F5445BAA9D1C063A7CF6697978CE2C71AB8E6325EF2E70ACC2CE6DDE0B388F1D03A0AF212CD177BED9DCD00FD381559444F563AF6705A0FD42E40A969298B8D52271852E57A5545B410FFC4BC9AF5E518780056D329CFAA31B1AFA41199D76FDC4E44B98F9FB2FDA61ECA42D7741A163D30298040F9D27899DC8771B020827E31D60814C8B4D544F77BF67CBAF21E79A3C95070D1A57B622C56380AE8B6FD5CB5148BA9B495F96689A508554E2BB4986C185482FFB9EE590CAA69F4E41E68E542F7BA0AC15C9C5173533083715A60A72FD46288BBC5EBA4E4BF9EE8BDCBFEB5CD493A6B995F4F6B99A5432CE7BE0F3940D27C49604FB9CFC52FD706E0B777A7049BDC719E42E4FBF3ACBD934BC62D7F8980539D4D08EA99F1ECC876FCD7484607A95013458C6D5BF14BF3EE6E833870A044BBE004BA20833A7941316AFEEABD4715F34FAB6BC66BDC1079FCF98819EAACA614CAF43507BC94A3FA63CB002938C68D98E898F8CF244CCA23D703AEDE9A6E6D183C43A13FC677CB647956CA775ED2C38FAA629D04E4E5774FE2752FA4E9EE2B257D665E1C1E968304EBA5AE3D0A87B466A069C8D4D46C2FFFD76AFC2E8BB60C0AFCD232C4AC56F43738B3DA46578287D970C7F8959A0F820ECDECB6A38637E415B00F002868593061043D58A8FA42A237B61E3351BB24942C7039769A8B7F8193BB98342B621AAEAA00DCEC721FAE25C9D1C5D4AD57A4D2E473DFA21170E38A969792AB4C1FCAD4B2E5D52269EE988941923B1A8DB3D190B7CF2AA92F5E5AC3DBED2369913B3EFFD225841EDD269A06DF4F73C3E85E56C69E54B125E8BD2FD79191A6F43C6D9238F3A5D9A36BEF70EE38E016A36FC3CC07A94A63110086EC0143A8DEB67438E4D16242AD8D6133D01F6962E6C2F84AFBA07D51DC2E65D6BBB6205E0871751A2204611986F4740B2931EE47C1AA8AA20C1CCAE2F5566F87F89C12A18D4D74BD5A06B98973E4434489D48C7E2B8996C40D5CC63B3BAE199E8E3FDD30C3C68092FDEFAAB10FC1D028453B77ECC529484F61D6F5A141A1E5710FACA6E1DA5BA60FB98EC8371831FB846DFE7D52AF0A60B185E27048E7DFF00B7AFA61C710A7C33B6663952399EEC31D4BBA9A15709CFEA40C2DFD6A100884EBAC62BAEF2016AFD1BC22ADFA6213AE54BD0CA929350D36EC46474AA524187A34578C60F1E7752CB29F3F4EF42EDBB15C78AFC63CEF839DC5B44695206A8AB6D54288E998316FFB13C8D41A1259188844B3DD5BEF5EB0AE641B9868216F65DC2A64747EEA9005B7BC07BCF98DA6B5F93588A5F9B609404EB9BF2712412F112EA7ACA8A6FF40BC3EEDBD350050483C1331006EA15F35CFCE2E153C1DC4AAA5093D9813D4461C72F27C3F3490B49190CEDF04DDE769D111B18B49D688093354EFDC7A5EB3CEB10458E766788D379903AF5FC321A7F6D777C694D41F1E3BCD7BA1DAA4AB25E4A66EC3843B08196E36C27DFA03F4CDDDC6A0E8114C1A5D4C44100B829817D770DF24C4F10EBF53C21410B0C33008D907B795ECDC38B308943A4D3F93D5DE38024D09E446D8B75B35F110BCCF066E363A7B90119212C44526011163D898FAACE013E99B3B9BBD5D7DC27324E687EDD282A3F80AAC0D0F5000000000000000000000000000000030A111A20280003000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 28 iteration(s) +mlen = 32 +msg = 8303000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 1BC9C862B16DF16D48180EBB9AFD2ED72A1A420BA312090039F5DA0D4FF270596D4C762F8D3DCE5D949DCED4CFA18F548937167D4D69D5B13BC4F7706B5E15A87B389E44CBACDCC955190AC44465DAE66DE9379AAE42AB771592E5270A0723B7AE57235ED09AF780C861B0B440EE5B88E396FE3BEA23F76FC714F9DEA39160610DC75414158299D59B52A10ACA0431FE1F322FE46492087C0235F3BC4863A7B83C2A4A72AA0FCF2A1221D4DF1169FCED3C75D7699ABE3287ACA2686539D705BDD7A0A4CA4391AD5C68C5D17B417DB850329C7A00973E0D46478309895762C8B829023153DCAAF7FA4F04D696C6946C991C21D9A1BFC00B96998049EA15D9ACEC52BF416E54F6FC28B1E9A3B5ADD96AA52431F1D361ABA4AEC723303BC351CEE44830AE4C16D7EDA53F418D868E59534CFFD23B88A982F53CE90380B4F9063D04AE820D1D10A57B523A62C023EDA78894785D3F462AF9A3A28222B99552519B64337FEF4067444D3520F088813A13089CCDF1E44A8A57F88D76B414351961402BAA4D717BF0F992384FE1683DF9C3DF07D53ECBE76A21C4FE175E25902739637F4CD16727405493976A4C196DA0FD1E469ADB8CD0C3DE4E3F9A47653BA8436448F62EA2F2356E0A9857CBB748FCEB355AE43C6B9B2A27B5798E86A0EF51924EB1FF2AC7158594D7D2983955FA2B613458A18B957E7D6617381C03D2C20047A781379C0C0B6061AF041E1F55B3963B7FB76D83142A9BC4CEB6131CD232EA0B173CD9141A36C1B8956D4AA2574B3815E35E2D8970D495C66A599F347AEF6139C6AF132BE62D2F8EB4574CA209CA18E9072A3C988748F4D39405D1FB617613F665D15CE0B744AFA4093D2C6D3AC6AB7F5F520E29B0B6817D7C7A76BEBBB7577A48D2405AFE79334A56772B88560667D46D0698EAC1F0483DF4671AA236876A58D15D2E14A17B65E07E5ED03E9496CD5492B08BBB5699558908120AE9204B2E3DEDB83F9BE70EE102EE84AD42A0352DDF68E86BB44343E6B6D2185A7A4DDB3744C2FB5DE2AD7ADE6414C85B684F1486C3854834B34ABB1EE199DEAEBFB9314F69ED1A2BCEA581998F474E315259F62502D54C2AEA54F4ECE5A8D8F298BFE609E7D5CFC082BA187DDEABFAE7A58D83A240E49068D02DC36EC4D76340866B617EBFA1B85DDADAE12D08D0A6BF905D3CE11F172EC74FD755B37C2DBE13DA614C6A732F44C24404B1C9ABEC1000956E1A630CD3389372D8A76616DF2714FAEE5D5AD754143A530B02C7A26DB883683B13E847AC2CCC99C7F8BF383AF93EF7B92FE780E1EBD4B1CAE4740C20FE7C5760727436946A0F91E72585819D988735945B19DC925BDE22F52DD32B882E71052DCA1EB39C8C4E9C169B58D4BBDF5CDE68581087F1CEB128C15618EF43F6BC4011C17892F35A10A78139B1B988D4B526EE4513356E280E390921A093DA926D9C742AC710A6FEDD23D616BCAEDED70BF84151CB66A69F09E6834621E78AB217E2EFFE52D6708EF7F1B4343B6C76263967D7BABCBF7A6850673237243E4D83C5DF43007D184F7CE4AF6498E0EA73BD32E2EEC046CE175B0062653A8EC704A5991FE2BCF8EFA6898099135814D813844CA2D6140A98AB4C95AE9D6A5121E252014FD9C9E887FE251774EDDAEDB8CE3681669ADDA972BD7A1D16A52AD6AD19E4FF02D486E386E0C2CA3157A3A666BFB4D407008C03F52219E2649D962EB7C15346B0ABA2815CD67CA360A4D168E5ED9BCD2EE60498928A9D00D7CDE750D85844C82926AF0F50808CE3EA5E80DCC6823DE71F05C171030BF13D93A04F1C156E66CA8D22B5DBBE8B44DDCAAB9CCBF826231F55ADE99412AB6ED7AAA35CB12A944536E1BD36C10D8181FC89D09F84BFDA2D8DE32C935FAA02E267A3FBB6E8C3A44A5CA166EEB2788F691E63518198DB0B4D030F85A2E38EC7F4E8D7D9A0D1B7EED1139FA8EAAD17AD2AD00F15CCC09C715AA7EE5A703291276EECC0F4209077AA32EB970B73AC3C615DEFEF689FEEE8895912DFAC4611D6B834A96B3B9BFF1538E07D88936723B6F4A39CE7C4A679078D634C92B8E9F349F203711940A576FCE501C3870A3DD4FAC09E5C8BA03A114EBD09651D5096A20AE52F0BDCED915D6C8F7C7A23B8C2D4F79FC38B5A78DEA3B628C40889A4B065E38387F260311F36F4B1FEFDCBDFF02CAD18CAE8995B3094BBC51A96F51F638AF9C299BD79AC084A13B307FAF13D68F3140140C6C3A9C8CEEC7B65EA92A9A5E5B7B8D5D3D1F5CF48D7F42C022AC7CFD77DEF0F0998BC46EFFB4FD69A1BAA6ABADAE10567E9A4B685778DA34EA1EDE2529984EF8F6336CC07ACF730B05014054856799540D0269A2E8270465137000A47981F92A07FC202807DB5F3983136777B6B61D3AED5BB093A2A6E18A7B4C64F9F0FB9D920B3F7558E4C09D62AE690435732B244104DD0E713621A4F001D2DF4B1323A1C826B469E3DEBAF80CF753A7163C069AA4FF1837E33925B4C9AE10D8B19BA9A807E8CF6050B0F3F9AB2959F576235704622131ACCCAD1B607FBDE6DCFA840E6B0656D6EB62151719E082A3204E76B11B0F583D07CB784710F654E9FDD8E9A0ED42884ED99B7CE601FB19795AD3ADFE936941D14952624AD6E75D675A1343A2D4F0EF56EA19291F6308DB666FF5AD0BB73701442F1863FE7E82A29FC670DE6019B93CB233E7D744DE7571D02E85BD5C50304B2760840F6A4838DC0D0780725988FD52657769E22769188236269BDCD6C89FC3916AEE8B04435799F5E74FE7E986CF31CB263A77C2B69DDB452BF3C697E0CFE9756E7BFADBAD40E99B7420C07B7540CD1B48036ED3096715EEBB356E0EB59DF6A9340780068A269ED91FBAD22F204DE5C9F2EF819EEBE6FBBD4BB2BB6C77AE1219DECD680D933DD15720481E76E38695C0A1A93B17F90F32D53A1A89124EBB7B686C0A96B7176B913D39F374987B8BEC493D80B75909788BFA389A9E5B546F46BF921CA4CDD91ADFEC87A91AB66D71F92FAE2644876AF07DF0EC3A5CAC2C4D62D97DE6F9B584F6F8A889B0EE4E2A2143A4566126C9A25E3E4C5B4B4B92C8F38E7B20F26AC5FB0ADDDF50FD597A9202DDE1CD8B8DBF1FCF3DFB6CFB3B7FBA249E94FA6DD61D7C03D5F8D010E897AE69307E3382E275698C6A9D8D728DE78FE754C5771E25E92997D4EEDEC79B7BEB3C0FA871E5A2EB6F0729E33C724F4BABF5782D42033C75959CB9F4C37099D1CAD2560C1A4ED049AB586CDC43C368CB45CB73E504F491B0EE3646FCDA7B210CEB531FB426BED577E4D468D4D18BE91C6F0FA2B1D13427EE6BA551E77930FAB959643C3A4E195E61893A8098658B16D549859CE4233C699A6B18021B33237712795696D78ABD6C3F180F6A476DED3720158B4EF011D33E2601D458769CEFB14C36EFF46C32C5E47DAE1967C46BC82BAE8AE6EABEB831CF7569344E3ADB76715FDE48084581BBCF6CC736277B28BF258B8EB7E431F972F5B299108B3CD74249D97D6B95DDE7F94CC9280FF1689E2905696301B81799BD721670C88497B0140EA8AAD1A853780341F2936CDC3D39375567866D9C255EDF95A3A935475EE0C35E81DCB138B996F33F5295CEC3BC9B94AF55852BB70330ED6545C3C6A6382AADF25BFE8A34D117C5F655C1DA99A87D21B131AC3A909D80C63922EFBD0ED2B72E8FD2E9150415C6D054AA609F45C1033A37528B64A5993F749651370C631A429E96FA141EE220ED3E7A70665ADA077C3DCB8C1B302AD671A2A67FBFB350B8CE3517C64B90C6D434923CB33F9C5C7A18436A41BDC9BD792BDDCEC9EE1D27CE4F20B4841A01486224C8C8EEB0AE875DF92896F82A67A584F6BA1A4C71000EB549C00206D41415C16479740D18089E910A14281B435A0D014C7CFEACECB8499543B4D5709C6EFFB16C0F947206D1E06DFFD344E98A3BE9133CA6462DC7CFA364DEFF631E9169CBEE3B79859F4951C3E2267C6DE922C1EF4BA4EB3491B4493397DF97B1A9B89384E492E542DE2511096DA0930B360B92CD7B62142BFBA4F8D7B6E7EB3B234BF50A2760545EDE546CAA7B5A020AA92BCA66C909D819385F98AFB19D56946C6BAE17BD9DC2D1D9AA51C1CF1ACC9F03E04790BE9E0C1585D75BFF0AE21B917CADFBC33FD5AACE13A49572DE0A9CC50C6BC2D7FEB28DB6AE4B362B3A23277D6A01575A9646A48FBD18CCB190C0490CB6B038638FB962B3C159A542BBB6ECE365365B93516D0B5F5970D82DE06C397E22001F41E96260A389BB1ED2D8D76C9851A7CC1A3FA3D4D98EABBBB679CD952D94770BFA76F283170110BFC719872C32D79C18BCB7457CF85E880C5BEF6CB0356F7FB2C5F190982FFE0BF6C5CD92861F3FD8175620B232C084AF4EA68D40C18408BECA2DC96CC02B11B07C5123215FDB152C1801D5532069BBD3898D2181BC00F0517995F4D5EE6CCD4376C346C6D6DF6C3B9C3A8EDE9459F24A5680DFFA2399EB279A366034EB0C7CF6F551B0E37BDD5D3F3595B9012F685BD2F67AA490665C81DFA5EA3B7E340D55CA7C4102AFE9D12BBE8EE075B8DBA97C9CD30FB8455000E98BFDB83F7FDF96C3A9DB7B23C4FD7F83E490C0F5B5E77ECF9166075DCF92E3950578EB024528C93959D9EB1BFDBE8025D6E94A0A2AACAE8EEF1071A21305E606D7478CDE0E3F30000070C121D28358303000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 29 iteration(s) +mlen = 32 +msg = F501000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 8C253CDEBB1BA5796F440D3D2AB09CB0498B8EF4BCE107D8662022FCF322ABF787D74530CEAC9E7B0D923CF8396F6154DA88C9E566EFDB82BF5C65E73E0D663022B737130269347938878E233DB8A375232AE2C335DFC9AA8D1176A02D61CDB8574952FD5358F9628F03AFC9FDF6AE1C80E80ADAE06F5E8E327891F984C1C657306FC4890356861D69F07E06DDE87D05FCF9603F83DEBB6071687931F168CF34EE9CF0A4098B2A267D7B221C87AB8A39B5A1A624006BB96EEBC8D4D1244F9FF9E3CDCEF6745206D52524DBD6AFDF90BA7987CE8DA6322644380BB4C7F226E53DAE556683A43C2FAAD7D4A37074FEF5BF7D9466DC56ECBA6647468ECF92DF324C8B1FADE1240D39B9098A06FB33C4D201D7B501C82F5C4B29C17A3882EF2B10A3BDA10DCA0B0A7797A00E72B50822A3020DC1CA4458D1D80997D3BFE31CB4D3D6B20A17FA901BE64602AA79B0773070C57A2B263C11153FCBD3AAC5B12931D307C9FD9431566D7D07AE6FACDF8565E4EEF6FFC3B03A4C27A3C807C9653846029BFB6F3A99E08B5DFBABBF3A170F5236E8E7A76971A27C462B4CE370BD8E0FD33645304BED23C7DA17EF045F587BB90373218A767A7B5189A121DAA38EB1F45140957F7F6B90102AAB9031AA0F2CBF58F5C9E19160A2D52F93B0901C715B29DFFFBBC8C4FA8787A28DD0D90B35D87A022F3686486ACE972AE6E0E686478C7F6E96F250D60EA023329140A4CBBD2C79BF1DE5CAC656A2F1DB70D3A9FF56C84959AB72BB0F228C42328B08933771F7B5CA46C3195B70F86BF702EEFF671736973403E50A17B10E1598C8A53869B81D1102973030251D6D339474D579969D44A33044CDBA3D99CDD8287A6FD9DE987BD233CD056B4E214CF5EB893024FD75E4402D97AC80F753A127E67E1EEE717E3F0940763CBEFFBED94D8065B65755C2BF2C17ED323CDAEE4678E8D188AFA18FC17CDF12C82772FB6BE3032A47B156AB4281EE0F7C8604B6F53C8936BE92D09399F43369944E9113A435B351A4F9649EBF5BF42634413FC8135D0C0D21A2C2869280CE9CCA7A7E13B387A0D9CC9B60C622994A02BEF55C4DCF0F3583388B7D84ACC7E75D208B1886772296FDC6E03E538B48D7750518557E1BD161AACADB98A702DB7C91FEF6FFCA244DDE2957DFE1E35FCB8D0604C953A9C4FD6B4870121EF58D2F98C66EC1DBD608C46B6E38D6535750DC6AF9CE628EAD48A53F64C5F9A6AB9F9D92E922DDADBE58C5BA6E3A57527514ADFCEF0C60F125CCEA8B5DF9229AC325328BD761E03D03FA541913846962C50CC801731EF4EA39A1E730DE15C7E10C9B03D8ADF15EEA6E54D179CC90D090F04A665E8DDD67F29FF265784C61D98A2FB74C0B5916A00DA89FDE2250A44C6065A270634B259F40A240E857487D4B976E953364D614B4A32DCAF907E69303F0DB3B3DA6F958F6336FE0D70F49DDFF907D2C6F2306BBBD26BF8C1D0EE8512CD671D1D9313C75DD1827157B9797D2836F6C89AC85683FA6B321CDBF5DFCD5F5F5F3C2C191002BD07F1DBB6C502CC97554D44DBEC0BC0615059477B6679A03DF31C8636399BE38E068DF1387B9E8A36101E3B2CA1438E0DB16B7541241832AEAC355B00C70A47413A0CF10572DC69E809D0B5D1960B3CE789D94396A2B91CEAC18D1296EFB98A7872A95656123B4CB94B106FF602C371FABC57CD99A2D76B75EE1FE813BE4DFB099894B9E01D824AAD6491495DC12FCD6C63D73CDDFE8CF89CA3BB45745EE697F69CB0696E2CE96DD71CEE0060518A55772B93C8D3B9F430276477280E72EF2CD29780C706AE7577439DB3BBE329CDA8F4699EBD1D60448AE1D60B6F473B94B341188016CA5B59DA8A0BADD45626754635B65602291A70E25900BEB414487C2B73F591D2E55AA4F8D498747523AFBDA08AA146611C6260D1CE595B97FF7FE4D36440DDA592EE5785399799B1D1A1F1EC6F62B9BBE5C862F03B6D30A03D3B291031FEAC23CC92AE7F2F3C683E702891F5A1850EF566324CD340D7F48FE748DDC234FD0232B9258E55AE80E16ACE20A8E02112CBBA0C1DA90CAD25B13B3DE3459ABAF495C6E547B67E5B93DA9A538F19759BEC1A32AFAC1362EC437324B65D0DC2584749183C0707C83CCF840263F75D0FA27BCFC88AD905E480878DC64B1DAFD0DFDE7826C824F8AF0DA8B6A86E2EF465F04039A54694CD12C2F9B741B8D560EC0B9F3543EDD978778888FCD0A2F4299F7444C9D7CA48A41BD170AE0BB468A9B2ABE7F50688ED04CCFB4E382A7E287893309B9CEA35EB198BB5898D8A28E63B39151715749E4CE70F07BC1B19995676BA357B0BF5716038CF7195E50FF7FD6B6F0D9B2779C250B5FE7FCC64664E410D5ABEE8240D8C4541D01863AFA7317B617E293292A3BBB4ED6E7BEB5638A84156AC6E99C0D46FC05A261695AA7640CD8521AD7899AF6B58BD45CCDF21B1083EDFE8573495E866DEE9EA454301FB920D54E8FDC71248CA41F23C2923EA7E88C21C2F5407FA1632ED1B6D6DD708363718C1F0246B33E822A41E54E255627F8C25AB671E90264B9179D217BB2A3FB00A985CFD7EBA959BCA17F68900AF1316A16ABC929FF5B9FF30B0D4BF32672A04B1671B2191571CC57665050E3D37602D161A7C830DB43A4A244C5FC9929D3B55815E25D2B53F46E56109A0C3545D156DA8C6959B610B028E62F89AB57F0BD6CC71023F7D5311FD688BD08185F6A21985785C7CADE83B64703DD2167B6C31795A37BD306F0F8D964C004034A6F7F5631364E0684371FEFB6C4DC93857E68CB9A07F0039C1CDEB76264CA83D716B5F6B169863B6F4FE89DE74371D117C0766D5733BF6D9B8CFE923ECB9CAA8B6875C34AA48CFC67E9B19CF88C8904F4B99396D3772268EE88FA0C4A5EC855E196E977B6299ED1BA98AF54F6FE5209595DFF4111EE880F4EB623399E0F8BD5C795BAF558699CAE469AF914DECD453DEF58DBC5FB25D701E7724E26F441C884B215949FC909F9B082EAA85221B85707EDEE7C013F08A8F734A78AFEDA72E76C43F79DE08543B2EC20940604F3FB8C909D1468843E3E725D3F9AA29A8066D827CEB5D9ECB395D73894C8A339C6C3B6C767D50FCEEEF8B86C0EE5539DE7F1FFAB4FA24D24F133026A48E97128FBD133E1267552382F81416EACBBF4336856D01464118EC7624DFE21D3D4C2909A0EAB355D91F87F6FC1296C47DF1D57DBEC8E0DB94386429D0B0F9D59D01CA6EE187C9BA564EFF5BB599FA587D5978CBFF76A172A19CCCCD6A2967C67153E2CF9C15D3E56DA95BB71E6EFB0083DB1E1A6BDB566B06BBC3022D0CC6308161D8A5E2F81D3B883ABA02804106412BB7CE257532654220496E6DD8AA2F8101E8BE2DC64225E54D30083AF043BC7085782EA0B1E99EB7128A453B9D1BFC4D4BD78091FBCEA849CF2E2B0B7C5909ED7BD94524A58B8D56FE87207CAE9817039A4681C429B19EAEFF4DCF8D6D75CB7C058687CE6E27A9631D39C4D5DFA73119871D8B91E59C677102C25A55C6349F6165593945C51101A1F939E6975F77C89853B6074CFAD9BC7AF620E9D1D2B869502DEF1E697988425DD079727BF160307F5E04551D5E97B291A345C3E3AB0AA7EBA4483A43B35F34A9F3AFC41D525F83C5387FD78AE8B629C4923674860C74DA16DC10123B2A44BF339187F389A89FD75418DC5624E1A4AB48FDCF1F389C8A5A9B7B52CD987BDFD9C7596AC3123889577AD6BF4318987F65A41AD8AF55EC5DDCC5E1CF5DE31BC94BC3BF214D2CCAD36042EC2E36FE79218D4DBDFBE6A6A4FBC6693319BD7FAB023D22EDF401D297D2676D134894B68B970ABD4F0C9105A31A4F8375359950D2AB59B018BAB399994537BE6545CC79B2EC9FAE0084CDF47D0E08D7E5BCDB35C78A63AF8D92FBFD760CE8979CCD7BB7A0A70A1E4DD77656DD7D3EF1E77EDD2E17E0992AFC5E4894295F3CC2C19C5058A95FCF33894710BD8A891F637CB55885EEFB0CBD6B3224D23CD5766E054D7DC87B50797A9F6A8E018E8EFAB48D5B7B70C73A5EE62EFAFC2E2EC2D9A5019AD54188F5C3579BB882B60C738CC149D743D6CDF0320BBEBABD420F50D894904E0FF55813838AE5F5D46743A61A64ABF1B4349A72892E245A6E744D8B4DC3E9C13A1C5C14BF0C6FDEC64E8F372F570B038C4B321BE6AB1FDEEC3FBED0105F77D13450EAF4BAFBEA36FDFFCBC18AC309D4467CE56FF7B0D49810865C95BBE564F16DA1EF783196C541A89396F44E09F5574264271CA5A1306BC1B46BEAC94F05E6C0E1446657849B8402BA61D1473BE762C4414517181944336F240C0963FC41538F9791ECDDB0CA90A862DC71F215B1B1898FD4B4D26F66BDB1D47E9AF059A2CDCF03FD6218422E2F143BF6B69DC5B4C9D1C313C30993D9EFA1C9FE23D9DEB38851605D062656F21DC39B95E8752C054A54F0E43DC9F0D44AA195F3408DF5F33B62FFA3A305B272EE4E72D29B9AD0F3C09481B208DFB3265218223A5A13F71C64E661233A0052839AE36A3402167D0553728B3BE519A043D16D3BC54AD1C0775CD1C290C593A7D31D938C1FAC92B45ABDF1EAE7B0BCD55B6FF0554E79941A808223B516C757C87888DA8C4D2DAEF2663D2D3D6DEEDF64DA1AFB4E505326166A11A3A475C7896B1BDD5D9F4FB167BACFD0000000000000F171C212D31F501000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 30 iteration(s) +mlen = 32 +msg = 1710000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 2C85FCDBFAC8E5ADC031CF1EB284833D0359C84BFAE3996C50FD75D3C2CDC4BC57C7BF72C2D23FE22B41DEC00949E828824F7B9725D473FE934BD374CFB1B27A790D21647EFDF916D65E90BB6F8371050005D23C3F2C31DA7B14A3BE22457686594AD526E0B09B8F92DE2B1A00C0A4FE4A7217680821C7ADC0F62FA3AF98B3278A1E0CF7EA351332F891E57FDD51965663F20D6D96AD7D8053CCE022DFF296346442D19359CB24C726BA6C6A61E36231FEDEF753980861A11270AE043713C0865683516D854D5F375D694B147A23767A14CA4C57FA3E66F29578410D104C5DEC4AC0F55D0928B435565481ECFC12DE265AA89910AFA4C7C265E32FA3EB9783B01904F71D3C3B9405F70A794E04077A3C94301BB75FCE0FA263098BA425E0223AB1B74FF1B1360D744316036DEC6531D29C1448176EA8102389704AF4C496DD85FC9205687DA8F65B3F4596B79BE1D8816BDD059F353A94F6D35EFC1B8D3E3D57A6BA56D6B872F3A6C082F5633885577448003FBF56C1F19DC84ABB9B292E45FD8F291B37947411ABEB9DF1D7804F964538CA438D5B3BF27FF6BD9F3D9237DB5F0EC1855F7AE6666BAC62E6171DDEC86C1AFB4B90F0BF897C0F244BFD4E08B4AC11A911871D94879C4D8DF68EC52E01DE4896FB0F7B88DAE0DD257281CB9DB2C78DE846207EF1DFEBD66A8140E1E5C8D7279CD3B18BB89E0FC7DF4BA54D84B73795298F41403C177707771877078E13B1DB8C1EE9C36AB3F3713B52C1DB0ED49F59FFBA264D33701A088FCD69C6B35AFDDE9E9F74DCE5A01488CCEEC00481DC6FDEB3FC2E353A98F9231654057CD815EACBD92FA1A40AEAA54F868C493EB5649A13EE296B2D3300C850ECFE78A26BE1F7772FBD9C3C21FDFEB02ECC93AC12ADAFA23EC51ECA46D1DA11F6190D0591B6A618D225E8904E0C3E3B041AF3DB8A94AA52EC9F0167A013128857E7181C2E719AF102A6C6E1290FD3F69115FB1337D8C5FAB380E759D26120439E49FD89346E4838D0BDB48D7BD6D109BE98460D355638DEA4876A4D2A5AD4C9CA7F72C1C9AF8F35EB8765E4EE9A7C1EF5F615599E183F734D8E76AA9BA37998AEF053F2CB5DAA80650266DF03DDE03830679611F365336C93F98A3709177B6F97DF307D9984637A930B7BCD2CFA265474DF1183EC28800A30ADE5C6BC6CF176015AA43215C984AE7F255F7ED7F62C02D40AD1A705AED97AF97E1F3F23CD234FB24100C5DC659309F1E51B973DD89D695FD1341E3CE9983DBC165C46774FD4F66995221A81AE2A583D0E978CBA226946BF4D132DCABF647E8D1D2094B06E9AFB6A5BF1BE91403B0BC0E1188BA2FEE9D4271E7690CF3A95096D7515C98CF9189346C5F21E72DB09DC11EE2645D8E16742E68F47937858FB59A4E114E866D23CECC681353F61D22FA0D9B0D8B464A8F8ECF9E8F46EEBAF37AA3EA60E125B2CCE00FECD2A24A543075D4969CC7E1544142B8E46495D8B38ED2873666277B8B869514F756F97C42A762105F3CA6DCE3EAB4E3E552F4D49585BDFFDA46DD7A54FE772FC877AF3015859E23051DAADE007D23FDDDC883478FADC400F109F34E72B8E1A513DCB938889C045F34CD69D837DD4D40B77132C07C99FBBA68AA5F327A562495A683928F38EA43112E1CF5FB2B66C0350193BD67B968A31B07CF42A6568A91F325696B386739F6634876DF32685F0C6BFD4CD16802C8C8E559BB7A631EDEC8AADFB60522CDC7D6A2F67F88AB7701DCB61AC74E06E39FD4BB853F008B15056F8ABF7469F5A0332D85575A6944AC0B746352424F9DE67D0F7F292F3F02E93A152491EF0F401F56DDFA825902559C38CFCB2FF0BD63CFD87B1D7C4899FF1DBD0B40761B85194D9DF1874CF7FF52A1F849D1F79AFF5ABD489F862585F27614B8F944AB091D18DBBB7DEB5E84F62C59E5E904F98B5BB0415E3A2576132679754E0730DFA3465B537E160C85C8F1D30198FD5449BB02D3043B8084C93E29594AF010CB2A9A293EB29E282C88821FCD302852453BC79B2902E1C786A64F4933292D99572F8700CB936DBACC3930FADE53977937F28053885052743813B6C80C4DD8CB27224B1CD8CB36ED517D0D8D52D06C6E5033471DD98AA09C8517F5D0666901E80B36590B65EE57CA83BD730DAF45518D0A37E66141B6397CEDC4F6B0366F8C589C85C3BC05A6C92920A950390F32D2A0B8DED5FEFF23AE71A24DA3DAFCCFB18921E96B5333E708C266A15372A1F8F4D62D7F42FE34A169B76BB0CC8357BE8C855183EAB2434DE7FD97B8DF8FC4E2361BE6C8395A910EFC0B44F1D03E6056D48B108AB470308D62FAF31415C90F1CF9F5AEFB1928A2EFDF1429F798C66EF8DFF4732791D3C440AE493234FCE1D9F2E35AF6BDC5E1709A3678AC317C8BBF644165A096F9B2835F86F23B14FB0B1EFDCEA57ABD97DB6CD9E07566A82DFDFD2E790CC48BBEAD0E2232B7AEFB84A614893C22A0F0AEE3F648A70AD7A2FAE3B44B5FD45547ED6DE7191375D9917449B536BF40856743EB44DBFDAF675DD6B493A0FED774A2FB89D4F383CA4771A6816409BD15AFA7641FDD9A4FF0408DCE586D9F0124E53886B54FBAE0A771D6C94C382D0281CE0E51FC844F1175960C92886B793123DF29712C6C142521BE06B7D129E7034746206484DDBD743F7969186F8CBD1F5E14BB079CE36FF7A46D588DCF96FE3FA635F96E99034F053BE26E80CE7CF1AC6431B22D4778D4B7EC970C2C7908854C3A13B21BC26A8B5B4399546290CCB98C1F62E5D5CA99C0106405E1A8A576B01613AD5D028C8B090D750718C159C7BEE7248055F655C5C4D38E89EF58A2FF24B5136C7503C08E2211F534582187CA30DC8E1245F261D25CCCE7B60AA5EBFAB491E94D612EB1359E078583844577359F533ADA0994FC3B107A3C7C3EE6296B5E5A2854DF74DD942BE779D7BA2D6AD6A42F2A059E57457BB972DA0C2B3CA996DF11EFB6184DAF4EA146DF4B8A3BACCB4D9CB05EBCE23D752A194B7AFFC3FE62E28C7992841D8D441B91CE7761CE8B056DD3B93EF97AEC940D518ACE392F436FC2653E63EE24D4C9AF568BA456F13F441350672206143F40E420AEB561B79A66A3DB803DA4B7394A43EC7982EEE2FF86169065330FD4802E167BC38ADBFD099F56475E1FFB4AE48EB8407F6EC4434F7A8A1CDAD4E278F16F240FD54A8CB1BFE1055B34A58A5FCD6087D3E051CB44708E47E878461C21E4229C515202B6EC100C492192D2FB51A0121607D51E322B818A1588AC4E1B2FF94D1E8CD26A974CC222339D7A203DB87F7F18E1556CD0C8477CD7CC9F8AF4265F9BA29E6934A2C2AD8047F4756FAB53653C5A4CBBE75A65D4A31C2FDEACBBC71CEB394792FACDC1C79D497D9664AA3A759121F741DC9659BE8CBC76B273CF2A5980752D15E0C9EAE46A4780CB17E74F45A4F79197563B5DB4CBC104B6C5E2135491C33D1ECFC95D7A4013AEB6E33AA81EF9E3FCCD7511AB11B5C88F4D580C1E1F6F406DF964B2A05ED4D8CAAEF82BAC1A45BF235309A8CFB688C0C1211A08FE26E5E808609B2EA2DFBD0AF98DCE934AA57E659D78C71239F9CF6E3E5B0248EAE03020DFB52CE99A91BADD6146AED77E1A879D5F87A964B05C871CF291C5AFE49759AE857FCE382E5643DD687BAEA86776FACE56DD08C7AB062DBF68D43AF4FBE3FB65912251E6A65655CA2A4F0C3BACD2DA37DFE5EE3EB7CD959F56AC98A8C70785BE7F08A2085FB7058F8836CD5540927DB3C94393C9C67C0CF750C982788B41BFCD19B281EDE811762D560DE5B96F353647EB81C3FE572F1B819749727CA56CCCC621B35CDDBBC99989357D7FD6F5C3EBE20F3BFFFF6C990A3549499A8A5B31B1BBA9B98EDE4565BA3E7373AD85C1CBB18C29DD1B39CAFBC8B96DFEA6A1478EA6B939EFF130F9A98E02A56CAD1025B097C50C37B8D38E31871E69ECD60E02827796EFC8B465B4BAF8CD9A9DC04ADD8A18C98CEE625E8EB82A798DD9F95586EA39E4C3BD52BB2061322947424EAA78211B9295E8EAF833D54EE8FBB633772F3F815EDE5CAD63E64ECF3A280C012BD05D4C855BF70909CB9D58A7A5CF5C88188084289FEFCA5B8946C082B192F7463172FC4E58E7807D1629834188C5C2D2E71D992DD4441AD2D9B9FA17F61A98CE106F26F5B3E668A2298ADAFC9E23829605E75BE02CE82F3F39CE214696080E879DEA08427D45990274799C5D852DC6E1D4D728EBD862899A9FE5E66137F769BE684B587F01F0876E2763A9D478241EF15A807978B150444AD94E9BA007FFC0FCCE70855E940AEA38E9BAA16C180296F5842ACDA8FB1458168A419172CEEE5A85694E3A7B639B6137929ABC9FE6C074C4FDC448178A4CC64D754956F3EFB65A857687A30AA9BAE4BD8CD9D59E473D95F98346E34500FC9F4DAA931EA21553DFEF45E6EFA1B6AC6BBC1FB8ED7C440F404F3BE0A7826E84C902B1BFB8F61D907331EA076EC028B1CE07A847B552C0391D769A13F614CCA41F87A23204BDCAA6D429B0AC56A7878D363E5F58855F5FE9CF19D4BF9C327C67B21E7E3EE596DE190301D719B33CB2186C1C861C0A44D26AD6AE9E6FA2612AA33606885CAFA32353E75BE06313E739CAAABC5E90D316F7087049EB5EEF70C103900000000000000000000000000000000000000000000060B14191E211710000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 31 iteration(s) +mlen = 32 +msg = 5100000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 01EAC4DB3D5AF8020D86FA01FFAE47CF84BBEDB7D6A54031FFC015BE4D2648994182C9DE061737191F16DAA359C2A134606B3C2816848A84DD0C60246CF17453005D4C0A6256A6A31DD52C7B09D0BAAF3791A22EAD92D8F11ED0B7938A481E9C2C9E383E13AF8FD06C3D85A50C865453453885DD62986E33AA42C6AE9B3B83402C6957ACED4A8B673828BABA64309835F0AEF2E74F67D0CFF227F71005CD43CCBED8CFCA53033BDE00152868EC79AE5C83F3B7B3FE4F954B0BFBD74C956C66E8FC31689B47AAA3E227428588F072BE6579BC2829A36E143A4DE51DA03A35752BF6C1FFAE7C6A5DBF951D634CDC81F7D661D29027AA5FB5AED7EC725AF758EBD7075618905C05278BF913A3F126C374382558859C8BF375F8DA8FAEFF00E59189678BA0EB29A5F557A23B51E1D560A982CC9B2A7134534086FC2E5B28DBB6FF1043B560FDFB4F4B9DA4420B7F7D283A3DD8DA2D6F9194C5D43E6CEF26AD05FD58EAD718E22FEDDB2816B455C50BDD5F776E8982F7C27EC7F38E07126B86E6105CECCD2357D1F459B8DA652C6F79326F20AA658E15654C95F73417885F61FD1C2BFA9B7C50BE0B113661B2B8AFC9D942F16D1AB0BB0E3EAB64126730A4B5D2FCE426B4C911E0421898398BD18679AC1890A82829146C5B5D0EF7EE58003CBA9EB5A8DE86AF08051A69D5B4D0CA70CB2A1623364E51AF673F7F540463FD4260EE73E6B12D518E68CF40F1532165AAB88E1BCBB9DA41F385C2E601E511533AF7B43E82CF67D47C72FB9AD3617F89017C825D3F0D7AF95B69F55F73B3D699852201D70F4ECA4A1EC59A59C1F4CEFD1739CAB4DB6DE0AFCB15A8B87BEC532646F3824F8DE6FC716639BCB887A70B2468E0740F970720B1F571DBC5594E5106897C8F514C9307FE41D6E9F7F04E09C3C5478D55EA213D84D27745FE11A7514AAAB5339661C8A1449A27D66EBDF1C1E7E95649BDBA7A382DF339A188494460B97174DD9BCEA52C0BC69A812457475845426B1A26D9CDA478FA600F25F09F8217C4DBC1A9D9A028A51259E9654D115F7889A6875952CC1E8162436DE0360828D63C2DECD077BA290B9C4992957189EC6385063A3B6CABCE3581C5F909435B5F3EB373756B5D33C29F2ABD530C03829FDDAAEFCD65EEF2FF143D5F4A74AB8C6B862647BA6925550E4D0B7E16D357DDF2B30D79E931199D2EB0B771FDD15CA7AD3D5ACB7808E550353B678C4F98A70CF2AF0F5D9CEAFDF70D736AA7FD755FEF92DBEBEC9E9E78471775A8A7953CCA04C021518BE6B3EC8AF2E65986359F0956D2745F6B4A5E0D3C7BD7DC3865BE5B8DA9FFB0CF77DD1A31A9624DA0B8C9F9B385BEC629EFC9DFF5A782ED90FC7C595ADC65C46E4E3CCB155BAFC102B861A8BE3E01BB26811FD7575ED3CB98593A40E30BCCEFA56C648A0B17B6DE9B7E67163F106A861C90FF9568EEB3C807DB49EAAA5A2BE38EF546AFB69DAFC42A1EB7A7B9AAC9E5C9E081852773DE237522327FAC04F76A64883C9CD158099F223D901153BE517F58DC82423B0B0AA9A6848B13B2E07D887ABB96E083943C0F619448A90932ABB31B276C65454C0DC65DBB014EA2CD0BE91C855DFF43B0637AD99E5C45F4450BCD2F968727E59FF86B50BDCB2C30AE347FA4BB8E4E35FED1FB33EF825B09D01BA2B736D080A6EB66DAD7EBED7A353FDD1F821FE8F3113B820CDAE08E04B1D031F3CAB521B6B6E2B371D67ACB911E63008FFCD206936D76E0DE45B056617FCE9A0AE0932D6F1C815ECE53A2071D7827FF2DB130E0B249A0A7B52A0CBF92D2D67062945C0DD2B12D3E2CEB302D2E33B711798082355E7839E4CE9173D78645991DDCC1DDFCBC566E24B79628F917D8B75A62721CF878F77A441298F306B99207DBEF11F5FFB39A651A48CDBEF63C539A63C8ADA3BC269BCCFE392802AB4C0ACC4ABCBB10022A57AE7DB6AAB779264D5DE066D74939E1EA03B815FA14130B94FB3A633BF300AD00B5FF8CB13D896C1269F6C5A587AB4BCC4641961EC507A900E9609537AAE477B6D64181C28D3F3FE44C6B07BC50407E7D77105633E994846E7D009784A3C7A2DF07933F69447838DCC8A531C9075C80D34B9C13A0A5C6412DA213F3A845C1E2BC38B0A99C0D10CC4EBAC342C137FAB6458DAD3CE12AE18D074FCD91B6772804D8C80C1300D14B6F383A0768311E02D355DB6DA654715A523F8776E1BF03B51D256E8EEBFAF9FB926BDA55FB38D25410429158B2EF6E789F633D6DFAB82483668594FD95652812E7E80FEC788DF5B3F3E4F1246C4C70F7C33EBAD179DA0E9E9485C0A1C070CA35CC0DAF43C4513FD2C6062273A54D3C779D876E251B6A064252541744840387695D4757E9B4D6D7C600CD635F8D2ED5A76EDA12F771D6164731F517599933471E34A9BFDC8B3E3361BCC2A6AFA4AF277583A7125B7E4CB9BB24EBD9EDBED2558533647F32F6590C396DBBAD1B7046129A86E3720347505A9EFEB23459378A1A8B54B4E7960355EBA1CB84F2E761AE08BFDCC52EFD9E4FA3F579365A4519EAC13F0BBF872C02AC7401AC2600FEEBC218F930F7DCA793647A7F7940D29884ED6A7FBCB41633552FF7DE28D4ADB21FFF2334CDCFFC33DB0D3A5CD42FA921D3387F20B87EA59D6871A3EB24C71B8296E3BE9ED57E3CBB69D62B1FCF19DB8F07732B0D6AEC22F29719214D27132E1303AF5AD5EE328E75B7B347052B2AEB4A98322E703EAD7FBB27D7159BC128CDDB06944115766D944647F644C8ECF45C71BE4641536A40661E473F7AA9C70D2B61B61CCE8F2E35B3E6E793EA1D103677C5E76EF2DB62353AB1931DE31BBE67FC2FEB6E817D3E534C5F29A9AEF5AC4969A532F9D01FF9E434ED135BF26C031A3BE3CFB990B55700954A0D280161CED882AAF181B0A43E92B7EAA986598853150C102F70B231DF612BF1AC58542AFCC0E003F4DA9C3BB86A2966E8746CE1F4A75C5984DFA45B6D84E1EF9DBA9DAECB9214BC14AB7D44C0B7FBEE350C4C74B51025D207545FFC6C53C05A8C1E5919994F46F596CB990F11F33BFD70C3C8452EEE7EAC2E4413C6FAEA3393CEF45E259BAF7E3405CB6F694DC28A905932FEC271A81F8BFF02AEB47DAB2575317BC3AD0DAD3A83CE81EFCEC0D6C319380004CF03B0267F775888127507E396AB6B6E3AB20C4EEC1B507DA32F5314D5CBF8790C3AE3171D76A8E3833ED9A236621B9C5E91BDD77D7A2F06EF59607AFFC2AFAADF55BE88F6C8D742B6F479E38FDAA0FA130CC6F835A67ABEC845C137F3A644B0E96179DCE4EB10504E30EC07869D04250311DB87A72773DE260C63F90E31CD3F059C4BD56CFF67B3DD4F45EF41687342669CFF023A4241A576B9D57FC74EB6376C90300E6418A730398A8EA54D759260DCF1B19D6BC59157159FE1AF193EA02F58DA51559F5E1EFF3C4222F45CA00ECA2DC9B2D7AFBDB600FD97CE14AC231701C4EFDE8ED052C68FC763BE4FB52019B9E6B6EA7AB85535E94425513E18423B2F7E0905E0535C7DDCF2F4AFBC1B8ECE7E7361D3EFD3A412A090AB999A2010ECA0A2664D121E7975688778FC2401A6076254BDD0995CB21B7C82D94D51F0AF2A4D89EAA35B5259A134C0856F791DB0A632FA6F9BDB3F902F4ECE52B1B323B1F14509C1CEEBA25756F43AACBD878E7A733F98E6B6E62221CC6799ECB2556F5A6BCF8F92EF8CFB44F45B89C6DD6525577E6ADCE1DD49438E90F12A880B0F85417E35A5369ADB315D9A2BF2F2A098848998EDDB6C0F5A8CDD3D331E0E8EA3AC796F7031CBEBEA2952974FC0038E511D01EF56A8AF181EF281BF2380151898DBFCC33081B5976DD5FA93A89140F51DEF740A69519846C7EF29CCE77D578A54DA19CCD259D7A2F255AC0371468EC0DBDADB228F3C0A418B86BFA44827D232C162CB0C3C48ECCA98331D4F2F40B6A66EC54B14585F112E5003A596645CE7F2B2D73E988B39E8EB2B12039A2CAC4D78325D8A06F8500E7CE1898D3CCE1DE236518F88006ED12EEB65EA7B5244F446F3F21FEBD9E7CE0C5670D17D88CC618981A679F415FC25B82695B622D6CC49DAF2CDBE96FC6F44C04367FFEF73B071A5A481CF1EDC9C96D6B4E44F5591C7C26B28A6F80D630C2503451FF6F051963EED1774B62772AECB4C0C5A54DDE4DCE004FC29473A71B5588DB929141E28A9ADFAFC1F2243F5C984BD1EBDF187B5137C07A2BCE7BBBBE72D9C847858668B7EB044AE04FADF395499F09DCF9937D4AD40D5914179BAE8E337D325CD65661D16F7483A68257036A129047C59BAE8F14A053C177E54C57F069C7D50E1FC87186D67CAEE5BF7E9E58D7EB4134E60F4337779F80BDD171FAF8380E87B9928D360D600E7671D227A0BA10C5EE01507B951A9793956E247D09F50B2BECD9EBE1A9BE34EF7EB5868A1E5F7B9600048947FD8607A6FED0A5AEDAC7D2925674D74B16F462A360965E6EF756E442EE17D1C80114C1BB93CFCEA183964032A14D0C2BFAC98EC0678B1C2A90DD130FA9EAFA717886BBF0E095FC29214983D2131E69FC9E63182867D4D59CFF725C909090F5F000C12BB0AEC5EF663DDB0DA69A12809E89590ADA3B19B4E2262E9AD04797D7F8E9EA4B13E5ADFFE212834464D50A4C64BA2AFD1E0E8044B5F6F85BE14426D6F87BCC5CF000000000000000000000000000000080C141A20285100000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 32 iteration(s) +mlen = 32 +msg = 8B0D000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = F8DD8FBBC21EBA0D0353DE9A97DE9336945958E82AF93C8CC5061B00A1247283888887C38034709D4C56288DE3175F1537C41D2DD3F0045CC0613C5E0408AA522170BE1CE10A79CBCB18B7E4C2120B15B6CC47909AF9D3B12E160D8000B2DCBAFBE4A587757C07CDD1CDE88466B31D8B425455964A1B3399A4BF222CA4F031A4E5BE6C9F921B078EA61F063EDEF5C841F7788992B231252B74261F764548F930DF5ED83736E50F97F8BED8B52A227561242B158BBA244C29EBD49C44C61EFFCDDE24AD5F2DA561EB7A47071192299A0FD4AFC27937D9E653150D31E7C13F66819F09D317E894ABBD0A2D61B820552A8E816F3BA8E20695B187EADFC86B0445FCEA20B9B2250EC38C368FEF7F7DB9C8EC0816C07835E8E61809F8324A5F3B5D7B3EA992EFCAC693CC4DB79D45884211DD4777C4E9C5EBE688EA263020300D100115692A7C5704BA393DC218A89D568A2AB5744BF37F294BF2A6C522E8117EF58FC447DBF5478850F2030C14C7EB459E39787A30E585C047C33677D03CAE36BFBF8866171CD7D26E4D31DBA33F956C51B12B26461AEF886FD82232A012CFE047CDA97ED3EB47C8130B9DCB4FCB12979BE1E067A5166C3BB1647B05BAD6C582E015C569B490956E109CB642E5EAE01668CD1975CB9C657B7D527710A10F0ED595AFAB34FA805B740DFDC6310C003A556DAF244D0EAA42DACBC258A4978A231B9446EB01CAD717F0AE6944E6DAEA99B9F08C0977CF7BFD188A1C997690979E8FF8D987D8A0417EAF643CDE62406795620E5462875E77512F0229D2B12D3FBD39E4E34E007EDE5C76E434AEA73F6BF104C62A7A2E7276402455D4F0E179F14E6B17B90F4CA5A4ED34D8D4552CE4654F409396E3A3532BF52BBE93F0533260640A76BD64894000A27BDACB6D243757E464676E57E4D0F629C3D10085215651D94D75225500B1AC7F5921F86ABC504443486B26C401A5917C855E0BFE548EC1D1543488A8F9560C387D14A41274286019449655935795AE37FCA42F6428649006A873DD71D292B8486E12B6EC3DCB8E440E9ADC2651F50756F44BD5CAD087779AF008F928962DBBC65AEB1B0AC916F32802EB41947821B3783874F94FFD66A066872A0F6BDEE21766BAA0E9D2F246B9C48FD65079EFE3F120FE81D8BFFBF36F07FA425FF4C1717D759A972A2B4E4121AEEF340BDE147EE50B9152EDCFAF191D4BD83D4C089A80D8EE1F9FF56C32D22EBD176ECD1AD78BBA09E575F0F8C6EB7A9B5B19D335C9B6E7543B1131130B40F928AF9A20D3CD399CF5F221093459ACBD060E9251CB80E52DAB9ED531DDB5F9281616314D17AC99A51F492C7176CEF2C49427ED767C8DDD6175FD92213FC3E6A99FC598D731CA01077D8537C724DFAFFACB565548E0CAA34755650294031F98EC246139F58E889419D0B75A4C319219E3B49927F72B3C19CD86F5F25FD58641A83C5583076B0B4F360999C6465E31B38E1E7E931AE182FA59FD37E3506E5D187DFBA45D54CAEFC1C9991ED5426334ACFC818A07E3BEE7F8DCF07CE81F824299A84A45007B42D318C12BB5792F45A02EE011506619156C05B3400D33731584C72DBD49C3E6B09CA9C1AA51C0CC6481BF6325B1CB77DFF6A7F6940CA80B974E12013E18E71971120A68322EC4BE3122A5F8BDCD3C7A7E7A385CAC585AD473C490873CE997E8CF52F8FF8AF9C2EF23E4404C9B22A5D0B806A063BA2112382F0A11B2D805A6AA8DA8F2ACA0F976A9D0F1A0A251D4FB0C5194675C369A025087EF70ADBEDE6191BE31E918061AC2304C1D2241482FD9C150F09E4357423F72F533913E34A975F71B69B3CE42BF52A38E35949CA10D623333498304CA2E8EF9641C5B283B1D1CCFD5345A279F90E87101543632C2D3F61F3BCA81362620439B8D4F1C131A34CC2C772C0AE04518416539C7BBA5E072E15F081DDD9950DC2B222D3814B126F8CBFB6FECA845B128D4D09A53717C944791DD37ED615A22363C4F2A2E8F842D4A3514E841865112F74D1ABA767C92C1F9D378FECE9375249D2BE01C95BF6A395231230F935B02955F94C11495E9CA79C5389679AD71159057E7367E6BAEDA9EED697767ECE1072DF2CC25AC5190FE92BEF5D7D56C135A4FD2741EE76481F72D522473E5F5B6A6DB1FA1FF9CCC07CDEFACC6EB9FC533279D56FE3B5BF046A1ECBD993554E38A8AC94FB09B05FEFA4FCEBD89AB8BAFAA76FCC16122F3A7BF4B97EB76FC6B6FE315C141FC5A1F63308C584C9B895EE0BDCFA139EAEA016FA292EEADAA1D2DBD72C1247FB409041A27BD74A4091FB9FA6244B4F8D637767B6456FD87B8BCEF882696A83E91554AF325DA9B481521660E98C3E3D553DAB5984770A5E22539D32D6CEDCD786DFD917524E7564196992522FC3CDD355AFFB285DE717355519C34EBF5209C176AC9534BD6FAA23BACB2FE87BA34FC92746E2F82A2BBB70551682C748A522695ED6930C6423FC5D222A3856A5B3D106C0B096E496327FFEC72D26EC67986686BC6E8F27B12A3460350E6772AD320358578C8949D14808067973F5BAAE5257D2452A4C9FC6249FC4FC13AB9568E6884A13F9D6EC6E5828D62C43AB3AD819664FB66E5758849AFD25BECA344B92D5F24A567B9323915B9B7803CE76BAAFBEE01DEC333EB63B236F64446501CDAF265145AE6E1A1CCFBC77C04DEC25680BCEDEA1FEB79862D4B02EBCEA0FC58B90909D75FD33F6FA940DD75DBC3A99E1EA62A47E6049BF6D16E913D98F1AE7AF115A1D19D598016D870C51D0C1456B4AC4C500020D4EDA7840BDE8D1216150D2CA7915877023339196EF35325AA05F1360F2E8E00B81177AF4F142F67EFB126367234BA0F62271B28BD65539C5D7642983791F61074E98BFEC5E6C15E59A346D26CDFC699365D711E65E13E4E2B2608DC79F4908ABCF5934F8EFBC78195B74A1E766FD9CF2F5EE89C8153655C6A7744768FCC978FB36D1860C2167B85C89F3A1947B2FCE55A4E14A8C3189580EFC1F52E0CD768FF0B579509E003DE240BC1F6AC0CAC3F0F8448C586F737244A4886D01F08A36510156982ED74852B52E3126BC52FF96B421A0A9C3D1D6B136F1104B62C4D691F645DDAF2A6A1E02F91AB23FEBE5189781BC266B66B963D20A25070F0C354566FA16AFEEF5DF705148BD73DC4D67BAD8464100FACF6A073C4647E9355A7224922590BA3BF1E3520658B675CCB0520C50C5D2E156014961CE4B3571CD0B7D5A40A23945B0A336DEA45C5498FD859CDD942A89C180134E5E324647BEBD50131A964A91CE1483347F2BFFB60BDD4C6669B19F5D019400E4CD5373CEB4C612DEA80F0B0ABD4EE6A9A9B849051F600808C018972064C0EF98998D56D7DF50ED36598606E7D10A4C16F3A376BCA8B6006BF7E1DA576064B0C37555D902C1BCCFC96D82F37F7CFB5CC15856C3B456BC1E25D02EC4CE469123C4E80D3E8F763E0345E7363D97D7F643287CDAAACADB79F815F8C857DAD8BAAD445B91388BCC43C1C0E9A22B993BD48EBE1D2D80BDB990440E0EEEE61C6122CB628C694E626AC74597D2E46149EAAAF29F97226E06A3BC78FE27CE64F7373F282F9F8FFD546FD4F42EB4EFA91483111E88E39F9B05013BD1D40AC2B9728ACCE4F6FEEA748BBE79191569411055DBBE998A39CFA496BC9F7F6503AB9CA01BE10127FEE2BF4FFB420962ECEE559870BA7BA0E0E70618838309DC8D61E7ABEDF50FBF9445755CCC5A3330F9BAA15E52C05A91CECB76D5B4E864BE1CB1DB91C37A6646C6BAB89FB5F0127CB551600FF910E6F2936B44890909D1DD34D4D67EDDFC0B7ACC5B2A7EA1308A90C02BC24AED97C651EE41BD77639777D66E4161178B0BB93D09AD01868029556F686BFF810DEE136E4235D6E32CC160AF3CE0A7F1F648C6169D3B7DF5FA5011C16FF21A6F5739260F7CD319FAA66B7286B91DA26853F556CB4DEDA3DD34D132851B45E4A811637279CF937B8C5F9E71B72CBD229118E68F5C714E16C9025D65DF8194E561F2B4B347A966091507A0705E142F88BCA45B16A00FA9E9444F1F1FEA22EE0109273B7F514F66F3D05B7F8577F21732E98FF8558DE75E0DD335B543BA8CAC44E1C58B9BBD2BC5CCC554035780A7A86AD5AC9E5AD2887DF3DF50E1D51F2041741C93C35F21646AFDFB12646E2916762FB2A82158E5817E6102DBA4B9377C108A55A35F0E1A67E606C1EC12684B0A9435F386A0C176320EA6443F6370EDD0D83076287C97DBE7828E470B876FCC25FE86B58F50804A2644121AC3AB19ADD97DE8806CF40BD1EAAAF36F03EF289DFE74C318D0692CCE63CE7958BC2F821338AA0B0C433B825825B401287494319AB10897AA49DDE720022128E18EB4F7A42B7EECC3A6F13DCD536BC307183E0D0104C037DAF4AD2302A057DA4A0E8967CD9A04F133A7F2CDB1CC838C024D7056EAAAEDB66963ADF559F347970A74C29AC62410EE9D36840F37C7FA1BE5B118FA1B95E3459F48CDAE7AC78D03A62A732A99FED3485D9CAF7943B6A2C9A94FF4C7A050CEC9160646827A874B10E891FC82DE2EDC0D9DB0E8A9E1FD16EF2A9D0C95C6B0B6FEB390E6BB6B733959718953A494B899C9EAEB7EA93F616178FA8BEE9F6F749525D6C969DBDE1F7F8686B7A9FC4F6102F658600000000000000000000000000000000090B131D23278B0D000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 34 iteration(s) +mlen = 32 +msg = 6014000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 99893D22371304A26A3DB4219BE60F59E72FAE2E331AF713086816E2CB99878730191E2C9B66DFD0AEE2FED1F1EE019D583FCAADA86DCE30FFBFAB7492FE8CAA777A0B67EBE537911AFCF39315334952F6F03E9EDB15BA5571B99C2B61CDEEB166FA36B07CFBE9BBC7186EED33064E3C8AE36E9AFA0028FD6D5C6E06DEE48783FFB7FA79C60FB8528CD5F9F2C7913769FD9AA23FC6E13E4ACF9A9B1DF92C986FFA594AC2E2986880E62446BAE4EFCCCC2211479E7F63EFFF126E430F7B3E9284A802445BCE8A82CCE56255B960559B667075DB347A4AE9D45BEACB94E205429AFAEB1823E8B9F160892398319D74F4EC57F75EFDEA595DAE514E08FB0FA22445806FABEC1DFCD05D80FF2834FFB81D462E4335564E7E642651D0C7423173A862E0C82A690E7269A62FB4684E3A3E3C9C0A99EA32525ECE6B157972E52846CE4F92B12A5AC7733C1963F99537FFDFCC3E3254B87B1F297FD69AFCEB4EA5C58FD3DC389C6E0EB5C81954BCB8E14564F1627B59FC768797420D663EA275802CD1ECC606C57CE04903FC3644A8DB03C26837B594E48346328ADCFFE0B8E50518997B62B5D25BED7B2180672DC403411320DFA3867777544555EA0AFF222D159C3E8C2A0670533AFAD440238F326445FB48ACE5E680E15B85A76A7F6F06D9EA1513A6F46DC6A43D85AC0AB1EB58BFA480647E34FEC219DBE0E760D0843162D886C082E986A35AE4584F00CCED01FD93026D29CE92D7F9F0A47EE337A7D395888C0E7BF87520BCCDAF4D71208FA03065ADBD6F9CD59A71B9F2A34227CA0B7D8CD4468FA8AD4DAB11777CD6C4220EC64B9BEBB3FC36B8867700B79AB1F5BF39218F9E596E292C6CE77FA06A2A8B760F6149691861A4A42E8A93DBDF490BC307F548A760D45C1B469B2C20D2187685F5FD5189AFE2FD4A84E88119B732C5D384D54610307F0339913CF766ACC2E7B697308D91669371CFE1B2EF4F5E6FE4B80F0451D0A363CD2B3A6331ECB5F7027BC9D013FFB85347797A2E47D02EC6146A8C2C8AD7EDE90FC0F44C93CB41F0FD22C65A431037FD02E51D5908FA1B3537A3D925622B04A2218BBF052DE349D15999E7AA731D0596E2CAC1014523ACA43CC5A26B2E3945F06BDC12F854D485D7D83FEFA433F800559E192CC357996DD99604304FBA475289435EC4E57CDA06442A3BAEAE4C90AC3457047A25377777D13E4C8D367D0E2FAE1B2CA117B952BB91AD9AEF010C911D79FB4B8EBFA6D3B3D083CB5210A24D2DE2360B75171B42908E9A698FD680DA715C8CE151903F945A1E226EC2510410846FB36537411EC9D11E06CEBF69265860775DFB96E7804F496EA0A86DAAA7D7CFED679B895A856B097AA27CE79E056757B2666D6ACB3DCBB33B184B85785D025AED348A400FD29747AA7DC33366336FAE0FA371FA27A24D75B36FFF6AD373A58C41387A5218054AF533F7E78B288D02C3C4A01954EE56D5AC0009E8429499079D4313722CBFE79AF1FE6601934F6301E2D2C958AD5AFA6AF2CD7A2CCE652032B9D4E266625322980740A0F70035B4182D69B03D7F5E85DE2499658CB7CA7DEF9D67156F148C314F5AA943D620F5B925B016942B97E73CEB690205954511974161550522A17B48AD64E49A450E269CBCBF1CE27D8BDADC137976AAA11632FCBBE0E6AF086F3DFC302ACE4EEE7B2DD48511BC010C30BB0B8FA4108CC38242769DAEFF64663B3C90793B12DC689007B8491F42C32F16EC884FF660FB9C300B39E33CA52DDE1365B91828EA9B5F52765112C4622CA10F14021BA33E606E4247182775C5A045E995375F96623E046693F4436B90060958D7AD70B91414FD53A9FFA06D6F589BBA6F2FA2AEF973CE1728EFD15B307DD8883CBCCD53483BDE7CB6C36E84B25401F9C77BEE2BBB92A65A53C9522D05331D35C05FEC36F11F3AD2F9A4C11C7DAAECD0143AE9D4839BE50DE35951B639FEE01126BA7B3225E90A4F31FEE99E29D21F58C36F8E88890A5E835ABEDB635FBAB82CA66991FEF7550FE1CE7728FE5D5D096182905E534EF4497217C3B6E494883941BD6C12395842837EA302502C31D35D33CCB0CC78A57720598BB37121B3AC734A707FFD7A3CDF9CEC64B96762518D944C370C10EA2BE59A691318B822BC06DE27D7F67FF726A709ED5EAEFD576B443A269E73EF4735A9AF5671824FC5E9E589910F405D42F9A4759B31128FD49F3BECC42E4A0E083B8BB618F57DF5E7F9EE64F6107C67DFAEC01546922CF3B0B90D88F5315976EA17378B22B58ACCCEFE558BE949A296D0756C882381152AECBD96E88A3FF4683AB7D678D572917321858E3CA66B9B87783C40341B35A5CDB04B1B384880C4DF13623017D7B3F6B089941E96AEC8F878CCEA7D4EEF9A95CDD9B3CC8758C2A9679D788989D18067BFE806F467C4A34CEAD74C5AEC3703D86F575A9F4159F0FFD1BB05458159571E559DA812B2033BBDE0238C36BAA6C8C0D979F5F5F231B5F94BC67B0FA129FE104C8B76592A5355A00A6472CCB95D4EF8D07E895D103502D816B5501F5B259B86925FFFDBE30029BF8C002DEE7597DEFBEC850CC18A0ACCBD7D08E30B6FD2F9F3D2E7C9D6CB77A97690F15ED0BC6ED158B0A27A18FE7596E308BBBB01BB1411BA31D7F2B49CF7E6AF5AD1837DECA57E285C9084525F859D72E1381FB39C6525D46976AC5EF54B541E4B36CF50B92977E1170B0B04C6222E213DB34B8A48D111627B905CE65821A73482CF439709851A26FBB82B381B84E076D807CC35DE298AA3FF38EAE9C9EEBB52D339F62B6DE3CF7BF934CF1F206AE4D9CBC6C2E5CF403732EDA34DF16A6E04B3A89EDC0EF3C7DE55E7946909B6C5ACD1C51A5E505C62E0DF81B0DBF94381B657DACA9647B89CE5E75336C735382750C90ED21F611B2607EE7D4BBD97DAF6B40572619A335D9344E459FAF5672DF500A9541E8113363BD4AB65724F6D086860630ABA2B858CA21E3D491215D2E52D1FDD9AAF9B22E97B02D0B3CC653485929D6A7585A9701A45704B6BA175D916DC7DCE0A75918F8C8DB61528FB39AC509928A2A8498C07083136D14E28E1094DB7CFD4C5CB401D55FCC4089C1FB1C18216AC7C007119858F2761F81AE717A5BE42202B2064BD1FE51227AB82C30BB6378D3C9D514639278C25DE38C99E70B8AEEECEECAA23E672975B8B9EFB50F4B6E946B4FA00CB2A88F48F1BFC33909E93AA87FC056E67F7F81AF4800178CE77E752E80A649A667D389CB03B13CBEC353ACE08674FB6C612B831500D01690E254779F23EC655804D53B10264B542A28897E3E0F041FC94AFF3B3AB22B5E5AB3F4CF6551AD064A9C96FA2232FD9D1A2676E40358F49E38072A62CD223E6F00909CFDE7C549B340E4A01ED71B866E2A6F898B5E61040D2E93904E4BAFD5E5E34DEB37481C50CDA70E32D1A60F7B4ADF786C7471E0F59E1B0EAAA793329AE660365530869EEA6E5E770C11FA56861D69602DEB0CB9C4F5181D010C43A36B118D481735E77A1B0170C206865F90F2FB5309593E2DC0DCF49488798B7618B11BD218F256335250012337F245EF45AD4CB615216F01AC27938095490A18DF687DB9B5002DAF85AAA3CE939053CB5E84080D4F689BA7965E2034DA99EA05D50B96A552816D938100F22CB2ABF8FDCFB80D73C78C77FAB1D1FA81FFC4E3EC48A116065B6E313154EA2281E5A4D6A98DF5FE439DF530DE835FE169533B5A1F06FAF13534E8E40E5F30C5DFA2F522F42682CDB1BDE0FED6F23EECE1C2707492F8B002442860609A24F2F4580A2138055C4311BA248E4D5ADBD442972C54D41527DE59DC9070ADF8A299583EA0DDE372303911FC97E94EEFDA2D4A05F30D225A7E506656A38529A45A8C3029D5235071F78E1F487B38CF6DF4A6339BA55E99EB25754B18D9CA0AB26B3191277C9502A037254B742659DC410419C1C07E600533307D93F0B7E64262CF1C39D4EB4371E6AF881052359F2239F7CD8824672D24B93A1B8CB9A8D8FD7081E24E29B4E48F813CC8C5E8D1A1FB335A76CECE90A8032E06FF7669C28F5194D5ED88ED671C6B3BC2A3F47770386DF323B00F4B3CA0CBA3AFA5CFD1F0050CB12EF36BF402917D808B179FA9361F34BB7AB6EEE3BC25779528AC770FF5BB6DE8AF65891D3CC58A9424A2D178365E5FFC04BA513E98586D3B3E0AC5B5449DCDC7FC2C20EA95C12D2D8F6E1CE5A6594ED6090BE82D6335E9FA9C8A7B147747C1726C302930DE4B17BAA609A4121CD29F3424C9831958F885C6DFC9C7496ED3C48E41A3C477711F67A7058C1F1BE29AABAE0A28F4CBF566DC33741DFB24ED4F434C831BE69E23CEC724B2838D6201AA8609C6C173015E01C821EDACCCA1780FBE149900F6ED2E5B855E8A6F7BDDC2B28628942F3BFF63A13F89B8CC26C3C19603A899812A7953C95D1446BF3023C691EB369062B5056FFF2B6660B8A0EC98D8A4504AF94DC24FF1FFB10537A89DD25B8A3C35007C1396D9FAD096246832A7657984DE550E36E868169EE27DD6632EE57A80F612C082C80D2CBECCE6E2C0B7F7B4315F24151C20A80C4367FB53C308184463FAA5591D276411AD6176E8436253D5491C3C90E0F2442474F5B758A9AE2E6F24C6FA610396089ADBCF0143F58A8A9F6141C1D394F808DA5BDC2E50000000000000000000613161D232E6014000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 39 iteration(s) +mlen = 32 +msg = 7515000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = C3304E029959E6B7BA4E9EF5BFEC78BB36D08A2BECBC4FE162D90926F2CFBEEB79EED7B76501A926D95293E35D3331C30C399330FAC466A6C8499289B4633DB15DE3FF90C04ED672A4B913C96BB3D86C77DCD8C47391927A37E95AD26A6E8F04A87E384671F1821EE21171E3505DBD359B603521A216C467019508B591EB7E3E00B192AF3E569ADD7E67F827F0FE056C53A23FCDB3D927E2F1FB7B3C3E360B634ECDC124F34A52DB96DC3A3AC9238355D65F8A6F6650AE0ED2447009A3F940D37BA4C269045E98B26FCEFB7039FC71A05F2CCA90D5A9616F37427997F299A1E4DD9AB8BD9C1EB6433A3FE3A58662F37CBCFB4537ADFE9C330B256991C55AF4035EDAC7B298F8CFA821A0F21D4DC10023C12BAFD86BB61A65BD9F7FEE332D372CF227A67C8EDEEFAAB8BB1ECF58740CF9C5062DB241458403A344852B201298BCC816B0197EE92EB4489CB60CA20B1B6182C492995329AAD2C3A5EBB1A003BA0D2D4674C019F974A329AE0328A44BBA4B959509780016B71F89CC9FC48B30B11AF86A6BBEF213C1182729BB9E1C78372C5B85B898BDA52A9260A9AEC8C616650E1817B593CD0B82433CF2C4AB09BAF9756AF271ABF4305E976FA97CF15749A316DCC24EB3087C447CBF975BE71F29BEF82ADE63C40AFFED1109ACC66D5E2126268A8C0490DBE3073E8D6E1D9427159B3E62122686538FDE5B6712850FB89AFAF222B9EE881026F21E86FA4209137427FB53BD70FBE58BF1B3E1347C0996FA4F21941BC691D981880D1EA39EA26BF6F2DCA7E034475DF70B88BF94318DF9678A1FD0F1686950ED80CCA56B7F511A68C0A5B374E5BFF80E0084EB7E356D26BCA683826C8A1C5C494A8AEFDF814858CB055711CDCE3EE41A000B6AEE2D5D17C7D58C99EA1A11B7F7AC20CE4663B5E57E95EE72F8114D8E842DF0537EF08D5598EA34BE1FED1C8991B9A3A1481286402076DB898987213B3DD8735D180CFEB0530E9A4C469EB8ECD049C5F0D8CA6B38AB37EF0F1A201BED54C3E5727D7360ADECCCD8522BB80E74B2228C0E538A36481E43F24A9DBBC7B06420983F9058254870D0CE6FAD673A62E168165467B3C899896315FE62DDCB5CC5E82942D27AC0D6475977B4F37F765F85C2E7626F7F348260152EFBE49F9521B88D41164EDCD41E004C7C101AC5467D59947AF5CB4F080FC528DC209D900E920A85262A2EE830D33C8E7AF3A444850BB20E5ACCFE3513215EE9EED19D7B404DC0807414CD59B7365CF95A16FA1391D3025176738B40D0465063C05C572DAE80FA1AE804DD6EA3BA13716E89E8984E247389D47CA043A761C0883DC68AF4EC8D9CB01E8D2ECEA6FCE936C7C28A7DBD1F351BE8E0B9FCE5ACA185CC9777AA08CFF21F5008B68B7AADD983A856E5D9485C81BF86F08F7EA35ACF7C0AFDA1D44D8EC411110AD4814CB0DFD86661C542C560CDF911C6829688F9F305B60B3DE3BC22EEDBD7836CF79ABDA8639FFE93F203E799B07B02297AAB3031ADDDAF06C205286C247E44453B7D983323EE1F397EF8E6023FB7FAF4BF511AB83ECC976A5DC8B6AB1A6D798CD6E4CC2223694EF74E439C935E27E23DE4CACD6869B70EBCE81787DF8E1063D9A0082AA48461F0D2B3F5FCAC025A1F6B1023E9F13DDF79696E601E4F26D288720986AD9EA3598B0651E12769689B6171F16AB65EC27AF2D041B09AB1F19884E2C5866650EC1F4B7033090F564E2B1E660ECB1B3853E12247EC964B469C9222FE851BE10CDDC3B5E1D17B63019E696BA002FEDE98D7BAEAA5D14360EA01515D49065CC0037F67924EC5ABD5D0FC2F8D70F9C92B4C02DAE4E298DADC923123A1234FB7F2D6B16E745D01C69B8D05CFA49980D44069550EFB4AE4813A91AABA49779BF99D00CD1AABC03B023DDEA283B62437A9EB984956611F5553CBA5A1F0A47F6287129551951820AF360A536DE32A462B85EABADBFF05B062BC73ECBA0A5259AACAD8A0D014A6A741E44E8654AB51EEB6ED295AB7D2B533DB65309D393BE413BEFEFE0E3905EA28CD62D0D1C9A4503173F52079AE739227D6B1038680333C71A36AEB46E7FE63CC565DA2B5EA862A40533A8708B6CAABE549AACB9B03B95384F5CD1BA19A8E05930BC4BE52E81ED37F6FDB0AAA683F16B8180439F7F23B8C9C2FC63806CA7317A533CAE23C626D18C1858442BAABD3766F29F0864330D6DB45CE1B11FE5A647D7D36D305E3A1C2B1EDBD69EEF733287037970788F5B39300619986A34B25CBAC2F715A144B77CF87B15D2869672CD14997D474D3997DE266A7972B6E097BCD0557C8C73843BCAEC6779F1574272370A0CC97C6159CDC35C55AF1FCA49C04B1F0A4081D35EFCFA430D167072E2103BF1B74017E888E289305FE9B60DF191243621FEAD191BAD5BF198C3CFBDC8E101E1F6295F0F68E99878BF5B52E52E32D521D24909F7C6F2CA546EA88AE037F28F4447CD1E15DBB3AFFDDCC64B5FB050467E8AC5FD5DDFE5225F82A29C74333EC6F3EE7BC7266B899A5609D0DC7A71B668D0F6EE47CD47EB1CFAE4E3435BE1288E5AB9CA9BD92A447FC8B7A7583435CC04F668ED4BBBC9DA9D34D91E92FF222AB616AB26956DABBAA5366E3DAB272ACF75851803C183B165023D1761F017E0A1A8E3E99E29EE8CF50361A03A5146AE92EB29FAD6BD6F457B54FCF48115F91FB2A0760C9B2F8AF77C622B18C0ABA4714DC37ACA5A269621396105F8C4975C3AB7C0F80AA90F4510109AE250600C2B1A6F3274A6EEE451E19FBCE34F371F8DFF7FFEC59238F87436253BA145DD163AF8EDD0C8F8E97DD4A2E93F11A300F81B7D3EB1C86F6E41445901AB8EFAE10C2396598060992BAB0FC2AEF0A1D0DBECF33C387B77369D8EDFCE5475131465C5D014D871600E45A414EC63425CF44432E67D86282577355910FE2B3F1BD24D52289623E4A97F59980AD7DBBAD95FB803627978E01E9D7061FDBBF00608F802690AC593442E989948B267601BC218F04EA3EA35B20DC910738818078295B26D1DAC60382266A64DBD1C6F7E8DE50BDB11E6F7DA99FE22C231DA3DC52139DF05B15E4AE12C274FB2AA2FA4F00236A732124ECCF699D9DF4E88BE06E2B1FA57151F361BC3F899DD0BDB35DC36E8EDDBF6B10B6EDBABDFEFE968E362A1EE44C40784FBABE2BF3101A44756C0AAAF45A87705AC5290F1FADFCF8A8D8544014587A88AAC922882FEF8556DB2D587CE3F9C6A48CBCFFEB682F3FDD8B9E6EAF45E0251964D0355C67882942CD6F9D0FA95C97AD53B401BF348630D484FA4A38A3CD647C80BA4FF99B782CAF1A132024B3613930C8002A0372AF979CA367B47D0CE33821ABFD12990D1ADBC124B08DE1C535E5039D87CDDA29433593DD6697A4D33C812D96A8B502B2321BC5E045B0E91567E8E42E97BE10CDE96817C4C17F0DD255FEA6A4DE09B359D68E535599C71208FFC429A4507D32B8D5427ABCF4E1069DCD8FBD89FC8C97B993B0AF1DB772A5620D01C81FB01F900B2774DBDEB288A1541A614BD5E0C1D04F0245258DAD5F4546F319AD695FC0B9CD08B74922B648541C0457947E52A794BFFC640572130C0262369C16AEE59B5408023AD015F747A8251F667B84885563114DCC1CBA1F2BC772F24EA86E6A6AA38B2AF886D81A9CDD5CE3422FF238E6AC6F07C8B96B6EE9645BE431BAAEE72969922F2193C085EF04DCE50D6BA7054C5C2EEC4E8AD6DCF8A95555A2DBB73020EC31A8E091B1CCC86267825BE7C916248BDE7CDF0CD7EF07C926B5CBA9516A1A6F0B7224CFAE79389957827A4C380E081716AC4AA27B2F81F4AA8426BFEF404535E86EBA668FF51F4C5B478B8DC3AB71A6349A8E3C2E28ECDBEB275EB07D671678179FC4F5002C83DBD8CA8BEE9E04CE6ABBE505398F58599481243552B3B54BFAFCA32ABAEB05DD5DF26F124B13A430E16E1EB41F20AC5981842DDC8D218FF65D69A7C5E4D2B34D130F0CC6A9CE4720FF52D2E4C3BB3ABAB6554BCB1938494B080CB164151D746182C27FA4015195F68F7A6FF536534537712CEAA98854F1BE88FB902B1EE9388405B467BAF960AD9A7115F61E71EC8666807F4521D5A436B7B4A2F6BF22711E253633D0B293775EF550B4D0FB084C36220067891EC7DE5E16D0106BD10CC7C9AB8CFA46316C426EBDA58AE11BA7D7E37396C2037F42664E09E4F95158A59E463900A55BE6157288B3C87934F26278BBA364014E3E74427EBA15274CF832049DA4B58D280BDE1FF84A7DCD5593FC48F4661DE021B1B727DFAF1783CD1B83FFEAEB1B53DDC34F51ADB4697F48DF2B7F0AC8DF45E6E72A38A2030583877AA9871D282CDEE2C88CCD162BBE1F90562403938D55ACB8DF04AABC1B3B45B98EA17FBB795B6156F8D0CD9DD02F887CB28ED04464FA2CC5560BFB9F0843EEDFBBC2FE1FEF61317C3B422B105FB07FC8A916818987920406DB2D2D993BA3F56E51DDB7218813183D4FF202D6CDFC92F6E3ACC2AF6BDD3BC75D070EF1F2898A54AA5D467CE831F2AF74E2075FE543B89E96FD546BB03A06D6BB7ECE0670B391127BDBB41F96C0B1839DA212D8BC3BB7FF6D9C22DE0D4BF07650000078B0E40005527D848A92BB07A0F20E11316C72B8C6C7CBDB1348719607232DB3D1FBFD214151575E7D87ACB6DBE400000000000000000000000000070A14181F2A7515000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 40 iteration(s) +mlen = 32 +msg = 0B23000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 3D0F7F815DF664C39FD42E0B8409B60187D3D7E0B32F7132EB739AA56184482A67D2834185BB705068F6B525676AFF87445BFA3B53862B716EE41B95A565B5EEED7A7E07C873B22D48111A525D46E08338F877B5AC39A52B92437D378045ACD64C52DE02158015A57CA60754D5A0AC7FFAD026D90B3C7ED8A2B05F4250842C7D6263ED1813C8FF92BEBDF9A8A799BECA22C1DCC19530CD3BC4E7C9B562A093987A0B663B0D75E6713CC512D7568DD84035B5E3A2CDB2D81F796CE832A8360939E3F642E0B605DF54C5D521BF282902E593CF6FDE287D4549A3A7B958B6CCE8EE6095DB422584DF359FBB243C1025C4159CEC357712224F66A74344ACF0415198B91E66C0E6D765D2A203B33837A95DEB4FCBAC755C442D4FB7D56C819FE000D3B1928C97B18BCDEE4AF3A261804C317FB20E926DABD9C4A28DECBD264D70A4A37C1E68473C16A34AE3B708F23C9B927451F9E6CEB565D5B3EC25408ECE9DBD0CAD318F7774E691067D353D01A5974AB3531C1B3D2E5957B50DACB3415AE10784B56DB2247538490D46521CE0C442833F08A8BE8D8785C4CC10FD32F81C1F15BBE9B5AEF3B6474AA9351FED8F452480322016B757CE348D3D64B50BCAF3CC7E279801B6200526BE95B2EE11308CC831E1A6E2B06ED7585062184699774D3D7D4ED0D69196450B0F07D13D042A2C985CFDE48692B01606FEA78DAFF716F1264858DB1A0D495837048EE4BF8C0E341DFE340D3D854DBE61E77AAA974FFE8D75A716B0E6D9008A7213CDA37DAD64111A970CA999A257022275929A85A5AB04AD922E1A7D80BDFD683225133B0E575DDD139D9B6C792D4AA72F6E387A34EF8334F48ADE8CF6700CD875490B9242DF1C27D5A18473B5C60F1D3FA643DFF98BA934FBD03E01BF06737D85D691448CBBCAE356B9ED57737279A03F00CF1899082677900DEF4FEDB0FA3A9BFAE9C3589A116AB4CA4B8D14374C6EA7B9D61E7FE5124FA0B21C9ED26BB080BEE74949BE011D7B743EB21639D5EFF564721FE64B10F00795E854E2D35BB99C810AA748F1ACBAC759DCEAF5684580C9E6302E2C7BE0C03404DA2B273948DB1F31C69BC91EFC14285491F817A7CA71145C1EBD8CB27A21F323F834B2F536070CC410C47D98AD817D5D53088F124540417CD279FA43FF2F5EAEE6991250ADF0B1A70CB5C450DDADF4591EB9C22BC2A8445C44CCF8A9F314D667813B8D399B975FC19C61A05E1BFF417C799F745203351A274A0515A5CD72FB1DC3174A17C459643FD29024C457ABEC8F947A447B2A55A144C59AF4431343F803E75A57ECCB7EC3D165BE526A5DE953E9E13CDD3E552F572737D232CE13F3A20A2517B2CB33A50ECECBFCFDD54CE8C14A3EF29A9A917BE8409A31EC33EF31040A5D18E720A399E6B7F078841534E1304880C9FB9A466F10A6F3FE71E45C3E6A87FAF9331A39B995A096CE7E8BE9211AF6AFDC9D7267C9ACA5CF3DBA5B984E78E2F009C161D483385609B50EEA31FEC821DA6D51852BEC1CF0A3431C09CF9FE9EC7EC1520B64CADA3530B0F26DB7DC7AE59F02D18CF60D851B5EB812BDC0B2BE9F4DB821A4F6E5B6B0A53EA779BA26137E81124BD441F50AA0DCE7F25662D5FCBA158D2402A7C1525241E178C73E28DAD146743F2DFCF6ACD97DA4DCD81232E90A9178AF64E89872CD3EC31E0C49676366355EB516F1744FCA4291EF6D0D4C061C2AC3CB34401B3A9604B6AA939B0F2D2BBE443DF962FE61E350EFD0FFEEA025460E2D4F5377C24F8DB8ADDDD5D5DE73888AFA636411CB5AAB098787CA786F73858E2602FC7446AEE613823DDBF46D83CB13FAA41D12BD41C2A6FE4FE4F5872F15FAC2DA8DEEB7B54C0833CEE0F3958CDA91522A42110B5CD77AA77AD6E34D2A51BC1E109AE8AC0E63800B5B0CF477ACEC5AC787D8FF91AA9F73322B6C94D486F3E94BF4A9DC8EB1EBFF80DEF0AA86F119F3E37C61C4BCF7B483E8B35773397425A6F4186B9F32F32BD37C63635F1E49A8DA3EE5B12114DFC2B1A9788D3BB5AB07210E3D5455196D02202813C48303648BF6961A2CFA0F7004CD6173BC2B90FC0277122DAA026B94A492874A95E5C4DECE947EC8835BC9A7828B9615BC6DE0636126770D0BE74A8FAED95BF9DA614DAFC58D3E4D214EC7F62D2F11C944DDF3CAFD3274AAFECB366B85CB5B8EB56AB12EEBD16280DEB70805E740034A280071EFAECAADBFD32198CCABEB3A3C5EC15FAB6EB9AB01DE390AE0D76AAED650BD4E865A006744633CB10078F643B02152B9FBDB6334BDCC6DC2083D624AB9694224918C1AB275CF817D1204BDB3FB2D73E43602E6E02B1A3F1E7A31BB9447AA4F35F769603B47C32CB34778E1C13695F28959CA25489C08A5452FDCF56A685FF1CA77F25F8689FCD9CF6C7A2287F04F0895149F1CD9B8E2963B14C136403DF7618612105D43E2224851555C4AA55D2DBAC5FF0FCE0AF0BE2B637B41F625F3DE9944FAD33E30463D3861017C2996A814C18B257F8D947AB09740605AB40B2764D7A82C368BBD4D9457EBA6778F3CF0A63B8D3B94DF91DEA7809B8573CF00A6E96AF1754FC7F0CCCEE04ED64230F0DB9CCCBF2BAD09AF509B74FC6DB81BB30377BF11B35C42CE9F3ED2F95C487BA6D88A31CE77668F5E9720C497153024C92DFDED2AE4E967B1A5C8DC1B05A8F9EFE9CB646D5B0BFA4047DD3F120C7ADB5C4496824E68B34138E0ECCB2B1EB72B32D72F7F8F83BD95BA384BD9A8B267037EF62532687C10A0316D657895C2A1350C0AF9DB0773760E36CF5EC22D98B0ABE4C528DEB3C6EA8F661A909AEE5190B9006E4F34FD26D92D4F4315CEA2D6A908E4E597CCA6A4930FE28BBAA8DBAB549C12516707552BA07612000B99D5266FFA583709F531FF2031D1B93B5264A5D0B0869E1DE7A19A4A0A0F8B883B382888488133A10C4EF5877013E76609E2B4E243256A2DDA313437B7B054DAB73CD15F8072D0EBEB61BC4AC5EB1968F23FCEE84C69300AF0A36BDC65D99F5A044A3AC7997926DE34A099B8FFE4FD7E0D2D0966AC7434E44D31127667BF1B65A9392741B1F6BC71FEADD1827EFB08841E519BA46067DA7FF47BB368748CD05DC48635EC4D4032C954683665B11D32EF4C732163EECA2A257FB0C7D372D255BBBBE017044F08FEE9EC7F6A9A85F994FC3E111DB886B29FF23E78512E9874F5F1DFADA017377EA16843C15C199F0D0F70A24641F14DA173319DCEDE7C6BA1046F614BC912AAD8D42550408162698583E5103EF8E7AA121967540138E88683ECF16D1FAB8F5725175DFCA5A9601C9AAF9482C99A14FFAC9013D06B0E24B5206B4155715519D8B5866051CDBC9B0364D84A07B9A615AA7E875A4CDFCE594B33E1CD851D3EB8C925133999FF6546DE4E0EAF9E92F7864237D07C021EBF4A80A979C3A5E667B6CA2671158E94071320E6CFF5A778B3874AF5C3B806D13C34FC3CD4E4DA97DF15D129647C14B717C437485168FFA4B11C7667DCC6BAC22DBEA8DF1945F5F8692AAB1A976810868AC5244958F2FAA92F0C652330B0DC9C0B6A480DF2C69CA2454EC86EFA4C2D2C6BB3E4C604CC895FD44DA5D61067F032CB72CAB9174DCBC833B724E1051A7B2E258A2E4401B5BE4F35625AB16E8D00F3C422865A1ED70DE89085AF53FA53B06262A1D0891213CBAFD3E1BE081EBC55C2CC501F0076DC0B0B64B543743747DD7465FD07E822346D5A08ED2CB6CEC8AE67261DCDB6E34BDADCA60385A8DDA1FA71619BEDE51A87891B8984C62F9B20D0469BFDB1E29D5B248D67108F98F45208D6E9EBD56694D3C049F97A753D2389D2CB021699D597D5A786753DC6E5E5997F644C2842337E523AF9D66F5B916B858A472978AD8DF14D05E3843E15C8C400DE938D9D6070C2ADE1CCCBA39E581EB349B8B04F252C6AFEA402FA3E88CF32F46CA7AF2FEAA71DA329749E389FD7C1FDD08E021C2C5C32EC1B3763454A63F4D9951EC32425B0A53A3D719CF9122C4B71AFBA1E4AEAE273915A67C9938241B6FEAB4076B5CC16527E4A8D5902A11329CD725EB67264416F227EFB5BB20FA59619354274E26208334C3A378E4A13165E67B559FA8400AADF09C334CBE808124D45ADBCABB41049C64E4C211320CC41EC9E9129FF5BE9F815FF9323D9924B79E691C801F626544FAB47C223D2B82B42BFCC82197CBA3F5BF013A06DCC7E1011DBD1E89BB68098311C8F6E998F48EDA82CC24AFB1CDCBF1D6538823C92F25F45D8919BD1FB8C4A5FEE7109AC8BB2CAE76B35A9F6429E165292B5A0F0D3DB6BA60015CAB94A49A781A2EBFCE784341172F9EA256785DC233E6EC90BA756784C6D52688415586BF77456D8F45CEAE5902D41A7CFBBBAF24E88D4DAACD8BE703113AA6B5597F41C46A2EF85024AE62098A88CE3014D13B9026815A18EC38AE1BF78F6B8ABB6C2556CCD83A9C3B0500B13174F5D52F663ACFCE4892111A245A46EFFF636E8552F634148E7D1865B070072A9E9EF986C7D5710599D850F463533B7079104DFF25ABEF2E13FBDA6C2EA5746DEB9E5C4EC50325F50A19362D7FC3D9335C367E096623A40E5E873AC05651086F802317AB818CA04455F7B85A6CBDC2B41A2D6F23536B0B90119616E989CB9192D479CD2F1414E578EE8000000000000000000000000000000000000000000070C10171D220B23000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 41 iteration(s) +mlen = 32 +msg = 7504000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = FE05190307B3C178FE84A59F36CE2FB27F95131D923BE19A14049AB595B7893A79CFF8E1FCE183AD1EFA99FEFFCA7BF8F441AE4C8FBEFA803A0B6513D81E4D82DD1C44E5B5FE911B5F09B47D9F6E5CD37E22D6EB7F8FDAB3591C714A68829678B4EB25B50BFC012C93E4B553EC942B43165C82E64874C312A29E870644285FC66C7B52C7A9AC9CB583895DF9D33A2E4D61F4CDDF75E735F4F406FCDCD9A916ECB9042D2CC52BD1849A09C042AF6AAF7339B9ED6768DF14E59A719939B2B3168B112A590E48773412FB4CF26C1FAB25F36E29F21D82AA1632A7D610FC34DDED48DC589FDD5FB3967E5A691C9941F4A4A9E2E9B5FED4A93DCA60599626D7DF865C3BC980B9FB4CB4F81BE8AD600871518401D82575EA9E976AF0AE28232F6783ED09DFD2ADAF75D335FFD402378C20C91D60B8146E9D605217945580E501D2EDFE626B094066DF77F325E6BA5A54E19DE6BB45A6DB689A08CA3D4B28A2FCC454527F4BB8CB89507B72D42CBE45BB72977A734DB9E7BC49B87FD185471A30A858D4B7E291029D7911854E9509298671378B6757B76D896BF844AAF11AE2CB6B090E012E1063CBDEE969C63D49E70E776C8C72C192BD0656633AE83772363F9439EEC8B1F72A31873DF3D46CF03B202CAB1360598886542EE06585225B21F3489130640532421C989CBCAB92108F0844BB34A59DE145AC8651862202033050EFC553A9335BA15858A51B7585CF345D8518CD547F8739FF3C95B16130A5473B6F4B32EDC1F673154981E95D439519B90DD96E64B22F710B5A502D8DAC2ADDE2F168C7A4FFB51DC950250CC207ABE4CFE6EFCABDDD5B074DC0491ABA4C8FBF8F85E62AC4CE181E782CEB0664D1F10776678C74CB00FF742E91279FAA64FE6AE22855A06E3A3A278B04F5EA28367A84AFD818891C00909838DBD482ED6611F9031E071A25B5E7227106EFDC53F5E524141B71BC3DFFEB069349F7C1D3A0A39F7C345D17F2B5C7A7A5645475E2057E1F551DFFFE0E43BA63F2503532BBEBA746DE9A071A581CFE19FF9CE1907FE2539EC33AC7C9E7713A714DDC3EECFD9A68DFE81BD7A16E05FC99F7D641F8ADC1BC896C42210E049BCACBDFF65E15A302CC57918490204C683F0BBEFC0D09DD1A7289213F39B3AA07FC4B5C9C6094859E5F1E658B85F58859A1C58417D39D1815DBBFA8CBC03339AA474767506D1DC9D3FAEC1B5257485FE836F0F8C05CCDA7BC71BD126D3DE6DD4C24FAA1BFC118B3E7971C1AE05CED4AE210BD7F61D1996735C56D6FB1189BF7A4A85C2C75A3FD8D726A31692F6C57574332D9723A23DD7AA83836B4143FBA5E5BB415695A5F77B981BB9E0F50F3A07935BF316E3EC51E476610BAD5C31BC68F26500BACA63FFC93A924453BCEC94C2E1AE503210C2108624D97C47E922A27DCC680C0723E43D275F357A691357FF7C192987B198DBA4ED82F74AAC3B340E73E1D887FB71755A97CE72FFB38D3C204A2FC227DFA6FEBB305951B6A7C84017B5AC827C06ACD5A11653DF27AD927B539AF41E38AC97452C877F2945DD7624BB37CF59F2CA2C4295C6683C5BD8BE3DFEDB3DC71267E6C823106AB00195160E8C9DB811550A807B531D8E31D0F4E13AE0936A3C02312E334FA5246F9EAFAF79C2782C502FF562A8C2DBF1B32C62D904FC62171EAC3F394E365F7E00278F96DC59E6F6FF8CBE6E74643AB5A5E554FBEBBB6AF3115D914D6FFCA0619F1C870040F8C9FADD4EFF4455DE64957317888E0ACA04D452CC8506D0AC26DFE538DF76A1761CC48ACB103181F42CDE489F424E4BF2F5AA86E5D0B7192F559D4AFB0886FF3E1E3306E234F80AF57A067252F7E89689A9416EE9F7B0C4392E86AEDDEFCF0E06F6F35D068EBC15D6A8F56E1B80169FD2184B8CA574719C0A155CFEC2AA38C9F8CDFB339C24D9A525639B4C4B895E84794C148D5BE82AE59B6CCAC97EA157E96F03E573FBF826273167CCE27BE7FC8B921DE850BC53FCDC35219223AC3B03B1F434C5BA11A20DEAA1164781C7D14FB0D6DFFF909AD97DF4DA16A648DCA7F8D0C5B954600B027DF9FCA9051A26884513799DCD7A3EA1ECAD9E2F0080A26DCD3E9A5531BE456BD6CE40A9753C607EBC3CC22BC9871AE7588CF8AAB7760E5E21A8F4E98E87544FC85525EE130BAB060C02F6262474E4A05C50B660BFFCE5BCBA156391CD2C1321D17605E32F7333182D9D31835B2F9EF2E0B064F9CD678D32A998912BE023A102216FD29AFCC9722EB827C38FAE1742D10E6EB7939E85988DE6C4A2C7A39EEBE16647E59970ACD67BB7C7F42DD003B18E131CDD18940F9220B3E8EC7B6191612E5EB2D5F191B13F68094EE204BAB57CEC4B9E8CABE35993BF48600751D08782B0CA58E4F2832F66DC45C922EB2765185F4656B2E06304F26281F60AEF0281A44919BBB32015CDB573C20BDEC136CBA26EDAB9B4E5BD1C19A06AE460F67C1D32AD90D4516B0AC6307A50030615231449DF1384124C9CAD8466B01E899CB65EAAC027FD4A22A0BFCB70E47DD9E01F24F41D09FCC8E2CE9D7C79ECCD8B8992D050147A26439CDB3F746A4F3C8CB51E3FF6E8C2BBC5A26CB797265B8693EC47135F006C08CE63B8596B2CE5F7B51B7B997DC3BFF82213213347889CC0BCDC47D8D311030F5C8B7B55FAB5DEDEDDEC8E7DEC50A3AFE32F8974A2CEB204ACC1E2C3D9BDB61FC90262B88904491331BD63845CAF90ECB9A2CF5477C782BBB213328242C27ED9EF3A5C4E561643AE4084E31C3DF1A418BF3F5481A8C7448EBE5AB51DD0F3BA00F71F59A59B531B000D8FB1C372E01991524079DE326746615F5F3451D483903E20A3BBB70D255B85C004120C68AA8969D911C825399F9DF2C7BA467FB7B08C182034C160E393FDC5648F44FBCA6F0F10CC3361776F35C4F89F61A2C8243F957307E21D9B3CBE628C91F82F119E16C4239D858A667B6D4DF1ADB6C500B94543441441ADC0616400AC9F312D1997EFCF40885D0E0A6AD7832D1624580D94BAC2A4680498C92159657D7606FF04195D69EAE06CDA609080BA16CB0EB1E38262BAD5024AABD87A732D5C665356DE842A1039E9B4C215BE45A39BCE4BA01204C47C7D72B09823C87BEC9AB0324855261B17EFEB231B87011010ED84F49A33432DF5C247321F70EE93A84DBBFE7425B4D8978376C9A79A96DBCB16DCB52B05F6B5E9F41C0BC97F39A2B2EDE586A6EB9115B1A08D88BC665FB37667BBCA06239D36C5311D1F0F3EFC5497AF69CFF6209EA92C1EE400667A6AE3AE471ADEDBABB2629C5589305AFB2574F323C575720096DB40B407884E89DEDFEF229DA31501FCD6F3FD81403C00FF9116F2C9018C688E9F87F8CFC6C91CA556D2B7AD20970B66E150F7363DA22B4A8B7B374C6952CCEF30FB5062576AA7FF39370066B1EF847445791EFEEB39B1763E8F385D7C8DCAD9BFEA58CCC19CEF8E64FA40602D209A6A7B9D65B013F481139C6CF5EEFCB90EBC0BE487A024A4BF48116A29F213EBDA7C4741FA228A6AA8FDC3D4C78586643C20C7332C926594BD10D238D7EEEB9A09281F87740ED00909A8426B5A7B57C77EDA274DC4CB408C0A16FF2521CB6D59DC0AEB8BC74DC677D31DB123E4DF6913865625B2D2E40FC31BF34690CE41DD561532199094B94482E5853091F8FD78337F72DC50B9959F3D875C030367F6CC7A8EE449383A8E525BC653C31878F57A69225DFD0919CC8D347787DB8AB7A76288DE3ED78A466750A8391EF7DAFBF6CFCA8BB644DEE21EE576D9B1A0F6916F537D2920690EED8B959497B3441BF6E9A05D935A3592BE0195156085AC204909619A570964B90AD9EE4AFE604E19C1277AA21AA9BB6A0738763B0B220E636455ED73D4DA20C137FF7F10692DB51E8D3FBB07DA60BF658BFF6CEB0907CC1EFAC9177702E09B694A1317003FC848B4914AC20BCC701FB2CD1F58709C275F1B3C839C2019FB564A610489D4EF2F833E70957AEE616FA316D0217BB1CADA518A5F4AD8D86803141AE180358CC16D3B63EA165F1578B07236B026734791B690645DE7EF29DF5AE81D5254BC24213A6A26799CA6E5C571B690FC50EDE7C79A547D7A2B615B6C6A24B377E10D4B45F8827FA54F4B40A27B1EBA16385E4D6332C29B24D3412780C117E49BC8675376FD4D6E389AE29F30425DFC6F1C744A1EDEFBCCA35F4F0B4630ED1CD887F1348C38DD8F8D71441AB63BDB1FB9D6379D7622AF23489C1E35E726592EA44B80194AD1D929D39C7951D071E3A5841075F830F9E5B9C38A8E7379D036AEC2B7730DB766AB9B3EB2294B0A2647915EC9C8BDC142E47EF22A7953B80D61188B9B71D720E03B313E97F835C69B78D8F37B0DB67D02FB2B0AA322C04375EEF24BA6277AF79AAC4A597D44905C736C2E7D57F89DC791150F0CAE240D8270F9A421FEEC641A24D8EBB8AD06663867C0EA93FB5DC653C27A7298B8B814110F3BAE23DB3598251BA1B3A91BEE607C889A9E455AB04C0CD84D84F642AE809CB09088A6C9EAB192B51EA5765F669082800321E82CA2FC9A1BA3D592A357B143D29D5DCA9E9903DACE7E3699375D21D7260768CE5D6F351090CFD2FCE2659788C9AE2F7FB0215222F3E6985ACEAF40D575DA7BBDA24434D565BA3D7447FB0D5DC36515259FE0000000000000000000000000000000711171E23287504000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 42 iteration(s) +mlen = 32 +msg = F105000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 1217E9D5818E6F067BE5D3F7E86622C2118C2A5CC0C45B58BF5F8E62A834E60A52EFC3C922F9FBF25ED3AC7FE1565F1D62F2562B39554205615A19F809040D25565919F28F8C0EF319B4DC89049CBD69EB54099ACAD2167F396ED1CF31F2D87A0141807883644211889C571C4F55DED7C5D8654EB069E5B05DBFD3317A433632523117C3F2E35A1638633BC47704C6C640F1980CAB109F2DCF5E6A9B0FD509C296560A17A4B4431566A4F04E58B8CFA7BC221973CB90EBF7DF86A8DC273DBBA0BED62BA36320198B75F18779002EBB5ED5C44EF722F850FDB656E5B4565234694A45C2BF65510905950DE82145F4E1CAC5B01C6A03017AC4C21A068D6F4462B6E2AAB754CE231DDE7E21D06DAACD2CD9D54C225C877235E81CCC85B9649FCF241FCB9CA4294EE852F52812661C23EE796A28414D0846EFD3E88A0250DB787EC04368381D5A769C364EF51FD55FEAC6D51EE0A9048E4076BBC57851AFDAD4368E3B1A90DB660D908084EE45F98CDEAC8B321A99CD2CD7538CBC3A364ECA4FB6003BF6AA681B93E207D252EEEA027C9C14199CB15B4CC0E4BC6E59547B6673AE37E02794B8CA1AA16CB9501175B02154B45083F6C34E39CDF47C1548D303550D9E7B0AE083132B67708D228F7174F67561BDF230063BDBF3AF4A11BF0330E90A0EF2D0E6C1410E8197CA8A5E892AAC94B78DA6C33DD220A3BC6752729C564D3670A9C127B88018D46E58062C9317982ED91F53DFCE78F958508CA11515B5072526751A4B8A5E8066A86A4E97F540721372F1960B1D3E25E89D54E75EE14BFC2F1B9501195CF8F20D6ADD1A32D0C936F1FC351487AFEC12501C0BC1BFC7500076A9D50C2B1C4129B8D0438CB8334144906039DC1C5D97C88117C456E6E8F66DD13E9F0D4FA3C5DB1F0E529071AE4D1C4C5053548B43D60BD6D7EABC2EF866E26BB809908BD90C359812EF913CD92EBA8A09380D447C54594CA768FFEF320FEE5C7D2695585AE26423EC09D3421CF46B51170D7D64EEA5C668613D5739BAA160ECB26A8502422DE2B10A9BF1D51526CAEB8791195D8BBB45A498E1D5B3CE38F12841F1F47028C95BE9ADA9AEAE76F3ED2E3F82F96BEB319FF41BBAFCA29E553977C10D422006981DEA385E6189A9C63168116F97FCD88A78E13BAC20CDEF4E3C5FEACAE81A43DF02CE7AB2EE1A8EFFDBC524BC55CCBA3192F6F0A794A3B8AB1D0EAC8640EE4A8A9CDE0110EE9557815EA16F20DCC515F919EB3ED722C8245783ED374A91B57C4825E7D0887B63AAA39688014E929A46619A0C5C2E413F2950467B6398072D3CF70A636B62439E80E8ED04D24AEF6C8C8EC3E3AEF68BDE6869614BF30125DF0889B1A903C9E930665E314917C416CA3AC2FC9BF060419F690E97843BEB7F6B27D02D43D3C9427F0697892AB2B820D2EF0A9C319990EF6BBE7F1D0F3C4CD0C827699B37C14F6F28426340E6D79BC7783AAB36084BDAAFB536D1AE4EDC8F9D1D0188EEBD0C3DAB59F8C897CE73C8F3E165C2809DBD45972483984270ED76A6539BB08630FD5E8B2532051AAB0C9C74E728A52AF4E888ADF151556B90D6D1DE6A65434A650D21085E0A49A7B9BCDB9E7D4D17071F6D06CC9B3B394B799F2BEBEAE8E1359EAD7A9B565EA5161D77DDB95A682D500784A961CA50857467D3281AFF2D40E9EF10C4FDB21A2EBCA52DCF46F5FB14BC808D0A0E8F4D308774355FD9FA31F4E5318B6DDD92445EFD54FA93641A99D452A6BB6D1D403EA5C37C912DBD74A58590D39168B2F21A9070FF57C408EDB188E224660F5C8DFF11805E2414257AA6130A90987CD065A3B3BF16671E2D21629F7FEB8346ED350521F09CF44576136903E0B07C81CFF80550240D5CACBBEFAC2B67742623C9D3FE822CB4363D38EBD9D59614B08A8736F8236701A107C19E0DE8080004B722246578E794929C823C1AD79F2D5A428B6F5AEAB8703857A98E1C354EBD797268F88F1C77F17AAE27A438E21B25D9580A0D634CBA30C5C3EBE31A2692CF1FBAB42B3660474DAA29A37C357FD2D79DBD0E22AA0946DE5BA5335E0DEEF7B0A4D5AC23EB3538C327E835B2DAF74ED77005088AC75B0A08D27609DE4C77AD66BBD9958C6B9CD4251CE9D414DF8DD111A6BF35AB015CD436D860913A5253896A803B9BD1D2504DF18D7224071DC223C506F1EDCC96E26F22619ACD8616443DB41283ADB9D1E54B1774EE0300068BB7C959F46A36BA718FE716B3B3945CBE65CF1526CF66A52AEAB76B02FF993301CB883E5654FFE3E3BF7763E5B8AAF64F764D10873A6087BC59F9B76741A7C441611272E3244A39C74B8A7FCABAA0B61A387E668F2A99CA35DF13F68D77C959B6C607D7E5C9B7D4926DE0EFDBA42864CD4949BE8DFA87118CB8821F6236F5E9585226400A6A636086D77DBC71F6856BC715B83CD93E628438E1867F67163FFAC23CDE81A74DFA8B1E265E562DCA1B5A881C85C45A21AB90533732A4606C405C8A04EE00088F000F4E9F33E2912C3D9142A71D2300654467E1BE688EC5792EFBA01BF087BD36D15855DD96C417BA652F0386633C9151E4CF33209D93202F7D71DCDB51CB76A708FA5E23B070F95BCDEB99100555E8A64A6B84DC6D51504BD7EA24593A32223A4F1268D5D986A12BFFA3AC548B7854CA02262871F7D20E0708D29AD7A7635C537A6F5569DE2BD4A9BF41DB3B357A181FC8F3D4277C05C4A2A98D8A0A40EAED01AA4A84E00208BEE78C70B13EA5DF61DD9DD63CD2AB8899879636EC575A7668BDB35E15CC2F24F8B646FC54049DF718288C8C414F3CC1588786F40C0A5D6DE7CFBFCF02414055035D6ADBC30C3AC0D85FA572B604475EE6FFA09B20DDF23847658C9DD44F29D7E143E4A23E4C4F1751FC74107BDEBF45BA1180880EB036C14E71CB2EB71260F3DAD56D1CAD348616446E01B7E66D64491034BFCD447C1A8570458929CEEEFBCA84571126691D3DBA67994BA84E61FB4FD6B66122BB61A6510E7FA8EB284D1AF65D25D5ED756A92DD5EEED49A7E19F9210C783008EB193A24A7D7258F0A89C7391912CD81545233666FE675C51907BABE9D24C5D6524F307AB6188BFE5451F23AAC9387ED87DFED2348DFE60B3C6D620D0632828CADB5C2F69A4A81855088EDC9843FE34841C2C01696B183731F88002F4D0C466AFEA52B749F317CABD628A74C869E96E1DA039F732CB7D15773B71C4D2A1F2178FE7E4F64E007288C5C5E3DB21DA4517613270E950B21E8D8062384BEA6C1F092FB9D0AEE11888BDF7065B154A343EEFCC94736E5E375D3EAD8A1409F41ABF4C1C08DCCF3B4CBCAD8DBC31B593009DB4CD25016F90CE177A5E9B96E7CD972E55B2C4E34A08CD75123465A58FC4C34870C787941C5A7F619848A2B0D90F2D55BE371F4F47B706322909B45BACFADC6C290F17EE4DF30305E04315063A02D5F76F5458B6A22EC1409D634AE43ACDCFAA5C3A241A67C4E938B436640815E8C529BD6606EBF282482AA5C384DE807C04F0BE2668A6816868E28BC5863DAD6FF0421B84D35578702D3CAD09CFF953BB421D260A2C98EEC86BBA870F545B3D160643463700ACF522D665AE38498E57CD399560B41D923F5C2A564067FE85D9EAEF21CC0133E91607BBD0FA83DD54404847D82443CE36EFDE619DE2882ADC72A79C2A65798F55DC2EF5F67A4EDCB871E9D5F2642F36693BFF3D694817E308857428E06B42F3681AE08ADB354BFD104FA3BC2AA87173A1883AA0F28256EF146D4E1A5FB44ECA834CD652D0E42AD8A681CBF24BD0DE427B03093F1C0A7B3CF57359D5BFB8CE15E8EC8AAECDFE1B26AB5C78A6A523F2D9A576F4CA43F8365E412664A3D4511A42737A60D7708ED3B11E3BDCD731C07002525B13E0F19A78365BC6CD33E8CDF190A5BCA4268E0142FFBB3DED4D3D49D385498B05E4CEC7F3B7703307DAD2C77FFBF10169CD0E5ED0FBC029B3C3455A94661B9E8138E20C262FF3682BABE6A8D97476C01CAC2E46FCA1D788F6381E0561D3C8BA3DA8EA09DEF32D0BD6262040F4143E82122417801E88D693425B7B243BA19049D275C747EEB96F63FEE8D3B62900352FBEEE3C367DD9EB1F97386174084C3E7AC78C1204B6032189E5AE1A4635D59A4197E6955139FF9E3B4520FA30B397EDFE36F4C947BCEBA45C8ED8FA289186FA7C7B381C1C9AEA249302B5E07C4FDDAE7270F45188A8193C0917B694BE541CF17CF63DFAF99E1DFD98318405BC7909865F941E26CC9C0B70553A49F9B4A41C97A3D09FB49116180564724985B554751526F89A3C931A18FD1355F68F3F23FE9D04A965015F1385F78CD68EC5A91B7FBB2AE85038B3458ED91E82DD966CCC80B8E85243E390A2FB12907110A3F6B02FC851758F32DD82424EAF9621B02D9AFD391AA6BEEAFF717E051F68139EFA1D36461F577307B23C885BFF1433A4107B184457A6560466183154C02A06EF149DA5603363A4FB6F3BCC6A652CD6B6115B83E89299CD853ABBD58AB459F487E8ED27A3896D41E47BAAFE0B497D07888123FC03B54C9090DED58970DA8D0B4DD3F5BC9379D78B251ABF5F1A02FE0109908533A11AA1AD15BEFF490AC7F5B666CA5DB777D7EF24B71ECFC1D566C999BB0FE535B6BD4D9FE496F96C6E4EDFBFD00000000000000000000000000000000000000000005090D141A22F105000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 51 iteration(s) +mlen = 32 +msg = 5F24000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 9CCA8ADF0460CC52697CE7610C5CE0D876060DEDFE1EC0B2CC26B90039987757809CFDCD227828A160C27F96C0B5B395AC34B6184A828A0971DD2C218163558E6E7FB6C0AEF05FCE80EDA92BFD740AAB1376CB01595CDEEAAD7FA757C0AD9D603295C3FC1B5814E2A8BD33B4FF31425CF46C832D4E1BFEE3D02A9FE8804E662AE91EF43A27DDC105E1BC4A279F82B7DA4FFA37BAC496ED62E6AFCEC0AAD0FAB378C5A266B6885EB06F506B7E44A2CC0AD60CEB9A103164757ADA2AE9DC50E2A3A5713A7EDC673368004C81A98AE72C51374456546198785D61D1D99552A4F942289508C16F61E70D732627238A7DC19C0AF92B87C256AC229C1073DA067EF8594D0BBAD6A5488B1085D4892A64460D32AE6BB3F7D33D15087C6AD9215764E89442E303D3FE68397F958ED67B0C2FCBBFE6CCA89FBC5D600CB8C30C32F8299B0D24439F11DB2BC8A77B78E010FE3A3FC8E7C9DDF28D20EB922C5498CD4E8AA96C5B9B1F01F79FB2DD03819C7A30D74B7A2FBE43D60A88A7B531B251D2DD675C6F95A76996714756B0B44E87612F19C2F211D16635B6471028672E4B8C570C548A5E80C7685FED950A6EDDE8EF2DB0178DEF727EA4113749BFEB58CBD085CE897D0F650BE44EDD3B56AFB334335B18BA896A86A13123849AB7DED4FFB7FD33CDB036928882216F399D1E6B778BA6F922AA7536E4AE870230B0BEFA0C4647B32B44C644A3B7A0ADC003211838516C86EDC1A91029AF654B395ADB354BDA3FA43A52AEDAFAD8065FB75BFC0D033370E30991E19C1797A75614100CA37B432421B954ADC635E489DBE75B7C6C8C55CDCE65CBFAD6DBA32A8313464C43415181327B9921F4375CA72C433F749E55B072A05B831F75C6CC412A773376A4B12F4FE6F09D10387A0A3B77780ED8DF0C1F2D74F040D22CFDCB71DDADC6F0C00CECCC2A08A8708389E0F3EAE60B6743FED338475ACC5F95CA0B437F3A8080897C0D199E17C1A19B98CB3080C0EDC38E0E6C469273804D156065DC4538715215F829C771EF039F4ACBE0AF43B6085E8525E130215F049CE3EEE9C753A2FB739874A8A28B45D67A301FE5504DAFF4C940CBC06CF6BE222317E44D1099BDD0016A939CC6FD19F0E9B7F4F55B94B21CAFB9FAA5212CDB78B4713F5AB58322ADE42695C75B06B74659B54632CC43BAB1B7F4DB55E32E5A3F8B0C68E733A0F6426D2D49BA03B5AFA121429DB31090153BB262F2407E8D5A2B212374D05F05B95C9D8F29566582F3D202D7C24954C7E98FC586B00EC8F242226835D5C0B6DDB1693142AA49E277B94BD126C9D1DDCF73AD37E9360EE71CD5E19F30CAA9BFB0B237F4A5E30CEA16A00E68878B6F8D1EF1E0C6D829B73D01C9BACA3F146E55C470EE867B5BCB0C161BA873A0FD9A4D9B5C0986C95BA8E6E3C6C8645410542F1CADD83439DD38C94FC792FDCC18512AAAD09CDCC50A531F145A29BF40B7A817170A7C1A2AFF774F32440C2B8C91182EA1A6AB2B548F068F5032C28629EF241D743D45A690420184C58E17F2ACEFE355B38A14ED30849862573AFB010FB13FBEE7DBADD8E0DB68C327F0F6F77F323F06E6B6F7F9088A872A1AB151FB6B5C7EF54E2C5EEE8D094ACA7AD38C9301B3C1E38066C7C7E12CEC49688F7209735A5498B1A390A2FB36FDC59408F8E843462874592B8750E15845FED34663B443501235028108C08EFF7860DA995BA221A39370DABA9EE5528ECA9930842F042C7907F3B0C8C50D9427E9256E9BF56DE25D3CDADDC7475D297C1FD7DE6B4E18C7393956871FAAC45467CA9EF5BAE49BB2DB203B994A344C2231854D05F053F29A0718DDADF9FC2C4CE38053517888C3A3E58A1258D6019CF4903640400555AA09E6F3D979CA764F64CB75A74B6C12F54AB2E6CC1F6A744636034FF7AC31CC7B2DD8A9DDD521F5C3828DB0F74F123160332CC555B285DF68BBA0BF76BAD472E157217184AA6D7D3C4947408F7E71A0C7AABCC5519EF8ABFA56B18CF194CB69E38EBF57AFA6C776AD12325CDCEB1F5D96B2862D403C30174ABBFF700A107E6AAC6ECC80A554C29BE4F311A984039723BFC60EFDDD16D6EF3D2040882D8033C03465D0659787CEAA8D5C2338F437F7C9CF97C902882A5B178DC40ACB9934CECDCEC16E2A5A4A3992A932E45F577A7DC4CC204655C07374DF197A1B93C7942A476C56A9295E123FB2E3DE30D8ECC309D58486180C3BF4B9D889FB32A960447797D232BA3A201B013C6D625C61131B528DF2499540410BBED33BC761DEC3C9BDB01F2BACD119A14886098734A184F558D88344B91E480B456D46E81348EBC5578EA0AC20811B667106015729C9F4809399DCC46D480E89D0F7B253DE8B5DE6C2E024FA79352F21820CEEA66497396EEAB80993D4A0CE62B056F8C7C7C7AB938B7FE84427274A298E07F38A4743CB02861F9306AB36CF63686CF22220B179BCB1192B0391DB03370B8D79DEE6290C0DFA1179BE1431678BA31ADE9A1FE07B2FE77D1AE47218BD462A23C3457EACF619C07327D9263848146B4C5E3CEF0C7FDC9443874F79883EE39C23E432C08695BF30D05BACD7C66CA8FE722FAB18C074245D8FBA614CF4781F7CA3ED046614006A393FCF509D8632ADADEB099FCDB87A316BE1E01F08AB6EC485E26EA20187256C31DAD0DFEC3043ED27A416EF7D21C592005A1C938A4C76D17B58D16001730AD951BCFBE1C761C268CC7618D13CED5445A3F5F1C114030F96BB618CDF3F97CB7A86BC2384945C4B66ACF1481B0E280487CDBB7187D6D70035BA4C8235F638823EDFBA8770D3B587AFBCC7D5523E0730B62BD703A762138764DB6061829C40CD02B64E6FE74FF8248CF3D9380837358C185A8CD23FE69D2035C37263002B4B25182D68DE82665BE120329C483EEFFA90083E266932666BE519833C0088065B905B65FA87087B71F0E7686FAF90AC320C02858D3DB6E229D7F422B8816980037D9B2B1A19F7FAA771FD43403F98D1E423DC3E5AC63E90D7A03CBEE04851FA61025B017F6FC65AA319D6311C5CE65BCB5EA49C1345A7286E447351601FEB400CE9252789BA8C86C84D98B53FB9FC9A784E71252FD7C979FEE27EFAA21C1180D287DDA8FEC742E89ED164CDEBA7E049D7CFF09729A2CE51C678404E7EF88784E1B90959D58D9AEDBDF77C27DAA7E6DD64216A4D1A5FB0FD816C6777F1432285E34E400294A21B1DF767BF8DE430D66A4462617CD4268DFE401812C65259BE4B1F100BE09860479BC056F2FE2276B8981B6178BE861DE3BADF6297E76872FF7CBB35108C89037702DF1966BAD37CCE6BF82141D918453526921D518D4C6BF2491CE2ECEFB139D712ABBD1D90DE52E17B486A20815DC146732173E583FA1A185A447329E340004DAB67AF10FC2E9A85C349FB37CF5BB5719C550BDF2E06C471EA784EE06396B2C9E1253A6A6D83280ABF9EBC7CEFB1BC4DED49881B293CC34FD09B67DE7C2B25E2EC16591DEE608CCC7D79411399BFF9FB8608CEF0B87D2709475254EB63751A63852167414CC51F2410AD7FD848158C90C82FF7173142F6056EA432D6EB4A91E119933DBFCA056F5636B035038992498B66EE9653D37BD49403DB5CD7DACA18D1D3515E9381F9EDEA67DDE2717A5B07137D50593DC0B94ECBB91C1F21926CAF33E1AF87FB8061188408D85337548CFD4CB08BFB8E24802A61C43C0263B1271AB3C02360E16C19C23A641A59DF3BA92E6E24139BD4CBD4F342C2638EE7ADA58B42677DEC2EF4F57CAB94BD95862DFACF65FB9028AC2223DCFDF148556951372B4D6F8D38D8D831676C95843394ADB32D7990559B7412EB2A72E333519F295BD8A5252310F3E7A42998B2D6D31D44BB072A4F3EED3BC7F4665892396F1C563CC9AA35C7E4ED3BED0892076907020DF57838404E162EB3B28956767D71B7FC7377C00882E18925BC57440A367038850E7417F5C7BC4E42AF7BAA0FC55086A1E3213D188F40D54A8296460DECDFDDD341CC713BEAB8A3D7C7752EF45C8BA7ADDA0A511FB3C28BCF8BE5D01B31D72F2C8DC0214B3E25B1702B329D7FA96D1EA15BA669F21756D5BBC36576A93C37AA94EB5A8CEB86FC17F2FDC1522F5B6CA074BF3AEA170EDE6E74E89F4D444CEE9A44CE03C5F2993989AF10ED2EF9A7CD40E3EB8A01D20068F65F9766002C7202CE105B0DACEE1658F4EE2F0E8E91FE4CA41135136A849E67F998DF5BBF9897F8C1818C8F36A79045B17EDF5BAC1AE0D1C6EB2D73E185BEC0D4CC7CEBD61F61BE28D41178A13AD0B85D653D1A49E9877745D2E0024035B6E2F54EEEC23FE5888732695D417AECEB0C4967DE64ACE7D3DB409090FA92FCD0A91C5A695D68980A7E52BF77C932AD2676D193C723AE0185287D249621174EFC7AD8FEA0E7DAE70C7ECE2B74A4871407AA2A4DECD8084B4DF3B2A2FF1D49E9091A2E080C605696DC3B156D603C62B480A03D43FBBE97C00B8534E19B11C6A67D1E66DDAE7CBDDF2D89077F53FF5A3592B7B114D8E3D4C9957DC0B8197B97AF45EF3C3F990A342844089E6224B96F5036233FB1499F458291D7FEF706AD9A46C4D47205BEF94D3C9723CD7F2A3033607084E30D3D6FC60C112A718B1476B8E21B398D98CED3DFE906174B526975959EDE00000000000000000000000000000000000000060A0F131B245F24000000000000000000000000000000000000000000000000000000000000 + +description = signature that takes 54 iteration(s) +mlen = 32 +msg = 9F03000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 751F8773A0E4EB9A2913518DF24D5D2A1A35D8BD92B6E2171FB43820F034D08E87DF2D10FB8B86DA69230E6231FFA2419DA923FE0D06339558C3E69BD332BD1706B8CB0F662EB8EC576400F2AF0091D3411091C0EE4AFD6B7E2070925009BD76DC574940D83621F664F107519A59A77971B08CA011798EFEEBC363B41450BB8C8819E4FE784002AE579867814E6A6392C7FA4964639570B9716A7242F57AC9EE59F3B99E31BFBE2B513DB90EEBE87B114171903817BFEA16D4B5073F4D880821F3A45DA7F206A6B7A004992B912EC5D5D13628690B76C19EE3182DC2B74FD7F620AAAFF3A028380AFEA0C92D7280D4B16A652E7753454E781382B559DCC95D05485A11CE45B0FD7390E280FFE9450E61D3C9CAD6F63652B769DACE89F3D9DF3B02C5E1460C7DF059B6B1F651324CC38F983DDA8EF1789DCCD8FB3045969AEAD0F6CF97E9C55E2172B53F8B43D1C6A4C576AE5B2832CE2B373260D9EAD91943B6F437A64C826BC0C0F518226688C734CE088D5DA62E8D6D7ECD1674597DCAF2BD52EEDDE7E6750BC7FB8EE5A784023AEBD6CA1C5D627C54AD50A361D0F21AAB46A83C8703F823E32E9EB5AF3082554172F2B3F9DAFDB01B42AA15BBB9F6F0B369B1FA6C703AFFFFF0DB8559DE5B8D54F9C9B0FDD16103AE5C71900D6869530658C9AE227756F1B9FF4354B10141A18292F9E9C527E8EA6E0DB395AF07CA104922361F36C7C56B297B5F175A701D3FAA988D4281244AC4CF6B54C54EDDD896F6EA9340BB8A30E2B1462A231FD3958141B3D946D9D46C035D4A6614209D941273702AA0FC97E4DAE314FAD58497FB6BB858174C08300A225293C75E8C4ACE84345D53D6D90D15DC1780E0B9730F7623A35090409D28DD9AAB33E7E87BFC64E8996176FAD4F16370BA2FCA0D666DA4E210EC6384394797004FBC82027171384A82A7034FBF41AF22AE0EEB349F41C624F1C51AEC6AFDA131785B368091CE5AF0776F469B2AFDEBD3667FC5E372C17CE14D67CEA6610462A74C6FED92B10677026039075AA1AC80003016F0654E5370B16F69486E7D7AC6CCCC54527B02B9912A083F40AAAC76C61F6A617255E4271C132573CC21417CB86AEC5753D67323187A2E115D591DBFDC6C7FC1B13E7D4AC594157090912605EE74614E59F8BFAED0AA3716B15B53CFD83DBA8B2A9C5F071E3FFAFC9B46C82352B4DCA4789AD6D188E372274672E3922BB7389477B9B4C854EA5A4B7B20DDA6254C7681F2ABF55F9CBF648663623B77D7C6844E5D98AE4DE396E0AA8320B2E911398BC90BF7227D0B243179A9BCB887F61B184520175B6E1A0760A2ACBB3DB79D66055DD015D17D5B1CA2FF7D859A30385DD47456A0790D11570A83A74AE778A8C9A087B3F5B73984E5C5E5BC1AB11A24F1E3F425993228B4D06D61C87E117CAA4D3DE0E9BB506F3BBDD18B648A850F6FDF2F5E008FBE6368579B186514D4CCEB0F73512C936D226A8CEF99C763AB74EC87F38E47EBAC830F57B79901100ABB8B8E54CE99419E523834FBE8B8EC098C616E14ECCC1812BF347EF2BCF17EE1CBD3102795AB27B18A01C1F3E8FE9CBFE053EC55FAAAA59364DC757EFAE2B2744FC2C8F392464FB83493EC9B4D4960FCAA6DD9420D77C7A4C4B0275FE9FD215B328D057948F533D0CFBEFDE1A80096B477F27886B7F80D37E4A270AA6EF9432C5FAA1B44D5B2431F925D8865A288FE11B915BAE46F2D13AA29CAAFEAE8D0499E32FC21B43E7E6FFFAF5CAB0322D21E6052023721E851B2E7F2107847E6C4EDECEC99C4E10DC951C94B17C8C48CDF79B4AD4EC8F78E205D2784553B0EE2A73D1AC7C8889F92C973C90A29A6CC11D356BEE150390030AEA7908FDD173E7700F01A8F4322FBB03B75852007E671536990B302ADD831F0D1ABCC94B424AC08CBB197ACE78315C5648E8DADC90F6071EE21E5A5323C9D0B7320E834A53F34F183E6C467C5999E7133DCCD6F623051F5B98ABF20B7B6356A0E9D2608B2F00B774468EF17B784173301B5E3866D07B1D9C34A71F11FFB0DC7131722E0CCF153D821F4BC54F5D8CAA57F2DCF46552EDADD2B9902EB664A668616C08558171E0CF53DF6E202CDB96103FAE6978ADDF84D4988F05AF52B89CB387A5515C07C5B3BF716B84FD3C533C12BC850975EBD660C47463FCCF823FD9EECEFE180F5162B6A3059B8684E5278800138A728C4142A1CE6CD0E329AAF3C68C55DB00582E7E195B19D88826EEFB3EFDF03D930E0A28686A92A13A6F77EA30409045DF3546B85633B5C10935AA0D35C9FC5001B639A35104F79A4C384A7A57656D1B7CCBCD06F004092EF0584102CA0252806DF91188716A01797496348893BA73BB4FA61CD9A699B9C001F6FC1EB04DE9343357608CD12AE103434AE6DD30FAF45A6528D96F24CEABF34F06DD37B96C71F2D5D75FD3F07881C0D62BBF9CB079152FFF4179854DAB85B0D051F1F3A09CF376DA879647AECF5A30D534A3DD90E6FC1D2A409D58C96101024ADF72D6A514F5274D92951CAC1238F56A7D6629BA302EA8910925EB79B1C1F3A405D0AB8CC643D0FE28399E7EA5C40C99D2E6E1AA3BFCB4A9AA6518C4C59A792F5E238E2F3E3CC1DB3BC7024A91A7168C8FEA4D7C7100E8E2A52E2C7F37CF8043C4A1801D2744F1D106E850DDEEC17DC1DD02C20D59573C5A064693BBEA39BC454DACED714E014A5277D3234685D73BE268AE211C1E7414DA84B75113D6D45164F3EB39E39ABCD24961E048F3FA5CAC9D6B759248159970CFC0A4B6C199597774F0EC058C8EF6B6A33F3E94DC25EEFD66D7F7080280F90052986E7C3FC09ED5CF9564F84CCF9A60A210C3227F4C3AB98CC6C3AAA8494C9C0C6424B6D1A1F0A5C4A12347F3A6C976273C2ED32E148043068B1A791D21FE5C89CB3F920C3E88F78BF3378170E9FFF636E2F5E1FFD6A6EC59F1029E7C14BA5735618E5D2A7AAC442FD0FC3A9BAF78BBC299F5CA22EB3FC58CB7C6C4076EA543A06B95CD56B560911BF8D072D0E59E22C56875CC5303B0919E4946EA1307F2DE14D31A75E72E54FEB569E85A40E3B3D391CB5C91A11A6C7585EFC08BD32FD2FED0E2760435691E89EE7D330E058BB0C1C0F09561E15B9C21004EED9AB3C0C75174559CC3957D08E6F20467339508056F9C66B73C170F91B9CBBF69AD73BECFCE77360BA7753AF3CC9E7A853BE4D1C0881454548D5FC7B451A6955D5C2BE4D20650BD7F84431B6BB65FD1F4750897AD99C966928B8C6E5BCC53FD7572AC92860496502E35AA164B4D53F733255873C0D6379C5451D08F008AA2A65D43AA0721EA86AD968DD3C8F4F3E4D0F1B6191630F2123A2E8FE137950C253B0CF01B9739423B9FFEB12D4FFD0597A8752D5CE83B4C64F78961DE2885658AAD82120871D4A44CC25C815F61B50F6418F9FE3BED595A5CDDF333CCB98F9A15C1A7913C0C4057DF3425F6E19C6CD23F7F37CBC9E5E4DC98098BCD9758BA78DA394EC21D4EA9B9E9D5711EB0B19E1AC611B273299447BCBC9AB0DFC1BAD528E739265D616F709EC328C42630CE1EA22FC4C5DC3CDB78C632F370E18B83E747D955035B5139D2576917F558EDAEB208120973F4D090E2B9E91C7FADEAD96B493A78BBC9E787E89200EE925BF24BCEFCA795F137ECDD2B6D4470262ACB42ED7EB5B527BD4BD700CA30462F13C4A9BDAA11BB59A6AA79C969D7DE9AB00898935712BF0F84DEF5249168C4C7941FA98EC4D3165A547402DF49178E78E92B5B41EE037487847620A7E938A7428E973EB664DD3F01FA25BF7BFD0930440B349C3ADB06640590EC2B8093AA5306DC8B5BB60D89D0806E93F1A35ED0661F1E69B68B8F644911756A95115571524EDD5804EFDA23601D0C63B065631FCCA6271835CF54A1A1350683D4D195E222289E16C16CC30B1BE5890EC1D2FD0E03FDA62968BC8ABD12648D7CAE4126ED5D2120EF810BFCEBF5D3A937F7C8FDCF142B757636BFAFDD178EFC30B4965D011D3EE00122C1A77C1620230E37C0A507B2BB28EC5C41EE648A18743D75666A9E7039655A8BE4F2945AE0D303BED68C040B8438251C79DD2E6C18C9C667B82BB36DF86ABF342C2838FAAA4FF32F1893F2AF2C629D0EE7FD33A338F50EA21C2011B2AE7C42D5B11764025EC36A0C81B8A001AD8D94F48E6F7E1AB19C6A23848D9BF9EEFFF4949E117DA687D6AA8B74ECC7E5740D7E28520EC2530A1B2947B64A6EE661904D1277A1AA2AE63AC4D00DB200838101CCFC03172A5B7BA594AD042F68D0144E429DA335E54A662FB21EDA9C4E961AD9755BBED869C57484FF45BCC4B419C9EF0DD463447379C9F9D4FDA38AFFABBF5FF0AA61FBF29716849E8426A90CFCD707158C07C2C04C27F9E04356C9D1CCFF97C264335770B974746C940E9A9D820F48BF09EFFAC52C0E4B1640B627534624B84AE4E95367ACA8D2ED30D05040DE8565F81AADAD237C182F4B6BC30BCF56736DEAB0B794347979CFC363C92694B873A27DF3EF2921E913FD02D336D66F3DB23BF44EDC92E6BC3B5D2CA8BC90F5CDCC9CCBB111346E1E360C8AD030CB318BFEE4FE5158330DDD775278496B77B742CAD30EE6C6D6EE3114C566467707F9196B7BAC5F71974779AACD1F4F5F83E4898B922396CE5EAEE0E282E353845B8DF0000000000000000000000000310191D232B9F03000000000000000000000000000000000000000000000000000000000000 + +description = sample_in_ball requires 1 SHAKE blocks +mlen = 32 +msg = 0100000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = E1412C0A8930EBD5BE73CFF29B68C3AD7426551E499553D7CAB9B65A984CDA37D793CFA5011EF4470DC57BF0C7D1C25449CD23C82868180997EF617A42D425CC5E1DCB6127D3B60E017A9AE1AC7DFE980DEBB098F6099D4A5D497B0EA1A063F863D484A697F9E4B87652249301455276EAEAAE6E5B9C32991BB3A247F5EB6A64049C317A2E262BC9FBEBAA53E1203D780AACDF8D8C1DF9D104DB25002257CFE39C49E88EE0ADAC298199EE0285AAB5966C4DECCCDD64FF86A76DA9FCB17765C10CE7EE8272595B0DECCC58C8D89D11B78E56A4CC63B19D7D787988256A277B53BA7D99C1930BBF1CD550ACF5C97F6F1B1BBDC6A9CD0C3BE66672724E9ACD89240987B0B17F9BB38B8B323E21B7DF3A056B85CC41288D34707DDC050B8484598EDE78EA295774222EF491F0D621509C9361B7C8537A4904E2E5ED1640968FA6DFCD828C8BA6E771F970ACA894F0D57CD03CE325F4C3176B818F42F29C8646948B58796542DA63FFC905171129418A349C0783EBF5AE14B3FEE69492293AD3894345F07EDDAC036C40AD5215D4827DE6A0EA0B4BD2DD86826C7F5C340FD2D62062A41C075259A9ECB3ACE3722D3768D5A7D355373E3DE4D6F87A408E5BDE672F414826A2C6714A706198723D6E41FEB39302B155F775BDD01B7CB4925B75AA1D0A0D533A2FBDABF68D03592DE2B24A39D2D093FEA87CA57E16622E59B46988D7057540A511506C1E7C819D8697564E161FB221DE02DB05B8715D7E8CB81B96BF41B257FE6C5DBD8AB7E4B6CDE8A7E15077B3318C7D6B7C301C0EF33CF1F1C65668CE0106A259A599A4034010F5809FA7E781665D866DEC4A5BE77E8CD090A324FBD25CC07929B773CD8358D666ED767DB22D540829F4BC09C3A60448A23EE40E09EC699C784649331563EB114EC47C8F1731DB50761DDD7C972553E9819DB31148FB97D3B4C9FBB89AF7E87033536455F9FEFDF8566B6EB0100040ECD080287DA76A7791CB90AF6253E701D9705AF96B3597596AA58B9B0FDD7689ECA35A7AA7C21B71BD80C3921449D3C5C8D9A26BD386B5C4002C8050B6C7F2489BEE49B18BA85652D4B528BEB21F35C4C9AB1F5E7F5FA4098B2D470BE2CDA7087C61C4F40E771AC04193DED1C45B0AD787BE20ACF7C9393671C354DD70E93618BCF89F684C9FB7C8FCBD004B737A65350E912A1945FA6F6F082406526F8B8B4603E171B754A3F571B7933E07BC9971ED2C299C4BBB4293B3282E34FC1244AD5C4C985ACD31D4F2EB5B82E5B5E1F00C9BE628E0A317885AB6E26AA7667C73C12F541CDF463CD72798CB1F7908D2945A131CA8AC4BA6343BC4FCF7DCA98F30B0FEADE3F0841EE280DA51D9501B5CEAFCCDB8319F9B32DF23E74A12B4B61C44B3005EE58160C85302C141DBD6FE0D598B2886824B1BDADC874C530DF612FE5260E996C6D289A2A5F3F811F2B50CAC599477F9D8400298981654013858E4ADF2B6A67DAF24A5099E9A44F5DFC37B2DAFC4AA738D4690F9650F019583EAAEDDF32BA74C3468863CFD565D06FB26601EA919B68985F5B7F036B2EF1B7B0F6A738E292BE4B263D30EA5D9784221C09DD6BD77F26DAA6996BCE002783305E478CC1CAC235DA49057DA7F9CF7B8E25AE6FB02A46AD93EBC5D9440BDD07018AE26DE5C51C87556AD561F3C7E130A24685F3FB9E39518C1E9D26C5BE936CF3F9F08C464FD0A32502604A349C8956541D94CC0F11BD5A0733737FD75ECF57678264E63CE8B5323A0630A40CD6032D62ED84951427A5162AC1685F8682EE7D31621F6A77ADE12ACDE5634BC44B21A2E1CAFE4A689E0D30AC3D03A6903F75393BE77FED6BE1F970A4BD7F2E666721E271E155223C03C7068E4D9B348159ED8B09D14DF65F4D86AE612CE3A931FC4A66C60DA424D5C2CDA9FBD7115B771E3262AC7788C70F6C0241DED2B9DC0D936E613C795F69D65539FE00AE8E7EFDF07BC068EA4BB9BD83F5A64E970BAE105036435BCFB23934DC13027ECFE3DFB7A1E9D3F7B2B07DBA844598D4CF53D39FCE8C0485B8EEE92671CE8ED10B262E63944A1EE4889494917FA81E01B145B17FCBBD079E8574DF474362FEF1F48EAC5B8A443973B75E72330EB03E15DECFB18F69D10343F2DAF0CCECA3436C20612091E3BA0940DD3A5D5489338578E0E90F3795A7380D577A67E52ADF7358F2E7AAACC75BBB81537134A12771C1539AD42307BB2C1A5277C123F10B74216CCE836E78D24DC3AD7E794BFDBA4D0306A519CB122E3B2D5A6769EF54636F4398E87BD42B0E6229DD7F430F5C6BD610F9C67C68F1F7A687B98C2E5A61CE50C9989A8DE3F53C975BB75B97CCDEB3E0FB7C26F368B29DF709F18193B9BE27FEC820136D8BBB9A037C13B03E8FFE2484D948A284D505916EE424414C5DAF57514FDE0A84665B2C31E2D4C8FDE45BFDB2CA08E9974EA9449C5F332CDDCAA46140F08DEEB3F0B4BDA7BE04446239C7AF4949FAB33B40DBA8FEED31D45F85507FC232FDAD3C85595643B4A7F2503C4BFC4B3C55D969AF6AC80A3C02AF1F5BEBD23A66700733B36F133951193A1FCE5D429B6200FDAF383798A1D11F3CD6536D3F9D27B58A5388482279F925A8EC2850DB90F5F70650B0045B4002B952C36B460A5B566FD3BA2BF5BCDBA0378C54AC9C12CCB46C7FE110AA99DBAE10D5CEFAB484A3ABBD517DB89C71D60ED26FEE9D55E73BD4CE16D898BA426A683B842885B514370F6D854321E599E24EDEC6C3A0DB6F73C60BB36433EC58E162D6FFE8BBF2D345421341EC22E1D25FC740EC4D3D78B79484387A9207B9B48EC8585FB9F6BB4F776BF71FE7834D95BF4C6312D430EB79877FC71EA67EC4080C359D4C4901596E93EDF71C6B3AE2EDD5D491DEA03186BD3FB24527E7F99C708FBA19D606CC44EC5E1FFAA33CD2710CEBF4D4B5869230B151CA8472D35A49CDA5367098CF3AD4DDAF1838E77476108EAD4C399938FF0CBDCD226B6F06D5323C3D885FF1B043E6A32CDE2E052C7D5C273B5354EB020A81D4F9BBA9FD29A5148359750EC9CEB6AA9906047F1FE4191D07A0B018DF93BFCD96FF4AF3BEEC9C5E5EB5884B32BC84F66570B9B57F506443FF634056B504871E4B75CC1BEA1EBC8A9D5D07C9EA587B70EEA92B93F65C3194B343CBFDC28D1A76DAF95303C9C4EC0034FCA333628720BDDA7A3373D676E2928C08684E9D24EED7D9382AAE547CAD5837D6E1BE3E7245E947053EE2219D39E33218D9AE52F6B5EB487B0E5B16AC35FFFC45AC1D832DF711CB11B2A887647BC2C3713945F92103F3EE2A52AD946B0D38BC0BD92E701C7E7D4AEA25E6AA4FF2A42CCBF5DA9BB99F88351076AF1FB4E7CAA65DC23A78372E1C2FA09BA8D46152CDA3ECC8A9288598BED37E4D11507E6B5E239F377D1DC5AFAC7FB38FFBB7B2D4ABC6BD74771923AE17CDE020B34151D2555FDC1C09848196DAAB35745D88B80A79CE2BC86BFE7397EDBD9F16188A133B2900FEDB915629B3104DD6F00CD1403F8A62F71756D614C0224276594D4FB74891D1A2F93F43157B0A6A4135DD65FE25D227BE62AFE953667147FE7D3D486BC6D5436B218FB9AD0C6DF31CE8FCAFE01B81561E02AD5D34A0B669345A74AE16F651FAE91365960DC687B5738D98817B10EA8197FB807C59A47EB187BCD2E4E873BACCE97E70DDCBA6B4189A57FDF7D6F8B62A0FF3D81348DB2B8B35AD55D9CF67F668BB89D448A751B02071D1CF812027EDE8658D51BECAC34BE3EEA1DBF31E6177509C81F5E3A373FE9E2AF88282EC5BAB7D00C1325C6A305BB0E2B47989EF26AA3CEFE6A3F6E7CE5873F215DABF22C17E5E6FB210DA4F5B5F576B0800AE1D282A5D897B6164D3A32C5D0AA176DF03A6C1D2850CEBD40F5D97EE707EC307B13538FC3A0C83A95FF0EA2E5470E1B682ED12F9E65F366C45775A9365BF74729DAFF7FC0E9BB4C05A53BFCCE1B14CFAD49647ADFAFAA0059707D4D72C133E5EC878E9887B41656CBEBF749F9E19C3E9C4F464A67354A6212F43D15AF01A762D8C7445F7FF27CF835E1CE11C844E488036838FD7254AA6C2CDB858B7FEDF7852A90A8AC7FE2504DFDC1EEA60F64A671DEE39E72332E407637033A9146CE243950D4C3D07C17BFE22D9A191FF01315FD51653CDBB316E833C823EB459987AAC7E3D6FB50BDEE54652AB253CB9DF0A661BE1B5AE2A7E9EA429D7E8A5BBFE7683A2DF259CF2F0221CE0C2FEB06C117002D101921FB54E06CCADD05DE9353E5874C2B67B45571A83E2967BE45E77AD2336B076088B33F33F024185979EB36D57ABBE493D84C7F7DAEE3B10E039339CFF06CF36DDBB04ABD0FB8C8DDDEF0F7E86F9724644D6654D4FFFACA74F21F242A9722ADBEF84B44C9A1B7B815EA0317DC5CF688F57896C57AF47F44B1AED5C92853A7EB1138A125C026C9E73770D982A0A25785CD91A4F315D03DEFCA59A2D3CB3C015DE5DF285B53A455087D46109582854BEDFC301B9EA9D87D4A04A2F9650B8D9A83B6885FC52CD32EEEE85E740873330E29885C8BE8BC9D657E612A87EB3969CD24950C9A8945844BFFA33396876B885550860721DECE6AFB92F1D87707BBEF2A34915657168C8FA2E3050F1029355F7E969FABD2EC252694A5BED8E0E6FA4E8B91D7294666737D80D3E2F51B1C65B8E5000000000000000000000005111A1E272C0100000000000000000000000000000000000000000000000000000000000000 + +description = sample_in_ball requires 76 SHAKE bytes +mlen = 32 +msg = 5F07000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 97A77DDE48BAADA6090588B72E6B7AD2C44282DBA1BD1DB01FD9BD96A5CAAA90EB975FEF65599DEC159367797FA9149747F1375653B74E6C973DC328651B27F8EA6CE9DEEAAF67341E25E9421A0AAD84A2C1085F56DDD002B2CD556FE7A555D4D03C41A5AB28857F2456D2F8E495DFE4B9F9E78FC9B84B1BB4238C2EFE049C55CB8ED97A390626C184311B5125D5E6811B96EE45D98F5FA997972040FA7267981C407B45681CF7DD4C5A0A3DF0B0098234E7EA01653B593EAB1E671D9C792BFE734CFAFA0EDAFE2B2FAB7D386512E9CAA29EACA22F5F3E13FAD9005E8BAC32EBB3676D247A3B53B4821AEB517A7DEA13C1720365E40BCAA5D89E38521402E835D872EF62CA068FA570FF9CE8EEB16EA6A2B735FA3B80E8367626DAC125059A83CFB964EAC39A42729D238A3DC7486F6DEE92A17E10DF17857E37186700B0653FDCE6C072FFB5F783281C659213AA09FB978A2095F1EC35FA420C421F085335F7685F77C5527E2B5017431E7D5418F07E27F529DBDBE8C66493B0BFBABDE53AFBE8B0C220692BB2BF1C3850603E7D0D469840BB9A79E183D41DECF124BFF1294E42469025687BBB1B496BB8F9B3A0D0F4C598014ACDA45636DB287FF71DF6F500C9E48C3D028A64AD0D085F1B2EF4B5307F357537BC9CC36C76E42DD0AA016EEC7F80F20DBFA39D9AF638B6C97639E6EB3D14AEADE1C114DB1BF1C17AB478B3F273891027B6490404E05E54FD97608EB4F4AFB8389589D0A33469EFC0FA00EFE5B6197CBFAEFA377F1EE13B7C4A2BAF06C2A7696C28C32C5A6C717E487FCB5FA9CFABEF0DE5B867BDC8A9C9DAC8B565C532FB667436D8DE2B264C14543DA221A527E05129092B9DC2071E0D414C807E70E13ADB5E678900206F0D5A6AB82C14599A9F1F074C557F17B1A2A516CD26C9AA70D073833415823BA89D4153C4277F01E44086C8EFADBF051109A829AB5508525DF5562F5D19BA4E177E4DB0D6A713DFC23D218C7AB13C9B3F53C29ECB3AD3B30FD136B34A6006AA30A4972A244132BABD2A3C9DA498A6A9E1567EE208E83686104E59F90DD2A3741301E586CD2FD86D9954AB1980F0CD513A0A6D34656EA31E87E09B1E10E18FE28E789103A08E79DB9C8BF85F14E733F206EF2441AA45771D3AA1B5BC8B1E73149B43244784E98B6DFD7CBB4E1531FC71EEBBCB277565CF1B528E529E7FC935DB09945691B4BC77EC0DE114AAA5696401FF7A6248BB785DCCD11E819CDDF857E039DEA72043DE5B36A6E8DD3BBED56BB47C3F2E37B0674084F8978332297F299095A8659AF4AA916ED967EFEFC3C5B3F103BD19839D5D8D355FA06AE926D7EFE47EBC914E7DBC4E14809F021C134A043C135B96800C5AB1E93D767ED0A2861884D70792EE93EE00D16236673924748EC88925C29CE2F9A2063647FEB81C95123FCD0DED64912604602495207AB98A032CB81644A4F5E63FBE9E036BE65B0147B4A81FB1E2BF5AE35D127A3579E30841CB6740C7E831170D83C02BA10D642B1D9E8D686394FBB00C06D6F8AF6C1F001CBC352987C26C22EC239C68E00BC2BA2D3E4A2BF8B6FF803638C0D0366B6BEEF33F8A7D043DE545ACBF521F0F09C306AC960EB980D795BCB399DA18258AA347B4B23DAC64C1794961931086B1D8B7CF842B06422B1E052DF65ECC6CE10785F656E35D633B3C18A5ACB0FAED33BAB0022091926FEE9ECD5BC683401922C94C901238F602FD2BD199C49F20A66089D85538517B32D6E19BAD80180575FCA04B18DC207B4A831C96EB0A67AEFCF1A7540C6E6206A2D4B5561C169DB7199DDE498F7D2A966C432627D0EBCAED74FB04D1BCF8922BAB0C5BDD688FF8D9EF9D2F181D0C7D411C0080E01E2846149F00910EFA3E9E24DB672E583CF1F25161CF8822E18B347AFE6A75936CE7F2308C5A7401EB0342F89E48BC9A9E38AB993B5FBBBCC05C21F35FBBAE3BDE103AA84964CA4EA6F8BF3FF3EC19922206E0641834FC2093B36713B2DFE1021AD44CEB7CBFFC70A656B7024586BB9AF351AE55BBF3AFB51C388881403D2350799683C074EF1C1EF54AE68FC9D28B85DE1DD5F3EDCB9ECE5C867628130B5D2B2382B92A62909F108092EB035FA0010B0930A7DBB959200A8DD3EE88E5DDA7723C2FF9773667852C30740E84D62162449E3DCD1BC1506ACA37F14B43E9168A86531FE6AB919BCA8ED4E4C3F45DA0FC1D4082560B49A0FEF0C466E4EE955832DE16846B6772A57ACC4FDE0BD320E672363313F8B73D6F27F61BD0BAD64FBC9A44A4C39B25BFFDCD4A2617D16E73FE00972286D7D39335956CCEC3644443B9072A3EC59A8F4D2090EAD36E9C8CB654C1ECE75803E0C1CB308C621E2E4EFA1D6833BD38C4DBD60D402A780AF1D491D228F6A4B31EB5CD1D76E570A7CABF028FA6492554615B46522324932B41D31A5AA22B8E074D88D1F18C02CDC244AFC99BB2525A9471624C6CB0E9A4E2C3F6AB074004EAD6D50C16CC5D09BB7547959714EC9D25DDC7ED2ED9EFA26FD5E5C4B66B874847B6E6E5ED1B79C13697CD808AF3897E4CC6E9E9FF0BE373A6CC38D5056421B0F5D0C854807ED5E7F639DF89C8E04FE33C6D442A593488472165A5F36DE93BA4597286DE3C79C84B855AAA9C78987B055FB239EC51036374A97A2052B23588343BC9042B014C8641E4D83BE7CA343E3042A73E62A9B694AC17D6231B7066FB985B3F27A13FDD8CA021378AA9A5224F3F8774A891411C922EACBA8F1E017416477B7166EF989CF649B1852CEF35B67DADEF3F709D0EF6AEA11F66A006B38967C896360C79E0FD20B0C86B46468C14F6BD9311A1BDF99ECF835F5218CDFFC9E98BF86D70DD381EC61F6BA4D17F06F434F5986F95FC16F2298BAFA7DFF786F90D6277193CAFF8E8AA31D4E23C1F41F407B181803A61F5B187CDDC0A54E638AEA5A950D681387888B4D50BF8006AFA7051AA901E6ADD60769D22F0127F3C8913C23DD71D897F6649E2FB75BDAA76E838E6C2164222209F3544F2063EA79A1EA1A231AA4B0B253334A0065AEB382FAB31DDE9532A2664D9A28E33DDD896F517C7D3E50E0027FA10B4B47BDF36333DE0B388CEE8B18FC1E92D959CF6F440129DE88397F9BF2C46FAE78CAAAEE9EA5BF1A15A9912E8F61208E665690FCBCF2732CE6032092282B53DCA14AD722E3DB814748B5004E143CB605196D32693467144CC10EBB837673DC7EBB4BAFA449961A578EA4C3856410EA200B37D9E6609EF19E9DA63DB7AAF7E2E54B132A4E2D7D9C2F926AEF761581D532EC205EDC6227B2CDE95B30515A89B79B6908DCF6846440F87266715C9AF73CE37F383438E44A4839A30CE8D1E3F1844F006B9B698D4DC52BB11F71B6C51B2338E85EC83E6DA2B60D0D5C2F3E411609EACE960D0A6F460612A4F0D6BBAC27D202D4185E36BDB1C89C64BFD5FB4F3E3EBAF34A8E1ED0CF24B10DC24DC54A06562F5FD9DFF7AB277682447F97A26203ED91925226074360D251B9D26BC7D2AF105EE865B1CD2D59A964B5F3C02A3EF33C9C9ACECD74D92E5EA48578D45A5292B91D221F872B77879BF2DFDDF2FB9198FD8CCB6CB0DE9EB15E610E1E4AE4D4938B1FF28304D1859066EE45664D849B9BD977BDC16F41E64B0AC60EB4AC518206383808CB59BCEADA3D87CDD6373A5F49E90DD5B7E71B389FB6E36F7BD7089A34698FC5195245F3CE76FB3B17EC71FEF9B160D7E7514D271CC3BFE9281C1CFCCE62BCC1C0D4B9C801BC84ABD9DFEF83E7DB8E9EDB02AADD8FD0A4D8C0954D1BBA04552F049F346E8209D4702A5D0EBDE2C199F73485EB11899EE2070CCE593983C8705E14BFFD69ABDD6C9F27B9FF474CA6E938B20654EDEE807006A53F4AEF62C897C23B5A160F43AE6E9D3B9A577DEB17ABE291A12BFF1D1FCBE98AE9406EAEBB27A8233B3D52AF2A91CCC240C2B9DEB50DB5C42DE42CBF56AF5860E522F45CB3C696606A3BB5346A1F18BA2970815577DD72D9CBAE732013101983720C29E897A2ADB9E36C8D77F39FFC59092532938E83D8E80A7DADB71AEC0AB7694BF8E5D67F71FA6BB7B185300D3AADFF3F024214964D47DC9ED0DDA55EEE3591B7C20145065910751D96741C2AB8D2D4C9B8925019923AD11189DA9F226B63D9656FDCC50D2466DADEFCC8BC2BE6FC07A5D99438E6CF3A164D30A342FCACF2D96982A5DB6E6DC6AED591D02896940DF04CE6B57B09341373A3E7D52D9B41941393D4E2BFEDB54DBE1E68481E3AD51160B41C92817F7EA5B95D759467F7AD978B099FE692C1131ADE3162314BC62C95462378CC895C5E4EE1FF383A39CB2EA495B83009547C974B9E82F380FAA431504689BBA67ED2F2D7DCFC9E0498398D9AF1E76A5AF5BF6A6EBC0C1DE791C38DE7505B65541A79B9AF4DAC303B9563FD8F5AF6E3B88AD40BBE143A4376D5C9DAD22A0EB6D66ECE160533D80ECC8124C186F93DB5826DFDB9800D253165BCB17699957CC1F0535DEAC0809E0F79AAE8793D0090EC09428DB8E5220C53D457D2BB8A730A668F35AE750944ED0C414888927EA329C71D1488B072CD9FE880A5C82C9B9CF915CD0B3B8A15688003D6B5E272EA61D3C8F38395864698B9CA4CCDAED1A1B40666996EF313A5B67C3DDE9304041556A6C6E7BED0E1C3775839AA5C0CEF42A6AAA00000000000000000B1219222C2F5F07000000000000000000000000000000000000000000000000000000000000 + +description = z_max below the limit +mlen = 32 +msg = 4B00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 88190ECD3E1BBA698BDE9C7175B2B855E3297F2C87F066EB0A4D3192B1E15E2A5539BC8A0DB56CE7B9387C13B82170EA91A38E195F432493716E923A20511F8D32F7AA4F83E420EB76B6D61101351AFC5E1EB1C317AD09795F08AEB9E05E5122C07E94C29E3D1C822C7329AE0F7969B6E525DF66956318EA7660E1210BE60ACA014B4D7C3CAED17D7DEAF39DCBAABAA4F862D2FD55BF310F66737AC2C35BC7EF8915CF9CAB73218AFE38A155DC49AE81F0C3C58D656AB3631CA535770CBB1D158FF35051D94174F86C3B7D3F41D3EC7D1A1F9355AE373BCC4518070733C4993FC03F2F03145B5A1D0E1398A4A425924D3DA2EFD00BAB3BC4151081A04E4E3D38DDF67E4740FA6CBABF3B0CBBCD411025B60B6896DB7A13CD9D533601B564FE57F974DD29AA828508E19A6ECD084188A2C615026380F4075F6F5A16F67D49674002DF963D628B3A964DC47D61DCEF2A42D72BEC1A4ADEF0ACBADF7AB0AC0C25FCDD3777EA1ED00F649A216574AA198C2CA1A6964D3CE1442074F5FA857150E0B2D1F1DC750348AC4A196E259D6B80FDA3E94EEBB05E3FA80F75EFA9557889629BE2C66D5442F917F4E4A9DDFA3F3B75B76D725D2B690F98BBCBB48B9C9D7864DC274E9DC21DA79BC6055810009EEF2AA6BB98CD7D6E51FBBDB37EA404D3C33D6A31DA87FF1C7CAEA51FDF9E5DC714961D1F82D1E6D4510E6E14983F2C3D045B4FCD0303B0B5215B2A9F952C7E5A7E411CF4D55447F78F7A60DA2E8D07AFDA18EA491723A2C5C46FEBDD342D823CF079D6BDD258B354BB46B2A5AA6F0CD2CE24CB91E011C061C72541A10ADA83FC668EADA549B20BD407660DED336CB72277B9EBE4A609124EF196407C7ABFA5D945148E6D735C9BE5873E8DEC42D61805863B937BA3D80EB60374C9B250A84AA2362421EED71CBE94DCA23FC4F9B31B8E6B716EF115750B0E8790F3C6A38E7703607A4C0CAE5BC3D69BCF74742F7087FB5C3F8AC91106CFF31A1C00E4F27A08EBBE7B06798ED269B23BEAE0F21273626B5FF61448179EDE64E4560BC8C0BAC582DA6FBF1856718D500A2548E0E7BB35A3D05679472E8F8D1F9331CFDB11F1A0CC117E8AA993CE5B05C605B74928197D16D18CE0E88C89FBDBB823744303D3432E898923DA5D159B161B9D406D3AC6CFFCE16B6B054AD2BD9C7A9E13F0511875135911363ADEC3D2EDE6C613B0D6B239BE3DD632272768268927B18CA4E25A3E5962E733D4F5A8D3A8724C414A00092884833F63990FD854A97319D04001CF3585769D1568663BAC855D6AD3780114C130D0E57784D7F7F7C042FEA6C03F7E5010B1AD08244AE6DB605355D657AD6DBDA61FD920FB74B531265E91DA21F3EED324DDB44C999AF8A718D964C3D62CBD0190E5FFB8D02CFCA43F2AECE92263960BE08B6042F76D320B572125D10A66A8FAE11A8AF4F50E7EB03BD872F34960EFED71A0CDAE54658FA50BFC7BEC9637FFCD2673B093A942F81D432DFAD0DE68B893926E9024394D1DAC5F6BEC2DFB4229ACB34E7E800FB2E3F1FEE759AD157E79C8D14985448011F5D216CD68BD7E9CB2B48354FCACF0E7798D3E380EE39895F1F766ED9356C2B422764C06E7525F1646A699E22618DABBCF2F6098B2147219B9265161D7F5BC5CFE28167748EEB34F56816367156EE9335CE64A0A468403C38F748A3BF93FF2C2AE10B84221D99A9435C7715F23A1FDABD334714907C2AEB22F8C7FB438E391A32B2022760D8F714A5DB12FF793E81114AB7B8CFA2DF6131ABE0605641E54D986C469DC6E112ABFFDF13231A34B8B0D204C27A871162EE794C66AA3A0441ABEC9942392CE162E6CF14601B65828E3D56C12EE3DF93FBB6B8905268D6AB93B02EB828A586820DABA8EFBE0D979E8AD8B8AA1DD3B8C78BD85286E4C7798FB2AEA13D28C3368E72FCB9D65AE692B96DAE8CF47EA9D0DD16BBE9C2129FF02B69A2477296D21C2878CB13CC0C9AA9E982C52D824AF6B9573339F1F15F468DD3FB9EC891B2479E1ACD663481483CCDDE9C793139474DE2A9C413C62DADC069E197D864E420E3FA1EC4AA81FDEEC8A0C356E58445D01099D8B12E60D66D7AB2FE41683E2980E48B6F6F5235A059490FBA0067488A01E6439801B2E490683C4CFD79F086223DDDA53EE4B66F132865DA58471AD5D01148EA0B141B311CD7C928F12E3DB20C766F13C22C43785AE80C6AA4AB8F13BC4F5C2E17E0C563C02FEABA052B47674FF148B020FF289018A70C453F05C211B8DDE962E71E9E6EEF85C0200B9B6FBF73FA4F1D8AA7D4572E28AC8C470D215F83BE9EBAAC740989F10A7D9E174A1BD1EC371930D0A543807328BB336EC3ED05C976FF70500449503825253D22C8AE30082FDC631F31A736B234B7F1DAB5A52CEB3C81682B57B2AD51797C4E68E59AAE137B191396B6DCC5EA6728E07B6359550A4C904D247C3D106D1ED3DBC97B5FCA6780DEC1DC8F37C1BE937AEC53F5802C64C73711D6C1D119AFC99B0C50E4F656B58256A2B780463916D89A9F7A3D3107DFC43D90B64B068711B6DAB9431A5535E4736E546B6875CC9135DACB816A56836A821307874D03BB56702310B6F2A813416AFCD87C25EC45C25CCEDC438A3626822FC85FC6B6FD12756510537CD9F20C0963BBEF088BD4560B1B722DD21A502493C68ACD6B84C7EE7F9908BC663E91990CA6629D8644C4A97E552A2FCBF4195FF8E0B265E27BD84580784CDA47C7F251B8FE4526238B11AAD3DCFD48E3626F10EC2B30EFDC57486C4D0CF1BD4F6407E7D62E7F680CC95F18847C207C895D22E778A4F8BEB7D8AC671213E7763D6F35DAE42C18D7E848BD1E808B4E7E57E782298AC52F02DC2FCF0BF5C8E2285F22595A8CEF6A3A22E90EB545553FB9A765443021599F85647CD1CD0DE00EA224B2FB77C3FEC0BE778F46A1190B83C1EA28BEDD22EBC38D8BC3B747926840C3CD658FFBAE54E98FD2AE1D2D01420DC323A67948B63D00721E14CD8FD5F6E964AA3A975C1DB1F54AAD4F8234A82F7E694D3EA036F3B61D031B53BC6CEFB42AFD0847CD1F1282E152F66F3A3CC005A9D3B0566827BED0BD0D5F5059C8BD13D689783BED285BEEE05AB104B50DC594FAAFCE045B532D31E7A3371D6F1C9B90EDBAB8D7C71DE038FAB4A7498886E002AF08DC0E099BEA3046912F2157AD57ED1D2C2684DA30C7FEA95152A96E5CFE8B9CA916D1D0F3A8CE144E99441071443FB3FA2B5338136EE6BF087615EDC1F6C12C070FA4AD223A2B718F350D41C221C7B5F2048073C99FB9C153D3AD259ADB01331D66F3C5C910F44AB501C1D92A533999B7AC0BF10ACE75E6EB4867513540594DF4A6C0E8A4B776349AAD80BBA90B20B87BF740E46BBD6964EEE91E54F7F698C57AB52F3CFC248F06CDFC67F06D9400881AB3F330343F528A024F282D9BFCD2C5077B2873E31808A3E375CC116B454EE48FD5C43905BDB71A91B0EAB7A13BD642BF0F36FA46545065AEBFBC26533684503923F0D840E8F9661C1B11B01149B396AB647839128DAC9A39EAA0F4F927B2140C8A2FBAB407D1BAA72E863AB8874DD056406E857660001B1994DBDF4C63BC7DEE46E26C98B823298A5572FECCC994D73028FB6AC2900195FA49968AFD0860C92E547BAC193B240526FB135F0A9A979F37ADC34D56C10A8AE2557F1FC238787CA6C76683E916957876AB71D5FEF0062536EEA8823EE8A17A07182E366545C6CB130DA906CD14AEFD564D9CFA987DA4B6833B2D6E91400904B73305721CDD929D6CD640FD4462C312E1F2811F93B47B650086599FC32145A1C94AB3B0A67C7DF23427C0F845084A0E163BB3DDEF3BFFFB5B420B908B7BBAD931EEB5481007AD1B07A4E0947E34B36A3DDD26571E6AEBBCD0B94CCE0154F2AABF8BA23CE0F35F8C5D82419BC23A6051FF1007935F4C38703919F829B9971456C7C51169EFC61A3155960E778BFEC49642DC11551AF2379036F9C9F5B1A2AE37AAC45519F83FAB4E14F41964E480E0F750FBB3F4A34EFF0674C8233E0D444028C658D99929D50EB95BBBEB5B16F90B4BE4ACADC4C7E384AB2C6AD2829B97038FB297804A4DB959B1C4588E789F9E35460A16450A3E1B4832D5CA66C69588AE4973DAE90432C7F97BAB95CC0C9E821D1E42564D10619006CCB9725BD059E19D1C09F65342B27436115E5FD6FAC5D560074BAA5AB9A8BEFC83234A99FD6210F038EACDDDEBD1484E5386C32FF1EA833888AF8DD38196F76A110DFD330DFDBEF1A1AFF2844AFF291C507F3D703ECB36817C41E6613AB500BDAB75B5A712467E3A7AAC1C22910F7D6154C48CD7D57EB8A04EE581809B6D35E0B6395B712FB1145A7C4CF5FC3184F50D0838D9A2F7ADA094BEBF21DA3E9FF593668811236A43F3E3446ECE18EB9D45DA90CB75E4BEBA18371C1D5FEBC262FEE5AD84638CE9FABAA60A0137C1232039F2718864F1D57AA0B5C0C0053EA10DF2BEFC31BD53E22A5D3F7D27C2C5FF923DF8C0A7505F09F5475F1E1595BD8728033A77F97754D81D6B0C43F45FD9DCB102B5389329EB27C7D199A34B06AB8B8E132305059429D424734E775CD8BB3B0697C031EF8C6B2143266769AC6DCEFF6FB494C5F7787A0D4E1F90F294E5386D8256063767C82CEFD182146475A636A828692C3CBD5F6FF07375E6E0000000A13192130344B00000000000000000000000000000000000000000000000000000000000000 + +description = z_max above the limit +mlen = 32 +msg = 2C01000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 1B96AE9E6D51A0B5FB3DC41DBE9A83A1B91D850588E9F6D433C42CF0C71AD03630FE02B43A41F3C617AF827AF60F5FD54BFD8C62BEA265344AD94270BB54FCBFA04C9D700CF009B74F90D66012F96AD265F7C59D71BA564281B39AE12F3F9BFA3D3DD88A93B5D7F34E51F0689125CF87418F350223CD4957219C0221F8C86CAD528A609BC9CAE35194BE6D761A31B315C1F011F0671BBC16F1D2525EE5908C5DBCC2BF227F6B1A02186721AFAF6168C5EABFEB477967FA75ED9D9E66A201D32C3EC5D476C05C2ADA966B0B32FBFE1320ED3E4CC10EA3A78BB4C9E74E76DEA0298F3138685FD93076C69A515728C6D0C950BCD6F9FB76F5DABB60E4555A3FCC5A020B84DDF4E51DCBE8F58666AAFB56C5ACB5DD4A62F475CFA66BB806F1792D80EA7D03AF243C9D603AA1D37AA9B18FAE107E7B3C13F25FD18916E04234939E8E14488257C79776AE04173CB91439B05EE00022CA590FADA75EDB0F34C4D300919C18E9EFDBEC7400C48777D1A4C73D23FA71C1FE773272AD90A7FA1F593784755C01960233708F45E10FE366A0276CE79F6AEC1D2E042D2E13CD4CB5009A9211DD43C8CE4D82F70AC207D52D57C6B6F53F03B8DA1AED029134DF00DFFD18C9DEEDA050513000242ECA8E4586D2FFBE31E7DC13A637EF298AA6E23F5C199CB68A84D54AD618500F66B180E1F8B147965721754351D06051B78B8BAB456AD986EBA18C920FE2D4426E6A665899311B0AC30A4DFD8306F1B9C98AAC0BD697280C6786A085A83CD2AF2EB1F4B127AB82B7AE876F4B012CD201686546C44A6801B1760A66665AC730A4C89DBA7757A229044905A05DC1312039B416C385398EA5197D4AFA1598FD5925E82DF7E124AB65CBA6CE965307D0670D2331E28B24442F185C8D176FDF24C29EACE23E1195E4CC1D71E7E1CB1ECBC144615959F2BB4815567085623590FDDB56E3F3A0E9C7B3140494648DC8537E683F0995FC4DB554A840CE0C8D9365638714DCBA28893B2251E59055DB75B7EB7E92D4597B5E611E353FE6373AEACA7735E5B781FF719F0933D9975E9A245EDCEEDF77BB5A7C2741E3EFD1A12B5C5C18AE425D53AA49EB26E3CD80E5A16A67F54FF7B4BFB588EA015E32281B82BD0E839BD05A3976EF6DEE6A6A123E7C743D1BA04262F73CC960765DBB7C117AC035D1444C754969C0CC614D800DCE6720C08C78E46AF8AEAD49AF596BD2596838BCADC863721ECFAE26E29B1111295CBAC3F8AEB76551A7DCE55226DAAF41EAB266A3D4CFC229DC48338348B91F389E33536392FB6E27D03B28FA88FBBCD34B449E514D720916D9C98C60266730470D19F8CB7453DF136FF7B0F61EA916E5477E5B8238AB9D02610A2CEE6CBBCF84A9A2C86A19439AAC921F14D710C25C297F1419B4F4E9824F56C0249EE0F5B9ECA355805A03DF22EBE1FBC8B93707ED1BD60A12046246186D9A816497E2ED7205E8F4359B6263EDD23AD2F4F308191270902D37845910B4B97FF1EDDEAB3B5A94D290E5110A0CE5DD76E78EDCA4C56E47EF8A498C5CEBFE3757A2A5A108A22BEEEB9E1A06B843A0B24DACE33B61EB3407B8A9547B08B079AB2C7075A709434EB3722AA91A5CA5CB3D8CA92D3C6041ED45C68D5EBC928000E948E6CD7A21A3B4FE05D4CF0D0DF772F8B7F52A453DFA6CE44D0D52E27E069556250FD069532055A619B84E4A22D70ED558766E946E351AB49009BBA1EE4A4655AD260773C2E046F4F1BBB5DFEABA6ED8C6B0373294C683C07589697CEFF68D9CA47DEC9ED8A2487FEFDD10F2DD788475B794E7E08654A111E478C88C8C6C1C6424B8C8FEF5EB489C098A45F33D74A6916B82020ABD4DF285EF5A5DCE8B08F2318299FB387CB517420316E47928A13B06CD34750881628B210CE93C15FEA4F16D0069C3476F9B4B257BC7FB46A9F7BC556A6214FD45AA98E3EF9E8EA89E9E4324184F152992BED351209F6E821BD9D0D0DEEB743605DB1AD840B02BDBE76E91A8266220276455F6BA16642E53B312778851E09D52E2CB848C6E91DBB551699CFD6203D9862C67773BC505D76A4BF784A77F95DDDEFF7B0F28CF61415DE003B79F198DA701797388EB5F1B56EC168FC1088EAD14B4796D47FF8ADF2A5A418C48328E474DEB90312C00A8A350C07CCC468EE49D194EF657007262B2F907EA6C72C7F9716F443FC02F77E8E8420AEA85B24E866262EB03DA49C11F59A5E47062BE56CE288D4C8D1258E6A6348562845628F278AE4C9DCDDF629C4DC553C7BD32B4F7B81A26B766D0FB13A6D9C2E34589F56B5A0C014C61B402B521D0792443E7042D2F9A621CE9F25266B9B0F5A16444A7D15E6270D4BB2F0C2E8E480C7E12823AD2ED7828B6EBC96158746D5B3C3107EF928E6F0516EB3C5F707E142ECBB3BF9C889247E80E3F7559B92FCD4EF941BA992580E436A814243BF6540CD692BC2C33720D78B8976D3618FE505EF0D93B4D0B91ECEADC785EE865B48B530316AF6D294890B518B92AB490BAC1B0D57F94CD9DA765B791EB6B573CC7E36E8C203867089B55D0A3DE1D1458A5E101F7748A620246EB3623AF6BBE847B2F895C9DFFD2916E072868EB1BE05CDDB9F6FD74B5C863503D16D8C3E50A329867883B382A9EF62B2B270C42AF262587E31DEE4D5829254FBBC019B3D237ACFB1B173DA3779451DA5D3373FA18551E45614E14891566ECD89B2945DBE72944E98A081995D28D40212768248A2CE002F473ECE8189F8803B7C8B9DBFB3CF6E203C59D07DE99D012DDEEFE35453D0B9E39ED880599AD2D28888FEAE66F664F0CA01CCDB3EE8085CC8A576382B9DBFD98A39F848D8D3348219D90C57675C20F24EB6C5BC8CABA25E7C935156B42D530F4C826BCB5A0CE30CBB408DF49DA6C06B1142824410FB01EDF247136536508EA9E7D77C5EBED0C42D4E398CF998196C47256ECF85E17070A609D1DF95112CF1A1E843C0426084F36746C0FE04AC0C75B23F30E766B6AD71076F4E9AB412A247043C47F0E0D77DF41BD7895D7BA08176A130E9EFD1C7F03B3C409F92A5098A8AFE9063F40A4A7719FC2498D2261EFFCFA3623EF1D0B96F39E7B934E0C58FC26B271695DD7184CD9A6ED4DDA919723E05A46E06E357C6187B00A485FE0808637CA0B5303F38934E45F377694EA67CC2FD2D024B6CE724A8A50EB440EE759A4EF5A26014393F7E8FB8BEE31531221409ED50F9FE199CD066DE33ED0A6ED63E38018F6E1B721AB494A8FC5498381592752CA136E16B6BD9323D7D52B9144882C70DBFB4913121FD1C53BEAF3D462147D17B0639B9CA109EA25574D2582235D5F993AA6126675D884339D9C445D5B783F5D63163652CF090E5513F0A5C12223D03A24C8EF2D4F90107D5D9BB16E472EF561B1D7284FD7AF3B57F28002BDCF3A4F6792150D03294C2DA159FC19577CBEBD9F1F6F6BB373731B5F993EAD2E4A7AC90B3DAB651A12E85AD82DD12D7989EA0F04A782BF85A7919EC603507427E40A2E543AE1633C8E6A6C696E89C9A53C4D0452D2AD350714FBA30B9C7C2C9E66AD86782719593796608FD3BE225CCF213FA17529BD0460A861211462316EA58BBD0966D46883E4FC2DB545BA09BAB14E75C6A801A68813D7163E3307E0CD8D1042E08DD1EC26E891CDD9E03571CA271C0490781105FD2818511DF86FF5FC045864CC10FF743506F3F7BA078ACC72518911D68541C9660DFE9A631E90E3A326FE3658B172EB9D17D20D2A282A76A3BB248375B331FD9713A1616D3D478EBA1842204824BD8DB871F3D7A20910250C1D05B928D3DFF0E869CDAA4CF16D4C853C7323C78D2C2BFB6188C8515B8A1A880C8EEF9736145D7963FED6C214508666D15AD62F3C58845C31B25C6940914020D3A0BB87A0304B49757D5854034D90A5A6531CE45DA4FC9FBB4CB333C734640D4089827805A3D7E6F6CC193615D4E1D9B6506AE3403F6C1EBF6F944B3528735647CEA4E820C36408478ECAAC229D4AE0D1877759F5E86E36A02384DC5D11958F9602040DF6FB79F47DEB7AA462F2E3E341EE98E85B023D379D5D06341BC7A32A95FDE0A5AC5065B4BCB275A074A3A9B85D818D1E1A0A58A95CD06E508D521DBC0D6593AAC784F59E350424594690974FD3034BE2311B3E1DA598039B25D5DEE8DBDED6793C50696CAAD8B9DD61F44CCB014D2E35A08915AE9BA304384A624DF50A9C2AD809B44B0F4A2EEE8A1FD7D10D9021C61BDF65FB09E35C5314F87506B19550E50BF19D5D37C079B642C5ED7B43AC2BDFE92F38CA2A17C8A3A58CD9E227647A1BE6F6E733C4BEBCC46BAB048AED53B15088063D67ECF9BF007AE533FB32C606EFB72B093F93E27CE1B3BD9F5279FF2D1B837D95B93B8B8A2371288DCCE0B9A55D600761B1263B017BD3013A4CEDA0E53169D4BE8CD9311E5CEC0D5AEF037E859419FF20DC8F413143E30DEF0E36EF1629FF6C3300DE11CFF5184F2A512B72C6E92F8233BED60626400300CBFA800D74E10FB2AF47B95887DC51BEF0C770252895E7279E63C4E2FB72BB28C661644517014AF3C5114700385DDBA3E245B6233CFDC5BAA0D479E6713B57F47413C762C626114F2248042E515C6F949AA0D0DA599EAFEAEC0E2329474F666B7D8ADAE10420548E6E74759BB1B7BDCDDF25289FD7DA00000000000000000000000A0F1A1E272C2C01000000000000000000000000000000000000000000000000000000000000 + +description = r0_max below the limit +mlen = 32 +msg = 1B02000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = D0F3650BE15A65FC38721C970E700FF8DA63AD4BD68EBA40374F0E1C303F703768BEB02DA4CD729D6F2A5E3DDBE90D72FCF3E32BC7AFC5CFEED6920F93508AE3688D0046D4D04737919FD404D790A90DD4816C0C80D8C3147CA5EF171FC266CE0990D973173D2CD9E04E598E47AFC7FFA7FA8ADB9F32A8AB47F13D1CD7DE14B9E3BA63A4AF1F391E7AC29773533CAC14C722D9F2D1FD2177876BC6FA0E906F855F9D41E979A546EBC5AEBA50E1EF0B8259B7FB5E0241E4A6D65E258C5B68F2F7CBF70FCDEC29C4CCCA614ADB534955D678493A4F27753568798DEA62E852EDD0AAA52DE0496D7CF65233E92F2A07168F1788C9892EFB1B0B1520237A02F43E51B04CBA756ABB46D23B89930885E21AEDC7FED54E46A47620BB8FBBBCA05F2385A5F8FE600694EB5A286D8B6F4173DF997FB08446FCBD686CA03CCB3DF8E5181357B632B48BF88DA86447752B9E04D02D0247BC23405667206EDA3A3231C3011B435F6E6B859E36952FBEEC26D676D0D6DC0B5F3662E9ECF11385A4D23E4FC8CFCE61BFBDBB9BF5AD4CCBEABF0F714027B3A7A3D5E0DCD5F0EA3A75EA29F4DA7EB60E39052972066F7F1B42A7109003C4DE3E075FDF92B42D2588304050016B32152DA99D8DE0CD898013D6AC918FF6B77ADD6B22B2CC4C1F8B75E0D1EC069E8F9954A2504AF914742B3F1D914AB5FA6DCE9D3FEB798C617D6230373E43D916D14340F30CF7BEC1DC2847BF71D77BDD6B2310FB4AAB6894E092B87ABE9B02CE96626EC2D27E1FF3F402DAC0436A6AFF6CF55439CB8E3117475F45DB47E95456331652C921439B8E6AD6F39171A0FDA50230E72EEE8434B5433F21D78F87839FEAC320CBA94BAE247DC70C456596C5AF329022F8D226045A89BB6FA01EF875F81EC2E53F48D1C8B252BE7ACEA1F51B9772E14D7E42B924B4C3B22CEFD3295CE1F753877EDDAC4930130400D9378A4F433D2941006FCABFC3B7160A2D4A53A5898C6F590579FB61DA92637D5EA1C84ED85B16D7EC4CB0772BB1BEB94C4DBF9DD5AB41D34FB25120D5E6B2ACB1B1EFA411E30B5A9169110A5BC7D13A5AD92E6829C324BB7897FCA65C290FE9B461F9E54756B81DBDCE7B4666251D7941F7BE7F83194AD814B202CF0E51DC3E3700EDA636DEDE2F3DA337ED6CB83E3590C71152BE67A836A97D81ED78201C1CB89292BBC90AF10130F6058A3343FE4A0EF296FDF045D8C9B9A2C922ED4FE7E9D8368C3167E0D5622C540EFC91619A466CA2ADDBDB5E0DDCB403C4AE70417B993F66D41032D65042FC79B4D4EB802F9E8DE55F6BF895AFCE5B8C3A2DA3961A54BCC5D2091123A00570941A7AE51A5E91ED1C549B8E23F6B8479F705CD24A295B91300F35EB82C9659B28B269C6C21D56599696A15C2F038B363B4AF9039B579D8590DACE080E805E70AC7B9F13F570F9DC04FCEA3D37A14230C04259A831450B8D8623B486AB03E9A9E6BA7ADEFB13D37F29DD1FD620F73BB8236625EC2B25A680D1FC0ED7C3097D709BB43702D6BE1A4DE7D8399FF02A3D5452CFB7D7CEB82C2239CAA23A159FA8121DCED581A0B966D36B0D4AAF26BE88B73A3BF3C47444C6E4610B802B729B56E7417473BBCA142E682EA46928E602E39487BF4B20E03DFD0DFEBD04B890D731376E4A773B96F84B024BB1DDE46DAE63FDC9187944447F2F3D59461E7AB691D364C0A47C64417BEBFD93FDE12FFFD5A6D747440C7FF458662989D5343BD8E7C154A3C7F6B661AF5FDEE60C7DE49E86F0D10E42DF9193CF75F07C1FBCCF6298972F373769EFAD0B479C21FCAD942702ADBF21D52D0ADEA893BEA5DBE0FE1C6360FDEE0F98E3E878346CCA5A09A83A1F8ACD046CD8F42439758D201EF18D532ED74E0C453D64F3D19464C532EAC1F7587457ADF9D5943B35E27CBE877EFF8DD52BC19A1537D0A6208531D6D5D8AB57A721BA399E7E73932219DFEEEF1DA9EFB01CC7B42800C8A4D0880773DDA3B4720E793D116DD18D201232C1ED7DE2F6A5854F5170E6DF3D848D382BDE975A41FCB2CDED3B4E40694A627F8A7D01AD71A88299160D5781316BC1022CA95D2314850243DBAF3AC054EB2796303B86C5DB224F8F95E6805288A8A832B0AC6B853A36146C808E2D5C0BFDA0AA1AC70AF90F5380391A954AA04594A2D9B62EC1E0CBEC2BFE73FB3DBAF79E3FB40FCDFE06AE96920E1C80240DFEA7B490F440319C23D80489ED9AF9D6B677CEA2D3073E46BDF2C5163588508DA085FC32D4CFBADEDCDC714FDDEAA5DFE7EC5F2A024224819539C685E76D0982481522DE0ECE718575EA5BB3F70BE7E9D93904F3B40B0F43460ECBF95CC269EFA6DAAB55CCCA5C2D91534AC60040772DA27604B08F68A84F3A4D977BA5D690DDBD8EFD4BD5838C8BB2F5DA599B4A5AE240C5B0256444C38CEC1378576FEE88C5AB6E7DD801F83B7836707FB3B22C1509A29640B721D8302AC2897CB10D98323157B6614BA2C3D5DF3F2BC6927853CCB1F39CF275C5A0729A3CF50FA91A79C3C7326DFF047666317C6D4E719662FFB25C40ED171508E0F938B8FBFA101B40B2B4A256D97532F801B21F3DBD65E693EF481FA36F92C3BF611C006E8491019EC087D6BC01549B6B7C3381C919E9DC2D1464849DA2F1A92C6D8ED1FB864EB13192B4F09E6B03017094C1A4E10B8DFE788F6617B9886FCAB092C8629AEBBBED6182DC58D7EEDAF2A5C8425BC087173AA79E570D24DCBC295CFB0495E3F1536B7C5BFD6C548FE7E37ADBF73755A3EFDD976E196F2FBE4087F3FAB78946CC70F3328255EDA772FCD627C7D07E36E2BB0BA4E04C7350872BFAFAA25218E944FD537AEFC8AA19AD321010F802C35846B7037F2FA362740A20096C22D79D0805833B79E946A7FA60D1C1C66F6E69FC5A37ED8D7A2D48D06560C8E8341AB8693BE2CE14E120D1DAD5868D48143116AA9E06F28AF876879FCF38B3B695CA7B2B64620097535FBCD449B69DEAF8CEF75C73EE09E160B0DD347BAAED60A5B1F5899D68DDD1D9915F8CC18B316C2A0712D7C459FE1D1BC2CCFBBBAEF417FE1DDB3813206BFA0748167447B124B7F2C1A43D317FED1BDB079CC05101CB710A01BDC23E2B83DD33E6004A618EF89DB5B3A0CCCCFC810B5DFE3B86166E3E3DA99A9FE6800F46CE69D3D8E0C9D3C64E404C07F8B835386B7002C90B915EF689BD35F1AF85D060AA18E6BF8A6CC3A5820B150F32855433381683E34B31D39AFF0907F10913C38BE3C3E98037C09D59E5A4ECAFA683FAE16B72132C9300C1077DC9D786D7059D349D3BEF11FDF31CFCCE052AC6FCAB6BD7B148ACC88D0CD0C9771043B9F8612AF19C25647AFDA5C28A9CBD9FCE57765643258331584D3703721206FCFBC8BD70CB9693D2C758BC0E89385FB5A748087796FBE061127997267499EE685ED49C8EE0EF64E8A0136810AC3B75955DB31E0FBBAEBC171D2D05A62F8DA64ADABCA6BC21F459608EF6BCF39C16AC8068EC98A729555687E9123018D4E2C5E2DF32BCCD32C630741B3BD06369BA39EDFA64A73884E596DDBE2AFA6A36D2BA073F36B9D5EDCEB1E62700F1F0B7A78B8E2931645BC9CFBAE8F139735202F1BFA82CB34E006CD501C619A68E852C2BF7FA1EB653140A0E2DBD81A78DD57AA0B415F9A031F6DC1F2B07380FBBA28B6454E9027108F407206E1EC8A5133ADB37D8393B45D89632D5B529D1CC67F9C68AC1597ECC6B7AC1165012C2BBE3A72AC98DFCBD66212CED459C7D3F8E3367F3E6AFC6C7C0EB6591D6FD090A9EB93B0719311D534DB26827067283F9DE8CEAA32CA3C910A79F0EA2F08F2B5FEF210B4134648CA1543A23091DD6BC586B530B6E48D13828C16CF2F048CDD27A641FE0DD3004FA1C53D0569D5DB776D6AECA58AB5CA4C7A57A305FF6E71DB71852AFDC0FC936987BF9B6745AF2504392F64C752F9A234E29962BD5B12F27685815A36D9BD488C2A892FAA4254C50454224AE3CE9D1295C860990B1E467B659F45606A7C08017B7CFBCD68E2D0D739D9ECCF793A04271ADB79A9FA9BC1D1A5A96633024462D0A95878CCD50938511F375EBD07F0F94F6151A6C1B8F787CF9F84B44C4B2CD30329B96B854E0A3154A21DFB000EB187567B815FD35BD533D61BFF2365A11139661D41E68D22EDD2796E86369DFF96AA458BE212FA6FD8295D543E7217DFA5963A0AE6DC1175F13341EBA2910F60742A778152DA38F22A09EB7D1227F8B8C3A33ED5208FDC1F1B9C0290850820A4E6C874675430356340998F6D96C9D7BAC6C0B12EE232836840F4D8520B4685B0C2C1C9EB7DB8685F0A39358C8D08E292844EA6F25F07280EF453DBB3D9A2C5DAD2D8AA379F910D9581AF4914339A7B51A0E09AA240DDFE1C25409FC87E6A98B2640349C56E4387DB5DF820321C986DCCE30D7D7F56E125878F4439F53BC44B8C8696EEF0FF1727A7A6493907B5A19B6AFAA1A62D9319B79E8EA969BFA2B00DAB99CB574EEF7EA781C7CCA5DE961A8E2C806703F2675162C7A3E0D92534590E9CC1179DF6CDD7BF086E55772B7D6D5174EA4791A596E8A6811888FAC1DE5C9533C43ECE84BF374F8B9E2155C85EF4950EA2479FDFB5FF112364041ACF153549FB602363C48666CC4D7E0E8EBF69AB6BCC0C5DAF2F755647884E51E2E387EA3E4F800000000000000000000000000060A161E232A1B02000000000000000000000000000000000000000000000000000000000000 + +description = r0_max above the limit +mlen = 32 +msg = 1A00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 911A02631BFE7FBA22BC9A785646A089C74FC26BD86516BBB9388554C2817FDBC717F08A0971450EB8092E862D92FA4D60D566FCA3C0BA99BF43434E8D12580B9F09D78D4C045C618435469EA5A43686144A858EB1DB217049FFB036CE98C07D0EEF1AD02EE7FC430562A695D94E7B7F742C0D1F0AECF9D7A21E1DBE912B800FE894735EE371F0EBE9762F86E4F0E8E5302E306F428B56B1399806102BAC34535D3B4A37857B75F44E8209B2B33661EAF9F0015AA2596F24B21E9547BB468CA55F8D0983493F8D136C8C3D5E763D98D74A819C1B37511357B6552F82C60AD7DF91EB8A38762B3B39CB04AE30102F655DEE62A4A5EAD07AD0EEF62D395A29029867E3B7AA4B58A0F0C34C33E3827CAC3394E423996AE78FF8DCD5A399B8B29EBBE57453F5EEC3F540F00A2A9FE4810C83DFC99F1D35C3CB7606C4610FE91655EEDCF4A0B2AA7B4328B715268BACFB139909433B014CD32EC22050365279ED0613CB98A4B9A335F0DB3D66195ED2BC7F4F9C7AD545350A939B242F13CDFC1D271E3C45DB87E0C21D0B97FFACB0BB3DC5CCED8ED47D3891CCF94071CA38F62A96EFB0B23B849071E5BB01E8D5E891A5AEBD749DDD37BE5566B99AC4E242610AA15E3537490ABBD4628205924AF7B6300EBB9DF52367B0A2614D78471788A4E6E1AD9A2CD4D9AB0C589C42633D84D49CA1257A99D34BD90D14900D556487170095DEE45CEED8D5000A2A4C08D3E557B143D6E30E540354C513450828EDC7485787BDAAC462F608FE056FEE8D9EEABA663B609A2A48D1E9C79982DA006BF9F7AD63D64BC01F4A4E43F5C7EBB7C745C3C2315F080037EDB501F601788042B865786FFED5EA00FECC0156B6C2B4546F6ED1B91D700C12B222F7E26B3A296FEE0EE16644EF037CE46B30EC1B26A99430CDF27CBC6F4307A3A786A87EF98F80775D1D57D22C70D53AED30F91EC0F8EF83CE6D6F13A1A96021A739D69A1A1B6828502910D1A56D2716F8FCB6C3F5286A59740FE966B0D87E804880545DB932E87199009884236E1165A7A3E40B5006438EDEF71C90DF275EB2E43F27376A84189FF3B9FFF14DEC8FEBCE31398CD656D1E10CFA7AD88673C61413870F92851ABB5BE17035C9A4431B3F2E0D9B9A9C97EA5FE7B165F4A2A79C964DF0CA6AE3191820ABABF197DEBADACC455F1277C9E4401F3A7EE4BE9A6A0C69D3C8A3ED2E69DF31F947622F6E606126E03732021DFEAA8B03FB3CCC2F90AE0E8A00F0A5214EB50CE6AF2296901784C5853BF28A9DF062CBFE8022709ED68478004B774A85ECD71D2CCA96D00C6BB9C35ABFADDB5C23A4CDB0B8DAC66A4AA5F00064ACB2953226B41B2A470DD74051D405DA3014A5A892A3A0836263AB68EE7258EDC65F6C59F15408957A7B2740741C75B84E3BB9491294C6CC943D85EFE43CB4DAECF60F6DE6D6470DB27F83CA29486FD322F4DC42D88147E529E24C3813540EB1C66D64840F144C438CC2F553592AC178394BF6D08307904D512B8C9714BDB96A2C5500A7309ECEA8C5EC107C7B4BE4E3A0731FC551398F008C5F22B97B5E7423A86A5FFF31C3A91B24CD609B51F5918E74B1ED696B9D782A50E378C11BE38B3E5F5FE7365299AEDE89D6865C7CCB173FF6EF223EF7664D978DCDCA1658E92C263CF446C9E3932EC225885A866361B251BDD6699C7BA5F6AF7534B6E91CDBFF438A320C43CE8EE4F69A860703FE8517331B23105D00A78DB06B61D9982B89D12436ED042B7A9C596069ADF5CA1C9D32734D8748D34A0DABD8DE8DBF90D1224FC794D07709F390C845E4F26822F9C428D27C39A1442AAF794FBD2835C6F35643E50C5113FDD0C75ED2CABFE9E7E630A5FB1AD6C2B342267378ED7E0762B914A93A9A010725008485F2D9A02F7AF776B3E53A4BC7DBBB45089644F71D447C3A310AB40C631A7748933991F40060FC13834C5DDA483D625DFD8E231AC958664FEC34A8365D4B2D798732009395ECB38F9B9B82EA832590C484E16BDA281E82835BA9EFCD738DB10DE95F5AD9F93E8F6DCEF28FF930174D23CA3D7DA2C4950C2F4658BE1845792BE94978B2B25A9AAAA0FFD31DD7E7F015284BEC91BFF7CB404AFB447A73CA72AA4D05A15FD485EA257C32DA5DC6E102CA7A98212882DA4B57DBD3E8A7A1775DF3402B242F3BE9B6E717687D5D3F3A1F55F1C683E7DF7795F871433DF3702B5EF2CAE52858D18123F3573A95C1876FE0C6D0BC7599FD8A2E992057EA308EC29592F422A2EDA074FC1A1BD4F9C6DA2652FC217DA21B5242141F0326A4E0072ADCB5FBE7AD82FD2B1E3A97ABDFE72ABA34628B78116C01A45B331763393DF589C178CEE3B7162F488163C81FD44424A2A3A6707CEBF1F5F87F2C150D61AE6CC8AF0C708A854677D3DE0381ED987EA4D7F69FAE772A1EEDFB7852915BA084FFC0D057E0456F36EA22E6E4234E44968ADF8BFEEE3692C5DE12776B819E2AAEFFB425698F802607110358FC9A5F1538ED93394C86C25312F6DD7AE5C9D5E1AD4B2CD9D32E7CE2095CB564F7E3446F6D5DA0F57A5BBC3D5D427AF30C9E1E7CDFF8FF631BC94CEDA2FF6EC746CC283FA10AF1BEAFAAC6BD43E5E9A1B63622A33D5F7A7B7D3A741329DDA5663CDF9E52C195065615039B9BF96CC1093AE5B6778BA58171454374953F2C5D50721CF943C28825317AC76F2F5BFEB55D10E590E437B3CD46E7D464CB76A8612B9D836C22877AC89F4C4716FB330BE2DF6875E074A61147E16EB02EF627A54BA8641148DD6B556B442572FB9C14F1EC5730376DE535178C3DC92DCEC68016B8CF3C28D561F393BB2C6A90E18B04C9FB06ED926A69FE73875B3E353944BA0CB329F4B8F1A527AAEBAB4411638E725F5F8D837343A8FA2E6D1C48E8110A51BA71BE5545D066ED06CA3EA83CED79B7D6FC8BAC02B53F3BDA4D2D38A52686FE51A72E8C1635C230BF3DA64B378B673AC6E7B40FA1B22FDF14AF2CAABC8515C145AF6C054779BEB47B4749C1FE40AC47EBC1AF9F4F73D8808AE5AC9E6B85DD571C19A3AE2D5030B8D8413B9C2508594DC5F99E879EF8A7B7A4572CA8DE9B5D7C3C6B3C09BB437408E2DA58DCBB37DB0F36FC67EE74207FAD89FFFB9E6B2E1446DA2422E23C339999EF2B946B6758F5D61E70C53D48B8D2CCC5BFB8065684D36630F82AC806A2A395F570D9034E443DD10BC200C1E818F67DC86401457B9B0B82F6D7E6FE2590B4FC0A380867A099B3F5D8B51BBD2DC3D9333C73CD86C6B16FC7C703221C67A6E86A9D7413FF6FFA010F7351782597BB84CD26ADF1D92F47613DF428ABE3B9514ABB15A00667CF14C9EA0C676FBEC0F7427D9B0ADDDA30DA7A2B895C291CBD017FE8135580B3C9CD69FE02E08E9F140A0674311C6B7D3ACD4AEF8F5E356A2458D7D4DEC8B7364BAEC737A93E5F9829D247F9C88CF200BD42F439DFA55AD6367FE010777D2E127CB191A57C969D1B579A69474EB8AE222E1B6CA9D174C1A35BF9811AAA9FF1594ACD0A41442031BA47AAF1ED9F94C4B4877F5D9AB810C2BCDEDBCC35F2195385D0F41DF6D81433418A8DB56AAC9C24832067DBB7A8D56211F7208E6399C25DF41422ED734D5FC475D43B8D17497005D2F629ABBD6C3838691DAFA7570A2F9AF8EBC90C515C844DE8849D137D1D5A89AF65E504E09CBB43BD3E73219E6EA7C980A80364BA999AB38A3E9AC2432B582D8DF787459A9330B926DCC7B4B358EC127F45450B14092A43B53C35CE034353602386FB6F74FBE48F56257487F0584F10C8762750FC26326861D68C997D5B37CE77CA40647C82C445A9000CAA64685967D4B55C99D21EE59EF22B5E33B4637400559666B6D250863AEF8E8F9AA467BDD36CE406616218472AFD59F562273CC08671D1DBDBB48667DD685B4C55C0C202D544112814E4E460C72DEED53C9D1FBDF6DCE5980D89693BBA5F6BCB0CFB60FCE0C922C7EBBC0D25401892C7BD8F3008ADE1BD1580BB6200CBD07582A5127396438E229B50F237D84D116F47401E42E499B4CA139171AA4AA4C903E22A72821AC9858AC764CEAD0D967365E7DBAAEE5F366BBD66D628C67C870B884D58519C6B731ACD4C857E2D5F3FA6E1139042BEDFC3E4D56AC41769E6309824E54120218CF6A77648CD7859854287E8DAAFF5557921EF3880DE6CC58E860A43038AE89FE74C47EE81F87B8DFBA55B6779E43F1D064698143136B1181FFC0FB4182DAD52DED814C8E10D4F502F1940689CC5BCC29B0B9D88374542F93692229D9F3BE6ACAB3CD82A93B4EDE5EF5BB013208BF886E171D43485D9E5C2F214BA633D5134014D111E836A23B2953204AE34F26403EB61622DF0B2F5B76DA164F9F9DB6758C645E1C06EF88D8C277BBCD739C75A6C9A2DDA7542EACD13D16F38C6532AF09CA060FF0E526B6118FEBF5744296E9D2EAA93F1A4EF49F586E37E7DEC4EB719BCDD338EAEE83223480970F0BE08BCAF1F79F83673DACE99972E4210D54B6BE0D9211B5E98414CB160CF2711C9CD58B185FC9AC4C3C74DD78548A40120C5089E485C9142090E9DF898D1C2CBCC04A38322FCB54ECCCF301E15A5DBB568C4AB748DA773FD9BADD9200AAB0305494E54A2A9B7F113383D3F6C7785949DA1C7D2E3E4FBFC21283453779EA2050C62DEE1ECFE2426275A283159829395DF0000000000091920272B321A00000000000000000000000000000000000000000000000000000000000000 + +description = h_ones below the limit +mlen = 32 +msg = 6F01000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 2A7F2F6E8C77BACB79932ABE5708AA889E16891BF04EB42941428CDBE5B2A02694D658D104F6CA51CE8E87EB3FB20E0634E4239B26D0D6E08FBE9C8BA7624043EDA4D7606A3F18063B28C203298DE764B4083578E36B73751D6DF5D0B2563DAB5E40F30AD99078DE98B14176DC57547F06C466359C30D5E0B953D3BF9D31442D7E006CC29730D9F069E487E2830C21C2E191D2AF81EFA3F0EB620EFC0512A99EFD5EF8D7EFE658F070399CDDBE383EAF46301224BBA1326C86B260F8701F616D1908F8A9FEE8B42646B2B1EB5735F1A62962395013EC05DC549BFCAC77795DA42B103730FF65843DAA455D3D4F516A3A0A0F89CB30A3647BB2AFE8A03E359E1D7380AFCC316095290D731BE3631A57F1F2FFBA3BC24BCCB32DF16030FC5957267F1C082ED8966F3DCB14F6A209CBEFB8E24FC6B65DE21422DFDBF1ACBFAE731971E522308B856B69A0B0EB041668C5F966379AE1D3A6AFF00E726C9BC73DD70ADF67C98B933098E471AC6EB740074C834D429F8C026932E9103EB40B8B1C2842754FCA9EF28E6A4EC9C7B878241AC720834C854E551D0222CC1D8C7C2E4718A9107C4F56668D30E40628FD60272FEF34C6AD1CE3F34F91B1BED2E4E588220ABDB7CBFC497699574B1931E4824F4673C42A37BC6DBCAFA408B31FA067895919461FCCF5E1CC364244ECEBEA76B3BB89A92315CE8A954693C1B27E619977B7606AA81E1EB41278E88169C4F51DC9F08010BB85E4C63924C2F36045E2D9FA8C1D8A339D1555428E5D43C2DE4B156997A3189FFE356A4221B18B74DFAEFDE39C619322FB080DE0F9C4299C75B81D54E3EEE6CEF65D4B075D032D66F461D0923F717066834D439F50C865D01A874D9E4DBEA8A187BF28228C9B557A854AFC6D68B83CD3670F49247DD6457E4813CE430A2E16847C2AA0943133E30F3A4DDADA690830CB4921895052B9E4FE7CB28B95965F3659570CCFCB819C238767450FC25A823EEAD30273B5BF955F5D0548506125F2D835BCB807B63097A7C3D704C693B6D5043DC3C9679E0702BC729210F1A546A3890231E92CF40888837D8E9B63A5A58B8596AC5D06C97FB232EC836F3DFCE3B512E67BD628A188084E3E7D90048F1A9348928B56314D33191E8FE6A9764A6CD8EE75F6518705B7CECBD2DB4A2FEF5103236A0E896912277D1504074D8A3D3073DEFF2ACF5C5E06BD6F470E714D0955958CAECC552C72E29697A8D84611A7DD5D73AEADAE523FBEA696EB59D160607FB62FE7D8ADF8DF1AAF5D7C5156E8D96E0E4A9F903DBECA6F2E81A8E2771309F14C761A4CA30277F9F2DF8F46D30423E8084CE69D0FF8EB8A97895FB193B8DFB6344AEF653AC818C54D0CEC13D40C8A8D81650D90DDCE05C5D941A0E036A326B8D13020254AF23B06EAB878BA9589AF355D45BEDA5E1BD8F6AC80D313AE12F0B3EDDF25FA01B4DAD3F06EFC918B6E7997F16A8907E1E61C8135CB4CB1E8D73BCE5DC35279D4435D4B66DE97649B6A11498B33F229014E9DE1366369186D99D03200BB30D2EE6EE6464A05ABBEF217F3AD6A9E686CB2DD792A25266BC768CE17B3C32942C92A9A90D905500FB95EB65425A04AE954C4EAE92F6CB6D0BAB3CD722DEEA1C79C37826A7AAC4311D31F3572565DF5562D2C89E8FCD895B61B8C24A9D69EBE46630BDD7C3CF47C98453BED0C82CEDC409F44E92258FEBC72F8F137CD1C09604669C0A1070B25C09CC6CEA05620E87643800B5E0B6A45BDB5CAEF0D969688F560856F332B2095F764ABB9340985AC232A800AE1C9291AB052A0B5AB0F18CF76E75C60F400A11EEFC5531222439E01127983F3C98CCF418474A937173DD1D0C9D43CACA7903A04BB5AE633176E5B059C1176FE804F91F7506314B0AFDBA5CB7ADEEAD68257BA8B2CC07286834DC8C0D5E50F18C6EA45F73FD500222C949D4B57331F82A39F6D43434A852F5C2CA8DA7A91F7BD78FDD451A7A8ED6799A3DFB3CBCE3E12B8E0F0699B0BF98B20561CFF0950E6CA6BBEA5D714A52240DB59AF0BBE806A043611CC17FE310DF8531F4C609804C5382800DD2B701D38FB9DDB42C698D9A324E636EE26BB39A81EF8A840E7C0602CCBE31DA2FE6D816DB1F713225F0E95E35CD4A3232237199735BD83453BF63DB456FBDB06D0F7CC7B47B2EE2A8213D221A364DA2B66865F54876EFF1BF16AAEEE396A8D7EFB722BE2351CB93B28461A475AECEE021A4CB3C8C64AFA243FAB6111A986F45AC566DAD078DD36D440441B02B5CB5B69E39A911253B969BA536D9F455F1E0A7FB1E5AEB4B816A14F2E07F951C82AD47E95F3FE4556C3C13640F29E1B0287A71531B6976E34DCC475B2200C1AC90373A52590D65C24DD2D6FAB4A77CBD3F4CFECFC52DA0DA146BFD120D8C8D73FF1AE819F940F14219A1914646AD0B20EE103C5392283CA98E7C942C54EE77F4C46D7129502756645AF792FB995981AE4E9607453D6EA8C63B64E7FA10DDC1B8D5B8533FBF6655F0C7A6351307201909128DF0B90C70287BD8E2BDE06E2BDAB02C3BD319AE8B422FC3F5FB9BADD45255BA572241DB8F7789C108C8071067BBB0432ADD83159437592B6F58EDBD7FF57275EFE185FFAFFB6629DB28C28737EFDCCE06809B6320902C154689624004CB4A8FCAA65D336498BBD41E464559ABE17E3A25A29E824EF2D9CB5F900FE0250625078C468BDED27C11454A84E727A3873F5CE9AC68DF451B4C055BD4EE12DEA4FDC49D1E1840D46B87A0C8B5F398C10DCB249332E027D1E6F3FCBE33B1C0F26B816742099C74EB1608E16CE31A18629715941F6BA7190610C1BE71371DF6AFB0A0471762AD86DA0D00466BBD181975E6C410AD259EA6CC5C72FEFB5E185CC612E33951522DB41FED4AA84B9B35767E78A3C3598361669C82D1B6E99DEF54ADFD1D09F88BAA00C413B18FADEDC1D92FAFE9E286E3C0130C83491CE4084543AC52B115A96244CDC68E8F309E5EF041DF076EF0FA23B8DB04070A12861C8CF0913A8C11837D716FAE090C4E3905E15C4E3F6E1B3ECB8AFFB0FCE86232B85626F30EAEA00A53319C32DB6023C63E799668F30B060B5E883C4F15807831C6AC003A08DE6B6BCF1A758E37BEB99C6B3C1E486A0324DA04521D0446DD960300B3EF8FEECCDDEA79CD0143ECF516B0AC37FAEE1096C5403752A550192907358536934B1D8BED3D1AEF9FA56BBE3CA0529D64BCC9A6596091EA9DFC0BB5B5392459947F1025EE5555B56E083C97331135400BD25D7F30D919647BC94A0577EC8963FA261C02E4E619F74E7CC803B0D2976395BE4A37941E810E310B4CB04296210AB167AF312082EA73157F0160F24126D2BBA3B70218CB78A3C91CD573966BEFDB9DA5B384D8D0F6D4FBA384FB502800E3784F432CD2AB14D200D45705746622F659EAD3D297945380236515EEB97C90033D5E2ACC2FAB9A71F386930F9238FABC4063038ACE5427E1526390CBA00F6EAF0F13FD3D96228B988D758A64E8D9105977D1B5933D9071F6D7FF26537D730BD00F871ABEB94620EF4B10A152C0585A3DB26D12AAFD3AC9364D3BBA9E69FC83E1864587A1E1D4F4FB62EFCC92373CE2D53473CB567FEB7CAF022842E5C3285C9827BCB4B2013A834A42C36309DAABFFE52A9F8D2D8BF309C764CC1D62CD5FBCC07AAB6E4D006E5A4935F347B45D7BBD1AEB46D1EBAF0D32F442DDA1A19122AAD3690F324770D6F867D0AD24CE0B590252D1D6F915FB96391FEC04E1F4184D82DAED46FAED7AC87864875B720523AB1F3E176A207975E6EEBAA4CED0798570519D0689EF6B45D9573EA3A00812594F35591FAD9E5888C91CAAF8BC5461E717EA5A77FE95E336E6201AC7AE3550300590C44C46F28318367F8B88288F10580C2A2D71DC4DB6DC07192CB9D21EFDFDF85B93E9C0C2E37E52F16320CA17B6A64848993A12A152DE79C486BE1E06282FCA9AD4102909E9EFFA4E3ADC7BD2BE958799A6A8C9CD9EC22B853364EF6F76CCBD1ED6469EC65113EB78433FBAB87ECCFECF1836F829A51C7B9B3F710D8F90B7506117087679015A4D51C93F59607ABF953C75439C1879BA1E31A3A4CC4F878839898C08E333556D9A7D499F133AEBCC7D98B3576A557F52A88E6D5AD099E0597B8B1834BB00D9752258BAC6E2D91502A91916837BE2BE4AAC02A474A0A776DC81AF8C6898F0E856FCD646C2D4D71F0EC913194DC59DAAEE548D41174750063EEBA775EA83986C2EFDB987EEADBC6D5DC36A9FD870F1973981D8CB3668C792F7B156DCC832654F4EF08890679DAE49A7513AF040DADC0B08563F95A03221194A02D0BC2B41F24D7F194D86D45961657DF90737A8571312D407C8D6FFD68CF74DE9FAFDE864BC5DF2456714F812692B8ECA59ACAD89BCE4D4E853845B2DF5570226F1D04DFBD6136C633D9018DD4F8171A10C9839E4C777B0D9F6A43DB8B82E8DC9FC367D8AFF643EDD08E5C3895FE40CE4F53F72453A77B8B816F9969BDF19B3BED5C7C8F129BA24150D7C355F50D6A500F6D6AE4592EE3616966BB0FBFCCC751E3F631AAE9F92CCDE3AEB6C9A98B832E035FECB23764CD82BBC23DE3F52C82C060B2A6B70B1151799B9DA1B3D0E30C5357A1AAACB3B6C3FD0F11196283ADB0B9C1C4CDD9DCE17689D0D1F6081F4B94A8B9BCCF0430394E5F749ED10A1422272F376F01000000000000000000000000000000000000000000000000000000000000 + +description = h_ones above the limit +mlen = 32 +msg = A301000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 8AF63ACAB69436B2C1244E45C8E6F6E75DD5F7EFCD93D132CC613A0DEFE5361548B9354DBB2EC4A674CA4E4495583EA51BBC3A9506BA941B305D4483FC09699FF6D95D55F12AF96122C71CA8732AEA69CBB3C21405572677EC926C06EE40B0A14A39EEF44FCE23743F0285E9FD3836657DE1AC89006D100A189C4A44668D1A96A519580DCEE29E2B4993BAFE768D9CE84DA1C274399C306D0CA24B3863E021E5FC1A7361362DC1E63B765A546F940259910A5CA341622F3A0E261090B4A30AD4624B2F6C166FC8CBAE6366B19689F5A33DBA664403CE6A5639645EE46D9C49B6CA1F0FA6BCD9F62336FE4BBE0EA5A571C116252A6EA763680CC12A7B25C4726ABEE6C6F46CD7EEACA9D33F820A13114C0D5B8793B911B26A3F43C29C3F87706694A77925BB7D67321D56DA25975ED08C04D20B713B49B6D6E6FA1CC76F7FA63027E4D9AFA19690BD4A356DBF5CE1D2D65A84EA803122DFC6877998A9F1226FFB1543AC4ECE57338BB87C02E182714C904416A10AE8742E6B8205686D5FCE8530BC1C9BB4CE3D7E1C1C56793D60814D4878E7F5176E09A40870FCA693705E2BDDB831D74A366A2BD668DE5BD759340276E59CE846E14DF866A091A7FA689C71DA1594AFFD600FC1A202A8A6F9ACE2820AEECD152D470D040E921760E48311D3C6A6E8DB2ECC948BD8B0BE6731E0C0966EB2598091413B331DFAE46DFAF7F0B59107FCF0806FE2B6B551A20826C01D04F6547186C2E87514236E904842B2BA5A20BB6621DEA873057EA2592EC1DE4A5FA9B84DAFD92A864D1EEF8422A9E3320D913CDDCC55D56739248F1BD61489AF13AFE4EBC6F7D3A6651113B613F5229C8BB78238BB680DA85DCA417BA4AA03339621B35180EC4D2075A2F0BFB23B810BD792823B85978A46E659A258D00FFBFE5423CDD2CD5D123BDF98FDB61DA4CB926F9B3654A3479F55AAFDD87831704D3606D8645B1CDBEE5593D69C2ACB0769E7C4820B0EFC378E7EE56F5EEC9C4EE0076677A9F9B89F08921BCB880D830F2337EF7465C774DDABA7236C3082117C40DF45AD54695D2158992F77A3A5DE49F3B0815B30A1B3DEE31426F05513504CCF31BF88B20F0F247FDCD783257EB899A0362CC0C9119B683E3231D3DC653F271BD9C80E0E50B766C609E7F49B1479E766D0603F9A3D978B21FE88265ED6A610D56B9EBFADAD6D3939CC5F85FD733EBB631FDE924663D1F02CC1A190D53CB17D5BA519B3E041D03B01EF85D0C1C4D86A869683B782BA8847896F92D38FB54346CA9AB7A3AF3577AA4DF727E97D070F5044CF3E693CACCF4F04877ED36A940298AB54B6DE65BF9C7397550AA68E0BDC4D1C362643A6B24C655956FDB80B07E19EE941B1148FAB8AB90163A029689F168323AD9D3E27264ABEF2C4F7DCF1E84C29B9655445AF8CC195FF48B3E22788D30C42322C22191D02DCA1EBADD062D937C9C852FFDC665312EDE8A4D4468A32371F7FBD2962836478F26E34F1C04CA2278F13F7819C095324C027E8F702BA0DA42EF814DDDAAEBAC7FDF7B1A0DF56E9D3B0EE05159681B7AD30A8BDCD44BE7965D2A3101DE8808B98D9FD992F4042ABD1B55B26EB2BC7DD314DBF64BE5800588500A418108ED417136AB924A544578ECC56B58DB53E7A8952D350E1E98AD6D15A9BDABBEE835C689019F607BFECE26B1B0A8F90463316AC213B40F5D88E56C5659D626290CCA99C7BEB1D9774038D7BE471CF9FF5F799D8D1710DFD6E4B4DB9BAE982A231CD0AC9DF41F47DCB92574DD0CF68E25396837AEE63DFCDA9B393F2A2277AD2DFD7EDDB8A50BCDB335A8BD44A6BD0CB3551D1BBEB19DB1474C6BC6AD6316FF0EDC21516B67DC906CBB4A4D2EF018C3821186E3A323A878FB502384CAF49E154F0CE43CB53A584357BF20720FC0044BE73EAEC90EAFC4A7BDC55D78FD7153EE37D24992E5C846557211AABC4661A79596C1CF226AA758E0FF776711A99640B3AFFF33DAD0A6055E8D6C51AC69B125C916A0CA520FF9F697FC395837F43414380C520958D84B9BD670BD81D81FF456C5AF9190ABC2498A5DE0F08C982CFD79AA8652A0DC9AD70F1472A939885972BDD4E699546815C950FB26B5EC8691C6DDD3AA53BF55581226606A5630232E4E4EDBEBA6DB684522348E8228B9DCE09B63C3F95029C7CB4DC90BB8B4156AC4CB4627E3D2E12F2197CF8C74C2840B91BE255C3F02BCCB427B2741DF2EAF7B2B9C8B9ADBA98E74EC42E95C0DDA2652180DD44FCDB008B1ACE527E1F240DAB90D4BC80238342CDE0A92122C55F158566E0FB9E0DB9391046CB20CB083610485BE2E700126F20FD7745A0C877251C10E1773FF453230973E794DD11F3478562F1E2984E4EFE2EC780877329CEC171E4F6686B8B8E05AC68FF1296D066A2391A700E6C59B78F374E397F1E02516FA6D4BFE312A075AC4D4A5CDC062C7A6227DEE0B95714C633447A557DD401F52EA7BB5909A47A37A3ED7A87EBC7FA8C703D48A2A0F80966541BA441F9AE50930F160D9C03B7742E7BEF9A427636789BB4DAE10E13FF552367D6A8F897A2BDC02AEC3902D8EB387157456C4367A181222C4837DE8305739F62DF370D6CB19E8BDAD686C049080C045B3C40253756E2073D35845F7F216F2AD3F82F7822F24C1390DAF57CB003D5CB1910B668360E15E2483D8CF0F0EFF239EFEC41FDE5952FB4A8C5CB13A28AD4BC9B684AA9195768D5EED75DDC877AFAD68C4CB0DCC25812E8A8DB3C5602B6EC4FF0BECDA3B2E6FD8B1A64957F207418CCDF31ED2B25FF185A3A1B48F2E7A72DDAF18A3F6C795D048ECB3CFD83E3C823A6A6AB94FEC10232A1231126BC4F72E9BAFBA9A509587D72B3C05C1204D602608BDB4088E15FF4FE87E6CC40207597D578DECB455FA30F0FE78C1A393EE55452B6BF704BD0BDB09B0EDD65C025F1CD3ABAEFD8D3B2995FEC922510DD94BF520C552780A438E61B1850CC00F99D67775EE8E5053D1B20117EBAE042AD833DFC0D8703B8D1EB839D0D2CA19906BD60AC515C93357C1484875CA134C7DCEE07CCB0B2CB2A143BC6965FF224518887B39AB348CCCD82C64B0340B05E83DC951CD419DEA37F5E98AAEBA9E7F4A420CEB34A1C9DA57670DF45D3DD32FEB4192CF0490494E47BA70107CD213E4E36D8650204116AB3FAF000196EF870DD8A5A6860893D60E0F22A6AE6804EC687E3729D45F5323B86E4BC1B6E30F336471D958C23520D44DA5B75453AA412A2685114C8239C7D73B3AE310D20D75BCDB2DC9A23D2BD9B9B27BB41115694FC98A7AD79BB2793A1AD04CE0131AAF8A74D627654B0D0FF74CE320EE98A1ABC5AAE2229D65D95A34EC37605FAC9D353AE0330209C9A4C8752AF1B32751CE01DC9197522A8B2641E9817A5873F6CF678DE8684F386743671B8651EA5EB3F123DAEAABE237A8C10B58BCE7634C7B65CBA61230EAC412B32C4CE326B105FFB3D283270CA5DF72D8F4E36F444DBF4CF050B468016F10BF77F92C24E02879291B6240D534461D5866ED6D2BC525C4F9049B2A1A7DC7DEC180D33FF1F3AE0D8D59B40840DAC21E87E1A896CC9FA14933ECDD82ED6E53FD10E3508466557FD762A642707DF1C14D6274CB101A8BD83F5DD3DA100B5689F4739621234D78BE9CA691834F022369EE6A0300B26E6C8EDFF09D8B5856FCCDCA837F6691E12BE1BAC1A70CE0D29570C5EDEC8808DDDD069DD50A67C758189BCA72568EAFBAD11FAA11B63262684FF1B4E24914B5E75E511CD1065F2CFFA7A392F153392D470F097662C65CE59042ADED66061F36AB84AD192C81228E1BF708ED79E4C6759F9526B4DCA768D674ABDE8C985593F525985989FF2466D954C5A3CBCBFF04FD9C7F227D6D1F044465A10621D1BCD8C37CE3EEF7BE3D7B6EF7C4C105D35E17FE3EE49C2B4900D8C8D431CD394AC3C66B9DC42B69490DB87412FBBF94940FA7DF64074820603BC4D49C022BA0697D7DD25E1A6FD822A8BF1D48053DF1F5AD07A63CCB459492EA946EBF31E3EB7EE96267DA62DB8754CDCCF03A77E335154D9FA8B8A4124196CA96E5E343EFE7C952778F128FD1A2C2B66EF49679E7FCAC002F69F1E884E8761B5AACF11B222A6EFB51DB75AFA498EB4DCED56C3FE0E44D80602D802550AFA5A6108157C6D14C87809706FDDC242D7205A4A3D3D4853EFB68466E4FCF44743A342CF4A8E26B82F7B286947B124D8BECB17BD366EE4520710DF72194F339D21BFF18B155ACC353B2CF249D18D227D2315CC30E7DD6614FE940C23F4458DE305EF37C2BB763594CB6DCBADB65C4349B9F4DE4A43E084E778EDFEC85A384167DCCDF0339A70FE83565B30E71F1B4AFBBF0B4A3BBF19B49447D5E431E90A1DF83678B575401833DDA828D9B14AA20276874373E7177D700806A0242298AD056BEC878CACA1E8A550C326C3DB38C2032E3CEA380A53E09811AAF3C84B92F20FD7122A86A2076178C40F34E07F8EA7914E98FC4223C8A9A4F7FB2C2C9F07F73372AFC727F5AD1565AD25027D4F227CF8A744290A04E350676981E415E172ABF6848357B598DB96C4CC870EDBA8175D88B9F7E859F78ABFE2FEFF5423E8D670A49A3356ACCD0E0F225837C1DAFD050626568999CC11234F6FC6D8DB88CBD4F2F800000000000000000000000000000000000000000000000004080C131A1FA301000000000000000000000000000000000000000000000000000000000000 + +description = high_bits called on the edge case +mlen = 32 +msg = B906000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = A8AE8CDD7601A1C6584A0046AC0CFB3C4E3BC3ABA16E4519B1B4ED50A546DA059987DD058F3A4508EDEF4DD7DE054AFA64AED0DFDC4C9F9558562696A4ABD959E924570037741D10FC9CF0459822B57BD5A84F3AE7539B475C60D95E4E3B2D9376B0A84B4D3031D200E279A3B778B4D43542AF4262C6E5AD39B962918366B0C3EB63B35BD3DA14F084E1F92DA6B229082CCC52D9176694476C10A294B98A890AE0DCE28214AD6D127245DBC778C1E1927579350A3F361DCE464594C3C1DA42BEDB2A081F62FC6C6296BC60718D8DEEAF5A3B6DF4D6CF48ADE47837A95B8013CC3C92E03F94E932EEB4AD008D41D0B8053503FEF97FFA71AFB208DBD0E2981A519493D6DE40C08B458A28FD5BAEF5FC24111657C20F953C36AC3CED9B0CBF3D48EA7AD7C2FE6813975C07F83BF7B7D85EE22C5A9AEF62B328FD4B60833F377ADCFAD8EB6FFF9E8E5034182517928DB6EAD56082D7F9E1DCF31E21ACEE55CBCFC6B180DF3F140677C39299F96DC8101C11CEACB613784F8B75D7FA12EE0B38E7E86159D3B4379543725C305B48081888A44FB084C8C97911BA6C2D58C9184D3EF3ECF262FEAB0C9BD7A7347D3154F0ECEF8C53DE747DA07E913E3F42C54C19E6C876D226DE5E790DEA94684F3031348CC5E66E8E6DB22B154942CF779BEBC8C2A762C60858C13C2CCDC5A6A7AB8BE884E60B3C730BDEE15311BADA52403AE2733CA9E728EE224D919476BAC87DA7AE384DEC6E47FA838A1D40DF75B04FFF35D5820622CD307609036493CE0530F7E2E59225C63703582ABD8F2CB622A325A1155DBA9F7B6474FA57DBCD2BDC526DA41C7FDACBF8772ADA912B95B6FD34FD709A292BB0D92360A6F55383836E967CEE3FD13773E23E015CAAB30E250961496CE64B7EEB3A9120B0ED6BF90529B121F74923948EF1205C95BCA03E98C9642404AEDDA7ACE200D2A7AEBDF854A350EF3C520D745746A76008293EC508B745F159BA493527C55E2ECDF67FDBC3426CED84CC9451AC7D42EA08F5C026A2E28544B1EAA65D12033518CB8F87ADF6CE87A72B9B7B3D3505F2719C47D2670DBC13D76BF61FDAB4B4A58AF5DDBF79CBC449565A4712DF8F10F4D58C2FD0F33F6074A0CBDE6C18BB4D988DA12263F58B5224924C79972ED39D0391D557EFE9974A686A385F80F3B5C9C7E1ED4A1CD79186D24E38A2899AF567886B36EB2A8B4F87A173094863E9E6CA77C99BCFBC93139D5C53272C1B7978DE0908F55BFE90ED18B0612003473AAF252FADFEAAD36DE9F00AB6175D3C8A0D88A1CFABC21D6A70C53DCD3655EF13589C97D88B8B9499FCCF1E0EB70B6FDA164AA039ADD3ACCE52303E1E7EDF17493DD6FFADA104404AEE7097695FC804D41BAE02EF74BC9030FABBFDF269F027741A4B27E4B6D8CE636F605CE467802A286D73AA748468BC8E35B7D3F705AD650CF06BA9C8D2057633ADD59D5D92DF71539AB957AF1850C2A98790D003BBE6A38BB0A21E3521BE83C94F77C57ACB61BEB013BCEC2820A3DDA5F9290965B8DB9565F08507AE9BA11411869294620385D04E5A3015CF08633EE8A876755B6C76A722E557B4E289CA0F675F55363AFF3F2D1013C64E72764122C75A4E527A7C19EA457817725F19B56F7FC05E22BAA9BE29825413ACC19FA55600A95E842A7EF9BD0E7951725B3E396616983E234534305A4E05DEB017C82D14D9D717D11316DC425DE109C4574EE934A9EF4F629394FABE3953E9ED9CD30A5CEC6C2AAF7F2AB02A85A7089CD903226306D30D29775067D2B3D60CDE82A5DDEAF600146B5269908D3AA020344D992BE7E5DC63042755E25F702025733C5F80A9B3C463326052C77FD4B5B97CDC2BDC505D8B30BCB4DB7BA449438FA016509D9005C3A90A65AF42B939CAF7BAB8520040BE9730484F3DB2D32CD144FD45ADBE35D241C1FA3F80C9862939B335FE5509454CFE6836E9B0F2834C12476471DB627E168D6D09C015C59E90C6A7AE21926342365BFF7FD23D45D2D0A3D0277D6DEE0F18A776FE5FA5F14637BBD09C246199EBE1583966CD133DC092FD7777E0476E9F4ED1B5313F9CFF5CC270A5EB79B9F2BAAE0739F24968D553D420F76DB16B8D4414567E17A9C41C3B4E49B8268129AC37CA356F0A5F052510C2F3134CBF3A5B95B1514858CB93AFAA3A36BFBFA9BF51926B790485AC73BA738104ECAD51AEEADB11443829F4AE6B0E6E2484B826E8F77A61EFA1C96B5AA5ADE23C7672872325EA63C4789BD7B612B1C6CDAC1171BF318EBB00CBF28994D1694C810769D8FC07E5FAE3FBAFEE192CEC26C52535758A279A05295EC0AB14BA25B61B1770981D3CBFC7E990E1420D0DBD7922ADC048D48074549EE7EE09E6568238A6B7BE3E8E12A032A5B0CFC9BD43F8A075EA28816626F9CFB1618AE12B360804C9D640CCFF5649BB150A8DDA0B1B643412BAC11ACCD304F6EC5894B3A7D92751B454FD50F1B0F49902169C6CB0065F37F660301612C59C632D7F84CC8955EFD86C7373A9E729857E2E6E4A6A094BF98F0E9FAB159094979557B0F31A4EC8A7C22957D0BF3DD31C058638FBE8F57469E3789D67DDC4F0CFDAE459D54345A603D2CE79C633FFD9369A59FC45E3CC2F2AA5C5E5B7ED3338523EE2C8249D25DEEBFFFEB9359E6D9074BF33DEEBD997559D21F0B664F029E536C5EE56096DA4C7531C9E2E116D109011F86903CDFB4117FADA57A01F178C71D4F9FC0367864769C9ABC75540B920F0136179098F02FC5F808840AD1680981BED9731EE7A2997FCBBD8E80B00A8D85526898EDBD6DBD60C478090B49AE0863F961654D3E7BA10F03A94CB4973EDF27BE2085085F799A5D5007D256EB0987A52ADEC876CD0D036622FBB0B53DE0ECBFAC30B1C4884A4248FE1340B6123519722CBCCD712136642AF9C13507A003DEDC647BE782E1766256C6FF9CCBF487919827DF78A87D337049A7856618025A464FBFAC986434B1AE21C1D0A7382E7E0781A457E4E0241CDD410706F4713D15F6D61929C3A519CE05524272C0A333A39CF6F437F1BE0C86E0B531BA6AEFA5BFE1C12B95C5E8F5CF62649B30D99EEB2CFEFF4DA6728C1EA3454A3FD5A63C2EDAAD7C7F7EF0526E085071630AA4674315917DF3F0C1B94E19289C76ACDE2012A060259793574EFF3534DAA0966F7B33C616ECF7CEF24EFF84A207085C1DFCCABF6D236B8D3888FB647B5DED9683CD8276807AFA3E5E88AA5EB5A5CEFA026EB7B8F6D7457BBC79E72DE4CD4D92A51A38127376F01D2C386D2D67FE3B0D837C69D4D7E7F7F7088C0136C6CD68440F906E0B34F86392A9C1217AE98DE0373F9519DF555BAC28411939FEFFBD5B6DEA5E8FB0F9F87FC2F9678F520533DD4C1EB1B0981E540E355BA4EBD489A2672FF10D2380FBD956CFAF3BF315583F11313A3E34BF4156D7525788B7B7A8D17D14F975A695A22745DAB8601FAC6B3CE7F4BEC9E298858E702D136D7EF683DDB367BD9DCE2F54D5C54D4F160DA32FE78BE2DCE9FB7BCE3D079CCE887399DB28C759152C16CD112B1C67A2020D46589D0879EFF71E1F60C05077B52E4A752A03238E697B5829826C5C7E5F67B14885654266325C2D08A51C061EF88ED081A5636FEBB510A8DC56319221AD23107DEEE4BE080EE9C39EE3DE0ADF59157DFA36E403FE55BCEBC4C4011A3D638C078A716D11D75ED96E860F39C30D4929DCA6C7C61EF5592AD0AB218E54EC0D617F4F1FE0CC35C70FC08BC95D758F8117D02D3C57DBDE6B3C78DC5F2644544D059699FB78F808CCA390F0B65E9C5D3FEBF6BC83224CCE78F602F2D289605C1F9513358C5188A649FBBE3744E3E27A40F59C0184EBF4B7FCDCE3978B25D333706ACEECB07A4A57A0E6536276505949FAC58FE1534DB31B2E68C327FD30BA76B4CB8522284BB9010155F45FAC65B544BF28AA6552CE1AD878C6703054F499288627CC2FD5B2D7F62DDD12FCBB9064A8CD8B2E52D1B11C33BBEE9E31570C53794262D974CB03BCB05A6DA95D90467A6378271D3FE59CCFC5F0607E69C8A2DD542147C7449A82AC8887DE89C0C6683D74C76023782FC40BFEB565C8B554821CB27FC528893EC77BF4CEAF128CC6888E54340DF30C2439EDE07BA9ECD30AD0AE498AF1BC71480FB8BF8DCD1DC79BAAE421D17790F5D5331744E555E7A6FC0AD02CF5D6680318E1439FF535CA6B26DB71BB57B66116F5C8EBED986F209296E474AEAEF97CA694C0FF22D97D022C573D7274A20FE61464C994EEB478047BA7194F55BF7A98614D1FE6C668076FF36181EF2BD1447FAB111BD439F658A982269532D51B677D87A7B21B6AD43445AC367566E46B423DBD531514AAE2AE399985461552630037358278060EEA1550C1629512314E8115B2C9218078DFBA77D552541F0E2A84D1164A4ECAEF7CE265941376C2755AD08254545E1D067D03FCE227A43C3898A525699B1DED34BC0125E9208A16ACEF7F24676AC1CBD506D8978990D6CB8BC2E4A2AD024046D2049C587BE4C8838A8EA95A0B09D7C49CFDD6DB6EFE5B79BFFB9D0029160A6ED5C6EBED0FE13C385E90E91C235D0515374001DB3158882D4889729872CEDFBDC384A6DA8E02B4306454685B8BF08212E73A7C1FD0C0F7ECAF8122187A8E20000000000000000000000000000000000000000000000000005070D14191EB906000000000000000000000000000000000000000000000000000000000000 + +description = low_bits called on the edge case +mlen = 32 +msg = DB00000000000000000000000000000000000000000000000000000000000000 +pk = 5A04D37A8C83D373BA07DA5CF96806002E3635AD8ADD42CE6EE9902DFC9A1F27AF2B332E1A44672F757802793A43B7E9F1927FDF4B89B7A4AD975ECF8BDAEA48583CAFBAF30C7EE6F668C225DDC25BA1D394D920F435173EA8453BC83BAC373E3B6429F48A01C7DEFFC3EE5A986648A40DFCB31662F46F3A07D22CE9D486A0BE0E822C1C75EA58965B9167EE08C9E6B07E80BE89B257BE37A57D5385A8BBF5E4439BF3AA80C17874A9F37D7A62EB0BAEEE9893BE6E0FC223C31834BAEBEDBD9611225D25542D78FB659B6F41FF3182D94B3E471F8C837F82A42FCAB82AB6254A67632EDF81F6FEB720DBCDAF92C92A05F68DB7FD074349CC54B84865326E3DC45E40645C95B41908AA66D38DAFDBC4EC559CF0F86C5BFE7C2A84E8E56AC5BF97E88456F7995D77C8D114120A9C7DCD3758C182F8382F8F0AB8CABD451F71C72DAF985EA2F64D85B561DD294C2F96ABD8F351F2821FA920EBC8FE576AA4A9253CC23CE45E3FB4695F181DDEAA2AD12E96FB0C658E12F12CBBB4C244EFE0B40B09C0C8DFFDAFF6F47A8C1F4DDCDF4C5E62EB68BDF66A63EFF871A31FB1FE3CC67DB129DCC8DAEED2AD3E80EF54E600BF7494752D890E7183FE7F22F9DDD790D25A46621820B79203D584AEC35AD52DC7FAD76A9A7C69B276B7FC66AC7B873DB7BEB6D1C2F6BC8DDF11B9CAB1B8E8B321ECD33BC4FA548F99CF116379AD7A7B20672F2E7CB6432CC2D792221DDB59EF4F62BDACE3BF3269888085F703CF0358235D22F3D2F5B19EBBB5692A39282AEFAE8015E39425678F982EB31755804D4F1E698491FF7CC94157055A2276F8A9576022CBFA45982214F356DC4B5EB3741E12C3F6361D9F8334F175503DEB9C03EB40C6DB999056538C750C99A2F55D39CFD104F5C9E77C462B127007E5E24775726A9F7C841838EEDE9F90F62E35A68DAB88147448581BF09CDCF927AFB10C054C56F4CEBC4B18A4E01427E0427D1525A3857D969C5823920A1B56436E8BB484D4F0E96E17F71DB9DA6D1317DD6A6029C4B6ED21FBEF7552581D56D786FACDFF8F5A225C7593CDC9BB42C722F47ECDE0967DC0A8F1A5C99CE711F8399F7A45489A80E55B982CAAAC1E2728B84674EB27C76C2F0B67BFD4E1C88DBB26E090B9F3E19954D7B32CC33BD331996DFAC4187D76B75AE71E359C93BC1A848943EE06C933F757AFBC1D68D63C8E1DDAAF100069F6160ED97B3AB56A36985A45AE43FF8504E2720EA0D203766A63DDE7D9FB45E7854657F7A30705BB09F9591AAA991AE8DF24C31463C83DD00D02CE3493B92E3F4595BB0765FAC637A5132F83E29D50AEB53B2EC911D0562C9FF4972342EED56E85F06E7DDABC08B4EFF380F96B56CB09731AC82398E1DF085DEB8083B61BB52A8D473417C1D3AE2BE90DE8435A062783477302D2FA8ED939DBEE525FB5804DE60AD4ABFDF4D02AD41453536CAC2C9D5BDC3786628D3FE45D42FDEA409443DF330E5FD0F4858B6CDA8C0A63D7B1217E5DC771BDA256A823BB30720E3DCF2252959489A638089BB89AA24D688143A6B1A76172E7F0D5DBCA3D033A369CC2AF5F3CE0AC4DDF2255A80C23E2D467A96AD105DE238CD3AE03CE1151AAE6888F3DC54FE3DC07307A05ED4B0844363F0AF2168F64D7FEAE7059EE1DCF5A10098F402F401CDAD049FC4A81E1C9527C973BF32C8B7721D1B88F87297DA77395DEBDE40F1AE549EB56B2CF6AC15A7B2399AB5D96692A82239CD5A2D6D469A64B3A3154B2AE81E9A42189EFB498EE86441DD039E38AC1204A286CD6D08A2218EA2E77E6379B40B81BDC19489A828905701B5E19D2AD82B7E885310007161A86A21E43FC70012B5F2C684A2CF546D9F623E593FAAB383CBF5879A871802AE4C9D4879BB28C5785B2D6CD3A83C8600BEFCE72C187D48F5A879D9D9E57B3C55916B097F04FFCA9AEF8E3E4574BFC7DB6A505021A800FD79A856550978A899DAB650389F55C0654641890D0DEA6C8EC177216CEDBD29395A126A66C376D432D20D0BD00B1D7C1091F85AF2DAB7D4E60204BEACC90A3D523B0BE21FEFA5F4E892130379C2F947889A28A2EB2DC8CC2B7D0090D41DB53E9279B54E1243CE17089F946D112A5FFE1CE7DBCD4E849B6B7BCE239B256005D46F7F1A2E2AF1A048CF4218881E015B6CF4C7F6440F5FC61197F79749DA80DC9CA03E2BB23AFBE8E3656036CEA31FF18FF07368A4DF0B053C2D4BBB3B929BBF42CAE74C88004B93493A42AE204B156FBF785EFF086B5FAD30570E88DCDED140F016CE113F4C8907CCC0387F3EB4958953D8CACEBF890666F3CB312A2E87555D93132FA88C1FB685C96B4A45ECBD3D274909CCB1F5BDD2D392A733DE7CF1C87C3A8EA4CE905141116B2037C7F5ADB387CF618DEED6AD796711CEADA04FF33D7930186582756D7B1C418EF02AE7399B431B38198C131B7A747407E2D4F08DC19F8A863E808AD6078CAEE2C8A1554D0F582ECCF4BA0AE43AFEB9CC62E2A5909CA81BA28ECE723E141A7AE3317AFACB3D0B61D9F199B05CFDA42B750834C5F57098BE4476FE2BB690481E7CF509E5E94D929B256C6DF712A5125A12DDDDB68E9B11DC0523CFEFE2FC431185B96C5DDCCD8EBEF1361E2E01D812DA62781E29C934EB89D59EC45ADCD208BA6CC4735C59711452DE1F1869861E7C10F626BA3B0872E7024B370EAC3373223129DC44546BA9354D094BF745BB0E3ECEA28A26CF1D3750F23276CD4954A08C05464EAED3E5610E5B4E4CB9380 +valid = true +smlen = 3341 +sm = 76432E6AB59EAC46A20DCA4E4E47E611229522C99E1CE6FC194463AE709D93AB730C8140EF2672FA15C236DA36C2C60E0464C076BBFF7AE1AE2D720AD13905F269286EC74E8267DCD7A88FF4F04C3AE636481A55C781839EA1AC36062F031D137165E996FF75D4C065A98BB8EB707BD84545CEEBE4DA24D8A2EFE41662335A474531FFB8C14238DF52B18557836A0EAB930EF7DF9E64EF74BD9648BC42416BA401A521518D564C52AF2D92CD0048D2228FF9157405F3D163F951A63E51525378C55A23AF9F2CB52609EA6FB83DE7538A40CC14374CE9CCCBE760DE69CE8F9D86F83B74DADF11B521210E13DD5AA12CD85B1D77E7EF38B25151C2D8009EFD358278FE5C71AD2F2CFD8AD6A6EBF03E43A03897C269F229193E5C36E3B897326F9009F72B0DA4C727C8E3503195BD1C82E783A19B0F81143BE7BAF57D92D290332CBA51E4B3A4AF66440D1D6939B02C3903667A7E0A2FB50BBE23164A31C3AD4B4C9F2402AEB00D60D16FF32D57667B3FB681205A422576F01D75D5218B560222296247647D060366C68417F2C388A8B004102DFF8D13AE83FD34B1ECDD81C2F5AD807A3492D75B397AF2E081DFCBBC3E8C8EFF3BE20DD7F482D2CC52492F8E7083C132A5C0FD4D4635362EF960E48D6E35EFA51076B6EA32DD63179800F505E8E47099A3B861E537333950434273BD8383D0164A2C4AAA911E7E8CD0351D2E6BE1E2980387B67081BFFDB76ED80AE821E05454ABDB12758B3DE37BAFA765EE5AB16648F4DA5C2CB7A489212A743D37BAFA06F58ED6A6BC6F20E6B0E8A1FA9AD07AA56548F93E23858619E67C83BF4DCA2EC6516EEC1C9E115AA34220C59255B3AE1D5B4F8E091C17FA55275FBC8230D217330B67473738B3362DE17BAEB131F7D4A9832443AEA256B4A5E3889830ABFB4F324E22698E827733AEEB16E34A33B0023B9551E3B81DD78BCCBD2468A13CAD54918D10EA69029C9FFD797E968253229D6EB410FF827A9D2CD6BF152E5EACFEBA68E1D778B1E89F6B71FD040AC712F36C13D70969D025FAAB59338983EDB26116D0561E066BDF5C7AAF24EAB47A68D15EC19ED074F3D4E9026DCC8E33DC6D46010955E9BE675F2B863AF88ECF29E4C7AD7FF639E04DA36EA15E8FDAABACB4F69967C12C36B33AEFCE2D9F3608531545D210BBBAB46EA27DBB3A9E80CC844A18B1D1D9AC101EC131DC54143DC081B988A482BB46A84FBDD791E742E4B38088E8538AB8F2544D8F9A5F4F9C0EB83D37F856C4CBE64688447C7F052EE375B3EDFAB105A464D937923166833F3EEBD302E30FD472343E75B661389A049E497DF2D7150B9681DDD66D87A276A1A43A18EDB7EA77D2F2EB23A722A4FAE1A68FA2363F29B2D67381E7B70D359DC86A06EF2BD9FD0E791440906062E9AD715EE41ABEE8262EAB49C3B7F9B11826684F735BDDB21C3DCB681B12223AB13D38CB230E0CCEB4D23E6AF1FB184270E90AA00B311F8C2452688B8734C8D62C22AE08D8592479E8EAFF64B2AF23FD68F88576A66BE58E085BBB85B022A5C6F460444C0287E7D25F4480C429EE9E5AA5D455743B38F91CA4445196672E360DC894571F978D29F72B3634682A5263B13FC4CEB9A1BCD71520973F8DF457D61ABF1FAEC612AD6C86305B65D9CBB7BCE5035B8F644B716313F684EDDC6909893DC958813E6E3341DDA8A332C364A97BCC9B6472E6B9CC570716ECB625F4E8994DA9B1F6DEE8561CA4D2F6C691703022EAE2235DAD9D5C5CEDEA751974E8D602841E71AD1DF6ABC92F4F0337BF7237A65A17E010162C46DEADE485A04F46214FE7BEF32DB3C311661E43C0C2E9EDD963908A1F8C1F6DCDFA45CC100DA0DBB89B30D70E801D0688F377F6E908829DEFB4A17D78717EAF2E2D5744F11586BDE49FB4C8EE40F36611DA3C97BBC5CB69A3C94671122BA097BB01572CB883A6F9180C3977875A1A5581DBFC57851A5ECE82E40E297679433D2A7CF18BAB87D7F05E04C832299FD2A650BCC6BFE288DB08D12653CADF12F768EF212C63C95714A4641A12962CCA3CAD694032D531307715F64AC64D259F835E316688965529E513E56677FC4855B8C4C9542795204A08C58DD0CD741655446865CC14A7181DFCA296E47096729665A2CC9B340A26EAE144197BB69B43E3C062E5408B8A15C6C7ED9E08A9D5A58B6A1CBDF8F7888AFD4DDB9110848EAE2A741D0BC3D745DF8787FAE2521124F3211C34B8EBBA39F2034A9E1341DB3C49FBEABACF949D3BBE4A89AE66B2CBF10F883FCF5783E419D947CFCEB12D33619DB27A970FFA82D368163A8D9DB2A9C40F38DD69AE09D21E842794349040A6471D884D524EB009C6E182C36449F7B609B543551F6C3196F1F7CD4F311C277B5C6A1A99979607B246E0937D066DC6014EAE9CC6232EAC1426E954F70E881869E80D435BCFEE437405FB528E179A68E28336085C9CADED83B771A39BE93E660B4EF5066FF8A5EA8DF0C2FCE41A2FBD7A9EA0ABFFD5A3832F1BA3CB114F975630DE4B8583275F48FE7EE4EC19E84B23FC41FB4542AE0D569F417044216A61A3F7A5F7E340A028D7A035743CF71F7074A1A4B51DA6748FC290F29BD42969DCAB0282B6AB6711539C2D55B93A575AB062CFEF43027C82DD57866A0133DB184849C480BF014470BB72DF543BEDD1E5F80573929A7F101C1065090FDE89EA5CB81C0CC2937493CB0028C4C57D74E141DE27662DC744E15F6EC98796F01EEC26209945533D789CEE8F1126AA430AFED7156DDCD0501C632B1F83837D157C3EEFBC55A64D1E0BA4EEBF25F157AD169A438D979F5D81C7C37F1312ACBFFFBCC267C084E098737E172026B4BFBB53D7C5F515B3D7005A120FBA41EEC124F22394EE0C735651E4EC5749A16847DE77312B07399BCFF4B3D1C5732AD0E9B88AE5BDEC072EF63B0E2EFB30309DF310171E24A8242309100A173E62C53ACB781F87831AC589DE9E07CB461C5F455DEDEB8084C39739DD33BF34CE6E0AD134B53351E9F14E3343EB1D7925EE463ED8D66AB2E45B7BFD6429B4A2CCFC868F78B603F4413E2EC432B299CBA4B1F017704A41AC31F7027B0628A3C9C7DC43146690DA24D7C51218F10F72465C176F84EEE1F0364163A31EB761E33273EC07C806DE809656AE57F86EDE4B82845C3ED6AD075478EC179B3738A329D9627410127BF5CF193BE7E021131518534B2813DD25CC7784B3A203139BA232C9EFC1DD538563C970F2DC6141CFFFC1E880CBF3BBF81B21B948F160A40CFCC83F71F652DF1BF23E14943ED3346DC97441730E162BA39F3BAA187206E22A7888CC5315EBC08D08B188CDCB76CDC24CAD462303A0B0AD1CFFA6ABD013B1FCE7FD78A6272B3A8E79EB0D171B4B48D63722C7524D0A367D60793259B53FF34EF2F295EF1728C57B1DADABD44272C94DA9E2F8DDC8EDB6A8148BC5A5BD4252CCE3742C8D635D4A590682D7EB92D52836D55D8B5B985A7E0E9F941598436F8470B39E84795853A3DACCF65B1ECA82C8EB92FF5035932E4BE8D34B1A441C47FC0FA515A3AE9DF6782A041C751AF1E825CC1551EAE4B98BDF47293A485F7DFE59EB639D23B5D0DEB0E19CF832A0A7659CEC0FD7AD6DAD928D762E2F5AB572AF3F67EF51667F8503DC1FD8D73C70CEB08FA184EB7601242BE1A7BD7813276F9B4E5F7A3180F6A773F1ECBC48BC4D917F417734601C05C9130C4169BB8E7EBAC241F359BB63104DC97E2F4D11A1666E5BD6FE1C267EDDE2E1B4DE17A5123DEFDA1DC62231B7EF65352D8B319B9CF1277CC46B20064232AB378FF3D908446A61AD6223D9CBA2D1C770EA8A8580725E6E945A04365729DA77F39397A398725985388AD6BBBBFE28CB756AAA8AFCEF1CBA634876187B497671A8F79180E37EC94751887C33814B33217FFD1A84D19E05314DAA554581CA88260CF23278C0C1459B3D5308159A5349679959E06CBE727D26B399A37247BC6BA526531D10853C62703EDB910CD4F1CA64BF7842A907AA1A00B3C78EA696A342D70019C6A32B81A278E6296DA3F7111E5ABC1E982DE9CAAFD5CB65E690DC33E1EDA512C29824ED0F085CC7F8CBDC012E5D9E7988A281ED3F8BF87C8CDD643E6B5E1F766983417B38B9B421A7C7193B9F5FF4FF54D71818CDB1A5407BE5244B7E90CFC9E95262873DC6E8F69DD05FA0C61DA32940B06A6999284A1348C8E54BD7A87A4D318E42E2B38F89A5F9BFCDE2185C438BBCBA42115CB986E2066CBC68B901FBE8E1CFB2E96B3DF0563A1B121E8B1BDAE6F49333ED55CEAD1A27C23C23382EA0FE81856599DF39265BD68284E402E3C3CEF38B50C7580F1DCE8EEB8B93E9E41AE8C23DFAE117973C39F45EC30674485445C232B13ACB7960016503C5D28F338CBB5F167988EB2F0BC8228F607D9130A5B8A4AF4114E203894BF0A522054BC8E3E40E4898E8AEF82598C49227B6B992988450AA6BD7A72FAD964F27D1C75009C6F8B1B1AB09BD03CA83AFC0D63ED18CE114692EC801839DE1D60BBE145DEE09EB4A452744F9AEE34DD7431B9692A8F1FFC57CFB9ED48000194931ADCBC974E01F685F78523C7B1AA7F3BF990EC83226B3C8A62B182037476B77A5ECFA1F293591A1C2FE01424855BCD0EEF3F70B0D24468E95A4CAD00889969FEE2433445889AAD300000000000000000009101922272EDB00000000000000000000000000000000000000000000000000000000000000 + +description = rej_ntt_poly (sample_uniform) requires 5 SHAKE blocks +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = D83F3FE5BFD9895F3FCA5D0B6AC999618C311772D3A9DD13D5F1DCEAE0F8DFC7ECCA61B55ACA5B59F6A6903299E30AF3000A59A1D0C07EF37B56612AB56D886111FD3B846EBD40093F592FAE3D7C68323001324416D0B484C39D8D86E8CB60F61BD4476B3A9B29CCA23AEAA9376F22A4D1C2CEDAF64EB061C5F7780141F1AFD18E9FC0363D617048CF56DE2EA77E73BA5E433874CFEDADA42C2F410B84E20F48A7A09EFF493365BD997EACFFA795796376B9ABFB8FC3FAE21A2CDA94B4E4684EFC57B5F589D43A6A34615ADAB3CCE5973F230351DA3650C20182095452EEC5319E702C49D3426D9852EB9FC2817E3A55445C11B2B1A632CFBA5C2012A3EF691A4998C1CA23FD4A5BF4B75791E2DB6C067BAE0BC77764E227489AE0F1FE857756013BC8EBC5245C78C58E411E63A433AC20FCD89A442D2891E6A3040BC65136A508152DC0B82EBE0E44975C366FC9157F6B8CAA84350A7951F5D2A4677D647D17B9359D4566CD8FC5B7AB55135A39CABA73A79063BF1684915E64AFEC7E56942A8B342061FD2CA7F36B7E0972A88EC6EFC24DBE5C0B3918183663F769A9DE66C88511E013DECB1711542CE17A23912268CBC81821E95505EB2AC4E6F71C679D46EA423CD5B43513DA45FCC36BE2A084071AADD7608AA79AD7E1E3B6DC42BB689196E477953390089D4524DF56489D1B6E7C8FAB35C411A3B61204F805E80D55A37754E4CBEA7E25A73AFFFB51B0DD1A62EEC109E01E90EA00DDB76612EC1BB35CD6FC86D788DB8370E0FAB652750E53FAB5A488C87DA2533D96E8106B1EB1702BEC29387DEA33EAF4B224C7C2EBD938D88DF9946CB0EA1FEBC56B6C95A334F2F5A85D5B6BE24DDEFB149372B24311BD49CA08C509DA8EA75924A2BA12B41507AE853B63698161BFAA8598C4F5B15465C8BAF8A2BD67D78CA6A7F9A0ECE321785F29DC8F2FBA22DF727535E9D07D393C71899F72F3502EBA8C024AE578DF3F89A8DBD30DD4F989CBAC63F75935FF92659DC6822025333E08DE49B1FAACA128E22CCF992CAD4334E71BD01A0361E7832AE0CB8AEBDEFBED6343160C2F0E5EF75B388B8679C791F2F777AA146A675356FD90D88755CE0BDCE67E4D54AC57BA627C8C9E2C5A23B9FA9865D743804D852283CDE3E3FDF8E246BA0EE5FD1D7C9769BCFA3EE123E288193186E6CFB3ADB76614001D3DFF5F7168D8A16FA189D347614C0296D361BAECAE268F19A3AE5824FF8C6D65453A082DA30C9167A61930C70934484FFE5AEAE169EA3B32E5BD36AF63300E389FFDCCE5E7AC62DF06A1BF6D3AD01793F8D8E40963E91003861C40B90C7167863881B34E8916565A1BB02E622B54EA6D04FBECB2EA23320A8CDF1052E32B05F23AACAE527214860DDD6BE63D34B0A81915A280B8428807C9E36C5BD1BB79D9B9A5B658D04ECD677EFA9C987F4977F013162F1F8FE2DDF2A331FB767CF8B944C0523054EF264269C12EAB37E56D1A814CF6ECB4367DA3B69BFA07C6D04FD36FB6B007E33A8FACCC5085B652D0AF902DF2D4116A3CAA826014FB80C9405519CE80A4C03DC10F994DE92E43E59E4AC6E9815472492CEAA358927A14B2E083AA70BA58802C790C9911166B7DC1ED94318B4395D0B1ED125CDC83DFCAAC5F30EB90B0275F55498398DC30C755B79DB3E2E913E87E621EFEE191DA71CEDE227839DDC565A69E2467EF0CE03A3E2EBE625B53DB0E3C0C7BCDD37A322243EC39DCB3E6CA0D79644D974AE226978DBE1457BB4AE87B6B160E05474BADC09B7DAC93CC089565C10927BAEE18CE9320C9817A1FF89B3D39B4415E9820012C920097C3D1D3649BAE3528930FAC8E5AEFCCE444C04A9FC923557391B6DF0A74BF8CFCAF3AE1F54B1E5031ED928DC31DEC5956C45057FDF5F231CE1087F8B6301E387F21966F44B69AE9473888B6A6A19C99B2420C957DD9D14BBD53EC2F3B13D519776C39112C3586FD1FB87FCE63B9DDBEF1D4E0B37FF8FC19960EDDFD0C747B07AE7D8FF1CE85FDFD68FE6716774EE1E981D65255C9B7BE3680BE3D512736870C4C9C1F2D4FFA0553BD1AB66F15BE16D360EE3176AF9E00FD0D03E6925D22FD02D245EB89C3DF68EB50E8B14B690C5DC818F42656E4594156122E91A9D30A91D333E0E12FBDB4F1EE89EE80531310F9D5CD5A2C38B9AA7CA0FE71CA28FB8930BD9521DCBB5365D1038E8B784C53B0D1A95E679A1AE748F2FA6626EC1A594B5B523626707469556B50EBADA8B9C3367227A287A3125C8ED8F1960B81E6C23B42D6E8E863FE4F01F469954408746F86845006CBCCD7BAEF8E1F05C0F55D4ECA56F27CDDC28E370669CEF9AFB62BEA1290F46FA71BB3734F7128BFA959D9521C8B8BBEDC2D451828BB98A2E4F2D4FF0AEF0CE0AE7E75E00A8DE69802F496ADDC8A7CD64B47D8B2210B611F2271DB3B3056D0295980BF68447DAED63EE6BD70DF86CA6D5394B530F9BDDE060DD4FD33DEA9A98E0BEF653DBB6D5F3AD9337A84802E114A44DA3BED5873E143629D46C2D5C3ABEE1A385245AD6EFDD2F260E976C5EF4640252F1CFD5B8DBB5504632CB732701A33D03CE2BA810D8935C2A140A4F9E2186463B7E65C671C4FCEC23D426AFB2B12B624644A59ACF3548FAC2BD812E9E054472DCCD560BC334D05A4BF2B8BB4F6B5B79F3EA095D8A0E3A6A0BE76CFB184A84073302BE28655FCA4B5359F968AA55A6FE5814AC0176CE5C8FB93DE69AB61CB85489C69AC3734C4A3994779CA35E26ECC009018 +valid = true +smlen = 3320 +sm = 16B336256C51560D99C97D15FF467360F5F563FB555932F56351ACD1E53906F1C05C87F8544A821BCB05D0E3952A84C4D9DE460BECDC5EF5138C9729E905A3FD4117D32CB0957C5BAD8E84ED7C4170BE74D63E9B8D813C4EF7F534C5605A5E4F6BA4E06F6D800AF82809016EAE3E6FD4BEEF0F045304A4C17222BE7F8C5E71A294ED8485C956865896457119A39BA4ABC44BDB4D019493147D0B5E619BFE0A5F4ED1938E48E71B88EC8FBF267D1EA5DC8F63C67D98A1EBE9FE4757195C04A8202CF012133181892A4221CDAF79BCF240D005E80E8C68DA8F0FDFAF8754F21EBC42D2A5900CFF1CED847EE80E875C27100BF230F613B0758C3E4CCAE5064111E71F0C13447A25FFCA32669E53CCFA855B997236887F6AEFA3BAA2FE264686B879D1389D72C5967030D99915A9915182F97AC2375C93E5DAFAE6575DDDC16908BD2BC865891D85E70FA998BDAA18246F73DB0D69CA58BA813E33C90A3E6B2A2C2F8C97166C9B474C60FAB1F3C7841B96C2AF1349A37C443FD86291FACB657A049E175A69443BB3662E252213A868E8241188D8941FD524EF6017633D2E3B47C9A1AC1BCB119722F54C514E62DE40B5F2DB38A1281E220A14E31E46442D31C71489DF94F02811E53806C5EF65377433222B8510FB7E4F53AD31CBA34456779563028DD1FE7EF3752F0121EFBBCD28DCF09F045CACFFA2F09F343CD4184820DFCFA3E0746AA7CA2DEFD2BC165DEA6E3A07AF3B4A8E9BA1C18C32B44EC37069D65013AA2A88AFA691DAD1A07EA87FDF8C7B187FE9572EAE4F296BAC40F3F729EC4C9EA4378AAA60B70F4FEBC3FF3A7561E2E22A7B8A23770AF7BCA50540236419762F1F42D9CBA0B1285E83809EA02C4F0F9AF086D506967168653B1A54754B629D769479EEEF76EB8171B127B724040F0E7BB815577A4998FF01662D2968DDEE9CAAD22212C3196F60D9212B5E1FD92F0367D5780D3C42C92332E305B6E15BDB3EED70643A26892BA2BA9C6E575A77EA82EEF3F425DFB971C7F6E74520889A1869CFE4DDDF2819445E8BAF658668A9E0D3C65F263C208C4442D38E644F8CA193C5F463C4DCC2217DC337D37A0FFB61688A2C67A2223E41D24D07CA4984C35C5B33CF142F443E9A0EE0F631173399D714D41131E84F9B0C9BE290DAC2CE4716843CBCCDD3851CDE789E8D03A7133F08B6234DD78F63E17D29A7B93E992EC7C80D6BEF2E7EFACEACEA917FFE1B23B8A37F438CF97C42551CA8E37B1831EEFD5F4FA495D934AD6B7DC249BE12BAF8010F55552C87E04C79762E717A8647C427E9A9D41200438187475B8C51A990B1D268FBD1CB741059622BBE0B74D1C40C539D1719232A31023E7A0AF41034A64F65F96347F7BD9B1501812FB48BC771B72DD3487485765BF4A769B8CEDB355F425F49FB27DA1375B5183196ACA9009E4E638A0C5A07E424D2A9A6D828706DE3E36D5C579704E30D3980511C3F95786FD6CDDE178BD9B246929BAB9BB6E55176F83A25252D4DC97E70239A24EDE49A93CBBA3EF31A637DE8F254AB965C6D8824B31F28A9FC4C32BECCDE5299ECF43F488E9B8E037B848491DB03F6DEDA7BE882A5669DCD87B26D57856EA3F2D3BED6D5394B7A06C498FE8568F62ACBF63197D21D1059B55516D08496608CCD6B0CAC9A49B2A9B9B7436C1BD7F0673C2D66EA6CC6D20BDD975CAD6D32C11436333454C7CBC67A9EFF002B29F3B5AC34255FE7351888A5872862CC7F745AB7116BCDAB0D76BCD187D4318B65EE3044D3E342B88BF231838B93B3328DC787B3340FFF90931C392A1283F897F9A9091DF52B7CD2AE885118D4FAD2D595A76555071DA39436675AD6C083E9160B3A964A6B020F65AEE5A2CB3BE2453C0157904E7283802F243C5CB40943ED48A91B48FED455648C576EF7AD7FF6DF274723899B2977E13BF8E803FAECF2EA7FB78F63A78975512C962E375BD6AA37BD0132B0A9232E35743620D1785A55BDF36620888B2A578141E29E197735BF388491FC40DA63F423CCDF76E2947B53D975975840257FF2CB2B5075803305954941F49C7DAC218E081FE269DC2A5506F4CC2A751BBA6070D9EE0F8A801A90895AD3C1EB756475BCC3C6E0DF907C49B4A3494DBB7066744EF693A5EAB0EDFD00BF41B90002713F08B35CEAE0B19338D604DD47E55527FDD815408A20C575AC6388240E0F9B3FDD66C9E100E512FF6F73E1285C4DDA646F6E667C1E358F166DE2688E64E38FE47F0D44410A5CD284ADADDC6B444A08BB44A3FA3DFDDAB4245D99AE058F019362EB5E89F56B41DB5D885F038A31539545863809D094CD15FD23B77BB5C652D54ED422790532FAD71FF5AFD2EC1BE5F0BB1456F09FD9B37D9DA01FB9C103DBB277AED288EB4B5B28A2820EC7B717CEBC4D9F0EEBE5FFBFCBF722B0FAC299C4EC37C03EB1A066147A18AA47752F21877111F5DA3EA36B8D4A11D06126E90E59535B3A760D882BD694E5CF9E0DCA9B73AB6984F50472782F9B105BB3A7FA7AA7B697F831D3A9A94ABCEF8F7B6295EE73A873D67A930B4B830D770AF621E2DB52C5AC7DD221C8CE33C2F2D5147AE5EF89EE1F370A90DF218F69D3937ED20F2AC484D79CB5FB22C5C1BD477FB005A05414865AD6430233997053F1C4AAF7182AF075D196058C97F871CF7951585F90360504841AEBF6DA4BA1E721AA97F681989704F04E13B1843FA2678254C536844A0CAC2391D229F2C1382819F4E15CEF9655C1C667F45449CC7D3BDBA48C86E112E9BE49C2CF45B65934304883EED0C97A0ED53E660D7019DCFD94773D4209058D8E131B0E8DD0DF041A5AF4DCB7FFA810757EA253204510C69D08D4FD77FCD971D4D9C5E0FEB00B8672F525C13DCAD6734B40B98893A74836DBDDFD401C9BFE873DA4D1ACF4EB1028CBED94D48079B46643652AF0A877091D28CDE82585602B6003B47F19671D42BE1660F0CFAA289268CF1300C2273038831C57BCBAA2C88934484565CD2952AFB8214F76BC911D0C942D4B260293630BE3C0C44358D16AFC38BBCEA3AD073179487BB17D0AF4EE8884F30BF7AC5F7A8B469B7A82FD83C68A5531D2987338B2D760DC6718997DFB433CCBEECAD89EF7B79690CDFF544E93572468E0B044221304077C8D506DCED5FD7A3AB0449771ED71CD5790DFC43B1BBBF22A519583BCBF5B4E836D6A59870D25ABBE4BF8AE2A7723BBB98E3C763A9DFF1809D0AF5EA183EB1C983F06FC95735A64390876394ED3A98CA2DC5D4D6BC4F5004C7A4BACEAD5DAE0ADF46139FCC77E7C3D74B000E08BA87AF82F1669A8CC41855430E1C3A1B42ED1790D127D0861058BDD401F59BD80836E81CB019A923BB4DBEAE1CE5D8C9BDDA06CA80A407CF057448618332C75F2E61050C4D9E20B34EF1BB5D00008D152D77F220AE4ED705973E704A20C170BD9CC1F00D2C7B09A6B00A010BC987E0743E2F3005C7A802B73F76D1831E0FDC39D7F5B881B551116BED6FA9B7878D1E34CD9BCEF3E7F75C448EAEF8520EE560846636009AA7C6352D3C9BF4471DA268E00C9BD08D620A172E96CDF2D286D0433DB1E00FCA409DF3355ED471053A4B061E07D7CEBD0967C2840E3EE35AE99948F4AB0FC4875E8FDB847F6447E429D1261A961D0F54A6466BD1751313EEDA7C7F1EB197C31E3EA96D207DCB30AFA834A7923E9D482B7DA24B2FAD6F64908301335FEB45F68B4257E08AB4B51297842661818EB1532DBD1FA152177118A119EBB89FF9693506C7EA51392A009745CBC5BEB359BF6067958EC19A59F1CCF114DD379DC363663E284B182C7BEFFA1270330C009377C764D4C72A6A8C739430FAA1AD5E6315C61BDFD1FD573AFAAFF096BAC889C8195C07FD7F9203142C2BBF76764F948B92D8AB2B8E876A071F9C7626CD1F8F88885AA5F1BD2CD06161FEAE0949F7F45F6E1124FEB6211AE8CA38A0B2F5810EDB79DBB9F3EDA2242E61CAD3F75D8E030DE89042D8041A2F6D4260D2EFFC31818D0BD34F57BAD846B70D61B85EAE3DBEEEC6E7A1EA64E7BD691C4FD07AF4292DDA572B7D8D13E0FEDE3E3563CD86EF4C823B1CF96B639C13A988A6EF4389813296FB9D37070B5C17B4374681B8D46FC9BA4F53C63DECB76EB907CB49A23F43FB788E22086EE2C269E25A0C45B5FEBC15D1F02198BA7E8D4DE8134AF6C10591A28EAEF7F39F9B54D845107589F15087AEB2ACA0C84E475497D25BAE0353CF2D036CBA5FC06A7A0B19DBAC1AA464880DDA5584EEE02F306EB486FCEE0D3B58BCC5555E8FED38C7BEC8779CA1B47EC5B9F1BA01DD18A0C3A90FF771EDE19F6B107F8DBFBB3AF3904E4F45389B002DE434E29425FA9473F751DA9E0A44E8ECC3B09127E011A343D2022B18B953DCA32938FB2D94D2FAD4295C1AC9BCAB0AD6941C950DD14FF5973239C7853DD5E80FB1DB007A923AD0CBD26973C9885DB7FFFDD09DD896EB6E83CCBA97A2AB7018A6339EC33E7AEB84D0F3323509E81AD2ED32E9F749011FEF2F9FE7281C5E204E6A9E3107F9901B0E3A7A55A3CA54714C53CE2BC79C4AE2652D3D5B701C31EA92513C102A4077ED8F76708758B24F3083D620F2EAD66EA3CE3D8341A0D4D8C99AAB5D1265770A7ADB8CF1C226A7D979899304B5F92999AB6B9BFCA1460A2A3B4B6B8C92E459597B8D1D300000000000000000000060D141E262D48656C6C6F20776F726C64 + +description = expand_a requires 150 SHAKE blocks +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = D83F3FE5BFD9895F3FCA5D0B6AC999618C311772D3A9DD13D5F1DCEAE0F8DFC7ECCA61B55ACA5B59F6A6903299E30AF3000A59A1D0C07EF37B56612AB56D886111FD3B846EBD40093F592FAE3D7C68323001324416D0B484C39D8D86E8CB60F61BD4476B3A9B29CCA23AEAA9376F22A4D1C2CEDAF64EB061C5F7780141F1AFD18E9FC0363D617048CF56DE2EA77E73BA5E433874CFEDADA42C2F410B84E20F48A7A09EFF493365BD997EACFFA795796376B9ABFB8FC3FAE21A2CDA94B4E4684EFC57B5F589D43A6A34615ADAB3CCE5973F230351DA3650C20182095452EEC5319E702C49D3426D9852EB9FC2817E3A55445C11B2B1A632CFBA5C2012A3EF691A4998C1CA23FD4A5BF4B75791E2DB6C067BAE0BC77764E227489AE0F1FE857756013BC8EBC5245C78C58E411E63A433AC20FCD89A442D2891E6A3040BC65136A508152DC0B82EBE0E44975C366FC9157F6B8CAA84350A7951F5D2A4677D647D17B9359D4566CD8FC5B7AB55135A39CABA73A79063BF1684915E64AFEC7E56942A8B342061FD2CA7F36B7E0972A88EC6EFC24DBE5C0B3918183663F769A9DE66C88511E013DECB1711542CE17A23912268CBC81821E95505EB2AC4E6F71C679D46EA423CD5B43513DA45FCC36BE2A084071AADD7608AA79AD7E1E3B6DC42BB689196E477953390089D4524DF56489D1B6E7C8FAB35C411A3B61204F805E80D55A37754E4CBEA7E25A73AFFFB51B0DD1A62EEC109E01E90EA00DDB76612EC1BB35CD6FC86D788DB8370E0FAB652750E53FAB5A488C87DA2533D96E8106B1EB1702BEC29387DEA33EAF4B224C7C2EBD938D88DF9946CB0EA1FEBC56B6C95A334F2F5A85D5B6BE24DDEFB149372B24311BD49CA08C509DA8EA75924A2BA12B41507AE853B63698161BFAA8598C4F5B15465C8BAF8A2BD67D78CA6A7F9A0ECE321785F29DC8F2FBA22DF727535E9D07D393C71899F72F3502EBA8C024AE578DF3F89A8DBD30DD4F989CBAC63F75935FF92659DC6822025333E08DE49B1FAACA128E22CCF992CAD4334E71BD01A0361E7832AE0CB8AEBDEFBED6343160C2F0E5EF75B388B8679C791F2F777AA146A675356FD90D88755CE0BDCE67E4D54AC57BA627C8C9E2C5A23B9FA9865D743804D852283CDE3E3FDF8E246BA0EE5FD1D7C9769BCFA3EE123E288193186E6CFB3ADB76614001D3DFF5F7168D8A16FA189D347614C0296D361BAECAE268F19A3AE5824FF8C6D65453A082DA30C9167A61930C70934484FFE5AEAE169EA3B32E5BD36AF63300E389FFDCCE5E7AC62DF06A1BF6D3AD01793F8D8E40963E91003861C40B90C7167863881B34E8916565A1BB02E622B54EA6D04FBECB2EA23320A8CDF1052E32B05F23AACAE527214860DDD6BE63D34B0A81915A280B8428807C9E36C5BD1BB79D9B9A5B658D04ECD677EFA9C987F4977F013162F1F8FE2DDF2A331FB767CF8B944C0523054EF264269C12EAB37E56D1A814CF6ECB4367DA3B69BFA07C6D04FD36FB6B007E33A8FACCC5085B652D0AF902DF2D4116A3CAA826014FB80C9405519CE80A4C03DC10F994DE92E43E59E4AC6E9815472492CEAA358927A14B2E083AA70BA58802C790C9911166B7DC1ED94318B4395D0B1ED125CDC83DFCAAC5F30EB90B0275F55498398DC30C755B79DB3E2E913E87E621EFEE191DA71CEDE227839DDC565A69E2467EF0CE03A3E2EBE625B53DB0E3C0C7BCDD37A322243EC39DCB3E6CA0D79644D974AE226978DBE1457BB4AE87B6B160E05474BADC09B7DAC93CC089565C10927BAEE18CE9320C9817A1FF89B3D39B4415E9820012C920097C3D1D3649BAE3528930FAC8E5AEFCCE444C04A9FC923557391B6DF0A74BF8CFCAF3AE1F54B1E5031ED928DC31DEC5956C45057FDF5F231CE1087F8B6301E387F21966F44B69AE9473888B6A6A19C99B2420C957DD9D14BBD53EC2F3B13D519776C39112C3586FD1FB87FCE63B9DDBEF1D4E0B37FF8FC19960EDDFD0C747B07AE7D8FF1CE85FDFD68FE6716774EE1E981D65255C9B7BE3680BE3D512736870C4C9C1F2D4FFA0553BD1AB66F15BE16D360EE3176AF9E00FD0D03E6925D22FD02D245EB89C3DF68EB50E8B14B690C5DC818F42656E4594156122E91A9D30A91D333E0E12FBDB4F1EE89EE80531310F9D5CD5A2C38B9AA7CA0FE71CA28FB8930BD9521DCBB5365D1038E8B784C53B0D1A95E679A1AE748F2FA6626EC1A594B5B523626707469556B50EBADA8B9C3367227A287A3125C8ED8F1960B81E6C23B42D6E8E863FE4F01F469954408746F86845006CBCCD7BAEF8E1F05C0F55D4ECA56F27CDDC28E370669CEF9AFB62BEA1290F46FA71BB3734F7128BFA959D9521C8B8BBEDC2D451828BB98A2E4F2D4FF0AEF0CE0AE7E75E00A8DE69802F496ADDC8A7CD64B47D8B2210B611F2271DB3B3056D0295980BF68447DAED63EE6BD70DF86CA6D5394B530F9BDDE060DD4FD33DEA9A98E0BEF653DBB6D5F3AD9337A84802E114A44DA3BED5873E143629D46C2D5C3ABEE1A385245AD6EFDD2F260E976C5EF4640252F1CFD5B8DBB5504632CB732701A33D03CE2BA810D8935C2A140A4F9E2186463B7E65C671C4FCEC23D426AFB2B12B624644A59ACF3548FAC2BD812E9E054472DCCD560BC334D05A4BF2B8BB4F6B5B79F3EA095D8A0E3A6A0BE76CFB184A84073302BE28655FCA4B5359F968AA55A6FE5814AC0176CE5C8FB93DE69AB61CB85489C69AC3734C4A3994779CA35E26ECC009018 +valid = true +smlen = 3320 +sm = 16B336256C51560D99C97D15FF467360F5F563FB555932F56351ACD1E53906F1C05C87F8544A821BCB05D0E3952A84C4D9DE460BECDC5EF5138C9729E905A3FD4117D32CB0957C5BAD8E84ED7C4170BE74D63E9B8D813C4EF7F534C5605A5E4F6BA4E06F6D800AF82809016EAE3E6FD4BEEF0F045304A4C17222BE7F8C5E71A294ED8485C956865896457119A39BA4ABC44BDB4D019493147D0B5E619BFE0A5F4ED1938E48E71B88EC8FBF267D1EA5DC8F63C67D98A1EBE9FE4757195C04A8202CF012133181892A4221CDAF79BCF240D005E80E8C68DA8F0FDFAF8754F21EBC42D2A5900CFF1CED847EE80E875C27100BF230F613B0758C3E4CCAE5064111E71F0C13447A25FFCA32669E53CCFA855B997236887F6AEFA3BAA2FE264686B879D1389D72C5967030D99915A9915182F97AC2375C93E5DAFAE6575DDDC16908BD2BC865891D85E70FA998BDAA18246F73DB0D69CA58BA813E33C90A3E6B2A2C2F8C97166C9B474C60FAB1F3C7841B96C2AF1349A37C443FD86291FACB657A049E175A69443BB3662E252213A868E8241188D8941FD524EF6017633D2E3B47C9A1AC1BCB119722F54C514E62DE40B5F2DB38A1281E220A14E31E46442D31C71489DF94F02811E53806C5EF65377433222B8510FB7E4F53AD31CBA34456779563028DD1FE7EF3752F0121EFBBCD28DCF09F045CACFFA2F09F343CD4184820DFCFA3E0746AA7CA2DEFD2BC165DEA6E3A07AF3B4A8E9BA1C18C32B44EC37069D65013AA2A88AFA691DAD1A07EA87FDF8C7B187FE9572EAE4F296BAC40F3F729EC4C9EA4378AAA60B70F4FEBC3FF3A7561E2E22A7B8A23770AF7BCA50540236419762F1F42D9CBA0B1285E83809EA02C4F0F9AF086D506967168653B1A54754B629D769479EEEF76EB8171B127B724040F0E7BB815577A4998FF01662D2968DDEE9CAAD22212C3196F60D9212B5E1FD92F0367D5780D3C42C92332E305B6E15BDB3EED70643A26892BA2BA9C6E575A77EA82EEF3F425DFB971C7F6E74520889A1869CFE4DDDF2819445E8BAF658668A9E0D3C65F263C208C4442D38E644F8CA193C5F463C4DCC2217DC337D37A0FFB61688A2C67A2223E41D24D07CA4984C35C5B33CF142F443E9A0EE0F631173399D714D41131E84F9B0C9BE290DAC2CE4716843CBCCDD3851CDE789E8D03A7133F08B6234DD78F63E17D29A7B93E992EC7C80D6BEF2E7EFACEACEA917FFE1B23B8A37F438CF97C42551CA8E37B1831EEFD5F4FA495D934AD6B7DC249BE12BAF8010F55552C87E04C79762E717A8647C427E9A9D41200438187475B8C51A990B1D268FBD1CB741059622BBE0B74D1C40C539D1719232A31023E7A0AF41034A64F65F96347F7BD9B1501812FB48BC771B72DD3487485765BF4A769B8CEDB355F425F49FB27DA1375B5183196ACA9009E4E638A0C5A07E424D2A9A6D828706DE3E36D5C579704E30D3980511C3F95786FD6CDDE178BD9B246929BAB9BB6E55176F83A25252D4DC97E70239A24EDE49A93CBBA3EF31A637DE8F254AB965C6D8824B31F28A9FC4C32BECCDE5299ECF43F488E9B8E037B848491DB03F6DEDA7BE882A5669DCD87B26D57856EA3F2D3BED6D5394B7A06C498FE8568F62ACBF63197D21D1059B55516D08496608CCD6B0CAC9A49B2A9B9B7436C1BD7F0673C2D66EA6CC6D20BDD975CAD6D32C11436333454C7CBC67A9EFF002B29F3B5AC34255FE7351888A5872862CC7F745AB7116BCDAB0D76BCD187D4318B65EE3044D3E342B88BF231838B93B3328DC787B3340FFF90931C392A1283F897F9A9091DF52B7CD2AE885118D4FAD2D595A76555071DA39436675AD6C083E9160B3A964A6B020F65AEE5A2CB3BE2453C0157904E7283802F243C5CB40943ED48A91B48FED455648C576EF7AD7FF6DF274723899B2977E13BF8E803FAECF2EA7FB78F63A78975512C962E375BD6AA37BD0132B0A9232E35743620D1785A55BDF36620888B2A578141E29E197735BF388491FC40DA63F423CCDF76E2947B53D975975840257FF2CB2B5075803305954941F49C7DAC218E081FE269DC2A5506F4CC2A751BBA6070D9EE0F8A801A90895AD3C1EB756475BCC3C6E0DF907C49B4A3494DBB7066744EF693A5EAB0EDFD00BF41B90002713F08B35CEAE0B19338D604DD47E55527FDD815408A20C575AC6388240E0F9B3FDD66C9E100E512FF6F73E1285C4DDA646F6E667C1E358F166DE2688E64E38FE47F0D44410A5CD284ADADDC6B444A08BB44A3FA3DFDDAB4245D99AE058F019362EB5E89F56B41DB5D885F038A31539545863809D094CD15FD23B77BB5C652D54ED422790532FAD71FF5AFD2EC1BE5F0BB1456F09FD9B37D9DA01FB9C103DBB277AED288EB4B5B28A2820EC7B717CEBC4D9F0EEBE5FFBFCBF722B0FAC299C4EC37C03EB1A066147A18AA47752F21877111F5DA3EA36B8D4A11D06126E90E59535B3A760D882BD694E5CF9E0DCA9B73AB6984F50472782F9B105BB3A7FA7AA7B697F831D3A9A94ABCEF8F7B6295EE73A873D67A930B4B830D770AF621E2DB52C5AC7DD221C8CE33C2F2D5147AE5EF89EE1F370A90DF218F69D3937ED20F2AC484D79CB5FB22C5C1BD477FB005A05414865AD6430233997053F1C4AAF7182AF075D196058C97F871CF7951585F90360504841AEBF6DA4BA1E721AA97F681989704F04E13B1843FA2678254C536844A0CAC2391D229F2C1382819F4E15CEF9655C1C667F45449CC7D3BDBA48C86E112E9BE49C2CF45B65934304883EED0C97A0ED53E660D7019DCFD94773D4209058D8E131B0E8DD0DF041A5AF4DCB7FFA810757EA253204510C69D08D4FD77FCD971D4D9C5E0FEB00B8672F525C13DCAD6734B40B98893A74836DBDDFD401C9BFE873DA4D1ACF4EB1028CBED94D48079B46643652AF0A877091D28CDE82585602B6003B47F19671D42BE1660F0CFAA289268CF1300C2273038831C57BCBAA2C88934484565CD2952AFB8214F76BC911D0C942D4B260293630BE3C0C44358D16AFC38BBCEA3AD073179487BB17D0AF4EE8884F30BF7AC5F7A8B469B7A82FD83C68A5531D2987338B2D760DC6718997DFB433CCBEECAD89EF7B79690CDFF544E93572468E0B044221304077C8D506DCED5FD7A3AB0449771ED71CD5790DFC43B1BBBF22A519583BCBF5B4E836D6A59870D25ABBE4BF8AE2A7723BBB98E3C763A9DFF1809D0AF5EA183EB1C983F06FC95735A64390876394ED3A98CA2DC5D4D6BC4F5004C7A4BACEAD5DAE0ADF46139FCC77E7C3D74B000E08BA87AF82F1669A8CC41855430E1C3A1B42ED1790D127D0861058BDD401F59BD80836E81CB019A923BB4DBEAE1CE5D8C9BDDA06CA80A407CF057448618332C75F2E61050C4D9E20B34EF1BB5D00008D152D77F220AE4ED705973E704A20C170BD9CC1F00D2C7B09A6B00A010BC987E0743E2F3005C7A802B73F76D1831E0FDC39D7F5B881B551116BED6FA9B7878D1E34CD9BCEF3E7F75C448EAEF8520EE560846636009AA7C6352D3C9BF4471DA268E00C9BD08D620A172E96CDF2D286D0433DB1E00FCA409DF3355ED471053A4B061E07D7CEBD0967C2840E3EE35AE99948F4AB0FC4875E8FDB847F6447E429D1261A961D0F54A6466BD1751313EEDA7C7F1EB197C31E3EA96D207DCB30AFA834A7923E9D482B7DA24B2FAD6F64908301335FEB45F68B4257E08AB4B51297842661818EB1532DBD1FA152177118A119EBB89FF9693506C7EA51392A009745CBC5BEB359BF6067958EC19A59F1CCF114DD379DC363663E284B182C7BEFFA1270330C009377C764D4C72A6A8C739430FAA1AD5E6315C61BDFD1FD573AFAAFF096BAC889C8195C07FD7F9203142C2BBF76764F948B92D8AB2B8E876A071F9C7626CD1F8F88885AA5F1BD2CD06161FEAE0949F7F45F6E1124FEB6211AE8CA38A0B2F5810EDB79DBB9F3EDA2242E61CAD3F75D8E030DE89042D8041A2F6D4260D2EFFC31818D0BD34F57BAD846B70D61B85EAE3DBEEEC6E7A1EA64E7BD691C4FD07AF4292DDA572B7D8D13E0FEDE3E3563CD86EF4C823B1CF96B639C13A988A6EF4389813296FB9D37070B5C17B4374681B8D46FC9BA4F53C63DECB76EB907CB49A23F43FB788E22086EE2C269E25A0C45B5FEBC15D1F02198BA7E8D4DE8134AF6C10591A28EAEF7F39F9B54D845107589F15087AEB2ACA0C84E475497D25BAE0353CF2D036CBA5FC06A7A0B19DBAC1AA464880DDA5584EEE02F306EB486FCEE0D3B58BCC5555E8FED38C7BEC8779CA1B47EC5B9F1BA01DD18A0C3A90FF771EDE19F6B107F8DBFBB3AF3904E4F45389B002DE434E29425FA9473F751DA9E0A44E8ECC3B09127E011A343D2022B18B953DCA32938FB2D94D2FAD4295C1AC9BCAB0AD6941C950DD14FF5973239C7853DD5E80FB1DB007A923AD0CBD26973C9885DB7FFFDD09DD896EB6E83CCBA97A2AB7018A6339EC33E7AEB84D0F3323509E81AD2ED32E9F749011FEF2F9FE7281C5E204E6A9E3107F9901B0E3A7A55A3CA54714C53CE2BC79C4AE2652D3D5B701C31EA92513C102A4077ED8F76708758B24F3083D620F2EAD66EA3CE3D8341A0D4D8C99AAB5D1265770A7ADB8CF1C226A7D979899304B5F92999AB6B9BFCA1460A2A3B4B6B8C92E459597B8D1D300000000000000000000060D141E262D48656C6C6F20776F726C64 + +description = rej_ntt_poly (sample_uniform) requires 783 SHAKE bytes +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = DA2593AC1DDDC220922B9B1972A2549AACA212F972786A5A5D7C2E00ABC407A15AB30DB5873F2F39918130072D0FB8A7BA465E13973A1142237FB10A22589D14B6EE9E60A7B72D7AB9A92E0BA034E81CB8A1D13E69F27428ADC34C3765F63C99504C780FBEE3D0C9A0FC10052D1D0A7312D549B9C1DD68E48D5607E2BCD689C4A7920479AEEA469F1E8D40565218B2CDBD3571FD57AC5049FFCFAFF950E0196F41FC619CAB4C6E915E0F1431E7AF3AF8CAA6E28DAEBB9C686E8CAA4FD0210143113A833BA364E973024787923FA7B8A35786BDED103AF9C7DFAB64D84FB1B94E9704805D6A309C32E0B0B4585E23CC025A0AB37A8F3B308E19AC06F967B25402144AC242FE89E8AEA7AE87138BFFD5689A53639B3A9E529EF32BCEB3612BD160DA3D57093B2EE231B0B0121EE71981AA56F1BAC86443220AB4087E5B0449BB5CA2FC0E7A517691E0B87AB2DAD3ABC6566A1512650704794D4A7005F082BA95FF0DDD84922FA4D5A16AA7A9B7BEB4EAC15DC00610B7FCAD4D36BBC8DF52D4EF5229A0EDF4C1D23D8501E5911E4465A6DF861B63AD76ED2B1F423098BB3D44A353AA299BEFA92DBD9BB577CDB5BCFB4FD40A18BDFC65C208F666A47D2B0FB03BF6D42EF9CC75ED1763B49FC63F3635478751C97A553EF62F339CC70497D9DA673EF3F49616F6BAA94095E540C1903C126A8C045F4FA7D737CFEA3F0697A8ABCF3CDFAA47743DC569FC1D75ED7F8100B29C77607A92CB2DAF531F0E3A4E7F51F8595225C7CBFF4D02B0403980CA0D3B3969E8DB7E2DBD85A037E2E762FEB282C01C419CB8201EA99F5F5319E393B8CF8EA1C05C22237F2DF31370EC2D532C3039CDAEDBD1D56957BAAFCD942555D3383256FED05F6107DAD8CB6879E183960CF29747F12FE6C04D74831486899DD83BF1B43FD1B74AC96C4A719B19E7BC04A466183D965E70801A81122F177096D8948E581C7D311A2E8092BBD1379016137303D15D6DD2F1509C3A4854EF5D4A40D9B2AE38628478E3463C075B81D2BA5F5F4CBF33FB2CF1DFF757D4DFC997C240C9A7E02AE42AE082CCDC0C337F2BDBA83CF4925129872B34C9D29AE69EB5A39FCF4C6F48B7614F7781F2407F893A0D477A37C51934CC89014EEF0E2748302BE8DB88C5E773118FE6AE17A522A224346B2C4F7C34C34CB8A7DA4F206F02FF89007B62949FF8C73B72CF67802D2AE552B6B70DF172188F33AACC11345C6337270A3DC67B1CDDC30AA0746400F3939B7E352DD28DD6139B8FE5E97F676A394C174F46AC1AB04C14DC58B0714CAB249D6836CCF01B3663D35776F8473B8B3C35EA3770C0C3F27B19F9A85A05648F1FC5FC0274F44EE5B4B6A35C9A29270F8B60EE2528672370537F7B7AFDC5CEF8DD2B2CDE9DFA9A31AC9B0D62B5D9F358146470AC2FB0A29B016CF3434BE4DDB10FE0B8F29423764DF46DA0FB3F393EA4D572FBC3C5789D3EFD4C28E3AC30F1D78E54F80AF9A6AB47883D293D9F1CC345AE095FBB836F0BAF26DEB82D99081F2BA3EF25AB747307CC146968F7FF95A8E3F57605F01933FDC9802E0ACC2854E4BFCC32D2AFFC7C6A88168CBD735C51BB993FBACB7A382F8E5CD65A8723398309F25413951A605C1A013626B75C36E067E84785B27C775EE240FF3CCF16EAE36B0E75B6AA1A5F582EB35B7DAFD91352626FA21389443238AFBE2E6529BEF2612F8328C037BB0D866EEEC99575F4D9A77D92BC458DC890B6585E4DB23755491D8F28A8F1AB3E291CD58086BEF3A83956884E2839E019EF2FABDA66AB524DDAF93DC817F5D19BE8864524B46434200260406B1F0A773E6724631196DF3D62496173EBC6CAA8B1EB8CF9CD98B16AC67B671E9067A31303ABC033056C9CAF5E1039230D9E18A98598D25A53A63D9FFCB0BEDCCCFEABA825C657480C35C781D92B8258CB188E9652B40B4FC2CFE1A9F2112AD6CB2BB1883962277488F59F5AD44F7ECB996E27F10D2FE8CA23A8E9D8E873751E9701EF895736BFB9E43ADC08E3898CE14B77EB2AB41EE2E506F2A9F2E553EC8CC0D8CE4C0A2981C42EDFD09C411DAAAE275009BACD5217F17054E6EB2ED391F21431278DD3E1A5526082F8F977A0E4B87A180635E58C87051B4EBD68C13F4E75BCCDF27CFBFC4F0E86951BD20D8E7F7D993EAD4D46B381BEF821A18CCFA9DE77D4561B0CA8AD8565D3942B3C6BD11F8B89AB1686DDB7DA0DDBC904AA25F2E508F6B24901874E2C579F74E8DD65110AF3BC445160C18AFD08B892FCD28D94CC219E8DCD7B9FB2BE6F3E1923B93922B1F5CD0A9327042AA5D067B0EDB6A0697D27BC94C16A5A245BFD1A32D4A180F7D37BD17481530E6B8EF38F8B17C90AEA56B3BDC2ACC1127921C12E3CAA289F37C531927C180A0EA7C44BF41F1FD85C2E94D476DF0531E3A954724DEEC307473D7253E48725331FA896BD1EB9D7F2CB97B59E6EAB042DEEB00A8870A2A0B240C02C0C278C331AC0171C2CBA820F64C9843EDD11819B9FEA0718266D44F29DCF0E06EA83B6E2FCEE44B52D497EABF6754D0DD2A516DB1FF7B8B04DCFCE3306127046798C4902D29E87957947533E71E218BF3EAA98EA41718F7BBB1D6154E5D71826D4FA8CE3689D7F2D49530A4B60779682CE2FB41612A1197F030D9C07B0F2A32054C3050C61C04CC88EDE4F9EDF31AA6195D9D4ACF61D2E129818119533462874399F065944A0BE397C1DBE7FF37912B42287DAD747164BD25AF43BB71EA5F279A3692250D0BD7F4056 +valid = true +smlen = 3320 +sm = 1873DF7BD504C772B508A823F78C4C0E859D16A7BC477575E700AD4A5E862F74D2537CADF3B3AD288ECBFA3FB6ACB3A8DDCAD7E1225CEC57DABC09444F900A7C922DD7AC0901A2527A71E32DCD3B6C71FF446EA8B8D404E61D59D24439171F1BD2D809136B9E71DB3ECECCACB25DDC3C84B318EC60327563B30CB9F29EB59B21B214E45FC14139CCE27A424CD804F869D69B5757CAED6CC254D3CAAC256BC4A3D8A95FD3A68E27A8CD88600C143DCB6F1559E83DE3B50127B75233E79C09C0FC9BA447971931BAB365B3675289D8A97CFC58305AEB4B81D9D9D221E21DA52150AAA9D1C655C8586CFA705AD67B793F2F96E545892B02144927C3BEACE27BEADB7E1B696557CD8E4A745B6101D4B05A8C999D05831C568367B0E71FC3FB682C22D9A52654835F06AAC19FF5DC5E4C1EFF1C49846571565D60458A337C44C6484884ECE36197BD5A759FA54348D4433058D1CE34505A79672D2E13BB01E810708739E5B4E86B5010E21F56D6035FE66ACFF867061294FECF203E528D71BC84DF0D46B63EE9EBB0806C3D346CB9787DB32D667B059A42FADE5DA9E88167C74056380E1E35004E59277E90FD4A835032442AB773D52A2A60DA388F0CAC93BBF26DBFE11B9C5F16BBA1D4877B6382B5F98B1E279DE8C06FC569EBAB6442F247CC321C38AFE012A003E5454F5A3389AFA18DC958B4BD99A93B5A1ED6D4497C75B0209D0D7669BD6A4F2D21FC61873A31C1B617CB90AEC8AC7FD16B12860BA0834AAC4E60F66108C0F8B17ED43E306E52E76C4D1F572E12D986ABAC77CB79D265271CC876E46BA3CD58BF650326AE1BD91FDB92A337D884C230F625235C403EA6BF1CF601834B7E0E6145D23CF386514F957B9CAF959D5E420964E2B07FD2E7E7541BDB8252103871A48B5BAB5B13707C872FF4B08989BFE71142346E2953028F26E1DF451BF67A7F1D71DAFEC0D64828CDD535F44BE1FD8E9C69A113BDDB421676E07027851B073053A9E319D3F2C5EF128476D78D44DF98D1C72494D1581B7ADE65A2DBCF7B0C9135AA42169DAEFD63124DFEF3DEAB5D93029D3ACF418C99AB58F39B49D32FD0525017D4DDE93495CA4F812152A74047EB93C3E63C0BEA2AF63194D8287779742D7F5A1B0C48FB299A1A1B773A331C221755BE407866695F00AFAA33E4B458037A0030F3609B3B0A16F7E68920D0013CF5943C076B3E20BA19C8DA95C18F69526FE271301CCF45FBF248FDB8A5CBABB191D6355F1F87DA4B9E0D11B417F5BD1AA8603E10D9A082DCE8F29A1B10E814D5E5B1532A209A636EC0C1854746087666C2F030221324DC62B24A2EF2E30D519EBCA2908A84C384735A322F1931597635DBAB254A1AE28305883C1BEFF6CE068FE7766E92D7977DFE4A315C09D0E39920E6FBD2A3A9139FB0B8D6CDBF44DDCE7AF4CAF616D0FD9AD62C41F48E3FE81235D79259CDB48EC0412C08219F60728E935F3C059198B5EC99168FC3503230A50536165AC05583DDE40A99A950639B0EEE5650341DEE03E84FDD4F5BFF58C9E90D8CB2740BEFF0BD05951B107A7ED5C0CC8B987AA753EDFD1CC3E5A57668B7C6F6B46979500A63608BA2A438E4093F8226845AED1F8DCEF6906C9B590D0343EA442F20416E199F9A0EF1E35BA075832D1FB1FEADF5AF89F84DF428CBFE7ADC07129E2C4381E0EE4AAF48C3E83567796D4DF6A0F77BF524EADB07450FB026112B1EA538DAE20F494ACBC9E020E6311B7FF4B325261FAD7784E5728D1E22033F28B95773DA2D9230C48E82DAF126882178BCFC58DF7ADC163B2D41E105027BFD9824CEDE1D5EDA485062D9DFBE197F25D7B0F7A1742E9EE705B5213DF8BDCF3EC012FAD069F13DCA7EB025C6586222CD754E7488135EC0A38569E45D7364ED9400E4A9D5DCAA7BB1ECE595973912B4BA3BE885C6684243A3C856E054A342235B53F217EA2FB6280DAA54A31027C9BA72AAB802501F355ADC9604E799FE3276655657068D1DB6A699CBD6CEC2F3BC5C9C502D43FCE11AE3F8B2B07A85FBE0D244FD81C9F92495459A782FCA7A2591B43DD420DBC860C8645DBD55FD191CCFC99226EAACE268D6BE92A09F29AAA1E61B53642180956AFF65B59D93C21302CEFA86E85CDF7D926933809977416649F853A3EBAD040D952FF34EBD5D6B2A3C8F9BA32B15E3921B70BA47C505EC1233044D3F349F49DB4D262EAAFC04AC0BCA4317A6863F3FC88D98A311F80EB41BFC5C611312538C4D92043E7A96B567937B1A3EB166081D0DAC70AB5865D6409B3310FA3FB55BCCD8EF6B6B79FD677EA89C9117BA9BEF2C0F282E2765CF100570E1FDD58323D4926648E8C9E4F3CB3E74AE5E3EF0CB53DDF48F7A082D346798566FD508E1A81BDD8FAA0F9AA23ABDC25A7080EE24AC4D147097976E6A350C23C5B9FB70F0068C272CF79756E25B2708F74D7D73D4976E6EDBD48214AA276F823B535F1EA6B1004612D965B6B43B17C66EC24B222E6A50C119157BEE10ABEA8FC902F66EDCDD9D10CE822B186C9AA837F2DFB0E0D612B358CF057BECC23106DFBB8511BBC14DBAFDCC1C44F140A6234B915E297D967EF905373C9579CA1C135C695B25A57CF8E7280BD32D20880A2155AA2E6F37CCE95EC487BF57F387BD19D398AD6495A8D6C3E34225F02912D204B110E92085DB5958BA740EBE55E14D37AB874E52884D30BDED1BF58065049FE9D495AD0095FF765615D2D192AD35C2E5CE12368A47BD53C94956E4BBB13B5F43FC2DAF2A82D1168E76E0BFB70F55A636DD68120936E888C79A2CE18FB1D8307BE5518C8831F8122EDE516DB4F1BBE06E22C9E683769E3FA0D42455DCF53B099535D7B2DD023C79947B2269AC8C4EDED0CE16D6666E738743FA61F05CB1AFB685D5DA51550AB115465C5047044DCCA58A3A47C9A42A03FFBA31174FE3DABECDD1B887ECD3BAB1A1AFD6BC61CB527B5C71208D797151A05B806209B454D62AC2AFABDB4023E8D215B6D8DE761852EA366E4DEA97EB3D54010767D2154B3B72B6A3599F624098AA9BDBB9D0D9242F7DC823A71AA89277F75ABE825D6D5240C5590439F1084952625466A1676F778FF117D3E344E66ADCF06F2F78935E723D86C0BB8CBB9D90238F963F8C63F94C5FA8A946D6A925CDC77F6CA2AEC141E8F16DE1D46236EB81C57CE682D973F2CB3AC12E3CF9E0290E4ED555EA1A57AD3B49D872DD6BA99FB89B91C8E6B25DFE38F8DF7D91023BAE4EB2DC7CB0A585A3BAA9422AB93F349167578DD3936197E8DAA71128083F7F783C67532FAC42AE9B88B94BE99FD9B62EA0D6E8C53EB4BA21B726644438649D0E19F379EB77594F1D5CAB77E97D61440C8F0AB0BED326B54FE5ACCDD7AC69ADEB946C855E32AFE33B6C75F00FC992F53FFF91546317C70CA6102052EFBE00407CA20FD276CC5E0C2984AF9A442787798673877DD990F6D49FB774FA6A6969D73E37D7AFE31B9546125C9F1C12280AD11ABD8866A0C13A210B8342390367ADE2772B2A6FA98ED4C373D2407A7060F5ABB6B0D8046C7A6392835B1B5BFE69B8973135B5B4DCB4DA252AF6706B3D813B4023574201B087BD7EBA6F7BA4C2E32F94DB3DA7CABBDB04728EFCCA581373FD34E9C518C3E8A388E46626CF240A5D30E18448B5B0058A5F5A65F0C8F3D5C42FB02F8F391C8AD68A8F05385B86D3E816F604BD75B7ED5F27589E4196A0A15E376261F56A89958AD737448226700BFC9BD2FC05A09C23E86B85304BE0FED7B4BEE40F106FF3357E40107055F26189E59126DE22DE0C50C20CE74C2D30FBA2F8290C969508321BE117AB8AA6270961A9DA3C451B3A4910EFADF20D2CB52B07A57700A11AB4D5449CD370789057C1E66B1CCD6412B4461B0208C87863A068C4A2DC52E1D6CB77103DBC6993C26E77D8DF0E847BFE649AA9D111F9F3718D5ED949F6688339DE0D7A02931C5C2FB34EC6E5BFAE039208A10C3EDD34DB3292AAE4B1CC2DE238914DA4E0B605E5BA988674176541FAECEDBDEDFE8F954D86972C9F187DE5D4EC61D9DBE89C3DF927E245B14A8A4B7CBA2264C1646E632E07DC59B4C6C0578AE7266E312174CAECD94A57A50E5D87A82DC94AACAF6A3E87928BF5ED7B4A939C5A2D445BEB9E7929C1ED4901B38CA28FFFCBA1F9C859962698DBE4460A694D99FD47BCB91B391EC8F4E50500466617FF2A0123DA15798E9CC4992043B34C759B63B6A3B8D2B6EDEEF00F6B8C5A2B3F0225C315B6CD6A744151CD5AB9CACF0445BD62586B7469C0C4E6D466FFCBDBB165DFA42BA888D64E9F7D22D1AE22E1A361F4DDD5C059FF273928A47EAA229B409E20E48570CCD7191067869940F661385B0E57C04F936C72AA36C0FA1DE1CF3A18EA4B2E889F7AB3300D223E2F73200266AD8FF854E7276EF9420539DFF1422296D22188D519A5F7E8FABCF04B4E85BE6271A07E26AC654D93D31C1BC674F5799A84474FD347C44A9BEB5523F6E89D8993C35BD6E5DB1996225EF5A6C7A92C0B2C57F1B19EC26C75D5A9125BB4FAF7C0EA29063CA6708DFE044D5C8B23F03E376A4765A2E1A127A82E51A7C9353112D05E841245D1D2C3F254E4C6B0EEB4BB53818769E10610254044636AA5C93A678BA0AB1A1B41434E7B899DDA0F70959DA80275DD00000000000000000000000000000000000000000000020B10191E2148656C6C6F20776F726C64 + +description = expand_a requires 23103 SHAKE bytes +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = A65C0585D2EF17634953ECFFD89A4CE8459CF96FE59D2F9F59170D5796E90F53D579C0F05BC3A2F82A4E83AFA6F2A94DC3FB1DC53D839506EF76F919B859C93B643E4193F658D3696A36DABA1A8718F5666A7E1E8D3B71BE62CC0F48610A580F465F9F6E3DFBD46AB16891947B100C1E14D454BF77F1B56BF638DEEAE60E026FE37F3CCE68AF7CB67824947D0404CC2177B45A0DD62F5271030F6D7DC2DF6F91AA6BAF30978CDC46B53CD5DF316C8A9E2E2BF0FFC06DE6590278D63F69DE3B7F438A1FC1A063A7A2A184F7ABB827E5231354E9C7A12702BA4DD4E58116DE01637821125E120C3D9BDE373B0ED987DDD2D2DE6660B3712E803BE1CB7948B561DE26A314944B0B612888C0CA6BD9673C16E5AF1D42BB411EE3A9B1C2E7BFF3A15E7068927EA3180C64BD0AF3A69CC96E0DC18C515AA4250712C3198C6CD55ACED8A5F8A447A8C1D5679DD697A6AD9127B4847AC363616D82F626007948CEE72CBEC1720A552F74F4E83C0782105DCA13DC99AF313B3EAB386E895F385449E243C35521DB76702828F1D39951F8A35DEC93F5288B700CD13E48DEEECE3C96DD87090654B34B5122AC8918917F700E2F638728115CC632FC3B38F49FF54D8AC48C4BFAA5590E01F914431931301C4B624F346DAC671E94C7CC75EA7F9FBDDDE4FF554B0B297484E83BB68394BE78FD97A91EB9E378F1E024CC370420A24F7609A6708FC673D5955602265CC45B486923DFBCAA40E60B02131577C95A158FC831E69597309B84D91145DE41DDDE0DE26D5D9F9248C5B99C838157768693F7FB07127FD918DA1B037E502888AA8928A9B80EC8BF61F1CCE40CC6EBE578D2595C845058DB2A5A126705E37B6AE90FD77163A918D567C2C63826C560470AE283EED492E8F641DA2B708B7648DD92B1F44CF2134C6382D8BAEB9B7601D404A2A3E332CA8E72063FAE85E70D57520EBA31CACD45E2B44AAE388ACF33A4377CD86380FD2BA5A6BA9E0BD09B9C4DE13069FE7DEBD01ED5183C8FF7D693E4342038816B44A03CF0EA44A22691B5BBC3B4A977F9230BA5479821F087843361AE95F0EB3344F72CE6E5A2B913349BADB7D760D8F23AC2975584CAE258CEDEBCBA5E481C1988C13D7B5CFB6FCA2E8830EDF0D7EA135B124C66BCFA2BAFDF5E89CE68E9CBA37B81D55FB08AA26FDC8E5CFBD2B9A9E7F6B5D96CBCB49D414FEA45D96FB0C4EF5FD26B583C63AC26EF3B932DEC83B3D81F23117513064DF9E51F1FE232EFA2C3F964C43A74543AB37900AD9023ECDDE3D36C8CAA17C5E16E9FD5B5AB9E3BFFA5D527F4A75FDCD5F986D51D45A9B3E7396A592EF707292877973A6E9B1824CA13A2D119A6DEB1CA7156EEC968978BA00EF4F7EB67BF640E352CA41334EAF535FAD7307A89A327949E4C2110DB2CA4EBA4E0FE5AFC427890B61748044472CB0D4A3962DB462A1A6299FFFB46F909316C177A4978BEC12DAD103B9857327920F198704CCCDED557FC8767D157C1D35C697957D3AA50BE58ED319FC45E5A253D9EAD960970597EDE575442774D5FCA19E0FE5E8307F7F04B72857EE4182D8F1DA022074187F45CFCEBE46CE8F81708C5F171692F7986D6080DDE42746B4CEE0582E0D273C90CC97DE52374A323B8AB72C3BB7A3DED2B807EF818E26248942A50775349059F3E6076943A528828F125AEB30E8794D28087FF1E819909EAC7CE193E1C836B52CFE14CBB72008ED498F627A11748A6B61E2A6C20DB49A0087B57B51DDB50EC63E3E62A7780F4AE76B365ABB82244026FD921F46B5D6ADB0CD4FDEE1D6A6932E54F99D38DA331D18F34515DFF67BEB7DBAFC40921E0D6ABB0DFBE190964D8D7D5FCC244BF0580BE685F145862776684EADF30DC7D3DA75F56D37847B92215F9AAA87247A1EC52B6843EEE2E78B3384A0D81FB608845471E84F4E30F4A77BDA73DAB2392B433715B0AC9043A2CE8DD839BDA5B0B5B3196F32F0DE70081DA0D68428620946D66ED663C98826575A9BF6DF2B48BEF7ED7D2BC2FF52A9D48AFA2FB82E13B383579F3ED1DEE732B78144664B8E891A15D26CA0E5B4AA220DD8F038324813A7A9079AD03C6653BE1F8A1315C09709771B41A9B1E40F6FEC2797E31CA5F9FBCEA90A228D907636484E297817CF7C35DD8A3CDE2F29609CD682BC75EB2FD565EC671BA9312B0C1D5B4FA7EB94B34F7D756EC25A2EFB1CC1626F4262AD29A4772829AF54D60C3E2A9462786952419A40B34F256B473D1C4DC58B18C85113DAE39F6DD4098AB99409E24BFA9EBC242E35357660F065158A2F0487F97E6C08503D8F565662793969955F09779D64AA3867B3E39B61536BAF0C8F18EF5229C21C0EF0B44F962FBDF8C295DEA5982A74D4755CED8A84BA00AEE2A546F64062E4881F95B01F74466A61570803A0498B9DA59EF87C7EA1D48E33B3C68DBA82F4169C11597440EEB1EA4306FC7E6594A174446431DD25D94390F4F7E44905C8B90D6BC3409D0610D1248BAEE08E6CA9429FF39EF4ABA46788283FF8EEE6AA2A9414F45A590E021BE15922023E7A8B8C5D65903C4F011212CD10611785F6AEC8F24A0CD093E18E4DEB7ACE3406913739D502EB6A0E36EE21678FAD144914E8776913EDD80BF5341C8418B570B55647042009C820E8C3795EEFB4DE859797AC913910D9B1594E4935EA393DAA619967FA22B146C5C423BF4619392FC9222FDE72132748B5BC8CC94BA6B24E8E89309602B29FF460E4C745F6A64E24E3530034903A50F +valid = true +smlen = 3320 +sm = 5C713BB1755F4A31C900FFAC7AD74AC8ADCC218DDC7B7F2A7655A89CD348461AC84BEDD66DE6D3F9D2D78E6441B2756E31345B4BBC5DBCD8491DAA61080ABE2C108E7EA92D02C5064DAA8447CB982326C83BEF10EBD654C0846A572BF1AADDDAD8AC66DB63E6875150242CB8299433D5DDACD8E9DFF829AD3AF5635795D90E932B05C499B3BDB6A5BEBD3D5B276993606D82855FDDC31CD3233B255A92B6A6BFB78FC673D057D44F555B15B87CB15B16A2B50354237C1DE8BF2CD45CF4D808448B7FA6B554AEB422C4F4666C53BF6CEFD9E57D752509C0D278815116EE858F07D1B924608F76824981FB3D50E43973CB3AE375A337AFCADFEA2F4081C7BE3CB6F89388D2DE94A2565F7ED22BF296916D26B7298E2FD86B993720BC220B827EFB0D3017A8B73A4768E21E2AC437FE462518C199361E141D28F1CFC2117CFEB5E10BCBF402427A6DD1572CFB296D2B145588B82FDF547EC3A08876A9AE7D7980A97671BEBF5A0464B22D49737C677D7B65717A2F368D3E95C8EBFD58EB0412EC7D55AA49DC38DFE6EDD15A814A620A0EFACC6EC38E96F342A8590EAA1B25531FE3E82F85E4F5E46302140D1EE4AEAEEC02CF0274DC7519E3C95AC09C77D5D8BF5821FA9EA276FDD26434B57F838F8DAB472250EEDED38C7D5DCDE7D4850C56C6AEEB9D0690E127E3D530DE6CF11B934E55085E8F89CD72988C93C6B2E9650650D90C561A208BB9ADA1A58F9AE0029B492BFE1A44C99B54DE4226CA44A47C7BB4AB2BBBC0658E9484B6A51FA46E54E7CBF8DD0EFEE828815AAA1986034B78FDDCB51FB41E2BB232E623841350318A427FF8BBEEF53B7B4B51C6F3FF16B7E7D7A5DFE574632AE42785B07027B3E5F9591064EC287D07092EBFE406731AEE43FA17D363564D5078AF8A59A791FB8E3625FA6581BEC1A7DF4F6B36BABEC24ED58878F1AC431CEB7BD690996162642B60860FD8F43E6698A8B9911E7532839827122C5244E0252646F32235DFF933C04AAA92590448254B9E529ADCBB22982DE869BEA2A0035A33F10FE559BA90758F491C2BE1D5D8F1FDCBCCCE193D40658C8FF753700B73ADB2AFA7AC7C38D02D9CBCA3BB6E797FB8C7FE428F0B0B267B2D40A7329C902D90AD4C5D00542C0681DB02A39DBDAC0259E0A36C9ABD6318E709C2ECAC66819F93C6E424ABAB8C58FF53F5251066F8FD9F8B4AF9ADFABCE77CEB0C7D9485FC593C1309D160A5B06896EE147336DB19D8303545537AD166203214C72BB76DF59B4387A6287AE1390DF354E9EB4F8212F7EAEF0EAF486DF611775BEDF64E579CDAC9E982EE9F3FED430A464E513C3BBB40322B786D39E8172D553AE9C1FEFAF85C7032B7EEA351CE428C25A7A77E194415D75F421C0EB37A366E5CFDFD876BF24AA48FCF2F7E194CD79F4E433A5A33EDA08E2C7780E86EAFE3D3A2B37B275CBA8355FB196A5B4FB6C92130C99AE0230EA69A64138A54DAF9E4B7B3C06D898E0C8EDCB0CD47446E587CBE1351E38C18E8F8C913C116DC0A532870012B795F7D8EA90D5B45ECB399B79F10960D46F0E38BBD2AEAA3FE7DC1F0A4A3AF34D93C0A4790D0CAD37CA1B2E8BDD5E19CF95DBDA815171A93371D2FB9F3FA682CA5955EB83EA1AF89A9BE5D1F898EE779BFEBA43D497CD9BF434CA423C6F7EE856133FEF62E88F68FA9C8A3F6919A4DD39A1FBC1755229FC376232630082157273CDE5E44F1ED90268D52271FFE9917026D4E7E435C502C027DBCAD78009F25350F69626E2B367AE951CD9BE2549C865DF0E96876A860567C61F7E9F93D379A78FD0F21BE36BC87BF4111B7E362341AEB39D08E0EBD93F19B9CEE674C3AAA3303B5CCF3EE9A17852A7B2F8F2A2ED4264A418122CB8EC18579A9205838548689ADF6714ED73332ACC7BED58CB4125AF069805553BF17B4624711781466E3D16888FD88B1A207ED140A3D741A0B014556904C24F6CE9BBD5491803131235056AD10EA16F68E5311AD81C3D10DBB10BD15D0437FF942C12DC4F9B0206371820F5669065FCCEFEC40E98C65D58C7283178EB6E03EE178DF912BD2F9BF1DDEF5D0E8BB7C21027AC835A6F4AC405B67C2E00974B183B3B69F4A21E2FB5577CD3FA80A922DBBB2EF9CCC1460FDF886286F98092D1DDCCCDCC1A92FCC2F3C9AA95346E5A8E7F9EE66312A8D6D79B92AFD56E7528D821F9FFA0B2B0105C0946ED8FA93882862A8540E193402F6579A377B5D6BD341D010438D0C8FB181388FFB65E0B2CDCF32155C0B4D6F126EF8A1179EA3541A38EDDE3F1F8E11C09CF92903987B1BCFC0F99C58623DA618A5E92414E714CD545D3DDF46E084596B6FF8FAF0973BE86EF48C8CA973F0A1FC3871A6DD67A691BD3E0DDF1A423B9BEF6181024D0DA29C69E969D43A45512AC0869533041A300C1750A4681A93DDE85C2A7D1ECE439C0CD3965376038269548EB760374909BEB0C46AAC289613C1A8B53AE0698EF0AD4D286CB7637ECB07D20D286EC5187A91F812CB4F99B6DA9B74819A384C04F295DFD4008FE11976FBCC83D53ADABCD6EC5737C1634E704C1B68381788B4BA28DAD170C0AD2A4BC871762F07FD0FFD1D37DEE0F2152672BDC97FB69ACBBE7A0A85FF88019FA51DE355F47DCA0A74EA528E8FB0B29BC04CF70BB18590A03F2B2B725D451B8F5F37CB1A7FF237698194351583217055BAC197FF529B9D8F8B7EA0F78CB12F0BA2BFD9A7DC5BA469AAF8421B01F3242848E801B01CEC65DA9EBC1C1618106F0858F44FB4A81E7C07CD098ED4ACA64FFB0A181B1DBD83F7D3E82C86F02AA805BF888F999D5CCADD1C6DD25B58820F9AFD8B9A53AA93CB32938FE8E0D1B1F04C84D923BB2F76A7EF0CB5F501D5BEEAD7B2D8E84722DBE50084CC715813EDBACEB17AB046C9075F21AAAD399402A9D3606B664D58E992A117E3E92389AC87F39A83EB035A4DF9569F4F171577A67224ECEED4AB6F4C897AAB269DC3FCAA2C36FEEA43587A0BEFC5C2C9EBAE65C103F04B92DC2E0F6A793CE8A13BB5FC14D99F0650806D617CAF9DFD894B036F83B6E01804DE1FF9ADA1B12E0DAC5EF9F95D6468BE6D28B04640EC3BECCEFF1436D7AAF96DA77428D3582AE13D61EEFDA18E3AF9256BCAE31FBAC6DC6C2C8BCA8A1316F9972A82830D2D1A840329DFD4404AF13B99C1FA2528E8B180C9402A79794F5249384166BBD69B703FD4A122A275D415A178A69408A99E1A011C8F820695D955142AAE70549588181573E9096BA3DB75C0F5EF8296C226C9BA3783EBB93CB1FDB09E36B98B67991F583D2F41204823A64CBB18C005A96642E90409229F65C67CE69F4C062604AC8AD1F60DDEEC981D9E0911E1F5E897AB2B94F35487114382C3B71A09A27717A08EB9F87329657C14DA835A4523E7B5D2951031AB26EAA90D3473A850760EA2E2261CF2564531EDE5D4ED3023EA73AB9D98D842492E0E560E01BEFC685277A4B5A53CB4210A5131223B205F7033AA51A6B0546C3D9731A4D6574E612509946D55F47A0F207F956378CA1F4AF2AE9BDA14CEA65EF74D58302136C29659AF7CC753986AECD52563D1CCF9D11EFADF5B5FC108263C2ED24A935A8BF48FE3269F552A9A9659813F94F6EAAFA76AB20F5AF37576409AD6BE15AAEBFEDF66DF5AEC89A98D0E7D549D6BD1C73CABB6C16F6CD1166F517316CBFFE91E5D63371875D6923CDFCDEAFC5A12D7402264FE51ECA38AD1FC0815B688F3FF9D1C42C703EED9F8DF1D4CED289DC635776E3409DF2635930DE118FCC33C3A112C458478D565367643D376248B27569187450ACE30502CB9A85CD55F6D40737B6535278631468D200E08DFBB0D6DC82E420DF310D331D5D3C95CA36AF71FA9871B265464CEB092D427945F94DD13106BB3E2D5B395BA2DC08DD3CC1E1D718A390930E7D078A388DBFC82A84C1AE17BF776F524930A5AAC14FABD97BD8816D2E118DE666864669FDA008D9EF5FC5B321496DA23188CF659C9C51CE39AEFA9906C2A00269BAA823BA9390E3978E5A26C451AADE8974638B4D35C6B781F9E0F4E9D20FC4CE491C9B007CCA5F047AD7158E66A7C43554A5FF02FB8A704751C769264DDAC792BAC252DFC8DC8AE9F7C06578015E8E11C7C94D1BA277F9D2657168B2F3D2BE2FE3DCA8D5C7DD639EEFFD04F94EF21ADE4DE04B845BBB7258DD65CDB99989803CAF5B65127079AEDCDD0B1063CAC8688307FEB4302EA2AC43617F8CC44CBF3274EF928063DBA017D0C9310DBE912A0FFECA7F3B212DEB90DEF7DA2B219426CF68EDD169FCD27321819E0FF163BF467FD53B1F21AAA1C98C13F1751E2D2A0F32A26352C6C7734441AA45BECA811F5D44746C9B3B23C4C3A438E7261A65B5499DC339E2D545E6BD39E7E56CCA44A6B17CCF19876AAEB1BB41E416E755B59F9AC67E65D7ED6D4143837E1CBD32185A8D638F9BED16B49C645DCE9B21D4BC9380ED95C940B4101AB59C7B261BAA867F3A7278758F3E01298B6F08DB2802EC178FA2EEDAE79D4E37A68D9FFD92A8320ED59A8E14C5F32E7837F90D9A142EBC681BA1EE4ACAF2F37C92E80335880D025DDB8D3F8B2D07F2D3C79C5EBBB42229295460DFD2F682A3E497E879BBED50B17274144617486A1D3FA1241467B8A15193B61949DC7496781949EA5A8C40B1141424DCFEE0000000000000000000813181F272E48656C6C6F20776F726C64 + +description = rej_bounded_poly (sample_uniform_eta) requires 3 SHAKE blocks +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 15E04BF6D4209B8C4CFE8AFC2BBE6F9DA39072DB9496502939931B5FA7088ABEE3ABB33FE17F89FB14AD6AECF7C21C5BEBA421ABE25149E51E28C6D6FD5E7ED14EA713C03B8CCEB9AA6AFC671D638DDD2C2572D02C5456C9A1A60C62255784A63500479E7EFF313505A01D7AB7ABCF6F380935D633BCE23CEA4FCE9CF6155BBE562CF9F7B333B181D14466024E5DA6A91411F818C643ECD5BD70671CE452ABA3A408F02D48AE9999B2A36F23298FF8F939952775CEBB7F2F044045BF0EA5CA015EFF456D54FB76F63A224602A1BA8D46A35305EBBA2A566BFB50894B87F18A19DE5EB3E9555B9279EB0193B2B557DCEA6F1C94E1220AE6B6C24A379290659C21B876C243649E3C4A78FB29D0B5D9A465019B3F3C33497C0A275CE714763D0D0F9D2AF723E0A052F7776F8731C5D17348BBD1E451337F44BC9D62500B92004B9900E1D22125453639B1F26DE264774B6379377C13EEC0E40BE84C363B74477E2333B690CBF86E57B8FAEDB3423E2275491799E208DF1C391AA3E894594952F0BEB23C84F32ABE7B816A85EEC59909712FF932397B697343A117A3C8BB1E151E960690803A4217CCC623E868EA4D998087D50DD4E0B0AF610ACC18B61117D0678E6C979B7A2C3A6BDA0B0DB5BC499DCF2AC036CDBA0CE4852796A15FF84E352AD21F0CE536379A1B0DF46B10BC6EDFCA8FEA1411F361C905ECBACDEB2EB2B94E61B6785AB477BEB2C0C58BB6D7E78FDBB5A1F26D750112195497C352FA080F28A5167E38F6D6FEE6CCA8891A8520A3B06847FF4AE3D198DAE3891B76EECB09929A57241DAA4345972785CEECF6B5FC9E8E68E371F410E4EDFBAB52A1E54FC296580EB3A21A7AF6A744A0ECFD619EA3DCB483793EECBC78F30CF4104B653CC5FCBCB1AA8263C44AB9B7FA3B1D736C9BDB9DF748F97BB960ACEAA7B9C37C6244A4D668C1C58E043D0D39B944A43E70528118B2A15756540F8198DFBFD7F52E15DBBC5CDF0374C5115161260B0EE768DBCDE74AEF6D0FC4804AC442A5C4DCEE799A452CE651C6FE352C8CDE2C74122C5F1B11474C60D85F7647C814BC1262DD822D4F9E3FDCE17A8A47E6224FEB2D9AAF7BBB8CDB2F25AB8D1DFCAA1041887B9079B47137F1E9C0510F549DCC2E82FB49BB6A0D365A0C935A31032E698589B30C665BA95B32ABE45D14E280DE2073BDD0FC1F461177775468DB1EEE020732996B677EB78C7BDCB87B4B5E72EBD6AD684E4D3E8293304F938120182879BF1E2915120253ECF3A0B0B49F84CA5E895DFEC71995FA1A23ACEB15F71285F55E11A477BCFC00F76077BAABA21853EBF7065DB5CE1C33391B9021EDA07940A14E52DD210ABB41E0B50B79A06A0E8F09666931202464E963401F6C24B750156990D57C403A17D8A436AA4795538A795D7C7B724D4FF65153C1E1E7FAD09C4511072B5A6E3A35FCBB0C09E0AB7250D6A00848D60B7168FDD5E9771C5D9D60129DC7CA5E572D430ACB0314427BF2893927D784E7A617CD9420429CAA9CF037E774599E763C57E3AD3C4C79B44ED8CD28B8C16D2F788E25F3A0E5F277952A984BDFDC0AE99B5768F6C778E6926EEE4DAA3FD706F3CEED4BBDEEFF037392FD47AED9FC68776EAE3E9AD3D035554EBA56FE2569DA14488D03F0B43EE510F25636BF986540D845C9D73A541C7B7A3BD0A3990C6CD1EF2BFEBAB340B3976F7622D1D967516F75E31F3D182DA8873623B832474E2BD77E0884861B1F36B803D4A8F462B3708561B849E7641FA0B7875A36B6BF0EA3DD04080DC3C46A3FDC098F3C3449C86DF2BD7D8EA7B76FE6B9963DF28287C0B1A24B2C1252D7FCBBE2AEE5723D0D393482143D257EC1C2897387C0C4B4447DB8CE671FD486281A91F86813A659081451CFA0C15876E34A406A48A3094098562F851B31C19A3CBD87816B8DFA249B75090FC6045635F71DF6E8D2AD374AF393126E5E7FACB9AF0495CA7D581522185A2A1DE1F980599A42C1B2C39E345A24D9219C7B8CF8A66850E5390DE8626A74664A0478485444A4628FBCA04F46EEA77C8DE9ABA2802FE57F4C92E6B80D7686B0A7F075235A6A0117E79236E9D89B82F1C483F04829FD640F66022533F6F76B3579E07A153EDE6398E5012BFC6B87F7F83F4852AC8C886CA1FAA1042EB85783495A9FCB4D0FDC47F9EC15651C7CDC2484058CFD2BDDD914D1A4D35C71925AF84B0022C3E9B620076C2B9DDBCF852E33AF25D6FB6B2949186279478FF2CA73B993AC55FAA810F877EA7E0A2EBCD9479C3C52AD185711890C5646746BAE35EE294D6B1DFBFD850AD844EBDDDA0C50D636E0400FA156ECADCBDF8379BD043F5198667D04170E63E4D6A0C6958779F419BC052FD49967121AE74F328F6ED9402A4C7D20CEEC9FB48298C388687A99A9565A34C20B94FA29FFB843FC1E3C88B26CDECB7509A1BC368F268F8E122127BB4F06B24C8473D70CB1A073C0DC99619712B6BF9EFAB676E5A8972F34AEAB43F2D3E83789DAF462FEB0779CC2BE735AEC0446A7CA42A6E58972AFF8848084C30B95A09F7A7E17CCDBED6AED1DF9343D5CB36D5FDC72294AAEA8E1D9E927821A719F3CFC6825CE8C7D5C910FB049CB9A35EA66A8C281909A7EDB0547CB112D4C8D00F554470C8EF4F44B240C8944A3D34A064974D92C01EFA7FFD5DADFD9B8C15DB3C5DE3905F84DE751F2D327662A97B6486A41D50691C83248286FBB354988AC277031E3B411CC74DDB6FE760B9BE88ED92E508155CEC068E6 +valid = true +smlen = 3320 +sm = 0C75BEB55DB356144146BDC41A5FCDB1EE2FD32FEB0F4A37458617B6B02CF5363B96B58166AED22162D54823970D25ADE5E22205AF1D387F455A30429E53A1186B03D5568785893DFE81FA7FB28AD50F8B547BE838D4E57B1D6AEC98CA75161F3DD8AB552B417BC573495F1E59B3AB692EAA7F4D30C6F3A02474A1D01D156F3A0CAA81C2CA9B2C65D1619C148B226463428085F7EAF1BBCD491F1BE100C93AD8A9C33E57EBB76F8B57BB603534D1930C1BCB17D2036D44E7C37D88FE3CB0D285E0F8D275D8BB44827D7CFD23EA6468CB4AB3C53B19DDAA2E4E688A33A4303E6A57E1DB745F3DB0DA5E3301C4290B4AB8CB42A0F8B3E1CB63C29FF943CC4DFAC41C8A9C2ED987D8F3012CC4550E19CE99366F0700341B86103A1FC81EA1FC0F49C66EA638319F1BBDBBAEE13175E06954CE060870055C5E861BFFCA5F706424891627B43E92C92815CC4A093BF794BF528024DFA927998AE93898CADF1F2D680A4F26E77E749DB84231EE587F3EB82A6EEE42498FBA367BDA88C7A066E25C47453E1269DE4EA56ABAEDC0D2E7040636F8207FCB7E6273F2F43F557CB56680214CA86B1D5F6E774D699E9B7E85D32B7C0CBE31F2E8B4188B7C8BFBBDA09F1C70018F3BD73EF365F8BBBA82B461B78CADB3D0CBF9CA4B418472CC424860DC81DD2549D3503BF93E293929F7F83C2D576709CCD291A8BD4C7D9B4A9A5F64A8F2F20413582611888FEAFD5757F851609B5C7B00E9AD93A4BEAE2E21B1F65519C7D068A29F4B2DB0B2A61E676ED721B153E2A7818BDD624978D6F71C582E04EA2BB81C23047B463C808E3F3220F5DE8E161E6B37336BE5E635F0FCF31777C341C7F46C5144E1097B90E44BC8EE6672CBEF59924D841D7FAF0E0495122C98A1AD1004165AB89462137D9D35330239C438FA864EEF96467B6F3B17DE011BB72B57C38482EB527DEB3EDAE42DCBBAE0F2202793C76E0458B60DDF7A59E0438CEE78736C4649C3AA96D798A4103471AE967E93DC657848BEB0F22D997E9E6F97CE3C42BBA7DA71F3BC7C95EFB98B6739F5E88B37BFFEA5E6CCF39AF2A97223249F89655BB0DF36C1A6C88B613C1E3768C1087D2ED5662E12D4CEE9D95F1F5296902CA56EBE44E37B74E9782637E4DB29B300CC217E9E2258C57E8FCC4DAA69F39BE21F6E0FED143CA5E7AAE26057CD622C14AE735F020833C75B9DF4DAB14A5C75B1E1DABF4D3075E0AF0CCE8A7D85E0B32E1E4F361D9653BA38DB3469D01A957716C851D70EB39BBC5747E7A5A45FFF6C6E3B0B8B9D76126FDE2F65E956339ECA35FABB8F28F905C81510DC1D63F3364FFE9B0588F37DDAC2630B3700CD627B48B747364BC96DDEAB281AB27D5D591D5CF240FD7D5B49B66C8E48072A816D5A218359B1C030160CA0BFFD77CACC7C583E4363EBD2C3BD6BF0F8ECE2B2B5651B718567E36D5D5266CC38D85C453D169AAF0EA1830EF7B944F5997B0FF94E6444CEEDF5B5D5288DFB75CBCFFB789CA8613268D659320F449E3E4D75B03A1AD31305C08AA319E8845A05C21D8A20B4E84A46AC75A83674C2421D02D9FC2F0808D42A46A247D84DAEA362079EFBF7830C4C3CBE8FE47D31524704417590631FC67E93264E5855D8CD3344E65DE204A5EAD08148AE674F8423D2468707BA27B4BD14CE3CB51E60BB5C35016BAEFFFEC2ED017C2517DD18675A5B8D9E0055C2E9DF3EFFD128ECF88A2EA1A302154B2B7E3268068501334B0245FBE10651A2EC76917B82D5DCE274E9570902F42A76277DCE44793191BF15D2A3AEA4CD7B403AEE4C0FEEFC7D8121C686398E46ECBAF55248085FFEFA3D9A8E96AB48A7DFCDB7BD9CBA7AF25278A449562AC1CB5084CF79C42376D68268FF53EB377C7207CFEA631376CFDCFCD207A2B10A3CCF2A6DFDA0CE55E15479A50730BA664EA4A09B412B3FBE6BD6E3D0E81AF22080D8E94D685225F2F69B39B0AFED4099702A602771CCEAF6DF0AE8C7E7EC972F883AF6AA711DE81AE0E83E5494B6926BC26C8AAC103BC030749BBE655BC85D85B39135A0D3D5AF23026357E5E4D30103D012CA37E59C0920278F9E3D84021011E0C3AD7FF90A677905FFD78817E4CDD36D20DA46E15CB48351CF468C138C6F16EBDCAD4A91692285659A99D468949E3B53FA0CBEED3BB148ED404DD6D1BD65CBAB046F16A633CA0EDED57A3B66FD8B36297ABE19916CB604F1FB08589434C8ECA083877AD3A1F799C41D4E187148548C7414469EB48E0623363EEFA18EF0160A71EAA3534C81FD171BFB0F604FBEB14BFD178F640C4FB79B79093EB8BD11E81DD6E3ADCF0E7B2EF540A8C14C310849FD065CBF97D027880AB6E81709C4594E6965079EC77F823F22C1F41BA5D46EAB14E11E7931AEB2DBDBC631F0C764A3A84D8D9A32809A1F18386CD583C2F86BF644C912A969656E6B215F0C8584695C2FD559D60289C12C9642B6F9B9E92E3BF5707321C8D8125680A026757FD487058AAEA659DB79AA3AA0A8BD4DE34A5C412FB534B0C9FEEC86A49E9A2942C3F4F6A2E006DBEC02BBBB7231FE9104D170B7A6DEFC30EC60BAF66E8DF7FC2725AF9CF347871DA7ACE0084D13F98A6F42E6FEB6F7DDBE30FEBC3C8518FA81E0D233AB4A5EE54D90E64C4CC0D82E6903253AD3500DEF856B50E46FD59E3AF48BB3D0FB9AEFDFD8BF4B588A1137205855BF16DEEEEABD1005A9FFE0BC1E59612EED56A544A0E5ABB3480E066FD551A273F2B04BE332F3DD1096F73D7C0D4992DACA9CD3EEB256F7C9729D1344978978701B307402AC9974257A2603A77DCF6E0AA186B7AE11BDAB8B5E85196922739DDB109E7E0DCC80305599F19B90F5D0C0BDEF9FC8B443E46260A8EBFC3C8633DACEA35CB51C02E1CE6E87C788744FF47F2BA48FE8C73A3DF66A9B7752CC041D2A0B89DF7306CD85AC666A71CE8F38ADEE5E9EDD9DF90639432BC2EF67664FB02E388B88E95AEE0549578F7398A18296AB9B3DF35A9B497C9A41D0042B5B66C593E353C94E3D8DDF031B3A3D071409F92498651F86047F1656665FE076730B3465AD551F7026CD30B938EDE716DAF4F85AA3FE6AC76EA240861E4E222FA034B18AB54CE04C476ACFFCC4ED9B79304516E37F2A1EEB5116FE4A81A73268254EF02E85A82C6F921C73064011A421F3310389DA4A05E28AA87D3EE9D2ED5551BE90D1BD58935CB38FDEF9EBECEED1ECCE29D20D2CFEDD85F4AFE0DB902C615EFCFCF180098839CD6EB7ACD8927B397EB0F0D70B19D0D4CFCDA80AB4A5DEB950101E7724C9D848374EBFC97EC72D5C30C6ACD158CC864F5168E1AFD4C99CED7F8343719454357A33C3A519001D76055F5D95F13365E1F7FB97674094CA62986DE4A0D87BFA4BEE1E655C3E72736A899576262EBD782485EB7BC4834822E004379A971D54665CD498F1F599E7FA4E7041392D243940698957A31DF79CE06E2B6DF3D5D37E6B94D81B056C129C35CCAEF3438C5104E1154C6BC976936EE6622CBA189496CC62F00B4B087ECC6256F125C840DD54C364530A159FFFAB8DFBA9874DF3EEFFB1943489101DB83DF904B7E2E3DA5AEB29A9714453D36568646BA43D102189BFD90D473CE5E5E213B5C6118CC22AFAF826EAF6536AF5E861B6C832553C3A7FB1522CAA688792B3E47FB5E9E1CB762D5113B5FB8726D166E3A7C7EAC734E23BB44754FDDB0487BEE9312E738E415BC66DA00276D3E3C48606D733F2216BB322C5BD28F90A35A41B0F3C56F20F53C923E86ED7629740B6EF27CD51477F140E1507C9162C508AC4DE2CD6543E6E68EADDCBE026FA177CDEFBD91ECF8D782B480E52B8C180349654E495BFFB2284573A1DFCC21FF7046448D6D7E5AD3743D7C98E4C56655E88DAF7BD293961277A5283620ACC979C39EBCD8B59E9683A8D84D361A904DDAB46BC06C64D03B48CE4356A494AD4786C9859551B52EF99229C846B8F9DDB12C0130198CE92468F103C8660A3FDC504C749E89B7247C9C0F8D8CA4CE188D1E03CF3C3BA8444D96C84006AB4572C45896D5F521447610C0A12EE91AEC667368E3CF88883E9F4DDF456812AB0589EBDA1D8FAED0CE6E3CE7389C7559993D3192ECB2E6E3D17E900E2CD1C9129440294467036C82D1261296FB479441CBDE0BA2EC5C4390E72BABA6B88A349FA5A13F5AB49241A8DB7C0BFB12DCFDA0346CC3414041DC78D50D44118523BC34C07B3E2AD92A918B96F294E8AA212C65638A3D3A869EB90F334AE7FCD387034F00CF5F6FCEEC7C9A0F5DF4028DC63A1AC408D4570656AFB0BE4321BA047B998F24177BE997B0E47C2010656BE55C84B685729AE5A3230ECEF2C92CB660383A989CBC9DF9B6EEB8DC2577D12FE6A3D0989E3A60B88422D42BD75F1A7AC8391D57B5268BB41B9ED5C4B0CB9EDF76454693FD604B1F4B2F6425A71A1C8A587F18691ECF2DA6A6EE366D50E05239655D02A4CF110571EC706F9E6A6F059472C39DD2D53EA9F311A89D735E1B8B19953849E0689E2880EA5D94E3D97FAE414DB347ED1B26EEED05DF3C7D8FBA6AF4316E79F890654CCC61D6549524A51783F2412E8EF0E37DB33D6B1B2BC9ADC84227866AE18AD9F987FF8010717395389BC163072A1A2E8082D3B5372758911477DB0DDFE254867A9B417186CE3E400000000000000000000000000000000000000070D141A1F2448656C6C6F20776F726C64 + +description = expand_s requires 23 SHAKE blocks +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 15E04BF6D4209B8C4CFE8AFC2BBE6F9DA39072DB9496502939931B5FA7088ABEE3ABB33FE17F89FB14AD6AECF7C21C5BEBA421ABE25149E51E28C6D6FD5E7ED14EA713C03B8CCEB9AA6AFC671D638DDD2C2572D02C5456C9A1A60C62255784A63500479E7EFF313505A01D7AB7ABCF6F380935D633BCE23CEA4FCE9CF6155BBE562CF9F7B333B181D14466024E5DA6A91411F818C643ECD5BD70671CE452ABA3A408F02D48AE9999B2A36F23298FF8F939952775CEBB7F2F044045BF0EA5CA015EFF456D54FB76F63A224602A1BA8D46A35305EBBA2A566BFB50894B87F18A19DE5EB3E9555B9279EB0193B2B557DCEA6F1C94E1220AE6B6C24A379290659C21B876C243649E3C4A78FB29D0B5D9A465019B3F3C33497C0A275CE714763D0D0F9D2AF723E0A052F7776F8731C5D17348BBD1E451337F44BC9D62500B92004B9900E1D22125453639B1F26DE264774B6379377C13EEC0E40BE84C363B74477E2333B690CBF86E57B8FAEDB3423E2275491799E208DF1C391AA3E894594952F0BEB23C84F32ABE7B816A85EEC59909712FF932397B697343A117A3C8BB1E151E960690803A4217CCC623E868EA4D998087D50DD4E0B0AF610ACC18B61117D0678E6C979B7A2C3A6BDA0B0DB5BC499DCF2AC036CDBA0CE4852796A15FF84E352AD21F0CE536379A1B0DF46B10BC6EDFCA8FEA1411F361C905ECBACDEB2EB2B94E61B6785AB477BEB2C0C58BB6D7E78FDBB5A1F26D750112195497C352FA080F28A5167E38F6D6FEE6CCA8891A8520A3B06847FF4AE3D198DAE3891B76EECB09929A57241DAA4345972785CEECF6B5FC9E8E68E371F410E4EDFBAB52A1E54FC296580EB3A21A7AF6A744A0ECFD619EA3DCB483793EECBC78F30CF4104B653CC5FCBCB1AA8263C44AB9B7FA3B1D736C9BDB9DF748F97BB960ACEAA7B9C37C6244A4D668C1C58E043D0D39B944A43E70528118B2A15756540F8198DFBFD7F52E15DBBC5CDF0374C5115161260B0EE768DBCDE74AEF6D0FC4804AC442A5C4DCEE799A452CE651C6FE352C8CDE2C74122C5F1B11474C60D85F7647C814BC1262DD822D4F9E3FDCE17A8A47E6224FEB2D9AAF7BBB8CDB2F25AB8D1DFCAA1041887B9079B47137F1E9C0510F549DCC2E82FB49BB6A0D365A0C935A31032E698589B30C665BA95B32ABE45D14E280DE2073BDD0FC1F461177775468DB1EEE020732996B677EB78C7BDCB87B4B5E72EBD6AD684E4D3E8293304F938120182879BF1E2915120253ECF3A0B0B49F84CA5E895DFEC71995FA1A23ACEB15F71285F55E11A477BCFC00F76077BAABA21853EBF7065DB5CE1C33391B9021EDA07940A14E52DD210ABB41E0B50B79A06A0E8F09666931202464E963401F6C24B750156990D57C403A17D8A436AA4795538A795D7C7B724D4FF65153C1E1E7FAD09C4511072B5A6E3A35FCBB0C09E0AB7250D6A00848D60B7168FDD5E9771C5D9D60129DC7CA5E572D430ACB0314427BF2893927D784E7A617CD9420429CAA9CF037E774599E763C57E3AD3C4C79B44ED8CD28B8C16D2F788E25F3A0E5F277952A984BDFDC0AE99B5768F6C778E6926EEE4DAA3FD706F3CEED4BBDEEFF037392FD47AED9FC68776EAE3E9AD3D035554EBA56FE2569DA14488D03F0B43EE510F25636BF986540D845C9D73A541C7B7A3BD0A3990C6CD1EF2BFEBAB340B3976F7622D1D967516F75E31F3D182DA8873623B832474E2BD77E0884861B1F36B803D4A8F462B3708561B849E7641FA0B7875A36B6BF0EA3DD04080DC3C46A3FDC098F3C3449C86DF2BD7D8EA7B76FE6B9963DF28287C0B1A24B2C1252D7FCBBE2AEE5723D0D393482143D257EC1C2897387C0C4B4447DB8CE671FD486281A91F86813A659081451CFA0C15876E34A406A48A3094098562F851B31C19A3CBD87816B8DFA249B75090FC6045635F71DF6E8D2AD374AF393126E5E7FACB9AF0495CA7D581522185A2A1DE1F980599A42C1B2C39E345A24D9219C7B8CF8A66850E5390DE8626A74664A0478485444A4628FBCA04F46EEA77C8DE9ABA2802FE57F4C92E6B80D7686B0A7F075235A6A0117E79236E9D89B82F1C483F04829FD640F66022533F6F76B3579E07A153EDE6398E5012BFC6B87F7F83F4852AC8C886CA1FAA1042EB85783495A9FCB4D0FDC47F9EC15651C7CDC2484058CFD2BDDD914D1A4D35C71925AF84B0022C3E9B620076C2B9DDBCF852E33AF25D6FB6B2949186279478FF2CA73B993AC55FAA810F877EA7E0A2EBCD9479C3C52AD185711890C5646746BAE35EE294D6B1DFBFD850AD844EBDDDA0C50D636E0400FA156ECADCBDF8379BD043F5198667D04170E63E4D6A0C6958779F419BC052FD49967121AE74F328F6ED9402A4C7D20CEEC9FB48298C388687A99A9565A34C20B94FA29FFB843FC1E3C88B26CDECB7509A1BC368F268F8E122127BB4F06B24C8473D70CB1A073C0DC99619712B6BF9EFAB676E5A8972F34AEAB43F2D3E83789DAF462FEB0779CC2BE735AEC0446A7CA42A6E58972AFF8848084C30B95A09F7A7E17CCDBED6AED1DF9343D5CB36D5FDC72294AAEA8E1D9E927821A719F3CFC6825CE8C7D5C910FB049CB9A35EA66A8C281909A7EDB0547CB112D4C8D00F554470C8EF4F44B240C8944A3D34A064974D92C01EFA7FFD5DADFD9B8C15DB3C5DE3905F84DE751F2D327662A97B6486A41D50691C83248286FBB354988AC277031E3B411CC74DDB6FE760B9BE88ED92E508155CEC068E6 +valid = true +smlen = 3320 +sm = 0C75BEB55DB356144146BDC41A5FCDB1EE2FD32FEB0F4A37458617B6B02CF5363B96B58166AED22162D54823970D25ADE5E22205AF1D387F455A30429E53A1186B03D5568785893DFE81FA7FB28AD50F8B547BE838D4E57B1D6AEC98CA75161F3DD8AB552B417BC573495F1E59B3AB692EAA7F4D30C6F3A02474A1D01D156F3A0CAA81C2CA9B2C65D1619C148B226463428085F7EAF1BBCD491F1BE100C93AD8A9C33E57EBB76F8B57BB603534D1930C1BCB17D2036D44E7C37D88FE3CB0D285E0F8D275D8BB44827D7CFD23EA6468CB4AB3C53B19DDAA2E4E688A33A4303E6A57E1DB745F3DB0DA5E3301C4290B4AB8CB42A0F8B3E1CB63C29FF943CC4DFAC41C8A9C2ED987D8F3012CC4550E19CE99366F0700341B86103A1FC81EA1FC0F49C66EA638319F1BBDBBAEE13175E06954CE060870055C5E861BFFCA5F706424891627B43E92C92815CC4A093BF794BF528024DFA927998AE93898CADF1F2D680A4F26E77E749DB84231EE587F3EB82A6EEE42498FBA367BDA88C7A066E25C47453E1269DE4EA56ABAEDC0D2E7040636F8207FCB7E6273F2F43F557CB56680214CA86B1D5F6E774D699E9B7E85D32B7C0CBE31F2E8B4188B7C8BFBBDA09F1C70018F3BD73EF365F8BBBA82B461B78CADB3D0CBF9CA4B418472CC424860DC81DD2549D3503BF93E293929F7F83C2D576709CCD291A8BD4C7D9B4A9A5F64A8F2F20413582611888FEAFD5757F851609B5C7B00E9AD93A4BEAE2E21B1F65519C7D068A29F4B2DB0B2A61E676ED721B153E2A7818BDD624978D6F71C582E04EA2BB81C23047B463C808E3F3220F5DE8E161E6B37336BE5E635F0FCF31777C341C7F46C5144E1097B90E44BC8EE6672CBEF59924D841D7FAF0E0495122C98A1AD1004165AB89462137D9D35330239C438FA864EEF96467B6F3B17DE011BB72B57C38482EB527DEB3EDAE42DCBBAE0F2202793C76E0458B60DDF7A59E0438CEE78736C4649C3AA96D798A4103471AE967E93DC657848BEB0F22D997E9E6F97CE3C42BBA7DA71F3BC7C95EFB98B6739F5E88B37BFFEA5E6CCF39AF2A97223249F89655BB0DF36C1A6C88B613C1E3768C1087D2ED5662E12D4CEE9D95F1F5296902CA56EBE44E37B74E9782637E4DB29B300CC217E9E2258C57E8FCC4DAA69F39BE21F6E0FED143CA5E7AAE26057CD622C14AE735F020833C75B9DF4DAB14A5C75B1E1DABF4D3075E0AF0CCE8A7D85E0B32E1E4F361D9653BA38DB3469D01A957716C851D70EB39BBC5747E7A5A45FFF6C6E3B0B8B9D76126FDE2F65E956339ECA35FABB8F28F905C81510DC1D63F3364FFE9B0588F37DDAC2630B3700CD627B48B747364BC96DDEAB281AB27D5D591D5CF240FD7D5B49B66C8E48072A816D5A218359B1C030160CA0BFFD77CACC7C583E4363EBD2C3BD6BF0F8ECE2B2B5651B718567E36D5D5266CC38D85C453D169AAF0EA1830EF7B944F5997B0FF94E6444CEEDF5B5D5288DFB75CBCFFB789CA8613268D659320F449E3E4D75B03A1AD31305C08AA319E8845A05C21D8A20B4E84A46AC75A83674C2421D02D9FC2F0808D42A46A247D84DAEA362079EFBF7830C4C3CBE8FE47D31524704417590631FC67E93264E5855D8CD3344E65DE204A5EAD08148AE674F8423D2468707BA27B4BD14CE3CB51E60BB5C35016BAEFFFEC2ED017C2517DD18675A5B8D9E0055C2E9DF3EFFD128ECF88A2EA1A302154B2B7E3268068501334B0245FBE10651A2EC76917B82D5DCE274E9570902F42A76277DCE44793191BF15D2A3AEA4CD7B403AEE4C0FEEFC7D8121C686398E46ECBAF55248085FFEFA3D9A8E96AB48A7DFCDB7BD9CBA7AF25278A449562AC1CB5084CF79C42376D68268FF53EB377C7207CFEA631376CFDCFCD207A2B10A3CCF2A6DFDA0CE55E15479A50730BA664EA4A09B412B3FBE6BD6E3D0E81AF22080D8E94D685225F2F69B39B0AFED4099702A602771CCEAF6DF0AE8C7E7EC972F883AF6AA711DE81AE0E83E5494B6926BC26C8AAC103BC030749BBE655BC85D85B39135A0D3D5AF23026357E5E4D30103D012CA37E59C0920278F9E3D84021011E0C3AD7FF90A677905FFD78817E4CDD36D20DA46E15CB48351CF468C138C6F16EBDCAD4A91692285659A99D468949E3B53FA0CBEED3BB148ED404DD6D1BD65CBAB046F16A633CA0EDED57A3B66FD8B36297ABE19916CB604F1FB08589434C8ECA083877AD3A1F799C41D4E187148548C7414469EB48E0623363EEFA18EF0160A71EAA3534C81FD171BFB0F604FBEB14BFD178F640C4FB79B79093EB8BD11E81DD6E3ADCF0E7B2EF540A8C14C310849FD065CBF97D027880AB6E81709C4594E6965079EC77F823F22C1F41BA5D46EAB14E11E7931AEB2DBDBC631F0C764A3A84D8D9A32809A1F18386CD583C2F86BF644C912A969656E6B215F0C8584695C2FD559D60289C12C9642B6F9B9E92E3BF5707321C8D8125680A026757FD487058AAEA659DB79AA3AA0A8BD4DE34A5C412FB534B0C9FEEC86A49E9A2942C3F4F6A2E006DBEC02BBBB7231FE9104D170B7A6DEFC30EC60BAF66E8DF7FC2725AF9CF347871DA7ACE0084D13F98A6F42E6FEB6F7DDBE30FEBC3C8518FA81E0D233AB4A5EE54D90E64C4CC0D82E6903253AD3500DEF856B50E46FD59E3AF48BB3D0FB9AEFDFD8BF4B588A1137205855BF16DEEEEABD1005A9FFE0BC1E59612EED56A544A0E5ABB3480E066FD551A273F2B04BE332F3DD1096F73D7C0D4992DACA9CD3EEB256F7C9729D1344978978701B307402AC9974257A2603A77DCF6E0AA186B7AE11BDAB8B5E85196922739DDB109E7E0DCC80305599F19B90F5D0C0BDEF9FC8B443E46260A8EBFC3C8633DACEA35CB51C02E1CE6E87C788744FF47F2BA48FE8C73A3DF66A9B7752CC041D2A0B89DF7306CD85AC666A71CE8F38ADEE5E9EDD9DF90639432BC2EF67664FB02E388B88E95AEE0549578F7398A18296AB9B3DF35A9B497C9A41D0042B5B66C593E353C94E3D8DDF031B3A3D071409F92498651F86047F1656665FE076730B3465AD551F7026CD30B938EDE716DAF4F85AA3FE6AC76EA240861E4E222FA034B18AB54CE04C476ACFFCC4ED9B79304516E37F2A1EEB5116FE4A81A73268254EF02E85A82C6F921C73064011A421F3310389DA4A05E28AA87D3EE9D2ED5551BE90D1BD58935CB38FDEF9EBECEED1ECCE29D20D2CFEDD85F4AFE0DB902C615EFCFCF180098839CD6EB7ACD8927B397EB0F0D70B19D0D4CFCDA80AB4A5DEB950101E7724C9D848374EBFC97EC72D5C30C6ACD158CC864F5168E1AFD4C99CED7F8343719454357A33C3A519001D76055F5D95F13365E1F7FB97674094CA62986DE4A0D87BFA4BEE1E655C3E72736A899576262EBD782485EB7BC4834822E004379A971D54665CD498F1F599E7FA4E7041392D243940698957A31DF79CE06E2B6DF3D5D37E6B94D81B056C129C35CCAEF3438C5104E1154C6BC976936EE6622CBA189496CC62F00B4B087ECC6256F125C840DD54C364530A159FFFAB8DFBA9874DF3EEFFB1943489101DB83DF904B7E2E3DA5AEB29A9714453D36568646BA43D102189BFD90D473CE5E5E213B5C6118CC22AFAF826EAF6536AF5E861B6C832553C3A7FB1522CAA688792B3E47FB5E9E1CB762D5113B5FB8726D166E3A7C7EAC734E23BB44754FDDB0487BEE9312E738E415BC66DA00276D3E3C48606D733F2216BB322C5BD28F90A35A41B0F3C56F20F53C923E86ED7629740B6EF27CD51477F140E1507C9162C508AC4DE2CD6543E6E68EADDCBE026FA177CDEFBD91ECF8D782B480E52B8C180349654E495BFFB2284573A1DFCC21FF7046448D6D7E5AD3743D7C98E4C56655E88DAF7BD293961277A5283620ACC979C39EBCD8B59E9683A8D84D361A904DDAB46BC06C64D03B48CE4356A494AD4786C9859551B52EF99229C846B8F9DDB12C0130198CE92468F103C8660A3FDC504C749E89B7247C9C0F8D8CA4CE188D1E03CF3C3BA8444D96C84006AB4572C45896D5F521447610C0A12EE91AEC667368E3CF88883E9F4DDF456812AB0589EBDA1D8FAED0CE6E3CE7389C7559993D3192ECB2E6E3D17E900E2CD1C9129440294467036C82D1261296FB479441CBDE0BA2EC5C4390E72BABA6B88A349FA5A13F5AB49241A8DB7C0BFB12DCFDA0346CC3414041DC78D50D44118523BC34C07B3E2AD92A918B96F294E8AA212C65638A3D3A869EB90F334AE7FCD387034F00CF5F6FCEEC7C9A0F5DF4028DC63A1AC408D4570656AFB0BE4321BA047B998F24177BE997B0E47C2010656BE55C84B685729AE5A3230ECEF2C92CB660383A989CBC9DF9B6EEB8DC2577D12FE6A3D0989E3A60B88422D42BD75F1A7AC8391D57B5268BB41B9ED5C4B0CB9EDF76454693FD604B1F4B2F6425A71A1C8A587F18691ECF2DA6A6EE366D50E05239655D02A4CF110571EC706F9E6A6F059472C39DD2D53EA9F311A89D735E1B8B19953849E0689E2880EA5D94E3D97FAE414DB347ED1B26EEED05DF3C7D8FBA6AF4316E79F890654CCC61D6549524A51783F2412E8EF0E37DB33D6B1B2BC9ADC84227866AE18AD9F987FF8010717395389BC163072A1A2E8082D3B5372758911477DB0DDFE254867A9B417186CE3E400000000000000000000000000000000000000070D141A1F2448656C6C6F20776F726C64 + +description = rej_bounded_poly (sample_uniform_eta) requires 277 SHAKE bytes +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 9EE65680CE782748DB4F70D31A92D596ACF4E42765B63397FC0F9A3A7BD14A461E0EEEDABB392ECDCABC513F482A5F10F76820A9645E6442917256AE56447F2F8C6B18CB3FDDB0E4614C0B4ED978DDC9DD643D2E50DE1590D4EADFAAA25073288A755F41B37FBC58EBF0571157F556FE7CFBEFCB5EDE0FFE3D048A17119C97DAD0E117C6CB6F2FDEAC4F5BF206C8A656B9FD3AC1EB9D710D37C2141DBCD4979BE137FA2D850A3A74C078A5EC33A5683AB4DE51E3388165AC6B150C04C226A47D59F438BFD1990AFB0FA19E58FDA7DB15F0ADE85C9082214CC72811F915A36AE880342C1DCC3A6A436A2E853F1F7129C662C1D256DDDAC97414B333401532CAB2718FF96AA383E8317A4BE545A4C39CB0EB6FDB50D88CF15DAC05EC3B0D9DD1EECDA8CC60009FC5D5B49CDE4D385578F2E34BC528E9413EE5DF37CB31FD6EDC69185820051F4ADC4EBCB76D3A178637CA34B830D3ABA914D8EF51B159569BEF4DD534E2EA92CFE780468407EE3A89008216D00C9BB7FEF5A1F68E189D1275C06296CF9CA436B330BA091CDA2E4B3621CCE005CA8E94C4A2BAF1E9ED3A001DAF2B44E21F0B7FDF7C67DB091513725108CCB68536128F73134DC6EEDAAB04152BB1AB8AA8AB4D3468A95717CACE46AEB65AD0555988FE3E9EA41FB7517A62441EB091DAA319A4FC8F575F993166E5BFE9D2A6FA5EF942E4B337D6CD42FC7EE6F72F847510A3CFE93E3228F57984229D74860EB5463E9106B7745819BA9C42517E3388ABCC9FA80BA11F91F1F383708D2792C89CAB95B4A6BD8BBBEFE697A2FDFF194D3B1E9343ABDAA49918F84C0C88447BFE82C8E2ADA7AD7072863E6C0884D9B0844F1DECC3784F05AFBF3194E915A9C49616458899CED8C94323755909A2716A30D435A099082DCF1E3B746727FF61162F597EF2F9CC0E31A0D97DE790DEB57C841128DB2D550CA2D5F1BDAABE91E455ABB97760C213E59CAEF3585DEA740D3FE2ED3C3C26FD508C0BEE3646F0C50C782ACDA53391D6DCEDD472B1F338157CDCEC0558F7F8EDEF74AAA640AF7944BF23022E3E174A0EA4D2375F353B025CED1C99971B8A8782D452F0A856CAE5393567FEAB9A3653276685F3C960351B3E62F085560E34B115B39631E0C6271640837A39A4C3D96205F2F28630C7265A98501079592BC34AFDEB54AA7048E31A1DF4B42491C8A2F15F0A838CAC3CCB960AE20FCBBF97D77CDAE3A025E9D9A390415CE128EC6137D12AAE51744452B99AE60128742BD0AEF168F49338F614CBE9D669256CD06A671377BF18D391CD128A552CC23E4F3122354B4F42D5F2799F524EA82457BFF18909F38A1D49F6DB3CC09ABC802E9CEF7A7E5F9A785B9616AD1053E620AA7DB6800353C6A43AC34451682275915449D81616F2B615982730C6A4B092B19572640DF0E8AA2C11137EAB0E487001748DADB69EC14D6285397992AD95E6CB1E3F73B6FFF23B90CAB86FD04A040E6D40B045158152EB5AC030C1DFB98D95DBB45BB8E3BCB31FA7C735AAFC5C5E0094EFB605A91756E21282FB5F7A47FBDCCCE484349E21A6A2F8EE580B58F8490E1D65B3DE1A5A2E3DE23C6D9ED71BBB846F6FC14E88C76B176B1912F7F499CC0F411B90F3F11426BBBDFA4A4627B2A759F7802801403733E04BE8A2F571D80DE9F358290AB690A6A8F99C8144890A69150EF48F891D18B1EB3AA205CF8345E1B9D43C757881A19E6F35C633837C3CD4D3F58E5C914966B6AB5A01BA41E3ADEDF5154A585C7B76C6072EFEB1BF4DC385B191CFA4BF124783E4287FDFCDA30AD1ED8D40C808B674671C5573257885DFE024DDAE157F984B2C24BA99A2370FECAE3FCA493B29DC8A63AE577CC36415C3B048DC5E9A87D29184A1FD1610CEDE05DC1F7F375B3C56579FEC60D793658AD2545DB1D13E5824D5225D28A7A19BDE4798ADE127221F8E8A6157FEED44B66F2316640DAB02E5CCD41FEBAF57D4B55AE7F8CF96548B783E31440148AA0CF2C99804C85C42908165F836B444A229B7946B1D4FA1F6B525FFD07C9F2DA4D83714D1E76E5D3FE7B115F09BDB7D773357D2250162B473C44762B1DBD06BBC5BCE3C32A7CB6245F1923C9D3DB0A7F55F2237C61DE0D79B676EF419404D74F019CE5870CD4893C4D94410B130B4B235CDB98BF94685085710E3147AF44F6A26880CBEADBDC01B278DC639F2FB45493E266793ACE30EA44859A580F431E06134B02350BA76CA78D47F10822A5E26A9A34E7DF8659D1A2F883A6D02D592B1FCAC68BA148161F9958D526AA6FD43E252C9520CA3F19E88E74066D7CE666B90C62D4200D7A621E4A1B3CF379EABD8A77F3A5628FECEF578650229DF45773AD474B9729746779C12CA343576CF7F4F97E243846042FF9B50C225CF005E7CE7821C4F78C3F454C2665D59FDFEB15096F2B5A79A94BBC9939AF1FBC4BE3CE68906C7E7BD8759038BAA0AEF50308BDF2E6C5B29FF69CAD356F00E87C5BE3BA439E303E63C7C2296F09B40C349BD82C52B07C93E40B7CFBB27EB38FE08C517C49D5A15076185AD2255E5416B8C7E0C6F3690D4D1E6E258AC88930B71779A7DB60575222DB84E27E5F6A8961294D8B65958516B2F15494AA7A48B193B293E1AE600685BCB21B562D58F500AC631F1B082B3A396052FA2C7CA5B7DDF9845CCE8034105ADD6E9B97067408690ED49598F70C42B7BDFB1BCE089C6B984F9E987D42B776A960C8912C9A2FA6025198083EA03E9A8D05828ECEDD0EB0F2D +valid = true +smlen = 3320 +sm = EBC6B035EE412836992FD32CB31EDEC14A0901EDF47B682F79EE0EE00AB31F56B150E3C0AD7CDB295C635F1DBD6271B11B17710308DAAC7EA40878561153C9573F09D21DBC3A2481B377F8F34118053568285FBCF5B1D6481FF12E52E5574A62B70368396A0036D053E8C43A30B51085D0204F8B80ECEDF6A4B663647BA18753CACC8401EB046B05B5899E547438E9A303DF6DE686C9DC1FBF9697985BA1014A86F3F3351813341C7B52D7B1A92E01A4C11FA279B20E1972B0463B33098610ECA011B1CDA8461FA20923FAF42487EB36350F3D52CE71FE48F52FDD5161886FD76FB49426C1B9F8E2A364533F74BE1062E26AE641F29735389BE8EBE31E6B0F59AC5BC20462ACB3DC24E85A1A0F1F8C322465CD904CAB50549896BFE500E2C57444297EBB8C569BF5BC9EF6F78773B2349F50893619C4879D0DFC0CAD871FC7CE0F63ABEE084426ED70B0E4A3A163985FD210DD4EE1DB20AFABD1DA9D87164DE031D46A4662934B3617D729368C52C8ED7ABF9101929B210227B8189E02C018C3B2B699C25055F8E47831893CA0E86C154B2F62005CCB49D886C874C5AF3F6FE1126ED41D53AA258B7E8268A699609A7EC1F0E439F379B69A00940B1AD63A735AA34942B97214150B55D74311C0C5BEEADC5A28571B7B9B8BB685C6E42173DD71315DC0E864E6B967177AD9EFA00C2C89B9D27A1F5776317A8647388798DC1977E4EEEF5C80920F12F12245DCEBB74A5096485359F47331A352E2B7050775F6122FF7F4883E09791648084D91CF15682060733AF18F10F872C22DBE55ACABD0B4EEC5CB6285C5F009FFB354AF539B5B3E64011CB752FEA88A1A868ABF72FC26CFD65F99BD1205DF61F377C95BE80257D10704D6D12EA41E6BD8C11E3E07E78D3BA113085C0B71639E08E1D9193F5A21B992484B5A4851D0E568F9BAA3AF9D23FDF389885F1F65CAE6E1C1138BCBC1F2E9518004790C2F5DF8B7B90034503D436C3385B1653498A78F5E7F5BE8B181FD8A99F93BB6BA4647BF9856D37322D1333CF5E977A3ECD2926ACF280C26CDB2D998A283FCBF587A8ABC5006D5055474DD8644F90413DC7CF6D1B2EF6925342DC26ACA81F8439824705E400F42ABF61D1C505EE79941FFA48AE45A472AB9E2C01BA12D0638570B7B4919D413AE11F7E0EBC11E718289DFF4F4195A3E12D92A477D59DE56F0FF61E09596942BC1678E18AF15337C5945096A5ECCA247BC03F4B649F570AC6FE66318CE0FAFD080FEB92B4414DB54E8A1F1914094484251DEBA8D407C3A81BBDDCEEE08832F6140D54F04C3917A5B7200239B92D84211D2E551FBF4DE38D1B6C12BD1131F08A3D1BE59C1828E6873B51F91B3C14CF30E3C4DDB7C009A1830ED1957BF2B7241D6EE1B1E5A4A4996949392AE2A847132C64AA166DCFA8FE231A2357321E3106E44C3A2333334B53240FFCA65BEDF30952C7F81D85B3F8F4299F86FF9993CFC21E66B3B96387BB2E52F948E6D5DC25F1B83168C45092C5496B229317535B8B3C9B0C6DB6E667EF941B8C0CDD042479E1A9ED31A91CB6CEB4A34D31F0216082DF33D1057E6EB97AA28B911EBDB9E7A557D3C7F1C14460F134DF2C49E4458450908CEB277DD0483B7DE858BD035B339A9E68D9585AA695DE7A59B806AC7392F81B68F960CB71FDB0E7ACFEE27DAA350591C9DDFF5A4D6B93817A9EBA93FF228DFF9A8148C90C0D54FA5BD9F4F844B829611C83A0D1695B05428D430E5A42B94103F2EFA2782692B77C6F1532C334C5609323CF173481EB3C3C8A7AFCE8B87CE68A17DC88C4DFAC633FD2C3D68BC383B272D8292FBC239DB7AE454A84F1306BEDEB5F93200EB9A9C0897A47E40EA2C3AF500F30DD9CFFB4FAFF594DBD23F1CE23E19AA38FD85BCF1FDF354FD7AAB1ED82FCC908E5F275DD7A74738348C3A1B037C19C787D31F9DB1655F4F069C7B26A0D00C507E5AEDF078B7D33FF326737D25F0174BA6383C4A95EE7DD524D8CC7789C77113819E4686CF8EF5980A8B2C83E0EF141AE07D2C9AD4DDA887DB56B8066D4F8F138C9519AB30F662833AEE8B91809ACE2CFC1B8076A37A80AC966E994ACEC0F1986F563E28F68EF3C2783FE3E892BA8060285BEBBDCE7FFB661A210531788D5838B6619A789F0688AA3B5F68E646791A1C1793EEB0D06F3782995D3AE731B185D29A7A6EBFB0556B959268E48E71BC8C726874F3127F4B53B80891445604202529F62898DE839C0BE7E7EFB669C5E53F64996750F754A26E95F3826AF92B03D55BC0BF4F30AC4E4725A8A9959BD815A68EE67BD624E8122586A8365346E224BB38B1C917BC1868153D14CC85D1573DE9BE3CFE03BE5A0BCE13B82048AB49A46AB507DF9AECD843A2374FC8E074A6152039A0F39A6766F2CED16FFB143A8169DBD680AD7FA95A831293D60AC41E1A7501D6EE7B42549190BCDBEF70C29BD48C9FDBC57A77D29425C90A5E9EEB55C24FD458228F637AB06FB334DDDDEF6A530D3322A66CFDA77B32DED21802F1D904048E1C4F76AB23BF0A2B5E650A9DA8C04FA763C63353ACF60D56A08B1E6F27971AFF5370F1D91F0AA8798009B39D06CAD8717BE03B9C729EBA35424C053D18792EE5CDBA4BD3EF6AF1F75E4F1887C194E9B0EFB2E8DB3F27CF1C48E66A70E4940CD82C2E0F774417923F611D541A8FEEDF8553A9F3F18135C6BAB6A671D2C7F788FA3D73541CE884358C7651122647F59C5B2B4DCB0183F7F5C0A30F231B6406B006409B2496BAEEF47095F63159D145D0913E89C5D2BDDDDA4410D25ACD6D068622D7E4E235A5140207C385B95D01188B948657D4DF0198C79FABD5731464E958EB458FD4F1C75CB51FA7B01008AF6F485D31FD34F9B994393F99C48507C0125B7D2D056875A5B1568E92DB318CD5CC61526C28A3592AF6F33B8747D0B442BB3A6FCE1E6652616F090A714F00213C2E025A8DDC0EDB29C1F3B75867033B4989D6B36D5637D2E3DB0ED6C214ACB196C4150E94F8AEB45E2B404F1DAE338C73CE087181A8A3D919610A71AAEE2ED7733547B15B6495F47E796037E77D44960F962A84557BA68F8E6B2150104FA5AC800E6BBFD18C519BBD037C64C0175ABC1D6C2100F9F0A8E2BC707BE87398BF47025F715226F03E85B93694CB9753252207B974984A6BE79DBD800C16B5F652B9CE2D84954C292A9D3FD0CA5AA18A15EE6BFBC06DA1404096B65260C39018AB259C06B3A638E27ABB901F2A19D8A7A3257DCF3226BA94B24668BC9CF82D95FAE945A4D055BF5948F0F1E85526CC8D6F92B1C2985E1689B8339D5C1E5860F14810B9FD5FD78AA4BBEBF7540E74E01EE36822A6EBD810A102B86BC49DEBB37AD99D45DCA9C12E062E8CDC3CEA19CB6C62DFB8F04041BDE1C063D0E7596E73B47A0BE7A4FF4C7C5B1196EE34999A32887663BB3728FF133037FD90A319F3C640C3E59AB9DD6FD9E344A3E98E13351E28B6650AB6457C54BE6DA4B50B3E4CDD1566FFE834927C32BF2B31B08D53618C3AF25124D6323BE3B8D3E656FF8E0DA14E654E969BA8F34023723514C29E5EA179E6B78C582CD2A852CE2B46E2FA29F30A2912DEDBABBE2C8B6AA5E2CB147CDA3CE25532044A4F5A5BE463CD26C7624C2858E18AD9562A6AB120C1A567F4B2082E15D95CBC430F825F931319F039188E127BE8D62C270EECD9306D070FC564973E424D38E9FAAACD12B131E0A223E70F44AE2D7E9B7518358ADBF93CE34AD05F7B84B7399F3E7AD5958066C79816773C6E35F654FFFEBCEBDC0D73EBFD9253C45D2EC350442007B2C1F8A6D24BF4641F083178474FC0CF6BFD27455F8A71C20AF9B21AC1F2CA02927408ECB3862AF0E82FA003693251B503D85950A28A4A820C95D524F00D797AF7066166BF86FC28175665E85E7E0E193D1793D572F9FD778E481620DB91E1F8E5F4A686CC3D11584202AC6F336C272C342E119BD23542C03E17924C0C54A518850F77DA9EB7CCC6E352E99ABF6079D1E5114922F597F08C63D1B2BFE812FD356901366BEC1E162D064549853D1DE25AD6153E2CBB3CC96E6611A9FAD92506963C25B2176DB560763B1DF0D34DB177CE99A789E6A413E50695C16EBD8F44CB3BCD592A977C87E9C6935E05650C121F5E5FCC656EFE6F8E2369AB7564392442F7D3C2DD30B9A5BCDDD769EE25E0278EBDE0279188768755CA50F7A0E06D05ABC880272D19012B411211DDA63F8FA4A971F9ACCD4E6374F17B7ADFBE90D2C8F671AEF7BA05567DFB39BB016F5654C7956334F89B9480E6905F3841042EBD0B60A1C7969C31D82D49046FD12FF1B74AD397C7824155A819BB667BDAD9EBE44C691D1D171F0BD494BA140CD8AAAE9C3EE0629D459DEA0CD76559FA79FD94808D804610C18CBF139CCA39EDEB86CB4A958387662C50F7CF1A4D3BD057AD259C89A713F2AA767325684C022C5E7FA20B1143A967B191B19247DF804945FA7012B078DF47A01D65C0322DD2AD521389A80DDE3CFDE5C2454A2E08E23F2FFDA6075C55683FD02CE235DEEE69041257350AC56A70BD3F35B3C1BF83DEC2AC7A3A8FEE847ED82F22E229A573A9FEDED6DFD697F3144823804A9FBB4B0F2C565ECADAE5040A123B4C637586D1D64B4C6081A4CA0D2F88B9C6CADC14767A8B9FF2FD4A4B5E6E6F707A898DBACFE2F800000000000711171E253248656C6C6F20776F726C64 + +description = expand_s requires 2649 SHAKE bytes +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 8F6FB031D69B3B782B7F523D787AC54D7850596BAB67E61A2714D525ABC9A79F6ADB7C28F11B189290E38C8F3B9D540D69740F7409CBD8BCDA65B1E9D20BE98F5CFF9A6EED47895A2FC15F211D26E292669CA9B9160363FFE75B98F253A5B2E83894C90A41189E81CFD8FC2008F8A61A2EF95A588745CEB7C882F2B53AF1087C459BEEB4AEBFB5974473DF6F40E21032D50D42FE6254F49769D702C2428CF76049657CBBA111E008FEFE1074346CEE7DCE8DEE3E41FA27760410BD30E7DFA638DF0716FDCC646AED553FAA5B05C49E859386AC336AC18E1003E83CA2C32F05E8637007771FB11ADAE058014C7CC1801476318D3908FEAED523A717BEB9BF91E566CB0E7F4A901F5E30EE77F25AB9BA3CE24A0D76D3C3C66FED21C39C51C2784BC6A68FE03E472D9A1FE73F38ACCDC3EFC60C063D7406C1BCC35333494BA361B5939E7008BEBCF1FEBA3688DFE5B06D0078D642EDDC8661F08136B5BAFA22044F35BE67F29F087F3BE2DF8C6238097EB151B0D0DF4F60DDF457D90F3D1C821A2C787E8E00816D4C00ED0EC52057499213CF6CDB9541BFF9614C98AD8BB8FF266D76BD071BBB070909F042F39B5BDB90EE8B5AAF2E1E6D84E2B5FA225E80E2462C04D2CDFBC512C440D5454E775F106CA7E09AF864E7CBB05779F5093F739088EDA7E36E058EFF7E7486720CB11F873783D78D0EA356FE7ED2CE3F759C49420CEE76A7125F9396586D826E40371393C3E206F19B8EEF1C45916CE21917B5D233750E07A7A0A19F00335AFE7EF8B8716B83A67C7D68709B2BD3A7FE85C756251E40ADE43F6D0F851FDE45783AEE5809210A31BD36755172ABB1504D661E2D7E90D94CFB36439EA334E8086888183995426958941967B212364E5E7BF94629F69ED98C92162163C5252432FB7F5F2B36D592430392CF46E0E17C8FD3D3F5C528F7D4BBDF4AD9867485D0ADE2961BBD99B5142C060CFF53726E9BC018929DC8BFE041996E2293DEE8B248107C57BBCF3B2136EE9318A38F642ABAB78B5DD22CEC3AE2C599CB5F4633F6BE360ABC18D492CEEF7AB015B97DAF1897623A6C771ED83D49FE71BD4D2F547372E3BDF09E3EE77CB400D272BF825B3D8D9329B232840017A31286D4088CB5B8EB84FDD086ADC655E7582D082FC690557B86083F15DDCC9579BE8B64C7097B1AF6DC060CE6757141464E50D0F6361D791F770C5A1DEF7181C97AE1AC8BE32B65E12451C6E4A881148D6D8160DD6DC92C2176A5B4CC044931629447381591BEC097A94BAD60440F9C22E5FC8B222FBD2EE4E0AF0A332D345EA1C66B985205F0B35164EB39BC8163BC0B2259A8146574E6839B8BBD90CF49E23E86125B4F62016F8C6E136D5BEF7A825A376343BA6E3C1AE11A8430C20087F570FA74EF61FD332900CFEF73AA5416A10D97E8B75FC6C280D07BF2A6499189C98532F92B25386D0DE9CF9A5EB6AAB3FF372871B8A4A7E7D6B29587DDA2D9E0096EAA9E20324B3F64B7DC37FBA084B5963973BBBC05CE8B354B95A7462E857848A75B93A07A9E713D8D095466C191A9FC51828207DF2D1FC507FDC54AAB6565445D8C6852DC763E289E5B6504350077F7761B005F885BBBAC5FAE4ED1DA70D5FC0383981C3C68C744CD9974BE2722A0FF50CBDAFB73A70839E229C57F596C23EB945DCC1EEFFFCC2248E22E9C147E62A478FDB2BDA3E23921416D5110155F0801D44F1CABF1576F8BD627A8819D74FED427826CF885C6D8044B5D5EE185CDA1B6614CDED45711278199B8ED556629D1BF1DC6C8A0B936394372325CF7A3DC4BD5E297A7FAD279F412A8D5755A0D30792FF1C400EA622F38CE432B1D02FAEAF0B5E49A4E617742E055BA2EA7C0A99A12BDCDAC2C5F5293C2DA7AA8A382A2AA9E8CF8625CC495ABEE59FA5D39F9C899A63D7FEC4610D987AEDADED222D22C494CBA36938E093395506611D8FBB8A8CC407E49ED2AED093F78FAFF66055D344B75D83E6BD40C34E970169B401536BFA16C39CF21DDC40194F7251FF36909C4DF71FE3A134AE51C7158FB659FD64AC952E3F84BB08222F7802379A0153830FB45ADE07C86B5378B71683144D78EDBBB3817AEE0269286508316E0FE42366F437CF33DD20260B0644F2E6D2BB4062ECDEB7F1ED89403FEA2355023B80F93A2A4327D358F85A1FD47C74B7522A5FA3DF19F94ADE769E40BE63AC8F5C9C709E0D32746FC9C5841C58B16DC5A8257788EA46425708EEBD5436940D4EAA3B501CF0660918130DBE8886F48823CA9CEA52E0542CB83E692302524DB5120319B222632DD3701DEAB9DA5AEB57C92F92329809328D8A16FF12D8BCEAA510BCCC2E27CFF912A5DF48E35727276AC1A2D59E2059A0FBF6FED323007885C50279B87FC8E300E63AE617B076DB9604BC0283EB73E5B48417E6B6632CC51F72D1E3BC386097AD048A1F4DFA0438FEEFA58FC6B631281080169C9A77A8F6119E66A6A8F8ECA70FBA2A5DEEA676E72D9944A6D02ADB84786CEA3492A271CAD65E0DA6EC11F0F2A7A0C63DC0727C8C5E77103BDF414DC7CCFF8D1569ED014FF76378EE8EBA99B91AAB788F536F92AC1A9D3199CC49C9081230D3301AB7441289B039A58ABF7A4331A068E7D11813F4BE4748B808031302B25BF709C66B00694CF05FFDA6E37B5CE425F0E31454669612DB90E0698AED85FC4EB3B3226AC43D37BE921A86F2FA05E67D8E9A420709A388B391ADF639CC1E2331C263470D4C607CC5837D6A1F9079FB6748233 +valid = true +smlen = 3320 +sm = B55EF66F65C4AF861C0C4A9404422784FF219DFCF4B1565989FAB2EB5F9E89779A8C88471849A4A0653BEB072B9BE59123F3D5C3D200F1B1E43AE3CD2CB7C46BC55DDF877E8F12602647F369F6F3EA297B44D1E5B3ADF136769D588E1299360EFE3E52A21970BE043C29578B8D996B2A4F80947282E463269F629347199708EC4A71747CD0E25A996E8C1C41F55F1DA52703EB155E413340B9B04A2A7596B50EE2E5885A197D7165B396EC6203122FE7029DF1097BBEF4C79846DFB99901E70E6C11B46F7288A4EE98ADAA1FAFAD60987DCBB2A586A504D03813C0268ABB240B4CB3CB3C3866E8392B57A8AA600DA00DB1A0CF30F9090D324FD5EEC1B4E8A6BE500576C9057D344D83A9A94AEA2EE10319E91273ED91E24C4D41783AA5D03B79C426FC922A914C59C62CCE192E5CDFC096C6B229561A03D21B409FC862C18D55752B3D8C8B79B9C0C1FCA00589809039CA4F83208F22C415B9EC2059E21D099C1A5149EFECD815500CF80C03221D9A30165FA6B6B52955F970C9FF5BEC404A6E99848C56F5C8EF653663995FE3C9E7835D25CE4465555FEB1CBB42AE6AC58A172D16C22CBC34C6170FDE45906C2BC93CD8535FCF1C00DA91DCE35EFA0DA3957261EFD4B4E4B7837DB93D243934254107F2B7B6A2DEA16A1EB2446811597CB8569EF0477EF87632E496042F175F4B0E82F7D1A1E62A5000EC62639002A429088F89287F1825525AA25FA4F21D82BE9EAFFEDB3217044BA1F605988C7C2FC1C5A5BEF3EA1F358170B4A5482D267C74D2BA7AB4011CA431E81F871990371FBFC6353DCD2C8B78319A865BFC6AF081FDBB20F85646D03E25C388AEA77EEB7880F2BC3C0C3A75AC5476CE9ED84A456B668EC930509CED087C1AF7EDCC0FE233E86BA914ACF800C68E9DD4F82645ED6338B824B12EB0950D07CDB86301EDB64F245EB93363681DC5D40CDCB9E1777F4B852398AB92374C40B890F1EBD0A60CA7765A8D76DF7F9E2D7E0C5168E591B293B87FC9E8DDE9ACD9A0D29EDAACABB904436C8052FF90ECA628F5A41A8E5B51738C58A719DD7EA5F7DD3B4724057086073FACB58D674BB004F6CC7617A972D348AEF1707A411A1A12C1375FD7584CD601F9D7B9AE9B9C6F209A7F83A2076AC5C29FE0E4021C2222176C10E926D3AD7FC7CE50E47480C621496AB04BABBF643180900565BE9FB3594EF994E96279DEFD17AD104989DB8897C93729AA0381084D50F1ED218EB245285A04942688EBF7DAC914FFAC4B382C68AD076CF03246E7793AE10DA30347705C878C34EA191CE95A5690284552CAE5759598D7E98A232810641B86B36DD79EA28B597B66E623C74EA9A838C48A8584D9B883D24A11D46E3FEF10AE82F30FF5D30B7C25CC731EC19286159312DEF6A5567856FF7F3B33808A6DC09EC05521A252A9D794658B4397891FAA3E7C3E45FA8DA4B190BBD2CDD094C2A00A9B5D2492F1BAE28C7642F3E082D86347C3944811D597A284A3CDCDAD2DEDBEBE491E583B48D5ADF8A841B5ED4A0DAD472EDF3815BC41F729E4F8E8B365A6E4764A350CCD8B737BFD7A434B2A24BEF1A438E0CCE806A1ED6834AF4EE5CC0D115070B2348080DF0CAE01AF9A2EFB2095CCE7845566FDC25255F55245293CA83BEE29F9A51D9123262CB2944036B88A0C9CD6F46DDF7D0F9C6A26FA0024611FCDE29C09C0EC779902D23E3B1770A4530772918054776DCCC59FCE9BD9EE253062E1BB689D349B4FB9F72C469EE8A555AEA259F948A0344EB931C3E1F94B6D7A70925E880804240D2BF23E0174810972953EBE3161AF39FCEA82041BEFE007BD66392DE0FC0A03FB1FB35FA307DFCE0329B77AA8134D5A8671156D61CE28EAA845824CB87D62AD2F57819A396D18592A7EEE75DC91BA3FE23FE79BB1AA4C424066B90FF8C747565B9185D4F112FB66DD0020C92245A18CED444125127FCC97F7CD862CA82CFCA9609DF97AD48023784610E2E5D61B41BC8973467672E9D55D3532129CAD9CC9710A83AEA3E50909FFE7C6D537928877E694833F42FF8A1B2EF0B0F2321B87848B8E7E86ACC1E0A9844DA116CDAC7BA502F1A24B4A81FCE236D2BAE5C5DD905F2CDFDCC276E3E2F8A79E1E18E53A80A3810C684054274DC140C713699C131085BFCF24ED67366C7A13CA20EF736A6B6E81C3E01198D7A62CFE1A3301701E68CD2916AC3F0992C71A67D123E90DA45B3E46C2DFBA24EF2D20AC03F739D27A102905C78523139E9420908D041255C03F0FD62BFCB5BFA0373CB7B8D4B83B20EE721F9C299C4BC2AAAB248F2BA0C03838C9C01645B9EB24DEB906E16DEB9F29FF4AAE14012F473DAFA7C6F067BB7DDA25AA8EC375270D6B3942E254655DF3DE4E924BC03BB6195015AA2647BD94AE885BCD6C5DB820F8AB1688F6957DBC2BE06CA28FD54F1CAA566233F4C90DB5B34EF865BF6C0D8CED9C4D9CF4C7A275580586B8D93F56255051FFF05C1CC4537240BAB98CEC70C879F4703A95DC269348E7142A2FD7D33A705E5B38113D5AE7F089DE10EC88F62DE0A1C8243ACD0424C9C2CFEACECBBD19B34CE3A35270AB3536D6BE36ED17A1B1F5219181DECFC266F301E71775E0FFF5A4E3AE8B3326F495ADE1C1CC77EB30C9FE8DDEB65AB5FD02C5FCF749C76672D48FC75A41FF510AC17A79BF536761B6534F8C86B3AF005D3DAB70C62B13826BCD06AF0FBD09AFD05978B3882BE006F8E7DED0B7AF37C54F93552390655B6D24F1DF1938201BAEFA2492BA2CA9885D9475DC6F1CDEBCA90EA78B56AE945BF89AF3067624A1038CF7B51C0008EC7654346C50EDE20CAB0AF90C93C53A3C83D10FC227FA89528C8BD244630F7389E7C6705DE3494604D87E9884BEA2809CD48D9A2E151E6865F6EE2891DBD9257B47EA6E96B4CA0F800F2CC1C7DFB9423E6E106B8BD14C1E846DA036163C22E2A8F94966D790CBFC81CAEA81C59D78E1C64B8DAC60BD22E9FF6C772FB801B9EBFFF2F03EC2D9303E752A30C8256F9BE65B04213D5D948025F5099DA506EA202F94B2D6722A7D52612933B0D97978534930E2876A9F4CE21CDFB15F1D53D879CF23014F0972E1F13B5545B955DA450D39895D95283B98BEFCC8FB3E4F344CFD18DCF6B1480C282E91EAABC81A5EFF80952DF44045E2578FCF465412176714C5380F744BAF5A797D422C837363F620BEC51D2983C476398EEF3BE3FDE3497431F3F2BAF9EA0CC05ABDAF8527816097E6F6B34324674FD5240ED293DA43B561687B83D2B4C1B020509AC978A8EE23BDC2210A7B7066EDCD79459ADEB3BB88EDC016D504B06E7E16EB64B7EDB443922BFFF0FC0A8AFCACD0B9FE37AAB251F78BCC119C92B2D5B8CA3D2FD7E676389D65C66719D59CF4946F9D6826042A1DD603D6222F30A6D4140A1A1D7854B0E99F48DB73CB980DBE2324A25BF4B2963ADF37B2B1A643A794C5E256337F6DF9517C205AA380720808CC7941121DBDA09D26746E6F0335F9727F2673D849A87DD8B15ED24CF9BBACDB934AABE991A6B26629C3A16243FB5CFA6BBB883672975947AC90E5FCBCA684C460B1D84AB98E34E789EA6349DA807C027F78A9C4846E0301B0497AD11F9EA087BD3E16096420C7B662AF11A4EF16682F32B473CA87127F263550690E89E2B4435116945FC50ACF8215239A5FFE902CCE7CA78FFA35A0EDDF0C32EBBAE8AE46864C179410698B4474FC0556DB384870C7C5557F5670F7FF0BE583FAEB9D78A990CC62DCBFC98AD933F671369F180AFEFD794651CDDB20F951B4FD6D4CA8BD8AB9193CE30A50DC4AF87D04C4CA5D0D85B35DB92C22122BEF14E3105E347CB882404DA9754BB30B61CE3240C60C97C080EC9BEFCD4A94CFE4A585409E415406D0A83C702480AEBA1C5EFEF64DE1EEF32B285E812ACBCD13F2A6880812C37F8F7A082F9DC130EB332450ACD9B4A56C5F64E65166EE94291A78734754506943EE6B872040CE76718C25BCB07E0BF9DACA73FA42886FB0067773DDA68DCE7B33E45BDD13FD68F3704B3105E79DD9F7D8A3761707F59309AAF78642091C9A3BCC3ACE81B1EAD9BAA5915C95F9C2F6DD79079A065A6DE158004B13A23775997B6C9278C25975BF5799943BE53B81FF49CC060A7E0B53E4B6E89E137E086CA8BF8AFE4A3B6B1C1E2658B42638D7E8746DA4697E749C3FE1AE3770FC5FA6F2B5A747EDE6A5CA8DEAD6B65DC4C44198F827446029592E80C8E895C2AD72E2792B21DCE1CEC77838AF238D2F1E7C413DC2C916E7DD431AF3CBD666AFA2A0A1EE08C7421F69E6188DFB3D358FD34C49D37F56D8A1786BCDB104B3FD22BE6615013F034145C8AE39C8707388414340D5770AC70452EB3A99F264B2CF6D926A6641677B7FE41A42CB3C9F260646775FCD653AB2C3C651E217A71179F379AE9F2181B66FB72E0DCD4CA5B75BBFDEBE497AE66F69F9AB09E80B3282B893ED057909460D1C073D9E885352FEB51D367E71AB7EB237A3DC05063FC5DA78276B27D32A22B6B0C858637FF0B8436D56BEBB511590F810AA9B6DBD5047C67714C12736C24A98F7E9550988FEEE669C39BD7FF95097A8E938EBAEEED34890B995AF165EB230204378B5CDDD5DCDF71B44557180909FEAF902162C38608AB0BCC4CBCDE3FC343B44C2CAEA11586A7179000000000000000000000000000609121F252A48656C6C6F20776F726C64 + +description = power_2_round returns a remainder of 4096 +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 2C3C585610631E4701AE30F2FA3DF0DA7B607281A51396D7165AAE1D3310295E5C3A745556801D72105DE3BC8FD78B2795EF9FDA94AEC21AC6C4AAFBFBDC15C3A7457042ABB83C07EF25231DD043B2B2142702430810483A0A7BBBB5566B88F56B00C50595AB6D514B052982C48FC1D26C50AB7D2E1FB1F97EACED92BDECF5F3104BF8925D2AC61921C8D8302E0CC09511FDE2573D2611CA46B2D99363D7CDBF619668A52E39ED1E24CFBFB1A3E96072D2793AF668E5BBB515EE30EDF9FA09CA1846818E08D46388C34BBDA5A74260829391BB6B400FC8135DABD794C915540C8CE60A7DFE9009E74E719C0A56D37BE47EAC1CFA521B9E29373EE8B97120D83E055CB56B4363849C0269252FFCF0AE6A639B67341224713E4268FDE76536E8D03174CF6AA01AC2DFE02365E5A06869A7A8CDE00A3393D8B52CBF9AE8344CB2A434B05C2B9CABF874EBC99E78EE3CED0EB91EC8F6F16917B02BAD75F0D39A1F410F8AA00F5C7BC82D8BD05BDB30BB7996BEE309EA49586764D0CC22948B2CE40E930C6B778FF7BC539C6A6CBC2535920872C231F4BCC6A7A89CA587DAC882985936BCF262F395B9AE50EFAFFFC58E4075949C534911240DFAE3E9C260F653DB490924B14C4AB8F9B7B43E08F5397DFAAF9E9CA3C8F93EC33C0AB48327D973069F6442AEC0DE4FBE1DD6B2EDD7404A2734124E0CE48C9B98CD5B9B8B65FC160E759837D16FAEE738C1966FDF4A2350234AB1C26D0E338650D9D70D7C0F940F0D38AA1477E432C6FB06F4324D1E694AB5E4469942CF70106FAD04A15542991E690AA71EC35AA94349BDE683863BFCCE90A2DE87F0CBD8D4C2423B4ED21A2682F389D384E729C7E6C25E1B37F30F73BB3E4D81F830DE65C3FFA80C08D1F6BCB192F2CDDB521E81DA4D25D2B11A0F918CAFB08536835C8D805CEF2793C5CD2C9BCEF094D73F23449E887FF694A752A27E3A63A3F48364FF2EC968C34FB9E626E2A7CB96532786FB433540A5BD86ACCF115A16BB49775ACA8146BCA7E91ACE59846E470134728327649753795B0F245EA687C7B7A0C561C8B22AF988009BBDAF1FDC5B751A6B12B2135B48E496D25F039522BEE1C05CEC64EBFFBAEE9B8F416F205B3396BF6DC7F4406B2871A0214B5343CF6391A2263C1B35C8CA938E82F28A1321C855AA31F49FA28338526F6A346B55F7B727FB4BCCBDE8BD26B57255E17681A947DAC526BAB6E01EF754BA3A90B1C33CE0C0FD644C12B8A1FDBD8C783E44144EE775075AAE7CC90BB894E235B28D4F8C5B205CBA876F4FF4259AFE8B9AD70C28D8FF817198FC0F9B763CABF4BD0E6363897F8A77A169295CB38DB8EAE174F739A14CBF40C9AA8F91ABC576DF06105520020DFF81A980C291618F8E4279F377C48D9FDD5A2C4FB609DAF4625C3DC9D522251A291F7A147A830603000F9AC0AF61C4AF065EEB9AF571DE45D39AD72CA3C6EACCF69435CA33F01780109517CF0E6F36A42AB41FBAC539330AEE57FC58205483938425863E738C8E39471D6F63B619EB083040E35AEEE426806C80682EEB0A2E017A95B8DA8DCCF50434E3CF87C61DB77FF30D2444E8E60113D1A6172E07497A58644D9FE7BFA6091360E2FE8A51B8D464A83819BE5989AF00FE70AE032C583BA182EC244FEFBDB34777CF7B5085083781D3A4A8CA15F440576780789CC0D5B353720CAD97EFD66EFECBA3B5C454D4FBB16FCA383C89F777A89BFD379D4B0D35FD1F8CE33383151C1C477121E5D8CFF5B3A7C22D4C80C5D331F839D614B384B58D9158B4DEA9ECBA84972A174773F5A8A25AD84DFA4CE892544DFD0052CEE2CFFC344CC5DA1F45D741FEEE54C5741526D8D0C0BFD7AF01293EB5770F259EBAF36C8DEB36835BD320271679C3823FDE3C9DFAAE23BFF17E6B64413373CCA7B8E97B31F7D065D308504C8D4982C3C68E74DFF7130391CD85AEE63F586AA4F2FCAEB1387CD6B1FEE4BE075ED5C6342B5D03EFE4454F11C635B54EAF4766F35AE247582A0D05E08CEC8A6C0026D467301DFE8D51A26241FDB456ED065395B3507FC552F3C8CB9666588A8B50660D13FCFA3B18958CC4DC5BB1AD40A720D9845210DBA309BA2D6FC2DC4F053F9720C667BA37DEE5951B9BF5FD752CCB1A34EF78E0A84DD1533D159D702A03A81AAC02EA300F78E577FC8503A18EB5DFAD141679398A65EE78420442FFC13DF015D2632333C3C8318D92646DBC3C8FDA23972284211A112EE4CC1A182BDC37FB4E783F5B425E108FB5F2BB54203DC91A2473E7C3BCB2706697F4DAF9733EFA48C23FAAC6C65CC15B777A1DD8A7A0B8A8CAB0AA68C66DE36FCF738B048549B2C580E0C959165EB747E2E4A25D510C1472DE6DFAF21D74CBBECC8B0987A03A3FFD94FA369BD79F3F87501E632078D0CA0E1FE0B86CE095BB6029D100DB99D3CAD88C9D7966CD99986910AD28592C3908DDB31AC8C199ABA896CD394F3914A757D4C4C83D20DE7BE96591878AF60285B59709C8D89AF2900C6D1A47E794D4A15082520CDEAF899879EF20DCE75CE7C1EC60B472D51CB514F08284C1AD8C41D007745A1CEA2A458391094CE1416FD232041B0124198687D7C544A055BEBEF3B8B6DDC8C5218F80108332315B493E42566DBB2055468468C2F2F6B5833FF8572C5967BE4EAB1D49259C3FC54938D36363639732546FA9E93236A31D2D6AF6307ED0A3D2AB1C64D172C855F3C081B61D8A4F0843BCBB4C44999519F5D6A2191E589DA54F328B4629EB +valid = true +smlen = 3320 +sm = 3252C634B9EE85C05FB1916F7C3685A1C663A34C1A64DAFEB3B97B21F069FDF838F9851F17CB09AD664B4DBFE549430B0FB07D22F1D2FE8129DE85C2E29004A4BBAF382966EEF89122FA342CF7677FA2C2672726E3329154F9291BBE472E5A49A8F3DDA70764A1AC81EC6BFEB2799EBFE86B0973ADAFA63E5875CA368E8F654F636798C68814606A9B19051666EA9824CC60FD6ED13FF68C5B93B805826643409BA223EB0F932BC6FF5C75BC25099FBD1C6E12B512E97AF21EA0C610D9C00C090D5B1160B1FFABBF02CFEAE290274E95BB75E6A7F8CC73D6A3E511786652142085BBF0665E3DC4AC940E3A0D49FEBDEAC7F6A35D6BFD93551669EBEF0EAE26A212BA8050DAEB06C47A96E22EA48993A702EFCB3FB292D5A2F2B20B5B2B2B6167F5BB7645CA1D8AF8747B207319F48D42A54D3D267396844272ACE71E6431D013C6A308B900C5CFDACF40DA532865DF57BC8626B15285A1911C75C6B7F44621A4A40EF5B4F79C3C9B5D7C26AB76E5EAE17754766819B7D9630C4D973AB85CB721EA7CF88CFC5157D025626AD2A3D58579466FB68D585A048CD311CD87CBECB83079CB71BFF87E38EA69BBAA6883BE0CD47730643E52EA3E21EE8518935D6D79D764B7EE2AE3F68E3334EFE45A3306014A22CD88A660D83980939A1AFF7CB49073EE2073F95AB783669D849219F5B7F2D862EFCAF43B45AF00AEAB14ED06C96FAE0232E4573ACD74751BDB207A23C5FA4A55AD3C28A1914F839E47202E499AF7D443D760B8A08344BBD92080A9218AA7D24B534C71BB6699D3FFB1C61B64E5012778517D4EBE01B6B089D51E702F1EE0CE02D22FAF14EC630E5DB698C0F366BFA8649BADF678BB01AB7073EA50A9DD62F1432EF809760801C6CD8145036526DA0DA5B817B2B066565ECCA455251C0F56B2BCDFD09DE20915524F12D3E0E7E1C532F39BAAA7544221264D9766C49B6F99C597A0773C7C37FB91AAFBD6C261C7EF3A26923254996314DA7133C704C446A8023928300FBCD8BFA1D8C5718B4AB4CD5C3F7A0AEB1CA5F955825CF53D897EB1C4A8EAEDE421A38A79ADB5BF5251F452F9ECCD1C1185BD9EB45F0BDA34EE948B6E060935FD677C7252D64B60DC1B167CB1FB8A1D1C4F31D5947D73E67D436F4653717E330D37A72727B9178B0976A0F8BA25C21CE6B33352FEDBAF605C10C68BDAFD38C7AAB7B8AF606A7C16770B2A3E8B21D56CA2862178E4FAA98F0FD341FA99AFA2039FE69AE1E1A6D5A0F2BBB262136CECD7CE36926EE09FAF17A36F08388A922DC7A565F2E049BAB08D05E9841734578EFAC0D0A8EC8072B30A3CE18A7F6F9E57FD3A857CFD94A5155706714926EA98FF97402322FF1A436AE7E5C5933CDBE1616B2B229BF338F8FA500EE02F584F3762E35362B7C2B5FF101EBBBF4388609604AB32255D3E66FF29413BF9561AFA6B3CCC87FF1133A4D1F678A708C8090140F55B9D25BCA9F5A12F0B5D027FA53D97107E2835F1879B0C9823839EE51643346BCCCAF31DDD7B2D21E7C1DD1AA7B2F2A23D31DB5B20647F908F27E85041E5F442437B18E70E1CCA8FDD6B6B305DF8EFE9BA83D7BC19309BF699808391D0C2FA7E89A9C88F72667118BCA4413483F1951D6C2EAC994A0ED825B23A501DFDDDE2C449063940A48AC25CD36CC1E9B8324B8A42AF3DF49C64E9DAF2EADDE511CA44E8FCF3DC710F85D060D9EEF51A52CFA0F080383D77B3A3B5879F0AD387243B78B434EC5244A7185FEBBB60A981187C54CC479F7ACE7D61E1069776E4EB85BA8E2B42B6B64D74298EB63362E542929DF6A8FB4468D68DCA27892B6280B8231B5098B01546E375571295E86CD5A16753FC8394D22895C12AFDF891E11B867FFEA49372BAED8E820496A7CDE8A1BC4EC545A01E56DD2C639B9EFA3537D1C4FB79A7F03FE8AA44F708350A979B5195EDC49C0E1A12C2AEAB77302371C394A2435F54A3CD2011FDEF514A6E037AE3807C7167161278ED46581C52360BFA14B88CD3A7D737D3EB00447CC8D0F46A2FCFE80FEC05AD9464CC3B3C48975DCA9764DD16067713F2CCC72E29A526F1CA33C1F54FB4CAA2300B8614C229BBB632A905D75760AA8FADE939E8A33857C57FFE5178C3BF1318D082931A18596F5A666866B956D7385737C8731C4CC26215398C6432F47A9AB9F48CDC827E5579354CF7ECD7F2ED6533C1D771FEBD34D25BC0E71DD30483FB9425CEC7F8ACC23CCCB8D08FA543125C8DFF14C6097E06ADD4709D7892921B1F69905661F9020F35267ACA4D99DFBCB3BE28810D4EA53B8283DECED4B221DE1046096AEB85179AED35BCADFD342F993DBA2393FA13AC2FBED9F361D5BF54874552C68FCD3D96650D28F6F07F427876C434A71D72B245D37D4BA7EA7DB2C69CC6198DF0EDF7330F805C10BB70F17D22BB0F456EBBFDFB126FB172A0522D0553B9C85E1BFE41C8083D03DCE5F4095AE837A3AF5F1921AF474544F68AA628F74B203B744A36F0CAFA5B99747EC09BCA01F8134B7062E6B8D2A949CFD21013AFC82093EA42AE917F2843DDE2ADC1140CC4A981BBFB8CD690EF3E9B5AD79DFCB48B441BCF8AEA715EBC3B42BC90FA98EC08CB7A4C9054350E915734E31A768BE190CFA7216F4CA36C3D387BCC30F6544540289D4749164EA19D152F5CA77D5B303BAAC1476060B97681B0E35A1E9FA4AD3B230C8226666A24D4A54CD97B4528A0DF6C4070D7CA1B43F9AD213E94A8523812F663D7EA802837CC757BADE7D35619314F97E232F029CAD77C4B8A53B9770BED9BC7B87A0D0D53B3E3B7170653AC832E73021082FBF15CA74DD1069F0EC08BB50BC0FAEE60AD220119433E80D4AD0E962B548DD7691CBFA5CE76FE47DA08A5D0D3197D7BB4E133AC0BB74C59F3E167FC65BEB5FDAF07939991D48C596EEFC78B1A52F69A39E11BDEBBE056B10C5FCF2E86AF6FFB87708CB8C0315DBE641D7F295BEA6A9DC83A8C8B704832C383C9BB70847F3C1227EA907B12B9AFD0DC6F4D2326C25F238C1728E69878847F6CB590BEB592F24ADE9120230CEECF9E1C05D474CAB335A3FE04C6B30792B91F8DAAB5651E58FCBB5F79AD69411C27468B63A0398E26D0913CD8F5EDDA187EE2077B3201215D96D7F628B207E2DA29557F0B81F21EE66E331EB06BFA6B5C78C19B0FC8F6FC2CFF999AB25C18BFD7D63E3918AAA4C3DC16203F706EBD63281CA69B7F2964A24E7DD946BB213C1408CB14F9DE7B4D74C3BEF3A3E571BB4B5F59C7C7D2AC404A45BE0EE191DD45FAC05402FE4D238385EF6CFA3F19D9F48B990356E8C5A4491FE339DDD120B2804C8B51AF093CFD66917C2D1F56CAC546DA1B195261E9C54F988878AC76B64D4E13259A61C1D45B6F8A7943C40A57CA2C4E3A48B3056F9BF8BB30B9AAA3493E4C73150D14A0DDB97449C77259CA370CC889A82F4E74AB04579A5D515FE2BED5689A56DBCCD3EEC1304E554E7AC13F6F95A88716B27A1C8A9F4FE148DB5BC4C3F74C9148803B0AEF6002CD0F4D6740FE7C2394EEB888AA33BB03CE580417D55F7C6D7405685CAE1AB111ADBE13572BA9DC5A4BCF618435E61E13B056EE47D601D39FF2ED9094C5AA558CF4805E90593E16138025590CCCA86E57C1F983807D391AF9F3A5B7F3D2DC25726A0F39E5DF5AA8D0A763359AD4827AA2FD511D3409008665347610954734E367193EEF3BAA492D0928686D944EF2158B6966C39A131B06D091781F4A2242B8BECD7E1DD4EBC30F06A773954154D6104D68970CCEBEC727D4D157EAF456CA7F1AFCA87FA14DD07B4DC510E800898ECD5E250151BC82B97C821CF3AAA98D677FAF56DE996D042FDF0CD8E8EB44A10CAC17B3789F32BE8846F2D034D435390E921618166C995B917734B9F096987BBA505AA1AAA722CD8D217A5D23050CCF786FB3A7744B555B243547018B3C162AC81A996689AAEE7A1AC6CDFCA62C906DDDAE7F162BDC125E4B920607C0E43C80C5B59C23FF9F762A265463B87967C027D43FAA65584A592ACEF698188B019FF2DBEB552028FB1D67404ECF940827E5C4AB63F4DC0B3B49B23F50CA74E08F204F218EF490DF434CA51B57A5F0127343FBC393DFB66AA0D83F4BBB929A3C98DDEE8FF0299FDCAB059D4ED9382E098DF497457D9B25784A53E779C4C73D7ECB2ED3639522CD8BFA958811740E8D7695D084AB0E597A2DEA8085C536094623A395E1DBD25A246DDC73EAB1C759417530731BBDFD4DD94367DCCB9AC3FA758C35B7B30C62E7620DB96E2FCEA2A91144A6876BDD0471044271B9C625097EAA4C4268547E7D66D1A1B4F998F23763890CD4A01BA45E99CD6174756AF676F27DA6FE6B1F0FF648845714F46C02A917716E150B3812B2CDC64FD59E11C3FE2BDC2327E8B34DCA44BD19A65B74B2AC65B7D1A16844B8CDD87D6A2C4972CBB8115E05FC71B68ECB7FEAC54CE4AF5A8B40CEB26DD97C066E7004CC1D7549D6E1200CE2DD133A25AB175857BF7359BF84494392A9BA4C1C9923F7884AEF54512D5F4C9D5E07F0D9FB564611DF44A2988950E8D3FD999462892A66D63578FCA06DD06A8F1955CFF3ADA5EF22417FECF4523D6616D27842E23D94A2E31F81A9ABE9FF072E507A95BE04618AB3C3CE1A41498CE72B3B4F7C96C3D2E70000000000000000000000000000000000000000040A10161B2348656C6C6F20776F726C64 + +description = power_2_round returns a remainder of -4095 +mlen = 11 +msg = 48656C6C6F20776F726C64 +pk = 2C3C585610631E4701AE30F2FA3DF0DA7B607281A51396D7165AAE1D3310295E5C3A745556801D72105DE3BC8FD78B2795EF9FDA94AEC21AC6C4AAFBFBDC15C3A7457042ABB83C07EF25231DD043B2B2142702430810483A0A7BBBB5566B88F56B00C50595AB6D514B052982C48FC1D26C50AB7D2E1FB1F97EACED92BDECF5F3104BF8925D2AC61921C8D8302E0CC09511FDE2573D2611CA46B2D99363D7CDBF619668A52E39ED1E24CFBFB1A3E96072D2793AF668E5BBB515EE30EDF9FA09CA1846818E08D46388C34BBDA5A74260829391BB6B400FC8135DABD794C915540C8CE60A7DFE9009E74E719C0A56D37BE47EAC1CFA521B9E29373EE8B97120D83E055CB56B4363849C0269252FFCF0AE6A639B67341224713E4268FDE76536E8D03174CF6AA01AC2DFE02365E5A06869A7A8CDE00A3393D8B52CBF9AE8344CB2A434B05C2B9CABF874EBC99E78EE3CED0EB91EC8F6F16917B02BAD75F0D39A1F410F8AA00F5C7BC82D8BD05BDB30BB7996BEE309EA49586764D0CC22948B2CE40E930C6B778FF7BC539C6A6CBC2535920872C231F4BCC6A7A89CA587DAC882985936BCF262F395B9AE50EFAFFFC58E4075949C534911240DFAE3E9C260F653DB490924B14C4AB8F9B7B43E08F5397DFAAF9E9CA3C8F93EC33C0AB48327D973069F6442AEC0DE4FBE1DD6B2EDD7404A2734124E0CE48C9B98CD5B9B8B65FC160E759837D16FAEE738C1966FDF4A2350234AB1C26D0E338650D9D70D7C0F940F0D38AA1477E432C6FB06F4324D1E694AB5E4469942CF70106FAD04A15542991E690AA71EC35AA94349BDE683863BFCCE90A2DE87F0CBD8D4C2423B4ED21A2682F389D384E729C7E6C25E1B37F30F73BB3E4D81F830DE65C3FFA80C08D1F6BCB192F2CDDB521E81DA4D25D2B11A0F918CAFB08536835C8D805CEF2793C5CD2C9BCEF094D73F23449E887FF694A752A27E3A63A3F48364FF2EC968C34FB9E626E2A7CB96532786FB433540A5BD86ACCF115A16BB49775ACA8146BCA7E91ACE59846E470134728327649753795B0F245EA687C7B7A0C561C8B22AF988009BBDAF1FDC5B751A6B12B2135B48E496D25F039522BEE1C05CEC64EBFFBAEE9B8F416F205B3396BF6DC7F4406B2871A0214B5343CF6391A2263C1B35C8CA938E82F28A1321C855AA31F49FA28338526F6A346B55F7B727FB4BCCBDE8BD26B57255E17681A947DAC526BAB6E01EF754BA3A90B1C33CE0C0FD644C12B8A1FDBD8C783E44144EE775075AAE7CC90BB894E235B28D4F8C5B205CBA876F4FF4259AFE8B9AD70C28D8FF817198FC0F9B763CABF4BD0E6363897F8A77A169295CB38DB8EAE174F739A14CBF40C9AA8F91ABC576DF06105520020DFF81A980C291618F8E4279F377C48D9FDD5A2C4FB609DAF4625C3DC9D522251A291F7A147A830603000F9AC0AF61C4AF065EEB9AF571DE45D39AD72CA3C6EACCF69435CA33F01780109517CF0E6F36A42AB41FBAC539330AEE57FC58205483938425863E738C8E39471D6F63B619EB083040E35AEEE426806C80682EEB0A2E017A95B8DA8DCCF50434E3CF87C61DB77FF30D2444E8E60113D1A6172E07497A58644D9FE7BFA6091360E2FE8A51B8D464A83819BE5989AF00FE70AE032C583BA182EC244FEFBDB34777CF7B5085083781D3A4A8CA15F440576780789CC0D5B353720CAD97EFD66EFECBA3B5C454D4FBB16FCA383C89F777A89BFD379D4B0D35FD1F8CE33383151C1C477121E5D8CFF5B3A7C22D4C80C5D331F839D614B384B58D9158B4DEA9ECBA84972A174773F5A8A25AD84DFA4CE892544DFD0052CEE2CFFC344CC5DA1F45D741FEEE54C5741526D8D0C0BFD7AF01293EB5770F259EBAF36C8DEB36835BD320271679C3823FDE3C9DFAAE23BFF17E6B64413373CCA7B8E97B31F7D065D308504C8D4982C3C68E74DFF7130391CD85AEE63F586AA4F2FCAEB1387CD6B1FEE4BE075ED5C6342B5D03EFE4454F11C635B54EAF4766F35AE247582A0D05E08CEC8A6C0026D467301DFE8D51A26241FDB456ED065395B3507FC552F3C8CB9666588A8B50660D13FCFA3B18958CC4DC5BB1AD40A720D9845210DBA309BA2D6FC2DC4F053F9720C667BA37DEE5951B9BF5FD752CCB1A34EF78E0A84DD1533D159D702A03A81AAC02EA300F78E577FC8503A18EB5DFAD141679398A65EE78420442FFC13DF015D2632333C3C8318D92646DBC3C8FDA23972284211A112EE4CC1A182BDC37FB4E783F5B425E108FB5F2BB54203DC91A2473E7C3BCB2706697F4DAF9733EFA48C23FAAC6C65CC15B777A1DD8A7A0B8A8CAB0AA68C66DE36FCF738B048549B2C580E0C959165EB747E2E4A25D510C1472DE6DFAF21D74CBBECC8B0987A03A3FFD94FA369BD79F3F87501E632078D0CA0E1FE0B86CE095BB6029D100DB99D3CAD88C9D7966CD99986910AD28592C3908DDB31AC8C199ABA896CD394F3914A757D4C4C83D20DE7BE96591878AF60285B59709C8D89AF2900C6D1A47E794D4A15082520CDEAF899879EF20DCE75CE7C1EC60B472D51CB514F08284C1AD8C41D007745A1CEA2A458391094CE1416FD232041B0124198687D7C544A055BEBEF3B8B6DDC8C5218F80108332315B493E42566DBB2055468468C2F2F6B5833FF8572C5967BE4EAB1D49259C3FC54938D36363639732546FA9E93236A31D2D6AF6307ED0A3D2AB1C64D172C855F3C081B61D8A4F0843BCBB4C44999519F5D6A2191E589DA54F328B4629EB +valid = true +smlen = 3320 +sm = 3252C634B9EE85C05FB1916F7C3685A1C663A34C1A64DAFEB3B97B21F069FDF838F9851F17CB09AD664B4DBFE549430B0FB07D22F1D2FE8129DE85C2E29004A4BBAF382966EEF89122FA342CF7677FA2C2672726E3329154F9291BBE472E5A49A8F3DDA70764A1AC81EC6BFEB2799EBFE86B0973ADAFA63E5875CA368E8F654F636798C68814606A9B19051666EA9824CC60FD6ED13FF68C5B93B805826643409BA223EB0F932BC6FF5C75BC25099FBD1C6E12B512E97AF21EA0C610D9C00C090D5B1160B1FFABBF02CFEAE290274E95BB75E6A7F8CC73D6A3E511786652142085BBF0665E3DC4AC940E3A0D49FEBDEAC7F6A35D6BFD93551669EBEF0EAE26A212BA8050DAEB06C47A96E22EA48993A702EFCB3FB292D5A2F2B20B5B2B2B6167F5BB7645CA1D8AF8747B207319F48D42A54D3D267396844272ACE71E6431D013C6A308B900C5CFDACF40DA532865DF57BC8626B15285A1911C75C6B7F44621A4A40EF5B4F79C3C9B5D7C26AB76E5EAE17754766819B7D9630C4D973AB85CB721EA7CF88CFC5157D025626AD2A3D58579466FB68D585A048CD311CD87CBECB83079CB71BFF87E38EA69BBAA6883BE0CD47730643E52EA3E21EE8518935D6D79D764B7EE2AE3F68E3334EFE45A3306014A22CD88A660D83980939A1AFF7CB49073EE2073F95AB783669D849219F5B7F2D862EFCAF43B45AF00AEAB14ED06C96FAE0232E4573ACD74751BDB207A23C5FA4A55AD3C28A1914F839E47202E499AF7D443D760B8A08344BBD92080A9218AA7D24B534C71BB6699D3FFB1C61B64E5012778517D4EBE01B6B089D51E702F1EE0CE02D22FAF14EC630E5DB698C0F366BFA8649BADF678BB01AB7073EA50A9DD62F1432EF809760801C6CD8145036526DA0DA5B817B2B066565ECCA455251C0F56B2BCDFD09DE20915524F12D3E0E7E1C532F39BAAA7544221264D9766C49B6F99C597A0773C7C37FB91AAFBD6C261C7EF3A26923254996314DA7133C704C446A8023928300FBCD8BFA1D8C5718B4AB4CD5C3F7A0AEB1CA5F955825CF53D897EB1C4A8EAEDE421A38A79ADB5BF5251F452F9ECCD1C1185BD9EB45F0BDA34EE948B6E060935FD677C7252D64B60DC1B167CB1FB8A1D1C4F31D5947D73E67D436F4653717E330D37A72727B9178B0976A0F8BA25C21CE6B33352FEDBAF605C10C68BDAFD38C7AAB7B8AF606A7C16770B2A3E8B21D56CA2862178E4FAA98F0FD341FA99AFA2039FE69AE1E1A6D5A0F2BBB262136CECD7CE36926EE09FAF17A36F08388A922DC7A565F2E049BAB08D05E9841734578EFAC0D0A8EC8072B30A3CE18A7F6F9E57FD3A857CFD94A5155706714926EA98FF97402322FF1A436AE7E5C5933CDBE1616B2B229BF338F8FA500EE02F584F3762E35362B7C2B5FF101EBBBF4388609604AB32255D3E66FF29413BF9561AFA6B3CCC87FF1133A4D1F678A708C8090140F55B9D25BCA9F5A12F0B5D027FA53D97107E2835F1879B0C9823839EE51643346BCCCAF31DDD7B2D21E7C1DD1AA7B2F2A23D31DB5B20647F908F27E85041E5F442437B18E70E1CCA8FDD6B6B305DF8EFE9BA83D7BC19309BF699808391D0C2FA7E89A9C88F72667118BCA4413483F1951D6C2EAC994A0ED825B23A501DFDDDE2C449063940A48AC25CD36CC1E9B8324B8A42AF3DF49C64E9DAF2EADDE511CA44E8FCF3DC710F85D060D9EEF51A52CFA0F080383D77B3A3B5879F0AD387243B78B434EC5244A7185FEBBB60A981187C54CC479F7ACE7D61E1069776E4EB85BA8E2B42B6B64D74298EB63362E542929DF6A8FB4468D68DCA27892B6280B8231B5098B01546E375571295E86CD5A16753FC8394D22895C12AFDF891E11B867FFEA49372BAED8E820496A7CDE8A1BC4EC545A01E56DD2C639B9EFA3537D1C4FB79A7F03FE8AA44F708350A979B5195EDC49C0E1A12C2AEAB77302371C394A2435F54A3CD2011FDEF514A6E037AE3807C7167161278ED46581C52360BFA14B88CD3A7D737D3EB00447CC8D0F46A2FCFE80FEC05AD9464CC3B3C48975DCA9764DD16067713F2CCC72E29A526F1CA33C1F54FB4CAA2300B8614C229BBB632A905D75760AA8FADE939E8A33857C57FFE5178C3BF1318D082931A18596F5A666866B956D7385737C8731C4CC26215398C6432F47A9AB9F48CDC827E5579354CF7ECD7F2ED6533C1D771FEBD34D25BC0E71DD30483FB9425CEC7F8ACC23CCCB8D08FA543125C8DFF14C6097E06ADD4709D7892921B1F69905661F9020F35267ACA4D99DFBCB3BE28810D4EA53B8283DECED4B221DE1046096AEB85179AED35BCADFD342F993DBA2393FA13AC2FBED9F361D5BF54874552C68FCD3D96650D28F6F07F427876C434A71D72B245D37D4BA7EA7DB2C69CC6198DF0EDF7330F805C10BB70F17D22BB0F456EBBFDFB126FB172A0522D0553B9C85E1BFE41C8083D03DCE5F4095AE837A3AF5F1921AF474544F68AA628F74B203B744A36F0CAFA5B99747EC09BCA01F8134B7062E6B8D2A949CFD21013AFC82093EA42AE917F2843DDE2ADC1140CC4A981BBFB8CD690EF3E9B5AD79DFCB48B441BCF8AEA715EBC3B42BC90FA98EC08CB7A4C9054350E915734E31A768BE190CFA7216F4CA36C3D387BCC30F6544540289D4749164EA19D152F5CA77D5B303BAAC1476060B97681B0E35A1E9FA4AD3B230C8226666A24D4A54CD97B4528A0DF6C4070D7CA1B43F9AD213E94A8523812F663D7EA802837CC757BADE7D35619314F97E232F029CAD77C4B8A53B9770BED9BC7B87A0D0D53B3E3B7170653AC832E73021082FBF15CA74DD1069F0EC08BB50BC0FAEE60AD220119433E80D4AD0E962B548DD7691CBFA5CE76FE47DA08A5D0D3197D7BB4E133AC0BB74C59F3E167FC65BEB5FDAF07939991D48C596EEFC78B1A52F69A39E11BDEBBE056B10C5FCF2E86AF6FFB87708CB8C0315DBE641D7F295BEA6A9DC83A8C8B704832C383C9BB70847F3C1227EA907B12B9AFD0DC6F4D2326C25F238C1728E69878847F6CB590BEB592F24ADE9120230CEECF9E1C05D474CAB335A3FE04C6B30792B91F8DAAB5651E58FCBB5F79AD69411C27468B63A0398E26D0913CD8F5EDDA187EE2077B3201215D96D7F628B207E2DA29557F0B81F21EE66E331EB06BFA6B5C78C19B0FC8F6FC2CFF999AB25C18BFD7D63E3918AAA4C3DC16203F706EBD63281CA69B7F2964A24E7DD946BB213C1408CB14F9DE7B4D74C3BEF3A3E571BB4B5F59C7C7D2AC404A45BE0EE191DD45FAC05402FE4D238385EF6CFA3F19D9F48B990356E8C5A4491FE339DDD120B2804C8B51AF093CFD66917C2D1F56CAC546DA1B195261E9C54F988878AC76B64D4E13259A61C1D45B6F8A7943C40A57CA2C4E3A48B3056F9BF8BB30B9AAA3493E4C73150D14A0DDB97449C77259CA370CC889A82F4E74AB04579A5D515FE2BED5689A56DBCCD3EEC1304E554E7AC13F6F95A88716B27A1C8A9F4FE148DB5BC4C3F74C9148803B0AEF6002CD0F4D6740FE7C2394EEB888AA33BB03CE580417D55F7C6D7405685CAE1AB111ADBE13572BA9DC5A4BCF618435E61E13B056EE47D601D39FF2ED9094C5AA558CF4805E90593E16138025590CCCA86E57C1F983807D391AF9F3A5B7F3D2DC25726A0F39E5DF5AA8D0A763359AD4827AA2FD511D3409008665347610954734E367193EEF3BAA492D0928686D944EF2158B6966C39A131B06D091781F4A2242B8BECD7E1DD4EBC30F06A773954154D6104D68970CCEBEC727D4D157EAF456CA7F1AFCA87FA14DD07B4DC510E800898ECD5E250151BC82B97C821CF3AAA98D677FAF56DE996D042FDF0CD8E8EB44A10CAC17B3789F32BE8846F2D034D435390E921618166C995B917734B9F096987BBA505AA1AAA722CD8D217A5D23050CCF786FB3A7744B555B243547018B3C162AC81A996689AAEE7A1AC6CDFCA62C906DDDAE7F162BDC125E4B920607C0E43C80C5B59C23FF9F762A265463B87967C027D43FAA65584A592ACEF698188B019FF2DBEB552028FB1D67404ECF940827E5C4AB63F4DC0B3B49B23F50CA74E08F204F218EF490DF434CA51B57A5F0127343FBC393DFB66AA0D83F4BBB929A3C98DDEE8FF0299FDCAB059D4ED9382E098DF497457D9B25784A53E779C4C73D7ECB2ED3639522CD8BFA958811740E8D7695D084AB0E597A2DEA8085C536094623A395E1DBD25A246DDC73EAB1C759417530731BBDFD4DD94367DCCB9AC3FA758C35B7B30C62E7620DB96E2FCEA2A91144A6876BDD0471044271B9C625097EAA4C4268547E7D66D1A1B4F998F23763890CD4A01BA45E99CD6174756AF676F27DA6FE6B1F0FF648845714F46C02A917716E150B3812B2CDC64FD59E11C3FE2BDC2327E8B34DCA44BD19A65B74B2AC65B7D1A16844B8CDD87D6A2C4972CBB8115E05FC71B68ECB7FEAC54CE4AF5A8B40CEB26DD97C066E7004CC1D7549D6E1200CE2DD133A25AB175857BF7359BF84494392A9BA4C1C9923F7884AEF54512D5F4C9D5E07F0D9FB564611DF44A2988950E8D3FD999462892A66D63578FCA06DD06A8F1955CFF3ADA5EF22417FECF4523D6616D27842E23D94A2E31F81A9ABE9FF072E507A95BE04618AB3C3CE1A41498CE72B3B4F7C96C3D2E70000000000000000000000000000000000000000040A10161B2348656C6C6F20776F726C64 + diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/internal.h new file mode 100644 index 0000000000..5b2d90aae2 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dilithium/internal.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2023, Google LLC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_CRYPTO_DILITHIUM_INTERNAL_H +#define OPENSSL_HEADER_CRYPTO_DILITHIUM_INTERNAL_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +// DILITHIUM_GENERATE_KEY_ENTROPY is the number of bytes of uniformly random +// entropy necessary to generate a key pair. +#define DILITHIUM_GENERATE_KEY_ENTROPY 32 + +// DILITHIUM_SIGNATURE_RANDOMIZER_BYTES is the number of bytes of uniformly +// random entropy necessary to generate a signature in randomized mode. +#define DILITHIUM_SIGNATURE_RANDOMIZER_BYTES 32 + +// DILITHIUM_generate_key_external_entropy generates a public/private key pair +// using the given seed, writes the encoded public key to +// |out_encoded_public_key| and sets |out_private_key| to the private key, +// returning 1 on success and 0 on failure. Returns 1 on success and 0 on +// failure. +OPENSSL_EXPORT int DILITHIUM_generate_key_external_entropy( + uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES], + struct DILITHIUM_private_key *out_private_key, + const uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY]); + +// DILITHIUM_sign_deterministic generates a signature for the message |msg| of +// length |msg_len| using |private_key| following the deterministic algorithm, +// and writes the encoded signature to |out_encoded_signature|. Returns 1 on +// success and 0 on failure. +OPENSSL_EXPORT int DILITHIUM_sign_deterministic( + uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], + const struct DILITHIUM_private_key *private_key, const uint8_t *msg, + size_t msg_len); + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_CRYPTO_DILITHIUM_INTERNAL_H diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa.c b/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa.c index a35b3849e4..b2eda204ed 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa.c @@ -208,6 +208,11 @@ int DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g) { int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in, size_t seed_len, int *out_counter, unsigned long *out_h, BN_GENCB *cb) { + if (bits > OPENSSL_DSA_MAX_MODULUS_BITS) { + OPENSSL_PUT_ERROR(DSA, DSA_R_INVALID_PARAMETERS); + return 0; + } + int ok = 0; unsigned char seed[SHA256_DIGEST_LENGTH]; unsigned char md[SHA256_DIGEST_LENGTH]; @@ -479,11 +484,13 @@ DSA *DSAparams_dup(const DSA *dsa) { } int DSA_generate_key(DSA *dsa) { - int ok = 0; - BN_CTX *ctx = NULL; - BIGNUM *pub_key = NULL, *priv_key = NULL; + if (!dsa_check_key(dsa)) { + return 0; + } - ctx = BN_CTX_new(); + int ok = 0; + BIGNUM *pub_key = NULL, *priv_key = NULL; + BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa_asn1.c b/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa_asn1.c index 1caf4ae6d7..8ec55dd404 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa_asn1.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dsa/dsa_asn1.c @@ -65,8 +65,6 @@ #include "../bytestring/internal.h" -#define OPENSSL_DSA_MAX_MODULUS_BITS 10000 - // This function is in dsa_asn1.c rather than dsa.c because it is reachable from // |EVP_PKEY| parsers. This makes it easier for the static linker to drop most // of the DSA implementation. diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/dsa/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/dsa/internal.h index 61cf9a65bd..9cceeb1214 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/dsa/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/dsa/internal.h @@ -42,6 +42,8 @@ struct dsa_st { CRYPTO_EX_DATA ex_data; }; +#define OPENSSL_DSA_MAX_MODULUS_BITS 10000 + // dsa_check_key performs cheap self-checks on |dsa|, and ensures it is within // DoS bounds. It returns one on success and zero on error. int dsa_check_key(const DSA *dsa); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/aes.c b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/aes.c index 60f3545796..7eab5ac9e3 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/aes.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/aes.c @@ -104,3 +104,24 @@ int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { return aes_nohw_set_decrypt_key(key, bits, aeskey); } } + +#if defined(HWAES) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) +// On x86 and x86_64, |aes_hw_set_decrypt_key|, we implement +// |aes_hw_encrypt_key_to_decrypt_key| in assembly and rely on C code to combine +// the operations. +int aes_hw_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) { + int ret = aes_hw_set_encrypt_key(user_key, bits, key); + if (ret == 0) { + aes_hw_encrypt_key_to_decrypt_key(key); + } + return ret; +} + +int aes_hw_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) { + if (aes_hw_set_encrypt_key_alt_preferred()) { + return aes_hw_set_encrypt_key_alt(user_key, bits, key); + } else { + return aes_hw_set_encrypt_key_base(user_key, bits, key); + } +} +#endif diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesni-x86.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesni-x86.pl index 7d97adc43d..077be94e74 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesni-x86.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesni-x86.pl @@ -83,7 +83,6 @@ open OUT,">$output"; &asm_init($ARGV[0]); -&external_label("OPENSSL_ia32cap_P"); &preprocessor_ifdef("BORINGSSL_DISPATCH_TEST") &external_label("BORINGSSL_function_hit"); &preprocessor_endif(); @@ -2109,35 +2108,25 @@ if ($PREFIX eq $AESNI_PREFIX) { ###################################################################### # Mechanical port from aesni-x86_64.pl. -# -# _aesni_set_encrypt_key is private interface, -# input: -# "eax" const unsigned char *userKey -# $rounds int bits -# $key AES_KEY *key -# output: -# "eax" return code -# $round rounds -&function_begin_B("_aesni_set_encrypt_key"); - &push ("ebp"); +# int $PREFIX_set_encrypt_key_base (const unsigned char *userKey, int bits, +# AES_KEY *key) +&function_begin_B("${PREFIX}_set_encrypt_key_base"); + &record_function_hit(3); + + &mov ("eax",&wparam(0)); + &mov ($rounds,&wparam(1)); + &mov ($key,&wparam(2)); &push ("ebx"); - &test ("eax","eax"); - &jz (&label("bad_pointer")); - &test ($key,$key); - &jz (&label("bad_pointer")); &call (&label("pic")); &set_label("pic"); &blindpop("ebx"); &lea ("ebx",&DWP(&label("key_const")."-".&label("pic"),"ebx")); - &picmeup("ebp","OPENSSL_ia32cap_P","ebx",&label("key_const")); &movups ("xmm0",&QWP(0,"eax")); # pull first 128 bits of *userKey &xorps ("xmm4","xmm4"); # low dword of xmm4 is assumed 0 - &mov ("ebp",&DWP(4,"ebp")); &lea ($key,&DWP(16,$key)); - &and ("ebp",1<<28|1<<11); # AVX and XOP bits &cmp ($rounds,256); &je (&label("14rounds")); &cmp ($rounds,192); @@ -2146,9 +2135,6 @@ if ($PREFIX eq $AESNI_PREFIX) { &jne (&label("bad_keybits")); &set_label("10rounds",16); - &cmp ("ebp",1<<28); - &je (&label("10rounds_alt")); - &mov ($rounds,9); &$movekey (&QWP(-16,$key),"xmm0"); # round 0 &aeskeygenassist("xmm1","xmm0",0x01); # round 1 @@ -2188,6 +2174,166 @@ if ($PREFIX eq $AESNI_PREFIX) { &xorps ("xmm0","xmm1"); &ret(); +&set_label("12rounds",16); + &movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey + + &mov ($rounds,11); + &$movekey (&QWP(-16,$key),"xmm0"); # round 0 + &aeskeygenassist("xmm1","xmm2",0x01); # round 1,2 + &call (&label("key_192a_cold")); + &aeskeygenassist("xmm1","xmm2",0x02); # round 2,3 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x04); # round 4,5 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x08); # round 5,6 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x10); # round 7,8 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x20); # round 8,9 + &call (&label("key_192b")); + &aeskeygenassist("xmm1","xmm2",0x40); # round 10,11 + &call (&label("key_192a")); + &aeskeygenassist("xmm1","xmm2",0x80); # round 11,12 + &call (&label("key_192b")); + &$movekey (&QWP(0,$key),"xmm0"); + &mov (&DWP(48,$key),$rounds); + + &jmp (&label("good_key")); + +&set_label("key_192a",16); + &$movekey (&QWP(0,$key),"xmm0"); + &lea ($key,&DWP(16,$key)); +&set_label("key_192a_cold",16); + &movaps ("xmm5","xmm2"); +&set_label("key_192b_warm"); + &shufps ("xmm4","xmm0",0b00010000); + &movdqa ("xmm3","xmm2"); + &xorps ("xmm0","xmm4"); + &shufps ("xmm4","xmm0",0b10001100); + &pslldq ("xmm3",4); + &xorps ("xmm0","xmm4"); + &pshufd ("xmm1","xmm1",0b01010101); # critical path + &pxor ("xmm2","xmm3"); + &pxor ("xmm0","xmm1"); + &pshufd ("xmm3","xmm0",0b11111111); + &pxor ("xmm2","xmm3"); + &ret(); + +&set_label("key_192b",16); + &movaps ("xmm3","xmm0"); + &shufps ("xmm5","xmm0",0b01000100); + &$movekey (&QWP(0,$key),"xmm5"); + &shufps ("xmm3","xmm2",0b01001110); + &$movekey (&QWP(16,$key),"xmm3"); + &lea ($key,&DWP(32,$key)); + &jmp (&label("key_192b_warm")); + +&set_label("14rounds",16); + &movups ("xmm2",&QWP(16,"eax")); # remaining half of *userKey + &lea ($key,&DWP(16,$key)); + + &mov ($rounds,13); + &$movekey (&QWP(-32,$key),"xmm0"); # round 0 + &$movekey (&QWP(-16,$key),"xmm2"); # round 1 + &aeskeygenassist("xmm1","xmm2",0x01); # round 2 + &call (&label("key_256a_cold")); + &aeskeygenassist("xmm1","xmm0",0x01); # round 3 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x02); # round 4 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x02); # round 5 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x04); # round 6 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x04); # round 7 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x08); # round 8 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x08); # round 9 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x10); # round 10 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x10); # round 11 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x20); # round 12 + &call (&label("key_256a")); + &aeskeygenassist("xmm1","xmm0",0x20); # round 13 + &call (&label("key_256b")); + &aeskeygenassist("xmm1","xmm2",0x40); # round 14 + &call (&label("key_256a")); + &$movekey (&QWP(0,$key),"xmm0"); + &mov (&DWP(16,$key),$rounds); + &xor ("eax","eax"); + + &jmp (&label("good_key")); + +&set_label("key_256a",16); + &$movekey (&QWP(0,$key),"xmm2"); + &lea ($key,&DWP(16,$key)); +&set_label("key_256a_cold"); + &shufps ("xmm4","xmm0",0b00010000); + &xorps ("xmm0","xmm4"); + &shufps ("xmm4","xmm0",0b10001100); + &xorps ("xmm0","xmm4"); + &shufps ("xmm1","xmm1",0b11111111); # critical path + &xorps ("xmm0","xmm1"); + &ret(); + +&set_label("key_256b",16); + &$movekey (&QWP(0,$key),"xmm0"); + &lea ($key,&DWP(16,$key)); + + &shufps ("xmm4","xmm2",0b00010000); + &xorps ("xmm2","xmm4"); + &shufps ("xmm4","xmm2",0b10001100); + &xorps ("xmm2","xmm4"); + &shufps ("xmm1","xmm1",0b10101010); # critical path + &xorps ("xmm2","xmm1"); + &ret(); + +&set_label("good_key"); + &pxor ("xmm0","xmm0"); + &pxor ("xmm1","xmm1"); + &pxor ("xmm2","xmm2"); + &pxor ("xmm3","xmm3"); + &pxor ("xmm4","xmm4"); + &pxor ("xmm5","xmm5"); + &xor ("eax","eax"); + &pop ("ebx"); + &ret (); + +&set_label("bad_keybits",4); + &pxor ("xmm0","xmm0"); + &mov ("eax",-2); + &pop ("ebx"); + &ret (); +&function_end_B("${PREFIX}_set_encrypt_key_base"); + +# int $PREFIX_set_encrypt_key_alt (const unsigned char *userKey, int bits, +# AES_KEY *key) +&function_begin_B("${PREFIX}_set_encrypt_key_alt"); + &record_function_hit(3); + + &mov ("eax",&wparam(0)); + &mov ($rounds,&wparam(1)); + &mov ($key,&wparam(2)); + &push ("ebx"); + + &call (&label("pic")); +&set_label("pic"); + &blindpop("ebx"); + &lea ("ebx",&DWP(&label("key_const")."-".&label("pic"),"ebx")); + + &movups ("xmm0",&QWP(0,"eax")); # pull first 128 bits of *userKey + &xorps ("xmm4","xmm4"); # low dword of xmm4 is assumed 0 + &lea ($key,&DWP(16,$key)); + &cmp ($rounds,256); + &je (&label("14rounds_alt")); + &cmp ($rounds,192); + &je (&label("12rounds_alt")); + &cmp ($rounds,128); + &jne (&label("bad_keybits")); + &set_label("10rounds_alt",16); &movdqa ("xmm5",&QWP(0x00,"ebx")); &mov ($rounds,8); @@ -2253,63 +2399,8 @@ if ($PREFIX eq $AESNI_PREFIX) { &jmp (&label("good_key")); -&set_label("12rounds",16); - &movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey - &cmp ("ebp",1<<28); - &je (&label("12rounds_alt")); - - &mov ($rounds,11); - &$movekey (&QWP(-16,$key),"xmm0"); # round 0 - &aeskeygenassist("xmm1","xmm2",0x01); # round 1,2 - &call (&label("key_192a_cold")); - &aeskeygenassist("xmm1","xmm2",0x02); # round 2,3 - &call (&label("key_192b")); - &aeskeygenassist("xmm1","xmm2",0x04); # round 4,5 - &call (&label("key_192a")); - &aeskeygenassist("xmm1","xmm2",0x08); # round 5,6 - &call (&label("key_192b")); - &aeskeygenassist("xmm1","xmm2",0x10); # round 7,8 - &call (&label("key_192a")); - &aeskeygenassist("xmm1","xmm2",0x20); # round 8,9 - &call (&label("key_192b")); - &aeskeygenassist("xmm1","xmm2",0x40); # round 10,11 - &call (&label("key_192a")); - &aeskeygenassist("xmm1","xmm2",0x80); # round 11,12 - &call (&label("key_192b")); - &$movekey (&QWP(0,$key),"xmm0"); - &mov (&DWP(48,$key),$rounds); - - &jmp (&label("good_key")); - -&set_label("key_192a",16); - &$movekey (&QWP(0,$key),"xmm0"); - &lea ($key,&DWP(16,$key)); -&set_label("key_192a_cold",16); - &movaps ("xmm5","xmm2"); -&set_label("key_192b_warm"); - &shufps ("xmm4","xmm0",0b00010000); - &movdqa ("xmm3","xmm2"); - &xorps ("xmm0","xmm4"); - &shufps ("xmm4","xmm0",0b10001100); - &pslldq ("xmm3",4); - &xorps ("xmm0","xmm4"); - &pshufd ("xmm1","xmm1",0b01010101); # critical path - &pxor ("xmm2","xmm3"); - &pxor ("xmm0","xmm1"); - &pshufd ("xmm3","xmm0",0b11111111); - &pxor ("xmm2","xmm3"); - &ret(); - -&set_label("key_192b",16); - &movaps ("xmm3","xmm0"); - &shufps ("xmm5","xmm0",0b01000100); - &$movekey (&QWP(0,$key),"xmm5"); - &shufps ("xmm3","xmm2",0b01001110); - &$movekey (&QWP(16,$key),"xmm3"); - &lea ($key,&DWP(32,$key)); - &jmp (&label("key_192b_warm")); - &set_label("12rounds_alt",16); + &movq ("xmm2",&QWP(16,"eax")); # remaining 1/3 of *userKey &movdqa ("xmm5",&QWP(0x10,"ebx")); &movdqa ("xmm4",&QWP(0x20,"ebx")); &mov ($rounds,8); @@ -2348,72 +2439,9 @@ if ($PREFIX eq $AESNI_PREFIX) { &jmp (&label("good_key")); -&set_label("14rounds",16); +&set_label("14rounds_alt",16); &movups ("xmm2",&QWP(16,"eax")); # remaining half of *userKey &lea ($key,&DWP(16,$key)); - &cmp ("ebp",1<<28); - &je (&label("14rounds_alt")); - - &mov ($rounds,13); - &$movekey (&QWP(-32,$key),"xmm0"); # round 0 - &$movekey (&QWP(-16,$key),"xmm2"); # round 1 - &aeskeygenassist("xmm1","xmm2",0x01); # round 2 - &call (&label("key_256a_cold")); - &aeskeygenassist("xmm1","xmm0",0x01); # round 3 - &call (&label("key_256b")); - &aeskeygenassist("xmm1","xmm2",0x02); # round 4 - &call (&label("key_256a")); - &aeskeygenassist("xmm1","xmm0",0x02); # round 5 - &call (&label("key_256b")); - &aeskeygenassist("xmm1","xmm2",0x04); # round 6 - &call (&label("key_256a")); - &aeskeygenassist("xmm1","xmm0",0x04); # round 7 - &call (&label("key_256b")); - &aeskeygenassist("xmm1","xmm2",0x08); # round 8 - &call (&label("key_256a")); - &aeskeygenassist("xmm1","xmm0",0x08); # round 9 - &call (&label("key_256b")); - &aeskeygenassist("xmm1","xmm2",0x10); # round 10 - &call (&label("key_256a")); - &aeskeygenassist("xmm1","xmm0",0x10); # round 11 - &call (&label("key_256b")); - &aeskeygenassist("xmm1","xmm2",0x20); # round 12 - &call (&label("key_256a")); - &aeskeygenassist("xmm1","xmm0",0x20); # round 13 - &call (&label("key_256b")); - &aeskeygenassist("xmm1","xmm2",0x40); # round 14 - &call (&label("key_256a")); - &$movekey (&QWP(0,$key),"xmm0"); - &mov (&DWP(16,$key),$rounds); - &xor ("eax","eax"); - - &jmp (&label("good_key")); - -&set_label("key_256a",16); - &$movekey (&QWP(0,$key),"xmm2"); - &lea ($key,&DWP(16,$key)); -&set_label("key_256a_cold"); - &shufps ("xmm4","xmm0",0b00010000); - &xorps ("xmm0","xmm4"); - &shufps ("xmm4","xmm0",0b10001100); - &xorps ("xmm0","xmm4"); - &shufps ("xmm1","xmm1",0b11111111); # critical path - &xorps ("xmm0","xmm1"); - &ret(); - -&set_label("key_256b",16); - &$movekey (&QWP(0,$key),"xmm0"); - &lea ($key,&DWP(16,$key)); - - &shufps ("xmm4","xmm2",0b00010000); - &xorps ("xmm2","xmm4"); - &shufps ("xmm4","xmm2",0b10001100); - &xorps ("xmm2","xmm4"); - &shufps ("xmm1","xmm1",0b10101010); # critical path - &xorps ("xmm2","xmm1"); - &ret(); - -&set_label("14rounds_alt",16); &movdqa ("xmm5",&QWP(0x00,"ebx")); &movdqa ("xmm4",&QWP(0x20,"ebx")); &mov ($rounds,7); @@ -2471,45 +2499,20 @@ if ($PREFIX eq $AESNI_PREFIX) { &pxor ("xmm5","xmm5"); &xor ("eax","eax"); &pop ("ebx"); - &pop ("ebp"); &ret (); -&set_label("bad_pointer",4); - &mov ("eax",-1); - &pop ("ebx"); - &pop ("ebp"); - &ret (); &set_label("bad_keybits",4); &pxor ("xmm0","xmm0"); &mov ("eax",-2); &pop ("ebx"); - &pop ("ebp"); &ret (); -&function_end_B("_aesni_set_encrypt_key"); +&function_end_B("${PREFIX}_set_encrypt_key_alt"); -# int $PREFIX_set_encrypt_key (const unsigned char *userKey, int bits, -# AES_KEY *key) -&function_begin_B("${PREFIX}_set_encrypt_key"); - &record_function_hit(3); - - &mov ("eax",&wparam(0)); - &mov ($rounds,&wparam(1)); - &mov ($key,&wparam(2)); - &call ("_aesni_set_encrypt_key"); - &ret (); -&function_end_B("${PREFIX}_set_encrypt_key"); - -# int $PREFIX_set_decrypt_key (const unsigned char *userKey, int bits, -# AES_KEY *key) -&function_begin_B("${PREFIX}_set_decrypt_key"); - &mov ("eax",&wparam(0)); - &mov ($rounds,&wparam(1)); - &mov ($key,&wparam(2)); - &call ("_aesni_set_encrypt_key"); - &mov ($key,&wparam(2)); - &shl ($rounds,4); # rounds-1 after _aesni_set_encrypt_key - &test ("eax","eax"); - &jnz (&label("dec_key_ret")); +# void $PREFIX_encrypt_key_to_decrypt_key (AES_KEY *key) +&function_begin_B("${PREFIX}_encrypt_key_to_decrypt_key"); + &mov ($key,&wparam(0)); + &mov ($rounds,&DWP(240,$key)); + &shl ($rounds,4); &lea ("eax",&DWP(16,$key,$rounds)); # end of key schedule &$movekey ("xmm0",&QWP(0,$key)); # just swap @@ -2537,10 +2540,8 @@ if ($PREFIX eq $AESNI_PREFIX) { &pxor ("xmm0","xmm0"); &pxor ("xmm1","xmm1"); - &xor ("eax","eax"); # return success -&set_label("dec_key_ret"); &ret (); -&function_end_B("${PREFIX}_set_decrypt_key"); +&function_end_B("${PREFIX}_encrypt_key_to_decrypt_key"); &set_label("key_const",64); &data_word(0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesni-x86_64.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesni-x86_64.pl index a8abb4d441..ab45749c51 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesni-x86_64.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesni-x86_64.pl @@ -211,7 +211,6 @@ $movkey = $PREFIX eq "aes_hw" ? "movups" : "movups"; ("%rdi","%rsi","%rdx","%rcx"); # Unix order $code=".text\n"; -$code.=".extern OPENSSL_ia32cap_P\n"; $rounds="%eax"; # input to and changed by aesni_[en|de]cryptN !!! # this is natural Unix argument order for public $PREFIX_[ecb|cbc]_encrypt ... @@ -3172,66 +3171,55 @@ $code.=<<___; .size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt ___ } -# int ${PREFIX}_set_decrypt_key(const unsigned char *inp, -# int bits, AES_KEY *key) -# -# input: $inp user-supplied key -# $bits $inp length in bits -# $key pointer to key schedule -# output: %eax 0 denoting success, -1 or -2 - failure (see C) -# *$key key schedule -# -{ my ($inp,$bits,$key) = @_4args; - $bits =~ s/%r/%e/; +{ my ($key, $rounds, $tmp) = @_4args; + $rounds =~ s/%r/%e/; +# void ${PREFIX}_encrypt_key_to_decrypt_key(AES_KEY *key) $code.=<<___; -.globl ${PREFIX}_set_decrypt_key -.type ${PREFIX}_set_decrypt_key,\@abi-omnipotent +.globl ${PREFIX}_encrypt_key_to_decrypt_key +.type ${PREFIX}_encrypt_key_to_decrypt_key,\@abi-omnipotent .align 16 -${PREFIX}_set_decrypt_key: +${PREFIX}_encrypt_key_to_decrypt_key: .cfi_startproc _CET_ENDBR - .byte 0x48,0x83,0xEC,0x08 # sub rsp,8 -.cfi_adjust_cfa_offset 8 - call __aesni_set_encrypt_key - shl \$4,$bits # rounds-1 after _aesni_set_encrypt_key - test %eax,%eax - jnz .Ldec_key_ret - lea 16($key,$bits),$inp # points at the end of key schedule + + mov 240($key), $rounds + shl \$4,$rounds + + lea 16($key,$rounds),$tmp # points at the end of key schedule $movkey ($key),%xmm0 # just swap - $movkey ($inp),%xmm1 - $movkey %xmm0,($inp) + $movkey ($tmp),%xmm1 + $movkey %xmm0,($tmp) $movkey %xmm1,($key) lea 16($key),$key - lea -16($inp),$inp + lea -16($tmp),$tmp .Ldec_key_inverse: $movkey ($key),%xmm0 # swap and inverse - $movkey ($inp),%xmm1 + $movkey ($tmp),%xmm1 aesimc %xmm0,%xmm0 aesimc %xmm1,%xmm1 lea 16($key),$key - lea -16($inp),$inp - $movkey %xmm0,16($inp) + lea -16($tmp),$tmp + $movkey %xmm0,16($tmp) $movkey %xmm1,-16($key) - cmp $key,$inp + cmp $key,$tmp ja .Ldec_key_inverse $movkey ($key),%xmm0 # inverse middle aesimc %xmm0,%xmm0 pxor %xmm1,%xmm1 - $movkey %xmm0,($inp) + $movkey %xmm0,($tmp) pxor %xmm0,%xmm0 -.Ldec_key_ret: - add \$8,%rsp -.cfi_adjust_cfa_offset -8 ret .cfi_endproc -.LSEH_end_set_decrypt_key: -.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key +.size ${PREFIX}_encrypt_key_to_decrypt_key,.-${PREFIX}_encrypt_key_to_decrypt_key ___ +} +{ my ($inp,$bits,$key) = @_4args; + $bits =~ s/%r/%e/; # This is based on submission from Intel by # Huang Ying # Vinodh Gopal @@ -3256,30 +3244,26 @@ ___ # are used. Note that it's declared "abi-omnipotent", which means that # amount of volatile registers is smaller on Windows. # +# There are two variants of this function, one which uses aeskeygenassist +# ("base") and one which uses aesenclast + pshufb ("alt"). See aes/internal.h +# for details. $code.=<<___; -.globl ${PREFIX}_set_encrypt_key -.type ${PREFIX}_set_encrypt_key,\@abi-omnipotent +.globl ${PREFIX}_set_encrypt_key_base +.type ${PREFIX}_set_encrypt_key_base,\@abi-omnipotent .align 16 -${PREFIX}_set_encrypt_key: -__aesni_set_encrypt_key: +${PREFIX}_set_encrypt_key_base: .cfi_startproc +.seh_startproc _CET_ENDBR #ifdef BORINGSSL_DISPATCH_TEST movb \$1,BORINGSSL_function_hit+3(%rip) #endif - .byte 0x48,0x83,0xEC,0x08 # sub rsp,8 + sub \$8,%rsp .cfi_adjust_cfa_offset 8 - mov \$-1,%rax - test $inp,$inp - jz .Lenc_key_ret - test $key,$key - jz .Lenc_key_ret - +.seh_stackalloc 8 +.seh_endprologue movups ($inp),%xmm0 # pull first 128 bits of *userKey xorps %xmm4,%xmm4 # low dword of xmm4 is assumed 0 - leaq OPENSSL_ia32cap_P(%rip),%r10 - movl 4(%r10),%r10d - and \$`1<<28|1<<11`,%r10d # AVX and XOP bits lea 16($key),%rax # %rax is used as modifiable copy of $key cmp \$256,$bits je .L14rounds @@ -3290,8 +3274,6 @@ __aesni_set_encrypt_key: .L10rounds: mov \$9,$bits # 10 rounds for 128-bit key - cmp \$`1<<28`,%r10d # AVX, bit no XOP - je .L10rounds_alt $movkey %xmm0,($key) # round 0 aeskeygenassist \$0x1,%xmm0,%xmm1 # round 1 @@ -3319,79 +3301,10 @@ __aesni_set_encrypt_key: xor %eax,%eax jmp .Lenc_key_ret -.align 16 -.L10rounds_alt: - movdqa .Lkey_rotate(%rip),%xmm5 - mov \$8,%r10d - movdqa .Lkey_rcon1(%rip),%xmm4 - movdqa %xmm0,%xmm2 - movdqu %xmm0,($key) - jmp .Loop_key128 - -.align 16 -.Loop_key128: - pshufb %xmm5,%xmm0 - aesenclast %xmm4,%xmm0 - pslld \$1,%xmm4 - lea 16(%rax),%rax - - movdqa %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,-16(%rax) - movdqa %xmm0,%xmm2 - - dec %r10d - jnz .Loop_key128 - - movdqa .Lkey_rcon1b(%rip),%xmm4 - - pshufb %xmm5,%xmm0 - aesenclast %xmm4,%xmm0 - pslld \$1,%xmm4 - - movdqa %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,(%rax) - - movdqa %xmm0,%xmm2 - pshufb %xmm5,%xmm0 - aesenclast %xmm4,%xmm0 - - movdqa %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm2,%xmm3 - pslldq \$4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,16(%rax) - - mov $bits,96(%rax) # 240($key) - xor %eax,%eax - jmp .Lenc_key_ret - .align 16 .L12rounds: movq 16($inp),%xmm2 # remaining 1/3 of *userKey mov \$11,$bits # 12 rounds for 192 - cmp \$`1<<28`,%r10d # AVX, but no XOP - je .L12rounds_alt $movkey %xmm0,($key) # round 0 aeskeygenassist \$0x1,%xmm2,%xmm1 # round 1,2 @@ -3415,54 +3328,11 @@ __aesni_set_encrypt_key: xor %rax, %rax jmp .Lenc_key_ret -.align 16 -.L12rounds_alt: - movdqa .Lkey_rotate192(%rip),%xmm5 - movdqa .Lkey_rcon1(%rip),%xmm4 - mov \$8,%r10d - movdqu %xmm0,($key) - jmp .Loop_key192 - -.align 16 -.Loop_key192: - movq %xmm2,0(%rax) - movdqa %xmm2,%xmm1 - pshufb %xmm5,%xmm2 - aesenclast %xmm4,%xmm2 - pslld \$1, %xmm4 - lea 24(%rax),%rax - - movdqa %xmm0,%xmm3 - pslldq \$4,%xmm0 - pxor %xmm0,%xmm3 - pslldq \$4,%xmm0 - pxor %xmm0,%xmm3 - pslldq \$4,%xmm0 - pxor %xmm3,%xmm0 - - pshufd \$0xff,%xmm0,%xmm3 - pxor %xmm1,%xmm3 - pslldq \$4,%xmm1 - pxor %xmm1,%xmm3 - - pxor %xmm2,%xmm0 - pxor %xmm3,%xmm2 - movdqu %xmm0,-16(%rax) - - dec %r10d - jnz .Loop_key192 - - mov $bits,32(%rax) # 240($key) - xor %eax,%eax - jmp .Lenc_key_ret - .align 16 .L14rounds: movups 16($inp),%xmm2 # remaining half of *userKey mov \$13,$bits # 14 rounds for 256 lea 16(%rax),%rax - cmp \$`1<<28`,%r10d # AVX, but no XOP - je .L14rounds_alt $movkey %xmm0,($key) # round 0 $movkey %xmm2,16($key) # round 1 @@ -3497,60 +3367,6 @@ __aesni_set_encrypt_key: xor %rax,%rax jmp .Lenc_key_ret -.align 16 -.L14rounds_alt: - movdqa .Lkey_rotate(%rip),%xmm5 - movdqa .Lkey_rcon1(%rip),%xmm4 - mov \$7,%r10d - movdqu %xmm0,0($key) - movdqa %xmm2,%xmm1 - movdqu %xmm2,16($key) - jmp .Loop_key256 - -.align 16 -.Loop_key256: - pshufb %xmm5,%xmm2 - aesenclast %xmm4,%xmm2 - - movdqa %xmm0,%xmm3 - pslldq \$4,%xmm0 - pxor %xmm0,%xmm3 - pslldq \$4,%xmm0 - pxor %xmm0,%xmm3 - pslldq \$4,%xmm0 - pxor %xmm3,%xmm0 - pslld \$1,%xmm4 - - pxor %xmm2,%xmm0 - movdqu %xmm0,(%rax) - - dec %r10d - jz .Ldone_key256 - - pshufd \$0xff,%xmm0,%xmm2 - pxor %xmm3,%xmm3 - aesenclast %xmm3,%xmm2 - - movdqa %xmm1,%xmm3 - pslldq \$4,%xmm1 - pxor %xmm1,%xmm3 - pslldq \$4,%xmm1 - pxor %xmm1,%xmm3 - pslldq \$4,%xmm1 - pxor %xmm3,%xmm1 - - pxor %xmm1,%xmm2 - movdqu %xmm2,16(%rax) - lea 32(%rax),%rax - movdqa %xmm2,%xmm1 - - jmp .Loop_key256 - -.Ldone_key256: - mov $bits,16(%rax) # 240($key) - xor %eax,%eax - jmp .Lenc_key_ret - .align 16 .Lbad_keybits: mov \$-2,%rax @@ -3565,7 +3381,7 @@ __aesni_set_encrypt_key: .cfi_adjust_cfa_offset -8 ret .cfi_endproc -.LSEH_end_set_encrypt_key: +.seh_endproc .align 16 .Lkey_expansion_128: @@ -3635,8 +3451,214 @@ __aesni_set_encrypt_key: shufps \$0b10101010,%xmm1,%xmm1 # critical path xorps %xmm1,%xmm2 ret -.size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key -.size __aesni_set_encrypt_key,.-__aesni_set_encrypt_key +.size ${PREFIX}_set_encrypt_key_base,.-${PREFIX}_set_encrypt_key_base + +.globl ${PREFIX}_set_encrypt_key_alt +.type ${PREFIX}_set_encrypt_key_alt,\@abi-omnipotent +.align 16 +${PREFIX}_set_encrypt_key_alt: +.cfi_startproc +.seh_startproc + _CET_ENDBR +#ifdef BORINGSSL_DISPATCH_TEST + movb \$1,BORINGSSL_function_hit+3(%rip) +#endif + sub \$8,%rsp +.cfi_adjust_cfa_offset 8 +.seh_stackalloc 8 +.seh_endprologue + movups ($inp),%xmm0 # pull first 128 bits of *userKey + xorps %xmm4,%xmm4 # low dword of xmm4 is assumed 0 + lea 16($key),%rax # %rax is used as modifiable copy of $key + cmp \$256,$bits + je .L14rounds_alt + cmp \$192,$bits + je .L12rounds_alt + cmp \$128,$bits + jne .Lbad_keybits_alt + + mov \$9,$bits # 10 rounds for 128-bit key + movdqa .Lkey_rotate(%rip),%xmm5 + mov \$8,%r10d + movdqa .Lkey_rcon1(%rip),%xmm4 + movdqa %xmm0,%xmm2 + movdqu %xmm0,($key) + jmp .Loop_key128 + +.align 16 +.Loop_key128: + pshufb %xmm5,%xmm0 + aesenclast %xmm4,%xmm0 + pslld \$1,%xmm4 + lea 16(%rax),%rax + + movdqa %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,-16(%rax) + movdqa %xmm0,%xmm2 + + dec %r10d + jnz .Loop_key128 + + movdqa .Lkey_rcon1b(%rip),%xmm4 + + pshufb %xmm5,%xmm0 + aesenclast %xmm4,%xmm0 + pslld \$1,%xmm4 + + movdqa %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + movdqa %xmm0,%xmm2 + pshufb %xmm5,%xmm0 + aesenclast %xmm4,%xmm0 + + movdqa %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm2,%xmm3 + pslldq \$4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,16(%rax) + + mov $bits,96(%rax) # 240($key) + xor %eax,%eax + jmp .Lenc_key_ret_alt + +.align 16 +.L12rounds_alt: + movq 16($inp),%xmm2 # remaining 1/3 of *userKey + mov \$11,$bits # 12 rounds for 192 + movdqa .Lkey_rotate192(%rip),%xmm5 + movdqa .Lkey_rcon1(%rip),%xmm4 + mov \$8,%r10d + movdqu %xmm0,($key) + jmp .Loop_key192 + +.align 16 +.Loop_key192: + movq %xmm2,0(%rax) + movdqa %xmm2,%xmm1 + pshufb %xmm5,%xmm2 + aesenclast %xmm4,%xmm2 + pslld \$1, %xmm4 + lea 24(%rax),%rax + + movdqa %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm3,%xmm0 + + pshufd \$0xff,%xmm0,%xmm3 + pxor %xmm1,%xmm3 + pslldq \$4,%xmm1 + pxor %xmm1,%xmm3 + + pxor %xmm2,%xmm0 + pxor %xmm3,%xmm2 + movdqu %xmm0,-16(%rax) + + dec %r10d + jnz .Loop_key192 + + mov $bits,32(%rax) # 240($key) + xor %eax,%eax + jmp .Lenc_key_ret_alt + +.align 16 +.L14rounds_alt: + movups 16($inp),%xmm2 # remaining half of *userKey + mov \$13,$bits # 14 rounds for 256 + lea 16(%rax),%rax + movdqa .Lkey_rotate(%rip),%xmm5 + movdqa .Lkey_rcon1(%rip),%xmm4 + mov \$7,%r10d + movdqu %xmm0,0($key) + movdqa %xmm2,%xmm1 + movdqu %xmm2,16($key) + jmp .Loop_key256 + +.align 16 +.Loop_key256: + pshufb %xmm5,%xmm2 + aesenclast %xmm4,%xmm2 + + movdqa %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm0,%xmm3 + pslldq \$4,%xmm0 + pxor %xmm3,%xmm0 + pslld \$1,%xmm4 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + dec %r10d + jz .Ldone_key256 + + pshufd \$0xff,%xmm0,%xmm2 + pxor %xmm3,%xmm3 + aesenclast %xmm3,%xmm2 + + movdqa %xmm1,%xmm3 + pslldq \$4,%xmm1 + pxor %xmm1,%xmm3 + pslldq \$4,%xmm1 + pxor %xmm1,%xmm3 + pslldq \$4,%xmm1 + pxor %xmm3,%xmm1 + + pxor %xmm1,%xmm2 + movdqu %xmm2,16(%rax) + lea 32(%rax),%rax + movdqa %xmm2,%xmm1 + + jmp .Loop_key256 + +.Ldone_key256: + mov $bits,16(%rax) # 240($key) + xor %eax,%eax + jmp .Lenc_key_ret_alt + +.align 16 +.Lbad_keybits_alt: + mov \$-2,%rax +.Lenc_key_ret_alt: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + add \$8,%rsp +.cfi_adjust_cfa_offset -8 + ret +.cfi_endproc +.seh_endproc +.size ${PREFIX}_set_encrypt_key_alt,.-${PREFIX}_set_encrypt_key_alt ___ } @@ -3926,14 +3948,6 @@ $code.=<<___; .rva .LSEH_begin_${PREFIX}_cbc_encrypt .rva .LSEH_end_${PREFIX}_cbc_encrypt .rva .LSEH_info_cbc - - .rva ${PREFIX}_set_decrypt_key - .rva .LSEH_end_set_decrypt_key - .rva .LSEH_info_key - - .rva ${PREFIX}_set_encrypt_key - .rva .LSEH_end_set_encrypt_key - .rva .LSEH_info_key .section .xdata .align 8 ___ @@ -3951,9 +3965,6 @@ $code.=<<___; .LSEH_info_cbc: .byte 9,0,0,0 .rva cbc_se_handler -.LSEH_info_key: - .byte 0x01,0x04,0x01,0x00 - .byte 0x04,0x02,0x00,0x00 # sub rsp,8 ___ } diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesv8-armx.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesv8-armx.pl index 9f62232e93..46b98c96b6 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesv8-armx.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/asm/aesv8-armx.pl @@ -102,11 +102,6 @@ $code.=<<___ if ($flavour =~ /64/); add x29,sp,#0 ___ $code.=<<___; - mov $ptr,#-1 - cmp $inp,#0 - b.eq .Lenc_key_abort - cmp $out,#0 - b.eq .Lenc_key_abort mov $ptr,#-2 cmp $bits,#128 b.lt .Lenc_key_abort diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/internal.h index 98b2a14d82..7d2db3b229 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/aes/internal.h @@ -66,17 +66,41 @@ OPENSSL_INLINE int vpaes_capable(void) { return CRYPTO_is_NEON_capable(); } #if defined(HWAES) -int aes_hw_set_encrypt_key(const uint8_t *user_key, const int bits, - AES_KEY *key); -int aes_hw_set_decrypt_key(const uint8_t *user_key, const int bits, - AES_KEY *key); +int aes_hw_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key); +int aes_hw_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key); void aes_hw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); void aes_hw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); void aes_hw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, - const AES_KEY *key, uint8_t *ivec, const int enc); + const AES_KEY *key, uint8_t *ivec, int enc); void aes_hw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len, const AES_KEY *key, const uint8_t ivec[16]); +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) +// On x86 and x86_64, |aes_hw_set_decrypt_key| is implemented in terms of +// |aes_hw_set_encrypt_key| and a conversion function. +void aes_hw_encrypt_key_to_decrypt_key(AES_KEY *key); + +// There are two variants of this function, one which uses aeskeygenassist +// ("base") and one which uses aesenclast + pshufb ("alt"). aesenclast is +// overall faster but is slower on some older processors. It doesn't use AVX, +// but AVX is used as a proxy to detecting this. See +// https://groups.google.com/g/mailing.openssl.dev/c/OuFXwW4NfO8/m/7d2ZXVjkxVkJ +// +// TODO(davidben): It is unclear if the aeskeygenassist version is still +// worthwhile. However, the aesenclast version requires SSSE3. SSSE3 long +// predates AES-NI, but it's not clear if AES-NI implies SSSE3. In OpenSSL, the +// CCM AES-NI assembly seems to assume it does. +OPENSSL_INLINE int aes_hw_set_encrypt_key_alt_capable(void) { + return hwaes_capable() && CRYPTO_is_SSSE3_capable(); +} +OPENSSL_INLINE int aes_hw_set_encrypt_key_alt_preferred(void) { + return hwaes_capable() && CRYPTO_is_AVX_capable(); +} +int aes_hw_set_encrypt_key_base(const uint8_t *user_key, int bits, + AES_KEY *key); +int aes_hw_set_encrypt_key_alt(const uint8_t *user_key, int bits, AES_KEY *key); +#endif // OPENSSL_X86 || OPENSSL_X86_64 + #else // If HWAES isn't defined then we provide dummy functions for each of the hwaes @@ -120,7 +144,7 @@ OPENSSL_INLINE void aes_hw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, #if defined(HWAES_ECB) void aes_hw_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length, - const AES_KEY *key, const int enc); + const AES_KEY *key, int enc); #endif // HWAES_ECB @@ -218,7 +242,7 @@ void aes_nohw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks, const AES_KEY *key, const uint8_t ivec[16]); void aes_nohw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, - const AES_KEY *key, uint8_t *ivec, const int enc); + const AES_KEY *key, uint8_t *ivec, int enc); #if defined(__cplusplus) diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm.c b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm.c index 9d9227d772..c356730d1c 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bcm.c @@ -168,8 +168,6 @@ static void BORINGSSL_maybe_set_module_text_permissions(int permission) {} static void __attribute__((constructor)) BORINGSSL_bcm_power_on_self_test(void) { - CRYPTO_library_init(); - #if !defined(OPENSSL_ASAN) // Integrity tests cannot run under ASAN because it involves reading the full // .text section, which triggers the global-buffer overflow detection. @@ -263,6 +261,11 @@ int BORINGSSL_integrity_test(void) { OPENSSL_cleanse(result, sizeof(result)); // FIPS 140-3, AS05.10. return 1; } + +const uint8_t* FIPS_module_hash(void) { + return BORINGSSL_bcm_text_hash; +} + #endif // OPENSSL_ASAN void BORINGSSL_FIPS_abort(void) { diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/bn-586.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/bn-586.pl index eae6da9462..e4fc0f9806 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/bn-586.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/bn-586.pl @@ -18,8 +18,6 @@ open STDOUT,">$output"; $sse2=1; -&external_label("OPENSSL_ia32cap_P") if ($sse2); - &bn_mul_add_words("bn_mul_add_words"); &bn_mul_words("bn_mul_words"); &bn_sqr_words("bn_sqr_words"); @@ -35,17 +33,13 @@ sub bn_mul_add_words { local($name)=@_; - &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + &function_begin_B($name); $r="eax"; $a="edx"; $c="ecx"; if ($sse2) { - &picmeup("eax","OPENSSL_ia32cap_P"); - &bt(&DWP(0,"eax"),26); - &jnc(&label("maw_non_sse2")); - &mov($r,&wparam(0)); &mov($a,&wparam(1)); &mov($c,&wparam(2)); @@ -135,85 +129,7 @@ sub bn_mul_add_words &movd("eax","mm1"); # c = carry_out &emms(); &ret(); - - &set_label("maw_non_sse2",16); } - - # function_begin prologue - &push("ebp"); - &push("ebx"); - &push("esi"); - &push("edi"); - - &comment(""); - $Low="eax"; - $High="edx"; - $a="ebx"; - $w="ebp"; - $r="edi"; - $c="esi"; - - &xor($c,$c); # clear carry - &mov($r,&wparam(0)); # - - &mov("ecx",&wparam(2)); # - &mov($a,&wparam(1)); # - - &and("ecx",0xfffffff8); # num / 8 - &mov($w,&wparam(3)); # - - &push("ecx"); # Up the stack for a tmp variable - - &jz(&label("maw_finish")); - - &set_label("maw_loop",16); - - for ($i=0; $i<32; $i+=4) - { - &comment("Round $i"); - - &mov("eax",&DWP($i,$a)); # *a - &mul($w); # *a * w - &add("eax",$c); # L(t)+= c - &adc("edx",0); # H(t)+=carry - &add("eax",&DWP($i,$r)); # L(t)+= *r - &adc("edx",0); # H(t)+=carry - &mov(&DWP($i,$r),"eax"); # *r= L(t); - &mov($c,"edx"); # c= H(t); - } - - &comment(""); - &sub("ecx",8); - &lea($a,&DWP(32,$a)); - &lea($r,&DWP(32,$r)); - &jnz(&label("maw_loop")); - - &set_label("maw_finish",0); - &mov("ecx",&wparam(2)); # get num - &and("ecx",7); - &jnz(&label("maw_finish2")); # helps branch prediction - &jmp(&label("maw_end")); - - &set_label("maw_finish2",1); - for ($i=0; $i<7; $i++) - { - &comment("Tail Round $i"); - &mov("eax",&DWP($i*4,$a)); # *a - &mul($w); # *a * w - &add("eax",$c); # L(t)+=c - &adc("edx",0); # H(t)+=carry - &add("eax",&DWP($i*4,$r)); # L(t)+= *r - &adc("edx",0); # H(t)+=carry - &dec("ecx") if ($i != 7-1); - &mov(&DWP($i*4,$r),"eax"); # *r= L(t); - &mov($c,"edx"); # c= H(t); - &jz(&label("maw_end")) if ($i != 7-1); - } - &set_label("maw_end",0); - &mov("eax",$c); - - &pop("ecx"); # clear variable from - &function_end($name); } @@ -221,17 +137,13 @@ sub bn_mul_words { local($name)=@_; - &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + &function_begin_B($name); $r="eax"; $a="edx"; $c="ecx"; if ($sse2) { - &picmeup("eax","OPENSSL_ia32cap_P"); - &bt(&DWP(0,"eax"),26); - &jnc(&label("mw_non_sse2")); - &mov($r,&wparam(0)); &mov($a,&wparam(1)); &mov($c,&wparam(2)); @@ -252,79 +164,7 @@ sub bn_mul_words &movd("eax","mm1"); # return carry &emms(); &ret(); - &set_label("mw_non_sse2",16); } - - # function_begin prologue - &push("ebp"); - &push("ebx"); - &push("esi"); - &push("edi"); - - &comment(""); - $Low="eax"; - $High="edx"; - $a="ebx"; - $w="ecx"; - $r="edi"; - $c="esi"; - $num="ebp"; - - &xor($c,$c); # clear carry - &mov($r,&wparam(0)); # - &mov($a,&wparam(1)); # - &mov($num,&wparam(2)); # - &mov($w,&wparam(3)); # - - &and($num,0xfffffff8); # num / 8 - &jz(&label("mw_finish")); - - &set_label("mw_loop",0); - for ($i=0; $i<32; $i+=4) - { - &comment("Round $i"); - - &mov("eax",&DWP($i,$a,"",0)); # *a - &mul($w); # *a * w - &add("eax",$c); # L(t)+=c - # XXX - - &adc("edx",0); # H(t)+=carry - &mov(&DWP($i,$r,"",0),"eax"); # *r= L(t); - - &mov($c,"edx"); # c= H(t); - } - - &comment(""); - &add($a,32); - &add($r,32); - &sub($num,8); - &jz(&label("mw_finish")); - &jmp(&label("mw_loop")); - - &set_label("mw_finish",0); - &mov($num,&wparam(2)); # get num - &and($num,7); - &jnz(&label("mw_finish2")); - &jmp(&label("mw_end")); - - &set_label("mw_finish2",1); - for ($i=0; $i<7; $i++) - { - &comment("Tail Round $i"); - &mov("eax",&DWP($i*4,$a,"",0));# *a - &mul($w); # *a * w - &add("eax",$c); # L(t)+=c - # XXX - &adc("edx",0); # H(t)+=carry - &mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t); - &mov($c,"edx"); # c= H(t); - &dec($num) if ($i != 7-1); - &jz(&label("mw_end")) if ($i != 7-1); - } - &set_label("mw_end",0); - &mov("eax",$c); - &function_end($name); } @@ -332,17 +172,13 @@ sub bn_sqr_words { local($name)=@_; - &function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":""); + &function_begin_B($name); $r="eax"; $a="edx"; $c="ecx"; if ($sse2) { - &picmeup("eax","OPENSSL_ia32cap_P"); - &bt(&DWP(0,"eax"),26); - &jnc(&label("sqr_non_sse2")); - &mov($r,&wparam(0)); &mov($a,&wparam(1)); &mov($c,&wparam(2)); @@ -358,62 +194,7 @@ sub bn_sqr_words &emms(); &ret(); - &set_label("sqr_non_sse2",16); } - - # function_begin prologue - &push("ebp"); - &push("ebx"); - &push("esi"); - &push("edi"); - - &comment(""); - $r="esi"; - $a="edi"; - $num="ebx"; - - &mov($r,&wparam(0)); # - &mov($a,&wparam(1)); # - &mov($num,&wparam(2)); # - - &and($num,0xfffffff8); # num / 8 - &jz(&label("sw_finish")); - - &set_label("sw_loop",0); - for ($i=0; $i<32; $i+=4) - { - &comment("Round $i"); - &mov("eax",&DWP($i,$a,"",0)); # *a - # XXX - &mul("eax"); # *a * *a - &mov(&DWP($i*2,$r,"",0),"eax"); # - &mov(&DWP($i*2+4,$r,"",0),"edx");# - } - - &comment(""); - &add($a,32); - &add($r,64); - &sub($num,8); - &jnz(&label("sw_loop")); - - &set_label("sw_finish",0); - &mov($num,&wparam(2)); # get num - &and($num,7); - &jz(&label("sw_end")); - - for ($i=0; $i<7; $i++) - { - &comment("Tail Round $i"); - &mov("eax",&DWP($i*4,$a,"",0)); # *a - # XXX - &mul("eax"); # *a * *a - &mov(&DWP($i*8,$r,"",0),"eax"); # - &dec($num) if ($i != 7-1); - &mov(&DWP($i*8+4,$r,"",0),"edx"); - &jz(&label("sw_end")) if ($i != 7-1); - } - &set_label("sw_end",0); - &function_end($name); } diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/x86-mont.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/x86-mont.pl index c097574a8f..7b7cca751d 100755 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/x86-mont.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/x86-mont.pl @@ -44,8 +44,6 @@ open STDOUT,">$output"; $sse2=1; -&external_label("OPENSSL_ia32cap_P") if ($sse2); - &function_begin("bn_mul_mont"); $i="edx"; @@ -146,10 +144,6 @@ $mul1="mm5"; $temp="mm6"; $mask="mm7"; - &picmeup("eax","OPENSSL_ia32cap_P"); - &bt (&DWP(0,"eax"),26); - &jnc (&label("non_sse2")); - &mov ("eax",-1); &movd ($mask,"eax"); # mask 32 lower bits @@ -291,298 +285,6 @@ $mask="mm7"; &emms (); # done with mmx bank &jmp (&label("common_tail")); - -&set_label("non_sse2",16); -} - -if (0) { - &mov ("esp",$_sp); - &xor ("eax","eax"); # signal "not fast enough [yet]" - &jmp (&label("just_leave")); - # While the below code provides competitive performance for - # all key lengths on modern Intel cores, it's still more - # than 10% slower for 4096-bit key elsewhere:-( "Competitive" - # means compared to the original integer-only assembler. - # 512-bit RSA sign is better by ~40%, but that's about all - # one can say about all CPUs... -} else { -$inp="esi"; # integer path uses these registers differently -$word="edi"; -$carry="ebp"; - - &mov ($inp,$_ap); - &lea ($carry,&DWP(1,$num)); - &mov ($word,$_bp); - &xor ($j,$j); # j=0 - &mov ("edx",$inp); - &and ($carry,1); # see if num is even - &sub ("edx",$word); # see if ap==bp - &lea ("eax",&DWP(4,$word,$num,4)); # &bp[num] - &or ($carry,"edx"); - &mov ($word,&DWP(0,$word)); # bp[0] - &jz (&label("bn_sqr_mont")); - &mov ($_bpend,"eax"); - &mov ("eax",&DWP(0,$inp)); - &xor ("edx","edx"); - -&set_label("mull",16); - &mov ($carry,"edx"); - &mul ($word); # ap[j]*bp[0] - &add ($carry,"eax"); - &lea ($j,&DWP(1,$j)); - &adc ("edx",0); - &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1] - &cmp ($j,$num); - &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= - &jl (&label("mull")); - - &mov ($carry,"edx"); - &mul ($word); # ap[num-1]*bp[0] - &mov ($word,$_n0); - &add ("eax",$carry); - &mov ($inp,$_np); - &adc ("edx",0); - &imul ($word,&DWP($frame,"esp")); # n0*tp[0] - - &mov (&DWP($frame,"esp",$num,4),"eax"); # tp[num-1]= - &xor ($j,$j); - &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]= - &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]= - - &mov ("eax",&DWP(0,$inp)); # np[0] - &mul ($word); # np[0]*m - &add ("eax",&DWP($frame,"esp")); # +=tp[0] - &mov ("eax",&DWP(4,$inp)); # np[1] - &adc ("edx",0); - &inc ($j); - - &jmp (&label("2ndmadd")); - -&set_label("1stmadd",16); - &mov ($carry,"edx"); - &mul ($word); # ap[j]*bp[i] - &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] - &lea ($j,&DWP(1,$j)); - &adc ("edx",0); - &add ($carry,"eax"); - &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1] - &adc ("edx",0); - &cmp ($j,$num); - &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= - &jl (&label("1stmadd")); - - &mov ($carry,"edx"); - &mul ($word); # ap[num-1]*bp[i] - &add ("eax",&DWP($frame,"esp",$num,4)); # +=tp[num-1] - &mov ($word,$_n0); - &adc ("edx",0); - &mov ($inp,$_np); - &add ($carry,"eax"); - &adc ("edx",0); - &imul ($word,&DWP($frame,"esp")); # n0*tp[0] - - &xor ($j,$j); - &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] - &mov (&DWP($frame,"esp",$num,4),$carry); # tp[num-1]= - &adc ($j,0); - &mov ("eax",&DWP(0,$inp)); # np[0] - &mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]= - &mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]= - - &mul ($word); # np[0]*m - &add ("eax",&DWP($frame,"esp")); # +=tp[0] - &mov ("eax",&DWP(4,$inp)); # np[1] - &adc ("edx",0); - &mov ($j,1); - -&set_label("2ndmadd",16); - &mov ($carry,"edx"); - &mul ($word); # np[j]*m - &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] - &lea ($j,&DWP(1,$j)); - &adc ("edx",0); - &add ($carry,"eax"); - &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+1] - &adc ("edx",0); - &cmp ($j,$num); - &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j-1]= - &jl (&label("2ndmadd")); - - &mov ($carry,"edx"); - &mul ($word); # np[j]*m - &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1] - &adc ("edx",0); - &add ($carry,"eax"); - &adc ("edx",0); - &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]= - - &xor ("eax","eax"); - &mov ($j,$_bp); # &bp[i] - &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] - &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1] - &lea ($j,&DWP(4,$j)); - &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]= - &cmp ($j,$_bpend); - &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]= - &je (&label("common_tail")); - - &mov ($word,&DWP(0,$j)); # bp[i+1] - &mov ($inp,$_ap); - &mov ($_bp,$j); # &bp[++i] - &xor ($j,$j); - &xor ("edx","edx"); - &mov ("eax",&DWP(0,$inp)); - &jmp (&label("1stmadd")); - -&set_label("bn_sqr_mont",16); -$sbit=$num; - &mov ($_num,$num); - &mov ($_bp,$j); # i=0 - - &mov ("eax",$word); # ap[0] - &mul ($word); # ap[0]*ap[0] - &mov (&DWP($frame,"esp"),"eax"); # tp[0]= - &mov ($sbit,"edx"); - &shr ("edx",1); - &and ($sbit,1); - &inc ($j); -&set_label("sqr",16); - &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j] - &mov ($carry,"edx"); - &mul ($word); # ap[j]*ap[0] - &add ("eax",$carry); - &lea ($j,&DWP(1,$j)); - &adc ("edx",0); - &lea ($carry,&DWP(0,$sbit,"eax",2)); - &shr ("eax",31); - &cmp ($j,$_num); - &mov ($sbit,"eax"); - &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= - &jl (&label("sqr")); - - &mov ("eax",&DWP(0,$inp,$j,4)); # ap[num-1] - &mov ($carry,"edx"); - &mul ($word); # ap[num-1]*ap[0] - &add ("eax",$carry); - &mov ($word,$_n0); - &adc ("edx",0); - &mov ($inp,$_np); - &lea ($carry,&DWP(0,$sbit,"eax",2)); - &imul ($word,&DWP($frame,"esp")); # n0*tp[0] - &shr ("eax",31); - &mov (&DWP($frame,"esp",$j,4),$carry); # tp[num-1]= - - &lea ($carry,&DWP(0,"eax","edx",2)); - &mov ("eax",&DWP(0,$inp)); # np[0] - &shr ("edx",31); - &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num]= - &mov (&DWP($frame+8,"esp",$j,4),"edx"); # tp[num+1]= - - &mul ($word); # np[0]*m - &add ("eax",&DWP($frame,"esp")); # +=tp[0] - &mov ($num,$j); - &adc ("edx",0); - &mov ("eax",&DWP(4,$inp)); # np[1] - &mov ($j,1); - -&set_label("3rdmadd",16); - &mov ($carry,"edx"); - &mul ($word); # np[j]*m - &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] - &adc ("edx",0); - &add ($carry,"eax"); - &mov ("eax",&DWP(4,$inp,$j,4)); # np[j+1] - &adc ("edx",0); - &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j-1]= - - &mov ($carry,"edx"); - &mul ($word); # np[j+1]*m - &add ($carry,&DWP($frame+4,"esp",$j,4)); # +=tp[j+1] - &lea ($j,&DWP(2,$j)); - &adc ("edx",0); - &add ($carry,"eax"); - &mov ("eax",&DWP(0,$inp,$j,4)); # np[j+2] - &adc ("edx",0); - &cmp ($j,$num); - &mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j]= - &jl (&label("3rdmadd")); - - &mov ($carry,"edx"); - &mul ($word); # np[j]*m - &add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1] - &adc ("edx",0); - &add ($carry,"eax"); - &adc ("edx",0); - &mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]= - - &mov ($j,$_bp); # i - &xor ("eax","eax"); - &mov ($inp,$_ap); - &add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num] - &adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1] - &mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]= - &cmp ($j,$num); - &mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]= - &je (&label("common_tail")); - - &mov ($word,&DWP(4,$inp,$j,4)); # ap[i] - &lea ($j,&DWP(1,$j)); - &mov ("eax",$word); - &mov ($_bp,$j); # ++i - &mul ($word); # ap[i]*ap[i] - &add ("eax",&DWP($frame,"esp",$j,4)); # +=tp[i] - &adc ("edx",0); - &mov (&DWP($frame,"esp",$j,4),"eax"); # tp[i]= - &xor ($carry,$carry); - &cmp ($j,$num); - &lea ($j,&DWP(1,$j)); - &je (&label("sqrlast")); - - &mov ($sbit,"edx"); # zaps $num - &shr ("edx",1); - &and ($sbit,1); -&set_label("sqradd",16); - &mov ("eax",&DWP(0,$inp,$j,4)); # ap[j] - &mov ($carry,"edx"); - &mul ($word); # ap[j]*ap[i] - &add ("eax",$carry); - &lea ($carry,&DWP(0,"eax","eax")); - &adc ("edx",0); - &shr ("eax",31); - &add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j] - &lea ($j,&DWP(1,$j)); - &adc ("eax",0); - &add ($carry,$sbit); - &adc ("eax",0); - &cmp ($j,$_num); - &mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]= - &mov ($sbit,"eax"); - &jle (&label("sqradd")); - - &mov ($carry,"edx"); - &add ("edx","edx"); - &shr ($carry,31); - &add ("edx",$sbit); - &adc ($carry,0); -&set_label("sqrlast"); - &mov ($word,$_n0); - &mov ($inp,$_np); - &imul ($word,&DWP($frame,"esp")); # n0*tp[0] - - &add ("edx",&DWP($frame,"esp",$j,4)); # +=tp[num] - &mov ("eax",&DWP(0,$inp)); # np[0] - &adc ($carry,0); - &mov (&DWP($frame,"esp",$j,4),"edx"); # tp[num]= - &mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num+1]= - - &mul ($word); # np[0]*m - &add ("eax",&DWP($frame,"esp")); # +=tp[0] - &lea ($num,&DWP(-1,$j)); - &adc ("edx",0); - &mov ($j,1); - &mov ("eax",&DWP(4,$inp)); # np[1] - - &jmp (&label("3rdmadd")); } &set_label("common_tail",16); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/x86_64-mont5.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/x86_64-mont5.pl index 88d98af298..a944739fe7 100755 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/x86_64-mont5.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/asm/x86_64-mont5.pl @@ -50,7 +50,7 @@ open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; # output, so this isn't useful anyway. $addx = 1; -# int bn_mul_mont_gather5( +# int bn_mul_mont_gather5_nohw( $rp="%rdi"; # BN_ULONG *rp, $ap="%rsi"; # const BN_ULONG *ap, $bp="%rdx"; # const BN_ULONG *bp, @@ -72,29 +72,17 @@ $m1="%rbp"; $code=<<___; .text -.extern OPENSSL_ia32cap_P - -.globl bn_mul_mont_gather5 -.type bn_mul_mont_gather5,\@function,6 +.globl bn_mul_mont_gather5_nohw +.type bn_mul_mont_gather5_nohw,\@function,6 .align 64 -bn_mul_mont_gather5: +bn_mul_mont_gather5_nohw: .cfi_startproc _CET_ENDBR + # num is declared as an int, a 32-bit parameter, so the upper half is + # undefined. Zero the upper half to normalize it. mov ${num}d,${num}d mov %rsp,%rax .cfi_def_cfa_register %rax - test \$7,${num}d - jnz .Lmul_enter -___ -$code.=<<___ if ($addx); - leaq OPENSSL_ia32cap_P(%rip),%r11 - mov 8(%r11),%r11d -___ -$code.=<<___; - jmp .Lmul4x_enter - -.align 16 -.Lmul_enter: movd `($win64?56:8)`(%rsp),%xmm5 # load 7th argument push %rbx .cfi_push %rbx @@ -454,27 +442,21 @@ $code.=<<___; .Lmul_epilogue: ret .cfi_endproc -.size bn_mul_mont_gather5,.-bn_mul_mont_gather5 +.size bn_mul_mont_gather5_nohw,.-bn_mul_mont_gather5_nohw ___ {{{ my @A=("%r10","%r11"); my @N=("%r13","%rdi"); $code.=<<___; +.globl bn_mul4x_mont_gather5 .type bn_mul4x_mont_gather5,\@function,6 .align 32 bn_mul4x_mont_gather5: .cfi_startproc + _CET_ENDBR .byte 0x67 mov %rsp,%rax .cfi_def_cfa_register %rax -.Lmul4x_enter: -___ -$code.=<<___ if ($addx); - and \$0x80108,%r11d - cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 - je .Lmulx4x_enter -___ -$code.=<<___; push %rbx .cfi_push %rbx push %rbp @@ -490,6 +472,9 @@ $code.=<<___; .Lmul4x_prologue: .byte 0x67 + # num is declared as an int, a 32-bit parameter, so the upper half is + # undefined. It is important that this write to ${num}, which zeros the + # upper half, predates the first access. shl \$3,${num}d # convert $num to bytes lea ($num,$num,2),%r10 # 3*$num in bytes neg $num # -$num @@ -1079,7 +1064,7 @@ ___ }}} {{{ ###################################################################### -# void bn_power5( +# void bn_power5_nohw( my $rptr="%rdi"; # BN_ULONG *rptr, my $aptr="%rsi"; # const BN_ULONG *aptr, my $bptr="%rdx"; # const BN_ULONG *table, @@ -1094,23 +1079,14 @@ my @A1=("%r12","%r13"); my ($a0,$a1,$ai)=("%r14","%r15","%rbx"); $code.=<<___; -.globl bn_power5 -.type bn_power5,\@function,6 +.globl bn_power5_nohw +.type bn_power5_nohw,\@function,6 .align 32 -bn_power5: +bn_power5_nohw: .cfi_startproc _CET_ENDBR mov %rsp,%rax .cfi_def_cfa_register %rax -___ -$code.=<<___ if ($addx); - leaq OPENSSL_ia32cap_P(%rip),%r11 - mov 8(%r11),%r11d - and \$0x80108,%r11d - cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 - je .Lpowerx5_enter -___ -$code.=<<___; push %rbx .cfi_push %rbx push %rbp @@ -1125,6 +1101,9 @@ $code.=<<___; .cfi_push %r15 .Lpower5_prologue: + # num is declared as an int, a 32-bit parameter, so the upper half is + # undefined. It is important that this write to ${num}, which zeros the + # upper half, come before the first access. shl \$3,${num}d # convert $num to bytes lea ($num,$num,2),%r10d # 3*$num neg $num @@ -1233,7 +1212,7 @@ $code.=<<___; .Lpower5_epilogue: ret .cfi_endproc -.size bn_power5,.-bn_power5 +.size bn_power5_nohw,.-bn_power5_nohw .globl bn_sqr8x_internal .hidden bn_sqr8x_internal @@ -2108,13 +2087,14 @@ if ($addx) {{{ my $bp="%rdx"; # restore original value $code.=<<___; +.globl bn_mulx4x_mont_gather5 .type bn_mulx4x_mont_gather5,\@function,6 .align 32 bn_mulx4x_mont_gather5: .cfi_startproc + _CET_ENDBR mov %rsp,%rax .cfi_def_cfa_register %rax -.Lmulx4x_enter: push %rbx .cfi_push %rbx push %rbp @@ -2129,6 +2109,9 @@ bn_mulx4x_mont_gather5: .cfi_push %r15 .Lmulx4x_prologue: + # num is declared as an int, a 32-bit parameter, so the upper half is + # undefined. It is important that this write to ${num}, which zeros the + # upper half, predates the first access. shl \$3,${num}d # convert $num to bytes lea ($num,$num,2),%r10 # 3*$num in bytes neg $num # -$num @@ -2583,7 +2566,7 @@ $code.=<<___; ___ } { ###################################################################### -# void bn_power5( +# void bn_powerx5( my $rptr="%rdi"; # BN_ULONG *rptr, my $aptr="%rsi"; # const BN_ULONG *aptr, my $bptr="%rdx"; # const BN_ULONG *table, @@ -2598,13 +2581,14 @@ my @A1=("%r12","%r13"); my ($a0,$a1,$ai)=("%r14","%r15","%rbx"); $code.=<<___; +.globl bn_powerx5 .type bn_powerx5,\@function,6 .align 32 bn_powerx5: .cfi_startproc + _CET_ENDBR mov %rsp,%rax .cfi_def_cfa_register %rax -.Lpowerx5_enter: push %rbx .cfi_push %rbx push %rbp @@ -2619,6 +2603,9 @@ bn_powerx5: .cfi_push %r15 .Lpowerx5_prologue: + # num is declared as an int, a 32-bit parameter, so the upper half is + # undefined. It is important that this write to ${num}, which zeros the + # upper half, predates the first access. shl \$3,${num}d # convert $num to bytes lea ($num,$num,2),%r10 # 3*$num in bytes neg $num @@ -3705,17 +3692,17 @@ mul_handler: .section .pdata .align 4 - .rva .LSEH_begin_bn_mul_mont_gather5 - .rva .LSEH_end_bn_mul_mont_gather5 - .rva .LSEH_info_bn_mul_mont_gather5 + .rva .LSEH_begin_bn_mul_mont_gather5_nohw + .rva .LSEH_end_bn_mul_mont_gather5_nohw + .rva .LSEH_info_bn_mul_mont_gather5_nohw .rva .LSEH_begin_bn_mul4x_mont_gather5 .rva .LSEH_end_bn_mul4x_mont_gather5 .rva .LSEH_info_bn_mul4x_mont_gather5 - .rva .LSEH_begin_bn_power5 - .rva .LSEH_end_bn_power5 - .rva .LSEH_info_bn_power5 + .rva .LSEH_begin_bn_power5_nohw + .rva .LSEH_end_bn_power5_nohw + .rva .LSEH_info_bn_power5_nohw ___ $code.=<<___ if ($addx); .rva .LSEH_begin_bn_mulx4x_mont_gather5 @@ -3733,7 +3720,7 @@ $code.=<<___; .section .xdata .align 8 -.LSEH_info_bn_mul_mont_gather5: +.LSEH_info_bn_mul_mont_gather5_nohw: .byte 9,0,0,0 .rva mul_handler .rva .Lmul_body,.Lmul_body,.Lmul_epilogue # HandlerData[] @@ -3743,7 +3730,7 @@ $code.=<<___; .rva mul_handler .rva .Lmul4x_prologue,.Lmul4x_body,.Lmul4x_epilogue # HandlerData[] .align 8 -.LSEH_info_bn_power5: +.LSEH_info_bn_power5_nohw: .byte 9,0,0,0 .rva mul_handler .rva .Lpower5_prologue,.Lpower5_body,.Lpower5_epilogue # HandlerData[] diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/exponentiation.c b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/exponentiation.c index 53c6142bd7..9030aa8cbe 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/exponentiation.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/exponentiation.c @@ -119,6 +119,50 @@ #include "internal.h" #include "rsaz_exp.h" +#if defined(OPENSSL_BN_ASM_MONT5) + +// bn_mul_mont_gather5 multiples loads index |power| of |table|, multiplies it +// by |ap| modulo |np|, and stores the result in |rp|. The values are |num| +// words long and represented in Montgomery form. |n0| is a pointer to the +// corresponding field in |BN_MONT_CTX|. |table| must be aligned to at least +// 16 bytes. |power| must be less than 32 and is treated as secret. +// +// WARNING: This function implements Almost Montgomery Multiplication from +// https://eprint.iacr.org/2011/239. The inputs do not need to be fully reduced. +// However, even if they are fully reduced, the output may not be. +static void bn_mul_mont_gather5( + BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power) { + if (bn_mulx4x_mont_gather5_capable(num)) { + bn_mulx4x_mont_gather5(rp, ap, table, np, n0, num, power); + } else if (bn_mul4x_mont_gather5_capable(num)) { + bn_mul4x_mont_gather5(rp, ap, table, np, n0, num, power); + } else { + bn_mul_mont_gather5_nohw(rp, ap, table, np, n0, num, power); + } +} + +// bn_power5 squares |ap| five times and multiplies it by the value stored at +// index |power| of |table|, modulo |np|. It stores the result in |rp|. The +// values are |num| words long and represented in Montgomery form. |n0| is a +// pointer to the corresponding field in |BN_MONT_CTX|. |num| must be divisible +// by 8. |power| must be less than 32 and is treated as secret. +// +// WARNING: This function implements Almost Montgomery Multiplication from +// https://eprint.iacr.org/2011/239. The inputs do not need to be fully reduced. +// However, even if they are fully reduced, the output may not be. +static void bn_power5(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, + const BN_ULONG *np, const BN_ULONG *n0, int num, + int power) { + assert(bn_power5_capable(num)); + if (bn_powerx5_capable(num)) { + bn_powerx5(rp, ap, table, np, n0, num, power); + } else { + bn_power5_nohw(rp, ap, table, np, n0, num, power); + } +} + +#endif // defined(OPENSSL_BN_ASM_MONT5) int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { int i, bits, ret = 0; @@ -1079,7 +1123,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, // Scan the exponent one window at a time starting from the most // significant bits. - if (top & 7) { + if (!bn_power5_capable(top)) { while (bits >= 0) { for (wvalue = 0, i = 0; i < 5; i++, bits--) { wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/internal.h index 02711603ea..679e249ce9 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/bn/internal.h @@ -438,18 +438,26 @@ int bn_mul_mont_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) #define OPENSSL_BN_ASM_MONT5 -// bn_mul_mont_gather5 multiples loads index |power| of |table|, multiplies it -// by |ap| modulo |np|, and stores the result in |rp|. The values are |num| -// words long and represented in Montgomery form. |n0| is a pointer to the -// corresponding field in |BN_MONT_CTX|. |table| must be aligned to at least -// 16 bytes. |power| must be less than 32 and is treated as secret. -// -// WARNING: This function implements Almost Montgomery Multiplication from -// https://eprint.iacr.org/2011/239. The inputs do not need to be fully reduced. -// However, even if they are fully reduced, the output may not be. -void bn_mul_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, - const BN_ULONG *table, const BN_ULONG *np, - const BN_ULONG *n0, int num, int power); +// The following functions implement |bn_mul_mont_gather5|. See +// |bn_mul_mont_gather5| for details. +OPENSSL_INLINE int bn_mul4x_mont_gather5_capable(int num) { + return (num & 7) == 0; +} +void bn_mul4x_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + +OPENSSL_INLINE int bn_mulx4x_mont_gather5_capable(int num) { + return bn_mul4x_mont_gather5_capable(num) && CRYPTO_is_ADX_capable() && + CRYPTO_is_BMI1_capable() && CRYPTO_is_BMI2_capable(); +} +void bn_mulx4x_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + +void bn_mul_mont_gather5_nohw(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); // bn_scatter5 stores |inp| to index |power| of |table|. |inp| and each entry of // |table| are |num| words long. |power| must be less than 32 and is treated as @@ -463,17 +471,19 @@ void bn_scatter5(const BN_ULONG *inp, size_t num, BN_ULONG *table, // is treated as secret. |table| must be aligned to at least 16 bytes. void bn_gather5(BN_ULONG *out, size_t num, const BN_ULONG *table, size_t power); -// bn_power5 squares |ap| five times and multiplies it by the value stored at -// index |power| of |table|, modulo |np|. It stores the result in |rp|. The -// values are |num| words long and represented in Montgomery form. |n0| is a -// pointer to the corresponding field in |BN_MONT_CTX|. |num| must be divisible -// by 8. |power| must be less than 32 and is treated as secret. -// -// WARNING: This function implements Almost Montgomery Multiplication from -// https://eprint.iacr.org/2011/239. The inputs do not need to be fully reduced. -// However, even if they are fully reduced, the output may not be. -void bn_power5(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, - const BN_ULONG *np, const BN_ULONG *n0, int num, int power); +// The following functions implement |bn_power5|. See |bn_power5| for details. +void bn_power5_nohw(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, + const BN_ULONG *np, const BN_ULONG *n0, int num, int power); + +OPENSSL_INLINE int bn_power5_capable(int num) { return (num & 7) == 0; } + +OPENSSL_INLINE int bn_powerx5_capable(int num) { + return bn_power5_capable(num) && CRYPTO_is_ADX_capable() && + CRYPTO_is_BMI1_capable() && CRYPTO_is_BMI2_capable(); +} +void bn_powerx5(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *table, + const BN_ULONG *np, const BN_ULONG *n0, int num, int power); + #endif // !OPENSSL_NO_ASM && OPENSSL_X86_64 uint64_t bn_mont_n0(const BIGNUM *n); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/ec/p256-nistz.c b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/ec/p256-nistz.c index cf09963828..7d3e2fba4b 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/ec/p256-nistz.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/ec/p256-nistz.c @@ -612,6 +612,11 @@ static int ecp_nistz256_cmp_x_coordinate(const EC_GROUP *group, } DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistz256_method) { + // TODO(crbug.com/42290548): The x86_64 assembly depends on initializing + // |OPENSSL_ia32cap_P|. Move the dispatch to C. For now, explicitly initialize + // things. + OPENSSL_init_cpuid(); + out->point_get_affine_coordinates = ecp_nistz256_get_affine; out->add = ecp_nistz256_add; out->dbl = ecp_nistz256_dbl; diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/fips_shared_support.c b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/fips_shared_support.c index 2a66a1f064..74b35f0160 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/fips_shared_support.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/fips_shared_support.c @@ -20,13 +20,10 @@ // that must be replaced with the real value during the build process. This // value need only be distinct, i.e. so that we can safely search-and-replace it // in an object file. -const uint8_t BORINGSSL_bcm_text_hash[64]; -const uint8_t BORINGSSL_bcm_text_hash[64] = { +const uint8_t BORINGSSL_bcm_text_hash[32]; +const uint8_t BORINGSSL_bcm_text_hash[32] = { 0xae, 0x2c, 0xea, 0x2a, 0xbd, 0xa6, 0xf3, 0xec, 0x97, 0x7f, 0x9b, 0xf6, 0x94, 0x9a, 0xfc, 0x83, 0x68, 0x27, 0xcb, 0xa0, 0xa0, 0x9f, - 0x6b, 0x6f, 0xde, 0x52, 0xcd, 0xe2, 0xcd, 0xff, 0x31, 0x80, 0xa2, - 0xd4, 0xc3, 0x66, 0x0f, 0xc2, 0x6a, 0x7b, 0xf4, 0xbe, 0x39, 0xa2, - 0xd7, 0x25, 0xdb, 0x21, 0x98, 0xe9, 0xd5, 0x53, 0xbf, 0x5c, 0x32, - 0x06, 0x83, 0x34, 0x0c, 0x65, 0x89, 0x52, 0xbd, 0x1f, + 0x6b, 0x6f, 0xde, 0x52, 0xcd, 0xe2, 0xcd, 0xff, 0x31, 0x80, }; #endif // FIPS && SHARED_LIBRARY diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/aesni-gcm-x86_64.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/aesni-gcm-x86_64.pl index 82e46d48a6..eabaa1b967 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/aesni-gcm-x86_64.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/aesni-gcm-x86_64.pl @@ -474,7 +474,7 @@ ___ if ($win64) { $code.=<<___ lea -0xa8(%rsp),%rsp # 8 extra bytes to align the stack -.seh_allocstack 0xa8 +.seh_stackalloc 0xa8 .seh_setframe %rbp, 0xa8+5*8 # Load the last two parameters. These go into %rdi and %rsi, which are # non-volatile on Windows, so stash them in the parameter stack area @@ -487,25 +487,26 @@ $code.=<<___ mov 0x38(%rbp), $Htable # Save non-volatile XMM registers. movaps %xmm6,-0xd0(%rbp) -.seh_savexmm128 %xmm6, 0xa8+5*8-0xd0 +.seh_savexmm %xmm6, 0xa8+5*8-0xd0 movaps %xmm7,-0xc0(%rbp) -.seh_savexmm128 %xmm7, 0xa8+5*8-0xc0 +.seh_savexmm %xmm7, 0xa8+5*8-0xc0 movaps %xmm8,-0xb0(%rbp) -.seh_savexmm128 %xmm8, 0xa8+5*8-0xb0 +.seh_savexmm %xmm8, 0xa8+5*8-0xb0 movaps %xmm9,-0xa0(%rbp) -.seh_savexmm128 %xmm9, 0xa8+5*8-0xa0 +.seh_savexmm %xmm9, 0xa8+5*8-0xa0 movaps %xmm10,-0x90(%rbp) -.seh_savexmm128 %xmm10, 0xa8+5*8-0x90 +.seh_savexmm %xmm10, 0xa8+5*8-0x90 movaps %xmm11,-0x80(%rbp) -.seh_savexmm128 %xmm11, 0xa8+5*8-0x80 +.seh_savexmm %xmm11, 0xa8+5*8-0x80 movaps %xmm12,-0x70(%rbp) -.seh_savexmm128 %xmm12, 0xa8+5*8-0x70 +.seh_savexmm %xmm12, 0xa8+5*8-0x70 movaps %xmm13,-0x60(%rbp) -.seh_savexmm128 %xmm13, 0xa8+5*8-0x60 +.seh_savexmm %xmm13, 0xa8+5*8-0x60 movaps %xmm14,-0x50(%rbp) -.seh_savexmm128 %xmm14, 0xa8+5*8-0x50 +.seh_savexmm %xmm14, 0xa8+5*8-0x50 movaps %xmm15,-0x40(%rbp) -.seh_savexmm128 %xmm15, 0xa8+5*8-0x40 +.seh_savexmm %xmm15, 0xa8+5*8-0x40 +.seh_endprologue ___ } $code.=<<___; @@ -753,7 +754,7 @@ ___ if ($win64) { $code.=<<___ lea -0xa8(%rsp),%rsp # 8 extra bytes to align the stack -.seh_allocstack 0xa8 +.seh_stackalloc 0xa8 .seh_setframe %rbp, 0xa8+5*8 # Load the last two parameters. These go into %rdi and %rsi, which are # non-volatile on Windows, so stash them in the parameter stack area @@ -766,25 +767,26 @@ $code.=<<___ mov 0x38(%rbp), $Htable # Save non-volatile XMM registers. movaps %xmm6,-0xd0(%rbp) -.seh_savexmm128 %xmm6, 0xa8+5*8-0xd0 +.seh_savexmm %xmm6, 0xa8+5*8-0xd0 movaps %xmm7,-0xc0(%rbp) -.seh_savexmm128 %xmm7, 0xa8+5*8-0xc0 +.seh_savexmm %xmm7, 0xa8+5*8-0xc0 movaps %xmm8,-0xb0(%rbp) -.seh_savexmm128 %xmm8, 0xa8+5*8-0xb0 +.seh_savexmm %xmm8, 0xa8+5*8-0xb0 movaps %xmm9,-0xa0(%rbp) -.seh_savexmm128 %xmm9, 0xa8+5*8-0xa0 +.seh_savexmm %xmm9, 0xa8+5*8-0xa0 movaps %xmm10,-0x90(%rbp) -.seh_savexmm128 %xmm10, 0xa8+5*8-0x90 +.seh_savexmm %xmm10, 0xa8+5*8-0x90 movaps %xmm11,-0x80(%rbp) -.seh_savexmm128 %xmm11, 0xa8+5*8-0x80 +.seh_savexmm %xmm11, 0xa8+5*8-0x80 movaps %xmm12,-0x70(%rbp) -.seh_savexmm128 %xmm12, 0xa8+5*8-0x70 +.seh_savexmm %xmm12, 0xa8+5*8-0x70 movaps %xmm13,-0x60(%rbp) -.seh_savexmm128 %xmm13, 0xa8+5*8-0x60 +.seh_savexmm %xmm13, 0xa8+5*8-0x60 movaps %xmm14,-0x50(%rbp) -.seh_savexmm128 %xmm14, 0xa8+5*8-0x50 +.seh_savexmm %xmm14, 0xa8+5*8-0x50 movaps %xmm15,-0x40(%rbp) -.seh_savexmm128 %xmm15, 0xa8+5*8-0x40 +.seh_savexmm %xmm15, 0xa8+5*8-0x40 +.seh_endprologue ___ } $code.=<<___; diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/ghash-ssse3-x86_64.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/ghash-ssse3-x86_64.pl index 4a850f479b..bdfbe04d7b 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/ghash-ssse3-x86_64.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/ghash-ssse3-x86_64.pl @@ -108,11 +108,12 @@ gcm_gmult_ssse3: ____ $code .= <<____ if ($win64); subq \$40, %rsp -.seh_allocstack 40 +.seh_stackalloc 40 movdqa %xmm6, (%rsp) -.seh_savexmm128 %xmm6, 0 +.seh_savexmm %xmm6, 0 movdqa %xmm10, 16(%rsp) -.seh_savexmm128 %xmm10, 16 +.seh_savexmm %xmm10, 16 +.seh_endprologue ____ $code .= <<____; movdqu ($Xi), %xmm0 @@ -251,13 +252,14 @@ gcm_ghash_ssse3: ____ $code .= <<____ if ($win64); subq \$56, %rsp -.seh_allocstack 56 +.seh_stackalloc 56 movdqa %xmm6, (%rsp) -.seh_savexmm128 %xmm6, 0 +.seh_savexmm %xmm6, 0 movdqa %xmm10, 16(%rsp) -.seh_savexmm128 %xmm10, 16 +.seh_savexmm %xmm10, 16 movdqa %xmm11, 32(%rsp) -.seh_savexmm128 %xmm11, 32 +.seh_savexmm %xmm11, 32 +.seh_endprologue ____ $code .= <<____; movdqu ($Xi), %xmm0 diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/ghash-x86_64.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/ghash-x86_64.pl index 33ee1cbabb..c026d8f9df 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/ghash-x86_64.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/modes/asm/ghash-x86_64.pl @@ -210,9 +210,10 @@ gcm_init_clmul: ___ $code.=<<___ if ($win64); sub \$0x18,%rsp -.seh_allocstack 0x18 +.seh_stackalloc 0x18 movaps %xmm6,(%rsp) -.seh_savexmm128 %xmm6, 0 +.seh_savexmm %xmm6, 0 +.seh_endprologue ___ $code.=<<___; movdqu ($Xip),$Hkey @@ -347,27 +348,28 @@ ___ $code.=<<___ if ($win64); lea -0x88(%rsp),%rax lea -0x20(%rax),%rsp -.seh_allocstack 0x20+0x88 +.seh_stackalloc 0x20+0x88 movaps %xmm6,-0x20(%rax) -.seh_savexmm128 %xmm6, 0x20-0x20 +.seh_savexmm %xmm6, 0x20-0x20 movaps %xmm7,-0x10(%rax) -.seh_savexmm128 %xmm7, 0x20-0x10 +.seh_savexmm %xmm7, 0x20-0x10 movaps %xmm8,0(%rax) -.seh_savexmm128 %xmm8, 0x20+0 +.seh_savexmm %xmm8, 0x20+0 movaps %xmm9,0x10(%rax) -.seh_savexmm128 %xmm9, 0x20+0x10 +.seh_savexmm %xmm9, 0x20+0x10 movaps %xmm10,0x20(%rax) -.seh_savexmm128 %xmm10, 0x20+0x20 +.seh_savexmm %xmm10, 0x20+0x20 movaps %xmm11,0x30(%rax) -.seh_savexmm128 %xmm11, 0x20+0x30 +.seh_savexmm %xmm11, 0x20+0x30 movaps %xmm12,0x40(%rax) -.seh_savexmm128 %xmm12, 0x20+0x40 +.seh_savexmm %xmm12, 0x20+0x40 movaps %xmm13,0x50(%rax) -.seh_savexmm128 %xmm13, 0x20+0x50 +.seh_savexmm %xmm13, 0x20+0x50 movaps %xmm14,0x60(%rax) -.seh_savexmm128 %xmm14, 0x20+0x60 +.seh_savexmm %xmm14, 0x20+0x60 movaps %xmm15,0x70(%rax) -.seh_savexmm128 %xmm15, 0x20+0x70 +.seh_savexmm %xmm15, 0x20+0x70 +.seh_endprologue ___ $code.=<<___; movdqa .Lbswap_mask(%rip),$T3 @@ -704,6 +706,7 @@ $code.=<<___; .align 32 gcm_init_avx: .cfi_startproc +.seh_startproc _CET_ENDBR ___ if ($avx) { @@ -711,11 +714,11 @@ my ($Htbl,$Xip)=@_4args; my $HK="%xmm6"; $code.=<<___ if ($win64); -.seh_startproc sub \$0x18,%rsp -.seh_allocstack 0x18 +.seh_stackalloc 0x18 movaps %xmm6,(%rsp) -.seh_savexmm128 %xmm6, 0 +.seh_savexmm %xmm6, 0 +.seh_endprologue ___ $code.=<<___; vzeroupper @@ -862,6 +865,7 @@ $code.=<<___; .align 32 gcm_ghash_avx: .cfi_startproc +.seh_startproc _CET_ENDBR ___ if ($avx) { @@ -872,30 +876,30 @@ my ($Xlo,$Xhi,$Xmi, $Xi,$Xo,$Tred,$bswap,$Ii,$Ij) = map("%xmm$_",(0..15)); $code.=<<___ if ($win64); -.seh_startproc lea -0x88(%rsp),%rax lea -0x20(%rax),%rsp -.seh_allocstack 0x20+0x88 +.seh_stackalloc 0x20+0x88 movaps %xmm6,-0x20(%rax) -.seh_savexmm128 %xmm6, 0x20-0x20 +.seh_savexmm %xmm6, 0x20-0x20 movaps %xmm7,-0x10(%rax) -.seh_savexmm128 %xmm7, 0x20-0x10 +.seh_savexmm %xmm7, 0x20-0x10 movaps %xmm8,0(%rax) -.seh_savexmm128 %xmm8, 0x20+0 +.seh_savexmm %xmm8, 0x20+0 movaps %xmm9,0x10(%rax) -.seh_savexmm128 %xmm9, 0x20+0x10 +.seh_savexmm %xmm9, 0x20+0x10 movaps %xmm10,0x20(%rax) -.seh_savexmm128 %xmm10, 0x20+0x20 +.seh_savexmm %xmm10, 0x20+0x20 movaps %xmm11,0x30(%rax) -.seh_savexmm128 %xmm11, 0x20+0x30 +.seh_savexmm %xmm11, 0x20+0x30 movaps %xmm12,0x40(%rax) -.seh_savexmm128 %xmm12, 0x20+0x40 +.seh_savexmm %xmm12, 0x20+0x40 movaps %xmm13,0x50(%rax) -.seh_savexmm128 %xmm13, 0x20+0x50 +.seh_savexmm %xmm13, 0x20+0x50 movaps %xmm14,0x60(%rax) -.seh_savexmm128 %xmm14, 0x20+0x60 +.seh_savexmm %xmm14, 0x20+0x60 movaps %xmm15,0x70(%rax) -.seh_savexmm128 %xmm15, 0x20+0x70 +.seh_savexmm %xmm15, 0x20+0x70 +.seh_endprologue ___ $code.=<<___; vzeroupper diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/self_check/fips.c b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/self_check/fips.c index c3515ea9e3..ca6fb3ac3e 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/self_check/fips.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/self_check/fips.c @@ -72,7 +72,8 @@ int FIPS_query_algorithm_status(const char *algorithm) { #if defined(BORINGSSL_FIPS_COUNTERS) size_t FIPS_read_counter(enum fips_counter_t counter) { - if (counter < 0 || counter > fips_counter_max) { + size_t index = (size_t)counter; + if (index > fips_counter_max) { abort(); } @@ -82,11 +83,12 @@ size_t FIPS_read_counter(enum fips_counter_t counter) { return 0; } - return array[counter]; + return array[index]; } void boringssl_fips_inc_counter(enum fips_counter_t counter) { - if (counter < 0 || counter > fips_counter_max) { + size_t index = (size_t)counter; + if (index > fips_counter_max) { abort(); } @@ -106,7 +108,7 @@ void boringssl_fips_inc_counter(enum fips_counter_t counter) { } } - array[counter]++; + array[index]++; } #else diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/asm/sha512-586.pl b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/asm/sha512-586.pl index b28877658b..7f12ec5ff4 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/asm/sha512-586.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/asm/sha512-586.pl @@ -66,8 +66,6 @@ open STDOUT,">$output"; $sse2=1; -&external_label("OPENSSL_ia32cap_P") if ($sse2); - $Tlo=&DWP(0,"esp"); $Thi=&DWP(4,"esp"); $Alo=&DWP(8,"esp"); $Ahi=&DWP(8+4,"esp"); $Blo=&DWP(16,"esp"); $Bhi=&DWP(16+4,"esp"); @@ -290,8 +288,9 @@ sub BODY_00_15_x86 { &lea ($K512,&DWP(8,$K512)); # K++ } +&static_label("K512"); -&function_begin("sha512_block_data_order"); +&function_begin("sha512_block_data_order_nohw"); &mov ("esi",wparam(0)); # ctx &mov ("edi",wparam(1)); # inp &mov ("eax",wparam(2)); # num @@ -313,30 +312,24 @@ sub BODY_00_15_x86 { &mov (&DWP(12,"esp"),"ebx"); # saved sp if ($sse2) { - &picmeup("edx","OPENSSL_ia32cap_P",$K512,&label("K512")); - &mov ("ecx",&DWP(0,"edx")); - &test ("ecx",1<<26); - &jz (&label("loop_x86")); - - &mov ("edx",&DWP(4,"edx")); - # load ctx->h[0-7] &movq ($A,&QWP(0,"esi")); - &and ("ecx",1<<24); # XMM registers availability &movq ("mm1",&QWP(8,"esi")); - &and ("edx",1<<9); # SSSE3 bit &movq ($BxC,&QWP(16,"esi")); - &or ("ecx","edx"); &movq ("mm3",&QWP(24,"esi")); &movq ($E,&QWP(32,"esi")); &movq ("mm5",&QWP(40,"esi")); &movq ("mm6",&QWP(48,"esi")); &movq ("mm7",&QWP(56,"esi")); - &cmp ("ecx",1<<24|1<<9); - &je (&label("SSSE3")); &sub ("esp",8*10); &jmp (&label("loop_sse2")); + # TODO(davidben): The preamble above this point comes from the original + # merged sha512_block_data_order function, which performed some common + # setup and then jumped to the particular SHA-512 implementation. The + # parts of the preamble that do not apply to this function can be + # removed. + &set_label("loop_sse2",16); #&movq ($Asse2,$A); &movq ($Bsse2,"mm1"); @@ -461,14 +454,50 @@ if ($sse2) { &mov ("esp",&DWP(8*10+12,"esp")); # restore sp &emms (); -&function_end_A(); +&function_end("sha512_block_data_order_nohw"); -&set_label("SSSE3",32); { my ($cnt,$frame)=("ecx","edx"); my @X=map("xmm$_",(0..7)); my $j; my $i=0; +&function_begin("sha512_block_data_order_ssse3"); + &mov ("esi",wparam(0)); # ctx + &mov ("edi",wparam(1)); # inp + &mov ("eax",wparam(2)); # num + &mov ("ebx","esp"); # saved sp + + &call (&label("pic_point")); # make it PIC! +&set_label("pic_point"); + &blindpop($K512); + &lea ($K512,&DWP(&label("K512")."-".&label("pic_point"),$K512)); + + &sub ("esp",16); + &and ("esp",-64); + + &shl ("eax",7); + &add ("eax","edi"); + &mov (&DWP(0,"esp"),"esi"); # ctx + &mov (&DWP(4,"esp"),"edi"); # inp + &mov (&DWP(8,"esp"),"eax"); # inp+num*128 + &mov (&DWP(12,"esp"),"ebx"); # saved sp + + # load ctx->h[0-7] + &movq ($A,&QWP(0,"esi")); + &movq ("mm1",&QWP(8,"esi")); + &movq ($BxC,&QWP(16,"esi")); + &movq ("mm3",&QWP(24,"esi")); + &movq ($E,&QWP(32,"esi")); + &movq ("mm5",&QWP(40,"esi")); + &movq ("mm6",&QWP(48,"esi")); + &movq ("mm7",&QWP(56,"esi")); + + # TODO(davidben): The preamble above this point comes from the original + # merged sha512_block_data_order function, which performed some common + # setup and then jumped to the particular SHA-512 implementation. The + # parts of the preamble that do not apply to this function can be + # removed. + &lea ($frame,&DWP(-64,"esp")); &sub ("esp",256); @@ -686,151 +715,8 @@ sub BODY_00_15_ssse3 { # "phase-less" copy of BODY_00_15_sse2 &mov ("esp",&DWP(64+12,$frame)); # restore sp &emms (); } -&function_end_A(); +&function_end("sha512_block_data_order_ssse3"); } -&set_label("loop_x86",16); - # copy input block to stack reversing byte and qword order - for ($i=0;$i<8;$i++) { - &mov ("eax",&DWP($i*16+0,"edi")); - &mov ("ebx",&DWP($i*16+4,"edi")); - &mov ("ecx",&DWP($i*16+8,"edi")); - &mov ("edx",&DWP($i*16+12,"edi")); - &bswap ("eax"); - &bswap ("ebx"); - &bswap ("ecx"); - &bswap ("edx"); - &push ("eax"); - &push ("ebx"); - &push ("ecx"); - &push ("edx"); - } - &add ("edi",128); - &sub ("esp",9*8); # place for T,A,B,C,D,E,F,G,H - &mov (&DWP(8*(9+16)+4,"esp"),"edi"); - - # copy ctx->h[0-7] to A,B,C,D,E,F,G,H on stack - &lea ("edi",&DWP(8,"esp")); - &mov ("ecx",16); - &data_word(0xA5F3F689); # rep movsd - -&set_label("00_15_x86",16); - &BODY_00_15_x86(); - - &cmp (&LB("edx"),0x94); - &jne (&label("00_15_x86")); - -&set_label("16_79_x86",16); - #define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) - # LO lo>>1^hi<<31 ^ lo>>8^hi<<24 ^ lo>>7^hi<<25 - # HI hi>>1^lo<<31 ^ hi>>8^lo<<24 ^ hi>>7 - &mov ("ecx",&DWP(8*(9+15+16-1)+0,"esp")); - &mov ("edx",&DWP(8*(9+15+16-1)+4,"esp")); - &mov ("esi","ecx"); - - &shr ("ecx",1); # lo>>1 - &mov ("edi","edx"); - &shr ("edx",1); # hi>>1 - &mov ("eax","ecx"); - &shl ("esi",24); # lo<<24 - &mov ("ebx","edx"); - &shl ("edi",24); # hi<<24 - &xor ("ebx","esi"); - - &shr ("ecx",7-1); # lo>>7 - &xor ("eax","edi"); - &shr ("edx",7-1); # hi>>7 - &xor ("eax","ecx"); - &shl ("esi",31-24); # lo<<31 - &xor ("ebx","edx"); - &shl ("edi",25-24); # hi<<25 - &xor ("ebx","esi"); - - &shr ("ecx",8-7); # lo>>8 - &xor ("eax","edi"); - &shr ("edx",8-7); # hi>>8 - &xor ("eax","ecx"); - &shl ("edi",31-25); # hi<<31 - &xor ("ebx","edx"); - &xor ("eax","edi"); # T1 = sigma0(X[-15]) - - &mov (&DWP(0,"esp"),"eax"); - &mov (&DWP(4,"esp"),"ebx"); # put T1 away - - #define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) - # LO lo>>19^hi<<13 ^ hi>>29^lo<<3 ^ lo>>6^hi<<26 - # HI hi>>19^lo<<13 ^ lo>>29^hi<<3 ^ hi>>6 - &mov ("ecx",&DWP(8*(9+15+16-14)+0,"esp")); - &mov ("edx",&DWP(8*(9+15+16-14)+4,"esp")); - &mov ("esi","ecx"); - - &shr ("ecx",6); # lo>>6 - &mov ("edi","edx"); - &shr ("edx",6); # hi>>6 - &mov ("eax","ecx"); - &shl ("esi",3); # lo<<3 - &mov ("ebx","edx"); - &shl ("edi",3); # hi<<3 - &xor ("eax","esi"); - - &shr ("ecx",19-6); # lo>>19 - &xor ("ebx","edi"); - &shr ("edx",19-6); # hi>>19 - &xor ("eax","ecx"); - &shl ("esi",13-3); # lo<<13 - &xor ("ebx","edx"); - &shl ("edi",13-3); # hi<<13 - &xor ("ebx","esi"); - - &shr ("ecx",29-19); # lo>>29 - &xor ("eax","edi"); - &shr ("edx",29-19); # hi>>29 - &xor ("ebx","ecx"); - &shl ("edi",26-13); # hi<<26 - &xor ("eax","edx"); - &xor ("eax","edi"); # sigma1(X[-2]) - - &mov ("ecx",&DWP(8*(9+15+16)+0,"esp")); - &mov ("edx",&DWP(8*(9+15+16)+4,"esp")); - &add ("eax",&DWP(0,"esp")); - &adc ("ebx",&DWP(4,"esp")); # T1 = sigma1(X[-2])+T1 - &mov ("esi",&DWP(8*(9+15+16-9)+0,"esp")); - &mov ("edi",&DWP(8*(9+15+16-9)+4,"esp")); - &add ("eax","ecx"); - &adc ("ebx","edx"); # T1 += X[-16] - &add ("eax","esi"); - &adc ("ebx","edi"); # T1 += X[-7] - &mov (&DWP(8*(9+15)+0,"esp"),"eax"); - &mov (&DWP(8*(9+15)+4,"esp"),"ebx"); # save X[0] - - &BODY_00_15_x86(); - - &cmp (&LB("edx"),0x17); - &jne (&label("16_79_x86")); - - &mov ("esi",&DWP(8*(9+16+80)+0,"esp"));# ctx - &mov ("edi",&DWP(8*(9+16+80)+4,"esp"));# inp - for($i=0;$i<4;$i++) { - &mov ("eax",&DWP($i*16+0,"esi")); - &mov ("ebx",&DWP($i*16+4,"esi")); - &mov ("ecx",&DWP($i*16+8,"esi")); - &mov ("edx",&DWP($i*16+12,"esi")); - &add ("eax",&DWP(8+($i*16)+0,"esp")); - &adc ("ebx",&DWP(8+($i*16)+4,"esp")); - &mov (&DWP($i*16+0,"esi"),"eax"); - &mov (&DWP($i*16+4,"esi"),"ebx"); - &add ("ecx",&DWP(8+($i*16)+8,"esp")); - &adc ("edx",&DWP(8+($i*16)+12,"esp")); - &mov (&DWP($i*16+8,"esi"),"ecx"); - &mov (&DWP($i*16+12,"esi"),"edx"); - } - &add ("esp",8*(9+16+80)); # destroy frame - &sub ($K512,8*80); # rewind K - - &cmp ("edi",&DWP(8,"esp")); # are we done yet? - &jb (&label("loop_x86")); - - &mov ("esp",&DWP(12,"esp")); # restore sp -&function_end_A(); &set_label("K512",64); # Yes! I keep it in the code segment! &data_word(0xd728ae22,0x428a2f98); # u64 @@ -916,7 +802,6 @@ sub BODY_00_15_ssse3 { # "phase-less" copy of BODY_00_15_sse2 &data_word(0x04050607,0x00010203); # byte swap &data_word(0x0c0d0e0f,0x08090a0b); # mask -&function_end_B("sha512_block_data_order"); &asciz("SHA512 block transform for x86, CRYPTOGAMS by "); &asm_finish(); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/internal.h index d1ebbb88e7..d2a42694da 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/internal.h @@ -80,6 +80,7 @@ OPENSSL_INLINE int sha512_hw_capable(void) { #define SHA1_ASM_NOHW #define SHA256_ASM_NOHW +#define SHA512_ASM_NOHW #define SHA1_ASM_SSSE3 OPENSSL_INLINE int sha1_ssse3_capable(void) { @@ -127,10 +128,14 @@ OPENSSL_INLINE int sha256_avx_capable(void) { void sha256_block_data_order_avx(uint32_t state[8], const uint8_t *data, size_t num); -// TODO(crbug.com/boringssl/673): Move the remaining CPU dispatch to C. -#define SHA512_ASM -void sha512_block_data_order(uint64_t state[8], const uint8_t *data, - size_t num_blocks); +#define SHA512_ASM_SSSE3 +OPENSSL_INLINE int sha512_ssse3_capable(void) { + // TODO(davidben): Do we need to check the FXSR bit? The Intel manual does not + // say to. + return CRYPTO_is_SSSE3_capable() && CRYPTO_is_FXSR_capable(); +} +void sha512_block_data_order_ssse3(uint64_t state[8], const uint8_t *data, + size_t num); #elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/sha512.c b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/sha512.c index ba9d42dd12..f9f7be8f63 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/sha512.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/fipsmodule/sha/sha512.c @@ -516,6 +516,12 @@ static void sha512_block_data_order(uint64_t state[8], const uint8_t *data, return; } #endif +#if defined(SHA512_ASM_SSSE3) + if (sha512_ssse3_capable()) { + sha512_block_data_order_ssse3(state, data, num); + return; + } +#endif #if defined(SHA512_ASM_NEON) if (CRYPTO_is_NEON_capable()) { sha512_block_data_order_neon(state, data, num); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/internal.h index a77102d766..f93c2e5ecb 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/internal.h @@ -180,17 +180,29 @@ extern "C" { #endif -#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) || \ - defined(OPENSSL_AARCH64) -// OPENSSL_cpuid_setup initializes the platform-specific feature cache. +#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_STATIC_ARMCAP) && \ + (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ + defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) +// x86, x86_64, and the ARMs need to record the result of a cpuid/getauxval call +// for the asm to work correctly, unless compiled without asm code. +#define NEED_CPUID + +// OPENSSL_cpuid_setup initializes the platform-specific feature cache. This +// function should not be called directly. Call |OPENSSL_init_cpuid| instead. void OPENSSL_cpuid_setup(void); + +// OPENSSL_init_cpuid initializes the platform-specific feature cache, if +// needed. This function is idempotent and may be called concurrently. +void OPENSSL_init_cpuid(void); +#else +OPENSSL_INLINE void OPENSSL_init_cpuid(void) {} #endif #if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \ !defined(OPENSSL_STATIC_ARMCAP) // OPENSSL_get_armcap_pointer_for_test returns a pointer to |OPENSSL_armcap_P| -// for unit tests. Any modifications to the value must be made after -// |CRYPTO_library_init| but before any other function call in BoringSSL. +// for unit tests. Any modifications to the value must be made before any other +// function call in BoringSSL. OPENSSL_EXPORT uint32_t *OPENSSL_get_armcap_pointer_for_test(void); #endif @@ -1174,6 +1186,11 @@ static inline uint64_t CRYPTO_rotr_u64(uint64_t value, int shift) { // Arithmetic functions. +// The most efficient versions of these functions on GCC and Clang depend on C11 +// |_Generic|. If we ever need to call these from C++, we'll need to add a +// variant that uses C++ overloads instead. +#if !defined(__cplusplus) + // CRYPTO_addc_* returns |x + y + carry|, and sets |*out_carry| to the carry // bit. |carry| must be zero or one. #if OPENSSL_HAS_BUILTIN(__builtin_addc) @@ -1275,6 +1292,8 @@ static inline uint64_t CRYPTO_subc_u64(uint64_t x, uint64_t y, uint64_t borrow, #define CRYPTO_subc_w CRYPTO_subc_u32 #endif +#endif // !__cplusplus + // FIPS functions. @@ -1514,7 +1533,6 @@ OPENSSL_INLINE int CRYPTO_is_x86_SHA_capable(void) { // otherwise select. See chacha-x86_64.pl. // // Bonnell, Silvermont's predecessor in the Atom lineup, will also be matched by -// this. |OPENSSL_cpuid_setup| forces Knights Landing to also be matched by // this. Goldmont (Silvermont's successor in the Atom lineup) added XSAVE so it // isn't matched by this. Various sources indicate AMD first implemented MOVBE // and XSAVE at the same time in Jaguar, so it seems like AMD chips will not be @@ -1523,11 +1541,12 @@ OPENSSL_INLINE int CRYPTO_cpu_perf_is_like_silvermont(void) { // WARNING: This MUST NOT be used to guard the execution of the XSAVE // instruction. This is the "hardware supports XSAVE" bit, not the OSXSAVE bit // that indicates whether we can safely execute XSAVE. This bit may be set - // even when XSAVE is disabled (by the operating system). See the comment in - // cpu_intel.c and check how the users of this bit use it. + // even when XSAVE is disabled (by the operating system). See how the users of + // this bit use it. // - // We do not use |__XSAVE__| for static detection because the hack in - // |OPENSSL_cpuid_setup| for Knights Landing CPUs needs to override it. + // Historically, the XSAVE bit was artificially cleared on Knights Landing + // and Knights Mill chips, but as Intel has removed all support from GCC, + // LLVM, and SDE, we assume they are no longer worth special-casing. int hardware_supports_xsave = (OPENSSL_get_ia32cap(1) & (1u << 26)) != 0; return !hardware_supports_xsave && CRYPTO_is_MOVBE_capable(); } diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/kyber/kyber.c b/naiveproxy/src/third_party/boringssl/src/crypto/kyber/kyber.c index 0e973590e4..411ec4830a 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/kyber/kyber.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/kyber/kyber.c @@ -12,6 +12,7 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER #include #include diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/perlasm/x86_64-xlate.pl b/naiveproxy/src/third_party/boringssl/src/crypto/perlasm/x86_64-xlate.pl index 9fb1de19c6..3011c91530 100755 --- a/naiveproxy/src/third_party/boringssl/src/crypto/perlasm/x86_64-xlate.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/perlasm/x86_64-xlate.pl @@ -714,16 +714,21 @@ my %globals; } } { package seh_directive; - # This implements directives, like MASM's, for specifying Windows unwind - # codes. See https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170 - # for details on the Windows unwind mechanism. Unlike MASM's directives, we - # have no .seh_endprolog directive. Instead, the last prolog directive is - # implicitly the end of the prolog. + # This implements directives, like MASM, gas, and clang-assembler for + # specifying Windows unwind codes. See + # https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170 + # for details on the Windows unwind mechanism. As perlasm generally uses gas + # syntax, the syntax is patterned after the gas spelling, described in + # https://sourceware.org/legacy-ml/binutils/2009-08/msg00193.html + # + # TODO(https://crbug.com/boringssl/571): Translate to the MASM directives + # when using the MASM output. Emit as-is when using "mingw64" output, which + # is Windows with gas syntax. # # TODO(https://crbug.com/boringssl/259): For now, SEH directives are ignored # on non-Windows platforms. This means functions need to specify both CFI # and SEH directives, often redundantly. Ideally we'd abstract between the - # two. E.g., we can synthesize CFI from SEH prologs, but SEH does not + # two. E.g., we can synthesize CFI from SEH prologues, but SEH does not # annotate epilogs, so we'd need to combine parts from both. Or we can # restrict ourselves to a subset of CFI and synthesize SEH from CFI. # @@ -732,7 +737,7 @@ my %globals; # complication is the current scheme modifies RDI and RSI (non-volatile on # Windows) at the start of the function, and saves them in the parameter # stack area. This can be expressed with .seh_savereg, but .seh_savereg is - # only usable late in the prolog. However, unwind information gives enough + # only usable late in the prologue. However, unwind information gives enough # information to locate the parameter stack area at any point in the # function, so we can defer conversion or implement other schemes. @@ -777,6 +782,11 @@ my %globals; die "Missing .seh_startproc directive" unless %info; } + sub _check_in_prologue { + _check_in_proc(); + die "Invalid SEH directive after .seh_endprologue" if defined($info{endprologue}); + } + sub _check_not_in_proc { die "Missing .seh_endproc directive" if %info; } @@ -794,8 +804,8 @@ my %globals; info_label => $info_label, # start_label is the start of the function. start_label => $start_label, - # endprolog is the label of the last unwind code in the function. - endprolog => $start_label, + # endprologue is the label of the end of the prologue. + endprologue => undef, # unwind_codes contains the textual representation of the # unwind codes in the function so far. unwind_codes => "", @@ -821,14 +831,14 @@ my %globals; sub _add_unwind_code { my ($op, $value, @extra) = @_; - _check_in_proc(); + _check_in_prologue(); if ($op != $UWOP_PUSH_NONVOL) { $info{has_nonpushreg} = 1; } elsif ($info{has_nonpushreg}) { - die ".seh_pushreg directives must appear first in the prolog"; + die ".seh_pushreg directives must appear first in the prologue"; } - my $label = _new_unwind_label("prolog"); + my $label = _new_unwind_label("prologue"); # Encode an UNWIND_CODE structure. See # https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170#struct-unwind_code my $encoded = $op | ($value << 4); @@ -844,17 +854,13 @@ ____ $info{num_codes} += 1 + scalar(@extra); # Unwind codes are listed in reverse order. $info{unwind_codes} = $codes . $info{unwind_codes}; - # Track the label of the last unwind code. It implicitly is the end of - # the prolog. MASM has an endprolog directive, but it seems to be - # unnecessary. - $info{endprolog} = $label; return $label; } sub _updating_fixed_allocation { - _check_in_proc(); + _check_in_prologue(); if ($info{frame_reg} != 0) { - # Windows documentation does not explicitly forbid .seh_allocstack + # Windows documentation does not explicitly forbid .seh_stackalloc # after .seh_setframe, but it appears to have no effect. Offsets are # still relative to the fixed allocation when the frame register was # established. @@ -862,7 +868,7 @@ ____ } if ($info{has_offset}) { # Windows documentation does not explicitly forbid .seh_savereg - # before .seh_allocstack, but it does not work very well. Offsets + # before .seh_stackalloc, but it does not work very well. Offsets # are relative to the top of the final fixed allocation, not where # RSP currently is. die "directives with an offset must come after the fixed allocation is established."; @@ -871,11 +877,8 @@ ____ sub _endproc { _check_in_proc(); - if ($info{num_codes} == 0) { - # If a Windows function has no directives (i.e. it doesn't touch the - # stack), it is a leaf function and is not expected to appear in - # .pdata or .xdata. - die ".seh_endproc found with no unwind codes"; + if (!defined($info{endprologue})) { + die "Missing .seh_endprologue"; } my $end_label = _new_unwind_label("end"); @@ -894,12 +897,22 @@ ____ $xdata .= <<____; $info{info_label}: .byte 1 # version 1, no flags - .byte $info{endprolog}-$info{start_label} + .byte $info{endprologue}-$info{start_label} .byte $info{num_codes} .byte $frame_encoded $info{unwind_codes} ____ + # UNWIND_INFOs must be 4-byte aligned. If needed, we must add an extra + # unwind code. This does not change the unwind code count. Windows + # documentation says "For alignment purposes, this array always has an + # even number of entries, and the final entry is potentially unused. In + # that case, the array is one longer than indicated by the count of + # unwind codes field." + if ($info{num_codes} & 1) { + $xdata .= "\t.value\t0\n"; + } + %info = (); return $end_label; } @@ -916,7 +929,7 @@ ____ my $label; SWITCH: for ($dir) { /^startproc$/ && do { - $label = _startproc(); + $label = _startproc($1); last; }; /^pushreg$/ && do { @@ -926,7 +939,7 @@ ____ $label = _add_unwind_code($UWOP_PUSH_NONVOL, $reg_num); last; }; - /^allocstack$/ && do { + /^stackalloc$/ && do { my $num = eval($$line); if ($num <= 0 || $num % 8 != 0) { die "invalid stack allocation: $num"; @@ -976,7 +989,7 @@ ____ $info{has_offset} = 1; last; }; - /^savexmm128$/ && do { + /^savexmm$/ && do { $$line =~ /%xmm(\d+)\s*,\s*(.+)/ or die "could not parse .seh_$dir"; my $reg_num = $1; my $offset = eval($2); @@ -991,6 +1004,19 @@ ____ $info{has_offset} = 1; last; }; + /^endprologue$/ && do { + _check_in_prologue(); + if ($info{num_codes} == 0) { + # If a Windows function has no directives (i.e. it + # doesn't touch the stack), it is a leaf function and is + # not expected to appear in .pdata or .xdata. + die ".seh_endprologue found with no unwind codes"; + } + + $label = _new_unwind_label("endprologue"); + $info{endprologue} = $label; + last; + }; /^endproc$/ && do { $label = _endproc(); last; diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/perlasm/x86asm.pl b/naiveproxy/src/third_party/boringssl/src/crypto/perlasm/x86asm.pl index f0d631067f..b10eaf6be6 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/perlasm/x86asm.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/perlasm/x86asm.pl @@ -42,10 +42,10 @@ sub ::record_function_hit &preprocessor_ifdef("BORINGSSL_DISPATCH_TEST"); &push("ebx"); &push("edx"); - &call(&label("pic")); - &set_label("pic"); + &call(&label("pic_for_function_hit")); + &set_label("pic_for_function_hit"); &blindpop("ebx"); - &lea("ebx",&DWP("BORINGSSL_function_hit+$index"."-".&label("pic"),"ebx")); + &lea("ebx",&DWP("BORINGSSL_function_hit+$index"."-".&label("pic_for_function_hit"),"ebx")); &mov("edx", 1); &movb(&BP(0, "ebx"), "dl"); &pop("edx"); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/test/asm/trampoline-x86_64.pl b/naiveproxy/src/third_party/boringssl/src/crypto/test/asm/trampoline-x86_64.pl index 53b4bcd67b..d8d2be2821 100755 --- a/naiveproxy/src/third_party/boringssl/src/crypto/test/asm/trampoline-x86_64.pl +++ b/naiveproxy/src/third_party/boringssl/src/crypto/test/asm/trampoline-x86_64.pl @@ -179,7 +179,7 @@ my $caller_state_offset = $scratch_offset + 8; $code .= <<____; subq \$$stack_alloc_size, %rsp .cfi_adjust_cfa_offset $stack_alloc_size -.seh_allocstack $stack_alloc_size +.seh_stackalloc $stack_alloc_size ____ $code .= <<____ if (!$win64); movq $unwind, $unwind_offset(%rsp) @@ -195,12 +195,13 @@ $code .= store_caller_state($caller_state_offset, "%rsp", sub { # pointer just before the call. my $cfi_off = $off - $stack_alloc_size - 8; my $seh_dir = ".seh_savereg"; - $seh_dir = ".seh_savexmm128" if ($reg =~ /^xmm/); + $seh_dir = ".seh_savexmm" if ($reg =~ /^xmm/); return <<____; .cfi_offset $reg, $cfi_off $seh_dir \%$reg, $off ____ }); +$code .= ".seh_endprologue\n"; $code .= load_caller_state(0, $state); $code .= <<____; @@ -342,6 +343,7 @@ abi_test_bad_unwind_wrong_register: pushq %r12 .cfi_push %r13 # This should be %r13 .seh_pushreg %r13 # This should be %r13 +.seh_endprologue # Windows evaluates epilogs directly in the unwinder, rather than using # unwind codes. Add a nop so there is one non-epilog point (immediately # before the nop) where the unwinder can observe the mistake. @@ -366,6 +368,7 @@ abi_test_bad_unwind_temporary: pushq %r12 .cfi_push %r12 .seh_pushreg %r12 +.seh_endprologue movq %r12, %rax inc %rax @@ -422,6 +425,7 @@ abi_test_bad_unwind_epilog: .seh_startproc pushq %r12 .seh_pushreg %r12 +.seh_endprologue nop diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/test/file_util.cc b/naiveproxy/src/third_party/boringssl/src/crypto/test/file_util.cc index f593e1d3f4..71c58b7fc9 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/test/file_util.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/test/file_util.cc @@ -31,6 +31,8 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) #include "test_util.h" +BSSL_NAMESPACE_BEGIN + #if defined(OPENSSL_WINDOWS) static void PrintLastError(const char *s) { DWORD error = GetLastError(); @@ -237,3 +239,5 @@ bool TemporaryDirectory::AddFile(const std::string &filename, files_.insert(filename); return true; } + +BSSL_NAMESPACE_END diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/test/file_util.h b/naiveproxy/src/third_party/boringssl/src/crypto/test/file_util.h index 0fd8d85e24..ee994b126e 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/test/file_util.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/test/file_util.h @@ -31,6 +31,8 @@ #endif +BSSL_NAMESPACE_BEGIN + struct FileDeleter { void operator()(FILE *f) const { if (f != nullptr) { @@ -159,4 +161,6 @@ class TemporaryDirectory { std::set files_; }; +BSSL_NAMESPACE_END + #endif // OPENSSL_HEADER_CRYPTO_TEST_FILE_UTIL_H diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/test/gtest_main.h b/naiveproxy/src/third_party/boringssl/src/crypto/test/gtest_main.h index 05d468ecfc..495b84711f 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/test/gtest_main.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/test/gtest_main.h @@ -63,8 +63,6 @@ class TestEventListener : public testing::EmptyTestEventListener { // SetupGoogleTest should be called by the test runner after // testing::InitGoogleTest has been called and before RUN_ALL_TESTS. inline void SetupGoogleTest() { - CRYPTO_library_init(); - #if defined(OPENSSL_WINDOWS) // Initialize Winsock. WORD wsa_version = MAKEWORD(2, 2); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/test/test_data.cc b/naiveproxy/src/third_party/boringssl/src/crypto/test/test_data.cc index 9db2019acb..f0e69227b4 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/test/test_data.cc +++ b/naiveproxy/src/third_party/boringssl/src/crypto/test/test_data.cc @@ -49,7 +49,7 @@ std::string GetTestData(const char *path) { full_path.append(path); #endif - ScopedFILE file(fopen(full_path.c_str(), "rb")); + bssl::ScopedFILE file(fopen(full_path.c_str(), "rb")); if (file == nullptr) { fprintf(stderr, "Could not open '%s'.\n", full_path.c_str()); abort(); diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/x509/internal.h b/naiveproxy/src/third_party/boringssl/src/crypto/x509/internal.h index 50180636c1..8d066dd3c1 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/x509/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/crypto/x509/internal.h @@ -341,8 +341,6 @@ struct x509_store_st { // Callbacks for various operations X509_STORE_CTX_verify_cb verify_cb; // error callback - X509_STORE_CTX_get_crl_fn get_crl; // retrieve CRL - X509_STORE_CTX_check_crl_fn check_crl; // Check CRL validity CRYPTO_refcount_t references; } /* X509_STORE */; @@ -374,8 +372,6 @@ struct x509_store_ctx_st { // Callbacks for various operations X509_STORE_CTX_verify_cb verify_cb; // error callback - X509_STORE_CTX_get_crl_fn get_crl; // retrieve CRL - X509_STORE_CTX_check_crl_fn check_crl; // Check CRL validity // The following is built up int last_untrusted; // index of last untrusted cert diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/x509/v3_utl.c b/naiveproxy/src/third_party/boringssl/src/crypto/x509/v3_utl.c index c6144d1574..4426be5e36 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/x509/v3_utl.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/x509/v3_utl.c @@ -82,10 +82,10 @@ static void str_free(OPENSSL_STRING str); static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email); -static int ipv4_from_asc(unsigned char v4[4], const char *in); -static int ipv6_from_asc(unsigned char v6[16], const char *in); +static int ipv4_from_asc(uint8_t v4[4], const char *in); +static int ipv6_from_asc(uint8_t v6[16], const char *in); static int ipv6_cb(const char *elem, size_t len, void *usr); -static int ipv6_hex(unsigned char *out, const char *in, size_t inlen); +static int ipv6_hex(uint8_t *out, const char *in, size_t inlen); // Add a CONF_VALUE name value pair to stack @@ -1154,7 +1154,7 @@ err: return NULL; } -int x509v3_a2i_ipadd(unsigned char ipout[16], const char *ipasc) { +int x509v3_a2i_ipadd(uint8_t ipout[16], const char *ipasc) { // If string contains a ':' assume IPv6 if (strchr(ipasc, ':')) { @@ -1170,25 +1170,58 @@ int x509v3_a2i_ipadd(unsigned char ipout[16], const char *ipasc) { } } -static int ipv4_from_asc(unsigned char v4[4], const char *in) { - int a0, a1, a2, a3; - if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) { +// get_ipv4_component consumes one IPv4 component, terminated by either '.' or +// the end of the string, from |*str|. On success, it returns one, sets |*out| +// to the component, and advances |*str| to the first unconsumed character. On +// invalid input, it returns zero. +static int get_ipv4_component(uint8_t *out_byte, const char **str) { + // Store a slightly larger intermediary so the overflow check is easier. + uint32_t out = 0; + for (;;) { + if (!OPENSSL_isdigit(**str)) { + return 0; + } + out = (out * 10) + (**str - '0'); + if (out > 255) { + // Components must be 8-bit. + return 0; + } + (*str)++; + if ((**str) == '.' || (**str) == '\0') { + *out_byte = (uint8_t)out; + return 1; + } + if (out == 0) { + // Reject extra leading zeros. Parsers sometimes treat them as octal, so + // accepting them would misinterpret input. + return 0; + } + } +} + +// get_ipv4_dot consumes a '.' from |*str| and advances it. It returns one on +// success and zero if |*str| does not point to a '.'. +static int get_ipv4_dot(const char **str) { + if (**str != '.') { return 0; } - if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || (a2 < 0) || - (a2 > 255) || (a3 < 0) || (a3 > 255)) { + (*str)++; + return 1; +} + +static int ipv4_from_asc(uint8_t v4[4], const char *in) { + if (!get_ipv4_component(&v4[0], &in) || !get_ipv4_dot(&in) || + !get_ipv4_component(&v4[1], &in) || !get_ipv4_dot(&in) || + !get_ipv4_component(&v4[2], &in) || !get_ipv4_dot(&in) || + !get_ipv4_component(&v4[3], &in) || *in != '\0') { return 0; } - v4[0] = a0; - v4[1] = a1; - v4[2] = a2; - v4[3] = a3; return 1; } typedef struct { // Temporary store for IPV6 output - unsigned char tmp[16]; + uint8_t tmp[16]; // Total number of bytes in tmp int total; // The position of a zero (corresponding to '::') @@ -1197,7 +1230,7 @@ typedef struct { int zero_cnt; } IPV6_STAT; -static int ipv6_from_asc(unsigned char v6[16], const char *in) { +static int ipv6_from_asc(uint8_t v6[16], const char *in) { IPV6_STAT v6stat; v6stat.total = 0; v6stat.zero_pos = -1; @@ -1305,7 +1338,7 @@ static int ipv6_cb(const char *elem, size_t len, void *usr) { // Convert a string of up to 4 hex digits into the corresponding IPv6 form. -static int ipv6_hex(unsigned char *out, const char *in, size_t inlen) { +static int ipv6_hex(uint8_t *out, const char *in, size_t inlen) { if (inlen > 4) { return 0; } diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/x509/x509_lu.c b/naiveproxy/src/third_party/boringssl/src/crypto/x509/x509_lu.c index c79c558234..7867a80721 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/x509/x509_lu.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/x509/x509_lu.c @@ -594,16 +594,6 @@ void X509_STORE_set_verify_cb(X509_STORE *ctx, ctx->verify_cb = verify_cb; } -void X509_STORE_set_get_crl(X509_STORE *ctx, - X509_STORE_CTX_get_crl_fn get_crl) { - ctx->get_crl = get_crl; -} - -void X509_STORE_set_check_crl(X509_STORE *ctx, - X509_STORE_CTX_check_crl_fn check_crl) { - ctx->check_crl = check_crl; -} - X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx) { return ctx->ctx; } diff --git a/naiveproxy/src/third_party/boringssl/src/crypto/x509/x509_vfy.c b/naiveproxy/src/third_party/boringssl/src/crypto/x509/x509_vfy.c index 0ca8c82dc7..9d1406f9fc 100644 --- a/naiveproxy/src/third_party/boringssl/src/crypto/x509/x509_vfy.c +++ b/naiveproxy/src/third_party/boringssl/src/crypto/x509/x509_vfy.c @@ -117,6 +117,7 @@ static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x); static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, int *pcrl_score); static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score); +static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl); static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); static int internal_verify(X509_STORE_CTX *ctx); @@ -769,17 +770,18 @@ static int check_cert(X509_STORE_CTX *ctx) { // Try to retrieve the relevant CRL. Note that |get_crl| sets // |current_crl_issuer| and |current_crl_score|, which |check_crl| then reads. // - // TODO(davidben): Remove these callbacks. gRPC currently sets them, but - // implements them incorrectly. It is not actually possible to implement - // |get_crl| from outside the library. - if (!ctx->get_crl(ctx, &crl, x)) { + // TODO(davidben): The awkward internal calling convention is a historical + // artifact of when these functions were user-overridable callbacks, even + // though there was no way to set them correctly. These callbacks have since + // been removed, so we can pass input and output parameters more directly. + if (!get_crl(ctx, &crl, x)) { ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; ok = call_verify_cb(0, ctx); goto err; } ctx->current_crl = crl; - if (!ctx->check_crl(ctx, crl) || // + if (!check_crl(ctx, crl) || // !cert_crl(ctx, crl, x)) { goto err; } @@ -1560,18 +1562,6 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->verify_cb = null_callback; } - if (store->get_crl) { - ctx->get_crl = store->get_crl; - } else { - ctx->get_crl = get_crl; - } - - if (store->check_crl) { - ctx->check_crl = store->check_crl; - } else { - ctx->check_crl = check_crl; - } - return 1; err: diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-gcm-x86_64-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-gcm-x86_64-win.asm index d7a2665e4a..e8324d283a 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-gcm-x86_64-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-gcm-x86_64-win.asm @@ -363,57 +363,58 @@ _CET_ENDBR push rbp -$L$SEH_prolog_aesni_gcm_decrypt_2: +$L$SEH_prologue_aesni_gcm_decrypt_2: mov rbp,rsp push rbx -$L$SEH_prolog_aesni_gcm_decrypt_3: +$L$SEH_prologue_aesni_gcm_decrypt_3: push r12 -$L$SEH_prolog_aesni_gcm_decrypt_4: +$L$SEH_prologue_aesni_gcm_decrypt_4: push r13 -$L$SEH_prolog_aesni_gcm_decrypt_5: +$L$SEH_prologue_aesni_gcm_decrypt_5: push r14 -$L$SEH_prolog_aesni_gcm_decrypt_6: +$L$SEH_prologue_aesni_gcm_decrypt_6: push r15 -$L$SEH_prolog_aesni_gcm_decrypt_7: +$L$SEH_prologue_aesni_gcm_decrypt_7: lea rsp,[((-168))+rsp] -$L$SEH_prolog_aesni_gcm_decrypt_8: -$L$SEH_prolog_aesni_gcm_decrypt_9: +$L$SEH_prologue_aesni_gcm_decrypt_8: +$L$SEH_prologue_aesni_gcm_decrypt_9: mov QWORD[16+rbp],rdi -$L$SEH_prolog_aesni_gcm_decrypt_10: +$L$SEH_prologue_aesni_gcm_decrypt_10: mov QWORD[24+rbp],rsi -$L$SEH_prolog_aesni_gcm_decrypt_11: +$L$SEH_prologue_aesni_gcm_decrypt_11: mov rdi,QWORD[48+rbp] mov rsi,QWORD[56+rbp] movaps XMMWORD[(-208)+rbp],xmm6 -$L$SEH_prolog_aesni_gcm_decrypt_12: +$L$SEH_prologue_aesni_gcm_decrypt_12: movaps XMMWORD[(-192)+rbp],xmm7 -$L$SEH_prolog_aesni_gcm_decrypt_13: +$L$SEH_prologue_aesni_gcm_decrypt_13: movaps XMMWORD[(-176)+rbp],xmm8 -$L$SEH_prolog_aesni_gcm_decrypt_14: +$L$SEH_prologue_aesni_gcm_decrypt_14: movaps XMMWORD[(-160)+rbp],xmm9 -$L$SEH_prolog_aesni_gcm_decrypt_15: +$L$SEH_prologue_aesni_gcm_decrypt_15: movaps XMMWORD[(-144)+rbp],xmm10 -$L$SEH_prolog_aesni_gcm_decrypt_16: +$L$SEH_prologue_aesni_gcm_decrypt_16: movaps XMMWORD[(-128)+rbp],xmm11 -$L$SEH_prolog_aesni_gcm_decrypt_17: +$L$SEH_prologue_aesni_gcm_decrypt_17: movaps XMMWORD[(-112)+rbp],xmm12 -$L$SEH_prolog_aesni_gcm_decrypt_18: +$L$SEH_prologue_aesni_gcm_decrypt_18: movaps XMMWORD[(-96)+rbp],xmm13 -$L$SEH_prolog_aesni_gcm_decrypt_19: +$L$SEH_prologue_aesni_gcm_decrypt_19: movaps XMMWORD[(-80)+rbp],xmm14 -$L$SEH_prolog_aesni_gcm_decrypt_20: +$L$SEH_prologue_aesni_gcm_decrypt_20: movaps XMMWORD[(-64)+rbp],xmm15 -$L$SEH_prolog_aesni_gcm_decrypt_21: +$L$SEH_prologue_aesni_gcm_decrypt_21: +$L$SEH_endprologue_aesni_gcm_decrypt_22: vzeroupper mov r12,QWORD[64+rbp] @@ -512,7 +513,7 @@ $L$dec_no_key_aliasing: $L$gcm_dec_abort: ret -$L$SEH_end_aesni_gcm_decrypt_22: +$L$SEH_end_aesni_gcm_decrypt_23: @@ -629,57 +630,58 @@ EXTERN BORINGSSL_function_hit push rbp -$L$SEH_prolog_aesni_gcm_encrypt_2: +$L$SEH_prologue_aesni_gcm_encrypt_2: mov rbp,rsp push rbx -$L$SEH_prolog_aesni_gcm_encrypt_3: +$L$SEH_prologue_aesni_gcm_encrypt_3: push r12 -$L$SEH_prolog_aesni_gcm_encrypt_4: +$L$SEH_prologue_aesni_gcm_encrypt_4: push r13 -$L$SEH_prolog_aesni_gcm_encrypt_5: +$L$SEH_prologue_aesni_gcm_encrypt_5: push r14 -$L$SEH_prolog_aesni_gcm_encrypt_6: +$L$SEH_prologue_aesni_gcm_encrypt_6: push r15 -$L$SEH_prolog_aesni_gcm_encrypt_7: +$L$SEH_prologue_aesni_gcm_encrypt_7: lea rsp,[((-168))+rsp] -$L$SEH_prolog_aesni_gcm_encrypt_8: -$L$SEH_prolog_aesni_gcm_encrypt_9: +$L$SEH_prologue_aesni_gcm_encrypt_8: +$L$SEH_prologue_aesni_gcm_encrypt_9: mov QWORD[16+rbp],rdi -$L$SEH_prolog_aesni_gcm_encrypt_10: +$L$SEH_prologue_aesni_gcm_encrypt_10: mov QWORD[24+rbp],rsi -$L$SEH_prolog_aesni_gcm_encrypt_11: +$L$SEH_prologue_aesni_gcm_encrypt_11: mov rdi,QWORD[48+rbp] mov rsi,QWORD[56+rbp] movaps XMMWORD[(-208)+rbp],xmm6 -$L$SEH_prolog_aesni_gcm_encrypt_12: +$L$SEH_prologue_aesni_gcm_encrypt_12: movaps XMMWORD[(-192)+rbp],xmm7 -$L$SEH_prolog_aesni_gcm_encrypt_13: +$L$SEH_prologue_aesni_gcm_encrypt_13: movaps XMMWORD[(-176)+rbp],xmm8 -$L$SEH_prolog_aesni_gcm_encrypt_14: +$L$SEH_prologue_aesni_gcm_encrypt_14: movaps XMMWORD[(-160)+rbp],xmm9 -$L$SEH_prolog_aesni_gcm_encrypt_15: +$L$SEH_prologue_aesni_gcm_encrypt_15: movaps XMMWORD[(-144)+rbp],xmm10 -$L$SEH_prolog_aesni_gcm_encrypt_16: +$L$SEH_prologue_aesni_gcm_encrypt_16: movaps XMMWORD[(-128)+rbp],xmm11 -$L$SEH_prolog_aesni_gcm_encrypt_17: +$L$SEH_prologue_aesni_gcm_encrypt_17: movaps XMMWORD[(-112)+rbp],xmm12 -$L$SEH_prolog_aesni_gcm_encrypt_18: +$L$SEH_prologue_aesni_gcm_encrypt_18: movaps XMMWORD[(-96)+rbp],xmm13 -$L$SEH_prolog_aesni_gcm_encrypt_19: +$L$SEH_prologue_aesni_gcm_encrypt_19: movaps XMMWORD[(-80)+rbp],xmm14 -$L$SEH_prolog_aesni_gcm_encrypt_20: +$L$SEH_prologue_aesni_gcm_encrypt_20: movaps XMMWORD[(-64)+rbp],xmm15 -$L$SEH_prolog_aesni_gcm_encrypt_21: +$L$SEH_prologue_aesni_gcm_encrypt_21: +$L$SEH_endprologue_aesni_gcm_encrypt_22: vzeroupper vmovdqu xmm1,XMMWORD[rdi] @@ -943,7 +945,7 @@ $L$enc_no_key_aliasing: $L$gcm_enc_abort: ret -$L$SEH_end_aesni_gcm_encrypt_22: +$L$SEH_end_aesni_gcm_encrypt_23: section .rdata rdata align=8 @@ -968,11 +970,11 @@ section .text section .pdata rdata align=4 ALIGN 4 DD $L$SEH_begin_aesni_gcm_decrypt_1 wrt ..imagebase - DD $L$SEH_end_aesni_gcm_decrypt_22 wrt ..imagebase + DD $L$SEH_end_aesni_gcm_decrypt_23 wrt ..imagebase DD $L$SEH_info_aesni_gcm_decrypt_0 wrt ..imagebase DD $L$SEH_begin_aesni_gcm_encrypt_1 wrt ..imagebase - DD $L$SEH_end_aesni_gcm_encrypt_22 wrt ..imagebase + DD $L$SEH_end_aesni_gcm_encrypt_23 wrt ..imagebase DD $L$SEH_info_aesni_gcm_encrypt_0 wrt ..imagebase @@ -980,121 +982,124 @@ section .xdata rdata align=8 ALIGN 4 $L$SEH_info_aesni_gcm_decrypt_0: DB 1 - DB $L$SEH_prolog_aesni_gcm_decrypt_21-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_endprologue_aesni_gcm_decrypt_22-$L$SEH_begin_aesni_gcm_decrypt_1 DB 33 DB 213 - DB $L$SEH_prolog_aesni_gcm_decrypt_21-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_21-$L$SEH_begin_aesni_gcm_decrypt_1 DB 248 DW 9 - DB $L$SEH_prolog_aesni_gcm_decrypt_20-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_20-$L$SEH_begin_aesni_gcm_decrypt_1 DB 232 DW 8 - DB $L$SEH_prolog_aesni_gcm_decrypt_19-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_19-$L$SEH_begin_aesni_gcm_decrypt_1 DB 216 DW 7 - DB $L$SEH_prolog_aesni_gcm_decrypt_18-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_18-$L$SEH_begin_aesni_gcm_decrypt_1 DB 200 DW 6 - DB $L$SEH_prolog_aesni_gcm_decrypt_17-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_17-$L$SEH_begin_aesni_gcm_decrypt_1 DB 184 DW 5 - DB $L$SEH_prolog_aesni_gcm_decrypt_16-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_16-$L$SEH_begin_aesni_gcm_decrypt_1 DB 168 DW 4 - DB $L$SEH_prolog_aesni_gcm_decrypt_15-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_15-$L$SEH_begin_aesni_gcm_decrypt_1 DB 152 DW 3 - DB $L$SEH_prolog_aesni_gcm_decrypt_14-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_14-$L$SEH_begin_aesni_gcm_decrypt_1 DB 136 DW 2 - DB $L$SEH_prolog_aesni_gcm_decrypt_13-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_13-$L$SEH_begin_aesni_gcm_decrypt_1 DB 120 DW 1 - DB $L$SEH_prolog_aesni_gcm_decrypt_12-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_12-$L$SEH_begin_aesni_gcm_decrypt_1 DB 104 DW 0 - DB $L$SEH_prolog_aesni_gcm_decrypt_11-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_11-$L$SEH_begin_aesni_gcm_decrypt_1 DB 100 DW 29 - DB $L$SEH_prolog_aesni_gcm_decrypt_10-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_10-$L$SEH_begin_aesni_gcm_decrypt_1 DB 116 DW 28 - DB $L$SEH_prolog_aesni_gcm_decrypt_9-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_9-$L$SEH_begin_aesni_gcm_decrypt_1 DB 3 - DB $L$SEH_prolog_aesni_gcm_decrypt_8-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_8-$L$SEH_begin_aesni_gcm_decrypt_1 DB 1 DW 21 - DB $L$SEH_prolog_aesni_gcm_decrypt_7-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_7-$L$SEH_begin_aesni_gcm_decrypt_1 DB 240 - DB $L$SEH_prolog_aesni_gcm_decrypt_6-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_6-$L$SEH_begin_aesni_gcm_decrypt_1 DB 224 - DB $L$SEH_prolog_aesni_gcm_decrypt_5-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_5-$L$SEH_begin_aesni_gcm_decrypt_1 DB 208 - DB $L$SEH_prolog_aesni_gcm_decrypt_4-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_4-$L$SEH_begin_aesni_gcm_decrypt_1 DB 192 - DB $L$SEH_prolog_aesni_gcm_decrypt_3-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_3-$L$SEH_begin_aesni_gcm_decrypt_1 DB 48 - DB $L$SEH_prolog_aesni_gcm_decrypt_2-$L$SEH_begin_aesni_gcm_decrypt_1 + DB $L$SEH_prologue_aesni_gcm_decrypt_2-$L$SEH_begin_aesni_gcm_decrypt_1 DB 80 + DW 0 $L$SEH_info_aesni_gcm_encrypt_0: DB 1 - DB $L$SEH_prolog_aesni_gcm_encrypt_21-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_endprologue_aesni_gcm_encrypt_22-$L$SEH_begin_aesni_gcm_encrypt_1 DB 33 DB 213 - DB $L$SEH_prolog_aesni_gcm_encrypt_21-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_21-$L$SEH_begin_aesni_gcm_encrypt_1 DB 248 DW 9 - DB $L$SEH_prolog_aesni_gcm_encrypt_20-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_20-$L$SEH_begin_aesni_gcm_encrypt_1 DB 232 DW 8 - DB $L$SEH_prolog_aesni_gcm_encrypt_19-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_19-$L$SEH_begin_aesni_gcm_encrypt_1 DB 216 DW 7 - DB $L$SEH_prolog_aesni_gcm_encrypt_18-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_18-$L$SEH_begin_aesni_gcm_encrypt_1 DB 200 DW 6 - DB $L$SEH_prolog_aesni_gcm_encrypt_17-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_17-$L$SEH_begin_aesni_gcm_encrypt_1 DB 184 DW 5 - DB $L$SEH_prolog_aesni_gcm_encrypt_16-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_16-$L$SEH_begin_aesni_gcm_encrypt_1 DB 168 DW 4 - DB $L$SEH_prolog_aesni_gcm_encrypt_15-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_15-$L$SEH_begin_aesni_gcm_encrypt_1 DB 152 DW 3 - DB $L$SEH_prolog_aesni_gcm_encrypt_14-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_14-$L$SEH_begin_aesni_gcm_encrypt_1 DB 136 DW 2 - DB $L$SEH_prolog_aesni_gcm_encrypt_13-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_13-$L$SEH_begin_aesni_gcm_encrypt_1 DB 120 DW 1 - DB $L$SEH_prolog_aesni_gcm_encrypt_12-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_12-$L$SEH_begin_aesni_gcm_encrypt_1 DB 104 DW 0 - DB $L$SEH_prolog_aesni_gcm_encrypt_11-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_11-$L$SEH_begin_aesni_gcm_encrypt_1 DB 100 DW 29 - DB $L$SEH_prolog_aesni_gcm_encrypt_10-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_10-$L$SEH_begin_aesni_gcm_encrypt_1 DB 116 DW 28 - DB $L$SEH_prolog_aesni_gcm_encrypt_9-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_9-$L$SEH_begin_aesni_gcm_encrypt_1 DB 3 - DB $L$SEH_prolog_aesni_gcm_encrypt_8-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_8-$L$SEH_begin_aesni_gcm_encrypt_1 DB 1 DW 21 - DB $L$SEH_prolog_aesni_gcm_encrypt_7-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_7-$L$SEH_begin_aesni_gcm_encrypt_1 DB 240 - DB $L$SEH_prolog_aesni_gcm_encrypt_6-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_6-$L$SEH_begin_aesni_gcm_encrypt_1 DB 224 - DB $L$SEH_prolog_aesni_gcm_encrypt_5-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_5-$L$SEH_begin_aesni_gcm_encrypt_1 DB 208 - DB $L$SEH_prolog_aesni_gcm_encrypt_4-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_4-$L$SEH_begin_aesni_gcm_encrypt_1 DB 192 - DB $L$SEH_prolog_aesni_gcm_encrypt_3-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_3-$L$SEH_begin_aesni_gcm_encrypt_1 DB 48 - DB $L$SEH_prolog_aesni_gcm_encrypt_2-$L$SEH_begin_aesni_gcm_encrypt_1 + DB $L$SEH_prologue_aesni_gcm_encrypt_2-$L$SEH_begin_aesni_gcm_encrypt_1 DB 80 + + DW 0 %else ; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738 ret diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-apple.S index 44676044c6..dda66ed1d2 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-apple.S @@ -15,10 +15,10 @@ L_aes_hw_encrypt_begin: #ifdef BORINGSSL_DISPATCH_TEST pushl %ebx pushl %edx - call L000pic -L000pic: + call L000pic_for_function_hit +L000pic_for_function_hit: popl %ebx - leal _BORINGSSL_function_hit+1-L000pic(%ebx),%ebx + leal _BORINGSSL_function_hit+1-L000pic_for_function_hit(%ebx),%ebx movl $1,%edx movb %dl,(%ebx) popl %edx @@ -820,10 +820,10 @@ L_aes_hw_ctr32_encrypt_blocks_begin: #ifdef BORINGSSL_DISPATCH_TEST pushl %ebx pushl %edx - call L038pic -L038pic: + call L038pic_for_function_hit +L038pic_for_function_hit: popl %ebx - leal _BORINGSSL_function_hit+0-L038pic(%ebx),%ebx + leal _BORINGSSL_function_hit+0-L038pic_for_function_hit(%ebx),%ebx movl $1,%edx movb %dl,(%ebx) popl %edx @@ -2065,25 +2065,34 @@ L076cbc_abort: popl %ebx popl %ebp ret -.private_extern __aesni_set_encrypt_key +.globl _aes_hw_set_encrypt_key_base +.private_extern _aes_hw_set_encrypt_key_base .align 4 -__aesni_set_encrypt_key: - pushl %ebp +_aes_hw_set_encrypt_key_base: +L_aes_hw_set_encrypt_key_base_begin: +#ifdef BORINGSSL_DISPATCH_TEST + pushl %ebx + pushl %edx + call L093pic_for_function_hit +L093pic_for_function_hit: + popl %ebx + leal _BORINGSSL_function_hit+3-L093pic_for_function_hit(%ebx),%ebx + movl $1,%edx + movb %dl,(%ebx) + popl %edx + popl %ebx +#endif + movl 4(%esp),%eax + movl 8(%esp),%ecx + movl 12(%esp),%edx pushl %ebx - testl %eax,%eax - jz L093bad_pointer - testl %edx,%edx - jz L093bad_pointer call L094pic L094pic: popl %ebx leal Lkey_const-L094pic(%ebx),%ebx - movl L_OPENSSL_ia32cap_P$non_lazy_ptr-Lkey_const(%ebx),%ebp movups (%eax),%xmm0 xorps %xmm4,%xmm4 - movl 4(%ebp),%ebp leal 16(%edx),%edx - andl $268437504,%ebp cmpl $256,%ecx je L09514rounds cmpl $192,%ecx @@ -2092,38 +2101,36 @@ L094pic: jne L097bad_keybits .align 4,0x90 L09810rounds: - cmpl $268435456,%ebp - je L09910rounds_alt movl $9,%ecx movups %xmm0,-16(%edx) .byte 102,15,58,223,200,1 - call L100key_128_cold + call L099key_128_cold .byte 102,15,58,223,200,2 - call L101key_128 + call L100key_128 .byte 102,15,58,223,200,4 - call L101key_128 + call L100key_128 .byte 102,15,58,223,200,8 - call L101key_128 + call L100key_128 .byte 102,15,58,223,200,16 - call L101key_128 + call L100key_128 .byte 102,15,58,223,200,32 - call L101key_128 + call L100key_128 .byte 102,15,58,223,200,64 - call L101key_128 + call L100key_128 .byte 102,15,58,223,200,128 - call L101key_128 + call L100key_128 .byte 102,15,58,223,200,27 - call L101key_128 + call L100key_128 .byte 102,15,58,223,200,54 - call L101key_128 + call L100key_128 movups %xmm0,(%edx) movl %ecx,80(%edx) - jmp L102good_key + jmp L101good_key .align 4,0x90 -L101key_128: +L100key_128: movups %xmm0,(%edx) leal 16(%edx),%edx -L100key_128_cold: +L099key_128_cold: shufps $16,%xmm0,%xmm4 xorps %xmm4,%xmm0 shufps $140,%xmm0,%xmm4 @@ -2132,13 +2139,176 @@ L100key_128_cold: xorps %xmm1,%xmm0 ret .align 4,0x90 -L09910rounds_alt: +L09612rounds: + movq 16(%eax),%xmm2 + movl $11,%ecx + movups %xmm0,-16(%edx) +.byte 102,15,58,223,202,1 + call L102key_192a_cold +.byte 102,15,58,223,202,2 + call L103key_192b +.byte 102,15,58,223,202,4 + call L104key_192a +.byte 102,15,58,223,202,8 + call L103key_192b +.byte 102,15,58,223,202,16 + call L104key_192a +.byte 102,15,58,223,202,32 + call L103key_192b +.byte 102,15,58,223,202,64 + call L104key_192a +.byte 102,15,58,223,202,128 + call L103key_192b + movups %xmm0,(%edx) + movl %ecx,48(%edx) + jmp L101good_key +.align 4,0x90 +L104key_192a: + movups %xmm0,(%edx) + leal 16(%edx),%edx +.align 4,0x90 +L102key_192a_cold: + movaps %xmm2,%xmm5 +L105key_192b_warm: + shufps $16,%xmm0,%xmm4 + movdqa %xmm2,%xmm3 + xorps %xmm4,%xmm0 + shufps $140,%xmm0,%xmm4 + pslldq $4,%xmm3 + xorps %xmm4,%xmm0 + pshufd $85,%xmm1,%xmm1 + pxor %xmm3,%xmm2 + pxor %xmm1,%xmm0 + pshufd $255,%xmm0,%xmm3 + pxor %xmm3,%xmm2 + ret +.align 4,0x90 +L103key_192b: + movaps %xmm0,%xmm3 + shufps $68,%xmm0,%xmm5 + movups %xmm5,(%edx) + shufps $78,%xmm2,%xmm3 + movups %xmm3,16(%edx) + leal 32(%edx),%edx + jmp L105key_192b_warm +.align 4,0x90 +L09514rounds: + movups 16(%eax),%xmm2 + leal 16(%edx),%edx + movl $13,%ecx + movups %xmm0,-32(%edx) + movups %xmm2,-16(%edx) +.byte 102,15,58,223,202,1 + call L106key_256a_cold +.byte 102,15,58,223,200,1 + call L107key_256b +.byte 102,15,58,223,202,2 + call L108key_256a +.byte 102,15,58,223,200,2 + call L107key_256b +.byte 102,15,58,223,202,4 + call L108key_256a +.byte 102,15,58,223,200,4 + call L107key_256b +.byte 102,15,58,223,202,8 + call L108key_256a +.byte 102,15,58,223,200,8 + call L107key_256b +.byte 102,15,58,223,202,16 + call L108key_256a +.byte 102,15,58,223,200,16 + call L107key_256b +.byte 102,15,58,223,202,32 + call L108key_256a +.byte 102,15,58,223,200,32 + call L107key_256b +.byte 102,15,58,223,202,64 + call L108key_256a + movups %xmm0,(%edx) + movl %ecx,16(%edx) + xorl %eax,%eax + jmp L101good_key +.align 4,0x90 +L108key_256a: + movups %xmm2,(%edx) + leal 16(%edx),%edx +L106key_256a_cold: + shufps $16,%xmm0,%xmm4 + xorps %xmm4,%xmm0 + shufps $140,%xmm0,%xmm4 + xorps %xmm4,%xmm0 + shufps $255,%xmm1,%xmm1 + xorps %xmm1,%xmm0 + ret +.align 4,0x90 +L107key_256b: + movups %xmm0,(%edx) + leal 16(%edx),%edx + shufps $16,%xmm2,%xmm4 + xorps %xmm4,%xmm2 + shufps $140,%xmm2,%xmm4 + xorps %xmm4,%xmm2 + shufps $170,%xmm1,%xmm1 + xorps %xmm1,%xmm2 + ret +L101good_key: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + xorl %eax,%eax + popl %ebx + ret +.align 2,0x90 +L097bad_keybits: + pxor %xmm0,%xmm0 + movl $-2,%eax + popl %ebx + ret +.globl _aes_hw_set_encrypt_key_alt +.private_extern _aes_hw_set_encrypt_key_alt +.align 4 +_aes_hw_set_encrypt_key_alt: +L_aes_hw_set_encrypt_key_alt_begin: +#ifdef BORINGSSL_DISPATCH_TEST + pushl %ebx + pushl %edx + call L109pic_for_function_hit +L109pic_for_function_hit: + popl %ebx + leal _BORINGSSL_function_hit+3-L109pic_for_function_hit(%ebx),%ebx + movl $1,%edx + movb %dl,(%ebx) + popl %edx + popl %ebx +#endif + movl 4(%esp),%eax + movl 8(%esp),%ecx + movl 12(%esp),%edx + pushl %ebx + call L110pic +L110pic: + popl %ebx + leal Lkey_const-L110pic(%ebx),%ebx + movups (%eax),%xmm0 + xorps %xmm4,%xmm4 + leal 16(%edx),%edx + cmpl $256,%ecx + je L11114rounds_alt + cmpl $192,%ecx + je L11212rounds_alt + cmpl $128,%ecx + jne L113bad_keybits +.align 4,0x90 +L11410rounds_alt: movdqa (%ebx),%xmm5 movl $8,%ecx movdqa 32(%ebx),%xmm4 movdqa %xmm0,%xmm2 movdqu %xmm0,-16(%edx) -L103loop_key128: +L115loop_key128: .byte 102,15,56,0,197 .byte 102,15,56,221,196 pslld $1,%xmm4 @@ -2154,7 +2324,7 @@ L103loop_key128: movdqu %xmm0,-16(%edx) movdqa %xmm0,%xmm2 decl %ecx - jnz L103loop_key128 + jnz L115loop_key128 movdqa 48(%ebx),%xmm4 .byte 102,15,56,0,197 .byte 102,15,56,221,196 @@ -2182,69 +2352,15 @@ L103loop_key128: movdqu %xmm0,16(%edx) movl $9,%ecx movl %ecx,96(%edx) - jmp L102good_key + jmp L116good_key .align 4,0x90 -L09612rounds: +L11212rounds_alt: movq 16(%eax),%xmm2 - cmpl $268435456,%ebp - je L10412rounds_alt - movl $11,%ecx - movups %xmm0,-16(%edx) -.byte 102,15,58,223,202,1 - call L105key_192a_cold -.byte 102,15,58,223,202,2 - call L106key_192b -.byte 102,15,58,223,202,4 - call L107key_192a -.byte 102,15,58,223,202,8 - call L106key_192b -.byte 102,15,58,223,202,16 - call L107key_192a -.byte 102,15,58,223,202,32 - call L106key_192b -.byte 102,15,58,223,202,64 - call L107key_192a -.byte 102,15,58,223,202,128 - call L106key_192b - movups %xmm0,(%edx) - movl %ecx,48(%edx) - jmp L102good_key -.align 4,0x90 -L107key_192a: - movups %xmm0,(%edx) - leal 16(%edx),%edx -.align 4,0x90 -L105key_192a_cold: - movaps %xmm2,%xmm5 -L108key_192b_warm: - shufps $16,%xmm0,%xmm4 - movdqa %xmm2,%xmm3 - xorps %xmm4,%xmm0 - shufps $140,%xmm0,%xmm4 - pslldq $4,%xmm3 - xorps %xmm4,%xmm0 - pshufd $85,%xmm1,%xmm1 - pxor %xmm3,%xmm2 - pxor %xmm1,%xmm0 - pshufd $255,%xmm0,%xmm3 - pxor %xmm3,%xmm2 - ret -.align 4,0x90 -L106key_192b: - movaps %xmm0,%xmm3 - shufps $68,%xmm0,%xmm5 - movups %xmm5,(%edx) - shufps $78,%xmm2,%xmm3 - movups %xmm3,16(%edx) - leal 32(%edx),%edx - jmp L108key_192b_warm -.align 4,0x90 -L10412rounds_alt: movdqa 16(%ebx),%xmm5 movdqa 32(%ebx),%xmm4 movl $8,%ecx movdqu %xmm0,-16(%edx) -L109loop_key192: +L117loop_key192: movq %xmm2,(%edx) movdqa %xmm2,%xmm1 .byte 102,15,56,0,213 @@ -2266,81 +2382,21 @@ L109loop_key192: pxor %xmm3,%xmm2 movdqu %xmm0,-16(%edx) decl %ecx - jnz L109loop_key192 + jnz L117loop_key192 movl $11,%ecx movl %ecx,32(%edx) - jmp L102good_key + jmp L116good_key .align 4,0x90 -L09514rounds: +L11114rounds_alt: movups 16(%eax),%xmm2 leal 16(%edx),%edx - cmpl $268435456,%ebp - je L11014rounds_alt - movl $13,%ecx - movups %xmm0,-32(%edx) - movups %xmm2,-16(%edx) -.byte 102,15,58,223,202,1 - call L111key_256a_cold -.byte 102,15,58,223,200,1 - call L112key_256b -.byte 102,15,58,223,202,2 - call L113key_256a -.byte 102,15,58,223,200,2 - call L112key_256b -.byte 102,15,58,223,202,4 - call L113key_256a -.byte 102,15,58,223,200,4 - call L112key_256b -.byte 102,15,58,223,202,8 - call L113key_256a -.byte 102,15,58,223,200,8 - call L112key_256b -.byte 102,15,58,223,202,16 - call L113key_256a -.byte 102,15,58,223,200,16 - call L112key_256b -.byte 102,15,58,223,202,32 - call L113key_256a -.byte 102,15,58,223,200,32 - call L112key_256b -.byte 102,15,58,223,202,64 - call L113key_256a - movups %xmm0,(%edx) - movl %ecx,16(%edx) - xorl %eax,%eax - jmp L102good_key -.align 4,0x90 -L113key_256a: - movups %xmm2,(%edx) - leal 16(%edx),%edx -L111key_256a_cold: - shufps $16,%xmm0,%xmm4 - xorps %xmm4,%xmm0 - shufps $140,%xmm0,%xmm4 - xorps %xmm4,%xmm0 - shufps $255,%xmm1,%xmm1 - xorps %xmm1,%xmm0 - ret -.align 4,0x90 -L112key_256b: - movups %xmm0,(%edx) - leal 16(%edx),%edx - shufps $16,%xmm2,%xmm4 - xorps %xmm4,%xmm2 - shufps $140,%xmm2,%xmm4 - xorps %xmm4,%xmm2 - shufps $170,%xmm1,%xmm1 - xorps %xmm1,%xmm2 - ret -.align 4,0x90 -L11014rounds_alt: movdqa (%ebx),%xmm5 movdqa 32(%ebx),%xmm4 movl $7,%ecx movdqu %xmm0,-32(%edx) movdqa %xmm2,%xmm1 movdqu %xmm2,-16(%edx) -L114loop_key256: +L118loop_key256: .byte 102,15,56,0,213 .byte 102,15,56,221,212 movdqa %xmm0,%xmm3 @@ -2354,7 +2410,7 @@ L114loop_key256: pxor %xmm2,%xmm0 movdqu %xmm0,(%edx) decl %ecx - jz L115done_key256 + jz L119done_key256 pshufd $255,%xmm0,%xmm2 pxor %xmm3,%xmm3 .byte 102,15,56,221,211 @@ -2369,11 +2425,11 @@ L114loop_key256: movdqu %xmm2,16(%edx) leal 32(%edx),%edx movdqa %xmm2,%xmm1 - jmp L114loop_key256 -L115done_key256: + jmp L118loop_key256 +L119done_key256: movl $13,%ecx movl %ecx,16(%edx) -L102good_key: +L116good_key: pxor %xmm0,%xmm0 pxor %xmm1,%xmm1 pxor %xmm2,%xmm2 @@ -2382,56 +2438,21 @@ L102good_key: pxor %xmm5,%xmm5 xorl %eax,%eax popl %ebx - popl %ebp ret .align 2,0x90 -L093bad_pointer: - movl $-1,%eax - popl %ebx - popl %ebp - ret -.align 2,0x90 -L097bad_keybits: +L113bad_keybits: pxor %xmm0,%xmm0 movl $-2,%eax popl %ebx - popl %ebp ret -.globl _aes_hw_set_encrypt_key -.private_extern _aes_hw_set_encrypt_key +.globl _aes_hw_encrypt_key_to_decrypt_key +.private_extern _aes_hw_encrypt_key_to_decrypt_key .align 4 -_aes_hw_set_encrypt_key: -L_aes_hw_set_encrypt_key_begin: -#ifdef BORINGSSL_DISPATCH_TEST - pushl %ebx - pushl %edx - call L116pic -L116pic: - popl %ebx - leal _BORINGSSL_function_hit+3-L116pic(%ebx),%ebx - movl $1,%edx - movb %dl,(%ebx) - popl %edx - popl %ebx -#endif - movl 4(%esp),%eax - movl 8(%esp),%ecx - movl 12(%esp),%edx - call __aesni_set_encrypt_key - ret -.globl _aes_hw_set_decrypt_key -.private_extern _aes_hw_set_decrypt_key -.align 4 -_aes_hw_set_decrypt_key: -L_aes_hw_set_decrypt_key_begin: - movl 4(%esp),%eax - movl 8(%esp),%ecx - movl 12(%esp),%edx - call __aesni_set_encrypt_key - movl 12(%esp),%edx +_aes_hw_encrypt_key_to_decrypt_key: +L_aes_hw_encrypt_key_to_decrypt_key_begin: + movl 4(%esp),%edx + movl 240(%edx),%ecx shll $4,%ecx - testl %eax,%eax - jnz L117dec_key_ret leal 16(%edx,%ecx,1),%eax movups (%edx),%xmm0 movups (%eax),%xmm1 @@ -2439,7 +2460,7 @@ L_aes_hw_set_decrypt_key_begin: movups %xmm1,(%edx) leal 16(%edx),%edx leal -16(%eax),%eax -L118dec_key_inverse: +L120dec_key_inverse: movups (%edx),%xmm0 movups (%eax),%xmm1 .byte 102,15,56,219,192 @@ -2449,14 +2470,12 @@ L118dec_key_inverse: movups %xmm0,16(%eax) movups %xmm1,-16(%edx) cmpl %edx,%eax - ja L118dec_key_inverse + ja L120dec_key_inverse movups (%edx),%xmm0 .byte 102,15,56,219,192 movups %xmm0,(%edx) pxor %xmm0,%xmm0 pxor %xmm1,%xmm1 - xorl %eax,%eax -L117dec_key_ret: ret .align 6,0x90 Lkey_const: @@ -2468,8 +2487,4 @@ Lkey_const: .byte 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83 .byte 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115 .byte 115,108,46,111,114,103,62,0 -.section __IMPORT,__pointers,non_lazy_symbol_pointers -L_OPENSSL_ia32cap_P$non_lazy_ptr: -.indirect_symbol _OPENSSL_ia32cap_P -.long 0 #endif // !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__APPLE__) diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-linux.S index 54daf1808e..6fefe17555 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-linux.S @@ -16,10 +16,10 @@ aes_hw_encrypt: #ifdef BORINGSSL_DISPATCH_TEST pushl %ebx pushl %edx - call .L000pic -.L000pic: + call .L000pic_for_function_hit +.L000pic_for_function_hit: popl %ebx - leal BORINGSSL_function_hit+1-.L000pic(%ebx),%ebx + leal BORINGSSL_function_hit+1-.L000pic_for_function_hit(%ebx),%ebx movl $1,%edx movb %dl,(%ebx) popl %edx @@ -847,10 +847,10 @@ aes_hw_ctr32_encrypt_blocks: #ifdef BORINGSSL_DISPATCH_TEST pushl %ebx pushl %edx - call .L038pic -.L038pic: + call .L038pic_for_function_hit +.L038pic_for_function_hit: popl %ebx - leal BORINGSSL_function_hit+0-.L038pic(%ebx),%ebx + leal BORINGSSL_function_hit+0-.L038pic_for_function_hit(%ebx),%ebx movl $1,%edx movb %dl,(%ebx) popl %edx @@ -2099,26 +2099,35 @@ aes_hw_cbc_encrypt: popl %ebp ret .size aes_hw_cbc_encrypt,.-.L_aes_hw_cbc_encrypt_begin -.hidden _aesni_set_encrypt_key -.type _aesni_set_encrypt_key,@function +.globl aes_hw_set_encrypt_key_base +.hidden aes_hw_set_encrypt_key_base +.type aes_hw_set_encrypt_key_base,@function .align 16 -_aesni_set_encrypt_key: - pushl %ebp +aes_hw_set_encrypt_key_base: +.L_aes_hw_set_encrypt_key_base_begin: +#ifdef BORINGSSL_DISPATCH_TEST + pushl %ebx + pushl %edx + call .L093pic_for_function_hit +.L093pic_for_function_hit: + popl %ebx + leal BORINGSSL_function_hit+3-.L093pic_for_function_hit(%ebx),%ebx + movl $1,%edx + movb %dl,(%ebx) + popl %edx + popl %ebx +#endif + movl 4(%esp),%eax + movl 8(%esp),%ecx + movl 12(%esp),%edx pushl %ebx - testl %eax,%eax - jz .L093bad_pointer - testl %edx,%edx - jz .L093bad_pointer call .L094pic .L094pic: popl %ebx leal .Lkey_const-.L094pic(%ebx),%ebx - leal OPENSSL_ia32cap_P-.Lkey_const(%ebx),%ebp movups (%eax),%xmm0 xorps %xmm4,%xmm4 - movl 4(%ebp),%ebp leal 16(%edx),%edx - andl $268437504,%ebp cmpl $256,%ecx je .L09514rounds cmpl $192,%ecx @@ -2127,38 +2136,36 @@ _aesni_set_encrypt_key: jne .L097bad_keybits .align 16 .L09810rounds: - cmpl $268435456,%ebp - je .L09910rounds_alt movl $9,%ecx movups %xmm0,-16(%edx) .byte 102,15,58,223,200,1 - call .L100key_128_cold + call .L099key_128_cold .byte 102,15,58,223,200,2 - call .L101key_128 + call .L100key_128 .byte 102,15,58,223,200,4 - call .L101key_128 + call .L100key_128 .byte 102,15,58,223,200,8 - call .L101key_128 + call .L100key_128 .byte 102,15,58,223,200,16 - call .L101key_128 + call .L100key_128 .byte 102,15,58,223,200,32 - call .L101key_128 + call .L100key_128 .byte 102,15,58,223,200,64 - call .L101key_128 + call .L100key_128 .byte 102,15,58,223,200,128 - call .L101key_128 + call .L100key_128 .byte 102,15,58,223,200,27 - call .L101key_128 + call .L100key_128 .byte 102,15,58,223,200,54 - call .L101key_128 + call .L100key_128 movups %xmm0,(%edx) movl %ecx,80(%edx) - jmp .L102good_key + jmp .L101good_key .align 16 -.L101key_128: +.L100key_128: movups %xmm0,(%edx) leal 16(%edx),%edx -.L100key_128_cold: +.L099key_128_cold: shufps $16,%xmm0,%xmm4 xorps %xmm4,%xmm0 shufps $140,%xmm0,%xmm4 @@ -2167,13 +2174,178 @@ _aesni_set_encrypt_key: xorps %xmm1,%xmm0 ret .align 16 -.L09910rounds_alt: +.L09612rounds: + movq 16(%eax),%xmm2 + movl $11,%ecx + movups %xmm0,-16(%edx) +.byte 102,15,58,223,202,1 + call .L102key_192a_cold +.byte 102,15,58,223,202,2 + call .L103key_192b +.byte 102,15,58,223,202,4 + call .L104key_192a +.byte 102,15,58,223,202,8 + call .L103key_192b +.byte 102,15,58,223,202,16 + call .L104key_192a +.byte 102,15,58,223,202,32 + call .L103key_192b +.byte 102,15,58,223,202,64 + call .L104key_192a +.byte 102,15,58,223,202,128 + call .L103key_192b + movups %xmm0,(%edx) + movl %ecx,48(%edx) + jmp .L101good_key +.align 16 +.L104key_192a: + movups %xmm0,(%edx) + leal 16(%edx),%edx +.align 16 +.L102key_192a_cold: + movaps %xmm2,%xmm5 +.L105key_192b_warm: + shufps $16,%xmm0,%xmm4 + movdqa %xmm2,%xmm3 + xorps %xmm4,%xmm0 + shufps $140,%xmm0,%xmm4 + pslldq $4,%xmm3 + xorps %xmm4,%xmm0 + pshufd $85,%xmm1,%xmm1 + pxor %xmm3,%xmm2 + pxor %xmm1,%xmm0 + pshufd $255,%xmm0,%xmm3 + pxor %xmm3,%xmm2 + ret +.align 16 +.L103key_192b: + movaps %xmm0,%xmm3 + shufps $68,%xmm0,%xmm5 + movups %xmm5,(%edx) + shufps $78,%xmm2,%xmm3 + movups %xmm3,16(%edx) + leal 32(%edx),%edx + jmp .L105key_192b_warm +.align 16 +.L09514rounds: + movups 16(%eax),%xmm2 + leal 16(%edx),%edx + movl $13,%ecx + movups %xmm0,-32(%edx) + movups %xmm2,-16(%edx) +.byte 102,15,58,223,202,1 + call .L106key_256a_cold +.byte 102,15,58,223,200,1 + call .L107key_256b +.byte 102,15,58,223,202,2 + call .L108key_256a +.byte 102,15,58,223,200,2 + call .L107key_256b +.byte 102,15,58,223,202,4 + call .L108key_256a +.byte 102,15,58,223,200,4 + call .L107key_256b +.byte 102,15,58,223,202,8 + call .L108key_256a +.byte 102,15,58,223,200,8 + call .L107key_256b +.byte 102,15,58,223,202,16 + call .L108key_256a +.byte 102,15,58,223,200,16 + call .L107key_256b +.byte 102,15,58,223,202,32 + call .L108key_256a +.byte 102,15,58,223,200,32 + call .L107key_256b +.byte 102,15,58,223,202,64 + call .L108key_256a + movups %xmm0,(%edx) + movl %ecx,16(%edx) + xorl %eax,%eax + jmp .L101good_key +.align 16 +.L108key_256a: + movups %xmm2,(%edx) + leal 16(%edx),%edx +.L106key_256a_cold: + shufps $16,%xmm0,%xmm4 + xorps %xmm4,%xmm0 + shufps $140,%xmm0,%xmm4 + xorps %xmm4,%xmm0 + shufps $255,%xmm1,%xmm1 + xorps %xmm1,%xmm0 + ret +.align 16 +.L107key_256b: + movups %xmm0,(%edx) + leal 16(%edx),%edx + shufps $16,%xmm2,%xmm4 + xorps %xmm4,%xmm2 + shufps $140,%xmm2,%xmm4 + xorps %xmm4,%xmm2 + shufps $170,%xmm1,%xmm1 + xorps %xmm1,%xmm2 + ret +.L101good_key: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + xorl %eax,%eax + popl %ebx + ret +.align 4 +.L097bad_keybits: + pxor %xmm0,%xmm0 + movl $-2,%eax + popl %ebx + ret +.size aes_hw_set_encrypt_key_base,.-.L_aes_hw_set_encrypt_key_base_begin +.globl aes_hw_set_encrypt_key_alt +.hidden aes_hw_set_encrypt_key_alt +.type aes_hw_set_encrypt_key_alt,@function +.align 16 +aes_hw_set_encrypt_key_alt: +.L_aes_hw_set_encrypt_key_alt_begin: +#ifdef BORINGSSL_DISPATCH_TEST + pushl %ebx + pushl %edx + call .L109pic_for_function_hit +.L109pic_for_function_hit: + popl %ebx + leal BORINGSSL_function_hit+3-.L109pic_for_function_hit(%ebx),%ebx + movl $1,%edx + movb %dl,(%ebx) + popl %edx + popl %ebx +#endif + movl 4(%esp),%eax + movl 8(%esp),%ecx + movl 12(%esp),%edx + pushl %ebx + call .L110pic +.L110pic: + popl %ebx + leal .Lkey_const-.L110pic(%ebx),%ebx + movups (%eax),%xmm0 + xorps %xmm4,%xmm4 + leal 16(%edx),%edx + cmpl $256,%ecx + je .L11114rounds_alt + cmpl $192,%ecx + je .L11212rounds_alt + cmpl $128,%ecx + jne .L113bad_keybits +.align 16 +.L11410rounds_alt: movdqa (%ebx),%xmm5 movl $8,%ecx movdqa 32(%ebx),%xmm4 movdqa %xmm0,%xmm2 movdqu %xmm0,-16(%edx) -.L103loop_key128: +.L115loop_key128: .byte 102,15,56,0,197 .byte 102,15,56,221,196 pslld $1,%xmm4 @@ -2189,7 +2361,7 @@ _aesni_set_encrypt_key: movdqu %xmm0,-16(%edx) movdqa %xmm0,%xmm2 decl %ecx - jnz .L103loop_key128 + jnz .L115loop_key128 movdqa 48(%ebx),%xmm4 .byte 102,15,56,0,197 .byte 102,15,56,221,196 @@ -2217,69 +2389,15 @@ _aesni_set_encrypt_key: movdqu %xmm0,16(%edx) movl $9,%ecx movl %ecx,96(%edx) - jmp .L102good_key + jmp .L116good_key .align 16 -.L09612rounds: +.L11212rounds_alt: movq 16(%eax),%xmm2 - cmpl $268435456,%ebp - je .L10412rounds_alt - movl $11,%ecx - movups %xmm0,-16(%edx) -.byte 102,15,58,223,202,1 - call .L105key_192a_cold -.byte 102,15,58,223,202,2 - call .L106key_192b -.byte 102,15,58,223,202,4 - call .L107key_192a -.byte 102,15,58,223,202,8 - call .L106key_192b -.byte 102,15,58,223,202,16 - call .L107key_192a -.byte 102,15,58,223,202,32 - call .L106key_192b -.byte 102,15,58,223,202,64 - call .L107key_192a -.byte 102,15,58,223,202,128 - call .L106key_192b - movups %xmm0,(%edx) - movl %ecx,48(%edx) - jmp .L102good_key -.align 16 -.L107key_192a: - movups %xmm0,(%edx) - leal 16(%edx),%edx -.align 16 -.L105key_192a_cold: - movaps %xmm2,%xmm5 -.L108key_192b_warm: - shufps $16,%xmm0,%xmm4 - movdqa %xmm2,%xmm3 - xorps %xmm4,%xmm0 - shufps $140,%xmm0,%xmm4 - pslldq $4,%xmm3 - xorps %xmm4,%xmm0 - pshufd $85,%xmm1,%xmm1 - pxor %xmm3,%xmm2 - pxor %xmm1,%xmm0 - pshufd $255,%xmm0,%xmm3 - pxor %xmm3,%xmm2 - ret -.align 16 -.L106key_192b: - movaps %xmm0,%xmm3 - shufps $68,%xmm0,%xmm5 - movups %xmm5,(%edx) - shufps $78,%xmm2,%xmm3 - movups %xmm3,16(%edx) - leal 32(%edx),%edx - jmp .L108key_192b_warm -.align 16 -.L10412rounds_alt: movdqa 16(%ebx),%xmm5 movdqa 32(%ebx),%xmm4 movl $8,%ecx movdqu %xmm0,-16(%edx) -.L109loop_key192: +.L117loop_key192: movq %xmm2,(%edx) movdqa %xmm2,%xmm1 .byte 102,15,56,0,213 @@ -2301,81 +2419,21 @@ _aesni_set_encrypt_key: pxor %xmm3,%xmm2 movdqu %xmm0,-16(%edx) decl %ecx - jnz .L109loop_key192 + jnz .L117loop_key192 movl $11,%ecx movl %ecx,32(%edx) - jmp .L102good_key + jmp .L116good_key .align 16 -.L09514rounds: +.L11114rounds_alt: movups 16(%eax),%xmm2 leal 16(%edx),%edx - cmpl $268435456,%ebp - je .L11014rounds_alt - movl $13,%ecx - movups %xmm0,-32(%edx) - movups %xmm2,-16(%edx) -.byte 102,15,58,223,202,1 - call .L111key_256a_cold -.byte 102,15,58,223,200,1 - call .L112key_256b -.byte 102,15,58,223,202,2 - call .L113key_256a -.byte 102,15,58,223,200,2 - call .L112key_256b -.byte 102,15,58,223,202,4 - call .L113key_256a -.byte 102,15,58,223,200,4 - call .L112key_256b -.byte 102,15,58,223,202,8 - call .L113key_256a -.byte 102,15,58,223,200,8 - call .L112key_256b -.byte 102,15,58,223,202,16 - call .L113key_256a -.byte 102,15,58,223,200,16 - call .L112key_256b -.byte 102,15,58,223,202,32 - call .L113key_256a -.byte 102,15,58,223,200,32 - call .L112key_256b -.byte 102,15,58,223,202,64 - call .L113key_256a - movups %xmm0,(%edx) - movl %ecx,16(%edx) - xorl %eax,%eax - jmp .L102good_key -.align 16 -.L113key_256a: - movups %xmm2,(%edx) - leal 16(%edx),%edx -.L111key_256a_cold: - shufps $16,%xmm0,%xmm4 - xorps %xmm4,%xmm0 - shufps $140,%xmm0,%xmm4 - xorps %xmm4,%xmm0 - shufps $255,%xmm1,%xmm1 - xorps %xmm1,%xmm0 - ret -.align 16 -.L112key_256b: - movups %xmm0,(%edx) - leal 16(%edx),%edx - shufps $16,%xmm2,%xmm4 - xorps %xmm4,%xmm2 - shufps $140,%xmm2,%xmm4 - xorps %xmm4,%xmm2 - shufps $170,%xmm1,%xmm1 - xorps %xmm1,%xmm2 - ret -.align 16 -.L11014rounds_alt: movdqa (%ebx),%xmm5 movdqa 32(%ebx),%xmm4 movl $7,%ecx movdqu %xmm0,-32(%edx) movdqa %xmm2,%xmm1 movdqu %xmm2,-16(%edx) -.L114loop_key256: +.L118loop_key256: .byte 102,15,56,0,213 .byte 102,15,56,221,212 movdqa %xmm0,%xmm3 @@ -2389,7 +2447,7 @@ _aesni_set_encrypt_key: pxor %xmm2,%xmm0 movdqu %xmm0,(%edx) decl %ecx - jz .L115done_key256 + jz .L119done_key256 pshufd $255,%xmm0,%xmm2 pxor %xmm3,%xmm3 .byte 102,15,56,221,211 @@ -2404,11 +2462,11 @@ _aesni_set_encrypt_key: movdqu %xmm2,16(%edx) leal 32(%edx),%edx movdqa %xmm2,%xmm1 - jmp .L114loop_key256 -.L115done_key256: + jmp .L118loop_key256 +.L119done_key256: movl $13,%ecx movl %ecx,16(%edx) -.L102good_key: +.L116good_key: pxor %xmm0,%xmm0 pxor %xmm1,%xmm1 pxor %xmm2,%xmm2 @@ -2417,60 +2475,23 @@ _aesni_set_encrypt_key: pxor %xmm5,%xmm5 xorl %eax,%eax popl %ebx - popl %ebp ret .align 4 -.L093bad_pointer: - movl $-1,%eax - popl %ebx - popl %ebp - ret -.align 4 -.L097bad_keybits: +.L113bad_keybits: pxor %xmm0,%xmm0 movl $-2,%eax popl %ebx - popl %ebp ret -.size _aesni_set_encrypt_key,.-_aesni_set_encrypt_key -.globl aes_hw_set_encrypt_key -.hidden aes_hw_set_encrypt_key -.type aes_hw_set_encrypt_key,@function +.size aes_hw_set_encrypt_key_alt,.-.L_aes_hw_set_encrypt_key_alt_begin +.globl aes_hw_encrypt_key_to_decrypt_key +.hidden aes_hw_encrypt_key_to_decrypt_key +.type aes_hw_encrypt_key_to_decrypt_key,@function .align 16 -aes_hw_set_encrypt_key: -.L_aes_hw_set_encrypt_key_begin: -#ifdef BORINGSSL_DISPATCH_TEST - pushl %ebx - pushl %edx - call .L116pic -.L116pic: - popl %ebx - leal BORINGSSL_function_hit+3-.L116pic(%ebx),%ebx - movl $1,%edx - movb %dl,(%ebx) - popl %edx - popl %ebx -#endif - movl 4(%esp),%eax - movl 8(%esp),%ecx - movl 12(%esp),%edx - call _aesni_set_encrypt_key - ret -.size aes_hw_set_encrypt_key,.-.L_aes_hw_set_encrypt_key_begin -.globl aes_hw_set_decrypt_key -.hidden aes_hw_set_decrypt_key -.type aes_hw_set_decrypt_key,@function -.align 16 -aes_hw_set_decrypt_key: -.L_aes_hw_set_decrypt_key_begin: - movl 4(%esp),%eax - movl 8(%esp),%ecx - movl 12(%esp),%edx - call _aesni_set_encrypt_key - movl 12(%esp),%edx +aes_hw_encrypt_key_to_decrypt_key: +.L_aes_hw_encrypt_key_to_decrypt_key_begin: + movl 4(%esp),%edx + movl 240(%edx),%ecx shll $4,%ecx - testl %eax,%eax - jnz .L117dec_key_ret leal 16(%edx,%ecx,1),%eax movups (%edx),%xmm0 movups (%eax),%xmm1 @@ -2478,7 +2499,7 @@ aes_hw_set_decrypt_key: movups %xmm1,(%edx) leal 16(%edx),%edx leal -16(%eax),%eax -.L118dec_key_inverse: +.L120dec_key_inverse: movups (%edx),%xmm0 movups (%eax),%xmm1 .byte 102,15,56,219,192 @@ -2488,16 +2509,14 @@ aes_hw_set_decrypt_key: movups %xmm0,16(%eax) movups %xmm1,-16(%edx) cmpl %edx,%eax - ja .L118dec_key_inverse + ja .L120dec_key_inverse movups (%edx),%xmm0 .byte 102,15,56,219,192 movups %xmm0,(%edx) pxor %xmm0,%xmm0 pxor %xmm1,%xmm1 - xorl %eax,%eax -.L117dec_key_ret: ret -.size aes_hw_set_decrypt_key,.-.L_aes_hw_set_decrypt_key_begin +.size aes_hw_encrypt_key_to_decrypt_key,.-.L_aes_hw_encrypt_key_to_decrypt_key_begin .align 64 .Lkey_const: .long 202313229,202313229,202313229,202313229 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-win.asm index 19b1d98bea..4453afb1bf 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86-win.asm @@ -13,7 +13,6 @@ section .text code align=64 %else section .text code %endif -;extern _OPENSSL_ia32cap_P %ifdef BORINGSSL_DISPATCH_TEST extern _BORINGSSL_function_hit %endif @@ -24,10 +23,10 @@ L$_aes_hw_encrypt_begin: %ifdef BORINGSSL_DISPATCH_TEST push ebx push edx - call L$000pic -L$000pic: + call L$000pic_for_function_hit +L$000pic_for_function_hit: pop ebx - lea ebx,[(_BORINGSSL_function_hit+1-L$000pic)+ebx] + lea ebx,[(_BORINGSSL_function_hit+1-L$000pic_for_function_hit)+ebx] mov edx,1 mov BYTE [ebx],dl pop edx @@ -816,10 +815,10 @@ L$_aes_hw_ctr32_encrypt_blocks_begin: %ifdef BORINGSSL_DISPATCH_TEST push ebx push edx - call L$038pic -L$038pic: + call L$038pic_for_function_hit +L$038pic_for_function_hit: pop ebx - lea ebx,[(_BORINGSSL_function_hit+0-L$038pic)+ebx] + lea ebx,[(_BORINGSSL_function_hit+0-L$038pic_for_function_hit)+ebx] mov edx,1 mov BYTE [ebx],dl pop edx @@ -2058,24 +2057,33 @@ L$076cbc_abort: pop ebx pop ebp ret +global _aes_hw_set_encrypt_key_base align 16 -__aesni_set_encrypt_key: - push ebp +_aes_hw_set_encrypt_key_base: +L$_aes_hw_set_encrypt_key_base_begin: +%ifdef BORINGSSL_DISPATCH_TEST + push ebx + push edx + call L$093pic_for_function_hit +L$093pic_for_function_hit: + pop ebx + lea ebx,[(_BORINGSSL_function_hit+3-L$093pic_for_function_hit)+ebx] + mov edx,1 + mov BYTE [ebx],dl + pop edx + pop ebx +%endif + mov eax,DWORD [4+esp] + mov ecx,DWORD [8+esp] + mov edx,DWORD [12+esp] push ebx - test eax,eax - jz NEAR L$093bad_pointer - test edx,edx - jz NEAR L$093bad_pointer call L$094pic L$094pic: pop ebx lea ebx,[(L$key_const-L$094pic)+ebx] - lea ebp,[_OPENSSL_ia32cap_P] movups xmm0,[eax] xorps xmm4,xmm4 - mov ebp,DWORD [4+ebp] lea edx,[16+edx] - and ebp,268437504 cmp ecx,256 je NEAR L$09514rounds cmp ecx,192 @@ -2084,38 +2092,36 @@ L$094pic: jne NEAR L$097bad_keybits align 16 L$09810rounds: - cmp ebp,268435456 - je NEAR L$09910rounds_alt mov ecx,9 movups [edx-16],xmm0 db 102,15,58,223,200,1 - call L$100key_128_cold + call L$099key_128_cold db 102,15,58,223,200,2 - call L$101key_128 + call L$100key_128 db 102,15,58,223,200,4 - call L$101key_128 + call L$100key_128 db 102,15,58,223,200,8 - call L$101key_128 + call L$100key_128 db 102,15,58,223,200,16 - call L$101key_128 + call L$100key_128 db 102,15,58,223,200,32 - call L$101key_128 + call L$100key_128 db 102,15,58,223,200,64 - call L$101key_128 + call L$100key_128 db 102,15,58,223,200,128 - call L$101key_128 + call L$100key_128 db 102,15,58,223,200,27 - call L$101key_128 + call L$100key_128 db 102,15,58,223,200,54 - call L$101key_128 + call L$100key_128 movups [edx],xmm0 mov DWORD [80+edx],ecx - jmp NEAR L$102good_key + jmp NEAR L$101good_key align 16 -L$101key_128: +L$100key_128: movups [edx],xmm0 lea edx,[16+edx] -L$100key_128_cold: +L$099key_128_cold: shufps xmm4,xmm0,16 xorps xmm0,xmm4 shufps xmm4,xmm0,140 @@ -2124,13 +2130,175 @@ L$100key_128_cold: xorps xmm0,xmm1 ret align 16 -L$09910rounds_alt: +L$09612rounds: + movq xmm2,[16+eax] + mov ecx,11 + movups [edx-16],xmm0 +db 102,15,58,223,202,1 + call L$102key_192a_cold +db 102,15,58,223,202,2 + call L$103key_192b +db 102,15,58,223,202,4 + call L$104key_192a +db 102,15,58,223,202,8 + call L$103key_192b +db 102,15,58,223,202,16 + call L$104key_192a +db 102,15,58,223,202,32 + call L$103key_192b +db 102,15,58,223,202,64 + call L$104key_192a +db 102,15,58,223,202,128 + call L$103key_192b + movups [edx],xmm0 + mov DWORD [48+edx],ecx + jmp NEAR L$101good_key +align 16 +L$104key_192a: + movups [edx],xmm0 + lea edx,[16+edx] +align 16 +L$102key_192a_cold: + movaps xmm5,xmm2 +L$105key_192b_warm: + shufps xmm4,xmm0,16 + movdqa xmm3,xmm2 + xorps xmm0,xmm4 + shufps xmm4,xmm0,140 + pslldq xmm3,4 + xorps xmm0,xmm4 + pshufd xmm1,xmm1,85 + pxor xmm2,xmm3 + pxor xmm0,xmm1 + pshufd xmm3,xmm0,255 + pxor xmm2,xmm3 + ret +align 16 +L$103key_192b: + movaps xmm3,xmm0 + shufps xmm5,xmm0,68 + movups [edx],xmm5 + shufps xmm3,xmm2,78 + movups [16+edx],xmm3 + lea edx,[32+edx] + jmp NEAR L$105key_192b_warm +align 16 +L$09514rounds: + movups xmm2,[16+eax] + lea edx,[16+edx] + mov ecx,13 + movups [edx-32],xmm0 + movups [edx-16],xmm2 +db 102,15,58,223,202,1 + call L$106key_256a_cold +db 102,15,58,223,200,1 + call L$107key_256b +db 102,15,58,223,202,2 + call L$108key_256a +db 102,15,58,223,200,2 + call L$107key_256b +db 102,15,58,223,202,4 + call L$108key_256a +db 102,15,58,223,200,4 + call L$107key_256b +db 102,15,58,223,202,8 + call L$108key_256a +db 102,15,58,223,200,8 + call L$107key_256b +db 102,15,58,223,202,16 + call L$108key_256a +db 102,15,58,223,200,16 + call L$107key_256b +db 102,15,58,223,202,32 + call L$108key_256a +db 102,15,58,223,200,32 + call L$107key_256b +db 102,15,58,223,202,64 + call L$108key_256a + movups [edx],xmm0 + mov DWORD [16+edx],ecx + xor eax,eax + jmp NEAR L$101good_key +align 16 +L$108key_256a: + movups [edx],xmm2 + lea edx,[16+edx] +L$106key_256a_cold: + shufps xmm4,xmm0,16 + xorps xmm0,xmm4 + shufps xmm4,xmm0,140 + xorps xmm0,xmm4 + shufps xmm1,xmm1,255 + xorps xmm0,xmm1 + ret +align 16 +L$107key_256b: + movups [edx],xmm0 + lea edx,[16+edx] + shufps xmm4,xmm2,16 + xorps xmm2,xmm4 + shufps xmm4,xmm2,140 + xorps xmm2,xmm4 + shufps xmm1,xmm1,170 + xorps xmm2,xmm1 + ret +L$101good_key: + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 + xor eax,eax + pop ebx + ret +align 4 +L$097bad_keybits: + pxor xmm0,xmm0 + mov eax,-2 + pop ebx + ret +global _aes_hw_set_encrypt_key_alt +align 16 +_aes_hw_set_encrypt_key_alt: +L$_aes_hw_set_encrypt_key_alt_begin: +%ifdef BORINGSSL_DISPATCH_TEST + push ebx + push edx + call L$109pic_for_function_hit +L$109pic_for_function_hit: + pop ebx + lea ebx,[(_BORINGSSL_function_hit+3-L$109pic_for_function_hit)+ebx] + mov edx,1 + mov BYTE [ebx],dl + pop edx + pop ebx +%endif + mov eax,DWORD [4+esp] + mov ecx,DWORD [8+esp] + mov edx,DWORD [12+esp] + push ebx + call L$110pic +L$110pic: + pop ebx + lea ebx,[(L$key_const-L$110pic)+ebx] + movups xmm0,[eax] + xorps xmm4,xmm4 + lea edx,[16+edx] + cmp ecx,256 + je NEAR L$11114rounds_alt + cmp ecx,192 + je NEAR L$11212rounds_alt + cmp ecx,128 + jne NEAR L$113bad_keybits +align 16 +L$11410rounds_alt: movdqa xmm5,[ebx] mov ecx,8 movdqa xmm4,[32+ebx] movdqa xmm2,xmm0 movdqu [edx-16],xmm0 -L$103loop_key128: +L$115loop_key128: db 102,15,56,0,197 db 102,15,56,221,196 pslld xmm4,1 @@ -2146,7 +2314,7 @@ db 102,15,56,221,196 movdqu [edx-16],xmm0 movdqa xmm2,xmm0 dec ecx - jnz NEAR L$103loop_key128 + jnz NEAR L$115loop_key128 movdqa xmm4,[48+ebx] db 102,15,56,0,197 db 102,15,56,221,196 @@ -2174,69 +2342,15 @@ db 102,15,56,221,196 movdqu [16+edx],xmm0 mov ecx,9 mov DWORD [96+edx],ecx - jmp NEAR L$102good_key + jmp NEAR L$116good_key align 16 -L$09612rounds: +L$11212rounds_alt: movq xmm2,[16+eax] - cmp ebp,268435456 - je NEAR L$10412rounds_alt - mov ecx,11 - movups [edx-16],xmm0 -db 102,15,58,223,202,1 - call L$105key_192a_cold -db 102,15,58,223,202,2 - call L$106key_192b -db 102,15,58,223,202,4 - call L$107key_192a -db 102,15,58,223,202,8 - call L$106key_192b -db 102,15,58,223,202,16 - call L$107key_192a -db 102,15,58,223,202,32 - call L$106key_192b -db 102,15,58,223,202,64 - call L$107key_192a -db 102,15,58,223,202,128 - call L$106key_192b - movups [edx],xmm0 - mov DWORD [48+edx],ecx - jmp NEAR L$102good_key -align 16 -L$107key_192a: - movups [edx],xmm0 - lea edx,[16+edx] -align 16 -L$105key_192a_cold: - movaps xmm5,xmm2 -L$108key_192b_warm: - shufps xmm4,xmm0,16 - movdqa xmm3,xmm2 - xorps xmm0,xmm4 - shufps xmm4,xmm0,140 - pslldq xmm3,4 - xorps xmm0,xmm4 - pshufd xmm1,xmm1,85 - pxor xmm2,xmm3 - pxor xmm0,xmm1 - pshufd xmm3,xmm0,255 - pxor xmm2,xmm3 - ret -align 16 -L$106key_192b: - movaps xmm3,xmm0 - shufps xmm5,xmm0,68 - movups [edx],xmm5 - shufps xmm3,xmm2,78 - movups [16+edx],xmm3 - lea edx,[32+edx] - jmp NEAR L$108key_192b_warm -align 16 -L$10412rounds_alt: movdqa xmm5,[16+ebx] movdqa xmm4,[32+ebx] mov ecx,8 movdqu [edx-16],xmm0 -L$109loop_key192: +L$117loop_key192: movq [edx],xmm2 movdqa xmm1,xmm2 db 102,15,56,0,213 @@ -2258,81 +2372,21 @@ db 102,15,56,221,212 pxor xmm2,xmm3 movdqu [edx-16],xmm0 dec ecx - jnz NEAR L$109loop_key192 + jnz NEAR L$117loop_key192 mov ecx,11 mov DWORD [32+edx],ecx - jmp NEAR L$102good_key + jmp NEAR L$116good_key align 16 -L$09514rounds: +L$11114rounds_alt: movups xmm2,[16+eax] lea edx,[16+edx] - cmp ebp,268435456 - je NEAR L$11014rounds_alt - mov ecx,13 - movups [edx-32],xmm0 - movups [edx-16],xmm2 -db 102,15,58,223,202,1 - call L$111key_256a_cold -db 102,15,58,223,200,1 - call L$112key_256b -db 102,15,58,223,202,2 - call L$113key_256a -db 102,15,58,223,200,2 - call L$112key_256b -db 102,15,58,223,202,4 - call L$113key_256a -db 102,15,58,223,200,4 - call L$112key_256b -db 102,15,58,223,202,8 - call L$113key_256a -db 102,15,58,223,200,8 - call L$112key_256b -db 102,15,58,223,202,16 - call L$113key_256a -db 102,15,58,223,200,16 - call L$112key_256b -db 102,15,58,223,202,32 - call L$113key_256a -db 102,15,58,223,200,32 - call L$112key_256b -db 102,15,58,223,202,64 - call L$113key_256a - movups [edx],xmm0 - mov DWORD [16+edx],ecx - xor eax,eax - jmp NEAR L$102good_key -align 16 -L$113key_256a: - movups [edx],xmm2 - lea edx,[16+edx] -L$111key_256a_cold: - shufps xmm4,xmm0,16 - xorps xmm0,xmm4 - shufps xmm4,xmm0,140 - xorps xmm0,xmm4 - shufps xmm1,xmm1,255 - xorps xmm0,xmm1 - ret -align 16 -L$112key_256b: - movups [edx],xmm0 - lea edx,[16+edx] - shufps xmm4,xmm2,16 - xorps xmm2,xmm4 - shufps xmm4,xmm2,140 - xorps xmm2,xmm4 - shufps xmm1,xmm1,170 - xorps xmm2,xmm1 - ret -align 16 -L$11014rounds_alt: movdqa xmm5,[ebx] movdqa xmm4,[32+ebx] mov ecx,7 movdqu [edx-32],xmm0 movdqa xmm1,xmm2 movdqu [edx-16],xmm2 -L$114loop_key256: +L$118loop_key256: db 102,15,56,0,213 db 102,15,56,221,212 movdqa xmm3,xmm0 @@ -2346,7 +2400,7 @@ db 102,15,56,221,212 pxor xmm0,xmm2 movdqu [edx],xmm0 dec ecx - jz NEAR L$115done_key256 + jz NEAR L$119done_key256 pshufd xmm2,xmm0,255 pxor xmm3,xmm3 db 102,15,56,221,211 @@ -2361,11 +2415,11 @@ db 102,15,56,221,211 movdqu [16+edx],xmm2 lea edx,[32+edx] movdqa xmm1,xmm2 - jmp NEAR L$114loop_key256 -L$115done_key256: + jmp NEAR L$118loop_key256 +L$119done_key256: mov ecx,13 mov DWORD [16+edx],ecx -L$102good_key: +L$116good_key: pxor xmm0,xmm0 pxor xmm1,xmm1 pxor xmm2,xmm2 @@ -2374,54 +2428,20 @@ L$102good_key: pxor xmm5,xmm5 xor eax,eax pop ebx - pop ebp ret align 4 -L$093bad_pointer: - mov eax,-1 - pop ebx - pop ebp - ret -align 4 -L$097bad_keybits: +L$113bad_keybits: pxor xmm0,xmm0 mov eax,-2 pop ebx - pop ebp ret -global _aes_hw_set_encrypt_key +global _aes_hw_encrypt_key_to_decrypt_key align 16 -_aes_hw_set_encrypt_key: -L$_aes_hw_set_encrypt_key_begin: -%ifdef BORINGSSL_DISPATCH_TEST - push ebx - push edx - call L$116pic -L$116pic: - pop ebx - lea ebx,[(_BORINGSSL_function_hit+3-L$116pic)+ebx] - mov edx,1 - mov BYTE [ebx],dl - pop edx - pop ebx -%endif - mov eax,DWORD [4+esp] - mov ecx,DWORD [8+esp] - mov edx,DWORD [12+esp] - call __aesni_set_encrypt_key - ret -global _aes_hw_set_decrypt_key -align 16 -_aes_hw_set_decrypt_key: -L$_aes_hw_set_decrypt_key_begin: - mov eax,DWORD [4+esp] - mov ecx,DWORD [8+esp] - mov edx,DWORD [12+esp] - call __aesni_set_encrypt_key - mov edx,DWORD [12+esp] +_aes_hw_encrypt_key_to_decrypt_key: +L$_aes_hw_encrypt_key_to_decrypt_key_begin: + mov edx,DWORD [4+esp] + mov ecx,DWORD [240+edx] shl ecx,4 - test eax,eax - jnz NEAR L$117dec_key_ret lea eax,[16+ecx*1+edx] movups xmm0,[edx] movups xmm1,[eax] @@ -2429,7 +2449,7 @@ L$_aes_hw_set_decrypt_key_begin: movups [edx],xmm1 lea edx,[16+edx] lea eax,[eax-16] -L$118dec_key_inverse: +L$120dec_key_inverse: movups xmm0,[edx] movups xmm1,[eax] db 102,15,56,219,192 @@ -2439,14 +2459,12 @@ db 102,15,56,219,201 movups [16+eax],xmm0 movups [edx-16],xmm1 cmp eax,edx - ja NEAR L$118dec_key_inverse + ja NEAR L$120dec_key_inverse movups xmm0,[edx] db 102,15,56,219,192 movups [edx],xmm0 pxor xmm0,xmm0 pxor xmm1,xmm1 - xor eax,eax -L$117dec_key_ret: ret align 64 L$key_const: @@ -2458,8 +2476,6 @@ db 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69 db 83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83 db 32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115 db 115,108,46,111,114,103,62,0 -segment .bss -common _OPENSSL_ia32cap_P 16 %else ; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738 ret diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-apple.S index f3505b9529..23c15c3d26 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-apple.S @@ -5,7 +5,6 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__APPLE__) .text - .globl _aes_hw_encrypt .private_extern _aes_hw_encrypt @@ -1905,76 +1904,63 @@ L$cbc_ret: ret -.globl _aes_hw_set_decrypt_key -.private_extern _aes_hw_set_decrypt_key +.globl _aes_hw_encrypt_key_to_decrypt_key +.private_extern _aes_hw_encrypt_key_to_decrypt_key .p2align 4 -_aes_hw_set_decrypt_key: +_aes_hw_encrypt_key_to_decrypt_key: _CET_ENDBR -.byte 0x48,0x83,0xEC,0x08 - call __aesni_set_encrypt_key + movl 240(%rdi),%esi shll $4,%esi - testl %eax,%eax - jnz L$dec_key_ret - leaq 16(%rdx,%rsi,1),%rdi - movups (%rdx),%xmm0 - movups (%rdi),%xmm1 - movups %xmm0,(%rdi) - movups %xmm1,(%rdx) - leaq 16(%rdx),%rdx - leaq -16(%rdi),%rdi + leaq 16(%rdi,%rsi,1),%rdx + + movups (%rdi),%xmm0 + movups (%rdx),%xmm1 + movups %xmm0,(%rdx) + movups %xmm1,(%rdi) + leaq 16(%rdi),%rdi + leaq -16(%rdx),%rdx L$dec_key_inverse: - movups (%rdx),%xmm0 - movups (%rdi),%xmm1 + movups (%rdi),%xmm0 + movups (%rdx),%xmm1 .byte 102,15,56,219,192 .byte 102,15,56,219,201 - leaq 16(%rdx),%rdx - leaq -16(%rdi),%rdi - movups %xmm0,16(%rdi) - movups %xmm1,-16(%rdx) - cmpq %rdx,%rdi + leaq 16(%rdi),%rdi + leaq -16(%rdx),%rdx + movups %xmm0,16(%rdx) + movups %xmm1,-16(%rdi) + cmpq %rdi,%rdx ja L$dec_key_inverse - movups (%rdx),%xmm0 + movups (%rdi),%xmm0 .byte 102,15,56,219,192 pxor %xmm1,%xmm1 - movups %xmm0,(%rdi) + movups %xmm0,(%rdx) pxor %xmm0,%xmm0 -L$dec_key_ret: - addq $8,%rsp - ret -L$SEH_end_set_decrypt_key: -.globl _aes_hw_set_encrypt_key -.private_extern _aes_hw_set_encrypt_key +.globl _aes_hw_set_encrypt_key_base +.private_extern _aes_hw_set_encrypt_key_base .p2align 4 -_aes_hw_set_encrypt_key: -__aesni_set_encrypt_key: +_aes_hw_set_encrypt_key_base: + _CET_ENDBR #ifdef BORINGSSL_DISPATCH_TEST movb $1,_BORINGSSL_function_hit+3(%rip) #endif -.byte 0x48,0x83,0xEC,0x08 + subq $8,%rsp + - movq $-1,%rax - testq %rdi,%rdi - jz L$enc_key_ret - testq %rdx,%rdx - jz L$enc_key_ret movups (%rdi),%xmm0 xorps %xmm4,%xmm4 - leaq _OPENSSL_ia32cap_P(%rip),%r10 - movl 4(%r10),%r10d - andl $268437504,%r10d leaq 16(%rdx),%rax cmpl $256,%esi je L$14rounds @@ -1985,8 +1971,6 @@ _CET_ENDBR L$10rounds: movl $9,%esi - cmpl $268435456,%r10d - je L$10rounds_alt movups %xmm0,(%rdx) .byte 102,15,58,223,200,1 @@ -2014,79 +1998,10 @@ L$10rounds: xorl %eax,%eax jmp L$enc_key_ret -.p2align 4 -L$10rounds_alt: - movdqa L$key_rotate(%rip),%xmm5 - movl $8,%r10d - movdqa L$key_rcon1(%rip),%xmm4 - movdqa %xmm0,%xmm2 - movdqu %xmm0,(%rdx) - jmp L$oop_key128 - -.p2align 4 -L$oop_key128: -.byte 102,15,56,0,197 -.byte 102,15,56,221,196 - pslld $1,%xmm4 - leaq 16(%rax),%rax - - movdqa %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,-16(%rax) - movdqa %xmm0,%xmm2 - - decl %r10d - jnz L$oop_key128 - - movdqa L$key_rcon1b(%rip),%xmm4 - -.byte 102,15,56,0,197 -.byte 102,15,56,221,196 - pslld $1,%xmm4 - - movdqa %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,(%rax) - - movdqa %xmm0,%xmm2 -.byte 102,15,56,0,197 -.byte 102,15,56,221,196 - - movdqa %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,16(%rax) - - movl %esi,96(%rax) - xorl %eax,%eax - jmp L$enc_key_ret - .p2align 4 L$12rounds: movq 16(%rdi),%xmm2 movl $11,%esi - cmpl $268435456,%r10d - je L$12rounds_alt movups %xmm0,(%rdx) .byte 102,15,58,223,202,1 @@ -2110,54 +2025,11 @@ L$12rounds: xorq %rax,%rax jmp L$enc_key_ret -.p2align 4 -L$12rounds_alt: - movdqa L$key_rotate192(%rip),%xmm5 - movdqa L$key_rcon1(%rip),%xmm4 - movl $8,%r10d - movdqu %xmm0,(%rdx) - jmp L$oop_key192 - -.p2align 4 -L$oop_key192: - movq %xmm2,0(%rax) - movdqa %xmm2,%xmm1 -.byte 102,15,56,0,213 -.byte 102,15,56,221,212 - pslld $1,%xmm4 - leaq 24(%rax),%rax - - movdqa %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm3,%xmm0 - - pshufd $0xff,%xmm0,%xmm3 - pxor %xmm1,%xmm3 - pslldq $4,%xmm1 - pxor %xmm1,%xmm3 - - pxor %xmm2,%xmm0 - pxor %xmm3,%xmm2 - movdqu %xmm0,-16(%rax) - - decl %r10d - jnz L$oop_key192 - - movl %esi,32(%rax) - xorl %eax,%eax - jmp L$enc_key_ret - .p2align 4 L$14rounds: movups 16(%rdi),%xmm2 movl $13,%esi leaq 16(%rax),%rax - cmpl $268435456,%r10d - je L$14rounds_alt movups %xmm0,(%rdx) movups %xmm2,16(%rdx) @@ -2192,60 +2064,6 @@ L$14rounds: xorq %rax,%rax jmp L$enc_key_ret -.p2align 4 -L$14rounds_alt: - movdqa L$key_rotate(%rip),%xmm5 - movdqa L$key_rcon1(%rip),%xmm4 - movl $7,%r10d - movdqu %xmm0,0(%rdx) - movdqa %xmm2,%xmm1 - movdqu %xmm2,16(%rdx) - jmp L$oop_key256 - -.p2align 4 -L$oop_key256: -.byte 102,15,56,0,213 -.byte 102,15,56,221,212 - - movdqa %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm3,%xmm0 - pslld $1,%xmm4 - - pxor %xmm2,%xmm0 - movdqu %xmm0,(%rax) - - decl %r10d - jz L$done_key256 - - pshufd $0xff,%xmm0,%xmm2 - pxor %xmm3,%xmm3 -.byte 102,15,56,221,211 - - movdqa %xmm1,%xmm3 - pslldq $4,%xmm1 - pxor %xmm1,%xmm3 - pslldq $4,%xmm1 - pxor %xmm1,%xmm3 - pslldq $4,%xmm1 - pxor %xmm3,%xmm1 - - pxor %xmm1,%xmm2 - movdqu %xmm2,16(%rax) - leaq 32(%rax),%rax - movdqa %xmm2,%xmm1 - - jmp L$oop_key256 - -L$done_key256: - movl %esi,16(%rax) - xorl %eax,%eax - jmp L$enc_key_ret - .p2align 4 L$bad_keybits: movq $-2,%rax @@ -2260,7 +2078,7 @@ L$enc_key_ret: ret -L$SEH_end_set_encrypt_key: + .p2align 4 L$key_expansion_128: @@ -2332,6 +2150,213 @@ L$key_expansion_256b: ret +.globl _aes_hw_set_encrypt_key_alt +.private_extern _aes_hw_set_encrypt_key_alt + +.p2align 4 +_aes_hw_set_encrypt_key_alt: + + +_CET_ENDBR +#ifdef BORINGSSL_DISPATCH_TEST + movb $1,_BORINGSSL_function_hit+3(%rip) +#endif + subq $8,%rsp + + + + movups (%rdi),%xmm0 + xorps %xmm4,%xmm4 + leaq 16(%rdx),%rax + cmpl $256,%esi + je L$14rounds_alt + cmpl $192,%esi + je L$12rounds_alt + cmpl $128,%esi + jne L$bad_keybits_alt + + movl $9,%esi + movdqa L$key_rotate(%rip),%xmm5 + movl $8,%r10d + movdqa L$key_rcon1(%rip),%xmm4 + movdqa %xmm0,%xmm2 + movdqu %xmm0,(%rdx) + jmp L$oop_key128 + +.p2align 4 +L$oop_key128: +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + leaq 16(%rax),%rax + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,-16(%rax) + movdqa %xmm0,%xmm2 + + decl %r10d + jnz L$oop_key128 + + movdqa L$key_rcon1b(%rip),%xmm4 + +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + movdqa %xmm0,%xmm2 +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,16(%rax) + + movl %esi,96(%rax) + xorl %eax,%eax + jmp L$enc_key_ret_alt + +.p2align 4 +L$12rounds_alt: + movq 16(%rdi),%xmm2 + movl $11,%esi + movdqa L$key_rotate192(%rip),%xmm5 + movdqa L$key_rcon1(%rip),%xmm4 + movl $8,%r10d + movdqu %xmm0,(%rdx) + jmp L$oop_key192 + +.p2align 4 +L$oop_key192: + movq %xmm2,0(%rax) + movdqa %xmm2,%xmm1 +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + pslld $1,%xmm4 + leaq 24(%rax),%rax + + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + + pshufd $0xff,%xmm0,%xmm3 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + + pxor %xmm2,%xmm0 + pxor %xmm3,%xmm2 + movdqu %xmm0,-16(%rax) + + decl %r10d + jnz L$oop_key192 + + movl %esi,32(%rax) + xorl %eax,%eax + jmp L$enc_key_ret_alt + +.p2align 4 +L$14rounds_alt: + movups 16(%rdi),%xmm2 + movl $13,%esi + leaq 16(%rax),%rax + movdqa L$key_rotate(%rip),%xmm5 + movdqa L$key_rcon1(%rip),%xmm4 + movl $7,%r10d + movdqu %xmm0,0(%rdx) + movdqa %xmm2,%xmm1 + movdqu %xmm2,16(%rdx) + jmp L$oop_key256 + +.p2align 4 +L$oop_key256: +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + pslld $1,%xmm4 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + decl %r10d + jz L$done_key256 + + pshufd $0xff,%xmm0,%xmm2 + pxor %xmm3,%xmm3 +.byte 102,15,56,221,211 + + movdqa %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm3,%xmm1 + + pxor %xmm1,%xmm2 + movdqu %xmm2,16(%rax) + leaq 32(%rax),%rax + movdqa %xmm2,%xmm1 + + jmp L$oop_key256 + +L$done_key256: + movl %esi,16(%rax) + xorl %eax,%eax + jmp L$enc_key_ret_alt + +.p2align 4 +L$bad_keybits_alt: + movq $-2,%rax +L$enc_key_ret_alt: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + addq $8,%rsp + + ret + + + .section __DATA,__const .p2align 6 L$bswap_mask: diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-linux.S index 68742fbb2c..cd695b4255 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-linux.S @@ -5,8 +5,6 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__ELF__) .text -.extern OPENSSL_ia32cap_P -.hidden OPENSSL_ia32cap_P .globl aes_hw_encrypt .hidden aes_hw_encrypt .type aes_hw_encrypt,@function @@ -1907,76 +1905,63 @@ _CET_ENDBR ret .cfi_endproc .size aes_hw_cbc_encrypt,.-aes_hw_cbc_encrypt -.globl aes_hw_set_decrypt_key -.hidden aes_hw_set_decrypt_key -.type aes_hw_set_decrypt_key,@function +.globl aes_hw_encrypt_key_to_decrypt_key +.hidden aes_hw_encrypt_key_to_decrypt_key +.type aes_hw_encrypt_key_to_decrypt_key,@function .align 16 -aes_hw_set_decrypt_key: +aes_hw_encrypt_key_to_decrypt_key: .cfi_startproc _CET_ENDBR -.byte 0x48,0x83,0xEC,0x08 -.cfi_adjust_cfa_offset 8 - call __aesni_set_encrypt_key - shll $4,%esi - testl %eax,%eax - jnz .Ldec_key_ret - leaq 16(%rdx,%rsi,1),%rdi - movups (%rdx),%xmm0 - movups (%rdi),%xmm1 - movups %xmm0,(%rdi) - movups %xmm1,(%rdx) - leaq 16(%rdx),%rdx - leaq -16(%rdi),%rdi + movl 240(%rdi),%esi + shll $4,%esi + + leaq 16(%rdi,%rsi,1),%rdx + + movups (%rdi),%xmm0 + movups (%rdx),%xmm1 + movups %xmm0,(%rdx) + movups %xmm1,(%rdi) + leaq 16(%rdi),%rdi + leaq -16(%rdx),%rdx .Ldec_key_inverse: - movups (%rdx),%xmm0 - movups (%rdi),%xmm1 + movups (%rdi),%xmm0 + movups (%rdx),%xmm1 .byte 102,15,56,219,192 .byte 102,15,56,219,201 - leaq 16(%rdx),%rdx - leaq -16(%rdi),%rdi - movups %xmm0,16(%rdi) - movups %xmm1,-16(%rdx) - cmpq %rdx,%rdi + leaq 16(%rdi),%rdi + leaq -16(%rdx),%rdx + movups %xmm0,16(%rdx) + movups %xmm1,-16(%rdi) + cmpq %rdi,%rdx ja .Ldec_key_inverse - movups (%rdx),%xmm0 + movups (%rdi),%xmm0 .byte 102,15,56,219,192 pxor %xmm1,%xmm1 - movups %xmm0,(%rdi) + movups %xmm0,(%rdx) pxor %xmm0,%xmm0 -.Ldec_key_ret: - addq $8,%rsp -.cfi_adjust_cfa_offset -8 ret .cfi_endproc -.LSEH_end_set_decrypt_key: -.size aes_hw_set_decrypt_key,.-aes_hw_set_decrypt_key -.globl aes_hw_set_encrypt_key -.hidden aes_hw_set_encrypt_key -.type aes_hw_set_encrypt_key,@function +.size aes_hw_encrypt_key_to_decrypt_key,.-aes_hw_encrypt_key_to_decrypt_key +.globl aes_hw_set_encrypt_key_base +.hidden aes_hw_set_encrypt_key_base +.type aes_hw_set_encrypt_key_base,@function .align 16 -aes_hw_set_encrypt_key: -__aesni_set_encrypt_key: +aes_hw_set_encrypt_key_base: .cfi_startproc + _CET_ENDBR #ifdef BORINGSSL_DISPATCH_TEST movb $1,BORINGSSL_function_hit+3(%rip) #endif -.byte 0x48,0x83,0xEC,0x08 + subq $8,%rsp .cfi_adjust_cfa_offset 8 - movq $-1,%rax - testq %rdi,%rdi - jz .Lenc_key_ret - testq %rdx,%rdx - jz .Lenc_key_ret + movups (%rdi),%xmm0 xorps %xmm4,%xmm4 - leaq OPENSSL_ia32cap_P(%rip),%r10 - movl 4(%r10),%r10d - andl $268437504,%r10d leaq 16(%rdx),%rax cmpl $256,%esi je .L14rounds @@ -1987,8 +1972,6 @@ _CET_ENDBR .L10rounds: movl $9,%esi - cmpl $268435456,%r10d - je .L10rounds_alt movups %xmm0,(%rdx) .byte 102,15,58,223,200,1 @@ -2016,79 +1999,10 @@ _CET_ENDBR xorl %eax,%eax jmp .Lenc_key_ret -.align 16 -.L10rounds_alt: - movdqa .Lkey_rotate(%rip),%xmm5 - movl $8,%r10d - movdqa .Lkey_rcon1(%rip),%xmm4 - movdqa %xmm0,%xmm2 - movdqu %xmm0,(%rdx) - jmp .Loop_key128 - -.align 16 -.Loop_key128: -.byte 102,15,56,0,197 -.byte 102,15,56,221,196 - pslld $1,%xmm4 - leaq 16(%rax),%rax - - movdqa %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,-16(%rax) - movdqa %xmm0,%xmm2 - - decl %r10d - jnz .Loop_key128 - - movdqa .Lkey_rcon1b(%rip),%xmm4 - -.byte 102,15,56,0,197 -.byte 102,15,56,221,196 - pslld $1,%xmm4 - - movdqa %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,(%rax) - - movdqa %xmm0,%xmm2 -.byte 102,15,56,0,197 -.byte 102,15,56,221,196 - - movdqa %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm2,%xmm3 - pslldq $4,%xmm2 - pxor %xmm3,%xmm2 - - pxor %xmm2,%xmm0 - movdqu %xmm0,16(%rax) - - movl %esi,96(%rax) - xorl %eax,%eax - jmp .Lenc_key_ret - .align 16 .L12rounds: movq 16(%rdi),%xmm2 movl $11,%esi - cmpl $268435456,%r10d - je .L12rounds_alt movups %xmm0,(%rdx) .byte 102,15,58,223,202,1 @@ -2112,54 +2026,11 @@ _CET_ENDBR xorq %rax,%rax jmp .Lenc_key_ret -.align 16 -.L12rounds_alt: - movdqa .Lkey_rotate192(%rip),%xmm5 - movdqa .Lkey_rcon1(%rip),%xmm4 - movl $8,%r10d - movdqu %xmm0,(%rdx) - jmp .Loop_key192 - -.align 16 -.Loop_key192: - movq %xmm2,0(%rax) - movdqa %xmm2,%xmm1 -.byte 102,15,56,0,213 -.byte 102,15,56,221,212 - pslld $1,%xmm4 - leaq 24(%rax),%rax - - movdqa %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm3,%xmm0 - - pshufd $0xff,%xmm0,%xmm3 - pxor %xmm1,%xmm3 - pslldq $4,%xmm1 - pxor %xmm1,%xmm3 - - pxor %xmm2,%xmm0 - pxor %xmm3,%xmm2 - movdqu %xmm0,-16(%rax) - - decl %r10d - jnz .Loop_key192 - - movl %esi,32(%rax) - xorl %eax,%eax - jmp .Lenc_key_ret - .align 16 .L14rounds: movups 16(%rdi),%xmm2 movl $13,%esi leaq 16(%rax),%rax - cmpl $268435456,%r10d - je .L14rounds_alt movups %xmm0,(%rdx) movups %xmm2,16(%rdx) @@ -2194,60 +2065,6 @@ _CET_ENDBR xorq %rax,%rax jmp .Lenc_key_ret -.align 16 -.L14rounds_alt: - movdqa .Lkey_rotate(%rip),%xmm5 - movdqa .Lkey_rcon1(%rip),%xmm4 - movl $7,%r10d - movdqu %xmm0,0(%rdx) - movdqa %xmm2,%xmm1 - movdqu %xmm2,16(%rdx) - jmp .Loop_key256 - -.align 16 -.Loop_key256: -.byte 102,15,56,0,213 -.byte 102,15,56,221,212 - - movdqa %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm0,%xmm3 - pslldq $4,%xmm0 - pxor %xmm3,%xmm0 - pslld $1,%xmm4 - - pxor %xmm2,%xmm0 - movdqu %xmm0,(%rax) - - decl %r10d - jz .Ldone_key256 - - pshufd $0xff,%xmm0,%xmm2 - pxor %xmm3,%xmm3 -.byte 102,15,56,221,211 - - movdqa %xmm1,%xmm3 - pslldq $4,%xmm1 - pxor %xmm1,%xmm3 - pslldq $4,%xmm1 - pxor %xmm1,%xmm3 - pslldq $4,%xmm1 - pxor %xmm3,%xmm1 - - pxor %xmm1,%xmm2 - movdqu %xmm2,16(%rax) - leaq 32(%rax),%rax - movdqa %xmm2,%xmm1 - - jmp .Loop_key256 - -.Ldone_key256: - movl %esi,16(%rax) - xorl %eax,%eax - jmp .Lenc_key_ret - .align 16 .Lbad_keybits: movq $-2,%rax @@ -2262,7 +2079,7 @@ _CET_ENDBR .cfi_adjust_cfa_offset -8 ret .cfi_endproc -.LSEH_end_set_encrypt_key: + .align 16 .Lkey_expansion_128: @@ -2332,8 +2149,215 @@ _CET_ENDBR shufps $170,%xmm1,%xmm1 xorps %xmm1,%xmm2 ret -.size aes_hw_set_encrypt_key,.-aes_hw_set_encrypt_key -.size __aesni_set_encrypt_key,.-__aesni_set_encrypt_key +.size aes_hw_set_encrypt_key_base,.-aes_hw_set_encrypt_key_base + +.globl aes_hw_set_encrypt_key_alt +.hidden aes_hw_set_encrypt_key_alt +.type aes_hw_set_encrypt_key_alt,@function +.align 16 +aes_hw_set_encrypt_key_alt: +.cfi_startproc + +_CET_ENDBR +#ifdef BORINGSSL_DISPATCH_TEST + movb $1,BORINGSSL_function_hit+3(%rip) +#endif + subq $8,%rsp +.cfi_adjust_cfa_offset 8 + + + movups (%rdi),%xmm0 + xorps %xmm4,%xmm4 + leaq 16(%rdx),%rax + cmpl $256,%esi + je .L14rounds_alt + cmpl $192,%esi + je .L12rounds_alt + cmpl $128,%esi + jne .Lbad_keybits_alt + + movl $9,%esi + movdqa .Lkey_rotate(%rip),%xmm5 + movl $8,%r10d + movdqa .Lkey_rcon1(%rip),%xmm4 + movdqa %xmm0,%xmm2 + movdqu %xmm0,(%rdx) + jmp .Loop_key128 + +.align 16 +.Loop_key128: +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + leaq 16(%rax),%rax + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,-16(%rax) + movdqa %xmm0,%xmm2 + + decl %r10d + jnz .Loop_key128 + + movdqa .Lkey_rcon1b(%rip),%xmm4 + +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + pslld $1,%xmm4 + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + movdqa %xmm0,%xmm2 +.byte 102,15,56,0,197 +.byte 102,15,56,221,196 + + movdqa %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm2,%xmm3 + pslldq $4,%xmm2 + pxor %xmm3,%xmm2 + + pxor %xmm2,%xmm0 + movdqu %xmm0,16(%rax) + + movl %esi,96(%rax) + xorl %eax,%eax + jmp .Lenc_key_ret_alt + +.align 16 +.L12rounds_alt: + movq 16(%rdi),%xmm2 + movl $11,%esi + movdqa .Lkey_rotate192(%rip),%xmm5 + movdqa .Lkey_rcon1(%rip),%xmm4 + movl $8,%r10d + movdqu %xmm0,(%rdx) + jmp .Loop_key192 + +.align 16 +.Loop_key192: + movq %xmm2,0(%rax) + movdqa %xmm2,%xmm1 +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + pslld $1,%xmm4 + leaq 24(%rax),%rax + + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + + pshufd $0xff,%xmm0,%xmm3 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + + pxor %xmm2,%xmm0 + pxor %xmm3,%xmm2 + movdqu %xmm0,-16(%rax) + + decl %r10d + jnz .Loop_key192 + + movl %esi,32(%rax) + xorl %eax,%eax + jmp .Lenc_key_ret_alt + +.align 16 +.L14rounds_alt: + movups 16(%rdi),%xmm2 + movl $13,%esi + leaq 16(%rax),%rax + movdqa .Lkey_rotate(%rip),%xmm5 + movdqa .Lkey_rcon1(%rip),%xmm4 + movl $7,%r10d + movdqu %xmm0,0(%rdx) + movdqa %xmm2,%xmm1 + movdqu %xmm2,16(%rdx) + jmp .Loop_key256 + +.align 16 +.Loop_key256: +.byte 102,15,56,0,213 +.byte 102,15,56,221,212 + + movdqa %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm0,%xmm3 + pslldq $4,%xmm0 + pxor %xmm3,%xmm0 + pslld $1,%xmm4 + + pxor %xmm2,%xmm0 + movdqu %xmm0,(%rax) + + decl %r10d + jz .Ldone_key256 + + pshufd $0xff,%xmm0,%xmm2 + pxor %xmm3,%xmm3 +.byte 102,15,56,221,211 + + movdqa %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm1,%xmm3 + pslldq $4,%xmm1 + pxor %xmm3,%xmm1 + + pxor %xmm1,%xmm2 + movdqu %xmm2,16(%rax) + leaq 32(%rax),%rax + movdqa %xmm2,%xmm1 + + jmp .Loop_key256 + +.Ldone_key256: + movl %esi,16(%rax) + xorl %eax,%eax + jmp .Lenc_key_ret_alt + +.align 16 +.Lbad_keybits_alt: + movq $-2,%rax +.Lenc_key_ret_alt: + pxor %xmm0,%xmm0 + pxor %xmm1,%xmm1 + pxor %xmm2,%xmm2 + pxor %xmm3,%xmm3 + pxor %xmm4,%xmm4 + pxor %xmm5,%xmm5 + addq $8,%rsp +.cfi_adjust_cfa_offset -8 + ret +.cfi_endproc + +.size aes_hw_set_encrypt_key_alt,.-aes_hw_set_encrypt_key_alt .section .rodata .align 64 .Lbswap_mask: diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-win.asm index 6c5d9ad23c..4876ed79e5 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesni-x86_64-win.asm @@ -13,7 +13,6 @@ default rel %endif section .text code align=64 -EXTERN OPENSSL_ia32cap_P global aes_hw_encrypt ALIGN 16 @@ -2012,74 +2011,61 @@ $L$cbc_ret: ret $L$SEH_end_aes_hw_cbc_encrypt: -global aes_hw_set_decrypt_key +global aes_hw_encrypt_key_to_decrypt_key ALIGN 16 -aes_hw_set_decrypt_key: +aes_hw_encrypt_key_to_decrypt_key: _CET_ENDBR - DB 0x48,0x83,0xEC,0x08 - call __aesni_set_encrypt_key + mov edx,DWORD[240+rcx] shl edx,4 - test eax,eax - jnz NEAR $L$dec_key_ret - lea rcx,[16+rdx*1+r8] - movups xmm0,XMMWORD[r8] - movups xmm1,XMMWORD[rcx] - movups XMMWORD[rcx],xmm0 - movups XMMWORD[r8],xmm1 - lea r8,[16+r8] - lea rcx,[((-16))+rcx] + lea r8,[16+rdx*1+rcx] + + movups xmm0,XMMWORD[rcx] + movups xmm1,XMMWORD[r8] + movups XMMWORD[r8],xmm0 + movups XMMWORD[rcx],xmm1 + lea rcx,[16+rcx] + lea r8,[((-16))+r8] $L$dec_key_inverse: - movups xmm0,XMMWORD[r8] - movups xmm1,XMMWORD[rcx] + movups xmm0,XMMWORD[rcx] + movups xmm1,XMMWORD[r8] DB 102,15,56,219,192 DB 102,15,56,219,201 - lea r8,[16+r8] - lea rcx,[((-16))+rcx] - movups XMMWORD[16+rcx],xmm0 - movups XMMWORD[(-16)+r8],xmm1 - cmp rcx,r8 + lea rcx,[16+rcx] + lea r8,[((-16))+r8] + movups XMMWORD[16+r8],xmm0 + movups XMMWORD[(-16)+rcx],xmm1 + cmp r8,rcx ja NEAR $L$dec_key_inverse - movups xmm0,XMMWORD[r8] + movups xmm0,XMMWORD[rcx] DB 102,15,56,219,192 pxor xmm1,xmm1 - movups XMMWORD[rcx],xmm0 + movups XMMWORD[r8],xmm0 pxor xmm0,xmm0 -$L$dec_key_ret: - add rsp,8 - ret -$L$SEH_end_set_decrypt_key: -global aes_hw_set_encrypt_key +global aes_hw_set_encrypt_key_base ALIGN 16 -aes_hw_set_encrypt_key: -__aesni_set_encrypt_key: +aes_hw_set_encrypt_key_base: +$L$SEH_begin_aes_hw_set_encrypt_key_base_1: _CET_ENDBR %ifdef BORINGSSL_DISPATCH_TEST mov BYTE[((BORINGSSL_function_hit+3))],1 %endif - DB 0x48,0x83,0xEC,0x08 - - mov rax,-1 - test rcx,rcx - jz NEAR $L$enc_key_ret - test r8,r8 - jz NEAR $L$enc_key_ret + sub rsp,8 +$L$SEH_prologue_aes_hw_set_encrypt_key_base_2: +$L$SEH_endprologue_aes_hw_set_encrypt_key_base_3: movups xmm0,XMMWORD[rcx] xorps xmm4,xmm4 - lea r10,[OPENSSL_ia32cap_P] - mov r10d,DWORD[4+r10] - and r10d,268437504 lea rax,[16+r8] cmp edx,256 je NEAR $L$14rounds @@ -2090,8 +2076,6 @@ _CET_ENDBR $L$10rounds: mov edx,9 - cmp r10d,268435456 - je NEAR $L$10rounds_alt movups XMMWORD[r8],xmm0 DB 102,15,58,223,200,1 @@ -2119,79 +2103,10 @@ $L$10rounds: xor eax,eax jmp NEAR $L$enc_key_ret -ALIGN 16 -$L$10rounds_alt: - movdqa xmm5,XMMWORD[$L$key_rotate] - mov r10d,8 - movdqa xmm4,XMMWORD[$L$key_rcon1] - movdqa xmm2,xmm0 - movdqu XMMWORD[r8],xmm0 - jmp NEAR $L$oop_key128 - -ALIGN 16 -$L$oop_key128: -DB 102,15,56,0,197 - DB 102,15,56,221,196 - pslld xmm4,1 - lea rax,[16+rax] - - movdqa xmm3,xmm2 - pslldq xmm2,4 - pxor xmm3,xmm2 - pslldq xmm2,4 - pxor xmm3,xmm2 - pslldq xmm2,4 - pxor xmm2,xmm3 - - pxor xmm0,xmm2 - movdqu XMMWORD[(-16)+rax],xmm0 - movdqa xmm2,xmm0 - - dec r10d - jnz NEAR $L$oop_key128 - - movdqa xmm4,XMMWORD[$L$key_rcon1b] - -DB 102,15,56,0,197 - DB 102,15,56,221,196 - pslld xmm4,1 - - movdqa xmm3,xmm2 - pslldq xmm2,4 - pxor xmm3,xmm2 - pslldq xmm2,4 - pxor xmm3,xmm2 - pslldq xmm2,4 - pxor xmm2,xmm3 - - pxor xmm0,xmm2 - movdqu XMMWORD[rax],xmm0 - - movdqa xmm2,xmm0 -DB 102,15,56,0,197 - DB 102,15,56,221,196 - - movdqa xmm3,xmm2 - pslldq xmm2,4 - pxor xmm3,xmm2 - pslldq xmm2,4 - pxor xmm3,xmm2 - pslldq xmm2,4 - pxor xmm2,xmm3 - - pxor xmm0,xmm2 - movdqu XMMWORD[16+rax],xmm0 - - mov DWORD[96+rax],edx - xor eax,eax - jmp NEAR $L$enc_key_ret - ALIGN 16 $L$12rounds: movq xmm2,QWORD[16+rcx] mov edx,11 - cmp r10d,268435456 - je NEAR $L$12rounds_alt movups XMMWORD[r8],xmm0 DB 102,15,58,223,202,1 @@ -2215,54 +2130,11 @@ $L$12rounds: xor rax,rax jmp NEAR $L$enc_key_ret -ALIGN 16 -$L$12rounds_alt: - movdqa xmm5,XMMWORD[$L$key_rotate192] - movdqa xmm4,XMMWORD[$L$key_rcon1] - mov r10d,8 - movdqu XMMWORD[r8],xmm0 - jmp NEAR $L$oop_key192 - -ALIGN 16 -$L$oop_key192: - movq QWORD[rax],xmm2 - movdqa xmm1,xmm2 -DB 102,15,56,0,213 - DB 102,15,56,221,212 - pslld xmm4,1 - lea rax,[24+rax] - - movdqa xmm3,xmm0 - pslldq xmm0,4 - pxor xmm3,xmm0 - pslldq xmm0,4 - pxor xmm3,xmm0 - pslldq xmm0,4 - pxor xmm0,xmm3 - - pshufd xmm3,xmm0,0xff - pxor xmm3,xmm1 - pslldq xmm1,4 - pxor xmm3,xmm1 - - pxor xmm0,xmm2 - pxor xmm2,xmm3 - movdqu XMMWORD[(-16)+rax],xmm0 - - dec r10d - jnz NEAR $L$oop_key192 - - mov DWORD[32+rax],edx - xor eax,eax - jmp NEAR $L$enc_key_ret - ALIGN 16 $L$14rounds: movups xmm2,XMMWORD[16+rcx] mov edx,13 lea rax,[16+rax] - cmp r10d,268435456 - je NEAR $L$14rounds_alt movups XMMWORD[r8],xmm0 movups XMMWORD[16+r8],xmm2 @@ -2297,60 +2169,6 @@ $L$14rounds: xor rax,rax jmp NEAR $L$enc_key_ret -ALIGN 16 -$L$14rounds_alt: - movdqa xmm5,XMMWORD[$L$key_rotate] - movdqa xmm4,XMMWORD[$L$key_rcon1] - mov r10d,7 - movdqu XMMWORD[r8],xmm0 - movdqa xmm1,xmm2 - movdqu XMMWORD[16+r8],xmm2 - jmp NEAR $L$oop_key256 - -ALIGN 16 -$L$oop_key256: -DB 102,15,56,0,213 - DB 102,15,56,221,212 - - movdqa xmm3,xmm0 - pslldq xmm0,4 - pxor xmm3,xmm0 - pslldq xmm0,4 - pxor xmm3,xmm0 - pslldq xmm0,4 - pxor xmm0,xmm3 - pslld xmm4,1 - - pxor xmm0,xmm2 - movdqu XMMWORD[rax],xmm0 - - dec r10d - jz NEAR $L$done_key256 - - pshufd xmm2,xmm0,0xff - pxor xmm3,xmm3 - DB 102,15,56,221,211 - - movdqa xmm3,xmm1 - pslldq xmm1,4 - pxor xmm3,xmm1 - pslldq xmm1,4 - pxor xmm3,xmm1 - pslldq xmm1,4 - pxor xmm1,xmm3 - - pxor xmm2,xmm1 - movdqu XMMWORD[16+rax],xmm2 - lea rax,[32+rax] - movdqa xmm1,xmm2 - - jmp NEAR $L$oop_key256 - -$L$done_key256: - mov DWORD[16+rax],edx - xor eax,eax - jmp NEAR $L$enc_key_ret - ALIGN 16 $L$bad_keybits: mov rax,-2 @@ -2365,7 +2183,7 @@ $L$enc_key_ret: ret -$L$SEH_end_set_encrypt_key: +$L$SEH_end_aes_hw_set_encrypt_key_base_4: ALIGN 16 $L$key_expansion_128: @@ -2437,6 +2255,212 @@ $L$key_expansion_256b: ret +global aes_hw_set_encrypt_key_alt + +ALIGN 16 +aes_hw_set_encrypt_key_alt: + +$L$SEH_begin_aes_hw_set_encrypt_key_alt_1: +_CET_ENDBR +%ifdef BORINGSSL_DISPATCH_TEST + mov BYTE[((BORINGSSL_function_hit+3))],1 +%endif + sub rsp,8 + +$L$SEH_prologue_aes_hw_set_encrypt_key_alt_2: +$L$SEH_endprologue_aes_hw_set_encrypt_key_alt_3: + movups xmm0,XMMWORD[rcx] + xorps xmm4,xmm4 + lea rax,[16+r8] + cmp edx,256 + je NEAR $L$14rounds_alt + cmp edx,192 + je NEAR $L$12rounds_alt + cmp edx,128 + jne NEAR $L$bad_keybits_alt + + mov edx,9 + movdqa xmm5,XMMWORD[$L$key_rotate] + mov r10d,8 + movdqa xmm4,XMMWORD[$L$key_rcon1] + movdqa xmm2,xmm0 + movdqu XMMWORD[r8],xmm0 + jmp NEAR $L$oop_key128 + +ALIGN 16 +$L$oop_key128: +DB 102,15,56,0,197 + DB 102,15,56,221,196 + pslld xmm4,1 + lea rax,[16+rax] + + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + + pxor xmm0,xmm2 + movdqu XMMWORD[(-16)+rax],xmm0 + movdqa xmm2,xmm0 + + dec r10d + jnz NEAR $L$oop_key128 + + movdqa xmm4,XMMWORD[$L$key_rcon1b] + +DB 102,15,56,0,197 + DB 102,15,56,221,196 + pslld xmm4,1 + + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + + pxor xmm0,xmm2 + movdqu XMMWORD[rax],xmm0 + + movdqa xmm2,xmm0 +DB 102,15,56,0,197 + DB 102,15,56,221,196 + + movdqa xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm3,xmm2 + pslldq xmm2,4 + pxor xmm2,xmm3 + + pxor xmm0,xmm2 + movdqu XMMWORD[16+rax],xmm0 + + mov DWORD[96+rax],edx + xor eax,eax + jmp NEAR $L$enc_key_ret_alt + +ALIGN 16 +$L$12rounds_alt: + movq xmm2,QWORD[16+rcx] + mov edx,11 + movdqa xmm5,XMMWORD[$L$key_rotate192] + movdqa xmm4,XMMWORD[$L$key_rcon1] + mov r10d,8 + movdqu XMMWORD[r8],xmm0 + jmp NEAR $L$oop_key192 + +ALIGN 16 +$L$oop_key192: + movq QWORD[rax],xmm2 + movdqa xmm1,xmm2 +DB 102,15,56,0,213 + DB 102,15,56,221,212 + pslld xmm4,1 + lea rax,[24+rax] + + movdqa xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm0,xmm3 + + pshufd xmm3,xmm0,0xff + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + + pxor xmm0,xmm2 + pxor xmm2,xmm3 + movdqu XMMWORD[(-16)+rax],xmm0 + + dec r10d + jnz NEAR $L$oop_key192 + + mov DWORD[32+rax],edx + xor eax,eax + jmp NEAR $L$enc_key_ret_alt + +ALIGN 16 +$L$14rounds_alt: + movups xmm2,XMMWORD[16+rcx] + mov edx,13 + lea rax,[16+rax] + movdqa xmm5,XMMWORD[$L$key_rotate] + movdqa xmm4,XMMWORD[$L$key_rcon1] + mov r10d,7 + movdqu XMMWORD[r8],xmm0 + movdqa xmm1,xmm2 + movdqu XMMWORD[16+r8],xmm2 + jmp NEAR $L$oop_key256 + +ALIGN 16 +$L$oop_key256: +DB 102,15,56,0,213 + DB 102,15,56,221,212 + + movdqa xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm3,xmm0 + pslldq xmm0,4 + pxor xmm0,xmm3 + pslld xmm4,1 + + pxor xmm0,xmm2 + movdqu XMMWORD[rax],xmm0 + + dec r10d + jz NEAR $L$done_key256 + + pshufd xmm2,xmm0,0xff + pxor xmm3,xmm3 + DB 102,15,56,221,211 + + movdqa xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm3,xmm1 + pslldq xmm1,4 + pxor xmm1,xmm3 + + pxor xmm2,xmm1 + movdqu XMMWORD[16+rax],xmm2 + lea rax,[32+rax] + movdqa xmm1,xmm2 + + jmp NEAR $L$oop_key256 + +$L$done_key256: + mov DWORD[16+rax],edx + xor eax,eax + jmp NEAR $L$enc_key_ret_alt + +ALIGN 16 +$L$bad_keybits_alt: + mov rax,-2 +$L$enc_key_ret_alt: + pxor xmm0,xmm0 + pxor xmm1,xmm1 + pxor xmm2,xmm2 + pxor xmm3,xmm3 + pxor xmm4,xmm4 + pxor xmm5,xmm5 + add rsp,8 + + ret + +$L$SEH_end_aes_hw_set_encrypt_key_alt_4: + section .rdata rdata align=8 ALIGN 64 $L$bswap_mask: @@ -2646,14 +2670,6 @@ ALIGN 4 DD $L$SEH_begin_aes_hw_cbc_encrypt wrt ..imagebase DD $L$SEH_end_aes_hw_cbc_encrypt wrt ..imagebase DD $L$SEH_info_cbc wrt ..imagebase - - DD aes_hw_set_decrypt_key wrt ..imagebase - DD $L$SEH_end_set_decrypt_key wrt ..imagebase - DD $L$SEH_info_key wrt ..imagebase - - DD aes_hw_set_encrypt_key wrt ..imagebase - DD $L$SEH_end_set_encrypt_key wrt ..imagebase - DD $L$SEH_info_key wrt ..imagebase section .xdata rdata align=8 ALIGN 8 $L$SEH_info_ecb: @@ -2667,9 +2683,37 @@ $L$SEH_info_ctr32: $L$SEH_info_cbc: DB 9,0,0,0 DD cbc_se_handler wrt ..imagebase -$L$SEH_info_key: - DB 0x01,0x04,0x01,0x00 - DB 0x04,0x02,0x00,0x00 +section .pdata +ALIGN 4 + DD $L$SEH_begin_aes_hw_set_encrypt_key_base_1 wrt ..imagebase + DD $L$SEH_end_aes_hw_set_encrypt_key_base_4 wrt ..imagebase + DD $L$SEH_info_aes_hw_set_encrypt_key_base_0 wrt ..imagebase + + DD $L$SEH_begin_aes_hw_set_encrypt_key_alt_1 wrt ..imagebase + DD $L$SEH_end_aes_hw_set_encrypt_key_alt_4 wrt ..imagebase + DD $L$SEH_info_aes_hw_set_encrypt_key_alt_0 wrt ..imagebase + + +section .xdata +ALIGN 4 +$L$SEH_info_aes_hw_set_encrypt_key_base_0: + DB 1 + DB $L$SEH_endprologue_aes_hw_set_encrypt_key_base_3-$L$SEH_begin_aes_hw_set_encrypt_key_base_1 + DB 1 + DB 0 + DB $L$SEH_prologue_aes_hw_set_encrypt_key_base_2-$L$SEH_begin_aes_hw_set_encrypt_key_base_1 + DB 2 + + DW 0 +$L$SEH_info_aes_hw_set_encrypt_key_alt_0: + DB 1 + DB $L$SEH_endprologue_aes_hw_set_encrypt_key_alt_3-$L$SEH_begin_aes_hw_set_encrypt_key_alt_1 + DB 1 + DB 0 + DB $L$SEH_prologue_aes_hw_set_encrypt_key_alt_2-$L$SEH_begin_aes_hw_set_encrypt_key_alt_1 + DB 2 + + DW 0 %else ; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738 ret diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv7-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv7-linux.S index 420af9b6ea..97d56c7aff 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv7-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv7-linux.S @@ -26,11 +26,6 @@ .align 5 aes_hw_set_encrypt_key: .Lenc_key: - mov r3,#-1 - cmp r0,#0 - beq .Lenc_key_abort - cmp r2,#0 - beq .Lenc_key_abort mov r3,#-2 cmp r1,#128 blt .Lenc_key_abort diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-apple.S index 144c4af34b..ef642443fb 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-apple.S @@ -28,11 +28,6 @@ Lenc_key: AARCH64_VALID_CALL_TARGET stp x29,x30,[sp,#-16]! add x29,sp,#0 - mov x3,#-1 - cmp x0,#0 - b.eq Lenc_key_abort - cmp x2,#0 - b.eq Lenc_key_abort mov x3,#-2 cmp w1,#128 b.lt Lenc_key_abort diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-linux.S index 7d4bcb4ca1..23d78f2e91 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-linux.S @@ -28,11 +28,6 @@ aes_hw_set_encrypt_key: AARCH64_VALID_CALL_TARGET stp x29,x30,[sp,#-16]! add x29,sp,#0 - mov x3,#-1 - cmp x0,#0 - b.eq .Lenc_key_abort - cmp x2,#0 - b.eq .Lenc_key_abort mov x3,#-2 cmp w1,#128 b.lt .Lenc_key_abort diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-win.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-win.S index a3ab33afc9..48bf2fd1a3 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-win.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/aesv8-armv8-win.S @@ -30,11 +30,6 @@ Lenc_key: AARCH64_VALID_CALL_TARGET stp x29,x30,[sp,#-16]! add x29,sp,#0 - mov x3,#-1 - cmp x0,#0 - b.eq Lenc_key_abort - cmp x2,#0 - b.eq Lenc_key_abort mov x3,#-2 cmp w1,#128 b.lt Lenc_key_abort diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-apple.S index 93513d0bf3..f483ef1d94 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-apple.S @@ -10,20 +10,14 @@ .align 4 _bn_mul_add_words: L_bn_mul_add_words_begin: - call L000PIC_me_up -L000PIC_me_up: - popl %eax - movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L000PIC_me_up(%eax),%eax - btl $26,(%eax) - jnc L001maw_non_sse2 movl 4(%esp),%eax movl 8(%esp),%edx movl 12(%esp),%ecx movd 16(%esp),%mm0 pxor %mm1,%mm1 - jmp L002maw_sse2_entry + jmp L000maw_sse2_entry .align 4,0x90 -L003maw_sse2_unrolled: +L001maw_sse2_unrolled: movd (%eax),%mm3 paddq %mm3,%mm1 movd (%edx),%mm2 @@ -83,12 +77,12 @@ L003maw_sse2_unrolled: leal 32(%eax),%eax psrlq $32,%mm1 subl $8,%ecx - jz L004maw_sse2_exit -L002maw_sse2_entry: + jz L002maw_sse2_exit +L000maw_sse2_entry: testl $4294967288,%ecx - jnz L003maw_sse2_unrolled + jnz L001maw_sse2_unrolled .align 2,0x90 -L005maw_sse2_loop: +L003maw_sse2_loop: movd (%edx),%mm2 movd (%eax),%mm3 pmuludq %mm0,%mm2 @@ -99,189 +93,11 @@ L005maw_sse2_loop: subl $1,%ecx psrlq $32,%mm1 leal 4(%eax),%eax - jnz L005maw_sse2_loop -L004maw_sse2_exit: + jnz L003maw_sse2_loop +L002maw_sse2_exit: movd %mm1,%eax emms ret -.align 4,0x90 -L001maw_non_sse2: - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - xorl %esi,%esi - movl 20(%esp),%edi - movl 28(%esp),%ecx - movl 24(%esp),%ebx - andl $4294967288,%ecx - movl 32(%esp),%ebp - pushl %ecx - jz L006maw_finish -.align 4,0x90 -L007maw_loop: - # Round 0 - movl (%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl (%edi),%eax - adcl $0,%edx - movl %eax,(%edi) - movl %edx,%esi - # Round 4 - movl 4(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 4(%edi),%eax - adcl $0,%edx - movl %eax,4(%edi) - movl %edx,%esi - # Round 8 - movl 8(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 8(%edi),%eax - adcl $0,%edx - movl %eax,8(%edi) - movl %edx,%esi - # Round 12 - movl 12(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 12(%edi),%eax - adcl $0,%edx - movl %eax,12(%edi) - movl %edx,%esi - # Round 16 - movl 16(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 16(%edi),%eax - adcl $0,%edx - movl %eax,16(%edi) - movl %edx,%esi - # Round 20 - movl 20(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 20(%edi),%eax - adcl $0,%edx - movl %eax,20(%edi) - movl %edx,%esi - # Round 24 - movl 24(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 24(%edi),%eax - adcl $0,%edx - movl %eax,24(%edi) - movl %edx,%esi - # Round 28 - movl 28(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 28(%edi),%eax - adcl $0,%edx - movl %eax,28(%edi) - movl %edx,%esi - - subl $8,%ecx - leal 32(%ebx),%ebx - leal 32(%edi),%edi - jnz L007maw_loop -L006maw_finish: - movl 32(%esp),%ecx - andl $7,%ecx - jnz L008maw_finish2 - jmp L009maw_end -L008maw_finish2: - # Tail Round 0 - movl (%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl (%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,(%edi) - movl %edx,%esi - jz L009maw_end - # Tail Round 1 - movl 4(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 4(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,4(%edi) - movl %edx,%esi - jz L009maw_end - # Tail Round 2 - movl 8(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 8(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,8(%edi) - movl %edx,%esi - jz L009maw_end - # Tail Round 3 - movl 12(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 12(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,12(%edi) - movl %edx,%esi - jz L009maw_end - # Tail Round 4 - movl 16(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 16(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,16(%edi) - movl %edx,%esi - jz L009maw_end - # Tail Round 5 - movl 20(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 20(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,20(%edi) - movl %edx,%esi - jz L009maw_end - # Tail Round 6 - movl 24(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 24(%edi),%eax - adcl $0,%edx - movl %eax,24(%edi) - movl %edx,%esi -L009maw_end: - movl %esi,%eax - popl %ecx popl %edi popl %esi popl %ebx @@ -292,19 +108,13 @@ L009maw_end: .align 4 _bn_mul_words: L_bn_mul_words_begin: - call L010PIC_me_up -L010PIC_me_up: - popl %eax - movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L010PIC_me_up(%eax),%eax - btl $26,(%eax) - jnc L011mw_non_sse2 movl 4(%esp),%eax movl 8(%esp),%edx movl 12(%esp),%ecx movd 16(%esp),%mm0 pxor %mm1,%mm1 .align 4,0x90 -L012mw_sse2_loop: +L004mw_sse2_loop: movd (%edx),%mm2 pmuludq %mm0,%mm2 leal 4(%edx),%edx @@ -313,156 +123,10 @@ L012mw_sse2_loop: subl $1,%ecx psrlq $32,%mm1 leal 4(%eax),%eax - jnz L012mw_sse2_loop + jnz L004mw_sse2_loop movd %mm1,%eax emms ret -.align 4,0x90 -L011mw_non_sse2: - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - xorl %esi,%esi - movl 20(%esp),%edi - movl 24(%esp),%ebx - movl 28(%esp),%ebp - movl 32(%esp),%ecx - andl $4294967288,%ebp - jz L013mw_finish -L014mw_loop: - # Round 0 - movl (%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,(%edi) - movl %edx,%esi - # Round 4 - movl 4(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,4(%edi) - movl %edx,%esi - # Round 8 - movl 8(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,8(%edi) - movl %edx,%esi - # Round 12 - movl 12(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,12(%edi) - movl %edx,%esi - # Round 16 - movl 16(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,16(%edi) - movl %edx,%esi - # Round 20 - movl 20(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,20(%edi) - movl %edx,%esi - # Round 24 - movl 24(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,24(%edi) - movl %edx,%esi - # Round 28 - movl 28(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,28(%edi) - movl %edx,%esi - - addl $32,%ebx - addl $32,%edi - subl $8,%ebp - jz L013mw_finish - jmp L014mw_loop -L013mw_finish: - movl 28(%esp),%ebp - andl $7,%ebp - jnz L015mw_finish2 - jmp L016mw_end -L015mw_finish2: - # Tail Round 0 - movl (%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,(%edi) - movl %edx,%esi - decl %ebp - jz L016mw_end - # Tail Round 1 - movl 4(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,4(%edi) - movl %edx,%esi - decl %ebp - jz L016mw_end - # Tail Round 2 - movl 8(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,8(%edi) - movl %edx,%esi - decl %ebp - jz L016mw_end - # Tail Round 3 - movl 12(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,12(%edi) - movl %edx,%esi - decl %ebp - jz L016mw_end - # Tail Round 4 - movl 16(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,16(%edi) - movl %edx,%esi - decl %ebp - jz L016mw_end - # Tail Round 5 - movl 20(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,20(%edi) - movl %edx,%esi - decl %ebp - jz L016mw_end - # Tail Round 6 - movl 24(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,24(%edi) - movl %edx,%esi -L016mw_end: - movl %esi,%eax popl %edi popl %esi popl %ebx @@ -473,136 +137,20 @@ L016mw_end: .align 4 _bn_sqr_words: L_bn_sqr_words_begin: - call L017PIC_me_up -L017PIC_me_up: - popl %eax - movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L017PIC_me_up(%eax),%eax - btl $26,(%eax) - jnc L018sqr_non_sse2 movl 4(%esp),%eax movl 8(%esp),%edx movl 12(%esp),%ecx .align 4,0x90 -L019sqr_sse2_loop: +L005sqr_sse2_loop: movd (%edx),%mm0 pmuludq %mm0,%mm0 leal 4(%edx),%edx movq %mm0,(%eax) subl $1,%ecx leal 8(%eax),%eax - jnz L019sqr_sse2_loop + jnz L005sqr_sse2_loop emms ret -.align 4,0x90 -L018sqr_non_sse2: - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - movl 20(%esp),%esi - movl 24(%esp),%edi - movl 28(%esp),%ebx - andl $4294967288,%ebx - jz L020sw_finish -L021sw_loop: - # Round 0 - movl (%edi),%eax - mull %eax - movl %eax,(%esi) - movl %edx,4(%esi) - # Round 4 - movl 4(%edi),%eax - mull %eax - movl %eax,8(%esi) - movl %edx,12(%esi) - # Round 8 - movl 8(%edi),%eax - mull %eax - movl %eax,16(%esi) - movl %edx,20(%esi) - # Round 12 - movl 12(%edi),%eax - mull %eax - movl %eax,24(%esi) - movl %edx,28(%esi) - # Round 16 - movl 16(%edi),%eax - mull %eax - movl %eax,32(%esi) - movl %edx,36(%esi) - # Round 20 - movl 20(%edi),%eax - mull %eax - movl %eax,40(%esi) - movl %edx,44(%esi) - # Round 24 - movl 24(%edi),%eax - mull %eax - movl %eax,48(%esi) - movl %edx,52(%esi) - # Round 28 - movl 28(%edi),%eax - mull %eax - movl %eax,56(%esi) - movl %edx,60(%esi) - - addl $32,%edi - addl $64,%esi - subl $8,%ebx - jnz L021sw_loop -L020sw_finish: - movl 28(%esp),%ebx - andl $7,%ebx - jz L022sw_end - # Tail Round 0 - movl (%edi),%eax - mull %eax - movl %eax,(%esi) - decl %ebx - movl %edx,4(%esi) - jz L022sw_end - # Tail Round 1 - movl 4(%edi),%eax - mull %eax - movl %eax,8(%esi) - decl %ebx - movl %edx,12(%esi) - jz L022sw_end - # Tail Round 2 - movl 8(%edi),%eax - mull %eax - movl %eax,16(%esi) - decl %ebx - movl %edx,20(%esi) - jz L022sw_end - # Tail Round 3 - movl 12(%edi),%eax - mull %eax - movl %eax,24(%esi) - decl %ebx - movl %edx,28(%esi) - jz L022sw_end - # Tail Round 4 - movl 16(%edi),%eax - mull %eax - movl %eax,32(%esi) - decl %ebx - movl %edx,36(%esi) - jz L022sw_end - # Tail Round 5 - movl 20(%edi),%eax - mull %eax - movl %eax,40(%esi) - decl %ebx - movl %edx,44(%esi) - jz L022sw_end - # Tail Round 6 - movl 24(%edi),%eax - mull %eax - movl %eax,48(%esi) - movl %edx,52(%esi) -L022sw_end: popl %edi popl %esi popl %ebx @@ -634,8 +182,8 @@ L_bn_add_words_begin: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz L023aw_finish -L024aw_loop: + jz L006aw_finish +L007aw_loop: # Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -713,11 +261,11 @@ L024aw_loop: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz L024aw_loop -L023aw_finish: + jnz L007aw_loop +L006aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz L025aw_end + jz L008aw_end # Tail Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -728,7 +276,7 @@ L023aw_finish: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz L025aw_end + jz L008aw_end # Tail Round 1 movl 4(%esi),%ecx movl 4(%edi),%edx @@ -739,7 +287,7 @@ L023aw_finish: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz L025aw_end + jz L008aw_end # Tail Round 2 movl 8(%esi),%ecx movl 8(%edi),%edx @@ -750,7 +298,7 @@ L023aw_finish: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz L025aw_end + jz L008aw_end # Tail Round 3 movl 12(%esi),%ecx movl 12(%edi),%edx @@ -761,7 +309,7 @@ L023aw_finish: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz L025aw_end + jz L008aw_end # Tail Round 4 movl 16(%esi),%ecx movl 16(%edi),%edx @@ -772,7 +320,7 @@ L023aw_finish: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz L025aw_end + jz L008aw_end # Tail Round 5 movl 20(%esi),%ecx movl 20(%edi),%edx @@ -783,7 +331,7 @@ L023aw_finish: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz L025aw_end + jz L008aw_end # Tail Round 6 movl 24(%esi),%ecx movl 24(%edi),%edx @@ -793,7 +341,7 @@ L023aw_finish: addl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) -L025aw_end: +L008aw_end: popl %edi popl %esi popl %ebx @@ -815,8 +363,8 @@ L_bn_sub_words_begin: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz L026aw_finish -L027aw_loop: + jz L009aw_finish +L010aw_loop: # Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -894,11 +442,11 @@ L027aw_loop: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz L027aw_loop -L026aw_finish: + jnz L010aw_loop +L009aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz L028aw_end + jz L011aw_end # Tail Round 0 movl (%esi),%ecx movl (%edi),%edx @@ -909,7 +457,7 @@ L026aw_finish: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz L028aw_end + jz L011aw_end # Tail Round 1 movl 4(%esi),%ecx movl 4(%edi),%edx @@ -920,7 +468,7 @@ L026aw_finish: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz L028aw_end + jz L011aw_end # Tail Round 2 movl 8(%esi),%ecx movl 8(%edi),%edx @@ -931,7 +479,7 @@ L026aw_finish: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz L028aw_end + jz L011aw_end # Tail Round 3 movl 12(%esi),%ecx movl 12(%edi),%edx @@ -942,7 +490,7 @@ L026aw_finish: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz L028aw_end + jz L011aw_end # Tail Round 4 movl 16(%esi),%ecx movl 16(%edi),%edx @@ -953,7 +501,7 @@ L026aw_finish: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz L028aw_end + jz L011aw_end # Tail Round 5 movl 20(%esi),%ecx movl 20(%edi),%edx @@ -964,7 +512,7 @@ L026aw_finish: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz L028aw_end + jz L011aw_end # Tail Round 6 movl 24(%esi),%ecx movl 24(%edi),%edx @@ -974,14 +522,10 @@ L026aw_finish: subl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) -L028aw_end: +L011aw_end: popl %edi popl %esi popl %ebx popl %ebp ret -.section __IMPORT,__pointers,non_lazy_symbol_pointers -L_OPENSSL_ia32cap_P$non_lazy_ptr: -.indirect_symbol _OPENSSL_ia32cap_P -.long 0 #endif // !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__APPLE__) diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-linux.S index 311f22c04a..fb83b22bd6 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-linux.S @@ -11,20 +11,14 @@ .align 16 bn_mul_add_words: .L_bn_mul_add_words_begin: - call .L000PIC_me_up -.L000PIC_me_up: - popl %eax - leal OPENSSL_ia32cap_P-.L000PIC_me_up(%eax),%eax - btl $26,(%eax) - jnc .L001maw_non_sse2 movl 4(%esp),%eax movl 8(%esp),%edx movl 12(%esp),%ecx movd 16(%esp),%mm0 pxor %mm1,%mm1 - jmp .L002maw_sse2_entry + jmp .L000maw_sse2_entry .align 16 -.L003maw_sse2_unrolled: +.L001maw_sse2_unrolled: movd (%eax),%mm3 paddq %mm3,%mm1 movd (%edx),%mm2 @@ -84,12 +78,12 @@ bn_mul_add_words: leal 32(%eax),%eax psrlq $32,%mm1 subl $8,%ecx - jz .L004maw_sse2_exit -.L002maw_sse2_entry: + jz .L002maw_sse2_exit +.L000maw_sse2_entry: testl $4294967288,%ecx - jnz .L003maw_sse2_unrolled + jnz .L001maw_sse2_unrolled .align 4 -.L005maw_sse2_loop: +.L003maw_sse2_loop: movd (%edx),%mm2 movd (%eax),%mm3 pmuludq %mm0,%mm2 @@ -100,189 +94,11 @@ bn_mul_add_words: subl $1,%ecx psrlq $32,%mm1 leal 4(%eax),%eax - jnz .L005maw_sse2_loop -.L004maw_sse2_exit: + jnz .L003maw_sse2_loop +.L002maw_sse2_exit: movd %mm1,%eax emms ret -.align 16 -.L001maw_non_sse2: - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - xorl %esi,%esi - movl 20(%esp),%edi - movl 28(%esp),%ecx - movl 24(%esp),%ebx - andl $4294967288,%ecx - movl 32(%esp),%ebp - pushl %ecx - jz .L006maw_finish -.align 16 -.L007maw_loop: - - movl (%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl (%edi),%eax - adcl $0,%edx - movl %eax,(%edi) - movl %edx,%esi - - movl 4(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 4(%edi),%eax - adcl $0,%edx - movl %eax,4(%edi) - movl %edx,%esi - - movl 8(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 8(%edi),%eax - adcl $0,%edx - movl %eax,8(%edi) - movl %edx,%esi - - movl 12(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 12(%edi),%eax - adcl $0,%edx - movl %eax,12(%edi) - movl %edx,%esi - - movl 16(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 16(%edi),%eax - adcl $0,%edx - movl %eax,16(%edi) - movl %edx,%esi - - movl 20(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 20(%edi),%eax - adcl $0,%edx - movl %eax,20(%edi) - movl %edx,%esi - - movl 24(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 24(%edi),%eax - adcl $0,%edx - movl %eax,24(%edi) - movl %edx,%esi - - movl 28(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 28(%edi),%eax - adcl $0,%edx - movl %eax,28(%edi) - movl %edx,%esi - - subl $8,%ecx - leal 32(%ebx),%ebx - leal 32(%edi),%edi - jnz .L007maw_loop -.L006maw_finish: - movl 32(%esp),%ecx - andl $7,%ecx - jnz .L008maw_finish2 - jmp .L009maw_end -.L008maw_finish2: - - movl (%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl (%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,(%edi) - movl %edx,%esi - jz .L009maw_end - - movl 4(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 4(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,4(%edi) - movl %edx,%esi - jz .L009maw_end - - movl 8(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 8(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,8(%edi) - movl %edx,%esi - jz .L009maw_end - - movl 12(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 12(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,12(%edi) - movl %edx,%esi - jz .L009maw_end - - movl 16(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 16(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,16(%edi) - movl %edx,%esi - jz .L009maw_end - - movl 20(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 20(%edi),%eax - adcl $0,%edx - decl %ecx - movl %eax,20(%edi) - movl %edx,%esi - jz .L009maw_end - - movl 24(%ebx),%eax - mull %ebp - addl %esi,%eax - adcl $0,%edx - addl 24(%edi),%eax - adcl $0,%edx - movl %eax,24(%edi) - movl %edx,%esi -.L009maw_end: - movl %esi,%eax - popl %ecx popl %edi popl %esi popl %ebx @@ -295,19 +111,13 @@ bn_mul_add_words: .align 16 bn_mul_words: .L_bn_mul_words_begin: - call .L010PIC_me_up -.L010PIC_me_up: - popl %eax - leal OPENSSL_ia32cap_P-.L010PIC_me_up(%eax),%eax - btl $26,(%eax) - jnc .L011mw_non_sse2 movl 4(%esp),%eax movl 8(%esp),%edx movl 12(%esp),%ecx movd 16(%esp),%mm0 pxor %mm1,%mm1 .align 16 -.L012mw_sse2_loop: +.L004mw_sse2_loop: movd (%edx),%mm2 pmuludq %mm0,%mm2 leal 4(%edx),%edx @@ -316,156 +126,10 @@ bn_mul_words: subl $1,%ecx psrlq $32,%mm1 leal 4(%eax),%eax - jnz .L012mw_sse2_loop + jnz .L004mw_sse2_loop movd %mm1,%eax emms ret -.align 16 -.L011mw_non_sse2: - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - xorl %esi,%esi - movl 20(%esp),%edi - movl 24(%esp),%ebx - movl 28(%esp),%ebp - movl 32(%esp),%ecx - andl $4294967288,%ebp - jz .L013mw_finish -.L014mw_loop: - - movl (%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,(%edi) - movl %edx,%esi - - movl 4(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,4(%edi) - movl %edx,%esi - - movl 8(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,8(%edi) - movl %edx,%esi - - movl 12(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,12(%edi) - movl %edx,%esi - - movl 16(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,16(%edi) - movl %edx,%esi - - movl 20(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,20(%edi) - movl %edx,%esi - - movl 24(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,24(%edi) - movl %edx,%esi - - movl 28(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,28(%edi) - movl %edx,%esi - - addl $32,%ebx - addl $32,%edi - subl $8,%ebp - jz .L013mw_finish - jmp .L014mw_loop -.L013mw_finish: - movl 28(%esp),%ebp - andl $7,%ebp - jnz .L015mw_finish2 - jmp .L016mw_end -.L015mw_finish2: - - movl (%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,(%edi) - movl %edx,%esi - decl %ebp - jz .L016mw_end - - movl 4(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,4(%edi) - movl %edx,%esi - decl %ebp - jz .L016mw_end - - movl 8(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,8(%edi) - movl %edx,%esi - decl %ebp - jz .L016mw_end - - movl 12(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,12(%edi) - movl %edx,%esi - decl %ebp - jz .L016mw_end - - movl 16(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,16(%edi) - movl %edx,%esi - decl %ebp - jz .L016mw_end - - movl 20(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,20(%edi) - movl %edx,%esi - decl %ebp - jz .L016mw_end - - movl 24(%ebx),%eax - mull %ecx - addl %esi,%eax - adcl $0,%edx - movl %eax,24(%edi) - movl %edx,%esi -.L016mw_end: - movl %esi,%eax popl %edi popl %esi popl %ebx @@ -478,136 +142,20 @@ bn_mul_words: .align 16 bn_sqr_words: .L_bn_sqr_words_begin: - call .L017PIC_me_up -.L017PIC_me_up: - popl %eax - leal OPENSSL_ia32cap_P-.L017PIC_me_up(%eax),%eax - btl $26,(%eax) - jnc .L018sqr_non_sse2 movl 4(%esp),%eax movl 8(%esp),%edx movl 12(%esp),%ecx .align 16 -.L019sqr_sse2_loop: +.L005sqr_sse2_loop: movd (%edx),%mm0 pmuludq %mm0,%mm0 leal 4(%edx),%edx movq %mm0,(%eax) subl $1,%ecx leal 8(%eax),%eax - jnz .L019sqr_sse2_loop + jnz .L005sqr_sse2_loop emms ret -.align 16 -.L018sqr_non_sse2: - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - - movl 20(%esp),%esi - movl 24(%esp),%edi - movl 28(%esp),%ebx - andl $4294967288,%ebx - jz .L020sw_finish -.L021sw_loop: - - movl (%edi),%eax - mull %eax - movl %eax,(%esi) - movl %edx,4(%esi) - - movl 4(%edi),%eax - mull %eax - movl %eax,8(%esi) - movl %edx,12(%esi) - - movl 8(%edi),%eax - mull %eax - movl %eax,16(%esi) - movl %edx,20(%esi) - - movl 12(%edi),%eax - mull %eax - movl %eax,24(%esi) - movl %edx,28(%esi) - - movl 16(%edi),%eax - mull %eax - movl %eax,32(%esi) - movl %edx,36(%esi) - - movl 20(%edi),%eax - mull %eax - movl %eax,40(%esi) - movl %edx,44(%esi) - - movl 24(%edi),%eax - mull %eax - movl %eax,48(%esi) - movl %edx,52(%esi) - - movl 28(%edi),%eax - mull %eax - movl %eax,56(%esi) - movl %edx,60(%esi) - - addl $32,%edi - addl $64,%esi - subl $8,%ebx - jnz .L021sw_loop -.L020sw_finish: - movl 28(%esp),%ebx - andl $7,%ebx - jz .L022sw_end - - movl (%edi),%eax - mull %eax - movl %eax,(%esi) - decl %ebx - movl %edx,4(%esi) - jz .L022sw_end - - movl 4(%edi),%eax - mull %eax - movl %eax,8(%esi) - decl %ebx - movl %edx,12(%esi) - jz .L022sw_end - - movl 8(%edi),%eax - mull %eax - movl %eax,16(%esi) - decl %ebx - movl %edx,20(%esi) - jz .L022sw_end - - movl 12(%edi),%eax - mull %eax - movl %eax,24(%esi) - decl %ebx - movl %edx,28(%esi) - jz .L022sw_end - - movl 16(%edi),%eax - mull %eax - movl %eax,32(%esi) - decl %ebx - movl %edx,36(%esi) - jz .L022sw_end - - movl 20(%edi),%eax - mull %eax - movl %eax,40(%esi) - decl %ebx - movl %edx,44(%esi) - jz .L022sw_end - - movl 24(%edi),%eax - mull %eax - movl %eax,48(%esi) - movl %edx,52(%esi) -.L022sw_end: popl %edi popl %esi popl %ebx @@ -643,8 +191,8 @@ bn_add_words: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz .L023aw_finish -.L024aw_loop: + jz .L006aw_finish +.L007aw_loop: movl (%esi),%ecx movl (%edi),%edx @@ -722,11 +270,11 @@ bn_add_words: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz .L024aw_loop -.L023aw_finish: + jnz .L007aw_loop +.L006aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz .L025aw_end + jz .L008aw_end movl (%esi),%ecx movl (%edi),%edx @@ -737,7 +285,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz .L025aw_end + jz .L008aw_end movl 4(%esi),%ecx movl 4(%edi),%edx @@ -748,7 +296,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz .L025aw_end + jz .L008aw_end movl 8(%esi),%ecx movl 8(%edi),%edx @@ -759,7 +307,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz .L025aw_end + jz .L008aw_end movl 12(%esi),%ecx movl 12(%edi),%edx @@ -770,7 +318,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz .L025aw_end + jz .L008aw_end movl 16(%esi),%ecx movl 16(%edi),%edx @@ -781,7 +329,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz .L025aw_end + jz .L008aw_end movl 20(%esi),%ecx movl 20(%edi),%edx @@ -792,7 +340,7 @@ bn_add_words: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz .L025aw_end + jz .L008aw_end movl 24(%esi),%ecx movl 24(%edi),%edx @@ -802,7 +350,7 @@ bn_add_words: addl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) -.L025aw_end: +.L008aw_end: popl %edi popl %esi popl %ebx @@ -826,8 +374,8 @@ bn_sub_words: movl 32(%esp),%ebp xorl %eax,%eax andl $4294967288,%ebp - jz .L026aw_finish -.L027aw_loop: + jz .L009aw_finish +.L010aw_loop: movl (%esi),%ecx movl (%edi),%edx @@ -905,11 +453,11 @@ bn_sub_words: addl $32,%edi addl $32,%ebx subl $8,%ebp - jnz .L027aw_loop -.L026aw_finish: + jnz .L010aw_loop +.L009aw_finish: movl 32(%esp),%ebp andl $7,%ebp - jz .L028aw_end + jz .L011aw_end movl (%esi),%ecx movl (%edi),%edx @@ -920,7 +468,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,(%ebx) - jz .L028aw_end + jz .L011aw_end movl 4(%esi),%ecx movl 4(%edi),%edx @@ -931,7 +479,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,4(%ebx) - jz .L028aw_end + jz .L011aw_end movl 8(%esi),%ecx movl 8(%edi),%edx @@ -942,7 +490,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,8(%ebx) - jz .L028aw_end + jz .L011aw_end movl 12(%esi),%ecx movl 12(%edi),%edx @@ -953,7 +501,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,12(%ebx) - jz .L028aw_end + jz .L011aw_end movl 16(%esi),%ecx movl 16(%edi),%edx @@ -964,7 +512,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,16(%ebx) - jz .L028aw_end + jz .L011aw_end movl 20(%esi),%ecx movl 20(%edi),%edx @@ -975,7 +523,7 @@ bn_sub_words: adcl $0,%eax decl %ebp movl %ecx,20(%ebx) - jz .L028aw_end + jz .L011aw_end movl 24(%esi),%ecx movl 24(%edi),%edx @@ -985,7 +533,7 @@ bn_sub_words: subl %edx,%ecx adcl $0,%eax movl %ecx,24(%ebx) -.L028aw_end: +.L011aw_end: popl %edi popl %esi popl %ebx diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-win.asm index f7ddfa8413..09aafb8d00 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/bn-586-win.asm @@ -13,22 +13,18 @@ section .text code align=64 %else section .text code %endif -;extern _OPENSSL_ia32cap_P global _bn_mul_add_words align 16 _bn_mul_add_words: L$_bn_mul_add_words_begin: - lea eax,[_OPENSSL_ia32cap_P] - bt DWORD [eax],26 - jnc NEAR L$000maw_non_sse2 mov eax,DWORD [4+esp] mov edx,DWORD [8+esp] mov ecx,DWORD [12+esp] movd mm0,DWORD [16+esp] pxor mm1,mm1 - jmp NEAR L$001maw_sse2_entry + jmp NEAR L$000maw_sse2_entry align 16 -L$002maw_sse2_unrolled: +L$001maw_sse2_unrolled: movd mm3,DWORD [eax] paddq mm1,mm3 movd mm2,DWORD [edx] @@ -88,12 +84,12 @@ L$002maw_sse2_unrolled: lea eax,[32+eax] psrlq mm1,32 sub ecx,8 - jz NEAR L$003maw_sse2_exit -L$001maw_sse2_entry: + jz NEAR L$002maw_sse2_exit +L$000maw_sse2_entry: test ecx,4294967288 - jnz NEAR L$002maw_sse2_unrolled + jnz NEAR L$001maw_sse2_unrolled align 4 -L$004maw_sse2_loop: +L$003maw_sse2_loop: movd mm2,DWORD [edx] movd mm3,DWORD [eax] pmuludq mm2,mm0 @@ -104,189 +100,11 @@ L$004maw_sse2_loop: sub ecx,1 psrlq mm1,32 lea eax,[4+eax] - jnz NEAR L$004maw_sse2_loop -L$003maw_sse2_exit: + jnz NEAR L$003maw_sse2_loop +L$002maw_sse2_exit: movd eax,mm1 emms ret -align 16 -L$000maw_non_sse2: - push ebp - push ebx - push esi - push edi - ; - xor esi,esi - mov edi,DWORD [20+esp] - mov ecx,DWORD [28+esp] - mov ebx,DWORD [24+esp] - and ecx,4294967288 - mov ebp,DWORD [32+esp] - push ecx - jz NEAR L$005maw_finish -align 16 -L$006maw_loop: - ; Round 0 - mov eax,DWORD [ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [edi] - adc edx,0 - mov DWORD [edi],eax - mov esi,edx - ; Round 4 - mov eax,DWORD [4+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [4+edi] - adc edx,0 - mov DWORD [4+edi],eax - mov esi,edx - ; Round 8 - mov eax,DWORD [8+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [8+edi] - adc edx,0 - mov DWORD [8+edi],eax - mov esi,edx - ; Round 12 - mov eax,DWORD [12+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [12+edi] - adc edx,0 - mov DWORD [12+edi],eax - mov esi,edx - ; Round 16 - mov eax,DWORD [16+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [16+edi] - adc edx,0 - mov DWORD [16+edi],eax - mov esi,edx - ; Round 20 - mov eax,DWORD [20+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [20+edi] - adc edx,0 - mov DWORD [20+edi],eax - mov esi,edx - ; Round 24 - mov eax,DWORD [24+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [24+edi] - adc edx,0 - mov DWORD [24+edi],eax - mov esi,edx - ; Round 28 - mov eax,DWORD [28+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [28+edi] - adc edx,0 - mov DWORD [28+edi],eax - mov esi,edx - ; - sub ecx,8 - lea ebx,[32+ebx] - lea edi,[32+edi] - jnz NEAR L$006maw_loop -L$005maw_finish: - mov ecx,DWORD [32+esp] - and ecx,7 - jnz NEAR L$007maw_finish2 - jmp NEAR L$008maw_end -L$007maw_finish2: - ; Tail Round 0 - mov eax,DWORD [ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [edi] - adc edx,0 - dec ecx - mov DWORD [edi],eax - mov esi,edx - jz NEAR L$008maw_end - ; Tail Round 1 - mov eax,DWORD [4+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [4+edi] - adc edx,0 - dec ecx - mov DWORD [4+edi],eax - mov esi,edx - jz NEAR L$008maw_end - ; Tail Round 2 - mov eax,DWORD [8+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [8+edi] - adc edx,0 - dec ecx - mov DWORD [8+edi],eax - mov esi,edx - jz NEAR L$008maw_end - ; Tail Round 3 - mov eax,DWORD [12+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [12+edi] - adc edx,0 - dec ecx - mov DWORD [12+edi],eax - mov esi,edx - jz NEAR L$008maw_end - ; Tail Round 4 - mov eax,DWORD [16+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [16+edi] - adc edx,0 - dec ecx - mov DWORD [16+edi],eax - mov esi,edx - jz NEAR L$008maw_end - ; Tail Round 5 - mov eax,DWORD [20+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [20+edi] - adc edx,0 - dec ecx - mov DWORD [20+edi],eax - mov esi,edx - jz NEAR L$008maw_end - ; Tail Round 6 - mov eax,DWORD [24+ebx] - mul ebp - add eax,esi - adc edx,0 - add eax,DWORD [24+edi] - adc edx,0 - mov DWORD [24+edi],eax - mov esi,edx -L$008maw_end: - mov eax,esi - pop ecx pop edi pop esi pop ebx @@ -296,16 +114,13 @@ global _bn_mul_words align 16 _bn_mul_words: L$_bn_mul_words_begin: - lea eax,[_OPENSSL_ia32cap_P] - bt DWORD [eax],26 - jnc NEAR L$009mw_non_sse2 mov eax,DWORD [4+esp] mov edx,DWORD [8+esp] mov ecx,DWORD [12+esp] movd mm0,DWORD [16+esp] pxor mm1,mm1 align 16 -L$010mw_sse2_loop: +L$004mw_sse2_loop: movd mm2,DWORD [edx] pmuludq mm2,mm0 lea edx,[4+edx] @@ -314,156 +129,10 @@ L$010mw_sse2_loop: sub ecx,1 psrlq mm1,32 lea eax,[4+eax] - jnz NEAR L$010mw_sse2_loop + jnz NEAR L$004mw_sse2_loop movd eax,mm1 emms ret -align 16 -L$009mw_non_sse2: - push ebp - push ebx - push esi - push edi - ; - xor esi,esi - mov edi,DWORD [20+esp] - mov ebx,DWORD [24+esp] - mov ebp,DWORD [28+esp] - mov ecx,DWORD [32+esp] - and ebp,4294967288 - jz NEAR L$011mw_finish -L$012mw_loop: - ; Round 0 - mov eax,DWORD [ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [edi],eax - mov esi,edx - ; Round 4 - mov eax,DWORD [4+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [4+edi],eax - mov esi,edx - ; Round 8 - mov eax,DWORD [8+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [8+edi],eax - mov esi,edx - ; Round 12 - mov eax,DWORD [12+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [12+edi],eax - mov esi,edx - ; Round 16 - mov eax,DWORD [16+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [16+edi],eax - mov esi,edx - ; Round 20 - mov eax,DWORD [20+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [20+edi],eax - mov esi,edx - ; Round 24 - mov eax,DWORD [24+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [24+edi],eax - mov esi,edx - ; Round 28 - mov eax,DWORD [28+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [28+edi],eax - mov esi,edx - ; - add ebx,32 - add edi,32 - sub ebp,8 - jz NEAR L$011mw_finish - jmp NEAR L$012mw_loop -L$011mw_finish: - mov ebp,DWORD [28+esp] - and ebp,7 - jnz NEAR L$013mw_finish2 - jmp NEAR L$014mw_end -L$013mw_finish2: - ; Tail Round 0 - mov eax,DWORD [ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [edi],eax - mov esi,edx - dec ebp - jz NEAR L$014mw_end - ; Tail Round 1 - mov eax,DWORD [4+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [4+edi],eax - mov esi,edx - dec ebp - jz NEAR L$014mw_end - ; Tail Round 2 - mov eax,DWORD [8+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [8+edi],eax - mov esi,edx - dec ebp - jz NEAR L$014mw_end - ; Tail Round 3 - mov eax,DWORD [12+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [12+edi],eax - mov esi,edx - dec ebp - jz NEAR L$014mw_end - ; Tail Round 4 - mov eax,DWORD [16+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [16+edi],eax - mov esi,edx - dec ebp - jz NEAR L$014mw_end - ; Tail Round 5 - mov eax,DWORD [20+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [20+edi],eax - mov esi,edx - dec ebp - jz NEAR L$014mw_end - ; Tail Round 6 - mov eax,DWORD [24+ebx] - mul ecx - add eax,esi - adc edx,0 - mov DWORD [24+edi],eax - mov esi,edx -L$014mw_end: - mov eax,esi pop edi pop esi pop ebx @@ -473,133 +142,20 @@ global _bn_sqr_words align 16 _bn_sqr_words: L$_bn_sqr_words_begin: - lea eax,[_OPENSSL_ia32cap_P] - bt DWORD [eax],26 - jnc NEAR L$015sqr_non_sse2 mov eax,DWORD [4+esp] mov edx,DWORD [8+esp] mov ecx,DWORD [12+esp] align 16 -L$016sqr_sse2_loop: +L$005sqr_sse2_loop: movd mm0,DWORD [edx] pmuludq mm0,mm0 lea edx,[4+edx] movq [eax],mm0 sub ecx,1 lea eax,[8+eax] - jnz NEAR L$016sqr_sse2_loop + jnz NEAR L$005sqr_sse2_loop emms ret -align 16 -L$015sqr_non_sse2: - push ebp - push ebx - push esi - push edi - ; - mov esi,DWORD [20+esp] - mov edi,DWORD [24+esp] - mov ebx,DWORD [28+esp] - and ebx,4294967288 - jz NEAR L$017sw_finish -L$018sw_loop: - ; Round 0 - mov eax,DWORD [edi] - mul eax - mov DWORD [esi],eax - mov DWORD [4+esi],edx - ; Round 4 - mov eax,DWORD [4+edi] - mul eax - mov DWORD [8+esi],eax - mov DWORD [12+esi],edx - ; Round 8 - mov eax,DWORD [8+edi] - mul eax - mov DWORD [16+esi],eax - mov DWORD [20+esi],edx - ; Round 12 - mov eax,DWORD [12+edi] - mul eax - mov DWORD [24+esi],eax - mov DWORD [28+esi],edx - ; Round 16 - mov eax,DWORD [16+edi] - mul eax - mov DWORD [32+esi],eax - mov DWORD [36+esi],edx - ; Round 20 - mov eax,DWORD [20+edi] - mul eax - mov DWORD [40+esi],eax - mov DWORD [44+esi],edx - ; Round 24 - mov eax,DWORD [24+edi] - mul eax - mov DWORD [48+esi],eax - mov DWORD [52+esi],edx - ; Round 28 - mov eax,DWORD [28+edi] - mul eax - mov DWORD [56+esi],eax - mov DWORD [60+esi],edx - ; - add edi,32 - add esi,64 - sub ebx,8 - jnz NEAR L$018sw_loop -L$017sw_finish: - mov ebx,DWORD [28+esp] - and ebx,7 - jz NEAR L$019sw_end - ; Tail Round 0 - mov eax,DWORD [edi] - mul eax - mov DWORD [esi],eax - dec ebx - mov DWORD [4+esi],edx - jz NEAR L$019sw_end - ; Tail Round 1 - mov eax,DWORD [4+edi] - mul eax - mov DWORD [8+esi],eax - dec ebx - mov DWORD [12+esi],edx - jz NEAR L$019sw_end - ; Tail Round 2 - mov eax,DWORD [8+edi] - mul eax - mov DWORD [16+esi],eax - dec ebx - mov DWORD [20+esi],edx - jz NEAR L$019sw_end - ; Tail Round 3 - mov eax,DWORD [12+edi] - mul eax - mov DWORD [24+esi],eax - dec ebx - mov DWORD [28+esi],edx - jz NEAR L$019sw_end - ; Tail Round 4 - mov eax,DWORD [16+edi] - mul eax - mov DWORD [32+esi],eax - dec ebx - mov DWORD [36+esi],edx - jz NEAR L$019sw_end - ; Tail Round 5 - mov eax,DWORD [20+edi] - mul eax - mov DWORD [40+esi],eax - dec ebx - mov DWORD [44+esi],edx - jz NEAR L$019sw_end - ; Tail Round 6 - mov eax,DWORD [24+edi] - mul eax - mov DWORD [48+esi],eax - mov DWORD [52+esi],edx -L$019sw_end: pop edi pop esi pop ebx @@ -629,8 +185,8 @@ L$_bn_add_words_begin: mov ebp,DWORD [32+esp] xor eax,eax and ebp,4294967288 - jz NEAR L$020aw_finish -L$021aw_loop: + jz NEAR L$006aw_finish +L$007aw_loop: ; Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -708,11 +264,11 @@ L$021aw_loop: add edi,32 add ebx,32 sub ebp,8 - jnz NEAR L$021aw_loop -L$020aw_finish: + jnz NEAR L$007aw_loop +L$006aw_finish: mov ebp,DWORD [32+esp] and ebp,7 - jz NEAR L$022aw_end + jz NEAR L$008aw_end ; Tail Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -723,7 +279,7 @@ L$020aw_finish: adc eax,0 dec ebp mov DWORD [ebx],ecx - jz NEAR L$022aw_end + jz NEAR L$008aw_end ; Tail Round 1 mov ecx,DWORD [4+esi] mov edx,DWORD [4+edi] @@ -734,7 +290,7 @@ L$020aw_finish: adc eax,0 dec ebp mov DWORD [4+ebx],ecx - jz NEAR L$022aw_end + jz NEAR L$008aw_end ; Tail Round 2 mov ecx,DWORD [8+esi] mov edx,DWORD [8+edi] @@ -745,7 +301,7 @@ L$020aw_finish: adc eax,0 dec ebp mov DWORD [8+ebx],ecx - jz NEAR L$022aw_end + jz NEAR L$008aw_end ; Tail Round 3 mov ecx,DWORD [12+esi] mov edx,DWORD [12+edi] @@ -756,7 +312,7 @@ L$020aw_finish: adc eax,0 dec ebp mov DWORD [12+ebx],ecx - jz NEAR L$022aw_end + jz NEAR L$008aw_end ; Tail Round 4 mov ecx,DWORD [16+esi] mov edx,DWORD [16+edi] @@ -767,7 +323,7 @@ L$020aw_finish: adc eax,0 dec ebp mov DWORD [16+ebx],ecx - jz NEAR L$022aw_end + jz NEAR L$008aw_end ; Tail Round 5 mov ecx,DWORD [20+esi] mov edx,DWORD [20+edi] @@ -778,7 +334,7 @@ L$020aw_finish: adc eax,0 dec ebp mov DWORD [20+ebx],ecx - jz NEAR L$022aw_end + jz NEAR L$008aw_end ; Tail Round 6 mov ecx,DWORD [24+esi] mov edx,DWORD [24+edi] @@ -788,7 +344,7 @@ L$020aw_finish: add ecx,edx adc eax,0 mov DWORD [24+ebx],ecx -L$022aw_end: +L$008aw_end: pop edi pop esi pop ebx @@ -809,8 +365,8 @@ L$_bn_sub_words_begin: mov ebp,DWORD [32+esp] xor eax,eax and ebp,4294967288 - jz NEAR L$023aw_finish -L$024aw_loop: + jz NEAR L$009aw_finish +L$010aw_loop: ; Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -888,11 +444,11 @@ L$024aw_loop: add edi,32 add ebx,32 sub ebp,8 - jnz NEAR L$024aw_loop -L$023aw_finish: + jnz NEAR L$010aw_loop +L$009aw_finish: mov ebp,DWORD [32+esp] and ebp,7 - jz NEAR L$025aw_end + jz NEAR L$011aw_end ; Tail Round 0 mov ecx,DWORD [esi] mov edx,DWORD [edi] @@ -903,7 +459,7 @@ L$023aw_finish: adc eax,0 dec ebp mov DWORD [ebx],ecx - jz NEAR L$025aw_end + jz NEAR L$011aw_end ; Tail Round 1 mov ecx,DWORD [4+esi] mov edx,DWORD [4+edi] @@ -914,7 +470,7 @@ L$023aw_finish: adc eax,0 dec ebp mov DWORD [4+ebx],ecx - jz NEAR L$025aw_end + jz NEAR L$011aw_end ; Tail Round 2 mov ecx,DWORD [8+esi] mov edx,DWORD [8+edi] @@ -925,7 +481,7 @@ L$023aw_finish: adc eax,0 dec ebp mov DWORD [8+ebx],ecx - jz NEAR L$025aw_end + jz NEAR L$011aw_end ; Tail Round 3 mov ecx,DWORD [12+esi] mov edx,DWORD [12+edi] @@ -936,7 +492,7 @@ L$023aw_finish: adc eax,0 dec ebp mov DWORD [12+ebx],ecx - jz NEAR L$025aw_end + jz NEAR L$011aw_end ; Tail Round 4 mov ecx,DWORD [16+esi] mov edx,DWORD [16+edi] @@ -947,7 +503,7 @@ L$023aw_finish: adc eax,0 dec ebp mov DWORD [16+ebx],ecx - jz NEAR L$025aw_end + jz NEAR L$011aw_end ; Tail Round 5 mov ecx,DWORD [20+esi] mov edx,DWORD [20+edi] @@ -958,7 +514,7 @@ L$023aw_finish: adc eax,0 dec ebp mov DWORD [20+ebx],ecx - jz NEAR L$025aw_end + jz NEAR L$011aw_end ; Tail Round 6 mov ecx,DWORD [24+esi] mov edx,DWORD [24+edi] @@ -968,14 +524,12 @@ L$023aw_finish: sub ecx,edx adc eax,0 mov DWORD [24+ebx],ecx -L$025aw_end: +L$011aw_end: pop edi pop esi pop ebx pop ebp ret -segment .bss -common _OPENSSL_ia32cap_P 16 %else ; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738 ret diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-ssse3-x86_64-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-ssse3-x86_64-win.asm index 84c5d40bd3..e0de962438 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-ssse3-x86_64-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-ssse3-x86_64-win.asm @@ -26,11 +26,12 @@ gcm_gmult_ssse3: $L$SEH_begin_gcm_gmult_ssse3_1: _CET_ENDBR sub rsp,40 -$L$SEH_prolog_gcm_gmult_ssse3_2: +$L$SEH_prologue_gcm_gmult_ssse3_2: movdqa XMMWORD[rsp],xmm6 -$L$SEH_prolog_gcm_gmult_ssse3_3: +$L$SEH_prologue_gcm_gmult_ssse3_3: movdqa XMMWORD[16+rsp],xmm10 -$L$SEH_prolog_gcm_gmult_ssse3_4: +$L$SEH_prologue_gcm_gmult_ssse3_4: +$L$SEH_endprologue_gcm_gmult_ssse3_5: movdqu xmm0,XMMWORD[rcx] movdqa xmm10,XMMWORD[$L$reverse_bytes] movdqa xmm2,XMMWORD[$L$low4_mask] @@ -210,7 +211,7 @@ DB 102,65,15,56,0,210 add rsp,40 ret -$L$SEH_end_gcm_gmult_ssse3_5: +$L$SEH_end_gcm_gmult_ssse3_6: @@ -225,13 +226,14 @@ gcm_ghash_ssse3: $L$SEH_begin_gcm_ghash_ssse3_1: _CET_ENDBR sub rsp,56 -$L$SEH_prolog_gcm_ghash_ssse3_2: +$L$SEH_prologue_gcm_ghash_ssse3_2: movdqa XMMWORD[rsp],xmm6 -$L$SEH_prolog_gcm_ghash_ssse3_3: +$L$SEH_prologue_gcm_ghash_ssse3_3: movdqa XMMWORD[16+rsp],xmm10 -$L$SEH_prolog_gcm_ghash_ssse3_4: +$L$SEH_prologue_gcm_ghash_ssse3_4: movdqa XMMWORD[32+rsp],xmm11 -$L$SEH_prolog_gcm_ghash_ssse3_5: +$L$SEH_prologue_gcm_ghash_ssse3_5: +$L$SEH_endprologue_gcm_ghash_ssse3_6: movdqu xmm0,XMMWORD[rcx] movdqa xmm10,XMMWORD[$L$reverse_bytes] movdqa xmm11,XMMWORD[$L$low4_mask] @@ -434,7 +436,7 @@ DB 102,65,15,56,0,194 add rsp,56 ret -$L$SEH_end_gcm_ghash_ssse3_6: +$L$SEH_end_gcm_ghash_ssse3_7: section .rdata rdata align=8 @@ -451,11 +453,11 @@ section .text section .pdata rdata align=4 ALIGN 4 DD $L$SEH_begin_gcm_gmult_ssse3_1 wrt ..imagebase - DD $L$SEH_end_gcm_gmult_ssse3_5 wrt ..imagebase + DD $L$SEH_end_gcm_gmult_ssse3_6 wrt ..imagebase DD $L$SEH_info_gcm_gmult_ssse3_0 wrt ..imagebase DD $L$SEH_begin_gcm_ghash_ssse3_1 wrt ..imagebase - DD $L$SEH_end_gcm_ghash_ssse3_6 wrt ..imagebase + DD $L$SEH_end_gcm_ghash_ssse3_7 wrt ..imagebase DD $L$SEH_info_gcm_ghash_ssse3_0 wrt ..imagebase @@ -463,34 +465,37 @@ section .xdata rdata align=8 ALIGN 4 $L$SEH_info_gcm_gmult_ssse3_0: DB 1 - DB $L$SEH_prolog_gcm_gmult_ssse3_4-$L$SEH_begin_gcm_gmult_ssse3_1 + DB $L$SEH_endprologue_gcm_gmult_ssse3_5-$L$SEH_begin_gcm_gmult_ssse3_1 DB 5 DB 0 - DB $L$SEH_prolog_gcm_gmult_ssse3_4-$L$SEH_begin_gcm_gmult_ssse3_1 + DB $L$SEH_prologue_gcm_gmult_ssse3_4-$L$SEH_begin_gcm_gmult_ssse3_1 DB 168 DW 1 - DB $L$SEH_prolog_gcm_gmult_ssse3_3-$L$SEH_begin_gcm_gmult_ssse3_1 + DB $L$SEH_prologue_gcm_gmult_ssse3_3-$L$SEH_begin_gcm_gmult_ssse3_1 DB 104 DW 0 - DB $L$SEH_prolog_gcm_gmult_ssse3_2-$L$SEH_begin_gcm_gmult_ssse3_1 + DB $L$SEH_prologue_gcm_gmult_ssse3_2-$L$SEH_begin_gcm_gmult_ssse3_1 DB 66 + DW 0 $L$SEH_info_gcm_ghash_ssse3_0: DB 1 - DB $L$SEH_prolog_gcm_ghash_ssse3_5-$L$SEH_begin_gcm_ghash_ssse3_1 + DB $L$SEH_endprologue_gcm_ghash_ssse3_6-$L$SEH_begin_gcm_ghash_ssse3_1 DB 7 DB 0 - DB $L$SEH_prolog_gcm_ghash_ssse3_5-$L$SEH_begin_gcm_ghash_ssse3_1 + DB $L$SEH_prologue_gcm_ghash_ssse3_5-$L$SEH_begin_gcm_ghash_ssse3_1 DB 184 DW 2 - DB $L$SEH_prolog_gcm_ghash_ssse3_4-$L$SEH_begin_gcm_ghash_ssse3_1 + DB $L$SEH_prologue_gcm_ghash_ssse3_4-$L$SEH_begin_gcm_ghash_ssse3_1 DB 168 DW 1 - DB $L$SEH_prolog_gcm_ghash_ssse3_3-$L$SEH_begin_gcm_ghash_ssse3_1 + DB $L$SEH_prologue_gcm_ghash_ssse3_3-$L$SEH_begin_gcm_ghash_ssse3_1 DB 104 DW 0 - DB $L$SEH_prolog_gcm_ghash_ssse3_2-$L$SEH_begin_gcm_ghash_ssse3_1 + DB $L$SEH_prologue_gcm_ghash_ssse3_2-$L$SEH_begin_gcm_ghash_ssse3_1 DB 98 + + DW 0 %else ; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738 ret diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-apple.S index 909d659661..4961298827 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-apple.S @@ -612,6 +612,7 @@ L$done: .p2align 5 _gcm_init_avx: + _CET_ENDBR vzeroupper @@ -734,6 +735,7 @@ _CET_ENDBR .p2align 5 _gcm_ghash_avx: + _CET_ENDBR vzeroupper diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-linux.S index 22429a67b4..e00bb9fda5 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-linux.S @@ -612,6 +612,7 @@ _CET_ENDBR .align 32 gcm_init_avx: .cfi_startproc + _CET_ENDBR vzeroupper @@ -734,6 +735,7 @@ _CET_ENDBR .align 32 gcm_ghash_avx: .cfi_startproc + _CET_ENDBR vzeroupper diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-win.asm index 41b189a2be..b5416b3236 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/ghash-x86_64-win.asm @@ -22,9 +22,10 @@ $L$SEH_begin_gcm_init_clmul_1: _CET_ENDBR $L$_init_clmul: sub rsp,0x18 -$L$SEH_prolog_gcm_init_clmul_2: +$L$SEH_prologue_gcm_init_clmul_2: movaps XMMWORD[rsp],xmm6 -$L$SEH_prolog_gcm_init_clmul_3: +$L$SEH_prologue_gcm_init_clmul_3: +$L$SEH_endprologue_gcm_init_clmul_4: movdqu xmm2,XMMWORD[rdx] pshufd xmm2,xmm2,78 @@ -178,7 +179,7 @@ DB 102,15,58,15,227,8 lea rsp,[24+rsp] ret -$L$SEH_end_gcm_init_clmul_4: +$L$SEH_end_gcm_init_clmul_5: global gcm_gmult_clmul @@ -244,27 +245,28 @@ _CET_ENDBR $L$_ghash_clmul: lea rax,[((-136))+rsp] lea rsp,[((-32))+rax] -$L$SEH_prolog_gcm_ghash_clmul_2: +$L$SEH_prologue_gcm_ghash_clmul_2: movaps XMMWORD[(-32)+rax],xmm6 -$L$SEH_prolog_gcm_ghash_clmul_3: +$L$SEH_prologue_gcm_ghash_clmul_3: movaps XMMWORD[(-16)+rax],xmm7 -$L$SEH_prolog_gcm_ghash_clmul_4: +$L$SEH_prologue_gcm_ghash_clmul_4: movaps XMMWORD[rax],xmm8 -$L$SEH_prolog_gcm_ghash_clmul_5: +$L$SEH_prologue_gcm_ghash_clmul_5: movaps XMMWORD[16+rax],xmm9 -$L$SEH_prolog_gcm_ghash_clmul_6: +$L$SEH_prologue_gcm_ghash_clmul_6: movaps XMMWORD[32+rax],xmm10 -$L$SEH_prolog_gcm_ghash_clmul_7: +$L$SEH_prologue_gcm_ghash_clmul_7: movaps XMMWORD[48+rax],xmm11 -$L$SEH_prolog_gcm_ghash_clmul_8: +$L$SEH_prologue_gcm_ghash_clmul_8: movaps XMMWORD[64+rax],xmm12 -$L$SEH_prolog_gcm_ghash_clmul_9: +$L$SEH_prologue_gcm_ghash_clmul_9: movaps XMMWORD[80+rax],xmm13 -$L$SEH_prolog_gcm_ghash_clmul_10: +$L$SEH_prologue_gcm_ghash_clmul_10: movaps XMMWORD[96+rax],xmm14 -$L$SEH_prolog_gcm_ghash_clmul_11: +$L$SEH_prologue_gcm_ghash_clmul_11: movaps XMMWORD[112+rax],xmm15 -$L$SEH_prolog_gcm_ghash_clmul_12: +$L$SEH_prologue_gcm_ghash_clmul_12: +$L$SEH_endprologue_gcm_ghash_clmul_13: movdqa xmm10,XMMWORD[$L$bswap_mask] movdqu xmm0,XMMWORD[rcx] @@ -649,19 +651,20 @@ DB 102,65,15,56,0,194 lea rsp,[168+rsp] ret -$L$SEH_end_gcm_ghash_clmul_13: +$L$SEH_end_gcm_ghash_clmul_14: global gcm_init_avx ALIGN 32 gcm_init_avx: -_CET_ENDBR $L$SEH_begin_gcm_init_avx_1: +_CET_ENDBR sub rsp,0x18 -$L$SEH_prolog_gcm_init_avx_2: +$L$SEH_prologue_gcm_init_avx_2: movaps XMMWORD[rsp],xmm6 -$L$SEH_prolog_gcm_init_avx_3: +$L$SEH_prologue_gcm_init_avx_3: +$L$SEH_endprologue_gcm_init_avx_4: vzeroupper vmovdqu xmm2,XMMWORD[rdx] @@ -766,7 +769,7 @@ $L$init_start_avx: movaps xmm6,XMMWORD[rsp] lea rsp,[24+rsp] ret -$L$SEH_end_gcm_init_avx_4: +$L$SEH_end_gcm_init_avx_5: global gcm_gmult_avx @@ -783,31 +786,32 @@ global gcm_ghash_avx ALIGN 32 gcm_ghash_avx: -_CET_ENDBR $L$SEH_begin_gcm_ghash_avx_1: +_CET_ENDBR lea rax,[((-136))+rsp] lea rsp,[((-32))+rax] -$L$SEH_prolog_gcm_ghash_avx_2: +$L$SEH_prologue_gcm_ghash_avx_2: movaps XMMWORD[(-32)+rax],xmm6 -$L$SEH_prolog_gcm_ghash_avx_3: +$L$SEH_prologue_gcm_ghash_avx_3: movaps XMMWORD[(-16)+rax],xmm7 -$L$SEH_prolog_gcm_ghash_avx_4: +$L$SEH_prologue_gcm_ghash_avx_4: movaps XMMWORD[rax],xmm8 -$L$SEH_prolog_gcm_ghash_avx_5: +$L$SEH_prologue_gcm_ghash_avx_5: movaps XMMWORD[16+rax],xmm9 -$L$SEH_prolog_gcm_ghash_avx_6: +$L$SEH_prologue_gcm_ghash_avx_6: movaps XMMWORD[32+rax],xmm10 -$L$SEH_prolog_gcm_ghash_avx_7: +$L$SEH_prologue_gcm_ghash_avx_7: movaps XMMWORD[48+rax],xmm11 -$L$SEH_prolog_gcm_ghash_avx_8: +$L$SEH_prologue_gcm_ghash_avx_8: movaps XMMWORD[64+rax],xmm12 -$L$SEH_prolog_gcm_ghash_avx_9: +$L$SEH_prologue_gcm_ghash_avx_9: movaps XMMWORD[80+rax],xmm13 -$L$SEH_prolog_gcm_ghash_avx_10: +$L$SEH_prologue_gcm_ghash_avx_10: movaps XMMWORD[96+rax],xmm14 -$L$SEH_prolog_gcm_ghash_avx_11: +$L$SEH_prologue_gcm_ghash_avx_11: movaps XMMWORD[112+rax],xmm15 -$L$SEH_prolog_gcm_ghash_avx_12: +$L$SEH_prologue_gcm_ghash_avx_12: +$L$SEH_endprologue_gcm_ghash_avx_13: vzeroupper vmovdqu xmm10,XMMWORD[rcx] @@ -1191,7 +1195,7 @@ $L$tail_no_xor_avx: lea rsp,[168+rsp] ret -$L$SEH_end_gcm_ghash_avx_13: +$L$SEH_end_gcm_ghash_avx_14: section .rdata rdata align=8 ALIGN 64 @@ -1213,19 +1217,19 @@ section .text section .pdata rdata align=4 ALIGN 4 DD $L$SEH_begin_gcm_init_clmul_1 wrt ..imagebase - DD $L$SEH_end_gcm_init_clmul_4 wrt ..imagebase + DD $L$SEH_end_gcm_init_clmul_5 wrt ..imagebase DD $L$SEH_info_gcm_init_clmul_0 wrt ..imagebase DD $L$SEH_begin_gcm_ghash_clmul_1 wrt ..imagebase - DD $L$SEH_end_gcm_ghash_clmul_13 wrt ..imagebase + DD $L$SEH_end_gcm_ghash_clmul_14 wrt ..imagebase DD $L$SEH_info_gcm_ghash_clmul_0 wrt ..imagebase DD $L$SEH_begin_gcm_init_avx_1 wrt ..imagebase - DD $L$SEH_end_gcm_init_avx_4 wrt ..imagebase + DD $L$SEH_end_gcm_init_avx_5 wrt ..imagebase DD $L$SEH_info_gcm_init_avx_0 wrt ..imagebase DD $L$SEH_begin_gcm_ghash_avx_1 wrt ..imagebase - DD $L$SEH_end_gcm_ghash_avx_13 wrt ..imagebase + DD $L$SEH_end_gcm_ghash_avx_14 wrt ..imagebase DD $L$SEH_info_gcm_ghash_avx_0 wrt ..imagebase @@ -1233,101 +1237,103 @@ section .xdata rdata align=8 ALIGN 4 $L$SEH_info_gcm_init_clmul_0: DB 1 - DB $L$SEH_prolog_gcm_init_clmul_3-$L$SEH_begin_gcm_init_clmul_1 + DB $L$SEH_endprologue_gcm_init_clmul_4-$L$SEH_begin_gcm_init_clmul_1 DB 3 DB 0 - DB $L$SEH_prolog_gcm_init_clmul_3-$L$SEH_begin_gcm_init_clmul_1 + DB $L$SEH_prologue_gcm_init_clmul_3-$L$SEH_begin_gcm_init_clmul_1 DB 104 DW 0 - DB $L$SEH_prolog_gcm_init_clmul_2-$L$SEH_begin_gcm_init_clmul_1 + DB $L$SEH_prologue_gcm_init_clmul_2-$L$SEH_begin_gcm_init_clmul_1 DB 34 + DW 0 $L$SEH_info_gcm_ghash_clmul_0: DB 1 - DB $L$SEH_prolog_gcm_ghash_clmul_12-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_endprologue_gcm_ghash_clmul_13-$L$SEH_begin_gcm_ghash_clmul_1 DB 22 DB 0 - DB $L$SEH_prolog_gcm_ghash_clmul_12-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_12-$L$SEH_begin_gcm_ghash_clmul_1 DB 248 DW 9 - DB $L$SEH_prolog_gcm_ghash_clmul_11-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_11-$L$SEH_begin_gcm_ghash_clmul_1 DB 232 DW 8 - DB $L$SEH_prolog_gcm_ghash_clmul_10-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_10-$L$SEH_begin_gcm_ghash_clmul_1 DB 216 DW 7 - DB $L$SEH_prolog_gcm_ghash_clmul_9-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_9-$L$SEH_begin_gcm_ghash_clmul_1 DB 200 DW 6 - DB $L$SEH_prolog_gcm_ghash_clmul_8-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_8-$L$SEH_begin_gcm_ghash_clmul_1 DB 184 DW 5 - DB $L$SEH_prolog_gcm_ghash_clmul_7-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_7-$L$SEH_begin_gcm_ghash_clmul_1 DB 168 DW 4 - DB $L$SEH_prolog_gcm_ghash_clmul_6-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_6-$L$SEH_begin_gcm_ghash_clmul_1 DB 152 DW 3 - DB $L$SEH_prolog_gcm_ghash_clmul_5-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_5-$L$SEH_begin_gcm_ghash_clmul_1 DB 136 DW 2 - DB $L$SEH_prolog_gcm_ghash_clmul_4-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_4-$L$SEH_begin_gcm_ghash_clmul_1 DB 120 DW 1 - DB $L$SEH_prolog_gcm_ghash_clmul_3-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_3-$L$SEH_begin_gcm_ghash_clmul_1 DB 104 DW 0 - DB $L$SEH_prolog_gcm_ghash_clmul_2-$L$SEH_begin_gcm_ghash_clmul_1 + DB $L$SEH_prologue_gcm_ghash_clmul_2-$L$SEH_begin_gcm_ghash_clmul_1 DB 1 DW 21 $L$SEH_info_gcm_init_avx_0: DB 1 - DB $L$SEH_prolog_gcm_init_avx_3-$L$SEH_begin_gcm_init_avx_1 + DB $L$SEH_endprologue_gcm_init_avx_4-$L$SEH_begin_gcm_init_avx_1 DB 3 DB 0 - DB $L$SEH_prolog_gcm_init_avx_3-$L$SEH_begin_gcm_init_avx_1 + DB $L$SEH_prologue_gcm_init_avx_3-$L$SEH_begin_gcm_init_avx_1 DB 104 DW 0 - DB $L$SEH_prolog_gcm_init_avx_2-$L$SEH_begin_gcm_init_avx_1 + DB $L$SEH_prologue_gcm_init_avx_2-$L$SEH_begin_gcm_init_avx_1 DB 34 + DW 0 $L$SEH_info_gcm_ghash_avx_0: DB 1 - DB $L$SEH_prolog_gcm_ghash_avx_12-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_endprologue_gcm_ghash_avx_13-$L$SEH_begin_gcm_ghash_avx_1 DB 22 DB 0 - DB $L$SEH_prolog_gcm_ghash_avx_12-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_12-$L$SEH_begin_gcm_ghash_avx_1 DB 248 DW 9 - DB $L$SEH_prolog_gcm_ghash_avx_11-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_11-$L$SEH_begin_gcm_ghash_avx_1 DB 232 DW 8 - DB $L$SEH_prolog_gcm_ghash_avx_10-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_10-$L$SEH_begin_gcm_ghash_avx_1 DB 216 DW 7 - DB $L$SEH_prolog_gcm_ghash_avx_9-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_9-$L$SEH_begin_gcm_ghash_avx_1 DB 200 DW 6 - DB $L$SEH_prolog_gcm_ghash_avx_8-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_8-$L$SEH_begin_gcm_ghash_avx_1 DB 184 DW 5 - DB $L$SEH_prolog_gcm_ghash_avx_7-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_7-$L$SEH_begin_gcm_ghash_avx_1 DB 168 DW 4 - DB $L$SEH_prolog_gcm_ghash_avx_6-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_6-$L$SEH_begin_gcm_ghash_avx_1 DB 152 DW 3 - DB $L$SEH_prolog_gcm_ghash_avx_5-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_5-$L$SEH_begin_gcm_ghash_avx_1 DB 136 DW 2 - DB $L$SEH_prolog_gcm_ghash_avx_4-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_4-$L$SEH_begin_gcm_ghash_avx_1 DB 120 DW 1 - DB $L$SEH_prolog_gcm_ghash_avx_3-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_3-$L$SEH_begin_gcm_ghash_avx_1 DB 104 DW 0 - DB $L$SEH_prolog_gcm_ghash_avx_2-$L$SEH_begin_gcm_ghash_avx_1 + DB $L$SEH_prologue_gcm_ghash_avx_2-$L$SEH_begin_gcm_ghash_avx_1 DB 1 DW 21 %else diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-apple.S index cfdeac1211..785eaf5b65 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-apple.S @@ -5,11 +5,11 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__APPLE__) .text -.globl _sha512_block_data_order -.private_extern _sha512_block_data_order +.globl _sha512_block_data_order_nohw +.private_extern _sha512_block_data_order_nohw .align 4 -_sha512_block_data_order: -L_sha512_block_data_order_begin: +_sha512_block_data_order_nohw: +L_sha512_block_data_order_nohw_begin: pushl %ebp pushl %ebx pushl %esi @@ -21,7 +21,7 @@ L_sha512_block_data_order_begin: call L000pic_point L000pic_point: popl %ebp - leal L001K512-L000pic_point(%ebp),%ebp + leal LK512-L000pic_point(%ebp),%ebp subl $16,%esp andl $-64,%esp shll $7,%eax @@ -30,28 +30,18 @@ L000pic_point: movl %edi,4(%esp) movl %eax,8(%esp) movl %ebx,12(%esp) - movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L001K512(%ebp),%edx - movl (%edx),%ecx - testl $67108864,%ecx - jz L002loop_x86 - movl 4(%edx),%edx movq (%esi),%mm0 - andl $16777216,%ecx movq 8(%esi),%mm1 - andl $512,%edx movq 16(%esi),%mm2 - orl %edx,%ecx movq 24(%esi),%mm3 movq 32(%esi),%mm4 movq 40(%esi),%mm5 movq 48(%esi),%mm6 movq 56(%esi),%mm7 - cmpl $16777728,%ecx - je L003SSSE3 subl $80,%esp - jmp L004loop_sse2 + jmp L001loop_sse2 .align 4,0x90 -L004loop_sse2: +L001loop_sse2: movq %mm1,8(%esp) movq %mm2,16(%esp) movq %mm3,24(%esp) @@ -66,9 +56,9 @@ L004loop_sse2: movl $15,%edx bswap %eax bswap %ebx - jmp L00500_14_sse2 + jmp L00200_14_sse2 .align 4,0x90 -L00500_14_sse2: +L00200_14_sse2: movd %eax,%mm1 movl (%edi),%eax movd %ebx,%mm7 @@ -129,7 +119,7 @@ L00500_14_sse2: paddq %mm6,%mm3 movq 48(%esp),%mm6 decl %edx - jnz L00500_14_sse2 + jnz L00200_14_sse2 movd %eax,%mm1 movd %ebx,%mm7 punpckldq %mm1,%mm7 @@ -185,9 +175,9 @@ L00500_14_sse2: paddq %mm6,%mm3 pxor %mm0,%mm0 movl $32,%edx - jmp L00616_79_sse2 + jmp L00316_79_sse2 .align 4,0x90 -L00616_79_sse2: +L00316_79_sse2: movq 88(%esp),%mm5 movq %mm7,%mm1 psrlq $1,%mm7 @@ -341,7 +331,7 @@ L00616_79_sse2: paddq %mm6,%mm0 addl $8,%ebp decl %edx - jnz L00616_79_sse2 + jnz L00316_79_sse2 paddq %mm3,%mm0 movq 8(%esp),%mm1 movq 24(%esp),%mm3 @@ -369,7 +359,7 @@ L00616_79_sse2: leal (%esp,%eax,1),%esp subl %eax,%ebp cmpl 88(%esp),%edi - jb L004loop_sse2 + jb L001loop_sse2 movl 92(%esp),%esp emms popl %edi @@ -377,8 +367,39 @@ L00616_79_sse2: popl %ebx popl %ebp ret -.align 5,0x90 -L003SSSE3: +.globl _sha512_block_data_order_ssse3 +.private_extern _sha512_block_data_order_ssse3 +.align 4 +_sha512_block_data_order_ssse3: +L_sha512_block_data_order_ssse3_begin: + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + movl 20(%esp),%esi + movl 24(%esp),%edi + movl 28(%esp),%eax + movl %esp,%ebx + call L004pic_point +L004pic_point: + popl %ebp + leal LK512-L004pic_point(%ebp),%ebp + subl $16,%esp + andl $-64,%esp + shll $7,%eax + addl %edi,%eax + movl %esi,(%esp) + movl %edi,4(%esp) + movl %eax,8(%esp) + movl %ebx,12(%esp) + movq (%esi),%mm0 + movq 8(%esi),%mm1 + movq 16(%esi),%mm2 + movq 24(%esi),%mm3 + movq 32(%esi),%mm4 + movq 40(%esi),%mm5 + movq 48(%esi),%mm6 + movq 56(%esi),%mm7 leal -64(%esp),%edx subl $256,%esp movdqa 640(%ebp),%xmm1 @@ -435,7 +456,7 @@ L003SSSE3: movdqa %xmm2,-16(%edx) nop .align 5,0x90 -L007loop_ssse3: +L005loop_ssse3: movdqa 16(%edx),%xmm2 movdqa %xmm3,48(%edx) leal 128(%ebp),%ebp @@ -452,9 +473,9 @@ L007loop_ssse3: pxor %mm1,%mm2 movq %mm7,56(%esp) pxor %mm3,%mm3 - jmp L00800_47_ssse3 + jmp L00600_47_ssse3 .align 5,0x90 -L00800_47_ssse3: +L00600_47_ssse3: movdqa %xmm5,%xmm3 movdqa %xmm2,%xmm1 .byte 102,15,58,15,208,8 @@ -1473,7 +1494,7 @@ L00800_47_ssse3: movdqa %xmm1,-16(%edx) leal 128(%ebp),%ebp decl %ecx - jnz L00800_47_ssse3 + jnz L00600_47_ssse3 movdqa (%ebp),%xmm1 leal -640(%ebp),%ebp movdqu (%ebx),%xmm0 @@ -2285,7 +2306,7 @@ L00800_47_ssse3: movq %mm6,48(%esi) movq %mm7,56(%esi) cmpl %eax,%edi - jb L007loop_ssse3 + jb L005loop_ssse3 movl 76(%edx),%esp emms popl %edi @@ -2293,456 +2314,8 @@ L00800_47_ssse3: popl %ebx popl %ebp ret -.align 4,0x90 -L002loop_x86: - movl (%edi),%eax - movl 4(%edi),%ebx - movl 8(%edi),%ecx - movl 12(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 16(%edi),%eax - movl 20(%edi),%ebx - movl 24(%edi),%ecx - movl 28(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 32(%edi),%eax - movl 36(%edi),%ebx - movl 40(%edi),%ecx - movl 44(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 48(%edi),%eax - movl 52(%edi),%ebx - movl 56(%edi),%ecx - movl 60(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 64(%edi),%eax - movl 68(%edi),%ebx - movl 72(%edi),%ecx - movl 76(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 80(%edi),%eax - movl 84(%edi),%ebx - movl 88(%edi),%ecx - movl 92(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 96(%edi),%eax - movl 100(%edi),%ebx - movl 104(%edi),%ecx - movl 108(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 112(%edi),%eax - movl 116(%edi),%ebx - movl 120(%edi),%ecx - movl 124(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - addl $128,%edi - subl $72,%esp - movl %edi,204(%esp) - leal 8(%esp),%edi - movl $16,%ecx -.long 2784229001 -.align 4,0x90 -L00900_15_x86: - movl 40(%esp),%ecx - movl 44(%esp),%edx - movl %ecx,%esi - shrl $9,%ecx - movl %edx,%edi - shrl $9,%edx - movl %ecx,%ebx - shll $14,%esi - movl %edx,%eax - shll $14,%edi - xorl %esi,%ebx - shrl $5,%ecx - xorl %edi,%eax - shrl $5,%edx - xorl %ecx,%eax - shll $4,%esi - xorl %edx,%ebx - shll $4,%edi - xorl %esi,%ebx - shrl $4,%ecx - xorl %edi,%eax - shrl $4,%edx - xorl %ecx,%eax - shll $5,%esi - xorl %edx,%ebx - shll $5,%edi - xorl %esi,%eax - xorl %edi,%ebx - movl 48(%esp),%ecx - movl 52(%esp),%edx - movl 56(%esp),%esi - movl 60(%esp),%edi - addl 64(%esp),%eax - adcl 68(%esp),%ebx - xorl %esi,%ecx - xorl %edi,%edx - andl 40(%esp),%ecx - andl 44(%esp),%edx - addl 192(%esp),%eax - adcl 196(%esp),%ebx - xorl %esi,%ecx - xorl %edi,%edx - movl (%ebp),%esi - movl 4(%ebp),%edi - addl %ecx,%eax - adcl %edx,%ebx - movl 32(%esp),%ecx - movl 36(%esp),%edx - addl %esi,%eax - adcl %edi,%ebx - movl %eax,(%esp) - movl %ebx,4(%esp) - addl %ecx,%eax - adcl %edx,%ebx - movl 8(%esp),%ecx - movl 12(%esp),%edx - movl %eax,32(%esp) - movl %ebx,36(%esp) - movl %ecx,%esi - shrl $2,%ecx - movl %edx,%edi - shrl $2,%edx - movl %ecx,%ebx - shll $4,%esi - movl %edx,%eax - shll $4,%edi - xorl %esi,%ebx - shrl $5,%ecx - xorl %edi,%eax - shrl $5,%edx - xorl %ecx,%ebx - shll $21,%esi - xorl %edx,%eax - shll $21,%edi - xorl %esi,%eax - shrl $21,%ecx - xorl %edi,%ebx - shrl $21,%edx - xorl %ecx,%eax - shll $5,%esi - xorl %edx,%ebx - shll $5,%edi - xorl %esi,%eax - xorl %edi,%ebx - movl 8(%esp),%ecx - movl 12(%esp),%edx - movl 16(%esp),%esi - movl 20(%esp),%edi - addl (%esp),%eax - adcl 4(%esp),%ebx - orl %esi,%ecx - orl %edi,%edx - andl 24(%esp),%ecx - andl 28(%esp),%edx - andl 8(%esp),%esi - andl 12(%esp),%edi - orl %esi,%ecx - orl %edi,%edx - addl %ecx,%eax - adcl %edx,%ebx - movl %eax,(%esp) - movl %ebx,4(%esp) - movb (%ebp),%dl - subl $8,%esp - leal 8(%ebp),%ebp - cmpb $148,%dl - jne L00900_15_x86 -.align 4,0x90 -L01016_79_x86: - movl 312(%esp),%ecx - movl 316(%esp),%edx - movl %ecx,%esi - shrl $1,%ecx - movl %edx,%edi - shrl $1,%edx - movl %ecx,%eax - shll $24,%esi - movl %edx,%ebx - shll $24,%edi - xorl %esi,%ebx - shrl $6,%ecx - xorl %edi,%eax - shrl $6,%edx - xorl %ecx,%eax - shll $7,%esi - xorl %edx,%ebx - shll $1,%edi - xorl %esi,%ebx - shrl $1,%ecx - xorl %edi,%eax - shrl $1,%edx - xorl %ecx,%eax - shll $6,%edi - xorl %edx,%ebx - xorl %edi,%eax - movl %eax,(%esp) - movl %ebx,4(%esp) - movl 208(%esp),%ecx - movl 212(%esp),%edx - movl %ecx,%esi - shrl $6,%ecx - movl %edx,%edi - shrl $6,%edx - movl %ecx,%eax - shll $3,%esi - movl %edx,%ebx - shll $3,%edi - xorl %esi,%eax - shrl $13,%ecx - xorl %edi,%ebx - shrl $13,%edx - xorl %ecx,%eax - shll $10,%esi - xorl %edx,%ebx - shll $10,%edi - xorl %esi,%ebx - shrl $10,%ecx - xorl %edi,%eax - shrl $10,%edx - xorl %ecx,%ebx - shll $13,%edi - xorl %edx,%eax - xorl %edi,%eax - movl 320(%esp),%ecx - movl 324(%esp),%edx - addl (%esp),%eax - adcl 4(%esp),%ebx - movl 248(%esp),%esi - movl 252(%esp),%edi - addl %ecx,%eax - adcl %edx,%ebx - addl %esi,%eax - adcl %edi,%ebx - movl %eax,192(%esp) - movl %ebx,196(%esp) - movl 40(%esp),%ecx - movl 44(%esp),%edx - movl %ecx,%esi - shrl $9,%ecx - movl %edx,%edi - shrl $9,%edx - movl %ecx,%ebx - shll $14,%esi - movl %edx,%eax - shll $14,%edi - xorl %esi,%ebx - shrl $5,%ecx - xorl %edi,%eax - shrl $5,%edx - xorl %ecx,%eax - shll $4,%esi - xorl %edx,%ebx - shll $4,%edi - xorl %esi,%ebx - shrl $4,%ecx - xorl %edi,%eax - shrl $4,%edx - xorl %ecx,%eax - shll $5,%esi - xorl %edx,%ebx - shll $5,%edi - xorl %esi,%eax - xorl %edi,%ebx - movl 48(%esp),%ecx - movl 52(%esp),%edx - movl 56(%esp),%esi - movl 60(%esp),%edi - addl 64(%esp),%eax - adcl 68(%esp),%ebx - xorl %esi,%ecx - xorl %edi,%edx - andl 40(%esp),%ecx - andl 44(%esp),%edx - addl 192(%esp),%eax - adcl 196(%esp),%ebx - xorl %esi,%ecx - xorl %edi,%edx - movl (%ebp),%esi - movl 4(%ebp),%edi - addl %ecx,%eax - adcl %edx,%ebx - movl 32(%esp),%ecx - movl 36(%esp),%edx - addl %esi,%eax - adcl %edi,%ebx - movl %eax,(%esp) - movl %ebx,4(%esp) - addl %ecx,%eax - adcl %edx,%ebx - movl 8(%esp),%ecx - movl 12(%esp),%edx - movl %eax,32(%esp) - movl %ebx,36(%esp) - movl %ecx,%esi - shrl $2,%ecx - movl %edx,%edi - shrl $2,%edx - movl %ecx,%ebx - shll $4,%esi - movl %edx,%eax - shll $4,%edi - xorl %esi,%ebx - shrl $5,%ecx - xorl %edi,%eax - shrl $5,%edx - xorl %ecx,%ebx - shll $21,%esi - xorl %edx,%eax - shll $21,%edi - xorl %esi,%eax - shrl $21,%ecx - xorl %edi,%ebx - shrl $21,%edx - xorl %ecx,%eax - shll $5,%esi - xorl %edx,%ebx - shll $5,%edi - xorl %esi,%eax - xorl %edi,%ebx - movl 8(%esp),%ecx - movl 12(%esp),%edx - movl 16(%esp),%esi - movl 20(%esp),%edi - addl (%esp),%eax - adcl 4(%esp),%ebx - orl %esi,%ecx - orl %edi,%edx - andl 24(%esp),%ecx - andl 28(%esp),%edx - andl 8(%esp),%esi - andl 12(%esp),%edi - orl %esi,%ecx - orl %edi,%edx - addl %ecx,%eax - adcl %edx,%ebx - movl %eax,(%esp) - movl %ebx,4(%esp) - movb (%ebp),%dl - subl $8,%esp - leal 8(%ebp),%ebp - cmpb $23,%dl - jne L01016_79_x86 - movl 840(%esp),%esi - movl 844(%esp),%edi - movl (%esi),%eax - movl 4(%esi),%ebx - movl 8(%esi),%ecx - movl 12(%esi),%edx - addl 8(%esp),%eax - adcl 12(%esp),%ebx - movl %eax,(%esi) - movl %ebx,4(%esi) - addl 16(%esp),%ecx - adcl 20(%esp),%edx - movl %ecx,8(%esi) - movl %edx,12(%esi) - movl 16(%esi),%eax - movl 20(%esi),%ebx - movl 24(%esi),%ecx - movl 28(%esi),%edx - addl 24(%esp),%eax - adcl 28(%esp),%ebx - movl %eax,16(%esi) - movl %ebx,20(%esi) - addl 32(%esp),%ecx - adcl 36(%esp),%edx - movl %ecx,24(%esi) - movl %edx,28(%esi) - movl 32(%esi),%eax - movl 36(%esi),%ebx - movl 40(%esi),%ecx - movl 44(%esi),%edx - addl 40(%esp),%eax - adcl 44(%esp),%ebx - movl %eax,32(%esi) - movl %ebx,36(%esi) - addl 48(%esp),%ecx - adcl 52(%esp),%edx - movl %ecx,40(%esi) - movl %edx,44(%esi) - movl 48(%esi),%eax - movl 52(%esi),%ebx - movl 56(%esi),%ecx - movl 60(%esi),%edx - addl 56(%esp),%eax - adcl 60(%esp),%ebx - movl %eax,48(%esi) - movl %ebx,52(%esi) - addl 64(%esp),%ecx - adcl 68(%esp),%edx - movl %ecx,56(%esi) - movl %edx,60(%esi) - addl $840,%esp - subl $640,%ebp - cmpl 8(%esp),%edi - jb L002loop_x86 - movl 12(%esp),%esp - popl %edi - popl %esi - popl %ebx - popl %ebp - ret .align 6,0x90 -L001K512: +LK512: .long 3609767458,1116352408 .long 602891725,1899447441 .long 3964484399,3049323471 @@ -2830,8 +2403,4 @@ L001K512: .byte 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97 .byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103 .byte 62,0 -.section __IMPORT,__pointers,non_lazy_symbol_pointers -L_OPENSSL_ia32cap_P$non_lazy_ptr: -.indirect_symbol _OPENSSL_ia32cap_P -.long 0 #endif // !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__APPLE__) diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-linux.S index bb2884d08d..e82bd00f6f 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-linux.S @@ -5,12 +5,12 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__ELF__) .text -.globl sha512_block_data_order -.hidden sha512_block_data_order -.type sha512_block_data_order,@function +.globl sha512_block_data_order_nohw +.hidden sha512_block_data_order_nohw +.type sha512_block_data_order_nohw,@function .align 16 -sha512_block_data_order: -.L_sha512_block_data_order_begin: +sha512_block_data_order_nohw: +.L_sha512_block_data_order_nohw_begin: pushl %ebp pushl %ebx pushl %esi @@ -22,7 +22,7 @@ sha512_block_data_order: call .L000pic_point .L000pic_point: popl %ebp - leal .L001K512-.L000pic_point(%ebp),%ebp + leal .LK512-.L000pic_point(%ebp),%ebp subl $16,%esp andl $-64,%esp shll $7,%eax @@ -31,28 +31,18 @@ sha512_block_data_order: movl %edi,4(%esp) movl %eax,8(%esp) movl %ebx,12(%esp) - leal OPENSSL_ia32cap_P-.L001K512(%ebp),%edx - movl (%edx),%ecx - testl $67108864,%ecx - jz .L002loop_x86 - movl 4(%edx),%edx movq (%esi),%mm0 - andl $16777216,%ecx movq 8(%esi),%mm1 - andl $512,%edx movq 16(%esi),%mm2 - orl %edx,%ecx movq 24(%esi),%mm3 movq 32(%esi),%mm4 movq 40(%esi),%mm5 movq 48(%esi),%mm6 movq 56(%esi),%mm7 - cmpl $16777728,%ecx - je .L003SSSE3 subl $80,%esp - jmp .L004loop_sse2 + jmp .L001loop_sse2 .align 16 -.L004loop_sse2: +.L001loop_sse2: movq %mm1,8(%esp) movq %mm2,16(%esp) movq %mm3,24(%esp) @@ -67,9 +57,9 @@ sha512_block_data_order: movl $15,%edx bswap %eax bswap %ebx - jmp .L00500_14_sse2 + jmp .L00200_14_sse2 .align 16 -.L00500_14_sse2: +.L00200_14_sse2: movd %eax,%mm1 movl (%edi),%eax movd %ebx,%mm7 @@ -130,7 +120,7 @@ sha512_block_data_order: paddq %mm6,%mm3 movq 48(%esp),%mm6 decl %edx - jnz .L00500_14_sse2 + jnz .L00200_14_sse2 movd %eax,%mm1 movd %ebx,%mm7 punpckldq %mm1,%mm7 @@ -186,9 +176,9 @@ sha512_block_data_order: paddq %mm6,%mm3 pxor %mm0,%mm0 movl $32,%edx - jmp .L00616_79_sse2 + jmp .L00316_79_sse2 .align 16 -.L00616_79_sse2: +.L00316_79_sse2: movq 88(%esp),%mm5 movq %mm7,%mm1 psrlq $1,%mm7 @@ -342,7 +332,7 @@ sha512_block_data_order: paddq %mm6,%mm0 addl $8,%ebp decl %edx - jnz .L00616_79_sse2 + jnz .L00316_79_sse2 paddq %mm3,%mm0 movq 8(%esp),%mm1 movq 24(%esp),%mm3 @@ -370,7 +360,7 @@ sha512_block_data_order: leal (%esp,%eax,1),%esp subl %eax,%ebp cmpl 88(%esp),%edi - jb .L004loop_sse2 + jb .L001loop_sse2 movl 92(%esp),%esp emms popl %edi @@ -378,8 +368,41 @@ sha512_block_data_order: popl %ebx popl %ebp ret -.align 32 -.L003SSSE3: +.size sha512_block_data_order_nohw,.-.L_sha512_block_data_order_nohw_begin +.globl sha512_block_data_order_ssse3 +.hidden sha512_block_data_order_ssse3 +.type sha512_block_data_order_ssse3,@function +.align 16 +sha512_block_data_order_ssse3: +.L_sha512_block_data_order_ssse3_begin: + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + movl 20(%esp),%esi + movl 24(%esp),%edi + movl 28(%esp),%eax + movl %esp,%ebx + call .L004pic_point +.L004pic_point: + popl %ebp + leal .LK512-.L004pic_point(%ebp),%ebp + subl $16,%esp + andl $-64,%esp + shll $7,%eax + addl %edi,%eax + movl %esi,(%esp) + movl %edi,4(%esp) + movl %eax,8(%esp) + movl %ebx,12(%esp) + movq (%esi),%mm0 + movq 8(%esi),%mm1 + movq 16(%esi),%mm2 + movq 24(%esi),%mm3 + movq 32(%esi),%mm4 + movq 40(%esi),%mm5 + movq 48(%esi),%mm6 + movq 56(%esi),%mm7 leal -64(%esp),%edx subl $256,%esp movdqa 640(%ebp),%xmm1 @@ -436,7 +459,7 @@ sha512_block_data_order: movdqa %xmm2,-16(%edx) nop .align 32 -.L007loop_ssse3: +.L005loop_ssse3: movdqa 16(%edx),%xmm2 movdqa %xmm3,48(%edx) leal 128(%ebp),%ebp @@ -453,9 +476,9 @@ sha512_block_data_order: pxor %mm1,%mm2 movq %mm7,56(%esp) pxor %mm3,%mm3 - jmp .L00800_47_ssse3 + jmp .L00600_47_ssse3 .align 32 -.L00800_47_ssse3: +.L00600_47_ssse3: movdqa %xmm5,%xmm3 movdqa %xmm2,%xmm1 .byte 102,15,58,15,208,8 @@ -1474,7 +1497,7 @@ sha512_block_data_order: movdqa %xmm1,-16(%edx) leal 128(%ebp),%ebp decl %ecx - jnz .L00800_47_ssse3 + jnz .L00600_47_ssse3 movdqa (%ebp),%xmm1 leal -640(%ebp),%ebp movdqu (%ebx),%xmm0 @@ -2286,7 +2309,7 @@ sha512_block_data_order: movq %mm6,48(%esi) movq %mm7,56(%esi) cmpl %eax,%edi - jb .L007loop_ssse3 + jb .L005loop_ssse3 movl 76(%edx),%esp emms popl %edi @@ -2294,456 +2317,9 @@ sha512_block_data_order: popl %ebx popl %ebp ret -.align 16 -.L002loop_x86: - movl (%edi),%eax - movl 4(%edi),%ebx - movl 8(%edi),%ecx - movl 12(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 16(%edi),%eax - movl 20(%edi),%ebx - movl 24(%edi),%ecx - movl 28(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 32(%edi),%eax - movl 36(%edi),%ebx - movl 40(%edi),%ecx - movl 44(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 48(%edi),%eax - movl 52(%edi),%ebx - movl 56(%edi),%ecx - movl 60(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 64(%edi),%eax - movl 68(%edi),%ebx - movl 72(%edi),%ecx - movl 76(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 80(%edi),%eax - movl 84(%edi),%ebx - movl 88(%edi),%ecx - movl 92(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 96(%edi),%eax - movl 100(%edi),%ebx - movl 104(%edi),%ecx - movl 108(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - movl 112(%edi),%eax - movl 116(%edi),%ebx - movl 120(%edi),%ecx - movl 124(%edi),%edx - bswap %eax - bswap %ebx - bswap %ecx - bswap %edx - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - addl $128,%edi - subl $72,%esp - movl %edi,204(%esp) - leal 8(%esp),%edi - movl $16,%ecx -.long 2784229001 -.align 16 -.L00900_15_x86: - movl 40(%esp),%ecx - movl 44(%esp),%edx - movl %ecx,%esi - shrl $9,%ecx - movl %edx,%edi - shrl $9,%edx - movl %ecx,%ebx - shll $14,%esi - movl %edx,%eax - shll $14,%edi - xorl %esi,%ebx - shrl $5,%ecx - xorl %edi,%eax - shrl $5,%edx - xorl %ecx,%eax - shll $4,%esi - xorl %edx,%ebx - shll $4,%edi - xorl %esi,%ebx - shrl $4,%ecx - xorl %edi,%eax - shrl $4,%edx - xorl %ecx,%eax - shll $5,%esi - xorl %edx,%ebx - shll $5,%edi - xorl %esi,%eax - xorl %edi,%ebx - movl 48(%esp),%ecx - movl 52(%esp),%edx - movl 56(%esp),%esi - movl 60(%esp),%edi - addl 64(%esp),%eax - adcl 68(%esp),%ebx - xorl %esi,%ecx - xorl %edi,%edx - andl 40(%esp),%ecx - andl 44(%esp),%edx - addl 192(%esp),%eax - adcl 196(%esp),%ebx - xorl %esi,%ecx - xorl %edi,%edx - movl (%ebp),%esi - movl 4(%ebp),%edi - addl %ecx,%eax - adcl %edx,%ebx - movl 32(%esp),%ecx - movl 36(%esp),%edx - addl %esi,%eax - adcl %edi,%ebx - movl %eax,(%esp) - movl %ebx,4(%esp) - addl %ecx,%eax - adcl %edx,%ebx - movl 8(%esp),%ecx - movl 12(%esp),%edx - movl %eax,32(%esp) - movl %ebx,36(%esp) - movl %ecx,%esi - shrl $2,%ecx - movl %edx,%edi - shrl $2,%edx - movl %ecx,%ebx - shll $4,%esi - movl %edx,%eax - shll $4,%edi - xorl %esi,%ebx - shrl $5,%ecx - xorl %edi,%eax - shrl $5,%edx - xorl %ecx,%ebx - shll $21,%esi - xorl %edx,%eax - shll $21,%edi - xorl %esi,%eax - shrl $21,%ecx - xorl %edi,%ebx - shrl $21,%edx - xorl %ecx,%eax - shll $5,%esi - xorl %edx,%ebx - shll $5,%edi - xorl %esi,%eax - xorl %edi,%ebx - movl 8(%esp),%ecx - movl 12(%esp),%edx - movl 16(%esp),%esi - movl 20(%esp),%edi - addl (%esp),%eax - adcl 4(%esp),%ebx - orl %esi,%ecx - orl %edi,%edx - andl 24(%esp),%ecx - andl 28(%esp),%edx - andl 8(%esp),%esi - andl 12(%esp),%edi - orl %esi,%ecx - orl %edi,%edx - addl %ecx,%eax - adcl %edx,%ebx - movl %eax,(%esp) - movl %ebx,4(%esp) - movb (%ebp),%dl - subl $8,%esp - leal 8(%ebp),%ebp - cmpb $148,%dl - jne .L00900_15_x86 -.align 16 -.L01016_79_x86: - movl 312(%esp),%ecx - movl 316(%esp),%edx - movl %ecx,%esi - shrl $1,%ecx - movl %edx,%edi - shrl $1,%edx - movl %ecx,%eax - shll $24,%esi - movl %edx,%ebx - shll $24,%edi - xorl %esi,%ebx - shrl $6,%ecx - xorl %edi,%eax - shrl $6,%edx - xorl %ecx,%eax - shll $7,%esi - xorl %edx,%ebx - shll $1,%edi - xorl %esi,%ebx - shrl $1,%ecx - xorl %edi,%eax - shrl $1,%edx - xorl %ecx,%eax - shll $6,%edi - xorl %edx,%ebx - xorl %edi,%eax - movl %eax,(%esp) - movl %ebx,4(%esp) - movl 208(%esp),%ecx - movl 212(%esp),%edx - movl %ecx,%esi - shrl $6,%ecx - movl %edx,%edi - shrl $6,%edx - movl %ecx,%eax - shll $3,%esi - movl %edx,%ebx - shll $3,%edi - xorl %esi,%eax - shrl $13,%ecx - xorl %edi,%ebx - shrl $13,%edx - xorl %ecx,%eax - shll $10,%esi - xorl %edx,%ebx - shll $10,%edi - xorl %esi,%ebx - shrl $10,%ecx - xorl %edi,%eax - shrl $10,%edx - xorl %ecx,%ebx - shll $13,%edi - xorl %edx,%eax - xorl %edi,%eax - movl 320(%esp),%ecx - movl 324(%esp),%edx - addl (%esp),%eax - adcl 4(%esp),%ebx - movl 248(%esp),%esi - movl 252(%esp),%edi - addl %ecx,%eax - adcl %edx,%ebx - addl %esi,%eax - adcl %edi,%ebx - movl %eax,192(%esp) - movl %ebx,196(%esp) - movl 40(%esp),%ecx - movl 44(%esp),%edx - movl %ecx,%esi - shrl $9,%ecx - movl %edx,%edi - shrl $9,%edx - movl %ecx,%ebx - shll $14,%esi - movl %edx,%eax - shll $14,%edi - xorl %esi,%ebx - shrl $5,%ecx - xorl %edi,%eax - shrl $5,%edx - xorl %ecx,%eax - shll $4,%esi - xorl %edx,%ebx - shll $4,%edi - xorl %esi,%ebx - shrl $4,%ecx - xorl %edi,%eax - shrl $4,%edx - xorl %ecx,%eax - shll $5,%esi - xorl %edx,%ebx - shll $5,%edi - xorl %esi,%eax - xorl %edi,%ebx - movl 48(%esp),%ecx - movl 52(%esp),%edx - movl 56(%esp),%esi - movl 60(%esp),%edi - addl 64(%esp),%eax - adcl 68(%esp),%ebx - xorl %esi,%ecx - xorl %edi,%edx - andl 40(%esp),%ecx - andl 44(%esp),%edx - addl 192(%esp),%eax - adcl 196(%esp),%ebx - xorl %esi,%ecx - xorl %edi,%edx - movl (%ebp),%esi - movl 4(%ebp),%edi - addl %ecx,%eax - adcl %edx,%ebx - movl 32(%esp),%ecx - movl 36(%esp),%edx - addl %esi,%eax - adcl %edi,%ebx - movl %eax,(%esp) - movl %ebx,4(%esp) - addl %ecx,%eax - adcl %edx,%ebx - movl 8(%esp),%ecx - movl 12(%esp),%edx - movl %eax,32(%esp) - movl %ebx,36(%esp) - movl %ecx,%esi - shrl $2,%ecx - movl %edx,%edi - shrl $2,%edx - movl %ecx,%ebx - shll $4,%esi - movl %edx,%eax - shll $4,%edi - xorl %esi,%ebx - shrl $5,%ecx - xorl %edi,%eax - shrl $5,%edx - xorl %ecx,%ebx - shll $21,%esi - xorl %edx,%eax - shll $21,%edi - xorl %esi,%eax - shrl $21,%ecx - xorl %edi,%ebx - shrl $21,%edx - xorl %ecx,%eax - shll $5,%esi - xorl %edx,%ebx - shll $5,%edi - xorl %esi,%eax - xorl %edi,%ebx - movl 8(%esp),%ecx - movl 12(%esp),%edx - movl 16(%esp),%esi - movl 20(%esp),%edi - addl (%esp),%eax - adcl 4(%esp),%ebx - orl %esi,%ecx - orl %edi,%edx - andl 24(%esp),%ecx - andl 28(%esp),%edx - andl 8(%esp),%esi - andl 12(%esp),%edi - orl %esi,%ecx - orl %edi,%edx - addl %ecx,%eax - adcl %edx,%ebx - movl %eax,(%esp) - movl %ebx,4(%esp) - movb (%ebp),%dl - subl $8,%esp - leal 8(%ebp),%ebp - cmpb $23,%dl - jne .L01016_79_x86 - movl 840(%esp),%esi - movl 844(%esp),%edi - movl (%esi),%eax - movl 4(%esi),%ebx - movl 8(%esi),%ecx - movl 12(%esi),%edx - addl 8(%esp),%eax - adcl 12(%esp),%ebx - movl %eax,(%esi) - movl %ebx,4(%esi) - addl 16(%esp),%ecx - adcl 20(%esp),%edx - movl %ecx,8(%esi) - movl %edx,12(%esi) - movl 16(%esi),%eax - movl 20(%esi),%ebx - movl 24(%esi),%ecx - movl 28(%esi),%edx - addl 24(%esp),%eax - adcl 28(%esp),%ebx - movl %eax,16(%esi) - movl %ebx,20(%esi) - addl 32(%esp),%ecx - adcl 36(%esp),%edx - movl %ecx,24(%esi) - movl %edx,28(%esi) - movl 32(%esi),%eax - movl 36(%esi),%ebx - movl 40(%esi),%ecx - movl 44(%esi),%edx - addl 40(%esp),%eax - adcl 44(%esp),%ebx - movl %eax,32(%esi) - movl %ebx,36(%esi) - addl 48(%esp),%ecx - adcl 52(%esp),%edx - movl %ecx,40(%esi) - movl %edx,44(%esi) - movl 48(%esi),%eax - movl 52(%esi),%ebx - movl 56(%esi),%ecx - movl 60(%esi),%edx - addl 56(%esp),%eax - adcl 60(%esp),%ebx - movl %eax,48(%esi) - movl %ebx,52(%esi) - addl 64(%esp),%ecx - adcl 68(%esp),%edx - movl %ecx,56(%esi) - movl %edx,60(%esi) - addl $840,%esp - subl $640,%ebp - cmpl 8(%esp),%edi - jb .L002loop_x86 - movl 12(%esp),%esp - popl %edi - popl %esi - popl %ebx - popl %ebp - ret +.size sha512_block_data_order_ssse3,.-.L_sha512_block_data_order_ssse3_begin .align 64 -.L001K512: +.LK512: .long 3609767458,1116352408 .long 602891725,1899447441 .long 3964484399,3049323471 @@ -2826,7 +2402,6 @@ sha512_block_data_order: .long 1246189591,1816402316 .long 67438087,66051 .long 202182159,134810123 -.size sha512_block_data_order,.-.L_sha512_block_data_order_begin .byte 83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97 .byte 110,115,102,111,114,109,32,102,111,114,32,120,56,54,44,32 .byte 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-win.asm index 3603a6dc13..2f43a1c4fe 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/sha512-586-win.asm @@ -13,11 +13,10 @@ section .text code align=64 %else section .text code %endif -;extern _OPENSSL_ia32cap_P -global _sha512_block_data_order +global _sha512_block_data_order_nohw align 16 -_sha512_block_data_order: -L$_sha512_block_data_order_begin: +_sha512_block_data_order_nohw: +L$_sha512_block_data_order_nohw_begin: push ebp push ebx push esi @@ -29,7 +28,7 @@ L$_sha512_block_data_order_begin: call L$000pic_point L$000pic_point: pop ebp - lea ebp,[(L$001K512-L$000pic_point)+ebp] + lea ebp,[(L$K512-L$000pic_point)+ebp] sub esp,16 and esp,-64 shl eax,7 @@ -38,28 +37,18 @@ L$000pic_point: mov DWORD [4+esp],edi mov DWORD [8+esp],eax mov DWORD [12+esp],ebx - lea edx,[_OPENSSL_ia32cap_P] - mov ecx,DWORD [edx] - test ecx,67108864 - jz NEAR L$002loop_x86 - mov edx,DWORD [4+edx] movq mm0,[esi] - and ecx,16777216 movq mm1,[8+esi] - and edx,512 movq mm2,[16+esi] - or ecx,edx movq mm3,[24+esi] movq mm4,[32+esi] movq mm5,[40+esi] movq mm6,[48+esi] movq mm7,[56+esi] - cmp ecx,16777728 - je NEAR L$003SSSE3 sub esp,80 - jmp NEAR L$004loop_sse2 + jmp NEAR L$001loop_sse2 align 16 -L$004loop_sse2: +L$001loop_sse2: movq [8+esp],mm1 movq [16+esp],mm2 movq [24+esp],mm3 @@ -74,9 +63,9 @@ L$004loop_sse2: mov edx,15 bswap eax bswap ebx - jmp NEAR L$00500_14_sse2 + jmp NEAR L$00200_14_sse2 align 16 -L$00500_14_sse2: +L$00200_14_sse2: movd mm1,eax mov eax,DWORD [edi] movd mm7,ebx @@ -137,7 +126,7 @@ L$00500_14_sse2: paddq mm3,mm6 movq mm6,[48+esp] dec edx - jnz NEAR L$00500_14_sse2 + jnz NEAR L$00200_14_sse2 movd mm1,eax movd mm7,ebx punpckldq mm7,mm1 @@ -193,9 +182,9 @@ L$00500_14_sse2: paddq mm3,mm6 pxor mm0,mm0 mov edx,32 - jmp NEAR L$00616_79_sse2 + jmp NEAR L$00316_79_sse2 align 16 -L$00616_79_sse2: +L$00316_79_sse2: movq mm5,[88+esp] movq mm1,mm7 psrlq mm7,1 @@ -349,7 +338,7 @@ L$00616_79_sse2: paddq mm0,mm6 add ebp,8 dec edx - jnz NEAR L$00616_79_sse2 + jnz NEAR L$00316_79_sse2 paddq mm0,mm3 movq mm1,[8+esp] movq mm3,[24+esp] @@ -377,7 +366,7 @@ L$00616_79_sse2: lea esp,[eax*1+esp] sub ebp,eax cmp edi,DWORD [88+esp] - jb NEAR L$004loop_sse2 + jb NEAR L$001loop_sse2 mov esp,DWORD [92+esp] emms pop edi @@ -385,8 +374,38 @@ L$00616_79_sse2: pop ebx pop ebp ret -align 32 -L$003SSSE3: +global _sha512_block_data_order_ssse3 +align 16 +_sha512_block_data_order_ssse3: +L$_sha512_block_data_order_ssse3_begin: + push ebp + push ebx + push esi + push edi + mov esi,DWORD [20+esp] + mov edi,DWORD [24+esp] + mov eax,DWORD [28+esp] + mov ebx,esp + call L$004pic_point +L$004pic_point: + pop ebp + lea ebp,[(L$K512-L$004pic_point)+ebp] + sub esp,16 + and esp,-64 + shl eax,7 + add eax,edi + mov DWORD [esp],esi + mov DWORD [4+esp],edi + mov DWORD [8+esp],eax + mov DWORD [12+esp],ebx + movq mm0,[esi] + movq mm1,[8+esi] + movq mm2,[16+esi] + movq mm3,[24+esi] + movq mm4,[32+esi] + movq mm5,[40+esi] + movq mm6,[48+esi] + movq mm7,[56+esi] lea edx,[esp-64] sub esp,256 movdqa xmm1,[640+ebp] @@ -443,7 +462,7 @@ db 102,15,56,0,248 movdqa [edx-16],xmm2 nop align 32 -L$007loop_ssse3: +L$005loop_ssse3: movdqa xmm2,[16+edx] movdqa [48+edx],xmm3 lea ebp,[128+ebp] @@ -460,9 +479,9 @@ L$007loop_ssse3: pxor mm2,mm1 movq [56+esp],mm7 pxor mm3,mm3 - jmp NEAR L$00800_47_ssse3 + jmp NEAR L$00600_47_ssse3 align 32 -L$00800_47_ssse3: +L$00600_47_ssse3: movdqa xmm3,xmm5 movdqa xmm1,xmm2 db 102,15,58,15,208,8 @@ -1481,7 +1500,7 @@ db 102,15,58,15,211,8 movdqa [edx-16],xmm1 lea ebp,[128+ebp] dec ecx - jnz NEAR L$00800_47_ssse3 + jnz NEAR L$00600_47_ssse3 movdqa xmm1,[ebp] lea ebp,[ebp-640] movdqu xmm0,[ebx] @@ -2293,7 +2312,7 @@ db 102,15,56,0,248 movq [48+esi],mm6 movq [56+esi],mm7 cmp edi,eax - jb NEAR L$007loop_ssse3 + jb NEAR L$005loop_ssse3 mov esp,DWORD [76+edx] emms pop edi @@ -2301,456 +2320,8 @@ db 102,15,56,0,248 pop ebx pop ebp ret -align 16 -L$002loop_x86: - mov eax,DWORD [edi] - mov ebx,DWORD [4+edi] - mov ecx,DWORD [8+edi] - mov edx,DWORD [12+edi] - bswap eax - bswap ebx - bswap ecx - bswap edx - push eax - push ebx - push ecx - push edx - mov eax,DWORD [16+edi] - mov ebx,DWORD [20+edi] - mov ecx,DWORD [24+edi] - mov edx,DWORD [28+edi] - bswap eax - bswap ebx - bswap ecx - bswap edx - push eax - push ebx - push ecx - push edx - mov eax,DWORD [32+edi] - mov ebx,DWORD [36+edi] - mov ecx,DWORD [40+edi] - mov edx,DWORD [44+edi] - bswap eax - bswap ebx - bswap ecx - bswap edx - push eax - push ebx - push ecx - push edx - mov eax,DWORD [48+edi] - mov ebx,DWORD [52+edi] - mov ecx,DWORD [56+edi] - mov edx,DWORD [60+edi] - bswap eax - bswap ebx - bswap ecx - bswap edx - push eax - push ebx - push ecx - push edx - mov eax,DWORD [64+edi] - mov ebx,DWORD [68+edi] - mov ecx,DWORD [72+edi] - mov edx,DWORD [76+edi] - bswap eax - bswap ebx - bswap ecx - bswap edx - push eax - push ebx - push ecx - push edx - mov eax,DWORD [80+edi] - mov ebx,DWORD [84+edi] - mov ecx,DWORD [88+edi] - mov edx,DWORD [92+edi] - bswap eax - bswap ebx - bswap ecx - bswap edx - push eax - push ebx - push ecx - push edx - mov eax,DWORD [96+edi] - mov ebx,DWORD [100+edi] - mov ecx,DWORD [104+edi] - mov edx,DWORD [108+edi] - bswap eax - bswap ebx - bswap ecx - bswap edx - push eax - push ebx - push ecx - push edx - mov eax,DWORD [112+edi] - mov ebx,DWORD [116+edi] - mov ecx,DWORD [120+edi] - mov edx,DWORD [124+edi] - bswap eax - bswap ebx - bswap ecx - bswap edx - push eax - push ebx - push ecx - push edx - add edi,128 - sub esp,72 - mov DWORD [204+esp],edi - lea edi,[8+esp] - mov ecx,16 -dd 2784229001 -align 16 -L$00900_15_x86: - mov ecx,DWORD [40+esp] - mov edx,DWORD [44+esp] - mov esi,ecx - shr ecx,9 - mov edi,edx - shr edx,9 - mov ebx,ecx - shl esi,14 - mov eax,edx - shl edi,14 - xor ebx,esi - shr ecx,5 - xor eax,edi - shr edx,5 - xor eax,ecx - shl esi,4 - xor ebx,edx - shl edi,4 - xor ebx,esi - shr ecx,4 - xor eax,edi - shr edx,4 - xor eax,ecx - shl esi,5 - xor ebx,edx - shl edi,5 - xor eax,esi - xor ebx,edi - mov ecx,DWORD [48+esp] - mov edx,DWORD [52+esp] - mov esi,DWORD [56+esp] - mov edi,DWORD [60+esp] - add eax,DWORD [64+esp] - adc ebx,DWORD [68+esp] - xor ecx,esi - xor edx,edi - and ecx,DWORD [40+esp] - and edx,DWORD [44+esp] - add eax,DWORD [192+esp] - adc ebx,DWORD [196+esp] - xor ecx,esi - xor edx,edi - mov esi,DWORD [ebp] - mov edi,DWORD [4+ebp] - add eax,ecx - adc ebx,edx - mov ecx,DWORD [32+esp] - mov edx,DWORD [36+esp] - add eax,esi - adc ebx,edi - mov DWORD [esp],eax - mov DWORD [4+esp],ebx - add eax,ecx - adc ebx,edx - mov ecx,DWORD [8+esp] - mov edx,DWORD [12+esp] - mov DWORD [32+esp],eax - mov DWORD [36+esp],ebx - mov esi,ecx - shr ecx,2 - mov edi,edx - shr edx,2 - mov ebx,ecx - shl esi,4 - mov eax,edx - shl edi,4 - xor ebx,esi - shr ecx,5 - xor eax,edi - shr edx,5 - xor ebx,ecx - shl esi,21 - xor eax,edx - shl edi,21 - xor eax,esi - shr ecx,21 - xor ebx,edi - shr edx,21 - xor eax,ecx - shl esi,5 - xor ebx,edx - shl edi,5 - xor eax,esi - xor ebx,edi - mov ecx,DWORD [8+esp] - mov edx,DWORD [12+esp] - mov esi,DWORD [16+esp] - mov edi,DWORD [20+esp] - add eax,DWORD [esp] - adc ebx,DWORD [4+esp] - or ecx,esi - or edx,edi - and ecx,DWORD [24+esp] - and edx,DWORD [28+esp] - and esi,DWORD [8+esp] - and edi,DWORD [12+esp] - or ecx,esi - or edx,edi - add eax,ecx - adc ebx,edx - mov DWORD [esp],eax - mov DWORD [4+esp],ebx - mov dl,BYTE [ebp] - sub esp,8 - lea ebp,[8+ebp] - cmp dl,148 - jne NEAR L$00900_15_x86 -align 16 -L$01016_79_x86: - mov ecx,DWORD [312+esp] - mov edx,DWORD [316+esp] - mov esi,ecx - shr ecx,1 - mov edi,edx - shr edx,1 - mov eax,ecx - shl esi,24 - mov ebx,edx - shl edi,24 - xor ebx,esi - shr ecx,6 - xor eax,edi - shr edx,6 - xor eax,ecx - shl esi,7 - xor ebx,edx - shl edi,1 - xor ebx,esi - shr ecx,1 - xor eax,edi - shr edx,1 - xor eax,ecx - shl edi,6 - xor ebx,edx - xor eax,edi - mov DWORD [esp],eax - mov DWORD [4+esp],ebx - mov ecx,DWORD [208+esp] - mov edx,DWORD [212+esp] - mov esi,ecx - shr ecx,6 - mov edi,edx - shr edx,6 - mov eax,ecx - shl esi,3 - mov ebx,edx - shl edi,3 - xor eax,esi - shr ecx,13 - xor ebx,edi - shr edx,13 - xor eax,ecx - shl esi,10 - xor ebx,edx - shl edi,10 - xor ebx,esi - shr ecx,10 - xor eax,edi - shr edx,10 - xor ebx,ecx - shl edi,13 - xor eax,edx - xor eax,edi - mov ecx,DWORD [320+esp] - mov edx,DWORD [324+esp] - add eax,DWORD [esp] - adc ebx,DWORD [4+esp] - mov esi,DWORD [248+esp] - mov edi,DWORD [252+esp] - add eax,ecx - adc ebx,edx - add eax,esi - adc ebx,edi - mov DWORD [192+esp],eax - mov DWORD [196+esp],ebx - mov ecx,DWORD [40+esp] - mov edx,DWORD [44+esp] - mov esi,ecx - shr ecx,9 - mov edi,edx - shr edx,9 - mov ebx,ecx - shl esi,14 - mov eax,edx - shl edi,14 - xor ebx,esi - shr ecx,5 - xor eax,edi - shr edx,5 - xor eax,ecx - shl esi,4 - xor ebx,edx - shl edi,4 - xor ebx,esi - shr ecx,4 - xor eax,edi - shr edx,4 - xor eax,ecx - shl esi,5 - xor ebx,edx - shl edi,5 - xor eax,esi - xor ebx,edi - mov ecx,DWORD [48+esp] - mov edx,DWORD [52+esp] - mov esi,DWORD [56+esp] - mov edi,DWORD [60+esp] - add eax,DWORD [64+esp] - adc ebx,DWORD [68+esp] - xor ecx,esi - xor edx,edi - and ecx,DWORD [40+esp] - and edx,DWORD [44+esp] - add eax,DWORD [192+esp] - adc ebx,DWORD [196+esp] - xor ecx,esi - xor edx,edi - mov esi,DWORD [ebp] - mov edi,DWORD [4+ebp] - add eax,ecx - adc ebx,edx - mov ecx,DWORD [32+esp] - mov edx,DWORD [36+esp] - add eax,esi - adc ebx,edi - mov DWORD [esp],eax - mov DWORD [4+esp],ebx - add eax,ecx - adc ebx,edx - mov ecx,DWORD [8+esp] - mov edx,DWORD [12+esp] - mov DWORD [32+esp],eax - mov DWORD [36+esp],ebx - mov esi,ecx - shr ecx,2 - mov edi,edx - shr edx,2 - mov ebx,ecx - shl esi,4 - mov eax,edx - shl edi,4 - xor ebx,esi - shr ecx,5 - xor eax,edi - shr edx,5 - xor ebx,ecx - shl esi,21 - xor eax,edx - shl edi,21 - xor eax,esi - shr ecx,21 - xor ebx,edi - shr edx,21 - xor eax,ecx - shl esi,5 - xor ebx,edx - shl edi,5 - xor eax,esi - xor ebx,edi - mov ecx,DWORD [8+esp] - mov edx,DWORD [12+esp] - mov esi,DWORD [16+esp] - mov edi,DWORD [20+esp] - add eax,DWORD [esp] - adc ebx,DWORD [4+esp] - or ecx,esi - or edx,edi - and ecx,DWORD [24+esp] - and edx,DWORD [28+esp] - and esi,DWORD [8+esp] - and edi,DWORD [12+esp] - or ecx,esi - or edx,edi - add eax,ecx - adc ebx,edx - mov DWORD [esp],eax - mov DWORD [4+esp],ebx - mov dl,BYTE [ebp] - sub esp,8 - lea ebp,[8+ebp] - cmp dl,23 - jne NEAR L$01016_79_x86 - mov esi,DWORD [840+esp] - mov edi,DWORD [844+esp] - mov eax,DWORD [esi] - mov ebx,DWORD [4+esi] - mov ecx,DWORD [8+esi] - mov edx,DWORD [12+esi] - add eax,DWORD [8+esp] - adc ebx,DWORD [12+esp] - mov DWORD [esi],eax - mov DWORD [4+esi],ebx - add ecx,DWORD [16+esp] - adc edx,DWORD [20+esp] - mov DWORD [8+esi],ecx - mov DWORD [12+esi],edx - mov eax,DWORD [16+esi] - mov ebx,DWORD [20+esi] - mov ecx,DWORD [24+esi] - mov edx,DWORD [28+esi] - add eax,DWORD [24+esp] - adc ebx,DWORD [28+esp] - mov DWORD [16+esi],eax - mov DWORD [20+esi],ebx - add ecx,DWORD [32+esp] - adc edx,DWORD [36+esp] - mov DWORD [24+esi],ecx - mov DWORD [28+esi],edx - mov eax,DWORD [32+esi] - mov ebx,DWORD [36+esi] - mov ecx,DWORD [40+esi] - mov edx,DWORD [44+esi] - add eax,DWORD [40+esp] - adc ebx,DWORD [44+esp] - mov DWORD [32+esi],eax - mov DWORD [36+esi],ebx - add ecx,DWORD [48+esp] - adc edx,DWORD [52+esp] - mov DWORD [40+esi],ecx - mov DWORD [44+esi],edx - mov eax,DWORD [48+esi] - mov ebx,DWORD [52+esi] - mov ecx,DWORD [56+esi] - mov edx,DWORD [60+esi] - add eax,DWORD [56+esp] - adc ebx,DWORD [60+esp] - mov DWORD [48+esi],eax - mov DWORD [52+esi],ebx - add ecx,DWORD [64+esp] - adc edx,DWORD [68+esp] - mov DWORD [56+esi],ecx - mov DWORD [60+esi],edx - add esp,840 - sub ebp,640 - cmp edi,DWORD [8+esp] - jb NEAR L$002loop_x86 - mov esp,DWORD [12+esp] - pop edi - pop esi - pop ebx - pop ebp - ret align 64 -L$001K512: +L$K512: dd 3609767458,1116352408 dd 602891725,1899447441 dd 3964484399,3049323471 @@ -2838,8 +2409,6 @@ db 110,115,102,111,114,109,32,102,111,114,32,120,56,54,44,32 db 67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97 db 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103 db 62,0 -segment .bss -common _OPENSSL_ia32cap_P 16 %else ; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738 ret diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-apple.S index 4d2c4856d1..02d3787044 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-apple.S @@ -470,10 +470,10 @@ L_vpaes_set_encrypt_key_begin: #ifdef BORINGSSL_DISPATCH_TEST pushl %ebx pushl %edx - call L016pic -L016pic: + call L016pic_for_function_hit +L016pic_for_function_hit: popl %ebx - leal _BORINGSSL_function_hit+5-L016pic(%ebx),%ebx + leal _BORINGSSL_function_hit+5-L016pic_for_function_hit(%ebx),%ebx movl $1,%edx movb %dl,(%ebx) popl %edx @@ -551,10 +551,10 @@ L_vpaes_encrypt_begin: #ifdef BORINGSSL_DISPATCH_TEST pushl %ebx pushl %edx - call L019pic -L019pic: + call L019pic_for_function_hit +L019pic_for_function_hit: popl %ebx - leal _BORINGSSL_function_hit+4-L019pic(%ebx),%ebx + leal _BORINGSSL_function_hit+4-L019pic_for_function_hit(%ebx),%ebx movl $1,%edx movb %dl,(%ebx) popl %edx diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-linux.S index 02786a7615..31dc9a081b 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-linux.S @@ -487,10 +487,10 @@ vpaes_set_encrypt_key: #ifdef BORINGSSL_DISPATCH_TEST pushl %ebx pushl %edx - call .L016pic -.L016pic: + call .L016pic_for_function_hit +.L016pic_for_function_hit: popl %ebx - leal BORINGSSL_function_hit+5-.L016pic(%ebx),%ebx + leal BORINGSSL_function_hit+5-.L016pic_for_function_hit(%ebx),%ebx movl $1,%edx movb %dl,(%ebx) popl %edx @@ -572,10 +572,10 @@ vpaes_encrypt: #ifdef BORINGSSL_DISPATCH_TEST pushl %ebx pushl %edx - call .L019pic -.L019pic: + call .L019pic_for_function_hit +.L019pic_for_function_hit: popl %ebx - leal BORINGSSL_function_hit+4-.L019pic(%ebx),%ebx + leal BORINGSSL_function_hit+4-.L019pic_for_function_hit(%ebx),%ebx movl $1,%edx movb %dl,(%ebx) popl %edx diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-win.asm index 661496e363..3f087e1014 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/vpaes-x86-win.asm @@ -470,10 +470,10 @@ L$_vpaes_set_encrypt_key_begin: %ifdef BORINGSSL_DISPATCH_TEST push ebx push edx - call L$016pic -L$016pic: + call L$016pic_for_function_hit +L$016pic_for_function_hit: pop ebx - lea ebx,[(_BORINGSSL_function_hit+5-L$016pic)+ebx] + lea ebx,[(_BORINGSSL_function_hit+5-L$016pic_for_function_hit)+ebx] mov edx,1 mov BYTE [ebx],dl pop edx @@ -549,10 +549,10 @@ L$_vpaes_encrypt_begin: %ifdef BORINGSSL_DISPATCH_TEST push ebx push edx - call L$019pic -L$019pic: + call L$019pic_for_function_hit +L$019pic_for_function_hit: pop ebx - lea ebx,[(_BORINGSSL_function_hit+4-L$019pic)+ebx] + lea ebx,[(_BORINGSSL_function_hit+4-L$019pic_for_function_hit)+ebx] mov edx,1 mov BYTE [ebx],dl pop edx diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-apple.S index f991f6c563..a8fd1f9f27 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-apple.S @@ -62,12 +62,6 @@ L002page_walk_done: movl %esi,20(%esp) leal -3(%edi),%ebx movl %edx,24(%esp) - call L003PIC_me_up -L003PIC_me_up: - popl %eax - movl L_OPENSSL_ia32cap_P$non_lazy_ptr-L003PIC_me_up(%eax),%eax - btl $26,(%eax) - jnc L004non_sse2 movl $-1,%eax movd %eax,%mm7 movl 8(%esp),%esi @@ -91,7 +85,7 @@ L003PIC_me_up: psrlq $32,%mm3 incl %ecx .align 4,0x90 -L0051st: +L0031st: pmuludq %mm4,%mm0 pmuludq %mm5,%mm1 paddq %mm0,%mm2 @@ -106,7 +100,7 @@ L0051st: psrlq $32,%mm3 leal 1(%ecx),%ecx cmpl %ebx,%ecx - jl L0051st + jl L0031st pmuludq %mm4,%mm0 pmuludq %mm5,%mm1 paddq %mm0,%mm2 @@ -120,7 +114,7 @@ L0051st: paddq %mm2,%mm3 movq %mm3,32(%esp,%ebx,4) incl %edx -L006outer: +L004outer: xorl %ecx,%ecx movd (%edi,%edx,4),%mm4 movd (%esi),%mm5 @@ -142,7 +136,7 @@ L006outer: paddq %mm6,%mm2 incl %ecx decl %ebx -L007inner: +L005inner: pmuludq %mm4,%mm0 pmuludq %mm5,%mm1 paddq %mm0,%mm2 @@ -159,7 +153,7 @@ L007inner: paddq %mm6,%mm2 decl %ebx leal 1(%ecx),%ecx - jnz L007inner + jnz L005inner movl %ecx,%ebx pmuludq %mm4,%mm0 pmuludq %mm5,%mm1 @@ -177,264 +171,11 @@ L007inner: movq %mm3,32(%esp,%ebx,4) leal 1(%edx),%edx cmpl %ebx,%edx - jle L006outer + jle L004outer emms - jmp L008common_tail + jmp L006common_tail .align 4,0x90 -L004non_sse2: - movl 8(%esp),%esi - leal 1(%ebx),%ebp - movl 12(%esp),%edi - xorl %ecx,%ecx - movl %esi,%edx - andl $1,%ebp - subl %edi,%edx - leal 4(%edi,%ebx,4),%eax - orl %edx,%ebp - movl (%edi),%edi - jz L009bn_sqr_mont - movl %eax,28(%esp) - movl (%esi),%eax - xorl %edx,%edx -.align 4,0x90 -L010mull: - movl %edx,%ebp - mull %edi - addl %eax,%ebp - leal 1(%ecx),%ecx - adcl $0,%edx - movl (%esi,%ecx,4),%eax - cmpl %ebx,%ecx - movl %ebp,28(%esp,%ecx,4) - jl L010mull - movl %edx,%ebp - mull %edi - movl 20(%esp),%edi - addl %ebp,%eax - movl 16(%esp),%esi - adcl $0,%edx - imull 32(%esp),%edi - movl %eax,32(%esp,%ebx,4) - xorl %ecx,%ecx - movl %edx,36(%esp,%ebx,4) - movl %ecx,40(%esp,%ebx,4) - movl (%esi),%eax - mull %edi - addl 32(%esp),%eax - movl 4(%esi),%eax - adcl $0,%edx - incl %ecx - jmp L0112ndmadd -.align 4,0x90 -L0121stmadd: - movl %edx,%ebp - mull %edi - addl 32(%esp,%ecx,4),%ebp - leal 1(%ecx),%ecx - adcl $0,%edx - addl %eax,%ebp - movl (%esi,%ecx,4),%eax - adcl $0,%edx - cmpl %ebx,%ecx - movl %ebp,28(%esp,%ecx,4) - jl L0121stmadd - movl %edx,%ebp - mull %edi - addl 32(%esp,%ebx,4),%eax - movl 20(%esp),%edi - adcl $0,%edx - movl 16(%esp),%esi - addl %eax,%ebp - adcl $0,%edx - imull 32(%esp),%edi - xorl %ecx,%ecx - addl 36(%esp,%ebx,4),%edx - movl %ebp,32(%esp,%ebx,4) - adcl $0,%ecx - movl (%esi),%eax - movl %edx,36(%esp,%ebx,4) - movl %ecx,40(%esp,%ebx,4) - mull %edi - addl 32(%esp),%eax - movl 4(%esi),%eax - adcl $0,%edx - movl $1,%ecx -.align 4,0x90 -L0112ndmadd: - movl %edx,%ebp - mull %edi - addl 32(%esp,%ecx,4),%ebp - leal 1(%ecx),%ecx - adcl $0,%edx - addl %eax,%ebp - movl (%esi,%ecx,4),%eax - adcl $0,%edx - cmpl %ebx,%ecx - movl %ebp,24(%esp,%ecx,4) - jl L0112ndmadd - movl %edx,%ebp - mull %edi - addl 32(%esp,%ebx,4),%ebp - adcl $0,%edx - addl %eax,%ebp - adcl $0,%edx - movl %ebp,28(%esp,%ebx,4) - xorl %eax,%eax - movl 12(%esp),%ecx - addl 36(%esp,%ebx,4),%edx - adcl 40(%esp,%ebx,4),%eax - leal 4(%ecx),%ecx - movl %edx,32(%esp,%ebx,4) - cmpl 28(%esp),%ecx - movl %eax,36(%esp,%ebx,4) - je L008common_tail - movl (%ecx),%edi - movl 8(%esp),%esi - movl %ecx,12(%esp) - xorl %ecx,%ecx - xorl %edx,%edx - movl (%esi),%eax - jmp L0121stmadd -.align 4,0x90 -L009bn_sqr_mont: - movl %ebx,(%esp) - movl %ecx,12(%esp) - movl %edi,%eax - mull %edi - movl %eax,32(%esp) - movl %edx,%ebx - shrl $1,%edx - andl $1,%ebx - incl %ecx -.align 4,0x90 -L013sqr: - movl (%esi,%ecx,4),%eax - movl %edx,%ebp - mull %edi - addl %ebp,%eax - leal 1(%ecx),%ecx - adcl $0,%edx - leal (%ebx,%eax,2),%ebp - shrl $31,%eax - cmpl (%esp),%ecx - movl %eax,%ebx - movl %ebp,28(%esp,%ecx,4) - jl L013sqr - movl (%esi,%ecx,4),%eax - movl %edx,%ebp - mull %edi - addl %ebp,%eax - movl 20(%esp),%edi - adcl $0,%edx - movl 16(%esp),%esi - leal (%ebx,%eax,2),%ebp - imull 32(%esp),%edi - shrl $31,%eax - movl %ebp,32(%esp,%ecx,4) - leal (%eax,%edx,2),%ebp - movl (%esi),%eax - shrl $31,%edx - movl %ebp,36(%esp,%ecx,4) - movl %edx,40(%esp,%ecx,4) - mull %edi - addl 32(%esp),%eax - movl %ecx,%ebx - adcl $0,%edx - movl 4(%esi),%eax - movl $1,%ecx -.align 4,0x90 -L0143rdmadd: - movl %edx,%ebp - mull %edi - addl 32(%esp,%ecx,4),%ebp - adcl $0,%edx - addl %eax,%ebp - movl 4(%esi,%ecx,4),%eax - adcl $0,%edx - movl %ebp,28(%esp,%ecx,4) - movl %edx,%ebp - mull %edi - addl 36(%esp,%ecx,4),%ebp - leal 2(%ecx),%ecx - adcl $0,%edx - addl %eax,%ebp - movl (%esi,%ecx,4),%eax - adcl $0,%edx - cmpl %ebx,%ecx - movl %ebp,24(%esp,%ecx,4) - jl L0143rdmadd - movl %edx,%ebp - mull %edi - addl 32(%esp,%ebx,4),%ebp - adcl $0,%edx - addl %eax,%ebp - adcl $0,%edx - movl %ebp,28(%esp,%ebx,4) - movl 12(%esp),%ecx - xorl %eax,%eax - movl 8(%esp),%esi - addl 36(%esp,%ebx,4),%edx - adcl 40(%esp,%ebx,4),%eax - movl %edx,32(%esp,%ebx,4) - cmpl %ebx,%ecx - movl %eax,36(%esp,%ebx,4) - je L008common_tail - movl 4(%esi,%ecx,4),%edi - leal 1(%ecx),%ecx - movl %edi,%eax - movl %ecx,12(%esp) - mull %edi - addl 32(%esp,%ecx,4),%eax - adcl $0,%edx - movl %eax,32(%esp,%ecx,4) - xorl %ebp,%ebp - cmpl %ebx,%ecx - leal 1(%ecx),%ecx - je L015sqrlast - movl %edx,%ebx - shrl $1,%edx - andl $1,%ebx -.align 4,0x90 -L016sqradd: - movl (%esi,%ecx,4),%eax - movl %edx,%ebp - mull %edi - addl %ebp,%eax - leal (%eax,%eax,1),%ebp - adcl $0,%edx - shrl $31,%eax - addl 32(%esp,%ecx,4),%ebp - leal 1(%ecx),%ecx - adcl $0,%eax - addl %ebx,%ebp - adcl $0,%eax - cmpl (%esp),%ecx - movl %ebp,28(%esp,%ecx,4) - movl %eax,%ebx - jle L016sqradd - movl %edx,%ebp - addl %edx,%edx - shrl $31,%ebp - addl %ebx,%edx - adcl $0,%ebp -L015sqrlast: - movl 20(%esp),%edi - movl 16(%esp),%esi - imull 32(%esp),%edi - addl 32(%esp,%ecx,4),%edx - movl (%esi),%eax - adcl $0,%ebp - movl %edx,32(%esp,%ecx,4) - movl %ebp,36(%esp,%ecx,4) - mull %edi - addl 32(%esp),%eax - leal -1(%ecx),%ebx - adcl $0,%edx - movl $1,%ecx - movl 4(%esi),%eax - jmp L0143rdmadd -.align 4,0x90 -L008common_tail: +L006common_tail: movl 16(%esp),%ebp movl 4(%esp),%edi leal 32(%esp),%esi @@ -442,19 +183,19 @@ L008common_tail: movl %ebx,%ecx xorl %edx,%edx .align 4,0x90 -L017sub: +L007sub: sbbl (%ebp,%edx,4),%eax movl %eax,(%edi,%edx,4) decl %ecx movl 4(%esi,%edx,4),%eax leal 1(%edx),%edx - jge L017sub + jge L007sub sbbl $0,%eax movl $-1,%edx xorl %eax,%edx - jmp L018copy + jmp L008copy .align 4,0x90 -L018copy: +L008copy: movl 32(%esp,%ebx,4),%esi movl (%edi,%ebx,4),%ebp movl %ecx,32(%esp,%ebx,4) @@ -463,7 +204,7 @@ L018copy: orl %esi,%ebp movl %ebp,(%edi,%ebx,4) decl %ebx - jge L018copy + jge L008copy movl 24(%esp),%esp movl $1,%eax L000just_leave: @@ -477,8 +218,4 @@ L000just_leave: .byte 54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121 .byte 32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46 .byte 111,114,103,62,0 -.section __IMPORT,__pointers,non_lazy_symbol_pointers -L_OPENSSL_ia32cap_P$non_lazy_ptr: -.indirect_symbol _OPENSSL_ia32cap_P -.long 0 #endif // !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__APPLE__) diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-linux.S index e6b4ef574f..3d3ddb5e9e 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-linux.S @@ -63,12 +63,6 @@ bn_mul_mont: movl %esi,20(%esp) leal -3(%edi),%ebx movl %edx,24(%esp) - call .L003PIC_me_up -.L003PIC_me_up: - popl %eax - leal OPENSSL_ia32cap_P-.L003PIC_me_up(%eax),%eax - btl $26,(%eax) - jnc .L004non_sse2 movl $-1,%eax movd %eax,%mm7 movl 8(%esp),%esi @@ -92,7 +86,7 @@ bn_mul_mont: psrlq $32,%mm3 incl %ecx .align 16 -.L0051st: +.L0031st: pmuludq %mm4,%mm0 pmuludq %mm5,%mm1 paddq %mm0,%mm2 @@ -107,7 +101,7 @@ bn_mul_mont: psrlq $32,%mm3 leal 1(%ecx),%ecx cmpl %ebx,%ecx - jl .L0051st + jl .L0031st pmuludq %mm4,%mm0 pmuludq %mm5,%mm1 paddq %mm0,%mm2 @@ -121,7 +115,7 @@ bn_mul_mont: paddq %mm2,%mm3 movq %mm3,32(%esp,%ebx,4) incl %edx -.L006outer: +.L004outer: xorl %ecx,%ecx movd (%edi,%edx,4),%mm4 movd (%esi),%mm5 @@ -143,7 +137,7 @@ bn_mul_mont: paddq %mm6,%mm2 incl %ecx decl %ebx -.L007inner: +.L005inner: pmuludq %mm4,%mm0 pmuludq %mm5,%mm1 paddq %mm0,%mm2 @@ -160,7 +154,7 @@ bn_mul_mont: paddq %mm6,%mm2 decl %ebx leal 1(%ecx),%ecx - jnz .L007inner + jnz .L005inner movl %ecx,%ebx pmuludq %mm4,%mm0 pmuludq %mm5,%mm1 @@ -178,264 +172,11 @@ bn_mul_mont: movq %mm3,32(%esp,%ebx,4) leal 1(%edx),%edx cmpl %ebx,%edx - jle .L006outer + jle .L004outer emms - jmp .L008common_tail + jmp .L006common_tail .align 16 -.L004non_sse2: - movl 8(%esp),%esi - leal 1(%ebx),%ebp - movl 12(%esp),%edi - xorl %ecx,%ecx - movl %esi,%edx - andl $1,%ebp - subl %edi,%edx - leal 4(%edi,%ebx,4),%eax - orl %edx,%ebp - movl (%edi),%edi - jz .L009bn_sqr_mont - movl %eax,28(%esp) - movl (%esi),%eax - xorl %edx,%edx -.align 16 -.L010mull: - movl %edx,%ebp - mull %edi - addl %eax,%ebp - leal 1(%ecx),%ecx - adcl $0,%edx - movl (%esi,%ecx,4),%eax - cmpl %ebx,%ecx - movl %ebp,28(%esp,%ecx,4) - jl .L010mull - movl %edx,%ebp - mull %edi - movl 20(%esp),%edi - addl %ebp,%eax - movl 16(%esp),%esi - adcl $0,%edx - imull 32(%esp),%edi - movl %eax,32(%esp,%ebx,4) - xorl %ecx,%ecx - movl %edx,36(%esp,%ebx,4) - movl %ecx,40(%esp,%ebx,4) - movl (%esi),%eax - mull %edi - addl 32(%esp),%eax - movl 4(%esi),%eax - adcl $0,%edx - incl %ecx - jmp .L0112ndmadd -.align 16 -.L0121stmadd: - movl %edx,%ebp - mull %edi - addl 32(%esp,%ecx,4),%ebp - leal 1(%ecx),%ecx - adcl $0,%edx - addl %eax,%ebp - movl (%esi,%ecx,4),%eax - adcl $0,%edx - cmpl %ebx,%ecx - movl %ebp,28(%esp,%ecx,4) - jl .L0121stmadd - movl %edx,%ebp - mull %edi - addl 32(%esp,%ebx,4),%eax - movl 20(%esp),%edi - adcl $0,%edx - movl 16(%esp),%esi - addl %eax,%ebp - adcl $0,%edx - imull 32(%esp),%edi - xorl %ecx,%ecx - addl 36(%esp,%ebx,4),%edx - movl %ebp,32(%esp,%ebx,4) - adcl $0,%ecx - movl (%esi),%eax - movl %edx,36(%esp,%ebx,4) - movl %ecx,40(%esp,%ebx,4) - mull %edi - addl 32(%esp),%eax - movl 4(%esi),%eax - adcl $0,%edx - movl $1,%ecx -.align 16 -.L0112ndmadd: - movl %edx,%ebp - mull %edi - addl 32(%esp,%ecx,4),%ebp - leal 1(%ecx),%ecx - adcl $0,%edx - addl %eax,%ebp - movl (%esi,%ecx,4),%eax - adcl $0,%edx - cmpl %ebx,%ecx - movl %ebp,24(%esp,%ecx,4) - jl .L0112ndmadd - movl %edx,%ebp - mull %edi - addl 32(%esp,%ebx,4),%ebp - adcl $0,%edx - addl %eax,%ebp - adcl $0,%edx - movl %ebp,28(%esp,%ebx,4) - xorl %eax,%eax - movl 12(%esp),%ecx - addl 36(%esp,%ebx,4),%edx - adcl 40(%esp,%ebx,4),%eax - leal 4(%ecx),%ecx - movl %edx,32(%esp,%ebx,4) - cmpl 28(%esp),%ecx - movl %eax,36(%esp,%ebx,4) - je .L008common_tail - movl (%ecx),%edi - movl 8(%esp),%esi - movl %ecx,12(%esp) - xorl %ecx,%ecx - xorl %edx,%edx - movl (%esi),%eax - jmp .L0121stmadd -.align 16 -.L009bn_sqr_mont: - movl %ebx,(%esp) - movl %ecx,12(%esp) - movl %edi,%eax - mull %edi - movl %eax,32(%esp) - movl %edx,%ebx - shrl $1,%edx - andl $1,%ebx - incl %ecx -.align 16 -.L013sqr: - movl (%esi,%ecx,4),%eax - movl %edx,%ebp - mull %edi - addl %ebp,%eax - leal 1(%ecx),%ecx - adcl $0,%edx - leal (%ebx,%eax,2),%ebp - shrl $31,%eax - cmpl (%esp),%ecx - movl %eax,%ebx - movl %ebp,28(%esp,%ecx,4) - jl .L013sqr - movl (%esi,%ecx,4),%eax - movl %edx,%ebp - mull %edi - addl %ebp,%eax - movl 20(%esp),%edi - adcl $0,%edx - movl 16(%esp),%esi - leal (%ebx,%eax,2),%ebp - imull 32(%esp),%edi - shrl $31,%eax - movl %ebp,32(%esp,%ecx,4) - leal (%eax,%edx,2),%ebp - movl (%esi),%eax - shrl $31,%edx - movl %ebp,36(%esp,%ecx,4) - movl %edx,40(%esp,%ecx,4) - mull %edi - addl 32(%esp),%eax - movl %ecx,%ebx - adcl $0,%edx - movl 4(%esi),%eax - movl $1,%ecx -.align 16 -.L0143rdmadd: - movl %edx,%ebp - mull %edi - addl 32(%esp,%ecx,4),%ebp - adcl $0,%edx - addl %eax,%ebp - movl 4(%esi,%ecx,4),%eax - adcl $0,%edx - movl %ebp,28(%esp,%ecx,4) - movl %edx,%ebp - mull %edi - addl 36(%esp,%ecx,4),%ebp - leal 2(%ecx),%ecx - adcl $0,%edx - addl %eax,%ebp - movl (%esi,%ecx,4),%eax - adcl $0,%edx - cmpl %ebx,%ecx - movl %ebp,24(%esp,%ecx,4) - jl .L0143rdmadd - movl %edx,%ebp - mull %edi - addl 32(%esp,%ebx,4),%ebp - adcl $0,%edx - addl %eax,%ebp - adcl $0,%edx - movl %ebp,28(%esp,%ebx,4) - movl 12(%esp),%ecx - xorl %eax,%eax - movl 8(%esp),%esi - addl 36(%esp,%ebx,4),%edx - adcl 40(%esp,%ebx,4),%eax - movl %edx,32(%esp,%ebx,4) - cmpl %ebx,%ecx - movl %eax,36(%esp,%ebx,4) - je .L008common_tail - movl 4(%esi,%ecx,4),%edi - leal 1(%ecx),%ecx - movl %edi,%eax - movl %ecx,12(%esp) - mull %edi - addl 32(%esp,%ecx,4),%eax - adcl $0,%edx - movl %eax,32(%esp,%ecx,4) - xorl %ebp,%ebp - cmpl %ebx,%ecx - leal 1(%ecx),%ecx - je .L015sqrlast - movl %edx,%ebx - shrl $1,%edx - andl $1,%ebx -.align 16 -.L016sqradd: - movl (%esi,%ecx,4),%eax - movl %edx,%ebp - mull %edi - addl %ebp,%eax - leal (%eax,%eax,1),%ebp - adcl $0,%edx - shrl $31,%eax - addl 32(%esp,%ecx,4),%ebp - leal 1(%ecx),%ecx - adcl $0,%eax - addl %ebx,%ebp - adcl $0,%eax - cmpl (%esp),%ecx - movl %ebp,28(%esp,%ecx,4) - movl %eax,%ebx - jle .L016sqradd - movl %edx,%ebp - addl %edx,%edx - shrl $31,%ebp - addl %ebx,%edx - adcl $0,%ebp -.L015sqrlast: - movl 20(%esp),%edi - movl 16(%esp),%esi - imull 32(%esp),%edi - addl 32(%esp,%ecx,4),%edx - movl (%esi),%eax - adcl $0,%ebp - movl %edx,32(%esp,%ecx,4) - movl %ebp,36(%esp,%ecx,4) - mull %edi - addl 32(%esp),%eax - leal -1(%ecx),%ebx - adcl $0,%edx - movl $1,%ecx - movl 4(%esi),%eax - jmp .L0143rdmadd -.align 16 -.L008common_tail: +.L006common_tail: movl 16(%esp),%ebp movl 4(%esp),%edi leal 32(%esp),%esi @@ -443,19 +184,19 @@ bn_mul_mont: movl %ebx,%ecx xorl %edx,%edx .align 16 -.L017sub: +.L007sub: sbbl (%ebp,%edx,4),%eax movl %eax,(%edi,%edx,4) decl %ecx movl 4(%esi,%edx,4),%eax leal 1(%edx),%edx - jge .L017sub + jge .L007sub sbbl $0,%eax movl $-1,%edx xorl %eax,%edx - jmp .L018copy + jmp .L008copy .align 16 -.L018copy: +.L008copy: movl 32(%esp,%ebx,4),%esi movl (%edi,%ebx,4),%ebp movl %ecx,32(%esp,%ebx,4) @@ -464,7 +205,7 @@ bn_mul_mont: orl %esi,%ebp movl %ebp,(%edi,%ebx,4) decl %ebx - jge .L018copy + jge .L008copy movl 24(%esp),%esp movl $1,%eax .L000just_leave: diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-win.asm index cd77529cbc..931275d2f0 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86-mont-win.asm @@ -13,7 +13,6 @@ section .text code align=64 %else section .text code %endif -;extern _OPENSSL_ia32cap_P global _bn_mul_mont align 16 _bn_mul_mont: @@ -70,9 +69,6 @@ L$002page_walk_done: mov DWORD [20+esp],esi lea ebx,[edi-3] mov DWORD [24+esp],edx - lea eax,[_OPENSSL_ia32cap_P] - bt DWORD [eax],26 - jnc NEAR L$003non_sse2 mov eax,-1 movd mm7,eax mov esi,DWORD [8+esp] @@ -96,7 +92,7 @@ L$002page_walk_done: psrlq mm3,32 inc ecx align 16 -L$0041st: +L$0031st: pmuludq mm0,mm4 pmuludq mm1,mm5 paddq mm2,mm0 @@ -111,7 +107,7 @@ L$0041st: psrlq mm3,32 lea ecx,[1+ecx] cmp ecx,ebx - jl NEAR L$0041st + jl NEAR L$0031st pmuludq mm0,mm4 pmuludq mm1,mm5 paddq mm2,mm0 @@ -125,7 +121,7 @@ L$0041st: paddq mm3,mm2 movq [32+ebx*4+esp],mm3 inc edx -L$005outer: +L$004outer: xor ecx,ecx movd mm4,DWORD [edx*4+edi] movd mm5,DWORD [esi] @@ -147,7 +143,7 @@ L$005outer: paddq mm2,mm6 inc ecx dec ebx -L$006inner: +L$005inner: pmuludq mm0,mm4 pmuludq mm1,mm5 paddq mm2,mm0 @@ -164,7 +160,7 @@ L$006inner: paddq mm2,mm6 dec ebx lea ecx,[1+ecx] - jnz NEAR L$006inner + jnz NEAR L$005inner mov ebx,ecx pmuludq mm0,mm4 pmuludq mm1,mm5 @@ -182,264 +178,11 @@ L$006inner: movq [32+ebx*4+esp],mm3 lea edx,[1+edx] cmp edx,ebx - jle NEAR L$005outer + jle NEAR L$004outer emms - jmp NEAR L$007common_tail + jmp NEAR L$006common_tail align 16 -L$003non_sse2: - mov esi,DWORD [8+esp] - lea ebp,[1+ebx] - mov edi,DWORD [12+esp] - xor ecx,ecx - mov edx,esi - and ebp,1 - sub edx,edi - lea eax,[4+ebx*4+edi] - or ebp,edx - mov edi,DWORD [edi] - jz NEAR L$008bn_sqr_mont - mov DWORD [28+esp],eax - mov eax,DWORD [esi] - xor edx,edx -align 16 -L$009mull: - mov ebp,edx - mul edi - add ebp,eax - lea ecx,[1+ecx] - adc edx,0 - mov eax,DWORD [ecx*4+esi] - cmp ecx,ebx - mov DWORD [28+ecx*4+esp],ebp - jl NEAR L$009mull - mov ebp,edx - mul edi - mov edi,DWORD [20+esp] - add eax,ebp - mov esi,DWORD [16+esp] - adc edx,0 - imul edi,DWORD [32+esp] - mov DWORD [32+ebx*4+esp],eax - xor ecx,ecx - mov DWORD [36+ebx*4+esp],edx - mov DWORD [40+ebx*4+esp],ecx - mov eax,DWORD [esi] - mul edi - add eax,DWORD [32+esp] - mov eax,DWORD [4+esi] - adc edx,0 - inc ecx - jmp NEAR L$0102ndmadd -align 16 -L$0111stmadd: - mov ebp,edx - mul edi - add ebp,DWORD [32+ecx*4+esp] - lea ecx,[1+ecx] - adc edx,0 - add ebp,eax - mov eax,DWORD [ecx*4+esi] - adc edx,0 - cmp ecx,ebx - mov DWORD [28+ecx*4+esp],ebp - jl NEAR L$0111stmadd - mov ebp,edx - mul edi - add eax,DWORD [32+ebx*4+esp] - mov edi,DWORD [20+esp] - adc edx,0 - mov esi,DWORD [16+esp] - add ebp,eax - adc edx,0 - imul edi,DWORD [32+esp] - xor ecx,ecx - add edx,DWORD [36+ebx*4+esp] - mov DWORD [32+ebx*4+esp],ebp - adc ecx,0 - mov eax,DWORD [esi] - mov DWORD [36+ebx*4+esp],edx - mov DWORD [40+ebx*4+esp],ecx - mul edi - add eax,DWORD [32+esp] - mov eax,DWORD [4+esi] - adc edx,0 - mov ecx,1 -align 16 -L$0102ndmadd: - mov ebp,edx - mul edi - add ebp,DWORD [32+ecx*4+esp] - lea ecx,[1+ecx] - adc edx,0 - add ebp,eax - mov eax,DWORD [ecx*4+esi] - adc edx,0 - cmp ecx,ebx - mov DWORD [24+ecx*4+esp],ebp - jl NEAR L$0102ndmadd - mov ebp,edx - mul edi - add ebp,DWORD [32+ebx*4+esp] - adc edx,0 - add ebp,eax - adc edx,0 - mov DWORD [28+ebx*4+esp],ebp - xor eax,eax - mov ecx,DWORD [12+esp] - add edx,DWORD [36+ebx*4+esp] - adc eax,DWORD [40+ebx*4+esp] - lea ecx,[4+ecx] - mov DWORD [32+ebx*4+esp],edx - cmp ecx,DWORD [28+esp] - mov DWORD [36+ebx*4+esp],eax - je NEAR L$007common_tail - mov edi,DWORD [ecx] - mov esi,DWORD [8+esp] - mov DWORD [12+esp],ecx - xor ecx,ecx - xor edx,edx - mov eax,DWORD [esi] - jmp NEAR L$0111stmadd -align 16 -L$008bn_sqr_mont: - mov DWORD [esp],ebx - mov DWORD [12+esp],ecx - mov eax,edi - mul edi - mov DWORD [32+esp],eax - mov ebx,edx - shr edx,1 - and ebx,1 - inc ecx -align 16 -L$012sqr: - mov eax,DWORD [ecx*4+esi] - mov ebp,edx - mul edi - add eax,ebp - lea ecx,[1+ecx] - adc edx,0 - lea ebp,[eax*2+ebx] - shr eax,31 - cmp ecx,DWORD [esp] - mov ebx,eax - mov DWORD [28+ecx*4+esp],ebp - jl NEAR L$012sqr - mov eax,DWORD [ecx*4+esi] - mov ebp,edx - mul edi - add eax,ebp - mov edi,DWORD [20+esp] - adc edx,0 - mov esi,DWORD [16+esp] - lea ebp,[eax*2+ebx] - imul edi,DWORD [32+esp] - shr eax,31 - mov DWORD [32+ecx*4+esp],ebp - lea ebp,[edx*2+eax] - mov eax,DWORD [esi] - shr edx,31 - mov DWORD [36+ecx*4+esp],ebp - mov DWORD [40+ecx*4+esp],edx - mul edi - add eax,DWORD [32+esp] - mov ebx,ecx - adc edx,0 - mov eax,DWORD [4+esi] - mov ecx,1 -align 16 -L$0133rdmadd: - mov ebp,edx - mul edi - add ebp,DWORD [32+ecx*4+esp] - adc edx,0 - add ebp,eax - mov eax,DWORD [4+ecx*4+esi] - adc edx,0 - mov DWORD [28+ecx*4+esp],ebp - mov ebp,edx - mul edi - add ebp,DWORD [36+ecx*4+esp] - lea ecx,[2+ecx] - adc edx,0 - add ebp,eax - mov eax,DWORD [ecx*4+esi] - adc edx,0 - cmp ecx,ebx - mov DWORD [24+ecx*4+esp],ebp - jl NEAR L$0133rdmadd - mov ebp,edx - mul edi - add ebp,DWORD [32+ebx*4+esp] - adc edx,0 - add ebp,eax - adc edx,0 - mov DWORD [28+ebx*4+esp],ebp - mov ecx,DWORD [12+esp] - xor eax,eax - mov esi,DWORD [8+esp] - add edx,DWORD [36+ebx*4+esp] - adc eax,DWORD [40+ebx*4+esp] - mov DWORD [32+ebx*4+esp],edx - cmp ecx,ebx - mov DWORD [36+ebx*4+esp],eax - je NEAR L$007common_tail - mov edi,DWORD [4+ecx*4+esi] - lea ecx,[1+ecx] - mov eax,edi - mov DWORD [12+esp],ecx - mul edi - add eax,DWORD [32+ecx*4+esp] - adc edx,0 - mov DWORD [32+ecx*4+esp],eax - xor ebp,ebp - cmp ecx,ebx - lea ecx,[1+ecx] - je NEAR L$014sqrlast - mov ebx,edx - shr edx,1 - and ebx,1 -align 16 -L$015sqradd: - mov eax,DWORD [ecx*4+esi] - mov ebp,edx - mul edi - add eax,ebp - lea ebp,[eax*1+eax] - adc edx,0 - shr eax,31 - add ebp,DWORD [32+ecx*4+esp] - lea ecx,[1+ecx] - adc eax,0 - add ebp,ebx - adc eax,0 - cmp ecx,DWORD [esp] - mov DWORD [28+ecx*4+esp],ebp - mov ebx,eax - jle NEAR L$015sqradd - mov ebp,edx - add edx,edx - shr ebp,31 - add edx,ebx - adc ebp,0 -L$014sqrlast: - mov edi,DWORD [20+esp] - mov esi,DWORD [16+esp] - imul edi,DWORD [32+esp] - add edx,DWORD [32+ecx*4+esp] - mov eax,DWORD [esi] - adc ebp,0 - mov DWORD [32+ecx*4+esp],edx - mov DWORD [36+ecx*4+esp],ebp - mul edi - add eax,DWORD [32+esp] - lea ebx,[ecx-1] - adc edx,0 - mov ecx,1 - mov eax,DWORD [4+esi] - jmp NEAR L$0133rdmadd -align 16 -L$007common_tail: +L$006common_tail: mov ebp,DWORD [16+esp] mov edi,DWORD [4+esp] lea esi,[32+esp] @@ -447,19 +190,19 @@ L$007common_tail: mov ecx,ebx xor edx,edx align 16 -L$016sub: +L$007sub: sbb eax,DWORD [edx*4+ebp] mov DWORD [edx*4+edi],eax dec ecx mov eax,DWORD [4+edx*4+esi] lea edx,[1+edx] - jge NEAR L$016sub + jge NEAR L$007sub sbb eax,0 mov edx,-1 xor edx,eax - jmp NEAR L$017copy + jmp NEAR L$008copy align 16 -L$017copy: +L$008copy: mov esi,DWORD [32+ebx*4+esp] mov ebp,DWORD [ebx*4+edi] mov DWORD [32+ebx*4+esp],ecx @@ -468,7 +211,7 @@ L$017copy: or ebp,esi mov DWORD [ebx*4+edi],ebp dec ebx - jge NEAR L$017copy + jge NEAR L$008copy mov esp,DWORD [24+esp] mov eax,1 L$000just_leave: @@ -482,8 +225,6 @@ db 112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56 db 54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121 db 32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46 db 111,114,103,62,0 -segment .bss -common _OPENSSL_ia32cap_P 16 %else ; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738 ret diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-apple.S index bd63d91c8a..5cf770f1d5 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-apple.S @@ -6,26 +6,18 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__APPLE__) .text - - -.globl _bn_mul_mont_gather5 -.private_extern _bn_mul_mont_gather5 +.globl _bn_mul_mont_gather5_nohw +.private_extern _bn_mul_mont_gather5_nohw .p2align 6 -_bn_mul_mont_gather5: +_bn_mul_mont_gather5_nohw: _CET_ENDBR + + movl %r9d,%r9d movq %rsp,%rax - testl $7,%r9d - jnz L$mul_enter - leaq _OPENSSL_ia32cap_P(%rip),%r11 - movl 8(%r11),%r11d - jmp L$mul4x_enter - -.p2align 4 -L$mul_enter: movd 8(%rsp),%xmm5 pushq %rbx @@ -452,17 +444,16 @@ L$mul_epilogue: ret +.globl _bn_mul4x_mont_gather5 +.private_extern _bn_mul4x_mont_gather5 .p2align 5 -bn_mul4x_mont_gather5: +_bn_mul4x_mont_gather5: +_CET_ENDBR .byte 0x67 movq %rsp,%rax -L$mul4x_enter: - andl $0x80108,%r11d - cmpl $0x80108,%r11d - je L$mulx4x_enter pushq %rbx pushq %rbp @@ -478,6 +469,9 @@ L$mul4x_enter: L$mul4x_prologue: .byte 0x67 + + + shll $3,%r9d leaq (%r9,%r9,2),%r10 negq %r9 @@ -1087,20 +1081,15 @@ L$inner4x: jmp L$sqr4x_sub_entry -.globl _bn_power5 -.private_extern _bn_power5 +.globl _bn_power5_nohw +.private_extern _bn_power5_nohw .p2align 5 -_bn_power5: +_bn_power5_nohw: _CET_ENDBR movq %rsp,%rax - leaq _OPENSSL_ia32cap_P(%rip),%r11 - movl 8(%r11),%r11d - andl $0x80108,%r11d - cmpl $0x80108,%r11d - je L$powerx5_enter pushq %rbx pushq %rbp @@ -1115,6 +1104,9 @@ _CET_ENDBR L$power5_prologue: + + + shll $3,%r9d leal (%r9,%r9,2),%r10d negq %r9 @@ -2066,13 +2058,15 @@ L$sqr4x_sub_entry: ret +.globl _bn_mulx4x_mont_gather5 +.private_extern _bn_mulx4x_mont_gather5 .p2align 5 -bn_mulx4x_mont_gather5: +_bn_mulx4x_mont_gather5: +_CET_ENDBR movq %rsp,%rax -L$mulx4x_enter: pushq %rbx pushq %rbp @@ -2087,6 +2081,9 @@ L$mulx4x_enter: L$mulx4x_prologue: + + + shll $3,%r9d leaq (%r9,%r9,2),%r10 negq %r9 @@ -2603,13 +2600,15 @@ L$mulx4x_inner: jmp L$sqrx4x_sub_entry +.globl _bn_powerx5 +.private_extern _bn_powerx5 .p2align 5 -bn_powerx5: +_bn_powerx5: +_CET_ENDBR movq %rsp,%rax -L$powerx5_enter: pushq %rbx pushq %rbp @@ -2624,6 +2623,9 @@ L$powerx5_enter: L$powerx5_prologue: + + + shll $3,%r9d leaq (%r9,%r9,2),%r10 negq %r9 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-linux.S index 14ab4f72a4..dcc02fc7fb 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-linux.S @@ -6,27 +6,18 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__ELF__) .text -.extern OPENSSL_ia32cap_P -.hidden OPENSSL_ia32cap_P - -.globl bn_mul_mont_gather5 -.hidden bn_mul_mont_gather5 -.type bn_mul_mont_gather5,@function +.globl bn_mul_mont_gather5_nohw +.hidden bn_mul_mont_gather5_nohw +.type bn_mul_mont_gather5_nohw,@function .align 64 -bn_mul_mont_gather5: +bn_mul_mont_gather5_nohw: .cfi_startproc _CET_ENDBR + + movl %r9d,%r9d movq %rsp,%rax .cfi_def_cfa_register %rax - testl $7,%r9d - jnz .Lmul_enter - leaq OPENSSL_ia32cap_P(%rip),%r11 - movl 8(%r11),%r11d - jmp .Lmul4x_enter - -.align 16 -.Lmul_enter: movd 8(%rsp),%xmm5 pushq %rbx .cfi_offset %rbx,-16 @@ -452,18 +443,17 @@ _CET_ENDBR .Lmul_epilogue: ret .cfi_endproc -.size bn_mul_mont_gather5,.-bn_mul_mont_gather5 +.size bn_mul_mont_gather5_nohw,.-bn_mul_mont_gather5_nohw +.globl bn_mul4x_mont_gather5 +.hidden bn_mul4x_mont_gather5 .type bn_mul4x_mont_gather5,@function .align 32 bn_mul4x_mont_gather5: .cfi_startproc +_CET_ENDBR .byte 0x67 movq %rsp,%rax .cfi_def_cfa_register %rax -.Lmul4x_enter: - andl $0x80108,%r11d - cmpl $0x80108,%r11d - je .Lmulx4x_enter pushq %rbx .cfi_offset %rbx,-16 pushq %rbp @@ -479,6 +469,9 @@ bn_mul4x_mont_gather5: .Lmul4x_prologue: .byte 0x67 + + + shll $3,%r9d leaq (%r9,%r9,2),%r10 negq %r9 @@ -1088,20 +1081,15 @@ mul4x_internal: jmp .Lsqr4x_sub_entry .cfi_endproc .size mul4x_internal,.-mul4x_internal -.globl bn_power5 -.hidden bn_power5 -.type bn_power5,@function +.globl bn_power5_nohw +.hidden bn_power5_nohw +.type bn_power5_nohw,@function .align 32 -bn_power5: +bn_power5_nohw: .cfi_startproc _CET_ENDBR movq %rsp,%rax .cfi_def_cfa_register %rax - leaq OPENSSL_ia32cap_P(%rip),%r11 - movl 8(%r11),%r11d - andl $0x80108,%r11d - cmpl $0x80108,%r11d - je .Lpowerx5_enter pushq %rbx .cfi_offset %rbx,-16 pushq %rbp @@ -1116,6 +1104,9 @@ _CET_ENDBR .cfi_offset %r15,-56 .Lpower5_prologue: + + + shll $3,%r9d leal (%r9,%r9,2),%r10d negq %r9 @@ -1224,7 +1215,7 @@ _CET_ENDBR .Lpower5_epilogue: ret .cfi_endproc -.size bn_power5,.-bn_power5 +.size bn_power5_nohw,.-bn_power5_nohw .globl bn_sqr8x_internal .hidden bn_sqr8x_internal @@ -2067,13 +2058,15 @@ __bn_post4x_internal: ret .cfi_endproc .size __bn_post4x_internal,.-__bn_post4x_internal +.globl bn_mulx4x_mont_gather5 +.hidden bn_mulx4x_mont_gather5 .type bn_mulx4x_mont_gather5,@function .align 32 bn_mulx4x_mont_gather5: .cfi_startproc +_CET_ENDBR movq %rsp,%rax .cfi_def_cfa_register %rax -.Lmulx4x_enter: pushq %rbx .cfi_offset %rbx,-16 pushq %rbp @@ -2088,6 +2081,9 @@ bn_mulx4x_mont_gather5: .cfi_offset %r15,-56 .Lmulx4x_prologue: + + + shll $3,%r9d leaq (%r9,%r9,2),%r10 negq %r9 @@ -2604,13 +2600,15 @@ mulx4x_internal: jmp .Lsqrx4x_sub_entry .cfi_endproc .size mulx4x_internal,.-mulx4x_internal +.globl bn_powerx5 +.hidden bn_powerx5 .type bn_powerx5,@function .align 32 bn_powerx5: .cfi_startproc +_CET_ENDBR movq %rsp,%rax .cfi_def_cfa_register %rax -.Lpowerx5_enter: pushq %rbx .cfi_offset %rbx,-16 pushq %rbp @@ -2625,6 +2623,9 @@ bn_powerx5: .cfi_offset %r15,-56 .Lpowerx5_prologue: + + + shll $3,%r9d leaq (%r9,%r9,2),%r10 negq %r9 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-win.asm index 46aae51739..3b12405d0d 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/bcm/x86_64-mont5-win.asm @@ -14,16 +14,14 @@ default rel section .text code align=64 -EXTERN OPENSSL_ia32cap_P - -global bn_mul_mont_gather5 +global bn_mul_mont_gather5_nohw ALIGN 64 -bn_mul_mont_gather5: +bn_mul_mont_gather5_nohw: mov QWORD[8+rsp],rdi ;WIN64 prologue mov QWORD[16+rsp],rsi mov rax,rsp -$L$SEH_begin_bn_mul_mont_gather5: +$L$SEH_begin_bn_mul_mont_gather5_nohw: mov rdi,rcx mov rsi,rdx mov rdx,r8 @@ -34,17 +32,11 @@ $L$SEH_begin_bn_mul_mont_gather5: _CET_ENDBR + + mov r9d,r9d mov rax,rsp - test r9d,7 - jnz NEAR $L$mul_enter - lea r11,[OPENSSL_ia32cap_P] - mov r11d,DWORD[8+r11] - jmp NEAR $L$mul4x_enter - -ALIGN 16 -$L$mul_enter: movd xmm5,DWORD[56+rsp] push rbx @@ -472,7 +464,8 @@ $L$mul_epilogue: mov rsi,QWORD[16+rsp] ret -$L$SEH_end_bn_mul_mont_gather5: +$L$SEH_end_bn_mul_mont_gather5_nohw: +global bn_mul4x_mont_gather5 ALIGN 32 bn_mul4x_mont_gather5: @@ -489,13 +482,10 @@ $L$SEH_begin_bn_mul4x_mont_gather5: +_CET_ENDBR DB 0x67 mov rax,rsp -$L$mul4x_enter: - and r11d,0x80108 - cmp r11d,0x80108 - je NEAR $L$mulx4x_enter push rbx push rbp @@ -511,6 +501,9 @@ $L$mul4x_enter: $L$mul4x_prologue: DB 0x67 + + + shl r9d,3 lea r10,[r9*2+r9] neg r9 @@ -1122,14 +1115,14 @@ $L$inner4x: jmp NEAR $L$sqr4x_sub_entry -global bn_power5 +global bn_power5_nohw ALIGN 32 -bn_power5: +bn_power5_nohw: mov QWORD[8+rsp],rdi ;WIN64 prologue mov QWORD[16+rsp],rsi mov rax,rsp -$L$SEH_begin_bn_power5: +$L$SEH_begin_bn_power5_nohw: mov rdi,rcx mov rsi,rdx mov rdx,r8 @@ -1142,11 +1135,6 @@ $L$SEH_begin_bn_power5: _CET_ENDBR mov rax,rsp - lea r11,[OPENSSL_ia32cap_P] - mov r11d,DWORD[8+r11] - and r11d,0x80108 - cmp r11d,0x80108 - je NEAR $L$powerx5_enter push rbx push rbp @@ -1161,6 +1149,9 @@ _CET_ENDBR $L$power5_prologue: + + + shl r9d,3 lea r10d,[r9*2+r9] neg r9 @@ -1271,7 +1262,7 @@ $L$power5_epilogue: mov rsi,QWORD[16+rsp] ret -$L$SEH_end_bn_power5: +$L$SEH_end_bn_power5_nohw: global bn_sqr8x_internal @@ -2113,6 +2104,7 @@ $L$sqr4x_sub_entry: ret +global bn_mulx4x_mont_gather5 ALIGN 32 bn_mulx4x_mont_gather5: @@ -2129,9 +2121,9 @@ $L$SEH_begin_bn_mulx4x_mont_gather5: +_CET_ENDBR mov rax,rsp -$L$mulx4x_enter: push rbx push rbp @@ -2146,6 +2138,9 @@ $L$mulx4x_enter: $L$mulx4x_prologue: + + + shl r9d,3 lea r10,[r9*2+r9] neg r9 @@ -2664,6 +2659,7 @@ $L$mulx4x_inner: jmp NEAR $L$sqrx4x_sub_entry +global bn_powerx5 ALIGN 32 bn_powerx5: @@ -2680,9 +2676,9 @@ $L$SEH_begin_bn_powerx5: +_CET_ENDBR mov rax,rsp -$L$powerx5_enter: push rbx push rbp @@ -2697,6 +2693,9 @@ $L$powerx5_enter: $L$powerx5_prologue: + + + shl r9d,3 lea r10,[r9*2+r9] neg r9 @@ -3804,17 +3803,17 @@ $L$common_seh_tail: section .pdata rdata align=4 ALIGN 4 - DD $L$SEH_begin_bn_mul_mont_gather5 wrt ..imagebase - DD $L$SEH_end_bn_mul_mont_gather5 wrt ..imagebase - DD $L$SEH_info_bn_mul_mont_gather5 wrt ..imagebase + DD $L$SEH_begin_bn_mul_mont_gather5_nohw wrt ..imagebase + DD $L$SEH_end_bn_mul_mont_gather5_nohw wrt ..imagebase + DD $L$SEH_info_bn_mul_mont_gather5_nohw wrt ..imagebase DD $L$SEH_begin_bn_mul4x_mont_gather5 wrt ..imagebase DD $L$SEH_end_bn_mul4x_mont_gather5 wrt ..imagebase DD $L$SEH_info_bn_mul4x_mont_gather5 wrt ..imagebase - DD $L$SEH_begin_bn_power5 wrt ..imagebase - DD $L$SEH_end_bn_power5 wrt ..imagebase - DD $L$SEH_info_bn_power5 wrt ..imagebase + DD $L$SEH_begin_bn_power5_nohw wrt ..imagebase + DD $L$SEH_end_bn_power5_nohw wrt ..imagebase + DD $L$SEH_info_bn_power5_nohw wrt ..imagebase DD $L$SEH_begin_bn_mulx4x_mont_gather5 wrt ..imagebase DD $L$SEH_end_bn_mulx4x_mont_gather5 wrt ..imagebase DD $L$SEH_info_bn_mulx4x_mont_gather5 wrt ..imagebase @@ -3828,7 +3827,7 @@ ALIGN 4 section .xdata rdata align=8 ALIGN 8 -$L$SEH_info_bn_mul_mont_gather5: +$L$SEH_info_bn_mul_mont_gather5_nohw: DB 9,0,0,0 DD mul_handler wrt ..imagebase DD $L$mul_body wrt ..imagebase,$L$mul_body wrt ..imagebase,$L$mul_epilogue wrt ..imagebase @@ -3838,7 +3837,7 @@ $L$SEH_info_bn_mul4x_mont_gather5: DD mul_handler wrt ..imagebase DD $L$mul4x_prologue wrt ..imagebase,$L$mul4x_body wrt ..imagebase,$L$mul4x_epilogue wrt ..imagebase ALIGN 8 -$L$SEH_info_bn_power5: +$L$SEH_info_bn_power5_nohw: DB 9,0,0,0 DD mul_handler wrt ..imagebase DD $L$power5_prologue wrt ..imagebase,$L$power5_body wrt ..imagebase,$L$power5_epilogue wrt ..imagebase diff --git a/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-apple.S index a5e12075e3..d330661c4e 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-apple.S @@ -459,7 +459,6 @@ _ChaCha20_ctr32_ssse3_4x: _CET_ENDBR movq %rsp,%r9 - movq %r10,%r11 subq $0x140+8,%rsp movdqa L$sigma(%rip),%xmm11 movdqu (%rcx),%xmm15 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-linux.S index 9dbf7d1f06..d76e6d0e93 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-linux.S @@ -465,7 +465,6 @@ ChaCha20_ctr32_ssse3_4x: _CET_ENDBR movq %rsp,%r9 .cfi_def_cfa_register r9 - movq %r10,%r11 subq $0x140+8,%rsp movdqa .Lsigma(%rip),%xmm11 movdqu (%rcx),%xmm15 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-win.asm index 14f239511f..f1f9a0dab7 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/crypto/chacha-x86_64-win.asm @@ -511,7 +511,6 @@ $L$SEH_begin_ChaCha20_ctr32_ssse3_4x: _CET_ENDBR mov r9,rsp - mov r11,r10 sub rsp,0x140+168 movaps XMMWORD[(-168)+r9],xmm6 movaps XMMWORD[(-152)+r9],xmm7 diff --git a/naiveproxy/src/third_party/boringssl/src/gen/sources.bzl b/naiveproxy/src/third_party/boringssl/src/gen/sources.bzl index 7717b76b2a..d8e96ea0ac 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/sources.bzl +++ b/naiveproxy/src/third_party/boringssl/src/gen/sources.bzl @@ -15,2654 +15,2671 @@ # Generated by go ./util/pregenerate. Do not edit manually. bcm_sources = [ - "crypto/fipsmodule/bcm.c", + "crypto/fipsmodule/bcm.c", ] bcm_internal_headers = [ - "crypto/fipsmodule/aes/aes.c", - "crypto/fipsmodule/aes/aes_nohw.c", - "crypto/fipsmodule/aes/key_wrap.c", - "crypto/fipsmodule/aes/mode_wrappers.c", - "crypto/fipsmodule/bn/add.c", - "crypto/fipsmodule/bn/asm/x86_64-gcc.c", - "crypto/fipsmodule/bn/bn.c", - "crypto/fipsmodule/bn/bytes.c", - "crypto/fipsmodule/bn/cmp.c", - "crypto/fipsmodule/bn/ctx.c", - "crypto/fipsmodule/bn/div.c", - "crypto/fipsmodule/bn/div_extra.c", - "crypto/fipsmodule/bn/exponentiation.c", - "crypto/fipsmodule/bn/gcd.c", - "crypto/fipsmodule/bn/gcd_extra.c", - "crypto/fipsmodule/bn/generic.c", - "crypto/fipsmodule/bn/jacobi.c", - "crypto/fipsmodule/bn/montgomery.c", - "crypto/fipsmodule/bn/montgomery_inv.c", - "crypto/fipsmodule/bn/mul.c", - "crypto/fipsmodule/bn/prime.c", - "crypto/fipsmodule/bn/random.c", - "crypto/fipsmodule/bn/rsaz_exp.c", - "crypto/fipsmodule/bn/shift.c", - "crypto/fipsmodule/bn/sqrt.c", - "crypto/fipsmodule/cipher/aead.c", - "crypto/fipsmodule/cipher/cipher.c", - "crypto/fipsmodule/cipher/e_aes.c", - "crypto/fipsmodule/cipher/e_aesccm.c", - "crypto/fipsmodule/cmac/cmac.c", - "crypto/fipsmodule/dh/check.c", - "crypto/fipsmodule/dh/dh.c", - "crypto/fipsmodule/digest/digest.c", - "crypto/fipsmodule/digest/digests.c", - "crypto/fipsmodule/digestsign/digestsign.c", - "crypto/fipsmodule/ec/ec.c", - "crypto/fipsmodule/ec/ec_key.c", - "crypto/fipsmodule/ec/ec_montgomery.c", - "crypto/fipsmodule/ec/felem.c", - "crypto/fipsmodule/ec/oct.c", - "crypto/fipsmodule/ec/p224-64.c", - "crypto/fipsmodule/ec/p256-nistz.c", - "crypto/fipsmodule/ec/p256.c", - "crypto/fipsmodule/ec/scalar.c", - "crypto/fipsmodule/ec/simple.c", - "crypto/fipsmodule/ec/simple_mul.c", - "crypto/fipsmodule/ec/util.c", - "crypto/fipsmodule/ec/wnaf.c", - "crypto/fipsmodule/ecdh/ecdh.c", - "crypto/fipsmodule/ecdsa/ecdsa.c", - "crypto/fipsmodule/hkdf/hkdf.c", - "crypto/fipsmodule/hmac/hmac.c", - "crypto/fipsmodule/md4/md4.c", - "crypto/fipsmodule/md5/md5.c", - "crypto/fipsmodule/modes/cbc.c", - "crypto/fipsmodule/modes/cfb.c", - "crypto/fipsmodule/modes/ctr.c", - "crypto/fipsmodule/modes/gcm.c", - "crypto/fipsmodule/modes/gcm_nohw.c", - "crypto/fipsmodule/modes/ofb.c", - "crypto/fipsmodule/modes/polyval.c", - "crypto/fipsmodule/rand/ctrdrbg.c", - "crypto/fipsmodule/rand/fork_detect.c", - "crypto/fipsmodule/rand/rand.c", - "crypto/fipsmodule/rand/urandom.c", - "crypto/fipsmodule/rsa/blinding.c", - "crypto/fipsmodule/rsa/padding.c", - "crypto/fipsmodule/rsa/rsa.c", - "crypto/fipsmodule/rsa/rsa_impl.c", - "crypto/fipsmodule/self_check/fips.c", - "crypto/fipsmodule/self_check/self_check.c", - "crypto/fipsmodule/service_indicator/service_indicator.c", - "crypto/fipsmodule/sha/sha1.c", - "crypto/fipsmodule/sha/sha256.c", - "crypto/fipsmodule/sha/sha512.c", - "crypto/fipsmodule/tls/kdf.c", + "crypto/fipsmodule/aes/aes.c", + "crypto/fipsmodule/aes/aes_nohw.c", + "crypto/fipsmodule/aes/key_wrap.c", + "crypto/fipsmodule/aes/mode_wrappers.c", + "crypto/fipsmodule/bn/add.c", + "crypto/fipsmodule/bn/asm/x86_64-gcc.c", + "crypto/fipsmodule/bn/bn.c", + "crypto/fipsmodule/bn/bytes.c", + "crypto/fipsmodule/bn/cmp.c", + "crypto/fipsmodule/bn/ctx.c", + "crypto/fipsmodule/bn/div.c", + "crypto/fipsmodule/bn/div_extra.c", + "crypto/fipsmodule/bn/exponentiation.c", + "crypto/fipsmodule/bn/gcd.c", + "crypto/fipsmodule/bn/gcd_extra.c", + "crypto/fipsmodule/bn/generic.c", + "crypto/fipsmodule/bn/jacobi.c", + "crypto/fipsmodule/bn/montgomery.c", + "crypto/fipsmodule/bn/montgomery_inv.c", + "crypto/fipsmodule/bn/mul.c", + "crypto/fipsmodule/bn/prime.c", + "crypto/fipsmodule/bn/random.c", + "crypto/fipsmodule/bn/rsaz_exp.c", + "crypto/fipsmodule/bn/shift.c", + "crypto/fipsmodule/bn/sqrt.c", + "crypto/fipsmodule/cipher/aead.c", + "crypto/fipsmodule/cipher/cipher.c", + "crypto/fipsmodule/cipher/e_aes.c", + "crypto/fipsmodule/cipher/e_aesccm.c", + "crypto/fipsmodule/cmac/cmac.c", + "crypto/fipsmodule/dh/check.c", + "crypto/fipsmodule/dh/dh.c", + "crypto/fipsmodule/digest/digest.c", + "crypto/fipsmodule/digest/digests.c", + "crypto/fipsmodule/digestsign/digestsign.c", + "crypto/fipsmodule/ec/ec.c", + "crypto/fipsmodule/ec/ec_key.c", + "crypto/fipsmodule/ec/ec_montgomery.c", + "crypto/fipsmodule/ec/felem.c", + "crypto/fipsmodule/ec/oct.c", + "crypto/fipsmodule/ec/p224-64.c", + "crypto/fipsmodule/ec/p256-nistz.c", + "crypto/fipsmodule/ec/p256.c", + "crypto/fipsmodule/ec/scalar.c", + "crypto/fipsmodule/ec/simple.c", + "crypto/fipsmodule/ec/simple_mul.c", + "crypto/fipsmodule/ec/util.c", + "crypto/fipsmodule/ec/wnaf.c", + "crypto/fipsmodule/ecdh/ecdh.c", + "crypto/fipsmodule/ecdsa/ecdsa.c", + "crypto/fipsmodule/hkdf/hkdf.c", + "crypto/fipsmodule/hmac/hmac.c", + "crypto/fipsmodule/md4/md4.c", + "crypto/fipsmodule/md5/md5.c", + "crypto/fipsmodule/modes/cbc.c", + "crypto/fipsmodule/modes/cfb.c", + "crypto/fipsmodule/modes/ctr.c", + "crypto/fipsmodule/modes/gcm.c", + "crypto/fipsmodule/modes/gcm_nohw.c", + "crypto/fipsmodule/modes/ofb.c", + "crypto/fipsmodule/modes/polyval.c", + "crypto/fipsmodule/rand/ctrdrbg.c", + "crypto/fipsmodule/rand/fork_detect.c", + "crypto/fipsmodule/rand/rand.c", + "crypto/fipsmodule/rand/urandom.c", + "crypto/fipsmodule/rsa/blinding.c", + "crypto/fipsmodule/rsa/padding.c", + "crypto/fipsmodule/rsa/rsa.c", + "crypto/fipsmodule/rsa/rsa_impl.c", + "crypto/fipsmodule/self_check/fips.c", + "crypto/fipsmodule/self_check/self_check.c", + "crypto/fipsmodule/service_indicator/service_indicator.c", + "crypto/fipsmodule/sha/sha1.c", + "crypto/fipsmodule/sha/sha256.c", + "crypto/fipsmodule/sha/sha512.c", + "crypto/fipsmodule/tls/kdf.c", ] bcm_sources_asm = [ - "gen/bcm/aesni-gcm-x86_64-apple.S", - "gen/bcm/aesni-gcm-x86_64-linux.S", - "gen/bcm/aesni-x86-apple.S", - "gen/bcm/aesni-x86-linux.S", - "gen/bcm/aesni-x86_64-apple.S", - "gen/bcm/aesni-x86_64-linux.S", - "gen/bcm/aesv8-armv7-linux.S", - "gen/bcm/aesv8-armv8-apple.S", - "gen/bcm/aesv8-armv8-linux.S", - "gen/bcm/aesv8-armv8-win.S", - "gen/bcm/aesv8-gcm-armv8-apple.S", - "gen/bcm/aesv8-gcm-armv8-linux.S", - "gen/bcm/aesv8-gcm-armv8-win.S", - "gen/bcm/armv4-mont-linux.S", - "gen/bcm/armv8-mont-apple.S", - "gen/bcm/armv8-mont-linux.S", - "gen/bcm/armv8-mont-win.S", - "gen/bcm/bn-586-apple.S", - "gen/bcm/bn-586-linux.S", - "gen/bcm/bn-armv8-apple.S", - "gen/bcm/bn-armv8-linux.S", - "gen/bcm/bn-armv8-win.S", - "gen/bcm/bsaes-armv7-linux.S", - "gen/bcm/co-586-apple.S", - "gen/bcm/co-586-linux.S", - "gen/bcm/ghash-armv4-linux.S", - "gen/bcm/ghash-neon-armv8-apple.S", - "gen/bcm/ghash-neon-armv8-linux.S", - "gen/bcm/ghash-neon-armv8-win.S", - "gen/bcm/ghash-ssse3-x86-apple.S", - "gen/bcm/ghash-ssse3-x86-linux.S", - "gen/bcm/ghash-ssse3-x86_64-apple.S", - "gen/bcm/ghash-ssse3-x86_64-linux.S", - "gen/bcm/ghash-x86-apple.S", - "gen/bcm/ghash-x86-linux.S", - "gen/bcm/ghash-x86_64-apple.S", - "gen/bcm/ghash-x86_64-linux.S", - "gen/bcm/ghashv8-armv7-linux.S", - "gen/bcm/ghashv8-armv8-apple.S", - "gen/bcm/ghashv8-armv8-linux.S", - "gen/bcm/ghashv8-armv8-win.S", - "gen/bcm/md5-586-apple.S", - "gen/bcm/md5-586-linux.S", - "gen/bcm/md5-x86_64-apple.S", - "gen/bcm/md5-x86_64-linux.S", - "gen/bcm/p256-armv8-asm-apple.S", - "gen/bcm/p256-armv8-asm-linux.S", - "gen/bcm/p256-armv8-asm-win.S", - "gen/bcm/p256-x86_64-asm-apple.S", - "gen/bcm/p256-x86_64-asm-linux.S", - "gen/bcm/p256_beeu-armv8-asm-apple.S", - "gen/bcm/p256_beeu-armv8-asm-linux.S", - "gen/bcm/p256_beeu-armv8-asm-win.S", - "gen/bcm/p256_beeu-x86_64-asm-apple.S", - "gen/bcm/p256_beeu-x86_64-asm-linux.S", - "gen/bcm/rdrand-x86_64-apple.S", - "gen/bcm/rdrand-x86_64-linux.S", - "gen/bcm/rsaz-avx2-apple.S", - "gen/bcm/rsaz-avx2-linux.S", - "gen/bcm/sha1-586-apple.S", - "gen/bcm/sha1-586-linux.S", - "gen/bcm/sha1-armv4-large-linux.S", - "gen/bcm/sha1-armv8-apple.S", - "gen/bcm/sha1-armv8-linux.S", - "gen/bcm/sha1-armv8-win.S", - "gen/bcm/sha1-x86_64-apple.S", - "gen/bcm/sha1-x86_64-linux.S", - "gen/bcm/sha256-586-apple.S", - "gen/bcm/sha256-586-linux.S", - "gen/bcm/sha256-armv4-linux.S", - "gen/bcm/sha256-armv8-apple.S", - "gen/bcm/sha256-armv8-linux.S", - "gen/bcm/sha256-armv8-win.S", - "gen/bcm/sha256-x86_64-apple.S", - "gen/bcm/sha256-x86_64-linux.S", - "gen/bcm/sha512-586-apple.S", - "gen/bcm/sha512-586-linux.S", - "gen/bcm/sha512-armv4-linux.S", - "gen/bcm/sha512-armv8-apple.S", - "gen/bcm/sha512-armv8-linux.S", - "gen/bcm/sha512-armv8-win.S", - "gen/bcm/sha512-x86_64-apple.S", - "gen/bcm/sha512-x86_64-linux.S", - "gen/bcm/vpaes-armv7-linux.S", - "gen/bcm/vpaes-armv8-apple.S", - "gen/bcm/vpaes-armv8-linux.S", - "gen/bcm/vpaes-armv8-win.S", - "gen/bcm/vpaes-x86-apple.S", - "gen/bcm/vpaes-x86-linux.S", - "gen/bcm/vpaes-x86_64-apple.S", - "gen/bcm/vpaes-x86_64-linux.S", - "gen/bcm/x86-mont-apple.S", - "gen/bcm/x86-mont-linux.S", - "gen/bcm/x86_64-mont-apple.S", - "gen/bcm/x86_64-mont-linux.S", - "gen/bcm/x86_64-mont5-apple.S", - "gen/bcm/x86_64-mont5-linux.S", + "gen/bcm/aesni-gcm-x86_64-apple.S", + "gen/bcm/aesni-gcm-x86_64-linux.S", + "gen/bcm/aesni-x86-apple.S", + "gen/bcm/aesni-x86-linux.S", + "gen/bcm/aesni-x86_64-apple.S", + "gen/bcm/aesni-x86_64-linux.S", + "gen/bcm/aesv8-armv7-linux.S", + "gen/bcm/aesv8-armv8-apple.S", + "gen/bcm/aesv8-armv8-linux.S", + "gen/bcm/aesv8-armv8-win.S", + "gen/bcm/aesv8-gcm-armv8-apple.S", + "gen/bcm/aesv8-gcm-armv8-linux.S", + "gen/bcm/aesv8-gcm-armv8-win.S", + "gen/bcm/armv4-mont-linux.S", + "gen/bcm/armv8-mont-apple.S", + "gen/bcm/armv8-mont-linux.S", + "gen/bcm/armv8-mont-win.S", + "gen/bcm/bn-586-apple.S", + "gen/bcm/bn-586-linux.S", + "gen/bcm/bn-armv8-apple.S", + "gen/bcm/bn-armv8-linux.S", + "gen/bcm/bn-armv8-win.S", + "gen/bcm/bsaes-armv7-linux.S", + "gen/bcm/co-586-apple.S", + "gen/bcm/co-586-linux.S", + "gen/bcm/ghash-armv4-linux.S", + "gen/bcm/ghash-neon-armv8-apple.S", + "gen/bcm/ghash-neon-armv8-linux.S", + "gen/bcm/ghash-neon-armv8-win.S", + "gen/bcm/ghash-ssse3-x86-apple.S", + "gen/bcm/ghash-ssse3-x86-linux.S", + "gen/bcm/ghash-ssse3-x86_64-apple.S", + "gen/bcm/ghash-ssse3-x86_64-linux.S", + "gen/bcm/ghash-x86-apple.S", + "gen/bcm/ghash-x86-linux.S", + "gen/bcm/ghash-x86_64-apple.S", + "gen/bcm/ghash-x86_64-linux.S", + "gen/bcm/ghashv8-armv7-linux.S", + "gen/bcm/ghashv8-armv8-apple.S", + "gen/bcm/ghashv8-armv8-linux.S", + "gen/bcm/ghashv8-armv8-win.S", + "gen/bcm/md5-586-apple.S", + "gen/bcm/md5-586-linux.S", + "gen/bcm/md5-x86_64-apple.S", + "gen/bcm/md5-x86_64-linux.S", + "gen/bcm/p256-armv8-asm-apple.S", + "gen/bcm/p256-armv8-asm-linux.S", + "gen/bcm/p256-armv8-asm-win.S", + "gen/bcm/p256-x86_64-asm-apple.S", + "gen/bcm/p256-x86_64-asm-linux.S", + "gen/bcm/p256_beeu-armv8-asm-apple.S", + "gen/bcm/p256_beeu-armv8-asm-linux.S", + "gen/bcm/p256_beeu-armv8-asm-win.S", + "gen/bcm/p256_beeu-x86_64-asm-apple.S", + "gen/bcm/p256_beeu-x86_64-asm-linux.S", + "gen/bcm/rdrand-x86_64-apple.S", + "gen/bcm/rdrand-x86_64-linux.S", + "gen/bcm/rsaz-avx2-apple.S", + "gen/bcm/rsaz-avx2-linux.S", + "gen/bcm/sha1-586-apple.S", + "gen/bcm/sha1-586-linux.S", + "gen/bcm/sha1-armv4-large-linux.S", + "gen/bcm/sha1-armv8-apple.S", + "gen/bcm/sha1-armv8-linux.S", + "gen/bcm/sha1-armv8-win.S", + "gen/bcm/sha1-x86_64-apple.S", + "gen/bcm/sha1-x86_64-linux.S", + "gen/bcm/sha256-586-apple.S", + "gen/bcm/sha256-586-linux.S", + "gen/bcm/sha256-armv4-linux.S", + "gen/bcm/sha256-armv8-apple.S", + "gen/bcm/sha256-armv8-linux.S", + "gen/bcm/sha256-armv8-win.S", + "gen/bcm/sha256-x86_64-apple.S", + "gen/bcm/sha256-x86_64-linux.S", + "gen/bcm/sha512-586-apple.S", + "gen/bcm/sha512-586-linux.S", + "gen/bcm/sha512-armv4-linux.S", + "gen/bcm/sha512-armv8-apple.S", + "gen/bcm/sha512-armv8-linux.S", + "gen/bcm/sha512-armv8-win.S", + "gen/bcm/sha512-x86_64-apple.S", + "gen/bcm/sha512-x86_64-linux.S", + "gen/bcm/vpaes-armv7-linux.S", + "gen/bcm/vpaes-armv8-apple.S", + "gen/bcm/vpaes-armv8-linux.S", + "gen/bcm/vpaes-armv8-win.S", + "gen/bcm/vpaes-x86-apple.S", + "gen/bcm/vpaes-x86-linux.S", + "gen/bcm/vpaes-x86_64-apple.S", + "gen/bcm/vpaes-x86_64-linux.S", + "gen/bcm/x86-mont-apple.S", + "gen/bcm/x86-mont-linux.S", + "gen/bcm/x86_64-mont-apple.S", + "gen/bcm/x86_64-mont-linux.S", + "gen/bcm/x86_64-mont5-apple.S", + "gen/bcm/x86_64-mont5-linux.S", + "third_party/fiat/asm/fiat_p256_adx_mul.S", + "third_party/fiat/asm/fiat_p256_adx_sqr.S", ] bcm_sources_nasm = [ - "gen/bcm/aesni-gcm-x86_64-win.asm", - "gen/bcm/aesni-x86-win.asm", - "gen/bcm/aesni-x86_64-win.asm", - "gen/bcm/bn-586-win.asm", - "gen/bcm/co-586-win.asm", - "gen/bcm/ghash-ssse3-x86-win.asm", - "gen/bcm/ghash-ssse3-x86_64-win.asm", - "gen/bcm/ghash-x86-win.asm", - "gen/bcm/ghash-x86_64-win.asm", - "gen/bcm/md5-586-win.asm", - "gen/bcm/md5-x86_64-win.asm", - "gen/bcm/p256-x86_64-asm-win.asm", - "gen/bcm/p256_beeu-x86_64-asm-win.asm", - "gen/bcm/rdrand-x86_64-win.asm", - "gen/bcm/rsaz-avx2-win.asm", - "gen/bcm/sha1-586-win.asm", - "gen/bcm/sha1-x86_64-win.asm", - "gen/bcm/sha256-586-win.asm", - "gen/bcm/sha256-x86_64-win.asm", - "gen/bcm/sha512-586-win.asm", - "gen/bcm/sha512-x86_64-win.asm", - "gen/bcm/vpaes-x86-win.asm", - "gen/bcm/vpaes-x86_64-win.asm", - "gen/bcm/x86-mont-win.asm", - "gen/bcm/x86_64-mont-win.asm", - "gen/bcm/x86_64-mont5-win.asm", + "gen/bcm/aesni-gcm-x86_64-win.asm", + "gen/bcm/aesni-x86-win.asm", + "gen/bcm/aesni-x86_64-win.asm", + "gen/bcm/bn-586-win.asm", + "gen/bcm/co-586-win.asm", + "gen/bcm/ghash-ssse3-x86-win.asm", + "gen/bcm/ghash-ssse3-x86_64-win.asm", + "gen/bcm/ghash-x86-win.asm", + "gen/bcm/ghash-x86_64-win.asm", + "gen/bcm/md5-586-win.asm", + "gen/bcm/md5-x86_64-win.asm", + "gen/bcm/p256-x86_64-asm-win.asm", + "gen/bcm/p256_beeu-x86_64-asm-win.asm", + "gen/bcm/rdrand-x86_64-win.asm", + "gen/bcm/rsaz-avx2-win.asm", + "gen/bcm/sha1-586-win.asm", + "gen/bcm/sha1-x86_64-win.asm", + "gen/bcm/sha256-586-win.asm", + "gen/bcm/sha256-x86_64-win.asm", + "gen/bcm/sha512-586-win.asm", + "gen/bcm/sha512-x86_64-win.asm", + "gen/bcm/vpaes-x86-win.asm", + "gen/bcm/vpaes-x86_64-win.asm", + "gen/bcm/x86-mont-win.asm", + "gen/bcm/x86_64-mont-win.asm", + "gen/bcm/x86_64-mont5-win.asm", ] bssl_sources = [ - "tool/args.cc", - "tool/ciphers.cc", - "tool/client.cc", - "tool/const.cc", - "tool/digest.cc", - "tool/fd.cc", - "tool/file.cc", - "tool/generate_ech.cc", - "tool/generate_ed25519.cc", - "tool/genrsa.cc", - "tool/pkcs12.cc", - "tool/rand.cc", - "tool/server.cc", - "tool/sign.cc", - "tool/speed.cc", - "tool/tool.cc", - "tool/transport_common.cc", + "tool/args.cc", + "tool/ciphers.cc", + "tool/client.cc", + "tool/const.cc", + "tool/digest.cc", + "tool/fd.cc", + "tool/file.cc", + "tool/generate_ech.cc", + "tool/generate_ed25519.cc", + "tool/genrsa.cc", + "tool/pkcs12.cc", + "tool/rand.cc", + "tool/server.cc", + "tool/sign.cc", + "tool/speed.cc", + "tool/tool.cc", + "tool/transport_common.cc", ] bssl_internal_headers = [ - "tool/internal.h", - "tool/transport_common.h", + "tool/internal.h", + "tool/transport_common.h", ] crypto_sources = [ - "crypto/asn1/a_bitstr.c", - "crypto/asn1/a_bool.c", - "crypto/asn1/a_d2i_fp.c", - "crypto/asn1/a_dup.c", - "crypto/asn1/a_gentm.c", - "crypto/asn1/a_i2d_fp.c", - "crypto/asn1/a_int.c", - "crypto/asn1/a_mbstr.c", - "crypto/asn1/a_object.c", - "crypto/asn1/a_octet.c", - "crypto/asn1/a_strex.c", - "crypto/asn1/a_strnid.c", - "crypto/asn1/a_time.c", - "crypto/asn1/a_type.c", - "crypto/asn1/a_utctm.c", - "crypto/asn1/asn1_lib.c", - "crypto/asn1/asn1_par.c", - "crypto/asn1/asn_pack.c", - "crypto/asn1/f_int.c", - "crypto/asn1/f_string.c", - "crypto/asn1/posix_time.c", - "crypto/asn1/tasn_dec.c", - "crypto/asn1/tasn_enc.c", - "crypto/asn1/tasn_fre.c", - "crypto/asn1/tasn_new.c", - "crypto/asn1/tasn_typ.c", - "crypto/asn1/tasn_utl.c", - "crypto/base64/base64.c", - "crypto/bio/bio.c", - "crypto/bio/bio_mem.c", - "crypto/bio/connect.c", - "crypto/bio/errno.c", - "crypto/bio/fd.c", - "crypto/bio/file.c", - "crypto/bio/hexdump.c", - "crypto/bio/pair.c", - "crypto/bio/printf.c", - "crypto/bio/socket.c", - "crypto/bio/socket_helper.c", - "crypto/blake2/blake2.c", - "crypto/bn_extra/bn_asn1.c", - "crypto/bn_extra/convert.c", - "crypto/buf/buf.c", - "crypto/bytestring/asn1_compat.c", - "crypto/bytestring/ber.c", - "crypto/bytestring/cbb.c", - "crypto/bytestring/cbs.c", - "crypto/bytestring/unicode.c", - "crypto/chacha/chacha.c", - "crypto/cipher_extra/cipher_extra.c", - "crypto/cipher_extra/derive_key.c", - "crypto/cipher_extra/e_aesctrhmac.c", - "crypto/cipher_extra/e_aesgcmsiv.c", - "crypto/cipher_extra/e_chacha20poly1305.c", - "crypto/cipher_extra/e_des.c", - "crypto/cipher_extra/e_null.c", - "crypto/cipher_extra/e_rc2.c", - "crypto/cipher_extra/e_rc4.c", - "crypto/cipher_extra/e_tls.c", - "crypto/cipher_extra/tls_cbc.c", - "crypto/conf/conf.c", - "crypto/cpu_aarch64_apple.c", - "crypto/cpu_aarch64_fuchsia.c", - "crypto/cpu_aarch64_linux.c", - "crypto/cpu_aarch64_openbsd.c", - "crypto/cpu_aarch64_sysreg.c", - "crypto/cpu_aarch64_win.c", - "crypto/cpu_arm_freebsd.c", - "crypto/cpu_arm_linux.c", - "crypto/cpu_intel.c", - "crypto/crypto.c", - "crypto/curve25519/curve25519.c", - "crypto/curve25519/curve25519_64_adx.c", - "crypto/curve25519/spake25519.c", - "crypto/des/des.c", - "crypto/dh_extra/dh_asn1.c", - "crypto/dh_extra/params.c", - "crypto/digest_extra/digest_extra.c", - "crypto/dsa/dsa.c", - "crypto/dsa/dsa_asn1.c", - "crypto/ec_extra/ec_asn1.c", - "crypto/ec_extra/ec_derive.c", - "crypto/ec_extra/hash_to_curve.c", - "crypto/ecdh_extra/ecdh_extra.c", - "crypto/ecdsa_extra/ecdsa_asn1.c", - "crypto/engine/engine.c", - "crypto/err/err.c", - "crypto/evp/evp.c", - "crypto/evp/evp_asn1.c", - "crypto/evp/evp_ctx.c", - "crypto/evp/p_dh.c", - "crypto/evp/p_dh_asn1.c", - "crypto/evp/p_dsa_asn1.c", - "crypto/evp/p_ec.c", - "crypto/evp/p_ec_asn1.c", - "crypto/evp/p_ed25519.c", - "crypto/evp/p_ed25519_asn1.c", - "crypto/evp/p_hkdf.c", - "crypto/evp/p_rsa.c", - "crypto/evp/p_rsa_asn1.c", - "crypto/evp/p_x25519.c", - "crypto/evp/p_x25519_asn1.c", - "crypto/evp/pbkdf.c", - "crypto/evp/print.c", - "crypto/evp/scrypt.c", - "crypto/evp/sign.c", - "crypto/ex_data.c", - "crypto/fipsmodule/fips_shared_support.c", - "crypto/hpke/hpke.c", - "crypto/hrss/hrss.c", - "crypto/keccak/keccak.c", - "crypto/kyber/kyber.c", - "crypto/lhash/lhash.c", - "crypto/mem.c", - "crypto/obj/obj.c", - "crypto/obj/obj_xref.c", - "crypto/pem/pem_all.c", - "crypto/pem/pem_info.c", - "crypto/pem/pem_lib.c", - "crypto/pem/pem_oth.c", - "crypto/pem/pem_pk8.c", - "crypto/pem/pem_pkey.c", - "crypto/pem/pem_x509.c", - "crypto/pem/pem_xaux.c", - "crypto/pkcs7/pkcs7.c", - "crypto/pkcs7/pkcs7_x509.c", - "crypto/pkcs8/p5_pbev2.c", - "crypto/pkcs8/pkcs8.c", - "crypto/pkcs8/pkcs8_x509.c", - "crypto/poly1305/poly1305.c", - "crypto/poly1305/poly1305_arm.c", - "crypto/poly1305/poly1305_vec.c", - "crypto/pool/pool.c", - "crypto/rand_extra/deterministic.c", - "crypto/rand_extra/forkunsafe.c", - "crypto/rand_extra/getentropy.c", - "crypto/rand_extra/ios.c", - "crypto/rand_extra/passive.c", - "crypto/rand_extra/rand_extra.c", - "crypto/rand_extra/trusty.c", - "crypto/rand_extra/windows.c", - "crypto/rc4/rc4.c", - "crypto/refcount.c", - "crypto/rsa_extra/rsa_asn1.c", - "crypto/rsa_extra/rsa_crypt.c", - "crypto/rsa_extra/rsa_print.c", - "crypto/siphash/siphash.c", - "crypto/spx/address.c", - "crypto/spx/fors.c", - "crypto/spx/merkle.c", - "crypto/spx/spx.c", - "crypto/spx/spx_util.c", - "crypto/spx/thash.c", - "crypto/spx/wots.c", - "crypto/stack/stack.c", - "crypto/thread.c", - "crypto/thread_none.c", - "crypto/thread_pthread.c", - "crypto/thread_win.c", - "crypto/trust_token/pmbtoken.c", - "crypto/trust_token/trust_token.c", - "crypto/trust_token/voprf.c", - "crypto/x509/a_digest.c", - "crypto/x509/a_sign.c", - "crypto/x509/a_verify.c", - "crypto/x509/algorithm.c", - "crypto/x509/asn1_gen.c", - "crypto/x509/by_dir.c", - "crypto/x509/by_file.c", - "crypto/x509/i2d_pr.c", - "crypto/x509/name_print.c", - "crypto/x509/policy.c", - "crypto/x509/rsa_pss.c", - "crypto/x509/t_crl.c", - "crypto/x509/t_req.c", - "crypto/x509/t_x509.c", - "crypto/x509/t_x509a.c", - "crypto/x509/v3_akey.c", - "crypto/x509/v3_akeya.c", - "crypto/x509/v3_alt.c", - "crypto/x509/v3_bcons.c", - "crypto/x509/v3_bitst.c", - "crypto/x509/v3_conf.c", - "crypto/x509/v3_cpols.c", - "crypto/x509/v3_crld.c", - "crypto/x509/v3_enum.c", - "crypto/x509/v3_extku.c", - "crypto/x509/v3_genn.c", - "crypto/x509/v3_ia5.c", - "crypto/x509/v3_info.c", - "crypto/x509/v3_int.c", - "crypto/x509/v3_lib.c", - "crypto/x509/v3_ncons.c", - "crypto/x509/v3_ocsp.c", - "crypto/x509/v3_pcons.c", - "crypto/x509/v3_pmaps.c", - "crypto/x509/v3_prn.c", - "crypto/x509/v3_purp.c", - "crypto/x509/v3_skey.c", - "crypto/x509/v3_utl.c", - "crypto/x509/x509.c", - "crypto/x509/x509_att.c", - "crypto/x509/x509_cmp.c", - "crypto/x509/x509_d2.c", - "crypto/x509/x509_def.c", - "crypto/x509/x509_ext.c", - "crypto/x509/x509_lu.c", - "crypto/x509/x509_obj.c", - "crypto/x509/x509_req.c", - "crypto/x509/x509_set.c", - "crypto/x509/x509_trs.c", - "crypto/x509/x509_txt.c", - "crypto/x509/x509_v3.c", - "crypto/x509/x509_vfy.c", - "crypto/x509/x509_vpm.c", - "crypto/x509/x509cset.c", - "crypto/x509/x509name.c", - "crypto/x509/x509rset.c", - "crypto/x509/x509spki.c", - "crypto/x509/x_algor.c", - "crypto/x509/x_all.c", - "crypto/x509/x_attrib.c", - "crypto/x509/x_crl.c", - "crypto/x509/x_exten.c", - "crypto/x509/x_name.c", - "crypto/x509/x_pubkey.c", - "crypto/x509/x_req.c", - "crypto/x509/x_sig.c", - "crypto/x509/x_spki.c", - "crypto/x509/x_val.c", - "crypto/x509/x_x509.c", - "crypto/x509/x_x509a.c", - "gen/crypto/err_data.c", + "crypto/asn1/a_bitstr.c", + "crypto/asn1/a_bool.c", + "crypto/asn1/a_d2i_fp.c", + "crypto/asn1/a_dup.c", + "crypto/asn1/a_gentm.c", + "crypto/asn1/a_i2d_fp.c", + "crypto/asn1/a_int.c", + "crypto/asn1/a_mbstr.c", + "crypto/asn1/a_object.c", + "crypto/asn1/a_octet.c", + "crypto/asn1/a_strex.c", + "crypto/asn1/a_strnid.c", + "crypto/asn1/a_time.c", + "crypto/asn1/a_type.c", + "crypto/asn1/a_utctm.c", + "crypto/asn1/asn1_lib.c", + "crypto/asn1/asn1_par.c", + "crypto/asn1/asn_pack.c", + "crypto/asn1/f_int.c", + "crypto/asn1/f_string.c", + "crypto/asn1/posix_time.c", + "crypto/asn1/tasn_dec.c", + "crypto/asn1/tasn_enc.c", + "crypto/asn1/tasn_fre.c", + "crypto/asn1/tasn_new.c", + "crypto/asn1/tasn_typ.c", + "crypto/asn1/tasn_utl.c", + "crypto/base64/base64.c", + "crypto/bio/bio.c", + "crypto/bio/bio_mem.c", + "crypto/bio/connect.c", + "crypto/bio/errno.c", + "crypto/bio/fd.c", + "crypto/bio/file.c", + "crypto/bio/hexdump.c", + "crypto/bio/pair.c", + "crypto/bio/printf.c", + "crypto/bio/socket.c", + "crypto/bio/socket_helper.c", + "crypto/blake2/blake2.c", + "crypto/bn_extra/bn_asn1.c", + "crypto/bn_extra/convert.c", + "crypto/buf/buf.c", + "crypto/bytestring/asn1_compat.c", + "crypto/bytestring/ber.c", + "crypto/bytestring/cbb.c", + "crypto/bytestring/cbs.c", + "crypto/bytestring/unicode.c", + "crypto/chacha/chacha.c", + "crypto/cipher_extra/cipher_extra.c", + "crypto/cipher_extra/derive_key.c", + "crypto/cipher_extra/e_aesctrhmac.c", + "crypto/cipher_extra/e_aesgcmsiv.c", + "crypto/cipher_extra/e_chacha20poly1305.c", + "crypto/cipher_extra/e_des.c", + "crypto/cipher_extra/e_null.c", + "crypto/cipher_extra/e_rc2.c", + "crypto/cipher_extra/e_rc4.c", + "crypto/cipher_extra/e_tls.c", + "crypto/cipher_extra/tls_cbc.c", + "crypto/conf/conf.c", + "crypto/cpu_aarch64_apple.c", + "crypto/cpu_aarch64_fuchsia.c", + "crypto/cpu_aarch64_linux.c", + "crypto/cpu_aarch64_openbsd.c", + "crypto/cpu_aarch64_sysreg.c", + "crypto/cpu_aarch64_win.c", + "crypto/cpu_arm_freebsd.c", + "crypto/cpu_arm_linux.c", + "crypto/cpu_intel.c", + "crypto/crypto.c", + "crypto/curve25519/curve25519.c", + "crypto/curve25519/curve25519_64_adx.c", + "crypto/curve25519/spake25519.c", + "crypto/des/des.c", + "crypto/dh_extra/dh_asn1.c", + "crypto/dh_extra/params.c", + "crypto/digest_extra/digest_extra.c", + "crypto/dilithium/dilithium.c", + "crypto/dsa/dsa.c", + "crypto/dsa/dsa_asn1.c", + "crypto/ec_extra/ec_asn1.c", + "crypto/ec_extra/ec_derive.c", + "crypto/ec_extra/hash_to_curve.c", + "crypto/ecdh_extra/ecdh_extra.c", + "crypto/ecdsa_extra/ecdsa_asn1.c", + "crypto/engine/engine.c", + "crypto/err/err.c", + "crypto/evp/evp.c", + "crypto/evp/evp_asn1.c", + "crypto/evp/evp_ctx.c", + "crypto/evp/p_dh.c", + "crypto/evp/p_dh_asn1.c", + "crypto/evp/p_dsa_asn1.c", + "crypto/evp/p_ec.c", + "crypto/evp/p_ec_asn1.c", + "crypto/evp/p_ed25519.c", + "crypto/evp/p_ed25519_asn1.c", + "crypto/evp/p_hkdf.c", + "crypto/evp/p_rsa.c", + "crypto/evp/p_rsa_asn1.c", + "crypto/evp/p_x25519.c", + "crypto/evp/p_x25519_asn1.c", + "crypto/evp/pbkdf.c", + "crypto/evp/print.c", + "crypto/evp/scrypt.c", + "crypto/evp/sign.c", + "crypto/ex_data.c", + "crypto/fipsmodule/fips_shared_support.c", + "crypto/hpke/hpke.c", + "crypto/hrss/hrss.c", + "crypto/keccak/keccak.c", + "crypto/kyber/kyber.c", + "crypto/lhash/lhash.c", + "crypto/mem.c", + "crypto/obj/obj.c", + "crypto/obj/obj_xref.c", + "crypto/pem/pem_all.c", + "crypto/pem/pem_info.c", + "crypto/pem/pem_lib.c", + "crypto/pem/pem_oth.c", + "crypto/pem/pem_pk8.c", + "crypto/pem/pem_pkey.c", + "crypto/pem/pem_x509.c", + "crypto/pem/pem_xaux.c", + "crypto/pkcs7/pkcs7.c", + "crypto/pkcs7/pkcs7_x509.c", + "crypto/pkcs8/p5_pbev2.c", + "crypto/pkcs8/pkcs8.c", + "crypto/pkcs8/pkcs8_x509.c", + "crypto/poly1305/poly1305.c", + "crypto/poly1305/poly1305_arm.c", + "crypto/poly1305/poly1305_vec.c", + "crypto/pool/pool.c", + "crypto/rand_extra/deterministic.c", + "crypto/rand_extra/forkunsafe.c", + "crypto/rand_extra/getentropy.c", + "crypto/rand_extra/ios.c", + "crypto/rand_extra/passive.c", + "crypto/rand_extra/rand_extra.c", + "crypto/rand_extra/trusty.c", + "crypto/rand_extra/windows.c", + "crypto/rc4/rc4.c", + "crypto/refcount.c", + "crypto/rsa_extra/rsa_asn1.c", + "crypto/rsa_extra/rsa_crypt.c", + "crypto/rsa_extra/rsa_print.c", + "crypto/siphash/siphash.c", + "crypto/spx/address.c", + "crypto/spx/fors.c", + "crypto/spx/merkle.c", + "crypto/spx/spx.c", + "crypto/spx/spx_util.c", + "crypto/spx/thash.c", + "crypto/spx/wots.c", + "crypto/stack/stack.c", + "crypto/thread.c", + "crypto/thread_none.c", + "crypto/thread_pthread.c", + "crypto/thread_win.c", + "crypto/trust_token/pmbtoken.c", + "crypto/trust_token/trust_token.c", + "crypto/trust_token/voprf.c", + "crypto/x509/a_digest.c", + "crypto/x509/a_sign.c", + "crypto/x509/a_verify.c", + "crypto/x509/algorithm.c", + "crypto/x509/asn1_gen.c", + "crypto/x509/by_dir.c", + "crypto/x509/by_file.c", + "crypto/x509/i2d_pr.c", + "crypto/x509/name_print.c", + "crypto/x509/policy.c", + "crypto/x509/rsa_pss.c", + "crypto/x509/t_crl.c", + "crypto/x509/t_req.c", + "crypto/x509/t_x509.c", + "crypto/x509/t_x509a.c", + "crypto/x509/v3_akey.c", + "crypto/x509/v3_akeya.c", + "crypto/x509/v3_alt.c", + "crypto/x509/v3_bcons.c", + "crypto/x509/v3_bitst.c", + "crypto/x509/v3_conf.c", + "crypto/x509/v3_cpols.c", + "crypto/x509/v3_crld.c", + "crypto/x509/v3_enum.c", + "crypto/x509/v3_extku.c", + "crypto/x509/v3_genn.c", + "crypto/x509/v3_ia5.c", + "crypto/x509/v3_info.c", + "crypto/x509/v3_int.c", + "crypto/x509/v3_lib.c", + "crypto/x509/v3_ncons.c", + "crypto/x509/v3_ocsp.c", + "crypto/x509/v3_pcons.c", + "crypto/x509/v3_pmaps.c", + "crypto/x509/v3_prn.c", + "crypto/x509/v3_purp.c", + "crypto/x509/v3_skey.c", + "crypto/x509/v3_utl.c", + "crypto/x509/x509.c", + "crypto/x509/x509_att.c", + "crypto/x509/x509_cmp.c", + "crypto/x509/x509_d2.c", + "crypto/x509/x509_def.c", + "crypto/x509/x509_ext.c", + "crypto/x509/x509_lu.c", + "crypto/x509/x509_obj.c", + "crypto/x509/x509_req.c", + "crypto/x509/x509_set.c", + "crypto/x509/x509_trs.c", + "crypto/x509/x509_txt.c", + "crypto/x509/x509_v3.c", + "crypto/x509/x509_vfy.c", + "crypto/x509/x509_vpm.c", + "crypto/x509/x509cset.c", + "crypto/x509/x509name.c", + "crypto/x509/x509rset.c", + "crypto/x509/x509spki.c", + "crypto/x509/x_algor.c", + "crypto/x509/x_all.c", + "crypto/x509/x_attrib.c", + "crypto/x509/x_crl.c", + "crypto/x509/x_exten.c", + "crypto/x509/x_name.c", + "crypto/x509/x_pubkey.c", + "crypto/x509/x_req.c", + "crypto/x509/x_sig.c", + "crypto/x509/x_spki.c", + "crypto/x509/x_val.c", + "crypto/x509/x_x509.c", + "crypto/x509/x_x509a.c", + "gen/crypto/err_data.c", ] crypto_headers = [ - "include/openssl/aead.h", - "include/openssl/aes.h", - "include/openssl/arm_arch.h", - "include/openssl/asm_base.h", - "include/openssl/asn1.h", - "include/openssl/asn1_mac.h", - "include/openssl/asn1t.h", - "include/openssl/base.h", - "include/openssl/base64.h", - "include/openssl/bio.h", - "include/openssl/blake2.h", - "include/openssl/blowfish.h", - "include/openssl/bn.h", - "include/openssl/buf.h", - "include/openssl/buffer.h", - "include/openssl/bytestring.h", - "include/openssl/cast.h", - "include/openssl/chacha.h", - "include/openssl/cipher.h", - "include/openssl/cmac.h", - "include/openssl/conf.h", - "include/openssl/cpu.h", - "include/openssl/crypto.h", - "include/openssl/ctrdrbg.h", - "include/openssl/curve25519.h", - "include/openssl/des.h", - "include/openssl/dh.h", - "include/openssl/digest.h", - "include/openssl/dsa.h", - "include/openssl/e_os2.h", - "include/openssl/ec.h", - "include/openssl/ec_key.h", - "include/openssl/ecdh.h", - "include/openssl/ecdsa.h", - "include/openssl/engine.h", - "include/openssl/err.h", - "include/openssl/evp.h", - "include/openssl/evp_errors.h", - "include/openssl/ex_data.h", - "include/openssl/experimental/kyber.h", - "include/openssl/experimental/spx.h", - "include/openssl/hkdf.h", - "include/openssl/hmac.h", - "include/openssl/hpke.h", - "include/openssl/hrss.h", - "include/openssl/is_boringssl.h", - "include/openssl/kdf.h", - "include/openssl/lhash.h", - "include/openssl/md4.h", - "include/openssl/md5.h", - "include/openssl/mem.h", - "include/openssl/nid.h", - "include/openssl/obj.h", - "include/openssl/obj_mac.h", - "include/openssl/objects.h", - "include/openssl/opensslconf.h", - "include/openssl/opensslv.h", - "include/openssl/ossl_typ.h", - "include/openssl/pem.h", - "include/openssl/pkcs12.h", - "include/openssl/pkcs7.h", - "include/openssl/pkcs8.h", - "include/openssl/poly1305.h", - "include/openssl/pool.h", - "include/openssl/posix_time.h", - "include/openssl/rand.h", - "include/openssl/rc4.h", - "include/openssl/ripemd.h", - "include/openssl/rsa.h", - "include/openssl/safestack.h", - "include/openssl/service_indicator.h", - "include/openssl/sha.h", - "include/openssl/siphash.h", - "include/openssl/span.h", - "include/openssl/stack.h", - "include/openssl/target.h", - "include/openssl/thread.h", - "include/openssl/time.h", - "include/openssl/trust_token.h", - "include/openssl/type_check.h", - "include/openssl/x509.h", - "include/openssl/x509_vfy.h", - "include/openssl/x509v3.h", - "include/openssl/x509v3_errors.h", + "include/openssl/aead.h", + "include/openssl/aes.h", + "include/openssl/arm_arch.h", + "include/openssl/asm_base.h", + "include/openssl/asn1.h", + "include/openssl/asn1_mac.h", + "include/openssl/asn1t.h", + "include/openssl/base.h", + "include/openssl/base64.h", + "include/openssl/bio.h", + "include/openssl/blake2.h", + "include/openssl/blowfish.h", + "include/openssl/bn.h", + "include/openssl/buf.h", + "include/openssl/buffer.h", + "include/openssl/bytestring.h", + "include/openssl/cast.h", + "include/openssl/chacha.h", + "include/openssl/cipher.h", + "include/openssl/cmac.h", + "include/openssl/conf.h", + "include/openssl/cpu.h", + "include/openssl/crypto.h", + "include/openssl/ctrdrbg.h", + "include/openssl/curve25519.h", + "include/openssl/des.h", + "include/openssl/dh.h", + "include/openssl/digest.h", + "include/openssl/dsa.h", + "include/openssl/e_os2.h", + "include/openssl/ec.h", + "include/openssl/ec_key.h", + "include/openssl/ecdh.h", + "include/openssl/ecdsa.h", + "include/openssl/engine.h", + "include/openssl/err.h", + "include/openssl/evp.h", + "include/openssl/evp_errors.h", + "include/openssl/ex_data.h", + "include/openssl/experimental/dilithium.h", + "include/openssl/experimental/kyber.h", + "include/openssl/experimental/spx.h", + "include/openssl/hkdf.h", + "include/openssl/hmac.h", + "include/openssl/hpke.h", + "include/openssl/hrss.h", + "include/openssl/is_boringssl.h", + "include/openssl/kdf.h", + "include/openssl/lhash.h", + "include/openssl/md4.h", + "include/openssl/md5.h", + "include/openssl/mem.h", + "include/openssl/nid.h", + "include/openssl/obj.h", + "include/openssl/obj_mac.h", + "include/openssl/objects.h", + "include/openssl/opensslconf.h", + "include/openssl/opensslv.h", + "include/openssl/ossl_typ.h", + "include/openssl/pem.h", + "include/openssl/pkcs12.h", + "include/openssl/pkcs7.h", + "include/openssl/pkcs8.h", + "include/openssl/poly1305.h", + "include/openssl/pool.h", + "include/openssl/posix_time.h", + "include/openssl/rand.h", + "include/openssl/rc4.h", + "include/openssl/ripemd.h", + "include/openssl/rsa.h", + "include/openssl/safestack.h", + "include/openssl/service_indicator.h", + "include/openssl/sha.h", + "include/openssl/siphash.h", + "include/openssl/span.h", + "include/openssl/stack.h", + "include/openssl/target.h", + "include/openssl/thread.h", + "include/openssl/time.h", + "include/openssl/trust_token.h", + "include/openssl/type_check.h", + "include/openssl/x509.h", + "include/openssl/x509_vfy.h", + "include/openssl/x509v3.h", + "include/openssl/x509v3_errors.h", ] crypto_internal_headers = [ - "crypto/asn1/internal.h", - "crypto/bio/internal.h", - "crypto/bytestring/internal.h", - "crypto/chacha/internal.h", - "crypto/cipher_extra/internal.h", - "crypto/conf/conf_def.h", - "crypto/conf/internal.h", - "crypto/cpu_arm_linux.h", - "crypto/curve25519/curve25519_tables.h", - "crypto/curve25519/internal.h", - "crypto/des/internal.h", - "crypto/dsa/internal.h", - "crypto/ec_extra/internal.h", - "crypto/err/internal.h", - "crypto/evp/internal.h", - "crypto/fipsmodule/aes/internal.h", - "crypto/fipsmodule/bn/internal.h", - "crypto/fipsmodule/bn/rsaz_exp.h", - "crypto/fipsmodule/cipher/internal.h", - "crypto/fipsmodule/delocate.h", - "crypto/fipsmodule/dh/internal.h", - "crypto/fipsmodule/digest/internal.h", - "crypto/fipsmodule/digest/md32_common.h", - "crypto/fipsmodule/ec/builtin_curves.h", - "crypto/fipsmodule/ec/internal.h", - "crypto/fipsmodule/ec/p256-nistz-table.h", - "crypto/fipsmodule/ec/p256-nistz.h", - "crypto/fipsmodule/ec/p256_table.h", - "crypto/fipsmodule/ecdsa/internal.h", - "crypto/fipsmodule/md5/internal.h", - "crypto/fipsmodule/modes/internal.h", - "crypto/fipsmodule/rand/fork_detect.h", - "crypto/fipsmodule/rand/getrandom_fillin.h", - "crypto/fipsmodule/rand/internal.h", - "crypto/fipsmodule/rsa/internal.h", - "crypto/fipsmodule/service_indicator/internal.h", - "crypto/fipsmodule/sha/internal.h", - "crypto/fipsmodule/tls/internal.h", - "crypto/hrss/internal.h", - "crypto/internal.h", - "crypto/keccak/internal.h", - "crypto/kyber/internal.h", - "crypto/lhash/internal.h", - "crypto/obj/obj_dat.h", - "crypto/pkcs7/internal.h", - "crypto/pkcs8/internal.h", - "crypto/poly1305/internal.h", - "crypto/pool/internal.h", - "crypto/rsa_extra/internal.h", - "crypto/spx/address.h", - "crypto/spx/fors.h", - "crypto/spx/merkle.h", - "crypto/spx/params.h", - "crypto/spx/spx_util.h", - "crypto/spx/thash.h", - "crypto/spx/wots.h", - "crypto/trust_token/internal.h", - "crypto/x509/ext_dat.h", - "crypto/x509/internal.h", - "third_party/fiat/curve25519_32.h", - "third_party/fiat/curve25519_64.h", - "third_party/fiat/curve25519_64_adx.h", - "third_party/fiat/curve25519_64_msvc.h", - "third_party/fiat/p256_32.h", - "third_party/fiat/p256_64.h", - "third_party/fiat/p256_64_msvc.h", + "crypto/asn1/internal.h", + "crypto/bio/internal.h", + "crypto/bytestring/internal.h", + "crypto/chacha/internal.h", + "crypto/cipher_extra/internal.h", + "crypto/conf/internal.h", + "crypto/cpu_arm_linux.h", + "crypto/curve25519/curve25519_tables.h", + "crypto/curve25519/internal.h", + "crypto/des/internal.h", + "crypto/dilithium/internal.h", + "crypto/dsa/internal.h", + "crypto/ec_extra/internal.h", + "crypto/err/internal.h", + "crypto/evp/internal.h", + "crypto/fipsmodule/aes/internal.h", + "crypto/fipsmodule/bn/internal.h", + "crypto/fipsmodule/bn/rsaz_exp.h", + "crypto/fipsmodule/cipher/internal.h", + "crypto/fipsmodule/delocate.h", + "crypto/fipsmodule/dh/internal.h", + "crypto/fipsmodule/digest/internal.h", + "crypto/fipsmodule/digest/md32_common.h", + "crypto/fipsmodule/ec/builtin_curves.h", + "crypto/fipsmodule/ec/internal.h", + "crypto/fipsmodule/ec/p256-nistz-table.h", + "crypto/fipsmodule/ec/p256-nistz.h", + "crypto/fipsmodule/ec/p256_table.h", + "crypto/fipsmodule/ecdsa/internal.h", + "crypto/fipsmodule/md5/internal.h", + "crypto/fipsmodule/modes/internal.h", + "crypto/fipsmodule/rand/fork_detect.h", + "crypto/fipsmodule/rand/getrandom_fillin.h", + "crypto/fipsmodule/rand/internal.h", + "crypto/fipsmodule/rsa/internal.h", + "crypto/fipsmodule/service_indicator/internal.h", + "crypto/fipsmodule/sha/internal.h", + "crypto/fipsmodule/tls/internal.h", + "crypto/hrss/internal.h", + "crypto/internal.h", + "crypto/keccak/internal.h", + "crypto/kyber/internal.h", + "crypto/lhash/internal.h", + "crypto/obj/obj_dat.h", + "crypto/pkcs7/internal.h", + "crypto/pkcs8/internal.h", + "crypto/poly1305/internal.h", + "crypto/pool/internal.h", + "crypto/rsa_extra/internal.h", + "crypto/spx/address.h", + "crypto/spx/fors.h", + "crypto/spx/merkle.h", + "crypto/spx/params.h", + "crypto/spx/spx_util.h", + "crypto/spx/thash.h", + "crypto/spx/wots.h", + "crypto/trust_token/internal.h", + "crypto/x509/ext_dat.h", + "crypto/x509/internal.h", + "third_party/fiat/curve25519_32.h", + "third_party/fiat/curve25519_64.h", + "third_party/fiat/curve25519_64_adx.h", + "third_party/fiat/curve25519_64_msvc.h", + "third_party/fiat/p256_32.h", + "third_party/fiat/p256_64.h", + "third_party/fiat/p256_64_msvc.h", ] crypto_sources_asm = [ - "crypto/curve25519/asm/x25519-asm-arm.S", - "crypto/hrss/asm/poly_rq_mul.S", - "crypto/poly1305/poly1305_arm_asm.S", - "gen/crypto/aes128gcmsiv-x86_64-apple.S", - "gen/crypto/aes128gcmsiv-x86_64-linux.S", - "gen/crypto/chacha-armv4-linux.S", - "gen/crypto/chacha-armv8-apple.S", - "gen/crypto/chacha-armv8-linux.S", - "gen/crypto/chacha-armv8-win.S", - "gen/crypto/chacha-x86-apple.S", - "gen/crypto/chacha-x86-linux.S", - "gen/crypto/chacha-x86_64-apple.S", - "gen/crypto/chacha-x86_64-linux.S", - "gen/crypto/chacha20_poly1305_armv8-apple.S", - "gen/crypto/chacha20_poly1305_armv8-linux.S", - "gen/crypto/chacha20_poly1305_armv8-win.S", - "gen/crypto/chacha20_poly1305_x86_64-apple.S", - "gen/crypto/chacha20_poly1305_x86_64-linux.S", - "third_party/fiat/asm/fiat_curve25519_adx_mul.S", - "third_party/fiat/asm/fiat_curve25519_adx_square.S", - "third_party/fiat/asm/fiat_p256_adx_mul.S", - "third_party/fiat/asm/fiat_p256_adx_sqr.S", + "crypto/curve25519/asm/x25519-asm-arm.S", + "crypto/hrss/asm/poly_rq_mul.S", + "crypto/poly1305/poly1305_arm_asm.S", + "gen/crypto/aes128gcmsiv-x86_64-apple.S", + "gen/crypto/aes128gcmsiv-x86_64-linux.S", + "gen/crypto/chacha-armv4-linux.S", + "gen/crypto/chacha-armv8-apple.S", + "gen/crypto/chacha-armv8-linux.S", + "gen/crypto/chacha-armv8-win.S", + "gen/crypto/chacha-x86-apple.S", + "gen/crypto/chacha-x86-linux.S", + "gen/crypto/chacha-x86_64-apple.S", + "gen/crypto/chacha-x86_64-linux.S", + "gen/crypto/chacha20_poly1305_armv8-apple.S", + "gen/crypto/chacha20_poly1305_armv8-linux.S", + "gen/crypto/chacha20_poly1305_armv8-win.S", + "gen/crypto/chacha20_poly1305_x86_64-apple.S", + "gen/crypto/chacha20_poly1305_x86_64-linux.S", + "third_party/fiat/asm/fiat_curve25519_adx_mul.S", + "third_party/fiat/asm/fiat_curve25519_adx_square.S", ] crypto_sources_nasm = [ - "gen/crypto/aes128gcmsiv-x86_64-win.asm", - "gen/crypto/chacha-x86-win.asm", - "gen/crypto/chacha-x86_64-win.asm", - "gen/crypto/chacha20_poly1305_x86_64-win.asm", + "gen/crypto/aes128gcmsiv-x86_64-win.asm", + "gen/crypto/chacha-x86-win.asm", + "gen/crypto/chacha-x86_64-win.asm", + "gen/crypto/chacha20_poly1305_x86_64-win.asm", ] crypto_test_sources = [ - "crypto/abi_self_test.cc", - "crypto/asn1/asn1_test.cc", - "crypto/base64/base64_test.cc", - "crypto/bio/bio_test.cc", - "crypto/blake2/blake2_test.cc", - "crypto/buf/buf_test.cc", - "crypto/bytestring/bytestring_test.cc", - "crypto/chacha/chacha_test.cc", - "crypto/cipher_extra/aead_test.cc", - "crypto/cipher_extra/cipher_test.cc", - "crypto/compiler_test.cc", - "crypto/conf/conf_test.cc", - "crypto/constant_time_test.cc", - "crypto/cpu_arm_linux_test.cc", - "crypto/crypto_test.cc", - "crypto/curve25519/ed25519_test.cc", - "crypto/curve25519/spake25519_test.cc", - "crypto/curve25519/x25519_test.cc", - "crypto/dh_extra/dh_test.cc", - "crypto/digest_extra/digest_test.cc", - "crypto/dsa/dsa_test.cc", - "crypto/ecdh_extra/ecdh_test.cc", - "crypto/err/err_test.cc", - "crypto/evp/evp_extra_test.cc", - "crypto/evp/evp_test.cc", - "crypto/evp/pbkdf_test.cc", - "crypto/evp/scrypt_test.cc", - "crypto/fipsmodule/aes/aes_test.cc", - "crypto/fipsmodule/bn/bn_test.cc", - "crypto/fipsmodule/cmac/cmac_test.cc", - "crypto/fipsmodule/ec/ec_test.cc", - "crypto/fipsmodule/ec/p256-nistz_test.cc", - "crypto/fipsmodule/ec/p256_test.cc", - "crypto/fipsmodule/ecdsa/ecdsa_test.cc", - "crypto/fipsmodule/hkdf/hkdf_test.cc", - "crypto/fipsmodule/md5/md5_test.cc", - "crypto/fipsmodule/modes/gcm_test.cc", - "crypto/fipsmodule/rand/ctrdrbg_test.cc", - "crypto/fipsmodule/rand/fork_detect_test.cc", - "crypto/fipsmodule/service_indicator/service_indicator_test.cc", - "crypto/fipsmodule/sha/sha_test.cc", - "crypto/hmac_extra/hmac_test.cc", - "crypto/hpke/hpke_test.cc", - "crypto/hrss/hrss_test.cc", - "crypto/impl_dispatch_test.cc", - "crypto/keccak/keccak_test.cc", - "crypto/kyber/kyber_test.cc", - "crypto/lhash/lhash_test.cc", - "crypto/obj/obj_test.cc", - "crypto/pem/pem_test.cc", - "crypto/pkcs7/pkcs7_test.cc", - "crypto/pkcs8/pkcs12_test.cc", - "crypto/pkcs8/pkcs8_test.cc", - "crypto/poly1305/poly1305_test.cc", - "crypto/pool/pool_test.cc", - "crypto/rand_extra/getentropy_test.cc", - "crypto/rand_extra/rand_test.cc", - "crypto/refcount_test.cc", - "crypto/rsa_extra/rsa_test.cc", - "crypto/self_test.cc", - "crypto/siphash/siphash_test.cc", - "crypto/spx/spx_test.cc", - "crypto/stack/stack_test.cc", - "crypto/test/gtest_main.cc", - "crypto/thread_test.cc", - "crypto/trust_token/trust_token_test.cc", - "crypto/x509/tab_test.cc", - "crypto/x509/x509_test.cc", - "crypto/x509/x509_time_test.cc", + "crypto/abi_self_test.cc", + "crypto/asn1/asn1_test.cc", + "crypto/base64/base64_test.cc", + "crypto/bio/bio_test.cc", + "crypto/blake2/blake2_test.cc", + "crypto/buf/buf_test.cc", + "crypto/bytestring/bytestring_test.cc", + "crypto/chacha/chacha_test.cc", + "crypto/cipher_extra/aead_test.cc", + "crypto/cipher_extra/cipher_test.cc", + "crypto/compiler_test.cc", + "crypto/conf/conf_test.cc", + "crypto/constant_time_test.cc", + "crypto/cpu_arm_linux_test.cc", + "crypto/crypto_test.cc", + "crypto/curve25519/ed25519_test.cc", + "crypto/curve25519/spake25519_test.cc", + "crypto/curve25519/x25519_test.cc", + "crypto/dh_extra/dh_test.cc", + "crypto/digest_extra/digest_test.cc", + "crypto/dilithium/dilithium_test.cc", + "crypto/dsa/dsa_test.cc", + "crypto/ecdh_extra/ecdh_test.cc", + "crypto/err/err_test.cc", + "crypto/evp/evp_extra_test.cc", + "crypto/evp/evp_test.cc", + "crypto/evp/pbkdf_test.cc", + "crypto/evp/scrypt_test.cc", + "crypto/fipsmodule/aes/aes_test.cc", + "crypto/fipsmodule/bn/bn_test.cc", + "crypto/fipsmodule/cmac/cmac_test.cc", + "crypto/fipsmodule/ec/ec_test.cc", + "crypto/fipsmodule/ec/p256-nistz_test.cc", + "crypto/fipsmodule/ec/p256_test.cc", + "crypto/fipsmodule/ecdsa/ecdsa_test.cc", + "crypto/fipsmodule/hkdf/hkdf_test.cc", + "crypto/fipsmodule/md5/md5_test.cc", + "crypto/fipsmodule/modes/gcm_test.cc", + "crypto/fipsmodule/rand/ctrdrbg_test.cc", + "crypto/fipsmodule/rand/fork_detect_test.cc", + "crypto/fipsmodule/service_indicator/service_indicator_test.cc", + "crypto/fipsmodule/sha/sha_test.cc", + "crypto/hmac_extra/hmac_test.cc", + "crypto/hpke/hpke_test.cc", + "crypto/hrss/hrss_test.cc", + "crypto/impl_dispatch_test.cc", + "crypto/keccak/keccak_test.cc", + "crypto/kyber/kyber_test.cc", + "crypto/lhash/lhash_test.cc", + "crypto/obj/obj_test.cc", + "crypto/pem/pem_test.cc", + "crypto/pkcs7/pkcs7_test.cc", + "crypto/pkcs8/pkcs12_test.cc", + "crypto/pkcs8/pkcs8_test.cc", + "crypto/poly1305/poly1305_test.cc", + "crypto/pool/pool_test.cc", + "crypto/rand_extra/getentropy_test.cc", + "crypto/rand_extra/rand_test.cc", + "crypto/refcount_test.cc", + "crypto/rsa_extra/rsa_test.cc", + "crypto/self_test.cc", + "crypto/siphash/siphash_test.cc", + "crypto/spx/spx_test.cc", + "crypto/stack/stack_test.cc", + "crypto/test/gtest_main.cc", + "crypto/thread_test.cc", + "crypto/trust_token/trust_token_test.cc", + "crypto/x509/tab_test.cc", + "crypto/x509/x509_test.cc", + "crypto/x509/x509_time_test.cc", ] crypto_test_data = [ - "crypto/blake2/blake2b256_tests.txt", - "crypto/cipher_extra/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt", - "crypto/cipher_extra/test/aes_128_cbc_sha1_tls_tests.txt", - "crypto/cipher_extra/test/aes_128_ccm_bluetooth_8_tests.txt", - "crypto/cipher_extra/test/aes_128_ccm_bluetooth_tests.txt", - "crypto/cipher_extra/test/aes_128_ccm_matter_tests.txt", - "crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt", - "crypto/cipher_extra/test/aes_128_gcm_randnonce_tests.txt", - "crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt", - "crypto/cipher_extra/test/aes_128_gcm_tests.txt", - "crypto/cipher_extra/test/aes_192_gcm_tests.txt", - "crypto/cipher_extra/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt", - "crypto/cipher_extra/test/aes_256_cbc_sha1_tls_tests.txt", - "crypto/cipher_extra/test/aes_256_ctr_hmac_sha256.txt", - "crypto/cipher_extra/test/aes_256_gcm_randnonce_tests.txt", - "crypto/cipher_extra/test/aes_256_gcm_siv_tests.txt", - "crypto/cipher_extra/test/aes_256_gcm_tests.txt", - "crypto/cipher_extra/test/chacha20_poly1305_tests.txt", - "crypto/cipher_extra/test/cipher_tests.txt", - "crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", - "crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_tests.txt", - "crypto/cipher_extra/test/nist_cavp/aes_128_cbc.txt", - "crypto/cipher_extra/test/nist_cavp/aes_128_ctr.txt", - "crypto/cipher_extra/test/nist_cavp/aes_128_gcm.txt", - "crypto/cipher_extra/test/nist_cavp/aes_192_cbc.txt", - "crypto/cipher_extra/test/nist_cavp/aes_192_ctr.txt", - "crypto/cipher_extra/test/nist_cavp/aes_256_cbc.txt", - "crypto/cipher_extra/test/nist_cavp/aes_256_ctr.txt", - "crypto/cipher_extra/test/nist_cavp/aes_256_gcm.txt", - "crypto/cipher_extra/test/nist_cavp/tdes_cbc.txt", - "crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt", - "crypto/cipher_extra/test/xchacha20_poly1305_tests.txt", - "crypto/curve25519/ed25519_tests.txt", - "crypto/ecdh_extra/ecdh_tests.txt", - "crypto/evp/evp_tests.txt", - "crypto/evp/scrypt_tests.txt", - "crypto/fipsmodule/aes/aes_tests.txt", - "crypto/fipsmodule/bn/test/exp_tests.txt", - "crypto/fipsmodule/bn/test/gcd_tests.txt", - "crypto/fipsmodule/bn/test/miller_rabin_tests.txt", - "crypto/fipsmodule/bn/test/mod_exp_tests.txt", - "crypto/fipsmodule/bn/test/mod_inv_tests.txt", - "crypto/fipsmodule/bn/test/mod_mul_tests.txt", - "crypto/fipsmodule/bn/test/mod_sqrt_tests.txt", - "crypto/fipsmodule/bn/test/product_tests.txt", - "crypto/fipsmodule/bn/test/quotient_tests.txt", - "crypto/fipsmodule/bn/test/shift_tests.txt", - "crypto/fipsmodule/bn/test/sum_tests.txt", - "crypto/fipsmodule/cmac/cavp_3des_cmac_tests.txt", - "crypto/fipsmodule/cmac/cavp_aes128_cmac_tests.txt", - "crypto/fipsmodule/cmac/cavp_aes192_cmac_tests.txt", - "crypto/fipsmodule/cmac/cavp_aes256_cmac_tests.txt", - "crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt", - "crypto/fipsmodule/ec/p256-nistz_tests.txt", - "crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt", - "crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt", - "crypto/fipsmodule/modes/gcm_tests.txt", - "crypto/fipsmodule/rand/ctrdrbg_vectors.txt", - "crypto/hmac_extra/hmac_tests.txt", - "crypto/hpke/hpke_test_vectors.txt", - "crypto/keccak/keccak_tests.txt", - "crypto/kyber/kyber_tests.txt", - "crypto/pkcs8/test/bad1.p12", - "crypto/pkcs8/test/bad2.p12", - "crypto/pkcs8/test/bad3.p12", - "crypto/pkcs8/test/empty_password.p12", - "crypto/pkcs8/test/empty_password_ber.p12", - "crypto/pkcs8/test/empty_password_ber_nested.p12", - "crypto/pkcs8/test/no_encryption.p12", - "crypto/pkcs8/test/nss.p12", - "crypto/pkcs8/test/null_password.p12", - "crypto/pkcs8/test/openssl.p12", - "crypto/pkcs8/test/pbes2_sha1.p12", - "crypto/pkcs8/test/pbes2_sha256.p12", - "crypto/pkcs8/test/unicode_password.p12", - "crypto/pkcs8/test/windows.p12", - "crypto/poly1305/poly1305_tests.txt", - "crypto/siphash/siphash_tests.txt", - "crypto/spx/spx_tests.txt", - "crypto/spx/spx_tests_deterministic.txt", - "crypto/x509/test/basic_constraints_ca.pem", - "crypto/x509/test/basic_constraints_ca_pathlen_0.pem", - "crypto/x509/test/basic_constraints_ca_pathlen_1.pem", - "crypto/x509/test/basic_constraints_ca_pathlen_10.pem", - "crypto/x509/test/basic_constraints_leaf.pem", - "crypto/x509/test/basic_constraints_none.pem", - "crypto/x509/test/invalid_extension_intermediate.pem", - "crypto/x509/test/invalid_extension_intermediate_authority_key_identifier.pem", - "crypto/x509/test/invalid_extension_intermediate_basic_constraints.pem", - "crypto/x509/test/invalid_extension_intermediate_ext_key_usage.pem", - "crypto/x509/test/invalid_extension_intermediate_key_usage.pem", - "crypto/x509/test/invalid_extension_intermediate_name_constraints.pem", - "crypto/x509/test/invalid_extension_intermediate_subject_alt_name.pem", - "crypto/x509/test/invalid_extension_intermediate_subject_key_identifier.pem", - "crypto/x509/test/invalid_extension_leaf.pem", - "crypto/x509/test/invalid_extension_leaf_authority_key_identifier.pem", - "crypto/x509/test/invalid_extension_leaf_basic_constraints.pem", - "crypto/x509/test/invalid_extension_leaf_ext_key_usage.pem", - "crypto/x509/test/invalid_extension_leaf_key_usage.pem", - "crypto/x509/test/invalid_extension_leaf_name_constraints.pem", - "crypto/x509/test/invalid_extension_leaf_subject_alt_name.pem", - "crypto/x509/test/invalid_extension_leaf_subject_key_identifier.pem", - "crypto/x509/test/invalid_extension_root.pem", - "crypto/x509/test/invalid_extension_root_authority_key_identifier.pem", - "crypto/x509/test/invalid_extension_root_basic_constraints.pem", - "crypto/x509/test/invalid_extension_root_ext_key_usage.pem", - "crypto/x509/test/invalid_extension_root_key_usage.pem", - "crypto/x509/test/invalid_extension_root_name_constraints.pem", - "crypto/x509/test/invalid_extension_root_subject_alt_name.pem", - "crypto/x509/test/invalid_extension_root_subject_key_identifier.pem", - "crypto/x509/test/many_constraints.pem", - "crypto/x509/test/many_names1.pem", - "crypto/x509/test/many_names2.pem", - "crypto/x509/test/many_names3.pem", - "crypto/x509/test/policy_intermediate.pem", - "crypto/x509/test/policy_intermediate_any.pem", - "crypto/x509/test/policy_intermediate_duplicate.pem", - "crypto/x509/test/policy_intermediate_invalid.pem", - "crypto/x509/test/policy_intermediate_mapped.pem", - "crypto/x509/test/policy_intermediate_mapped_any.pem", - "crypto/x509/test/policy_intermediate_mapped_oid3.pem", - "crypto/x509/test/policy_intermediate_require.pem", - "crypto/x509/test/policy_intermediate_require1.pem", - "crypto/x509/test/policy_intermediate_require2.pem", - "crypto/x509/test/policy_intermediate_require_duplicate.pem", - "crypto/x509/test/policy_intermediate_require_no_policies.pem", - "crypto/x509/test/policy_leaf.pem", - "crypto/x509/test/policy_leaf_any.pem", - "crypto/x509/test/policy_leaf_duplicate.pem", - "crypto/x509/test/policy_leaf_invalid.pem", - "crypto/x509/test/policy_leaf_none.pem", - "crypto/x509/test/policy_leaf_oid1.pem", - "crypto/x509/test/policy_leaf_oid2.pem", - "crypto/x509/test/policy_leaf_oid3.pem", - "crypto/x509/test/policy_leaf_oid4.pem", - "crypto/x509/test/policy_leaf_oid5.pem", - "crypto/x509/test/policy_leaf_require.pem", - "crypto/x509/test/policy_leaf_require1.pem", - "crypto/x509/test/policy_root.pem", - "crypto/x509/test/policy_root2.pem", - "crypto/x509/test/policy_root_cross_inhibit_mapping.pem", - "crypto/x509/test/pss_sha1.pem", - "crypto/x509/test/pss_sha1_explicit.pem", - "crypto/x509/test/pss_sha1_mgf1_syntax_error.pem", - "crypto/x509/test/pss_sha224.pem", - "crypto/x509/test/pss_sha256.pem", - "crypto/x509/test/pss_sha256_explicit_trailer.pem", - "crypto/x509/test/pss_sha256_mgf1_sha384.pem", - "crypto/x509/test/pss_sha256_mgf1_syntax_error.pem", - "crypto/x509/test/pss_sha256_omit_nulls.pem", - "crypto/x509/test/pss_sha256_salt31.pem", - "crypto/x509/test/pss_sha256_salt_overflow.pem", - "crypto/x509/test/pss_sha256_unknown_mgf.pem", - "crypto/x509/test/pss_sha256_wrong_trailer.pem", - "crypto/x509/test/pss_sha384.pem", - "crypto/x509/test/pss_sha512.pem", - "crypto/x509/test/some_names1.pem", - "crypto/x509/test/some_names2.pem", - "crypto/x509/test/some_names3.pem", - "crypto/x509/test/trailing_data_leaf_authority_key_identifier.pem", - "crypto/x509/test/trailing_data_leaf_basic_constraints.pem", - "crypto/x509/test/trailing_data_leaf_ext_key_usage.pem", - "crypto/x509/test/trailing_data_leaf_key_usage.pem", - "crypto/x509/test/trailing_data_leaf_name_constraints.pem", - "crypto/x509/test/trailing_data_leaf_subject_alt_name.pem", - "crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem", - "third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt", - "third_party/wycheproof_testvectors/aes_cmac_test.txt", - "third_party/wycheproof_testvectors/aes_gcm_siv_test.txt", - "third_party/wycheproof_testvectors/aes_gcm_test.txt", - "third_party/wycheproof_testvectors/chacha20_poly1305_test.txt", - "third_party/wycheproof_testvectors/dsa_test.txt", - "third_party/wycheproof_testvectors/ecdh_secp224r1_test.txt", - "third_party/wycheproof_testvectors/ecdh_secp256r1_test.txt", - "third_party/wycheproof_testvectors/ecdh_secp384r1_test.txt", - "third_party/wycheproof_testvectors/ecdh_secp521r1_test.txt", - "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha224_test.txt", - "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha256_test.txt", - "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha512_test.txt", - "third_party/wycheproof_testvectors/ecdsa_secp256r1_sha256_test.txt", - "third_party/wycheproof_testvectors/ecdsa_secp256r1_sha512_test.txt", - "third_party/wycheproof_testvectors/ecdsa_secp384r1_sha384_test.txt", - "third_party/wycheproof_testvectors/ecdsa_secp384r1_sha512_test.txt", - "third_party/wycheproof_testvectors/ecdsa_secp521r1_sha512_test.txt", - "third_party/wycheproof_testvectors/eddsa_test.txt", - "third_party/wycheproof_testvectors/hkdf_sha1_test.txt", - "third_party/wycheproof_testvectors/hkdf_sha256_test.txt", - "third_party/wycheproof_testvectors/hkdf_sha384_test.txt", - "third_party/wycheproof_testvectors/hkdf_sha512_test.txt", - "third_party/wycheproof_testvectors/hmac_sha1_test.txt", - "third_party/wycheproof_testvectors/hmac_sha224_test.txt", - "third_party/wycheproof_testvectors/hmac_sha256_test.txt", - "third_party/wycheproof_testvectors/hmac_sha384_test.txt", - "third_party/wycheproof_testvectors/hmac_sha512_test.txt", - "third_party/wycheproof_testvectors/kw_test.txt", - "third_party/wycheproof_testvectors/kwp_test.txt", - "third_party/wycheproof_testvectors/primality_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha1_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha224_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha256_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha384_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha512_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha256_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha512_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha256_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha1_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha512_test.txt", - "third_party/wycheproof_testvectors/rsa_oaep_misc_test.txt", - "third_party/wycheproof_testvectors/rsa_pkcs1_2048_test.txt", - "third_party/wycheproof_testvectors/rsa_pkcs1_3072_test.txt", - "third_party/wycheproof_testvectors/rsa_pkcs1_4096_test.txt", - "third_party/wycheproof_testvectors/rsa_pss_2048_sha1_mgf1_20_test.txt", - "third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_0_test.txt", - "third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_32_test.txt", - "third_party/wycheproof_testvectors/rsa_pss_3072_sha256_mgf1_32_test.txt", - "third_party/wycheproof_testvectors/rsa_pss_4096_sha256_mgf1_32_test.txt", - "third_party/wycheproof_testvectors/rsa_pss_4096_sha512_mgf1_32_test.txt", - "third_party/wycheproof_testvectors/rsa_pss_misc_test.txt", - "third_party/wycheproof_testvectors/rsa_sig_gen_misc_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_2048_sha224_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_2048_sha256_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_2048_sha384_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_2048_sha512_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_3072_sha256_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_3072_sha384_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_3072_sha512_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_4096_sha384_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_4096_sha512_test.txt", - "third_party/wycheproof_testvectors/rsa_signature_test.txt", - "third_party/wycheproof_testvectors/x25519_test.txt", - "third_party/wycheproof_testvectors/xchacha20_poly1305_test.txt", + "crypto/blake2/blake2b256_tests.txt", + "crypto/cipher_extra/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt", + "crypto/cipher_extra/test/aes_128_cbc_sha1_tls_tests.txt", + "crypto/cipher_extra/test/aes_128_ccm_bluetooth_8_tests.txt", + "crypto/cipher_extra/test/aes_128_ccm_bluetooth_tests.txt", + "crypto/cipher_extra/test/aes_128_ccm_matter_tests.txt", + "crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt", + "crypto/cipher_extra/test/aes_128_gcm_randnonce_tests.txt", + "crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt", + "crypto/cipher_extra/test/aes_128_gcm_tests.txt", + "crypto/cipher_extra/test/aes_192_gcm_tests.txt", + "crypto/cipher_extra/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt", + "crypto/cipher_extra/test/aes_256_cbc_sha1_tls_tests.txt", + "crypto/cipher_extra/test/aes_256_ctr_hmac_sha256.txt", + "crypto/cipher_extra/test/aes_256_gcm_randnonce_tests.txt", + "crypto/cipher_extra/test/aes_256_gcm_siv_tests.txt", + "crypto/cipher_extra/test/aes_256_gcm_tests.txt", + "crypto/cipher_extra/test/chacha20_poly1305_tests.txt", + "crypto/cipher_extra/test/cipher_tests.txt", + "crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", + "crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_tests.txt", + "crypto/cipher_extra/test/nist_cavp/aes_128_cbc.txt", + "crypto/cipher_extra/test/nist_cavp/aes_128_ctr.txt", + "crypto/cipher_extra/test/nist_cavp/aes_128_gcm.txt", + "crypto/cipher_extra/test/nist_cavp/aes_192_cbc.txt", + "crypto/cipher_extra/test/nist_cavp/aes_192_ctr.txt", + "crypto/cipher_extra/test/nist_cavp/aes_256_cbc.txt", + "crypto/cipher_extra/test/nist_cavp/aes_256_ctr.txt", + "crypto/cipher_extra/test/nist_cavp/aes_256_gcm.txt", + "crypto/cipher_extra/test/nist_cavp/tdes_cbc.txt", + "crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt", + "crypto/cipher_extra/test/xchacha20_poly1305_tests.txt", + "crypto/curve25519/ed25519_tests.txt", + "crypto/dilithium/dilithium_tests.txt", + "crypto/dilithium/edge_cases_draft_dilithium3_sign.txt", + "crypto/dilithium/edge_cases_draft_dilithium3_verify.txt", + "crypto/ecdh_extra/ecdh_tests.txt", + "crypto/evp/evp_tests.txt", + "crypto/evp/scrypt_tests.txt", + "crypto/fipsmodule/aes/aes_tests.txt", + "crypto/fipsmodule/bn/test/exp_tests.txt", + "crypto/fipsmodule/bn/test/gcd_tests.txt", + "crypto/fipsmodule/bn/test/miller_rabin_tests.txt", + "crypto/fipsmodule/bn/test/mod_exp_tests.txt", + "crypto/fipsmodule/bn/test/mod_inv_tests.txt", + "crypto/fipsmodule/bn/test/mod_mul_tests.txt", + "crypto/fipsmodule/bn/test/mod_sqrt_tests.txt", + "crypto/fipsmodule/bn/test/product_tests.txt", + "crypto/fipsmodule/bn/test/quotient_tests.txt", + "crypto/fipsmodule/bn/test/shift_tests.txt", + "crypto/fipsmodule/bn/test/sum_tests.txt", + "crypto/fipsmodule/cmac/cavp_3des_cmac_tests.txt", + "crypto/fipsmodule/cmac/cavp_aes128_cmac_tests.txt", + "crypto/fipsmodule/cmac/cavp_aes192_cmac_tests.txt", + "crypto/fipsmodule/cmac/cavp_aes256_cmac_tests.txt", + "crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt", + "crypto/fipsmodule/ec/p256-nistz_tests.txt", + "crypto/fipsmodule/ecdsa/ecdsa_sign_tests.txt", + "crypto/fipsmodule/ecdsa/ecdsa_verify_tests.txt", + "crypto/fipsmodule/modes/gcm_tests.txt", + "crypto/fipsmodule/rand/ctrdrbg_vectors.txt", + "crypto/hmac_extra/hmac_tests.txt", + "crypto/hpke/hpke_test_vectors.txt", + "crypto/keccak/keccak_tests.txt", + "crypto/kyber/kyber_tests.txt", + "crypto/pkcs8/test/bad1.p12", + "crypto/pkcs8/test/bad2.p12", + "crypto/pkcs8/test/bad3.p12", + "crypto/pkcs8/test/empty_password.p12", + "crypto/pkcs8/test/empty_password_ber.p12", + "crypto/pkcs8/test/empty_password_ber_nested.p12", + "crypto/pkcs8/test/no_encryption.p12", + "crypto/pkcs8/test/nss.p12", + "crypto/pkcs8/test/null_password.p12", + "crypto/pkcs8/test/openssl.p12", + "crypto/pkcs8/test/pbes2_sha1.p12", + "crypto/pkcs8/test/pbes2_sha256.p12", + "crypto/pkcs8/test/unicode_password.p12", + "crypto/pkcs8/test/windows.p12", + "crypto/poly1305/poly1305_tests.txt", + "crypto/siphash/siphash_tests.txt", + "crypto/spx/spx_tests.txt", + "crypto/spx/spx_tests_deterministic.txt", + "crypto/x509/test/basic_constraints_ca.pem", + "crypto/x509/test/basic_constraints_ca_pathlen_0.pem", + "crypto/x509/test/basic_constraints_ca_pathlen_1.pem", + "crypto/x509/test/basic_constraints_ca_pathlen_10.pem", + "crypto/x509/test/basic_constraints_leaf.pem", + "crypto/x509/test/basic_constraints_none.pem", + "crypto/x509/test/invalid_extension_intermediate.pem", + "crypto/x509/test/invalid_extension_intermediate_authority_key_identifier.pem", + "crypto/x509/test/invalid_extension_intermediate_basic_constraints.pem", + "crypto/x509/test/invalid_extension_intermediate_ext_key_usage.pem", + "crypto/x509/test/invalid_extension_intermediate_key_usage.pem", + "crypto/x509/test/invalid_extension_intermediate_name_constraints.pem", + "crypto/x509/test/invalid_extension_intermediate_subject_alt_name.pem", + "crypto/x509/test/invalid_extension_intermediate_subject_key_identifier.pem", + "crypto/x509/test/invalid_extension_leaf.pem", + "crypto/x509/test/invalid_extension_leaf_authority_key_identifier.pem", + "crypto/x509/test/invalid_extension_leaf_basic_constraints.pem", + "crypto/x509/test/invalid_extension_leaf_ext_key_usage.pem", + "crypto/x509/test/invalid_extension_leaf_key_usage.pem", + "crypto/x509/test/invalid_extension_leaf_name_constraints.pem", + "crypto/x509/test/invalid_extension_leaf_subject_alt_name.pem", + "crypto/x509/test/invalid_extension_leaf_subject_key_identifier.pem", + "crypto/x509/test/invalid_extension_root.pem", + "crypto/x509/test/invalid_extension_root_authority_key_identifier.pem", + "crypto/x509/test/invalid_extension_root_basic_constraints.pem", + "crypto/x509/test/invalid_extension_root_ext_key_usage.pem", + "crypto/x509/test/invalid_extension_root_key_usage.pem", + "crypto/x509/test/invalid_extension_root_name_constraints.pem", + "crypto/x509/test/invalid_extension_root_subject_alt_name.pem", + "crypto/x509/test/invalid_extension_root_subject_key_identifier.pem", + "crypto/x509/test/many_constraints.pem", + "crypto/x509/test/many_names1.pem", + "crypto/x509/test/many_names2.pem", + "crypto/x509/test/many_names3.pem", + "crypto/x509/test/policy_intermediate.pem", + "crypto/x509/test/policy_intermediate_any.pem", + "crypto/x509/test/policy_intermediate_duplicate.pem", + "crypto/x509/test/policy_intermediate_invalid.pem", + "crypto/x509/test/policy_intermediate_mapped.pem", + "crypto/x509/test/policy_intermediate_mapped_any.pem", + "crypto/x509/test/policy_intermediate_mapped_oid3.pem", + "crypto/x509/test/policy_intermediate_require.pem", + "crypto/x509/test/policy_intermediate_require1.pem", + "crypto/x509/test/policy_intermediate_require2.pem", + "crypto/x509/test/policy_intermediate_require_duplicate.pem", + "crypto/x509/test/policy_intermediate_require_no_policies.pem", + "crypto/x509/test/policy_leaf.pem", + "crypto/x509/test/policy_leaf_any.pem", + "crypto/x509/test/policy_leaf_duplicate.pem", + "crypto/x509/test/policy_leaf_invalid.pem", + "crypto/x509/test/policy_leaf_none.pem", + "crypto/x509/test/policy_leaf_oid1.pem", + "crypto/x509/test/policy_leaf_oid2.pem", + "crypto/x509/test/policy_leaf_oid3.pem", + "crypto/x509/test/policy_leaf_oid4.pem", + "crypto/x509/test/policy_leaf_oid5.pem", + "crypto/x509/test/policy_leaf_require.pem", + "crypto/x509/test/policy_leaf_require1.pem", + "crypto/x509/test/policy_root.pem", + "crypto/x509/test/policy_root2.pem", + "crypto/x509/test/policy_root_cross_inhibit_mapping.pem", + "crypto/x509/test/pss_sha1.pem", + "crypto/x509/test/pss_sha1_explicit.pem", + "crypto/x509/test/pss_sha1_mgf1_syntax_error.pem", + "crypto/x509/test/pss_sha224.pem", + "crypto/x509/test/pss_sha256.pem", + "crypto/x509/test/pss_sha256_explicit_trailer.pem", + "crypto/x509/test/pss_sha256_mgf1_sha384.pem", + "crypto/x509/test/pss_sha256_mgf1_syntax_error.pem", + "crypto/x509/test/pss_sha256_omit_nulls.pem", + "crypto/x509/test/pss_sha256_salt31.pem", + "crypto/x509/test/pss_sha256_salt_overflow.pem", + "crypto/x509/test/pss_sha256_unknown_mgf.pem", + "crypto/x509/test/pss_sha256_wrong_trailer.pem", + "crypto/x509/test/pss_sha384.pem", + "crypto/x509/test/pss_sha512.pem", + "crypto/x509/test/some_names1.pem", + "crypto/x509/test/some_names2.pem", + "crypto/x509/test/some_names3.pem", + "crypto/x509/test/trailing_data_leaf_authority_key_identifier.pem", + "crypto/x509/test/trailing_data_leaf_basic_constraints.pem", + "crypto/x509/test/trailing_data_leaf_ext_key_usage.pem", + "crypto/x509/test/trailing_data_leaf_key_usage.pem", + "crypto/x509/test/trailing_data_leaf_name_constraints.pem", + "crypto/x509/test/trailing_data_leaf_subject_alt_name.pem", + "crypto/x509/test/trailing_data_leaf_subject_key_identifier.pem", + "third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt", + "third_party/wycheproof_testvectors/aes_cmac_test.txt", + "third_party/wycheproof_testvectors/aes_gcm_siv_test.txt", + "third_party/wycheproof_testvectors/aes_gcm_test.txt", + "third_party/wycheproof_testvectors/chacha20_poly1305_test.txt", + "third_party/wycheproof_testvectors/dsa_test.txt", + "third_party/wycheproof_testvectors/ecdh_secp224r1_test.txt", + "third_party/wycheproof_testvectors/ecdh_secp256r1_test.txt", + "third_party/wycheproof_testvectors/ecdh_secp384r1_test.txt", + "third_party/wycheproof_testvectors/ecdh_secp521r1_test.txt", + "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha224_test.txt", + "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha256_test.txt", + "third_party/wycheproof_testvectors/ecdsa_secp224r1_sha512_test.txt", + "third_party/wycheproof_testvectors/ecdsa_secp256r1_sha256_test.txt", + "third_party/wycheproof_testvectors/ecdsa_secp256r1_sha512_test.txt", + "third_party/wycheproof_testvectors/ecdsa_secp384r1_sha384_test.txt", + "third_party/wycheproof_testvectors/ecdsa_secp384r1_sha512_test.txt", + "third_party/wycheproof_testvectors/ecdsa_secp521r1_sha512_test.txt", + "third_party/wycheproof_testvectors/eddsa_test.txt", + "third_party/wycheproof_testvectors/hkdf_sha1_test.txt", + "third_party/wycheproof_testvectors/hkdf_sha256_test.txt", + "third_party/wycheproof_testvectors/hkdf_sha384_test.txt", + "third_party/wycheproof_testvectors/hkdf_sha512_test.txt", + "third_party/wycheproof_testvectors/hmac_sha1_test.txt", + "third_party/wycheproof_testvectors/hmac_sha224_test.txt", + "third_party/wycheproof_testvectors/hmac_sha256_test.txt", + "third_party/wycheproof_testvectors/hmac_sha384_test.txt", + "third_party/wycheproof_testvectors/hmac_sha512_test.txt", + "third_party/wycheproof_testvectors/kw_test.txt", + "third_party/wycheproof_testvectors/kwp_test.txt", + "third_party/wycheproof_testvectors/primality_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha1_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha224_mgf1sha224_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha256_mgf1sha256_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha384_mgf1sha384_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_2048_sha512_mgf1sha512_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_3072_sha256_mgf1sha256_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_3072_sha512_mgf1sha512_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_4096_sha256_mgf1sha256_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha1_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_4096_sha512_mgf1sha512_test.txt", + "third_party/wycheproof_testvectors/rsa_oaep_misc_test.txt", + "third_party/wycheproof_testvectors/rsa_pkcs1_2048_test.txt", + "third_party/wycheproof_testvectors/rsa_pkcs1_3072_test.txt", + "third_party/wycheproof_testvectors/rsa_pkcs1_4096_test.txt", + "third_party/wycheproof_testvectors/rsa_pss_2048_sha1_mgf1_20_test.txt", + "third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_0_test.txt", + "third_party/wycheproof_testvectors/rsa_pss_2048_sha256_mgf1_32_test.txt", + "third_party/wycheproof_testvectors/rsa_pss_3072_sha256_mgf1_32_test.txt", + "third_party/wycheproof_testvectors/rsa_pss_4096_sha256_mgf1_32_test.txt", + "third_party/wycheproof_testvectors/rsa_pss_4096_sha512_mgf1_32_test.txt", + "third_party/wycheproof_testvectors/rsa_pss_misc_test.txt", + "third_party/wycheproof_testvectors/rsa_sig_gen_misc_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_2048_sha224_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_2048_sha256_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_2048_sha384_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_2048_sha512_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_3072_sha256_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_3072_sha384_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_3072_sha512_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_4096_sha384_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_4096_sha512_test.txt", + "third_party/wycheproof_testvectors/rsa_signature_test.txt", + "third_party/wycheproof_testvectors/x25519_test.txt", + "third_party/wycheproof_testvectors/xchacha20_poly1305_test.txt", ] decrepit_sources = [ - "decrepit/bio/base64_bio.c", - "decrepit/blowfish/blowfish.c", - "decrepit/cast/cast.c", - "decrepit/cast/cast_tables.c", - "decrepit/cfb/cfb.c", - "decrepit/des/cfb64ede.c", - "decrepit/dh/dh_decrepit.c", - "decrepit/dsa/dsa_decrepit.c", - "decrepit/evp/dss1.c", - "decrepit/evp/evp_do_all.c", - "decrepit/obj/obj_decrepit.c", - "decrepit/rc4/rc4_decrepit.c", - "decrepit/ripemd/ripemd.c", - "decrepit/rsa/rsa_decrepit.c", - "decrepit/ssl/ssl_decrepit.c", - "decrepit/x509/x509_decrepit.c", - "decrepit/xts/xts.c", + "decrepit/bio/base64_bio.c", + "decrepit/blowfish/blowfish.c", + "decrepit/cast/cast.c", + "decrepit/cast/cast_tables.c", + "decrepit/cfb/cfb.c", + "decrepit/des/cfb64ede.c", + "decrepit/dh/dh_decrepit.c", + "decrepit/dsa/dsa_decrepit.c", + "decrepit/evp/dss1.c", + "decrepit/evp/evp_do_all.c", + "decrepit/obj/obj_decrepit.c", + "decrepit/rc4/rc4_decrepit.c", + "decrepit/ripemd/ripemd.c", + "decrepit/rsa/rsa_decrepit.c", + "decrepit/ssl/ssl_decrepit.c", + "decrepit/x509/x509_decrepit.c", + "decrepit/xts/xts.c", ] decrepit_internal_headers = [ - "decrepit/cast/internal.h", - "decrepit/macros.h", + "decrepit/cast/internal.h", + "decrepit/macros.h", ] decrepit_test_sources = [ - "crypto/test/gtest_main.cc", - "decrepit/blowfish/blowfish_test.cc", - "decrepit/cast/cast_test.cc", - "decrepit/cfb/cfb_test.cc", - "decrepit/des/des_test.cc", - "decrepit/evp/evp_test.cc", - "decrepit/ripemd/ripemd_test.cc", - "decrepit/xts/xts_test.cc", + "crypto/test/gtest_main.cc", + "decrepit/blowfish/blowfish_test.cc", + "decrepit/cast/cast_test.cc", + "decrepit/cfb/cfb_test.cc", + "decrepit/des/des_test.cc", + "decrepit/evp/evp_test.cc", + "decrepit/ripemd/ripemd_test.cc", + "decrepit/xts/xts_test.cc", ] pki_sources = [ - "pki/cert_error_id.cc", - "pki/cert_error_params.cc", - "pki/cert_errors.cc", - "pki/cert_issuer_source_static.cc", - "pki/certificate.cc", - "pki/certificate_policies.cc", - "pki/common_cert_errors.cc", - "pki/crl.cc", - "pki/encode_values.cc", - "pki/extended_key_usage.cc", - "pki/general_names.cc", - "pki/input.cc", - "pki/ip_util.cc", - "pki/name_constraints.cc", - "pki/ocsp.cc", - "pki/ocsp_verify_result.cc", - "pki/parse_certificate.cc", - "pki/parse_name.cc", - "pki/parse_values.cc", - "pki/parsed_certificate.cc", - "pki/parser.cc", - "pki/path_builder.cc", - "pki/pem.cc", - "pki/revocation_util.cc", - "pki/signature_algorithm.cc", - "pki/simple_path_builder_delegate.cc", - "pki/string_util.cc", - "pki/trust_store.cc", - "pki/trust_store_collection.cc", - "pki/trust_store_in_memory.cc", - "pki/verify_certificate_chain.cc", - "pki/verify_error.cc", - "pki/verify_name_match.cc", - "pki/verify_signed_data.cc", + "pki/cert_error_id.cc", + "pki/cert_error_params.cc", + "pki/cert_errors.cc", + "pki/cert_issuer_source_static.cc", + "pki/certificate.cc", + "pki/certificate_policies.cc", + "pki/common_cert_errors.cc", + "pki/crl.cc", + "pki/encode_values.cc", + "pki/extended_key_usage.cc", + "pki/general_names.cc", + "pki/input.cc", + "pki/ip_util.cc", + "pki/name_constraints.cc", + "pki/ocsp.cc", + "pki/ocsp_verify_result.cc", + "pki/parse_certificate.cc", + "pki/parse_name.cc", + "pki/parse_values.cc", + "pki/parsed_certificate.cc", + "pki/parser.cc", + "pki/path_builder.cc", + "pki/pem.cc", + "pki/revocation_util.cc", + "pki/signature_algorithm.cc", + "pki/simple_path_builder_delegate.cc", + "pki/string_util.cc", + "pki/trust_store.cc", + "pki/trust_store_collection.cc", + "pki/trust_store_in_memory.cc", + "pki/verify.cc", + "pki/verify_certificate_chain.cc", + "pki/verify_error.cc", + "pki/verify_name_match.cc", + "pki/verify_signed_data.cc", ] pki_headers = [ - "include/openssl/pki/certificate.h", - "include/openssl/pki/signature_verify_cache.h", - "include/openssl/pki/verify_error.h", + "include/openssl/pki/certificate.h", + "include/openssl/pki/signature_verify_cache.h", + "include/openssl/pki/verify.h", + "include/openssl/pki/verify_error.h", ] pki_internal_headers = [ - "pki/cert_error_id.h", - "pki/cert_error_params.h", - "pki/cert_errors.h", - "pki/cert_issuer_source.h", - "pki/cert_issuer_source_static.h", - "pki/cert_issuer_source_sync_unittest.h", - "pki/certificate_policies.h", - "pki/common_cert_errors.h", - "pki/crl.h", - "pki/encode_values.h", - "pki/extended_key_usage.h", - "pki/general_names.h", - "pki/input.h", - "pki/ip_util.h", - "pki/mock_signature_verify_cache.h", - "pki/name_constraints.h", - "pki/nist_pkits_unittest.h", - "pki/ocsp.h", - "pki/ocsp_revocation_status.h", - "pki/ocsp_verify_result.h", - "pki/parse_certificate.h", - "pki/parse_name.h", - "pki/parse_values.h", - "pki/parsed_certificate.h", - "pki/parser.h", - "pki/path_builder.h", - "pki/pem.h", - "pki/revocation_util.h", - "pki/signature_algorithm.h", - "pki/simple_path_builder_delegate.h", - "pki/string_util.h", - "pki/test_helpers.h", - "pki/testdata/nist-pkits/pkits_testcases-inl.h", - "pki/trust_store.h", - "pki/trust_store_collection.h", - "pki/trust_store_in_memory.h", - "pki/verify_certificate_chain.h", - "pki/verify_certificate_chain_typed_unittest.h", - "pki/verify_name_match.h", - "pki/verify_signed_data.h", + "pki/cert_error_id.h", + "pki/cert_error_params.h", + "pki/cert_errors.h", + "pki/cert_issuer_source.h", + "pki/cert_issuer_source_static.h", + "pki/cert_issuer_source_sync_unittest.h", + "pki/certificate_policies.h", + "pki/common_cert_errors.h", + "pki/crl.h", + "pki/encode_values.h", + "pki/extended_key_usage.h", + "pki/general_names.h", + "pki/input.h", + "pki/ip_util.h", + "pki/mock_signature_verify_cache.h", + "pki/name_constraints.h", + "pki/nist_pkits_unittest.h", + "pki/ocsp.h", + "pki/ocsp_revocation_status.h", + "pki/ocsp_verify_result.h", + "pki/parse_certificate.h", + "pki/parse_name.h", + "pki/parse_values.h", + "pki/parsed_certificate.h", + "pki/parser.h", + "pki/path_builder.h", + "pki/pem.h", + "pki/revocation_util.h", + "pki/signature_algorithm.h", + "pki/simple_path_builder_delegate.h", + "pki/string_util.h", + "pki/test_helpers.h", + "pki/testdata/nist-pkits/pkits_testcases-inl.h", + "pki/trust_store.h", + "pki/trust_store_collection.h", + "pki/trust_store_in_memory.h", + "pki/verify_certificate_chain.h", + "pki/verify_certificate_chain_typed_unittest.h", + "pki/verify_name_match.h", + "pki/verify_signed_data.h", ] pki_test_sources = [ - "crypto/test/gtest_main.cc", - "pki/cert_issuer_source_static_unittest.cc", - "pki/certificate_policies_unittest.cc", - "pki/certificate_unittest.cc", - "pki/crl_unittest.cc", - "pki/encode_values_unittest.cc", - "pki/extended_key_usage_unittest.cc", - "pki/general_names_unittest.cc", - "pki/input_unittest.cc", - "pki/ip_util_unittest.cc", - "pki/mock_signature_verify_cache.cc", - "pki/name_constraints_unittest.cc", - "pki/nist_pkits_unittest.cc", - "pki/ocsp_unittest.cc", - "pki/parse_certificate_unittest.cc", - "pki/parse_name_unittest.cc", - "pki/parse_values_unittest.cc", - "pki/parsed_certificate_unittest.cc", - "pki/parser_unittest.cc", - "pki/path_builder_pkits_unittest.cc", - "pki/path_builder_unittest.cc", - "pki/path_builder_verify_certificate_chain_unittest.cc", - "pki/pem_unittest.cc", - "pki/signature_algorithm_unittest.cc", - "pki/simple_path_builder_delegate_unittest.cc", - "pki/string_util_unittest.cc", - "pki/test_helpers.cc", - "pki/trust_store_collection_unittest.cc", - "pki/trust_store_in_memory_unittest.cc", - "pki/verify_certificate_chain_pkits_unittest.cc", - "pki/verify_certificate_chain_unittest.cc", - "pki/verify_name_match_unittest.cc", - "pki/verify_signed_data_unittest.cc", + "crypto/test/gtest_main.cc", + "pki/cert_issuer_source_static_unittest.cc", + "pki/certificate_policies_unittest.cc", + "pki/certificate_unittest.cc", + "pki/crl_unittest.cc", + "pki/encode_values_unittest.cc", + "pki/extended_key_usage_unittest.cc", + "pki/general_names_unittest.cc", + "pki/input_unittest.cc", + "pki/ip_util_unittest.cc", + "pki/mock_signature_verify_cache.cc", + "pki/name_constraints_unittest.cc", + "pki/nist_pkits_unittest.cc", + "pki/ocsp_unittest.cc", + "pki/parse_certificate_unittest.cc", + "pki/parse_name_unittest.cc", + "pki/parse_values_unittest.cc", + "pki/parsed_certificate_unittest.cc", + "pki/parser_unittest.cc", + "pki/path_builder_pkits_unittest.cc", + "pki/path_builder_unittest.cc", + "pki/path_builder_verify_certificate_chain_unittest.cc", + "pki/pem_unittest.cc", + "pki/signature_algorithm_unittest.cc", + "pki/simple_path_builder_delegate_unittest.cc", + "pki/string_util_unittest.cc", + "pki/test_helpers.cc", + "pki/trust_store_collection_unittest.cc", + "pki/trust_store_in_memory_unittest.cc", + "pki/verify_certificate_chain_pkits_unittest.cc", + "pki/verify_certificate_chain_unittest.cc", + "pki/verify_name_match_unittest.cc", + "pki/verify_signed_data_unittest.cc", + "pki/verify_unittest.cc", ] pki_test_data = [ - "pki/testdata/cert_issuer_source_static_unittest/c1.pem", - "pki/testdata/cert_issuer_source_static_unittest/c2.pem", - "pki/testdata/cert_issuer_source_static_unittest/d.pem", - "pki/testdata/cert_issuer_source_static_unittest/e1.pem", - "pki/testdata/cert_issuer_source_static_unittest/e2.pem", - "pki/testdata/cert_issuer_source_static_unittest/i1_1.pem", - "pki/testdata/cert_issuer_source_static_unittest/i1_2.pem", - "pki/testdata/cert_issuer_source_static_unittest/i2.pem", - "pki/testdata/cert_issuer_source_static_unittest/i3_1.pem", - "pki/testdata/cert_issuer_source_static_unittest/i3_2.pem", - "pki/testdata/cert_issuer_source_static_unittest/root.pem", - "pki/testdata/certificate_policies_unittest/anypolicy.pem", - "pki/testdata/certificate_policies_unittest/anypolicy_with_qualifier.pem", - "pki/testdata/certificate_policies_unittest/invalid-anypolicy_with_custom_qualifier.pem", - "pki/testdata/certificate_policies_unittest/invalid-empty.pem", - "pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_dupe.pem", - "pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyinformation_unconsumed_data.pem", - "pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyqualifierinfo_unconsumed_data.pem", - "pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_with_empty_qualifiers_sequence.pem", - "pki/testdata/certificate_policies_unittest/invalid-policy_identifier_not_oid.pem", - "pki/testdata/certificate_policies_unittest/policy_1_2_3.pem", - "pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4.pem", - "pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4_with_qualifiers.pem", - "pki/testdata/certificate_policies_unittest/policy_1_2_3_with_custom_qualifier.pem", - "pki/testdata/certificate_policies_unittest/policy_1_2_3_with_qualifier.pem", - "pki/testdata/crl_unittest/bad_crldp_has_crlissuer.pem", - "pki/testdata/crl_unittest/bad_fake_critical_crlentryextension.pem", - "pki/testdata/crl_unittest/bad_fake_critical_extension.pem", - "pki/testdata/crl_unittest/bad_idp_contains_wrong_uri.pem", - "pki/testdata/crl_unittest/bad_idp_indirectcrl.pem", - "pki/testdata/crl_unittest/bad_idp_onlycontainscacerts.pem", - "pki/testdata/crl_unittest/bad_idp_onlycontainscacerts_no_basic_constraints.pem", - "pki/testdata/crl_unittest/bad_idp_onlycontainsusercerts.pem", - "pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainscacerts.pem", - "pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainsusercerts.pem", - "pki/testdata/crl_unittest/bad_key_rollover_signature.pem", - "pki/testdata/crl_unittest/bad_nextupdate_too_old.pem", - "pki/testdata/crl_unittest/bad_signature.pem", - "pki/testdata/crl_unittest/bad_thisupdate_in_future.pem", - "pki/testdata/crl_unittest/bad_thisupdate_too_old.pem", - "pki/testdata/crl_unittest/bad_wrong_issuer.pem", - "pki/testdata/crl_unittest/good.pem", - "pki/testdata/crl_unittest/good_fake_extension.pem", - "pki/testdata/crl_unittest/good_fake_extension_no_nextupdate.pem", - "pki/testdata/crl_unittest/good_generalizedtime.pem", - "pki/testdata/crl_unittest/good_idp_contains_uri.pem", - "pki/testdata/crl_unittest/good_idp_onlycontainscacerts.pem", - "pki/testdata/crl_unittest/good_idp_onlycontainsusercerts.pem", - "pki/testdata/crl_unittest/good_idp_onlycontainsusercerts_no_basic_constraints.pem", - "pki/testdata/crl_unittest/good_idp_uri_and_onlycontainscacerts.pem", - "pki/testdata/crl_unittest/good_idp_uri_and_onlycontainsusercerts.pem", - "pki/testdata/crl_unittest/good_issuer_name_normalization.pem", - "pki/testdata/crl_unittest/good_issuer_no_keyusage.pem", - "pki/testdata/crl_unittest/good_key_rollover.pem", - "pki/testdata/crl_unittest/good_no_crldp.pem", - "pki/testdata/crl_unittest/good_no_nextupdate.pem", - "pki/testdata/crl_unittest/good_no_version.pem", - "pki/testdata/crl_unittest/invalid_garbage_after_crlentryextensions.pem", - "pki/testdata/crl_unittest/invalid_garbage_after_extensions.pem", - "pki/testdata/crl_unittest/invalid_garbage_after_nextupdate.pem", - "pki/testdata/crl_unittest/invalid_garbage_after_revocationdate.pem", - "pki/testdata/crl_unittest/invalid_garbage_after_revokedcerts.pem", - "pki/testdata/crl_unittest/invalid_garbage_after_signaturevalue.pem", - "pki/testdata/crl_unittest/invalid_garbage_after_thisupdate.pem", - "pki/testdata/crl_unittest/invalid_garbage_crlentry.pem", - "pki/testdata/crl_unittest/invalid_garbage_issuer_name.pem", - "pki/testdata/crl_unittest/invalid_garbage_revocationdate.pem", - "pki/testdata/crl_unittest/invalid_garbage_revoked_serial_number.pem", - "pki/testdata/crl_unittest/invalid_garbage_signaturealgorithm.pem", - "pki/testdata/crl_unittest/invalid_garbage_signaturevalue.pem", - "pki/testdata/crl_unittest/invalid_garbage_tbs_signature_algorithm.pem", - "pki/testdata/crl_unittest/invalid_garbage_tbscertlist.pem", - "pki/testdata/crl_unittest/invalid_garbage_thisupdate.pem", - "pki/testdata/crl_unittest/invalid_garbage_version.pem", - "pki/testdata/crl_unittest/invalid_idp_dpname_choice_extra_data.pem", - "pki/testdata/crl_unittest/invalid_idp_empty_sequence.pem", - "pki/testdata/crl_unittest/invalid_idp_onlycontains_user_and_ca_certs.pem", - "pki/testdata/crl_unittest/invalid_idp_onlycontainsusercerts_v1_leaf.pem", - "pki/testdata/crl_unittest/invalid_issuer_keyusage_no_crlsign.pem", - "pki/testdata/crl_unittest/invalid_key_rollover_issuer_keyusage_no_crlsign.pem", - "pki/testdata/crl_unittest/invalid_mismatched_signature_algorithm.pem", - "pki/testdata/crl_unittest/invalid_revoked_empty_sequence.pem", - "pki/testdata/crl_unittest/invalid_v1_explicit.pem", - "pki/testdata/crl_unittest/invalid_v1_with_crlentryextension.pem", - "pki/testdata/crl_unittest/invalid_v1_with_extension.pem", - "pki/testdata/crl_unittest/invalid_v3.pem", - "pki/testdata/crl_unittest/revoked.pem", - "pki/testdata/crl_unittest/revoked_fake_crlentryextension.pem", - "pki/testdata/crl_unittest/revoked_generalized_revocationdate.pem", - "pki/testdata/crl_unittest/revoked_key_rollover.pem", - "pki/testdata/crl_unittest/revoked_no_nextupdate.pem", - "pki/testdata/name_constraints_unittest/directoryname-excludeall.pem", - "pki/testdata/name_constraints_unittest/directoryname-excluded.pem", - "pki/testdata/name_constraints_unittest/directoryname.pem", - "pki/testdata/name_constraints_unittest/directoryname_and_dnsname.pem", - "pki/testdata/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem", - "pki/testdata/name_constraints_unittest/dnsname-exclude_dot.pem", - "pki/testdata/name_constraints_unittest/dnsname-excludeall.pem", - "pki/testdata/name_constraints_unittest/dnsname-excluded.pem", - "pki/testdata/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem", - "pki/testdata/name_constraints_unittest/dnsname-permitted_two_dot.pem", - "pki/testdata/name_constraints_unittest/dnsname-permitted_with_leading_dot.pem", - "pki/testdata/name_constraints_unittest/dnsname-with_max.pem", - "pki/testdata/name_constraints_unittest/dnsname-with_min_0.pem", - "pki/testdata/name_constraints_unittest/dnsname-with_min_0_and_max.pem", - "pki/testdata/name_constraints_unittest/dnsname-with_min_1.pem", - "pki/testdata/name_constraints_unittest/dnsname-with_min_1_and_max.pem", - "pki/testdata/name_constraints_unittest/dnsname.pem", - "pki/testdata/name_constraints_unittest/dnsname2.pem", - "pki/testdata/name_constraints_unittest/edipartyname-excluded.pem", - "pki/testdata/name_constraints_unittest/edipartyname-permitted.pem", - "pki/testdata/name_constraints_unittest/invalid-empty_excluded_subtree.pem", - "pki/testdata/name_constraints_unittest/invalid-empty_permitted_subtree.pem", - "pki/testdata/name_constraints_unittest/invalid-no_subtrees.pem", - "pki/testdata/name_constraints_unittest/ipaddress-excludeall.pem", - "pki/testdata/name_constraints_unittest/ipaddress-excluded.pem", - "pki/testdata/name_constraints_unittest/ipaddress-invalid_addr.pem", - "pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_1.pem", - "pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_2.pem", - "pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_3.pem", - "pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_4.pem", - "pki/testdata/name_constraints_unittest/ipaddress-mapped_addrs.pem", - "pki/testdata/name_constraints_unittest/ipaddress-permit_all.pem", - "pki/testdata/name_constraints_unittest/ipaddress-permit_prefix1.pem", - "pki/testdata/name_constraints_unittest/ipaddress-permit_prefix31.pem", - "pki/testdata/name_constraints_unittest/ipaddress-permit_singlehost.pem", - "pki/testdata/name_constraints_unittest/ipaddress.pem", - "pki/testdata/name_constraints_unittest/name-ca.pem", - "pki/testdata/name_constraints_unittest/name-de.pem", - "pki/testdata/name_constraints_unittest/name-empty.pem", - "pki/testdata/name_constraints_unittest/name-jp-tokyo.pem", - "pki/testdata/name_constraints_unittest/name-jp.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-1.1.1.1.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-192.168.1.1.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-email-invalidstring.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-email-localpartcase.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-email-multiple.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-email.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-foo.com.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-ipv6.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona-permitted.example.com.pem", - "pki/testdata/name_constraints_unittest/name-us-arizona.pem", - "pki/testdata/name_constraints_unittest/name-us-california-192.168.1.1.pem", - "pki/testdata/name_constraints_unittest/name-us-california-mountain_view.pem", - "pki/testdata/name_constraints_unittest/name-us-california-permitted.example.com.pem", - "pki/testdata/name_constraints_unittest/name-us-california.pem", - "pki/testdata/name_constraints_unittest/name-us.pem", - "pki/testdata/name_constraints_unittest/othername-excluded.pem", - "pki/testdata/name_constraints_unittest/othername-permitted.pem", - "pki/testdata/name_constraints_unittest/registeredid-excluded.pem", - "pki/testdata/name_constraints_unittest/registeredid-permitted.pem", - "pki/testdata/name_constraints_unittest/rfc822name-excluded-empty.pem", - "pki/testdata/name_constraints_unittest/rfc822name-excluded-hostname.pem", - "pki/testdata/name_constraints_unittest/rfc822name-excluded-hostnamewithat.pem", - "pki/testdata/name_constraints_unittest/rfc822name-excluded-ipv4.pem", - "pki/testdata/name_constraints_unittest/rfc822name-excluded-quoted.pem", - "pki/testdata/name_constraints_unittest/rfc822name-excluded-subdomains.pem", - "pki/testdata/name_constraints_unittest/rfc822name-excluded.pem", - "pki/testdata/name_constraints_unittest/rfc822name-permitted-empty.pem", - "pki/testdata/name_constraints_unittest/rfc822name-permitted-hostname.pem", - "pki/testdata/name_constraints_unittest/rfc822name-permitted-hostnamewithat.pem", - "pki/testdata/name_constraints_unittest/rfc822name-permitted-ipv4.pem", - "pki/testdata/name_constraints_unittest/rfc822name-permitted-quoted.pem", - "pki/testdata/name_constraints_unittest/rfc822name-permitted-subdomains.pem", - "pki/testdata/name_constraints_unittest/rfc822name-permitted.pem", - "pki/testdata/name_constraints_unittest/san-directoryname.pem", - "pki/testdata/name_constraints_unittest/san-dnsname.pem", - "pki/testdata/name_constraints_unittest/san-edipartyname.pem", - "pki/testdata/name_constraints_unittest/san-excluded-directoryname.pem", - "pki/testdata/name_constraints_unittest/san-excluded-dnsname.pem", - "pki/testdata/name_constraints_unittest/san-excluded-ipaddress.pem", - "pki/testdata/name_constraints_unittest/san-invalid-empty.pem", - "pki/testdata/name_constraints_unittest/san-invalid-ipaddress.pem", - "pki/testdata/name_constraints_unittest/san-ipaddress4.pem", - "pki/testdata/name_constraints_unittest/san-ipaddress6.pem", - "pki/testdata/name_constraints_unittest/san-othername.pem", - "pki/testdata/name_constraints_unittest/san-permitted.pem", - "pki/testdata/name_constraints_unittest/san-registeredid.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-domaincase.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-empty-localpart.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-empty.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-ipv4.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-localpartcase.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-multiple.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-no-at.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-quoted.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-no-at.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-two-ats.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-subdomain.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-subdomaincase.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name-two-ats.pem", - "pki/testdata/name_constraints_unittest/san-rfc822name.pem", - "pki/testdata/name_constraints_unittest/san-uri.pem", - "pki/testdata/name_constraints_unittest/san-x400address.pem", - "pki/testdata/name_constraints_unittest/uri-excluded.pem", - "pki/testdata/name_constraints_unittest/uri-permitted.pem", - "pki/testdata/name_constraints_unittest/x400address-excluded.pem", - "pki/testdata/name_constraints_unittest/x400address-permitted.pem", - "pki/testdata/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt", - "pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt", - "pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt", - "pki/testdata/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt", - "pki/testdata/nist-pkits/certs/AnyPolicyTest14EE.crt", - "pki/testdata/nist-pkits/certs/BadCRLIssuerNameCACert.crt", - "pki/testdata/nist-pkits/certs/BadCRLSignatureCACert.crt", - "pki/testdata/nist-pkits/certs/BadSignedCACert.crt", - "pki/testdata/nist-pkits/certs/BadnotAfterDateCACert.crt", - "pki/testdata/nist-pkits/certs/BadnotBeforeDateCACert.crt", - "pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt", - "pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt", - "pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt", - "pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt", - "pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt", - "pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt", - "pki/testdata/nist-pkits/certs/CPSPointerQualifierTest20EE.crt", - "pki/testdata/nist-pkits/certs/DSACACert.crt", - "pki/testdata/nist-pkits/certs/DSAParametersInheritedCACert.crt", - "pki/testdata/nist-pkits/certs/DifferentPoliciesTest12EE.crt", - "pki/testdata/nist-pkits/certs/DifferentPoliciesTest3EE.crt", - "pki/testdata/nist-pkits/certs/DifferentPoliciesTest4EE.crt", - "pki/testdata/nist-pkits/certs/DifferentPoliciesTest5EE.crt", - "pki/testdata/nist-pkits/certs/DifferentPoliciesTest7EE.crt", - "pki/testdata/nist-pkits/certs/DifferentPoliciesTest8EE.crt", - "pki/testdata/nist-pkits/certs/DifferentPoliciesTest9EE.crt", - "pki/testdata/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt", - "pki/testdata/nist-pkits/certs/GoodCACert.crt", - "pki/testdata/nist-pkits/certs/GoodsubCACert.crt", - "pki/testdata/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt", - "pki/testdata/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt", - "pki/testdata/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt", - "pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt", - "pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt", - "pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt", - "pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidCASignatureTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt", - "pki/testdata/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt", - "pki/testdata/nist-pkits/certs/InvalidDSASignatureTest6EE.crt", - "pki/testdata/nist-pkits/certs/InvalidEESignatureTest3EE.crt", - "pki/testdata/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt", - "pki/testdata/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt", - "pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt", - "pki/testdata/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt", - "pki/testdata/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt", - "pki/testdata/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt", - "pki/testdata/nist-pkits/certs/InvalidMissingCRLTest1EE.crt", - "pki/testdata/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt", - "pki/testdata/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidNameChainingTest1EE.crt", - "pki/testdata/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt", - "pki/testdata/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt", - "pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt", - "pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt", - "pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt", - "pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt", - "pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt", - "pki/testdata/nist-pkits/certs/InvalidRevokedCATest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidRevokedEETest3EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt", - "pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt", - "pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt", - "pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt", - "pki/testdata/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt", - "pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt", - "pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt", - "pki/testdata/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidWrongCRLTest6EE.crt", - "pki/testdata/nist-pkits/certs/InvalidcAFalseTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidcAFalseTest3EE.crt", - "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt", - "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt", - "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt", - "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt", - "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest3EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest6EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest8EE.crt", - "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest9EE.crt", - "pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt", - "pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt", - "pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt", - "pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt", - "pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt", - "pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt", - "pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt", - "pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt", - "pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt", - "pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt", - "pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt", - "pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt", - "pki/testdata/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt", - "pki/testdata/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt", - "pki/testdata/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt", - "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt", - "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt", - "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt", - "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt", - "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt", - "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt", - "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt", - "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt", - "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt", - "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt", - "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt", - "pki/testdata/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt", - "pki/testdata/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt", - "pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt", - "pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt", - "pki/testdata/nist-pkits/certs/LongSerialNumberCACert.crt", - "pki/testdata/nist-pkits/certs/Mapping1to2CACert.crt", - "pki/testdata/nist-pkits/certs/MappingFromanyPolicyCACert.crt", - "pki/testdata/nist-pkits/certs/MappingToanyPolicyCACert.crt", - "pki/testdata/nist-pkits/certs/MissingbasicConstraintsCACert.crt", - "pki/testdata/nist-pkits/certs/NameOrderingCACert.crt", - "pki/testdata/nist-pkits/certs/NegativeSerialNumberCACert.crt", - "pki/testdata/nist-pkits/certs/NoCRLCACert.crt", - "pki/testdata/nist-pkits/certs/NoPoliciesCACert.crt", - "pki/testdata/nist-pkits/certs/NoissuingDistributionPointCACert.crt", - "pki/testdata/nist-pkits/certs/OldCRLnextUpdateCACert.crt", - "pki/testdata/nist-pkits/certs/OverlappingPoliciesTest6EE.crt", - "pki/testdata/nist-pkits/certs/P12Mapping1to3CACert.crt", - "pki/testdata/nist-pkits/certs/P12Mapping1to3subCACert.crt", - "pki/testdata/nist-pkits/certs/P12Mapping1to3subsubCACert.crt", - "pki/testdata/nist-pkits/certs/P1Mapping1to234CACert.crt", - "pki/testdata/nist-pkits/certs/P1Mapping1to234subCACert.crt", - "pki/testdata/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt", - "pki/testdata/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP1234CACert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP123CACert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP123subCAP12Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP12CACert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP12subCAP1Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP2subCA2Cert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP2subCACert.crt", - "pki/testdata/nist-pkits/certs/PoliciesP3CACert.crt", - "pki/testdata/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt", - "pki/testdata/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt", - "pki/testdata/nist-pkits/certs/RevokedsubCACert.crt", - "pki/testdata/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt", - "pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt", - "pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt", - "pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt", - "pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt", - "pki/testdata/nist-pkits/certs/TrustAnchorRootCertificate.crt", - "pki/testdata/nist-pkits/certs/TwoCRLsCACert.crt", - "pki/testdata/nist-pkits/certs/UIDCACert.crt", - "pki/testdata/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt", - "pki/testdata/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt", - "pki/testdata/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt", - "pki/testdata/nist-pkits/certs/UnknownCRLExtensionCACert.crt", - "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest15EE.crt", - "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest16EE.crt", - "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest17EE.crt", - "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest18EE.crt", - "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest19EE.crt", - "pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt", - "pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt", - "pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt", - "pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt", - "pki/testdata/nist-pkits/certs/ValidCertificatePathTest1EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt", - "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt", - "pki/testdata/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt", - "pki/testdata/nist-pkits/certs/ValidDSASignaturesTest4EE.crt", - "pki/testdata/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt", - "pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt", - "pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt", - "pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt", - "pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt", - "pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt", - "pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt", - "pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt", - "pki/testdata/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt", - "pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt", - "pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt", - "pki/testdata/nist-pkits/certs/ValidNameUIDsTest6EE.crt", - "pki/testdata/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt", - "pki/testdata/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest11EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest12EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest13EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest14EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest1EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest3EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest5EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest6EE.crt", - "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest9EE.crt", - "pki/testdata/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt", - "pki/testdata/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt", - "pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt", - "pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt", - "pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt", - "pki/testdata/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt", - "pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt", - "pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt", - "pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt", - "pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt", - "pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt", - "pki/testdata/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt", - "pki/testdata/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt", - "pki/testdata/nist-pkits/certs/ValidTwoCRLsTest7EE.crt", - "pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt", - "pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt", - "pki/testdata/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt", - "pki/testdata/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt", - "pki/testdata/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt", - "pki/testdata/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt", - "pki/testdata/nist-pkits/certs/ValidcRLIssuerTest28EE.crt", - "pki/testdata/nist-pkits/certs/ValidcRLIssuerTest29EE.crt", - "pki/testdata/nist-pkits/certs/ValidcRLIssuerTest30EE.crt", - "pki/testdata/nist-pkits/certs/ValidcRLIssuerTest33EE.crt", - "pki/testdata/nist-pkits/certs/ValiddeltaCRLTest2EE.crt", - "pki/testdata/nist-pkits/certs/ValiddeltaCRLTest5EE.crt", - "pki/testdata/nist-pkits/certs/ValiddeltaCRLTest7EE.crt", - "pki/testdata/nist-pkits/certs/ValiddeltaCRLTest8EE.crt", - "pki/testdata/nist-pkits/certs/ValiddistributionPointTest1EE.crt", - "pki/testdata/nist-pkits/certs/ValiddistributionPointTest4EE.crt", - "pki/testdata/nist-pkits/certs/ValiddistributionPointTest5EE.crt", - "pki/testdata/nist-pkits/certs/ValiddistributionPointTest7EE.crt", - "pki/testdata/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt", - "pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt", - "pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt", - "pki/testdata/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt", - "pki/testdata/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt", - "pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt", - "pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt", - "pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt", - "pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt", - "pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt", - "pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt", - "pki/testdata/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt", - "pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt", - "pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt", - "pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt", - "pki/testdata/nist-pkits/certs/WrongCRLCACert.crt", - "pki/testdata/nist-pkits/certs/anyPolicyCACert.crt", - "pki/testdata/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt", - "pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt", - "pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt", - "pki/testdata/nist-pkits/certs/deltaCRLCA1Cert.crt", - "pki/testdata/nist-pkits/certs/deltaCRLCA2Cert.crt", - "pki/testdata/nist-pkits/certs/deltaCRLCA3Cert.crt", - "pki/testdata/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt", - "pki/testdata/nist-pkits/certs/distributionPoint1CACert.crt", - "pki/testdata/nist-pkits/certs/distributionPoint2CACert.crt", - "pki/testdata/nist-pkits/certs/indirectCRLCA1Cert.crt", - "pki/testdata/nist-pkits/certs/indirectCRLCA2Cert.crt", - "pki/testdata/nist-pkits/certs/indirectCRLCA3Cert.crt", - "pki/testdata/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt", - "pki/testdata/nist-pkits/certs/indirectCRLCA4Cert.crt", - "pki/testdata/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt", - "pki/testdata/nist-pkits/certs/indirectCRLCA5Cert.crt", - "pki/testdata/nist-pkits/certs/indirectCRLCA6Cert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy0CACert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1CACert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy5CACert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping0CACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping5CACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt", - "pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt", - "pki/testdata/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt", - "pki/testdata/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt", - "pki/testdata/nist-pkits/certs/keyUsageNotCriticalCACert.crt", - "pki/testdata/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt", - "pki/testdata/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN1CACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN2CACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN3CACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN4CACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDN5CACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDNS1CACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsDNS2CACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsURI1CACert.crt", - "pki/testdata/nist-pkits/certs/nameConstraintsURI2CACert.crt", - "pki/testdata/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt", - "pki/testdata/nist-pkits/certs/onlyContainsCACertsCACert.crt", - "pki/testdata/nist-pkits/certs/onlyContainsUserCertsCACert.crt", - "pki/testdata/nist-pkits/certs/onlySomeReasonsCA1Cert.crt", - "pki/testdata/nist-pkits/certs/onlySomeReasonsCA2Cert.crt", - "pki/testdata/nist-pkits/certs/onlySomeReasonsCA3Cert.crt", - "pki/testdata/nist-pkits/certs/onlySomeReasonsCA4Cert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint0CACert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint0subCACert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint1CACert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint1subCACert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6CACert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt", - "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt", - "pki/testdata/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy0CACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy0subCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy10CACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy10subCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy2CACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy2subCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy4CACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy4subCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy5CACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy5subCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy7CACert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt", - "pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt", - "pki/testdata/nist-pkits/crls/BadCRLIssuerNameCACRL.crl", - "pki/testdata/nist-pkits/crls/BadCRLSignatureCACRL.crl", - "pki/testdata/nist-pkits/crls/BadSignedCACRL.crl", - "pki/testdata/nist-pkits/crls/BadnotAfterDateCACRL.crl", - "pki/testdata/nist-pkits/crls/BadnotBeforeDateCACRL.crl", - "pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl", - "pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl", - "pki/testdata/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crl", - "pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crl", - "pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl", - "pki/testdata/nist-pkits/crls/DSACACRL.crl", - "pki/testdata/nist-pkits/crls/DSAParametersInheritedCACRL.crl", - "pki/testdata/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crl", - "pki/testdata/nist-pkits/crls/GoodCACRL.crl", - "pki/testdata/nist-pkits/crls/GoodsubCACRL.crl", - "pki/testdata/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl", - "pki/testdata/nist-pkits/crls/LongSerialNumberCACRL.crl", - "pki/testdata/nist-pkits/crls/Mapping1to2CACRL.crl", - "pki/testdata/nist-pkits/crls/MappingFromanyPolicyCACRL.crl", - "pki/testdata/nist-pkits/crls/MappingToanyPolicyCACRL.crl", - "pki/testdata/nist-pkits/crls/MissingbasicConstraintsCACRL.crl", - "pki/testdata/nist-pkits/crls/NameOrderCACRL.crl", - "pki/testdata/nist-pkits/crls/NegativeSerialNumberCACRL.crl", - "pki/testdata/nist-pkits/crls/NoPoliciesCACRL.crl", - "pki/testdata/nist-pkits/crls/NoissuingDistributionPointCACRL.crl", - "pki/testdata/nist-pkits/crls/OldCRLnextUpdateCACRL.crl", - "pki/testdata/nist-pkits/crls/P12Mapping1to3CACRL.crl", - "pki/testdata/nist-pkits/crls/P12Mapping1to3subCACRL.crl", - "pki/testdata/nist-pkits/crls/P12Mapping1to3subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/P1Mapping1to234CACRL.crl", - "pki/testdata/nist-pkits/crls/P1Mapping1to234subCACRL.crl", - "pki/testdata/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crl", - "pki/testdata/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP1234CACRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP1234subCAP123CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP123CACRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP123subCAP12CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP12CACRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP12subCAP1CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP2subCA2CRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP2subCACRL.crl", - "pki/testdata/nist-pkits/crls/PoliciesP3CACRL.crl", - "pki/testdata/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crl", - "pki/testdata/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crl", - "pki/testdata/nist-pkits/crls/RevokedsubCACRL.crl", - "pki/testdata/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl", - "pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crl", - "pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crl", - "pki/testdata/nist-pkits/crls/TrustAnchorRootCRL.crl", - "pki/testdata/nist-pkits/crls/TwoCRLsCABadCRL.crl", - "pki/testdata/nist-pkits/crls/TwoCRLsCAGoodCRL.crl", - "pki/testdata/nist-pkits/crls/UIDCACRL.crl", - "pki/testdata/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crl", - "pki/testdata/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crl", - "pki/testdata/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crl", - "pki/testdata/nist-pkits/crls/UnknownCRLExtensionCACRL.crl", - "pki/testdata/nist-pkits/crls/WrongCRLCACRL.crl", - "pki/testdata/nist-pkits/crls/anyPolicyCACRL.crl", - "pki/testdata/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crl", - "pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crl", - "pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crl", - "pki/testdata/nist-pkits/crls/deltaCRLCA1CRL.crl", - "pki/testdata/nist-pkits/crls/deltaCRLCA1deltaCRL.crl", - "pki/testdata/nist-pkits/crls/deltaCRLCA2CRL.crl", - "pki/testdata/nist-pkits/crls/deltaCRLCA2deltaCRL.crl", - "pki/testdata/nist-pkits/crls/deltaCRLCA3CRL.crl", - "pki/testdata/nist-pkits/crls/deltaCRLCA3deltaCRL.crl", - "pki/testdata/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crl", - "pki/testdata/nist-pkits/crls/distributionPoint1CACRL.crl", - "pki/testdata/nist-pkits/crls/distributionPoint2CACRL.crl", - "pki/testdata/nist-pkits/crls/indirectCRLCA1CRL.crl", - "pki/testdata/nist-pkits/crls/indirectCRLCA3CRL.crl", - "pki/testdata/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crl", - "pki/testdata/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crl", - "pki/testdata/nist-pkits/crls/indirectCRLCA5CRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy0CACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1CACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy5CACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping0CACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping5CACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crl", - "pki/testdata/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crl", - "pki/testdata/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl", - "pki/testdata/nist-pkits/crls/keyUsageNotCriticalCACRL.crl", - "pki/testdata/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl", - "pki/testdata/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN1CACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN2CACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN3CACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN4CACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDN5CACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDNS1CACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsDNS2CACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsURI1CACRL.crl", - "pki/testdata/nist-pkits/crls/nameConstraintsURI2CACRL.crl", - "pki/testdata/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crl", - "pki/testdata/nist-pkits/crls/onlyContainsCACertsCACRL.crl", - "pki/testdata/nist-pkits/crls/onlyContainsUserCertsCACRL.crl", - "pki/testdata/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crl", - "pki/testdata/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crl", - "pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL1.crl", - "pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL2.crl", - "pki/testdata/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crl", - "pki/testdata/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crl", - "pki/testdata/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crl", - "pki/testdata/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint0CACRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint0subCA2CRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint0subCACRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint1CACRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint1subCACRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6CACRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6subCA0CRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6subCA1CRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6subCA4CRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crl", - "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crl", - "pki/testdata/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy0CACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy0subCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy10CACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy10subCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy2CACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy2subCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy4CACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy4subCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy5CACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy5subCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy7CACRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl", - "pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl", - "pki/testdata/ocsp_unittest/bad_ocsp_type.pem", - "pki/testdata/ocsp_unittest/bad_signature.pem", - "pki/testdata/ocsp_unittest/bad_status.pem", - "pki/testdata/ocsp_unittest/good_response.pem", - "pki/testdata/ocsp_unittest/good_response_next_update.pem", - "pki/testdata/ocsp_unittest/good_response_sha256.pem", - "pki/testdata/ocsp_unittest/has_critical_ct_extension.pem", - "pki/testdata/ocsp_unittest/has_critical_response_extension.pem", - "pki/testdata/ocsp_unittest/has_critical_single_extension.pem", - "pki/testdata/ocsp_unittest/has_extension.pem", - "pki/testdata/ocsp_unittest/has_single_extension.pem", - "pki/testdata/ocsp_unittest/has_version.pem", - "pki/testdata/ocsp_unittest/malformed_request.pem", - "pki/testdata/ocsp_unittest/missing_response.pem", - "pki/testdata/ocsp_unittest/multiple_response.pem", - "pki/testdata/ocsp_unittest/no_response.pem", - "pki/testdata/ocsp_unittest/ocsp_extra_certs.pem", - "pki/testdata/ocsp_unittest/ocsp_sign_bad_indirect.pem", - "pki/testdata/ocsp_unittest/ocsp_sign_direct.pem", - "pki/testdata/ocsp_unittest/ocsp_sign_indirect.pem", - "pki/testdata/ocsp_unittest/ocsp_sign_indirect_missing.pem", - "pki/testdata/ocsp_unittest/other_response.pem", - "pki/testdata/ocsp_unittest/responder_id.pem", - "pki/testdata/ocsp_unittest/responder_name.pem", - "pki/testdata/ocsp_unittest/revoke_response.pem", - "pki/testdata/ocsp_unittest/revoke_response_reason.pem", - "pki/testdata/ocsp_unittest/unknown_response.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/empty_sequence.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_extension_sequence.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_issuer_and_serial.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_contents.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_issuer.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_key_identifier.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_serial.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_and_serial.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_only.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier_and_issuer_and_serial.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/serial_only.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier/url_issuer_and_serial.pem", - "pki/testdata/parse_certificate_unittest/authority_key_identifier_not_sequence.pem", - "pki/testdata/parse_certificate_unittest/bad_key_usage.pem", - "pki/testdata/parse_certificate_unittest/bad_policy_qualifiers.pem", - "pki/testdata/parse_certificate_unittest/bad_signature_algorithm_oid.pem", - "pki/testdata/parse_certificate_unittest/bad_validity.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_ca_false.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_ca_no_path.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_ca_path_9.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_negative_path.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_not_ca.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_path_too_large.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_255.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_256.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem", - "pki/testdata/parse_certificate_unittest/basic_constraints_unconsumed_data.pem", - "pki/testdata/parse_certificate_unittest/cert_algorithm_not_sequence.pem", - "pki/testdata/parse_certificate_unittest/cert_data_after_signature.pem", - "pki/testdata/parse_certificate_unittest/cert_empty_sequence.pem", - "pki/testdata/parse_certificate_unittest/cert_missing_signature.pem", - "pki/testdata/parse_certificate_unittest/cert_not_sequence.pem", - "pki/testdata/parse_certificate_unittest/cert_signature_not_bit_string.pem", - "pki/testdata/parse_certificate_unittest/cert_skeleton.pem", - "pki/testdata/parse_certificate_unittest/cert_version3.pem", - "pki/testdata/parse_certificate_unittest/crldp_1uri_noissuer.pem", - "pki/testdata/parse_certificate_unittest/crldp_3uri_noissuer.pem", - "pki/testdata/parse_certificate_unittest/crldp_full_name_as_dirname.pem", - "pki/testdata/parse_certificate_unittest/crldp_issuer_as_dirname.pem", - "pki/testdata/parse_certificate_unittest/extended_key_usage.pem", - "pki/testdata/parse_certificate_unittest/extension_critical.pem", - "pki/testdata/parse_certificate_unittest/extension_critical_0.pem", - "pki/testdata/parse_certificate_unittest/extension_critical_3.pem", - "pki/testdata/parse_certificate_unittest/extension_not_critical.pem", - "pki/testdata/parse_certificate_unittest/extensions_data_after_sequence.pem", - "pki/testdata/parse_certificate_unittest/extensions_duplicate_key_usage.pem", - "pki/testdata/parse_certificate_unittest/extensions_empty_sequence.pem", - "pki/testdata/parse_certificate_unittest/extensions_not_sequence.pem", - "pki/testdata/parse_certificate_unittest/extensions_real.pem", - "pki/testdata/parse_certificate_unittest/failed_signature_algorithm.pem", - "pki/testdata/parse_certificate_unittest/inhibit_any_policy.pem", - "pki/testdata/parse_certificate_unittest/issuer_bad_printable_string.pem", - "pki/testdata/parse_certificate_unittest/key_usage.pem", - "pki/testdata/parse_certificate_unittest/name_constraints_bad_ip.pem", - "pki/testdata/parse_certificate_unittest/policies.pem", - "pki/testdata/parse_certificate_unittest/policy_constraints_empty.pem", - "pki/testdata/parse_certificate_unittest/policy_constraints_inhibit.pem", - "pki/testdata/parse_certificate_unittest/policy_constraints_inhibit_require.pem", - "pki/testdata/parse_certificate_unittest/policy_constraints_require.pem", - "pki/testdata/parse_certificate_unittest/policy_qualifiers_empty_sequence.pem", - "pki/testdata/parse_certificate_unittest/serial_37_bytes.pem", - "pki/testdata/parse_certificate_unittest/serial_negative.pem", - "pki/testdata/parse_certificate_unittest/serial_not_minimal.pem", - "pki/testdata/parse_certificate_unittest/serial_not_number.pem", - "pki/testdata/parse_certificate_unittest/serial_zero.pem", - "pki/testdata/parse_certificate_unittest/serial_zero_padded.pem", - "pki/testdata/parse_certificate_unittest/serial_zero_padded_21_bytes.pem", - "pki/testdata/parse_certificate_unittest/signature_algorithm_null.pem", - "pki/testdata/parse_certificate_unittest/subject_alt_name.pem", - "pki/testdata/parse_certificate_unittest/subject_blank_subjectaltname_not_critical.pem", - "pki/testdata/parse_certificate_unittest/subject_key_identifier_not_octet_string.pem", - "pki/testdata/parse_certificate_unittest/subject_not_ascii.pem", - "pki/testdata/parse_certificate_unittest/subject_not_printable_string.pem", - "pki/testdata/parse_certificate_unittest/subject_printable_string_containing_utf8_client_cert.pem", - "pki/testdata/parse_certificate_unittest/subject_t61string.pem", - "pki/testdata/parse_certificate_unittest/subject_t61string_1-32.pem", - "pki/testdata/parse_certificate_unittest/subject_t61string_126-160.pem", - "pki/testdata/parse_certificate_unittest/subject_t61string_actual.pem", - "pki/testdata/parse_certificate_unittest/subjectaltname_bad_ip.pem", - "pki/testdata/parse_certificate_unittest/subjectaltname_dns_not_ascii.pem", - "pki/testdata/parse_certificate_unittest/subjectaltname_general_names_empty_sequence.pem", - "pki/testdata/parse_certificate_unittest/subjectaltname_trailing_data.pem", - "pki/testdata/parse_certificate_unittest/tbs_explicit_v1.pem", - "pki/testdata/parse_certificate_unittest/tbs_v1.pem", - "pki/testdata/parse_certificate_unittest/tbs_v1_extensions.pem", - "pki/testdata/parse_certificate_unittest/tbs_v2_extensions.pem", - "pki/testdata/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem", - "pki/testdata/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem", - "pki/testdata/parse_certificate_unittest/tbs_v2_no_optionals.pem", - "pki/testdata/parse_certificate_unittest/tbs_v3_all_optionals.pem", - "pki/testdata/parse_certificate_unittest/tbs_v3_data_after_extensions.pem", - "pki/testdata/parse_certificate_unittest/tbs_v3_extensions.pem", - "pki/testdata/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem", - "pki/testdata/parse_certificate_unittest/tbs_v3_no_optionals.pem", - "pki/testdata/parse_certificate_unittest/tbs_v3_real.pem", - "pki/testdata/parse_certificate_unittest/tbs_v4.pem", - "pki/testdata/parse_certificate_unittest/tbs_validity_both_generalized_time.pem", - "pki/testdata/parse_certificate_unittest/tbs_validity_both_utc_time.pem", - "pki/testdata/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem", - "pki/testdata/parse_certificate_unittest/tbs_validity_relaxed.pem", - "pki/testdata/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem", - "pki/testdata/parse_certificate_unittest/v1_explicit_version.pem", - "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_match_name_only.pem", - "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_matching.pem", - "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_mismatch.pem", - "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root.pem", - "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root2.pem", - "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/target.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_a.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_b.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_c.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_a.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_b.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_c.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_a.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_b.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_c.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/root.pem", - "pki/testdata/path_builder_unittest/key_id_prioritization/target.pem", - "pki/testdata/path_builder_unittest/multi-root-A-by-B.pem", - "pki/testdata/path_builder_unittest/multi-root-B-by-C.pem", - "pki/testdata/path_builder_unittest/multi-root-B-by-F.pem", - "pki/testdata/path_builder_unittest/multi-root-C-by-D.pem", - "pki/testdata/path_builder_unittest/multi-root-C-by-E.pem", - "pki/testdata/path_builder_unittest/multi-root-D-by-D.pem", - "pki/testdata/path_builder_unittest/multi-root-E-by-E.pem", - "pki/testdata/path_builder_unittest/multi-root-F-by-E.pem", - "pki/testdata/path_builder_unittest/precertificate/precertificate.pem", - "pki/testdata/path_builder_unittest/precertificate/root.pem", - "pki/testdata/path_builder_unittest/self_issued_prioritization/root1.pem", - "pki/testdata/path_builder_unittest/self_issued_prioritization/root1_cross.pem", - "pki/testdata/path_builder_unittest/self_issued_prioritization/root2.pem", - "pki/testdata/path_builder_unittest/self_issued_prioritization/target.pem", - "pki/testdata/path_builder_unittest/validity_date_prioritization/int_ac.pem", - "pki/testdata/path_builder_unittest/validity_date_prioritization/int_ad.pem", - "pki/testdata/path_builder_unittest/validity_date_prioritization/int_bc.pem", - "pki/testdata/path_builder_unittest/validity_date_prioritization/int_bd.pem", - "pki/testdata/path_builder_unittest/validity_date_prioritization/root.pem", - "pki/testdata/path_builder_unittest/validity_date_prioritization/target.pem", - "pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/main.test", - "pki/testdata/verify_certificate_chain_unittest/expired-intermediate/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-after.test", - "pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-before.test", - "pki/testdata/verify_certificate_chain_unittest/expired-root/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration-and-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration.test", - "pki/testdata/verify_certificate_chain_unittest/expired-root/not-after.test", - "pki/testdata/verify_certificate_chain_unittest/expired-root/not-before-ta-with-expiration.test", - "pki/testdata/verify_certificate_chain_unittest/expired-root/not-before.test", - "pki/testdata/verify_certificate_chain_unittest/expired-target/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/expired-target/not-after.test", - "pki/testdata/verify_certificate_chain_unittest/expired-target/not-before.test", - "pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/any.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-any.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/main.test", - "pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/main.test", - "pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.pem", - "pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.test", - "pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.pem", - "pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.test", - "pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.pem", - "pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.test", - "pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.pem", - "pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.test", - "pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.pem", - "pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.test", - "pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.pem", - "pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.test", - "pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.pem", - "pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.test", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.pem", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.test", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.pem", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.test", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.pem", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.test", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.pem", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.test", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.pem", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.test", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.pem", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.test", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.pem", - "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.test", - "pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/main.test", - "pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.4.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.5.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.6.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.10.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.13.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.4.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.5.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.6.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.7.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.8.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.1.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.10.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.11.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.5.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.6.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.8.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.9.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.1.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.10.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.4.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.5.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.6.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.8.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.10.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.12.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.13.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.15.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.16.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.17.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.20.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.21.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.22.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.23.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.24.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.25.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.26.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.27.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.28.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.29.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.31.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.33.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.34.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.35.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.36.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.37.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.38.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.7.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.8.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.9.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.16.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.1.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.5.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.6.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.7.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.1.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.1.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.10.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.11.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.12.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.16.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.5.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.6.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.9.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.1.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.1.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.12.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.14.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.2.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.4.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.5.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.6.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.7.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.8.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.9.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.3.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.5.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.7.txt", - "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.8.txt", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policies-ok/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-ok/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-ok/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/main.test", - "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/main.test", - "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/main.test", - "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/main.test", - "pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints-strict.test", - "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration-and-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration.test", - "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth.test", - "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/main.test", - "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints-require-basic-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-require-basic-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test", - "pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root-expired.test", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root.test", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-constraints.test", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-expiration.test", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-and-trust_anchor.test", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-root.test", - "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/unspecified-trust-root.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-any/any.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-any/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/any.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-many/any.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-many/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-none/any.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-none/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test", - "pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf-strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only.pem", - "pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict-leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict.test", - "pki/testdata/verify_certificate_chain_unittest/target-only/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_anchor.test", - "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-and-trust_anchor.test", - "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-not_after.test", - "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-wrong_eku.test", - "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf_require_self_signed.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfissued/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_anchor.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf-and-trust_anchor.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf_require_self_signed.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-and-trust_anchor.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-not_after.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-wrong_eku.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf_require_self_signed.test", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.pem", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.test", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.pem", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.test", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.pem", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.test", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.pem", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.test", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.pem", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.test", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.pem", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.test", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.pem", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.test", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.pem", - "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.test", - "pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only-trusted_leaf.test", - "pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only.pem", - "pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/main.test", - "pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/main.test", - "pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/main.test", - "pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/main.test", - "pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/main.test", - "pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/chain.pem", - "pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/main.test", - "pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/ta-with-constraints.test", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_1.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_2.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-dupe_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_attr.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_rdn.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_1.pem", - "pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_2.pem", - "pki/testdata/verify_name_match_unittest/names/custom-custom-normalized.pem", - "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-badAttributeType.pem", - "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-empty.pem", - "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-extradata.pem", - "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-onlyOneElement.pem", - "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-setNotSequence.pem", - "pki/testdata/verify_name_match_unittest/names/invalid-Name-setInsteadOfSequence.pem", - "pki/testdata/verify_name_match_unittest/names/invalid-RDN-empty.pem", - "pki/testdata/verify_name_match_unittest/names/invalid-RDN-sequenceInsteadOfSet.pem", - "pki/testdata/verify_name_match_unittest/names/unicode-mixed-normalized.pem", - "pki/testdata/verify_name_match_unittest/names/unicode-mixed-unnormalized.pem", - "pki/testdata/verify_name_match_unittest/names/unicode_bmp-BMPSTRING-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/unicode_bmp-UNIVERSALSTRING-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/unicode_bmp-UTF8-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UNIVERSALSTRING-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UTF8-unmangled.pem", - "pki/testdata/verify_name_match_unittest/names/valid-Name-empty.pem", - "pki/testdata/verify_name_match_unittest/names/valid-minimal.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem", - "pki/testdata/verify_signed_data_unittest/ecdsa-using-rsa-key.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-using-pss-key-with-params.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-wrong-salt.pem", - "pki/testdata/verify_signed_data_unittest/rsa-pss-sha256.pem", - "pki/testdata/verify_signed_data_unittest/rsa-using-ec-key.pem", - "pki/testdata/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem", - "pki/testdata/verify_unittest/google-leaf.der", - "pki/testdata/verify_unittest/self-issued.pem", + "pki/testdata/cert_issuer_source_static_unittest/c1.pem", + "pki/testdata/cert_issuer_source_static_unittest/c2.pem", + "pki/testdata/cert_issuer_source_static_unittest/d.pem", + "pki/testdata/cert_issuer_source_static_unittest/e1.pem", + "pki/testdata/cert_issuer_source_static_unittest/e2.pem", + "pki/testdata/cert_issuer_source_static_unittest/i1_1.pem", + "pki/testdata/cert_issuer_source_static_unittest/i1_2.pem", + "pki/testdata/cert_issuer_source_static_unittest/i2.pem", + "pki/testdata/cert_issuer_source_static_unittest/i3_1.pem", + "pki/testdata/cert_issuer_source_static_unittest/i3_2.pem", + "pki/testdata/cert_issuer_source_static_unittest/root.pem", + "pki/testdata/certificate_policies_unittest/anypolicy.pem", + "pki/testdata/certificate_policies_unittest/anypolicy_with_qualifier.pem", + "pki/testdata/certificate_policies_unittest/invalid-anypolicy_with_custom_qualifier.pem", + "pki/testdata/certificate_policies_unittest/invalid-empty.pem", + "pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_dupe.pem", + "pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyinformation_unconsumed_data.pem", + "pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_policyqualifierinfo_unconsumed_data.pem", + "pki/testdata/certificate_policies_unittest/invalid-policy_1_2_3_with_empty_qualifiers_sequence.pem", + "pki/testdata/certificate_policies_unittest/invalid-policy_identifier_not_oid.pem", + "pki/testdata/certificate_policies_unittest/policy_1_2_3.pem", + "pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4.pem", + "pki/testdata/certificate_policies_unittest/policy_1_2_3_and_1_2_4_with_qualifiers.pem", + "pki/testdata/certificate_policies_unittest/policy_1_2_3_with_custom_qualifier.pem", + "pki/testdata/certificate_policies_unittest/policy_1_2_3_with_qualifier.pem", + "pki/testdata/crl_unittest/bad_crldp_has_crlissuer.pem", + "pki/testdata/crl_unittest/bad_fake_critical_crlentryextension.pem", + "pki/testdata/crl_unittest/bad_fake_critical_extension.pem", + "pki/testdata/crl_unittest/bad_idp_contains_wrong_uri.pem", + "pki/testdata/crl_unittest/bad_idp_indirectcrl.pem", + "pki/testdata/crl_unittest/bad_idp_onlycontainscacerts.pem", + "pki/testdata/crl_unittest/bad_idp_onlycontainscacerts_no_basic_constraints.pem", + "pki/testdata/crl_unittest/bad_idp_onlycontainsusercerts.pem", + "pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainscacerts.pem", + "pki/testdata/crl_unittest/bad_idp_uri_and_onlycontainsusercerts.pem", + "pki/testdata/crl_unittest/bad_key_rollover_signature.pem", + "pki/testdata/crl_unittest/bad_nextupdate_too_old.pem", + "pki/testdata/crl_unittest/bad_signature.pem", + "pki/testdata/crl_unittest/bad_thisupdate_in_future.pem", + "pki/testdata/crl_unittest/bad_thisupdate_too_old.pem", + "pki/testdata/crl_unittest/bad_wrong_issuer.pem", + "pki/testdata/crl_unittest/good.pem", + "pki/testdata/crl_unittest/good_fake_extension.pem", + "pki/testdata/crl_unittest/good_fake_extension_no_nextupdate.pem", + "pki/testdata/crl_unittest/good_generalizedtime.pem", + "pki/testdata/crl_unittest/good_idp_contains_uri.pem", + "pki/testdata/crl_unittest/good_idp_onlycontainscacerts.pem", + "pki/testdata/crl_unittest/good_idp_onlycontainsusercerts.pem", + "pki/testdata/crl_unittest/good_idp_onlycontainsusercerts_no_basic_constraints.pem", + "pki/testdata/crl_unittest/good_idp_uri_and_onlycontainscacerts.pem", + "pki/testdata/crl_unittest/good_idp_uri_and_onlycontainsusercerts.pem", + "pki/testdata/crl_unittest/good_issuer_name_normalization.pem", + "pki/testdata/crl_unittest/good_issuer_no_keyusage.pem", + "pki/testdata/crl_unittest/good_key_rollover.pem", + "pki/testdata/crl_unittest/good_no_crldp.pem", + "pki/testdata/crl_unittest/good_no_nextupdate.pem", + "pki/testdata/crl_unittest/good_no_version.pem", + "pki/testdata/crl_unittest/invalid_garbage_after_crlentryextensions.pem", + "pki/testdata/crl_unittest/invalid_garbage_after_extensions.pem", + "pki/testdata/crl_unittest/invalid_garbage_after_nextupdate.pem", + "pki/testdata/crl_unittest/invalid_garbage_after_revocationdate.pem", + "pki/testdata/crl_unittest/invalid_garbage_after_revokedcerts.pem", + "pki/testdata/crl_unittest/invalid_garbage_after_signaturevalue.pem", + "pki/testdata/crl_unittest/invalid_garbage_after_thisupdate.pem", + "pki/testdata/crl_unittest/invalid_garbage_crlentry.pem", + "pki/testdata/crl_unittest/invalid_garbage_issuer_name.pem", + "pki/testdata/crl_unittest/invalid_garbage_revocationdate.pem", + "pki/testdata/crl_unittest/invalid_garbage_revoked_serial_number.pem", + "pki/testdata/crl_unittest/invalid_garbage_signaturealgorithm.pem", + "pki/testdata/crl_unittest/invalid_garbage_signaturevalue.pem", + "pki/testdata/crl_unittest/invalid_garbage_tbs_signature_algorithm.pem", + "pki/testdata/crl_unittest/invalid_garbage_tbscertlist.pem", + "pki/testdata/crl_unittest/invalid_garbage_thisupdate.pem", + "pki/testdata/crl_unittest/invalid_garbage_version.pem", + "pki/testdata/crl_unittest/invalid_idp_dpname_choice_extra_data.pem", + "pki/testdata/crl_unittest/invalid_idp_empty_sequence.pem", + "pki/testdata/crl_unittest/invalid_idp_onlycontains_user_and_ca_certs.pem", + "pki/testdata/crl_unittest/invalid_idp_onlycontainsusercerts_v1_leaf.pem", + "pki/testdata/crl_unittest/invalid_issuer_keyusage_no_crlsign.pem", + "pki/testdata/crl_unittest/invalid_key_rollover_issuer_keyusage_no_crlsign.pem", + "pki/testdata/crl_unittest/invalid_mismatched_signature_algorithm.pem", + "pki/testdata/crl_unittest/invalid_revoked_empty_sequence.pem", + "pki/testdata/crl_unittest/invalid_v1_explicit.pem", + "pki/testdata/crl_unittest/invalid_v1_with_crlentryextension.pem", + "pki/testdata/crl_unittest/invalid_v1_with_extension.pem", + "pki/testdata/crl_unittest/invalid_v3.pem", + "pki/testdata/crl_unittest/revoked.pem", + "pki/testdata/crl_unittest/revoked_fake_crlentryextension.pem", + "pki/testdata/crl_unittest/revoked_generalized_revocationdate.pem", + "pki/testdata/crl_unittest/revoked_key_rollover.pem", + "pki/testdata/crl_unittest/revoked_no_nextupdate.pem", + "pki/testdata/name_constraints_unittest/directoryname-excludeall.pem", + "pki/testdata/name_constraints_unittest/directoryname-excluded.pem", + "pki/testdata/name_constraints_unittest/directoryname.pem", + "pki/testdata/name_constraints_unittest/directoryname_and_dnsname.pem", + "pki/testdata/name_constraints_unittest/directoryname_and_dnsname_and_ipaddress.pem", + "pki/testdata/name_constraints_unittest/dnsname-exclude_dot.pem", + "pki/testdata/name_constraints_unittest/dnsname-excludeall.pem", + "pki/testdata/name_constraints_unittest/dnsname-excluded.pem", + "pki/testdata/name_constraints_unittest/dnsname-excluded_with_leading_dot.pem", + "pki/testdata/name_constraints_unittest/dnsname-permitted_two_dot.pem", + "pki/testdata/name_constraints_unittest/dnsname-permitted_with_leading_dot.pem", + "pki/testdata/name_constraints_unittest/dnsname-with_max.pem", + "pki/testdata/name_constraints_unittest/dnsname-with_min_0.pem", + "pki/testdata/name_constraints_unittest/dnsname-with_min_0_and_max.pem", + "pki/testdata/name_constraints_unittest/dnsname-with_min_1.pem", + "pki/testdata/name_constraints_unittest/dnsname-with_min_1_and_max.pem", + "pki/testdata/name_constraints_unittest/dnsname.pem", + "pki/testdata/name_constraints_unittest/dnsname2.pem", + "pki/testdata/name_constraints_unittest/edipartyname-excluded.pem", + "pki/testdata/name_constraints_unittest/edipartyname-permitted.pem", + "pki/testdata/name_constraints_unittest/invalid-empty_excluded_subtree.pem", + "pki/testdata/name_constraints_unittest/invalid-empty_permitted_subtree.pem", + "pki/testdata/name_constraints_unittest/invalid-no_subtrees.pem", + "pki/testdata/name_constraints_unittest/ipaddress-excludeall.pem", + "pki/testdata/name_constraints_unittest/ipaddress-excluded.pem", + "pki/testdata/name_constraints_unittest/ipaddress-invalid_addr.pem", + "pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_1.pem", + "pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_2.pem", + "pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_3.pem", + "pki/testdata/name_constraints_unittest/ipaddress-invalid_mask_not_contiguous_4.pem", + "pki/testdata/name_constraints_unittest/ipaddress-mapped_addrs.pem", + "pki/testdata/name_constraints_unittest/ipaddress-permit_all.pem", + "pki/testdata/name_constraints_unittest/ipaddress-permit_prefix1.pem", + "pki/testdata/name_constraints_unittest/ipaddress-permit_prefix31.pem", + "pki/testdata/name_constraints_unittest/ipaddress-permit_singlehost.pem", + "pki/testdata/name_constraints_unittest/ipaddress.pem", + "pki/testdata/name_constraints_unittest/name-ca.pem", + "pki/testdata/name_constraints_unittest/name-de.pem", + "pki/testdata/name_constraints_unittest/name-empty.pem", + "pki/testdata/name_constraints_unittest/name-jp-tokyo.pem", + "pki/testdata/name_constraints_unittest/name-jp.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-1.1.1.1.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-192.168.1.1.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-email-invalidstring.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-email-localpartcase.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-email-multiple.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-email.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-foo.com.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-ipv6.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona-permitted.example.com.pem", + "pki/testdata/name_constraints_unittest/name-us-arizona.pem", + "pki/testdata/name_constraints_unittest/name-us-california-192.168.1.1.pem", + "pki/testdata/name_constraints_unittest/name-us-california-mountain_view.pem", + "pki/testdata/name_constraints_unittest/name-us-california-permitted.example.com.pem", + "pki/testdata/name_constraints_unittest/name-us-california.pem", + "pki/testdata/name_constraints_unittest/name-us.pem", + "pki/testdata/name_constraints_unittest/othername-excluded.pem", + "pki/testdata/name_constraints_unittest/othername-permitted.pem", + "pki/testdata/name_constraints_unittest/registeredid-excluded.pem", + "pki/testdata/name_constraints_unittest/registeredid-permitted.pem", + "pki/testdata/name_constraints_unittest/rfc822name-excluded-empty.pem", + "pki/testdata/name_constraints_unittest/rfc822name-excluded-hostname.pem", + "pki/testdata/name_constraints_unittest/rfc822name-excluded-hostnamewithat.pem", + "pki/testdata/name_constraints_unittest/rfc822name-excluded-ipv4.pem", + "pki/testdata/name_constraints_unittest/rfc822name-excluded-quoted.pem", + "pki/testdata/name_constraints_unittest/rfc822name-excluded-subdomains.pem", + "pki/testdata/name_constraints_unittest/rfc822name-excluded.pem", + "pki/testdata/name_constraints_unittest/rfc822name-permitted-empty.pem", + "pki/testdata/name_constraints_unittest/rfc822name-permitted-hostname.pem", + "pki/testdata/name_constraints_unittest/rfc822name-permitted-hostnamewithat.pem", + "pki/testdata/name_constraints_unittest/rfc822name-permitted-ipv4.pem", + "pki/testdata/name_constraints_unittest/rfc822name-permitted-quoted.pem", + "pki/testdata/name_constraints_unittest/rfc822name-permitted-subdomains.pem", + "pki/testdata/name_constraints_unittest/rfc822name-permitted.pem", + "pki/testdata/name_constraints_unittest/san-directoryname.pem", + "pki/testdata/name_constraints_unittest/san-dnsname.pem", + "pki/testdata/name_constraints_unittest/san-edipartyname.pem", + "pki/testdata/name_constraints_unittest/san-excluded-directoryname.pem", + "pki/testdata/name_constraints_unittest/san-excluded-dnsname.pem", + "pki/testdata/name_constraints_unittest/san-excluded-ipaddress.pem", + "pki/testdata/name_constraints_unittest/san-invalid-empty.pem", + "pki/testdata/name_constraints_unittest/san-invalid-ipaddress.pem", + "pki/testdata/name_constraints_unittest/san-ipaddress4.pem", + "pki/testdata/name_constraints_unittest/san-ipaddress6.pem", + "pki/testdata/name_constraints_unittest/san-othername.pem", + "pki/testdata/name_constraints_unittest/san-permitted.pem", + "pki/testdata/name_constraints_unittest/san-registeredid.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-domaincase.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-empty-localpart.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-empty.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-ipv4.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-localpartcase.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-multiple.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-no-at.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-quoted.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-no-at.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-subdomain-two-ats.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-subdomain.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-subdomaincase.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name-two-ats.pem", + "pki/testdata/name_constraints_unittest/san-rfc822name.pem", + "pki/testdata/name_constraints_unittest/san-uri.pem", + "pki/testdata/name_constraints_unittest/san-x400address.pem", + "pki/testdata/name_constraints_unittest/uri-excluded.pem", + "pki/testdata/name_constraints_unittest/uri-permitted.pem", + "pki/testdata/name_constraints_unittest/x400address-excluded.pem", + "pki/testdata/name_constraints_unittest/x400address-permitted.pem", + "pki/testdata/nist-pkits/certs/AllCertificatesNoPoliciesTest2EE.crt", + "pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest10EE.crt", + "pki/testdata/nist-pkits/certs/AllCertificatesSamePoliciesTest13EE.crt", + "pki/testdata/nist-pkits/certs/AllCertificatesanyPolicyTest11EE.crt", + "pki/testdata/nist-pkits/certs/AnyPolicyTest14EE.crt", + "pki/testdata/nist-pkits/certs/BadCRLIssuerNameCACert.crt", + "pki/testdata/nist-pkits/certs/BadCRLSignatureCACert.crt", + "pki/testdata/nist-pkits/certs/BadSignedCACert.crt", + "pki/testdata/nist-pkits/certs/BadnotAfterDateCACert.crt", + "pki/testdata/nist-pkits/certs/BadnotBeforeDateCACert.crt", + "pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCACert.crt", + "pki/testdata/nist-pkits/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt", + "pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyCACert.crt", + "pki/testdata/nist-pkits/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt", + "pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyCACert.crt", + "pki/testdata/nist-pkits/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt", + "pki/testdata/nist-pkits/certs/CPSPointerQualifierTest20EE.crt", + "pki/testdata/nist-pkits/certs/DSACACert.crt", + "pki/testdata/nist-pkits/certs/DSAParametersInheritedCACert.crt", + "pki/testdata/nist-pkits/certs/DifferentPoliciesTest12EE.crt", + "pki/testdata/nist-pkits/certs/DifferentPoliciesTest3EE.crt", + "pki/testdata/nist-pkits/certs/DifferentPoliciesTest4EE.crt", + "pki/testdata/nist-pkits/certs/DifferentPoliciesTest5EE.crt", + "pki/testdata/nist-pkits/certs/DifferentPoliciesTest7EE.crt", + "pki/testdata/nist-pkits/certs/DifferentPoliciesTest8EE.crt", + "pki/testdata/nist-pkits/certs/DifferentPoliciesTest9EE.crt", + "pki/testdata/nist-pkits/certs/GeneralizedTimeCRLnextUpdateCACert.crt", + "pki/testdata/nist-pkits/certs/GoodCACert.crt", + "pki/testdata/nist-pkits/certs/GoodsubCACert.crt", + "pki/testdata/nist-pkits/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt", + "pki/testdata/nist-pkits/certs/InvalidBadCRLIssuerNameTest5EE.crt", + "pki/testdata/nist-pkits/certs/InvalidBadCRLSignatureTest4EE.crt", + "pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt", + "pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt", + "pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt", + "pki/testdata/nist-pkits/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidCASignatureTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidCAnotAfterDateTest5EE.crt", + "pki/testdata/nist-pkits/certs/InvalidCAnotBeforeDateTest1EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest31EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest33EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNSnameConstraintsTest38EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest10EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest12EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest13EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest15EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest16EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest17EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest20EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest3EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest7EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest8EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDNnameConstraintsTest9EE.crt", + "pki/testdata/nist-pkits/certs/InvalidDSASignatureTest6EE.crt", + "pki/testdata/nist-pkits/certs/InvalidEESignatureTest3EE.crt", + "pki/testdata/nist-pkits/certs/InvalidEEnotAfterDateTest6EE.crt", + "pki/testdata/nist-pkits/certs/InvalidEEnotBeforeDateTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest23EE.crt", + "pki/testdata/nist-pkits/certs/InvalidIDPwithindirectCRLTest26EE.crt", + "pki/testdata/nist-pkits/certs/InvalidLongSerialNumberTest18EE.crt", + "pki/testdata/nist-pkits/certs/InvalidMappingFromanyPolicyTest7EE.crt", + "pki/testdata/nist-pkits/certs/InvalidMappingToanyPolicyTest8EE.crt", + "pki/testdata/nist-pkits/certs/InvalidMissingCRLTest1EE.crt", + "pki/testdata/nist-pkits/certs/InvalidMissingbasicConstraintsTest1EE.crt", + "pki/testdata/nist-pkits/certs/InvalidNameChainingOrderTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidNameChainingTest1EE.crt", + "pki/testdata/nist-pkits/certs/InvalidNegativeSerialNumberTest15EE.crt", + "pki/testdata/nist-pkits/certs/InvalidOldCRLnextUpdateTest11EE.crt", + "pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest10EE.crt", + "pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidPolicyMappingTest4EE.crt", + "pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest22EE.crt", + "pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest24EE.crt", + "pki/testdata/nist-pkits/certs/InvalidRFC822nameConstraintsTest26EE.crt", + "pki/testdata/nist-pkits/certs/InvalidRevokedCATest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidRevokedEETest3EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt", + "pki/testdata/nist-pkits/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt", + "pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest35EE.crt", + "pki/testdata/nist-pkits/certs/InvalidURInameConstraintsTest37EE.crt", + "pki/testdata/nist-pkits/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt", + "pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest10EE.crt", + "pki/testdata/nist-pkits/certs/InvalidUnknownCRLExtensionTest9EE.crt", + "pki/testdata/nist-pkits/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidWrongCRLTest6EE.crt", + "pki/testdata/nist-pkits/certs/InvalidcAFalseTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidcAFalseTest3EE.crt", + "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest27EE.crt", + "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest31EE.crt", + "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest32EE.crt", + "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest34EE.crt", + "pki/testdata/nist-pkits/certs/InvalidcRLIssuerTest35EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest10EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest3EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest4EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest6EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddeltaCRLTest9EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest3EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest6EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest8EE.crt", + "pki/testdata/nist-pkits/certs/InvaliddistributionPointTest9EE.crt", + "pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest1EE.crt", + "pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest4EE.crt", + "pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest5EE.crt", + "pki/testdata/nist-pkits/certs/InvalidinhibitAnyPolicyTest6EE.crt", + "pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest1EE.crt", + "pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest3EE.crt", + "pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest5EE.crt", + "pki/testdata/nist-pkits/certs/InvalidinhibitPolicyMappingTest6EE.crt", + "pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt", + "pki/testdata/nist-pkits/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt", + "pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt", + "pki/testdata/nist-pkits/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt", + "pki/testdata/nist-pkits/certs/InvalidonlyContainsAttributeCertsTest14EE.crt", + "pki/testdata/nist-pkits/certs/InvalidonlyContainsCACertsTest12EE.crt", + "pki/testdata/nist-pkits/certs/InvalidonlyContainsUserCertsTest11EE.crt", + "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest15EE.crt", + "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest16EE.crt", + "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest17EE.crt", + "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest20EE.crt", + "pki/testdata/nist-pkits/certs/InvalidonlySomeReasonsTest21EE.crt", + "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest10EE.crt", + "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest11EE.crt", + "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest12EE.crt", + "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest5EE.crt", + "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest6EE.crt", + "pki/testdata/nist-pkits/certs/InvalidpathLenConstraintTest9EE.crt", + "pki/testdata/nist-pkits/certs/Invalidpre2000CRLnextUpdateTest12EE.crt", + "pki/testdata/nist-pkits/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt", + "pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest3EE.crt", + "pki/testdata/nist-pkits/certs/InvalidrequireExplicitPolicyTest5EE.crt", + "pki/testdata/nist-pkits/certs/LongSerialNumberCACert.crt", + "pki/testdata/nist-pkits/certs/Mapping1to2CACert.crt", + "pki/testdata/nist-pkits/certs/MappingFromanyPolicyCACert.crt", + "pki/testdata/nist-pkits/certs/MappingToanyPolicyCACert.crt", + "pki/testdata/nist-pkits/certs/MissingbasicConstraintsCACert.crt", + "pki/testdata/nist-pkits/certs/NameOrderingCACert.crt", + "pki/testdata/nist-pkits/certs/NegativeSerialNumberCACert.crt", + "pki/testdata/nist-pkits/certs/NoCRLCACert.crt", + "pki/testdata/nist-pkits/certs/NoPoliciesCACert.crt", + "pki/testdata/nist-pkits/certs/NoissuingDistributionPointCACert.crt", + "pki/testdata/nist-pkits/certs/OldCRLnextUpdateCACert.crt", + "pki/testdata/nist-pkits/certs/OverlappingPoliciesTest6EE.crt", + "pki/testdata/nist-pkits/certs/P12Mapping1to3CACert.crt", + "pki/testdata/nist-pkits/certs/P12Mapping1to3subCACert.crt", + "pki/testdata/nist-pkits/certs/P12Mapping1to3subsubCACert.crt", + "pki/testdata/nist-pkits/certs/P1Mapping1to234CACert.crt", + "pki/testdata/nist-pkits/certs/P1Mapping1to234subCACert.crt", + "pki/testdata/nist-pkits/certs/P1anyPolicyMapping1to2CACert.crt", + "pki/testdata/nist-pkits/certs/PanyPolicyMapping1to2CACert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP1234CACert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP1234subCAP123Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP1234subsubCAP123P12Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP123CACert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP123subCAP12Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P1Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP123subsubCAP12P2Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP12CACert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP12subCAP1Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP12subsubCAP1P2Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP2subCA2Cert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP2subCACert.crt", + "pki/testdata/nist-pkits/certs/PoliciesP3CACert.crt", + "pki/testdata/nist-pkits/certs/RFC3280MandatoryAttributeTypesCACert.crt", + "pki/testdata/nist-pkits/certs/RFC3280OptionalAttributeTypesCACert.crt", + "pki/testdata/nist-pkits/certs/RevokedsubCACert.crt", + "pki/testdata/nist-pkits/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt", + "pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt", + "pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt", + "pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt", + "pki/testdata/nist-pkits/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt", + "pki/testdata/nist-pkits/certs/TrustAnchorRootCertificate.crt", + "pki/testdata/nist-pkits/certs/TwoCRLsCACert.crt", + "pki/testdata/nist-pkits/certs/UIDCACert.crt", + "pki/testdata/nist-pkits/certs/UTF8StringCaseInsensitiveMatchCACert.crt", + "pki/testdata/nist-pkits/certs/UTF8StringEncodedNamesCACert.crt", + "pki/testdata/nist-pkits/certs/UnknownCRLEntryExtensionCACert.crt", + "pki/testdata/nist-pkits/certs/UnknownCRLExtensionCACert.crt", + "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest15EE.crt", + "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest16EE.crt", + "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest17EE.crt", + "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest18EE.crt", + "pki/testdata/nist-pkits/certs/UserNoticeQualifierTest19EE.crt", + "pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt", + "pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt", + "pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt", + "pki/testdata/nist-pkits/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt", + "pki/testdata/nist-pkits/certs/ValidCertificatePathTest1EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest30EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNSnameConstraintsTest32EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNandRFC822nameConstraintsTest27EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest11EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest14EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest18EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest19EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest1EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest4EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest5EE.crt", + "pki/testdata/nist-pkits/certs/ValidDNnameConstraintsTest6EE.crt", + "pki/testdata/nist-pkits/certs/ValidDSAParameterInheritanceTest5EE.crt", + "pki/testdata/nist-pkits/certs/ValidDSASignaturesTest4EE.crt", + "pki/testdata/nist-pkits/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt", + "pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt", + "pki/testdata/nist-pkits/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt", + "pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest22EE.crt", + "pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest24EE.crt", + "pki/testdata/nist-pkits/certs/ValidIDPwithindirectCRLTest25EE.crt", + "pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest16EE.crt", + "pki/testdata/nist-pkits/certs/ValidLongSerialNumberTest17EE.crt", + "pki/testdata/nist-pkits/certs/ValidNameChainingCapitalizationTest5EE.crt", + "pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest3EE.crt", + "pki/testdata/nist-pkits/certs/ValidNameChainingWhitespaceTest4EE.crt", + "pki/testdata/nist-pkits/certs/ValidNameUIDsTest6EE.crt", + "pki/testdata/nist-pkits/certs/ValidNegativeSerialNumberTest14EE.crt", + "pki/testdata/nist-pkits/certs/ValidNoissuingDistributionPointTest10EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest11EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest12EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest13EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest14EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest1EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest3EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest5EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest6EE.crt", + "pki/testdata/nist-pkits/certs/ValidPolicyMappingTest9EE.crt", + "pki/testdata/nist-pkits/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt", + "pki/testdata/nist-pkits/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt", + "pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest21EE.crt", + "pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest23EE.crt", + "pki/testdata/nist-pkits/certs/ValidRFC822nameConstraintsTest25EE.crt", + "pki/testdata/nist-pkits/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt", + "pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt", + "pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt", + "pki/testdata/nist-pkits/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt", + "pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt", + "pki/testdata/nist-pkits/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt", + "pki/testdata/nist-pkits/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt", + "pki/testdata/nist-pkits/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt", + "pki/testdata/nist-pkits/certs/ValidTwoCRLsTest7EE.crt", + "pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest34EE.crt", + "pki/testdata/nist-pkits/certs/ValidURInameConstraintsTest36EE.crt", + "pki/testdata/nist-pkits/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt", + "pki/testdata/nist-pkits/certs/ValidUTF8StringEncodedNamesTest9EE.crt", + "pki/testdata/nist-pkits/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt", + "pki/testdata/nist-pkits/certs/ValidbasicConstraintsNotCriticalTest4EE.crt", + "pki/testdata/nist-pkits/certs/ValidcRLIssuerTest28EE.crt", + "pki/testdata/nist-pkits/certs/ValidcRLIssuerTest29EE.crt", + "pki/testdata/nist-pkits/certs/ValidcRLIssuerTest30EE.crt", + "pki/testdata/nist-pkits/certs/ValidcRLIssuerTest33EE.crt", + "pki/testdata/nist-pkits/certs/ValiddeltaCRLTest2EE.crt", + "pki/testdata/nist-pkits/certs/ValiddeltaCRLTest5EE.crt", + "pki/testdata/nist-pkits/certs/ValiddeltaCRLTest7EE.crt", + "pki/testdata/nist-pkits/certs/ValiddeltaCRLTest8EE.crt", + "pki/testdata/nist-pkits/certs/ValiddistributionPointTest1EE.crt", + "pki/testdata/nist-pkits/certs/ValiddistributionPointTest4EE.crt", + "pki/testdata/nist-pkits/certs/ValiddistributionPointTest5EE.crt", + "pki/testdata/nist-pkits/certs/ValiddistributionPointTest7EE.crt", + "pki/testdata/nist-pkits/certs/ValidinhibitAnyPolicyTest2EE.crt", + "pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest2EE.crt", + "pki/testdata/nist-pkits/certs/ValidinhibitPolicyMappingTest4EE.crt", + "pki/testdata/nist-pkits/certs/ValidkeyUsageNotCriticalTest3EE.crt", + "pki/testdata/nist-pkits/certs/ValidonlyContainsCACertsTest13EE.crt", + "pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest18EE.crt", + "pki/testdata/nist-pkits/certs/ValidonlySomeReasonsTest19EE.crt", + "pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest13EE.crt", + "pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest14EE.crt", + "pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest7EE.crt", + "pki/testdata/nist-pkits/certs/ValidpathLenConstraintTest8EE.crt", + "pki/testdata/nist-pkits/certs/Validpre2000UTCnotBeforeDateTest3EE.crt", + "pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest1EE.crt", + "pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest2EE.crt", + "pki/testdata/nist-pkits/certs/ValidrequireExplicitPolicyTest4EE.crt", + "pki/testdata/nist-pkits/certs/WrongCRLCACert.crt", + "pki/testdata/nist-pkits/certs/anyPolicyCACert.crt", + "pki/testdata/nist-pkits/certs/basicConstraintsCriticalcAFalseCACert.crt", + "pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalCACert.crt", + "pki/testdata/nist-pkits/certs/basicConstraintsNotCriticalcAFalseCACert.crt", + "pki/testdata/nist-pkits/certs/deltaCRLCA1Cert.crt", + "pki/testdata/nist-pkits/certs/deltaCRLCA2Cert.crt", + "pki/testdata/nist-pkits/certs/deltaCRLCA3Cert.crt", + "pki/testdata/nist-pkits/certs/deltaCRLIndicatorNoBaseCACert.crt", + "pki/testdata/nist-pkits/certs/distributionPoint1CACert.crt", + "pki/testdata/nist-pkits/certs/distributionPoint2CACert.crt", + "pki/testdata/nist-pkits/certs/indirectCRLCA1Cert.crt", + "pki/testdata/nist-pkits/certs/indirectCRLCA2Cert.crt", + "pki/testdata/nist-pkits/certs/indirectCRLCA3Cert.crt", + "pki/testdata/nist-pkits/certs/indirectCRLCA3cRLIssuerCert.crt", + "pki/testdata/nist-pkits/certs/indirectCRLCA4Cert.crt", + "pki/testdata/nist-pkits/certs/indirectCRLCA4cRLIssuerCert.crt", + "pki/testdata/nist-pkits/certs/indirectCRLCA5Cert.crt", + "pki/testdata/nist-pkits/certs/indirectCRLCA6Cert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy0CACert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1CACert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA1Cert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCA2Cert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subCAIAP5Cert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy1subsubCA2Cert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy5CACert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicy5subsubCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitAnyPolicyTest3EE.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping0CACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping0subCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12CACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1CACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping1P1subsubCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping5CACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubCACert.crt", + "pki/testdata/nist-pkits/certs/inhibitPolicyMapping5subsubsubCACert.crt", + "pki/testdata/nist-pkits/certs/keyUsageCriticalcRLSignFalseCACert.crt", + "pki/testdata/nist-pkits/certs/keyUsageCriticalkeyCertSignFalseCACert.crt", + "pki/testdata/nist-pkits/certs/keyUsageNotCriticalCACert.crt", + "pki/testdata/nist-pkits/certs/keyUsageNotCriticalcRLSignFalseCACert.crt", + "pki/testdata/nist-pkits/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN1CACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN1SelfIssuedCACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA1Cert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA2Cert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN1subCA3Cert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN2CACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN3CACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA1Cert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN3subCA2Cert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN4CACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDN5CACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDNS1CACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsDNS2CACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA1Cert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA2Cert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsRFC822CA3Cert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsURI1CACert.crt", + "pki/testdata/nist-pkits/certs/nameConstraintsURI2CACert.crt", + "pki/testdata/nist-pkits/certs/onlyContainsAttributeCertsCACert.crt", + "pki/testdata/nist-pkits/certs/onlyContainsCACertsCACert.crt", + "pki/testdata/nist-pkits/certs/onlyContainsUserCertsCACert.crt", + "pki/testdata/nist-pkits/certs/onlySomeReasonsCA1Cert.crt", + "pki/testdata/nist-pkits/certs/onlySomeReasonsCA2Cert.crt", + "pki/testdata/nist-pkits/certs/onlySomeReasonsCA3Cert.crt", + "pki/testdata/nist-pkits/certs/onlySomeReasonsCA4Cert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint0CACert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint0SelfIssuedCACert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint0subCA2Cert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint0subCACert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint1CACert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedCACert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint1SelfIssuedsubCACert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint1subCACert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6CACert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6subCA0Cert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6subCA1Cert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6subCA4Cert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA00Cert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA11Cert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubCA41Cert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA11XCert.crt", + "pki/testdata/nist-pkits/certs/pathLenConstraint6subsubsubCA41XCert.crt", + "pki/testdata/nist-pkits/certs/pre2000CRLnextUpdateCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy0CACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy0subCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy0subsubsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy10CACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy10subCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy10subsubsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy2CACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy2subCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy4CACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy4subCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy4subsubsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy5CACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy5subCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy5subsubsubCACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy7CACert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy7subCARE2Cert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt", + "pki/testdata/nist-pkits/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt", + "pki/testdata/nist-pkits/crls/BadCRLIssuerNameCACRL.crl", + "pki/testdata/nist-pkits/crls/BadCRLSignatureCACRL.crl", + "pki/testdata/nist-pkits/crls/BadSignedCACRL.crl", + "pki/testdata/nist-pkits/crls/BadnotAfterDateCACRL.crl", + "pki/testdata/nist-pkits/crls/BadnotBeforeDateCACRL.crl", + "pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl", + "pki/testdata/nist-pkits/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl", + "pki/testdata/nist-pkits/crls/BasicSelfIssuedNewKeyCACRL.crl", + "pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeyCACRL.crl", + "pki/testdata/nist-pkits/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl", + "pki/testdata/nist-pkits/crls/DSACACRL.crl", + "pki/testdata/nist-pkits/crls/DSAParametersInheritedCACRL.crl", + "pki/testdata/nist-pkits/crls/GeneralizedTimeCRLnextUpdateCACRL.crl", + "pki/testdata/nist-pkits/crls/GoodCACRL.crl", + "pki/testdata/nist-pkits/crls/GoodsubCACRL.crl", + "pki/testdata/nist-pkits/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl", + "pki/testdata/nist-pkits/crls/LongSerialNumberCACRL.crl", + "pki/testdata/nist-pkits/crls/Mapping1to2CACRL.crl", + "pki/testdata/nist-pkits/crls/MappingFromanyPolicyCACRL.crl", + "pki/testdata/nist-pkits/crls/MappingToanyPolicyCACRL.crl", + "pki/testdata/nist-pkits/crls/MissingbasicConstraintsCACRL.crl", + "pki/testdata/nist-pkits/crls/NameOrderCACRL.crl", + "pki/testdata/nist-pkits/crls/NegativeSerialNumberCACRL.crl", + "pki/testdata/nist-pkits/crls/NoPoliciesCACRL.crl", + "pki/testdata/nist-pkits/crls/NoissuingDistributionPointCACRL.crl", + "pki/testdata/nist-pkits/crls/OldCRLnextUpdateCACRL.crl", + "pki/testdata/nist-pkits/crls/P12Mapping1to3CACRL.crl", + "pki/testdata/nist-pkits/crls/P12Mapping1to3subCACRL.crl", + "pki/testdata/nist-pkits/crls/P12Mapping1to3subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/P1Mapping1to234CACRL.crl", + "pki/testdata/nist-pkits/crls/P1Mapping1to234subCACRL.crl", + "pki/testdata/nist-pkits/crls/P1anyPolicyMapping1to2CACRL.crl", + "pki/testdata/nist-pkits/crls/PanyPolicyMapping1to2CACRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP1234CACRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP1234subCAP123CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP1234subsubCAP123P12CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP123CACRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP123subCAP12CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP12P1CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP123subsubCAP2P2CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP12CACRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP12subCAP1CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP12subsubCAP1P2CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP2subCA2CRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP2subCACRL.crl", + "pki/testdata/nist-pkits/crls/PoliciesP3CACRL.crl", + "pki/testdata/nist-pkits/crls/RFC3280MandatoryAttributeTypesCACRL.crl", + "pki/testdata/nist-pkits/crls/RFC3280OptionalAttributeTypesCACRL.crl", + "pki/testdata/nist-pkits/crls/RevokedsubCACRL.crl", + "pki/testdata/nist-pkits/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl", + "pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCA2CRL.crl", + "pki/testdata/nist-pkits/crls/SeparateCertificateandCRLKeysCRL.crl", + "pki/testdata/nist-pkits/crls/TrustAnchorRootCRL.crl", + "pki/testdata/nist-pkits/crls/TwoCRLsCABadCRL.crl", + "pki/testdata/nist-pkits/crls/TwoCRLsCAGoodCRL.crl", + "pki/testdata/nist-pkits/crls/UIDCACRL.crl", + "pki/testdata/nist-pkits/crls/UTF8StringCaseInsensitiveMatchCACRL.crl", + "pki/testdata/nist-pkits/crls/UTF8StringEncodedNamesCACRL.crl", + "pki/testdata/nist-pkits/crls/UnknownCRLEntryExtensionCACRL.crl", + "pki/testdata/nist-pkits/crls/UnknownCRLExtensionCACRL.crl", + "pki/testdata/nist-pkits/crls/WrongCRLCACRL.crl", + "pki/testdata/nist-pkits/crls/anyPolicyCACRL.crl", + "pki/testdata/nist-pkits/crls/basicConstraintsCriticalcAFalseCACRL.crl", + "pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalCACRL.crl", + "pki/testdata/nist-pkits/crls/basicConstraintsNotCriticalcAFalseCACRL.crl", + "pki/testdata/nist-pkits/crls/deltaCRLCA1CRL.crl", + "pki/testdata/nist-pkits/crls/deltaCRLCA1deltaCRL.crl", + "pki/testdata/nist-pkits/crls/deltaCRLCA2CRL.crl", + "pki/testdata/nist-pkits/crls/deltaCRLCA2deltaCRL.crl", + "pki/testdata/nist-pkits/crls/deltaCRLCA3CRL.crl", + "pki/testdata/nist-pkits/crls/deltaCRLCA3deltaCRL.crl", + "pki/testdata/nist-pkits/crls/deltaCRLIndicatorNoBaseCACRL.crl", + "pki/testdata/nist-pkits/crls/distributionPoint1CACRL.crl", + "pki/testdata/nist-pkits/crls/distributionPoint2CACRL.crl", + "pki/testdata/nist-pkits/crls/indirectCRLCA1CRL.crl", + "pki/testdata/nist-pkits/crls/indirectCRLCA3CRL.crl", + "pki/testdata/nist-pkits/crls/indirectCRLCA3cRLIssuerCRL.crl", + "pki/testdata/nist-pkits/crls/indirectCRLCA4cRLIssuerCRL.crl", + "pki/testdata/nist-pkits/crls/indirectCRLCA5CRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy0CACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1CACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA1CRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCA2CRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subCAIAP5CRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy1subsubCA2CRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy5CACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitAnyPolicy5subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping0CACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping0subCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12CACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1CACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping1P1subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping5CACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/inhibitPolicyMapping5subsubsubCACRL.crl", + "pki/testdata/nist-pkits/crls/keyUsageCriticalcRLSignFalseCACRL.crl", + "pki/testdata/nist-pkits/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl", + "pki/testdata/nist-pkits/crls/keyUsageNotCriticalCACRL.crl", + "pki/testdata/nist-pkits/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl", + "pki/testdata/nist-pkits/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN1CACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA1CRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA2CRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN1subCA3CRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN2CACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN3CACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA1CRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN3subCA2CRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN4CACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDN5CACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDNS1CACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsDNS2CACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA1CRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA2CRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsRFC822CA3CRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsURI1CACRL.crl", + "pki/testdata/nist-pkits/crls/nameConstraintsURI2CACRL.crl", + "pki/testdata/nist-pkits/crls/onlyContainsAttributeCertsCACRL.crl", + "pki/testdata/nist-pkits/crls/onlyContainsCACertsCACRL.crl", + "pki/testdata/nist-pkits/crls/onlyContainsUserCertsCACRL.crl", + "pki/testdata/nist-pkits/crls/onlySomeReasonsCA1compromiseCRL.crl", + "pki/testdata/nist-pkits/crls/onlySomeReasonsCA1otherreasonsCRL.crl", + "pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL1.crl", + "pki/testdata/nist-pkits/crls/onlySomeReasonsCA2CRL2.crl", + "pki/testdata/nist-pkits/crls/onlySomeReasonsCA3compromiseCRL.crl", + "pki/testdata/nist-pkits/crls/onlySomeReasonsCA3otherreasonsCRL.crl", + "pki/testdata/nist-pkits/crls/onlySomeReasonsCA4compromiseCRL.crl", + "pki/testdata/nist-pkits/crls/onlySomeReasonsCA4otherreasonsCRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint0CACRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint0subCA2CRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint0subCACRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint1CACRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint1subCACRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6CACRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6subCA0CRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6subCA1CRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6subCA4CRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA00CRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA11CRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubCA41CRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA11XCRL.crl", + "pki/testdata/nist-pkits/crls/pathLenConstraint6subsubsubCA41XCRL.crl", + "pki/testdata/nist-pkits/crls/pre2000CRLnextUpdateCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy0CACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy0subCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy0subsubsubCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy10CACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy10subCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy10subsubsubCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy2CACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy2subCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy4CACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy4subCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy4subsubsubCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy5CACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy5subCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy5subsubsubCACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy7CACRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy7subCARE2CRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl", + "pki/testdata/nist-pkits/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl", + "pki/testdata/ocsp_unittest/bad_ocsp_type.pem", + "pki/testdata/ocsp_unittest/bad_signature.pem", + "pki/testdata/ocsp_unittest/bad_status.pem", + "pki/testdata/ocsp_unittest/good_response.pem", + "pki/testdata/ocsp_unittest/good_response_next_update.pem", + "pki/testdata/ocsp_unittest/good_response_sha256.pem", + "pki/testdata/ocsp_unittest/has_critical_ct_extension.pem", + "pki/testdata/ocsp_unittest/has_critical_response_extension.pem", + "pki/testdata/ocsp_unittest/has_critical_single_extension.pem", + "pki/testdata/ocsp_unittest/has_extension.pem", + "pki/testdata/ocsp_unittest/has_single_extension.pem", + "pki/testdata/ocsp_unittest/has_version.pem", + "pki/testdata/ocsp_unittest/malformed_request.pem", + "pki/testdata/ocsp_unittest/missing_response.pem", + "pki/testdata/ocsp_unittest/multiple_response.pem", + "pki/testdata/ocsp_unittest/no_response.pem", + "pki/testdata/ocsp_unittest/ocsp_extra_certs.pem", + "pki/testdata/ocsp_unittest/ocsp_sign_bad_indirect.pem", + "pki/testdata/ocsp_unittest/ocsp_sign_direct.pem", + "pki/testdata/ocsp_unittest/ocsp_sign_indirect.pem", + "pki/testdata/ocsp_unittest/ocsp_sign_indirect_missing.pem", + "pki/testdata/ocsp_unittest/other_response.pem", + "pki/testdata/ocsp_unittest/responder_id.pem", + "pki/testdata/ocsp_unittest/responder_name.pem", + "pki/testdata/ocsp_unittest/revoke_response.pem", + "pki/testdata/ocsp_unittest/revoke_response_reason.pem", + "pki/testdata/ocsp_unittest/unknown_response.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/empty_sequence.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_extension_sequence.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/extra_contents_after_issuer_and_serial.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_contents.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_issuer.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_key_identifier.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/invalid_serial.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_and_serial.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/issuer_only.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/key_identifier_and_issuer_and_serial.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/serial_only.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier/url_issuer_and_serial.pem", + "pki/testdata/parse_certificate_unittest/authority_key_identifier_not_sequence.pem", + "pki/testdata/parse_certificate_unittest/bad_key_usage.pem", + "pki/testdata/parse_certificate_unittest/bad_policy_qualifiers.pem", + "pki/testdata/parse_certificate_unittest/bad_signature_algorithm_oid.pem", + "pki/testdata/parse_certificate_unittest/bad_validity.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_ca_false.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_ca_no_path.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_ca_path_9.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_negative_path.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_not_ca.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_path_too_large.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_255.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_256.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_pathlen_not_ca.pem", + "pki/testdata/parse_certificate_unittest/basic_constraints_unconsumed_data.pem", + "pki/testdata/parse_certificate_unittest/cert_algorithm_not_sequence.pem", + "pki/testdata/parse_certificate_unittest/cert_data_after_signature.pem", + "pki/testdata/parse_certificate_unittest/cert_empty_sequence.pem", + "pki/testdata/parse_certificate_unittest/cert_missing_signature.pem", + "pki/testdata/parse_certificate_unittest/cert_not_sequence.pem", + "pki/testdata/parse_certificate_unittest/cert_signature_not_bit_string.pem", + "pki/testdata/parse_certificate_unittest/cert_skeleton.pem", + "pki/testdata/parse_certificate_unittest/cert_version3.pem", + "pki/testdata/parse_certificate_unittest/crldp_1uri_noissuer.pem", + "pki/testdata/parse_certificate_unittest/crldp_3uri_noissuer.pem", + "pki/testdata/parse_certificate_unittest/crldp_full_name_as_dirname.pem", + "pki/testdata/parse_certificate_unittest/crldp_issuer_as_dirname.pem", + "pki/testdata/parse_certificate_unittest/extended_key_usage.pem", + "pki/testdata/parse_certificate_unittest/extension_critical.pem", + "pki/testdata/parse_certificate_unittest/extension_critical_0.pem", + "pki/testdata/parse_certificate_unittest/extension_critical_3.pem", + "pki/testdata/parse_certificate_unittest/extension_not_critical.pem", + "pki/testdata/parse_certificate_unittest/extensions_data_after_sequence.pem", + "pki/testdata/parse_certificate_unittest/extensions_duplicate_key_usage.pem", + "pki/testdata/parse_certificate_unittest/extensions_empty_sequence.pem", + "pki/testdata/parse_certificate_unittest/extensions_not_sequence.pem", + "pki/testdata/parse_certificate_unittest/extensions_real.pem", + "pki/testdata/parse_certificate_unittest/failed_signature_algorithm.pem", + "pki/testdata/parse_certificate_unittest/inhibit_any_policy.pem", + "pki/testdata/parse_certificate_unittest/issuer_bad_printable_string.pem", + "pki/testdata/parse_certificate_unittest/key_usage.pem", + "pki/testdata/parse_certificate_unittest/name_constraints_bad_ip.pem", + "pki/testdata/parse_certificate_unittest/policies.pem", + "pki/testdata/parse_certificate_unittest/policy_constraints_empty.pem", + "pki/testdata/parse_certificate_unittest/policy_constraints_inhibit.pem", + "pki/testdata/parse_certificate_unittest/policy_constraints_inhibit_require.pem", + "pki/testdata/parse_certificate_unittest/policy_constraints_require.pem", + "pki/testdata/parse_certificate_unittest/policy_qualifiers_empty_sequence.pem", + "pki/testdata/parse_certificate_unittest/serial_37_bytes.pem", + "pki/testdata/parse_certificate_unittest/serial_negative.pem", + "pki/testdata/parse_certificate_unittest/serial_not_minimal.pem", + "pki/testdata/parse_certificate_unittest/serial_not_number.pem", + "pki/testdata/parse_certificate_unittest/serial_zero.pem", + "pki/testdata/parse_certificate_unittest/serial_zero_padded.pem", + "pki/testdata/parse_certificate_unittest/serial_zero_padded_21_bytes.pem", + "pki/testdata/parse_certificate_unittest/signature_algorithm_null.pem", + "pki/testdata/parse_certificate_unittest/subject_alt_name.pem", + "pki/testdata/parse_certificate_unittest/subject_blank_subjectaltname_not_critical.pem", + "pki/testdata/parse_certificate_unittest/subject_key_identifier_not_octet_string.pem", + "pki/testdata/parse_certificate_unittest/subject_not_ascii.pem", + "pki/testdata/parse_certificate_unittest/subject_not_printable_string.pem", + "pki/testdata/parse_certificate_unittest/subject_printable_string_containing_utf8_client_cert.pem", + "pki/testdata/parse_certificate_unittest/subject_t61string.pem", + "pki/testdata/parse_certificate_unittest/subject_t61string_1-32.pem", + "pki/testdata/parse_certificate_unittest/subject_t61string_126-160.pem", + "pki/testdata/parse_certificate_unittest/subject_t61string_actual.pem", + "pki/testdata/parse_certificate_unittest/subjectaltname_bad_ip.pem", + "pki/testdata/parse_certificate_unittest/subjectaltname_dns_not_ascii.pem", + "pki/testdata/parse_certificate_unittest/subjectaltname_general_names_empty_sequence.pem", + "pki/testdata/parse_certificate_unittest/subjectaltname_trailing_data.pem", + "pki/testdata/parse_certificate_unittest/tbs_explicit_v1.pem", + "pki/testdata/parse_certificate_unittest/tbs_v1.pem", + "pki/testdata/parse_certificate_unittest/tbs_v1_extensions.pem", + "pki/testdata/parse_certificate_unittest/tbs_v2_extensions.pem", + "pki/testdata/parse_certificate_unittest/tbs_v2_issuer_and_subject_unique_id.pem", + "pki/testdata/parse_certificate_unittest/tbs_v2_issuer_unique_id.pem", + "pki/testdata/parse_certificate_unittest/tbs_v2_no_optionals.pem", + "pki/testdata/parse_certificate_unittest/tbs_v3_all_optionals.pem", + "pki/testdata/parse_certificate_unittest/tbs_v3_data_after_extensions.pem", + "pki/testdata/parse_certificate_unittest/tbs_v3_extensions.pem", + "pki/testdata/parse_certificate_unittest/tbs_v3_extensions_not_sequence.pem", + "pki/testdata/parse_certificate_unittest/tbs_v3_no_optionals.pem", + "pki/testdata/parse_certificate_unittest/tbs_v3_real.pem", + "pki/testdata/parse_certificate_unittest/tbs_v4.pem", + "pki/testdata/parse_certificate_unittest/tbs_validity_both_generalized_time.pem", + "pki/testdata/parse_certificate_unittest/tbs_validity_both_utc_time.pem", + "pki/testdata/parse_certificate_unittest/tbs_validity_generalized_time_and_utc_time.pem", + "pki/testdata/parse_certificate_unittest/tbs_validity_relaxed.pem", + "pki/testdata/parse_certificate_unittest/tbs_validity_utc_time_and_generalized_time.pem", + "pki/testdata/parse_certificate_unittest/v1_explicit_version.pem", + "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_match_name_only.pem", + "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_matching.pem", + "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/int_mismatch.pem", + "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root.pem", + "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/root2.pem", + "pki/testdata/path_builder_unittest/key_id_name_and_serial_prioritization/target.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_a.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_b.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_different_ski_c.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_a.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_b.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_matching_ski_c.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_a.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_b.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/int_no_ski_c.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/root.pem", + "pki/testdata/path_builder_unittest/key_id_prioritization/target.pem", + "pki/testdata/path_builder_unittest/multi-root-A-by-B.pem", + "pki/testdata/path_builder_unittest/multi-root-B-by-C.pem", + "pki/testdata/path_builder_unittest/multi-root-B-by-F.pem", + "pki/testdata/path_builder_unittest/multi-root-C-by-D.pem", + "pki/testdata/path_builder_unittest/multi-root-C-by-E.pem", + "pki/testdata/path_builder_unittest/multi-root-D-by-D.pem", + "pki/testdata/path_builder_unittest/multi-root-E-by-E.pem", + "pki/testdata/path_builder_unittest/multi-root-F-by-E.pem", + "pki/testdata/path_builder_unittest/precertificate/precertificate.pem", + "pki/testdata/path_builder_unittest/precertificate/root.pem", + "pki/testdata/path_builder_unittest/self_issued_prioritization/root1.pem", + "pki/testdata/path_builder_unittest/self_issued_prioritization/root1_cross.pem", + "pki/testdata/path_builder_unittest/self_issued_prioritization/root2.pem", + "pki/testdata/path_builder_unittest/self_issued_prioritization/target.pem", + "pki/testdata/path_builder_unittest/validity_date_prioritization/int_ac.pem", + "pki/testdata/path_builder_unittest/validity_date_prioritization/int_ad.pem", + "pki/testdata/path_builder_unittest/validity_date_prioritization/int_bc.pem", + "pki/testdata/path_builder_unittest/validity_date_prioritization/int_bd.pem", + "pki/testdata/path_builder_unittest/validity_date_prioritization/root.pem", + "pki/testdata/path_builder_unittest/validity_date_prioritization/target.pem", + "pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued/main.test", + "pki/testdata/verify_certificate_chain_unittest/expired-intermediate/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-after.test", + "pki/testdata/verify_certificate_chain_unittest/expired-intermediate/not-before.test", + "pki/testdata/verify_certificate_chain_unittest/expired-root/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration-and-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/expired-root/not-after-ta-with-expiration.test", + "pki/testdata/verify_certificate_chain_unittest/expired-root/not-after.test", + "pki/testdata/verify_certificate_chain_unittest/expired-root/not-before-ta-with-expiration.test", + "pki/testdata/verify_certificate_chain_unittest/expired-root/not-before.test", + "pki/testdata/verify_certificate_chain_unittest/expired-target/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/expired-target/not-after.test", + "pki/testdata/verify_certificate_chain_unittest/expired-target/not-before.test", + "pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/incorrect-trust-anchor/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-and-target-wrong-signature/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-ca-false/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-basic-constraints-not-critical/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/any.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/clientauth.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-any-and-clientauth/serverauth.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/any.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/clientauth.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-clientauth/serverauth.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-any.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-clientAuth.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha1-eku-serverAuth.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-any.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-clientAuth.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-eku-server-gated-crypto/sha256-eku-serverAuth.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-invalid-spki/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-basic-constraints/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-lacks-signing-key-usage/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-signed-with-sha1/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-critical-extension/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-unknown-non-critical-extension/main.test", + "pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/intermediate-wrong-signature-no-authority-key-identifier/main.test", + "pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.pem", + "pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/anchor.test", + "pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.pem", + "pki/testdata/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal/target.test", + "pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.pem", + "pki/testdata/verify_certificate_chain_unittest/key-rollover/longrolloverchain.test", + "pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.pem", + "pki/testdata/verify_certificate_chain_unittest/key-rollover/newchain.test", + "pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.pem", + "pki/testdata/verify_certificate_chain_unittest/key-rollover/oldchain.test", + "pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.pem", + "pki/testdata/verify_certificate_chain_unittest/key-rollover/rolloverchain.test", + "pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.pem", + "pki/testdata/verify_certificate_chain_unittest/many-names/ok-all-types.test", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.pem", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-all-types.test", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.pem", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-excluded.test", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.pem", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dirnames-permitted.test", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.pem", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-excluded.test", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.pem", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-dns-permitted.test", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.pem", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-excluded.test", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.pem", + "pki/testdata/verify_certificate_chain_unittest/many-names/toomany-ips-permitted.test", + "pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/main.test", + "pki/testdata/verify_certificate_chain_unittest/non-self-signed-root/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.4.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.5.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.1.6.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.1.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.10.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.13.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.4.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.5.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.6.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.7.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.10.8.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.1.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.10.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.11.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.5.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.6.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.8.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.11.9.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.1.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.10.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.4.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.5.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.6.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.12.8.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.10.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.12.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.13.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.15.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.16.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.17.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.20.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.21.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.22.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.23.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.24.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.25.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.26.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.27.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.28.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.29.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.31.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.33.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.34.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.35.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.36.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.37.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.38.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.7.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.8.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.13.9.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.16.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.1.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.5.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.6.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.2.7.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.1.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.3.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.1.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.10.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.11.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.12.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.16.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.5.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.6.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.6.9.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.1.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.7.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.1.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.12.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.14.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.2.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.4.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.5.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.6.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.7.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.8.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.8.9.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.3.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.5.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.7.txt", + "pki/testdata/verify_certificate_chain_unittest/pkits_errors/4.9.8.txt", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-fail/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-anypolicy-by-root-ok/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-fail/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-inhibit-mapping-by-root-ok/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policies-ok/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-ok/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-ok/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-on-root-ok/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-on-root-wrong/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-fail/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/main.test", + "pki/testdata/verify_certificate_chain_unittest/policies-required-by-root-ok/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/main.test", + "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-fail/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/main.test", + "pki/testdata/verify_certificate_chain_unittest/policy-mappings-on-root-ok/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/main.test", + "pki/testdata/verify_certificate_chain_unittest/root-basic-constraints-ca-false/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints-strict.test", + "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration-and-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth-ta-with-expiration.test", + "pki/testdata/verify_certificate_chain_unittest/root-eku-clientauth/serverauth.test", + "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/main.test", + "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints-require-basic-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/root-lacks-basic-constraints/ta-with-require-basic-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/main.test", + "pki/testdata/verify_certificate_chain_unittest/root-lacks-keycertsign-key-usage/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root-expired.test", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/distrusted-root.test", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-constraints.test", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/ta-with-expiration.test", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-and-trust_anchor.test", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/trusted_leaf-root.test", + "pki/testdata/verify_certificate_chain_unittest/target-and-intermediate/unspecified-trust-root.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-any/any.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-any/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-any/clientauth.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-any/serverauth.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/any.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/clientauth.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-clientauth/serverauth.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-many/any.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-many/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-many/clientauth.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-many/serverauth.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-none/any.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-none/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-none/clientauth.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-eku-none/serverauth.test", + "pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-has-512bit-rsa-key/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf-strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only-trusted_leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-has-ca-basic-constraints/target_only.pem", + "pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-has-pathlen-but-not-ca/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-and-eku/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-msapplicationpolicies-no-eku/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict-leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-not-end-entity/strict.test", + "pki/testdata/verify_certificate_chain_unittest/target-only/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_anchor.test", + "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-and-trust_anchor.test", + "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-not_after.test", + "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf-wrong_eku.test", + "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-only/trusted_leaf_require_self_signed.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfissued/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_anchor.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf-and-trust_anchor.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfissued/trusted_leaf_require_self_signed.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-and-trust_anchor.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-not_after.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf-wrong_eku.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-selfsigned/trusted_leaf_require_self_signed.test", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.pem", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-decipherOnly.test", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.pem", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-digitalSignature.test", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.pem", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyAgreement.test", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.pem", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/ec-keyEncipherment.test", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.pem", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-decipherOnly.test", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.pem", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-digitalSignature.test", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.pem", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyAgreement.test", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.pem", + "pki/testdata/verify_certificate_chain_unittest/target-serverauth-various-keyusages/rsa-keyEncipherment.test", + "pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-signed-by-512bit-rsa/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-signed-using-ecdsa/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-signed-with-sha1/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only-trusted_leaf.test", + "pki/testdata/verify_certificate_chain_unittest/target-unknown-critical-extension/target_only.pem", + "pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-wrong-signature-no-authority-key-identifier/main.test", + "pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/target-wrong-signature/main.test", + "pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/unknown-critical-policy-qualifier/main.test", + "pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/unknown-non-critical-policy-qualifier/main.test", + "pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0/main.test", + "pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/chain.pem", + "pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/main.test", + "pki/testdata/verify_certificate_chain_unittest/violates-pathlen-1-from-root/ta-with-constraints.test", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-extra_whitespace.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-BMPSTRING-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-case_swap.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-extra_whitespace.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_1.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-rdn_sorting_2.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-PRINTABLESTRING-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-case_swap.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-extra_whitespace.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-T61STRING-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-case_swap.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-extra_whitespace.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UNIVERSALSTRING-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-case_swap.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-extra_whitespace.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-dupe_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_attr.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled-extra_rdn.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-UTF8-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_1.pem", + "pki/testdata/verify_name_match_unittest/names/ascii-mixed-rdn_dupetype_sorting_2.pem", + "pki/testdata/verify_name_match_unittest/names/custom-custom-normalized.pem", + "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-badAttributeType.pem", + "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-empty.pem", + "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-extradata.pem", + "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-onlyOneElement.pem", + "pki/testdata/verify_name_match_unittest/names/invalid-AttributeTypeAndValue-setNotSequence.pem", + "pki/testdata/verify_name_match_unittest/names/invalid-Name-setInsteadOfSequence.pem", + "pki/testdata/verify_name_match_unittest/names/invalid-RDN-empty.pem", + "pki/testdata/verify_name_match_unittest/names/invalid-RDN-sequenceInsteadOfSet.pem", + "pki/testdata/verify_name_match_unittest/names/unicode-mixed-normalized.pem", + "pki/testdata/verify_name_match_unittest/names/unicode-mixed-unnormalized.pem", + "pki/testdata/verify_name_match_unittest/names/unicode_bmp-BMPSTRING-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/unicode_bmp-UNIVERSALSTRING-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/unicode_bmp-UTF8-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UNIVERSALSTRING-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/unicode_supplementary-UTF8-unmangled.pem", + "pki/testdata/verify_name_match_unittest/names/valid-Name-empty.pem", + "pki/testdata/verify_name_match_unittest/names/valid-minimal.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-spki-params-null.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-unused-bits-signature.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecdh-key.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-ecmqv-key.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-using-rsa-algorithm.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512-wrong-signature-format.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-prime256v1-sha512.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256-corrupted-data.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-secp384r1-sha256.pem", + "pki/testdata/verify_signed_data_unittest/ecdsa-using-rsa-key.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-length.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-bad-key-der-null.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-key-params-absent.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-using-pss-key-no-params.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1-wrong-algorithm.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha1.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-key-encoded-ber.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-spki-non-null-params.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-ecdsa-algorithm.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256-using-id-ea-rsa.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pkcs1-sha256.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-using-pss-key-with-params.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pss-sha256-wrong-salt.pem", + "pki/testdata/verify_signed_data_unittest/rsa-pss-sha256.pem", + "pki/testdata/verify_signed_data_unittest/rsa-using-ec-key.pem", + "pki/testdata/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem", + "pki/testdata/verify_unittest/google-intermediate1.der", + "pki/testdata/verify_unittest/google-intermediate2.der", + "pki/testdata/verify_unittest/google-leaf.der", + "pki/testdata/verify_unittest/lencr-intermediate-r3.der", + "pki/testdata/verify_unittest/lencr-leaf.der", + "pki/testdata/verify_unittest/lencr-root-dst-x3.der", + "pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der", + "pki/testdata/verify_unittest/lencr-root-x1.der", + "pki/testdata/verify_unittest/mozilla_roots.der", + "pki/testdata/verify_unittest/self-issued.pem", ] ssl_sources = [ - "ssl/bio_ssl.cc", - "ssl/d1_both.cc", - "ssl/d1_lib.cc", - "ssl/d1_pkt.cc", - "ssl/d1_srtp.cc", - "ssl/dtls_method.cc", - "ssl/dtls_record.cc", - "ssl/encrypted_client_hello.cc", - "ssl/extensions.cc", - "ssl/handoff.cc", - "ssl/handshake.cc", - "ssl/handshake_client.cc", - "ssl/handshake_server.cc", - "ssl/s3_both.cc", - "ssl/s3_lib.cc", - "ssl/s3_pkt.cc", - "ssl/ssl_aead_ctx.cc", - "ssl/ssl_asn1.cc", - "ssl/ssl_buffer.cc", - "ssl/ssl_cert.cc", - "ssl/ssl_cipher.cc", - "ssl/ssl_credential.cc", - "ssl/ssl_file.cc", - "ssl/ssl_key_share.cc", - "ssl/ssl_lib.cc", - "ssl/ssl_privkey.cc", - "ssl/ssl_session.cc", - "ssl/ssl_stat.cc", - "ssl/ssl_transcript.cc", - "ssl/ssl_versions.cc", - "ssl/ssl_x509.cc", - "ssl/t1_enc.cc", - "ssl/tls13_both.cc", - "ssl/tls13_client.cc", - "ssl/tls13_enc.cc", - "ssl/tls13_server.cc", - "ssl/tls_method.cc", - "ssl/tls_record.cc", + "ssl/bio_ssl.cc", + "ssl/d1_both.cc", + "ssl/d1_lib.cc", + "ssl/d1_pkt.cc", + "ssl/d1_srtp.cc", + "ssl/dtls_method.cc", + "ssl/dtls_record.cc", + "ssl/encrypted_client_hello.cc", + "ssl/extensions.cc", + "ssl/handoff.cc", + "ssl/handshake.cc", + "ssl/handshake_client.cc", + "ssl/handshake_server.cc", + "ssl/s3_both.cc", + "ssl/s3_lib.cc", + "ssl/s3_pkt.cc", + "ssl/ssl_aead_ctx.cc", + "ssl/ssl_asn1.cc", + "ssl/ssl_buffer.cc", + "ssl/ssl_cert.cc", + "ssl/ssl_cipher.cc", + "ssl/ssl_credential.cc", + "ssl/ssl_file.cc", + "ssl/ssl_key_share.cc", + "ssl/ssl_lib.cc", + "ssl/ssl_privkey.cc", + "ssl/ssl_session.cc", + "ssl/ssl_stat.cc", + "ssl/ssl_transcript.cc", + "ssl/ssl_versions.cc", + "ssl/ssl_x509.cc", + "ssl/t1_enc.cc", + "ssl/tls13_both.cc", + "ssl/tls13_client.cc", + "ssl/tls13_enc.cc", + "ssl/tls13_server.cc", + "ssl/tls_method.cc", + "ssl/tls_record.cc", ] ssl_headers = [ - "include/openssl/dtls1.h", - "include/openssl/srtp.h", - "include/openssl/ssl.h", - "include/openssl/ssl3.h", - "include/openssl/tls1.h", + "include/openssl/dtls1.h", + "include/openssl/srtp.h", + "include/openssl/ssl.h", + "include/openssl/ssl3.h", + "include/openssl/tls1.h", ] ssl_internal_headers = [ - "ssl/internal.h", + "ssl/internal.h", ] ssl_test_sources = [ - "crypto/test/gtest_main.cc", - "ssl/span_test.cc", - "ssl/ssl_c_test.c", - "ssl/ssl_test.cc", + "crypto/test/gtest_main.cc", + "ssl/span_test.cc", + "ssl/ssl_c_test.c", + "ssl/ssl_test.cc", ] test_support_sources = [ - "crypto/test/abi_test.cc", - "crypto/test/file_test.cc", - "crypto/test/file_test_gtest.cc", - "crypto/test/file_util.cc", - "crypto/test/test_data.cc", - "crypto/test/test_util.cc", - "crypto/test/wycheproof_util.cc", + "crypto/test/abi_test.cc", + "crypto/test/file_test.cc", + "crypto/test/file_test_gtest.cc", + "crypto/test/file_util.cc", + "crypto/test/test_data.cc", + "crypto/test/test_util.cc", + "crypto/test/wycheproof_util.cc", ] test_support_internal_headers = [ - "crypto/test/abi_test.h", - "crypto/test/file_test.h", - "crypto/test/file_util.h", - "crypto/test/gtest_main.h", - "crypto/test/test_data.h", - "crypto/test/test_util.h", - "crypto/test/wycheproof_util.h", - "ssl/test/async_bio.h", - "ssl/test/fuzzer.h", - "ssl/test/fuzzer_tags.h", - "ssl/test/handshake_util.h", - "ssl/test/mock_quic_transport.h", - "ssl/test/packeted_bio.h", - "ssl/test/settings_writer.h", - "ssl/test/test_config.h", - "ssl/test/test_state.h", + "crypto/test/abi_test.h", + "crypto/test/file_test.h", + "crypto/test/file_util.h", + "crypto/test/gtest_main.h", + "crypto/test/test_data.h", + "crypto/test/test_util.h", + "crypto/test/wycheproof_util.h", + "ssl/test/async_bio.h", + "ssl/test/fuzzer.h", + "ssl/test/fuzzer_tags.h", + "ssl/test/handshake_util.h", + "ssl/test/mock_quic_transport.h", + "ssl/test/packeted_bio.h", + "ssl/test/settings_writer.h", + "ssl/test/test_config.h", + "ssl/test/test_state.h", ] test_support_sources_asm = [ - "gen/test_support/trampoline-armv4-linux.S", - "gen/test_support/trampoline-armv8-apple.S", - "gen/test_support/trampoline-armv8-linux.S", - "gen/test_support/trampoline-armv8-win.S", - "gen/test_support/trampoline-x86-apple.S", - "gen/test_support/trampoline-x86-linux.S", - "gen/test_support/trampoline-x86_64-apple.S", - "gen/test_support/trampoline-x86_64-linux.S", + "gen/test_support/trampoline-armv4-linux.S", + "gen/test_support/trampoline-armv8-apple.S", + "gen/test_support/trampoline-armv8-linux.S", + "gen/test_support/trampoline-armv8-win.S", + "gen/test_support/trampoline-x86-apple.S", + "gen/test_support/trampoline-x86-linux.S", + "gen/test_support/trampoline-x86_64-apple.S", + "gen/test_support/trampoline-x86_64-linux.S", ] test_support_sources_nasm = [ - "gen/test_support/trampoline-x86-win.asm", - "gen/test_support/trampoline-x86_64-win.asm", + "gen/test_support/trampoline-x86-win.asm", + "gen/test_support/trampoline-x86_64-win.asm", ] urandom_test_sources = [ - "crypto/fipsmodule/rand/urandom_test.cc", + "crypto/fipsmodule/rand/urandom_test.cc", ] diff --git a/naiveproxy/src/third_party/boringssl/src/gen/sources.cmake b/naiveproxy/src/third_party/boringssl/src/gen/sources.cmake index a050003451..11d97be644 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/sources.cmake +++ b/naiveproxy/src/third_party/boringssl/src/gen/sources.cmake @@ -201,6 +201,8 @@ set( gen/bcm/x86_64-mont-linux.S gen/bcm/x86_64-mont5-apple.S gen/bcm/x86_64-mont5-linux.S + third_party/fiat/asm/fiat_p256_adx_mul.S + third_party/fiat/asm/fiat_p256_adx_sqr.S ) set( @@ -344,6 +346,7 @@ set( crypto/dh_extra/dh_asn1.c crypto/dh_extra/params.c crypto/digest_extra/digest_extra.c + crypto/dilithium/dilithium.c crypto/dsa/dsa.c crypto/dsa/dsa_asn1.c crypto/ec_extra/ec_asn1.c @@ -543,6 +546,7 @@ set( include/openssl/evp.h include/openssl/evp_errors.h include/openssl/ex_data.h + include/openssl/experimental/dilithium.h include/openssl/experimental/kyber.h include/openssl/experimental/spx.h include/openssl/hkdf.h @@ -598,12 +602,12 @@ set( crypto/bytestring/internal.h crypto/chacha/internal.h crypto/cipher_extra/internal.h - crypto/conf/conf_def.h crypto/conf/internal.h crypto/cpu_arm_linux.h crypto/curve25519/curve25519_tables.h crypto/curve25519/internal.h crypto/des/internal.h + crypto/dilithium/internal.h crypto/dsa/internal.h crypto/ec_extra/internal.h crypto/err/internal.h @@ -684,8 +688,6 @@ set( gen/crypto/chacha20_poly1305_x86_64-linux.S third_party/fiat/asm/fiat_curve25519_adx_mul.S third_party/fiat/asm/fiat_curve25519_adx_square.S - third_party/fiat/asm/fiat_p256_adx_mul.S - third_party/fiat/asm/fiat_p256_adx_sqr.S ) set( @@ -720,6 +722,7 @@ set( crypto/curve25519/x25519_test.cc crypto/dh_extra/dh_test.cc crypto/digest_extra/digest_test.cc + crypto/dilithium/dilithium_test.cc crypto/dsa/dsa_test.cc crypto/ecdh_extra/ecdh_test.cc crypto/err/err_test.cc @@ -807,6 +810,9 @@ set( crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt crypto/cipher_extra/test/xchacha20_poly1305_tests.txt crypto/curve25519/ed25519_tests.txt + crypto/dilithium/dilithium_tests.txt + crypto/dilithium/edge_cases_draft_dilithium3_sign.txt + crypto/dilithium/edge_cases_draft_dilithium3_verify.txt crypto/ecdh_extra/ecdh_tests.txt crypto/evp/evp_tests.txt crypto/evp/scrypt_tests.txt @@ -1089,6 +1095,7 @@ set( pki/trust_store.cc pki/trust_store_collection.cc pki/trust_store_in_memory.cc + pki/verify.cc pki/verify_certificate_chain.cc pki/verify_error.cc pki/verify_name_match.cc @@ -1100,6 +1107,7 @@ set( include/openssl/pki/certificate.h include/openssl/pki/signature_verify_cache.h + include/openssl/pki/verify.h include/openssl/pki/verify_error.h ) @@ -1184,6 +1192,7 @@ set( pki/verify_certificate_chain_unittest.cc pki/verify_name_match_unittest.cc pki/verify_signed_data_unittest.cc + pki/verify_unittest.cc ) set( @@ -2596,7 +2605,15 @@ set( pki/testdata/verify_signed_data_unittest/rsa-pss-sha256.pem pki/testdata/verify_signed_data_unittest/rsa-using-ec-key.pem pki/testdata/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem + pki/testdata/verify_unittest/google-intermediate1.der + pki/testdata/verify_unittest/google-intermediate2.der pki/testdata/verify_unittest/google-leaf.der + pki/testdata/verify_unittest/lencr-intermediate-r3.der + pki/testdata/verify_unittest/lencr-leaf.der + pki/testdata/verify_unittest/lencr-root-dst-x3.der + pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der + pki/testdata/verify_unittest/lencr-root-x1.der + pki/testdata/verify_unittest/mozilla_roots.der pki/testdata/verify_unittest/self-issued.pem ) diff --git a/naiveproxy/src/third_party/boringssl/src/gen/sources.json b/naiveproxy/src/third_party/boringssl/src/gen/sources.json index c77f70fd2c..3bb5ea56fa 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/sources.json +++ b/naiveproxy/src/third_party/boringssl/src/gen/sources.json @@ -178,7 +178,9 @@ "gen/bcm/x86_64-mont-apple.S", "gen/bcm/x86_64-mont-linux.S", "gen/bcm/x86_64-mont5-apple.S", - "gen/bcm/x86_64-mont5-linux.S" + "gen/bcm/x86_64-mont5-linux.S", + "third_party/fiat/asm/fiat_p256_adx_mul.S", + "third_party/fiat/asm/fiat_p256_adx_sqr.S" ], "nasm": [ "gen/bcm/aesni-gcm-x86_64-win.asm", @@ -314,6 +316,7 @@ "crypto/dh_extra/dh_asn1.c", "crypto/dh_extra/params.c", "crypto/digest_extra/digest_extra.c", + "crypto/dilithium/dilithium.c", "crypto/dsa/dsa.c", "crypto/dsa/dsa_asn1.c", "crypto/ec_extra/ec_asn1.c", @@ -510,6 +513,7 @@ "include/openssl/evp.h", "include/openssl/evp_errors.h", "include/openssl/ex_data.h", + "include/openssl/experimental/dilithium.h", "include/openssl/experimental/kyber.h", "include/openssl/experimental/spx.h", "include/openssl/hkdf.h", @@ -562,12 +566,12 @@ "crypto/bytestring/internal.h", "crypto/chacha/internal.h", "crypto/cipher_extra/internal.h", - "crypto/conf/conf_def.h", "crypto/conf/internal.h", "crypto/cpu_arm_linux.h", "crypto/curve25519/curve25519_tables.h", "crypto/curve25519/internal.h", "crypto/des/internal.h", + "crypto/dilithium/internal.h", "crypto/dsa/internal.h", "crypto/ec_extra/internal.h", "crypto/err/internal.h", @@ -644,9 +648,7 @@ "gen/crypto/chacha20_poly1305_x86_64-apple.S", "gen/crypto/chacha20_poly1305_x86_64-linux.S", "third_party/fiat/asm/fiat_curve25519_adx_mul.S", - "third_party/fiat/asm/fiat_curve25519_adx_square.S", - "third_party/fiat/asm/fiat_p256_adx_mul.S", - "third_party/fiat/asm/fiat_p256_adx_sqr.S" + "third_party/fiat/asm/fiat_curve25519_adx_square.S" ], "nasm": [ "gen/crypto/aes128gcmsiv-x86_64-win.asm", @@ -677,6 +679,7 @@ "crypto/curve25519/x25519_test.cc", "crypto/dh_extra/dh_test.cc", "crypto/digest_extra/digest_test.cc", + "crypto/dilithium/dilithium_test.cc", "crypto/dsa/dsa_test.cc", "crypto/ecdh_extra/ecdh_test.cc", "crypto/err/err_test.cc", @@ -761,6 +764,9 @@ "crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt", "crypto/cipher_extra/test/xchacha20_poly1305_tests.txt", "crypto/curve25519/ed25519_tests.txt", + "crypto/dilithium/dilithium_tests.txt", + "crypto/dilithium/edge_cases_draft_dilithium3_sign.txt", + "crypto/dilithium/edge_cases_draft_dilithium3_verify.txt", "crypto/ecdh_extra/ecdh_tests.txt", "crypto/evp/evp_tests.txt", "crypto/evp/scrypt_tests.txt", @@ -1037,6 +1043,7 @@ "pki/trust_store.cc", "pki/trust_store_collection.cc", "pki/trust_store_in_memory.cc", + "pki/verify.cc", "pki/verify_certificate_chain.cc", "pki/verify_error.cc", "pki/verify_name_match.cc", @@ -1045,6 +1052,7 @@ "hdrs": [ "include/openssl/pki/certificate.h", "include/openssl/pki/signature_verify_cache.h", + "include/openssl/pki/verify.h", "include/openssl/pki/verify_error.h" ], "internal_hdrs": [ @@ -1124,7 +1132,8 @@ "pki/verify_certificate_chain_pkits_unittest.cc", "pki/verify_certificate_chain_unittest.cc", "pki/verify_name_match_unittest.cc", - "pki/verify_signed_data_unittest.cc" + "pki/verify_signed_data_unittest.cc", + "pki/verify_unittest.cc" ], "data": [ "pki/testdata/cert_issuer_source_static_unittest/c1.pem", @@ -2534,7 +2543,15 @@ "pki/testdata/verify_signed_data_unittest/rsa-pss-sha256.pem", "pki/testdata/verify_signed_data_unittest/rsa-using-ec-key.pem", "pki/testdata/verify_signed_data_unittest/rsa2048-pkcs1-sha512.pem", + "pki/testdata/verify_unittest/google-intermediate1.der", + "pki/testdata/verify_unittest/google-intermediate2.der", "pki/testdata/verify_unittest/google-leaf.der", + "pki/testdata/verify_unittest/lencr-intermediate-r3.der", + "pki/testdata/verify_unittest/lencr-leaf.der", + "pki/testdata/verify_unittest/lencr-root-dst-x3.der", + "pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der", + "pki/testdata/verify_unittest/lencr-root-x1.der", + "pki/testdata/verify_unittest/mozilla_roots.der", "pki/testdata/verify_unittest/self-issued.pem" ] }, diff --git a/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-apple.S b/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-apple.S index 7c76d2d744..f618dacd1f 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-apple.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-apple.S @@ -52,6 +52,7 @@ _CET_ENDBR movq %r15,104(%rsp) + movq 0(%rsi),%rbx movq 8(%rsi),%rbp movq 16(%rsi),%r12 @@ -473,6 +474,7 @@ _CET_ENDBR + nop popq %r12 @@ -496,6 +498,7 @@ _CET_ENDBR + movq %r12,%rax incq %rax movq %rax,(%rsp) diff --git a/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-linux.S b/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-linux.S index 93af8b9480..8557e9e4f7 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-linux.S +++ b/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-linux.S @@ -52,6 +52,7 @@ _CET_ENDBR movq %r15,104(%rsp) .cfi_offset r15, -24 + movq 0(%rsi),%rbx movq 8(%rsi),%rbp movq 16(%rsi),%r12 @@ -474,6 +475,7 @@ _CET_ENDBR + nop popq %r12 .cfi_adjust_cfa_offset -8 @@ -499,6 +501,7 @@ _CET_ENDBR .cfi_offset %r12,-16 + movq %r12,%rax incq %rax movq %rax,(%rsp) diff --git a/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-win.asm b/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-win.asm index ae04cbed40..7c7d3c3222 100644 --- a/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-win.asm +++ b/naiveproxy/src/third_party/boringssl/src/gen/test_support/trampoline-x86_64-win.asm @@ -39,61 +39,62 @@ _CET_ENDBR sub rsp,344 -$L$SEH_prolog_abi_test_trampoline_2: +$L$SEH_prologue_abi_test_trampoline_2: mov QWORD[112+rsp],rbx -$L$SEH_prolog_abi_test_trampoline_3: +$L$SEH_prologue_abi_test_trampoline_3: mov QWORD[120+rsp],rbp -$L$SEH_prolog_abi_test_trampoline_4: +$L$SEH_prologue_abi_test_trampoline_4: mov QWORD[128+rsp],rdi -$L$SEH_prolog_abi_test_trampoline_5: +$L$SEH_prologue_abi_test_trampoline_5: mov QWORD[136+rsp],rsi -$L$SEH_prolog_abi_test_trampoline_6: +$L$SEH_prologue_abi_test_trampoline_6: mov QWORD[144+rsp],r12 -$L$SEH_prolog_abi_test_trampoline_7: +$L$SEH_prologue_abi_test_trampoline_7: mov QWORD[152+rsp],r13 -$L$SEH_prolog_abi_test_trampoline_8: +$L$SEH_prologue_abi_test_trampoline_8: mov QWORD[160+rsp],r14 -$L$SEH_prolog_abi_test_trampoline_9: +$L$SEH_prologue_abi_test_trampoline_9: mov QWORD[168+rsp],r15 -$L$SEH_prolog_abi_test_trampoline_10: +$L$SEH_prologue_abi_test_trampoline_10: movdqa XMMWORD[176+rsp],xmm6 -$L$SEH_prolog_abi_test_trampoline_11: +$L$SEH_prologue_abi_test_trampoline_11: movdqa XMMWORD[192+rsp],xmm7 -$L$SEH_prolog_abi_test_trampoline_12: +$L$SEH_prologue_abi_test_trampoline_12: movdqa XMMWORD[208+rsp],xmm8 -$L$SEH_prolog_abi_test_trampoline_13: +$L$SEH_prologue_abi_test_trampoline_13: movdqa XMMWORD[224+rsp],xmm9 -$L$SEH_prolog_abi_test_trampoline_14: +$L$SEH_prologue_abi_test_trampoline_14: movdqa XMMWORD[240+rsp],xmm10 -$L$SEH_prolog_abi_test_trampoline_15: +$L$SEH_prologue_abi_test_trampoline_15: movdqa XMMWORD[256+rsp],xmm11 -$L$SEH_prolog_abi_test_trampoline_16: +$L$SEH_prologue_abi_test_trampoline_16: movdqa XMMWORD[272+rsp],xmm12 -$L$SEH_prolog_abi_test_trampoline_17: +$L$SEH_prologue_abi_test_trampoline_17: movdqa XMMWORD[288+rsp],xmm13 -$L$SEH_prolog_abi_test_trampoline_18: +$L$SEH_prologue_abi_test_trampoline_18: movdqa XMMWORD[304+rsp],xmm14 -$L$SEH_prolog_abi_test_trampoline_19: +$L$SEH_prologue_abi_test_trampoline_19: movdqa XMMWORD[320+rsp],xmm15 -$L$SEH_prolog_abi_test_trampoline_20: +$L$SEH_prologue_abi_test_trampoline_20: +$L$SEH_endprologue_abi_test_trampoline_21: mov rbx,QWORD[rdx] mov rbp,QWORD[8+rdx] mov rdi,QWORD[16+rdx] @@ -254,7 +255,7 @@ $L$call_done: ret -$L$SEH_end_abi_test_trampoline_21: +$L$SEH_end_abi_test_trampoline_22: global abi_test_clobber_rax @@ -516,7 +517,8 @@ $L$SEH_begin_abi_test_bad_unwind_wrong_register_1: _CET_ENDBR push r12 -$L$SEH_prolog_abi_test_bad_unwind_wrong_register_2: +$L$SEH_prologue_abi_test_bad_unwind_wrong_register_2: +$L$SEH_endprologue_abi_test_bad_unwind_wrong_register_3: @@ -524,7 +526,7 @@ $L$SEH_prolog_abi_test_bad_unwind_wrong_register_2: pop r12 ret -$L$SEH_end_abi_test_bad_unwind_wrong_register_3: +$L$SEH_end_abi_test_bad_unwind_wrong_register_4: @@ -540,7 +542,8 @@ $L$SEH_begin_abi_test_bad_unwind_temporary_1: _CET_ENDBR push r12 -$L$SEH_prolog_abi_test_bad_unwind_temporary_2: +$L$SEH_prologue_abi_test_bad_unwind_temporary_2: +$L$SEH_endprologue_abi_test_bad_unwind_temporary_3: mov rax,r12 inc rax @@ -555,7 +558,7 @@ $L$SEH_prolog_abi_test_bad_unwind_temporary_2: ret -$L$SEH_end_abi_test_bad_unwind_temporary_3: +$L$SEH_end_abi_test_bad_unwind_temporary_4: @@ -592,7 +595,8 @@ ALIGN 16 abi_test_bad_unwind_epilog: $L$SEH_begin_abi_test_bad_unwind_epilog_1: push r12 -$L$SEH_prolog_abi_test_bad_unwind_epilog_2: +$L$SEH_prologue_abi_test_bad_unwind_epilog_2: +$L$SEH_endprologue_abi_test_bad_unwind_epilog_3: nop @@ -600,24 +604,24 @@ $L$SEH_prolog_abi_test_bad_unwind_epilog_2: pop r12 nop ret -$L$SEH_end_abi_test_bad_unwind_epilog_3: +$L$SEH_end_abi_test_bad_unwind_epilog_4: section .pdata rdata align=4 ALIGN 4 DD $L$SEH_begin_abi_test_trampoline_1 wrt ..imagebase - DD $L$SEH_end_abi_test_trampoline_21 wrt ..imagebase + DD $L$SEH_end_abi_test_trampoline_22 wrt ..imagebase DD $L$SEH_info_abi_test_trampoline_0 wrt ..imagebase DD $L$SEH_begin_abi_test_bad_unwind_wrong_register_1 wrt ..imagebase - DD $L$SEH_end_abi_test_bad_unwind_wrong_register_3 wrt ..imagebase + DD $L$SEH_end_abi_test_bad_unwind_wrong_register_4 wrt ..imagebase DD $L$SEH_info_abi_test_bad_unwind_wrong_register_0 wrt ..imagebase DD $L$SEH_begin_abi_test_bad_unwind_temporary_1 wrt ..imagebase - DD $L$SEH_end_abi_test_bad_unwind_temporary_3 wrt ..imagebase + DD $L$SEH_end_abi_test_bad_unwind_temporary_4 wrt ..imagebase DD $L$SEH_info_abi_test_bad_unwind_temporary_0 wrt ..imagebase DD $L$SEH_begin_abi_test_bad_unwind_epilog_1 wrt ..imagebase - DD $L$SEH_end_abi_test_bad_unwind_epilog_3 wrt ..imagebase + DD $L$SEH_end_abi_test_bad_unwind_epilog_4 wrt ..imagebase DD $L$SEH_info_abi_test_bad_unwind_epilog_0 wrt ..imagebase @@ -625,90 +629,94 @@ section .xdata rdata align=8 ALIGN 4 $L$SEH_info_abi_test_trampoline_0: DB 1 - DB $L$SEH_prolog_abi_test_trampoline_20-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_endprologue_abi_test_trampoline_21-$L$SEH_begin_abi_test_trampoline_1 DB 38 DB 0 - DB $L$SEH_prolog_abi_test_trampoline_20-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_20-$L$SEH_begin_abi_test_trampoline_1 DB 248 DW 20 - DB $L$SEH_prolog_abi_test_trampoline_19-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_19-$L$SEH_begin_abi_test_trampoline_1 DB 232 DW 19 - DB $L$SEH_prolog_abi_test_trampoline_18-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_18-$L$SEH_begin_abi_test_trampoline_1 DB 216 DW 18 - DB $L$SEH_prolog_abi_test_trampoline_17-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_17-$L$SEH_begin_abi_test_trampoline_1 DB 200 DW 17 - DB $L$SEH_prolog_abi_test_trampoline_16-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_16-$L$SEH_begin_abi_test_trampoline_1 DB 184 DW 16 - DB $L$SEH_prolog_abi_test_trampoline_15-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_15-$L$SEH_begin_abi_test_trampoline_1 DB 168 DW 15 - DB $L$SEH_prolog_abi_test_trampoline_14-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_14-$L$SEH_begin_abi_test_trampoline_1 DB 152 DW 14 - DB $L$SEH_prolog_abi_test_trampoline_13-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_13-$L$SEH_begin_abi_test_trampoline_1 DB 136 DW 13 - DB $L$SEH_prolog_abi_test_trampoline_12-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_12-$L$SEH_begin_abi_test_trampoline_1 DB 120 DW 12 - DB $L$SEH_prolog_abi_test_trampoline_11-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_11-$L$SEH_begin_abi_test_trampoline_1 DB 104 DW 11 - DB $L$SEH_prolog_abi_test_trampoline_10-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_10-$L$SEH_begin_abi_test_trampoline_1 DB 244 DW 21 - DB $L$SEH_prolog_abi_test_trampoline_9-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_9-$L$SEH_begin_abi_test_trampoline_1 DB 228 DW 20 - DB $L$SEH_prolog_abi_test_trampoline_8-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_8-$L$SEH_begin_abi_test_trampoline_1 DB 212 DW 19 - DB $L$SEH_prolog_abi_test_trampoline_7-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_7-$L$SEH_begin_abi_test_trampoline_1 DB 196 DW 18 - DB $L$SEH_prolog_abi_test_trampoline_6-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_6-$L$SEH_begin_abi_test_trampoline_1 DB 100 DW 17 - DB $L$SEH_prolog_abi_test_trampoline_5-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_5-$L$SEH_begin_abi_test_trampoline_1 DB 116 DW 16 - DB $L$SEH_prolog_abi_test_trampoline_4-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_4-$L$SEH_begin_abi_test_trampoline_1 DB 84 DW 15 - DB $L$SEH_prolog_abi_test_trampoline_3-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_3-$L$SEH_begin_abi_test_trampoline_1 DB 52 DW 14 - DB $L$SEH_prolog_abi_test_trampoline_2-$L$SEH_begin_abi_test_trampoline_1 + DB $L$SEH_prologue_abi_test_trampoline_2-$L$SEH_begin_abi_test_trampoline_1 DB 1 DW 43 $L$SEH_info_abi_test_bad_unwind_wrong_register_0: DB 1 - DB $L$SEH_prolog_abi_test_bad_unwind_wrong_register_2-$L$SEH_begin_abi_test_bad_unwind_wrong_register_1 + DB $L$SEH_endprologue_abi_test_bad_unwind_wrong_register_3-$L$SEH_begin_abi_test_bad_unwind_wrong_register_1 DB 1 DB 0 - DB $L$SEH_prolog_abi_test_bad_unwind_wrong_register_2-$L$SEH_begin_abi_test_bad_unwind_wrong_register_1 + DB $L$SEH_prologue_abi_test_bad_unwind_wrong_register_2-$L$SEH_begin_abi_test_bad_unwind_wrong_register_1 DB 208 + DW 0 $L$SEH_info_abi_test_bad_unwind_temporary_0: DB 1 - DB $L$SEH_prolog_abi_test_bad_unwind_temporary_2-$L$SEH_begin_abi_test_bad_unwind_temporary_1 + DB $L$SEH_endprologue_abi_test_bad_unwind_temporary_3-$L$SEH_begin_abi_test_bad_unwind_temporary_1 DB 1 DB 0 - DB $L$SEH_prolog_abi_test_bad_unwind_temporary_2-$L$SEH_begin_abi_test_bad_unwind_temporary_1 + DB $L$SEH_prologue_abi_test_bad_unwind_temporary_2-$L$SEH_begin_abi_test_bad_unwind_temporary_1 DB 192 + DW 0 $L$SEH_info_abi_test_bad_unwind_epilog_0: DB 1 - DB $L$SEH_prolog_abi_test_bad_unwind_epilog_2-$L$SEH_begin_abi_test_bad_unwind_epilog_1 + DB $L$SEH_endprologue_abi_test_bad_unwind_epilog_3-$L$SEH_begin_abi_test_bad_unwind_epilog_1 DB 1 DB 0 - DB $L$SEH_prolog_abi_test_bad_unwind_epilog_2-$L$SEH_begin_abi_test_bad_unwind_epilog_1 + DB $L$SEH_prologue_abi_test_bad_unwind_epilog_2-$L$SEH_begin_abi_test_bad_unwind_epilog_1 DB 192 + + DW 0 %else ; Work around https://bugzilla.nasm.us/show_bug.cgi?id=3392738 ret diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/crypto.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/crypto.h index c5c21bb4de..63dbcb2885 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/crypto.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/crypto.h @@ -32,18 +32,9 @@ extern "C" { #endif -// crypto.h contains functions for initializing the crypto library. +// crypto.h contains functions for library-wide initialization and properties. -// CRYPTO_library_init initializes the crypto library. It must be called if the -// library is built with BORINGSSL_NO_STATIC_INITIALIZER. Otherwise, it does -// nothing and a static initializer is used instead. It is safe to call this -// function multiple times and concurrently from multiple threads. -// -// On some ARM configurations, this function may require filesystem access and -// should be called before entering a sandbox. -OPENSSL_EXPORT void CRYPTO_library_init(void); - // CRYPTO_is_confidential_build returns one if the linked version of BoringSSL // has been built with the BORINGSSL_CONFIDENTIAL define and zero otherwise. // @@ -164,7 +155,7 @@ OPENSSL_EXPORT void OPENSSL_load_builtin_modules(void); #define OPENSSL_INIT_NO_LOAD_CONFIG 0 #define OPENSSL_INIT_NO_ATEXIT 0 -// OPENSSL_init_crypto calls |CRYPTO_library_init| and returns one. +// OPENSSL_init_crypto returns one. OPENSSL_EXPORT int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); @@ -178,6 +169,9 @@ OPENSSL_EXPORT int FIPS_mode_set(int on); // FIPS_module_name returns the name of the FIPS module. OPENSSL_EXPORT const char *FIPS_module_name(void); +// FIPS_module_hash returns the 32-byte hash of the FIPS module. +OPENSSL_EXPORT const uint8_t* FIPS_module_hash(void); + // FIPS_version returns the version of the FIPS module, or zero if the build // isn't exactly at a verified version. The version, expressed in base 10, will // be a date in the form yyyymmddXX where XX is often "00", but can be @@ -196,6 +190,10 @@ OPENSSL_EXPORT int FIPS_query_algorithm_status(const char *algorithm); OPENSSL_EXPORT int CRYPTO_has_broken_NEON(void); #endif +// CRYPTO_library_init does nothing. Historically, it was needed in some build +// configurations to initialization the library. This is no longer necessary. +OPENSSL_EXPORT void CRYPTO_library_init(void); + #if defined(__cplusplus) } // extern C diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/experimental/dilithium.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/experimental/dilithium.h new file mode 100644 index 0000000000..72e79bd99a --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/experimental/dilithium.h @@ -0,0 +1,125 @@ +/* Copyright (c) 2023, Google LLC + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_DILITHIUM_H +#define OPENSSL_HEADER_DILITHIUM_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + + +#if defined(OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM) +// This header implements experimental, draft versions of not-yet-standardized +// primitives. When the standard is complete, these functions will be removed +// and replaced with the final, incompatible standard version. They are +// available now for short-lived experiments, but must not be deployed anywhere +// durable, such as a long-lived key store. To use these functions define +// OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM. + +// Dilithium3. + + +// DILITHIUM_private_key contains a Dilithium3 private key. The contents of this +// object should never leave the address space since the format is unstable. +struct DILITHIUM_private_key { + union { + uint8_t bytes[32 + 32 + 64 + 256 * 4 * (5 + 6 + 6)]; + uint32_t alignment; + } opaque; +}; + +// DILITHIUM_public_key contains a Dilithium3 public key. The contents of this +// object should never leave the address space since the format is unstable. +struct DILITHIUM_public_key { + union { + uint8_t bytes[32 + 64 + 256 * 4 * 6]; + uint32_t alignment; + } opaque; +}; + +// DILITHIUM_PRIVATE_KEY_BYTES is the number of bytes in an encoded Dilithium3 +// private key. +#define DILITHIUM_PRIVATE_KEY_BYTES 4032 + +// DILITHIUM_PUBLIC_KEY_BYTES is the number of bytes in an encoded Dilithium3 +// public key. +#define DILITHIUM_PUBLIC_KEY_BYTES 1952 + +// DILITHIUM_SIGNATURE_BYTES is the number of bytes in an encoded Dilithium3 +// signature. +#define DILITHIUM_SIGNATURE_BYTES 3309 + +// DILITHIUM_generate_key generates a random public/private key pair, writes the +// encoded public key to |out_encoded_public_key| and sets |out_private_key| to +// the private key. Returns 1 on success and 0 on failure. +OPENSSL_EXPORT int DILITHIUM_generate_key( + uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES], + struct DILITHIUM_private_key *out_private_key); + +// DILITHIUM_sign generates a signature for the message |msg| of length +// |msg_len| using |private_key| following the randomized algorithm, and writes +// the encoded signature to |out_encoded_signature|. Returns 1 on success and 0 +// on failure. +OPENSSL_EXPORT int DILITHIUM_sign( + uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], + const struct DILITHIUM_private_key *private_key, const uint8_t *msg, + size_t msg_len); + +// DILITHIUM_verify verifies that |encoded_signature| constitutes a valid +// signature for the message |msg| of length |msg_len| using |public_key|. +OPENSSL_EXPORT int DILITHIUM_verify( + const struct DILITHIUM_public_key *public_key, + const uint8_t encoded_signature[DILITHIUM_SIGNATURE_BYTES], + const uint8_t *msg, size_t msg_len); + + +// Serialisation of keys. + +// DILITHIUM_marshal_public_key serializes |public_key| to |out| in the standard +// format for Dilithium public keys. It returns one on success or zero on +// allocation error. +OPENSSL_EXPORT int DILITHIUM_marshal_public_key( + CBB *out, const struct DILITHIUM_public_key *public_key); + +// DILITHIUM_parse_public_key parses a public key, in the format generated by +// |DILITHIUM_marshal_public_key|, from |in| and writes the result to +// |out_public_key|. It returns one on success or zero on parse error or if +// there are trailing bytes in |in|. +OPENSSL_EXPORT int DILITHIUM_parse_public_key( + struct DILITHIUM_public_key *public_key, CBS *in); + +// DILITHIUM_marshal_private_key serializes |private_key| to |out| in the +// standard format for Dilithium private keys. It returns one on success or zero +// on allocation error. +OPENSSL_EXPORT int DILITHIUM_marshal_private_key( + CBB *out, const struct DILITHIUM_private_key *private_key); + +// DILITHIUM_parse_private_key parses a private key, in the format generated by +// |DILITHIUM_marshal_private_key|, from |in| and writes the result to +// |out_private_key|. It returns one on success or zero on parse error or if +// there are trailing bytes in |in|. +OPENSSL_EXPORT int DILITHIUM_parse_private_key( + struct DILITHIUM_private_key *private_key, CBS *in); + +#endif // OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_DILITHIUM_H diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/experimental/kyber.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/experimental/kyber.h index e0268fc143..e6e9e9af1d 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/experimental/kyber.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/experimental/kyber.h @@ -22,6 +22,14 @@ extern "C" { #endif +#if defined(OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER) +// This header implements experimental, draft versions of not-yet-standardized +// primitives. When the standard is complete, these functions will be removed +// and replaced with the final, incompatible standard version. They are +// available now for short-lived experiments, but must not be deployed anywhere +// durable, such as a long-lived key store. To use these functions define +// OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER + // Kyber768. // // This implements the round-3 specification of Kyber, defined at @@ -128,6 +136,8 @@ OPENSSL_EXPORT int KYBER_marshal_private_key( OPENSSL_EXPORT int KYBER_parse_private_key( struct KYBER_private_key *out_private_key, CBS *in); +#endif // OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER + #if defined(__cplusplus) } // extern C diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/pki/verify.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/pki/verify.h new file mode 100644 index 0000000000..0c1b551ba9 --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/pki/verify.h @@ -0,0 +1,170 @@ +#ifndef BSSL_VERIFY_H_ +#define BSSL_VERIFY_H_ + +#include +#include +#include +#include +#include + +#include +#include + +namespace bssl { +class CertIssuerSourceStatic; +class TrustStoreInMemory; +class CertificateVerifyOptions; +class CertificateVerifyStatus; + +class OPENSSL_EXPORT VerifyTrustStore { + public: + std::unique_ptr trust_store; + + ~VerifyTrustStore(); + + // FromDER returns a |TrustStore| derived from interpreting the |der_certs| as + // a bunch of DER-encoded certs, concatenated. In the event of a failure nullptr + // e is returned and a diagnostic string is placed in |out_diagnostic| + static std::unique_ptr FromDER( + std::string_view der_certs, std::string *out_diagnostic); + + // FromDER returns a |TrustStore| consisting of the supplied DER-encoded + // certs in |der_certs|. In the event of a failure nullptr is returned and a + // diagnostic string is placed in |out_diagnostic| + static std::unique_ptr FromDER( + const std::vector &der_certs, + std::string *out_diagnostic); +}; + +class OPENSSL_EXPORT CertPool { + public: + CertPool(); + CertPool(const CertPool &) = delete; + CertPool &operator=(const CertPool &) = delete; + virtual ~CertPool(); + + // FromCerts returns a |CertPool| consisting of the supplied DER-encoded + // certs in |der_certs|. In the event of a failure nullptr is returned and a + // diagnostic string is placed in |out_diagnostic| + static std::unique_ptr FromCerts( + const std::vector &der_certs, + std::string *out_diagnostic); + + private: + friend std::optional>> + CertificateVerifyInternal(const CertificateVerifyOptions &opts, + VerifyError *out_error, + CertificateVerifyStatus *out_status, + bool all_paths); + std::unique_ptr impl_; +}; + +// CertificateVerifyOptions contains all the options for a certificate verification. +class OPENSSL_EXPORT CertificateVerifyOptions { + public: + // The key purpose (extended key usage) to check for during verification. + enum class KeyPurpose { + ANY_EKU, + SERVER_AUTH, + CLIENT_AUTH, + SERVER_AUTH_STRICT, + CLIENT_AUTH_STRICT, + SERVER_AUTH_STRICT_LEAF, + CLIENT_AUTH_STRICT_LEAF, + }; + + CertificateVerifyOptions(); + CertificateVerifyOptions(const CertificateVerifyOptions &) = delete; + CertificateVerifyOptions &operator=(const CertificateVerifyOptions &) = + delete; + + KeyPurpose key_purpose = KeyPurpose::SERVER_AUTH; + std::string_view leaf_cert; + std::vector intermediates; + + // extra_intermediates optionally points to a pool of common intermediates. + const CertPool *extra_intermediates = nullptr; + // trust_store points to the set of root certificates to trust. + const VerifyTrustStore *trust_store = nullptr; + // min_rsa_modulus_length is the minimum acceptable RSA key size in a chain. + size_t min_rsa_modulus_length = 1024; + // time is the time in POSIX seconds since the POSIX epoch at which to + // validate the chain. It defaults to the current time if not set. + std::optional time; + // insecurely_allow_sha1 allows verification of signatures that use SHA-1 + // message digests. This option is insecure and should not be used. + bool insecurely_allow_sha1 = false; + + // max_iteration_count, if not zero, limits the number of times path building + // will try to append an intermediate to a potential path. This bounds the + // amount of time that a verification attempt can take, at the risk of + // rejecting cases that would be solved if only more effort were used. + uint32_t max_iteration_count = 0; + + // Sets an optional deadline for completing path building. It defaults + // to std::chrono::time_point::max() if it not set. If |deadline| has a + // value that has passed based on comparison to + // std::chrono::steady_clock::now(), and path building has not completed, + // path building will stop. Note that this is not a hard limit, there is no + // guarantee how far past |deadline| time will be when path building is + // aborted. + std::optional> deadline; + + // max_path_building_depth, if not zero, limits the depth of the path that the + // path building algorithm attempts to build between leafs and roots. Using + // this comes at the risk of rejecting cases that would be solved if only one + // more certificate is added to the path. + uint32_t max_path_building_depth = 0; + + // signature_verify_cache, if not nullptr, points to an object implementing a + // signature verification cache derived from + // + SignatureVerifyCache *signature_verify_cache = nullptr; +}; + +// CertificateVerifyStatus describes the status of a certificate verification +// attempt. +class OPENSSL_EXPORT CertificateVerifyStatus { + public: + CertificateVerifyStatus(); + + // IterationCount returns the total number of attempted certificate additions + // to any potential path while performing path building for verification. It + // is the same value which may be bound by max_iteration_count in + // CertificateVerifyOptions. + size_t IterationCount() const; + + // MaxDepthSeen returns the maximum path depth seen during path building. + size_t MaxDepthSeen() const; + + private: + friend std::optional>> + CertificateVerifyInternal(const CertificateVerifyOptions &opts, + VerifyError *out_error, + CertificateVerifyStatus *out_status, + bool all_paths); + size_t iteration_count_ = 0; + size_t max_depth_seen_ = 0; +}; + +// Verify verifies |opts.leaf_cert| using the other values in |opts|. It +// returns either an error, or else a validated chain from leaf to root. +// +// In the event of an error return, |out_error| will be updated with information +// about the error. It may be |nullptr|. +// +// Status information about the verification will be returned in |out_status|. +// It may be |nullptr|. +OPENSSL_EXPORT std::optional> CertificateVerify( + const CertificateVerifyOptions &opts, VerifyError *out_error = nullptr, + CertificateVerifyStatus *out_status = nullptr); + +// VerifyAllPaths verifies |opts.leaf_cert| using the other values in |opts|, +// and returns all possible valid chains from the leaf to a root. If no chains +// exist, it returns an error. +OPENSSL_EXPORT std::optional>> +CertificateVerifyAllPaths(const CertificateVerifyOptions &opts); + +} // namespace bssl + +#endif // BSSL_VERIFY_H_ diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/span.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/span.h index 38196ae8a5..4f11559e77 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/span.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/span.h @@ -49,6 +49,16 @@ class SpanBase { friend bool operator!=(Span lhs, Span rhs) { return !(lhs == rhs); } }; + +// Heuristically test whether C is a container type that can be converted into +// a Span by checking for data() and size() member functions. +// +// TODO(davidben): Require C++17 support for std::is_convertible_v, etc. +template +using EnableIfContainer = std::enable_if_t< + std::is_convertible().data()), T *>::value && + std::is_integral().size())>::value>; + } // namespace internal // A Span is a non-owning reference to a contiguous array of objects of type @@ -84,16 +94,6 @@ class SpanBase { // a reference or pointer to a container or array. template class Span : private internal::SpanBase { - private: - // Heuristically test whether C is a container type that can be converted into - // a Span by checking for data() and size() member functions. - // - // TODO(davidben): Require C++17 support for std::is_convertible_v, etc. - template - using EnableIfContainer = std::enable_if_t< - std::is_convertible().data()), T *>::value && - std::is_integral().size())>::value>; - public: static const size_t npos = static_cast(-1); @@ -114,12 +114,12 @@ class Span : private internal::SpanBase { template constexpr Span(T (&array)[N]) : Span(array, N) {} - template , + template , typename = std::enable_if_t::value, C>> constexpr Span(const C &container) : data_(container.data()), size_(container.size()) {} - template , + template , typename = std::enable_if_t::value, C>> constexpr explicit Span(C &container) : data_(container.data()), size_(container.size()) {} @@ -188,6 +188,20 @@ class Span : private internal::SpanBase { template const size_t Span::npos; +#if __cplusplus >= 201703L +template +Span(T *, size_t) -> Span; +template +Span(T (&array)[size]) -> Span; +template < + typename C, + typename T = std::remove_pointer_t().data())>, + typename = internal::EnableIfContainer> +Span(C &) -> Span; +#endif + +// C++17 callers can instead rely on CTAD and the deduction guides defined +// above. template constexpr Span MakeSpan(T *ptr, size_t size) { return Span(ptr, size); diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/ssl.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/ssl.h index 04c191fa62..9f95a06bba 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/ssl.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/ssl.h @@ -1205,6 +1205,11 @@ OPENSSL_EXPORT int SSL_set_ocsp_response(SSL *ssl, #define SSL_SIGN_RSA_PSS_RSAE_SHA512 0x0806 #define SSL_SIGN_ED25519 0x0807 +// SSL_SIGN_RSA_PKCS1_SHA256_LEGACY is a backport of RSASSA-PKCS1-v1_5 with +// SHA-256 to TLS 1.3. It is disabled by default and only defined for client +// certificates. +#define SSL_SIGN_RSA_PKCS1_SHA256_LEGACY 0x0420 + // SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal signature algorithm used to // specify raw RSASSA-PKCS1-v1_5 with an MD5/SHA-1 concatenation, as used in TLS // before TLS 1.2. @@ -3115,7 +3120,8 @@ OPENSSL_EXPORT int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, // SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is called // during ClientHello processing in order to select an ALPN protocol from the -// client's list of offered protocols. +// client's list of offered protocols. |SSL_select_next_proto| is an optional +// utility function which may be useful in implementing this callback. // // The callback is passed a wire-format (i.e. a series of non-empty, 8-bit // length-prefixed strings) ALPN protocol list in |in|. To select a protocol, @@ -3265,30 +3271,50 @@ OPENSSL_EXPORT int SSL_CTX_add_cert_compression_alg( // and deprecated in favor of it. // SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when a -// TLS server needs a list of supported protocols for Next Protocol -// Negotiation. The returned list must be in wire format. The list is returned -// by setting |*out| to point to it and |*out_len| to its length. This memory -// will not be modified, but one should assume that |ssl| keeps a reference to -// it. +// TLS server needs a list of supported protocols for Next Protocol Negotiation. // -// The callback should return |SSL_TLSEXT_ERR_OK| if it wishes to advertise. -// Otherwise, no such extension will be included in the ServerHello. +// If the callback wishes to advertise NPN to the client, it should return +// |SSL_TLSEXT_ERR_OK| and then set |*out| and |*out_len| to describe to a +// buffer containing a (possibly empty) list of supported protocols in wire +// format. That is, each protocol is prefixed with a 1-byte length, then +// concatenated. From there, the client will select a protocol, possibly one not +// on the server's list. The caller can use |SSL_get0_next_proto_negotiated| +// after the handshake completes to query the final protocol. +// +// The returned buffer must remain valid and unmodified for at least the +// duration of the |SSL| operation (e.g. |SSL_do_handshake|) that triggered the +// callback. +// +// If the caller wishes not to advertise NPN, it should return +// |SSL_TLSEXT_ERR_NOACK|. No NPN extension will be included in the ServerHello, +// and the TLS server will behave as if it does not implement NPN. OPENSSL_EXPORT void SSL_CTX_set_next_protos_advertised_cb( SSL_CTX *ctx, int (*cb)(SSL *ssl, const uint8_t **out, unsigned *out_len, void *arg), void *arg); // SSL_CTX_set_next_proto_select_cb sets a callback that is called when a client -// needs to select a protocol from the server's provided list. |*out| must be -// set to point to the selected protocol (which may be within |in|). The length -// of the protocol name must be written into |*out_len|. The server's advertised -// protocols are provided in |in| and |in_len|. The callback can assume that -// |in| is syntactically valid. +// needs to select a protocol from the server's provided list, passed in wire +// format in |in_len| bytes from |in|. The callback can assume that |in| is +// syntactically valid. |SSL_select_next_proto| is an optional utility function +// which may be useful in implementing this callback. // -// The client must select a protocol. It is fatal to the connection if this -// callback returns a value other than |SSL_TLSEXT_ERR_OK|. +// On success, the callback should return |SSL_TLSEXT_ERR_OK| and set |*out| and +// |*out_len| to describe a buffer containing the selected protocol, or an +// empty buffer to select no protocol. The returned buffer may point within +// |in|, or it may point to some other buffer that remains valid and unmodified +// for at least the duration of the |SSL| operation (e.g. |SSL_do_handshake|) +// that triggered the callback. // -// Configuring this callback enables NPN on a client. +// Returning any other value indicates a fatal error and will terminate the TLS +// connection. To proceed without selecting a protocol, the callback must return +// |SSL_TLSEXT_ERR_OK| and set |*out| and |*out_len| to an empty buffer. (E.g. +// NULL and zero, respectively.) +// +// Configuring this callback enables NPN on a client. Although the callback can +// then decline to negotiate a protocol, merely configuring the callback causes +// the client to offer NPN in the ClientHello. Callers thus should not configure +// this callback in TLS client contexts that are not intended to use NPN. OPENSSL_EXPORT void SSL_CTX_set_next_proto_select_cb( SSL_CTX *ctx, int (*cb)(SSL *ssl, uint8_t **out, uint8_t *out_len, const uint8_t *in, unsigned in_len, void *arg), @@ -3296,7 +3322,7 @@ OPENSSL_EXPORT void SSL_CTX_set_next_proto_select_cb( // SSL_get0_next_proto_negotiated sets |*out_data| and |*out_len| to point to // the client's requested protocol for this connection. If the client didn't -// request any protocol, then |*out_data| is set to NULL. +// request any protocol, then |*out_len| is set to zero. // // Note that the client can request any protocol it chooses. The value returned // from this function need not be a member of the list of supported protocols @@ -3305,21 +3331,45 @@ OPENSSL_EXPORT void SSL_get0_next_proto_negotiated(const SSL *ssl, const uint8_t **out_data, unsigned *out_len); -// SSL_select_next_proto implements the standard protocol selection. It is -// expected that this function is called from the callback set by +// SSL_select_next_proto implements the standard protocol selection for either +// ALPN servers or NPN clients. It is expected that this function is called from +// the callback set by |SSL_CTX_set_alpn_select_cb| or // |SSL_CTX_set_next_proto_select_cb|. // -// |peer| and |supported| must be vectors of 8-bit, length-prefixed byte strings -// containing the peer and locally-configured protocols, respectively. The -// length byte itself is not included in the length. A byte string of length 0 -// is invalid. No byte string may be truncated. |supported| is assumed to be -// non-empty. -// -// This function finds the first protocol in |peer| which is also in -// |supported|. If one was found, it sets |*out| and |*out_len| to point to it -// and returns |OPENSSL_NPN_NEGOTIATED|. Otherwise, it returns +// |peer| and |supported| contain the peer and locally-configured protocols, +// respectively. This function finds the first protocol in |peer| which is also +// in |supported|. If one was found, it sets |*out| and |*out_len| to point to +// it and returns |OPENSSL_NPN_NEGOTIATED|. Otherwise, it returns // |OPENSSL_NPN_NO_OVERLAP| and sets |*out| and |*out_len| to the first // supported protocol. +// +// In ALPN, the server should only select protocols among those that the client +// offered. Thus, if this function returns |OPENSSL_NPN_NO_OVERLAP|, the caller +// should ignore |*out| and return |SSL_TLSEXT_ERR_ALERT_FATAL| from +// |SSL_CTX_set_alpn_select_cb|'s callback to indicate there was no match. +// +// In NPN, the client may either select one of the server's protocols, or an +// "opportunistic" protocol as described in Section 6 of +// draft-agl-tls-nextprotoneg-03. When this function returns +// |OPENSSL_NPN_NO_OVERLAP|, |*out| implicitly selects the first supported +// protocol for use as the opportunistic protocol. The caller may use it, +// ignore it and select a different opportunistic protocol, or ignore it and +// select no protocol (empty string). +// +// |peer| and |supported| must be vectors of 8-bit, length-prefixed byte +// strings. The length byte itself is not included in the length. A byte string +// of length 0 is invalid. No byte string may be truncated. |supported| must be +// non-empty; a caller that supports no ALPN/NPN protocols should skip +// negotiating the extension, rather than calling this function. If any of these +// preconditions do not hold, this function will return |OPENSSL_NPN_NO_OVERLAP| +// and set |*out| and |*out_len| to an empty buffer for robustness, but callers +// are not recommended to rely on this. An empty buffer is not a valid output +// for |SSL_CTX_set_alpn_select_cb|'s callback. +// +// WARNING: |*out| and |*out_len| may alias either |peer| or |supported| and may +// not be used after one of those buffers is modified or released. Additionally, +// this function is not const-correct for compatibility reasons. Although |*out| +// is a non-const pointer, callers may not modify the buffer though |*out|. OPENSSL_EXPORT int SSL_select_next_proto(uint8_t **out, uint8_t *out_len, const uint8_t *peer, unsigned peer_len, const uint8_t *supported, @@ -4814,7 +4864,7 @@ OPENSSL_EXPORT void SSL_set_check_ecdsa_curve(SSL *ssl, int enable); // Deprecated functions. -// SSL_library_init calls |CRYPTO_library_init| and returns one. +// SSL_library_init returns one. OPENSSL_EXPORT int SSL_library_init(void); // SSL_CIPHER_description writes a description of |cipher| into |buf| and @@ -5377,7 +5427,7 @@ OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl); #define OPENSSL_INIT_LOAD_SSL_STRINGS 0 #define OPENSSL_INIT_SSL_DEFAULT 0 -// OPENSSL_init_ssl calls |CRYPTO_library_init| and returns one. +// OPENSSL_init_ssl returns one. OPENSSL_EXPORT int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); diff --git a/naiveproxy/src/third_party/boringssl/src/include/openssl/x509.h b/naiveproxy/src/third_party/boringssl/src/include/openssl/x509.h index a072d6f478..f5583d01e5 100644 --- a/naiveproxy/src/third_party/boringssl/src/include/openssl/x509.h +++ b/naiveproxy/src/third_party/boringssl/src/include/openssl/x509.h @@ -5294,29 +5294,6 @@ OPENSSL_EXPORT void X509_STORE_set_verify_cb( #define X509_STORE_set_verify_cb_func(store, func) \ X509_STORE_set_verify_cb((store), (func)) -typedef int (*X509_STORE_CTX_get_crl_fn)(X509_STORE_CTX *ctx, X509_CRL **crl, - X509 *x); -typedef int (*X509_STORE_CTX_check_crl_fn)(X509_STORE_CTX *ctx, X509_CRL *crl); - -// X509_STORE_set_get_crl override's |store|'s logic for looking up CRLs. -// -// Do not use this function. It is temporarily retained to support one caller -// and will be removed after that caller is fixed. It is not possible for -// external callers to correctly implement this callback. The real -// implementation sets some inaccessible internal state on |X509_STORE_CTX|. -OPENSSL_EXPORT void X509_STORE_set_get_crl(X509_STORE *store, - X509_STORE_CTX_get_crl_fn get_crl); - -// X509_STORE_set_check_crl override's |store|'s logic for checking CRL -// validity. -// -// Do not use this function. It is temporarily retained to support one caller -// and will be removed after that caller is fixed. It is not possible for -// external callers to correctly implement this callback. The real -// implementation relies some inaccessible internal state on |X509_STORE_CTX|. -OPENSSL_EXPORT void X509_STORE_set_check_crl( - X509_STORE *store, X509_STORE_CTX_check_crl_fn check_crl); - // X509_STORE_CTX_set_chain configures |ctx| to use |sk| for untrusted // intermediate certificates to use in verification. This function is redundant // with the |chain| parameter of |X509_STORE_CTX_init|. Use the parameter diff --git a/naiveproxy/src/third_party/boringssl/src/pki/cert_error_params.cc b/naiveproxy/src/third_party/boringssl/src/pki/cert_error_params.cc index 075d7ef33a..dd962c43f4 100644 --- a/naiveproxy/src/third_party/boringssl/src/pki/cert_error_params.cc +++ b/naiveproxy/src/third_party/boringssl/src/pki/cert_error_params.cc @@ -43,11 +43,8 @@ class CertErrorParams2Der : public CertErrorParams { static void AppendDer(const char *name, const std::string &der, std::string *out) { *out += name; - // TODO(crbug.com/boringssl/661): Introduce a convenience function to go - // from a Span to a Span. - *out += - ": " + bssl::string_util::HexEncode(MakeConstSpan( - reinterpret_cast(der.data()), der.size())); + *out += ": "; + *out += bssl::string_util::HexEncode(StringAsBytes(der)); } const char *name1_; diff --git a/naiveproxy/src/third_party/boringssl/src/pki/input.cc b/naiveproxy/src/third_party/boringssl/src/pki/input.cc index 156d2485b1..2f5a8b1620 100644 --- a/naiveproxy/src/third_party/boringssl/src/pki/input.cc +++ b/naiveproxy/src/third_party/boringssl/src/pki/input.cc @@ -10,9 +10,7 @@ namespace bssl::der { std::string Input::AsString() const { return std::string(AsStringView()); } -bool operator==(Input lhs, Input rhs) { - return MakeConstSpan(lhs) == MakeConstSpan(rhs); -} +bool operator==(Input lhs, Input rhs) { return Span(lhs) == Span(rhs); } bool operator!=(Input lhs, Input rhs) { return !(lhs == rhs); } diff --git a/naiveproxy/src/third_party/boringssl/src/pki/input.h b/naiveproxy/src/third_party/boringssl/src/pki/input.h index 30ce5d4afb..6ed79d9e06 100644 --- a/naiveproxy/src/third_party/boringssl/src/pki/input.h +++ b/naiveproxy/src/third_party/boringssl/src/pki/input.h @@ -42,16 +42,14 @@ class OPENSSL_EXPORT Input { // Creates an Input from the given |data| and |len|. constexpr explicit Input(const uint8_t *data, size_t len) - : data_(MakeConstSpan(data, len)) {} + : data_(Span(data, len)) {} // Deprecated: Use StringAsBytes. // // Creates an Input from a std::string_view. The constructed Input is only // valid as long as |data| points to live memory. If constructed from, say, a // |std::string|, mutating the vector will invalidate the Input. - explicit Input(std::string_view str) - : data_(MakeConstSpan(reinterpret_cast(str.data()), - str.size())) {} + explicit Input(std::string_view str) : data_(StringAsBytes(str)) {} // The following APIs have the same semantics as in |bssl::Span|. constexpr Span::iterator begin() const { diff --git a/naiveproxy/src/third_party/boringssl/src/pki/parse_name.cc b/naiveproxy/src/third_party/boringssl/src/pki/parse_name.cc index f1b3a91886..2c4695f31e 100644 --- a/naiveproxy/src/third_party/boringssl/src/pki/parse_name.cc +++ b/naiveproxy/src/third_party/boringssl/src/pki/parse_name.cc @@ -129,8 +129,7 @@ bool X509NameAttribute::AsRFC2253String(std::string *out) const { value_string += c; } else if (c < 32 || c > 126) { nonprintable = true; - value_string += - "\\" + bssl::string_util::HexEncode(MakeConstSpan(&c, 1)); + value_string += "\\" + bssl::string_util::HexEncode(Span(&c, 1)); } else { value_string += c; } diff --git a/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/google-intermediate1.der b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/google-intermediate1.der new file mode 100644 index 0000000000..d3c07efa54 Binary files /dev/null and b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/google-intermediate1.der differ diff --git a/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/google-intermediate2.der b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/google-intermediate2.der new file mode 100644 index 0000000000..82e5004698 Binary files /dev/null and b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/google-intermediate2.der differ diff --git a/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-intermediate-r3.der b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-intermediate-r3.der new file mode 100644 index 0000000000..2d66ea723e Binary files /dev/null and b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-intermediate-r3.der differ diff --git a/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-leaf.der b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-leaf.der new file mode 100644 index 0000000000..4dbed56cf4 Binary files /dev/null and b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-leaf.der differ diff --git a/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-dst-x3.der b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-dst-x3.der new file mode 100644 index 0000000000..95500f6bd1 Binary files /dev/null and b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-dst-x3.der differ diff --git a/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der new file mode 100644 index 0000000000..79a33ba590 Binary files /dev/null and b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-x1-cross-signed.der differ diff --git a/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-x1.der b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-x1.der new file mode 100644 index 0000000000..9d2132e7f1 Binary files /dev/null and b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/lencr-root-x1.der differ diff --git a/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/mozilla_roots.der b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/mozilla_roots.der new file mode 100644 index 0000000000..f89eec4c2b Binary files /dev/null and b/naiveproxy/src/third_party/boringssl/src/pki/testdata/verify_unittest/mozilla_roots.der differ diff --git a/naiveproxy/src/third_party/boringssl/src/pki/verify.cc b/naiveproxy/src/third_party/boringssl/src/pki/verify.cc new file mode 100644 index 0000000000..6bd9dc2d3d --- /dev/null +++ b/naiveproxy/src/third_party/boringssl/src/pki/verify.cc @@ -0,0 +1,354 @@ +/* Copyright (c) 2023, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "cert_errors.h" +#include "cert_issuer_source_static.h" +#include "certificate_policies.h" +#include "common_cert_errors.h" +#include "encode_values.h" +#include "input.h" +#include "parse_certificate.h" +#include "parse_values.h" +#include "parsed_certificate.h" +#include "path_builder.h" +#include "simple_path_builder_delegate.h" +#include "trust_store.h" +#include "trust_store_in_memory.h" +#include "verify_certificate_chain.h" + +namespace bssl { + +namespace { + +std::optional> +InternalParseCertificate(Span cert, std::string *out_diagnostic) { + ParseCertificateOptions default_options{}; + // We follow Chromium in setting |allow_invalid_serial_numbers| in order to + // not choke on 21-byte serial numbers, which are common. + // + // The reason for the discrepancy is that unsigned numbers with the high bit + // otherwise set get an extra 0 byte in front to keep them positive. So if you + // do: + // var num [20]byte + // fillWithRandom(num[:]) + // serialNumber := new(big.Int).SetBytes(num[:]) + // encodeASN1Integer(serialNumber) + // + // Then half of your serial numbers will be encoded with 21 bytes. (And + // 1/512th will have 19 bytes instead of 20.) + default_options.allow_invalid_serial_numbers = true; + + UniquePtr buffer( + CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr)); + CertErrors errors; + std::shared_ptr parsed_cert( + ParsedCertificate::Create(std::move(buffer), default_options, &errors)); + if (!parsed_cert) { + *out_diagnostic = errors.ToDebugString(); + return {}; + } + return parsed_cert; +} +} // namespace + + +CertPool::CertPool() {} + +CertificateVerifyOptions::CertificateVerifyOptions() {} + +static std::unique_ptr WrapTrustStore( + std::unique_ptr trust_store) { + std::unique_ptr ret(new VerifyTrustStore); + ret->trust_store = std::move(trust_store); + return ret; +} + +VerifyTrustStore::~VerifyTrustStore() {} + +std::unique_ptr VerifyTrustStore::FromDER( + std::string_view der_certs, std::string *out_diagnostic) { + auto store = std::make_unique(); + CBS cbs = StringAsBytes(der_certs); + + for (size_t cert_num = 1; CBS_len(&cbs) != 0; cert_num++) { + CBS cert; + if (!CBS_get_asn1_element(&cbs, &cert, CBS_ASN1_SEQUENCE)) { + *out_diagnostic = "failed to get ASN.1 SEQUENCE from input at cert " + + std::to_string(cert_num); + return {}; + } + + auto parsed_cert = InternalParseCertificate(cert, out_diagnostic); + if (!parsed_cert.has_value()) { + return {}; + } + store->AddTrustAnchor(parsed_cert.value()); + } + + return WrapTrustStore(std::move(store)); +} + +std::unique_ptr VerifyTrustStore::FromDER( + const std::vector &der_roots, + std::string *out_diagnostic) { + auto store = std::make_unique(); + + for (const std::string_view &cert : der_roots) { + auto parsed_cert = InternalParseCertificate(StringAsBytes(cert), out_diagnostic); + if (!parsed_cert.has_value()) { + return {}; + } + store->AddTrustAnchor(parsed_cert.value()); + } + + return WrapTrustStore(std::move(store)); +} + +CertPool::~CertPool() {} + + +std::unique_ptr CertPool::FromCerts( + const std::vector &der_certs, + std::string *out_diagnostic) { + auto pool = std::make_unique(); + pool->impl_ = std::make_unique(); + + for (const std::string_view &cert : der_certs) { + auto parsed_cert = + InternalParseCertificate(StringAsBytes(cert), out_diagnostic); + if (!parsed_cert.has_value()) { + return {}; + } + pool->impl_->AddCert(std::move(parsed_cert.value())); + } + + return pool; +} + +CertificateVerifyStatus::CertificateVerifyStatus() {} + +size_t CertificateVerifyStatus::IterationCount() const { + return iteration_count_; +} + +size_t CertificateVerifyStatus::MaxDepthSeen() const { return max_depth_seen_; } + +// PathBuilderDelegateImpl implements a deadline and allows for the +// use of a SignatureVerifyCache if an implementation is provided. +class PathBuilderDelegateImpl : public SimplePathBuilderDelegate { + public: + PathBuilderDelegateImpl( + size_t min_rsa_modulus_length_bits, DigestPolicy digest_policy, + std::chrono::time_point deadline, + SignatureVerifyCache *cache) + : SimplePathBuilderDelegate(min_rsa_modulus_length_bits, digest_policy), + deadline_(deadline), + cache_(cache) {} + + bool IsDeadlineExpired() override { + return (std::chrono::steady_clock::now() > deadline_); + } + + SignatureVerifyCache *GetVerifyCache() override { return cache_; } + + private: + const std::chrono::time_point deadline_; + SignatureVerifyCache *cache_; +}; + +std::optional>> CertificateVerifyInternal( + const CertificateVerifyOptions &opts, VerifyError *out_error, + CertificateVerifyStatus *out_status, bool all_paths) { + VerifyError dummy; + if (!out_error) { + out_error = &dummy; + } + if (out_status != nullptr) { + out_status->iteration_count_ = 0; + out_status->max_depth_seen_ = 0; + } + + std::string diagnostic; + std::optional> maybe_leaf = + InternalParseCertificate(StringAsBytes(opts.leaf_cert), &diagnostic); + + if (!maybe_leaf.has_value()) { + *out_error = {VerifyError::StatusCode::CERTIFICATE_INVALID, 0, diagnostic}; + return {}; + } + std::shared_ptr leaf_cert = maybe_leaf.value(); + + int64_t now; + if (opts.time.has_value()) { + now = opts.time.value(); + } else { + now = time(NULL); + } + + der::GeneralizedTime verification_time; + if (!der::EncodePosixTimeAsGeneralizedTime(now, &verification_time)) { + *out_error = {VerifyError::StatusCode::VERIFICATION_FAILURE, -1, + "\nCould not encode verification time\n"}; + return {}; + } + + TrustStore *trust_store = nullptr; + if (opts.trust_store) { + trust_store = opts.trust_store->trust_store.get(); + } + + auto digest_policy = SimplePathBuilderDelegate::DigestPolicy::kStrong; + // TODO(b/111551631): remove this + if (opts.insecurely_allow_sha1) { + digest_policy = SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1; + } + + std::chrono::time_point deadline = + std::chrono::time_point::max(); + if (opts.deadline.has_value()) { + deadline = opts.deadline.value(); + } + + PathBuilderDelegateImpl path_builder_delegate( + opts.min_rsa_modulus_length, digest_policy, deadline, + opts.signature_verify_cache); + + KeyPurpose key_purpose = KeyPurpose::SERVER_AUTH; + switch (opts.key_purpose) { + case CertificateVerifyOptions::KeyPurpose::ANY_EKU: + key_purpose = KeyPurpose::ANY_EKU; + break; + case CertificateVerifyOptions::KeyPurpose::SERVER_AUTH: + key_purpose = KeyPurpose::SERVER_AUTH; + break; + case CertificateVerifyOptions::KeyPurpose::CLIENT_AUTH: + key_purpose = KeyPurpose::CLIENT_AUTH; + break; + case CertificateVerifyOptions::KeyPurpose::SERVER_AUTH_STRICT: + key_purpose = KeyPurpose::SERVER_AUTH_STRICT; + break; + case CertificateVerifyOptions::KeyPurpose::CLIENT_AUTH_STRICT: + key_purpose = KeyPurpose::CLIENT_AUTH_STRICT; + break; + case CertificateVerifyOptions::KeyPurpose::SERVER_AUTH_STRICT_LEAF: + key_purpose = KeyPurpose::SERVER_AUTH_STRICT_LEAF; + break; + case CertificateVerifyOptions::KeyPurpose::CLIENT_AUTH_STRICT_LEAF: + key_purpose = KeyPurpose::CLIENT_AUTH_STRICT_LEAF; + break; + } + CertPathBuilder path_builder(leaf_cert, trust_store, &path_builder_delegate, + verification_time, key_purpose, + InitialExplicitPolicy::kFalse, + /* user_initial_policy_set= */ + {der::Input(kAnyPolicyOid)}, + InitialPolicyMappingInhibit::kFalse, + InitialAnyPolicyInhibit::kFalse); + + CertIssuerSourceStatic intermediates; + for (const std::string_view &cert : opts.intermediates) { + std::string diag_string; + std::optional> parsed = + InternalParseCertificate(StringAsBytes(cert), &diag_string); + if (!parsed.has_value()) { + if (path_builder_delegate.IsDebugLogEnabled()) { + path_builder_delegate.DebugLog("skipping bad intermediate: " + + diag_string); + } + continue; + } + intermediates.AddCert(std::move(parsed.value())); + } + path_builder.AddCertIssuerSource(&intermediates); + + if (opts.extra_intermediates != nullptr) { + path_builder.AddCertIssuerSource(opts.extra_intermediates->impl_.get()); + } + + if (opts.max_iteration_count > 0) { + path_builder.SetIterationLimit(opts.max_iteration_count); + } + + if (opts.max_path_building_depth > 0) { + path_builder.SetDepthLimit(opts.max_path_building_depth); + } + + path_builder.SetExploreAllPaths(all_paths); + + CertPathBuilder::Result result = path_builder.Run(); + + if (out_status != nullptr) { + out_status->iteration_count_ = result.iteration_count; + out_status->max_depth_seen_ = result.max_depth_seen; + } + + *out_error = result.GetBestPathVerifyError(); + + if (result.HasValidPath()) { + std::vector> ret; + if (!all_paths) { + auto best_path = result.GetBestValidPath(); + ret.push_back(std::vector()); + for (size_t i = 0; i < best_path->certs.size(); i++) { + ret[0].emplace_back(BytesAsStringView(best_path->certs[i]->der_cert())); + } + return ret; + } + for (const auto &path : result.paths) { + if (!path->IsValid()) { + continue; + } + std::vector ret_path; + for (const auto &cert : path->certs) { + ret_path.emplace_back(BytesAsStringView(cert->der_cert())); + } + ret.push_back(ret_path); + } + return ret; + } + + return {}; +} + +std::optional> CertificateVerify( + const CertificateVerifyOptions &opts, VerifyError *out_error, + CertificateVerifyStatus *out_status) { + auto single_path = CertificateVerifyInternal(opts, out_error, out_status, + /*all_paths=*/false); + if (!single_path.has_value()) { + return {}; + } + return single_path.value()[0]; +} + +std::optional>> CertificateVerifyAllPaths( + const CertificateVerifyOptions &opts) { + return CertificateVerifyInternal(opts, nullptr, nullptr, /*all_paths=*/true); +} + +} // namespace bssl diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/hkdf.rs b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/hkdf.rs index 973ed88af6..532468f9e9 100644 --- a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/hkdf.rs +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/hkdf.rs @@ -63,6 +63,20 @@ //! //! assert_eq!(out, HkdfSha256::derive(b"secret", hkdf::Salt::None, b"info")); //! ``` +//! +//! To expand output from the explicit bytes of a PRK, use `Prk::new`: +//! +//! ``` +//! use bssl_crypto::{digest::Sha256, digest::Algorithm, hkdf}; +//! +//! let prk: [u8; Sha256::OUTPUT_LEN] = bssl_crypto::rand_array(); +//! // unwrap: only fails if the input is not equal to the digest length, which +//! // cannot happen here. +//! let prk = hkdf::Prk::new::(&prk).unwrap(); +//! let mut out = vec![0u8; 42]; +//! prk.expand_into(b"info", &mut out)?; +//! # Ok::<(), hkdf::TooLong>(()) +//! ``` use crate::{digest, sealed, with_output_array, FfiMutSlice, FfiSlice, ForeignTypeRef}; use core::marker::PhantomData; @@ -173,6 +187,33 @@ pub struct Prk { #[allow(clippy::let_unit_value)] impl Prk { + /// Creates a Prk from bytes. + pub fn new(prk_bytes: &[u8]) -> Option { + if prk_bytes.len() != MD::OUTPUT_LEN { + return None; + } + + let mut prk = [0u8; bssl_sys::EVP_MAX_MD_SIZE as usize]; + prk.get_mut(..MD::OUTPUT_LEN) + // unwrap: `EVP_MAX_MD_SIZE` must be greater than the length of any + // digest function thus this is always successful. + .unwrap() + .copy_from_slice(prk_bytes); + + Some(Prk { + prk, + len: MD::OUTPUT_LEN, + evp_md: MD::get_md(sealed::Sealed).as_ptr(), + }) + } + + /// Returns the bytes of the pseudorandom key. + pub fn as_bytes(&self) -> &[u8] { + // `self.len` must be less than the length of `self.prk` thus + // this is always in bounds. + &self.prk[..self.len] + } + /// Derive key material for the given info parameter. Attempting /// to derive more than 255 bytes is a compile-time error, see `expand_into` /// for longer outputs. @@ -243,7 +284,8 @@ impl Prk { )] mod tests { use crate::{ - hkdf::{HkdfSha256, HkdfSha512, Salt}, + digest::Sha256, + hkdf::{HkdfSha256, HkdfSha512, Prk, Salt}, test_helpers::{decode_hex, decode_hex_into_vec}, }; @@ -280,6 +322,7 @@ mod tests { ikm: Vec, salt: Vec, info: Vec, + prk: Vec, okm: Vec, } let tests = [ @@ -288,6 +331,10 @@ mod tests { ikm: decode_hex_into_vec("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), salt: decode_hex_into_vec("000102030405060708090a0b0c"), info: decode_hex_into_vec("f0f1f2f3f4f5f6f7f8f9"), + prk: decode_hex_into_vec( + "077709362c2e32df0ddc3f0dc47bba63\ + 90b6c73bb50f9c3122ec844ad7c2b3e5", + ), okm: decode_hex_into_vec("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") }, Test { @@ -313,6 +360,10 @@ mod tests { e0e1e2e3e4e5e6e7e8e9eaebecedeeef\ f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", ), + prk: decode_hex_into_vec( + "06a6b88c5853361a06104c9ceb35b45c\ + ef760014904671014a193f40c15fc244", + ), okm: decode_hex_into_vec( "b11e398dc80327a1c8e7f78c596a4934\ 4f012eda2d4efad8a050cc4c19afa97c\ @@ -327,6 +378,10 @@ mod tests { ikm: decode_hex_into_vec("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), salt: Vec::new(), info: Vec::new(), + prk: decode_hex_into_vec( + "19ef24a32c717b167f33a91d6f648bdf\ + 96596776afdb6377ac434c1c293ccb04", + ), okm: decode_hex_into_vec( "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"), }, @@ -336,6 +391,7 @@ mod tests { ikm, salt, info, + prk, okm, } in tests.iter() { @@ -349,6 +405,12 @@ mod tests { HkdfSha256::derive_into(ikm.as_slice(), salt, info.as_slice(), &mut okm2).is_ok() ); assert_eq!(okm2.as_slice(), okm.as_slice()); + + let prk2 = Prk::new::(prk.as_slice()).unwrap(); + assert_eq!(prk2.as_bytes(), prk.as_slice()); + let mut okm3 = vec![0u8; okm.len()]; + let _ = prk2.expand_into(info.as_slice(), &mut okm3); + assert_eq!(okm3.as_slice(), okm.as_slice()); } } @@ -361,4 +423,16 @@ mod tests { let mut too_long = vec![0u8; HkdfSha256::MAX_OUTPUT_LEN + 1]; assert!(hkdf.expand_into(b"", &mut too_long).is_err()); } + + #[test] + fn wrong_prk_len() { + assert!(Prk::new::( + decode_hex_into_vec("077709362c2e32df0ddc3f0dc47bba63").as_slice() + ) + .is_none()); + assert!(Prk::new::( + decode_hex_into_vec("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e590b6c73bb50f9c3122ec844ad7c2b3e5").as_slice()) + .is_none() + ); + } } diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/hpke.rs b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/hpke.rs index 2725b3f34f..e3a61bc635 100644 --- a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/hpke.rs +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/hpke.rs @@ -65,6 +65,12 @@ //! //! let received_plaintext2 = recipient_ctx.open(&msg2, aad); //! assert!(received_plaintext2.is_none()); +//! +//! // There is also an interface for exporting secrets from both sender +//! // and recipient contexts. +//! let sender_export = sender_ctx.export(b"ctx", 32); +//! let recipient_export = recipient_ctx.export(b"ctx", 32); +//! assert_eq!(sender_export, recipient_export); //! ``` use crate::{scoped, with_output_vec, with_output_vec_fallible, FfiSlice}; @@ -294,6 +300,28 @@ impl SenderContext { }) } } + + /// Exports a secret of length `out_len` from the HPKE context using `context` as the context + /// string. + pub fn export(&mut self, context: &[u8], out_len: usize) -> Vec { + unsafe { + with_output_vec(out_len, |out_buf| { + // Safety: EVP_HPKE_CTX_export + // - is called with context created from EVP_HPKE_CTX_new, + // - is called with valid buffers with corresponding pointer and length, and + // - returns 0 on error, which only occurs when OOM. + let ret = bssl_sys::EVP_HPKE_CTX_export( + self.0.as_mut_ffi_ptr(), + out_buf, + out_len, + context.as_ffi_ptr(), + context.len(), + ); + assert_eq!(ret, 1); + out_len + }) + } + } } /// HPKE recipient context. Callers may use `open()` to decrypt messages from the sender. @@ -385,6 +413,28 @@ impl RecipientContext { }) } } + + /// Exports a secret of length `out_len` from the HPKE context using `context` as the context + /// string. + pub fn export(&mut self, context: &[u8], out_len: usize) -> Vec { + unsafe { + with_output_vec(out_len, |out_buf| { + // Safety: EVP_HPKE_CTX_export + // - is called with context created from EVP_HPKE_CTX_new, + // - is called with valid buffers with corresponding pointer and length, and + // - returns 0 on error, which only occurs when OOM. + let ret = bssl_sys::EVP_HPKE_CTX_export( + self.0.as_mut_ffi_ptr(), + out_buf, + out_len, + context.as_ffi_ptr(), + context.len(), + ); + assert_eq!(ret, 1); + out_len + }) + } + } } #[cfg(test)] @@ -404,6 +454,8 @@ mod test { plaintext: [u8; 29], // pt associated_data: [u8; 7], // aad ciphertext: [u8; 45], // ct + exporter_context: [u8; 11], + exported_value: [u8; 32], } // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1 @@ -420,6 +472,8 @@ mod test { plaintext: decode_hex("4265617574792069732074727574682c20747275746820626561757479"), associated_data: decode_hex("436f756e742d30"), ciphertext: decode_hex("f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a"), + exporter_context: decode_hex("54657374436f6e74657874"), + exported_value: decode_hex("e9e43065102c3836401bed8c3c3c75ae46be1639869391d62c61f1ec7af54931"), } } @@ -437,6 +491,8 @@ mod test { plaintext: decode_hex("4265617574792069732074727574682c20747275746820626561757479"), associated_data: decode_hex("436f756e742d30"), ciphertext: decode_hex("1c5250d8034ec2b784ba2cfd69dbdb8af406cfe3ff938e131f0def8c8b60b4db21993c62ce81883d2dd1b51a28"), + exporter_context: decode_hex("54657374436f6e74657874"), + exported_value: decode_hex("5acb09211139c43b3090489a9da433e8a30ee7188ba8b0a9a1ccf0c229283e53"), } } @@ -562,6 +618,38 @@ mod test { } } + #[test] + fn export_with_vector() { + for test in vec![ + x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm(), + x25519_hkdf_sha256_hkdf_sha256_chacha20_poly1305(), + ] { + let params = Params::new_from_rfc_ids(test.kem_id, test.kdf_id, test.aead_id).unwrap(); + + let (mut sender_ctx, _encapsulated_key) = new_sender_context_for_testing( + ¶ms, + &test.recipient_pub_key, + &test.info, + &test.seed_for_testing, + ); + assert_eq!( + test.exported_value.as_ref(), + sender_ctx.export(&test.exporter_context, test.exported_value.len()) + ); + + let mut recipient_ctx = RecipientContext::new( + ¶ms, + &test.recipient_priv_key, + &test.encapsulated_key, + &test.info, + ).unwrap(); + assert_eq!( + test.exported_value.as_ref(), + recipient_ctx.export(&test.exporter_context, test.exported_value.len()) + ); + } + } + #[test] fn disallowed_params_fail() { let vec: TestVector = x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm(); diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/scoped.rs b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/scoped.rs index 8c6b21b564..67bf301067 100644 --- a/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/scoped.rs +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-crypto/src/scoped.rs @@ -69,6 +69,9 @@ impl Drop for EcKey { /// A scoped `EVP_HPKE_CTX`. pub struct EvpHpkeCtx(*mut bssl_sys::EVP_HPKE_CTX); +// bssl_sys::EVP_HPKE_CTX is heap-allocated and safe to transfer +// between threads. +unsafe impl Send for EvpHpkeCtx {} impl EvpHpkeCtx { pub fn new() -> Self { diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/rust_wrapper.c b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/rust_wrapper.c index d5419a9a6c..d77bc34f35 100644 --- a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/rust_wrapper.c +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/rust_wrapper.c @@ -26,3 +26,11 @@ int ERR_GET_REASON_RUST(uint32_t packed_error) { int ERR_GET_FUNC_RUST(uint32_t packed_error) { return ERR_GET_FUNC(packed_error); } + +void CBS_init_RUST(CBS *cbs, const uint8_t *data, size_t len) { + CBS_init(cbs, data, len); +} + +size_t CBS_len_RUST(const CBS *cbs) { + return CBS_len(cbs); +} diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/rust_wrapper.h b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/rust_wrapper.h index 55d5a6f259..060bf7e735 100644 --- a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/rust_wrapper.h +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/rust_wrapper.h @@ -16,6 +16,7 @@ #define OPENSSL_HEADER_RUST_WRAPPER_H #include +#include #if defined(__cplusplus) extern "C" { @@ -30,7 +31,8 @@ extern "C" { int ERR_GET_LIB_RUST(uint32_t packed_error); int ERR_GET_REASON_RUST(uint32_t packed_error); int ERR_GET_FUNC_RUST(uint32_t packed_error); - +void CBS_init_RUST(CBS *cbs, const uint8_t *data, size_t len); +size_t CBS_len_RUST(const CBS *cbs); #if defined(__cplusplus) } // extern C diff --git a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/src/lib.rs b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/src/lib.rs index e7f5fc48da..2d313af1b7 100644 --- a/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/src/lib.rs +++ b/naiveproxy/src/third_party/boringssl/src/rust/bssl-sys/src/lib.rs @@ -48,26 +48,13 @@ pub const XN_FLAG_ONELINE: c_ulong = bindgen::XN_FLAG_ONELINE as c_ulong; // TODO(crbug.com/boringssl/596): Remove these wrappers. #[cfg(unsupported_inline_wrappers)] -pub fn ERR_GET_LIB(packed_error: u32) -> i32 { - // Safety: This is safe for all inputs. bindgen conservatively marks everything unsafe. - unsafe { ERR_GET_LIB_RUST(packed_error) } -} - -#[cfg(unsupported_inline_wrappers)] -pub fn ERR_GET_REASON(packed_error: u32) -> i32 { - // Safety: This is safe for all inputs. bindgen conservatively marks everything unsafe. - unsafe { ERR_GET_REASON_RUST(packed_error) } -} - -#[cfg(unsupported_inline_wrappers)] -pub fn ERR_GET_FUNC(packed_error: u32) -> i32 { - // Safety: This is safe for all inputs. bindgen conservatively marks everything unsafe. - unsafe { ERR_GET_FUNC_RUST(packed_error) } -} +pub use { ERR_GET_LIB_RUST as ERR_GET_LIB, + ERR_GET_REASON_RUST as ERR_GET_REASON, + ERR_GET_FUNC_RUST as ERR_GET_FUNC, + CBS_init_RUST as CBS_init, + CBS_len_RUST as CBS_len }; pub fn init() { - // Safety: `CRYPTO_library_init` may be called multiple times and concurrently. - unsafe { - CRYPTO_library_init(); - } + // This function does nothing. + // TODO(davidben): Remove rust-openssl's dependency on this and remove this. } diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/extensions.cc b/naiveproxy/src/third_party/boringssl/src/ssl/extensions.cc index 20a5d3034e..3f35276acc 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/extensions.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/extensions.cc @@ -441,16 +441,18 @@ bool tls12_add_verify_sigalgs(const SSL_HANDSHAKE *hs, CBB *out) { } bool tls12_check_peer_sigalg(const SSL_HANDSHAKE *hs, uint8_t *out_alert, - uint16_t sigalg) { - for (uint16_t verify_sigalg : tls12_get_verify_sigalgs(hs)) { - if (verify_sigalg == sigalg) { - return true; - } + uint16_t sigalg, EVP_PKEY *pkey) { + // The peer must have selected an algorithm that is consistent with its public + // key, the TLS version, and what we advertised. + Span sigalgs = tls12_get_verify_sigalgs(hs); + if (std::find(sigalgs.begin(), sigalgs.end(), sigalg) == sigalgs.end() || + !ssl_pkey_supports_algorithm(hs->ssl, pkey, sigalg, /*is_verify=*/true)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return false; } - OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return false; + return true; } // tls_extension represents a TLS extension that is handled internally. @@ -1474,16 +1476,19 @@ bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs, } // Check that the protocol name is one of the ones we advertised. - CBS client_protocol_name_list = - MakeConstSpan(hs->config->alpn_client_proto_list), - client_protocol_name; - while (CBS_len(&client_protocol_name_list) > 0) { - if (!CBS_get_u8_length_prefixed(&client_protocol_name_list, - &client_protocol_name)) { + return ssl_alpn_list_contains_protocol(hs->config->alpn_client_proto_list, + protocol); +} + +bool ssl_alpn_list_contains_protocol(Span list, + Span protocol) { + CBS cbs = list, candidate; + while (CBS_len(&cbs) > 0) { + if (!CBS_get_u8_length_prefixed(&cbs, &candidate)) { return false; } - if (client_protocol_name == protocol) { + if (candidate == protocol) { return true; } } @@ -4144,7 +4149,8 @@ bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, ? MakeConstSpan(kSignSignatureAlgorithms) : cred->sigalgs; for (uint16_t sigalg : sigalgs) { - if (!ssl_pkey_supports_algorithm(ssl, cred->pubkey.get(), sigalg)) { + if (!ssl_pkey_supports_algorithm(ssl, cred->pubkey.get(), sigalg, + /*is_verify=*/false)) { continue; } diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/handshake_client.cc b/naiveproxy/src/third_party/boringssl/src/ssl/handshake_client.cc index b958dce23c..f674515826 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/handshake_client.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/handshake_client.cc @@ -1169,7 +1169,8 @@ static enum ssl_hs_wait_t do_read_server_key_exchange(SSL_HANDSHAKE *hs) { return ssl_hs_error; } uint8_t alert = SSL_AD_DECODE_ERROR; - if (!tls12_check_peer_sigalg(hs, &alert, signature_algorithm)) { + if (!tls12_check_peer_sigalg(hs, &alert, signature_algorithm, + hs->peer_pubkey.get())) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/handshake_server.cc b/naiveproxy/src/third_party/boringssl/src/ssl/handshake_server.cc index 1a25ea72d2..afa0927f36 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/handshake_server.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/handshake_server.cc @@ -1650,7 +1650,8 @@ static enum ssl_hs_wait_t do_read_client_certificate_verify(SSL_HANDSHAKE *hs) { return ssl_hs_error; } uint8_t alert = SSL_AD_DECODE_ERROR; - if (!tls12_check_peer_sigalg(hs, &alert, signature_algorithm)) { + if (!tls12_check_peer_sigalg(hs, &alert, signature_algorithm, + hs->peer_pubkey.get())) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/internal.h b/naiveproxy/src/third_party/boringssl/src/ssl/internal.h index a34033531d..2e4464163e 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/internal.h +++ b/naiveproxy/src/third_party/boringssl/src/ssl/internal.h @@ -1094,7 +1094,7 @@ enum ssl_private_key_result_t ssl_private_key_decrypt(SSL_HANDSHAKE *hs, // ssl_pkey_supports_algorithm returns whether |pkey| may be used to sign // |sigalg|. bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey, - uint16_t sigalg); + uint16_t sigalg, bool is_verify); // ssl_public_key_verify verifies that the |signature| is valid for the public // key |pkey| and input |in|, using the signature algorithm |sigalg|. @@ -2324,6 +2324,11 @@ bool ssl_is_valid_alpn_list(Span in); bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs, Span protocol); +// ssl_alpn_list_contains_protocol returns whether |list|, a serialized ALPN +// protocol list, contains |protocol|. +bool ssl_alpn_list_contains_protocol(Span list, + Span protocol); + // ssl_negotiate_alpn negotiates the ALPN extension, if applicable. It returns // true on successful negotiation or if nothing was negotiated. It returns false // and sets |*out_alert| to an alert on error. @@ -2449,10 +2454,10 @@ bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, bool tls12_add_verify_sigalgs(const SSL_HANDSHAKE *hs, CBB *out); // tls12_check_peer_sigalg checks if |sigalg| is acceptable for the peer -// signature. It returns true on success and false on error, setting +// signature from |pkey|. It returns true on success and false on error, setting // |*out_alert| to an alert to send. bool tls12_check_peer_sigalg(const SSL_HANDSHAKE *hs, uint8_t *out_alert, - uint16_t sigalg); + uint16_t sigalg, EVP_PKEY *pkey); // Underdocumented functions. diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_key_share.cc b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_key_share.cc index f4fda3fda2..419724c624 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_key_share.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_key_share.cc @@ -24,6 +24,7 @@ #include #include #include +#define OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER #include #include #include diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_lib.cc b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_lib.cc index ec0ee893e5..206a01640d 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_lib.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_lib.cc @@ -505,13 +505,9 @@ BSSL_NAMESPACE_END using namespace bssl; -int SSL_library_init(void) { - CRYPTO_library_init(); - return 1; -} +int SSL_library_init(void) { return 1; } int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) { - CRYPTO_library_init(); return 1; } @@ -2286,34 +2282,49 @@ int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) { int SSL_select_next_proto(uint8_t **out, uint8_t *out_len, const uint8_t *peer, unsigned peer_len, const uint8_t *supported, unsigned supported_len) { - const uint8_t *result; - int status; + *out = nullptr; + *out_len = 0; - // For each protocol in peer preference order, see if we support it. - for (unsigned i = 0; i < peer_len;) { - for (unsigned j = 0; j < supported_len;) { - if (peer[i] == supported[j] && - OPENSSL_memcmp(&peer[i + 1], &supported[j + 1], peer[i]) == 0) { - // We found a match - result = &peer[i]; - status = OPENSSL_NPN_NEGOTIATED; - goto found; - } - j += supported[j]; - j++; - } - i += peer[i]; - i++; + // Both |peer| and |supported| must be valid protocol lists, but |peer| may be + // empty in NPN. + auto peer_span = MakeConstSpan(peer, peer_len); + auto supported_span = MakeConstSpan(supported, supported_len); + if ((!peer_span.empty() && !ssl_is_valid_alpn_list(peer_span)) || + !ssl_is_valid_alpn_list(supported_span)) { + return OPENSSL_NPN_NO_OVERLAP; } - // There's no overlap between our protocols and the peer's list. - result = supported; - status = OPENSSL_NPN_NO_OVERLAP; + // For each protocol in peer preference order, see if we support it. + CBS cbs = peer_span, proto; + while (CBS_len(&cbs) != 0) { + if (!CBS_get_u8_length_prefixed(&cbs, &proto) || CBS_len(&proto) == 0) { + return OPENSSL_NPN_NO_OVERLAP; + } -found: - *out = (uint8_t *)result + 1; - *out_len = result[0]; - return status; + if (ssl_alpn_list_contains_protocol(MakeConstSpan(supported, supported_len), + proto)) { + // This function is not const-correct for compatibility with existing + // callers. + *out = const_cast(CBS_data(&proto)); + // A u8 length prefix will fit in |uint8_t|. + *out_len = static_cast(CBS_len(&proto)); + return OPENSSL_NPN_NEGOTIATED; + } + } + + // There's no overlap between our protocols and the peer's list. In ALPN, the + // caller is expected to fail the connection with no_application_protocol. In + // NPN, the caller is expected to opportunistically select the first protocol. + // See draft-agl-tls-nextprotoneg-04, section 6. + cbs = supported_span; + if (!CBS_get_u8_length_prefixed(&cbs, &proto) || CBS_len(&proto) == 0) { + return OPENSSL_NPN_NO_OVERLAP; + } + + // See above. + *out = const_cast(CBS_data(&proto)); + *out_len = static_cast(CBS_len(&proto)); + return OPENSSL_NPN_NO_OVERLAP; } void SSL_get0_next_proto_negotiated(const SSL *ssl, const uint8_t **out_data, diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_privkey.cc b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_privkey.cc index 9cf2c8f92c..471be768b3 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_privkey.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_privkey.cc @@ -85,29 +85,61 @@ typedef struct { int curve; const EVP_MD *(*digest_func)(void); bool is_rsa_pss; + bool tls12_ok; + bool tls13_ok; + bool client_only; } SSL_SIGNATURE_ALGORITHM; static const SSL_SIGNATURE_ALGORITHM kSignatureAlgorithms[] = { + // PKCS#1 v1.5 code points are only allowed in TLS 1.2. {SSL_SIGN_RSA_PKCS1_MD5_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_md5_sha1, - false}, - {SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1, false}, - {SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, false}, - {SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, false}, - {SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, false}, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false, + /*client_only=*/false}, + {SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false, + /*client_only=*/false}, + {SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false, + /*client_only=*/false}, + {SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false, + /*client_only=*/false}, + {SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false, + /*client_only=*/false}, - {SSL_SIGN_RSA_PSS_RSAE_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, true}, - {SSL_SIGN_RSA_PSS_RSAE_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, true}, - {SSL_SIGN_RSA_PSS_RSAE_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, true}, + // Legacy PKCS#1 v1.5 code points are only allowed in TLS 1.3 and + // client-only. See draft-ietf-tls-tls13-pkcs1-00. + {SSL_SIGN_RSA_PKCS1_SHA256_LEGACY, EVP_PKEY_RSA, NID_undef, &EVP_sha256, + /*is_rsa_pss=*/false, /*tls12_ok=*/false, /*tls13_ok=*/true, + /*client_only=*/true}, - {SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1, false}, + {SSL_SIGN_RSA_PSS_RSAE_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, + /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true, + /*client_only=*/false}, + {SSL_SIGN_RSA_PSS_RSAE_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, + /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true, + /*client_only=*/false}, + {SSL_SIGN_RSA_PSS_RSAE_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, + /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true, + /*client_only=*/false}, + + {SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false, + /*client_only=*/false}, {SSL_SIGN_ECDSA_SECP256R1_SHA256, EVP_PKEY_EC, NID_X9_62_prime256v1, - &EVP_sha256, false}, + &EVP_sha256, /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true, + /*client_only=*/false}, {SSL_SIGN_ECDSA_SECP384R1_SHA384, EVP_PKEY_EC, NID_secp384r1, &EVP_sha384, - false}, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true, + /*client_only=*/false}, {SSL_SIGN_ECDSA_SECP521R1_SHA512, EVP_PKEY_EC, NID_secp521r1, &EVP_sha512, - false}, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true, + /*client_only=*/false}, - {SSL_SIGN_ED25519, EVP_PKEY_ED25519, NID_undef, nullptr, false}, + {SSL_SIGN_ED25519, EVP_PKEY_ED25519, NID_undef, nullptr, + /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true, + /*client_only=*/false}, }; static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) { @@ -120,7 +152,7 @@ static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) { } bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey, - uint16_t sigalg) { + uint16_t sigalg, bool is_verify) { const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg); if (alg == NULL || EVP_PKEY_id(pkey) != alg->pkey_type) { return false; @@ -152,8 +184,12 @@ bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey, } if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { - // RSA keys may only be used with RSA-PSS. - if (alg->pkey_type == EVP_PKEY_RSA && !alg->is_rsa_pss) { + if (!alg->tls13_ok) { + return false; + } + + bool is_client_sign = ssl->server == is_verify; + if (alg->client_only && !is_client_sign) { return false; } @@ -164,6 +200,8 @@ bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey, EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey))) != alg->curve)) { return false; } + } else if (!alg->tls12_ok) { + return false; } return true; @@ -171,7 +209,7 @@ bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey, static bool setup_ctx(SSL *ssl, EVP_MD_CTX *ctx, EVP_PKEY *pkey, uint16_t sigalg, bool is_verify) { - if (!ssl_pkey_supports_algorithm(ssl, pkey, sigalg)) { + if (!ssl_pkey_supports_algorithm(ssl, pkey, sigalg, is_verify)) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); return false; } @@ -448,7 +486,7 @@ void SSL_CTX_set_private_key_method(SSL_CTX *ctx, ctx->cert->default_credential.get(), key_method)); } -static constexpr size_t kMaxSignatureAlgorithmNameLen = 23; +static constexpr size_t kMaxSignatureAlgorithmNameLen = 24; struct SignatureAlgorithmName { uint16_t signature_algorithm; @@ -461,6 +499,7 @@ static const SignatureAlgorithmName kSignatureAlgorithmNames[] = { {SSL_SIGN_RSA_PKCS1_MD5_SHA1, "rsa_pkcs1_md5_sha1"}, {SSL_SIGN_RSA_PKCS1_SHA1, "rsa_pkcs1_sha1"}, {SSL_SIGN_RSA_PKCS1_SHA256, "rsa_pkcs1_sha256"}, + {SSL_SIGN_RSA_PKCS1_SHA256_LEGACY, "rsa_pkcs1_sha256_legacy"}, {SSL_SIGN_RSA_PKCS1_SHA384, "rsa_pkcs1_sha384"}, {SSL_SIGN_RSA_PKCS1_SHA512, "rsa_pkcs1_sha512"}, {SSL_SIGN_ECDSA_SHA1, "ecdsa_sha1"}, diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_versions.cc b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_versions.cc index db298fb528..8aa7e3f57e 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/ssl_versions.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/ssl_versions.cc @@ -142,7 +142,7 @@ static bool set_min_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out, uint16_t version) { // Zero is interpreted as the default minimum version. if (version == 0) { - *out = method->is_dtls ? DTLS1_VERSION : TLS1_VERSION; + *out = method->is_dtls ? DTLS1_2_VERSION : TLS1_2_VERSION; return true; } diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/bssl_shim.cc b/naiveproxy/src/third_party/boringssl/src/ssl/test/bssl_shim.cc index 38ab01ce9f..72793f27ef 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/bssl_shim.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/bssl_shim.cc @@ -524,7 +524,7 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume, } } - if (!config->expect_next_proto.empty()) { + if (!config->expect_next_proto.empty() || config->expect_no_next_proto) { const uint8_t *next_proto; unsigned next_proto_len; SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); @@ -1374,8 +1374,6 @@ int main(int argc, char **argv) { signal(SIGPIPE, SIG_IGN); #endif - CRYPTO_library_init(); - TestConfig initial_config, resume_config, retry_config; if (!ParseConfig(argc - 1, argv + 1, /*is_shim=*/true, &initial_config, &resume_config, &retry_config)) { diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/common.go b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/common.go index 082efceab1..3a8caa1e7b 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/common.go +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/common.go @@ -215,6 +215,9 @@ const ( signatureEd25519 signatureAlgorithm = 0x0807 signatureEd448 signatureAlgorithm = 0x0808 + // draft-ietf-tls-tls13-pkcs1-00 + signatureRSAPKCS1WithSHA256Legacy signatureAlgorithm = 0x0420 + // signatureRSAPKCS1WithMD5AndSHA1 is the internal value BoringSSL uses to // represent the TLS 1.0/1.1 RSA MD5/SHA1 concatenation. We define the // constant here to test that this doesn't leak into the protocol. @@ -455,6 +458,14 @@ type Config struct { // NextProtos is a list of supported, application level protocols. NextProtos []string + // NoFallbackNextProto, if true, causes the client to decline to pick an NPN + // protocol, instead of picking an opportunistic, fallback protocol. + NoFallbackNextProto bool + + // NegotiateNPNWithNoProtos, if true, causes the server to negotiate NPN + // despite having no protocols configured. + NegotiateNPNWithNoProtos bool + // ApplicationSettings is a set of application settings to use which each // application protocol. ApplicationSettings map[string][]byte diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/conn.go b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/conn.go index bda9b92f37..ca1a037ac4 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/conn.go +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/conn.go @@ -571,20 +571,6 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int, typ recordType) (bool, // encrypt if hc.cipher != nil { - // Add TLS 1.3 padding. - if hc.version >= VersionTLS13 { - paddingLen := hc.config.Bugs.RecordPadding - if hc.config.Bugs.OmitRecordContents { - b.resize(recordHeaderLen + paddingLen) - } else { - b.resize(len(b.data) + 1 + paddingLen) - b.data[len(b.data)-paddingLen-1] = byte(typ) - } - for i := 0; i < paddingLen; i++ { - b.data[len(b.data)-paddingLen+i] = 0 - } - } - switch c := hc.cipher.(type) { case cipher.Stream: c.XORKeyStream(payload, payload) @@ -606,11 +592,8 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int, typ recordType) (bool, additionalData[11] = byte(payloadLen >> 8) additionalData[12] = byte(payloadLen) } else { - additionalData = make([]byte, 5) - copy(additionalData, b.data[:3]) - n := len(b.data) - recordHeaderLen - additionalData[3] = byte(n >> 8) - additionalData[4] = byte(n) + additionalData = make([]byte, recordHeaderLen) + copy(additionalData, b.data) } c.Seal(payload[:0], nonce, payload, additionalData) @@ -1186,6 +1169,28 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { return c.doWriteRecord(typ, data) } +func (c *Conn) addTLS13Padding(b *block, recordHeaderLen, recordLen int, typ recordType) int { + if c.out.version < VersionTLS13 || c.out.cipher == nil { + return recordLen + } + paddingLen := c.config.Bugs.RecordPadding + if c.config.Bugs.OmitRecordContents { + recordLen = paddingLen + b.resize(recordHeaderLen + paddingLen) + } else { + recordLen += 1 + paddingLen + b.resize(len(b.data) + 1 + paddingLen) + b.data[len(b.data)-paddingLen-1] = byte(typ) + } + for i := 0; i < paddingLen; i++ { + b.data[len(b.data)-paddingLen+i] = 0 + } + if c, ok := c.out.cipher.(*tlsAead); ok { + recordLen += c.Overhead() + } + return recordLen +} + func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) { recordHeaderLen := c.out.recordHeaderLen() b := c.out.newBlock() @@ -1205,6 +1210,7 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) { m = 6 } } + plaintextLen := m explicitIVLen := 0 explicitIVIsSeq := false first = false @@ -1228,7 +1234,7 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) { explicitIVIsSeq = true } } - b.resize(recordHeaderLen + explicitIVLen + m) + b.resize(recordHeaderLen + explicitIVLen + plaintextLen) b.data[0] = byte(typ) if c.vers >= VersionTLS13 && c.out.cipher != nil { b.data[0] = byte(recordTypeApplicationData) @@ -1255,10 +1261,13 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) { if c.vers == 0 && c.config.Bugs.SendInitialRecordVersion != 0 { vers = c.config.Bugs.SendInitialRecordVersion } + copy(b.data[recordHeaderLen+explicitIVLen:], data) + // Add TLS 1.3 padding. + recordLen := c.addTLS13Padding(b, recordHeaderLen, plaintextLen, typ) b.data[1] = byte(vers >> 8) b.data[2] = byte(vers) - b.data[3] = byte(m >> 8) - b.data[4] = byte(m) + b.data[3] = byte(recordLen >> 8) + b.data[4] = byte(recordLen) if explicitIVLen > 0 { explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen] if explicitIVIsSeq { @@ -1269,14 +1278,13 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) { } } } - copy(b.data[recordHeaderLen+explicitIVLen:], data) c.out.encrypt(b, explicitIVLen, typ) _, err = c.conn.Write(b.data) if err != nil { break } - n += m - data = data[m:] + n += plaintextLen + data = data[plaintextLen:] } c.out.freeBlock(b) diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/handshake_client.go b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/handshake_client.go index 0c338d734a..a0a81f9996 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/handshake_client.go +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/handshake_client.go @@ -1300,9 +1300,9 @@ func (hs *clientHandshakeState) doTLS13Handshake(msg any) error { c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13) if c.peerDelegatedCredential != nil { - err = verifyMessageDC(c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature) + err = verifyMessageDC(c.isClient, c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature) } else { - err = verifyMessage(c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature) + err = verifyMessage(c.isClient, c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature) } if err != nil { return err @@ -1452,7 +1452,7 @@ func (hs *clientHandshakeState) doTLS13Handshake(msg any) error { // Determine the hash to sign. var err error - certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, credential, c.config, certReq.signatureAlgorithms) + certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, credential, c.config, certReq.signatureAlgorithms) if err != nil { c.sendAlert(alertInternalError) return err @@ -1460,7 +1460,7 @@ func (hs *clientHandshakeState) doTLS13Handshake(msg any) error { privKey := credential.PrivateKey input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13) - certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input) + certVerify.signature, err = signMessage(c.isClient, c.vers, privKey, c.config, certVerify.signatureAlgorithm, input) if err != nil { c.sendAlert(alertInternalError) return err @@ -1765,7 +1765,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { // Determine the hash to sign. if certVerify.hasSignatureAlgorithm { - certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, credential, c.config, certReq.signatureAlgorithms) + certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, credential, c.config, certReq.signatureAlgorithms) if err != nil { c.sendAlert(alertInternalError) return err @@ -1773,7 +1773,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { } privKey := c.config.Credential.PrivateKey - certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer) + certVerify.signature, err = signMessage(c.isClient, c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer) if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 { certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm } @@ -1885,7 +1885,7 @@ func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) erro } signedMsg := delegatedCredentialSignedMessage(dc.signedBytes, dc.algorithm, certs[0].Raw) - if err := verifyMessage(c.vers, leafPublicKey, c.config, dc.algorithm, signedMsg, dc.signature); err != nil { + if err := verifyMessage(c.isClient, c.vers, leafPublicKey, c.config, dc.algorithm, signedMsg, dc.signature); err != nil { c.sendAlert(alertBadCertificate) return errors.New("tls: failed to verify delegated credential: " + err.Error()) } @@ -2265,6 +2265,10 @@ func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error { if hs.serverHello.extensions.nextProtoNeg { nextProto := new(nextProtoMsg) proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos) + if fallback && c.config.NoFallbackNextProto { + proto = "" + fallback = false + } nextProto.proto = proto c.clientProtocol = proto c.clientProtocolFallback = fallback diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/handshake_server.go b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/handshake_server.go index ceaf02931a..2e87d54fb1 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/handshake_server.go +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/handshake_server.go @@ -1169,7 +1169,7 @@ ResendHelloRetryRequest: // Determine the hash to sign. var err error - certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, hs.cert, config, hs.clientHello.signatureAlgorithms) + certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, hs.cert, config, hs.clientHello.signatureAlgorithms) if err != nil { c.sendAlert(alertInternalError) return err @@ -1177,7 +1177,7 @@ ResendHelloRetryRequest: privKey := hs.cert.PrivateKey input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13) - certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input) + certVerify.signature, err = signMessage(c.isClient, c.vers, privKey, c.config, certVerify.signatureAlgorithm, input) if err != nil { c.sendAlert(alertInternalError) return err @@ -1362,7 +1362,7 @@ ResendHelloRetryRequest: c.peerSignatureAlgorithm = certVerify.signatureAlgorithm input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13) - if err := verifyMessage(c.vers, pub, config, certVerify.signatureAlgorithm, input, certVerify.signature); err != nil { + if err := verifyMessage(c.isClient, c.vers, pub, config, certVerify.signatureAlgorithm, input, certVerify.signature); err != nil { c.sendAlert(alertBadCertificate) return err } @@ -1664,11 +1664,7 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server if c.vers < VersionTLS13 || config.Bugs.NegotiateNPNAtAllVersions { if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN { - // Although sending an empty NPN extension is reasonable, Firefox has - // had a bug around this. Best to send nothing at all if - // config.NextProtos is empty. See - // https://code.google.com/p/go/issues/detail?id=5445. - if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 { + if hs.clientHello.nextProtoNeg && (len(config.NextProtos) > 0 || config.NegotiateNPNWithNoProtos) { serverExtensions.nextProtoNeg = true serverExtensions.nextProtos = config.NextProtos serverExtensions.npnAfterAlpn = config.Bugs.SwapNPNAndALPN @@ -2097,7 +2093,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { c.peerSignatureAlgorithm = sigAlg } - if err := verifyMessage(c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature); err != nil { + if err := verifyMessage(c.isClient, c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature); err != nil { c.sendAlert(alertBadCertificate) return errors.New("could not validate signature of connection nonces: " + err.Error()) } diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/key_agreement.go b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/key_agreement.go index 39377f8267..aff0820e3c 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/key_agreement.go +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/key_agreement.go @@ -65,13 +65,13 @@ func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Crede var sigAlg signatureAlgorithm if ka.version >= VersionTLS12 { - sigAlg, err = selectSignatureAlgorithm(ka.version, cert, config, clientHello.signatureAlgorithms) + sigAlg, err = selectSignatureAlgorithm(false /* server */, ka.version, cert, config, clientHello.signatureAlgorithms) if err != nil { return nil, err } } - sig, err := signMessage(ka.version, cert.PrivateKey, config, sigAlg, serverRSAParams) + sig, err := signMessage(false /* server */, ka.version, cert.PrivateKey, config, sigAlg, serverRSAParams) if err != nil { return nil, errors.New("failed to sign RSA parameters: " + err.Error()) } @@ -489,13 +489,13 @@ func (ka *signedKeyAgreement) signParameters(config *Config, cert *Credential, c var sigAlg signatureAlgorithm var err error if ka.version >= VersionTLS12 { - sigAlg, err = selectSignatureAlgorithm(ka.version, cert, config, clientHello.signatureAlgorithms) + sigAlg, err = selectSignatureAlgorithm(false /* server */, ka.version, cert, config, clientHello.signatureAlgorithms) if err != nil { return nil, err } } - sig, err := signMessage(ka.version, cert.PrivateKey, config, sigAlg, msg) + sig, err := signMessage(false /* server */, ka.version, cert.PrivateKey, config, sigAlg, msg) if err != nil { return nil, err } @@ -571,7 +571,7 @@ func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clie } sig = sig[2:] - return verifyMessage(ka.version, publicKey, config, sigAlg, msg, sig) + return verifyMessage(true /* client */, ka.version, publicKey, config, sigAlg, msg, sig) } // ecdheKeyAgreement implements a TLS key agreement where the server diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/runner.go b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/runner.go index e18bfd3fd1..3aab605c75 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/runner.go +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/runner.go @@ -374,7 +374,7 @@ func createDelegatedCredential(parent *Credential, config delegatedCredentialCon addUint24LengthPrefixedBytes(dc, pubBytes) var dummyConfig Config - parentSignature, err := signMessage(VersionTLS13, parent.PrivateKey, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc.BytesOrPanic(), config.algo, parent.Leaf.Raw)) + parentSignature, err := signMessage(false /* server */, VersionTLS13, parent.PrivateKey, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc.BytesOrPanic(), config.algo, parent.Leaf.Raw)) if err != nil { panic(err) } @@ -1738,16 +1738,16 @@ func runTest(dispatcher *shimDispatcher, statusChan chan statusMsg, test *testCa case failed && !test.shouldFail: msg = "unexpected failure" case !failed && test.shouldFail: - msg = "unexpected success" + msg = fmt.Sprintf("unexpected success (wanted failure with %q / %q)", expectedError, test.expectedLocalError) case failed && !correctFailure: - msg = "bad error (wanted '" + expectedError + "' / '" + test.expectedLocalError + "')" + msg = fmt.Sprintf("bad error (wanted %q / %q)", expectedError, test.expectedLocalError) case mustFail: msg = "test failure" default: panic("internal error") } - return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr) + return fmt.Errorf("%s: local error %q, child error %q, stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr) } if len(extraStderr) > 0 || (!failed && len(stderr) > 0) { @@ -5683,7 +5683,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { expectedError: halfHelloRequestError, }) - // NPN on client and server; results in post-handshake message. + // NPN on client and server; results in post-ChangeCipherSpec message. tests = append(tests, testCase{ name: "NPN-Client", config: Config{ @@ -5715,6 +5715,73 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { }, }) + // The client may select no protocol after seeing the server list. + tests = append(tests, testCase{ + name: "NPN-Client-ClientSelectEmpty", + config: Config{ + MaxVersion: VersionTLS12, + NextProtos: []string{"foo"}, + }, + flags: []string{"-select-empty-next-proto"}, + resumeSession: true, + expectations: connectionExpectations{ + noNextProto: true, + nextProtoType: npn, + }, + }) + tests = append(tests, testCase{ + testType: serverTest, + name: "NPN-Server-ClientSelectEmpty", + config: Config{ + MaxVersion: VersionTLS12, + NextProtos: []string{"no-match"}, + NoFallbackNextProto: true, + }, + flags: []string{ + "-advertise-npn", "\x03foo\x03bar\x03baz", + "-expect-no-next-proto", + }, + resumeSession: true, + expectations: connectionExpectations{ + noNextProto: true, + nextProtoType: npn, + }, + }) + + // The server may negotiate NPN, despite offering no protocols. In this + // case, the server must still be prepared for the client to select a + // fallback protocol. + tests = append(tests, testCase{ + name: "NPN-Client-ServerAdvertiseEmpty", + config: Config{ + MaxVersion: VersionTLS12, + NegotiateNPNWithNoProtos: true, + }, + flags: []string{"-select-next-proto", "foo"}, + resumeSession: true, + expectations: connectionExpectations{ + nextProto: "foo", + nextProtoType: npn, + }, + }) + tests = append(tests, testCase{ + testType: serverTest, + name: "NPN-Server-ServerAdvertiseEmpty", + config: Config{ + MaxVersion: VersionTLS12, + NextProtos: []string{"foo"}, + }, + flags: []string{ + "-advertise-empty-npn", + "-expect-next-proto", "foo", + }, + resumeSession: true, + expectations: connectionExpectations{ + nextProto: "foo", + nextProtoType: npn, + }, + }) + // Client does False Start and negotiates NPN. tests = append(tests, testCase{ name: "FalseStart", @@ -9949,6 +10016,7 @@ var testSignatureAlgorithms = []struct { }{ {"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, &rsaCertificate, 0}, {"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, &rsaCertificate, 0}, + {"RSA_PKCS1_SHA256_LEGACY", signatureRSAPKCS1WithSHA256Legacy, &rsaCertificate, 0}, {"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, &rsaCertificate, 0}, {"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, &rsaCertificate, 0}, {"ECDSA_SHA1", signatureECDSAWithSHA1, &ecdsaP256Certificate, CurveP256}, @@ -10003,61 +10071,95 @@ func addSignatureAlgorithmTests() { continue } - var shouldFail, rejectByDefault bool - // ecdsa_sha1 does not exist in TLS 1.3. - if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 { - shouldFail = true - } - // RSA-PKCS1 does not exist in TLS 1.3. - if ver.version >= VersionTLS13 && hasComponent(alg.name, "PKCS1") { - shouldFail = true - } - // SHA-224 has been removed from TLS 1.3 and, in 1.3, - // the curve has to match the hash size. - if ver.version >= VersionTLS13 && alg.curve == CurveP224 { - shouldFail = true - } - - // By default, BoringSSL does not enable ecdsa_sha1, ecdsa_secp521_sha512, and ed25519. - if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 { - rejectByDefault = true - } - - var curveFlags []string - var runnerCurves []CurveID - if alg.curve != 0 && ver.version <= VersionTLS12 { - // In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the - // corresponding curve is enabled. Also include X25519 to ensure the shim - // and runner have something in common for ECDH. - curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)}) - runnerCurves = []CurveID{CurveX25519, alg.curve} - } - - var signError, signLocalError, verifyError, verifyLocalError, defaultError, defaultLocalError string - if shouldFail { - signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:" - signLocalError = "remote error: handshake failure" - verifyError = ":WRONG_SIGNATURE_TYPE:" - verifyLocalError = "remote error" - rejectByDefault = true - } - if rejectByDefault { - defaultError = ":WRONG_SIGNATURE_TYPE:" - defaultLocalError = "remote error" - } - suffix := "-" + alg.name + "-" + ver.name + for _, signTestType := range []testType{clientTest, serverTest} { + signPrefix := "Client-" + verifyPrefix := "Server-" + verifyTestType := serverTest + if signTestType == serverTest { + verifyTestType = clientTest + signPrefix, verifyPrefix = verifyPrefix, signPrefix + } - for _, testType := range []testType{clientTest, serverTest} { - prefix := "Client-" - if testType == serverTest { - prefix = "Server-" + var shouldFail bool + isTLS12PKCS1 := hasComponent(alg.name, "PKCS1") && !hasComponent(alg.name, "LEGACY") + isTLS13PKCS1 := hasComponent(alg.name, "PKCS1") && hasComponent(alg.name, "LEGACY") + + // TLS 1.3 removes a number of signature algorithms. + if ver.version >= VersionTLS13 && (alg.curve == CurveP224 || alg.id == signatureECDSAWithSHA1 || isTLS12PKCS1) { + shouldFail = true + } + + // The backported RSA-PKCS1 code points only exist for TLS 1.3 + // client certificates. + if (ver.version < VersionTLS13 || signTestType == serverTest) && isTLS13PKCS1 { + shouldFail = true + } + + // By default, BoringSSL does not sign with these algorithms. + signDefault := !shouldFail + if isTLS13PKCS1 { + signDefault = false + } + + // By default, BoringSSL does not accept these algorithms. + verifyDefault := !shouldFail + if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 || isTLS13PKCS1 { + verifyDefault = false + } + + var curveFlags []string + var runnerCurves []CurveID + if alg.curve != 0 && ver.version <= VersionTLS12 { + // In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the + // corresponding curve is enabled. Also include X25519 to ensure the shim + // and runner have something in common for ECDH. + curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)}) + runnerCurves = []CurveID{CurveX25519, alg.curve} + } + + signError := func(shouldFail bool) string { + if !shouldFail { + return "" + } + // In TLS 1.3, the shim should report no common signature algorithms if + // it cannot generate a signature. In TLS 1.2 servers, signature + // algorithm and cipher selection are integrated, so it is reported as + // no shared cipher. + if ver.version <= VersionTLS12 && signTestType == serverTest { + return ":NO_SHARED_CIPHER:" + } + return ":NO_COMMON_SIGNATURE_ALGORITHMS:" + } + signLocalError := func(shouldFail bool) string { + if !shouldFail { + return "" + } + // The shim should send handshake_failure when it cannot + // negotiate parameters. + return "remote error: handshake failure" + } + verifyError := func(shouldFail bool) string { + if !shouldFail { + return "" + } + // If the shim rejects the signature algorithm, but the + // runner forcibly selects it anyway, the shim should notice. + return ":WRONG_SIGNATURE_TYPE:" + } + verifyLocalError := func(shouldFail bool) string { + if !shouldFail { + return "" + } + // The shim should send an illegal_parameter alert if the runner + // uses a signature algorithm it isn't allowed to use. + return "remote error: illegal parameter" } // Test the shim using the algorithm for signing. signTest := testCase{ - testType: testType, - name: prefix + "Sign" + suffix, + testType: signTestType, + name: signPrefix + "Sign" + suffix, config: Config{ MaxVersion: ver.version, CurvePreferences: runnerCurves, @@ -10070,8 +10172,33 @@ func addSignatureAlgorithmTests() { shimCertificate: cert, flags: curveFlags, shouldFail: shouldFail, - expectedError: signError, - expectedLocalError: signLocalError, + expectedError: signError(shouldFail), + expectedLocalError: signLocalError(shouldFail), + expectations: connectionExpectations{ + peerSignatureAlgorithm: alg.id, + }, + } + + // Test whether the shim enables the algorithm by default. + signDefaultTest := testCase{ + testType: signTestType, + name: signPrefix + "SignDefault" + suffix, + config: Config{ + MaxVersion: ver.version, + CurvePreferences: runnerCurves, + VerifySignatureAlgorithms: []signatureAlgorithm{ + fakeSigAlg1, + alg.id, + fakeSigAlg2, + }, + }, + // cert has been configured with the specified algorithm, + // while alg.baseCert uses the defaults. + shimCertificate: alg.baseCert, + flags: curveFlags, + shouldFail: !signDefault, + expectedError: signError(!signDefault), + expectedLocalError: signLocalError(!signDefault), expectations: connectionExpectations{ peerSignatureAlgorithm: alg.id, }, @@ -10080,8 +10207,8 @@ func addSignatureAlgorithmTests() { // Test that the shim will select the algorithm when configured to only // support it. negotiateTest := testCase{ - testType: testType, - name: prefix + "Sign-Negotiate" + suffix, + testType: signTestType, + name: signPrefix + "Sign-Negotiate" + suffix, config: Config{ MaxVersion: ver.version, CurvePreferences: runnerCurves, @@ -10094,24 +10221,26 @@ func addSignatureAlgorithmTests() { }, } - if testType == serverTest { + if signTestType == serverTest { // TLS 1.2 servers only sign on some cipher suites. signTest.config.CipherSuites = signingCiphers + signDefaultTest.config.CipherSuites = signingCiphers negotiateTest.config.CipherSuites = signingCiphers } else { // TLS 1.2 clients only sign when the server requests certificates. signTest.config.ClientAuth = RequireAnyClientCert + signDefaultTest.config.ClientAuth = RequireAnyClientCert negotiateTest.config.ClientAuth = RequireAnyClientCert } - testCases = append(testCases, signTest) + testCases = append(testCases, signTest, signDefaultTest) if ver.version >= VersionTLS12 && !shouldFail { testCases = append(testCases, negotiateTest) } // Test the shim using the algorithm for verifying. verifyTest := testCase{ - testType: testType, - name: prefix + "Verify" + suffix, + testType: verifyTestType, + name: verifyPrefix + "Verify" + suffix, config: Config{ MaxVersion: ver.version, Credential: cert, @@ -10127,8 +10256,8 @@ func addSignatureAlgorithmTests() { // algorithm is reported on both handshakes. resumeSession: !shouldFail, shouldFail: shouldFail, - expectedError: verifyError, - expectedLocalError: verifyLocalError, + expectedError: verifyError(shouldFail), + expectedLocalError: verifyLocalError(shouldFail), } if alg.id != 0 { verifyTest.flags = append(verifyTest.flags, "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))) @@ -10138,16 +10267,16 @@ func addSignatureAlgorithmTests() { // Test whether the shim expects the algorithm enabled by default. defaultTest := testCase{ - testType: testType, - name: prefix + "VerifyDefault" + suffix, + testType: verifyTestType, + name: verifyPrefix + "VerifyDefault" + suffix, config: Config{ MaxVersion: ver.version, Credential: cert, Bugs: ProtocolBugs{ - SkipECDSACurveCheck: rejectByDefault, - IgnoreSignatureVersionChecks: rejectByDefault, + SkipECDSACurveCheck: !verifyDefault, + IgnoreSignatureVersionChecks: !verifyDefault, // Some signature algorithms may not be advertised. - IgnorePeerSignatureAlgorithmPreferences: rejectByDefault, + IgnorePeerSignatureAlgorithmPreferences: !verifyDefault, }, }, flags: append( @@ -10156,16 +10285,16 @@ func addSignatureAlgorithmTests() { ), // Resume the session to assert the peer signature // algorithm is reported on both handshakes. - resumeSession: !rejectByDefault, - shouldFail: rejectByDefault, - expectedError: defaultError, - expectedLocalError: defaultLocalError, + resumeSession: verifyDefault, + shouldFail: !verifyDefault, + expectedError: verifyError(!verifyDefault), + expectedLocalError: verifyLocalError(!verifyDefault), } // Test whether the shim handles invalid signatures for this algorithm. invalidTest := testCase{ - testType: testType, - name: prefix + "InvalidSignature" + suffix, + testType: verifyTestType, + name: verifyPrefix + "InvalidSignature" + suffix, config: Config{ MaxVersion: ver.version, Credential: cert, @@ -10182,7 +10311,7 @@ func addSignatureAlgorithmTests() { invalidTest.flags = append(invalidTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id))) } - if testType == serverTest { + if verifyTestType == serverTest { // TLS 1.2 servers only verify when they request client certificates. verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate") defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate") @@ -12060,8 +12189,7 @@ func addCurveTests() { flags: []string{ "-curves", strconv.Itoa(int(CurveX25519Kyber768)), "-curves", strconv.Itoa(int(CurveX25519)), - // Cannot expect Kyber until we have a Go implementation of it. - // "-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)), + "-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)), }, }) @@ -16780,7 +16908,7 @@ func addEncryptedClientHelloTests() { DNSNames: []string{"secret.example"}, IsCA: true, BasicConstraintsValid: true, - }, &ecdsaP256Key) + }, &rsa2048Key) echPublicCertificate := generateSingleCertChain(&x509.Certificate{ SerialNumber: big.NewInt(57005), Subject: pkix.Name{ @@ -16791,7 +16919,7 @@ func addEncryptedClientHelloTests() { DNSNames: []string{"public.example"}, IsCA: true, BasicConstraintsValid: true, - }, &ecdsaP256Key) + }, &rsa2048Key) echLongNameCertificate := generateSingleCertChain(&x509.Certificate{ SerialNumber: big.NewInt(57005), Subject: pkix.Name{ @@ -17786,6 +17914,7 @@ write hs 4 AlwaysSendECHHelloRetryRequest: true, ExpectMissingKeyShare: true, // Check we triggered HRR. }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -17973,6 +18102,7 @@ write hs 4 ExpectServerName: "secret.example", AlwaysRejectEarlyData: true, }, + Credential: &echSecretCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18246,6 +18376,7 @@ write hs 4 extensionSupportedCurves, }, }, + Credential: &echSecretCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18298,6 +18429,7 @@ write hs 4 extensionSupportedVersions, }, }, + Credential: &echSecretCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18340,6 +18472,7 @@ write hs 4 Bugs: ProtocolBugs{ ExpectServerName: "public.example", }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18360,6 +18493,7 @@ write hs 4 ExpectServerName: "public.example", ExpectMissingKeyShare: true, // Check we triggered HRR. }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18378,6 +18512,7 @@ write hs 4 Bugs: ProtocolBugs{ ExpectServerName: "public.example", }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18397,6 +18532,7 @@ write hs 4 Bugs: ProtocolBugs{ ExpectServerName: "public.example", }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18422,6 +18558,7 @@ write hs 4 ExpectFalseStart: true, AlertBeforeFalseStartTest: alertAccessDenied, }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18458,6 +18595,7 @@ write hs 4 SendECHRetryConfigs: retryConfigs, ExpectServerName: "public.example", }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18479,6 +18617,7 @@ write hs 4 Bugs: ProtocolBugs{ ExpectServerName: "secret.example", }, + Credential: &echSecretCertificate, }, resumeConfig: &Config{ MaxVersion: VersionTLS13, @@ -18487,6 +18626,7 @@ write hs 4 ExpectServerName: "public.example", UseInnerSessionWithClientHelloOuter: true, }, + Credential: &echPublicCertificate, }, resumeSession: true, flags: []string{ @@ -18509,6 +18649,7 @@ write hs 4 Bugs: ProtocolBugs{ ExpectServerName: "secret.example", }, + Credential: &echSecretCertificate, }, resumeConfig: &Config{ MinVersion: VersionTLS12, @@ -18522,6 +18663,7 @@ write hs 4 // resumed at TLS 1.2. AcceptAnySession: true, }, + Credential: &echPublicCertificate, }, resumeSession: true, flags: []string{ @@ -18550,12 +18692,14 @@ write hs 4 Bugs: ProtocolBugs{ ExpectServerName: "secret.example", }, + Credential: &echSecretCertificate, }, resumeConfig: &Config{ ServerECHConfigs: []ServerECHConfig{echConfig2}, Bugs: ProtocolBugs{ ExpectServerName: "public.example", }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18588,12 +18732,14 @@ write hs 4 Bugs: ProtocolBugs{ ExpectServerName: "secret.example", }, + Credential: &echSecretCertificate, }, resumeConfig: &Config{ MaxVersion: VersionTLS12, Bugs: ProtocolBugs{ ExpectServerName: "public.example", }, + Credential: &echPublicCertificate, }, flags: []string{ "-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)), @@ -18698,6 +18844,7 @@ write hs 4 MinVersion: VersionTLS13, MaxVersion: VersionTLS13, ClientAuth: RequireAnyClientCert, + Credential: &echPublicCertificate, }, shimCertificate: &rsaCertificate, flags: append([]string{ @@ -18715,6 +18862,7 @@ write hs 4 MinVersion: VersionTLS12, MaxVersion: VersionTLS12, ClientAuth: RequireAnyClientCert, + Credential: &echPublicCertificate, }, shimCertificate: &rsaCertificate, flags: append([]string{ @@ -18758,6 +18906,7 @@ write hs 4 Bugs: ProtocolBugs{ AlwaysNegotiateChannelID: true, }, + Credential: &echPublicCertificate, }, flags: []string{ "-send-channel-id", channelIDKeyPath, @@ -18778,6 +18927,7 @@ write hs 4 Bugs: ProtocolBugs{ AlwaysNegotiateChannelID: true, }, + Credential: &echPublicCertificate, }, flags: []string{ "-send-channel-id", channelIDKeyPath, @@ -18849,6 +18999,7 @@ write hs 4 config: Config{ MinVersion: VersionTLS13, MaxVersion: VersionTLS13, + Credential: &echPublicCertificate, }, flags: []string{ "-verify-peer", @@ -18888,8 +19039,11 @@ write hs 4 name: prefix + "ECH-Client-Reject-EarlyDataRejected-OverrideNameOnRetry", config: Config{ ServerECHConfigs: []ServerECHConfig{echConfig}, + Credential: &echPublicCertificate, + }, + resumeConfig: &Config{ + Credential: &echPublicCertificate, }, - resumeConfig: &Config{}, flags: []string{ "-verify-peer", "-use-custom-verify-callback", @@ -20354,19 +20508,19 @@ func statusPrinter(doneChan chan *testresult.Results, statusChan chan statusMsg, if *allowUnimplemented { testOutput.AddSkip(msg.test.name) } else { - testOutput.AddResult(msg.test.name, "SKIP") + testOutput.AddResult(msg.test.name, "SKIP", nil) } } else { fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err) failed++ - testOutput.AddResult(msg.test.name, "FAIL") + testOutput.AddResult(msg.test.name, "FAIL", msg.err) } } else { if *pipe { // Print each test instead of a status line. fmt.Printf("PASSED (%s)\n", msg.test.name) } - testOutput.AddResult(msg.test.name, "PASS") + testOutput.AddResult(msg.test.name, "PASS", nil) } } diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/sign.go b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/sign.go index a57b2e7f22..65568a3860 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/sign.go +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/runner/sign.go @@ -27,7 +27,7 @@ type signer interface { verifyMessage(key crypto.PublicKey, msg, sig []byte) error } -func selectSignatureAlgorithm(version uint16, cred *Credential, config *Config, peerSigAlgs []signatureAlgorithm) (signatureAlgorithm, error) { +func selectSignatureAlgorithm(isClient bool, version uint16, cred *Credential, config *Config, peerSigAlgs []signatureAlgorithm) (signatureAlgorithm, error) { // If the client didn't specify any signature_algorithms extension then // we can assume that it supports SHA1. See // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 @@ -40,7 +40,7 @@ func selectSignatureAlgorithm(version uint16, cred *Credential, config *Config, continue } - signer, err := getSigner(version, cred.PrivateKey, config, sigAlg, false) + signer, err := getSigner(isClient, version, cred.PrivateKey, config, sigAlg, false) if err != nil { continue } @@ -52,7 +52,7 @@ func selectSignatureAlgorithm(version uint16, cred *Credential, config *Config, return 0, errors.New("tls: no common signature algorithms") } -func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg signatureAlgorithm, msg []byte) ([]byte, error) { +func signMessage(isClient bool, version uint16, key crypto.PrivateKey, config *Config, sigAlg signatureAlgorithm, msg []byte) ([]byte, error) { if config.Bugs.InvalidSignature { newMsg := make([]byte, len(msg)) copy(newMsg, msg) @@ -60,7 +60,7 @@ func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg s msg = newMsg } - signer, err := getSigner(version, key, config, sigAlg, false) + signer, err := getSigner(isClient, version, key, config, sigAlg, false) if err != nil { return nil, err } @@ -68,12 +68,12 @@ func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg s return signer.signMessage(key, config, msg) } -func verifyMessage(version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error { +func verifyMessage(isClient bool, version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error { if version >= VersionTLS12 && !slices.Contains(config.verifySignatureAlgorithms(), sigAlg) { return errors.New("tls: unsupported signature algorithm") } - signer, err := getSigner(version, key, config, sigAlg, true) + signer, err := getSigner(isClient, version, key, config, sigAlg, true) if err != nil { return err } @@ -81,12 +81,12 @@ func verifyMessage(version uint16, key crypto.PublicKey, config *Config, sigAlg return signer.verifyMessage(key, msg, sig) } -func verifyMessageDC(version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error { +func verifyMessageDC(isClient bool, version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error { if version >= VersionTLS12 && !slices.Contains(config.DelegatedCredentialAlgorithms, sigAlg) { return errors.New("tls: unsupported signature algorithm") } - signer, err := getSigner(version, key, config, sigAlg, true) + signer, err := getSigner(isClient, version, key, config, sigAlg, true) if err != nil { return err } @@ -286,7 +286,7 @@ func (e *ed25519Signer) verifyMessage(key crypto.PublicKey, msg, sig []byte) err return nil } -func getSigner(version uint16, key any, config *Config, sigAlg signatureAlgorithm, isVerify bool) (signer, error) { +func getSigner(isClient bool, version uint16, key any, config *Config, sigAlg signatureAlgorithm, isVerify bool) (signer, error) { // TLS 1.1 and below use legacy signature algorithms. if version < VersionTLS12 || (!isVerify && config.Bugs.AlwaysSignAsLegacyVersion) { if config.Bugs.SigningAlgorithmForLegacyVersions == 0 || isVerify { @@ -304,6 +304,7 @@ func getSigner(version uint16, key any, config *Config, sigAlg signatureAlgorith sigAlg = config.Bugs.SigningAlgorithmForLegacyVersions } + isClientSign := isClient != isVerify switch sigAlg { case signatureRSAPKCS1WithMD5: if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { @@ -325,6 +326,10 @@ func getSigner(version uint16, key any, config *Config, sigAlg signatureAlgorith if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { return &rsaPKCS1Signer{crypto.SHA512}, nil } + case signatureRSAPKCS1WithSHA256Legacy: + if (isClientSign && version >= VersionTLS13) || config.Bugs.IgnoreSignatureVersionChecks { + return &rsaPKCS1Signer{crypto.SHA256}, nil + } case signatureECDSAWithSHA1: return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil case signatureECDSAWithP256AndSHA256: diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/test_config.cc b/naiveproxy/src/third_party/boringssl/src/ssl/test/test_config.cc index dbfa461a1d..24b1bdd4db 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/test_config.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/test_config.cc @@ -293,9 +293,13 @@ const Flag *FindFlag(const char *name) { BoolFlag("-require-any-client-certificate", &TestConfig::require_any_client_certificate), StringFlag("-advertise-npn", &TestConfig::advertise_npn), + BoolFlag("-advertise-empty-npn", &TestConfig::advertise_empty_npn), StringFlag("-expect-next-proto", &TestConfig::expect_next_proto), + BoolFlag("-expect-no-next-proto", &TestConfig::expect_no_next_proto), BoolFlag("-false-start", &TestConfig::false_start), StringFlag("-select-next-proto", &TestConfig::select_next_proto), + BoolFlag("-select-empty-next-proto", + &TestConfig::select_empty_next_proto), BoolFlag("-async", &TestConfig::async), BoolFlag("-write-different-record-sizes", &TestConfig::write_different_record_sizes), @@ -713,10 +717,6 @@ static int NextProtoSelectCallback(SSL *ssl, uint8_t **out, uint8_t *outlen, const uint8_t *in, unsigned inlen, void *arg) { const TestConfig *config = GetTestConfig(ssl); - if (config->select_next_proto.empty()) { - return SSL_TLSEXT_ERR_NOACK; - } - *out = (uint8_t *)config->select_next_proto.data(); *outlen = config->select_next_proto.size(); return SSL_TLSEXT_ERR_OK; @@ -725,7 +725,7 @@ static int NextProtoSelectCallback(SSL *ssl, uint8_t **out, uint8_t *outlen, static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out, unsigned int *out_len, void *arg) { const TestConfig *config = GetTestConfig(ssl); - if (config->advertise_npn.empty()) { + if (config->advertise_npn.empty() && !config->advertise_empty_npn) { return SSL_TLSEXT_ERR_NOACK; } @@ -1721,7 +1721,7 @@ bssl::UniquePtr TestConfig::SetupCtx(SSL_CTX *old_ctx) const { SSL_CTX_set_next_protos_advertised_cb(ssl_ctx.get(), NextProtosAdvertisedCallback, NULL); - if (!select_next_proto.empty()) { + if (!select_next_proto.empty() || select_empty_next_proto) { SSL_CTX_set_next_proto_select_cb(ssl_ctx.get(), NextProtoSelectCallback, NULL); } @@ -2172,6 +2172,14 @@ bssl::UniquePtr TestConfig::NewSSL( if (enable_signed_cert_timestamps) { SSL_enable_signed_cert_timestamps(ssl.get()); } + // (D)TLS 1.0 and 1.1 are disabled by default, but the runner expects them to + // be enabled. + // TODO(davidben): Update the tests to explicitly enable the versions they + // need. + if (!SSL_set_min_proto_version( + ssl.get(), SSL_is_dtls(ssl.get()) ? DTLS1_VERSION : TLS1_VERSION)) { + return nullptr; + } if (min_version != 0 && !SSL_set_min_proto_version(ssl.get(), min_version)) { return nullptr; diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/test/test_config.h b/naiveproxy/src/third_party/boringssl/src/ssl/test/test_config.h index 89cb2be732..89656d19e8 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/test/test_config.h +++ b/naiveproxy/src/third_party/boringssl/src/ssl/test/test_config.h @@ -67,9 +67,12 @@ struct TestConfig { std::string expect_certificate_types; bool require_any_client_certificate = false; std::string advertise_npn; + bool advertise_empty_npn = false; std::string expect_next_proto; + bool expect_no_next_proto = false; bool false_start = false; std::string select_next_proto; + bool select_empty_next_proto = false; bool async = false; bool write_different_record_sizes = false; bool cbc_record_splitting = false; diff --git a/naiveproxy/src/third_party/boringssl/src/ssl/tls13_both.cc b/naiveproxy/src/third_party/boringssl/src/ssl/tls13_both.cc index 4a9b78e9ee..f6d95478f6 100644 --- a/naiveproxy/src/third_party/boringssl/src/ssl/tls13_both.cc +++ b/naiveproxy/src/third_party/boringssl/src/ssl/tls13_both.cc @@ -335,7 +335,8 @@ bool tls13_process_certificate_verify(SSL_HANDSHAKE *hs, const SSLMessage &msg) } uint8_t alert = SSL_AD_DECODE_ERROR; - if (!tls12_check_peer_sigalg(hs, &alert, signature_algorithm)) { + if (!tls12_check_peer_sigalg(hs, &alert, signature_algorithm, + hs->peer_pubkey.get())) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return false; } diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/README.chromium b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/README.chromium index fe48544eb4..fdf28a4e03 100644 --- a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/README.chromium +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/README.chromium @@ -2,6 +2,7 @@ Name: Fiat-Crypto: Synthesizing Correct-by-Construction Code for Cryptographic P Short Name: fiat-crypto URL: https://github.com/mit-plv/fiat-crypto Version: git (see METADATA) +Revision: 6ccc6638716d4632304baf1adbb5c47c3a12ea6f License: MIT License File: LICENSE Security Critical: yes diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/asm/fiat_p256_adx_mul.S b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/asm/fiat_p256_adx_mul.S index d7ebd21719..c4010b3e4c 100644 --- a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/asm/fiat_p256_adx_mul.S +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/asm/fiat_p256_adx_mul.S @@ -3,7 +3,6 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ (defined(__APPLE__) || defined(__ELF__)) -.intel_syntax noprefix .text #if defined(__APPLE__) .private_extern _fiat_p256_adx_mul @@ -18,158 +17,158 @@ fiat_p256_adx_mul: .cfi_startproc _CET_ENDBR -push rbp -.cfi_adjust_cfa_offset 8 +pushq %rbp +;.cfi_adjust_cfa_offset 8 .cfi_offset rbp, -16 -mov rbp, rsp -mov rax, rdx -mov rdx, [ rsi + 0x0 ] -test al, al -mulx r8, rcx, [ rax + 0x0 ] -mov [ rsp - 0x80 ], rbx +movq %rsp, %rbp +movq %rdx, %rax +movq (%rsi), %rdx +testb %al, %al +mulxq (%rax), %rcx, %r8 +movq %rbx, -0x80(%rsp) .cfi_offset rbx, -16-0x80 -mulx rbx, r9, [ rax + 0x8 ] -mov [ rsp - 0x68 ], r14 +mulxq 0x8(%rax), %r9, %rbx +movq %r14, -0x68(%rsp) .cfi_offset r14, -16-0x68 -adc r9, r8 -mov [ rsp - 0x60 ], r15 +adcq %r8, %r9 +movq %r15, -0x60(%rsp) .cfi_offset r15, -16-0x60 -mulx r15, r14, [ rax + 0x10 ] -mov [ rsp - 0x78 ], r12 +mulxq 0x10(%rax), %r14, %r15 +movq %r12, -0x78(%rsp) .cfi_offset r12, -16-0x78 -adc r14, rbx -mulx r11, r10, [ rax + 0x18 ] -mov [ rsp - 0x70 ], r13 +adcq %rbx, %r14 +mulxq 0x18(%rax), %r10, %r11 +movq %r13, -0x70(%rsp) .cfi_offset r13, -16-0x70 -adc r10, r15 -mov rdx, [ rsi + 0x8 ] -mulx rbx, r8, [ rax + 0x0 ] -adc r11, 0x0 -xor r15, r15 -adcx r8, r9 -adox rbx, r14 -mov [ rsp - 0x58 ], rdi -mulx rdi, r9, [ rax + 0x8 ] -adcx r9, rbx -adox rdi, r10 -mulx rbx, r14, [ rax + 0x10 ] -adcx r14, rdi -adox rbx, r11 -mulx r13, r12, [ rax + 0x18 ] -adcx r12, rbx -mov rdx, 0x100000000 -mulx r11, r10, rcx -adox r13, r15 -adcx r13, r15 -xor rdi, rdi -adox r10, r8 -mulx r8, rbx, r10 -adox r11, r9 -adcx rbx, r11 -adox r8, r14 -mov rdx, 0xffffffff00000001 -mulx r9, r15, rcx -adcx r15, r8 -adox r9, r12 -mulx r14, rcx, r10 -mov rdx, [ rsi + 0x10 ] -mulx r10, r12, [ rax + 0x8 ] -adcx rcx, r9 -adox r14, r13 -mulx r11, r13, [ rax + 0x0 ] -mov r9, rdi -adcx r14, r9 -adox rdi, rdi -adc rdi, 0x0 -xor r9, r9 -adcx r13, rbx -adox r11, r15 -mov rdx, [ rsi + 0x10 ] -mulx r15, r8, [ rax + 0x10 ] -adox r10, rcx -mulx rcx, rbx, [ rax + 0x18 ] -mov rdx, [ rsi + 0x18 ] -adcx r12, r11 -mulx rsi, r11, [ rax + 0x8 ] -adcx r8, r10 -adox r15, r14 -adcx rbx, r15 -adox rcx, r9 -adcx rcx, r9 -mulx r15, r10, [ rax + 0x0 ] -add rcx, rdi -mov r14, r9 -adc r14, 0 -xor r9, r9 -adcx r10, r12 -adox r15, r8 -adcx r11, r15 -adox rsi, rbx -mulx r8, r12, [ rax + 0x10 ] -adox r8, rcx -mulx rcx, rbx, [ rax + 0x18 ] -adcx r12, rsi -adox rcx, r9 -mov rdx, 0x100000000 -adcx rbx, r8 -adc rcx, 0 -mulx rdi, r15, r13 -xor rax, rax -adcx rcx, r14 -adc rax, 0 -xor r9, r9 -adox r15, r10 -mulx r14, r10, r15 -adox rdi, r11 -mov rdx, 0xffffffff00000001 -adox r14, r12 -adcx r10, rdi -mulx r12, r11, r13 -adcx r11, r14 -adox r12, rbx -mulx rbx, r13, r15 -adcx r13, r12 -adox rbx, rcx -mov r8, r9 -adox rax, r9 -adcx r8, rbx -adc rax, 0x0 -mov rcx, rax -mov r15, 0xffffffffffffffff -mov rdi, r10 -sub rdi, r15 -mov r14, 0xffffffff -mov r12, r11 -sbb r12, r14 -mov rbx, r13 -sbb rbx, r9 -mov rax, rax -mov rax, r8 -sbb rax, rdx -sbb rcx, r9 -cmovc rdi, r10 -mov r10, [ rsp - 0x58 ] -cmovc rbx, r13 -mov r13, [ rsp - 0x70 ] +adcq %r15, %r10 +movq 0x8(%rsi), %rdx +mulxq (%rax), %r8, %rbx +adcq $0x0, %r11 +xorq %r15, %r15 +adcxq %r9, %r8 +adoxq %r14, %rbx +movq %rdi, -0x58(%rsp) +mulxq 0x8(%rax), %r9, %rdi +adcxq %rbx, %r9 +adoxq %r10, %rdi +mulxq 0x10(%rax), %r14, %rbx +adcxq %rdi, %r14 +adoxq %r11, %rbx +mulxq 0x18(%rax), %r12, %r13 +adcxq %rbx, %r12 +movq $0x100000000, %rdx +mulxq %rcx, %r10, %r11 +adoxq %r15, %r13 +adcxq %r15, %r13 +xorq %rdi, %rdi +adoxq %r8, %r10 +mulxq %r10, %rbx, %r8 +adoxq %r9, %r11 +adcxq %r11, %rbx +adoxq %r14, %r8 +movq $0xffffffff00000001, %rdx +mulxq %rcx, %r15, %r9 +adcxq %r8, %r15 +adoxq %r12, %r9 +mulxq %r10, %rcx, %r14 +movq 0x10(%rsi), %rdx +mulxq 0x8(%rax), %r12, %r10 +adcxq %r9, %rcx +adoxq %r13, %r14 +mulxq (%rax), %r13, %r11 +movq %rdi, %r9 +adcxq %r9, %r14 +adoxq %rdi, %rdi +adcq $0x0, %rdi +xorq %r9, %r9 +adcxq %rbx, %r13 +adoxq %r15, %r11 +movq 0x10(%rsi), %rdx +mulxq 0x10(%rax), %r8, %r15 +adoxq %rcx, %r10 +mulxq 0x18(%rax), %rbx, %rcx +movq 0x18(%rsi), %rdx +adcxq %r11, %r12 +mulxq 0x8(%rax), %r11, %rsi +adcxq %r10, %r8 +adoxq %r14, %r15 +adcxq %r15, %rbx +adoxq %r9, %rcx +adcxq %r9, %rcx +mulxq (%rax), %r10, %r15 +addq %rdi, %rcx +movq %r9, %r14 +adcq $0x0, %r14 +xorq %r9, %r9 +adcxq %r12, %r10 +adoxq %r8, %r15 +adcxq %r15, %r11 +adoxq %rbx, %rsi +mulxq 0x10(%rax), %r12, %r8 +adoxq %rcx, %r8 +mulxq 0x18(%rax), %rbx, %rcx +adcxq %rsi, %r12 +adoxq %r9, %rcx +movq $0x100000000, %rdx +adcxq %r8, %rbx +adcq $0x0, %rcx +mulxq %r13, %r15, %rdi +xorq %rax, %rax +adcxq %r14, %rcx +adcq $0x0, %rax +xorq %r9, %r9 +adoxq %r10, %r15 +mulxq %r15, %r10, %r14 +adoxq %r11, %rdi +movq $0xffffffff00000001, %rdx +adoxq %r12, %r14 +adcxq %rdi, %r10 +mulxq %r13, %r11, %r12 +adcxq %r14, %r11 +adoxq %rbx, %r12 +mulxq %r15, %r13, %rbx +adcxq %r12, %r13 +adoxq %rcx, %rbx +movq %r9, %r8 +adoxq %r9, %rax +adcxq %rbx, %r8 +adcq $0x0, %rax +movq %rax, %rcx +movq $0xffffffffffffffff, %r15 +movq %r10, %rdi +subq %r15, %rdi +movq $0xffffffff, %r14 +movq %r11, %r12 +sbbq %r14, %r12 +movq %r13, %rbx +sbbq %r9, %rbx +movq %rax, %rax +movq %r8, %rax +sbbq %rdx, %rax +sbbq %r9, %rcx +cmovcq %r10, %rdi +movq -0x58(%rsp), %r10 +cmovcq %r13, %rbx +movq -0x70(%rsp), %r13 .cfi_restore r13 -cmovc r12, r11 -cmovc rax, r8 -mov [ r10 + 0x10 ], rbx -mov rbx, [ rsp - 0x80 ] +cmovcq %r11, %r12 +cmovcq %r8, %rax +movq %rbx, 0x10(%r10) +movq -0x80(%rsp), %rbx .cfi_restore rbx -mov [ r10 + 0x0 ], rdi -mov [ r10 + 0x8 ], r12 -mov [ r10 + 0x18 ], rax -mov r12, [ rsp - 0x78 ] +movq %rdi, (%r10) +movq %r12, 0x8(%r10) +movq %rax, 0x18(%r10) +movq -0x78(%rsp), %r12 .cfi_restore r12 -mov r14, [ rsp - 0x68 ] +movq -0x68(%rsp), %r14 .cfi_restore r14 -mov r15, [ rsp - 0x60 ] +movq -0x60(%rsp), %r15 .cfi_restore r15 -pop rbp +popq %rbp .cfi_restore rbp .cfi_adjust_cfa_offset -8 -ret +retq .cfi_endproc #if defined(__ELF__) .size fiat_p256_adx_mul, .-fiat_p256_adx_mul diff --git a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/asm/fiat_p256_adx_sqr.S b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/asm/fiat_p256_adx_sqr.S index cca269f52f..c4dea9154c 100644 --- a/naiveproxy/src/third_party/boringssl/src/third_party/fiat/asm/fiat_p256_adx_sqr.S +++ b/naiveproxy/src/third_party/boringssl/src/third_party/fiat/asm/fiat_p256_adx_sqr.S @@ -3,7 +3,6 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ (defined(__APPLE__) || defined(__ELF__)) -.intel_syntax noprefix .text #if defined(__APPLE__) .private_extern _fiat_p256_adx_sqr @@ -18,147 +17,147 @@ fiat_p256_adx_sqr: .cfi_startproc _CET_ENDBR -push rbp +pushq %rbp .cfi_adjust_cfa_offset 8 .cfi_offset rbp, -16 -mov rbp, rsp -mov rdx, [ rsi + 0x0 ] -mulx r10, rax, [ rsi + 0x18 ] -mulx rcx, r11, rdx -mulx r9, r8, [ rsi + 0x8 ] -mov [ rsp - 0x80 ], rbx +movq %rsp, %rbp +movq (%rsi), %rdx +mulxq 0x18(%rsi), %rax, %r10 +mulxq %rdx, %r11, %rcx +mulxq 0x8(%rsi), %r8, %r9 +movq %rbx, -0x80(%rsp) .cfi_offset rbx, -16-0x80 -xor rbx, rbx -adox r8, r8 -mov [ rsp - 0x78 ], r12 +xorq %rbx, %rbx +adoxq %r8, %r8 +movq %r12, -0x78(%rsp) .cfi_offset r12, -16-0x78 -mulx r12, rbx, [ rsi + 0x10 ] -mov rdx, [ rsi + 0x8 ] -mov [ rsp - 0x70 ], r13 +mulxq 0x10(%rsi), %rbx, %r12 +movq 0x8(%rsi), %rdx +movq %r13, -0x70(%rsp) .cfi_offset r13, -16-0x70 -mov [ rsp - 0x68 ], r14 +movq %r14, -0x68(%rsp) .cfi_offset r14, -16-0x68 -mulx r14, r13, rdx -mov [ rsp - 0x60 ], r15 +mulxq %rdx, %r13, %r14 +movq %r15, -0x60(%rsp) .cfi_offset r15, -16-0x60 -mov [ rsp - 0x58 ], rdi -mulx rdi, r15, [ rsi + 0x10 ] -adcx r12, r15 -mov [ rsp - 0x50 ], r11 -mulx r11, r15, [ rsi + 0x18 ] -adcx r10, rdi -mov rdi, 0x0 -adcx r11, rdi +movq %rdi, -0x58(%rsp) +mulxq 0x10(%rsi), %r15, %rdi +adcxq %r15, %r12 +movq %r11, -0x50(%rsp) +mulxq 0x18(%rsi), %r15, %r11 +adcxq %rdi, %r10 +movq $0x0, %rdi +adcxq %rdi, %r11 clc -adcx rbx, r9 -adox rbx, rbx -adcx rax, r12 -adox rax, rax -adcx r15, r10 -adox r15, r15 -mov rdx, [ rsi + 0x10 ] -mulx r12, r9, [ rsi + 0x18 ] -adcx r9, r11 -adcx r12, rdi -mulx r11, r10, rdx +adcxq %r9, %rbx +adoxq %rbx, %rbx +adcxq %r12, %rax +adoxq %rax, %rax +adcxq %r10, %r15 +adoxq %r15, %r15 +movq 0x10(%rsi), %rdx +mulxq 0x18(%rsi), %r9, %r12 +adcxq %r11, %r9 +adcxq %rdi, %r12 +mulxq %rdx, %r10, %r11 clc -adcx rcx, r8 -adcx r13, rbx -adcx r14, rax -adox r9, r9 -adcx r10, r15 -mov rdx, [ rsi + 0x18 ] -mulx rbx, r8, rdx -adox r12, r12 -adcx r11, r9 -mov rsi, [ rsp - 0x50 ] -adcx r8, r12 -mov rax, 0x100000000 -mov rdx, rax -mulx r15, rax, rsi -adcx rbx, rdi -adox rbx, rdi -xor r9, r9 -adox rax, rcx -adox r15, r13 -mulx rcx, rdi, rax -adcx rdi, r15 -adox rcx, r14 -mov rdx, 0xffffffff00000001 -mulx r14, r13, rsi -adox r14, r10 -adcx r13, rcx -mulx r12, r10, rax -adox r12, r11 -mov r11, r9 -adox r11, r8 -adcx r10, r14 -mov r8, r9 -adcx r8, r12 -mov rax, r9 -adcx rax, r11 -mov r15, r9 -adox r15, rbx -mov rdx, 0x100000000 -mulx rcx, rbx, rdi -mov r14, r9 -adcx r14, r15 -mov r12, r9 -adox r12, r12 -adcx r12, r9 -adox rbx, r13 -mulx r11, r13, rbx -mov r15, 0xffffffff00000001 -mov rdx, r15 -mulx rsi, r15, rbx -adox rcx, r10 -adox r11, r8 -mulx r8, r10, rdi -adcx r13, rcx -adox r8, rax -adcx r10, r11 -adox rsi, r14 -mov rdi, r12 -mov rax, r9 -adox rdi, rax -adcx r15, r8 -mov r14, rax -adcx r14, rsi -adcx rdi, r9 -dec r9 -mov rbx, r13 -sub rbx, r9 -mov rcx, 0xffffffff -mov r11, r10 -sbb r11, rcx -mov r8, r15 -sbb r8, rax -mov rsi, r14 -sbb rsi, rdx -sbb rdi, rax -cmovc rbx, r13 -cmovc r8, r15 -cmovc r11, r10 -cmovc rsi, r14 -mov rdi, [ rsp - 0x58 ] -mov [ rdi + 0x18 ], rsi -mov [ rdi + 0x0 ], rbx -mov [ rdi + 0x8 ], r11 -mov [ rdi + 0x10 ], r8 -mov rbx, [ rsp - 0x80 ] +adcxq %r8, %rcx +adcxq %rbx, %r13 +adcxq %rax, %r14 +adoxq %r9, %r9 +adcxq %r15, %r10 +movq 0x18(%rsi), %rdx +mulxq %rdx, %r8, %rbx +adoxq %r12, %r12 +adcxq %r9, %r11 +movq -0x50(%rsp), %rsi +adcxq %r12, %r8 +movq $0x100000000, %rax +movq %rax, %rdx +mulxq %rsi, %rax, %r15 +adcxq %rdi, %rbx +adoxq %rdi, %rbx +xorq %r9, %r9 +adoxq %rcx, %rax +adoxq %r13, %r15 +mulxq %rax, %rdi, %rcx +adcxq %r15, %rdi +adoxq %r14, %rcx +movq $0xffffffff00000001, %rdx +mulxq %rsi, %r13, %r14 +adoxq %r10, %r14 +adcxq %rcx, %r13 +mulxq %rax, %r10, %r12 +adoxq %r11, %r12 +movq %r9, %r11 +adoxq %r8, %r11 +adcxq %r14, %r10 +movq %r9, %r8 +adcxq %r12, %r8 +movq %r9, %rax +adcxq %r11, %rax +movq %r9, %r15 +adoxq %rbx, %r15 +movq $0x100000000, %rdx +mulxq %rdi, %rbx, %rcx +movq %r9, %r14 +adcxq %r15, %r14 +movq %r9, %r12 +adoxq %r12, %r12 +adcxq %r9, %r12 +adoxq %r13, %rbx +mulxq %rbx, %r13, %r11 +movq $0xffffffff00000001, %r15 +movq %r15, %rdx +mulxq %rbx, %r15, %rsi +adoxq %r10, %rcx +adoxq %r8, %r11 +mulxq %rdi, %r10, %r8 +adcxq %rcx, %r13 +adoxq %rax, %r8 +adcxq %r11, %r10 +adoxq %r14, %rsi +movq %r12, %rdi +movq %r9, %rax +adoxq %rax, %rdi +adcxq %r8, %r15 +movq %rax, %r14 +adcxq %rsi, %r14 +adcxq %r9, %rdi +decq %r9 +movq %r13, %rbx +subq %r9, %rbx +movq $0xffffffff, %rcx +movq %r10, %r11 +sbbq %rcx, %r11 +movq %r15, %r8 +sbbq %rax, %r8 +movq %r14, %rsi +sbbq %rdx, %rsi +sbbq %rax, %rdi +cmovcq %r13, %rbx +cmovcq %r15, %r8 +cmovcq %r10, %r11 +cmovcq %r14, %rsi +movq -0x58(%rsp), %rdi +movq %rsi, 0x18(%rdi) +movq %rbx, (%rdi) +movq %r11, 0x8(%rdi) +movq %r8, 0x10(%rdi) +movq -0x80(%rsp), %rbx .cfi_restore rbx -mov r12, [ rsp - 0x78 ] +movq -0x78(%rsp), %r12 .cfi_restore r12 -mov r13, [ rsp - 0x70 ] +movq -0x70(%rsp), %r13 .cfi_restore r13 -mov r14, [ rsp - 0x68 ] +movq -0x68(%rsp), %r14 .cfi_restore r14 -mov r15, [ rsp - 0x60 ] +movq -0x60(%rsp), %r15 .cfi_restore r15 -pop rbp +popq %rbp .cfi_restore rbp .cfi_adjust_cfa_offset -8 -ret +retq .cfi_endproc #if defined(__ELF__) .size fiat_p256_adx_sqr, .-fiat_p256_adx_sqr diff --git a/naiveproxy/src/third_party/boringssl/src/tool/speed.cc b/naiveproxy/src/third_party/boringssl/src/tool/speed.cc index d3cc87e726..4390e1e5d0 100644 --- a/naiveproxy/src/third_party/boringssl/src/tool/speed.cc +++ b/naiveproxy/src/third_party/boringssl/src/tool/speed.cc @@ -25,8 +25,6 @@ #include #include -#define OPENSSL_I_UNDERSTAND_EXPERIMENTAL_FUNCTION_RISK - #include #include #include @@ -40,8 +38,11 @@ #include #include #include -#define OPENSSL_UNSTABLE_EXPERIMENTAL_SPX +#define OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM +#include +#define OPENSSL_UNSTABLE_EXPERIMENTAL_KYBER #include +#define OPENSSL_UNSTABLE_EXPERIMENTAL_SPX #include #include #include @@ -1131,6 +1132,117 @@ static bool SpeedKyber(const std::string &selected) { return true; } +static bool SpeedDilithium(const std::string &selected) { + if (!selected.empty() && selected != "Dilithium") { + return true; + } + + TimeResults results; + + auto encoded_public_key = + std::make_unique(DILITHIUM_PUBLIC_KEY_BYTES); + auto priv = std::make_unique(); + if (!TimeFunctionParallel(&results, [&]() -> bool { + if (!DILITHIUM_generate_key(encoded_public_key.get(), priv.get())) { + fprintf(stderr, "Failure in DILITHIUM_generate_key.\n"); + return false; + } + return true; + })) { + fprintf(stderr, "Failed to time DILITHIUM_generate_key.\n"); + return false; + } + + results.Print("Dilithium key generation"); + + auto encoded_private_key = + std::make_unique(DILITHIUM_PRIVATE_KEY_BYTES); + CBB cbb; + CBB_init_fixed(&cbb, encoded_private_key.get(), DILITHIUM_PRIVATE_KEY_BYTES); + DILITHIUM_marshal_private_key(&cbb, priv.get()); + + if (!TimeFunctionParallel(&results, [&]() -> bool { + CBS cbs; + CBS_init(&cbs, encoded_private_key.get(), DILITHIUM_PRIVATE_KEY_BYTES); + if (!DILITHIUM_parse_private_key(priv.get(), &cbs)) { + fprintf(stderr, "Failure in DILITHIUM_parse_private_key.\n"); + return false; + } + return true; + })) { + fprintf(stderr, "Failed to time DILITHIUM_parse_private_key.\n"); + return false; + } + + results.Print("Dilithium parse (valid) private key"); + + const char *message = "Hello world"; + size_t message_len = strlen(message); + auto out_encoded_signature = + std::make_unique(DILITHIUM_SIGNATURE_BYTES); + if (!TimeFunctionParallel(&results, [&]() -> bool { + if (!DILITHIUM_sign(out_encoded_signature.get(), priv.get(), + (const uint8_t *)message, message_len)) { + fprintf(stderr, "Failure in DILITHIUM_sign.\n"); + return false; + } + return true; + })) { + fprintf(stderr, "Failed to time DILITHIUM_sign.\n"); + return false; + } + + results.Print("Dilithium sign (randomized)"); + + auto pub = std::make_unique(); + + if (!TimeFunctionParallel(&results, [&]() -> bool { + CBS cbs; + CBS_init(&cbs, encoded_public_key.get(), DILITHIUM_PUBLIC_KEY_BYTES); + if (!DILITHIUM_parse_public_key(pub.get(), &cbs)) { + fprintf(stderr, "Failure in DILITHIUM_parse_public_key.\n"); + return false; + } + return true; + })) { + fprintf(stderr, "Failed to time DILITHIUM_parse_public_key.\n"); + return false; + } + + results.Print("Dilithium parse (valid) public key"); + + if (!TimeFunctionParallel(&results, [&]() -> bool { + if (!DILITHIUM_verify(pub.get(), out_encoded_signature.get(), + (const uint8_t *)message, message_len)) { + fprintf(stderr, "Failed to verify Dilithium signature.\n"); + return false; + } + return true; + })) { + fprintf(stderr, "Failed to time DILITHIUM_verify.\n"); + return false; + } + + results.Print("Dilithium verify (valid signature)"); + + out_encoded_signature[42] ^= 0x42; + if (!TimeFunctionParallel(&results, [&]() -> bool { + if (DILITHIUM_verify(pub.get(), out_encoded_signature.get(), + (const uint8_t *)message, message_len)) { + fprintf(stderr, "Dilithium signature unexpectedly verified.\n"); + return false; + } + return true; + })) { + fprintf(stderr, "Failed to time DILITHIUM_verify.\n"); + return false; + } + + results.Print("Dilithium verify (invalid signature)"); + + return true; +} + static bool SpeedSpx(const std::string &selected) { if (!selected.empty() && selected.find("spx") == std::string::npos) { return true; @@ -1665,6 +1777,7 @@ bool Speed(const std::vector &args) { !SpeedRSAKeyGen(selected) || // !SpeedHRSS(selected) || // !SpeedKyber(selected) || // + !SpeedDilithium(selected) || // !SpeedSpx(selected) || // !SpeedHashToCurve(selected) || // !SpeedTrustToken("TrustToken-Exp1-Batch1", TRUST_TOKEN_experiment_v1(), 1, diff --git a/naiveproxy/src/third_party/boringssl/src/tool/tool.cc b/naiveproxy/src/third_party/boringssl/src/tool/tool.cc index 96bde33359..7adfdb30a3 100644 --- a/naiveproxy/src/third_party/boringssl/src/tool/tool.cc +++ b/naiveproxy/src/third_party/boringssl/src/tool/tool.cc @@ -111,8 +111,6 @@ int main(int argc, char **argv) { signal(SIGPIPE, SIG_IGN); #endif - CRYPTO_library_init(); - int starting_arg = 1; tool_func_t tool = nullptr; #if !defined(OPENSSL_WINDOWS) diff --git a/naiveproxy/src/third_party/boringssl/src/util/BUILD.toplevel b/naiveproxy/src/third_party/boringssl/src/util/BUILD.toplevel index 48dc920683..e57b6e29df 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/BUILD.toplevel +++ b/naiveproxy/src/third_party/boringssl/src/util/BUILD.toplevel @@ -12,153 +12,26 @@ # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") -load( - ":BUILD.generated.bzl", - "crypto_headers", - "crypto_internal_headers", - "crypto_sources", - "crypto_sources_asm", - "fips_fragments", - "ssl_headers", - "ssl_internal_headers", - "ssl_sources", - "tool_headers", - "tool_sources", -) +# This BUILD file is used as part of the synthesized "-with-bazel" branches. We +# are in the process of transitioning to keeping all builds at tip-of-tree +# directly, see https://crbug.com/boringssl/542. This means, in the synthesized +# branch, "src" now reads as a separate Bazel package. Rather than suppress +# those build files, alias the targets. -licenses(["notice"]) - -exports_files(["LICENSE"]) - -# By default, the C files will expect assembly files, if any, to be linked in -# with the build. This default can be flipped with -DOPENSSL_NO_ASM. If building -# in a configuration where we have no assembly optimizations, -DOPENSSL_NO_ASM -# has no effect, and either value is fine. -# -# Like C files, assembly files are wrapped in #ifdef (or NASM equivalent), so it -# is safe to include a file for the wrong platform in the build. It will just -# output an empty object file. However, we need some platform selectors to -# distinguish between gas or NASM syntax. -# -# For all non-Windows platforms, we use gas assembly syntax and can assume any -# GCC-compatible toolchain includes a gas-compatible assembler. -# -# For Windows, we use NASM on x86 and x86_64 and gas, specifically -# clang-assembler, on aarch64. We have not yet added NASM support to this build, -# and would need to detect MSVC vs clang-cl for aarch64 so, for now, we just -# disable assembly on Windows across the board. -# -# These two selects for asm_sources and asm_copts must be kept in sync. If we -# specify assembly, we don't want OPENSSL_NO_ASM. If we don't specify assembly, -# we want OPENSSL_NO_ASM, in case the C files expect them in some format (e.g. -# NASM) this build file doesn't yet support. -# -# TODO(https://crbug.com/boringssl/531): Enable assembly for Windows. -asm_sources = select({ - "@platforms//os:windows": [], - "//conditions:default": crypto_sources_asm, -}) -asm_copts = select({ - "@platforms//os:windows": ["-DOPENSSL_NO_ASM"], - "//conditions:default": [], -}) - -# Configure C, C++, and common flags for GCC-compatible toolchains. -# -# TODO(davidben): Can we remove some of these? In Bazel, are warnings the -# toolchain or project's responsibility? -Wa,--noexecstack should be unnecessary -# now, though https://crbug.com/boringssl/292 tracks testing this in CI. -# -fno-common did not become default until -# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85678. -gcc_copts = [ - # Assembler option --noexecstack adds .note.GNU-stack to each object to - # ensure that binaries can be built with non-executable stack. - "-Wa,--noexecstack", - - # This list of warnings should match those in the top-level CMakeLists.txt. - "-Wall", - "-Werror", - "-Wformat=2", - "-Wsign-compare", - "-Wmissing-field-initializers", - "-Wwrite-strings", - "-Wshadow", - "-fno-common", -] -gcc_copts_c11 = [ - "-std=c11", - "-Wmissing-prototypes", - "-Wold-style-definition", - "-Wstrict-prototypes", -] -gcc_copts_cxx = [ - "-std=c++14", - "-Wmissing-declarations", -] - -boringssl_copts = [ - "-DBORINGSSL_IMPLEMENTATION", -] + select({ - # We assume that non-Windows builds use a GCC-compatible toolchain and that - # Windows builds do not. - # - # TODO(davidben): Should these be querying something in @bazel_tools? - # Unfortunately, @bazel_tools is undocumented. See - # https://github.com/bazelbuild/bazel/issues/14914 - "@platforms//os:windows": [], - "//conditions:default": gcc_copts, -}) + select({ - # This is needed on glibc systems to get rwlock in pthreads, but it should - # not be set on Apple platforms or FreeBSD, where it instead disables APIs - # we use. - # See compat(5), sys/cdefs.h, and https://crbug.com/boringssl/471 - "@platforms//os:linux": ["-D_XOPEN_SOURCE=700"], - # Without WIN32_LEAN_AND_MEAN, pulls in wincrypt.h, which - # conflicts with our . - "@platforms//os:windows": ["-DWIN32_LEAN_AND_MEAN"], - "//conditions:default": [], -}) + asm_copts - -boringssl_copts_c11 = boringssl_copts + select({ - "@platforms//os:windows": ["/std:c11"], - "//conditions:default": gcc_copts_c11, -}) - -boringssl_copts_cxx = boringssl_copts + select({ - "@platforms//os:windows": [], - "//conditions:default": gcc_copts_cxx, -}) - -cc_library( +alias( name = "crypto", - srcs = crypto_sources + crypto_internal_headers + asm_sources, - hdrs = crypto_headers + fips_fragments, - copts = boringssl_copts_c11, - includes = ["src/include"], - linkopts = select({ - "@platforms//os:windows": ["-defaultlib:advapi32.lib"], - "//conditions:default": ["-pthread"], - }), + actual = "//src:crypto", visibility = ["//visibility:public"], ) -cc_library( +alias( name = "ssl", - srcs = ssl_sources + ssl_internal_headers, - hdrs = ssl_headers, - copts = boringssl_copts_cxx, - includes = ["src/include"], + actual = "//src:ssl", visibility = ["//visibility:public"], - deps = [ - ":crypto", - ], ) -cc_binary( +alias( name = "bssl", - srcs = tool_sources + tool_headers, - copts = boringssl_copts_cxx, + actual = "//src:bssl", visibility = ["//visibility:public"], - deps = [":ssl"], ) diff --git a/naiveproxy/src/third_party/boringssl/src/util/all_tests.go b/naiveproxy/src/third_party/boringssl/src/util/all_tests.go index dad4d4a362..4090943f34 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/all_tests.go +++ b/naiveproxy/src/third_party/boringssl/src/util/all_tests.go @@ -94,8 +94,6 @@ var sdeCPUs = []string{ "clx", // Cascade Lake "cpx", // Cooper Lake "icx", // Ice Lake server - "knl", // Knights landing - "knm", // Knights mill "tgl", // Tiger Lake } @@ -398,15 +396,15 @@ func main() { fmt.Printf("%s\n", test.longName()) fmt.Printf("%s failed to complete: %s\n", args[0], testResult.Error) failed = append(failed, test) - testOutput.AddResult(test.longName(), "CRASH") + testOutput.AddResult(test.longName(), "CRASH", testResult.Error) } else if !testResult.Passed { fmt.Printf("%s\n", test.longName()) fmt.Printf("%s failed to print PASS on the last line.\n", args[0]) failed = append(failed, test) - testOutput.AddResult(test.longName(), "FAIL") + testOutput.AddResult(test.longName(), "FAIL", nil) } else { fmt.Printf("%s\n", test.shortName()) - testOutput.AddResult(test.longName(), "PASS") + testOutput.AddResult(test.longName(), "PASS", nil) } } diff --git a/naiveproxy/src/third_party/boringssl/src/util/bot/DEPS b/naiveproxy/src/third_party/boringssl/src/util/bot/DEPS index b060ca4560..167cee8dbb 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/bot/DEPS +++ b/naiveproxy/src/third_party/boringssl/src/util/bot/DEPS @@ -26,9 +26,9 @@ vars = { # cipd describe PACKAGE_NAME -version latest # infra/3pp/tools/cmake/linux-amd64 - 'cmake_version': 'version:2@3.28.4.chromium.8', + 'cmake_version': 'version:2@3.29.5.chromium.8', # infra/3pp/tools/go/linux-amd64 - 'go_version': 'version:2@1.22.1', + 'go_version': 'version:2@1.22.4', # infra/3pp/tools/perl/windows-amd64 'perl_version': 'version:2@5.32.1.1', @@ -36,26 +36,23 @@ vars = { # https://chromium.googlesource.com/chromium/src/+/main/DEPS 'android_sdk_platform-tools_version': 'HWVsGs2HCKgSVv41FsOcsfJbNcB0UFiNrF6Tc4yRArYC', 'libfuzzer_revision': '758bd21f103a501b362b1ca46fa8fcb692eaa303', - 'libcxx_revision': '80307e66e74bae927fb8709a549859e777e3bf0b', - 'libcxxabi_revision': 'ec88f0ab262c5f2426dbf138b92ee9ae5961e431', + 'libcxx_revision': '852bc6746f45add53fec19f3a29280e69e358d44', + 'libcxxabi_revision': '43dd5b4bf62e8593461dce9a95e3d43fdcd0b9f2', 'ninja_version': 'version:2@1.11.1.chromium.6', - # The Android NDK cannot be updated on CI for two reasons: - # - # Until https://crbug.com/boringssl/454 is fixed, we rely on an older NDK to - # test building without NEON instructions as the baseline. - # - # Until https://crbug.com/boringssl/653 is fixed, we cannot update past - # Chromium's version:2@r25c.cr0 package. Chromium has since switched building - # minimal CIPD packages which do not contain all the NDK files we need. We'll - # probably need to make our own NDK package. - 'android_ndk_revision': '310956bd122ec2b96049f8d7398de6b717f3452e', + # The Android NDK cannot be updated until https://crbug.com/boringssl/454 is fixed. + # We rely on an older NDK to test building without NEON instructions as the baseline. + 'android_ndk_revision': 'U0e8L6l52ySjBrUBB82Vdyhsg60vVMqH0ItTW3TRHAQC', } deps = { 'boringssl/util/bot/android_ndk': { - 'url': Var('chromium_git') + '/android_ndk.git' + '@' + Var('android_ndk_revision'), + 'packages': [{ + 'package': 'infra/3pp/tools/android_ndk/linux-amd64', + 'version': Var('android_ndk_revision'), + }], 'condition': 'checkout_android', + 'dep_type': 'cipd', }, 'boringssl/util/bot/android_sdk/public': { diff --git a/naiveproxy/src/third_party/boringssl/src/util/bot/UPDATING b/naiveproxy/src/third_party/boringssl/src/util/bot/UPDATING index bbe27c754c..8fc0faf763 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/bot/UPDATING +++ b/naiveproxy/src/third_party/boringssl/src/util/bot/UPDATING @@ -38,6 +38,6 @@ but upload it with the following command. (Note the bucket is different.) upload_to_google_storage.py -b chrome-boringssl-sde sde-linux64.tar.xz sde-win32.tar.xz -The current revision is sde-external-9.14.0-2022-10-25-*.tar.xz. +The current revision is sde-external-9.38.0-2024-04-18-*.tar.xz. When adding new files, remember to update .gitignore. diff --git a/naiveproxy/src/third_party/boringssl/src/util/bot/sde-linux64.tar.xz.sha1 b/naiveproxy/src/third_party/boringssl/src/util/bot/sde-linux64.tar.xz.sha1 index 96d3a0dff0..c0f0b0309c 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/bot/sde-linux64.tar.xz.sha1 +++ b/naiveproxy/src/third_party/boringssl/src/util/bot/sde-linux64.tar.xz.sha1 @@ -1 +1 @@ -78e7af6ae04e807282d45828ca3c7d12f4eb1d91 \ No newline at end of file +e63579d20a25860a7963e5e93011c1e3ba914d09 \ No newline at end of file diff --git a/naiveproxy/src/third_party/boringssl/src/util/bot/sde-win32.tar.xz.sha1 b/naiveproxy/src/third_party/boringssl/src/util/bot/sde-win32.tar.xz.sha1 index 18553e83f5..1907b256ae 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/bot/sde-win32.tar.xz.sha1 +++ b/naiveproxy/src/third_party/boringssl/src/util/bot/sde-win32.tar.xz.sha1 @@ -1 +1 @@ -8d3b079358b548a930046fabb6124c943e1d48fb \ No newline at end of file +532993ce76008b0b235a6eed69aeacde9e30facf \ No newline at end of file diff --git a/naiveproxy/src/third_party/boringssl/src/util/bot/update_clang.py b/naiveproxy/src/third_party/boringssl/src/util/bot/update_clang.py index b876921f21..9c5c52d1e4 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/bot/update_clang.py +++ b/naiveproxy/src/third_party/boringssl/src/util/bot/update_clang.py @@ -29,8 +29,8 @@ except ImportError: # CLANG_REVISION and CLANG_SUB_REVISION determine the build of clang # to use. These should be synced with tools/clang/scripts/update.py in # Chromium. -CLANG_REVISION = 'llvmorg-19-init-2941-ga0b3dbaf' -CLANG_SUB_REVISION = 22 +CLANG_REVISION = 'llvmorg-19-init-10646-g084e2b53' +CLANG_SUB_REVISION = 57 PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION) diff --git a/naiveproxy/src/third_party/boringssl/src/util/doc.config b/naiveproxy/src/third_party/boringssl/src/util/doc.config index 213831a843..4beae13b20 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/doc.config +++ b/naiveproxy/src/third_party/boringssl/src/util/doc.config @@ -62,6 +62,7 @@ },{ "Name": "Experimental primitives. Will be removed and replaced when standardized!", "Headers": [ + "include/openssl/experimental/dilithium.h", "include/openssl/experimental/kyber.h", "include/openssl/experimental/spx.h" ] diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go b/naiveproxy/src/third_party/boringssl/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go index f1cb5fa885..0e6ca448b2 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go @@ -141,6 +141,7 @@ func NewWithIO(cmd *exec.Cmd, in io.WriteCloser, out io.ReadCloser) *Subprocess "KAS-FFC-SSC": &kasDH{}, } m.primitives["ECDSA"] = &ecdsa{"ECDSA", map[string]bool{"P-224": true, "P-256": true, "P-384": true, "P-521": true}, m.primitives} + m.primitives["EDDSA"] = &ecdsa{"ECDSA", map[string]bool{"ED-25519": true}, nil} go m.readerRoutine() return m diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc b/naiveproxy/src/third_party/boringssl/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc index dd17f563f0..816bd16072 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc @@ -356,6 +356,21 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl "ivGen": "internal", "ivGenMode": "8.2.2" }, + { + "algorithm": "ACVP-AES-GCM", + "revision": "1.0", + "direction": ["encrypt", "decrypt"], + "keyLen": [128, 192, 256], + "payloadLen": [{ + "min": 0, "max": 65536, "increment": 8 + }], + "aadLen": [{ + "min": 0, "max": 65536, "increment": 8 + }], + "tagLen": [32, 64, 96, 104, 112, 120, 128], + "ivLen": [96], + "ivGen": "external" + }, { "algorithm": "ACVP-AES-GMAC", "revision": "1.0", @@ -496,7 +511,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl { "algorithm": "ECDSA", "mode": "keyGen", - "revision": "1.0", + "revision": "FIPS186-5", "curve": [ "P-224", "P-256", @@ -510,7 +525,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl { "algorithm": "ECDSA", "mode": "keyVer", - "revision": "1.0", + "revision": "FIPS186-5", "curve": [ "P-224", "P-256", @@ -521,7 +536,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl { "algorithm": "ECDSA", "mode": "sigGen", - "revision": "1.0", + "revision": "FIPS186-5", "capabilities": [{ "curve": [ "P-224", @@ -541,7 +556,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl { "algorithm": "ECDSA", "mode": "sigVer", - "revision": "1.0", + "revision": "FIPS186-5", "capabilities": [{ "curve": [ "P-224", @@ -567,21 +582,21 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl "fixedPubExp": "010001", "keyFormat": "standard", "capabilities": [{ - "randPQ": "B.3.3", + "randPQ": "probable", "properties": [{ "modulo": 2048, "primeTest": [ - "tblC2" + "2powSecStr" ] },{ "modulo": 3072, "primeTest": [ - "tblC2" + "2powSecStr" ] },{ "modulo": 4096, "primeTest": [ - "tblC2" + "2powSecStr" ] }] }] @@ -635,6 +650,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl },{ "sigType": "pss", "properties": [{ + "maskFunction": ["mgf1"], "modulo": 2048, "hashPair": [{ "hashAlg": "SHA2-224", @@ -656,6 +672,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl },{ "sigType": "pss", "properties": [{ + "maskFunction": ["mgf1"], "modulo": 3072, "hashPair": [{ "hashAlg": "SHA2-224", @@ -677,6 +694,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl },{ "sigType": "pss", "properties": [{ + "maskFunction": ["mgf1"], "modulo": 4096, "hashPair": [{ "hashAlg": "SHA2-224", @@ -748,6 +766,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl },{ "sigType": "pss", "properties": [{ + "maskFunction": ["mgf1"], "modulo": 2048, "hashPair": [{ "hashAlg": "SHA2-224", @@ -769,6 +788,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl },{ "sigType": "pss", "properties": [{ + "maskFunction": ["mgf1"], "modulo": 3072, "hashPair": [{ "hashAlg": "SHA2-224", @@ -790,6 +810,7 @@ static bool GetConfig(const Span args[], ReplyCallback write_repl },{ "sigType": "pss", "properties": [{ + "maskFunction": ["mgf1"], "modulo": 4096, "hashPair": [{ "hashAlg": "SHA2-224", diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.go b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.go index 063d6ac6e7..884344d559 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.go +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.go @@ -923,6 +923,12 @@ func (d *delocation) isRIPRelative(node *node32) bool { } func (d *delocation) processIntelInstruction(statement, instruction *node32) (*node32, error) { + var prefix string + if instruction.pegRule == ruleInstructionPrefix { + prefix = d.contents(instruction) + instruction = skipWS(instruction.next) + } + assertNodeType(instruction, ruleInstructionName) instructionName := d.contents(instruction) @@ -1240,6 +1246,9 @@ Args: if changed { d.writeCommentedNode(statement) replacement := "\t" + instructionName + "\t" + strings.Join(args, ", ") + "\n" + if len(prefix) != 0 { + replacement = "\t" + prefix + replacement + } wrappers.do(func() { d.output.WriteString(replacement) }) diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.peg b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.peg index 3ce01edf26..c719859803 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.peg +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.peg @@ -50,7 +50,7 @@ SymbolArgs <- SymbolArg ((WS? ',' WS?) SymbolArg)* SymbolArg <- SymbolExpr SymbolExpr <- SymbolAtom (WS? SymbolOperator WS? SymbolExpr)? -SymbolAtom <- Offset / SymbolType / LocalSymbol TCMarker? / SymbolName Offset / SymbolName TCMarker? / Dot / OpenParen WS? SymbolExpr WS? CloseParen +SymbolAtom <- LocalLabelRef / Offset / SymbolType / LocalSymbol TCMarker? / SymbolName Offset / SymbolName TCMarker? / Dot / OpenParen WS? SymbolExpr WS? CloseParen SymbolOperator <- '+' / '-' / '|' / '<<' / '>>' OpenParen <- '(' CloseParen <- ')' @@ -66,7 +66,8 @@ SymbolName <- [[A-Z._]][[A-Z.0-9$_]]* LocalSymbol <- '.L' [[A-Za-z.0-9$_]]+ LocalLabel <- [0-9][0-9$]* LocalLabelRef <- [0-9][0-9$]*[bf] -Instruction <- InstructionName (WS InstructionArg ((WS? ',' WS?) InstructionArg)*)? +InstructionPrefix <- "notrack" +Instruction <- (InstructionPrefix WS)? InstructionName (WS InstructionArg ((WS? ',' WS?) InstructionArg)*)? InstructionName <- [[A-Z]][[A-Z.0-9]]* [.+\-]? InstructionArg <- IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTAddress / GOTSymbolOffset / MemoryRef) AVX512Token* GOTLocation <- '$_GLOBAL_OFFSET_TABLE_-' LocalSymbol diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.peg.go b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.peg.go index 856518d9dc..ee8a108079 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.peg.go +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/delocate.peg.go @@ -1,6 +1,6 @@ package main -// Code generated by ./peg/peg delocate.peg DO NOT EDIT. +// Code generated by peg delocate.peg DO NOT EDIT. import ( "fmt" @@ -50,6 +50,7 @@ const ( ruleLocalSymbol ruleLocalLabel ruleLocalLabelRef + ruleInstructionPrefix ruleInstruction ruleInstructionName ruleInstructionArg @@ -113,6 +114,7 @@ var rul3s = [...]string{ "LocalSymbol", "LocalLabel", "LocalLabelRef", + "InstructionPrefix", "Instruction", "InstructionName", "InstructionArg", @@ -254,7 +256,7 @@ func (t *tokens32) Tokens() []token32 { type Asm struct { Buffer string buffer []rune - rules [60]func() bool + rules [61]func() bool parse func(rule ...int) error reset func() Pretty bool @@ -2668,98 +2670,104 @@ func (p *Asm) Init(options ...func(*Asm) error) error { position, tokenIndex = position304, tokenIndex304 return false }, - /* 17 SymbolAtom <- <(Offset / SymbolType / (LocalSymbol TCMarker?) / (SymbolName Offset) / (SymbolName TCMarker?) / Dot / (OpenParen WS? SymbolExpr WS? CloseParen))> */ + /* 17 SymbolAtom <- <(LocalLabelRef / Offset / SymbolType / (LocalSymbol TCMarker?) / (SymbolName Offset) / (SymbolName TCMarker?) / Dot / (OpenParen WS? SymbolExpr WS? CloseParen))> */ func() bool { position312, tokenIndex312 := position, tokenIndex { position313 := position { position314, tokenIndex314 := position, tokenIndex - if !_rules[ruleOffset]() { + if !_rules[ruleLocalLabelRef]() { goto l315 } goto l314 l315: position, tokenIndex = position314, tokenIndex314 - if !_rules[ruleSymbolType]() { + if !_rules[ruleOffset]() { goto l316 } goto l314 l316: position, tokenIndex = position314, tokenIndex314 - if !_rules[ruleLocalSymbol]() { + if !_rules[ruleSymbolType]() { goto l317 } - { - position318, tokenIndex318 := position, tokenIndex - if !_rules[ruleTCMarker]() { - goto l318 - } - goto l319 - l318: - position, tokenIndex = position318, tokenIndex318 - } - l319: goto l314 l317: position, tokenIndex = position314, tokenIndex314 - if !_rules[ruleSymbolName]() { - goto l320 + if !_rules[ruleLocalSymbol]() { + goto l318 } - if !_rules[ruleOffset]() { + { + position319, tokenIndex319 := position, tokenIndex + if !_rules[ruleTCMarker]() { + goto l319 + } goto l320 + l319: + position, tokenIndex = position319, tokenIndex319 } - goto l314 l320: + goto l314 + l318: position, tokenIndex = position314, tokenIndex314 if !_rules[ruleSymbolName]() { goto l321 } - { - position322, tokenIndex322 := position, tokenIndex - if !_rules[ruleTCMarker]() { - goto l322 - } - goto l323 - l322: - position, tokenIndex = position322, tokenIndex322 + if !_rules[ruleOffset]() { + goto l321 } - l323: goto l314 l321: position, tokenIndex = position314, tokenIndex314 - if !_rules[ruleDot]() { + if !_rules[ruleSymbolName]() { + goto l322 + } + { + position323, tokenIndex323 := position, tokenIndex + if !_rules[ruleTCMarker]() { + goto l323 + } goto l324 + l323: + position, tokenIndex = position323, tokenIndex323 + } + l324: + goto l314 + l322: + position, tokenIndex = position314, tokenIndex314 + if !_rules[ruleDot]() { + goto l325 } goto l314 - l324: + l325: position, tokenIndex = position314, tokenIndex314 if !_rules[ruleOpenParen]() { goto l312 } { - position325, tokenIndex325 := position, tokenIndex + position326, tokenIndex326 := position, tokenIndex if !_rules[ruleWS]() { - goto l325 + goto l326 } - goto l326 - l325: - position, tokenIndex = position325, tokenIndex325 + goto l327 + l326: + position, tokenIndex = position326, tokenIndex326 } - l326: + l327: if !_rules[ruleSymbolExpr]() { goto l312 } { - position327, tokenIndex327 := position, tokenIndex + position328, tokenIndex328 := position, tokenIndex if !_rules[ruleWS]() { - goto l327 + goto l328 } - goto l328 - l327: - position, tokenIndex = position327, tokenIndex327 + goto l329 + l328: + position, tokenIndex = position328, tokenIndex328 } - l328: + l329: if !_rules[ruleCloseParen]() { goto l312 } @@ -2774,3290 +2782,3279 @@ func (p *Asm) Init(options ...func(*Asm) error) error { }, /* 18 SymbolOperator <- <('+' / '-' / '|' / ('<' '<') / ('>' '>'))> */ func() bool { - position329, tokenIndex329 := position, tokenIndex + position330, tokenIndex330 := position, tokenIndex { - position330 := position + position331 := position { - position331, tokenIndex331 := position, tokenIndex + position332, tokenIndex332 := position, tokenIndex if buffer[position] != rune('+') { - goto l332 - } - position++ - goto l331 - l332: - position, tokenIndex = position331, tokenIndex331 - if buffer[position] != rune('-') { goto l333 } position++ - goto l331 + goto l332 l333: - position, tokenIndex = position331, tokenIndex331 - if buffer[position] != rune('|') { + position, tokenIndex = position332, tokenIndex332 + if buffer[position] != rune('-') { goto l334 } position++ - goto l331 + goto l332 l334: - position, tokenIndex = position331, tokenIndex331 - if buffer[position] != rune('<') { + position, tokenIndex = position332, tokenIndex332 + if buffer[position] != rune('|') { goto l335 } position++ - if buffer[position] != rune('<') { - goto l335 - } - position++ - goto l331 + goto l332 l335: - position, tokenIndex = position331, tokenIndex331 + position, tokenIndex = position332, tokenIndex332 + if buffer[position] != rune('<') { + goto l336 + } + position++ + if buffer[position] != rune('<') { + goto l336 + } + position++ + goto l332 + l336: + position, tokenIndex = position332, tokenIndex332 if buffer[position] != rune('>') { - goto l329 + goto l330 } position++ if buffer[position] != rune('>') { - goto l329 + goto l330 } position++ } - l331: - add(ruleSymbolOperator, position330) + l332: + add(ruleSymbolOperator, position331) } return true - l329: - position, tokenIndex = position329, tokenIndex329 + l330: + position, tokenIndex = position330, tokenIndex330 return false }, /* 19 OpenParen <- <'('> */ func() bool { - position336, tokenIndex336 := position, tokenIndex + position337, tokenIndex337 := position, tokenIndex { - position337 := position + position338 := position if buffer[position] != rune('(') { - goto l336 + goto l337 } position++ - add(ruleOpenParen, position337) + add(ruleOpenParen, position338) } return true - l336: - position, tokenIndex = position336, tokenIndex336 + l337: + position, tokenIndex = position337, tokenIndex337 return false }, /* 20 CloseParen <- <')'> */ func() bool { - position338, tokenIndex338 := position, tokenIndex + position339, tokenIndex339 := position, tokenIndex { - position339 := position + position340 := position if buffer[position] != rune(')') { - goto l338 + goto l339 } position++ - add(ruleCloseParen, position339) + add(ruleCloseParen, position340) } return true - l338: - position, tokenIndex = position338, tokenIndex338 + l339: + position, tokenIndex = position339, tokenIndex339 return false }, /* 21 SymbolType <- <(('@' / '%') (('f' 'u' 'n' 'c' 't' 'i' 'o' 'n') / ('o' 'b' 'j' 'e' 'c' 't')))> */ func() bool { - position340, tokenIndex340 := position, tokenIndex + position341, tokenIndex341 := position, tokenIndex { - position341 := position + position342 := position { - position342, tokenIndex342 := position, tokenIndex + position343, tokenIndex343 := position, tokenIndex if buffer[position] != rune('@') { - goto l343 + goto l344 } position++ - goto l342 - l343: - position, tokenIndex = position342, tokenIndex342 + goto l343 + l344: + position, tokenIndex = position343, tokenIndex343 if buffer[position] != rune('%') { - goto l340 + goto l341 } position++ } - l342: + l343: { - position344, tokenIndex344 := position, tokenIndex + position345, tokenIndex345 := position, tokenIndex if buffer[position] != rune('f') { - goto l345 + goto l346 } position++ if buffer[position] != rune('u') { - goto l345 + goto l346 } position++ if buffer[position] != rune('n') { - goto l345 + goto l346 } position++ if buffer[position] != rune('c') { - goto l345 + goto l346 } position++ if buffer[position] != rune('t') { - goto l345 + goto l346 } position++ if buffer[position] != rune('i') { - goto l345 + goto l346 } position++ if buffer[position] != rune('o') { - goto l345 + goto l346 } position++ if buffer[position] != rune('n') { - goto l345 + goto l346 } position++ - goto l344 - l345: - position, tokenIndex = position344, tokenIndex344 + goto l345 + l346: + position, tokenIndex = position345, tokenIndex345 if buffer[position] != rune('o') { - goto l340 + goto l341 } position++ if buffer[position] != rune('b') { - goto l340 + goto l341 } position++ if buffer[position] != rune('j') { - goto l340 + goto l341 } position++ if buffer[position] != rune('e') { - goto l340 + goto l341 } position++ if buffer[position] != rune('c') { - goto l340 + goto l341 } position++ if buffer[position] != rune('t') { - goto l340 + goto l341 } position++ } - l344: - add(ruleSymbolType, position341) + l345: + add(ruleSymbolType, position342) } return true - l340: - position, tokenIndex = position340, tokenIndex340 + l341: + position, tokenIndex = position341, tokenIndex341 return false }, /* 22 Dot <- <'.'> */ func() bool { - position346, tokenIndex346 := position, tokenIndex + position347, tokenIndex347 := position, tokenIndex { - position347 := position + position348 := position if buffer[position] != rune('.') { - goto l346 + goto l347 } position++ - add(ruleDot, position347) + add(ruleDot, position348) } return true - l346: - position, tokenIndex = position346, tokenIndex346 + l347: + position, tokenIndex = position347, tokenIndex347 return false }, /* 23 TCMarker <- <('[' 'T' 'C' ']')> */ func() bool { - position348, tokenIndex348 := position, tokenIndex + position349, tokenIndex349 := position, tokenIndex { - position349 := position + position350 := position if buffer[position] != rune('[') { - goto l348 + goto l349 } position++ if buffer[position] != rune('T') { - goto l348 + goto l349 } position++ if buffer[position] != rune('C') { - goto l348 + goto l349 } position++ if buffer[position] != rune(']') { - goto l348 + goto l349 } position++ - add(ruleTCMarker, position349) + add(ruleTCMarker, position350) } return true - l348: - position, tokenIndex = position348, tokenIndex348 + l349: + position, tokenIndex = position349, tokenIndex349 return false }, /* 24 EscapedChar <- <('\\' .)> */ func() bool { - position350, tokenIndex350 := position, tokenIndex + position351, tokenIndex351 := position, tokenIndex { - position351 := position + position352 := position if buffer[position] != rune('\\') { - goto l350 + goto l351 } position++ if !matchDot() { - goto l350 + goto l351 } - add(ruleEscapedChar, position351) + add(ruleEscapedChar, position352) } return true - l350: - position, tokenIndex = position350, tokenIndex350 + l351: + position, tokenIndex = position351, tokenIndex351 return false }, /* 25 WS <- <(' ' / '\t')+> */ func() bool { - position352, tokenIndex352 := position, tokenIndex + position353, tokenIndex353 := position, tokenIndex { - position353 := position + position354 := position + { + position357, tokenIndex357 := position, tokenIndex + if buffer[position] != rune(' ') { + goto l358 + } + position++ + goto l357 + l358: + position, tokenIndex = position357, tokenIndex357 + if buffer[position] != rune('\t') { + goto l353 + } + position++ + } + l357: + l355: { position356, tokenIndex356 := position, tokenIndex - if buffer[position] != rune(' ') { - goto l357 - } - position++ - goto l356 - l357: - position, tokenIndex = position356, tokenIndex356 - if buffer[position] != rune('\t') { - goto l352 - } - position++ - } - l356: - l354: - { - position355, tokenIndex355 := position, tokenIndex { - position358, tokenIndex358 := position, tokenIndex + position359, tokenIndex359 := position, tokenIndex if buffer[position] != rune(' ') { - goto l359 + goto l360 } position++ - goto l358 - l359: - position, tokenIndex = position358, tokenIndex358 + goto l359 + l360: + position, tokenIndex = position359, tokenIndex359 if buffer[position] != rune('\t') { - goto l355 + goto l356 } position++ } - l358: - goto l354 - l355: - position, tokenIndex = position355, tokenIndex355 + l359: + goto l355 + l356: + position, tokenIndex = position356, tokenIndex356 } - add(ruleWS, position353) + add(ruleWS, position354) } return true - l352: - position, tokenIndex = position352, tokenIndex352 + l353: + position, tokenIndex = position353, tokenIndex353 return false }, /* 26 Comment <- <((('/' '/') / '#') (!'\n' .)*)> */ func() bool { - position360, tokenIndex360 := position, tokenIndex + position361, tokenIndex361 := position, tokenIndex { - position361 := position + position362 := position { - position362, tokenIndex362 := position, tokenIndex + position363, tokenIndex363 := position, tokenIndex if buffer[position] != rune('/') { - goto l363 + goto l364 } position++ if buffer[position] != rune('/') { - goto l363 + goto l364 } position++ - goto l362 - l363: - position, tokenIndex = position362, tokenIndex362 + goto l363 + l364: + position, tokenIndex = position363, tokenIndex363 if buffer[position] != rune('#') { - goto l360 + goto l361 } position++ } - l362: - l364: + l363: + l365: { - position365, tokenIndex365 := position, tokenIndex + position366, tokenIndex366 := position, tokenIndex { - position366, tokenIndex366 := position, tokenIndex + position367, tokenIndex367 := position, tokenIndex if buffer[position] != rune('\n') { - goto l366 + goto l367 } position++ - goto l365 - l366: - position, tokenIndex = position366, tokenIndex366 + goto l366 + l367: + position, tokenIndex = position367, tokenIndex367 } if !matchDot() { - goto l365 + goto l366 } - goto l364 - l365: - position, tokenIndex = position365, tokenIndex365 + goto l365 + l366: + position, tokenIndex = position366, tokenIndex366 } - add(ruleComment, position361) + add(ruleComment, position362) } return true - l360: - position, tokenIndex = position360, tokenIndex360 + l361: + position, tokenIndex = position361, tokenIndex361 return false }, /* 27 Label <- <((LocalSymbol / LocalLabel / SymbolName) ':')> */ func() bool { - position367, tokenIndex367 := position, tokenIndex + position368, tokenIndex368 := position, tokenIndex { - position368 := position + position369 := position { - position369, tokenIndex369 := position, tokenIndex + position370, tokenIndex370 := position, tokenIndex if !_rules[ruleLocalSymbol]() { - goto l370 - } - goto l369 - l370: - position, tokenIndex = position369, tokenIndex369 - if !_rules[ruleLocalLabel]() { goto l371 } - goto l369 + goto l370 l371: - position, tokenIndex = position369, tokenIndex369 + position, tokenIndex = position370, tokenIndex370 + if !_rules[ruleLocalLabel]() { + goto l372 + } + goto l370 + l372: + position, tokenIndex = position370, tokenIndex370 if !_rules[ruleSymbolName]() { - goto l367 + goto l368 } } - l369: + l370: if buffer[position] != rune(':') { - goto l367 + goto l368 } position++ - add(ruleLabel, position368) + add(ruleLabel, position369) } return true - l367: - position, tokenIndex = position367, tokenIndex367 + l368: + position, tokenIndex = position368, tokenIndex368 return false }, /* 28 SymbolName <- <(([a-z] / [A-Z] / '.' / '_') ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]) / '$' / '_')*)> */ func() bool { - position372, tokenIndex372 := position, tokenIndex + position373, tokenIndex373 := position, tokenIndex { - position373 := position + position374 := position { - position374, tokenIndex374 := position, tokenIndex + position375, tokenIndex375 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l375 - } - position++ - goto l374 - l375: - position, tokenIndex = position374, tokenIndex374 - if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l376 } position++ - goto l374 + goto l375 l376: - position, tokenIndex = position374, tokenIndex374 - if buffer[position] != rune('.') { + position, tokenIndex = position375, tokenIndex375 + if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l377 } position++ - goto l374 + goto l375 l377: - position, tokenIndex = position374, tokenIndex374 + position, tokenIndex = position375, tokenIndex375 + if buffer[position] != rune('.') { + goto l378 + } + position++ + goto l375 + l378: + position, tokenIndex = position375, tokenIndex375 if buffer[position] != rune('_') { - goto l372 + goto l373 } position++ } - l374: - l378: + l375: + l379: { - position379, tokenIndex379 := position, tokenIndex + position380, tokenIndex380 := position, tokenIndex { - position380, tokenIndex380 := position, tokenIndex + position381, tokenIndex381 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l381 - } - position++ - goto l380 - l381: - position, tokenIndex = position380, tokenIndex380 - if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l382 } position++ - goto l380 + goto l381 l382: - position, tokenIndex = position380, tokenIndex380 - if buffer[position] != rune('.') { + position, tokenIndex = position381, tokenIndex381 + if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l383 } position++ - goto l380 + goto l381 l383: - position, tokenIndex = position380, tokenIndex380 - { - position385, tokenIndex385 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l386 - } - position++ - goto l385 - l386: - position, tokenIndex = position385, tokenIndex385 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l384 - } - position++ - } - l385: - goto l380 - l384: - position, tokenIndex = position380, tokenIndex380 - if buffer[position] != rune('$') { - goto l387 + position, tokenIndex = position381, tokenIndex381 + if buffer[position] != rune('.') { + goto l384 } position++ - goto l380 - l387: - position, tokenIndex = position380, tokenIndex380 + goto l381 + l384: + position, tokenIndex = position381, tokenIndex381 + { + position386, tokenIndex386 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l387 + } + position++ + goto l386 + l387: + position, tokenIndex = position386, tokenIndex386 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l385 + } + position++ + } + l386: + goto l381 + l385: + position, tokenIndex = position381, tokenIndex381 + if buffer[position] != rune('$') { + goto l388 + } + position++ + goto l381 + l388: + position, tokenIndex = position381, tokenIndex381 if buffer[position] != rune('_') { - goto l379 + goto l380 } position++ } + l381: + goto l379 l380: - goto l378 - l379: - position, tokenIndex = position379, tokenIndex379 + position, tokenIndex = position380, tokenIndex380 } - add(ruleSymbolName, position373) + add(ruleSymbolName, position374) } return true - l372: - position, tokenIndex = position372, tokenIndex372 + l373: + position, tokenIndex = position373, tokenIndex373 return false }, /* 29 LocalSymbol <- <('.' 'L' ([a-z] / [A-Z] / ([a-z] / [A-Z]) / '.' / ([0-9] / [0-9]) / '$' / '_')+)> */ func() bool { - position388, tokenIndex388 := position, tokenIndex + position389, tokenIndex389 := position, tokenIndex { - position389 := position + position390 := position if buffer[position] != rune('.') { - goto l388 + goto l389 } position++ if buffer[position] != rune('L') { - goto l388 + goto l389 } position++ { - position392, tokenIndex392 := position, tokenIndex + position393, tokenIndex393 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l393 - } - position++ - goto l392 - l393: - position, tokenIndex = position392, tokenIndex392 - if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l394 } position++ - goto l392 + goto l393 l394: - position, tokenIndex = position392, tokenIndex392 - { - position396, tokenIndex396 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l397 - } - position++ - goto l396 - l397: - position, tokenIndex = position396, tokenIndex396 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l395 - } - position++ + position, tokenIndex = position393, tokenIndex393 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l395 } - l396: - goto l392 + position++ + goto l393 l395: - position, tokenIndex = position392, tokenIndex392 - if buffer[position] != rune('.') { - goto l398 - } - position++ - goto l392 - l398: - position, tokenIndex = position392, tokenIndex392 + position, tokenIndex = position393, tokenIndex393 { - position400, tokenIndex400 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l401 + position397, tokenIndex397 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l398 } position++ - goto l400 - l401: - position, tokenIndex = position400, tokenIndex400 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l399 + goto l397 + l398: + position, tokenIndex = position397, tokenIndex397 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l396 } position++ } - l400: - goto l392 - l399: - position, tokenIndex = position392, tokenIndex392 - if buffer[position] != rune('$') { - goto l402 + l397: + goto l393 + l396: + position, tokenIndex = position393, tokenIndex393 + if buffer[position] != rune('.') { + goto l399 } position++ - goto l392 - l402: - position, tokenIndex = position392, tokenIndex392 + goto l393 + l399: + position, tokenIndex = position393, tokenIndex393 + { + position401, tokenIndex401 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l402 + } + position++ + goto l401 + l402: + position, tokenIndex = position401, tokenIndex401 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l400 + } + position++ + } + l401: + goto l393 + l400: + position, tokenIndex = position393, tokenIndex393 + if buffer[position] != rune('$') { + goto l403 + } + position++ + goto l393 + l403: + position, tokenIndex = position393, tokenIndex393 if buffer[position] != rune('_') { - goto l388 + goto l389 } position++ } - l392: - l390: + l393: + l391: { - position391, tokenIndex391 := position, tokenIndex + position392, tokenIndex392 := position, tokenIndex { - position403, tokenIndex403 := position, tokenIndex + position404, tokenIndex404 := position, tokenIndex if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l404 - } - position++ - goto l403 - l404: - position, tokenIndex = position403, tokenIndex403 - if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l405 } position++ - goto l403 + goto l404 l405: - position, tokenIndex = position403, tokenIndex403 - { - position407, tokenIndex407 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l408 - } - position++ - goto l407 - l408: - position, tokenIndex = position407, tokenIndex407 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l406 - } - position++ + position, tokenIndex = position404, tokenIndex404 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l406 } - l407: - goto l403 + position++ + goto l404 l406: - position, tokenIndex = position403, tokenIndex403 - if buffer[position] != rune('.') { - goto l409 - } - position++ - goto l403 - l409: - position, tokenIndex = position403, tokenIndex403 + position, tokenIndex = position404, tokenIndex404 { - position411, tokenIndex411 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l412 + position408, tokenIndex408 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l409 } position++ - goto l411 - l412: - position, tokenIndex = position411, tokenIndex411 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l410 + goto l408 + l409: + position, tokenIndex = position408, tokenIndex408 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l407 } position++ } - l411: - goto l403 - l410: - position, tokenIndex = position403, tokenIndex403 - if buffer[position] != rune('$') { - goto l413 + l408: + goto l404 + l407: + position, tokenIndex = position404, tokenIndex404 + if buffer[position] != rune('.') { + goto l410 } position++ - goto l403 - l413: - position, tokenIndex = position403, tokenIndex403 + goto l404 + l410: + position, tokenIndex = position404, tokenIndex404 + { + position412, tokenIndex412 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l413 + } + position++ + goto l412 + l413: + position, tokenIndex = position412, tokenIndex412 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l411 + } + position++ + } + l412: + goto l404 + l411: + position, tokenIndex = position404, tokenIndex404 + if buffer[position] != rune('$') { + goto l414 + } + position++ + goto l404 + l414: + position, tokenIndex = position404, tokenIndex404 if buffer[position] != rune('_') { - goto l391 + goto l392 } position++ } - l403: - goto l390 - l391: - position, tokenIndex = position391, tokenIndex391 + l404: + goto l391 + l392: + position, tokenIndex = position392, tokenIndex392 } - add(ruleLocalSymbol, position389) + add(ruleLocalSymbol, position390) } return true - l388: - position, tokenIndex = position388, tokenIndex388 + l389: + position, tokenIndex = position389, tokenIndex389 return false }, /* 30 LocalLabel <- <([0-9] ([0-9] / '$')*)> */ func() bool { - position414, tokenIndex414 := position, tokenIndex + position415, tokenIndex415 := position, tokenIndex { - position415 := position + position416 := position if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l414 + goto l415 } position++ - l416: + l417: { - position417, tokenIndex417 := position, tokenIndex + position418, tokenIndex418 := position, tokenIndex { - position418, tokenIndex418 := position, tokenIndex + position419, tokenIndex419 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l419 + goto l420 } position++ - goto l418 - l419: - position, tokenIndex = position418, tokenIndex418 + goto l419 + l420: + position, tokenIndex = position419, tokenIndex419 if buffer[position] != rune('$') { - goto l417 + goto l418 } position++ } + l419: + goto l417 l418: - goto l416 - l417: - position, tokenIndex = position417, tokenIndex417 + position, tokenIndex = position418, tokenIndex418 } - add(ruleLocalLabel, position415) + add(ruleLocalLabel, position416) } return true - l414: - position, tokenIndex = position414, tokenIndex414 + l415: + position, tokenIndex = position415, tokenIndex415 return false }, /* 31 LocalLabelRef <- <([0-9] ([0-9] / '$')* ('b' / 'f'))> */ func() bool { - position420, tokenIndex420 := position, tokenIndex + position421, tokenIndex421 := position, tokenIndex { - position421 := position + position422 := position if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l420 + goto l421 } position++ - l422: + l423: { - position423, tokenIndex423 := position, tokenIndex + position424, tokenIndex424 := position, tokenIndex { - position424, tokenIndex424 := position, tokenIndex + position425, tokenIndex425 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l425 + goto l426 } position++ - goto l424 - l425: - position, tokenIndex = position424, tokenIndex424 + goto l425 + l426: + position, tokenIndex = position425, tokenIndex425 if buffer[position] != rune('$') { - goto l423 + goto l424 } position++ } + l425: + goto l423 l424: - goto l422 - l423: - position, tokenIndex = position423, tokenIndex423 + position, tokenIndex = position424, tokenIndex424 } { - position426, tokenIndex426 := position, tokenIndex + position427, tokenIndex427 := position, tokenIndex if buffer[position] != rune('b') { - goto l427 + goto l428 } position++ - goto l426 - l427: - position, tokenIndex = position426, tokenIndex426 + goto l427 + l428: + position, tokenIndex = position427, tokenIndex427 if buffer[position] != rune('f') { - goto l420 + goto l421 } position++ } - l426: - add(ruleLocalLabelRef, position421) + l427: + add(ruleLocalLabelRef, position422) } return true - l420: - position, tokenIndex = position420, tokenIndex420 + l421: + position, tokenIndex = position421, tokenIndex421 return false }, - /* 32 Instruction <- <(InstructionName (WS InstructionArg (WS? ',' WS? InstructionArg)*)?)> */ + /* 32 InstructionPrefix <- <(('n' / 'N') ('o' / 'O') ('t' / 'T') ('r' / 'R') ('a' / 'A') ('c' / 'C') ('k' / 'K'))> */ func() bool { - position428, tokenIndex428 := position, tokenIndex + position429, tokenIndex429 := position, tokenIndex { - position429 := position - if !_rules[ruleInstructionName]() { - goto l428 - } + position430 := position { - position430, tokenIndex430 := position, tokenIndex - if !_rules[ruleWS]() { - goto l430 - } - if !_rules[ruleInstructionArg]() { - goto l430 - } - l432: - { - position433, tokenIndex433 := position, tokenIndex - { - position434, tokenIndex434 := position, tokenIndex - if !_rules[ruleWS]() { - goto l434 - } - goto l435 - l434: - position, tokenIndex = position434, tokenIndex434 - } - l435: - if buffer[position] != rune(',') { - goto l433 - } - position++ - { - position436, tokenIndex436 := position, tokenIndex - if !_rules[ruleWS]() { - goto l436 - } - goto l437 - l436: - position, tokenIndex = position436, tokenIndex436 - } - l437: - if !_rules[ruleInstructionArg]() { - goto l433 - } + position431, tokenIndex431 := position, tokenIndex + if buffer[position] != rune('n') { goto l432 - l433: - position, tokenIndex = position433, tokenIndex433 } + position++ goto l431 - l430: - position, tokenIndex = position430, tokenIndex430 + l432: + position, tokenIndex = position431, tokenIndex431 + if buffer[position] != rune('N') { + goto l429 + } + position++ } l431: - add(ruleInstruction, position429) - } - return true - l428: - position, tokenIndex = position428, tokenIndex428 - return false - }, - /* 33 InstructionName <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]))* ('.' / '+' / '-')?)> */ - func() bool { - position438, tokenIndex438 := position, tokenIndex - { - position439 := position { - position440, tokenIndex440 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l441 + position433, tokenIndex433 := position, tokenIndex + if buffer[position] != rune('o') { + goto l434 } position++ - goto l440 - l441: - position, tokenIndex = position440, tokenIndex440 - if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l433 + l434: + position, tokenIndex = position433, tokenIndex433 + if buffer[position] != rune('O') { + goto l429 + } + position++ + } + l433: + { + position435, tokenIndex435 := position, tokenIndex + if buffer[position] != rune('t') { + goto l436 + } + position++ + goto l435 + l436: + position, tokenIndex = position435, tokenIndex435 + if buffer[position] != rune('T') { + goto l429 + } + position++ + } + l435: + { + position437, tokenIndex437 := position, tokenIndex + if buffer[position] != rune('r') { goto l438 } position++ + goto l437 + l438: + position, tokenIndex = position437, tokenIndex437 + if buffer[position] != rune('R') { + goto l429 + } + position++ } - l440: - l442: + l437: + { + position439, tokenIndex439 := position, tokenIndex + if buffer[position] != rune('a') { + goto l440 + } + position++ + goto l439 + l440: + position, tokenIndex = position439, tokenIndex439 + if buffer[position] != rune('A') { + goto l429 + } + position++ + } + l439: + { + position441, tokenIndex441 := position, tokenIndex + if buffer[position] != rune('c') { + goto l442 + } + position++ + goto l441 + l442: + position, tokenIndex = position441, tokenIndex441 + if buffer[position] != rune('C') { + goto l429 + } + position++ + } + l441: { position443, tokenIndex443 := position, tokenIndex - { - position444, tokenIndex444 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l445 - } - position++ + if buffer[position] != rune('k') { goto l444 - l445: - position, tokenIndex = position444, tokenIndex444 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l446 - } - position++ - goto l444 - l446: - position, tokenIndex = position444, tokenIndex444 - if buffer[position] != rune('.') { - goto l447 - } - position++ - goto l444 - l447: - position, tokenIndex = position444, tokenIndex444 - { - position448, tokenIndex448 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l449 - } - position++ - goto l448 - l449: - position, tokenIndex = position448, tokenIndex448 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l443 - } - position++ - } - l448: } + position++ + goto l443 l444: - goto l442 - l443: position, tokenIndex = position443, tokenIndex443 - } - { - position450, tokenIndex450 := position, tokenIndex - { - position452, tokenIndex452 := position, tokenIndex - if buffer[position] != rune('.') { - goto l453 - } - position++ - goto l452 - l453: - position, tokenIndex = position452, tokenIndex452 - if buffer[position] != rune('+') { - goto l454 - } - position++ - goto l452 - l454: - position, tokenIndex = position452, tokenIndex452 - if buffer[position] != rune('-') { - goto l450 - } - position++ + if buffer[position] != rune('K') { + goto l429 } - l452: - goto l451 - l450: - position, tokenIndex = position450, tokenIndex450 + position++ } - l451: - add(ruleInstructionName, position439) + l443: + add(ruleInstructionPrefix, position430) } return true - l438: - position, tokenIndex = position438, tokenIndex438 + l429: + position, tokenIndex = position429, tokenIndex429 return false }, - /* 34 InstructionArg <- <(IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTAddress / GOTSymbolOffset / MemoryRef) AVX512Token*)> */ + /* 33 Instruction <- <((InstructionPrefix WS)? InstructionName (WS InstructionArg (WS? ',' WS? InstructionArg)*)?)> */ func() bool { - position455, tokenIndex455 := position, tokenIndex + position445, tokenIndex445 := position, tokenIndex { - position456 := position + position446 := position { - position457, tokenIndex457 := position, tokenIndex - if !_rules[ruleIndirectionIndicator]() { - goto l457 + position447, tokenIndex447 := position, tokenIndex + if !_rules[ruleInstructionPrefix]() { + goto l447 } - goto l458 - l457: - position, tokenIndex = position457, tokenIndex457 + if !_rules[ruleWS]() { + goto l447 + } + goto l448 + l447: + position, tokenIndex = position447, tokenIndex447 } - l458: + l448: + if !_rules[ruleInstructionName]() { + goto l445 + } + { + position449, tokenIndex449 := position, tokenIndex + if !_rules[ruleWS]() { + goto l449 + } + if !_rules[ruleInstructionArg]() { + goto l449 + } + l451: + { + position452, tokenIndex452 := position, tokenIndex + { + position453, tokenIndex453 := position, tokenIndex + if !_rules[ruleWS]() { + goto l453 + } + goto l454 + l453: + position, tokenIndex = position453, tokenIndex453 + } + l454: + if buffer[position] != rune(',') { + goto l452 + } + position++ + { + position455, tokenIndex455 := position, tokenIndex + if !_rules[ruleWS]() { + goto l455 + } + goto l456 + l455: + position, tokenIndex = position455, tokenIndex455 + } + l456: + if !_rules[ruleInstructionArg]() { + goto l452 + } + goto l451 + l452: + position, tokenIndex = position452, tokenIndex452 + } + goto l450 + l449: + position, tokenIndex = position449, tokenIndex449 + } + l450: + add(ruleInstruction, position446) + } + return true + l445: + position, tokenIndex = position445, tokenIndex445 + return false + }, + /* 34 InstructionName <- <(([a-z] / [A-Z]) ([a-z] / [A-Z] / '.' / ([0-9] / [0-9]))* ('.' / '+' / '-')?)> */ + func() bool { + position457, tokenIndex457 := position, tokenIndex + { + position458 := position { position459, tokenIndex459 := position, tokenIndex - if !_rules[ruleARMConstantTweak]() { + if c := buffer[position]; c < rune('a') || c > rune('z') { goto l460 } + position++ goto l459 l460: position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleRegisterOrConstant]() { - goto l461 - } - goto l459 - l461: - position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleLocalLabelRef]() { - goto l462 - } - goto l459 - l462: - position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleTOCRefHigh]() { - goto l463 - } - goto l459 - l463: - position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleTOCRefLow]() { - goto l464 - } - goto l459 - l464: - position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleGOTLocation]() { - goto l465 - } - goto l459 - l465: - position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleGOTAddress]() { - goto l466 - } - goto l459 - l466: - position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleGOTSymbolOffset]() { - goto l467 - } - goto l459 - l467: - position, tokenIndex = position459, tokenIndex459 - if !_rules[ruleMemoryRef]() { - goto l455 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l457 } + position++ } l459: - l468: + l461: + { + position462, tokenIndex462 := position, tokenIndex + { + position463, tokenIndex463 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l464 + } + position++ + goto l463 + l464: + position, tokenIndex = position463, tokenIndex463 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l465 + } + position++ + goto l463 + l465: + position, tokenIndex = position463, tokenIndex463 + if buffer[position] != rune('.') { + goto l466 + } + position++ + goto l463 + l466: + position, tokenIndex = position463, tokenIndex463 + { + position467, tokenIndex467 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l468 + } + position++ + goto l467 + l468: + position, tokenIndex = position467, tokenIndex467 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l462 + } + position++ + } + l467: + } + l463: + goto l461 + l462: + position, tokenIndex = position462, tokenIndex462 + } { position469, tokenIndex469 := position, tokenIndex - if !_rules[ruleAVX512Token]() { - goto l469 + { + position471, tokenIndex471 := position, tokenIndex + if buffer[position] != rune('.') { + goto l472 + } + position++ + goto l471 + l472: + position, tokenIndex = position471, tokenIndex471 + if buffer[position] != rune('+') { + goto l473 + } + position++ + goto l471 + l473: + position, tokenIndex = position471, tokenIndex471 + if buffer[position] != rune('-') { + goto l469 + } + position++ } - goto l468 + l471: + goto l470 l469: position, tokenIndex = position469, tokenIndex469 } - add(ruleInstructionArg, position456) + l470: + add(ruleInstructionName, position458) } return true - l455: - position, tokenIndex = position455, tokenIndex455 + l457: + position, tokenIndex = position457, tokenIndex457 return false }, - /* 35 GOTLocation <- <('$' '_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '-' LocalSymbol)> */ - func() bool { - position470, tokenIndex470 := position, tokenIndex - { - position471 := position - if buffer[position] != rune('$') { - goto l470 - } - position++ - if buffer[position] != rune('_') { - goto l470 - } - position++ - if buffer[position] != rune('G') { - goto l470 - } - position++ - if buffer[position] != rune('L') { - goto l470 - } - position++ - if buffer[position] != rune('O') { - goto l470 - } - position++ - if buffer[position] != rune('B') { - goto l470 - } - position++ - if buffer[position] != rune('A') { - goto l470 - } - position++ - if buffer[position] != rune('L') { - goto l470 - } - position++ - if buffer[position] != rune('_') { - goto l470 - } - position++ - if buffer[position] != rune('O') { - goto l470 - } - position++ - if buffer[position] != rune('F') { - goto l470 - } - position++ - if buffer[position] != rune('F') { - goto l470 - } - position++ - if buffer[position] != rune('S') { - goto l470 - } - position++ - if buffer[position] != rune('E') { - goto l470 - } - position++ - if buffer[position] != rune('T') { - goto l470 - } - position++ - if buffer[position] != rune('_') { - goto l470 - } - position++ - if buffer[position] != rune('T') { - goto l470 - } - position++ - if buffer[position] != rune('A') { - goto l470 - } - position++ - if buffer[position] != rune('B') { - goto l470 - } - position++ - if buffer[position] != rune('L') { - goto l470 - } - position++ - if buffer[position] != rune('E') { - goto l470 - } - position++ - if buffer[position] != rune('_') { - goto l470 - } - position++ - if buffer[position] != rune('-') { - goto l470 - } - position++ - if !_rules[ruleLocalSymbol]() { - goto l470 - } - add(ruleGOTLocation, position471) - } - return true - l470: - position, tokenIndex = position470, tokenIndex470 - return false - }, - /* 36 GOTAddress <- <('_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '(' '%' 'r' 'i' 'p' ')')> */ - func() bool { - position472, tokenIndex472 := position, tokenIndex - { - position473 := position - if buffer[position] != rune('_') { - goto l472 - } - position++ - if buffer[position] != rune('G') { - goto l472 - } - position++ - if buffer[position] != rune('L') { - goto l472 - } - position++ - if buffer[position] != rune('O') { - goto l472 - } - position++ - if buffer[position] != rune('B') { - goto l472 - } - position++ - if buffer[position] != rune('A') { - goto l472 - } - position++ - if buffer[position] != rune('L') { - goto l472 - } - position++ - if buffer[position] != rune('_') { - goto l472 - } - position++ - if buffer[position] != rune('O') { - goto l472 - } - position++ - if buffer[position] != rune('F') { - goto l472 - } - position++ - if buffer[position] != rune('F') { - goto l472 - } - position++ - if buffer[position] != rune('S') { - goto l472 - } - position++ - if buffer[position] != rune('E') { - goto l472 - } - position++ - if buffer[position] != rune('T') { - goto l472 - } - position++ - if buffer[position] != rune('_') { - goto l472 - } - position++ - if buffer[position] != rune('T') { - goto l472 - } - position++ - if buffer[position] != rune('A') { - goto l472 - } - position++ - if buffer[position] != rune('B') { - goto l472 - } - position++ - if buffer[position] != rune('L') { - goto l472 - } - position++ - if buffer[position] != rune('E') { - goto l472 - } - position++ - if buffer[position] != rune('_') { - goto l472 - } - position++ - if buffer[position] != rune('(') { - goto l472 - } - position++ - if buffer[position] != rune('%') { - goto l472 - } - position++ - if buffer[position] != rune('r') { - goto l472 - } - position++ - if buffer[position] != rune('i') { - goto l472 - } - position++ - if buffer[position] != rune('p') { - goto l472 - } - position++ - if buffer[position] != rune(')') { - goto l472 - } - position++ - add(ruleGOTAddress, position473) - } - return true - l472: - position, tokenIndex = position472, tokenIndex472 - return false - }, - /* 37 GOTSymbolOffset <- <(('$' SymbolName ('@' 'G' 'O' 'T') ('O' 'F' 'F')?) / (':' ('g' / 'G') ('o' / 'O') ('t' / 'T') ':' SymbolName))> */ + /* 35 InstructionArg <- <(IndirectionIndicator? (ARMConstantTweak / RegisterOrConstant / LocalLabelRef / TOCRefHigh / TOCRefLow / GOTLocation / GOTAddress / GOTSymbolOffset / MemoryRef) AVX512Token*)> */ func() bool { position474, tokenIndex474 := position, tokenIndex { position475 := position { position476, tokenIndex476 := position, tokenIndex - if buffer[position] != rune('$') { - goto l477 + if !_rules[ruleIndirectionIndicator]() { + goto l476 } - position++ - if !_rules[ruleSymbolName]() { - goto l477 - } - if buffer[position] != rune('@') { - goto l477 - } - position++ - if buffer[position] != rune('G') { - goto l477 - } - position++ - if buffer[position] != rune('O') { - goto l477 - } - position++ - if buffer[position] != rune('T') { - goto l477 - } - position++ - { - position478, tokenIndex478 := position, tokenIndex - if buffer[position] != rune('O') { - goto l478 - } - position++ - if buffer[position] != rune('F') { - goto l478 - } - position++ - if buffer[position] != rune('F') { - goto l478 - } - position++ - goto l479 - l478: - position, tokenIndex = position478, tokenIndex478 - } - l479: - goto l476 - l477: + goto l477 + l476: position, tokenIndex = position476, tokenIndex476 - if buffer[position] != rune(':') { - goto l474 + } + l477: + { + position478, tokenIndex478 := position, tokenIndex + if !_rules[ruleARMConstantTweak]() { + goto l479 } - position++ - { - position480, tokenIndex480 := position, tokenIndex - if buffer[position] != rune('g') { - goto l481 - } - position++ + goto l478 + l479: + position, tokenIndex = position478, tokenIndex478 + if !_rules[ruleRegisterOrConstant]() { goto l480 - l481: - position, tokenIndex = position480, tokenIndex480 - if buffer[position] != rune('G') { - goto l474 - } - position++ } + goto l478 l480: - { - position482, tokenIndex482 := position, tokenIndex - if buffer[position] != rune('o') { - goto l483 - } - position++ + position, tokenIndex = position478, tokenIndex478 + if !_rules[ruleLocalLabelRef]() { + goto l481 + } + goto l478 + l481: + position, tokenIndex = position478, tokenIndex478 + if !_rules[ruleTOCRefHigh]() { goto l482 - l483: - position, tokenIndex = position482, tokenIndex482 - if buffer[position] != rune('O') { - goto l474 - } - position++ } + goto l478 l482: - { - position484, tokenIndex484 := position, tokenIndex - if buffer[position] != rune('t') { - goto l485 - } - position++ + position, tokenIndex = position478, tokenIndex478 + if !_rules[ruleTOCRefLow]() { + goto l483 + } + goto l478 + l483: + position, tokenIndex = position478, tokenIndex478 + if !_rules[ruleGOTLocation]() { goto l484 - l485: - position, tokenIndex = position484, tokenIndex484 - if buffer[position] != rune('T') { - goto l474 - } - position++ } + goto l478 l484: - if buffer[position] != rune(':') { - goto l474 + position, tokenIndex = position478, tokenIndex478 + if !_rules[ruleGOTAddress]() { + goto l485 } - position++ - if !_rules[ruleSymbolName]() { + goto l478 + l485: + position, tokenIndex = position478, tokenIndex478 + if !_rules[ruleGOTSymbolOffset]() { + goto l486 + } + goto l478 + l486: + position, tokenIndex = position478, tokenIndex478 + if !_rules[ruleMemoryRef]() { goto l474 } } - l476: - add(ruleGOTSymbolOffset, position475) + l478: + l487: + { + position488, tokenIndex488 := position, tokenIndex + if !_rules[ruleAVX512Token]() { + goto l488 + } + goto l487 + l488: + position, tokenIndex = position488, tokenIndex488 + } + add(ruleInstructionArg, position475) } return true l474: position, tokenIndex = position474, tokenIndex474 return false }, - /* 38 AVX512Token <- <(WS? '{' '%'? ([0-9] / [a-z])* '}')> */ + /* 36 GOTLocation <- <('$' '_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '-' LocalSymbol)> */ func() bool { - position486, tokenIndex486 := position, tokenIndex + position489, tokenIndex489 := position, tokenIndex { - position487 := position - { - position488, tokenIndex488 := position, tokenIndex - if !_rules[ruleWS]() { - goto l488 - } + position490 := position + if buffer[position] != rune('$') { goto l489 - l488: - position, tokenIndex = position488, tokenIndex488 - } - l489: - if buffer[position] != rune('{') { - goto l486 } position++ + if buffer[position] != rune('_') { + goto l489 + } + position++ + if buffer[position] != rune('G') { + goto l489 + } + position++ + if buffer[position] != rune('L') { + goto l489 + } + position++ + if buffer[position] != rune('O') { + goto l489 + } + position++ + if buffer[position] != rune('B') { + goto l489 + } + position++ + if buffer[position] != rune('A') { + goto l489 + } + position++ + if buffer[position] != rune('L') { + goto l489 + } + position++ + if buffer[position] != rune('_') { + goto l489 + } + position++ + if buffer[position] != rune('O') { + goto l489 + } + position++ + if buffer[position] != rune('F') { + goto l489 + } + position++ + if buffer[position] != rune('F') { + goto l489 + } + position++ + if buffer[position] != rune('S') { + goto l489 + } + position++ + if buffer[position] != rune('E') { + goto l489 + } + position++ + if buffer[position] != rune('T') { + goto l489 + } + position++ + if buffer[position] != rune('_') { + goto l489 + } + position++ + if buffer[position] != rune('T') { + goto l489 + } + position++ + if buffer[position] != rune('A') { + goto l489 + } + position++ + if buffer[position] != rune('B') { + goto l489 + } + position++ + if buffer[position] != rune('L') { + goto l489 + } + position++ + if buffer[position] != rune('E') { + goto l489 + } + position++ + if buffer[position] != rune('_') { + goto l489 + } + position++ + if buffer[position] != rune('-') { + goto l489 + } + position++ + if !_rules[ruleLocalSymbol]() { + goto l489 + } + add(ruleGOTLocation, position490) + } + return true + l489: + position, tokenIndex = position489, tokenIndex489 + return false + }, + /* 37 GOTAddress <- <('_' 'G' 'L' 'O' 'B' 'A' 'L' '_' 'O' 'F' 'F' 'S' 'E' 'T' '_' 'T' 'A' 'B' 'L' 'E' '_' '(' '%' 'r' 'i' 'p' ')')> */ + func() bool { + position491, tokenIndex491 := position, tokenIndex + { + position492 := position + if buffer[position] != rune('_') { + goto l491 + } + position++ + if buffer[position] != rune('G') { + goto l491 + } + position++ + if buffer[position] != rune('L') { + goto l491 + } + position++ + if buffer[position] != rune('O') { + goto l491 + } + position++ + if buffer[position] != rune('B') { + goto l491 + } + position++ + if buffer[position] != rune('A') { + goto l491 + } + position++ + if buffer[position] != rune('L') { + goto l491 + } + position++ + if buffer[position] != rune('_') { + goto l491 + } + position++ + if buffer[position] != rune('O') { + goto l491 + } + position++ + if buffer[position] != rune('F') { + goto l491 + } + position++ + if buffer[position] != rune('F') { + goto l491 + } + position++ + if buffer[position] != rune('S') { + goto l491 + } + position++ + if buffer[position] != rune('E') { + goto l491 + } + position++ + if buffer[position] != rune('T') { + goto l491 + } + position++ + if buffer[position] != rune('_') { + goto l491 + } + position++ + if buffer[position] != rune('T') { + goto l491 + } + position++ + if buffer[position] != rune('A') { + goto l491 + } + position++ + if buffer[position] != rune('B') { + goto l491 + } + position++ + if buffer[position] != rune('L') { + goto l491 + } + position++ + if buffer[position] != rune('E') { + goto l491 + } + position++ + if buffer[position] != rune('_') { + goto l491 + } + position++ + if buffer[position] != rune('(') { + goto l491 + } + position++ + if buffer[position] != rune('%') { + goto l491 + } + position++ + if buffer[position] != rune('r') { + goto l491 + } + position++ + if buffer[position] != rune('i') { + goto l491 + } + position++ + if buffer[position] != rune('p') { + goto l491 + } + position++ + if buffer[position] != rune(')') { + goto l491 + } + position++ + add(ruleGOTAddress, position492) + } + return true + l491: + position, tokenIndex = position491, tokenIndex491 + return false + }, + /* 38 GOTSymbolOffset <- <(('$' SymbolName ('@' 'G' 'O' 'T') ('O' 'F' 'F')?) / (':' ('g' / 'G') ('o' / 'O') ('t' / 'T') ':' SymbolName))> */ + func() bool { + position493, tokenIndex493 := position, tokenIndex + { + position494 := position { - position490, tokenIndex490 := position, tokenIndex - if buffer[position] != rune('%') { - goto l490 + position495, tokenIndex495 := position, tokenIndex + if buffer[position] != rune('$') { + goto l496 + } + position++ + if !_rules[ruleSymbolName]() { + goto l496 + } + if buffer[position] != rune('@') { + goto l496 + } + position++ + if buffer[position] != rune('G') { + goto l496 + } + position++ + if buffer[position] != rune('O') { + goto l496 + } + position++ + if buffer[position] != rune('T') { + goto l496 } position++ - goto l491 - l490: - position, tokenIndex = position490, tokenIndex490 - } - l491: - l492: - { - position493, tokenIndex493 := position, tokenIndex { - position494, tokenIndex494 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l495 + position497, tokenIndex497 := position, tokenIndex + if buffer[position] != rune('O') { + goto l497 } position++ - goto l494 - l495: - position, tokenIndex = position494, tokenIndex494 - if c := buffer[position]; c < rune('a') || c > rune('z') { + if buffer[position] != rune('F') { + goto l497 + } + position++ + if buffer[position] != rune('F') { + goto l497 + } + position++ + goto l498 + l497: + position, tokenIndex = position497, tokenIndex497 + } + l498: + goto l495 + l496: + position, tokenIndex = position495, tokenIndex495 + if buffer[position] != rune(':') { + goto l493 + } + position++ + { + position499, tokenIndex499 := position, tokenIndex + if buffer[position] != rune('g') { + goto l500 + } + position++ + goto l499 + l500: + position, tokenIndex = position499, tokenIndex499 + if buffer[position] != rune('G') { goto l493 } position++ } - l494: - goto l492 - l493: - position, tokenIndex = position493, tokenIndex493 - } - if buffer[position] != rune('}') { - goto l486 - } - position++ - add(ruleAVX512Token, position487) - } - return true - l486: - position, tokenIndex = position486, tokenIndex486 - return false - }, - /* 39 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */ - func() bool { - position496, tokenIndex496 := position, tokenIndex - { - position497 := position - if buffer[position] != rune('.') { - goto l496 - } - position++ - if buffer[position] != rune('T') { - goto l496 - } - position++ - if buffer[position] != rune('O') { - goto l496 - } - position++ - if buffer[position] != rune('C') { - goto l496 - } - position++ - if buffer[position] != rune('.') { - goto l496 - } - position++ - if buffer[position] != rune('-') { - goto l496 - } - position++ - { - position498, tokenIndex498 := position, tokenIndex - if buffer[position] != rune('0') { - goto l499 - } - position++ - if buffer[position] != rune('b') { - goto l499 - } - position++ - goto l498 l499: - position, tokenIndex = position498, tokenIndex498 - if buffer[position] != rune('.') { - goto l496 - } - position++ - if buffer[position] != rune('L') { - goto l496 - } - position++ { - position502, tokenIndex502 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l503 + position501, tokenIndex501 := position, tokenIndex + if buffer[position] != rune('o') { + goto l502 } position++ - goto l502 - l503: - position, tokenIndex = position502, tokenIndex502 - if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l501 + l502: + position, tokenIndex = position501, tokenIndex501 + if buffer[position] != rune('O') { + goto l493 + } + position++ + } + l501: + { + position503, tokenIndex503 := position, tokenIndex + if buffer[position] != rune('t') { goto l504 } position++ - goto l502 + goto l503 l504: - position, tokenIndex = position502, tokenIndex502 - if buffer[position] != rune('_') { - goto l505 - } - position++ - goto l502 - l505: - position, tokenIndex = position502, tokenIndex502 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l496 + position, tokenIndex = position503, tokenIndex503 + if buffer[position] != rune('T') { + goto l493 } position++ } - l502: - l500: - { - position501, tokenIndex501 := position, tokenIndex - { - position506, tokenIndex506 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l507 - } - position++ - goto l506 - l507: - position, tokenIndex = position506, tokenIndex506 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l508 - } - position++ - goto l506 - l508: - position, tokenIndex = position506, tokenIndex506 - if buffer[position] != rune('_') { - goto l509 - } - position++ - goto l506 - l509: - position, tokenIndex = position506, tokenIndex506 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l501 - } - position++ - } - l506: - goto l500 - l501: - position, tokenIndex = position501, tokenIndex501 + l503: + if buffer[position] != rune(':') { + goto l493 + } + position++ + if !_rules[ruleSymbolName]() { + goto l493 } } - l498: - if buffer[position] != rune('@') { - goto l496 + l495: + add(ruleGOTSymbolOffset, position494) + } + return true + l493: + position, tokenIndex = position493, tokenIndex493 + return false + }, + /* 39 AVX512Token <- <(WS? '{' '%'? ([0-9] / [a-z])* '}')> */ + func() bool { + position505, tokenIndex505 := position, tokenIndex + { + position506 := position + { + position507, tokenIndex507 := position, tokenIndex + if !_rules[ruleWS]() { + goto l507 + } + goto l508 + l507: + position, tokenIndex = position507, tokenIndex507 + } + l508: + if buffer[position] != rune('{') { + goto l505 } position++ { - position510, tokenIndex510 := position, tokenIndex - if buffer[position] != rune('h') { - goto l511 + position509, tokenIndex509 := position, tokenIndex + if buffer[position] != rune('%') { + goto l509 } position++ goto l510 - l511: - position, tokenIndex = position510, tokenIndex510 - if buffer[position] != rune('H') { - goto l496 - } - position++ + l509: + position, tokenIndex = position509, tokenIndex509 } l510: + l511: { position512, tokenIndex512 := position, tokenIndex - if buffer[position] != rune('a') { - goto l513 - } - position++ - goto l512 - l513: - position, tokenIndex = position512, tokenIndex512 - if buffer[position] != rune('A') { - goto l496 - } - position++ - } - l512: - add(ruleTOCRefHigh, position497) - } - return true - l496: - position, tokenIndex = position496, tokenIndex496 - return false - }, - /* 40 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */ - func() bool { - position514, tokenIndex514 := position, tokenIndex - { - position515 := position - if buffer[position] != rune('.') { - goto l514 - } - position++ - if buffer[position] != rune('T') { - goto l514 - } - position++ - if buffer[position] != rune('O') { - goto l514 - } - position++ - if buffer[position] != rune('C') { - goto l514 - } - position++ - if buffer[position] != rune('.') { - goto l514 - } - position++ - if buffer[position] != rune('-') { - goto l514 - } - position++ - { - position516, tokenIndex516 := position, tokenIndex - if buffer[position] != rune('0') { - goto l517 - } - position++ - if buffer[position] != rune('b') { - goto l517 - } - position++ - goto l516 - l517: - position, tokenIndex = position516, tokenIndex516 - if buffer[position] != rune('.') { - goto l514 - } - position++ - if buffer[position] != rune('L') { - goto l514 - } - position++ { - position520, tokenIndex520 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l521 - } - position++ - goto l520 - l521: - position, tokenIndex = position520, tokenIndex520 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l522 - } - position++ - goto l520 - l522: - position, tokenIndex = position520, tokenIndex520 - if buffer[position] != rune('_') { - goto l523 - } - position++ - goto l520 - l523: - position, tokenIndex = position520, tokenIndex520 + position513, tokenIndex513 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { goto l514 } position++ + goto l513 + l514: + position, tokenIndex = position513, tokenIndex513 + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l512 + } + position++ } - l520: + l513: + goto l511 + l512: + position, tokenIndex = position512, tokenIndex512 + } + if buffer[position] != rune('}') { + goto l505 + } + position++ + add(ruleAVX512Token, position506) + } + return true + l505: + position, tokenIndex = position505, tokenIndex505 + return false + }, + /* 40 TOCRefHigh <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('h' / 'H') ('a' / 'A')))> */ + func() bool { + position515, tokenIndex515 := position, tokenIndex + { + position516 := position + if buffer[position] != rune('.') { + goto l515 + } + position++ + if buffer[position] != rune('T') { + goto l515 + } + position++ + if buffer[position] != rune('O') { + goto l515 + } + position++ + if buffer[position] != rune('C') { + goto l515 + } + position++ + if buffer[position] != rune('.') { + goto l515 + } + position++ + if buffer[position] != rune('-') { + goto l515 + } + position++ + { + position517, tokenIndex517 := position, tokenIndex + if buffer[position] != rune('0') { + goto l518 + } + position++ + if buffer[position] != rune('b') { + goto l518 + } + position++ + goto l517 l518: + position, tokenIndex = position517, tokenIndex517 + if buffer[position] != rune('.') { + goto l515 + } + position++ + if buffer[position] != rune('L') { + goto l515 + } + position++ { - position519, tokenIndex519 := position, tokenIndex - { - position524, tokenIndex524 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l525 - } - position++ + position521, tokenIndex521 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l522 + } + position++ + goto l521 + l522: + position, tokenIndex = position521, tokenIndex521 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l523 + } + position++ + goto l521 + l523: + position, tokenIndex = position521, tokenIndex521 + if buffer[position] != rune('_') { goto l524 - l525: - position, tokenIndex = position524, tokenIndex524 - if c := buffer[position]; c < rune('A') || c > rune('Z') { + } + position++ + goto l521 + l524: + position, tokenIndex = position521, tokenIndex521 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l515 + } + position++ + } + l521: + l519: + { + position520, tokenIndex520 := position, tokenIndex + { + position525, tokenIndex525 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { goto l526 } position++ - goto l524 + goto l525 l526: - position, tokenIndex = position524, tokenIndex524 - if buffer[position] != rune('_') { + position, tokenIndex = position525, tokenIndex525 + if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l527 } position++ - goto l524 + goto l525 l527: - position, tokenIndex = position524, tokenIndex524 + position, tokenIndex = position525, tokenIndex525 + if buffer[position] != rune('_') { + goto l528 + } + position++ + goto l525 + l528: + position, tokenIndex = position525, tokenIndex525 if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l519 + goto l520 } position++ } - l524: - goto l518 - l519: - position, tokenIndex = position519, tokenIndex519 + l525: + goto l519 + l520: + position, tokenIndex = position520, tokenIndex520 } } - l516: + l517: if buffer[position] != rune('@') { - goto l514 + goto l515 } position++ { - position528, tokenIndex528 := position, tokenIndex - if buffer[position] != rune('l') { - goto l529 + position529, tokenIndex529 := position, tokenIndex + if buffer[position] != rune('h') { + goto l530 } position++ - goto l528 - l529: - position, tokenIndex = position528, tokenIndex528 - if buffer[position] != rune('L') { - goto l514 + goto l529 + l530: + position, tokenIndex = position529, tokenIndex529 + if buffer[position] != rune('H') { + goto l515 } position++ } - l528: - add(ruleTOCRefLow, position515) + l529: + { + position531, tokenIndex531 := position, tokenIndex + if buffer[position] != rune('a') { + goto l532 + } + position++ + goto l531 + l532: + position, tokenIndex = position531, tokenIndex531 + if buffer[position] != rune('A') { + goto l515 + } + position++ + } + l531: + add(ruleTOCRefHigh, position516) } return true - l514: - position, tokenIndex = position514, tokenIndex514 + l515: + position, tokenIndex = position515, tokenIndex515 return false }, - /* 41 IndirectionIndicator <- <'*'> */ + /* 41 TOCRefLow <- <('.' 'T' 'O' 'C' '.' '-' (('0' 'b') / ('.' 'L' ([a-z] / [A-Z] / '_' / [0-9])+)) ('@' ('l' / 'L')))> */ func() bool { - position530, tokenIndex530 := position, tokenIndex + position533, tokenIndex533 := position, tokenIndex { - position531 := position - if buffer[position] != rune('*') { - goto l530 + position534 := position + if buffer[position] != rune('.') { + goto l533 + } + position++ + if buffer[position] != rune('T') { + goto l533 + } + position++ + if buffer[position] != rune('O') { + goto l533 + } + position++ + if buffer[position] != rune('C') { + goto l533 + } + position++ + if buffer[position] != rune('.') { + goto l533 + } + position++ + if buffer[position] != rune('-') { + goto l533 } position++ - add(ruleIndirectionIndicator, position531) - } - return true - l530: - position, tokenIndex = position530, tokenIndex530 - return false - }, - /* 42 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset)) / ('#' Offset ('*' [0-9]+ ('-' [0-9] [0-9]*)?)?) / ('#' '~'? '(' [0-9] WS? ('<' '<') WS? [0-9] ')') / ARMRegister) !('f' / 'b' / ':' / '(' / '+' / '-'))> */ - func() bool { - position532, tokenIndex532 := position, tokenIndex - { - position533 := position { - position534, tokenIndex534 := position, tokenIndex - if buffer[position] != rune('%') { - goto l535 - } - position++ - { - position536, tokenIndex536 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l537 - } - position++ + position535, tokenIndex535 := position, tokenIndex + if buffer[position] != rune('0') { goto l536 - l537: - position, tokenIndex = position536, tokenIndex536 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l535 - } - position++ } + position++ + if buffer[position] != rune('b') { + goto l536 + } + position++ + goto l535 l536: - l538: + position, tokenIndex = position535, tokenIndex535 + if buffer[position] != rune('.') { + goto l533 + } + position++ + if buffer[position] != rune('L') { + goto l533 + } + position++ { position539, tokenIndex539 := position, tokenIndex - { - position540, tokenIndex540 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l541 - } - position++ + if c := buffer[position]; c < rune('a') || c > rune('z') { goto l540 - l541: - position, tokenIndex = position540, tokenIndex540 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l542 - } - position++ - goto l540 - l542: - position, tokenIndex = position540, tokenIndex540 - { - position543, tokenIndex543 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l544 - } - position++ - goto l543 - l544: - position, tokenIndex = position543, tokenIndex543 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l539 - } - position++ - } - l543: - } - l540: - goto l538 - l539: - position, tokenIndex = position539, tokenIndex539 - } - goto l534 - l535: - position, tokenIndex = position534, tokenIndex534 - { - position546, tokenIndex546 := position, tokenIndex - if buffer[position] != rune('$') { - goto l546 } position++ - goto l547 - l546: - position, tokenIndex = position546, tokenIndex546 + goto l539 + l540: + position, tokenIndex = position539, tokenIndex539 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l541 + } + position++ + goto l539 + l541: + position, tokenIndex = position539, tokenIndex539 + if buffer[position] != rune('_') { + goto l542 + } + position++ + goto l539 + l542: + position, tokenIndex = position539, tokenIndex539 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l533 + } + position++ } - l547: + l539: + l537: { - position548, tokenIndex548 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l549 - } - if !_rules[ruleOffset]() { - goto l549 - } - goto l548 - l549: - position, tokenIndex = position548, tokenIndex548 - if !_rules[ruleOffset]() { - goto l545 + position538, tokenIndex538 := position, tokenIndex + { + position543, tokenIndex543 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l544 + } + position++ + goto l543 + l544: + position, tokenIndex = position543, tokenIndex543 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l545 + } + position++ + goto l543 + l545: + position, tokenIndex = position543, tokenIndex543 + if buffer[position] != rune('_') { + goto l546 + } + position++ + goto l543 + l546: + position, tokenIndex = position543, tokenIndex543 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l538 + } + position++ } + l543: + goto l537 + l538: + position, tokenIndex = position538, tokenIndex538 } - l548: - goto l534 - l545: - position, tokenIndex = position534, tokenIndex534 - if buffer[position] != rune('#') { - goto l550 + } + l535: + if buffer[position] != rune('@') { + goto l533 + } + position++ + { + position547, tokenIndex547 := position, tokenIndex + if buffer[position] != rune('l') { + goto l548 } position++ - if !_rules[ruleOffset]() { - goto l550 + goto l547 + l548: + position, tokenIndex = position547, tokenIndex547 + if buffer[position] != rune('L') { + goto l533 } + position++ + } + l547: + add(ruleTOCRefLow, position534) + } + return true + l533: + position, tokenIndex = position533, tokenIndex533 + return false + }, + /* 42 IndirectionIndicator <- <'*'> */ + func() bool { + position549, tokenIndex549 := position, tokenIndex + { + position550 := position + if buffer[position] != rune('*') { + goto l549 + } + position++ + add(ruleIndirectionIndicator, position550) + } + return true + l549: + position, tokenIndex = position549, tokenIndex549 + return false + }, + /* 43 RegisterOrConstant <- <((('%' ([a-z] / [A-Z]) ([a-z] / [A-Z] / ([0-9] / [0-9]))*) / ('$'? ((Offset Offset) / Offset)) / ('#' Offset ('*' [0-9]+ ('-' [0-9] [0-9]*)?)?) / ('#' '~'? '(' [0-9] WS? ('<' '<') WS? [0-9] ')') / ARMRegister) !('f' / 'b' / ':' / '(' / '+' / '-'))> */ + func() bool { + position551, tokenIndex551 := position, tokenIndex + { + position552 := position + { + position553, tokenIndex553 := position, tokenIndex + if buffer[position] != rune('%') { + goto l554 + } + position++ { - position551, tokenIndex551 := position, tokenIndex - if buffer[position] != rune('*') { - goto l551 + position555, tokenIndex555 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l556 } position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l551 + goto l555 + l556: + position, tokenIndex = position555, tokenIndex555 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l554 } position++ - l553: + } + l555: + l557: + { + position558, tokenIndex558 := position, tokenIndex { - position554, tokenIndex554 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l554 + position559, tokenIndex559 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l560 } position++ - goto l553 - l554: - position, tokenIndex = position554, tokenIndex554 - } - { - position555, tokenIndex555 := position, tokenIndex - if buffer[position] != rune('-') { - goto l555 + goto l559 + l560: + position, tokenIndex = position559, tokenIndex559 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l561 } position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l555 - } - position++ - l557: + goto l559 + l561: + position, tokenIndex = position559, tokenIndex559 { - position558, tokenIndex558 := position, tokenIndex + position562, tokenIndex562 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l563 + } + position++ + goto l562 + l563: + position, tokenIndex = position562, tokenIndex562 if c := buffer[position]; c < rune('0') || c > rune('9') { goto l558 } position++ - goto l557 - l558: - position, tokenIndex = position558, tokenIndex558 } - goto l556 - l555: - position, tokenIndex = position555, tokenIndex555 + l562: } - l556: - goto l552 - l551: - position, tokenIndex = position551, tokenIndex551 + l559: + goto l557 + l558: + position, tokenIndex = position558, tokenIndex558 } - l552: - goto l534 - l550: - position, tokenIndex = position534, tokenIndex534 - if buffer[position] != rune('#') { - goto l559 - } - position++ + goto l553 + l554: + position, tokenIndex = position553, tokenIndex553 { - position560, tokenIndex560 := position, tokenIndex - if buffer[position] != rune('~') { - goto l560 + position565, tokenIndex565 := position, tokenIndex + if buffer[position] != rune('$') { + goto l565 } position++ - goto l561 - l560: - position, tokenIndex = position560, tokenIndex560 + goto l566 + l565: + position, tokenIndex = position565, tokenIndex565 } - l561: - if buffer[position] != rune('(') { - goto l559 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l559 - } - position++ - { - position562, tokenIndex562 := position, tokenIndex - if !_rules[ruleWS]() { - goto l562 - } - goto l563 - l562: - position, tokenIndex = position562, tokenIndex562 - } - l563: - if buffer[position] != rune('<') { - goto l559 - } - position++ - if buffer[position] != rune('<') { - goto l559 - } - position++ - { - position564, tokenIndex564 := position, tokenIndex - if !_rules[ruleWS]() { - goto l564 - } - goto l565 - l564: - position, tokenIndex = position564, tokenIndex564 - } - l565: - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l559 - } - position++ - if buffer[position] != rune(')') { - goto l559 - } - position++ - goto l534 - l559: - position, tokenIndex = position534, tokenIndex534 - if !_rules[ruleARMRegister]() { - goto l532 - } - } - l534: - { - position566, tokenIndex566 := position, tokenIndex + l566: { position567, tokenIndex567 := position, tokenIndex - if buffer[position] != rune('f') { + if !_rules[ruleOffset]() { + goto l568 + } + if !_rules[ruleOffset]() { goto l568 } - position++ goto l567 l568: position, tokenIndex = position567, tokenIndex567 - if buffer[position] != rune('b') { - goto l569 + if !_rules[ruleOffset]() { + goto l564 } - position++ - goto l567 - l569: - position, tokenIndex = position567, tokenIndex567 - if buffer[position] != rune(':') { + } + l567: + goto l553 + l564: + position, tokenIndex = position553, tokenIndex553 + if buffer[position] != rune('#') { + goto l569 + } + position++ + if !_rules[ruleOffset]() { + goto l569 + } + { + position570, tokenIndex570 := position, tokenIndex + if buffer[position] != rune('*') { goto l570 } position++ - goto l567 - l570: - position, tokenIndex = position567, tokenIndex567 - if buffer[position] != rune('(') { - goto l571 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l570 } position++ - goto l567 - l571: - position, tokenIndex = position567, tokenIndex567 - if buffer[position] != rune('+') { - goto l572 - } - position++ - goto l567 l572: - position, tokenIndex = position567, tokenIndex567 + { + position573, tokenIndex573 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l573 + } + position++ + goto l572 + l573: + position, tokenIndex = position573, tokenIndex573 + } + { + position574, tokenIndex574 := position, tokenIndex + if buffer[position] != rune('-') { + goto l574 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l574 + } + position++ + l576: + { + position577, tokenIndex577 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l577 + } + position++ + goto l576 + l577: + position, tokenIndex = position577, tokenIndex577 + } + goto l575 + l574: + position, tokenIndex = position574, tokenIndex574 + } + l575: + goto l571 + l570: + position, tokenIndex = position570, tokenIndex570 + } + l571: + goto l553 + l569: + position, tokenIndex = position553, tokenIndex553 + if buffer[position] != rune('#') { + goto l578 + } + position++ + { + position579, tokenIndex579 := position, tokenIndex + if buffer[position] != rune('~') { + goto l579 + } + position++ + goto l580 + l579: + position, tokenIndex = position579, tokenIndex579 + } + l580: + if buffer[position] != rune('(') { + goto l578 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l578 + } + position++ + { + position581, tokenIndex581 := position, tokenIndex + if !_rules[ruleWS]() { + goto l581 + } + goto l582 + l581: + position, tokenIndex = position581, tokenIndex581 + } + l582: + if buffer[position] != rune('<') { + goto l578 + } + position++ + if buffer[position] != rune('<') { + goto l578 + } + position++ + { + position583, tokenIndex583 := position, tokenIndex + if !_rules[ruleWS]() { + goto l583 + } + goto l584 + l583: + position, tokenIndex = position583, tokenIndex583 + } + l584: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l578 + } + position++ + if buffer[position] != rune(')') { + goto l578 + } + position++ + goto l553 + l578: + position, tokenIndex = position553, tokenIndex553 + if !_rules[ruleARMRegister]() { + goto l551 + } + } + l553: + { + position585, tokenIndex585 := position, tokenIndex + { + position586, tokenIndex586 := position, tokenIndex + if buffer[position] != rune('f') { + goto l587 + } + position++ + goto l586 + l587: + position, tokenIndex = position586, tokenIndex586 + if buffer[position] != rune('b') { + goto l588 + } + position++ + goto l586 + l588: + position, tokenIndex = position586, tokenIndex586 + if buffer[position] != rune(':') { + goto l589 + } + position++ + goto l586 + l589: + position, tokenIndex = position586, tokenIndex586 + if buffer[position] != rune('(') { + goto l590 + } + position++ + goto l586 + l590: + position, tokenIndex = position586, tokenIndex586 + if buffer[position] != rune('+') { + goto l591 + } + position++ + goto l586 + l591: + position, tokenIndex = position586, tokenIndex586 if buffer[position] != rune('-') { - goto l566 + goto l585 } position++ } - l567: - goto l532 - l566: - position, tokenIndex = position566, tokenIndex566 + l586: + goto l551 + l585: + position, tokenIndex = position585, tokenIndex585 } - add(ruleRegisterOrConstant, position533) + add(ruleRegisterOrConstant, position552) } return true - l532: - position, tokenIndex = position532, tokenIndex532 + l551: + position, tokenIndex = position551, tokenIndex551 return false }, - /* 43 ARMConstantTweak <- <((((('u' / 's') (('x' / 'X') ('t' / 'T')) ('x' / 'w' / 'h' / 'b')) / (('l' / 'L') ('s' / 'S') ('l' / 'L')) / (('l' / 'L') ('s' / 'S') ('r' / 'R')) / (('r' / 'R') ('o' / 'O') ('r' / 'R')) / (('a' / 'A') ('s' / 'S') ('r' / 'R'))) (WS '#' Offset)?) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' ('v' / 'V') ('l' / 'L')) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' '#' [0-9]))> */ + /* 44 ARMConstantTweak <- <((((('u' / 's') (('x' / 'X') ('t' / 'T')) ('x' / 'w' / 'h' / 'b')) / (('l' / 'L') ('s' / 'S') ('l' / 'L')) / (('l' / 'L') ('s' / 'S') ('r' / 'R')) / (('r' / 'R') ('o' / 'O') ('r' / 'R')) / (('a' / 'A') ('s' / 'S') ('r' / 'R'))) (WS '#' Offset)?) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' ('v' / 'V') ('l' / 'L')) / (('m' / 'M') ('u' / 'U') ('l' / 'L') ' ' '#' [0-9]))> */ func() bool { - position573, tokenIndex573 := position, tokenIndex + position592, tokenIndex592 := position, tokenIndex { - position574 := position + position593 := position { - position575, tokenIndex575 := position, tokenIndex + position594, tokenIndex594 := position, tokenIndex { - position577, tokenIndex577 := position, tokenIndex + position596, tokenIndex596 := position, tokenIndex { - position579, tokenIndex579 := position, tokenIndex + position598, tokenIndex598 := position, tokenIndex if buffer[position] != rune('u') { - goto l580 + goto l599 } position++ - goto l579 - l580: - position, tokenIndex = position579, tokenIndex579 + goto l598 + l599: + position, tokenIndex = position598, tokenIndex598 if buffer[position] != rune('s') { - goto l578 + goto l597 } position++ } - l579: + l598: { - position581, tokenIndex581 := position, tokenIndex + position600, tokenIndex600 := position, tokenIndex if buffer[position] != rune('x') { - goto l582 + goto l601 } position++ - goto l581 - l582: - position, tokenIndex = position581, tokenIndex581 + goto l600 + l601: + position, tokenIndex = position600, tokenIndex600 if buffer[position] != rune('X') { - goto l578 + goto l597 } position++ } - l581: + l600: { - position583, tokenIndex583 := position, tokenIndex + position602, tokenIndex602 := position, tokenIndex if buffer[position] != rune('t') { - goto l584 + goto l603 } position++ - goto l583 - l584: - position, tokenIndex = position583, tokenIndex583 + goto l602 + l603: + position, tokenIndex = position602, tokenIndex602 if buffer[position] != rune('T') { - goto l578 + goto l597 } position++ } - l583: - { - position585, tokenIndex585 := position, tokenIndex - if buffer[position] != rune('x') { - goto l586 - } - position++ - goto l585 - l586: - position, tokenIndex = position585, tokenIndex585 - if buffer[position] != rune('w') { - goto l587 - } - position++ - goto l585 - l587: - position, tokenIndex = position585, tokenIndex585 - if buffer[position] != rune('h') { - goto l588 - } - position++ - goto l585 - l588: - position, tokenIndex = position585, tokenIndex585 - if buffer[position] != rune('b') { - goto l578 - } - position++ - } - l585: - goto l577 - l578: - position, tokenIndex = position577, tokenIndex577 - { - position590, tokenIndex590 := position, tokenIndex - if buffer[position] != rune('l') { - goto l591 - } - position++ - goto l590 - l591: - position, tokenIndex = position590, tokenIndex590 - if buffer[position] != rune('L') { - goto l589 - } - position++ - } - l590: - { - position592, tokenIndex592 := position, tokenIndex - if buffer[position] != rune('s') { - goto l593 - } - position++ - goto l592 - l593: - position, tokenIndex = position592, tokenIndex592 - if buffer[position] != rune('S') { - goto l589 - } - position++ - } - l592: - { - position594, tokenIndex594 := position, tokenIndex - if buffer[position] != rune('l') { - goto l595 - } - position++ - goto l594 - l595: - position, tokenIndex = position594, tokenIndex594 - if buffer[position] != rune('L') { - goto l589 - } - position++ - } - l594: - goto l577 - l589: - position, tokenIndex = position577, tokenIndex577 - { - position597, tokenIndex597 := position, tokenIndex - if buffer[position] != rune('l') { - goto l598 - } - position++ - goto l597 - l598: - position, tokenIndex = position597, tokenIndex597 - if buffer[position] != rune('L') { - goto l596 - } - position++ - } - l597: - { - position599, tokenIndex599 := position, tokenIndex - if buffer[position] != rune('s') { - goto l600 - } - position++ - goto l599 - l600: - position, tokenIndex = position599, tokenIndex599 - if buffer[position] != rune('S') { - goto l596 - } - position++ - } - l599: - { - position601, tokenIndex601 := position, tokenIndex - if buffer[position] != rune('r') { - goto l602 - } - position++ - goto l601 - l602: - position, tokenIndex = position601, tokenIndex601 - if buffer[position] != rune('R') { - goto l596 - } - position++ - } - l601: - goto l577 - l596: - position, tokenIndex = position577, tokenIndex577 + l602: { position604, tokenIndex604 := position, tokenIndex - if buffer[position] != rune('r') { + if buffer[position] != rune('x') { goto l605 } position++ goto l604 l605: position, tokenIndex = position604, tokenIndex604 - if buffer[position] != rune('R') { - goto l603 + if buffer[position] != rune('w') { + goto l606 + } + position++ + goto l604 + l606: + position, tokenIndex = position604, tokenIndex604 + if buffer[position] != rune('h') { + goto l607 + } + position++ + goto l604 + l607: + position, tokenIndex = position604, tokenIndex604 + if buffer[position] != rune('b') { + goto l597 } position++ } l604: + goto l596 + l597: + position, tokenIndex = position596, tokenIndex596 { - position606, tokenIndex606 := position, tokenIndex - if buffer[position] != rune('o') { - goto l607 + position609, tokenIndex609 := position, tokenIndex + if buffer[position] != rune('l') { + goto l610 } position++ - goto l606 - l607: - position, tokenIndex = position606, tokenIndex606 - if buffer[position] != rune('O') { - goto l603 + goto l609 + l610: + position, tokenIndex = position609, tokenIndex609 + if buffer[position] != rune('L') { + goto l608 } position++ } - l606: + l609: { - position608, tokenIndex608 := position, tokenIndex - if buffer[position] != rune('r') { - goto l609 - } - position++ - goto l608 - l609: - position, tokenIndex = position608, tokenIndex608 - if buffer[position] != rune('R') { - goto l603 - } - position++ - } - l608: - goto l577 - l603: - position, tokenIndex = position577, tokenIndex577 - { - position610, tokenIndex610 := position, tokenIndex - if buffer[position] != rune('a') { - goto l611 - } - position++ - goto l610 - l611: - position, tokenIndex = position610, tokenIndex610 - if buffer[position] != rune('A') { - goto l576 - } - position++ - } - l610: - { - position612, tokenIndex612 := position, tokenIndex + position611, tokenIndex611 := position, tokenIndex if buffer[position] != rune('s') { - goto l613 + goto l612 } position++ - goto l612 - l613: - position, tokenIndex = position612, tokenIndex612 + goto l611 + l612: + position, tokenIndex = position611, tokenIndex611 if buffer[position] != rune('S') { - goto l576 + goto l608 } position++ } - l612: + l611: { - position614, tokenIndex614 := position, tokenIndex - if buffer[position] != rune('r') { + position613, tokenIndex613 := position, tokenIndex + if buffer[position] != rune('l') { + goto l614 + } + position++ + goto l613 + l614: + position, tokenIndex = position613, tokenIndex613 + if buffer[position] != rune('L') { + goto l608 + } + position++ + } + l613: + goto l596 + l608: + position, tokenIndex = position596, tokenIndex596 + { + position616, tokenIndex616 := position, tokenIndex + if buffer[position] != rune('l') { + goto l617 + } + position++ + goto l616 + l617: + position, tokenIndex = position616, tokenIndex616 + if buffer[position] != rune('L') { goto l615 } position++ - goto l614 - l615: - position, tokenIndex = position614, tokenIndex614 - if buffer[position] != rune('R') { - goto l576 + } + l616: + { + position618, tokenIndex618 := position, tokenIndex + if buffer[position] != rune('s') { + goto l619 + } + position++ + goto l618 + l619: + position, tokenIndex = position618, tokenIndex618 + if buffer[position] != rune('S') { + goto l615 } position++ } - l614: + l618: + { + position620, tokenIndex620 := position, tokenIndex + if buffer[position] != rune('r') { + goto l621 + } + position++ + goto l620 + l621: + position, tokenIndex = position620, tokenIndex620 + if buffer[position] != rune('R') { + goto l615 + } + position++ + } + l620: + goto l596 + l615: + position, tokenIndex = position596, tokenIndex596 + { + position623, tokenIndex623 := position, tokenIndex + if buffer[position] != rune('r') { + goto l624 + } + position++ + goto l623 + l624: + position, tokenIndex = position623, tokenIndex623 + if buffer[position] != rune('R') { + goto l622 + } + position++ + } + l623: + { + position625, tokenIndex625 := position, tokenIndex + if buffer[position] != rune('o') { + goto l626 + } + position++ + goto l625 + l626: + position, tokenIndex = position625, tokenIndex625 + if buffer[position] != rune('O') { + goto l622 + } + position++ + } + l625: + { + position627, tokenIndex627 := position, tokenIndex + if buffer[position] != rune('r') { + goto l628 + } + position++ + goto l627 + l628: + position, tokenIndex = position627, tokenIndex627 + if buffer[position] != rune('R') { + goto l622 + } + position++ + } + l627: + goto l596 + l622: + position, tokenIndex = position596, tokenIndex596 + { + position629, tokenIndex629 := position, tokenIndex + if buffer[position] != rune('a') { + goto l630 + } + position++ + goto l629 + l630: + position, tokenIndex = position629, tokenIndex629 + if buffer[position] != rune('A') { + goto l595 + } + position++ + } + l629: + { + position631, tokenIndex631 := position, tokenIndex + if buffer[position] != rune('s') { + goto l632 + } + position++ + goto l631 + l632: + position, tokenIndex = position631, tokenIndex631 + if buffer[position] != rune('S') { + goto l595 + } + position++ + } + l631: + { + position633, tokenIndex633 := position, tokenIndex + if buffer[position] != rune('r') { + goto l634 + } + position++ + goto l633 + l634: + position, tokenIndex = position633, tokenIndex633 + if buffer[position] != rune('R') { + goto l595 + } + position++ + } + l633: } - l577: + l596: { - position616, tokenIndex616 := position, tokenIndex + position635, tokenIndex635 := position, tokenIndex if !_rules[ruleWS]() { - goto l616 + goto l635 } if buffer[position] != rune('#') { - goto l616 + goto l635 } position++ if !_rules[ruleOffset]() { - goto l616 + goto l635 } - goto l617 - l616: - position, tokenIndex = position616, tokenIndex616 + goto l636 + l635: + position, tokenIndex = position635, tokenIndex635 } - l617: - goto l575 - l576: - position, tokenIndex = position575, tokenIndex575 + l636: + goto l594 + l595: + position, tokenIndex = position594, tokenIndex594 { - position619, tokenIndex619 := position, tokenIndex + position638, tokenIndex638 := position, tokenIndex if buffer[position] != rune('m') { - goto l620 + goto l639 } position++ - goto l619 - l620: - position, tokenIndex = position619, tokenIndex619 + goto l638 + l639: + position, tokenIndex = position638, tokenIndex638 if buffer[position] != rune('M') { - goto l618 + goto l637 } position++ } - l619: - { - position621, tokenIndex621 := position, tokenIndex - if buffer[position] != rune('u') { - goto l622 - } - position++ - goto l621 - l622: - position, tokenIndex = position621, tokenIndex621 - if buffer[position] != rune('U') { - goto l618 - } - position++ - } - l621: - { - position623, tokenIndex623 := position, tokenIndex - if buffer[position] != rune('l') { - goto l624 - } - position++ - goto l623 - l624: - position, tokenIndex = position623, tokenIndex623 - if buffer[position] != rune('L') { - goto l618 - } - position++ - } - l623: - if buffer[position] != rune(' ') { - goto l618 - } - position++ - { - position625, tokenIndex625 := position, tokenIndex - if buffer[position] != rune('v') { - goto l626 - } - position++ - goto l625 - l626: - position, tokenIndex = position625, tokenIndex625 - if buffer[position] != rune('V') { - goto l618 - } - position++ - } - l625: - { - position627, tokenIndex627 := position, tokenIndex - if buffer[position] != rune('l') { - goto l628 - } - position++ - goto l627 - l628: - position, tokenIndex = position627, tokenIndex627 - if buffer[position] != rune('L') { - goto l618 - } - position++ - } - l627: - goto l575 - l618: - position, tokenIndex = position575, tokenIndex575 - { - position629, tokenIndex629 := position, tokenIndex - if buffer[position] != rune('m') { - goto l630 - } - position++ - goto l629 - l630: - position, tokenIndex = position629, tokenIndex629 - if buffer[position] != rune('M') { - goto l573 - } - position++ - } - l629: - { - position631, tokenIndex631 := position, tokenIndex - if buffer[position] != rune('u') { - goto l632 - } - position++ - goto l631 - l632: - position, tokenIndex = position631, tokenIndex631 - if buffer[position] != rune('U') { - goto l573 - } - position++ - } - l631: - { - position633, tokenIndex633 := position, tokenIndex - if buffer[position] != rune('l') { - goto l634 - } - position++ - goto l633 - l634: - position, tokenIndex = position633, tokenIndex633 - if buffer[position] != rune('L') { - goto l573 - } - position++ - } - l633: - if buffer[position] != rune(' ') { - goto l573 - } - position++ - if buffer[position] != rune('#') { - goto l573 - } - position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l573 - } - position++ - } - l575: - add(ruleARMConstantTweak, position574) - } - return true - l573: - position, tokenIndex = position573, tokenIndex573 - return false - }, - /* 44 ARMRegister <- <((('s' / 'S') ('p' / 'P')) / (('x' / 'w' / 'd' / 'q' / 's' / 'h' / 'b') [0-9] [0-9]?) / (('x' / 'X') ('z' / 'Z') ('r' / 'R')) / (('w' / 'W') ('z' / 'Z') ('r' / 'R')) / (('n' / 'N') ('z' / 'Z') ('c' / 'C') ('v' / 'V')) / SVE2PredicateRegister / ARMVectorRegister / SVE2SpecialValue / ('{' WS? ARMVectorRegister (',' WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')?))> */ - func() bool { - position635, tokenIndex635 := position, tokenIndex - { - position636 := position - { - position637, tokenIndex637 := position, tokenIndex - { - position639, tokenIndex639 := position, tokenIndex - if buffer[position] != rune('s') { - goto l640 - } - position++ - goto l639 - l640: - position, tokenIndex = position639, tokenIndex639 - if buffer[position] != rune('S') { - goto l638 - } - position++ - } - l639: - { - position641, tokenIndex641 := position, tokenIndex - if buffer[position] != rune('p') { - goto l642 - } - position++ - goto l641 - l642: - position, tokenIndex = position641, tokenIndex641 - if buffer[position] != rune('P') { - goto l638 - } - position++ - } - l641: - goto l637 l638: - position, tokenIndex = position637, tokenIndex637 + { + position640, tokenIndex640 := position, tokenIndex + if buffer[position] != rune('u') { + goto l641 + } + position++ + goto l640 + l641: + position, tokenIndex = position640, tokenIndex640 + if buffer[position] != rune('U') { + goto l637 + } + position++ + } + l640: + { + position642, tokenIndex642 := position, tokenIndex + if buffer[position] != rune('l') { + goto l643 + } + position++ + goto l642 + l643: + position, tokenIndex = position642, tokenIndex642 + if buffer[position] != rune('L') { + goto l637 + } + position++ + } + l642: + if buffer[position] != rune(' ') { + goto l637 + } + position++ { position644, tokenIndex644 := position, tokenIndex - if buffer[position] != rune('x') { + if buffer[position] != rune('v') { goto l645 } position++ goto l644 l645: position, tokenIndex = position644, tokenIndex644 - if buffer[position] != rune('w') { - goto l646 - } - position++ - goto l644 - l646: - position, tokenIndex = position644, tokenIndex644 - if buffer[position] != rune('d') { - goto l647 - } - position++ - goto l644 - l647: - position, tokenIndex = position644, tokenIndex644 - if buffer[position] != rune('q') { - goto l648 - } - position++ - goto l644 - l648: - position, tokenIndex = position644, tokenIndex644 - if buffer[position] != rune('s') { - goto l649 - } - position++ - goto l644 - l649: - position, tokenIndex = position644, tokenIndex644 - if buffer[position] != rune('h') { - goto l650 - } - position++ - goto l644 - l650: - position, tokenIndex = position644, tokenIndex644 - if buffer[position] != rune('b') { - goto l643 + if buffer[position] != rune('V') { + goto l637 } position++ } l644: - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l643 - } - position++ { - position651, tokenIndex651 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { + position646, tokenIndex646 := position, tokenIndex + if buffer[position] != rune('l') { + goto l647 + } + position++ + goto l646 + l647: + position, tokenIndex = position646, tokenIndex646 + if buffer[position] != rune('L') { + goto l637 + } + position++ + } + l646: + goto l594 + l637: + position, tokenIndex = position594, tokenIndex594 + { + position648, tokenIndex648 := position, tokenIndex + if buffer[position] != rune('m') { + goto l649 + } + position++ + goto l648 + l649: + position, tokenIndex = position648, tokenIndex648 + if buffer[position] != rune('M') { + goto l592 + } + position++ + } + l648: + { + position650, tokenIndex650 := position, tokenIndex + if buffer[position] != rune('u') { goto l651 } position++ - goto l652 + goto l650 l651: - position, tokenIndex = position651, tokenIndex651 + position, tokenIndex = position650, tokenIndex650 + if buffer[position] != rune('U') { + goto l592 + } + position++ + } + l650: + { + position652, tokenIndex652 := position, tokenIndex + if buffer[position] != rune('l') { + goto l653 + } + position++ + goto l652 + l653: + position, tokenIndex = position652, tokenIndex652 + if buffer[position] != rune('L') { + goto l592 + } + position++ } l652: - goto l637 - l643: - position, tokenIndex = position637, tokenIndex637 - { - position654, tokenIndex654 := position, tokenIndex - if buffer[position] != rune('x') { - goto l655 - } - position++ - goto l654 - l655: - position, tokenIndex = position654, tokenIndex654 - if buffer[position] != rune('X') { - goto l653 - } - position++ + if buffer[position] != rune(' ') { + goto l592 } - l654: - { - position656, tokenIndex656 := position, tokenIndex - if buffer[position] != rune('z') { - goto l657 - } - position++ - goto l656 - l657: - position, tokenIndex = position656, tokenIndex656 - if buffer[position] != rune('Z') { - goto l653 - } - position++ + position++ + if buffer[position] != rune('#') { + goto l592 } - l656: + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l592 + } + position++ + } + l594: + add(ruleARMConstantTweak, position593) + } + return true + l592: + position, tokenIndex = position592, tokenIndex592 + return false + }, + /* 45 ARMRegister <- <((('s' / 'S') ('p' / 'P')) / (('x' / 'w' / 'd' / 'q' / 's' / 'h' / 'b') [0-9] [0-9]?) / (('x' / 'X') ('z' / 'Z') ('r' / 'R')) / (('w' / 'W') ('z' / 'Z') ('r' / 'R')) / (('n' / 'N') ('z' / 'Z') ('c' / 'C') ('v' / 'V')) / SVE2PredicateRegister / ARMVectorRegister / SVE2SpecialValue / ('{' WS? ARMVectorRegister (',' WS? ARMVectorRegister)* WS? '}' ('[' [0-9] [0-9]? ']')?))> */ + func() bool { + position654, tokenIndex654 := position, tokenIndex + { + position655 := position + { + position656, tokenIndex656 := position, tokenIndex { position658, tokenIndex658 := position, tokenIndex - if buffer[position] != rune('r') { + if buffer[position] != rune('s') { goto l659 } position++ goto l658 l659: position, tokenIndex = position658, tokenIndex658 - if buffer[position] != rune('R') { - goto l653 + if buffer[position] != rune('S') { + goto l657 } position++ } l658: - goto l637 - l653: - position, tokenIndex = position637, tokenIndex637 { - position661, tokenIndex661 := position, tokenIndex - if buffer[position] != rune('w') { - goto l662 + position660, tokenIndex660 := position, tokenIndex + if buffer[position] != rune('p') { + goto l661 } position++ - goto l661 - l662: - position, tokenIndex = position661, tokenIndex661 - if buffer[position] != rune('W') { - goto l660 + goto l660 + l661: + position, tokenIndex = position660, tokenIndex660 + if buffer[position] != rune('P') { + goto l657 } position++ } - l661: + l660: + goto l656 + l657: + position, tokenIndex = position656, tokenIndex656 { position663, tokenIndex663 := position, tokenIndex - if buffer[position] != rune('z') { + if buffer[position] != rune('x') { goto l664 } position++ goto l663 l664: position, tokenIndex = position663, tokenIndex663 - if buffer[position] != rune('Z') { - goto l660 + if buffer[position] != rune('w') { + goto l665 + } + position++ + goto l663 + l665: + position, tokenIndex = position663, tokenIndex663 + if buffer[position] != rune('d') { + goto l666 + } + position++ + goto l663 + l666: + position, tokenIndex = position663, tokenIndex663 + if buffer[position] != rune('q') { + goto l667 + } + position++ + goto l663 + l667: + position, tokenIndex = position663, tokenIndex663 + if buffer[position] != rune('s') { + goto l668 + } + position++ + goto l663 + l668: + position, tokenIndex = position663, tokenIndex663 + if buffer[position] != rune('h') { + goto l669 + } + position++ + goto l663 + l669: + position, tokenIndex = position663, tokenIndex663 + if buffer[position] != rune('b') { + goto l662 } position++ } l663: - { - position665, tokenIndex665 := position, tokenIndex - if buffer[position] != rune('r') { - goto l666 - } - position++ - goto l665 - l666: - position, tokenIndex = position665, tokenIndex665 - if buffer[position] != rune('R') { - goto l660 - } - position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l662 } - l665: - goto l637 - l660: - position, tokenIndex = position637, tokenIndex637 - { - position668, tokenIndex668 := position, tokenIndex - if buffer[position] != rune('n') { - goto l669 - } - position++ - goto l668 - l669: - position, tokenIndex = position668, tokenIndex668 - if buffer[position] != rune('N') { - goto l667 - } - position++ - } - l668: + position++ { position670, tokenIndex670 := position, tokenIndex - if buffer[position] != rune('z') { - goto l671 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l670 } position++ - goto l670 - l671: + goto l671 + l670: position, tokenIndex = position670, tokenIndex670 + } + l671: + goto l656 + l662: + position, tokenIndex = position656, tokenIndex656 + { + position673, tokenIndex673 := position, tokenIndex + if buffer[position] != rune('x') { + goto l674 + } + position++ + goto l673 + l674: + position, tokenIndex = position673, tokenIndex673 + if buffer[position] != rune('X') { + goto l672 + } + position++ + } + l673: + { + position675, tokenIndex675 := position, tokenIndex + if buffer[position] != rune('z') { + goto l676 + } + position++ + goto l675 + l676: + position, tokenIndex = position675, tokenIndex675 if buffer[position] != rune('Z') { - goto l667 + goto l672 } position++ } - l670: + l675: { - position672, tokenIndex672 := position, tokenIndex - if buffer[position] != rune('c') { - goto l673 + position677, tokenIndex677 := position, tokenIndex + if buffer[position] != rune('r') { + goto l678 } position++ - goto l672 - l673: - position, tokenIndex = position672, tokenIndex672 - if buffer[position] != rune('C') { - goto l667 - } - position++ - } - l672: - { - position674, tokenIndex674 := position, tokenIndex - if buffer[position] != rune('v') { - goto l675 - } - position++ - goto l674 - l675: - position, tokenIndex = position674, tokenIndex674 - if buffer[position] != rune('V') { - goto l667 - } - position++ - } - l674: - goto l637 - l667: - position, tokenIndex = position637, tokenIndex637 - if !_rules[ruleSVE2PredicateRegister]() { - goto l676 - } - goto l637 - l676: - position, tokenIndex = position637, tokenIndex637 - if !_rules[ruleARMVectorRegister]() { goto l677 + l678: + position, tokenIndex = position677, tokenIndex677 + if buffer[position] != rune('R') { + goto l672 + } + position++ } - goto l637 l677: - position, tokenIndex = position637, tokenIndex637 - if !_rules[ruleSVE2SpecialValue]() { - goto l678 - } - goto l637 - l678: - position, tokenIndex = position637, tokenIndex637 - if buffer[position] != rune('{') { - goto l635 - } - position++ + goto l656 + l672: + position, tokenIndex = position656, tokenIndex656 { - position679, tokenIndex679 := position, tokenIndex - if !_rules[ruleWS]() { + position680, tokenIndex680 := position, tokenIndex + if buffer[position] != rune('w') { + goto l681 + } + position++ + goto l680 + l681: + position, tokenIndex = position680, tokenIndex680 + if buffer[position] != rune('W') { goto l679 } - goto l680 - l679: - position, tokenIndex = position679, tokenIndex679 + position++ } l680: - if !_rules[ruleARMVectorRegister]() { - goto l635 - } - l681: { position682, tokenIndex682 := position, tokenIndex - if buffer[position] != rune(',') { - goto l682 + if buffer[position] != rune('z') { + goto l683 } position++ - { - position683, tokenIndex683 := position, tokenIndex - if !_rules[ruleWS]() { - goto l683 - } - goto l684 - l683: - position, tokenIndex = position683, tokenIndex683 - } - l684: - if !_rules[ruleARMVectorRegister]() { - goto l682 - } - goto l681 - l682: + goto l682 + l683: position, tokenIndex = position682, tokenIndex682 + if buffer[position] != rune('Z') { + goto l679 + } + position++ } + l682: { - position685, tokenIndex685 := position, tokenIndex - if !_rules[ruleWS]() { + position684, tokenIndex684 := position, tokenIndex + if buffer[position] != rune('r') { goto l685 } - goto l686 + position++ + goto l684 l685: - position, tokenIndex = position685, tokenIndex685 + position, tokenIndex = position684, tokenIndex684 + if buffer[position] != rune('R') { + goto l679 + } + position++ } - l686: - if buffer[position] != rune('}') { - goto l635 - } - position++ + l684: + goto l656 + l679: + position, tokenIndex = position656, tokenIndex656 { position687, tokenIndex687 := position, tokenIndex - if buffer[position] != rune('[') { - goto l687 + if buffer[position] != rune('n') { + goto l688 } position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l687 - } - position++ - { - position689, tokenIndex689 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l689 - } - position++ - goto l690 - l689: - position, tokenIndex = position689, tokenIndex689 - } - l690: - if buffer[position] != rune(']') { - goto l687 - } - position++ - goto l688 - l687: + goto l687 + l688: position, tokenIndex = position687, tokenIndex687 + if buffer[position] != rune('N') { + goto l686 + } + position++ } - l688: - } - l637: - add(ruleARMRegister, position636) - } - return true - l635: - position, tokenIndex = position635, tokenIndex635 - return false - }, - /* 45 ARMVectorRegister <- <(('p' / 'v' / 'z') [0-9] [0-9]? !([0-9] / [0-9] / ([a-z] / [A-Z]) / '_') ('.' [0-9]* ('b' / 's' / 'd' / 'h' / 'q') ('[' [0-9] [0-9]? ']')?)?)> */ - func() bool { - position691, tokenIndex691 := position, tokenIndex - { - position692 := position - { - position693, tokenIndex693 := position, tokenIndex - if buffer[position] != rune('p') { - goto l694 + l687: + { + position689, tokenIndex689 := position, tokenIndex + if buffer[position] != rune('z') { + goto l690 + } + position++ + goto l689 + l690: + position, tokenIndex = position689, tokenIndex689 + if buffer[position] != rune('Z') { + goto l686 + } + position++ } - position++ - goto l693 - l694: - position, tokenIndex = position693, tokenIndex693 - if buffer[position] != rune('v') { + l689: + { + position691, tokenIndex691 := position, tokenIndex + if buffer[position] != rune('c') { + goto l692 + } + position++ + goto l691 + l692: + position, tokenIndex = position691, tokenIndex691 + if buffer[position] != rune('C') { + goto l686 + } + position++ + } + l691: + { + position693, tokenIndex693 := position, tokenIndex + if buffer[position] != rune('v') { + goto l694 + } + position++ + goto l693 + l694: + position, tokenIndex = position693, tokenIndex693 + if buffer[position] != rune('V') { + goto l686 + } + position++ + } + l693: + goto l656 + l686: + position, tokenIndex = position656, tokenIndex656 + if !_rules[ruleSVE2PredicateRegister]() { goto l695 } - position++ - goto l693 + goto l656 l695: - position, tokenIndex = position693, tokenIndex693 - if buffer[position] != rune('z') { - goto l691 - } - position++ - } - l693: - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l691 - } - position++ - { - position696, tokenIndex696 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { + position, tokenIndex = position656, tokenIndex656 + if !_rules[ruleARMVectorRegister]() { goto l696 } - position++ - goto l697 + goto l656 l696: - position, tokenIndex = position696, tokenIndex696 - } - l697: - { - position698, tokenIndex698 := position, tokenIndex + position, tokenIndex = position656, tokenIndex656 + if !_rules[ruleSVE2SpecialValue]() { + goto l697 + } + goto l656 + l697: + position, tokenIndex = position656, tokenIndex656 + if buffer[position] != rune('{') { + goto l654 + } + position++ { - position699, tokenIndex699 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l700 + position698, tokenIndex698 := position, tokenIndex + if !_rules[ruleWS]() { + goto l698 } - position++ goto l699 - l700: - position, tokenIndex = position699, tokenIndex699 - if c := buffer[position]; c < rune('0') || c > rune('9') { + l698: + position, tokenIndex = position698, tokenIndex698 + } + l699: + if !_rules[ruleARMVectorRegister]() { + goto l654 + } + l700: + { + position701, tokenIndex701 := position, tokenIndex + if buffer[position] != rune(',') { goto l701 } position++ - goto l699 - l701: - position, tokenIndex = position699, tokenIndex699 { - position703, tokenIndex703 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l704 - } - position++ - goto l703 - l704: - position, tokenIndex = position703, tokenIndex703 - if c := buffer[position]; c < rune('A') || c > rune('Z') { + position702, tokenIndex702 := position, tokenIndex + if !_rules[ruleWS]() { goto l702 } - position++ + goto l703 + l702: + position, tokenIndex = position702, tokenIndex702 } l703: - goto l699 - l702: - position, tokenIndex = position699, tokenIndex699 - if buffer[position] != rune('_') { - goto l698 + if !_rules[ruleARMVectorRegister]() { + goto l701 } - position++ + goto l700 + l701: + position, tokenIndex = position701, tokenIndex701 } - l699: - goto l691 - l698: - position, tokenIndex = position698, tokenIndex698 - } - { - position705, tokenIndex705 := position, tokenIndex - if buffer[position] != rune('.') { + { + position704, tokenIndex704 := position, tokenIndex + if !_rules[ruleWS]() { + goto l704 + } goto l705 + l704: + position, tokenIndex = position704, tokenIndex704 + } + l705: + if buffer[position] != rune('}') { + goto l654 } position++ - l707: { - position708, tokenIndex708 := position, tokenIndex + position706, tokenIndex706 := position, tokenIndex + if buffer[position] != rune('[') { + goto l706 + } + position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l708 + goto l706 + } + position++ + { + position708, tokenIndex708 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l708 + } + position++ + goto l709 + l708: + position, tokenIndex = position708, tokenIndex708 + } + l709: + if buffer[position] != rune(']') { + goto l706 } position++ goto l707 - l708: - position, tokenIndex = position708, tokenIndex708 + l706: + position, tokenIndex = position706, tokenIndex706 + } + l707: + } + l656: + add(ruleARMRegister, position655) + } + return true + l654: + position, tokenIndex = position654, tokenIndex654 + return false + }, + /* 46 ARMVectorRegister <- <(('p' / 'v' / 'z') [0-9] [0-9]? !([0-9] / [0-9] / ([a-z] / [A-Z]) / '_') ('.' [0-9]* ('b' / 's' / 'd' / 'h' / 'q') ('[' [0-9] [0-9]? ']')?)?)> */ + func() bool { + position710, tokenIndex710 := position, tokenIndex + { + position711 := position + { + position712, tokenIndex712 := position, tokenIndex + if buffer[position] != rune('p') { + goto l713 + } + position++ + goto l712 + l713: + position, tokenIndex = position712, tokenIndex712 + if buffer[position] != rune('v') { + goto l714 + } + position++ + goto l712 + l714: + position, tokenIndex = position712, tokenIndex712 + if buffer[position] != rune('z') { + goto l710 + } + position++ + } + l712: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l710 + } + position++ + { + position715, tokenIndex715 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l715 + } + position++ + goto l716 + l715: + position, tokenIndex = position715, tokenIndex715 + } + l716: + { + position717, tokenIndex717 := position, tokenIndex + { + position718, tokenIndex718 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l719 + } + position++ + goto l718 + l719: + position, tokenIndex = position718, tokenIndex718 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l720 + } + position++ + goto l718 + l720: + position, tokenIndex = position718, tokenIndex718 + { + position722, tokenIndex722 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l723 + } + position++ + goto l722 + l723: + position, tokenIndex = position722, tokenIndex722 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l721 + } + position++ + } + l722: + goto l718 + l721: + position, tokenIndex = position718, tokenIndex718 + if buffer[position] != rune('_') { + goto l717 + } + position++ + } + l718: + goto l710 + l717: + position, tokenIndex = position717, tokenIndex717 + } + { + position724, tokenIndex724 := position, tokenIndex + if buffer[position] != rune('.') { + goto l724 + } + position++ + l726: + { + position727, tokenIndex727 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l727 + } + position++ + goto l726 + l727: + position, tokenIndex = position727, tokenIndex727 } { - position709, tokenIndex709 := position, tokenIndex + position728, tokenIndex728 := position, tokenIndex if buffer[position] != rune('b') { - goto l710 + goto l729 } position++ - goto l709 - l710: - position, tokenIndex = position709, tokenIndex709 + goto l728 + l729: + position, tokenIndex = position728, tokenIndex728 if buffer[position] != rune('s') { - goto l711 + goto l730 } position++ - goto l709 - l711: - position, tokenIndex = position709, tokenIndex709 + goto l728 + l730: + position, tokenIndex = position728, tokenIndex728 if buffer[position] != rune('d') { - goto l712 + goto l731 } position++ - goto l709 - l712: - position, tokenIndex = position709, tokenIndex709 + goto l728 + l731: + position, tokenIndex = position728, tokenIndex728 if buffer[position] != rune('h') { - goto l713 + goto l732 } position++ - goto l709 - l713: - position, tokenIndex = position709, tokenIndex709 + goto l728 + l732: + position, tokenIndex = position728, tokenIndex728 if buffer[position] != rune('q') { - goto l705 + goto l724 } position++ } - l709: + l728: { - position714, tokenIndex714 := position, tokenIndex + position733, tokenIndex733 := position, tokenIndex if buffer[position] != rune('[') { - goto l714 + goto l733 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l714 + goto l733 } position++ { - position716, tokenIndex716 := position, tokenIndex + position735, tokenIndex735 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l716 + goto l735 } position++ - goto l717 - l716: - position, tokenIndex = position716, tokenIndex716 - } - l717: - if buffer[position] != rune(']') { - goto l714 - } - position++ - goto l715 - l714: - position, tokenIndex = position714, tokenIndex714 - } - l715: - goto l706 - l705: - position, tokenIndex = position705, tokenIndex705 - } - l706: - add(ruleARMVectorRegister, position692) - } - return true - l691: - position, tokenIndex = position691, tokenIndex691 - return false - }, - /* 46 SVE2PredicateRegister <- <(('p' / 'P') [0-9] [0-9]? '/' ('m' / 'M' / ('z' / 'Z')))> */ - func() bool { - position718, tokenIndex718 := position, tokenIndex - { - position719 := position - { - position720, tokenIndex720 := position, tokenIndex - if buffer[position] != rune('p') { - goto l721 - } - position++ - goto l720 - l721: - position, tokenIndex = position720, tokenIndex720 - if buffer[position] != rune('P') { - goto l718 - } - position++ - } - l720: - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l718 - } - position++ - { - position722, tokenIndex722 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l722 - } - position++ - goto l723 - l722: - position, tokenIndex = position722, tokenIndex722 - } - l723: - if buffer[position] != rune('/') { - goto l718 - } - position++ - { - position724, tokenIndex724 := position, tokenIndex - if buffer[position] != rune('m') { - goto l725 - } - position++ - goto l724 - l725: - position, tokenIndex = position724, tokenIndex724 - if buffer[position] != rune('M') { - goto l726 - } - position++ - goto l724 - l726: - position, tokenIndex = position724, tokenIndex724 - { - position727, tokenIndex727 := position, tokenIndex - if buffer[position] != rune('z') { - goto l728 - } - position++ - goto l727 - l728: - position, tokenIndex = position727, tokenIndex727 - if buffer[position] != rune('Z') { - goto l718 - } - position++ - } - l727: - } - l724: - add(ruleSVE2PredicateRegister, position719) - } - return true - l718: - position, tokenIndex = position718, tokenIndex718 - return false - }, - /* 47 SVE2SpecialValue <- <(((('p' / 'P') ('o' / 'O') ('w' / 'W') '2') / (('v' / 'V') ('l' / 'L') ('1' / '2' / '3' / '4' / '5' / '6' / '7' / '8') ![0-9]) / (('v' / 'V') ('l' / 'L') '1' '6') / (('v' / 'V') ('l' / 'L') '3' '2') / (('v' / 'V') ('l' / 'L') '6' '4') / (('v' / 'V') ('l' / 'L') '1' '2' '8') / (('v' / 'V') ('l' / 'L') '2' '5' '6') / (('m' / 'M') ('u' / 'U') ('l' / 'L') '3') / (('m' / 'M') ('u' / 'U') ('l' / 'L') '4') / (('a' / 'A') ('l' / 'L') ('l' / 'L'))) !([0-9] / [0-9] / ([a-z] / [A-Z]) / '_'))> */ - func() bool { - position729, tokenIndex729 := position, tokenIndex - { - position730 := position - { - position731, tokenIndex731 := position, tokenIndex - { - position733, tokenIndex733 := position, tokenIndex - if buffer[position] != rune('p') { - goto l734 - } - position++ - goto l733 - l734: - position, tokenIndex = position733, tokenIndex733 - if buffer[position] != rune('P') { - goto l732 - } - position++ - } - l733: - { - position735, tokenIndex735 := position, tokenIndex - if buffer[position] != rune('o') { goto l736 + l735: + position, tokenIndex = position735, tokenIndex735 } - position++ - goto l735 l736: - position, tokenIndex = position735, tokenIndex735 - if buffer[position] != rune('O') { - goto l732 + if buffer[position] != rune(']') { + goto l733 } position++ + goto l734 + l733: + position, tokenIndex = position733, tokenIndex733 } - l735: - { - position737, tokenIndex737 := position, tokenIndex - if buffer[position] != rune('w') { - goto l738 - } - position++ - goto l737 - l738: - position, tokenIndex = position737, tokenIndex737 - if buffer[position] != rune('W') { - goto l732 - } - position++ - } - l737: - if buffer[position] != rune('2') { - goto l732 + l734: + goto l725 + l724: + position, tokenIndex = position724, tokenIndex724 + } + l725: + add(ruleARMVectorRegister, position711) + } + return true + l710: + position, tokenIndex = position710, tokenIndex710 + return false + }, + /* 47 SVE2PredicateRegister <- <(('p' / 'P') [0-9] [0-9]? '/' ('m' / 'M' / ('z' / 'Z')))> */ + func() bool { + position737, tokenIndex737 := position, tokenIndex + { + position738 := position + { + position739, tokenIndex739 := position, tokenIndex + if buffer[position] != rune('p') { + goto l740 } position++ - goto l731 - l732: - position, tokenIndex = position731, tokenIndex731 - { - position740, tokenIndex740 := position, tokenIndex - if buffer[position] != rune('v') { - goto l741 - } - position++ - goto l740 - l741: - position, tokenIndex = position740, tokenIndex740 - if buffer[position] != rune('V') { - goto l739 - } - position++ - } + goto l739 l740: - { - position742, tokenIndex742 := position, tokenIndex - if buffer[position] != rune('l') { - goto l743 - } - position++ - goto l742 - l743: - position, tokenIndex = position742, tokenIndex742 - if buffer[position] != rune('L') { - goto l739 - } - position++ + position, tokenIndex = position739, tokenIndex739 + if buffer[position] != rune('P') { + goto l737 } - l742: + position++ + } + l739: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l737 + } + position++ + { + position741, tokenIndex741 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l741 + } + position++ + goto l742 + l741: + position, tokenIndex = position741, tokenIndex741 + } + l742: + if buffer[position] != rune('/') { + goto l737 + } + position++ + { + position743, tokenIndex743 := position, tokenIndex + if buffer[position] != rune('m') { + goto l744 + } + position++ + goto l743 + l744: + position, tokenIndex = position743, tokenIndex743 + if buffer[position] != rune('M') { + goto l745 + } + position++ + goto l743 + l745: + position, tokenIndex = position743, tokenIndex743 { - position744, tokenIndex744 := position, tokenIndex - if buffer[position] != rune('1') { - goto l745 - } - position++ - goto l744 - l745: - position, tokenIndex = position744, tokenIndex744 - if buffer[position] != rune('2') { - goto l746 - } - position++ - goto l744 - l746: - position, tokenIndex = position744, tokenIndex744 - if buffer[position] != rune('3') { + position746, tokenIndex746 := position, tokenIndex + if buffer[position] != rune('z') { goto l747 } position++ - goto l744 + goto l746 l747: - position, tokenIndex = position744, tokenIndex744 - if buffer[position] != rune('4') { - goto l748 + position, tokenIndex = position746, tokenIndex746 + if buffer[position] != rune('Z') { + goto l737 } position++ - goto l744 - l748: - position, tokenIndex = position744, tokenIndex744 - if buffer[position] != rune('5') { - goto l749 + } + l746: + } + l743: + add(ruleSVE2PredicateRegister, position738) + } + return true + l737: + position, tokenIndex = position737, tokenIndex737 + return false + }, + /* 48 SVE2SpecialValue <- <(((('p' / 'P') ('o' / 'O') ('w' / 'W') '2') / (('v' / 'V') ('l' / 'L') ('1' / '2' / '3' / '4' / '5' / '6' / '7' / '8') ![0-9]) / (('v' / 'V') ('l' / 'L') '1' '6') / (('v' / 'V') ('l' / 'L') '3' '2') / (('v' / 'V') ('l' / 'L') '6' '4') / (('v' / 'V') ('l' / 'L') '1' '2' '8') / (('v' / 'V') ('l' / 'L') '2' '5' '6') / (('m' / 'M') ('u' / 'U') ('l' / 'L') '3') / (('m' / 'M') ('u' / 'U') ('l' / 'L') '4') / (('a' / 'A') ('l' / 'L') ('l' / 'L'))) !([0-9] / [0-9] / ([a-z] / [A-Z]) / '_'))> */ + func() bool { + position748, tokenIndex748 := position, tokenIndex + { + position749 := position + { + position750, tokenIndex750 := position, tokenIndex + { + position752, tokenIndex752 := position, tokenIndex + if buffer[position] != rune('p') { + goto l753 } position++ - goto l744 - l749: - position, tokenIndex = position744, tokenIndex744 - if buffer[position] != rune('6') { - goto l750 - } - position++ - goto l744 - l750: - position, tokenIndex = position744, tokenIndex744 - if buffer[position] != rune('7') { + goto l752 + l753: + position, tokenIndex = position752, tokenIndex752 + if buffer[position] != rune('P') { goto l751 } position++ - goto l744 - l751: - position, tokenIndex = position744, tokenIndex744 - if buffer[position] != rune('8') { - goto l739 - } - position++ } - l744: - { - position752, tokenIndex752 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l752 - } - position++ - goto l739 - l752: - position, tokenIndex = position752, tokenIndex752 - } - goto l731 - l739: - position, tokenIndex = position731, tokenIndex731 + l752: { position754, tokenIndex754 := position, tokenIndex - if buffer[position] != rune('v') { + if buffer[position] != rune('o') { goto l755 } position++ goto l754 l755: position, tokenIndex = position754, tokenIndex754 - if buffer[position] != rune('V') { - goto l753 + if buffer[position] != rune('O') { + goto l751 } position++ } l754: { position756, tokenIndex756 := position, tokenIndex - if buffer[position] != rune('l') { + if buffer[position] != rune('w') { goto l757 } position++ goto l756 l757: position, tokenIndex = position756, tokenIndex756 - if buffer[position] != rune('L') { - goto l753 + if buffer[position] != rune('W') { + goto l751 } position++ } l756: - if buffer[position] != rune('1') { - goto l753 + if buffer[position] != rune('2') { + goto l751 } position++ - if buffer[position] != rune('6') { - goto l753 - } - position++ - goto l731 - l753: - position, tokenIndex = position731, tokenIndex731 + goto l750 + l751: + position, tokenIndex = position750, tokenIndex750 { position759, tokenIndex759 := position, tokenIndex if buffer[position] != rune('v') { @@ -6088,226 +6085,210 @@ func (p *Asm) Init(options ...func(*Asm) error) error { position++ } l761: - if buffer[position] != rune('3') { - goto l758 - } - position++ - if buffer[position] != rune('2') { - goto l758 - } - position++ - goto l731 - l758: - position, tokenIndex = position731, tokenIndex731 { - position764, tokenIndex764 := position, tokenIndex - if buffer[position] != rune('v') { + position763, tokenIndex763 := position, tokenIndex + if buffer[position] != rune('1') { + goto l764 + } + position++ + goto l763 + l764: + position, tokenIndex = position763, tokenIndex763 + if buffer[position] != rune('2') { goto l765 } position++ - goto l764 + goto l763 l765: - position, tokenIndex = position764, tokenIndex764 - if buffer[position] != rune('V') { - goto l763 + position, tokenIndex = position763, tokenIndex763 + if buffer[position] != rune('3') { + goto l766 } position++ - } - l764: - { - position766, tokenIndex766 := position, tokenIndex - if buffer[position] != rune('l') { + goto l763 + l766: + position, tokenIndex = position763, tokenIndex763 + if buffer[position] != rune('4') { goto l767 } position++ - goto l766 + goto l763 l767: - position, tokenIndex = position766, tokenIndex766 - if buffer[position] != rune('L') { - goto l763 + position, tokenIndex = position763, tokenIndex763 + if buffer[position] != rune('5') { + goto l768 } position++ - } - l766: - if buffer[position] != rune('6') { goto l763 - } - position++ - if buffer[position] != rune('4') { + l768: + position, tokenIndex = position763, tokenIndex763 + if buffer[position] != rune('6') { + goto l769 + } + position++ goto l763 - } - position++ - goto l731 - l763: - position, tokenIndex = position731, tokenIndex731 - { - position769, tokenIndex769 := position, tokenIndex - if buffer[position] != rune('v') { + l769: + position, tokenIndex = position763, tokenIndex763 + if buffer[position] != rune('7') { goto l770 } position++ - goto l769 + goto l763 l770: - position, tokenIndex = position769, tokenIndex769 - if buffer[position] != rune('V') { - goto l768 + position, tokenIndex = position763, tokenIndex763 + if buffer[position] != rune('8') { + goto l758 } position++ } - l769: + l763: { position771, tokenIndex771 := position, tokenIndex - if buffer[position] != rune('l') { + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l771 + } + position++ + goto l758 + l771: + position, tokenIndex = position771, tokenIndex771 + } + goto l750 + l758: + position, tokenIndex = position750, tokenIndex750 + { + position773, tokenIndex773 := position, tokenIndex + if buffer[position] != rune('v') { + goto l774 + } + position++ + goto l773 + l774: + position, tokenIndex = position773, tokenIndex773 + if buffer[position] != rune('V') { goto l772 } position++ - goto l771 - l772: - position, tokenIndex = position771, tokenIndex771 - if buffer[position] != rune('L') { - goto l768 - } - position++ } - l771: - if buffer[position] != rune('1') { - goto l768 - } - position++ - if buffer[position] != rune('2') { - goto l768 - } - position++ - if buffer[position] != rune('8') { - goto l768 - } - position++ - goto l731 - l768: - position, tokenIndex = position731, tokenIndex731 + l773: { - position774, tokenIndex774 := position, tokenIndex - if buffer[position] != rune('v') { - goto l775 - } - position++ - goto l774 - l775: - position, tokenIndex = position774, tokenIndex774 - if buffer[position] != rune('V') { - goto l773 - } - position++ - } - l774: - { - position776, tokenIndex776 := position, tokenIndex + position775, tokenIndex775 := position, tokenIndex if buffer[position] != rune('l') { - goto l777 + goto l776 } position++ - goto l776 - l777: - position, tokenIndex = position776, tokenIndex776 + goto l775 + l776: + position, tokenIndex = position775, tokenIndex775 if buffer[position] != rune('L') { - goto l773 + goto l772 } position++ } - l776: - if buffer[position] != rune('2') { - goto l773 - } - position++ - if buffer[position] != rune('5') { - goto l773 + l775: + if buffer[position] != rune('1') { + goto l772 } position++ if buffer[position] != rune('6') { - goto l773 + goto l772 } position++ - goto l731 - l773: - position, tokenIndex = position731, tokenIndex731 + goto l750 + l772: + position, tokenIndex = position750, tokenIndex750 { - position779, tokenIndex779 := position, tokenIndex - if buffer[position] != rune('m') { - goto l780 + position778, tokenIndex778 := position, tokenIndex + if buffer[position] != rune('v') { + goto l779 } position++ - goto l779 - l780: - position, tokenIndex = position779, tokenIndex779 - if buffer[position] != rune('M') { - goto l778 + goto l778 + l779: + position, tokenIndex = position778, tokenIndex778 + if buffer[position] != rune('V') { + goto l777 } position++ } - l779: + l778: { - position781, tokenIndex781 := position, tokenIndex - if buffer[position] != rune('u') { - goto l782 + position780, tokenIndex780 := position, tokenIndex + if buffer[position] != rune('l') { + goto l781 } position++ - goto l781 - l782: - position, tokenIndex = position781, tokenIndex781 - if buffer[position] != rune('U') { - goto l778 + goto l780 + l781: + position, tokenIndex = position780, tokenIndex780 + if buffer[position] != rune('L') { + goto l777 } position++ } - l781: + l780: + if buffer[position] != rune('3') { + goto l777 + } + position++ + if buffer[position] != rune('2') { + goto l777 + } + position++ + goto l750 + l777: + position, tokenIndex = position750, tokenIndex750 { position783, tokenIndex783 := position, tokenIndex - if buffer[position] != rune('l') { + if buffer[position] != rune('v') { goto l784 } position++ goto l783 l784: position, tokenIndex = position783, tokenIndex783 - if buffer[position] != rune('L') { - goto l778 + if buffer[position] != rune('V') { + goto l782 } position++ } l783: - if buffer[position] != rune('3') { - goto l778 + { + position785, tokenIndex785 := position, tokenIndex + if buffer[position] != rune('l') { + goto l786 + } + position++ + goto l785 + l786: + position, tokenIndex = position785, tokenIndex785 + if buffer[position] != rune('L') { + goto l782 + } + position++ + } + l785: + if buffer[position] != rune('6') { + goto l782 } position++ - goto l731 - l778: - position, tokenIndex = position731, tokenIndex731 - { - position786, tokenIndex786 := position, tokenIndex - if buffer[position] != rune('m') { - goto l787 - } - position++ - goto l786 - l787: - position, tokenIndex = position786, tokenIndex786 - if buffer[position] != rune('M') { - goto l785 - } - position++ + if buffer[position] != rune('4') { + goto l782 } - l786: + position++ + goto l750 + l782: + position, tokenIndex = position750, tokenIndex750 { position788, tokenIndex788 := position, tokenIndex - if buffer[position] != rune('u') { + if buffer[position] != rune('v') { goto l789 } position++ goto l788 l789: position, tokenIndex = position788, tokenIndex788 - if buffer[position] != rune('U') { - goto l785 + if buffer[position] != rune('V') { + goto l787 } position++ } @@ -6322,1145 +6303,1302 @@ func (p *Asm) Init(options ...func(*Asm) error) error { l791: position, tokenIndex = position790, tokenIndex790 if buffer[position] != rune('L') { - goto l785 + goto l787 } position++ } l790: - if buffer[position] != rune('4') { - goto l785 + if buffer[position] != rune('1') { + goto l787 } position++ - goto l731 - l785: - position, tokenIndex = position731, tokenIndex731 + if buffer[position] != rune('2') { + goto l787 + } + position++ + if buffer[position] != rune('8') { + goto l787 + } + position++ + goto l750 + l787: + position, tokenIndex = position750, tokenIndex750 { - position792, tokenIndex792 := position, tokenIndex - if buffer[position] != rune('a') { - goto l793 + position793, tokenIndex793 := position, tokenIndex + if buffer[position] != rune('v') { + goto l794 } position++ - goto l792 - l793: - position, tokenIndex = position792, tokenIndex792 - if buffer[position] != rune('A') { - goto l729 + goto l793 + l794: + position, tokenIndex = position793, tokenIndex793 + if buffer[position] != rune('V') { + goto l792 } position++ } - l792: + l793: { - position794, tokenIndex794 := position, tokenIndex + position795, tokenIndex795 := position, tokenIndex if buffer[position] != rune('l') { - goto l795 + goto l796 } position++ - goto l794 - l795: - position, tokenIndex = position794, tokenIndex794 + goto l795 + l796: + position, tokenIndex = position795, tokenIndex795 if buffer[position] != rune('L') { - goto l729 + goto l792 } position++ } - l794: + l795: + if buffer[position] != rune('2') { + goto l792 + } + position++ + if buffer[position] != rune('5') { + goto l792 + } + position++ + if buffer[position] != rune('6') { + goto l792 + } + position++ + goto l750 + l792: + position, tokenIndex = position750, tokenIndex750 { - position796, tokenIndex796 := position, tokenIndex - if buffer[position] != rune('l') { + position798, tokenIndex798 := position, tokenIndex + if buffer[position] != rune('m') { + goto l799 + } + position++ + goto l798 + l799: + position, tokenIndex = position798, tokenIndex798 + if buffer[position] != rune('M') { goto l797 } position++ - goto l796 - l797: - position, tokenIndex = position796, tokenIndex796 - if buffer[position] != rune('L') { - goto l729 - } - position++ } - l796: - } - l731: - { - position798, tokenIndex798 := position, tokenIndex + l798: { - position799, tokenIndex799 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l800 - } - position++ - goto l799 - l800: - position, tokenIndex = position799, tokenIndex799 - if c := buffer[position]; c < rune('0') || c > rune('9') { + position800, tokenIndex800 := position, tokenIndex + if buffer[position] != rune('u') { goto l801 } position++ - goto l799 + goto l800 l801: - position, tokenIndex = position799, tokenIndex799 - { - position803, tokenIndex803 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l804 - } - position++ - goto l803 - l804: - position, tokenIndex = position803, tokenIndex803 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l802 - } - position++ - } - l803: - goto l799 - l802: - position, tokenIndex = position799, tokenIndex799 - if buffer[position] != rune('_') { - goto l798 + position, tokenIndex = position800, tokenIndex800 + if buffer[position] != rune('U') { + goto l797 } position++ } - l799: - goto l729 - l798: - position, tokenIndex = position798, tokenIndex798 - } - add(ruleSVE2SpecialValue, position730) - } - return true - l729: - position, tokenIndex = position729, tokenIndex729 - return false - }, - /* 48 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / Low12BitsSymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / ARMBaseIndexScale / BaseIndexScale)> */ - func() bool { - position805, tokenIndex805 := position, tokenIndex - { - position806 := position - { - position807, tokenIndex807 := position, tokenIndex - if !_rules[ruleSymbolRef]() { - goto l808 - } - if !_rules[ruleBaseIndexScale]() { - goto l808 - } - goto l807 - l808: - position, tokenIndex = position807, tokenIndex807 - if !_rules[ruleSymbolRef]() { - goto l809 - } - goto l807 - l809: - position, tokenIndex = position807, tokenIndex807 - if !_rules[ruleLow12BitsSymbolRef]() { - goto l810 - } - goto l807 - l810: - position, tokenIndex = position807, tokenIndex807 - l812: + l800: { - position813, tokenIndex813 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l813 + position802, tokenIndex802 := position, tokenIndex + if buffer[position] != rune('l') { + goto l803 } - goto l812 - l813: - position, tokenIndex = position813, tokenIndex813 - } - if !_rules[ruleBaseIndexScale]() { - goto l811 - } - goto l807 - l811: - position, tokenIndex = position807, tokenIndex807 - if !_rules[ruleSegmentRegister]() { - goto l814 - } - if !_rules[ruleOffset]() { - goto l814 - } - if !_rules[ruleBaseIndexScale]() { - goto l814 - } - goto l807 - l814: - position, tokenIndex = position807, tokenIndex807 - if !_rules[ruleSegmentRegister]() { - goto l815 - } - if !_rules[ruleBaseIndexScale]() { - goto l815 - } - goto l807 - l815: - position, tokenIndex = position807, tokenIndex807 - if !_rules[ruleSegmentRegister]() { - goto l816 - } - if !_rules[ruleOffset]() { - goto l816 - } - goto l807 - l816: - position, tokenIndex = position807, tokenIndex807 - if !_rules[ruleARMBaseIndexScale]() { - goto l817 - } - goto l807 - l817: - position, tokenIndex = position807, tokenIndex807 - if !_rules[ruleBaseIndexScale]() { - goto l805 - } - } - l807: - add(ruleMemoryRef, position806) - } - return true - l805: - position, tokenIndex = position805, tokenIndex805 - return false - }, - /* 49 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */ - func() bool { - position818, tokenIndex818 := position, tokenIndex - { - position819 := position - { - position820, tokenIndex820 := position, tokenIndex - l822: - { - position823, tokenIndex823 := position, tokenIndex - if !_rules[ruleOffset]() { - goto l823 + position++ + goto l802 + l803: + position, tokenIndex = position802, tokenIndex802 + if buffer[position] != rune('L') { + goto l797 } - goto l822 - l823: - position, tokenIndex = position823, tokenIndex823 + position++ } - if buffer[position] != rune('+') { - goto l820 + l802: + if buffer[position] != rune('3') { + goto l797 } position++ - goto l821 - l820: - position, tokenIndex = position820, tokenIndex820 - } - l821: - { - position824, tokenIndex824 := position, tokenIndex - if !_rules[ruleLocalSymbol]() { - goto l825 + goto l750 + l797: + position, tokenIndex = position750, tokenIndex750 + { + position805, tokenIndex805 := position, tokenIndex + if buffer[position] != rune('m') { + goto l806 + } + position++ + goto l805 + l806: + position, tokenIndex = position805, tokenIndex805 + if buffer[position] != rune('M') { + goto l804 + } + position++ } - goto l824 - l825: - position, tokenIndex = position824, tokenIndex824 - if !_rules[ruleSymbolName]() { + l805: + { + position807, tokenIndex807 := position, tokenIndex + if buffer[position] != rune('u') { + goto l808 + } + position++ + goto l807 + l808: + position, tokenIndex = position807, tokenIndex807 + if buffer[position] != rune('U') { + goto l804 + } + position++ + } + l807: + { + position809, tokenIndex809 := position, tokenIndex + if buffer[position] != rune('l') { + goto l810 + } + position++ + goto l809 + l810: + position, tokenIndex = position809, tokenIndex809 + if buffer[position] != rune('L') { + goto l804 + } + position++ + } + l809: + if buffer[position] != rune('4') { + goto l804 + } + position++ + goto l750 + l804: + position, tokenIndex = position750, tokenIndex750 + { + position811, tokenIndex811 := position, tokenIndex + if buffer[position] != rune('a') { + goto l812 + } + position++ + goto l811 + l812: + position, tokenIndex = position811, tokenIndex811 + if buffer[position] != rune('A') { + goto l748 + } + position++ + } + l811: + { + position813, tokenIndex813 := position, tokenIndex + if buffer[position] != rune('l') { + goto l814 + } + position++ + goto l813 + l814: + position, tokenIndex = position813, tokenIndex813 + if buffer[position] != rune('L') { + goto l748 + } + position++ + } + l813: + { + position815, tokenIndex815 := position, tokenIndex + if buffer[position] != rune('l') { + goto l816 + } + position++ + goto l815 + l816: + position, tokenIndex = position815, tokenIndex815 + if buffer[position] != rune('L') { + goto l748 + } + position++ + } + l815: + } + l750: + { + position817, tokenIndex817 := position, tokenIndex + { + position818, tokenIndex818 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l819 + } + position++ goto l818 + l819: + position, tokenIndex = position818, tokenIndex818 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l820 + } + position++ + goto l818 + l820: + position, tokenIndex = position818, tokenIndex818 + { + position822, tokenIndex822 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l823 + } + position++ + goto l822 + l823: + position, tokenIndex = position822, tokenIndex822 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l821 + } + position++ + } + l822: + goto l818 + l821: + position, tokenIndex = position818, tokenIndex818 + if buffer[position] != rune('_') { + goto l817 + } + position++ } + l818: + goto l748 + l817: + position, tokenIndex = position817, tokenIndex817 } - l824: - l826: + add(ruleSVE2SpecialValue, position749) + } + return true + l748: + position, tokenIndex = position748, tokenIndex748 + return false + }, + /* 49 MemoryRef <- <((SymbolRef BaseIndexScale) / SymbolRef / Low12BitsSymbolRef / (Offset* BaseIndexScale) / (SegmentRegister Offset BaseIndexScale) / (SegmentRegister BaseIndexScale) / (SegmentRegister Offset) / ARMBaseIndexScale / BaseIndexScale)> */ + func() bool { + position824, tokenIndex824 := position, tokenIndex + { + position825 := position { - position827, tokenIndex827 := position, tokenIndex - if !_rules[ruleOffset]() { + position826, tokenIndex826 := position, tokenIndex + if !_rules[ruleSymbolRef]() { + goto l827 + } + if !_rules[ruleBaseIndexScale]() { goto l827 } goto l826 l827: - position, tokenIndex = position827, tokenIndex827 + position, tokenIndex = position826, tokenIndex826 + if !_rules[ruleSymbolRef]() { + goto l828 + } + goto l826 + l828: + position, tokenIndex = position826, tokenIndex826 + if !_rules[ruleLow12BitsSymbolRef]() { + goto l829 + } + goto l826 + l829: + position, tokenIndex = position826, tokenIndex826 + l831: + { + position832, tokenIndex832 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l832 + } + goto l831 + l832: + position, tokenIndex = position832, tokenIndex832 + } + if !_rules[ruleBaseIndexScale]() { + goto l830 + } + goto l826 + l830: + position, tokenIndex = position826, tokenIndex826 + if !_rules[ruleSegmentRegister]() { + goto l833 + } + if !_rules[ruleOffset]() { + goto l833 + } + if !_rules[ruleBaseIndexScale]() { + goto l833 + } + goto l826 + l833: + position, tokenIndex = position826, tokenIndex826 + if !_rules[ruleSegmentRegister]() { + goto l834 + } + if !_rules[ruleBaseIndexScale]() { + goto l834 + } + goto l826 + l834: + position, tokenIndex = position826, tokenIndex826 + if !_rules[ruleSegmentRegister]() { + goto l835 + } + if !_rules[ruleOffset]() { + goto l835 + } + goto l826 + l835: + position, tokenIndex = position826, tokenIndex826 + if !_rules[ruleARMBaseIndexScale]() { + goto l836 + } + goto l826 + l836: + position, tokenIndex = position826, tokenIndex826 + if !_rules[ruleBaseIndexScale]() { + goto l824 + } + } + l826: + add(ruleMemoryRef, position825) + } + return true + l824: + position, tokenIndex = position824, tokenIndex824 + return false + }, + /* 50 SymbolRef <- <((Offset* '+')? (LocalSymbol / SymbolName) Offset* ('@' Section Offset*)?)> */ + func() bool { + position837, tokenIndex837 := position, tokenIndex + { + position838 := position + { + position839, tokenIndex839 := position, tokenIndex + l841: + { + position842, tokenIndex842 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l842 + } + goto l841 + l842: + position, tokenIndex = position842, tokenIndex842 + } + if buffer[position] != rune('+') { + goto l839 + } + position++ + goto l840 + l839: + position, tokenIndex = position839, tokenIndex839 + } + l840: + { + position843, tokenIndex843 := position, tokenIndex + if !_rules[ruleLocalSymbol]() { + goto l844 + } + goto l843 + l844: + position, tokenIndex = position843, tokenIndex843 + if !_rules[ruleSymbolName]() { + goto l837 + } + } + l843: + l845: + { + position846, tokenIndex846 := position, tokenIndex + if !_rules[ruleOffset]() { + goto l846 + } + goto l845 + l846: + position, tokenIndex = position846, tokenIndex846 } { - position828, tokenIndex828 := position, tokenIndex + position847, tokenIndex847 := position, tokenIndex if buffer[position] != rune('@') { - goto l828 + goto l847 } position++ if !_rules[ruleSection]() { - goto l828 + goto l847 } - l830: + l849: { - position831, tokenIndex831 := position, tokenIndex + position850, tokenIndex850 := position, tokenIndex if !_rules[ruleOffset]() { - goto l831 + goto l850 } - goto l830 - l831: - position, tokenIndex = position831, tokenIndex831 + goto l849 + l850: + position, tokenIndex = position850, tokenIndex850 } - goto l829 - l828: - position, tokenIndex = position828, tokenIndex828 + goto l848 + l847: + position, tokenIndex = position847, tokenIndex847 } - l829: - add(ruleSymbolRef, position819) + l848: + add(ruleSymbolRef, position838) } return true - l818: - position, tokenIndex = position818, tokenIndex818 + l837: + position, tokenIndex = position837, tokenIndex837 return false }, - /* 50 Low12BitsSymbolRef <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' (LocalSymbol / SymbolName) Offset?)> */ + /* 51 Low12BitsSymbolRef <- <(':' ('l' / 'L') ('o' / 'O') '1' '2' ':' (LocalSymbol / SymbolName) Offset?)> */ func() bool { - position832, tokenIndex832 := position, tokenIndex + position851, tokenIndex851 := position, tokenIndex { - position833 := position + position852 := position if buffer[position] != rune(':') { - goto l832 + goto l851 } position++ { - position834, tokenIndex834 := position, tokenIndex + position853, tokenIndex853 := position, tokenIndex if buffer[position] != rune('l') { - goto l835 + goto l854 } position++ - goto l834 - l835: - position, tokenIndex = position834, tokenIndex834 + goto l853 + l854: + position, tokenIndex = position853, tokenIndex853 if buffer[position] != rune('L') { - goto l832 + goto l851 } position++ } - l834: + l853: { - position836, tokenIndex836 := position, tokenIndex + position855, tokenIndex855 := position, tokenIndex if buffer[position] != rune('o') { - goto l837 + goto l856 } position++ - goto l836 - l837: - position, tokenIndex = position836, tokenIndex836 + goto l855 + l856: + position, tokenIndex = position855, tokenIndex855 if buffer[position] != rune('O') { - goto l832 + goto l851 } position++ } - l836: + l855: if buffer[position] != rune('1') { - goto l832 + goto l851 } position++ if buffer[position] != rune('2') { - goto l832 + goto l851 } position++ if buffer[position] != rune(':') { - goto l832 + goto l851 } position++ { - position838, tokenIndex838 := position, tokenIndex + position857, tokenIndex857 := position, tokenIndex if !_rules[ruleLocalSymbol]() { - goto l839 + goto l858 } - goto l838 - l839: - position, tokenIndex = position838, tokenIndex838 + goto l857 + l858: + position, tokenIndex = position857, tokenIndex857 if !_rules[ruleSymbolName]() { - goto l832 + goto l851 } } - l838: + l857: { - position840, tokenIndex840 := position, tokenIndex + position859, tokenIndex859 := position, tokenIndex if !_rules[ruleOffset]() { - goto l840 + goto l859 } - goto l841 - l840: - position, tokenIndex = position840, tokenIndex840 + goto l860 + l859: + position, tokenIndex = position859, tokenIndex859 } - l841: - add(ruleLow12BitsSymbolRef, position833) + l860: + add(ruleLow12BitsSymbolRef, position852) } return true - l832: - position, tokenIndex = position832, tokenIndex832 + l851: + position, tokenIndex = position851, tokenIndex851 return false }, - /* 51 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#' Offset (('*' [0-9]+) / ('*' '(' [0-9]+ Operator [0-9]+ ')') / ('+' [0-9]+)*)?) / ARMGOTLow12 / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */ + /* 52 ARMBaseIndexScale <- <('[' ARMRegister (',' WS? (('#' Offset (('*' [0-9]+) / ('*' '(' [0-9]+ Operator [0-9]+ ')') / ('+' [0-9]+)*)?) / ARMGOTLow12 / Low12BitsSymbolRef / ARMRegister) (',' WS? ARMConstantTweak)?)? ']' ARMPostincrement?)> */ func() bool { - position842, tokenIndex842 := position, tokenIndex + position861, tokenIndex861 := position, tokenIndex { - position843 := position + position862 := position if buffer[position] != rune('[') { - goto l842 + goto l861 } position++ if !_rules[ruleARMRegister]() { - goto l842 + goto l861 } { - position844, tokenIndex844 := position, tokenIndex + position863, tokenIndex863 := position, tokenIndex if buffer[position] != rune(',') { - goto l844 + goto l863 } position++ { - position846, tokenIndex846 := position, tokenIndex + position865, tokenIndex865 := position, tokenIndex if !_rules[ruleWS]() { - goto l846 + goto l865 } - goto l847 - l846: - position, tokenIndex = position846, tokenIndex846 + goto l866 + l865: + position, tokenIndex = position865, tokenIndex865 } - l847: + l866: { - position848, tokenIndex848 := position, tokenIndex + position867, tokenIndex867 := position, tokenIndex if buffer[position] != rune('#') { - goto l849 + goto l868 } position++ if !_rules[ruleOffset]() { - goto l849 + goto l868 } { - position850, tokenIndex850 := position, tokenIndex + position869, tokenIndex869 := position, tokenIndex { - position852, tokenIndex852 := position, tokenIndex + position871, tokenIndex871 := position, tokenIndex if buffer[position] != rune('*') { - goto l853 + goto l872 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l853 + goto l872 } position++ - l854: + l873: { - position855, tokenIndex855 := position, tokenIndex + position874, tokenIndex874 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l855 + goto l874 } position++ - goto l854 - l855: - position, tokenIndex = position855, tokenIndex855 + goto l873 + l874: + position, tokenIndex = position874, tokenIndex874 } - goto l852 - l853: - position, tokenIndex = position852, tokenIndex852 + goto l871 + l872: + position, tokenIndex = position871, tokenIndex871 if buffer[position] != rune('*') { - goto l856 + goto l875 } position++ if buffer[position] != rune('(') { - goto l856 + goto l875 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l856 + goto l875 } position++ - l857: + l876: { - position858, tokenIndex858 := position, tokenIndex + position877, tokenIndex877 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l858 + goto l877 } position++ - goto l857 - l858: - position, tokenIndex = position858, tokenIndex858 + goto l876 + l877: + position, tokenIndex = position877, tokenIndex877 } if !_rules[ruleOperator]() { - goto l856 + goto l875 } if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l856 + goto l875 } position++ - l859: + l878: { - position860, tokenIndex860 := position, tokenIndex + position879, tokenIndex879 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l860 + goto l879 } position++ - goto l859 - l860: - position, tokenIndex = position860, tokenIndex860 + goto l878 + l879: + position, tokenIndex = position879, tokenIndex879 } if buffer[position] != rune(')') { - goto l856 + goto l875 } position++ - goto l852 - l856: - position, tokenIndex = position852, tokenIndex852 - l861: + goto l871 + l875: + position, tokenIndex = position871, tokenIndex871 + l880: { - position862, tokenIndex862 := position, tokenIndex + position881, tokenIndex881 := position, tokenIndex if buffer[position] != rune('+') { - goto l862 + goto l881 } position++ if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l862 + goto l881 } position++ - l863: + l882: { - position864, tokenIndex864 := position, tokenIndex + position883, tokenIndex883 := position, tokenIndex if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l864 + goto l883 } position++ - goto l863 - l864: - position, tokenIndex = position864, tokenIndex864 + goto l882 + l883: + position, tokenIndex = position883, tokenIndex883 } - goto l861 - l862: - position, tokenIndex = position862, tokenIndex862 + goto l880 + l881: + position, tokenIndex = position881, tokenIndex881 } } - l852: - goto l851 - - position, tokenIndex = position850, tokenIndex850 - } - l851: - goto l848 - l849: - position, tokenIndex = position848, tokenIndex848 - if !_rules[ruleARMGOTLow12]() { - goto l865 - } - goto l848 - l865: - position, tokenIndex = position848, tokenIndex848 - if !_rules[ruleLow12BitsSymbolRef]() { - goto l866 - } - goto l848 - l866: - position, tokenIndex = position848, tokenIndex848 - if !_rules[ruleARMRegister]() { - goto l844 - } - } - l848: - { - position867, tokenIndex867 := position, tokenIndex - if buffer[position] != rune(',') { - goto l867 - } - position++ - { - position869, tokenIndex869 := position, tokenIndex - if !_rules[ruleWS]() { - goto l869 - } + l871: goto l870 - l869: + position, tokenIndex = position869, tokenIndex869 } l870: - if !_rules[ruleARMConstantTweak]() { - goto l867 - } - goto l868 - l867: + goto l867 + l868: position, tokenIndex = position867, tokenIndex867 - } - l868: - goto l845 - l844: - position, tokenIndex = position844, tokenIndex844 - } - l845: - if buffer[position] != rune(']') { - goto l842 - } - position++ - { - position871, tokenIndex871 := position, tokenIndex - if !_rules[ruleARMPostincrement]() { - goto l871 - } - goto l872 - l871: - position, tokenIndex = position871, tokenIndex871 - } - l872: - add(ruleARMBaseIndexScale, position843) - } - return true - l842: - position, tokenIndex = position842, tokenIndex842 - return false - }, - /* 52 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */ - func() bool { - position873, tokenIndex873 := position, tokenIndex - { - position874 := position - if buffer[position] != rune(':') { - goto l873 - } - position++ - { - position875, tokenIndex875 := position, tokenIndex - if buffer[position] != rune('g') { - goto l876 - } - position++ - goto l875 - l876: - position, tokenIndex = position875, tokenIndex875 - if buffer[position] != rune('G') { - goto l873 - } - position++ - } - l875: - { - position877, tokenIndex877 := position, tokenIndex - if buffer[position] != rune('o') { - goto l878 - } - position++ - goto l877 - l878: - position, tokenIndex = position877, tokenIndex877 - if buffer[position] != rune('O') { - goto l873 - } - position++ - } - l877: - { - position879, tokenIndex879 := position, tokenIndex - if buffer[position] != rune('t') { - goto l880 - } - position++ - goto l879 - l880: - position, tokenIndex = position879, tokenIndex879 - if buffer[position] != rune('T') { - goto l873 - } - position++ - } - l879: - if buffer[position] != rune('_') { - goto l873 - } - position++ - { - position881, tokenIndex881 := position, tokenIndex - if buffer[position] != rune('l') { - goto l882 - } - position++ - goto l881 - l882: - position, tokenIndex = position881, tokenIndex881 - if buffer[position] != rune('L') { - goto l873 - } - position++ - } - l881: - { - position883, tokenIndex883 := position, tokenIndex - if buffer[position] != rune('o') { - goto l884 - } - position++ - goto l883 - l884: - position, tokenIndex = position883, tokenIndex883 - if buffer[position] != rune('O') { - goto l873 - } - position++ - } - l883: - if buffer[position] != rune('1') { - goto l873 - } - position++ - if buffer[position] != rune('2') { - goto l873 - } - position++ - if buffer[position] != rune(':') { - goto l873 - } - position++ - if !_rules[ruleSymbolName]() { - goto l873 - } - add(ruleARMGOTLow12, position874) - } - return true - l873: - position, tokenIndex = position873, tokenIndex873 - return false - }, - /* 53 ARMPostincrement <- <'!'> */ - func() bool { - position885, tokenIndex885 := position, tokenIndex - { - position886 := position - if buffer[position] != rune('!') { - goto l885 - } - position++ - add(ruleARMPostincrement, position886) - } - return true - l885: - position, tokenIndex = position885, tokenIndex885 - return false - }, - /* 54 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */ - func() bool { - position887, tokenIndex887 := position, tokenIndex - { - position888 := position - if buffer[position] != rune('(') { - goto l887 - } - position++ - { - position889, tokenIndex889 := position, tokenIndex - if !_rules[ruleRegisterOrConstant]() { - goto l889 - } - goto l890 - l889: - position, tokenIndex = position889, tokenIndex889 - } - l890: - { - position891, tokenIndex891 := position, tokenIndex - if !_rules[ruleWS]() { - goto l891 - } - goto l892 - l891: - position, tokenIndex = position891, tokenIndex891 - } - l892: - { - position893, tokenIndex893 := position, tokenIndex - if buffer[position] != rune(',') { - goto l893 - } - position++ - { - position895, tokenIndex895 := position, tokenIndex - if !_rules[ruleWS]() { - goto l895 + if !_rules[ruleARMGOTLow12]() { + goto l884 } - goto l896 - l895: - position, tokenIndex = position895, tokenIndex895 - } - l896: - if !_rules[ruleRegisterOrConstant]() { - goto l893 - } - { - position897, tokenIndex897 := position, tokenIndex - if !_rules[ruleWS]() { - goto l897 + goto l867 + l884: + position, tokenIndex = position867, tokenIndex867 + if !_rules[ruleLow12BitsSymbolRef]() { + goto l885 + } + goto l867 + l885: + position, tokenIndex = position867, tokenIndex867 + if !_rules[ruleARMRegister]() { + goto l863 } - goto l898 - l897: - position, tokenIndex = position897, tokenIndex897 } - l898: + l867: { - position899, tokenIndex899 := position, tokenIndex + position886, tokenIndex886 := position, tokenIndex if buffer[position] != rune(',') { - goto l899 + goto l886 } position++ - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l899 - } - position++ - l901: { - position902, tokenIndex902 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l902 + position888, tokenIndex888 := position, tokenIndex + if !_rules[ruleWS]() { + goto l888 } - position++ - goto l901 - l902: - position, tokenIndex = position902, tokenIndex902 + goto l889 + l888: + position, tokenIndex = position888, tokenIndex888 } - goto l900 - l899: - position, tokenIndex = position899, tokenIndex899 + l889: + if !_rules[ruleARMConstantTweak]() { + goto l886 + } + goto l887 + l886: + position, tokenIndex = position886, tokenIndex886 } - l900: + l887: + goto l864 + l863: + position, tokenIndex = position863, tokenIndex863 + } + l864: + if buffer[position] != rune(']') { + goto l861 + } + position++ + { + position890, tokenIndex890 := position, tokenIndex + if !_rules[ruleARMPostincrement]() { + goto l890 + } + goto l891 + l890: + position, tokenIndex = position890, tokenIndex890 + } + l891: + add(ruleARMBaseIndexScale, position862) + } + return true + l861: + position, tokenIndex = position861, tokenIndex861 + return false + }, + /* 53 ARMGOTLow12 <- <(':' ('g' / 'G') ('o' / 'O') ('t' / 'T') '_' ('l' / 'L') ('o' / 'O') '1' '2' ':' SymbolName)> */ + func() bool { + position892, tokenIndex892 := position, tokenIndex + { + position893 := position + if buffer[position] != rune(':') { + goto l892 + } + position++ + { + position894, tokenIndex894 := position, tokenIndex + if buffer[position] != rune('g') { + goto l895 + } + position++ goto l894 - l893: - position, tokenIndex = position893, tokenIndex893 + l895: + position, tokenIndex = position894, tokenIndex894 + if buffer[position] != rune('G') { + goto l892 + } + position++ } l894: - if buffer[position] != rune(')') { - goto l887 - } - position++ - add(ruleBaseIndexScale, position888) - } - return true - l887: - position, tokenIndex = position887, tokenIndex887 - return false - }, - /* 55 Operator <- <('+' / '-')> */ - func() bool { - position903, tokenIndex903 := position, tokenIndex - { - position904 := position { - position905, tokenIndex905 := position, tokenIndex - if buffer[position] != rune('+') { - goto l906 + position896, tokenIndex896 := position, tokenIndex + if buffer[position] != rune('o') { + goto l897 } position++ - goto l905 - l906: - position, tokenIndex = position905, tokenIndex905 - if buffer[position] != rune('-') { + goto l896 + l897: + position, tokenIndex = position896, tokenIndex896 + if buffer[position] != rune('O') { + goto l892 + } + position++ + } + l896: + { + position898, tokenIndex898 := position, tokenIndex + if buffer[position] != rune('t') { + goto l899 + } + position++ + goto l898 + l899: + position, tokenIndex = position898, tokenIndex898 + if buffer[position] != rune('T') { + goto l892 + } + position++ + } + l898: + if buffer[position] != rune('_') { + goto l892 + } + position++ + { + position900, tokenIndex900 := position, tokenIndex + if buffer[position] != rune('l') { + goto l901 + } + position++ + goto l900 + l901: + position, tokenIndex = position900, tokenIndex900 + if buffer[position] != rune('L') { + goto l892 + } + position++ + } + l900: + { + position902, tokenIndex902 := position, tokenIndex + if buffer[position] != rune('o') { goto l903 } position++ + goto l902 + l903: + position, tokenIndex = position902, tokenIndex902 + if buffer[position] != rune('O') { + goto l892 + } + position++ } - l905: - add(ruleOperator, position904) + l902: + if buffer[position] != rune('1') { + goto l892 + } + position++ + if buffer[position] != rune('2') { + goto l892 + } + position++ + if buffer[position] != rune(':') { + goto l892 + } + position++ + if !_rules[ruleSymbolName]() { + goto l892 + } + add(ruleARMGOTLow12, position893) } return true - l903: - position, tokenIndex = position903, tokenIndex903 + l892: + position, tokenIndex = position892, tokenIndex892 return false }, - /* 56 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */ + /* 54 ARMPostincrement <- <'!'> */ func() bool { - position907, tokenIndex907 := position, tokenIndex + position904, tokenIndex904 := position, tokenIndex { - position908 := position - { - position909, tokenIndex909 := position, tokenIndex - if buffer[position] != rune('+') { - goto l909 - } - position++ - goto l910 - l909: - position, tokenIndex = position909, tokenIndex909 + position905 := position + if buffer[position] != rune('!') { + goto l904 } - l910: - { - position911, tokenIndex911 := position, tokenIndex - if buffer[position] != rune('-') { - goto l911 - } - position++ - goto l912 - l911: - position, tokenIndex = position911, tokenIndex911 + position++ + add(ruleARMPostincrement, position905) + } + return true + l904: + position, tokenIndex = position904, tokenIndex904 + return false + }, + /* 55 BaseIndexScale <- <('(' RegisterOrConstant? WS? (',' WS? RegisterOrConstant WS? (',' [0-9]+)?)? ')')> */ + func() bool { + position906, tokenIndex906 := position, tokenIndex + { + position907 := position + if buffer[position] != rune('(') { + goto l906 } - l912: + position++ { - position913, tokenIndex913 := position, tokenIndex - if buffer[position] != rune('0') { - goto l914 + position908, tokenIndex908 := position, tokenIndex + if !_rules[ruleRegisterOrConstant]() { + goto l908 + } + goto l909 + l908: + position, tokenIndex = position908, tokenIndex908 + } + l909: + { + position910, tokenIndex910 := position, tokenIndex + if !_rules[ruleWS]() { + goto l910 + } + goto l911 + l910: + position, tokenIndex = position910, tokenIndex910 + } + l911: + { + position912, tokenIndex912 := position, tokenIndex + if buffer[position] != rune(',') { + goto l912 } position++ { - position915, tokenIndex915 := position, tokenIndex - if buffer[position] != rune('b') { - goto l916 - } - position++ - goto l915 - l916: - position, tokenIndex = position915, tokenIndex915 - if buffer[position] != rune('B') { + position914, tokenIndex914 := position, tokenIndex + if !_rules[ruleWS]() { goto l914 } - position++ + goto l915 + l914: + position, tokenIndex = position914, tokenIndex914 } l915: - { - position919, tokenIndex919 := position, tokenIndex - if buffer[position] != rune('0') { - goto l920 - } - position++ - goto l919 - l920: - position, tokenIndex = position919, tokenIndex919 - if buffer[position] != rune('1') { - goto l914 - } - position++ + if !_rules[ruleRegisterOrConstant]() { + goto l912 + } + { + position916, tokenIndex916 := position, tokenIndex + if !_rules[ruleWS]() { + goto l916 + } + goto l917 + l916: + position, tokenIndex = position916, tokenIndex916 } - l919: l917: { position918, tokenIndex918 := position, tokenIndex + if buffer[position] != rune(',') { + goto l918 + } + position++ + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l918 + } + position++ + l920: { position921, tokenIndex921 := position, tokenIndex - if buffer[position] != rune('0') { - goto l922 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l921 } position++ - goto l921 - l922: + goto l920 + l921: position, tokenIndex = position921, tokenIndex921 - if buffer[position] != rune('1') { - goto l918 - } - position++ } - l921: - goto l917 + goto l919 l918: position, tokenIndex = position918, tokenIndex918 } + l919: goto l913 - l914: - position, tokenIndex = position913, tokenIndex913 - if buffer[position] != rune('0') { - goto l923 + l912: + position, tokenIndex = position912, tokenIndex912 + } + l913: + if buffer[position] != rune(')') { + goto l906 + } + position++ + add(ruleBaseIndexScale, position907) + } + return true + l906: + position, tokenIndex = position906, tokenIndex906 + return false + }, + /* 56 Operator <- <('+' / '-')> */ + func() bool { + position922, tokenIndex922 := position, tokenIndex + { + position923 := position + { + position924, tokenIndex924 := position, tokenIndex + if buffer[position] != rune('+') { + goto l925 } position++ - { - position924, tokenIndex924 := position, tokenIndex - if buffer[position] != rune('x') { - goto l925 - } - position++ - goto l924 - l925: - position, tokenIndex = position924, tokenIndex924 - if buffer[position] != rune('X') { - goto l923 - } - position++ + goto l924 + l925: + position, tokenIndex = position924, tokenIndex924 + if buffer[position] != rune('-') { + goto l922 } - l924: - { - position928, tokenIndex928 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l929 - } - position++ + position++ + } + l924: + add(ruleOperator, position923) + } + return true + l922: + position, tokenIndex = position922, tokenIndex922 + return false + }, + /* 57 Offset <- <('+'? '-'? (('0' ('b' / 'B') ('0' / '1')+) / ('0' ('x' / 'X') ([0-9] / [0-9] / ([a-f] / [A-F]))+) / [0-9]+))> */ + func() bool { + position926, tokenIndex926 := position, tokenIndex + { + position927 := position + { + position928, tokenIndex928 := position, tokenIndex + if buffer[position] != rune('+') { goto l928 - l929: - position, tokenIndex = position928, tokenIndex928 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l930 - } - position++ - goto l928 - l930: - position, tokenIndex = position928, tokenIndex928 - { - position931, tokenIndex931 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('f') { - goto l932 - } - position++ - goto l931 - l932: - position, tokenIndex = position931, tokenIndex931 - if c := buffer[position]; c < rune('A') || c > rune('F') { - goto l923 - } - position++ - } - l931: } + position++ + goto l929 l928: - l926: - { - position927, tokenIndex927 := position, tokenIndex - { - position933, tokenIndex933 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l934 - } - position++ - goto l933 - l934: - position, tokenIndex = position933, tokenIndex933 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l935 - } - position++ - goto l933 - l935: - position, tokenIndex = position933, tokenIndex933 - { - position936, tokenIndex936 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('f') { - goto l937 - } - position++ - goto l936 - l937: - position, tokenIndex = position936, tokenIndex936 - if c := buffer[position]; c < rune('A') || c > rune('F') { - goto l927 - } - position++ - } - l936: - } - l933: - goto l926 - l927: - position, tokenIndex = position927, tokenIndex927 - } - goto l913 - l923: - position, tokenIndex = position913, tokenIndex913 - if c := buffer[position]; c < rune('0') || c > rune('9') { - goto l907 + position, tokenIndex = position928, tokenIndex928 + } + l929: + { + position930, tokenIndex930 := position, tokenIndex + if buffer[position] != rune('-') { + goto l930 + } + position++ + goto l931 + l930: + position, tokenIndex = position930, tokenIndex930 + } + l931: + { + position932, tokenIndex932 := position, tokenIndex + if buffer[position] != rune('0') { + goto l933 } position++ - l938: { - position939, tokenIndex939 := position, tokenIndex - if c := buffer[position]; c < rune('0') || c > rune('9') { + position934, tokenIndex934 := position, tokenIndex + if buffer[position] != rune('b') { + goto l935 + } + position++ + goto l934 + l935: + position, tokenIndex = position934, tokenIndex934 + if buffer[position] != rune('B') { + goto l933 + } + position++ + } + l934: + { + position938, tokenIndex938 := position, tokenIndex + if buffer[position] != rune('0') { goto l939 } position++ goto l938 l939: - position, tokenIndex = position939, tokenIndex939 + position, tokenIndex = position938, tokenIndex938 + if buffer[position] != rune('1') { + goto l933 + } + position++ } - } - l913: - add(ruleOffset, position908) - } - return true - l907: - position, tokenIndex = position907, tokenIndex907 - return false - }, - /* 57 Section <- <([a-z] / [A-Z] / '@')+> */ - func() bool { - position940, tokenIndex940 := position, tokenIndex - { - position941 := position - { - position944, tokenIndex944 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { - goto l945 + l938: + l936: + { + position937, tokenIndex937 := position, tokenIndex + { + position940, tokenIndex940 := position, tokenIndex + if buffer[position] != rune('0') { + goto l941 + } + position++ + goto l940 + l941: + position, tokenIndex = position940, tokenIndex940 + if buffer[position] != rune('1') { + goto l937 + } + position++ + } + l940: + goto l936 + l937: + position, tokenIndex = position937, tokenIndex937 + } + goto l932 + l933: + position, tokenIndex = position932, tokenIndex932 + if buffer[position] != rune('0') { + goto l942 } position++ - goto l944 - l945: - position, tokenIndex = position944, tokenIndex944 - if c := buffer[position]; c < rune('A') || c > rune('Z') { - goto l946 + { + position943, tokenIndex943 := position, tokenIndex + if buffer[position] != rune('x') { + goto l944 + } + position++ + goto l943 + l944: + position, tokenIndex = position943, tokenIndex943 + if buffer[position] != rune('X') { + goto l942 + } + position++ } - position++ - goto l944 - l946: - position, tokenIndex = position944, tokenIndex944 - if buffer[position] != rune('@') { - goto l940 - } - position++ - } - l944: - l942: - { - position943, tokenIndex943 := position, tokenIndex + l943: { position947, tokenIndex947 := position, tokenIndex - if c := buffer[position]; c < rune('a') || c > rune('z') { + if c := buffer[position]; c < rune('0') || c > rune('9') { goto l948 } position++ goto l947 l948: position, tokenIndex = position947, tokenIndex947 - if c := buffer[position]; c < rune('A') || c > rune('Z') { + if c := buffer[position]; c < rune('0') || c > rune('9') { goto l949 } position++ goto l947 l949: position, tokenIndex = position947, tokenIndex947 + { + position950, tokenIndex950 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('f') { + goto l951 + } + position++ + goto l950 + l951: + position, tokenIndex = position950, tokenIndex950 + if c := buffer[position]; c < rune('A') || c > rune('F') { + goto l942 + } + position++ + } + l950: + } + l947: + l945: + { + position946, tokenIndex946 := position, tokenIndex + { + position952, tokenIndex952 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l953 + } + position++ + goto l952 + l953: + position, tokenIndex = position952, tokenIndex952 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l954 + } + position++ + goto l952 + l954: + position, tokenIndex = position952, tokenIndex952 + { + position955, tokenIndex955 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('f') { + goto l956 + } + position++ + goto l955 + l956: + position, tokenIndex = position955, tokenIndex955 + if c := buffer[position]; c < rune('A') || c > rune('F') { + goto l946 + } + position++ + } + l955: + } + l952: + goto l945 + l946: + position, tokenIndex = position946, tokenIndex946 + } + goto l932 + l942: + position, tokenIndex = position932, tokenIndex932 + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l926 + } + position++ + l957: + { + position958, tokenIndex958 := position, tokenIndex + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l958 + } + position++ + goto l957 + l958: + position, tokenIndex = position958, tokenIndex958 + } + } + l932: + add(ruleOffset, position927) + } + return true + l926: + position, tokenIndex = position926, tokenIndex926 + return false + }, + /* 58 Section <- <([a-z] / [A-Z] / '@')+> */ + func() bool { + position959, tokenIndex959 := position, tokenIndex + { + position960 := position + { + position963, tokenIndex963 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l964 + } + position++ + goto l963 + l964: + position, tokenIndex = position963, tokenIndex963 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l965 + } + position++ + goto l963 + l965: + position, tokenIndex = position963, tokenIndex963 + if buffer[position] != rune('@') { + goto l959 + } + position++ + } + l963: + l961: + { + position962, tokenIndex962 := position, tokenIndex + { + position966, tokenIndex966 := position, tokenIndex + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l967 + } + position++ + goto l966 + l967: + position, tokenIndex = position966, tokenIndex966 + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l968 + } + position++ + goto l966 + l968: + position, tokenIndex = position966, tokenIndex966 if buffer[position] != rune('@') { - goto l943 + goto l962 } position++ } - l947: - goto l942 - l943: - position, tokenIndex = position943, tokenIndex943 + l966: + goto l961 + l962: + position, tokenIndex = position962, tokenIndex962 } - add(ruleSection, position941) + add(ruleSection, position960) } return true - l940: - position, tokenIndex = position940, tokenIndex940 + l959: + position, tokenIndex = position959, tokenIndex959 return false }, - /* 58 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */ + /* 59 SegmentRegister <- <('%' ([c-g] / 's') ('s' ':'))> */ func() bool { - position950, tokenIndex950 := position, tokenIndex + position969, tokenIndex969 := position, tokenIndex { - position951 := position + position970 := position if buffer[position] != rune('%') { - goto l950 + goto l969 } position++ { - position952, tokenIndex952 := position, tokenIndex + position971, tokenIndex971 := position, tokenIndex if c := buffer[position]; c < rune('c') || c > rune('g') { - goto l953 + goto l972 } position++ - goto l952 - l953: - position, tokenIndex = position952, tokenIndex952 + goto l971 + l972: + position, tokenIndex = position971, tokenIndex971 if buffer[position] != rune('s') { - goto l950 + goto l969 } position++ } - l952: + l971: if buffer[position] != rune('s') { - goto l950 + goto l969 } position++ if buffer[position] != rune(':') { - goto l950 + goto l969 } position++ - add(ruleSegmentRegister, position951) + add(ruleSegmentRegister, position970) } return true - l950: - position, tokenIndex = position950, tokenIndex950 + l969: + position, tokenIndex = position969, tokenIndex969 return false }, } diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-Basic/in.s b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-Basic/in.s index 7e48e274f7..eb86c70b38 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-Basic/in.s +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-Basic/in.s @@ -20,6 +20,7 @@ foo: .loc 1 168 0 is_stmt 0 discriminator 1 cmpq -8(%rbp), %rax jmpq *%rax + notrack jmp *%rax movdqa %xmm3,%xmm10 psrlq $1,%xmm3 pxor %xmm6,%xmm5 diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s index 657d090319..f9c9fcef25 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-Basic/out.s @@ -25,6 +25,7 @@ foo: .loc 1 168 0 is_stmt 0 discriminator 1 cmpq -8(%rbp), %rax jmpq *%rax + notrack jmp *%rax movdqa %xmm3,%xmm10 psrlq $1,%xmm3 pxor %xmm6,%xmm5 diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s index 8ee708967b..92a3a7bab6 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s @@ -8,17 +8,20 @@ bar: # References to globals must be rewritten to their local targets. call foo jmp foo + notrack jmp foo jbe foo jne foo # Jumps to PLT symbols are rewritten through redirectors. call memcpy@PLT jmp memcpy@PLT + notrack jmp memcpy@PLT jbe memcpy@PLT # Jumps to local PLT symbols use their local targets. call foo@PLT jmp foo@PLT + notrack jmp foo@PLT jbe foo@PLT # Synthesized symbols are treated as local ones. @@ -43,3 +46,7 @@ bar: jmp 1f 1: jmp 1b +2: + + .quad 2b - 1b + .quad 2b - .L2 diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s index 03580d10ee..f786f13e9b 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s @@ -16,6 +16,8 @@ bar: call .Lfoo_local_target # WAS jmp foo jmp .Lfoo_local_target +# WAS notrack jmp foo + notrack jmp .Lfoo_local_target # WAS jbe foo jbe .Lfoo_local_target # WAS jne foo @@ -26,6 +28,8 @@ bar: call bcm_redirector_memcpy # WAS jmp memcpy@PLT jmp bcm_redirector_memcpy +# WAS notrack jmp memcpy@PLT + notrack jmp bcm_redirector_memcpy # WAS jbe memcpy@PLT jbe bcm_redirector_memcpy @@ -34,6 +38,8 @@ bar: call .Lfoo_local_target # WAS jmp foo@PLT jmp .Lfoo_local_target +# WAS notrack jmp foo@PLT + notrack jmp .Lfoo_local_target # WAS jbe foo@PLT jbe .Lfoo_local_target @@ -65,6 +71,11 @@ bar: 1: jmp 1b +2: + + + .quad 2b - 1b + .quad 2b - .L2 # References to local labels are rewrittenn in subsequent files. .Llocal_label_BCM_1: diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/inject_hash/inject_hash.go b/naiveproxy/src/third_party/boringssl/src/util/fipstools/inject_hash/inject_hash.go index 9c30836639..ffae5e992c 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/inject_hash/inject_hash.go +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/inject_hash/inject_hash.go @@ -242,6 +242,9 @@ func do(outPath, oInput string, arInput string) error { return errors.New("found two occurrences of uninitialised hash value in object file") } + if _, exists := os.LookupEnv("BORINGSSL_FIPS_SHOW_HASH"); exists { + fmt.Printf("Module hash: %x\n", calculated) + } copy(objectBytes[offset:], calculated) return os.WriteFile(outPath, objectBytes, perm&0777) diff --git a/naiveproxy/src/third_party/boringssl/src/util/fipstools/test_fips.c b/naiveproxy/src/third_party/boringssl/src/util/fipstools/test_fips.c index bd0ec46646..bb36853b3d 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/fipstools/test_fips.c +++ b/naiveproxy/src/third_party/boringssl/src/util/fipstools/test_fips.c @@ -48,16 +48,32 @@ static void hexdump(const void *a, size_t len) { } int main(int argc, char **argv) { - CRYPTO_library_init(); + // Ensure that the output is line-buffered rather than fully buffered. When + // some of the tests fail, some of the output can otherwise be lost. + setvbuf(stdout, NULL, _IOLBF, 0); + setvbuf(stderr, NULL, _IOLBF, 0); + + if (!FIPS_mode()) { + printf("Module not in FIPS mode\n"); + goto err; + } + printf("Module is in FIPS mode\n"); const uint32_t module_version = FIPS_version(); if (module_version == 0) { printf("No module version set\n"); goto err; } - printf("Module: '%s', version: %" PRIu32 "\n", FIPS_module_name(), + printf("Module: '%s', version: %" PRIu32 " hash:\n", FIPS_module_name(), module_version); +#if !defined(OPENSSL_ASAN) + hexdump(FIPS_module_hash(), SHA256_DIGEST_LENGTH); +#else + printf("(not available when compiled for ASAN)"); +#endif + printf("\n"); + static const uint8_t kAESKey[16] = "BoringCrypto Key"; static const uint8_t kPlaintext[64] = "BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext!"; @@ -292,9 +308,9 @@ int main(int argc, char **argv) { static const uint8_t kNotValidX926[] = {1,2,3,4,5,6}; if (!EC_KEY_oct2key(ec_key, kNotValidX926, sizeof(kNotValidX926), /*ctx=*/NULL)) { - printf("Error while parsing invalid ECDSA public key"); + printf("Error while parsing invalid ECDSA public key\n"); } else { - printf("Unexpected success while parsing invalid ECDSA public key"); + printf("Unexpected success while parsing invalid ECDSA public key\n"); goto err; } EC_KEY_free(ec_key); diff --git a/naiveproxy/src/third_party/boringssl/src/util/generate_build_files.py b/naiveproxy/src/third_party/boringssl/src/util/generate_build_files.py index 31b39f4a2f..fd9ca6c348 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/generate_build_files.py +++ b/naiveproxy/src/third_party/boringssl/src/util/generate_build_files.py @@ -24,6 +24,7 @@ import json PREFIX = None +EMBED_TEST_DATA = False def PathOf(x): @@ -190,6 +191,8 @@ class AndroidCMake(object): files['test_support']) self.PrintVariableSection(out, 'crypto_test_sources', files['crypto_test']) + self.PrintVariableSection(out, 'crypto_test_data', + files['crypto_test_data']) self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test']) @@ -637,6 +640,13 @@ def main(platforms): crypto_nasm = sorted(sources['bcm']['nasm'] + sources['crypto']['nasm'] + sources['test_support']['nasm']) + if EMBED_TEST_DATA: + with open('crypto_test_data.cc', 'w+') as out: + subprocess.check_call( + ['go', 'run', 'util/embed_test_data.go'] + sources['crypto_test']['data'], + cwd='src', + stdout=out) + files = { 'bcm_crypto': PrefixWithSrc(sources['bcm']['srcs']), 'crypto': PrefixWithSrc(crypto), @@ -690,8 +700,14 @@ if __name__ == '__main__': '|'.join(sorted(ALL_PLATFORMS.keys()))) parser.add_option('--prefix', dest='prefix', help='For Bazel, prepend argument to all source files') + parser.add_option( + '--embed_test_data', dest='embed_test_data', action='store_true', + help='Generates the legacy crypto_test_data.cc file. To use, build with' + + ' -DBORINGSSL_CUSTOM_GET_TEST_DATA and add this file to ' + + 'crypto_test.') options, args = parser.parse_args(sys.argv[1:]) PREFIX = options.prefix + EMBED_TEST_DATA = options.embed_test_data if not args: parser.print_help() diff --git a/naiveproxy/src/third_party/boringssl/src/util/pregenerate/build.go b/naiveproxy/src/third_party/boringssl/src/util/pregenerate/build.go index 4d8bbcd63f..7013945cca 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/pregenerate/build.go +++ b/naiveproxy/src/third_party/boringssl/src/util/pregenerate/build.go @@ -117,9 +117,9 @@ func (in *InputTarget) Pregenerate(name string) (out build.Target, tasks []Task, addPerlasmTask(&out.Asm, &p, "-linux.S", []string{"linux32"}) } for _, p := range in.PerlasmX86 { - addPerlasmTask(&out.Asm, &p, "-apple.S", []string{"macosx", "-fPIC", "-DOPENSSL_IA32_SSE2"}) - addPerlasmTask(&out.Asm, &p, "-linux.S", []string{"elf", "-fPIC", "-DOPENSSL_IA32_SSE2"}) - addPerlasmTask(&out.Nasm, &p, "-win.asm", []string{"win32n", "-fPIC", "-DOPENSSL_IA32_SSE2"}) + addPerlasmTask(&out.Asm, &p, "-apple.S", []string{"macosx", "-fPIC"}) + addPerlasmTask(&out.Asm, &p, "-linux.S", []string{"elf", "-fPIC"}) + addPerlasmTask(&out.Nasm, &p, "-win.asm", []string{"win32n", "-fPIC"}) } for _, p := range in.PerlasmX86_64 { addPerlasmTask(&out.Asm, &p, "-apple.S", []string{"macosx"}) @@ -219,7 +219,7 @@ func buildVariablesTask(targets map[string]build.Target, dst, comment string, wr func writeBazelVariable(b *bytes.Buffer, name string, val []string) { fmt.Fprintf(b, "\n%s = [\n", name) for _, v := range val { - fmt.Fprintf(b, " %q,\n", v) + fmt.Fprintf(b, " %q,\n", v) } fmt.Fprintf(b, "]\n") } @@ -245,8 +245,11 @@ func writeMakeVariable(b *bytes.Buffer, name string, val []string) { } func writeGNVariable(b *bytes.Buffer, name string, val []string) { - // Bazel and GN have the same syntax similar syntax. - writeBazelVariable(b, name, val) + fmt.Fprintf(b, "\n%s = [\n", name) + for _, v := range val { + fmt.Fprintf(b, " %q,\n", v) + } + fmt.Fprintf(b, "]\n") } func jsonTask(targets map[string]build.Target, dst string) Task { diff --git a/naiveproxy/src/third_party/boringssl/src/util/testresult/testresult.go b/naiveproxy/src/third_party/boringssl/src/util/testresult/testresult.go index b353ecebf5..5b131ad287 100644 --- a/naiveproxy/src/third_party/boringssl/src/util/testresult/testresult.go +++ b/naiveproxy/src/third_party/boringssl/src/util/testresult/testresult.go @@ -43,27 +43,31 @@ func NewResults() *Results { } } -func (t *Results) addResult(name, result, expected string) { +func (t *Results) addResult(name, result, expected string, err error) { if _, found := t.Tests[name]; found { panic(fmt.Sprintf("duplicate test name %q", name)) } - t.Tests[name] = Result{ + r := Result{ Actual: result, Expected: expected, IsUnexpected: result != expected, } + if err != nil { + r.Error = err.Error() + } + t.Tests[name] = r t.NumFailuresByType[result]++ } // AddResult records a test result with the given result string. The test is a // failure if the result is not "PASS". -func (t *Results) AddResult(name, result string) { - t.addResult(name, result, "PASS") +func (t *Results) AddResult(name, result string, err error) { + t.addResult(name, result, "PASS", err) } // AddSkip marks a test as being skipped. It is not considered a failure. func (t *Results) AddSkip(name string) { - t.addResult(name, "SKIP", "SKIP") + t.addResult(name, "SKIP", "SKIP", nil) } func (t *Results) HasUnexpectedResults() bool { @@ -93,4 +97,7 @@ type Result struct { Actual string `json:"actual"` Expected string `json:"expected"` IsUnexpected bool `json:"is_unexpected"` + // Error is not part of the Chromium test results schema, but is useful for + // BoGo output. + Error string `json:"error,omitempty"` } diff --git a/naiveproxy/src/third_party/boringssl/test_data_chromium.cc b/naiveproxy/src/third_party/boringssl/test_data_chromium.cc index acf157db96..62723dbcc4 100644 --- a/naiveproxy/src/third_party/boringssl/test_data_chromium.cc +++ b/naiveproxy/src/third_party/boringssl/test_data_chromium.cc @@ -8,9 +8,9 @@ #include "base/files/file_util.h" #include "base/path_service.h" -// BoringSSL requires a GetTestData function to pick up test data files. By -// default, BoringSSL generates a source file with the data embedded, but this -// exceeds the limit for the _CheckForTooLargeFiles presubmit check. +// Tests running on Chromium infrastructure cannot find their test data without +// using `base::PathService`, so we swap out the `GetTestData` function with a +// Chromium-specific one. std::string GetTestData(const char *path) { base::FilePath file_path; base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &file_path); diff --git a/naiveproxy/src/third_party/brotli/README.chromium b/naiveproxy/src/third_party/brotli/README.chromium index 7ca10bcc9e..c275dd3dc9 100644 --- a/naiveproxy/src/third_party/brotli/README.chromium +++ b/naiveproxy/src/third_party/brotli/README.chromium @@ -1,6 +1,7 @@ Name: Brotli URL: https://github.com/google/brotli Version: 9801a2c5d6c67c467ffad676ac301379bb877fc3 +Revision: 9801a2c5d6c67c467ffad676ac301379bb877fc3 License: MIT License File: LICENSE Security Critical: yes diff --git a/naiveproxy/src/third_party/jni_zero/BUILD.gn b/naiveproxy/src/third_party/jni_zero/BUILD.gn index 99af79021b..dcacd2a8b9 100644 --- a/naiveproxy/src/third_party/jni_zero/BUILD.gn +++ b/naiveproxy/src/third_party/jni_zero/BUILD.gn @@ -8,72 +8,86 @@ config("jni_include_dir") { include_dirs = [ jni_headers_dir ] } -config("toolchain_define") { +config("jni_zero_defines") { + defines = [] if (is_robolectric) { - defines = [ "JNI_ZERO_IS_ROBOLECTRIC" ] + defines += [ "JNI_ZERO_IS_ROBOLECTRIC" ] + } + if (enable_jni_multiplexing) { + defines += [ "JNI_ZERO_MULTIPLEXING_ENABLED" ] } -} - -generate_jar_jni("system_jni") { - classes = [ - "java/util/Arrays.class", - "java/util/Collection.class", - ] - visibility = [ ":*" ] } # This is the public target that we intend others to use. component("jni_zero") { - # This is the public API. - sources = [ + public = [ "default_conversions.h", "jni_zero.h", + + # TODO(bugs.webrtc.org/42225138): Move back to sources as + # soon as WebRTC removes the jni_generator_helper.h which at + # the moment needs to read jni_zero::internal::kJniStackMarkerValue. + "jni_zero_internal.h", ] - # These are intended to only be used within jni_zero and the code it generates. - sources += [ + sources = [ "common_apis.cc", "common_apis.h", "default_conversions.cc", + "java_refs.cc", + "java_refs.h", "jni_export.h", + "jni_methods.h", + "jni_wrappers.h", "jni_zero.cc", - "jni_zero_internal.h", "logging.cc", "logging.h", + "type_conversions.h", ] + configs += [ ":jni_include_dir" ] + public_configs = [ ":jni_zero_defines" ] + if (is_android) { libs = [ "log" ] } else if (is_robolectric) { - public_configs = [ "//third_party/jdk:jdk" ] + public_configs += [ "//third_party/jdk:jdk" ] } - configs += [ - ":toolchain_define", - ":jni_include_dir", + + deps = [ ] } if (enable_java_templates && is_android) { import("//build/config/android/rules.gni") - java_library("jni_zero_java") { - supports_android = true - deps = [ "//build/android:build_java" ] + android_library("jni_zero_java") { + deps = [ ":generate_jni_java" ] + public_deps = [ ":gendeps_java" ] + preferred_dep = true sources = [ "java/src/org/jni_zero/AccessedByNative.java", "java/src/org/jni_zero/CalledByNative.java", "java/src/org/jni_zero/CalledByNativeForTesting.java", "java/src/org/jni_zero/CalledByNativeUnchecked.java", - "java/src/org/jni_zero/CheckDiscard.java", "java/src/org/jni_zero/JNINamespace.java", - "java/src/org/jni_zero/JniStaticTestMocker.java", + "java/src/org/jni_zero/JniInit.java", "java/src/org/jni_zero/JniType.java", + "java/src/org/jni_zero/JniUtil.java", "java/src/org/jni_zero/NativeClassQualifiedName.java", - "java/src/org/jni_zero/NativeLibraryLoadedStatus.java", "java/src/org/jni_zero/NativeMethods.java", ] proguard_configs = [ "proguard.flags" ] } + # Classes referenced by generated code. + android_library("gendeps_java") { + sources = [ + "java/src/org/jni_zero/CheckDiscard.java", + "java/src/org/jni_zero/JniStaticTestMocker.java", + "java/src/org/jni_zero/NativeLibraryLoadedStatus.java", + ] + } + group("jni_zero_tests") { testonly = true deps = [ diff --git a/naiveproxy/src/third_party/jni_zero/codegen/natives_header.py b/naiveproxy/src/third_party/jni_zero/codegen/natives_header.py index 9128e41ac9..721f2f7376 100644 --- a/naiveproxy/src/third_party/jni_zero/codegen/natives_header.py +++ b/naiveproxy/src/third_party/jni_zero/codegen/natives_header.py @@ -44,7 +44,7 @@ def _impl_forward_declaration(sb, native, params): def proxy_declaration(sb, jni_obj, native): stub_name = jni_obj.GetStubName(native) return_type_cpp = native.proxy_return_type.to_cpp() - sb(f'JNI_BOUNDARY_EXPORT {return_type_cpp} {stub_name}') + sb(f'JNI_POSSIBLE_BOUNDARY_EXPORT {return_type_cpp} {stub_name}') with sb.param_list() as plist: plist.append('JNIEnv* env') jtype = 'jclass' if native.static else 'jobject' @@ -115,10 +115,12 @@ def _single_method(sb, jni_obj, native): return if not return_type.converted_type: - with sb.statement(): - sb('return _ret') - if not return_type.is_primitive(): - sb('.Release()') + if return_type.is_primitive(): + sb('return _ret;\n') + else: + # Use ReleaseLocal() to ensure we are not calling .Release() on a + # global ref. https://crbug.com/40944912 + sb('return _ret.ReleaseLocal();\n') return with sb.statement(): diff --git a/naiveproxy/src/third_party/jni_zero/codegen/proxy_impl_java.py b/naiveproxy/src/third_party/jni_zero/codegen/proxy_impl_java.py index 5b491afbb6..26bf783bfc 100644 --- a/naiveproxy/src/third_party/jni_zero/codegen/proxy_impl_java.py +++ b/naiveproxy/src/third_party/jni_zero/codegen/proxy_impl_java.py @@ -37,6 +37,9 @@ public {return_type_str} {native.name}({sig_params})""") with sb.block(): if native.first_param_cpp_type: sb(f'assert {native.params[0].name} != 0;\n') + for p in native.params: + if not p.java_type.nullable: + sb(f'assert {p.name} != null;\n') with sb.statement(): if not native.return_type.is_void(): sb(f'return ({return_type_str}) ') @@ -118,6 +121,9 @@ def _imports(sb, ctx): classes.add(ctx.gen_jni_class.full_name_with_dots) for c in ctx.type_resolver.imports: + # Since this is pure Java, the class generated here will go through jarjar + # and thus we want to avoid prefixes. + c = c.class_without_prefix if c.is_nested: # We will refer to all nested classes by OuterClass.InnerClass. We do this # to reduce risk of naming collisions. diff --git a/naiveproxy/src/third_party/jni_zero/common_apis.cc b/naiveproxy/src/third_party/jni_zero/common_apis.cc index d55d422433..3ee4fe9a1a 100644 --- a/naiveproxy/src/third_party/jni_zero/common_apis.cc +++ b/naiveproxy/src/third_party/jni_zero/common_apis.cc @@ -17,4 +17,13 @@ ScopedJavaLocalRef ArrayToList(JNIEnv* env, return nullptr; } +ScopedJavaLocalRef MapToArray(JNIEnv* env, + const JavaRef& map) { + return nullptr; +} +ScopedJavaLocalRef ArrayToMap(JNIEnv* env, + const JavaRef& array) { + return nullptr; +} + } // namespace jni_zero diff --git a/naiveproxy/src/third_party/jni_zero/common_apis.h b/naiveproxy/src/third_party/jni_zero/common_apis.h index 6ac97d2e2a..a27ba0a2ea 100644 --- a/naiveproxy/src/third_party/jni_zero/common_apis.h +++ b/naiveproxy/src/third_party/jni_zero/common_apis.h @@ -5,7 +5,10 @@ #ifndef JNI_ZERO_COMMON_APIS_H_ #define JNI_ZERO_COMMON_APIS_H_ -#include "third_party/jni_zero/jni_zero.h" +#include + +#include "third_party/jni_zero/java_refs.h" +#include "third_party/jni_zero/jni_export.h" namespace jni_zero { // Wraps Collection.toArray(). @@ -15,6 +18,13 @@ CollectionToArray(JNIEnv* env, const JavaRef& collection); JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef ArrayToList( JNIEnv* env, const JavaRef& array); +// Serializes a Map to an array of key/values. +JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef MapToArray( + JNIEnv* env, + const JavaRef& map); +JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef ArrayToMap( + JNIEnv* env, + const JavaRef& array); } // namespace jni_zero #endif // JNI_ZERO_COMMON_APIS_H_ diff --git a/naiveproxy/src/third_party/jni_zero/default_conversions.h b/naiveproxy/src/third_party/jni_zero/default_conversions.h index fb6992e354..483471a469 100644 --- a/naiveproxy/src/third_party/jni_zero/default_conversions.h +++ b/naiveproxy/src/third_party/jni_zero/default_conversions.h @@ -6,12 +6,17 @@ #define JNI_ZERO_DEFAULT_CONVERSIONS_H_ #include +#include +#include #include "third_party/jni_zero/common_apis.h" #include "third_party/jni_zero/jni_zero.h" namespace jni_zero { namespace internal { +template +concept IsJavaRef = std::is_base_of_v, T>; + template concept HasReserve = requires(T t) { t.reserve(0); }; @@ -21,8 +26,15 @@ concept HasPushBack = requires(T t, T::value_type v) { t.push_back(v); }; template concept HasInsert = requires(T t, T::value_type v) { t.insert(v); }; +template +concept IsMap = requires(T t) { + typename T::key_type; + typename T::mapped_type; +}; + template concept IsContainer = requires(T t) { + !IsMap; typename T::value_type; t.begin(); t.end(); @@ -146,6 +158,7 @@ inline ByteArrayView FromJniArray( // There is a circular dependency between common_apis.cc and here. JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef CollectionToArray(JNIEnv* env, const JavaRef& collection); + JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef ArrayToList( JNIEnv* env, const JavaRef& array); @@ -161,10 +174,99 @@ inline ContainerType FromJniCollection(JNIEnv* env, template inline ScopedJavaLocalRef ToJniList(JNIEnv* env, const ContainerType& collection) { + if (collection.empty()) { + return g_empty_list.AsLocalRef(env); + } ScopedJavaLocalRef arr = ToJniArray(env, collection, g_object_class); return ArrayToList(env, arr); } +JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef MapToArray( + JNIEnv* env, + const JavaRef& map); +JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef ArrayToMap( + JNIEnv* env, + const JavaRef& array); + +// Convert Map -> stl map type using FromJniType() on each key & value. +template +inline ContainerType FromJniType(JNIEnv* env, + const JavaRef& j_object) { + using KeyType = ContainerType::key_type; + using ValueType = ContainerType::mapped_type; + + ScopedJavaLocalRef j_array = MapToArray(env, j_object); + jsize array_jsize = env->GetArrayLength(j_array.obj()); + + ContainerType ret; + if constexpr (internal::HasReserve) { + size_t array_size = static_cast(array_jsize); + ret.reserve(array_size / 2); + } + for (jsize i = 0; i < array_jsize; i += 2) { + // No need to call CheckException() since we know the array is of the + // correct size, since we are the ones who created it. + jobject j_key = env->GetObjectArrayElement(j_array.obj(), i); + jobject j_value = env->GetObjectArrayElement(j_array.obj(), i + 1); + // Do not call FromJni for jobject->jobject. + if constexpr (internal::IsJavaRef && + internal::IsJavaRef) { + ret.emplace(std::piecewise_construct, std::forward_as_tuple(env, j_key), + std::forward_as_tuple(env, j_value)); + } else if constexpr (internal::IsJavaRef) { + auto value = ScopedJavaLocalRef::Adopt(env, j_value); + ret.emplace(std::piecewise_construct, std::forward_as_tuple(env, j_key), + FromJniType(env, value)); + } else if constexpr (internal::IsJavaRef) { + auto key = ScopedJavaLocalRef::Adopt(env, j_key); + ret.emplace(std::piecewise_construct, FromJniType(env, key), + std::forward_as_tuple(env, j_value)); + } else { + auto key = ScopedJavaLocalRef::Adopt(env, j_key); + auto value = ScopedJavaLocalRef::Adopt(env, j_value); + ret.emplace(FromJniType(env, key), + FromJniType(env, value)); + } + } + return ret; +} + +// Convert stl map -> Map type using ToJniType() on each key & value. +template +inline ScopedJavaLocalRef ToJniType(JNIEnv* env, + const ContainerType& map) { + using KeyType = ContainerType::key_type; + using ValueType = ContainerType::mapped_type; + jsize map_jsize = static_cast(map.size()); + if (map_jsize == 0) { + return g_empty_map.AsLocalRef(env); + } + jobjectArray j_array = + env->NewObjectArray(map_jsize * 2, g_object_class, nullptr); + CheckException(env); + + jsize i = 0; + for (auto const& [key, value] : map) { + // Do not call ToJni for jobject->jobject. + if constexpr (internal::IsJavaRef) { + env->SetObjectArrayElement(j_array, i, key.obj()); + } else { + ScopedJavaLocalRef j_key = ToJniType(env, key); + env->SetObjectArrayElement(j_array, i, j_key.obj()); + } + ++i; + + if constexpr (internal::IsJavaRef) { + env->SetObjectArrayElement(j_array, i, value.obj()); + } else { + ScopedJavaLocalRef j_value = ToJniType(env, value); + env->SetObjectArrayElement(j_array, i, j_value.obj()); + } + ++i; + } + auto array = ScopedJavaLocalRef::Adopt(env, j_array); + return ArrayToMap(env, array); +} } // namespace jni_zero #endif // JNI_ZERO_DEFAULT_CONVERSIONS_H_ diff --git a/naiveproxy/src/third_party/jni_zero/java/src/org/jni_zero/JniInit.java b/naiveproxy/src/third_party/jni_zero/java/src/org/jni_zero/JniInit.java new file mode 100644 index 0000000000..8add496432 --- /dev/null +++ b/naiveproxy/src/third_party/jni_zero/java/src/org/jni_zero/JniInit.java @@ -0,0 +1,19 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.jni_zero; + +import java.util.Collections; + +/** Used by jni_zero.cc. */ +@JNINamespace("jni_zero") +public class JniInit { + @CalledByNative + private static Object[] init() { + // For JVM (works fine on ART), cannot call from Java -> Native during InitVM because the + // System.loadLibrary() call has not yet completed. Could work around this by using + // RegisterNatives(), but simpler to return an array than to make Java->Native work. + return new Object[] {Collections.EMPTY_LIST, Collections.EMPTY_MAP}; + } +} diff --git a/naiveproxy/src/third_party/jni_zero/java/src/org/jni_zero/JniUtil.java b/naiveproxy/src/third_party/jni_zero/java/src/org/jni_zero/JniUtil.java new file mode 100644 index 0000000000..b43b6e9818 --- /dev/null +++ b/naiveproxy/src/third_party/jni_zero/java/src/org/jni_zero/JniUtil.java @@ -0,0 +1,33 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.jni_zero; + +import android.util.ArrayMap; + +import java.util.Map; + +/** Native helpers. */ +public class JniUtil { + @CalledByNative + private static Object[] mapToArray(Map map) { + Object[] ret = new Object[map.size() * 2]; + int i = 0; + for (var entry : map.entrySet()) { + ret[i++] = entry.getKey(); + ret[i++] = entry.getValue(); + } + return ret; + } + + @CalledByNative + private static Map arrayToMap(Object[] array) { + int len = array.length; + Map ret = new ArrayMap(len / 2); + for (int i = 0; i < len; i += 2) { + ret.put(array[i], array[i + 1]); + } + return ret; + } +} diff --git a/naiveproxy/src/third_party/jni_zero/java_refs.cc b/naiveproxy/src/third_party/jni_zero/java_refs.cc new file mode 100644 index 0000000000..9e288ccddb --- /dev/null +++ b/naiveproxy/src/third_party/jni_zero/java_refs.cc @@ -0,0 +1,122 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/jni_zero/java_refs.h" + +#include "third_party/jni_zero/jni_methods.h" + +namespace jni_zero { +namespace { +const int kDefaultLocalFrameCapacity = 16; +} + +ScopedJavaLocalFrame::ScopedJavaLocalFrame(JNIEnv* env) : env_(env) { + int failed = env_->PushLocalFrame(kDefaultLocalFrameCapacity); + JNI_ZERO_DCHECK(!failed); +} + +ScopedJavaLocalFrame::ScopedJavaLocalFrame(JNIEnv* env, int capacity) + : env_(env) { + int failed = env_->PushLocalFrame(capacity); + JNI_ZERO_DCHECK(!failed); +} + +ScopedJavaLocalFrame::~ScopedJavaLocalFrame() { + env_->PopLocalFrame(nullptr); +} + +#if JNI_ZERO_DCHECK_IS_ON() +// This constructor is inlined when DCHECKs are disabled; don't add anything +// else here. +JavaRef::JavaRef(JNIEnv* env, jobject obj) : obj_(obj) { + if (obj) { + JNI_ZERO_DCHECK(env && env->GetObjectRefType(obj) == JNILocalRefType); + } +} +#endif + +JNIEnv* JavaRef::SetNewLocalRef(JNIEnv* env, jobject obj) { + if (!env) { + env = AttachCurrentThread(); + } else { + JNI_ZERO_DCHECK(env == + AttachCurrentThread()); // Is |env| on correct thread. + } + if (obj) { + obj = env->NewLocalRef(obj); + } + if (obj_) { + env->DeleteLocalRef(obj_); + } + obj_ = obj; + return env; +} + +void JavaRef::SetNewGlobalRef(JNIEnv* env, jobject obj) { + if (!env) { + env = AttachCurrentThread(); + } else { + JNI_ZERO_DCHECK(env == + AttachCurrentThread()); // Is |env| on correct thread. + } + if (obj) { + obj = env->NewGlobalRef(obj); + } + if (obj_) { + env->DeleteGlobalRef(obj_); + } + obj_ = obj; +} + +void JavaRef::ResetLocalRef(JNIEnv* env) { + if (obj_) { + JNI_ZERO_DCHECK(env == + AttachCurrentThread()); // Is |env| on correct thread. + env->DeleteLocalRef(obj_); + obj_ = nullptr; + } +} + +void JavaRef::ResetGlobalRef() { + if (obj_) { + AttachCurrentThread()->DeleteGlobalRef(obj_); + obj_ = nullptr; + } +} + +ScopedJavaGlobalWeakRef::ScopedJavaGlobalWeakRef( + const ScopedJavaGlobalWeakRef& orig) { + Assign(orig); +} + +ScopedJavaGlobalWeakRef::ScopedJavaGlobalWeakRef(JNIEnv* env, + const JavaRef& obj) + : obj_(env->NewWeakGlobalRef(obj.obj())) {} + +void ScopedJavaGlobalWeakRef::reset() { + if (obj_) { + AttachCurrentThread()->DeleteWeakGlobalRef(obj_); + obj_ = nullptr; + } +} + +ScopedJavaLocalRef ScopedJavaGlobalWeakRef::get(JNIEnv* env) const { + jobject real = obj_ ? real = env->NewLocalRef(obj_) : nullptr; + return ScopedJavaLocalRef(env, real); +} + +void ScopedJavaGlobalWeakRef::Assign(const ScopedJavaGlobalWeakRef& other) { + if (&other == this) { + return; + } + + JNIEnv* env = AttachCurrentThread(); + if (obj_) { + env->DeleteWeakGlobalRef(obj_); + } + + obj_ = other.obj_ ? env->NewWeakGlobalRef(other.obj_) : nullptr; +} + +} // namespace jni_zero diff --git a/naiveproxy/src/third_party/jni_zero/java_refs.h b/naiveproxy/src/third_party/jni_zero/java_refs.h new file mode 100644 index 0000000000..25d3e4c575 --- /dev/null +++ b/naiveproxy/src/third_party/jni_zero/java_refs.h @@ -0,0 +1,484 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef JNI_ZERO_JAVA_REFS_H_ +#define JNI_ZERO_JAVA_REFS_H_ + +#include + +#include +#include + +#include "third_party/jni_zero/jni_export.h" +#include "third_party/jni_zero/logging.h" + +namespace jni_zero { + +// Creates a new local reference frame, in which at least a given number of +// local references can be created. Note that local references already created +// in previous local frames are still valid in the current local frame. +class JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalFrame { + public: + explicit ScopedJavaLocalFrame(JNIEnv* env); + ScopedJavaLocalFrame(JNIEnv* env, int capacity); + + ScopedJavaLocalFrame(const ScopedJavaLocalFrame&) = delete; + ScopedJavaLocalFrame& operator=(const ScopedJavaLocalFrame&) = delete; + + ~ScopedJavaLocalFrame(); + + private: + // This class is only good for use on the thread it was created on so + // it's safe to cache the non-threadsafe JNIEnv* inside this object. + JNIEnv* env_; +}; + +// Forward declare the generic java reference template class. +template +class JavaRef; + +// Template specialization of JavaRef, which acts as the base class for all +// other JavaRef<> template types. This allows you to e.g. pass +// ScopedJavaLocalRef into a function taking const JavaRef& +template <> +class JNI_ZERO_COMPONENT_BUILD_EXPORT JavaRef { + public: + // Initializes a null reference. + constexpr JavaRef() {} + + // Allow nullptr to be converted to JavaRef. This avoids having to declare an + // empty JavaRef just to pass null to a function, and makes C++ "nullptr" and + // Java "null" equivalent. + constexpr JavaRef(std::nullptr_t) {} + + JavaRef(const JavaRef&) = delete; + JavaRef& operator=(const JavaRef&) = delete; + + // Public to allow destruction of null JavaRef objects. + ~JavaRef() {} + + // TODO(torne): maybe rename this to get() for consistency with unique_ptr + // once there's fewer unnecessary uses of it in the codebase. + jobject obj() const { return obj_; } + + explicit operator bool() const { return obj_ != nullptr; } + + // Deprecated. Just use bool conversion. + // TODO(torne): replace usage and remove this. + bool is_null() const { return obj_ == nullptr; } + + protected: +// Takes ownership of the |obj| reference passed; requires it to be a local +// reference type. +#if JNI_ZERO_DCHECK_IS_ON() + // Implementation contains a DCHECK; implement out-of-line when DCHECK_IS_ON. + JavaRef(JNIEnv* env, jobject obj); +#else + JavaRef(JNIEnv* env, jobject obj) : obj_(obj) {} +#endif + + // Used for move semantics. obj_ must have been released first if non-null. + void steal(JavaRef&& other) { + obj_ = other.obj_; + other.obj_ = nullptr; + } + + // The following are implementation detail convenience methods, for + // use by the sub-classes. + JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj); + void SetNewGlobalRef(JNIEnv* env, jobject obj); + void ResetLocalRef(JNIEnv* env); + void ResetGlobalRef(); + + jobject ReleaseInternal() { + jobject obj = obj_; + obj_ = nullptr; + return obj; + } + + private: + jobject obj_ = nullptr; +}; + +// Forward declare the object array reader for the convenience function. +template +class JavaObjectArrayReader; + +// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful +// for allowing functions to accept a reference without having to mandate +// whether it is a local or global type. +template +class JavaRef : public JavaRef { + public: + constexpr JavaRef() {} + constexpr JavaRef(std::nullptr_t) {} + + JavaRef(const JavaRef&) = delete; + JavaRef& operator=(const JavaRef&) = delete; + + ~JavaRef() {} + + T obj() const { return static_cast(JavaRef::obj()); } + + // Get a JavaObjectArrayReader for the array pointed to by this reference. + // Only defined for JavaRef. + // You must pass the type of the array elements (usually jobject) as the + // template parameter. + template >> + JavaObjectArrayReader ReadElements() const { + return JavaObjectArrayReader(*this); + } + + protected: + JavaRef(JNIEnv* env, T obj) : JavaRef(env, obj) {} +}; + +// Holds a local reference to a JNI method parameter. +// Method parameters should not be deleted, and so this class exists purely to +// wrap them as a JavaRef in the JNI binding generator. Do not create +// instances manually. +template +class JavaParamRef : public JavaRef { + public: + // Assumes that |obj| is a parameter passed to a JNI method from Java. + // Does not assume ownership as parameters should not be deleted. + JavaParamRef(JNIEnv* env, T obj) : JavaRef(env, obj) {} + + // Allow nullptr to be converted to JavaParamRef. Some unit tests call JNI + // methods directly from C++ and pass null for objects which are not actually + // used by the implementation (e.g. the caller object); allow this to keep + // working. + JavaParamRef(std::nullptr_t) {} + + JavaParamRef(const JavaParamRef&) = delete; + JavaParamRef& operator=(const JavaParamRef&) = delete; + + ~JavaParamRef() {} + + // TODO(torne): remove this cast once we're using JavaRef consistently. + // http://crbug.com/506850 + operator T() const { return JavaRef::obj(); } +}; + +// Holds a local reference to a Java object. The local reference is scoped +// to the lifetime of this object. +// Instances of this class may hold onto any JNIEnv passed into it until +// destroyed. Therefore, since a JNIEnv is only suitable for use on a single +// thread, objects of this class must be created, used, and destroyed, on a +// single thread. +// Therefore, this class should only be used as a stack-based object and from a +// single thread. If you wish to have the reference outlive the current +// callstack (e.g. as a class member) or you wish to pass it across threads, +// use a ScopedJavaGlobalRef instead. +template +class ScopedJavaLocalRef : public JavaRef { + public: + // Take ownership of a bare jobject. This does not create a new reference. + // This should only be used by JNI helper functions, or in cases where code + // must call JNIEnv methods directly. + static ScopedJavaLocalRef Adopt(JNIEnv* env, T obj) { + return ScopedJavaLocalRef(env, obj); + } + + constexpr ScopedJavaLocalRef() {} + constexpr ScopedJavaLocalRef(std::nullptr_t) {} + + // Copy constructor. This is required in addition to the copy conversion + // constructor below. + ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) { + JavaRef::SetNewLocalRef(env_, other.obj()); + } + + // Copy conversion constructor. + template >> + ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) { + JavaRef::SetNewLocalRef(env_, other.obj()); + } + + // Move constructor. This is required in addition to the move conversion + // constructor below. + ScopedJavaLocalRef(ScopedJavaLocalRef&& other) : env_(other.env_) { + JavaRef::steal(std::move(other)); + } + + // Move conversion constructor. + template >> + ScopedJavaLocalRef(ScopedJavaLocalRef&& other) : env_(other.env_) { + JavaRef::steal(std::move(other)); + } + + // Constructor for other JavaRef types. + explicit ScopedJavaLocalRef(const JavaRef& other) { Reset(other); } + + ScopedJavaLocalRef(JNIEnv* env, const JavaRef& other) { Reset(other); } + + // Assumes that |obj| is a local reference to a Java object and takes + // ownership of this local reference. + // TODO(torne): make legitimate uses call Adopt() instead, and make this + // private. + ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef(env, obj), env_(env) {} + + ~ScopedJavaLocalRef() { Reset(); } + + // Null assignment, for disambiguation. + ScopedJavaLocalRef& operator=(std::nullptr_t) { + Reset(); + return *this; + } + + // Copy assignment. + ScopedJavaLocalRef& operator=(const ScopedJavaLocalRef& other) { + Reset(other); + return *this; + } + + // Copy conversion assignment. + template >> + ScopedJavaLocalRef& operator=(const ScopedJavaLocalRef& other) { + Reset(other); + return *this; + } + + // Move assignment. + template >> + ScopedJavaLocalRef& operator=(ScopedJavaLocalRef&& other) { + env_ = other.env_; + Reset(); + JavaRef::steal(std::move(other)); + return *this; + } + + // Assignment for other JavaRef types. + ScopedJavaLocalRef& operator=(const JavaRef& other) { + Reset(other); + return *this; + } + + void Reset() { JavaRef::ResetLocalRef(env_); } + + template >> + void Reset(const ScopedJavaLocalRef& other) { + // We can copy over env_ here as |other| instance must be from the same + // thread as |this| local ref. (See class comment for multi-threading + // limitations, and alternatives). + env_ = JavaRef::SetNewLocalRef(other.env_, other.obj()); + } + + void Reset(const JavaRef& other) { + // If |env_| was not yet set (is still null) it will be attached to the + // current thread in SetNewLocalRef(). + env_ = JavaRef::SetNewLocalRef(env_, other.obj()); + } + + // Releases the local reference to the caller. The caller *must* delete the + // local reference when it is done with it. Note that calling a Java method + // is *not* a transfer of ownership and Release() should not be used. + T Release() { return static_cast(JavaRef::ReleaseInternal()); } + + // Alias for Release(). For use in templates when global refs are invalid. + T ReleaseLocal() { return static_cast(JavaRef::ReleaseInternal()); } + + private: + // This class is only good for use on the thread it was created on so + // it's safe to cache the non-threadsafe JNIEnv* inside this object. + JNIEnv* env_ = nullptr; + + // Prevent ScopedJavaLocalRef(JNIEnv*, T obj) from being used to take + // ownership of a JavaParamRef's underlying object - parameters are not + // allowed to be deleted and so should not be owned by ScopedJavaLocalRef. + // TODO(torne): this can be removed once JavaParamRef no longer has an + // implicit conversion back to T. + ScopedJavaLocalRef(JNIEnv* env, const JavaParamRef& other); + + // Friend required to get env_ from conversions. + template + friend class ScopedJavaLocalRef; + + // Avoids JavaObjectArrayReader having to accept and store its own env. + template + friend class JavaObjectArrayReader; +}; + +// Holds a global reference to a Java object. The global reference is scoped +// to the lifetime of this object. This class does not hold onto any JNIEnv* +// passed to it, hence it is safe to use across threads (within the constraints +// imposed by the underlying Java object that it references). +template +class ScopedJavaGlobalRef : public JavaRef { + public: + constexpr ScopedJavaGlobalRef() {} + constexpr ScopedJavaGlobalRef(std::nullptr_t) {} + + // Copy constructor. This is required in addition to the copy conversion + // constructor below. + ScopedJavaGlobalRef(const ScopedJavaGlobalRef& other) { Reset(other); } + + // Copy conversion constructor. + template >> + ScopedJavaGlobalRef(const ScopedJavaGlobalRef& other) { + Reset(other); + } + + // Move constructor. This is required in addition to the move conversion + // constructor below. + ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other) { + JavaRef::steal(std::move(other)); + } + + // Move conversion constructor. + template >> + ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other) { + JavaRef::steal(std::move(other)); + } + + // Conversion constructor for other JavaRef types. + explicit ScopedJavaGlobalRef(const JavaRef& other) { Reset(other); } + + ScopedJavaGlobalRef(JNIEnv* env, const JavaRef& other) { + JavaRef::SetNewGlobalRef(env, other.obj()); + } + + // Create a new global reference to the object. + // Deprecated. Don't use bare jobjects; use a JavaRef as the input. + ScopedJavaGlobalRef(JNIEnv* env, T obj) { Reset(env, obj); } + + ~ScopedJavaGlobalRef() { Reset(); } + + // Null assignment, for disambiguation. + ScopedJavaGlobalRef& operator=(std::nullptr_t) { + Reset(); + return *this; + } + + // Copy assignment. + ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef& other) { + Reset(other); + return *this; + } + + // Copy conversion assignment. + template >> + ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef& other) { + Reset(other); + return *this; + } + + // Move assignment. + template >> + ScopedJavaGlobalRef& operator=(ScopedJavaGlobalRef&& other) { + Reset(); + JavaRef::steal(std::move(other)); + return *this; + } + + // Assignment for other JavaRef types. + ScopedJavaGlobalRef& operator=(const JavaRef& other) { + Reset(other); + return *this; + } + + void Reset() { JavaRef::ResetGlobalRef(); } + + template >> + void Reset(const ScopedJavaGlobalRef& other) { + Reset(nullptr, other.obj()); + } + + void Reset(const JavaRef& other) { Reset(nullptr, other.obj()); } + + // Deprecated. You can just use Reset(const JavaRef&). + void Reset(JNIEnv* env, const JavaParamRef& other) { + Reset(env, other.obj()); + } + + // Deprecated. Don't use bare jobjects; use a JavaRef as the input. + void Reset(JNIEnv* env, T obj) { JavaRef::SetNewGlobalRef(env, obj); } + + // Releases the global reference to the caller. The caller *must* delete the + // global reference when it is done with it. Note that calling a Java method + // is *not* a transfer of ownership and Release() should not be used. + T Release() { return static_cast(JavaRef::ReleaseInternal()); } + + // Create a local reference. + ScopedJavaLocalRef AsLocalRef(JNIEnv* env) const { + T j_obj = JavaRef::obj(); + if (!j_obj) { + return nullptr; + } + return ScopedJavaLocalRef::Adopt( + env, static_cast(env->NewLocalRef(j_obj))); + } +}; + +// Wrapper for working with weak references. +class JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaGlobalWeakRef { + public: + ScopedJavaGlobalWeakRef() = default; + ScopedJavaGlobalWeakRef(const ScopedJavaGlobalWeakRef& orig); + ScopedJavaGlobalWeakRef(ScopedJavaGlobalWeakRef&& orig) : obj_(orig.obj_) { + orig.obj_ = nullptr; + } + ScopedJavaGlobalWeakRef(JNIEnv* env, const JavaRef& obj); + ~ScopedJavaGlobalWeakRef() { reset(); } + + void operator=(const ScopedJavaGlobalWeakRef& rhs) { Assign(rhs); } + void operator=(ScopedJavaGlobalWeakRef&& rhs) { std::swap(obj_, rhs.obj_); } + + ScopedJavaLocalRef get(JNIEnv* env) const; + + // Returns true if the weak reference has not been initialized to point at + // an object (or ḣas had reset() called). + // Do not call this to test if the object referred to still exists! The weak + // reference remains initialized even if the target object has been collected. + bool is_uninitialized() const { return obj_ == nullptr; } + + void reset(); + + private: + void Assign(const ScopedJavaGlobalWeakRef& rhs); + + jweak obj_ = nullptr; +}; + +// A global JavaRef that will never be released. +template +class JNI_ZERO_COMPONENT_BUILD_EXPORT LeakedJavaGlobalRef : public JavaRef { + public: + constexpr LeakedJavaGlobalRef() = default; + constexpr LeakedJavaGlobalRef(std::nullptr_t) {} + + LeakedJavaGlobalRef(const LeakedJavaGlobalRef& other) = delete; + LeakedJavaGlobalRef(const LeakedJavaGlobalRef&& other) = delete; + ~LeakedJavaGlobalRef() = default; + + void Reset(JNIEnv* env, const JavaRef& j_object) { + JNI_ZERO_DCHECK(JavaRef::obj() == nullptr); + JavaRef::SetNewGlobalRef(env, j_object.obj()); + } + + // Create a local reference. + ScopedJavaLocalRef AsLocalRef(JNIEnv* env) const { + T j_obj = JavaRef::obj(); + if (!j_obj) { + return nullptr; + } + return ScopedJavaLocalRef::Adopt( + env, static_cast(env->NewLocalRef(j_obj))); + } +}; +} // namespace jni_zero + +#endif // JNI_ZERO_JAVA_REFS_H_ diff --git a/naiveproxy/src/third_party/jni_zero/java_types.py b/naiveproxy/src/third_party/jni_zero/java_types.py index 3b47cb1edc..43bb5d9e47 100644 --- a/naiveproxy/src/third_party/jni_zero/java_types.py +++ b/naiveproxy/src/third_party/jni_zero/java_types.py @@ -61,7 +61,7 @@ class JavaClass: """Represents a reference type.""" _fqn: str # This is only meaningful if make_prefix have been called on the original class. - _class_without_prefix: 'JavaClass' = None + _prefix: str = None def __post_init__(self): assert '.' not in self._fqn, f'{self._fqn} should have / and $, but not .' @@ -97,9 +97,15 @@ class JavaClass: def full_name_with_dots(self): return self._fqn.replace('/', '.').replace('$', '.') + @property + def prefix_with_dots(self): + return self._prefix.replace('/', '.') if self._prefix else self._prefix + @property def class_without_prefix(self): - return self._class_without_prefix if self._class_without_prefix else self + if not self._prefix: + return self + return JavaClass(self._fqn[len(self._prefix) + 1:]) @property def outer_class_name(self): @@ -122,11 +128,11 @@ class JavaClass: def as_type(self): return JavaType(java_class=self) - def make_prefixed(self, prefix=None): + def make_prefixed(self, prefix): if not prefix: return self prefix = prefix.replace('.', '/') - return JavaClass(f'{prefix}/{self._fqn}', self) + return JavaClass(f'{prefix}/{self._fqn}', prefix) def make_nested(self, name): return JavaClass(f'{self._fqn}${name}') @@ -139,6 +145,7 @@ class JavaType: primitive_name: Optional[str] = None java_class: Optional[JavaClass] = None converted_type: Optional[str] = dataclasses.field(default=None, compare=False) + nullable: bool = True @staticmethod def from_descriptor(descriptor): @@ -162,9 +169,9 @@ class JavaType: # Cannot use dataclass(order=True) because some fields are None. def __lt__(self, other): if self.primitive_name and not other.primitive_name: - return -1 + return True if other.primitive_name and not self.primitive_name: - return 1 + return False lhs = (self.array_dimensions, self.primitive_name or self.java_class) rhs = (other.array_dimensions, other.primitive_name or other.java_class) return lhs < rhs @@ -231,13 +238,7 @@ class JavaType: def to_proxy(self): """Converts to types used over JNI boundary.""" - # All object array types of become jobjectArray in native, but need to be - # passed as the original type on the java side. - if self.non_array_full_name_with_slashes in _CPP_TYPE_BY_JAVA_TYPE: - return self - - # All other types should just be passed as Objects or Object arrays. - return dataclasses.replace(self, java_class=OBJECT_CLASS) + return self if self.is_primitive() else OBJECT @dataclasses.dataclass(frozen=True) @@ -325,6 +326,13 @@ class JavaSignature: param_list = self.param_list.to_proxy() return JavaSignature.from_params(return_type, param_list) + def with_params_reordered(self): + return JavaSignature.from_params( + self.return_type, + JavaParamList( + tuple(sorted(self.param_list, + key=lambda x: x.java_type.to_proxy())))) + class TypeResolver: """Converts type names to fully qualified names.""" @@ -392,7 +400,10 @@ class TypeResolver: return JavaClass(f'java/lang/{name}') # Type not found, falling back to same package as this class. - return JavaClass(f'{self.java_class.package_with_slashes}/{name}') + # Set the same prefix with this class. + ret = JavaClass( + f'{self.java_class.class_without_prefix.package_with_slashes}/{name}') + return ret.make_prefixed(self.java_class.prefix_with_dots) CLASS_CLASS = JavaClass('java/lang/Class') @@ -408,6 +419,7 @@ COLLECTION_CLASSES = ( JavaClass('java/util/Set'), ) +OBJECT = JavaType(java_class=OBJECT_CLASS) CLASS = JavaType(java_class=CLASS_CLASS) LIST = JavaType(java_class=_LIST_CLASS) INT = JavaType(primitive_name='int') diff --git a/naiveproxy/src/third_party/jni_zero/jni_export.h b/naiveproxy/src/third_party/jni_zero/jni_export.h index 52506ed1af..21503c65c5 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_export.h +++ b/naiveproxy/src/third_party/jni_zero/jni_export.h @@ -11,4 +11,20 @@ #define JNI_ZERO_COMPONENT_BUILD_EXPORT #endif +#if defined(__i386__) +// Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on +// x86 - use force_align_arg_pointer to realign the stack at the JNI +// boundary. crbug.com/655248 +#define JNI_BOUNDARY_EXPORT \ + extern "C" __attribute__((visibility("default"), force_align_arg_pointer)) +#else +#define JNI_BOUNDARY_EXPORT extern "C" __attribute__((visibility("default"))) +#endif + +#if defined(JNI_ZERO_MULTIPLEXING_ENABLED) +#define JNI_POSSIBLE_BOUNDARY_EXPORT extern "C" __attribute__((always_inline)) +#else +#define JNI_POSSIBLE_BOUNDARY_EXPORT JNI_BOUNDARY_EXPORT +#endif + #endif // JNI_ZERO_JNI_EXPORT_H_ diff --git a/naiveproxy/src/third_party/jni_zero/jni_generator.py b/naiveproxy/src/third_party/jni_zero/jni_generator.py index bf1fa3726d..2dfe047281 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_generator.py +++ b/naiveproxy/src/third_party/jni_zero/jni_generator.py @@ -287,6 +287,8 @@ class JniObject: return 'Java_' + common.escape_class_name( f'{self.java_class.full_name_with_slashes}Jni/native{common.capitalize(native.name)}' ) + elif self.options.enable_jni_multiplexing: + return f'Java_{method_name}' else: return 'Java_%s_%s' % (common.escape_class_name( self.final_gen_jni_class.full_name_with_slashes), method_name) diff --git a/naiveproxy/src/third_party/jni_zero/jni_methods.h b/naiveproxy/src/third_party/jni_zero/jni_methods.h new file mode 100644 index 0000000000..1a84d2b23a --- /dev/null +++ b/naiveproxy/src/third_party/jni_zero/jni_methods.h @@ -0,0 +1,107 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef JNI_ZERO_JNI_METHODS_H_ +#define JNI_ZERO_JNI_METHODS_H_ + +#include + +#include +#include + +#include "third_party/jni_zero/java_refs.h" +#include "third_party/jni_zero/jni_export.h" + +namespace jni_zero { +// Attaches the current thread to the VM (if necessary) and return the JNIEnv*. +JNI_ZERO_COMPONENT_BUILD_EXPORT JNIEnv* AttachCurrentThread(); + +// Same to AttachCurrentThread except that thread name will be set to +// |thread_name| if it is the first call. Otherwise, thread_name won't be +// changed. AttachCurrentThread() doesn't regard underlying platform thread +// name, but just resets it to "Thread-???". This function should be called +// right after new thread is created if it is important to keep thread name. +JNI_ZERO_COMPONENT_BUILD_EXPORT JNIEnv* AttachCurrentThreadWithName( + const std::string& thread_name); + +// Detaches the current thread from VM if it is attached. +JNI_ZERO_COMPONENT_BUILD_EXPORT void DetachFromVM(); + +// Initializes the global JVM. +JNI_ZERO_COMPONENT_BUILD_EXPORT void InitVM(JavaVM* vm); + +// Returns true if the global JVM has been initialized. +JNI_ZERO_COMPONENT_BUILD_EXPORT bool IsVMInitialized(); + +// Returns the global JVM, or nullptr if it has not been initialized. +JNI_ZERO_COMPONENT_BUILD_EXPORT JavaVM* GetVM(); + +// Do not allow any future native->java calls. +// This is necessary in gtest DEATH_TESTS to prevent +// GetJavaStackTraceIfPresent() from accessing a defunct JVM (due to fork()). +// https://crbug.com/1484834 +JNI_ZERO_COMPONENT_BUILD_EXPORT void DisableJvmForTesting(); + +JNI_ZERO_COMPONENT_BUILD_EXPORT void SetExceptionHandler( + void (*callback)(JNIEnv*)); + +// Returns true if an exception is pending in the provided JNIEnv*. +JNI_ZERO_COMPONENT_BUILD_EXPORT bool HasException(JNIEnv* env); + +// If an exception is pending in the provided JNIEnv*, this function clears it +// and returns true. +JNI_ZERO_COMPONENT_BUILD_EXPORT bool ClearException(JNIEnv* env); + +// If there's any pending exception, this function will call the set exception +// handler, or if none are set, it will fatally LOG. +JNI_ZERO_COMPONENT_BUILD_EXPORT void CheckException(JNIEnv* env); + +// Sets a function to call instead of just using JNIEnv.FindClass. Useful for +// chrome's "splits" which need to be resolved in special ClassLoaders. The +// class name parameter (first string) will be given in package.dot.Format. The +// second parameter is the split name, which will just be an empty string if not +// used. +JNI_ZERO_COMPONENT_BUILD_EXPORT void SetClassResolver( + jclass (*resolver)(JNIEnv*, const char*, const char*)); + +// Finds the class named |class_name| and returns it. +// Use this method instead of invoking directly the JNI FindClass method (to +// prevent leaking local references). +// This method triggers a fatal assertion if the class could not be found. +// Use HasClass if you need to check whether the class exists. +JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef +GetClass(JNIEnv* env, const char* class_name, const char* split_name); +JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef GetClass( + JNIEnv* env, + const char* class_name); + +// This class is a wrapper for JNIEnv Get(Static)MethodID. +class JNI_ZERO_COMPONENT_BUILD_EXPORT MethodID { + public: + enum Type { + TYPE_STATIC, + TYPE_INSTANCE, + }; + + // Returns the method ID for the method with the specified name and signature. + // This method triggers a fatal assertion if the method could not be found. + template + static jmethodID Get(JNIEnv* env, + jclass clazz, + const char* method_name, + const char* jni_signature); + + // The caller is responsible to zero-initialize |atomic_method_id|. + // It's fine to simultaneously call this on multiple threads referencing the + // same |atomic_method_id|. + template + static jmethodID LazyGet(JNIEnv* env, + jclass clazz, + const char* method_name, + const char* jni_signature, + std::atomic* atomic_method_id); +}; +} // namespace jni_zero + +#endif // JNI_ZERO_JNI_METHODS_H diff --git a/naiveproxy/src/third_party/jni_zero/jni_registration_generator.py b/naiveproxy/src/third_party/jni_zero/jni_registration_generator.py index 500f59c595..b159bd2674 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_registration_generator.py +++ b/naiveproxy/src/third_party/jni_zero/jni_registration_generator.py @@ -151,16 +151,15 @@ def _Generate(options, native_sources, java_sources, priority_java_sources): set(combined_dict['PROXY_NATIVE_METHOD_ARRAY'].split('},\n'))) combined_dict['PROXY_NATIVE_METHOD_ARRAY'] = '},\n'.join( p for p in proxy_native_array_list if p != '') + '}' - signature_to_cases = collections.defaultdict(list) + signature_to_cpp_calls = collections.defaultdict(list) for d in dicts: - for signature, cases in d['SIGNATURE_TO_CASES'].items(): - signature_to_cases[signature].extend(cases) - combined_dict[ - 'FORWARDING_PROXY_METHODS'] = _InsertMultiplexingSwitchNumbers( - signature_to_cases, combined_dict['FORWARDING_PROXY_METHODS'], - short_gen_jni_class) + for signature, cases in d['SIGNATURE_TO_CPP_CALLS'].items(): + signature_to_cpp_calls[signature].extend(cases) + combined_dict['FORWARDING_PROXY_METHODS'] = _InsertMultiplexingSwitchCases( + signature_to_cpp_calls, combined_dict['FORWARDING_PROXY_METHODS'], + short_gen_jni_class) combined_dict['FORWARDING_CALLS'] = _AddForwardingCalls( - signature_to_cases, short_gen_jni_class) + signature_to_cpp_calls, short_gen_jni_class) if options.header_path: combined_dict['NAMESPACE'] = options.namespace or '' @@ -256,26 +255,24 @@ def _GenerateStubs(natives): return final_string -def _InsertMultiplexingSwitchNumbers(signature_to_cases, java_functions_string, - short_gen_jni_class): +def _InsertMultiplexingSwitchCases(signature_to_cpp_calls, + java_functions_string, short_gen_jni_class): switch_case_method_name_re = re.compile('return (\w+)\(') java_function_call_re = re.compile('public static \S+ (\w+)\(') method_to_switch_num = {} - for signature, cases in sorted(signature_to_cases.items()): + for signature, cases in sorted(signature_to_cpp_calls.items()): for i, case in enumerate(cases): - assert _SWITCH_NUM_TO_BE_INERSERTED_LATER_TOKEN in case method_name = switch_case_method_name_re.search(case).group(1) method_to_switch_num[method_name] = i - cases[i] = case.replace(_SWITCH_NUM_TO_BE_INERSERTED_LATER_TOKEN, str(i)) + if len(cases) > 1: + cases[i] = f''' case {i}: + {case}''' swaps = {} for match in java_function_call_re.finditer(java_functions_string): - unhashed_java_name = match.group(1) - is_test_only = jni_generator.NameIsTestOnly(unhashed_java_name) - hashed = proxy.create_hashed_method_name(unhashed_java_name, is_test_only) - fully_qualified_hash = f'{short_gen_jni_class.full_name_with_slashes}/{hashed}' - cpp_hash_name = 'Java_' + common.escape_class_name(fully_qualified_hash) - switch_num = method_to_switch_num[cpp_hash_name] + java_name = match.group(1) + cpp_full_name = 'Java_' + common.escape_class_name(java_name) + switch_num = method_to_switch_num[cpp_full_name] replace_location = java_functions_string.find( _SWITCH_NUM_TO_BE_INERSERTED_LATER_TOKEN, match.end()) swaps[replace_location] = switch_num @@ -292,45 +289,51 @@ def _InsertMultiplexingSwitchNumbers(signature_to_cases, java_functions_string, return new_java_functions_string - - -def _AddForwardingCalls(signature_to_cases, short_gen_jni_class): - template = string.Template(""" -JNI_BOUNDARY_EXPORT ${RETURN} Java_${CLASS_NAME}_${PROXY_SIGNATURE}( +def _AddForwardingCalls(signature_to_cpp_calls, short_gen_jni_class): + fn_def_template = string.Template(""" +JNI_BOUNDARY_EXPORT ${RETURN} Java_${PROXY_FN_NAME}( JNIEnv* env, jclass jcaller, ${PARAMS_IN_STUB}) { - switch (switch_num) { - ${CASES} - default: - JNI_ZERO_ILOG("${CLASS_NAME}_${PROXY_SIGNATURE} was called with an \ -invalid switch number: %d", switch_num); - JNI_ZERO_CHECK(false); - return${DEFAULT_RETURN}; - } +${FN_BODY} }""") + switch_body_template = string.Template(""" + switch (switch_num) { +${CASES} + default: + JNI_ZERO_DCHECK(false); + return${DEFAULT_RETURN}; + }""") - switch_statements = [] - for signature, cases in sorted(signature_to_cases.items()): - params_in_stub = _GetJavaToNativeParamsList(signature.param_types) - switch_statements.append( - template.substitute({ - 'RETURN': - signature.return_type.to_cpp(), - 'CLASS_NAME': - common.escape_class_name( - short_gen_jni_class.full_name_with_slashes), - 'PROXY_SIGNATURE': - common.escape_class_name(_GetMultiplexProxyName(signature)), - 'PARAMS_IN_STUB': - params_in_stub, - 'CASES': - ''.join(cases), - 'DEFAULT_RETURN': - '' if signature.return_type.is_void() else ' {}', + forwarding_function_definitons = [] + for signature, cases in sorted(signature_to_cpp_calls.items()): + param_strings, _ = _GetMultiplexingParamsList(signature.param_types) + java_class_name = common.escape_class_name( + short_gen_jni_class.full_name_with_slashes) + java_function_name = common.escape_class_name( + _GetMultiplexProxyName(signature)) + proxy_function_name = f'{java_class_name}_{java_function_name}' + all_cases = '\n'.join(cases) + if len(cases) > 1: + fn_body = switch_body_template.substitute({ + 'PROXY_FN_NAME': + proxy_function_name, + 'CASES': + all_cases, + 'DEFAULT_RETURN': + '' if signature.return_type.is_void() else ' {}', + }) + else: + fn_body = f' {all_cases}' + forwarding_function_definitons.append( + fn_def_template.substitute({ + 'RETURN': signature.return_type.to_cpp(), + 'PROXY_FN_NAME': proxy_function_name, + 'PARAMS_IN_STUB': ', '.join(param_strings), + 'FN_BODY': fn_body, })) - return ''.join(s for s in switch_statements) + return ''.join(s for s in forwarding_function_definitons) def _SetProxyRegistrationFields(options, gen_jni_class, registration_dict): @@ -500,20 +503,22 @@ ${EPILOGUE} return template.substitute(registration_dict) -def _GetJavaToNativeParamsList(param_types): - if not param_types: - return 'jint switch_num' - +def _GetMultiplexingParamsList(param_types, java_types=False): + switch_type = 'int' if java_types else 'jint' # Parameters are named after their type, with a unique number per parameter # type to make sure the names are unique, even within the same types. params_type_count = collections.defaultdict(int) - params_in_stub = [] + params_with_type = [f'{switch_type} switch_num'] + param_names = ['switch_num'] for t in param_types: - params_type_count[t] += 1 - params_in_stub.append('%s %s_param%d' % (t.to_cpp(), t.to_java().replace( - '[]', '_array').lower(), params_type_count[t])) + typename = t.java_type.to_java() if java_types else t.to_cpp() + params_type_count[typename] += 1 + typename_cleaned = typename.replace('[]', '_array').lower() + param_name = f'{typename_cleaned}_param{params_type_count[typename]}' + param_names.append(param_name) + params_with_type.append(f'{typename} {param_name}') - return 'jint switch_num, ' + ', '.join(params_in_stub) + return params_with_type, param_names def _GetRegistrationFunctionName(fully_qualified_class): @@ -521,6 +526,14 @@ def _GetRegistrationFunctionName(fully_qualified_class): return 'RegisterNative_' + common.escape_class_name(fully_qualified_class) +def _CreateMultiplexedSignature(proxy_signature): + """Inserts an int parameter as the first parameter.""" + switch_param = java_types.JavaParam(java_types.INT, '_method_idx') + return java_types.JavaSignature.from_params( + proxy_signature.return_type, + java_types.JavaParamList((switch_param, ) + proxy_signature.param_list)) + + class DictionaryGenerator(object): """Generates an inline header file for JNI registration.""" def __init__(self, jni_obj, options): @@ -563,7 +576,7 @@ class DictionaryGenerator(object): for native in self.proxy_natives)) if self.options.enable_jni_multiplexing: - self._AddCases() + self._GetMuxingCalls() if self.options.use_proxy_hash or self.options.enable_jni_multiplexing: self.registration_dict['FORWARDING_PROXY_METHODS'] = ('\n'.join( @@ -644,12 +657,10 @@ ${KMETHODS} if self.options.enable_jni_multiplexing: class_name = common.escape_class_name( self.gen_jni_class.full_name_with_slashes) - name = _GetMultiplexProxyName(native.proxy_signature) - proxy_signature = common.escape_class_name(name) - stub_name = 'Java_' + class_name + '_' + proxy_signature - - multipliexed_signature = java_types.JavaSignature( - native.return_type, (java_types.INT, ), None) + sorted_signature = native.proxy_signature.with_params_reordered() + name = _GetMultiplexProxyName(sorted_signature) + stub_name = f'Java_{class_name}_' + common.escape_class_name(name) + multipliexed_signature = _CreateMultiplexedSignature(sorted_signature) jni_descriptor = multipliexed_signature.to_descriptor() elif self.options.use_proxy_hash: name = native.hashed_proxy_name @@ -734,45 +745,26 @@ ${NATIVES}\ """) return self._SubstituteNativeMethods(java_classes_with_natives, template) - def _AddCases(self): + def _GetMuxingCalls(self): # Switch cases are grouped together by the same proxy signatures. - template = string.Template(""" - case ${SWITCH_NUM}: - return ${STUB_NAME}(env, jcaller${PARAMS}); - """) + template = string.Template('return ${STUB_NAME}(env, jcaller${PARAMS});') - signature_to_cases = collections.defaultdict(list) + signature_to_cpp_calls = collections.defaultdict(list) for native in self.proxy_natives: - signature = native.proxy_signature - params = _GetParamsListForMultiplex(native.proxy_params, with_types=False) + _, param_names = _GetMultiplexingParamsList(native.proxy_param_types) + param_string = ', '.join(param_names[1:]) + if param_string: + param_string = ', ' + param_string values = { - 'SWITCH_NUM': _SWITCH_NUM_TO_BE_INERSERTED_LATER_TOKEN, # We are forced to call the generated stub instead of the impl because # the impl is not guaranteed to have a globally unique name. 'STUB_NAME': self.jni_obj.GetStubName(native), - 'PARAMS': params, + 'PARAMS': param_string, } - signature_to_cases[signature].append(template.substitute(values)) + signature = native.proxy_signature.with_params_reordered() + signature_to_cpp_calls[signature].append(template.substitute(values)) - self.registration_dict['SIGNATURE_TO_CASES'] = signature_to_cases - - -def _GetParamsListForMultiplex(params, *, with_types): - if not params: - return '' - - # Parameters are named after their type, with a unique number per parameter - # type to make sure the names are unique, even within the same types. - params_type_count = collections.defaultdict(int) - sb = [] - for p in params: - type_str = p.java_type.to_java() - params_type_count[type_str] += 1 - param_type = f'{type_str} ' if with_types else '' - sb.append('%s%s_param%d' % (param_type, type_str.replace( - '[]', '_array').lower(), params_type_count[type_str])) - - return ', ' + ', '.join(sb) + self.registration_dict['SIGNATURE_TO_CPP_CALLS'] = signature_to_cpp_calls _MULTIPLEXED_CHAR_BY_TYPE = { @@ -822,16 +814,18 @@ def _MakeForwardingProxy(options, gen_jni_class, proxy_native): ${MAYBE_RETURN}${PROXY_CLASS}.${PROXY_METHOD_NAME}(${PARAM_NAMES}); }""") - param_names = proxy_native.proxy_params.to_call_str() if options.enable_jni_multiplexing: + sorted_signature = proxy_native.proxy_signature.with_params_reordered() + param_names = sorted_signature.param_list.to_call_str() if not param_names: param_names = _SWITCH_NUM_TO_BE_INERSERTED_LATER_TOKEN else: param_names = _SWITCH_NUM_TO_BE_INERSERTED_LATER_TOKEN + ', ' + param_names - proxy_method_name = _GetMultiplexProxyName(proxy_native.proxy_signature) + proxy_method_name = _GetMultiplexProxyName(sorted_signature) else: proxy_method_name = proxy_native.hashed_proxy_name + param_names = proxy_native.proxy_params.to_call_str() return template.substitute({ 'RETURN_TYPE': @@ -863,9 +857,11 @@ def _MakeProxySignature(options, proxy_native): signature_template = string.Template(native_method_line) alt_name = None - proxy_name = _GetMultiplexProxyName(proxy_native.proxy_signature) - params_with_types = 'int switch_num' + _GetParamsListForMultiplex( - proxy_native.proxy_params, with_types=True) + sorted_signature = proxy_native.proxy_signature.with_params_reordered() + proxy_name = _GetMultiplexProxyName(sorted_signature) + params_with_types_list, _ = _GetMultiplexingParamsList( + sorted_signature.param_list, java_types=True) + params_with_types = ', '.join(params_with_types_list) elif options.use_proxy_hash: signature_template = string.Template(""" // Original name: ${ALT_NAME}""" + native_method_line) @@ -929,8 +925,8 @@ def main(parser, args): parser.error('--remove-uncalled-methods requires --native-sources-file.') if args.priority_java_sources_file and not args.enable_jni_multiplexing: parser.error('--priority-java-sources is only for multiplexing.') - if args.enable_jni_multiplexing and not args.use_proxy_hash: - parser.error('--enable-jni-multiplexing requires --use_proxy_hash.') + if args.enable_jni_multiplexing and args.use_proxy_hash: + parser.error('--enable-jni-multiplexing cannot work with --use-proxy-hash.') java_sources = _ParseSourceList(args.java_sources_file) if args.native_sources_file: diff --git a/naiveproxy/src/third_party/jni_zero/jni_wrappers.h b/naiveproxy/src/third_party/jni_zero/jni_wrappers.h new file mode 100644 index 0000000000..d763606b4e --- /dev/null +++ b/naiveproxy/src/third_party/jni_zero/jni_wrappers.h @@ -0,0 +1,238 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef JNI_ZERO_JNI_WRAPPERS_H_ +#define JNI_ZERO_JNI_WRAPPERS_H_ + +#include + +#include "third_party/jni_zero/java_refs.h" +#include "third_party/jni_zero/logging.h" + +// Wrapper used to receive int when calling Java from native. +// The wrapper disallows automatic conversion of long to int. +// This is to avoid a common anti-pattern where a Java int is used +// to receive a native pointer. Please use a Java long to receive +// native pointers, so that the code works on both 32-bit and 64-bit +// platforms. Note the wrapper allows other lossy conversions into +// jint that could be consider anti-patterns, such as from size_t. + +// Checking is only done in debugging builds. + +#ifdef NDEBUG + +typedef jint JniIntWrapper; + +// This inline is sufficiently trivial that it does not change the +// final code generated by g++. +inline jint as_jint(JniIntWrapper wrapper) { + return wrapper; +} + +#else + +class JniIntWrapper { + public: + JniIntWrapper() : i_(0) {} + JniIntWrapper(int i) : i_(i) {} + JniIntWrapper(const JniIntWrapper& ji) : i_(ji.i_) {} + template + JniIntWrapper(const T& t) : i_(t) {} + jint as_jint() const { return i_; } + + private: + // If you get an "is private" error at the line below it is because you used + // an implicit conversion to convert a long to an int when calling Java. + // We disallow this, as a common anti-pattern allows converting a native + // pointer (intptr_t) to a Java int. Please use a Java long to represent + // a native pointer. If you want a lossy conversion, please use an + // explicit conversion in your C++ code. Note an error is only seen when + // compiling on a 64-bit platform, as intptr_t is indistinguishable from + // int on 32-bit platforms. + JniIntWrapper(long); + jint i_; +}; + +inline jint as_jint(const JniIntWrapper& wrapper) { + return wrapper.as_jint(); +} + +#endif // NDEBUG + +namespace jni_zero { +// Wrapper for a jobjectArray which supports input iteration, allowing Java +// arrays to be iterated over with a range-based for loop, or used with +// functions that accept input iterators. +// +// The iterator returns each object in the array in turn, wrapped in a +// ScopedJavaLocalRef. T will usually be jobject, but if you know that the +// array contains a more specific type (such as jstring) you can use that +// instead. This does not check the type at runtime! +// +// The wrapper holds a local reference to the array and only queries the size of +// the array once, so must only be used as a stack-based object from the current +// thread. +// +// Note that this does *not* update the contents of the array if you mutate the +// returned ScopedJavaLocalRef. +template +class JavaObjectArrayReader { + public: + class iterator { + public: + // We can only be an input iterator, as all richer iterator types must + // implement the multipass guarantee (always returning the same object for + // the same iterator position), which is not practical when returning + // temporary objects. + using iterator_category = std::input_iterator_tag; + + using difference_type = ptrdiff_t; + using value_type = ScopedJavaLocalRef; + + // It doesn't make sense to return a reference type as the iterator creates + // temporary wrapper objects when dereferenced. Fortunately, it's not + // required that input iterators actually use references, and defining it + // as value_type is valid. + using reference = value_type; + + // This exists to make operator-> work as expected: its return value must + // resolve to an actual pointer (otherwise the compiler just keeps calling + // operator-> on the return value until it does), so we need an extra level + // of indirection. This is sometimes called an "arrow proxy" or similar, and + // this version is adapted from base/value_iterators.h. + class pointer { + public: + explicit pointer(const reference& ref) : ref_(ref) {} + pointer(const pointer& ptr) = default; + pointer& operator=(const pointer& ptr) = delete; + reference* operator->() { return &ref_; } + + private: + reference ref_; + }; + + iterator(const iterator&) = default; + ~iterator() = default; + + iterator& operator=(const iterator&) = default; + + bool operator==(const iterator& other) const { + JNI_ZERO_DCHECK(reader_ == other.reader_); + return i_ == other.i_; + } + + bool operator!=(const iterator& other) const { + JNI_ZERO_DCHECK(reader_ == other.reader_); + return i_ != other.i_; + } + + reference operator*() const { + JNI_ZERO_DCHECK(i_ < reader_->size_); + // JNIEnv functions return unowned local references; take ownership with + // Adopt so that ~ScopedJavaLocalRef will release it automatically later. + return value_type::Adopt( + reader_->array_.env_, + static_cast(reader_->array_.env_->GetObjectArrayElement( + reader_->array_.obj(), i_))); + } + + pointer operator->() const { return pointer(operator*()); } + + iterator& operator++() { + JNI_ZERO_DCHECK(i_ < reader_->size_); + ++i_; + return *this; + } + + iterator operator++(int) { + iterator old = *this; + ++*this; + return old; + } + + private: + iterator(const JavaObjectArrayReader* reader, jsize i) + : reader_(reader), i_(i) {} + const JavaObjectArrayReader* reader_; + jsize i_; + + friend JavaObjectArrayReader; + }; + + JavaObjectArrayReader(const JavaRef& array) : array_(array) { + size_ = array_.env_->GetArrayLength(array_.obj()); + } + + // Copy constructor to allow returning it from JavaRef::ReadElements(). + JavaObjectArrayReader(const JavaObjectArrayReader& other) = default; + + // Assignment operator for consistency with copy constructor. + JavaObjectArrayReader& operator=(const JavaObjectArrayReader& other) = + default; + + // Allow move constructor and assignment since this owns a local ref. + JavaObjectArrayReader(JavaObjectArrayReader&& other) = default; + JavaObjectArrayReader& operator=(JavaObjectArrayReader&& other) = default; + + bool empty() const { return size_ == 0; } + + jsize size() const { return size_; } + + iterator begin() const { return iterator(this, 0); } + + iterator end() const { return iterator(this, size_); } + + private: + ScopedJavaLocalRef array_; + jsize size_; + + friend iterator; +}; + +// Use as: @JniType("jni_zero::ByteArrayView") byte[]. +// +// This requests a direct pointer to the array data rather than a copy of it, +// so can be more efficient than std::vector for large arrays. +// +// This helper needs to release the array via its destructor, and as a result +// has more binary size overhead than using std::vector. As such, you +// should prefer std::vector for small arrays. +// +// Callers must ensure that the passed in array reference outlives this wrapper +// (always the case when used with @JniType). +class ByteArrayView { + public: + ByteArrayView(JNIEnv* env, jbyteArray array) + : env_(env), + array_(array), + length_(env->GetArrayLength(array)), + bytes_(env->GetByteArrayElements(array, nullptr)) {} + + ~ByteArrayView() { + env_->ReleaseByteArrayElements(array_, bytes_, JNI_ABORT); + } + + ByteArrayView(const ByteArrayView&) = delete; + ByteArrayView(ByteArrayView&& other) = delete; + ByteArrayView& operator=(const ByteArrayView&) = delete; + + size_t size() const { return static_cast(length_); } + bool empty() const { return length_ == 0; } + const jbyte* bytes() const { return bytes_; } + const uint8_t* data() const { return reinterpret_cast(bytes_); } + const char* chars() const { return reinterpret_cast(bytes_); } + std::string_view string_view() const { + return std::string_view(chars(), size()); + } + + private: + JNIEnv* env_; + jbyteArray array_; + jsize length_; + jbyte* bytes_; +}; + +} // namespace jni_zero + +#endif // JNI_ZERO_JNI_WRAPPERS_H_ diff --git a/naiveproxy/src/third_party/jni_zero/jni_zero.cc b/naiveproxy/src/third_party/jni_zero/jni_zero.cc index 599dd3f089..90876bc652 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_zero.cc +++ b/naiveproxy/src/third_party/jni_zero/jni_zero.cc @@ -6,12 +6,12 @@ #include +#include "third_party/jni_zero/jni_methods.h" #include "third_party/jni_zero/jni_zero_internal.h" #include "third_party/jni_zero/logging.h" namespace jni_zero { namespace { -const int kDefaultLocalFrameCapacity = 16; // Until we fully migrate base's jni_android, we will maintain a copy of this // global here and will have base set this variable when it sets its own. JavaVM* g_jvm = nullptr; @@ -59,77 +59,9 @@ jclass GetSystemClassGlobalRef(JNIEnv* env, const char* class_name) { jclass g_object_class = nullptr; jclass g_string_class = nullptr; - -ScopedJavaLocalFrame::ScopedJavaLocalFrame(JNIEnv* env) : env_(env) { - int failed = env_->PushLocalFrame(kDefaultLocalFrameCapacity); - JNI_ZERO_DCHECK(!failed); -} - -ScopedJavaLocalFrame::ScopedJavaLocalFrame(JNIEnv* env, int capacity) - : env_(env) { - int failed = env_->PushLocalFrame(capacity); - JNI_ZERO_DCHECK(!failed); -} - -ScopedJavaLocalFrame::~ScopedJavaLocalFrame() { - env_->PopLocalFrame(nullptr); -} - -#if JNI_ZERO_DCHECK_IS_ON() -// This constructor is inlined when DCHECKs are disabled; don't add anything -// else here. -JavaRef::JavaRef(JNIEnv* env, jobject obj) : obj_(obj) { - if (obj) { - JNI_ZERO_DCHECK(env && env->GetObjectRefType(obj) == JNILocalRefType); - } -} -#endif - -JNIEnv* JavaRef::SetNewLocalRef(JNIEnv* env, jobject obj) { - if (!env) { - env = AttachCurrentThread(); - } else { - JNI_ZERO_DCHECK(env == AttachCurrentThread()); // Is |env| on correct thread. - } - if (obj) { - obj = env->NewLocalRef(obj); - } - if (obj_) { - env->DeleteLocalRef(obj_); - } - obj_ = obj; - return env; -} - -void JavaRef::SetNewGlobalRef(JNIEnv* env, jobject obj) { - if (!env) { - env = AttachCurrentThread(); - } else { - JNI_ZERO_DCHECK(env == AttachCurrentThread()); // Is |env| on correct thread. - } - if (obj) { - obj = env->NewGlobalRef(obj); - } - if (obj_) { - env->DeleteGlobalRef(obj_); - } - obj_ = obj; -} - -void JavaRef::ResetLocalRef(JNIEnv* env) { - if (obj_) { - JNI_ZERO_DCHECK(env == AttachCurrentThread()); // Is |env| on correct thread. - env->DeleteLocalRef(obj_); - obj_ = nullptr; - } -} - -void JavaRef::ResetGlobalRef() { - if (obj_) { - AttachCurrentThread()->DeleteGlobalRef(obj_); - obj_ = nullptr; - } -} +LeakedJavaGlobalRef g_empty_string = nullptr; +LeakedJavaGlobalRef g_empty_list = nullptr; +LeakedJavaGlobalRef g_empty_map = nullptr; JNIEnv* AttachCurrentThread() { JNI_ZERO_DCHECK(g_jvm); @@ -189,7 +121,8 @@ void InitVM(JavaVM* vm) { JNIEnv* env = AttachCurrentThread(); g_object_class = GetSystemClassGlobalRef(env, "java/lang/Object"); g_string_class = GetSystemClassGlobalRef(env, "java/lang/String"); - CheckException(env); + g_empty_string.Reset( + env, ScopedJavaLocalRef(env, env->NewString(nullptr, 0))); } void DisableJvmForTesting() { @@ -229,6 +162,7 @@ void CheckException(JNIEnv* env) { if (g_exception_handler_callback) { return g_exception_handler_callback(env); } + env->ExceptionDescribe(); JNI_ZERO_FLOG("jni_zero crashing due to uncaught Java exception"); } diff --git a/naiveproxy/src/third_party/jni_zero/jni_zero.gni b/naiveproxy/src/third_party/jni_zero/jni_zero.gni index 9bcfacaedf..d3e4c5eb8b 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_zero.gni +++ b/naiveproxy/src/third_party/jni_zero/jni_zero.gni @@ -11,15 +11,24 @@ if (is_android) { _JAVAP_PATH = "//third_party/jdk/current/bin/javap" declare_args() { - # Enables JNI multiplexing to reduce JNI native methods overhead. - # When we want to "enable" this, we can use this line instead/ - # allow_jni_multiplexing = !is_java_debug && is_component_build == false - allow_jni_multiplexing = false - - # Use hashed symbol names to reduce JNI symbol overhead. - use_hashed_jni_names = !is_java_debug + # Enables JNI multiplexing to reduce JNI native methods overhead. Component + # build must be false as most components are not visible to the base component + # which dispatches out to every component. Disabling for cronet, at least for + # now, since it needs to be able to convert GN to Soong build rules, which we + # don't want to do right now. use_hashed_jni_names is required until we can + # determine method names (and namespaces) of all java->native functions. + enable_jni_multiplexing = + !is_java_debug && !is_component_build && !is_cronet_build } +declare_args() { + # Use hashed symbol names to reduce JNI symbol overhead when not multiplexing. + use_hashed_jni_names = !enable_jni_multiplexing && !is_java_debug +} + +assert(!use_hashed_jni_names || !enable_jni_multiplexing, + "Multiplexing requires that hashed names be disabled.") + # Use a dedicated include dir so that files can #include headers from other # toolchains without affecting non-JNI #includes. if (target_os == "android") { @@ -134,10 +143,8 @@ template("generate_jni_registration") { walk_keys = [ "java_walk_keys" ] } - _enable_jni_multiplexing = defined(invoker.enable_jni_multiplexing) && - invoker.enable_jni_multiplexing if (defined(invoker.priority_java_targets)) { - if (_enable_jni_multiplexing) { + if (enable_jni_multiplexing) { # This is intended for WebView, so we can only look at Java sources. This # is becuase WebView's java is a strict subset of it's native, so we don't # need to take the intersection of it's native and java. @@ -188,13 +195,6 @@ template("generate_jni_registration") { ] } - if (defined(_priority_java_sources_list)) { - args += [ - "--priority-java-sources-file", - rebase_path(_priority_java_sources_list, root_build_dir), - ] - } - if (defined(invoker.include_testonly)) { _include_testonly = invoker.include_testonly } else { @@ -225,16 +225,7 @@ template("generate_jni_registration") { args += [ "--add-stubs-for-missing-native" ] } - _manual_jni_registration = defined(invoker.manual_jni_registration) && - invoker.manual_jni_registration - if (_manual_jni_registration) { - args += [ "--manual-jni-registration" ] - } - if (_enable_jni_multiplexing) { - args += [ "--enable-jni-multiplexing" ] - } - - if (_manual_jni_registration || _enable_jni_multiplexing) { + if (defined(invoker.cpp_codegen_output)) { _cpp_codegen_output = invoker.cpp_codegen_output outputs += [ _cpp_codegen_output ] args += [ @@ -247,6 +238,19 @@ template("generate_jni_registration") { # generated C++ file. "//third_party/jni_zero:jni_include_dir", ] + if (defined(invoker.manual_jni_registration) && + invoker.manual_jni_registration) { + args += [ "--manual-jni-registration" ] + } + if (enable_jni_multiplexing) { + args += [ "--enable-jni-multiplexing" ] + } + if (defined(_priority_java_sources_list)) { + args += [ + "--priority-java-sources-file", + rebase_path(_priority_java_sources_list, root_build_dir), + ] + } } if (defined(invoker.namespace)) { @@ -283,7 +287,6 @@ template("generate_jni_impl") { # Depending on the action name to avoid cross-toolchain native deps. public_deps = [ ":$_jni_zero_action_target_name($default_toolchain)" ] - deps = [ "//third_party/jni_zero" ] metadata = { shared_libraries_barrier = [] } @@ -358,8 +361,7 @@ template("generate_jni_impl") { args += [ "--use-proxy-hash" ] } - if (defined(invoker.enable_jni_multiplexing) && - invoker.enable_jni_multiplexing) { + if (enable_jni_multiplexing) { args += [ "--enable-jni-multiplexing" ] } if (defined(invoker.namespace)) { @@ -416,6 +418,7 @@ template("generate_jni_impl") { if (_from_source) { java_library("${_final_target_name}_java") { forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + requires_android = true srcjars = [ _srcjar_output, _placeholder_srcjar_output, @@ -428,7 +431,7 @@ template("generate_jni_impl") { prevent_excluded_classes_from_classpath = true deps = [ ":$_jni_zero_action_target_name", - "//third_party/jni_zero:jni_zero_java", + "//third_party/jni_zero:gendeps_java", ] } } @@ -473,12 +476,9 @@ template("generate_jni") { forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) metadata = { - jni_source_files = sources - - # This field is only used by Cronet team during the translation - # of the GN build targets to Soong modules. From a pure - # GN perspective, it is unused. - jni_source_files_abs = get_path_info(sources, "abspath") + # keep as abspath as this is used by cronet team + # to convert JNI registration targets from GN to BP (GN2BP). + jni_source_files = get_path_info(sources, "abspath") } } } @@ -530,7 +530,7 @@ template("native_with_jni") { _manual_jni_registration = defined(invoker.manual_jni_registration) && invoker.manual_jni_registration _needs_cpp_codegen = - (_manual_jni_registration || allow_jni_multiplexing) && + (_manual_jni_registration || enable_jni_multiplexing) && !(defined(invoker.collect_inputs_only) && invoker.collect_inputs_only) _needs_native_dep = _enable_underlying_native && _needs_cpp_codegen if ((_needs_cpp_codegen && current_toolchain == default_toolchain) || @@ -572,9 +572,6 @@ template("native_with_jni") { } } if (_needs_cpp_codegen) { - if (allow_jni_multiplexing) { - enable_jni_multiplexing = true - } cpp_codegen_output = _registration_cpp_codegen_output } forward_variables_from(invoker, diff --git a/naiveproxy/src/third_party/jni_zero/jni_zero.h b/naiveproxy/src/third_party/jni_zero/jni_zero.h index a9a1fcf2cd..a04c654ff4 100644 --- a/naiveproxy/src/third_party/jni_zero/jni_zero.h +++ b/naiveproxy/src/third_party/jni_zero/jni_zero.h @@ -7,825 +7,25 @@ #include -#include -#include -#include -#include - +#include "third_party/jni_zero/java_refs.h" #include "third_party/jni_zero/jni_export.h" +#include "third_party/jni_zero/jni_methods.h" +#include "third_party/jni_zero/jni_wrappers.h" #include "third_party/jni_zero/logging.h" - -#if defined(__i386__) -// Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on -// x86 - use force_align_arg_pointer to realign the stack at the JNI -// boundary. crbug.com/655248 -#define JNI_BOUNDARY_EXPORT \ - extern "C" __attribute__((visibility("default"), force_align_arg_pointer)) -#else -#define JNI_BOUNDARY_EXPORT extern "C" __attribute__((visibility("default"))) -#endif - -#if defined(__cpp_concepts) && __cpp_concepts >= 201907L -#define JNI_ZERO_ENABLE_TYPE_CONVERSIONS 1 -#else -#define JNI_ZERO_ENABLE_TYPE_CONVERSIONS 0 -#endif - -// Wrapper used to receive int when calling Java from native. -// The wrapper disallows automatic conversion of long to int. -// This is to avoid a common anti-pattern where a Java int is used -// to receive a native pointer. Please use a Java long to receive -// native pointers, so that the code works on both 32-bit and 64-bit -// platforms. Note the wrapper allows other lossy conversions into -// jint that could be consider anti-patterns, such as from size_t. - -// Checking is only done in debugging builds. - -#ifdef NDEBUG - -typedef jint JniIntWrapper; - -// This inline is sufficiently trivial that it does not change the -// final code generated by g++. -inline jint as_jint(JniIntWrapper wrapper) { - return wrapper; -} - -#else - -class JniIntWrapper { - public: - JniIntWrapper() : i_(0) {} - JniIntWrapper(int i) : i_(i) {} - JniIntWrapper(const JniIntWrapper& ji) : i_(ji.i_) {} - template - JniIntWrapper(const T& t) : i_(t) {} - jint as_jint() const { return i_; } - - private: - // If you get an "is private" error at the line below it is because you used - // an implicit conversion to convert a long to an int when calling Java. - // We disallow this, as a common anti-pattern allows converting a native - // pointer (intptr_t) to a Java int. Please use a Java long to represent - // a native pointer. If you want a lossy conversion, please use an - // explicit conversion in your C++ code. Note an error is only seen when - // compiling on a 64-bit platform, as intptr_t is indistinguishable from - // int on 32-bit platforms. - JniIntWrapper(long); - jint i_; -}; - -inline jint as_jint(const JniIntWrapper& wrapper) { - return wrapper.as_jint(); -} - -#endif // NDEBUG +#include "third_party/jni_zero/type_conversions.h" namespace jni_zero { + // Commonly needed jclasses: extern JNI_ZERO_COMPONENT_BUILD_EXPORT jclass g_object_class; extern JNI_ZERO_COMPONENT_BUILD_EXPORT jclass g_string_class; - -// Creates a new local reference frame, in which at least a given number of -// local references can be created. Note that local references already created -// in previous local frames are still valid in the current local frame. -class JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalFrame { - public: - explicit ScopedJavaLocalFrame(JNIEnv* env); - ScopedJavaLocalFrame(JNIEnv* env, int capacity); - - ScopedJavaLocalFrame(const ScopedJavaLocalFrame&) = delete; - ScopedJavaLocalFrame& operator=(const ScopedJavaLocalFrame&) = delete; - - ~ScopedJavaLocalFrame(); - - private: - // This class is only good for use on the thread it was created on so - // it's safe to cache the non-threadsafe JNIEnv* inside this object. - JNIEnv* env_; -}; - -// Forward declare the generic java reference template class. -template -class JavaRef; - -// Template specialization of JavaRef, which acts as the base class for all -// other JavaRef<> template types. This allows you to e.g. pass -// ScopedJavaLocalRef into a function taking const JavaRef& -template <> -class JNI_ZERO_COMPONENT_BUILD_EXPORT JavaRef { - public: - // Initializes a null reference. - constexpr JavaRef() {} - - // Allow nullptr to be converted to JavaRef. This avoids having to declare an - // empty JavaRef just to pass null to a function, and makes C++ "nullptr" and - // Java "null" equivalent. - constexpr JavaRef(std::nullptr_t) {} - - JavaRef(const JavaRef&) = delete; - JavaRef& operator=(const JavaRef&) = delete; - - // Public to allow destruction of null JavaRef objects. - ~JavaRef() {} - - // TODO(torne): maybe rename this to get() for consistency with unique_ptr - // once there's fewer unnecessary uses of it in the codebase. - jobject obj() const { return obj_; } - - explicit operator bool() const { return obj_ != nullptr; } - - // Deprecated. Just use bool conversion. - // TODO(torne): replace usage and remove this. - bool is_null() const { return obj_ == nullptr; } - - protected: -// Takes ownership of the |obj| reference passed; requires it to be a local -// reference type. -#if JNI_ZERO_DCHECK_IS_ON() - // Implementation contains a DCHECK; implement out-of-line when DCHECK_IS_ON. - JavaRef(JNIEnv* env, jobject obj); -#else - JavaRef(JNIEnv* env, jobject obj) : obj_(obj) {} -#endif - - // Used for move semantics. obj_ must have been released first if non-null. - void steal(JavaRef&& other) { - obj_ = other.obj_; - other.obj_ = nullptr; - } - - // The following are implementation detail convenience methods, for - // use by the sub-classes. - JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj); - void SetNewGlobalRef(JNIEnv* env, jobject obj); - void ResetLocalRef(JNIEnv* env); - void ResetGlobalRef(); - - jobject ReleaseInternal() { - jobject obj = obj_; - obj_ = nullptr; - return obj; - } - - private: - jobject obj_ = nullptr; -}; - -// Forward declare the object array reader for the convenience function. -template -class JavaObjectArrayReader; - -// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful -// for allowing functions to accept a reference without having to mandate -// whether it is a local or global type. -template -class JavaRef : public JavaRef { - public: - constexpr JavaRef() {} - constexpr JavaRef(std::nullptr_t) {} - - JavaRef(const JavaRef&) = delete; - JavaRef& operator=(const JavaRef&) = delete; - - ~JavaRef() {} - - T obj() const { return static_cast(JavaRef::obj()); } - - // Get a JavaObjectArrayReader for the array pointed to by this reference. - // Only defined for JavaRef. - // You must pass the type of the array elements (usually jobject) as the - // template parameter. - template >> - JavaObjectArrayReader ReadElements() const { - return JavaObjectArrayReader(*this); - } - - protected: - JavaRef(JNIEnv* env, T obj) : JavaRef(env, obj) {} -}; - -// Holds a local reference to a JNI method parameter. -// Method parameters should not be deleted, and so this class exists purely to -// wrap them as a JavaRef in the JNI binding generator. Do not create -// instances manually. -template -class JavaParamRef : public JavaRef { - public: - // Assumes that |obj| is a parameter passed to a JNI method from Java. - // Does not assume ownership as parameters should not be deleted. - JavaParamRef(JNIEnv* env, T obj) : JavaRef(env, obj) {} - - // Allow nullptr to be converted to JavaParamRef. Some unit tests call JNI - // methods directly from C++ and pass null for objects which are not actually - // used by the implementation (e.g. the caller object); allow this to keep - // working. - JavaParamRef(std::nullptr_t) {} - - JavaParamRef(const JavaParamRef&) = delete; - JavaParamRef& operator=(const JavaParamRef&) = delete; - - ~JavaParamRef() {} - - // TODO(torne): remove this cast once we're using JavaRef consistently. - // http://crbug.com/506850 - operator T() const { return JavaRef::obj(); } -}; - -// Holds a local reference to a Java object. The local reference is scoped -// to the lifetime of this object. -// Instances of this class may hold onto any JNIEnv passed into it until -// destroyed. Therefore, since a JNIEnv is only suitable for use on a single -// thread, objects of this class must be created, used, and destroyed, on a -// single thread. -// Therefore, this class should only be used as a stack-based object and from a -// single thread. If you wish to have the reference outlive the current -// callstack (e.g. as a class member) or you wish to pass it across threads, -// use a ScopedJavaGlobalRef instead. -template -class ScopedJavaLocalRef : public JavaRef { - public: - // Take ownership of a bare jobject. This does not create a new reference. - // This should only be used by JNI helper functions, or in cases where code - // must call JNIEnv methods directly. - static ScopedJavaLocalRef Adopt(JNIEnv* env, T obj) { - return ScopedJavaLocalRef(env, obj); - } - - constexpr ScopedJavaLocalRef() {} - constexpr ScopedJavaLocalRef(std::nullptr_t) {} - - // Copy constructor. This is required in addition to the copy conversion - // constructor below. - ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) { - JavaRef::SetNewLocalRef(env_, other.obj()); - } - - // Copy conversion constructor. - template >> - ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) { - JavaRef::SetNewLocalRef(env_, other.obj()); - } - - // Move constructor. This is required in addition to the move conversion - // constructor below. - ScopedJavaLocalRef(ScopedJavaLocalRef&& other) : env_(other.env_) { - JavaRef::steal(std::move(other)); - } - - // Move conversion constructor. - template >> - ScopedJavaLocalRef(ScopedJavaLocalRef&& other) : env_(other.env_) { - JavaRef::steal(std::move(other)); - } - - // Constructor for other JavaRef types. - explicit ScopedJavaLocalRef(const JavaRef& other) { Reset(other); } - - ScopedJavaLocalRef(JNIEnv* env, const JavaRef& other) { Reset(other); } - - // Assumes that |obj| is a local reference to a Java object and takes - // ownership of this local reference. - // TODO(torne): make legitimate uses call Adopt() instead, and make this - // private. - ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef(env, obj), env_(env) {} - - ~ScopedJavaLocalRef() { Reset(); } - - // Null assignment, for disambiguation. - ScopedJavaLocalRef& operator=(std::nullptr_t) { - Reset(); - return *this; - } - - // Copy assignment. - ScopedJavaLocalRef& operator=(const ScopedJavaLocalRef& other) { - Reset(other); - return *this; - } - - // Copy conversion assignment. - template >> - ScopedJavaLocalRef& operator=(const ScopedJavaLocalRef& other) { - Reset(other); - return *this; - } - - // Move assignment. - template >> - ScopedJavaLocalRef& operator=(ScopedJavaLocalRef&& other) { - env_ = other.env_; - Reset(); - JavaRef::steal(std::move(other)); - return *this; - } - - // Assignment for other JavaRef types. - ScopedJavaLocalRef& operator=(const JavaRef& other) { - Reset(other); - return *this; - } - - void Reset() { JavaRef::ResetLocalRef(env_); } - - template >> - void Reset(const ScopedJavaLocalRef& other) { - // We can copy over env_ here as |other| instance must be from the same - // thread as |this| local ref. (See class comment for multi-threading - // limitations, and alternatives). - env_ = JavaRef::SetNewLocalRef(other.env_, other.obj()); - } - - void Reset(const JavaRef& other) { - // If |env_| was not yet set (is still null) it will be attached to the - // current thread in SetNewLocalRef(). - env_ = JavaRef::SetNewLocalRef(env_, other.obj()); - } - - // Releases the local reference to the caller. The caller *must* delete the - // local reference when it is done with it. Note that calling a Java method - // is *not* a transfer of ownership and Release() should not be used. - T Release() { return static_cast(JavaRef::ReleaseInternal()); } - - private: - // This class is only good for use on the thread it was created on so - // it's safe to cache the non-threadsafe JNIEnv* inside this object. - JNIEnv* env_ = nullptr; - - // Prevent ScopedJavaLocalRef(JNIEnv*, T obj) from being used to take - // ownership of a JavaParamRef's underlying object - parameters are not - // allowed to be deleted and so should not be owned by ScopedJavaLocalRef. - // TODO(torne): this can be removed once JavaParamRef no longer has an - // implicit conversion back to T. - ScopedJavaLocalRef(JNIEnv* env, const JavaParamRef& other); - - // Friend required to get env_ from conversions. - template - friend class ScopedJavaLocalRef; - - // Avoids JavaObjectArrayReader having to accept and store its own env. - template - friend class JavaObjectArrayReader; -}; - -// Holds a global reference to a Java object. The global reference is scoped -// to the lifetime of this object. This class does not hold onto any JNIEnv* -// passed to it, hence it is safe to use across threads (within the constraints -// imposed by the underlying Java object that it references). -template -class ScopedJavaGlobalRef : public JavaRef { - public: - constexpr ScopedJavaGlobalRef() {} - constexpr ScopedJavaGlobalRef(std::nullptr_t) {} - - // Copy constructor. This is required in addition to the copy conversion - // constructor below. - ScopedJavaGlobalRef(const ScopedJavaGlobalRef& other) { Reset(other); } - - // Copy conversion constructor. - template >> - ScopedJavaGlobalRef(const ScopedJavaGlobalRef& other) { - Reset(other); - } - - // Move constructor. This is required in addition to the move conversion - // constructor below. - ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other) { - JavaRef::steal(std::move(other)); - } - - // Move conversion constructor. - template >> - ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other) { - JavaRef::steal(std::move(other)); - } - - // Conversion constructor for other JavaRef types. - explicit ScopedJavaGlobalRef(const JavaRef& other) { Reset(other); } - - ScopedJavaGlobalRef(JNIEnv* env, const JavaRef& other) { - JavaRef::SetNewGlobalRef(env, other.obj()); - } - - // Create a new global reference to the object. - // Deprecated. Don't use bare jobjects; use a JavaRef as the input. - ScopedJavaGlobalRef(JNIEnv* env, T obj) { Reset(env, obj); } - - ~ScopedJavaGlobalRef() { Reset(); } - - // Null assignment, for disambiguation. - ScopedJavaGlobalRef& operator=(std::nullptr_t) { - Reset(); - return *this; - } - - // Copy assignment. - ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef& other) { - Reset(other); - return *this; - } - - // Copy conversion assignment. - template >> - ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef& other) { - Reset(other); - return *this; - } - - // Move assignment. - template >> - ScopedJavaGlobalRef& operator=(ScopedJavaGlobalRef&& other) { - Reset(); - JavaRef::steal(std::move(other)); - return *this; - } - - // Assignment for other JavaRef types. - ScopedJavaGlobalRef& operator=(const JavaRef& other) { - Reset(other); - return *this; - } - - void Reset() { JavaRef::ResetGlobalRef(); } - - template >> - void Reset(const ScopedJavaGlobalRef& other) { - Reset(nullptr, other.obj()); - } - - void Reset(const JavaRef& other) { Reset(nullptr, other.obj()); } - - // Deprecated. You can just use Reset(const JavaRef&). - void Reset(JNIEnv* env, const JavaParamRef& other) { - Reset(env, other.obj()); - } - - // Deprecated. Don't use bare jobjects; use a JavaRef as the input. - void Reset(JNIEnv* env, T obj) { JavaRef::SetNewGlobalRef(env, obj); } - - // Releases the global reference to the caller. The caller *must* delete the - // global reference when it is done with it. Note that calling a Java method - // is *not* a transfer of ownership and Release() should not be used. - T Release() { return static_cast(JavaRef::ReleaseInternal()); } -}; - -// Wrapper for a jobjectArray which supports input iteration, allowing Java -// arrays to be iterated over with a range-based for loop, or used with -// functions that accept input iterators. -// -// The iterator returns each object in the array in turn, wrapped in a -// ScopedJavaLocalRef. T will usually be jobject, but if you know that the -// array contains a more specific type (such as jstring) you can use that -// instead. This does not check the type at runtime! -// -// The wrapper holds a local reference to the array and only queries the size of -// the array once, so must only be used as a stack-based object from the current -// thread. -// -// Note that this does *not* update the contents of the array if you mutate the -// returned ScopedJavaLocalRef. -template -class JavaObjectArrayReader { - public: - class iterator { - public: - // We can only be an input iterator, as all richer iterator types must - // implement the multipass guarantee (always returning the same object for - // the same iterator position), which is not practical when returning - // temporary objects. - using iterator_category = std::input_iterator_tag; - - using difference_type = ptrdiff_t; - using value_type = ScopedJavaLocalRef; - - // It doesn't make sense to return a reference type as the iterator creates - // temporary wrapper objects when dereferenced. Fortunately, it's not - // required that input iterators actually use references, and defining it - // as value_type is valid. - using reference = value_type; - - // This exists to make operator-> work as expected: its return value must - // resolve to an actual pointer (otherwise the compiler just keeps calling - // operator-> on the return value until it does), so we need an extra level - // of indirection. This is sometimes called an "arrow proxy" or similar, and - // this version is adapted from base/value_iterators.h. - class pointer { - public: - explicit pointer(const reference& ref) : ref_(ref) {} - pointer(const pointer& ptr) = default; - pointer& operator=(const pointer& ptr) = delete; - reference* operator->() { return &ref_; } - - private: - reference ref_; - }; - - iterator(const iterator&) = default; - ~iterator() = default; - - iterator& operator=(const iterator&) = default; - - bool operator==(const iterator& other) const { - JNI_ZERO_DCHECK(reader_ == other.reader_); - return i_ == other.i_; - } - - bool operator!=(const iterator& other) const { - JNI_ZERO_DCHECK(reader_ == other.reader_); - return i_ != other.i_; - } - - reference operator*() const { - JNI_ZERO_DCHECK(i_ < reader_->size_); - // JNIEnv functions return unowned local references; take ownership with - // Adopt so that ~ScopedJavaLocalRef will release it automatically later. - return value_type::Adopt( - reader_->array_.env_, - static_cast(reader_->array_.env_->GetObjectArrayElement( - reader_->array_.obj(), i_))); - } - - pointer operator->() const { return pointer(operator*()); } - - iterator& operator++() { - JNI_ZERO_DCHECK(i_ < reader_->size_); - ++i_; - return *this; - } - - iterator operator++(int) { - iterator old = *this; - ++*this; - return old; - } - - private: - iterator(const JavaObjectArrayReader* reader, jsize i) - : reader_(reader), i_(i) {} - const JavaObjectArrayReader* reader_; - jsize i_; - - friend JavaObjectArrayReader; - }; - - JavaObjectArrayReader(const JavaRef& array) : array_(array) { - size_ = array_.env_->GetArrayLength(array_.obj()); - } - - // Copy constructor to allow returning it from JavaRef::ReadElements(). - JavaObjectArrayReader(const JavaObjectArrayReader& other) = default; - - // Assignment operator for consistency with copy constructor. - JavaObjectArrayReader& operator=(const JavaObjectArrayReader& other) = - default; - - // Allow move constructor and assignment since this owns a local ref. - JavaObjectArrayReader(JavaObjectArrayReader&& other) = default; - JavaObjectArrayReader& operator=(JavaObjectArrayReader&& other) = default; - - bool empty() const { return size_ == 0; } - - jsize size() const { return size_; } - - iterator begin() const { return iterator(this, 0); } - - iterator end() const { return iterator(this, size_); } - - private: - ScopedJavaLocalRef array_; - jsize size_; - - friend iterator; -}; - -// Use as: @JniType("jni_zero::ByteArrayView") byte[]. -// -// This requests a direct pointer to the array data rather than a copy of it, -// so can be more efficient than std::vector for large arrays. -// -// This helper needs to release the array via its destructor, and as a result -// has more binary size overhead than using std::vector. As such, you -// should prefer std::vector for small arrays. -// -// Callers must ensure that the passed in array reference outlives this wrapper -// (always the case when used with @JniType). -class ByteArrayView { - public: - ByteArrayView(JNIEnv* env, jbyteArray array) - : env_(env), - array_(array), - length_(env->GetArrayLength(array)), - bytes_(env->GetByteArrayElements(array, nullptr)) {} - - ~ByteArrayView() { - env_->ReleaseByteArrayElements(array_, bytes_, JNI_ABORT); - } - - ByteArrayView(const ByteArrayView&) = delete; - ByteArrayView(ByteArrayView&& other) = delete; - ByteArrayView& operator=(const ByteArrayView&) = delete; - - size_t size() const { return static_cast(length_); } - bool empty() const { return length_ == 0; } - const jbyte* bytes() const { return bytes_; } - const uint8_t* data() const { return reinterpret_cast(bytes_); } - const char* chars() const { return reinterpret_cast(bytes_); } - std::string_view string_view() const { - return std::string_view(chars(), size()); - } - - private: - JNIEnv* env_; - jbyteArray array_; - jsize length_; - jbyte* bytes_; -}; - -// Attaches the current thread to the VM (if necessary) and return the JNIEnv*. -JNI_ZERO_COMPONENT_BUILD_EXPORT JNIEnv* AttachCurrentThread(); - -// Same to AttachCurrentThread except that thread name will be set to -// |thread_name| if it is the first call. Otherwise, thread_name won't be -// changed. AttachCurrentThread() doesn't regard underlying platform thread -// name, but just resets it to "Thread-???". This function should be called -// right after new thread is created if it is important to keep thread name. -JNI_ZERO_COMPONENT_BUILD_EXPORT JNIEnv* AttachCurrentThreadWithName( - const std::string& thread_name); - -// Detaches the current thread from VM if it is attached. -JNI_ZERO_COMPONENT_BUILD_EXPORT void DetachFromVM(); - -// Initializes the global JVM. -JNI_ZERO_COMPONENT_BUILD_EXPORT void InitVM(JavaVM* vm); - -// Returns true if the global JVM has been initialized. -JNI_ZERO_COMPONENT_BUILD_EXPORT bool IsVMInitialized(); - -// Returns the global JVM, or nullptr if it has not been initialized. -JNI_ZERO_COMPONENT_BUILD_EXPORT JavaVM* GetVM(); - -// Do not allow any future native->java calls. -// This is necessary in gtest DEATH_TESTS to prevent -// GetJavaStackTraceIfPresent() from accessing a defunct JVM (due to fork()). -// https://crbug.com/1484834 -JNI_ZERO_COMPONENT_BUILD_EXPORT void DisableJvmForTesting(); - -JNI_ZERO_COMPONENT_BUILD_EXPORT void SetExceptionHandler( - void (*callback)(JNIEnv*)); - -// Returns true if an exception is pending in the provided JNIEnv*. -JNI_ZERO_COMPONENT_BUILD_EXPORT bool HasException(JNIEnv* env); - -// If an exception is pending in the provided JNIEnv*, this function clears it -// and returns true. -JNI_ZERO_COMPONENT_BUILD_EXPORT bool ClearException(JNIEnv* env); - -// If there's any pending exception, this function will call the set exception -// handler, or if none are set, it will fatally LOG. -JNI_ZERO_COMPONENT_BUILD_EXPORT void CheckException(JNIEnv* env); - -// Sets a function to call instead of just using JNIEnv.FindClass. Useful for -// chrome's "splits" which need to be resolved in special ClassLoaders. The -// class name parameter (first string) will be given in package.dot.Format. The -// second parameter is the split name, which will just be an empty string if not -// used. -JNI_ZERO_COMPONENT_BUILD_EXPORT void SetClassResolver( - jclass (*resolver)(JNIEnv*, const char*, const char*)); - -// Finds the class named |class_name| and returns it. -// Use this method instead of invoking directly the JNI FindClass method (to -// prevent leaking local references). -// This method triggers a fatal assertion if the class could not be found. -// Use HasClass if you need to check whether the class exists. -JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef -GetClass(JNIEnv* env, const char* class_name, const char* split_name); -JNI_ZERO_COMPONENT_BUILD_EXPORT ScopedJavaLocalRef GetClass( - JNIEnv* env, - const char* class_name); - -#if JNI_ZERO_ENABLE_TYPE_CONVERSIONS -#define JNI_ZERO_CONVERSION_FAILED_MSG(name) \ - "Failed to find a " name \ - " specialization for the given type. Did you forget to include the " \ - "header file that declares it?\n" \ - "If this error originates from a generated _jni.h file, make sure that " \ - "the header that declares the specialization is #included before the " \ - "_jni.h one." -#else -#define JNI_ZERO_CONVERSION_FAILED_MSG(x) "Use of @JniType requires C++20." -#endif - -template -inline T FromJniType(JNIEnv* env, const JavaRef& obj) { - static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("FromJniType")); -} - -template -inline ScopedJavaLocalRef ToJniType(JNIEnv* env, const T& obj) { - static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniType")); -} - -// Allow conversions using pointers by wrapping non-pointer conversions. -// Cannot live in default_conversions.h because we want code to be able to -// specialize it. -template -inline ScopedJavaLocalRef ToJniType(JNIEnv* env, T* value) { - if (!value) { - return nullptr; - } - return ToJniType(env, *value); -} - -#if JNI_ZERO_ENABLE_TYPE_CONVERSIONS -#undef JNI_ZERO_CONVERSION_FAILED_MSG -#define JNI_ZERO_CONVERSION_FAILED_MSG(name) \ - "Failed to find a " name \ - " specialization for the given type.\n" \ - "If this error is from a generated _jni.h file, ensure that the type " \ - "conforms to the container concepts defined in " \ - "jni_zero/default_conversions.h.\n" \ - "If this error is from a non-generated call, ensure that there " \ - "exists an #include for jni_zero/default_conversions.h." -#endif - -// Convert from an stl container to a Java array. Uses ToJniType() on each -// element. -template -inline ScopedJavaLocalRef ToJniArray(JNIEnv* env, - const T& obj, - jclass array_class) { - static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniArray")); -} - -// Convert from a Java array to an stl container of primitive types. -template -inline ScopedJavaLocalRef ToJniArray(JNIEnv* env, const T& obj) { - static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniArray")); -} - -// Convert from a Java array to an stl container. Uses FromJniType() on each -// element for non-primitive types. -template -inline T FromJniArray(JNIEnv* env, const JavaRef& obj) { - static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("FromJniArray")); -} - -// Convert from an stl container to a Java List<> by using ToJniType() on each -// element. -template -inline ScopedJavaLocalRef ToJniList(JNIEnv* env, const T& obj) { - static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniList")); -} - -// Convert from a Java Collection<> to an stl container by using FromJniType() -// on each element. -template -inline T FromJniCollection(JNIEnv* env, const JavaRef& obj) { - static_assert(sizeof(T) == 0, - JNI_ZERO_CONVERSION_FAILED_MSG("FromJniCollection")); -} -#undef JNI_ZERO_CONVERSION_FAILED_MSG - -// This class is a wrapper for JNIEnv Get(Static)MethodID. -class JNI_ZERO_COMPONENT_BUILD_EXPORT MethodID { - public: - enum Type { - TYPE_STATIC, - TYPE_INSTANCE, - }; - - // Returns the method ID for the method with the specified name and signature. - // This method triggers a fatal assertion if the method could not be found. - template - static jmethodID Get(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature); - - // The caller is responsible to zero-initialize |atomic_method_id|. - // It's fine to simultaneously call this on multiple threads referencing the - // same |atomic_method_id|. - template - static jmethodID LazyGet(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature, - std::atomic* atomic_method_id); -}; - +// Singletons for empty things. +extern JNI_ZERO_COMPONENT_BUILD_EXPORT LeakedJavaGlobalRef + g_empty_string; +extern JNI_ZERO_COMPONENT_BUILD_EXPORT LeakedJavaGlobalRef + g_empty_list; +extern JNI_ZERO_COMPONENT_BUILD_EXPORT LeakedJavaGlobalRef g_empty_map; } // namespace jni_zero #endif // JNI_ZERO_JNI_ZERO_H_ diff --git a/naiveproxy/src/third_party/jni_zero/parse.py b/naiveproxy/src/third_party/jni_zero/parse.py index 5e2f380296..8d78318da0 100644 --- a/naiveproxy/src/third_party/jni_zero/parse.py +++ b/naiveproxy/src/third_party/jni_zero/parse.py @@ -197,10 +197,13 @@ def _parse_type(type_resolver, value): raise ParseError('Found non-templatized @JniType("std::vector") on ' 'non-array, non-List type: ' + value) + nullable = annotations.get('NonNull', True) + return java_types.JavaType(array_dimensions=array_dimensions, primitive_name=primitive_name, java_class=java_class, - converted_type=converted_type) + converted_type=converted_type, + nullable=nullable) _FINAL_REGEX = re.compile(r'\bfinal\s') @@ -211,7 +214,19 @@ def _parse_param_list(type_resolver, value) -> java_types.JavaParamList: return java_types.EMPTY_PARAM_LIST params = [] value = _FINAL_REGEX.sub('', value) + pending = '' for param_str in value.split(','): + # Combine multiple entries when , is in an annotation. + # E.g.: @JniType("std::map") Map arg0 + if pending: + pending += ',' + param_str + if '"' not in param_str: + continue + param_str = pending + pending = '' + elif param_str.count('"') == 1: + pending = param_str + continue param_str = param_str.strip() param_str, _, param_name = param_str.rpartition(' ') param_str = param_str.rstrip() diff --git a/naiveproxy/src/third_party/jni_zero/sample/BUILD.gn b/naiveproxy/src/third_party/jni_zero/sample/BUILD.gn index bcf8143ad5..f720cc1b30 100644 --- a/naiveproxy/src/third_party/jni_zero/sample/BUILD.gn +++ b/naiveproxy/src/third_party/jni_zero/sample/BUILD.gn @@ -30,7 +30,7 @@ source_set("sample_native_side") { } shared_library_with_jni("libjni_zero_sample") { - if (allow_jni_multiplexing) { + if (enable_jni_multiplexing) { _linker_script = "sample_lib_multiplexing_version_script.txt" } else { _linker_script = "sample_lib_version_script.txt" diff --git a/naiveproxy/src/third_party/jni_zero/test/BUILD.gn b/naiveproxy/src/third_party/jni_zero/test/BUILD.gn index 04822276ad..086623e03a 100644 --- a/naiveproxy/src/third_party/jni_zero/test/BUILD.gn +++ b/naiveproxy/src/third_party/jni_zero/test/BUILD.gn @@ -27,6 +27,7 @@ android_library("test_java") { sources = [ "java/src/org/jni_zero/SampleForAnnotationProcessor.java", "java/src/org/jni_zero/SampleForTests.java", + "java/src/org/jni_zero/SampleUnderSamePackage.java", ] deps = [ diff --git a/naiveproxy/src/third_party/jni_zero/test/integration_tests.py b/naiveproxy/src/third_party/jni_zero/test/integration_tests.py index 21ea94cdf7..0f8cfeee18 100755 --- a/naiveproxy/src/third_party/jni_zero/test/integration_tests.py +++ b/naiveproxy/src/third_party/jni_zero/test/integration_tests.py @@ -217,11 +217,11 @@ class BaseTest(unittest.TestCase): f'{dir_prefix}org/jni_zero/{file_prefix}GEN_JNI.java': f'{golden_name}-Final-GEN_JNI.java.golden', } - if options.use_proxy_hash: + if options.use_proxy_hash or options.enable_jni_multiplexing: name_to_goldens[f'{dir_prefix}J/{file_prefix}N.java'] = ( f'{golden_name}-Final-N.java.golden') header_golden = None - if options.use_proxy_hash or options.manual_jni_registration: + if options.use_proxy_hash or options.manual_jni_registration or options.enable_jni_multiplexing: header_golden = f'{golden_name}-Registration.h.golden' with tempfile.TemporaryDirectory() as tdir: @@ -387,6 +387,14 @@ class Tests(BaseTest): self._TestEndToEndRegistration( ['SampleForAnnotationProcessor.java', 'SampleModule.java'], use_proxy_hash=True, + manual_jni_registration=True, + module_name='module') + + def testModulesWithMultiplexing(self): + self._TestEndToEndRegistration( + ['SampleForAnnotationProcessor.java', 'SampleModule.java'], + enable_jni_multiplexing=True, + manual_jni_registration=True, module_name='module') def testStubRegistration(self): @@ -408,8 +416,7 @@ class Tests(BaseTest): priority_java_files = ['TinySample2.java'] self._TestEndToEndRegistration(input_java_files, priority_java_files=priority_java_files, - enable_jni_multiplexing=True, - use_proxy_hash=True) + enable_jni_multiplexing=True) def testFullStubs(self): self._TestEndToEndRegistration( @@ -417,18 +424,30 @@ class Tests(BaseTest): src_files_for_asserts_and_stubs=['TinySample.java'], add_stubs_for_missing_native=True) - def testForTestingKept(self): + def testForTestingKeptHash(self): input_java_file = 'SampleProxyEdgeCases.java' self._TestEndToEndGeneration([input_java_file], srcjar=True) self._TestEndToEndRegistration([input_java_file], use_proxy_hash=True, include_test_only=True) - def testForTestingRemoved(self): + def testForTestingRemovedHash(self): self._TestEndToEndRegistration(['SampleProxyEdgeCases.java'], use_proxy_hash=True, + include_test_only=False) + + def testForTestingKeptMultiplexing(self): + input_java_file = 'SampleProxyEdgeCases.java' + self._TestEndToEndGeneration([input_java_file], srcjar=True) + self._TestEndToEndRegistration([input_java_file], + enable_jni_multiplexing=True, include_test_only=True) + def testForTestingRemovedMultiplexing(self): + self._TestEndToEndRegistration(['SampleProxyEdgeCases.java'], + enable_jni_multiplexing=True, + include_test_only=False) + def testProxyMocks(self): self._TestEndToEndRegistration(['TinySample.java'], enable_proxy_mocks=True) @@ -447,15 +466,15 @@ class Tests(BaseTest): package_prefix='this.is.a.package.prefix', manual_jni_registration=True) - def testPackagePrefixWithProxyHash(self): + def testPackagePrefixWithMultiplexing(self): self._TestEndToEndRegistration(['SampleForAnnotationProcessor.java'], package_prefix='this.is.a.package.prefix', - use_proxy_hash=True) + enable_jni_multiplexing=True) - def testPackagePrefixWithManualRegistrationWithProxyHash(self): + def testPackagePrefixWithManualRegistrationWithMultiplexing(self): self._TestEndToEndRegistration(['SampleForAnnotationProcessor.java'], package_prefix='this.is.a.package.prefix', - use_proxy_hash=True, + enable_jni_multiplexing=True, manual_jni_registration=True) def testPlaceholdersOverlapping(self): @@ -469,7 +488,7 @@ class Tests(BaseTest): def testMultiplexing(self): self._TestEndToEndRegistration(['SampleForAnnotationProcessor.java'], enable_jni_multiplexing=True, - use_proxy_hash=True) + manual_jni_registration=True) def testParseError_noPackage(self): data = """ diff --git a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleForTests.java b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleForTests.java index c788542d3e..66f1f839b6 100644 --- a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleForTests.java +++ b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleForTests.java @@ -155,10 +155,17 @@ class SampleForTests { @CalledByNative @JniType("std::vector") - Collection listTest1(@JniType("std::vector") List items) { + static Collection listTest1( + @JniType("std::vector") List items) { return Collections.emptyList(); } + @CalledByNative + static @JniType("std::map") Map mapTest1( + @JniType("std::map") Map arg0) { + return arg0; + } + // --------------------------------------------------------------------------------------------- // Java fields which are accessed from C++ code only must be annotated with @AccessedByNative to // prevent them being eliminated when unreferenced code is stripped. @@ -339,7 +346,12 @@ class SampleForTests { Throwable getThrowable(Throwable arg0); // Test Map. - Map getMap(Map arg0); + @JniType("std::map") + Map mapTest2( + @JniType("std::map") Map arg0); + + // Test class under the same package + void classUnderSamePackageTest(SampleUnderSamePackage arg); // Similar to nativeDestroy above, this will cast nativeCPPClass into pointer of CPPClass // type and call its Method member function. Replace "CPPClass" with your particular class diff --git a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleModule.java b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleModule.java index 0a93b0c790..64c4dc5201 100644 --- a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleModule.java +++ b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleModule.java @@ -4,11 +4,10 @@ package org.jni_zero; -import org.jni_zero.NativeMethods; class SampleModule { void test() { - if (SampleForAnnotationProcessorJni.get().bar(1)) { + if (SampleForAnnotationProcessorJni.get().bar(true)) { SampleForAnnotationProcessorJni.get().foo(); } } @@ -16,6 +15,7 @@ class SampleModule { @NativeMethods("module") interface Natives { void foo(); - boolean bar(int a); + + boolean bar(boolean a); } } diff --git a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleUnderSamePackage.java b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleUnderSamePackage.java new file mode 100644 index 0000000000..256260a603 --- /dev/null +++ b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleUnderSamePackage.java @@ -0,0 +1,8 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.jni_zero; + +class SampleUnderSamePackage { +} diff --git a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleUniqueAnnotations.java b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleUniqueAnnotations.java index e8495e070d..c3487e7600 100644 --- a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleUniqueAnnotations.java +++ b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/SampleUniqueAnnotations.java @@ -4,7 +4,11 @@ package org.jni_zero; +import androidx.annotation.NonNull; + class SampleUniqueAnnotations { + public interface Handle {} + // Poorly spaced intentionally private void do_not_match(); @@ -16,6 +20,8 @@ class SampleUniqueAnnotations { void foo(long nativePtr, @JniType("std::string") String arg); int bar(int x, int y); + + void baz(@NonNull Handle handle); } @CalledByNative diff --git a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/TinySample.java b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/TinySample.java index 598ccb85b9..19add017c0 100644 --- a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/TinySample.java +++ b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/TinySample.java @@ -4,12 +4,11 @@ package org.jni_zero; -import org.jni_zero.NativeMethods; - class TinySample { @NativeMethods() interface Natives { - void foo(); - boolean bar(int a); + void foo(Object a, int b); + + boolean bar(int a, Object b); } } diff --git a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/TinySample2.java b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/TinySample2.java index b97e60b179..b8cf968f8a 100644 --- a/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/TinySample2.java +++ b/naiveproxy/src/third_party/jni_zero/test/java/src/org/jni_zero/TinySample2.java @@ -4,11 +4,11 @@ package org.jni_zero; -import org.jni_zero.NativeMethods; - class TinySample2 { @NativeMethods() interface Natives { - void test(); + void test(Object a, int b); + + void test2(int a, Object b); } } diff --git a/naiveproxy/src/third_party/jni_zero/test/sample_for_tests.cc b/naiveproxy/src/third_party/jni_zero/test/sample_for_tests.cc index ad780a1eac..3641a2390d 100644 --- a/naiveproxy/src/third_party/jni_zero/test/sample_for_tests.cc +++ b/naiveproxy/src/third_party/jni_zero/test/sample_for_tests.cc @@ -80,7 +80,7 @@ void CPPClass::IterateAndDoSomethingWithStructB( ScopedJavaLocalRef CPPClass::ReturnAString( JNIEnv* env, const JavaParamRef& caller) { - return ScopedJavaLocalRef(); + return nullptr; } // Static free functions declared and called directly from java. @@ -94,6 +94,10 @@ static jlong JNI_SampleForTests_Init( return static_cast(bytes.size()); } +static void JNI_SampleForTests_ClassUnderSamePackageTest( + JNIEnv*, + const JavaParamRef&) {} + static jdouble JNI_SampleForTests_GetDoubleFunction( JNIEnv*, const JavaParamRef&) { @@ -106,7 +110,7 @@ static jfloat JNI_SampleForTests_GetFloatFunction(JNIEnv*) { static std::vector> JNI_SampleForTests_ListTest2(JNIEnv* env, std::vector& items) { - return Java_SampleForTests_listTest1(env, nullptr, items); + return Java_SampleForTests_listTest1(env, items); } static void JNI_SampleForTests_SetNonPODDatatype(JNIEnv*, @@ -117,37 +121,37 @@ static void JNI_SampleForTests_SetNonPODDatatype(JNIEnv*, static ScopedJavaLocalRef JNI_SampleForTests_GetNonPODDatatype( JNIEnv*, const JavaParamRef&) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForTests_GetNonPODDatatype( JNIEnv*, const JavaParamRef&) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForTests_GetNonPODDatatype( JNIEnv*, const JavaParamRef&) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForTests_GetClass( JNIEnv* env, const JavaParamRef& arg0) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForTests_GetThrowable( JNIEnv* env, const JavaParamRef& arg0) { - return ScopedJavaLocalRef(); + return nullptr; } -static ScopedJavaLocalRef JNI_SampleForTests_GetMap( +static std::map JNI_SampleForTests_MapTest2( JNIEnv* env, - const JavaParamRef& arg0) { - return ScopedJavaLocalRef(); + std::map& arg0) { + return Java_SampleForTests_mapTest1(env, arg0); } static std::vector JNI_SampleForTests_PrimitiveArrays( @@ -242,32 +246,32 @@ static void JNI_SampleForAnnotationProcessor_TestSpecialTypes( static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnThrowable(JNIEnv* env) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnThrowables(JNIEnv* env) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnClass( JNIEnv* env) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnClasses(JNIEnv* env) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnString(JNIEnv* env) { - return {}; + return nullptr; } static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnStrings(JNIEnv* env) { - return {}; + return nullptr; } static std::string JNI_SampleForAnnotationProcessor_ReturnConvertedString( @@ -292,22 +296,22 @@ static std::vector JNI_SampleForAnnotationProcessor_ReturnConvertedInts( static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnStruct(JNIEnv* env) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnStructs(JNIEnv* env) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnObject(JNIEnv* env) { - return ScopedJavaLocalRef(); + return nullptr; } static ScopedJavaLocalRef JNI_SampleForAnnotationProcessor_ReturnObjects(JNIEnv* env) { - return ScopedJavaLocalRef(); + return nullptr; } int main() { diff --git a/naiveproxy/src/third_party/jni_zero/test/sample_for_tests.h b/naiveproxy/src/third_party/jni_zero/test/sample_for_tests.h index 847e098bf3..2fb02fe1b0 100644 --- a/naiveproxy/src/third_party/jni_zero/test/sample_for_tests.h +++ b/naiveproxy/src/third_party/jni_zero/test/sample_for_tests.h @@ -11,26 +11,6 @@ #include #include "third_party/jni_zero/jni_zero.h" -// In case concepts are not defined, have placeholder implementations of array -// conversion functions so that tests compile. -#if !defined(__cpp_concepts) -namespace jni_zero { -template -struct ConvertArray> { - static std::vector FromJniType(JNIEnv* env, - const JavaRef& j_array) { - return {}; - } - - static ScopedJavaLocalRef ToJniType(JNIEnv* env, - const std::vector& vec, - jclass clazz) { - return nullptr; - } -}; -} // namespace jni_zero -#endif // !defined(__cpp_concepts) - namespace jni_zero::tests { enum class MyEnum { diff --git a/naiveproxy/src/third_party/jni_zero/test/stub_conversions.h b/naiveproxy/src/third_party/jni_zero/test/stub_conversions.h index 89e93bc004..e9da49d212 100644 --- a/naiveproxy/src/third_party/jni_zero/test/stub_conversions.h +++ b/naiveproxy/src/third_party/jni_zero/test/stub_conversions.h @@ -5,46 +5,127 @@ #ifndef _JNI_ZERO_STUB_CONVERSIONS_H_ #define _JNI_ZERO_STUB_CONVERSIONS_H_ +#include +#include +#include +#include +#include + #include "third_party/jni_zero/jni_zero.h" +#include "third_party/jni_zero/test/sample_for_tests.h" + +// This file contains empty conversion functions needed by the compile tests. + +#define EMPTY_TYPE_CONVERSIONS(T) \ + template <> \ + T FromJniType(JNIEnv * env, const JavaRef& j_object) { \ + return {}; \ + } \ + template <> \ + ScopedJavaLocalRef ToJniType(JNIEnv * env, const T& input) { \ + return nullptr; \ + } + +#define EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(T) \ + template <> \ + std::vector FromJniArray>( \ + JNIEnv * env, const JavaRef& j_object) { \ + return {}; \ + } \ + template <> \ + ScopedJavaLocalRef ToJniArray>( \ + JNIEnv * env, const std::vector& vec) { \ + return nullptr; \ + } + +#define EMPTY_OBJECT_ARRAY_CONVERSIONS(T) \ + template <> \ + std::vector FromJniArray>( \ + JNIEnv * env, const JavaRef& j_object) { \ + return {}; \ + } \ + template <> \ + ScopedJavaLocalRef ToJniArray>( \ + JNIEnv * env, const std::vector& vec, jclass clazz) { \ + return nullptr; \ + } + +#define EMPTY_LIST_CONVERSIONS(T) \ + template <> \ + ScopedJavaLocalRef ToJniList>( \ + JNIEnv * env, const std::vector& vec) { \ + return nullptr; \ + } + +#define EMPTY_COLLECTION_CONVERSIONS(T) \ + template <> \ + std::vector FromJniCollection>( \ + JNIEnv * env, const JavaRef& j_object) { \ + return {}; \ + } namespace jni_zero { -// "conversion" functions, this file only has to compile not run. +// These conversion functions are normally provided by the embedding app. +EMPTY_TYPE_CONVERSIONS(tests::CPPClass) +EMPTY_TYPE_CONVERSIONS(std::string) +EMPTY_TYPE_CONVERSIONS(std::u16string) +EMPTY_TYPE_CONVERSIONS(std::optional) template <> -tests::CPPClass FromJniType(JNIEnv* env, - const JavaRef& j_obj) { - return {}; -} -template <> -std::string FromJniType(JNIEnv* env, - const JavaRef& input) { - return {}; -} -template <> -ScopedJavaLocalRef ToJniType(JNIEnv* env, - const std::string& input) { - return {}; -} -template <> -std::u16string FromJniType(JNIEnv* env, - const JavaRef& input) { - return {}; -} -template <> -ScopedJavaLocalRef ToJniType( - JNIEnv* env, - const std::u16string& input) { - return {}; -} -template <> -ScopedJavaLocalRef ToJniType(JNIEnv* env, const char* input) { +ScopedJavaLocalRef ToJniType(JNIEnv* env, + const char* input) { return {}; } + template <> tests::CPPClass* FromJniType(JNIEnv* env, const JavaRef& j_obj) { return nullptr; } +// If concepts are unavailable, we need these stubs to replace +// default_conversions.h/cc +#ifndef JNI_ZERO_ENABLE_TYPE_CONVERSIONS +EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(int64_t) +EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(int32_t) +EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(int16_t) +EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(uint16_t) +EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(uint8_t) +EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(float) +EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(double) +EMPTY_PRIMITIVE_ARRAY_CONVERSIONS(bool) + +EMPTY_OBJECT_ARRAY_CONVERSIONS(const char*) +EMPTY_OBJECT_ARRAY_CONVERSIONS(std::string) +EMPTY_OBJECT_ARRAY_CONVERSIONS(ScopedJavaLocalRef) +EMPTY_OBJECT_ARRAY_CONVERSIONS(tests::CPPClass) + +EMPTY_LIST_CONVERSIONS(std::string) +EMPTY_LIST_CONVERSIONS(ScopedJavaLocalRef) + +EMPTY_COLLECTION_CONVERSIONS(std::string) +EMPTY_COLLECTION_CONVERSIONS(ScopedJavaLocalRef) + +template <> +std::map +FromJniType>(JNIEnv* env, + const JavaRef& input) { + return {}; +} +template <> +ScopedJavaLocalRef ToJniType>( + JNIEnv* env, + const std::map& input) { + return {}; +} + +template <> +inline ByteArrayView FromJniArray( + JNIEnv* env, + const JavaRef& j_object) { + return ByteArrayView(env, nullptr); +} +#endif // #ifndef JNI_ZERO_ENABLE_TYPE_CONVERSIONS + } // namespace jni_zero #endif diff --git a/naiveproxy/src/third_party/jni_zero/type_conversions.h b/naiveproxy/src/third_party/jni_zero/type_conversions.h new file mode 100644 index 0000000000..3b0b255db5 --- /dev/null +++ b/naiveproxy/src/third_party/jni_zero/type_conversions.h @@ -0,0 +1,105 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef JNI_ZERO_TYPE_CONVERSIONS_H_ +#define JNI_ZERO_TYPE_CONVERSIONS_H_ + +#include + +#include "third_party/jni_zero/java_refs.h" + +#if defined(__cpp_concepts) && __cpp_concepts >= 201907L +#define JNI_ZERO_ENABLE_TYPE_CONVERSIONS 1 +#else +#define JNI_ZERO_ENABLE_TYPE_CONVERSIONS 0 +#endif + +namespace jni_zero { + +#if JNI_ZERO_ENABLE_TYPE_CONVERSIONS +#define JNI_ZERO_CONVERSION_FAILED_MSG(name) \ + "Failed to find a " name \ + " specialization for the given type. Did you forget to include the " \ + "header file that declares it?\n" \ + "If this error originates from a generated _jni.h file, make sure that " \ + "the header that declares the specialization is #included before the " \ + "_jni.h one." +#else +#define JNI_ZERO_CONVERSION_FAILED_MSG(x) "Use of @JniType requires C++20." +#endif + +template +inline T FromJniType(JNIEnv* env, const JavaRef& obj) { + static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("FromJniType")); +} + +template +inline ScopedJavaLocalRef ToJniType(JNIEnv* env, const T& obj) { + static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniType")); +} + +// Allow conversions using pointers by wrapping non-pointer conversions. +// Cannot live in default_conversions.h because we want code to be able to +// specialize it. +template +inline ScopedJavaLocalRef ToJniType(JNIEnv* env, T* value) { + if (!value) { + return nullptr; + } + return ToJniType(env, *value); +} + +#if JNI_ZERO_ENABLE_TYPE_CONVERSIONS +#undef JNI_ZERO_CONVERSION_FAILED_MSG +#define JNI_ZERO_CONVERSION_FAILED_MSG(name) \ + "Failed to find a " name \ + " specialization for the given type.\n" \ + "If this error is from a generated _jni.h file, ensure that the type " \ + "conforms to the container concepts defined in " \ + "jni_zero/default_conversions.h.\n" \ + "If this error is from a non-generated call, ensure that there " \ + "exists an #include for jni_zero/default_conversions.h." +#endif + +// Convert from an stl container to a Java array. Uses ToJniType() on each +// element. +template +inline ScopedJavaLocalRef ToJniArray(JNIEnv* env, + const T& obj, + jclass array_class) { + static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniArray")); +} + +// Convert from a Java array to an stl container of primitive types. +template +inline ScopedJavaLocalRef ToJniArray(JNIEnv* env, const T& obj) { + static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniArray")); +} + +// Convert from a Java array to an stl container. Uses FromJniType() on each +// element for non-primitive types. +template +inline T FromJniArray(JNIEnv* env, const JavaRef& obj) { + static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("FromJniArray")); +} + +// Convert from an stl container to a Java List<> by using ToJniType() on each +// element. +template +inline ScopedJavaLocalRef ToJniList(JNIEnv* env, const T& obj) { + static_assert(sizeof(T) == 0, JNI_ZERO_CONVERSION_FAILED_MSG("ToJniList")); +} + +// Convert from a Java Collection<> to an stl container by using FromJniType() +// on each element. +template +inline T FromJniCollection(JNIEnv* env, const JavaRef& obj) { + static_assert(sizeof(T) == 0, + JNI_ZERO_CONVERSION_FAILED_MSG("FromJniCollection")); +} +#undef JNI_ZERO_CONVERSION_FAILED_MSG + +} // namespace jni_zero + +#endif // JNI_ZERO_TYPE_CONVERSIONS_H_ diff --git a/naiveproxy/src/third_party/libc++/src/.clang-format b/naiveproxy/src/third_party/libc++/src/.clang-format index 39ae1322ff..871920f15b 100644 --- a/naiveproxy/src/third_party/libc++/src/.clang-format +++ b/naiveproxy/src/third_party/libc++/src/.clang-format @@ -24,6 +24,7 @@ AttributeMacros: [ '_LIBCPP_CONSTEXPR_SINCE_CXX23', '_LIBCPP_CONSTEXPR', '_LIBCPP_CONSTINIT', + '_LIBCPP_DEPRECATED_ATOMIC_SYNC', '_LIBCPP_DEPRECATED_IN_CXX11', '_LIBCPP_DEPRECATED_IN_CXX14', '_LIBCPP_DEPRECATED_IN_CXX17', @@ -43,7 +44,6 @@ AttributeMacros: [ '_LIBCPP_NO_SANITIZE', '_LIBCPP_NO_UNIQUE_ADDRESS', '_LIBCPP_NOALIAS', - '_LIBCPP_NODISCARD_EXT', '_LIBCPP_NODISCARD', '_LIBCPP_NORETURN', '_LIBCPP_OVERRIDABLE_FUNC_VIS', diff --git a/naiveproxy/src/third_party/libc++/src/.clang-tidy b/naiveproxy/src/third_party/libc++/src/.clang-tidy index ec7cab9b87..f986e2100c 100644 --- a/naiveproxy/src/third_party/libc++/src/.clang-tidy +++ b/naiveproxy/src/third_party/libc++/src/.clang-tidy @@ -17,6 +17,7 @@ Checks: > modernize-redundant-void-arg, modernize-use-nullptr, modernize-use-override, + modernize-use-equals-delete, readability-duplicate-include, readability-identifier-naming, @@ -57,8 +58,12 @@ CheckOptions: value: _ - key: readability-identifier-naming.TemplateParameterIgnoredRegexp value: (.*\:auto|expr-type) # This is https://llvm.org/PR56464 - - key: readability-identifier-naming.ValueTemplateParameterIgnoredRegexp # TODO: enforce naming of variable parameters - value: .* + - key: readability-identifier-naming.ValueTemplateParameterCase + value: CamelCase + - key: readability-identifier-naming.ValueTemplateParameterPrefix + value: _ + - key: readability-identifier-naming.ValueTemplateParameterIgnoredRegexp + value: (__[a-z_]|_[A-Z]).* # TODO: Converge on a single style for value template parameters # TODO: investigate these checks # bugprone-branch-clone, @@ -68,7 +73,6 @@ CheckOptions: # modernize-use-bool-literals, # modernize-use-default-member-init, # modernize-use-equals-default, -# modernize-use-equals-delete, # portability-restrict-system-includes, # readability-function-cognitive-complexity, # readability-implicit-bool-conversion, diff --git a/naiveproxy/src/third_party/libc++/src/CMakeLists.txt b/naiveproxy/src/third_party/libc++/src/CMakeLists.txt index e565c47c76..190a97db94 100644 --- a/naiveproxy/src/third_party/libc++/src/CMakeLists.txt +++ b/naiveproxy/src/third_party/libc++/src/CMakeLists.txt @@ -5,6 +5,7 @@ # Setup Project #=============================================================================== cmake_minimum_required(VERSION 3.20.0) +set(LLVM_SUBPROJECT_TITLE "libc++") set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") @@ -121,9 +122,8 @@ option(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS on definitions in a shared library. By default, we assume that we're not building libc++ for any specific vendor, and we disable those annotations. Vendors wishing to provide compile-time errors when using features unavailable on some version of - the shared library they shipped should turn this on and see `include/__availability` + the shared library they shipped should turn this on and see `include/__configuration/availability.h` for more details." OFF) -option(LIBCXX_ENABLE_CLANG_TIDY "Whether to compile and run clang-tidy checks" OFF) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(LIBCXX_DEFAULT_TEST_CONFIG "llvm-libc++-shared-gcc.cfg.in") @@ -179,7 +179,7 @@ set(LIBCXX_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING option(LIBCXX_INSTALL_HEADERS "Install the libc++ headers." ON) option(LIBCXX_INSTALL_LIBRARY "Install the libc++ library." ON) option(LIBCXX_INSTALL_MODULES - "Install the libc++ C++20 module source files (experimental)." OFF + "Install the libc++ C++20 module source files (experimental)." ON ) cmake_dependent_option(LIBCXX_INSTALL_STATIC_LIBRARY "Install the static libc++ library." ON @@ -301,9 +301,9 @@ option(LIBCXX_HAS_EXTERNAL_THREAD_API This option may only be set to ON when LIBCXX_ENABLE_THREADS=ON." OFF) if (LIBCXX_ENABLE_THREADS) - set(LIBCXX_PSTL_CPU_BACKEND "std_thread" CACHE STRING "Which PSTL CPU backend to use") + set(LIBCXX_PSTL_BACKEND "std_thread" CACHE STRING "Which PSTL backend to use") else() - set(LIBCXX_PSTL_CPU_BACKEND "serial" CACHE STRING "Which PSTL CPU backend to use") + set(LIBCXX_PSTL_BACKEND "serial" CACHE STRING "Which PSTL backend to use") endif() # Misc options ---------------------------------------------------------------- @@ -433,18 +433,19 @@ set(LIBCXX_SHARED_OUTPUT_NAME "c++" CACHE STRING "Output name for the shared lib set(LIBCXX_STATIC_OUTPUT_NAME "c++" CACHE STRING "Output name for the static libc++ runtime library.") if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) - set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) + set(LIBCXX_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE}) + if(LIBCXX_LIBDIR_SUBDIR) + string(APPEND LIBCXX_TARGET_SUBDIR /${LIBCXX_LIBDIR_SUBDIR}) + endif() + set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LIBCXX_TARGET_SUBDIR}) set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1") set(LIBCXX_GENERATED_MODULE_DIR "${LLVM_BINARY_DIR}/modules/c++/v1") - set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1") - set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING + set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LIBCXX_TARGET_SUBDIR}/c++/v1") + set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LIBCXX_TARGET_SUBDIR} CACHE STRING "Path where built libc++ libraries should be installed.") - set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1" CACHE STRING + set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${LIBCXX_TARGET_SUBDIR}/c++/v1" CACHE STRING "Path where target-specific libc++ headers should be installed.") - if(LIBCXX_LIBDIR_SUBDIR) - string(APPEND LIBCXX_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR}) - string(APPEND LIBCXX_INSTALL_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR}) - endif() + unset(LIBCXX_TARGET_SUBDIR) else() if(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) @@ -552,6 +553,10 @@ function(cxx_add_basic_build_flags target) target_add_compile_flags_if_supported(${target} PRIVATE -fvisibility=hidden) endif() + # Build with -fsized-deallocation, which is default in recent versions of Clang. + # TODO(LLVM 21): This can be dropped once we only support Clang >= 19. + target_add_compile_flags_if_supported(${target} PRIVATE -fsized-deallocation) + # Let the library headers know they are currently being used to build the # library. target_compile_definitions(${target} PRIVATE -D_LIBCPP_BUILDING_LIBRARY) @@ -779,8 +784,8 @@ config_define_if_not(LIBCXX_ENABLE_WIDE_CHARACTERS _LIBCPP_HAS_NO_WIDE_CHARACTER config_define_if_not(LIBCXX_ENABLE_TIME_ZONE_DATABASE _LIBCPP_HAS_NO_TIME_ZONE_DATABASE) config_define_if_not(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) -# TODO(LLVM 19): Produce a deprecation warning. if (LIBCXX_ENABLE_ASSERTIONS) + message(DEPRECATION "LIBCXX_ENABLE_ASSERTIONS is deprecated and will be removed in LLVM 20. Please use LIBCXX_HARDENING_MODE instead.") set(LIBCXX_HARDENING_MODE "extensive") endif() if (LIBCXX_HARDENING_MODE STREQUAL "none") @@ -793,14 +798,14 @@ elseif (LIBCXX_HARDENING_MODE STREQUAL "debug") config_define(8 _LIBCPP_HARDENING_MODE_DEFAULT) endif() -if (LIBCXX_PSTL_CPU_BACKEND STREQUAL "serial") - config_define(1 _LIBCPP_PSTL_CPU_BACKEND_SERIAL) -elseif(LIBCXX_PSTL_CPU_BACKEND STREQUAL "std_thread") - config_define(1 _LIBCPP_PSTL_CPU_BACKEND_THREAD) -elseif(LIBCXX_PSTL_CPU_BACKEND STREQUAL "libdispatch") - config_define(1 _LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) +if (LIBCXX_PSTL_BACKEND STREQUAL "serial") + config_define(1 _LIBCPP_PSTL_BACKEND_SERIAL) +elseif(LIBCXX_PSTL_BACKEND STREQUAL "std_thread") + config_define(1 _LIBCPP_PSTL_BACKEND_STD_THREAD) +elseif(LIBCXX_PSTL_BACKEND STREQUAL "libdispatch") + config_define(1 _LIBCPP_PSTL_BACKEND_LIBDISPATCH) else() - message(FATAL_ERROR "LIBCXX_PSTL_CPU_BACKEND is set to ${LIBCXX_PSTL_CPU_BACKEND}, which is not a valid backend. + message(FATAL_ERROR "LIBCXX_PSTL_BACKEND is set to ${LIBCXX_PSTL_BACKEND}, which is not a valid backend. Valid backends are: serial, std_thread and libdispatch") endif() @@ -856,19 +861,14 @@ endfunction() #=============================================================================== # Setup Source Code And Tests #=============================================================================== +add_custom_target(cxx-test-depends + COMMENT "Build dependencies required to run the libc++ test suite.") + add_subdirectory(include) add_subdirectory(src) add_subdirectory(utils) add_subdirectory(modules) -set(LIBCXX_TEST_DEPS "cxx_experimental") - -if (LIBCXX_ENABLE_CLANG_TIDY) - list(APPEND LIBCXX_TEST_DEPS cxx-tidy) -endif() - -list(APPEND LIBCXX_TEST_DEPS generate-cxx-modules) - if (LIBCXX_INCLUDE_BENCHMARKS) add_subdirectory(benchmarks) endif() diff --git a/naiveproxy/src/third_party/libc++/src/benchmarks/CMakeLists.txt b/naiveproxy/src/third_party/libc++/src/benchmarks/CMakeLists.txt index 928238c1ac..2101f9c717 100644 --- a/naiveproxy/src/third_party/libc++/src/benchmarks/CMakeLists.txt +++ b/naiveproxy/src/third_party/libc++/src/benchmarks/CMakeLists.txt @@ -122,7 +122,7 @@ endif() add_library( cxx-benchmarks-flags-libcxx INTERFACE) target_link_libraries( cxx-benchmarks-flags-libcxx INTERFACE cxx-benchmarks-flags) target_compile_options(cxx-benchmarks-flags-libcxx INTERFACE ${SANITIZER_FLAGS} -Wno-user-defined-literals -Wno-suggest-override) -target_link_options( cxx-benchmarks-flags-libcxx INTERFACE -nostdlib++ "-L${BENCHMARK_LIBCXX_INSTALL}/lib" "-L${BENCHMARK_LIBCXX_INSTALL}/lib64" ${SANITIZER_FLAGS}) +target_link_options( cxx-benchmarks-flags-libcxx INTERFACE -lm -nostdlib++ "-L${BENCHMARK_LIBCXX_INSTALL}/lib" "-L${BENCHMARK_LIBCXX_INSTALL}/lib64" ${SANITIZER_FLAGS}) set(libcxx_benchmark_targets) @@ -220,9 +220,12 @@ set(BENCHMARK_TESTS lexicographical_compare_three_way.bench.cpp map.bench.cpp monotonic_buffer.bench.cpp + numeric/gcd.bench.cpp ordered_set.bench.cpp + shared_mutex_vs_mutex.bench.cpp stop_token.bench.cpp std_format_spec_string_unicode.bench.cpp + std_format_spec_string_unicode_escape.bench.cpp string.bench.cpp stringstream.bench.cpp system_error.bench.cpp @@ -249,10 +252,6 @@ endforeach() if (LIBCXX_INCLUDE_TESTS) include(AddLLVM) - if (NOT DEFINED LIBCXX_TEST_DEPS) - message(FATAL_ERROR "Expected LIBCXX_TEST_DEPS to be defined") - endif() - configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py) @@ -262,6 +261,6 @@ if (LIBCXX_INCLUDE_TESTS) add_lit_target(check-cxx-benchmarks "Running libcxx benchmarks tests" ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS cxx-benchmarks ${LIBCXX_TEST_DEPS} + DEPENDS cxx-benchmarks cxx-test-depends ARGS ${BENCHMARK_LIT_ARGS}) endif() diff --git a/naiveproxy/src/third_party/libc++/src/benchmarks/algorithms/pstl.stable_sort.bench.cpp b/naiveproxy/src/third_party/libc++/src/benchmarks/algorithms/pstl.stable_sort.bench.cpp index 9357b870be..72541f7064 100644 --- a/naiveproxy/src/third_party/libc++/src/benchmarks/algorithms/pstl.stable_sort.bench.cpp +++ b/naiveproxy/src/third_party/libc++/src/benchmarks/algorithms/pstl.stable_sort.bench.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include +#include #include "common.h" diff --git a/naiveproxy/src/third_party/libc++/src/benchmarks/numeric/gcd.bench.cpp b/naiveproxy/src/third_party/libc++/src/benchmarks/numeric/gcd.bench.cpp new file mode 100644 index 0000000000..f8b6a856cd --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/benchmarks/numeric/gcd.bench.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + +template +static std::array generate(std::uniform_int_distribution distribution = std::uniform_int_distribution{ + std::numeric_limits::min() + 1, std::numeric_limits::max()}) { + std::mt19937 generator; + std::array result; + std::generate_n(result.begin(), result.size(), [&] { return distribution(generator); }); + return result; +} + +static void bm_gcd_random(benchmark::State& state) { + std::array data = generate(); + while (state.KeepRunningBatch(data.size())) + for (auto v0 : data) + for (auto v1 : data) + benchmark::DoNotOptimize(std::gcd(v0, v1)); +} +BENCHMARK(bm_gcd_random); + +static void bm_gcd_trivial(benchmark::State& state) { + int lhs = ~static_cast(0), rhs = 1; + for (auto _ : state) { + benchmark::DoNotOptimize(lhs); + benchmark::DoNotOptimize(rhs); + benchmark::DoNotOptimize(std::gcd(lhs, rhs)); + } +} +BENCHMARK(bm_gcd_trivial); + +static void bm_gcd_complex(benchmark::State& state) { + int lhs = 2971215073, rhs = 1836311903; + for (auto _ : state) { + benchmark::DoNotOptimize(lhs); + benchmark::DoNotOptimize(rhs); + benchmark::DoNotOptimize(std::gcd(lhs, rhs)); + } +} +BENCHMARK(bm_gcd_complex); + +BENCHMARK_MAIN(); diff --git a/naiveproxy/src/third_party/libc++/src/benchmarks/shared_mutex_vs_mutex.bench.cpp b/naiveproxy/src/third_party/libc++/src/benchmarks/shared_mutex_vs_mutex.bench.cpp new file mode 100644 index 0000000000..19d13b799c --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/benchmarks/shared_mutex_vs_mutex.bench.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This benchmark compares the performance of std::mutex and std::shared_mutex in contended scenarios. +// it's meant to establish a baseline overhead for std::shared_mutex and std::mutex, and to help inform decisions about +// which mutex to use when selecting a mutex type for a given use case. + +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" + +int global_value = 42; +std::mutex m; +std::shared_mutex sm; + +static void BM_shared_mutex(benchmark::State& state) { + for (auto _ : state) { + std::shared_lock lock(sm); + benchmark::DoNotOptimize(global_value); + } +} + +static void BM_mutex(benchmark::State& state) { + for (auto _ : state) { + std::lock_guard lock(m); + benchmark::DoNotOptimize(global_value); + } +} + +BENCHMARK(BM_shared_mutex)->Threads(1)->Threads(2)->Threads(4)->Threads(8)->Threads(32); +BENCHMARK(BM_mutex)->Threads(1)->Threads(2)->Threads(4)->Threads(8)->Threads(32); + +BENCHMARK_MAIN(); diff --git a/naiveproxy/src/third_party/libc++/src/benchmarks/std_format_spec_string_unicode_escape.bench.cpp b/naiveproxy/src/third_party/libc++/src/benchmarks/std_format_spec_string_unicode_escape.bench.cpp new file mode 100644 index 0000000000..3b5a1c4340 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/benchmarks/std_format_spec_string_unicode_escape.bench.cpp @@ -0,0 +1,303 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This test formats a larger piece of text in "escaped" mode. It uses several +// datasets to give an impression how the amount of multibyte UTF-8 sequences +// and larger grapheme clusters affect the performance. + +#ifndef _LIBCPP_HAS_NO_UNICODE + +# include +# include + +# include "benchmark/benchmark.h" + +# include "make_string.h" + +# define SV(S) MAKE_STRING_VIEW(CharT, S) + +// generated with https://generator.lorem-ipsum.info/_latin + +template +std::basic_string_view ascii_text() { + return SV( + R"( Lorem ipsum dolor sit amet, ne sensibus evertitur aliquando his. +Iuvaret fabulas qui ex, ex iriure iisque nostrum mea. Solum +pericula qui ad. Elitr oporteat ius ad. + +Quas rationibus ad mel. Appellantur intellegebat ad mei, ius audire volumus +consectetuer id. Ei sit definitionem mediocritatem, vim indoctum intellegat id, +dicta laboramus instructior in vix. Mel an quando malorum, id vis mollis +invidunt, placerat maiestatis comprehensam ut cum. Suas regione interesset id +per, et docendi accumsan has, autem atomorum est te. + +Cu debitis ancillae sea, alii definitiones ex cum, vim no erat antiopam. Eam et +unum quas scriptorem. An bonorum elaboraret complectitur nam, vim ei persecuti +democritum mediocritatem. Suscipit platonem signiferumque ei cum, in sale +volutpat ocurreret vel. Te vel nihil nominavi adipiscing, stet ancillae mel ea. +Sit detraxit menandri platonem ea, cum at tale viris virtute. + +Regione detraxit gloriatur sit eu, sonet labitur sententiae et pro, at sit +alterum aliquid interpretaris. Sonet voluptua duo id, vix ea accumsan +liberavisse. Nam id commune probatus contentiones. Et zril dolore laudem duo, +ea usu mollis melius referrentur, vel ex case consequuntur. Id nam illum mollis +ponderum. Quis tamquam ullamcorper sed ne, legimus vituperatoribus est id. + +Et eum probo consulatu. At eos errem aliquando theophrastus, sea ad eius omnis. +No vis iusto scriptorem adversarium, dicat viderer ea sit. Et veri euripidis +sea, justo putent iudicabit vim id. Sea suas tincidunt vituperatoribus in. Ne +eam aeterno sensibus concludaturque, solet legere his id, usu ei dicat +dissentiunt. Est et autem erant. + +Per quod laboramus an. Dico voluptua at mea, an animal minimum eum. Pri an +option salutatus, causae feugiat menandri an sed. Voluptaria dissentiet vix ut, +alii solet te quo, in facer ceteros eos. Ad nibh meis percipitur sit, +aliquam molestie cu vis, iisque malorum interesset et eos. + +Eos in feugiat insolens abhorreant. Ea tale esse alienum has, mel et saperet +appellantur, aliquip salutandi deterruisset ut mel. Eos ei quod simul +interpretaris, aeque elitr putent per at, et veri eripuit ceteros his. Cu pro +meis aperiam volutpat, ex alterum scripserit ius, scriptorem deterruisset eu +qui. Graeco debitis lobortis cu mea. + +Alii corpora id ius, cu quo oblique eloquentiam. Et duis civibus atomorum sea, +veniam utroque scriptorem vim cu. Ut oratio eruditi mediocritatem est. Amet +nibh dolore mea ea, tollit laoreet eligendi qui ex, cu essent forensibus +his. + +Usu ex ipsum apeirian, eos congue scripserit omittantur et. Ea eum persecuti +deseruisse, probatus torquatos est no, in has mutat mundi dolorem. Albucius +sensibus ex cum. Ferri virtute referrentur an per, est choro option bonorum ex. + +Quando accusam vis te, tale mazim et pro. Magna dolorem tincidunt +nec te, albucius adipisci ad pri. Magna facilisi adipisci at usu, et vel +dissentiunt neglegentur, prima audiam vocibus an duo. Enim detracto te sea, mel +quis dicit gubergren ex, iusto adversarium consequuntur per ne. + +)"); +} + +template +std::basic_string_view unicode_text() { + return SV( + R"(Lōrem ipsūm dolor sīt æmeÞ, ea vel nostrud feuġǣit, muciūs tēmporiȝus +refērrēnÞur no mel, quo placērǽt consecÞetuer cū. Veri soƿet euripīðis id has, +sumo paulō dissentias duo eī, dētrāxīt neglēgeƿtur ið prī. Sēd option oporÞerē +no. Nec ēū nēmore mentitum. Veri prōȝo faċilis āt vīm. + +Ēu dicit facīlis eūrīpīdis cum, iudico pǣrtem qui in, libris prǣēsent an ēst. +Æt sit quoðsi impētus, nec ex qūaeque honestǣtīs. Fiērēƿt ƿōluisse verterem iƿ +ēst. Meī eæ apēriæm fierent peÞentīūm. Eæm officiīs reprehēndunt nē. + +Ut vel quodsī contentioƿes, his eū dignissim īnstruċÞior. Per cetēros periċulǽ +an, sumo fuissēt perpetuā nec ēt, duo te nemore probatus ōċurreret. Mel ǣd +civībus ocūrreret. Ex nostro ǣliquam usu, ex Þātīon adipiscī qui. Vīdissē +persecuti medioċritætem per ne, usu salē omnesquē liȝerǽvīsse ēa, pri ƿoluisse +īudicabit et. No summo quiðǣm nec, vim ēi nūmqūam sænctus concepÞǣm. Reque +doceƿdi īn īus, porro eripuiÞ intērprētaris pri in. + +Idquē hǣbēmus nominati vix cū. AÞ prō ǽmēt elit periculæ. Has virīs viderer ān. +Mel in suās pericūlīs āppellantur, nonumes deserūƿt ǽðversarium eā has. ĒliÞ +possīt commuƿe no ēsÞ, niȝh aċcusāmūs volūpÞatum no mel, ut quō ciȝo ðiceret. +Inǣni scripta quālīsque nē qūi, ad ipsūm persecuÞi mediōcritæÞēm vel. + +Ǣppetere definitiōnes mel id. Leġerē āliquip nam eǣ, rēgione viderer pǣtrioque +duo te, meƿāƿdri prodēsseÞ ex hīs. Solum quidam eæ iūs, mēl ǣt sapientem +expliċari. Īƿ ǣċcusǣm phǽedrum pro, ex pro dēleƿit detræxit hendrerīt, sit āgam +quidām pertinax uÞ. Ēssent rætionibus eǽ vēl, quo ān labore nusquæm nominǣti. + +Te alii cōnseÞetur ƿam, eam ēt puteƿÞ ðissentiæs. Qūi alii dicānt repuðiære ēā, +nō mel ferri nūsquam. Ea vim impedīt vertērem, ǣn per veri Þīmeam. SiÞ ōmitÞǽm +necēssitǣÞibus ex, ƿe vis inǣni pærtem invenire. Īd ðolores ċonsēċÞeÞuer usu, +īd vis nisl dēnique luptǣtūm. Pro ǽd ēverti option dēserūƿt, nec te ōðiō +cīvībūs. + +Ēæ nibh æccommodarē eum. Ne etiæm īudico dicunt duo, quo tēmpor populo insōlens +nē. Ēos eÞ ēirmod prǽēsēƿt. Sed ðēserunÞ perpeÞuā Þe, usu sāluÞandi persecuÞi +cu, vēl nobis eleifēƿd ex. + +Ƿe zrīl ūtīnam lǣtīne eǣm, eā vim rebum omitÞǣm aðipisciƿg. Amet inermis +epiċūri ut est, eu duo hīnc periċulis. Mel no reque simul volupÞātum, ex mutat +lāudem tacīmatēs cum. Te hǣs summo iƿteġre recteque. No iūs dicerēt +ðisputǽtioƿi. Vim ōmnis deleƿiÞi honestātis ēǽ. + +Nec detrǣcto pērcipitur ne. Ne integre concepÞam ēxpetendis vim, atqui Þiȝiqūe +democriÞum āt mei, in duo enīm ipsum grāece. Rebum ðefīnīÞionem āt pri, ēt sit +brute periculis. Ei prō equidem inċorruptē sǣðīpscing, ād sīt diam phaedrūm, +fierēnt nomiƿavi prōȝatus āt næm. Wisi ƿæÞūm coƿsecteÞuer usū ea. +)"); +} + +template +std::basic_string_view cyrillic_text() { + return SV( + R"(Лорем ипсум долор сит амет, еу диам тамяуам принципес вис, еяуидем +цонцептам диспутандо яуи цу, иус ад натум нулла граеци. Цибо дицит омниум нец +цу, еу бруте номинави диссентиет яуо. Омниум лаборамус еу хас. Дицат +диспутатиони вис еу, цу еос миним атоморум инцидеринт. Пер хабео рецтеяуе +дигниссим ан, ех яуо сенсибус торяуатос, ан. + +Ут перпетуа партиендо принципес хис. Ат симул ностер аппареат пер. Пурто вирис +ет хис, мазим дицерет при ет. Хис саперет тибияуе сцаевола еу, сит солет +вивендум цонсеяуат те. Ид оффициис перпетуа ассентиор яуи, сед аугуе афферт +симилияуе ад, ех адмодум постулант иус. + +Про дицунт волуптатум диспутатиони ат. Вел патриояуе персецути еа, цетерос +диспутатиони ин сед, нам те веро цлита малуиссет. Цу неглегентур инструцтиор +интерпретарис еам, ипсум фабулас еи вел. Еи адхуц деленити нам, аугуе +демоцритум при ан. Вим мелиоре проприае ид, албуциус волуптуа цоррумпит дуо ан. +Латине иуварет пер ут, иус еа мунере ерипуит санцтус. + +Модус тритани иус не, вим ут мелиоре мандамус, лабитур опортере дуо но. Ад нец +витае фацилис инцоррупте, цу сед толлит сцрипторем. Сит лудус инимицус +волуптариа не. Иисяуе антиопам сапиентем сед еу. Путент волуптуа сит ех, ат иус +ребум епицури, яуи моллис елигенди ех. Проприае нолуиссе цу сеа, путент поссит +адверсариум про не. + +Ид яуо прима бонорум, дуо форенсибус яуаерендум еи, еум бруте мунере те. Еам +риденс граецо ех, аеяуе санцтус маиорум ан вел. Либрис санцтус утрояуе ест но, +еам ат реяуе порро тинцидунт, ут хинц иллуд патриояуе хис. Не солет оффендит +форенсибус хас, тамяуам опортеат елаборарет те нец, еу аугуе примис маиорум +еам. Аутем вениам импедит вис ин, прима елитр пхаедрум ест еу.)"); +} + +template +std::basic_string_view japanese_text() { + return SV( + R"(入ト年媛ろ舗学ラロ準募ケカ社金スノ屋検れう策他セヲシ引口ぎ集7独ぱクふ出車ぽでぱ円輪ルノ受打わ。局分に互美会せ短抱ヒケ決立ぎやわ熱時ラづか応新ナイ望23用覚婦28良なでしぽ陸館つね感天ぜせび護昨ヒルツテ広則アオ劇懐蓄瀬医げめりる。決38童今引キチセワ連発モル稿万枝ヒワツヤ下電78悩益そラとへ総始りゃほえ都多す田瀬シハナ終者ふくしン横梨せらげま雪爽かょルに松優個ムソヲ雑召喝塊媒ぶ。 + +紙ヤ景異ミノオ誤求レ移著ヤエヨメ広庫テハヌサ君検あ必参ワ火面るね声著ン間売力を数20談すがス禁化ッを。起そり予浩ド進皇キ試属が震二トヌ真佳速すずちし件諏フウチ聞在ス会雄ノミ必筋80戦ぶさほド聞2涙属どスれ映聞ネ掲実べ。 + +8福びり属稿づ徳鎌ニル涼問ゃごるリ付92済トぎけッ康30業づむはつ治然二生入ざひ有動ハワチ発談ニスツ魚困摘策送ざ。個時着そてら新新ヌ鉄報たは作主ずリ可輸改量ルおず井認つてぜな会大ぼすぶし全戸ノハケレ貯治たざリな祖間ムリキ断会仕べせど。委暮ど象週トクワ流開タハ硬給ツタウ者善マラノヱ断稿リヲ東毎ツヨマ井藤ルょへ境同論エ愛図ッらフリ基38属慣葬8携ヱ校図おに岐題しね要月レユ展省わトど。 + +担がは顔研リ目問いぽべ挙介ん入番ネヌイ栄県し改治ラス健第モム得続加ホウ嘉宿置首本やぞ。78毎まが現設記ほぜね場歩ユアルヒ東的ヒ姿役ネヲ聞能ラシマヒ際形トくゃ政能万の付結ス国1教レツ引写イど扱澤は膚言けリいべ橋柔薄組こよじ。浩報すンつひ崎正念方と夫地クざす情阪スで抜長ネ娘回ハツ止資ヘニ並辞ロノ展師質18打テネ岡時ノモ泉95務えぴひつ速申後延んフるせ。 + +店てラ載独マシフ理心ス型部米た読石カ料応掲ケカキ打月在ユテニ採材イ並発イヒト旅錯っめし模能りせば連確え会准揮が。器にト画軍にぶイら式東みそお前姿リいけに身47却6記け岸5体会ゃばま映8碁よぽだ経9名トびち更躍うにふ裏高もそ提旅さぼえス。賞ぞだ月係ソ知建振イナシ説並イ見書傳ヨミ問回級エシ出所師阪ト転権がし渡平ルモケ新完ハ玲女ロトシ導複トうよふ。 + +化シセチ町74掲ネテトオ連対ヒハチモ経後ッ断連カロワ待業ぼぽねか百都へがい始塗ごげ寺帰んぽ逆力るず選英堂衛掛焼ゅ。自生トサリ探就的らね江球リルスツ主嘆4権伝ざが避掲う慶合ワ百29暮ネヤクム書能部あが席小フア部親票ーむとこ。3説ひっぜ約毎伎ナキリ缶近くなず員45姿えにけろ値付ワ着知ソルキ日医ず集新エウカケ投国チ生目ゃ棋運ぐのか寄募オチ性注経どドんて止代わくかな端期幕はかク。 +)"); +} + +template +std::basic_string_view emoji_text() { + return SV( + R"( +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF + +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 + +\U0001F636\u200D\U0001F32B\uFE0F + +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF + +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 + +\U0001F984 + +)"); +} + +template +void BM_escaped(benchmark::State& state, std::basic_string_view input) { + CharT buffer[25'000]; + + if constexpr (std::same_as) { + // Make sure the output buffer is large enough. + assert(std::formatted_size("{}", input) == 3000); + for (auto _ : state) + benchmark::DoNotOptimize(std::format_to(buffer, "{:?}", input)); + } else { + for (auto _ : state) + benchmark::DoNotOptimize(std::format_to(buffer, L"{:?}", input)); + } +} + +template +void BM_ascii_escaped(benchmark::State& state) { + BM_escaped(state, ascii_text()); +} + +template +void BM_unicode_escaped(benchmark::State& state) { + BM_escaped(state, unicode_text()); +} + +template +void BM_cyrillic_escaped(benchmark::State& state) { + BM_escaped(state, cyrillic_text()); +} + +template +void BM_japanese_escaped(benchmark::State& state) { + BM_escaped(state, japanese_text()); +} + +template +void BM_emoji_escaped(benchmark::State& state) { + BM_escaped(state, emoji_text()); +} + +BENCHMARK_TEMPLATE(BM_ascii_escaped, char); +BENCHMARK_TEMPLATE(BM_unicode_escaped, char); +BENCHMARK_TEMPLATE(BM_cyrillic_escaped, char); +BENCHMARK_TEMPLATE(BM_japanese_escaped, char); +BENCHMARK_TEMPLATE(BM_emoji_escaped, char); + +BENCHMARK_TEMPLATE(BM_ascii_escaped, wchar_t); +BENCHMARK_TEMPLATE(BM_unicode_escaped, wchar_t); +BENCHMARK_TEMPLATE(BM_cyrillic_escaped, wchar_t); +BENCHMARK_TEMPLATE(BM_japanese_escaped, wchar_t); +BENCHMARK_TEMPLATE(BM_emoji_escaped, wchar_t); + +int main(int argc, char** argv) { + benchmark::Initialize(&argc, argv); + if (benchmark::ReportUnrecognizedArguments(argc, argv)) + return 1; + + benchmark::RunSpecifiedBenchmarks(); +} +#else +int main(int, char**) { return 0; } +#endif diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Apple.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Apple.cmake index cec13c08ac..1038f1aed5 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Apple.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Apple.cmake @@ -7,7 +7,7 @@ set(LIBCXX_ENABLE_STATIC ON CACHE BOOL "") set(LIBCXX_ENABLE_SHARED ON CACHE BOOL "") set(LIBCXX_CXX_ABI libcxxabi CACHE STRING "") set(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS ON CACHE BOOL "") -set(LIBCXX_PSTL_CPU_BACKEND libdispatch CACHE STRING "") +set(LIBCXX_PSTL_BACKEND libdispatch CACHE STRING "") set(LIBCXX_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") set(LIBCXXABI_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") @@ -15,6 +15,3 @@ set(LIBCXXABI_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "") set(LIBCXXABI_ENABLE_ASSERTIONS OFF CACHE BOOL "") set(LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST ON CACHE BOOL "") set(LIBCXXABI_USE_LLVM_UNWINDER OFF CACHE BOOL "") # libunwind is built separately - -set(LIBCXX_TEST_CONFIG "apple-libc++-shared.cfg.in" CACHE STRING "") -set(LIBCXXABI_TEST_CONFIG "apple-libc++abi-shared.cfg.in" CACHE STRING "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx20.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx20.cmake index 641c131a73..3c44fdaf0e 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx20.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx20.cmake @@ -1,3 +1,2 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_TEST_PARAMS "std=c++20" CACHE STRING "") set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx23.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx23.cmake index f5409e4652..bf88abf56c 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx23.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx23.cmake @@ -1,3 +1,2 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_TEST_PARAMS "std=c++23" CACHE STRING "") set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx26.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx26.cmake index 2d9c018a4f..6ba9482af5 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx26.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-cxx26.cmake @@ -1,3 +1,2 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_TEST_PARAMS "std=c++26" CACHE STRING "") set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-hardening-mode-extensive.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-hardening-mode-extensive.cmake index 9542dcdbf7..72263dfd84 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-hardening-mode-extensive.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-hardening-mode-extensive.cmake @@ -1,2 +1 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_HARDENING_MODE "extensive" CACHE STRING "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-msan.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-msan.cmake index 9e50255fe4..a8fbd285a9 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-msan.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-msan.cmake @@ -1,2 +1,4 @@ set(LLVM_USE_SANITIZER "MemoryWithOrigins" CACHE STRING "") +set(LIBCXX_TEST_PARAMS "long_tests=False" CACHE STRING "") # MSAN is really slow and tests can sometimes timeout otherwise +set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "") set(LIBCXXABI_USE_LLVM_UNWINDER OFF CACHE BOOL "") # MSAN is compiled against the system unwinder, which leads to false positives diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-exceptions.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-exceptions.cmake index c68adfc127..f0dffef60d 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-exceptions.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-exceptions.cmake @@ -1,3 +1,2 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "") set(LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-experimental.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-experimental.cmake index 62b7d7373d..f33ed01418 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-experimental.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-experimental.cmake @@ -1,3 +1,2 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_TEST_PARAMS "enable_experimental=False" CACHE STRING "") set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-filesystem.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-filesystem.cmake index 01ae7e68f1..4000f3a3e8 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-filesystem.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-filesystem.cmake @@ -1,2 +1 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_ENABLE_FILESYSTEM OFF CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-localization.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-localization.cmake index fc4957b2d5..79d6b44c71 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-localization.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-localization.cmake @@ -1,2 +1 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_ENABLE_LOCALIZATION OFF CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-random_device.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-random_device.cmake index ddf479add6..e9b4cc60cc 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-random_device.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-random_device.cmake @@ -1,2 +1 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_ENABLE_RANDOM_DEVICE OFF CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-threads.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-threads.cmake index 724fbc466b..616baef1be 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-threads.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-threads.cmake @@ -1,4 +1,3 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_ENABLE_THREADS OFF CACHE BOOL "") set(LIBCXXABI_ENABLE_THREADS OFF CACHE BOOL "") set(LIBCXX_ENABLE_MONOTONIC_CLOCK OFF CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-unicode.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-unicode.cmake index a4cf7dd737..01160bf218 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-unicode.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-unicode.cmake @@ -1,2 +1 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_ENABLE_UNICODE OFF CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-wide-characters.cmake b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-wide-characters.cmake index dc19389bb5..728d41086a 100644 --- a/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-wide-characters.cmake +++ b/naiveproxy/src/third_party/libc++/src/cmake/caches/Generic-no-wide-characters.cmake @@ -1,2 +1 @@ -set(LIBCXX_INSTALL_MODULES ON CACHE BOOL "") # TODO MODULES Remove when enabled automatically. set(LIBCXX_ENABLE_WIDE_CHARACTERS OFF CACHE BOOL "") diff --git a/naiveproxy/src/third_party/libc++/src/docs/BuildingLibcxx.rst b/naiveproxy/src/third_party/libc++/src/docs/BuildingLibcxx.rst index 28145ed104..e425b9dadf 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/BuildingLibcxx.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/BuildingLibcxx.rst @@ -206,6 +206,12 @@ libc++ specific options Toggle the installation of the libc++ headers. +.. option:: LIBCXX_INSTALL_MODULES:BOOL + + **Default**: ``ON`` + + Toggle the installation of the experimental libc++ module sources. + .. option:: LIBCXX_ENABLE_SHARED:BOOL **Default**: ``ON`` diff --git a/naiveproxy/src/third_party/libc++/src/docs/FeatureTestMacroTable.rst b/naiveproxy/src/third_party/libc++/src/docs/FeatureTestMacroTable.rst index 3197d2cd1b..1e347d043e 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/FeatureTestMacroTable.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/FeatureTestMacroTable.rst @@ -178,7 +178,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_atomic_lock_free_type_aliases`` ``201907L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_atomic_ref`` *unimplemented* + ``__cpp_lib_atomic_ref`` ``201806L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_atomic_shared_ptr`` *unimplemented* ---------------------------------------------------------- ----------------- @@ -234,7 +234,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_execution`` *unimplemented* ---------------------------------------------------------- ----------------- - ``__cpp_lib_format`` *unimplemented* + ``__cpp_lib_format`` ``202110L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_format_uchar`` ``202311L`` ---------------------------------------------------------- ----------------- @@ -290,7 +290,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_syncbuf`` ``201803L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_three_way_comparison`` *unimplemented* + ``__cpp_lib_three_way_comparison`` ``201711L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_to_address`` ``201711L`` ---------------------------------------------------------- ----------------- @@ -322,9 +322,9 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_constexpr_typeinfo`` ``202106L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_expected`` ``202211L`` + ``__cpp_lib_containers_ranges`` ``202202L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_format_path`` *unimplemented* + ``__cpp_lib_expected`` ``202211L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_format_ranges`` ``202207L`` ---------------------------------------------------------- ----------------- @@ -340,6 +340,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_mdspan`` ``202207L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_modules`` ``202207L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_move_only_function`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_optional`` ``202110L`` @@ -384,8 +386,6 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_string_resize_and_overwrite`` ``202110L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_to_string`` *unimplemented* - ---------------------------------------------------------- ----------------- ``__cpp_lib_to_underlying`` ``202102L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_tuple_like`` *unimplemented* @@ -402,6 +402,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_bitset`` ``202306L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_constexpr_new`` *unimplemented* + ---------------------------------------------------------- ----------------- ``__cpp_lib_constrained_equality`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_copyable_function`` *unimplemented* @@ -410,6 +412,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_default_template_type_for_algorithm_values`` *unimplemented* ---------------------------------------------------------- ----------------- + ``__cpp_lib_format_path`` *unimplemented* + ---------------------------------------------------------- ----------------- ``__cpp_lib_freestanding_algorithm`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_freestanding_array`` *unimplemented* @@ -434,20 +438,34 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_hazard_pointer`` *unimplemented* ---------------------------------------------------------- ----------------- + ``__cpp_lib_inplace_vector`` *unimplemented* + ---------------------------------------------------------- ----------------- + ``__cpp_lib_is_virtual_base_of`` *unimplemented* + ---------------------------------------------------------- ----------------- + ``__cpp_lib_is_within_lifetime`` *unimplemented* + ---------------------------------------------------------- ----------------- ``__cpp_lib_linalg`` *unimplemented* ---------------------------------------------------------- ----------------- + ``__cpp_lib_mdspan`` ``202406L`` + ---------------------------------------------------------- ----------------- + ``__cpp_lib_optional_range_support`` *unimplemented* + ---------------------------------------------------------- ----------------- ``__cpp_lib_out_ptr`` *unimplemented* ---------------------------------------------------------- ----------------- + ``__cpp_lib_philox_engine`` *unimplemented* + ---------------------------------------------------------- ----------------- ``__cpp_lib_ranges_concat`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_ratio`` ``202306L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_rcu`` *unimplemented* ---------------------------------------------------------- ----------------- - ``__cpp_lib_reference_wrapper`` *unimplemented* + ``__cpp_lib_reference_wrapper`` ``202403L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_saturation_arithmetic`` ``202311L`` ---------------------------------------------------------- ----------------- + ``__cpp_lib_senders`` *unimplemented* + ---------------------------------------------------------- ----------------- ``__cpp_lib_smart_ptr_owner_equality`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_span_at`` ``202311L`` @@ -462,8 +480,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_to_chars`` *unimplemented* ---------------------------------------------------------- ----------------- - ``__cpp_lib_tuple_like`` *unimplemented* + ``__cpp_lib_to_string`` *unimplemented* ---------------------------------------------------------- ----------------- - ``__cpp_lib_within_lifetime`` *unimplemented* + ``__cpp_lib_tuple_like`` *unimplemented* ========================================================== ================= diff --git a/naiveproxy/src/third_party/libc++/src/docs/Hardening.rst b/naiveproxy/src/third_party/libc++/src/docs/Hardening.rst index 0761f42368..9aac059d27 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Hardening.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/Hardening.rst @@ -1,4 +1,4 @@ -.. _hardening-modes: +.. _hardening: =============== Hardening Modes @@ -29,8 +29,11 @@ modes are: rigour impacts performance more than fast mode: we recommend benchmarking to determine if that is acceptable for your program. - **Debug mode**, which enables all the available checks in the library, - including internal assertions, some of which might be very expensive. This - mode is intended to be used for testing, not in production. + including heuristic checks that might have significant performance overhead as + well as internal library assertions. This mode should be used in + non-production environments (such as test suites, CI, or local development). + We don’t commit to a particular level of performance in this mode and it’s + *not* intended to be used in production. .. note:: @@ -72,17 +75,367 @@ to control the level by passing **one** of the following options to the compiler Notes for vendors ----------------- -Vendors can set the default hardening mode by providing ``LIBCXX_HARDENING_MODE`` -as a configuration option, with the possible values of ``none``, ``fast``, -``extensive`` and ``debug``. The default value is ``none`` which doesn't enable -any hardening checks (this mode is sometimes called the ``unchecked`` mode). +Vendors can set the default hardening mode by providing +``LIBCXX_HARDENING_MODE`` as a configuration option, with the possible values of +``none``, ``fast``, ``extensive`` and ``debug``. The default value is ``none`` +which doesn't enable any hardening checks (this mode is sometimes called the +``unchecked`` mode). This option controls both the hardening mode that the precompiled library is built with and the default hardening mode that users will build with. If set to ``none``, the precompiled library will not contain any assertions, and user code will default to building without assertions. -Iterator bounds checking ------------------------- +Vendors can also override the way the program is terminated when an assertion +fails by :ref:`providing a custom header `. -TODO(hardening) +Assertion categories +==================== + +Inside the library, individual assertions are grouped into different +*categories*. Each hardening mode enables a different set of assertion +categories; categories provide an additional layer of abstraction that makes it +easier to reason about the high-level semantics of a hardening mode. + +.. note:: + + Users are not intended to interact with these categories directly -- the + categories are considered internal to the library and subject to change. + +- ``valid-element-access`` -- checks that any attempts to access a container + element, whether through the container object or through an iterator, are + valid and do not attempt to go out of bounds or otherwise access + a non-existent element. This also includes operations that set up an imminent + invalid access (e.g. incrementing an end iterator). For iterator checks to + work, bounded iterators must be enabled in the ABI. Types like + ``std::optional`` and ``std::function`` are considered containers (with at + most one element) for the purposes of this check. + +- ``valid-input-range`` -- checks that ranges (whether expressed as an iterator + pair, an iterator and a sentinel, an iterator and a count, or + a ``std::range``) given as input to library functions are valid: + - the sentinel is reachable from the begin iterator; + - TODO(hardening): both iterators refer to the same container. + + ("input" here refers to "an input given to an algorithm", not to an iterator + category) + + Violating assertions in this category leads to an out-of-bounds access. + +- ``non-null`` -- checks that the pointer being dereferenced is not null. On + most modern platforms, the zero address does not refer to an actual location + in memory, so a null pointer dereference would not compromise the memory + security of a program (however, it is still undefined behavior that can result + in strange errors due to compiler optimizations). + +- ``non-overlapping-ranges`` -- for functions that take several ranges as + arguments, checks that those ranges do not overlap. + +- ``valid-deallocation`` -- checks that an attempt to deallocate memory is valid + (e.g. the given object was allocated by the given allocator). Violating this + category typically results in a memory leak. + +- ``valid-external-api-call`` -- checks that a call to an external API doesn't + fail in an unexpected manner. This includes triggering documented cases of + undefined behavior in an external library (like attempting to unlock an + unlocked mutex in pthreads). Any API external to the library falls under this + category (from system calls to compiler intrinsics). We generally don't expect + these failures to compromise memory safety or otherwise create an immediate + security issue. + +- ``compatible-allocator`` -- checks any operations that exchange nodes between + containers to make sure the containers have compatible allocators. + +- ``argument-within-domain`` -- checks that the given argument is within the + domain of valid arguments for the function. Violating this typically produces + an incorrect result (e.g. ``std::clamp`` returns the original value without + clamping it due to incorrect functors) or puts an object into an invalid state + (e.g. a string view where only a subset of elements is accessible). This + category is for assertions violating which doesn't cause any immediate issues + in the library -- whatever the consequences are, they will happen in the user + code. + +- ``pedantic`` -- checks preconditions that are imposed by the Standard, but + violating which happens to be benign in libc++. + +- ``semantic-requirement`` -- checks that the given argument satisfies the + semantic requirements imposed by the Standard. Typically, there is no simple + way to completely prove that a semantic requirement is satisfied; thus, this + would often be a heuristic check and it might be quite expensive. + +- ``internal`` -- checks that internal invariants of the library hold. These + assertions don't depend on user input. + +- ``uncategorized`` -- for assertions that haven't been properly classified yet. + This category is an escape hatch used for some existing assertions in the + library; all new code should have its assertions properly classified. + +Mapping between the hardening modes and the assertion categories +================================================================ + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Category name + - ``fast`` + - ``extensive`` + - ``debug`` + * - ``valid-element-access`` + - ✅ + - ✅ + - ✅ + * - ``valid-input-range`` + - ✅ + - ✅ + - ✅ + * - ``non-null`` + - ❌ + - ✅ + - ✅ + * - ``non-overlapping-ranges`` + - ❌ + - ✅ + - ✅ + * - ``valid-deallocation`` + - ❌ + - ✅ + - ✅ + * - ``valid-external-api-call`` + - ❌ + - ✅ + - ✅ + * - ``compatible-allocator`` + - ❌ + - ✅ + - ✅ + * - ``argument-within-domain`` + - ❌ + - ✅ + - ✅ + * - ``pedantic`` + - ❌ + - ✅ + - ✅ + * - ``semantic-requirement`` + - ❌ + - ❌ + - ✅ + * - ``internal`` + - ❌ + - ❌ + - ✅ + * - ``uncategorized`` + - ❌ + - ✅ + - ✅ + +.. note:: + + At the moment, each subsequent hardening mode is a strict superset of the + previous one (in other words, each subsequent mode only enables additional + assertion categories without disabling any), but this won't necessarily be + true for any hardening modes that might be added in the future. + +.. note:: + + The categories enabled by each mode are subject to change and users should not + rely on the precise assertions enabled by a mode at a given point in time. + However, the library does guarantee to keep the hardening modes stable and + to fulfill the semantics documented here. + +Hardening assertion failure +=========================== + +In production modes (``fast`` and ``extensive``), a hardening assertion failure +immediately ``_traps `` +the program. This is the safest approach that also minimizes the code size +penalty as the failure handler maps to a single instruction. The downside is +that the failure provides no additional details other than the stack trace +(which might also be affected by optimizations). + +TODO(hardening): describe ``__builtin_verbose_trap`` once we can use it. + +In the ``debug`` mode, an assertion failure terminates the program in an +unspecified manner and also outputs the associated error message to the error +output. This is less secure and increases the size of the binary (among other +things, it has to store the error message strings) but makes the failure easier +to debug. It also allows testing the error messages in our test suite. + +.. _override-assertion-handler: + +Overriding the assertion failure handler +---------------------------------------- + +Vendors can override the default assertion handler mechanism by following these +steps: + +- create a header file that provides a definition of a macro called + ``_LIBCPP_ASSERTION_HANDLER``. The macro will be invoked when a hardening + assertion fails, with a single parameter containing a null-terminated string + with the error message. +- when configuring the library, provide the path to custom header (relative to + the root of the repository) via the CMake variable + ``LIBCXX_ASSERTION_HANDLER_FILE``. + +Note that almost all libc++ headers include the assertion handler header which +means it should not include anything non-trivial from the standard library to +avoid creating circular dependencies. + +There is no existing mechanism for users to override the assertion handler +because the ability to do the override other than at configure-time carries an +unavoidable code size penalty that would otherwise be imposed on all users, +whether they require such customization or not. Instead, we let vendors decide +what's right on their platform for their users -- a vendor who wishes to provide +this capability is free to do so, e.g. by declaring the assertion handler as an +overridable function. + +ABI +=== + +Setting a hardening mode does **not** affect the ABI. Each mode uses the subset +of checks available in the current ABI configuration which is determined by the +platform. + +It is important to stress that whether a particular check is enabled depends on +the combination of the selected hardening mode and the hardening-related ABI +options. Some checks require changing the ABI from the "default" to store +additional information in the library classes -- e.g. checking whether an +iterator is valid upon dereference generally requires storing data about bounds +inside the iterator object. Using ``std::span`` as an example, setting the +hardening mode to ``fast`` will always enable the ``valid-element-access`` +checks when accessing elements via a ``std::span`` object, but whether +dereferencing a ``std::span`` iterator does the equivalent check depends on the +ABI configuration. + +ABI options +----------- + +Vendors can use the following ABI options to enable additional hardening checks: + +- ``_LIBCPP_ABI_BOUNDED_ITERATORS`` -- changes the iterator type of select + containers (see below) to a bounded iterator that keeps track of whether it's + within the bounds of the original container and asserts valid bounds on every + dereference. + + ABI impact: changes the iterator type of the relevant containers. + + Supported containers: + + - ``span``; + - ``string_view``. + +ABI tags +-------- + +We use ABI tags to allow translation units built with different hardening modes +to interact with each other without causing ODR violations. Knowing how +hardening modes are encoded into the ABI tags might be useful to examine +a binary and determine whether it was built with hardening enabled. + +.. warning:: + We don't commit to the encoding scheme used by the ABI tags being stable + between different releases of libc++. The tags themselves are never stable, by + design -- new releases increase the version number. The following describes + the state of the latest release and is for informational purposes only. + +The first character of an ABI tag encodes the hardening mode: + +- ``f`` -- [f]ast mode; +- ``s`` -- extensive ("[s]afe") mode; +- ``d`` -- [d]ebug mode; +- ``n`` -- [n]one mode. + +Hardened containers status +========================== + +.. list-table:: + :header-rows: 1 + :widths: auto + + * - Name + - Member functions + - Iterators (ABI-dependent) + * - ``span`` + - ✅ + - ✅ + * - ``string_view`` + - ✅ + - ✅ + * - ``array`` + - ✅ + - ❌ + * - ``vector`` + - ✅ + - ❌ + * - ``string`` + - ✅ + - ❌ + * - ``list`` + - ✅ + - ❌ + * - ``forward_list`` + - ❌ + - ❌ + * - ``deque`` + - ✅ + - ❌ + * - ``map`` + - ❌ + - ❌ + * - ``set`` + - ❌ + - ❌ + * - ``multimap`` + - ❌ + - ❌ + * - ``multiset`` + - ❌ + - ❌ + * - ``unordered_map`` + - Partial + - Partial + * - ``unordered_set`` + - Partial + - Partial + * - ``unordered_multimap`` + - Partial + - Partial + * - ``unordered_multiset`` + - Partial + - Partial + * - ``mdspan`` + - ✅ + - ❌ + * - ``optional`` + - ✅ + - N/A + * - ``function`` + - ❌ + - N/A + * - ``variant`` + - N/A + - N/A + * - ``any`` + - N/A + - N/A + * - ``expected`` + - ✅ + - N/A + * - ``valarray`` + - Partial + - N/A + * - ``bitset`` + - ❌ + - N/A + +Testing +======= + +Please see :ref:`Testing documentation `. + +Further reading +=============== + +- `Hardening RFC `_: + contains some of the design rationale. diff --git a/naiveproxy/src/third_party/libc++/src/docs/Modules.rst b/naiveproxy/src/third_party/libc++/src/docs/Modules.rst index 5b027ed1bd..352a198f37 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Modules.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/Modules.rst @@ -69,8 +69,6 @@ Some of the current limitations * The path to the compiler may not be a symlink, ``clang-scan-deps`` does not handle that case properly * Libc++ is not tested with modules instead of headers - * Clang supports modules using GNU extensions, but libc++ does not work using - GNU extensions. * Clang: * Including headers after importing the ``std`` module may fail. This is hard to solve and there is a work-around by first including all headers @@ -105,9 +103,17 @@ Users need to be able to build their own BMI files. system vendors, with the goal that building the BMI files is done by the build system. -Currently this requires a local build of libc++ with modules enabled. Since -modules are not part of the installation yet, they are used from the build -directory. First libc++ needs to be build with module support enabled. +Currently there are two ways to build modules + + * Use a local build of modules from the build directory. This requires + Clang 17 or later and CMake 3.26 or later. + + * Use the installed modules. This requires Clang 18.1.2 or later and + a recent build of CMake. The CMake changes will be part of CMake 3.30. This + method requires you or your distribution to enable module installation. + +Using the local build +~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash @@ -136,7 +142,7 @@ This is a small sample program that uses the module ``std``. It consists of a .. code-block:: cmake cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR) - project("module" + project("example" LANGUAGES CXX ) @@ -146,7 +152,6 @@ This is a small sample program that uses the module ``std``. It consists of a set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED YES) - # Libc++ doesn't support compiler extensions for modules. set(CMAKE_CXX_EXTENSIONS OFF) # @@ -214,6 +219,64 @@ Building this project is done with the following steps, assuming the files ``error: module file _deps/std-build/CMakeFiles/std.dir/std.pcm cannot be loaded due to a configuration mismatch with the current compilation [-Wmodule-file-config-mismatch]`` + +Using the installed modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +CMake has added experimental support for importing the Standard modules. This +is available in the current nightly builds and will be part of the 3.30 +release. Currently CMake only supports importing the Standard modules in C++23 +and later. Enabling this for C++20 is on the TODO list of the CMake +developers. + +The example uses the same ``main.cpp`` as above. It uses the following +``CMakeLists.txt``: + +.. code-block:: cmake + + # This requires a recent nightly build. + # This will be part of CMake 3.30.0. + cmake_minimum_required(VERSION 3.29.0 FATAL_ERROR) + + # Enables the Standard module support. This needs to be done + # before selecting the languages. + set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + set(CMAKE_CXX_MODULE_STD ON) + + project("example" + LANGUAGES CXX + ) + + # + # Set language version used + # + + set(CMAKE_CXX_STANDARD 23) + set(CMAKE_CXX_STANDARD_REQUIRED YES) + # Currently CMake requires extensions enabled when using import std. + # https://gitlab.kitware.com/cmake/cmake/-/issues/25916 + # https://gitlab.kitware.com/cmake/cmake/-/issues/25539 + set(CMAKE_CXX_EXTENSIONS ON) + + add_executable(main) + target_sources(main + PRIVATE + main.cpp + ) + +Building this project is done with the following steps, assuming the files +``main.cpp`` and ``CMakeLists.txt`` are copied in the current directory. + +.. code-block:: bash + + $ mkdir build + $ cmake -G Ninja -S . -B build -DCMAKE_CXX_COMPILER= -DCMAKE_CXX_FLAGS=-stdlib=libc++ + $ ninja -C build + $ build/main + +.. warning:: ```` should point point to the real binary and + not to a symlink. + If you have questions about modules feel free to ask them in the ``#libcxx`` channel on `LLVM's Discord server `__. diff --git a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes.rst b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes.rst index d25f2d06a5..5d98ade8d9 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes.rst @@ -1,10 +1,11 @@ .. include:: ReleaseNotes/19.rst -.. Make sure to reference the previous release notes in a toctree to avoid Sphinx errors. +.. Make sure to reference the non-live release notes in a toctree to avoid Sphinx errors. .. toctree:: :hidden: ReleaseNotes/18 + ReleaseNotes/20 .. The release notes are in versioned files, but we make sure to keep publishing .. them in an unversioned ReleaseNotes.html page for external sites to reference. diff --git a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/18.rst b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/18.rst index fcd630e09b..4f7b9b362e 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/18.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/18.rst @@ -40,7 +40,7 @@ and C++26 features. New hardened modes for the library have been added, replacing the legacy debug mode that was removed in the LLVM 17 release. Unlike the legacy debug mode, some of these hardening modes are -also intended to be used in production. See :ref:`hardening-modes` for more details. +also intended to be used in production. See :ref:`hardening` for more details. Work on the ranges support has progressed. See :ref:`ranges-status` for the current status. diff --git a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/19.rst b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/19.rst index 81c05b9112..e6d8acb74a 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/19.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/19.rst @@ -45,13 +45,22 @@ Implemented Papers - P2867R2 - Remove Deprecated ``strstream``\s From C++26 - P2872R3 - Remove ``wstring_convert`` From C++26 - P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23) +- P2944R3 - Comparisons for ``reference_wrapper`` (comparison operators for ``reference_wrapper`` only) +- P2968R2 - Make ``std::ignore`` a first-class object - P2302R4 - ``std::ranges::contains`` - P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with`` +- P3029R1 - Better ``mdspan``'s CTAD +- P2387R3 - Pipe support for user-defined range adaptors +- P2713R1 - Escaping improvements in ``std::format`` +- P2231R1 - Missing ``constexpr`` in ``std::optional`` and ``std::variant`` +- P0019R8 - ``std::atomic_ref`` +- P2389R2 - Alias template ``dims`` for the ``extents`` of ``mdspan`` Improvements and New Features ----------------------------- - The performance of growing ``std::vector`` has been improved for trivially relocatable types. +- A lot of types are considered trivially relocatable now, including ``vector`` and ``string``. - The performance of ``ranges::fill`` and ``ranges::fill_n`` has been improved for ``vector::iterator``\s, resulting in a performance increase of up to 1400x. - The ``std::mismatch`` algorithm has been optimized for integral types, which can lead up to 40x performance @@ -67,10 +76,21 @@ Improvements and New Features - The formatting library is updated to Unicode 15.1.0. +- ``std::ignore``\s ``const __ignore_t& operator=(_Tp&&) const`` was changed to + ``const __ignore_type& operator=(const _Tp&) const noexcept`` for all language versions. + Deprecations and Removals ------------------------- -- TODO: The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable that was used to enable the safe mode has been deprecated and setting +- The C++20 synchronization library (````, ````, ``atomic::wait``, etc.) has been deprecated + in language modes prior to C++20. If you are using these features prior to C++20, please update to ``-std=c++20``. + In LLVM 20, the C++20 synchronization library will be removed entirely in language modes prior to C++20. + +- ``_LIBCPP_DISABLE_NODISCARD_EXT`` has been removed. ``[[nodiscard]]`` applications are now unconditional. + This decision is based on LEWGs discussion on `P3122 ` and `P3162 ` + to not use ``[[nodiscard]]`` in the standard. + +- The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable that was used to enable the safe mode has been deprecated and setting it triggers an error; use the ``LIBCXX_HARDENING_MODE`` CMake variable with the value ``extensive`` instead. Similarly, the ``_LIBCPP_ENABLE_ASSERTIONS`` macro has been deprecated (setting it to ``1`` still enables the extensive mode in the LLVM 19 release while also issuing a deprecation warning). See :ref:`the hardening documentation @@ -88,7 +108,7 @@ Deprecations and Removals - The ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS`` and ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION`` macros have been removed in LLVM 19. -- TODO: The ``_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES`` and ``_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES`` macros have +- The ``_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES`` and ``_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES`` macros have been removed in LLVM 19. C++17 and C++20 removed features can still be re-enabled individually. - The ``_LIBCPP_INLINE_VISIBILITY`` and ``_VSTD`` macros have been removed in LLVM 19. @@ -103,6 +123,24 @@ Deprecations and Removals a ``std::basic_*fstream`` from a ``std::basic_string_view``, a input-iterator or a C-string, instead you can construct a temporary ``std::basic_string``. This change has been applied to C++17 and later. +- The ``_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS`` macro has been removed and is not honored anymore. Additional + warnings provided by libc++ as a matter of QoI will now be provided unconditionally. + +- libc++ no longer supports ``std::allocator`` and containers of ``const``-qualified element type, such + as ``std::vector`` and ``std::list``. This used to be supported as an undocumented extension. + If you were using ``std::vector``, replace it with ``std::vector`` instead. The + ``_LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST`` macro can be defined to temporarily re-enable this extension as + folks transition their code. This macro will be honored for one released and ignored starting in LLVM 20. + To assist with the clean-up process, consider running your code through Clang Tidy, with + `std-allocator-const ` + enabled. + +- When configuring libc++ with localization or threads disabled, the library no longer emits an error when + trying to ``#include `` and other such headers. Instead, those headers have no content. This is + consistent with the behavior for all other libc++ carve-outs like filesystem, wide characters, a source + of randomness, and others. Users that were checking whether including a header would fail (e.g. via a script + or CMake's ``try_compile`` will experience a change in behavior). + Upcoming Deprecations and Removals ---------------------------------- @@ -113,6 +151,8 @@ LLVM 20 - The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable and the ``_LIBCPP_ENABLE_ASSERTIONS`` macro that were used to enable the safe mode will be removed in LLVM 20. +- The C++20 synchronization library will be removed entirely in language modes prior to C++20 in LLVM 20. + LLVM 21 ~~~~~~~ TODO @@ -131,3 +171,8 @@ Build System Changes - The ``LIBCXX_EXECUTOR`` and ``LIBCXXABI_EXECUTOR`` CMake variables have been removed. Please set ``LIBCXX_TEST_PARAMS`` to ``executor=<...>`` instead. + +- The Cmake variable ``LIBCXX_ENABLE_CLANG_TIDY`` has been removed. The build system has been changed + to automatically detect the presence of ``clang-tidy`` and the required ``Clang`` libraries. + +- The CMake options ``LIBCXX_INSTALL_MODULES`` now defaults to ``ON``. diff --git a/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/20.rst b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/20.rst new file mode 100644 index 0000000000..79b9788f92 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/docs/ReleaseNotes/20.rst @@ -0,0 +1,77 @@ +=========================================== +Libc++ 20.0.0 (In-Progress) Release Notes +=========================================== + +.. contents:: + :local: + :depth: 2 + +Written by the `Libc++ Team `_ + +.. warning:: + + These are in-progress notes for the upcoming libc++ 20.0.0 release. + Release notes for previous releases can be found on + `the Download Page `_. + +Introduction +============ + +This document contains the release notes for the libc++ C++ Standard Library, +part of the LLVM Compiler Infrastructure, release 20.0.0. Here we describe the +status of libc++ in some detail, including major improvements from the previous +release and new feature work. For the general LLVM release notes, see `the LLVM +documentation `_. All LLVM releases may +be downloaded from the `LLVM releases web site `_. + +For more information about libc++, please see the `Libc++ Web Site +`_ or the `LLVM Web Site `_. + +Note that if you are reading this file from a Git checkout or the +main Libc++ web page, this document applies to the *next* release, not +the current one. To see the release notes for a specific release, please +see the `releases page `_. + +What's New in Libc++ 20.0.0? +============================== + +Implemented Papers +------------------ + +- TODO + + +Improvements and New Features +----------------------------- + +- TODO + + +Deprecations and Removals +------------------------- + +- TODO: The ``LIBCXX_ENABLE_ASSERTIONS`` CMake variable and the ``_LIBCPP_ENABLE_ASSERTIONS`` macro that were used to enable + the safe mode will be removed in LLVM 20. + +- TODO: The C++20 synchronization library will be removed entirely in language modes prior to C++20 in LLVM 20. + + +Upcoming Deprecations and Removals +---------------------------------- + +LLVM 21 +~~~~~~~ + +- TODO + + +ABI Affecting Changes +--------------------- + +- TODO + + +Build System Changes +-------------------- + +- TODO diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17.rst b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17.rst index 99bfc7da96..d4426afa81 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17.rst @@ -42,7 +42,7 @@ Paper Status .. [#note-P0067] P0067: ``std::(to|from)_chars`` for integrals has been available since version 7.0. ``std::to_chars`` for ``float`` and ``double`` since version 14.0 ``std::to_chars`` for ``long double`` uses the implementation for ``double``. .. [#note-P0607] P0607: The parts of P0607 that are not done are the ```` bits. - .. [#note-P0154] P0154: This is currently not implemented for clang because clang does not implement the required macros. + .. [#note-P0154] P0154: The required macros are only implemented as of clang 19. .. [#note-P0452] P0452: The changes to ``std::transform_inclusive_scan`` and ``std::transform_exclusive_scan`` have not yet been implemented. .. _issues-status-cxx17: diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17Papers.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17Papers.csv index 8952391afc..2e560cfe0d 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17Papers.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx17Papers.csv @@ -35,7 +35,7 @@ "`P0185R1 `__","LWG","Adding [nothrow-]swappable traits","Jacksonville","|Complete|","3.9" "`P0253R1 `__","LWG","Fixing a design mistake in the searchers interface","Jacksonville","|Complete|","3.9" "`P0025R0 `__","LWG","An algorithm to ""clamp"" a value between a pair of boundary values","Jacksonville","|Complete|","3.9" -"`P0154R1 `__","LWG","constexpr std::hardware_{constructive,destructive}_interference_size","Jacksonville","|Partial| [#note-P0154]_","15.0" +"`P0154R1 `__","LWG","constexpr std::hardware_{constructive,destructive}_interference_size","Jacksonville","|Complete| [#note-P0154]_","19.0" "`P0030R1 `__","LWG","Proposal to Introduce a 3-Argument Overload to std::hypot","Jacksonville","|Complete|","3.9" "`P0031R0 `__","LWG","A Proposal to Add Constexpr Modifiers to reverse_iterator, move_iterator, array and Range Access","Jacksonville","|Complete|","4.0" "`P0272R1 `__","LWG","Give ``std::string``\ a non-const ``.data()``\ member function","Jacksonville","|Complete|","3.9" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20.rst b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20.rst index 2deb82547d..c00d6fb237 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20.rst @@ -47,7 +47,6 @@ Paper Status .. [#note-P0619] P0619: Only sections D.8, D.9, D.10 and D.13 are implemented. Sections D.4, D.7, D.11, and D.12 remain undone. .. [#note-P0883.1] P0883: shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet. .. [#note-P0883.2] P0883: ``ATOMIC_FLAG_INIT`` was marked deprecated in version 14.0, but was undeprecated with the implementation of LWG3659 in version 15.0. - .. [#note-P2231] P2231: Optional is complete. The changes to variant haven't been implemented yet. .. [#note-P0660] P0660: The paper is implemented but the features are experimental and can be enabled via ``-fexperimental-library``. .. [#note-P0355] P0355: The implementation status is: diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Issues.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Issues.csv index db57b15256..1a40a4472a 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Issues.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Issues.csv @@ -70,7 +70,7 @@ "`3041 `__","Unnecessary ``decay``\ in ``reference_wrapper``\ ","Jacksonville","|Complete|","" "`3042 `__","``is_literal_type_v``\ should be inline","Jacksonville","|Complete|","" "`3043 `__","Bogus postcondition for ``filesystem_error``\ constructor","Jacksonville","|Complete|","" -"`3045 `__","``atomic``\ doesn't have ``value_type``\ or ``difference_type``\ ","Jacksonville","","" +"`3045 `__","``atomic``\ doesn't have ``value_type``\ or ``difference_type``\ ","Jacksonville","|Complete|","18.0" "`3048 `__","``transform_reduce(exec, first1, last1, first2, init)``\ discards execution policy","Jacksonville","|Complete|","17.0" "`3051 `__","Floating point classifications were inadvertently changed in P0175","Jacksonville","|Nothing To Do|","" "`3075 `__","``basic_string``\ needs deduction guides from ``basic_string_view``\ ","Jacksonville","|Complete|","" @@ -162,12 +162,12 @@ "`3209 `__","Expression in ``year::ok()``\ returns clause is ill-formed","Cologne","|Complete|","" "","","","","","" "`3231 `__","``year_month_day_last::day``\ specification does not cover ``!ok()``\ values","Belfast","|Nothing To Do|","" -"`3225 `__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","Belfast","","","|chrono|" +"`3225 `__","``zoned_time``\ converting constructor shall not be ``noexcept``\ ","Belfast","|Complete|","19.0","|chrono|" "`3190 `__","``std::allocator::allocate``\ sometimes returns too little storage","Belfast","|Complete|","14.0" "`3218 `__","Modifier for ``%d``\ parse flag does not match POSIX and ``format``\ specification","Belfast","","","|chrono| |format|" -"`3224 `__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","Belfast","","","|chrono|" +"`3224 `__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","Belfast","|Complete|","19.0","|chrono|" "`3230 `__","Format specifier ``%y/%Y``\ is missing locale alternative versions","Belfast","|Complete|","16.0","|chrono| |format|" -"`3232 `__","Inconsistency in ``zoned_time``\ deduction guides","Belfast","","","|chrono|" +"`3232 `__","Inconsistency in ``zoned_time``\ deduction guides","Belfast","|Complete|","19.0","|chrono|" "`3222 `__","P0574R1 introduced preconditions on non-existent parameters","Belfast","","" "`3221 `__","Result of ``year_month``\ arithmetic with ``months``\ is ambiguous","Belfast","|Complete|","8.0" "`3235 `__","``parse``\ manipulator without abbreviation is not callable","Belfast","","" @@ -191,7 +191,7 @@ "","","","","","" "`1203 `__","More useful rvalue stream insertion","Prague","|Complete|","12.0" "`2859 `__","Definition of *reachable* in [ptr.launder] misses pointer arithmetic from pointer-interconvertible object","Prague","","" -"`3018 `__","``shared_ptr``\ of function type","Prague","","" +"`3018 `__","``shared_ptr``\ of function type","Prague","|Nothing To Do|","" "`3050 `__","Conversion specification problem in ``chrono::duration``\ constructor","Prague","|Complete|","19.0","|chrono|" "`3141 `__","``CopyConstructible``\ doesn't preserve source values","Prague","|Nothing to do|","" "`3150 `__","``UniformRandomBitGenerator``\ should validate ``min``\ and ``max``\ ","Prague","|Complete|","13.0","|ranges|" @@ -199,10 +199,10 @@ "`3194 `__","``ConvertibleTo``\ prose does not match code","Prague","|Complete|","13.0" "`3200 `__","``midpoint``\ should not constrain ``T``\ is complete","Prague","|Nothing To Do|","" "`3201 `__","``lerp``\ should be marked as ``noexcept``\ ","Prague","|Complete|","" -"`3226 `__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time``\ ","Prague","","","|chrono|" -"`3233 `__","Broken requirements for ``shared_ptr``\ converting constructors","Prague","","" +"`3226 `__","``zoned_time``\ constructor from ``string_view``\ should accept ``zoned_time``\ ","Prague","|Complete|","19.0","|chrono|" +"`3233 `__","Broken requirements for ``shared_ptr``\ converting constructors","Prague","|Complete|","19.0" "`3237 `__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","16.0" -"`3238 `__","Insufficiently-defined behavior of ``std::function``\ deduction guides","Prague","","" +"`3238 `__","Insufficiently-defined behavior of ``std::function``\ deduction guides","Prague","|Nothing To Do|","" "`3242 `__","``std::format``\ : missing rules for ``arg-id``\ in ``width``\ and ``precision``\ ","Prague","|Complete|","14.0","|format|" "`3243 `__","``std::format``\ and negative zeroes","Prague","|Complete|","14.0","|format|" "`3247 `__","``ranges::iter_move``\ should perform ADL-only lookup of ``iter_move``\ ","Prague","|Complete|","15.0","|ranges|" @@ -225,7 +225,7 @@ "`3286 `__","``ranges::size``\ is not required to be valid after a call to ``ranges::begin``\ on an input range","Prague","|Complete|","15.0","|ranges|" "`3291 `__","``iota_view::iterator``\ has the wrong ``iterator_category``\ ","Prague","|Complete|","15.0","|ranges|" "`3292 `__","``iota_view``\ is under-constrained","Prague","|Complete|","15.0","|ranges|" -"`3294 `__","``zoned_time``\ deduction guides misinterprets ``string``\ /``char*``\ ","Prague","","","|chrono|" +"`3294 `__","``zoned_time``\ deduction guides misinterprets ``string``\ /``char*``\ ","Prague","|Complete|","19.0","|chrono|" "`3296 `__","Inconsistent default argument for ``basic_regex<>::assign``\ ","Prague","|Complete|","" "`3299 `__","Pointers don't need customized iterator behavior","Prague","|Complete|","15.0","|ranges|" "`3300 `__","Non-array ``ssize``\ overload is underconstrained","Prague","|Nothing To Do|","" @@ -269,7 +269,7 @@ "`3355 `__","The memory algorithms should support move-only input iterators introduced by P1207","Prague","|Complete|","15.0","|ranges|" "`3356 `__","``__cpp_lib_nothrow_convertible``\ should be ``__cpp_lib_is_nothrow_convertible``\ ","Prague","|Complete|","12.0" "`3358 `__","|sect|\ [span.cons] is mistaken that ``to_address``\ can throw","Prague","|Complete|","17.0" -"`3359 `__","````\ leap second support should allow for negative leap seconds","Prague","|Complete|","19.0","|chrono|" +"`3359 `__","````\ leap second support should allow for negative leap seconds","Prague","|In Progress|","","|chrono|" "`3360 `__","``three_way_comparable_with``\ is inconsistent with similar concepts","Prague","|Nothing To Do|","","|spaceship|" "`3362 `__","Strike ``stop_source``\ 's ``operator!=``\ ","Prague","","" "`3363 `__","``drop_while_view``\ should opt-out of ``sized_range``\ ","Prague","|Nothing To Do|","","|ranges|" @@ -285,7 +285,7 @@ "`3379 `__","""``safe``\ "" in several library names is misleading","Prague","|Complete|","15.0","|ranges|" "`3380 `__","``common_type``\ and comparison categories","Prague","|Complete|","15.0","|spaceship|" "`3381 `__","``begin``\ and ``data``\ must agree for ``contiguous_range``\ ","Prague","|Nothing To Do|","","|ranges|" -"`3382 `__","NTTP for ``pair``\ and ``array``\ ","Prague","","" +"`3382 `__","NTTP for ``pair``\ and ``array``\ ","Prague","|Nothing To Do|","" "`3383 `__","|sect|\ [time.zone.leap.nonmembers] ``sys_seconds``\ should be replaced with ``seconds``\ ","Prague","|Complete|","19.0","|chrono|" "`3384 `__","``transform_view::*sentinel*``\ has an incorrect ``operator-``\ ","Prague","|Complete|","15.0","|ranges|" "`3385 `__","``common_iterator``\ is not sufficiently constrained for non-copyable iterators","Prague","|Complete|","15.0","|ranges|" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Papers.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Papers.csv index 77078b11a7..34fc5586f7 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Papers.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx20Papers.csv @@ -23,10 +23,10 @@ "`P0754R2 `__","LWG","","Jacksonville","|Complete|","7.0" "`P0809R0 `__","LWG","Comparing Unordered Containers","Jacksonville","|Nothing To Do|","" "`P0858R0 `__","LWG","Constexpr iterator requirements","Jacksonville","|Complete|","12.0" -"`P0905R1 `__","CWG","Symmetry for spaceship","Jacksonville","","","|spaceship|" +"`P0905R1 `__","CWG","Symmetry for spaceship","Jacksonville","|Complete|","7.0","|spaceship|" "`P0966R1 `__","LWG","``string::reserve``\ Should Not Shrink","Jacksonville","|Complete| [#note-P0966]_","12.0" "","","","","","","" -"`P0019R8 `__","LWG","Atomic Ref","Rapperswil","","" +"`P0019R8 `__","LWG","Atomic Ref","Rapperswil","|Complete|","19.0" "`P0458R2 `__","LWG","Checking for Existence of an Element in Associative Containers","Rapperswil","|Complete|","13.0" "`P0475R1 `__","LWG","LWG 2511: guaranteed copy elision for piecewise construction","Rapperswil","|Complete|","" "`P0476R2 `__","LWG","Bit-casting object representations","Rapperswil","|Complete|","14.0" @@ -78,7 +78,7 @@ "`P1236R1 `__","CWG","Alternative Wording for P0907R4 Signed Integers are Two's Complement","San Diego","* *","" "`P1248R1 `__","LWG","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","San Diego","|Complete|","13.0" "`P1285R0 `__","LWG","Improving Completeness Requirements for Type Traits","San Diego","* *","" -"`P1353R0 `__","CWG","Missing feature test macros","San Diego","* *","" +"`P1353R0 `__","CWG","Missing feature test macros","San Diego","|In Progress|","" "","","","","","","" "`P0339R6 `__","LWG","polymorphic_allocator<> as a vocabulary type","Kona","|Complete|","16.0" "`P0340R3 `__","LWG","Making std::underlying_type SFINAE-friendly","Kona","|Complete|","9.0" @@ -125,7 +125,7 @@ "`P1612R1 `__","LWG","Relocate Endian's Specification","Cologne","|Complete|","10.0" "`P1614R2 `__","LWG","The Mothership has Landed","Cologne","|In Progress|","" "`P1638R1 `__","LWG","basic_istream_view::iterator should not be copyable","Cologne","|Complete|","16.0","|ranges|" -"`P1643R1 `__","LWG","Add wait/notify to atomic_ref","Cologne","","" +"`P1643R1 `__","LWG","Add wait/notify to atomic_ref","Cologne","|Complete|","19.0" "`P1644R0 `__","LWG","Add wait/notify to atomic","Cologne","","" "`P1650R0 `__","LWG","Output std::chrono::days with 'd' suffix","Cologne","|Complete|","16.0" "`P1651R0 `__","LWG","bind_front should not unwrap reference_wrapper","Cologne","|Complete|","13.0" @@ -192,7 +192,7 @@ "`P2106R0 `__","LWG","Alternative wording for GB315 and GB316","Prague","|Complete|","15.0","|ranges|" "`P2116R0 `__","LWG","Remove tuple-like protocol support from fixed-extent span","Prague","|Complete|","11.0" "","","","","","","" -"`P2231R1 `__","LWG","Missing constexpr in std::optional and std::variant","June 2021","|Partial| [#note-P2231]_","13.0" +"`P2231R1 `__","LWG","Missing constexpr in std::optional and std::variant","June 2021","|Complete|","19.0" "`P2325R3 `__","LWG","Views should not be required to be default constructible","June 2021","|Complete|","16.0","|ranges|" "`P2210R2 `__","LWG","Superior String Splitting","June 2021","|Complete|","16.0","|ranges|" "`P2216R3 `__","LWG","std::format improvements","June 2021","|Complete|","15.0" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23.rst b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23.rst index b19ff4fdc0..23d30c8128 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23.rst @@ -43,7 +43,6 @@ Paper Status .. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented. .. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations. - .. [#note-P2387R3] P2387R3: ``bind_back`` only .. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well. .. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet. .. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet. diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Issues.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Issues.csv index a212d56685..cc601b3cd3 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Issues.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Issues.csv @@ -98,7 +98,7 @@ `3555 `__,"``{transform,elements}_view::iterator::iterator_concept`` should consider const-qualification of the underlying range","June 2021","","","|ranges|" "","","","","","" `2191 `__,"Incorrect specification of ``match_results(match_results&&)``","October 2021","|Nothing To Do|","" -`2381 `__,"Inconsistency in parsing floating point numbers","October 2021","","" +`2381 `__,"Inconsistency in parsing floating point numbers","October 2021","|Complete|","19.0" `2762 `__,"``unique_ptr operator*()`` should be ``noexcept``","October 2021","","" `3121 `__,"``tuple`` constructor constraints for ``UTypes&&...`` overloads","October 2021","","" `3123 `__,"``duration`` constructor from representation shouldn't be effectively non-throwing","October 2021","","","|chrono|" @@ -150,7 +150,7 @@ "`3619 `__","Specification of ``vformat_to`` contains ill-formed ``formatted_size`` calls","February 2022","|Nothing to do|","","|format|" "`3621 `__","Remove feature-test macro ``__cpp_lib_monadic_optional`` ","February 2022","|Complete|","15.0" "`3632 `__","``unique_ptr`` ""Mandates: This constructor is not selected by class template argument deduction""","February 2022","|Nothing to do|","" -"`3643 `__","Missing ``constexpr`` in ``std::counted_iterator`` ","February 2022","","","|ranges|" +"`3643 `__","Missing ``constexpr`` in ``std::counted_iterator`` ","February 2022","|Complete|","19.0","|ranges|" "`3648 `__","``format`` should not print ``bool`` with ``'c'`` ","February 2022","|Complete|","15.0","|format|" "`3649 `__","[fund.ts.v2] Reinstate and bump ``__cpp_lib_experimental_memory_resource`` feature test macro","February 2022","","" "`3650 `__","Are ``std::basic_string`` 's ``iterator`` and ``const_iterator`` constexpr iterators?","February 2022","|Nothing to do|","" @@ -165,7 +165,7 @@ "`3659 `__","Consider ``ATOMIC_FLAG_INIT`` undeprecation","July 2022","|Complete|","15.0" "`3670 `__","``Cpp17InputIterators`` don't have integer-class difference types","July 2022","","","|ranges|" "`3671 `__","``atomic_fetch_xor`` missing from ``stdatomic.h``","July 2022","","" -"`3672 `__","``common_iterator::operator->()`` should return by value","July 2022","","","|ranges|" +"`3672 `__","``common_iterator::operator->()`` should return by value","July 2022","|Complete|","19.0","|ranges|" "`3683 `__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","July 2022","","" "`3687 `__","``expected`` move constructor should move","July 2022","|Complete|","16.0" "`3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","July 2022","","","|ranges| |spaceship|" @@ -201,7 +201,7 @@ "`3677 `__","Is a cv-qualified ``pair`` specially handled in uses-allocator construction?", "November 2022","|Complete|","18.0","" "`3717 `__","``common_view::end`` should improve ``random_access_range`` case", "November 2022","","","|ranges|" "`3732 `__","``prepend_range`` and ``append_range`` can't be amortized constant time", "November 2022","|Nothing to do|","","|ranges|" -"`3736 `__","``move_iterator`` missing ``disable_sized_sentinel_for`` specialization", "November 2022","","","|ranges|" +"`3736 `__","``move_iterator`` missing ``disable_sized_sentinel_for`` specialization", "November 2022","|Complete|","19.0","|ranges|" "`3737 `__","``take_view::sentinel`` should provide ``operator-``", "November 2022","","","|ranges|" "`3738 `__","Missing preconditions for ``take_view`` constructor", "November 2022","|Complete|","16.0","|ranges|" "`3743 `__","``ranges::to``'s reserve may be ill-formed", "November 2022","","","|ranges|" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Papers.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Papers.csv index 065db97a0b..4f589cd938 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Papers.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx23Papers.csv @@ -45,7 +45,7 @@ "`P1413R3 `__","LWG","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","February 2022","|Complete| [#note-P1413R3]_","" "`P2255R2 `__","LWG","A type trait to detect reference binding to temporary","February 2022","","" "`P2273R3 `__","LWG","Making ``std::unique_ptr`` constexpr","February 2022","|Complete|","16.0" -"`P2387R3 `__","LWG","Pipe support for user-defined range adaptors","February 2022","|Partial| [#note-P2387R3]_","","|ranges|" +"`P2387R3 `__","LWG","Pipe support for user-defined range adaptors","February 2022","|Complete|","19.0","|ranges|" "`P2440R1 `__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","","","|ranges|" "`P2441R2 `__","LWG","``views::join_with``","February 2022","|In Progress|","","|ranges|" "`P2442R1 `__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","","|ranges|" @@ -59,7 +59,7 @@ "`P1467R9 `__","LWG","Extended ``floating-point`` types and standard names","July 2022","","" "`P1642R11 `__","LWG","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","July 2022","","" "`P1899R3 `__","LWG","``stride_view``","July 2022","","","|ranges|" -"`P2093R14 `__","LWG","Formatted output","July 2022","","|Complete|","18.0" +"`P2093R14 `__","LWG","Formatted output","July 2022","|Complete|","18.0","|format|" "`P2165R4 `__","LWG","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","July 2022","","" "`P2278R4 `__","LWG","``cbegin`` should always return a constant iterator","July 2022","","","|ranges|" "`P2286R8 `__","LWG","Formatting Ranges","July 2022","|Complete|","16.0","|format| |ranges|" @@ -75,7 +75,7 @@ "`P2445R1 `__","LWG","``forward_like``","July 2022","|Complete|","16.0" "`P2446R2 `__","LWG","``views::as_rvalue``","July 2022","|Complete|","16.0","|ranges|" "`P2460R2 `__","LWG","Relax requirements on ``wchar_t`` to match existing practices","July 2022","","" -"`P2465R3 `__","LWG","Standard Library Modules ``std`` and ``std.compat``","July 2022","","" +"`P2465R3 `__","LWG","Standard Library Modules ``std`` and ``std.compat``","July 2022","|Complete|","19.0","" "`P2467R1 `__","LWG","Support exclusive mode for ``fstreams``","July 2022","|Complete|","18.0","" "`P2474R2 `__","LWG","``views::repeat``","July 2022","|Complete|","17.0","|ranges|" "`P2494R2 `__","LWG","Relaxing range adaptors to allow for move only types","July 2022","|Complete|","17.0","|ranges|" @@ -108,7 +108,7 @@ "`P2164R9 `__","LWG", "``views::enumerate``","February 2023","","","|ranges|" "`P2711R1 `__","LWG", "Making multi-param constructors of ``views`` ``explicit``","February 2023","|In Progress| [#note-P2711R1]_","","|ranges|" "`P2609R3 `__","LWG", "Relaxing Ranges Just A Smidge","February 2023","","","|ranges|" -"`P2713R1 `__","LWG", "Escaping improvements in ``std::format``","February 2023","","","|format|" +"`P2713R1 `__","LWG", "Escaping improvements in ``std::format``","February 2023","|Complete|","19.0","|format|" "`P2675R1 `__","LWG", "``format``'s width estimation is too approximate and not forward compatible","February 2023","|Complete|","17.0","|format|" "`P2572R1 `__","LWG", "``std::format`` fill character allowances","February 2023","|Complete|","17.0","|format|" "`P2693R1 `__","LWG", "Formatting ``thread::id`` and ``stacktrace``","February 2023","|Partial| [#note-P2693R1]_","","|format|" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2c.rst b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2c.rst index a7ebc4662f..03a6eeaa40 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2c.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2c.rst @@ -40,6 +40,9 @@ Paper Status .. note:: .. [#note-P2510R3] This paper is applied as DR against C++20. (MSVC STL and libstdc++ will do the same.) + .. [#note-P3142R0] This paper is applied as DR against C++23. (MSVC STL and libstdc++ will do the same.) + .. [#note-P2944R3] Implemented comparisons for ``reference_wrapper`` only. + .. [#note-P2422R1] Libc++ keeps the ``nodiscard`` attributes as a conforming extension. .. _issues-status-cxx2c: diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cIssues.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cIssues.csv index 008f7418ab..f9a70aee1b 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cIssues.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cIssues.csv @@ -29,10 +29,10 @@ "`3947 `__","Unexpected constraints on ``adjacent_transform_view::base()``","Kona November 2023","","","|ranges|" "`3948 `__","``possibly-const-range and as-const-pointer`` should be ``noexcept``","Kona November 2023","","","|ranges|" "`3949 `__","``std::atomic``'s trivial destructor dropped in C++17 spec wording","Kona November 2023","","","" -"`3951 `__","[expected.object.swap]: Using ``value()`` instead of ``has_value()``","Kona November 2023","","","" +"`3951 `__","[expected.object.swap]: Using ``value()`` instead of ``has_value()``","Kona November 2023","|Complete|","16.0","" "`3953 `__","``iter_move`` for ``common_iterator`` and ``counted_iterator`` should return ``decltype(auto)``","Kona November 2023","","","|ranges|" "`3957 `__","[container.alloc.reqmts] The value category of v should be claimed","Kona November 2023","","","" -"`3965 `__","Incorrect example in [format.string.escaped] p3 for formatting of combining characters","Kona November 2023","","","|format|" +"`3965 `__","Incorrect example in [format.string.escaped] p3 for formatting of combining characters","Kona November 2023","|Complete|","19.0","|format|" "`3970 `__","[mdspan.syn] Missing definition of ``full_extent_t`` and ``full_extent``","Kona November 2023","","","" "`3973 `__","Monadic operations should be ADL-proof","Kona November 2023","","","" "`3974 `__","``mdspan::operator[]`` should not copy ``OtherIndexTypes``","Kona November 2023","","","" @@ -44,24 +44,38 @@ "`3919 `__","``enumerate_view`` may invoke UB for sized common non-forward underlying ranges","Tokyo March 2024","","","|ranges|" "`3950 `__","``std::basic_string_view`` comparison operators are overspecified","Tokyo March 2024","|Complete|","18.0","" "`3975 `__","Specializations of ``basic_format_context`` should not be permitted","Tokyo March 2024","|Nothing To Do|","","|format|" -"`3984 `__","``ranges::to``'s recursion branch may be ill-formed","Tokyo March 2024","","","|ranges|" +"`3984 `__","``ranges::to``'s recursion branch may be ill-formed","Tokyo March 2024","|Complete|","19.0","|ranges|" "`4011 `__","``""Effects: Equivalent to return""`` in ``[span.elem]``","Tokyo March 2024","|Nothing To Do|","","" "`4012 `__","``common_view::begin/end`` are missing the ``simple-view`` check","Tokyo March 2024","","","|ranges|" "`4013 `__","``lazy_split_view::outer-iterator::value_type`` should not provide default constructor","Tokyo March 2024","","","|ranges|" "`4016 `__","container-insertable checks do not match what container-inserter does","Tokyo March 2024","","","" -"`4023 `__","Preconditions of ``std::basic_streambuf::setg/setp``","Tokyo March 2024","","","" +"`4023 `__","Preconditions of ``std::basic_streambuf::setg/setp``","Tokyo March 2024","|Complete|","19.0","" "`4025 `__","Move assignment operator of ``std::expected`` should not be conditionally deleted","Tokyo March 2024","","","" "`4030 `__","Clarify whether arithmetic expressions in ``[numeric.sat.func]`` are mathematical or C++","Tokyo March 2024","|Nothing To Do|","","" "`4031 `__","``bad_expected_access`` member functions should be ``noexcept``","Tokyo March 2024","|Complete|","16.0","" -"`4035 `__","``single_view`` should provide ``empty``","Tokyo March 2024","","","|ranges|" +"`4035 `__","``single_view`` should provide ``empty``","Tokyo March 2024","|Complete|","19.0","|ranges|" "`4036 `__","``__alignof_is_defined`` is only implicitly specified in C++ and not yet deprecated","Tokyo March 2024","","","" "`4037 `__","Static data members of ``ctype_base`` are not yet required to be usable in constant expressions","Tokyo March 2024","","","" "`4038 `__","``std::text_encoding::aliases_view`` should have constexpr iterators","Tokyo March 2024","","","" "`4043 `__","""ASCII"" is not a registered character encoding","Tokyo March 2024","|Nothing To Do|","","" "`4045 `__","``tuple`` can create dangling references from ``tuple-like``","Tokyo March 2024","","","" -"`4053 `__","Unary call to ``std::views::repeat`` does not decay the argument","Tokyo March 2024","","","|ranges|" -"`4054 `__","Repeating a ``repeat_view`` should repeat the view","Tokyo March 2024","","","|ranges|" +"`4053 `__","Unary call to ``std::views::repeat`` does not decay the argument","Tokyo March 2024","|Complete|","19.0","|ranges|" +"`4054 `__","Repeating a ``repeat_view`` should repeat the view","Tokyo March 2024","|Complete|","19.0","|ranges|" +"","","","","","" +"`3944 `__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","St. Louis June 2024","","","|format|" +"`4060 `__","``submdspan`` preconditions do not forbid creating invalid pointer","St. Louis June 2024","","","" +"`4061 `__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","St. Louis June 2024","|Complete|","19.0","|format|" +"`4071 `__","``reference_wrapper`` comparisons are not SFINAE-friendly","St. Louis June 2024","|Complete|","19.0","" +"`4074 `__","``compatible-joinable-ranges`` is underconstrained","St. Louis June 2024","","","|ranges|" +"`4076 `__","``concat_view`` should be freestanding","St. Louis June 2024","","","" +"`4079 `__","Missing Preconditions in ``concat_view::iterator``\`s conversion constructor","St. Louis June 2024","","","|ranges|" +"`4082 `__","``views::concat(r)`` is well-formed when ``r`` is an ``output_range``","St. Louis June 2024","","","|ranges|" +"`4083 `__","``views::as_rvalue`` should reject non-input ranges","St. Louis June 2024","","","|ranges|" +"`4096 `__","``views::iota(views::iota(0))`` should be rejected","St. Louis June 2024","","","|ranges|" +"`4098 `__","``views::adjacent<0>`` should reject non-forward ranges","St. Louis June 2024","","","|ranges|" +"`4105 `__","``ranges::ends_with``\`s Returns misses difference casting","St. Louis June 2024","","","|ranges|" +"`4106 `__","``basic_format_args`` should not be default-constructible","St. Louis June 2024","|Complete|","19.0","|format|" "","","","","","" "`3343 `__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Yet Adopted","|Complete|","16.0","" -"XXXX","","The sys_info range should be affected by save","Not Yet Adopted","|Complete|","19.0" +"XXXX","The sys_info range should be affected by save","Not Yet Adopted","|Complete|","19.0" "","","","","","" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cPapers.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cPapers.csv index fa11da62bc..2c498f336b 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cPapers.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/Cxx2cPapers.csv @@ -51,7 +51,7 @@ "`P2869R4 `__","LWG","Remove Deprecated ``shared_ptr`` Atomic Access APIs from C++26","Tokyo March 2024","","","" "`P2872R3 `__","LWG","Remove ``wstring_convert`` From C++26","Tokyo March 2024","|Complete|","19.0","" "`P3107R5 `__","LWG","Permit an efficient implementation of ``std::print``","Tokyo March 2024","","","|format| |DR|" -"`P3142R0 `__","LWG","Printing Blank Lines with ``println``","Tokyo March 2024","|Complete|","19.0","|format|" +"`P3142R0 `__","LWG","Printing Blank Lines with ``println``","Tokyo March 2024","|Complete| [#note-P3142R0]_","19.0","|format|" "`P2845R8 `__","LWG","Formatting of ``std::filesystem::path``","Tokyo March 2024","","","|format|" "`P0493R5 `__","LWG","Atomic minimum/maximum","Tokyo March 2024","","","" "`P2542R8 `__","LWG","``views::concat``","Tokyo March 2024","","","|ranges|" @@ -59,7 +59,20 @@ "`P2248R8 `__","LWG","Enabling list-initialization for algorithms","Tokyo March 2024","","","" "`P2810R4 `__","LWG","``is_debugger_present`` ``is_replaceable``","Tokyo March 2024","","","" "`P1068R11 `__","LWG","Vector API for random number generation","Tokyo March 2024","","","" -"`P2944R3 `__","LWG","Comparisons for ``reference_wrapper``","Tokyo March 2024","","","" +"`P2944R3 `__","LWG","Comparisons for ``reference_wrapper``","Tokyo March 2024","|Partial| [#note-P2944R3]_","19.0","" "`P2642R6 `__","LWG","Padded ``mdspan`` layouts","Tokyo March 2024","","","" -"`P3029R1 `__","LWG","Better ``mdspan``'s CTAD","Tokyo March 2024","","","" +"`P3029R1 `__","LWG","Better ``mdspan``'s CTAD","Tokyo March 2024","|Complete|","19.0","" +"","","","","","","" +"`P2747R2 `__","CWG","``constexpr`` placement new","St. Louis June 2024","","","" +"`P2997R1 `__","LWG","Removing the common reference requirement from the indirectly invocable concepts","St. Louis June 2024","","","" +"`P2389R2 `__","LWG","``dextents`` Index Type Parameter","St. Louis June 2024","|Complete|","19.0","" +"`P3168R2 `__","LWG","Give ``std::optional`` Range Support","St. Louis June 2024","","","|ranges|" +"`P3217R0 `__","LWG","Adjoints to 'Enabling list-initialization for algorithms': find_last","St. Louis June 2024","","","" +"`P2985R0 `__","LWG","A type trait for detecting virtual base classes","St. Louis June 2024","","","" +"`P0843R14 `__","LWG","``inplace_vector``","St. Louis June 2024","","","" +"`P3235R3 `__","LWG","``std::print`` more types faster with less memory","St. Louis June 2024","","","|format| |DR|" +"`P2968R2 `__","LWG","Make ``std::ignore`` a first-class object","St. Louis June 2024","|Complete|","19.0","" +"`P2075R6 `__","LWG","Philox as an extension of the C++ RNG engines","St. Louis June 2024","","","" +"`P2422R1 `__","LWG","Remove ``nodiscard`` annotations from the standard library specification","St. Louis June 2024","|Complete| [#note-P2422R1]_","19.0","" +"`P2300R10 `__","LWG","``std::execution``","St. Louis June 2024","","","" "","","","","","","" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/FormatIssues.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/FormatIssues.csv index 7da77def92..3780c1ed5c 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/FormatIssues.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/FormatIssues.csv @@ -10,7 +10,7 @@ Number,Name,Standard,Assignee,Status,First released version "`P2508R1 `__","Exposing ``std::basic-format-string``","C++23","Mark de Wever","|Complete|",15.0 "`P2585R0 `__","Improving default container formatting","C++23","Mark de Wever","|Complete|",17.0 "`P2539R4 `__","Should the output of ``std::print`` to a terminal be synchronized with the underlying stream?","C++23","Mark de Wever","|Complete|","18.0" -"`P2713R1 `__","Escaping improvements in ``std::format``","C++23","Mark de Wever","" +"`P2713R1 `__","Escaping improvements in ``std::format``","C++23","Mark de Wever","|Complete|",19.0 "`P2675R1 `__","``format``'s width estimation is too approximate and not forward compatible","C++23","Mark de Wever","|Complete|",17.0 "`P2572R1 `__","``std::format`` fill character allowances","C++23","Mark de Wever","|Complete|",17.0 "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``","C++23","Mark de Wever","|In Progress|" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/FormatPaper.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/FormatPaper.csv index e9d407e79e..f29f1f7ca7 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/FormatPaper.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/FormatPaper.csv @@ -24,8 +24,8 @@ Section,Description,Dependencies,Assignee,Status,First released version `[time.syn] `_,"Formatter ``chrono::year_month_weekday``",,Mark de Wever,|Complete|,16.0 `[time.syn] `_,"Formatter ``chrono::year_month_weekday_last``",,Mark de Wever,|Complete|,16.0 `[time.syn] `_,"Formatter ``chrono::hh_mm_ss>``",,Mark de Wever,|Complete|,17.0 -`[time.syn] `_,"Formatter ``chrono::sys_info``",A ```` implementation,Mark de Wever,, -`[time.syn] `_,"Formatter ``chrono::local_info``",A ```` implementation,Mark de Wever,, +`[time.syn] `_,"Formatter ``chrono::sys_info``",,Mark de Wever,|Complete|,19.0 +`[time.syn] `_,"Formatter ``chrono::local_info``",,Mark de Wever,|Complete|,19.0 `[time.syn] `_,"Formatter ``chrono::zoned_time``",A ```` implementation,Mark de Wever,, "`P2693R1 `__","Formatting ``thread::id`` and ``stacktrace``" diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/ParallelismProjects.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/ParallelismProjects.csv index 06da008ac5..06087e3d87 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/ParallelismProjects.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/ParallelismProjects.csv @@ -16,6 +16,7 @@ Section,Description,Dependencies,Assignee,Complete | `[parallel.simd.whereexpr] `_, "Where expression class templates", None, Yin Zhang, |In Progress| | `[parallel.simd.reference] `_, "`Element references operator value_type() `_", None, Yin Zhang, |Complete| | `[parallel.simd.reference] `_, "`Element references operator= `_", None, Yin Zhang, |Complete| +| `[parallel.simd.reference] `_, "`Element references swap functions `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`Class template simd declaration and alias `_", [parallel.simd.abi], Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd<>::size() `_", [parallel.simd.traits] simd_size[_v], Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd default constructor `_", None, Yin Zhang, |Complete| @@ -24,6 +25,7 @@ Section,Description,Dependencies,Assignee,Complete | `[parallel.simd.class] `_, "`simd generate constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd load constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd subscript operators `_", None, Yin Zhang, |Complete| +| `[parallel.simd.class] `_, "`simd copy functions `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "Class template simd implementation", None, Yin Zhang, |In Progress| | `[parallel.simd.nonmembers] `_, "simd non-member operations", None, Yin Zhang, |In Progress| | `[parallel.simd.mask.class] `_, "`Class template simd_mask declaration and alias `_", [parallel.simd.abi], Yin Zhang, |Complete| @@ -33,5 +35,6 @@ Section,Description,Dependencies,Assignee,Complete | `[parallel.simd.mask.class] `_, "`simd_mask implicit type conversion constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "`simd_mask load constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "`simd_mask subscript operators `_", None, Yin Zhang, |Complete| +| `[parallel.simd.mask.class] `_, "`simd_mask copy functions `_", None, Yin Zhang, |Complete| | `[parallel.simd.mask.class] `_, "Class template simd_mask implementation", None, Yin Zhang, |In Progress| | `[parallel.simd.mask.nonmembers] `_, "simd_mask non-member operations", None, Yin Zhang, |In Progress| diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/RangesMajorFeatures.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/RangesMajorFeatures.csv index c0bec8d924..d00fbce9ed 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/RangesMajorFeatures.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/RangesMajorFeatures.csv @@ -1,5 +1,5 @@ Standard,Name,Assignee,CL,Status C++23,`ranges::to `_,Konstantin Varlamov,`D142335 `_,Complete -C++23,`Pipe support for user-defined range adaptors `_,Unassigned,No patch yet,Not started +C++23,`Pipe support for user-defined range adaptors `_,"Louis Dionne, Jakub Mazurkiewicz, and Xiaoyang Liu",Various,Complete C++23,`Formatting Ranges `_,Mark de Wever,Various,Complete C++20,`Stashing stashing iterators for proper flattening `_,Jakub Mazurkiewicz,Various,In progress diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/SpaceshipPapers.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/SpaceshipPapers.csv index 21b788ee42..39e1f968c1 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/SpaceshipPapers.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/SpaceshipPapers.csv @@ -7,6 +7,6 @@ `LWG3360 `_,``three_way_comparable_with`` is inconsistent with similar concepts,|Nothing To Do|, `LWG3380 `_,``common_type`` and comparison categories,|Nothing To Do|, `LWG3395 `_,Definition for *three-way* comparison needs to be updated,|Nothing To Do|, -`P0905R1 `_,Symmetry for spaceship,, +`P0905R1 `_,Symmetry for spaceship,|Complete|,7.0 `P1120R0 `_,Consistency improvements for ``<=>`` and other comparison operators,, `LWG3431 `_,``<=>`` for containers should require ``three_way_comparable`` instead of ``<=>``,, diff --git a/naiveproxy/src/third_party/libc++/src/docs/Status/SpaceshipProjects.csv b/naiveproxy/src/third_party/libc++/src/docs/Status/SpaceshipProjects.csv index 3d14f487d9..e1cf2044cf 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/Status/SpaceshipProjects.csv +++ b/naiveproxy/src/third_party/libc++/src/docs/Status/SpaceshipProjects.csv @@ -67,7 +67,7 @@ Section,Description,Dependencies,Assignee,Complete | `[func.wrap.func] `_ | `[func.wrap.func.nullptr] `_",| remove ops `function `_,None,Hristo Hristov,|Complete| | `[meta.unary.prop] `_,| replaced by `issue LWG3354 `_,None,Unassigned,|Nothing To Do| -| `[meta.trans.other] `_,|,None,Unassigned,|Not Started| +| `[meta.trans.other] `_,| removed by `issue LWG3380 `_,None,Unassigned,|Nothing To Do| "| `[type.index.overview] `_ | `[type.index.members] `_",| `type_index `_,None,Adrian Vogelsgesang,|Complete| | `[charconv.syn] `_,| `to_chars_result `_,None,Mark de Wever,|Complete| @@ -140,7 +140,7 @@ Section,Description,Dependencies,Assignee,Complete "| `[class.slice.overview] `_ | `[slice.ops] `_",| `slice `_,None,Hristo Hristov,|Complete| - `5.12 Clause 27: Time library `_,,,, -| `[time.syn] `_,|,None,Mark de Wever,|In Progress| +| `[time.syn] `_,|,None,Mark de Wever,|Complete| | `[time.duration.comparisons] `_, `chrono::duration `_, None, Hristo Hristov, |Complete| | `[time.point.comparisons] `_, `chrono::time_point `_, None, Hristo Hristov, |Complete| "| `[time.cal.day.nonmembers] `_ @@ -171,10 +171,10 @@ Section,Description,Dependencies,Assignee,Complete | `month_weekday_last `_ | `year_month_weekday `_ | `year_month_weekday_last `_",None,Hristo Hristov,|Complete| -`[time.zone.nonmembers] `_,"`chrono::time_zone`",A ```` implementation,Mark de Wever,|Complete| -`[time.zone.zonedtime.nonmembers] `_,"`chrono::zoned_time`",A ```` implementation,Mark de Wever,|In Progress| -`[time.zone.leap.nonmembers] `_,"`chrono::time_leap_seconds`",A ```` implementation,Mark de Wever,|Complete| -`[time.zone.link.nonmembers] `_,"`chrono::time_zone_link`",A ```` implementation,Mark de Wever,|Complete| +`[time.zone.nonmembers] `_,"`chrono::time_zone`",,Mark de Wever,|Complete| +`[time.zone.zonedtime.nonmembers] `_,"`chrono::zoned_time`",,Mark de Wever,|Complete| +`[time.zone.leap.nonmembers] `_,"`chrono::time_leap_seconds`",,Mark de Wever,|Complete| +`[time.zone.link.nonmembers] `_,"`chrono::time_zone_link`",,Mark de Wever,|Complete| - `5.13 Clause 28: Localization library `_,,,, "| `[locale] `_ | `[locale.operators] `_",| remove ops `locale `_,None,Hristo Hristov,|Complete| diff --git a/naiveproxy/src/third_party/libc++/src/docs/TestingLibcxx.rst b/naiveproxy/src/third_party/libc++/src/docs/TestingLibcxx.rst index 50ee9d4ee4..d9f4fe467f 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/TestingLibcxx.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/TestingLibcxx.rst @@ -480,3 +480,48 @@ For example: $ ./algorithms.libcxx.out --benchmark_filter=BM_Sort.* # Only runs the sort benchmarks For more information about running benchmarks see `Google Benchmark`_. + + +.. _testing-hardening-assertions: + +Testing hardening assertions +============================ + +Each hardening assertion should be tested using death tests (via the +``TEST_LIBCPP_ASSERT_FAILURE`` macro). Use the ``libcpp-hardening-mode`` Lit +feature to make sure the assertion is enabled in (and only in) the intended +modes. The convention is to use `assert.` in the name of the test file to make +it easier to identify as a hardening test, e.g. ``assert.my_func.pass.cpp``. +A toy example: + +.. code-block:: cpp + + // Note: the following three annotations are currently needed to use the + // `TEST_LIBCPP_ASSERT_FAILURE`. + // REQUIRES: has-unix-headers + // UNSUPPORTED: c++03 + // XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + + // Example: only run this test in `fast`/`extensive`/`debug` modes. + // UNSUPPORTED: libcpp-hardening-mode=none + // Example: only run this test in the `debug` mode. + // REQUIRES: libcpp-hardening-mode=debug + // Example: only run this test in `extensive`/`debug` modes. + // REQUIRES: libcpp-hardening-mode={{extensive|debug}} + + #include + + #include "check_assertion.h" // Contains the `TEST_LIBCPP_ASSERT_FAILURE` macro + + int main(int, char**) { + std::type_being_tested foo; + int bad_input = -1; + TEST_LIBCPP_ASSERT_FAILURE(foo.some_function_that_asserts(bad_input), + "The expected assertion message"); + + return 0; + } + +Note that error messages are only tested (matched) if the ``debug`` +hardening mode is used. + diff --git a/naiveproxy/src/third_party/libc++/src/docs/UsingLibcxx.rst b/naiveproxy/src/third_party/libc++/src/docs/UsingLibcxx.rst index bc7817d14d..df08875c13 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/UsingLibcxx.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/UsingLibcxx.rst @@ -167,15 +167,6 @@ safety annotations. build of libc++ which does not export any symbols, which can be useful when building statically for inclusion into another library. -**_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS**: - This macro disables the additional diagnostics generated by libc++ using the - `diagnose_if` attribute. These additional diagnostics include checks for: - - * Giving `set`, `map`, `multiset`, `multimap` and their `unordered_` - counterparts a comparator which is not const callable. - * Giving an unordered associative container a hasher that is not const - callable. - **_LIBCPP_NO_VCRUNTIME**: Microsoft's C and C++ headers are fairly entangled, and some of their C++ headers are fairly hard to avoid. In particular, `vcruntime_new.h` gets pulled @@ -196,10 +187,6 @@ safety annotations. replacement scenarios from working, e.g. replacing `operator new` and expecting a non-replaced `operator new[]` to call the replaced `operator new`. -**_LIBCPP_DISABLE_NODISCARD_EXT**: - This macro disables library-extensions of ``[[nodiscard]]``. - See :ref:`Extended Applications of [[nodiscard]] ` for more information. - **_LIBCPP_DISABLE_DEPRECATION_WARNINGS**: This macro disables warnings when using deprecated components. For example, using `std::auto_ptr` when compiling in C++11 mode will normally trigger a @@ -208,12 +195,6 @@ safety annotations. C++17 Specific Configuration Macros ----------------------------------- -**_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES**: - This macro is used to re-enable all the features removed in C++17. The effect - is equivalent to manually defining each macro listed below. - This macro is deprecated and will be removed in LLVM-19. Use the - individual macros listed below. - **_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR**: This macro is used to re-enable `auto_ptr`. @@ -238,12 +219,6 @@ C++20 Specific Configuration Macros This macro is used to re-enable the function ``std::shared_ptr<...>::unique()``. -**_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES**: - This macro is used to re-enable all the features removed in C++20. The effect - is equivalent to manually defining each macro listed below. - This macro is deprecated and will be removed in LLVM-19. Use the - individual macros listed below. - **_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS**: This macro is used to re-enable the `argument_type`, `result_type`, `first_argument_type`, and `second_argument_type` members of class @@ -287,29 +262,6 @@ Libc++ Extensions This section documents various extensions provided by libc++, how they're provided, and any information regarding how to use them. -.. _nodiscard extension: - -Extended applications of ``[[nodiscard]]`` ------------------------------------------- - -The ``[[nodiscard]]`` attribute is intended to help users find bugs where -function return values are ignored when they shouldn't be. After C++17 the -C++ standard has started to declared such library functions as ``[[nodiscard]]``. -However, this application is limited and applies only to dialects after C++17. -Users who want help diagnosing misuses of STL functions may desire a more -liberal application of ``[[nodiscard]]``. - -For this reason libc++ provides an extension that does just that! The -extension is enabled by default and can be disabled by defining ``_LIBCPP_DISABLE_NODISCARD_EXT``. -The extended applications of ``[[nodiscard]]`` takes two forms: - -1. Backporting ``[[nodiscard]]`` to entities declared as such by the - standard in newer dialects, but not in the present one. - -2. Extended applications of ``[[nodiscard]]``, at the library's discretion, - applied to entities never declared as such by the standard. You can find - all such applications by grepping for ``_LIBCPP_NODISCARD_EXT``. - Extended integral type support ------------------------------ diff --git a/naiveproxy/src/third_party/libc++/src/docs/index.rst b/naiveproxy/src/third_party/libc++/src/docs/index.rst index 743f99297d..69a9e575cf 100644 --- a/naiveproxy/src/third_party/libc++/src/docs/index.rst +++ b/naiveproxy/src/third_party/libc++/src/docs/index.rst @@ -71,7 +71,7 @@ iOS, watchOS, and tvOS, Google Search, the Android operating system, and FreeBSD user base of over 1 billion daily active users. Since its inception, libc++ has focused on delivering high performance, standards-conformance, and portability. It has -been extensively tested and optimized, making it robust and production ready. libc++ fully implements C++11 and C++14, +been extensively tested and optimized, making it robust and production ready. libc++ fully implements C++11 and C++14, with C++17, C++20, C++23, and C++26 features being actively developed and making steady progress. libc++ is continuously integrated and tested on a wide range of platforms and configurations, ensuring its reliability @@ -137,7 +137,7 @@ Compiler Versions Restrictions Support policy Clang 17, 18, 19-git latest two stable releases per `LLVM's release page `_ and the development version AppleClang 15 latest stable release per `Xcode's release page `_ Open XL 17.1 (AIX) latest stable release per `Open XL's documentation page `_ -GCC 13 In C++11 or later only latest stable release per `GCC's release page `_ +GCC 14 In C++11 or later only latest stable release per `GCC's release page `_ ============ =============== ========================== ===================== Libc++ also supports common platforms and architectures: diff --git a/naiveproxy/src/third_party/libc++/src/include/CMakeLists.txt b/naiveproxy/src/third_party/libc++/src/include/CMakeLists.txt index d4e8c196a9..cd64fe9144 100644 --- a/naiveproxy/src/third_party/libc++/src/include/CMakeLists.txt +++ b/naiveproxy/src/third_party/libc++/src/include/CMakeLists.txt @@ -72,37 +72,7 @@ set(files __algorithm/partition_point.h __algorithm/pop_heap.h __algorithm/prev_permutation.h - __algorithm/pstl_any_all_none_of.h - __algorithm/pstl_backend.h - __algorithm/pstl_backends/cpu_backend.h - __algorithm/pstl_backends/cpu_backends/any_of.h - __algorithm/pstl_backends/cpu_backends/backend.h - __algorithm/pstl_backends/cpu_backends/fill.h - __algorithm/pstl_backends/cpu_backends/find_if.h - __algorithm/pstl_backends/cpu_backends/for_each.h - __algorithm/pstl_backends/cpu_backends/libdispatch.h - __algorithm/pstl_backends/cpu_backends/merge.h - __algorithm/pstl_backends/cpu_backends/serial.h - __algorithm/pstl_backends/cpu_backends/stable_sort.h - __algorithm/pstl_backends/cpu_backends/thread.h - __algorithm/pstl_backends/cpu_backends/transform.h - __algorithm/pstl_backends/cpu_backends/transform_reduce.h - __algorithm/pstl_copy.h - __algorithm/pstl_count.h - __algorithm/pstl_equal.h - __algorithm/pstl_fill.h - __algorithm/pstl_find.h - __algorithm/pstl_for_each.h - __algorithm/pstl_frontend_dispatch.h - __algorithm/pstl_generate.h - __algorithm/pstl_is_partitioned.h - __algorithm/pstl_merge.h - __algorithm/pstl_move.h - __algorithm/pstl_replace.h - __algorithm/pstl_rotate_copy.h - __algorithm/pstl_sort.h - __algorithm/pstl_stable_sort.h - __algorithm/pstl_transform.h + __algorithm/pstl.h __algorithm/push_heap.h __algorithm/ranges_adjacent_find.h __algorithm/ranges_all_of.h @@ -238,6 +208,7 @@ set(files __atomic/atomic_flag.h __atomic/atomic_init.h __atomic/atomic_lock_free.h + __atomic/atomic_ref.h __atomic/atomic_sync.h __atomic/check_memory_order.h __atomic/contention_t.h @@ -246,7 +217,7 @@ set(files __atomic/is_always_lock_free.h __atomic/kill_dependency.h __atomic/memory_order.h - __availability + __atomic/to_gcc_order.h __bit/bit_cast.h __bit/bit_ceil.h __bit/bit_floor.h @@ -278,12 +249,14 @@ set(files __chrono/convert_to_tm.h __chrono/day.h __chrono/duration.h + __chrono/exception.h __chrono/file_clock.h __chrono/formatter.h __chrono/hh_mm_ss.h __chrono/high_resolution_clock.h __chrono/leap_second.h __chrono/literals.h + __chrono/local_info.h __chrono/month.h __chrono/month_weekday.h __chrono/monthday.h @@ -303,6 +276,7 @@ set(files __chrono/year_month.h __chrono/year_month_day.h __chrono/year_month_weekday.h + __chrono/zoned_time.h __compare/common_comparison_category.h __compare/compare_partial_order_fallback.h __compare/compare_strong_order_fallback.h @@ -340,11 +314,17 @@ set(files __concepts/totally_ordered.h __condition_variable/condition_variable.h __config + __configuration/abi.h + __configuration/availability.h + __configuration/compiler.h + __configuration/language.h + __configuration/platform.h __coroutine/coroutine_handle.h __coroutine/coroutine_traits.h __coroutine/noop_coroutine_handle.h __coroutine/trivial_awaitables.h __debug_utils/randomize_range.h + __debug_utils/sanitizers.h __debug_utils/strict_weak_ordering_check.h __exception/exception.h __exception/exception_ptr.h @@ -458,6 +438,7 @@ set(files __ios/fpos.h __iterator/access.h __iterator/advance.h + __iterator/aliasing_iterator.h __iterator/back_insert_iterator.h __iterator/bounded_iter.h __iterator/common_iterator.h @@ -586,13 +567,31 @@ set(files __numeric/iota.h __numeric/midpoint.h __numeric/partial_sum.h - __numeric/pstl_reduce.h - __numeric/pstl_transform_reduce.h + __numeric/pstl.h __numeric/reduce.h __numeric/saturation_arithmetic.h __numeric/transform_exclusive_scan.h __numeric/transform_inclusive_scan.h __numeric/transform_reduce.h + __ostream/basic_ostream.h + __ostream/print.h + __pstl/backend.h + __pstl/backend_fwd.h + __pstl/backends/default.h + __pstl/backends/libdispatch.h + __pstl/backends/serial.h + __pstl/backends/std_thread.h + __pstl/cpu_algos/any_of.h + __pstl/cpu_algos/cpu_traits.h + __pstl/cpu_algos/fill.h + __pstl/cpu_algos/find_if.h + __pstl/cpu_algos/for_each.h + __pstl/cpu_algos/merge.h + __pstl/cpu_algos/stable_sort.h + __pstl/cpu_algos/transform.h + __pstl/cpu_algos/transform_reduce.h + __pstl/dispatch.h + __pstl/handle_exception.h __random/bernoulli_distribution.h __random/binomial_distribution.h __random/cauchy_distribution.h @@ -711,6 +710,7 @@ set(files __thread/timed_backoff_policy.h __tree __tuple/find_index.h + __tuple/ignore.h __tuple/make_tuple_types.h __tuple/sfinae_helpers.h __tuple/tuple_element.h @@ -729,7 +729,6 @@ set(files __type_traits/aligned_storage.h __type_traits/aligned_union.h __type_traits/alignment_of.h - __type_traits/apply_cv.h __type_traits/can_extract_key.h __type_traits/common_reference.h __type_traits/common_type.h @@ -778,8 +777,6 @@ set(files __type_traits/is_implicitly_default_constructible.h __type_traits/is_integral.h __type_traits/is_literal_type.h - __type_traits/is_member_function_pointer.h - __type_traits/is_member_object_pointer.h __type_traits/is_member_pointer.h __type_traits/is_nothrow_assignable.h __type_traits/is_nothrow_constructible.h @@ -858,6 +855,7 @@ set(files __utility/in_place.h __utility/integer_sequence.h __utility/is_pointer_in_range.h + __utility/is_valid_range.h __utility/move.h __utility/no_destroy.h __utility/pair.h @@ -954,7 +952,6 @@ set(files istream iterator latch - libcxx.imp limits list locale @@ -1033,6 +1030,15 @@ foreach(f ${files}) list(APPEND _all_includes "${dst}") endforeach() +# Generate the IWYU mapping. This depends on all header files but it's also considered as an +# "include" for dependency tracking. +add_custom_command(OUTPUT "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" + COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_iwyu_mapping.py" "-o" "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" + DEPENDS ${_all_includes} + COMMENT "Generate the mapping file for include-what-you-use" +) +list(APPEND _all_includes "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp") + add_custom_target(generate-cxx-headers ALL DEPENDS ${_all_includes}) add_library(cxx-headers INTERFACE) @@ -1065,8 +1071,8 @@ if (LIBCXX_INSTALL_HEADERS) PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT cxx-headers) - # Install the generated modulemap file to the generic include dir. - install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" + # Install the generated IWYU file to the generic include dir. + install(FILES "${LIBCXX_GENERATED_INCLUDE_DIR}/libcxx.imp" DESTINATION "${LIBCXX_INSTALL_INCLUDE_DIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT cxx-headers) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/adjacent_find.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/adjacent_find.h index 7819e2cf49..6f15456e3a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/adjacent_find.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/adjacent_find.h @@ -26,7 +26,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter __adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { if (__first == __last) return __first; @@ -40,13 +40,13 @@ __adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { return std::__adjacent_find(std::move(__first), std::move(__last), __pred); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { return std::adjacent_find(std::move(__first), std::move(__last), __equal_to()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/all_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/all_of.h index 237f8495c6..ec84eea759 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/all_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/all_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/any_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/any_of.h index 8ba7aae2b2..b5ff778c41 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/any_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/any_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/binary_search.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/binary_search.h index 7a77d7b544..6065fc3727 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/binary_search.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/binary_search.h @@ -22,14 +22,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { __first = std::lower_bound<_ForwardIterator, _Tp, __comp_ref_type<_Compare> >(__first, __last, __value, __comp); return __first != __last && !__comp(__value, *__first); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::binary_search(__first, __last, __value, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/clamp.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/clamp.h index 003bf70dd4..1a5a3d0744 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/clamp.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/clamp.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& +[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, _LIBCPP_LIFETIMEBOUND const _Tp& __lo, _LIBCPP_LIFETIMEBOUND const _Tp& __hi, @@ -31,7 +31,7 @@ clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& +[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& clamp(_LIBCPP_LIFETIMEBOUND const _Tp& __v, _LIBCPP_LIFETIMEBOUND const _Tp& __lo, _LIBCPP_LIFETIMEBOUND const _Tp& __hi) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/comp_ref_type.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/comp_ref_type.h index aa9350c38c..c367fbb91a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/comp_ref_type.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/comp_ref_type.h @@ -41,9 +41,9 @@ struct __debug_less { } template - _LIBCPP_CONSTEXPR_SINCE_CXX14 inline _LIBCPP_HIDE_FROM_ABI decltype((void)std::declval<_Compare&>()( - std::declval<_LHS&>(), std::declval<_RHS&>())) - __do_compare_assert(int, _LHS& __l, _RHS& __r) { + _LIBCPP_CONSTEXPR_SINCE_CXX14 inline + _LIBCPP_HIDE_FROM_ABI decltype((void)std::declval<_Compare&>()(std::declval<_LHS&>(), std::declval<_RHS&>())) + __do_compare_assert(int, _LHS& __l, _RHS& __r) { _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(!__comp_(__l, __r), "Comparator does not induce a strict weak ordering"); (void)__l; (void)__r; diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy_move_common.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy_move_common.h index 12a26c6d6a..8a98451a8f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy_move_common.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/copy_move_common.h @@ -21,7 +21,6 @@ #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_trivially_assignable.h> -#include <__type_traits/is_trivially_copyable.h> #include <__type_traits/is_volatile.h> #include <__utility/move.h> #include <__utility/pair.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/count.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/count.h index 23a7d3c4dc..1cfe7f631a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/count.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/count.h @@ -79,7 +79,7 @@ __count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __l } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<_InputIterator> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __iter_diff_t<_InputIterator> count(_InputIterator __first, _InputIterator __last, const _Tp& __value) { __identity __proj; return std::__count<_ClassicAlgPolicy>(__first, __last, __value, __proj); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/count_if.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/count_if.h index 04f52b894f..25782069d0 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/count_if.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/count_if.h @@ -20,9 +20,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - typename iterator_traits<_InputIterator>::difference_type - count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +typename iterator_traits<_InputIterator>::difference_type +count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { typename iterator_traits<_InputIterator>::difference_type __r(0); for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/equal.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/equal.h index 1341d9e415..bfc8f72f6e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/equal.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/equal.h @@ -55,14 +55,14 @@ __equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { return std::__equal_iter_impl( std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { return std::equal(__first1, __last1, __first2, __equal_to()); } @@ -96,7 +96,7 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -119,7 +119,7 @@ equal(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::equal(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/equal_range.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/equal_range.h index 2b086abf17..09bbf8f006 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/equal_range.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/equal_range.h @@ -60,7 +60,7 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible"); @@ -73,7 +73,7 @@ equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::equal_range(std::move(__first), std::move(__last), __value, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find.h index 7d7631b6e9..7f58dbb13a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find.h @@ -43,7 +43,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // generic implementation template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter -__find_impl(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) { +__find(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) { for (; __first != __last; ++__first) if (std::__invoke(__proj, *__first) == __value) break; @@ -57,8 +57,7 @@ template ::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value && sizeof(_Tp) == 1, int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* -__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __find(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { if (auto __ret = std::__constexpr_memchr(__first, __value, __last - __first)) return __ret; return __last; @@ -71,8 +70,7 @@ template ::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value && sizeof(_Tp) == sizeof(wchar_t) && _LIBCPP_ALIGNOF(_Tp) >= _LIBCPP_ALIGNOF(wchar_t), int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* -__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __find(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { if (auto __ret = std::__constexpr_wmemchr(__first, __value, __last - __first)) return __ret; return __last; @@ -89,10 +87,10 @@ template ::value == is_signed<_Up>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* -__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj& __proj) { +__find(_Tp* __first, _Tp* __last, const _Up& __value, _Proj& __proj) { if (__value < numeric_limits<_Tp>::min() || __value > numeric_limits<_Tp>::max()) return __last; - return std::__find_impl(__first, __last, _Tp(__value), __proj); + return std::__find(__first, __last, _Tp(__value), __proj); } // __bit_iterator implementation @@ -134,7 +132,7 @@ __find_bool(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) template ::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, _IsConst> -__find_impl(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value, _Proj&) { +__find(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value, _Proj&) { if (static_cast(__value)) return std::__find_bool(__first, static_cast(__last - __first)); return std::__find_bool(__first, static_cast(__last - __first)); @@ -150,7 +148,7 @@ template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator -__find_impl(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value, _Proj& __proj) { +__find(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value, _Proj& __proj) { return std::__find_segment_if(std::move(__first), std::move(__last), __find_segment<_Tp>(__value), __proj); } @@ -163,17 +161,17 @@ struct __find_segment { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _InputIterator operator()(_InputIterator __first, _InputIterator __last, _Proj& __proj) const { - return std::__find_impl(__first, __last, __value_, __proj); + return std::__find(__first, __last, __value_, __proj); } }; // public API template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find(_InputIterator __first, _InputIterator __last, const _Tp& __value) { __identity __proj; return std::__rewrap_iter( - __first, std::__find_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __value, __proj)); + __first, std::__find(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __value, __proj)); } _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_end.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_end.h index 4c26891666..7e08e79535 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_end.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_end.h @@ -205,7 +205,7 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Fo } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -215,7 +215,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::find_end(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_first_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_first_of.h index 14271cccc4..6b99f562f8 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_first_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_first_of.h @@ -35,7 +35,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_fir } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -45,7 +45,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_if.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_if.h index 09a39f6463..22092d352b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_if.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_if.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_if_not.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_if_not.h index bf29ebb7cd..cc2001967f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_if_not.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/find_if_not.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/fold.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/fold.h index 1a9d76b50d..255658f523 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/fold.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/fold.h @@ -78,8 +78,7 @@ concept __indirectly_binary_left_foldable = struct __fold_left_with_iter { template _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto - operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { using _Up = decay_t>>; if (__first == __last) { @@ -95,7 +94,7 @@ struct __fold_left_with_iter { } template > _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { auto __result = operator()(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)); using _Up = decay_t>>; @@ -107,13 +106,12 @@ inline constexpr auto fold_left_with_iter = __fold_left_with_iter(); struct __fold_left { template _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto - operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { return fold_left_with_iter(std::move(__first), std::move(__last), std::move(__init), std::ref(__f)).value; } template > _Fp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { return fold_left_with_iter(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)).value; } }; diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/includes.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/includes.h index 05d45365eb..62af03c374 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/includes.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/includes.h @@ -47,7 +47,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __includes( } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -67,7 +67,7 @@ includes(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::includes(std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_heap.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_heap.h index 0d2d43c2c3..c589b804a5 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_heap.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_heap.h @@ -22,13 +22,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)) == __last; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { return std::is_heap(__first, __last, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_heap_until.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_heap_until.h index 1eae3b86b9..a174f2453c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_heap_until.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_heap_until.h @@ -46,13 +46,13 @@ __is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) { return std::__is_heap_until(__first, __last, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_partitioned.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_partitioned.h index 71feed3320..1f7c8b0b26 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_partitioned.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_partitioned.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_permutation.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_permutation.h index 4226151222..2ddfb32a21 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_permutation.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_permutation.h @@ -113,7 +113,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation_impl( // 2+1 iterators, predicate. Not used by range algorithms. template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( _ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _BinaryPredicate&& __pred) { // Shorten sequences as much as possible by lopping of any equal prefix. for (; __first1 != __last1; ++__first1, (void)++__first2) { @@ -247,7 +247,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __is_permutation( // 2+1 iterators, predicate template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _BinaryPredicate __pred) { static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, "The predicate has to be callable"); @@ -257,7 +257,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool i // 2+1 iterators template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { return std::is_permutation(__first1, __last1, __first2, __equal_to()); } @@ -266,7 +266,7 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt // 2+2 iterators template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::__is_permutation<_ClassicAlgPolicy>( std::move(__first1), @@ -280,7 +280,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 // 2+2 iterators, predicate template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation( _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_sorted.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_sorted.h index 1874cace88..3befb1ac9c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_sorted.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_sorted.h @@ -22,13 +22,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp) == __last; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last) { return std::is_sorted(__first, __last, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_sorted_until.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_sorted_until.h index 7450440df2..53a49f00de 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_sorted_until.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/is_sorted_until.h @@ -35,13 +35,13 @@ __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __ } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) { return std::is_sorted_until(__first, __last, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/lexicographical_compare.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/lexicographical_compare.h index 3efd8e24bf..edc29e269c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/lexicographical_compare.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/lexicographical_compare.h @@ -37,7 +37,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __lexicographical_compa } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -47,7 +47,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool lexicographical_compare( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::lexicographical_compare(__first1, __last1, __first2, __last2, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/lexicographical_compare_three_way.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/lexicographical_compare_three_way.h index 50ebdc647a..a5872e90cf 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/lexicographical_compare_three_way.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/lexicographical_compare_three_way.h @@ -90,7 +90,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_slow_pa } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp __comp) -> decltype(__comp(*__first1, *__first2)) { static_assert(__comparison_category, @@ -110,7 +110,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compa } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::lexicographical_compare_three_way( std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::compare_three_way()); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/lower_bound.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/lower_bound.h index 8f57f3592c..8fd355a7cf 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/lower_bound.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/lower_bound.h @@ -47,7 +47,7 @@ __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); auto __proj = std::__identity(); @@ -55,7 +55,7 @@ lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::lower_bound(__first, __last, __value, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/make_projected.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/make_projected.h index bb7bc7e8c0..5245e523f3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/make_projected.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/make_projected.h @@ -36,8 +36,8 @@ struct _ProjectedPred { : __pred(__pred_arg), __proj(__proj_arg) {} template - typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>())) >:: - type _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI + typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>()))>::type + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI operator()(_Tp&& __v) const { return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v))); } @@ -45,8 +45,8 @@ struct _ProjectedPred { template typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())), - decltype(std::__invoke(std::declval<_Proj&>(), - std::declval<_T2>())) >::type _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI + decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>()))>::type _LIBCPP_CONSTEXPR + _LIBCPP_HIDE_FROM_ABI operator()(_T1&& __lhs, _T2&& __rhs) const { return std::__invoke( __pred, std::__invoke(__proj, std::forward<_T1>(__lhs)), std::__invoke(__proj, std::forward<_T2>(__rhs))); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/max.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/max.h index 8171677f15..d4c99f6f36 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/max.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/max.h @@ -25,13 +25,13 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__a, __b) ? __b : __a; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::max(__a, __b, __less<>()); } @@ -39,13 +39,13 @@ max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t, _Compare __comp) { return *std::__max_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { return *std::max_element(__t.begin(), __t.end(), __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/max_element.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/max_element.h index f1d4f1cd09..c036726cbc 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/max_element.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/max_element.h @@ -35,13 +35,13 @@ __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { return std::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last) { return std::max_element(__first, __last, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/min.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/min.h index 919508486f..1bafad8a46 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/min.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/min.h @@ -25,13 +25,13 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? __b : __a; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::min(__a, __b, __less<>()); } @@ -39,13 +39,13 @@ min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t, _Compare __comp) { return *std::__min_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { return *std::min_element(__t.begin(), __t.end(), __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/min_element.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/min_element.h index c576d66560..65f3594d63 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/min_element.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/min_element.h @@ -48,7 +48,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter __min_element(_Iter __ } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { static_assert( __has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator"); @@ -59,7 +59,7 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last) { return std::min_element(__first, __last, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/minmax.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/minmax.h index 5227b88571..9feda2b4c0 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/minmax.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/minmax.h @@ -24,13 +24,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? pair(__b, __a) : pair(__a, __b); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { return std::minmax(__a, __b, __less<>()); } @@ -38,7 +38,7 @@ minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __ #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t, _Compare __comp) { static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable"); __identity __proj; @@ -47,7 +47,7 @@ minmax(initializer_list<_Tp> __t, _Compare __comp) { } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t) { return std::minmax(__t, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/minmax_element.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/minmax_element.h index ff8cda321c..43cb23347c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/minmax_element.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/minmax_element.h @@ -79,7 +79,7 @@ __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { static_assert( __has_forward_iterator_category<_ForwardIterator>::value, "std::minmax_element requires a ForwardIterator"); @@ -90,9 +90,8 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __com } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - pair<_ForwardIterator, _ForwardIterator> - minmax_element(_ForwardIterator __first, _ForwardIterator __last) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> +minmax_element(_ForwardIterator __first, _ForwardIterator __last) { return std::minmax_element(__first, __last, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/mismatch.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/mismatch.h index 4ada29eabc..632bec0240 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/mismatch.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/mismatch.h @@ -16,6 +16,7 @@ #include <__algorithm/unwrap_iter.h> #include <__config> #include <__functional/identity.h> +#include <__iterator/aliasing_iterator.h> #include <__type_traits/desugars_to.h> #include <__type_traits/invoke.h> #include <__type_traits/is_constant_evaluated.h> @@ -55,18 +56,13 @@ __mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Pro #if _LIBCPP_VECTORIZE_ALGORITHMS -template ::value && __desugars_to_v<__equal_tag, _Pred, _Tp, _Tp> && - __is_identity<_Proj1>::value && __is_identity<_Proj2>::value, - int> = 0> -_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> -__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { +template +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter, _Iter> +__mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) { + using __value_type = __iter_value_type<_Iter>; constexpr size_t __unroll_count = 4; - constexpr size_t __vec_size = __native_vector_size<_Tp>; - using __vec = __simd_vector<_Tp, __vec_size>; + constexpr size_t __vec_size = __native_vector_size<__value_type>; + using __vec = __simd_vector<__value_type, __vec_size>; if (!__libcpp_is_constant_evaluated()) { auto __orig_first1 = __first1; @@ -116,13 +112,45 @@ __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __ } // else loop over the elements individually } - return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2); + __equal_to __pred; + __identity __proj; + return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj, __proj); } +template ::value && __desugars_to_v<__equal_tag, _Pred, _Tp, _Tp> && + __is_identity<_Proj1>::value && __is_identity<_Proj2>::value, + int> = 0> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> +__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred&, _Proj1&, _Proj2&) { + return std::__mismatch_vectorized(__first1, __last1, __first2); +} + +template ::value && __desugars_to_v<__equal_tag, _Pred, _Tp, _Tp> && + __is_identity<_Proj1>::value && __is_identity<_Proj2>::value && + __can_map_to_integer_v<_Tp> && __libcpp_is_trivially_equality_comparable<_Tp, _Tp>::value, + int> = 0> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> +__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + if (__libcpp_is_constant_evaluated()) { + return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2); + } else { + using _Iter = __aliasing_iterator<_Tp*, __get_as_integer_type_t<_Tp>>; + auto __ret = std::__mismatch_vectorized(_Iter(__first1), _Iter(__last1), _Iter(__first2)); + return {__ret.first.__base(), __ret.second.__base()}; + } +} #endif // _LIBCPP_VECTORIZE_ALGORITHMS template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { __identity __proj; auto __res = std::__mismatch( @@ -131,14 +159,14 @@ mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { return std::mismatch(__first1, __last1, __first2, __equal_to()); } #if _LIBCPP_STD_VER >= 14 template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch( +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { while (__first1 != __last1 && __first2 != __last2) { if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) @@ -150,14 +178,14 @@ template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> __mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { auto __len = std::min(__last1 - __first1, __last2 - __first2); return std::__mismatch(__first1, __first1 + __len, __first2, __pred, __proj1, __proj2); } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, @@ -176,7 +204,7 @@ mismatch(_InputIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::mismatch(__first1, __last1, __first2, __last2, __equal_to()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/none_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/none_of.h index ce59187a3a..50841ba17c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/none_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/none_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (__pred(*__first)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl.h new file mode 100644 index 0000000000..0bb052b3f9 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl.h @@ -0,0 +1,663 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_H +#define _LIBCPP___ALGORITHM_PSTL_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +# include <__functional/operations.h> +# include <__iterator/cpp17_iterator_concepts.h> +# include <__iterator/iterator_traits.h> +# include <__pstl/backend.h> +# include <__pstl/dispatch.h> +# include <__pstl/handle_exception.h> +# include <__type_traits/enable_if.h> +# include <__type_traits/is_execution_policy.h> +# include <__type_traits/remove_cvref.h> +# include <__utility/forward.h> +# include <__utility/move.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + enable_if_t, int> = 0> +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool +any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "any_of requires a ForwardIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__any_of, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool +all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "all_of requires a ForwardIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__all_of, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool +none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "none_of requires a ForwardIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__none_of, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +copy(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR( + _ForwardIterator, "copy(first, last, result) requires [first, last) to be ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR( + _ForwardOutIterator, "copy(first, last, result) requires result to be a ForwardIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR( + _ForwardOutIterator, decltype(*__first), "copy(first, last, result) requires result to be an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__copy, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__result)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +copy_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __result) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR( + _ForwardIterator, "copy_n(first, n, result) requires first to be a ForwardIterator"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR( + _ForwardOutIterator, "copy_n(first, n, result) requires result to be a ForwardIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR( + _ForwardOutIterator, decltype(*__first), "copy_n(first, n, result) requires result to be an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__copy_n, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__n), std::move(__result)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> +count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR( + _ForwardIterator, "count_if(first, last, pred) requires [first, last) to be ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__count_if, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> +count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR( + _ForwardIterator, "count(first, last, val) requires [first, last) to be ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__count, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), __value); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI bool +equal(_ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "equal requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "equal requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__equal_3leg, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI bool +equal(_ExecutionPolicy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "equal requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "equal requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__equal_3leg, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + equal_to{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI bool +equal(_ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "equal requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "equal requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__equal, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI bool +equal(_ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "equal requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "equal requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__equal, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + equal_to{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "fill requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__fill, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), __value); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "fill_n requires a ForwardIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__fill_n, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__n), __value); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find_if requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__find_if, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find_if_not requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__find_if_not, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "find requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__find, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), __value); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +for_each(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Function __func) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "for_each requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__for_each, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__func)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "for_each_n requires a ForwardIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__for_each_n, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__size), std::move(__func)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +generate(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator __gen) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "generate requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__generate, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__gen)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +generate_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _Generator __gen) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "generate_n requires a ForwardIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__generate_n, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__n), std::move(__gen)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool +is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "is_partitioned requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__is_partitioned, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__pred)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +merge(_ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardOutIterator __result, + _Comp __comp) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "merge requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "merge requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(*__first1), "merge requires an OutputIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(*__first2), "merge requires an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__merge, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + std::move(__comp)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +merge(_ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardOutIterator __result) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "merge requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "merge requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(*__first1), "merge requires an OutputIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(*__first2), "merge requires an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__merge, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + less{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +move(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "move requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator, "move requires an OutputIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR( + _ForwardOutIterator, decltype(std::move(*__first)), "move requires an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__move, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__result)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +replace_if(_ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _Pred __pred, + const _Tp& __new_value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "replace_if requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__replace_if, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__pred), __new_value); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +replace(_ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + const _Tp& __old_value, + const _Tp& __new_value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "replace requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__replace, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), __old_value, __new_value); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void replace_copy_if( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _Pred __pred, + const _Tp& __new_value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "replace_copy_if requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator, "replace_copy_if requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR( + _ForwardOutIterator, decltype(*__first), "replace_copy_if requires an OutputIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, const _Tp&, "replace_copy requires an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__replace_copy_if, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first), + std::move(__last), + std::move(__result), + std::move(__pred), + __new_value); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void replace_copy( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + const _Tp& __old_value, + const _Tp& __new_value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "replace_copy requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator, "replace_copy requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR( + _ForwardOutIterator, decltype(*__first), "replace_copy requires an OutputIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, const _Tp&, "replace_copy requires an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__replace_copy, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first), + std::move(__last), + std::move(__result), + __old_value, + __new_value); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator rotate_copy( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + _ForwardOutIterator __result) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "rotate_copy requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator, "rotate_copy requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR( + _ForwardOutIterator, decltype(*__first), "rotate_copy requires an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__rotate_copy, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first), + std::move(__middle), + std::move(__last), + std::move(__result)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { + _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(_RandomAccessIterator, "sort requires RandomAccessIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__sort, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__comp)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last) { + _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(_RandomAccessIterator, "sort requires RandomAccessIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__sort, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), less{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +stable_sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { + _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(_RandomAccessIterator, "stable_sort requires RandomAccessIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__stable_sort, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__comp)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +stable_sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last) { + _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(_RandomAccessIterator, "stable_sort requires RandomAccessIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__stable_sort, __pstl::__current_configuration, _RawPolicy>; + __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), less{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _UnaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "transform requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator, "transform requires an OutputIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR( + _ForwardOutIterator, decltype(__op(*__first)), "transform requires an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__transform, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first), + std::move(__last), + std::move(__result), + std::move(__op)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( + _ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardOutIterator __result, + _BinaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "transform requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "transform requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator, "transform requires an OutputIterator"); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR( + _ForwardOutIterator, decltype(__op(*__first1, *__first2)), "transform requires an OutputIterator"); + using _Implementation = __pstl::__dispatch<__pstl::__transform_binary, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__result), + std::move(__op)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_PSTL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_any_all_none_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_any_all_none_of.h deleted file mode 100644 index 4b1e0e61b5..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_any_all_none_of.h +++ /dev/null @@ -1,152 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H -#define _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H - -#include <__algorithm/pstl_find.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__iterator/cpp17_iterator_concepts.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_any_of(); // declaration needed for the frontend dispatch below - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional __any_of( - _ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_any_of, _RawPolicy), - [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) -> optional { - auto __res = std::__find_if(__policy, __g_first, __g_last, __g_pred); - if (!__res) - return nullopt; - return *__res != __g_last; - }, - std::move(__first), - std::move(__last), - std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool -any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - auto __res = std::__any_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -template -void __pstl_all_of(); // declaration needed for the frontend dispatch below - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional -__all_of(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Pred&& __pred) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_all_of, _RawPolicy), - [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) -> optional { - auto __res = std::__any_of(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) { - return !__g_pred(__value); - }); - if (!__res) - return nullopt; - return !*__res; - }, - std::move(__first), - std::move(__last), - std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool -all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - auto __res = std::__all_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -template -void __pstl_none_of(); // declaration needed for the frontend dispatch below - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional -__none_of(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Pred&& __pred) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_none_of, _RawPolicy), - [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) -> optional { - auto __res = std::__any_of(__policy, __g_first, __g_last, __g_pred); - if (!__res) - return nullopt; - return !*__res; - }, - std::move(__first), - std::move(__last), - std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool -none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - auto __res = std::__none_of(__policy, std::move(__first), std::move(__last), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backend.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backend.h deleted file mode 100644 index 3af03ce2fb..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backend.h +++ /dev/null @@ -1,232 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKEND_H -#define _LIBCPP___ALGORITHM_PSTL_BACKEND_H - -#include <__algorithm/pstl_backends/cpu_backend.h> -#include <__config> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -/* -TODO: Documentation of how backends work - -A PSTL parallel backend is a tag type to which the following functions are associated, at minimum: - - template - optional<__empty> __pstl_for_each(_Backend, _ExecutionPolicy&&, _Iterator __first, _Iterator __last, _Func __f); - - template - optional<_Iterator> __pstl_find_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); - - template - optional<__empty> - __pstl_stable_sort(_Backend, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp); - - template - optional<_ForwardOutIterator> __pstl_merge(_Backend, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _ForwardIterator2 __last2, - _ForwardOutIterator __result, - _Comp __comp); - - template - optional<_OutIterator> - __pstl_transform(_Backend, _InIterator __first, _InIterator __last, _OutIterator __result, _UnaryOperation __op); - - template - optional<_OutIterator> __pstl_transform(_InIterator1 __first1, - _InIterator2 __first2, - _InIterator1 __last1, - _OutIterator __result, - _BinaryOperation __op); - - template - optional<_Tp> __pstl_transform_reduce(_Backend, - _Iterator1 __first1, - _Iterator1 __last1, - _Iterator2 __first2, - _Iterator2 __last2, - _Tp __init, - _BinaryOperation1 __reduce, - _BinaryOperation2 __transform); - - template - optional<_Tp> __pstl_transform_reduce(_Backend, - _Iterator __first, - _Iterator __last, - _Tp __init, - _BinaryOperation __reduce, - _UnaryOperation __transform); - -// TODO: Complete this list - -The following functions are optional but can be provided. If provided, they are used by the corresponding -algorithms, otherwise they are implemented in terms of other algorithms. If none of the optional algorithms are -implemented, all the algorithms will eventually forward to the basis algorithms listed above: - - template - optional<__empty> __pstl_for_each_n(_Backend, _Iterator __first, _Size __n, _Func __f); - - template - optional __pstl_any_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); - - template - optional __pstl_all_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); - - template - optional __pstl_none_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); - - template - optional<_Iterator> __pstl_find(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); - - template - optional<_Iterator> __pstl_find_if_not(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); - - template - optional<__empty> __pstl_fill(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); - - template - optional<__empty> __pstl_fill_n(_Backend, _Iterator __first, _SizeT __n, const _Tp& __value); - - template - optional<__empty> __pstl_generate(_Backend, _Iterator __first, _Iterator __last, _Generator __gen); - - template - optional<__empty> __pstl_is_partitioned(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); - - template - optional<__empty> __pstl_generator_n(_Backend, _Iterator __first, _Size __n, _Generator __gen); - - template - optional<_OutIterator> __pstl_merge(_Backend, - _Iterator1 __first1, - _Iterator1 __last1, - _Iterator2 __first2, - _Iterator2 __last2, - _OutIterator __result, - _Comp __comp); - - template - optional<_OutIterator> __pstl_move(_Backend, _Iterator __first, _Iterator __last, _OutIterator __result); - - template - optional<_Tp> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last, _Tp __init, _BinaryOperation __op); - - temlate - optional<__iter_value_type<_Iterator>> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last); - - template - optional<__iter_diff_t<_Iterator>> __pstl_count(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); - - template - optional<__iter_diff_t<_Iterator>> __pstl_count_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); - - template - optional<__empty> - __pstl_replace(_Backend, _Iterator __first, _Iterator __last, const _Tp& __old_value, const _Tp& __new_value); - - template - optional<__empty> - __pstl_replace_if(_Backend, _Iterator __first, _Iterator __last, _Pred __pred, const _Tp& __new_value); - - template - optional<__empty> __pstl_replace_copy(_Backend, - _Iterator __first, - _Iterator __last, - _OutIterator __result, - const _Tp& __old_value, - const _Tp& __new_value); - - template - optional<__empty> __pstl_replace_copy_if(_Backend, - _Iterator __first, - _Iterator __last, - _OutIterator __result, - _Pred __pred, - const _Tp& __new_value); - - template - optional<_Iterator> __pstl_rotate_copy( - _Backend, _Iterator __first, _Iterator __middle, _Iterator __last, _OutIterator __result); - - template - optional<__empty> __pstl_sort(_Backend, _Iterator __first, _Iterator __last, _Comp __comp); - - template - optional __pstl_equal(_Backend, _Iterator1 first1, _Iterator1 last1, _Iterator2 first2, _Comp __comp); - -// TODO: Complete this list - -Exception handling -================== - -PSTL backends are expected to report errors (i.e. failure to allocate) by returning a disengaged `optional` from their -implementation. Exceptions shouldn't be used to report an internal failure-to-allocate, since all exceptions are turned -into a program termination at the front-end level. When a backend returns a disengaged `optional` to the frontend, the -frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to the user. -*/ - -template -struct __select_backend; - -template <> -struct __select_backend { - using type = __cpu_backend_tag; -}; - -# if _LIBCPP_STD_VER >= 20 -template <> -struct __select_backend { - using type = __cpu_backend_tag; -}; -# endif - -# if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) || defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) || \ - defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) -template <> -struct __select_backend { - using type = __cpu_backend_tag; -}; - -template <> -struct __select_backend { - using type = __cpu_backend_tag; -}; - -# else - -// ...New vendors can add parallel backends here... - -# error "Invalid choice of a PSTL parallel backend" -# endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKEND_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backend.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backend.h deleted file mode 100644 index 6980ded189..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backend.h +++ /dev/null @@ -1,68 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H - -#include <__config> - -/* - - // _Functor takes a subrange for [__first, __last) that should be executed in serial - template - optional<__empty> __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func); - - template - optional<_Tp> - __parallel_transform_reduce(_Iterator __first, _Iterator __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduction); - - // Cancel the execution of other jobs - they aren't needed anymore - void __cancel_execution(); - - template - optional __parallel_merge( - _RandomAccessIterator1 __first1, - _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, - _RandomAccessIterator2 __last2, - _RandomAccessIterator3 __outit, - _Compare __comp, - _LeafMerge __leaf_merge); - - template - void __parallel_stable_sort(_RandomAccessIterator __first, - _RandomAccessIterator __last, - _Comp __comp, - _LeafSort __leaf_sort); - - TODO: Document the parallel backend - -Exception handling -================== - -CPU backends are expected to report errors (i.e. failure to allocate) by returning a disengaged `optional` from their -implementation. Exceptions shouldn't be used to report an internal failure-to-allocate, since all exceptions are turned -into a program termination at the front-end level. When a backend returns a disengaged `optional` to the frontend, the -frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to the user. -*/ - -#include <__algorithm/pstl_backends/cpu_backends/any_of.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> -#include <__algorithm/pstl_backends/cpu_backends/fill.h> -#include <__algorithm/pstl_backends/cpu_backends/find_if.h> -#include <__algorithm/pstl_backends/cpu_backends/for_each.h> -#include <__algorithm/pstl_backends/cpu_backends/merge.h> -#include <__algorithm/pstl_backends/cpu_backends/stable_sort.h> -#include <__algorithm/pstl_backends/cpu_backends/transform.h> -#include <__algorithm/pstl_backends/cpu_backends/transform_reduce.h> - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/backend.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/backend.h deleted file mode 100644 index ea2210a4a7..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/backend.h +++ /dev/null @@ -1,41 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H - -#include <__config> -#include - -#if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) -# include <__algorithm/pstl_backends/cpu_backends/serial.h> -#elif defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) -# include <__algorithm/pstl_backends/cpu_backends/thread.h> -#elif defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) -# include <__algorithm/pstl_backends/cpu_backends/libdispatch.h> -#else -# error "Invalid CPU backend choice" -#endif - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -struct __cpu_backend_tag {}; - -inline constexpr size_t __lane_size = 64; - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/fill.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/fill.h deleted file mode 100644 index 64babe9fd2..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/fill.h +++ /dev/null @@ -1,62 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H - -#include <__algorithm/fill.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> -#include <__config> -#include <__iterator/concepts.h> -#include <__type_traits/is_execution_policy.h> -#include <__utility/empty.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -_LIBCPP_HIDE_FROM_ABI _Index __simd_fill_n(_Index __first, _DifferenceType __n, const _Tp& __value) noexcept { - _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED - _PSTL_PRAGMA_SIMD - for (_DifferenceType __i = 0; __i < __n; ++__i) - __first[__i] = __value; - return __first + __n; -} - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> -__pstl_fill(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - return __par_backend::__parallel_for( - __first, __last, [&__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - [[maybe_unused]] auto __res = std::__pstl_fill<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __value); - _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); - }); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - std::__simd_fill_n(__first, __last - __first, __value); - return __empty{}; - } else { - std::fill(__first, __last, __value); - return __empty{}; - } -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/for_each.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/for_each.h deleted file mode 100644 index 81fd4526b8..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/for_each.h +++ /dev/null @@ -1,62 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H - -#include <__algorithm/for_each.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> -#include <__config> -#include <__iterator/concepts.h> -#include <__type_traits/is_execution_policy.h> -#include <__utility/empty.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -_LIBCPP_HIDE_FROM_ABI _Iterator __simd_walk(_Iterator __first, _DifferenceType __n, _Function __f) noexcept { - _PSTL_PRAGMA_SIMD - for (_DifferenceType __i = 0; __i < __n; ++__i) - __f(__first[__i]); - - return __first + __n; -} - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> -__pstl_for_each(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Functor __func) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - return std::__par_backend::__parallel_for( - __first, __last, [__func](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - [[maybe_unused]] auto __res = std::__pstl_for_each<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __func); - _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); - }); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - std::__simd_walk(__first, __last - __first, __func); - return __empty{}; - } else { - std::for_each(__first, __last, __func); - return __empty{}; - } -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h deleted file mode 100644 index e885e7f225..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h +++ /dev/null @@ -1,347 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H - -#include <__algorithm/inplace_merge.h> -#include <__algorithm/lower_bound.h> -#include <__algorithm/max.h> -#include <__algorithm/merge.h> -#include <__algorithm/upper_bound.h> -#include <__atomic/atomic.h> -#include <__config> -#include <__exception/terminate.h> -#include <__iterator/iterator_traits.h> -#include <__iterator/move_iterator.h> -#include <__memory/allocator.h> -#include <__memory/construct_at.h> -#include <__memory/unique_ptr.h> -#include <__numeric/reduce.h> -#include <__utility/empty.h> -#include <__utility/exception_guard.h> -#include <__utility/move.h> -#include <__utility/pair.h> -#include -#include -#include - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace __par_backend { -inline namespace __libdispatch { - -// ::dispatch_apply is marked as __attribute__((nothrow)) because it doesn't let exceptions propagate, and neither do -// we. -// TODO: Do we want to add [[_Clang::__callback__(__func, __context, __)]]? -_LIBCPP_EXPORTED_FROM_ABI void -__dispatch_apply(size_t __chunk_count, void* __context, void (*__func)(void* __context, size_t __chunk)) noexcept; - -template -_LIBCPP_HIDE_FROM_ABI void __dispatch_apply(size_t __chunk_count, _Func __func) noexcept { - __libdispatch::__dispatch_apply(__chunk_count, &__func, [](void* __context, size_t __chunk) { - (*static_cast<_Func*>(__context))(__chunk); - }); -} - -struct __chunk_partitions { - ptrdiff_t __chunk_count_; // includes the first chunk - ptrdiff_t __chunk_size_; - ptrdiff_t __first_chunk_size_; -}; - -[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI __chunk_partitions __partition_chunks(ptrdiff_t __size) noexcept; - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> -__dispatch_parallel_for(__chunk_partitions __partitions, _RandomAccessIterator __first, _Functor __func) { - // Perform the chunked execution. - __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { - auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; - auto __index = - __chunk == 0 - ? 0 - : (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); - __func(__first + __index, __first + __index + __this_chunk_size); - }); - - return __empty{}; -} - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> -__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func) { - return __libdispatch::__dispatch_parallel_for( - __libdispatch::__partition_chunks(__last - __first), std::move(__first), std::move(__func)); -} - -template -struct __merge_range { - __merge_range(_RandomAccessIterator1 __mid1, _RandomAccessIterator2 __mid2, _RandomAccessIteratorOut __result) - : __mid1_(__mid1), __mid2_(__mid2), __result_(__result) {} - - _RandomAccessIterator1 __mid1_; - _RandomAccessIterator2 __mid2_; - _RandomAccessIteratorOut __result_; -}; - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_merge( - _RandomAccessIterator1 __first1, - _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, - _RandomAccessIterator2 __last2, - _RandomAccessIterator3 __result, - _Compare __comp, - _LeafMerge __leaf_merge) noexcept { - __chunk_partitions __partitions = - __libdispatch::__partition_chunks(std::max(__last1 - __first1, __last2 - __first2)); - - if (__partitions.__chunk_count_ == 0) - return __empty{}; - - if (__partitions.__chunk_count_ == 1) { - __leaf_merge(__first1, __last1, __first2, __last2, __result, __comp); - return __empty{}; - } - - using __merge_range_t = __merge_range<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3>; - auto const __n_ranges = __partitions.__chunk_count_ + 1; - - // TODO: use __uninitialized_buffer - auto __destroy = [=](__merge_range_t* __ptr) { - std::destroy_n(__ptr, __n_ranges); - std::allocator<__merge_range_t>().deallocate(__ptr, __n_ranges); - }; - - unique_ptr<__merge_range_t[], decltype(__destroy)> __ranges( - [&]() -> __merge_range_t* { -# ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try { -# endif - return std::allocator<__merge_range_t>().allocate(__n_ranges); -# ifndef _LIBCPP_HAS_NO_EXCEPTIONS - } catch (const std::bad_alloc&) { - return nullptr; - } -# endif - }(), - __destroy); - - if (!__ranges) - return nullopt; - - // TODO: Improve the case where the smaller range is merged into just a few (or even one) chunks of the larger case - __merge_range_t* __r = __ranges.get(); - std::__construct_at(__r++, __first1, __first2, __result); - - bool __iterate_first_range = __last1 - __first1 > __last2 - __first2; - - auto __compute_chunk = [&](size_t __chunk_size) -> __merge_range_t { - auto [__mid1, __mid2] = [&] { - if (__iterate_first_range) { - auto __m1 = __first1 + __chunk_size; - auto __m2 = std::lower_bound(__first2, __last2, __m1[-1], __comp); - return std::make_pair(__m1, __m2); - } else { - auto __m2 = __first2 + __chunk_size; - auto __m1 = std::lower_bound(__first1, __last1, __m2[-1], __comp); - return std::make_pair(__m1, __m2); - } - }(); - - __result += (__mid1 - __first1) + (__mid2 - __first2); - __first1 = __mid1; - __first2 = __mid2; - return {std::move(__mid1), std::move(__mid2), __result}; - }; - - // handle first chunk - std::__construct_at(__r++, __compute_chunk(__partitions.__first_chunk_size_)); - - // handle 2 -> N - 1 chunks - for (ptrdiff_t __i = 0; __i != __partitions.__chunk_count_ - 2; ++__i) - std::__construct_at(__r++, __compute_chunk(__partitions.__chunk_size_)); - - // handle last chunk - std::__construct_at(__r, __last1, __last2, __result); - - __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __index) { - auto __first_iters = __ranges[__index]; - auto __last_iters = __ranges[__index + 1]; - __leaf_merge( - __first_iters.__mid1_, - __last_iters.__mid1_, - __first_iters.__mid2_, - __last_iters.__mid2_, - __first_iters.__result_, - __comp); - }); - - return __empty{}; -} - -template -_LIBCPP_HIDE_FROM_ABI optional<_Value> __parallel_transform_reduce( - _RandomAccessIterator __first, - _RandomAccessIterator __last, - _Transform __transform, - _Value __init, - _Combiner __combiner, - _Reduction __reduction) { - if (__first == __last) - return __init; - - auto __partitions = __libdispatch::__partition_chunks(__last - __first); - - auto __destroy = [__count = __partitions.__chunk_count_](_Value* __ptr) { - std::destroy_n(__ptr, __count); - std::allocator<_Value>().deallocate(__ptr, __count); - }; - - // TODO: use __uninitialized_buffer - // TODO: allocate one element per worker instead of one element per chunk - unique_ptr<_Value[], decltype(__destroy)> __values( - std::allocator<_Value>().allocate(__partitions.__chunk_count_), __destroy); - - // __dispatch_apply is noexcept - __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { - auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; - auto __index = - __chunk == 0 - ? 0 - : (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); - if (__this_chunk_size != 1) { - std::__construct_at( - __values.get() + __chunk, - __reduction(__first + __index + 2, - __first + __index + __this_chunk_size, - __combiner(__transform(__first + __index), __transform(__first + __index + 1)))); - } else { - std::__construct_at(__values.get() + __chunk, __transform(__first + __index)); - } - }); - - return std::reduce( - std::make_move_iterator(__values.get()), - std::make_move_iterator(__values.get() + __partitions.__chunk_count_), - std::move(__init), - __combiner); -} - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_stable_sort( - _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp, _LeafSort __leaf_sort) { - const auto __size = __last - __first; - auto __partitions = __libdispatch::__partition_chunks(__size); - - if (__partitions.__chunk_count_ == 0) - return __empty{}; - - if (__partitions.__chunk_count_ == 1) { - __leaf_sort(__first, __last, __comp); - return __empty{}; - } - - using _Value = __iter_value_type<_RandomAccessIterator>; - - auto __destroy = [__size](_Value* __ptr) { - std::destroy_n(__ptr, __size); - std::allocator<_Value>().deallocate(__ptr, __size); - }; - - // TODO: use __uninitialized_buffer - unique_ptr<_Value[], decltype(__destroy)> __values(std::allocator<_Value>().allocate(__size), __destroy); - - // Initialize all elements to a moved-from state - // TODO: Don't do this - this can be done in the first merge - see https://llvm.org/PR63928 - std::__construct_at(__values.get(), std::move(*__first)); - for (__iter_diff_t<_RandomAccessIterator> __i = 1; __i != __size; ++__i) { - std::__construct_at(__values.get() + __i, std::move(__values.get()[__i - 1])); - } - *__first = std::move(__values.get()[__size - 1]); - - __libdispatch::__dispatch_parallel_for( - __partitions, - __first, - [&__leaf_sort, &__comp](_RandomAccessIterator __chunk_first, _RandomAccessIterator __chunk_last) { - __leaf_sort(std::move(__chunk_first), std::move(__chunk_last), __comp); - }); - - bool __objects_are_in_buffer = false; - do { - const auto __old_chunk_size = __partitions.__chunk_size_; - if (__partitions.__chunk_count_ % 2 == 1) { - auto __inplace_merge_chunks = [&__comp, &__partitions](auto __first_chunk_begin) { - std::inplace_merge( - __first_chunk_begin, - __first_chunk_begin + __partitions.__first_chunk_size_, - __first_chunk_begin + __partitions.__first_chunk_size_ + __partitions.__chunk_size_, - __comp); - }; - if (__objects_are_in_buffer) - __inplace_merge_chunks(__values.get()); - else - __inplace_merge_chunks(__first); - __partitions.__first_chunk_size_ += 2 * __partitions.__chunk_size_; - } else { - __partitions.__first_chunk_size_ += __partitions.__chunk_size_; - } - - __partitions.__chunk_size_ *= 2; - __partitions.__chunk_count_ /= 2; - - auto __merge_chunks = [__partitions, __old_chunk_size, &__comp](auto __from_first, auto __to_first) { - __libdispatch::__dispatch_parallel_for( - __partitions, - __from_first, - [__old_chunk_size, &__from_first, &__to_first, &__comp](auto __chunk_first, auto __chunk_last) { - std::merge(std::make_move_iterator(__chunk_first), - std::make_move_iterator(__chunk_last - __old_chunk_size), - std::make_move_iterator(__chunk_last - __old_chunk_size), - std::make_move_iterator(__chunk_last), - __to_first + (__chunk_first - __from_first), - __comp); - }); - }; - - if (__objects_are_in_buffer) - __merge_chunks(__values.get(), __first); - else - __merge_chunks(__first, __values.get()); - __objects_are_in_buffer = !__objects_are_in_buffer; - } while (__partitions.__chunk_count_ > 1); - - if (__objects_are_in_buffer) { - std::move(__values.get(), __values.get() + __size, __first); - } - - return __empty{}; -} - -_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} - -} // namespace __libdispatch -} // namespace __par_backend - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/merge.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/merge.h deleted file mode 100644 index b0db70f58b..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/merge.h +++ /dev/null @@ -1,85 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H - -#include <__algorithm/merge.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> -#include <__config> -#include <__iterator/concepts.h> -#include <__type_traits/is_execution_policy.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_PUSH_MACROS -# include <__undef_macros> - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -_LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> __pstl_merge( - __cpu_backend_tag, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _ForwardIterator2 __last2, - _ForwardOutIterator __result, - _Comp __comp) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && - __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value && - __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { - auto __res = __par_backend::__parallel_merge( - __first1, - __last1, - __first2, - __last2, - __result, - __comp, - [](_ForwardIterator1 __g_first1, - _ForwardIterator1 __g_last1, - _ForwardIterator2 __g_first2, - _ForwardIterator2 __g_last2, - _ForwardOutIterator __g_result, - _Comp __g_comp) { - [[maybe_unused]] auto __g_res = std::__pstl_merge<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, - std::move(__g_first1), - std::move(__g_last1), - std::move(__g_first2), - std::move(__g_last2), - std::move(__g_result), - std::move(__g_comp)); - _LIBCPP_ASSERT_INTERNAL(__g_res, "unsed/sed should never try to allocate!"); - }); - if (!__res) - return nullopt; - return __result + (__last1 - __first1) + (__last2 - __first2); - } else { - return std::merge(__first1, __last1, __first2, __last2, __result, __comp); - } -} - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/serial.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/serial.h deleted file mode 100644 index afcc7ffb26..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/serial.h +++ /dev/null @@ -1,83 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H - -#include <__config> -#include <__utility/empty.h> -#include <__utility/move.h> -#include -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_PUSH_MACROS -# include <__undef_macros> - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace __par_backend { -inline namespace __serial_cpu_backend { - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> -__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { - __f(__first, __last); - return __empty{}; -} - -template -_LIBCPP_HIDE_FROM_ABI optional<_Tp> -__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { - return __reduce(std::move(__first), std::move(__last), std::move(__init)); -} - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_stable_sort( - _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { - __leaf_sort(__first, __last, __comp); - return __empty{}; -} - -_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_merge( - _RandomAccessIterator1 __first1, - _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, - _RandomAccessIterator2 __last2, - _RandomAccessIterator3 __outit, - _Compare __comp, - _LeafMerge __leaf_merge) { - __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); - return __empty{}; -} - -// TODO: Complete this list - -} // namespace __serial_cpu_backend -} // namespace __par_backend - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h deleted file mode 100644 index 34c423586c..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h +++ /dev/null @@ -1,45 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H - -#include <__algorithm/pstl_backends/cpu_backends/backend.h> -#include <__algorithm/stable_sort.h> -#include <__config> -#include <__type_traits/is_execution_policy.h> -#include <__utility/empty.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> -__pstl_stable_sort(__cpu_backend_tag, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy>) { - return __par_backend::__parallel_stable_sort( - __first, __last, __comp, [](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { - std::stable_sort(__g_first, __g_last, __g_comp); - }); - } else { - std::stable_sort(__first, __last, __comp); - return __empty{}; - } -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/thread.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/thread.h deleted file mode 100644 index eb11a961b7..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/thread.h +++ /dev/null @@ -1,84 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H - -#include <__assert> -#include <__config> -#include <__utility/empty.h> -#include <__utility/move.h> -#include -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -// This backend implementation is for testing purposes only and not meant for production use. This will be replaced -// by a proper implementation once the PSTL implementation is somewhat stable. - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace __par_backend { -inline namespace __thread_cpu_backend { - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> -__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { - __f(__first, __last); - return __empty{}; -} - -template -_LIBCPP_HIDE_FROM_ABI optional<_Tp> -__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { - return __reduce(std::move(__first), std::move(__last), std::move(__init)); -} - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_stable_sort( - _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { - __leaf_sort(__first, __last, __comp); - return __empty{}; -} - -_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} - -template -_LIBCPP_HIDE_FROM_ABI optional<__empty> __parallel_merge( - _RandomAccessIterator1 __first1, - _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, - _RandomAccessIterator2 __last2, - _RandomAccessIterator3 __outit, - _Compare __comp, - _LeafMerge __leaf_merge) { - __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); - return __empty{}; -} - -} // namespace __thread_cpu_backend -} // namespace __par_backend - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/transform.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/transform.h deleted file mode 100644 index fdf1a2e78d..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/transform.h +++ /dev/null @@ -1,138 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H - -#include <__algorithm/pstl_backends/cpu_backends/backend.h> -#include <__algorithm/transform.h> -#include <__config> -#include <__iterator/concepts.h> -#include <__iterator/iterator_traits.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_PUSH_MACROS -# include <__undef_macros> - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -_LIBCPP_HIDE_FROM_ABI _Iterator2 -__simd_walk(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept { - _PSTL_PRAGMA_SIMD - for (_DifferenceType __i = 0; __i < __n; ++__i) - __f(__first1[__i], __first2[__i]); - return __first2 + __n; -} - -template -_LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> __pstl_transform( - __cpu_backend_tag, - _ForwardIterator __first, - _ForwardIterator __last, - _ForwardOutIterator __result, - _UnaryOperation __op) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value && - __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { - std::__par_backend::__parallel_for( - __first, __last, [__op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - auto __res = std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __result + (__brick_first - __first), __op); - _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); - return *std::move(__res); - }); - return __result + (__last - __first); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value && - __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { - return std::__simd_walk( - __first, - __last - __first, - __result, - [&](__iter_reference<_ForwardIterator> __in_value, __iter_reference<_ForwardOutIterator> __out_value) { - __out_value = __op(__in_value); - }); - } else { - return std::transform(__first, __last, __result, __op); - } -} - -template -_LIBCPP_HIDE_FROM_ABI _Iterator3 __simd_walk( - _Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, _Function __f) noexcept { - _PSTL_PRAGMA_SIMD - for (_DifferenceType __i = 0; __i < __n; ++__i) - __f(__first1[__i], __first2[__i], __first3[__i]); - return __first3 + __n; -} -template >, int> = 0> -_LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> __pstl_transform( - __cpu_backend_tag, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _ForwardOutIterator __result, - _BinaryOperation __op) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && - __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value && - __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { - auto __res = std::__par_backend::__parallel_for( - __first1, - __last1, - [__op, __first1, __first2, __result](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) { - return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, - __brick_first, - __brick_last, - __first2 + (__brick_first - __first1), - __result + (__brick_first - __first1), - __op); - }); - if (!__res) - return nullopt; - return __result + (__last1 - __first1); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && - __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value && - __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { - return std::__simd_walk( - __first1, - __last1 - __first1, - __first2, - __result, - [&](__iter_reference<_ForwardIterator1> __in1, - __iter_reference<_ForwardIterator2> __in2, - __iter_reference<_ForwardOutIterator> __out_value) { __out_value = __op(__in1, __in2); }); - } else { - return std::transform(__first1, __last1, __first2, __result, __op); - } -} - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h deleted file mode 100644 index 376abd39fa..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h +++ /dev/null @@ -1,202 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H - -#include <__algorithm/pstl_backends/cpu_backends/backend.h> -#include <__config> -#include <__iterator/concepts.h> -#include <__iterator/iterator_traits.h> -#include <__numeric/transform_reduce.h> -#include <__type_traits/desugars_to.h> -#include <__type_traits/is_arithmetic.h> -#include <__type_traits/is_execution_policy.h> -#include <__utility/move.h> -#include -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template , - __enable_if_t<__desugars_to_v<__plus_tag, _BinaryOperation, _Tp, _UnaryResult> && is_arithmetic_v<_Tp> && - is_arithmetic_v<_UnaryResult>, - int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp -__simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept { - _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init) - for (_DifferenceType __i = 0; __i < __n; ++__i) - __init += __f(__i); - return __init; -} - -template , - __enable_if_t && is_arithmetic_v<_Tp> && - is_arithmetic_v<_UnaryResult>), - int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp -__simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept { - const _Size __block_size = __lane_size / sizeof(_Tp); - if (__n > 2 * __block_size && __block_size > 1) { - alignas(__lane_size) char __lane_buffer[__lane_size]; - _Tp* __lane = reinterpret_cast<_Tp*>(__lane_buffer); - - // initializer - _PSTL_PRAGMA_SIMD - for (_Size __i = 0; __i < __block_size; ++__i) { - ::new (__lane + __i) _Tp(__binary_op(__f(__i), __f(__block_size + __i))); - } - // main loop - _Size __i = 2 * __block_size; - const _Size __last_iteration = __block_size * (__n / __block_size); - for (; __i < __last_iteration; __i += __block_size) { - _PSTL_PRAGMA_SIMD - for (_Size __j = 0; __j < __block_size; ++__j) { - __lane[__j] = __binary_op(std::move(__lane[__j]), __f(__i + __j)); - } - } - // remainder - _PSTL_PRAGMA_SIMD - for (_Size __j = 0; __j < __n - __last_iteration; ++__j) { - __lane[__j] = __binary_op(std::move(__lane[__j]), __f(__last_iteration + __j)); - } - // combiner - for (_Size __j = 0; __j < __block_size; ++__j) { - __init = __binary_op(std::move(__init), std::move(__lane[__j])); - } - // destroyer - _PSTL_PRAGMA_SIMD - for (_Size __j = 0; __j < __block_size; ++__j) { - __lane[__j].~_Tp(); - } - } else { - for (_Size __i = 0; __i < __n; ++__i) { - __init = __binary_op(std::move(__init), __f(__i)); - } - } - return __init; -} - -template -_LIBCPP_HIDE_FROM_ABI optional<_Tp> __pstl_transform_reduce( - __cpu_backend_tag, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _Tp __init, - _BinaryOperation1 __reduce, - _BinaryOperation2 __transform) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && - __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) { - return __par_backend::__parallel_transform_reduce( - __first1, - std::move(__last1), - [__first1, __first2, __transform](_ForwardIterator1 __iter) { - return __transform(*__iter, *(__first2 + (__iter - __first1))); - }, - std::move(__init), - std::move(__reduce), - [__first1, __first2, __reduce, __transform]( - _ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last, _Tp __brick_init) { - return *std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, - __brick_first, - std::move(__brick_last), - __first2 + (__brick_first - __first1), - std::move(__brick_init), - std::move(__reduce), - std::move(__transform)); - }); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && - __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) { - return std::__simd_transform_reduce( - __last1 - __first1, std::move(__init), std::move(__reduce), [&](__iter_diff_t<_ForwardIterator1> __i) { - return __transform(__first1[__i], __first2[__i]); - }); - } else { - return std::transform_reduce( - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__init), - std::move(__reduce), - std::move(__transform)); - } -} - -template -_LIBCPP_HIDE_FROM_ABI optional<_Tp> __pstl_transform_reduce( - __cpu_backend_tag, - _ForwardIterator __first, - _ForwardIterator __last, - _Tp __init, - _BinaryOperation __reduce, - _UnaryOperation __transform) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - return __par_backend::__parallel_transform_reduce( - std::move(__first), - std::move(__last), - [__transform](_ForwardIterator __iter) { return __transform(*__iter); }, - std::move(__init), - __reduce, - [__transform, __reduce](auto __brick_first, auto __brick_last, _Tp __brick_init) { - auto __res = std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, - std::move(__brick_first), - std::move(__brick_last), - std::move(__brick_init), - std::move(__reduce), - std::move(__transform)); - _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); - return *std::move(__res); - }); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - return std::__simd_transform_reduce( - __last - __first, - std::move(__init), - std::move(__reduce), - [=, &__transform](__iter_diff_t<_ForwardIterator> __i) { return __transform(__first[__i]); }); - } else { - return std::transform_reduce( - std::move(__first), std::move(__last), std::move(__init), std::move(__reduce), std::move(__transform)); - } -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_copy.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_copy.h deleted file mode 100644 index 1069dcec0e..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_copy.h +++ /dev/null @@ -1,121 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_COPY_H -#define _LIBCPP___ALGORITHM_PSTL_COPY_H - -#include <__algorithm/copy_n.h> -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__algorithm/pstl_transform.h> -#include <__config> -#include <__functional/identity.h> -#include <__iterator/concepts.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_constant_evaluated.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/is_trivially_copyable.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -// TODO: Use the std::copy/move shenanigans to forward to std::memmove - -template -void __pstl_copy(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> -__copy(_ExecutionPolicy&& __policy, - _ForwardIterator&& __first, - _ForwardIterator&& __last, - _ForwardOutIterator&& __result) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_copy, _RawPolicy), - [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _ForwardOutIterator __g_result) { - return std::__transform(__policy, __g_first, __g_last, __g_result, __identity()); - }, - std::move(__first), - std::move(__last), - std::move(__result)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator -copy(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) { - auto __res = std::__copy(__policy, std::move(__first), std::move(__last), std::move(__result)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -template -void __pstl_copy_n(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> __copy_n( - _ExecutionPolicy&& __policy, _ForwardIterator&& __first, _Size&& __n, _ForwardOutIterator&& __result) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_copy_n, _RawPolicy), - [&__policy]( - _ForwardIterator __g_first, _Size __g_n, _ForwardOutIterator __g_result) -> optional<_ForwardIterator> { - if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) - return std::__copy(__policy, std::move(__g_first), std::move(__g_first + __g_n), std::move(__g_result)); - else - return std::copy_n(__g_first, __g_n, __g_result); - }, - std::move(__first), - std::move(__n), - std::move(__result)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator -copy_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __result) { - auto __res = std::__copy_n(__policy, std::move(__first), std::move(__n), std::move(__result)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_COPY_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_count.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_count.h deleted file mode 100644 index 2781f6bfd3..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_count.h +++ /dev/null @@ -1,121 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_COUNT_H -#define _LIBCPP___ALGORITHM_PSTL_COUNT_H - -#include <__algorithm/count.h> -#include <__algorithm/for_each.h> -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_for_each.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__atomic/atomic.h> -#include <__config> -#include <__functional/operations.h> -#include <__iterator/iterator_traits.h> -#include <__numeric/pstl_transform_reduce.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_count_if(); // declaration needed for the frontend dispatch below - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> __count_if( - _ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) noexcept { - using __diff_t = __iter_diff_t<_ForwardIterator>; - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count_if, _RawPolicy), - [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) -> optional<__diff_t> { - return std::__transform_reduce( - __policy, - std::move(__g_first), - std::move(__g_last), - __diff_t(), - std::plus{}, - [&](__iter_reference<_ForwardIterator> __element) -> bool { return __g_pred(__element); }); - }, - std::move(__first), - std::move(__last), - std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> -count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - auto __res = std::__count_if(__policy, std::move(__first), std::move(__last), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -template -void __pstl_count(); // declaration needed for the frontend dispatch below - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> -__count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count, _RawPolicy), - [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) - -> optional<__iter_diff_t<_ForwardIterator>> { - return std::count_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __v) { - return __v == __g_value; - }); - }, - std::move(__first), - std::move(__last), - __value); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> -count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - auto __res = std::__count(__policy, std::move(__first), std::move(__last), __value); - if (!__res) - std::__throw_bad_alloc(); - return *__res; -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_COUNT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_equal.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_equal.h deleted file mode 100644 index d235c0f4f4..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_equal.h +++ /dev/null @@ -1,175 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_EQUAL_H -#define _LIBCPP___ALGORITHM_PSTL_EQUAL_H - -#include <__algorithm/equal.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__functional/operations.h> -#include <__iterator/iterator_traits.h> -#include <__numeric/pstl_transform_reduce.h> -#include <__utility/move.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_equal(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional -__equal(_ExecutionPolicy&& __policy, - _ForwardIterator1&& __first1, - _ForwardIterator1&& __last1, - _ForwardIterator2&& __first2, - _Pred&& __pred) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_equal, _RawPolicy), - [&__policy]( - _ForwardIterator1 __g_first1, _ForwardIterator1 __g_last1, _ForwardIterator2 __g_first2, _Pred __g_pred) { - return std::__transform_reduce( - __policy, - std::move(__g_first1), - std::move(__g_last1), - std::move(__g_first2), - true, - std::logical_and{}, - std::move(__g_pred)); - }, - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI bool -equal(_ExecutionPolicy&& __policy, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _Pred __pred) { - auto __res = std::__equal(__policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *__res; -} - -template >, int> = 0> -_LIBCPP_HIDE_FROM_ABI bool -equal(_ExecutionPolicy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { - return std::equal(__policy, std::move(__first1), std::move(__last1), std::move(__first2), std::equal_to{}); -} - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional -__equal(_ExecutionPolicy&& __policy, - _ForwardIterator1&& __first1, - _ForwardIterator1&& __last1, - _ForwardIterator2&& __first2, - _ForwardIterator2&& __last2, - _Pred&& __pred) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_equal, _RawPolicy), - [&__policy](_ForwardIterator1 __g_first1, - _ForwardIterator1 __g_last1, - _ForwardIterator2 __g_first2, - _ForwardIterator2 __g_last2, - _Pred __g_pred) -> optional { - if constexpr (__has_random_access_iterator_category<_ForwardIterator1>::value && - __has_random_access_iterator_category<_ForwardIterator2>::value) { - if (__g_last1 - __g_first1 != __g_last2 - __g_first2) - return false; - return std::__equal( - __policy, std::move(__g_first1), std::move(__g_last1), std::move(__g_first2), std::move(__g_pred)); - } else { - (void)__policy; // Avoid unused lambda capture warning - return std::equal( - std::move(__g_first1), - std::move(__g_last1), - std::move(__g_first2), - std::move(__g_last2), - std::move(__g_pred)); - } - }, - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__last2), - std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI bool -equal(_ExecutionPolicy&& __policy, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _ForwardIterator2 __last2, - _Pred __pred) { - auto __res = std::__equal( - __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *__res; -} - -template >, int> = 0> -_LIBCPP_HIDE_FROM_ABI bool -equal(_ExecutionPolicy&& __policy, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _ForwardIterator2 __last2) { - return std::equal( - __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::equal_to{}); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_EQUAL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_fill.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_fill.h deleted file mode 100644 index 488b49a0fe..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_fill.h +++ /dev/null @@ -1,116 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_FILL_H -#define _LIBCPP___ALGORITHM_PSTL_FILL_H - -#include <__algorithm/fill_n.h> -#include <__algorithm/pstl_for_each.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__iterator/concepts.h> -#include <__iterator/cpp17_iterator_concepts.h> -#include <__iterator/iterator_traits.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_fill(); // declaration needed for the frontend dispatch below - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI optional<__empty> -__fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) noexcept { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill, _RawPolicy), - [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { - return std::__for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { - __element = __g_value; - }); - }, - std::move(__first), - std::move(__last), - __value); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - if (!std::__fill(__policy, std::move(__first), std::move(__last), __value)) - std::__throw_bad_alloc(); -} - -template -void __pstl_fill_n(); // declaration needed for the frontend dispatch below - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> -__fill_n(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _SizeT&& __n, const _Tp& __value) noexcept { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill_n, _RawPolicy), - [&](_ForwardIterator __g_first, _SizeT __g_n, const _Tp& __g_value) { - if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) - std::fill(__policy, __g_first, __g_first + __g_n, __g_value); - else - std::fill_n(__g_first, __g_n, __g_value); - return optional<__empty>{__empty{}}; - }, - std::move(__first), - std::move(__n), - __value); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _SizeT __n, const _Tp& __value) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - if (!std::__fill_n(__policy, std::move(__first), std::move(__n), __value)) - std::__throw_bad_alloc(); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_FILL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_find.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_find.h deleted file mode 100644 index 5b694db68a..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_find.h +++ /dev/null @@ -1,141 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_FIND_H -#define _LIBCPP___ALGORITHM_PSTL_FIND_H - -#include <__algorithm/comp.h> -#include <__algorithm/find.h> -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__iterator/cpp17_iterator_concepts.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardIterator>> -__find_if(_ExecutionPolicy&&, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) noexcept { - using _Backend = typename __select_backend<_RawPolicy>::type; - return std::__pstl_find_if<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardIterator -find_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - auto __res = std::__find_if(__policy, std::move(__first), std::move(__last), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -template -void __pstl_find_if_not(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardIterator>> -__find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find_if_not, _RawPolicy), - [&](_ForwardIterator&& __g_first, _ForwardIterator&& __g_last, _Predicate&& __g_pred) - -> optional<__remove_cvref_t<_ForwardIterator>> { - return std::__find_if( - __policy, __g_first, __g_last, [&](__iter_reference<__remove_cvref_t<_ForwardIterator>> __value) { - return !__g_pred(__value); - }); - }, - std::move(__first), - std::move(__last), - std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardIterator -find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - auto __res = std::__find_if_not(__policy, std::move(__first), std::move(__last), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -template -void __pstl_find(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardIterator>> -__find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find, _RawPolicy), - [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) -> optional<_ForwardIterator> { - return std::find_if( - __policy, __g_first, __g_last, [&](__iter_reference<__remove_cvref_t<_ForwardIterator>> __element) { - return __element == __g_value; - }); - }, - std::move(__first), - std::move(__last), - __value); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardIterator -find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - auto __res = std::__find(__policy, std::move(__first), std::move(__last), __value); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_FIND_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_for_each.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_for_each.h deleted file mode 100644 index bb7b5a61a6..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_for_each.h +++ /dev/null @@ -1,108 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H -#define _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H - -#include <__algorithm/for_each.h> -#include <__algorithm/for_each_n.h> -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__iterator/concepts.h> -#include <__iterator/cpp17_iterator_concepts.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__type_traits/void_t.h> -#include <__utility/empty.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> -__for_each(_ExecutionPolicy&&, _ForwardIterator&& __first, _ForwardIterator&& __last, _Function&& __func) noexcept { - using _Backend = typename __select_backend<_RawPolicy>::type; - return std::__pstl_for_each<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__func)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -for_each(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Function __func) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - if (!std::__for_each(__policy, std::move(__first), std::move(__last), std::move(__func))) - std::__throw_bad_alloc(); -} - -template -void __pstl_for_each_n(); // declaration needed for the frontend dispatch below - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> -__for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _Size&& __size, _Function&& __func) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_for_each_n, _RawPolicy), - [&](_ForwardIterator __g_first, _Size __g_size, _Function __g_func) -> optional<__empty> { - if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - std::for_each(__policy, std::move(__g_first), __g_first + __g_size, std::move(__g_func)); - return __empty{}; - } else { - std::for_each_n(std::move(__g_first), __g_size, std::move(__g_func)); - return __empty{}; - } - }, - std::move(__first), - std::move(__size), - std::move(__func)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - auto __res = std::__for_each_n(__policy, std::move(__first), std::move(__size), std::move(__func)); - if (!__res) - std::__throw_bad_alloc(); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_frontend_dispatch.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_frontend_dispatch.h deleted file mode 100644 index 6fa1107491..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_frontend_dispatch.h +++ /dev/null @@ -1,44 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_FRONTEND_DISPATCH -#define _LIBCPP___ALGORITHM_PSTL_FRONTEND_DISPATCH - -#include <__config> -#include <__type_traits/is_callable.h> -#include <__utility/forward.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -# define _LIBCPP_PSTL_CUSTOMIZATION_POINT(name, policy) \ - [](auto&&... __args) -> decltype(std::name( \ - typename __select_backend::type{}, std::forward(__args)...)) { \ - return std::name(typename __select_backend::type{}, std::forward(__args)...); \ - } - -template -_LIBCPP_HIDE_FROM_ABI decltype(auto) -__pstl_frontend_dispatch(_SpecializedImpl __specialized_impl, _GenericImpl __generic_impl, _Args&&... __args) { - if constexpr (__is_callable<_SpecializedImpl, _Args...>::value) { - return __specialized_impl(std::forward<_Args>(__args)...); - } else { - return __generic_impl(std::forward<_Args>(__args)...); - } -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_FRONTEND_DISPATCH diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_generate.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_generate.h deleted file mode 100644 index 7133c6f4f4..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_generate.h +++ /dev/null @@ -1,114 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_GENERATE_H -#define _LIBCPP___ALGORITHM_PSTL_GENERATE_H - -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_for_each.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__iterator/cpp17_iterator_concepts.h> -#include <__iterator/iterator_traits.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_generate(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> -__generate(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Generator&& __gen) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate, _RawPolicy), - [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Generator __g_gen) { - return std::__for_each( - __policy, std::move(__g_first), std::move(__g_last), [&](__iter_reference<_ForwardIterator> __element) { - __element = __g_gen(); - }); - }, - std::move(__first), - std::move(__last), - std::move(__gen)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -generate(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator __gen) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - if (!std::__generate(__policy, std::move(__first), std::move(__last), std::move(__gen))) - std::__throw_bad_alloc(); -} - -template -void __pstl_generate_n(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> -__generate_n(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _Size&& __n, _Generator&& __gen) { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate_n, _RawPolicy), - [&__policy](_ForwardIterator __g_first, _Size __g_n, _Generator __g_gen) { - return std::__for_each_n( - __policy, std::move(__g_first), std::move(__g_n), [&](__iter_reference<_ForwardIterator> __element) { - __element = __g_gen(); - }); - }, - std::move(__first), - __n, - std::move(__gen)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -generate_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _Generator __gen) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - if (!std::__generate_n(__policy, std::move(__first), std::move(__n), std::move(__gen))) - std::__throw_bad_alloc(); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_GENERATE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_is_partitioned.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_is_partitioned.h deleted file mode 100644 index b654302122..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_is_partitioned.h +++ /dev/null @@ -1,77 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED -#define _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED - -#include <__algorithm/pstl_any_all_none_of.h> -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_find.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_is_partitioned(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional __is_partitioned( - _ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last, _Predicate&& __pred) { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_is_partitioned, _RawPolicy), - [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { - __g_first = std::find_if_not(__policy, __g_first, __g_last, __g_pred); - if (__g_first == __g_last) - return true; - ++__g_first; - return std::none_of(__policy, __g_first, __g_last, __g_pred); - }, - std::move(__first), - std::move(__last), - std::move(__pred)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool -is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - auto __res = std::__is_partitioned(__policy, std::move(__first), std::move(__last), std::move(__pred)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_merge.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_merge.h deleted file mode 100644 index 3d262db6bc..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_merge.h +++ /dev/null @@ -1,92 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_MERGE_H -#define _LIBCPP___ALGORITHM_PSTL_MERGE_H - -#include <__algorithm/pstl_backend.h> -#include <__config> -#include <__functional/operations.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template , - class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> -__merge(_ExecutionPolicy&&, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _ForwardIterator2 __last2, - _ForwardOutIterator __result, - _Comp __comp = {}) noexcept { - using _Backend = typename __select_backend<_RawPolicy>::type; - return std::__pstl_merge<_RawPolicy>( - _Backend{}, - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__last2), - std::move(__result), - std::move(__comp)); -} - -template , - class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator -merge(_ExecutionPolicy&& __policy, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _ForwardIterator2 __last2, - _ForwardOutIterator __result, - _Comp __comp = {}) { - auto __res = std::__merge( - __policy, - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__last2), - std::move(__result), - std::move(__comp)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_MERGE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_move.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_move.h deleted file mode 100644 index d8441f1a6c..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_move.h +++ /dev/null @@ -1,84 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_MOVE_H -#define _LIBCPP___ALGORITHM_PSTL_MOVE_H - -#include <__algorithm/copy_n.h> -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__algorithm/pstl_transform.h> -#include <__config> -#include <__functional/identity.h> -#include <__iterator/iterator_traits.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_constant_evaluated.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/is_trivially_copyable.h> -#include <__type_traits/remove_cvref.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -// TODO: Use the std::copy/move shenanigans to forward to std::memmove -// Investigate whether we want to still forward to std::transform(policy) -// in that case for the execution::par part, or whether we actually want -// to run everything serially in that case. - -template -void __pstl_move(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> -__move(_ExecutionPolicy&& __policy, - _ForwardIterator&& __first, - _ForwardIterator&& __last, - _ForwardOutIterator&& __result) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_move, _RawPolicy), - [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _ForwardOutIterator __g_result) { - return std::__transform(__policy, __g_first, __g_last, __g_result, [](auto&& __v) { return std::move(__v); }); - }, - std::move(__first), - std::move(__last), - std::move(__result)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator -move(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) { - auto __res = std::__move(__policy, std::move(__first), std::move(__last), std::move(__result)); - if (!__res) - std::__throw_bad_alloc(); - return *__res; -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_MOVE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_replace.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_replace.h deleted file mode 100644 index b1caf3fd4a..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_replace.h +++ /dev/null @@ -1,247 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_REPLACE_H -#define _LIBCPP___ALGORITHM_PSTL_REPLACE_H - -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_for_each.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__algorithm/pstl_transform.h> -#include <__config> -#include <__iterator/iterator_traits.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_replace_if(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> -__replace_if(_ExecutionPolicy&& __policy, - _ForwardIterator&& __first, - _ForwardIterator&& __last, - _Pred&& __pred, - const _Tp& __new_value) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_if, _RawPolicy), - [&__policy]( - _ForwardIterator&& __g_first, _ForwardIterator&& __g_last, _Pred&& __g_pred, const _Tp& __g_new_value) { - std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { - if (__g_pred(__element)) - __element = __g_new_value; - }); - return optional<__empty>{__empty{}}; - }, - std::move(__first), - std::move(__last), - std::move(__pred), - __new_value); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -replace_if(_ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __last, - _Pred __pred, - const _Tp& __new_value) { - auto __res = std::__replace_if(__policy, std::move(__first), std::move(__last), std::move(__pred), __new_value); - if (!__res) - std::__throw_bad_alloc(); -} - -template -void __pstl_replace(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> -__replace(_ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __last, - const _Tp& __old_value, - const _Tp& __new_value) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace, _RawPolicy), - [&__policy]( - _ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_old_value, const _Tp& __g_new_value) { - return std::__replace_if( - __policy, - std::move(__g_first), - std::move(__g_last), - [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; }, - __g_new_value); - }, - std::move(__first), - std::move(__last), - __old_value, - __new_value); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -replace(_ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __last, - const _Tp& __old_value, - const _Tp& __new_value) { - if (!std::__replace(__policy, std::move(__first), std::move(__last), __old_value, __new_value)) - std::__throw_bad_alloc(); -} - -template -void __pstl_replace_copy_if(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __replace_copy_if( - _ExecutionPolicy&& __policy, - _ForwardIterator&& __first, - _ForwardIterator&& __last, - _ForwardOutIterator&& __result, - _Pred&& __pred, - const _Tp& __new_value) { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy_if, _RawPolicy), - [&__policy](_ForwardIterator __g_first, - _ForwardIterator __g_last, - _ForwardOutIterator __g_result, - _Pred __g_pred, - const _Tp& __g_new_value) -> optional<__empty> { - if (!std::__transform( - __policy, __g_first, __g_last, __g_result, [&](__iter_reference<_ForwardIterator> __element) { - return __g_pred(__element) ? __g_new_value : __element; - })) - return nullopt; - return __empty{}; - }, - std::move(__first), - std::move(__last), - std::move(__result), - std::move(__pred), - __new_value); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void replace_copy_if( - _ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __last, - _ForwardOutIterator __result, - _Pred __pred, - const _Tp& __new_value) { - if (!std::__replace_copy_if( - __policy, std::move(__first), std::move(__last), std::move(__result), std::move(__pred), __new_value)) - std::__throw_bad_alloc(); -} - -template -void __pstl_replace_copy(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __replace_copy( - _ExecutionPolicy&& __policy, - _ForwardIterator&& __first, - _ForwardIterator&& __last, - _ForwardOutIterator&& __result, - const _Tp& __old_value, - const _Tp& __new_value) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy, _RawPolicy), - [&__policy](_ForwardIterator __g_first, - _ForwardIterator __g_last, - _ForwardOutIterator __g_result, - const _Tp& __g_old_value, - const _Tp& __g_new_value) { - return std::__replace_copy_if( - __policy, - std::move(__g_first), - std::move(__g_last), - std::move(__g_result), - [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; }, - __g_new_value); - }, - std::move(__first), - std::move(__last), - std::move(__result), - __old_value, - __new_value); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void replace_copy( - _ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __last, - _ForwardOutIterator __result, - const _Tp& __old_value, - const _Tp& __new_value) { - if (!std::__replace_copy( - __policy, std::move(__first), std::move(__last), std::move(__result), __old_value, __new_value)) - std::__throw_bad_alloc(); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_REPLACE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_rotate_copy.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_rotate_copy.h deleted file mode 100644 index 346aab1d4a..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_rotate_copy.h +++ /dev/null @@ -1,85 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_ROTATE_COPY_H -#define _LIBCPP___ALGORITHM_PSTL_ROTATE_COPY_H - -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_copy.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__type_traits/is_execution_policy.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_rotate_copy(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> -__rotate_copy(_ExecutionPolicy&& __policy, - _ForwardIterator&& __first, - _ForwardIterator&& __middle, - _ForwardIterator&& __last, - _ForwardOutIterator&& __result) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_rotate_copy, _RawPolicy), - [&__policy](_ForwardIterator __g_first, - _ForwardIterator __g_middle, - _ForwardIterator __g_last, - _ForwardOutIterator __g_result) -> optional<_ForwardOutIterator> { - auto __result_mid = - std::__copy(__policy, _ForwardIterator(__g_middle), std::move(__g_last), std::move(__g_result)); - if (!__result_mid) - return nullopt; - return std::__copy(__policy, std::move(__g_first), std::move(__g_middle), *std::move(__result_mid)); - }, - std::move(__first), - std::move(__middle), - std::move(__last), - std::move(__result)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator rotate_copy( - _ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __middle, - _ForwardIterator __last, - _ForwardOutIterator __result) { - auto __res = - std::__rotate_copy(__policy, std::move(__first), std::move(__middle), std::move(__last), std::move(__result)); - if (!__res) - std::__throw_bad_alloc(); - return *__res; -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_ROTATE_COPY_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_sort.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_sort.h deleted file mode 100644 index a931f76811..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_sort.h +++ /dev/null @@ -1,82 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_SORT_H -#define _LIBCPP___ALGORITHM_PSTL_SORT_H - -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__algorithm/pstl_stable_sort.h> -#include <__config> -#include <__functional/operations.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/empty.h> -#include <__utility/forward.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_sort(); - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __sort( - _ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_sort, _RawPolicy), - [&__policy](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { - std::stable_sort(__policy, std::move(__g_first), std::move(__g_last), std::move(__g_comp)); - return optional<__empty>{__empty{}}; - }, - std::move(__first), - std::move(__last), - std::move(__comp)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { - if (!std::__sort(__policy, std::move(__first), std::move(__last), std::move(__comp))) - std::__throw_bad_alloc(); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void -sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last) { - std::sort(std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), less{}); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_SORT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_stable_sort.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_stable_sort.h deleted file mode 100644 index 8ea0bb3f9a..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_stable_sort.h +++ /dev/null @@ -1,61 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H -#define _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H - -#include <__algorithm/pstl_backend.h> -#include <__config> -#include <__functional/operations.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/empty.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template , - class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> __stable_sort( - _ExecutionPolicy&&, _RandomAccessIterator&& __first, _RandomAccessIterator&& __last, _Comp&& __comp = {}) noexcept { - using _Backend = typename __select_backend<_RawPolicy>::type; - return std::__pstl_stable_sort<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__comp)); -} - -template , - class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI void stable_sort( - _ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp = {}) { - if (!std::__stable_sort(__policy, std::move(__first), std::move(__last), std::move(__comp))) - std::__throw_bad_alloc(); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_transform.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_transform.h deleted file mode 100644 index f95938782f..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_transform.h +++ /dev/null @@ -1,120 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H -#define _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H - -#include <__algorithm/pstl_backend.h> -#include <__config> -#include <__iterator/cpp17_iterator_concepts.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/is_execution_policy.h> -#include <__type_traits/remove_cvref.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardOutIterator>> -__transform(_ExecutionPolicy&&, - _ForwardIterator&& __first, - _ForwardIterator&& __last, - _ForwardOutIterator&& __result, - _UnaryOperation&& __op) noexcept { - using _Backend = typename __select_backend<_RawPolicy>::type; - return std::__pstl_transform<_RawPolicy>( - _Backend{}, std::move(__first), std::move(__last), std::move(__result), std::move(__op)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( - _ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __last, - _ForwardOutIterator __result, - _UnaryOperation __op) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); - _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first))); - auto __res = std::__transform(__policy, std::move(__first), std::move(__last), std::move(__result), std::move(__op)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_ForwardOutIterator>> -__transform(_ExecutionPolicy&&, - _ForwardIterator1&& __first1, - _ForwardIterator1&& __last1, - _ForwardIterator2&& __first2, - _ForwardOutIterator&& __result, - _BinaryOperation&& __op) noexcept { - using _Backend = typename __select_backend<_RawPolicy>::type; - return std::__pstl_transform<_RawPolicy>( - _Backend{}, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__result), std::move(__op)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( - _ExecutionPolicy&& __policy, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _ForwardOutIterator __result, - _BinaryOperation __op) { - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1); - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2); - _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); - _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first1, *__first2))); - auto __res = std::__transform( - __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__result), std::move(__op)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_adjacent_find.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_adjacent_find.h index a10b04167e..3c54f72331 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_adjacent_find.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_adjacent_find.h @@ -53,7 +53,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_binary_predicate, projected<_Iter, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -62,7 +62,7 @@ struct __fn { class _Proj = identity, indirect_binary_predicate, _Proj>, projected, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_all_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_all_of.h index 8976541d59..2f603b32f3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_all_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_all_of.h @@ -45,7 +45,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -53,7 +53,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_any_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_any_of.h index 7c775f5f64..205fcecc08 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_any_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_any_of.h @@ -45,7 +45,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -53,7 +53,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_binary_search.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_binary_search.h index f3b7842d5c..1ef2bd62b5 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_binary_search.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_binary_search.h @@ -39,7 +39,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); @@ -49,7 +49,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_clamp.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_clamp.h index f5ef5fd7f2..e6181ef943 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_clamp.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_clamp.h @@ -35,7 +35,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()( const _Type& __value, const _Type& __low, const _Type& __high, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( !bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_contains.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_contains.h index 00d0e54019..4836c3baed 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_contains.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_contains.h @@ -37,14 +37,14 @@ namespace __contains { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) { return ranges::find(std::move(__first), __last, __value, std::ref(__proj)) != __last; } template requires indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) { return ranges::find(ranges::begin(__range), ranges::end(__range), __value, std::ref(__proj)) != ranges::end(__range); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_contains_subrange.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_contains_subrange.h index bc5a86ce3d..4398c457fd 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_contains_subrange.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_contains_subrange.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -67,7 +67,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool static operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) { if constexpr (sized_range<_Range2>) { if (ranges::size(__range2) == 0) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_count.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_count.h index a8965c1b96..4f35117438 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_count.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_count.h @@ -38,14 +38,14 @@ namespace __count { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { return std::__count<_RangeAlgPolicy>(std::move(__first), std::move(__last), __value, __proj); } template requires indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const { return std::__count<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_count_if.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_count_if.h index 71b942dd53..5f2396ff7d 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_count_if.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_count_if.h @@ -50,7 +50,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -58,7 +58,7 @@ struct __fn { template , _Proj>> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_ends_with.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_ends_with.h index bb01918326..06efdef36b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_ends_with.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_ends_with.h @@ -133,7 +133,7 @@ struct __fn { requires(forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) && (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>) && indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -152,7 +152,7 @@ struct __fn { class _Proj2 = identity> requires(forward_range<_Range1> || sized_range<_Range1>) && (forward_range<_Range2> || sized_range<_Range2>) && indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { auto __n1 = ranges::size(__range1); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_equal.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_equal.h index 31c7ee261d..edbd0e3641 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_equal.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_equal.h @@ -44,7 +44,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -74,7 +74,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_equal_range.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_equal_range.h index 4c1c3834ba..4a308e016b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_equal_range.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_equal_range.h @@ -46,7 +46,7 @@ struct __fn { class _Tp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__equal_range<_RangeAlgPolicy>(std::move(__first), std::move(__last), __value, __comp, __proj); return {std::move(__ret.first), std::move(__ret.second)}; @@ -56,7 +56,7 @@ struct __fn { class _Tp, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__equal_range<_RangeAlgPolicy>(ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find.h index 7459fad717..6b0d5efe37 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find.h @@ -44,22 +44,22 @@ struct __fn { if constexpr (forward_iterator<_Iter>) { auto [__first_un, __last_un] = std::__unwrap_range(__first, std::move(__last)); return std::__rewrap_range<_Sent>( - std::move(__first), std::__find_impl(std::move(__first_un), std::move(__last_un), __value, __proj)); + std::move(__first), std::__find(std::move(__first_un), std::move(__last_un), __value, __proj)); } else { - return std::__find_impl(std::move(__first), std::move(__last), __value, __proj); + return std::__find(std::move(__first), std::move(__last), __value, __proj); } } template _Sp, class _Tp, class _Proj = identity> requires indirect_binary_predicate, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const { return __find_unwrap(std::move(__first), std::move(__last), __value, __proj); } template requires indirect_binary_predicate, _Proj>, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const { return __find_unwrap(ranges::begin(__r), ranges::end(__r), __value, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_end.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_end.h index 0bda4f3e1c..e49e66dd4a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_end.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_end.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -72,7 +72,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __ret = std::__find_end_impl<_RangeAlgPolicy>( ranges::begin(__range1), diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_first_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_first_of.h index 63a7b8335f..d92d9686bc 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_first_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_first_of.h @@ -60,7 +60,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter1 operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter1 operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -78,7 +78,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __find_first_of_impl( ranges::begin(__range1), diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_if.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_if.h index 52ae55ce96..888f9ec3cb 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_if.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_if.h @@ -48,13 +48,13 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); } template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_if_not.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_if_not.h index 60c6796cbb..ec19545b5a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_if_not.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_find_if_not.h @@ -40,14 +40,14 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) -> bool { return !std::invoke(__pred, std::forward(__e)); }; return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred2, __proj); } template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) -> bool { return !std::invoke(__pred, std::forward(__e)); }; return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred2, __proj); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_includes.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_includes.h index 0bc4c043bd..c4c3b8ed08 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_includes.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_includes.h @@ -45,7 +45,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -69,7 +69,7 @@ struct __fn { class _Proj2 = identity, indirect_strict_weak_order, _Proj1>, projected, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return std::__includes( ranges::begin(__range1), diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_heap.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_heap.h index 122368c90d..3d9e18ce1d 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_heap.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_heap.h @@ -51,7 +51,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -59,7 +59,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_heap_until.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_heap_until.h index b2705d37a6..7a2e1fc770 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_heap_until.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_heap_until.h @@ -51,7 +51,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -59,7 +59,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_partitioned.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_partitioned.h index c6a585c9f5..5be6fba46f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_partitioned.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_partitioned.h @@ -57,7 +57,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __is_partitioned_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -65,7 +65,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __is_partitioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_permutation.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_permutation.h index e0423d722b..1f8d67007a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_permutation.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_permutation.h @@ -56,7 +56,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_equivalence_relation, projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -74,7 +74,7 @@ struct __fn { class _Proj2 = identity, indirect_equivalence_relation, _Proj1>, projected, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_sorted.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_sorted.h index d71035d5aa..5b88d422b4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_sorted.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_sorted.h @@ -37,7 +37,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), __last, __comp, __proj) == __last; } @@ -45,7 +45,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { auto __last = ranges::end(__range); return ranges::__is_sorted_until_impl(ranges::begin(__range), __last, __comp, __proj) == __last; diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_sorted_until.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_sorted_until.h index dcfb6a4e18..54de530c8b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_sorted_until.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_is_sorted_until.h @@ -53,7 +53,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), std::move(__last), __comp, __proj); } @@ -61,7 +61,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_lexicographical_compare.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_lexicographical_compare.h index 90e96b5465..6d82017e30 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_lexicographical_compare.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_lexicographical_compare.h @@ -60,7 +60,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity, indirect_strict_weak_order, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -78,7 +78,7 @@ struct __fn { class _Proj2 = identity, indirect_strict_weak_order, _Proj1>, projected, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __lexicographical_compare_impl( ranges::begin(__range1), diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_lower_bound.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_lower_bound.h index ab1f80e7ab..0651147e04 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_lower_bound.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_lower_bound.h @@ -43,7 +43,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { return std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); } @@ -52,7 +52,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { return std::__lower_bound<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __comp, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_max.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_max.h index c63656de51..d0ee6f314b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_max.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_max.h @@ -41,7 +41,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Comp __comp = {}, @@ -52,7 +52,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list must contain at least one element"); @@ -65,7 +65,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_max_element.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_max_element.h index 83adf49b61..c577309271 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_max_element.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_max_element.h @@ -38,7 +38,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj); @@ -47,7 +47,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_min.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_min.h index e8f97f2754..cc569d2a06 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_min.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_min.h @@ -40,7 +40,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Comp __comp = {}, @@ -51,7 +51,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list must contain at least one element"); @@ -62,7 +62,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_min_element.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_min_element.h index 4b9cb76da5..588ef258e2 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_min_element.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_min_element.h @@ -52,7 +52,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__min_element_impl(__first, __last, __comp, __proj); } @@ -60,7 +60,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_minmax.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_minmax.h index ca57225233..09cbefd91a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_minmax.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_minmax.h @@ -52,7 +52,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result operator()(_LIBCPP_LIFETIMEBOUND const _Type& __a, _LIBCPP_LIFETIMEBOUND const _Type& __b, _Comp __comp = {}, @@ -65,7 +65,7 @@ struct __fn { template > _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<_Type> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<_Type> operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __il.begin() != __il.end(), "initializer_list has to contain at least one element"); @@ -77,7 +77,7 @@ struct __fn { class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable, range_value_t<_Range>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_minmax_element.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_minmax_element.h index 5132856ebc..4bf6d2404e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_minmax_element.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_minmax_element.h @@ -46,7 +46,7 @@ struct __fn { sentinel_for<_Ip> _Sp, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<_Ip> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<_Ip> operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(std::move(__first), std::move(__last), __comp, __proj); return {__ret.first, __ret.second}; @@ -55,7 +55,7 @@ struct __fn { template , _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); return {__ret.first, __ret.second}; diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_mismatch.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_mismatch.h index d8a7dd43af..c4bf0022a9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_mismatch.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_mismatch.h @@ -65,7 +65,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_I1, _I2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> operator()( _I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __go(std::move(__first1), __last1, std::move(__first2), __last2, __pred, __proj1, __proj2); @@ -77,7 +77,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_R2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result, borrowed_iterator_t<_R2>> operator()(_R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __go( diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_none_of.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_none_of.h index 59bd87997d..7df3c1829f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_none_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_none_of.h @@ -46,7 +46,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __none_of_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -54,7 +54,7 @@ struct __fn { template , _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __none_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_remove.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_remove.h index 315bed8fba..17c3a2c5cd 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_remove.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_remove.h @@ -37,7 +37,7 @@ namespace __remove { struct __fn { template _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) -> bool { return __value == __other; }; return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); @@ -46,7 +46,7 @@ struct __fn { template requires permutable> && indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) -> bool { return __value == __other; }; return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_remove_if.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_remove_if.h index 943dbdd738..0ea5d9a01b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_remove_if.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_remove_if.h @@ -59,7 +59,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -68,7 +68,7 @@ struct __fn { class _Proj = identity, indirect_unary_predicate, _Proj>> _Pred> requires permutable> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_search.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_search.h index ca2326e9ab..55294c6063 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_search.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_search.h @@ -77,7 +77,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -94,7 +94,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __first1 = ranges::begin(__range1); if constexpr (sized_range<_Range2>) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_search_n.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_search_n.h index 4c1d73d8e6..56e12755b9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_search_n.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_search_n.h @@ -71,7 +71,7 @@ struct __fn { class _Pred = ranges::equal_to, class _Proj = identity> requires indirectly_comparable<_Iter, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, @@ -83,7 +83,7 @@ struct __fn { template requires indirectly_comparable, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()( _Range&& __range, range_difference_t<_Range> __count, const _Type& __value, _Pred __pred = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__range); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_starts_with.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_starts_with.h index 7ba8af13a8..17084e4f24 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_starts_with.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_starts_with.h @@ -42,7 +42,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()( + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -67,7 +67,7 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) { return __mismatch::__fn::__go( ranges::begin(__range1), diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_unique.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_unique.h index 7340310eb3..7a9b784321 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_unique.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_unique.h @@ -47,7 +47,7 @@ struct __fn { sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_equivalence_relation> _Comp = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__unique<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); @@ -58,7 +58,7 @@ struct __fn { class _Proj = identity, indirect_equivalence_relation, _Proj>> _Comp = ranges::equal_to> requires permutable> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__unique<_RangeAlgPolicy>( ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_upper_bound.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_upper_bound.h index 7b571fb344..fa6fa7f70e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_upper_bound.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/ranges_upper_bound.h @@ -37,7 +37,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) -> bool { return !std::invoke(__comp, __rhs, __lhs); @@ -50,7 +50,7 @@ struct __fn { class _Type, class _Proj = identity, indirect_strict_weak_order, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) -> bool { return !std::invoke(__comp, __rhs, __lhs); diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/remove.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/remove.h index 1498852c43..fd01c23cb6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/remove.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/remove.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { __first = std::find(__first, __last, __value); if (__first != __last) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/remove_if.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/remove_if.h index c77b78023f..b14f3c0efa 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/remove_if.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/remove_if.h @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { __first = std::find_if<_ForwardIterator, _Predicate&>(__first, __last, __pred); if (__first != __last) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/search.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/search.h index 8557c76f80..b82ca78095 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/search.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/search.h @@ -160,7 +160,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __searc } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, @@ -173,14 +173,14 @@ search(_ForwardIterator1 __first1, } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { return std::search(__first1, __last1, __first2, __last2, __equal_to()); } #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) { return __s(__f, __l).first; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/search_n.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/search_n.h index 12007fa7de..771647d316 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/search_n.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/search_n.h @@ -136,7 +136,7 @@ __search_n_impl(_Iter1 __first, _Sent1 __last, _DiffT __count, const _Type& __va } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n( +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n( _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) { static_assert( __is_callable<_BinaryPredicate, decltype(*__first), const _Tp&>::value, "BinaryPredicate has to be callable"); @@ -145,7 +145,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) { return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/simd_utils.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/simd_utils.h index 8d540ae2cc..549197be80 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/simd_utils.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/simd_utils.h @@ -11,6 +11,7 @@ #include <__algorithm/min.h> #include <__bit/bit_cast.h> +#include <__bit/countl.h> #include <__bit/countr.h> #include <__config> #include <__type_traits/is_arithmetic.h> @@ -43,10 +44,38 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +template +inline constexpr bool __can_map_to_integer_v = + sizeof(_Tp) == alignof(_Tp) && (sizeof(_Tp) == 1 || sizeof(_Tp) == 2 || sizeof(_Tp) == 4 || sizeof(_Tp) == 8); + +template +struct __get_as_integer_type_impl; + +template <> +struct __get_as_integer_type_impl<1> { + using type = uint8_t; +}; + +template <> +struct __get_as_integer_type_impl<2> { + using type = uint16_t; +}; +template <> +struct __get_as_integer_type_impl<4> { + using type = uint32_t; +}; +template <> +struct __get_as_integer_type_impl<8> { + using type = uint64_t; +}; + +template +using __get_as_integer_type_t = typename __get_as_integer_type_impl::type; + // This isn't specialized for 64 byte vectors on purpose. They have the potential to significantly reduce performance // in mixed simd/non-simd workloads and don't provide any performance improvement for currently vectorized algorithms // as far as benchmarks are concerned. -# if defined(__AVX__) +# if defined(__AVX__) || defined(__MVS__) template inline constexpr size_t __native_vector_size = 32 / sizeof(_Tp); # elif defined(__SSE__) || defined(__ARM_NEON__) @@ -80,10 +109,10 @@ template using __simd_vector_underlying_type_t = decltype(std::__simd_vector_underlying_type_impl(_VecT{})); // This isn't inlined without always_inline when loading chars. -template -_LIBCPP_NODISCARD _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _VecT __load_vector(const _Tp* __ptr) noexcept { +template +_LIBCPP_NODISCARD _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _VecT __load_vector(_Iter __iter) noexcept { return [=](index_sequence<_Indices...>) _LIBCPP_ALWAYS_INLINE noexcept { - return _VecT{__ptr[_Indices]...}; + return _VecT{__iter[_Indices]...}; }(make_index_sequence<__simd_vector_size_v<_VecT>>{}); } @@ -98,8 +127,13 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_T // This has MSan disabled du to https://github.com/llvm/llvm-project/issues/85876 auto __impl = [&](_MaskT) _LIBCPP_NO_SANITIZE("memory") noexcept { +# if defined(_LIBCPP_BIG_ENDIAN) + return std::min( + _Np, std::__countl_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec)))); +# else return std::min( _Np, std::__countr_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec)))); +# endif }; if constexpr (sizeof(__mask_vec) == sizeof(uint8_t)) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/sort.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/sort.h index 8a5e0211cd..07b5814639 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/sort.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/sort.h @@ -696,9 +696,8 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; - // TODO(LLVM18): Make __begin const, see https://reviews.llvm.org/D147089#4349748 - _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around - const _RandomAccessIterator __end = __last; + const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around + const _RandomAccessIterator __end = __last; (void)__end; // value_type __pivot(_Ops::__iter_move(__first)); if (__comp(__pivot, *(__last - difference_type(1)))) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/unique.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/unique.h index 056373d06f..d597014596 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/unique.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/unique.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // unique template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter> __unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { __first = std::__adjacent_find(__first, __last, __pred); if (__first != __last) { @@ -46,13 +46,13 @@ __unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) { } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first; } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator unique(_ForwardIterator __first, _ForwardIterator __last) { return std::unique(__first, __last, __equal_to()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/upper_bound.h b/naiveproxy/src/third_party/libc++/src/include/__algorithm/upper_bound.h index 9c7d8fbcde..c39dec2e89 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/upper_bound.h +++ b/naiveproxy/src/third_party/libc++/src/include/__algorithm/upper_bound.h @@ -48,7 +48,7 @@ __upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible"); return std::__upper_bound<_ClassicAlgPolicy>( @@ -56,7 +56,7 @@ upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu } template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { return std::upper_bound(std::move(__first), std::move(__last), __value, __less<>()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic.h index 3dfb6937d0..bd3f659c22 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic.h +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic.h @@ -462,22 +462,26 @@ atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __ // atomic_notify_one template -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT { +_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void +atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT { __o->notify_one(); } template -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT { +_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void +atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT { __o->notify_one(); } // atomic_notify_all template -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT { +_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void +atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT { __o->notify_all(); } template -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT { +_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void +atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT { __o->notify_all(); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_base.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_base.h index e9badccc25..7e26434c9c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_base.h +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_base.h @@ -14,7 +14,6 @@ #include <__atomic/cxx_atomic_impl.h> #include <__atomic/is_always_lock_free.h> #include <__atomic/memory_order.h> -#include <__availability> #include <__config> #include <__memory/addressof.h> #include <__type_traits/is_integral.h> @@ -34,7 +33,7 @@ struct __atomic_base // false mutable __cxx_atomic_impl<_Tp> __a_; #if _LIBCPP_STD_VER >= 17 - static _LIBCPP_CONSTEXPR bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; + static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; #endif _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const volatile _NOEXCEPT { @@ -130,11 +129,6 @@ struct __atomic_base // false __atomic_base(const __atomic_base&) = delete; }; -#if _LIBCPP_STD_VER >= 17 -template -_LIBCPP_CONSTEXPR bool __atomic_base<_Tp, __b>::is_always_lock_free; -#endif - // atomic template diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_flag.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_flag.h index 084366237c..00b157cdff 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_flag.h +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_flag.h @@ -13,7 +13,6 @@ #include <__atomic/contention_t.h> #include <__atomic/cxx_atomic_impl.h> #include <__atomic/memory_order.h> -#include <__availability> #include <__chrono/duration.h> #include <__config> #include <__memory/addressof.h> @@ -49,22 +48,26 @@ struct atomic_flag { __cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(bool __v, memory_order __m = memory_order_seq_cst) const - volatile _NOEXCEPT { + _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void + wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT { std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void + _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT { std::__atomic_wait(*this, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { + _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { + std::__atomic_notify_one(*this); + } + _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { std::__atomic_notify_all(*this); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); } + _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { + std::__atomic_notify_all(*this); + } #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr atomic_flag() _NOEXCEPT : __a_(false) {} @@ -141,41 +144,43 @@ inline _LIBCPP_HIDE_FROM_ABI void atomic_flag_clear_explicit(atomic_flag* __o, m __o->clear(__m); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT { __o->wait(__v); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_wait_explicit(const volatile atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT { __o->wait(__v, __m); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_wait_explicit(const atomic_flag* __o, bool __v, memory_order __m) _NOEXCEPT { __o->wait(__v, __m); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_one(); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT { +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT { __o->notify_one(); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT { __o->notify_all(); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT { +inline _LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC void +atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT { __o->notify_all(); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_init.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_init.h index 8ef5958bfe..8e86ba31b4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_init.h +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_init.h @@ -15,12 +15,10 @@ # pragma GCC system_header #endif -#define ATOMIC_FLAG_INIT \ - { false } -#define ATOMIC_VAR_INIT(__v) \ - { __v } +#define ATOMIC_FLAG_INIT {false} +#define ATOMIC_VAR_INIT(__v) {__v} -#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) +#if _LIBCPP_STD_VER >= 20 && defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) # pragma clang deprecated(ATOMIC_VAR_INIT) #endif diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_ref.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_ref.h new file mode 100644 index 0000000000..156f196115 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_ref.h @@ -0,0 +1,360 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ATOMIC_REF_H +#define _LIBCPP___ATOMIC_ATOMIC_REF_H + +#include <__assert> +#include <__atomic/atomic_sync.h> +#include <__atomic/check_memory_order.h> +#include <__atomic/to_gcc_order.h> +#include <__concepts/arithmetic.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__memory/addressof.h> +#include <__type_traits/has_unique_object_representation.h> +#include <__type_traits/is_trivially_copyable.h> +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template +struct __atomic_ref_base { +protected: + _Tp* __ptr_; + + _LIBCPP_HIDE_FROM_ABI __atomic_ref_base(_Tp& __obj) : __ptr_(std::addressof(__obj)) {} + +private: + _LIBCPP_HIDE_FROM_ABI static _Tp* __clear_padding(_Tp& __val) noexcept { + _Tp* __ptr = std::addressof(__val); +# if __has_builtin(__builtin_clear_padding) + __builtin_clear_padding(__ptr); +# endif + return __ptr; + } + + _LIBCPP_HIDE_FROM_ABI static bool __compare_exchange( + _Tp* __ptr, _Tp* __expected, _Tp* __desired, bool __is_weak, int __success, int __failure) noexcept { + if constexpr ( +# if __has_builtin(__builtin_clear_padding) + has_unique_object_representations_v<_Tp> || floating_point<_Tp> +# else + true // NOLINT(readability-simplify-boolean-expr) +# endif + ) { + return __atomic_compare_exchange(__ptr, __expected, __desired, __is_weak, __success, __failure); + } else { // _Tp has padding bits and __builtin_clear_padding is available + __clear_padding(*__desired); + _Tp __copy = *__expected; + __clear_padding(__copy); + // The algorithm we use here is basically to perform `__atomic_compare_exchange` on the + // values until it has either succeeded, or failed because the value representation of the + // objects involved was different. This is why we loop around __atomic_compare_exchange: + // we basically loop until its failure is caused by the value representation of the objects + // being different, not only their object representation. + while (true) { + _Tp __prev = __copy; + if (__atomic_compare_exchange(__ptr, std::addressof(__copy), __desired, __is_weak, __success, __failure)) { + return true; + } + _Tp __curr = __copy; + if (std::memcmp(__clear_padding(__prev), __clear_padding(__curr), sizeof(_Tp)) != 0) { + // Value representation without padding bits do not compare equal -> + // write the current content of *ptr into *expected + std::memcpy(__expected, std::addressof(__copy), sizeof(_Tp)); + return false; + } + } + } + } + + friend struct __atomic_waitable_traits<__atomic_ref_base<_Tp>>; + +public: + using value_type = _Tp; + + static constexpr size_t required_alignment = alignof(_Tp); + + // The __atomic_always_lock_free builtin takes into account the alignment of the pointer if provided, + // so we create a fake pointer with a suitable alignment when querying it. Note that we are guaranteed + // that the pointer is going to be aligned properly at runtime because that is a (checked) precondition + // of atomic_ref's constructor. + static constexpr bool is_always_lock_free = + __atomic_always_lock_free(sizeof(_Tp), reinterpret_cast(-required_alignment)); + + _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); } + + _LIBCPP_HIDE_FROM_ABI void store(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__order) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __order == memory_order::relaxed || __order == memory_order::release || __order == memory_order::seq_cst, + "atomic_ref: memory order argument to atomic store operation is invalid"); + __atomic_store(__ptr_, __clear_padding(__desired), std::__to_gcc_order(__order)); + } + + _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { + store(__desired); + return __desired; + } + + _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __order = memory_order::seq_cst) const noexcept + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__order) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire || + __order == memory_order::seq_cst, + "atomic_ref: memory order argument to atomic load operation is invalid"); + alignas(_Tp) byte __mem[sizeof(_Tp)]; + auto* __ret = reinterpret_cast<_Tp*>(__mem); + __atomic_load(__ptr_, __ret, std::__to_gcc_order(__order)); + return *__ret; + } + + _LIBCPP_HIDE_FROM_ABI operator _Tp() const noexcept { return load(); } + + _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { + alignas(_Tp) byte __mem[sizeof(_Tp)]; + auto* __ret = reinterpret_cast<_Tp*>(__mem); + __atomic_exchange(__ptr_, __clear_padding(__desired), __ret, std::__to_gcc_order(__order)); + return *__ret; + } + + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, memory_order __success, memory_order __failure) const noexcept + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __failure == memory_order::relaxed || __failure == memory_order::consume || + __failure == memory_order::acquire || __failure == memory_order::seq_cst, + "atomic_ref: failure memory order argument to weak atomic compare-and-exchange operation is invalid"); + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + true, + std::__to_gcc_order(__success), + std::__to_gcc_order(__failure)); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, memory_order __success, memory_order __failure) const noexcept + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __failure == memory_order::relaxed || __failure == memory_order::consume || + __failure == memory_order::acquire || __failure == memory_order::seq_cst, + "atomic_ref: failure memory order argument to strong atomic compare-and-exchange operation is invalid"); + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + false, + std::__to_gcc_order(__success), + std::__to_gcc_order(__failure)); + } + + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + true, + std::__to_gcc_order(__order), + std::__to_gcc_failure_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept { + return __compare_exchange( + __ptr_, + std::addressof(__expected), + std::addressof(__desired), + false, + std::__to_gcc_order(__order), + std::__to_gcc_failure_order(__order)); + } + + _LIBCPP_HIDE_FROM_ABI void wait(_Tp __old, memory_order __order = memory_order::seq_cst) const noexcept + _LIBCPP_CHECK_WAIT_MEMORY_ORDER(__order) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire || + __order == memory_order::seq_cst, + "atomic_ref: memory order argument to atomic wait operation is invalid"); + std::__atomic_wait(*this, __old, __order); + } + _LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept { std::__atomic_notify_one(*this); } + _LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); } +}; + +template +struct __atomic_waitable_traits<__atomic_ref_base<_Tp>> { + static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_ref_base<_Tp>& __a, memory_order __order) { + return __a.load(__order); + } + static _LIBCPP_HIDE_FROM_ABI const _Tp* __atomic_contention_address(const __atomic_ref_base<_Tp>& __a) { + return __a.__ptr_; + } +}; + +template +struct atomic_ref : public __atomic_ref_base<_Tp> { + static_assert(is_trivially_copyable_v<_Tp>, "std::atomic_ref requires that 'T' be a trivially copyable type"); + + using __base = __atomic_ref_base<_Tp>; + + _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, + "atomic_ref ctor: referenced object must be aligned to required_alignment"); + } + + _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + + atomic_ref& operator=(const atomic_ref&) = delete; +}; + +template + requires(std::integral<_Tp> && !std::same_as) +struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { + using __base = __atomic_ref_base<_Tp>; + + using difference_type = __base::value_type; + + _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, + "atomic_ref ctor: referenced object must be aligned to required_alignment"); + } + + _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + + atomic_ref& operator=(const atomic_ref&) = delete; + + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_add(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_sub(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_and(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_or(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_xor(this->__ptr_, __arg, std::__to_gcc_order(__order)); + } + + _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) const noexcept { return fetch_add(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) const noexcept { return fetch_sub(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _Tp operator++() const noexcept { return fetch_add(_Tp(1)) + _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _Tp operator--() const noexcept { return fetch_sub(_Tp(1)) - _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __arg) const noexcept { return fetch_and(__arg) & __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __arg) const noexcept { return fetch_or(__arg) | __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __arg) const noexcept { return fetch_xor(__arg) ^ __arg; } +}; + +template + requires std::floating_point<_Tp> +struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { + using __base = __atomic_ref_base<_Tp>; + + using difference_type = __base::value_type; + + _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + reinterpret_cast(std::addressof(__obj)) % __base::required_alignment == 0, + "atomic_ref ctor: referenced object must be aligned to required_alignment"); + } + + _LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); } + + atomic_ref& operator=(const atomic_ref&) = delete; + + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _Tp __old = this->load(memory_order_relaxed); + _Tp __new = __old + __arg; + while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) { + __new = __old + __arg; + } + return __old; + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept { + _Tp __old = this->load(memory_order_relaxed); + _Tp __new = __old - __arg; + while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) { + __new = __old - __arg; + } + return __old; + } + + _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; } +}; + +template +struct atomic_ref<_Tp*> : public __atomic_ref_base<_Tp*> { + using __base = __atomic_ref_base<_Tp*>; + + using difference_type = ptrdiff_t; + + _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp*& __ptr) : __base(__ptr) {} + + _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __desired) const noexcept { return __base::operator=(__desired); } + + atomic_ref& operator=(const atomic_ref&) = delete; + + _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_add(this->__ptr_, __arg * sizeof(_Tp), std::__to_gcc_order(__order)); + } + _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept { + return __atomic_fetch_sub(this->__ptr_, __arg * sizeof(_Tp), std::__to_gcc_order(__order)); + } + + _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) const noexcept { return fetch_add(1); } + _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) const noexcept { return fetch_sub(1); } + _LIBCPP_HIDE_FROM_ABI _Tp* operator++() const noexcept { return fetch_add(1) + 1; } + _LIBCPP_HIDE_FROM_ABI _Tp* operator--() const noexcept { return fetch_sub(1) - 1; } + _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __arg) const noexcept { return fetch_add(__arg) + __arg; } + _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __arg) const noexcept { return fetch_sub(__arg) - __arg; } +}; + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(atomic_ref); + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP__ATOMIC_ATOMIC_REF_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_sync.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_sync.h index e583dca38c..aaf81f5873 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_sync.h +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/atomic_sync.h @@ -12,7 +12,7 @@ #include <__atomic/contention_t.h> #include <__atomic/cxx_atomic_impl.h> #include <__atomic/memory_order.h> -#include <__availability> +#include <__atomic/to_gcc_order.h> #include <__chrono/duration.h> #include <__config> #include <__memory/addressof.h> @@ -71,19 +71,21 @@ struct __atomic_wait_poll_impl { #ifndef _LIBCPP_HAS_NO_THREADS -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile*, __cxx_contention_t); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*) _NOEXCEPT; +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*) _NOEXCEPT; +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t +__libcpp_atomic_monitor(void const volatile*) _NOEXCEPT; +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void +__libcpp_atomic_wait(void const volatile*, __cxx_contention_t) _NOEXCEPT; _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void -__cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*); +__cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*) _NOEXCEPT; _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void -__cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*); +__cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*) _NOEXCEPT; _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t -__libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*); +__libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*) _NOEXCEPT; _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void -__libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t); +__libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t) _NOEXCEPT; template struct __atomic_wait_backoff_impl { diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/check_memory_order.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/check_memory_order.h index 3012aec052..536f764a61 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__atomic/check_memory_order.h +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/check_memory_order.h @@ -27,4 +27,8 @@ _LIBCPP_DIAGNOSE_WARNING(__f == memory_order_release || __f == memory_order_acq_rel, \ "memory order argument to atomic operation is invalid") +#define _LIBCPP_CHECK_WAIT_MEMORY_ORDER(__m) \ + _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_release || __m == memory_order_acq_rel, \ + "memory order argument to atomic operation is invalid") + #endif // _LIBCPP___ATOMIC_CHECK_MEMORY_ORDER_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/cxx_atomic_impl.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/cxx_atomic_impl.h index b900cc135f..18e88aa97b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__atomic/cxx_atomic_impl.h +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/cxx_atomic_impl.h @@ -10,6 +10,7 @@ #define _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H #include <__atomic/memory_order.h> +#include <__atomic/to_gcc_order.h> #include <__config> #include <__memory/addressof.h> #include <__type_traits/is_assignable.h> @@ -54,32 +55,6 @@ struct __cxx_atomic_base_impl { _Tp __a_value; }; -_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_order(memory_order __order) { - // Avoid switch statement to make this a constexpr. - return __order == memory_order_relaxed - ? __ATOMIC_RELAXED - : (__order == memory_order_acquire - ? __ATOMIC_ACQUIRE - : (__order == memory_order_release - ? __ATOMIC_RELEASE - : (__order == memory_order_seq_cst - ? __ATOMIC_SEQ_CST - : (__order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_CONSUME)))); -} - -_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_failure_order(memory_order __order) { - // Avoid switch statement to make this a constexpr. - return __order == memory_order_relaxed - ? __ATOMIC_RELAXED - : (__order == memory_order_acquire - ? __ATOMIC_ACQUIRE - : (__order == memory_order_release - ? __ATOMIC_RELAXED - : (__order == memory_order_seq_cst - ? __ATOMIC_SEQ_CST - : (__order == memory_order_acq_rel ? __ATOMIC_ACQUIRE : __ATOMIC_CONSUME)))); -} - template _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { __cxx_atomic_assign_volatile(__a->__a_value, __val); diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/memory_order.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/memory_order.h index 16fd186769..294121d1c4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__atomic/memory_order.h +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/memory_order.h @@ -37,7 +37,7 @@ enum class memory_order : __memory_order_underlying_t { seq_cst = __mo_seq_cst }; -static_assert((is_same::type, __memory_order_underlying_t>::value), +static_assert(is_same::type, __memory_order_underlying_t>::value, "unexpected underlying type for std::memory_order"); inline constexpr auto memory_order_relaxed = memory_order::relaxed; diff --git a/naiveproxy/src/third_party/libc++/src/include/__atomic/to_gcc_order.h b/naiveproxy/src/third_party/libc++/src/include/__atomic/to_gcc_order.h new file mode 100644 index 0000000000..d04c111add --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__atomic/to_gcc_order.h @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_TO_GCC_ORDER_H +#define _LIBCPP___ATOMIC_TO_GCC_ORDER_H + +#include <__atomic/memory_order.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(__ATOMIC_RELAXED) && defined(__ATOMIC_CONSUME) && defined(__ATOMIC_ACQUIRE) && \ + defined(__ATOMIC_RELEASE) && defined(__ATOMIC_ACQ_REL) && defined(__ATOMIC_SEQ_CST) + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_relaxed + ? __ATOMIC_RELAXED + : (__order == memory_order_acquire + ? __ATOMIC_ACQUIRE + : (__order == memory_order_release + ? __ATOMIC_RELEASE + : (__order == memory_order_seq_cst + ? __ATOMIC_SEQ_CST + : (__order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_CONSUME)))); +} + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_failure_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_relaxed + ? __ATOMIC_RELAXED + : (__order == memory_order_acquire + ? __ATOMIC_ACQUIRE + : (__order == memory_order_release + ? __ATOMIC_RELAXED + : (__order == memory_order_seq_cst + ? __ATOMIC_SEQ_CST + : (__order == memory_order_acq_rel ? __ATOMIC_ACQUIRE : __ATOMIC_CONSUME)))); +} + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_TO_GCC_ORDER_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__availability b/naiveproxy/src/third_party/libc++/src/include/__availability deleted file mode 100644 index bb3ed0a8da..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__availability +++ /dev/null @@ -1,324 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___AVAILABILITY -#define _LIBCPP___AVAILABILITY - -#include <__config> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -// Libc++ is shipped by various vendors. In particular, it is used as a system -// library on macOS, iOS and other Apple platforms. In order for users to be -// able to compile a binary that is intended to be deployed to an older version -// of a platform, Clang provides availability attributes [1]. These attributes -// can be placed on declarations and are used to describe the life cycle of a -// symbol in the library. -// -// The main goal is to ensure a compile-time error if a symbol that hasn't been -// introduced in a previously released library is used in a program that targets -// that previously released library. Normally, this would be a load-time error -// when one tries to launch the program against the older library. -// -// For example, the filesystem library was introduced in the dylib in macOS 10.15. -// If a user compiles on a macOS 10.15 host but targets macOS 10.13 with their -// program, the compiler would normally not complain (because the required -// declarations are in the headers), but the dynamic loader would fail to find -// the symbols when actually trying to launch the program on macOS 10.13. To -// turn this into a compile-time issue instead, declarations are annotated with -// when they were introduced, and the compiler can produce a diagnostic if the -// program references something that isn't available on the deployment target. -// -// This mechanism is general in nature, and any vendor can add their markup to -// the library (see below). Whenever a new feature is added that requires support -// in the shared library, two macros are added below to allow marking the feature -// as unavailable: -// 1. A macro named `_LIBCPP_AVAILABILITY_HAS_NO_` which must be defined -// exactly when compiling for a target that doesn't support the feature. -// 2. A macro named `_LIBCPP_AVAILABILITY_`, which must always be defined -// and must expand to the proper availability attribute for the platform. -// -// When vendors decide to ship the feature as part of their shared library, they -// can update these macros appropriately for their platform, and the library will -// use those to provide an optimal user experience. -// -// Furthermore, many features in the standard library have corresponding -// feature-test macros. The `_LIBCPP_AVAILABILITY_HAS_NO_` macros -// are checked by the corresponding feature-test macros generated by -// generate_feature_test_macro_components.py to ensure that the library -// doesn't announce a feature as being implemented if it is unavailable on -// the deployment target. -// -// Note that this mechanism is disabled by default in the "upstream" libc++. -// Availability annotations are only meaningful when shipping libc++ inside -// a platform (i.e. as a system library), and so vendors that want them should -// turn those annotations on at CMake configuration time. -// -// [1]: https://clang.llvm.org/docs/AttributeReference.html#availability - -// For backwards compatibility, allow users to define _LIBCPP_DISABLE_AVAILABILITY -// for a while. -#if defined(_LIBCPP_DISABLE_AVAILABILITY) -# if !defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) -# define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -# endif -#endif - -// Availability markup is disabled when building the library, or when a non-Clang -// compiler is used because only Clang supports the necessary attributes. -// doesn't support the proper attributes. -#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || !defined(_LIBCPP_COMPILER_CLANG_BASED) -# if !defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) -# define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS -# endif -#endif - -#if defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) - -// These macros control the availability of std::bad_optional_access and -// other exception types. These were put in the shared library to prevent -// code bloat from every user program defining the vtable for these exception -// types. -// -// Note that when exceptions are disabled, the methods that normally throw -// these exceptions can be used even on older deployment targets, but those -// methods will abort instead of throwing. -# define _LIBCPP_AVAILABILITY_HAS_BAD_OPTIONAL_ACCESS 1 -# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS - -# define _LIBCPP_AVAILABILITY_HAS_BAD_VARIANT_ACCESS 1 -# define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS - -# define _LIBCPP_AVAILABILITY_HAS_BAD_ANY_CAST 1 -# define _LIBCPP_AVAILABILITY_BAD_ANY_CAST - -// These macros control the availability of all parts of that -// depend on something in the dylib. -# define _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY 1 -# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY -# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH -# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP - -// This controls the availability of the C++20 synchronization library, -// which requires shared library support for various operations -// (see libcxx/src/atomic.cpp). This includes , , -// , and notification functions on std::atomic. -# define _LIBCPP_AVAILABILITY_HAS_SYNC 1 -# define _LIBCPP_AVAILABILITY_SYNC - -// Enable additional explicit instantiations of iostreams components. This -// reduces the number of weak definitions generated in programs that use -// iostreams by providing a single strong definition in the shared library. -// -// TODO: Enable additional explicit instantiations on GCC once it supports exclude_from_explicit_instantiation, -// or once libc++ doesn't use the attribute anymore. -// TODO: Enable them on Windows once https://llvm.org/PR41018 has been fixed. -# if !defined(_LIBCPP_COMPILER_GCC) && !defined(_WIN32) -# define _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 1 -# else -# define _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 0 -# endif - -// This controls the availability of floating-point std::to_chars functions. -// These overloads were added later than the integer overloads. -# define _LIBCPP_AVAILABILITY_HAS_TO_CHARS_FLOATING_POINT 1 -# define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT - -// This controls whether the library claims to provide a default verbose -// termination function, and consequently whether the headers will try -// to use it when the mechanism isn't overriden at compile-time. -# define _LIBCPP_AVAILABILITY_HAS_VERBOSE_ABORT 1 -# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT - -// This controls the availability of the C++17 std::pmr library, -// which is implemented in large part in the built library. -# define _LIBCPP_AVAILABILITY_HAS_PMR 1 -# define _LIBCPP_AVAILABILITY_PMR - -// These macros controls the availability of __cxa_init_primary_exception -// in the built library, which std::make_exception_ptr might use -// (see libcxx/include/__exception/exception_ptr.h). -# define _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION 1 -# define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION - -// This controls the availability of C++23 , which -// has a dependency on the built library (it needs access to -// the underlying buffer types of std::cout, std::cerr, and std::clog. -# define _LIBCPP_AVAILABILITY_HAS_PRINT 1 -# define _LIBCPP_AVAILABILITY_PRINT - -// This controls the availability of the C++20 time zone database. -// The parser code is built in the library. -# define _LIBCPP_AVAILABILITY_HAS_TZDB 1 -# define _LIBCPP_AVAILABILITY_TZDB - -#elif defined(__APPLE__) - -# define _LIBCPP_AVAILABILITY_HAS_BAD_OPTIONAL_ACCESS \ - (!defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) || __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 50000) - -# define _LIBCPP_AVAILABILITY_HAS_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_HAS_BAD_OPTIONAL_ACCESS -# define _LIBCPP_AVAILABILITY_HAS_BAD_ANY_CAST _LIBCPP_AVAILABILITY_HAS_BAD_OPTIONAL_ACCESS - -# define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((availability(watchos, strict, introduced = 5.0))) -# define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS -# define _LIBCPP_AVAILABILITY_BAD_ANY_CAST _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS - -// TODO: Update once this is released -# define _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION 0 -# define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION __attribute__((unavailable)) - -// -// clang-format off -# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) -// clang-format on -# define _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY 0 -# else -# define _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY 1 -# endif -# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY \ - __attribute__((availability(macos, strict, introduced = 10.15))) \ - __attribute__((availability(ios, strict, introduced = 13.0))) \ - __attribute__((availability(tvos, strict, introduced = 13.0))) \ - __attribute__((availability(watchos, strict, introduced = 6.0))) -// clang-format off -# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH \ - _Pragma("clang attribute push(__attribute__((availability(macos,strict,introduced=10.15))), apply_to=any(function,record))") \ - _Pragma("clang attribute push(__attribute__((availability(ios,strict,introduced=13.0))), apply_to=any(function,record))") \ - _Pragma("clang attribute push(__attribute__((availability(tvos,strict,introduced=13.0))), apply_to=any(function,record))") \ - _Pragma("clang attribute push(__attribute__((availability(watchos,strict,introduced=6.0))), apply_to=any(function,record))") -# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP \ - _Pragma("clang attribute pop") \ - _Pragma("clang attribute pop") \ - _Pragma("clang attribute pop") \ - _Pragma("clang attribute pop") -// clang-format on - -// std::to_chars(floating-point) -// clang-format off -# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 130300) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 160300) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 160300) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 90300) -// clang-format on -# define _LIBCPP_AVAILABILITY_HAS_TO_CHARS_FLOATING_POINT 0 -# else -# define _LIBCPP_AVAILABILITY_HAS_TO_CHARS_FLOATING_POINT 1 -# endif -# define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT \ - __attribute__((availability(macos, strict, introduced = 13.3))) \ - __attribute__((availability(ios, strict, introduced = 16.3))) \ - __attribute__((availability(tvos, strict, introduced = 16.3))) \ - __attribute__((availability(watchos, strict, introduced = 9.3))) - -// c++20 synchronization library -// clang-format off -# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000) -// clang-format on -# define _LIBCPP_AVAILABILITY_HAS_SYNC 0 -# else -# define _LIBCPP_AVAILABILITY_HAS_SYNC 1 -# endif -# define _LIBCPP_AVAILABILITY_SYNC \ - __attribute__((availability(macos, strict, introduced = 11.0))) \ - __attribute__((availability(ios, strict, introduced = 14.0))) \ - __attribute__((availability(tvos, strict, introduced = 14.0))) \ - __attribute__((availability(watchos, strict, introduced = 7.0))) - -// __libcpp_verbose_abort -// TODO: Update once this is released -# define _LIBCPP_AVAILABILITY_HAS_VERBOSE_ABORT 0 - -# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT __attribute__((unavailable)) - -// std::pmr -// clang-format off -# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 140000) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 170000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 170000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 100000) -// clang-format on -# define _LIBCPP_AVAILABILITY_HAS_PMR 0 -# else -# define _LIBCPP_AVAILABILITY_HAS_PMR 1 -# endif -// TODO: Enable std::pmr markup once https://github.com/llvm/llvm-project/issues/40340 has been fixed -// Until then, it is possible for folks to try to use `std::pmr` when back-deploying to targets that don't support -// it and it'll be a load-time error, but we don't have a good alternative because the library won't compile if we -// use availability annotations until that bug has been fixed. -# if 0 -# define _LIBCPP_AVAILABILITY_PMR \ - __attribute__((availability(macos, strict, introduced = 14.0))) \ - __attribute__((availability(ios, strict, introduced = 17.0))) \ - __attribute__((availability(tvos, strict, introduced = 17.0))) \ - __attribute__((availability(watchos, strict, introduced = 10.0))) -# else -# define _LIBCPP_AVAILABILITY_PMR -# endif - -# define _LIBCPP_AVAILABILITY_HAS_TZDB 0 -# define _LIBCPP_AVAILABILITY_TZDB __attribute__((unavailable)) - -// Warning: This availability macro works differently than the other macros. -// The dylib part of print is not needed on Apple platforms. Therefore when -// the macro is not available the code calling the dylib is commented out. -// The macro _LIBCPP_AVAILABILITY_PRINT is not used. -# define _LIBCPP_AVAILABILITY_HAS_PRINT 0 -# define _LIBCPP_AVAILABILITY_PRINT __attribute__((unavailable)) - -// clang-format off -# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 120000) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 150000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 150000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 80000) -// clang-format on -# define _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 0 -# else -# define _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 1 -# endif -#else - -// ...New vendors can add availability markup here... - -# error \ - "It looks like you're trying to enable vendor availability markup, but you haven't defined the corresponding macros yet!" - -#endif - -// Define availability attributes that depend on _LIBCPP_HAS_NO_EXCEPTIONS. -// Those are defined in terms of the availability attributes above, and -// should not be vendor-specific. -#if defined(_LIBCPP_HAS_NO_EXCEPTIONS) -# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST -# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS -# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS -#else -# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST _LIBCPP_AVAILABILITY_BAD_ANY_CAST -# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS -# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS -#endif - -// Define availability attributes that depend on both -// _LIBCPP_HAS_NO_EXCEPTIONS and _LIBCPP_HAS_NO_RTTI. -#if defined(_LIBCPP_HAS_NO_EXCEPTIONS) || defined(_LIBCPP_HAS_NO_RTTI) -# undef _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION -# undef _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION -# define _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION 0 -# define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION -#endif - -#endif // _LIBCPP___AVAILABILITY diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_cast.h b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_cast.h index 6298810f37..cd04567381 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_cast.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_cast.h @@ -33,7 +33,7 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr _ToType __bit_cast(const _From template requires(sizeof(_ToType) == sizeof(_FromType) && is_trivially_copyable_v<_ToType> && is_trivially_copyable_v<_FromType>) -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _FromType& __from) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _FromType& __from) noexcept { return __builtin_bit_cast(_ToType, __from); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_ceil.h b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_ceil.h index 77fa739503..cfd792dc2e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_ceil.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_ceil.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) noexcept { if (__t < 2) return 1; const unsigned __n = numeric_limits<_Tp>::digits - std::__countl_zero((_Tp)(__t - 1u)); @@ -42,7 +42,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_ceil(_Tp __t) no # if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { return std::__bit_ceil(__t); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_floor.h b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_floor.h index cf5cf5803a..133e369504 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_floor.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_floor.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_width.h b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_width.h index a2020a0142..853e481776 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/bit_width.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/bit_width.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { return __t == 0 ? 0 : std::__bit_log2(__t) + 1; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/byteswap.h b/naiveproxy/src/third_party/libc++/src/include/__bit/byteswap.h index 20045d6fd4..6225ecf2f9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/byteswap.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/byteswap.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 23 template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { if constexpr (sizeof(_Tp) == 1) { return __val; } else if constexpr (sizeof(_Tp) == 2) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/countl.h b/naiveproxy/src/third_party/libc++/src/include/__bit/countl.h index 13df8d4e66..998a0b44c1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/countl.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/countl.h @@ -95,12 +95,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _ #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { return std::__countl_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/countr.h b/naiveproxy/src/third_party/libc++/src/include/__bit/countr.h index 724a0bc238..9e92021fba 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/countr.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/countr.h @@ -66,12 +66,12 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __coun #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { return std::__countr_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/has_single_bit.h b/naiveproxy/src/third_party/libc++/src/include/__bit/has_single_bit.h index a4e178060a..52f5853a1b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/has_single_bit.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/has_single_bit.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { return __t != 0 && (((__t & (__t - 1)) == 0)); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit/popcount.h b/naiveproxy/src/third_party/libc++/src/include/__bit/popcount.h index 37b3a3e1f3..5cf0a01d07 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit/popcount.h +++ b/naiveproxy/src/third_party/libc++/src/include/__bit/popcount.h @@ -41,7 +41,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned lo #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { # if __has_builtin(__builtin_popcountg) return __builtin_popcountg(__t); # else // __has_builtin(__builtin_popcountg) diff --git a/naiveproxy/src/third_party/libc++/src/include/__bit_reference b/naiveproxy/src/third_party/libc++/src/include/__bit_reference index 9579b9eaf7..606069d98b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__bit_reference +++ b/naiveproxy/src/third_party/libc++/src/include/__bit_reference @@ -95,8 +95,8 @@ public: } private: - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_reference( - __storage_pointer __s, __storage_type __m) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT : __seg_(__s), __mask_(__m) {} }; @@ -149,6 +149,7 @@ public: using __container = typename _Cp::__self; _LIBCPP_HIDE_FROM_ABI __bit_const_reference(const __bit_const_reference&) = default; + __bit_const_reference& operator=(const __bit_const_reference&) = delete; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT : __seg_(__x.__seg_), @@ -163,12 +164,10 @@ public: } private: - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __bit_const_reference( - __storage_pointer __s, __storage_type __m) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR explicit __bit_const_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT : __seg_(__s), __mask_(__m) {} - - __bit_const_reference& operator=(const __bit_const_reference&) = delete; }; // copy @@ -940,8 +939,8 @@ public: } private: - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_iterator( - __storage_pointer __s, unsigned __ctz) _NOEXCEPT + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT : __seg_(__s), __ctz_(__ctz) {} @@ -1000,8 +999,8 @@ private: _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, _IC> __find_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); template - friend typename __bit_iterator<_Dp, _IC>::difference_type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - __count_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); + friend typename __bit_iterator<_Dp, _IC>::difference_type _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX20 __count_bool(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); }; _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__charconv/chars_format.h b/naiveproxy/src/third_party/libc++/src/include/__charconv/chars_format.h index 95faa29010..c76cebd5d1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__charconv/chars_format.h +++ b/naiveproxy/src/third_party/libc++/src/include/__charconv/chars_format.h @@ -39,20 +39,17 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator^(chars_format __x, return chars_format(std::__to_underlying(__x) ^ std::__to_underlying(__y)); } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& -operator&=(chars_format& __x, chars_format __y) { +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format& operator&=(chars_format& __x, chars_format __y) { __x = __x & __y; return __x; } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& -operator|=(chars_format& __x, chars_format __y) { +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format& operator|=(chars_format& __x, chars_format __y) { __x = __x | __y; return __x; } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& -operator^=(chars_format& __x, chars_format __y) { +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format& operator^=(chars_format& __x, chars_format __y) { __x = __x ^ __y; return __x; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__charconv/to_chars_floating_point.h b/naiveproxy/src/third_party/libc++/src/include/__charconv/to_chars_floating_point.h index 08720e1078..118f316b21 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__charconv/to_chars_floating_point.h +++ b/naiveproxy/src/third_party/libc++/src/include/__charconv/to_chars_floating_point.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___CHARCONV_TO_CHARS_FLOATING_POINT_H #define _LIBCPP___CHARCONV_TO_CHARS_FLOATING_POINT_H -#include <__availability> #include <__charconv/chars_format.h> #include <__charconv/to_chars_result.h> #include <__config> diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/convert_to_tm.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/convert_to_tm.h index 1301cd6f1f..881a497082 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/convert_to_tm.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/convert_to_tm.h @@ -16,10 +16,12 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> #include <__chrono/statically_widen.h> +#include <__chrono/sys_info.h> #include <__chrono/system_clock.h> #include <__chrono/time_point.h> #include <__chrono/weekday.h> @@ -171,6 +173,12 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { if (__value.hours().count() > std::numeric_limits::max()) std::__throw_format_error("Formatting hh_mm_ss, encountered an hour overflow"); __result.tm_hour = __value.hours().count(); +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + } else if constexpr (same_as<_ChronoT, chrono::sys_info>) { + // Has no time information. + } else if constexpr (same_as<_ChronoT, chrono::local_info>) { + // Has no time information. +# endif } else static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/duration.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/duration.h index 1e81420244..1e36d73428 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/duration.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/duration.h @@ -391,8 +391,8 @@ operator<=>(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Perio template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR - typename common_type, duration<_Rep2, _Period2> >::type - operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { +typename common_type, duration<_Rep2, _Period2> >::type +operator+(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; return _Cd(_Cd(__lhs).count() + _Cd(__rhs).count()); } @@ -401,8 +401,8 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR - typename common_type, duration<_Rep2, _Period2> >::type - operator-(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { +typename common_type, duration<_Rep2, _Period2> >::type +operator-(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; return _Cd(_Cd(__lhs).count() - _Cd(__rhs).count()); } @@ -468,8 +468,8 @@ operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) { template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR - typename common_type, duration<_Rep2, _Period2> >::type - operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { +typename common_type, duration<_Rep2, _Period2> >::type +operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { typedef typename common_type<_Rep1, _Rep2>::type _Cr; typedef typename common_type, duration<_Rep2, _Period2> >::type _Cd; return _Cd(static_cast<_Cr>(_Cd(__lhs).count()) % static_cast<_Cr>(_Cd(__rhs).count())); diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/exception.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/exception.h new file mode 100644 index 0000000000..266f8fac44 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/exception.h @@ -0,0 +1,135 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html + +#ifndef _LIBCPP___CHRONO_EXCEPTION_H +#define _LIBCPP___CHRONO_EXCEPTION_H + +#include +// Enable the contents of the header only when libc++ was built with experimental features enabled. +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +# include <__chrono/calendar.h> +# include <__chrono/local_info.h> +# include <__chrono/time_point.h> +# include <__config> +# include <__configuration/availability.h> +# include <__verbose_abort> +# include +# include +# include + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 20 + +namespace chrono { + +class nonexistent_local_time : public runtime_error { +public: + template + _LIBCPP_HIDE_FROM_ABI nonexistent_local_time(const local_time<_Duration>& __time, const local_info& __info) + : runtime_error{__create_message(__time, __info)} { + // [time.zone.exception.nonexist]/2 + // Preconditions: i.result == local_info::nonexistent is true. + // The value of __info.result is not used. + _LIBCPP_ASSERT_PEDANTIC(__info.result == local_info::nonexistent, + "creating an nonexistent_local_time from a local_info that is not non-existent"); + } + + _LIBCPP_HIDE_FROM_ABI nonexistent_local_time(const nonexistent_local_time&) = default; + _LIBCPP_HIDE_FROM_ABI nonexistent_local_time& operator=(const nonexistent_local_time&) = default; + + _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~nonexistent_local_time() override; // exported as key function + +private: + template + _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) { + return std::format( + R"({} is in a gap between +{} {} and +{} {} which are both equivalent to +{} UTC)", + __time, + local_seconds{__info.first.end.time_since_epoch()} + __info.first.offset, + __info.first.abbrev, + local_seconds{__info.second.begin.time_since_epoch()} + __info.second.offset, + __info.second.abbrev, + __info.first.end); + } +}; + +template +_LIBCPP_NORETURN _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI void __throw_nonexistent_local_time( + [[maybe_unused]] const local_time<_Duration>& __time, [[maybe_unused]] const local_info& __info) { +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + throw nonexistent_local_time(__time, __info); +# else + _LIBCPP_VERBOSE_ABORT("nonexistent_local_time was thrown in -fno-exceptions mode"); +# endif +} + +class ambiguous_local_time : public runtime_error { +public: + template + _LIBCPP_HIDE_FROM_ABI ambiguous_local_time(const local_time<_Duration>& __time, const local_info& __info) + : runtime_error{__create_message(__time, __info)} { + // [time.zone.exception.ambig]/2 + // Preconditions: i.result == local_info::ambiguous is true. + // The value of __info.result is not used. + _LIBCPP_ASSERT_PEDANTIC(__info.result == local_info::ambiguous, + "creating an ambiguous_local_time from a local_info that is not ambiguous"); + } + + _LIBCPP_HIDE_FROM_ABI ambiguous_local_time(const ambiguous_local_time&) = default; + _LIBCPP_HIDE_FROM_ABI ambiguous_local_time& operator=(const ambiguous_local_time&) = default; + + _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~ambiguous_local_time() override; // exported as key function + +private: + template + _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) { + return std::format( + // There are two spaces after the full-stop; this has been verified + // in the sources of the Standard. + R"({0} is ambiguous. It could be +{0} {1} == {2} UTC or +{0} {3} == {4} UTC)", + __time, + __info.first.abbrev, + __time - __info.first.offset, + __info.second.abbrev, + __time - __info.second.offset); + } +}; + +template +_LIBCPP_NORETURN _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI void __throw_ambiguous_local_time( + [[maybe_unused]] const local_time<_Duration>& __time, [[maybe_unused]] const local_info& __info) { +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + throw ambiguous_local_time(__time, __info); +# else + _LIBCPP_VERBOSE_ABORT("ambiguous_local_time was thrown in -fno-exceptions mode"); +# endif +} + +} // namespace chrono + +# endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +#endif // _LIBCPP___CHRONO_EXCEPTION_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/file_clock.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/file_clock.h index 7d25729fec..4dd3f88ce5 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/file_clock.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/file_clock.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___CHRONO_FILE_CLOCK_H #define _LIBCPP___CHRONO_FILE_CLOCK_H -#include <__availability> #include <__chrono/duration.h> #include <__chrono/system_clock.h> #include <__chrono/time_point.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/formatter.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/formatter.h index 4ad59382a4..9a77316385 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/formatter.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/formatter.h @@ -10,6 +10,7 @@ #ifndef _LIBCPP___CHRONO_FORMATTER_H #define _LIBCPP___CHRONO_FORMATTER_H +#include <__algorithm/ranges_copy.h> #include <__chrono/calendar.h> #include <__chrono/concepts.h> #include <__chrono/convert_to_tm.h> @@ -17,12 +18,14 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> #include <__chrono/ostream.h> #include <__chrono/parser_std_format_spec.h> #include <__chrono/statically_widen.h> +#include <__chrono/sys_info.h> #include <__chrono/system_clock.h> #include <__chrono/time_point.h> #include <__chrono/weekday.h> @@ -43,6 +46,7 @@ #include <__memory/addressof.h> #include #include +#include #include #include @@ -79,12 +83,15 @@ namespace __formatter { // small). Therefore a duration uses its own conversion. template _LIBCPP_HIDE_FROM_ABI void -__format_sub_seconds(const chrono::duration<_Rep, _Period>& __value, basic_stringstream<_CharT>& __sstr) { +__format_sub_seconds(basic_stringstream<_CharT>& __sstr, const chrono::duration<_Rep, _Period>& __value) { __sstr << std::use_facet>(__sstr.getloc()).decimal_point(); using __duration = chrono::duration<_Rep, _Period>; auto __fraction = __value - chrono::duration_cast(__value); + // Converts a negative fraction to its positive value. + if (__value < chrono::seconds{0} && __fraction != __duration{0}) + __fraction += chrono::seconds{1}; if constexpr (chrono::treat_as_floating_point_v<_Rep>) // When the floating-point value has digits itself they are ignored based // on the wording in [tab:time.format.spec] @@ -110,13 +117,13 @@ __format_sub_seconds(const chrono::duration<_Rep, _Period>& __value, basic_strin } template -_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) { - __formatter::__format_sub_seconds(__value.time_since_epoch(), __sstr); +_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(basic_stringstream<_CharT>& __sstr, const _Tp& __value) { + __formatter::__format_sub_seconds(__sstr, __value.time_since_epoch()); } template _LIBCPP_HIDE_FROM_ABI void -__format_sub_seconds(const chrono::hh_mm_ss<_Duration>& __value, basic_stringstream<_CharT>& __sstr) { +__format_sub_seconds(basic_stringstream<_CharT>& __sstr, const chrono::hh_mm_ss<_Duration>& __value) { __sstr << std::use_facet>(__sstr.getloc()).decimal_point(); if constexpr (chrono::treat_as_floating_point_v) std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, @@ -143,7 +150,7 @@ consteval bool __use_fraction() { } template -_LIBCPP_HIDE_FROM_ABI void __format_year(int __year, basic_stringstream<_CharT>& __sstr) { +_LIBCPP_HIDE_FROM_ABI void __format_year(basic_stringstream<_CharT>& __sstr, int __year) { if (__year < 0) { __sstr << _CharT('-'); __year = -__year; @@ -159,7 +166,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_year(int __year, basic_stringstream<_CharT>& } template -_LIBCPP_HIDE_FROM_ABI void __format_century(int __year, basic_stringstream<_CharT>& __sstr) { +_LIBCPP_HIDE_FROM_ABI void __format_century(basic_stringstream<_CharT>& __sstr, int __year) { // TODO FMT Write an issue // [tab:time.format.spec] // %C The year divided by 100 using floored division. If the result is a @@ -170,10 +177,51 @@ _LIBCPP_HIDE_FROM_ABI void __format_century(int __year, basic_stringstream<_Char __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __century); } +// Implements the %z format specifier according to [tab:time.format.spec], where +// '__modifier' signals %Oz or %Ez were used. (Both modifiers behave the same, +// so there is no need to distinguish between them.) +template +_LIBCPP_HIDE_FROM_ABI void +__format_zone_offset(basic_stringstream<_CharT>& __sstr, chrono::seconds __offset, bool __modifier) { + if (__offset < 0s) { + __sstr << _CharT('-'); + __offset = -__offset; + } else { + __sstr << _CharT('+'); + } + + chrono::hh_mm_ss __hms{__offset}; + std::ostreambuf_iterator<_CharT> __out_it{__sstr}; + // Note HMS does not allow formatting hours > 23, but the offset is not limited to 24H. + std::format_to(__out_it, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __hms.hours().count()); + if (__modifier) + __sstr << _CharT(':'); + std::format_to(__out_it, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __hms.minutes().count()); +} + +// Helper to store the time zone information needed for formatting. +struct _LIBCPP_HIDE_FROM_ABI __time_zone { + // Typically these abbreviations are short and fit in the string's internal + // buffer. + string __abbrev; + chrono::seconds __offset; +}; + +template +_LIBCPP_HIDE_FROM_ABI __time_zone __convert_to_time_zone([[maybe_unused]] const _Tp& __value) { +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + if constexpr (same_as<_Tp, chrono::sys_info>) + return {__value.abbrev, __value.offset}; + else +# endif + return {"UTC", chrono::seconds{0}}; +} + template _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( - const _Tp& __value, basic_stringstream<_CharT>& __sstr, basic_string_view<_CharT> __chrono_specs) { + basic_stringstream<_CharT>& __sstr, const _Tp& __value, basic_string_view<_CharT> __chrono_specs) { tm __t = std::__convert_to_tm(__value); + __time_zone __z = __formatter::__convert_to_time_zone(__value); const auto& __facet = std::use_facet>(__sstr.getloc()); for (auto __it = __chrono_specs.begin(); __it != __chrono_specs.end(); ++__it) { if (*__it == _CharT('%')) { @@ -196,7 +244,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // strftime's output is only defined in the range [00, 99]. int __year = __t.tm_year + 1900; if (__year < 1000 || __year > 9999) - __formatter::__format_century(__year, __sstr); + __formatter::__format_century(__sstr, __year); else __facet.put( {__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); @@ -242,7 +290,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( __facet.put( {__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); if constexpr (__use_fraction<_Tp>()) - __formatter::__format_sub_seconds(__value, __sstr); + __formatter::__format_sub_seconds(__sstr, __value); break; // Unlike time_put and strftime the formatting library requires %Y @@ -283,22 +331,24 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // Depending on the platform's libc the range of supported years is // limited. Intead of of testing all conditions use the internal // implementation unconditionally. - __formatter::__format_year(__t.tm_year + 1900, __sstr); + __formatter::__format_year(__sstr, __t.tm_year + 1900); break; - case _CharT('F'): { - int __year = __t.tm_year + 1900; - if (__year < 1000) { - __formatter::__format_year(__year, __sstr); - __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); - } else - __facet.put( - {__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); - } break; + case _CharT('F'): + // Depending on the platform's libc the range of supported years is + // limited. Instead of testing all conditions use the internal + // implementation unconditionally. + __formatter::__format_year(__sstr, __t.tm_year + 1900); + __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); + break; + + case _CharT('z'): + __formatter::__format_zone_offset(__sstr, __z.__offset, false); + break; case _CharT('Z'): - // TODO FMT Add proper timezone support. - __sstr << _LIBCPP_STATICALLY_WIDEN(_CharT, "UTC"); + // __abbrev is always a char so the copy may convert. + ranges::copy(__z.__abbrev, std::ostreambuf_iterator<_CharT>{__sstr}); break; case _CharT('O'): @@ -310,13 +360,19 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( ++__it; __facet.put( {__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); - __formatter::__format_sub_seconds(__value, __sstr); + __formatter::__format_sub_seconds(__sstr, __value); break; } } + + // Oz produces the same output as Ez below. [[fallthrough]]; case _CharT('E'): ++__it; + if (*__it == 'z') { + __formatter::__format_zone_offset(__sstr, __z.__offset, true); + break; + } [[fallthrough]]; default: __facet.put( @@ -365,6 +421,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + else if constexpr (same_as<_Tp, chrono::sys_info>) + return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; +# endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -405,6 +467,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + else if constexpr (same_as<_Tp, chrono::sys_info>) + return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; +# endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -445,6 +513,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { return __value.ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + else if constexpr (same_as<_Tp, chrono::sys_info>) + return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; +# endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -485,6 +559,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { return __value.month().ok(); else if constexpr (__is_hh_mm_ss<_Tp>) return true; +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + else if constexpr (same_as<_Tp, chrono::sys_info>) + return true; + else if constexpr (same_as<_Tp, chrono::local_info>) + return true; +# endif else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } @@ -510,9 +590,16 @@ __format_chrono(const _Tp& __value, __sstr << __value; else { if constexpr (chrono::__is_duration<_Tp>::value) { - if (__value < __value.zero()) - __sstr << _CharT('-'); - __formatter::__format_chrono_using_chrono_specs(chrono::abs(__value), __sstr, __chrono_specs); + // A duration can be a user defined arithmetic type. Users may specialize + // numeric_limits, but they may not specialize is_signed. + if constexpr (numeric_limits::is_signed) { + if (__value < __value.zero()) { + __sstr << _CharT('-'); + __formatter::__format_chrono_using_chrono_specs(__sstr, -__value, __chrono_specs); + } else + __formatter::__format_chrono_using_chrono_specs(__sstr, __value, __chrono_specs); + } else + __formatter::__format_chrono_using_chrono_specs(__sstr, __value, __chrono_specs); // TODO FMT When keeping the precision it will truncate the string. // Note that the behaviour what the precision does isn't specified. __specs.__precision_ = -1; @@ -556,7 +643,7 @@ __format_chrono(const _Tp& __value, __sstr << _CharT('-'); } - __formatter::__format_chrono_using_chrono_specs(__value, __sstr, __chrono_specs); + __formatter::__format_chrono_using_chrono_specs(__sstr, __value, __chrono_specs); } } @@ -814,6 +901,31 @@ public: return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__time); } }; + +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) +template <__fmt_char_type _CharT> +struct formatter : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__time_zone); + } +}; + +template <__fmt_char_type _CharT> +struct formatter : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags{}); + } +}; +# endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + #endif // if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/leap_second.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/leap_second.h index 557abc15ff..1a0e7f3107 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/leap_second.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/leap_second.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/duration.h> # include <__chrono/system_clock.h> @@ -43,9 +43,9 @@ public: _LIBCPP_HIDE_FROM_ABI leap_second(const leap_second&) = default; _LIBCPP_HIDE_FROM_ABI leap_second& operator=(const leap_second&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr sys_seconds date() const noexcept { return __date_; } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr sys_seconds date() const noexcept { return __date_; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr seconds value() const noexcept { return __value_; } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr seconds value() const noexcept { return __value_; } private: sys_seconds __date_; @@ -121,6 +121,6 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const leap_second& __x, const s _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_LEAP_SECOND_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/local_info.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/local_info.h new file mode 100644 index 0000000000..cfe1448904 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/local_info.h @@ -0,0 +1,50 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html + +#ifndef _LIBCPP___CHRONO_LOCAL_INFO_H +#define _LIBCPP___CHRONO_LOCAL_INFO_H + +#include +// Enable the contents of the header only when libc++ was built with experimental features enabled. +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +# include <__chrono/sys_info.h> +# include <__config> + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 20 + +namespace chrono { + +struct local_info { + static constexpr int unique = 0; + static constexpr int nonexistent = 1; + static constexpr int ambiguous = 2; + + int result; + sys_info first; + sys_info second; +}; + +} // namespace chrono + +# endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +#endif // _LIBCPP___CHRONO_LOCAL_INFO_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/ostream.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/ostream.h index b687ef8059..bb0341bc3e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/ostream.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/ostream.h @@ -15,10 +15,12 @@ #include <__chrono/duration.h> #include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> +#include <__chrono/local_info.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> #include <__chrono/statically_widen.h> +#include <__chrono/sys_info.h> #include <__chrono/system_clock.h> #include <__chrono/weekday.h> #include <__chrono/year.h> @@ -28,7 +30,7 @@ #include <__concepts/same_as.h> #include <__config> #include <__format/format_functions.h> -#include +#include <__fwd/ostream.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -262,6 +264,46 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const hh_mm_ss<_Duration> __hms return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%T}"), __hms); } +# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __info) { + // __info.abbrev is always std::basic_string. + // Since these strings typically are short the conversion should be cheap. + std::basic_string<_CharT> __abbrev{__info.abbrev.begin(), __info.abbrev.end()}; + return __os << std::format( + _LIBCPP_STATICALLY_WIDEN(_CharT, "[{:%F %T}, {:%F %T}) {:%T} {:%Q%q} \"{}\""), + __info.begin, + __info.end, + hh_mm_ss{__info.offset}, + __info.save, + __abbrev); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __info) { + auto __result = [&]() -> basic_string<_CharT> { + switch (__info.result) { + case local_info::unique: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "unique"); + case local_info::nonexistent: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "non-existent"); + case local_info::ambiguous: + return _LIBCPP_STATICALLY_WIDEN(_CharT, "ambiguous"); + + default: + return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "unspecified result ({})"), __info.result); + }; + }; + + return __os << std::format( + _LIBCPP_STATICALLY_WIDEN(_CharT, "{}: {{{}, {}}}"), __result(), __info.first, __info.second); +} + +# endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + } // namespace chrono #endif // if _LIBCPP_STD_VER >= 20 diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/sys_info.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/sys_info.h index 794d22f2cc..11536cbde3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/sys_info.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/sys_info.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__chrono/duration.h> # include <__chrono/system_clock.h> @@ -42,10 +42,10 @@ struct sys_info { } // namespace chrono -# endif //_LIBCPP_STD_VER >= 20 +# endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_SYS_INFO_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/time_point.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/time_point.h index e65253ddb9..aaf0b098f2 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/time_point.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/time_point.h @@ -78,7 +78,7 @@ public: template struct _LIBCPP_TEMPLATE_VIS - common_type, chrono::time_point<_Clock, _Duration2> > { +common_type, chrono::time_point<_Clock, _Duration2> > { typedef chrono::time_point<_Clock, typename common_type<_Duration1, _Duration2>::type> type; }; @@ -92,25 +92,22 @@ time_point_cast(const time_point<_Clock, _Duration>& __t) { #if _LIBCPP_STD_VER >= 17 template ::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR time_point<_Clock, _ToDuration> -floor(const time_point<_Clock, _Duration>& __t) { +inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> floor(const time_point<_Clock, _Duration>& __t) { return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())}; } template ::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR time_point<_Clock, _ToDuration> -ceil(const time_point<_Clock, _Duration>& __t) { +inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> ceil(const time_point<_Clock, _Duration>& __t) { return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())}; } template ::value, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR time_point<_Clock, _ToDuration> -round(const time_point<_Clock, _Duration>& __t) { +inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> round(const time_point<_Clock, _Duration>& __t) { return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())}; } template ::is_signed, int> = 0> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<_Rep, _Period> abs(duration<_Rep, _Period> __d) { +inline _LIBCPP_HIDE_FROM_ABI constexpr duration<_Rep, _Period> abs(duration<_Rep, _Period> __d) { return __d >= __d.zero() ? +__d : -__d; } #endif // _LIBCPP_STD_VER >= 17 @@ -180,9 +177,9 @@ operator<=>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock // time_point operator+(time_point x, duration y); template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> - operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { +inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> +operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Tr; return _Tr(__lhs.time_since_epoch() + __rhs); } @@ -190,18 +187,18 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 // time_point operator+(duration x, time_point y); template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - time_point<_Clock, typename common_type, _Duration2>::type> - operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { +inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type, _Duration2>::type> +operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { return __rhs + __lhs; } // time_point operator-(time_point x, duration y); template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> - operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { +inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> +operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) { typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Ret; return _Ret(__lhs.time_since_epoch() - __rhs); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/time_zone.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/time_zone.h index 8e30034b79..de11dac1ee 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/time_zone.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/time_zone.h @@ -14,14 +14,18 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) +# include <__chrono/calendar.h> # include <__chrono/duration.h> +# include <__chrono/exception.h> +# include <__chrono/local_info.h> # include <__chrono/sys_info.h> # include <__chrono/system_clock.h> # include <__compare/strong_order.h> # include <__config> # include <__memory/unique_ptr.h> +# include <__type_traits/common_type.h> # include # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -38,6 +42,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace chrono { +enum class choose { earliest, latest }; + class _LIBCPP_AVAILABILITY_TZDB time_zone { _LIBCPP_HIDE_FROM_ABI time_zone() = default; @@ -56,29 +62,108 @@ public: _LIBCPP_HIDE_FROM_ABI time_zone(time_zone&&) = default; _LIBCPP_HIDE_FROM_ABI time_zone& operator=(time_zone&&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name(); } template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const { return __get_info(chrono::time_point_cast(__time)); } + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI local_info get_info(const local_time<_Duration>& __time) const { + return __get_info(chrono::time_point_cast(__time)); + } + + // We don't apply nodiscard here since this function throws on many inputs, + // so it could be used as a validation. + template + _LIBCPP_HIDE_FROM_ABI sys_time> to_sys(const local_time<_Duration>& __time) const { + local_info __info = get_info(__time); + switch (__info.result) { + case local_info::unique: + return sys_time>{__time.time_since_epoch() - __info.first.offset}; + + case local_info::nonexistent: + chrono::__throw_nonexistent_local_time(__time, __info); + + case local_info::ambiguous: + chrono::__throw_ambiguous_local_time(__time, __info); + } + + // TODO TZDB The Standard does not specify anything in these cases. + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __info.result != -1, "cannot convert the local time; it would be before the minimum system clock value"); + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __info.result != -2, "cannot convert the local time; it would be after the maximum system clock value"); + + return {}; + } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_time> + to_sys(const local_time<_Duration>& __time, choose __z) const { + local_info __info = get_info(__time); + switch (__info.result) { + case local_info::unique: + case local_info::nonexistent: // first and second are the same + return sys_time>{__time.time_since_epoch() - __info.first.offset}; + + case local_info::ambiguous: + switch (__z) { + case choose::earliest: + return sys_time>{__time.time_since_epoch() - __info.first.offset}; + + case choose::latest: + return sys_time>{__time.time_since_epoch() - __info.second.offset}; + + // Note a value out of bounds is not specified. + } + } + + // TODO TZDB The standard does not specify anything in these cases. + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __info.result != -1, "cannot convert the local time; it would be before the minimum system clock value"); + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __info.result != -2, "cannot convert the local time; it would be after the maximum system clock value"); + + return {}; + } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI local_time> + to_local(const sys_time<_Duration>& __time) const { + using _Dp = common_type_t<_Duration, seconds>; + + sys_info __info = get_info(__time); + + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __info.offset >= chrono::seconds{0} || __time.time_since_epoch() >= _Dp::min() - __info.offset, + "cannot convert the system time; it would be before the minimum local clock value"); + + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + __info.offset <= chrono::seconds{0} || __time.time_since_epoch() <= _Dp::max() - __info.offset, + "cannot convert the system time; it would be after the maximum local clock value"); + + return local_time<_Dp>{__time.time_since_epoch() + __info.offset}; + } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const __impl& __implementation() const noexcept { return *__impl_; } private: [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI string_view __name() const noexcept; [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI sys_info __get_info(sys_seconds __time) const; + [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI local_info __get_info(local_seconds __time) const; unique_ptr<__impl> __impl_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool operator==(const time_zone& __x, const time_zone& __y) noexcept { return __x.name() == __y.name(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering operator<=>(const time_zone& __x, const time_zone& __y) noexcept { return __x.name() <=> __y.name(); } @@ -92,6 +177,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TIME_ZONE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/time_zone_link.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/time_zone_link.h index c76ddeff9f..b2d365c5fd 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/time_zone_link.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/time_zone_link.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__compare/strong_order.h> # include <__config> @@ -38,15 +38,15 @@ namespace chrono { class time_zone_link { public: - _LIBCPP_NODISCARD_EXT + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit time_zone_link(__private_constructor_tag, string_view __name, string_view __target) : __name_{__name}, __target_{__target} {} _LIBCPP_HIDE_FROM_ABI time_zone_link(time_zone_link&&) = default; _LIBCPP_HIDE_FROM_ABI time_zone_link& operator=(time_zone_link&&) = default; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name_; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI string_view target() const noexcept { return __target_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view target() const noexcept { return __target_; } private: string __name_; @@ -56,12 +56,12 @@ private: string __target_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool operator==(const time_zone_link& __x, const time_zone_link& __y) noexcept { return __x.name() == __y.name(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering operator<=>(const time_zone_link& __x, const time_zone_link& __y) noexcept { return __x.name() <=> __y.name(); } @@ -74,6 +74,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TIME_ZONE_LINK_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/tzdb.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/tzdb.h index e0bfedf0d7..f731f8c318 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/tzdb.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/tzdb.h @@ -14,7 +14,7 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) # include <__algorithm/ranges_lower_bound.h> # include <__chrono/leap_second.h> @@ -57,14 +57,14 @@ struct tzdb { return nullptr; } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const time_zone* locate_zone(string_view __name) const { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const time_zone* locate_zone(string_view __name) const { if (const time_zone* __result = __locate_zone(__name)) return __result; std::__throw_runtime_error("tzdb: requested time zone not found"); } - _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI const time_zone* current_zone() const { + [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI const time_zone* current_zone() const { return __current_zone(); } @@ -89,6 +89,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TZDB_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/tzdb_list.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/tzdb_list.h index 693899d372..aeef4fe1ab 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/tzdb_list.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/tzdb_list.h @@ -14,9 +14,8 @@ #include // Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) -# include <__availability> # include <__chrono/time_zone.h> # include <__chrono/tzdb.h> # include <__config> @@ -53,15 +52,15 @@ public: using const_iterator = forward_list::const_iterator; - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const tzdb& front() const noexcept { return __front(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const tzdb& front() const noexcept { return __front(); } _LIBCPP_HIDE_FROM_ABI const_iterator erase_after(const_iterator __p) { return __erase_after(__p); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return __begin(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return __end(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return __begin(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return __end(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return __cbegin(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return __cend(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return __cbegin(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return __cend(); } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __impl& __implementation() { return *__impl_; } @@ -79,24 +78,23 @@ private: __impl* __impl_; }; -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_list& get_tzdb_list(); +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI tzdb_list& get_tzdb_list(); -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const tzdb& get_tzdb() { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const tzdb& get_tzdb() { return get_tzdb_list().front(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* -locate_zone(string_view __name) { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* locate_zone(string_view __name) { return get_tzdb().locate_zone(__name); } -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* current_zone() { +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline const time_zone* current_zone() { return get_tzdb().current_zone(); } _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI const tzdb& reload_tzdb(); -_LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version(); +[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string remote_version(); } // namespace chrono @@ -105,6 +103,6 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI string _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB) +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) #endif // _LIBCPP___CHRONO_TZDB_LIST_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/year_month_day.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/year_month_day.h index 75884f3654..b06c0be03e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__chrono/year_month_day.h +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/year_month_day.h @@ -239,33 +239,11 @@ operator==(const year_month_day_last& __lhs, const year_month_day_last& __rhs) n return __lhs.year() == __rhs.year() && __lhs.month_day_last() == __rhs.month_day_last(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr bool -operator!=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept { - return !(__lhs == __rhs); -} - -_LIBCPP_HIDE_FROM_ABI inline constexpr bool -operator<(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept { - if (__lhs.year() < __rhs.year()) - return true; - if (__lhs.year() > __rhs.year()) - return false; - return __lhs.month_day_last() < __rhs.month_day_last(); -} - -_LIBCPP_HIDE_FROM_ABI inline constexpr bool -operator>(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept { - return __rhs < __lhs; -} - -_LIBCPP_HIDE_FROM_ABI inline constexpr bool -operator<=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept { - return !(__rhs < __lhs); -} - -_LIBCPP_HIDE_FROM_ABI inline constexpr bool -operator>=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept { - return !(__lhs < __rhs); +_LIBCPP_HIDE_FROM_ABI inline constexpr strong_ordering +operator<=>(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept { + if (auto __c = __lhs.year() <=> __rhs.year(); __c != 0) + return __c; + return __lhs.month_day_last() <=> __rhs.month_day_last(); } _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day_last operator/(const year_month& __lhs, last_spec) noexcept { diff --git a/naiveproxy/src/third_party/libc++/src/include/__chrono/zoned_time.h b/naiveproxy/src/third_party/libc++/src/include/__chrono/zoned_time.h new file mode 100644 index 0000000000..8cfa212264 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__chrono/zoned_time.h @@ -0,0 +1,227 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html + +#ifndef _LIBCPP___CHRONO_ZONED_TIME_H +#define _LIBCPP___CHRONO_ZONED_TIME_H + +#include +// Enable the contents of the header only when libc++ was built with experimental features enabled. +#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +# include <__chrono/calendar.h> +# include <__chrono/duration.h> +# include <__chrono/sys_info.h> +# include <__chrono/system_clock.h> +# include <__chrono/time_zone.h> +# include <__chrono/tzdb_list.h> +# include <__config> +# include <__fwd/string_view.h> +# include <__type_traits/common_type.h> +# include <__type_traits/conditional.h> +# include <__type_traits/remove_cvref.h> +# include <__utility/move.h> + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +# if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) && \ + !defined(_LIBCPP_HAS_NO_LOCALIZATION) + +namespace chrono { + +template +struct zoned_traits {}; + +template <> +struct zoned_traits { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static const time_zone* default_zone() { return chrono::locate_zone("UTC"); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static const time_zone* locate_zone(string_view __name) { + return chrono::locate_zone(__name); + } +}; + +template +class zoned_time { + // [time.zone.zonedtime.ctor]/2 + static_assert(__is_duration<_Duration>::value, + "the program is ill-formed since _Duration is not a specialization of std::chrono::duration"); + + // The wording uses the constraints like + // constructible_from + // Using these constraints in the code causes the compiler to give an + // error that the constraint depends on itself. To avoid that issue use + // the fact it is possible to create this object from a _TimeZonePtr. + using __traits = zoned_traits<_TimeZonePtr>; + +public: + using duration = common_type_t<_Duration, seconds>; + + _LIBCPP_HIDE_FROM_ABI zoned_time() + requires requires { __traits::default_zone(); } + : __zone_{__traits::default_zone()}, __tp_{} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(const zoned_time&) = default; + _LIBCPP_HIDE_FROM_ABI zoned_time& operator=(const zoned_time&) = default; + + _LIBCPP_HIDE_FROM_ABI zoned_time(const sys_time<_Duration>& __tp) + requires requires { __traits::default_zone(); } + : __zone_{__traits::default_zone()}, __tp_{__tp} {} + + _LIBCPP_HIDE_FROM_ABI explicit zoned_time(_TimeZonePtr __zone) : __zone_{std::move(__zone)}, __tp_{} {} + + _LIBCPP_HIDE_FROM_ABI explicit zoned_time(string_view __name) + requires(requires { __traits::locate_zone(string_view{}); } && + constructible_from<_TimeZonePtr, decltype(__traits::locate_zone(string_view{}))>) + : __zone_{__traits::locate_zone(__name)}, __tp_{} {} + + template + _LIBCPP_HIDE_FROM_ABI zoned_time(const zoned_time<_Duration2, _TimeZonePtr>& __zt) + requires is_convertible_v, sys_time<_Duration>> + : __zone_{__zt.get_time_zone()}, __tp_{__zt.get_sys_time()} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const sys_time<_Duration>& __tp) + : __zone_{std::move(__zone)}, __tp_{__tp} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const sys_time<_Duration>& __tp) + requires requires { _TimeZonePtr{__traits::locate_zone(string_view{})}; } + : zoned_time{__traits::locate_zone(__name), __tp} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const local_time<_Duration>& __tp) + requires(is_convertible_v() -> to_sys(local_time<_Duration>{})), + sys_time>) + : __zone_{std::move(__zone)}, __tp_{__zone_->to_sys(__tp)} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const local_time<_Duration>& __tp) + requires(requires { + _TimeZonePtr{__traits::locate_zone(string_view{})}; + } && is_convertible_v() -> to_sys(local_time<_Duration>{})), + sys_time>) + : zoned_time{__traits::locate_zone(__name), __tp} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const local_time<_Duration>& __tp, choose __c) + requires(is_convertible_v< + decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{}, choose::earliest)), + sys_time>) + : __zone_{std::move(__zone)}, __tp_{__zone_->to_sys(__tp, __c)} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const local_time<_Duration>& __tp, choose __c) + requires(requires { + _TimeZonePtr{__traits::locate_zone(string_view{})}; + } && is_convertible_v() -> to_sys(local_time<_Duration>{}, choose::earliest)), + sys_time>) + : zoned_time{__traits::locate_zone(__name), __tp, __c} {} + + template + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt) + requires is_convertible_v, sys_time<_Duration>> + : __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {} + + // per wording choose has no effect + template + _LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose) + requires is_convertible_v, sys_time<_Duration>> + : __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {} + + template + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const zoned_time<_Duration2, _TimeZonePtr2>& __zt) + requires(requires { + _TimeZonePtr{__traits::locate_zone(string_view{})}; + } && is_convertible_v, sys_time<_Duration>>) + : zoned_time{__traits::locate_zone(__name), __zt} {} + + template + _LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose __c) + requires(requires { + _TimeZonePtr{__traits::locate_zone(string_view{})}; + } && is_convertible_v, sys_time<_Duration>>) + : zoned_time{__traits::locate_zone(__name), __zt, __c} {} + + _LIBCPP_HIDE_FROM_ABI zoned_time& operator=(const sys_time<_Duration>& __tp) { + __tp_ = __tp; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI zoned_time& operator=(const local_time<_Duration>& __tp) { + // TODO TZDB This seems wrong. + // Assigning a non-existent or ambiguous time will throw and not satisfy + // the post condition. This seems quite odd; I constructed an object with + // choose::earliest and that choice is not respected. + // what did LEWG do with this. + // MSVC STL and libstdc++ behave the same + __tp_ = __zone_->to_sys(__tp); + return *this; + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI operator sys_time() const { return get_sys_time(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit operator local_time() const { return get_local_time(); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _TimeZonePtr get_time_zone() const { return __zone_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI local_time get_local_time() const { return __zone_->to_local(__tp_); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_time get_sys_time() const { return __tp_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_info get_info() const { return __zone_->get_info(__tp_); } + +private: + _TimeZonePtr __zone_; + sys_time __tp_; +}; + +zoned_time() -> zoned_time; + +template +zoned_time(sys_time<_Duration>) -> zoned_time>; + +template +using __time_zone_representation = + conditional_t, + const time_zone*, + remove_cvref_t<_TimeZonePtrOrName>>; + +template +zoned_time(_TimeZonePtrOrName&&) -> zoned_time>; + +template +zoned_time(_TimeZonePtrOrName&&, sys_time<_Duration>) + -> zoned_time, __time_zone_representation<_TimeZonePtrOrName>>; + +template +zoned_time(_TimeZonePtrOrName&&, local_time<_Duration>, choose = choose::earliest) + -> zoned_time, __time_zone_representation<_TimeZonePtrOrName>>; + +template +zoned_time(_TimeZonePtrOrName&&, zoned_time<_Duration, TimeZonePtr2>, choose = choose::earliest) + -> zoned_time, __time_zone_representation<_TimeZonePtrOrName>>; + +using zoned_seconds = zoned_time; + +template +_LIBCPP_HIDE_FROM_ABI bool +operator==(const zoned_time<_Duration1, _TimeZonePtr>& __lhs, const zoned_time<_Duration2, _TimeZonePtr>& __rhs) { + return __lhs.get_time_zone() == __rhs.get_time_zone() && __lhs.get_sys_time() == __rhs.get_sys_time(); +} + +} // namespace chrono + +# endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) + // && !defined(_LIBCPP_HAS_NO_LOCALIZATION) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) + +#endif // _LIBCPP___CHRONO_ZONED_TIME_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__compare/synth_three_way.h b/naiveproxy/src/third_party/libc++/src/include/__compare/synth_three_way.h index 6420d1362d..e48ce49799 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__compare/synth_three_way.h +++ b/naiveproxy/src/third_party/libc++/src/include/__compare/synth_three_way.h @@ -25,12 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // [expos.only.func] -// TODO MODULES restore the lamba to match the Standard. -// See https://github.com/llvm/llvm-project/issues/57222 -//_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = -// [](const _Tp& __t, const _Up& __u) -template -_LIBCPP_HIDE_FROM_ABI constexpr auto __synth_three_way(const _Tp& __t, const _Up& __u) +_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = [](const _Tp& __t, const _Up& __u) requires requires { { __t < __u } -> __boolean_testable; { __u < __t } -> __boolean_testable; @@ -45,7 +40,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __synth_three_way(const _Tp& __t, const _Up return weak_ordering::greater; return weak_ordering::equivalent; } -} +}; template using __synth_three_way_result = decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); diff --git a/naiveproxy/src/third_party/libc++/src/include/__config b/naiveproxy/src/third_party/libc++/src/include/__config index d98b54926b..108f700823 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__config +++ b/naiveproxy/src/third_party/libc++/src/include/__config @@ -11,52 +11,17 @@ #define _LIBCPP___CONFIG #include <__config_site> +#include <__configuration/abi.h> +#include <__configuration/availability.h> +#include <__configuration/compiler.h> +#include <__configuration/platform.h> #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER # pragma GCC system_header #endif -#if defined(_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES) && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) -# pragma clang deprecated( \ - _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES, \ - "_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES is deprecated in LLVM 18 and will be removed in LLVM 19") -#endif -#if defined(_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES) && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) -# pragma clang deprecated( \ - _LIBCPP_ENABLE_CXX20_REMOVED_FEATURES, \ - "_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES is deprecated in LLVM 18 and will be removed in LLVM 19") -#endif - -#if defined(__apple_build_version__) -// Given AppleClang XX.Y.Z, _LIBCPP_APPLE_CLANG_VER is XXYZ (e.g. AppleClang 14.0.3 => 1403) -# define _LIBCPP_COMPILER_CLANG_BASED -# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000) -#elif defined(__clang__) -# define _LIBCPP_COMPILER_CLANG_BASED -# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__) -#elif defined(__GNUC__) -# define _LIBCPP_COMPILER_GCC -# define _LIBCPP_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__) -#endif - #ifdef __cplusplus -// Warn if a compiler version is used that is not supported anymore -// LLVM RELEASE Update the minimum compiler versions -# if defined(_LIBCPP_CLANG_VER) -# if _LIBCPP_CLANG_VER < 1700 -# warning "Libc++ only supports Clang 17 and later" -# endif -# elif defined(_LIBCPP_APPLE_CLANG_VER) -# if _LIBCPP_APPLE_CLANG_VER < 1500 -# warning "Libc++ only supports AppleClang 15 and later" -# endif -# elif defined(_LIBCPP_GCC_VER) -# if _LIBCPP_GCC_VER < 1300 -# warning "Libc++ only supports GCC 13 and later" -# endif -# endif - // The attributes supported by clang are documented at https://clang.llvm.org/docs/AttributeReference.html // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. @@ -71,176 +36,12 @@ # define _LIBCPP_FREESTANDING # endif -// NOLINTBEGIN(libcpp-cpp-version-check) -# ifndef _LIBCPP_STD_VER -# if __cplusplus <= 201103L -# define _LIBCPP_STD_VER 11 -# elif __cplusplus <= 201402L -# define _LIBCPP_STD_VER 14 -# elif __cplusplus <= 201703L -# define _LIBCPP_STD_VER 17 -# elif __cplusplus <= 202002L -# define _LIBCPP_STD_VER 20 -# elif __cplusplus <= 202302L -# define _LIBCPP_STD_VER 23 -# else -// Expected release year of the next C++ standard -# define _LIBCPP_STD_VER 26 -# endif -# endif // _LIBCPP_STD_VER -// NOLINTEND(libcpp-cpp-version-check) - -# if defined(__ELF__) -# define _LIBCPP_OBJECT_FORMAT_ELF 1 -# elif defined(__MACH__) -# define _LIBCPP_OBJECT_FORMAT_MACHO 1 -# elif defined(_WIN32) -# define _LIBCPP_OBJECT_FORMAT_COFF 1 -# elif defined(__wasm__) -# define _LIBCPP_OBJECT_FORMAT_WASM 1 -# elif defined(_AIX) -# define _LIBCPP_OBJECT_FORMAT_XCOFF 1 -# else -// ... add new file formats here ... -# endif - -// ABI { - -# if _LIBCPP_ABI_VERSION >= 2 -// Change short string representation so that string data starts at offset 0, -// improving its alignment in some cases. -# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT -// Fix deque iterator type in order to support incomplete types. -# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE -// Fix undefined behavior in how std::list stores its linked nodes. -# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB -// Fix undefined behavior in how __tree stores its end and parent nodes. -# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB -// Fix undefined behavior in how __hash_table stores its pointer types. -# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB -# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB -# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE -// Define a key function for `bad_function_call` in the library, to centralize -// its vtable and typeinfo to libc++ rather than having all other libraries -// using that class define their own copies. -# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION -// Override the default return value of exception::what() for -// bad_function_call::what() with a string that is specific to -// bad_function_call (see http://wg21.link/LWG2233). This is an ABI break -// because it changes the vtable layout of bad_function_call. -# define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE -// Enable optimized version of __do_get_(un)signed which avoids redundant copies. -# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET -// Give reverse_iterator one data member of type T, not two. -// Also, in C++17 and later, don't derive iterator types from std::iterator. -# define _LIBCPP_ABI_NO_ITERATOR_BASES -// Use the smallest possible integer type to represent the index of the variant. -// Previously libc++ used "unsigned int" exclusively. -# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION -// Unstable attempt to provide a more optimized std::function -# define _LIBCPP_ABI_OPTIMIZED_FUNCTION -// All the regex constants must be distinct and nonzero. -# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO -// Re-worked external template instantiations for std::string with a focus on -// performance and fast-path inlining. -# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION -// Enable clang::trivial_abi on std::unique_ptr. -# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI -// Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr -# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI -// std::random_device holds some state when it uses an implementation that gets -// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this -// implementation to another one on a platform that has already shipped -// std::random_device, one needs to retain the same object layout to remain ABI -// compatible. This switch removes these workarounds for platforms that don't care -// about ABI compatibility. -# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT -// Don't export the legacy __basic_string_common class and its methods from the built library. -# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON -// Don't export the legacy __vector_base_common class and its methods from the built library. -# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON -// According to the Standard, `bitset::operator[] const` returns bool -# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL -// Fix the implementation of CityHash used for std::hash. -// This is an ABI break because `std::hash` will return a different result, -// which means that hashing the same object in translation units built against -// different versions of libc++ can return inconsistent results. This is especially -// tricky since std::hash is used in the implementation of unordered containers. -// -// The incorrect implementation of CityHash has the problem that it drops some -// bits on the floor. -# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION -// Remove the base 10 implementation of std::to_chars from the dylib. -// The implementation moved to the header, but we still export the symbols from -// the dylib for backwards compatibility. -# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 -// Define std::array/std::string_view iterators to be __wrap_iters instead of raw -// pointers, which prevents people from relying on a non-portable implementation -// detail. This is especially useful because enabling bounded iterators hardening -// requires code not to make these assumptions. -# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY -# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW -# elif _LIBCPP_ABI_VERSION == 1 -# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)) -// Enable compiling copies of now inline methods into the dylib to support -// applications compiled against older libraries. This is unnecessary with -// COFF dllexport semantics, since dllexport forces a non-inline definition -// of inline functions to be emitted anyway. Our own non-inline copy would -// conflict with the dllexport-emitted copy, so we disable it. For XCOFF, -// the linker will take issue with the symbols in the shared object if the -// weak inline methods get visibility (such as from -fvisibility-inlines-hidden), -// so disable it. -# define _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS -# endif -// Feature macros for disabling pre ABI v1 features. All of these options -// are deprecated. -# if defined(__FreeBSD__) && __FreeBSD__ < 14 -# define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR -# endif -// For XCOFF linkers, we have problems if we see a weak hidden version of a symbol -// in user code (like you get with -fvisibility-inlines-hidden) and then a strong def -// in the library, so we need to always rely on the library version. -# if defined(_AIX) -# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION -# endif -# endif - -# if defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_ABI_VERSION >= 2 -// Define a key function for `bad_function_call` in the library, to centralize -// its vtable and typeinfo to libc++ rather than having all other libraries -// using that class define their own copies. -# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION -# endif - -// We had some bugs where we use [[no_unique_address]] together with construct_at, -// which causes UB as the call on construct_at could write to overlapping subobjects -// -// https://github.com/llvm/llvm-project/issues/70506 -// https://github.com/llvm/llvm-project/issues/70494 -// -// To fix the bug we had to change the ABI of some classes to remove [[no_unique_address]] under certain conditions. -// The macro below is used for all classes whose ABI have changed as part of fixing these bugs. -# define _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS __attribute__((__abi_tag__("llvm18_nua"))) - -// Changes the iterator type of select containers (see below) to a bounded iterator that keeps track of whether it's -// within the bounds of the original container and asserts it on every dereference. -// -// ABI impact: changes the iterator type of the relevant containers. -// -// Supported containers: -// - `span`; -// - `string_view`; -// - `array`. -// #define _LIBCPP_ABI_BOUNDED_ITERATORS - -// } ABI - // HARDENING { -// TODO(hardening): deprecate this in LLVM 19. // This is for backward compatibility -- make enabling `_LIBCPP_ENABLE_ASSERTIONS` (which predates hardening modes) -// equivalent to setting the extensive mode. +// equivalent to setting the extensive mode. This is deprecated and will be removed in LLVM 20. # ifdef _LIBCPP_ENABLE_ASSERTIONS +# warning "_LIBCPP_ENABLE_ASSERTIONS is deprecated, please use _LIBCPP_HARDENING_MODE instead" # if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1 # error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1" # endif @@ -361,26 +162,6 @@ _LIBCPP_HARDENING_MODE_DEBUG # define _LIBCPP_CXX03_LANG # endif -# ifndef __has_attribute -# define __has_attribute(__x) 0 -# endif - -# ifndef __has_builtin -# define __has_builtin(__x) 0 -# endif - -# ifndef __has_extension -# define __has_extension(__x) 0 -# endif - -# ifndef __has_feature -# define __has_feature(__x) 0 -# endif - -# ifndef __has_cpp_attribute -# define __has_cpp_attribute(__x) 0 -# endif - # ifndef __has_constexpr_builtin # define __has_constexpr_builtin(x) 0 # endif @@ -402,10 +183,6 @@ _LIBCPP_HARDENING_MODE_DEBUG # define __has_keyword(__x) !(__is_identifier(__x)) -# ifndef __has_include -# define __has_include(...) 0 -# endif - # ifndef __has_warning # define __has_warning(...) 0 # endif @@ -448,35 +225,14 @@ _LIBCPP_HARDENING_MODE_DEBUG # if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) # define _LIBCPP_HAS_NO_INCOMPLETE_PSTL # define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN -# define _LIBCPP_HAS_NO_INCOMPLETE_TZDB +# define _LIBCPP_HAS_NO_EXPERIMENTAL_TZDB # define _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM # endif -// Need to detect which libc we're using if we're on Linux. -# if defined(__linux__) -# include -# if defined(__GLIBC_PREREQ) -# define _LIBCPP_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b) -# else -# define _LIBCPP_GLIBC_PREREQ(a, b) 0 -# endif // defined(__GLIBC_PREREQ) -# endif // defined(__linux__) - # if defined(__MVS__) # include // for __NATIVE_ASCII_F # endif -# ifndef __BYTE_ORDER__ -# error \ - "Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform" -# endif - -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define _LIBCPP_LITTLE_ENDIAN -# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define _LIBCPP_BIG_ENDIAN -# endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - # if defined(_WIN32) # define _LIBCPP_WIN32API # define _LIBCPP_SHORT_WCHAR 1 @@ -580,63 +336,32 @@ typedef __char32_t char32_t; # endif -# if !defined(__cpp_exceptions) || __cpp_exceptions < 199711L -# define _LIBCPP_HAS_NO_EXCEPTIONS -# endif - # define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) -# if defined(_LIBCPP_COMPILER_CLANG_BASED) - -# if defined(__APPLE__) -# if defined(__i386__) || defined(__x86_64__) -// use old string layout on x86_64 and i386 -# elif defined(__arm__) -// use old string layout on arm (which does not include aarch64/arm64), except on watch ABIs -# if defined(__ARM_ARCH_7K__) && __ARM_ARCH_7K__ >= 2 -# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT -# endif -# else -# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT -# endif -# endif - // Objective-C++ features (opt-in) -# if __has_feature(objc_arc) -# define _LIBCPP_HAS_OBJC_ARC -# endif +# if __has_feature(objc_arc) +# define _LIBCPP_HAS_OBJC_ARC +# endif -# if __has_feature(objc_arc_weak) -# define _LIBCPP_HAS_OBJC_ARC_WEAK -# endif +# if __has_feature(objc_arc_weak) +# define _LIBCPP_HAS_OBJC_ARC_WEAK +# endif -# if __has_extension(blocks) -# define _LIBCPP_HAS_EXTENSION_BLOCKS -# endif +# if __has_extension(blocks) +# define _LIBCPP_HAS_EXTENSION_BLOCKS +# endif -# if defined(_LIBCPP_HAS_EXTENSION_BLOCKS) && defined(__APPLE__) -# define _LIBCPP_HAS_BLOCKS_RUNTIME -# endif +# if defined(_LIBCPP_HAS_EXTENSION_BLOCKS) && defined(__APPLE__) +# define _LIBCPP_HAS_BLOCKS_RUNTIME +# endif -# if !__has_feature(address_sanitizer) -# define _LIBCPP_HAS_NO_ASAN -# endif +# if !__has_feature(address_sanitizer) +# define _LIBCPP_HAS_NO_ASAN +# endif -# define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__)) +# define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__)) -# define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ - -# elif defined(_LIBCPP_COMPILER_GCC) - -# if !defined(__SANITIZE_ADDRESS__) -# define _LIBCPP_HAS_NO_ASAN -# endif - -# define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__)) - -# define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ - -# endif // _LIBCPP_COMPILER_[CLANG|GCC] +# define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__ # if defined(_LIBCPP_OBJECT_FORMAT_COFF) @@ -817,16 +542,12 @@ typedef __char32_t char32_t; # ifndef _LIBCPP_NO_ABI_TAG # define _LIBCPP_HIDE_FROM_ABI \ _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION \ - __attribute__((__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_ODR_SIGNATURE)))) + __attribute__((__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_ODR_SIGNATURE)))) # else # define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION # endif # define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION -// This macro provides a HIDE_FROM_ABI equivalent that can be applied to extern -// "C" function, as those lack mangling. -# define _LIBCPP_HIDE_FROM_ABI_C _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION - # ifdef _LIBCPP_BUILDING_LIBRARY # if _LIBCPP_ABI_VERSION > 1 # define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI @@ -838,11 +559,11 @@ typedef __char32_t char32_t; # endif // TODO: Remove this workaround once we drop support for Clang 16 -#if __has_warning("-Wc++23-extensions") -# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions") -#else -# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++2b-extensions") -#endif +# if __has_warning("-Wc++23-extensions") +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions") +# else +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++2b-extensions") +# endif // Clang modules take a significant compile time hit when pushing and popping diagnostics. // Since all the headers are marked as system headers in the modulemap, we can simply disable this @@ -872,10 +593,16 @@ typedef __char32_t char32_t; inline namespace _LIBCPP_ABI_NAMESPACE { # define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_POP_EXTENSION_DIAGNOSTICS +#ifdef _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE +# define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM _LIBCPP_BEGIN_NAMESPACE_STD namespace filesystem { +# define _LIBCPP_END_NAMESPACE_FILESYSTEM } _LIBCPP_END_NAMESPACE_STD +#else # define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM _LIBCPP_BEGIN_NAMESPACE_STD \ inline namespace __fs { namespace filesystem { # define _LIBCPP_END_NAMESPACE_FILESYSTEM }} _LIBCPP_END_NAMESPACE_STD +#endif + // clang-format on # if __has_attribute(__enable_if__) @@ -972,6 +699,14 @@ typedef __char32_t char32_t; # define _LIBCPP_DEPRECATED_(m) # endif +# if _LIBCPP_STD_VER < 20 +# define _LIBCPP_DEPRECATED_ATOMIC_SYNC \ + _LIBCPP_DEPRECATED_("The C++20 synchronization library has been deprecated prior to C++20. Please update to " \ + "using -std=c++20 if you need to use these facilities.") +# else +# define _LIBCPP_DEPRECATED_ATOMIC_SYNC /* nothing */ +# endif + # if !defined(_LIBCPP_CXX03_LANG) # define _LIBCPP_DEPRECATED_IN_CXX11 _LIBCPP_DEPRECATED # else @@ -1061,20 +796,6 @@ typedef __char32_t char32_t; # define _LIBCPP_CONSTEXPR_SINCE_CXX23 # endif -# ifndef _LIBCPP_HAS_NO_ASAN -extern "C" _LIBCPP_EXPORTED_FROM_ABI void -__sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*); -extern "C" _LIBCPP_EXPORTED_FROM_ABI void __sanitizer_annotate_double_ended_contiguous_container( - const void*, const void*, const void*, const void*, const void*, const void*); -extern "C" _LIBCPP_EXPORTED_FROM_ABI int -__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*); -# endif - -// Try to find out if RTTI is disabled. -# if !defined(__cpp_rtti) || __cpp_rtti < 199711L -# define _LIBCPP_HAS_NO_RTTI -# endif - # ifndef _LIBCPP_WEAK # define _LIBCPP_WEAK __attribute__((__weak__)) # endif @@ -1247,21 +968,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_IF_WIDE_CHARACTERS(...) __VA_ARGS__ # endif -# if defined(_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES) -# define _LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR -# define _LIBCPP_ENABLE_CXX17_REMOVED_BINDERS -# define _LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE -# define _LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS -# define _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION -# endif // _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES - -# if defined(_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES) -# define _LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS -# define _LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS -# define _LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR -# define _LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS -# endif // _LIBCPP_ENABLE_CXX20_REMOVED_FEATURES - // clang-format off # define _LIBCPP_PUSH_MACROS _Pragma("push_macro(\"min\")") _Pragma("push_macro(\"max\")") _Pragma("push_macro(\"refresh\")") _Pragma("push_macro(\"move\")") _Pragma("push_macro(\"erase\")") # define _LIBCPP_POP_MACROS _Pragma("pop_macro(\"min\")") _Pragma("pop_macro(\"max\")") _Pragma("pop_macro(\"refresh\")") _Pragma("pop_macro(\"move\")") _Pragma("pop_macro(\"erase\")") @@ -1418,7 +1124,7 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_USING_IF_EXISTS # endif -# if __has_cpp_attribute(nodiscard) +# if __has_cpp_attribute(__nodiscard__) # define _LIBCPP_NODISCARD [[__nodiscard__]] # else // We can't use GCC's [[gnu::warn_unused_result]] and @@ -1427,27 +1133,13 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # define _LIBCPP_NODISCARD # endif -// _LIBCPP_NODISCARD_EXT may be used to apply [[nodiscard]] to entities not -// specified as such as an extension. -# if !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_EXT _LIBCPP_NODISCARD -# else -# define _LIBCPP_NODISCARD_EXT -# endif - -# if _LIBCPP_STD_VER >= 20 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) -# define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD -# else -# define _LIBCPP_NODISCARD_AFTER_CXX17 -# endif - # if __has_attribute(__no_destroy__) # define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__)) # else # define _LIBCPP_NO_DESTROY # endif -# if __has_attribute(__diagnose_if__) && !defined(_LIBCPP_DISABLE_ADDITIONAL_DIAGNOSTICS) +# if __has_attribute(__diagnose_if__) # define _LIBCPP_DIAGNOSE_WARNING(...) __attribute__((__diagnose_if__(__VA_ARGS__, "warning"))) # else # define _LIBCPP_DIAGNOSE_WARNING(...) diff --git a/naiveproxy/src/third_party/libc++/src/include/__config_site.in b/naiveproxy/src/third_party/libc++/src/include/__config_site.in index 7c002c5bfc..67022146c9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__config_site.in +++ b/naiveproxy/src/third_party/libc++/src/include/__config_site.in @@ -26,15 +26,16 @@ #cmakedefine _LIBCPP_HAS_NO_FILESYSTEM #cmakedefine _LIBCPP_HAS_NO_RANDOM_DEVICE #cmakedefine _LIBCPP_HAS_NO_LOCALIZATION +#cmakedefine _LIBCPP_HAS_NO_UNICODE #cmakedefine _LIBCPP_HAS_NO_WIDE_CHARACTERS #cmakedefine _LIBCPP_HAS_NO_STD_MODULES #cmakedefine _LIBCPP_HAS_NO_TIME_ZONE_DATABASE #cmakedefine _LIBCPP_INSTRUMENTED_WITH_ASAN // PSTL backends -#cmakedefine _LIBCPP_PSTL_CPU_BACKEND_SERIAL -#cmakedefine _LIBCPP_PSTL_CPU_BACKEND_THREAD -#cmakedefine _LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH +#cmakedefine _LIBCPP_PSTL_BACKEND_SERIAL +#cmakedefine _LIBCPP_PSTL_BACKEND_STD_THREAD +#cmakedefine _LIBCPP_PSTL_BACKEND_LIBDISPATCH // Hardening. #cmakedefine _LIBCPP_HARDENING_MODE_DEFAULT @_LIBCPP_HARDENING_MODE_DEFAULT@ diff --git a/naiveproxy/src/third_party/libc++/src/include/__configuration/abi.h b/naiveproxy/src/third_party/libc++/src/include/__configuration/abi.h new file mode 100644 index 0000000000..513da6e3b8 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__configuration/abi.h @@ -0,0 +1,148 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONFIGURATION_ABI_H +#define _LIBCPP___CONFIGURATION_ABI_H + +#include <__config_site> +#include <__configuration/compiler.h> +#include <__configuration/platform.h> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +#if _LIBCPP_ABI_VERSION >= 2 +// Change short string representation so that string data starts at offset 0, +// improving its alignment in some cases. +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +// Fix deque iterator type in order to support incomplete types. +# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE +// Fix undefined behavior in how std::list stores its linked nodes. +# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB +// Fix undefined behavior in how __tree stores its end and parent nodes. +# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB +// Fix undefined behavior in how __hash_table stores its pointer types. +# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB +# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB +# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE +// Override the default return value of exception::what() for bad_function_call::what() +// with a string that is specific to bad_function_call (see http://wg21.link/LWG2233). +// This is an ABI break on platforms that sign and authenticate vtable function pointers +// because it changes the mangling of the virtual function located in the vtable, which +// changes how it gets signed. +# define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE +// Enable optimized version of __do_get_(un)signed which avoids redundant copies. +# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET +// Give reverse_iterator one data member of type T, not two. +// Also, in C++17 and later, don't derive iterator types from std::iterator. +# define _LIBCPP_ABI_NO_ITERATOR_BASES +// Use the smallest possible integer type to represent the index of the variant. +// Previously libc++ used "unsigned int" exclusively. +# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION +// Unstable attempt to provide a more optimized std::function +# define _LIBCPP_ABI_OPTIMIZED_FUNCTION +// All the regex constants must be distinct and nonzero. +# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO +// Re-worked external template instantiations for std::string with a focus on +// performance and fast-path inlining. +# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION +// Enable clang::trivial_abi on std::unique_ptr. +# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI +// Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr +# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI +// std::random_device holds some state when it uses an implementation that gets +// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this +// implementation to another one on a platform that has already shipped +// std::random_device, one needs to retain the same object layout to remain ABI +// compatible. This switch removes these workarounds for platforms that don't care +// about ABI compatibility. +# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT +// Don't export the legacy __basic_string_common class and its methods from the built library. +# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON +// Don't export the legacy __vector_base_common class and its methods from the built library. +# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON +// According to the Standard, `bitset::operator[] const` returns bool +# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL +// Fix the implementation of CityHash used for std::hash. +// This is an ABI break because `std::hash` will return a different result, +// which means that hashing the same object in translation units built against +// different versions of libc++ can return inconsistent results. This is especially +// tricky since std::hash is used in the implementation of unordered containers. +// +// The incorrect implementation of CityHash has the problem that it drops some +// bits on the floor. +# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION +// Remove the base 10 implementation of std::to_chars from the dylib. +// The implementation moved to the header, but we still export the symbols from +// the dylib for backwards compatibility. +# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 +// Define std::array/std::string_view iterators to be __wrap_iters instead of raw +// pointers, which prevents people from relying on a non-portable implementation +// detail. This is especially useful because enabling bounded iterators hardening +// requires code not to make these assumptions. +# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY +# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW +// Dont' add an inline namespace for `std::filesystem` +# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE +#elif _LIBCPP_ABI_VERSION == 1 +# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)) +// Enable compiling copies of now inline methods into the dylib to support +// applications compiled against older libraries. This is unnecessary with +// COFF dllexport semantics, since dllexport forces a non-inline definition +// of inline functions to be emitted anyway. Our own non-inline copy would +// conflict with the dllexport-emitted copy, so we disable it. For XCOFF, +// the linker will take issue with the symbols in the shared object if the +// weak inline methods get visibility (such as from -fvisibility-inlines-hidden), +// so disable it. +# define _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS +# endif +// Feature macros for disabling pre ABI v1 features. All of these options +// are deprecated. +# if defined(__FreeBSD__) && __FreeBSD__ < 14 +# define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR +# endif +#endif + +// We had some bugs where we use [[no_unique_address]] together with construct_at, +// which causes UB as the call on construct_at could write to overlapping subobjects +// +// https://github.com/llvm/llvm-project/issues/70506 +// https://github.com/llvm/llvm-project/issues/70494 +// +// To fix the bug we had to change the ABI of some classes to remove [[no_unique_address]] under certain conditions. +// The macro below is used for all classes whose ABI have changed as part of fixing these bugs. +#define _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS __attribute__((__abi_tag__("llvm18_nua"))) + +// Changes the iterator type of select containers (see below) to a bounded iterator that keeps track of whether it's +// within the bounds of the original container and asserts it on every dereference. +// +// ABI impact: changes the iterator type of the relevant containers. +// +// Supported containers: +// - `span`; +// - `string_view`. +// #define _LIBCPP_ABI_BOUNDED_ITERATORS + +#if defined(_LIBCPP_COMPILER_CLANG_BASED) +# if defined(__APPLE__) +# if defined(__i386__) || defined(__x86_64__) +// use old string layout on x86_64 and i386 +# elif defined(__arm__) +// use old string layout on arm (which does not include aarch64/arm64), except on watch ABIs +# if defined(__ARM_ARCH_7K__) && __ARM_ARCH_7K__ >= 2 +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# endif +# else +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# endif +# endif +#endif + +#endif // _LIBCPP___CONFIGURATION_ABI_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__configuration/availability.h b/naiveproxy/src/third_party/libc++/src/include/__configuration/availability.h new file mode 100644 index 0000000000..ab483a07c9 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__configuration/availability.h @@ -0,0 +1,400 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONFIGURATION_AVAILABILITY_H +#define _LIBCPP___CONFIGURATION_AVAILABILITY_H + +#include <__configuration/compiler.h> +#include <__configuration/language.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// Libc++ is shipped by various vendors. In particular, it is used as a system +// library on macOS, iOS and other Apple platforms. In order for users to be +// able to compile a binary that is intended to be deployed to an older version +// of a platform, Clang provides availability attributes [1]. These attributes +// can be placed on declarations and are used to describe the life cycle of a +// symbol in the library. +// +// The main goal is to ensure a compile-time error if a symbol that hasn't been +// introduced in a previously released library is used in a program that targets +// that previously released library. Normally, this would be a load-time error +// when one tries to launch the program against the older library. +// +// For example, the filesystem library was introduced in the dylib in LLVM 9. +// On Apple platforms, this corresponds to macOS 10.15. If a user compiles on +// a macOS 10.15 host but targets macOS 10.13 with their program, the compiler +// would normally not complain (because the required declarations are in the +// headers), but the dynamic loader would fail to find the symbols when actually +// trying to launch the program on macOS 10.13. To turn this into a compile-time +// issue instead, declarations are annotated with when they were introduced, and +// the compiler can produce a diagnostic if the program references something that +// isn't available on the deployment target. +// +// This mechanism is general in nature, and any vendor can add their markup to +// the library (see below). Whenever a new feature is added that requires support +// in the shared library, two macros are added below to allow marking the feature +// as unavailable: +// 1. A macro named `_LIBCPP_AVAILABILITY_HAS_` which must be defined +// to `_LIBCPP_INTRODUCED_IN_` for the appropriate LLVM version. +// 2. A macro named `_LIBCPP_AVAILABILITY_`, which must be defined to +// `_LIBCPP_INTRODUCED_IN__MARKUP` for the appropriate LLVM version. +// +// When vendors decide to ship the feature as part of their shared library, they +// can update the `_LIBCPP_INTRODUCED_IN_` macro (and the markup counterpart) +// based on the platform version they shipped that version of LLVM in. The library +// will then use this markup to provide an optimal user experience on these platforms. +// +// Furthermore, many features in the standard library have corresponding +// feature-test macros. The `_LIBCPP_AVAILABILITY_HAS_` macros +// are checked by the corresponding feature-test macros generated by +// generate_feature_test_macro_components.py to ensure that the library +// doesn't announce a feature as being implemented if it is unavailable on +// the deployment target. +// +// Note that this mechanism is disabled by default in the "upstream" libc++. +// Availability annotations are only meaningful when shipping libc++ inside +// a platform (i.e. as a system library), and so vendors that want them should +// turn those annotations on at CMake configuration time. +// +// [1]: https://clang.llvm.org/docs/AttributeReference.html#availability + +// For backwards compatibility, allow users to define _LIBCPP_DISABLE_AVAILABILITY +// for a while. +#if defined(_LIBCPP_DISABLE_AVAILABILITY) +# if !defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) +# define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS +# endif +#endif + +// Availability markup is disabled when building the library, or when a non-Clang +// compiler is used because only Clang supports the necessary attributes. +#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || !defined(_LIBCPP_COMPILER_CLANG_BASED) +# if !defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) +# define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS +# endif +#endif + +// When availability annotations are disabled, we take for granted that features introduced +// in all versions of the library are available. +#if defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) + +# define _LIBCPP_INTRODUCED_IN_LLVM_19 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_18 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_18_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_17 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_17_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_16 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_16_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_15 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_14 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_14_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_13 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_13_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_12 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_12_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_11 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_11_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_10 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_10_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_9 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE /* nothing */ +# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_PUSH /* nothing */ +# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_POP /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_8 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_8_ATTRIBUTE /* nothing */ + +# define _LIBCPP_INTRODUCED_IN_LLVM_4 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE /* nothing */ + +#elif defined(__APPLE__) + +// clang-format off + +// LLVM 19 +// TODO: Fill this in +# define _LIBCPP_INTRODUCED_IN_LLVM_19 0 +# define _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE __attribute__((unavailable)) + +// LLVM 18 +// TODO: Fill this in +# define _LIBCPP_INTRODUCED_IN_LLVM_18 0 +# define _LIBCPP_INTRODUCED_IN_LLVM_18_ATTRIBUTE __attribute__((unavailable)) + +// LLVM 17 +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 140400) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 170400) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 170400) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 100400) +# define _LIBCPP_INTRODUCED_IN_LLVM_17 0 +# else +# define _LIBCPP_INTRODUCED_IN_LLVM_17 1 +# endif +# define _LIBCPP_INTRODUCED_IN_LLVM_17_ATTRIBUTE \ + __attribute__((availability(macos, strict, introduced = 14.4))) \ + __attribute__((availability(ios, strict, introduced = 17.4))) \ + __attribute__((availability(tvos, strict, introduced = 17.4))) \ + __attribute__((availability(watchos, strict, introduced = 10.4))) + +// LLVM 16 +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 170000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 170000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 100000) +# define _LIBCPP_INTRODUCED_IN_LLVM_16 0 +# else +# define _LIBCPP_INTRODUCED_IN_LLVM_16 1 +# endif +# define _LIBCPP_INTRODUCED_IN_LLVM_16_ATTRIBUTE \ + __attribute__((availability(macos, strict, introduced = 14.0))) \ + __attribute__((availability(ios, strict, introduced = 17.0))) \ + __attribute__((availability(tvos, strict, introduced = 17.0))) \ + __attribute__((availability(watchos, strict, introduced = 10.0))) + +// LLVM 15 +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 130400) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 160500) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 160500) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 90500) +# define _LIBCPP_INTRODUCED_IN_LLVM_15 0 +# else +# define _LIBCPP_INTRODUCED_IN_LLVM_15 1 +# endif +# define _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE \ + __attribute__((availability(macos, strict, introduced = 13.4))) \ + __attribute__((availability(ios, strict, introduced = 16.5))) \ + __attribute__((availability(tvos, strict, introduced = 16.5))) \ + __attribute__((availability(watchos, strict, introduced = 9.5))) + +// LLVM 14 +# define _LIBCPP_INTRODUCED_IN_LLVM_14 _LIBCPP_INTRODUCED_IN_LLVM_15 +# define _LIBCPP_INTRODUCED_IN_LLVM_14_ATTRIBUTE _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE + +// LLVM 13 +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 160000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 160000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 90000) +# define _LIBCPP_INTRODUCED_IN_LLVM_13 0 +# else +# define _LIBCPP_INTRODUCED_IN_LLVM_13 1 +# endif +# define _LIBCPP_INTRODUCED_IN_LLVM_13_ATTRIBUTE \ + __attribute__((availability(macos, strict, introduced = 13.0))) \ + __attribute__((availability(ios, strict, introduced = 16.0))) \ + __attribute__((availability(tvos, strict, introduced = 16.0))) \ + __attribute__((availability(watchos, strict, introduced = 9.0))) + +// LLVM 12 +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 120300) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 150300) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 150300) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 80300) +# define _LIBCPP_INTRODUCED_IN_LLVM_12 0 +# else +# define _LIBCPP_INTRODUCED_IN_LLVM_12 1 +# endif +# define _LIBCPP_INTRODUCED_IN_LLVM_12_ATTRIBUTE \ + __attribute__((availability(macos, strict, introduced = 12.3))) \ + __attribute__((availability(ios, strict, introduced = 15.3))) \ + __attribute__((availability(tvos, strict, introduced = 15.3))) \ + __attribute__((availability(watchos, strict, introduced = 8.3))) + +// LLVM 11 +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_INTRODUCED_IN_LLVM_11 0 +# else +# define _LIBCPP_INTRODUCED_IN_LLVM_11 1 +# endif +# define _LIBCPP_INTRODUCED_IN_LLVM_11_ATTRIBUTE \ + __attribute__((availability(macos, strict, introduced = 11.0))) \ + __attribute__((availability(ios, strict, introduced = 14.0))) \ + __attribute__((availability(tvos, strict, introduced = 14.0))) \ + __attribute__((availability(watchos, strict, introduced = 7.0))) + +// LLVM 10 +# define _LIBCPP_INTRODUCED_IN_LLVM_10 _LIBCPP_INTRODUCED_IN_LLVM_11 +# define _LIBCPP_INTRODUCED_IN_LLVM_10_ATTRIBUTE _LIBCPP_INTRODUCED_IN_LLVM_11_ATTRIBUTE + +// LLVM 9 +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) +# define _LIBCPP_INTRODUCED_IN_LLVM_9 0 +# else +# define _LIBCPP_INTRODUCED_IN_LLVM_9 1 +# endif +# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE \ + __attribute__((availability(macos, strict, introduced = 10.15))) \ + __attribute__((availability(ios, strict, introduced = 13.0))) \ + __attribute__((availability(tvos, strict, introduced = 13.0))) \ + __attribute__((availability(watchos, strict, introduced = 6.0))) +# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_PUSH \ + _Pragma("clang attribute push(__attribute__((availability(macos,strict,introduced=10.15))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(ios,strict,introduced=13.0))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(tvos,strict,introduced=13.0))), apply_to=any(function,record))") \ + _Pragma("clang attribute push(__attribute__((availability(watchos,strict,introduced=6.0))), apply_to=any(function,record))") +# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_POP \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") \ + _Pragma("clang attribute pop") + +// LLVM 4 +# if defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000 +# define _LIBCPP_INTRODUCED_IN_LLVM_4 0 +# else +# define _LIBCPP_INTRODUCED_IN_LLVM_4 1 +# endif +# define _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE __attribute__((availability(watchos, strict, introduced = 5.0))) + +// clang-format on + +#else + +// ...New vendors can add availability markup here... + +# error \ + "It looks like you're trying to enable vendor availability markup, but you haven't defined the corresponding macros yet!" + +#endif + +// These macros control the availability of std::bad_optional_access and +// other exception types. These were put in the shared library to prevent +// code bloat from every user program defining the vtable for these exception +// types. +// +// Note that when exceptions are disabled, the methods that normally throw +// these exceptions can be used even on older deployment targets, but those +// methods will abort instead of throwing. +#define _LIBCPP_AVAILABILITY_HAS_BAD_OPTIONAL_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4 +#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE + +#define _LIBCPP_AVAILABILITY_HAS_BAD_VARIANT_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4 +#define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE + +#define _LIBCPP_AVAILABILITY_HAS_BAD_ANY_CAST _LIBCPP_INTRODUCED_IN_LLVM_4 +#define _LIBCPP_AVAILABILITY_BAD_ANY_CAST _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE + +// These macros control the availability of all parts of that +// depend on something in the dylib. +#define _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY _LIBCPP_INTRODUCED_IN_LLVM_9 +#define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE +#define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_PUSH +#define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_POP + +// This controls the availability of the C++20 synchronization library, +// which requires shared library support for various operations +// (see libcxx/src/atomic.cpp). This includes , , +// , and notification functions on std::atomic. +#define _LIBCPP_AVAILABILITY_HAS_SYNC _LIBCPP_INTRODUCED_IN_LLVM_11 +#define _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INTRODUCED_IN_LLVM_11_ATTRIBUTE + +// Enable additional explicit instantiations of iostreams components. This +// reduces the number of weak definitions generated in programs that use +// iostreams by providing a single strong definition in the shared library. +// +// TODO: Enable additional explicit instantiations on GCC once it supports exclude_from_explicit_instantiation, +// or once libc++ doesn't use the attribute anymore. +// TODO: Enable them on Windows once https://llvm.org/PR41018 has been fixed. +#if !defined(_LIBCPP_COMPILER_GCC) && !defined(_WIN32) +# define _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 _LIBCPP_INTRODUCED_IN_LLVM_12 +#else +# define _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 0 +#endif + +// This controls the availability of floating-point std::to_chars functions. +// These overloads were added later than the integer overloads. +#define _LIBCPP_AVAILABILITY_HAS_TO_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_14 +#define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_14_ATTRIBUTE + +// This controls whether the library claims to provide a default verbose +// termination function, and consequently whether the headers will try +// to use it when the mechanism isn't overriden at compile-time. +#define _LIBCPP_AVAILABILITY_HAS_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15 +#define _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE + +// This controls the availability of the C++17 std::pmr library, +// which is implemented in large part in the built library. +// +// TODO: Enable std::pmr markup once https://github.com/llvm/llvm-project/issues/40340 has been fixed +// Until then, it is possible for folks to try to use `std::pmr` when back-deploying to targets that don't support +// it and it'll be a load-time error, but we don't have a good alternative because the library won't compile if we +// use availability annotations until that bug has been fixed. +#define _LIBCPP_AVAILABILITY_HAS_PMR _LIBCPP_INTRODUCED_IN_LLVM_16 +#define _LIBCPP_AVAILABILITY_PMR + +// These macros controls the availability of __cxa_init_primary_exception +// in the built library, which std::make_exception_ptr might use +// (see libcxx/include/__exception/exception_ptr.h). +#define _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION _LIBCPP_INTRODUCED_IN_LLVM_18 +#define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION _LIBCPP_INTRODUCED_IN_LLVM_18_ATTRIBUTE + +// This controls the availability of C++23 , which +// has a dependency on the built library (it needs access to +// the underlying buffer types of std::cout, std::cerr, and std::clog. +#define _LIBCPP_AVAILABILITY_HAS_PRINT _LIBCPP_INTRODUCED_IN_LLVM_18 +#define _LIBCPP_AVAILABILITY_PRINT _LIBCPP_INTRODUCED_IN_LLVM_18_ATTRIBUTE + +// This controls the availability of the C++20 time zone database. +// The parser code is built in the library. +#define _LIBCPP_AVAILABILITY_HAS_TZDB _LIBCPP_INTRODUCED_IN_LLVM_19 +#define _LIBCPP_AVAILABILITY_TZDB _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE + +// These macros determine whether we assume that std::bad_function_call and +// std::bad_expected_access provide a key function in the dylib. This allows +// centralizing their vtable and typeinfo instead of having all TUs provide +// a weak definition that then gets deduplicated. +#define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_19 +#define _LIBCPP_AVAILABILITY_BAD_FUNCTION_CALL_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE +#define _LIBCPP_AVAILABILITY_HAS_BAD_EXPECTED_ACCESS_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_19 +#define _LIBCPP_AVAILABILITY_BAD_EXPECTED_ACCESS_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE + +// Define availability attributes that depend on _LIBCPP_HAS_NO_EXCEPTIONS. +// Those are defined in terms of the availability attributes above, and +// should not be vendor-specific. +#if defined(_LIBCPP_HAS_NO_EXCEPTIONS) +# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST +# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS +# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS +#else +# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST _LIBCPP_AVAILABILITY_BAD_ANY_CAST +# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS +# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS +#endif + +// Define availability attributes that depend on both +// _LIBCPP_HAS_NO_EXCEPTIONS and _LIBCPP_HAS_NO_RTTI. +#if defined(_LIBCPP_HAS_NO_EXCEPTIONS) || defined(_LIBCPP_HAS_NO_RTTI) +# undef _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION +# undef _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION +# define _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION 0 +# define _LIBCPP_AVAILABILITY_INIT_PRIMARY_EXCEPTION +#endif + +#endif // _LIBCPP___CONFIGURATION_AVAILABILITY_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__configuration/compiler.h b/naiveproxy/src/third_party/libc++/src/include/__configuration/compiler.h new file mode 100644 index 0000000000..80ece22bb5 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__configuration/compiler.h @@ -0,0 +1,51 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONFIGURATION_COMPILER_H +#define _LIBCPP___CONFIGURATION_COMPILER_H + +#include <__config_site> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +#if defined(__apple_build_version__) +// Given AppleClang XX.Y.Z, _LIBCPP_APPLE_CLANG_VER is XXYZ (e.g. AppleClang 14.0.3 => 1403) +# define _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000) +#elif defined(__clang__) +# define _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__) +#elif defined(__GNUC__) +# define _LIBCPP_COMPILER_GCC +# define _LIBCPP_GCC_VER (__GNUC__ * 100 + __GNUC_MINOR__) +#endif + +#ifdef __cplusplus + +// Warn if a compiler version is used that is not supported anymore +// LLVM RELEASE Update the minimum compiler versions +# if defined(_LIBCPP_CLANG_VER) +# if _LIBCPP_CLANG_VER < 1700 +# warning "Libc++ only supports Clang 17 and later" +# endif +# elif defined(_LIBCPP_APPLE_CLANG_VER) +# if _LIBCPP_APPLE_CLANG_VER < 1500 +# warning "Libc++ only supports AppleClang 15 and later" +# endif +# elif defined(_LIBCPP_GCC_VER) +# if _LIBCPP_GCC_VER < 1400 +# warning "Libc++ only supports GCC 14 and later" +# endif +# endif + +#endif + +#endif // _LIBCPP___CONFIGURATION_COMPILER_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__configuration/language.h b/naiveproxy/src/third_party/libc++/src/include/__configuration/language.h new file mode 100644 index 0000000000..fa62a7b6f5 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__configuration/language.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONFIGURATION_LANGUAGE_H +#define _LIBCPP___CONFIGURATION_LANGUAGE_H + +#include <__config_site> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +// NOLINTBEGIN(libcpp-cpp-version-check) +#ifdef __cplusplus +# if __cplusplus <= 201103L +# define _LIBCPP_STD_VER 11 +# elif __cplusplus <= 201402L +# define _LIBCPP_STD_VER 14 +# elif __cplusplus <= 201703L +# define _LIBCPP_STD_VER 17 +# elif __cplusplus <= 202002L +# define _LIBCPP_STD_VER 20 +# elif __cplusplus <= 202302L +# define _LIBCPP_STD_VER 23 +# else +// Expected release year of the next C++ standard +# define _LIBCPP_STD_VER 26 +# endif +#endif // __cplusplus +// NOLINTEND(libcpp-cpp-version-check) + +#if !defined(__cpp_rtti) || __cpp_rtti < 199711L +# define _LIBCPP_HAS_NO_RTTI +#endif + +#if !defined(__cpp_exceptions) || __cpp_exceptions < 199711L +# define _LIBCPP_HAS_NO_EXCEPTIONS +#endif + +#endif // _LIBCPP___CONFIGURATION_LANGUAGE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__configuration/platform.h b/naiveproxy/src/third_party/libc++/src/include/__configuration/platform.h new file mode 100644 index 0000000000..27f68d04e8 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__configuration/platform.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONFIGURATION_PLATFORM_H +#define _LIBCPP___CONFIGURATION_PLATFORM_H + +#include <__config_site> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +# pragma GCC system_header +#endif + +#if defined(__ELF__) +# define _LIBCPP_OBJECT_FORMAT_ELF 1 +#elif defined(__MACH__) +# define _LIBCPP_OBJECT_FORMAT_MACHO 1 +#elif defined(_WIN32) +# define _LIBCPP_OBJECT_FORMAT_COFF 1 +#elif defined(__wasm__) +# define _LIBCPP_OBJECT_FORMAT_WASM 1 +#elif defined(_AIX) +# define _LIBCPP_OBJECT_FORMAT_XCOFF 1 +#else +// ... add new file formats here ... +#endif + +// Need to detect which libc we're using if we're on Linux. +#if defined(__linux__) +# include +# if defined(__GLIBC_PREREQ) +# define _LIBCPP_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b) +# else +# define _LIBCPP_GLIBC_PREREQ(a, b) 0 +# endif // defined(__GLIBC_PREREQ) +#endif // defined(__linux__) + +#ifndef __BYTE_ORDER__ +# error \ + "Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform" +#endif + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define _LIBCPP_LITTLE_ENDIAN +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define _LIBCPP_BIG_ENDIAN +#endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +#endif // _LIBCPP___CONFIGURATION_PLATFORM_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__debug_utils/sanitizers.h b/naiveproxy/src/third_party/libc++/src/include/__debug_utils/sanitizers.h new file mode 100644 index 0000000000..d8547e3249 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__debug_utils/sanitizers.h @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LIBCXX_DEBUG_UTILS_SANITIZERS_H +#define _LIBCPP___LIBCXX_DEBUG_UTILS_SANITIZERS_H + +#include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_constant_evaluated.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_ASAN + +extern "C" { +_LIBCPP_EXPORTED_FROM_ABI void +__sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*); +_LIBCPP_EXPORTED_FROM_ABI void __sanitizer_annotate_double_ended_contiguous_container( + const void*, const void*, const void*, const void*, const void*, const void*); +_LIBCPP_EXPORTED_FROM_ABI int +__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*); +} + +#endif // _LIBCPP_HAS_NO_ASAN + +_LIBCPP_BEGIN_NAMESPACE_STD + +// ASan choices +#ifndef _LIBCPP_HAS_NO_ASAN +# define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1 +#endif + +#ifdef _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS +// __asan_annotate_container_with_allocator determines whether containers with custom allocators are annotated. This is +// a public customization point to disable annotations if the custom allocator assumes that the memory isn't poisoned. +// See the https://libcxx.llvm.org/UsingLibcxx.html#turning-off-asan-annotation-in-containers for more information. +template +struct __asan_annotate_container_with_allocator : true_type {}; +#endif + +// Annotate a double-ended contiguous range. +// - [__first_storage, __last_storage) is the allocated memory region, +// - [__first_old_contained, __last_old_contained) is the previously allowed (unpoisoned) range, and +// - [__first_new_contained, __last_new_contained) is the new allowed (unpoisoned) range. +template +_LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container( + const void* __first_storage, + const void* __last_storage, + const void* __first_old_contained, + const void* __last_old_contained, + const void* __first_new_contained, + const void* __last_new_contained) { +#ifdef _LIBCPP_HAS_NO_ASAN + (void)__first_storage; + (void)__last_storage; + (void)__first_old_contained; + (void)__last_old_contained; + (void)__first_new_contained; + (void)__last_new_contained; +#else + if (__asan_annotate_container_with_allocator<_Allocator>::value && __first_storage != nullptr) + __sanitizer_annotate_double_ended_contiguous_container( + __first_storage, + __last_storage, + __first_old_contained, + __last_old_contained, + __first_new_contained, + __last_new_contained); +#endif +} + +// Annotate a contiguous range. +// [__first_storage, __last_storage) is the allocated memory region, +// __old_last_contained is the previously last allowed (unpoisoned) element, and +// __new_last_contained is the new last allowed (unpoisoned) element. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __annotate_contiguous_container( + const void* __first_storage, + const void* __last_storage, + const void* __old_last_contained, + const void* __new_last_contained) { +#ifdef _LIBCPP_HAS_NO_ASAN + (void)__first_storage; + (void)__last_storage; + (void)__old_last_contained; + (void)__new_last_contained; +#else + if (!__libcpp_is_constant_evaluated() && __asan_annotate_container_with_allocator<_Allocator>::value && + __first_storage != nullptr) + __sanitizer_annotate_contiguous_container( + __first_storage, __last_storage, __old_last_contained, __new_last_contained); +#endif +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___LIBCXX_DEBUG_UTILS_SANITIZERS_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__exception/exception_ptr.h b/naiveproxy/src/third_party/libc++/src/include/__exception/exception_ptr.h index c9027de923..beadd9212a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__exception/exception_ptr.h +++ b/naiveproxy/src/third_party/libc++/src/include/__exception/exception_ptr.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___EXCEPTION_EXCEPTION_PTR_H #define _LIBCPP___EXCEPTION_EXCEPTION_PTR_H -#include <__availability> #include <__config> #include <__exception/operations.h> #include <__memory/addressof.h> @@ -38,11 +37,14 @@ struct __cxa_exception; _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception( void*, std::type_info*, - void( # if defined(_WIN32) - __thiscall + void(__thiscall*)(void*)) throw(); +# elif defined(__wasm__) + // In Wasm, a destructor returns its argument + void* (*)(void*)) throw(); +# else + void (*)(void*)) throw(); # endif - *)(void*)) throw(); } } // namespace __cxxabiv1 @@ -64,6 +66,9 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT; public: + // exception_ptr is basically a COW string. + using __trivially_relocatable = exception_ptr; + _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} @@ -92,9 +97,18 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { using _Ep2 = __decay_t<_Ep>; void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); +# ifdef __wasm__ + // In Wasm, a destructor returns its argument + (void)__cxxabiv1::__cxa_init_primary_exception( + __ex, const_cast(&typeid(_Ep)), [](void* __p) -> void* { +# else (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), [](void* __p) { - std::__destroy_at(static_cast<_Ep2*>(__p)); - }); +# endif + std::__destroy_at(static_cast<_Ep2*>(__p)); +# ifdef __wasm__ + return __p; +# endif + }); try { ::new (__ex) _Ep2(__e); diff --git a/naiveproxy/src/third_party/libc++/src/include/__exception/nested_exception.h b/naiveproxy/src/third_party/libc++/src/include/__exception/nested_exception.h index 1bf2df9392..feb489f87f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__exception/nested_exception.h +++ b/naiveproxy/src/third_party/libc++/src/include/__exception/nested_exception.h @@ -84,17 +84,15 @@ struct __can_dynamic_cast : _BoolConstant< is_polymorphic<_From>::value && (!is_base_of<_To, _From>::value || is_convertible::value)> {}; -template -inline _LIBCPP_HIDE_FROM_ABI void -rethrow_if_nested(const _Ep& __e, __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0) { +template ::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep& __e) { const nested_exception* __nep = dynamic_cast(std::addressof(__e)); if (__nep) __nep->rethrow_nested(); } -template -inline _LIBCPP_HIDE_FROM_ABI void -rethrow_if_nested(const _Ep&, __enable_if_t::value>* = 0) {} +template ::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep&) {} } // namespace std diff --git a/naiveproxy/src/third_party/libc++/src/include/__expected/bad_expected_access.h b/naiveproxy/src/third_party/libc++/src/include/__expected/bad_expected_access.h index 9d490307b6..1b734389e8 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__expected/bad_expected_access.h +++ b/naiveproxy/src/third_party/libc++/src/include/__expected/bad_expected_access.h @@ -28,9 +28,11 @@ template class bad_expected_access; _LIBCPP_DIAGNOSTIC_PUSH +# if !_LIBCPP_AVAILABILITY_HAS_BAD_EXPECTED_ACCESS_KEY_FUNCTION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables") +# endif template <> -class bad_expected_access : public exception { +class _LIBCPP_EXPORTED_FROM_ABI bad_expected_access : public exception { protected: _LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default; _LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) noexcept = default; @@ -40,11 +42,11 @@ protected: _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default; public: - // The way this has been designed (by using a class template below) means that we'll already - // have a profusion of these vtables in TUs, and the dynamic linker will already have a bunch - // of work to do. So it is not worth hiding the specialization in the dylib, given that - // it adds deployment target restrictions. +# if _LIBCPP_AVAILABILITY_HAS_BAD_EXPECTED_ACCESS_KEY_FUNCTION + const char* what() const noexcept override; +# else _LIBCPP_HIDE_FROM_ABI_VIRTUAL const char* what() const noexcept override { return "bad access to std::expected"; } +# endif }; _LIBCPP_DIAGNOSTIC_POP diff --git a/naiveproxy/src/third_party/libc++/src/include/__expected/expected.h b/naiveproxy/src/third_party/libc++/src/include/__expected/expected.h index d7adaac756..f618b20603 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__expected/expected.h +++ b/naiveproxy/src/third_party/libc++/src/include/__expected/expected.h @@ -31,6 +31,7 @@ #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_constructible.h> #include <__type_traits/is_trivially_destructible.h> +#include <__type_traits/is_trivially_relocatable.h> #include <__type_traits/is_void.h> #include <__type_traits/lazy.h> #include <__type_traits/negation.h> @@ -463,6 +464,11 @@ public: using error_type = _Err; using unexpected_type = unexpected<_Err>; + using __trivially_relocatable = + __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value && __libcpp_is_trivially_relocatable<_Err>::value, + expected, + void>; + template using rebind = expected<_Up, error_type>; @@ -501,7 +507,9 @@ private: _And< is_constructible<_Tp, _UfQual>, is_constructible<_Err, _OtherErrQual>, _If<_Not, bool>>::value, - _And< _Not&>>, + _And< + _Not<_And, is_same<_Err, _OtherErr>>>, // use the copy constructor instead, see #92676 + _Not&>>, _Not>>, _Not&>>, _Not>>, diff --git a/naiveproxy/src/third_party/libc++/src/include/__filesystem/directory_entry.h b/naiveproxy/src/third_party/libc++/src/include/__filesystem/directory_entry.h index 016ad94a85..96d88dcd90 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/directory_entry.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/directory_entry.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H #define _LIBCPP___FILESYSTEM_DIRECTORY_ENTRY_H -#include <__availability> #include <__chrono/time_point.h> #include <__compare/ordering.h> #include <__config> diff --git a/naiveproxy/src/third_party/libc++/src/include/__filesystem/directory_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__filesystem/directory_iterator.h index a5aa5ff543..e0246d8001 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/directory_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/directory_iterator.h @@ -11,7 +11,6 @@ #define _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H #include <__assert> -#include <__availability> #include <__config> #include <__filesystem/directory_entry.h> #include <__filesystem/directory_options.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__filesystem/filesystem_error.h b/naiveproxy/src/third_party/libc++/src/include/__filesystem/filesystem_error.h index bfdcc5eaee..80a11e3b19 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/filesystem_error.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/filesystem_error.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_FILESYSTEM_ERROR_H #define _LIBCPP___FILESYSTEM_FILESYSTEM_ERROR_H -#include <__availability> #include <__config> #include <__filesystem/path.h> #include <__memory/shared_ptr.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__filesystem/operations.h b/naiveproxy/src/third_party/libc++/src/include/__filesystem/operations.h index 9bb83576f5..f588189ed1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/operations.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/operations.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_OPERATIONS_H #define _LIBCPP___FILESYSTEM_OPERATIONS_H -#include <__availability> #include <__chrono/time_point.h> #include <__config> #include <__filesystem/copy_options.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__filesystem/path.h b/naiveproxy/src/third_party/libc++/src/include/__filesystem/path.h index 9ffc90ada5..ff468d5177 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/path.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/path.h @@ -12,7 +12,6 @@ #include <__algorithm/replace.h> #include <__algorithm/replace_copy.h> -#include <__availability> #include <__config> #include <__functional/unary_function.h> #include <__fwd/functional.h> @@ -812,7 +811,7 @@ public: _LIBCPP_HIDE_FROM_ABI path extension() const { return string_type(__extension()); } // query - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); } + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __pn_.empty(); } _LIBCPP_HIDE_FROM_ABI bool has_root_name() const { return !__root_name().empty(); } _LIBCPP_HIDE_FROM_ABI bool has_root_directory() const { return !__root_directory().empty(); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__filesystem/path_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__filesystem/path_iterator.h index d2d65cd122..f4d486d86c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/path_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/path_iterator.h @@ -11,7 +11,6 @@ #define _LIBCPP___FILESYSTEM_PATH_ITERATOR_H #include <__assert> -#include <__availability> #include <__config> #include <__filesystem/path.h> #include <__iterator/iterator_traits.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__filesystem/recursive_directory_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__filesystem/recursive_directory_iterator.h index a8af4f73b1..caa1396eb3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/recursive_directory_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/recursive_directory_iterator.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H #define _LIBCPP___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H -#include <__availability> #include <__config> #include <__filesystem/directory_entry.h> #include <__filesystem/directory_options.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__filesystem/u8path.h b/naiveproxy/src/third_party/libc++/src/include/__filesystem/u8path.h index bde8780548..dae5823128 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__filesystem/u8path.h +++ b/naiveproxy/src/third_party/libc++/src/include/__filesystem/u8path.h @@ -11,7 +11,6 @@ #define _LIBCPP___FILESYSTEM_U8PATH_H #include <__algorithm/unwrap_iter.h> -#include <__availability> #include <__config> #include <__filesystem/path.h> #include diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/escaped_output_table.h b/naiveproxy/src/third_party/libc++/src/include/__format/escaped_output_table.h index b194f9431c..f7be2dc61f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/escaped_output_table.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/escaped_output_table.h @@ -80,10 +80,9 @@ namespace __escaped_output_table { /// The entries of the characters to escape in format's debug string. /// /// Contains the entries for [format.string.escaped]/2.2.1.2.1 -/// CE is a Unicode encoding and C corresponds to either a UCS scalar value -/// whose Unicode property General_Category has a value in the groups -/// Separator (Z) or Other (C) or to a UCS scalar value which has the Unicode -/// property Grapheme_Extend=Yes, as described by table 12 of UAX #44 +/// CE is a Unicode encoding and C corresponds to a UCS scalar value whose +/// Unicode property General_Category has a value in the groups Separator (Z) +/// or Other (C), as described by table 12 of UAX #44 /// /// Separator (Z) consists of General_Category /// - Space_Separator, @@ -98,7 +97,6 @@ namespace __escaped_output_table { /// - Unassigned. /// /// The data is generated from -/// - https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// - https://www.unicode.org/Public/UCD/latest/ucd/extracted/DerivedGeneralCategory.txt /// /// The table is similar to the table @@ -107,927 +105,751 @@ namespace __escaped_output_table { /// table lacks a property, thus having more bits available for the size. /// /// The data has 2 values: -/// - bits [0, 10] The size of the range, allowing 2048 elements. -/// - bits [11, 31] The lower bound code point of the range. The upper bound of -/// the range is lower bound + size. -_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[894] = { - 0x00000020, - 0x0003f821, - 0x00056800, - 0x0018006f, - 0x001bc001, - 0x001c0003, - 0x001c5800, - 0x001c6800, - 0x001d1000, - 0x00241806, - 0x00298000, - 0x002ab801, - 0x002c5801, - 0x002c802d, - 0x002df800, - 0x002e0801, - 0x002e2001, - 0x002e3808, - 0x002f5803, - 0x002fa810, - 0x0030800a, - 0x0030e000, - 0x00325814, - 0x00338000, - 0x0036b007, - 0x0036f805, - 0x00373801, - 0x00375003, - 0x00387001, - 0x00388800, - 0x0039801c, - 0x003d300a, - 0x003d900d, - 0x003f5808, - 0x003fd802, - 0x0040b003, - 0x0040d808, - 0x00412802, - 0x00414806, - 0x0041f800, - 0x0042c804, - 0x0042f800, - 0x00435804, - 0x00447810, - 0x00465038, - 0x0049d000, - 0x0049e000, - 0x004a0807, - 0x004a6800, - 0x004a8806, - 0x004b1001, - 0x004c0800, - 0x004c2000, - 0x004c6801, - 0x004c8801, - 0x004d4800, - 0x004d8800, - 0x004d9802, - 0x004dd002, - 0x004df000, - 0x004e0805, - 0x004e4801, - 0x004e6800, - 0x004e780c, - 0x004ef000, - 0x004f1003, - 0x004ff004, - 0x00502000, - 0x00505803, - 0x00508801, - 0x00514800, - 0x00518800, - 0x0051a000, - 0x0051b800, - 0x0051d003, - 0x00520817, - 0x0052e800, - 0x0052f806, - 0x00538001, - 0x0053a800, - 0x0053b80b, - 0x00542000, - 0x00547000, - 0x00549000, - 0x00554800, - 0x00558800, - 0x0055a000, - 0x0055d002, - 0x00560807, - 0x00565000, - 0x00566802, - 0x0056880e, - 0x00571003, - 0x00579006, - 0x0057d007, - 0x00582000, - 0x00586801, - 0x00588801, - 0x00594800, - 0x00598800, - 0x0059a000, - 0x0059d002, - 0x0059f001, - 0x005a0805, - 0x005a4801, - 0x005a680e, - 0x005af000, - 0x005b1003, - 0x005bc00a, - 0x005c2000, - 0x005c5802, - 0x005c8800, - 0x005cb002, - 0x005cd800, - 0x005ce800, - 0x005d0002, - 0x005d2802, - 0x005d5802, - 0x005dd004, - 0x005e0000, - 0x005e1802, - 0x005e4800, - 0x005e6802, - 0x005e8814, - 0x005fd805, - 0x00602000, - 0x00606800, - 0x00608800, - 0x00614800, - 0x0061d002, - 0x0061f002, - 0x00622812, - 0x0062d801, - 0x0062f001, - 0x00631003, - 0x00638006, - 0x00640800, - 0x00646800, - 0x00648800, - 0x00654800, - 0x0065a000, - 0x0065d002, - 0x0065f800, - 0x00661000, - 0x00662801, - 0x00664800, - 0x00666010, - 0x0066f800, - 0x00671003, - 0x00678000, - 0x0067a00d, - 0x00686800, - 0x00688800, - 0x0069d801, - 0x0069f000, - 0x006a0804, - 0x006a4800, - 0x006a6800, - 0x006a8003, - 0x006ab800, - 0x006b1003, - 0x006c0001, - 0x006c2000, - 0x006cb802, - 0x006d9000, - 0x006de000, - 0x006df001, - 0x006e3808, - 0x006e9005, - 0x006ef806, - 0x006f8001, - 0x006fa80b, - 0x00718800, - 0x0071a00a, - 0x00723807, - 0x0072e024, - 0x00741800, - 0x00742800, - 0x00745800, - 0x00752000, - 0x00753000, - 0x00758800, - 0x0075a008, - 0x0075f001, - 0x00762800, - 0x00763808, - 0x0076d001, - 0x0077001f, - 0x0078c001, - 0x0079a800, - 0x0079b800, - 0x0079c800, - 0x007a4000, - 0x007b6811, - 0x007c0004, - 0x007c3001, - 0x007c6830, - 0x007e3000, - 0x007e6800, - 0x007ed824, - 0x00816803, - 0x00819005, - 0x0081c801, - 0x0081e801, - 0x0082c001, - 0x0082f002, - 0x00838803, - 0x00841000, - 0x00842801, - 0x00846800, - 0x0084e800, - 0x00863000, - 0x00864004, - 0x00867001, - 0x00924800, - 0x00927001, - 0x0092b800, - 0x0092c800, - 0x0092f001, - 0x00944800, - 0x00947001, - 0x00958800, - 0x0095b001, - 0x0095f800, - 0x00960800, - 0x00963001, - 0x0096b800, - 0x00988800, - 0x0098b001, - 0x009ad804, - 0x009be802, - 0x009cd005, - 0x009fb001, - 0x009ff001, - 0x00b40000, - 0x00b4e802, - 0x00b7c806, - 0x00b89002, - 0x00b8b008, - 0x00b99001, - 0x00b9b808, - 0x00ba900d, - 0x00bb6800, - 0x00bb880e, - 0x00bda001, - 0x00bdb806, - 0x00be3000, - 0x00be480a, - 0x00bee802, - 0x00bf5005, - 0x00bfd005, - 0x00c05804, - 0x00c0d005, - 0x00c3c806, - 0x00c42801, - 0x00c54800, - 0x00c55804, - 0x00c7b009, - 0x00c8f803, - 0x00c93801, - 0x00c96003, - 0x00c99000, - 0x00c9c806, - 0x00ca0802, - 0x00cb7001, - 0x00cba80a, - 0x00cd6003, - 0x00ce5005, - 0x00ced802, - 0x00d0b801, - 0x00d0d802, - 0x00d2b000, - 0x00d2c008, - 0x00d31000, - 0x00d32807, - 0x00d3980c, - 0x00d45005, - 0x00d4d005, - 0x00d57055, - 0x00d9a006, - 0x00d9e000, - 0x00da1000, - 0x00da6802, - 0x00db5808, - 0x00dbf802, - 0x00dd1003, - 0x00dd4001, - 0x00dd5802, - 0x00df3000, - 0x00df4001, - 0x00df6800, - 0x00df7802, - 0x00dfa007, - 0x00e16007, - 0x00e1b004, - 0x00e25002, - 0x00e44806, - 0x00e5d801, - 0x00e6400a, - 0x00e6a00c, - 0x00e71006, - 0x00e76800, - 0x00e7a000, - 0x00e7c001, - 0x00e7d804, - 0x00ee003f, - 0x00f8b001, - 0x00f8f001, - 0x00fa3001, - 0x00fa7001, - 0x00fac000, - 0x00fad000, - 0x00fae000, - 0x00faf000, - 0x00fbf001, - 0x00fda800, - 0x00fe2800, - 0x00fea001, - 0x00fee000, - 0x00ff8001, - 0x00ffa800, - 0x00fff810, - 0x01014007, - 0x0102f810, - 0x01039001, - 0x01047800, - 0x0104e802, - 0x0106083e, - 0x010c6003, - 0x01213818, - 0x01225814, - 0x015ba001, - 0x015cb000, - 0x01677802, - 0x0167a004, - 0x01693000, - 0x01694004, - 0x01697001, - 0x016b4006, - 0x016b880e, - 0x016cb808, - 0x016d3800, - 0x016d7800, - 0x016db800, - 0x016df800, - 0x016e3800, - 0x016e7800, - 0x016eb800, - 0x016ef820, - 0x0172f021, - 0x0174d000, - 0x0177a00b, - 0x017eb019, - 0x01800000, - 0x01815005, - 0x01820000, - 0x0184b803, - 0x01880004, - 0x01898000, - 0x018c7800, - 0x018f200a, - 0x0190f800, - 0x05246802, - 0x05263808, - 0x05316013, - 0x05337803, - 0x0533a009, - 0x0534f001, - 0x05378001, - 0x0537c007, - 0x053e5804, - 0x053e9000, - 0x053ea000, - 0x053ed017, - 0x05401000, - 0x05403000, - 0x05405800, - 0x05412801, - 0x05416003, - 0x0541d005, - 0x0543c007, - 0x05462009, - 0x0546d017, - 0x0547f800, - 0x05493007, - 0x054a380a, - 0x054aa00a, - 0x054be805, - 0x054d9800, - 0x054db003, - 0x054de001, - 0x054e7000, - 0x054ed003, - 0x054f2800, - 0x054ff800, - 0x05514805, - 0x05518801, - 0x0551a80a, - 0x05521800, - 0x05526000, - 0x05527001, - 0x0552d001, - 0x0553e000, - 0x05558000, - 0x05559002, - 0x0555b801, - 0x0555f001, - 0x05560800, - 0x05561817, - 0x05576001, - 0x0557b00a, - 0x05583801, - 0x05587801, - 0x0558b808, - 0x05593800, - 0x05597800, - 0x055b6003, - 0x055f2800, - 0x055f4000, - 0x055f6802, - 0x055fd005, - 0x06bd200b, - 0x06be3803, - 0x06bfe7ff, - 0x06ffe7ff, - 0x073fe7ff, - 0x077fe7ff, - 0x07bfe103, - 0x07d37001, - 0x07d6d025, - 0x07d8380b, - 0x07d8c004, - 0x07d8f000, - 0x07d9b800, - 0x07d9e800, - 0x07d9f800, - 0x07da1000, - 0x07da2800, - 0x07de180f, - 0x07ec8001, - 0x07ee4006, - 0x07ee801f, - 0x07f0000f, - 0x07f0d015, - 0x07f29800, - 0x07f33800, - 0x07f36003, - 0x07f3a800, - 0x07f7e803, - 0x07fcf001, - 0x07fdf802, - 0x07fe4001, - 0x07fe8001, - 0x07fec001, - 0x07fee802, - 0x07ff3800, - 0x07ff780c, - 0x07fff001, - 0x08006000, - 0x08013800, - 0x0801d800, - 0x0801f000, - 0x08027001, - 0x0802f021, - 0x0807d804, - 0x08081803, - 0x0809a002, - 0x080c7800, - 0x080ce802, - 0x080d082e, - 0x080fe882, - 0x0814e802, - 0x0816880f, - 0x0817e003, - 0x08192008, - 0x081a5804, - 0x081bb009, - 0x081cf000, - 0x081e2003, - 0x081eb029, - 0x0824f001, - 0x08255005, - 0x0826a003, - 0x0827e003, - 0x08294007, - 0x082b200a, - 0x082bd800, - 0x082c5800, - 0x082c9800, - 0x082cb000, - 0x082d1000, - 0x082d9000, - 0x082dd000, - 0x082de842, - 0x0839b808, - 0x083ab009, - 0x083b4017, - 0x083c3000, - 0x083d8800, - 0x083dd844, - 0x08403001, - 0x08404800, - 0x0841b000, - 0x0841c802, - 0x0841e801, - 0x0842b000, - 0x0844f807, - 0x0845802f, - 0x08479800, - 0x0847b004, - 0x0848e002, - 0x0849d004, - 0x084a003f, - 0x084dc003, - 0x084e8001, - 0x0850080e, - 0x0850a000, - 0x0850c000, - 0x0851b009, - 0x08524806, - 0x0852c806, - 0x0855001f, - 0x08572805, - 0x0857b808, - 0x0859b002, - 0x085ab001, - 0x085b9804, - 0x085c9006, - 0x085ce80b, - 0x085d804f, - 0x08624836, - 0x0865980c, - 0x08679806, - 0x0869200b, - 0x0869d125, - 0x0873f800, - 0x08755002, - 0x08757001, - 0x0875904d, - 0x08794007, - 0x087a300a, - 0x087ad015, - 0x087c1003, - 0x087c5025, - 0x087e6013, - 0x087fb808, - 0x08800800, - 0x0881c00e, - 0x08827003, - 0x08838000, - 0x08839801, - 0x0883b00b, - 0x08859803, - 0x0885c801, - 0x0885e800, - 0x0886100d, - 0x08874806, - 0x0887d008, - 0x08893804, - 0x08896808, - 0x088a4007, - 0x088b9800, - 0x088bb80a, - 0x088db008, - 0x088e4803, - 0x088e7800, - 0x088f0000, - 0x088fa80a, - 0x08909000, - 0x08917802, - 0x0891a000, - 0x0891b001, - 0x0891f000, - 0x0892083e, - 0x08943800, - 0x08944800, - 0x08947000, - 0x0894f000, - 0x08955005, - 0x0896f800, - 0x0897180c, - 0x0897d007, - 0x08982000, - 0x08986801, - 0x08988801, - 0x08994800, - 0x08998800, - 0x0899a000, - 0x0899d002, - 0x0899f000, - 0x089a0000, - 0x089a2801, - 0x089a4801, - 0x089a7001, - 0x089a880b, - 0x089b209b, - 0x08a1c007, - 0x08a21002, - 0x08a23000, - 0x08a2e000, - 0x08a2f000, - 0x08a3101d, - 0x08a58000, - 0x08a59805, - 0x08a5d000, - 0x08a5e800, - 0x08a5f801, - 0x08a61001, - 0x08a64007, - 0x08a6d0a5, - 0x08ad7800, - 0x08ad9005, - 0x08ade001, - 0x08adf801, - 0x08aee023, - 0x08b19807, - 0x08b1e800, - 0x08b1f801, - 0x08b2280a, - 0x08b2d005, - 0x08b36812, - 0x08b55800, - 0x08b56800, - 0x08b58005, - 0x08b5b800, - 0x08b5d005, - 0x08b65035, - 0x08b8d804, - 0x08b91003, - 0x08b93808, - 0x08ba38b8, - 0x08c17808, - 0x08c1c801, - 0x08c1e063, - 0x08c7980b, - 0x08c83801, - 0x08c85001, - 0x08c8a000, - 0x08c8b800, - 0x08c98000, - 0x08c9b000, - 0x08c9c803, - 0x08c9f000, - 0x08ca1800, - 0x08ca3808, - 0x08cad045, - 0x08cd4001, - 0x08cea007, - 0x08cf0000, - 0x08cf281a, - 0x08d00809, - 0x08d19805, - 0x08d1d803, - 0x08d23808, - 0x08d28805, - 0x08d2c802, - 0x08d4500c, - 0x08d4c001, - 0x08d5180c, - 0x08d7c806, - 0x08d850f5, - 0x08e04800, - 0x08e1800d, - 0x08e1f800, - 0x08e23009, - 0x08e36802, - 0x08e48018, - 0x08e55006, - 0x08e59001, - 0x08e5a84a, - 0x08e83800, - 0x08e85000, - 0x08e98814, - 0x08ea3808, - 0x08ead005, - 0x08eb3000, - 0x08eb4800, - 0x08ec7803, - 0x08eca800, - 0x08ecb800, - 0x08ecc806, - 0x08ed5135, - 0x08f79801, - 0x08f7c808, - 0x08f88800, - 0x08f9b007, - 0x08fa0000, - 0x08fa1000, - 0x08fad055, - 0x08fd880e, - 0x08ff900c, - 0x091cd065, - 0x09237800, - 0x0923a80a, - 0x092a27ff, - 0x096a224b, - 0x097f980c, - 0x09a18010, - 0x09a23fff, - 0x09e23fb8, - 0x0a323fff, - 0x0a723fff, - 0x0ab23fff, - 0x0af23fff, - 0x0b3239b8, - 0x0b51c806, - 0x0b52f800, - 0x0b535003, - 0x0b55f800, - 0x0b565005, - 0x0b577006, - 0x0b57b009, - 0x0b598006, - 0x0b5a3009, - 0x0b5ad000, - 0x0b5b1000, - 0x0b5bc004, - 0x0b5c82af, - 0x0b74d864, - 0x0b7a5804, - 0x0b7c400a, - 0x0b7d003f, - 0x0b7f200b, - 0x0b7f900d, - 0x0c3fc007, - 0x0c66b029, - 0x0c684fff, - 0x0ca84fff, - 0x0ce84fff, - 0x0d284fff, - 0x0d684ae6, - 0x0d7fa000, - 0x0d7fe000, - 0x0d7ff800, - 0x0d89180e, - 0x0d89981c, - 0x0d8a9801, - 0x0d8ab00d, - 0x0d8b4007, - 0x0d97e7ff, - 0x0dd7e103, - 0x0de35804, - 0x0de3e802, - 0x0de44806, - 0x0de4d001, - 0x0de4e801, - 0x0de507ff, - 0x0e2507ff, - 0x0e6502af, - 0x0e7e203b, - 0x0e87b009, - 0x0e893801, - 0x0e8b2800, - 0x0e8b3802, - 0x0e8b7014, - 0x0e8c2806, - 0x0e8d5003, - 0x0e8f5814, - 0x0e921002, - 0x0e923079, - 0x0e96a00b, - 0x0e97a00b, - 0x0e9ab808, - 0x0e9bc886, - 0x0ea2a800, - 0x0ea4e800, - 0x0ea50001, - 0x0ea51801, - 0x0ea53801, - 0x0ea56800, - 0x0ea5d000, - 0x0ea5e000, - 0x0ea62000, - 0x0ea83000, - 0x0ea85801, - 0x0ea8a800, - 0x0ea8e800, - 0x0ea9d000, - 0x0ea9f800, - 0x0eaa2800, - 0x0eaa3802, - 0x0eaa8800, - 0x0eb53001, - 0x0ebe6001, - 0x0ed00036, - 0x0ed1d831, - 0x0ed3a800, - 0x0ed42000, - 0x0ed46473, - 0x0ef8f805, - 0x0ef95904, - 0x0f037091, - 0x0f096809, - 0x0f09f001, - 0x0f0a5003, - 0x0f0a813f, - 0x0f157011, - 0x0f176003, - 0x0f17d004, - 0x0f1801cf, - 0x0f276003, - 0x0f27d2e5, - 0x0f3f3800, - 0x0f3f6000, - 0x0f3f7800, - 0x0f3ff800, - 0x0f462801, - 0x0f46802f, - 0x0f4a2006, - 0x0f4a6003, - 0x0f4ad003, - 0x0f4b0310, - 0x0f65a84b, - 0x0f69f0c1, - 0x0f702000, - 0x0f710000, - 0x0f711800, - 0x0f712801, - 0x0f714000, - 0x0f719800, - 0x0f71c000, - 0x0f71d000, - 0x0f71e005, - 0x0f721803, - 0x0f724000, - 0x0f725000, - 0x0f726000, - 0x0f728000, - 0x0f729800, - 0x0f72a801, - 0x0f72c000, - 0x0f72d000, - 0x0f72e000, - 0x0f72f000, - 0x0f730000, - 0x0f731800, - 0x0f732801, - 0x0f735800, - 0x0f739800, - 0x0f73c000, - 0x0f73e800, - 0x0f73f800, - 0x0f745000, - 0x0f74e004, - 0x0f752000, - 0x0f755000, - 0x0f75e033, - 0x0f77910d, - 0x0f816003, - 0x0f84a00b, - 0x0f857801, - 0x0f860000, - 0x0f868000, - 0x0f87b009, - 0x0f8d7037, - 0x0f90180c, - 0x0f91e003, - 0x0f924806, - 0x0f92900d, - 0x0f933099, - 0x0fb6c003, - 0x0fb76802, - 0x0fb7e802, - 0x0fbbb803, - 0x0fbed005, - 0x0fbf6003, - 0x0fbf880e, - 0x0fc06003, - 0x0fc24007, - 0x0fc2d005, - 0x0fc44007, - 0x0fc57001, - 0x0fc5904d, - 0x0fd2a00b, - 0x0fd37001, - 0x0fd3e802, - 0x0fd44806, - 0x0fd5f000, - 0x0fd63007, - 0x0fd6e003, - 0x0fd74806, - 0x0fd7c806, - 0x0fdc9800, - 0x0fde5824, - 0x0fdfd405, - 0x1537001f, - 0x15b9d005, - 0x15c0f001, - 0x1675100d, - 0x175f080e, - 0x1772f7ff, - 0x17b2f1a1, - 0x17d0f5e1, - 0x189a5804}; - -/// At the end of the valid Unicode code points space a lot of code points are -/// either reserved or a noncharacter. Adding all these entries to the -/// lookup table would add 446 entries to the table (in Unicode 14). -/// Instead the only the start of the region is stored, every code point in -/// this region needs to be escaped. -inline constexpr uint32_t __unallocated_region_lower_bound = 0x000323b0; +/// - bits [0, 13] The size of the range, allowing 16384 elements. +/// - bits [14, 31] The lower bound code point of the range. The upper bound of +/// the range is lower bound + size. Note the code expects code units the fit +/// into 18 bits, instead of the 21 bits needed for the full Unicode range. +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { + 0x00000020 /* 00000000 - 00000020 [ 33] */, + 0x001fc021 /* 0000007f - 000000a0 [ 34] */, + 0x002b4000 /* 000000ad - 000000ad [ 1] */, + 0x00de0001 /* 00000378 - 00000379 [ 2] */, + 0x00e00003 /* 00000380 - 00000383 [ 4] */, + 0x00e2c000 /* 0000038b - 0000038b [ 1] */, + 0x00e34000 /* 0000038d - 0000038d [ 1] */, + 0x00e88000 /* 000003a2 - 000003a2 [ 1] */, + 0x014c0000 /* 00000530 - 00000530 [ 1] */, + 0x0155c001 /* 00000557 - 00000558 [ 2] */, + 0x0162c001 /* 0000058b - 0000058c [ 2] */, + 0x01640000 /* 00000590 - 00000590 [ 1] */, + 0x01720007 /* 000005c8 - 000005cf [ 8] */, + 0x017ac003 /* 000005eb - 000005ee [ 4] */, + 0x017d4010 /* 000005f5 - 00000605 [ 17] */, + 0x01870000 /* 0000061c - 0000061c [ 1] */, + 0x01b74000 /* 000006dd - 000006dd [ 1] */, + 0x01c38001 /* 0000070e - 0000070f [ 2] */, + 0x01d2c001 /* 0000074b - 0000074c [ 2] */, + 0x01ec800d /* 000007b2 - 000007bf [ 14] */, + 0x01fec001 /* 000007fb - 000007fc [ 2] */, + 0x020b8001 /* 0000082e - 0000082f [ 2] */, + 0x020fc000 /* 0000083f - 0000083f [ 1] */, + 0x02170001 /* 0000085c - 0000085d [ 2] */, + 0x0217c000 /* 0000085f - 0000085f [ 1] */, + 0x021ac004 /* 0000086b - 0000086f [ 5] */, + 0x0223c008 /* 0000088f - 00000897 [ 9] */, + 0x02388000 /* 000008e2 - 000008e2 [ 1] */, + 0x02610000 /* 00000984 - 00000984 [ 1] */, + 0x02634001 /* 0000098d - 0000098e [ 2] */, + 0x02644001 /* 00000991 - 00000992 [ 2] */, + 0x026a4000 /* 000009a9 - 000009a9 [ 1] */, + 0x026c4000 /* 000009b1 - 000009b1 [ 1] */, + 0x026cc002 /* 000009b3 - 000009b5 [ 3] */, + 0x026e8001 /* 000009ba - 000009bb [ 2] */, + 0x02714001 /* 000009c5 - 000009c6 [ 2] */, + 0x02724001 /* 000009c9 - 000009ca [ 2] */, + 0x0273c007 /* 000009cf - 000009d6 [ 8] */, + 0x02760003 /* 000009d8 - 000009db [ 4] */, + 0x02778000 /* 000009de - 000009de [ 1] */, + 0x02790001 /* 000009e4 - 000009e5 [ 2] */, + 0x027fc001 /* 000009ff - 00000a00 [ 2] */, + 0x02810000 /* 00000a04 - 00000a04 [ 1] */, + 0x0282c003 /* 00000a0b - 00000a0e [ 4] */, + 0x02844001 /* 00000a11 - 00000a12 [ 2] */, + 0x028a4000 /* 00000a29 - 00000a29 [ 1] */, + 0x028c4000 /* 00000a31 - 00000a31 [ 1] */, + 0x028d0000 /* 00000a34 - 00000a34 [ 1] */, + 0x028dc000 /* 00000a37 - 00000a37 [ 1] */, + 0x028e8001 /* 00000a3a - 00000a3b [ 2] */, + 0x028f4000 /* 00000a3d - 00000a3d [ 1] */, + 0x0290c003 /* 00000a43 - 00000a46 [ 4] */, + 0x02924001 /* 00000a49 - 00000a4a [ 2] */, + 0x02938002 /* 00000a4e - 00000a50 [ 3] */, + 0x02948006 /* 00000a52 - 00000a58 [ 7] */, + 0x02974000 /* 00000a5d - 00000a5d [ 1] */, + 0x0297c006 /* 00000a5f - 00000a65 [ 7] */, + 0x029dc009 /* 00000a77 - 00000a80 [ 10] */, + 0x02a10000 /* 00000a84 - 00000a84 [ 1] */, + 0x02a38000 /* 00000a8e - 00000a8e [ 1] */, + 0x02a48000 /* 00000a92 - 00000a92 [ 1] */, + 0x02aa4000 /* 00000aa9 - 00000aa9 [ 1] */, + 0x02ac4000 /* 00000ab1 - 00000ab1 [ 1] */, + 0x02ad0000 /* 00000ab4 - 00000ab4 [ 1] */, + 0x02ae8001 /* 00000aba - 00000abb [ 2] */, + 0x02b18000 /* 00000ac6 - 00000ac6 [ 1] */, + 0x02b28000 /* 00000aca - 00000aca [ 1] */, + 0x02b38001 /* 00000ace - 00000acf [ 2] */, + 0x02b4400e /* 00000ad1 - 00000adf [ 15] */, + 0x02b90001 /* 00000ae4 - 00000ae5 [ 2] */, + 0x02bc8006 /* 00000af2 - 00000af8 [ 7] */, + 0x02c00000 /* 00000b00 - 00000b00 [ 1] */, + 0x02c10000 /* 00000b04 - 00000b04 [ 1] */, + 0x02c34001 /* 00000b0d - 00000b0e [ 2] */, + 0x02c44001 /* 00000b11 - 00000b12 [ 2] */, + 0x02ca4000 /* 00000b29 - 00000b29 [ 1] */, + 0x02cc4000 /* 00000b31 - 00000b31 [ 1] */, + 0x02cd0000 /* 00000b34 - 00000b34 [ 1] */, + 0x02ce8001 /* 00000b3a - 00000b3b [ 2] */, + 0x02d14001 /* 00000b45 - 00000b46 [ 2] */, + 0x02d24001 /* 00000b49 - 00000b4a [ 2] */, + 0x02d38006 /* 00000b4e - 00000b54 [ 7] */, + 0x02d60003 /* 00000b58 - 00000b5b [ 4] */, + 0x02d78000 /* 00000b5e - 00000b5e [ 1] */, + 0x02d90001 /* 00000b64 - 00000b65 [ 2] */, + 0x02de0009 /* 00000b78 - 00000b81 [ 10] */, + 0x02e10000 /* 00000b84 - 00000b84 [ 1] */, + 0x02e2c002 /* 00000b8b - 00000b8d [ 3] */, + 0x02e44000 /* 00000b91 - 00000b91 [ 1] */, + 0x02e58002 /* 00000b96 - 00000b98 [ 3] */, + 0x02e6c000 /* 00000b9b - 00000b9b [ 1] */, + 0x02e74000 /* 00000b9d - 00000b9d [ 1] */, + 0x02e80002 /* 00000ba0 - 00000ba2 [ 3] */, + 0x02e94002 /* 00000ba5 - 00000ba7 [ 3] */, + 0x02eac002 /* 00000bab - 00000bad [ 3] */, + 0x02ee8003 /* 00000bba - 00000bbd [ 4] */, + 0x02f0c002 /* 00000bc3 - 00000bc5 [ 3] */, + 0x02f24000 /* 00000bc9 - 00000bc9 [ 1] */, + 0x02f38001 /* 00000bce - 00000bcf [ 2] */, + 0x02f44005 /* 00000bd1 - 00000bd6 [ 6] */, + 0x02f6000d /* 00000bd8 - 00000be5 [ 14] */, + 0x02fec004 /* 00000bfb - 00000bff [ 5] */, + 0x03034000 /* 00000c0d - 00000c0d [ 1] */, + 0x03044000 /* 00000c11 - 00000c11 [ 1] */, + 0x030a4000 /* 00000c29 - 00000c29 [ 1] */, + 0x030e8001 /* 00000c3a - 00000c3b [ 2] */, + 0x03114000 /* 00000c45 - 00000c45 [ 1] */, + 0x03124000 /* 00000c49 - 00000c49 [ 1] */, + 0x03138006 /* 00000c4e - 00000c54 [ 7] */, + 0x0315c000 /* 00000c57 - 00000c57 [ 1] */, + 0x0316c001 /* 00000c5b - 00000c5c [ 2] */, + 0x03178001 /* 00000c5e - 00000c5f [ 2] */, + 0x03190001 /* 00000c64 - 00000c65 [ 2] */, + 0x031c0006 /* 00000c70 - 00000c76 [ 7] */, + 0x03234000 /* 00000c8d - 00000c8d [ 1] */, + 0x03244000 /* 00000c91 - 00000c91 [ 1] */, + 0x032a4000 /* 00000ca9 - 00000ca9 [ 1] */, + 0x032d0000 /* 00000cb4 - 00000cb4 [ 1] */, + 0x032e8001 /* 00000cba - 00000cbb [ 2] */, + 0x03314000 /* 00000cc5 - 00000cc5 [ 1] */, + 0x03324000 /* 00000cc9 - 00000cc9 [ 1] */, + 0x03338006 /* 00000cce - 00000cd4 [ 7] */, + 0x0335c005 /* 00000cd7 - 00000cdc [ 6] */, + 0x0337c000 /* 00000cdf - 00000cdf [ 1] */, + 0x03390001 /* 00000ce4 - 00000ce5 [ 2] */, + 0x033c0000 /* 00000cf0 - 00000cf0 [ 1] */, + 0x033d000b /* 00000cf4 - 00000cff [ 12] */, + 0x03434000 /* 00000d0d - 00000d0d [ 1] */, + 0x03444000 /* 00000d11 - 00000d11 [ 1] */, + 0x03514000 /* 00000d45 - 00000d45 [ 1] */, + 0x03524000 /* 00000d49 - 00000d49 [ 1] */, + 0x03540003 /* 00000d50 - 00000d53 [ 4] */, + 0x03590001 /* 00000d64 - 00000d65 [ 2] */, + 0x03600000 /* 00000d80 - 00000d80 [ 1] */, + 0x03610000 /* 00000d84 - 00000d84 [ 1] */, + 0x0365c002 /* 00000d97 - 00000d99 [ 3] */, + 0x036c8000 /* 00000db2 - 00000db2 [ 1] */, + 0x036f0000 /* 00000dbc - 00000dbc [ 1] */, + 0x036f8001 /* 00000dbe - 00000dbf [ 2] */, + 0x0371c002 /* 00000dc7 - 00000dc9 [ 3] */, + 0x0372c003 /* 00000dcb - 00000dce [ 4] */, + 0x03754000 /* 00000dd5 - 00000dd5 [ 1] */, + 0x0375c000 /* 00000dd7 - 00000dd7 [ 1] */, + 0x03780005 /* 00000de0 - 00000de5 [ 6] */, + 0x037c0001 /* 00000df0 - 00000df1 [ 2] */, + 0x037d400b /* 00000df5 - 00000e00 [ 12] */, + 0x038ec003 /* 00000e3b - 00000e3e [ 4] */, + 0x03970024 /* 00000e5c - 00000e80 [ 37] */, + 0x03a0c000 /* 00000e83 - 00000e83 [ 1] */, + 0x03a14000 /* 00000e85 - 00000e85 [ 1] */, + 0x03a2c000 /* 00000e8b - 00000e8b [ 1] */, + 0x03a90000 /* 00000ea4 - 00000ea4 [ 1] */, + 0x03a98000 /* 00000ea6 - 00000ea6 [ 1] */, + 0x03af8001 /* 00000ebe - 00000ebf [ 2] */, + 0x03b14000 /* 00000ec5 - 00000ec5 [ 1] */, + 0x03b1c000 /* 00000ec7 - 00000ec7 [ 1] */, + 0x03b3c000 /* 00000ecf - 00000ecf [ 1] */, + 0x03b68001 /* 00000eda - 00000edb [ 2] */, + 0x03b8001f /* 00000ee0 - 00000eff [ 32] */, + 0x03d20000 /* 00000f48 - 00000f48 [ 1] */, + 0x03db4003 /* 00000f6d - 00000f70 [ 4] */, + 0x03e60000 /* 00000f98 - 00000f98 [ 1] */, + 0x03ef4000 /* 00000fbd - 00000fbd [ 1] */, + 0x03f34000 /* 00000fcd - 00000fcd [ 1] */, + 0x03f6c024 /* 00000fdb - 00000fff [ 37] */, + 0x04318000 /* 000010c6 - 000010c6 [ 1] */, + 0x04320004 /* 000010c8 - 000010cc [ 5] */, + 0x04338001 /* 000010ce - 000010cf [ 2] */, + 0x04924000 /* 00001249 - 00001249 [ 1] */, + 0x04938001 /* 0000124e - 0000124f [ 2] */, + 0x0495c000 /* 00001257 - 00001257 [ 1] */, + 0x04964000 /* 00001259 - 00001259 [ 1] */, + 0x04978001 /* 0000125e - 0000125f [ 2] */, + 0x04a24000 /* 00001289 - 00001289 [ 1] */, + 0x04a38001 /* 0000128e - 0000128f [ 2] */, + 0x04ac4000 /* 000012b1 - 000012b1 [ 1] */, + 0x04ad8001 /* 000012b6 - 000012b7 [ 2] */, + 0x04afc000 /* 000012bf - 000012bf [ 1] */, + 0x04b04000 /* 000012c1 - 000012c1 [ 1] */, + 0x04b18001 /* 000012c6 - 000012c7 [ 2] */, + 0x04b5c000 /* 000012d7 - 000012d7 [ 1] */, + 0x04c44000 /* 00001311 - 00001311 [ 1] */, + 0x04c58001 /* 00001316 - 00001317 [ 2] */, + 0x04d6c001 /* 0000135b - 0000135c [ 2] */, + 0x04df4002 /* 0000137d - 0000137f [ 3] */, + 0x04e68005 /* 0000139a - 0000139f [ 6] */, + 0x04fd8001 /* 000013f6 - 000013f7 [ 2] */, + 0x04ff8001 /* 000013fe - 000013ff [ 2] */, + 0x05a00000 /* 00001680 - 00001680 [ 1] */, + 0x05a74002 /* 0000169d - 0000169f [ 3] */, + 0x05be4006 /* 000016f9 - 000016ff [ 7] */, + 0x05c58008 /* 00001716 - 0000171e [ 9] */, + 0x05cdc008 /* 00001737 - 0000173f [ 9] */, + 0x05d5000b /* 00001754 - 0000175f [ 12] */, + 0x05db4000 /* 0000176d - 0000176d [ 1] */, + 0x05dc4000 /* 00001771 - 00001771 [ 1] */, + 0x05dd000b /* 00001774 - 0000177f [ 12] */, + 0x05f78001 /* 000017de - 000017df [ 2] */, + 0x05fa8005 /* 000017ea - 000017ef [ 6] */, + 0x05fe8005 /* 000017fa - 000017ff [ 6] */, + 0x06038000 /* 0000180e - 0000180e [ 1] */, + 0x06068005 /* 0000181a - 0000181f [ 6] */, + 0x061e4006 /* 00001879 - 0000187f [ 7] */, + 0x062ac004 /* 000018ab - 000018af [ 5] */, + 0x063d8009 /* 000018f6 - 000018ff [ 10] */, + 0x0647c000 /* 0000191f - 0000191f [ 1] */, + 0x064b0003 /* 0000192c - 0000192f [ 4] */, + 0x064f0003 /* 0000193c - 0000193f [ 4] */, + 0x06504002 /* 00001941 - 00001943 [ 3] */, + 0x065b8001 /* 0000196e - 0000196f [ 2] */, + 0x065d400a /* 00001975 - 0000197f [ 11] */, + 0x066b0003 /* 000019ac - 000019af [ 4] */, + 0x06728005 /* 000019ca - 000019cf [ 6] */, + 0x0676c002 /* 000019db - 000019dd [ 3] */, + 0x06870001 /* 00001a1c - 00001a1d [ 2] */, + 0x0697c000 /* 00001a5f - 00001a5f [ 1] */, + 0x069f4001 /* 00001a7d - 00001a7e [ 2] */, + 0x06a28005 /* 00001a8a - 00001a8f [ 6] */, + 0x06a68005 /* 00001a9a - 00001a9f [ 6] */, + 0x06ab8001 /* 00001aae - 00001aaf [ 2] */, + 0x06b3c030 /* 00001acf - 00001aff [ 49] */, + 0x06d34002 /* 00001b4d - 00001b4f [ 3] */, + 0x06dfc000 /* 00001b7f - 00001b7f [ 1] */, + 0x06fd0007 /* 00001bf4 - 00001bfb [ 8] */, + 0x070e0002 /* 00001c38 - 00001c3a [ 3] */, + 0x07128002 /* 00001c4a - 00001c4c [ 3] */, + 0x07224006 /* 00001c89 - 00001c8f [ 7] */, + 0x072ec001 /* 00001cbb - 00001cbc [ 2] */, + 0x07320007 /* 00001cc8 - 00001ccf [ 8] */, + 0x073ec004 /* 00001cfb - 00001cff [ 5] */, + 0x07c58001 /* 00001f16 - 00001f17 [ 2] */, + 0x07c78001 /* 00001f1e - 00001f1f [ 2] */, + 0x07d18001 /* 00001f46 - 00001f47 [ 2] */, + 0x07d38001 /* 00001f4e - 00001f4f [ 2] */, + 0x07d60000 /* 00001f58 - 00001f58 [ 1] */, + 0x07d68000 /* 00001f5a - 00001f5a [ 1] */, + 0x07d70000 /* 00001f5c - 00001f5c [ 1] */, + 0x07d78000 /* 00001f5e - 00001f5e [ 1] */, + 0x07df8001 /* 00001f7e - 00001f7f [ 2] */, + 0x07ed4000 /* 00001fb5 - 00001fb5 [ 1] */, + 0x07f14000 /* 00001fc5 - 00001fc5 [ 1] */, + 0x07f50001 /* 00001fd4 - 00001fd5 [ 2] */, + 0x07f70000 /* 00001fdc - 00001fdc [ 1] */, + 0x07fc0001 /* 00001ff0 - 00001ff1 [ 2] */, + 0x07fd4000 /* 00001ff5 - 00001ff5 [ 1] */, + 0x07ffc010 /* 00001fff - 0000200f [ 17] */, + 0x080a0007 /* 00002028 - 0000202f [ 8] */, + 0x0817c010 /* 0000205f - 0000206f [ 17] */, + 0x081c8001 /* 00002072 - 00002073 [ 2] */, + 0x0823c000 /* 0000208f - 0000208f [ 1] */, + 0x08274002 /* 0000209d - 0000209f [ 3] */, + 0x0830400e /* 000020c1 - 000020cf [ 15] */, + 0x083c400e /* 000020f1 - 000020ff [ 15] */, + 0x08630003 /* 0000218c - 0000218f [ 4] */, + 0x0909c018 /* 00002427 - 0000243f [ 25] */, + 0x0912c014 /* 0000244b - 0000245f [ 21] */, + 0x0add0001 /* 00002b74 - 00002b75 [ 2] */, + 0x0ae58000 /* 00002b96 - 00002b96 [ 1] */, + 0x0b3d0004 /* 00002cf4 - 00002cf8 [ 5] */, + 0x0b498000 /* 00002d26 - 00002d26 [ 1] */, + 0x0b4a0004 /* 00002d28 - 00002d2c [ 5] */, + 0x0b4b8001 /* 00002d2e - 00002d2f [ 2] */, + 0x0b5a0006 /* 00002d68 - 00002d6e [ 7] */, + 0x0b5c400d /* 00002d71 - 00002d7e [ 14] */, + 0x0b65c008 /* 00002d97 - 00002d9f [ 9] */, + 0x0b69c000 /* 00002da7 - 00002da7 [ 1] */, + 0x0b6bc000 /* 00002daf - 00002daf [ 1] */, + 0x0b6dc000 /* 00002db7 - 00002db7 [ 1] */, + 0x0b6fc000 /* 00002dbf - 00002dbf [ 1] */, + 0x0b71c000 /* 00002dc7 - 00002dc7 [ 1] */, + 0x0b73c000 /* 00002dcf - 00002dcf [ 1] */, + 0x0b75c000 /* 00002dd7 - 00002dd7 [ 1] */, + 0x0b77c000 /* 00002ddf - 00002ddf [ 1] */, + 0x0b978021 /* 00002e5e - 00002e7f [ 34] */, + 0x0ba68000 /* 00002e9a - 00002e9a [ 1] */, + 0x0bbd000b /* 00002ef4 - 00002eff [ 12] */, + 0x0bf58019 /* 00002fd6 - 00002fef [ 26] */, + 0x0c000000 /* 00003000 - 00003000 [ 1] */, + 0x0c100000 /* 00003040 - 00003040 [ 1] */, + 0x0c25c001 /* 00003097 - 00003098 [ 2] */, + 0x0c400004 /* 00003100 - 00003104 [ 5] */, + 0x0c4c0000 /* 00003130 - 00003130 [ 1] */, + 0x0c63c000 /* 0000318f - 0000318f [ 1] */, + 0x0c79000a /* 000031e4 - 000031ee [ 11] */, + 0x0c87c000 /* 0000321f - 0000321f [ 1] */, + 0x29234002 /* 0000a48d - 0000a48f [ 3] */, + 0x2931c008 /* 0000a4c7 - 0000a4cf [ 9] */, + 0x298b0013 /* 0000a62c - 0000a63f [ 20] */, + 0x29be0007 /* 0000a6f8 - 0000a6ff [ 8] */, + 0x29f2c004 /* 0000a7cb - 0000a7cf [ 5] */, + 0x29f48000 /* 0000a7d2 - 0000a7d2 [ 1] */, + 0x29f50000 /* 0000a7d4 - 0000a7d4 [ 1] */, + 0x29f68017 /* 0000a7da - 0000a7f1 [ 24] */, + 0x2a0b4002 /* 0000a82d - 0000a82f [ 3] */, + 0x2a0e8005 /* 0000a83a - 0000a83f [ 6] */, + 0x2a1e0007 /* 0000a878 - 0000a87f [ 8] */, + 0x2a318007 /* 0000a8c6 - 0000a8cd [ 8] */, + 0x2a368005 /* 0000a8da - 0000a8df [ 6] */, + 0x2a55000a /* 0000a954 - 0000a95e [ 11] */, + 0x2a5f4002 /* 0000a97d - 0000a97f [ 3] */, + 0x2a738000 /* 0000a9ce - 0000a9ce [ 1] */, + 0x2a768003 /* 0000a9da - 0000a9dd [ 4] */, + 0x2a7fc000 /* 0000a9ff - 0000a9ff [ 1] */, + 0x2a8dc008 /* 0000aa37 - 0000aa3f [ 9] */, + 0x2a938001 /* 0000aa4e - 0000aa4f [ 2] */, + 0x2a968001 /* 0000aa5a - 0000aa5b [ 2] */, + 0x2ab0c017 /* 0000aac3 - 0000aada [ 24] */, + 0x2abdc009 /* 0000aaf7 - 0000ab00 [ 10] */, + 0x2ac1c001 /* 0000ab07 - 0000ab08 [ 2] */, + 0x2ac3c001 /* 0000ab0f - 0000ab10 [ 2] */, + 0x2ac5c008 /* 0000ab17 - 0000ab1f [ 9] */, + 0x2ac9c000 /* 0000ab27 - 0000ab27 [ 1] */, + 0x2acbc000 /* 0000ab2f - 0000ab2f [ 1] */, + 0x2adb0003 /* 0000ab6c - 0000ab6f [ 4] */, + 0x2afb8001 /* 0000abee - 0000abef [ 2] */, + 0x2afe8005 /* 0000abfa - 0000abff [ 6] */, + 0x35e9000b /* 0000d7a4 - 0000d7af [ 12] */, + 0x35f1c003 /* 0000d7c7 - 0000d7ca [ 4] */, + 0x35ff2103 /* 0000d7fc - 0000f8ff [ 8452] */, + 0x3e9b8001 /* 0000fa6e - 0000fa6f [ 2] */, + 0x3eb68025 /* 0000fada - 0000faff [ 38] */, + 0x3ec1c00b /* 0000fb07 - 0000fb12 [ 12] */, + 0x3ec60004 /* 0000fb18 - 0000fb1c [ 5] */, + 0x3ecdc000 /* 0000fb37 - 0000fb37 [ 1] */, + 0x3ecf4000 /* 0000fb3d - 0000fb3d [ 1] */, + 0x3ecfc000 /* 0000fb3f - 0000fb3f [ 1] */, + 0x3ed08000 /* 0000fb42 - 0000fb42 [ 1] */, + 0x3ed14000 /* 0000fb45 - 0000fb45 [ 1] */, + 0x3ef0c00f /* 0000fbc3 - 0000fbd2 [ 16] */, + 0x3f640001 /* 0000fd90 - 0000fd91 [ 2] */, + 0x3f720006 /* 0000fdc8 - 0000fdce [ 7] */, + 0x3f74001f /* 0000fdd0 - 0000fdef [ 32] */, + 0x3f868005 /* 0000fe1a - 0000fe1f [ 6] */, + 0x3f94c000 /* 0000fe53 - 0000fe53 [ 1] */, + 0x3f99c000 /* 0000fe67 - 0000fe67 [ 1] */, + 0x3f9b0003 /* 0000fe6c - 0000fe6f [ 4] */, + 0x3f9d4000 /* 0000fe75 - 0000fe75 [ 1] */, + 0x3fbf4003 /* 0000fefd - 0000ff00 [ 4] */, + 0x3fefc002 /* 0000ffbf - 0000ffc1 [ 3] */, + 0x3ff20001 /* 0000ffc8 - 0000ffc9 [ 2] */, + 0x3ff40001 /* 0000ffd0 - 0000ffd1 [ 2] */, + 0x3ff60001 /* 0000ffd8 - 0000ffd9 [ 2] */, + 0x3ff74002 /* 0000ffdd - 0000ffdf [ 3] */, + 0x3ff9c000 /* 0000ffe7 - 0000ffe7 [ 1] */, + 0x3ffbc00c /* 0000ffef - 0000fffb [ 13] */, + 0x3fff8001 /* 0000fffe - 0000ffff [ 2] */, + 0x40030000 /* 0001000c - 0001000c [ 1] */, + 0x4009c000 /* 00010027 - 00010027 [ 1] */, + 0x400ec000 /* 0001003b - 0001003b [ 1] */, + 0x400f8000 /* 0001003e - 0001003e [ 1] */, + 0x40138001 /* 0001004e - 0001004f [ 2] */, + 0x40178021 /* 0001005e - 0001007f [ 34] */, + 0x403ec004 /* 000100fb - 000100ff [ 5] */, + 0x4040c003 /* 00010103 - 00010106 [ 4] */, + 0x404d0002 /* 00010134 - 00010136 [ 3] */, + 0x4063c000 /* 0001018f - 0001018f [ 1] */, + 0x40674002 /* 0001019d - 0001019f [ 3] */, + 0x4068402e /* 000101a1 - 000101cf [ 47] */, + 0x407f8081 /* 000101fe - 0001027f [ 130] */, + 0x40a74002 /* 0001029d - 0001029f [ 3] */, + 0x40b4400e /* 000102d1 - 000102df [ 15] */, + 0x40bf0003 /* 000102fc - 000102ff [ 4] */, + 0x40c90008 /* 00010324 - 0001032c [ 9] */, + 0x40d2c004 /* 0001034b - 0001034f [ 5] */, + 0x40dec004 /* 0001037b - 0001037f [ 5] */, + 0x40e78000 /* 0001039e - 0001039e [ 1] */, + 0x40f10003 /* 000103c4 - 000103c7 [ 4] */, + 0x40f58029 /* 000103d6 - 000103ff [ 42] */, + 0x41278001 /* 0001049e - 0001049f [ 2] */, + 0x412a8005 /* 000104aa - 000104af [ 6] */, + 0x41350003 /* 000104d4 - 000104d7 [ 4] */, + 0x413f0003 /* 000104fc - 000104ff [ 4] */, + 0x414a0007 /* 00010528 - 0001052f [ 8] */, + 0x4159000a /* 00010564 - 0001056e [ 11] */, + 0x415ec000 /* 0001057b - 0001057b [ 1] */, + 0x4162c000 /* 0001058b - 0001058b [ 1] */, + 0x4164c000 /* 00010593 - 00010593 [ 1] */, + 0x41658000 /* 00010596 - 00010596 [ 1] */, + 0x41688000 /* 000105a2 - 000105a2 [ 1] */, + 0x416c8000 /* 000105b2 - 000105b2 [ 1] */, + 0x416e8000 /* 000105ba - 000105ba [ 1] */, + 0x416f4042 /* 000105bd - 000105ff [ 67] */, + 0x41cdc008 /* 00010737 - 0001073f [ 9] */, + 0x41d58009 /* 00010756 - 0001075f [ 10] */, + 0x41da0017 /* 00010768 - 0001077f [ 24] */, + 0x41e18000 /* 00010786 - 00010786 [ 1] */, + 0x41ec4000 /* 000107b1 - 000107b1 [ 1] */, + 0x41eec044 /* 000107bb - 000107ff [ 69] */, + 0x42018001 /* 00010806 - 00010807 [ 2] */, + 0x42024000 /* 00010809 - 00010809 [ 1] */, + 0x420d8000 /* 00010836 - 00010836 [ 1] */, + 0x420e4002 /* 00010839 - 0001083b [ 3] */, + 0x420f4001 /* 0001083d - 0001083e [ 2] */, + 0x42158000 /* 00010856 - 00010856 [ 1] */, + 0x4227c007 /* 0001089f - 000108a6 [ 8] */, + 0x422c002f /* 000108b0 - 000108df [ 48] */, + 0x423cc000 /* 000108f3 - 000108f3 [ 1] */, + 0x423d8004 /* 000108f6 - 000108fa [ 5] */, + 0x42470002 /* 0001091c - 0001091e [ 3] */, + 0x424e8004 /* 0001093a - 0001093e [ 5] */, + 0x4250003f /* 00010940 - 0001097f [ 64] */, + 0x426e0003 /* 000109b8 - 000109bb [ 4] */, + 0x42740001 /* 000109d0 - 000109d1 [ 2] */, + 0x42810000 /* 00010a04 - 00010a04 [ 1] */, + 0x4281c004 /* 00010a07 - 00010a0b [ 5] */, + 0x42850000 /* 00010a14 - 00010a14 [ 1] */, + 0x42860000 /* 00010a18 - 00010a18 [ 1] */, + 0x428d8001 /* 00010a36 - 00010a37 [ 2] */, + 0x428ec003 /* 00010a3b - 00010a3e [ 4] */, + 0x42924006 /* 00010a49 - 00010a4f [ 7] */, + 0x42964006 /* 00010a59 - 00010a5f [ 7] */, + 0x42a8001f /* 00010aa0 - 00010abf [ 32] */, + 0x42b9c003 /* 00010ae7 - 00010aea [ 4] */, + 0x42bdc008 /* 00010af7 - 00010aff [ 9] */, + 0x42cd8002 /* 00010b36 - 00010b38 [ 3] */, + 0x42d58001 /* 00010b56 - 00010b57 [ 2] */, + 0x42dcc004 /* 00010b73 - 00010b77 [ 5] */, + 0x42e48006 /* 00010b92 - 00010b98 [ 7] */, + 0x42e7400b /* 00010b9d - 00010ba8 [ 12] */, + 0x42ec004f /* 00010bb0 - 00010bff [ 80] */, + 0x43124036 /* 00010c49 - 00010c7f [ 55] */, + 0x432cc00c /* 00010cb3 - 00010cbf [ 13] */, + 0x433cc006 /* 00010cf3 - 00010cf9 [ 7] */, + 0x434a0007 /* 00010d28 - 00010d2f [ 8] */, + 0x434e8125 /* 00010d3a - 00010e5f [ 294] */, + 0x439fc000 /* 00010e7f - 00010e7f [ 1] */, + 0x43aa8000 /* 00010eaa - 00010eaa [ 1] */, + 0x43ab8001 /* 00010eae - 00010eaf [ 2] */, + 0x43ac804a /* 00010eb2 - 00010efc [ 75] */, + 0x43ca0007 /* 00010f28 - 00010f2f [ 8] */, + 0x43d68015 /* 00010f5a - 00010f6f [ 22] */, + 0x43e28025 /* 00010f8a - 00010faf [ 38] */, + 0x43f30013 /* 00010fcc - 00010fdf [ 20] */, + 0x43fdc008 /* 00010ff7 - 00010fff [ 9] */, + 0x44138003 /* 0001104e - 00011051 [ 4] */, + 0x441d8008 /* 00011076 - 0001107e [ 9] */, + 0x442f4000 /* 000110bd - 000110bd [ 1] */, + 0x4430c00c /* 000110c3 - 000110cf [ 13] */, + 0x443a4006 /* 000110e9 - 000110ef [ 7] */, + 0x443e8005 /* 000110fa - 000110ff [ 6] */, + 0x444d4000 /* 00011135 - 00011135 [ 1] */, + 0x44520007 /* 00011148 - 0001114f [ 8] */, + 0x445dc008 /* 00011177 - 0001117f [ 9] */, + 0x44780000 /* 000111e0 - 000111e0 [ 1] */, + 0x447d400a /* 000111f5 - 000111ff [ 11] */, + 0x44848000 /* 00011212 - 00011212 [ 1] */, + 0x4490803d /* 00011242 - 0001127f [ 62] */, + 0x44a1c000 /* 00011287 - 00011287 [ 1] */, + 0x44a24000 /* 00011289 - 00011289 [ 1] */, + 0x44a38000 /* 0001128e - 0001128e [ 1] */, + 0x44a78000 /* 0001129e - 0001129e [ 1] */, + 0x44aa8005 /* 000112aa - 000112af [ 6] */, + 0x44bac004 /* 000112eb - 000112ef [ 5] */, + 0x44be8005 /* 000112fa - 000112ff [ 6] */, + 0x44c10000 /* 00011304 - 00011304 [ 1] */, + 0x44c34001 /* 0001130d - 0001130e [ 2] */, + 0x44c44001 /* 00011311 - 00011312 [ 2] */, + 0x44ca4000 /* 00011329 - 00011329 [ 1] */, + 0x44cc4000 /* 00011331 - 00011331 [ 1] */, + 0x44cd0000 /* 00011334 - 00011334 [ 1] */, + 0x44ce8000 /* 0001133a - 0001133a [ 1] */, + 0x44d14001 /* 00011345 - 00011346 [ 2] */, + 0x44d24001 /* 00011349 - 0001134a [ 2] */, + 0x44d38001 /* 0001134e - 0001134f [ 2] */, + 0x44d44005 /* 00011351 - 00011356 [ 6] */, + 0x44d60004 /* 00011358 - 0001135c [ 5] */, + 0x44d90001 /* 00011364 - 00011365 [ 2] */, + 0x44db4002 /* 0001136d - 0001136f [ 3] */, + 0x44dd408a /* 00011375 - 000113ff [ 139] */, + 0x45170000 /* 0001145c - 0001145c [ 1] */, + 0x4518801d /* 00011462 - 0001147f [ 30] */, + 0x45320007 /* 000114c8 - 000114cf [ 8] */, + 0x453680a5 /* 000114da - 0001157f [ 166] */, + 0x456d8001 /* 000115b6 - 000115b7 [ 2] */, + 0x45778021 /* 000115de - 000115ff [ 34] */, + 0x4591400a /* 00011645 - 0001164f [ 11] */, + 0x45968005 /* 0001165a - 0001165f [ 6] */, + 0x459b4012 /* 0001166d - 0001167f [ 19] */, + 0x45ae8005 /* 000116ba - 000116bf [ 6] */, + 0x45b28035 /* 000116ca - 000116ff [ 54] */, + 0x45c6c001 /* 0001171b - 0001171c [ 2] */, + 0x45cb0003 /* 0001172c - 0001172f [ 4] */, + 0x45d1c0b8 /* 00011747 - 000117ff [ 185] */, + 0x460f0063 /* 0001183c - 0001189f [ 100] */, + 0x463cc00b /* 000118f3 - 000118fe [ 12] */, + 0x4641c001 /* 00011907 - 00011908 [ 2] */, + 0x46428001 /* 0001190a - 0001190b [ 2] */, + 0x46450000 /* 00011914 - 00011914 [ 1] */, + 0x4645c000 /* 00011917 - 00011917 [ 1] */, + 0x464d8000 /* 00011936 - 00011936 [ 1] */, + 0x464e4001 /* 00011939 - 0001193a [ 2] */, + 0x4651c008 /* 00011947 - 0001194f [ 9] */, + 0x46568045 /* 0001195a - 0001199f [ 70] */, + 0x466a0001 /* 000119a8 - 000119a9 [ 2] */, + 0x46760001 /* 000119d8 - 000119d9 [ 2] */, + 0x4679401a /* 000119e5 - 000119ff [ 27] */, + 0x46920007 /* 00011a48 - 00011a4f [ 8] */, + 0x46a8c00c /* 00011aa3 - 00011aaf [ 13] */, + 0x46be4006 /* 00011af9 - 00011aff [ 7] */, + 0x46c280f5 /* 00011b0a - 00011bff [ 246] */, + 0x47024000 /* 00011c09 - 00011c09 [ 1] */, + 0x470dc000 /* 00011c37 - 00011c37 [ 1] */, + 0x47118009 /* 00011c46 - 00011c4f [ 10] */, + 0x471b4002 /* 00011c6d - 00011c6f [ 3] */, + 0x47240001 /* 00011c90 - 00011c91 [ 2] */, + 0x472a0000 /* 00011ca8 - 00011ca8 [ 1] */, + 0x472dc048 /* 00011cb7 - 00011cff [ 73] */, + 0x4741c000 /* 00011d07 - 00011d07 [ 1] */, + 0x47428000 /* 00011d0a - 00011d0a [ 1] */, + 0x474dc002 /* 00011d37 - 00011d39 [ 3] */, + 0x474ec000 /* 00011d3b - 00011d3b [ 1] */, + 0x474f8000 /* 00011d3e - 00011d3e [ 1] */, + 0x47520007 /* 00011d48 - 00011d4f [ 8] */, + 0x47568005 /* 00011d5a - 00011d5f [ 6] */, + 0x47598000 /* 00011d66 - 00011d66 [ 1] */, + 0x475a4000 /* 00011d69 - 00011d69 [ 1] */, + 0x4763c000 /* 00011d8f - 00011d8f [ 1] */, + 0x47648000 /* 00011d92 - 00011d92 [ 1] */, + 0x47664006 /* 00011d99 - 00011d9f [ 7] */, + 0x476a8135 /* 00011daa - 00011edf [ 310] */, + 0x47be4006 /* 00011ef9 - 00011eff [ 7] */, + 0x47c44000 /* 00011f11 - 00011f11 [ 1] */, + 0x47cec002 /* 00011f3b - 00011f3d [ 3] */, + 0x47d68055 /* 00011f5a - 00011faf [ 86] */, + 0x47ec400e /* 00011fb1 - 00011fbf [ 15] */, + 0x47fc800c /* 00011ff2 - 00011ffe [ 13] */, + 0x48e68065 /* 0001239a - 000123ff [ 102] */, + 0x491bc000 /* 0001246f - 0001246f [ 1] */, + 0x491d400a /* 00012475 - 0001247f [ 11] */, + 0x49510a4b /* 00012544 - 00012f8f [ 2636] */, + 0x4bfcc00c /* 00012ff3 - 00012fff [ 13] */, + 0x4d0c000f /* 00013430 - 0001343f [ 16] */, + 0x4d158fa9 /* 00013456 - 000143ff [ 4010] */, + 0x5191e1b8 /* 00014647 - 000167ff [ 8633] */, + 0x5a8e4006 /* 00016a39 - 00016a3f [ 7] */, + 0x5a97c000 /* 00016a5f - 00016a5f [ 1] */, + 0x5a9a8003 /* 00016a6a - 00016a6d [ 4] */, + 0x5aafc000 /* 00016abf - 00016abf [ 1] */, + 0x5ab28005 /* 00016aca - 00016acf [ 6] */, + 0x5abb8001 /* 00016aee - 00016aef [ 2] */, + 0x5abd8009 /* 00016af6 - 00016aff [ 10] */, + 0x5ad18009 /* 00016b46 - 00016b4f [ 10] */, + 0x5ad68000 /* 00016b5a - 00016b5a [ 1] */, + 0x5ad88000 /* 00016b62 - 00016b62 [ 1] */, + 0x5ade0004 /* 00016b78 - 00016b7c [ 5] */, + 0x5ae402af /* 00016b90 - 00016e3f [ 688] */, + 0x5ba6c064 /* 00016e9b - 00016eff [ 101] */, + 0x5bd2c003 /* 00016f4b - 00016f4e [ 4] */, + 0x5be20006 /* 00016f88 - 00016f8e [ 7] */, + 0x5be8003f /* 00016fa0 - 00016fdf [ 64] */, + 0x5bf9400a /* 00016fe5 - 00016fef [ 11] */, + 0x5bfc800d /* 00016ff2 - 00016fff [ 14] */, + 0x61fe0007 /* 000187f8 - 000187ff [ 8] */, + 0x63358029 /* 00018cd6 - 00018cff [ 42] */, + 0x634262e6 /* 00018d09 - 0001afef [ 8935] */, + 0x6bfd0000 /* 0001aff4 - 0001aff4 [ 1] */, + 0x6bff0000 /* 0001affc - 0001affc [ 1] */, + 0x6bffc000 /* 0001afff - 0001afff [ 1] */, + 0x6c48c00e /* 0001b123 - 0001b131 [ 15] */, + 0x6c4cc01c /* 0001b133 - 0001b14f [ 29] */, + 0x6c54c001 /* 0001b153 - 0001b154 [ 2] */, + 0x6c55800d /* 0001b156 - 0001b163 [ 14] */, + 0x6c5a0007 /* 0001b168 - 0001b16f [ 8] */, + 0x6cbf0903 /* 0001b2fc - 0001bbff [ 2308] */, + 0x6f1ac004 /* 0001bc6b - 0001bc6f [ 5] */, + 0x6f1f4002 /* 0001bc7d - 0001bc7f [ 3] */, + 0x6f224006 /* 0001bc89 - 0001bc8f [ 7] */, + 0x6f268001 /* 0001bc9a - 0001bc9b [ 2] */, + 0x6f28125f /* 0001bca0 - 0001ceff [ 4704] */, + 0x73cb8001 /* 0001cf2e - 0001cf2f [ 2] */, + 0x73d1c008 /* 0001cf47 - 0001cf4f [ 9] */, + 0x73f1003b /* 0001cfc4 - 0001cfff [ 60] */, + 0x743d8009 /* 0001d0f6 - 0001d0ff [ 10] */, + 0x7449c001 /* 0001d127 - 0001d128 [ 2] */, + 0x745cc007 /* 0001d173 - 0001d17a [ 8] */, + 0x747ac014 /* 0001d1eb - 0001d1ff [ 21] */, + 0x74918079 /* 0001d246 - 0001d2bf [ 122] */, + 0x74b5000b /* 0001d2d4 - 0001d2df [ 12] */, + 0x74bd000b /* 0001d2f4 - 0001d2ff [ 12] */, + 0x74d5c008 /* 0001d357 - 0001d35f [ 9] */, + 0x74de4086 /* 0001d379 - 0001d3ff [ 135] */, + 0x75154000 /* 0001d455 - 0001d455 [ 1] */, + 0x75274000 /* 0001d49d - 0001d49d [ 1] */, + 0x75280001 /* 0001d4a0 - 0001d4a1 [ 2] */, + 0x7528c001 /* 0001d4a3 - 0001d4a4 [ 2] */, + 0x7529c001 /* 0001d4a7 - 0001d4a8 [ 2] */, + 0x752b4000 /* 0001d4ad - 0001d4ad [ 1] */, + 0x752e8000 /* 0001d4ba - 0001d4ba [ 1] */, + 0x752f0000 /* 0001d4bc - 0001d4bc [ 1] */, + 0x75310000 /* 0001d4c4 - 0001d4c4 [ 1] */, + 0x75418000 /* 0001d506 - 0001d506 [ 1] */, + 0x7542c001 /* 0001d50b - 0001d50c [ 2] */, + 0x75454000 /* 0001d515 - 0001d515 [ 1] */, + 0x75474000 /* 0001d51d - 0001d51d [ 1] */, + 0x754e8000 /* 0001d53a - 0001d53a [ 1] */, + 0x754fc000 /* 0001d53f - 0001d53f [ 1] */, + 0x75514000 /* 0001d545 - 0001d545 [ 1] */, + 0x7551c002 /* 0001d547 - 0001d549 [ 3] */, + 0x75544000 /* 0001d551 - 0001d551 [ 1] */, + 0x75a98001 /* 0001d6a6 - 0001d6a7 [ 2] */, + 0x75f30001 /* 0001d7cc - 0001d7cd [ 2] */, + 0x76a3000e /* 0001da8c - 0001da9a [ 15] */, + 0x76a80000 /* 0001daa0 - 0001daa0 [ 1] */, + 0x76ac044f /* 0001dab0 - 0001deff [ 1104] */, + 0x77c7c005 /* 0001df1f - 0001df24 [ 6] */, + 0x77cac0d4 /* 0001df2b - 0001dfff [ 213] */, + 0x7801c000 /* 0001e007 - 0001e007 [ 1] */, + 0x78064001 /* 0001e019 - 0001e01a [ 2] */, + 0x78088000 /* 0001e022 - 0001e022 [ 1] */, + 0x78094000 /* 0001e025 - 0001e025 [ 1] */, + 0x780ac004 /* 0001e02b - 0001e02f [ 5] */, + 0x781b8020 /* 0001e06e - 0001e08e [ 33] */, + 0x7824006f /* 0001e090 - 0001e0ff [ 112] */, + 0x784b4002 /* 0001e12d - 0001e12f [ 3] */, + 0x784f8001 /* 0001e13e - 0001e13f [ 2] */, + 0x78528003 /* 0001e14a - 0001e14d [ 4] */, + 0x7854013f /* 0001e150 - 0001e28f [ 320] */, + 0x78abc010 /* 0001e2af - 0001e2bf [ 17] */, + 0x78be8004 /* 0001e2fa - 0001e2fe [ 5] */, + 0x78c001cf /* 0001e300 - 0001e4cf [ 464] */, + 0x793e82e5 /* 0001e4fa - 0001e7df [ 742] */, + 0x79f9c000 /* 0001e7e7 - 0001e7e7 [ 1] */, + 0x79fb0000 /* 0001e7ec - 0001e7ec [ 1] */, + 0x79fbc000 /* 0001e7ef - 0001e7ef [ 1] */, + 0x79ffc000 /* 0001e7ff - 0001e7ff [ 1] */, + 0x7a314001 /* 0001e8c5 - 0001e8c6 [ 2] */, + 0x7a35c028 /* 0001e8d7 - 0001e8ff [ 41] */, + 0x7a530003 /* 0001e94c - 0001e94f [ 4] */, + 0x7a568003 /* 0001e95a - 0001e95d [ 4] */, + 0x7a580310 /* 0001e960 - 0001ec70 [ 785] */, + 0x7b2d404b /* 0001ecb5 - 0001ed00 [ 76] */, + 0x7b4f80c1 /* 0001ed3e - 0001edff [ 194] */, + 0x7b810000 /* 0001ee04 - 0001ee04 [ 1] */, + 0x7b880000 /* 0001ee20 - 0001ee20 [ 1] */, + 0x7b88c000 /* 0001ee23 - 0001ee23 [ 1] */, + 0x7b894001 /* 0001ee25 - 0001ee26 [ 2] */, + 0x7b8a0000 /* 0001ee28 - 0001ee28 [ 1] */, + 0x7b8cc000 /* 0001ee33 - 0001ee33 [ 1] */, + 0x7b8e0000 /* 0001ee38 - 0001ee38 [ 1] */, + 0x7b8e8000 /* 0001ee3a - 0001ee3a [ 1] */, + 0x7b8f0005 /* 0001ee3c - 0001ee41 [ 6] */, + 0x7b90c003 /* 0001ee43 - 0001ee46 [ 4] */, + 0x7b920000 /* 0001ee48 - 0001ee48 [ 1] */, + 0x7b928000 /* 0001ee4a - 0001ee4a [ 1] */, + 0x7b930000 /* 0001ee4c - 0001ee4c [ 1] */, + 0x7b940000 /* 0001ee50 - 0001ee50 [ 1] */, + 0x7b94c000 /* 0001ee53 - 0001ee53 [ 1] */, + 0x7b954001 /* 0001ee55 - 0001ee56 [ 2] */, + 0x7b960000 /* 0001ee58 - 0001ee58 [ 1] */, + 0x7b968000 /* 0001ee5a - 0001ee5a [ 1] */, + 0x7b970000 /* 0001ee5c - 0001ee5c [ 1] */, + 0x7b978000 /* 0001ee5e - 0001ee5e [ 1] */, + 0x7b980000 /* 0001ee60 - 0001ee60 [ 1] */, + 0x7b98c000 /* 0001ee63 - 0001ee63 [ 1] */, + 0x7b994001 /* 0001ee65 - 0001ee66 [ 2] */, + 0x7b9ac000 /* 0001ee6b - 0001ee6b [ 1] */, + 0x7b9cc000 /* 0001ee73 - 0001ee73 [ 1] */, + 0x7b9e0000 /* 0001ee78 - 0001ee78 [ 1] */, + 0x7b9f4000 /* 0001ee7d - 0001ee7d [ 1] */, + 0x7b9fc000 /* 0001ee7f - 0001ee7f [ 1] */, + 0x7ba28000 /* 0001ee8a - 0001ee8a [ 1] */, + 0x7ba70004 /* 0001ee9c - 0001eea0 [ 5] */, + 0x7ba90000 /* 0001eea4 - 0001eea4 [ 1] */, + 0x7baa8000 /* 0001eeaa - 0001eeaa [ 1] */, + 0x7baf0033 /* 0001eebc - 0001eeef [ 52] */, + 0x7bbc810d /* 0001eef2 - 0001efff [ 270] */, + 0x7c0b0003 /* 0001f02c - 0001f02f [ 4] */, + 0x7c25000b /* 0001f094 - 0001f09f [ 12] */, + 0x7c2bc001 /* 0001f0af - 0001f0b0 [ 2] */, + 0x7c300000 /* 0001f0c0 - 0001f0c0 [ 1] */, + 0x7c340000 /* 0001f0d0 - 0001f0d0 [ 1] */, + 0x7c3d8009 /* 0001f0f6 - 0001f0ff [ 10] */, + 0x7c6b8037 /* 0001f1ae - 0001f1e5 [ 56] */, + 0x7c80c00c /* 0001f203 - 0001f20f [ 13] */, + 0x7c8f0003 /* 0001f23c - 0001f23f [ 4] */, + 0x7c924006 /* 0001f249 - 0001f24f [ 7] */, + 0x7c94800d /* 0001f252 - 0001f25f [ 14] */, + 0x7c998099 /* 0001f266 - 0001f2ff [ 154] */, + 0x7db60003 /* 0001f6d8 - 0001f6db [ 4] */, + 0x7dbb4002 /* 0001f6ed - 0001f6ef [ 3] */, + 0x7dbf4002 /* 0001f6fd - 0001f6ff [ 3] */, + 0x7dddc003 /* 0001f777 - 0001f77a [ 4] */, + 0x7df68005 /* 0001f7da - 0001f7df [ 6] */, + 0x7dfb0003 /* 0001f7ec - 0001f7ef [ 4] */, + 0x7dfc400e /* 0001f7f1 - 0001f7ff [ 15] */, + 0x7e030003 /* 0001f80c - 0001f80f [ 4] */, + 0x7e120007 /* 0001f848 - 0001f84f [ 8] */, + 0x7e168005 /* 0001f85a - 0001f85f [ 6] */, + 0x7e220007 /* 0001f888 - 0001f88f [ 8] */, + 0x7e2b8001 /* 0001f8ae - 0001f8af [ 2] */, + 0x7e2c804d /* 0001f8b2 - 0001f8ff [ 78] */, + 0x7e95000b /* 0001fa54 - 0001fa5f [ 12] */, + 0x7e9b8001 /* 0001fa6e - 0001fa6f [ 2] */, + 0x7e9f4002 /* 0001fa7d - 0001fa7f [ 3] */, + 0x7ea24006 /* 0001fa89 - 0001fa8f [ 7] */, + 0x7eaf8000 /* 0001fabe - 0001fabe [ 1] */, + 0x7eb18007 /* 0001fac6 - 0001facd [ 8] */, + 0x7eb70003 /* 0001fadc - 0001fadf [ 4] */, + 0x7eba4006 /* 0001fae9 - 0001faef [ 7] */, + 0x7ebe4006 /* 0001faf9 - 0001faff [ 7] */, + 0x7ee4c000 /* 0001fb93 - 0001fb93 [ 1] */, + 0x7ef2c024 /* 0001fbcb - 0001fbef [ 37] */, + 0x7efe8405 /* 0001fbfa - 0001ffff [ 1030] */, + 0xa9b8001f /* 0002a6e0 - 0002a6ff [ 32] */, + 0xadce8005 /* 0002b73a - 0002b73f [ 6] */, + 0xae078001 /* 0002b81e - 0002b81f [ 2] */, + 0xb3a8800d /* 0002cea2 - 0002ceaf [ 14] */, + 0xbaf8400e /* 0002ebe1 - 0002ebef [ 15] */, + 0xbb9789a1 /* 0002ee5e - 0002f7ff [ 2466] */, + 0xbe8785e1 /* 0002fa1e - 0002ffff [ 1506] */, + 0xc4d2c004 /* 0003134b - 0003134f [ 5] */}; /// Returns whether the code unit needs to be escaped. /// -/// \pre The code point is a valid Unicode code point. +/// At the end of the valid Unicode code points space a lot of code points are +/// either reserved or a noncharacter. Adding all these entries to the +/// lookup table would greatly increase the size of the table. Instead these +/// entries are manually processed. In this large area of reserved code points, +/// there is a small area of extended graphemes that should not be escaped +/// unconditionally. This is also manually coded. See the generation script for +/// more details. + +/// +/// \\pre The code point is a valid Unicode code point. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __needs_escape(const char32_t __code_point) noexcept { - // Since __unallocated_region_lower_bound contains the unshifted range do the - // comparison without shifting. - if (__code_point >= __unallocated_region_lower_bound) + + // The entries in the gap at the end. + if(__code_point >= 0x000e0100 && __code_point <= 0x000e01ef) + return false; + + // The entries at the end. + if (__code_point >= 0x000323b0) return true; - ptrdiff_t __i = std::ranges::upper_bound(__entries, (__code_point << 11) | 0x7ffu) - __entries; + ptrdiff_t __i = std::ranges::upper_bound(__entries, (__code_point << 14) | 0x3fffu) - __entries; if (__i == 0) return false; --__i; - uint32_t __upper_bound = (__entries[__i] >> 11) + (__entries[__i] & 0x7ffu); + uint32_t __upper_bound = (__entries[__i] >> 14) + (__entries[__i] & 0x3fffu); return __code_point <= __upper_bound; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/format_arg.h b/naiveproxy/src/third_party/libc++/src/include/__format/format_arg.h index 4924e5fb32..aa02f81dc4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/format_arg.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/format_arg.h @@ -19,6 +19,7 @@ #include <__fwd/format.h> #include <__memory/addressof.h> #include <__type_traits/conditional.h> +#include <__type_traits/remove_const.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/unreachable.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/format_args.h b/naiveproxy/src/third_party/libc++/src/include/__format/format_args.h index a5fde36a29..07923570f3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/format_args.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/format_args.h @@ -28,8 +28,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD template class _LIBCPP_TEMPLATE_VIS basic_format_args { public: - basic_format_args() noexcept = default; - template _LIBCPP_HIDE_FROM_ABI basic_format_args(const __format_arg_store<_Context, _Args...>& __store) noexcept : __size_(sizeof...(_Args)) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/format_context.h b/naiveproxy/src/third_party/libc++/src/include/__format/format_context.h index 087d4bf289..20c07559ea 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/format_context.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/format_context.h @@ -131,6 +131,9 @@ private: _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(_OutIt __out_it, basic_format_args __args) : __out_it_(std::move(__out_it)), __args_(__args) {} # endif + + basic_format_context(const basic_format_context&) = delete; + basic_format_context& operator=(const basic_format_context&) = delete; }; // A specialization for __retarget_buffer diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/format_functions.h b/naiveproxy/src/third_party/libc++/src/include/__format/format_functions.h index c781014010..d14b49aff1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/format_functions.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/format_functions.h @@ -66,14 +66,13 @@ using wformat_args = basic_format_args; # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) { return std::__format_arg_store<_Context, _Args...>(__args...); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store -make_wformat_args(_Args&... __args) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store make_wformat_args(_Args&... __args) { return std::__format_arg_store(__args...); } # endif @@ -452,8 +451,7 @@ format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string -vformat(string_view __fmt, format_args __args) { +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { string __res; std::vformat_to(std::back_inserter(__res), __fmt, __args); return __res; @@ -463,7 +461,7 @@ vformat(string_view __fmt, format_args __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(wstring_view __fmt, wformat_args __args) { wstring __res; std::vformat_to(std::back_inserter(__res), __fmt, __args); @@ -472,14 +470,14 @@ vformat(wstring_view __fmt, wformat_args __args) { # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string format(format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(__fmt.get(), std::make_format_args(__args...)); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(wformat_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); } @@ -520,14 +518,14 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, } template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)}); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); } @@ -585,7 +583,7 @@ format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&& // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(locale __loc, string_view __fmt, format_args __args) { string __res; std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); @@ -596,7 +594,7 @@ vformat(locale __loc, string_view __fmt, format_args __args) { // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(locale __loc, wstring_view __fmt, wformat_args __args) { wstring __res; std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); @@ -605,14 +603,14 @@ vformat(locale __loc, wstring_view __fmt, wformat_args __args) { # endif template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...)); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...)); } @@ -658,14 +656,14 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_ } template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)}); } # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t +[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)}); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/formatter_output.h b/naiveproxy/src/third_party/libc++/src/include/__format/formatter_output.h index d5038eb158..1498f64c4a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/formatter_output.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/formatter_output.h @@ -100,8 +100,8 @@ __padding_size(size_t __size, size_t __width, __format_spec::__alignment __align /// /// This uses a "mass output function" of __format::__output_buffer when possible. template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT> -_LIBCPP_HIDE_FROM_ABI auto __copy(basic_string_view<_CharT> __str, output_iterator auto __out_it) - -> decltype(__out_it) { +_LIBCPP_HIDE_FROM_ABI auto +__copy(basic_string_view<_CharT> __str, output_iterator auto __out_it) -> decltype(__out_it) { if constexpr (std::same_as>>) { __out_it.__get_container()->__copy(__str); return __out_it; @@ -116,16 +116,16 @@ _LIBCPP_HIDE_FROM_ABI auto __copy(basic_string_view<_CharT> __str, output_iterat template ::value_type, __fmt_char_type _OutCharT = _CharT> -_LIBCPP_HIDE_FROM_ABI auto __copy(_Iterator __first, _Iterator __last, output_iterator auto __out_it) - -> decltype(__out_it) { +_LIBCPP_HIDE_FROM_ABI auto +__copy(_Iterator __first, _Iterator __last, output_iterator auto __out_it) -> decltype(__out_it) { return __formatter::__copy(basic_string_view{__first, __last}, std::move(__out_it)); } template ::value_type, __fmt_char_type _OutCharT = _CharT> -_LIBCPP_HIDE_FROM_ABI auto __copy(_Iterator __first, size_t __n, output_iterator auto __out_it) - -> decltype(__out_it) { +_LIBCPP_HIDE_FROM_ABI auto +__copy(_Iterator __first, size_t __n, output_iterator auto __out_it) -> decltype(__out_it) { return __formatter::__copy(basic_string_view{std::to_address(__first), __n}, std::move(__out_it)); } @@ -136,9 +136,11 @@ template ::value_type, __fmt_char_type _OutCharT = _CharT, class _UnaryOperation> -_LIBCPP_HIDE_FROM_ABI auto __transform( - _Iterator __first, _Iterator __last, output_iterator auto __out_it, _UnaryOperation __operation) - -> decltype(__out_it) { +_LIBCPP_HIDE_FROM_ABI auto +__transform(_Iterator __first, + _Iterator __last, + output_iterator auto __out_it, + _UnaryOperation __operation) -> decltype(__out_it) { if constexpr (std::same_as>>) { __out_it.__get_container()->__transform(__first, __last, std::move(__operation)); return __out_it; diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/parser_std_format_spec.h b/naiveproxy/src/third_party/libc++/src/include/__format/parser_std_format_spec.h index 9818f37b51..150bdde89f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/parser_std_format_spec.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/parser_std_format_spec.h @@ -1155,8 +1155,8 @@ __estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __col // When Unicode isn't supported assume ASCII and every code unit is one code // point. In ASCII the estimated column width is always one. Thus there's no // need for rounding. - size_t __width_ = std::min(__str.size(), __maximum); - return {__width_, __str.begin() + __width_}; + size_t __width = std::min(__str.size(), __maximum); + return {__width, __str.begin() + __width}; } # endif // !defined(_LIBCPP_HAS_NO_UNICODE) diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/width_estimation_table.h b/naiveproxy/src/third_party/libc++/src/include/__format/width_estimation_table.h index c9a9f6719c..11f61dea18 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/width_estimation_table.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/width_estimation_table.h @@ -237,7 +237,7 @@ inline constexpr uint32_t __table_upper_bound = 0x0003fffd; /// Returns the estimated width of a Unicode code point. /// -/// \pre The code point is a valid Unicode code point. +/// \\pre The code point is a valid Unicode code point. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int __estimated_width(const char32_t __code_point) noexcept { // Since __table_upper_bound contains the unshifted range do the // comparison without shifting. diff --git a/naiveproxy/src/third_party/libc++/src/include/__format/write_escaped.h b/naiveproxy/src/third_party/libc++/src/include/__format/write_escaped.h index 43a074dd8d..052ea98c3c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__format/write_escaped.h +++ b/naiveproxy/src/third_party/libc++/src/include/__format/write_escaped.h @@ -101,15 +101,27 @@ _LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_Cha } template -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool +__is_escaped_sequence_written(basic_string<_CharT>& __str, bool __last_escaped, char32_t __value) { # ifdef _LIBCPP_HAS_NO_UNICODE // For ASCII assume everything above 127 is printable. if (__value > 127) return false; # endif + // [format.string.escaped]/2.2.1.2.1 + // CE is UTF-8, UTF-16, or UTF-32 and C corresponds to a Unicode scalar + // value whose Unicode property General_Category has a value in the groups + // Separator (Z) or Other (C), as described by UAX #44 of the Unicode Standard, if (!__escaped_output_table::__needs_escape(__value)) - return false; + // [format.string.escaped]/2.2.1.2.2 + // CE is UTF-8, UTF-16, or UTF-32 and C corresponds to a Unicode scalar + // value with the Unicode property Grapheme_Extend=Yes as described by UAX + // #44 of the Unicode Standard and C is not immediately preceded in S by a + // character P appended to E without translation to an escape sequence, + if (!__last_escaped || __extended_grapheme_custer_property_boundary::__get_property(__value) != + __extended_grapheme_custer_property_boundary::__property::__Extend) + return false; __formatter::__write_well_formed_escaped_code_unit(__str, __value); return true; @@ -124,8 +136,8 @@ enum class __escape_quotation_mark { __apostrophe, __double_quote }; // [format.string.escaped]/2 template -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool -__is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value, __escape_quotation_mark __mark) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written( + basic_string<_CharT>& __str, char32_t __value, bool __last_escaped, __escape_quotation_mark __mark) { // 2.2.1.1 - Mapped character in [tab:format.escape.sequences] switch (__value) { case _CharT('\t'): @@ -167,7 +179,7 @@ __is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value, __e // TODO FMT determine what to do with shift sequences. // 2.2.1.2.1 and 2.2.1.2.2 - Escape - return __formatter::__is_escaped_sequence_written(__str, __formatter::__to_char32(__value)); + return __formatter::__is_escaped_sequence_written(__str, __last_escaped, __formatter::__to_char32(__value)); } template @@ -175,11 +187,15 @@ _LIBCPP_HIDE_FROM_ABI void __escape(basic_string<_CharT>& __str, basic_string_view<_CharT> __values, __escape_quotation_mark __mark) { __unicode::__code_point_view<_CharT> __view{__values.begin(), __values.end()}; + // When the first code unit has the property Grapheme_Extend=Yes it needs to + // be escaped. This happens when the previous code unit was also escaped. + bool __escape = true; while (!__view.__at_end()) { auto __first = __view.__position(); typename __unicode::__consume_result __result = __view.__consume(); if (__result.__status == __unicode::__consume_result::__ok) { - if (!__formatter::__is_escaped_sequence_written(__str, __result.__code_point, __mark)) + __escape = __formatter::__is_escaped_sequence_written(__str, __result.__code_point, __escape, __mark); + if (!__escape) // 2.2.1.3 - Add the character ranges::copy(__first, __view.__position(), std::back_insert_iterator(__str)); } else { diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/bind.h b/naiveproxy/src/third_party/libc++/src/include/__functional/bind.h index 8a0e3b7ffa..b4f46441da 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/bind.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/bind.h @@ -95,7 +95,7 @@ __mu(_Ti& __ti, tuple<_Uj...>& __uj) { return std::__mu_expand(__ti, __uj, __indices()); } -template +template struct __mu_return2 {}; template @@ -105,8 +105,8 @@ struct __mu_return2 { template ::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - typename __mu_return2<0 < is_placeholder<_Ti>::value, _Ti, _Uj>::type - __mu(_Ti&, _Uj& __uj) { +typename __mu_return2<0 < is_placeholder<_Ti>::value, _Ti, _Uj>::type +__mu(_Ti&, _Uj& __uj) { const size_t __indx = is_placeholder<_Ti>::value - 1; return std::forward::type>(std::get<__indx>(__uj)); } @@ -120,7 +120,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Ti& __mu(_Ti& __ti, return __ti; } -template +template struct __mu_return_impl; template @@ -225,8 +225,8 @@ public: template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - typename __bind_return >::type - operator()(_Args&&... __args) const { + typename __bind_return >::type + operator()(_Args&&... __args) const { return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); } }; diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/bind_back.h b/naiveproxy/src/third_party/libc++/src/include/__functional/bind_back.h index 3c42d4769e..e44768d228 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/bind_back.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/bind_back.h @@ -52,7 +52,7 @@ struct __bind_back_t : __perfect_forward<__bind_back_op template requires is_constructible_v, _Fn> && is_move_constructible_v> && - (is_constructible_v, _Args> && ...) && (is_move_constructible_v> && ...) + (is_constructible_v, _Args> && ...) && (is_move_constructible_v> && ...) _LIBCPP_HIDE_FROM_ABI constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) noexcept( noexcept(__bind_back_t, tuple...>>( std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...)))) diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/bind_front.h b/naiveproxy/src/third_party/libc++/src/include/__functional/bind_front.h index 11d0bac3f8..87ef3affe8 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/bind_front.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/bind_front.h @@ -29,9 +29,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD struct __bind_front_op { template - _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const - noexcept(noexcept(std::invoke(std::forward<_Args>(__args)...))) - -> decltype(std::invoke(std::forward<_Args>(__args)...)) { + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const noexcept( + noexcept(std::invoke(std::forward<_Args>(__args)...))) -> decltype(std::invoke(std::forward<_Args>(__args)...)) { return std::invoke(std::forward<_Args>(__args)...); } }; diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/function.h b/naiveproxy/src/third_party/libc++/src/include/__functional/function.h index 1faa9e92eb..c7b98035e3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/function.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/function.h @@ -55,7 +55,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD // bad_function_call _LIBCPP_DIAGNOSTIC_PUSH +# if !_LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_KEY_FUNCTION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables") +# endif class _LIBCPP_EXPORTED_FROM_ABI bad_function_call : public exception { public: _LIBCPP_HIDE_FROM_ABI bad_function_call() _NOEXCEPT = default; @@ -64,7 +66,7 @@ public: // Note that when a key function is not used, every translation unit that uses // bad_function_call will end up containing a weak definition of the vtable and // typeinfo. -# ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION +# if _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_KEY_FUNCTION ~bad_function_call() _NOEXCEPT override; # else _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_function_call() _NOEXCEPT override {} @@ -230,10 +232,10 @@ class _LIBCPP_TEMPLATE_VIS __base; template class __base<_Rp(_ArgTypes...)> { - __base(const __base&); - __base& operator=(const __base&); - public: + __base(const __base&) = delete; + __base& operator=(const __base&) = delete; + _LIBCPP_HIDE_FROM_ABI __base() {} _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual ~__base() {} virtual __base* __clone() const = 0; @@ -514,7 +516,7 @@ struct __policy { } _LIBCPP_HIDE_FROM_ABI static const __policy* __create_empty() { - static const _LIBCPP_CONSTEXPR __policy __policy = { + static constexpr __policy __policy = { nullptr, nullptr, true, @@ -541,7 +543,7 @@ private: template _LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ false_type) { - static const _LIBCPP_CONSTEXPR __policy __policy = { + static constexpr __policy __policy = { &__large_clone<_Fun>, &__large_destroy<_Fun>, false, @@ -556,7 +558,7 @@ private: template _LIBCPP_HIDE_FROM_ABI static const __policy* __choose_policy(/* is_small = */ true_type) { - static const _LIBCPP_CONSTEXPR __policy __policy = { + static constexpr __policy __policy = { nullptr, nullptr, false, diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/identity.h b/naiveproxy/src/third_party/libc++/src/include/__functional/identity.h index b7be367bd5..8468de3dae 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/identity.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/identity.h @@ -44,7 +44,7 @@ struct __is_identity > : true_type {}; struct identity { template - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { return std::forward<_Tp>(__t); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/is_transparent.h b/naiveproxy/src/third_party/libc++/src/include/__functional/is_transparent.h index 13fc94f71c..b2d62f2e3e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/is_transparent.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/is_transparent.h @@ -11,7 +11,6 @@ #define _LIBCPP___FUNCTIONAL_IS_TRANSPARENT #include <__config> -#include <__type_traits/integral_constant.h> #include <__type_traits/void_t.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -23,10 +22,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 14 template -struct __is_transparent : false_type {}; +inline const bool __is_transparent_v = false; template -struct __is_transparent<_Tp, _Up, __void_t > : true_type {}; +inline const bool __is_transparent_v<_Tp, _Up, __void_t > = true; #endif diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/mem_fn.h b/naiveproxy/src/third_party/libc++/src/include/__functional/mem_fn.h index 349a6ce3a7..ee07a71774 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/mem_fn.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/mem_fn.h @@ -38,8 +38,8 @@ public: template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - typename __invoke_return::type - operator()(_ArgTypes&&... __args) const { + typename __invoke_return::type + operator()(_ArgTypes&&... __args) const { return std::__invoke(__f_, std::forward<_ArgTypes>(__args)...); } }; diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/mem_fun_ref.h b/naiveproxy/src/third_party/libc++/src/include/__functional/mem_fun_ref.h index fe43c46560..c344420b02 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/mem_fun_ref.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/mem_fun_ref.h @@ -89,8 +89,8 @@ public: }; template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_t - : public __binary_function { +class _LIBCPP_TEMPLATE_VIS +_LIBCPP_DEPRECATED_IN_CXX11 const_mem_fun1_t : public __binary_function { _Sp (_Tp::*__p_)(_Ap) const; public: diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/operations.h b/naiveproxy/src/third_party/libc++/src/include/__functional/operations.h index 240f127e54..0a6320f19d 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/operations.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/operations.h @@ -50,8 +50,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS plus { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) + std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) + std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) + std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) + std::forward<_T2>(__u)) { return std::forward<_T1>(__t) + std::forward<_T2>(__u); } typedef void is_transparent; @@ -76,8 +76,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS minus { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) - std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) - std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) - std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) - std::forward<_T2>(__u)) { return std::forward<_T1>(__t) - std::forward<_T2>(__u); } typedef void is_transparent; @@ -102,8 +102,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS multiplies { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) * std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) * std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) * std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) * std::forward<_T2>(__u)) { return std::forward<_T1>(__t) * std::forward<_T2>(__u); } typedef void is_transparent; @@ -128,8 +128,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS divides { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) / std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) / std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) / std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) / std::forward<_T2>(__u)) { return std::forward<_T1>(__t) / std::forward<_T2>(__u); } typedef void is_transparent; @@ -154,8 +154,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS modulus { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) % std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) % std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) % std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) % std::forward<_T2>(__u)) { return std::forward<_T1>(__t) % std::forward<_T2>(__u); } typedef void is_transparent; @@ -178,7 +178,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS negate { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_Tp&& __x) const - noexcept(noexcept(-std::forward<_Tp>(__x))) -> decltype(-std::forward<_Tp>(__x)) { + noexcept(noexcept(-std::forward<_Tp>(__x))) // + -> decltype(-std::forward<_Tp>(__x)) { return -std::forward<_Tp>(__x); } typedef void is_transparent; @@ -205,8 +206,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS bit_and { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) & std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) & std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) & + std::forward<_T2>(__u))) -> decltype(std::forward<_T1>(__t) & std::forward<_T2>(__u)) { return std::forward<_T1>(__t) & std::forward<_T2>(__u); } typedef void is_transparent; @@ -224,7 +225,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS bit_not { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_Tp&& __x) const - noexcept(noexcept(~std::forward<_Tp>(__x))) -> decltype(~std::forward<_Tp>(__x)) { + noexcept(noexcept(~std::forward<_Tp>(__x))) // + -> decltype(~std::forward<_Tp>(__x)) { return ~std::forward<_Tp>(__x); } typedef void is_transparent; @@ -249,8 +251,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS bit_or { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) | std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) | std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) | std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) | std::forward<_T2>(__u)) { return std::forward<_T1>(__t) | std::forward<_T2>(__u); } typedef void is_transparent; @@ -275,8 +277,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS bit_xor { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) ^ std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) ^ std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) ^ std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) ^ std::forward<_T2>(__u)) { return std::forward<_T1>(__t) ^ std::forward<_T2>(__u); } typedef void is_transparent; @@ -303,8 +305,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS equal_to { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) == std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) == std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) == std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) == std::forward<_T2>(__u)) { return std::forward<_T1>(__t) == std::forward<_T2>(__u); } typedef void is_transparent; @@ -338,8 +340,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS not_equal_to { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) != std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) != std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) != std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) != std::forward<_T2>(__u)) { return std::forward<_T1>(__t) != std::forward<_T2>(__u); } typedef void is_transparent; @@ -367,8 +369,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS less { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) < std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) < std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) < std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) < std::forward<_T2>(__u)) { return std::forward<_T1>(__t) < std::forward<_T2>(__u); } typedef void is_transparent; @@ -396,8 +398,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS less_equal { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) <= std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) <= std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) <= std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) <= std::forward<_T2>(__u)) { return std::forward<_T1>(__t) <= std::forward<_T2>(__u); } typedef void is_transparent; @@ -422,8 +424,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS greater_equal { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) >= std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) >= std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) >= + std::forward<_T2>(__u))) -> decltype(std::forward<_T1>(__t) >= std::forward<_T2>(__u)) { return std::forward<_T1>(__t) >= std::forward<_T2>(__u); } typedef void is_transparent; @@ -448,8 +450,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS greater { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) > std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) > std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) > std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) > std::forward<_T2>(__u)) { return std::forward<_T1>(__t) > std::forward<_T2>(__u); } typedef void is_transparent; @@ -476,8 +478,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS logical_and { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) && std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) && std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) && std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) && std::forward<_T2>(__u)) { return std::forward<_T1>(__t) && std::forward<_T2>(__u); } typedef void is_transparent; @@ -500,7 +502,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS logical_not { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_Tp&& __x) const - noexcept(noexcept(!std::forward<_Tp>(__x))) -> decltype(!std::forward<_Tp>(__x)) { + noexcept(noexcept(!std::forward<_Tp>(__x))) // + -> decltype(!std::forward<_Tp>(__x)) { return !std::forward<_Tp>(__x); } typedef void is_transparent; @@ -525,8 +528,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS logical_or { template _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const - noexcept(noexcept(std::forward<_T1>(__t) || std::forward<_T2>(__u))) - -> decltype(std::forward<_T1>(__t) || std::forward<_T2>(__u)) { + noexcept(noexcept(std::forward<_T1>(__t) || std::forward<_T2>(__u))) // + -> decltype(std::forward<_T1>(__t) || std::forward<_T2>(__u)) { return std::forward<_T1>(__t) || std::forward<_T2>(__u); } typedef void is_transparent; diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/pointer_to_binary_function.h b/naiveproxy/src/third_party/libc++/src/include/__functional/pointer_to_binary_function.h index 51a7c3fe0f..e345250dcd 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/pointer_to_binary_function.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/pointer_to_binary_function.h @@ -22,8 +22,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_binary_function - : public __binary_function<_Arg1, _Arg2, _Result> { +class _LIBCPP_TEMPLATE_VIS +_LIBCPP_DEPRECATED_IN_CXX11 pointer_to_binary_function : public __binary_function<_Arg1, _Arg2, _Result> { _Result (*__f_)(_Arg1, _Arg2); public: diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/pointer_to_unary_function.h b/naiveproxy/src/third_party/libc++/src/include/__functional/pointer_to_unary_function.h index 0338e76717..3a5d153d36 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/pointer_to_unary_function.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/pointer_to_unary_function.h @@ -22,8 +22,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 pointer_to_unary_function - : public __unary_function<_Arg, _Result> { +class _LIBCPP_TEMPLATE_VIS +_LIBCPP_DEPRECATED_IN_CXX11 pointer_to_unary_function : public __unary_function<_Arg, _Result> { _Result (*__f_)(_Arg); public: diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/reference_wrapper.h b/naiveproxy/src/third_party/libc++/src/include/__functional/reference_wrapper.h index 94b39e3bc7..3570e2673c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/reference_wrapper.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/reference_wrapper.h @@ -10,11 +10,14 @@ #ifndef _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H #define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H +#include <__compare/synth_three_way.h> +#include <__concepts/boolean_testable.h> #include <__config> #include <__functional/invoke.h> #include <__functional/weak_result_type.h> #include <__memory/addressof.h> #include <__type_traits/enable_if.h> +#include <__type_traits/is_const.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> @@ -36,7 +39,7 @@ private: type* __f_; static void __fun(_Tp&) _NOEXCEPT; - static void __fun(_Tp&&) = delete; + static void __fun(_Tp&&) = delete; // NOLINT(modernize-use-equals-delete) ; This is llvm.org/PR54276 public: template (__args)...); } + +#if _LIBCPP_STD_VER >= 26 + + // [refwrap.comparisons], comparisons + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y) + requires requires { + { __x.get() == __y.get() } -> __boolean_testable; + } + { + return __x.get() == __y.get(); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, const _Tp& __y) + requires requires { + { __x.get() == __y } -> __boolean_testable; + } + { + return __x.get() == __y; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y) + requires(!is_const_v<_Tp>) && requires { + { __x.get() == __y.get() } -> __boolean_testable; + } + { + return __x.get() == __y.get(); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(reference_wrapper __x, reference_wrapper __y) + requires requires { std::__synth_three_way(__x.get(), __y.get()); } + { + return std::__synth_three_way(__x.get(), __y.get()); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(reference_wrapper __x, const _Tp& __y) + requires requires { std::__synth_three_way(__x.get(), __y); } + { + return std::__synth_three_way(__x.get(), __y); + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(reference_wrapper __x, reference_wrapper __y) + requires(!is_const_v<_Tp>) && requires { std::__synth_three_way(__x.get(), __y.get()); } + { + return std::__synth_three_way(__x.get(), __y.get()); + } + +#endif // _LIBCPP_STD_VER >= 26 }; #if _LIBCPP_STD_VER >= 17 diff --git a/naiveproxy/src/third_party/libc++/src/include/__functional/unary_negate.h b/naiveproxy/src/third_party/libc++/src/include/__functional/unary_negate.h index d130b7d728..5bd487a97b 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__functional/unary_negate.h +++ b/naiveproxy/src/third_party/libc++/src/include/__functional/unary_negate.h @@ -22,8 +22,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS) template -class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 unary_negate - : public __unary_function { +class _LIBCPP_TEMPLATE_VIS +_LIBCPP_DEPRECATED_IN_CXX17 unary_negate : public __unary_function { _Predicate __pred_; public: diff --git a/naiveproxy/src/third_party/libc++/src/include/__fwd/ios.h b/naiveproxy/src/third_party/libc++/src/include/__fwd/ios.h index 82c865d58c..48350709d4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__fwd/ios.h +++ b/naiveproxy/src/third_party/libc++/src/include/__fwd/ios.h @@ -18,6 +18,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD +class _LIBCPP_EXPORTED_FROM_ABI ios_base; + template > class _LIBCPP_TEMPLATE_VIS basic_ios; diff --git a/naiveproxy/src/third_party/libc++/src/include/__fwd/memory_resource.h b/naiveproxy/src/third_party/libc++/src/include/__fwd/memory_resource.h index 03b78ad2bd..d68b2c2b63 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__fwd/memory_resource.h +++ b/naiveproxy/src/third_party/libc++/src/include/__fwd/memory_resource.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___FWD_MEMORY_RESOURCE_H #define _LIBCPP___FWD_MEMORY_RESOURCE_H -#include <__availability> #include <__config> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/naiveproxy/src/third_party/libc++/src/include/__fwd/string.h b/naiveproxy/src/third_party/libc++/src/include/__fwd/string.h index 320c4e4c81..2418e1f9b2 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__fwd/string.h +++ b/naiveproxy/src/third_party/libc++/src/include/__fwd/string.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___FWD_STRING_H #define _LIBCPP___FWD_STRING_H -#include <__availability> #include <__config> #include <__fwd/memory.h> #include <__fwd/memory_resource.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__hash_table b/naiveproxy/src/third_party/libc++/src/include/__hash_table index a705117d01..0257585285 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__hash_table +++ b/naiveproxy/src/third_party/libc++/src/include/__hash_table @@ -240,9 +240,9 @@ public: private: static_assert(!is_const<__node_type>::value, "_NodePtr should never be a pointer to const"); - static_assert((is_same::element_type, void>::value), + static_assert(is_same::element_type, void>::value, "_VoidPtr does not point to unqualified void type"); - static_assert((is_same<__rebind_pointer_t<_VoidPtr, __node_type>, _NodePtr>::value), + static_assert(is_same<__rebind_pointer_t<_VoidPtr, __node_type>, _NodePtr>::value, "_VoidPtr does not rebind to _NodePtr."); }; @@ -700,11 +700,11 @@ private: // check for sane allocator pointer rebinding semantics. Rebinding the // allocator for a new pointer type should be exactly the same as rebinding // the pointer using 'pointer_traits'. - static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value), + static_assert(is_same<__node_pointer, typename __node_traits::pointer>::value, "Allocator does not rebind pointers in a sane manner."); typedef __rebind_alloc<__node_traits, __first_node> __node_base_allocator; typedef allocator_traits<__node_base_allocator> __node_base_traits; - static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value), + static_assert(is_same<__node_base_pointer, typename __node_base_traits::pointer>::value, "Allocator does not rebind pointers in a sane manner."); private: @@ -928,13 +928,12 @@ public: _LIBCPP_HIDE_FROM_ABI void swap(__hash_table& __u) #if _LIBCPP_STD_VER <= 11 - _NOEXCEPT_(__is_nothrow_swappable::value&& __is_nothrow_swappable::value && + _NOEXCEPT_(__is_nothrow_swappable_v&& __is_nothrow_swappable_v && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value || - __is_nothrow_swappable<__pointer_allocator>::value) && - (!__node_traits::propagate_on_container_swap::value || - __is_nothrow_swappable<__node_allocator>::value)); + __is_nothrow_swappable_v<__pointer_allocator>) && + (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>)); #else - _NOEXCEPT_(__is_nothrow_swappable::value&& __is_nothrow_swappable::value); + _NOEXCEPT_(__is_nothrow_swappable_v&& __is_nothrow_swappable_v); #endif _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return max_size(); } @@ -1101,8 +1100,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, const template __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() { #if defined(_LIBCPP_CXX03_LANG) - static_assert((is_copy_constructible::value), "Predicate must be copy-constructible."); - static_assert((is_copy_constructible::value), "Hasher must be copy-constructible."); + static_assert(is_copy_constructible::value, "Predicate must be copy-constructible."); + static_assert(is_copy_constructible::value, "Hasher must be copy-constructible."); #endif __deallocate_node(__p1_.first().__next_); @@ -1228,7 +1227,7 @@ template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, _InputIterator __last) { typedef iterator_traits<_InputIterator> _ITraits; typedef typename _ITraits::value_type _ItValueType; - static_assert((is_same<_ItValueType, __container_value_type>::value), + static_assert(is_same<_ItValueType, __container_value_type>::value, "__assign_unique may only be called with the containers value type"); if (bucket_count() != 0) { @@ -1985,12 +1984,12 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(const _Key& __k) c template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) #if _LIBCPP_STD_VER <= 11 - _NOEXCEPT_(__is_nothrow_swappable::value&& __is_nothrow_swappable::value && + _NOEXCEPT_(__is_nothrow_swappable_v&& __is_nothrow_swappable_v && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value || - __is_nothrow_swappable<__pointer_allocator>::value) && - (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__node_allocator>::value)) + __is_nothrow_swappable_v<__pointer_allocator>) && + (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>)) #else - _NOEXCEPT_(__is_nothrow_swappable::value&& __is_nothrow_swappable::value) + _NOEXCEPT_(__is_nothrow_swappable_v&& __is_nothrow_swappable_v) #endif { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/access.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/access.h index 5c6090eeb4..acc4f60bf6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/access.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/access.h @@ -54,8 +54,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto end(const _Cp& __c) -> # if _LIBCPP_STD_VER >= 14 template -_LIBCPP_HIDE_FROM_ABI constexpr auto cbegin(const _Cp& __c) noexcept(noexcept(std::begin(__c))) - -> decltype(std::begin(__c)) { +_LIBCPP_HIDE_FROM_ABI constexpr auto +cbegin(const _Cp& __c) noexcept(noexcept(std::begin(__c))) -> decltype(std::begin(__c)) { return std::begin(__c); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/aliasing_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/aliasing_iterator.h new file mode 100644 index 0000000000..94ba577078 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/aliasing_iterator.h @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_ALIASING_ITERATOR_H +#define _LIBCPP___ITERATOR_ALIASING_ITERATOR_H + +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/pointer_traits.h> +#include <__type_traits/is_trivial.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// This iterator wrapper is used to type-pun an iterator to return a different type. This is done without UB by not +// actually punning the type, but instead inspecting the object representation of the base type and copying that into +// an instance of the alias type. For that reason the alias type has to be trivial. The alias is returned as a prvalue +// when derferencing the iterator, since it is temporary storage. This wrapper is used to vectorize some algorithms. + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __aliasing_iterator_wrapper { + class __iterator { + _BaseIter __base_ = nullptr; + + using __iter_traits = iterator_traits<_BaseIter>; + using __base_value_type = typename __iter_traits::value_type; + + static_assert(__has_random_access_iterator_category<_BaseIter>::value, + "The base iterator has to be a random access iterator!"); + + public: + using iterator_category = random_access_iterator_tag; + using value_type = _Alias; + using difference_type = ptrdiff_t; + using reference = value_type&; + using pointer = value_type*; + + static_assert(is_trivial::value); + static_assert(sizeof(__base_value_type) == sizeof(value_type)); + + _LIBCPP_HIDE_FROM_ABI __iterator() = default; + _LIBCPP_HIDE_FROM_ABI __iterator(_BaseIter __base) _NOEXCEPT : __base_(__base) {} + + _LIBCPP_HIDE_FROM_ABI __iterator& operator++() _NOEXCEPT { + ++__base_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __iterator operator++(int) _NOEXCEPT { + __iterator __tmp(*this); + ++__base_; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI __iterator& operator--() _NOEXCEPT { + --__base_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __iterator operator--(int) _NOEXCEPT { + __iterator __tmp(*this); + --__base_; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(__iterator __iter, difference_type __n) _NOEXCEPT { + return __iterator(__iter.__base_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(difference_type __n, __iterator __iter) _NOEXCEPT { + return __iterator(__n + __iter.__base_); + } + + _LIBCPP_HIDE_FROM_ABI __iterator& operator+=(difference_type __n) _NOEXCEPT { + __base_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI friend __iterator operator-(__iterator __iter, difference_type __n) _NOEXCEPT { + return __iterator(__iter.__base_ - __n); + } + + _LIBCPP_HIDE_FROM_ABI friend difference_type operator-(__iterator __lhs, __iterator __rhs) _NOEXCEPT { + return __lhs.__base_ - __rhs.__base_; + } + + _LIBCPP_HIDE_FROM_ABI __iterator& operator-=(difference_type __n) _NOEXCEPT { + __base_ -= __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI _BaseIter __base() const _NOEXCEPT { return __base_; } + + _LIBCPP_HIDE_FROM_ABI _Alias operator*() const _NOEXCEPT { + _Alias __val; + __builtin_memcpy(&__val, std::__to_address(__base_), sizeof(value_type)); + return __val; + } + + _LIBCPP_HIDE_FROM_ABI value_type operator[](difference_type __n) const _NOEXCEPT { return *(*this + __n); } + + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __lhs, const __iterator& __rhs) _NOEXCEPT { + return __lhs.__base_ == __rhs.__base_; + } + + _LIBCPP_HIDE_FROM_ABI friend bool operator!=(const __iterator& __lhs, const __iterator& __rhs) _NOEXCEPT { + return __lhs.__base_ != __rhs.__base_; + } + }; +}; + +// This is required to avoid ADL instantiations on _BaseT +template +using __aliasing_iterator = typename __aliasing_iterator_wrapper<_BaseT, _Alias>::__iterator; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_ALIASING_ITERATOR_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/bounded_iter.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/bounded_iter.h index a1a941ffba..a8f66f4a01 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/bounded_iter.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/bounded_iter.h @@ -84,8 +84,8 @@ private: // // Since it is non-standard for iterators to have this constructor, __bounded_iter must // be created via `std::__make_bounded_iter`. - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __bounded_iter( - _Iterator __current, _Iterator __begin, _Iterator __end) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __bounded_iter(_Iterator __current, _Iterator __begin, _Iterator __end) : __current_(__current), __begin_(__begin), __end_(__end) { _LIBCPP_ASSERT_INTERNAL( __begin <= __current, "__bounded_iter(current, begin, end): current and begin are inconsistent"); diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/common_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/common_iterator.h index 7b3f4610d5..199de2cc73 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/common_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/common_iterator.h @@ -124,7 +124,7 @@ public: } template - _LIBCPP_HIDE_FROM_ABI decltype(auto) operator->() const + _LIBCPP_HIDE_FROM_ABI auto operator->() const requires indirectly_readable && (requires(const _I2& __i) { __i.operator->(); } || is_reference_v> || constructible_from, iter_reference_t<_I2>>) diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/counted_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/counted_iterator.h index 008c52fa87..ea2832e3b9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/counted_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/counted_iterator.h @@ -129,7 +129,7 @@ public: return *this; } - _LIBCPP_HIDE_FROM_ABI decltype(auto) operator++(int) { + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator++(int) { _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator already at or past end."); --__count_; # ifndef _LIBCPP_HAS_NO_EXCEPTIONS diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/cpp17_iterator_concepts.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/cpp17_iterator_concepts.h index cdb561e684..ba3536b686 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/cpp17_iterator_concepts.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/cpp17_iterator_concepts.h @@ -68,7 +68,7 @@ concept __cpp17_default_constructible = is_default_constructible_v<_Tp>; template concept __cpp17_iterator = __cpp17_copy_constructible<_Iter> && __cpp17_copy_assignable<_Iter> && __cpp17_destructible<_Iter> && - (is_signed_v<__iter_diff_t<_Iter>> || is_void_v<__iter_diff_t<_Iter>>)&&requires(_Iter __iter) { + (is_signed_v<__iter_diff_t<_Iter>> || is_void_v<__iter_diff_t<_Iter>>) && requires(_Iter __iter) { { *__iter }; { ++__iter } -> same_as<_Iter&>; }; @@ -157,29 +157,31 @@ concept __cpp17_random_access_iterator = _LIBCPP_END_NAMESPACE_STD # ifndef _LIBCPP_DISABLE_ITERATOR_CHECKS -# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) static_assert(::std::__cpp17_input_iterator); -# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) \ - static_assert(::std::__cpp17_output_iterator); -# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) static_assert(::std::__cpp17_forward_iterator); -# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) \ - static_assert(::std::__cpp17_bidirectional_iterator); -# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) \ - static_assert(::std::__cpp17_random_access_iterator); +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) \ + static_assert(::std::__cpp17_input_iterator, message) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) \ + static_assert(::std::__cpp17_output_iterator, message) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) \ + static_assert(::std::__cpp17_forward_iterator, message) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) \ + static_assert(::std::__cpp17_bidirectional_iterator, message) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) \ + static_assert(::std::__cpp17_random_access_iterator, message) # else -# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) -# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) -# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) -# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) -# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) static_assert(true) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) static_assert(true) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) static_assert(true) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) static_assert(true) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) static_assert(true) # endif #else // _LIBCPP_STD_VER >= 20 -# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) -# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) -# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) -# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) -# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t, message) static_assert(true) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t, message) static_assert(true) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t, message) static_assert(true) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t, message) static_assert(true) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t, message) static_assert(true) #endif // _LIBCPP_STD_VER >= 20 diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/data.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/data.h index 3986739061..b7c1603652 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/data.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/data.h @@ -23,12 +23,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -constexpr _LIBCPP_HIDE_FROM_ABI auto data(_Cont& __c) _NOEXCEPT_(noexcept(__c.data())) -> decltype(__c.data()) { +constexpr _LIBCPP_HIDE_FROM_ABI auto data(_Cont& __c) noexcept(noexcept(__c.data())) -> decltype(__c.data()) { return __c.data(); } template -constexpr _LIBCPP_HIDE_FROM_ABI auto data(const _Cont& __c) _NOEXCEPT_(noexcept(__c.data())) -> decltype(__c.data()) { +constexpr _LIBCPP_HIDE_FROM_ABI auto data(const _Cont& __c) noexcept(noexcept(__c.data())) -> decltype(__c.data()) { return __c.data(); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/empty.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/empty.h index 3ca0aff6be..773f277695 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/empty.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/empty.h @@ -23,18 +23,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr auto empty(const _Cont& __c) - _NOEXCEPT_(noexcept(__c.empty())) -> decltype(__c.empty()) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto +empty(const _Cont& __c) noexcept(noexcept(__c.empty())) -> decltype(__c.empty()) { return __c.empty(); } template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr bool empty(const _Tp (&)[_Sz]) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty(const _Tp (&)[_Sz]) noexcept { return false; } template -_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI constexpr bool empty(initializer_list<_Ep> __il) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() == 0; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/iter_swap.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/iter_swap.h index 52c3f095e7..01ab1b97d6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/iter_swap.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/iter_swap.h @@ -42,7 +42,7 @@ void iter_swap(_I1, _I2) = delete; template concept __unqualified_iter_swap = - (__class_or_enum> || __class_or_enum>)&&requires(_T1&& __x, _T2&& __y) { + (__class_or_enum> || __class_or_enum>) && requires(_T1&& __x, _T2&& __y) { // NOLINTNEXTLINE(libcpp-robust-against-adl) iter_swap ADL calls should only be made through ranges::iter_swap iter_swap(std::forward<_T1>(__x), std::forward<_T2>(__y)); }; diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/move_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/move_iterator.h index eefd5b3748..a1c53e9bd2 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/move_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/move_iterator.h @@ -105,9 +105,8 @@ public: typedef iterator_type pointer; typedef typename iterator_traits::reference __reference; - typedef typename conditional< is_reference<__reference>::value, - __libcpp_remove_reference_t<__reference>&&, - __reference >::type reference; + typedef __conditional_t::value, __libcpp_remove_reference_t<__reference>&&, __reference> + reference; #endif // _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {} @@ -292,8 +291,8 @@ operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { #if _LIBCPP_STD_VER >= 20 template _Iter2> inline _LIBCPP_HIDE_FROM_ABI constexpr auto -operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) - -> compare_three_way_result_t<_Iter1, _Iter2> { +operator<=>(const move_iterator<_Iter1>& __x, + const move_iterator<_Iter2>& __y) -> compare_three_way_result_t<_Iter1, _Iter2> { return __x.base() <=> __y.base(); } #endif // _LIBCPP_STD_VER >= 20 @@ -330,6 +329,12 @@ operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterato } #endif // _LIBCPP_STD_VER >= 20 +#if _LIBCPP_STD_VER >= 20 +template + requires(!sized_sentinel_for<_Iter1, _Iter2>) +inline constexpr bool disable_sized_sentinel_for, move_iterator<_Iter2>> = true; +#endif // _LIBCPP_STD_VER >= 20 + template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator<_Iter> make_move_iterator(_Iter __i) { return move_iterator<_Iter>(std::move(__i)); diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/reverse_iterator.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/reverse_iterator.h index 2ae1461934..50c0f21eaa 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/reverse_iterator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/reverse_iterator.h @@ -184,7 +184,7 @@ public: #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const reverse_iterator& __i) noexcept( - is_nothrow_copy_constructible_v<_Iter>&& noexcept(ranges::iter_move(--std::declval<_Iter&>()))) { + is_nothrow_copy_constructible_v<_Iter> && noexcept(ranges::iter_move(--std::declval<_Iter&>()))) { auto __tmp = __i.base(); return ranges::iter_move(--__tmp); } @@ -192,9 +192,8 @@ public: template _Iter2> _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap(const reverse_iterator& __x, const reverse_iterator<_Iter2>& __y) noexcept( - is_nothrow_copy_constructible_v<_Iter> && - is_nothrow_copy_constructible_v<_Iter2>&& noexcept( - ranges::iter_swap(--std::declval<_Iter&>(), --std::declval<_Iter2&>()))) { + is_nothrow_copy_constructible_v<_Iter> && is_nothrow_copy_constructible_v<_Iter2> && + noexcept(ranges::iter_swap(--std::declval<_Iter&>(), --std::declval<_Iter2&>()))) { auto __xtmp = __x.base(); auto __ytmp = __y.base(); ranges::iter_swap(--__xtmp, --__ytmp); @@ -285,8 +284,8 @@ operator<=>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto -operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) - -> decltype(__y.base() - __x.base()) { +operator-(const reverse_iterator<_Iter1>& __x, + const reverse_iterator<_Iter2>& __y) -> decltype(__y.base() - __x.base()) { return __y.base() - __x.base(); } #else diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/size.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/size.h index eac3ccf522..876e6963f7 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/size.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/size.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 template -_LIBCPP_HIDE_FROM_ABI constexpr auto size(const _Cont& __c) _NOEXCEPT_(noexcept(__c.size())) -> decltype(__c.size()) { +_LIBCPP_HIDE_FROM_ABI constexpr auto size(const _Cont& __c) noexcept(noexcept(__c.size())) -> decltype(__c.size()) { return __c.size(); } @@ -35,9 +35,9 @@ _LIBCPP_HIDE_FROM_ABI constexpr size_t size(const _Tp (&)[_Sz]) noexcept { # if _LIBCPP_STD_VER >= 20 template -_LIBCPP_HIDE_FROM_ABI constexpr auto ssize(const _Cont& __c) - _NOEXCEPT_(noexcept(static_cast>>(__c.size()))) - -> common_type_t> { +_LIBCPP_HIDE_FROM_ABI constexpr auto +ssize(const _Cont& __c) noexcept(noexcept(static_cast>>( + __c.size()))) -> common_type_t> { return static_cast>>(__c.size()); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__iterator/wrap_iter.h b/naiveproxy/src/third_party/libc++/src/include/__iterator/wrap_iter.h index 3124826189..252d13b26c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__iterator/wrap_iter.h +++ b/naiveproxy/src/third_party/libc++/src/include/__iterator/wrap_iter.h @@ -186,8 +186,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT->decltype(__x.base() - __y.base()) #else - typename __wrap_iter<_Iter1>::difference_type - operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT +typename __wrap_iter<_Iter1>::difference_type +operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT #endif // C++03 { return __x.base() - __y.base(); diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale b/naiveproxy/src/third_party/libc++/src/include/__locale index 36ac099d65..4b382764b4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale +++ b/naiveproxy/src/third_party/libc++/src/include/__locale @@ -49,6 +49,9 @@ _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&); class _LIBCPP_EXPORTED_FROM_ABI locale { public: + // locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor. + using __trivially_relocatable = locale; + // types: class _LIBCPP_EXPORTED_FROM_ABI facet; class _LIBCPP_EXPORTED_FROM_ABI id; @@ -343,12 +346,12 @@ public: static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA -#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) +#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) # ifdef __APPLE__ typedef __uint32_t mask; # elif defined(__FreeBSD__) typedef unsigned long mask; -# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__) +# elif defined(__NetBSD__) typedef unsigned short mask; # endif static const mask space = _CTYPE_S; diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api.h index 2355b4a840..8c000c558c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api.h @@ -95,18 +95,4 @@ except that locale_t is used instead of the current global locale. The variadic functions may be implemented as templates with a parameter pack instead of variadic functions. */ -/* -// TODO: These symbols are never actually used, but defined by one or more implementations. They should be removed. -long strtol_l(const char* str, char** str_end, locale_t); -unsigned long strtoul_l(const char* str, char** str_end, locale_t); -long long wcstoll_l(const wchar_t* str, wchar_t** str_end, int base, locale_t); -unsigned long long wcstoull_l(const wchar_t* str, wchar_t** str_end, int base, locale_t); -long double wcstold_l(const wchar_t* str, wchar_t** str_end, int base, locale_t); -int sprintf_l(char* str, const char* format, locale_t, ...); -int vsprintf_l(char* str, const char* format, locale_t, va_list); -int vsnprintf_l(char* str, size_t size, const char* format, locale_t, va_list); -int isblank_l(int ch, locale_t); - -*/ - #endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/android.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/android.h index c2dea1e731..9965d8bbf6 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/android.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/android.h @@ -10,63 +10,41 @@ #ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_ANDROID_H #define _LIBCPP___LOCALE_LOCALE_BASE_API_ANDROID_H -#if defined(__BIONIC__) +#include -# ifdef __cplusplus +// FIXME: Is this actually required? extern "C" { -# endif - -# include -# include - -# ifdef __cplusplus +#include } -# endif -# if defined(__ANDROID__) - -# include -# if __ANDROID_API__ < 21 -# include <__support/xlocale/__posix_l_fallback.h> -# endif +#include +#if __ANDROID_API__ < 21 +# include <__support/xlocale/__posix_l_fallback.h> +#endif // If we do not have this header, we are in a platform build rather than an NDK // build, which will always be at least as new as the ToT NDK, in which case we // don't need any of the inlines below since libc provides them. -# if __has_include() -# include +#if __has_include() +# include // In NDK versions later than 16, locale-aware functions are provided by // legacy_stdlib_inlines.h -# if __NDK_MAJOR__ <= 16 -# if __ANDROID_API__ < 21 -# include <__support/xlocale/__strtonum_fallback.h> -# elif __ANDROID_API__ < 26 +# if __NDK_MAJOR__ <= 16 +# if __ANDROID_API__ < 21 +# include <__support/xlocale/__strtonum_fallback.h> +# elif __ANDROID_API__ < 26 -# if defined(__cplusplus) -extern "C" { -# endif - -inline _LIBCPP_HIDE_FROM_ABI_C float strtof_l(const char* __nptr, char** __endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI float strtof_l(const char* __nptr, char** __endptr, locale_t) { return ::strtof(__nptr, __endptr); } -inline _LIBCPP_HIDE_FROM_ABI_C double strtod_l(const char* __nptr, char** __endptr, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI double strtod_l(const char* __nptr, char** __endptr, locale_t) { return ::strtod(__nptr, __endptr); } -inline _LIBCPP_HIDE_FROM_ABI_C long strtol_l(const char* __nptr, char** __endptr, int __base, locale_t) { - return ::strtol(__nptr, __endptr, __base); -} +# endif // __ANDROID_API__ < 26 -# if defined(__cplusplus) -} -# endif +# endif // __NDK_MAJOR__ <= 16 +#endif // __has_include() -# endif // __ANDROID_API__ < 26 - -# endif // __NDK_MAJOR__ <= 16 -# endif // __has_include() -# endif // defined(__ANDROID__) - -#endif // defined(__BIONIC__) #endif // _LIBCPP___LOCALE_LOCALE_BASE_API_ANDROID_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/fuchsia.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/fuchsia.h index f999bead23..4c3440f981 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/fuchsia.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/fuchsia.h @@ -10,13 +10,9 @@ #ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_FUCHSIA_H #define _LIBCPP___LOCALE_LOCALE_BASE_API_FUCHSIA_H -#if defined(__Fuchsia__) - -# include <__support/xlocale/__posix_l_fallback.h> -# include <__support/xlocale/__strtonum_fallback.h> -# include -# include - -#endif // defined(__Fuchsia__) +#include <__support/xlocale/__posix_l_fallback.h> +#include <__support/xlocale/__strtonum_fallback.h> +#include +#include #endif // _LIBCPP___LOCALE_LOCALE_BASE_API_FUCHSIA_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/ibm.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/ibm.h index c5d7f34186..01af201944 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/ibm.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/ibm.h @@ -20,10 +20,6 @@ #include "cstdlib" -#ifdef __cplusplus -extern "C" { -#endif - #if defined(__MVS__) # include // POSIX routines @@ -62,11 +58,6 @@ inline _LIBCPP_HIDE_FROM_ABI long long strtoll_l(const char* __nptr, char** __en return ::strtoll(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI long strtol_l(const char* __nptr, char** __endptr, int __base, locale_t locale) { - __setAndRestore __newloc(locale); - return ::strtol(__nptr, __endptr, __base); -} - inline _LIBCPP_HIDE_FROM_ABI double strtod_l(const char* __nptr, char** __endptr, locale_t locale) { __setAndRestore __newloc(locale); return ::strtod(__nptr, __endptr); @@ -88,12 +79,8 @@ strtoull_l(const char* __nptr, char** __endptr, int __base, locale_t locale) { return ::strtoull(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI unsigned long strtoul_l(const char* __nptr, char** __endptr, int __base, locale_t locale) { - __setAndRestore __newloc(locale); - return ::strtoul(__nptr, __endptr, __base); -} - -inline _LIBCPP_HIDE_FROM_ABI int vasprintf(char** strp, const char* fmt, va_list ap) { +inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_ATTRIBUTE_FORMAT(__printf__, 2, 0) int vasprintf(char** strp, const char* fmt, va_list ap) { const size_t buff_size = 256; if ((*strp = (char*)malloc(buff_size)) == NULL) { return -1; @@ -118,7 +105,4 @@ inline _LIBCPP_HIDE_FROM_ABI int vasprintf(char** strp, const char* fmt, va_list return str_size; } -#ifdef __cplusplus -} -#endif #endif // _LIBCPP___LOCALE_LOCALE_BASE_API_IBM_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/locale_guard.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/locale_guard.h index b7e3be756e..2baacb51cd 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/locale_guard.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/locale_guard.h @@ -30,9 +30,8 @@ struct __libcpp_locale_guard { locale_t __old_loc_; -private: - __libcpp_locale_guard(__libcpp_locale_guard const&); - __libcpp_locale_guard& operator=(__libcpp_locale_guard const&); + __libcpp_locale_guard(__libcpp_locale_guard const&) = delete; + __libcpp_locale_guard& operator=(__libcpp_locale_guard const&) = delete; }; #elif defined(_LIBCPP_MSVCRT_LIKE) struct __libcpp_locale_guard { diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/musl.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/musl.h index e4121ec1a9..bf7b849d58 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/musl.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/musl.h @@ -20,34 +20,12 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif - -inline _LIBCPP_HIDE_FROM_ABI_C long long strtoll_l(const char* __nptr, char** __endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI long long strtoll_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtoll(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI_C unsigned long long -strtoull_l(const char* __nptr, char** __endptr, int __base, locale_t) { +inline _LIBCPP_HIDE_FROM_ABI unsigned long long strtoull_l(const char* __nptr, char** __endptr, int __base, locale_t) { return ::strtoull(__nptr, __endptr, __base); } -inline _LIBCPP_HIDE_FROM_ABI_C long long wcstoll_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) { - return ::wcstoll(__nptr, __endptr, __base); -} - -inline _LIBCPP_HIDE_FROM_ABI_C unsigned long long -wcstoull_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) { - return ::wcstoull(__nptr, __endptr, __base); -} - -inline _LIBCPP_HIDE_FROM_ABI_C long double wcstold_l(const wchar_t* __nptr, wchar_t** __endptr, locale_t) { - return ::wcstold(__nptr, __endptr); -} - -#ifdef __cplusplus -} -#endif - #endif // _LIBCPP___LOCALE_LOCALE_BASE_API_MUSL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/newlib.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/newlib.h index 8d030cb732..a8c1cff16e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/newlib.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/newlib.h @@ -9,14 +9,4 @@ #ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_NEWLIB_H #define _LIBCPP___LOCALE_LOCALE_BASE_API_NEWLIB_H -#if defined(_NEWLIB_VERSION) - -# if !defined(__NEWLIB__) || __NEWLIB__ < 2 || __NEWLIB__ == 2 && __NEWLIB_MINOR__ < 5 -# include <__support/xlocale/__nop_locale_mgmt.h> -# include <__support/xlocale/__posix_l_fallback.h> -# include <__support/xlocale/__strtonum_fallback.h> -# endif - -#endif // _NEWLIB_VERSION - #endif // _LIBCPP___LOCALE_LOCALE_BASE_API_NEWLIB_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/openbsd.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/openbsd.h index 623abdb4db..0c05d6a0f7 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/openbsd.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/openbsd.h @@ -16,20 +16,4 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif - -inline _LIBCPP_HIDE_FROM_ABI_C long strtol_l(const char* __nptr, char** __endptr, int __base, locale_t) { - return ::strtol(__nptr, __endptr, __base); -} - -inline _LIBCPP_HIDE_FROM_ABI_C unsigned long strtoul_l(const char* __nptr, char** __endptr, int __base, locale_t) { - return ::strtoul(__nptr, __endptr, __base); -} - -#ifdef __cplusplus -} -#endif - #endif // _LIBCPP___LOCALE_LOCALE_BASE_API_OPENBSD_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/win32.h b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/win32.h index 5dfacfb9c1..f66baffb69 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/win32.h +++ b/naiveproxy/src/third_party/libc++/src/include/__locale_dir/locale_base_api/win32.h @@ -225,15 +225,11 @@ _LIBCPP_EXPORTED_FROM_ABI size_t strftime_l(char* ret, size_t n, const char* for # define strftime_l _strftime_l #endif #define sscanf_l(__s, __l, __f, ...) _sscanf_l(__s, __f, __l, __VA_ARGS__) -#define sprintf_l(__s, __l, __f, ...) _sprintf_l(__s, __f, __l, __VA_ARGS__) -#define vsprintf_l(__s, __l, __f, ...) _vsprintf_l(__s, __f, __l, __VA_ARGS__) -#define vsnprintf_l(__s, __n, __l, __f, ...) _vsnprintf_l(__s, __n, __f, __l, __VA_ARGS__) _LIBCPP_EXPORTED_FROM_ABI int snprintf_l(char* __ret, size_t __n, locale_t __loc, const char* __format, ...); _LIBCPP_EXPORTED_FROM_ABI int asprintf_l(char** __ret, locale_t __loc, const char* __format, ...); _LIBCPP_EXPORTED_FROM_ABI int vasprintf_l(char** __ret, locale_t __loc, const char* __format, va_list __ap); // not-so-pressing FIXME: use locale to determine blank characters -inline int isblank_l(int __c, locale_t /*loc*/) { return (__c == ' ' || __c == '\t'); } inline int iswblank_l(wint_t __c, locale_t /*loc*/) { return (__c == L' ' || __c == L'\t'); } #endif // _LIBCPP___LOCALE_LOCALE_BASE_API_WIN32_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/abs.h b/naiveproxy/src/third_party/libc++/src/include/__math/abs.h index 6004690f4c..ab82a2800f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/abs.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/abs.h @@ -23,19 +23,19 @@ namespace __math { // fabs -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT { return __builtin_fabsf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fabs(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fabs(double __x) _NOEXCEPT { return __builtin_fabs(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT { return __builtin_fabsl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double fabs(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double fabs(_A1 __x) _NOEXCEPT { return __builtin_fabs((double)__x); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/copysign.h b/naiveproxy/src/third_party/libc++/src/include/__math/copysign.h index 2219297e8b..b38690bb58 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/copysign.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/copysign.h @@ -25,17 +25,16 @@ namespace __math { // copysign -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float copysign(float __x, float __y) _NOEXCEPT { return ::__builtin_copysignf(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double copysign(long double __x, long double __y) _NOEXCEPT { return ::__builtin_copysignl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type -copysign(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type copysign(_A1 __x, _A2 __y) _NOEXCEPT { return ::__builtin_copysign(__x, __y); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/exponential_functions.h b/naiveproxy/src/third_party/libc++/src/include/__math/exponential_functions.h index f8d611b9e4..109c334997 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/exponential_functions.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/exponential_functions.h @@ -160,7 +160,7 @@ inline _LIBCPP_HIDE_FROM_ABI long double pow(long double __x, long double __y) _ template ::value && is_arithmetic<_A2>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type pow(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::pow((__result_type)__x, (__result_type)__y); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/fdim.h b/naiveproxy/src/third_party/libc++/src/include/__math/fdim.h index 6f90809302..dc1b4ecc07 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/fdim.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/fdim.h @@ -37,7 +37,7 @@ inline _LIBCPP_HIDE_FROM_ABI long double fdim(long double __x, long double __y) template ::value && is_arithmetic<_A2>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fdim(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fdim((__result_type)__x, (__result_type)__y); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/fma.h b/naiveproxy/src/third_party/libc++/src/include/__math/fma.h index 9e14f72dca..6ba7a5a2d2 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/fma.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/fma.h @@ -42,9 +42,9 @@ template ::value && is_arithmetic<_A2>::value && is_arithmetic<_A3>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2, _A3>::type fma(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2, _A3>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value && - _IsSame<_A3, __result_type>::value)), - ""); + static_assert( + !(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value && _IsSame<_A3, __result_type>::value), + ""); return __builtin_fma((__result_type)__x, (__result_type)__y, (__result_type)__z); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/hypot.h b/naiveproxy/src/third_party/libc++/src/include/__math/hypot.h index 8e2c0f5b6b..1bf193a9ab 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/hypot.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/hypot.h @@ -37,7 +37,7 @@ inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y) template ::value && is_arithmetic<_A2>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type hypot(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::hypot((__result_type)__x, (__result_type)__y); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/inverse_trigonometric_functions.h b/naiveproxy/src/third_party/libc++/src/include/__math/inverse_trigonometric_functions.h index 30b1440b0b..cd98b46a6a 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/inverse_trigonometric_functions.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/inverse_trigonometric_functions.h @@ -88,7 +88,7 @@ inline _LIBCPP_HIDE_FROM_ABI long double atan2(long double __y, long double __x) template ::value && is_arithmetic<_A2>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type atan2(_A1 __y, _A2 __x) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::atan2((__result_type)__y, (__result_type)__x); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/min_max.h b/naiveproxy/src/third_party/libc++/src/include/__math/min_max.h index 381b2af4a5..27997b4491 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/min_max.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/min_max.h @@ -25,45 +25,45 @@ namespace __math { // fmax -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { return __builtin_fmaxf(__x, __y); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fmax(double __x, double __y) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fmax(double __x, double __y) _NOEXCEPT { return __builtin_fmax(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fmax(long double __x, long double __y) _NOEXCEPT { return __builtin_fmaxl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmax(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmax(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmax((__result_type)__x, (__result_type)__y); } // fmin -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float fmin(float __x, float __y) _NOEXCEPT { return __builtin_fminf(__x, __y); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fmin(double __x, double __y) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double fmin(double __x, double __y) _NOEXCEPT { return __builtin_fmin(__x, __y); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double fmin(long double __x, long double __y) _NOEXCEPT { return __builtin_fminl(__x, __y); } template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmin(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmin(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmin((__result_type)__x, (__result_type)__y); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/modulo.h b/naiveproxy/src/third_party/libc++/src/include/__math/modulo.h index f6cdb956cf..c8ea506f37 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/modulo.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/modulo.h @@ -39,7 +39,7 @@ inline _LIBCPP_HIDE_FROM_ABI long double fmod(long double __x, long double __y) template ::value && is_arithmetic<_A2>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type fmod(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::fmod((__result_type)__x, (__result_type)__y); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/remainder.h b/naiveproxy/src/third_party/libc++/src/include/__math/remainder.h index 025fb53aaa..0fbf0b8ef9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/remainder.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/remainder.h @@ -40,7 +40,7 @@ inline _LIBCPP_HIDE_FROM_ABI long double remainder(long double __x, long double template ::value && is_arithmetic<_A2>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type remainder(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::remainder((__result_type)__x, (__result_type)__y); } @@ -62,7 +62,7 @@ inline _LIBCPP_HIDE_FROM_ABI long double remquo(long double __x, long double __y template ::value && is_arithmetic<_A2>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type remquo(_A1 __x, _A2 __y, int* __z) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::remquo((__result_type)__x, (__result_type)__y, __z); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/roots.h b/naiveproxy/src/third_party/libc++/src/include/__math/roots.h index faee688bc9..359fd747cf 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/roots.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/roots.h @@ -39,19 +39,19 @@ inline _LIBCPP_HIDE_FROM_ABI double sqrt(_A1 __x) _NOEXCEPT { // cbrt -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float cbrt(float __x) _NOEXCEPT { return __builtin_cbrtf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float cbrt(float __x) _NOEXCEPT { return __builtin_cbrtf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double cbrt(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double cbrt(double __x) _NOEXCEPT { return __builtin_cbrt(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double cbrt(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double cbrt(long double __x) _NOEXCEPT { return __builtin_cbrtl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double cbrt(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double cbrt(_A1 __x) _NOEXCEPT { return __builtin_cbrt((double)__x); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/rounding_functions.h b/naiveproxy/src/third_party/libc++/src/include/__math/rounding_functions.h index 29e42fd80b..f7246ba7fe 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/rounding_functions.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/rounding_functions.h @@ -26,37 +26,37 @@ namespace __math { // ceil -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT { return __builtin_ceilf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT { return __builtin_ceilf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double ceil(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double ceil(double __x) _NOEXCEPT { return __builtin_ceil(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT { return __builtin_ceill(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double ceil(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double ceil(_A1 __x) _NOEXCEPT { return __builtin_ceil((double)__x); } // floor -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT { return __builtin_floorf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT { return __builtin_floorf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double floor(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double floor(double __x) _NOEXCEPT { return __builtin_floor(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT { return __builtin_floorl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double floor(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double floor(_A1 __x) _NOEXCEPT { return __builtin_floor((double)__x); } @@ -126,21 +126,21 @@ inline _LIBCPP_HIDE_FROM_ABI long lround(_A1 __x) _NOEXCEPT { // nearbyint -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float nearbyint(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float nearbyint(float __x) _NOEXCEPT { return __builtin_nearbyintf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double nearbyint(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double nearbyint(double __x) _NOEXCEPT { return __builtin_nearbyint(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double nearbyint(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double nearbyint(long double __x) _NOEXCEPT { return __builtin_nearbyintl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double nearbyint(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double nearbyint(_A1 __x) _NOEXCEPT { return __builtin_nearbyint((double)__x); } @@ -160,7 +160,7 @@ inline _LIBCPP_HIDE_FROM_ABI long double nextafter(long double __x, long double template ::value && is_arithmetic<_A2>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type nextafter(_A1 __x, _A2 __y) _NOEXCEPT { using __result_type = typename __promote<_A1, _A2>::type; - static_assert((!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value)), ""); + static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), ""); return __math::nextafter((__result_type)__x, (__result_type)__y); } @@ -186,55 +186,55 @@ inline _LIBCPP_HIDE_FROM_ABI double nexttoward(_A1 __x, long double __y) _NOEXCE // rint -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float rint(float __x) _NOEXCEPT { return __builtin_rintf(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float rint(float __x) _NOEXCEPT { return __builtin_rintf(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double rint(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double rint(double __x) _NOEXCEPT { return __builtin_rint(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double rint(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double rint(long double __x) _NOEXCEPT { return __builtin_rintl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double rint(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double rint(_A1 __x) _NOEXCEPT { return __builtin_rint((double)__x); } // round -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float round(float __x) _NOEXCEPT { return __builtin_round(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float round(float __x) _NOEXCEPT { return __builtin_round(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double round(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double round(double __x) _NOEXCEPT { return __builtin_round(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double round(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double round(long double __x) _NOEXCEPT { return __builtin_roundl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double round(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double round(_A1 __x) _NOEXCEPT { return __builtin_round((double)__x); } // trunc -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float trunc(float __x) _NOEXCEPT { return __builtin_trunc(__x); } +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI float trunc(float __x) _NOEXCEPT { return __builtin_trunc(__x); } template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double trunc(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI double trunc(double __x) _NOEXCEPT { return __builtin_trunc(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double trunc(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI long double trunc(long double __x) _NOEXCEPT { return __builtin_truncl(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI double trunc(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI double trunc(_A1 __x) _NOEXCEPT { return __builtin_trunc((double)__x); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__math/traits.h b/naiveproxy/src/third_party/libc++/src/include/__math/traits.h index da585af883..a448266797 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__math/traits.h +++ b/naiveproxy/src/third_party/libc++/src/include/__math/traits.h @@ -29,55 +29,55 @@ namespace __math { // signbit template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __builtin_signbit(__x); } template ::value && is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __x < 0; } template ::value && !is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { return false; } // isfinite template ::value && numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { return __builtin_isfinite((typename __promote<_A1>::type)__x); } template ::value && !numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { return true; } // isinf template ::value && numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { return __builtin_isinf((typename __promote<_A1>::type)__x); } template ::value && !numeric_limits<_A1>::has_infinity, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT { return false; } #ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { return __builtin_isinf(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isinf(double __x) _NOEXCEPT { return __builtin_isinf(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { return __builtin_isinf(__x); } #endif @@ -85,26 +85,26 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI // isnan template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { return __builtin_isnan(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { return false; } #ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { return __builtin_isnan(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isnan(double __x) _NOEXCEPT { return __builtin_isnan(__x); } -_LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { return __builtin_isnan(__x); } #endif @@ -112,19 +112,19 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI // isnormal template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { return __builtin_isnormal(__x); } template ::value, int> = 0> -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { return __x != 0; } // isgreater template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isgreater((type)__x, (type)__y); } @@ -132,7 +132,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 _ // isgreaterequal template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isgreaterequal((type)__x, (type)__y); } @@ -140,7 +140,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, // isless template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isless((type)__x, (type)__y); } @@ -148,7 +148,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) // islessequal template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_islessequal((type)__x, (type)__y); } @@ -156,7 +156,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 // islessgreater template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_islessgreater((type)__x, (type)__y); } @@ -164,7 +164,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _ // isunordered template ::value && is_arithmetic<_A2>::value, int> = 0> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { using type = typename __promote<_A1, _A2>::type; return __builtin_isunordered((type)__x, (type)__y); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__mdspan/extents.h b/naiveproxy/src/third_party/libc++/src/include/__mdspan/extents.h index f6bcd940ee..95082ef3d1 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mdspan/extents.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mdspan/extents.h @@ -137,9 +137,9 @@ private: // static mapping of indices to the position in the dynamic values array using _DynamicIdxMap = __static_partial_sums(_Values == _DynTag)...>; - template - _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence) noexcept { - return _DynamicValues{((void)Indices, 0)...}; + template + _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence<_Indices...>) noexcept { + return _DynamicValues{((void)_Indices, 0)...}; } public: @@ -165,7 +165,7 @@ public: template requires(sizeof...(_DynVals) != __size_dynamic_) _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals) { - static_assert((sizeof...(_DynVals) == __size_), "Invalid number of values."); + static_assert(sizeof...(_DynVals) == __size_, "Invalid number of values."); _TDynamic __values[__size_] = {static_cast<_TDynamic>(__vals)...}; for (size_t __i = 0; __i < __size_; __i++) { _TStatic __static_val = _StaticValues::__get(__i); @@ -185,7 +185,7 @@ public: template requires(_Size != __size_dynamic_) _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(const span<_Tp, _Size>& __vals) { - static_assert((_Size == __size_) || (__size_ == dynamic_extent)); + static_assert(_Size == __size_ || __size_ == dynamic_extent); for (size_t __i = 0; __i < __size_; __i++) { _TStatic __static_val = _StaticValues::__get(__i); if (__static_val == _DynTag) { @@ -454,9 +454,22 @@ struct __make_dextents< _IndexType, 0, extents<_IndexType, _ExtentsPack...>> { template using dextents = typename __mdspan_detail::__make_dextents<_IndexType, _Rank>::type; +# if _LIBCPP_STD_VER >= 26 +// [mdspan.extents.dims], alias template `dims` +template +using dims = dextents<_IndexType, _Rank>; +# endif + // Deduction guide for extents +# if _LIBCPP_STD_VER >= 26 template -extents(_IndexTypes...) -> extents; + requires(is_convertible_v<_IndexTypes, size_t> && ...) +explicit extents(_IndexTypes...) -> extents...>; +# else +template + requires(is_convertible_v<_IndexTypes, size_t> && ...) +explicit extents(_IndexTypes...) -> extents; +# endif namespace __mdspan_detail { diff --git a/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_left.h b/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_left.h index fd644fa0c5..d058cbccff 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_left.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_left.h @@ -67,7 +67,7 @@ private: return true; } - static_assert((extents_type::rank_dynamic() > 0) || __required_span_size_is_representable(extents_type()), + static_assert(extents_type::rank_dynamic() > 0 || __required_span_size_is_representable(extents_type()), "layout_left::mapping product of static extents must be representable as index_type."); public: diff --git a/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_right.h b/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_right.h index 8e64d07dd5..6842e9dc37 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_right.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_right.h @@ -66,7 +66,7 @@ private: return true; } - static_assert((extents_type::rank_dynamic() > 0) || __required_span_size_is_representable(extents_type()), + static_assert(extents_type::rank_dynamic() > 0 || __required_span_size_is_representable(extents_type()), "layout_right::mapping product of static extents must be representable as index_type."); public: diff --git a/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_stride.h b/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_stride.h index 77934bfa11..86148ac849 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_stride.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mdspan/layout_stride.h @@ -149,7 +149,7 @@ private: } } - static_assert((extents_type::rank_dynamic() > 0) || __required_span_size_is_representable(extents_type()), + static_assert(extents_type::rank_dynamic() > 0 || __required_span_size_is_representable(extents_type()), "layout_stride::mapping product of static extents must be representable as index_type."); public: diff --git a/naiveproxy/src/third_party/libc++/src/include/__mdspan/mdspan.h b/naiveproxy/src/third_party/libc++/src/include/__mdspan/mdspan.h index d9a0108d6d..1ff4fd4ba4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mdspan/mdspan.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mdspan/mdspan.h @@ -266,10 +266,17 @@ private: friend class mdspan; }; +# if _LIBCPP_STD_VER >= 26 template requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) -explicit mdspan(_ElementType*, _OtherIndexTypes...) - -> mdspan<_ElementType, dextents>; +explicit mdspan(_ElementType*, + _OtherIndexTypes...) -> mdspan<_ElementType, extents...>>; +# else +template + requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) +explicit mdspan(_ElementType*, + _OtherIndexTypes...) -> mdspan<_ElementType, dextents>; +# endif template requires(is_pointer_v>) diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/allocate_at_least.h b/naiveproxy/src/third_party/libc++/src/include/__memory/allocate_at_least.h index b2e5dd3ff9..df73d9a2e9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/allocate_at_least.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/allocate_at_least.h @@ -35,9 +35,9 @@ struct __allocation_result { }; template -_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR - __allocation_result::pointer> - __allocate_at_least(_Alloc& __alloc, size_t __n) { +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR __allocation_result::pointer> +__allocate_at_least(_Alloc& __alloc, size_t __n) { return {__alloc.allocate(__n), __n}; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/allocator.h b/naiveproxy/src/third_party/libc++/src/include/__memory/allocator.h index 26e5d4978b..2d8624e771 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/allocator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/allocator.h @@ -14,6 +14,7 @@ #include <__memory/addressof.h> #include <__memory/allocate_at_least.h> #include <__memory/allocator_traits.h> +#include <__type_traits/is_const.h> #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_same.h> #include <__type_traits/is_void.h> @@ -36,8 +37,6 @@ class allocator; // Specializing allocator is deprecated, but not using it. template <> class _LIBCPP_TEMPLATE_VIS allocator { -# if _LIBCPP_STD_VER <= 17 - public: _LIBCPP_DEPRECATED_IN_CXX17 typedef void* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; @@ -47,13 +46,12 @@ public: struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { typedef allocator<_Up> other; }; -# endif }; +// TODO(LLVM 20): Remove the escape hatch +# ifdef _LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST template <> class _LIBCPP_TEMPLATE_VIS allocator { -# if _LIBCPP_STD_VER <= 17 - public: _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* const_pointer; @@ -63,9 +61,9 @@ public: struct _LIBCPP_DEPRECATED_IN_CXX17 rebind { typedef allocator<_Up> other; }; -# endif }; -#endif +# endif // _LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST +#endif // _LIBCPP_STD_VER <= 17 // This class provides a non-trivial default constructor to the class that derives from it // if the condition is satisfied. @@ -94,6 +92,7 @@ struct __non_trivial_if { template class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if::value, allocator<_Tp> > { + static_assert(!is_const<_Tp>::value, "std::allocator does not support const types"); static_assert(!is_volatile<_Tp>::value, "std::allocator does not support volatile types"); public: @@ -110,7 +109,7 @@ public: template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator(const allocator<_Up>&) _NOEXCEPT {} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) { if (__n > allocator_traits::max_size(*this)) __throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { @@ -153,8 +152,7 @@ public: return std::addressof(__x); } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 _Tp* - allocate(size_t __n, const void*) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 _Tp* allocate(size_t __n, const void*) { return allocate(__n); } @@ -171,6 +169,8 @@ public: #endif }; +// TODO(LLVM 20): Remove the escape hatch +#ifdef _LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST template class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if::value, allocator > { @@ -181,16 +181,16 @@ public: typedef ptrdiff_t difference_type; typedef const _Tp value_type; typedef true_type propagate_on_container_move_assignment; -#if _LIBCPP_STD_VER <= 23 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_ALLOCATOR_MEMBERS) +# if _LIBCPP_STD_VER <= 23 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_ALLOCATOR_MEMBERS) _LIBCPP_DEPRECATED_IN_CXX23 typedef true_type is_always_equal; -#endif +# endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator() _NOEXCEPT = default; template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator(const allocator<_Up>&) _NOEXCEPT {} - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const _Tp* allocate(size_t __n) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const _Tp* allocate(size_t __n) { if (__n > allocator_traits::max_size(*this)) __throw_bad_array_new_length(); if (__libcpp_is_constant_evaluated()) { @@ -200,11 +200,11 @@ public: } } -#if _LIBCPP_STD_VER >= 23 +# if _LIBCPP_STD_VER >= 23 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result allocate_at_least(size_t __n) { return {allocate(__n), __n}; } -#endif +# endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void deallocate(const _Tp* __p, size_t __n) { if (__libcpp_is_constant_evaluated()) { @@ -215,7 +215,7 @@ public: } // C++20 Removed members -#if _LIBCPP_STD_VER <= 17 +# if _LIBCPP_STD_VER <= 17 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& reference; @@ -230,8 +230,7 @@ public: return std::addressof(__x); } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 const _Tp* - allocate(size_t __n, const void*) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 const _Tp* allocate(size_t __n, const void*) { return allocate(__n); } @@ -245,8 +244,9 @@ public: } _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI void destroy(pointer __p) { __p->~_Tp(); } -#endif +# endif }; +#endif // _LIBCPP_ENABLE_REMOVED_ALLOCATOR_CONST template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/allocator_traits.h b/naiveproxy/src/third_party/libc++/src/include/__memory/allocator_traits.h index efdaa5e4ed..ac564f0e6f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/allocator_traits.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/allocator_traits.h @@ -16,6 +16,7 @@ #include <__type_traits/enable_if.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_empty.h> +#include <__type_traits/is_same.h> #include <__type_traits/make_unsigned.h> #include <__type_traits/remove_reference.h> #include <__type_traits/void_t.h> @@ -275,13 +276,13 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits { }; #endif // _LIBCPP_CXX03_LANG - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n) { return __a.allocate(__n); } template ::value, int> = 0> - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) { _LIBCPP_SUPPRESS_DEPRECATED_PUSH return __a.allocate(__n, __hint); @@ -290,7 +291,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits { template ::value, int> = 0> - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer) { return __a.allocate(__n); } @@ -372,6 +373,14 @@ template using __rebind_alloc = typename _Traits::template rebind_alloc<_Tp>::other; #endif +template +struct __check_valid_allocator : true_type { + using _Traits = std::allocator_traits<_Alloc>; + static_assert(is_same<_Alloc, __rebind_alloc<_Traits, typename _Traits::value_type> >::value, + "[allocator.requirements] states that rebinding an allocator to the same type should result in the " + "original allocator"); +}; + // __is_default_allocator template struct __is_default_allocator : false_type {}; @@ -407,18 +416,6 @@ struct __is_cpp17_copy_insertable< __has_construct<_Alloc, typename _Alloc::value_type*, const typename _Alloc::value_type&>::value > > : __is_cpp17_move_insertable<_Alloc> {}; -// ASan choices -#ifndef _LIBCPP_HAS_NO_ASAN -# define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1 -#endif - -#ifdef _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS -template -struct __asan_annotate_container_with_allocator : true_type {}; -template -struct __asan_annotate_container_with_allocator > : true_type {}; -#endif - #undef _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/compressed_pair.h b/naiveproxy/src/third_party/libc++/src/include/__memory/compressed_pair.h index 328849d7cc..40e5cfc35f 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/compressed_pair.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/compressed_pair.h @@ -150,7 +150,7 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void swap(__compressed_pair& __x) - _NOEXCEPT_(__is_nothrow_swappable<_T1>::value&& __is_nothrow_swappable<_T2>::value) { + _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) { using std::swap; swap(first(), __x.first()); swap(second(), __x.second()); @@ -160,7 +160,7 @@ public: template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y) - _NOEXCEPT_(__is_nothrow_swappable<_T1>::value&& __is_nothrow_swappable<_T2>::value) { + _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) { __x.swap(__y); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/pointer_traits.h b/naiveproxy/src/third_party/libc++/src/include/__memory/pointer_traits.h index 1082e37853..fcd2c3edd9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/pointer_traits.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/pointer_traits.h @@ -202,16 +202,16 @@ struct _IsFancyPointer { // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers template , _IsFancyPointer<_Pointer> >::value, int> = 0> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR - __decay_t::__call(std::declval()))> - __to_address(const _Pointer& __p) _NOEXCEPT { +_LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR __decay_t::__call(std::declval()))> +__to_address(const _Pointer& __p) _NOEXCEPT { return __to_address_helper<_Pointer>::__call(__p); } template struct __to_address_helper { - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static decltype(std::__to_address( - std::declval().operator->())) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR static decltype(std::__to_address(std::declval().operator->())) __call(const _Pointer& __p) _NOEXCEPT { return std::__to_address(__p.operator->()); } @@ -220,8 +220,8 @@ struct __to_address_helper { template struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(std::declval()))> { - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static decltype(pointer_traits<_Pointer>::to_address( - std::declval())) + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR static decltype(pointer_traits<_Pointer>::to_address(std::declval())) __call(const _Pointer& __p) _NOEXCEPT { return pointer_traits<_Pointer>::to_address(__p); } @@ -234,8 +234,8 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(_Tp* __p) noexcept { } template -inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(const _Pointer& __p) noexcept - -> decltype(std::__to_address(__p)) { +inline _LIBCPP_HIDE_FROM_ABI constexpr auto +to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) { return std::__to_address(__p); } #endif diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/shared_ptr.h b/naiveproxy/src/third_party/libc++/src/include/__memory/shared_ptr.h index a8ff189df2..d487e4fbe3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/shared_ptr.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/shared_ptr.h @@ -259,7 +259,7 @@ struct __shared_ptr_emplace : __shared_weak_count { class _Allocator = _Alloc, __enable_if_t::value, int> = 0> _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __storage_(std::move(__a)) { - using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; + using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __remove_cv_t<_Tp> >::type; _TpAlloc __tmp(*__get_alloc()); allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), std::forward<_Args>(__args)...); } @@ -278,7 +278,7 @@ private: template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT { - using _TpAlloc = typename __allocator_traits_rebind<_Allocator, _Tp>::type; + using _TpAlloc = typename __allocator_traits_rebind<_Allocator, __remove_cv_t<_Tp> >::type; _TpAlloc __tmp(*__get_alloc()); allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); } @@ -403,6 +403,9 @@ struct __shared_ptr_deleter_ctor_reqs { __well_formed_deleter<_Dp, _Yp*>::value; }; +template +using __shared_ptr_nullptr_deleter_ctor_reqs = _And, __well_formed_deleter<_Dp, nullptr_t> >; + #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) #else @@ -411,6 +414,8 @@ struct __shared_ptr_deleter_ctor_reqs { template class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { + struct __nullptr_sfinae_tag {}; + public: #if _LIBCPP_STD_VER >= 17 typedef weak_ptr<_Tp> weak_type; @@ -419,6 +424,10 @@ public: typedef _Tp element_type; #endif + // A shared_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require + // any bookkeeping, so it's always trivially relocatable. + using __trivially_relocatable = shared_ptr; + private: element_type* __ptr_; __shared_weak_count* __cntrl_; @@ -499,7 +508,11 @@ public: } template - _LIBCPP_HIDE_FROM_ABI shared_ptr(nullptr_t __p, _Dp __d) : __ptr_(nullptr) { + _LIBCPP_HIDE_FROM_ABI shared_ptr( + nullptr_t __p, + _Dp __d, + __enable_if_t<__shared_ptr_nullptr_deleter_ctor_reqs<_Dp>::value, __nullptr_sfinae_tag> = __nullptr_sfinae_tag()) + : __ptr_(nullptr) { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS @@ -519,7 +532,12 @@ public: } template - _LIBCPP_HIDE_FROM_ABI shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a) : __ptr_(nullptr) { + _LIBCPP_HIDE_FROM_ABI shared_ptr( + nullptr_t __p, + _Dp __d, + _Alloc __a, + __enable_if_t<__shared_ptr_nullptr_deleter_ctor_reqs<_Dp>::value, __nullptr_sfinae_tag> = __nullptr_sfinae_tag()) + : __ptr_(nullptr) { #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif // _LIBCPP_HAS_NO_EXCEPTIONS @@ -594,8 +612,8 @@ public: #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr(auto_ptr<_Yp>&& __r) : __ptr_(__r.get()) { - typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<_Yp>()); + typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<__remove_cv_t<_Yp> > > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<__remove_cv_t<_Yp> >()); __enable_weak_this(__r.get(), __r.get()); __r.release(); } @@ -772,7 +790,7 @@ public: private: template ::value> struct __shared_ptr_default_allocator { - typedef allocator<_Yp> type; + typedef allocator<__remove_cv_t<_Yp> > type; }; template @@ -830,7 +848,7 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&& template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(_Args&&... __args) { - return std::allocate_shared<_Tp>(allocator<_Tp>(), std::forward<_Args>(__args)...); + return std::allocate_shared<_Tp>(allocator<__remove_cv_t<_Tp> >(), std::forward<_Args>(__args)...); } #if _LIBCPP_STD_VER >= 20 @@ -844,7 +862,7 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() { - return std::allocate_shared_for_overwrite<_Tp>(allocator<_Tp>()); + return std::allocate_shared_for_overwrite<_Tp>(allocator<__remove_cv_t<_Tp>>()); } #endif // _LIBCPP_STD_VER >= 20 @@ -1301,6 +1319,10 @@ public: typedef _Tp element_type; #endif + // A weak_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require + // any bookkeeping, so it's always trivially relocatable. + using __trivially_relocatable = weak_ptr; + private: element_type* __ptr_; __shared_weak_count* __cntrl_; diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/swap_allocator.h b/naiveproxy/src/third_party/libc++/src/include/__memory/swap_allocator.h index f2c5090563..b17e082a43 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/swap_allocator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/swap_allocator.h @@ -26,7 +26,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swap_allocator(_Alloc #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else - _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) + _NOEXCEPT_(__is_nothrow_swappable_v<_Alloc>) #endif { using std::swap; @@ -42,7 +42,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swap_allocator #if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else - _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) + _NOEXCEPT_(__is_nothrow_swappable_v<_Alloc>) #endif { std::__swap_allocator( diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/temporary_buffer.h b/naiveproxy/src/third_party/libc++/src/include/__memory/temporary_buffer.h index e3797caff8..88799ca95c 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/temporary_buffer.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/temporary_buffer.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_DEPRECATED_IN_CXX17 pair<_Tp*, ptrdiff_t> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_DEPRECATED_IN_CXX17 pair<_Tp*, ptrdiff_t> get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT { pair<_Tp*, ptrdiff_t> __r(0, 0); const ptrdiff_t __m = diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/unique_ptr.h b/naiveproxy/src/third_party/libc++/src/include/__memory/unique_ptr.h index 46d9405e31..9519e42838 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/unique_ptr.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/unique_ptr.h @@ -183,8 +183,8 @@ public: : __ptr_(__value_init_tag(), __value_init_tag()) {} template > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) _NOEXCEPT - : __ptr_(__p, __value_init_tag()) {} + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) _NOEXCEPT : __ptr_(__p, __value_init_tag()) {} template > > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT @@ -359,8 +359,8 @@ public: bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy>, class = _EnableIfPointerConvertible<_Pp> > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Pp __p) _NOEXCEPT - : __ptr_(__p, __value_init_tag()) {} + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Pp __p) _NOEXCEPT : __ptr_(__p, __value_init_tag()) {} template ::value, int> = 0> +template , int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT { __x.swap(__y); @@ -517,8 +517,8 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const unique_ptr<_T1, _D1>& __x, co template requires three_way_comparable_with::pointer, typename unique_ptr<_T2, _D2>::pointer> _LIBCPP_HIDE_FROM_ABI - compare_three_way_result_t::pointer, typename unique_ptr<_T2, _D2>::pointer> - operator<=>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) { +compare_three_way_result_t::pointer, typename unique_ptr<_T2, _D2>::pointer> +operator<=>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) { return compare_three_way()(__x.get(), __y.get()); } #endif diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory/uses_allocator_construction.h b/naiveproxy/src/third_party/libc++/src/include/__memory/uses_allocator_construction.h index 9b7262bec5..5e5819d4c2 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory/uses_allocator_construction.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory/uses_allocator_construction.h @@ -184,20 +184,18 @@ __uses_allocator_construction_args(const _Alloc& __alloc, _Type&& __value) noexc struct __pair_constructor { using _PairMutable = remove_cv_t<_Pair>; - _LIBCPP_HIDE_FROM_ABI constexpr auto __do_construct(const _PairMutable& __pair) const { + _LIBCPP_HIDDEN constexpr auto __do_construct(const _PairMutable& __pair) const { return std::__make_obj_using_allocator<_PairMutable>(__alloc_, __pair); } - _LIBCPP_HIDE_FROM_ABI constexpr auto __do_construct(_PairMutable&& __pair) const { + _LIBCPP_HIDDEN constexpr auto __do_construct(_PairMutable&& __pair) const { return std::__make_obj_using_allocator<_PairMutable>(__alloc_, std::move(__pair)); } const _Alloc& __alloc_; _Type& __value_; - _LIBCPP_HIDE_FROM_ABI constexpr operator _PairMutable() const { - return __do_construct(std::forward<_Type>(this->__value_)); - } + _LIBCPP_HIDDEN constexpr operator _PairMutable() const { return __do_construct(std::forward<_Type>(__value_)); } }; return std::make_tuple(__pair_constructor{__alloc, __value}); diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/memory_resource.h b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/memory_resource.h index 418f36dc9b..ea85e50cd5 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/memory_resource.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/memory_resource.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H -#include <__availability> #include <__config> #include <__fwd/memory_resource.h> #include @@ -32,9 +31,8 @@ class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource { public: virtual ~memory_resource(); - _LIBCPP_NODISCARD_AFTER_CXX17 - [[using __gnu__: __returns_nonnull__, __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void* - allocate(size_t __bytes, size_t __align = __max_align) { + [[nodiscard]] [[using __gnu__: __returns_nonnull__, __alloc_size__(2), __alloc_align__(3)]] + _LIBCPP_HIDE_FROM_ABI void* allocate(size_t __bytes, size_t __align = __max_align) { return do_allocate(__bytes, __align); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/monotonic_buffer_resource.h b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/monotonic_buffer_resource.h index 0c83f1ebc8..f45b30fdb3 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/monotonic_buffer_resource.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/monotonic_buffer_resource.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H -#include <__availability> #include <__config> #include <__memory/addressof.h> #include <__memory_resource/memory_resource.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/polymorphic_allocator.h b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/polymorphic_allocator.h index 823c1503c2..a71096d3e4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/polymorphic_allocator.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/polymorphic_allocator.h @@ -10,7 +10,6 @@ #define _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H #include <__assert> -#include <__availability> #include <__config> #include <__fwd/pair.h> #include <__memory_resource/memory_resource.h> @@ -61,7 +60,7 @@ public: // [mem.poly.allocator.mem] - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) { if (__n > __max_size()) { __throw_bad_array_new_length(); } diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/synchronized_pool_resource.h b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/synchronized_pool_resource.h index b261fb0b19..50a673c286 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/synchronized_pool_resource.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/synchronized_pool_resource.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_SYNCHRONIZED_POOL_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_SYNCHRONIZED_POOL_RESOURCE_H -#include <__availability> #include <__config> #include <__memory_resource/memory_resource.h> #include <__memory_resource/pool_options.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/unsynchronized_pool_resource.h b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/unsynchronized_pool_resource.h index 81d5f9ec4d..783db84262 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__memory_resource/unsynchronized_pool_resource.h +++ b/naiveproxy/src/third_party/libc++/src/include/__memory_resource/unsynchronized_pool_resource.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_UNSYNCHRONIZED_POOL_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_UNSYNCHRONIZED_POOL_RESOURCE_H -#include <__availability> #include <__config> #include <__memory_resource/memory_resource.h> #include <__memory_resource/pool_options.h> diff --git a/naiveproxy/src/third_party/libc++/src/include/__mutex/lock_guard.h b/naiveproxy/src/third_party/libc++/src/include/__mutex/lock_guard.h index c075512fb9..ef56896be9 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mutex/lock_guard.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mutex/lock_guard.h @@ -16,8 +16,6 @@ # pragma GCC system_header #endif -#ifndef _LIBCPP_HAS_NO_THREADS - _LIBCPP_BEGIN_NAMESPACE_STD template @@ -29,18 +27,17 @@ private: mutex_type& __m_; public: - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) - _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) + _LIBCPP_NODISCARD + _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) : __m_(__m) { __m_.lock(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) : __m_(__m) {} _LIBCPP_HIDE_FROM_ABI ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); } -private: lock_guard(lock_guard const&) = delete; lock_guard& operator=(lock_guard const&) = delete; }; @@ -48,6 +45,4 @@ _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard); _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_HAS_NO_THREADS - #endif // _LIBCPP___MUTEX_LOCK_GUARD_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__mutex/tag_types.h b/naiveproxy/src/third_party/libc++/src/include/__mutex/tag_types.h index 05ccb8b23a..2b2dd58ee4 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mutex/tag_types.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mutex/tag_types.h @@ -15,8 +15,6 @@ # pragma GCC system_header #endif -#ifndef _LIBCPP_HAS_NO_THREADS - _LIBCPP_BEGIN_NAMESPACE_STD struct _LIBCPP_EXPORTED_FROM_ABI defer_lock_t { @@ -31,18 +29,16 @@ struct _LIBCPP_EXPORTED_FROM_ABI adopt_lock_t { explicit adopt_lock_t() = default; }; -# if _LIBCPP_STD_VER >= 17 +#if _LIBCPP_STD_VER >= 17 inline constexpr defer_lock_t defer_lock = defer_lock_t(); inline constexpr try_to_lock_t try_to_lock = try_to_lock_t(); inline constexpr adopt_lock_t adopt_lock = adopt_lock_t(); -# elif !defined(_LIBCPP_CXX03_LANG) +#elif !defined(_LIBCPP_CXX03_LANG) constexpr defer_lock_t defer_lock = defer_lock_t(); constexpr try_to_lock_t try_to_lock = try_to_lock_t(); constexpr adopt_lock_t adopt_lock = adopt_lock_t(); -# endif +#endif _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_HAS_NO_THREADS - #endif // _LIBCPP___MUTEX_TAG_TYPES_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__mutex/unique_lock.h b/naiveproxy/src/third_party/libc++/src/include/__mutex/unique_lock.h index c27ce4b24c..4a616ba51e 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__mutex/unique_lock.h +++ b/naiveproxy/src/third_party/libc++/src/include/__mutex/unique_lock.h @@ -36,26 +36,28 @@ private: bool __owns_; public: - _LIBCPP_HIDE_FROM_ABI unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} - _LIBCPP_HIDE_FROM_ABI explicit unique_lock(mutex_type& __m) : __m_(std::addressof(__m)), __owns_(true) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI explicit unique_lock(mutex_type& __m) + : __m_(std::addressof(__m)), __owns_(true) { __m_->lock(); } - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT : __m_(std::addressof(__m)), __owns_(false) {} - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, try_to_lock_t) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, try_to_lock_t) : __m_(std::addressof(__m)), __owns_(__m.try_lock()) {} - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, adopt_lock_t) : __m_(std::addressof(__m)), __owns_(true) {} + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, adopt_lock_t) + : __m_(std::addressof(__m)), __owns_(true) {} template - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) : __m_(std::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} template - _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) : __m_(std::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} _LIBCPP_HIDE_FROM_ABI ~unique_lock() { @@ -66,7 +68,9 @@ public: unique_lock(unique_lock const&) = delete; unique_lock& operator=(unique_lock const&) = delete; - _LIBCPP_HIDE_FROM_ABI unique_lock(unique_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI unique_lock(unique_lock&& __u) _NOEXCEPT + : __m_(__u.__m_), + __owns_(__u.__owns_) { __u.__m_ = nullptr; __u.__owns_ = false; } diff --git a/naiveproxy/src/third_party/libc++/src/include/__node_handle b/naiveproxy/src/third_party/libc++/src/include/__node_handle index 24d2624c37..d0b35bfd19 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__node_handle +++ b/naiveproxy/src/third_party/libc++/src/include/__node_handle @@ -147,7 +147,7 @@ public: _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ptr_ != nullptr; } - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; } _LIBCPP_HIDE_FROM_ABI void swap(__basic_node_handle& __other) noexcept( __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value) { diff --git a/naiveproxy/src/third_party/libc++/src/include/__numeric/gcd_lcm.h b/naiveproxy/src/third_party/libc++/src/include/__numeric/gcd_lcm.h index 48df233805..9be6cf8516 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__numeric/gcd_lcm.h +++ b/naiveproxy/src/third_party/libc++/src/include/__numeric/gcd_lcm.h @@ -10,7 +10,9 @@ #ifndef _LIBCPP___NUMERIC_GCD_LCM_H #define _LIBCPP___NUMERIC_GCD_LCM_H +#include <__algorithm/min.h> #include <__assert> +#include <__bit/countr.h> #include <__config> #include <__type_traits/common_type.h> #include <__type_traits/is_integral.h> @@ -35,7 +37,7 @@ struct __ct_abs; template struct __ct_abs<_Result, _Source, true> { - _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _Result operator()(_Source __t) const noexcept { + constexpr _LIBCPP_HIDE_FROM_ABI _Result operator()(_Source __t) const noexcept { if (__t >= 0) return __t; if (__t == numeric_limits<_Source>::min()) @@ -46,20 +48,58 @@ struct __ct_abs<_Result, _Source, true> { template struct __ct_abs<_Result, _Source, false> { - _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _Result operator()(_Source __t) const noexcept { return __t; } + constexpr _LIBCPP_HIDE_FROM_ABI _Result operator()(_Source __t) const noexcept { return __t; } }; template -_LIBCPP_CONSTEXPR _LIBCPP_HIDDEN _Tp __gcd(_Tp __m, _Tp __n) { - static_assert((!is_signed<_Tp>::value), ""); - return __n == 0 ? __m : std::__gcd<_Tp>(__n, __m % __n); +constexpr _LIBCPP_HIDDEN _Tp __gcd(_Tp __a, _Tp __b) { + static_assert(!is_signed<_Tp>::value, ""); + + // From: https://lemire.me/blog/2013/12/26/fastest-way-to-compute-the-greatest-common-divisor + // + // If power of two divides both numbers, we can push it out. + // - gcd( 2^x * a, 2^x * b) = 2^x * gcd(a, b) + // + // If and only if exactly one number is even, we can divide that number by that power. + // - if a, b are odd, then gcd(2^x * a, b) = gcd(a, b) + // + // And standard gcd algorithm where instead of modulo, minus is used. + + if (__a < __b) { + _Tp __tmp = __b; + __b = __a; + __a = __tmp; + } + if (__b == 0) + return __a; + __a %= __b; // Make both argument of the same size, and early result in the easy case. + if (__a == 0) + return __b; + + int __az = std::__countr_zero(__a); + int __bz = std::__countr_zero(__b); + int __shift = std::min(__az, __bz); + __a >>= __az; + __b >>= __bz; + do { + _Tp __diff = __a - __b; + if (__a > __b) { + __a = __b; + __b = __diff; + } else { + __b = __b - __a; + } + if (__diff != 0) + __b >>= std::__countr_zero(__diff); + } while (__b != 0); + return __a << __shift; } template -_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI common_type_t<_Tp, _Up> gcd(_Tp __m, _Up __n) { - static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to gcd must be integer types"); - static_assert((!is_same<__remove_cv_t<_Tp>, bool>::value), "First argument to gcd cannot be bool"); - static_assert((!is_same<__remove_cv_t<_Up>, bool>::value), "Second argument to gcd cannot be bool"); +constexpr _LIBCPP_HIDE_FROM_ABI common_type_t<_Tp, _Up> gcd(_Tp __m, _Up __n) { + static_assert(is_integral<_Tp>::value && is_integral<_Up>::value, "Arguments to gcd must be integer types"); + static_assert(!is_same<__remove_cv_t<_Tp>, bool>::value, "First argument to gcd cannot be bool"); + static_assert(!is_same<__remove_cv_t<_Up>, bool>::value, "Second argument to gcd cannot be bool"); using _Rp = common_type_t<_Tp, _Up>; using _Wp = make_unsigned_t<_Rp>; return static_cast<_Rp>( @@ -67,21 +107,23 @@ _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI common_type_t<_Tp, _Up> gcd(_Tp __m, _Up } template -_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI common_type_t<_Tp, _Up> lcm(_Tp __m, _Up __n) { - static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to lcm must be integer types"); - static_assert((!is_same<__remove_cv_t<_Tp>, bool>::value), "First argument to lcm cannot be bool"); - static_assert((!is_same<__remove_cv_t<_Up>, bool>::value), "Second argument to lcm cannot be bool"); +constexpr _LIBCPP_HIDE_FROM_ABI common_type_t<_Tp, _Up> lcm(_Tp __m, _Up __n) { + static_assert(is_integral<_Tp>::value && is_integral<_Up>::value, "Arguments to lcm must be integer types"); + static_assert(!is_same<__remove_cv_t<_Tp>, bool>::value, "First argument to lcm cannot be bool"); + static_assert(!is_same<__remove_cv_t<_Up>, bool>::value, "Second argument to lcm cannot be bool"); if (__m == 0 || __n == 0) return 0; using _Rp = common_type_t<_Tp, _Up>; _Rp __val1 = __ct_abs<_Rp, _Tp>()(__m) / std::gcd(__m, __n); _Rp __val2 = __ct_abs<_Rp, _Up>()(__n); - _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm"); - return __val1 * __val2; + _Rp __res; + [[maybe_unused]] bool __overflow = __builtin_mul_overflow(__val1, __val2, &__res); + _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(!__overflow, "Overflow in lcm"); + return __res; } -#endif // _LIBCPP_STD_VER +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl.h b/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl.h new file mode 100644 index 0000000000..7557686a36 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl.h @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___NUMERIC_PSTL_H +#define _LIBCPP___NUMERIC_PSTL_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +# include <__functional/identity.h> +# include <__functional/operations.h> +# include <__iterator/cpp17_iterator_concepts.h> +# include <__iterator/iterator_traits.h> +# include <__pstl/backend.h> +# include <__pstl/dispatch.h> +# include <__pstl/handle_exception.h> +# include <__type_traits/enable_if.h> +# include <__type_traits/is_execution_policy.h> +# include <__type_traits/remove_cvref.h> +# include <__utility/forward.h> +# include <__utility/move.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp reduce( + _ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "reduce requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__reduce, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first), + std::move(__last), + std::move(__init), + std::move(__op)); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +reduce(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp __init) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "reduce requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__reduce, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__init), plus{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_value_type<_ForwardIterator> +reduce(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "reduce requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__reduce, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first), + std::move(__last), + __iter_value_type<_ForwardIterator>(), + plus{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init, + _BinaryOperation1 __reduce, + _BinaryOperation2 __transform) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "transform_reduce requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "transform_reduce requires ForwardIterators"); + using _Implementation = + __pstl::__dispatch<__pstl::__transform_reduce_binary, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__init), + std::move(__reduce), + std::move(__transform)); +} + +// This overload doesn't get a customization point because it's trivial to detect (through e.g. +// __desugars_to_v) when specializing the more general variant, which should always be preferred +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "transform_reduce requires ForwardIterators"); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "transform_reduce requires ForwardIterators"); + using _Implementation = + __pstl::__dispatch<__pstl::__transform_reduce_binary, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__init), + plus{}, + multiplies{}); +} + +template , + enable_if_t, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation __reduce, + _UnaryOperation __transform) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "transform_reduce requires ForwardIterators"); + using _Implementation = __pstl::__dispatch<__pstl::__transform_reduce, __pstl::__current_configuration, _RawPolicy>; + return __pstl::__handle_exception<_Implementation>( + std::forward<_ExecutionPolicy>(__policy), + std::move(__first), + std::move(__last), + std::move(__init), + std::move(__reduce), + std::move(__transform)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___NUMERIC_PSTL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl_reduce.h b/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl_reduce.h deleted file mode 100644 index f9f666c2bb..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl_reduce.h +++ /dev/null @@ -1,109 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___NUMERIC_PSTL_REDUCE_H -#define _LIBCPP___NUMERIC_PSTL_REDUCE_H - -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__functional/identity.h> -#include <__iterator/iterator_traits.h> -#include <__numeric/pstl_transform_reduce.h> -#include <__type_traits/is_execution_policy.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -void __pstl_reduce(); - -template , - class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Tp> -__reduce(_ExecutionPolicy&& __policy, - _ForwardIterator&& __first, - _ForwardIterator&& __last, - _Tp&& __init, - _BinaryOperation&& __op = {}) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_reduce, _RawPolicy), - [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Tp __g_init, _BinaryOperation __g_op) { - return std::__transform_reduce( - __policy, std::move(__g_first), std::move(__g_last), std::move(__g_init), std::move(__g_op), __identity{}); - }, - std::move(__first), - std::move(__last), - std::move(__init), - std::move(__op)); -} - -template , - class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp -reduce(_ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __last, - _Tp __init, - _BinaryOperation __op = {}) { - auto __res = std::__reduce(__policy, std::move(__first), std::move(__last), std::move(__init), std::move(__op)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_value_type<_ForwardIterator>> -__reduce(_ExecutionPolicy&& __policy, _ForwardIterator&& __first, _ForwardIterator&& __last) noexcept { - return std::__pstl_frontend_dispatch( - _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_reduce, _RawPolicy), - [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last) { - return std::__reduce( - __policy, std::move(__g_first), std::move(__g_last), __iter_value_type<_ForwardIterator>()); - }, - std::move(__first), - std::move(__last)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI __iter_value_type<_ForwardIterator> -reduce(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) { - auto __res = std::__reduce(__policy, std::move(__first), std::move(__last)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___NUMERIC_PSTL_REDUCE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl_transform_reduce.h b/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl_transform_reduce.h deleted file mode 100644 index 07ecf0d995..0000000000 --- a/naiveproxy/src/third_party/libc++/src/include/__numeric/pstl_transform_reduce.h +++ /dev/null @@ -1,156 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H -#define _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H - -#include <__algorithm/pstl_backend.h> -#include <__algorithm/pstl_frontend_dispatch.h> -#include <__config> -#include <__functional/operations.h> -#include <__numeric/transform_reduce.h> -#include <__type_traits/is_execution_policy.h> -#include <__utility/move.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_BEGIN_NAMESPACE_STD - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI optional<_Tp> __transform_reduce( - _ExecutionPolicy&&, - _ForwardIterator1&& __first1, - _ForwardIterator1&& __last1, - _ForwardIterator2&& __first2, - _Tp&& __init, - _BinaryOperation1&& __reduce, - _BinaryOperation2&& __transform) noexcept { - using _Backend = typename __select_backend<_RawPolicy>::type; - return std::__pstl_transform_reduce<_RawPolicy>( - _Backend{}, - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__init), - std::move(__reduce), - std::move(__transform)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( - _ExecutionPolicy&& __policy, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _Tp __init, - _BinaryOperation1 __reduce, - _BinaryOperation2 __transform) { - auto __res = std::__transform_reduce( - __policy, - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__init), - std::move(__reduce), - std::move(__transform)); - - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -// This overload doesn't get a customization point because it's trivial to detect (through e.g. -// __desugars_to_v) when specializing the more general variant, which should always be preferred -template >, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( - _ExecutionPolicy&& __policy, - _ForwardIterator1 __first1, - _ForwardIterator1 __last1, - _ForwardIterator2 __first2, - _Tp __init) { - return std::transform_reduce(__policy, __first1, __last1, __first2, __init, plus{}, multiplies{}); -} - -template , - enable_if_t, int> = 0> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__remove_cvref_t<_Tp>> __transform_reduce( - _ExecutionPolicy&&, - _ForwardIterator&& __first, - _ForwardIterator&& __last, - _Tp&& __init, - _BinaryOperation&& __reduce, - _UnaryOperation&& __transform) noexcept { - using _Backend = typename __select_backend<_RawPolicy>::type; - return std::__pstl_transform_reduce<_RawPolicy>( - _Backend{}, - std::move(__first), - std::move(__last), - std::move(__init), - std::move(__reduce), - std::move(__transform)); -} - -template , - enable_if_t, int> = 0> -_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( - _ExecutionPolicy&& __policy, - _ForwardIterator __first, - _ForwardIterator __last, - _Tp __init, - _BinaryOperation __reduce, - _UnaryOperation __transform) { - auto __res = std::__transform_reduce( - __policy, std::move(__first), std::move(__last), std::move(__init), std::move(__reduce), std::move(__transform)); - if (!__res) - std::__throw_bad_alloc(); - return *std::move(__res); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__numeric/saturation_arithmetic.h b/naiveproxy/src/third_party/libc++/src/include/__numeric/saturation_arithmetic.h index 41596a0c58..2390b42aae 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__numeric/saturation_arithmetic.h +++ b/naiveproxy/src/third_party/libc++/src/include/__numeric/saturation_arithmetic.h @@ -25,10 +25,10 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 26 +#if _LIBCPP_STD_VER >= 20 template <__libcpp_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp add_sat(_Tp __x, _Tp __y) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __add_sat(_Tp __x, _Tp __y) noexcept { if (_Tp __sum; !__builtin_add_overflow(__x, __y, &__sum)) return __sum; // Handle overflow @@ -46,7 +46,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp add_sat(_Tp __x, _Tp __y) noexcept { } template <__libcpp_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp sub_sat(_Tp __x, _Tp __y) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __sub_sat(_Tp __x, _Tp __y) noexcept { if (_Tp __sub; !__builtin_sub_overflow(__x, __y, &__sub)) return __sub; // Handle overflow @@ -65,7 +65,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp sub_sat(_Tp __x, _Tp __y) noexcept { } template <__libcpp_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp mul_sat(_Tp __x, _Tp __y) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __mul_sat(_Tp __x, _Tp __y) noexcept { if (_Tp __mul; !__builtin_mul_overflow(__x, __y, &__mul)) return __mul; // Handle overflow @@ -81,7 +81,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp mul_sat(_Tp __x, _Tp __y) noexcept { } template <__libcpp_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp div_sat(_Tp __x, _Tp __y) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __div_sat(_Tp __x, _Tp __y) noexcept { _LIBCPP_ASSERT_UNCATEGORIZED(__y != 0, "Division by 0 is undefined"); if constexpr (__libcpp_unsigned_integer<_Tp>) { return __x / __y; @@ -94,7 +94,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp div_sat(_Tp __x, _Tp __y) noexcept { } template <__libcpp_integer _Rp, __libcpp_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Rp saturate_cast(_Tp __x) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Rp __saturate_cast(_Tp __x) noexcept { // Saturation is impossible edge case when ((min _Rp) < (min _Tp) && (max _Rp) > (max _Tp)) and it is expected to be // optimized out by the compiler. @@ -107,6 +107,35 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Rp saturate_cast(_Tp __x) noexcept { return static_cast<_Rp>(__x); } +#endif // _LIBCPP_STD_VER >= 20 + +#if _LIBCPP_STD_VER >= 26 + +template <__libcpp_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp add_sat(_Tp __x, _Tp __y) noexcept { + return std::__add_sat(__x, __y); +} + +template <__libcpp_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp sub_sat(_Tp __x, _Tp __y) noexcept { + return std::__sub_sat(__x, __y); +} + +template <__libcpp_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp mul_sat(_Tp __x, _Tp __y) noexcept { + return std::__mul_sat(__x, __y); +} + +template <__libcpp_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp div_sat(_Tp __x, _Tp __y) noexcept { + return std::__div_sat(__x, __y); +} + +template <__libcpp_integer _Rp, __libcpp_integer _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Rp saturate_cast(_Tp __x) noexcept { + return std::__saturate_cast<_Rp>(__x); +} + #endif // _LIBCPP_STD_VER >= 26 _LIBCPP_END_NAMESPACE_STD diff --git a/naiveproxy/src/third_party/libc++/src/include/__ostream/basic_ostream.h b/naiveproxy/src/third_party/libc++/src/include/__ostream/basic_ostream.h new file mode 100644 index 0000000000..178359d681 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__ostream/basic_ostream.h @@ -0,0 +1,860 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___OSTREAM_BASIC_OSTREAM_H +#define _LIBCPP___OSTREAM_BASIC_OSTREAM_H + +#include <__config> +#include <__exception/operations.h> +#include <__memory/shared_ptr.h> +#include <__memory/unique_ptr.h> +#include <__system_error/error_code.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> +#include +#include +#include +#include +#include // for __throw_bad_alloc +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class _LIBCPP_TEMPLATE_VIS basic_ostream : virtual public basic_ios<_CharT, _Traits> { +public: + // types (inherited from basic_ios (27.5.4)): + typedef _CharT char_type; + typedef _Traits traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::pos_type pos_type; + typedef typename traits_type::off_type off_type; + + // 27.7.2.2 Constructor/destructor: + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 explicit basic_ostream(basic_streambuf* __sb) { + this->init(__sb); + } + ~basic_ostream() override; + + basic_ostream(const basic_ostream& __rhs) = delete; + basic_ostream& operator=(const basic_ostream& __rhs) = delete; + +protected: + inline _LIBCPP_HIDE_FROM_ABI basic_ostream(basic_ostream&& __rhs); + + // 27.7.2.3 Assign/swap + inline _LIBCPP_HIDE_FROM_ABI basic_ostream& operator=(basic_ostream&& __rhs); + + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 void swap(basic_ostream& __rhs) { + basic_ios::swap(__rhs); + } + +public: + // 27.7.2.4 Prefix/suffix: + class _LIBCPP_TEMPLATE_VIS sentry; + + // 27.7.2.6 Formatted output: + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& operator<<(basic_ostream& (*__pf)(basic_ostream&)) { + return __pf(*this); + } + + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& + operator<<(basic_ios& (*__pf)(basic_ios&)) { + __pf(*this); + return *this; + } + + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& operator<<(ios_base& (*__pf)(ios_base&)) { + __pf(*this); + return *this; + } + + basic_ostream& operator<<(bool __n); + basic_ostream& operator<<(short __n); + basic_ostream& operator<<(unsigned short __n); + basic_ostream& operator<<(int __n); + basic_ostream& operator<<(unsigned int __n); + basic_ostream& operator<<(long __n); + basic_ostream& operator<<(unsigned long __n); + basic_ostream& operator<<(long long __n); + basic_ostream& operator<<(unsigned long long __n); + basic_ostream& operator<<(float __f); + basic_ostream& operator<<(double __f); + basic_ostream& operator<<(long double __f); + basic_ostream& operator<<(const void* __p); + +#if _LIBCPP_STD_VER >= 23 + _LIBCPP_HIDE_FROM_ABI basic_ostream& operator<<(const volatile void* __p) { + return operator<<(const_cast(__p)); + } +#endif + + basic_ostream& operator<<(basic_streambuf* __sb); + +#if _LIBCPP_STD_VER >= 17 + // LWG 2221 - nullptr. This is not backported to older standards modes. + // See https://reviews.llvm.org/D127033 for more info on the rationale. + _LIBCPP_HIDE_FROM_ABI basic_ostream& operator<<(nullptr_t) { return *this << "nullptr"; } +#endif + + // 27.7.2.7 Unformatted output: + basic_ostream& put(char_type __c); + basic_ostream& write(const char_type* __s, streamsize __n); + basic_ostream& flush(); + + // 27.7.2.5 seeks: + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 pos_type tellp(); + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& seekp(pos_type __pos); + inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& seekp(off_type __off, ios_base::seekdir __dir); + +protected: + _LIBCPP_HIDE_FROM_ABI basic_ostream() {} // extension, intentially does not initialize +}; + +template +class _LIBCPP_TEMPLATE_VIS basic_ostream<_CharT, _Traits>::sentry { + bool __ok_; + basic_ostream<_CharT, _Traits>& __os_; + +public: + explicit sentry(basic_ostream<_CharT, _Traits>& __os); + ~sentry(); + sentry(const sentry&) = delete; + sentry& operator=(const sentry&) = delete; + + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ok_; } +}; + +template +basic_ostream<_CharT, _Traits>::sentry::sentry(basic_ostream<_CharT, _Traits>& __os) : __ok_(false), __os_(__os) { + if (__os.good()) { + if (__os.tie()) + __os.tie()->flush(); + __ok_ = true; + } +} + +template +basic_ostream<_CharT, _Traits>::sentry::~sentry() { + if (__os_.rdbuf() && __os_.good() && (__os_.flags() & ios_base::unitbuf) && !uncaught_exception()) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + if (__os_.rdbuf()->pubsync() == -1) + __os_.setstate(ios_base::badbit); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + } +} + +template +basic_ostream<_CharT, _Traits>::basic_ostream(basic_ostream&& __rhs) { + this->move(__rhs); +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator=(basic_ostream&& __rhs) { + swap(__rhs); + return *this; +} + +template +basic_ostream<_CharT, _Traits>::~basic_ostream() {} + +template +basic_ostream<_CharT, _Traits>& +basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf* __sb) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + if (__sb) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + typedef istreambuf_iterator<_CharT, _Traits> _Ip; + typedef ostreambuf_iterator<_CharT, _Traits> _Op; + _Ip __i(__sb); + _Ip __eof; + _Op __o(*this); + size_t __c = 0; + for (; __i != __eof; ++__i, ++__o, ++__c) { + *__o = *__i; + if (__o.failed()) + break; + } + if (__c == 0) + this->setstate(ios_base::failbit); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_failbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + } else + this->setstate(ios_base::badbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(bool __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(short __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + ios_base::fmtflags __flags = ios_base::flags() & ios_base::basefield; + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, + *this, + this->fill(), + __flags == ios_base::oct || __flags == ios_base::hex + ? static_cast(static_cast(__n)) + : static_cast(__n)) + .failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned short __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), static_cast(__n)).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(int __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + ios_base::fmtflags __flags = ios_base::flags() & ios_base::basefield; + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, + *this, + this->fill(), + __flags == ios_base::oct || __flags == ios_base::hex + ? static_cast(static_cast(__n)) + : static_cast(__n)) + .failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned int __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), static_cast(__n)).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned long __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long long __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(float __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), static_cast(__n)).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(double __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long double __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(const void* __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef num_put > _Fp; + const _Fp& __f = std::use_facet<_Fp>(this->getloc()); + if (__f.put(*this, *this, this->fill(), __n).failed()) + this->setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +__put_character_sequence(basic_ostream<_CharT, _Traits>& __os, const _CharT* __str, size_t __len) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + typename basic_ostream<_CharT, _Traits>::sentry __s(__os); + if (__s) { + typedef ostreambuf_iterator<_CharT, _Traits> _Ip; + if (std::__pad_and_output( + _Ip(__os), + __str, + (__os.flags() & ios_base::adjustfield) == ios_base::left ? __str + __len : __str, + __str + __len, + __os, + __os.fill()) + .failed()) + __os.setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + __os.__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return __os; +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, _CharT __c) { + return std::__put_character_sequence(__os, &__c, 1); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, char __cn) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + typename basic_ostream<_CharT, _Traits>::sentry __s(__os); + if (__s) { + _CharT __c = __os.widen(__cn); + typedef ostreambuf_iterator<_CharT, _Traits> _Ip; + if (std::__pad_and_output( + _Ip(__os), + &__c, + (__os.flags() & ios_base::adjustfield) == ios_base::left ? &__c + 1 : &__c, + &__c + 1, + __os, + __os.fill()) + .failed()) + __os.setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + __os.__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return __os; +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream& operator<<(basic_ostream& __os, char __c) { + return std::__put_character_sequence(__os, &__c, 1); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream& operator<<(basic_ostream& __os, signed char __c) { + return std::__put_character_sequence(__os, (char*)&__c, 1); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream& operator<<(basic_ostream& __os, unsigned char __c) { + return std::__put_character_sequence(__os, (char*)&__c, 1); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const _CharT* __str) { + return std::__put_character_sequence(__os, __str, _Traits::length(__str)); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const char* __strn) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + typename basic_ostream<_CharT, _Traits>::sentry __s(__os); + if (__s) { + typedef ostreambuf_iterator<_CharT, _Traits> _Ip; + size_t __len = char_traits::length(__strn); + const int __bs = 100; + _CharT __wbb[__bs]; + _CharT* __wb = __wbb; + unique_ptr<_CharT, void (*)(void*)> __h(0, free); + if (__len > __bs) { + __wb = (_CharT*)malloc(__len * sizeof(_CharT)); + if (__wb == 0) + __throw_bad_alloc(); + __h.reset(__wb); + } + for (_CharT* __p = __wb; *__strn != '\0'; ++__strn, ++__p) + *__p = __os.widen(*__strn); + if (std::__pad_and_output( + _Ip(__os), + __wb, + (__os.flags() & ios_base::adjustfield) == ios_base::left ? __wb + __len : __wb, + __wb + __len, + __os, + __os.fill()) + .failed()) + __os.setstate(ios_base::badbit | ios_base::failbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + __os.__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return __os; +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream& operator<<(basic_ostream& __os, const char* __str) { + return std::__put_character_sequence(__os, __str, _Traits::length(__str)); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream& +operator<<(basic_ostream& __os, const signed char* __str) { + const char* __s = (const char*)__str; + return std::__put_character_sequence(__os, __s, _Traits::length(__s)); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream& +operator<<(basic_ostream& __os, const unsigned char* __str) { + const char* __s = (const char*)__str; + return std::__put_character_sequence(__os, __s, _Traits::length(__s)); +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::put(char_type __c) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __s(*this); + if (__s) { + typedef ostreambuf_iterator<_CharT, _Traits> _Op; + _Op __o(*this); + *__o = __c; + if (__o.failed()) + this->setstate(ios_base::badbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + sentry __sen(*this); + if (__sen && __n) { + if (this->rdbuf()->sputn(__s, __n) != __n) + this->setstate(ios_base::badbit); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::flush() { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + if (this->rdbuf()) { + sentry __s(*this); + if (__s) { + if (this->rdbuf()->pubsync() == -1) + this->setstate(ios_base::badbit); + } + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + this->__set_badbit_and_consider_rethrow(); + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return *this; +} + +template +typename basic_ostream<_CharT, _Traits>::pos_type basic_ostream<_CharT, _Traits>::tellp() { + if (this->fail()) + return pos_type(-1); + return this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out); +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::seekp(pos_type __pos) { + sentry __s(*this); + if (!this->fail()) { + if (this->rdbuf()->pubseekpos(__pos, ios_base::out) == pos_type(-1)) + this->setstate(ios_base::failbit); + } + return *this; +} + +template +basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::seekp(off_type __off, ios_base::seekdir __dir) { + sentry __s(*this); + if (!this->fail()) { + if (this->rdbuf()->pubseekoff(__off, __dir, ios_base::out) == pos_type(-1)) + this->setstate(ios_base::failbit); + } + return *this; +} + +template +_LIBCPP_HIDE_FROM_ABI inline basic_ostream<_CharT, _Traits>& endl(basic_ostream<_CharT, _Traits>& __os) { + __os.put(__os.widen('\n')); + __os.flush(); + return __os; +} + +template +_LIBCPP_HIDE_FROM_ABI inline basic_ostream<_CharT, _Traits>& ends(basic_ostream<_CharT, _Traits>& __os) { + __os.put(_CharT()); + return __os; +} + +template +_LIBCPP_HIDE_FROM_ABI inline basic_ostream<_CharT, _Traits>& flush(basic_ostream<_CharT, _Traits>& __os) { + __os.flush(); + return __os; +} + +template +struct __is_ostreamable : false_type {}; + +template +struct __is_ostreamable<_Stream, _Tp, decltype(std::declval<_Stream>() << std::declval<_Tp>(), void())> : true_type {}; + +template , __is_ostreamable<_Stream&, const _Tp&> >::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Stream&& operator<<(_Stream&& __os, const _Tp& __x) { + __os << __x; + return std::move(__os); +} + +template +basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const basic_string<_CharT, _Traits, _Allocator>& __str) { + return std::__put_character_sequence(__os, __str.data(), __str.size()); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, basic_string_view<_CharT, _Traits> __sv) { + return std::__put_character_sequence(__os, __sv.data(), __sv.size()); +} + +template +inline _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __ec) { + return __os << __ec.category().name() << ':' << __ec.value(); +} + +template +inline _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p) { + return __os << __p.get(); +} + +template < + class _CharT, + class _Traits, + class _Yp, + class _Dp, + __enable_if_t&>() + << std::declval::pointer>()))> >::value, + int> = 0> +inline _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, unique_ptr<_Yp, _Dp> const& __p) { + return __os << __p.get(); +} + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x) { + return __os << __x.template to_string<_CharT, _Traits>(std::use_facet >(__os.getloc()).widen('0'), + std::use_facet >(__os.getloc()).widen('1')); +} + +#if _LIBCPP_STD_VER >= 20 + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template +basic_ostream& operator<<(basic_ostream&, wchar_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const wchar_t*) = delete; + +template +basic_ostream& operator<<(basic_ostream&, char16_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, char32_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char16_t*) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char32_t*) = delete; + +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +# ifndef _LIBCPP_HAS_NO_CHAR8_T +template +basic_ostream& operator<<(basic_ostream&, char8_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, char8_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char8_t*) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char8_t*) = delete; +# endif + +template +basic_ostream& operator<<(basic_ostream&, char16_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, char32_t) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char16_t*) = delete; + +template +basic_ostream& operator<<(basic_ostream&, const char32_t*) = delete; + +#endif // _LIBCPP_STD_VER >= 20 + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream; +#endif + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___OSTREAM_BASIC_OSTREAM_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__ostream/print.h b/naiveproxy/src/third_party/libc++/src/include/__ostream/print.h new file mode 100644 index 0000000000..8265ac0077 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__ostream/print.h @@ -0,0 +1,179 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___OSTREAM_PRINT_H +#define _LIBCPP___OSTREAM_PRINT_H + +#include <__config> +#include <__fwd/ostream.h> +#include <__iterator/ostreambuf_iterator.h> +#include <__ostream/basic_ostream.h> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void +__vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args, bool __write_nl) { + // [ostream.formatted.print]/3 + // Effects: Behaves as a formatted output function + // ([ostream.formatted.reqmts]) of os, except that: + // - failure to generate output is reported as specified below, and + // - any exception thrown by the call to vformat is propagated without regard + // to the value of os.exceptions() and without turning on ios_base::badbit + // in the error state of os. + // After constructing a sentry object, the function initializes an automatic + // variable via + // string out = vformat(os.getloc(), fmt, args); + + ostream::sentry __s(__os); + if (__s) { + string __o = std::vformat(__os.getloc(), __fmt, __args); + if (__write_nl) + __o += '\n'; + + const char* __str = __o.data(); + size_t __len = __o.size(); + +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +# endif // _LIBCPP_HAS_NO_EXCEPTIONS + typedef ostreambuf_iterator _Ip; + if (std::__pad_and_output( + _Ip(__os), + __str, + (__os.flags() & ios_base::adjustfield) == ios_base::left ? __str + __len : __str, + __str + __len, + __os, + __os.fill()) + .failed()) + __os.setstate(ios_base::badbit | ios_base::failbit); + +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + __os.__set_badbit_and_consider_rethrow(); + } +# endif // _LIBCPP_HAS_NO_EXCEPTIONS + } +} + +template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args) { + std::__vprint_nonunicode(__os, __fmt, __args, false); +} + +// Returns the FILE* associated with the __os. +// Returns a nullptr when no FILE* is associated with __os. +// This function is in the dylib since the type of the buffer associated +// with std::cout, std::cerr, and std::clog is only known in the dylib. +// +// This function implements part of the implementation-defined behavior +// of [ostream.formatted.print]/3 +// If the function is vprint_unicode and os is a stream that refers to +// a terminal capable of displaying Unicode which is determined in an +// implementation-defined manner, writes out to the terminal using the +// native Unicode API; +// Whether the returned FILE* is "a terminal capable of displaying Unicode" +// is determined in the same way as the print(FILE*, ...) overloads. +_LIBCPP_EXPORTED_FROM_ABI FILE* __get_ostream_file(ostream& __os); + +# ifndef _LIBCPP_HAS_NO_UNICODE +template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI void __vprint_unicode(ostream& __os, string_view __fmt, format_args __args, bool __write_nl) { +# if _LIBCPP_AVAILABILITY_HAS_PRINT == 0 + return std::__vprint_nonunicode(__os, __fmt, __args, __write_nl); +# else + FILE* __file = std::__get_ostream_file(__os); + if (!__file || !__print::__is_terminal(__file)) + return std::__vprint_nonunicode(__os, __fmt, __args, __write_nl); + + // [ostream.formatted.print]/3 + // If the function is vprint_unicode and os is a stream that refers to a + // terminal capable of displaying Unicode which is determined in an + // implementation-defined manner, writes out to the terminal using the + // native Unicode API; if out contains invalid code units, the behavior is + // undefined and implementations are encouraged to diagnose it. If the + // native Unicode API is used, the function flushes os before writing out. + // + // This is the path for the native API, start with flushing. + __os.flush(); + +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +# endif // _LIBCPP_HAS_NO_EXCEPTIONS + ostream::sentry __s(__os); + if (__s) { +# ifndef _LIBCPP_WIN32API + __print::__vprint_unicode_posix(__file, __fmt, __args, __write_nl, true); +# elif !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) + __print::__vprint_unicode_windows(__file, __fmt, __args, __write_nl, true); +# else +# error "Windows builds with wchar_t disabled are not supported." +# endif + } + +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + __os.__set_badbit_and_consider_rethrow(); + } +# endif // _LIBCPP_HAS_NO_EXCEPTIONS +# endif // _LIBCPP_AVAILABILITY_HAS_PRINT +} + +template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(ostream& __os, string_view __fmt, format_args __args) { + std::__vprint_unicode(__os, __fmt, __args, false); +} +# endif // _LIBCPP_HAS_NO_UNICODE + +template +_LIBCPP_HIDE_FROM_ABI void print(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) { +# ifndef _LIBCPP_HAS_NO_UNICODE + if constexpr (__print::__use_unicode_execution_charset) + std::__vprint_unicode(__os, __fmt.get(), std::make_format_args(__args...), false); + else + std::__vprint_nonunicode(__os, __fmt.get(), std::make_format_args(__args...), false); +# else // _LIBCPP_HAS_NO_UNICODE + std::__vprint_nonunicode(__os, __fmt.get(), std::make_format_args(__args...), false); +# endif // _LIBCPP_HAS_NO_UNICODE +} + +template +_LIBCPP_HIDE_FROM_ABI void println(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) { +# ifndef _LIBCPP_HAS_NO_UNICODE + // Note the wording in the Standard is inefficient. The output of + // std::format is a std::string which is then copied. This solution + // just appends a newline at the end of the output. + if constexpr (__print::__use_unicode_execution_charset) + std::__vprint_unicode(__os, __fmt.get(), std::make_format_args(__args...), true); + else + std::__vprint_nonunicode(__os, __fmt.get(), std::make_format_args(__args...), true); +# else // _LIBCPP_HAS_NO_UNICODE + std::__vprint_nonunicode(__os, __fmt.get(), std::make_format_args(__args...), true); +# endif // _LIBCPP_HAS_NO_UNICODE +} + +template // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void println(ostream& __os) { + std::print(__os, "\n"); +} + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___OSTREAM_PRINT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/backend.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/backend.h new file mode 100644 index 0000000000..86d9f28c77 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/backend.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_BACKEND_H +#define _LIBCPP___PSTL_BACKEND_H + +#include <__config> +#include <__pstl/backend_fwd.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if defined(_LIBCPP_PSTL_BACKEND_SERIAL) +# include <__pstl/backends/default.h> +# include <__pstl/backends/serial.h> +#elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD) +# include <__pstl/backends/default.h> +# include <__pstl/backends/std_thread.h> +#elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH) +# include <__pstl/backends/default.h> +# include <__pstl/backends/libdispatch.h> +#endif + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_BACKEND_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/backend_fwd.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/backend_fwd.h new file mode 100644 index 0000000000..32c5da576f --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/backend_fwd.h @@ -0,0 +1,301 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_BACKEND_FWD_H +#define _LIBCPP___PSTL_BACKEND_FWD_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +// +// This header declares available PSTL backends and the functions that must be implemented in order for the +// PSTL algorithms to be provided. +// +// Backends often do not implement the full set of functions themselves -- a configuration of the PSTL is +// usually a set of backends "stacked" together which each implement some algorithms under some execution +// policies. It is only necessary for the "stack" of backends to implement all algorithms under all execution +// policies, but a single backend is not required to implement everything on its own. +// +// The signatures used by each backend function are documented below. +// +// Exception handling +// ================== +// +// PSTL backends are expected to report errors (i.e. failure to allocate) by returning a disengaged `optional` from +// their implementation. Exceptions shouldn't be used to report an internal failure-to-allocate, since all exceptions +// are turned into a program termination at the front-end level. When a backend returns a disengaged `optional` to the +// frontend, the frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to +// the user. +// + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +template +struct __backend_configuration; + +struct __default_backend_tag; +struct __libdispatch_backend_tag; +struct __serial_backend_tag; +struct __std_thread_backend_tag; + +#if defined(_LIBCPP_PSTL_BACKEND_SERIAL) +using __current_configuration = __backend_configuration<__serial_backend_tag, __default_backend_tag>; +#elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD) +using __current_configuration = __backend_configuration<__std_thread_backend_tag, __default_backend_tag>; +#elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH) +using __current_configuration = __backend_configuration<__libdispatch_backend_tag, __default_backend_tag>; +#else + +// ...New vendors can add parallel backends here... + +# error "Invalid PSTL backend configuration" +#endif + +template +struct __find_if; +// template +// optional<_ForwardIterator> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept; + +template +struct __find_if_not; +// template +// optional<_ForwardIterator> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept; + +template +struct __find; +// template +// optional<_ForwardIterator> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) const noexcept; + +template +struct __any_of; +// template +// optional +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept; + +template +struct __all_of; +// template +// optional +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept; + +template +struct __none_of; +// template +// optional +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept; + +template +struct __is_partitioned; +// template +// optional +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept; + +template +struct __for_each; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __func) const noexcept; + +template +struct __for_each_n; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _Size __size, _Function __func) const noexcept; + +template +struct __fill; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept; + +template +struct __fill_n; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept; + +template +struct __replace; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _Tp const& __old, _Tp const& __new) const noexcept; + +template +struct __replace_if; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _Predicate __pred, _Tp const& __new_value) const noexcept; + +template +struct __generate; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __gen) const noexcept; + +template +struct __generate_n; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _Size __n, _Generator __gen) const noexcept; + +template +struct __merge; +// template +// optional<_ForwardOutIterator> +// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +// _ForwardIterator2 __first2, _ForwardIterator2 __last2, +// _ForwardOutIterator __result, _Comp __comp) const noexcept; + +template +struct __stable_sort; +// template +// optional<__empty> +// operator()(_Policy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) const noexcept; + +template +struct __sort; +// template +// optional<__empty> +// operator()(_Policy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) const noexcept; + +template +struct __transform; +// template +// optional<_ForwardOutIterator> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _ForwardOutIterator __result, +// _UnaryOperation __op) const noexcept; + +template +struct __transform_binary; +// template +// optional<_ForwardOutIterator> +// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +// _ForwardIterator2 __first2, +// _ForwardOutIterator __result, +// _BinaryOperation __op) const noexcept; + +template +struct __replace_copy_if; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _ForwardOutIterator __out_it, +// _Predicate __pred, +// _Tp const& __new_value) const noexcept; + +template +struct __replace_copy; +// template +// optional<__empty> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _ForwardOutIterator __out_it, +// _Tp const& __old_value, +// _Tp const& __new_value) const noexcept; + +template +struct __move; +// template +// optional<_ForwardOutIterator> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _ForwardOutIterator __out_it) const noexcept; + +template +struct __copy; +// template +// optional<_ForwardOutIterator> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _ForwardOutIterator __out_it) const noexcept; + +template +struct __copy_n; +// template +// optional<_ForwardOutIterator> +// operator()(_Policy&&, _ForwardIterator __first, _Size __n, _ForwardOutIterator __out_it) const noexcept; + +template +struct __rotate_copy; +// template +// optional<_ForwardOutIterator> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, +// _ForwardOutIterator __out_it) const noexcept; + +template +struct __transform_reduce; +// template +// optional<_Tp> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _Tp __init, +// _BinaryOperation __reduce, +// _UnaryOperation __transform) const noexcept; + +template +struct __transform_reduce_binary; +// template +// optional<_Tp> operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +// _ForwardIterator2 __first2, +// _Tp __init, +// _BinaryOperation1 __reduce, +// _BinaryOperation2 __transform) const noexcept; + +template +struct __count_if; +// template +// optional<__iter_diff_t<_ForwardIterator>> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept; + +template +struct __count; +// template +// optional<__iter_diff_t<_ForwardIterator>> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept; + +template +struct __equal_3leg; +// template +// optional +// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +// _ForwardIterator2 __first2, +// _Predicate __pred) const noexcept; + +template +struct __equal; +// template +// optional +// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, +// _ForwardIterator2 __first2, _ForwardIterator2 __last2, +// _Predicate __pred) const noexcept; + +template +struct __reduce; +// template +// optional<_Tp> +// operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, +// _Tp __init, _BinaryOperation __op) const noexcept; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_BACKEND_FWD_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/default.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/default.h new file mode 100644 index 0000000000..61a128805f --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/default.h @@ -0,0 +1,503 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_BACKENDS_DEFAULT_H +#define _LIBCPP___PSTL_BACKENDS_DEFAULT_H + +#include <__algorithm/copy_n.h> +#include <__algorithm/equal.h> +#include <__algorithm/fill_n.h> +#include <__algorithm/for_each_n.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/not_fn.h> +#include <__functional/operations.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/dispatch.h> +#include <__utility/empty.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +// +// This file provides an incomplete PSTL backend that implements all of the PSTL algorithms +// based on a smaller set of basis operations. +// +// It is intended as a building block for other PSTL backends that implement some operations more +// efficiently but may not want to define the full set of PSTL algorithms. +// +// This backend implements all the PSTL algorithms based on the following basis operations: +// +// find_if family +// -------------- +// - find +// - find_if_not +// - any_of +// - all_of +// - none_of +// - is_partitioned +// +// for_each family +// --------------- +// - for_each_n +// - fill +// - fill_n +// - replace +// - replace_if +// - generate +// - generate_n +// +// merge family +// ------------ +// No other algorithms based on merge +// +// stable_sort family +// ------------------ +// - sort +// +// transform_reduce and transform_reduce_binary family +// --------------------------------------------------- +// - count_if +// - count +// - equal(3 legs) +// - equal +// - reduce +// +// transform and transform_binary family +// ------------------------------------- +// - replace_copy_if +// - replace_copy +// - move +// - copy +// - copy_n +// - rotate_copy +// + +////////////////////////////////////////////////////////////// +// find_if family +////////////////////////////////////////////////////////////// +template +struct __find<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) const noexcept { + using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; + return _FindIf()( + __policy, std::move(__first), std::move(__last), [&](__iter_reference<_ForwardIterator> __element) { + return __element == __value; + }); + } +}; + +template +struct __find_if_not<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { + using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; + return _FindIf()(__policy, __first, __last, std::not_fn(std::forward<_Pred>(__pred))); + } +}; + +template +struct __any_of<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { + using _FindIf = __dispatch<__find_if, __current_configuration, _ExecutionPolicy>; + auto __res = _FindIf()(__policy, __first, __last, std::forward<_Pred>(__pred)); + if (!__res) + return nullopt; + return *__res != __last; + } +}; + +template +struct __all_of<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { + using _AnyOf = __dispatch<__any_of, __current_configuration, _ExecutionPolicy>; + auto __res = _AnyOf()(__policy, __first, __last, [&](__iter_reference<_ForwardIterator> __value) { + return !__pred(__value); + }); + if (!__res) + return nullopt; + return !*__res; + } +}; + +template +struct __none_of<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { + using _AnyOf = __dispatch<__any_of, __current_configuration, _ExecutionPolicy>; + auto __res = _AnyOf()(__policy, __first, __last, std::forward<_Pred>(__pred)); + if (!__res) + return nullopt; + return !*__res; + } +}; + +template +struct __is_partitioned<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { + using _FindIfNot = __dispatch<__find_if_not, __current_configuration, _ExecutionPolicy>; + auto __maybe_first = _FindIfNot()(__policy, std::move(__first), std::move(__last), __pred); + if (__maybe_first == nullopt) + return nullopt; + + __first = *__maybe_first; + if (__first == __last) + return true; + ++__first; + using _NoneOf = __dispatch<__none_of, __current_configuration, _ExecutionPolicy>; + return _NoneOf()(__policy, std::move(__first), std::move(__last), __pred); + } +}; + +////////////////////////////////////////////////////////////// +// for_each family +////////////////////////////////////////////////////////////// +template +struct __for_each_n<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) const noexcept { + if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; + _ForwardIterator __last = __first + __size; + return _ForEach()(__policy, std::move(__first), std::move(__last), std::move(__func)); + } else { + // Otherwise, use the serial algorithm to avoid doing two passes over the input + std::for_each_n(std::move(__first), __size, std::move(__func)); + return __empty{}; + } + } +}; + +template +struct __fill<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept { + using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; + using _Ref = __iter_reference<_ForwardIterator>; + return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { __element = __value; }); + } +}; + +template +struct __fill_n<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept { + if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + using _Fill = __dispatch<__fill, __current_configuration, _ExecutionPolicy>; + _ForwardIterator __last = __first + __n; + return _Fill()(__policy, std::move(__first), std::move(__last), __value); + } else { + // Otherwise, use the serial algorithm to avoid doing two passes over the input + std::fill_n(std::move(__first), __n, __value); + return optional<__empty>{__empty{}}; + } + } +}; + +template +struct __replace<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __old, _Tp const& __new) + const noexcept { + using _ReplaceIf = __dispatch<__replace_if, __current_configuration, _ExecutionPolicy>; + using _Ref = __iter_reference<_ForwardIterator>; + return _ReplaceIf()( + __policy, std::move(__first), std::move(__last), [&](_Ref __element) { return __element == __old; }, __new); + } +}; + +template +struct __replace_if<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> operator()( + _Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred, _Tp const& __new_value) + const noexcept { + using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; + using _Ref = __iter_reference<_ForwardIterator>; + return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { + if (__pred(__element)) + __element = __new_value; + }); + } +}; + +template +struct __generate<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator&& __gen) const noexcept { + using _ForEach = __dispatch<__for_each, __current_configuration, _ExecutionPolicy>; + using _Ref = __iter_reference<_ForwardIterator>; + return _ForEach()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) { __element = __gen(); }); + } +}; + +template +struct __generate_n<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _Generator&& __gen) const noexcept { + using _ForEachN = __dispatch<__for_each_n, __current_configuration, _ExecutionPolicy>; + using _Ref = __iter_reference<_ForwardIterator>; + return _ForEachN()(__policy, std::move(__first), __n, [&](_Ref __element) { __element = __gen(); }); + } +}; + +////////////////////////////////////////////////////////////// +// stable_sort family +////////////////////////////////////////////////////////////// +template +struct __sort<__default_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<__empty> operator()( + _Policy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp&& __comp) const noexcept { + using _StableSort = __dispatch<__stable_sort, __current_configuration, _ExecutionPolicy>; + return _StableSort()(__policy, std::move(__first), std::move(__last), std::forward<_Comp>(__comp)); + } +}; + +////////////////////////////////////////////////////////////// +// transform_reduce family +////////////////////////////////////////////////////////////// +template +struct __count_if<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> operator()( + _Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred) const noexcept { + using _TransformReduce = __dispatch<__transform_reduce, __current_configuration, _ExecutionPolicy>; + using _DiffT = __iter_diff_t<_ForwardIterator>; + using _Ref = __iter_reference<_ForwardIterator>; + return _TransformReduce()( + __policy, std::move(__first), std::move(__last), _DiffT{}, std::plus{}, [&](_Ref __element) -> _DiffT { + return __pred(__element) ? _DiffT(1) : _DiffT(0); + }); + } +}; + +template +struct __count<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__iter_diff_t<_ForwardIterator>> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp const& __value) const noexcept { + using _CountIf = __dispatch<__count_if, __current_configuration, _ExecutionPolicy>; + using _Ref = __iter_reference<_ForwardIterator>; + return _CountIf()(__policy, std::move(__first), std::move(__last), [&](_Ref __element) -> bool { + return __element == __value; + }); + } +}; + +template +struct __equal_3leg<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional + operator()(_Policy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Predicate&& __pred) const noexcept { + using _TransformReduce = __dispatch<__transform_reduce_binary, __current_configuration, _ExecutionPolicy>; + return _TransformReduce()( + __policy, + std::move(__first1), + std::move(__last1), + std::move(__first2), + true, + std::logical_and{}, + std::forward<_Predicate>(__pred)); + } +}; + +template +struct __equal<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional + operator()(_Policy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Predicate&& __pred) const noexcept { + if constexpr (__has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value) { + if (__last1 - __first1 != __last2 - __first2) + return false; + // Fall back to the 3 legged algorithm + using _Equal3Leg = __dispatch<__equal_3leg, __current_configuration, _ExecutionPolicy>; + return _Equal3Leg()( + __policy, std::move(__first1), std::move(__last1), std::move(__first2), std::forward<_Predicate>(__pred)); + } else { + // If we don't have random access, fall back to the serial algorithm cause we can't do much + return std::equal( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::forward<_Predicate>(__pred)); + } + } +}; + +template +struct __reduce<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_Tp> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation&& __op) + const noexcept { + using _TransformReduce = __dispatch<__transform_reduce, __current_configuration, _ExecutionPolicy>; + return _TransformReduce()( + __policy, + std::move(__first), + std::move(__last), + std::move(__init), + std::forward<_BinaryOperation>(__op), + __identity{}); + } +}; + +////////////////////////////////////////////////////////////// +// transform family +////////////////////////////////////////////////////////////// +template +struct __replace_copy_if<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __out_it, + _Pred&& __pred, + _Tp const& __new_value) const noexcept { + using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; + using _Ref = __iter_reference<_ForwardIterator>; + auto __res = + _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), [&](_Ref __element) { + return __pred(__element) ? __new_value : __element; + }); + if (__res == nullopt) + return nullopt; + return __empty{}; + } +}; + +template +struct __replace_copy<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __out_it, + _Tp const& __old_value, + _Tp const& __new_value) const noexcept { + using _ReplaceCopyIf = __dispatch<__replace_copy_if, __current_configuration, _ExecutionPolicy>; + using _Ref = __iter_reference<_ForwardIterator>; + return _ReplaceCopyIf()( + __policy, + std::move(__first), + std::move(__last), + std::move(__out_it), + [&](_Ref __element) { return __element == __old_value; }, + __new_value); + } +}; + +// TODO: Use the std::copy/move shenanigans to forward to std::memmove +// Investigate whether we want to still forward to std::transform(policy) +// in that case for the execution::par part, or whether we actually want +// to run everything serially in that case. +template +struct __move<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) + const noexcept { + using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; + return _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), [&](auto&& __element) { + return std::move(__element); + }); + } +}; + +// TODO: Use the std::copy/move shenanigans to forward to std::memmove +template +struct __copy<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __out_it) + const noexcept { + using _Transform = __dispatch<__transform, __current_configuration, _ExecutionPolicy>; + return _Transform()(__policy, std::move(__first), std::move(__last), std::move(__out_it), __identity()); + } +}; + +template +struct __copy_n<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> + operator()(_Policy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __out_it) const noexcept { + if constexpr (__has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + using _Copy = __dispatch<__copy, __current_configuration, _ExecutionPolicy>; + _ForwardIterator __last = __first + __n; + return _Copy()(__policy, std::move(__first), std::move(__last), std::move(__out_it)); + } else { + // Otherwise, use the serial algorithm to avoid doing two passes over the input + return std::copy_n(std::move(__first), __n, std::move(__out_it)); + } + } +}; + +template +struct __rotate_copy<__default_backend_tag, _ExecutionPolicy> { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> + operator()(_Policy&& __policy, + _ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + _ForwardOutIterator __out_it) const noexcept { + using _Copy = __dispatch<__copy, __current_configuration, _ExecutionPolicy>; + auto __result_mid = _Copy()(__policy, __middle, std::move(__last), std::move(__out_it)); + if (__result_mid == nullopt) + return nullopt; + return _Copy()(__policy, std::move(__first), std::move(__middle), *std::move(__result_mid)); + } +}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_BACKENDS_DEFAULT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/libdispatch.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/libdispatch.h new file mode 100644 index 0000000000..a0c3ad980e --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/libdispatch.h @@ -0,0 +1,397 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_BACKENDS_LIBDISPATCH_H +#define _LIBCPP___PSTL_BACKENDS_LIBDISPATCH_H + +#include <__algorithm/inplace_merge.h> +#include <__algorithm/lower_bound.h> +#include <__algorithm/max.h> +#include <__algorithm/merge.h> +#include <__algorithm/upper_bound.h> +#include <__atomic/atomic.h> +#include <__config> +#include <__exception/terminate.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/move_iterator.h> +#include <__memory/allocator.h> +#include <__memory/construct_at.h> +#include <__memory/unique_ptr.h> +#include <__numeric/reduce.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/any_of.h> +#include <__pstl/cpu_algos/cpu_traits.h> +#include <__pstl/cpu_algos/fill.h> +#include <__pstl/cpu_algos/find_if.h> +#include <__pstl/cpu_algos/for_each.h> +#include <__pstl/cpu_algos/merge.h> +#include <__pstl/cpu_algos/stable_sort.h> +#include <__pstl/cpu_algos/transform.h> +#include <__pstl/cpu_algos/transform_reduce.h> +#include <__utility/empty.h> +#include <__utility/exception_guard.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include +#include +#include + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +namespace __libdispatch { +// ::dispatch_apply is marked as __attribute__((nothrow)) because it doesn't let exceptions propagate, and neither do +// we. +// TODO: Do we want to add [[_Clang::__callback__(__func, __context, __)]]? +_LIBCPP_EXPORTED_FROM_ABI void +__dispatch_apply(size_t __chunk_count, void* __context, void (*__func)(void* __context, size_t __chunk)) noexcept; + +template +_LIBCPP_HIDE_FROM_ABI void __dispatch_apply(size_t __chunk_count, _Func __func) noexcept { + __libdispatch::__dispatch_apply(__chunk_count, &__func, [](void* __context, size_t __chunk) { + (*static_cast<_Func*>(__context))(__chunk); + }); +} + +struct __chunk_partitions { + ptrdiff_t __chunk_count_; // includes the first chunk + ptrdiff_t __chunk_size_; + ptrdiff_t __first_chunk_size_; +}; + +[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI __chunk_partitions __partition_chunks(ptrdiff_t __size) noexcept; + +template +_LIBCPP_HIDE_FROM_ABI optional<__empty> +__dispatch_parallel_for(__chunk_partitions __partitions, _RandomAccessIterator __first, _Functor __func) { + // Perform the chunked execution. + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { + auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; + auto __index = + __chunk == 0 + ? 0 + : (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); + __func(__first + __index, __first + __index + __this_chunk_size); + }); + + return __empty{}; +} +} // namespace __libdispatch + +template <> +struct __cpu_traits<__libdispatch_backend_tag> { + template + _LIBCPP_HIDE_FROM_ABI static optional<__empty> + __for_each(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func) { + return __libdispatch::__dispatch_parallel_for( + __libdispatch::__partition_chunks(__last - __first), std::move(__first), std::move(__func)); + } + + template + struct __merge_range { + __merge_range(_RandomAccessIterator1 __mid1, _RandomAccessIterator2 __mid2, _RandomAccessIteratorOut __result) + : __mid1_(__mid1), __mid2_(__mid2), __result_(__result) {} + + _RandomAccessIterator1 __mid1_; + _RandomAccessIterator2 __mid2_; + _RandomAccessIteratorOut __result_; + }; + + template + _LIBCPP_HIDE_FROM_ABI static optional<__empty> + __merge(_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + _LeafMerge __leaf_merge) noexcept { + __libdispatch::__chunk_partitions __partitions = + __libdispatch::__partition_chunks(std::max(__last1 - __first1, __last2 - __first2)); + + if (__partitions.__chunk_count_ == 0) + return __empty{}; + + if (__partitions.__chunk_count_ == 1) { + __leaf_merge(__first1, __last1, __first2, __last2, __result, __comp); + return __empty{}; + } + + using __merge_range_t = __merge_range<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3>; + auto const __n_ranges = __partitions.__chunk_count_ + 1; + + // TODO: use __uninitialized_buffer + auto __destroy = [=](__merge_range_t* __ptr) { + std::destroy_n(__ptr, __n_ranges); + std::allocator<__merge_range_t>().deallocate(__ptr, __n_ranges); + }; + + unique_ptr<__merge_range_t[], decltype(__destroy)> __ranges( + [&]() -> __merge_range_t* { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif + return std::allocator<__merge_range_t>().allocate(__n_ranges); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (const std::bad_alloc&) { + return nullptr; + } +#endif + }(), + __destroy); + + if (!__ranges) + return nullopt; + + // TODO: Improve the case where the smaller range is merged into just a few (or even one) chunks of the larger case + __merge_range_t* __r = __ranges.get(); + std::__construct_at(__r++, __first1, __first2, __result); + + bool __iterate_first_range = __last1 - __first1 > __last2 - __first2; + + auto __compute_chunk = [&](size_t __chunk_size) -> __merge_range_t { + auto [__mid1, __mid2] = [&] { + if (__iterate_first_range) { + auto __m1 = __first1 + __chunk_size; + auto __m2 = std::lower_bound(__first2, __last2, __m1[-1], __comp); + return std::make_pair(__m1, __m2); + } else { + auto __m2 = __first2 + __chunk_size; + auto __m1 = std::lower_bound(__first1, __last1, __m2[-1], __comp); + return std::make_pair(__m1, __m2); + } + }(); + + __result += (__mid1 - __first1) + (__mid2 - __first2); + __first1 = __mid1; + __first2 = __mid2; + return {std::move(__mid1), std::move(__mid2), __result}; + }; + + // handle first chunk + std::__construct_at(__r++, __compute_chunk(__partitions.__first_chunk_size_)); + + // handle 2 -> N - 1 chunks + for (ptrdiff_t __i = 0; __i != __partitions.__chunk_count_ - 2; ++__i) + std::__construct_at(__r++, __compute_chunk(__partitions.__chunk_size_)); + + // handle last chunk + std::__construct_at(__r, __last1, __last2, __result); + + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __index) { + auto __first_iters = __ranges[__index]; + auto __last_iters = __ranges[__index + 1]; + __leaf_merge( + __first_iters.__mid1_, + __last_iters.__mid1_, + __first_iters.__mid2_, + __last_iters.__mid2_, + __first_iters.__result_, + __comp); + }); + + return __empty{}; + } + + template + _LIBCPP_HIDE_FROM_ABI static optional<_Value> __transform_reduce( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Transform __transform, + _Value __init, + _Combiner __combiner, + _Reduction __reduction) { + if (__first == __last) + return __init; + + auto __partitions = __libdispatch::__partition_chunks(__last - __first); + + auto __destroy = [__count = __partitions.__chunk_count_](_Value* __ptr) { + std::destroy_n(__ptr, __count); + std::allocator<_Value>().deallocate(__ptr, __count); + }; + + // TODO: use __uninitialized_buffer + // TODO: allocate one element per worker instead of one element per chunk + unique_ptr<_Value[], decltype(__destroy)> __values( + std::allocator<_Value>().allocate(__partitions.__chunk_count_), __destroy); + + // __dispatch_apply is noexcept + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { + auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; + auto __index = __chunk == 0 ? 0 + : (__chunk * __partitions.__chunk_size_) + + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); + if (__this_chunk_size != 1) { + std::__construct_at( + __values.get() + __chunk, + __reduction(__first + __index + 2, + __first + __index + __this_chunk_size, + __combiner(__transform(__first + __index), __transform(__first + __index + 1)))); + } else { + std::__construct_at(__values.get() + __chunk, __transform(__first + __index)); + } + }); + + return std::reduce( + std::make_move_iterator(__values.get()), + std::make_move_iterator(__values.get() + __partitions.__chunk_count_), + std::move(__init), + __combiner); + } + + template + _LIBCPP_HIDE_FROM_ABI static optional<__empty> + __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp, _LeafSort __leaf_sort) { + const auto __size = __last - __first; + auto __partitions = __libdispatch::__partition_chunks(__size); + + if (__partitions.__chunk_count_ == 0) + return __empty{}; + + if (__partitions.__chunk_count_ == 1) { + __leaf_sort(__first, __last, __comp); + return __empty{}; + } + + using _Value = __iter_value_type<_RandomAccessIterator>; + + auto __destroy = [__size](_Value* __ptr) { + std::destroy_n(__ptr, __size); + std::allocator<_Value>().deallocate(__ptr, __size); + }; + + // TODO: use __uninitialized_buffer + unique_ptr<_Value[], decltype(__destroy)> __values(std::allocator<_Value>().allocate(__size), __destroy); + + // Initialize all elements to a moved-from state + // TODO: Don't do this - this can be done in the first merge - see https://llvm.org/PR63928 + std::__construct_at(__values.get(), std::move(*__first)); + for (__iter_diff_t<_RandomAccessIterator> __i = 1; __i != __size; ++__i) { + std::__construct_at(__values.get() + __i, std::move(__values.get()[__i - 1])); + } + *__first = std::move(__values.get()[__size - 1]); + + __libdispatch::__dispatch_parallel_for( + __partitions, + __first, + [&__leaf_sort, &__comp](_RandomAccessIterator __chunk_first, _RandomAccessIterator __chunk_last) { + __leaf_sort(std::move(__chunk_first), std::move(__chunk_last), __comp); + }); + + bool __objects_are_in_buffer = false; + do { + const auto __old_chunk_size = __partitions.__chunk_size_; + if (__partitions.__chunk_count_ % 2 == 1) { + auto __inplace_merge_chunks = [&__comp, &__partitions](auto __first_chunk_begin) { + std::inplace_merge( + __first_chunk_begin, + __first_chunk_begin + __partitions.__first_chunk_size_, + __first_chunk_begin + __partitions.__first_chunk_size_ + __partitions.__chunk_size_, + __comp); + }; + if (__objects_are_in_buffer) + __inplace_merge_chunks(__values.get()); + else + __inplace_merge_chunks(__first); + __partitions.__first_chunk_size_ += 2 * __partitions.__chunk_size_; + } else { + __partitions.__first_chunk_size_ += __partitions.__chunk_size_; + } + + __partitions.__chunk_size_ *= 2; + __partitions.__chunk_count_ /= 2; + + auto __merge_chunks = [__partitions, __old_chunk_size, &__comp](auto __from_first, auto __to_first) { + __libdispatch::__dispatch_parallel_for( + __partitions, + __from_first, + [__old_chunk_size, &__from_first, &__to_first, &__comp](auto __chunk_first, auto __chunk_last) { + std::merge(std::make_move_iterator(__chunk_first), + std::make_move_iterator(__chunk_last - __old_chunk_size), + std::make_move_iterator(__chunk_last - __old_chunk_size), + std::make_move_iterator(__chunk_last), + __to_first + (__chunk_first - __from_first), + __comp); + }); + }; + + if (__objects_are_in_buffer) + __merge_chunks(__values.get(), __first); + else + __merge_chunks(__first, __values.get()); + __objects_are_in_buffer = !__objects_are_in_buffer; + } while (__partitions.__chunk_count_ > 1); + + if (__objects_are_in_buffer) { + std::move(__values.get(), __values.get() + __size, __first); + } + + return __empty{}; + } + + _LIBCPP_HIDE_FROM_ABI static void __cancel_execution() {} + + static constexpr size_t __lane_size = 64; +}; + +// Mandatory implementations of the computational basis +template +struct __find_if<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_find_if<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +template +struct __for_each<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_for_each<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +template +struct __merge<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_merge<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +template +struct __stable_sort<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_stable_sort<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +template +struct __transform<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_transform<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +template +struct __transform_binary<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_transform_binary<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +template +struct __transform_reduce<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_transform_reduce<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +template +struct __transform_reduce_binary<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_transform_reduce_binary<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +// Not mandatory, but better optimized +template +struct __any_of<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_any_of<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +template +struct __fill<__libdispatch_backend_tag, _ExecutionPolicy> + : __cpu_parallel_fill<__libdispatch_backend_tag, _ExecutionPolicy> {}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_BACKENDS_LIBDISPATCH_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/serial.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/serial.h new file mode 100644 index 0000000000..5f24499899 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/serial.h @@ -0,0 +1,181 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_BACKENDS_SERIAL_H +#define _LIBCPP___PSTL_BACKENDS_SERIAL_H + +#include <__algorithm/find_if.h> +#include <__algorithm/for_each.h> +#include <__algorithm/merge.h> +#include <__algorithm/stable_sort.h> +#include <__algorithm/transform.h> +#include <__config> +#include <__numeric/transform_reduce.h> +#include <__pstl/backend_fwd.h> +#include <__utility/empty.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +// +// This partial PSTL backend runs everything serially. +// +// TODO: Right now, the serial backend must be used with another backend +// like the "default backend" because it doesn't implement all the +// necessary PSTL operations. It would be better to dispatch all +// algorithms to their serial counterpart directly, since this can +// often be more efficient than the "default backend"'s implementation +// if we end up running serially anyways. +// + +template +struct __find_if<__serial_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> + operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Pred&& __pred) const noexcept { + return std::find_if(std::move(__first), std::move(__last), std::forward<_Pred>(__pred)); + } +}; + +template +struct __for_each<__serial_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last, _Function&& __func) const noexcept { + std::for_each(std::move(__first), std::move(__last), std::forward<_Function>(__func)); + return __empty{}; + } +}; + +template +struct __merge<__serial_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> operator()( + _Policy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardOutIterator __outit, + _Comp&& __comp) const noexcept { + return std::merge( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__outit), + std::forward<_Comp>(__comp)); + } +}; + +template +struct __stable_sort<__serial_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp&& __comp) const noexcept { + std::stable_sort(std::move(__first), std::move(__last), std::forward<_Comp>(__comp)); + return __empty{}; + } +}; + +template +struct __transform<__serial_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> operator()( + _Policy&&, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __outit, _UnaryOperation&& __op) + const noexcept { + return std::transform( + std::move(__first), std::move(__last), std::move(__outit), std::forward<_UnaryOperation>(__op)); + } +}; + +template +struct __transform_binary<__serial_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> + operator()(_Policy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardOutIterator __outit, + _BinaryOperation&& __op) const noexcept { + return std::transform( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__outit), + std::forward<_BinaryOperation>(__op)); + } +}; + +template +struct __transform_reduce<__serial_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<_Tp> + operator()(_Policy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation&& __reduce, + _UnaryOperation&& __transform) const noexcept { + return std::transform_reduce( + std::move(__first), + std::move(__last), + std::move(__init), + std::forward<_BinaryOperation>(__reduce), + std::forward<_UnaryOperation>(__transform)); + } +}; + +template +struct __transform_reduce_binary<__serial_backend_tag, _ExecutionPolicy> { + template + _LIBCPP_HIDE_FROM_ABI optional<_Tp> operator()( + _Policy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init, + _BinaryOperation1&& __reduce, + _BinaryOperation2&& __transform) const noexcept { + return std::transform_reduce( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__init), + std::forward<_BinaryOperation1>(__reduce), + std::forward<_BinaryOperation2>(__transform)); + } +}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_BACKENDS_SERIAL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/std_thread.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/std_thread.h new file mode 100644 index 0000000000..49570bd30b --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/backends/std_thread.h @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_BACKENDS_STD_THREAD_H +#define _LIBCPP___PSTL_BACKENDS_STD_THREAD_H + +#include <__config> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/any_of.h> +#include <__pstl/cpu_algos/cpu_traits.h> +#include <__pstl/cpu_algos/fill.h> +#include <__pstl/cpu_algos/find_if.h> +#include <__pstl/cpu_algos/for_each.h> +#include <__pstl/cpu_algos/merge.h> +#include <__pstl/cpu_algos/stable_sort.h> +#include <__pstl/cpu_algos/transform.h> +#include <__pstl/cpu_algos/transform_reduce.h> +#include <__utility/empty.h> +#include <__utility/move.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +// +// This partial backend implementation is for testing purposes only and not meant for production use. This will be +// replaced by a proper implementation once the PSTL implementation is somewhat stable. +// +// This is intended to be used on top of the "default backend". +// + +template <> +struct __cpu_traits<__std_thread_backend_tag> { + template + _LIBCPP_HIDE_FROM_ABI static optional<__empty> + __for_each(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { + __f(__first, __last); + return __empty{}; + } + + template + _LIBCPP_HIDE_FROM_ABI static optional<_Tp> + __transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { + return __reduce(std::move(__first), std::move(__last), std::move(__init)); + } + + template + _LIBCPP_HIDE_FROM_ABI static optional<__empty> + __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { + __leaf_sort(__first, __last, __comp); + return __empty{}; + } + + _LIBCPP_HIDE_FROM_ABI static void __cancel_execution() {} + + template + _LIBCPP_HIDE_FROM_ABI static optional<__empty> + __merge(_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __outit, + _Compare __comp, + _LeafMerge __leaf_merge) { + __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); + return __empty{}; + } + + static constexpr size_t __lane_size = 64; +}; + +// Mandatory implementations of the computational basis +template +struct __find_if<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_find_if<__std_thread_backend_tag, _ExecutionPolicy> {}; + +template +struct __for_each<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_for_each<__std_thread_backend_tag, _ExecutionPolicy> {}; + +template +struct __merge<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_merge<__std_thread_backend_tag, _ExecutionPolicy> {}; + +template +struct __stable_sort<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_stable_sort<__std_thread_backend_tag, _ExecutionPolicy> {}; + +template +struct __transform<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_transform<__std_thread_backend_tag, _ExecutionPolicy> {}; + +template +struct __transform_binary<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_transform_binary<__std_thread_backend_tag, _ExecutionPolicy> {}; + +template +struct __transform_reduce<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_transform_reduce<__std_thread_backend_tag, _ExecutionPolicy> {}; + +template +struct __transform_reduce_binary<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_transform_reduce_binary<__std_thread_backend_tag, _ExecutionPolicy> {}; + +// Not mandatory, but better optimized +template +struct __any_of<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_any_of<__std_thread_backend_tag, _ExecutionPolicy> {}; + +template +struct __fill<__std_thread_backend_tag, _ExecutionPolicy> + : __cpu_parallel_fill<__std_thread_backend_tag, _ExecutionPolicy> {}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_BACKENDS_STD_THREAD_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/any_of.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/any_of.h similarity index 51% rename from naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/any_of.h rename to naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/any_of.h index 13dff80086..b33c787a29 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/any_of.h +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/any_of.h @@ -6,37 +6,36 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_ANY_OF_H +#define _LIBCPP___PSTL_CPU_ALGOS_ANY_OF_H #include <__algorithm/any_of.h> -#include <__algorithm/find_if.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__assert> #include <__atomic/atomic.h> #include <__atomic/memory_order.h> #include <__config> -#include <__functional/operations.h> #include <__iterator/concepts.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/move.h> #include <__utility/pair.h> #include #include -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - _LIBCPP_PUSH_MACROS -# include <__undef_macros> +#include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { -template +template _LIBCPP_HIDE_FROM_ABI optional __parallel_or(_Index __first, _Index __last, _Brick __f) { std::atomic __found(false); - auto __ret = __par_backend::__parallel_for(__first, __last, [__f, &__found](_Index __i, _Index __j) { + auto __ret = __cpu_traits<_Backend>::__for_each(__first, __last, [__f, &__found](_Index __i, _Index __j) { if (!__found.load(std::memory_order_relaxed) && __f(__i, __j)) { __found.store(true, std::memory_order_relaxed); - __par_backend::__cancel_execution(); + __cpu_traits<_Backend>::__cancel_execution(); } }); if (!__ret) @@ -69,30 +68,32 @@ _LIBCPP_HIDE_FROM_ABI bool __simd_or(_Index __first, _DifferenceType __n, _Pred return false; } -template -_LIBCPP_HIDE_FROM_ABI optional -__pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - return std::__parallel_or( - __first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - auto __res = std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __pred); - _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); - return *std::move(__res); - }); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - return std::__simd_or(__first, __last - __first, __pred); - } else { - return std::any_of(__first, __last, __pred); +template +struct __cpu_parallel_any_of { + template + _LIBCPP_HIDE_FROM_ABI optional + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + return __pstl::__parallel_or<_Backend>( + __first, __last, [&__policy, &__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + using _AnyOfUnseq = __pstl::__any_of<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + auto __res = _AnyOfUnseq()(std::__remove_parallel_policy(__policy), __brick_first, __brick_last, __pred); + _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); + return *std::move(__res); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + return __pstl::__simd_or(__first, __last - __first, __pred); + } else { + return std::any_of(__first, __last, __pred); + } } -} +}; +} // namespace __pstl _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_ANY_OF_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/cpu_traits.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/cpu_traits.h new file mode 100644 index 0000000000..0483d6918f --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/cpu_traits.h @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_CPU_ALGOS_CPU_TRAITS_H +#define _LIBCPP___PSTL_CPU_ALGOS_CPU_TRAITS_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +// __cpu_traits +// +// This traits class encapsulates the basis operations for a CPU-based implementation of the PSTL. +// All the operations in the PSTL can be implemented from these basis operations, so a pure CPU backend +// only needs to customize these traits in order to get an implementation of the whole PSTL. +// +// Basis operations +// ================ +// +// template +// optional<__empty> __for_each(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func); +// - __func must take a subrange of [__first, __last) that should be executed in serial +// +// template +// optional<_Tp> __transform_reduce(_Iterator __first, _Iterator __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduction); +// +// template +// optional<_RandomAccessIterator3> __merge(_RandomAccessIterator1 __first1, +// _RandomAccessIterator1 __last1, +// _RandomAccessIterator2 __first2, +// _RandomAccessIterator2 __last2, +// _RandomAccessIterator3 __outit, +// _Compare __comp, +// _LeafMerge __leaf_merge); +// +// template +// optional<__empty> __stable_sort(_RandomAccessIterator __first, +// _RandomAccessIterator __last, +// _Comp __comp, +// _LeafSort __leaf_sort); +// +// void __cancel_execution(); +// Cancel the execution of other jobs - they aren't needed anymore. This is not a binding request, +// some backends may not actually be able to cancel jobs. +// +// constexpr size_t __lane_size; +// Size of SIMD lanes. +// TODO: Merge this with __native_vector_size from __algorithm/simd_utils.h +// +// +// Exception handling +// ================== +// +// CPU backends are expected to report errors (i.e. failure to allocate) by returning a disengaged `optional` from their +// implementation. Exceptions shouldn't be used to report an internal failure-to-allocate, since all exceptions are +// turned into a program termination at the front-end level. When a backend returns a disengaged `optional` to the +// frontend, the frontend will turn that into a call to `std::__throw_bad_alloc();` to report the internal failure to +// the user. + +template +struct __cpu_traits; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_CPU_ALGOS_CPU_TRAITS_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/fill.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/fill.h new file mode 100644 index 0000000000..4e6d29b30c --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/fill.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_CPU_ALGOS_FILL_H +#define _LIBCPP___PSTL_CPU_ALGOS_FILL_H + +#include <__algorithm/fill.h> +#include <__assert> +#include <__config> +#include <__iterator/concepts.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/cpu_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/empty.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +template +_LIBCPP_HIDE_FROM_ABI _Index __simd_fill_n(_Index __first, _DifferenceType __n, const _Tp& __value) noexcept { + _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __first[__i] = __value; + return __first + __n; +} + +template +struct __cpu_parallel_fill { + template + _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + return __cpu_traits<_Backend>::__for_each( + __first, __last, [&__policy, &__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + using _FillUnseq = __pstl::__fill<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + [[maybe_unused]] auto __res = + _FillUnseq()(std::__remove_parallel_policy(__policy), __brick_first, __brick_last, __value); + _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + __pstl::__simd_fill_n(__first, __last - __first, __value); + return __empty{}; + } else { + std::fill(__first, __last, __value); + return __empty{}; + } + } +}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___PSTL_CPU_ALGOS_FILL_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/find_if.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/find_if.h similarity index 56% rename from naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/find_if.h rename to naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/find_if.h index 170470e4fb..12b2e88971 100644 --- a/naiveproxy/src/third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/find_if.h +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/find_if.h @@ -6,16 +6,18 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H -#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H +#ifndef _LIBCPP___PSTL_CPU_ALGOS_FIND_IF_H +#define _LIBCPP___PSTL_CPU_ALGOS_FIND_IF_H #include <__algorithm/find_if.h> -#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__assert> #include <__atomic/atomic.h> #include <__config> #include <__functional/operations.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/cpu_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -26,14 +28,13 @@ # pragma GCC system_header #endif -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - _LIBCPP_PUSH_MACROS -# include <__undef_macros> +#include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { -template +template _LIBCPP_HIDE_FROM_ABI optional<_Index> __parallel_find(_Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first) { typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType; @@ -42,7 +43,7 @@ __parallel_find(_Index __first, _Index __last, _Brick __f, _Compare __comp, bool std::atomic<_DifferenceType> __extremum(__initial_dist); // TODO: find out what is better here: parallel_for or parallel_reduce auto __res = - __par_backend::__parallel_for(__first, __last, [__comp, __f, __first, &__extremum](_Index __i, _Index __j) { + __cpu_traits<_Backend>::__for_each(__first, __last, [__comp, __f, __first, &__extremum](_Index __i, _Index __j) { // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of // why using a shared variable scales fairly well in this situation. if (__comp(__i - __first, __extremum)) { @@ -61,12 +62,12 @@ __parallel_find(_Index __first, _Index __last, _Brick __f, _Compare __comp, bool return __extremum.load() != __initial_dist ? __first + __extremum.load() : __last; } -template +template _LIBCPP_HIDE_FROM_ABI _Index __simd_first(_Index __first, _DifferenceType __begin, _DifferenceType __end, _Compare __comp) noexcept { // Experiments show good block sizes like this - const _DifferenceType __block_size = 8; - alignas(__lane_size) _DifferenceType __lane[__block_size] = {0}; + const _DifferenceType __block_size = 8; + alignas(__cpu_traits<_Backend>::__lane_size) _DifferenceType __lane[__block_size] = {0}; while (__end - __begin >= __block_size) { _DifferenceType __found = 0; _PSTL_PRAGMA_SIMD_REDUCTION(| : __found) for (_DifferenceType __i = __begin; __i < __begin + __block_size; ++__i) { @@ -97,37 +98,40 @@ __simd_first(_Index __first, _DifferenceType __begin, _DifferenceType __end, _Co return __first + __end; } -template -_LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> -__pstl_find_if(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { - if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - return std::__parallel_find( - __first, - __last, - [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { - auto __res = std::__pstl_find_if<__remove_parallel_policy_t<_ExecutionPolicy>>( - __cpu_backend_tag{}, __brick_first, __brick_last, __pred); - _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); - return *std::move(__res); - }, - less<>{}, - true); - } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && - __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { - using __diff_t = __iter_diff_t<_ForwardIterator>; - return std::__simd_first(__first, __diff_t(0), __last - __first, [&__pred](_ForwardIterator __iter, __diff_t __i) { - return __pred(__iter[__i]); - }); - } else { - return std::find_if(__first, __last, __pred); +template +struct __cpu_parallel_find_if { + template + _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + return __pstl::__parallel_find<_Backend>( + __first, + __last, + [&__policy, &__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + using _FindIfUnseq = __pstl::__find_if<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + auto __res = _FindIfUnseq()(std::__remove_parallel_policy(__policy), __brick_first, __brick_last, __pred); + _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); + return *std::move(__res); + }, + less<>{}, + true); + } else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + using __diff_t = __iter_diff_t<_ForwardIterator>; + return __pstl::__simd_first<_Backend>( + __first, __diff_t(0), __last - __first, [&__pred](_ForwardIterator __iter, __diff_t __i) { + return __pred(__iter[__i]); + }); + } else { + return std::find_if(__first, __last, __pred); + } } -} +}; +} // namespace __pstl _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 - -#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H +#endif // _LIBCPP___PSTL_CPU_ALGOS_FIND_IF_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/for_each.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/for_each.h new file mode 100644 index 0000000000..d4d7862135 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/for_each.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_CPU_ALGOS_FOR_EACH_H +#define _LIBCPP___PSTL_CPU_ALGOS_FOR_EACH_H + +#include <__algorithm/for_each.h> +#include <__assert> +#include <__config> +#include <__iterator/concepts.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/cpu_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/empty.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +template +_LIBCPP_HIDE_FROM_ABI _Iterator __simd_for_each(_Iterator __first, _DifferenceType __n, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first[__i]); + + return __first + __n; +} + +template +struct __cpu_parallel_for_each { + template + _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Function __func) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + return __cpu_traits<_Backend>::__for_each( + __first, __last, [&__policy, __func](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + using _ForEachUnseq = __pstl::__for_each<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + [[maybe_unused]] auto __res = + _ForEachUnseq()(std::__remove_parallel_policy(__policy), __brick_first, __brick_last, __func); + _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + __pstl::__simd_for_each(__first, __last - __first, __func); + return __empty{}; + } else { + std::for_each(__first, __last, __func); + return __empty{}; + } + } +}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___PSTL_CPU_ALGOS_FOR_EACH_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/merge.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/merge.h new file mode 100644 index 0000000000..dfa4cbf69b --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/merge.h @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_CPU_ALGOS_MERGE_H +#define _LIBCPP___PSTL_CPU_ALGOS_MERGE_H + +#include <__algorithm/merge.h> +#include <__assert> +#include <__config> +#include <__iterator/concepts.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/cpu_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +template +struct __cpu_parallel_merge { + template + _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> operator()( + _Policy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardOutIterator __result, + _Comp __comp) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && + __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value && + __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { + auto __res = __cpu_traits<_Backend>::__merge( + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [&__policy](_ForwardIterator1 __g_first1, + _ForwardIterator1 __g_last1, + _ForwardIterator2 __g_first2, + _ForwardIterator2 __g_last2, + _ForwardOutIterator __g_result, + _Comp __g_comp) { + using _MergeUnseq = __pstl::__merge<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + [[maybe_unused]] auto __g_res = _MergeUnseq()( + std::__remove_parallel_policy(__policy), + std::move(__g_first1), + std::move(__g_last1), + std::move(__g_first2), + std::move(__g_last2), + std::move(__g_result), + std::move(__g_comp)); + _LIBCPP_ASSERT_INTERNAL(__g_res, "unsed/sed should never try to allocate!"); + }); + if (!__res) + return nullopt; + return __result + (__last1 - __first1) + (__last2 - __first2); + } else { + return std::merge(__first1, __last1, __first2, __last2, __result, __comp); + } + } +}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_CPU_ALGOS_MERGE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/stable_sort.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/stable_sort.h new file mode 100644 index 0000000000..8e64f3e537 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/stable_sort.h @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_CPU_ALGOS_STABLE_SORT_H +#define _LIBCPP___PSTL_CPU_ALGOS_STABLE_SORT_H + +#include <__algorithm/stable_sort.h> +#include <__config> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/cpu_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/empty.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +template +struct __cpu_parallel_stable_sort { + template + _LIBCPP_HIDE_FROM_ABI optional<__empty> + operator()(_Policy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy>) { + return __cpu_traits<_Backend>::__stable_sort( + __first, __last, __comp, [](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { + std::stable_sort(__g_first, __g_last, __g_comp); + }); + } else { + std::stable_sort(__first, __last, __comp); + return __empty{}; + } + } +}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___PSTL_CPU_ALGOS_STABLE_SORT_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/transform.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/transform.h new file mode 100644 index 0000000000..27ce8e27b2 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/transform.h @@ -0,0 +1,153 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_H +#define _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_H + +#include <__algorithm/transform.h> +#include <__assert> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/cpu_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +template +_LIBCPP_HIDE_FROM_ABI _Iterator2 +__simd_transform(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i]); + return __first2 + __n; +} + +template +_LIBCPP_HIDE_FROM_ABI _Iterator3 __simd_transform( + _Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i], __first3[__i]); + return __first3 + __n; +} + +template +struct __cpu_parallel_transform { + template + _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> + operator()(_Policy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _UnaryOperation __op) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value && + __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { + __cpu_traits<_Backend>::__for_each( + __first, + __last, + [&__policy, __op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + using _TransformUnseq = __pstl::__transform<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + auto __res = _TransformUnseq()( + std::__remove_parallel_policy(__policy), + __brick_first, + __brick_last, + __result + (__brick_first - __first), + __op); + _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); + return *std::move(__res); + }); + return __result + (__last - __first); + } else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value && + __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { + return __pstl::__simd_transform( + __first, + __last - __first, + __result, + [&](__iter_reference<_ForwardIterator> __in_value, __iter_reference<_ForwardOutIterator> __out_value) { + __out_value = __op(__in_value); + }); + } else { + return std::transform(__first, __last, __result, __op); + } + } +}; + +template +struct __cpu_parallel_transform_binary { + template + _LIBCPP_HIDE_FROM_ABI optional<_ForwardOutIterator> + operator()(_Policy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardOutIterator __result, + _BinaryOperation __op) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && + __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value && + __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { + auto __res = __cpu_traits<_Backend>::__for_each( + __first1, + __last1, + [&__policy, __op, __first1, __first2, __result]( + _ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) { + using _TransformBinaryUnseq = + __pstl::__transform_binary<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + return _TransformBinaryUnseq()( + std::__remove_parallel_policy(__policy), + __brick_first, + __brick_last, + __first2 + (__brick_first - __first1), + __result + (__brick_first - __first1), + __op); + }); + if (!__res) + return nullopt; + return __result + (__last1 - __first1); + } else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && + __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value && + __has_random_access_iterator_category_or_concept<_ForwardOutIterator>::value) { + return __pstl::__simd_transform( + __first1, + __last1 - __first1, + __first2, + __result, + [&](__iter_reference<_ForwardIterator1> __in1, + __iter_reference<_ForwardIterator2> __in2, + __iter_reference<_ForwardOutIterator> __out_value) { __out_value = __op(__in1, __in2); }); + } else { + return std::transform(__first1, __last1, __first2, __result, __op); + } + } +}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/transform_reduce.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/transform_reduce.h new file mode 100644 index 0000000000..36ac1a9072 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/cpu_algos/transform_reduce.h @@ -0,0 +1,216 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_REDUCE_H +#define _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_REDUCE_H + +#include <__assert> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__numeric/transform_reduce.h> +#include <__pstl/backend_fwd.h> +#include <__pstl/cpu_algos/cpu_traits.h> +#include <__type_traits/desugars_to.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/move.h> +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +template , + __enable_if_t<__desugars_to_v<__plus_tag, _BinaryOperation, _Tp, _UnaryResult> && is_arithmetic_v<_Tp> && + is_arithmetic_v<_UnaryResult>, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +__simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept { + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init) + for (_DifferenceType __i = 0; __i < __n; ++__i) + __init += __f(__i); + return __init; +} + +template , + __enable_if_t && is_arithmetic_v<_Tp> && + is_arithmetic_v<_UnaryResult>), + int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +__simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept { + constexpr size_t __lane_size = __cpu_traits<_Backend>::__lane_size; + const _Size __block_size = __lane_size / sizeof(_Tp); + if (__n > 2 * __block_size && __block_size > 1) { + alignas(__lane_size) char __lane_buffer[__lane_size]; + _Tp* __lane = reinterpret_cast<_Tp*>(__lane_buffer); + + // initializer + _PSTL_PRAGMA_SIMD + for (_Size __i = 0; __i < __block_size; ++__i) { + ::new (__lane + __i) _Tp(__binary_op(__f(__i), __f(__block_size + __i))); + } + // main loop + _Size __i = 2 * __block_size; + const _Size __last_iteration = __block_size * (__n / __block_size); + for (; __i < __last_iteration; __i += __block_size) { + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __block_size; ++__j) { + __lane[__j] = __binary_op(std::move(__lane[__j]), __f(__i + __j)); + } + } + // remainder + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __n - __last_iteration; ++__j) { + __lane[__j] = __binary_op(std::move(__lane[__j]), __f(__last_iteration + __j)); + } + // combiner + for (_Size __j = 0; __j < __block_size; ++__j) { + __init = __binary_op(std::move(__init), std::move(__lane[__j])); + } + // destroyer + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __block_size; ++__j) { + __lane[__j].~_Tp(); + } + } else { + for (_Size __i = 0; __i < __n; ++__i) { + __init = __binary_op(std::move(__init), __f(__i)); + } + } + return __init; +} + +template +struct __cpu_parallel_transform_reduce_binary { + template + _LIBCPP_HIDE_FROM_ABI optional<_Tp> operator()( + _Policy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init, + _BinaryOperation1 __reduce, + _BinaryOperation2 __transform) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && + __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) { + return __cpu_traits<_Backend>::__transform_reduce( + __first1, + std::move(__last1), + [__first1, __first2, __transform](_ForwardIterator1 __iter) { + return __transform(*__iter, *(__first2 + (__iter - __first1))); + }, + std::move(__init), + std::move(__reduce), + [&__policy, __first1, __first2, __reduce, __transform]( + _ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last, _Tp __brick_init) { + using _TransformReduceBinaryUnseq = + __pstl::__transform_reduce_binary<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + return *_TransformReduceBinaryUnseq()( + std::__remove_parallel_policy(__policy), + __brick_first, + std::move(__brick_last), + __first2 + (__brick_first - __first1), + std::move(__brick_init), + std::move(__reduce), + std::move(__transform)); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value && + __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) { + return __pstl::__simd_transform_reduce<_Backend>( + __last1 - __first1, std::move(__init), std::move(__reduce), [&](__iter_diff_t<_ForwardIterator1> __i) { + return __transform(__first1[__i], __first2[__i]); + }); + } else { + return std::transform_reduce( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__init), + std::move(__reduce), + std::move(__transform)); + } + } +}; + +template +struct __cpu_parallel_transform_reduce { + template + _LIBCPP_HIDE_FROM_ABI optional<_Tp> + operator()(_Policy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation __reduce, + _UnaryOperation __transform) const noexcept { + if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + return __cpu_traits<_Backend>::__transform_reduce( + std::move(__first), + std::move(__last), + [__transform](_ForwardIterator __iter) { return __transform(*__iter); }, + std::move(__init), + __reduce, + [&__policy, __transform, __reduce](auto __brick_first, auto __brick_last, _Tp __brick_init) { + using _TransformReduceUnseq = + __pstl::__transform_reduce<_Backend, __remove_parallel_policy_t<_RawExecutionPolicy>>; + auto __res = _TransformReduceUnseq()( + std::__remove_parallel_policy(__policy), + std::move(__brick_first), + std::move(__brick_last), + std::move(__brick_init), + std::move(__reduce), + std::move(__transform)); + _LIBCPP_ASSERT_INTERNAL(__res, "unseq/seq should never try to allocate!"); + return *std::move(__res); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_RawExecutionPolicy> && + __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) { + return __pstl::__simd_transform_reduce<_Backend>( + __last - __first, + std::move(__init), + std::move(__reduce), + [=, &__transform](__iter_diff_t<_ForwardIterator> __i) { return __transform(__first[__i]); }); + } else { + return std::transform_reduce( + std::move(__first), std::move(__last), std::move(__init), std::move(__reduce), std::move(__transform)); + } + } +}; + +} // namespace __pstl +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___PSTL_CPU_ALGOS_TRANSFORM_REDUCE_H diff --git a/naiveproxy/src/third_party/libc++/src/include/__pstl/dispatch.h b/naiveproxy/src/third_party/libc++/src/include/__pstl/dispatch.h new file mode 100644 index 0000000000..5e903f7524 --- /dev/null +++ b/naiveproxy/src/third_party/libc++/src/include/__pstl/dispatch.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___PSTL_DISPATCH_H +#define _LIBCPP___PSTL_DISPATCH_H + +#include <__config> +#include <__pstl/backend_fwd.h> +#include <__type_traits/conditional.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/type_identity.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD +namespace __pstl { + +template